From e73a0fb874e7135e2df6ac913db43e3337f00e17 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Fri, 15 Jan 2010 15:39:39 +0000 Subject: [PATCH] Added Value support to Labels and ComboBoxes. Altered all the PropertyComponent classes so that as well as being used as abstract base classes, they can now also be instantiated directly as controllers for a Value. This allows property panels to be built to control a set of Value objects without writing any custom classes. --- build/macosx/Juce.xcodeproj/project.pbxproj | 5 - .../JuceDemoPlugin.xcodeproj/project.pbxproj | 2 + extras/juce demo/src/juce_AppConfig.h | 2 + juce_amalgamated.cpp | 250212 +++++++-------- juce_amalgamated.h | 59770 +--- src/gui/components/controls/juce_ComboBox.cpp | 166 +- src/gui/components/controls/juce_ComboBox.h | 25 +- src/gui/components/controls/juce_Label.cpp | 34 +- src/gui/components/controls/juce_Label.h | 61 +- .../juce_BooleanPropertyComponent.cpp | 30 +- .../juce_BooleanPropertyComponent.h | 22 +- .../juce_ChoicePropertyComponent.cpp | 49 +- .../properties/juce_ChoicePropertyComponent.h | 18 +- .../juce_SliderPropertyComponent.cpp | 26 + .../properties/juce_SliderPropertyComponent.h | 22 +- .../properties/juce_TextPropertyComponent.cpp | 40 +- .../properties/juce_TextPropertyComponent.h | 21 +- 17 files changed, 129392 insertions(+), 181113 deletions(-) diff --git a/build/macosx/Juce.xcodeproj/project.pbxproj b/build/macosx/Juce.xcodeproj/project.pbxproj index 65cf2694cd..9ae71bffe9 100644 --- a/build/macosx/Juce.xcodeproj/project.pbxproj +++ b/build/macosx/Juce.xcodeproj/project.pbxproj @@ -4223,8 +4223,6 @@ 84A487F808A22DD800752A2B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; - ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; MACOSX_DEPLOYMENT_TARGET = 10.4; @@ -4235,10 +4233,7 @@ 84A487F908A22DD800752A2B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; - ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; - SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; STRIP_STYLE = "non-global"; }; name = Release; diff --git a/extras/audio plugins/demo/build/mac/JuceDemoPlugin.xcodeproj/project.pbxproj b/extras/audio plugins/demo/build/mac/JuceDemoPlugin.xcodeproj/project.pbxproj index 4e8f2af693..445c3d1994 100644 --- a/extras/audio plugins/demo/build/mac/JuceDemoPlugin.xcodeproj/project.pbxproj +++ b/extras/audio plugins/demo/build/mac/JuceDemoPlugin.xcodeproj/project.pbxproj @@ -683,6 +683,7 @@ COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; GCC_VERSION = 4.0; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = NO; GENERATE_PKGINFO_FILE = YES; INFOPLIST_FILE = Info.plist; INFOPLIST_PREPROCESS = YES; @@ -698,6 +699,7 @@ ARCHS = "$(ARCHS_STANDARD_32_BIT)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_VERSION = 4.0; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = NO; GENERATE_PKGINFO_FILE = YES; INFOPLIST_PREPROCESS = YES; SDKROOT = macosx10.5; diff --git a/extras/juce demo/src/juce_AppConfig.h b/extras/juce demo/src/juce_AppConfig.h index 44b184defa..6cafb933b8 100644 --- a/extras/juce demo/src/juce_AppConfig.h +++ b/extras/juce demo/src/juce_AppConfig.h @@ -72,6 +72,8 @@ #define JUCE_USE_CAMERA 0 #elif JUCE_MAC #define JUCE_USE_CAMERA 1 +#else // WINDOWS + #define JUCE_USE_CAMERA 0 #endif //#define JUCE_CHECK_MEMORY_LEAKS 1 diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index e3f85d2923..487c935b2d 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -1,40 +1,5 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-9 by Raw Material Software Ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the GNU General - Public License (Version 2), as published by the Free Software Foundation. - A copy of the license is included in the JUCE distribution, or can be found - online at www.gnu.org/licenses. - - JUCE is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - To release a closed-source product which uses JUCE, commercial licenses are - available: visit www.rawmaterialsoftware.com/juce for more information. - - ============================================================================== -*/ - -/* - This monolithic file contains the entire Juce source tree! - - To build an app which uses Juce, all you need to do is to add this - file to your project, and include juce.h in your own cpp files. - -*/ #ifdef __JUCE_JUCEHEADER__ - /* When you add the amalgamated cpp file to your project, you mustn't include it in - a file where you've already included juce.h - just put it inside a file on its own, - possibly with your config flags preceding it, but don't include anything else. */ #error #endif @@ -42,30 +7,18 @@ #ifndef __JUCE_TARGETPLATFORM_JUCEHEADER__ #define __JUCE_TARGETPLATFORM_JUCEHEADER__ -/* This file figures out which platform is being built, and defines some macros - that the rest of the code can use for OS-specific compilation. - - Macros that will be set here are: - - - One of JUCE_WINDOWS, JUCE_MAC or JUCE_LINUX. - - Either JUCE_32BIT or JUCE_64BIT, depending on the architecture. - - Either JUCE_LITTLE_ENDIAN or JUCE_BIG_ENDIAN. - - Either JUCE_INTEL or JUCE_PPC - - Either JUCE_GCC or JUCE_MSVC -*/ - #if (defined (_WIN32) || defined (_WIN64)) - #define JUCE_WIN32 1 - #define JUCE_WINDOWS 1 + #define JUCE_WIN32 1 + #define JUCE_WINDOWS 1 #elif defined (LINUX) || defined (__linux__) - #define JUCE_LINUX 1 + #define JUCE_LINUX 1 #elif defined(__APPLE_CPP__) || defined(__APPLE_CC__) #include // (needed to find out what platform we're using) #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR - #define JUCE_IPHONE 1 + #define JUCE_IPHONE 1 #else - #define JUCE_MAC 1 + #define JUCE_MAC 1 #endif #else #error "Unknown platform!" @@ -73,18 +26,21 @@ #if JUCE_WINDOWS #ifdef _MSC_VER - #ifdef _WIN64 - #define JUCE_64BIT 1 - #else - #define JUCE_32BIT 1 - #endif + #ifdef _WIN64 + #define JUCE_64BIT 1 + #else + #define JUCE_32BIT 1 + #endif #endif #ifdef _DEBUG - #define JUCE_DEBUG 1 + #define JUCE_DEBUG 1 + #endif + + #ifdef __MINGW32__ + #define JUCE_MINGW 1 #endif - /** If defined, this indicates that the processor is little-endian. */ #define JUCE_LITTLE_ENDIAN 1 #define JUCE_INTEL 1 @@ -93,33 +49,33 @@ #if JUCE_MAC #ifndef NDEBUG - #define JUCE_DEBUG 1 + #define JUCE_DEBUG 1 #endif #ifdef __LITTLE_ENDIAN__ - #define JUCE_LITTLE_ENDIAN 1 + #define JUCE_LITTLE_ENDIAN 1 #else - #define JUCE_BIG_ENDIAN 1 + #define JUCE_BIG_ENDIAN 1 #endif #if defined (__ppc__) || defined (__ppc64__) - #define JUCE_PPC 1 + #define JUCE_PPC 1 #else - #define JUCE_INTEL 1 + #define JUCE_INTEL 1 #endif #ifdef __LP64__ - #define JUCE_64BIT 1 + #define JUCE_64BIT 1 #else - #define JUCE_32BIT 1 + #define JUCE_32BIT 1 #endif #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4 - #error "Building for OSX 10.3 is no longer supported!" + #error "Building for OSX 10.3 is no longer supported!" #endif #ifndef MAC_OS_X_VERSION_10_5 - #error "To build with 10.4 compatibility, use a 10.5 or 10.6 SDK and set the deployment target to 10.4" + #error "To build with 10.4 compatibility, use a 10.5 or 10.6 SDK and set the deployment target to 10.4" #endif #endif @@ -127,31 +83,31 @@ #if JUCE_IPHONE #ifndef NDEBUG - #define JUCE_DEBUG 1 + #define JUCE_DEBUG 1 #endif #ifdef __LITTLE_ENDIAN__ - #define JUCE_LITTLE_ENDIAN 1 + #define JUCE_LITTLE_ENDIAN 1 #else - #define JUCE_BIG_ENDIAN 1 + #define JUCE_BIG_ENDIAN 1 #endif #endif #if JUCE_LINUX #ifdef _DEBUG - #define JUCE_DEBUG 1 + #define JUCE_DEBUG 1 #endif // Allow override for big-endian Linux platforms #ifndef JUCE_BIG_ENDIAN - #define JUCE_LITTLE_ENDIAN 1 + #define JUCE_LITTLE_ENDIAN 1 #endif #if defined (__LP64__) || defined (_LP64) - #define JUCE_64BIT 1 + #define JUCE_64BIT 1 #else - #define JUCE_32BIT 1 + #define JUCE_32BIT 1 #endif #define JUCE_INTEL 1 @@ -165,7 +121,7 @@ #define JUCE_MSVC 1 #if _MSC_VER >= 1400 - #define JUCE_USE_INTRINSICS 1 + #define JUCE_USE_INTRINSICS 1 #endif #else #error unknown compiler @@ -180,98 +136,46 @@ #ifndef __JUCE_CONFIG_JUCEHEADER__ #define __JUCE_CONFIG_JUCEHEADER__ -/* - This file contains macros that enable/disable various JUCE features. -*/ - -/** The name of the namespace that all Juce classes and functions will be - put inside. If this is not defined, no namespace will be used. -*/ #ifndef JUCE_NAMESPACE #define JUCE_NAMESPACE juce #endif -/** Normally, JUCE_DEBUG is set to 1 or 0 based on compiler and project settings, - but if you define this value, you can override this can force it to be true or - false. -*/ #ifndef JUCE_FORCE_DEBUG //#define JUCE_FORCE_DEBUG 1 #endif -/** If this flag is enabled, the the jassert and jassertfalse macros will - always use Logger::writeToLog() to write a message when an assertion happens. - - Enabling it will also leave this turned on in release builds. When it's disabled, - however, the jassert and jassertfalse macros will not be compiled in a - release build. - - @see jassert, jassertfalse, Logger -*/ #ifndef JUCE_LOG_ASSERTIONS // #define JUCE_LOG_ASSERTIONS 1 #endif -/** Comment out this macro if you haven't got the Steinberg ASIO SDK, without - which the ASIOAudioIODevice class can't be built. See the comments in the - ASIOAudioIODevice class's header file for more info about this. - - (This only affects a Win32 build) -*/ #ifndef JUCE_ASIO #define JUCE_ASIO 1 #endif -/** Comment out this macro to disable the Windows WASAPI audio device type. -*/ #ifndef JUCE_WASAPI // #define JUCE_WASAPI 1 #endif -/** Comment out this macro to disable the Windows WASAPI audio device type. -*/ #ifndef JUCE_DIRECTSOUND #define JUCE_DIRECTSOUND 1 #endif -/** Comment out this macro to disable building of ALSA device support on Linux. -*/ #ifndef JUCE_ALSA #define JUCE_ALSA 1 #endif -/** Comment out this macro to disable building of JACK device support on Linux. -*/ #ifndef JUCE_JACK #define JUCE_JACK 1 #endif -/** Comment out this macro if you don't want to enable QuickTime or if you don't - have the SDK installed. - - If this flag is not enabled, the QuickTimeMovieComponent and QuickTimeAudioFormat - classes will be unavailable. - - On Windows, if you enable this, you'll need to have the QuickTime SDK - installed, and its header files will need to be on your include path. -*/ #if ! (defined (JUCE_QUICKTIME) || JUCE_LINUX || JUCE_IPHONE || (JUCE_WINDOWS && ! JUCE_MSVC)) #define JUCE_QUICKTIME 1 #endif -/** Comment out this macro if you don't want to enable OpenGL or if you don't - have the appropriate headers and libraries available. If it's not enabled, the - OpenGLComponent class will be unavailable. -*/ #ifndef JUCE_OPENGL #define JUCE_OPENGL 1 #endif -/** These flags enable the Ogg-Vorbis and Flac audio formats. - - If you're not going to need either of these formats, turn off the flags to - avoid bloating your codebase with them. -*/ #ifndef JUCE_USE_FLAC #define JUCE_USE_FLAC 1 #endif @@ -280,94 +184,56 @@ #define JUCE_USE_OGGVORBIS 1 #endif -/** This flag lets you enable the AudioCDBurner class. You might want to disable - it to build without the MS SDK under windows. -*/ #if (! defined (JUCE_USE_CDBURNER)) && ! (JUCE_WINDOWS && ! JUCE_MSVC) #define JUCE_USE_CDBURNER 1 #endif -/** This flag lets you enable support for the AudioCDReader class. You might want to disable - it to build without the MS SDK under windows. -*/ #ifndef JUCE_USE_CDREADER #define JUCE_USE_CDREADER 1 #endif -/** Enabling this provides support for cameras, using the CameraDevice class -*/ #if JUCE_QUICKTIME && ! defined (JUCE_USE_CAMERA) // #define JUCE_USE_CAMERA 1 #endif -/** Enabling this macro means that all regions that get repainted will have a coloured - line drawn around them. - - This is handy if you're trying to optimise drawing, because it lets you easily see - when anything is being repainted unnecessarily. -*/ #ifndef JUCE_ENABLE_REPAINT_DEBUGGING // #define JUCE_ENABLE_REPAINT_DEBUGGING 1 #endif -/** Enable this under Linux to use Xinerama for multi-monitor support. -*/ #ifndef JUCE_USE_XINERAMA #define JUCE_USE_XINERAMA 1 #endif -/** Enable this under Linux to use XShm for faster shared-memory rendering. -*/ #ifndef JUCE_USE_XSHM #define JUCE_USE_XSHM 1 #endif -/** Enabling this builds support for VST audio plugins. - @see VSTPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_AU -*/ #ifndef JUCE_PLUGINHOST_VST // #define JUCE_PLUGINHOST_VST 1 #endif -/** Enabling this builds support for AudioUnit audio plugins. - @see AudioUnitPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_VST -*/ #ifndef JUCE_PLUGINHOST_AU // #define JUCE_PLUGINHOST_AU 1 #endif -/** Enabling this will avoid including any UI code in the build. This is handy for - writing command-line utilities, e.g. on linux boxes which don't have some - of the UI libraries installed. -*/ #ifndef JUCE_ONLY_BUILD_CORE_LIBRARY //#define JUCE_ONLY_BUILD_CORE_LIBRARY 1 #endif -/** This lets you disable building of the WebBrowserComponent, if it's not required. -*/ #ifndef JUCE_WEB_BROWSER #define JUCE_WEB_BROWSER 1 #endif -/** Setting this allows the build to use old Carbon libraries that will be - deprecated in newer versions of OSX. This is handy for some backwards-compatibility - reasons. -*/ #ifndef JUCE_SUPPORT_CARBON #define JUCE_SUPPORT_CARBON 1 #endif -/* These flags let you avoid the direct inclusion of some 3rd-party libs in the - codebase - you might need to use this if you're linking to some of these libraries - yourself. -*/ #ifndef JUCE_INCLUDE_ZLIB_CODE - #define JUCE_INCLUDE_ZLIB_CODE 1 + #define JUCE_INCLUDE_ZLIB_CODE 1 #endif #ifndef JUCE_INCLUDE_FLAC_CODE - #define JUCE_INCLUDE_FLAC_CODE 1 + #define JUCE_INCLUDE_FLAC_CODE 1 #endif #ifndef JUCE_INCLUDE_OGGVORBIS_CODE @@ -375,33 +241,21 @@ #endif #ifndef JUCE_INCLUDE_PNGLIB_CODE - #define JUCE_INCLUDE_PNGLIB_CODE 1 + #define JUCE_INCLUDE_PNGLIB_CODE 1 #endif #ifndef JUCE_INCLUDE_JPEGLIB_CODE - #define JUCE_INCLUDE_JPEGLIB_CODE 1 + #define JUCE_INCLUDE_JPEGLIB_CODE 1 #endif -/** Enable this to add extra memory-leak info to the new and delete operators. - - (Currently, this only affects Windows builds in debug mode). -*/ #ifndef JUCE_CHECK_MEMORY_LEAKS #define JUCE_CHECK_MEMORY_LEAKS 1 #endif -/** Enable this to turn on juce's internal catching of exceptions. - - Turning it off will avoid any exception catching. With it on, all exceptions - are passed to the JUCEApplication::unhandledException() callback for logging. -*/ #ifndef JUCE_CATCH_UNHANDLED_EXCEPTIONS #define JUCE_CATCH_UNHANDLED_EXCEPTIONS 1 #endif -/** If this macro is set, the Juce String class will use unicode as its - internal representation. If it isn't set, it'll use ANSI. -*/ #ifndef JUCE_STRINGS_ARE_UNICODE #define JUCE_STRINGS_ARE_UNICODE 1 #endif @@ -471,13 +325,16 @@ #include #include #include -#include #include -#include #include #include #include +#if ! JUCE_MINGW + #include + #include +#endif + #if JUCE_OPENGL #include #endif @@ -485,54 +342,17 @@ #undef PACKED #if JUCE_ASIO -/* - This is very frustrating - we only need to use a handful of definitions from - a couple of the header files in Steinberg's ASIO SDK, and it'd be easy to copy - about 30 lines of code into this cpp file to create a fully stand-alone ASIO - implementation... - - ..unfortunately that would break Steinberg's license agreement for use of - their SDK, so I'm not allowed to do this. - - This means that anyone who wants to use JUCE's ASIO abilities will have to: - - 1) Agree to Steinberg's licensing terms and download the ASIO SDK - (see www.steinberg.net/Steinberg/Developers.asp). - - 2) Rebuild the whole of JUCE, setting the global definition JUCE_ASIO (you - can un-comment the "#define JUCE_ASIO" line in juce_Config.h - if you prefer). Make sure that your header search path will find the - iasiodrv.h file that comes with the SDK. (Only about 2-3 of the SDK header - files are actually needed - so to simplify things, you could just copy - these into your JUCE directory). - - If you're compiling and you get an error here because you don't have the - ASIO SDK installed, you can disable ASIO support by commenting-out the - "#define JUCE_ASIO" line in juce_Config.h, and rebuild your Juce library. - */ #include "iasiodrv.h" #endif #if JUCE_USE_CDBURNER - /* You'll need the Platform SDK for these headers - if you don't have it and don't - need to use CD-burning, then you might just want to disable the JUCE_USE_CDBURNER - flag in juce_Config.h to avoid these includes. - */ #include #include #endif #if JUCE_USE_CAMERA - /* If you're using the camera classes, you'll need access to a few DirectShow headers. - - Both of these files are provided in the normal Windows SDK, but some Microsoft plonker - didn't realise that qedit.h doesn't actually compile without the rest of the DirectShow SDK! - Microsoft's suggested fix for this is to hack their qedit.h file! See: - http://social.msdn.microsoft.com/Forums/en-US/windowssdk/thread/ed097d2c-3d68-4f48-8448-277eaaf68252 - .. which is a pathetic bodge, but a lot less hassle than installing the full DShow SDK. - */ #include #include #endif @@ -546,22 +366,12 @@ #if JUCE_QUICKTIME - /* If you've got an include error here, you probably need to install the QuickTime SDK and - add its header directory to your include path. - - Alternatively, if you don't need any QuickTime services, just turn off the JUCE_QUICKTIME - flag in juce_Config.h - */ #include #include #include #include #include - /* If you've got QuickTime 7 installed, then these COM objects should be found in - the "\Program Files\Quicktime" directory. You'll need to add this directory to - your include search path to make these import statements work. - */ #import #import #endif @@ -570,48 +380,45 @@ #pragma warning (pop) #endif -/** A simple COM smart pointer. - Avoids having to include ATL just to get one of these. -*/ template class ComSmartPtr { public: - ComSmartPtr() throw() : p (0) {} - ComSmartPtr (T* const p_) : p (p_) { if (p_ != 0) p_->AddRef(); } - ComSmartPtr (const ComSmartPtr& p_) : p (p_.p) { if (p != 0) p->AddRef(); } - ~ComSmartPtr() { if (p != 0) p->Release(); } + ComSmartPtr() throw() : p (0) {} + ComSmartPtr (T* const p_) : p (p_) { if (p_ != 0) p_->AddRef(); } + ComSmartPtr (const ComSmartPtr& p_) : p (p_.p) { if (p != 0) p->AddRef(); } + ~ComSmartPtr() { if (p != 0) p->Release(); } - operator T*() const throw() { return p; } - T& operator*() const throw() { return *p; } - T** operator&() throw() { return &p; } - T* operator->() const throw() { return p; } + operator T*() const throw() { return p; } + T& operator*() const throw() { return *p; } + T** operator&() throw() { return &p; } + T* operator->() const throw() { return p; } - T* operator= (T* const newP) - { - if (newP != 0) - newP->AddRef(); + T* operator= (T* const newP) + { + if (newP != 0) + newP->AddRef(); - if (p != 0) - p->Release(); + if (p != 0) + p->Release(); - p = newP; - return newP; - } + p = newP; + return newP; + } - T* operator= (const ComSmartPtr& newP) { return operator= (newP.p); } + T* operator= (const ComSmartPtr& newP) { return operator= (newP.p); } - HRESULT CoCreateInstance (REFCLSID rclsid, DWORD dwClsContext) - { + HRESULT CoCreateInstance (REFCLSID rclsid, DWORD dwClsContext) + { #ifndef __MINGW32__ - operator= (0); - return ::CoCreateInstance (rclsid, 0, dwClsContext, __uuidof(T), (void**) &p); + operator= (0); + return ::CoCreateInstance (rclsid, 0, dwClsContext, __uuidof(T), (void**) &p); #else - return S_FALSE; + return S_FALSE; #endif - } + } - T* p; + T* p; }; #endif // __JUCE_WIN32_NATIVEINCLUDES_JUCEHEADER__ @@ -623,13 +430,6 @@ public: #ifndef __JUCE_LINUX_NATIVEINCLUDES_JUCEHEADER__ #define __JUCE_LINUX_NATIVEINCLUDES_JUCEHEADER__ -/* - This file wraps together all the linux-specific headers, so - that we can include them all just once, and compile all our - platform-specific stuff in one big lump, keeping it out of the - way of the rest of the codebase. -*/ - #include #include #include @@ -655,9 +455,6 @@ public: #include #include -/* Got a build error here? You'll need to install the freetype library... - The name of the package to install is "libfreetype6-dev". -*/ #include #include FT_FREETYPE_H @@ -670,7 +467,6 @@ public: #include #if JUCE_USE_XINERAMA - /* If you're trying to use Xinerama, you'll need to install the "libxinerama-dev" package.. */ #include #endif @@ -681,40 +477,16 @@ public: #endif #if JUCE_OPENGL - /* Got an include error here? - - If you want to install OpenGL support, the packages to get are "mesa-common-dev" - and "freeglut3-dev". - - Alternatively, you can turn off the JUCE_OPENGL flag in juce_Config.h if you - want to disable it. - */ #include #endif #undef KeyPress #if JUCE_ALSA - /* Got an include error here? If so, you've either not got ALSA installed, or you've - not got your paths set up correctly to find its header files. - - The package you need to install to get ASLA support is "libasound2-dev". - - If you don't have the ALSA library and don't want to build Juce with audio support, - just disable the JUCE_ALSA flag in juce_Config.h - */ #include #endif #if JUCE_JACK - /* Got an include error here? If so, you've either not got jack-audio-connection-kit - installed, or you've not got your paths set up correctly to find its header files. - - The package you need to install to get JACK support is "libjack-dev". - - If you don't have the jack-audio-connection-kit library and don't want to build - Juce with low latency audio support, just disable the JUCE_JACK flag in juce_Config.h - */ #include //#include #endif @@ -730,13 +502,6 @@ public: #ifndef __JUCE_MAC_NATIVEINCLUDES_JUCEHEADER__ #define __JUCE_MAC_NATIVEINCLUDES_JUCEHEADER__ -/* - This file wraps together all the mac-specific code, so that - we can include all the native headers just once, and compile all our - platform-specific stuff in one big lump, keeping it out of the way of - the rest of the codebase. -*/ - #define USE_COREGRAPHICS_RENDERING 1 #if JUCE_IPHONE @@ -809,240 +574,234 @@ public: #ifndef __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__ #define __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__ -/** - Creates a floating carbon window that can be used to hold a carbon UI. - - This is a handy class that's designed to be inlined where needed, e.g. - in the audio plugin hosting code. -*/ class CarbonViewWrapperComponent : public Component, - public ComponentMovementWatcher, - public Timer + public ComponentMovementWatcher, + public Timer { public: - CarbonViewWrapperComponent() - : ComponentMovementWatcher (this), - wrapperWindow (0), - embeddedView (0), - recursiveResize (false) - { - } + CarbonViewWrapperComponent() + : ComponentMovementWatcher (this), + wrapperWindow (0), + embeddedView (0), + recursiveResize (false) + { + } - virtual ~CarbonViewWrapperComponent() - { - jassert (embeddedView == 0); // must call deleteWindow() in the subclass's destructor! - } + virtual ~CarbonViewWrapperComponent() + { + jassert (embeddedView == 0); // must call deleteWindow() in the subclass's destructor! + } - virtual HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) = 0; - virtual void removeView (HIViewRef embeddedView) = 0; - virtual void mouseDown (int x, int y) {} - virtual void paint() {} + virtual HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) = 0; + virtual void removeView (HIViewRef embeddedView) = 0; + virtual void mouseDown (int x, int y) {} + virtual void paint() {} - virtual bool getEmbeddedViewSize (int& w, int& h) - { - if (embeddedView == 0) - return false; + virtual bool getEmbeddedViewSize (int& w, int& h) + { + if (embeddedView == 0) + return false; - HIRect bounds; - HIViewGetBounds (embeddedView, &bounds); - w = jmax (1, roundFloatToInt (bounds.size.width)); - h = jmax (1, roundFloatToInt (bounds.size.height)); - return true; - } + HIRect bounds; + HIViewGetBounds (embeddedView, &bounds); + w = jmax (1, roundToInt (bounds.size.width)); + h = jmax (1, roundToInt (bounds.size.height)); + return true; + } - void createWindow() - { - if (wrapperWindow == 0) - { - Rect r; - r.left = getScreenX(); - r.top = getScreenY(); - r.right = r.left + getWidth(); - r.bottom = r.top + getHeight(); + void createWindow() + { + if (wrapperWindow == 0) + { + Rect r; + r.left = getScreenX(); + r.top = getScreenY(); + r.right = r.left + getWidth(); + r.bottom = r.top + getHeight(); - CreateNewWindow (kDocumentWindowClass, - (WindowAttributes) (kWindowStandardHandlerAttribute | kWindowCompositingAttribute - | kWindowNoShadowAttribute | kWindowNoTitleBarAttribute), - &r, &wrapperWindow); + CreateNewWindow (kDocumentWindowClass, + (WindowAttributes) (kWindowStandardHandlerAttribute | kWindowCompositingAttribute + | kWindowNoShadowAttribute | kWindowNoTitleBarAttribute), + &r, &wrapperWindow); - jassert (wrapperWindow != 0); - if (wrapperWindow == 0) - return; + jassert (wrapperWindow != 0); + if (wrapperWindow == 0) + return; - NSWindow* carbonWindow = [[NSWindow alloc] initWithWindowRef: wrapperWindow]; - NSWindow* ownerWindow = [((NSView*) getWindowHandle()) window]; + NSWindow* carbonWindow = [[NSWindow alloc] initWithWindowRef: wrapperWindow]; + NSWindow* ownerWindow = [((NSView*) getWindowHandle()) window]; - [ownerWindow addChildWindow: carbonWindow - ordered: NSWindowAbove]; + [ownerWindow addChildWindow: carbonWindow + ordered: NSWindowAbove]; - embeddedView = attachView (wrapperWindow, HIViewGetRoot (wrapperWindow)); + embeddedView = attachView (wrapperWindow, HIViewGetRoot (wrapperWindow)); - EventTypeSpec windowEventTypes[] = { { kEventClassWindow, kEventWindowGetClickActivation }, - { kEventClassWindow, kEventWindowHandleDeactivate } }; + EventTypeSpec windowEventTypes[] = { { kEventClassWindow, kEventWindowGetClickActivation }, + { kEventClassWindow, kEventWindowHandleDeactivate } }; - EventHandlerUPP upp = NewEventHandlerUPP (carbonEventCallback); - InstallWindowEventHandler (wrapperWindow, upp, - sizeof (windowEventTypes) / sizeof (EventTypeSpec), - windowEventTypes, this, &eventHandlerRef); + EventHandlerUPP upp = NewEventHandlerUPP (carbonEventCallback); + InstallWindowEventHandler (wrapperWindow, upp, + sizeof (windowEventTypes) / sizeof (EventTypeSpec), + windowEventTypes, this, &eventHandlerRef); - setOurSizeToEmbeddedViewSize(); - setEmbeddedWindowToOurSize(); + setOurSizeToEmbeddedViewSize(); + setEmbeddedWindowToOurSize(); - creationTime = Time::getCurrentTime(); - } - } + creationTime = Time::getCurrentTime(); + } + } - void deleteWindow() - { - removeView (embeddedView); - embeddedView = 0; + void deleteWindow() + { + removeView (embeddedView); + embeddedView = 0; - if (wrapperWindow != 0) - { - RemoveEventHandler (eventHandlerRef); - DisposeWindow (wrapperWindow); - wrapperWindow = 0; - } - } + if (wrapperWindow != 0) + { + RemoveEventHandler (eventHandlerRef); + DisposeWindow (wrapperWindow); + wrapperWindow = 0; + } + } - void setOurSizeToEmbeddedViewSize() - { - int w, h; - if (getEmbeddedViewSize (w, h)) - { - if (w != getWidth() || h != getHeight()) - { - startTimer (50); + void setOurSizeToEmbeddedViewSize() + { + int w, h; + if (getEmbeddedViewSize (w, h)) + { + if (w != getWidth() || h != getHeight()) + { + startTimer (50); - setSize (w, h); - if (getParentComponent() != 0) - getParentComponent()->setSize (w, h); - } - else - { - startTimer (jlimit (50, 500, getTimerInterval() + 20)); - } - } - else - { - stopTimer(); - } - } + setSize (w, h); + if (getParentComponent() != 0) + getParentComponent()->setSize (w, h); + } + else + { + startTimer (jlimit (50, 500, getTimerInterval() + 20)); + } + } + else + { + stopTimer(); + } + } - void setEmbeddedWindowToOurSize() - { - if (! recursiveResize) - { - recursiveResize = true; + void setEmbeddedWindowToOurSize() + { + if (! recursiveResize) + { + recursiveResize = true; - if (embeddedView != 0) - { - HIRect r; - r.origin.x = 0; - r.origin.y = 0; - r.size.width = (float) getWidth(); - r.size.height = (float) getHeight(); - HIViewSetFrame (embeddedView, &r); - } + if (embeddedView != 0) + { + HIRect r; + r.origin.x = 0; + r.origin.y = 0; + r.size.width = (float) getWidth(); + r.size.height = (float) getHeight(); + HIViewSetFrame (embeddedView, &r); + } - if (wrapperWindow != 0) - { - Rect wr; - wr.left = getScreenX(); - wr.top = getScreenY(); - wr.right = wr.left + getWidth(); - wr.bottom = wr.top + getHeight(); + if (wrapperWindow != 0) + { + Rect wr; + wr.left = getScreenX(); + wr.top = getScreenY(); + wr.right = wr.left + getWidth(); + wr.bottom = wr.top + getHeight(); - SetWindowBounds (wrapperWindow, kWindowContentRgn, &wr); - ShowWindow (wrapperWindow); - } + SetWindowBounds (wrapperWindow, kWindowContentRgn, &wr); + ShowWindow (wrapperWindow); + } - recursiveResize = false; - } - } + recursiveResize = false; + } + } - void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) - { - setEmbeddedWindowToOurSize(); - } + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) + { + setEmbeddedWindowToOurSize(); + } - void componentPeerChanged() - { - deleteWindow(); - createWindow(); - } + void componentPeerChanged() + { + deleteWindow(); + createWindow(); + } - void componentVisibilityChanged (Component&) - { - if (isShowing()) - createWindow(); - else - deleteWindow(); + void componentVisibilityChanged (Component&) + { + if (isShowing()) + createWindow(); + else + deleteWindow(); - setEmbeddedWindowToOurSize(); - } + setEmbeddedWindowToOurSize(); + } - static void recursiveHIViewRepaint (HIViewRef view) - { - HIViewSetNeedsDisplay (view, true); - HIViewRef child = HIViewGetFirstSubview (view); + static void recursiveHIViewRepaint (HIViewRef view) + { + HIViewSetNeedsDisplay (view, true); + HIViewRef child = HIViewGetFirstSubview (view); - while (child != 0) - { - recursiveHIViewRepaint (child); - child = HIViewGetNextView (child); - } - } + while (child != 0) + { + recursiveHIViewRepaint (child); + child = HIViewGetNextView (child); + } + } - void timerCallback() - { - setOurSizeToEmbeddedViewSize(); + void timerCallback() + { + setOurSizeToEmbeddedViewSize(); - // To avoid strange overpainting problems when the UI is first opened, we'll - // repaint it a few times during the first second that it's on-screen.. - if ((Time::getCurrentTime() - creationTime).inMilliseconds() < 1000) - recursiveHIViewRepaint (HIViewGetRoot (wrapperWindow)); - } + // To avoid strange overpainting problems when the UI is first opened, we'll + // repaint it a few times during the first second that it's on-screen.. + if ((Time::getCurrentTime() - creationTime).inMilliseconds() < 1000) + recursiveHIViewRepaint (HIViewGetRoot (wrapperWindow)); + } - OSStatus carbonEventHandler (EventHandlerCallRef nextHandlerRef, - EventRef event) - { - switch (GetEventKind (event)) - { - case kEventWindowHandleDeactivate: - ActivateWindow (wrapperWindow, TRUE); - break; + OSStatus carbonEventHandler (EventHandlerCallRef nextHandlerRef, + EventRef event) + { + switch (GetEventKind (event)) + { + case kEventWindowHandleDeactivate: + ActivateWindow (wrapperWindow, TRUE); + break; - case kEventWindowGetClickActivation: - { - getTopLevelComponent()->toFront (false); + case kEventWindowGetClickActivation: + { + getTopLevelComponent()->toFront (false); - ClickActivationResult howToHandleClick = kActivateAndHandleClick; + ClickActivationResult howToHandleClick = kActivateAndHandleClick; - SetEventParameter (event, kEventParamClickActivation, typeClickActivationResult, - sizeof (ClickActivationResult), &howToHandleClick); + SetEventParameter (event, kEventParamClickActivation, typeClickActivationResult, + sizeof (ClickActivationResult), &howToHandleClick); - HIViewSetNeedsDisplay (embeddedView, true); - } - break; - } + HIViewSetNeedsDisplay (embeddedView, true); + } + break; + } - return noErr; - } + return noErr; + } - static pascal OSStatus carbonEventCallback (EventHandlerCallRef nextHandlerRef, - EventRef event, void* userData) - { - return ((CarbonViewWrapperComponent*) userData)->carbonEventHandler (nextHandlerRef, event); - } + static pascal OSStatus carbonEventCallback (EventHandlerCallRef nextHandlerRef, + EventRef event, void* userData) + { + return ((CarbonViewWrapperComponent*) userData)->carbonEventHandler (nextHandlerRef, event); + } protected: - WindowRef wrapperWindow; - HIViewRef embeddedView; - bool recursiveResize; - Time creationTime; + WindowRef wrapperWindow; + HIViewRef embeddedView; + bool recursiveResize; + Time creationTime; - EventHandlerRef eventHandlerRef; + EventHandlerRef eventHandlerRef; }; #endif // __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__ @@ -1060,29 +819,29 @@ protected: BEGIN_JUCE_NAMESPACE FileLogger::FileLogger (const File& logFile_, - const String& welcomeMessage, - const int maxInitialFileSizeBytes) - : logFile (logFile_) + const String& welcomeMessage, + const int maxInitialFileSizeBytes) + : logFile (logFile_) { - if (maxInitialFileSizeBytes >= 0) - trimFileSize (maxInitialFileSizeBytes); + if (maxInitialFileSizeBytes >= 0) + trimFileSize (maxInitialFileSizeBytes); - if (! logFile_.exists()) - { - // do this so that the parent directories get created.. - logFile_.create(); - } + if (! logFile_.exists()) + { + // do this so that the parent directories get created.. + logFile_.create(); + } - logStream = logFile_.createOutputStream (256); - jassert (logStream != 0); + logStream = logFile_.createOutputStream (256); + jassert (logStream != 0); - String welcome; - welcome << "\r\n**********************************************************\r\n" - << welcomeMessage - << "\r\nLog started: " << Time::getCurrentTime().toString (true, true) - << "\r\n"; + String welcome; + welcome << "\r\n**********************************************************\r\n" + << welcomeMessage + << "\r\nLog started: " << Time::getCurrentTime().toString (true, true) + << "\r\n"; - logMessage (welcome); + logMessage (welcome); } FileLogger::~FileLogger() @@ -1091,81 +850,81 @@ FileLogger::~FileLogger() void FileLogger::logMessage (const String& message) { - if (logStream != 0) - { - Logger::outputDebugString (message); + if (logStream != 0) + { + Logger::outputDebugString (message); - const ScopedLock sl (logLock); - (*logStream) << message << T("\r\n"); - logStream->flush(); - } + const ScopedLock sl (logLock); + (*logStream) << message << T("\r\n"); + logStream->flush(); + } } void FileLogger::trimFileSize (int maxFileSizeBytes) const { - if (maxFileSizeBytes <= 0) - { - logFile.deleteFile(); - } - else - { - const int64 fileSize = logFile.getSize(); + if (maxFileSizeBytes <= 0) + { + logFile.deleteFile(); + } + else + { + const int64 fileSize = logFile.getSize(); - if (fileSize > maxFileSizeBytes) - { - ScopedPointer in (logFile.createInputStream()); - jassert (in != 0); + if (fileSize > maxFileSizeBytes) + { + ScopedPointer in (logFile.createInputStream()); + jassert (in != 0); - if (in != 0) - { - in->setPosition (fileSize - maxFileSizeBytes); - String content; + if (in != 0) + { + in->setPosition (fileSize - maxFileSizeBytes); + String content; - { - MemoryBlock contentToSave; - contentToSave.setSize (maxFileSizeBytes + 4); - contentToSave.fillWith (0); + { + MemoryBlock contentToSave; + contentToSave.setSize (maxFileSizeBytes + 4); + contentToSave.fillWith (0); - in->read (contentToSave.getData(), maxFileSizeBytes); - in = 0; + in->read (contentToSave.getData(), maxFileSizeBytes); + in = 0; - content = contentToSave.toString(); - } + content = contentToSave.toString(); + } - int newStart = 0; + int newStart = 0; - while (newStart < fileSize - && content[newStart] != '\n' - && content[newStart] != '\r') - ++newStart; + while (newStart < fileSize + && content[newStart] != '\n' + && content[newStart] != '\r') + ++newStart; - logFile.deleteFile(); - logFile.appendText (content.substring (newStart), false, false); - } - } - } + logFile.deleteFile(); + logFile.appendText (content.substring (newStart), false, false); + } + } + } } FileLogger* FileLogger::createDefaultAppLogger (const String& logFileSubDirectoryName, - const String& logFileName, - const String& welcomeMessage, - const int maxInitialFileSizeBytes) + const String& logFileName, + const String& welcomeMessage, + const int maxInitialFileSizeBytes) { #if JUCE_MAC - File logFile ("~/Library/Logs"); - logFile = logFile.getChildFile (logFileName); + File logFile ("~/Library/Logs"); + logFile = logFile.getChildFile (logFileName); #else - File logFile (File::getSpecialLocation (File::userApplicationDataDirectory)); + File logFile (File::getSpecialLocation (File::userApplicationDataDirectory)); - if (logFile.isDirectory()) - { - logFile = logFile.getChildFile (logFileSubDirectoryName) - .getChildFile (logFileName); - } + if (logFile.isDirectory()) + { + logFile = logFile.getChildFile (logFileSubDirectoryName) + .getChildFile (logFileName); + } #endif - return new FileLogger (logFile, welcomeMessage, maxInitialFileSizeBytes); + return new FileLogger (logFile, welcomeMessage, maxInitialFileSizeBytes); } END_JUCE_NAMESPACE @@ -1186,30 +945,30 @@ Logger::~Logger() static Logger* currentLogger = 0; void Logger::setCurrentLogger (Logger* const newLogger, - const bool deleteOldLogger) + const bool deleteOldLogger) { - Logger* const oldLogger = currentLogger; - currentLogger = newLogger; + Logger* const oldLogger = currentLogger; + currentLogger = newLogger; - if (deleteOldLogger) - delete oldLogger; + if (deleteOldLogger) + delete oldLogger; } void Logger::writeToLog (const String& message) { - if (currentLogger != 0) - currentLogger->logMessage (message); - else - outputDebugString (message); + if (currentLogger != 0) + currentLogger->logMessage (message); + else + outputDebugString (message); } #if JUCE_LOG_ASSERTIONS void JUCE_API juce_LogAssertion (const char* filename, const int lineNum) throw() { - String m ("JUCE Assertion failure in "); - m << filename << ", line " << lineNum; + String m ("JUCE Assertion failure in "); + m << filename << ", line " << lineNum; - Logger::writeToLog (m); + Logger::writeToLog (m); } #endif @@ -1221,7 +980,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE Random::Random (const int64 seedValue) throw() - : seed (seedValue) + : seed (seedValue) { } @@ -1231,89 +990,89 @@ Random::~Random() throw() void Random::setSeed (const int64 newSeed) throw() { - seed = newSeed; + seed = newSeed; } void Random::setSeedRandomly() { - seed ^= (int64) (pointer_sized_int) this; - seed ^= nextInt64() ^ Time::getMillisecondCounter(); - seed ^= nextInt64() ^ Time::getHighResolutionTicks(); - seed ^= nextInt64() ^ Time::getHighResolutionTicksPerSecond(); - seed ^= nextInt64() ^ Time::currentTimeMillis(); + seed ^= (int64) (pointer_sized_int) this; + seed ^= nextInt64() ^ Time::getMillisecondCounter(); + seed ^= nextInt64() ^ Time::getHighResolutionTicks(); + seed ^= nextInt64() ^ Time::getHighResolutionTicksPerSecond(); + seed ^= nextInt64() ^ Time::currentTimeMillis(); } int Random::nextInt() throw() { - seed = (seed * literal64bit (0x5deece66d) + 11) & literal64bit (0xffffffffffff); + seed = (seed * literal64bit (0x5deece66d) + 11) & literal64bit (0xffffffffffff); - return (int) (seed >> 16); + return (int) (seed >> 16); } int Random::nextInt (const int maxValue) throw() { - jassert (maxValue > 0); - return (nextInt() & 0x7fffffff) % maxValue; + jassert (maxValue > 0); + return (nextInt() & 0x7fffffff) % maxValue; } int64 Random::nextInt64() throw() { - return (((int64) nextInt()) << 32) | (int64) (uint64) (uint32) nextInt(); + return (((int64) nextInt()) << 32) | (int64) (uint64) (uint32) nextInt(); } bool Random::nextBool() throw() { - return (nextInt() & 0x80000000) != 0; + return (nextInt() & 0x80000000) != 0; } float Random::nextFloat() throw() { - return ((uint32) nextInt()) / (float) 0xffffffff; + return ((uint32) nextInt()) / (float) 0xffffffff; } double Random::nextDouble() throw() { - return ((uint32) nextInt()) / (double) 0xffffffff; + return ((uint32) nextInt()) / (double) 0xffffffff; } const BitArray Random::nextLargeNumber (const BitArray& maximumValue) throw() { - BitArray n; + BitArray n; - do - { - fillBitsRandomly (n, 0, maximumValue.getHighestBit() + 1); - } - while (n.compare (maximumValue) >= 0); + do + { + fillBitsRandomly (n, 0, maximumValue.getHighestBit() + 1); + } + while (n.compare (maximumValue) >= 0); - return n; + return n; } void Random::fillBitsRandomly (BitArray& arrayToChange, int startBit, int numBits) throw() { - arrayToChange.setBit (startBit + numBits - 1, true); // to force the array to pre-allocate space + arrayToChange.setBit (startBit + numBits - 1, true); // to force the array to pre-allocate space - while ((startBit & 31) != 0 && numBits > 0) - { - arrayToChange.setBit (startBit++, nextBool()); - --numBits; - } + while ((startBit & 31) != 0 && numBits > 0) + { + arrayToChange.setBit (startBit++, nextBool()); + --numBits; + } - while (numBits >= 32) - { - arrayToChange.setBitRangeAsInt (startBit, 32, (unsigned int) nextInt()); - startBit += 32; - numBits -= 32; - } + while (numBits >= 32) + { + arrayToChange.setBitRangeAsInt (startBit, 32, (unsigned int) nextInt()); + startBit += 32; + numBits -= 32; + } - while (--numBits >= 0) - arrayToChange.setBit (startBit + numBits, nextBool()); + while (--numBits >= 0) + arrayToChange.setBit (startBit + numBits, nextBool()); } Random& Random::getSystemRandom() throw() { - static Random sysRand (1); - return sysRand; + static Random sysRand (1); + return sysRand; } END_JUCE_NAMESPACE @@ -1324,12 +1083,12 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE RelativeTime::RelativeTime (const double seconds_) throw() - : seconds (seconds_) + : seconds (seconds_) { } RelativeTime::RelativeTime (const RelativeTime& other) throw() - : seconds (other.seconds) + : seconds (other.seconds) { } @@ -1339,210 +1098,210 @@ RelativeTime::~RelativeTime() throw() const RelativeTime RelativeTime::milliseconds (const int milliseconds) throw() { - return RelativeTime (milliseconds * 0.001); + return RelativeTime (milliseconds * 0.001); } const RelativeTime RelativeTime::milliseconds (const int64 milliseconds) throw() { - return RelativeTime (milliseconds * 0.001); + return RelativeTime (milliseconds * 0.001); } const RelativeTime RelativeTime::minutes (const double numberOfMinutes) throw() { - return RelativeTime (numberOfMinutes * 60.0); + return RelativeTime (numberOfMinutes * 60.0); } const RelativeTime RelativeTime::hours (const double numberOfHours) throw() { - return RelativeTime (numberOfHours * (60.0 * 60.0)); + return RelativeTime (numberOfHours * (60.0 * 60.0)); } const RelativeTime RelativeTime::days (const double numberOfDays) throw() { - return RelativeTime (numberOfDays * (60.0 * 60.0 * 24.0)); + return RelativeTime (numberOfDays * (60.0 * 60.0 * 24.0)); } const RelativeTime RelativeTime::weeks (const double numberOfWeeks) throw() { - return RelativeTime (numberOfWeeks * (60.0 * 60.0 * 24.0 * 7.0)); + return RelativeTime (numberOfWeeks * (60.0 * 60.0 * 24.0 * 7.0)); } int64 RelativeTime::inMilliseconds() const throw() { - return (int64)(seconds * 1000.0); + return (int64)(seconds * 1000.0); } double RelativeTime::inMinutes() const throw() { - return seconds / 60.0; + return seconds / 60.0; } double RelativeTime::inHours() const throw() { - return seconds / (60.0 * 60.0); + return seconds / (60.0 * 60.0); } double RelativeTime::inDays() const throw() { - return seconds / (60.0 * 60.0 * 24.0); + return seconds / (60.0 * 60.0 * 24.0); } double RelativeTime::inWeeks() const throw() { - return seconds / (60.0 * 60.0 * 24.0 * 7.0); + return seconds / (60.0 * 60.0 * 24.0 * 7.0); } const String RelativeTime::getDescription (const String& returnValueForZeroTime) const throw() { - if (seconds < 0.001 && seconds > -0.001) - return returnValueForZeroTime; + if (seconds < 0.001 && seconds > -0.001) + return returnValueForZeroTime; - String result; + String result; - if (seconds < 0) - result = T("-"); + if (seconds < 0) + result = T("-"); - int fieldsShown = 0; - int n = abs ((int) inWeeks()); - if (n > 0) - { - result << n << ((n == 1) ? TRANS(" week ") - : TRANS(" weeks ")); - ++fieldsShown; - } + int fieldsShown = 0; + int n = abs ((int) inWeeks()); + if (n > 0) + { + result << n << ((n == 1) ? TRANS(" week ") + : TRANS(" weeks ")); + ++fieldsShown; + } - n = abs ((int) inDays()) % 7; - if (n > 0) - { - result << n << ((n == 1) ? TRANS(" day ") - : TRANS(" days ")); - ++fieldsShown; - } + n = abs ((int) inDays()) % 7; + if (n > 0) + { + result << n << ((n == 1) ? TRANS(" day ") + : TRANS(" days ")); + ++fieldsShown; + } - if (fieldsShown < 2) - { - n = abs ((int) inHours()) % 24; - if (n > 0) - { - result << n << ((n == 1) ? TRANS(" hr ") - : TRANS(" hrs ")); - ++fieldsShown; - } + if (fieldsShown < 2) + { + n = abs ((int) inHours()) % 24; + if (n > 0) + { + result << n << ((n == 1) ? TRANS(" hr ") + : TRANS(" hrs ")); + ++fieldsShown; + } - if (fieldsShown < 2) - { - n = abs ((int) inMinutes()) % 60; - if (n > 0) - { - result << n << ((n == 1) ? TRANS(" min ") - : TRANS(" mins ")); - ++fieldsShown; - } + if (fieldsShown < 2) + { + n = abs ((int) inMinutes()) % 60; + if (n > 0) + { + result << n << ((n == 1) ? TRANS(" min ") + : TRANS(" mins ")); + ++fieldsShown; + } - if (fieldsShown < 2) - { - n = abs ((int) inSeconds()) % 60; - if (n > 0) - { - result << n << ((n == 1) ? TRANS(" sec ") - : TRANS(" secs ")); - ++fieldsShown; - } + if (fieldsShown < 2) + { + n = abs ((int) inSeconds()) % 60; + if (n > 0) + { + result << n << ((n == 1) ? TRANS(" sec ") + : TRANS(" secs ")); + ++fieldsShown; + } - if (fieldsShown < 1) - { - n = abs ((int) inMilliseconds()) % 1000; - if (n > 0) - { - result << n << TRANS(" ms"); - ++fieldsShown; - } - } - } - } - } + if (fieldsShown < 1) + { + n = abs ((int) inMilliseconds()) % 1000; + if (n > 0) + { + result << n << TRANS(" ms"); + ++fieldsShown; + } + } + } + } + } - return result.trimEnd(); + return result.trimEnd(); } const RelativeTime& RelativeTime::operator= (const RelativeTime& other) throw() { - seconds = other.seconds; - return *this; + seconds = other.seconds; + return *this; } bool RelativeTime::operator== (const RelativeTime& other) const throw() { - return seconds == other.seconds; + return seconds == other.seconds; } bool RelativeTime::operator!= (const RelativeTime& other) const throw() { - return seconds != other.seconds; + return seconds != other.seconds; } bool RelativeTime::operator> (const RelativeTime& other) const throw() { - return seconds > other.seconds; + return seconds > other.seconds; } bool RelativeTime::operator< (const RelativeTime& other) const throw() { - return seconds < other.seconds; + return seconds < other.seconds; } bool RelativeTime::operator>= (const RelativeTime& other) const throw() { - return seconds >= other.seconds; + return seconds >= other.seconds; } bool RelativeTime::operator<= (const RelativeTime& other) const throw() { - return seconds <= other.seconds; + return seconds <= other.seconds; } const RelativeTime RelativeTime::operator+ (const RelativeTime& timeToAdd) const throw() { - return RelativeTime (seconds + timeToAdd.seconds); + return RelativeTime (seconds + timeToAdd.seconds); } const RelativeTime RelativeTime::operator- (const RelativeTime& timeToSubtract) const throw() { - return RelativeTime (seconds - timeToSubtract.seconds); + return RelativeTime (seconds - timeToSubtract.seconds); } const RelativeTime RelativeTime::operator+ (const double secondsToAdd) const throw() { - return RelativeTime (seconds + secondsToAdd); + return RelativeTime (seconds + secondsToAdd); } const RelativeTime RelativeTime::operator- (const double secondsToSubtract) const throw() { - return RelativeTime (seconds - secondsToSubtract); + return RelativeTime (seconds - secondsToSubtract); } const RelativeTime& RelativeTime::operator+= (const RelativeTime& timeToAdd) throw() { - seconds += timeToAdd.seconds; - return *this; + seconds += timeToAdd.seconds; + return *this; } const RelativeTime& RelativeTime::operator-= (const RelativeTime& timeToSubtract) throw() { - seconds -= timeToSubtract.seconds; - return *this; + seconds -= timeToSubtract.seconds; + return *this; } const RelativeTime& RelativeTime::operator+= (const double secondsToAdd) throw() { - seconds += secondsToAdd; - return *this; + seconds += secondsToAdd; + return *this; } const RelativeTime& RelativeTime::operator-= (const double secondsToSubtract) throw() { - seconds -= secondsToSubtract; - return *this; + seconds -= secondsToSubtract; + return *this; } END_JUCE_NAMESPACE @@ -1556,76 +1315,84 @@ void juce_initialiseStrings(); const String SystemStats::getJUCEVersion() throw() { - return "JUCE v" + String (JUCE_MAJOR_VERSION) + "." + String (JUCE_MINOR_VERSION); + return "JUCE v" + String (JUCE_MAJOR_VERSION) + "." + String (JUCE_MINOR_VERSION); } static bool juceInitialisedNonGUI = false; void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() { - if (! juceInitialisedNonGUI) - { + if (! juceInitialisedNonGUI) + { #if JUCE_MAC || JUCE_IPHONE - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; #endif #ifdef JUCE_DEBUG - { - // Some simple test code to keep an eye on things and make sure these functions - // work ok on all platforms. Let me know if any of these assertions fail! - int n = 1; - Atomic::increment (n); - jassert (Atomic::incrementAndReturn (n) == 3); - Atomic::decrement (n); - jassert (Atomic::decrementAndReturn (n) == 1); + { + // Some simple test code to keep an eye on things and make sure these functions + // work ok on all platforms. Let me know if any of these assertions fail! - jassert (ByteOrder::swap ((uint16) 0x1122) == 0x2211); - jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); + jassert (sizeof (pointer_sized_int) == sizeof (void*)); - // quick test to make sure the run-time lib doesn't crash on freeing a null-pointer. - SystemStats* nullPointer = 0; - juce_free (nullPointer); - delete[] nullPointer; - delete nullPointer; + char a1[7]; + jassert (numElementsInArray(a1) == 7); + int a2[3]; + jassert (numElementsInArray(a2) == 3); - // Some quick stream tests.. - int randomInt = Random::getSystemRandom().nextInt(); - int64 randomInt64 = Random::getSystemRandom().nextInt64(); - double randomDouble = Random::getSystemRandom().nextDouble(); - String randomString; - for (int i = 50; --i >= 0;) - randomString << (juce_wchar) (Random::getSystemRandom().nextInt() & 0xffff); + int n = 1; + Atomic::increment (n); + jassert (Atomic::incrementAndReturn (n) == 3); + Atomic::decrement (n); + jassert (Atomic::decrementAndReturn (n) == 1); - MemoryOutputStream mo; - mo.writeInt (randomInt); - mo.writeIntBigEndian (randomInt); - mo.writeCompressedInt (randomInt); - mo.writeString (randomString); - mo.writeInt64 (randomInt64); - mo.writeInt64BigEndian (randomInt64); - mo.writeDouble (randomDouble); - mo.writeDoubleBigEndian (randomDouble); + jassert (ByteOrder::swap ((uint16) 0x1122) == 0x2211); + jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); - MemoryInputStream mi (mo.getData(), mo.getDataSize(), false); - jassert (mi.readInt() == randomInt); - jassert (mi.readIntBigEndian() == randomInt); - jassert (mi.readCompressedInt() == randomInt); - jassert (mi.readString() == randomString); - jassert (mi.readInt64() == randomInt64); - jassert (mi.readInt64BigEndian() == randomInt64); - jassert (mi.readDouble() == randomDouble); - jassert (mi.readDoubleBigEndian() == randomDouble); - } + // quick test to make sure the run-time lib doesn't crash on freeing a null-pointer. + SystemStats* nullPointer = 0; + juce_free (nullPointer); + delete[] nullPointer; + delete nullPointer; + + // Some quick stream tests.. + int randomInt = Random::getSystemRandom().nextInt(); + int64 randomInt64 = Random::getSystemRandom().nextInt64(); + double randomDouble = Random::getSystemRandom().nextDouble(); + String randomString; + for (int i = 50; --i >= 0;) + randomString << (juce_wchar) (Random::getSystemRandom().nextInt() & 0xffff); + + MemoryOutputStream mo; + mo.writeInt (randomInt); + mo.writeIntBigEndian (randomInt); + mo.writeCompressedInt (randomInt); + mo.writeString (randomString); + mo.writeInt64 (randomInt64); + mo.writeInt64BigEndian (randomInt64); + mo.writeDouble (randomDouble); + mo.writeDoubleBigEndian (randomDouble); + + MemoryInputStream mi (mo.getData(), mo.getDataSize(), false); + jassert (mi.readInt() == randomInt); + jassert (mi.readIntBigEndian() == randomInt); + jassert (mi.readCompressedInt() == randomInt); + jassert (mi.readString() == randomString); + jassert (mi.readInt64() == randomInt64); + jassert (mi.readInt64BigEndian() == randomInt64); + jassert (mi.readDouble() == randomDouble); + jassert (mi.readDoubleBigEndian() == randomDouble); + } #endif - // Now the real initialisation.. + // Now the real initialisation.. - juceInitialisedNonGUI = true; + juceInitialisedNonGUI = true; - DBG (SystemStats::getJUCEVersion()); - juce_initialiseStrings(); - SystemStats::initialiseStats(); - Random::getSystemRandom().setSeedRandomly(); // (mustn't call this before initialiseStats() because it relies on the time being set up) - } + DBG (SystemStats::getJUCEVersion()); + juce_initialiseStrings(); + SystemStats::initialiseStats(); + Random::getSystemRandom().setSeedRandomly(); // (mustn't call this before initialiseStats() because it relies on the time being set up) + } } #if JUCE_WINDOWS @@ -1640,71 +1407,71 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() void JUCE_PUBLIC_FUNCTION shutdownJuce_NonGUI() { - if (juceInitialisedNonGUI) - { + if (juceInitialisedNonGUI) + { #if JUCE_MAC || JUCE_IPHONE - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; #endif #if JUCE_WINDOWS - // need to shut down sockets if they were used.. - if (juce_CloseWin32SocketLib != 0) - (*juce_CloseWin32SocketLib)(); + // need to shut down sockets if they were used.. + if (juce_CloseWin32SocketLib != 0) + (*juce_CloseWin32SocketLib)(); #endif - LocalisedStrings::setCurrentMappings (0); - Thread::stopAllThreads (3000); + LocalisedStrings::setCurrentMappings (0); + Thread::stopAllThreads (3000); #if JUCE_DEBUG - juce_CheckForDanglingStreams(); + juce_CheckForDanglingStreams(); #endif - juceInitialisedNonGUI = false; - } + juceInitialisedNonGUI = false; + } } #ifdef JUCE_DLL void* juce_Malloc (const int size) { - return malloc (size); + return malloc (size); } void* juce_Calloc (const int size) { - return calloc (1, size); + return calloc (1, size); } void* juce_Realloc (void* const block, const int size) { - return realloc (block, size); + return realloc (block, size); } void juce_Free (void* const block) { - free (block); + free (block); } #if defined (JUCE_DEBUG) && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS void* juce_DebugMalloc (const int size, const char* file, const int line) { - return _malloc_dbg (size, _NORMAL_BLOCK, file, line); + return _malloc_dbg (size, _NORMAL_BLOCK, file, line); } void* juce_DebugCalloc (const int size, const char* file, const int line) { - return _calloc_dbg (1, size, _NORMAL_BLOCK, file, line); + return _calloc_dbg (1, size, _NORMAL_BLOCK, file, line); } void* juce_DebugRealloc (void* const block, const int size, const char* file, const int line) { - return _realloc_dbg (block, size, _NORMAL_BLOCK, file, line); + return _realloc_dbg (block, size, _NORMAL_BLOCK, file, line); } void juce_DebugFree (void* const block) { - _free_dbg (block, _NORMAL_BLOCK); + _free_dbg (block, _NORMAL_BLOCK); } #endif @@ -1733,121 +1500,121 @@ BEGIN_JUCE_NAMESPACE #pragma warning (pop) #ifdef _INC_TIME_INL - #define USE_NEW_SECURE_TIME_FNS + #define USE_NEW_SECURE_TIME_FNS #endif #endif static void millisToLocal (const int64 millis, struct tm& result) throw() { - const int64 seconds = millis / 1000; + const int64 seconds = millis / 1000; - if (seconds < literal64bit (86400) || seconds >= literal64bit (2145916800)) - { - // use extended maths for dates beyond 1970 to 2037.. - const int timeZoneAdjustment = 31536000 - (int) (Time (1971, 0, 1, 0, 0).toMilliseconds() / 1000); - const int64 jdm = seconds + timeZoneAdjustment + literal64bit (210866803200); + if (seconds < literal64bit (86400) || seconds >= literal64bit (2145916800)) + { + // use extended maths for dates beyond 1970 to 2037.. + const int timeZoneAdjustment = 31536000 - (int) (Time (1971, 0, 1, 0, 0).toMilliseconds() / 1000); + const int64 jdm = seconds + timeZoneAdjustment + literal64bit (210866803200); - const int days = (int) (jdm / literal64bit (86400)); - const int a = 32044 + days; - const int b = (4 * a + 3) / 146097; - const int c = a - (b * 146097) / 4; - const int d = (4 * c + 3) / 1461; - const int e = c - (d * 1461) / 4; - const int m = (5 * e + 2) / 153; + const int days = (int) (jdm / literal64bit (86400)); + const int a = 32044 + days; + const int b = (4 * a + 3) / 146097; + const int c = a - (b * 146097) / 4; + const int d = (4 * c + 3) / 1461; + const int e = c - (d * 1461) / 4; + const int m = (5 * e + 2) / 153; - result.tm_mday = e - (153 * m + 2) / 5 + 1; - result.tm_mon = m + 2 - 12 * (m / 10); - result.tm_year = b * 100 + d - 6700 + (m / 10); - result.tm_wday = (days + 1) % 7; - result.tm_yday = -1; + result.tm_mday = e - (153 * m + 2) / 5 + 1; + result.tm_mon = m + 2 - 12 * (m / 10); + result.tm_year = b * 100 + d - 6700 + (m / 10); + result.tm_wday = (days + 1) % 7; + result.tm_yday = -1; - int t = (int) (jdm % literal64bit (86400)); - result.tm_hour = t / 3600; - t %= 3600; - result.tm_min = t / 60; - result.tm_sec = t % 60; - result.tm_isdst = -1; - } - else - { - time_t now = (time_t) (seconds); + int t = (int) (jdm % literal64bit (86400)); + result.tm_hour = t / 3600; + t %= 3600; + result.tm_min = t / 60; + result.tm_sec = t % 60; + result.tm_isdst = -1; + } + else + { + time_t now = (time_t) (seconds); #if JUCE_WINDOWS #ifdef USE_NEW_SECURE_TIME_FNS - if (now >= 0 && now <= 0x793406fff) - localtime_s (&result, &now); - else - zeromem (&result, sizeof (result)); + if (now >= 0 && now <= 0x793406fff) + localtime_s (&result, &now); + else + zeromem (&result, sizeof (result)); #else - result = *localtime (&now); + result = *localtime (&now); #endif #else - // more thread-safe - localtime_r (&now, &result); + // more thread-safe + localtime_r (&now, &result); #endif - } + } } Time::Time() throw() - : millisSinceEpoch (0) + : millisSinceEpoch (0) { } Time::Time (const Time& other) throw() - : millisSinceEpoch (other.millisSinceEpoch) + : millisSinceEpoch (other.millisSinceEpoch) { } Time::Time (const int64 ms) throw() - : millisSinceEpoch (ms) + : millisSinceEpoch (ms) { } Time::Time (const int year, - const int month, - const int day, - const int hours, - const int minutes, - const int seconds, - const int milliseconds, - const bool useLocalTime) throw() + const int month, + const int day, + const int hours, + const int minutes, + const int seconds, + const int milliseconds, + const bool useLocalTime) throw() { - jassert (year > 100); // year must be a 4-digit version + jassert (year > 100); // year must be a 4-digit version - if (year < 1971 || year >= 2038 || ! useLocalTime) - { - // use extended maths for dates beyond 1970 to 2037.. - const int timeZoneAdjustment = useLocalTime ? (31536000 - (int) (Time (1971, 0, 1, 0, 0).toMilliseconds() / 1000)) - : 0; - const int a = (13 - month) / 12; - const int y = year + 4800 - a; - const int jd = day + (153 * (month + 12 * a - 2) + 2) / 5 - + (y * 365) + (y / 4) - (y / 100) + (y / 400) - - 32045; + if (year < 1971 || year >= 2038 || ! useLocalTime) + { + // use extended maths for dates beyond 1970 to 2037.. + const int timeZoneAdjustment = useLocalTime ? (31536000 - (int) (Time (1971, 0, 1, 0, 0).toMilliseconds() / 1000)) + : 0; + const int a = (13 - month) / 12; + const int y = year + 4800 - a; + const int jd = day + (153 * (month + 12 * a - 2) + 2) / 5 + + (y * 365) + (y / 4) - (y / 100) + (y / 400) + - 32045; - const int64 s = ((int64) jd) * literal64bit (86400) - literal64bit (210866803200); + const int64 s = ((int64) jd) * literal64bit (86400) - literal64bit (210866803200); - millisSinceEpoch = 1000 * (s + (hours * 3600 + minutes * 60 + seconds - timeZoneAdjustment)) - + milliseconds; - } - else - { - struct tm t; - t.tm_year = year - 1900; - t.tm_mon = month; - t.tm_mday = day; - t.tm_hour = hours; - t.tm_min = minutes; - t.tm_sec = seconds; - t.tm_isdst = -1; + millisSinceEpoch = 1000 * (s + (hours * 3600 + minutes * 60 + seconds - timeZoneAdjustment)) + + milliseconds; + } + else + { + struct tm t; + t.tm_year = year - 1900; + t.tm_mon = month; + t.tm_mday = day; + t.tm_hour = hours; + t.tm_min = minutes; + t.tm_sec = seconds; + t.tm_isdst = -1; - millisSinceEpoch = 1000 * (int64) mktime (&t); + millisSinceEpoch = 1000 * (int64) mktime (&t); - if (millisSinceEpoch < 0) - millisSinceEpoch = 0; - else - millisSinceEpoch += milliseconds; - } + if (millisSinceEpoch < 0) + millisSinceEpoch = 0; + else + millisSinceEpoch += milliseconds; + } } Time::~Time() throw() @@ -1856,45 +1623,45 @@ Time::~Time() throw() const Time& Time::operator= (const Time& other) throw() { - millisSinceEpoch = other.millisSinceEpoch; - return *this; + millisSinceEpoch = other.millisSinceEpoch; + return *this; } int64 Time::currentTimeMillis() throw() { - static uint32 lastCounterResult = 0xffffffff; - static int64 correction = 0; + static uint32 lastCounterResult = 0xffffffff; + static int64 correction = 0; - const uint32 now = getMillisecondCounter(); + const uint32 now = getMillisecondCounter(); - // check the counter hasn't wrapped (also triggered the first time this function is called) - if (now < lastCounterResult) - { - // double-check it's actually wrapped, in case multi-cpu machines have timers that drift a bit. - if (lastCounterResult == 0xffffffff || now < lastCounterResult - 10) - { - // get the time once using normal library calls, and store the difference needed to - // turn the millisecond counter into a real time. + // check the counter hasn't wrapped (also triggered the first time this function is called) + if (now < lastCounterResult) + { + // double-check it's actually wrapped, in case multi-cpu machines have timers that drift a bit. + if (lastCounterResult == 0xffffffff || now < lastCounterResult - 10) + { + // get the time once using normal library calls, and store the difference needed to + // turn the millisecond counter into a real time. #if JUCE_WINDOWS - struct _timeb t; + struct _timeb t; #ifdef USE_NEW_SECURE_TIME_FNS - _ftime_s (&t); + _ftime_s (&t); #else - _ftime (&t); + _ftime (&t); #endif - correction = (((int64) t.time) * 1000 + t.millitm) - now; + correction = (((int64) t.time) * 1000 + t.millitm) - now; #else - struct timeval tv; - struct timezone tz; - gettimeofday (&tv, &tz); - correction = (((int64) tv.tv_sec) * 1000 + tv.tv_usec / 1000) - now; + struct timeval tv; + struct timezone tz; + gettimeofday (&tv, &tz); + correction = (((int64) tv.tv_sec) * 1000 + tv.tv_usec / 1000) - now; #endif - } - } + } + } - lastCounterResult = now; + lastCounterResult = now; - return correction + now; + return correction + now; } uint32 juce_millisecondsSinceStartup() throw(); @@ -1902,288 +1669,288 @@ static uint32 lastMSCounterValue = 0; uint32 Time::getMillisecondCounter() throw() { - const uint32 now = juce_millisecondsSinceStartup(); + const uint32 now = juce_millisecondsSinceStartup(); - if (now < lastMSCounterValue) - { - // in multi-threaded apps this might be called concurrently, so - // make sure that our last counter value only increases and doesn't - // go backwards.. - if (now < lastMSCounterValue - 1000) - lastMSCounterValue = now; - } - else - { - lastMSCounterValue = now; - } + if (now < lastMSCounterValue) + { + // in multi-threaded apps this might be called concurrently, so + // make sure that our last counter value only increases and doesn't + // go backwards.. + if (now < lastMSCounterValue - 1000) + lastMSCounterValue = now; + } + else + { + lastMSCounterValue = now; + } - return now; + return now; } uint32 Time::getApproximateMillisecondCounter() throw() { - jassert (lastMSCounterValue != 0); - return lastMSCounterValue; + jassert (lastMSCounterValue != 0); + return lastMSCounterValue; } void Time::waitForMillisecondCounter (const uint32 targetTime) throw() { - for (;;) - { - const uint32 now = getMillisecondCounter(); + for (;;) + { + const uint32 now = getMillisecondCounter(); - if (now >= targetTime) - break; + if (now >= targetTime) + break; - const int toWait = targetTime - now; + const int toWait = targetTime - now; - if (toWait > 2) - { - Thread::sleep (jmin (20, toWait >> 1)); - } - else - { - // xxx should consider using mutex_pause on the mac as it apparently - // makes it seem less like a spinlock and avoids lowering the thread pri. - for (int i = 10; --i >= 0;) - Thread::yield(); - } - } + if (toWait > 2) + { + Thread::sleep (jmin (20, toWait >> 1)); + } + else + { + // xxx should consider using mutex_pause on the mac as it apparently + // makes it seem less like a spinlock and avoids lowering the thread pri. + for (int i = 10; --i >= 0;) + Thread::yield(); + } + } } double Time::highResolutionTicksToSeconds (const int64 ticks) throw() { - return ticks / (double) getHighResolutionTicksPerSecond(); + return ticks / (double) getHighResolutionTicksPerSecond(); } int64 Time::secondsToHighResolutionTicks (const double seconds) throw() { - return (int64) (seconds * (double) getHighResolutionTicksPerSecond()); + return (int64) (seconds * (double) getHighResolutionTicksPerSecond()); } const Time JUCE_CALLTYPE Time::getCurrentTime() throw() { - return Time (currentTimeMillis()); + return Time (currentTimeMillis()); } const String Time::toString (const bool includeDate, - const bool includeTime, - const bool includeSeconds, - const bool use24HourClock) const throw() + const bool includeTime, + const bool includeSeconds, + const bool use24HourClock) const throw() { - String result; + String result; - if (includeDate) - { - result << getDayOfMonth() << ' ' - << getMonthName (true) << ' ' - << getYear(); + if (includeDate) + { + result << getDayOfMonth() << ' ' + << getMonthName (true) << ' ' + << getYear(); - if (includeTime) - result << ' '; - } + if (includeTime) + result << ' '; + } - if (includeTime) - { - if (includeSeconds) - { - result += String::formatted (T("%d:%02d:%02d "), - (use24HourClock) ? getHours() - : getHoursInAmPmFormat(), - getMinutes(), - getSeconds()); - } - else - { - result += String::formatted (T("%d.%02d"), - (use24HourClock) ? getHours() - : getHoursInAmPmFormat(), - getMinutes()); - } + if (includeTime) + { + if (includeSeconds) + { + result += String::formatted (T("%d:%02d:%02d "), + (use24HourClock) ? getHours() + : getHoursInAmPmFormat(), + getMinutes(), + getSeconds()); + } + else + { + result += String::formatted (T("%d.%02d"), + (use24HourClock) ? getHours() + : getHoursInAmPmFormat(), + getMinutes()); + } - if (! use24HourClock) - result << (isAfternoon() ? "pm" : "am"); - } + if (! use24HourClock) + result << (isAfternoon() ? "pm" : "am"); + } - return result.trimEnd(); + return result.trimEnd(); } const String Time::formatted (const tchar* const format) const throw() { - String buffer; - int bufferSize = 128; - buffer.preallocateStorage (bufferSize); + String buffer; + int bufferSize = 128; + buffer.preallocateStorage (bufferSize); - struct tm t; - millisToLocal (millisSinceEpoch, t); + struct tm t; + millisToLocal (millisSinceEpoch, t); - while (CharacterFunctions::ftime ((tchar*) (const tchar*) buffer, bufferSize, format, &t) <= 0) - { - bufferSize += 128; - buffer.preallocateStorage (bufferSize); - } + while (CharacterFunctions::ftime ((tchar*) (const tchar*) buffer, bufferSize, format, &t) <= 0) + { + bufferSize += 128; + buffer.preallocateStorage (bufferSize); + } - return buffer; + return buffer; } int Time::getYear() const throw() { - struct tm t; - millisToLocal (millisSinceEpoch, t); - return t.tm_year + 1900; + struct tm t; + millisToLocal (millisSinceEpoch, t); + return t.tm_year + 1900; } int Time::getMonth() const throw() { - struct tm t; - millisToLocal (millisSinceEpoch, t); - return t.tm_mon; + struct tm t; + millisToLocal (millisSinceEpoch, t); + return t.tm_mon; } int Time::getDayOfMonth() const throw() { - struct tm t; - millisToLocal (millisSinceEpoch, t); - return t.tm_mday; + struct tm t; + millisToLocal (millisSinceEpoch, t); + return t.tm_mday; } int Time::getDayOfWeek() const throw() { - struct tm t; - millisToLocal (millisSinceEpoch, t); - return t.tm_wday; + struct tm t; + millisToLocal (millisSinceEpoch, t); + return t.tm_wday; } int Time::getHours() const throw() { - struct tm t; - millisToLocal (millisSinceEpoch, t); - return t.tm_hour; + struct tm t; + millisToLocal (millisSinceEpoch, t); + return t.tm_hour; } int Time::getHoursInAmPmFormat() const throw() { - const int hours = getHours(); + const int hours = getHours(); - if (hours == 0) - return 12; - else if (hours <= 12) - return hours; - else - return hours - 12; + if (hours == 0) + return 12; + else if (hours <= 12) + return hours; + else + return hours - 12; } bool Time::isAfternoon() const throw() { - return getHours() >= 12; + return getHours() >= 12; } static int extendedModulo (const int64 value, const int modulo) throw() { - return (int) (value >= 0 ? (value % modulo) - : (value - ((value / modulo) + 1) * modulo)); + return (int) (value >= 0 ? (value % modulo) + : (value - ((value / modulo) + 1) * modulo)); } int Time::getMinutes() const throw() { - struct tm t; - millisToLocal (millisSinceEpoch, t); - return t.tm_min; + struct tm t; + millisToLocal (millisSinceEpoch, t); + return t.tm_min; } int Time::getSeconds() const throw() { - return extendedModulo (millisSinceEpoch / 1000, 60); + return extendedModulo (millisSinceEpoch / 1000, 60); } int Time::getMilliseconds() const throw() { - return extendedModulo (millisSinceEpoch, 1000); + return extendedModulo (millisSinceEpoch, 1000); } bool Time::isDaylightSavingTime() const throw() { - struct tm t; - millisToLocal (millisSinceEpoch, t); - return t.tm_isdst != 0; + struct tm t; + millisToLocal (millisSinceEpoch, t); + return t.tm_isdst != 0; } const String Time::getTimeZone() const throw() { - String zone[2]; + String zone[2]; #if JUCE_WINDOWS - _tzset(); + _tzset(); #ifdef USE_NEW_SECURE_TIME_FNS - { - char name [128]; - size_t length; + { + char name [128]; + size_t length; - for (int i = 0; i < 2; ++i) - { - zeromem (name, sizeof (name)); - _get_tzname (&length, name, 127, i); - zone[i] = name; - } - } + for (int i = 0; i < 2; ++i) + { + zeromem (name, sizeof (name)); + _get_tzname (&length, name, 127, i); + zone[i] = name; + } + } #else - const char** const zonePtr = (const char**) _tzname; - zone[0] = zonePtr[0]; - zone[1] = zonePtr[1]; + const char** const zonePtr = (const char**) _tzname; + zone[0] = zonePtr[0]; + zone[1] = zonePtr[1]; #endif #else - tzset(); - const char** const zonePtr = (const char**) tzname; - zone[0] = zonePtr[0]; - zone[1] = zonePtr[1]; + tzset(); + const char** const zonePtr = (const char**) tzname; + zone[0] = zonePtr[0]; + zone[1] = zonePtr[1]; #endif - if (isDaylightSavingTime()) - { - zone[0] = zone[1]; + if (isDaylightSavingTime()) + { + zone[0] = zone[1]; - if (zone[0].length() > 3 - && zone[0].containsIgnoreCase (T("daylight")) - && zone[0].contains (T("GMT"))) - zone[0] = "BST"; - } + if (zone[0].length() > 3 + && zone[0].containsIgnoreCase (T("daylight")) + && zone[0].contains (T("GMT"))) + zone[0] = "BST"; + } - return zone[0].substring (0, 3); + return zone[0].substring (0, 3); } const String Time::getMonthName (const bool threeLetterVersion) const throw() { - return getMonthName (getMonth(), threeLetterVersion); + return getMonthName (getMonth(), threeLetterVersion); } const String Time::getWeekdayName (const bool threeLetterVersion) const throw() { - return getWeekdayName (getDayOfWeek(), threeLetterVersion); + return getWeekdayName (getDayOfWeek(), threeLetterVersion); } const String Time::getMonthName (int monthNumber, - const bool threeLetterVersion) throw() + const bool threeLetterVersion) throw() { - const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - const char* const longMonthNames[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; + const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + const char* const longMonthNames[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; - monthNumber %= 12; + monthNumber %= 12; - return TRANS (threeLetterVersion ? shortMonthNames [monthNumber] - : longMonthNames [monthNumber]); + return TRANS (threeLetterVersion ? shortMonthNames [monthNumber] + : longMonthNames [monthNumber]); } const String Time::getWeekdayName (int day, - const bool threeLetterVersion) throw() + const bool threeLetterVersion) throw() { - const char* const shortDayNames[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; - const char* const longDayNames[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; + const char* const shortDayNames[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + const char* const longDayNames[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; - day %= 7; + day %= 7; - return TRANS (threeLetterVersion ? shortDayNames [day] - : longDayNames [day]); + return TRANS (threeLetterVersion ? shortDayNames [day] + : longDayNames [day]); } END_JUCE_NAMESPACE @@ -2194,55 +1961,55 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE BitArray::BitArray() throw() - : numValues (4), - highestBit (-1), - negative (false) + : numValues (4), + highestBit (-1), + negative (false) { - values.calloc (numValues + 1); + values.calloc (numValues + 1); } BitArray::BitArray (const int value) throw() - : numValues (4), - highestBit (31), - negative (value < 0) + : numValues (4), + highestBit (31), + negative (value < 0) { - values.calloc (numValues + 1); - values[0] = abs (value); - highestBit = getHighestBit(); + values.calloc (numValues + 1); + values[0] = abs (value); + highestBit = getHighestBit(); } BitArray::BitArray (int64 value) throw() - : numValues (4), - highestBit (63), - negative (value < 0) + : numValues (4), + highestBit (63), + negative (value < 0) { - values.calloc (numValues + 1); + values.calloc (numValues + 1); - if (value < 0) - value = -value; + if (value < 0) + value = -value; - values[0] = (unsigned int) value; - values[1] = (unsigned int) (value >> 32); - highestBit = getHighestBit(); + values[0] = (unsigned int) value; + values[1] = (unsigned int) (value >> 32); + highestBit = getHighestBit(); } BitArray::BitArray (const unsigned int value) throw() - : numValues (4), - highestBit (31), - negative (false) + : numValues (4), + highestBit (31), + negative (false) { - values.calloc (numValues + 1); - values[0] = value; - highestBit = getHighestBit(); + values.calloc (numValues + 1); + values[0] = value; + highestBit = getHighestBit(); } BitArray::BitArray (const BitArray& other) throw() - : numValues (jmax (4, (other.highestBit >> 5) + 1)), - highestBit (other.getHighestBit()), - negative (other.negative) + : numValues (jmax (4, (other.highestBit >> 5) + 1)), + highestBit (other.getHighestBit()), + negative (other.negative) { - values.malloc (numValues + 1); - memcpy (values, other.values, sizeof (unsigned int) * (numValues + 1)); + values.malloc (numValues + 1); + memcpy (values, other.values, sizeof (unsigned int) * (numValues + 1)); } BitArray::~BitArray() throw() @@ -2251,16 +2018,16 @@ BitArray::~BitArray() throw() const BitArray& BitArray::operator= (const BitArray& other) throw() { - if (this != &other) - { - highestBit = other.getHighestBit(); - numValues = jmax (4, (highestBit >> 5) + 1); - negative = other.negative; - values.malloc (numValues + 1); - memcpy (values, other.values, sizeof (unsigned int) * (numValues + 1)); - } + if (this != &other) + { + highestBit = other.getHighestBit(); + numValues = jmax (4, (highestBit >> 5) + 1); + negative = other.negative; + values.malloc (numValues + 1); + memcpy (values, other.values, sizeof (unsigned int) * (numValues + 1)); + } - return *this; + return *this; } // result == 0 = the same @@ -2268,832 +2035,832 @@ const BitArray& BitArray::operator= (const BitArray& other) throw() // result > 0 = this number is bigger int BitArray::compare (const BitArray& other) const throw() { - if (isNegative() == other.isNegative()) - { - const int absComp = compareAbsolute (other); - return isNegative() ? -absComp : absComp; - } - else - { - return isNegative() ? -1 : 1; - } + if (isNegative() == other.isNegative()) + { + const int absComp = compareAbsolute (other); + return isNegative() ? -absComp : absComp; + } + else + { + return isNegative() ? -1 : 1; + } } int BitArray::compareAbsolute (const BitArray& other) const throw() { - const int h1 = getHighestBit(); - const int h2 = other.getHighestBit(); + const int h1 = getHighestBit(); + const int h2 = other.getHighestBit(); - if (h1 > h2) - return 1; - else if (h1 < h2) - return -1; + if (h1 > h2) + return 1; + else if (h1 < h2) + return -1; - for (int i = (h1 >> 5) + 1; --i >= 0;) - if (values[i] != other.values[i]) - return (values[i] > other.values[i]) ? 1 : -1; + for (int i = (h1 >> 5) + 1; --i >= 0;) + if (values[i] != other.values[i]) + return (values[i] > other.values[i]) ? 1 : -1; - return 0; + return 0; } bool BitArray::operator== (const BitArray& other) const throw() { - return compare (other) == 0; + return compare (other) == 0; } bool BitArray::operator!= (const BitArray& other) const throw() { - return compare (other) != 0; + return compare (other) != 0; } bool BitArray::operator[] (const int bit) const throw() { - return bit >= 0 && bit <= highestBit - && ((values [bit >> 5] & (1 << (bit & 31))) != 0); + return bit >= 0 && bit <= highestBit + && ((values [bit >> 5] & (1 << (bit & 31))) != 0); } bool BitArray::isEmpty() const throw() { - return getHighestBit() < 0; + return getHighestBit() < 0; } void BitArray::clear() throw() { - if (numValues > 16) - { - numValues = 4; - values.calloc (numValues + 1); - } - else - { - zeromem (values, sizeof (unsigned int) * (numValues + 1)); - } + if (numValues > 16) + { + numValues = 4; + values.calloc (numValues + 1); + } + else + { + zeromem (values, sizeof (unsigned int) * (numValues + 1)); + } - highestBit = -1; - negative = false; + highestBit = -1; + negative = false; } void BitArray::setBit (const int bit) throw() { - if (bit >= 0) - { - if (bit > highestBit) - { - ensureSize (bit >> 5); - highestBit = bit; - } + if (bit >= 0) + { + if (bit > highestBit) + { + ensureSize (bit >> 5); + highestBit = bit; + } - values [bit >> 5] |= (1 << (bit & 31)); - } + values [bit >> 5] |= (1 << (bit & 31)); + } } void BitArray::setBit (const int bit, - const bool shouldBeSet) throw() + const bool shouldBeSet) throw() { - if (shouldBeSet) - setBit (bit); - else - clearBit (bit); + if (shouldBeSet) + setBit (bit); + else + clearBit (bit); } void BitArray::clearBit (const int bit) throw() { - if (bit >= 0 && bit <= highestBit) - values [bit >> 5] &= ~(1 << (bit & 31)); + if (bit >= 0 && bit <= highestBit) + values [bit >> 5] &= ~(1 << (bit & 31)); } void BitArray::setRange (int startBit, - int numBits, - const bool shouldBeSet) throw() + int numBits, + const bool shouldBeSet) throw() { - while (--numBits >= 0) - setBit (startBit++, shouldBeSet); + while (--numBits >= 0) + setBit (startBit++, shouldBeSet); } void BitArray::insertBit (const int bit, - const bool shouldBeSet) throw() + const bool shouldBeSet) throw() { - if (bit >= 0) - shiftBits (1, bit); + if (bit >= 0) + shiftBits (1, bit); - setBit (bit, shouldBeSet); + setBit (bit, shouldBeSet); } void BitArray::andWith (const BitArray& other) throw() { - // this operation will only work with the absolute values - jassert (isNegative() == other.isNegative()); + // this operation will only work with the absolute values + jassert (isNegative() == other.isNegative()); - int n = numValues; + int n = numValues; - while (n > other.numValues) - values[--n] = 0; + while (n > other.numValues) + values[--n] = 0; - while (--n >= 0) - values[n] &= other.values[n]; + while (--n >= 0) + values[n] &= other.values[n]; - if (other.highestBit < highestBit) - highestBit = other.highestBit; + if (other.highestBit < highestBit) + highestBit = other.highestBit; - highestBit = getHighestBit(); + highestBit = getHighestBit(); } void BitArray::orWith (const BitArray& other) throw() { - if (other.highestBit < 0) - return; + if (other.highestBit < 0) + return; - // this operation will only work with the absolute values - jassert (isNegative() == other.isNegative()); + // this operation will only work with the absolute values + jassert (isNegative() == other.isNegative()); - ensureSize (other.highestBit >> 5); + ensureSize (other.highestBit >> 5); - int n = (other.highestBit >> 5) + 1; + int n = (other.highestBit >> 5) + 1; - while (--n >= 0) - values[n] |= other.values[n]; + while (--n >= 0) + values[n] |= other.values[n]; - if (other.highestBit > highestBit) - highestBit = other.highestBit; + if (other.highestBit > highestBit) + highestBit = other.highestBit; - highestBit = getHighestBit(); + highestBit = getHighestBit(); } void BitArray::xorWith (const BitArray& other) throw() { - if (other.highestBit < 0) - return; + if (other.highestBit < 0) + return; - // this operation will only work with the absolute values - jassert (isNegative() == other.isNegative()); + // this operation will only work with the absolute values + jassert (isNegative() == other.isNegative()); - ensureSize (other.highestBit >> 5); + ensureSize (other.highestBit >> 5); - int n = (other.highestBit >> 5) + 1; + int n = (other.highestBit >> 5) + 1; - while (--n >= 0) - values[n] ^= other.values[n]; + while (--n >= 0) + values[n] ^= other.values[n]; - if (other.highestBit > highestBit) - highestBit = other.highestBit; + if (other.highestBit > highestBit) + highestBit = other.highestBit; - highestBit = getHighestBit(); + highestBit = getHighestBit(); } void BitArray::add (const BitArray& other) throw() { - if (other.isNegative()) - { - BitArray o (other); - o.negate(); - subtract (o); - return; - } + if (other.isNegative()) + { + BitArray o (other); + o.negate(); + subtract (o); + return; + } - if (isNegative()) - { - if (compareAbsolute (other) < 0) - { - BitArray temp (*this); - temp.negate(); - *this = other; - subtract (temp); - } - else - { - negate(); - subtract (other); - negate(); - } + if (isNegative()) + { + if (compareAbsolute (other) < 0) + { + BitArray temp (*this); + temp.negate(); + *this = other; + subtract (temp); + } + else + { + negate(); + subtract (other); + negate(); + } - return; - } + return; + } - if (other.highestBit > highestBit) - highestBit = other.highestBit; + if (other.highestBit > highestBit) + highestBit = other.highestBit; - ++highestBit; + ++highestBit; - const int numInts = (highestBit >> 5) + 1; - ensureSize (numInts); + const int numInts = (highestBit >> 5) + 1; + ensureSize (numInts); - int64 remainder = 0; + int64 remainder = 0; - for (int i = 0; i <= numInts; ++i) - { - if (i < numValues) - remainder += values[i]; + for (int i = 0; i <= numInts; ++i) + { + if (i < numValues) + remainder += values[i]; - if (i < other.numValues) - remainder += other.values[i]; + if (i < other.numValues) + remainder += other.values[i]; - values[i] = (unsigned int) remainder; - remainder >>= 32; - } + values[i] = (unsigned int) remainder; + remainder >>= 32; + } - jassert (remainder == 0); - highestBit = getHighestBit(); + jassert (remainder == 0); + highestBit = getHighestBit(); } void BitArray::subtract (const BitArray& other) throw() { - if (other.isNegative()) - { - BitArray o (other); - o.negate(); - add (o); - return; - } + if (other.isNegative()) + { + BitArray o (other); + o.negate(); + add (o); + return; + } - if (! isNegative()) - { - if (compareAbsolute (other) < 0) - { - BitArray temp (*this); - *this = other; - subtract (temp); - negate(); - return; - } - } - else - { - negate(); - add (other); - negate(); - return; - } + if (! isNegative()) + { + if (compareAbsolute (other) < 0) + { + BitArray temp (*this); + *this = other; + subtract (temp); + negate(); + return; + } + } + else + { + negate(); + add (other); + negate(); + return; + } - const int numInts = (highestBit >> 5) + 1; - const int maxOtherInts = (other.highestBit >> 5) + 1; - int64 amountToSubtract = 0; + const int numInts = (highestBit >> 5) + 1; + const int maxOtherInts = (other.highestBit >> 5) + 1; + int64 amountToSubtract = 0; - for (int i = 0; i <= numInts; ++i) - { - if (i <= maxOtherInts) - amountToSubtract += (int64)other.values[i]; + for (int i = 0; i <= numInts; ++i) + { + if (i <= maxOtherInts) + amountToSubtract += (int64)other.values[i]; - if (values[i] >= amountToSubtract) - { - values[i] = (unsigned int) (values[i] - amountToSubtract); - amountToSubtract = 0; - } - else - { - const int64 n = ((int64) values[i] + (((int64) 1) << 32)) - amountToSubtract; - values[i] = (unsigned int) n; - amountToSubtract = 1; - } - } + if (values[i] >= amountToSubtract) + { + values[i] = (unsigned int) (values[i] - amountToSubtract); + amountToSubtract = 0; + } + else + { + const int64 n = ((int64) values[i] + (((int64) 1) << 32)) - amountToSubtract; + values[i] = (unsigned int) n; + amountToSubtract = 1; + } + } } void BitArray::multiplyBy (const BitArray& other) throw() { - BitArray total; - highestBit = getHighestBit(); - const bool wasNegative = isNegative(); - setNegative (false); + BitArray total; + highestBit = getHighestBit(); + const bool wasNegative = isNegative(); + setNegative (false); - for (int i = 0; i <= highestBit; ++i) - { - if (operator[](i)) - { - BitArray n (other); - n.setNegative (false); - n.shiftBits (i); - total.add (n); - } - } + for (int i = 0; i <= highestBit; ++i) + { + if (operator[](i)) + { + BitArray n (other); + n.setNegative (false); + n.shiftBits (i); + total.add (n); + } + } - *this = total; - negative = wasNegative ^ other.isNegative(); + *this = total; + negative = wasNegative ^ other.isNegative(); } void BitArray::divideBy (const BitArray& divisor, BitArray& remainder) throw() { - jassert (this != &remainder); // (can't handle passing itself in to get the remainder) + jassert (this != &remainder); // (can't handle passing itself in to get the remainder) - const int divHB = divisor.getHighestBit(); - const int ourHB = getHighestBit(); + const int divHB = divisor.getHighestBit(); + const int ourHB = getHighestBit(); - if (divHB < 0 || ourHB < 0) - { - // division by zero - remainder.clear(); - clear(); - } - else - { - remainder = *this; - remainder.setNegative (false); - const bool wasNegative = isNegative(); - clear(); + if (divHB < 0 || ourHB < 0) + { + // division by zero + remainder.clear(); + clear(); + } + else + { + remainder = *this; + remainder.setNegative (false); + const bool wasNegative = isNegative(); + clear(); - BitArray temp (divisor); - temp.setNegative (false); + BitArray temp (divisor); + temp.setNegative (false); - int leftShift = ourHB - divHB; - temp.shiftBits (leftShift); + int leftShift = ourHB - divHB; + temp.shiftBits (leftShift); - while (leftShift >= 0) - { - if (remainder.compareAbsolute (temp) >= 0) - { - remainder.subtract (temp); - setBit (leftShift); - } + while (leftShift >= 0) + { + if (remainder.compareAbsolute (temp) >= 0) + { + remainder.subtract (temp); + setBit (leftShift); + } - if (--leftShift >= 0) - temp.shiftBits (-1); - } + if (--leftShift >= 0) + temp.shiftBits (-1); + } - negative = wasNegative ^ divisor.isNegative(); - remainder.setNegative (wasNegative); - } + negative = wasNegative ^ divisor.isNegative(); + remainder.setNegative (wasNegative); + } } void BitArray::modulo (const BitArray& divisor) throw() { - BitArray remainder; - divideBy (divisor, remainder); - *this = remainder; + BitArray remainder; + divideBy (divisor, remainder); + *this = remainder; } static const BitArray simpleGCD (BitArray* m, BitArray* n) throw() { - while (! m->isEmpty()) - { - if (n->compareAbsolute (*m) > 0) - swapVariables (m, n); + while (! m->isEmpty()) + { + if (n->compareAbsolute (*m) > 0) + swapVariables (m, n); - m->subtract (*n); - } + m->subtract (*n); + } - return *n; + return *n; } const BitArray BitArray::findGreatestCommonDivisor (BitArray n) const throw() { - BitArray m (*this); + BitArray m (*this); - while (! n.isEmpty()) - { - if (abs (m.getHighestBit() - n.getHighestBit()) <= 16) - return simpleGCD (&m, &n); + while (! n.isEmpty()) + { + if (abs (m.getHighestBit() - n.getHighestBit()) <= 16) + return simpleGCD (&m, &n); - BitArray temp1 (m), temp2; - temp1.divideBy (n, temp2); + BitArray temp1 (m), temp2; + temp1.divideBy (n, temp2); - m = n; - n = temp2; - } + m = n; + n = temp2; + } - return m; + return m; } void BitArray::exponentModulo (const BitArray& exponent, - const BitArray& modulus) throw() + const BitArray& modulus) throw() { - BitArray exp (exponent); - exp.modulo (modulus); + BitArray exp (exponent); + exp.modulo (modulus); - BitArray value (*this); - value.modulo (modulus); + BitArray value (*this); + value.modulo (modulus); - clear(); - setBit (0); + clear(); + setBit (0); - while (! exp.isEmpty()) - { - if (exp [0]) - { - multiplyBy (value); - this->modulo (modulus); - } + while (! exp.isEmpty()) + { + if (exp [0]) + { + multiplyBy (value); + this->modulo (modulus); + } - value.multiplyBy (value); - value.modulo (modulus); + value.multiplyBy (value); + value.modulo (modulus); - exp.shiftBits (-1); - } + exp.shiftBits (-1); + } } void BitArray::inverseModulo (const BitArray& modulus) throw() { - const BitArray one (1); + const BitArray one (1); - if (modulus == one || modulus.isNegative()) - { - clear(); - return; - } + if (modulus == one || modulus.isNegative()) + { + clear(); + return; + } - if (isNegative() || compareAbsolute (modulus) >= 0) - this->modulo (modulus); + if (isNegative() || compareAbsolute (modulus) >= 0) + this->modulo (modulus); - if (*this == one) - return; + if (*this == one) + return; - if (! (*this)[0]) - { - // not invertible - clear(); - return; - } + if (! (*this)[0]) + { + // not invertible + clear(); + return; + } - BitArray a1 (modulus); - BitArray a2 (*this); - BitArray b1 (modulus); - BitArray b2 (1); + BitArray a1 (modulus); + BitArray a2 (*this); + BitArray b1 (modulus); + BitArray b2 (1); - while (a2 != one) - { - BitArray temp1, temp2, multiplier (a1); - multiplier.divideBy (a2, temp1); + while (a2 != one) + { + BitArray temp1, temp2, multiplier (a1); + multiplier.divideBy (a2, temp1); - temp1 = a2; - temp1.multiplyBy (multiplier); - temp2 = a1; - temp2.subtract (temp1); - a1 = a2; - a2 = temp2; + temp1 = a2; + temp1.multiplyBy (multiplier); + temp2 = a1; + temp2.subtract (temp1); + a1 = a2; + a2 = temp2; - temp1 = b2; - temp1.multiplyBy (multiplier); - temp2 = b1; - temp2.subtract (temp1); - b1 = b2; - b2 = temp2; - } + temp1 = b2; + temp1.multiplyBy (multiplier); + temp2 = b1; + temp2.subtract (temp1); + b1 = b2; + b2 = temp2; + } - while (b2.isNegative()) - b2.add (modulus); + while (b2.isNegative()) + b2.add (modulus); - b2.modulo (modulus); - *this = b2; + b2.modulo (modulus); + *this = b2; } void BitArray::shiftBits (int bits, const int startBit) throw() { - if (highestBit < 0) - return; + if (highestBit < 0) + return; - if (startBit > 0) - { - if (bits < 0) - { - // right shift - for (int i = startBit; i <= highestBit; ++i) - setBit (i, operator[] (i - bits)); + if (startBit > 0) + { + if (bits < 0) + { + // right shift + for (int i = startBit; i <= highestBit; ++i) + setBit (i, operator[] (i - bits)); - highestBit = getHighestBit(); - } - else if (bits > 0) - { - // left shift - for (int i = highestBit + 1; --i >= startBit;) - setBit (i + bits, operator[] (i)); + highestBit = getHighestBit(); + } + else if (bits > 0) + { + // left shift + for (int i = highestBit + 1; --i >= startBit;) + setBit (i + bits, operator[] (i)); - while (--bits >= 0) - clearBit (bits + startBit); - } - } - else - { - if (bits < 0) - { - // right shift - bits = -bits; + while (--bits >= 0) + clearBit (bits + startBit); + } + } + else + { + if (bits < 0) + { + // right shift + bits = -bits; - if (bits > highestBit) - { - clear(); - } - else - { - const int wordsToMove = bits >> 5; - int top = 1 + (highestBit >> 5) - wordsToMove; - highestBit -= bits; + if (bits > highestBit) + { + clear(); + } + else + { + const int wordsToMove = bits >> 5; + int top = 1 + (highestBit >> 5) - wordsToMove; + highestBit -= bits; - if (wordsToMove > 0) - { - int i; - for (i = 0; i < top; ++i) - values [i] = values [i + wordsToMove]; + if (wordsToMove > 0) + { + int i; + for (i = 0; i < top; ++i) + values [i] = values [i + wordsToMove]; - for (i = 0; i < wordsToMove; ++i) - values [top + i] = 0; + for (i = 0; i < wordsToMove; ++i) + values [top + i] = 0; - bits &= 31; - } + bits &= 31; + } - if (bits != 0) - { - const int invBits = 32 - bits; + if (bits != 0) + { + const int invBits = 32 - bits; - --top; - for (int i = 0; i < top; ++i) - values[i] = (values[i] >> bits) | (values [i + 1] << invBits); + --top; + for (int i = 0; i < top; ++i) + values[i] = (values[i] >> bits) | (values [i + 1] << invBits); - values[top] = (values[top] >> bits); - } + values[top] = (values[top] >> bits); + } - highestBit = getHighestBit(); - } - } - else if (bits > 0) - { - // left shift - ensureSize (((highestBit + bits) >> 5) + 1); + highestBit = getHighestBit(); + } + } + else if (bits > 0) + { + // left shift + ensureSize (((highestBit + bits) >> 5) + 1); - const int wordsToMove = bits >> 5; - int top = 1 + (highestBit >> 5); - highestBit += bits; + const int wordsToMove = bits >> 5; + int top = 1 + (highestBit >> 5); + highestBit += bits; - if (wordsToMove > 0) - { - int i; - for (i = top; --i >= 0;) - values [i + wordsToMove] = values [i]; + if (wordsToMove > 0) + { + int i; + for (i = top; --i >= 0;) + values [i + wordsToMove] = values [i]; - for (i = 0; i < wordsToMove; ++i) - values [i] = 0; + for (i = 0; i < wordsToMove; ++i) + values [i] = 0; - bits &= 31; - } + bits &= 31; + } - if (bits != 0) - { - const int invBits = 32 - bits; + if (bits != 0) + { + const int invBits = 32 - bits; - for (int i = top + 1 + wordsToMove; --i > wordsToMove;) - values[i] = (values[i] << bits) | (values [i - 1] >> invBits); + for (int i = top + 1 + wordsToMove; --i > wordsToMove;) + values[i] = (values[i] << bits) | (values [i - 1] >> invBits); - values [wordsToMove] = values [wordsToMove] << bits; - } + values [wordsToMove] = values [wordsToMove] << bits; + } - highestBit = getHighestBit(); - } - } + highestBit = getHighestBit(); + } + } } const BitArray BitArray::getBitRange (int startBit, int numBits) const throw() { - BitArray r; - numBits = jmin (numBits, getHighestBit() + 1 - startBit); - r.ensureSize (numBits >> 5); - r.highestBit = numBits; + BitArray r; + numBits = jmin (numBits, getHighestBit() + 1 - startBit); + r.ensureSize (numBits >> 5); + r.highestBit = numBits; - int i = 0; - while (numBits > 0) - { - r.values[i++] = getBitRangeAsInt (startBit, jmin (32, numBits)); - numBits -= 32; - startBit += 32; - } + int i = 0; + while (numBits > 0) + { + r.values[i++] = getBitRangeAsInt (startBit, jmin (32, numBits)); + numBits -= 32; + startBit += 32; + } - r.highestBit = r.getHighestBit(); + r.highestBit = r.getHighestBit(); - return r; + return r; } int BitArray::getBitRangeAsInt (const int startBit, int numBits) const throw() { - if (numBits > 32) - { - jassertfalse // use getBitRange() if you need more than 32 bits.. - numBits = 32; - } + if (numBits > 32) + { + jassertfalse // use getBitRange() if you need more than 32 bits.. + numBits = 32; + } - numBits = jmin (numBits, highestBit + 1 - startBit); + numBits = jmin (numBits, highestBit + 1 - startBit); - if (numBits <= 0) - return 0; + if (numBits <= 0) + return 0; - const int pos = startBit >> 5; - const int offset = startBit & 31; - const int endSpace = 32 - numBits; + const int pos = startBit >> 5; + const int offset = startBit & 31; + const int endSpace = 32 - numBits; - uint32 n = ((uint32) values [pos]) >> offset; + uint32 n = ((uint32) values [pos]) >> offset; - if (offset > endSpace) - n |= ((uint32) values [pos + 1]) << (32 - offset); + if (offset > endSpace) + n |= ((uint32) values [pos + 1]) << (32 - offset); - return (int) (n & (((uint32) 0xffffffff) >> endSpace)); + return (int) (n & (((uint32) 0xffffffff) >> endSpace)); } void BitArray::setBitRangeAsInt (const int startBit, int numBits, unsigned int valueToSet) throw() { - if (numBits > 32) - { - jassertfalse - numBits = 32; - } + if (numBits > 32) + { + jassertfalse + numBits = 32; + } - for (int i = 0; i < numBits; ++i) - { - setBit (startBit + i, (valueToSet & 1) != 0); - valueToSet >>= 1; - } + for (int i = 0; i < numBits; ++i) + { + setBit (startBit + i, (valueToSet & 1) != 0); + valueToSet >>= 1; + } } bool BitArray::isNegative() const throw() { - return negative && ! isEmpty(); + return negative && ! isEmpty(); } void BitArray::setNegative (const bool neg) throw() { - negative = neg; + negative = neg; } void BitArray::negate() throw() { - negative = (! negative) && ! isEmpty(); + negative = (! negative) && ! isEmpty(); } int BitArray::countNumberOfSetBits() const throw() { - int total = 0; + int total = 0; - for (int i = (highestBit >> 5) + 1; --i >= 0;) - { - unsigned int n = values[i]; + for (int i = (highestBit >> 5) + 1; --i >= 0;) + { + unsigned int n = values[i]; - if (n == 0xffffffff) - { - total += 32; - } - else - { - while (n != 0) - { - total += (n & 1); - n >>= 1; - } - } - } + if (n == 0xffffffff) + { + total += 32; + } + else + { + while (n != 0) + { + total += (n & 1); + n >>= 1; + } + } + } - return total; + return total; } int BitArray::getHighestBit() const throw() { - for (int i = highestBit + 1; --i >= 0;) - if ((values [i >> 5] & (1 << (i & 31))) != 0) - return i; + for (int i = highestBit + 1; --i >= 0;) + if ((values [i >> 5] & (1 << (i & 31))) != 0) + return i; - return -1; + return -1; } int BitArray::findNextSetBit (int i) const throw() { - for (; i <= highestBit; ++i) - if ((values [i >> 5] & (1 << (i & 31))) != 0) - return i; + for (; i <= highestBit; ++i) + if ((values [i >> 5] & (1 << (i & 31))) != 0) + return i; - return -1; + return -1; } int BitArray::findNextClearBit (int i) const throw() { - for (; i <= highestBit; ++i) - if ((values [i >> 5] & (1 << (i & 31))) == 0) - break; + for (; i <= highestBit; ++i) + if ((values [i >> 5] & (1 << (i & 31))) == 0) + break; - return i; + return i; } void BitArray::ensureSize (const int numVals) throw() { - if (numVals + 2 >= numValues) - { - int oldSize = numValues; - numValues = ((numVals + 2) * 3) / 2; - values.realloc (numValues + 1); + if (numVals + 2 >= numValues) + { + int oldSize = numValues; + numValues = ((numVals + 2) * 3) / 2; + values.realloc (numValues + 1); - while (oldSize < numValues) - values [oldSize++] = 0; - } + while (oldSize < numValues) + values [oldSize++] = 0; + } } const String BitArray::toString (const int base, const int minimumNumCharacters) const throw() { - String s; - BitArray v (*this); + String s; + BitArray v (*this); - if (base == 2 || base == 8 || base == 16) - { - const int bits = (base == 2) ? 1 : (base == 8 ? 3 : 4); - static const tchar* const hexDigits = T("0123456789abcdef"); + if (base == 2 || base == 8 || base == 16) + { + const int bits = (base == 2) ? 1 : (base == 8 ? 3 : 4); + static const tchar* const hexDigits = T("0123456789abcdef"); - for (;;) - { - const int remainder = v.getBitRangeAsInt (0, bits); + for (;;) + { + const int remainder = v.getBitRangeAsInt (0, bits); - v.shiftBits (-bits); + v.shiftBits (-bits); - if (remainder == 0 && v.isEmpty()) - break; + if (remainder == 0 && v.isEmpty()) + break; - s = String::charToString (hexDigits [remainder]) + s; - } - } - else if (base == 10) - { - const BitArray ten (10); - BitArray remainder; + s = String::charToString (hexDigits [remainder]) + s; + } + } + else if (base == 10) + { + const BitArray ten (10); + BitArray remainder; - for (;;) - { - v.divideBy (ten, remainder); + for (;;) + { + v.divideBy (ten, remainder); - if (remainder.isEmpty() && v.isEmpty()) - break; + if (remainder.isEmpty() && v.isEmpty()) + break; - s = String (remainder.getBitRangeAsInt (0, 8)) + s; - } - } - else - { - jassertfalse // can't do the specified base - return String::empty; - } + s = String (remainder.getBitRangeAsInt (0, 8)) + s; + } + } + else + { + jassertfalse // can't do the specified base + return String::empty; + } - const int length = s.length(); + const int length = s.length(); - if (length < minimumNumCharacters) - s = String::repeatedString (T("0"), minimumNumCharacters - length) + s; + if (length < minimumNumCharacters) + s = String::repeatedString (T("0"), minimumNumCharacters - length) + s; - return isNegative() ? T("-") + s : s; + return isNegative() ? T("-") + s : s; } void BitArray::parseString (const String& text, - const int base) throw() + const int base) throw() { - clear(); - const tchar* t = (const tchar*) text; + clear(); + const tchar* t = (const tchar*) text; - if (base == 2 || base == 8 || base == 16) - { - const int bits = (base == 2) ? 1 : (base == 8 ? 3 : 4); + if (base == 2 || base == 8 || base == 16) + { + const int bits = (base == 2) ? 1 : (base == 8 ? 3 : 4); - for (;;) - { - const tchar c = *t++; - const int digit = CharacterFunctions::getHexDigitValue (c); + for (;;) + { + const tchar c = *t++; + const int digit = CharacterFunctions::getHexDigitValue (c); - if (((unsigned int) digit) < (unsigned int) base) - { - shiftBits (bits); - add (digit); - } - else if (c == 0) - { - break; - } - } - } - else if (base == 10) - { - const BitArray ten ((unsigned int) 10); + if (((unsigned int) digit) < (unsigned int) base) + { + shiftBits (bits); + add (digit); + } + else if (c == 0) + { + break; + } + } + } + else if (base == 10) + { + const BitArray ten ((unsigned int) 10); - for (;;) - { - const tchar c = *t++; + for (;;) + { + const tchar c = *t++; - if (c >= T('0') && c <= T('9')) - { - multiplyBy (ten); - add ((int) (c - T('0'))); - } - else if (c == 0) - { - break; - } - } - } + if (c >= T('0') && c <= T('9')) + { + multiplyBy (ten); + add ((int) (c - T('0'))); + } + else if (c == 0) + { + break; + } + } + } - setNegative (text.trimStart().startsWithChar (T('-'))); + setNegative (text.trimStart().startsWithChar (T('-'))); } const MemoryBlock BitArray::toMemoryBlock() const throw() { - const int numBytes = (getHighestBit() + 8) >> 3; - MemoryBlock mb (numBytes); + const int numBytes = (getHighestBit() + 8) >> 3; + MemoryBlock mb ((size_t) numBytes); - for (int i = 0; i < numBytes; ++i) - mb[i] = (uint8) getBitRangeAsInt (i << 3, 8); + for (int i = 0; i < numBytes; ++i) + mb[i] = (uint8) getBitRangeAsInt (i << 3, 8); - return mb; + return mb; } void BitArray::loadFromMemoryBlock (const MemoryBlock& data) throw() { - clear(); + clear(); - for (int i = data.getSize(); --i >= 0;) - this->setBitRangeAsInt (i << 3, 8, data [i]); + for (size_t i = data.getSize(); --i >= 0;) + this->setBitRangeAsInt ((int) (i << 3), 8, data [i]); } END_JUCE_NAMESPACE @@ -3104,347 +2871,353 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MemoryBlock::MemoryBlock() throw() - : size (0) + : size (0) { } -MemoryBlock::MemoryBlock (const int initialSize, - const bool initialiseToZero) throw() +MemoryBlock::MemoryBlock (const size_t initialSize, + const bool initialiseToZero) throw() { - if (initialSize > 0) - { - size = initialSize; - data.allocate (initialSize, initialiseToZero); - } - else - { - size = 0; - } + if (initialSize > 0) + { + size = initialSize; + data.allocate (initialSize, initialiseToZero); + } + else + { + size = 0; + } } MemoryBlock::MemoryBlock (const MemoryBlock& other) throw() - : size (other.size) + : size (other.size) { - if (size > 0) - { - jassert (other.data != 0); - data.malloc (size); - memcpy (data, other.data, size); - } + if (size > 0) + { + jassert (other.data != 0); + data.malloc (size); + memcpy (data, other.data, size); + } } MemoryBlock::MemoryBlock (const void* const dataToInitialiseFrom, - const int sizeInBytes) throw() - : size (jmax (0, sizeInBytes)) + const size_t sizeInBytes) throw() + : size (jmax ((size_t) 0, sizeInBytes)) { - jassert (sizeInBytes >= 0); + jassert (sizeInBytes >= 0); - if (size > 0) - { - jassert (dataToInitialiseFrom != 0); // non-zero size, but a zero pointer passed-in? + if (size > 0) + { + jassert (dataToInitialiseFrom != 0); // non-zero size, but a zero pointer passed-in? - data.malloc (size); + data.malloc (size); - if (dataToInitialiseFrom != 0) - memcpy (data, dataToInitialiseFrom, size); - } + if (dataToInitialiseFrom != 0) + memcpy (data, dataToInitialiseFrom, size); + } } MemoryBlock::~MemoryBlock() throw() { - jassert (size >= 0); // should never happen - jassert (size == 0 || data != 0); // non-zero size but no data allocated? + jassert (size >= 0); // should never happen + jassert (size == 0 || data != 0); // non-zero size but no data allocated? } const MemoryBlock& MemoryBlock::operator= (const MemoryBlock& other) throw() { - if (this != &other) - { - setSize (other.size, false); - memcpy (data, other.data, size); - } + if (this != &other) + { + setSize (other.size, false); + memcpy (data, other.data, size); + } - return *this; + return *this; } bool MemoryBlock::operator== (const MemoryBlock& other) const throw() { - return (size == other.size) - && (memcmp (data, other.data, size) == 0); + return (size == other.size) + && (memcmp (data, other.data, size) == 0); } bool MemoryBlock::operator!= (const MemoryBlock& other) const throw() { - return ! operator== (other); + return ! operator== (other); } // this will resize the block to this size -void MemoryBlock::setSize (const int newSize, - const bool initialiseToZero) throw() +void MemoryBlock::setSize (const size_t newSize, + const bool initialiseToZero) throw() { - if (size != newSize) - { - if (newSize <= 0) - { - data.free(); - size = 0; - } - else - { - if (data != 0) - { - data.realloc (newSize); + if (size != newSize) + { + if (newSize <= 0) + { + data.free(); + size = 0; + } + else + { + if (data != 0) + { + data.realloc (newSize); - if (initialiseToZero && (newSize > size)) - zeromem (data + size, newSize - size); - } - else - { - data.allocate (newSize, initialiseToZero); - } + if (initialiseToZero && (newSize > size)) + zeromem (data + size, newSize - size); + } + else + { + data.allocate (newSize, initialiseToZero); + } - size = newSize; - } - } + size = newSize; + } + } } -void MemoryBlock::ensureSize (const int minimumSize, - const bool initialiseToZero) throw() +void MemoryBlock::ensureSize (const size_t minimumSize, + const bool initialiseToZero) throw() { - if (size < minimumSize) - setSize (minimumSize, initialiseToZero); + if (size < minimumSize) + setSize (minimumSize, initialiseToZero); +} + +void MemoryBlock::swapWith (MemoryBlock& other) throw() +{ + swapVariables (size, other.size); + data.swapWith (other.data); } void MemoryBlock::fillWith (const uint8 value) throw() { - memset (data, (int) value, size); + memset (data, (int) value, size); } void MemoryBlock::append (const void* const srcData, - const int numBytes) throw() + const size_t numBytes) throw() { - if (numBytes > 0) - { - const int oldSize = size; - setSize (size + numBytes); - memcpy (data + oldSize, srcData, numBytes); - } + if (numBytes > 0) + { + const size_t oldSize = size; + setSize (size + numBytes); + memcpy (data + oldSize, srcData, numBytes); + } } -void MemoryBlock::copyFrom (const void* const src, int offset, int num) throw() +void MemoryBlock::copyFrom (const void* const src, int offset, size_t num) throw() { - const char* d = (const char*) src; + const char* d = (const char*) src; - if (offset < 0) - { - d -= offset; - num -= offset; - offset = 0; - } + if (offset < 0) + { + d -= offset; + num -= offset; + offset = 0; + } - if (offset + num > size) - num = size - offset; + if (offset + num > size) + num = size - offset; - if (num > 0) - memcpy (data + offset, d, num); + if (num > 0) + memcpy (data + offset, d, num); } -void MemoryBlock::copyTo (void* const dst, int offset, int num) const throw() +void MemoryBlock::copyTo (void* const dst, int offset, size_t num) const throw() { - char* d = (char*) dst; + char* d = (char*) dst; - if (offset < 0) - { - zeromem (d, -offset); - d -= offset; + if (offset < 0) + { + zeromem (d, -offset); + d -= offset; - num += offset; - offset = 0; - } + num += offset; + offset = 0; + } - if (offset + num > size) - { - const int newNum = size - offset; - zeromem (d + newNum, num - newNum); - num = newNum; - } + if (offset + num > size) + { + const size_t newNum = size - offset; + zeromem (d + newNum, num - newNum); + num = newNum; + } - if (num > 0) - memcpy (d, data + offset, num); + if (num > 0) + memcpy (d, data + offset, num); } -void MemoryBlock::removeSection (int startByte, int numBytesToRemove) throw() +void MemoryBlock::removeSection (size_t startByte, size_t numBytesToRemove) throw() { - if (startByte < 0) - { - numBytesToRemove += startByte; - startByte = 0; - } + if (startByte < 0) + { + numBytesToRemove += startByte; + startByte = 0; + } - if (startByte + numBytesToRemove >= size) - { - setSize (startByte); - } - else if (numBytesToRemove > 0) - { - memmove (data + startByte, - data + startByte + numBytesToRemove, - size - (startByte + numBytesToRemove)); + if (startByte + numBytesToRemove >= size) + { + setSize (startByte); + } + else if (numBytesToRemove > 0) + { + memmove (data + startByte, + data + startByte + numBytesToRemove, + size - (startByte + numBytesToRemove)); - setSize (size - numBytesToRemove); - } + setSize (size - numBytesToRemove); + } } const String MemoryBlock::toString() const throw() { - return String ((const char*) data, size); + return String ((const char*) data, size); } -int MemoryBlock::getBitRange (const int bitRangeStart, int numBits) const throw() +int MemoryBlock::getBitRange (const size_t bitRangeStart, size_t numBits) const throw() { - int res = 0; + int res = 0; - int byte = bitRangeStart >> 3; - int offsetInByte = bitRangeStart & 7; - int bitsSoFar = 0; + size_t byte = bitRangeStart >> 3; + int offsetInByte = bitRangeStart & 7; + size_t bitsSoFar = 0; - while (numBits > 0 && byte < size) - { - const int bitsThisTime = jmin (numBits, 8 - offsetInByte); - const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte; + while (numBits > 0 && (size_t) byte < size) + { + const int bitsThisTime = jmin ((int) numBits, 8 - offsetInByte); + const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte; - res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar); + res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar); - bitsSoFar += bitsThisTime; - numBits -= bitsThisTime; - ++byte; - offsetInByte = 0; - } + bitsSoFar += bitsThisTime; + numBits -= bitsThisTime; + ++byte; + offsetInByte = 0; + } - return res; + return res; } -void MemoryBlock::setBitRange (const int bitRangeStart, int numBits, int bitsToSet) throw() +void MemoryBlock::setBitRange (const size_t bitRangeStart, size_t numBits, int bitsToSet) throw() { - int byte = bitRangeStart >> 3; - int offsetInByte = bitRangeStart & 7; - unsigned int mask = ~((((unsigned int)0xffffffff) << (32 - numBits)) >> (32 - numBits)); + size_t byte = bitRangeStart >> 3; + int offsetInByte = bitRangeStart & 7; + unsigned int mask = ~((((unsigned int)0xffffffff) << (32 - numBits)) >> (32 - numBits)); - while (numBits > 0 && byte < size) - { - const int bitsThisTime = jmin (numBits, 8 - offsetInByte); + while (numBits > 0 && (size_t) byte < size) + { + const int bitsThisTime = jmin ((int) numBits, 8 - offsetInByte); - const unsigned int tempMask = (mask << offsetInByte) | ~((((unsigned int)0xffffffff) >> offsetInByte) << offsetInByte); - const unsigned int tempBits = bitsToSet << offsetInByte; + const unsigned int tempMask = (mask << offsetInByte) | ~((((unsigned int)0xffffffff) >> offsetInByte) << offsetInByte); + const unsigned int tempBits = bitsToSet << offsetInByte; - data[byte] = (char)((data[byte] & tempMask) | tempBits); + data[byte] = (char)((data[byte] & tempMask) | tempBits); - ++byte; - numBits -= bitsThisTime; - bitsToSet >>= bitsThisTime; - mask >>= bitsThisTime; - offsetInByte = 0; - } + ++byte; + numBits -= bitsThisTime; + bitsToSet >>= bitsThisTime; + mask >>= bitsThisTime; + offsetInByte = 0; + } } void MemoryBlock::loadFromHexString (const String& hex) throw() { - ensureSize (hex.length() >> 1); - char* dest = data; - int i = 0; + ensureSize (hex.length() >> 1); + char* dest = data; + int i = 0; - for (;;) - { - int byte = 0; + for (;;) + { + int byte = 0; - for (int loop = 2; --loop >= 0;) - { - byte <<= 4; + for (int loop = 2; --loop >= 0;) + { + byte <<= 4; - for (;;) - { - const tchar c = hex [i++]; + for (;;) + { + const tchar c = hex [i++]; - if (c >= T('0') && c <= T('9')) - { - byte |= c - T('0'); - break; - } - else if (c >= T('a') && c <= T('z')) - { - byte |= c - (T('a') - 10); - break; - } - else if (c >= T('A') && c <= T('Z')) - { - byte |= c - (T('A') - 10); - break; - } - else if (c == 0) - { - setSize ((int) (dest - data)); - return; - } - } - } + if (c >= T('0') && c <= T('9')) + { + byte |= c - T('0'); + break; + } + else if (c >= T('a') && c <= T('z')) + { + byte |= c - (T('a') - 10); + break; + } + else if (c >= T('A') && c <= T('Z')) + { + byte |= c - (T('A') - 10); + break; + } + else if (c == 0) + { + setSize ((int) (dest - data)); + return; + } + } + } - *dest++ = (char) byte; - } + *dest++ = (char) byte; + } } static const char* const encodingTable - = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+"; + = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+"; const String MemoryBlock::toBase64Encoding() const throw() { - const int numChars = ((size << 3) + 5) / 6; + const size_t numChars = ((size << 3) + 5) / 6; - String destString (size); // store the length, followed by a '.', and then the data. - const int initialLen = destString.length(); - destString.preallocateStorage (initialLen + 2 + numChars); + String destString ((unsigned int) size); // store the length, followed by a '.', and then the data. + const int initialLen = destString.length(); + destString.preallocateStorage (initialLen + 2 + numChars); - tchar* d = const_cast (((const tchar*) destString) + initialLen); - *d++ = T('.'); + tchar* d = const_cast (((const tchar*) destString) + initialLen); + *d++ = T('.'); - for (int i = 0; i < numChars; ++i) - *d++ = encodingTable [getBitRange (i * 6, 6)]; + for (size_t i = 0; i < numChars; ++i) + *d++ = encodingTable [getBitRange (i * 6, 6)]; - *d++ = 0; + *d++ = 0; - return destString; + return destString; } bool MemoryBlock::fromBase64Encoding (const String& s) throw() { - const int startPos = s.indexOfChar (T('.')) + 1; + const int startPos = s.indexOfChar (T('.')) + 1; - if (startPos <= 0) - return false; + if (startPos <= 0) + return false; - const int numBytesNeeded = s.substring (0, startPos - 1).getIntValue(); + const int numBytesNeeded = s.substring (0, startPos - 1).getIntValue(); - setSize (numBytesNeeded, true); + setSize (numBytesNeeded, true); - const int numChars = s.length() - startPos; - const tchar* const srcChars = ((const tchar*) s) + startPos; - int pos = 0; + const int numChars = s.length() - startPos; + const tchar* const srcChars = ((const tchar*) s) + startPos; + int pos = 0; - for (int i = 0; i < numChars; ++i) - { - const char c = (char) srcChars[i]; + for (int i = 0; i < numChars; ++i) + { + const char c = (char) srcChars[i]; - for (int j = 0; j < 64; ++j) - { - if (encodingTable[j] == c) - { - setBitRange (pos, 6, j); - pos += 6; - break; - } - } - } + for (int j = 0; j < 64; ++j) + { + if (encodingTable[j] == c) + { + setBitRange (pos, 6, j); + pos += 6; + break; + } + } + } - return true; + return true; } END_JUCE_NAMESPACE @@ -3455,27 +3228,27 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE PropertySet::PropertySet (const bool ignoreCaseOfKeyNames) throw() - : properties (ignoreCaseOfKeyNames), - fallbackProperties (0), - ignoreCaseOfKeys (ignoreCaseOfKeyNames) + : properties (ignoreCaseOfKeyNames), + fallbackProperties (0), + ignoreCaseOfKeys (ignoreCaseOfKeyNames) { } PropertySet::PropertySet (const PropertySet& other) throw() - : properties (other.properties), - fallbackProperties (other.fallbackProperties), - ignoreCaseOfKeys (other.ignoreCaseOfKeys) + : properties (other.properties), + fallbackProperties (other.fallbackProperties), + ignoreCaseOfKeys (other.ignoreCaseOfKeys) { } const PropertySet& PropertySet::operator= (const PropertySet& other) throw() { - properties = other.properties; - fallbackProperties = other.fallbackProperties; - ignoreCaseOfKeys = other.ignoreCaseOfKeys; + properties = other.properties; + fallbackProperties = other.fallbackProperties; + ignoreCaseOfKeys = other.ignoreCaseOfKeys; - propertyChanged(); - return *this; + propertyChanged(); + return *this; } PropertySet::~PropertySet() @@ -3484,182 +3257,182 @@ PropertySet::~PropertySet() void PropertySet::clear() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (properties.size() > 0) - { - properties.clear(); - propertyChanged(); - } + if (properties.size() > 0) + { + properties.clear(); + propertyChanged(); + } } const String PropertySet::getValue (const String& keyName, - const String& defaultValue) const throw() + const String& defaultValue) const throw() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); + const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); - if (index >= 0) - return properties.getAllValues() [index]; + if (index >= 0) + return properties.getAllValues() [index]; - return fallbackProperties != 0 ? fallbackProperties->getValue (keyName, defaultValue) - : defaultValue; + return fallbackProperties != 0 ? fallbackProperties->getValue (keyName, defaultValue) + : defaultValue; } int PropertySet::getIntValue (const String& keyName, - const int defaultValue) const throw() + const int defaultValue) const throw() { - const ScopedLock sl (lock); - const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); + const ScopedLock sl (lock); + const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); - if (index >= 0) - return properties.getAllValues() [index].getIntValue(); + if (index >= 0) + return properties.getAllValues() [index].getIntValue(); - return fallbackProperties != 0 ? fallbackProperties->getIntValue (keyName, defaultValue) - : defaultValue; + return fallbackProperties != 0 ? fallbackProperties->getIntValue (keyName, defaultValue) + : defaultValue; } double PropertySet::getDoubleValue (const String& keyName, - const double defaultValue) const throw() + const double defaultValue) const throw() { - const ScopedLock sl (lock); - const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); + const ScopedLock sl (lock); + const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); - if (index >= 0) - return properties.getAllValues()[index].getDoubleValue(); + if (index >= 0) + return properties.getAllValues()[index].getDoubleValue(); - return fallbackProperties != 0 ? fallbackProperties->getDoubleValue (keyName, defaultValue) - : defaultValue; + return fallbackProperties != 0 ? fallbackProperties->getDoubleValue (keyName, defaultValue) + : defaultValue; } bool PropertySet::getBoolValue (const String& keyName, - const bool defaultValue) const throw() + const bool defaultValue) const throw() { - const ScopedLock sl (lock); - const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); + const ScopedLock sl (lock); + const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); - if (index >= 0) - return properties.getAllValues() [index].getIntValue() != 0; + if (index >= 0) + return properties.getAllValues() [index].getIntValue() != 0; - return fallbackProperties != 0 ? fallbackProperties->getBoolValue (keyName, defaultValue) - : defaultValue; + return fallbackProperties != 0 ? fallbackProperties->getBoolValue (keyName, defaultValue) + : defaultValue; } XmlElement* PropertySet::getXmlValue (const String& keyName) const { - XmlDocument doc (getValue (keyName)); + XmlDocument doc (getValue (keyName)); - return doc.getDocumentElement(); + return doc.getDocumentElement(); } void PropertySet::setValue (const String& keyName, - const String& value) throw() + const String& value) throw() { - jassert (keyName.isNotEmpty()); // shouldn't use an empty key name! + jassert (keyName.isNotEmpty()); // shouldn't use an empty key name! - if (keyName.isNotEmpty()) - { - const ScopedLock sl (lock); + if (keyName.isNotEmpty()) + { + const ScopedLock sl (lock); - const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); + const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); - if (index < 0 || properties.getAllValues() [index] != value) - { - properties.set (keyName, value); - propertyChanged(); - } - } + if (index < 0 || properties.getAllValues() [index] != value) + { + properties.set (keyName, value); + propertyChanged(); + } + } } void PropertySet::removeValue (const String& keyName) throw() { - if (keyName.isNotEmpty()) - { - const ScopedLock sl (lock); - const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); + if (keyName.isNotEmpty()) + { + const ScopedLock sl (lock); + const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); - if (index >= 0) - { - properties.remove (keyName); - propertyChanged(); - } - } + if (index >= 0) + { + properties.remove (keyName); + propertyChanged(); + } + } } void PropertySet::setValue (const String& keyName, const tchar* const value) throw() { - setValue (keyName, String (value)); + setValue (keyName, String (value)); } void PropertySet::setValue (const String& keyName, const int value) throw() { - setValue (keyName, String (value)); + setValue (keyName, String (value)); } void PropertySet::setValue (const String& keyName, const double value) throw() { - setValue (keyName, String (value)); + setValue (keyName, String (value)); } void PropertySet::setValue (const String& keyName, const bool value) throw() { - setValue (keyName, String ((value) ? T("1") : T("0"))); + setValue (keyName, String ((value) ? T("1") : T("0"))); } void PropertySet::setValue (const String& keyName, const XmlElement* const xml) { - setValue (keyName, (xml == 0) ? String::empty - : xml->createDocument (String::empty, true)); + setValue (keyName, (xml == 0) ? String::empty + : xml->createDocument (String::empty, true)); } bool PropertySet::containsKey (const String& keyName) const throw() { - const ScopedLock sl (lock); - return properties.getAllKeys().contains (keyName, ignoreCaseOfKeys); + const ScopedLock sl (lock); + return properties.getAllKeys().contains (keyName, ignoreCaseOfKeys); } void PropertySet::setFallbackPropertySet (PropertySet* fallbackProperties_) throw() { - const ScopedLock sl (lock); - fallbackProperties = fallbackProperties_; + const ScopedLock sl (lock); + fallbackProperties = fallbackProperties_; } XmlElement* PropertySet::createXml (const String& nodeName) const throw() { - const ScopedLock sl (lock); - XmlElement* const xml = new XmlElement (nodeName); + const ScopedLock sl (lock); + XmlElement* const xml = new XmlElement (nodeName); - for (int i = 0; i < properties.getAllKeys().size(); ++i) - { - XmlElement* const e = new XmlElement (T("VALUE")); + for (int i = 0; i < properties.getAllKeys().size(); ++i) + { + XmlElement* const e = new XmlElement (T("VALUE")); - e->setAttribute (T("name"), properties.getAllKeys()[i]); - e->setAttribute (T("val"), properties.getAllValues()[i]); + e->setAttribute (T("name"), properties.getAllKeys()[i]); + e->setAttribute (T("val"), properties.getAllValues()[i]); - xml->addChildElement (e); - } + xml->addChildElement (e); + } - return xml; + return xml; } void PropertySet::restoreFromXml (const XmlElement& xml) throw() { - const ScopedLock sl (lock); - clear(); + const ScopedLock sl (lock); + clear(); - forEachXmlChildElementWithTagName (xml, e, T("VALUE")) - { - if (e->hasAttribute (T("name")) - && e->hasAttribute (T("val"))) - { - properties.set (e->getStringAttribute (T("name")), - e->getStringAttribute (T("val"))); - } - } + forEachXmlChildElementWithTagName (xml, e, T("VALUE")) + { + if (e->hasAttribute (T("name")) + && e->hasAttribute (T("val"))) + { + properties.set (e->getStringAttribute (T("name")), + e->getStringAttribute (T("val"))); + } + } - if (properties.size() > 0) - propertyChanged(); + if (properties.size() > 0) + propertyChanged(); } void PropertySet::propertyChanged() @@ -3676,432 +3449,432 @@ BEGIN_JUCE_NAMESPACE var::var() throw() : type (voidType) { - value.doubleValue = 0; + value.doubleValue = 0; } void var::releaseValue() throw() { - if (type == stringType) - delete value.stringValue; - else if (type == objectType && value.objectValue != 0) - value.objectValue->decReferenceCount(); + if (type == stringType) + delete value.stringValue; + else if (type == objectType && value.objectValue != 0) + value.objectValue->decReferenceCount(); } var::~var() { - releaseValue(); + releaseValue(); } var::var (const var& valueToCopy) throw() : type (valueToCopy.type), - value (valueToCopy.value) + value (valueToCopy.value) { - if (type == stringType) - value.stringValue = new String (*(value.stringValue)); - else if (type == objectType && value.objectValue != 0) - value.objectValue->incReferenceCount(); + if (type == stringType) + value.stringValue = new String (*(value.stringValue)); + else if (type == objectType && value.objectValue != 0) + value.objectValue->incReferenceCount(); } var::var (const int value_) throw() : type (intType) { - value.intValue = value_; + value.intValue = value_; } var::var (const bool value_) throw() : type (boolType) { - value.boolValue = value_; + value.boolValue = value_; } var::var (const double value_) throw() : type (doubleType) { - value.doubleValue = value_; + value.doubleValue = value_; } var::var (const String& value_) throw() : type (stringType) { - value.stringValue = new String (value_); + value.stringValue = new String (value_); } var::var (const char* const value_) throw() : type (stringType) { - value.stringValue = new String (value_); + value.stringValue = new String (value_); } var::var (const juce_wchar* const value_) throw() : type (stringType) { - value.stringValue = new String (value_); + value.stringValue = new String (value_); } var::var (DynamicObject* const object) throw() : type (objectType) { - value.objectValue = object; + value.objectValue = object; - if (object != 0) - object->incReferenceCount(); + if (object != 0) + object->incReferenceCount(); } var::var (MethodFunction method_) throw() : type (methodType) { - value.methodValue = method_; + value.methodValue = method_; } const var& var::operator= (const var& valueToCopy) throw() { - if (this != &valueToCopy) - { - if (type == valueToCopy.type) - { - switch (type) - { - case voidType: - break; + if (this != &valueToCopy) + { + if (type == valueToCopy.type) + { + switch (type) + { + case voidType: + break; - case intType: - case boolType: - case doubleType: - value = valueToCopy.value; - break; + case intType: + case boolType: + case doubleType: + value = valueToCopy.value; + break; - case stringType: - *(value.stringValue) = *(valueToCopy.value.stringValue); - break; + case stringType: + *(value.stringValue) = *(valueToCopy.value.stringValue); + break; - case objectType: - if (valueToCopy.value.objectValue != 0) - valueToCopy.value.objectValue->incReferenceCount(); + case objectType: + if (valueToCopy.value.objectValue != 0) + valueToCopy.value.objectValue->incReferenceCount(); - if (value.objectValue != 0) - value.objectValue->decReferenceCount(); + if (value.objectValue != 0) + value.objectValue->decReferenceCount(); - value.objectValue = valueToCopy.value.objectValue; - break; + value.objectValue = valueToCopy.value.objectValue; + break; - default: - jassertfalse; - break; - } - } - else - { - releaseValue(); - type = valueToCopy.type; + default: + jassertfalse; + break; + } + } + else + { + releaseValue(); + type = valueToCopy.type; - if (type == stringType) - { - value.stringValue = new String (*(valueToCopy.value.stringValue)); - } - else - { - value = valueToCopy.value; + if (type == stringType) + { + value.stringValue = new String (*(valueToCopy.value.stringValue)); + } + else + { + value = valueToCopy.value; - if (type == objectType && value.objectValue != 0) - value.objectValue->incReferenceCount(); - } - } - } + if (type == objectType && value.objectValue != 0) + value.objectValue->incReferenceCount(); + } + } + } - return *this; + return *this; } const var& var::operator= (const int value_) throw() { - releaseValue(); - type = intType; - value.intValue = value_; - return *this; + releaseValue(); + type = intType; + value.intValue = value_; + return *this; } const var& var::operator= (const bool value_) throw() { - releaseValue(); - type = boolType; - value.boolValue = value_; - return *this; + releaseValue(); + type = boolType; + value.boolValue = value_; + return *this; } const var& var::operator= (const double value_) throw() { - releaseValue(); - type = doubleType; - value.doubleValue = value_; - return *this; + releaseValue(); + type = doubleType; + value.doubleValue = value_; + return *this; } const var& var::operator= (const char* const value_) throw() { - releaseValue(); - type = stringType; - value.stringValue = new String (value_); - return *this; + releaseValue(); + type = stringType; + value.stringValue = new String (value_); + return *this; } const var& var::operator= (const juce_wchar* const value_) throw() { - releaseValue(); - type = stringType; - value.stringValue = new String (value_); - return *this; + releaseValue(); + type = stringType; + value.stringValue = new String (value_); + return *this; } const var& var::operator= (const String& value_) throw() { - releaseValue(); - type = stringType; - value.stringValue = new String (value_); - return *this; + releaseValue(); + type = stringType; + value.stringValue = new String (value_); + return *this; } const var& var::operator= (DynamicObject* const value_) throw() { - value_->incReferenceCount(); - releaseValue(); - type = objectType; - value.objectValue = value_; - return *this; + value_->incReferenceCount(); + releaseValue(); + type = objectType; + value.objectValue = value_; + return *this; } const var& var::operator= (MethodFunction method_) throw() { - releaseValue(); - type = doubleType; - value.methodValue = method_; - return *this; + releaseValue(); + type = doubleType; + value.methodValue = method_; + return *this; } var::operator int() const throw() { - switch (type) - { - case voidType: break; - case intType: return value.intValue; - case boolType: return value.boolValue ? 1 : 0; - case doubleType: return (int) value.doubleValue; - case stringType: return value.stringValue->getIntValue(); - case objectType: break; - default: jassertfalse; break; - } + switch (type) + { + case voidType: break; + case intType: return value.intValue; + case boolType: return value.boolValue ? 1 : 0; + case doubleType: return (int) value.doubleValue; + case stringType: return value.stringValue->getIntValue(); + case objectType: break; + default: jassertfalse; break; + } - return 0; + return 0; } var::operator bool() const throw() { - switch (type) - { - case voidType: break; - case intType: return value.intValue != 0; - case boolType: return value.boolValue; - case doubleType: return value.doubleValue != 0; - case stringType: return value.stringValue->getIntValue() != 0 - || value.stringValue->trim().equalsIgnoreCase (T("true")) - || value.stringValue->trim().equalsIgnoreCase (T("yes")); - case objectType: return value.objectValue != 0; - default: jassertfalse; break; - } + switch (type) + { + case voidType: break; + case intType: return value.intValue != 0; + case boolType: return value.boolValue; + case doubleType: return value.doubleValue != 0; + case stringType: return value.stringValue->getIntValue() != 0 + || value.stringValue->trim().equalsIgnoreCase (T("true")) + || value.stringValue->trim().equalsIgnoreCase (T("yes")); + case objectType: return value.objectValue != 0; + default: jassertfalse; break; + } - return false; + return false; } var::operator float() const throw() { - return (float) operator double(); + return (float) operator double(); } var::operator double() const throw() { - switch (type) - { - case voidType: break; - case intType: return value.intValue; - case boolType: return value.boolValue ? 1.0 : 0.0; - case doubleType: return value.doubleValue; - case stringType: return value.stringValue->getDoubleValue(); - case objectType: break; - default: jassertfalse; break; - } + switch (type) + { + case voidType: break; + case intType: return value.intValue; + case boolType: return value.boolValue ? 1.0 : 0.0; + case doubleType: return value.doubleValue; + case stringType: return value.stringValue->getDoubleValue(); + case objectType: break; + default: jassertfalse; break; + } - return 0.0; + return 0.0; } const String var::toString() const throw() { - switch (type) - { - case voidType: return String::empty; - case intType: return String (value.intValue); - case boolType: return value.boolValue ? T("1") : T("0"); - case doubleType: return String (value.doubleValue); - case stringType: return *(value.stringValue); - case objectType: return "Object 0x" + String::toHexString ((int) (pointer_sized_int) value.objectValue); - default: jassertfalse; break; - } + switch (type) + { + case voidType: return String::empty; + case intType: return String (value.intValue); + case boolType: return value.boolValue ? T("1") : T("0"); + case doubleType: return String (value.doubleValue); + case stringType: return *(value.stringValue); + case objectType: return "Object 0x" + String::toHexString ((int) (pointer_sized_int) value.objectValue); + default: jassertfalse; break; + } - return String::empty; + return String::empty; } var::operator const String() const throw() { - return toString(); + return toString(); } DynamicObject* var::getObject() const throw() { - return type == objectType ? value.objectValue : 0; + return type == objectType ? value.objectValue : 0; } bool var::operator== (const var& other) const throw() { - switch (type) - { - case voidType: return other.isVoid(); - case intType: return value.intValue == (int) other; - case boolType: return value.boolValue == (bool) other; - case doubleType: return value.doubleValue == (double) other; - case stringType: return (*(value.stringValue)) == other.toString(); - case objectType: return value.objectValue == other.getObject(); - default: jassertfalse; break; - } + switch (type) + { + case voidType: return other.isVoid(); + case intType: return value.intValue == (int) other; + case boolType: return value.boolValue == (bool) other; + case doubleType: return value.doubleValue == (double) other; + case stringType: return (*(value.stringValue)) == other.toString(); + case objectType: return value.objectValue == other.getObject(); + default: jassertfalse; break; + } - return false; + return false; } bool var::operator!= (const var& other) const throw() { - return ! operator== (other); + return ! operator== (other); } void var::writeToStream (OutputStream& output) const throw() { - switch (type) - { - case voidType: output.writeCompressedInt (0); break; - case intType: output.writeCompressedInt (5); output.writeByte (1); output.writeInt (value.intValue); break; - case boolType: output.writeCompressedInt (1); output.writeByte (value.boolValue ? 2 : 3); break; - case doubleType: output.writeCompressedInt (9); output.writeByte (4); output.writeDouble (value.doubleValue); break; - case stringType: - { - const int len = value.stringValue->copyToUTF8 (0); - output.writeCompressedInt (len + 1); - output.writeByte (5); - HeapBlock temp (len); - value.stringValue->copyToUTF8 (temp); - output.write (temp, len); - break; - } - case objectType: output.writeCompressedInt (0); jassertfalse; break; // Can't write an object to a stream! - default: jassertfalse; break; // Is this a corrupted object? - } + switch (type) + { + case voidType: output.writeCompressedInt (0); break; + case intType: output.writeCompressedInt (5); output.writeByte (1); output.writeInt (value.intValue); break; + case boolType: output.writeCompressedInt (1); output.writeByte (value.boolValue ? 2 : 3); break; + case doubleType: output.writeCompressedInt (9); output.writeByte (4); output.writeDouble (value.doubleValue); break; + case stringType: + { + const int len = value.stringValue->copyToUTF8 (0); + output.writeCompressedInt (len + 1); + output.writeByte (5); + HeapBlock temp (len); + value.stringValue->copyToUTF8 (temp); + output.write (temp, len); + break; + } + case objectType: output.writeCompressedInt (0); jassertfalse; break; // Can't write an object to a stream! + default: jassertfalse; break; // Is this a corrupted object? + } } const var var::readFromStream (InputStream& input) throw() { - const int numBytes = input.readCompressedInt(); + const int numBytes = input.readCompressedInt(); - if (numBytes > 0) - { - switch (input.readByte()) - { - case 1: return var (input.readInt()); - case 2: return var (true); - case 3: return var (false); - case 4: return var (input.readDouble()); - case 5: - { - MemoryBlock mb; - input.readIntoMemoryBlock (mb, numBytes - 1); - return var (String::fromUTF8 ((const uint8*) mb.getData(), mb.getSize())); - } + if (numBytes > 0) + { + switch (input.readByte()) + { + case 1: return var (input.readInt()); + case 2: return var (true); + case 3: return var (false); + case 4: return var (input.readDouble()); + case 5: + { + MemoryBlock mb; + input.readIntoMemoryBlock (mb, numBytes - 1); + return var (String::fromUTF8 ((const uint8*) mb.getData(), (int) mb.getSize())); + } - default: input.skipNextBytes (numBytes - 1); break; - } - } + default: input.skipNextBytes (numBytes - 1); break; + } + } - return var(); + return var(); } const var var::operator[] (const var::identifier& propertyName) const throw() { - if (type == objectType && value.objectValue != 0) - return value.objectValue->getProperty (propertyName); + if (type == objectType && value.objectValue != 0) + return value.objectValue->getProperty (propertyName); - return var(); + return var(); } const var var::invoke (const var::identifier& method, const var* arguments, int numArguments) const { - if (type == objectType && value.objectValue != 0) - return value.objectValue->invokeMethod (method, arguments, numArguments); + if (type == objectType && value.objectValue != 0) + return value.objectValue->invokeMethod (method, arguments, numArguments); - return var(); + return var(); } const var var::invoke (const var& targetObject, const var* arguments, int numArguments) const { - if (isMethod()) - { - DynamicObject* const target = targetObject.getObject(); + if (isMethod()) + { + DynamicObject* const target = targetObject.getObject(); - if (target != 0) - return (target->*(value.methodValue)) (arguments, numArguments); - } + if (target != 0) + return (target->*(value.methodValue)) (arguments, numArguments); + } - return var(); + return var(); } const var var::call (const var::identifier& method) const { - return invoke (method, 0, 0); + return invoke (method, 0, 0); } const var var::call (const var::identifier& method, const var& arg1) const { - return invoke (method, &arg1, 1); + return invoke (method, &arg1, 1); } const var var::call (const var::identifier& method, const var& arg1, const var& arg2) const { - var args[] = { arg1, arg2 }; - return invoke (method, args, 2); + var args[] = { arg1, arg2 }; + return invoke (method, args, 2); } const var var::call (const var::identifier& method, const var& arg1, const var& arg2, const var& arg3) { - var args[] = { arg1, arg2, arg3 }; - return invoke (method, args, 3); + var args[] = { arg1, arg2, arg3 }; + return invoke (method, args, 3); } const var var::call (const var::identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const { - var args[] = { arg1, arg2, arg3, arg4 }; - return invoke (method, args, 4); + var args[] = { arg1, arg2, arg3, arg4 }; + return invoke (method, args, 4); } const var var::call (const var::identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const { - var args[] = { arg1, arg2, arg3, arg4, arg5 }; - return invoke (method, args, 5); + var args[] = { arg1, arg2, arg3, arg4, arg5 }; + return invoke (method, args, 5); } var::identifier::identifier (const String& name_) throw() - : name (name_), - hashCode (name_.hashCode()) + : name (name_), + hashCode (name_.hashCode()) { - jassert (name_.isNotEmpty()); + jassert (name_.isNotEmpty()); } var::identifier::identifier (const char* const name_) throw() - : name (name_), - hashCode (name.hashCode()) + : name (name_), + hashCode (name.hashCode()) { - jassert (name.isNotEmpty()); + jassert (name.isNotEmpty()); } var::identifier::~identifier() throw() @@ -4118,67 +3891,67 @@ DynamicObject::~DynamicObject() bool DynamicObject::hasProperty (const var::identifier& propertyName) const { - const int index = propertyIds.indexOf (propertyName.hashCode); - return index >= 0 && ! propertyValues.getUnchecked (index)->isMethod(); + const int index = propertyIds.indexOf (propertyName.hashCode); + return index >= 0 && ! propertyValues.getUnchecked (index)->isMethod(); } const var DynamicObject::getProperty (const var::identifier& propertyName) const { - const int index = propertyIds.indexOf (propertyName.hashCode); - if (index >= 0) - return *propertyValues.getUnchecked (index); + const int index = propertyIds.indexOf (propertyName.hashCode); + if (index >= 0) + return *propertyValues.getUnchecked (index); - return var(); + return var(); } void DynamicObject::setProperty (const var::identifier& propertyName, const var& newValue) { - const int index = propertyIds.indexOf (propertyName.hashCode); + const int index = propertyIds.indexOf (propertyName.hashCode); - if (index >= 0) - { - propertyValues.set (index, new var (newValue)); - } - else - { - propertyIds.add (propertyName.hashCode); - propertyValues.add (new var (newValue)); - } + if (index >= 0) + { + propertyValues.set (index, new var (newValue)); + } + else + { + propertyIds.add (propertyName.hashCode); + propertyValues.add (new var (newValue)); + } } void DynamicObject::removeProperty (const var::identifier& propertyName) { - const int index = propertyIds.indexOf (propertyName.hashCode); + const int index = propertyIds.indexOf (propertyName.hashCode); - if (index >= 0) - { - propertyIds.remove (index); - propertyValues.remove (index); - } + if (index >= 0) + { + propertyIds.remove (index); + propertyValues.remove (index); + } } bool DynamicObject::hasMethod (const var::identifier& methodName) const { - return getProperty (methodName).isMethod(); + return getProperty (methodName).isMethod(); } const var DynamicObject::invokeMethod (const var::identifier& methodName, - const var* parameters, - int numParameters) + const var* parameters, + int numParameters) { - return getProperty (methodName).invoke (this, parameters, numParameters); + return getProperty (methodName).invoke (this, parameters, numParameters); } void DynamicObject::setMethod (const var::identifier& name, - var::MethodFunction methodFunction) + var::MethodFunction methodFunction) { - setProperty (name, methodFunction); + setProperty (name, methodFunction); } void DynamicObject::clear() { - propertyIds.clear(); - propertyValues.clear(); + propertyIds.clear(); + propertyValues.clear(); } END_JUCE_NAMESPACE @@ -4190,339 +3963,339 @@ BEGIN_JUCE_NAMESPACE static const uint32 initialPValues [18] = { - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, - 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, - 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, - 0x9216d5d9, 0x8979fb1b + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b }; static const uint32 initialSValues [4 * 256] = { - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, - 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, - 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, - 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, - 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, - 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, - 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, - 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, - 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, - 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, - 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, - 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, - 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, - 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, - 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, - 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, - 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, - 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, - 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, - 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, - 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, - 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, - 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, - 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, - 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, - 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, - 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, - 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, - 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, - 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, - 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, - 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, - 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, - 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, - 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, - 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, - 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, - 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, - 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, - 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, - 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, - 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, - 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, - 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, - 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, - 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, - 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, - 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, - 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, - 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, - 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, - 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, - 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, - 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, - 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, - 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, - 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, - 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, - 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, - 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, - 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, - 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, - 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, - 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, - 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, - 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, - 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, - 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, - 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, - 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, - 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, - 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, - 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, - 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, - 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, - 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, - 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, - 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, - 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, - 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, - 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, - 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, - 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, - 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, - 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, - 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, - 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, - 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, - 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, - 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, - 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, - 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, - 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, - 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, - 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, - 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, - 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, - 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, - 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, - 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, - 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, - 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, - 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, - 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, - 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, - 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, - 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, - 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, - 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, - 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, - 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, - 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, - 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, - 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, - 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, - 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, - 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, - 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, - 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, - 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, - 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, - 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, - 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, - 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, - 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, - 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, - 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, - 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, - 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, - 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, - 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, - 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, - 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, - 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, - 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, - 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, - 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, - 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, - 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, - 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, - 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, - 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, - 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, - 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, - 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, - 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, - 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, - 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, - 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, - 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, - 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, - 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, - 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, - 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, - 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, - 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, - 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, - 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, - 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, - 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, - 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, - 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, - 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, - 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, - 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, - 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, - 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, - 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, - 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 }; BlowFish::BlowFish (const uint8* keyData, int keyBytes) { - memcpy (p, initialPValues, sizeof (p)); + memcpy (p, initialPValues, sizeof (p)); - int i, j; - for (i = 4; --i >= 0;) - { - s[i].malloc (256); - memcpy (s[i], initialSValues + i * 256, 256 * sizeof (uint32)); - } + int i, j; + for (i = 4; --i >= 0;) + { + s[i].malloc (256); + memcpy (s[i], initialSValues + i * 256, 256 * sizeof (uint32)); + } - j = 0; + j = 0; - for (i = 0; i < 18; ++i) - { - uint32 d = 0; + for (i = 0; i < 18; ++i) + { + uint32 d = 0; - for (int k = 0; k < 4; ++k) - { - d = (d << 8) | keyData[j]; + for (int k = 0; k < 4; ++k) + { + d = (d << 8) | keyData[j]; - if (++j >= keyBytes) - j = 0; - } + if (++j >= keyBytes) + j = 0; + } - p[i] = initialPValues[i] ^ d; - } + p[i] = initialPValues[i] ^ d; + } - uint32 l = 0, r = 0; + uint32 l = 0, r = 0; - for (i = 0; i < 18; i += 2) - { - encrypt (l, r); + for (i = 0; i < 18; i += 2) + { + encrypt (l, r); - p[i] = l; - p[i + 1] = r; - } + p[i] = l; + p[i + 1] = r; + } - for (i = 0; i < 4; ++i) - { - for (j = 0; j < 256; j += 2) - { - encrypt (l, r); + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 256; j += 2) + { + encrypt (l, r); - s[i][j] = l; - s[i][j + 1] = r; - } - } + s[i][j] = l; + s[i][j + 1] = r; + } + } } BlowFish::BlowFish (const BlowFish& other) { - for (int i = 4; --i >= 0;) - s[i].malloc (256); + for (int i = 4; --i >= 0;) + s[i].malloc (256); - operator= (other); + operator= (other); } const BlowFish& BlowFish::operator= (const BlowFish& other) { - memcpy (p, other.p, sizeof (p)); + memcpy (p, other.p, sizeof (p)); - for (int i = 4; --i >= 0;) - memcpy (s[i], other.s[i], 256 * sizeof (uint32)); + for (int i = 4; --i >= 0;) + memcpy (s[i], other.s[i], 256 * sizeof (uint32)); - return *this; + return *this; } BlowFish::~BlowFish() @@ -4531,76 +4304,76 @@ BlowFish::~BlowFish() uint32 BlowFish::F (uint32 x) const { - uint16 a, b, c, d; - uint32 y; + uint16 a, b, c, d; + uint32 y; - d = (uint16) (x & 0xff); - x >>= 8; - c = (uint16) (x & 0xff); - x >>= 8; - b = (uint16) (x & 0xff); - x >>= 8; - a = (uint16) (x & 0xff); + d = (uint16) (x & 0xff); + x >>= 8; + c = (uint16) (x & 0xff); + x >>= 8; + b = (uint16) (x & 0xff); + x >>= 8; + a = (uint16) (x & 0xff); - y = s[0][a] + s[1][b]; - y = y ^ s[2][c]; - y = y + s[3][d]; + y = s[0][a] + s[1][b]; + y = y ^ s[2][c]; + y = y + s[3][d]; - return y; + return y; } void BlowFish::encrypt (uint32& data1, - uint32& data2) const + uint32& data2) const { - uint32 l = data1; - uint32 r = data2; + uint32 l = data1; + uint32 r = data2; - for (int i = 0; i < 16; ++i) - { - l = l ^ p[i]; - r = F (l) ^ r; + for (int i = 0; i < 16; ++i) + { + l = l ^ p[i]; + r = F (l) ^ r; - const uint32 temp = l; - l = r; - r = temp; - } + const uint32 temp = l; + l = r; + r = temp; + } - const uint32 temp = l; - l = r; - r = temp; + const uint32 temp = l; + l = r; + r = temp; - r = r ^ p[16]; - l = l ^ p[17]; + r = r ^ p[16]; + l = l ^ p[17]; - data1 = l; - data2 = r; + data1 = l; + data2 = r; } void BlowFish::decrypt (uint32& data1, - uint32& data2) const + uint32& data2) const { - uint32 l = data1; - uint32 r = data2; + uint32 l = data1; + uint32 r = data2; - for (int i = 17; i > 1; --i) - { - l =l ^ p[i]; - r = F (l) ^ r; + for (int i = 17; i > 1; --i) + { + l =l ^ p[i]; + r = F (l) ^ r; - const uint32 temp = l; - l = r; - r = temp; - } + const uint32 temp = l; + l = r; + r = temp; + } - const uint32 temp = l; - l = r; - r = temp; + const uint32 temp = l; + l = r; + r = temp; - r = r ^ p[1]; - l = l ^ p[0]; + r = r ^ p[1]; + l = l ^ p[0]; - data1 = l; - data2 = r; + data1 = l; + data2 = r; } END_JUCE_NAMESPACE @@ -4612,91 +4385,91 @@ BEGIN_JUCE_NAMESPACE MD5::MD5() { - zeromem (result, sizeof (result)); + zeromem (result, sizeof (result)); } MD5::MD5 (const MD5& other) { - memcpy (result, other.result, sizeof (result)); + memcpy (result, other.result, sizeof (result)); } const MD5& MD5::operator= (const MD5& other) { - memcpy (result, other.result, sizeof (result)); - return *this; + memcpy (result, other.result, sizeof (result)); + return *this; } MD5::MD5 (const MemoryBlock& data) { - ProcessContext context; - context.processBlock ((const uint8*) data.getData(), data.getSize()); - context.finish (result); + ProcessContext context; + context.processBlock ((const uint8*) data.getData(), data.getSize()); + context.finish (result); } -MD5::MD5 (const char* data, const int numBytes) +MD5::MD5 (const char* data, const size_t numBytes) { - ProcessContext context; - context.processBlock ((const uint8*) data, numBytes); - context.finish (result); + ProcessContext context; + context.processBlock ((const uint8*) data, numBytes); + context.finish (result); } MD5::MD5 (const String& text) { - ProcessContext context; + ProcessContext context; - const int len = text.length(); - const juce_wchar* const t = text; + const int len = text.length(); + const juce_wchar* const t = text; - for (int i = 0; i < len; ++i) - { - // force the string into integer-sized unicode characters, to try to make it - // get the same results on all platforms + compilers. - uint32 unicodeChar = (uint32) t[i]; - ByteOrder::swapIfBigEndian (unicodeChar); + for (int i = 0; i < len; ++i) + { + // force the string into integer-sized unicode characters, to try to make it + // get the same results on all platforms + compilers. + uint32 unicodeChar = (uint32) t[i]; + ByteOrder::swapIfBigEndian (unicodeChar); - context.processBlock ((const uint8*) &unicodeChar, - sizeof (unicodeChar)); - } + context.processBlock ((const uint8*) &unicodeChar, + sizeof (unicodeChar)); + } - context.finish (result); + context.finish (result); } -void MD5::processStream (InputStream& input, int numBytesToRead) +void MD5::processStream (InputStream& input, int64 numBytesToRead) { - ProcessContext context; + ProcessContext context; - if (numBytesToRead < 0) - numBytesToRead = INT_MAX; + if (numBytesToRead < 0) + numBytesToRead = INT_MAX; - while (numBytesToRead > 0) - { - char tempBuffer [512]; - const int bytesRead = input.read (tempBuffer, jmin (numBytesToRead, sizeof (tempBuffer))); + while (numBytesToRead > 0) + { + char tempBuffer [512]; + const int bytesRead = input.read (tempBuffer, (int) jmin (numBytesToRead, (int64) sizeof (tempBuffer))); - if (bytesRead <= 0) - break; + if (bytesRead <= 0) + break; - numBytesToRead -= bytesRead; + numBytesToRead -= bytesRead; - context.processBlock ((const uint8*) tempBuffer, bytesRead); - } + context.processBlock ((const uint8*) tempBuffer, bytesRead); + } - context.finish (result); + context.finish (result); } -MD5::MD5 (InputStream& input, int numBytesToRead) +MD5::MD5 (InputStream& input, int64 numBytesToRead) { - processStream (input, numBytesToRead); + processStream (input, numBytesToRead); } MD5::MD5 (const File& file) { - const ScopedPointer fin (file.createInputStream()); + const ScopedPointer fin (file.createInputStream()); - if (fin != 0) - processStream (*fin, -1); - else - zeromem (result, sizeof (result)); + if (fin != 0) + processStream (*fin, -1); + else + zeromem (result, sizeof (result)); } MD5::~MD5() @@ -4705,89 +4478,89 @@ MD5::~MD5() MD5::ProcessContext::ProcessContext() { - state[0] = 0x67452301; - state[1] = 0xefcdab89; - state[2] = 0x98badcfe; - state[3] = 0x10325476; + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; - count[0] = 0; - count[1] = 0; + count[0] = 0; + count[1] = 0; } -void MD5::ProcessContext::processBlock (const uint8* const data, int dataSize) +void MD5::ProcessContext::processBlock (const uint8* const data, size_t dataSize) { - int bufferPos = ((count[0] >> 3) & 0x3F); + int bufferPos = ((count[0] >> 3) & 0x3F); - count[0] += (dataSize << 3); + count[0] += (uint32) (dataSize << 3); - if (count[0] < ((uint32) dataSize << 3)) - count[1]++; + if (count[0] < ((uint32) dataSize << 3)) + count[1]++; - count[1] += (dataSize >> 29); + count[1] += (uint32) (dataSize >> 29); - const int spaceLeft = 64 - bufferPos; + const size_t spaceLeft = 64 - bufferPos; - int i = 0; + size_t i = 0; - if (dataSize >= spaceLeft) - { - memcpy (buffer + bufferPos, data, spaceLeft); + if (dataSize >= spaceLeft) + { + memcpy (buffer + bufferPos, data, spaceLeft); - transform (buffer); + transform (buffer); - i = spaceLeft; + i = spaceLeft; - while (i < dataSize - 63) - { - transform (data + i); - i += 64; - } + while (i < dataSize - 63) + { + transform (data + i); + i += 64; + } - bufferPos = 0; - } + bufferPos = 0; + } - memcpy (buffer + bufferPos, data + i, dataSize - i); + memcpy (buffer + bufferPos, data + i, dataSize - i); } static void encode (uint8* const output, - const uint32* const input, - const int numBytes) + const uint32* const input, + const int numBytes) { - uint32* const o = (uint32*) output; + uint32* const o = (uint32*) output; - for (int i = 0; i < (numBytes >> 2); ++i) - o[i] = ByteOrder::swapIfBigEndian (input [i]); + for (int i = 0; i < (numBytes >> 2); ++i) + o[i] = ByteOrder::swapIfBigEndian (input [i]); } static void decode (uint32* const output, - const uint8* const input, - const int numBytes) + const uint8* const input, + const int numBytes) { - for (int i = 0; i < (numBytes >> 2); ++i) - output[i] = ByteOrder::littleEndianInt ((const char*) input + (i << 2)); + for (int i = 0; i < (numBytes >> 2); ++i) + output[i] = ByteOrder::littleEndianInt ((const char*) input + (i << 2)); } void MD5::ProcessContext::finish (uint8* const result) { - unsigned char encodedLength[8]; - encode (encodedLength, count, 8); + unsigned char encodedLength[8]; + encode (encodedLength, count, 8); - // Pad out to 56 mod 64. - const int index = (uint32) ((count[0] >> 3) & 0x3f); + // Pad out to 56 mod 64. + const int index = (uint32) ((count[0] >> 3) & 0x3f); - const int paddingLength = (index < 56) ? (56 - index) - : (120 - index); + const int paddingLength = (index < 56) ? (56 - index) + : (120 - index); - uint8 paddingBuffer [64]; - zeromem (paddingBuffer, paddingLength); - paddingBuffer [0] = 0x80; - processBlock (paddingBuffer, paddingLength); + uint8 paddingBuffer [64]; + zeromem (paddingBuffer, paddingLength); + paddingBuffer [0] = 0x80; + processBlock (paddingBuffer, paddingLength); - processBlock (encodedLength, 8); + processBlock (encodedLength, 8); - encode (result, state, 16); + encode (result, state, 16); - zeromem (buffer, sizeof (buffer)); + zeromem (buffer, sizeof (buffer)); } #define S11 7 @@ -4812,136 +4585,136 @@ static inline uint32 G (const uint32 x, const uint32 y, const uint32 z) { retu static inline uint32 H (const uint32 x, const uint32 y, const uint32 z) { return x ^ y ^ z; } static inline uint32 I (const uint32 x, const uint32 y, const uint32 z) { return y ^ (x | ~z); } -static inline uint32 rotateLeft (const uint32 x, const uint32 n) { return (x << n) | (x >> (32 - n)); } +static inline uint32 rotateLeft (const uint32 x, const uint32 n) { return (x << n) | (x >> (32 - n)); } static inline void FF (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) { - a += F (b, c, d) + x + ac; - a = rotateLeft (a, s) + b; + a += F (b, c, d) + x + ac; + a = rotateLeft (a, s) + b; } static inline void GG (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) { - a += G (b, c, d) + x + ac; - a = rotateLeft (a, s) + b; + a += G (b, c, d) + x + ac; + a = rotateLeft (a, s) + b; } static inline void HH (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) { - a += H (b, c, d) + x + ac; - a = rotateLeft (a, s) + b; + a += H (b, c, d) + x + ac; + a = rotateLeft (a, s) + b; } static inline void II (uint32& a, const uint32 b, const uint32 c, const uint32 d, const uint32 x, const uint32 s, const uint32 ac) { - a += I (b, c, d) + x + ac; - a = rotateLeft (a, s) + b; + a += I (b, c, d) + x + ac; + a = rotateLeft (a, s) + b; } void MD5::ProcessContext::transform (const uint8* const bufferToTransform) { - uint32 a = state[0]; - uint32 b = state[1]; - uint32 c = state[2]; - uint32 d = state[3]; - uint32 x[16]; + uint32 a = state[0]; + uint32 b = state[1]; + uint32 c = state[2]; + uint32 d = state[3]; + uint32 x[16]; - decode (x, bufferToTransform, 64); + decode (x, bufferToTransform, 64); - FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ - FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ - FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ - FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ - FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ - FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ - FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ - FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ - FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ - FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ - FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ - FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ - FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ - FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ - FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ - FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ - GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ - GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ - GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ - GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ - GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ - GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ - GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ - GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ - GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ - GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ - GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ - GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ - GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ - GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ - GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ - HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ - HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ - HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ - HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ - HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ - HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ - HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ - HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ - HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ - HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ - HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ - HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ - HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ - HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ - HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ - II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ - II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ - II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ - II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ - II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ - II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ - II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ - II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ - II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ - II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ - II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ - II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ - II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ - II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ - II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; - zeromem (x, sizeof (x)); + zeromem (x, sizeof (x)); } const MemoryBlock MD5::getRawChecksumData() const { - return MemoryBlock (result, 16); + return MemoryBlock (result, 16); } const String MD5::toHexString() const { - return String::toHexString (result, 16, 0); + return String::toHexString (result, 16, 0); } bool MD5::operator== (const MD5& other) const { - return memcmp (result, other.result, 16) == 0; + return memcmp (result, other.result, 16) == 0; } bool MD5::operator!= (const MD5& other) const { - return ! operator== (other); + return ! operator== (other); } END_JUCE_NAMESPACE @@ -4953,225 +4726,225 @@ BEGIN_JUCE_NAMESPACE static void createSmallSieve (const int numBits, BitArray& result) throw() { - result.setBit (numBits); - result.clearBit (numBits); // to enlarge the array + result.setBit (numBits); + result.clearBit (numBits); // to enlarge the array - result.setBit (0); - int n = 2; + result.setBit (0); + int n = 2; - do - { - for (int i = n + n; i < numBits; i += n) - result.setBit (i); + do + { + for (int i = n + n; i < numBits; i += n) + result.setBit (i); - n = result.findNextClearBit (n + 1); - } - while (n <= (numBits >> 1)); + n = result.findNextClearBit (n + 1); + } + while (n <= (numBits >> 1)); } static void bigSieve (const BitArray& base, - const int numBits, - BitArray& result, - const BitArray& smallSieve, - const int smallSieveSize) throw() + const int numBits, + BitArray& result, + const BitArray& smallSieve, + const int smallSieveSize) throw() { - jassert (! base[0]); // must be even! + jassert (! base[0]); // must be even! - result.setBit (numBits); - result.clearBit (numBits); // to enlarge the array + result.setBit (numBits); + result.clearBit (numBits); // to enlarge the array - int index = smallSieve.findNextClearBit (0); + int index = smallSieve.findNextClearBit (0); - do - { - const int prime = (index << 1) + 1; + do + { + const int prime = (index << 1) + 1; - BitArray r (base); - BitArray remainder; - r.divideBy (prime, remainder); + BitArray r (base); + BitArray remainder; + r.divideBy (prime, remainder); - int i = prime - remainder.getBitRangeAsInt (0, 32); + int i = prime - remainder.getBitRangeAsInt (0, 32); - if (r.isEmpty()) - i += prime; + if (r.isEmpty()) + i += prime; - if ((i & 1) == 0) - i += prime; + if ((i & 1) == 0) + i += prime; - i = (i - 1) >> 1; + i = (i - 1) >> 1; - while (i < numBits) - { - result.setBit (i); - i += prime; - } + while (i < numBits) + { + result.setBit (i); + i += prime; + } - index = smallSieve.findNextClearBit (index + 1); - } - while (index < smallSieveSize); + index = smallSieve.findNextClearBit (index + 1); + } + while (index < smallSieveSize); } static bool findCandidate (const BitArray& base, - const BitArray& sieve, - const int numBits, - BitArray& result, - const int certainty) throw() + const BitArray& sieve, + const int numBits, + BitArray& result, + const int certainty) throw() { - for (int i = 0; i < numBits; ++i) - { - if (! sieve[i]) - { - result = base; - result.add (BitArray ((unsigned int) ((i << 1) + 1))); + for (int i = 0; i < numBits; ++i) + { + if (! sieve[i]) + { + result = base; + result.add (BitArray ((unsigned int) ((i << 1) + 1))); - if (Primes::isProbablyPrime (result, certainty)) - return true; - } - } + if (Primes::isProbablyPrime (result, certainty)) + return true; + } + } - return false; + return false; } const BitArray Primes::createProbablePrime (const int bitLength, - const int certainty, - const int* randomSeeds, - int numRandomSeeds) throw() + const int certainty, + const int* randomSeeds, + int numRandomSeeds) throw() { - int defaultSeeds [16]; + int defaultSeeds [16]; - if (numRandomSeeds <= 0) - { - randomSeeds = defaultSeeds; - numRandomSeeds = numElementsInArray (defaultSeeds); - Random r (0); + if (numRandomSeeds <= 0) + { + randomSeeds = defaultSeeds; + numRandomSeeds = numElementsInArray (defaultSeeds); + Random r (0); - for (int j = 10; --j >= 0;) - { - r.setSeedRandomly(); + for (int j = 10; --j >= 0;) + { + r.setSeedRandomly(); - for (int i = numRandomSeeds; --i >= 0;) - defaultSeeds[i] ^= r.nextInt() ^ Random::getSystemRandom().nextInt(); - } - } + for (int i = numRandomSeeds; --i >= 0;) + defaultSeeds[i] ^= r.nextInt() ^ Random::getSystemRandom().nextInt(); + } + } - BitArray smallSieve; - const int smallSieveSize = 15000; - createSmallSieve (smallSieveSize, smallSieve); + BitArray smallSieve; + const int smallSieveSize = 15000; + createSmallSieve (smallSieveSize, smallSieve); - BitArray p; + BitArray p; - for (int i = numRandomSeeds; --i >= 0;) - { - BitArray p2; + for (int i = numRandomSeeds; --i >= 0;) + { + BitArray p2; - Random r (randomSeeds[i]); - r.fillBitsRandomly (p2, 0, bitLength); + Random r (randomSeeds[i]); + r.fillBitsRandomly (p2, 0, bitLength); - p.xorWith (p2); - } + p.xorWith (p2); + } - p.setBit (bitLength - 1); - p.clearBit (0); + p.setBit (bitLength - 1); + p.clearBit (0); - const int searchLen = jmax (1024, (bitLength / 20) * 64); + const int searchLen = jmax (1024, (bitLength / 20) * 64); - while (p.getHighestBit() < bitLength) - { - p.add (2 * searchLen); + while (p.getHighestBit() < bitLength) + { + p.add (2 * searchLen); - BitArray sieve; - bigSieve (p, searchLen, sieve, - smallSieve, smallSieveSize); + BitArray sieve; + bigSieve (p, searchLen, sieve, + smallSieve, smallSieveSize); - BitArray candidate; + BitArray candidate; - if (findCandidate (p, sieve, searchLen, candidate, certainty)) - return candidate; - } + if (findCandidate (p, sieve, searchLen, candidate, certainty)) + return candidate; + } - jassertfalse - return BitArray(); + jassertfalse + return BitArray(); } static bool passesMillerRabin (const BitArray& n, int iterations) throw() { - const BitArray one (1); - const BitArray two (2); + const BitArray one (1); + const BitArray two (2); - BitArray nMinusOne (n); - nMinusOne.subtract (one); + BitArray nMinusOne (n); + nMinusOne.subtract (one); - BitArray d (nMinusOne); - const int s = d.findNextSetBit (0); - d.shiftBits (-s); + BitArray d (nMinusOne); + const int s = d.findNextSetBit (0); + d.shiftBits (-s); - BitArray smallPrimes; - int numBitsInSmallPrimes = 0; + BitArray smallPrimes; + int numBitsInSmallPrimes = 0; - for (;;) - { - numBitsInSmallPrimes += 256; - createSmallSieve (numBitsInSmallPrimes, smallPrimes); + for (;;) + { + numBitsInSmallPrimes += 256; + createSmallSieve (numBitsInSmallPrimes, smallPrimes); - const int numPrimesFound = numBitsInSmallPrimes - smallPrimes.countNumberOfSetBits(); + const int numPrimesFound = numBitsInSmallPrimes - smallPrimes.countNumberOfSetBits(); - if (numPrimesFound > iterations + 1) - break; - } + if (numPrimesFound > iterations + 1) + break; + } - int smallPrime = 2; + int smallPrime = 2; - while (--iterations >= 0) - { - smallPrime = smallPrimes.findNextClearBit (smallPrime + 1); + while (--iterations >= 0) + { + smallPrime = smallPrimes.findNextClearBit (smallPrime + 1); - BitArray r (smallPrime); - //r.createRandomNumber (nMinusOne); - r.exponentModulo (d, n); + BitArray r (smallPrime); + //r.createRandomNumber (nMinusOne); + r.exponentModulo (d, n); - if (! (r == one || r == nMinusOne)) - { - for (int j = 0; j < s; ++j) - { - r.exponentModulo (two, n); + if (! (r == one || r == nMinusOne)) + { + for (int j = 0; j < s; ++j) + { + r.exponentModulo (two, n); - if (r == nMinusOne) - break; - } + if (r == nMinusOne) + break; + } - if (r != nMinusOne) - return false; - } - } + if (r != nMinusOne) + return false; + } + } - return true; + return true; } bool Primes::isProbablyPrime (const BitArray& number, - const int certainty) throw() + const int certainty) throw() { - if (! number[0]) - return false; + if (! number[0]) + return false; - if (number.getHighestBit() <= 10) - { - const int num = number.getBitRangeAsInt (0, 10); + if (number.getHighestBit() <= 10) + { + const int num = number.getBitRangeAsInt (0, 10); - for (int i = num / 2; --i > 1;) - if (num % i == 0) - return false; + for (int i = num / 2; --i > 1;) + if (num % i == 0) + return false; - return true; - } - else - { - const BitArray screen (2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23); + return true; + } + else + { + const BitArray screen (2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23); - if (number.findGreatestCommonDivisor (screen) != BitArray (1)) - return false; + if (number.findGreatestCommonDivisor (screen) != BitArray (1)) + return false; - return passesMillerRabin (number, certainty); - } + return passesMillerRabin (number, certainty); + } } END_JUCE_NAMESPACE @@ -5187,16 +4960,16 @@ RSAKey::RSAKey() throw() RSAKey::RSAKey (const String& s) throw() { - if (s.containsChar (T(','))) - { - part1.parseString (s.upToFirstOccurrenceOf (T(","), false, false), 16); - part2.parseString (s.fromFirstOccurrenceOf (T(","), false, false), 16); - } - else - { - // the string needs to be two hex numbers, comma-separated.. - jassertfalse; - } + if (s.containsChar (T(','))) + { + part1.parseString (s.upToFirstOccurrenceOf (T(","), false, false), 16); + part2.parseString (s.fromFirstOccurrenceOf (T(","), false, false), 16); + } + else + { + // the string needs to be two hex numbers, comma-separated.. + jassertfalse; + } } RSAKey::~RSAKey() throw() @@ -5205,98 +4978,98 @@ RSAKey::~RSAKey() throw() const String RSAKey::toString() const throw() { - return part1.toString (16) + T(",") + part2.toString (16); + return part1.toString (16) + T(",") + part2.toString (16); } bool RSAKey::applyToValue (BitArray& value) const throw() { - if (part1.isEmpty() || part2.isEmpty() - || value.compare (0) <= 0) - { - jassertfalse // using an uninitialised key - value.clear(); - return false; - } + if (part1.isEmpty() || part2.isEmpty() + || value.compare (0) <= 0) + { + jassertfalse // using an uninitialised key + value.clear(); + return false; + } - BitArray result; + BitArray result; - while (! value.isEmpty()) - { - result.multiplyBy (part2); + while (! value.isEmpty()) + { + result.multiplyBy (part2); - BitArray remainder; - value.divideBy (part2, remainder); + BitArray remainder; + value.divideBy (part2, remainder); - remainder.exponentModulo (part1, part2); + remainder.exponentModulo (part1, part2); - result.add (remainder); - } + result.add (remainder); + } - value = result; + value = result; - return true; + return true; } static const BitArray findBestCommonDivisor (const BitArray& p, - const BitArray& q) throw() + const BitArray& q) throw() { - const BitArray one (1); + const BitArray one (1); - // try 3, 5, 9, 17, etc first because these only contain 2 bits and so - // are fast to divide + multiply - for (int i = 2; i <= 65536; i *= 2) - { - const BitArray e (1 + i); + // try 3, 5, 9, 17, etc first because these only contain 2 bits and so + // are fast to divide + multiply + for (int i = 2; i <= 65536; i *= 2) + { + const BitArray e (1 + i); - if (e.findGreatestCommonDivisor (p) == one - && e.findGreatestCommonDivisor (q) == one) - { - return e; - } - } + if (e.findGreatestCommonDivisor (p) == one + && e.findGreatestCommonDivisor (q) == one) + { + return e; + } + } - BitArray e (4); + BitArray e (4); - while (! (e.findGreatestCommonDivisor (p) == one - && e.findGreatestCommonDivisor (q) == one)) - { - e.add (one); - } + while (! (e.findGreatestCommonDivisor (p) == one + && e.findGreatestCommonDivisor (q) == one)) + { + e.add (one); + } - return e; + return e; } void RSAKey::createKeyPair (RSAKey& publicKey, - RSAKey& privateKey, - const int numBits, - const int* randomSeeds, - const int numRandomSeeds) throw() + RSAKey& privateKey, + const int numBits, + const int* randomSeeds, + const int numRandomSeeds) throw() { - jassert (numBits > 16); // not much point using less than this.. + jassert (numBits > 16); // not much point using less than this.. - BitArray p (Primes::createProbablePrime (numBits / 2, 30, randomSeeds, numRandomSeeds)); - BitArray q (Primes::createProbablePrime (numBits - numBits / 2, 30, randomSeeds, numRandomSeeds)); + BitArray p (Primes::createProbablePrime (numBits / 2, 30, randomSeeds, numRandomSeeds)); + BitArray q (Primes::createProbablePrime (numBits - numBits / 2, 30, randomSeeds, numRandomSeeds)); - BitArray n (p); - n.multiplyBy (q); // n = pq + BitArray n (p); + n.multiplyBy (q); // n = pq - const BitArray one (1); - p.subtract (one); - q.subtract (one); + const BitArray one (1); + p.subtract (one); + q.subtract (one); - BitArray m (p); - m.multiplyBy (q); // m = (p - 1)(q - 1) + BitArray m (p); + m.multiplyBy (q); // m = (p - 1)(q - 1) - const BitArray e (findBestCommonDivisor (p, q)); + const BitArray e (findBestCommonDivisor (p, q)); - BitArray d (e); - d.inverseModulo (m); + BitArray d (e); + d.inverseModulo (m); - publicKey.part1 = e; - publicKey.part2 = n; + publicKey.part1 = e; + publicKey.part2 = n; - privateKey.part1 = d; - privateKey.part2 = n; + privateKey.part1 = d; + privateKey.part2 = n; } END_JUCE_NAMESPACE @@ -5308,246 +5081,246 @@ BEGIN_JUCE_NAMESPACE char InputStream::readByte() { - char temp = 0; - read (&temp, 1); - return temp; + char temp = 0; + read (&temp, 1); + return temp; } bool InputStream::readBool() { - return readByte() != 0; + return readByte() != 0; } short InputStream::readShort() { - char temp [2]; + char temp [2]; - if (read (temp, 2) == 2) - return (short) ByteOrder::littleEndianShort (temp); - else - return 0; + if (read (temp, 2) == 2) + return (short) ByteOrder::littleEndianShort (temp); + else + return 0; } short InputStream::readShortBigEndian() { - char temp [2]; + char temp [2]; - if (read (temp, 2) == 2) - return (short) ByteOrder::bigEndianShort (temp); - else - return 0; + if (read (temp, 2) == 2) + return (short) ByteOrder::bigEndianShort (temp); + else + return 0; } int InputStream::readInt() { - char temp [4]; + char temp [4]; - if (read (temp, 4) == 4) - return (int) ByteOrder::littleEndianInt (temp); - else - return 0; + if (read (temp, 4) == 4) + return (int) ByteOrder::littleEndianInt (temp); + else + return 0; } int InputStream::readIntBigEndian() { - char temp [4]; + char temp [4]; - if (read (temp, 4) == 4) - return (int) ByteOrder::bigEndianInt (temp); - else - return 0; + if (read (temp, 4) == 4) + return (int) ByteOrder::bigEndianInt (temp); + else + return 0; } int InputStream::readCompressedInt() { - const unsigned char sizeByte = readByte(); - if (sizeByte == 0) - return 0; + const unsigned char sizeByte = readByte(); + if (sizeByte == 0) + return 0; - const int numBytes = (sizeByte & 0x7f); - if (numBytes > 4) - { - jassertfalse // trying to read corrupt data - this method must only be used - // to read data that was written by OutputStream::writeCompressedInt() - return 0; - } + const int numBytes = (sizeByte & 0x7f); + if (numBytes > 4) + { + jassertfalse // trying to read corrupt data - this method must only be used + // to read data that was written by OutputStream::writeCompressedInt() + return 0; + } - char bytes[4] = { 0, 0, 0, 0 }; - if (read (bytes, numBytes) != numBytes) - return 0; + char bytes[4] = { 0, 0, 0, 0 }; + if (read (bytes, numBytes) != numBytes) + return 0; - const int num = (int) ByteOrder::littleEndianInt (bytes); - return (sizeByte >> 7) ? -num : num; + const int num = (int) ByteOrder::littleEndianInt (bytes); + return (sizeByte >> 7) ? -num : num; } int64 InputStream::readInt64() { - char temp [8]; + char temp [8]; - if (read (temp, 8) == 8) - return (int64) ByteOrder::swapIfBigEndian (*(uint64*) temp); - else - return 0; + if (read (temp, 8) == 8) + return (int64) ByteOrder::swapIfBigEndian (*(uint64*) temp); + else + return 0; } int64 InputStream::readInt64BigEndian() { - char temp [8]; + char temp [8]; - if (read (temp, 8) == 8) - return (int64) ByteOrder::swapIfLittleEndian (*(uint64*) temp); - else - return 0; + if (read (temp, 8) == 8) + return (int64) ByteOrder::swapIfLittleEndian (*(uint64*) temp); + else + return 0; } float InputStream::readFloat() { - union { int asInt; float asFloat; } n; - n.asInt = readInt(); - return n.asFloat; + union { int asInt; float asFloat; } n; + n.asInt = readInt(); + return n.asFloat; } float InputStream::readFloatBigEndian() { - union { int asInt; float asFloat; } n; - n.asInt = readIntBigEndian(); - return n.asFloat; + union { int asInt; float asFloat; } n; + n.asInt = readIntBigEndian(); + return n.asFloat; } double InputStream::readDouble() { - union { int64 asInt; double asDouble; } n; - n.asInt = readInt64(); - return n.asDouble; + union { int64 asInt; double asDouble; } n; + n.asInt = readInt64(); + return n.asDouble; } double InputStream::readDoubleBigEndian() { - union { int64 asInt; double asDouble; } n; - n.asInt = readInt64BigEndian(); - return n.asDouble; + union { int64 asInt; double asDouble; } n; + n.asInt = readInt64BigEndian(); + return n.asDouble; } const String InputStream::readString() { - MemoryBlock buffer (256); - uint8* data = (uint8*) buffer.getData(); - int i = 0; + MemoryBlock buffer (256); + uint8* data = (uint8*) buffer.getData(); + size_t i = 0; - while ((data[i] = readByte()) != 0) - { - if (++i >= buffer.getSize()) - { - buffer.setSize (buffer.getSize() + 512); - data = (uint8*) buffer.getData(); - } - } + while ((data[i] = readByte()) != 0) + { + if (++i >= buffer.getSize()) + { + buffer.setSize (buffer.getSize() + 512); + data = (uint8*) buffer.getData(); + } + } - return String::fromUTF8 (data, i); + return String::fromUTF8 (data, (int) i); } const String InputStream::readNextLine() { - MemoryBlock buffer (256); - uint8* data = (uint8*) buffer.getData(); - int i = 0; + MemoryBlock buffer (256); + uint8* data = (uint8*) buffer.getData(); + size_t i = 0; - while ((data[i] = readByte()) != 0) - { - if (data[i] == '\n') - break; + while ((data[i] = readByte()) != 0) + { + if (data[i] == '\n') + break; - if (data[i] == '\r') - { - const int64 lastPos = getPosition(); + if (data[i] == '\r') + { + const int64 lastPos = getPosition(); - if (readByte() != '\n') - setPosition (lastPos); + if (readByte() != '\n') + setPosition (lastPos); - break; - } + break; + } - if (++i >= buffer.getSize()) - { - buffer.setSize (buffer.getSize() + 512); - data = (uint8*) buffer.getData(); - } - } + if (++i >= buffer.getSize()) + { + buffer.setSize (buffer.getSize() + 512); + data = (uint8*) buffer.getData(); + } + } - return String::fromUTF8 (data, i); + return String::fromUTF8 (data, (int) i); } int InputStream::readIntoMemoryBlock (MemoryBlock& block, - int numBytes) + int numBytes) { - const int64 totalLength = getTotalLength(); + const int64 totalLength = getTotalLength(); - if (totalLength >= 0) - { - const int totalBytesRemaining = (int) jmin ((int64) 0x7fffffff, - totalLength - getPosition()); + if (totalLength >= 0) + { + const int totalBytesRemaining = (int) jmin ((int64) 0x7fffffff, + totalLength - getPosition()); - if (numBytes < 0) - numBytes = totalBytesRemaining; - else if (numBytes > 0) - numBytes = jmin (numBytes, totalBytesRemaining); - else - return 0; - } + if (numBytes < 0) + numBytes = totalBytesRemaining; + else if (numBytes > 0) + numBytes = jmin (numBytes, totalBytesRemaining); + else + return 0; + } - const int originalBlockSize = block.getSize(); - int totalBytesRead = 0; + const size_t originalBlockSize = block.getSize(); + int totalBytesRead = 0; - if (numBytes > 0) - { - // know how many bytes we want, so we can resize the block first.. - block.setSize (originalBlockSize + numBytes, false); - totalBytesRead = read (((char*) block.getData()) + originalBlockSize, numBytes); - } - else - { - // read until end of stram.. - const int chunkSize = 32768; + if (numBytes > 0) + { + // know how many bytes we want, so we can resize the block first.. + block.setSize (originalBlockSize + numBytes, false); + totalBytesRead = read (((char*) block.getData()) + originalBlockSize, numBytes); + } + else + { + // read until end of stram.. + const int chunkSize = 32768; - for (;;) - { - block.ensureSize (originalBlockSize + totalBytesRead + chunkSize, false); + for (;;) + { + block.ensureSize (originalBlockSize + totalBytesRead + chunkSize, false); - const int bytesJustIn = read (((char*) block.getData()) - + originalBlockSize - + totalBytesRead, - chunkSize); + const int bytesJustIn = read (((char*) block.getData()) + + originalBlockSize + + totalBytesRead, + chunkSize); - if (bytesJustIn == 0) - break; + if (bytesJustIn == 0) + break; - totalBytesRead += bytesJustIn; - } - } + totalBytesRead += bytesJustIn; + } + } - // trim off any excess left at the end - block.setSize (originalBlockSize + totalBytesRead, false); - return totalBytesRead; + // trim off any excess left at the end + block.setSize (originalBlockSize + totalBytesRead, false); + return totalBytesRead; } const String InputStream::readEntireStreamAsString() { - MemoryBlock mb; - const int size = readIntoMemoryBlock (mb); + MemoryBlock mb; + const int size = readIntoMemoryBlock (mb); - return String::createStringFromData ((const char*) mb.getData(), size); + return String::createStringFromData ((const char*) mb.getData(), size); } void InputStream::skipNextBytes (int64 numBytesToSkip) { - if (numBytesToSkip > 0) - { - const int skipBufferSize = (int) jmin (numBytesToSkip, (int64) 16384); - HeapBlock temp (skipBufferSize); + if (numBytesToSkip > 0) + { + const int skipBufferSize = (int) jmin (numBytesToSkip, (int64) 16384); + HeapBlock temp (skipBufferSize); - while (numBytesToSkip > 0 && ! isExhausted()) - numBytesToSkip -= read (temp, (int) jmin (numBytesToSkip, (int64) skipBufferSize)); - } + while (numBytesToSkip > 0 && ! isExhausted()) + numBytesToSkip -= read (temp, (int) jmin (numBytesToSkip, (int64) skipBufferSize)); + } } END_JUCE_NAMESPACE @@ -5563,288 +5336,288 @@ static VoidArray activeStreams; void juce_CheckForDanglingStreams() { - /* - It's always a bad idea to leak any object, but if you're leaking output - streams, then there's a good chance that you're failing to flush a file - to disk properly, which could result in corrupted data and other similar - nastiness.. - */ - jassert (activeStreams.size() == 0); + /* + It's always a bad idea to leak any object, but if you're leaking output + streams, then there's a good chance that you're failing to flush a file + to disk properly, which could result in corrupted data and other similar + nastiness.. + */ + jassert (activeStreams.size() == 0); }; #endif OutputStream::OutputStream() throw() { #if JUCE_DEBUG - activeStreamLock.enter(); - activeStreams.add (this); - activeStreamLock.exit(); + activeStreamLock.enter(); + activeStreams.add (this); + activeStreamLock.exit(); #endif } OutputStream::~OutputStream() { #if JUCE_DEBUG - activeStreamLock.enter(); - activeStreams.removeValue (this); - activeStreamLock.exit(); + activeStreamLock.enter(); + activeStreams.removeValue (this); + activeStreamLock.exit(); #endif } void OutputStream::writeBool (bool b) { - writeByte ((b) ? (char) 1 - : (char) 0); + writeByte ((b) ? (char) 1 + : (char) 0); } void OutputStream::writeByte (char byte) { - write (&byte, 1); + write (&byte, 1); } void OutputStream::writeShort (short value) { - const unsigned short v = ByteOrder::swapIfBigEndian ((unsigned short) value); - write (&v, 2); + const unsigned short v = ByteOrder::swapIfBigEndian ((unsigned short) value); + write (&v, 2); } void OutputStream::writeShortBigEndian (short value) { - const unsigned short v = ByteOrder::swapIfLittleEndian ((unsigned short) value); - write (&v, 2); + const unsigned short v = ByteOrder::swapIfLittleEndian ((unsigned short) value); + write (&v, 2); } void OutputStream::writeInt (int value) { - const unsigned int v = ByteOrder::swapIfBigEndian ((unsigned int) value); - write (&v, 4); + const unsigned int v = ByteOrder::swapIfBigEndian ((unsigned int) value); + write (&v, 4); } void OutputStream::writeIntBigEndian (int value) { - const unsigned int v = ByteOrder::swapIfLittleEndian ((unsigned int) value); - write (&v, 4); + const unsigned int v = ByteOrder::swapIfLittleEndian ((unsigned int) value); + write (&v, 4); } void OutputStream::writeCompressedInt (int value) { - unsigned int un = (value < 0) ? (unsigned int) -value - : (unsigned int) value; + unsigned int un = (value < 0) ? (unsigned int) -value + : (unsigned int) value; - uint8 data[5]; - int num = 0; + uint8 data[5]; + int num = 0; - while (un > 0) - { - data[++num] = (uint8) un; - un >>= 8; - } + while (un > 0) + { + data[++num] = (uint8) un; + un >>= 8; + } - data[0] = (uint8) num; + data[0] = (uint8) num; - if (value < 0) - data[0] |= 0x80; + if (value < 0) + data[0] |= 0x80; - write (data, num + 1); + write (data, num + 1); } void OutputStream::writeInt64 (int64 value) { - const uint64 v = ByteOrder::swapIfBigEndian ((uint64) value); - write (&v, 8); + const uint64 v = ByteOrder::swapIfBigEndian ((uint64) value); + write (&v, 8); } void OutputStream::writeInt64BigEndian (int64 value) { - const uint64 v = ByteOrder::swapIfLittleEndian ((uint64) value); - write (&v, 8); + const uint64 v = ByteOrder::swapIfLittleEndian ((uint64) value); + write (&v, 8); } void OutputStream::writeFloat (float value) { - union { int asInt; float asFloat; } n; - n.asFloat = value; - writeInt (n.asInt); + union { int asInt; float asFloat; } n; + n.asFloat = value; + writeInt (n.asInt); } void OutputStream::writeFloatBigEndian (float value) { - union { int asInt; float asFloat; } n; - n.asFloat = value; - writeIntBigEndian (n.asInt); + union { int asInt; float asFloat; } n; + n.asFloat = value; + writeIntBigEndian (n.asInt); } void OutputStream::writeDouble (double value) { - union { int64 asInt; double asDouble; } n; - n.asDouble = value; - writeInt64 (n.asInt); + union { int64 asInt; double asDouble; } n; + n.asDouble = value; + writeInt64 (n.asInt); } void OutputStream::writeDoubleBigEndian (double value) { - union { int64 asInt; double asDouble; } n; - n.asDouble = value; - writeInt64BigEndian (n.asInt); + union { int64 asInt; double asDouble; } n; + n.asDouble = value; + writeInt64BigEndian (n.asInt); } void OutputStream::writeString (const String& text) { - const int numBytes = text.copyToUTF8 (0); - HeapBlock temp (numBytes); + const int numBytes = text.copyToUTF8 (0); + HeapBlock temp (numBytes); - text.copyToUTF8 (temp); - write (temp, numBytes); // (numBytes includes the terminating null). + text.copyToUTF8 (temp); + write (temp, numBytes); // (numBytes includes the terminating null). } void OutputStream::printf (const char* pf, ...) { - unsigned int bufSize = 256; - HeapBlock buf (bufSize); + unsigned int bufSize = 256; + HeapBlock buf (bufSize); - for (;;) - { - va_list list; - va_start (list, pf); + for (;;) + { + va_list list; + va_start (list, pf); - const int num = CharacterFunctions::vprintf (buf, bufSize, pf, list); + const int num = CharacterFunctions::vprintf (buf, bufSize, pf, list); - va_end (list); + va_end (list); - if (num > 0) - { - write (buf, num); - break; - } - else if (num == 0) - { - break; - } + if (num > 0) + { + write (buf, num); + break; + } + else if (num == 0) + { + break; + } - bufSize += 256; - buf.malloc (bufSize); - } + bufSize += 256; + buf.malloc (bufSize); + } } OutputStream& OutputStream::operator<< (const int number) { - const String s (number); - write ((const char*) s, s.length()); - return *this; + const String s (number); + write ((const char*) s, s.length()); + return *this; } OutputStream& OutputStream::operator<< (const double number) { - const String s (number); - write ((const char*) s, s.length()); - return *this; + const String s (number); + write ((const char*) s, s.length()); + return *this; } OutputStream& OutputStream::operator<< (const char character) { - writeByte (character); - return *this; + writeByte (character); + return *this; } OutputStream& OutputStream::operator<< (const char* const text) { - write (text, (int) strlen (text)); - return *this; + write (text, (int) strlen (text)); + return *this; } OutputStream& OutputStream::operator<< (const juce_wchar* const text) { - const String s (text); - write ((const char*) s, s.length()); - return *this; + const String s (text); + write ((const char*) s, s.length()); + return *this; } OutputStream& OutputStream::operator<< (const String& text) { - write ((const char*) text, - text.length()); + write ((const char*) text, + text.length()); - return *this; + return *this; } void OutputStream::writeText (const String& text, - const bool asUnicode, - const bool writeUnicodeHeaderBytes) + const bool asUnicode, + const bool writeUnicodeHeaderBytes) { - if (asUnicode) - { - if (writeUnicodeHeaderBytes) - write ("\x0ff\x0fe", 2); + if (asUnicode) + { + if (writeUnicodeHeaderBytes) + write ("\x0ff\x0fe", 2); - const juce_wchar* src = (const juce_wchar*) text; - bool lastCharWasReturn = false; + const juce_wchar* src = (const juce_wchar*) text; + bool lastCharWasReturn = false; - while (*src != 0) - { - if (*src == L'\n' && ! lastCharWasReturn) - writeShort ((short) L'\r'); + while (*src != 0) + { + if (*src == L'\n' && ! lastCharWasReturn) + writeShort ((short) L'\r'); - lastCharWasReturn = (*src == L'\r'); - writeShort ((short) *src++); - } - } - else - { - const char* src = (const char*) text; - const char* t = src; + lastCharWasReturn = (*src == L'\r'); + writeShort ((short) *src++); + } + } + else + { + const char* src = (const char*) text; + const char* t = src; - for (;;) - { - if (*t == '\n') - { - if (t > src) - write (src, (int) (t - src)); + for (;;) + { + if (*t == '\n') + { + if (t > src) + write (src, (int) (t - src)); - write ("\r\n", 2); - src = t + 1; - } - else if (*t == '\r') - { - if (t[1] == '\n') - ++t; - } - else if (*t == 0) - { - if (t > src) - write (src, (int) (t - src)); + write ("\r\n", 2); + src = t + 1; + } + else if (*t == '\r') + { + if (t[1] == '\n') + ++t; + } + else if (*t == 0) + { + if (t > src) + write (src, (int) (t - src)); - break; - } + break; + } - ++t; - } - } + ++t; + } + } } int OutputStream::writeFromInputStream (InputStream& source, - int numBytesToWrite) + int numBytesToWrite) { - if (numBytesToWrite < 0) - numBytesToWrite = 0x7fffffff; + if (numBytesToWrite < 0) + numBytesToWrite = 0x7fffffff; - int numWritten = 0; + int numWritten = 0; - while (numBytesToWrite > 0 && ! source.isExhausted()) - { - char buffer [8192]; + while (numBytesToWrite > 0 && ! source.isExhausted()) + { + char buffer [8192]; - const int num = source.read (buffer, jmin (numBytesToWrite, sizeof (buffer))); + const int num = source.read (buffer, (int) jmin ((size_t) numBytesToWrite, sizeof (buffer))); - if (num == 0) - break; + if (num == 0) + break; - write (buffer, num); + write (buffer, num); - numBytesToWrite -= num; - numWritten += num; - } + numBytesToWrite -= num; + numWritten += num; + } - return numWritten; + return numWritten; } END_JUCE_NAMESPACE @@ -5855,76 +5628,76 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile, - bool* isDirectory, bool* isHidden, int64* fileSize, - Time* modTime, Time* creationTime, bool* isReadOnly); + bool* isDirectory, bool* isHidden, int64* fileSize, + Time* modTime, Time* creationTime, bool* isReadOnly); bool juce_findFileNext (void* handle, String& resultFile, - bool* isDirectory, bool* isHidden, int64* fileSize, - Time* modTime, Time* creationTime, bool* isReadOnly); + bool* isDirectory, bool* isHidden, int64* fileSize, + Time* modTime, Time* creationTime, bool* isReadOnly); void juce_findFileClose (void* handle); DirectoryIterator::DirectoryIterator (const File& directory, - bool isRecursive, - const String& wc, - const int whatToLookFor_) + bool isRecursive, + const String& wc, + const int whatToLookFor_) : wildCard (wc), - index (-1), - whatToLookFor (whatToLookFor_) + index (-1), + whatToLookFor (whatToLookFor_) { - // you have to specify the type of files you're looking for! - jassert ((whatToLookFor_ & (File::findFiles | File::findDirectories)) != 0); - jassert (whatToLookFor_ > 0 && whatToLookFor_ <= 7); + // you have to specify the type of files you're looking for! + jassert ((whatToLookFor_ & (File::findFiles | File::findDirectories)) != 0); + jassert (whatToLookFor_ > 0 && whatToLookFor_ <= 7); - String path (directory.getFullPathName()); - if (! path.endsWithChar (File::separator)) - path += File::separator; + String path (directory.getFullPathName()); + if (! path.endsWithChar (File::separator)) + path += File::separator; - String filename; - bool isDirectory, isHidden; + String filename; + bool isDirectory, isHidden; - void* const handle = juce_findFileStart (path, - isRecursive ? T("*") : wc, - filename, &isDirectory, &isHidden, 0, 0, 0, 0); + void* const handle = juce_findFileStart (path, + isRecursive ? T("*") : wc, + filename, &isDirectory, &isHidden, 0, 0, 0, 0); - if (handle != 0) - { - do - { - if (! filename.containsOnly (T("."))) - { - bool addToList = false; + if (handle != 0) + { + do + { + if (! filename.containsOnly (T("."))) + { + bool addToList = false; - if (isDirectory) - { - if (isRecursive - && ((whatToLookFor_ & File::ignoreHiddenFiles) == 0 - || ! isHidden)) - { - dirsFound.add (new File (path + filename, 0)); - } + if (isDirectory) + { + if (isRecursive + && ((whatToLookFor_ & File::ignoreHiddenFiles) == 0 + || ! isHidden)) + { + dirsFound.add (new File (path + filename, 0)); + } - addToList = (whatToLookFor_ & File::findDirectories) != 0; - } - else - { - addToList = (whatToLookFor_ & File::findFiles) != 0; - } + addToList = (whatToLookFor_ & File::findDirectories) != 0; + } + else + { + addToList = (whatToLookFor_ & File::findFiles) != 0; + } - // if it's recursive, we're not relying on the OS iterator - // to do the wildcard match, so do it now.. - if (isRecursive && addToList) - addToList = filename.matchesWildcard (wc, true); + // if it's recursive, we're not relying on the OS iterator + // to do the wildcard match, so do it now.. + if (isRecursive && addToList) + addToList = filename.matchesWildcard (wc, true); - if (addToList && (whatToLookFor_ & File::ignoreHiddenFiles) != 0) - addToList = ! isHidden; + if (addToList && (whatToLookFor_ & File::ignoreHiddenFiles) != 0) + addToList = ! isHidden; - if (addToList) - filesFound.add (new File (path + filename, 0)); - } + if (addToList) + filesFound.add (new File (path + filename, 0)); + } - } while (juce_findFileNext (handle, filename, &isDirectory, &isHidden, 0, 0, 0, 0)); + } while (juce_findFileNext (handle, filename, &isDirectory, &isHidden, 0, 0, 0, 0)); - juce_findFileClose (handle); - } + juce_findFileClose (handle); + } } DirectoryIterator::~DirectoryIterator() @@ -5933,53 +5706,53 @@ DirectoryIterator::~DirectoryIterator() bool DirectoryIterator::next() { - if (subIterator != 0) - { - if (subIterator->next()) - return true; + if (subIterator != 0) + { + if (subIterator->next()) + return true; - subIterator = 0; - } + subIterator = 0; + } - if (index >= filesFound.size() + dirsFound.size() - 1) - return false; + if (index >= filesFound.size() + dirsFound.size() - 1) + return false; - ++index; + ++index; - if (index >= filesFound.size()) - { - subIterator = new DirectoryIterator (*(dirsFound [index - filesFound.size()]), - true, wildCard, whatToLookFor); - return next(); - } + if (index >= filesFound.size()) + { + subIterator = new DirectoryIterator (*(dirsFound [index - filesFound.size()]), + true, wildCard, whatToLookFor); + return next(); + } - return true; + return true; } const File DirectoryIterator::getFile() const { - if (subIterator != 0) - return subIterator->getFile(); + if (subIterator != 0) + return subIterator->getFile(); - const File* const f = filesFound [index]; + const File* const f = filesFound [index]; - return (f != 0) ? *f - : File::nonexistent; + return (f != 0) ? *f + : File::nonexistent; } float DirectoryIterator::getEstimatedProgress() const { - if (filesFound.size() + dirsFound.size() == 0) - { - return 0.0f; - } - else - { - const float detailedIndex = (subIterator != 0) ? index + subIterator->getEstimatedProgress() - : (float) index; + if (filesFound.size() + dirsFound.size() == 0) + { + return 0.0f; + } + else + { + const float detailedIndex = (subIterator != 0) ? index + subIterator->getEstimatedProgress() + : (float) index; - return detailedIndex / (filesFound.size() + dirsFound.size()); - } + return detailedIndex / (filesFound.size() + dirsFound.size()); + } } END_JUCE_NAMESPACE @@ -6034,139 +5807,139 @@ const String juce_getVolumeLabel (const String& filenameOnVolume, int& volumeSer // juce_firstResultFile gets the name of the file (not the whole pathname) and // the other pointers, if non-null, are set based on the properties of the file. void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile, - bool* isDirectory, bool* isHidden, int64* fileSize, Time* modTime, - Time* creationTime, bool* isReadOnly); + bool* isDirectory, bool* isHidden, int64* fileSize, Time* modTime, + Time* creationTime, bool* isReadOnly); // returns false when no more files are found bool juce_findFileNext (void* handle, String& resultFile, - bool* isDirectory, bool* isHidden, int64* fileSize, - Time* modTime, Time* creationTime, bool* isReadOnly); + bool* isDirectory, bool* isHidden, int64* fileSize, + Time* modTime, Time* creationTime, bool* isReadOnly); void juce_findFileClose (void* handle); static const String juce_addTrailingSeparator (const String& path) { - return path.endsWithChar (File::separator) ? path - : path + File::separator; + return path.endsWithChar (File::separator) ? path + : path + File::separator; } static const String parseAbsolutePath (String path) { - if (path.isEmpty()) - return String::empty; + if (path.isEmpty()) + return String::empty; #if JUCE_WINDOWS - // Windows.. - path = path.replaceCharacter (T('/'), T('\\')); + // Windows.. + path = path.replaceCharacter (T('/'), T('\\')); - if (path.startsWithChar (File::separator)) - { - if (path[1] != File::separator) - { - jassertfalse // using a filename that starts with a slash is a bit dodgy on - // Windows, because it needs a drive letter, which in this case - // we'll take from the CWD.. but this is a bit of an assumption that - // could be wrong.. + if (path.startsWithChar (File::separator)) + { + if (path[1] != File::separator) + { + jassertfalse // using a filename that starts with a slash is a bit dodgy on + // Windows, because it needs a drive letter, which in this case + // we'll take from the CWD.. but this is a bit of an assumption that + // could be wrong.. - path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path; - } - } - else if (path.indexOfChar (T(':')) < 0) - { - if (path.isEmpty()) - return String::empty; + path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path; + } + } + else if (path.indexOfChar (T(':')) < 0) + { + if (path.isEmpty()) + return String::empty; - jassertfalse // using a partial filename is a bad way to initialise a file, because - // we don't know what directory to put it in. - // Here we'll assume it's in the CWD, but this might not be what was - // intended.. + jassertfalse // using a partial filename is a bad way to initialise a file, because + // we don't know what directory to put it in. + // Here we'll assume it's in the CWD, but this might not be what was + // intended.. - return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName(); - } + return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName(); + } #else - // Mac or Linux.. - path = path.replaceCharacter (T('\\'), T('/')); + // Mac or Linux.. + path = path.replaceCharacter (T('\\'), T('/')); - if (path.startsWithChar (T('~'))) - { - const char* homeDir = 0; + if (path.startsWithChar (T('~'))) + { + const char* homeDir = 0; - if (path[1] == File::separator || path[1] == 0) - { - // expand a name of the form "~/abc" - path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName() - + path.substring (1); - } - else - { - // expand a name of type "~dave/abc" - const String userName (path.substring (1) - .upToFirstOccurrenceOf (T("/"), false, false)); + if (path[1] == File::separator || path[1] == 0) + { + // expand a name of the form "~/abc" + path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName() + + path.substring (1); + } + else + { + // expand a name of type "~dave/abc" + const String userName (path.substring (1) + .upToFirstOccurrenceOf (T("/"), false, false)); - struct passwd* const pw = getpwnam (userName); - if (pw != 0) - { - String home (homeDir); + struct passwd* const pw = getpwnam (userName); + if (pw != 0) + { + String home (homeDir); - if (home.endsWithChar (File::separator)) - home [home.length() - 1] = 0; + if (home.endsWithChar (File::separator)) + home [home.length() - 1] = 0; - path = String (pw->pw_dir) - + path.substring (userName.length()); - } - } - } - else if (! path.startsWithChar (File::separator)) - { - while (path.startsWith (T("./"))) - path = path.substring (2); + path = String (pw->pw_dir) + + path.substring (userName.length()); + } + } + } + else if (! path.startsWithChar (File::separator)) + { + while (path.startsWith (T("./"))) + path = path.substring (2); - if (path.isEmpty()) - return String::empty; + if (path.isEmpty()) + return String::empty; - jassertfalse // using a partial filename is a bad way to initialise a file, because - // we don't know what directory to put it in. - // Here we'll assume it's in the CWD, but this might not be what was - // intended.. + jassertfalse // using a partial filename is a bad way to initialise a file, because + // we don't know what directory to put it in. + // Here we'll assume it's in the CWD, but this might not be what was + // intended.. - return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName(); - } + return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName(); + } #endif - int len = path.length(); - while (--len > 0 && path [len] == File::separator) - path [len] = 0; + int len = path.length(); + while (--len > 0 && path [len] == File::separator) + path [len] = 0; - return path; + return path; } const File File::nonexistent; File::File (const String& fullPathName) - : fullPath (parseAbsolutePath (fullPathName)) + : fullPath (parseAbsolutePath (fullPathName)) { } File::File (const String& path, int) - : fullPath (path) + : fullPath (path) { } File::File (const File& other) - : fullPath (other.fullPath) + : fullPath (other.fullPath) { } const File& File::operator= (const String& newPath) { - fullPath = parseAbsolutePath (newPath); - return *this; + fullPath = parseAbsolutePath (newPath); + return *this; } const File& File::operator= (const File& other) { - fullPath = other.fullPath; - return *this; + fullPath = other.fullPath; + return *this; } #if JUCE_LINUX @@ -6176,911 +5949,900 @@ const File& File::operator= (const File& other) bool File::areFileNamesCaseSensitive() { #if NAMES_ARE_CASE_SENSITIVE - return true; + return true; #else - return false; + return false; #endif } bool File::operator== (const File& other) const { - // case-insensitive on Windows, but not on linux. + // case-insensitive on Windows, but not on linux. #if NAMES_ARE_CASE_SENSITIVE - return fullPath == other.fullPath; + return fullPath == other.fullPath; #else - return fullPath.equalsIgnoreCase (other.fullPath); + return fullPath.equalsIgnoreCase (other.fullPath); #endif } bool File::operator!= (const File& other) const { - return ! operator== (other); + return ! operator== (other); } bool File::exists() const { - return juce_fileExists (fullPath, false); + return juce_fileExists (fullPath, false); } bool File::existsAsFile() const { - return juce_fileExists (fullPath, true); + return juce_fileExists (fullPath, true); } bool File::isDirectory() const { - return juce_isDirectory (fullPath); + return juce_isDirectory (fullPath); } bool File::hasWriteAccess() const { - if (exists()) - return juce_canWriteToFile (fullPath); + if (exists()) + return juce_canWriteToFile (fullPath); #if ! JUCE_WINDOWS - else if ((! isDirectory()) && fullPath.containsChar (separator)) - return getParentDirectory().hasWriteAccess(); - else - return false; + else if ((! isDirectory()) && fullPath.containsChar (separator)) + return getParentDirectory().hasWriteAccess(); + else + return false; #else - // on windows, it seems that even read-only directories can still be written into, - // so checking the parent directory's permissions would return the wrong result.. - else - return true; + // on windows, it seems that even read-only directories can still be written into, + // so checking the parent directory's permissions would return the wrong result.. + else + return true; #endif } bool File::setReadOnly (const bool shouldBeReadOnly, - const bool applyRecursively) const + const bool applyRecursively) const { - bool worked = true; + bool worked = true; - if (applyRecursively && isDirectory()) - { - OwnedArray subFiles; - findChildFiles (subFiles, File::findFilesAndDirectories, false); + if (applyRecursively && isDirectory()) + { + OwnedArray subFiles; + findChildFiles (subFiles, File::findFilesAndDirectories, false); - for (int i = subFiles.size(); --i >= 0;) - worked = subFiles[i]->setReadOnly (shouldBeReadOnly, true) && worked; - } + for (int i = subFiles.size(); --i >= 0;) + worked = subFiles[i]->setReadOnly (shouldBeReadOnly, true) && worked; + } - return juce_setFileReadOnly (fullPath, shouldBeReadOnly) && worked; + return juce_setFileReadOnly (fullPath, shouldBeReadOnly) && worked; } bool File::deleteFile() const { - return (! exists()) - || juce_deleteFile (fullPath); + return (! exists()) + || juce_deleteFile (fullPath); } bool File::deleteRecursively() const { - bool worked = true; + bool worked = true; - if (isDirectory()) - { - OwnedArray subFiles; - findChildFiles (subFiles, File::findFilesAndDirectories, false); + if (isDirectory()) + { + OwnedArray subFiles; + findChildFiles (subFiles, File::findFilesAndDirectories, false); - for (int i = subFiles.size(); --i >= 0;) - worked = subFiles[i]->deleteRecursively() && worked; - } + for (int i = subFiles.size(); --i >= 0;) + worked = subFiles[i]->deleteRecursively() && worked; + } - return deleteFile() && worked; + return deleteFile() && worked; } bool File::moveFileTo (const File& newFile) const { - if (newFile.fullPath == fullPath) - return true; + if (newFile.fullPath == fullPath) + return true; #if ! NAMES_ARE_CASE_SENSITIVE - if (*this != newFile) + if (*this != newFile) #endif - if (! newFile.deleteFile()) - return false; + if (! newFile.deleteFile()) + return false; - return juce_moveFile (fullPath, newFile.fullPath); + return juce_moveFile (fullPath, newFile.fullPath); } bool File::copyFileTo (const File& newFile) const { - if (*this == newFile) - return true; + if (*this == newFile) + return true; - if (! newFile.deleteFile()) - return false; + if (! newFile.deleteFile()) + return false; - return juce_copyFile (fullPath, newFile.fullPath); + return juce_copyFile (fullPath, newFile.fullPath); } bool File::copyDirectoryTo (const File& newDirectory) const { - if (isDirectory() && newDirectory.createDirectory()) - { - OwnedArray subFiles; - findChildFiles (subFiles, File::findFiles, false); + if (isDirectory() && newDirectory.createDirectory()) + { + OwnedArray subFiles; + findChildFiles (subFiles, File::findFiles, false); - int i; - for (i = 0; i < subFiles.size(); ++i) - if (! subFiles[i]->copyFileTo (newDirectory.getChildFile (subFiles[i]->getFileName()))) - return false; + int i; + for (i = 0; i < subFiles.size(); ++i) + if (! subFiles[i]->copyFileTo (newDirectory.getChildFile (subFiles[i]->getFileName()))) + return false; - subFiles.clear(); - findChildFiles (subFiles, File::findDirectories, false); + subFiles.clear(); + findChildFiles (subFiles, File::findDirectories, false); - for (i = 0; i < subFiles.size(); ++i) - if (! subFiles[i]->copyDirectoryTo (newDirectory.getChildFile (subFiles[i]->getFileName()))) - return false; + for (i = 0; i < subFiles.size(); ++i) + if (! subFiles[i]->copyDirectoryTo (newDirectory.getChildFile (subFiles[i]->getFileName()))) + return false; - return true; - } + return true; + } - return false; + return false; } const String File::getPathUpToLastSlash() const { - const int lastSlash = fullPath.lastIndexOfChar (separator); + const int lastSlash = fullPath.lastIndexOfChar (separator); - if (lastSlash > 0) - return fullPath.substring (0, lastSlash); - else if (lastSlash == 0) - return separatorString; - else - return fullPath; + if (lastSlash > 0) + return fullPath.substring (0, lastSlash); + else if (lastSlash == 0) + return separatorString; + else + return fullPath; } const File File::getParentDirectory() const { - return File (getPathUpToLastSlash()); + return File (getPathUpToLastSlash()); } const String File::getFileName() const { - return fullPath.substring (fullPath.lastIndexOfChar (separator) + 1); + return fullPath.substring (fullPath.lastIndexOfChar (separator) + 1); } int File::hashCode() const { - return fullPath.hashCode(); + return fullPath.hashCode(); } int64 File::hashCode64() const { - return fullPath.hashCode64(); + return fullPath.hashCode64(); } const String File::getFileNameWithoutExtension() const { - const int lastSlash = fullPath.lastIndexOfChar (separator) + 1; - const int lastDot = fullPath.lastIndexOfChar (T('.')); + const int lastSlash = fullPath.lastIndexOfChar (separator) + 1; + const int lastDot = fullPath.lastIndexOfChar (T('.')); - if (lastDot > lastSlash) - return fullPath.substring (lastSlash, lastDot); - else - return fullPath.substring (lastSlash); + if (lastDot > lastSlash) + return fullPath.substring (lastSlash, lastDot); + else + return fullPath.substring (lastSlash); } bool File::isAChildOf (const File& potentialParent) const { - const String ourPath (getPathUpToLastSlash()); + const String ourPath (getPathUpToLastSlash()); #if NAMES_ARE_CASE_SENSITIVE - if (potentialParent.fullPath == ourPath) + if (potentialParent.fullPath == ourPath) #else - if (potentialParent.fullPath.equalsIgnoreCase (ourPath)) + if (potentialParent.fullPath.equalsIgnoreCase (ourPath)) #endif - { - return true; - } - else if (potentialParent.fullPath.length() >= ourPath.length()) - { - return false; - } - else - { - return getParentDirectory().isAChildOf (potentialParent); - } + { + return true; + } + else if (potentialParent.fullPath.length() >= ourPath.length()) + { + return false; + } + else + { + return getParentDirectory().isAChildOf (potentialParent); + } } bool File::isAbsolutePath (const String& path) { - return path.startsWithChar (T('/')) || path.startsWithChar (T('\\')) + return path.startsWithChar (T('/')) || path.startsWithChar (T('\\')) #if JUCE_WINDOWS - || (path.isNotEmpty() && ((const String&) path)[1] == T(':')); + || (path.isNotEmpty() && ((const String&) path)[1] == T(':')); #else - || path.startsWithChar (T('~')); + || path.startsWithChar (T('~')); #endif } const File File::getChildFile (String relativePath) const { - if (isAbsolutePath (relativePath)) - { - // the path is really absolute.. - return File (relativePath); - } - else - { - // it's relative, so remove any ../ or ./ bits at the start. - String path (fullPath); + if (isAbsolutePath (relativePath)) + { + // the path is really absolute.. + return File (relativePath); + } + else + { + // it's relative, so remove any ../ or ./ bits at the start. + String path (fullPath); - if (relativePath[0] == T('.')) - { + if (relativePath[0] == T('.')) + { #if JUCE_WINDOWS - relativePath = relativePath.replaceCharacter (T('/'), T('\\')).trimStart(); + relativePath = relativePath.replaceCharacter (T('/'), T('\\')).trimStart(); #else - relativePath = relativePath.replaceCharacter (T('\\'), T('/')).trimStart(); + relativePath = relativePath.replaceCharacter (T('\\'), T('/')).trimStart(); #endif - while (relativePath[0] == T('.')) - { - if (relativePath[1] == T('.')) - { - if (relativePath [2] == 0 || relativePath[2] == separator) - { - const int lastSlash = path.lastIndexOfChar (separator); - if (lastSlash >= 0) - path = path.substring (0, lastSlash); + while (relativePath[0] == T('.')) + { + if (relativePath[1] == T('.')) + { + if (relativePath [2] == 0 || relativePath[2] == separator) + { + const int lastSlash = path.lastIndexOfChar (separator); + if (lastSlash >= 0) + path = path.substring (0, lastSlash); - relativePath = relativePath.substring (3); - } - else - { - break; - } - } - else if (relativePath[1] == separator) - { - relativePath = relativePath.substring (2); - } - else - { - break; - } - } - } + relativePath = relativePath.substring (3); + } + else + { + break; + } + } + else if (relativePath[1] == separator) + { + relativePath = relativePath.substring (2); + } + else + { + break; + } + } + } - return File (juce_addTrailingSeparator (path) + relativePath); - } + return File (juce_addTrailingSeparator (path) + relativePath); + } } const File File::getSiblingFile (const String& fileName) const { - return getParentDirectory().getChildFile (fileName); + return getParentDirectory().getChildFile (fileName); } int64 File::getSize() const { - return juce_getFileSize (fullPath); + return juce_getFileSize (fullPath); } const String File::descriptionOfSizeInBytes (const int64 bytes) { - if (bytes == 1) - { - return "1 byte"; - } - else if (bytes < 1024) - { - return String ((int) bytes) + " bytes"; - } - else if (bytes < 1024 * 1024) - { - return String (bytes / 1024.0, 1) + " KB"; - } - else if (bytes < 1024 * 1024 * 1024) - { - return String (bytes / (1024.0 * 1024.0), 1) + " MB"; - } - else - { - return String (bytes / (1024.0 * 1024.0 * 1024.0), 1) + " GB"; - } + if (bytes == 1) + { + return "1 byte"; + } + else if (bytes < 1024) + { + return String ((int) bytes) + " bytes"; + } + else if (bytes < 1024 * 1024) + { + return String (bytes / 1024.0, 1) + " KB"; + } + else if (bytes < 1024 * 1024 * 1024) + { + return String (bytes / (1024.0 * 1024.0), 1) + " MB"; + } + else + { + return String (bytes / (1024.0 * 1024.0 * 1024.0), 1) + " GB"; + } } bool File::create() const { - if (! exists()) - { - const File parentDir (getParentDirectory()); + if (! exists()) + { + const File parentDir (getParentDirectory()); - if (parentDir == *this || ! parentDir.createDirectory()) - return false; + if (parentDir == *this || ! parentDir.createDirectory()) + return false; - void* const fh = juce_fileOpen (fullPath, true); + void* const fh = juce_fileOpen (fullPath, true); - if (fh == 0) - return false; + if (fh == 0) + return false; - juce_fileClose (fh); - } + juce_fileClose (fh); + } - return true; + return true; } bool File::createDirectory() const { - if (! isDirectory()) - { - const File parentDir (getParentDirectory()); + if (! isDirectory()) + { + const File parentDir (getParentDirectory()); - if (parentDir == *this || ! parentDir.createDirectory()) - return false; + if (parentDir == *this || ! parentDir.createDirectory()) + return false; - String dir (fullPath); + String dir (fullPath); - while (dir.endsWithChar (separator)) - dir [dir.length() - 1] = 0; + while (dir.endsWithChar (separator)) + dir [dir.length() - 1] = 0; - juce_createDirectory (dir); + juce_createDirectory (dir); - return isDirectory(); - } + return isDirectory(); + } - return true; + return true; } const Time File::getCreationTime() const { - int64 m, a, c; - juce_getFileTimes (fullPath, m, a, c); - return Time (c); + int64 m, a, c; + juce_getFileTimes (fullPath, m, a, c); + return Time (c); } bool File::setCreationTime (const Time& t) const { - return juce_setFileTimes (fullPath, 0, 0, t.toMilliseconds()); + return juce_setFileTimes (fullPath, 0, 0, t.toMilliseconds()); } const Time File::getLastModificationTime() const { - int64 m, a, c; - juce_getFileTimes (fullPath, m, a, c); - return Time (m); + int64 m, a, c; + juce_getFileTimes (fullPath, m, a, c); + return Time (m); } bool File::setLastModificationTime (const Time& t) const { - return juce_setFileTimes (fullPath, t.toMilliseconds(), 0, 0); + return juce_setFileTimes (fullPath, t.toMilliseconds(), 0, 0); } const Time File::getLastAccessTime() const { - int64 m, a, c; - juce_getFileTimes (fullPath, m, a, c); - return Time (a); + int64 m, a, c; + juce_getFileTimes (fullPath, m, a, c); + return Time (a); } bool File::setLastAccessTime (const Time& t) const { - return juce_setFileTimes (fullPath, 0, t.toMilliseconds(), 0); + return juce_setFileTimes (fullPath, 0, t.toMilliseconds(), 0); } bool File::loadFileAsData (MemoryBlock& destBlock) const { - if (! existsAsFile()) - return false; + if (! existsAsFile()) + return false; - FileInputStream in (*this); - return getSize() == in.readIntoMemoryBlock (destBlock); + FileInputStream in (*this); + return getSize() == in.readIntoMemoryBlock (destBlock); } const String File::loadFileAsString() const { - if (! existsAsFile()) - return String::empty; + if (! existsAsFile()) + return String::empty; - FileInputStream in (*this); - return in.readEntireStreamAsString(); + FileInputStream in (*this); + return in.readEntireStreamAsString(); } static inline bool fileTypeMatches (const int whatToLookFor, - const bool isDir, - const bool isHidden) + const bool isDir, + const bool isHidden) { - return (whatToLookFor & (isDir ? File::findDirectories - : File::findFiles)) != 0 - && ((! isHidden) - || (whatToLookFor & File::ignoreHiddenFiles) == 0); + return (whatToLookFor & (isDir ? File::findDirectories + : File::findFiles)) != 0 + && ((! isHidden) + || (whatToLookFor & File::ignoreHiddenFiles) == 0); } int File::findChildFiles (OwnedArray& results, - const int whatToLookFor, - const bool searchRecursively, - const String& wildCardPattern) const + const int whatToLookFor, + const bool searchRecursively, + const String& wildCardPattern) const { - // you have to specify the type of files you're looking for! - jassert ((whatToLookFor & (findFiles | findDirectories)) != 0); + // you have to specify the type of files you're looking for! + jassert ((whatToLookFor & (findFiles | findDirectories)) != 0); - int total = 0; + int total = 0; - // find child files or directories in this directory first.. - if (isDirectory()) - { - const String path (juce_addTrailingSeparator (fullPath)); + // find child files or directories in this directory first.. + if (isDirectory()) + { + const String path (juce_addTrailingSeparator (fullPath)); - String filename; - bool itemIsDirectory, itemIsHidden; + String filename; + bool itemIsDirectory, itemIsHidden; - void* const handle = juce_findFileStart (path, wildCardPattern, filename, - &itemIsDirectory, &itemIsHidden, - 0, 0, 0, 0); + void* const handle = juce_findFileStart (path, wildCardPattern, filename, + &itemIsDirectory, &itemIsHidden, + 0, 0, 0, 0); - if (handle != 0) - { - do - { - if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden) - && ! filename.containsOnly (T("."))) - { - results.add (new File (path + filename, 0)); - ++total; - } + if (handle != 0) + { + do + { + if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden) + && ! filename.containsOnly (T("."))) + { + results.add (new File (path + filename, 0)); + ++total; + } - } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0)); + } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0)); - juce_findFileClose (handle); - } - } - else - { - // trying to search for files inside a non-directory? - //jassertfalse - } + juce_findFileClose (handle); + } + } + else + { + // trying to search for files inside a non-directory? + //jassertfalse + } - // and recurse down if required. - if (searchRecursively) - { - OwnedArray subDirectories; - findChildFiles (subDirectories, File::findDirectories, false); + // and recurse down if required. + if (searchRecursively) + { + OwnedArray subDirectories; + findChildFiles (subDirectories, File::findDirectories, false); - for (int i = 0; i < subDirectories.size(); ++i) - { - total += subDirectories.getUnchecked(i) - ->findChildFiles (results, - whatToLookFor, - true, - wildCardPattern); - } - } + for (int i = 0; i < subDirectories.size(); ++i) + { + total += subDirectories.getUnchecked(i) + ->findChildFiles (results, + whatToLookFor, + true, + wildCardPattern); + } + } - return total; + return total; } int File::getNumberOfChildFiles (const int whatToLookFor, - const String& wildCardPattern) const + const String& wildCardPattern) const { - // you have to specify the type of files you're looking for! - jassert (whatToLookFor > 0 && whatToLookFor <= 3); + // you have to specify the type of files you're looking for! + jassert (whatToLookFor > 0 && whatToLookFor <= 3); - int count = 0; + int count = 0; - if (isDirectory()) - { - String filename; - bool itemIsDirectory, itemIsHidden; + if (isDirectory()) + { + String filename; + bool itemIsDirectory, itemIsHidden; - void* const handle = juce_findFileStart (fullPath, wildCardPattern, filename, - &itemIsDirectory, &itemIsHidden, - 0, 0, 0, 0); + void* const handle = juce_findFileStart (fullPath, wildCardPattern, filename, + &itemIsDirectory, &itemIsHidden, + 0, 0, 0, 0); - if (handle != 0) - { - do - { - if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden) - && ! filename.containsOnly (T("."))) - { - ++count; - } + if (handle != 0) + { + do + { + if (fileTypeMatches (whatToLookFor, itemIsDirectory, itemIsHidden) + && ! filename.containsOnly (T("."))) + { + ++count; + } - } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0)); + } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0)); - juce_findFileClose (handle); - } - } - else - { - // trying to search for files inside a non-directory? - jassertfalse - } + juce_findFileClose (handle); + } + } + else + { + // trying to search for files inside a non-directory? + jassertfalse + } - return count; + return count; } bool File::containsSubDirectories() const { - bool result = false; + bool result = false; - if (isDirectory()) - { - String filename; - bool itemIsDirectory, itemIsHidden; - void* const handle = juce_findFileStart (juce_addTrailingSeparator (fullPath), - T("*"), filename, - &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0); + if (isDirectory()) + { + String filename; + bool itemIsDirectory, itemIsHidden; + void* const handle = juce_findFileStart (juce_addTrailingSeparator (fullPath), + T("*"), filename, + &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0); - if (handle != 0) - { - do - { - if (itemIsDirectory) - { - result = true; - break; - } + if (handle != 0) + { + do + { + if (itemIsDirectory) + { + result = true; + break; + } - } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0)); + } while (juce_findFileNext (handle, filename, &itemIsDirectory, &itemIsHidden, 0, 0, 0, 0)); - juce_findFileClose (handle); - } - } + juce_findFileClose (handle); + } + } - return result; + return result; } const File File::getNonexistentChildFile (const String& prefix_, - const String& suffix, - bool putNumbersInBrackets) const + const String& suffix, + bool putNumbersInBrackets) const { - File f (getChildFile (prefix_ + suffix)); + File f (getChildFile (prefix_ + suffix)); - if (f.exists()) - { - int num = 2; - String prefix (prefix_); + if (f.exists()) + { + int num = 2; + String prefix (prefix_); - // remove any bracketed numbers that may already be on the end.. - if (prefix.trim().endsWithChar (T(')'))) - { - putNumbersInBrackets = true; + // remove any bracketed numbers that may already be on the end.. + if (prefix.trim().endsWithChar (T(')'))) + { + putNumbersInBrackets = true; - const int openBracks = prefix.lastIndexOfChar (T('(')); - const int closeBracks = prefix.lastIndexOfChar (T(')')); + const int openBracks = prefix.lastIndexOfChar (T('(')); + const int closeBracks = prefix.lastIndexOfChar (T(')')); - if (openBracks > 0 - && closeBracks > openBracks - && prefix.substring (openBracks + 1, closeBracks).containsOnly (T("0123456789"))) - { - num = prefix.substring (openBracks + 1, closeBracks).getIntValue() + 1; - prefix = prefix.substring (0, openBracks); - } - } + if (openBracks > 0 + && closeBracks > openBracks + && prefix.substring (openBracks + 1, closeBracks).containsOnly (T("0123456789"))) + { + num = prefix.substring (openBracks + 1, closeBracks).getIntValue() + 1; + prefix = prefix.substring (0, openBracks); + } + } - // also use brackets if it ends in a digit. - putNumbersInBrackets = putNumbersInBrackets - || CharacterFunctions::isDigit (prefix.getLastCharacter()); + // also use brackets if it ends in a digit. + putNumbersInBrackets = putNumbersInBrackets + || CharacterFunctions::isDigit (prefix.getLastCharacter()); - do - { - if (putNumbersInBrackets) - f = getChildFile (prefix + T('(') + String (num++) + T(')') + suffix); - else - f = getChildFile (prefix + String (num++) + suffix); + do + { + if (putNumbersInBrackets) + f = getChildFile (prefix + T('(') + String (num++) + T(')') + suffix); + else + f = getChildFile (prefix + String (num++) + suffix); - } while (f.exists()); - } + } while (f.exists()); + } - return f; + return f; } const File File::getNonexistentSibling (const bool putNumbersInBrackets) const { - if (exists()) - { - return getParentDirectory() - .getNonexistentChildFile (getFileNameWithoutExtension(), - getFileExtension(), - putNumbersInBrackets); - } - else - { - return *this; - } + if (exists()) + { + return getParentDirectory() + .getNonexistentChildFile (getFileNameWithoutExtension(), + getFileExtension(), + putNumbersInBrackets); + } + else + { + return *this; + } } const String File::getFileExtension() const { - String ext; + String ext; - if (! isDirectory()) - { - const int indexOfDot = fullPath.lastIndexOfChar (T('.')); + if (! isDirectory()) + { + const int indexOfDot = fullPath.lastIndexOfChar (T('.')); - if (indexOfDot > fullPath.lastIndexOfChar (separator)) - ext = fullPath.substring (indexOfDot); - } + if (indexOfDot > fullPath.lastIndexOfChar (separator)) + ext = fullPath.substring (indexOfDot); + } - return ext; + return ext; } bool File::hasFileExtension (const String& possibleSuffix) const { - if (possibleSuffix.isEmpty()) - return fullPath.lastIndexOfChar (T('.')) <= fullPath.lastIndexOfChar (separator); + if (possibleSuffix.isEmpty()) + return fullPath.lastIndexOfChar (T('.')) <= fullPath.lastIndexOfChar (separator); - const int semicolon = possibleSuffix.indexOfChar (0, T(';')); + const int semicolon = possibleSuffix.indexOfChar (0, T(';')); - if (semicolon >= 0) - { - return hasFileExtension (possibleSuffix.substring (0, semicolon).trimEnd()) - || hasFileExtension (possibleSuffix.substring (semicolon + 1).trimStart()); - } - else - { - if (fullPath.endsWithIgnoreCase (possibleSuffix)) - { - if (possibleSuffix.startsWithChar (T('.'))) - return true; + if (semicolon >= 0) + { + return hasFileExtension (possibleSuffix.substring (0, semicolon).trimEnd()) + || hasFileExtension (possibleSuffix.substring (semicolon + 1).trimStart()); + } + else + { + if (fullPath.endsWithIgnoreCase (possibleSuffix)) + { + if (possibleSuffix.startsWithChar (T('.'))) + return true; - const int dotPos = fullPath.length() - possibleSuffix.length() - 1; + const int dotPos = fullPath.length() - possibleSuffix.length() - 1; - if (dotPos >= 0) - return fullPath [dotPos] == T('.'); - } - } + if (dotPos >= 0) + return fullPath [dotPos] == T('.'); + } + } - return false; + return false; } const File File::withFileExtension (const String& newExtension) const { - if (fullPath.isEmpty()) - return File::nonexistent; + if (fullPath.isEmpty()) + return File::nonexistent; - String filePart (getFileName()); + String filePart (getFileName()); - int i = filePart.lastIndexOfChar (T('.')); - if (i < 0) - i = filePart.length(); + int i = filePart.lastIndexOfChar (T('.')); + if (i < 0) + i = filePart.length(); - String newExt (newExtension); + String newExt (newExtension); - if (newExt.isNotEmpty() && ! newExt.startsWithChar (T('.'))) - newExt = T(".") + newExt; + if (newExt.isNotEmpty() && ! newExt.startsWithChar (T('.'))) + newExt = T(".") + newExt; - return getSiblingFile (filePart.substring (0, i) + newExt); + return getSiblingFile (filePart.substring (0, i) + newExt); } bool File::startAsProcess (const String& parameters) const { - return exists() - && juce_launchFile (fullPath, parameters); + return exists() + && juce_launchFile (fullPath, parameters); } FileInputStream* File::createInputStream() const { - if (existsAsFile()) - return new FileInputStream (*this); - else - return 0; + if (existsAsFile()) + return new FileInputStream (*this); + else + return 0; } FileOutputStream* File::createOutputStream (const int bufferSize) const { - ScopedPointer out (new FileOutputStream (*this, bufferSize)); + ScopedPointer out (new FileOutputStream (*this, bufferSize)); - if (out->failedToOpen()) - return 0; + if (out->failedToOpen()) + return 0; - return out.release(); + return out.release(); } bool File::appendData (const void* const dataToAppend, - const int numberOfBytes) const + const int numberOfBytes) const { - if (numberOfBytes > 0) - { - const ScopedPointer out (createOutputStream()); + if (numberOfBytes > 0) + { + const ScopedPointer out (createOutputStream()); - if (out == 0) - return false; + if (out == 0) + return false; - out->write (dataToAppend, numberOfBytes); - } + out->write (dataToAppend, numberOfBytes); + } - return true; + return true; } bool File::replaceWithData (const void* const dataToWrite, - const int numberOfBytes) const + const int numberOfBytes) const { - jassert (numberOfBytes >= 0); // a negative number of bytes?? + jassert (numberOfBytes >= 0); // a negative number of bytes?? - if (numberOfBytes <= 0) - return deleteFile(); + if (numberOfBytes <= 0) + return deleteFile(); - const File tempFile (getSiblingFile (T(".") + getFileName()).getNonexistentSibling (false)); + const File tempFile (getSiblingFile (T(".") + getFileName()).getNonexistentSibling (false)); - if (tempFile.appendData (dataToWrite, numberOfBytes) - && tempFile.moveFileTo (*this)) - { - return true; - } + if (tempFile.appendData (dataToWrite, numberOfBytes) + && tempFile.moveFileTo (*this)) + { + return true; + } - tempFile.deleteFile(); - return false; + tempFile.deleteFile(); + return false; } bool File::appendText (const String& text, - const bool asUnicode, - const bool writeUnicodeHeaderBytes) const + const bool asUnicode, + const bool writeUnicodeHeaderBytes) const { - const ScopedPointer out (createOutputStream()); + const ScopedPointer out (createOutputStream()); - if (out != 0) - { - out->writeText (text, asUnicode, writeUnicodeHeaderBytes); - return true; - } + if (out != 0) + { + out->writeText (text, asUnicode, writeUnicodeHeaderBytes); + return true; + } - return false; -} - -bool File::printf (const tchar* pf, ...) const -{ - va_list list; - va_start (list, pf); - - String text; - text.vprintf (pf, list); - - return appendData ((const char*) text, text.length()); + return false; } bool File::replaceWithText (const String& textToWrite, - const bool asUnicode, - const bool writeUnicodeHeaderBytes) const + const bool asUnicode, + const bool writeUnicodeHeaderBytes) const { - const File tempFile (getSiblingFile (T(".") + getFileName()).getNonexistentSibling (false)); + const File tempFile (getSiblingFile (T(".") + getFileName()).getNonexistentSibling (false)); - if (tempFile.appendText (textToWrite, asUnicode, writeUnicodeHeaderBytes) - && tempFile.moveFileTo (*this)) - { - return true; - } + if (tempFile.appendText (textToWrite, asUnicode, writeUnicodeHeaderBytes) + && tempFile.moveFileTo (*this)) + { + return true; + } - tempFile.deleteFile(); - return false; + tempFile.deleteFile(); + return false; } const String File::createLegalPathName (const String& original) { - String s (original); - String start; + String s (original); + String start; - if (s[1] == T(':')) - { - start = s.substring (0, 2); - s = s.substring (2); - } + if (s[1] == T(':')) + { + start = s.substring (0, 2); + s = s.substring (2); + } - return start + s.removeCharacters (T("\"#@,;:<>*^|?")) - .substring (0, 1024); + return start + s.removeCharacters (T("\"#@,;:<>*^|?")) + .substring (0, 1024); } const String File::createLegalFileName (const String& original) { - String s (original.removeCharacters (T("\"#@,;:<>*^|?\\/"))); + String s (original.removeCharacters (T("\"#@,;:<>*^|?\\/"))); - const int maxLength = 128; // only the length of the filename, not the whole path - const int len = s.length(); + const int maxLength = 128; // only the length of the filename, not the whole path + const int len = s.length(); - if (len > maxLength) - { - const int lastDot = s.lastIndexOfChar (T('.')); + if (len > maxLength) + { + const int lastDot = s.lastIndexOfChar (T('.')); - if (lastDot > jmax (0, len - 12)) - { - s = s.substring (0, maxLength - (len - lastDot)) - + s.substring (lastDot); - } - else - { - s = s.substring (0, maxLength); - } - } + if (lastDot > jmax (0, len - 12)) + { + s = s.substring (0, maxLength - (len - lastDot)) + + s.substring (lastDot); + } + else + { + s = s.substring (0, maxLength); + } + } - return s; + return s; } const String File::getRelativePathFrom (const File& dir) const { - String thisPath (fullPath); + String thisPath (fullPath); - { - int len = thisPath.length(); - while (--len >= 0 && thisPath [len] == File::separator) - thisPath [len] = 0; - } + { + int len = thisPath.length(); + while (--len >= 0 && thisPath [len] == File::separator) + thisPath [len] = 0; + } - String dirPath (juce_addTrailingSeparator ((dir.existsAsFile()) ? dir.getParentDirectory().getFullPathName() - : dir.fullPath)); + String dirPath (juce_addTrailingSeparator ((dir.existsAsFile()) ? dir.getParentDirectory().getFullPathName() + : dir.fullPath)); - const int len = jmin (thisPath.length(), dirPath.length()); - int commonBitLength = 0; + const int len = jmin (thisPath.length(), dirPath.length()); + int commonBitLength = 0; - for (int i = 0; i < len; ++i) - { + for (int i = 0; i < len; ++i) + { #if NAMES_ARE_CASE_SENSITIVE - if (thisPath[i] != dirPath[i]) + if (thisPath[i] != dirPath[i]) #else - if (CharacterFunctions::toLowerCase (thisPath[i]) - != CharacterFunctions::toLowerCase (dirPath[i])) + if (CharacterFunctions::toLowerCase (thisPath[i]) + != CharacterFunctions::toLowerCase (dirPath[i])) #endif - { - break; - } + { + break; + } - ++commonBitLength; - } + ++commonBitLength; + } - while (commonBitLength > 0 && thisPath [commonBitLength - 1] != File::separator) - --commonBitLength; + while (commonBitLength > 0 && thisPath [commonBitLength - 1] != File::separator) + --commonBitLength; - // if the only common bit is the root, then just return the full path.. - if (commonBitLength <= 0 - || (commonBitLength == 1 && thisPath [1] == File::separator)) - return fullPath; + // if the only common bit is the root, then just return the full path.. + if (commonBitLength <= 0 + || (commonBitLength == 1 && thisPath [1] == File::separator)) + return fullPath; - thisPath = thisPath.substring (commonBitLength); - dirPath = dirPath.substring (commonBitLength); + thisPath = thisPath.substring (commonBitLength); + dirPath = dirPath.substring (commonBitLength); - while (dirPath.isNotEmpty()) - { + while (dirPath.isNotEmpty()) + { #if JUCE_WINDOWS - thisPath = T("..\\") + thisPath; + thisPath = T("..\\") + thisPath; #else - thisPath = T("../") + thisPath; + thisPath = T("../") + thisPath; #endif - const int sep = dirPath.indexOfChar (separator); + const int sep = dirPath.indexOfChar (separator); - if (sep >= 0) - dirPath = dirPath.substring (sep + 1); - else - dirPath = String::empty; - } + if (sep >= 0) + dirPath = dirPath.substring (sep + 1); + else + dirPath = String::empty; + } - return thisPath; + return thisPath; } void File::findFileSystemRoots (OwnedArray& destArray) { - const StringArray roots (juce_getFileSystemRoots()); + const StringArray roots (juce_getFileSystemRoots()); - for (int i = 0; i < roots.size(); ++i) - destArray.add (new File (roots[i])); + for (int i = 0; i < roots.size(); ++i) + destArray.add (new File (roots[i])); } const String File::getVolumeLabel() const { - int serialNum; - return juce_getVolumeLabel (fullPath, serialNum); + int serialNum; + return juce_getVolumeLabel (fullPath, serialNum); } int File::getVolumeSerialNumber() const { - int serialNum; - juce_getVolumeLabel (fullPath, serialNum); + int serialNum; + juce_getVolumeLabel (fullPath, serialNum); - return serialNum; + return serialNum; } const File File::createTempFile (const String& fileNameEnding) { - String tempName (T("temp")); - static int tempNum = 0; - tempName << tempNum++ << fileNameEnding; + String tempName (T("temp")); + static int tempNum = 0; + tempName << tempNum++ << fileNameEnding; - const File tempFile (getSpecialLocation (tempDirectory) - .getChildFile (tempName)); + const File tempFile (getSpecialLocation (tempDirectory) + .getChildFile (tempName)); - if (tempFile.exists()) - return createTempFile (fileNameEnding); - else - return tempFile; + if (tempFile.exists()) + return createTempFile (fileNameEnding); + else + return tempFile; } END_JUCE_NAMESPACE @@ -7096,61 +6858,61 @@ int juce_fileRead (void* handle, void* buffer, int size); int64 juce_fileSetPosition (void* handle, int64 pos); FileInputStream::FileInputStream (const File& f) - : file (f), - currentPosition (0), - needToSeek (true) + : file (f), + currentPosition (0), + needToSeek (true) { - totalSize = f.getSize(); + totalSize = f.getSize(); - fileHandle = juce_fileOpen (f.getFullPathName(), false); + fileHandle = juce_fileOpen (f.getFullPathName(), false); } FileInputStream::~FileInputStream() { - juce_fileClose (fileHandle); + juce_fileClose (fileHandle); } int64 FileInputStream::getTotalLength() { - return totalSize; + return totalSize; } int FileInputStream::read (void* buffer, int bytesToRead) { - int num = 0; + int num = 0; - if (needToSeek) - { - if (juce_fileSetPosition (fileHandle, currentPosition) < 0) - return 0; + if (needToSeek) + { + if (juce_fileSetPosition (fileHandle, currentPosition) < 0) + return 0; - needToSeek = false; - } + needToSeek = false; + } - num = juce_fileRead (fileHandle, buffer, bytesToRead); - currentPosition += num; + num = juce_fileRead (fileHandle, buffer, bytesToRead); + currentPosition += num; - return num; + return num; } bool FileInputStream::isExhausted() { - return currentPosition >= totalSize; + return currentPosition >= totalSize; } int64 FileInputStream::getPosition() { - return currentPosition; + return currentPosition; } bool FileInputStream::setPosition (int64 pos) { - pos = jlimit ((int64) 0, totalSize, pos); + pos = jlimit ((int64) 0, totalSize, pos); - needToSeek |= (currentPosition != pos); - currentPosition = pos; + needToSeek |= (currentPosition != pos); + currentPosition = pos; - return true; + return true; } END_JUCE_NAMESPACE @@ -7168,98 +6930,98 @@ int64 juce_fileGetPosition (void* handle); int64 juce_fileSetPosition (void* handle, int64 pos); FileOutputStream::FileOutputStream (const File& f, - const int bufferSize_) - : file (f), - bufferSize (bufferSize_), - bytesInBuffer (0) + const int bufferSize_) + : file (f), + bufferSize (bufferSize_), + bytesInBuffer (0) { - fileHandle = juce_fileOpen (f.getFullPathName(), true); + fileHandle = juce_fileOpen (f.getFullPathName(), true); - if (fileHandle != 0) - { - currentPosition = juce_fileGetPosition (fileHandle); + if (fileHandle != 0) + { + currentPosition = juce_fileGetPosition (fileHandle); - if (currentPosition < 0) - { - jassertfalse - juce_fileClose (fileHandle); - fileHandle = 0; - } - } + if (currentPosition < 0) + { + jassertfalse + juce_fileClose (fileHandle); + fileHandle = 0; + } + } - buffer.malloc (jmax (bufferSize_, 16)); + buffer.malloc (jmax (bufferSize_, 16)); } FileOutputStream::~FileOutputStream() { - flush(); + flush(); - juce_fileClose (fileHandle); + juce_fileClose (fileHandle); } int64 FileOutputStream::getPosition() { - return currentPosition; + return currentPosition; } bool FileOutputStream::setPosition (int64 newPosition) { - if (newPosition != currentPosition) - { - flush(); - currentPosition = juce_fileSetPosition (fileHandle, newPosition); - } + if (newPosition != currentPosition) + { + flush(); + currentPosition = juce_fileSetPosition (fileHandle, newPosition); + } - return newPosition == currentPosition; + return newPosition == currentPosition; } void FileOutputStream::flush() { - if (bytesInBuffer > 0) - { - juce_fileWrite (fileHandle, buffer, bytesInBuffer); - bytesInBuffer = 0; - } + if (bytesInBuffer > 0) + { + juce_fileWrite (fileHandle, buffer, bytesInBuffer); + bytesInBuffer = 0; + } - juce_fileFlush (fileHandle); + juce_fileFlush (fileHandle); } bool FileOutputStream::write (const void* const src, const int numBytes) { - if (bytesInBuffer + numBytes < bufferSize) - { - memcpy (buffer + bytesInBuffer, src, numBytes); - bytesInBuffer += numBytes; - currentPosition += numBytes; - } - else - { - if (bytesInBuffer > 0) - { - // flush the reservoir - const bool wroteOk = (juce_fileWrite (fileHandle, buffer, bytesInBuffer) == bytesInBuffer); - bytesInBuffer = 0; + if (bytesInBuffer + numBytes < bufferSize) + { + memcpy (buffer + bytesInBuffer, src, numBytes); + bytesInBuffer += numBytes; + currentPosition += numBytes; + } + else + { + if (bytesInBuffer > 0) + { + // flush the reservoir + const bool wroteOk = (juce_fileWrite (fileHandle, buffer, bytesInBuffer) == bytesInBuffer); + bytesInBuffer = 0; - if (! wroteOk) - return false; - } + if (! wroteOk) + return false; + } - if (numBytes < bufferSize) - { - memcpy (buffer + bytesInBuffer, src, numBytes); - bytesInBuffer += numBytes; - currentPosition += numBytes; - } - else - { - const int bytesWritten = juce_fileWrite (fileHandle, src, numBytes); - currentPosition += bytesWritten; + if (numBytes < bufferSize) + { + memcpy (buffer + bytesInBuffer, src, numBytes); + bytesInBuffer += numBytes; + currentPosition += numBytes; + } + else + { + const int bytesWritten = juce_fileWrite (fileHandle, src, numBytes); + currentPosition += bytesWritten; - return bytesWritten == numBytes; - } - } + return bytesWritten == numBytes; + } + } - return true; + return true; } END_JUCE_NAMESPACE @@ -7275,7 +7037,7 @@ FileSearchPath::FileSearchPath() FileSearchPath::FileSearchPath (const String& path) { - init (path); + init (path); } FileSearchPath::FileSearchPath (const FileSearchPath& other) @@ -7289,128 +7051,128 @@ FileSearchPath::~FileSearchPath() const FileSearchPath& FileSearchPath::operator= (const String& path) { - init (path); - return *this; + init (path); + return *this; } void FileSearchPath::init (const String& path) { - directories.clear(); - directories.addTokens (path, T(";"), T("\"")); - directories.trim(); - directories.removeEmptyStrings(); + directories.clear(); + directories.addTokens (path, T(";"), T("\"")); + directories.trim(); + directories.removeEmptyStrings(); - for (int i = directories.size(); --i >= 0;) - directories.set (i, directories[i].unquoted()); + for (int i = directories.size(); --i >= 0;) + directories.set (i, directories[i].unquoted()); } int FileSearchPath::getNumPaths() const { - return directories.size(); + return directories.size(); } const File FileSearchPath::operator[] (const int index) const { - return File (directories [index]); + return File (directories [index]); } const String FileSearchPath::toString() const { - StringArray directories2 (directories); - for (int i = directories2.size(); --i >= 0;) - if (directories2[i].containsChar (T(';'))) - directories2.set (i, directories2[i].quoted()); + StringArray directories2 (directories); + for (int i = directories2.size(); --i >= 0;) + if (directories2[i].containsChar (T(';'))) + directories2.set (i, directories2[i].quoted()); - return directories2.joinIntoString (T(";")); + return directories2.joinIntoString (T(";")); } void FileSearchPath::add (const File& dir, const int insertIndex) { - directories.insert (insertIndex, dir.getFullPathName()); + directories.insert (insertIndex, dir.getFullPathName()); } void FileSearchPath::addIfNotAlreadyThere (const File& dir) { - for (int i = 0; i < directories.size(); ++i) - if (File (directories[i]) == dir) - return; + for (int i = 0; i < directories.size(); ++i) + if (File (directories[i]) == dir) + return; - add (dir); + add (dir); } void FileSearchPath::remove (const int index) { - directories.remove (index); + directories.remove (index); } void FileSearchPath::addPath (const FileSearchPath& other) { - for (int i = 0; i < other.getNumPaths(); ++i) - addIfNotAlreadyThere (other[i]); + for (int i = 0; i < other.getNumPaths(); ++i) + addIfNotAlreadyThere (other[i]); } void FileSearchPath::removeRedundantPaths() { - for (int i = directories.size(); --i >= 0;) - { - const File d1 (directories[i]); + for (int i = directories.size(); --i >= 0;) + { + const File d1 (directories[i]); - for (int j = directories.size(); --j >= 0;) - { - const File d2 (directories[j]); + for (int j = directories.size(); --j >= 0;) + { + const File d2 (directories[j]); - if ((i != j) && (d1.isAChildOf (d2) || d1 == d2)) - { - directories.remove (i); - break; - } - } - } + if ((i != j) && (d1.isAChildOf (d2) || d1 == d2)) + { + directories.remove (i); + break; + } + } + } } void FileSearchPath::removeNonExistentPaths() { - for (int i = directories.size(); --i >= 0;) - if (! File (directories[i]).isDirectory()) - directories.remove (i); + for (int i = directories.size(); --i >= 0;) + if (! File (directories[i]).isDirectory()) + directories.remove (i); } int FileSearchPath::findChildFiles (OwnedArray& results, - const int whatToLookFor, - const bool searchRecursively, - const String& wildCardPattern) const + const int whatToLookFor, + const bool searchRecursively, + const String& wildCardPattern) const { - int total = 0; + int total = 0; - for (int i = 0; i < directories.size(); ++i) - total += operator[] (i).findChildFiles (results, - whatToLookFor, - searchRecursively, - wildCardPattern); + for (int i = 0; i < directories.size(); ++i) + total += operator[] (i).findChildFiles (results, + whatToLookFor, + searchRecursively, + wildCardPattern); - return total; + return total; } bool FileSearchPath::isFileInPath (const File& fileToCheck, - const bool checkRecursively) const + const bool checkRecursively) const { - for (int i = directories.size(); --i >= 0;) - { - const File d (directories[i]); + for (int i = directories.size(); --i >= 0;) + { + const File d (directories[i]); - if (checkRecursively) - { - if (fileToCheck.isAChildOf (d)) - return true; - } - else - { - if (fileToCheck.getParentDirectory() == d) - return true; - } - } + if (checkRecursively) + { + if (fileToCheck.isAChildOf (d)) + return true; + } + else + { + if (fileToCheck.getParentDirectory() == d) + return true; + } + } - return false; + return false; } END_JUCE_NAMESPACE @@ -7421,35 +7183,35 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE NamedPipe::NamedPipe() - : internal (0) + : internal (0) { } NamedPipe::~NamedPipe() { - close(); + close(); } bool NamedPipe::openExisting (const String& pipeName) { - currentPipeName = pipeName; - return openInternal (pipeName, false); + currentPipeName = pipeName; + return openInternal (pipeName, false); } bool NamedPipe::createNewPipe (const String& pipeName) { - currentPipeName = pipeName; - return openInternal (pipeName, true); + currentPipeName = pipeName; + return openInternal (pipeName, true); } bool NamedPipe::isOpen() const { - return internal != 0; + return internal != 0; } const String NamedPipe::getName() const { - return currentPipeName; + return currentPipeName; } // other methods for this class are implemented in the platform-specific files @@ -7463,18 +7225,18 @@ END_JUCE_NAMESPACE #include #ifdef _MSC_VER - #pragma warning (disable : 4127 4389 4018) + #pragma warning (disable : 4127 4389 4018) #endif #else #if JUCE_LINUX - #include - #include - #include - #include - #include + #include + #include + #include + #include + #include #elif (MACOSX_DEPLOYMENT_TARGET <= MAC_OS_X_VERSION_10_4) && ! JUCE_IPHONE - #include + #include #endif #include @@ -7498,550 +7260,550 @@ juce_CloseWin32SocketLibCall* juce_CloseWin32SocketLib = 0; static void initWin32Sockets() { - static CriticalSection lock; - const ScopedLock sl (lock); + static CriticalSection lock; + const ScopedLock sl (lock); - if (juce_CloseWin32SocketLib == 0) - { - WSADATA wsaData; - const WORD wVersionRequested = MAKEWORD (1, 1); - WSAStartup (wVersionRequested, &wsaData); + if (juce_CloseWin32SocketLib == 0) + { + WSADATA wsaData; + const WORD wVersionRequested = MAKEWORD (1, 1); + WSAStartup (wVersionRequested, &wsaData); - juce_CloseWin32SocketLib = &WSACleanup; - } + juce_CloseWin32SocketLib = &WSACleanup; + } } #endif static bool resetSocketOptions (const int handle, const bool isDatagram, const bool allowBroadcast) throw() { - const int sndBufSize = 65536; - const int rcvBufSize = 65536; - const int one = 1; + const int sndBufSize = 65536; + const int rcvBufSize = 65536; + const int one = 1; - return handle > 0 - && setsockopt (handle, SOL_SOCKET, SO_RCVBUF, (const char*) &rcvBufSize, sizeof (rcvBufSize)) == 0 - && setsockopt (handle, SOL_SOCKET, SO_SNDBUF, (const char*) &sndBufSize, sizeof (sndBufSize)) == 0 - && (isDatagram ? ((! allowBroadcast) || setsockopt (handle, SOL_SOCKET, SO_BROADCAST, (const char*) &one, sizeof (one)) == 0) - : (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (one)) == 0)); + return handle > 0 + && setsockopt (handle, SOL_SOCKET, SO_RCVBUF, (const char*) &rcvBufSize, sizeof (rcvBufSize)) == 0 + && setsockopt (handle, SOL_SOCKET, SO_SNDBUF, (const char*) &sndBufSize, sizeof (sndBufSize)) == 0 + && (isDatagram ? ((! allowBroadcast) || setsockopt (handle, SOL_SOCKET, SO_BROADCAST, (const char*) &one, sizeof (one)) == 0) + : (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (one)) == 0)); } static bool bindSocketToPort (const int handle, const int port) throw() { - if (handle <= 0 || port <= 0) - return false; + if (handle <= 0 || port <= 0) + return false; - struct sockaddr_in servTmpAddr; - zerostruct (servTmpAddr); - servTmpAddr.sin_family = PF_INET; - servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); - servTmpAddr.sin_port = htons ((uint16) port); + struct sockaddr_in servTmpAddr; + zerostruct (servTmpAddr); + servTmpAddr.sin_family = PF_INET; + servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); + servTmpAddr.sin_port = htons ((uint16) port); - return bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0; + return bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0; } static int readSocket (const int handle, - void* const destBuffer, const int maxBytesToRead, - bool volatile& connected, - const bool blockUntilSpecifiedAmountHasArrived) throw() + void* const destBuffer, const int maxBytesToRead, + bool volatile& connected, + const bool blockUntilSpecifiedAmountHasArrived) throw() { - int bytesRead = 0; + int bytesRead = 0; - while (bytesRead < maxBytesToRead) - { - int bytesThisTime; + while (bytesRead < maxBytesToRead) + { + int bytesThisTime; #if JUCE_WINDOWS - bytesThisTime = recv (handle, ((char*) destBuffer) + bytesRead, maxBytesToRead - bytesRead, 0); + bytesThisTime = recv (handle, ((char*) destBuffer) + bytesRead, maxBytesToRead - bytesRead, 0); #else - while ((bytesThisTime = ::read (handle, ((char*) destBuffer) + bytesRead, maxBytesToRead - bytesRead)) < 0 - && errno == EINTR - && connected) - { - } + while ((bytesThisTime = (int) ::read (handle, ((char*) destBuffer) + bytesRead, maxBytesToRead - bytesRead)) < 0 + && errno == EINTR + && connected) + { + } #endif - if (bytesThisTime <= 0 || ! connected) - { - if (bytesRead == 0) - bytesRead = -1; + if (bytesThisTime <= 0 || ! connected) + { + if (bytesRead == 0) + bytesRead = -1; - break; - } + break; + } - bytesRead += bytesThisTime; + bytesRead += bytesThisTime; - if (! blockUntilSpecifiedAmountHasArrived) - break; - } + if (! blockUntilSpecifiedAmountHasArrived) + break; + } - return bytesRead; + return bytesRead; } static int waitForReadiness (const int handle, const bool forReading, - const int timeoutMsecs) throw() + const int timeoutMsecs) throw() { - struct timeval timeout; - struct timeval* timeoutp; + struct timeval timeout; + struct timeval* timeoutp; - if (timeoutMsecs >= 0) - { - timeout.tv_sec = timeoutMsecs / 1000; - timeout.tv_usec = (timeoutMsecs % 1000) * 1000; - timeoutp = &timeout; - } - else - { - timeoutp = 0; - } + if (timeoutMsecs >= 0) + { + timeout.tv_sec = timeoutMsecs / 1000; + timeout.tv_usec = (timeoutMsecs % 1000) * 1000; + timeoutp = &timeout; + } + else + { + timeoutp = 0; + } - fd_set rset, wset; - FD_ZERO (&rset); - FD_SET (handle, &rset); - FD_ZERO (&wset); - FD_SET (handle, &wset); + fd_set rset, wset; + FD_ZERO (&rset); + FD_SET (handle, &rset); + FD_ZERO (&wset); + FD_SET (handle, &wset); - fd_set* const prset = forReading ? &rset : 0; - fd_set* const pwset = forReading ? 0 : &wset; + fd_set* const prset = forReading ? &rset : 0; + fd_set* const pwset = forReading ? 0 : &wset; #if JUCE_WINDOWS - if (select (handle + 1, prset, pwset, 0, timeoutp) < 0) - return -1; + if (select (handle + 1, prset, pwset, 0, timeoutp) < 0) + return -1; #else - { - int result; - while ((result = select (handle + 1, prset, pwset, 0, timeoutp)) < 0 - && errno == EINTR) - { - } + { + int result; + while ((result = select (handle + 1, prset, pwset, 0, timeoutp)) < 0 + && errno == EINTR) + { + } - if (result < 0) - return -1; - } + if (result < 0) + return -1; + } #endif - { - int opt; - juce_socklen_t len = sizeof (opt); + { + int opt; + juce_socklen_t len = sizeof (opt); - if (getsockopt (handle, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0 - || opt != 0) - return -1; - } + if (getsockopt (handle, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0 + || opt != 0) + return -1; + } - if ((forReading && FD_ISSET (handle, &rset)) - || ((! forReading) && FD_ISSET (handle, &wset))) - return 1; + if ((forReading && FD_ISSET (handle, &rset)) + || ((! forReading) && FD_ISSET (handle, &wset))) + return 1; - return 0; + return 0; } static bool setSocketBlockingState (const int handle, const bool shouldBlock) throw() { #if JUCE_WINDOWS - u_long nonBlocking = shouldBlock ? 0 : 1; + u_long nonBlocking = shouldBlock ? 0 : 1; - if (ioctlsocket (handle, FIONBIO, &nonBlocking) != 0) - return false; + if (ioctlsocket (handle, FIONBIO, &nonBlocking) != 0) + return false; #else - int socketFlags = fcntl (handle, F_GETFL, 0); + int socketFlags = fcntl (handle, F_GETFL, 0); - if (socketFlags == -1) - return false; + if (socketFlags == -1) + return false; - if (shouldBlock) - socketFlags &= ~O_NONBLOCK; - else - socketFlags |= O_NONBLOCK; + if (shouldBlock) + socketFlags &= ~O_NONBLOCK; + else + socketFlags |= O_NONBLOCK; - if (fcntl (handle, F_SETFL, socketFlags) != 0) - return false; + if (fcntl (handle, F_SETFL, socketFlags) != 0) + return false; #endif - return true; + return true; } static bool connectSocket (int volatile& handle, - const bool isDatagram, - void** serverAddress, - const String& hostName, - const int portNumber, - const int timeOutMillisecs) throw() + const bool isDatagram, + void** serverAddress, + const String& hostName, + const int portNumber, + const int timeOutMillisecs) throw() { - struct hostent* const hostEnt = gethostbyname (hostName); + struct hostent* const hostEnt = gethostbyname (hostName); - if (hostEnt == 0) - return false; + if (hostEnt == 0) + return false; - struct in_addr targetAddress; - memcpy (&targetAddress.s_addr, - *(hostEnt->h_addr_list), - sizeof (targetAddress.s_addr)); + struct in_addr targetAddress; + memcpy (&targetAddress.s_addr, + *(hostEnt->h_addr_list), + sizeof (targetAddress.s_addr)); - struct sockaddr_in servTmpAddr; - zerostruct (servTmpAddr); - servTmpAddr.sin_family = PF_INET; - servTmpAddr.sin_addr = targetAddress; - servTmpAddr.sin_port = htons ((uint16) portNumber); + struct sockaddr_in servTmpAddr; + zerostruct (servTmpAddr); + servTmpAddr.sin_family = PF_INET; + servTmpAddr.sin_addr = targetAddress; + servTmpAddr.sin_port = htons ((uint16) portNumber); - if (handle < 0) - handle = (int) socket (AF_INET, isDatagram ? SOCK_DGRAM : SOCK_STREAM, 0); + if (handle < 0) + handle = (int) socket (AF_INET, isDatagram ? SOCK_DGRAM : SOCK_STREAM, 0); - if (handle < 0) - return false; + if (handle < 0) + return false; - if (isDatagram) - { - *serverAddress = new struct sockaddr_in(); - *((struct sockaddr_in*) *serverAddress) = servTmpAddr; + if (isDatagram) + { + *serverAddress = new struct sockaddr_in(); + *((struct sockaddr_in*) *serverAddress) = servTmpAddr; - return true; - } + return true; + } - setSocketBlockingState (handle, false); + setSocketBlockingState (handle, false); - const int result = ::connect (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)); + const int result = ::connect (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)); - if (result < 0) - { + if (result < 0) + { #if JUCE_WINDOWS - if (result == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) + if (result == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) #else - if (errno == EINPROGRESS) + if (errno == EINPROGRESS) #endif - { - if (waitForReadiness (handle, false, timeOutMillisecs) != 1) - { - setSocketBlockingState (handle, true); - return false; - } - } - } + { + if (waitForReadiness (handle, false, timeOutMillisecs) != 1) + { + setSocketBlockingState (handle, true); + return false; + } + } + } - setSocketBlockingState (handle, true); - resetSocketOptions (handle, false, false); + setSocketBlockingState (handle, true); + resetSocketOptions (handle, false, false); - return true; + return true; } StreamingSocket::StreamingSocket() - : portNumber (0), - handle (-1), - connected (false), - isListener (false) + : portNumber (0), + handle (-1), + connected (false), + isListener (false) { #if JUCE_WINDOWS - initWin32Sockets(); + initWin32Sockets(); #endif } StreamingSocket::StreamingSocket (const String& hostName_, - const int portNumber_, - const int handle_) - : hostName (hostName_), - portNumber (portNumber_), - handle (handle_), - connected (true), - isListener (false) + const int portNumber_, + const int handle_) + : hostName (hostName_), + portNumber (portNumber_), + handle (handle_), + connected (true), + isListener (false) { #if JUCE_WINDOWS - initWin32Sockets(); + initWin32Sockets(); #endif - resetSocketOptions (handle_, false, false); + resetSocketOptions (handle_, false, false); } StreamingSocket::~StreamingSocket() { - close(); + close(); } int StreamingSocket::read (void* destBuffer, const int maxBytesToRead, const bool blockUntilSpecifiedAmountHasArrived) { - return (connected && ! isListener) ? readSocket (handle, destBuffer, maxBytesToRead, connected, blockUntilSpecifiedAmountHasArrived) - : -1; + return (connected && ! isListener) ? readSocket (handle, destBuffer, maxBytesToRead, connected, blockUntilSpecifiedAmountHasArrived) + : -1; } int StreamingSocket::write (const void* sourceBuffer, const int numBytesToWrite) { - if (isListener || ! connected) - return -1; + if (isListener || ! connected) + return -1; #if JUCE_WINDOWS - return send (handle, (const char*) sourceBuffer, numBytesToWrite, 0); + return send (handle, (const char*) sourceBuffer, numBytesToWrite, 0); #else - int result; + int result; - while ((result = ::write (handle, sourceBuffer, numBytesToWrite)) < 0 - && errno == EINTR) - { - } + while ((result = (int) ::write (handle, sourceBuffer, numBytesToWrite)) < 0 + && errno == EINTR) + { + } - return result; + return result; #endif } int StreamingSocket::waitUntilReady (const bool readyForReading, - const int timeoutMsecs) const + const int timeoutMsecs) const { - return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs) - : -1; + return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs) + : -1; } bool StreamingSocket::bindToPort (const int port) { - return bindSocketToPort (handle, port); + return bindSocketToPort (handle, port); } bool StreamingSocket::connect (const String& remoteHostName, - const int remotePortNumber, - const int timeOutMillisecs) + const int remotePortNumber, + const int timeOutMillisecs) { - if (isListener) - { - jassertfalse // a listener socket can't connect to another one! - return false; - } + if (isListener) + { + jassertfalse // a listener socket can't connect to another one! + return false; + } - if (connected) - close(); + if (connected) + close(); - hostName = remoteHostName; - portNumber = remotePortNumber; - isListener = false; + hostName = remoteHostName; + portNumber = remotePortNumber; + isListener = false; - connected = connectSocket (handle, false, 0, remoteHostName, - remotePortNumber, timeOutMillisecs); + connected = connectSocket (handle, false, 0, remoteHostName, + remotePortNumber, timeOutMillisecs); - if (! (connected && resetSocketOptions (handle, false, false))) - { - close(); - return false; - } + if (! (connected && resetSocketOptions (handle, false, false))) + { + close(); + return false; + } - return true; + return true; } void StreamingSocket::close() { #if JUCE_WINDOWS - closesocket (handle); - connected = false; + closesocket (handle); + connected = false; #else - if (connected) - { - connected = false; + if (connected) + { + connected = false; - if (isListener) - { - // need to do this to interrupt the accept() function.. - StreamingSocket temp; - temp.connect ("localhost", portNumber, 1000); - } - } + if (isListener) + { + // need to do this to interrupt the accept() function.. + StreamingSocket temp; + temp.connect ("localhost", portNumber, 1000); + } + } - ::close (handle); + ::close (handle); #endif - hostName = String::empty; - portNumber = 0; - handle = -1; - isListener = false; + hostName = String::empty; + portNumber = 0; + handle = -1; + isListener = false; } bool StreamingSocket::createListener (const int newPortNumber, const String& localHostName) { - if (connected) - close(); + if (connected) + close(); - hostName = "listener"; - portNumber = newPortNumber; - isListener = true; + hostName = "listener"; + portNumber = newPortNumber; + isListener = true; - struct sockaddr_in servTmpAddr; - zerostruct (servTmpAddr); - servTmpAddr.sin_family = PF_INET; - servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); + struct sockaddr_in servTmpAddr; + zerostruct (servTmpAddr); + servTmpAddr.sin_family = PF_INET; + servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); - if (localHostName.isNotEmpty()) - servTmpAddr.sin_addr.s_addr = ::inet_addr (localHostName.toUTF8()); + if (localHostName.isNotEmpty()) + servTmpAddr.sin_addr.s_addr = ::inet_addr (localHostName.toUTF8()); - servTmpAddr.sin_port = htons ((uint16) portNumber); + servTmpAddr.sin_port = htons ((uint16) portNumber); - handle = (int) socket (AF_INET, SOCK_STREAM, 0); + handle = (int) socket (AF_INET, SOCK_STREAM, 0); - if (handle < 0) - return false; + if (handle < 0) + return false; - const int reuse = 1; - setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse)); + const int reuse = 1; + setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse)); - if (bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0 - || listen (handle, SOMAXCONN) < 0) - { - close(); - return false; - } + if (bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0 + || listen (handle, SOMAXCONN) < 0) + { + close(); + return false; + } - connected = true; - return true; + connected = true; + return true; } StreamingSocket* StreamingSocket::waitForNextConnection() const { - jassert (isListener || ! connected); // to call this method, you first have to use createListener() to - // prepare this socket as a listener. + jassert (isListener || ! connected); // to call this method, you first have to use createListener() to + // prepare this socket as a listener. - if (connected && isListener) - { - struct sockaddr address; - juce_socklen_t len = sizeof (sockaddr); - const int newSocket = (int) accept (handle, &address, &len); + if (connected && isListener) + { + struct sockaddr address; + juce_socklen_t len = sizeof (sockaddr); + const int newSocket = (int) accept (handle, &address, &len); - if (newSocket >= 0 && connected) - return new StreamingSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr), - portNumber, newSocket); - } + if (newSocket >= 0 && connected) + return new StreamingSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr), + portNumber, newSocket); + } - return 0; + return 0; } bool StreamingSocket::isLocal() const throw() { - return hostName == T("127.0.0.1"); + return hostName == T("127.0.0.1"); } DatagramSocket::DatagramSocket (const int localPortNumber, const bool allowBroadcast_) - : portNumber (0), - handle (-1), - connected (true), - allowBroadcast (allowBroadcast_), - serverAddress (0) + : portNumber (0), + handle (-1), + connected (true), + allowBroadcast (allowBroadcast_), + serverAddress (0) { #if JUCE_WINDOWS - initWin32Sockets(); + initWin32Sockets(); #endif - handle = (int) socket (AF_INET, SOCK_DGRAM, 0); - bindToPort (localPortNumber); + handle = (int) socket (AF_INET, SOCK_DGRAM, 0); + bindToPort (localPortNumber); } DatagramSocket::DatagramSocket (const String& hostName_, const int portNumber_, - const int handle_, const int localPortNumber) - : hostName (hostName_), - portNumber (portNumber_), - handle (handle_), - connected (true), - allowBroadcast (false), - serverAddress (0) + const int handle_, const int localPortNumber) + : hostName (hostName_), + portNumber (portNumber_), + handle (handle_), + connected (true), + allowBroadcast (false), + serverAddress (0) { #if JUCE_WINDOWS - initWin32Sockets(); + initWin32Sockets(); #endif - resetSocketOptions (handle_, true, allowBroadcast); - bindToPort (localPortNumber); + resetSocketOptions (handle_, true, allowBroadcast); + bindToPort (localPortNumber); } DatagramSocket::~DatagramSocket() { - close(); + close(); - delete ((struct sockaddr_in*) serverAddress); - serverAddress = 0; + delete ((struct sockaddr_in*) serverAddress); + serverAddress = 0; } void DatagramSocket::close() { #if JUCE_WINDOWS - closesocket (handle); - connected = false; + closesocket (handle); + connected = false; #else - connected = false; - ::close (handle); + connected = false; + ::close (handle); #endif - hostName = String::empty; - portNumber = 0; - handle = -1; + hostName = String::empty; + portNumber = 0; + handle = -1; } bool DatagramSocket::bindToPort (const int port) { - return bindSocketToPort (handle, port); + return bindSocketToPort (handle, port); } bool DatagramSocket::connect (const String& remoteHostName, - const int remotePortNumber, - const int timeOutMillisecs) + const int remotePortNumber, + const int timeOutMillisecs) { - if (connected) - close(); + if (connected) + close(); - hostName = remoteHostName; - portNumber = remotePortNumber; + hostName = remoteHostName; + portNumber = remotePortNumber; - connected = connectSocket (handle, true, &serverAddress, - remoteHostName, remotePortNumber, - timeOutMillisecs); + connected = connectSocket (handle, true, &serverAddress, + remoteHostName, remotePortNumber, + timeOutMillisecs); - if (! (connected && resetSocketOptions (handle, true, allowBroadcast))) - { - close(); - return false; - } + if (! (connected && resetSocketOptions (handle, true, allowBroadcast))) + { + close(); + return false; + } - return true; + return true; } DatagramSocket* DatagramSocket::waitForNextConnection() const { - struct sockaddr address; - juce_socklen_t len = sizeof (sockaddr); + struct sockaddr address; + juce_socklen_t len = sizeof (sockaddr); - while (waitUntilReady (true, -1) == 1) - { - char buf[1]; + while (waitUntilReady (true, -1) == 1) + { + char buf[1]; - if (recvfrom (handle, buf, 0, 0, &address, &len) > 0) - { - return new DatagramSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr), - ntohs (((struct sockaddr_in*) &address)->sin_port), - -1, -1); - } - } + if (recvfrom (handle, buf, 0, 0, &address, &len) > 0) + { + return new DatagramSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr), + ntohs (((struct sockaddr_in*) &address)->sin_port), + -1, -1); + } + } - return 0; + return 0; } int DatagramSocket::waitUntilReady (const bool readyForReading, - const int timeoutMsecs) const + const int timeoutMsecs) const { - return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs) - : -1; + return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs) + : -1; } int DatagramSocket::read (void* destBuffer, const int maxBytesToRead, const bool blockUntilSpecifiedAmountHasArrived) { - return connected ? readSocket (handle, destBuffer, maxBytesToRead, connected, blockUntilSpecifiedAmountHasArrived) - : -1; + return connected ? readSocket (handle, destBuffer, maxBytesToRead, connected, blockUntilSpecifiedAmountHasArrived) + : -1; } int DatagramSocket::write (const void* sourceBuffer, const int numBytesToWrite) { - // You need to call connect() first to set the server address.. - jassert (serverAddress != 0 && connected); + // You need to call connect() first to set the server address.. + jassert (serverAddress != 0 && connected); - return connected ? sendto (handle, (const char*) sourceBuffer, - numBytesToWrite, 0, - (const struct sockaddr*) serverAddress, - sizeof (struct sockaddr_in)) - : -1; + return connected ? (int) sendto (handle, (const char*) sourceBuffer, + numBytesToWrite, 0, + (const struct sockaddr*) serverAddress, + sizeof (struct sockaddr_in)) + : -1; } bool DatagramSocket::isLocal() const throw() { - return hostName == T("127.0.0.1"); + return hostName == T("127.0.0.1"); } END_JUCE_NAMESPACE @@ -8056,57 +7818,57 @@ URL::URL() } URL::URL (const String& url_) - : url (url_) + : url (url_) { - int i = url.indexOfChar (T('?')); + int i = url.indexOfChar (T('?')); - if (i >= 0) - { - do - { - const int nextAmp = url.indexOfChar (i + 1, T('&')); - const int equalsPos = url.indexOfChar (i + 1, T('=')); + if (i >= 0) + { + do + { + const int nextAmp = url.indexOfChar (i + 1, T('&')); + const int equalsPos = url.indexOfChar (i + 1, T('=')); - if (equalsPos > i + 1) - { - if (nextAmp < 0) - { - parameters.set (removeEscapeChars (url.substring (i + 1, equalsPos)), - removeEscapeChars (url.substring (equalsPos + 1))); - } - else if (nextAmp > 0 && equalsPos < nextAmp) - { - parameters.set (removeEscapeChars (url.substring (i + 1, equalsPos)), - removeEscapeChars (url.substring (equalsPos + 1, nextAmp))); - } - } + if (equalsPos > i + 1) + { + if (nextAmp < 0) + { + parameters.set (removeEscapeChars (url.substring (i + 1, equalsPos)), + removeEscapeChars (url.substring (equalsPos + 1))); + } + else if (nextAmp > 0 && equalsPos < nextAmp) + { + parameters.set (removeEscapeChars (url.substring (i + 1, equalsPos)), + removeEscapeChars (url.substring (equalsPos + 1, nextAmp))); + } + } - i = nextAmp; - } - while (i >= 0); + i = nextAmp; + } + while (i >= 0); - url = url.upToFirstOccurrenceOf (T("?"), false, false); - } + url = url.upToFirstOccurrenceOf (T("?"), false, false); + } } URL::URL (const URL& other) - : url (other.url), - postData (other.postData), - parameters (other.parameters), - filesToUpload (other.filesToUpload), - mimeTypes (other.mimeTypes) + : url (other.url), + postData (other.postData), + parameters (other.parameters), + filesToUpload (other.filesToUpload), + mimeTypes (other.mimeTypes) { } const URL& URL::operator= (const URL& other) { - url = other.url; - postData = other.postData; - parameters = other.parameters; - filesToUpload = other.filesToUpload; - mimeTypes = other.mimeTypes; + url = other.url; + postData = other.postData; + parameters = other.parameters; + filesToUpload = other.filesToUpload; + mimeTypes = other.mimeTypes; - return *this; + return *this; } URL::~URL() @@ -8115,143 +7877,143 @@ URL::~URL() static const String getMangledParameters (const StringPairArray& parameters) { - String p; + String p; - for (int i = 0; i < parameters.size(); ++i) - { - if (i > 0) - p += T("&"); + for (int i = 0; i < parameters.size(); ++i) + { + if (i > 0) + p += T("&"); - p << URL::addEscapeChars (parameters.getAllKeys() [i], true) - << T("=") - << URL::addEscapeChars (parameters.getAllValues() [i], true); - } + p << URL::addEscapeChars (parameters.getAllKeys() [i], true) + << T("=") + << URL::addEscapeChars (parameters.getAllValues() [i], true); + } - return p; + return p; } const String URL::toString (const bool includeGetParameters) const { - if (includeGetParameters && parameters.size() > 0) - return url + T("?") + getMangledParameters (parameters); - else - return url; + if (includeGetParameters && parameters.size() > 0) + return url + T("?") + getMangledParameters (parameters); + else + return url; } bool URL::isWellFormed() const { - //xxx TODO - return url.isNotEmpty(); + //xxx TODO + return url.isNotEmpty(); } static int findStartOfDomain (const String& url) { - int i = 0; + int i = 0; - while (CharacterFunctions::isLetterOrDigit (url[i]) - || CharacterFunctions::indexOfChar (T("+-."), url[i], false) >= 0) - ++i; + while (CharacterFunctions::isLetterOrDigit (url[i]) + || CharacterFunctions::indexOfChar (T("+-."), url[i], false) >= 0) + ++i; - return url[i] == T(':') ? i + 1 : 0; + return url[i] == T(':') ? i + 1 : 0; } const String URL::getDomain() const { - int start = findStartOfDomain (url); - while (url[start] == T('/')) - ++start; + int start = findStartOfDomain (url); + while (url[start] == T('/')) + ++start; - const int end1 = url.indexOfChar (start, T('/')); - const int end2 = url.indexOfChar (start, T(':')); + const int end1 = url.indexOfChar (start, T('/')); + const int end2 = url.indexOfChar (start, T(':')); - const int end = (end1 < 0 || end2 < 0) ? jmax (end1, end2) - : jmin (end1, end2); + const int end = (end1 < 0 || end2 < 0) ? jmax (end1, end2) + : jmin (end1, end2); - return url.substring (start, end); + return url.substring (start, end); } const String URL::getSubPath() const { - int start = findStartOfDomain (url); - while (url[start] == T('/')) - ++start; + int start = findStartOfDomain (url); + while (url[start] == T('/')) + ++start; - const int startOfPath = url.indexOfChar (start, T('/')) + 1; + const int startOfPath = url.indexOfChar (start, T('/')) + 1; - return startOfPath <= 0 ? String::empty - : url.substring (startOfPath); + return startOfPath <= 0 ? String::empty + : url.substring (startOfPath); } const String URL::getScheme() const { - return url.substring (0, findStartOfDomain (url) - 1); + return url.substring (0, findStartOfDomain (url) - 1); } const URL URL::withNewSubPath (const String& newPath) const { - int start = findStartOfDomain (url); - while (url[start] == T('/')) - ++start; + int start = findStartOfDomain (url); + while (url[start] == T('/')) + ++start; - const int startOfPath = url.indexOfChar (start, T('/')) + 1; + const int startOfPath = url.indexOfChar (start, T('/')) + 1; - URL u (*this); + URL u (*this); - if (startOfPath > 0) - u.url = url.substring (0, startOfPath); + if (startOfPath > 0) + u.url = url.substring (0, startOfPath); - if (! u.url.endsWithChar (T('/'))) - u.url << '/'; + if (! u.url.endsWithChar (T('/'))) + u.url << '/'; - if (newPath.startsWithChar (T('/'))) - u.url << newPath.substring (1); - else - u.url << newPath; + if (newPath.startsWithChar (T('/'))) + u.url << newPath.substring (1); + else + u.url << newPath; - return u; + return u; } bool URL::isProbablyAWebsiteURL (const String& possibleURL) { - if (possibleURL.startsWithIgnoreCase (T("http:")) - || possibleURL.startsWithIgnoreCase (T("ftp:"))) - return true; + if (possibleURL.startsWithIgnoreCase (T("http:")) + || possibleURL.startsWithIgnoreCase (T("ftp:"))) + return true; - if (possibleURL.startsWithIgnoreCase (T("file:")) - || possibleURL.containsChar (T('@')) - || possibleURL.endsWithChar (T('.')) - || (! possibleURL.containsChar (T('.')))) - return false; + if (possibleURL.startsWithIgnoreCase (T("file:")) + || possibleURL.containsChar (T('@')) + || possibleURL.endsWithChar (T('.')) + || (! possibleURL.containsChar (T('.')))) + return false; - if (possibleURL.startsWithIgnoreCase (T("www.")) - && possibleURL.substring (5).containsChar (T('.'))) - return true; + if (possibleURL.startsWithIgnoreCase (T("www.")) + && possibleURL.substring (5).containsChar (T('.'))) + return true; - const char* commonTLDs[] = { "com", "net", "org", "uk", "de", "fr", "jp" }; + const char* commonTLDs[] = { "com", "net", "org", "uk", "de", "fr", "jp" }; - for (int i = 0; i < numElementsInArray (commonTLDs); ++i) - if ((possibleURL + T("/")).containsIgnoreCase (T(".") + String (commonTLDs[i]) + T("/"))) - return true; + for (int i = 0; i < numElementsInArray (commonTLDs); ++i) + if ((possibleURL + T("/")).containsIgnoreCase (T(".") + String (commonTLDs[i]) + T("/"))) + return true; - return false; + return false; } bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress) { - const int atSign = possibleEmailAddress.indexOfChar (T('@')); + const int atSign = possibleEmailAddress.indexOfChar (T('@')); - return atSign > 0 - && possibleEmailAddress.lastIndexOfChar (T('.')) > (atSign + 1) - && (! possibleEmailAddress.endsWithChar (T('.'))); + return atSign > 0 + && possibleEmailAddress.lastIndexOfChar (T('.')) > (atSign + 1) + && (! possibleEmailAddress.endsWithChar (T('.'))); } void* juce_openInternetFile (const String& url, - const String& headers, - const MemoryBlock& optionalPostData, - const bool isPost, - URL::OpenStreamProgressCallback* callback, - void* callbackContext, - int timeOutMs); + const String& headers, + const MemoryBlock& optionalPostData, + const bool isPost, + URL::OpenStreamProgressCallback* callback, + void* callbackContext, + int timeOutMs); void juce_closeInternetFile (void* handle); int juce_readFromInternetFile (void* handle, void* dest, int bytesToRead); @@ -8262,358 +8024,358 @@ class WebInputStream : public InputStream { public: - WebInputStream (const URL& url, - const bool isPost_, - URL::OpenStreamProgressCallback* const progressCallback_, - void* const progressCallbackContext_, - const String& extraHeaders, - int timeOutMs_) - : position (0), - finished (false), - isPost (isPost_), - progressCallback (progressCallback_), - progressCallbackContext (progressCallbackContext_), - timeOutMs (timeOutMs_) - { - server = url.toString (! isPost); + WebInputStream (const URL& url, + const bool isPost_, + URL::OpenStreamProgressCallback* const progressCallback_, + void* const progressCallbackContext_, + const String& extraHeaders, + int timeOutMs_) + : position (0), + finished (false), + isPost (isPost_), + progressCallback (progressCallback_), + progressCallbackContext (progressCallbackContext_), + timeOutMs (timeOutMs_) + { + server = url.toString (! isPost); - if (isPost_) - createHeadersAndPostData (url); + if (isPost_) + createHeadersAndPostData (url); - headers += extraHeaders; + headers += extraHeaders; - if (! headers.endsWithChar (T('\n'))) - headers << "\r\n"; + if (! headers.endsWithChar (T('\n'))) + headers << "\r\n"; - handle = juce_openInternetFile (server, headers, postData, isPost, - progressCallback_, progressCallbackContext_, - timeOutMs); - } + handle = juce_openInternetFile (server, headers, postData, isPost, + progressCallback_, progressCallbackContext_, + timeOutMs); + } - ~WebInputStream() - { - juce_closeInternetFile (handle); - } + ~WebInputStream() + { + juce_closeInternetFile (handle); + } - bool isError() const - { - return handle == 0; - } + bool isError() const + { + return handle == 0; + } - int64 getTotalLength() - { - return juce_getInternetFileContentLength (handle); - } + int64 getTotalLength() + { + return juce_getInternetFileContentLength (handle); + } - bool isExhausted() - { - return finished; - } + bool isExhausted() + { + return finished; + } - int read (void* dest, int bytes) - { - if (finished || isError()) - { - return 0; - } - else - { - const int bytesRead = juce_readFromInternetFile (handle, dest, bytes); - position += bytesRead; + int read (void* dest, int bytes) + { + if (finished || isError()) + { + return 0; + } + else + { + const int bytesRead = juce_readFromInternetFile (handle, dest, bytes); + position += bytesRead; - if (bytesRead == 0) - finished = true; + if (bytesRead == 0) + finished = true; - return bytesRead; - } - } + return bytesRead; + } + } - int64 getPosition() - { - return position; - } + int64 getPosition() + { + return position; + } - bool setPosition (int64 wantedPos) - { - if (wantedPos != position) - { - finished = false; + bool setPosition (int64 wantedPos) + { + if (wantedPos != position) + { + finished = false; - const int actualPos = juce_seekInInternetFile (handle, (int) wantedPos); + const int actualPos = juce_seekInInternetFile (handle, (int) wantedPos); - if (actualPos == wantedPos) - { - position = wantedPos; - } - else - { - if (wantedPos < position) - { - juce_closeInternetFile (handle); + if (actualPos == wantedPos) + { + position = wantedPos; + } + else + { + if (wantedPos < position) + { + juce_closeInternetFile (handle); - position = 0; - finished = false; + position = 0; + finished = false; - handle = juce_openInternetFile (server, headers, postData, isPost, - progressCallback, progressCallbackContext, - timeOutMs); - } + handle = juce_openInternetFile (server, headers, postData, isPost, + progressCallback, progressCallbackContext, + timeOutMs); + } - skipNextBytes (wantedPos - position); - } - } + skipNextBytes (wantedPos - position); + } + } - return true; - } + return true; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String server, headers; - MemoryBlock postData; - int64 position; - bool finished; - const bool isPost; - void* handle; - URL::OpenStreamProgressCallback* const progressCallback; - void* const progressCallbackContext; - const int timeOutMs; + String server, headers; + MemoryBlock postData; + int64 position; + bool finished; + const bool isPost; + void* handle; + URL::OpenStreamProgressCallback* const progressCallback; + void* const progressCallbackContext; + const int timeOutMs; - void createHeadersAndPostData (const URL& url) - { - if (url.getFilesToUpload().size() > 0) - { - // need to upload some files, so do it as multi-part... - String boundary (String::toHexString (Random::getSystemRandom().nextInt64())); + void createHeadersAndPostData (const URL& url) + { + if (url.getFilesToUpload().size() > 0) + { + // need to upload some files, so do it as multi-part... + String boundary (String::toHexString (Random::getSystemRandom().nextInt64())); - headers << "Content-Type: multipart/form-data; boundary=" << boundary << "\r\n"; + headers << "Content-Type: multipart/form-data; boundary=" << boundary << "\r\n"; - appendUTF8ToPostData ("--" + boundary); + appendUTF8ToPostData ("--" + boundary); - int i; - for (i = 0; i < url.getParameters().size(); ++i) - { - String s; - s << "\r\nContent-Disposition: form-data; name=\"" - << url.getParameters().getAllKeys() [i] - << "\"\r\n\r\n" - << url.getParameters().getAllValues() [i] - << "\r\n--" - << boundary; + int i; + for (i = 0; i < url.getParameters().size(); ++i) + { + String s; + s << "\r\nContent-Disposition: form-data; name=\"" + << url.getParameters().getAllKeys() [i] + << "\"\r\n\r\n" + << url.getParameters().getAllValues() [i] + << "\r\n--" + << boundary; - appendUTF8ToPostData (s); - } + appendUTF8ToPostData (s); + } - for (i = 0; i < url.getFilesToUpload().size(); ++i) - { - const File f (url.getFilesToUpload().getAllValues() [i]); - const String paramName (url.getFilesToUpload().getAllKeys() [i]); + for (i = 0; i < url.getFilesToUpload().size(); ++i) + { + const File f (url.getFilesToUpload().getAllValues() [i]); + const String paramName (url.getFilesToUpload().getAllKeys() [i]); - String s; - s << "\r\nContent-Disposition: form-data; name=\"" - << paramName - << "\"; filename=\"" - << f.getFileName() - << "\"\r\n"; + String s; + s << "\r\nContent-Disposition: form-data; name=\"" + << paramName + << "\"; filename=\"" + << f.getFileName() + << "\"\r\n"; - const String mimeType (url.getMimeTypesOfUploadFiles() - .getValue (paramName, String::empty)); + const String mimeType (url.getMimeTypesOfUploadFiles() + .getValue (paramName, String::empty)); - if (mimeType.isNotEmpty()) - s << "Content-Type: " << mimeType << "\r\n"; + if (mimeType.isNotEmpty()) + s << "Content-Type: " << mimeType << "\r\n"; - s << "Content-Transfer-Encoding: binary\r\n\r\n"; + s << "Content-Transfer-Encoding: binary\r\n\r\n"; - appendUTF8ToPostData (s); + appendUTF8ToPostData (s); - f.loadFileAsData (postData); + f.loadFileAsData (postData); - s = "\r\n--" + boundary; + s = "\r\n--" + boundary; - appendUTF8ToPostData (s); - } + appendUTF8ToPostData (s); + } - appendUTF8ToPostData ("--\r\n"); - } - else - { - appendUTF8ToPostData (getMangledParameters (url.getParameters())); - appendUTF8ToPostData (url.getPostData()); + appendUTF8ToPostData ("--\r\n"); + } + else + { + appendUTF8ToPostData (getMangledParameters (url.getParameters())); + appendUTF8ToPostData (url.getPostData()); - // just a short text attachment, so use simple url encoding.. - headers = "Content-Type: application/x-www-form-urlencoded\r\nContent-length: " - + String (postData.getSize()) - + "\r\n"; - } - } + // just a short text attachment, so use simple url encoding.. + headers = "Content-Type: application/x-www-form-urlencoded\r\nContent-length: " + + String ((unsigned int) postData.getSize()) + + "\r\n"; + } + } - void appendUTF8ToPostData (const String& text) - { - postData.append (text.toUTF8(), - (int) strlen (text.toUTF8())); - } + void appendUTF8ToPostData (const String& text) + { + postData.append (text.toUTF8(), + (int) strlen (text.toUTF8())); + } - WebInputStream (const WebInputStream&); - const WebInputStream& operator= (const WebInputStream&); + WebInputStream (const WebInputStream&); + const WebInputStream& operator= (const WebInputStream&); }; InputStream* URL::createInputStream (const bool usePostCommand, - OpenStreamProgressCallback* const progressCallback, - void* const progressCallbackContext, - const String& extraHeaders, - const int timeOutMs) const + OpenStreamProgressCallback* const progressCallback, + void* const progressCallbackContext, + const String& extraHeaders, + const int timeOutMs) const { - ScopedPointer wi (new WebInputStream (*this, usePostCommand, - progressCallback, progressCallbackContext, - extraHeaders, - timeOutMs)); + ScopedPointer wi (new WebInputStream (*this, usePostCommand, + progressCallback, progressCallbackContext, + extraHeaders, + timeOutMs)); - return wi->isError() ? 0 : wi.release(); + return wi->isError() ? 0 : wi.release(); } bool URL::readEntireBinaryStream (MemoryBlock& destData, - const bool usePostCommand) const + const bool usePostCommand) const { - const ScopedPointer in (createInputStream (usePostCommand)); + const ScopedPointer in (createInputStream (usePostCommand)); - if (in != 0) - { - in->readIntoMemoryBlock (destData, -1); - return true; - } + if (in != 0) + { + in->readIntoMemoryBlock (destData, -1); + return true; + } - return false; + return false; } const String URL::readEntireTextStream (const bool usePostCommand) const { - const ScopedPointer in (createInputStream (usePostCommand)); + const ScopedPointer in (createInputStream (usePostCommand)); - if (in != 0) - return in->readEntireStreamAsString(); + if (in != 0) + return in->readEntireStreamAsString(); - return String::empty; + return String::empty; } XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const { - XmlDocument doc (readEntireTextStream (usePostCommand)); - return doc.getDocumentElement(); + XmlDocument doc (readEntireTextStream (usePostCommand)); + return doc.getDocumentElement(); } const URL URL::withParameter (const String& parameterName, - const String& parameterValue) const + const String& parameterValue) const { - URL u (*this); - u.parameters.set (parameterName, parameterValue); - return u; + URL u (*this); + u.parameters.set (parameterName, parameterValue); + return u; } const URL URL::withFileToUpload (const String& parameterName, - const File& fileToUpload, - const String& mimeType) const + const File& fileToUpload, + const String& mimeType) const { - jassert (mimeType.isNotEmpty()); // You need to supply a mime type! + jassert (mimeType.isNotEmpty()); // You need to supply a mime type! - URL u (*this); - u.filesToUpload.set (parameterName, fileToUpload.getFullPathName()); - u.mimeTypes.set (parameterName, mimeType); - return u; + URL u (*this); + u.filesToUpload.set (parameterName, fileToUpload.getFullPathName()); + u.mimeTypes.set (parameterName, mimeType); + return u; } const URL URL::withPOSTData (const String& postData_) const { - URL u (*this); - u.postData = postData_; - return u; + URL u (*this); + u.postData = postData_; + return u; } const StringPairArray& URL::getParameters() const { - return parameters; + return parameters; } const StringPairArray& URL::getFilesToUpload() const { - return filesToUpload; + return filesToUpload; } const StringPairArray& URL::getMimeTypesOfUploadFiles() const { - return mimeTypes; + return mimeTypes; } const String URL::removeEscapeChars (const String& s) { - const int len = s.length(); - HeapBlock resultUTF8 (len * 4); - uint8* r = resultUTF8; + const int len = s.length(); + HeapBlock resultUTF8 (len * 4); + uint8* r = resultUTF8; - for (int i = 0; i < len; ++i) - { - char c = (char) s[i]; - if (c == 0) - break; + for (int i = 0; i < len; ++i) + { + char c = (char) s[i]; + if (c == 0) + break; - if (c == '+') - { - c = ' '; - } - else if (c == '%') - { - c = (char) s.substring (i + 1, i + 3).getHexValue32(); - i += 2; - } + if (c == '+') + { + c = ' '; + } + else if (c == '%') + { + c = (char) s.substring (i + 1, i + 3).getHexValue32(); + i += 2; + } - *r++ = c; - } + *r++ = c; + } - return String::fromUTF8 (resultUTF8); + return String::fromUTF8 (resultUTF8); } const String URL::addEscapeChars (const String& s, const bool isParameter) { - String result; - result.preallocateStorage (s.length() + 8); - const char* utf8 = s.toUTF8(); - const char* legalChars = isParameter ? "_-.*!'()" - : "_-$.*!'(),"; + String result; + result.preallocateStorage (s.length() + 8); + const char* utf8 = s.toUTF8(); + const char* legalChars = isParameter ? "_-.*!'()" + : "_-$.*!'(),"; - while (*utf8 != 0) - { - const char c = *utf8++; + while (*utf8 != 0) + { + const char c = *utf8++; - if (CharacterFunctions::isLetterOrDigit (c) - || CharacterFunctions::indexOfChar (legalChars, c, false) >= 0) - { - result << c; - } - else - { - const int v = (int) (uint8) c; + if (CharacterFunctions::isLetterOrDigit (c) + || CharacterFunctions::indexOfChar (legalChars, c, false) >= 0) + { + result << c; + } + else + { + const int v = (int) (uint8) c; - if (v < 0x10) - result << T("%0"); - else - result << T('%'); + if (v < 0x10) + result << T("%0"); + else + result << T('%'); - result << String::toHexString (v); - } - } + result << String::toHexString (v); + } + } - return result; + return result; } extern bool juce_launchFile (const String& fileName, const String& parameters); bool URL::launchInDefaultBrowser() const { - String u (toString (true)); + String u (toString (true)); - if (u.contains (T("@")) && ! u.contains (T(":"))) - u = "mailto:" + u; + if (u.contains (T("@")) && ! u.contains (T(":"))) + u = "mailto:" + u; - return juce_launchFile (u, String::empty); + return juce_launchFile (u, String::empty); } END_JUCE_NAMESPACE @@ -8624,21 +8386,21 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE BufferedInputStream::BufferedInputStream (InputStream* const source_, - const int bufferSize_, - const bool deleteSourceWhenDestroyed) + const int bufferSize_, + const bool deleteSourceWhenDestroyed) : source (source_), - sourceToDelete (deleteSourceWhenDestroyed ? source_ : 0), - bufferSize (jmax (256, bufferSize_)), - position (source_->getPosition()), - lastReadPos (0), - bufferOverlap (128) + sourceToDelete (deleteSourceWhenDestroyed ? source_ : 0), + bufferSize (jmax (256, bufferSize_)), + position (source_->getPosition()), + lastReadPos (0), + bufferOverlap (128) { - const int sourceSize = (int) source_->getTotalLength(); - if (sourceSize >= 0) - bufferSize = jmin (jmax (32, sourceSize), bufferSize); + const int sourceSize = (int) source_->getTotalLength(); + if (sourceSize >= 0) + bufferSize = jmin (jmax (32, sourceSize), bufferSize); - bufferStart = position; - buffer.malloc (bufferSize); + bufferStart = position; + buffer.malloc (bufferSize); } BufferedInputStream::~BufferedInputStream() @@ -8647,127 +8409,127 @@ BufferedInputStream::~BufferedInputStream() int64 BufferedInputStream::getTotalLength() { - return source->getTotalLength(); + return source->getTotalLength(); } int64 BufferedInputStream::getPosition() { - return position; + return position; } bool BufferedInputStream::setPosition (int64 newPosition) { - position = jmax ((int64) 0, newPosition); - return true; + position = jmax ((int64) 0, newPosition); + return true; } bool BufferedInputStream::isExhausted() { - return (position >= lastReadPos) - && source->isExhausted(); + return (position >= lastReadPos) + && source->isExhausted(); } void BufferedInputStream::ensureBuffered() { - const int64 bufferEndOverlap = lastReadPos - bufferOverlap; + const int64 bufferEndOverlap = lastReadPos - bufferOverlap; - if (position < bufferStart || position >= bufferEndOverlap) - { - int bytesRead; + if (position < bufferStart || position >= bufferEndOverlap) + { + int bytesRead; - if (position < lastReadPos - && position >= bufferEndOverlap - && position >= bufferStart) - { - const int bytesToKeep = (int) (lastReadPos - position); - memmove (buffer, buffer + (int) (position - bufferStart), bytesToKeep); + if (position < lastReadPos + && position >= bufferEndOverlap + && position >= bufferStart) + { + const int bytesToKeep = (int) (lastReadPos - position); + memmove (buffer, buffer + (int) (position - bufferStart), bytesToKeep); - bufferStart = position; + bufferStart = position; - bytesRead = source->read (buffer + bytesToKeep, - bufferSize - bytesToKeep); + bytesRead = source->read (buffer + bytesToKeep, + bufferSize - bytesToKeep); - lastReadPos += bytesRead; - bytesRead += bytesToKeep; - } - else - { - bufferStart = position; - source->setPosition (bufferStart); - bytesRead = source->read (buffer, bufferSize); - lastReadPos = bufferStart + bytesRead; - } + lastReadPos += bytesRead; + bytesRead += bytesToKeep; + } + else + { + bufferStart = position; + source->setPosition (bufferStart); + bytesRead = source->read (buffer, bufferSize); + lastReadPos = bufferStart + bytesRead; + } - while (bytesRead < bufferSize) - buffer [bytesRead++] = 0; - } + while (bytesRead < bufferSize) + buffer [bytesRead++] = 0; + } } int BufferedInputStream::read (void* destBuffer, int maxBytesToRead) { - if (position >= bufferStart - && position + maxBytesToRead <= lastReadPos) - { - memcpy (destBuffer, buffer + (int) (position - bufferStart), maxBytesToRead); - position += maxBytesToRead; + if (position >= bufferStart + && position + maxBytesToRead <= lastReadPos) + { + memcpy (destBuffer, buffer + (int) (position - bufferStart), maxBytesToRead); + position += maxBytesToRead; - return maxBytesToRead; - } - else - { - if (position < bufferStart || position >= lastReadPos) - ensureBuffered(); + return maxBytesToRead; + } + else + { + if (position < bufferStart || position >= lastReadPos) + ensureBuffered(); - int bytesRead = 0; + int bytesRead = 0; - while (maxBytesToRead > 0) - { - const int bytesAvailable = jmin (maxBytesToRead, (int) (lastReadPos - position)); + while (maxBytesToRead > 0) + { + const int bytesAvailable = jmin (maxBytesToRead, (int) (lastReadPos - position)); - if (bytesAvailable > 0) - { - memcpy (destBuffer, buffer + (int) (position - bufferStart), bytesAvailable); - maxBytesToRead -= bytesAvailable; - bytesRead += bytesAvailable; - position += bytesAvailable; - destBuffer = (void*) (((char*) destBuffer) + bytesAvailable); - } + if (bytesAvailable > 0) + { + memcpy (destBuffer, buffer + (int) (position - bufferStart), bytesAvailable); + maxBytesToRead -= bytesAvailable; + bytesRead += bytesAvailable; + position += bytesAvailable; + destBuffer = (void*) (((char*) destBuffer) + bytesAvailable); + } - const int64 oldLastReadPos = lastReadPos; - ensureBuffered(); + const int64 oldLastReadPos = lastReadPos; + ensureBuffered(); - if (oldLastReadPos == lastReadPos) - break; // if ensureBuffered() failed to read any more data, bail out + if (oldLastReadPos == lastReadPos) + break; // if ensureBuffered() failed to read any more data, bail out - if (isExhausted()) - break; - } + if (isExhausted()) + break; + } - return bytesRead; - } + return bytesRead; + } } const String BufferedInputStream::readString() { - if (position >= bufferStart - && position < lastReadPos) - { - const int maxChars = (int) (lastReadPos - position); + if (position >= bufferStart + && position < lastReadPos) + { + const int maxChars = (int) (lastReadPos - position); - const char* const src = buffer + (int) (position - bufferStart); + const char* const src = buffer + (int) (position - bufferStart); - for (int i = 0; i < maxChars; ++i) - { - if (src[i] == 0) - { - position += i + 1; + for (int i = 0; i < maxChars; ++i) + { + if (src[i] == 0) + { + position += i + 1; - return String::fromUTF8 ((const uint8*) src, i); - } - } - } + return String::fromUTF8 ((const uint8*) src, i); + } + } + } - return InputStream::readString(); + return InputStream::readString(); } END_JUCE_NAMESPACE @@ -8778,7 +8540,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE FileInputSource::FileInputSource (const File& file_) - : file (file_) + : file (file_) { } @@ -8788,17 +8550,17 @@ FileInputSource::~FileInputSource() InputStream* FileInputSource::createInputStream() { - return file.createInputStream(); + return file.createInputStream(); } InputStream* FileInputSource::createInputStreamFor (const String& relatedItemPath) { - return file.getSiblingFile (relatedItemPath).createInputStream(); + return file.getSiblingFile (relatedItemPath).createInputStream(); } int64 FileInputSource::hashCode() const { - return file.hashCode(); + return file.hashCode(); } END_JUCE_NAMESPACE @@ -8809,17 +8571,17 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MemoryInputStream::MemoryInputStream (const void* const sourceData, - const int sourceDataSize, - const bool keepInternalCopy) - : data ((const char*) sourceData), - dataSize (sourceDataSize), - position (0) + const size_t sourceDataSize, + const bool keepInternalCopy) + : data ((const char*) sourceData), + dataSize (sourceDataSize), + position (0) { - if (keepInternalCopy) - { - internalCopy.append (data, sourceDataSize); - data = (const char*) internalCopy.getData(); - } + if (keepInternalCopy) + { + internalCopy.append (data, sourceDataSize); + data = (const char*) internalCopy.getData(); + } } MemoryInputStream::~MemoryInputStream() @@ -8828,32 +8590,33 @@ MemoryInputStream::~MemoryInputStream() int64 MemoryInputStream::getTotalLength() { - return dataSize; + return dataSize; } int MemoryInputStream::read (void* buffer, int howMany) { - const int num = jmin (howMany, dataSize - position); - memcpy (buffer, data + position, num); - position += num; - return num; + jassert (howMany >= 0); + const int num = jmin (howMany, (int) (dataSize - position)); + memcpy (buffer, data + position, num); + position += num; + return (int) num; } bool MemoryInputStream::isExhausted() { - return (position >= dataSize); + return (position >= dataSize); } bool MemoryInputStream::setPosition (int64 pos) { - position = (int) jlimit ((int64) 0, (int64) dataSize, pos); + position = (int) jlimit ((int64) 0, (int64) dataSize, pos); - return true; + return true; } int64 MemoryInputStream::getPosition() { - return position; + return position; } END_JUCE_NAMESPACE @@ -8863,91 +8626,91 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -MemoryOutputStream::MemoryOutputStream (const int initialSize, - const int blockSizeToIncreaseBy, - MemoryBlock* const memoryBlockToWriteTo) throw() +MemoryOutputStream::MemoryOutputStream (const size_t initialSize, + const size_t blockSizeToIncreaseBy, + MemoryBlock* const memoryBlockToWriteTo) throw() : data (memoryBlockToWriteTo), - position (0), - size (0), - blockSize (jmax (16, blockSizeToIncreaseBy)) + position (0), + size (0), + blockSize (jmax ((size_t) 16, blockSizeToIncreaseBy)) { - if (data == 0) - dataToDelete = data = new MemoryBlock (initialSize); - else - data->setSize (initialSize, false); + if (data == 0) + dataToDelete = data = new MemoryBlock (initialSize); + else + data->setSize (initialSize, false); } MemoryOutputStream::~MemoryOutputStream() throw() { - flush(); + flush(); } void MemoryOutputStream::flush() { - if (dataToDelete == 0) - data->setSize (size, false); + if (dataToDelete == 0) + data->setSize (size, false); } void MemoryOutputStream::reset() throw() { - position = 0; - size = 0; + position = 0; + size = 0; } bool MemoryOutputStream::write (const void* buffer, int howMany) { - if (howMany > 0) - { - int storageNeeded = position + howMany; + if (howMany > 0) + { + size_t storageNeeded = position + howMany; - if (storageNeeded >= data->getSize()) - { - // if we need more space, increase the block by at least 10%.. - storageNeeded += jmax (blockSize, storageNeeded / 10); - storageNeeded = storageNeeded - (storageNeeded % blockSize) + blockSize; + if (storageNeeded >= data->getSize()) + { + // if we need more space, increase the block by at least 10%.. + storageNeeded += jmax (blockSize, storageNeeded / 10); + storageNeeded = storageNeeded - (storageNeeded % blockSize) + blockSize; - data->ensureSize (storageNeeded); - } + data->ensureSize (storageNeeded); + } - data->copyFrom (buffer, position, howMany); - position += howMany; - size = jmax (size, position); - } + data->copyFrom (buffer, (int) position, howMany); + position += howMany; + size = jmax (size, position); + } - return true; + return true; } const char* MemoryOutputStream::getData() throw() { - if (data->getSize() > size) - ((char*) data->getData()) [size] = 0; + if (data->getSize() > size) + ((char*) data->getData()) [size] = 0; - return (const char*) data->getData(); + return (const char*) data->getData(); } -int MemoryOutputStream::getDataSize() const throw() +size_t MemoryOutputStream::getDataSize() const throw() { - return size; + return size; } int64 MemoryOutputStream::getPosition() { - return position; + return position; } bool MemoryOutputStream::setPosition (int64 newPosition) { - if (newPosition <= size) - { - // ok to seek backwards - position = jlimit (0, size, (int) newPosition); - return true; - } - else - { - // trying to make it bigger isn't a good thing to do.. - return false; - } + if (newPosition <= (int64) size) + { + // ok to seek backwards + position = jlimit ((size_t) 0, size, (size_t) newPosition); + return true; + } + else + { + // trying to make it bigger isn't a good thing to do.. + return false; + } } END_JUCE_NAMESPACE @@ -8958,17 +8721,17 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE SubregionStream::SubregionStream (InputStream* const sourceStream, - const int64 startPositionInSourceStream_, - const int64 lengthOfSourceStream_, - const bool deleteSourceWhenDestroyed) throw() + const int64 startPositionInSourceStream_, + const int64 lengthOfSourceStream_, + const bool deleteSourceWhenDestroyed) throw() : source (sourceStream), - startPositionInSourceStream (startPositionInSourceStream_), - lengthOfSourceStream (lengthOfSourceStream_) + startPositionInSourceStream (startPositionInSourceStream_), + lengthOfSourceStream (lengthOfSourceStream_) { - if (deleteSourceWhenDestroyed) - sourceToDelete = source; + if (deleteSourceWhenDestroyed) + sourceToDelete = source; - setPosition (0); + setPosition (0); } SubregionStream::~SubregionStream() throw() @@ -8977,45 +8740,45 @@ SubregionStream::~SubregionStream() throw() int64 SubregionStream::getTotalLength() { - const int64 srcLen = source->getTotalLength() - startPositionInSourceStream; + const int64 srcLen = source->getTotalLength() - startPositionInSourceStream; - return (lengthOfSourceStream >= 0) ? jmin (lengthOfSourceStream, srcLen) - : srcLen; + return (lengthOfSourceStream >= 0) ? jmin (lengthOfSourceStream, srcLen) + : srcLen; } int64 SubregionStream::getPosition() { - return source->getPosition() - startPositionInSourceStream; + return source->getPosition() - startPositionInSourceStream; } bool SubregionStream::setPosition (int64 newPosition) { - return source->setPosition (jmax ((int64) 0, newPosition + startPositionInSourceStream)); + return source->setPosition (jmax ((int64) 0, newPosition + startPositionInSourceStream)); } int SubregionStream::read (void* destBuffer, int maxBytesToRead) { - if (lengthOfSourceStream < 0) - { - return source->read (destBuffer, maxBytesToRead); - } - else - { - maxBytesToRead = (int) jmin ((int64) maxBytesToRead, lengthOfSourceStream - getPosition()); + if (lengthOfSourceStream < 0) + { + return source->read (destBuffer, maxBytesToRead); + } + else + { + maxBytesToRead = (int) jmin ((int64) maxBytesToRead, lengthOfSourceStream - getPosition()); - if (maxBytesToRead <= 0) - return 0; + if (maxBytesToRead <= 0) + return 0; - return source->read (destBuffer, maxBytesToRead); - } + return source->read (destBuffer, maxBytesToRead); + } } bool SubregionStream::isExhausted() { - if (lengthOfSourceStream >= 0) - return (getPosition() >= lengthOfSourceStream) || source->isExhausted(); - else - return source->isExhausted(); + if (lengthOfSourceStream >= 0) + return (getPosition() >= lengthOfSourceStream) || source->isExhausted(); + else + return source->isExhausted(); } END_JUCE_NAMESPACE @@ -9026,71 +8789,71 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE PerformanceCounter::PerformanceCounter (const String& name_, - int runsPerPrintout, - const File& loggingFile) - : name (name_), - numRuns (0), - runsPerPrint (runsPerPrintout), - totalTime (0), - outputFile (loggingFile) + int runsPerPrintout, + const File& loggingFile) + : name (name_), + numRuns (0), + runsPerPrint (runsPerPrintout), + totalTime (0), + outputFile (loggingFile) { - if (outputFile != File::nonexistent) - { - String s ("**** Counter for \""); - s << name_ << "\" started at: " - << Time::getCurrentTime().toString (true, true) - << "\r\n"; + if (outputFile != File::nonexistent) + { + String s ("**** Counter for \""); + s << name_ << "\" started at: " + << Time::getCurrentTime().toString (true, true) + << "\r\n"; - outputFile.appendText (s, false, false); - } + outputFile.appendText (s, false, false); + } } PerformanceCounter::~PerformanceCounter() { - printStatistics(); + printStatistics(); } void PerformanceCounter::start() { - started = Time::getHighResolutionTicks(); + started = Time::getHighResolutionTicks(); } void PerformanceCounter::stop() { - const int64 now = Time::getHighResolutionTicks(); + const int64 now = Time::getHighResolutionTicks(); - totalTime += 1000.0 * Time::highResolutionTicksToSeconds (now - started); + totalTime += 1000.0 * Time::highResolutionTicksToSeconds (now - started); - if (++numRuns == runsPerPrint) - printStatistics(); + if (++numRuns == runsPerPrint) + printStatistics(); } void PerformanceCounter::printStatistics() { - if (numRuns > 0) - { - String s ("Performance count for \""); - s << name << "\" - average over " << numRuns << " run(s) = "; + if (numRuns > 0) + { + String s ("Performance count for \""); + s << name << "\" - average over " << numRuns << " run(s) = "; - const int micros = (int) (totalTime * (1000.0 / numRuns)); + const int micros = (int) (totalTime * (1000.0 / numRuns)); - if (micros > 10000) - s << (micros/1000) << " millisecs"; - else - s << micros << " microsecs"; + if (micros > 10000) + s << (micros/1000) << " millisecs"; + else + s << micros << " microsecs"; - s << ", total = " << String (totalTime / 1000, 5) << " seconds"; + s << ", total = " << String (totalTime / 1000, 5) << " seconds"; - Logger::outputDebugString (s); + Logger::outputDebugString (s); - s << "\r\n"; + s << "\r\n"; - if (outputFile != File::nonexistent) - outputFile.appendText (s, false, false); + if (outputFile != File::nonexistent) + outputFile.appendText (s, false, false); - numRuns = 0; - totalTime = 0; - } + numRuns = 0; + totalTime = 0; + } } END_JUCE_NAMESPACE @@ -9102,33 +8865,33 @@ BEGIN_JUCE_NAMESPACE Uuid::Uuid() { - // Mix up any available MAC addresses with some time-based pseudo-random numbers - // to make it very very unlikely that two UUIDs will ever be the same.. + // Mix up any available MAC addresses with some time-based pseudo-random numbers + // to make it very very unlikely that two UUIDs will ever be the same.. - static int64 macAddresses[2]; - static bool hasCheckedMacAddresses = false; + static int64 macAddresses[2]; + static bool hasCheckedMacAddresses = false; - if (! hasCheckedMacAddresses) - { - hasCheckedMacAddresses = true; - SystemStats::getMACAddresses (macAddresses, 2); - } + if (! hasCheckedMacAddresses) + { + hasCheckedMacAddresses = true; + SystemStats::getMACAddresses (macAddresses, 2); + } - value.asInt64[0] = macAddresses[0]; - value.asInt64[1] = macAddresses[1]; + value.asInt64[0] = macAddresses[0]; + value.asInt64[1] = macAddresses[1]; - // We'll use both a local RNG that is re-seeded, plus the shared RNG, - // whose seed will carry over between calls to this method. + // We'll use both a local RNG that is re-seeded, plus the shared RNG, + // whose seed will carry over between calls to this method. - Random r (macAddresses[0] ^ macAddresses[1] - ^ Random::getSystemRandom().nextInt64()); + Random r (macAddresses[0] ^ macAddresses[1] + ^ Random::getSystemRandom().nextInt64()); - for (int i = 4; --i >= 0;) - { - r.setSeedRandomly(); // calling this repeatedly improves randomness - value.asInt[i] ^= r.nextInt(); - value.asInt[i] ^= Random::getSystemRandom().nextInt(); - } + for (int i = 4; --i >= 0;) + { + r.setSeedRandomly(); // calling this repeatedly improves randomness + value.asInt[i] ^= r.nextInt(); + value.asInt[i] ^= Random::getSystemRandom().nextInt(); + } } Uuid::~Uuid() throw() @@ -9136,102 +8899,102 @@ Uuid::~Uuid() throw() } Uuid::Uuid (const Uuid& other) - : value (other.value) + : value (other.value) { } Uuid& Uuid::operator= (const Uuid& other) { - if (this != &other) - value = other.value; + if (this != &other) + value = other.value; - return *this; + return *this; } bool Uuid::operator== (const Uuid& other) const { - return memcmp (value.asBytes, other.value.asBytes, 16) == 0; + return memcmp (value.asBytes, other.value.asBytes, 16) == 0; } bool Uuid::operator!= (const Uuid& other) const { - return ! operator== (other); + return ! operator== (other); } bool Uuid::isNull() const throw() { - return (value.asInt64 [0] == 0) && (value.asInt64 [1] == 0); + return (value.asInt64 [0] == 0) && (value.asInt64 [1] == 0); } const String Uuid::toString() const { - return String::toHexString (value.asBytes, 16, 0); + return String::toHexString (value.asBytes, 16, 0); } Uuid::Uuid (const String& uuidString) { - operator= (uuidString); + operator= (uuidString); } Uuid& Uuid::operator= (const String& uuidString) { - int destIndex = 0; - int i = 0; + int destIndex = 0; + int i = 0; - for (;;) - { - int byte = 0; + for (;;) + { + int byte = 0; - for (int loop = 2; --loop >= 0;) - { - byte <<= 4; + for (int loop = 2; --loop >= 0;) + { + byte <<= 4; - for (;;) - { - const tchar c = uuidString [i++]; + for (;;) + { + const tchar c = uuidString [i++]; - if (c >= T('0') && c <= T('9')) - { - byte |= c - T('0'); - break; - } - else if (c >= T('a') && c <= T('z')) - { - byte |= c - (T('a') - 10); - break; - } - else if (c >= T('A') && c <= T('Z')) - { - byte |= c - (T('A') - 10); - break; - } - else if (c == 0) - { - while (destIndex < 16) - value.asBytes [destIndex++] = 0; + if (c >= T('0') && c <= T('9')) + { + byte |= c - T('0'); + break; + } + else if (c >= T('a') && c <= T('z')) + { + byte |= c - (T('a') - 10); + break; + } + else if (c >= T('A') && c <= T('Z')) + { + byte |= c - (T('A') - 10); + break; + } + else if (c == 0) + { + while (destIndex < 16) + value.asBytes [destIndex++] = 0; - return *this; - } - } - } + return *this; + } + } + } - value.asBytes [destIndex++] = (uint8) byte; - } + value.asBytes [destIndex++] = (uint8) byte; + } } Uuid::Uuid (const uint8* const rawData) { - operator= (rawData); + operator= (rawData); } Uuid& Uuid::operator= (const uint8* const rawData) { - if (rawData != 0) - memcpy (value.asBytes, rawData, 16); - else - zeromem (value.asBytes, 16); + if (rawData != 0) + memcpy (value.asBytes, rawData, 16); + else + zeromem (value.asBytes, 16); - return *this; + return *this; } END_JUCE_NAMESPACE @@ -9244,377 +9007,377 @@ BEGIN_JUCE_NAMESPACE class ZipFile::ZipEntryInfo { public: - ZipFile::ZipEntry entry; - int streamOffset; - int compressedSize; - bool compressed; + ZipFile::ZipEntry entry; + int streamOffset; + int compressedSize; + bool compressed; }; class ZipFile::ZipInputStream : public InputStream { public: - ZipInputStream (ZipFile& file_, ZipFile::ZipEntryInfo& zei) - : file (file_), - zipEntryInfo (zei), - pos (0), - headerSize (0), - inputStream (0) - { - inputStream = file_.inputStream; + ZipInputStream (ZipFile& file_, ZipFile::ZipEntryInfo& zei) + : file (file_), + zipEntryInfo (zei), + pos (0), + headerSize (0), + inputStream (0) + { + inputStream = file_.inputStream; - if (file_.inputSource != 0) - { - inputStream = file.inputSource->createInputStream(); - } - else - { + if (file_.inputSource != 0) + { + inputStream = file.inputSource->createInputStream(); + } + else + { #ifdef JUCE_DEBUG - file_.numOpenStreams++; + file_.numOpenStreams++; #endif - } + } - char buffer [30]; + char buffer [30]; - if (inputStream != 0 - && inputStream->setPosition (zei.streamOffset) - && inputStream->read (buffer, 30) == 30 - && ByteOrder::littleEndianInt (buffer) == 0x04034b50) - { - headerSize = 30 + ByteOrder::littleEndianShort (buffer + 26) - + ByteOrder::littleEndianShort (buffer + 28); - } - } + if (inputStream != 0 + && inputStream->setPosition (zei.streamOffset) + && inputStream->read (buffer, 30) == 30 + && ByteOrder::littleEndianInt (buffer) == 0x04034b50) + { + headerSize = 30 + ByteOrder::littleEndianShort (buffer + 26) + + ByteOrder::littleEndianShort (buffer + 28); + } + } - ~ZipInputStream() throw() - { + ~ZipInputStream() throw() + { #ifdef JUCE_DEBUG - if (inputStream != 0 && inputStream == file.inputStream) - file.numOpenStreams--; + if (inputStream != 0 && inputStream == file.inputStream) + file.numOpenStreams--; #endif - if (inputStream != file.inputStream) - delete inputStream; - } + if (inputStream != file.inputStream) + delete inputStream; + } - int64 getTotalLength() throw() - { - return zipEntryInfo.compressedSize; - } + int64 getTotalLength() throw() + { + return zipEntryInfo.compressedSize; + } - int read (void* buffer, int howMany) throw() - { - if (headerSize <= 0) - return 0; + int read (void* buffer, int howMany) throw() + { + if (headerSize <= 0) + return 0; - howMany = (int) jmin ((int64) howMany, zipEntryInfo.compressedSize - pos); + howMany = (int) jmin ((int64) howMany, zipEntryInfo.compressedSize - pos); - if (inputStream == 0) - return 0; + if (inputStream == 0) + return 0; - int num; + int num; - if (inputStream == file.inputStream) - { - const ScopedLock sl (file.lock); - inputStream->setPosition (pos + zipEntryInfo.streamOffset + headerSize); - num = inputStream->read (buffer, howMany); - } - else - { - inputStream->setPosition (pos + zipEntryInfo.streamOffset + headerSize); - num = inputStream->read (buffer, howMany); - } + if (inputStream == file.inputStream) + { + const ScopedLock sl (file.lock); + inputStream->setPosition (pos + zipEntryInfo.streamOffset + headerSize); + num = inputStream->read (buffer, howMany); + } + else + { + inputStream->setPosition (pos + zipEntryInfo.streamOffset + headerSize); + num = inputStream->read (buffer, howMany); + } - pos += num; - return num; - } + pos += num; + return num; + } - bool isExhausted() throw() - { - return headerSize <= 0 || pos >= zipEntryInfo.compressedSize; - } + bool isExhausted() throw() + { + return headerSize <= 0 || pos >= zipEntryInfo.compressedSize; + } - int64 getPosition() throw() - { - return pos; - } + int64 getPosition() throw() + { + return pos; + } - bool setPosition (int64 newPos) throw() - { - pos = jlimit ((int64) 0, (int64) zipEntryInfo.compressedSize, newPos); - return true; - } + bool setPosition (int64 newPos) throw() + { + pos = jlimit ((int64) 0, (int64) zipEntryInfo.compressedSize, newPos); + return true; + } private: - ZipFile& file; - ZipEntryInfo zipEntryInfo; - int64 pos; - int headerSize; - InputStream* inputStream; + ZipFile& file; + ZipEntryInfo zipEntryInfo; + int64 pos; + int headerSize; + InputStream* inputStream; - ZipInputStream (const ZipInputStream&); - const ZipInputStream& operator= (const ZipInputStream&); + ZipInputStream (const ZipInputStream&); + const ZipInputStream& operator= (const ZipInputStream&); }; ZipFile::ZipFile (InputStream* const source_, - const bool deleteStreamWhenDestroyed) throw() + const bool deleteStreamWhenDestroyed) throw() : inputStream (source_) #ifdef JUCE_DEBUG - , numOpenStreams (0) + , numOpenStreams (0) #endif { - if (deleteStreamWhenDestroyed) - streamToDelete = inputStream; + if (deleteStreamWhenDestroyed) + streamToDelete = inputStream; - init(); + init(); } ZipFile::ZipFile (const File& file) - : inputStream (0) + : inputStream (0) #ifdef JUCE_DEBUG - , numOpenStreams (0) + , numOpenStreams (0) #endif { - inputSource = new FileInputSource (file); - init(); + inputSource = new FileInputSource (file); + init(); } ZipFile::ZipFile (InputSource* const inputSource_) - : inputStream (0), - inputSource (inputSource_) + : inputStream (0), + inputSource (inputSource_) #ifdef JUCE_DEBUG - , numOpenStreams (0) + , numOpenStreams (0) #endif { - init(); + init(); } ZipFile::~ZipFile() throw() { #ifdef JUCE_DEBUG - entries.clear(); + entries.clear(); - // If you hit this assertion, it means you've created a stream to read - // one of the items in the zipfile, but you've forgotten to delete that - // stream object before deleting the file.. Streams can't be kept open - // after the file is deleted because they need to share the input - // stream that the file uses to read itself. - jassert (numOpenStreams == 0); + // If you hit this assertion, it means you've created a stream to read + // one of the items in the zipfile, but you've forgotten to delete that + // stream object before deleting the file.. Streams can't be kept open + // after the file is deleted because they need to share the input + // stream that the file uses to read itself. + jassert (numOpenStreams == 0); #endif } int ZipFile::getNumEntries() const throw() { - return entries.size(); + return entries.size(); } const ZipFile::ZipEntry* ZipFile::getEntry (const int index) const throw() { - ZipEntryInfo* const zei = (ZipEntryInfo*) entries [index]; + ZipEntryInfo* const zei = (ZipEntryInfo*) entries [index]; - return (zei != 0) ? &(zei->entry) - : 0; + return (zei != 0) ? &(zei->entry) + : 0; } int ZipFile::getIndexOfFileName (const String& fileName) const throw() { - for (int i = 0; i < entries.size(); ++i) - if (entries.getUnchecked (i)->entry.filename == fileName) - return i; + for (int i = 0; i < entries.size(); ++i) + if (entries.getUnchecked (i)->entry.filename == fileName) + return i; - return -1; + return -1; } const ZipFile::ZipEntry* ZipFile::getEntry (const String& fileName) const throw() { - return getEntry (getIndexOfFileName (fileName)); + return getEntry (getIndexOfFileName (fileName)); } InputStream* ZipFile::createStreamForEntry (const int index) { - ZipEntryInfo* const zei = entries[index]; - InputStream* stream = 0; + ZipEntryInfo* const zei = entries[index]; + InputStream* stream = 0; - if (zei != 0) - { - stream = new ZipInputStream (*this, *zei); + if (zei != 0) + { + stream = new ZipInputStream (*this, *zei); - if (zei->compressed) - { - stream = new GZIPDecompressorInputStream (stream, true, true, - zei->entry.uncompressedSize); + if (zei->compressed) + { + stream = new GZIPDecompressorInputStream (stream, true, true, + zei->entry.uncompressedSize); - // (much faster to unzip in big blocks using a buffer..) - stream = new BufferedInputStream (stream, 32768, true); - } - } + // (much faster to unzip in big blocks using a buffer..) + stream = new BufferedInputStream (stream, 32768, true); + } + } - return stream; + return stream; } class ZipFile::ZipFilenameComparator { public: - int compareElements (const ZipFile::ZipEntryInfo* first, const ZipFile::ZipEntryInfo* second) - { - return first->entry.filename.compare (second->entry.filename); - } + int compareElements (const ZipFile::ZipEntryInfo* first, const ZipFile::ZipEntryInfo* second) + { + return first->entry.filename.compare (second->entry.filename); + } }; void ZipFile::sortEntriesByFilename() { - ZipFilenameComparator sorter; - entries.sort (sorter); + ZipFilenameComparator sorter; + entries.sort (sorter); } void ZipFile::init() { - ScopedPointer toDelete; - InputStream* in = inputStream; + ScopedPointer toDelete; + InputStream* in = inputStream; - if (inputSource != 0) - { - in = inputSource->createInputStream(); - toDelete = in; - } + if (inputSource != 0) + { + in = inputSource->createInputStream(); + toDelete = in; + } - if (in != 0) - { - int numEntries = 0; - int pos = findEndOfZipEntryTable (in, numEntries); + if (in != 0) + { + int numEntries = 0; + int pos = findEndOfZipEntryTable (in, numEntries); - if (pos >= 0 && pos < in->getTotalLength()) - { - const int size = (int) (in->getTotalLength() - pos); + if (pos >= 0 && pos < in->getTotalLength()) + { + const int size = (int) (in->getTotalLength() - pos); - in->setPosition (pos); - MemoryBlock headerData; + in->setPosition (pos); + MemoryBlock headerData; - if (in->readIntoMemoryBlock (headerData, size) == size) - { - pos = 0; + if (in->readIntoMemoryBlock (headerData, size) == size) + { + pos = 0; - for (int i = 0; i < numEntries; ++i) - { - if (pos + 46 > size) - break; + for (int i = 0; i < numEntries; ++i) + { + if (pos + 46 > size) + break; - const char* const buffer = ((const char*) headerData.getData()) + pos; + const char* const buffer = ((const char*) headerData.getData()) + pos; - const int fileNameLen = ByteOrder::littleEndianShort (buffer + 28); + const int fileNameLen = ByteOrder::littleEndianShort (buffer + 28); - if (pos + 46 + fileNameLen > size) - break; + if (pos + 46 + fileNameLen > size) + break; - ZipEntryInfo* const zei = new ZipEntryInfo(); - zei->entry.filename = String::fromUTF8 ((const uint8*) buffer + 46, fileNameLen); + ZipEntryInfo* const zei = new ZipEntryInfo(); + zei->entry.filename = String::fromUTF8 ((const uint8*) buffer + 46, fileNameLen); - const int time = ByteOrder::littleEndianShort (buffer + 12); - const int date = ByteOrder::littleEndianShort (buffer + 14); + const int time = ByteOrder::littleEndianShort (buffer + 12); + const int date = ByteOrder::littleEndianShort (buffer + 14); - const int year = 1980 + (date >> 9); - const int month = ((date >> 5) & 15) - 1; - const int day = date & 31; - const int hours = time >> 11; - const int minutes = (time >> 5) & 63; - const int seconds = (time & 31) << 1; + const int year = 1980 + (date >> 9); + const int month = ((date >> 5) & 15) - 1; + const int day = date & 31; + const int hours = time >> 11; + const int minutes = (time >> 5) & 63; + const int seconds = (time & 31) << 1; - zei->entry.fileTime = Time (year, month, day, hours, minutes, seconds); + zei->entry.fileTime = Time (year, month, day, hours, minutes, seconds); - zei->compressed = ByteOrder::littleEndianShort (buffer + 10) != 0; - zei->compressedSize = ByteOrder::littleEndianInt (buffer + 20); - zei->entry.uncompressedSize = ByteOrder::littleEndianInt (buffer + 24); + zei->compressed = ByteOrder::littleEndianShort (buffer + 10) != 0; + zei->compressedSize = ByteOrder::littleEndianInt (buffer + 20); + zei->entry.uncompressedSize = ByteOrder::littleEndianInt (buffer + 24); - zei->streamOffset = ByteOrder::littleEndianInt (buffer + 42); - entries.add (zei); + zei->streamOffset = ByteOrder::littleEndianInt (buffer + 42); + entries.add (zei); - pos += 46 + fileNameLen - + ByteOrder::littleEndianShort (buffer + 30) - + ByteOrder::littleEndianShort (buffer + 32); - } - } - } - } + pos += 46 + fileNameLen + + ByteOrder::littleEndianShort (buffer + 30) + + ByteOrder::littleEndianShort (buffer + 32); + } + } + } + } } int ZipFile::findEndOfZipEntryTable (InputStream* input, int& numEntries) { - BufferedInputStream in (input, 8192, false); + BufferedInputStream in (input, 8192, false); - in.setPosition (in.getTotalLength()); - int64 pos = in.getPosition(); - const int64 lowestPos = jmax ((int64) 0, pos - 1024); + in.setPosition (in.getTotalLength()); + int64 pos = in.getPosition(); + const int64 lowestPos = jmax ((int64) 0, pos - 1024); - char buffer [32]; - zeromem (buffer, sizeof (buffer)); + char buffer [32]; + zeromem (buffer, sizeof (buffer)); - while (pos > lowestPos) - { - in.setPosition (pos - 22); - pos = in.getPosition(); - memcpy (buffer + 22, buffer, 4); + while (pos > lowestPos) + { + in.setPosition (pos - 22); + pos = in.getPosition(); + memcpy (buffer + 22, buffer, 4); - if (in.read (buffer, 22) != 22) - return 0; + if (in.read (buffer, 22) != 22) + return 0; - for (int i = 0; i < 22; ++i) - { - if (ByteOrder::littleEndianInt (buffer + i) == 0x06054b50) - { - in.setPosition (pos + i); - in.read (buffer, 22); - numEntries = ByteOrder::littleEndianShort (buffer + 10); + for (int i = 0; i < 22; ++i) + { + if (ByteOrder::littleEndianInt (buffer + i) == 0x06054b50) + { + in.setPosition (pos + i); + in.read (buffer, 22); + numEntries = ByteOrder::littleEndianShort (buffer + 10); - return ByteOrder::littleEndianInt (buffer + 16); - } - } - } + return ByteOrder::littleEndianInt (buffer + 16); + } + } + } - return 0; + return 0; } void ZipFile::uncompressTo (const File& targetDirectory, - const bool shouldOverwriteFiles) + const bool shouldOverwriteFiles) { - for (int i = 0; i < entries.size(); ++i) - { - const ZipEntry& zei = entries.getUnchecked(i)->entry; + for (int i = 0; i < entries.size(); ++i) + { + const ZipEntry& zei = entries.getUnchecked(i)->entry; - const File targetFile (targetDirectory.getChildFile (zei.filename)); + const File targetFile (targetDirectory.getChildFile (zei.filename)); - if (zei.filename.endsWithChar (T('/'))) - { - targetFile.createDirectory(); // (entry is a directory, not a file) - } - else - { - ScopedPointer in (createStreamForEntry (i)); + if (zei.filename.endsWithChar (T('/'))) + { + targetFile.createDirectory(); // (entry is a directory, not a file) + } + else + { + ScopedPointer in (createStreamForEntry (i)); - if (in != 0) - { - if (shouldOverwriteFiles) - targetFile.deleteFile(); + if (in != 0) + { + if (shouldOverwriteFiles) + targetFile.deleteFile(); - if ((! targetFile.exists()) - && targetFile.getParentDirectory().createDirectory()) - { - ScopedPointer out (targetFile.createOutputStream()); + if ((! targetFile.exists()) + && targetFile.getParentDirectory().createDirectory()) + { + ScopedPointer out (targetFile.createOutputStream()); - if (out != 0) - { - out->writeFromInputStream (*in, -1); - out = 0; + if (out != 0) + { + out->writeFromInputStream (*in, -1); + out = 0; - targetFile.setCreationTime (zei.fileTime); - targetFile.setLastModificationTime (zei.fileTime); - targetFile.setLastAccessTime (zei.fileTime); - } - } - } - } - } + targetFile.setCreationTime (zei.fileTime); + targetFile.setLastModificationTime (zei.fileTime); + targetFile.setLastAccessTime (zei.fileTime); + } + } + } + } + } } END_JUCE_NAMESPACE @@ -9638,732 +9401,732 @@ BEGIN_JUCE_NAMESPACE int CharacterFunctions::length (const char* const s) throw() { - return (int) strlen (s); + return (int) strlen (s); } int CharacterFunctions::length (const juce_wchar* const s) throw() { - return (int) wcslen (s); + return (int) wcslen (s); } void CharacterFunctions::copy (char* dest, const char* src, const int maxChars) throw() { - strncpy (dest, src, maxChars); + strncpy (dest, src, maxChars); } void CharacterFunctions::copy (juce_wchar* dest, const juce_wchar* src, int maxChars) throw() { - wcsncpy (dest, src, maxChars); + wcsncpy (dest, src, maxChars); } void CharacterFunctions::copy (juce_wchar* dest, const char* src, const int maxChars) throw() { - mbstowcs (dest, src, maxChars); + mbstowcs (dest, src, maxChars); } void CharacterFunctions::copy (char* dest, const juce_wchar* src, const int maxChars) throw() { - wcstombs (dest, src, maxChars); + wcstombs (dest, src, maxChars); } int CharacterFunctions::bytesRequiredForCopy (const juce_wchar* src) throw() { - return (int) wcstombs (0, src, 0); + return (int) wcstombs (0, src, 0); } void CharacterFunctions::append (char* dest, const char* src) throw() { - strcat (dest, src); + strcat (dest, src); } void CharacterFunctions::append (juce_wchar* dest, const juce_wchar* src) throw() { - wcscat (dest, src); + wcscat (dest, src); } int CharacterFunctions::compare (const char* const s1, const char* const s2) throw() { - return strcmp (s1, s2); + return strcmp (s1, s2); } int CharacterFunctions::compare (const juce_wchar* s1, const juce_wchar* s2) throw() { - jassert (s1 != 0 && s2 != 0); - return wcscmp (s1, s2); + jassert (s1 != 0 && s2 != 0); + return wcscmp (s1, s2); } int CharacterFunctions::compare (const char* const s1, const char* const s2, const int maxChars) throw() { - jassert (s1 != 0 && s2 != 0); - return strncmp (s1, s2, maxChars); + jassert (s1 != 0 && s2 != 0); + return strncmp (s1, s2, maxChars); } int CharacterFunctions::compare (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw() { - jassert (s1 != 0 && s2 != 0); - return wcsncmp (s1, s2, maxChars); + jassert (s1 != 0 && s2 != 0); + return wcsncmp (s1, s2, maxChars); } int CharacterFunctions::compareIgnoreCase (const char* const s1, const char* const s2) throw() { - jassert (s1 != 0 && s2 != 0); + jassert (s1 != 0 && s2 != 0); #if JUCE_WIN32 - return stricmp (s1, s2); + return stricmp (s1, s2); #else - return strcasecmp (s1, s2); + return strcasecmp (s1, s2); #endif } int CharacterFunctions::compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2) throw() { - jassert (s1 != 0 && s2 != 0); + jassert (s1 != 0 && s2 != 0); #if JUCE_WIN32 - return _wcsicmp (s1, s2); + return _wcsicmp (s1, s2); #else - for (;;) - { - if (*s1 != *s2) - { - const int diff = toUpperCase (*s1) - toUpperCase (*s2); + for (;;) + { + if (*s1 != *s2) + { + const int diff = toUpperCase (*s1) - toUpperCase (*s2); - if (diff != 0) - return diff < 0 ? -1 : 1; - } - else if (*s1 == 0) - break; + if (diff != 0) + return diff < 0 ? -1 : 1; + } + else if (*s1 == 0) + break; - ++s1; - ++s2; - } + ++s1; + ++s2; + } - return 0; + return 0; #endif } int CharacterFunctions::compareIgnoreCase (const char* const s1, const char* const s2, const int maxChars) throw() { - jassert (s1 != 0 && s2 != 0); + jassert (s1 != 0 && s2 != 0); #if JUCE_WIN32 - return strnicmp (s1, s2, maxChars); + return strnicmp (s1, s2, maxChars); #else - return strncasecmp (s1, s2, maxChars); + return strncasecmp (s1, s2, maxChars); #endif } int CharacterFunctions::compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw() { - jassert (s1 != 0 && s2 != 0); + jassert (s1 != 0 && s2 != 0); #if JUCE_WIN32 - return _wcsnicmp (s1, s2, maxChars); + return _wcsnicmp (s1, s2, maxChars); #else - while (--maxChars >= 0) - { - if (*s1 != *s2) - { - const int diff = toUpperCase (*s1) - toUpperCase (*s2); + while (--maxChars >= 0) + { + if (*s1 != *s2) + { + const int diff = toUpperCase (*s1) - toUpperCase (*s2); - if (diff != 0) - return diff < 0 ? -1 : 1; - } - else if (*s1 == 0) - break; + if (diff != 0) + return diff < 0 ? -1 : 1; + } + else if (*s1 == 0) + break; - ++s1; - ++s2; - } + ++s1; + ++s2; + } - return 0; + return 0; #endif } const char* CharacterFunctions::find (const char* const haystack, const char* const needle) throw() { - return strstr (haystack, needle); + return strstr (haystack, needle); } const juce_wchar* CharacterFunctions::find (const juce_wchar* haystack, const juce_wchar* const needle) throw() { - return wcsstr (haystack, needle); + return wcsstr (haystack, needle); } int CharacterFunctions::indexOfChar (const char* const haystack, const char needle, const bool ignoreCase) throw() { - if (haystack != 0) - { - int i = 0; + if (haystack != 0) + { + int i = 0; - if (ignoreCase) - { - const char n1 = toLowerCase (needle); - const char n2 = toUpperCase (needle); + if (ignoreCase) + { + const char n1 = toLowerCase (needle); + const char n2 = toUpperCase (needle); - if (n1 != n2) // if the char is the same in upper/lower case, fall through to the normal search - { - while (haystack[i] != 0) - { - if (haystack[i] == n1 || haystack[i] == n2) - return i; + if (n1 != n2) // if the char is the same in upper/lower case, fall through to the normal search + { + while (haystack[i] != 0) + { + if (haystack[i] == n1 || haystack[i] == n2) + return i; - ++i; - } + ++i; + } - return -1; - } + return -1; + } - jassert (n1 == needle); - } + jassert (n1 == needle); + } - while (haystack[i] != 0) - { - if (haystack[i] == needle) - return i; + while (haystack[i] != 0) + { + if (haystack[i] == needle) + return i; - ++i; - } - } + ++i; + } + } - return -1; + return -1; } int CharacterFunctions::indexOfChar (const juce_wchar* const haystack, const juce_wchar needle, const bool ignoreCase) throw() { - if (haystack != 0) - { - int i = 0; + if (haystack != 0) + { + int i = 0; - if (ignoreCase) - { - const juce_wchar n1 = toLowerCase (needle); - const juce_wchar n2 = toUpperCase (needle); + if (ignoreCase) + { + const juce_wchar n1 = toLowerCase (needle); + const juce_wchar n2 = toUpperCase (needle); - if (n1 != n2) // if the char is the same in upper/lower case, fall through to the normal search - { - while (haystack[i] != 0) - { - if (haystack[i] == n1 || haystack[i] == n2) - return i; + if (n1 != n2) // if the char is the same in upper/lower case, fall through to the normal search + { + while (haystack[i] != 0) + { + if (haystack[i] == n1 || haystack[i] == n2) + return i; - ++i; - } + ++i; + } - return -1; - } + return -1; + } - jassert (n1 == needle); - } + jassert (n1 == needle); + } - while (haystack[i] != 0) - { - if (haystack[i] == needle) - return i; + while (haystack[i] != 0) + { + if (haystack[i] == needle) + return i; - ++i; - } - } + ++i; + } + } - return -1; + return -1; } int CharacterFunctions::indexOfCharFast (const char* const haystack, const char needle) throw() { - jassert (haystack != 0); + jassert (haystack != 0); - int i = 0; - while (haystack[i] != 0) - { - if (haystack[i] == needle) - return i; + int i = 0; + while (haystack[i] != 0) + { + if (haystack[i] == needle) + return i; - ++i; - } + ++i; + } - return -1; + return -1; } int CharacterFunctions::indexOfCharFast (const juce_wchar* const haystack, const juce_wchar needle) throw() { - jassert (haystack != 0); + jassert (haystack != 0); - int i = 0; - while (haystack[i] != 0) - { - if (haystack[i] == needle) - return i; + int i = 0; + while (haystack[i] != 0) + { + if (haystack[i] == needle) + return i; - ++i; - } + ++i; + } - return -1; + return -1; } int CharacterFunctions::getIntialSectionContainingOnly (const char* const text, const char* const allowedChars) throw() { - return allowedChars == 0 ? 0 : (int) strspn (text, allowedChars); + return allowedChars == 0 ? 0 : (int) strspn (text, allowedChars); } int CharacterFunctions::getIntialSectionContainingOnly (const juce_wchar* const text, const juce_wchar* const allowedChars) throw() { - if (allowedChars == 0) - return 0; + if (allowedChars == 0) + return 0; - int i = 0; + int i = 0; - for (;;) - { - if (indexOfCharFast (allowedChars, text[i]) < 0) - break; + for (;;) + { + if (indexOfCharFast (allowedChars, text[i]) < 0) + break; - ++i; - } + ++i; + } - return i; + return i; } int CharacterFunctions::ftime (char* const dest, const int maxChars, const char* const format, const struct tm* const tm) throw() { - return (int) strftime (dest, maxChars, format, tm); + return (int) strftime (dest, maxChars, format, tm); } int CharacterFunctions::ftime (juce_wchar* const dest, const int maxChars, const juce_wchar* const format, const struct tm* const tm) throw() { - return (int) wcsftime (dest, maxChars, format, tm); + return (int) wcsftime (dest, maxChars, format, tm); } int CharacterFunctions::getIntValue (const char* const s) throw() { - return atoi (s); + return atoi (s); } int CharacterFunctions::getIntValue (const juce_wchar* s) throw() { #if JUCE_WIN32 - return _wtoi (s); + return _wtoi (s); #else - int v = 0; + int v = 0; - while (isWhitespace (*s)) - ++s; + while (isWhitespace (*s)) + ++s; - const bool isNeg = *s == T('-'); - if (isNeg) - ++s; + const bool isNeg = *s == T('-'); + if (isNeg) + ++s; - for (;;) - { - const wchar_t c = *s++; + for (;;) + { + const wchar_t c = *s++; - if (c >= T('0') && c <= T('9')) - v = v * 10 + (int) (c - T('0')); - else - break; - } + if (c >= T('0') && c <= T('9')) + v = v * 10 + (int) (c - T('0')); + else + break; + } - return isNeg ? -v : v; + return isNeg ? -v : v; #endif } int64 CharacterFunctions::getInt64Value (const char* s) throw() { #if JUCE_LINUX - return atoll (s); + return atoll (s); #elif defined (JUCE_WIN32) - return _atoi64 (s); + return _atoi64 (s); #else - int64 v = 0; + int64 v = 0; - while (isWhitespace (*s)) - ++s; + while (isWhitespace (*s)) + ++s; - const bool isNeg = *s == T('-'); - if (isNeg) - ++s; + const bool isNeg = *s == T('-'); + if (isNeg) + ++s; - for (;;) - { - const char c = *s++; + for (;;) + { + const char c = *s++; - if (c >= '0' && c <= '9') - v = v * 10 + (int64) (c - '0'); - else - break; - } + if (c >= '0' && c <= '9') + v = v * 10 + (int64) (c - '0'); + else + break; + } - return isNeg ? -v : v; + return isNeg ? -v : v; #endif } int64 CharacterFunctions::getInt64Value (const juce_wchar* s) throw() { #if JUCE_WIN32 - return _wtoi64 (s); + return _wtoi64 (s); #else - int64 v = 0; + int64 v = 0; - while (isWhitespace (*s)) - ++s; + while (isWhitespace (*s)) + ++s; - const bool isNeg = *s == T('-'); - if (isNeg) - ++s; + const bool isNeg = *s == T('-'); + if (isNeg) + ++s; - for (;;) - { - const juce_wchar c = *s++; + for (;;) + { + const juce_wchar c = *s++; - if (c >= T('0') && c <= T('9')) - v = v * 10 + (int64) (c - T('0')); - else - break; - } + if (c >= T('0') && c <= T('9')) + v = v * 10 + (int64) (c - T('0')); + else + break; + } - return isNeg ? -v : v; + return isNeg ? -v : v; #endif } static double juce_mulexp10 (const double value, int exponent) throw() { - if (exponent == 0) - return value; + if (exponent == 0) + return value; - if (value == 0) - return 0; + if (value == 0) + return 0; - const bool negative = (exponent < 0); - if (negative) - exponent = -exponent; + const bool negative = (exponent < 0); + if (negative) + exponent = -exponent; - double result = 1.0, power = 10.0; - for (int bit = 1; exponent != 0; bit <<= 1) - { - if ((exponent & bit) != 0) - { - exponent ^= bit; - result *= power; - if (exponent == 0) - break; - } - power *= power; - } + double result = 1.0, power = 10.0; + for (int bit = 1; exponent != 0; bit <<= 1) + { + if ((exponent & bit) != 0) + { + exponent ^= bit; + result *= power; + if (exponent == 0) + break; + } + power *= power; + } - return negative ? (value / result) : (value * result); + return negative ? (value / result) : (value * result); } template double juce_atof (const CharType* const original) throw() { - double result[3] = { 0, 0, 0 }, accumulator[2] = { 0, 0 }; - int exponentAdjustment[2] = { 0, 0 }, exponentAccumulator[2] = { -1, -1 }; - int exponent = 0, decPointIndex = 0, digit = 0; - int lastDigit = 0, numSignificantDigits = 0; - bool isNegative = false, digitsFound = false; - const int maxSignificantDigits = 15 + 2; + double result[3] = { 0, 0, 0 }, accumulator[2] = { 0, 0 }; + int exponentAdjustment[2] = { 0, 0 }, exponentAccumulator[2] = { -1, -1 }; + int exponent = 0, decPointIndex = 0, digit = 0; + int lastDigit = 0, numSignificantDigits = 0; + bool isNegative = false, digitsFound = false; + const int maxSignificantDigits = 15 + 2; - const CharType* s = original; - while (CharacterFunctions::isWhitespace (*s)) - ++s; + const CharType* s = original; + while (CharacterFunctions::isWhitespace (*s)) + ++s; - switch (*s) - { - case '-': isNegative = true; // fall-through.. - case '+': ++s; - } + switch (*s) + { + case '-': isNegative = true; // fall-through.. + case '+': ++s; + } - if (*s == 'n' || *s == 'N' || *s == 'i' || *s == 'I') - return atof (String (original)); // Let the c library deal with NAN and INF + if (*s == 'n' || *s == 'N' || *s == 'i' || *s == 'I') + return atof (String (original)); // Let the c library deal with NAN and INF - for (;;) - { - if (CharacterFunctions::isDigit (*s)) - { - lastDigit = digit; - digit = *s++ - '0'; - digitsFound = true; + for (;;) + { + if (CharacterFunctions::isDigit (*s)) + { + lastDigit = digit; + digit = *s++ - '0'; + digitsFound = true; - if (decPointIndex != 0) - exponentAdjustment[1]++; + if (decPointIndex != 0) + exponentAdjustment[1]++; - if (numSignificantDigits == 0 && digit == 0) - continue; + if (numSignificantDigits == 0 && digit == 0) + continue; - if (++numSignificantDigits > maxSignificantDigits) - { - if (digit > 5) - ++accumulator [decPointIndex]; - else if (digit == 5 && (lastDigit & 1) != 0) - ++accumulator [decPointIndex]; + if (++numSignificantDigits > maxSignificantDigits) + { + if (digit > 5) + ++accumulator [decPointIndex]; + else if (digit == 5 && (lastDigit & 1) != 0) + ++accumulator [decPointIndex]; - if (decPointIndex > 0) - exponentAdjustment[1]--; - else - exponentAdjustment[0]++; + if (decPointIndex > 0) + exponentAdjustment[1]--; + else + exponentAdjustment[0]++; - while (CharacterFunctions::isDigit (*s)) - { - ++s; - if (decPointIndex == 0) - exponentAdjustment[0]++; - } - } - else - { - const double maxAccumulatorValue = (double) ((UINT_MAX - 9) / 10); - if (accumulator [decPointIndex] > maxAccumulatorValue) - { - result [decPointIndex] = juce_mulexp10 (result [decPointIndex], exponentAccumulator [decPointIndex]) - + accumulator [decPointIndex]; - accumulator [decPointIndex] = 0; - exponentAccumulator [decPointIndex] = 0; - } + while (CharacterFunctions::isDigit (*s)) + { + ++s; + if (decPointIndex == 0) + exponentAdjustment[0]++; + } + } + else + { + const double maxAccumulatorValue = (double) ((UINT_MAX - 9) / 10); + if (accumulator [decPointIndex] > maxAccumulatorValue) + { + result [decPointIndex] = juce_mulexp10 (result [decPointIndex], exponentAccumulator [decPointIndex]) + + accumulator [decPointIndex]; + accumulator [decPointIndex] = 0; + exponentAccumulator [decPointIndex] = 0; + } - accumulator [decPointIndex] = accumulator[decPointIndex] * 10 + digit; - exponentAccumulator [decPointIndex]++; - } - } - else if (decPointIndex == 0 && *s == '.') - { - ++s; - decPointIndex = 1; + accumulator [decPointIndex] = accumulator[decPointIndex] * 10 + digit; + exponentAccumulator [decPointIndex]++; + } + } + else if (decPointIndex == 0 && *s == '.') + { + ++s; + decPointIndex = 1; - if (numSignificantDigits > maxSignificantDigits) - { - while (CharacterFunctions::isDigit (*s)) - ++s; - break; - } - } - else - { - break; - } - } + if (numSignificantDigits > maxSignificantDigits) + { + while (CharacterFunctions::isDigit (*s)) + ++s; + break; + } + } + else + { + break; + } + } - result[0] = juce_mulexp10 (result[0], exponentAccumulator[0]) + accumulator[0]; + result[0] = juce_mulexp10 (result[0], exponentAccumulator[0]) + accumulator[0]; - if (decPointIndex != 0) - result[1] = juce_mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1]; + if (decPointIndex != 0) + result[1] = juce_mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1]; - if ((*s == 'e' || *s == 'E') && digitsFound) - { - bool negativeExponent = false; + if ((*s == 'e' || *s == 'E') && digitsFound) + { + bool negativeExponent = false; - switch (*++s) - { - case '-': negativeExponent = true; // fall-through.. - case '+': ++s; - } + switch (*++s) + { + case '-': negativeExponent = true; // fall-through.. + case '+': ++s; + } - while (CharacterFunctions::isDigit (*s)) - exponent = (exponent * 10) + (*s++ - '0'); + while (CharacterFunctions::isDigit (*s)) + exponent = (exponent * 10) + (*s++ - '0'); - if (negativeExponent) - exponent = -exponent; - } + if (negativeExponent) + exponent = -exponent; + } - double r = juce_mulexp10 (result[0], exponent + exponentAdjustment[0]); - if (decPointIndex != 0) - r += juce_mulexp10 (result[1], exponent - exponentAdjustment[1]); + double r = juce_mulexp10 (result[0], exponent + exponentAdjustment[0]); + if (decPointIndex != 0) + r += juce_mulexp10 (result[1], exponent - exponentAdjustment[1]); - return isNegative ? -r : r; + return isNegative ? -r : r; } double CharacterFunctions::getDoubleValue (const char* const s) throw() { - return juce_atof (s); + return juce_atof (s); } double CharacterFunctions::getDoubleValue (const juce_wchar* const s) throw() { - return juce_atof (s); + return juce_atof (s); } char CharacterFunctions::toUpperCase (const char character) throw() { - return (char) toupper (character); + return (char) toupper (character); } juce_wchar CharacterFunctions::toUpperCase (const juce_wchar character) throw() { - return towupper (character); + return towupper (character); } void CharacterFunctions::toUpperCase (char* s) throw() { #if JUCE_WIN32 - strupr (s); + strupr (s); #else - while (*s != 0) - { - *s = toUpperCase (*s); - ++s; - } + while (*s != 0) + { + *s = toUpperCase (*s); + ++s; + } #endif } void CharacterFunctions::toUpperCase (juce_wchar* s) throw() { #if JUCE_WIN32 - _wcsupr (s); + _wcsupr (s); #else - while (*s != 0) - { - *s = toUpperCase (*s); - ++s; - } + while (*s != 0) + { + *s = toUpperCase (*s); + ++s; + } #endif } bool CharacterFunctions::isUpperCase (const char character) throw() { - return isupper (character) != 0; + return isupper (character) != 0; } bool CharacterFunctions::isUpperCase (const juce_wchar character) throw() { #if JUCE_WIN32 - return iswupper (character) != 0; + return iswupper (character) != 0; #else - return toLowerCase (character) != character; + return toLowerCase (character) != character; #endif } char CharacterFunctions::toLowerCase (const char character) throw() { - return (char) tolower (character); + return (char) tolower (character); } juce_wchar CharacterFunctions::toLowerCase (const juce_wchar character) throw() { - return towlower (character); + return towlower (character); } void CharacterFunctions::toLowerCase (char* s) throw() { #if JUCE_WIN32 - strlwr (s); + strlwr (s); #else - while (*s != 0) - { - *s = toLowerCase (*s); - ++s; - } + while (*s != 0) + { + *s = toLowerCase (*s); + ++s; + } #endif } void CharacterFunctions::toLowerCase (juce_wchar* s) throw() { #if JUCE_WIN32 - _wcslwr (s); + _wcslwr (s); #else - while (*s != 0) - { - *s = toLowerCase (*s); - ++s; - } + while (*s != 0) + { + *s = toLowerCase (*s); + ++s; + } #endif } bool CharacterFunctions::isLowerCase (const char character) throw() { - return islower (character) != 0; + return islower (character) != 0; } bool CharacterFunctions::isLowerCase (const juce_wchar character) throw() { #if JUCE_WIN32 - return iswlower (character) != 0; + return iswlower (character) != 0; #else - return toUpperCase (character) != character; + return toUpperCase (character) != character; #endif } bool CharacterFunctions::isWhitespace (const char character) throw() { - return character == T(' ') || (character <= 13 && character >= 9); + return character == T(' ') || (character <= 13 && character >= 9); } bool CharacterFunctions::isWhitespace (const juce_wchar character) throw() { - return iswspace (character) != 0; + return iswspace (character) != 0; } bool CharacterFunctions::isDigit (const char character) throw() { - return (character >= '0' && character <= '9'); + return (character >= '0' && character <= '9'); } bool CharacterFunctions::isDigit (const juce_wchar character) throw() { - return iswdigit (character) != 0; + return iswdigit (character) != 0; } bool CharacterFunctions::isLetter (const char character) throw() { - return (character >= 'a' && character <= 'z') - || (character >= 'A' && character <= 'Z'); + return (character >= 'a' && character <= 'z') + || (character >= 'A' && character <= 'Z'); } bool CharacterFunctions::isLetter (const juce_wchar character) throw() { - return iswalpha (character) != 0; + return iswalpha (character) != 0; } bool CharacterFunctions::isLetterOrDigit (const char character) throw() { - return (character >= 'a' && character <= 'z') - || (character >= 'A' && character <= 'Z') - || (character >= '0' && character <= '9'); + return (character >= 'a' && character <= 'z') + || (character >= 'A' && character <= 'Z') + || (character >= '0' && character <= '9'); } bool CharacterFunctions::isLetterOrDigit (const juce_wchar character) throw() { - return iswalnum (character) != 0; + return iswalnum (character) != 0; } int CharacterFunctions::getHexDigitValue (const tchar digit) throw() { - if (digit >= T('0') && digit <= T('9')) - return digit - T('0'); - else if (digit >= T('a') && digit <= T('f')) - return digit - (T('a') - 10); - else if (digit >= T('A') && digit <= T('F')) - return digit - (T('A') - 10); + if (digit >= T('0') && digit <= T('9')) + return digit - T('0'); + else if (digit >= T('a') && digit <= T('f')) + return digit - (T('a') - 10); + else if (digit >= T('A') && digit <= T('F')) + return digit - (T('A') - 10); - return -1; + return -1; } int CharacterFunctions::printf (char* const dest, const int maxLength, const char* const format, ...) throw() { - va_list list; - va_start (list, format); - return vprintf (dest, maxLength, format, list); + va_list list; + va_start (list, format); + return vprintf (dest, maxLength, format, list); } int CharacterFunctions::printf (juce_wchar* const dest, const int maxLength, const juce_wchar* const format, ...) throw() { - va_list list; - va_start (list, format); - return vprintf (dest, maxLength, format, list); + va_list list; + va_start (list, format); + return vprintf (dest, maxLength, format, list); } int CharacterFunctions::vprintf (char* const dest, const int maxLength, const char* const format, va_list& args) throw() { #if JUCE_WIN32 - return (int) _vsnprintf (dest, maxLength, format, args); + return (int) _vsnprintf (dest, maxLength, format, args); #else - return (int) vsnprintf (dest, maxLength, format, args); + return (int) vsnprintf (dest, maxLength, format, args); #endif } int CharacterFunctions::vprintf (juce_wchar* const dest, const int maxLength, const juce_wchar* const format, va_list& args) throw() { #if defined (JUCE_WIN32) - return (int) _vsnwprintf (dest, maxLength, format, args); + return (int) _vsnwprintf (dest, maxLength, format, args); #else - return (int) vswprintf (dest, maxLength, format, args); + return (int) vswprintf (dest, maxLength, format, args); #endif } @@ -10376,12 +10139,12 @@ BEGIN_JUCE_NAMESPACE LocalisedStrings::LocalisedStrings (const String& fileContents) { - loadFromText (fileContents); + loadFromText (fileContents); } LocalisedStrings::LocalisedStrings (const File& fileToLoad) { - loadFromText (fileToLoad.loadFileAsString()); + loadFromText (fileToLoad.loadFileAsString()); } LocalisedStrings::~LocalisedStrings() @@ -10390,78 +10153,78 @@ LocalisedStrings::~LocalisedStrings() const String LocalisedStrings::translate (const String& text) const { - return translations.getValue (text, text); + return translations.getValue (text, text); } static int findCloseQuote (const String& text, int startPos) { - tchar lastChar = 0; + tchar lastChar = 0; - for (;;) - { - const tchar c = text [startPos]; + for (;;) + { + const tchar c = text [startPos]; - if (c == 0 || (c == T('"') && lastChar != T('\\'))) - break; + if (c == 0 || (c == T('"') && lastChar != T('\\'))) + break; - lastChar = c; - ++startPos; - } + lastChar = c; + ++startPos; + } - return startPos; + return startPos; } static const String unescapeString (const String& s) { - return s.replace (T("\\\""), T("\"")) - .replace (T("\\\'"), T("\'")) - .replace (T("\\t"), T("\t")) - .replace (T("\\r"), T("\r")) - .replace (T("\\n"), T("\n")); + return s.replace (T("\\\""), T("\"")) + .replace (T("\\\'"), T("\'")) + .replace (T("\\t"), T("\t")) + .replace (T("\\r"), T("\r")) + .replace (T("\\n"), T("\n")); } void LocalisedStrings::loadFromText (const String& fileContents) { - StringArray lines; - lines.addLines (fileContents); + StringArray lines; + lines.addLines (fileContents); - for (int i = 0; i < lines.size(); ++i) - { - String line (lines[i].trim()); + for (int i = 0; i < lines.size(); ++i) + { + String line (lines[i].trim()); - if (line.startsWithChar (T('"'))) - { - int closeQuote = findCloseQuote (line, 1); + if (line.startsWithChar (T('"'))) + { + int closeQuote = findCloseQuote (line, 1); - const String originalText (unescapeString (line.substring (1, closeQuote))); + const String originalText (unescapeString (line.substring (1, closeQuote))); - if (originalText.isNotEmpty()) - { - const int openingQuote = findCloseQuote (line, closeQuote + 1); - closeQuote = findCloseQuote (line, openingQuote + 1); + if (originalText.isNotEmpty()) + { + const int openingQuote = findCloseQuote (line, closeQuote + 1); + closeQuote = findCloseQuote (line, openingQuote + 1); - const String newText (unescapeString (line.substring (openingQuote + 1, closeQuote))); + const String newText (unescapeString (line.substring (openingQuote + 1, closeQuote))); - if (newText.isNotEmpty()) - translations.set (originalText, newText); - } - } - else if (line.startsWithIgnoreCase (T("language:"))) - { - languageName = line.substring (9).trim(); - } - else if (line.startsWithIgnoreCase (T("countries:"))) - { - countryCodes.addTokens (line.substring (10).trim(), true); - countryCodes.trim(); - countryCodes.removeEmptyStrings(); - } - } + if (newText.isNotEmpty()) + translations.set (originalText, newText); + } + } + else if (line.startsWithIgnoreCase (T("language:"))) + { + languageName = line.substring (9).trim(); + } + else if (line.startsWithIgnoreCase (T("countries:"))) + { + countryCodes.addTokens (line.substring (10).trim(), true); + countryCodes.trim(); + countryCodes.removeEmptyStrings(); + } + } } void LocalisedStrings::setIgnoresCase (const bool shouldIgnoreCase) { - translations.setIgnoresCase (shouldIgnoreCase); + translations.setIgnoresCase (shouldIgnoreCase); } static CriticalSection currentMappingsLock; @@ -10469,30 +10232,30 @@ static LocalisedStrings* currentMappings = 0; void LocalisedStrings::setCurrentMappings (LocalisedStrings* newTranslations) { - const ScopedLock sl (currentMappingsLock); + const ScopedLock sl (currentMappingsLock); - delete currentMappings; - currentMappings = newTranslations; + delete currentMappings; + currentMappings = newTranslations; } LocalisedStrings* LocalisedStrings::getCurrentMappings() { - return currentMappings; + return currentMappings; } const String LocalisedStrings::translateWithCurrentMappings (const String& text) { - const ScopedLock sl (currentMappingsLock); + const ScopedLock sl (currentMappingsLock); - if (currentMappings != 0) - return currentMappings->translate (text); + if (currentMappings != 0) + return currentMappings->translate (text); - return text; + return text; } const String LocalisedStrings::translateWithCurrentMappings (const char* text) { - return translateWithCurrentMappings (String (text)); + return translateWithCurrentMappings (String (text)); } END_JUCE_NAMESPACE @@ -10516,2211 +10279,2211 @@ BEGIN_JUCE_NAMESPACE #endif static const char* const emptyCharString = "\0\0\0\0JUCE"; -static const int safeEmptyStringRefCount = 0x3fffffff; -String::InternalRefCountedStringHolder String::emptyString = { safeEmptyStringRefCount, 0, { 0 } }; -static tchar decimalPoint = T('.'); +static const int safeEmptyStringRefCount = 0x3fffffff; +String::InternalRefCountedStringHolder String::emptyString = { safeEmptyStringRefCount, 0, { 0 } }; +static tchar decimalPoint = T('.'); void juce_initialiseStrings() { - decimalPoint = String::fromUTF8 ((const uint8*) localeconv()->decimal_point) [0]; + decimalPoint = String::fromUTF8 ((const uint8*) localeconv()->decimal_point) [0]; } void String::deleteInternal() throw() { - if (Atomic::decrementAndReturn (text->refCount) == 0) - juce_free (text); + if (Atomic::decrementAndReturn (text->refCount) == 0) + juce_free (text); } void String::createInternal (const int numChars) throw() { - jassert (numChars > 0); + jassert (numChars > 0); - text = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder) - + numChars * sizeof (tchar)); - text->refCount = 1; - text->allocatedNumChars = numChars; - text->text[0] = 0; + text = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder) + + numChars * sizeof (tchar)); + text->refCount = 1; + text->allocatedNumChars = numChars; + text->text[0] = 0; } void String::createInternal (const tchar* const t, const tchar* const textEnd) throw() { - jassert (*(textEnd - 1) == 0); // must have a null terminator + jassert (*(textEnd - 1) == 0); // must have a null terminator - const int numChars = (int) (textEnd - t); - createInternal (numChars - 1); - memcpy (text->text, t, numChars * sizeof (tchar)); + const int numChars = (int) (textEnd - t); + createInternal (numChars - 1); + memcpy (text->text, t, numChars * sizeof (tchar)); } void String::appendInternal (const tchar* const newText, - const int numExtraChars) throw() + const int numExtraChars) throw() { - if (numExtraChars > 0) - { - const int oldLen = CharacterFunctions::length (text->text); - const int newTotalLen = oldLen + numExtraChars; + if (numExtraChars > 0) + { + const int oldLen = CharacterFunctions::length (text->text); + const int newTotalLen = oldLen + numExtraChars; - if (text->refCount > 1) - { - // it's in use by other strings as well, so we need to make a private copy before messing with it.. - InternalRefCountedStringHolder* const newTextHolder - = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder) - + newTotalLen * sizeof (tchar)); - newTextHolder->refCount = 1; - newTextHolder->allocatedNumChars = newTotalLen; + if (text->refCount > 1) + { + // it's in use by other strings as well, so we need to make a private copy before messing with it.. + InternalRefCountedStringHolder* const newTextHolder + = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder) + + newTotalLen * sizeof (tchar)); + newTextHolder->refCount = 1; + newTextHolder->allocatedNumChars = newTotalLen; - memcpy (newTextHolder->text, text->text, oldLen * sizeof (tchar)); - memcpy (newTextHolder->text + oldLen, newText, numExtraChars * sizeof (tchar)); + memcpy (newTextHolder->text, text->text, oldLen * sizeof (tchar)); + memcpy (newTextHolder->text + oldLen, newText, numExtraChars * sizeof (tchar)); - InternalRefCountedStringHolder* const old = text; - text = newTextHolder; + InternalRefCountedStringHolder* const old = text; + text = newTextHolder; - if (Atomic::decrementAndReturn (old->refCount) == 0) - juce_free (old); - } - else - { - // no other strings using it, so just expand it if needed.. - if (newTotalLen > text->allocatedNumChars) - { - text = (InternalRefCountedStringHolder*) - juce_realloc (text, sizeof (InternalRefCountedStringHolder) - + newTotalLen * sizeof (tchar)); + if (Atomic::decrementAndReturn (old->refCount) == 0) + juce_free (old); + } + else + { + // no other strings using it, so just expand it if needed.. + if (newTotalLen > text->allocatedNumChars) + { + text = (InternalRefCountedStringHolder*) + juce_realloc (text, sizeof (InternalRefCountedStringHolder) + + newTotalLen * sizeof (tchar)); - text->allocatedNumChars = newTotalLen; - } + text->allocatedNumChars = newTotalLen; + } - memcpy (text->text + oldLen, newText, numExtraChars * sizeof (tchar)); - } + memcpy (text->text + oldLen, newText, numExtraChars * sizeof (tchar)); + } - text->text [newTotalLen] = 0; - } + text->text [newTotalLen] = 0; + } } void String::dupeInternalIfMultiplyReferenced() throw() { - if (text->refCount > 1) - { - InternalRefCountedStringHolder* const old = text; - const int len = old->allocatedNumChars; + if (text->refCount > 1) + { + InternalRefCountedStringHolder* const old = text; + const int len = old->allocatedNumChars; - InternalRefCountedStringHolder* const newTextHolder - = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder) - + len * sizeof (tchar)); + InternalRefCountedStringHolder* const newTextHolder + = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder) + + len * sizeof (tchar)); - newTextHolder->refCount = 1; - newTextHolder->allocatedNumChars = len; + newTextHolder->refCount = 1; + newTextHolder->allocatedNumChars = len; - memcpy (newTextHolder->text, old->text, (len + 1) * sizeof (tchar)); + memcpy (newTextHolder->text, old->text, (len + 1) * sizeof (tchar)); - text = newTextHolder; + text = newTextHolder; - if (Atomic::decrementAndReturn (old->refCount) == 0) - juce_free (old); - } + if (Atomic::decrementAndReturn (old->refCount) == 0) + juce_free (old); + } } const String String::empty; String::String() throw() - : text (&emptyString) + : text (&emptyString) { } String::String (const String& other) throw() - : text (other.text) + : text (other.text) { - Atomic::increment (text->refCount); + Atomic::increment (text->refCount); } String::String (const int numChars, - const int /*dummyVariable*/) throw() + const int /*dummyVariable*/) throw() { - createInternal (numChars); + createInternal (numChars); } String::String (const char* const t) throw() { - if (t != 0 && *t != 0) - { - const int len = CharacterFunctions::length (t); - createInternal (len); + if (t != 0 && *t != 0) + { + const int len = CharacterFunctions::length (t); + createInternal (len); #if JUCE_STRINGS_ARE_UNICODE - CharacterFunctions::copy (text->text, t, len + 1); + CharacterFunctions::copy (text->text, t, len + 1); #else - memcpy (text->text, t, len + 1); + memcpy (text->text, t, len + 1); #endif - } - else - { - text = &emptyString; - emptyString.refCount = safeEmptyStringRefCount; - } + } + else + { + text = &emptyString; + emptyString.refCount = safeEmptyStringRefCount; + } } String::String (const juce_wchar* const t) throw() { - if (t != 0 && *t != 0) - { + if (t != 0 && *t != 0) + { #if JUCE_STRINGS_ARE_UNICODE - const int len = CharacterFunctions::length (t); - createInternal (len); + const int len = CharacterFunctions::length (t); + createInternal (len); - memcpy (text->text, t, (len + 1) * sizeof (tchar)); + memcpy (text->text, t, (len + 1) * sizeof (tchar)); #else - const int len = CharacterFunctions::bytesRequiredForCopy (t); - createInternal (len); + const int len = CharacterFunctions::bytesRequiredForCopy (t); + createInternal (len); - CharacterFunctions::copy (text->text, t, len + 1); + CharacterFunctions::copy (text->text, t, len + 1); #endif - } - else - { - text = &emptyString; - emptyString.refCount = safeEmptyStringRefCount; - } + } + else + { + text = &emptyString; + emptyString.refCount = safeEmptyStringRefCount; + } } String::String (const char* const t, - const int maxChars) throw() + const size_t maxChars) throw() { - int i; - for (i = 0; i < maxChars; ++i) - if (t[i] == 0) - break; + int i; + for (i = 0; (size_t) i < maxChars; ++i) + if (t[i] == 0) + break; - if (i > 0) - { - createInternal (i); + if (i > 0) + { + createInternal (i); #if JUCE_STRINGS_ARE_UNICODE - CharacterFunctions::copy (text->text, t, i); + CharacterFunctions::copy (text->text, t, i); #else - memcpy (text->text, t, i); + memcpy (text->text, t, i); #endif - text->text [i] = 0; - } - else - { - text = &emptyString; - emptyString.refCount = safeEmptyStringRefCount; - } + text->text [i] = 0; + } + else + { + text = &emptyString; + emptyString.refCount = safeEmptyStringRefCount; + } } String::String (const juce_wchar* const t, - const int maxChars) throw() + const size_t maxChars) throw() { - int i; - for (i = 0; i < maxChars; ++i) - if (t[i] == 0) - break; + int i; + for (i = 0; (size_t) i < maxChars; ++i) + if (t[i] == 0) + break; - if (i > 0) - { - createInternal (i); + if (i > 0) + { + createInternal (i); #if JUCE_STRINGS_ARE_UNICODE - memcpy (text->text, t, i * sizeof (tchar)); + memcpy (text->text, t, i * sizeof (tchar)); #else - CharacterFunctions::copy (text->text, t, i); + CharacterFunctions::copy (text->text, t, i); #endif - text->text [i] = 0; - } - else - { - text = &emptyString; - emptyString.refCount = safeEmptyStringRefCount; - } + text->text [i] = 0; + } + else + { + text = &emptyString; + emptyString.refCount = safeEmptyStringRefCount; + } } const String String::charToString (const tchar character) throw() { - tchar temp[2]; - temp[0] = character; - temp[1] = 0; + tchar temp[2]; + temp[0] = character; + temp[1] = 0; - return String (temp); + return String (temp); } // pass in a pointer to the END of a buffer.. static tchar* int64ToCharString (tchar* t, const int64 n) throw() { - *--t = 0; - int64 v = (n >= 0) ? n : -n; + *--t = 0; + int64 v = (n >= 0) ? n : -n; - do - { - *--t = (tchar) (T('0') + (int) (v % 10)); - v /= 10; + do + { + *--t = (tchar) (T('0') + (int) (v % 10)); + v /= 10; - } while (v > 0); + } while (v > 0); - if (n < 0) - *--t = T('-'); + if (n < 0) + *--t = T('-'); - return t; + return t; } static tchar* intToCharString (tchar* t, const int n) throw() { - if (n == (int) 0x80000000) // (would cause an overflow) - return int64ToCharString (t, n); + if (n == (int) 0x80000000) // (would cause an overflow) + return int64ToCharString (t, n); - *--t = 0; - int v = abs (n); + *--t = 0; + int v = abs (n); - do - { - *--t = (tchar) (T('0') + (v % 10)); - v /= 10; + do + { + *--t = (tchar) (T('0') + (v % 10)); + v /= 10; - } while (v > 0); + } while (v > 0); - if (n < 0) - *--t = T('-'); + if (n < 0) + *--t = T('-'); - return t; + return t; } static tchar* uintToCharString (tchar* t, unsigned int v) throw() { - *--t = 0; + *--t = 0; - do - { - *--t = (tchar) (T('0') + (v % 10)); - v /= 10; + do + { + *--t = (tchar) (T('0') + (v % 10)); + v /= 10; - } while (v > 0); + } while (v > 0); - return t; + return t; } String::String (const int number) throw() { - tchar buffer [16]; - tchar* const end = buffer + 16; + tchar buffer [16]; + tchar* const end = buffer + 16; - createInternal (intToCharString (end, number), end); + createInternal (intToCharString (end, number), end); } String::String (const unsigned int number) throw() { - tchar buffer [16]; - tchar* const end = buffer + 16; + tchar buffer [16]; + tchar* const end = buffer + 16; - createInternal (uintToCharString (end, number), end); + createInternal (uintToCharString (end, number), end); } String::String (const short number) throw() { - tchar buffer [16]; - tchar* const end = buffer + 16; + tchar buffer [16]; + tchar* const end = buffer + 16; - createInternal (intToCharString (end, (int) number), end); + createInternal (intToCharString (end, (int) number), end); } String::String (const unsigned short number) throw() { - tchar buffer [16]; - tchar* const end = buffer + 16; + tchar buffer [16]; + tchar* const end = buffer + 16; - createInternal (uintToCharString (end, (unsigned int) number), end); + createInternal (uintToCharString (end, (unsigned int) number), end); } String::String (const int64 number) throw() { - tchar buffer [32]; - tchar* const end = buffer + 32; + tchar buffer [32]; + tchar* const end = buffer + 32; - createInternal (int64ToCharString (end, number), end); + createInternal (int64ToCharString (end, number), end); } String::String (const uint64 number) throw() { - tchar buffer [32]; - tchar* const end = buffer + 32; - tchar* t = end; + tchar buffer [32]; + tchar* const end = buffer + 32; + tchar* t = end; - *--t = 0; - int64 v = number; + *--t = 0; + int64 v = number; - do - { - *--t = (tchar) (T('0') + (int) (v % 10)); - v /= 10; + do + { + *--t = (tchar) (T('0') + (int) (v % 10)); + v /= 10; - } while (v > 0); + } while (v > 0); - createInternal (t, end); + createInternal (t, end); } // a double-to-string routine that actually uses the number of dec. places you asked for // without resorting to exponent notation if the number's too big or small (which is what printf does). void String::doubleToStringWithDecPlaces (double n, int numDecPlaces) throw() { - const int bufSize = 80; - tchar buffer [bufSize]; - int len; - tchar* t; + const int bufSize = 80; + tchar buffer [bufSize]; + int len; + tchar* t; - if (numDecPlaces > 0 && n > -1.0e20 && n < 1.0e20) - { - int64 v = (int64) (pow (10.0, numDecPlaces) * fabs (n) + 0.5); + if (numDecPlaces > 0 && n > -1.0e20 && n < 1.0e20) + { + int64 v = (int64) (pow (10.0, numDecPlaces) * fabs (n) + 0.5); - t = buffer + bufSize; - *--t = (tchar) 0; + t = buffer + bufSize; + *--t = (tchar) 0; - while (numDecPlaces >= 0 || v > 0) - { - if (numDecPlaces == 0) - *--t = decimalPoint; + while (numDecPlaces >= 0 || v > 0) + { + if (numDecPlaces == 0) + *--t = decimalPoint; - *--t = (tchar) (T('0') + (v % 10)); + *--t = (tchar) (T('0') + (v % 10)); - v /= 10; - --numDecPlaces; - } + v /= 10; + --numDecPlaces; + } - if (n < 0) - *--t = T('-'); + if (n < 0) + *--t = T('-'); - len = (int) ((buffer + bufSize) - t); - } - else - { - len = CharacterFunctions::printf (buffer, bufSize, T("%.9g"), n) + 1; - t = buffer; - } + len = (int) ((buffer + bufSize) - t); + } + else + { + len = CharacterFunctions::printf (buffer, bufSize, T("%.9g"), n) + 1; + t = buffer; + } - if (len > 1) - { - jassert (len < numElementsInArray (buffer)); + if (len > 1) + { + jassert (len < numElementsInArray (buffer)); - createInternal (len - 1); - memcpy (text->text, t, len * sizeof (tchar)); - } - else - { - jassert (*t == 0); - text = &emptyString; - emptyString.refCount = safeEmptyStringRefCount; - } + createInternal (len - 1); + memcpy (text->text, t, len * sizeof (tchar)); + } + else + { + jassert (*t == 0); + text = &emptyString; + emptyString.refCount = safeEmptyStringRefCount; + } } String::String (const float number, - const int numberOfDecimalPlaces) throw() + const int numberOfDecimalPlaces) throw() { - doubleToStringWithDecPlaces ((double) number, - numberOfDecimalPlaces); + doubleToStringWithDecPlaces ((double) number, + numberOfDecimalPlaces); } String::String (const double number, - const int numberOfDecimalPlaces) throw() + const int numberOfDecimalPlaces) throw() { - doubleToStringWithDecPlaces (number, - numberOfDecimalPlaces); + doubleToStringWithDecPlaces (number, + numberOfDecimalPlaces); } String::~String() throw() { - emptyString.refCount = safeEmptyStringRefCount; + emptyString.refCount = safeEmptyStringRefCount; - if (Atomic::decrementAndReturn (text->refCount) == 0) - juce_free (text); + if (Atomic::decrementAndReturn (text->refCount) == 0) + juce_free (text); } -void String::preallocateStorage (const int numChars) throw() +void String::preallocateStorage (const size_t numChars) throw() { - if (numChars > text->allocatedNumChars) - { - dupeInternalIfMultiplyReferenced(); + if (numChars > (size_t) text->allocatedNumChars) + { + dupeInternalIfMultiplyReferenced(); - text = (InternalRefCountedStringHolder*) juce_realloc (text, sizeof (InternalRefCountedStringHolder) - + numChars * sizeof (tchar)); - text->allocatedNumChars = numChars; - } + text = (InternalRefCountedStringHolder*) juce_realloc (text, sizeof (InternalRefCountedStringHolder) + + numChars * sizeof (tchar)); + text->allocatedNumChars = (int) numChars; + } } #if JUCE_STRINGS_ARE_UNICODE String::operator const char*() const throw() { - if (isEmpty()) - { - return (const char*) emptyCharString; - } - else - { - String* const mutableThis = const_cast (this); + if (isEmpty()) + { + return (const char*) emptyCharString; + } + else + { + String* const mutableThis = const_cast (this); - mutableThis->dupeInternalIfMultiplyReferenced(); - int len = CharacterFunctions::bytesRequiredForCopy (text->text) + 1; - mutableThis->text = (InternalRefCountedStringHolder*) - juce_realloc (text, sizeof (InternalRefCountedStringHolder) - + (len * sizeof (juce_wchar) + len)); - char* otherCopy = (char*) (text->text + len); - --len; + mutableThis->dupeInternalIfMultiplyReferenced(); + int len = CharacterFunctions::bytesRequiredForCopy (text->text) + 1; + mutableThis->text = (InternalRefCountedStringHolder*) + juce_realloc (text, sizeof (InternalRefCountedStringHolder) + + (len * sizeof (juce_wchar) + len)); + char* otherCopy = (char*) (text->text + len); + --len; - CharacterFunctions::copy (otherCopy, text->text, len); - otherCopy [len] = 0; - return otherCopy; - } + CharacterFunctions::copy (otherCopy, text->text, len); + otherCopy [len] = 0; + return otherCopy; + } } #else String::operator const juce_wchar*() const throw() { - if (isEmpty()) - { - return (const juce_wchar*) emptyCharString; - } - else - { - String* const mutableThis = const_cast (this); + if (isEmpty()) + { + return (const juce_wchar*) emptyCharString; + } + else + { + String* const mutableThis = const_cast (this); - mutableThis->dupeInternalIfMultiplyReferenced(); - int len = CharacterFunctions::length (text->text) + 1; - mutableThis->text = (InternalRefCountedStringHolder*) - juce_realloc (text, sizeof (InternalRefCountedStringHolder) - + (len * sizeof (juce_wchar) + len)); + mutableThis->dupeInternalIfMultiplyReferenced(); + int len = CharacterFunctions::length (text->text) + 1; + mutableThis->text = (InternalRefCountedStringHolder*) + juce_realloc (text, sizeof (InternalRefCountedStringHolder) + + (len * sizeof (juce_wchar) + len)); - juce_wchar* otherCopy = (juce_wchar*) (text->text + len); - --len; + juce_wchar* otherCopy = (juce_wchar*) (text->text + len); + --len; - CharacterFunctions::copy (otherCopy, text->text, len); - otherCopy [len] = 0; - return otherCopy; - } + CharacterFunctions::copy (otherCopy, text->text, len); + otherCopy [len] = 0; + return otherCopy; + } } #endif void String::copyToBuffer (char* const destBuffer, - const int bufferSizeBytes) const throw() + const int bufferSizeBytes) const throw() { #if JUCE_STRINGS_ARE_UNICODE - const int len = jmin (bufferSizeBytes, CharacterFunctions::bytesRequiredForCopy (text->text)); - CharacterFunctions::copy (destBuffer, text->text, len); + const int len = jmin (bufferSizeBytes, CharacterFunctions::bytesRequiredForCopy (text->text)); + CharacterFunctions::copy (destBuffer, text->text, len); #else - const int len = jmin (bufferSizeBytes, length()); - memcpy (destBuffer, text->text, len * sizeof (tchar)); + const int len = jmin (bufferSizeBytes, length()); + memcpy (destBuffer, text->text, len * sizeof (tchar)); #endif - destBuffer [len] = 0; + destBuffer [len] = 0; } void String::copyToBuffer (juce_wchar* const destBuffer, - const int maxCharsToCopy) const throw() + const int maxCharsToCopy) const throw() { - const int len = jmin (maxCharsToCopy, length()); + const int len = jmin (maxCharsToCopy, length()); #if JUCE_STRINGS_ARE_UNICODE - memcpy (destBuffer, text->text, len * sizeof (juce_wchar)); + memcpy (destBuffer, text->text, len * sizeof (juce_wchar)); #else - CharacterFunctions::copy (destBuffer, text->text, len); + CharacterFunctions::copy (destBuffer, text->text, len); #endif - destBuffer [len] = 0; + destBuffer [len] = 0; } int String::length() const throw() { - return CharacterFunctions::length (text->text); + return CharacterFunctions::length (text->text); } int String::hashCode() const throw() { - const tchar* t = text->text; - int result = 0; + const tchar* t = text->text; + int result = 0; - while (*t != (tchar) 0) - result = 31 * result + *t++; + while (*t != (tchar) 0) + result = 31 * result + *t++; - return result; + return result; } int64 String::hashCode64() const throw() { - const tchar* t = text->text; - int64 result = 0; + const tchar* t = text->text; + int64 result = 0; - while (*t != (tchar) 0) - result = 101 * result + *t++; + while (*t != (tchar) 0) + result = 101 * result + *t++; - return result; + return result; } const String& String::operator= (const tchar* const otherText) throw() { - if (otherText != 0 && *otherText != 0) - { - const int otherLen = CharacterFunctions::length (otherText); + if (otherText != 0 && *otherText != 0) + { + const int otherLen = CharacterFunctions::length (otherText); - if (otherLen > 0) - { - // avoid resizing the memory block if the string is - // shrinking.. - if (text->refCount > 1 - || otherLen > text->allocatedNumChars - || otherLen <= (text->allocatedNumChars >> 1)) - { - deleteInternal(); - createInternal (otherLen); - } + if (otherLen > 0) + { + // avoid resizing the memory block if the string is + // shrinking.. + if (text->refCount > 1 + || otherLen > text->allocatedNumChars + || otherLen <= (text->allocatedNumChars >> 1)) + { + deleteInternal(); + createInternal (otherLen); + } - memcpy (text->text, otherText, (otherLen + 1) * sizeof (tchar)); + memcpy (text->text, otherText, (otherLen + 1) * sizeof (tchar)); - return *this; - } - } + return *this; + } + } - deleteInternal(); - text = &emptyString; - emptyString.refCount = safeEmptyStringRefCount; + deleteInternal(); + text = &emptyString; + emptyString.refCount = safeEmptyStringRefCount; - return *this; + return *this; } const String& String::operator= (const String& other) throw() { - if (this != &other) - { - Atomic::increment (other.text->refCount); + if (this != &other) + { + Atomic::increment (other.text->refCount); - if (Atomic::decrementAndReturn (text->refCount) == 0) - juce_free (text); + if (Atomic::decrementAndReturn (text->refCount) == 0) + juce_free (text); - text = other.text; - } + text = other.text; + } - return *this; + return *this; } bool String::operator== (const String& other) const throw() { - return text == other.text - || CharacterFunctions::compare (text->text, other.text->text) == 0; + return text == other.text + || CharacterFunctions::compare (text->text, other.text->text) == 0; } bool String::operator== (const tchar* const t) const throw() { - return t != 0 ? CharacterFunctions::compare (text->text, t) == 0 - : isEmpty(); + return t != 0 ? CharacterFunctions::compare (text->text, t) == 0 + : isEmpty(); } bool String::equalsIgnoreCase (const tchar* t) const throw() { - return t != 0 ? CharacterFunctions::compareIgnoreCase (text->text, t) == 0 - : isEmpty(); + return t != 0 ? CharacterFunctions::compareIgnoreCase (text->text, t) == 0 + : isEmpty(); } bool String::equalsIgnoreCase (const String& other) const throw() { - return text == other.text - || CharacterFunctions::compareIgnoreCase (text->text, other.text->text) == 0; + return text == other.text + || CharacterFunctions::compareIgnoreCase (text->text, other.text->text) == 0; } bool String::operator!= (const String& other) const throw() { - return text != other.text - && CharacterFunctions::compare (text->text, other.text->text) != 0; + return text != other.text + && CharacterFunctions::compare (text->text, other.text->text) != 0; } bool String::operator!= (const tchar* const t) const throw() { - return t != 0 ? (CharacterFunctions::compare (text->text, t) != 0) - : isNotEmpty(); + return t != 0 ? (CharacterFunctions::compare (text->text, t) != 0) + : isNotEmpty(); } bool String::operator> (const String& other) const throw() { - return compare (other) > 0; + return compare (other) > 0; } bool String::operator< (const tchar* const other) const throw() { - return compare (other) < 0; + return compare (other) < 0; } bool String::operator>= (const String& other) const throw() { - return compare (other) >= 0; + return compare (other) >= 0; } bool String::operator<= (const tchar* const other) const throw() { - return compare (other) <= 0; + return compare (other) <= 0; } int String::compare (const tchar* const other) const throw() { - return other != 0 ? CharacterFunctions::compare (text->text, other) - : isEmpty(); + return other != 0 ? CharacterFunctions::compare (text->text, other) + : isEmpty(); } int String::compareIgnoreCase (const tchar* const other) const throw() { - return other != 0 ? CharacterFunctions::compareIgnoreCase (text->text, other) - : isEmpty(); + return other != 0 ? CharacterFunctions::compareIgnoreCase (text->text, other) + : isEmpty(); } int String::compareLexicographically (const tchar* other) const throw() { - if (other == 0) - return isEmpty(); + if (other == 0) + return isEmpty(); - const tchar* s1 = text->text; - while (*s1 != 0 && ! CharacterFunctions::isLetterOrDigit (*s1)) - ++s1; + const tchar* s1 = text->text; + while (*s1 != 0 && ! CharacterFunctions::isLetterOrDigit (*s1)) + ++s1; - while (*other != 0 && ! CharacterFunctions::isLetterOrDigit (*other)) - ++other; + while (*other != 0 && ! CharacterFunctions::isLetterOrDigit (*other)) + ++other; - return CharacterFunctions::compareIgnoreCase (s1, other); + return CharacterFunctions::compareIgnoreCase (s1, other); } const String String::operator+ (const String& other) const throw() { - if (*(other.text->text) == 0) - return *this; + if (*(other.text->text) == 0) + return *this; - if (isEmpty()) - return other; + if (isEmpty()) + return other; - const int len = CharacterFunctions::length (text->text); - const int otherLen = CharacterFunctions::length (other.text->text); + const int len = CharacterFunctions::length (text->text); + const int otherLen = CharacterFunctions::length (other.text->text); - String result (len + otherLen, (int) 0); - memcpy (result.text->text, text->text, len * sizeof (tchar)); - memcpy (result.text->text + len, other.text->text, otherLen * sizeof (tchar)); - result.text->text [len + otherLen] = 0; + String result (len + otherLen, (int) 0); + memcpy (result.text->text, text->text, len * sizeof (tchar)); + memcpy (result.text->text + len, other.text->text, otherLen * sizeof (tchar)); + result.text->text [len + otherLen] = 0; - return result; + return result; } const String String::operator+ (const tchar* const textToAppend) const throw() { - if (textToAppend == 0 || *textToAppend == 0) - return *this; + if (textToAppend == 0 || *textToAppend == 0) + return *this; - const int len = CharacterFunctions::length (text->text); - const int otherLen = CharacterFunctions::length (textToAppend); + const int len = CharacterFunctions::length (text->text); + const int otherLen = CharacterFunctions::length (textToAppend); - String result (len + otherLen, (int) 0); - memcpy (result.text->text, text->text, len * sizeof (tchar)); - memcpy (result.text->text + len, textToAppend, otherLen * sizeof (tchar)); - result.text->text [len + otherLen] = 0; + String result (len + otherLen, (int) 0); + memcpy (result.text->text, text->text, len * sizeof (tchar)); + memcpy (result.text->text + len, textToAppend, otherLen * sizeof (tchar)); + result.text->text [len + otherLen] = 0; - return result; + return result; } const String String::operator+ (const tchar characterToAppend) const throw() { - if (characterToAppend == 0) - return *this; + if (characterToAppend == 0) + return *this; - const int len = CharacterFunctions::length (text->text); - String result ((int) (len + 1), (int) 0); + const int len = CharacterFunctions::length (text->text); + String result ((int) (len + 1), (int) 0); - memcpy (result.text->text, text->text, len * sizeof (tchar)); - result.text->text[len] = characterToAppend; - result.text->text[len + 1] = 0; + memcpy (result.text->text, text->text, len * sizeof (tchar)); + result.text->text[len] = characterToAppend; + result.text->text[len + 1] = 0; - return result; + return result; } const String JUCE_PUBLIC_FUNCTION operator+ (const char* const string1, - const String& string2) throw() + const String& string2) throw() { - String s (string1); - s += string2; - return s; + String s (string1); + s += string2; + return s; } const String JUCE_PUBLIC_FUNCTION operator+ (const juce_wchar* const string1, - const String& string2) throw() + const String& string2) throw() { - String s (string1); - s += string2; - return s; + String s (string1); + s += string2; + return s; } const String& String::operator+= (const tchar* const t) throw() { - if (t != 0) - appendInternal (t, CharacterFunctions::length (t)); + if (t != 0) + appendInternal (t, CharacterFunctions::length (t)); - return *this; + return *this; } const String& String::operator+= (const String& other) throw() { - if (isEmpty()) - operator= (other); - else - appendInternal (other.text->text, - CharacterFunctions::length (other.text->text)); + if (isEmpty()) + operator= (other); + else + appendInternal (other.text->text, + CharacterFunctions::length (other.text->text)); - return *this; + return *this; } const String& String::operator+= (const char ch) throw() { - char asString[2]; - asString[0] = ch; - asString[1] = 0; + char asString[2]; + asString[0] = ch; + asString[1] = 0; #if JUCE_STRINGS_ARE_UNICODE - operator+= (String (asString)); + operator+= (String (asString)); #else - appendInternal (asString, 1); + appendInternal (asString, 1); #endif - return *this; + return *this; } const String& String::operator+= (const juce_wchar ch) throw() { - juce_wchar asString[2]; - asString[0] = ch; - asString[1] = 0; + juce_wchar asString[2]; + asString[0] = ch; + asString[1] = 0; #if JUCE_STRINGS_ARE_UNICODE - appendInternal (asString, 1); + appendInternal (asString, 1); #else - operator+= (String (asString)); + operator+= (String (asString)); #endif - return *this; + return *this; } void String::append (const tchar* const other, - const int howMany) throw() + const int howMany) throw() { - if (howMany > 0) - { - int i; - for (i = 0; i < howMany; ++i) - if (other[i] == 0) - break; + if (howMany > 0) + { + int i; + for (i = 0; i < howMany; ++i) + if (other[i] == 0) + break; - appendInternal (other, i); - } + appendInternal (other, i); + } } String& String::operator<< (const int number) throw() { - tchar buffer [64]; - tchar* const end = buffer + 64; - const tchar* const t = intToCharString (end, number); - appendInternal (t, (int) (end - t) - 1); + tchar buffer [64]; + tchar* const end = buffer + 64; + const tchar* const t = intToCharString (end, number); + appendInternal (t, (int) (end - t) - 1); - return *this; + return *this; } String& String::operator<< (const unsigned int number) throw() { - tchar buffer [64]; - tchar* const end = buffer + 64; - const tchar* const t = uintToCharString (end, number); - appendInternal (t, (int) (end - t) - 1); + tchar buffer [64]; + tchar* const end = buffer + 64; + const tchar* const t = uintToCharString (end, number); + appendInternal (t, (int) (end - t) - 1); - return *this; + return *this; } String& String::operator<< (const short number) throw() { - tchar buffer [64]; - tchar* const end = buffer + 64; - const tchar* const t = intToCharString (end, (int) number); - appendInternal (t, (int) (end - t) - 1); + tchar buffer [64]; + tchar* const end = buffer + 64; + const tchar* const t = intToCharString (end, (int) number); + appendInternal (t, (int) (end - t) - 1); - return *this; + return *this; } String& String::operator<< (const long number) throw() { - return operator<< ((int) number); + return operator<< ((int) number); } String& String::operator<< (const unsigned long number) throw() { - return operator<< ((unsigned int) number); + return operator<< ((unsigned int) number); } String& String::operator<< (const double number) throw() { - operator+= (String (number)); - return *this; + operator+= (String (number)); + return *this; } String& String::operator<< (const float number) throw() { - operator+= (String (number)); - return *this; + operator+= (String (number)); + return *this; } String& String::operator<< (const char character) throw() { - operator+= (character); - return *this; + operator+= (character); + return *this; } String& String::operator<< (const juce_wchar character) throw() { - operator+= (character); - return *this; + operator+= (character); + return *this; } String& String::operator<< (const char* const t) throw() { #if JUCE_STRINGS_ARE_UNICODE - operator+= (String (t)); + operator+= (String (t)); #else - operator+= (t); + operator+= (t); #endif - return *this; + return *this; } String& String::operator<< (const juce_wchar* const t) throw() { #if JUCE_STRINGS_ARE_UNICODE - operator+= (t); + operator+= (t); #else - operator+= (String (t)); + operator+= (String (t)); #endif - return *this; + return *this; } String& String::operator<< (const String& t) throw() { - operator+= (t); - return *this; + operator+= (t); + return *this; } int String::indexOfChar (const tchar character) const throw() { - const tchar* t = text->text; + const tchar* t = text->text; - for (;;) - { - if (*t == character) - return (int) (t - text->text); + for (;;) + { + if (*t == character) + return (int) (t - text->text); - if (*t++ == 0) - return -1; - } + if (*t++ == 0) + return -1; + } } int String::lastIndexOfChar (const tchar character) const throw() { - for (int i = CharacterFunctions::length (text->text); --i >= 0;) - if (text->text[i] == character) - return i; + for (int i = CharacterFunctions::length (text->text); --i >= 0;) + if (text->text[i] == character) + return i; - return -1; + return -1; } int String::indexOf (const tchar* const t) const throw() { - const tchar* const r = CharacterFunctions::find (text->text, t); - return (r == 0) ? -1 - : (int) (r - text->text); + const tchar* const r = CharacterFunctions::find (text->text, t); + return (r == 0) ? -1 + : (int) (r - text->text); } int String::indexOfChar (const int startIndex, - const tchar character) const throw() + const tchar character) const throw() { - if (startIndex >= 0 && startIndex >= CharacterFunctions::length (text->text)) - return -1; + if (startIndex >= 0 && startIndex >= CharacterFunctions::length (text->text)) + return -1; - const tchar* t = text->text + jmax (0, startIndex); + const tchar* t = text->text + jmax (0, startIndex); - for (;;) - { - if (*t == character) - return (int) (t - text->text); + for (;;) + { + if (*t == character) + return (int) (t - text->text); - if (*t++ == 0) - return -1; - } + if (*t++ == 0) + return -1; + } } int String::indexOfAnyOf (const tchar* const charactersToLookFor, - const int startIndex, - const bool ignoreCase) const throw() + const int startIndex, + const bool ignoreCase) const throw() { - if (charactersToLookFor == 0 - || (startIndex >= 0 && startIndex >= CharacterFunctions::length (text->text))) - return -1; + if (charactersToLookFor == 0 + || (startIndex >= 0 && startIndex >= CharacterFunctions::length (text->text))) + return -1; - const tchar* t = text->text + jmax (0, startIndex); + const tchar* t = text->text + jmax (0, startIndex); - while (*t != 0) - { - if (CharacterFunctions::indexOfChar (charactersToLookFor, *t, ignoreCase) >= 0) - return (int) (t - text->text); + while (*t != 0) + { + if (CharacterFunctions::indexOfChar (charactersToLookFor, *t, ignoreCase) >= 0) + return (int) (t - text->text); - ++t; - } + ++t; + } - return -1; + return -1; } int String::indexOf (const int startIndex, - const tchar* const other) const throw() + const tchar* const other) const throw() { - if (other == 0 || startIndex >= CharacterFunctions::length (text->text)) - return -1; + if (other == 0 || startIndex >= CharacterFunctions::length (text->text)) + return -1; - const tchar* const found = CharacterFunctions::find (text->text + jmax (0, startIndex), - other); + const tchar* const found = CharacterFunctions::find (text->text + jmax (0, startIndex), + other); - return (found == 0) ? -1 - : (int) (found - text->text); + return (found == 0) ? -1 + : (int) (found - text->text); } int String::indexOfIgnoreCase (const tchar* const other) const throw() { - if (other != 0 && *other != 0) - { - const int len = CharacterFunctions::length (other); - const int end = CharacterFunctions::length (text->text) - len; + if (other != 0 && *other != 0) + { + const int len = CharacterFunctions::length (other); + const int end = CharacterFunctions::length (text->text) - len; - for (int i = 0; i <= end; ++i) - if (CharacterFunctions::compareIgnoreCase (text->text + i, other, len) == 0) - return i; - } + for (int i = 0; i <= end; ++i) + if (CharacterFunctions::compareIgnoreCase (text->text + i, other, len) == 0) + return i; + } - return -1; + return -1; } int String::indexOfIgnoreCase (const int startIndex, - const tchar* const other) const throw() + const tchar* const other) const throw() { - if (other != 0 && *other != 0) - { - const int len = CharacterFunctions::length (other); - const int end = length() - len; + if (other != 0 && *other != 0) + { + const int len = CharacterFunctions::length (other); + const int end = length() - len; - for (int i = jmax (0, startIndex); i <= end; ++i) - if (CharacterFunctions::compareIgnoreCase (text->text + i, other, len) == 0) - return i; - } + for (int i = jmax (0, startIndex); i <= end; ++i) + if (CharacterFunctions::compareIgnoreCase (text->text + i, other, len) == 0) + return i; + } - return -1; + return -1; } int String::lastIndexOf (const tchar* const other) const throw() { - if (other != 0 && *other != 0) - { - const int len = CharacterFunctions::length (other); - int i = length() - len; + if (other != 0 && *other != 0) + { + const int len = CharacterFunctions::length (other); + int i = length() - len; - if (i >= 0) - { - const tchar* n = text->text + i; + if (i >= 0) + { + const tchar* n = text->text + i; - while (i >= 0) - { - if (CharacterFunctions::compare (n--, other, len) == 0) - return i; + while (i >= 0) + { + if (CharacterFunctions::compare (n--, other, len) == 0) + return i; - --i; - } - } - } + --i; + } + } + } - return -1; + return -1; } int String::lastIndexOfIgnoreCase (const tchar* const other) const throw() { - if (other != 0 && *other != 0) - { - const int len = CharacterFunctions::length (other); - int i = length() - len; + if (other != 0 && *other != 0) + { + const int len = CharacterFunctions::length (other); + int i = length() - len; - if (i >= 0) - { - const tchar* n = text->text + i; + if (i >= 0) + { + const tchar* n = text->text + i; - while (i >= 0) - { - if (CharacterFunctions::compareIgnoreCase (n--, other, len) == 0) - return i; + while (i >= 0) + { + if (CharacterFunctions::compareIgnoreCase (n--, other, len) == 0) + return i; - --i; - } - } - } + --i; + } + } + } - return -1; + return -1; } int String::lastIndexOfAnyOf (const tchar* const charactersToLookFor, - const bool ignoreCase) const throw() + const bool ignoreCase) const throw() { - for (int i = CharacterFunctions::length (text->text); --i >= 0;) - if (CharacterFunctions::indexOfChar (charactersToLookFor, text->text [i], ignoreCase) >= 0) - return i; + for (int i = CharacterFunctions::length (text->text); --i >= 0;) + if (CharacterFunctions::indexOfChar (charactersToLookFor, text->text [i], ignoreCase) >= 0) + return i; - return -1; + return -1; } bool String::contains (const tchar* const other) const throw() { - return indexOf (other) >= 0; + return indexOf (other) >= 0; } bool String::containsChar (const tchar character) const throw() { - return indexOfChar (character) >= 0; + return indexOfChar (character) >= 0; } bool String::containsIgnoreCase (const tchar* const t) const throw() { - return indexOfIgnoreCase (t) >= 0; + return indexOfIgnoreCase (t) >= 0; } int String::indexOfWholeWord (const tchar* const word) const throw() { - if (word != 0 && *word != 0) - { - const int wordLen = CharacterFunctions::length (word); - const int end = length() - wordLen; - const tchar* t = text->text; + if (word != 0 && *word != 0) + { + const int wordLen = CharacterFunctions::length (word); + const int end = length() - wordLen; + const tchar* t = text->text; - for (int i = 0; i <= end; ++i) - { - if (CharacterFunctions::compare (t, word, wordLen) == 0 - && (i == 0 || ! CharacterFunctions::isLetterOrDigit (* (t - 1))) - && ! CharacterFunctions::isLetterOrDigit (t [wordLen])) - { - return i; - } + for (int i = 0; i <= end; ++i) + { + if (CharacterFunctions::compare (t, word, wordLen) == 0 + && (i == 0 || ! CharacterFunctions::isLetterOrDigit (* (t - 1))) + && ! CharacterFunctions::isLetterOrDigit (t [wordLen])) + { + return i; + } - ++t; - } - } + ++t; + } + } - return -1; + return -1; } int String::indexOfWholeWordIgnoreCase (const tchar* const word) const throw() { - if (word != 0 && *word != 0) - { - const int wordLen = CharacterFunctions::length (word); - const int end = length() - wordLen; - const tchar* t = text->text; + if (word != 0 && *word != 0) + { + const int wordLen = CharacterFunctions::length (word); + const int end = length() - wordLen; + const tchar* t = text->text; - for (int i = 0; i <= end; ++i) - { - if (CharacterFunctions::compareIgnoreCase (t, word, wordLen) == 0 - && (i == 0 || ! CharacterFunctions::isLetterOrDigit (* (t - 1))) - && ! CharacterFunctions::isLetterOrDigit (t [wordLen])) - { - return i; - } + for (int i = 0; i <= end; ++i) + { + if (CharacterFunctions::compareIgnoreCase (t, word, wordLen) == 0 + && (i == 0 || ! CharacterFunctions::isLetterOrDigit (* (t - 1))) + && ! CharacterFunctions::isLetterOrDigit (t [wordLen])) + { + return i; + } - ++t; - } - } + ++t; + } + } - return -1; + return -1; } bool String::containsWholeWord (const tchar* const wordToLookFor) const throw() { - return indexOfWholeWord (wordToLookFor) >= 0; + return indexOfWholeWord (wordToLookFor) >= 0; } bool String::containsWholeWordIgnoreCase (const tchar* const wordToLookFor) const throw() { - return indexOfWholeWordIgnoreCase (wordToLookFor) >= 0; + return indexOfWholeWordIgnoreCase (wordToLookFor) >= 0; } static int indexOfMatch (const tchar* const wildcard, - const tchar* const test, - const bool ignoreCase) throw() + const tchar* const test, + const bool ignoreCase) throw() { - int start = 0; + int start = 0; - while (test [start] != 0) - { - int i = 0; + while (test [start] != 0) + { + int i = 0; - for (;;) - { - const tchar wc = wildcard [i]; - const tchar c = test [i + start]; + for (;;) + { + const tchar wc = wildcard [i]; + const tchar c = test [i + start]; - if (wc == c - || (ignoreCase && CharacterFunctions::toLowerCase (wc) == CharacterFunctions::toLowerCase (c)) - || (wc == T('?') && c != 0)) - { - if (wc == 0) - return start; + if (wc == c + || (ignoreCase && CharacterFunctions::toLowerCase (wc) == CharacterFunctions::toLowerCase (c)) + || (wc == T('?') && c != 0)) + { + if (wc == 0) + return start; - ++i; - } - else - { - if (wc == T('*') && (wildcard [i + 1] == 0 - || indexOfMatch (wildcard + i + 1, - test + start + i, - ignoreCase) >= 0)) - { - return start; - } + ++i; + } + else + { + if (wc == T('*') && (wildcard [i + 1] == 0 + || indexOfMatch (wildcard + i + 1, + test + start + i, + ignoreCase) >= 0)) + { + return start; + } - break; - } - } + break; + } + } - ++start; - } + ++start; + } - return -1; + return -1; } bool String::matchesWildcard (const tchar* wildcard, const bool ignoreCase) const throw() { - int i = 0; + int i = 0; - for (;;) - { - const tchar wc = wildcard [i]; - const tchar c = text->text [i]; + for (;;) + { + const tchar wc = wildcard [i]; + const tchar c = text->text [i]; - if (wc == c - || (ignoreCase && CharacterFunctions::toLowerCase (wc) == CharacterFunctions::toLowerCase (c)) - || (wc == T('?') && c != 0)) - { - if (wc == 0) - return true; + if (wc == c + || (ignoreCase && CharacterFunctions::toLowerCase (wc) == CharacterFunctions::toLowerCase (c)) + || (wc == T('?') && c != 0)) + { + if (wc == 0) + return true; - ++i; - } - else - { - return wc == T('*') && (wildcard [i + 1] == 0 - || indexOfMatch (wildcard + i + 1, - text->text + i, - ignoreCase) >= 0); - } - } + ++i; + } + else + { + return wc == T('*') && (wildcard [i + 1] == 0 + || indexOfMatch (wildcard + i + 1, + text->text + i, + ignoreCase) >= 0); + } + } } void String::printf (const tchar* const pf, ...) throw() { - va_list list; - va_start (list, pf); + va_list list; + va_start (list, pf); - vprintf (pf, list); + vprintf (pf, list); } const String String::formatted (const tchar* const pf, ...) throw() { - va_list list; - va_start (list, pf); + va_list list; + va_start (list, pf); - String result; - result.vprintf (pf, list); - return result; + String result; + result.vprintf (pf, list); + return result; } void String::vprintf (const tchar* const pf, va_list& args) throw() { - tchar stackBuf [256]; - unsigned int bufSize = 256; - tchar* buf = stackBuf; + tchar stackBuf [256]; + unsigned int bufSize = 256; + tchar* buf = stackBuf; - deleteInternal(); + deleteInternal(); - do - { + do + { #if JUCE_LINUX && JUCE_64BIT - va_list tempArgs; - va_copy (tempArgs, args); - const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, tempArgs); - va_end (tempArgs); + va_list tempArgs; + va_copy (tempArgs, args); + const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, tempArgs); + va_end (tempArgs); #else - const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, args); + const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, args); #endif - if (num > 0) - { - createInternal (num); - memcpy (text->text, buf, (num + 1) * sizeof (tchar)); - break; - } - else if (num == 0) - { - text = &emptyString; - emptyString.refCount = safeEmptyStringRefCount; - break; - } + if (num > 0) + { + createInternal (num); + memcpy (text->text, buf, (num + 1) * sizeof (tchar)); + break; + } + else if (num == 0) + { + text = &emptyString; + emptyString.refCount = safeEmptyStringRefCount; + break; + } - if (buf != stackBuf) - juce_free (buf); + if (buf != stackBuf) + juce_free (buf); - bufSize += 256; - buf = (tchar*) juce_malloc (bufSize * sizeof (tchar)); - } - while (bufSize < 65536); // this is a sanity check to avoid situations where vprintf repeatedly - // returns -1 because of an error rather than because it needs more space. + bufSize += 256; + buf = (tchar*) juce_malloc (bufSize * sizeof (tchar)); + } + while (bufSize < 65536); // this is a sanity check to avoid situations where vprintf repeatedly + // returns -1 because of an error rather than because it needs more space. - if (buf != stackBuf) - juce_free (buf); + if (buf != stackBuf) + juce_free (buf); } const String String::repeatedString (const tchar* const stringToRepeat, - int numberOfTimesToRepeat) throw() + int numberOfTimesToRepeat) throw() { - const int len = CharacterFunctions::length (stringToRepeat); - String result ((int) (len * numberOfTimesToRepeat + 1), (int) 0); + const int len = CharacterFunctions::length (stringToRepeat); + String result ((int) (len * numberOfTimesToRepeat + 1), (int) 0); - tchar* n = result.text->text; - n[0] = 0; + tchar* n = result.text->text; + n[0] = 0; - while (--numberOfTimesToRepeat >= 0) - { - CharacterFunctions::append (n, stringToRepeat); - n += len; - } + while (--numberOfTimesToRepeat >= 0) + { + CharacterFunctions::append (n, stringToRepeat); + n += len; + } - return result; + return result; } const String String::replaceSection (int index, - int numCharsToReplace, - const tchar* const stringToInsert) const throw() + int numCharsToReplace, + const tchar* const stringToInsert) const throw() { - if (index < 0) - { - // a negative index to replace from? - jassertfalse - index = 0; - } + if (index < 0) + { + // a negative index to replace from? + jassertfalse + index = 0; + } - if (numCharsToReplace < 0) - { - // replacing a negative number of characters? - numCharsToReplace = 0; - jassertfalse; - } + if (numCharsToReplace < 0) + { + // replacing a negative number of characters? + numCharsToReplace = 0; + jassertfalse; + } - const int len = length(); + const int len = length(); - if (index + numCharsToReplace > len) - { - if (index > len) - { - // replacing beyond the end of the string? - index = len; - jassertfalse - } + if (index + numCharsToReplace > len) + { + if (index > len) + { + // replacing beyond the end of the string? + index = len; + jassertfalse + } - numCharsToReplace = len - index; - } + numCharsToReplace = len - index; + } - const int newStringLen = (stringToInsert != 0) ? CharacterFunctions::length (stringToInsert) : 0; - const int newTotalLen = len + newStringLen - numCharsToReplace; + const int newStringLen = (stringToInsert != 0) ? CharacterFunctions::length (stringToInsert) : 0; + const int newTotalLen = len + newStringLen - numCharsToReplace; - if (newTotalLen <= 0) - return String::empty; + if (newTotalLen <= 0) + return String::empty; - String result (newTotalLen, (int) 0); + String result (newTotalLen, (int) 0); - memcpy (result.text->text, - text->text, - index * sizeof (tchar)); + memcpy (result.text->text, + text->text, + index * sizeof (tchar)); - if (newStringLen > 0) - memcpy (result.text->text + index, - stringToInsert, - newStringLen * sizeof (tchar)); + if (newStringLen > 0) + memcpy (result.text->text + index, + stringToInsert, + newStringLen * sizeof (tchar)); - const int endStringLen = newTotalLen - (index + newStringLen); + const int endStringLen = newTotalLen - (index + newStringLen); - if (endStringLen > 0) - memcpy (result.text->text + (index + newStringLen), - text->text + (index + numCharsToReplace), - endStringLen * sizeof (tchar)); + if (endStringLen > 0) + memcpy (result.text->text + (index + newStringLen), + text->text + (index + numCharsToReplace), + endStringLen * sizeof (tchar)); - result.text->text [newTotalLen] = 0; + result.text->text [newTotalLen] = 0; - return result; + return result; } const String String::replace (const tchar* const stringToReplace, - const tchar* const stringToInsert, - const bool ignoreCase) const throw() + const tchar* const stringToInsert, + const bool ignoreCase) const throw() { - const int stringToReplaceLen = CharacterFunctions::length (stringToReplace); - const int stringToInsertLen = CharacterFunctions::length (stringToInsert); + const int stringToReplaceLen = CharacterFunctions::length (stringToReplace); + const int stringToInsertLen = CharacterFunctions::length (stringToInsert); - int i = 0; - String result (*this); + int i = 0; + String result (*this); - while ((i = (ignoreCase ? result.indexOfIgnoreCase (i, stringToReplace) - : result.indexOf (i, stringToReplace))) >= 0) - { - result = result.replaceSection (i, stringToReplaceLen, stringToInsert); - i += stringToInsertLen; - } + while ((i = (ignoreCase ? result.indexOfIgnoreCase (i, stringToReplace) + : result.indexOf (i, stringToReplace))) >= 0) + { + result = result.replaceSection (i, stringToReplaceLen, stringToInsert); + i += stringToInsertLen; + } - return result; + return result; } const String String::replaceCharacter (const tchar charToReplace, - const tchar charToInsert) const throw() + const tchar charToInsert) const throw() { - const int index = indexOfChar (charToReplace); + const int index = indexOfChar (charToReplace); - if (index < 0) - return *this; + if (index < 0) + return *this; - String result (*this); - result.dupeInternalIfMultiplyReferenced(); + String result (*this); + result.dupeInternalIfMultiplyReferenced(); - tchar* t = result.text->text + index; + tchar* t = result.text->text + index; - while (*t != 0) - { - if (*t == charToReplace) - *t = charToInsert; + while (*t != 0) + { + if (*t == charToReplace) + *t = charToInsert; - ++t; - } + ++t; + } - return result; + return result; } const String String::replaceCharacters (const String& charactersToReplace, - const tchar* const charactersToInsertInstead) const throw() + const tchar* const charactersToInsertInstead) const throw() { - String result (*this); - result.dupeInternalIfMultiplyReferenced(); + String result (*this); + result.dupeInternalIfMultiplyReferenced(); - tchar* t = result.text->text; - const int len2 = CharacterFunctions::length (charactersToInsertInstead); + tchar* t = result.text->text; + const int len2 = CharacterFunctions::length (charactersToInsertInstead); - // the two strings passed in are supposed to be the same length! - jassert (len2 == charactersToReplace.length()); + // the two strings passed in are supposed to be the same length! + jassert (len2 == charactersToReplace.length()); - while (*t != 0) - { - const int index = charactersToReplace.indexOfChar (*t); + while (*t != 0) + { + const int index = charactersToReplace.indexOfChar (*t); - if (((unsigned int) index) < (unsigned int) len2) - *t = charactersToInsertInstead [index]; + if (((unsigned int) index) < (unsigned int) len2) + *t = charactersToInsertInstead [index]; - ++t; - } + ++t; + } - return result; + return result; } bool String::startsWith (const tchar* const other) const throw() { - return other != 0 - && CharacterFunctions::compare (text->text, other, CharacterFunctions::length (other)) == 0; + return other != 0 + && CharacterFunctions::compare (text->text, other, CharacterFunctions::length (other)) == 0; } bool String::startsWithIgnoreCase (const tchar* const other) const throw() { - return other != 0 - && CharacterFunctions::compareIgnoreCase (text->text, other, CharacterFunctions::length (other)) == 0; + return other != 0 + && CharacterFunctions::compareIgnoreCase (text->text, other, CharacterFunctions::length (other)) == 0; } bool String::startsWithChar (const tchar character) const throw() { - jassert (character != 0); // strings can't contain a null character! + jassert (character != 0); // strings can't contain a null character! - return text->text[0] == character; + return text->text[0] == character; } bool String::endsWithChar (const tchar character) const throw() { - jassert (character != 0); // strings can't contain a null character! + jassert (character != 0); // strings can't contain a null character! - return text->text[0] != 0 - && text->text [length() - 1] == character; + return text->text[0] != 0 + && text->text [length() - 1] == character; } bool String::endsWith (const tchar* const other) const throw() { - if (other == 0) - return false; + if (other == 0) + return false; - const int thisLen = length(); - const int otherLen = CharacterFunctions::length (other); + const int thisLen = length(); + const int otherLen = CharacterFunctions::length (other); - return thisLen >= otherLen - && CharacterFunctions::compare (text->text + thisLen - otherLen, other) == 0; + return thisLen >= otherLen + && CharacterFunctions::compare (text->text + thisLen - otherLen, other) == 0; } bool String::endsWithIgnoreCase (const tchar* const other) const throw() { - if (other == 0) - return false; + if (other == 0) + return false; - const int thisLen = length(); - const int otherLen = CharacterFunctions::length (other); + const int thisLen = length(); + const int otherLen = CharacterFunctions::length (other); - return thisLen >= otherLen - && CharacterFunctions::compareIgnoreCase (text->text + thisLen - otherLen, other) == 0; + return thisLen >= otherLen + && CharacterFunctions::compareIgnoreCase (text->text + thisLen - otherLen, other) == 0; } const String String::toUpperCase() const throw() { - String result (*this); - result.dupeInternalIfMultiplyReferenced(); - CharacterFunctions::toUpperCase (result.text->text); - return result; + String result (*this); + result.dupeInternalIfMultiplyReferenced(); + CharacterFunctions::toUpperCase (result.text->text); + return result; } const String String::toLowerCase() const throw() { - String result (*this); - result.dupeInternalIfMultiplyReferenced(); - CharacterFunctions::toLowerCase (result.text->text); - return result; + String result (*this); + result.dupeInternalIfMultiplyReferenced(); + CharacterFunctions::toLowerCase (result.text->text); + return result; } tchar& String::operator[] (const int index) throw() { - jassert (((unsigned int) index) <= (unsigned int) length()); + jassert (((unsigned int) index) <= (unsigned int) length()); - dupeInternalIfMultiplyReferenced(); + dupeInternalIfMultiplyReferenced(); - return text->text [index]; + return text->text [index]; } tchar String::getLastCharacter() const throw() { - return (isEmpty()) ? ((tchar) 0) - : text->text [CharacterFunctions::length (text->text) - 1]; + return (isEmpty()) ? ((tchar) 0) + : text->text [CharacterFunctions::length (text->text) - 1]; } const String String::substring (int start, int end) const throw() { - if (start < 0) - start = 0; - else if (end <= start) - return empty; + if (start < 0) + start = 0; + else if (end <= start) + return empty; - int len = 0; - const tchar* const t = text->text; + int len = 0; + const tchar* const t = text->text; - while (len <= end && t [len] != 0) - ++len; + while (len <= end && t [len] != 0) + ++len; - if (end >= len) - { - if (start == 0) - return *this; + if (end >= len) + { + if (start == 0) + return *this; - end = len; - } + end = len; + } - return String (text->text + start, - end - start); + return String (text->text + start, + end - start); } const String String::substring (const int start) const throw() { - if (start <= 0) - return *this; + if (start <= 0) + return *this; - const int len = CharacterFunctions::length (text->text); + const int len = CharacterFunctions::length (text->text); - if (start >= len) - return empty; - else - return String (text->text + start, - len - start); + if (start >= len) + return empty; + else + return String (text->text + start, + len - start); } const String String::dropLastCharacters (const int numberToDrop) const throw() { - return String (text->text, - jmax (0, CharacterFunctions::length (text->text) - numberToDrop)); + return String (text->text, + jmax (0, CharacterFunctions::length (text->text) - numberToDrop)); } const String String::getLastCharacters (const int numCharacters) const throw() { - return String (text->text + jmax (0, CharacterFunctions::length (text->text) - jmax (0, numCharacters))); + return String (text->text + jmax (0, CharacterFunctions::length (text->text) - jmax (0, numCharacters))); } const String String::fromFirstOccurrenceOf (const tchar* const sub, - const bool includeSubString, - const bool ignoreCase) const throw() + const bool includeSubString, + const bool ignoreCase) const throw() { - const int i = ignoreCase ? indexOfIgnoreCase (sub) - : indexOf (sub); + const int i = ignoreCase ? indexOfIgnoreCase (sub) + : indexOf (sub); - if (i < 0) - return empty; - else - return substring (includeSubString ? i : i + CharacterFunctions::length (sub)); + if (i < 0) + return empty; + else + return substring (includeSubString ? i : i + CharacterFunctions::length (sub)); } const String String::fromLastOccurrenceOf (const tchar* const sub, - const bool includeSubString, - const bool ignoreCase) const throw() + const bool includeSubString, + const bool ignoreCase) const throw() { - const int i = ignoreCase ? lastIndexOfIgnoreCase (sub) - : lastIndexOf (sub); + const int i = ignoreCase ? lastIndexOfIgnoreCase (sub) + : lastIndexOf (sub); - if (i < 0) - return *this; - else - return substring (includeSubString ? i : i + CharacterFunctions::length (sub)); + if (i < 0) + return *this; + else + return substring (includeSubString ? i : i + CharacterFunctions::length (sub)); } const String String::upToFirstOccurrenceOf (const tchar* const sub, - const bool includeSubString, - const bool ignoreCase) const throw() + const bool includeSubString, + const bool ignoreCase) const throw() { - const int i = ignoreCase ? indexOfIgnoreCase (sub) - : indexOf (sub); + const int i = ignoreCase ? indexOfIgnoreCase (sub) + : indexOf (sub); - if (i < 0) - return *this; - else - return substring (0, includeSubString ? i + CharacterFunctions::length (sub) : i); + if (i < 0) + return *this; + else + return substring (0, includeSubString ? i + CharacterFunctions::length (sub) : i); } const String String::upToLastOccurrenceOf (const tchar* const sub, - const bool includeSubString, - const bool ignoreCase) const throw() + const bool includeSubString, + const bool ignoreCase) const throw() { - const int i = ignoreCase ? lastIndexOfIgnoreCase (sub) - : lastIndexOf (sub); - if (i < 0) - return *this; + const int i = ignoreCase ? lastIndexOfIgnoreCase (sub) + : lastIndexOf (sub); + if (i < 0) + return *this; - return substring (0, includeSubString ? i + CharacterFunctions::length (sub) : i); + return substring (0, includeSubString ? i + CharacterFunctions::length (sub) : i); } bool String::isQuotedString() const throw() { - const String trimmed (trimStart()); + const String trimmed (trimStart()); - return trimmed[0] == T('"') - || trimmed[0] == T('\''); + return trimmed[0] == T('"') + || trimmed[0] == T('\''); } const String String::unquoted() const throw() { - String s (*this); + String s (*this); - if (s[0] == T('"') || s[0] == T('\'')) - s = s.substring (1); + if (s[0] == T('"') || s[0] == T('\'')) + s = s.substring (1); - const int lastCharIndex = s.length() - 1; + const int lastCharIndex = s.length() - 1; - if (lastCharIndex >= 0 - && (s [lastCharIndex] == T('"') || s[lastCharIndex] == T('\''))) - s [lastCharIndex] = 0; + if (lastCharIndex >= 0 + && (s [lastCharIndex] == T('"') || s[lastCharIndex] == T('\''))) + s [lastCharIndex] = 0; - return s; + return s; } const String String::quoted (const tchar quoteCharacter) const throw() { - if (isEmpty()) - return charToString (quoteCharacter) + quoteCharacter; + if (isEmpty()) + return charToString (quoteCharacter) + quoteCharacter; - String t (*this); + String t (*this); - if (! t.startsWithChar (quoteCharacter)) - t = charToString (quoteCharacter) + t; + if (! t.startsWithChar (quoteCharacter)) + t = charToString (quoteCharacter) + t; - if (! t.endsWithChar (quoteCharacter)) - t += quoteCharacter; + if (! t.endsWithChar (quoteCharacter)) + t += quoteCharacter; - return t; + return t; } const String String::trim() const throw() { - if (isEmpty()) - return empty; + if (isEmpty()) + return empty; - int start = 0; + int start = 0; - while (CharacterFunctions::isWhitespace (text->text [start])) - ++start; + while (CharacterFunctions::isWhitespace (text->text [start])) + ++start; - const int len = CharacterFunctions::length (text->text); - int end = len - 1; + const int len = CharacterFunctions::length (text->text); + int end = len - 1; - while ((end >= start) && CharacterFunctions::isWhitespace (text->text [end])) - --end; + while ((end >= start) && CharacterFunctions::isWhitespace (text->text [end])) + --end; - ++end; + ++end; - if (end <= start) - return empty; - else if (start > 0 || end < len) - return String (text->text + start, end - start); - else - return *this; + if (end <= start) + return empty; + else if (start > 0 || end < len) + return String (text->text + start, end - start); + else + return *this; } const String String::trimStart() const throw() { - if (isEmpty()) - return empty; + if (isEmpty()) + return empty; - const tchar* t = text->text; + const tchar* t = text->text; - while (CharacterFunctions::isWhitespace (*t)) - ++t; + while (CharacterFunctions::isWhitespace (*t)) + ++t; - if (t == text->text) - return *this; - else - return String (t); + if (t == text->text) + return *this; + else + return String (t); } const String String::trimEnd() const throw() { - if (isEmpty()) - return empty; + if (isEmpty()) + return empty; - const tchar* endT = text->text + (CharacterFunctions::length (text->text) - 1); + const tchar* endT = text->text + (CharacterFunctions::length (text->text) - 1); - while ((endT >= text->text) && CharacterFunctions::isWhitespace (*endT)) - --endT; + while ((endT >= text->text) && CharacterFunctions::isWhitespace (*endT)) + --endT; - return String (text->text, (int) (++endT - text->text)); + return String (text->text, (int) (++endT - text->text)); } const String String::trimCharactersAtStart (const tchar* charactersToTrim) const throw() { - jassert (charactersToTrim != 0); + jassert (charactersToTrim != 0); - if (isEmpty()) - return empty; + if (isEmpty()) + return empty; - const tchar* t = text->text; + const tchar* t = text->text; - while (CharacterFunctions::indexOfCharFast (charactersToTrim, *t) >= 0) - ++t; + while (CharacterFunctions::indexOfCharFast (charactersToTrim, *t) >= 0) + ++t; - if (t == text->text) - return *this; - else - return String (t); + if (t == text->text) + return *this; + else + return String (t); } const String String::trimCharactersAtEnd (const tchar* charactersToTrim) const throw() { - jassert (charactersToTrim != 0); + jassert (charactersToTrim != 0); - if (isEmpty()) - return empty; + if (isEmpty()) + return empty; - const tchar* endT = text->text + (CharacterFunctions::length (text->text) - 1); + const tchar* endT = text->text + (CharacterFunctions::length (text->text) - 1); - while ((endT >= text->text) && CharacterFunctions::indexOfCharFast (charactersToTrim, *endT) >= 0) - --endT; + while ((endT >= text->text) && CharacterFunctions::indexOfCharFast (charactersToTrim, *endT) >= 0) + --endT; - return String (text->text, (int) (++endT - text->text)); + return String (text->text, (int) (++endT - text->text)); } const String String::retainCharacters (const tchar* const charactersToRetain) const throw() { - jassert (charactersToRetain != 0); + jassert (charactersToRetain != 0); - if (isEmpty()) - return empty; + if (isEmpty()) + return empty; - String result (text->allocatedNumChars, (int) 0); - tchar* dst = result.text->text; - const tchar* src = text->text; + String result (text->allocatedNumChars, (int) 0); + tchar* dst = result.text->text; + const tchar* src = text->text; - while (*src != 0) - { - if (CharacterFunctions::indexOfCharFast (charactersToRetain, *src) >= 0) - *dst++ = *src; + while (*src != 0) + { + if (CharacterFunctions::indexOfCharFast (charactersToRetain, *src) >= 0) + *dst++ = *src; - ++src; - } + ++src; + } - *dst = 0; - return result; + *dst = 0; + return result; } const String String::removeCharacters (const tchar* const charactersToRemove) const throw() { - jassert (charactersToRemove != 0); + jassert (charactersToRemove != 0); - if (isEmpty()) - return empty; + if (isEmpty()) + return empty; - String result (text->allocatedNumChars, (int) 0); - tchar* dst = result.text->text; - const tchar* src = text->text; + String result (text->allocatedNumChars, (int) 0); + tchar* dst = result.text->text; + const tchar* src = text->text; - while (*src != 0) - { - if (CharacterFunctions::indexOfCharFast (charactersToRemove, *src) < 0) - *dst++ = *src; + while (*src != 0) + { + if (CharacterFunctions::indexOfCharFast (charactersToRemove, *src) < 0) + *dst++ = *src; - ++src; - } + ++src; + } - *dst = 0; - return result; + *dst = 0; + return result; } const String String::initialSectionContainingOnly (const tchar* const permittedCharacters) const throw() { - return substring (0, CharacterFunctions::getIntialSectionContainingOnly (text->text, permittedCharacters)); + return substring (0, CharacterFunctions::getIntialSectionContainingOnly (text->text, permittedCharacters)); } const String String::initialSectionNotContaining (const tchar* const charactersToStopAt) const throw() { - jassert (charactersToStopAt != 0); + jassert (charactersToStopAt != 0); - const tchar* const t = text->text; - int i = 0; + const tchar* const t = text->text; + int i = 0; - while (t[i] != 0) - { - if (CharacterFunctions::indexOfCharFast (charactersToStopAt, t[i]) >= 0) - return String (text->text, i); + while (t[i] != 0) + { + if (CharacterFunctions::indexOfCharFast (charactersToStopAt, t[i]) >= 0) + return String (text->text, i); - ++i; - } + ++i; + } - return empty; + return empty; } bool String::containsOnly (const tchar* const chars) const throw() { - jassert (chars != 0); + jassert (chars != 0); - const tchar* t = text->text; + const tchar* t = text->text; - while (*t != 0) - if (CharacterFunctions::indexOfCharFast (chars, *t++) < 0) - return false; + while (*t != 0) + if (CharacterFunctions::indexOfCharFast (chars, *t++) < 0) + return false; - return true; + return true; } bool String::containsAnyOf (const tchar* const chars) const throw() { - jassert (chars != 0); + jassert (chars != 0); - const tchar* t = text->text; + const tchar* t = text->text; - while (*t != 0) - if (CharacterFunctions::indexOfCharFast (chars, *t++) >= 0) - return true; + while (*t != 0) + if (CharacterFunctions::indexOfCharFast (chars, *t++) >= 0) + return true; - return false; + return false; } bool String::containsNonWhitespaceChars() const throw() { - const tchar* t = text->text; + const tchar* t = text->text; - while (*t != 0) - if (! CharacterFunctions::isWhitespace (*t++)) - return true; + while (*t != 0) + if (! CharacterFunctions::isWhitespace (*t++)) + return true; - return false; + return false; } int String::getIntValue() const throw() { - return CharacterFunctions::getIntValue (text->text); + return CharacterFunctions::getIntValue (text->text); } int String::getTrailingIntValue() const throw() { - int n = 0; - int mult = 1; - const tchar* t = text->text + length(); + int n = 0; + int mult = 1; + const tchar* t = text->text + length(); - while (--t >= text->text) - { - const tchar c = *t; + while (--t >= text->text) + { + const tchar c = *t; - if (! CharacterFunctions::isDigit (c)) - { - if (c == T('-')) - n = -n; + if (! CharacterFunctions::isDigit (c)) + { + if (c == T('-')) + n = -n; - break; - } + break; + } - n += mult * (c - T('0')); - mult *= 10; - } + n += mult * (c - T('0')); + mult *= 10; + } - return n; + return n; } int64 String::getLargeIntValue() const throw() { - return CharacterFunctions::getInt64Value (text->text); + return CharacterFunctions::getInt64Value (text->text); } float String::getFloatValue() const throw() { - return (float) CharacterFunctions::getDoubleValue (text->text); + return (float) CharacterFunctions::getDoubleValue (text->text); } double String::getDoubleValue() const throw() { - return CharacterFunctions::getDoubleValue (text->text); + return CharacterFunctions::getDoubleValue (text->text); } static const tchar* const hexDigits = T("0123456789abcdef"); const String String::toHexString (const int number) throw() { - tchar buffer[32]; - tchar* const end = buffer + 32; - tchar* t = end; - *--t = 0; - unsigned int v = (unsigned int) number; + tchar buffer[32]; + tchar* const end = buffer + 32; + tchar* t = end; + *--t = 0; + unsigned int v = (unsigned int) number; - do - { - *--t = hexDigits [v & 15]; - v >>= 4; + do + { + *--t = hexDigits [v & 15]; + v >>= 4; - } while (v != 0); + } while (v != 0); - return String (t, (int) (((char*) end) - (char*) t) - 1); + return String (t, (int) (((char*) end) - (char*) t) - 1); } const String String::toHexString (const int64 number) throw() { - tchar buffer[32]; - tchar* const end = buffer + 32; - tchar* t = end; - *--t = 0; - uint64 v = (uint64) number; + tchar buffer[32]; + tchar* const end = buffer + 32; + tchar* t = end; + *--t = 0; + uint64 v = (uint64) number; - do - { - *--t = hexDigits [(int) (v & 15)]; - v >>= 4; + do + { + *--t = hexDigits [(int) (v & 15)]; + v >>= 4; - } while (v != 0); + } while (v != 0); - return String (t, (int) (((char*) end) - (char*) t)); + return String (t, (int) (((char*) end) - (char*) t)); } const String String::toHexString (const short number) throw() { - return toHexString ((int) (unsigned short) number); + return toHexString ((int) (unsigned short) number); } const String String::toHexString (const unsigned char* data, - const int size, - const int groupSize) throw() + const int size, + const int groupSize) throw() { - if (size <= 0) - return empty; + if (size <= 0) + return empty; - int numChars = (size * 2) + 2; - if (groupSize > 0) - numChars += size / groupSize; + int numChars = (size * 2) + 2; + if (groupSize > 0) + numChars += size / groupSize; - String s (numChars, (int) 0); + String s (numChars, (int) 0); - tchar* d = s.text->text; + tchar* d = s.text->text; - for (int i = 0; i < size; ++i) - { - *d++ = hexDigits [(*data) >> 4]; - *d++ = hexDigits [(*data) & 0xf]; - ++data; + for (int i = 0; i < size; ++i) + { + *d++ = hexDigits [(*data) >> 4]; + *d++ = hexDigits [(*data) & 0xf]; + ++data; - if (groupSize > 0 && (i % groupSize) == (groupSize - 1) && i < (size - 1)) - *d++ = T(' '); - } + if (groupSize > 0 && (i % groupSize) == (groupSize - 1) && i < (size - 1)) + *d++ = T(' '); + } - *d = 0; - return s; + *d = 0; + return s; } int String::getHexValue32() const throw() { - int result = 0; - const tchar* c = text->text; + int result = 0; + const tchar* c = text->text; - for (;;) - { - const int hexValue = CharacterFunctions::getHexDigitValue (*c); + for (;;) + { + const int hexValue = CharacterFunctions::getHexDigitValue (*c); - if (hexValue >= 0) - result = (result << 4) | hexValue; - else if (*c == 0) - break; + if (hexValue >= 0) + result = (result << 4) | hexValue; + else if (*c == 0) + break; - ++c; - } + ++c; + } - return result; + return result; } int64 String::getHexValue64() const throw() { - int64 result = 0; - const tchar* c = text->text; + int64 result = 0; + const tchar* c = text->text; - for (;;) - { - const int hexValue = CharacterFunctions::getHexDigitValue (*c); + for (;;) + { + const int hexValue = CharacterFunctions::getHexDigitValue (*c); - if (hexValue >= 0) - result = (result << 4) | hexValue; - else if (*c == 0) - break; + if (hexValue >= 0) + result = (result << 4) | hexValue; + else if (*c == 0) + break; - ++c; - } + ++c; + } - return result; + return result; } const String String::createStringFromData (const void* const data_, - const int size) throw() + const int size) throw() { - const char* const data = (const char*) data_; + const char* const data = (const char*) data_; - if (size <= 0 || data == 0) - { - return empty; - } - else if (size < 2) - { - return charToString (data[0]); - } - else if ((data[0] == (char)-2 && data[1] == (char)-1) - || (data[0] == (char)-1 && data[1] == (char)-2)) - { - // assume it's 16-bit unicode - const bool bigEndian = (data[0] == (char)-2); - const int numChars = size / 2 - 1; + if (size <= 0 || data == 0) + { + return empty; + } + else if (size < 2) + { + return charToString (data[0]); + } + else if ((data[0] == (char)-2 && data[1] == (char)-1) + || (data[0] == (char)-1 && data[1] == (char)-2)) + { + // assume it's 16-bit unicode + const bool bigEndian = (data[0] == (char)-2); + const int numChars = size / 2 - 1; - String result; - result.preallocateStorage (numChars + 2); + String result; + result.preallocateStorage (numChars + 2); - const uint16* const src = (const uint16*) (data + 2); - tchar* const dst = const_cast ((const tchar*) result); + const uint16* const src = (const uint16*) (data + 2); + tchar* const dst = const_cast ((const tchar*) result); - if (bigEndian) - { - for (int i = 0; i < numChars; ++i) - dst[i] = (tchar) ByteOrder::swapIfLittleEndian (src[i]); - } - else - { - for (int i = 0; i < numChars; ++i) - dst[i] = (tchar) ByteOrder::swapIfBigEndian (src[i]); - } + if (bigEndian) + { + for (int i = 0; i < numChars; ++i) + dst[i] = (tchar) ByteOrder::swapIfLittleEndian (src[i]); + } + else + { + for (int i = 0; i < numChars; ++i) + dst[i] = (tchar) ByteOrder::swapIfBigEndian (src[i]); + } - dst [numChars] = 0; - return result; - } - else - { - return String::fromUTF8 ((const uint8*) data, size); - } + dst [numChars] = 0; + return result; + } + else + { + return String::fromUTF8 ((const uint8*) data, size); + } } const char* String::toUTF8() const throw() { - if (isEmpty()) - { - return (const char*) emptyCharString; - } - else - { - String* const mutableThis = const_cast (this); + if (isEmpty()) + { + return (const char*) emptyCharString; + } + else + { + String* const mutableThis = const_cast (this); - mutableThis->dupeInternalIfMultiplyReferenced(); + mutableThis->dupeInternalIfMultiplyReferenced(); - const int currentLen = CharacterFunctions::length (text->text) + 1; - const int utf8BytesNeeded = copyToUTF8 (0); + const int currentLen = CharacterFunctions::length (text->text) + 1; + const int utf8BytesNeeded = copyToUTF8 (0); - mutableThis->text = (InternalRefCountedStringHolder*) - juce_realloc (text, sizeof (InternalRefCountedStringHolder) - + (currentLen * sizeof (juce_wchar) + utf8BytesNeeded)); + mutableThis->text = (InternalRefCountedStringHolder*) + juce_realloc (text, sizeof (InternalRefCountedStringHolder) + + (currentLen * sizeof (juce_wchar) + utf8BytesNeeded)); - char* const otherCopy = (char*) (text->text + currentLen); - copyToUTF8 ((uint8*) otherCopy); + char* const otherCopy = (char*) (text->text + currentLen); + copyToUTF8 ((uint8*) otherCopy); - return otherCopy; - } + return otherCopy; + } } int String::copyToUTF8 (uint8* const buffer, const int maxBufferSizeBytes) const throw() { - jassert (maxBufferSizeBytes >= 0); // keep this value positive, or no characters will be copied! + jassert (maxBufferSizeBytes >= 0); // keep this value positive, or no characters will be copied! #if JUCE_STRINGS_ARE_UNICODE - int num = 0, index = 0; + int num = 0, index = 0; - for (;;) - { - const uint32 c = (uint32) text->text [index++]; + for (;;) + { + const uint32 c = (uint32) text->text [index++]; - if (c >= 0x80) - { - int numExtraBytes = 1; + if (c >= 0x80) + { + int numExtraBytes = 1; - if (c >= 0x800) - { - ++numExtraBytes; + if (c >= 0x800) + { + ++numExtraBytes; - if (c >= 0x10000) - { - ++numExtraBytes; + if (c >= 0x10000) + { + ++numExtraBytes; - if (c >= 0x200000) - { - ++numExtraBytes; + if (c >= 0x200000) + { + ++numExtraBytes; - if (c >= 0x4000000) - ++numExtraBytes; - } - } - } + if (c >= 0x4000000) + ++numExtraBytes; + } + } + } - if (buffer != 0) - { - if (num + numExtraBytes >= maxBufferSizeBytes) - { - buffer [num++] = 0; - break; - } - else - { - buffer [num++] = (uint8) ((0xff << (7 - numExtraBytes)) | (c >> (numExtraBytes * 6))); + if (buffer != 0) + { + if (num + numExtraBytes >= maxBufferSizeBytes) + { + buffer [num++] = 0; + break; + } + else + { + buffer [num++] = (uint8) ((0xff << (7 - numExtraBytes)) | (c >> (numExtraBytes * 6))); - while (--numExtraBytes >= 0) - buffer [num++] = (uint8) (0x80 | (0x3f & (c >> (numExtraBytes * 6)))); - } - } - else - { - num += numExtraBytes + 1; - } - } - else - { - if (buffer != 0) - { - if (num + 1 >= maxBufferSizeBytes) - { - buffer [num++] = 0; - break; - } + while (--numExtraBytes >= 0) + buffer [num++] = (uint8) (0x80 | (0x3f & (c >> (numExtraBytes * 6)))); + } + } + else + { + num += numExtraBytes + 1; + } + } + else + { + if (buffer != 0) + { + if (num + 1 >= maxBufferSizeBytes) + { + buffer [num++] = 0; + break; + } - buffer [num] = (uint8) c; - } + buffer [num] = (uint8) c; + } - ++num; - } + ++num; + } - if (c == 0) - break; - } + if (c == 0) + break; + } - return num; + return num; #else - const int numBytes = jmin (maxBufferSizeBytes, length() + 1); + const int numBytes = jmin (maxBufferSizeBytes, length() + 1); - if (buffer != 0) - copyToBuffer ((char*) buffer, maxBufferSizeBytes); + if (buffer != 0) + copyToBuffer ((char*) buffer, maxBufferSizeBytes); - return numBytes; + return numBytes; #endif } const String String::fromUTF8 (const uint8* const buffer, int bufferSizeBytes) throw() { - if (buffer == 0) - return empty; + if (buffer == 0) + return empty; - if (bufferSizeBytes < 0) - bufferSizeBytes = INT_MAX; + if (bufferSizeBytes < 0) + bufferSizeBytes = INT_MAX; - int numBytes; - for (numBytes = 0; numBytes < bufferSizeBytes; ++numBytes) - if (buffer [numBytes] == 0) - break; + size_t numBytes; + for (numBytes = 0; numBytes < (size_t) bufferSizeBytes; ++numBytes) + if (buffer [numBytes] == 0) + break; - String result (numBytes + 1, 0); - tchar* dest = result.text->text; + String result ((int) numBytes + 1, 0); + tchar* dest = result.text->text; - int i = 0; - while (i < numBytes) - { - const uint8 c = buffer [i++]; + size_t i = 0; + while (i < numBytes) + { + const uint8 c = buffer [i++]; - if ((c & 0x80) != 0) - { - int mask = 0x7f; - int bit = 0x40; - int numExtraValues = 0; + if ((c & 0x80) != 0) + { + int mask = 0x7f; + int bit = 0x40; + int numExtraValues = 0; - while (bit != 0 && (c & bit) != 0) - { - bit >>= 1; - mask >>= 1; - ++numExtraValues; - } + while (bit != 0 && (c & bit) != 0) + { + bit >>= 1; + mask >>= 1; + ++numExtraValues; + } - int n = (c & mask); + int n = (c & mask); - while (--numExtraValues >= 0 && i < bufferSizeBytes) - { - const uint8 nextByte = buffer[i]; + while (--numExtraValues >= 0 && i < (size_t) bufferSizeBytes) + { + const uint8 nextByte = buffer[i]; - if ((nextByte & 0xc0) != 0x80) - break; + if ((nextByte & 0xc0) != 0x80) + break; - n <<= 6; - n |= (nextByte & 0x3f); - ++i; - } + n <<= 6; + n |= (nextByte & 0x3f); + ++i; + } - *dest++ = (tchar) n; - } - else - { - *dest++ = (tchar) c; - } - } + *dest++ = (tchar) n; + } + else + { + *dest++ = (tchar) c; + } + } - *dest = 0; - return result; + *dest = 0; + return result; } String::Concatenator::Concatenator (String& stringToAppendTo) - : result (stringToAppendTo), - nextIndex (stringToAppendTo.length()) + : result (stringToAppendTo), + nextIndex (stringToAppendTo.length()) { } @@ -12730,14 +12493,14 @@ String::Concatenator::~Concatenator() void String::Concatenator::append (const String& s) { - const int len = s.length(); + const int len = s.length(); - if (len > 0) - { - result.preallocateStorage (nextIndex + len); - s.copyToBuffer (const_cast ((const tchar*) result) + nextIndex, len); - nextIndex += len; - } + if (len > 0) + { + result.preallocateStorage (nextIndex + len); + s.copyToBuffer (const_cast ((const tchar*) result) + nextIndex, len); + nextIndex += len; + } } END_JUCE_NAMESPACE @@ -12753,511 +12516,511 @@ StringArray::StringArray() throw() StringArray::StringArray (const StringArray& other) throw() { - addArray (other); + addArray (other); } StringArray::StringArray (const juce_wchar** const initialStrings, - const int numberOfStrings) throw() + const int numberOfStrings) throw() { - for (int i = 0; i < numberOfStrings; ++i) - add (initialStrings [i]); + for (int i = 0; i < numberOfStrings; ++i) + add (initialStrings [i]); } StringArray::StringArray (const char** const initialStrings, - const int numberOfStrings) throw() + const int numberOfStrings) throw() { - for (int i = 0; i < numberOfStrings; ++i) - add (initialStrings [i]); + for (int i = 0; i < numberOfStrings; ++i) + add (initialStrings [i]); } StringArray::StringArray (const juce_wchar** const initialStrings) throw() { - int i = 0; + int i = 0; - while (initialStrings[i] != 0) - add (initialStrings [i++]); + while (initialStrings[i] != 0) + add (initialStrings [i++]); } StringArray::StringArray (const char** const initialStrings) throw() { - int i = 0; + int i = 0; - while (initialStrings[i] != 0) - add (initialStrings [i++]); + while (initialStrings[i] != 0) + add (initialStrings [i++]); } const StringArray& StringArray::operator= (const StringArray& other) throw() { - if (this != &other) - { - clear(); - addArray (other); - } + if (this != &other) + { + clear(); + addArray (other); + } - return *this; + return *this; } StringArray::~StringArray() throw() { - clear(); + clear(); } bool StringArray::operator== (const StringArray& other) const throw() { - if (other.size() != size()) - return false; + if (other.size() != size()) + return false; - for (int i = size(); --i >= 0;) - if (*other.strings.getUnchecked(i) != *strings.getUnchecked(i)) - return false; + for (int i = size(); --i >= 0;) + if (*other.strings.getUnchecked(i) != *strings.getUnchecked(i)) + return false; - return true; + return true; } bool StringArray::operator!= (const StringArray& other) const throw() { - return ! operator== (other); + return ! operator== (other); } void StringArray::clear() throw() { - strings.clear(); + strings.clear(); } const String& StringArray::operator[] (const int index) const throw() { - if (((unsigned int) index) < (unsigned int) strings.size()) - return *strings.getUnchecked (index); + if (((unsigned int) index) < (unsigned int) strings.size()) + return *strings.getUnchecked (index); - return String::empty; + return String::empty; } void StringArray::add (const String& newString) throw() { - strings.add (new String (newString)); + strings.add (new String (newString)); } void StringArray::insert (const int index, - const String& newString) throw() + const String& newString) throw() { - strings.insert (index, new String (newString)); + strings.insert (index, new String (newString)); } void StringArray::addIfNotAlreadyThere (const String& newString, - const bool ignoreCase) throw() + const bool ignoreCase) throw() { - if (! contains (newString, ignoreCase)) - add (newString); + if (! contains (newString, ignoreCase)) + add (newString); } void StringArray::addArray (const StringArray& otherArray, - int startIndex, - int numElementsToAdd) throw() + int startIndex, + int numElementsToAdd) throw() { - if (startIndex < 0) - { - jassertfalse - startIndex = 0; - } + if (startIndex < 0) + { + jassertfalse + startIndex = 0; + } - if (numElementsToAdd < 0 || startIndex + numElementsToAdd > otherArray.size()) - numElementsToAdd = otherArray.size() - startIndex; + if (numElementsToAdd < 0 || startIndex + numElementsToAdd > otherArray.size()) + numElementsToAdd = otherArray.size() - startIndex; - while (--numElementsToAdd >= 0) - strings.add (new String (*otherArray.strings.getUnchecked (startIndex++))); + while (--numElementsToAdd >= 0) + strings.add (new String (*otherArray.strings.getUnchecked (startIndex++))); } void StringArray::set (const int index, - const String& newString) throw() + const String& newString) throw() { - String* const s = strings [index]; + String* const s = strings [index]; - if (s != 0) - *s = newString; - else if (index >= 0) - add (newString); + if (s != 0) + *s = newString; + else if (index >= 0) + add (newString); } bool StringArray::contains (const String& stringToLookFor, - const bool ignoreCase) const throw() + const bool ignoreCase) const throw() { - if (ignoreCase) - { - for (int i = size(); --i >= 0;) - if (strings.getUnchecked(i)->equalsIgnoreCase (stringToLookFor)) - return true; - } - else - { - for (int i = size(); --i >= 0;) - if (stringToLookFor == *strings.getUnchecked(i)) - return true; - } + if (ignoreCase) + { + for (int i = size(); --i >= 0;) + if (strings.getUnchecked(i)->equalsIgnoreCase (stringToLookFor)) + return true; + } + else + { + for (int i = size(); --i >= 0;) + if (stringToLookFor == *strings.getUnchecked(i)) + return true; + } - return false; + return false; } int StringArray::indexOf (const String& stringToLookFor, - const bool ignoreCase, - int i) const throw() + const bool ignoreCase, + int i) const throw() { - if (i < 0) - i = 0; + if (i < 0) + i = 0; - const int numElements = size(); + const int numElements = size(); - if (ignoreCase) - { - while (i < numElements) - { - if (strings.getUnchecked(i)->equalsIgnoreCase (stringToLookFor)) - return i; + if (ignoreCase) + { + while (i < numElements) + { + if (strings.getUnchecked(i)->equalsIgnoreCase (stringToLookFor)) + return i; - ++i; - } - } - else - { - while (i < numElements) - { - if (stringToLookFor == *strings.getUnchecked (i)) - return i; + ++i; + } + } + else + { + while (i < numElements) + { + if (stringToLookFor == *strings.getUnchecked (i)) + return i; - ++i; - } - } + ++i; + } + } - return -1; + return -1; } void StringArray::remove (const int index) throw() { - strings.remove (index); + strings.remove (index); } void StringArray::removeString (const String& stringToRemove, - const bool ignoreCase) throw() + const bool ignoreCase) throw() { - if (ignoreCase) - { - for (int i = size(); --i >= 0;) - if (strings.getUnchecked(i)->equalsIgnoreCase (stringToRemove)) - strings.remove (i); - } - else - { - for (int i = size(); --i >= 0;) - if (stringToRemove == *strings.getUnchecked (i)) - strings.remove (i); - } + if (ignoreCase) + { + for (int i = size(); --i >= 0;) + if (strings.getUnchecked(i)->equalsIgnoreCase (stringToRemove)) + strings.remove (i); + } + else + { + for (int i = size(); --i >= 0;) + if (stringToRemove == *strings.getUnchecked (i)) + strings.remove (i); + } } void StringArray::removeEmptyStrings (const bool removeWhitespaceStrings) throw() { - if (removeWhitespaceStrings) - { - for (int i = size(); --i >= 0;) - if (! strings.getUnchecked(i)->containsNonWhitespaceChars()) - strings.remove (i); - } - else - { - for (int i = size(); --i >= 0;) - if (strings.getUnchecked(i)->isEmpty()) - strings.remove (i); - } + if (removeWhitespaceStrings) + { + for (int i = size(); --i >= 0;) + if (! strings.getUnchecked(i)->containsNonWhitespaceChars()) + strings.remove (i); + } + else + { + for (int i = size(); --i >= 0;) + if (strings.getUnchecked(i)->isEmpty()) + strings.remove (i); + } } void StringArray::trim() throw() { - for (int i = size(); --i >= 0;) - { - String& s = *strings.getUnchecked(i); - s = s.trim(); - } + for (int i = size(); --i >= 0;) + { + String& s = *strings.getUnchecked(i); + s = s.trim(); + } } class InternalStringArrayComparator { public: - static int compareElements (void* const first, void* const second) throw() - { - return ((const String*) first)->compare (*(const String*) second); - } + static int compareElements (void* const first, void* const second) throw() + { + return ((const String*) first)->compare (*(const String*) second); + } }; class InsensitiveInternalStringArrayComparator { public: - static int compareElements (void* const first, void* const second) throw() - { - return ((const String*) first)->compareIgnoreCase (*(const String*) second); - } + static int compareElements (void* const first, void* const second) throw() + { + return ((const String*) first)->compareIgnoreCase (*(const String*) second); + } }; void StringArray::sort (const bool ignoreCase) throw() { - if (ignoreCase) - { - InsensitiveInternalStringArrayComparator comp; - strings.sort (comp); - } - else - { - InternalStringArrayComparator comp; - strings.sort (comp); - } + if (ignoreCase) + { + InsensitiveInternalStringArrayComparator comp; + strings.sort (comp); + } + else + { + InternalStringArrayComparator comp; + strings.sort (comp); + } } void StringArray::move (const int currentIndex, int newIndex) throw() { - strings.move (currentIndex, newIndex); + strings.move (currentIndex, newIndex); } const String StringArray::joinIntoString (const String& separator, - int start, - int numberToJoin) const throw() + int start, + int numberToJoin) const throw() { - const int last = (numberToJoin < 0) ? size() - : jmin (size(), start + numberToJoin); + const int last = (numberToJoin < 0) ? size() + : jmin (size(), start + numberToJoin); - if (start < 0) - start = 0; + if (start < 0) + start = 0; - if (start >= last) - return String::empty; + if (start >= last) + return String::empty; - if (start == last - 1) - return *strings.getUnchecked (start); + if (start == last - 1) + return *strings.getUnchecked (start); - const int separatorLen = separator.length(); - int charsNeeded = separatorLen * (last - start - 1); + const int separatorLen = separator.length(); + int charsNeeded = separatorLen * (last - start - 1); - for (int i = start; i < last; ++i) - charsNeeded += strings.getUnchecked(i)->length(); + for (int i = start; i < last; ++i) + charsNeeded += strings.getUnchecked(i)->length(); - String result; - result.preallocateStorage (charsNeeded); + String result; + result.preallocateStorage (charsNeeded); - tchar* dest = (tchar*) (const tchar*) result; + tchar* dest = (tchar*) (const tchar*) result; - while (start < last) - { - const String& s = *strings.getUnchecked (start); - const int len = s.length(); + while (start < last) + { + const String& s = *strings.getUnchecked (start); + const int len = s.length(); - if (len > 0) - { - s.copyToBuffer (dest, len); - dest += len; - } + if (len > 0) + { + s.copyToBuffer (dest, len); + dest += len; + } - if (++start < last && separatorLen > 0) - { - separator.copyToBuffer (dest, separatorLen); - dest += separatorLen; - } - } + if (++start < last && separatorLen > 0) + { + separator.copyToBuffer (dest, separatorLen); + dest += separatorLen; + } + } - *dest = 0; + *dest = 0; - return result; + return result; } int StringArray::addTokens (const tchar* const text, - const bool preserveQuotedStrings) throw() + const bool preserveQuotedStrings) throw() { - return addTokens (text, - T(" \n\r\t"), - preserveQuotedStrings ? T("\"") : 0); + return addTokens (text, + T(" \n\r\t"), + preserveQuotedStrings ? T("\"") : 0); } int StringArray::addTokens (const tchar* const text, - const tchar* breakCharacters, - const tchar* quoteCharacters) throw() + const tchar* breakCharacters, + const tchar* quoteCharacters) throw() { - int num = 0; + int num = 0; - if (text != 0 && *text != 0) - { - if (breakCharacters == 0) - breakCharacters = T(""); + if (text != 0 && *text != 0) + { + if (breakCharacters == 0) + breakCharacters = T(""); - if (quoteCharacters == 0) - quoteCharacters = T(""); + if (quoteCharacters == 0) + quoteCharacters = T(""); - bool insideQuotes = false; - tchar currentQuoteChar = 0; + bool insideQuotes = false; + tchar currentQuoteChar = 0; - int i = 0; - int tokenStart = 0; + int i = 0; + int tokenStart = 0; - for (;;) - { - const tchar c = text[i]; + for (;;) + { + const tchar c = text[i]; - bool isBreak = (c == 0); + bool isBreak = (c == 0); - if (! (insideQuotes || isBreak)) - { - const tchar* b = breakCharacters; - while (*b != 0) - { - if (*b++ == c) - { - isBreak = true; - break; - } - } - } + if (! (insideQuotes || isBreak)) + { + const tchar* b = breakCharacters; + while (*b != 0) + { + if (*b++ == c) + { + isBreak = true; + break; + } + } + } - if (! isBreak) - { - bool isQuote = false; - const tchar* q = quoteCharacters; - while (*q != 0) - { - if (*q++ == c) - { - isQuote = true; - break; - } - } + if (! isBreak) + { + bool isQuote = false; + const tchar* q = quoteCharacters; + while (*q != 0) + { + if (*q++ == c) + { + isQuote = true; + break; + } + } - if (isQuote) - { - if (insideQuotes) - { - // only break out of quotes-mode if we find a matching quote to the - // one that we opened with.. - if (currentQuoteChar == c) - insideQuotes = false; - } - else - { - insideQuotes = true; - currentQuoteChar = c; - } - } - } - else - { - add (String (text + tokenStart, i - tokenStart)); + if (isQuote) + { + if (insideQuotes) + { + // only break out of quotes-mode if we find a matching quote to the + // one that we opened with.. + if (currentQuoteChar == c) + insideQuotes = false; + } + else + { + insideQuotes = true; + currentQuoteChar = c; + } + } + } + else + { + add (String (text + tokenStart, i - tokenStart)); - ++num; - tokenStart = i + 1; - } + ++num; + tokenStart = i + 1; + } - if (c == 0) - break; + if (c == 0) + break; - ++i; - } - } + ++i; + } + } - return num; + return num; } int StringArray::addLines (const tchar* text) throw() { - int numLines = 0; + int numLines = 0; - if (text != 0) - { - while (*text != 0) - { - const tchar* const startOfLine = text; + if (text != 0) + { + while (*text != 0) + { + const tchar* const startOfLine = text; - while (*text != 0) - { - if (*text == T('\r')) - { - ++text; - if (*text == T('\n')) - ++text; + while (*text != 0) + { + if (*text == T('\r')) + { + ++text; + if (*text == T('\n')) + ++text; - break; - } + break; + } - if (*text == T('\n')) - { - ++text; - break; - } + if (*text == T('\n')) + { + ++text; + break; + } - ++text; - } + ++text; + } - const tchar* endOfLine = text; - if (endOfLine > startOfLine && (*(endOfLine - 1) == T('\r') || *(endOfLine - 1) == T('\n'))) - --endOfLine; + const tchar* endOfLine = text; + if (endOfLine > startOfLine && (*(endOfLine - 1) == T('\r') || *(endOfLine - 1) == T('\n'))) + --endOfLine; - if (endOfLine > startOfLine && (*(endOfLine - 1) == T('\r') || *(endOfLine - 1) == T('\n'))) - --endOfLine; + if (endOfLine > startOfLine && (*(endOfLine - 1) == T('\r') || *(endOfLine - 1) == T('\n'))) + --endOfLine; - add (String (startOfLine, jmax (0, (int) (endOfLine - startOfLine)))); + add (String (startOfLine, jmax (0, (int) (endOfLine - startOfLine)))); - ++numLines; - } - } + ++numLines; + } + } - return numLines; + return numLines; } void StringArray::removeDuplicates (const bool ignoreCase) throw() { - for (int i = 0; i < size() - 1; ++i) - { - const String& s = *strings.getUnchecked(i); + for (int i = 0; i < size() - 1; ++i) + { + const String& s = *strings.getUnchecked(i); - int nextIndex = i + 1; + int nextIndex = i + 1; - for (;;) - { - nextIndex = indexOf (s, ignoreCase, nextIndex); + for (;;) + { + nextIndex = indexOf (s, ignoreCase, nextIndex); - if (nextIndex < 0) - break; + if (nextIndex < 0) + break; - strings.remove (nextIndex); - } - } + strings.remove (nextIndex); + } + } } void StringArray::appendNumbersToDuplicates (const bool ignoreCase, - const bool appendNumberToFirstInstance, - const tchar* const preNumberString, - const tchar* const postNumberString) throw() + const bool appendNumberToFirstInstance, + const tchar* const preNumberString, + const tchar* const postNumberString) throw() { - for (int i = 0; i < size() - 1; ++i) - { - String& s = *strings.getUnchecked(i); + for (int i = 0; i < size() - 1; ++i) + { + String& s = *strings.getUnchecked(i); - int nextIndex = indexOf (s, ignoreCase, i + 1); + int nextIndex = indexOf (s, ignoreCase, i + 1); - if (nextIndex >= 0) - { - const String original (s); + if (nextIndex >= 0) + { + const String original (s); - int number = 0; + int number = 0; - if (appendNumberToFirstInstance) - s = original + preNumberString + String (++number) + postNumberString; - else - ++number; + if (appendNumberToFirstInstance) + s = original + preNumberString + String (++number) + postNumberString; + else + ++number; - while (nextIndex >= 0) - { - set (nextIndex, (*this)[nextIndex] + preNumberString + String (++number) + postNumberString); - nextIndex = indexOf (original, ignoreCase, nextIndex + 1); - } - } - } + while (nextIndex >= 0) + { + set (nextIndex, (*this)[nextIndex] + preNumberString + String (++number) + postNumberString); + nextIndex = indexOf (original, ignoreCase, nextIndex + 1); + } + } + } } void StringArray::minimiseStorageOverheads() throw() { - strings.minimiseStorageOverheads(); + strings.minimiseStorageOverheads(); } END_JUCE_NAMESPACE @@ -13268,14 +13031,14 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE StringPairArray::StringPairArray (const bool ignoreCase_) throw() - : ignoreCase (ignoreCase_) + : ignoreCase (ignoreCase_) { } StringPairArray::StringPairArray (const StringPairArray& other) throw() - : keys (other.keys), - values (other.values), - ignoreCase (other.ignoreCase) + : keys (other.keys), + values (other.values), + ignoreCase (other.ignoreCase) { } @@ -13285,103 +13048,103 @@ StringPairArray::~StringPairArray() throw() const StringPairArray& StringPairArray::operator= (const StringPairArray& other) throw() { - keys = other.keys; - values = other.values; + keys = other.keys; + values = other.values; - return *this; + return *this; } bool StringPairArray::operator== (const StringPairArray& other) const throw() { - for (int i = keys.size(); --i >= 0;) - if (other [keys[i]] != values[i]) - return false; + for (int i = keys.size(); --i >= 0;) + if (other [keys[i]] != values[i]) + return false; - return true; + return true; } bool StringPairArray::operator!= (const StringPairArray& other) const throw() { - return ! operator== (other); + return ! operator== (other); } const String& StringPairArray::operator[] (const String& key) const throw() { - return values [keys.indexOf (key, ignoreCase)]; + return values [keys.indexOf (key, ignoreCase)]; } const String StringPairArray::getValue (const String& key, const String& defaultReturnValue) const { - const int i = keys.indexOf (key, ignoreCase); + const int i = keys.indexOf (key, ignoreCase); - if (i >= 0) - return values[i]; + if (i >= 0) + return values[i]; - return defaultReturnValue; + return defaultReturnValue; } void StringPairArray::set (const String& key, - const String& value) throw() + const String& value) throw() { - const int i = keys.indexOf (key, ignoreCase); + const int i = keys.indexOf (key, ignoreCase); - if (i >= 0) - { - values.set (i, value); - } - else - { - keys.add (key); - values.add (value); - } + if (i >= 0) + { + values.set (i, value); + } + else + { + keys.add (key); + values.add (value); + } } void StringPairArray::addArray (const StringPairArray& other) { - for (int i = 0; i < other.size(); ++i) - set (other.keys[i], other.values[i]); + for (int i = 0; i < other.size(); ++i) + set (other.keys[i], other.values[i]); } void StringPairArray::clear() throw() { - keys.clear(); - values.clear(); + keys.clear(); + values.clear(); } void StringPairArray::remove (const String& key) throw() { - remove (keys.indexOf (key, ignoreCase)); + remove (keys.indexOf (key, ignoreCase)); } void StringPairArray::remove (const int index) throw() { - keys.remove (index); - values.remove (index); + keys.remove (index); + values.remove (index); } void StringPairArray::setIgnoresCase (const bool shouldIgnoreCase) throw() { - ignoreCase = shouldIgnoreCase; + ignoreCase = shouldIgnoreCase; } const String StringPairArray::getDescription() const { - String s; + String s; - for (int i = 0; i < keys.size(); ++i) - { - s << keys[i] << T(" = ") << values[i]; - if (i < keys.size()) - s << T(", "); - } + for (int i = 0; i < keys.size(); ++i) + { + s << keys[i] << T(" = ") << values[i]; + if (i < keys.size()) + s << T(", "); + } - return s; + return s; } void StringPairArray::minimiseStorageOverheads() throw() { - keys.minimiseStorageOverheads(); - values.minimiseStorageOverheads(); + keys.minimiseStorageOverheads(); + values.minimiseStorageOverheads(); } END_JUCE_NAMESPACE @@ -13392,14 +13155,14 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE XmlDocument::XmlDocument (const String& documentText) throw() - : originalText (documentText), - ignoreEmptyTextElements (true) + : originalText (documentText), + ignoreEmptyTextElements (true) { } XmlDocument::XmlDocument (const File& file) { - inputSource = new FileInputSource (file); + inputSource = new FileInputSource (file); } XmlDocument::~XmlDocument() throw() @@ -13408,853 +13171,853 @@ XmlDocument::~XmlDocument() throw() void XmlDocument::setInputSource (InputSource* const newSource) throw() { - inputSource = newSource; + inputSource = newSource; } void XmlDocument::setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw() { - ignoreEmptyTextElements = shouldBeIgnored; + ignoreEmptyTextElements = shouldBeIgnored; } bool XmlDocument::isXmlIdentifierCharSlow (const tchar c) throw() { - return CharacterFunctions::isLetterOrDigit (c) - || c == T('_') - || c == T('-') - || c == T(':') - || c == T('.'); + return CharacterFunctions::isLetterOrDigit (c) + || c == T('_') + || c == T('-') + || c == T(':') + || c == T('.'); } inline bool XmlDocument::isXmlIdentifierChar (const tchar c) const throw() { - return (c > 0 && c <= 127) ? identifierLookupTable [(int) c] - : isXmlIdentifierCharSlow (c); + return (c > 0 && c <= 127) ? identifierLookupTable [(int) c] + : isXmlIdentifierCharSlow (c); } XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentElement) { - String textToParse (originalText); + String textToParse (originalText); - if (textToParse.isEmpty() && inputSource != 0) - { - ScopedPointer in (inputSource->createInputStream()); + if (textToParse.isEmpty() && inputSource != 0) + { + ScopedPointer in (inputSource->createInputStream()); - if (in != 0) - { - MemoryBlock data; + if (in != 0) + { + MemoryBlock data; - in->readIntoMemoryBlock (data, onlyReadOuterDocumentElement ? 8192 : -1); + in->readIntoMemoryBlock (data, onlyReadOuterDocumentElement ? 8192 : -1); - if (data.getSize() >= 2 - && ((data[0] == (char)-2 && data[1] == (char)-1) - || (data[0] == (char)-1 && data[1] == (char)-2))) - { - textToParse = String::createStringFromData ((const char*) data.getData(), data.getSize()); - } - else - { - textToParse = String::fromUTF8 ((const uint8*) data.getData(), data.getSize()); - } + if (data.getSize() >= 2 + && ((data[0] == (char)-2 && data[1] == (char)-1) + || (data[0] == (char)-1 && data[1] == (char)-2))) + { + textToParse = String::createStringFromData ((const char*) data.getData(), (int) data.getSize()); + } + else + { + textToParse = String::fromUTF8 ((const uint8*) data.getData(), (int) data.getSize()); + } - if (! onlyReadOuterDocumentElement) - originalText = textToParse; - } - } + if (! onlyReadOuterDocumentElement) + originalText = textToParse; + } + } - input = textToParse; - lastError = String::empty; - errorOccurred = false; - outOfData = false; - needToLoadDTD = true; + input = textToParse; + lastError = String::empty; + errorOccurred = false; + outOfData = false; + needToLoadDTD = true; - for (int i = 0; i < 128; ++i) - identifierLookupTable[i] = isXmlIdentifierCharSlow ((tchar) i); + for (int i = 0; i < 128; ++i) + identifierLookupTable[i] = isXmlIdentifierCharSlow ((tchar) i); - if (textToParse.isEmpty()) - { - lastError = "not enough input"; - } - else - { - skipHeader(); + if (textToParse.isEmpty()) + { + lastError = "not enough input"; + } + else + { + skipHeader(); - if (input != 0) - { - ScopedPointer result (readNextElement (! onlyReadOuterDocumentElement)); + if (input != 0) + { + ScopedPointer result (readNextElement (! onlyReadOuterDocumentElement)); - if (! errorOccurred) - return result.release(); - } - else - { - lastError = "incorrect xml header"; - } - } + if (! errorOccurred) + return result.release(); + } + else + { + lastError = "incorrect xml header"; + } + } - return 0; + return 0; } const String& XmlDocument::getLastParseError() const throw() { - return lastError; + return lastError; } void XmlDocument::setLastError (const String& desc, const bool carryOn) throw() { - lastError = desc; - errorOccurred = ! carryOn; + lastError = desc; + errorOccurred = ! carryOn; } const String XmlDocument::getFileContents (const String& filename) const { - if (inputSource != 0) - { - const ScopedPointer in (inputSource->createInputStreamFor (filename.trim().unquoted())); + if (inputSource != 0) + { + const ScopedPointer in (inputSource->createInputStreamFor (filename.trim().unquoted())); - if (in != 0) - return in->readEntireStreamAsString(); - } + if (in != 0) + return in->readEntireStreamAsString(); + } - return String::empty; + return String::empty; } tchar XmlDocument::readNextChar() throw() { - if (*input != 0) - { - return *input++; - } - else - { - outOfData = true; - return 0; - } + if (*input != 0) + { + return *input++; + } + else + { + outOfData = true; + return 0; + } } int XmlDocument::findNextTokenLength() throw() { - int len = 0; - tchar c = *input; + int len = 0; + tchar c = *input; - while (isXmlIdentifierChar (c)) - c = input [++len]; + while (isXmlIdentifierChar (c)) + c = input [++len]; - return len; + return len; } void XmlDocument::skipHeader() throw() { - const tchar* const found = CharacterFunctions::find (input, T("")); + if (found != 0) + { + input = found; + input = CharacterFunctions::find (input, T("?>")); - if (input == 0) - return; + if (input == 0) + return; - input += 2; - } + input += 2; + } - skipNextWhiteSpace(); - const tchar* docType = CharacterFunctions::find (input, T(" 0) - { - const tchar c = readNextChar(); + while (n > 0) + { + const tchar c = readNextChar(); - if (outOfData) - return; + if (outOfData) + return; - if (c == T('<')) - ++n; - else if (c == T('>')) - --n; - } + if (c == T('<')) + ++n; + else if (c == T('>')) + --n; + } - docType += 9; - dtdText = String (docType, (int) (input - (docType + 1))).trim(); + docType += 9; + dtdText = String (docType, (int) (input - (docType + 1))).trim(); } void XmlDocument::skipNextWhiteSpace() throw() { - for (;;) - { - tchar c = *input; + for (;;) + { + tchar c = *input; - while (CharacterFunctions::isWhitespace (c)) - c = *++input; + while (CharacterFunctions::isWhitespace (c)) + c = *++input; - if (c == 0) - { - outOfData = true; - break; - } - else if (c == T('<')) - { - if (input[1] == T('!') - && input[2] == T('-') - && input[3] == T('-')) - { - const tchar* const closeComment = CharacterFunctions::find (input, T("-->")); + if (c == 0) + { + outOfData = true; + break; + } + else if (c == T('<')) + { + if (input[1] == T('!') + && input[2] == T('-') + && input[3] == T('-')) + { + const tchar* const closeComment = CharacterFunctions::find (input, T("-->")); - if (closeComment == 0) - { - outOfData = true; - break; - } + if (closeComment == 0) + { + outOfData = true; + break; + } - input = closeComment + 3; - continue; - } - else if (input[1] == T('?')) - { - const tchar* const closeBracket = CharacterFunctions::find (input, T("?>")); + input = closeComment + 3; + continue; + } + else if (input[1] == T('?')) + { + const tchar* const closeBracket = CharacterFunctions::find (input, T("?>")); - if (closeBracket == 0) - { - outOfData = true; - break; - } + if (closeBracket == 0) + { + outOfData = true; + break; + } - input = closeBracket + 2; - continue; - } - } + input = closeBracket + 2; + continue; + } + } - break; - } + break; + } } void XmlDocument::readQuotedString (String& result) throw() { - const tchar quote = readNextChar(); + const tchar quote = readNextChar(); - while (! outOfData) - { - const tchar c = readNextChar(); + while (! outOfData) + { + const tchar c = readNextChar(); - if (c == quote) - break; + if (c == quote) + break; - if (c == T('&')) - { - --input; - readEntity (result); - } - else - { - --input; - const tchar* const start = input; + if (c == T('&')) + { + --input; + readEntity (result); + } + else + { + --input; + const tchar* const start = input; - for (;;) - { - const tchar character = *input; + for (;;) + { + const tchar character = *input; - if (character == quote) - { - result.append (start, (int) (input - start)); - ++input; + if (character == quote) + { + result.append (start, (int) (input - start)); + ++input; - return; - } - else if (character == T('&')) - { - result.append (start, (int) (input - start)); - break; - } - else if (character == 0) - { - outOfData = true; - setLastError ("unmatched quotes", false); - break; - } + return; + } + else if (character == T('&')) + { + result.append (start, (int) (input - start)); + break; + } + else if (character == 0) + { + outOfData = true; + setLastError ("unmatched quotes", false); + break; + } - ++input; - } - } - } + ++input; + } + } + } } XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) throw() { - XmlElement* node = 0; + XmlElement* node = 0; - skipNextWhiteSpace(); - if (outOfData) - return 0; + skipNextWhiteSpace(); + if (outOfData) + return 0; - input = CharacterFunctions::find (input, T("<")); + input = CharacterFunctions::find (input, T("<")); - if (input != 0) - { - ++input; - int tagLen = findNextTokenLength(); + if (input != 0) + { + ++input; + int tagLen = findNextTokenLength(); - if (tagLen == 0) - { - // no tag name - but allow for a gap after the '<' before giving an error - skipNextWhiteSpace(); - tagLen = findNextTokenLength(); + if (tagLen == 0) + { + // no tag name - but allow for a gap after the '<' before giving an error + skipNextWhiteSpace(); + tagLen = findNextTokenLength(); - if (tagLen == 0) - { - setLastError ("tag name missing", false); - return node; - } - } + if (tagLen == 0) + { + setLastError ("tag name missing", false); + return node; + } + } - node = new XmlElement (input, tagLen); - input += tagLen; - XmlElement::XmlAttributeNode* lastAttribute = 0; + node = new XmlElement (input, tagLen); + input += tagLen; + XmlElement::XmlAttributeNode* lastAttribute = 0; - // look for attributes - for (;;) - { - skipNextWhiteSpace(); + // look for attributes + for (;;) + { + skipNextWhiteSpace(); - const tchar c = *input; + const tchar c = *input; - // empty tag.. - if (c == T('/') && input[1] == T('>')) - { - input += 2; - break; - } + // empty tag.. + if (c == T('/') && input[1] == T('>')) + { + input += 2; + break; + } - // parse the guts of the element.. - if (c == T('>')) - { - ++input; - skipNextWhiteSpace(); + // parse the guts of the element.. + if (c == T('>')) + { + ++input; + skipNextWhiteSpace(); - if (alsoParseSubElements) - readChildElements (node); + if (alsoParseSubElements) + readChildElements (node); - break; - } + break; + } - // get an attribute.. - if (isXmlIdentifierChar (c)) - { - const int attNameLen = findNextTokenLength(); + // get an attribute.. + if (isXmlIdentifierChar (c)) + { + const int attNameLen = findNextTokenLength(); - if (attNameLen > 0) - { - const tchar* attNameStart = input; - input += attNameLen; + if (attNameLen > 0) + { + const tchar* attNameStart = input; + input += attNameLen; - skipNextWhiteSpace(); + skipNextWhiteSpace(); - if (readNextChar() == T('=')) - { - skipNextWhiteSpace(); + if (readNextChar() == T('=')) + { + skipNextWhiteSpace(); - const tchar nextChar = *input; + const tchar nextChar = *input; - if (nextChar == T('"') || nextChar == T('\'')) - { - XmlElement::XmlAttributeNode* const newAtt - = new XmlElement::XmlAttributeNode (String (attNameStart, attNameLen), - String::empty); + if (nextChar == T('"') || nextChar == T('\'')) + { + XmlElement::XmlAttributeNode* const newAtt + = new XmlElement::XmlAttributeNode (String (attNameStart, attNameLen), + String::empty); - readQuotedString (newAtt->value); + readQuotedString (newAtt->value); - if (lastAttribute == 0) - node->attributes = newAtt; - else - lastAttribute->next = newAtt; + if (lastAttribute == 0) + node->attributes = newAtt; + else + lastAttribute->next = newAtt; - lastAttribute = newAtt; + lastAttribute = newAtt; - continue; - } - } - } - } - else - { - if (! outOfData) - setLastError ("illegal character found in " + node->getTagName() + ": '" + c + "'", false); - } + continue; + } + } + } + } + else + { + if (! outOfData) + setLastError ("illegal character found in " + node->getTagName() + ": '" + c + "'", false); + } - break; - } - } + break; + } + } - return node; + return node; } void XmlDocument::readChildElements (XmlElement* parent) throw() { - XmlElement* lastChildNode = 0; + XmlElement* lastChildNode = 0; - for (;;) - { - skipNextWhiteSpace(); + for (;;) + { + skipNextWhiteSpace(); - if (outOfData) - { - setLastError ("unmatched tags", false); - break; - } + if (outOfData) + { + setLastError ("unmatched tags", false); + break; + } - if (*input == T('<')) - { - if (input[1] == T('/')) - { - // our close tag.. - input = CharacterFunctions::find (input, T(">")); - ++input; - break; - } - else if (input[1] == T('!') - && input[2] == T('[') - && input[3] == T('C') - && input[4] == T('D') - && input[5] == T('A') - && input[6] == T('T') - && input[7] == T('A') - && input[8] == T('[')) - { - input += 9; - const tchar* const inputStart = input; + if (*input == T('<')) + { + if (input[1] == T('/')) + { + // our close tag.. + input = CharacterFunctions::find (input, T(">")); + ++input; + break; + } + else if (input[1] == T('!') + && input[2] == T('[') + && input[3] == T('C') + && input[4] == T('D') + && input[5] == T('A') + && input[6] == T('T') + && input[7] == T('A') + && input[8] == T('[')) + { + input += 9; + const tchar* const inputStart = input; - int len = 0; + int len = 0; - for (;;) - { - if (*input == 0) - { - setLastError ("unterminated CDATA section", false); - outOfData = true; - break; - } - else if (input[0] == T(']') - && input[1] == T(']') - && input[2] == T('>')) - { - input += 3; - break; - } + for (;;) + { + if (*input == 0) + { + setLastError ("unterminated CDATA section", false); + outOfData = true; + break; + } + else if (input[0] == T(']') + && input[1] == T(']') + && input[2] == T('>')) + { + input += 3; + break; + } - ++input; - ++len; - } + ++input; + ++len; + } - XmlElement* const e = new XmlElement ((int) 0); - e->setText (String (inputStart, len)); + XmlElement* const e = new XmlElement ((int) 0); + e->setText (String (inputStart, len)); - if (lastChildNode != 0) - lastChildNode->nextElement = e; - else - parent->addChildElement (e); + if (lastChildNode != 0) + lastChildNode->nextElement = e; + else + parent->addChildElement (e); - lastChildNode = e; - } - else - { - // this is some other element, so parse and add it.. - XmlElement* const n = readNextElement (true); + lastChildNode = e; + } + else + { + // this is some other element, so parse and add it.. + XmlElement* const n = readNextElement (true); - if (n != 0) - { - if (lastChildNode == 0) - parent->addChildElement (n); - else - lastChildNode->nextElement = n; + if (n != 0) + { + if (lastChildNode == 0) + parent->addChildElement (n); + else + lastChildNode->nextElement = n; - lastChildNode = n; - } - else - { - return; - } - } - } - else - { - // read character block.. - XmlElement* const e = new XmlElement ((int)0); + lastChildNode = n; + } + else + { + return; + } + } + } + else + { + // read character block.. + XmlElement* const e = new XmlElement ((int)0); - if (lastChildNode != 0) - lastChildNode->nextElement = e; - else - parent->addChildElement (e); + if (lastChildNode != 0) + lastChildNode->nextElement = e; + else + parent->addChildElement (e); - lastChildNode = e; + lastChildNode = e; - String textElementContent; + String textElementContent; - for (;;) - { - const tchar c = *input; + for (;;) + { + const tchar c = *input; - if (c == T('<')) - break; + if (c == T('<')) + break; - if (c == 0) - { - setLastError ("unmatched tags", false); - outOfData = true; - return; - } + if (c == 0) + { + setLastError ("unmatched tags", false); + outOfData = true; + return; + } - if (c == T('&')) - { - String entity; - readEntity (entity); + if (c == T('&')) + { + String entity; + readEntity (entity); - if (entity.startsWithChar (T('<')) && entity [1] != 0) - { - const tchar* const oldInput = input; - const bool oldOutOfData = outOfData; + if (entity.startsWithChar (T('<')) && entity [1] != 0) + { + const tchar* const oldInput = input; + const bool oldOutOfData = outOfData; - input = (const tchar*) entity; - outOfData = false; + input = (const tchar*) entity; + outOfData = false; - for (;;) - { - XmlElement* const n = readNextElement (true); + for (;;) + { + XmlElement* const n = readNextElement (true); - if (n == 0) - break; + if (n == 0) + break; - if (lastChildNode == 0) - parent->addChildElement (n); - else - lastChildNode->nextElement = n; + if (lastChildNode == 0) + parent->addChildElement (n); + else + lastChildNode->nextElement = n; - lastChildNode = n; - } + lastChildNode = n; + } - input = oldInput; - outOfData = oldOutOfData; - } - else - { - textElementContent += entity; - } - } - else - { - const tchar* start = input; - int len = 0; + input = oldInput; + outOfData = oldOutOfData; + } + else + { + textElementContent += entity; + } + } + else + { + const tchar* start = input; + int len = 0; - for (;;) - { - const tchar nextChar = *input; + for (;;) + { + const tchar nextChar = *input; - if (nextChar == T('<') || nextChar == T('&')) - { - break; - } - else if (nextChar == 0) - { - setLastError ("unmatched tags", false); - outOfData = true; - return; - } + if (nextChar == T('<') || nextChar == T('&')) + { + break; + } + else if (nextChar == 0) + { + setLastError ("unmatched tags", false); + outOfData = true; + return; + } - ++input; - ++len; - } + ++input; + ++len; + } - textElementContent.append (start, len); - } - } + textElementContent.append (start, len); + } + } - if (ignoreEmptyTextElements ? textElementContent.containsNonWhitespaceChars() - : textElementContent.isNotEmpty()) - e->setText (textElementContent); - } - } + if (ignoreEmptyTextElements ? textElementContent.containsNonWhitespaceChars() + : textElementContent.isNotEmpty()) + e->setText (textElementContent); + } + } } void XmlDocument::readEntity (String& result) throw() { - // skip over the ampersand - ++input; + // skip over the ampersand + ++input; - if (CharacterFunctions::compareIgnoreCase (input, T("amp;"), 4) == 0) - { - input += 4; - result += T("&"); - } - else if (CharacterFunctions::compareIgnoreCase (input, T("quot;"), 5) == 0) - { - input += 5; - result += T("\""); - } - else if (CharacterFunctions::compareIgnoreCase (input, T("apos;"), 5) == 0) - { - input += 5; - result += T("\'"); - } - else if (CharacterFunctions::compareIgnoreCase (input, T("lt;"), 3) == 0) - { - input += 3; - result += T("<"); - } - else if (CharacterFunctions::compareIgnoreCase (input, T("gt;"), 3) == 0) - { - input += 3; - result += T(">"); - } - else if (*input == T('#')) - { - int charCode = 0; - ++input; + if (CharacterFunctions::compareIgnoreCase (input, T("amp;"), 4) == 0) + { + input += 4; + result += T("&"); + } + else if (CharacterFunctions::compareIgnoreCase (input, T("quot;"), 5) == 0) + { + input += 5; + result += T("\""); + } + else if (CharacterFunctions::compareIgnoreCase (input, T("apos;"), 5) == 0) + { + input += 5; + result += T("\'"); + } + else if (CharacterFunctions::compareIgnoreCase (input, T("lt;"), 3) == 0) + { + input += 3; + result += T("<"); + } + else if (CharacterFunctions::compareIgnoreCase (input, T("gt;"), 3) == 0) + { + input += 3; + result += T(">"); + } + else if (*input == T('#')) + { + int charCode = 0; + ++input; - if (*input == T('x') || *input == T('X')) - { - ++input; - int numChars = 0; + if (*input == T('x') || *input == T('X')) + { + ++input; + int numChars = 0; - while (input[0] != T(';')) - { - const int hexValue = CharacterFunctions::getHexDigitValue (input[0]); + while (input[0] != T(';')) + { + const int hexValue = CharacterFunctions::getHexDigitValue (input[0]); - if (hexValue < 0 || ++numChars > 8) - { - setLastError ("illegal escape sequence", true); - break; - } + if (hexValue < 0 || ++numChars > 8) + { + setLastError ("illegal escape sequence", true); + break; + } - charCode = (charCode << 4) | hexValue; - ++input; - } + charCode = (charCode << 4) | hexValue; + ++input; + } - ++input; - } - else if (input[0] >= T('0') && input[0] <= T('9')) - { - int numChars = 0; + ++input; + } + else if (input[0] >= T('0') && input[0] <= T('9')) + { + int numChars = 0; - while (input[0] != T(';')) - { - if (++numChars > 12) - { - setLastError ("illegal escape sequence", true); - break; - } + while (input[0] != T(';')) + { + if (++numChars > 12) + { + setLastError ("illegal escape sequence", true); + break; + } - charCode = charCode * 10 + (input[0] - T('0')); - ++input; - } + charCode = charCode * 10 + (input[0] - T('0')); + ++input; + } - ++input; - } - else - { - setLastError ("illegal escape sequence", true); - result += T("&"); - return; - } + ++input; + } + else + { + setLastError ("illegal escape sequence", true); + result += T("&"); + return; + } - result << (tchar) charCode; - } - else - { - const tchar* const entityNameStart = input; - const tchar* const closingSemiColon = CharacterFunctions::find (input, T(";")); + result << (tchar) charCode; + } + else + { + const tchar* const entityNameStart = input; + const tchar* const closingSemiColon = CharacterFunctions::find (input, T(";")); - if (closingSemiColon == 0) - { - outOfData = true; - result += T("&"); - } - else - { - input = closingSemiColon + 1; + if (closingSemiColon == 0) + { + outOfData = true; + result += T("&"); + } + else + { + input = closingSemiColon + 1; - result += expandExternalEntity (String (entityNameStart, - (int) (closingSemiColon - entityNameStart))); - } - } + result += expandExternalEntity (String (entityNameStart, + (int) (closingSemiColon - entityNameStart))); + } + } } const String XmlDocument::expandEntity (const String& ent) { - if (ent.equalsIgnoreCase (T("amp"))) - { - return T("&"); - } - else if (ent.equalsIgnoreCase (T("quot"))) - { - return T("\""); - } - else if (ent.equalsIgnoreCase (T("apos"))) - { - return T("\'"); - } - else if (ent.equalsIgnoreCase (T("lt"))) - { - return T("<"); - } - else if (ent.equalsIgnoreCase (T("gt"))) - { - return T(">"); - } - else if (ent[0] == T('#')) - { - if (ent[1] == T('x') || ent[1] == T('X')) - { - return String::charToString ((tchar) ent.substring (2).getHexValue32()); - } - else if (ent[1] >= T('0') && ent[1] <= T('9')) - { - return String::charToString ((tchar) ent.substring (1).getIntValue()); - } + if (ent.equalsIgnoreCase (T("amp"))) + { + return T("&"); + } + else if (ent.equalsIgnoreCase (T("quot"))) + { + return T("\""); + } + else if (ent.equalsIgnoreCase (T("apos"))) + { + return T("\'"); + } + else if (ent.equalsIgnoreCase (T("lt"))) + { + return T("<"); + } + else if (ent.equalsIgnoreCase (T("gt"))) + { + return T(">"); + } + else if (ent[0] == T('#')) + { + if (ent[1] == T('x') || ent[1] == T('X')) + { + return String::charToString ((tchar) ent.substring (2).getHexValue32()); + } + else if (ent[1] >= T('0') && ent[1] <= T('9')) + { + return String::charToString ((tchar) ent.substring (1).getIntValue()); + } - setLastError ("illegal escape sequence", false); - return T("&"); - } - else - { - return expandExternalEntity (ent); - } + setLastError ("illegal escape sequence", false); + return T("&"); + } + else + { + return expandExternalEntity (ent); + } } const String XmlDocument::expandExternalEntity (const String& entity) { - if (needToLoadDTD) - { - if (dtdText.isNotEmpty()) - { - while (dtdText.endsWithChar (T('>'))) - dtdText = dtdText.dropLastCharacters (1); + if (needToLoadDTD) + { + if (dtdText.isNotEmpty()) + { + while (dtdText.endsWithChar (T('>'))) + dtdText = dtdText.dropLastCharacters (1); - tokenisedDTD.addTokens (dtdText, true); + tokenisedDTD.addTokens (dtdText, true); - if (tokenisedDTD [tokenisedDTD.size() - 2].equalsIgnoreCase (T("system")) - && tokenisedDTD [tokenisedDTD.size() - 1].isQuotedString()) - { - const String fn (tokenisedDTD [tokenisedDTD.size() - 1]); + if (tokenisedDTD [tokenisedDTD.size() - 2].equalsIgnoreCase (T("system")) + && tokenisedDTD [tokenisedDTD.size() - 1].isQuotedString()) + { + const String fn (tokenisedDTD [tokenisedDTD.size() - 1]); - tokenisedDTD.clear(); - tokenisedDTD.addTokens (getFileContents (fn), true); - } - else - { - tokenisedDTD.clear(); - const int openBracket = dtdText.indexOfChar (T('[')); + tokenisedDTD.clear(); + tokenisedDTD.addTokens (getFileContents (fn), true); + } + else + { + tokenisedDTD.clear(); + const int openBracket = dtdText.indexOfChar (T('[')); - if (openBracket > 0) - { - const int closeBracket = dtdText.lastIndexOfChar (T(']')); + if (openBracket > 0) + { + const int closeBracket = dtdText.lastIndexOfChar (T(']')); - if (closeBracket > openBracket) - tokenisedDTD.addTokens (dtdText.substring (openBracket + 1, - closeBracket), true); - } - } + if (closeBracket > openBracket) + tokenisedDTD.addTokens (dtdText.substring (openBracket + 1, + closeBracket), true); + } + } - for (int i = tokenisedDTD.size(); --i >= 0;) - { - if (tokenisedDTD[i].startsWithChar (T('%')) - && tokenisedDTD[i].endsWithChar (T(';'))) - { - const String parsed (getParameterEntity (tokenisedDTD[i].substring (1, tokenisedDTD[i].length() - 1))); - StringArray newToks; - newToks.addTokens (parsed, true); + for (int i = tokenisedDTD.size(); --i >= 0;) + { + if (tokenisedDTD[i].startsWithChar (T('%')) + && tokenisedDTD[i].endsWithChar (T(';'))) + { + const String parsed (getParameterEntity (tokenisedDTD[i].substring (1, tokenisedDTD[i].length() - 1))); + StringArray newToks; + newToks.addTokens (parsed, true); - tokenisedDTD.remove (i); + tokenisedDTD.remove (i); - for (int j = newToks.size(); --j >= 0;) - tokenisedDTD.insert (i, newToks[j]); - } - } - } + for (int j = newToks.size(); --j >= 0;) + tokenisedDTD.insert (i, newToks[j]); + } + } + } - needToLoadDTD = false; - } + needToLoadDTD = false; + } - for (int i = 0; i < tokenisedDTD.size(); ++i) - { - if (tokenisedDTD[i] == entity) - { - if (tokenisedDTD[i - 1].equalsIgnoreCase (T("'))) - ent = ent.dropLastCharacters (1); + while (ent.endsWithChar (T('>'))) + ent = ent.dropLastCharacters (1); - ent = ent.trim().unquoted(); + ent = ent.trim().unquoted(); - // check for sub-entities.. - int ampersand = ent.indexOfChar (T('&')); + // check for sub-entities.. + int ampersand = ent.indexOfChar (T('&')); - while (ampersand >= 0) - { - const int semiColon = ent.indexOf (i + 1, T(";")); + while (ampersand >= 0) + { + const int semiColon = ent.indexOf (i + 1, T(";")); - if (semiColon < 0) - { - setLastError ("entity without terminating semi-colon", false); - break; - } + if (semiColon < 0) + { + setLastError ("entity without terminating semi-colon", false); + break; + } - const String resolved (expandEntity (ent.substring (i + 1, semiColon))); + const String resolved (expandEntity (ent.substring (i + 1, semiColon))); - ent = ent.substring (0, ampersand) - + resolved - + ent.substring (semiColon + 1); + ent = ent.substring (0, ampersand) + + resolved + + ent.substring (semiColon + 1); - ampersand = ent.indexOfChar (semiColon + 1, T('&')); - } + ampersand = ent.indexOfChar (semiColon + 1, T('&')); + } - return ent; - } - } - } + return ent; + } + } + } - setLastError ("unknown entity", true); + setLastError ("unknown entity", true); - return entity; + return entity; } const String XmlDocument::getParameterEntity (const String& entity) { - for (int i = 0; i < tokenisedDTD.size(); ++i) - { - if (tokenisedDTD[i] == entity) - { - if (tokenisedDTD [i - 1] == T("%") - && tokenisedDTD [i - 2].equalsIgnoreCase (T("'))) - ent = ent.dropLastCharacters (1); + while (ent.endsWithChar (T('>'))) + ent = ent.dropLastCharacters (1); - if (ent.equalsIgnoreCase (T("system"))) - { - String filename (tokenisedDTD [i + 2]); + if (ent.equalsIgnoreCase (T("system"))) + { + String filename (tokenisedDTD [i + 2]); - while (filename.endsWithChar (T('>'))) - filename = filename.dropLastCharacters (1); + while (filename.endsWithChar (T('>'))) + filename = filename.dropLastCharacters (1); - return getFileContents (filename); - } - else - { - return ent.trim().unquoted(); - } - } - } - } + return getFileContents (filename); + } + else + { + return ent.trim().unquoted(); + } + } + } + } - return entity; + return entity; } END_JUCE_NAMESPACE @@ -14265,1140 +14028,1137 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE XmlElement::XmlAttributeNode::XmlAttributeNode (const XmlAttributeNode& other) throw() - : name (other.name), - value (other.value), - next (0) + : name (other.name), + value (other.value), + next (0) { } XmlElement::XmlAttributeNode::XmlAttributeNode (const String& name_, - const String& value_) throw() - : name (name_), - value (value_), - next (0) + const String& value_) throw() + : name (name_), + value (value_), + next (0) { } XmlElement::XmlElement (const String& tagName_) throw() - : tagName (tagName_), - firstChildElement (0), - nextElement (0), - attributes (0) + : tagName (tagName_), + firstChildElement (0), + nextElement (0), + attributes (0) { - // the tag name mustn't be empty, or it'll look like a text element! - jassert (tagName_.containsNonWhitespaceChars()) + // the tag name mustn't be empty, or it'll look like a text element! + jassert (tagName_.containsNonWhitespaceChars()) } XmlElement::XmlElement (int /*dummy*/) throw() - : firstChildElement (0), - nextElement (0), - attributes (0) + : firstChildElement (0), + nextElement (0), + attributes (0) { } XmlElement::XmlElement (const tchar* const tagName_, - const int nameLen) throw() - : tagName (tagName_, nameLen), - firstChildElement (0), - nextElement (0), - attributes (0) + const int nameLen) throw() + : tagName (tagName_, nameLen), + firstChildElement (0), + nextElement (0), + attributes (0) { } XmlElement::XmlElement (const XmlElement& other) throw() - : tagName (other.tagName), - firstChildElement (0), - nextElement (0), - attributes (0) + : tagName (other.tagName), + firstChildElement (0), + nextElement (0), + attributes (0) { - copyChildrenAndAttributesFrom (other); + copyChildrenAndAttributesFrom (other); } const XmlElement& XmlElement::operator= (const XmlElement& other) throw() { - if (this != &other) - { - removeAllAttributes(); - deleteAllChildElements(); + if (this != &other) + { + removeAllAttributes(); + deleteAllChildElements(); - tagName = other.tagName; + tagName = other.tagName; - copyChildrenAndAttributesFrom (other); - } + copyChildrenAndAttributesFrom (other); + } - return *this; + return *this; } void XmlElement::copyChildrenAndAttributesFrom (const XmlElement& other) throw() { - XmlElement* child = other.firstChildElement; - XmlElement* lastChild = 0; + XmlElement* child = other.firstChildElement; + XmlElement* lastChild = 0; - while (child != 0) - { - XmlElement* const copiedChild = new XmlElement (*child); + while (child != 0) + { + XmlElement* const copiedChild = new XmlElement (*child); - if (lastChild != 0) - lastChild->nextElement = copiedChild; - else - firstChildElement = copiedChild; + if (lastChild != 0) + lastChild->nextElement = copiedChild; + else + firstChildElement = copiedChild; - lastChild = copiedChild; - child = child->nextElement; - } + lastChild = copiedChild; + child = child->nextElement; + } - const XmlAttributeNode* att = other.attributes; - XmlAttributeNode* lastAtt = 0; + const XmlAttributeNode* att = other.attributes; + XmlAttributeNode* lastAtt = 0; - while (att != 0) - { - XmlAttributeNode* const newAtt = new XmlAttributeNode (*att); + while (att != 0) + { + XmlAttributeNode* const newAtt = new XmlAttributeNode (*att); - if (lastAtt != 0) - lastAtt->next = newAtt; - else - attributes = newAtt; + if (lastAtt != 0) + lastAtt->next = newAtt; + else + attributes = newAtt; - lastAtt = newAtt; - att = att->next; - } + lastAtt = newAtt; + att = att->next; + } } XmlElement::~XmlElement() throw() { - XmlElement* child = firstChildElement; + XmlElement* child = firstChildElement; - while (child != 0) - { - XmlElement* const nextChild = child->nextElement; - delete child; - child = nextChild; - } + while (child != 0) + { + XmlElement* const nextChild = child->nextElement; + delete child; + child = nextChild; + } - XmlAttributeNode* att = attributes; + XmlAttributeNode* att = attributes; - while (att != 0) - { - XmlAttributeNode* const nextAtt = att->next; - delete att; - att = nextAtt; - } + while (att != 0) + { + XmlAttributeNode* const nextAtt = att->next; + delete att; + att = nextAtt; + } } static bool isLegalXmlChar (const juce_wchar character) { - if ((character >= 'a' && character <= 'z') - || (character >= 'A' && character <= 'Z') - || (character >= '0' && character <= '9')) - return true; + if ((character >= 'a' && character <= 'z') + || (character >= 'A' && character <= 'Z') + || (character >= '0' && character <= '9')) + return true; - const char* t = " .,;:-()_+=?!'#@[]/\\*%~{}"; + const char* t = " .,;:-()_+=?!'#@[]/\\*%~{}"; - do - { - if (((juce_wchar) (uint8) *t) == character) - return true; - } - while (*++t != 0); + do + { + if (((juce_wchar) (uint8) *t) == character) + return true; + } + while (*++t != 0); - return false; + return false; } static void escapeIllegalXmlChars (OutputStream& outputStream, - const String& text, - const bool changeNewLines) throw() + const String& text, + const bool changeNewLines) throw() { - const juce_wchar* t = (const juce_wchar*) text; + const juce_wchar* t = (const juce_wchar*) text; - for (;;) - { - const juce_wchar character = *t++; + for (;;) + { + const juce_wchar character = *t++; - if (character == 0) - { - break; - } - else if (isLegalXmlChar (character)) - { - outputStream.writeByte ((char) character); - } - else - { - switch (character) - { - case '&': - outputStream.write ("&", 5); - break; + if (character == 0) + { + break; + } + else if (isLegalXmlChar (character)) + { + outputStream.writeByte ((char) character); + } + else + { + switch (character) + { + case '&': + outputStream.write ("&", 5); + break; - case '"': - outputStream.write (""", 6); - break; + case '"': + outputStream.write (""", 6); + break; - case '>': - outputStream.write (">", 4); - break; + case '>': + outputStream.write (">", 4); + break; - case '<': - outputStream.write ("<", 4); - break; + case '<': + outputStream.write ("<", 4); + break; - case '\n': - if (changeNewLines) - outputStream.write (" ", 5); - else - outputStream.writeByte ((char) character); + case '\n': + if (changeNewLines) + outputStream.write (" ", 5); + else + outputStream.writeByte ((char) character); - break; + break; - case '\r': - if (changeNewLines) - outputStream.write (" ", 5); - else - outputStream.writeByte ((char) character); + case '\r': + if (changeNewLines) + outputStream.write (" ", 5); + else + outputStream.writeByte ((char) character); - break; + break; - default: - { - String encoded (T("&#")); - encoded << String ((int) (unsigned int) character).trim() - << T(';'); + default: + { + String encoded (T("&#")); + encoded << String ((int) (unsigned int) character).trim() + << T(';'); - outputStream.write ((const char*) encoded, encoded.length()); - } - } - } - } + outputStream.write ((const char*) encoded, encoded.length()); + } + } + } + } } static void writeSpaces (OutputStream& out, int numSpaces) throw() { - if (numSpaces > 0) - { - const char* const blanks = " "; - const int blankSize = (int) sizeof (blanks) - 1; + if (numSpaces > 0) + { + const char* const blanks = " "; + const int blankSize = (int) sizeof (blanks) - 1; - while (numSpaces > blankSize) - { - out.write (blanks, blankSize); - numSpaces -= blankSize; - } + while (numSpaces > blankSize) + { + out.write (blanks, blankSize); + numSpaces -= blankSize; + } - out.write (blanks, numSpaces); - } + out.write (blanks, numSpaces); + } } void XmlElement::writeElementAsText (OutputStream& outputStream, - const int indentationLevel, - const int lineWrapLength) const throw() + const int indentationLevel, + const int lineWrapLength) const throw() { - writeSpaces (outputStream, indentationLevel); + writeSpaces (outputStream, indentationLevel); - if (! isTextElement()) - { - outputStream.writeByte ('<'); - const int nameLen = tagName.length(); - outputStream.write ((const char*) tagName, nameLen); + if (! isTextElement()) + { + outputStream.writeByte ('<'); + const int nameLen = tagName.length(); + outputStream.write ((const char*) tagName, nameLen); - const int attIndent = indentationLevel + nameLen + 1; - int lineLen = 0; + const int attIndent = indentationLevel + nameLen + 1; + int lineLen = 0; - const XmlAttributeNode* att = attributes; - while (att != 0) - { - if (lineLen > lineWrapLength && indentationLevel >= 0) - { - outputStream.write ("\r\n", 2); - writeSpaces (outputStream, attIndent); - lineLen = 0; - } + const XmlAttributeNode* att = attributes; + while (att != 0) + { + if (lineLen > lineWrapLength && indentationLevel >= 0) + { + outputStream.write ("\r\n", 2); + writeSpaces (outputStream, attIndent); + lineLen = 0; + } - const int attNameLen = att->name.length(); - outputStream.writeByte (' '); - outputStream.write ((const char*) (att->name), attNameLen); - outputStream.write ("=\"", 2); - escapeIllegalXmlChars (outputStream, att->value, true); - outputStream.writeByte ('"'); - lineLen += 4 + attNameLen + att->value.length(); + const int attNameLen = att->name.length(); + outputStream.writeByte (' '); + outputStream.write ((const char*) (att->name), attNameLen); + outputStream.write ("=\"", 2); + escapeIllegalXmlChars (outputStream, att->value, true); + outputStream.writeByte ('"'); + lineLen += 4 + attNameLen + att->value.length(); - att = att->next; - } + att = att->next; + } - if (firstChildElement != 0) - { - XmlElement* child = firstChildElement; + if (firstChildElement != 0) + { + XmlElement* child = firstChildElement; - if (child->nextElement == 0 && child->isTextElement()) - { - outputStream.writeByte ('>'); - escapeIllegalXmlChars (outputStream, child->getText(), false); - } - else - { - if (indentationLevel >= 0) - outputStream.write (">\r\n", 3); - else - outputStream.writeByte ('>'); + if (child->nextElement == 0 && child->isTextElement()) + { + outputStream.writeByte ('>'); + escapeIllegalXmlChars (outputStream, child->getText(), false); + } + else + { + if (indentationLevel >= 0) + outputStream.write (">\r\n", 3); + else + outputStream.writeByte ('>'); - bool lastWasTextNode = false; + bool lastWasTextNode = false; - while (child != 0) - { - if (child->isTextElement()) - { - if ((! lastWasTextNode) && (indentationLevel >= 0)) - writeSpaces (outputStream, indentationLevel + 2); + while (child != 0) + { + if (child->isTextElement()) + { + if ((! lastWasTextNode) && (indentationLevel >= 0)) + writeSpaces (outputStream, indentationLevel + 2); - escapeIllegalXmlChars (outputStream, child->getText(), false); - lastWasTextNode = true; - } - else - { - if (indentationLevel >= 0) - { - if (lastWasTextNode) - outputStream.write ("\r\n", 2); + escapeIllegalXmlChars (outputStream, child->getText(), false); + lastWasTextNode = true; + } + else + { + if (indentationLevel >= 0) + { + if (lastWasTextNode) + outputStream.write ("\r\n", 2); - child->writeElementAsText (outputStream, indentationLevel + 2, lineWrapLength); - } - else - { - child->writeElementAsText (outputStream, indentationLevel, lineWrapLength); - } + child->writeElementAsText (outputStream, indentationLevel + 2, lineWrapLength); + } + else + { + child->writeElementAsText (outputStream, indentationLevel, lineWrapLength); + } - lastWasTextNode = false; - } + lastWasTextNode = false; + } - child = child->nextElement; - } + child = child->nextElement; + } - if (indentationLevel >= 0) - { - if (lastWasTextNode) - outputStream.write ("\r\n", 2); + if (indentationLevel >= 0) + { + if (lastWasTextNode) + outputStream.write ("\r\n", 2); - writeSpaces (outputStream, indentationLevel); - } - } + writeSpaces (outputStream, indentationLevel); + } + } - outputStream.write ("= 0) - outputStream.write (">\r\n", 3); - else - outputStream.writeByte ('>'); - } - else - { - if (indentationLevel >= 0) - outputStream.write ("/>\r\n", 4); - else - outputStream.write ("/>", 2); - } - } - else - { - if (indentationLevel >= 0) - writeSpaces (outputStream, indentationLevel + 2); + if (indentationLevel >= 0) + outputStream.write (">\r\n", 3); + else + outputStream.writeByte ('>'); + } + else + { + if (indentationLevel >= 0) + outputStream.write ("/>\r\n", 4); + else + outputStream.write ("/>", 2); + } + } + else + { + if (indentationLevel >= 0) + writeSpaces (outputStream, indentationLevel + 2); - escapeIllegalXmlChars (outputStream, getText(), false); - } + escapeIllegalXmlChars (outputStream, getText(), false); + } } const String XmlElement::createDocument (const String& dtdToUse, - const bool allOnOneLine, - const bool includeXmlHeader, - const tchar* const encodingType, - const int lineWrapLength) const throw() + const bool allOnOneLine, + const bool includeXmlHeader, + const tchar* const encodingType, + const int lineWrapLength) const throw() { - MemoryOutputStream mem (2048, 4096); - writeToStream (mem, dtdToUse, allOnOneLine, includeXmlHeader, encodingType, lineWrapLength); + MemoryOutputStream mem (2048, 4096); + writeToStream (mem, dtdToUse, allOnOneLine, includeXmlHeader, encodingType, lineWrapLength); - return String (mem.getData(), mem.getDataSize()); + return String (mem.getData(), mem.getDataSize()); } void XmlElement::writeToStream (OutputStream& output, - const String& dtdToUse, - const bool allOnOneLine, - const bool includeXmlHeader, - const tchar* const encodingType, - const int lineWrapLength) const throw() + const String& dtdToUse, + const bool allOnOneLine, + const bool includeXmlHeader, + const tchar* const encodingType, + const int lineWrapLength) const throw() { - if (includeXmlHeader) - { - output << " "; - else - output << "\"?>\r\n\r\n"; - } + if (allOnOneLine) + output << "\"?> "; + else + output << "\"?>\r\n\r\n"; + } - if (dtdToUse.isNotEmpty()) - { - output << dtdToUse; + if (dtdToUse.isNotEmpty()) + { + output << dtdToUse; - if (allOnOneLine) - output << " "; - else - output << "\r\n"; - } + if (allOnOneLine) + output << " "; + else + output << "\r\n"; + } - writeElementAsText (output, allOnOneLine ? -1 : 0, lineWrapLength); + writeElementAsText (output, allOnOneLine ? -1 : 0, lineWrapLength); } bool XmlElement::writeToFile (const File& file, - const String& dtdToUse, - const tchar* const encodingType, - const int lineWrapLength) const throw() + const String& dtdToUse, + const tchar* const encodingType, + const int lineWrapLength) const throw() { - if (file.hasWriteAccess()) - { - const File tempFile (file.getNonexistentSibling()); + if (file.hasWriteAccess()) + { + const File tempFile (file.getNonexistentSibling()); - ScopedPointer out (tempFile.createOutputStream()); + ScopedPointer out (tempFile.createOutputStream()); - if (out != 0) - { - writeToStream (*out, dtdToUse, false, true, encodingType, lineWrapLength); - out = 0; + if (out != 0) + { + writeToStream (*out, dtdToUse, false, true, encodingType, lineWrapLength); + out = 0; - if (! tempFile.exists()) - return false; + if (! tempFile.exists()) + return false; - int i; - for (i = 5; --i >= 0;) - { - if (tempFile.moveFileTo (file)) - return true; + int i; + for (i = 5; --i >= 0;) + { + if (tempFile.moveFileTo (file)) + return true; - Thread::sleep (100); - } + Thread::sleep (100); + } - for (i = 5; --i >= 0;) - { - if (tempFile.deleteFile()) - break; + for (i = 5; --i >= 0;) + { + if (tempFile.deleteFile()) + break; - Thread::sleep (100); - } - } - } + Thread::sleep (100); + } + } + } - return false; + return false; } bool XmlElement::hasTagName (const tchar* const tagNameWanted) const throw() { #ifdef JUCE_DEBUG - // if debugging, check that the case is actually the same, because - // valid xml is case-sensitive, and although this lets it pass, it's - // better not to.. - if (tagName.equalsIgnoreCase (tagNameWanted)) - { - jassert (tagName == tagNameWanted); - return true; - } - else - { - return false; - } + // if debugging, check that the case is actually the same, because + // valid xml is case-sensitive, and although this lets it pass, it's + // better not to.. + if (tagName.equalsIgnoreCase (tagNameWanted)) + { + jassert (tagName == tagNameWanted); + return true; + } + else + { + return false; + } #else - return tagName.equalsIgnoreCase (tagNameWanted); + return tagName.equalsIgnoreCase (tagNameWanted); #endif } XmlElement* XmlElement::getNextElementWithTagName (const tchar* const requiredTagName) const { - XmlElement* e = nextElement; + XmlElement* e = nextElement; - while (e != 0 && ! e->hasTagName (requiredTagName)) - e = e->nextElement; + while (e != 0 && ! e->hasTagName (requiredTagName)) + e = e->nextElement; - return e; + return e; } int XmlElement::getNumAttributes() const throw() { - const XmlAttributeNode* att = attributes; - int count = 0; + const XmlAttributeNode* att = attributes; + int count = 0; - while (att != 0) - { - att = att->next; - ++count; - } + while (att != 0) + { + att = att->next; + ++count; + } - return count; + return count; } const String& XmlElement::getAttributeName (const int index) const throw() { - const XmlAttributeNode* att = attributes; - int count = 0; + const XmlAttributeNode* att = attributes; + int count = 0; - while (att != 0) - { - if (count == index) - return att->name; + while (att != 0) + { + if (count == index) + return att->name; - att = att->next; - ++count; - } + att = att->next; + ++count; + } - return String::empty; + return String::empty; } const String& XmlElement::getAttributeValue (const int index) const throw() { - const XmlAttributeNode* att = attributes; - int count = 0; + const XmlAttributeNode* att = attributes; + int count = 0; - while (att != 0) - { - if (count == index) - return att->value; + while (att != 0) + { + if (count == index) + return att->value; - att = att->next; - ++count; - } + att = att->next; + ++count; + } - return String::empty; + return String::empty; } bool XmlElement::hasAttribute (const tchar* const attributeName) const throw() { - const XmlAttributeNode* att = attributes; + const XmlAttributeNode* att = attributes; - while (att != 0) - { - if (att->name.equalsIgnoreCase (attributeName)) - return true; + while (att != 0) + { + if (att->name.equalsIgnoreCase (attributeName)) + return true; - att = att->next; - } + att = att->next; + } - return false; + return false; } const String XmlElement::getStringAttribute (const tchar* const attributeName, - const tchar* const defaultReturnValue) const throw() + const tchar* const defaultReturnValue) const throw() { - const XmlAttributeNode* att = attributes; + const XmlAttributeNode* att = attributes; - while (att != 0) - { - if (att->name.equalsIgnoreCase (attributeName)) - return att->value; + while (att != 0) + { + if (att->name.equalsIgnoreCase (attributeName)) + return att->value; - att = att->next; - } + att = att->next; + } - return defaultReturnValue; + return defaultReturnValue; } int XmlElement::getIntAttribute (const tchar* const attributeName, - const int defaultReturnValue) const throw() + const int defaultReturnValue) const throw() { - const XmlAttributeNode* att = attributes; + const XmlAttributeNode* att = attributes; - while (att != 0) - { - if (att->name.equalsIgnoreCase (attributeName)) - return att->value.getIntValue(); + while (att != 0) + { + if (att->name.equalsIgnoreCase (attributeName)) + return att->value.getIntValue(); - att = att->next; - } + att = att->next; + } - return defaultReturnValue; + return defaultReturnValue; } double XmlElement::getDoubleAttribute (const tchar* const attributeName, - const double defaultReturnValue) const throw() + const double defaultReturnValue) const throw() { - const XmlAttributeNode* att = attributes; + const XmlAttributeNode* att = attributes; - while (att != 0) - { - if (att->name.equalsIgnoreCase (attributeName)) - return att->value.getDoubleValue(); + while (att != 0) + { + if (att->name.equalsIgnoreCase (attributeName)) + return att->value.getDoubleValue(); - att = att->next; - } + att = att->next; + } - return defaultReturnValue; + return defaultReturnValue; } bool XmlElement::getBoolAttribute (const tchar* const attributeName, - const bool defaultReturnValue) const throw() + const bool defaultReturnValue) const throw() { - const XmlAttributeNode* att = attributes; + const XmlAttributeNode* att = attributes; - while (att != 0) - { - if (att->name.equalsIgnoreCase (attributeName)) - { - tchar firstChar = att->value[0]; + while (att != 0) + { + if (att->name.equalsIgnoreCase (attributeName)) + { + tchar firstChar = att->value[0]; - if (CharacterFunctions::isWhitespace (firstChar)) - firstChar = att->value.trimStart() [0]; + if (CharacterFunctions::isWhitespace (firstChar)) + firstChar = att->value.trimStart() [0]; - return firstChar == T('1') - || firstChar == T('t') - || firstChar == T('y') - || firstChar == T('T') - || firstChar == T('Y'); - } + return firstChar == T('1') + || firstChar == T('t') + || firstChar == T('y') + || firstChar == T('T') + || firstChar == T('Y'); + } - att = att->next; - } + att = att->next; + } - return defaultReturnValue; + return defaultReturnValue; } bool XmlElement::compareAttribute (const tchar* const attributeName, - const tchar* const stringToCompareAgainst, - const bool ignoreCase) const throw() + const tchar* const stringToCompareAgainst, + const bool ignoreCase) const throw() { - const XmlAttributeNode* att = attributes; + const XmlAttributeNode* att = attributes; - while (att != 0) - { - if (att->name.equalsIgnoreCase (attributeName)) - { - if (ignoreCase) - return att->value.equalsIgnoreCase (stringToCompareAgainst); - else - return att->value == stringToCompareAgainst; - } + while (att != 0) + { + if (att->name.equalsIgnoreCase (attributeName)) + { + if (ignoreCase) + return att->value.equalsIgnoreCase (stringToCompareAgainst); + else + return att->value == stringToCompareAgainst; + } - att = att->next; - } + att = att->next; + } - return false; + return false; } void XmlElement::setAttribute (const tchar* const attributeName, - const String& value) throw() + const String& value) throw() { #ifdef JUCE_DEBUG - // check the identifier being passed in is legal.. - const tchar* t = attributeName; - while (*t != 0) - { - jassert (CharacterFunctions::isLetterOrDigit (*t) - || *t == T('_') - || *t == T('-') - || *t == T(':')); - ++t; - } + // check the identifier being passed in is legal.. + const tchar* t = attributeName; + while (*t != 0) + { + jassert (CharacterFunctions::isLetterOrDigit (*t) + || *t == T('_') + || *t == T('-') + || *t == T(':')); + ++t; + } #endif - if (attributes == 0) - { - attributes = new XmlAttributeNode (attributeName, value); - } - else - { - XmlAttributeNode* att = attributes; + if (attributes == 0) + { + attributes = new XmlAttributeNode (attributeName, value); + } + else + { + XmlAttributeNode* att = attributes; - for (;;) - { - if (att->name.equalsIgnoreCase (attributeName)) - { - att->value = value; - break; - } - else if (att->next == 0) - { - att->next = new XmlAttributeNode (attributeName, value); - break; - } + for (;;) + { + if (att->name.equalsIgnoreCase (attributeName)) + { + att->value = value; + break; + } + else if (att->next == 0) + { + att->next = new XmlAttributeNode (attributeName, value); + break; + } - att = att->next; - } - } + att = att->next; + } + } } void XmlElement::setAttribute (const tchar* const attributeName, - const tchar* const text) throw() + const tchar* const text) throw() { - setAttribute (attributeName, String (text)); + setAttribute (attributeName, String (text)); } void XmlElement::setAttribute (const tchar* const attributeName, - const int number) throw() + const int number) throw() { - setAttribute (attributeName, String (number)); + setAttribute (attributeName, String (number)); } void XmlElement::setAttribute (const tchar* const attributeName, - const double number) throw() + const double number) throw() { - tchar buffer [40]; - CharacterFunctions::printf (buffer, numElementsInArray (buffer), T("%.9g"), number); - - setAttribute (attributeName, buffer); + setAttribute (attributeName, String (number)); } void XmlElement::removeAttribute (const tchar* const attributeName) throw() { - XmlAttributeNode* att = attributes; - XmlAttributeNode* lastAtt = 0; + XmlAttributeNode* att = attributes; + XmlAttributeNode* lastAtt = 0; - while (att != 0) - { - if (att->name.equalsIgnoreCase (attributeName)) - { - if (lastAtt == 0) - attributes = att->next; - else - lastAtt->next = att->next; + while (att != 0) + { + if (att->name.equalsIgnoreCase (attributeName)) + { + if (lastAtt == 0) + attributes = att->next; + else + lastAtt->next = att->next; - delete att; - break; - } + delete att; + break; + } - lastAtt = att; - att = att->next; - } + lastAtt = att; + att = att->next; + } } void XmlElement::removeAllAttributes() throw() { - while (attributes != 0) - { - XmlAttributeNode* const nextAtt = attributes->next; - delete attributes; - attributes = nextAtt; - } + while (attributes != 0) + { + XmlAttributeNode* const nextAtt = attributes->next; + delete attributes; + attributes = nextAtt; + } } int XmlElement::getNumChildElements() const throw() { - int count = 0; - const XmlElement* child = firstChildElement; + int count = 0; + const XmlElement* child = firstChildElement; - while (child != 0) - { - ++count; - child = child->nextElement; - } + while (child != 0) + { + ++count; + child = child->nextElement; + } - return count; + return count; } XmlElement* XmlElement::getChildElement (const int index) const throw() { - int count = 0; - XmlElement* child = firstChildElement; + int count = 0; + XmlElement* child = firstChildElement; - while (child != 0 && count < index) - { - child = child->nextElement; - ++count; - } + while (child != 0 && count < index) + { + child = child->nextElement; + ++count; + } - return child; + return child; } XmlElement* XmlElement::getChildByName (const tchar* const childName) const throw() { - XmlElement* child = firstChildElement; + XmlElement* child = firstChildElement; - while (child != 0) - { - if (child->hasTagName (childName)) - break; + while (child != 0) + { + if (child->hasTagName (childName)) + break; - child = child->nextElement; - } + child = child->nextElement; + } - return child; + return child; } void XmlElement::addChildElement (XmlElement* const newNode) throw() { - if (newNode != 0) - { - if (firstChildElement == 0) - { - firstChildElement = newNode; - } - else - { - XmlElement* child = firstChildElement; + if (newNode != 0) + { + if (firstChildElement == 0) + { + firstChildElement = newNode; + } + else + { + XmlElement* child = firstChildElement; - while (child->nextElement != 0) - child = child->nextElement; + while (child->nextElement != 0) + child = child->nextElement; - child->nextElement = newNode; + child->nextElement = newNode; - // if this is non-zero, then something's probably - // gone wrong.. - jassert (newNode->nextElement == 0); - } - } + // if this is non-zero, then something's probably + // gone wrong.. + jassert (newNode->nextElement == 0); + } + } } void XmlElement::insertChildElement (XmlElement* const newNode, - int indexToInsertAt) throw() + int indexToInsertAt) throw() { - if (newNode != 0) - { - removeChildElement (newNode, false); + if (newNode != 0) + { + removeChildElement (newNode, false); - if (indexToInsertAt == 0) - { - newNode->nextElement = firstChildElement; - firstChildElement = newNode; - } - else - { - if (firstChildElement == 0) - { - firstChildElement = newNode; - } - else - { - if (indexToInsertAt < 0) - indexToInsertAt = INT_MAX; + if (indexToInsertAt == 0) + { + newNode->nextElement = firstChildElement; + firstChildElement = newNode; + } + else + { + if (firstChildElement == 0) + { + firstChildElement = newNode; + } + else + { + if (indexToInsertAt < 0) + indexToInsertAt = INT_MAX; - XmlElement* child = firstChildElement; + XmlElement* child = firstChildElement; - while (child->nextElement != 0 && --indexToInsertAt > 0) - child = child->nextElement; + while (child->nextElement != 0 && --indexToInsertAt > 0) + child = child->nextElement; - newNode->nextElement = child->nextElement; - child->nextElement = newNode; - } - } - } + newNode->nextElement = child->nextElement; + child->nextElement = newNode; + } + } + } } bool XmlElement::replaceChildElement (XmlElement* const currentChildElement, - XmlElement* const newNode) throw() + XmlElement* const newNode) throw() { - if (newNode != 0) - { - XmlElement* child = firstChildElement; - XmlElement* previousNode = 0; + if (newNode != 0) + { + XmlElement* child = firstChildElement; + XmlElement* previousNode = 0; - while (child != 0) - { - if (child == currentChildElement) - { - if (child != newNode) - { - if (previousNode == 0) - firstChildElement = newNode; - else - previousNode->nextElement = newNode; + while (child != 0) + { + if (child == currentChildElement) + { + if (child != newNode) + { + if (previousNode == 0) + firstChildElement = newNode; + else + previousNode->nextElement = newNode; - newNode->nextElement = child->nextElement; + newNode->nextElement = child->nextElement; - delete child; - } + delete child; + } - return true; - } + return true; + } - previousNode = child; - child = child->nextElement; - } - } + previousNode = child; + child = child->nextElement; + } + } - return false; + return false; } void XmlElement::removeChildElement (XmlElement* const childToRemove, - const bool shouldDeleteTheChild) throw() + const bool shouldDeleteTheChild) throw() { - if (childToRemove != 0) - { - if (firstChildElement == childToRemove) - { - firstChildElement = childToRemove->nextElement; - childToRemove->nextElement = 0; - } - else - { - XmlElement* child = firstChildElement; - XmlElement* last = 0; + if (childToRemove != 0) + { + if (firstChildElement == childToRemove) + { + firstChildElement = childToRemove->nextElement; + childToRemove->nextElement = 0; + } + else + { + XmlElement* child = firstChildElement; + XmlElement* last = 0; - while (child != 0) - { - if (child == childToRemove) - { - if (last == 0) - firstChildElement = child->nextElement; - else - last->nextElement = child->nextElement; + while (child != 0) + { + if (child == childToRemove) + { + if (last == 0) + firstChildElement = child->nextElement; + else + last->nextElement = child->nextElement; - childToRemove->nextElement = 0; - break; - } + childToRemove->nextElement = 0; + break; + } - last = child; - child = child->nextElement; - } - } + last = child; + child = child->nextElement; + } + } - if (shouldDeleteTheChild) - delete childToRemove; - } + if (shouldDeleteTheChild) + delete childToRemove; + } } bool XmlElement::isEquivalentTo (const XmlElement* const other, - const bool ignoreOrderOfAttributes) const throw() + const bool ignoreOrderOfAttributes) const throw() { - if (this != other) - { - if (other == 0 || tagName != other->tagName) - { - return false; - } + if (this != other) + { + if (other == 0 || tagName != other->tagName) + { + return false; + } - if (ignoreOrderOfAttributes) - { - int totalAtts = 0; - const XmlAttributeNode* att = attributes; + if (ignoreOrderOfAttributes) + { + int totalAtts = 0; + const XmlAttributeNode* att = attributes; - while (att != 0) - { - if (! other->compareAttribute (att->name, att->value)) - return false; + while (att != 0) + { + if (! other->compareAttribute (att->name, att->value)) + return false; - att = att->next; - ++totalAtts; - } + att = att->next; + ++totalAtts; + } - if (totalAtts != other->getNumAttributes()) - return false; - } - else - { - const XmlAttributeNode* thisAtt = attributes; - const XmlAttributeNode* otherAtt = other->attributes; + if (totalAtts != other->getNumAttributes()) + return false; + } + else + { + const XmlAttributeNode* thisAtt = attributes; + const XmlAttributeNode* otherAtt = other->attributes; - for (;;) - { - if (thisAtt == 0 || otherAtt == 0) - { - if (thisAtt == otherAtt) // both 0, so it's a match - break; + for (;;) + { + if (thisAtt == 0 || otherAtt == 0) + { + if (thisAtt == otherAtt) // both 0, so it's a match + break; - return false; - } + return false; + } - if (thisAtt->name != otherAtt->name - || thisAtt->value != otherAtt->value) - { - return false; - } + if (thisAtt->name != otherAtt->name + || thisAtt->value != otherAtt->value) + { + return false; + } - thisAtt = thisAtt->next; - otherAtt = otherAtt->next; - } - } + thisAtt = thisAtt->next; + otherAtt = otherAtt->next; + } + } - const XmlElement* thisChild = firstChildElement; - const XmlElement* otherChild = other->firstChildElement; + const XmlElement* thisChild = firstChildElement; + const XmlElement* otherChild = other->firstChildElement; - for (;;) - { - if (thisChild == 0 || otherChild == 0) - { - if (thisChild == otherChild) // both 0, so it's a match - break; + for (;;) + { + if (thisChild == 0 || otherChild == 0) + { + if (thisChild == otherChild) // both 0, so it's a match + break; - return false; - } + return false; + } - if (! thisChild->isEquivalentTo (otherChild, ignoreOrderOfAttributes)) - return false; + if (! thisChild->isEquivalentTo (otherChild, ignoreOrderOfAttributes)) + return false; - thisChild = thisChild->nextElement; - otherChild = otherChild->nextElement; - } - } + thisChild = thisChild->nextElement; + otherChild = otherChild->nextElement; + } + } - return true; + return true; } void XmlElement::deleteAllChildElements() throw() { - while (firstChildElement != 0) - { - XmlElement* const nextChild = firstChildElement->nextElement; - delete firstChildElement; - firstChildElement = nextChild; - } + while (firstChildElement != 0) + { + XmlElement* const nextChild = firstChildElement->nextElement; + delete firstChildElement; + firstChildElement = nextChild; + } } void XmlElement::deleteAllChildElementsWithTagName (const tchar* const name) throw() { - XmlElement* child = firstChildElement; + XmlElement* child = firstChildElement; - while (child != 0) - { - if (child->hasTagName (name)) - { - XmlElement* const nextChild = child->nextElement; - removeChildElement (child, true); - child = nextChild; - } - else - { - child = child->nextElement; - } - } + while (child != 0) + { + if (child->hasTagName (name)) + { + XmlElement* const nextChild = child->nextElement; + removeChildElement (child, true); + child = nextChild; + } + else + { + child = child->nextElement; + } + } } bool XmlElement::containsChildElement (const XmlElement* const possibleChild) const throw() { - const XmlElement* child = firstChildElement; + const XmlElement* child = firstChildElement; - while (child != 0) - { - if (child == possibleChild) - return true; + while (child != 0) + { + if (child == possibleChild) + return true; - child = child->nextElement; - } + child = child->nextElement; + } - return false; + return false; } XmlElement* XmlElement::findParentElementOf (const XmlElement* const elementToLookFor) throw() { - if (this == elementToLookFor || elementToLookFor == 0) - return 0; + if (this == elementToLookFor || elementToLookFor == 0) + return 0; - XmlElement* child = firstChildElement; + XmlElement* child = firstChildElement; - while (child != 0) - { - if (elementToLookFor == child) - return this; + while (child != 0) + { + if (elementToLookFor == child) + return this; - XmlElement* const found = child->findParentElementOf (elementToLookFor); + XmlElement* const found = child->findParentElementOf (elementToLookFor); - if (found != 0) - return found; + if (found != 0) + return found; - child = child->nextElement; - } + child = child->nextElement; + } - return 0; + return 0; } void XmlElement::getChildElementsAsArray (XmlElement** elems) const throw() { - XmlElement* e = firstChildElement; + XmlElement* e = firstChildElement; - while (e != 0) - { - *elems++ = e; - e = e->nextElement; - } + while (e != 0) + { + *elems++ = e; + e = e->nextElement; + } } void XmlElement::reorderChildElements (XmlElement** const elems, const int num) throw() { - XmlElement* e = firstChildElement = elems[0]; + XmlElement* e = firstChildElement = elems[0]; - for (int i = 1; i < num; ++i) - { - e->nextElement = elems[i]; - e = e->nextElement; - } + for (int i = 1; i < num; ++i) + { + e->nextElement = elems[i]; + e = e->nextElement; + } - e->nextElement = 0; + e->nextElement = 0; } bool XmlElement::isTextElement() const throw() { - return tagName.isEmpty(); + return tagName.isEmpty(); } static const tchar* const juce_xmltextContentAttributeName = T("text"); const String XmlElement::getText() const throw() { - jassert (isTextElement()); // you're trying to get the text from an element that - // isn't actually a text element.. If this contains text sub-nodes, you - // probably want to use getAllSubText instead. + jassert (isTextElement()); // you're trying to get the text from an element that + // isn't actually a text element.. If this contains text sub-nodes, you + // probably want to use getAllSubText instead. - return getStringAttribute (juce_xmltextContentAttributeName); + return getStringAttribute (juce_xmltextContentAttributeName); } void XmlElement::setText (const String& newText) throw() { - if (isTextElement()) - { - setAttribute (juce_xmltextContentAttributeName, newText); - } - else - { - jassertfalse // you can only change the text in a text element, not a normal one. - } + if (isTextElement()) + { + setAttribute (juce_xmltextContentAttributeName, newText); + } + else + { + jassertfalse // you can only change the text in a text element, not a normal one. + } } const String XmlElement::getAllSubText() const throw() { - String result; - String::Concatenator concatenator (result); - const XmlElement* child = firstChildElement; + String result; + String::Concatenator concatenator (result); + const XmlElement* child = firstChildElement; - while (child != 0) - { - if (child->isTextElement()) - concatenator.append (child->getText()); + while (child != 0) + { + if (child->isTextElement()) + concatenator.append (child->getText()); - child = child->nextElement; - } + child = child->nextElement; + } - return result; + return result; } const String XmlElement::getChildElementAllSubText (const tchar* const childTagName, - const String& defaultReturnValue) const throw() + const String& defaultReturnValue) const throw() { - const XmlElement* const child = getChildByName (childTagName); + const XmlElement* const child = getChildByName (childTagName); - if (child != 0) - return child->getAllSubText(); + if (child != 0) + return child->getAllSubText(); - return defaultReturnValue; + return defaultReturnValue; } XmlElement* XmlElement::createTextElement (const String& text) throw() { - XmlElement* const e = new XmlElement ((int) 0); - e->setAttribute (juce_xmltextContentAttributeName, text); - return e; + XmlElement* const e = new XmlElement ((int) 0); + e->setAttribute (juce_xmltextContentAttributeName, text); + return e; } void XmlElement::addTextElement (const String& text) throw() { - addChildElement (createTextElement (text)); + addChildElement (createTextElement (text)); } void XmlElement::deleteAllTextElements() throw() { - XmlElement* child = firstChildElement; + XmlElement* child = firstChildElement; - while (child != 0) - { - XmlElement* const next = child->nextElement; + while (child != 0) + { + XmlElement* const next = child->nextElement; - if (child->isTextElement()) - removeChildElement (child, true); + if (child->isTextElement()) + removeChildElement (child, true); - child = next; - } + child = next; + } } END_JUCE_NAMESPACE @@ -15418,137 +15178,137 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ReadWriteLock::ReadWriteLock() throw() - : numWaitingWriters (0), - numWriters (0), - writerThreadId (0) + : numWaitingWriters (0), + numWriters (0), + writerThreadId (0) { } ReadWriteLock::~ReadWriteLock() throw() { - jassert (readerThreads.size() == 0); - jassert (numWriters == 0); + jassert (readerThreads.size() == 0); + jassert (numWriters == 0); } void ReadWriteLock::enterRead() const throw() { - const Thread::ThreadID threadId = Thread::getCurrentThreadId(); - const ScopedLock sl (accessLock); + const Thread::ThreadID threadId = Thread::getCurrentThreadId(); + const ScopedLock sl (accessLock); - for (;;) - { - jassert (readerThreads.size() % 2 == 0); + for (;;) + { + jassert (readerThreads.size() % 2 == 0); - int i; - for (i = 0; i < readerThreads.size(); i += 2) - if (readerThreads.getUnchecked(i) == threadId) - break; + int i; + for (i = 0; i < readerThreads.size(); i += 2) + if (readerThreads.getUnchecked(i) == threadId) + break; - if (i < readerThreads.size() - || numWriters + numWaitingWriters == 0 - || (threadId == writerThreadId && numWriters > 0)) - { - if (i < readerThreads.size()) - { - readerThreads.set (i + 1, (Thread::ThreadID) (1 + (pointer_sized_int) readerThreads.getUnchecked (i + 1))); - } - else - { - readerThreads.add (threadId); - readerThreads.add ((Thread::ThreadID) 1); - } + if (i < readerThreads.size() + || numWriters + numWaitingWriters == 0 + || (threadId == writerThreadId && numWriters > 0)) + { + if (i < readerThreads.size()) + { + readerThreads.set (i + 1, (Thread::ThreadID) (1 + (pointer_sized_int) readerThreads.getUnchecked (i + 1))); + } + else + { + readerThreads.add (threadId); + readerThreads.add ((Thread::ThreadID) 1); + } - return; - } + return; + } - const ScopedUnlock ul (accessLock); - waitEvent.wait (100); - } + const ScopedUnlock ul (accessLock); + waitEvent.wait (100); + } } void ReadWriteLock::exitRead() const throw() { - const Thread::ThreadID threadId = Thread::getCurrentThreadId(); - const ScopedLock sl (accessLock); + const Thread::ThreadID threadId = Thread::getCurrentThreadId(); + const ScopedLock sl (accessLock); - for (int i = 0; i < readerThreads.size(); i += 2) - { - if (readerThreads.getUnchecked(i) == threadId) - { - const pointer_sized_int newCount = ((pointer_sized_int) readerThreads.getUnchecked (i + 1)) - 1; + for (int i = 0; i < readerThreads.size(); i += 2) + { + if (readerThreads.getUnchecked(i) == threadId) + { + const pointer_sized_int newCount = ((pointer_sized_int) readerThreads.getUnchecked (i + 1)) - 1; - if (newCount == 0) - { - readerThreads.removeRange (i, 2); - waitEvent.signal(); - } - else - { - readerThreads.set (i + 1, (Thread::ThreadID) newCount); - } + if (newCount == 0) + { + readerThreads.removeRange (i, 2); + waitEvent.signal(); + } + else + { + readerThreads.set (i + 1, (Thread::ThreadID) newCount); + } - return; - } - } + return; + } + } - jassertfalse // unlocking a lock that wasn't locked.. + jassertfalse // unlocking a lock that wasn't locked.. } void ReadWriteLock::enterWrite() const throw() { - const Thread::ThreadID threadId = Thread::getCurrentThreadId(); - const ScopedLock sl (accessLock); + const Thread::ThreadID threadId = Thread::getCurrentThreadId(); + const ScopedLock sl (accessLock); - for (;;) - { - if (readerThreads.size() + numWriters == 0 - || threadId == writerThreadId - || (readerThreads.size() == 2 - && readerThreads.getUnchecked(0) == threadId)) - { - writerThreadId = threadId; - ++numWriters; - break; - } + for (;;) + { + if (readerThreads.size() + numWriters == 0 + || threadId == writerThreadId + || (readerThreads.size() == 2 + && readerThreads.getUnchecked(0) == threadId)) + { + writerThreadId = threadId; + ++numWriters; + break; + } - ++numWaitingWriters; - accessLock.exit(); - waitEvent.wait (100); - accessLock.enter(); - --numWaitingWriters; - } + ++numWaitingWriters; + accessLock.exit(); + waitEvent.wait (100); + accessLock.enter(); + --numWaitingWriters; + } } bool ReadWriteLock::tryEnterWrite() const throw() { - const Thread::ThreadID threadId = Thread::getCurrentThreadId(); - const ScopedLock sl (accessLock); + const Thread::ThreadID threadId = Thread::getCurrentThreadId(); + const ScopedLock sl (accessLock); - if (readerThreads.size() + numWriters == 0 - || threadId == writerThreadId - || (readerThreads.size() == 2 - && readerThreads.getUnchecked(0) == threadId)) - { - writerThreadId = threadId; - ++numWriters; - return true; - } + if (readerThreads.size() + numWriters == 0 + || threadId == writerThreadId + || (readerThreads.size() == 2 + && readerThreads.getUnchecked(0) == threadId)) + { + writerThreadId = threadId; + ++numWriters; + return true; + } - return false; + return false; } void ReadWriteLock::exitWrite() const throw() { - const ScopedLock sl (accessLock); + const ScopedLock sl (accessLock); - // check this thread actually had the lock.. - jassert (numWriters > 0 && writerThreadId == Thread::getCurrentThreadId()); + // check this thread actually had the lock.. + jassert (numWriters > 0 && writerThreadId == Thread::getCurrentThreadId()); - if (--numWriters == 0) - { - writerThreadId = 0; - waitEvent.signal(); - } + if (--numWriters == 0) + { + writerThreadId = 0; + waitEvent.signal(); + } } END_JUCE_NAMESPACE @@ -15567,235 +15327,235 @@ void juce_setCurrentThreadName (const String& name); void juce_CloseThreadHandle (void* handle); #endif -static VoidArray runningThreads (4); +static VoidArray runningThreads; static CriticalSection runningThreadsLock; void Thread::threadEntryPoint (Thread* const thread) { - { - const ScopedLock sl (runningThreadsLock); - runningThreads.add (thread); - } + { + const ScopedLock sl (runningThreadsLock); + runningThreads.add (thread); + } - JUCE_TRY - { - thread->threadId_ = Thread::getCurrentThreadId(); + JUCE_TRY + { + thread->threadId_ = Thread::getCurrentThreadId(); - if (thread->threadName_.isNotEmpty()) - juce_setCurrentThreadName (thread->threadName_); + if (thread->threadName_.isNotEmpty()) + juce_setCurrentThreadName (thread->threadName_); - if (thread->startSuspensionEvent_.wait (10000)) - { - if (thread->affinityMask_ != 0) - setCurrentThreadAffinityMask (thread->affinityMask_); + if (thread->startSuspensionEvent_.wait (10000)) + { + if (thread->affinityMask_ != 0) + setCurrentThreadAffinityMask (thread->affinityMask_); - thread->run(); - } - } - JUCE_CATCH_ALL_ASSERT + thread->run(); + } + } + JUCE_CATCH_ALL_ASSERT - { - const ScopedLock sl (runningThreadsLock); + { + const ScopedLock sl (runningThreadsLock); - jassert (runningThreads.contains (thread)); - runningThreads.removeValue (thread); - } + jassert (runningThreads.contains (thread)); + runningThreads.removeValue (thread); + } #if JUCE_WIN32 - juce_CloseThreadHandle (thread->threadHandle_); + juce_CloseThreadHandle (thread->threadHandle_); #endif - thread->threadHandle_ = 0; - thread->threadId_ = 0; + thread->threadHandle_ = 0; + thread->threadId_ = 0; } // used to wrap the incoming call from the platform-specific code void JUCE_API juce_threadEntryPoint (void* userData) { - Thread::threadEntryPoint ((Thread*) userData); + Thread::threadEntryPoint ((Thread*) userData); } Thread::Thread (const String& threadName) - : threadName_ (threadName), - threadHandle_ (0), - threadPriority_ (5), - threadId_ (0), - affinityMask_ (0), - threadShouldExit_ (false) + : threadName_ (threadName), + threadHandle_ (0), + threadPriority_ (5), + threadId_ (0), + affinityMask_ (0), + threadShouldExit_ (false) { } Thread::~Thread() { - stopThread (100); + stopThread (100); } void Thread::startThread() { - const ScopedLock sl (startStopLock); + const ScopedLock sl (startStopLock); - threadShouldExit_ = false; + threadShouldExit_ = false; - if (threadHandle_ == 0) - { - threadHandle_ = juce_createThread ((void*) this); - juce_setThreadPriority (threadHandle_, threadPriority_); - startSuspensionEvent_.signal(); - } + if (threadHandle_ == 0) + { + threadHandle_ = juce_createThread ((void*) this); + juce_setThreadPriority (threadHandle_, threadPriority_); + startSuspensionEvent_.signal(); + } } void Thread::startThread (const int priority) { - const ScopedLock sl (startStopLock); + const ScopedLock sl (startStopLock); - if (threadHandle_ == 0) - { - threadPriority_ = priority; - startThread(); - } - else - { - setPriority (priority); - } + if (threadHandle_ == 0) + { + threadPriority_ = priority; + startThread(); + } + else + { + setPriority (priority); + } } bool Thread::isThreadRunning() const { - return threadHandle_ != 0; + return threadHandle_ != 0; } void Thread::signalThreadShouldExit() { - threadShouldExit_ = true; + threadShouldExit_ = true; } bool Thread::waitForThreadToExit (const int timeOutMilliseconds) const { - // Doh! So how exactly do you expect this thread to wait for itself to stop?? - jassert (getThreadId() != getCurrentThreadId()); + // Doh! So how exactly do you expect this thread to wait for itself to stop?? + jassert (getThreadId() != getCurrentThreadId()); - const int sleepMsPerIteration = 5; - int count = timeOutMilliseconds / sleepMsPerIteration; + const int sleepMsPerIteration = 5; + int count = timeOutMilliseconds / sleepMsPerIteration; - while (isThreadRunning()) - { - if (timeOutMilliseconds > 0 && --count < 0) - return false; + while (isThreadRunning()) + { + if (timeOutMilliseconds > 0 && --count < 0) + return false; - sleep (sleepMsPerIteration); - } + sleep (sleepMsPerIteration); + } - return true; + return true; } void Thread::stopThread (const int timeOutMilliseconds) { - // agh! You can't stop the thread that's calling this method! How on earth - // would that work?? - jassert (getCurrentThreadId() != getThreadId()); + // agh! You can't stop the thread that's calling this method! How on earth + // would that work?? + jassert (getCurrentThreadId() != getThreadId()); - const ScopedLock sl (startStopLock); + const ScopedLock sl (startStopLock); - if (isThreadRunning()) - { - signalThreadShouldExit(); - notify(); + if (isThreadRunning()) + { + signalThreadShouldExit(); + notify(); - if (timeOutMilliseconds != 0) - waitForThreadToExit (timeOutMilliseconds); + if (timeOutMilliseconds != 0) + waitForThreadToExit (timeOutMilliseconds); - if (isThreadRunning()) - { - // very bad karma if this point is reached, as - // there are bound to be locks and events left in - // silly states when a thread is killed by force.. - jassertfalse - Logger::writeToLog ("!! killing thread by force !!"); + if (isThreadRunning()) + { + // very bad karma if this point is reached, as + // there are bound to be locks and events left in + // silly states when a thread is killed by force.. + jassertfalse + Logger::writeToLog ("!! killing thread by force !!"); - juce_killThread (threadHandle_); - threadHandle_ = 0; - threadId_ = 0; + juce_killThread (threadHandle_); + threadHandle_ = 0; + threadId_ = 0; - const ScopedLock sl2 (runningThreadsLock); - runningThreads.removeValue (this); - } - } + const ScopedLock sl2 (runningThreadsLock); + runningThreads.removeValue (this); + } + } } bool Thread::setPriority (const int priority) { - const ScopedLock sl (startStopLock); + const ScopedLock sl (startStopLock); - const bool worked = juce_setThreadPriority (threadHandle_, priority); + const bool worked = juce_setThreadPriority (threadHandle_, priority); - if (worked) - threadPriority_ = priority; + if (worked) + threadPriority_ = priority; - return worked; + return worked; } bool Thread::setCurrentThreadPriority (const int priority) { - return juce_setThreadPriority (0, priority); + return juce_setThreadPriority (0, priority); } void Thread::setAffinityMask (const uint32 affinityMask) { - affinityMask_ = affinityMask; + affinityMask_ = affinityMask; } bool Thread::wait (const int timeOutMilliseconds) const { - return defaultEvent_.wait (timeOutMilliseconds); + return defaultEvent_.wait (timeOutMilliseconds); } void Thread::notify() const { - defaultEvent_.signal(); + defaultEvent_.signal(); } int Thread::getNumRunningThreads() { - return runningThreads.size(); + return runningThreads.size(); } Thread* Thread::getCurrentThread() { - const ThreadID thisId = getCurrentThreadId(); + const ThreadID thisId = getCurrentThreadId(); - const ScopedLock sl (runningThreadsLock); + const ScopedLock sl (runningThreadsLock); - for (int i = runningThreads.size(); --i >= 0;) - { - Thread* const t = (Thread*) runningThreads.getUnchecked(i); + for (int i = runningThreads.size(); --i >= 0;) + { + Thread* const t = (Thread*) runningThreads.getUnchecked(i); - if (t->threadId_ == thisId) - return t; - } + if (t->threadId_ == thisId) + return t; + } - return 0; + return 0; } void Thread::stopAllThreads (const int timeOutMilliseconds) { - { - const ScopedLock sl (runningThreadsLock); + { + const ScopedLock sl (runningThreadsLock); - for (int i = runningThreads.size(); --i >= 0;) - ((Thread*) runningThreads.getUnchecked(i))->signalThreadShouldExit(); - } + for (int i = runningThreads.size(); --i >= 0;) + ((Thread*) runningThreads.getUnchecked(i))->signalThreadShouldExit(); + } - for (;;) - { - runningThreadsLock.enter(); - Thread* const t = (Thread*) runningThreads[0]; - runningThreadsLock.exit(); + for (;;) + { + runningThreadsLock.enter(); + Thread* const t = (Thread*) runningThreads[0]; + runningThreadsLock.exit(); - if (t == 0) - break; + if (t == 0) + break; - t->stopThread (timeOutMilliseconds); - } + t->stopThread (timeOutMilliseconds); + } } END_JUCE_NAMESPACE @@ -15806,387 +15566,387 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ThreadPoolJob::ThreadPoolJob (const String& name) - : jobName (name), - pool (0), - shouldStop (false), - isActive (false), - shouldBeDeleted (false) + : jobName (name), + pool (0), + shouldStop (false), + isActive (false), + shouldBeDeleted (false) { } ThreadPoolJob::~ThreadPoolJob() { - // you mustn't delete a job while it's still in a pool! Use ThreadPool::removeJob() - // to remove it first! - jassert (pool == 0 || ! pool->contains (this)); + // you mustn't delete a job while it's still in a pool! Use ThreadPool::removeJob() + // to remove it first! + jassert (pool == 0 || ! pool->contains (this)); } const String ThreadPoolJob::getJobName() const { - return jobName; + return jobName; } void ThreadPoolJob::setJobName (const String& newName) { - jobName = newName; + jobName = newName; } void ThreadPoolJob::signalJobShouldExit() { - shouldStop = true; + shouldStop = true; } class ThreadPoolThread : public Thread { - ThreadPool& pool; - bool volatile busy; + ThreadPool& pool; + bool volatile busy; - ThreadPoolThread (const ThreadPoolThread&); - const ThreadPoolThread& operator= (const ThreadPoolThread&); + ThreadPoolThread (const ThreadPoolThread&); + const ThreadPoolThread& operator= (const ThreadPoolThread&); public: - ThreadPoolThread (ThreadPool& pool_) - : Thread (T("Pool")), - pool (pool_), - busy (false) - { - } + ThreadPoolThread (ThreadPool& pool_) + : Thread (T("Pool")), + pool (pool_), + busy (false) + { + } - ~ThreadPoolThread() - { - } + ~ThreadPoolThread() + { + } - void run() - { - while (! threadShouldExit()) - { - if (! pool.runNextJob()) - wait (500); - } - } + void run() + { + while (! threadShouldExit()) + { + if (! pool.runNextJob()) + wait (500); + } + } }; ThreadPool::ThreadPool (const int numThreads_, - const bool startThreadsOnlyWhenNeeded, - const int stopThreadsWhenNotUsedTimeoutMs) - : numThreads (jmax (1, numThreads_)), - threadStopTimeout (stopThreadsWhenNotUsedTimeoutMs), - priority (5) + const bool startThreadsOnlyWhenNeeded, + const int stopThreadsWhenNotUsedTimeoutMs) + : numThreads (jmax (1, numThreads_)), + threadStopTimeout (stopThreadsWhenNotUsedTimeoutMs), + priority (5) { - jassert (numThreads_ > 0); // not much point having one of these with no threads in it. + jassert (numThreads_ > 0); // not much point having one of these with no threads in it. - threads.calloc (numThreads); + threads.calloc (numThreads); - for (int i = numThreads; --i >= 0;) - threads[i] = new ThreadPoolThread (*this); + for (int i = numThreads; --i >= 0;) + threads[i] = new ThreadPoolThread (*this); - if (! startThreadsOnlyWhenNeeded) - for (int i = numThreads; --i >= 0;) - threads[i]->startThread (priority); + if (! startThreadsOnlyWhenNeeded) + for (int i = numThreads; --i >= 0;) + threads[i]->startThread (priority); } ThreadPool::~ThreadPool() { - removeAllJobs (true, 4000); + removeAllJobs (true, 4000); - int i; - for (i = numThreads; --i >= 0;) - threads[i]->signalThreadShouldExit(); + int i; + for (i = numThreads; --i >= 0;) + threads[i]->signalThreadShouldExit(); - for (i = numThreads; --i >= 0;) - { - threads[i]->stopThread (500); - delete threads[i]; - } + for (i = numThreads; --i >= 0;) + { + threads[i]->stopThread (500); + delete threads[i]; + } } void ThreadPool::addJob (ThreadPoolJob* const job) { - jassert (job != 0); - jassert (job->pool == 0); + jassert (job != 0); + jassert (job->pool == 0); - if (job->pool == 0) - { - job->pool = this; - job->shouldStop = false; - job->isActive = false; + if (job->pool == 0) + { + job->pool = this; + job->shouldStop = false; + job->isActive = false; - lock.enter(); - jobs.add (job); + lock.enter(); + jobs.add (job); - int numRunning = 0; + int numRunning = 0; - int i; - for (i = numThreads; --i >= 0;) - if (threads[i]->isThreadRunning() && ! threads[i]->threadShouldExit()) - ++numRunning; + int i; + for (i = numThreads; --i >= 0;) + if (threads[i]->isThreadRunning() && ! threads[i]->threadShouldExit()) + ++numRunning; - if (numRunning < numThreads) - { - bool startedOne = false; - int n = 1000; + if (numRunning < numThreads) + { + bool startedOne = false; + int n = 1000; - while (--n >= 0 && ! startedOne) - { - for (i = numThreads; --i >= 0;) - { - if (! threads[i]->isThreadRunning()) - { - threads[i]->startThread (priority); - startedOne = true; - break; - } - } + while (--n >= 0 && ! startedOne) + { + for (i = numThreads; --i >= 0;) + { + if (! threads[i]->isThreadRunning()) + { + threads[i]->startThread (priority); + startedOne = true; + break; + } + } - if (! startedOne) - Thread::sleep (2); - } - } + if (! startedOne) + Thread::sleep (2); + } + } - lock.exit(); + lock.exit(); - for (i = numThreads; --i >= 0;) - threads[i]->notify(); - } + for (i = numThreads; --i >= 0;) + threads[i]->notify(); + } } int ThreadPool::getNumJobs() const { - return jobs.size(); + return jobs.size(); } ThreadPoolJob* ThreadPool::getJob (const int index) const { - const ScopedLock sl (lock); - return (ThreadPoolJob*) jobs [index]; + const ScopedLock sl (lock); + return (ThreadPoolJob*) jobs [index]; } bool ThreadPool::contains (const ThreadPoolJob* const job) const { - const ScopedLock sl (lock); - return jobs.contains ((void*) job); + const ScopedLock sl (lock); + return jobs.contains ((void*) job); } bool ThreadPool::isJobRunning (const ThreadPoolJob* const job) const { - const ScopedLock sl (lock); - return jobs.contains ((void*) job) && job->isActive; + const ScopedLock sl (lock); + return jobs.contains ((void*) job) && job->isActive; } bool ThreadPool::waitForJobToFinish (const ThreadPoolJob* const job, - const int timeOutMs) const + const int timeOutMs) const { - if (job != 0) - { - const uint32 start = Time::getMillisecondCounter(); + if (job != 0) + { + const uint32 start = Time::getMillisecondCounter(); - while (contains (job)) - { - if (timeOutMs >= 0 && Time::getMillisecondCounter() >= start + timeOutMs) - return false; + while (contains (job)) + { + if (timeOutMs >= 0 && Time::getMillisecondCounter() >= start + timeOutMs) + return false; - jobFinishedSignal.wait (2); - } - } + jobFinishedSignal.wait (2); + } + } - return true; + return true; } bool ThreadPool::removeJob (ThreadPoolJob* const job, - const bool interruptIfRunning, - const int timeOutMs) + const bool interruptIfRunning, + const int timeOutMs) { - if (job != 0) - { - lock.enter(); + if (job != 0) + { + lock.enter(); - if (jobs.contains (job)) - { - if (job->isActive) - { - if (interruptIfRunning) - job->signalJobShouldExit(); + if (jobs.contains (job)) + { + if (job->isActive) + { + if (interruptIfRunning) + job->signalJobShouldExit(); - lock.exit(); + lock.exit(); - return waitForJobToFinish (job, timeOutMs); - } - else - { - jobs.removeValue (job); - } - } + return waitForJobToFinish (job, timeOutMs); + } + else + { + jobs.removeValue (job); + } + } - lock.exit(); - } + lock.exit(); + } - return true; + return true; } bool ThreadPool::removeAllJobs (const bool interruptRunningJobs, - const int timeOutMs, - const bool deleteInactiveJobs, - ThreadPool::JobSelector* selectedJobsToRemove) + const int timeOutMs, + const bool deleteInactiveJobs, + ThreadPool::JobSelector* selectedJobsToRemove) { - Array jobsToWaitFor; + Array jobsToWaitFor; - lock.enter(); + lock.enter(); - for (int i = jobs.size(); --i >= 0;) - { - ThreadPoolJob* const job = (ThreadPoolJob*) jobs.getUnchecked(i); + for (int i = jobs.size(); --i >= 0;) + { + ThreadPoolJob* const job = (ThreadPoolJob*) jobs.getUnchecked(i); - if (selectedJobsToRemove == 0 || selectedJobsToRemove->isJobSuitable (job)) - { - if (job->isActive) - { - jobsToWaitFor.add (job); + if (selectedJobsToRemove == 0 || selectedJobsToRemove->isJobSuitable (job)) + { + if (job->isActive) + { + jobsToWaitFor.add (job); - if (interruptRunningJobs) - job->signalJobShouldExit(); - } - else - { - jobs.remove (i); + if (interruptRunningJobs) + job->signalJobShouldExit(); + } + else + { + jobs.remove (i); - if (deleteInactiveJobs) - delete job; - } - } - } + if (deleteInactiveJobs) + delete job; + } + } + } - lock.exit(); + lock.exit(); - const uint32 start = Time::getMillisecondCounter(); + const uint32 start = Time::getMillisecondCounter(); - for (;;) - { - for (int i = jobsToWaitFor.size(); --i >= 0;) - if (! isJobRunning (jobsToWaitFor.getUnchecked (i))) - jobsToWaitFor.remove (i); + for (;;) + { + for (int i = jobsToWaitFor.size(); --i >= 0;) + if (! isJobRunning (jobsToWaitFor.getUnchecked (i))) + jobsToWaitFor.remove (i); - if (jobsToWaitFor.size() == 0) - break; + if (jobsToWaitFor.size() == 0) + break; - if (timeOutMs >= 0 && Time::getMillisecondCounter() >= start + timeOutMs) - return false; + if (timeOutMs >= 0 && Time::getMillisecondCounter() >= start + timeOutMs) + return false; - jobFinishedSignal.wait (20); - } + jobFinishedSignal.wait (20); + } - return true; + return true; } const StringArray ThreadPool::getNamesOfAllJobs (const bool onlyReturnActiveJobs) const { - StringArray s; - const ScopedLock sl (lock); + StringArray s; + const ScopedLock sl (lock); - for (int i = 0; i < jobs.size(); ++i) - { - const ThreadPoolJob* const job = (const ThreadPoolJob*) jobs.getUnchecked(i); - if (job->isActive || ! onlyReturnActiveJobs) - s.add (job->getJobName()); - } + for (int i = 0; i < jobs.size(); ++i) + { + const ThreadPoolJob* const job = (const ThreadPoolJob*) jobs.getUnchecked(i); + if (job->isActive || ! onlyReturnActiveJobs) + s.add (job->getJobName()); + } - return s; + return s; } bool ThreadPool::setThreadPriorities (const int newPriority) { - bool ok = true; + bool ok = true; - if (priority != newPriority) - { - priority = newPriority; + if (priority != newPriority) + { + priority = newPriority; - for (int i = numThreads; --i >= 0;) - if (! threads[i]->setPriority (newPriority)) - ok = false; - } + for (int i = numThreads; --i >= 0;) + if (! threads[i]->setPriority (newPriority)) + ok = false; + } - return ok; + return ok; } bool ThreadPool::runNextJob() { - lock.enter(); - ThreadPoolJob* job = 0; + lock.enter(); + ThreadPoolJob* job = 0; - for (int i = 0; i < jobs.size(); ++i) - { - job = (ThreadPoolJob*) jobs [i]; + for (int i = 0; i < jobs.size(); ++i) + { + job = (ThreadPoolJob*) jobs [i]; - if (job != 0 && ! (job->isActive || job->shouldStop)) - break; + if (job != 0 && ! (job->isActive || job->shouldStop)) + break; - job = 0; - } + job = 0; + } - if (job != 0) - { - job->isActive = true; - lock.exit(); + if (job != 0) + { + job->isActive = true; + lock.exit(); - JUCE_TRY - { - ThreadPoolJob::JobStatus result = job->runJob(); + JUCE_TRY + { + ThreadPoolJob::JobStatus result = job->runJob(); - lastJobEndTime = Time::getApproximateMillisecondCounter(); + lastJobEndTime = Time::getApproximateMillisecondCounter(); - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (jobs.contains (job)) - { - job->isActive = false; + if (jobs.contains (job)) + { + job->isActive = false; - if (result != ThreadPoolJob::jobNeedsRunningAgain || job->shouldStop) - { - job->pool = 0; - job->shouldStop = true; - jobs.removeValue (job); + if (result != ThreadPoolJob::jobNeedsRunningAgain || job->shouldStop) + { + job->pool = 0; + job->shouldStop = true; + jobs.removeValue (job); - if (result == ThreadPoolJob::jobHasFinishedAndShouldBeDeleted) - delete job; + if (result == ThreadPoolJob::jobHasFinishedAndShouldBeDeleted) + delete job; - jobFinishedSignal.signal(); - } - else - { - // move the job to the end of the queue if it wants another go - jobs.move (jobs.indexOf (job), -1); - } - } - } + jobFinishedSignal.signal(); + } + else + { + // move the job to the end of the queue if it wants another go + jobs.move (jobs.indexOf (job), -1); + } + } + } #if JUCE_CATCH_UNHANDLED_EXCEPTIONS - catch (...) - { - lock.enter(); - jobs.removeValue (job); - lock.exit(); - } + catch (...) + { + lock.enter(); + jobs.removeValue (job); + lock.exit(); + } #endif - } - else - { - lock.exit(); + } + else + { + lock.exit(); - if (threadStopTimeout > 0 - && Time::getApproximateMillisecondCounter() > lastJobEndTime + threadStopTimeout) - { - const ScopedLock sl (lock); + if (threadStopTimeout > 0 + && Time::getApproximateMillisecondCounter() > lastJobEndTime + threadStopTimeout) + { + const ScopedLock sl (lock); - if (jobs.size() == 0) - for (int i = numThreads; --i >= 0;) - threads[i]->signalThreadShouldExit(); - } - else - { - return false; - } - } + if (jobs.size() == 0) + for (int i = numThreads; --i >= 0;) + threads[i]->signalThreadShouldExit(); + } + else + { + return false; + } + } - return true; + return true; } END_JUCE_NAMESPACE @@ -16197,111 +15957,111 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE TimeSliceThread::TimeSliceThread (const String& threadName) - : Thread (threadName), - index (0), - clientBeingCalled (0), - clientsChanged (false) + : Thread (threadName), + index (0), + clientBeingCalled (0), + clientsChanged (false) { } TimeSliceThread::~TimeSliceThread() { - stopThread (2000); + stopThread (2000); } void TimeSliceThread::addTimeSliceClient (TimeSliceClient* const client) { - const ScopedLock sl (listLock); - clients.addIfNotAlreadyThere (client); - clientsChanged = true; - notify(); + const ScopedLock sl (listLock); + clients.addIfNotAlreadyThere (client); + clientsChanged = true; + notify(); } void TimeSliceThread::removeTimeSliceClient (TimeSliceClient* const client) { - const ScopedLock sl1 (listLock); - clientsChanged = true; + const ScopedLock sl1 (listLock); + clientsChanged = true; - // if there's a chance we're in the middle of calling this client, we need to - // also lock the outer lock.. - if (clientBeingCalled == client) - { - const ScopedUnlock ul (listLock); // unlock first to get the order right.. + // if there's a chance we're in the middle of calling this client, we need to + // also lock the outer lock.. + if (clientBeingCalled == client) + { + const ScopedUnlock ul (listLock); // unlock first to get the order right.. - const ScopedLock sl2 (callbackLock); - const ScopedLock sl3 (listLock); + const ScopedLock sl2 (callbackLock); + const ScopedLock sl3 (listLock); - clients.removeValue (client); - } - else - { - clients.removeValue (client); - } + clients.removeValue (client); + } + else + { + clients.removeValue (client); + } } int TimeSliceThread::getNumClients() const { - return clients.size(); + return clients.size(); } TimeSliceClient* TimeSliceThread::getClient (const int i) const { - const ScopedLock sl (listLock); - return clients [i]; + const ScopedLock sl (listLock); + return clients [i]; } void TimeSliceThread::run() { - int numCallsSinceBusy = 0; + int numCallsSinceBusy = 0; - while (! threadShouldExit()) - { - int timeToWait = 500; + while (! threadShouldExit()) + { + int timeToWait = 500; - { - const ScopedLock sl (callbackLock); + { + const ScopedLock sl (callbackLock); - { - const ScopedLock sl2 (listLock); + { + const ScopedLock sl2 (listLock); - if (clients.size() > 0) - { - index = (index + 1) % clients.size(); + if (clients.size() > 0) + { + index = (index + 1) % clients.size(); - clientBeingCalled = clients [index]; - } - else - { - index = 0; - clientBeingCalled = 0; - } + clientBeingCalled = clients [index]; + } + else + { + index = 0; + clientBeingCalled = 0; + } - if (clientsChanged) - { - clientsChanged = false; - numCallsSinceBusy = 0; - } - } + if (clientsChanged) + { + clientsChanged = false; + numCallsSinceBusy = 0; + } + } - if (clientBeingCalled != 0) - { - if (clientBeingCalled->useTimeSlice()) - numCallsSinceBusy = 0; - else - ++numCallsSinceBusy; + if (clientBeingCalled != 0) + { + if (clientBeingCalled->useTimeSlice()) + numCallsSinceBusy = 0; + else + ++numCallsSinceBusy; - if (numCallsSinceBusy >= clients.size()) - timeToWait = 500; - else if (index == 0) - timeToWait = 1; // throw in an occasional pause, to stop everything locking up - else - timeToWait = 0; - } - } + if (numCallsSinceBusy >= clients.size()) + timeToWait = 500; + else if (index == 0) + timeToWait = 1; // throw in an occasional pause, to stop everything locking up + else + timeToWait = 0; + } + } - if (timeToWait > 0) - wait (timeToWait); - } + if (timeToWait > 0) + wait (timeToWait); + } } END_JUCE_NAMESPACE @@ -16316,740 +16076,740 @@ BEGIN_JUCE_NAMESPACE class ValueTreeSetPropertyAction : public UndoableAction { public: - ValueTreeSetPropertyAction (const ValueTree::SharedObjectPtr& target_, const var::identifier& name_, - const var& newValue_, const bool isAddingNewProperty_, const bool isDeletingProperty_) - : target (target_), name (name_), newValue (newValue_), - isAddingNewProperty (isAddingNewProperty_), - isDeletingProperty (isDeletingProperty_) - { - if (! isAddingNewProperty) - oldValue = target_->getProperty (name_); - } + ValueTreeSetPropertyAction (const ValueTree::SharedObjectPtr& target_, const var::identifier& name_, + const var& newValue_, const bool isAddingNewProperty_, const bool isDeletingProperty_) + : target (target_), name (name_), newValue (newValue_), + isAddingNewProperty (isAddingNewProperty_), + isDeletingProperty (isDeletingProperty_) + { + if (! isAddingNewProperty) + oldValue = target_->getProperty (name_); + } - ~ValueTreeSetPropertyAction() {} + ~ValueTreeSetPropertyAction() {} - bool perform() - { - jassert (! (isAddingNewProperty && target->hasProperty (name))); + bool perform() + { + jassert (! (isAddingNewProperty && target->hasProperty (name))); - if (isDeletingProperty) - target->removeProperty (name, 0); - else - target->setProperty (name, newValue, 0); + if (isDeletingProperty) + target->removeProperty (name, 0); + else + target->setProperty (name, newValue, 0); - return true; - } + return true; + } - bool undo() - { - if (isAddingNewProperty) - target->removeProperty (name, 0); - else - target->setProperty (name, oldValue, 0); + bool undo() + { + if (isAddingNewProperty) + target->removeProperty (name, 0); + else + target->setProperty (name, oldValue, 0); - return true; - } + return true; + } - int getSizeInUnits() - { - return 32; //xxx should be more accurate - } + int getSizeInUnits() + { + return 32; //xxx should be more accurate + } private: - const ValueTree::SharedObjectPtr target; - const var::identifier name; - const var newValue; - var oldValue; - const bool isAddingNewProperty, isDeletingProperty; + const ValueTree::SharedObjectPtr target; + const var::identifier name; + const var newValue; + var oldValue; + const bool isAddingNewProperty, isDeletingProperty; - ValueTreeSetPropertyAction (const ValueTreeSetPropertyAction&); - const ValueTreeSetPropertyAction& operator= (const ValueTreeSetPropertyAction&); + ValueTreeSetPropertyAction (const ValueTreeSetPropertyAction&); + const ValueTreeSetPropertyAction& operator= (const ValueTreeSetPropertyAction&); }; class ValueTreeChildChangeAction : public UndoableAction { public: - ValueTreeChildChangeAction (const ValueTree::SharedObjectPtr& target_, const int childIndex_, - const ValueTree::SharedObjectPtr& newChild_) - : target (target_), - child (newChild_ != 0 ? newChild_ : target_->children [childIndex_]), - childIndex (childIndex_), - isDeleting (newChild_ == 0) - { - jassert (child != 0); - } + ValueTreeChildChangeAction (const ValueTree::SharedObjectPtr& target_, const int childIndex_, + const ValueTree::SharedObjectPtr& newChild_) + : target (target_), + child (newChild_ != 0 ? newChild_ : target_->children [childIndex_]), + childIndex (childIndex_), + isDeleting (newChild_ == 0) + { + jassert (child != 0); + } - ~ValueTreeChildChangeAction() {} + ~ValueTreeChildChangeAction() {} - bool perform() - { - if (isDeleting) - target->removeChild (childIndex, 0); - else - target->addChild (child, childIndex, 0); + bool perform() + { + if (isDeleting) + target->removeChild (childIndex, 0); + else + target->addChild (child, childIndex, 0); - return true; - } + return true; + } - bool undo() - { - if (isDeleting) - target->addChild (child, childIndex, 0); - else - target->removeChild (childIndex, 0); + bool undo() + { + if (isDeleting) + target->addChild (child, childIndex, 0); + else + target->removeChild (childIndex, 0); - return true; - } + return true; + } - int getSizeInUnits() - { - return 32; //xxx should be more accurate - } + int getSizeInUnits() + { + return 32; //xxx should be more accurate + } private: - const ValueTree::SharedObjectPtr target, child; - const int childIndex; - const bool isDeleting; + const ValueTree::SharedObjectPtr target, child; + const int childIndex; + const bool isDeleting; - ValueTreeChildChangeAction (const ValueTreeChildChangeAction&); - const ValueTreeChildChangeAction& operator= (const ValueTreeChildChangeAction&); + ValueTreeChildChangeAction (const ValueTreeChildChangeAction&); + const ValueTreeChildChangeAction& operator= (const ValueTreeChildChangeAction&); }; ValueTree::SharedObject::SharedObject (const String& type_) - : type (type_), parent (0) + : type (type_), parent (0) { } ValueTree::SharedObject::SharedObject (const SharedObject& other) - : type (other.type), parent (0) + : type (other.type), parent (0) { - int i; - for (i = 0; i < other.properties.size(); ++i) - { - const Property* const p = other.properties.getUnchecked(i); - properties.add (new Property (p->name, p->value)); - } + int i; + for (i = 0; i < other.properties.size(); ++i) + { + const Property* const p = other.properties.getUnchecked(i); + properties.add (new Property (p->name, p->value)); + } - for (i = 0; i < other.children.size(); ++i) - children.add (new SharedObject (*other.children.getUnchecked(i))); + for (i = 0; i < other.children.size(); ++i) + children.add (new SharedObject (*other.children.getUnchecked(i))); } ValueTree::SharedObject::~SharedObject() { - jassert (parent == 0); // this should never happen unless something isn't obeying the ref-counting! + jassert (parent == 0); // this should never happen unless something isn't obeying the ref-counting! - for (int i = children.size(); --i >= 0;) - { - const SharedObjectPtr c (children.getUnchecked(i)); - c->parent = 0; - children.remove (i); - c->sendParentChangeMessage(); - } + for (int i = children.size(); --i >= 0;) + { + const SharedObjectPtr c (children.getUnchecked(i)); + c->parent = 0; + children.remove (i); + c->sendParentChangeMessage(); + } } ValueTree::SharedObject::Property::Property (const var::identifier& name_, const var& value_) - : name (name_), value (value_) + : name (name_), value (value_) { } void ValueTree::deliverPropertyChangeMessage (const var::identifier& property) { - ValueTree v (object); + ValueTree v (object); - for (int i = listeners.size(); --i >= 0;) - { - ValueTree::Listener* const l = listeners[i]; - if (l != 0) - l->valueTreePropertyChanged (v, property); - } + for (int i = listeners.size(); --i >= 0;) + { + ValueTree::Listener* const l = listeners[i]; + if (l != 0) + l->valueTreePropertyChanged (v, property); + } } void ValueTree::SharedObject::sendPropertyChangeMessage (const var::identifier& property) { - for (int i = valueTreesWithListeners.size(); --i >= 0;) - { - ValueTree* const v = valueTreesWithListeners[i]; - if (v != 0) - v->deliverPropertyChangeMessage (property); - } + for (int i = valueTreesWithListeners.size(); --i >= 0;) + { + ValueTree* const v = valueTreesWithListeners[i]; + if (v != 0) + v->deliverPropertyChangeMessage (property); + } } void ValueTree::deliverChildChangeMessage() { - ValueTree v (object); + ValueTree v (object); - for (int i = listeners.size(); --i >= 0;) - { - ValueTree::Listener* const l = listeners[i]; - if (l != 0) - l->valueTreeChildrenChanged (v); - } + for (int i = listeners.size(); --i >= 0;) + { + ValueTree::Listener* const l = listeners[i]; + if (l != 0) + l->valueTreeChildrenChanged (v); + } } void ValueTree::SharedObject::sendChildChangeMessage() { - for (int i = valueTreesWithListeners.size(); --i >= 0;) - { - ValueTree* const v = valueTreesWithListeners[i]; - if (v != 0) - v->deliverChildChangeMessage(); - } + for (int i = valueTreesWithListeners.size(); --i >= 0;) + { + ValueTree* const v = valueTreesWithListeners[i]; + if (v != 0) + v->deliverChildChangeMessage(); + } } void ValueTree::deliverParentChangeMessage() { - ValueTree v (object); + ValueTree v (object); - for (int i = listeners.size(); --i >= 0;) - { - ValueTree::Listener* const l = listeners[i]; - if (l != 0) - l->valueTreeParentChanged (v); - } + for (int i = listeners.size(); --i >= 0;) + { + ValueTree::Listener* const l = listeners[i]; + if (l != 0) + l->valueTreeParentChanged (v); + } } void ValueTree::SharedObject::sendParentChangeMessage() { - int i; - for (i = children.size(); --i >= 0;) - { - SharedObject* const t = children[i]; - if (t != 0) - t->sendParentChangeMessage(); - } + int i; + for (i = children.size(); --i >= 0;) + { + SharedObject* const t = children[i]; + if (t != 0) + t->sendParentChangeMessage(); + } - for (i = valueTreesWithListeners.size(); --i >= 0;) - { - ValueTree* const v = valueTreesWithListeners[i]; - if (v != 0) - v->deliverParentChangeMessage(); - } + for (i = valueTreesWithListeners.size(); --i >= 0;) + { + ValueTree* const v = valueTreesWithListeners[i]; + if (v != 0) + v->deliverParentChangeMessage(); + } } const var ValueTree::SharedObject::getProperty (const var::identifier& name) const { - for (int i = properties.size(); --i >= 0;) - { - const Property* const p = properties.getUnchecked(i); - if (p->name == name) - return p->value; - } + for (int i = properties.size(); --i >= 0;) + { + const Property* const p = properties.getUnchecked(i); + if (p->name == name) + return p->value; + } - return var(); + return var(); } void ValueTree::SharedObject::setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager) { - for (int i = properties.size(); --i >= 0;) - { - Property* const p = properties.getUnchecked(i); + for (int i = properties.size(); --i >= 0;) + { + Property* const p = properties.getUnchecked(i); - if (p->name == name) - { - if (p->value != newValue) - { - if (undoManager == 0) - { - p->value = newValue; - sendPropertyChangeMessage (name); - } - else - { - undoManager->perform (new ValueTreeSetPropertyAction (this, name, newValue, false, false)); - } - } + if (p->name == name) + { + if (p->value != newValue) + { + if (undoManager == 0) + { + p->value = newValue; + sendPropertyChangeMessage (name); + } + else + { + undoManager->perform (new ValueTreeSetPropertyAction (this, name, newValue, false, false)); + } + } - return; - } - } + return; + } + } - if (undoManager == 0) - { - properties.add (new Property (name, newValue)); - sendPropertyChangeMessage (name); - } - else - { - undoManager->perform (new ValueTreeSetPropertyAction (this, name, newValue, true, false)); - } + if (undoManager == 0) + { + properties.add (new Property (name, newValue)); + sendPropertyChangeMessage (name); + } + else + { + undoManager->perform (new ValueTreeSetPropertyAction (this, name, newValue, true, false)); + } } bool ValueTree::SharedObject::hasProperty (const var::identifier& name) const { - for (int i = properties.size(); --i >= 0;) - if (properties.getUnchecked(i)->name == name) - return true; + for (int i = properties.size(); --i >= 0;) + if (properties.getUnchecked(i)->name == name) + return true; - return false; + return false; } void ValueTree::SharedObject::removeProperty (const var::identifier& name, UndoManager* const undoManager) { - for (int i = properties.size(); --i >= 0;) - { - Property* const p = properties.getUnchecked(i); + for (int i = properties.size(); --i >= 0;) + { + Property* const p = properties.getUnchecked(i); - if (p->name == name) - { - if (undoManager == 0) - { - properties.remove (i); - sendPropertyChangeMessage (name); - } - else - { - undoManager->perform (new ValueTreeSetPropertyAction (this, name, var(), false, true)); - } + if (p->name == name) + { + if (undoManager == 0) + { + properties.remove (i); + sendPropertyChangeMessage (name); + } + else + { + undoManager->perform (new ValueTreeSetPropertyAction (this, name, var(), false, true)); + } - break; - } - } + break; + } + } } void ValueTree::SharedObject::removeAllProperties (UndoManager* const undoManager) { - if (undoManager == 0) - { - while (properties.size() > 0) - { - const var::identifier name (properties.getLast()->name); - properties.removeLast(); - sendPropertyChangeMessage (name); - } - } - else - { - for (int i = properties.size(); --i >= 0;) - undoManager->perform (new ValueTreeSetPropertyAction (this, properties.getUnchecked(i)->name, var(), false, true)); - } + if (undoManager == 0) + { + while (properties.size() > 0) + { + const var::identifier name (properties.getLast()->name); + properties.removeLast(); + sendPropertyChangeMessage (name); + } + } + else + { + for (int i = properties.size(); --i >= 0;) + undoManager->perform (new ValueTreeSetPropertyAction (this, properties.getUnchecked(i)->name, var(), false, true)); + } } ValueTree ValueTree::SharedObject::getChildWithName (const String& typeToMatch) const { - for (int i = 0; i < children.size(); ++i) - if (children.getUnchecked(i)->type == typeToMatch) - return (SharedObject*) children.getUnchecked(i); + for (int i = 0; i < children.size(); ++i) + if (children.getUnchecked(i)->type == typeToMatch) + return (SharedObject*) children.getUnchecked(i); - return (SharedObject*) 0; + return (SharedObject*) 0; } ValueTree ValueTree::SharedObject::getChildWithProperty (const var::identifier& propertyName, const var& propertyValue) const { - for (int i = 0; i < children.size(); ++i) - if (children.getUnchecked(i)->getProperty (propertyName) == propertyValue) - return (SharedObject*) children.getUnchecked(i); + for (int i = 0; i < children.size(); ++i) + if (children.getUnchecked(i)->getProperty (propertyName) == propertyValue) + return (SharedObject*) children.getUnchecked(i); - return (SharedObject*) 0; + return (SharedObject*) 0; } bool ValueTree::SharedObject::isAChildOf (const SharedObject* const possibleParent) const { - const SharedObject* p = parent; + const SharedObject* p = parent; - while (p != 0) - { - if (p == possibleParent) - return true; + while (p != 0) + { + if (p == possibleParent) + return true; - p = p->parent; - } + p = p->parent; + } - return false; + return false; } void ValueTree::SharedObject::addChild (SharedObject* child, int index, UndoManager* const undoManager) { - if (child != 0 && child->parent != this) - { - if (child != this && ! isAChildOf (child)) - { - // You should always make sure that a child is removed from its previous parent before - // adding it somewhere else - otherwise, it's ambiguous as to whether a different - // undomanager should be used when removing it from its current parent.. - jassert (child->parent == 0); + if (child != 0 && child->parent != this) + { + if (child != this && ! isAChildOf (child)) + { + // You should always make sure that a child is removed from its previous parent before + // adding it somewhere else - otherwise, it's ambiguous as to whether a different + // undomanager should be used when removing it from its current parent.. + jassert (child->parent == 0); - if (child->parent != 0) - { - jassert (child->parent->children.indexOf (child) >= 0); - child->parent->removeChild (child->parent->children.indexOf (child), undoManager); - } + if (child->parent != 0) + { + jassert (child->parent->children.indexOf (child) >= 0); + child->parent->removeChild (child->parent->children.indexOf (child), undoManager); + } - if (undoManager == 0) - { - children.insert (index, child); - child->parent = this; - sendChildChangeMessage(); - child->sendParentChangeMessage(); - } - else - { - undoManager->perform (new ValueTreeChildChangeAction (this, index, child)); - } - } - else - { - // You're attempting to create a recursive loop! A node - // can't be a child of one of its own children! - jassertfalse - } - } + if (undoManager == 0) + { + children.insert (index, child); + child->parent = this; + sendChildChangeMessage(); + child->sendParentChangeMessage(); + } + else + { + undoManager->perform (new ValueTreeChildChangeAction (this, index, child)); + } + } + else + { + // You're attempting to create a recursive loop! A node + // can't be a child of one of its own children! + jassertfalse + } + } } void ValueTree::SharedObject::removeChild (const int childIndex, UndoManager* const undoManager) { - const SharedObjectPtr child (children [childIndex]); + const SharedObjectPtr child (children [childIndex]); - if (child != 0) - { - if (undoManager == 0) - { - children.remove (childIndex); - child->parent = 0; - sendChildChangeMessage(); - child->sendParentChangeMessage(); - } - else - { - undoManager->perform (new ValueTreeChildChangeAction (this, childIndex, 0)); - } - } + if (child != 0) + { + if (undoManager == 0) + { + children.remove (childIndex); + child->parent = 0; + sendChildChangeMessage(); + child->sendParentChangeMessage(); + } + else + { + undoManager->perform (new ValueTreeChildChangeAction (this, childIndex, 0)); + } + } } void ValueTree::SharedObject::removeAllChildren (UndoManager* const undoManager) { - while (children.size() > 0) - removeChild (children.size() - 1, 0); + while (children.size() > 0) + removeChild (children.size() - 1, 0); } ValueTree::ValueTree (const String& type_) - : object (new ValueTree::SharedObject (type_)) + : object (new ValueTree::SharedObject (type_)) { - jassert (type_.isNotEmpty()); // All objects should be given a sensible type name! + jassert (type_.isNotEmpty()); // All objects should be given a sensible type name! } ValueTree::ValueTree (SharedObject* const object_) - : object (object_) + : object (object_) { } ValueTree::ValueTree (const ValueTree& other) - : object (other.object) + : object (other.object) { } const ValueTree& ValueTree::operator= (const ValueTree& other) { - if (listeners.size() > 0) - { - if (object != 0) - object->valueTreesWithListeners.removeValue (this); + if (listeners.size() > 0) + { + if (object != 0) + object->valueTreesWithListeners.removeValue (this); - if (other.object != 0) - other.object->valueTreesWithListeners.add (this); - } + if (other.object != 0) + other.object->valueTreesWithListeners.add (this); + } - object = other.object; + object = other.object; - return *this; + return *this; } ValueTree::~ValueTree() { - if (listeners.size() > 0 && object != 0) - object->valueTreesWithListeners.removeValue (this); + if (listeners.size() > 0 && object != 0) + object->valueTreesWithListeners.removeValue (this); } bool ValueTree::operator== (const ValueTree& other) const { - return object == other.object; + return object == other.object; } bool ValueTree::operator!= (const ValueTree& other) const { - return object != other.object; + return object != other.object; } ValueTree ValueTree::createCopy() const { - return ValueTree (object != 0 ? new SharedObject (*object) : 0); + return ValueTree (object != 0 ? new SharedObject (*object) : 0); } bool ValueTree::hasType (const String& typeName) const { - return object != 0 && object->type == typeName; + return object != 0 && object->type == typeName; } const String ValueTree::getType() const { - return object != 0 ? object->type : String::empty; + return object != 0 ? object->type : String::empty; } ValueTree ValueTree::getParent() const { - return object != 0 ? ValueTree (object->parent) : ValueTree ((SharedObject*) 0); + return object != 0 ? ValueTree (object->parent) : ValueTree ((SharedObject*) 0); } const var ValueTree::operator[] (const var::identifier& name) const { - return object == 0 ? var() : object->getProperty (name); + return object == 0 ? var() : object->getProperty (name); } const var ValueTree::getProperty (const var::identifier& name) const { - return object == 0 ? var() : object->getProperty (name); + return object == 0 ? var() : object->getProperty (name); } void ValueTree::setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager) { - jassert (name.name.isNotEmpty()); + jassert (name.name.isNotEmpty()); - if (object != 0 && name.name.isNotEmpty()) - object->setProperty (name, newValue, undoManager); + if (object != 0 && name.name.isNotEmpty()) + object->setProperty (name, newValue, undoManager); } bool ValueTree::hasProperty (const var::identifier& name) const { - return object != 0 && object->hasProperty (name); + return object != 0 && object->hasProperty (name); } void ValueTree::removeProperty (const var::identifier& name, UndoManager* const undoManager) { - if (object != 0) - object->removeProperty (name, undoManager); + if (object != 0) + object->removeProperty (name, undoManager); } void ValueTree::removeAllProperties (UndoManager* const undoManager) { - if (object != 0) - object->removeAllProperties (undoManager); + if (object != 0) + object->removeAllProperties (undoManager); } int ValueTree::getNumProperties() const { - return object == 0 ? 0 : object->properties.size(); + return object == 0 ? 0 : object->properties.size(); } const var::identifier ValueTree::getPropertyName (int index) const { - const SharedObject::Property* const p = (object == 0) ? 0 : object->properties [index]; - return p != 0 ? p->name : var::identifier (String::empty); + const SharedObject::Property* const p = (object == 0) ? 0 : object->properties [index]; + return p != 0 ? p->name : var::identifier (String::empty); } class ValueTreePropertyValueSource : public Value::ValueSource, - public ValueTree::Listener + public ValueTree::Listener { public: - ValueTreePropertyValueSource (const ValueTree& tree_, - const var::identifier& property_, - UndoManager* const undoManager_) - : tree (tree_), - property (property_), - undoManager (undoManager_) - { - tree.addListener (this); - } + ValueTreePropertyValueSource (const ValueTree& tree_, + const var::identifier& property_, + UndoManager* const undoManager_) + : tree (tree_), + property (property_), + undoManager (undoManager_) + { + tree.addListener (this); + } - ~ValueTreePropertyValueSource() - { - tree.removeListener (this); - } + ~ValueTreePropertyValueSource() + { + tree.removeListener (this); + } - const var getValue() const - { - return tree [property]; - } + const var getValue() const + { + return tree [property]; + } - void setValue (const var& newValue) - { - tree.setProperty (property, newValue, undoManager); - } + void setValue (const var& newValue) + { + tree.setProperty (property, newValue, undoManager); + } - void valueTreePropertyChanged (ValueTree& tree, const var::identifier& changedProperty) - { - if (property == changedProperty) - sendChangeMessage (false); - } + void valueTreePropertyChanged (ValueTree& tree, const var::identifier& changedProperty) + { + if (property == changedProperty) + sendChangeMessage (false); + } - void valueTreeChildrenChanged (ValueTree& tree) {} - void valueTreeParentChanged (ValueTree& tree) {} + void valueTreeChildrenChanged (ValueTree& tree) {} + void valueTreeParentChanged (ValueTree& tree) {} private: - ValueTree tree; - const var::identifier property; - UndoManager* const undoManager; + ValueTree tree; + const var::identifier property; + UndoManager* const undoManager; - const ValueTreePropertyValueSource& operator= (const ValueTreePropertyValueSource&); + const ValueTreePropertyValueSource& operator= (const ValueTreePropertyValueSource&); }; Value ValueTree::getPropertyAsValue (const var::identifier& name, UndoManager* const undoManager) const { - return Value (new ValueTreePropertyValueSource (*this, name, undoManager)); + return Value (new ValueTreePropertyValueSource (*this, name, undoManager)); } int ValueTree::getNumChildren() const { - return object == 0 ? 0 : object->children.size(); + return object == 0 ? 0 : object->children.size(); } ValueTree ValueTree::getChild (int index) const { - return object != 0 ? (SharedObject*) object->children [index] : ValueTree ((SharedObject*) 0); + return object != 0 ? (SharedObject*) object->children [index] : ValueTree ((SharedObject*) 0); } ValueTree ValueTree::getChildWithName (const String& type) const { - return object != 0 ? object->getChildWithName (type) : ValueTree ((SharedObject*) 0); + return object != 0 ? object->getChildWithName (type) : ValueTree ((SharedObject*) 0); } ValueTree ValueTree::getChildWithProperty (const var::identifier& propertyName, const var& propertyValue) const { - return object != 0 ? object->getChildWithProperty (propertyName, propertyValue) : ValueTree ((SharedObject*) 0); + return object != 0 ? object->getChildWithProperty (propertyName, propertyValue) : ValueTree ((SharedObject*) 0); } bool ValueTree::isAChildOf (const ValueTree& possibleParent) const { - return object != 0 && object->isAChildOf (possibleParent.object); + return object != 0 && object->isAChildOf (possibleParent.object); } void ValueTree::addChild (ValueTree child, int index, UndoManager* const undoManager) { - if (object != 0) - object->addChild (child.object, index, undoManager); + if (object != 0) + object->addChild (child.object, index, undoManager); } void ValueTree::removeChild (const int childIndex, UndoManager* const undoManager) { - if (object != 0) - object->removeChild (childIndex, undoManager); + if (object != 0) + object->removeChild (childIndex, undoManager); } void ValueTree::removeChild (ValueTree& child, UndoManager* const undoManager) { - if (object != 0) - object->removeChild (object->children.indexOf (child.object), undoManager); + if (object != 0) + object->removeChild (object->children.indexOf (child.object), undoManager); } void ValueTree::removeAllChildren (UndoManager* const undoManager) { - if (object != 0) - object->removeAllChildren (undoManager); + if (object != 0) + object->removeAllChildren (undoManager); } void ValueTree::addListener (Listener* listener) { - if (listener != 0) - { - if (listeners.size() == 0 && object != 0) - object->valueTreesWithListeners.add (this); + if (listener != 0) + { + if (listeners.size() == 0 && object != 0) + object->valueTreesWithListeners.add (this); - listeners.add (listener); - } + listeners.add (listener); + } } void ValueTree::removeListener (Listener* listener) { - listeners.removeValue (listener); + listeners.removeValue (listener); - if (listeners.size() == 0 && object != 0) - object->valueTreesWithListeners.removeValue (this); + if (listeners.size() == 0 && object != 0) + object->valueTreesWithListeners.removeValue (this); } XmlElement* ValueTree::SharedObject::createXml() const { - XmlElement* xml = new XmlElement (type); + XmlElement* xml = new XmlElement (type); - int i; - for (i = 0; i < properties.size(); ++i) - { - const Property* const p = properties.getUnchecked(i); + int i; + for (i = 0; i < properties.size(); ++i) + { + const Property* const p = properties.getUnchecked(i); - jassert (! p->value.isObject()); // DynamicObjects can't be stored as XML! + jassert (! p->value.isObject()); // DynamicObjects can't be stored as XML! - xml->setAttribute (p->name.name, p->value.toString()); - } + xml->setAttribute (p->name.name, p->value.toString()); + } - for (i = 0; i < children.size(); ++i) - xml->addChildElement (children.getUnchecked(i)->createXml()); + for (i = 0; i < children.size(); ++i) + xml->addChildElement (children.getUnchecked(i)->createXml()); - return xml; + return xml; } XmlElement* ValueTree::createXml() const { - return object != 0 ? object->createXml() : 0; + return object != 0 ? object->createXml() : 0; } ValueTree ValueTree::fromXml (const XmlElement& xml) { - ValueTree v (xml.getTagName()); + ValueTree v (xml.getTagName()); - const int numAtts = xml.getNumAttributes(); // xxx inefficient - should write an att iterator.. + const int numAtts = xml.getNumAttributes(); // xxx inefficient - should write an att iterator.. - for (int i = 0; i < numAtts; ++i) - v.setProperty (xml.getAttributeName (i), xml.getAttributeValue (i), 0); + for (int i = 0; i < numAtts; ++i) + v.setProperty (xml.getAttributeName (i), xml.getAttributeValue (i), 0); - forEachXmlChildElement (xml, e) - { - v.addChild (fromXml (*e), -1, 0); - } + forEachXmlChildElement (xml, e) + { + v.addChild (fromXml (*e), -1, 0); + } - return v; + return v; } void ValueTree::writeToStream (OutputStream& output) { - output.writeString (getType()); + output.writeString (getType()); - const int numProps = getNumProperties(); - output.writeCompressedInt (numProps); + const int numProps = getNumProperties(); + output.writeCompressedInt (numProps); - int i; - for (i = 0; i < numProps; ++i) - { - const var::identifier name (getPropertyName(i)); - output.writeString (name.name); - getProperty(name).writeToStream (output); - } + int i; + for (i = 0; i < numProps; ++i) + { + const var::identifier name (getPropertyName(i)); + output.writeString (name.name); + getProperty(name).writeToStream (output); + } - const int numChildren = getNumChildren(); - output.writeCompressedInt (numChildren); + const int numChildren = getNumChildren(); + output.writeCompressedInt (numChildren); - for (i = 0; i < numChildren; ++i) - getChild (i).writeToStream (output); + for (i = 0; i < numChildren; ++i) + getChild (i).writeToStream (output); } ValueTree ValueTree::readFromStream (InputStream& input) { - String type (input.readString()); + String type (input.readString()); - if (type.isEmpty()) - return ValueTree ((SharedObject*) 0); + if (type.isEmpty()) + return ValueTree ((SharedObject*) 0); - ValueTree v (type); + ValueTree v (type); - const int numProps = input.readCompressedInt(); + const int numProps = input.readCompressedInt(); - if (numProps < 0) - { - jassertfalse // trying to read corrupted data! - return v; - } + if (numProps < 0) + { + jassertfalse // trying to read corrupted data! + return v; + } - int i; - for (i = 0; i < numProps; ++i) - { - const String name (input.readString()); - jassert (name.isNotEmpty()); - const var value (var::readFromStream (input)); - v.setProperty (name, value, 0); - } + int i; + for (i = 0; i < numProps; ++i) + { + const String name (input.readString()); + jassert (name.isNotEmpty()); + const var value (var::readFromStream (input)); + v.setProperty (name, value, 0); + } - const int numChildren = input.readCompressedInt(); + const int numChildren = input.readCompressedInt(); - for (i = 0; i < numChildren; ++i) - v.addChild (readFromStream (input), -1, 0); + for (i = 0; i < numChildren; ++i) + v.addChild (readFromStream (input), -1, 0); - return v; + return v; } END_JUCE_NAMESPACE @@ -17069,173 +16829,178 @@ Value::ValueSource::~ValueSource() void Value::ValueSource::sendChangeMessage (const bool synchronous) { - if (synchronous) - { - for (int i = valuesWithListeners.size(); --i >= 0;) - { - Value* const v = valuesWithListeners[i]; + if (synchronous) + { + for (int i = valuesWithListeners.size(); --i >= 0;) + { + Value* const v = valuesWithListeners[i]; - if (v != 0) - v->callListeners(); - } - } - else - { - triggerAsyncUpdate(); - } + if (v != 0) + v->callListeners(); + } + } + else + { + triggerAsyncUpdate(); + } } void Value::ValueSource::handleAsyncUpdate() { - sendChangeMessage (true); + sendChangeMessage (true); } class SimpleValueSource : public Value::ValueSource { public: - SimpleValueSource() - { - } + SimpleValueSource() + { + } - SimpleValueSource (const var& initialValue) - : value (initialValue) - { - } + SimpleValueSource (const var& initialValue) + : value (initialValue) + { + } - ~SimpleValueSource() - { - } + ~SimpleValueSource() + { + } - const var getValue() const - { - return value; - } + const var getValue() const + { + return value; + } - void setValue (const var& newValue) - { - if (newValue != value) - { - value = newValue; - sendChangeMessage (false); - } - } + void setValue (const var& newValue) + { + if (newValue != value) + { + value = newValue; + sendChangeMessage (false); + } + } private: - var value; + var value; - SimpleValueSource (const SimpleValueSource&); - const SimpleValueSource& operator= (const SimpleValueSource&); + SimpleValueSource (const SimpleValueSource&); + const SimpleValueSource& operator= (const SimpleValueSource&); }; Value::Value() - : value (new SimpleValueSource()) + : value (new SimpleValueSource()) { } Value::Value (ValueSource* const value_) - : value (value_) + : value (value_) { - jassert (value_ != 0); + jassert (value_ != 0); } Value::Value (const var& initialValue) - : value (new SimpleValueSource (initialValue)) + : value (new SimpleValueSource (initialValue)) { } Value::Value (const Value& other) - : value (other.value) + : value (other.value) { } const Value& Value::operator= (const Value& other) { - value = other.value; - return *this; + value = other.value; + return *this; } Value::~Value() { - if (listeners.size() > 0) - value->valuesWithListeners.removeValue (this); + if (listeners.size() > 0) + value->valuesWithListeners.removeValue (this); } const var Value::getValue() const { - return value->getValue(); + return value->getValue(); } void Value::setValue (const var& newValue) { - value->setValue (newValue); + value->setValue (newValue); +} + +const String Value::toString() const +{ + return value->getValue().toString(); } const Value& Value::operator= (const var& newValue) { - value->setValue (newValue); - return *this; + value->setValue (newValue); + return *this; } void Value::referTo (const Value& valueToReferTo) { - if (valueToReferTo.value != value) - { - if (listeners.size() > 0) - { - value->valuesWithListeners.removeValue (this); - valueToReferTo.value->valuesWithListeners.add (this); - } + if (valueToReferTo.value != value) + { + if (listeners.size() > 0) + { + value->valuesWithListeners.removeValue (this); + valueToReferTo.value->valuesWithListeners.add (this); + } - value = valueToReferTo.value; - callListeners(); - } + value = valueToReferTo.value; + callListeners(); + } } bool Value::refersToSameSourceAs (const Value& other) const { - return value == other.value; + return value == other.value; } bool Value::operator== (const Value& other) const { - return value == other.value || value->getValue() == other.getValue(); + return value == other.value || value->getValue() == other.getValue(); } bool Value::operator!= (const Value& other) const { - return value != other.value && value->getValue() != other.getValue(); + return value != other.value && value->getValue() != other.getValue(); } void Value::addListener (Listener* const listener) { - if (listener != 0) - { - if (listeners.size() == 0) - value->valuesWithListeners.add (this); + if (listener != 0) + { + if (listeners.size() == 0) + value->valuesWithListeners.add (this); - listeners.add (listener); - } + listeners.add (listener); + } } void Value::removeListener (Listener* const listener) { - listeners.removeValue (listener); + listeners.removeValue (listener); - if (listeners.size() == 0) - value->valuesWithListeners.removeValue (this); + if (listeners.size() == 0) + value->valuesWithListeners.removeValue (this); } void Value::callListeners() { - Value valueCopy (*this); // Use a copy in case this object gets deleted by a callback + Value valueCopy (*this); // Use a copy in case this object gets deleted by a callback - for (int i = listeners.size(); --i >= 0;) - { - Listener* const l = listeners[i]; + for (int i = listeners.size(); --i >= 0;) + { + Listener* const l = listeners[i]; - if (l != 0) - l->valueChanged (valueCopy); - } + if (l != 0) + l->valueChanged (valueCopy); + } } END_JUCE_NAMESPACE @@ -17257,39 +17022,39 @@ void juce_setCurrentThreadName (const String& name); static JUCEApplication* appInstance = 0; JUCEApplication::JUCEApplication() - : appReturnValue (0), - stillInitialising (true), - appLock (0) + : appReturnValue (0), + stillInitialising (true), + appLock (0) { } JUCEApplication::~JUCEApplication() { - if (appLock != 0) - { - appLock->exit(); - delete appLock; - } + if (appLock != 0) + { + appLock->exit(); + delete appLock; + } } JUCEApplication* JUCEApplication::getInstance() throw() { - return appInstance; + return appInstance; } bool JUCEApplication::isInitialising() const throw() { - return stillInitialising; + return stillInitialising; } const String JUCEApplication::getApplicationVersion() { - return String::empty; + return String::empty; } bool JUCEApplication::moreThanOneInstanceAllowed() { - return true; + return true; } void JUCEApplication::anotherInstanceStarted (const String&) @@ -17298,177 +17063,177 @@ void JUCEApplication::anotherInstanceStarted (const String&) void JUCEApplication::systemRequestedQuit() { - quit(); + quit(); } void JUCEApplication::quit() { - MessageManager::getInstance()->stopDispatchLoop(); + MessageManager::getInstance()->stopDispatchLoop(); } void JUCEApplication::setApplicationReturnValue (const int newReturnValue) throw() { - appReturnValue = newReturnValue; + appReturnValue = newReturnValue; } void JUCEApplication::unhandledException (const std::exception*, - const String&, - const int) + const String&, + const int) { - jassertfalse + jassertfalse } void JUCEApplication::sendUnhandledException (const std::exception* const e, - const char* const sourceFile, - const int lineNumber) + const char* const sourceFile, + const int lineNumber) { - if (appInstance != 0) - appInstance->unhandledException (e, sourceFile, lineNumber); + if (appInstance != 0) + appInstance->unhandledException (e, sourceFile, lineNumber); } ApplicationCommandTarget* JUCEApplication::getNextCommandTarget() { - return 0; + return 0; } void JUCEApplication::getAllCommands (Array & commands) { - commands.add (StandardApplicationCommandIDs::quit); + commands.add (StandardApplicationCommandIDs::quit); } void JUCEApplication::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result) { - if (commandID == StandardApplicationCommandIDs::quit) - { - result.setInfo ("Quit", - "Quits the application", - "Application", - 0); + if (commandID == StandardApplicationCommandIDs::quit) + { + result.setInfo ("Quit", + "Quits the application", + "Application", + 0); - result.defaultKeypresses.add (KeyPress (T('q'), ModifierKeys::commandModifier, 0)); - } + result.defaultKeypresses.add (KeyPress (T('q'), ModifierKeys::commandModifier, 0)); + } } bool JUCEApplication::perform (const InvocationInfo& info) { - if (info.commandID == StandardApplicationCommandIDs::quit) - { - systemRequestedQuit(); - return true; - } + if (info.commandID == StandardApplicationCommandIDs::quit) + { + systemRequestedQuit(); + return true; + } - return false; + return false; } int JUCEApplication::main (String& commandLine, JUCEApplication* const app) { - if (! app->initialiseApp (commandLine)) - return 0; + if (! app->initialiseApp (commandLine)) + return 0; - // now loop until a quit message is received.. - JUCE_TRY - { - MessageManager::getInstance()->runDispatchLoop(); - } + // now loop until a quit message is received.. + JUCE_TRY + { + MessageManager::getInstance()->runDispatchLoop(); + } #if JUCE_CATCH_UNHANDLED_EXCEPTIONS - catch (const std::exception& e) - { - app->unhandledException (&e, __FILE__, __LINE__); - } - catch (...) - { - app->unhandledException (0, __FILE__, __LINE__); - } + catch (const std::exception& e) + { + app->unhandledException (&e, __FILE__, __LINE__); + } + catch (...) + { + app->unhandledException (0, __FILE__, __LINE__); + } #endif - return shutdownAppAndClearUp(); + return shutdownAppAndClearUp(); } bool JUCEApplication::initialiseApp (String& commandLine) { - jassert (appInstance == 0); - appInstance = this; + jassert (appInstance == 0); + appInstance = this; - commandLineParameters = commandLine.trim(); - commandLine = String::empty; + commandLineParameters = commandLine.trim(); + commandLine = String::empty; - initialiseJuce_GUI(); + initialiseJuce_GUI(); #if ! JUCE_IPHONE - jassert (appLock == 0); // initialiseApp must only be called once! + jassert (appLock == 0); // initialiseApp must only be called once! - if (! moreThanOneInstanceAllowed()) - { - appLock = new InterProcessLock ("juceAppLock_" + getApplicationName()); + if (! moreThanOneInstanceAllowed()) + { + appLock = new InterProcessLock ("juceAppLock_" + getApplicationName()); - if (! appLock->enter(0)) - { - MessageManager::broadcastMessage (getApplicationName() + "/" + commandLineParameters); + if (! appLock->enter(0)) + { + MessageManager::broadcastMessage (getApplicationName() + "/" + commandLineParameters); - delete appInstance; - appInstance = 0; + delete appInstance; + appInstance = 0; - DBG ("Another instance is running - quitting..."); - return false; - } - } + DBG ("Another instance is running - quitting..."); + return false; + } + } #endif - // let the app do its setting-up.. - initialise (commandLineParameters); + // let the app do its setting-up.. + initialise (commandLineParameters); - // register for broadcast new app messages - MessageManager::getInstance()->registerBroadcastListener (this); + // register for broadcast new app messages + MessageManager::getInstance()->registerBroadcastListener (this); - stillInitialising = false; - return true; + stillInitialising = false; + return true; } int JUCEApplication::shutdownAppAndClearUp() { - jassert (appInstance != 0); - JUCEApplication* const app = appInstance; - int returnValue = 0; + jassert (appInstance != 0); + JUCEApplication* const app = appInstance; + int returnValue = 0; - MessageManager::getInstance()->deregisterBroadcastListener (app); + MessageManager::getInstance()->deregisterBroadcastListener (app); - static bool reentrancyCheck = false; + static bool reentrancyCheck = false; - if (! reentrancyCheck) - { - reentrancyCheck = true; + if (! reentrancyCheck) + { + reentrancyCheck = true; - JUCE_TRY - { - // give the app a chance to clean up.. - app->shutdown(); - } + JUCE_TRY + { + // give the app a chance to clean up.. + app->shutdown(); + } #if JUCE_CATCH_UNHANDLED_EXCEPTIONS - catch (const std::exception& e) - { - app->unhandledException (&e, __FILE__, __LINE__); - } - catch (...) - { - app->unhandledException (0, __FILE__, __LINE__); - } + catch (const std::exception& e) + { + app->unhandledException (&e, __FILE__, __LINE__); + } + catch (...) + { + app->unhandledException (0, __FILE__, __LINE__); + } #endif - JUCE_TRY - { - shutdownJuce_GUI(); + JUCE_TRY + { + shutdownJuce_GUI(); - returnValue = app->getApplicationReturnValue(); + returnValue = app->getApplicationReturnValue(); - appInstance = 0; - delete app; - } - JUCE_CATCH_ALL_ASSERT + appInstance = 0; + delete app; + } + JUCE_CATCH_ALL_ASSERT - reentrancyCheck = false; - } + reentrancyCheck = false; + } - return returnValue; + return returnValue; } #if JUCE_IPHONE @@ -17480,92 +17245,92 @@ extern const char* juce_Argv0; #endif int JUCEApplication::main (int argc, char* argv[], - JUCEApplication* const newApp) + JUCEApplication* const newApp) { #if ! JUCE_WINDOWS - juce_Argv0 = argv[0]; + juce_Argv0 = argv[0]; #endif #if JUCE_IPHONE - const ScopedAutoReleasePool pool; - return juce_IPhoneMain (argc, argv, newApp); + const ScopedAutoReleasePool pool; + return juce_IPhoneMain (argc, argv, newApp); #else #if JUCE_MAC - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; #endif - String cmd; - for (int i = 1; i < argc; ++i) - cmd << String::fromUTF8 ((const uint8*) argv[i]) << T(' '); + String cmd; + for (int i = 1; i < argc; ++i) + cmd << String::fromUTF8 ((const uint8*) argv[i]) << T(' '); - return JUCEApplication::main (cmd, newApp); + return JUCEApplication::main (cmd, newApp); #endif } void JUCEApplication::actionListenerCallback (const String& message) { - if (message.startsWith (getApplicationName() + "/")) - anotherInstanceStarted (message.substring (getApplicationName().length() + 1)); + if (message.startsWith (getApplicationName() + "/")) + anotherInstanceStarted (message.substring (getApplicationName().length() + 1)); } static bool juceInitialisedGUI = false; void JUCE_PUBLIC_FUNCTION initialiseJuce_GUI() { - if (! juceInitialisedGUI) - { + if (! juceInitialisedGUI) + { #if JUCE_MAC || JUCE_IPHONE - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; #endif - juceInitialisedGUI = true; + juceInitialisedGUI = true; - initialiseJuce_NonGUI(); - MessageManager::getInstance(); - LookAndFeel::setDefaultLookAndFeel (0); - juce_setCurrentThreadName ("Juce Message Thread"); + initialiseJuce_NonGUI(); + MessageManager::getInstance(); + LookAndFeel::setDefaultLookAndFeel (0); + juce_setCurrentThreadName ("Juce Message Thread"); #if JUCE_WINDOWS && JUCE_DEBUG - // This section is just for catching people who mess up their project settings and - // turn RTTI off.. - try - { - TextButton tb (String::empty); - Component* c = &tb; + // This section is just for catching people who mess up their project settings and + // turn RTTI off.. + try + { + TextButton tb (String::empty); + Component* c = &tb; - // Got an exception here? Then TURN ON RTTI in your compiler settings!! - c = dynamic_cast (c); - } - catch (...) - { - // Ended up here? If so, TURN ON RTTI in your compiler settings!! And if you - // got as far as this catch statement, then why haven't you got exception catching - // turned on in the debugger??? - jassertfalse - } + // Got an exception here? Then TURN ON RTTI in your compiler settings!! + c = dynamic_cast (c); + } + catch (...) + { + // Ended up here? If so, TURN ON RTTI in your compiler settings!! And if you + // got as far as this catch statement, then why haven't you got exception catching + // turned on in the debugger??? + jassertfalse + } #endif - } + } } void JUCE_PUBLIC_FUNCTION shutdownJuce_GUI() { - if (juceInitialisedGUI) - { + if (juceInitialisedGUI) + { #if JUCE_MAC - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; #endif - { - DeletedAtShutdown::deleteAll(); + { + DeletedAtShutdown::deleteAll(); - LookAndFeel::clearDefaultLookAndFeel(); - } + LookAndFeel::clearDefaultLookAndFeel(); + } - delete MessageManager::getInstance(); + delete MessageManager::getInstance(); - shutdownJuce_NonGUI(); + shutdownJuce_NonGUI(); - juceInitialisedGUI = false; - } + juceInitialisedGUI = false; + } } END_JUCE_NAMESPACE @@ -17576,41 +17341,41 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ApplicationCommandInfo::ApplicationCommandInfo (const CommandID commandID_) throw() - : commandID (commandID_), - flags (0) + : commandID (commandID_), + flags (0) { } void ApplicationCommandInfo::setInfo (const String& shortName_, - const String& description_, - const String& categoryName_, - const int flags_) throw() + const String& description_, + const String& categoryName_, + const int flags_) throw() { - shortName = shortName_; - description = description_; - categoryName = categoryName_; - flags = flags_; + shortName = shortName_; + description = description_; + categoryName = categoryName_; + flags = flags_; } void ApplicationCommandInfo::setActive (const bool b) throw() { - if (b) - flags &= ~isDisabled; - else - flags |= isDisabled; + if (b) + flags &= ~isDisabled; + else + flags |= isDisabled; } void ApplicationCommandInfo::setTicked (const bool b) throw() { - if (b) - flags |= isTicked; - else - flags &= ~isTicked; + if (b) + flags |= isTicked; + else + flags &= ~isTicked; } void ApplicationCommandInfo::addDefaultKeypress (const int keyCode, const ModifierKeys& modifiers) throw() { - defaultKeypresses.add (KeyPress (keyCode, modifiers, 0)); + defaultKeypresses.add (KeyPress (keyCode, modifiers, 0)); } END_JUCE_NAMESPACE @@ -17621,298 +17386,297 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ApplicationCommandManager::ApplicationCommandManager() - : listeners (8), - firstTarget (0) + : firstTarget (0) { - keyMappings = new KeyPressMappingSet (this); + keyMappings = new KeyPressMappingSet (this); - Desktop::getInstance().addFocusChangeListener (this); + Desktop::getInstance().addFocusChangeListener (this); } ApplicationCommandManager::~ApplicationCommandManager() { - Desktop::getInstance().removeFocusChangeListener (this); - keyMappings = 0; + Desktop::getInstance().removeFocusChangeListener (this); + keyMappings = 0; } void ApplicationCommandManager::clearCommands() { - commands.clear(); - keyMappings->clearAllKeyPresses(); - triggerAsyncUpdate(); + commands.clear(); + keyMappings->clearAllKeyPresses(); + triggerAsyncUpdate(); } void ApplicationCommandManager::registerCommand (const ApplicationCommandInfo& newCommand) { - // zero isn't a valid command ID! - jassert (newCommand.commandID != 0); + // zero isn't a valid command ID! + jassert (newCommand.commandID != 0); - // the name isn't optional! - jassert (newCommand.shortName.isNotEmpty()); + // the name isn't optional! + jassert (newCommand.shortName.isNotEmpty()); - if (getCommandForID (newCommand.commandID) == 0) - { - ApplicationCommandInfo* const newInfo = new ApplicationCommandInfo (newCommand); - newInfo->flags &= ~ApplicationCommandInfo::isTicked; - commands.add (newInfo); + if (getCommandForID (newCommand.commandID) == 0) + { + ApplicationCommandInfo* const newInfo = new ApplicationCommandInfo (newCommand); + newInfo->flags &= ~ApplicationCommandInfo::isTicked; + commands.add (newInfo); - keyMappings->resetToDefaultMapping (newCommand.commandID); + keyMappings->resetToDefaultMapping (newCommand.commandID); - triggerAsyncUpdate(); - } - else - { - // trying to re-register the same command with different parameters? - jassert (newCommand.shortName == getCommandForID (newCommand.commandID)->shortName - && (newCommand.description == getCommandForID (newCommand.commandID)->description || newCommand.description.isEmpty()) - && newCommand.categoryName == getCommandForID (newCommand.commandID)->categoryName - && newCommand.defaultKeypresses == getCommandForID (newCommand.commandID)->defaultKeypresses - && (newCommand.flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor)) - == (getCommandForID (newCommand.commandID)->flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor))); - } + triggerAsyncUpdate(); + } + else + { + // trying to re-register the same command with different parameters? + jassert (newCommand.shortName == getCommandForID (newCommand.commandID)->shortName + && (newCommand.description == getCommandForID (newCommand.commandID)->description || newCommand.description.isEmpty()) + && newCommand.categoryName == getCommandForID (newCommand.commandID)->categoryName + && newCommand.defaultKeypresses == getCommandForID (newCommand.commandID)->defaultKeypresses + && (newCommand.flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor)) + == (getCommandForID (newCommand.commandID)->flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor))); + } } void ApplicationCommandManager::registerAllCommandsForTarget (ApplicationCommandTarget* target) { - if (target != 0) - { - Array commandIDs; - target->getAllCommands (commandIDs); + if (target != 0) + { + Array commandIDs; + target->getAllCommands (commandIDs); - for (int i = 0; i < commandIDs.size(); ++i) - { - ApplicationCommandInfo info (commandIDs.getUnchecked(i)); - target->getCommandInfo (info.commandID, info); + for (int i = 0; i < commandIDs.size(); ++i) + { + ApplicationCommandInfo info (commandIDs.getUnchecked(i)); + target->getCommandInfo (info.commandID, info); - registerCommand (info); - } - } + registerCommand (info); + } + } } void ApplicationCommandManager::removeCommand (const CommandID commandID) { - for (int i = commands.size(); --i >= 0;) - { - if (commands.getUnchecked (i)->commandID == commandID) - { - commands.remove (i); - triggerAsyncUpdate(); + for (int i = commands.size(); --i >= 0;) + { + if (commands.getUnchecked (i)->commandID == commandID) + { + commands.remove (i); + triggerAsyncUpdate(); - const Array keys (keyMappings->getKeyPressesAssignedToCommand (commandID)); + const Array keys (keyMappings->getKeyPressesAssignedToCommand (commandID)); - for (int j = keys.size(); --j >= 0;) - keyMappings->removeKeyPress (keys.getReference (j)); - } - } + for (int j = keys.size(); --j >= 0;) + keyMappings->removeKeyPress (keys.getReference (j)); + } + } } void ApplicationCommandManager::commandStatusChanged() { - triggerAsyncUpdate(); + triggerAsyncUpdate(); } const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const CommandID commandID) const throw() { - for (int i = commands.size(); --i >= 0;) - if (commands.getUnchecked(i)->commandID == commandID) - return commands.getUnchecked(i); + for (int i = commands.size(); --i >= 0;) + if (commands.getUnchecked(i)->commandID == commandID) + return commands.getUnchecked(i); - return 0; + return 0; } const String ApplicationCommandManager::getNameOfCommand (const CommandID commandID) const throw() { - const ApplicationCommandInfo* const ci = getCommandForID (commandID); + const ApplicationCommandInfo* const ci = getCommandForID (commandID); - return (ci != 0) ? ci->shortName : String::empty; + return (ci != 0) ? ci->shortName : String::empty; } const String ApplicationCommandManager::getDescriptionOfCommand (const CommandID commandID) const throw() { - const ApplicationCommandInfo* const ci = getCommandForID (commandID); + const ApplicationCommandInfo* const ci = getCommandForID (commandID); - return (ci != 0) ? (ci->description.isNotEmpty() ? ci->description : ci->shortName) - : String::empty; + return (ci != 0) ? (ci->description.isNotEmpty() ? ci->description : ci->shortName) + : String::empty; } const StringArray ApplicationCommandManager::getCommandCategories() const throw() { - StringArray s; + StringArray s; - for (int i = 0; i < commands.size(); ++i) - s.addIfNotAlreadyThere (commands.getUnchecked(i)->categoryName, false); + for (int i = 0; i < commands.size(); ++i) + s.addIfNotAlreadyThere (commands.getUnchecked(i)->categoryName, false); - return s; + return s; } const Array ApplicationCommandManager::getCommandsInCategory (const String& categoryName) const throw() { - Array results (4); + Array results; - for (int i = 0; i < commands.size(); ++i) - if (commands.getUnchecked(i)->categoryName == categoryName) - results.add (commands.getUnchecked(i)->commandID); + for (int i = 0; i < commands.size(); ++i) + if (commands.getUnchecked(i)->categoryName == categoryName) + results.add (commands.getUnchecked(i)->commandID); - return results; + return results; } bool ApplicationCommandManager::invokeDirectly (const CommandID commandID, const bool asynchronously) { - ApplicationCommandTarget::InvocationInfo info (commandID); - info.invocationMethod = ApplicationCommandTarget::InvocationInfo::direct; + ApplicationCommandTarget::InvocationInfo info (commandID); + info.invocationMethod = ApplicationCommandTarget::InvocationInfo::direct; - return invoke (info, asynchronously); + return invoke (info, asynchronously); } bool ApplicationCommandManager::invoke (const ApplicationCommandTarget::InvocationInfo& info_, const bool asynchronously) { - // This call isn't thread-safe for use from a non-UI thread without locking the message - // manager first.. - jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); + // This call isn't thread-safe for use from a non-UI thread without locking the message + // manager first.. + jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - ApplicationCommandTarget* const target = getFirstCommandTarget (info_.commandID); + ApplicationCommandTarget* const target = getFirstCommandTarget (info_.commandID); - if (target == 0) - return false; + if (target == 0) + return false; - ApplicationCommandInfo commandInfo (0); - target->getCommandInfo (info_.commandID, commandInfo); + ApplicationCommandInfo commandInfo (0); + target->getCommandInfo (info_.commandID, commandInfo); - ApplicationCommandTarget::InvocationInfo info (info_); - info.commandFlags = commandInfo.flags; + ApplicationCommandTarget::InvocationInfo info (info_); + info.commandFlags = commandInfo.flags; - sendListenerInvokeCallback (info); + sendListenerInvokeCallback (info); - const bool ok = target->invoke (info, asynchronously); + const bool ok = target->invoke (info, asynchronously); - commandStatusChanged(); + commandStatusChanged(); - return ok; + return ok; } ApplicationCommandTarget* ApplicationCommandManager::getFirstCommandTarget (const CommandID) { - return firstTarget != 0 ? firstTarget - : findDefaultComponentTarget(); + return firstTarget != 0 ? firstTarget + : findDefaultComponentTarget(); } void ApplicationCommandManager::setFirstCommandTarget (ApplicationCommandTarget* const newTarget) throw() { - firstTarget = newTarget; + firstTarget = newTarget; } ApplicationCommandTarget* ApplicationCommandManager::getTargetForCommand (const CommandID commandID, - ApplicationCommandInfo& upToDateInfo) + ApplicationCommandInfo& upToDateInfo) { - ApplicationCommandTarget* target = getFirstCommandTarget (commandID); + ApplicationCommandTarget* target = getFirstCommandTarget (commandID); - if (target == 0) - target = JUCEApplication::getInstance(); + if (target == 0) + target = JUCEApplication::getInstance(); - if (target != 0) - target = target->getTargetForCommand (commandID); + if (target != 0) + target = target->getTargetForCommand (commandID); - if (target != 0) - target->getCommandInfo (commandID, upToDateInfo); + if (target != 0) + target->getCommandInfo (commandID, upToDateInfo); - return target; + return target; } ApplicationCommandTarget* ApplicationCommandManager::findTargetForComponent (Component* c) { - ApplicationCommandTarget* target = dynamic_cast (c); + ApplicationCommandTarget* target = dynamic_cast (c); - if (target == 0 && c != 0) - // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) - target = c->findParentComponentOfClass ((ApplicationCommandTarget*) 0); + if (target == 0 && c != 0) + // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) + target = c->findParentComponentOfClass ((ApplicationCommandTarget*) 0); - return target; + return target; } ApplicationCommandTarget* ApplicationCommandManager::findDefaultComponentTarget() { - Component* c = Component::getCurrentlyFocusedComponent(); + Component* c = Component::getCurrentlyFocusedComponent(); - if (c == 0) - { - TopLevelWindow* const activeWindow = TopLevelWindow::getActiveTopLevelWindow(); + if (c == 0) + { + TopLevelWindow* const activeWindow = TopLevelWindow::getActiveTopLevelWindow(); - if (activeWindow != 0) - { - c = activeWindow->getPeer()->getLastFocusedSubcomponent(); + if (activeWindow != 0) + { + c = activeWindow->getPeer()->getLastFocusedSubcomponent(); - if (c == 0) - c = activeWindow; - } - } + if (c == 0) + c = activeWindow; + } + } - if (c == 0 && Process::isForegroundProcess()) - { - // getting a bit desperate now - try all desktop comps.. - for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) - { - ApplicationCommandTarget* const target - = findTargetForComponent (Desktop::getInstance().getComponent (i) - ->getPeer()->getLastFocusedSubcomponent()); + if (c == 0 && Process::isForegroundProcess()) + { + // getting a bit desperate now - try all desktop comps.. + for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) + { + ApplicationCommandTarget* const target + = findTargetForComponent (Desktop::getInstance().getComponent (i) + ->getPeer()->getLastFocusedSubcomponent()); - if (target != 0) - return target; - } - } + if (target != 0) + return target; + } + } - if (c != 0) - { - ResizableWindow* const resizableWindow = dynamic_cast (c); + if (c != 0) + { + ResizableWindow* const resizableWindow = dynamic_cast (c); - // if we're focused on a ResizableWindow, chances are that it's the content - // component that really should get the event. And if not, the event will - // still be passed up to the top level window anyway, so let's send it to the - // content comp. - if (resizableWindow != 0 && resizableWindow->getContentComponent() != 0) - c = resizableWindow->getContentComponent(); + // if we're focused on a ResizableWindow, chances are that it's the content + // component that really should get the event. And if not, the event will + // still be passed up to the top level window anyway, so let's send it to the + // content comp. + if (resizableWindow != 0 && resizableWindow->getContentComponent() != 0) + c = resizableWindow->getContentComponent(); - ApplicationCommandTarget* const target = findTargetForComponent (c); + ApplicationCommandTarget* const target = findTargetForComponent (c); - if (target != 0) - return target; - } + if (target != 0) + return target; + } - return JUCEApplication::getInstance(); + return JUCEApplication::getInstance(); } void ApplicationCommandManager::addListener (ApplicationCommandManagerListener* const listener) throw() { - jassert (listener != 0); - if (listener != 0) - listeners.add (listener); + jassert (listener != 0); + if (listener != 0) + listeners.add (listener); } void ApplicationCommandManager::removeListener (ApplicationCommandManagerListener* const listener) throw() { - listeners.removeValue (listener); + listeners.removeValue (listener); } void ApplicationCommandManager::sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo& info) const { - for (int i = listeners.size(); --i >= 0;) - { - ((ApplicationCommandManagerListener*) listeners.getUnchecked (i))->applicationCommandInvoked (info); - i = jmin (i, listeners.size()); - } + for (int i = listeners.size(); --i >= 0;) + { + ((ApplicationCommandManagerListener*) listeners.getUnchecked (i))->applicationCommandInvoked (info); + i = jmin (i, listeners.size()); + } } void ApplicationCommandManager::handleAsyncUpdate() { - for (int i = listeners.size(); --i >= 0;) - { - ((ApplicationCommandManagerListener*) listeners.getUnchecked (i))->applicationCommandListChanged(); - i = jmin (i, listeners.size()); - } + for (int i = listeners.size(); --i >= 0;) + { + ((ApplicationCommandManagerListener*) listeners.getUnchecked (i))->applicationCommandListChanged(); + i = jmin (i, listeners.size()); + } } void ApplicationCommandManager::globalFocusChanged (Component*) { - commandStatusChanged(); + commandStatusChanged(); } END_JUCE_NAMESPACE @@ -17928,147 +17692,147 @@ ApplicationCommandTarget::ApplicationCommandTarget() ApplicationCommandTarget::~ApplicationCommandTarget() { - messageInvoker = 0; + messageInvoker = 0; } bool ApplicationCommandTarget::tryToInvoke (const InvocationInfo& info, const bool async) { - if (isCommandActive (info.commandID)) - { - if (async) - { - if (messageInvoker == 0) - messageInvoker = new CommandTargetMessageInvoker (this); + if (isCommandActive (info.commandID)) + { + if (async) + { + if (messageInvoker == 0) + messageInvoker = new CommandTargetMessageInvoker (this); - messageInvoker->postMessage (new Message (0, 0, 0, new ApplicationCommandTarget::InvocationInfo (info))); - return true; - } - else - { - const bool success = perform (info); + messageInvoker->postMessage (new Message (0, 0, 0, new ApplicationCommandTarget::InvocationInfo (info))); + return true; + } + else + { + const bool success = perform (info); - jassert (success); // hmm - your target should have been able to perform this command. If it can't - // do it at the moment for some reason, it should clear the 'isActive' flag when it - // returns the command's info. - return success; - } - } + jassert (success); // hmm - your target should have been able to perform this command. If it can't + // do it at the moment for some reason, it should clear the 'isActive' flag when it + // returns the command's info. + return success; + } + } - return false; + return false; } ApplicationCommandTarget* ApplicationCommandTarget::findFirstTargetParentComponent() { - Component* c = dynamic_cast (this); + Component* c = dynamic_cast (this); - if (c != 0) - // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) - return c->findParentComponentOfClass ((ApplicationCommandTarget*) 0); + if (c != 0) + // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) + return c->findParentComponentOfClass ((ApplicationCommandTarget*) 0); - return 0; + return 0; } ApplicationCommandTarget* ApplicationCommandTarget::getTargetForCommand (const CommandID commandID) { - ApplicationCommandTarget* target = this; - int depth = 0; + ApplicationCommandTarget* target = this; + int depth = 0; - while (target != 0) - { - Array commandIDs; - target->getAllCommands (commandIDs); + while (target != 0) + { + Array commandIDs; + target->getAllCommands (commandIDs); - if (commandIDs.contains (commandID)) - return target; + if (commandIDs.contains (commandID)) + return target; - target = target->getNextCommandTarget(); + target = target->getNextCommandTarget(); - ++depth; - jassert (depth < 100); // could be a recursive command chain?? - jassert (target != this); // definitely a recursive command chain! + ++depth; + jassert (depth < 100); // could be a recursive command chain?? + jassert (target != this); // definitely a recursive command chain! - if (depth > 100 || target == this) - break; - } + if (depth > 100 || target == this) + break; + } - if (target == 0) - { - target = JUCEApplication::getInstance(); + if (target == 0) + { + target = JUCEApplication::getInstance(); - if (target != 0) - { - Array commandIDs; - target->getAllCommands (commandIDs); + if (target != 0) + { + Array commandIDs; + target->getAllCommands (commandIDs); - if (commandIDs.contains (commandID)) - return target; - } - } + if (commandIDs.contains (commandID)) + return target; + } + } - return 0; + return 0; } bool ApplicationCommandTarget::isCommandActive (const CommandID commandID) { - ApplicationCommandInfo info (commandID); - info.flags = ApplicationCommandInfo::isDisabled; + ApplicationCommandInfo info (commandID); + info.flags = ApplicationCommandInfo::isDisabled; - getCommandInfo (commandID, info); + getCommandInfo (commandID, info); - return (info.flags & ApplicationCommandInfo::isDisabled) == 0; + return (info.flags & ApplicationCommandInfo::isDisabled) == 0; } bool ApplicationCommandTarget::invoke (const InvocationInfo& info, const bool async) { - ApplicationCommandTarget* target = this; - int depth = 0; + ApplicationCommandTarget* target = this; + int depth = 0; - while (target != 0) - { - if (target->tryToInvoke (info, async)) - return true; + while (target != 0) + { + if (target->tryToInvoke (info, async)) + return true; - target = target->getNextCommandTarget(); + target = target->getNextCommandTarget(); - ++depth; - jassert (depth < 100); // could be a recursive command chain?? - jassert (target != this); // definitely a recursive command chain! + ++depth; + jassert (depth < 100); // could be a recursive command chain?? + jassert (target != this); // definitely a recursive command chain! - if (depth > 100 || target == this) - break; - } + if (depth > 100 || target == this) + break; + } - if (target == 0) - { - target = JUCEApplication::getInstance(); + if (target == 0) + { + target = JUCEApplication::getInstance(); - if (target != 0) - return target->tryToInvoke (info, async); - } + if (target != 0) + return target->tryToInvoke (info, async); + } - return false; + return false; } bool ApplicationCommandTarget::invokeDirectly (const CommandID commandID, const bool asynchronously) { - ApplicationCommandTarget::InvocationInfo info (commandID); - info.invocationMethod = ApplicationCommandTarget::InvocationInfo::direct; + ApplicationCommandTarget::InvocationInfo info (commandID); + info.invocationMethod = ApplicationCommandTarget::InvocationInfo::direct; - return invoke (info, asynchronously); + return invoke (info, asynchronously); } ApplicationCommandTarget::InvocationInfo::InvocationInfo (const CommandID commandID_) throw() - : commandID (commandID_), - commandFlags (0), - invocationMethod (direct), - originatingComponent (0), - isKeyDown (false), - millisecsSinceKeyPressed (0) + : commandID (commandID_), + commandFlags (0), + invocationMethod (direct), + originatingComponent (0), + isKeyDown (false), + millisecsSinceKeyPressed (0) { } ApplicationCommandTarget::CommandTargetMessageInvoker::CommandTargetMessageInvoker (ApplicationCommandTarget* const owner_) - : owner (owner_) + : owner (owner_) { } @@ -18078,8 +17842,8 @@ ApplicationCommandTarget::CommandTargetMessageInvoker::~CommandTargetMessageInvo void ApplicationCommandTarget::CommandTargetMessageInvoker::handleMessage (const Message& message) { - const ScopedPointer info ((InvocationInfo*) message.pointerParameter); - owner->tryToInvoke (*info, false); + const ScopedPointer info ((InvocationInfo*) message.pointerParameter); + owner->tryToInvoke (*info, false); } END_JUCE_NAMESPACE @@ -18092,119 +17856,119 @@ BEGIN_JUCE_NAMESPACE juce_ImplementSingleton (ApplicationProperties) ApplicationProperties::ApplicationProperties() throw() - : msBeforeSaving (3000), - options (PropertiesFile::storeAsBinary), - commonSettingsAreReadOnly (0) + : msBeforeSaving (3000), + options (PropertiesFile::storeAsBinary), + commonSettingsAreReadOnly (0) { } ApplicationProperties::~ApplicationProperties() { - closeFiles(); - clearSingletonInstance(); + closeFiles(); + clearSingletonInstance(); } void ApplicationProperties::setStorageParameters (const String& applicationName, - const String& fileNameSuffix, - const String& folderName_, - const int millisecondsBeforeSaving, - const int propertiesFileOptions) throw() + const String& fileNameSuffix, + const String& folderName_, + const int millisecondsBeforeSaving, + const int propertiesFileOptions) throw() { - appName = applicationName; - fileSuffix = fileNameSuffix; - folderName = folderName_; - msBeforeSaving = millisecondsBeforeSaving; - options = propertiesFileOptions; + appName = applicationName; + fileSuffix = fileNameSuffix; + folderName = folderName_; + msBeforeSaving = millisecondsBeforeSaving; + options = propertiesFileOptions; } bool ApplicationProperties::testWriteAccess (const bool testUserSettings, - const bool testCommonSettings, - const bool showWarningDialogOnFailure) + const bool testCommonSettings, + const bool showWarningDialogOnFailure) { - const bool userOk = (! testUserSettings) || getUserSettings()->save(); - const bool commonOk = (! testCommonSettings) || getCommonSettings (false)->save(); + const bool userOk = (! testUserSettings) || getUserSettings()->save(); + const bool commonOk = (! testCommonSettings) || getCommonSettings (false)->save(); - if (! (userOk && commonOk)) - { - if (showWarningDialogOnFailure) - { - String filenames; + if (! (userOk && commonOk)) + { + if (showWarningDialogOnFailure) + { + String filenames; - if (userProps != 0 && ! userOk) - filenames << '\n' << userProps->getFile().getFullPathName(); + if (userProps != 0 && ! userOk) + filenames << '\n' << userProps->getFile().getFullPathName(); - if (commonProps != 0 && ! commonOk) - filenames << '\n' << commonProps->getFile().getFullPathName(); + if (commonProps != 0 && ! commonOk) + filenames << '\n' << commonProps->getFile().getFullPathName(); - AlertWindow::showMessageBox (AlertWindow::WarningIcon, - appName + TRANS(" - Unable to save settings"), - TRANS("An error occurred when trying to save the application's settings file...\n\nIn order to save and restore its settings, ") - + appName + TRANS(" needs to be able to write to the following files:\n") - + filenames - + TRANS("\n\nMake sure that these files aren't read-only, and that the disk isn't full.")); - } + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + appName + TRANS(" - Unable to save settings"), + TRANS("An error occurred when trying to save the application's settings file...\n\nIn order to save and restore its settings, ") + + appName + TRANS(" needs to be able to write to the following files:\n") + + filenames + + TRANS("\n\nMake sure that these files aren't read-only, and that the disk isn't full.")); + } - return false; - } + return false; + } - return true; + return true; } void ApplicationProperties::openFiles() throw() { - // You need to call setStorageParameters() before trying to get hold of the - // properties! - jassert (appName.isNotEmpty()); + // You need to call setStorageParameters() before trying to get hold of the + // properties! + jassert (appName.isNotEmpty()); - if (appName.isNotEmpty()) - { - if (userProps == 0) - userProps = PropertiesFile::createDefaultAppPropertiesFile (appName, fileSuffix, folderName, - false, msBeforeSaving, options); + if (appName.isNotEmpty()) + { + if (userProps == 0) + userProps = PropertiesFile::createDefaultAppPropertiesFile (appName, fileSuffix, folderName, + false, msBeforeSaving, options); - if (commonProps == 0) - commonProps = PropertiesFile::createDefaultAppPropertiesFile (appName, fileSuffix, folderName, - true, msBeforeSaving, options); + if (commonProps == 0) + commonProps = PropertiesFile::createDefaultAppPropertiesFile (appName, fileSuffix, folderName, + true, msBeforeSaving, options); - userProps->setFallbackPropertySet (commonProps); - } + userProps->setFallbackPropertySet (commonProps); + } } PropertiesFile* ApplicationProperties::getUserSettings() throw() { - if (userProps == 0) - openFiles(); + if (userProps == 0) + openFiles(); - return userProps; + return userProps; } PropertiesFile* ApplicationProperties::getCommonSettings (const bool returnUserPropsIfReadOnly) throw() { - if (commonProps == 0) - openFiles(); + if (commonProps == 0) + openFiles(); - if (returnUserPropsIfReadOnly) - { - if (commonSettingsAreReadOnly == 0) - commonSettingsAreReadOnly = commonProps->save() ? -1 : 1; + if (returnUserPropsIfReadOnly) + { + if (commonSettingsAreReadOnly == 0) + commonSettingsAreReadOnly = commonProps->save() ? -1 : 1; - if (commonSettingsAreReadOnly > 0) - return userProps; - } + if (commonSettingsAreReadOnly > 0) + return userProps; + } - return commonProps; + return commonProps; } bool ApplicationProperties::saveIfNeeded() { - return (userProps == 0 || userProps->saveIfNeeded()) - && (commonProps == 0 || commonProps->saveIfNeeded()); + return (userProps == 0 || userProps->saveIfNeeded()) + && (commonProps == 0 || commonProps->saveIfNeeded()); } void ApplicationProperties::closeFiles() { - userProps = 0; - commonProps = 0; + userProps = 0; + commonProps = 0; } END_JUCE_NAMESPACE @@ -18214,52 +17978,52 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -static VoidArray objectsToDelete (16); +static VoidArray objectsToDelete; static CriticalSection lock; DeletedAtShutdown::DeletedAtShutdown() { - const ScopedLock sl (lock); - objectsToDelete.add (this); + const ScopedLock sl (lock); + objectsToDelete.add (this); } DeletedAtShutdown::~DeletedAtShutdown() { - const ScopedLock sl (lock); - objectsToDelete.removeValue (this); + const ScopedLock sl (lock); + objectsToDelete.removeValue (this); } void DeletedAtShutdown::deleteAll() { - // make a local copy of the array, so it can't get into a loop if something - // creates another DeletedAtShutdown object during its destructor. - lock.enter(); - const VoidArray localCopy (objectsToDelete); - lock.exit(); + // make a local copy of the array, so it can't get into a loop if something + // creates another DeletedAtShutdown object during its destructor. + lock.enter(); + const VoidArray localCopy (objectsToDelete); + lock.exit(); - for (int i = localCopy.size(); --i >= 0;) - { - JUCE_TRY - { - DeletedAtShutdown* deletee = (DeletedAtShutdown*) localCopy.getUnchecked(i); + for (int i = localCopy.size(); --i >= 0;) + { + JUCE_TRY + { + DeletedAtShutdown* deletee = (DeletedAtShutdown*) localCopy.getUnchecked(i); - // double-check that it's not already been deleted during another object's destructor. - { - const ScopedLock sl (lock); - if (! objectsToDelete.contains (deletee)) - deletee = 0; - } + // double-check that it's not already been deleted during another object's destructor. + { + const ScopedLock sl (lock); + if (! objectsToDelete.contains (deletee)) + deletee = 0; + } - delete deletee; - } - JUCE_CATCH_EXCEPTION - } + delete deletee; + } + JUCE_CATCH_EXCEPTION + } - // if no objects got re-created during shutdown, this should have been emptied by their - // destructors - jassert (objectsToDelete.size() == 0); + // if no objects got re-created during shutdown, this should have been emptied by their + // destructors + jassert (objectsToDelete.size() == 0); - objectsToDelete.clear(); // just to make sure the array doesn't have any memory still allocated + objectsToDelete.clear(); // just to make sure the array doesn't have any memory still allocated } END_JUCE_NAMESPACE @@ -18276,258 +18040,258 @@ static const tchar* const propertyFileXmlTag = T("PROPERTIES"); static const tchar* const propertyTagName = T("VALUE"); PropertiesFile::PropertiesFile (const File& f, - const int millisecondsBeforeSaving, - const int options_) - : PropertySet (ignoreCaseOfKeyNames), - file (f), - timerInterval (millisecondsBeforeSaving), - options (options_), - needsWriting (false) + const int millisecondsBeforeSaving, + const int options_) + : PropertySet (ignoreCaseOfKeyNames), + file (f), + timerInterval (millisecondsBeforeSaving), + options (options_), + needsWriting (false) { - // You need to correctly specify just one storage format for the file - jassert ((options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsBinary - || (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsCompressedBinary - || (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsXML); + // You need to correctly specify just one storage format for the file + jassert ((options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsBinary + || (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsCompressedBinary + || (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsXML); - ScopedPointer fileStream (f.createInputStream()); + ScopedPointer fileStream (f.createInputStream()); - if (fileStream != 0) - { - int magicNumber = fileStream->readInt(); + if (fileStream != 0) + { + int magicNumber = fileStream->readInt(); - if (magicNumber == propFileMagicNumberCompressed) - { - fileStream = new GZIPDecompressorInputStream (new SubregionStream (fileStream.release(), 4, -1, true), - true); + if (magicNumber == propFileMagicNumberCompressed) + { + fileStream = new GZIPDecompressorInputStream (new SubregionStream (fileStream.release(), 4, -1, true), + true); - magicNumber = propFileMagicNumber; - } + magicNumber = propFileMagicNumber; + } - if (magicNumber == propFileMagicNumber) - { - BufferedInputStream in (fileStream.release(), 2048, true); + if (magicNumber == propFileMagicNumber) + { + BufferedInputStream in (fileStream.release(), 2048, true); - int numValues = in.readInt(); + int numValues = in.readInt(); - while (--numValues >= 0 && ! in.isExhausted()) - { - const String key (in.readString()); - const String value (in.readString()); + while (--numValues >= 0 && ! in.isExhausted()) + { + const String key (in.readString()); + const String value (in.readString()); - jassert (key.isNotEmpty()); - if (key.isNotEmpty()) - getAllProperties().set (key, value); - } - } - else - { - // Not a binary props file - let's see if it's XML.. - fileStream = 0; + jassert (key.isNotEmpty()); + if (key.isNotEmpty()) + getAllProperties().set (key, value); + } + } + else + { + // Not a binary props file - let's see if it's XML.. + fileStream = 0; - XmlDocument parser (f); - ScopedPointer doc (parser.getDocumentElement (true)); + XmlDocument parser (f); + ScopedPointer doc (parser.getDocumentElement (true)); - if (doc != 0 && doc->hasTagName (propertyFileXmlTag)) - { - doc = parser.getDocumentElement(); + if (doc != 0 && doc->hasTagName (propertyFileXmlTag)) + { + doc = parser.getDocumentElement(); - if (doc != 0) - { - forEachXmlChildElementWithTagName (*doc, e, propertyTagName) - { - const String name (e->getStringAttribute (T("name"))); + if (doc != 0) + { + forEachXmlChildElementWithTagName (*doc, e, propertyTagName) + { + const String name (e->getStringAttribute (T("name"))); - if (name.isNotEmpty()) - { - getAllProperties().set (name, - e->getFirstChildElement() != 0 - ? e->getFirstChildElement()->createDocument (String::empty, true) - : e->getStringAttribute (T("val"))); - } - } - } - else - { - // must be a pretty broken XML file we're trying to parse here! - jassertfalse - } - } - } - } + if (name.isNotEmpty()) + { + getAllProperties().set (name, + e->getFirstChildElement() != 0 + ? e->getFirstChildElement()->createDocument (String::empty, true) + : e->getStringAttribute (T("val"))); + } + } + } + else + { + // must be a pretty broken XML file we're trying to parse here! + jassertfalse + } + } + } + } } PropertiesFile::~PropertiesFile() { - saveIfNeeded(); + saveIfNeeded(); } bool PropertiesFile::saveIfNeeded() { - const ScopedLock sl (getLock()); - return (! needsWriting) || save(); + const ScopedLock sl (getLock()); + return (! needsWriting) || save(); } bool PropertiesFile::needsToBeSaved() const { - const ScopedLock sl (getLock()); - return needsWriting; + const ScopedLock sl (getLock()); + return needsWriting; } bool PropertiesFile::save() { - const ScopedLock sl (getLock()); + const ScopedLock sl (getLock()); - stopTimer(); + stopTimer(); - if (file == File::nonexistent - || file.isDirectory() - || ! file.getParentDirectory().createDirectory()) - return false; + if (file == File::nonexistent + || file.isDirectory() + || ! file.getParentDirectory().createDirectory()) + return false; - if ((options & storeAsXML) != 0) - { - XmlElement doc (propertyFileXmlTag); + if ((options & storeAsXML) != 0) + { + XmlElement doc (propertyFileXmlTag); - for (int i = 0; i < getAllProperties().size(); ++i) - { - XmlElement* const e = new XmlElement (propertyTagName); - e->setAttribute (T("name"), getAllProperties().getAllKeys() [i]); + for (int i = 0; i < getAllProperties().size(); ++i) + { + XmlElement* const e = new XmlElement (propertyTagName); + e->setAttribute (T("name"), getAllProperties().getAllKeys() [i]); - // if the value seems to contain xml, store it as such.. - XmlDocument xmlContent (getAllProperties().getAllValues() [i]); - XmlElement* const childElement = xmlContent.getDocumentElement(); + // if the value seems to contain xml, store it as such.. + XmlDocument xmlContent (getAllProperties().getAllValues() [i]); + XmlElement* const childElement = xmlContent.getDocumentElement(); - if (childElement != 0) - e->addChildElement (childElement); - else - e->setAttribute (T("val"), getAllProperties().getAllValues() [i]); + if (childElement != 0) + e->addChildElement (childElement); + else + e->setAttribute (T("val"), getAllProperties().getAllValues() [i]); - doc.addChildElement (e); - } + doc.addChildElement (e); + } - return doc.writeToFile (file, String::empty); - } - else - { - const File tempFile (file.getNonexistentSibling (false)); - ScopedPointer out (tempFile.createOutputStream()); + return doc.writeToFile (file, String::empty); + } + else + { + const File tempFile (file.getNonexistentSibling (false)); + ScopedPointer out (tempFile.createOutputStream()); - if (out != 0) - { - if ((options & storeAsCompressedBinary) != 0) - { - out->writeInt (propFileMagicNumberCompressed); - out->flush(); + if (out != 0) + { + if ((options & storeAsCompressedBinary) != 0) + { + out->writeInt (propFileMagicNumberCompressed); + out->flush(); - out = new GZIPCompressorOutputStream (out.release(), 9, true); - } - else - { - // have you set up the storage option flags correctly? - jassert ((options & storeAsBinary) != 0); + out = new GZIPCompressorOutputStream (out.release(), 9, true); + } + else + { + // have you set up the storage option flags correctly? + jassert ((options & storeAsBinary) != 0); - out->writeInt (propFileMagicNumber); - } + out->writeInt (propFileMagicNumber); + } - const int numProperties = getAllProperties().size(); + const int numProperties = getAllProperties().size(); - out->writeInt (numProperties); + out->writeInt (numProperties); - for (int i = 0; i < numProperties; ++i) - { - out->writeString (getAllProperties().getAllKeys() [i]); - out->writeString (getAllProperties().getAllValues() [i]); - } + for (int i = 0; i < numProperties; ++i) + { + out->writeString (getAllProperties().getAllKeys() [i]); + out->writeString (getAllProperties().getAllValues() [i]); + } - out->flush(); - out = 0; + out->flush(); + out = 0; - if (tempFile.moveFileTo (file)) - { - needsWriting = false; - return true; - } + if (tempFile.moveFileTo (file)) + { + needsWriting = false; + return true; + } - tempFile.deleteFile(); - } - } + tempFile.deleteFile(); + } + } - return false; + return false; } void PropertiesFile::timerCallback() { - saveIfNeeded(); + saveIfNeeded(); } void PropertiesFile::propertyChanged() { - sendChangeMessage (this); + sendChangeMessage (this); - needsWriting = true; + needsWriting = true; - if (timerInterval > 0) - startTimer (timerInterval); - else if (timerInterval == 0) - saveIfNeeded(); + if (timerInterval > 0) + startTimer (timerInterval); + else if (timerInterval == 0) + saveIfNeeded(); } const File PropertiesFile::getDefaultAppSettingsFile (const String& applicationName, - const String& fileNameSuffix, - const String& folderName, - const bool commonToAllUsers) + const String& fileNameSuffix, + const String& folderName, + const bool commonToAllUsers) { - // mustn't have illegal characters in this name.. - jassert (applicationName == File::createLegalFileName (applicationName)); + // mustn't have illegal characters in this name.. + jassert (applicationName == File::createLegalFileName (applicationName)); #if JUCE_MAC || JUCE_IPHONE - File dir (commonToAllUsers ? "/Library/Preferences" - : "~/Library/Preferences"); + File dir (commonToAllUsers ? "/Library/Preferences" + : "~/Library/Preferences"); - if (folderName.isNotEmpty()) - dir = dir.getChildFile (folderName); + if (folderName.isNotEmpty()) + dir = dir.getChildFile (folderName); #endif #ifdef JUCE_LINUX - const File dir ((commonToAllUsers ? T("/var/") : T("~/")) - + (folderName.isNotEmpty() ? folderName - : (T(".") + applicationName))); + const File dir ((commonToAllUsers ? T("/var/") : T("~/")) + + (folderName.isNotEmpty() ? folderName + : (T(".") + applicationName))); #endif #if JUCE_WIN32 - File dir (File::getSpecialLocation (commonToAllUsers ? File::commonApplicationDataDirectory - : File::userApplicationDataDirectory)); + File dir (File::getSpecialLocation (commonToAllUsers ? File::commonApplicationDataDirectory + : File::userApplicationDataDirectory)); - if (dir == File::nonexistent) - return File::nonexistent; + if (dir == File::nonexistent) + return File::nonexistent; - dir = dir.getChildFile (folderName.isNotEmpty() ? folderName - : applicationName); + dir = dir.getChildFile (folderName.isNotEmpty() ? folderName + : applicationName); #endif - return dir.getChildFile (applicationName) - .withFileExtension (fileNameSuffix); + return dir.getChildFile (applicationName) + .withFileExtension (fileNameSuffix); } PropertiesFile* PropertiesFile::createDefaultAppPropertiesFile (const String& applicationName, - const String& fileNameSuffix, - const String& folderName, - const bool commonToAllUsers, - const int millisecondsBeforeSaving, - const int propertiesFileOptions) + const String& fileNameSuffix, + const String& folderName, + const bool commonToAllUsers, + const int millisecondsBeforeSaving, + const int propertiesFileOptions) { - const File file (getDefaultAppSettingsFile (applicationName, - fileNameSuffix, - folderName, - commonToAllUsers)); + const File file (getDefaultAppSettingsFile (applicationName, + fileNameSuffix, + folderName, + commonToAllUsers)); - jassert (file != File::nonexistent); + jassert (file != File::nonexistent); - if (file == File::nonexistent) - return 0; + if (file == File::nonexistent) + return 0; - return new PropertiesFile (file, millisecondsBeforeSaving, propertiesFileOptions); + return new PropertiesFile (file, millisecondsBeforeSaving, propertiesFileOptions); } END_JUCE_NAMESPACE @@ -18538,14 +18302,14 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE FileBasedDocument::FileBasedDocument (const String& fileExtension_, - const String& fileWildcard_, - const String& openFileDialogTitle_, - const String& saveFileDialogTitle_) - : changedSinceSave (false), - fileExtension (fileExtension_), - fileWildcard (fileWildcard_), - openFileDialogTitle (openFileDialogTitle_), - saveFileDialogTitle (saveFileDialogTitle_) + const String& fileWildcard_, + const String& openFileDialogTitle_, + const String& saveFileDialogTitle_) + : changedSinceSave (false), + fileExtension (fileExtension_), + fileWildcard (fileWildcard_), + openFileDialogTitle (openFileDialogTitle_), + saveFileDialogTitle (saveFileDialogTitle_) { } @@ -18555,234 +18319,234 @@ FileBasedDocument::~FileBasedDocument() void FileBasedDocument::setChangedFlag (const bool hasChanged) { - changedSinceSave = hasChanged; + changedSinceSave = hasChanged; } void FileBasedDocument::changed() { - changedSinceSave = true; - sendChangeMessage (this); + changedSinceSave = true; + sendChangeMessage (this); } void FileBasedDocument::setFile (const File& newFile) { - if (documentFile != newFile) - { - documentFile = newFile; - changedSinceSave = true; - } + if (documentFile != newFile) + { + documentFile = newFile; + changedSinceSave = true; + } } bool FileBasedDocument::loadFrom (const File& newFile, - const bool showMessageOnFailure) + const bool showMessageOnFailure) { - MouseCursor::showWaitCursor(); + MouseCursor::showWaitCursor(); - const File oldFile (documentFile); - documentFile = newFile; + const File oldFile (documentFile); + documentFile = newFile; - String error; + String error; - if (newFile.existsAsFile()) - { - error = loadDocument (newFile); + if (newFile.existsAsFile()) + { + error = loadDocument (newFile); - if (error.isEmpty()) - { - setChangedFlag (false); - MouseCursor::hideWaitCursor(); + if (error.isEmpty()) + { + setChangedFlag (false); + MouseCursor::hideWaitCursor(); - setLastDocumentOpened (newFile); - return true; - } - } - else - { - error = "The file doesn't exist"; - } + setLastDocumentOpened (newFile); + return true; + } + } + else + { + error = "The file doesn't exist"; + } - documentFile = oldFile; - MouseCursor::hideWaitCursor(); + documentFile = oldFile; + MouseCursor::hideWaitCursor(); - if (showMessageOnFailure) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, - TRANS("Failed to open file..."), - TRANS("There was an error while trying to load the file:\n\n") - + newFile.getFullPathName() - + T("\n\n") - + error); - } + if (showMessageOnFailure) + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + TRANS("Failed to open file..."), + TRANS("There was an error while trying to load the file:\n\n") + + newFile.getFullPathName() + + T("\n\n") + + error); + } - return false; + return false; } bool FileBasedDocument::loadFromUserSpecifiedFile (const bool showMessageOnFailure) { - FileChooser fc (openFileDialogTitle, - getLastDocumentOpened(), - fileWildcard); + FileChooser fc (openFileDialogTitle, + getLastDocumentOpened(), + fileWildcard); - if (fc.browseForFileToOpen()) - return loadFrom (fc.getResult(), showMessageOnFailure); + if (fc.browseForFileToOpen()) + return loadFrom (fc.getResult(), showMessageOnFailure); - return false; + return false; } FileBasedDocument::SaveResult FileBasedDocument::save (const bool askUserForFileIfNotSpecified, - const bool showMessageOnFailure) + const bool showMessageOnFailure) { - return saveAs (documentFile, - false, - askUserForFileIfNotSpecified, - showMessageOnFailure); + return saveAs (documentFile, + false, + askUserForFileIfNotSpecified, + showMessageOnFailure); } FileBasedDocument::SaveResult FileBasedDocument::saveAs (const File& newFile, - const bool warnAboutOverwritingExistingFiles, - const bool askUserForFileIfNotSpecified, - const bool showMessageOnFailure) + const bool warnAboutOverwritingExistingFiles, + const bool askUserForFileIfNotSpecified, + const bool showMessageOnFailure) { - if (newFile == File::nonexistent) - { - if (askUserForFileIfNotSpecified) - { - return saveAsInteractive (true); - } - else - { - // can't save to an unspecified file - jassertfalse - return failedToWriteToFile; - } - } + if (newFile == File::nonexistent) + { + if (askUserForFileIfNotSpecified) + { + return saveAsInteractive (true); + } + else + { + // can't save to an unspecified file + jassertfalse + return failedToWriteToFile; + } + } - if (warnAboutOverwritingExistingFiles && newFile.exists()) - { - if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, - TRANS("File already exists"), - TRANS("There's already a file called:\n\n") - + newFile.getFullPathName() - + TRANS("\n\nAre you sure you want to overwrite it?"), - TRANS("overwrite"), - TRANS("cancel"))) - { - return userCancelledSave; - } - } + if (warnAboutOverwritingExistingFiles && newFile.exists()) + { + if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, + TRANS("File already exists"), + TRANS("There's already a file called:\n\n") + + newFile.getFullPathName() + + TRANS("\n\nAre you sure you want to overwrite it?"), + TRANS("overwrite"), + TRANS("cancel"))) + { + return userCancelledSave; + } + } - MouseCursor::showWaitCursor(); + MouseCursor::showWaitCursor(); - const File oldFile (documentFile); - documentFile = newFile; + const File oldFile (documentFile); + documentFile = newFile; - String error (saveDocument (newFile)); + String error (saveDocument (newFile)); - if (error.isEmpty()) - { - setChangedFlag (false); - MouseCursor::hideWaitCursor(); + if (error.isEmpty()) + { + setChangedFlag (false); + MouseCursor::hideWaitCursor(); - return savedOk; - } + return savedOk; + } - documentFile = oldFile; - MouseCursor::hideWaitCursor(); + documentFile = oldFile; + MouseCursor::hideWaitCursor(); - if (showMessageOnFailure) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, - TRANS("Error writing to file..."), - TRANS("An error occurred while trying to save \"") - + getDocumentTitle() - + TRANS("\" to the file:\n\n") - + newFile.getFullPathName() - + T("\n\n") - + error); - } + if (showMessageOnFailure) + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + TRANS("Error writing to file..."), + TRANS("An error occurred while trying to save \"") + + getDocumentTitle() + + TRANS("\" to the file:\n\n") + + newFile.getFullPathName() + + T("\n\n") + + error); + } - return failedToWriteToFile; + return failedToWriteToFile; } FileBasedDocument::SaveResult FileBasedDocument::saveIfNeededAndUserAgrees() { - if (! hasChangedSinceSaved()) - return savedOk; + if (! hasChangedSinceSaved()) + return savedOk; - const int r = AlertWindow::showYesNoCancelBox (AlertWindow::QuestionIcon, - TRANS("Closing document..."), - TRANS("Do you want to save the changes to \"") - + getDocumentTitle() + T("\"?"), - TRANS("save"), - TRANS("discard changes"), - TRANS("cancel")); + const int r = AlertWindow::showYesNoCancelBox (AlertWindow::QuestionIcon, + TRANS("Closing document..."), + TRANS("Do you want to save the changes to \"") + + getDocumentTitle() + T("\"?"), + TRANS("save"), + TRANS("discard changes"), + TRANS("cancel")); - if (r == 1) - { - // save changes - return save (true, true); - } - else if (r == 2) - { - // discard changes - return savedOk; - } + if (r == 1) + { + // save changes + return save (true, true); + } + else if (r == 2) + { + // discard changes + return savedOk; + } - return userCancelledSave; + return userCancelledSave; } FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool warnAboutOverwritingExistingFiles) { - File f; + File f; - if (documentFile.existsAsFile()) - f = documentFile; - else - f = getLastDocumentOpened(); + if (documentFile.existsAsFile()) + f = documentFile; + else + f = getLastDocumentOpened(); - String legalFilename (File::createLegalFileName (getDocumentTitle())); + String legalFilename (File::createLegalFileName (getDocumentTitle())); - if (legalFilename.isEmpty()) - legalFilename = "unnamed"; + if (legalFilename.isEmpty()) + legalFilename = "unnamed"; - if (f.existsAsFile() || f.getParentDirectory().isDirectory()) - f = f.getSiblingFile (legalFilename); - else - f = File::getSpecialLocation (File::userDocumentsDirectory).getChildFile (legalFilename); + if (f.existsAsFile() || f.getParentDirectory().isDirectory()) + f = f.getSiblingFile (legalFilename); + else + f = File::getSpecialLocation (File::userDocumentsDirectory).getChildFile (legalFilename); - f = f.withFileExtension (fileExtension) - .getNonexistentSibling (true); + f = f.withFileExtension (fileExtension) + .getNonexistentSibling (true); - FileChooser fc (saveFileDialogTitle, f, fileWildcard); + FileChooser fc (saveFileDialogTitle, f, fileWildcard); - if (fc.browseForFileToSave (warnAboutOverwritingExistingFiles)) - { - setLastDocumentOpened (fc.getResult()); + if (fc.browseForFileToSave (warnAboutOverwritingExistingFiles)) + { + setLastDocumentOpened (fc.getResult()); - File chosen (fc.getResult()); - if (chosen.getFileExtension().isEmpty()) - { - chosen = chosen.withFileExtension (fileExtension); + File chosen (fc.getResult()); + if (chosen.getFileExtension().isEmpty()) + { + chosen = chosen.withFileExtension (fileExtension); - if (chosen.exists()) - { - if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, - TRANS("File already exists"), - TRANS("There's already a file called:\n\n") - + chosen.getFullPathName() - + T("\n\nAre you sure you want to overwrite it?"), - TRANS("overwrite"), - TRANS("cancel"))) - { - return userCancelledSave; - } - } - } + if (chosen.exists()) + { + if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, + TRANS("File already exists"), + TRANS("There's already a file called:\n\n") + + chosen.getFullPathName() + + T("\n\nAre you sure you want to overwrite it?"), + TRANS("overwrite"), + TRANS("cancel"))) + { + return userCancelledSave; + } + } + } - return saveAs (chosen, false, false, true); - } + return saveAs (chosen, false, false, true); + } - return userCancelledSave; + return userCancelledSave; } END_JUCE_NAMESPACE @@ -18793,7 +18557,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE RecentlyOpenedFilesList::RecentlyOpenedFilesList() - : maxNumberOfItems (10) + : maxNumberOfItems (10) { } @@ -18803,100 +18567,100 @@ RecentlyOpenedFilesList::~RecentlyOpenedFilesList() void RecentlyOpenedFilesList::setMaxNumberOfItems (const int newMaxNumber) { - maxNumberOfItems = jmax (1, newMaxNumber); + maxNumberOfItems = jmax (1, newMaxNumber); - while (getNumFiles() > maxNumberOfItems) - files.remove (getNumFiles() - 1); + while (getNumFiles() > maxNumberOfItems) + files.remove (getNumFiles() - 1); } int RecentlyOpenedFilesList::getNumFiles() const { - return files.size(); + return files.size(); } const File RecentlyOpenedFilesList::getFile (const int index) const { - return File (files [index]); + return File (files [index]); } void RecentlyOpenedFilesList::clear() { - files.clear(); + files.clear(); } void RecentlyOpenedFilesList::addFile (const File& file) { - const String path (file.getFullPathName()); + const String path (file.getFullPathName()); - files.removeString (path, true); - files.insert (0, path); + files.removeString (path, true); + files.insert (0, path); - setMaxNumberOfItems (maxNumberOfItems); + setMaxNumberOfItems (maxNumberOfItems); } void RecentlyOpenedFilesList::removeNonExistentFiles() { - for (int i = getNumFiles(); --i >= 0;) - if (! getFile(i).exists()) - files.remove (i); + for (int i = getNumFiles(); --i >= 0;) + if (! getFile(i).exists()) + files.remove (i); } int RecentlyOpenedFilesList::createPopupMenuItems (PopupMenu& menuToAddTo, - const int baseItemId, - const bool showFullPaths, - const bool dontAddNonExistentFiles, - const File** filesToAvoid) + const int baseItemId, + const bool showFullPaths, + const bool dontAddNonExistentFiles, + const File** filesToAvoid) { - int num = 0; + int num = 0; - for (int i = 0; i < getNumFiles(); ++i) - { - const File f (getFile(i)); + for (int i = 0; i < getNumFiles(); ++i) + { + const File f (getFile(i)); - if ((! dontAddNonExistentFiles) || f.exists()) - { - bool needsAvoiding = false; + if ((! dontAddNonExistentFiles) || f.exists()) + { + bool needsAvoiding = false; - if (filesToAvoid != 0) - { - const File** avoid = filesToAvoid; + if (filesToAvoid != 0) + { + const File** avoid = filesToAvoid; - while (*avoid != 0) - { - if (f == **avoid) - { - needsAvoiding = true; - break; - } + while (*avoid != 0) + { + if (f == **avoid) + { + needsAvoiding = true; + break; + } - ++avoid; - } - } + ++avoid; + } + } - if (! needsAvoiding) - { - menuToAddTo.addItem (baseItemId + i, - showFullPaths ? f.getFullPathName() - : f.getFileName()); - ++num; - } - } - } + if (! needsAvoiding) + { + menuToAddTo.addItem (baseItemId + i, + showFullPaths ? f.getFullPathName() + : f.getFileName()); + ++num; + } + } + } - return num; + return num; } const String RecentlyOpenedFilesList::toString() const { - return files.joinIntoString (T("\n")); + return files.joinIntoString (T("\n")); } void RecentlyOpenedFilesList::restoreFromString (const String& stringifiedVersion) { - clear(); - files.addLines (stringifiedVersion); + clear(); + files.addLines (stringifiedVersion); - setMaxNumberOfItems (maxNumberOfItems); + setMaxNumberOfItems (maxNumberOfItems); } END_JUCE_NAMESPACE @@ -18907,248 +18671,248 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE UndoManager::UndoManager (const int maxNumberOfUnitsToKeep, - const int minimumTransactions) + const int minimumTransactions) : totalUnitsStored (0), - nextIndex (0), - newTransaction (true), - reentrancyCheck (false) + nextIndex (0), + newTransaction (true), + reentrancyCheck (false) { - setMaxNumberOfStoredUnits (maxNumberOfUnitsToKeep, - minimumTransactions); + setMaxNumberOfStoredUnits (maxNumberOfUnitsToKeep, + minimumTransactions); } UndoManager::~UndoManager() { - clearUndoHistory(); + clearUndoHistory(); } void UndoManager::clearUndoHistory() { - transactions.clear(); - transactionNames.clear(); - totalUnitsStored = 0; - nextIndex = 0; - sendChangeMessage (this); + transactions.clear(); + transactionNames.clear(); + totalUnitsStored = 0; + nextIndex = 0; + sendChangeMessage (this); } int UndoManager::getNumberOfUnitsTakenUpByStoredCommands() const { - return totalUnitsStored; + return totalUnitsStored; } void UndoManager::setMaxNumberOfStoredUnits (const int maxNumberOfUnitsToKeep, - const int minimumTransactions) + const int minimumTransactions) { - maxNumUnitsToKeep = jmax (1, maxNumberOfUnitsToKeep); - minimumTransactionsToKeep = jmax (1, minimumTransactions); + maxNumUnitsToKeep = jmax (1, maxNumberOfUnitsToKeep); + minimumTransactionsToKeep = jmax (1, minimumTransactions); } bool UndoManager::perform (UndoableAction* const command, const String& actionName) { - if (command != 0) - { - if (actionName.isNotEmpty()) - currentTransactionName = actionName; + if (command != 0) + { + if (actionName.isNotEmpty()) + currentTransactionName = actionName; - if (reentrancyCheck) - { - jassertfalse // don't call perform() recursively from the UndoableAction::perform() or - // undo() methods, or else these actions won't actually get done. + if (reentrancyCheck) + { + jassertfalse // don't call perform() recursively from the UndoableAction::perform() or + // undo() methods, or else these actions won't actually get done. - return false; - } - else - { - bool success = false; + return false; + } + else + { + bool success = false; - JUCE_TRY - { - success = command->perform(); - } - JUCE_CATCH_EXCEPTION + JUCE_TRY + { + success = command->perform(); + } + JUCE_CATCH_EXCEPTION - jassert (success); - if (success) - { - if (nextIndex > 0 && ! newTransaction) - { - OwnedArray* commandSet = transactions [nextIndex - 1]; + jassert (success); + if (success) + { + if (nextIndex > 0 && ! newTransaction) + { + OwnedArray* commandSet = transactions [nextIndex - 1]; - jassert (commandSet != 0); - if (commandSet == 0) - return false; + jassert (commandSet != 0); + if (commandSet == 0) + return false; - commandSet->add (command); - } - else - { - OwnedArray* commandSet = new OwnedArray(); - commandSet->add (command); - transactions.insert (nextIndex, commandSet); - transactionNames.insert (nextIndex, currentTransactionName); - ++nextIndex; - } + commandSet->add (command); + } + else + { + OwnedArray* commandSet = new OwnedArray(); + commandSet->add (command); + transactions.insert (nextIndex, commandSet); + transactionNames.insert (nextIndex, currentTransactionName); + ++nextIndex; + } - totalUnitsStored += command->getSizeInUnits(); - newTransaction = false; - } + totalUnitsStored += command->getSizeInUnits(); + newTransaction = false; + } - while (nextIndex < transactions.size()) - { - const OwnedArray * const lastSet = transactions.getLast(); + while (nextIndex < transactions.size()) + { + const OwnedArray * const lastSet = transactions.getLast(); - for (int i = lastSet->size(); --i >= 0;) - totalUnitsStored -= lastSet->getUnchecked (i)->getSizeInUnits(); + for (int i = lastSet->size(); --i >= 0;) + totalUnitsStored -= lastSet->getUnchecked (i)->getSizeInUnits(); - transactions.removeLast(); - transactionNames.remove (transactionNames.size() - 1); - } + transactions.removeLast(); + transactionNames.remove (transactionNames.size() - 1); + } - while (nextIndex > 0 - && totalUnitsStored > maxNumUnitsToKeep - && transactions.size() > minimumTransactionsToKeep) - { - const OwnedArray * const firstSet = transactions.getFirst(); + while (nextIndex > 0 + && totalUnitsStored > maxNumUnitsToKeep + && transactions.size() > minimumTransactionsToKeep) + { + const OwnedArray * const firstSet = transactions.getFirst(); - for (int i = firstSet->size(); --i >= 0;) - totalUnitsStored -= firstSet->getUnchecked (i)->getSizeInUnits(); + for (int i = firstSet->size(); --i >= 0;) + totalUnitsStored -= firstSet->getUnchecked (i)->getSizeInUnits(); - jassert (totalUnitsStored >= 0); // something fishy going on if this fails! + jassert (totalUnitsStored >= 0); // something fishy going on if this fails! - transactions.remove (0); - transactionNames.remove (0); - --nextIndex; - } + transactions.remove (0); + transactionNames.remove (0); + --nextIndex; + } - sendChangeMessage (this); + sendChangeMessage (this); - return success; - } - } + return success; + } + } - return false; + return false; } void UndoManager::beginNewTransaction (const String& actionName) { - newTransaction = true; - currentTransactionName = actionName; + newTransaction = true; + currentTransactionName = actionName; } void UndoManager::setCurrentTransactionName (const String& newName) { - currentTransactionName = newName; + currentTransactionName = newName; } bool UndoManager::canUndo() const { - return nextIndex > 0; + return nextIndex > 0; } bool UndoManager::canRedo() const { - return nextIndex < transactions.size(); + return nextIndex < transactions.size(); } const String UndoManager::getUndoDescription() const { - return transactionNames [nextIndex - 1]; + return transactionNames [nextIndex - 1]; } const String UndoManager::getRedoDescription() const { - return transactionNames [nextIndex]; + return transactionNames [nextIndex]; } bool UndoManager::undo() { - const OwnedArray* const commandSet = transactions [nextIndex - 1]; + const OwnedArray* const commandSet = transactions [nextIndex - 1]; - if (commandSet == 0) - return false; + if (commandSet == 0) + return false; - reentrancyCheck = true; - bool failed = false; + reentrancyCheck = true; + bool failed = false; - for (int i = commandSet->size(); --i >= 0;) - { - if (! commandSet->getUnchecked(i)->undo()) - { - jassertfalse - failed = true; - break; - } - } + for (int i = commandSet->size(); --i >= 0;) + { + if (! commandSet->getUnchecked(i)->undo()) + { + jassertfalse + failed = true; + break; + } + } - reentrancyCheck = false; + reentrancyCheck = false; - if (failed) - { - clearUndoHistory(); - } - else - { - --nextIndex; - } + if (failed) + { + clearUndoHistory(); + } + else + { + --nextIndex; + } - beginNewTransaction(); + beginNewTransaction(); - sendChangeMessage (this); - return true; + sendChangeMessage (this); + return true; } bool UndoManager::redo() { - const OwnedArray* const commandSet = transactions [nextIndex]; + const OwnedArray* const commandSet = transactions [nextIndex]; - if (commandSet == 0) - return false; + if (commandSet == 0) + return false; - reentrancyCheck = true; - bool failed = false; + reentrancyCheck = true; + bool failed = false; - for (int i = 0; i < commandSet->size(); ++i) - { - if (! commandSet->getUnchecked(i)->perform()) - { - jassertfalse - failed = true; - break; - } - } + for (int i = 0; i < commandSet->size(); ++i) + { + if (! commandSet->getUnchecked(i)->perform()) + { + jassertfalse + failed = true; + break; + } + } - reentrancyCheck = false; + reentrancyCheck = false; - if (failed) - { - clearUndoHistory(); - } - else - { - ++nextIndex; - } + if (failed) + { + clearUndoHistory(); + } + else + { + ++nextIndex; + } - beginNewTransaction(); + beginNewTransaction(); - sendChangeMessage (this); - return true; + sendChangeMessage (this); + return true; } bool UndoManager::undoCurrentTransactionOnly() { - return newTransaction ? false - : undo(); + return newTransaction ? false + : undo(); } void UndoManager::getActionsInCurrentTransaction (Array & actionsFound) const { - const OwnedArray * const commandSet = transactions [nextIndex - 1]; + const OwnedArray * const commandSet = transactions [nextIndex - 1]; - if (commandSet != 0 && ! newTransaction) - { - for (int i = 0; i < commandSet->size(); ++i) - actionsFound.add (commandSet->getUnchecked(i)); - } + if (commandSet != 0 && ! newTransaction) + { + for (int i = 0; i < commandSet->size(); ++i) + actionsFound.add (commandSet->getUnchecked(i)); + } } END_JUCE_NAMESPACE @@ -19164,704 +18928,704 @@ static const tchar* const aiffExtensions[] = { T(".aiff"), T(".aif"), 0 }; class AiffAudioFormatReader : public AudioFormatReader { public: - int bytesPerFrame; - int64 dataChunkStart; - bool littleEndian; + int bytesPerFrame; + int64 dataChunkStart; + bool littleEndian; - AiffAudioFormatReader (InputStream* in) - : AudioFormatReader (in, TRANS (aiffFormatName)) - { - if (input->readInt() == chunkName ("FORM")) - { - const int len = input->readIntBigEndian(); - const int64 end = input->getPosition() + len; + AiffAudioFormatReader (InputStream* in) + : AudioFormatReader (in, TRANS (aiffFormatName)) + { + if (input->readInt() == chunkName ("FORM")) + { + const int len = input->readIntBigEndian(); + const int64 end = input->getPosition() + len; - const int nextType = input->readInt(); - if (nextType == chunkName ("AIFF") || nextType == chunkName ("AIFC")) - { - bool hasGotVer = false; - bool hasGotData = false; - bool hasGotType = false; + const int nextType = input->readInt(); + if (nextType == chunkName ("AIFF") || nextType == chunkName ("AIFC")) + { + bool hasGotVer = false; + bool hasGotData = false; + bool hasGotType = false; - while (input->getPosition() < end) - { - const int type = input->readInt(); - const uint32 length = (uint32) input->readIntBigEndian(); - const int64 chunkEnd = input->getPosition() + length; + while (input->getPosition() < end) + { + const int type = input->readInt(); + const uint32 length = (uint32) input->readIntBigEndian(); + const int64 chunkEnd = input->getPosition() + length; - if (type == chunkName ("FVER")) - { - hasGotVer = true; + if (type == chunkName ("FVER")) + { + hasGotVer = true; - const int ver = input->readIntBigEndian(); - if (ver != 0 && ver != (int)0xa2805140) - break; - } - else if (type == chunkName ("COMM")) - { - hasGotType = true; + const int ver = input->readIntBigEndian(); + if (ver != 0 && ver != (int)0xa2805140) + break; + } + else if (type == chunkName ("COMM")) + { + hasGotType = true; - numChannels = (unsigned int)input->readShortBigEndian(); - lengthInSamples = input->readIntBigEndian(); - bitsPerSample = input->readShortBigEndian(); - bytesPerFrame = (numChannels * bitsPerSample) >> 3; + numChannels = (unsigned int)input->readShortBigEndian(); + lengthInSamples = input->readIntBigEndian(); + bitsPerSample = input->readShortBigEndian(); + bytesPerFrame = (numChannels * bitsPerSample) >> 3; - unsigned char sampleRateBytes[10]; - input->read (sampleRateBytes, 10); - const int byte0 = sampleRateBytes[0]; + unsigned char sampleRateBytes[10]; + input->read (sampleRateBytes, 10); + const int byte0 = sampleRateBytes[0]; - if ((byte0 & 0x80) != 0 - || byte0 <= 0x3F || byte0 > 0x40 - || (byte0 == 0x40 && sampleRateBytes[1] > 0x1C)) - break; + if ((byte0 & 0x80) != 0 + || byte0 <= 0x3F || byte0 > 0x40 + || (byte0 == 0x40 && sampleRateBytes[1] > 0x1C)) + break; - unsigned int sampRate = ByteOrder::bigEndianInt ((char*) sampleRateBytes + 2); - sampRate >>= (16414 - ByteOrder::bigEndianShort ((char*) sampleRateBytes)); - sampleRate = (int) sampRate; + unsigned int sampRate = ByteOrder::bigEndianInt ((char*) sampleRateBytes + 2); + sampRate >>= (16414 - ByteOrder::bigEndianShort ((char*) sampleRateBytes)); + sampleRate = (int) sampRate; - if (length <= 18) - { - // some types don't have a chunk large enough to include a compression - // type, so assume it's just big-endian pcm - littleEndian = false; - } - else - { - const int compType = input->readInt(); + if (length <= 18) + { + // some types don't have a chunk large enough to include a compression + // type, so assume it's just big-endian pcm + littleEndian = false; + } + else + { + const int compType = input->readInt(); - if (compType == chunkName ("NONE") || compType == chunkName ("twos")) - { - littleEndian = false; - } - else if (compType == chunkName ("sowt")) - { - littleEndian = true; - } - else - { - sampleRate = 0; - break; - } - } - } - else if (type == chunkName ("SSND")) - { - hasGotData = true; + if (compType == chunkName ("NONE") || compType == chunkName ("twos")) + { + littleEndian = false; + } + else if (compType == chunkName ("sowt")) + { + littleEndian = true; + } + else + { + sampleRate = 0; + break; + } + } + } + else if (type == chunkName ("SSND")) + { + hasGotData = true; - const int offset = input->readIntBigEndian(); - dataChunkStart = input->getPosition() + 4 + offset; - lengthInSamples = (bytesPerFrame > 0) ? jmin (lengthInSamples, (int64) (length / bytesPerFrame)) : 0; - } - else if ((hasGotVer && hasGotData && hasGotType) - || chunkEnd < input->getPosition() - || input->isExhausted()) - { - break; - } + const int offset = input->readIntBigEndian(); + dataChunkStart = input->getPosition() + 4 + offset; + lengthInSamples = (bytesPerFrame > 0) ? jmin (lengthInSamples, (int64) (length / bytesPerFrame)) : 0; + } + else if ((hasGotVer && hasGotData && hasGotType) + || chunkEnd < input->getPosition() + || input->isExhausted()) + { + break; + } - input->setPosition (chunkEnd); - } - } - } - } + input->setPosition (chunkEnd); + } + } + } + } - ~AiffAudioFormatReader() - { - } + ~AiffAudioFormatReader() + { + } - bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples) - { - const int64 samplesAvailable = lengthInSamples - startSampleInFile; + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) + { + const int64 samplesAvailable = lengthInSamples - startSampleInFile; - if (samplesAvailable < numSamples) - { - for (int i = numDestChannels; --i >= 0;) - if (destSamples[i] != 0) - zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * numSamples); + if (samplesAvailable < numSamples) + { + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * numSamples); - numSamples = (int) samplesAvailable; - } + numSamples = (int) samplesAvailable; + } - if (numSamples <= 0) - return true; + if (numSamples <= 0) + return true; - input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame); + input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame); - const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3) - char tempBuffer [tempBufSize]; + const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3) + char tempBuffer [tempBufSize]; - while (numSamples > 0) - { - int* left = destSamples[0]; - if (left != 0) - left += startOffsetInDestBuffer; + while (numSamples > 0) + { + int* left = destSamples[0]; + if (left != 0) + left += startOffsetInDestBuffer; - int* right = numDestChannels > 1 ? destSamples[1] : 0; - if (right != 0) - right += startOffsetInDestBuffer; + int* right = numDestChannels > 1 ? destSamples[1] : 0; + if (right != 0) + right += startOffsetInDestBuffer; - const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples); - const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); + const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples); + const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); - if (bytesRead < numThisTime * bytesPerFrame) - zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); + if (bytesRead < numThisTime * bytesPerFrame) + zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); - if (bitsPerSample == 16) - { - if (littleEndian) - { - const short* src = (const short*) tempBuffer; + if (bitsPerSample == 16) + { + if (littleEndian) + { + const short* src = (const short*) tempBuffer; - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; - ++src; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; - *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; - } - } - } - else - { - const char* src = (const char*) tempBuffer; + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + ++src; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + } + } + } + else + { + const char* src = (const char*) tempBuffer; - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = ByteOrder::bigEndianShort (src) << 16; - src += 4; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - src += 2; - *left++ = ByteOrder::bigEndianShort (src) << 16; - src += 2; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ByteOrder::bigEndianShort (src) << 16; - src += 2; - *right++ = ByteOrder::bigEndianShort (src) << 16; - src += 2; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ByteOrder::bigEndianShort (src) << 16; - src += 2; - } - } - } - } - else if (bitsPerSample == 24) - { - const char* src = (const char*)tempBuffer; + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = ByteOrder::bigEndianShort (src) << 16; + src += 4; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + src += 2; + *left++ = ByteOrder::bigEndianShort (src) << 16; + src += 2; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ByteOrder::bigEndianShort (src) << 16; + src += 2; + *right++ = ByteOrder::bigEndianShort (src) << 16; + src += 2; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ByteOrder::bigEndianShort (src) << 16; + src += 2; + } + } + } + } + else if (bitsPerSample == 24) + { + const char* src = (const char*)tempBuffer; - if (littleEndian) - { - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = ByteOrder::littleEndian24Bit (src) << 8; - src += 6; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - src += 3; - *left++ = ByteOrder::littleEndian24Bit (src) << 8; - src += 3; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ByteOrder::littleEndian24Bit (src) << 8; - src += 3; - *right++ = ByteOrder::littleEndian24Bit (src) << 8; - src += 3; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ByteOrder::littleEndian24Bit (src) << 8; - src += 3; - } - } - } - else - { - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = ByteOrder::bigEndian24Bit (src) << 8; - src += 6; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - src += 3; - *left++ = ByteOrder::bigEndian24Bit (src) << 8; - src += 3; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ByteOrder::bigEndian24Bit (src) << 8; - src += 3; - *right++ = ByteOrder::bigEndian24Bit (src) << 8; - src += 3; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ByteOrder::bigEndian24Bit (src) << 8; - src += 3; - } - } - } - } - else if (bitsPerSample == 32) - { - const unsigned int* src = (const unsigned int*) tempBuffer; - unsigned int* l = (unsigned int*) left; - unsigned int* r = (unsigned int*) right; + if (littleEndian) + { + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = ByteOrder::littleEndian24Bit (src) << 8; + src += 6; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + src += 3; + *left++ = ByteOrder::littleEndian24Bit (src) << 8; + src += 3; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ByteOrder::littleEndian24Bit (src) << 8; + src += 3; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; + src += 3; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ByteOrder::littleEndian24Bit (src) << 8; + src += 3; + } + } + } + else + { + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = ByteOrder::bigEndian24Bit (src) << 8; + src += 6; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + src += 3; + *left++ = ByteOrder::bigEndian24Bit (src) << 8; + src += 3; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ByteOrder::bigEndian24Bit (src) << 8; + src += 3; + *right++ = ByteOrder::bigEndian24Bit (src) << 8; + src += 3; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ByteOrder::bigEndian24Bit (src) << 8; + src += 3; + } + } + } + } + else if (bitsPerSample == 32) + { + const unsigned int* src = (const unsigned int*) tempBuffer; + unsigned int* l = (unsigned int*) left; + unsigned int* r = (unsigned int*) right; - if (littleEndian) - { - if (numChannels > 1) - { - if (l == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *r++ = ByteOrder::swapIfBigEndian (*src++); - } - } - else if (r == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = ByteOrder::swapIfBigEndian (*src++); - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = ByteOrder::swapIfBigEndian (*src++); - *r++ = ByteOrder::swapIfBigEndian (*src++); - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = ByteOrder::swapIfBigEndian (*src++); - } - } - } - else - { - if (numChannels > 1) - { - if (l == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *r++ = ByteOrder::swapIfLittleEndian (*src++); - } - } - else if (r == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = ByteOrder::swapIfLittleEndian (*src++); - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = ByteOrder::swapIfLittleEndian (*src++); - *r++ = ByteOrder::swapIfLittleEndian (*src++); - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = ByteOrder::swapIfLittleEndian (*src++); - } - } - } + if (littleEndian) + { + if (numChannels > 1) + { + if (l == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *r++ = ByteOrder::swapIfBigEndian (*src++); + } + } + else if (r == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = ByteOrder::swapIfBigEndian (*src++); + ++src; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = ByteOrder::swapIfBigEndian (*src++); + *r++ = ByteOrder::swapIfBigEndian (*src++); + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = ByteOrder::swapIfBigEndian (*src++); + } + } + } + else + { + if (numChannels > 1) + { + if (l == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *r++ = ByteOrder::swapIfLittleEndian (*src++); + } + } + else if (r == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = ByteOrder::swapIfLittleEndian (*src++); + ++src; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = ByteOrder::swapIfLittleEndian (*src++); + *r++ = ByteOrder::swapIfLittleEndian (*src++); + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = ByteOrder::swapIfLittleEndian (*src++); + } + } + } - left = (int*) l; - right = (int*) r; - } - else if (bitsPerSample == 8) - { - const char* src = (const char*) tempBuffer; + left = (int*) l; + right = (int*) r; + } + else if (bitsPerSample == 8) + { + const char* src = (const char*) tempBuffer; - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *right++ = ((int) *src++) << 24; - ++src; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *left++ = ((int) *src++) << 24; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int) *src++) << 24; - *right++ = ((int) *src++) << 24; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int) *src++) << 24; - } - } - } + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *right++ = ((int) *src++) << 24; + ++src; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *left++ = ((int) *src++) << 24; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int) *src++) << 24; + *right++ = ((int) *src++) << 24; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int) *src++) << 24; + } + } + } - startOffsetInDestBuffer += numThisTime; - numSamples -= numThisTime; - } + startOffsetInDestBuffer += numThisTime; + numSamples -= numThisTime; + } - if (numSamples > 0) - { - for (int i = numDestChannels; --i >= 0;) - if (destSamples[i] != 0) - zeromem (destSamples[i] + startOffsetInDestBuffer, - sizeof (int) * numSamples); - } + if (numSamples > 0) + { + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); + } - return true; - } + return true; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AiffAudioFormatReader (const AiffAudioFormatReader&); - const AiffAudioFormatReader& operator= (const AiffAudioFormatReader&); + AiffAudioFormatReader (const AiffAudioFormatReader&); + const AiffAudioFormatReader& operator= (const AiffAudioFormatReader&); - static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } }; class AiffAudioFormatWriter : public AudioFormatWriter { - MemoryBlock tempBlock; - uint32 lengthInSamples, bytesWritten; - int64 headerPosition; - bool writeFailed; + MemoryBlock tempBlock; + uint32 lengthInSamples, bytesWritten; + int64 headerPosition; + bool writeFailed; - static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } - AiffAudioFormatWriter (const AiffAudioFormatWriter&); - const AiffAudioFormatWriter& operator= (const AiffAudioFormatWriter&); + AiffAudioFormatWriter (const AiffAudioFormatWriter&); + const AiffAudioFormatWriter& operator= (const AiffAudioFormatWriter&); - void writeHeader() - { - const bool couldSeekOk = output->setPosition (headerPosition); - (void) couldSeekOk; + void writeHeader() + { + const bool couldSeekOk = output->setPosition (headerPosition); + (void) couldSeekOk; - // if this fails, you've given it an output stream that can't seek! It needs - // to be able to seek back to write the header - jassert (couldSeekOk); + // if this fails, you've given it an output stream that can't seek! It needs + // to be able to seek back to write the header + jassert (couldSeekOk); - const int headerLen = 54; - int audioBytes = lengthInSamples * ((bitsPerSample * numChannels) / 8); - audioBytes += (audioBytes & 1); + const int headerLen = 54; + int audioBytes = lengthInSamples * ((bitsPerSample * numChannels) / 8); + audioBytes += (audioBytes & 1); - output->writeInt (chunkName ("FORM")); - output->writeIntBigEndian (headerLen + audioBytes - 8); - output->writeInt (chunkName ("AIFF")); - output->writeInt (chunkName ("COMM")); - output->writeIntBigEndian (18); - output->writeShortBigEndian ((short) numChannels); - output->writeIntBigEndian (lengthInSamples); - output->writeShortBigEndian ((short) bitsPerSample); + output->writeInt (chunkName ("FORM")); + output->writeIntBigEndian (headerLen + audioBytes - 8); + output->writeInt (chunkName ("AIFF")); + output->writeInt (chunkName ("COMM")); + output->writeIntBigEndian (18); + output->writeShortBigEndian ((short) numChannels); + output->writeIntBigEndian (lengthInSamples); + output->writeShortBigEndian ((short) bitsPerSample); - uint8 sampleRateBytes[10]; - zeromem (sampleRateBytes, 10); + uint8 sampleRateBytes[10]; + zeromem (sampleRateBytes, 10); - if (sampleRate <= 1) - { - sampleRateBytes[0] = 0x3f; - sampleRateBytes[1] = 0xff; - sampleRateBytes[2] = 0x80; - } - else - { - int mask = 0x40000000; - sampleRateBytes[0] = 0x40; + if (sampleRate <= 1) + { + sampleRateBytes[0] = 0x3f; + sampleRateBytes[1] = 0xff; + sampleRateBytes[2] = 0x80; + } + else + { + int mask = 0x40000000; + sampleRateBytes[0] = 0x40; - if (sampleRate >= mask) - { - jassertfalse - sampleRateBytes[1] = 0x1d; - } - else - { - int n = (int) sampleRate; + if (sampleRate >= mask) + { + jassertfalse + sampleRateBytes[1] = 0x1d; + } + else + { + int n = (int) sampleRate; - int i; - for (i = 0; i <= 32 ; ++i) - { - if ((n & mask) != 0) - break; + int i; + for (i = 0; i <= 32 ; ++i) + { + if ((n & mask) != 0) + break; - mask >>= 1; - } + mask >>= 1; + } - n = n << (i + 1); + n = n << (i + 1); - sampleRateBytes[1] = (uint8) (29 - i); - sampleRateBytes[2] = (uint8) ((n >> 24) & 0xff); - sampleRateBytes[3] = (uint8) ((n >> 16) & 0xff); - sampleRateBytes[4] = (uint8) ((n >> 8) & 0xff); - sampleRateBytes[5] = (uint8) (n & 0xff); - } - } + sampleRateBytes[1] = (uint8) (29 - i); + sampleRateBytes[2] = (uint8) ((n >> 24) & 0xff); + sampleRateBytes[3] = (uint8) ((n >> 16) & 0xff); + sampleRateBytes[4] = (uint8) ((n >> 8) & 0xff); + sampleRateBytes[5] = (uint8) (n & 0xff); + } + } - output->write (sampleRateBytes, 10); + output->write (sampleRateBytes, 10); - output->writeInt (chunkName ("SSND")); - output->writeIntBigEndian (audioBytes + 8); - output->writeInt (0); - output->writeInt (0); + output->writeInt (chunkName ("SSND")); + output->writeIntBigEndian (audioBytes + 8); + output->writeInt (0); + output->writeInt (0); - jassert (output->getPosition() == headerLen); - } + jassert (output->getPosition() == headerLen); + } public: - AiffAudioFormatWriter (OutputStream* out, - const double sampleRate_, - const unsigned int chans, - const int bits) - : AudioFormatWriter (out, - TRANS (aiffFormatName), - sampleRate_, - chans, - bits), - lengthInSamples (0), - bytesWritten (0), - writeFailed (false) - { - headerPosition = out->getPosition(); - writeHeader(); - } + AiffAudioFormatWriter (OutputStream* out, + const double sampleRate_, + const unsigned int chans, + const int bits) + : AudioFormatWriter (out, + TRANS (aiffFormatName), + sampleRate_, + chans, + bits), + lengthInSamples (0), + bytesWritten (0), + writeFailed (false) + { + headerPosition = out->getPosition(); + writeHeader(); + } - ~AiffAudioFormatWriter() - { - if ((bytesWritten & 1) != 0) - output->writeByte (0); + ~AiffAudioFormatWriter() + { + if ((bytesWritten & 1) != 0) + output->writeByte (0); - writeHeader(); - } + writeHeader(); + } - bool write (const int** data, int numSamples) - { - if (writeFailed) - return false; + bool write (const int** data, int numSamples) + { + if (writeFailed) + return false; - const int bytes = numChannels * numSamples * bitsPerSample / 8; - tempBlock.ensureSize (bytes, false); - char* buffer = (char*) tempBlock.getData(); + const int bytes = numChannels * numSamples * bitsPerSample / 8; + tempBlock.ensureSize (bytes, false); + char* buffer = (char*) tempBlock.getData(); - const int* left = data[0]; - const int* right = data[1]; - if (right == 0) - right = left; + const int* left = data[0]; + const int* right = data[1]; + if (right == 0) + right = left; - if (bitsPerSample == 16) - { - short* b = (short*) buffer; + if (bitsPerSample == 16) + { + short* b = (short*) buffer; - if (numChannels > 1) - { - for (int i = numSamples; --i >= 0;) - { - *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*left++ >> 16)); - *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*right++ >> 16)); - } - } - else - { - for (int i = numSamples; --i >= 0;) - { - *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*left++ >> 16)); - } - } - } - else if (bitsPerSample == 24) - { - char* b = (char*) buffer; + if (numChannels > 1) + { + for (int i = numSamples; --i >= 0;) + { + *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*left++ >> 16)); + *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*right++ >> 16)); + } + } + else + { + for (int i = numSamples; --i >= 0;) + { + *b++ = (short) ByteOrder::swapIfLittleEndian ((uint16) (*left++ >> 16)); + } + } + } + else if (bitsPerSample == 24) + { + char* b = (char*) buffer; - if (numChannels > 1) - { - for (int i = numSamples; --i >= 0;) - { - ByteOrder::bigEndian24BitToChars (*left++ >> 8, b); - b += 3; - ByteOrder::bigEndian24BitToChars (*right++ >> 8, b); - b += 3; - } - } - else - { - for (int i = numSamples; --i >= 0;) - { - ByteOrder::bigEndian24BitToChars (*left++ >> 8, b); - b += 3; - } - } - } - else if (bitsPerSample == 32) - { - uint32* b = (uint32*) buffer; + if (numChannels > 1) + { + for (int i = numSamples; --i >= 0;) + { + ByteOrder::bigEndian24BitToChars (*left++ >> 8, b); + b += 3; + ByteOrder::bigEndian24BitToChars (*right++ >> 8, b); + b += 3; + } + } + else + { + for (int i = numSamples; --i >= 0;) + { + ByteOrder::bigEndian24BitToChars (*left++ >> 8, b); + b += 3; + } + } + } + else if (bitsPerSample == 32) + { + uint32* b = (uint32*) buffer; - if (numChannels > 1) - { - for (int i = numSamples; --i >= 0;) - { - *b++ = ByteOrder::swapIfLittleEndian ((uint32) *left++); - *b++ = ByteOrder::swapIfLittleEndian ((uint32) *right++); - } - } - else - { - for (int i = numSamples; --i >= 0;) - { - *b++ = ByteOrder::swapIfLittleEndian ((uint32) *left++); - } - } - } - else if (bitsPerSample == 8) - { - char* b = (char*) buffer; + if (numChannels > 1) + { + for (int i = numSamples; --i >= 0;) + { + *b++ = ByteOrder::swapIfLittleEndian ((uint32) *left++); + *b++ = ByteOrder::swapIfLittleEndian ((uint32) *right++); + } + } + else + { + for (int i = numSamples; --i >= 0;) + { + *b++ = ByteOrder::swapIfLittleEndian ((uint32) *left++); + } + } + } + else if (bitsPerSample == 8) + { + char* b = (char*) buffer; - if (numChannels > 1) - { - for (int i = numSamples; --i >= 0;) - { - *b++ = (char) (*left++ >> 24); - *b++ = (char) (*right++ >> 24); - } - } - else - { - for (int i = numSamples; --i >= 0;) - { - *b++ = (char) (*left++ >> 24); - } - } - } + if (numChannels > 1) + { + for (int i = numSamples; --i >= 0;) + { + *b++ = (char) (*left++ >> 24); + *b++ = (char) (*right++ >> 24); + } + } + else + { + for (int i = numSamples; --i >= 0;) + { + *b++ = (char) (*left++ >> 24); + } + } + } - if (bytesWritten + bytes >= (uint32) 0xfff00000 - || ! output->write (buffer, bytes)) - { - // failed to write to disk, so let's try writing the header. - // If it's just run out of disk space, then if it does manage - // to write the header, we'll still have a useable file.. - writeHeader(); - writeFailed = true; - return false; - } - else - { - bytesWritten += bytes; - lengthInSamples += numSamples; + if (bytesWritten + bytes >= (uint32) 0xfff00000 + || ! output->write (buffer, bytes)) + { + // failed to write to disk, so let's try writing the header. + // If it's just run out of disk space, then if it does manage + // to write the header, we'll still have a useable file.. + writeHeader(); + writeFailed = true; + return false; + } + else + { + bytesWritten += bytes; + lengthInSamples += numSamples; - return true; - } - } + return true; + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; AiffAudioFormat::AiffAudioFormat() - : AudioFormat (TRANS (aiffFormatName), (const tchar**) aiffExtensions) + : AudioFormat (TRANS (aiffFormatName), (const tchar**) aiffExtensions) { } @@ -19871,68 +19635,68 @@ AiffAudioFormat::~AiffAudioFormat() const Array AiffAudioFormat::getPossibleSampleRates() { - const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 }; - return Array (rates); + const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 }; + return Array (rates); } const Array AiffAudioFormat::getPossibleBitDepths() { - const int depths[] = { 8, 16, 24, 0 }; - return Array (depths); + const int depths[] = { 8, 16, 24, 0 }; + return Array (depths); } bool AiffAudioFormat::canDoStereo() { - return true; + return true; } bool AiffAudioFormat::canDoMono() { - return true; + return true; } #if JUCE_MAC bool AiffAudioFormat::canHandleFile (const File& f) { - if (AudioFormat::canHandleFile (f)) - return true; + if (AudioFormat::canHandleFile (f)) + return true; - const OSType type = PlatformUtilities::getTypeOfFile (f.getFullPathName()); - return type == 'AIFF' || type == 'AIFC' - || type == 'aiff' || type == 'aifc'; + const OSType type = PlatformUtilities::getTypeOfFile (f.getFullPathName()); + return type == 'AIFF' || type == 'AIFC' + || type == 'aiff' || type == 'aifc'; } #endif AudioFormatReader* AiffAudioFormat::createReaderFor (InputStream* sourceStream, - const bool deleteStreamIfOpeningFails) + const bool deleteStreamIfOpeningFails) { - ScopedPointer w (new AiffAudioFormatReader (sourceStream)); + ScopedPointer w (new AiffAudioFormatReader (sourceStream)); - if (w->sampleRate != 0) - return w.release(); + if (w->sampleRate != 0) + return w.release(); - if (! deleteStreamIfOpeningFails) - w->input = 0; + if (! deleteStreamIfOpeningFails) + w->input = 0; - return 0; + return 0; } AudioFormatWriter* AiffAudioFormat::createWriterFor (OutputStream* out, - double sampleRate, - unsigned int chans, - int bitsPerSample, - const StringPairArray& /*metadataValues*/, - int /*qualityOptionIndex*/) + double sampleRate, + unsigned int chans, + int bitsPerSample, + const StringPairArray& /*metadataValues*/, + int /*qualityOptionIndex*/) { - if (getPossibleBitDepths().contains (bitsPerSample)) - { - return new AiffAudioFormatWriter (out, - sampleRate, - chans, - bitsPerSample); - } + if (getPossibleBitDepths().contains (bitsPerSample)) + { + return new AiffAudioFormatWriter (out, + sampleRate, + chans, + bitsPerSample); + } - return 0; + return 0; } END_JUCE_NAMESPACE @@ -19949,50 +19713,50 @@ BEGIN_JUCE_NAMESPACE static void findCDs (OwnedArray& cds) { - File volumes ("/Volumes"); - volumes.findChildFiles (cds, File::findDirectories, false); + File volumes ("/Volumes"); + volumes.findChildFiles (cds, File::findDirectories, false); - for (int i = cds.size(); --i >= 0;) - if (! cds[i]->getChildFile (".TOC.plist").exists()) - cds.remove (i); + for (int i = cds.size(); --i >= 0;) + if (! cds[i]->getChildFile (".TOC.plist").exists()) + cds.remove (i); } const StringArray AudioCDReader::getAvailableCDNames() { - OwnedArray cds; - findCDs (cds); + OwnedArray cds; + findCDs (cds); - StringArray names; + StringArray names; - for (int i = 0; i < cds.size(); ++i) - names.add (cds[i]->getFileName()); + for (int i = 0; i < cds.size(); ++i) + names.add (cds[i]->getFileName()); - return names; + return names; } AudioCDReader* AudioCDReader::createReaderForCD (const int index) { - OwnedArray cds; - findCDs (cds); + OwnedArray cds; + findCDs (cds); - if (cds[index] != 0) - return new AudioCDReader (*cds[index]); - else - return 0; + if (cds[index] != 0) + return new AudioCDReader (*cds[index]); + else + return 0; } AudioCDReader::AudioCDReader (const File& volume) : AudioFormatReader (0, "CD Audio"), - volumeDir (volume), - currentReaderTrack (-1), - reader (0) + volumeDir (volume), + currentReaderTrack (-1), + reader (0) { - sampleRate = 44100.0; - bitsPerSample = 16; - numChannels = 2; - usesFloatingPointData = false; + sampleRate = 44100.0; + bitsPerSample = 16; + numChannels = 2; + usesFloatingPointData = false; - refreshTrackLengths(); + refreshTrackLengths(); } AudioCDReader::~AudioCDReader() @@ -20001,146 +19765,146 @@ AudioCDReader::~AudioCDReader() static int getTrackNumber (const File& file) { - return file.getFileName() - .initialSectionContainingOnly (T("0123456789")) - .getIntValue(); + return file.getFileName() + .initialSectionContainingOnly (T("0123456789")) + .getIntValue(); } int AudioCDReader::compareElements (const File* const first, const File* const second) throw() { - const int firstTrack = getTrackNumber (*first); - const int secondTrack = getTrackNumber (*second); + const int firstTrack = getTrackNumber (*first); + const int secondTrack = getTrackNumber (*second); - jassert (firstTrack > 0 && secondTrack > 0); + jassert (firstTrack > 0 && secondTrack > 0); - return firstTrack - secondTrack; + return firstTrack - secondTrack; } void AudioCDReader::refreshTrackLengths() { - tracks.clear(); - trackStartSamples.clear(); - volumeDir.findChildFiles (tracks, File::findFiles | File::ignoreHiddenFiles, false, T("*.aiff")); + tracks.clear(); + trackStartSamples.clear(); + volumeDir.findChildFiles (tracks, File::findFiles | File::ignoreHiddenFiles, false, T("*.aiff")); - tracks.sort (*this); + tracks.sort (*this); - AiffAudioFormat format; - int sample = 0; + AiffAudioFormat format; + int sample = 0; - for (int i = 0; i < tracks.size(); ++i) - { - trackStartSamples.add (sample); + for (int i = 0; i < tracks.size(); ++i) + { + trackStartSamples.add (sample); - FileInputStream* const in = tracks[i]->createInputStream(); + FileInputStream* const in = tracks[i]->createInputStream(); - if (in != 0) - { - ScopedPointer r (format.createReaderFor (in, true)); + if (in != 0) + { + ScopedPointer r (format.createReaderFor (in, true)); - if (r != 0) - sample += (int) r->lengthInSamples; - } - } + if (r != 0) + sample += (int) r->lengthInSamples; + } + } - trackStartSamples.add (sample); - lengthInSamples = sample; + trackStartSamples.add (sample); + lengthInSamples = sample; } bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples) + int64 startSampleInFile, int numSamples) { - while (numSamples > 0) - { - int track = -1; + while (numSamples > 0) + { + int track = -1; - for (int i = 0; i < trackStartSamples.size() - 1; ++i) - { - if (startSampleInFile < trackStartSamples.getUnchecked (i + 1)) - { - track = i; - break; - } - } + for (int i = 0; i < trackStartSamples.size() - 1; ++i) + { + if (startSampleInFile < trackStartSamples.getUnchecked (i + 1)) + { + track = i; + break; + } + } - if (track < 0) - return false; + if (track < 0) + return false; - if (track != currentReaderTrack) - { - reader = 0; + if (track != currentReaderTrack) + { + reader = 0; - if (tracks [track] != 0) - { - FileInputStream* const in = tracks [track]->createInputStream(); + if (tracks [track] != 0) + { + FileInputStream* const in = tracks [track]->createInputStream(); - if (in != 0) - { - BufferedInputStream* const bin = new BufferedInputStream (in, 65536, true); + if (in != 0) + { + BufferedInputStream* const bin = new BufferedInputStream (in, 65536, true); - AiffAudioFormat format; - reader = format.createReaderFor (bin, true); + AiffAudioFormat format; + reader = format.createReaderFor (bin, true); - if (reader == 0) - currentReaderTrack = -1; - else - currentReaderTrack = track; - } - } - } + if (reader == 0) + currentReaderTrack = -1; + else + currentReaderTrack = track; + } + } + } - if (reader == 0) - return false; + if (reader == 0) + return false; - const int startPos = (int) (startSampleInFile - trackStartSamples.getUnchecked (track)); - const int numAvailable = (int) jmin ((int64) numSamples, reader->lengthInSamples - startPos); + const int startPos = (int) (startSampleInFile - trackStartSamples.getUnchecked (track)); + const int numAvailable = (int) jmin ((int64) numSamples, reader->lengthInSamples - startPos); - reader->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, startPos, numAvailable); + reader->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, startPos, numAvailable); - numSamples -= numAvailable; - startSampleInFile += numAvailable; - } + numSamples -= numAvailable; + startSampleInFile += numAvailable; + } - return true; + return true; } bool AudioCDReader::isCDStillPresent() const { - return volumeDir.exists(); + return volumeDir.exists(); } int AudioCDReader::getNumTracks() const { - return tracks.size(); + return tracks.size(); } int AudioCDReader::getPositionOfTrackStart (int trackNum) const { - return trackStartSamples [trackNum]; + return trackStartSamples [trackNum]; } bool AudioCDReader::isTrackAudio (int trackNum) const { - return tracks [trackNum] != 0; + return tracks [trackNum] != 0; } void AudioCDReader::enableIndexScanning (bool b) { - // any way to do this on a Mac?? + // any way to do this on a Mac?? } int AudioCDReader::getLastIndex() const { - return 0; + return 0; } const Array AudioCDReader::findIndexesInTrack (const int trackNumber) { - return Array (); + return Array (); } int AudioCDReader::getCDDBId() { - return 0; //xxx + return 0; //xxx } #endif @@ -20153,489 +19917,489 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioFormatReader::AudioFormatReader (InputStream* const in, - const String& formatName_) - : sampleRate (0), - bitsPerSample (0), - lengthInSamples (0), - numChannels (0), - usesFloatingPointData (false), - input (in), - formatName (formatName_) + const String& formatName_) + : sampleRate (0), + bitsPerSample (0), + lengthInSamples (0), + numChannels (0), + usesFloatingPointData (false), + input (in), + formatName (formatName_) { } AudioFormatReader::~AudioFormatReader() { - delete input; + delete input; } bool AudioFormatReader::read (int** destSamples, - int numDestChannels, - int64 startSampleInSource, - int numSamplesToRead, - const bool fillLeftoverChannelsWithCopies) + int numDestChannels, + int64 startSampleInSource, + int numSamplesToRead, + const bool fillLeftoverChannelsWithCopies) { - jassert (numDestChannels > 0); // you have to actually give this some channels to work with! + jassert (numDestChannels > 0); // you have to actually give this some channels to work with! - int startOffsetInDestBuffer = 0; + int startOffsetInDestBuffer = 0; - if (startSampleInSource < 0) - { - const int silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead); + if (startSampleInSource < 0) + { + const int silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead); - for (int i = numDestChannels; --i >= 0;) - if (destSamples[i] != 0) - zeromem (destSamples[i], sizeof (int) * silence); + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i], sizeof (int) * silence); - startOffsetInDestBuffer += silence; - numSamplesToRead -= silence; - startSampleInSource = 0; - } + startOffsetInDestBuffer += silence; + numSamplesToRead -= silence; + startSampleInSource = 0; + } - if (numSamplesToRead <= 0) - return true; + if (numSamplesToRead <= 0) + return true; - if (! readSamples (destSamples, jmin (numChannels, numDestChannels), startOffsetInDestBuffer, - startSampleInSource, numSamplesToRead)) - return false; + if (! readSamples (destSamples, jmin ((int) numChannels, numDestChannels), startOffsetInDestBuffer, + startSampleInSource, numSamplesToRead)) + return false; - if (numDestChannels > (int) numChannels) - { - if (fillLeftoverChannelsWithCopies) - { - int* lastFullChannel = destSamples[0]; + if (numDestChannels > (int) numChannels) + { + if (fillLeftoverChannelsWithCopies) + { + int* lastFullChannel = destSamples[0]; - for (int i = numDestChannels; --i > 0;) - { - if (destSamples[i] != 0) - { - lastFullChannel = destSamples[i]; - break; - } - } + for (int i = numDestChannels; --i > 0;) + { + if (destSamples[i] != 0) + { + lastFullChannel = destSamples[i]; + break; + } + } - if (lastFullChannel != 0) - for (int i = numChannels; i < numDestChannels; ++i) - if (destSamples[i] != 0) - memcpy (destSamples[i], lastFullChannel, sizeof (int) * numSamplesToRead); - } - else - { - for (int i = numChannels; i < numDestChannels; ++i) - if (destSamples[i] != 0) - zeromem (destSamples[i], sizeof (int) * numSamplesToRead); - } - } + if (lastFullChannel != 0) + for (int i = numChannels; i < numDestChannels; ++i) + if (destSamples[i] != 0) + memcpy (destSamples[i], lastFullChannel, sizeof (int) * numSamplesToRead); + } + else + { + for (int i = numChannels; i < numDestChannels; ++i) + if (destSamples[i] != 0) + zeromem (destSamples[i], sizeof (int) * numSamplesToRead); + } + } - return true; + return true; } static void findMaxMin (const float* src, const int num, - float& maxVal, float& minVal) + float& maxVal, float& minVal) { - float mn = src[0]; - float mx = mn; + float mn = src[0]; + float mx = mn; - for (int i = 1; i < num; ++i) - { - const float s = src[i]; - if (s > mx) - mx = s; - if (s < mn) - mn = s; - } + for (int i = 1; i < num; ++i) + { + const float s = src[i]; + if (s > mx) + mx = s; + if (s < mn) + mn = s; + } - maxVal = mx; - minVal = mn; + maxVal = mx; + minVal = mn; } void AudioFormatReader::readMaxLevels (int64 startSampleInFile, - int64 numSamples, - float& lowestLeft, float& highestLeft, - float& lowestRight, float& highestRight) + int64 numSamples, + float& lowestLeft, float& highestLeft, + float& lowestRight, float& highestRight) { - if (numSamples <= 0) - { - lowestLeft = 0; - lowestRight = 0; - highestLeft = 0; - highestRight = 0; - return; - } + if (numSamples <= 0) + { + lowestLeft = 0; + lowestRight = 0; + highestLeft = 0; + highestRight = 0; + return; + } - const int bufferSize = (int) jmin (numSamples, (int64) 4096); - MemoryBlock tempSpace (bufferSize * sizeof (int) * 2 + 64); + const int bufferSize = (int) jmin (numSamples, (int64) 4096); + MemoryBlock tempSpace (bufferSize * sizeof (int) * 2 + 64); - int* tempBuffer[3]; - tempBuffer[0] = (int*) tempSpace.getData(); - tempBuffer[1] = ((int*) tempSpace.getData()) + bufferSize; - tempBuffer[2] = 0; + int* tempBuffer[3]; + tempBuffer[0] = (int*) tempSpace.getData(); + tempBuffer[1] = ((int*) tempSpace.getData()) + bufferSize; + tempBuffer[2] = 0; - if (usesFloatingPointData) - { - float lmin = 1.0e6f; - float lmax = -lmin; - float rmin = lmin; - float rmax = lmax; + if (usesFloatingPointData) + { + float lmin = 1.0e6f; + float lmax = -lmin; + float rmin = lmin; + float rmax = lmax; - while (numSamples > 0) - { - const int numToDo = (int) jmin (numSamples, (int64) bufferSize); - read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false); + while (numSamples > 0) + { + const int numToDo = (int) jmin (numSamples, (int64) bufferSize); + read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false); - numSamples -= numToDo; - startSampleInFile += numToDo; + numSamples -= numToDo; + startSampleInFile += numToDo; - float bufmin, bufmax; - findMaxMin ((float*) tempBuffer[0], numToDo, bufmax, bufmin); - lmin = jmin (lmin, bufmin); - lmax = jmax (lmax, bufmax); + float bufmin, bufmax; + findMaxMin ((float*) tempBuffer[0], numToDo, bufmax, bufmin); + lmin = jmin (lmin, bufmin); + lmax = jmax (lmax, bufmax); - if (numChannels > 1) - { - findMaxMin ((float*) tempBuffer[1], numToDo, bufmax, bufmin); - rmin = jmin (rmin, bufmin); - rmax = jmax (rmax, bufmax); - } - } + if (numChannels > 1) + { + findMaxMin ((float*) tempBuffer[1], numToDo, bufmax, bufmin); + rmin = jmin (rmin, bufmin); + rmax = jmax (rmax, bufmax); + } + } - if (numChannels <= 1) - { - rmax = lmax; - rmin = lmin; - } + if (numChannels <= 1) + { + rmax = lmax; + rmin = lmin; + } - lowestLeft = lmin; - highestLeft = lmax; - lowestRight = rmin; - highestRight = rmax; - } - else - { - int lmax = INT_MIN; - int lmin = INT_MAX; - int rmax = INT_MIN; - int rmin = INT_MAX; + lowestLeft = lmin; + highestLeft = lmax; + lowestRight = rmin; + highestRight = rmax; + } + else + { + int lmax = INT_MIN; + int lmin = INT_MAX; + int rmax = INT_MIN; + int rmin = INT_MAX; - while (numSamples > 0) - { - const int numToDo = (int) jmin (numSamples, (int64) bufferSize); - read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false); + while (numSamples > 0) + { + const int numToDo = (int) jmin (numSamples, (int64) bufferSize); + read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false); - numSamples -= numToDo; - startSampleInFile += numToDo; + numSamples -= numToDo; + startSampleInFile += numToDo; - for (int j = numChannels; --j >= 0;) - { - int bufMax = INT_MIN; - int bufMin = INT_MAX; + for (int j = numChannels; --j >= 0;) + { + int bufMax = INT_MIN; + int bufMin = INT_MAX; - const int* const b = tempBuffer[j]; + const int* const b = tempBuffer[j]; - for (int i = 0; i < numToDo; ++i) - { - const int samp = b[i]; + for (int i = 0; i < numToDo; ++i) + { + const int samp = b[i]; - if (samp < bufMin) - bufMin = samp; + if (samp < bufMin) + bufMin = samp; - if (samp > bufMax) - bufMax = samp; - } + if (samp > bufMax) + bufMax = samp; + } - if (j == 0) - { - lmax = jmax (lmax, bufMax); - lmin = jmin (lmin, bufMin); - } - else - { - rmax = jmax (rmax, bufMax); - rmin = jmin (rmin, bufMin); - } - } - } + if (j == 0) + { + lmax = jmax (lmax, bufMax); + lmin = jmin (lmin, bufMin); + } + else + { + rmax = jmax (rmax, bufMax); + rmin = jmin (rmin, bufMin); + } + } + } - if (numChannels <= 1) - { - rmax = lmax; - rmin = lmin; - } + if (numChannels <= 1) + { + rmax = lmax; + rmin = lmin; + } - lowestLeft = lmin / (float)INT_MAX; - highestLeft = lmax / (float)INT_MAX; - lowestRight = rmin / (float)INT_MAX; - highestRight = rmax / (float)INT_MAX; - } + lowestLeft = lmin / (float)INT_MAX; + highestLeft = lmax / (float)INT_MAX; + lowestRight = rmin / (float)INT_MAX; + highestRight = rmax / (float)INT_MAX; + } } int64 AudioFormatReader::searchForLevel (int64 startSample, - int64 numSamplesToSearch, - const double magnitudeRangeMinimum, - const double magnitudeRangeMaximum, - const int minimumConsecutiveSamples) + int64 numSamplesToSearch, + const double magnitudeRangeMinimum, + const double magnitudeRangeMaximum, + const int minimumConsecutiveSamples) { - if (numSamplesToSearch == 0) - return -1; + if (numSamplesToSearch == 0) + return -1; - const int bufferSize = 4096; - MemoryBlock tempSpace (bufferSize * sizeof (int) * 2 + 64); + const int bufferSize = 4096; + MemoryBlock tempSpace (bufferSize * sizeof (int) * 2 + 64); - int* tempBuffer[3]; - tempBuffer[0] = (int*) tempSpace.getData(); - tempBuffer[1] = ((int*) tempSpace.getData()) + bufferSize; - tempBuffer[2] = 0; + int* tempBuffer[3]; + tempBuffer[0] = (int*) tempSpace.getData(); + tempBuffer[1] = ((int*) tempSpace.getData()) + bufferSize; + tempBuffer[2] = 0; - int consecutive = 0; - int64 firstMatchPos = -1; + int consecutive = 0; + int64 firstMatchPos = -1; - jassert (magnitudeRangeMaximum > magnitudeRangeMinimum); + jassert (magnitudeRangeMaximum > magnitudeRangeMinimum); - const double doubleMin = jlimit (0.0, (double) INT_MAX, magnitudeRangeMinimum * INT_MAX); - const double doubleMax = jlimit (doubleMin, (double) INT_MAX, magnitudeRangeMaximum * INT_MAX); - const int intMagnitudeRangeMinimum = roundDoubleToInt (doubleMin); - const int intMagnitudeRangeMaximum = roundDoubleToInt (doubleMax); + const double doubleMin = jlimit (0.0, (double) INT_MAX, magnitudeRangeMinimum * INT_MAX); + const double doubleMax = jlimit (doubleMin, (double) INT_MAX, magnitudeRangeMaximum * INT_MAX); + const int intMagnitudeRangeMinimum = roundToInt (doubleMin); + const int intMagnitudeRangeMaximum = roundToInt (doubleMax); - while (numSamplesToSearch != 0) - { - const int numThisTime = (int) jmin (abs64 (numSamplesToSearch), (int64) bufferSize); - int64 bufferStart = startSample; + while (numSamplesToSearch != 0) + { + const int numThisTime = (int) jmin (abs64 (numSamplesToSearch), (int64) bufferSize); + int64 bufferStart = startSample; - if (numSamplesToSearch < 0) - bufferStart -= numThisTime; + if (numSamplesToSearch < 0) + bufferStart -= numThisTime; - if (bufferStart >= (int) lengthInSamples) - break; + if (bufferStart >= (int) lengthInSamples) + break; - read ((int**) tempBuffer, 2, bufferStart, numThisTime, false); + read ((int**) tempBuffer, 2, bufferStart, numThisTime, false); - int num = numThisTime; - while (--num >= 0) - { - if (numSamplesToSearch < 0) - --startSample; + int num = numThisTime; + while (--num >= 0) + { + if (numSamplesToSearch < 0) + --startSample; - bool matches = false; - const int index = (int) (startSample - bufferStart); + bool matches = false; + const int index = (int) (startSample - bufferStart); - if (usesFloatingPointData) - { - const float sample1 = fabsf (((float*) tempBuffer[0]) [index]); + if (usesFloatingPointData) + { + const float sample1 = fabsf (((float*) tempBuffer[0]) [index]); - if (sample1 >= magnitudeRangeMinimum - && sample1 <= magnitudeRangeMaximum) - { - matches = true; - } - else if (numChannels > 1) - { - const float sample2 = fabsf (((float*) tempBuffer[1]) [index]); + if (sample1 >= magnitudeRangeMinimum + && sample1 <= magnitudeRangeMaximum) + { + matches = true; + } + else if (numChannels > 1) + { + const float sample2 = fabsf (((float*) tempBuffer[1]) [index]); - matches = (sample2 >= magnitudeRangeMinimum - && sample2 <= magnitudeRangeMaximum); - } - } - else - { - const int sample1 = abs (tempBuffer[0] [index]); + matches = (sample2 >= magnitudeRangeMinimum + && sample2 <= magnitudeRangeMaximum); + } + } + else + { + const int sample1 = abs (tempBuffer[0] [index]); - if (sample1 >= intMagnitudeRangeMinimum - && sample1 <= intMagnitudeRangeMaximum) - { - matches = true; - } - else if (numChannels > 1) - { - const int sample2 = abs (tempBuffer[1][index]); + if (sample1 >= intMagnitudeRangeMinimum + && sample1 <= intMagnitudeRangeMaximum) + { + matches = true; + } + else if (numChannels > 1) + { + const int sample2 = abs (tempBuffer[1][index]); - matches = (sample2 >= intMagnitudeRangeMinimum - && sample2 <= intMagnitudeRangeMaximum); - } - } + matches = (sample2 >= intMagnitudeRangeMinimum + && sample2 <= intMagnitudeRangeMaximum); + } + } - if (matches) - { - if (firstMatchPos < 0) - firstMatchPos = startSample; + if (matches) + { + if (firstMatchPos < 0) + firstMatchPos = startSample; - if (++consecutive >= minimumConsecutiveSamples) - { - if (firstMatchPos < 0 || firstMatchPos >= lengthInSamples) - return -1; + if (++consecutive >= minimumConsecutiveSamples) + { + if (firstMatchPos < 0 || firstMatchPos >= lengthInSamples) + return -1; - return firstMatchPos; - } - } - else - { - consecutive = 0; - firstMatchPos = -1; - } + return firstMatchPos; + } + } + else + { + consecutive = 0; + firstMatchPos = -1; + } - if (numSamplesToSearch > 0) - ++startSample; - } + if (numSamplesToSearch > 0) + ++startSample; + } - if (numSamplesToSearch > 0) - numSamplesToSearch -= numThisTime; - else - numSamplesToSearch += numThisTime; - } + if (numSamplesToSearch > 0) + numSamplesToSearch -= numThisTime; + else + numSamplesToSearch += numThisTime; + } - return -1; + return -1; } AudioFormatWriter::AudioFormatWriter (OutputStream* const out, - const String& formatName_, - const double rate, - const unsigned int numChannels_, - const unsigned int bitsPerSample_) + const String& formatName_, + const double rate, + const unsigned int numChannels_, + const unsigned int bitsPerSample_) : sampleRate (rate), - numChannels (numChannels_), - bitsPerSample (bitsPerSample_), - usesFloatingPointData (false), - output (out), - formatName (formatName_) + numChannels (numChannels_), + bitsPerSample (bitsPerSample_), + usesFloatingPointData (false), + output (out), + formatName (formatName_) { } AudioFormatWriter::~AudioFormatWriter() { - delete output; + delete output; } bool AudioFormatWriter::writeFromAudioReader (AudioFormatReader& reader, - int64 startSample, - int64 numSamplesToRead) + int64 startSample, + int64 numSamplesToRead) { - const int bufferSize = 16384; - const int maxChans = 128; - AudioSampleBuffer tempBuffer (reader.numChannels, bufferSize); - int* buffers [maxChans]; + const int bufferSize = 16384; + const int maxChans = 128; + AudioSampleBuffer tempBuffer (reader.numChannels, bufferSize); + int* buffers [maxChans]; - for (int i = maxChans; --i >= 0;) - buffers[i] = 0; + for (int i = maxChans; --i >= 0;) + buffers[i] = 0; - if (numSamplesToRead < 0) - numSamplesToRead = reader.lengthInSamples; + if (numSamplesToRead < 0) + numSamplesToRead = reader.lengthInSamples; - while (numSamplesToRead > 0) - { - const int numToDo = (int) jmin (numSamplesToRead, (int64) bufferSize); + while (numSamplesToRead > 0) + { + const int numToDo = (int) jmin (numSamplesToRead, (int64) bufferSize); - for (int i = tempBuffer.getNumChannels(); --i >= 0;) - buffers[i] = (int*) tempBuffer.getSampleData (i, 0); + for (int i = tempBuffer.getNumChannels(); --i >= 0;) + buffers[i] = (int*) tempBuffer.getSampleData (i, 0); - if (! reader.read (buffers, maxChans, startSample, numToDo, false)) - return false; + if (! reader.read (buffers, maxChans, startSample, numToDo, false)) + return false; - if (reader.usesFloatingPointData != isFloatingPoint()) - { - int** bufferChan = buffers; + if (reader.usesFloatingPointData != isFloatingPoint()) + { + int** bufferChan = buffers; - while (*bufferChan != 0) - { - int* b = *bufferChan++; + while (*bufferChan != 0) + { + int* b = *bufferChan++; - if (isFloatingPoint()) - { - // int -> float - const double factor = 1.0 / INT_MAX; + if (isFloatingPoint()) + { + // int -> float + const double factor = 1.0 / INT_MAX; - for (int i = 0; i < numToDo; ++i) - ((float*)b)[i] = (float) (factor * b[i]); - } - else - { - // float -> int - for (int i = 0; i < numToDo; ++i) - { - const double samp = *(const float*) b; + for (int i = 0; i < numToDo; ++i) + ((float*)b)[i] = (float) (factor * b[i]); + } + else + { + // float -> int + for (int i = 0; i < numToDo; ++i) + { + const double samp = *(const float*) b; - if (samp <= -1.0) - *b++ = INT_MIN; - else if (samp >= 1.0) - *b++ = INT_MAX; - else - *b++ = roundDoubleToInt (INT_MAX * samp); - } - } - } - } + if (samp <= -1.0) + *b++ = INT_MIN; + else if (samp >= 1.0) + *b++ = INT_MAX; + else + *b++ = roundToInt (INT_MAX * samp); + } + } + } + } - if (! write ((const int**) buffers, numToDo)) - return false; + if (! write ((const int**) buffers, numToDo)) + return false; - numSamplesToRead -= numToDo; - startSample += numToDo; - } + numSamplesToRead -= numToDo; + startSample += numToDo; + } - return true; + return true; } bool AudioFormatWriter::writeFromAudioSource (AudioSource& source, - int numSamplesToRead, - const int samplesPerBlock) + int numSamplesToRead, + const int samplesPerBlock) { - const int maxChans = 128; - AudioSampleBuffer tempBuffer (getNumChannels(), samplesPerBlock); - int* buffers [maxChans]; + const int maxChans = 128; + AudioSampleBuffer tempBuffer (getNumChannels(), samplesPerBlock); + int* buffers [maxChans]; - while (numSamplesToRead > 0) - { - const int numToDo = jmin (numSamplesToRead, samplesPerBlock); + while (numSamplesToRead > 0) + { + const int numToDo = jmin (numSamplesToRead, samplesPerBlock); - AudioSourceChannelInfo info; - info.buffer = &tempBuffer; - info.startSample = 0; - info.numSamples = numToDo; - info.clearActiveBufferRegion(); + AudioSourceChannelInfo info; + info.buffer = &tempBuffer; + info.startSample = 0; + info.numSamples = numToDo; + info.clearActiveBufferRegion(); - source.getNextAudioBlock (info); + source.getNextAudioBlock (info); - int i; - for (i = maxChans; --i >= 0;) - buffers[i] = 0; + int i; + for (i = maxChans; --i >= 0;) + buffers[i] = 0; - for (i = tempBuffer.getNumChannels(); --i >= 0;) - buffers[i] = (int*) tempBuffer.getSampleData (i, 0); + for (i = tempBuffer.getNumChannels(); --i >= 0;) + buffers[i] = (int*) tempBuffer.getSampleData (i, 0); - if (! isFloatingPoint()) - { - int** bufferChan = buffers; + if (! isFloatingPoint()) + { + int** bufferChan = buffers; - while (*bufferChan != 0) - { - int* b = *bufferChan++; + while (*bufferChan != 0) + { + int* b = *bufferChan++; - // float -> int - for (int j = numToDo; --j >= 0;) - { - const double samp = *(const float*) b; + // float -> int + for (int j = numToDo; --j >= 0;) + { + const double samp = *(const float*) b; - if (samp <= -1.0) - *b++ = INT_MIN; - else if (samp >= 1.0) - *b++ = INT_MAX; - else - *b++ = roundDoubleToInt (INT_MAX * samp); - } - } - } + if (samp <= -1.0) + *b++ = INT_MIN; + else if (samp >= 1.0) + *b++ = INT_MAX; + else + *b++ = roundToInt (INT_MAX * samp); + } + } + } - if (! write ((const int**) buffers, numToDo)) - return false; + if (! write ((const int**) buffers, numToDo)) + return false; - numSamplesToRead -= numToDo; - } + numSamplesToRead -= numToDo; + } - return true; + return true; } AudioFormat::AudioFormat (const String& name, - const tchar** const extensions) + const tchar** const extensions) : formatName (name), - fileExtensions (extensions) + fileExtensions (extensions) { } @@ -20645,31 +20409,31 @@ AudioFormat::~AudioFormat() const String& AudioFormat::getFormatName() const { - return formatName; + return formatName; } const StringArray& AudioFormat::getFileExtensions() const { - return fileExtensions; + return fileExtensions; } bool AudioFormat::canHandleFile (const File& f) { - for (int i = 0; i < fileExtensions.size(); ++i) - if (f.hasFileExtension (fileExtensions[i])) - return true; + for (int i = 0; i < fileExtensions.size(); ++i) + if (f.hasFileExtension (fileExtensions[i])) + return true; - return false; + return false; } bool AudioFormat::isCompressed() { - return false; + return false; } const StringArray AudioFormat::getQualityOptions() { - return StringArray(); + return StringArray(); } END_JUCE_NAMESPACE @@ -20680,185 +20444,184 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioFormatManager::AudioFormatManager() - : knownFormats (4), - defaultFormatIndex (0) + : defaultFormatIndex (0) { } AudioFormatManager::~AudioFormatManager() { - clearFormats(); - clearSingletonInstance(); + clearFormats(); + clearSingletonInstance(); } juce_ImplementSingleton (AudioFormatManager); void AudioFormatManager::registerFormat (AudioFormat* newFormat, - const bool makeThisTheDefaultFormat) + const bool makeThisTheDefaultFormat) { - jassert (newFormat != 0); + jassert (newFormat != 0); - if (newFormat != 0) - { + if (newFormat != 0) + { #ifdef JUCE_DEBUG - for (int i = getNumKnownFormats(); --i >= 0;) - { - if (getKnownFormat (i)->getFormatName() == newFormat->getFormatName()) - { - jassertfalse // trying to add the same format twice! - } - } + for (int i = getNumKnownFormats(); --i >= 0;) + { + if (getKnownFormat (i)->getFormatName() == newFormat->getFormatName()) + { + jassertfalse // trying to add the same format twice! + } + } #endif - if (makeThisTheDefaultFormat) - defaultFormatIndex = knownFormats.size(); + if (makeThisTheDefaultFormat) + defaultFormatIndex = knownFormats.size(); - knownFormats.add (newFormat); - } + knownFormats.add (newFormat); + } } void AudioFormatManager::registerBasicFormats() { #if JUCE_MAC - registerFormat (new AiffAudioFormat(), true); - registerFormat (new WavAudioFormat(), false); + registerFormat (new AiffAudioFormat(), true); + registerFormat (new WavAudioFormat(), false); #else - registerFormat (new WavAudioFormat(), true); - registerFormat (new AiffAudioFormat(), false); + registerFormat (new WavAudioFormat(), true); + registerFormat (new AiffAudioFormat(), false); #endif #if JUCE_USE_FLAC - registerFormat (new FlacAudioFormat(), false); + registerFormat (new FlacAudioFormat(), false); #endif #if JUCE_USE_OGGVORBIS - registerFormat (new OggVorbisAudioFormat(), false); + registerFormat (new OggVorbisAudioFormat(), false); #endif } void AudioFormatManager::clearFormats() { - for (int i = getNumKnownFormats(); --i >= 0;) - delete getKnownFormat(i); + for (int i = getNumKnownFormats(); --i >= 0;) + delete getKnownFormat(i); - knownFormats.clear(); - defaultFormatIndex = 0; + knownFormats.clear(); + defaultFormatIndex = 0; } int AudioFormatManager::getNumKnownFormats() const { - return knownFormats.size(); + return knownFormats.size(); } AudioFormat* AudioFormatManager::getKnownFormat (const int index) const { - return (AudioFormat*) knownFormats [index]; + return (AudioFormat*) knownFormats [index]; } AudioFormat* AudioFormatManager::getDefaultFormat() const { - return getKnownFormat (defaultFormatIndex); + return getKnownFormat (defaultFormatIndex); } AudioFormat* AudioFormatManager::findFormatForFileExtension (const String& fileExtension) const { - String e (fileExtension); - if (! e.startsWithChar (T('.'))) - e = T(".") + e; + String e (fileExtension); + if (! e.startsWithChar (T('.'))) + e = T(".") + e; - for (int i = 0; i < getNumKnownFormats(); ++i) - if (getKnownFormat(i)->getFileExtensions().contains (e, true)) - return getKnownFormat(i); + for (int i = 0; i < getNumKnownFormats(); ++i) + if (getKnownFormat(i)->getFileExtensions().contains (e, true)) + return getKnownFormat(i); - return 0; + return 0; } const String AudioFormatManager::getWildcardForAllFormats() const { - StringArray allExtensions; + StringArray allExtensions; - int i; - for (i = 0; i < getNumKnownFormats(); ++i) - allExtensions.addArray (getKnownFormat (i)->getFileExtensions()); + int i; + for (i = 0; i < getNumKnownFormats(); ++i) + allExtensions.addArray (getKnownFormat (i)->getFileExtensions()); - allExtensions.trim(); - allExtensions.removeEmptyStrings(); + allExtensions.trim(); + allExtensions.removeEmptyStrings(); - String s; - for (i = 0; i < allExtensions.size(); ++i) - { - s << T('*'); + String s; + for (i = 0; i < allExtensions.size(); ++i) + { + s << T('*'); - if (! allExtensions[i].startsWithChar (T('.'))) - s << T('.'); + if (! allExtensions[i].startsWithChar (T('.'))) + s << T('.'); - s << allExtensions[i]; + s << allExtensions[i]; - if (i < allExtensions.size() - 1) - s << T(';'); - } + if (i < allExtensions.size() - 1) + s << T(';'); + } - return s; + return s; } AudioFormatReader* AudioFormatManager::createReaderFor (const File& file) { - // you need to actually register some formats before the manager can - // use them to open a file! - jassert (knownFormats.size() > 0); + // you need to actually register some formats before the manager can + // use them to open a file! + jassert (knownFormats.size() > 0); - for (int i = 0; i < getNumKnownFormats(); ++i) - { - AudioFormat* const af = getKnownFormat(i); + for (int i = 0; i < getNumKnownFormats(); ++i) + { + AudioFormat* const af = getKnownFormat(i); - if (af->canHandleFile (file)) - { - InputStream* const in = file.createInputStream(); + if (af->canHandleFile (file)) + { + InputStream* const in = file.createInputStream(); - if (in != 0) - { - AudioFormatReader* const r = af->createReaderFor (in, true); + if (in != 0) + { + AudioFormatReader* const r = af->createReaderFor (in, true); - if (r != 0) - return r; - } - } - } + if (r != 0) + return r; + } + } + } - return 0; + return 0; } AudioFormatReader* AudioFormatManager::createReaderFor (InputStream* audioFileStream) { - // you need to actually register some formats before the manager can - // use them to open a file! - jassert (knownFormats.size() > 0); + // you need to actually register some formats before the manager can + // use them to open a file! + jassert (knownFormats.size() > 0); - ScopedPointer in (audioFileStream); + ScopedPointer in (audioFileStream); - if (in != 0) - { - const int64 originalStreamPos = in->getPosition(); + if (in != 0) + { + const int64 originalStreamPos = in->getPosition(); - for (int i = 0; i < getNumKnownFormats(); ++i) - { - AudioFormatReader* const r = getKnownFormat(i)->createReaderFor (in, false); + for (int i = 0; i < getNumKnownFormats(); ++i) + { + AudioFormatReader* const r = getKnownFormat(i)->createReaderFor (in, false); - if (r != 0) - { - in.release(); - return r; - } + if (r != 0) + { + in.release(); + return r; + } - in->setPosition (originalStreamPos); + in->setPosition (originalStreamPos); - // the stream that is passed-in must be capable of being repositioned so - // that all the formats can have a go at opening it. - jassert (in->getPosition() == originalStreamPos); - } - } + // the stream that is passed-in must be capable of being repositioned so + // that all the formats can have a go at opening it. + jassert (in->getPosition() == originalStreamPos); + } + } - return 0; + return 0; } END_JUCE_NAMESPACE @@ -20869,64 +20632,64 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioSubsectionReader::AudioSubsectionReader (AudioFormatReader* const source_, - const int64 startSample_, - const int64 length_, - const bool deleteSourceWhenDeleted_) + const int64 startSample_, + const int64 length_, + const bool deleteSourceWhenDeleted_) : AudioFormatReader (0, source_->getFormatName()), - source (source_), - startSample (startSample_), - deleteSourceWhenDeleted (deleteSourceWhenDeleted_) + source (source_), + startSample (startSample_), + deleteSourceWhenDeleted (deleteSourceWhenDeleted_) { - length = jmin (jmax ((int64) 0, source->lengthInSamples - startSample), length_); + length = jmin (jmax ((int64) 0, source->lengthInSamples - startSample), length_); - sampleRate = source->sampleRate; - bitsPerSample = source->bitsPerSample; - lengthInSamples = length; - numChannels = source->numChannels; - usesFloatingPointData = source->usesFloatingPointData; + sampleRate = source->sampleRate; + bitsPerSample = source->bitsPerSample; + lengthInSamples = length; + numChannels = source->numChannels; + usesFloatingPointData = source->usesFloatingPointData; } AudioSubsectionReader::~AudioSubsectionReader() { - if (deleteSourceWhenDeleted) - delete source; + if (deleteSourceWhenDeleted) + delete source; } bool AudioSubsectionReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples) + int64 startSampleInFile, int numSamples) { - if (startSampleInFile + numSamples > length) - { - for (int i = numDestChannels; --i >= 0;) - if (destSamples[i] != 0) - zeromem (destSamples[i], sizeof (int) * numSamples); + if (startSampleInFile + numSamples > length) + { + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i], sizeof (int) * numSamples); - numSamples = jmin (numSamples, (int) (length - startSampleInFile)); + numSamples = jmin (numSamples, (int) (length - startSampleInFile)); - if (numSamples <= 0) - return true; - } + if (numSamples <= 0) + return true; + } - return source->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, - startSampleInFile + startSample, numSamples); + return source->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, + startSampleInFile + startSample, numSamples); } void AudioSubsectionReader::readMaxLevels (int64 startSampleInFile, - int64 numSamples, - float& lowestLeft, - float& highestLeft, - float& lowestRight, - float& highestRight) + int64 numSamples, + float& lowestLeft, + float& highestLeft, + float& lowestRight, + float& highestRight) { - startSampleInFile = jmax ((int64) 0, startSampleInFile); - numSamples = jmax ((int64) 0, jmin (numSamples, length - startSampleInFile)); + startSampleInFile = jmax ((int64) 0, startSampleInFile); + numSamples = jmax ((int64) 0, jmin (numSamples, length - startSampleInFile)); - source->readMaxLevels (startSampleInFile + startSample, - numSamples, - lowestLeft, - highestLeft, - lowestRight, - highestRight); + source->readMaxLevels (startSampleInFile + startSample, + numSamples, + lowestLeft, + highestLeft, + lowestRight, + highestRight); } END_JUCE_NAMESPACE @@ -20940,15 +20703,15 @@ const int timeBeforeDeletingReader = 2000; struct AudioThumbnailDataFormat { - char thumbnailMagic[4]; - int samplesPerThumbSample; - int64 totalSamples; // source samples - int64 numFinishedSamples; // source samples - int numThumbnailSamples; - int numChannels; - int sampleRate; - char future[16]; - char data[1]; + char thumbnailMagic[4]; + int samplesPerThumbSample; + int64 totalSamples; // source samples + int64 numFinishedSamples; // source samples + int numThumbnailSamples; + int numChannels; + int sampleRate; + char future[16]; + char data[1]; }; #if JUCE_BIG_ENDIAN @@ -20958,476 +20721,476 @@ struct AudioThumbnailDataFormat static void swapEndiannessIfNeeded (AudioThumbnailDataFormat* const d) { - (void) d; + (void) d; #if JUCE_BIG_ENDIAN - swap (d->samplesPerThumbSample); - swap (d->totalSamples); - swap (d->numFinishedSamples); - swap (d->numThumbnailSamples); - swap (d->numChannels); - swap (d->sampleRate); + swap (d->samplesPerThumbSample); + swap (d->totalSamples); + swap (d->numFinishedSamples); + swap (d->numThumbnailSamples); + swap (d->numChannels); + swap (d->sampleRate); #endif } AudioThumbnail::AudioThumbnail (const int orginalSamplesPerThumbnailSample_, - AudioFormatManager& formatManagerToUse_, - AudioThumbnailCache& cacheToUse) - : formatManagerToUse (formatManagerToUse_), - cache (cacheToUse), - orginalSamplesPerThumbnailSample (orginalSamplesPerThumbnailSample_) + AudioFormatManager& formatManagerToUse_, + AudioThumbnailCache& cacheToUse) + : formatManagerToUse (formatManagerToUse_), + cache (cacheToUse), + orginalSamplesPerThumbnailSample (orginalSamplesPerThumbnailSample_) { - clear(); + clear(); } AudioThumbnail::~AudioThumbnail() { - cache.removeThumbnail (this); + cache.removeThumbnail (this); - const ScopedLock sl (readerLock); - reader = 0; + const ScopedLock sl (readerLock); + reader = 0; } void AudioThumbnail::setSource (InputSource* const newSource) { - cache.removeThumbnail (this); - timerCallback(); // stops the timer and deletes the reader + cache.removeThumbnail (this); + timerCallback(); // stops the timer and deletes the reader - source = newSource; - clear(); + source = newSource; + clear(); - if (newSource != 0 - && ! (cache.loadThumb (*this, newSource->hashCode()) - && isFullyLoaded())) - { - { - const ScopedLock sl (readerLock); - reader = createReader(); - } + if (newSource != 0 + && ! (cache.loadThumb (*this, newSource->hashCode()) + && isFullyLoaded())) + { + { + const ScopedLock sl (readerLock); + reader = createReader(); + } - if (reader != 0) - { - initialiseFromAudioFile (*reader); - cache.addThumbnail (this); - } - } + if (reader != 0) + { + initialiseFromAudioFile (*reader); + cache.addThumbnail (this); + } + } - sendChangeMessage (this); + sendChangeMessage (this); } bool AudioThumbnail::useTimeSlice() { - const ScopedLock sl (readerLock); + const ScopedLock sl (readerLock); - if (isFullyLoaded()) - { - if (reader != 0) - startTimer (timeBeforeDeletingReader); + if (isFullyLoaded()) + { + if (reader != 0) + startTimer (timeBeforeDeletingReader); - cache.removeThumbnail (this); - return false; - } + cache.removeThumbnail (this); + return false; + } - if (reader == 0) - reader = createReader(); + if (reader == 0) + reader = createReader(); - if (reader != 0) - { - readNextBlockFromAudioFile (*reader); - stopTimer(); + if (reader != 0) + { + readNextBlockFromAudioFile (*reader); + stopTimer(); - sendChangeMessage (this); + sendChangeMessage (this); - const bool justFinished = isFullyLoaded(); + const bool justFinished = isFullyLoaded(); - if (justFinished) - cache.storeThumb (*this, source->hashCode()); + if (justFinished) + cache.storeThumb (*this, source->hashCode()); - return ! justFinished; - } + return ! justFinished; + } - return false; + return false; } AudioFormatReader* AudioThumbnail::createReader() const { - if (source != 0) - { - InputStream* const audioFileStream = source->createInputStream(); + if (source != 0) + { + InputStream* const audioFileStream = source->createInputStream(); - if (audioFileStream != 0) - return formatManagerToUse.createReaderFor (audioFileStream); - } + if (audioFileStream != 0) + return formatManagerToUse.createReaderFor (audioFileStream); + } - return 0; + return 0; } void AudioThumbnail::timerCallback() { - stopTimer(); + stopTimer(); - const ScopedLock sl (readerLock); - reader = 0; + const ScopedLock sl (readerLock); + reader = 0; } void AudioThumbnail::clear() { - data.setSize (sizeof (AudioThumbnailDataFormat) + 3); + data.setSize (sizeof (AudioThumbnailDataFormat) + 3); - AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); + AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); - d->thumbnailMagic[0] = 'j'; - d->thumbnailMagic[1] = 'a'; - d->thumbnailMagic[2] = 't'; - d->thumbnailMagic[3] = 'm'; + d->thumbnailMagic[0] = 'j'; + d->thumbnailMagic[1] = 'a'; + d->thumbnailMagic[2] = 't'; + d->thumbnailMagic[3] = 'm'; - d->samplesPerThumbSample = orginalSamplesPerThumbnailSample; - d->totalSamples = 0; - d->numFinishedSamples = 0; - d->numThumbnailSamples = 0; - d->numChannels = 0; - d->sampleRate = 0; + d->samplesPerThumbSample = orginalSamplesPerThumbnailSample; + d->totalSamples = 0; + d->numFinishedSamples = 0; + d->numThumbnailSamples = 0; + d->numChannels = 0; + d->sampleRate = 0; - numSamplesCached = 0; - cacheNeedsRefilling = true; + numSamplesCached = 0; + cacheNeedsRefilling = true; } void AudioThumbnail::loadFrom (InputStream& input) { - const ScopedLock sl (readerLock); + const ScopedLock sl (readerLock); - data.setSize (0); - input.readIntoMemoryBlock (data); + data.setSize (0); + input.readIntoMemoryBlock (data); - AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); - swapEndiannessIfNeeded (d); + AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); + swapEndiannessIfNeeded (d); - if (! (d->thumbnailMagic[0] == 'j' - && d->thumbnailMagic[1] == 'a' - && d->thumbnailMagic[2] == 't' - && d->thumbnailMagic[3] == 'm')) - { - clear(); - } + if (! (d->thumbnailMagic[0] == 'j' + && d->thumbnailMagic[1] == 'a' + && d->thumbnailMagic[2] == 't' + && d->thumbnailMagic[3] == 'm')) + { + clear(); + } - numSamplesCached = 0; - cacheNeedsRefilling = true; + numSamplesCached = 0; + cacheNeedsRefilling = true; } void AudioThumbnail::saveTo (OutputStream& output) const { - AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); - swapEndiannessIfNeeded (d); - output.write (data.getData(), data.getSize()); - swapEndiannessIfNeeded (d); + AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); + swapEndiannessIfNeeded (d); + output.write (data.getData(), (int) data.getSize()); + swapEndiannessIfNeeded (d); } bool AudioThumbnail::initialiseFromAudioFile (AudioFormatReader& fileReader) { - AudioThumbnailDataFormat* d = (AudioThumbnailDataFormat*) data.getData(); + AudioThumbnailDataFormat* d = (AudioThumbnailDataFormat*) data.getData(); - d->totalSamples = fileReader.lengthInSamples; - d->numChannels = jmin (2, fileReader.numChannels); - d->numFinishedSamples = 0; - d->sampleRate = roundDoubleToInt (fileReader.sampleRate); - d->numThumbnailSamples = (int) (d->totalSamples / d->samplesPerThumbSample) + 1; + d->totalSamples = fileReader.lengthInSamples; + d->numChannels = jmin ((uint32) 2, fileReader.numChannels); + d->numFinishedSamples = 0; + d->sampleRate = roundToInt (fileReader.sampleRate); + d->numThumbnailSamples = (int) (d->totalSamples / d->samplesPerThumbSample) + 1; - data.setSize (sizeof (AudioThumbnailDataFormat) + 3 + d->numThumbnailSamples * d->numChannels * 2); + data.setSize (sizeof (AudioThumbnailDataFormat) + 3 + d->numThumbnailSamples * d->numChannels * 2); - d = (AudioThumbnailDataFormat*) data.getData(); - zeromem (&(d->data[0]), d->numThumbnailSamples * d->numChannels * 2); + d = (AudioThumbnailDataFormat*) data.getData(); + zeromem (&(d->data[0]), d->numThumbnailSamples * d->numChannels * 2); - return d->totalSamples > 0; + return d->totalSamples > 0; } bool AudioThumbnail::readNextBlockFromAudioFile (AudioFormatReader& fileReader) { - AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); + AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); - if (d->numFinishedSamples < d->totalSamples) - { - const int numToDo = (int) jmin ((int64) 65536, d->totalSamples - d->numFinishedSamples); + if (d->numFinishedSamples < d->totalSamples) + { + const int numToDo = (int) jmin ((int64) 65536, d->totalSamples - d->numFinishedSamples); - generateSection (fileReader, - d->numFinishedSamples, - numToDo); + generateSection (fileReader, + d->numFinishedSamples, + numToDo); - d->numFinishedSamples += numToDo; - } + d->numFinishedSamples += numToDo; + } - cacheNeedsRefilling = true; - return (d->numFinishedSamples < d->totalSamples); + cacheNeedsRefilling = true; + return (d->numFinishedSamples < d->totalSamples); } int AudioThumbnail::getNumChannels() const throw() { - const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData(); - jassert (d != 0); + const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData(); + jassert (d != 0); - return d->numChannels; + return d->numChannels; } double AudioThumbnail::getTotalLength() const throw() { - const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData(); - jassert (d != 0); + const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData(); + jassert (d != 0); - if (d->sampleRate > 0) - return d->totalSamples / (double)d->sampleRate; - else - return 0.0; + if (d->sampleRate > 0) + return d->totalSamples / (double)d->sampleRate; + else + return 0.0; } void AudioThumbnail::generateSection (AudioFormatReader& fileReader, - int64 startSample, - int numSamples) + int64 startSample, + int numSamples) { - AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); - jassert (d != 0); + AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); + jassert (d != 0); - int firstDataPos = (int) (startSample / d->samplesPerThumbSample); - int lastDataPos = (int) ((startSample + numSamples) / d->samplesPerThumbSample); + int firstDataPos = (int) (startSample / d->samplesPerThumbSample); + int lastDataPos = (int) ((startSample + numSamples) / d->samplesPerThumbSample); - char* l = getChannelData (0); - char* r = getChannelData (1); + char* l = getChannelData (0); + char* r = getChannelData (1); - for (int i = firstDataPos; i < lastDataPos; ++i) - { - const int sourceStart = i * d->samplesPerThumbSample; - const int sourceEnd = sourceStart + d->samplesPerThumbSample; + for (int i = firstDataPos; i < lastDataPos; ++i) + { + const int sourceStart = i * d->samplesPerThumbSample; + const int sourceEnd = sourceStart + d->samplesPerThumbSample; - float lowestLeft, highestLeft, lowestRight, highestRight; + float lowestLeft, highestLeft, lowestRight, highestRight; - fileReader.readMaxLevels (sourceStart, - sourceEnd - sourceStart, - lowestLeft, - highestLeft, - lowestRight, - highestRight); + fileReader.readMaxLevels (sourceStart, + sourceEnd - sourceStart, + lowestLeft, + highestLeft, + lowestRight, + highestRight); - int n = i * 2; + int n = i * 2; - if (r != 0) - { - l [n] = (char) jlimit (-128.0f, 127.0f, lowestLeft * 127.0f); - r [n++] = (char) jlimit (-128.0f, 127.0f, lowestRight * 127.0f); - l [n] = (char) jlimit (-128.0f, 127.0f, highestLeft * 127.0f); - r [n++] = (char) jlimit (-128.0f, 127.0f, highestRight * 127.0f); - } - else - { - l [n++] = (char) jlimit (-128.0f, 127.0f, lowestLeft * 127.0f); - l [n++] = (char) jlimit (-128.0f, 127.0f, highestLeft * 127.0f); - } - } + if (r != 0) + { + l [n] = (char) jlimit (-128.0f, 127.0f, lowestLeft * 127.0f); + r [n++] = (char) jlimit (-128.0f, 127.0f, lowestRight * 127.0f); + l [n] = (char) jlimit (-128.0f, 127.0f, highestLeft * 127.0f); + r [n++] = (char) jlimit (-128.0f, 127.0f, highestRight * 127.0f); + } + else + { + l [n++] = (char) jlimit (-128.0f, 127.0f, lowestLeft * 127.0f); + l [n++] = (char) jlimit (-128.0f, 127.0f, highestLeft * 127.0f); + } + } } char* AudioThumbnail::getChannelData (int channel) const { - AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); - jassert (d != 0); + AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData(); + jassert (d != 0); - if (channel >= 0 && channel < d->numChannels) - return d->data + (channel * 2 * d->numThumbnailSamples); + if (channel >= 0 && channel < d->numChannels) + return d->data + (channel * 2 * d->numThumbnailSamples); - return 0; + return 0; } bool AudioThumbnail::isFullyLoaded() const throw() { - const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData(); - jassert (d != 0); + const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData(); + jassert (d != 0); - return d->numFinishedSamples >= d->totalSamples; + return d->numFinishedSamples >= d->totalSamples; } void AudioThumbnail::refillCache (const int numSamples, - double startTime, - const double timePerPixel) + double startTime, + const double timePerPixel) { - const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData(); - jassert (d != 0); + const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData(); + jassert (d != 0); - if (numSamples <= 0 - || timePerPixel <= 0.0 - || d->sampleRate <= 0) - { - numSamplesCached = 0; - cacheNeedsRefilling = true; - return; - } + if (numSamples <= 0 + || timePerPixel <= 0.0 + || d->sampleRate <= 0) + { + numSamplesCached = 0; + cacheNeedsRefilling = true; + return; + } - if (numSamples == numSamplesCached - && numChannelsCached == d->numChannels - && startTime == cachedStart - && timePerPixel == cachedTimePerPixel - && ! cacheNeedsRefilling) - { - return; - } + if (numSamples == numSamplesCached + && numChannelsCached == d->numChannels + && startTime == cachedStart + && timePerPixel == cachedTimePerPixel + && ! cacheNeedsRefilling) + { + return; + } - numSamplesCached = numSamples; - numChannelsCached = d->numChannels; - cachedStart = startTime; - cachedTimePerPixel = timePerPixel; + numSamplesCached = numSamples; + numChannelsCached = d->numChannels; + cachedStart = startTime; + cachedTimePerPixel = timePerPixel; - cachedLevels.ensureSize (2 * numChannelsCached * numSamples); + cachedLevels.ensureSize (2 * numChannelsCached * numSamples); - const bool needExtraDetail = (timePerPixel * d->sampleRate <= d->samplesPerThumbSample); + const bool needExtraDetail = (timePerPixel * d->sampleRate <= d->samplesPerThumbSample); - const ScopedLock sl (readerLock); + const ScopedLock sl (readerLock); - cacheNeedsRefilling = false; + cacheNeedsRefilling = false; - if (needExtraDetail && reader == 0) - reader = createReader(); + if (needExtraDetail && reader == 0) + reader = createReader(); - if (reader != 0 && timePerPixel * d->sampleRate <= d->samplesPerThumbSample) - { - startTimer (timeBeforeDeletingReader); + if (reader != 0 && timePerPixel * d->sampleRate <= d->samplesPerThumbSample) + { + startTimer (timeBeforeDeletingReader); - char* cacheData = (char*) cachedLevels.getData(); - int sample = roundDoubleToInt (startTime * d->sampleRate); + char* cacheData = (char*) cachedLevels.getData(); + int sample = roundToInt (startTime * d->sampleRate); - for (int i = numSamples; --i >= 0;) - { - const int nextSample = roundDoubleToInt ((startTime + timePerPixel) * d->sampleRate); + for (int i = numSamples; --i >= 0;) + { + const int nextSample = roundToInt ((startTime + timePerPixel) * d->sampleRate); - if (sample >= 0) - { - if (sample >= reader->lengthInSamples) - break; + if (sample >= 0) + { + if (sample >= reader->lengthInSamples) + break; - float lmin, lmax, rmin, rmax; + float lmin, lmax, rmin, rmax; - reader->readMaxLevels (sample, - jmax (1, nextSample - sample), - lmin, lmax, rmin, rmax); + reader->readMaxLevels (sample, + jmax (1, nextSample - sample), + lmin, lmax, rmin, rmax); - cacheData[0] = (char) jlimit (-128, 127, roundFloatToInt (lmin * 127.0f)); - cacheData[1] = (char) jlimit (-128, 127, roundFloatToInt (lmax * 127.0f)); + cacheData[0] = (char) jlimit (-128, 127, roundFloatToInt (lmin * 127.0f)); + cacheData[1] = (char) jlimit (-128, 127, roundFloatToInt (lmax * 127.0f)); - if (numChannelsCached > 1) - { - cacheData[2] = (char) jlimit (-128, 127, roundFloatToInt (rmin * 127.0f)); - cacheData[3] = (char) jlimit (-128, 127, roundFloatToInt (rmax * 127.0f)); - } + if (numChannelsCached > 1) + { + cacheData[2] = (char) jlimit (-128, 127, roundFloatToInt (rmin * 127.0f)); + cacheData[3] = (char) jlimit (-128, 127, roundFloatToInt (rmax * 127.0f)); + } - cacheData += 2 * numChannelsCached; - } + cacheData += 2 * numChannelsCached; + } - startTime += timePerPixel; - sample = nextSample; - } - } - else - { - for (int channelNum = 0; channelNum < numChannelsCached; ++channelNum) - { - char* const channelData = getChannelData (channelNum); - char* cacheData = ((char*) cachedLevels.getData()) + channelNum * 2; + startTime += timePerPixel; + sample = nextSample; + } + } + else + { + for (int channelNum = 0; channelNum < numChannelsCached; ++channelNum) + { + char* const channelData = getChannelData (channelNum); + char* cacheData = ((char*) cachedLevels.getData()) + channelNum * 2; - const double timeToThumbSampleFactor = d->sampleRate / (double) d->samplesPerThumbSample; + const double timeToThumbSampleFactor = d->sampleRate / (double) d->samplesPerThumbSample; - startTime = cachedStart; - int sample = roundDoubleToInt (startTime * timeToThumbSampleFactor); - const int numFinished = (int) (d->numFinishedSamples / d->samplesPerThumbSample); + startTime = cachedStart; + int sample = roundToInt (startTime * timeToThumbSampleFactor); + const int numFinished = (int) (d->numFinishedSamples / d->samplesPerThumbSample); - for (int i = numSamples; --i >= 0;) - { - const int nextSample = roundDoubleToInt ((startTime + timePerPixel) * timeToThumbSampleFactor); + for (int i = numSamples; --i >= 0;) + { + const int nextSample = roundToInt ((startTime + timePerPixel) * timeToThumbSampleFactor); - if (sample >= 0 && channelData != 0) - { - char mx = -128; - char mn = 127; + if (sample >= 0 && channelData != 0) + { + char mx = -128; + char mn = 127; - while (sample <= nextSample) - { - if (sample >= numFinished) - break; + while (sample <= nextSample) + { + if (sample >= numFinished) + break; - const int n = sample << 1; - const char sampMin = channelData [n]; - const char sampMax = channelData [n + 1]; + const int n = sample << 1; + const char sampMin = channelData [n]; + const char sampMax = channelData [n + 1]; - if (sampMin < mn) - mn = sampMin; + if (sampMin < mn) + mn = sampMin; - if (sampMax > mx) - mx = sampMax; + if (sampMax > mx) + mx = sampMax; - ++sample; - } + ++sample; + } - if (mn <= mx) - { - cacheData[0] = mn; - cacheData[1] = mx; - } - else - { - cacheData[0] = 1; - cacheData[1] = 0; - } - } - else - { - cacheData[0] = 1; - cacheData[1] = 0; - } + if (mn <= mx) + { + cacheData[0] = mn; + cacheData[1] = mx; + } + else + { + cacheData[0] = 1; + cacheData[1] = 0; + } + } + else + { + cacheData[0] = 1; + cacheData[1] = 0; + } - cacheData += numChannelsCached * 2; - startTime += timePerPixel; - sample = nextSample; - } - } - } + cacheData += numChannelsCached * 2; + startTime += timePerPixel; + sample = nextSample; + } + } + } } void AudioThumbnail::drawChannel (Graphics& g, - int x, int y, int w, int h, - double startTime, - double endTime, - int channelNum, - const float verticalZoomFactor) + int x, int y, int w, int h, + double startTime, + double endTime, + int channelNum, + const float verticalZoomFactor) { - refillCache (w, startTime, (endTime - startTime) / w); + refillCache (w, startTime, (endTime - startTime) / w); - if (numSamplesCached >= w - && channelNum >= 0 - && channelNum < numChannelsCached) - { - const float topY = (float) y; - const float bottomY = topY + h; - const float midY = topY + h * 0.5f; - const float vscale = verticalZoomFactor * h / 256.0f; + if (numSamplesCached >= w + && channelNum >= 0 + && channelNum < numChannelsCached) + { + const float topY = (float) y; + const float bottomY = topY + h; + const float midY = topY + h * 0.5f; + const float vscale = verticalZoomFactor * h / 256.0f; - const Rectangle clip (g.getClipBounds()); - const int skipLeft = jlimit (0, w, clip.getX() - x); - w -= skipLeft; - x += skipLeft; + const Rectangle clip (g.getClipBounds()); + const int skipLeft = jlimit (0, w, clip.getX() - x); + w -= skipLeft; + x += skipLeft; - const char* cacheData = ((const char*) cachedLevels.getData()) - + (channelNum << 1) - + skipLeft * (numChannelsCached << 1); + const char* cacheData = ((const char*) cachedLevels.getData()) + + (channelNum << 1) + + skipLeft * (numChannelsCached << 1); - while (--w >= 0) - { - const char mn = cacheData[0]; - const char mx = cacheData[1]; - cacheData += numChannelsCached << 1; + while (--w >= 0) + { + const char mn = cacheData[0]; + const char mx = cacheData[1]; + cacheData += numChannelsCached << 1; - if (mn <= mx) // if the wrong way round, signifies that the sample's not yet known - g.drawLine ((float) x, jmax (midY - mx * vscale - 0.3f, topY), - (float) x, jmin (midY - mn * vscale + 0.3f, bottomY)); + if (mn <= mx) // if the wrong way round, signifies that the sample's not yet known + g.drawLine ((float) x, jmax (midY - mx * vscale - 0.3f, topY), + (float) x, jmin (midY - mn * vscale + 0.3f, bottomY)); - ++x; + ++x; - if (x >= clip.getRight()) - break; - } - } + if (x >= clip.getRight()) + break; + } + } } END_JUCE_NAMESPACE @@ -21439,18 +21202,18 @@ BEGIN_JUCE_NAMESPACE struct ThumbnailCacheEntry { - int64 hash; - uint32 lastUsed; - MemoryBlock data; + int64 hash; + uint32 lastUsed; + MemoryBlock data; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; AudioThumbnailCache::AudioThumbnailCache (const int maxNumThumbsToStore_) - : TimeSliceThread (T("thumb cache")), - maxNumThumbsToStore (maxNumThumbsToStore_) + : TimeSliceThread (T("thumb cache")), + maxNumThumbsToStore (maxNumThumbsToStore_) { - startThread (2); + startThread (2); } AudioThumbnailCache::~AudioThumbnailCache() @@ -21459,82 +21222,82 @@ AudioThumbnailCache::~AudioThumbnailCache() bool AudioThumbnailCache::loadThumb (AudioThumbnail& thumb, const int64 hashCode) { - for (int i = thumbs.size(); --i >= 0;) - { - if (thumbs[i]->hash == hashCode) - { - MemoryInputStream in ((const char*) thumbs[i]->data.getData(), - thumbs[i]->data.getSize(), - false); + for (int i = thumbs.size(); --i >= 0;) + { + if (thumbs[i]->hash == hashCode) + { + MemoryInputStream in ((const char*) thumbs[i]->data.getData(), + thumbs[i]->data.getSize(), + false); - thumb.loadFrom (in); + thumb.loadFrom (in); - thumbs[i]->lastUsed = Time::getMillisecondCounter(); - return true; - } - } + thumbs[i]->lastUsed = Time::getMillisecondCounter(); + return true; + } + } - return false; + return false; } void AudioThumbnailCache::storeThumb (const AudioThumbnail& thumb, - const int64 hashCode) + const int64 hashCode) { - MemoryOutputStream out; - thumb.saveTo (out); + MemoryOutputStream out; + thumb.saveTo (out); - ThumbnailCacheEntry* te = 0; + ThumbnailCacheEntry* te = 0; - for (int i = thumbs.size(); --i >= 0;) - { - if (thumbs[i]->hash == hashCode) - { - te = thumbs[i]; - break; - } - } + for (int i = thumbs.size(); --i >= 0;) + { + if (thumbs[i]->hash == hashCode) + { + te = thumbs[i]; + break; + } + } - if (te == 0) - { - te = new ThumbnailCacheEntry(); - te->hash = hashCode; + if (te == 0) + { + te = new ThumbnailCacheEntry(); + te->hash = hashCode; - if (thumbs.size() < maxNumThumbsToStore) - { - thumbs.add (te); - } - else - { - int oldest = 0; - unsigned int oldestTime = Time::getMillisecondCounter() + 1; + if (thumbs.size() < maxNumThumbsToStore) + { + thumbs.add (te); + } + else + { + int oldest = 0; + unsigned int oldestTime = Time::getMillisecondCounter() + 1; - int i; - for (i = thumbs.size(); --i >= 0;) - if (thumbs[i]->lastUsed < oldestTime) - oldest = i; + int i; + for (i = thumbs.size(); --i >= 0;) + if (thumbs[i]->lastUsed < oldestTime) + oldest = i; - thumbs.set (i, te); - } - } + thumbs.set (i, te); + } + } - te->lastUsed = Time::getMillisecondCounter(); - te->data.setSize (0); - te->data.append (out.getData(), out.getDataSize()); + te->lastUsed = Time::getMillisecondCounter(); + te->data.setSize (0); + te->data.append (out.getData(), out.getDataSize()); } void AudioThumbnailCache::clear() { - thumbs.clear(); + thumbs.clear(); } void AudioThumbnailCache::addThumbnail (AudioThumbnail* const thumb) { - addTimeSliceClient (thumb); + addTimeSliceClient (thumb); } void AudioThumbnailCache::removeThumbnail (AudioThumbnail* const thumb) { - removeTimeSliceClient (thumb); + removeTimeSliceClient (thumb); } END_JUCE_NAMESPACE @@ -21556,12 +21319,6 @@ END_JUCE_NAMESPACE #pragma warning (disable : 4100) #endif - /* If you've got an include error here, you probably need to install the QuickTime SDK and - add its header directory to your include path. - - Alternatively, if you don't need any QuickTime services, just turn off the JUC_QUICKTIME - flag in juce_Config.h - */ #include #include #include @@ -21580,273 +21337,261 @@ bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle static const char* const quickTimeFormatName = "QuickTime file"; static const tchar* const quickTimeExtensions[] = { T(".mov"), T(".mp3"), T(".mp4"), 0 }; -class QTAudioReader : public AudioFormatReader +class QTAudioReader : public AudioFormatReader { public: - QTAudioReader (InputStream* const input_, const int trackNum_) - : AudioFormatReader (input_, TRANS (quickTimeFormatName)), - ok (false), - movie (0), - trackNum (trackNum_), - extractor (0), - lastSampleRead (0), - lastThreadId (0), - dataHandle (0) - { - bufferList.calloc (256, 1); + QTAudioReader (InputStream* const input_, const int trackNum_) + : AudioFormatReader (input_, TRANS (quickTimeFormatName)), + ok (false), + movie (0), + trackNum (trackNum_), + extractor (0), + lastSampleRead (0), + lastThreadId (0), + dataHandle (0) + { + bufferList.calloc (256, 1); #ifdef WIN32 - if (InitializeQTML (0) != noErr) - return; + if (InitializeQTML (0) != noErr) + return; #endif - if (EnterMovies() != noErr) - return; + if (EnterMovies() != noErr) + return; - bool opened = juce_OpenQuickTimeMovieFromStream (input_, movie, dataHandle); + bool opened = juce_OpenQuickTimeMovieFromStream (input_, movie, dataHandle); - if (! opened) - return; + if (! opened) + return; - { - const int numTracks = GetMovieTrackCount (movie); - int trackCount = 0; + { + const int numTracks = GetMovieTrackCount (movie); + int trackCount = 0; - for (int i = 1; i <= numTracks; ++i) - { - track = GetMovieIndTrack (movie, i); - media = GetTrackMedia (track); + for (int i = 1; i <= numTracks; ++i) + { + track = GetMovieIndTrack (movie, i); + media = GetTrackMedia (track); - OSType mediaType; - GetMediaHandlerDescription (media, &mediaType, 0, 0); + OSType mediaType; + GetMediaHandlerDescription (media, &mediaType, 0, 0); - if (mediaType == SoundMediaType - && trackCount++ == trackNum_) - { - ok = true; - break; - } - } - } + if (mediaType == SoundMediaType + && trackCount++ == trackNum_) + { + ok = true; + break; + } + } + } - if (! ok) - return; + if (! ok) + return; - ok = false; + ok = false; - lengthInSamples = GetMediaDecodeDuration (media); - usesFloatingPointData = false; + lengthInSamples = GetMediaDecodeDuration (media); + usesFloatingPointData = false; - samplesPerFrame = (int) (GetMediaDecodeDuration (media) / GetMediaSampleCount (media)); + samplesPerFrame = (int) (GetMediaDecodeDuration (media) / GetMediaSampleCount (media)); - trackUnitsPerFrame = GetMovieTimeScale (movie) * samplesPerFrame - / GetMediaTimeScale (media); + trackUnitsPerFrame = GetMovieTimeScale (movie) * samplesPerFrame + / GetMediaTimeScale (media); - OSStatus err = MovieAudioExtractionBegin (movie, 0, &extractor); + OSStatus err = MovieAudioExtractionBegin (movie, 0, &extractor); - unsigned long output_layout_size; - err = MovieAudioExtractionGetPropertyInfo (extractor, - kQTPropertyClass_MovieAudioExtraction_Audio, - kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, - 0, &output_layout_size, 0); - if (err != noErr) - return; + unsigned long output_layout_size; + err = MovieAudioExtractionGetPropertyInfo (extractor, + kQTPropertyClass_MovieAudioExtraction_Audio, + kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, + 0, &output_layout_size, 0); + if (err != noErr) + return; - HeapBlock qt_audio_channel_layout; - qt_audio_channel_layout.calloc (output_layout_size, 1); + HeapBlock qt_audio_channel_layout; + qt_audio_channel_layout.calloc (output_layout_size, 1); - err = MovieAudioExtractionGetProperty (extractor, - kQTPropertyClass_MovieAudioExtraction_Audio, - kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, - output_layout_size, qt_audio_channel_layout, 0); + err = MovieAudioExtractionGetProperty (extractor, + kQTPropertyClass_MovieAudioExtraction_Audio, + kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, + output_layout_size, qt_audio_channel_layout, 0); - qt_audio_channel_layout[0].mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; + qt_audio_channel_layout[0].mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; - err = MovieAudioExtractionSetProperty (extractor, - kQTPropertyClass_MovieAudioExtraction_Audio, - kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, - output_layout_size, - qt_audio_channel_layout); + err = MovieAudioExtractionSetProperty (extractor, + kQTPropertyClass_MovieAudioExtraction_Audio, + kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, + output_layout_size, + qt_audio_channel_layout); - err = MovieAudioExtractionGetProperty (extractor, - kQTPropertyClass_MovieAudioExtraction_Audio, - kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, - sizeof (inputStreamDesc), - &inputStreamDesc, 0); - if (err != noErr) - return; + err = MovieAudioExtractionGetProperty (extractor, + kQTPropertyClass_MovieAudioExtraction_Audio, + kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, + sizeof (inputStreamDesc), + &inputStreamDesc, 0); + if (err != noErr) + return; - inputStreamDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger - | kAudioFormatFlagIsPacked - | kAudioFormatFlagsNativeEndian; - inputStreamDesc.mBitsPerChannel = sizeof (SInt16) * 8; - inputStreamDesc.mChannelsPerFrame = jmin (2, inputStreamDesc.mChannelsPerFrame); - inputStreamDesc.mBytesPerFrame = sizeof (SInt16) * inputStreamDesc.mChannelsPerFrame; - inputStreamDesc.mBytesPerPacket = inputStreamDesc.mBytesPerFrame; + inputStreamDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger + | kAudioFormatFlagIsPacked + | kAudioFormatFlagsNativeEndian; + inputStreamDesc.mBitsPerChannel = sizeof (SInt16) * 8; + inputStreamDesc.mChannelsPerFrame = jmin ((UInt32) 2, inputStreamDesc.mChannelsPerFrame); + inputStreamDesc.mBytesPerFrame = sizeof (SInt16) * inputStreamDesc.mChannelsPerFrame; + inputStreamDesc.mBytesPerPacket = inputStreamDesc.mBytesPerFrame; - err = MovieAudioExtractionSetProperty (extractor, - kQTPropertyClass_MovieAudioExtraction_Audio, - kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, - sizeof (inputStreamDesc), - &inputStreamDesc); - if (err != noErr) - return; + err = MovieAudioExtractionSetProperty (extractor, + kQTPropertyClass_MovieAudioExtraction_Audio, + kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, + sizeof (inputStreamDesc), + &inputStreamDesc); + if (err != noErr) + return; - Boolean allChannelsDiscrete = false; - err = MovieAudioExtractionSetProperty (extractor, - kQTPropertyClass_MovieAudioExtraction_Movie, - kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete, - sizeof (allChannelsDiscrete), - &allChannelsDiscrete); + Boolean allChannelsDiscrete = false; + err = MovieAudioExtractionSetProperty (extractor, + kQTPropertyClass_MovieAudioExtraction_Movie, + kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete, + sizeof (allChannelsDiscrete), + &allChannelsDiscrete); - if (err != noErr) - return; + if (err != noErr) + return; - bufferList->mNumberBuffers = 1; - bufferList->mBuffers[0].mNumberChannels = inputStreamDesc.mChannelsPerFrame; - bufferList->mBuffers[0].mDataByteSize = (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16; - bufferList->mBuffers[0].mData = malloc (bufferList->mBuffers[0].mDataByteSize); + bufferList->mNumberBuffers = 1; + bufferList->mBuffers[0].mNumberChannels = inputStreamDesc.mChannelsPerFrame; + bufferList->mBuffers[0].mDataByteSize = (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16; + bufferList->mBuffers[0].mData = malloc (bufferList->mBuffers[0].mDataByteSize); - sampleRate = inputStreamDesc.mSampleRate; - bitsPerSample = 16; - numChannels = inputStreamDesc.mChannelsPerFrame; + sampleRate = inputStreamDesc.mSampleRate; + bitsPerSample = 16; + numChannels = inputStreamDesc.mChannelsPerFrame; - detachThread(); - ok = true; - } + detachThread(); + ok = true; + } - ~QTAudioReader() - { - if (dataHandle != 0) - DisposeHandle (dataHandle); + ~QTAudioReader() + { + if (dataHandle != 0) + DisposeHandle (dataHandle); - if (extractor != 0) - { - MovieAudioExtractionEnd (extractor); - extractor = 0; - } + if (extractor != 0) + { + MovieAudioExtractionEnd (extractor); + extractor = 0; + } - checkThreadIsAttached(); - DisposeMovie (movie); + checkThreadIsAttached(); + DisposeMovie (movie); - juce_free (bufferList->mBuffers[0].mData); + juce_free (bufferList->mBuffers[0].mData); #if JUCE_MAC - ExitMoviesOnThread (); + ExitMoviesOnThread (); #endif - } + } - bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples) - { - checkThreadIsAttached(); + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) + { + checkThreadIsAttached(); - while (numSamples > 0) - { - if (! loadFrame ((int) startSampleInFile)) - return false; + while (numSamples > 0) + { + if (! loadFrame ((int) startSampleInFile)) + return false; - const int numToDo = jmin (numSamples, samplesPerFrame); + const int numToDo = jmin (numSamples, samplesPerFrame); - for (int j = numDestChannels; --j >= 0;) - { - if (destSamples[j] != 0) - { - const short* const src = ((const short*) bufferList->mBuffers[0].mData) + j; + for (int j = numDestChannels; --j >= 0;) + { + if (destSamples[j] != 0) + { + const short* const src = ((const short*) bufferList->mBuffers[0].mData) + j; - for (int i = 0; i < numToDo; ++i) - destSamples[j][startOffsetInDestBuffer + i] = src [i << 1] << 16; - } - } + for (int i = 0; i < numToDo; ++i) + destSamples[j][startOffsetInDestBuffer + i] = src [i << 1] << 16; + } + } - startOffsetInDestBuffer += numToDo; - startSampleInFile += numToDo; - numSamples -= numToDo; - } + startOffsetInDestBuffer += numToDo; + startSampleInFile += numToDo; + numSamples -= numToDo; + } - detachThread(); - return true; - } + detachThread(); + return true; + } - bool loadFrame (const int sampleNum) - { - if (lastSampleRead != sampleNum) - { - TimeRecord time; - time.scale = (TimeScale) inputStreamDesc.mSampleRate; - time.base = 0; - time.value.hi = 0; - time.value.lo = (UInt32) sampleNum; + bool loadFrame (const int sampleNum) + { + if (lastSampleRead != sampleNum) + { + TimeRecord time; + time.scale = (TimeScale) inputStreamDesc.mSampleRate; + time.base = 0; + time.value.hi = 0; + time.value.lo = (UInt32) sampleNum; - OSStatus err = MovieAudioExtractionSetProperty (extractor, - kQTPropertyClass_MovieAudioExtraction_Movie, - kQTMovieAudioExtractionMoviePropertyID_CurrentTime, - sizeof (time), &time); + OSStatus err = MovieAudioExtractionSetProperty (extractor, + kQTPropertyClass_MovieAudioExtraction_Movie, + kQTMovieAudioExtractionMoviePropertyID_CurrentTime, + sizeof (time), &time); - if (err != noErr) - return false; - } + if (err != noErr) + return false; + } - bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * samplesPerFrame; + bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * samplesPerFrame; - UInt32 outFlags = 0; - UInt32 actualNumSamples = samplesPerFrame; - OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumSamples, - bufferList, &outFlags); + UInt32 outFlags = 0; + UInt32 actualNumSamples = samplesPerFrame; + OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumSamples, + bufferList, &outFlags); - lastSampleRead = sampleNum + samplesPerFrame; + lastSampleRead = sampleNum + samplesPerFrame; - return err == noErr; - } + return err == noErr; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - bool ok; + bool ok; private: - Movie movie; - Media media; - Track track; - const int trackNum; - double trackUnitsPerFrame; - int samplesPerFrame; - int lastSampleRead; - Thread::ThreadID lastThreadId; - MovieAudioExtractionRef extractor; - AudioStreamBasicDescription inputStreamDesc; - HeapBlock bufferList; - Handle dataHandle; + Movie movie; + Media media; + Track track; + const int trackNum; + double trackUnitsPerFrame; + int samplesPerFrame; + int lastSampleRead; + Thread::ThreadID lastThreadId; + MovieAudioExtractionRef extractor; + AudioStreamBasicDescription inputStreamDesc; + HeapBlock bufferList; + Handle dataHandle; - /*OSErr readMovieStream (long offset, long size, void* dataPtr) - { - input->setPosition (offset); - input->read (dataPtr, size); - return noErr; - } - - static OSErr readMovieStreamProc (long offset, long size, void* dataPtr, void* userRef) - { - return ((QTAudioReader*) userRef)->readMovieStream (offset, size, dataPtr); - }*/ - - void checkThreadIsAttached() - { + void checkThreadIsAttached() + { #if JUCE_MAC - if (Thread::getCurrentThreadId() != lastThreadId) - EnterMoviesOnThread (0); - AttachMovieToCurrentThread (movie); + if (Thread::getCurrentThreadId() != lastThreadId) + EnterMoviesOnThread (0); + AttachMovieToCurrentThread (movie); #endif - } + } - void detachThread() - { + void detachThread() + { #if JUCE_MAC - DetachMovieFromCurrentThread (movie); + DetachMovieFromCurrentThread (movie); #endif - } + } }; QuickTimeAudioFormat::QuickTimeAudioFormat() - : AudioFormat (TRANS (quickTimeFormatName), (const tchar**) quickTimeExtensions) + : AudioFormat (TRANS (quickTimeFormatName), (const tchar**) quickTimeExtensions) { } @@ -21856,47 +21601,47 @@ QuickTimeAudioFormat::~QuickTimeAudioFormat() const Array QuickTimeAudioFormat::getPossibleSampleRates() { - return Array(); + return Array(); } const Array QuickTimeAudioFormat::getPossibleBitDepths() { - return Array(); + return Array(); } bool QuickTimeAudioFormat::canDoStereo() { - return true; + return true; } bool QuickTimeAudioFormat::canDoMono() { - return true; + return true; } AudioFormatReader* QuickTimeAudioFormat::createReaderFor (InputStream* sourceStream, - const bool deleteStreamIfOpeningFails) + const bool deleteStreamIfOpeningFails) { - ScopedPointer r (new QTAudioReader (sourceStream, 0)); + ScopedPointer r (new QTAudioReader (sourceStream, 0)); - if (r->ok) - return r.release(); + if (r->ok) + return r.release(); - if (! deleteStreamIfOpeningFails) - r->input = 0; + if (! deleteStreamIfOpeningFails) + r->input = 0; - return 0; + return 0; } AudioFormatWriter* QuickTimeAudioFormat::createWriterFor (OutputStream* /*streamToWriteTo*/, - double /*sampleRateToUse*/, - unsigned int /*numberOfChannels*/, - int /*bitsPerSample*/, - const StringPairArray& /*metadataValues*/, - int /*qualityOptionIndex*/) + double /*sampleRateToUse*/, + unsigned int /*numberOfChannels*/, + int /*bitsPerSample*/, + const StringPairArray& /*metadataValues*/, + int /*qualityOptionIndex*/) { - jassertfalse // not yet implemented! - return 0; + jassertfalse // not yet implemented! + return 0; } END_JUCE_NAMESPACE @@ -21920,23 +21665,23 @@ const tchar* const WavAudioFormat::bwavTimeReference = T("bwav time reference const tchar* const WavAudioFormat::bwavCodingHistory = T("bwav coding history"); const StringPairArray WavAudioFormat::createBWAVMetadata (const String& description, - const String& originator, - const String& originatorRef, - const Time& date, - const int64 timeReferenceSamples, - const String& codingHistory) + const String& originator, + const String& originatorRef, + const Time& date, + const int64 timeReferenceSamples, + const String& codingHistory) { - StringPairArray m; + StringPairArray m; - m.set (bwavDescription, description); - m.set (bwavOriginator, originator); - m.set (bwavOriginatorRef, originatorRef); - m.set (bwavOriginationDate, date.formatted (T("%Y-%m-%d"))); - m.set (bwavOriginationTime, date.formatted (T("%H:%M:%S"))); - m.set (bwavTimeReference, String (timeReferenceSamples)); - m.set (bwavCodingHistory, codingHistory); + m.set (bwavDescription, description); + m.set (bwavOriginator, originator); + m.set (bwavOriginatorRef, originatorRef); + m.set (bwavOriginationDate, date.formatted (T("%Y-%m-%d"))); + m.set (bwavOriginationTime, date.formatted (T("%H:%M:%S"))); + m.set (bwavTimeReference, String (timeReferenceSamples)); + m.set (bwavCodingHistory, codingHistory); - return m; + return m; } #if JUCE_MSVC @@ -21950,119 +21695,119 @@ const StringPairArray WavAudioFormat::createBWAVMetadata (const String& descript struct BWAVChunk { - uint8 description [256]; - uint8 originator [32]; - uint8 originatorRef [32]; - uint8 originationDate [10]; - uint8 originationTime [8]; - uint32 timeRefLow; - uint32 timeRefHigh; - uint16 version; - uint8 umid[64]; - uint8 reserved[190]; - uint8 codingHistory[1]; + uint8 description [256]; + uint8 originator [32]; + uint8 originatorRef [32]; + uint8 originationDate [10]; + uint8 originationTime [8]; + uint32 timeRefLow; + uint32 timeRefHigh; + uint16 version; + uint8 umid[64]; + uint8 reserved[190]; + uint8 codingHistory[1]; - void copyTo (StringPairArray& values) const - { - values.set (WavAudioFormat::bwavDescription, String::fromUTF8 (description, 256)); - values.set (WavAudioFormat::bwavOriginator, String::fromUTF8 (originator, 32)); - values.set (WavAudioFormat::bwavOriginatorRef, String::fromUTF8 (originatorRef, 32)); - values.set (WavAudioFormat::bwavOriginationDate, String::fromUTF8 (originationDate, 10)); - values.set (WavAudioFormat::bwavOriginationTime, String::fromUTF8 (originationTime, 8)); + void copyTo (StringPairArray& values) const + { + values.set (WavAudioFormat::bwavDescription, String::fromUTF8 (description, 256)); + values.set (WavAudioFormat::bwavOriginator, String::fromUTF8 (originator, 32)); + values.set (WavAudioFormat::bwavOriginatorRef, String::fromUTF8 (originatorRef, 32)); + values.set (WavAudioFormat::bwavOriginationDate, String::fromUTF8 (originationDate, 10)); + values.set (WavAudioFormat::bwavOriginationTime, String::fromUTF8 (originationTime, 8)); - const uint32 timeLow = ByteOrder::swapIfBigEndian (timeRefLow); - const uint32 timeHigh = ByteOrder::swapIfBigEndian (timeRefHigh); - const int64 time = (((int64)timeHigh) << 32) + timeLow; + const uint32 timeLow = ByteOrder::swapIfBigEndian (timeRefLow); + const uint32 timeHigh = ByteOrder::swapIfBigEndian (timeRefHigh); + const int64 time = (((int64)timeHigh) << 32) + timeLow; - values.set (WavAudioFormat::bwavTimeReference, String (time)); - values.set (WavAudioFormat::bwavCodingHistory, String::fromUTF8 (codingHistory)); - } + values.set (WavAudioFormat::bwavTimeReference, String (time)); + values.set (WavAudioFormat::bwavCodingHistory, String::fromUTF8 (codingHistory)); + } - static MemoryBlock createFrom (const StringPairArray& values) - { - const int sizeNeeded = sizeof (BWAVChunk) + values [WavAudioFormat::bwavCodingHistory].copyToUTF8 (0) - 1; - MemoryBlock data ((sizeNeeded + 3) & ~3); - data.fillWith (0); + static MemoryBlock createFrom (const StringPairArray& values) + { + const size_t sizeNeeded = sizeof (BWAVChunk) + values [WavAudioFormat::bwavCodingHistory].copyToUTF8 (0) - 1; + MemoryBlock data ((sizeNeeded + 3) & ~3); + data.fillWith (0); - BWAVChunk* b = (BWAVChunk*) data.getData(); + BWAVChunk* b = (BWAVChunk*) data.getData(); - // Allow these calls to overwrite an extra byte at the end, which is fine as long - // as they get called in the right order.. - values [WavAudioFormat::bwavDescription].copyToUTF8 (b->description, 257); - values [WavAudioFormat::bwavOriginator].copyToUTF8 (b->originator, 33); - values [WavAudioFormat::bwavOriginatorRef].copyToUTF8 (b->originatorRef, 33); - values [WavAudioFormat::bwavOriginationDate].copyToUTF8 (b->originationDate, 11); - values [WavAudioFormat::bwavOriginationTime].copyToUTF8 (b->originationTime, 9); + // Allow these calls to overwrite an extra byte at the end, which is fine as long + // as they get called in the right order.. + values [WavAudioFormat::bwavDescription].copyToUTF8 (b->description, 257); + values [WavAudioFormat::bwavOriginator].copyToUTF8 (b->originator, 33); + values [WavAudioFormat::bwavOriginatorRef].copyToUTF8 (b->originatorRef, 33); + values [WavAudioFormat::bwavOriginationDate].copyToUTF8 (b->originationDate, 11); + values [WavAudioFormat::bwavOriginationTime].copyToUTF8 (b->originationTime, 9); - const int64 time = values [WavAudioFormat::bwavTimeReference].getLargeIntValue(); - b->timeRefLow = ByteOrder::swapIfBigEndian ((uint32) (time & 0xffffffff)); - b->timeRefHigh = ByteOrder::swapIfBigEndian ((uint32) (time >> 32)); + const int64 time = values [WavAudioFormat::bwavTimeReference].getLargeIntValue(); + b->timeRefLow = ByteOrder::swapIfBigEndian ((uint32) (time & 0xffffffff)); + b->timeRefHigh = ByteOrder::swapIfBigEndian ((uint32) (time >> 32)); - values [WavAudioFormat::bwavCodingHistory].copyToUTF8 (b->codingHistory); + values [WavAudioFormat::bwavCodingHistory].copyToUTF8 (b->codingHistory); - if (b->description[0] != 0 - || b->originator[0] != 0 - || b->originationDate[0] != 0 - || b->originationTime[0] != 0 - || b->codingHistory[0] != 0 - || time != 0) - { - return data; - } + if (b->description[0] != 0 + || b->originator[0] != 0 + || b->originationDate[0] != 0 + || b->originationTime[0] != 0 + || b->codingHistory[0] != 0 + || time != 0) + { + return data; + } - return MemoryBlock(); - } + return MemoryBlock(); + } } PACKED; struct SMPLChunk { - struct SampleLoop - { - uint32 identifier; - uint32 type; - uint32 start; - uint32 end; - uint32 fraction; - uint32 playCount; - } PACKED; + struct SampleLoop + { + uint32 identifier; + uint32 type; + uint32 start; + uint32 end; + uint32 fraction; + uint32 playCount; + } PACKED; - uint32 manufacturer; - uint32 product; - uint32 samplePeriod; - uint32 midiUnityNote; - uint32 midiPitchFraction; - uint32 smpteFormat; - uint32 smpteOffset; - uint32 numSampleLoops; - uint32 samplerData; - SampleLoop loops[1]; + uint32 manufacturer; + uint32 product; + uint32 samplePeriod; + uint32 midiUnityNote; + uint32 midiPitchFraction; + uint32 smpteFormat; + uint32 smpteOffset; + uint32 numSampleLoops; + uint32 samplerData; + SampleLoop loops[1]; - void copyTo (StringPairArray& values, const int totalSize) const - { - values.set (T("Manufacturer"), String (ByteOrder::swapIfBigEndian (manufacturer))); - values.set (T("Product"), String (ByteOrder::swapIfBigEndian (product))); - values.set (T("SamplePeriod"), String (ByteOrder::swapIfBigEndian (samplePeriod))); - values.set (T("MidiUnityNote"), String (ByteOrder::swapIfBigEndian (midiUnityNote))); - values.set (T("MidiPitchFraction"), String (ByteOrder::swapIfBigEndian (midiPitchFraction))); - values.set (T("SmpteFormat"), String (ByteOrder::swapIfBigEndian (smpteFormat))); - values.set (T("SmpteOffset"), String (ByteOrder::swapIfBigEndian (smpteOffset))); - values.set (T("NumSampleLoops"), String (ByteOrder::swapIfBigEndian (numSampleLoops))); - values.set (T("SamplerData"), String (ByteOrder::swapIfBigEndian (samplerData))); + void copyTo (StringPairArray& values, const int totalSize) const + { + values.set (T("Manufacturer"), String (ByteOrder::swapIfBigEndian (manufacturer))); + values.set (T("Product"), String (ByteOrder::swapIfBigEndian (product))); + values.set (T("SamplePeriod"), String (ByteOrder::swapIfBigEndian (samplePeriod))); + values.set (T("MidiUnityNote"), String (ByteOrder::swapIfBigEndian (midiUnityNote))); + values.set (T("MidiPitchFraction"), String (ByteOrder::swapIfBigEndian (midiPitchFraction))); + values.set (T("SmpteFormat"), String (ByteOrder::swapIfBigEndian (smpteFormat))); + values.set (T("SmpteOffset"), String (ByteOrder::swapIfBigEndian (smpteOffset))); + values.set (T("NumSampleLoops"), String (ByteOrder::swapIfBigEndian (numSampleLoops))); + values.set (T("SamplerData"), String (ByteOrder::swapIfBigEndian (samplerData))); - for (uint32 i = 0; i < numSampleLoops; ++i) - { - if ((uint8*) (loops + (i + 1)) > ((uint8*) this) + totalSize) - break; + for (uint32 i = 0; i < numSampleLoops; ++i) + { + if ((uint8*) (loops + (i + 1)) > ((uint8*) this) + totalSize) + break; - values.set (String::formatted (T("Loop%dIdentifier"), i), String (ByteOrder::swapIfBigEndian (loops[i].identifier))); - values.set (String::formatted (T("Loop%dType"), i), String (ByteOrder::swapIfBigEndian (loops[i].type))); - values.set (String::formatted (T("Loop%dStart"), i), String (ByteOrder::swapIfBigEndian (loops[i].start))); - values.set (String::formatted (T("Loop%dEnd"), i), String (ByteOrder::swapIfBigEndian (loops[i].end))); - values.set (String::formatted (T("Loop%dFraction"), i), String (ByteOrder::swapIfBigEndian (loops[i].fraction))); - values.set (String::formatted (T("Loop%dPlayCount"), i), String (ByteOrder::swapIfBigEndian (loops[i].playCount))); - } - } + values.set (String::formatted (T("Loop%dIdentifier"), i), String (ByteOrder::swapIfBigEndian (loops[i].identifier))); + values.set (String::formatted (T("Loop%dType"), i), String (ByteOrder::swapIfBigEndian (loops[i].type))); + values.set (String::formatted (T("Loop%dStart"), i), String (ByteOrder::swapIfBigEndian (loops[i].start))); + values.set (String::formatted (T("Loop%dEnd"), i), String (ByteOrder::swapIfBigEndian (loops[i].end))); + values.set (String::formatted (T("Loop%dFraction"), i), String (ByteOrder::swapIfBigEndian (loops[i].fraction))); + values.set (String::formatted (T("Loop%dPlayCount"), i), String (ByteOrder::swapIfBigEndian (loops[i].playCount))); + } + } } PACKED; #if JUCE_MSVC @@ -22073,522 +21818,522 @@ struct SMPLChunk class WavAudioFormatReader : public AudioFormatReader { - int bytesPerFrame; - int64 dataChunkStart, dataLength; + int bytesPerFrame; + int64 dataChunkStart, dataLength; - static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } - WavAudioFormatReader (const WavAudioFormatReader&); - const WavAudioFormatReader& operator= (const WavAudioFormatReader&); + WavAudioFormatReader (const WavAudioFormatReader&); + const WavAudioFormatReader& operator= (const WavAudioFormatReader&); public: - int64 bwavChunkStart, bwavSize; + int64 bwavChunkStart, bwavSize; - WavAudioFormatReader (InputStream* const in) - : AudioFormatReader (in, TRANS (wavFormatName)), - dataLength (0), - bwavChunkStart (0), - bwavSize (0) - { - if (input->readInt() == chunkName ("RIFF")) - { - const uint32 len = (uint32) input->readInt(); - const int64 end = input->getPosition() + len; - bool hasGotType = false; - bool hasGotData = false; + WavAudioFormatReader (InputStream* const in) + : AudioFormatReader (in, TRANS (wavFormatName)), + dataLength (0), + bwavChunkStart (0), + bwavSize (0) + { + if (input->readInt() == chunkName ("RIFF")) + { + const uint32 len = (uint32) input->readInt(); + const int64 end = input->getPosition() + len; + bool hasGotType = false; + bool hasGotData = false; - if (input->readInt() == chunkName ("WAVE")) - { - while (input->getPosition() < end - && ! input->isExhausted()) - { - const int chunkType = input->readInt(); - uint32 length = (uint32) input->readInt(); - const int64 chunkEnd = input->getPosition() + length + (length & 1); + if (input->readInt() == chunkName ("WAVE")) + { + while (input->getPosition() < end + && ! input->isExhausted()) + { + const int chunkType = input->readInt(); + uint32 length = (uint32) input->readInt(); + const int64 chunkEnd = input->getPosition() + length + (length & 1); - if (chunkType == chunkName ("fmt ")) - { - // read the format chunk - const short format = input->readShort(); - const short numChans = input->readShort(); - sampleRate = input->readInt(); - const int bytesPerSec = input->readInt(); + if (chunkType == chunkName ("fmt ")) + { + // read the format chunk + const short format = input->readShort(); + const short numChans = input->readShort(); + sampleRate = input->readInt(); + const int bytesPerSec = input->readInt(); - numChannels = numChans; - bytesPerFrame = bytesPerSec / (int)sampleRate; - bitsPerSample = 8 * bytesPerFrame / numChans; + numChannels = numChans; + bytesPerFrame = bytesPerSec / (int)sampleRate; + bitsPerSample = 8 * bytesPerFrame / numChans; - if (format == 3) - usesFloatingPointData = true; - else if (format != 1) - bytesPerFrame = 0; + if (format == 3) + usesFloatingPointData = true; + else if (format != 1) + bytesPerFrame = 0; - hasGotType = true; - } - else if (chunkType == chunkName ("data")) - { - // get the data chunk's position - dataLength = length; - dataChunkStart = input->getPosition(); - lengthInSamples = (bytesPerFrame > 0) ? (dataLength / bytesPerFrame) : 0; + hasGotType = true; + } + else if (chunkType == chunkName ("data")) + { + // get the data chunk's position + dataLength = length; + dataChunkStart = input->getPosition(); + lengthInSamples = (bytesPerFrame > 0) ? (dataLength / bytesPerFrame) : 0; - hasGotData = true; - } - else if (chunkType == chunkName ("bext")) - { - bwavChunkStart = input->getPosition(); - bwavSize = length; + hasGotData = true; + } + else if (chunkType == chunkName ("bext")) + { + bwavChunkStart = input->getPosition(); + bwavSize = length; - // Broadcast-wav extension chunk.. - HeapBlock bwav; - bwav.calloc (jmax (length + 1, (int) sizeof (BWAVChunk)), 1); - input->read (bwav, length); - bwav->copyTo (metadataValues); - } - else if (chunkType == chunkName ("smpl")) - { - HeapBlock smpl; - smpl.calloc (jmax (length + 1, (int) sizeof (SMPLChunk)), 1); - input->read (smpl, length); - smpl->copyTo (metadataValues, length); - } - else if (chunkEnd <= input->getPosition()) - { - break; - } + // Broadcast-wav extension chunk.. + HeapBlock bwav; + bwav.calloc (jmax ((size_t) length + 1, sizeof (BWAVChunk)), 1); + input->read (bwav, length); + bwav->copyTo (metadataValues); + } + else if (chunkType == chunkName ("smpl")) + { + HeapBlock smpl; + smpl.calloc (jmax ((size_t) length + 1, sizeof (SMPLChunk)), 1); + input->read (smpl, length); + smpl->copyTo (metadataValues, length); + } + else if (chunkEnd <= input->getPosition()) + { + break; + } - input->setPosition (chunkEnd); - } - } - } - } + input->setPosition (chunkEnd); + } + } + } + } - ~WavAudioFormatReader() - { - } + ~WavAudioFormatReader() + { + } - bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples) - { - const int64 samplesAvailable = lengthInSamples - startSampleInFile; + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) + { + const int64 samplesAvailable = lengthInSamples - startSampleInFile; - if (samplesAvailable < numSamples) - { - for (int i = numDestChannels; --i >= 0;) - if (destSamples[i] != 0) - zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * numSamples); + if (samplesAvailable < numSamples) + { + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * numSamples); - numSamples = (int) samplesAvailable; - } + numSamples = (int) samplesAvailable; + } - if (numSamples <= 0) - return true; + if (numSamples <= 0) + return true; - input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame); + input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame); - const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3) - char tempBuffer [tempBufSize]; + const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3) + char tempBuffer [tempBufSize]; - while (numSamples > 0) - { - int* left = destSamples[0]; - if (left != 0) - left += startOffsetInDestBuffer; + while (numSamples > 0) + { + int* left = destSamples[0]; + if (left != 0) + left += startOffsetInDestBuffer; - int* right = numDestChannels > 1 ? destSamples[1] : 0; - if (right != 0) - right += startOffsetInDestBuffer; + int* right = numDestChannels > 1 ? destSamples[1] : 0; + if (right != 0) + right += startOffsetInDestBuffer; - const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples); - const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); + const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples); + const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); - if (bytesRead < numThisTime * bytesPerFrame) - zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); + if (bytesRead < numThisTime * bytesPerFrame) + zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead); - if (bitsPerSample == 16) - { - const short* src = (const short*) tempBuffer; + if (bitsPerSample == 16) + { + const short* src = (const short*) tempBuffer; - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; - *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; - } - } - } - else if (bitsPerSample == 24) - { - const char* src = (const char*) tempBuffer; + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + ++src; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + *right++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = (int) ByteOrder::swapIfBigEndian ((unsigned short) *src++) << 16; + } + } + } + else if (bitsPerSample == 24) + { + const char* src = (const char*) tempBuffer; - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - src += 3; - *right++ = ByteOrder::littleEndian24Bit (src) << 8; - src += 3; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ByteOrder::littleEndian24Bit (src) << 8; - src += 6; - } - } - else - { - for (int i = 0; i < numThisTime; ++i) - { - *left++ = ByteOrder::littleEndian24Bit (src) << 8; - src += 3; - *right++ = ByteOrder::littleEndian24Bit (src) << 8; - src += 3; - } - } - } - else - { - for (int i = 0; i < numThisTime; ++i) - { - *left++ = ByteOrder::littleEndian24Bit (src) << 8; - src += 3; - } - } - } - else if (bitsPerSample == 32) - { - const unsigned int* src = (const unsigned int*) tempBuffer; - unsigned int* l = (unsigned int*) left; - unsigned int* r = (unsigned int*) right; + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + src += 3; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; + src += 3; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ByteOrder::littleEndian24Bit (src) << 8; + src += 6; + } + } + else + { + for (int i = 0; i < numThisTime; ++i) + { + *left++ = ByteOrder::littleEndian24Bit (src) << 8; + src += 3; + *right++ = ByteOrder::littleEndian24Bit (src) << 8; + src += 3; + } + } + } + else + { + for (int i = 0; i < numThisTime; ++i) + { + *left++ = ByteOrder::littleEndian24Bit (src) << 8; + src += 3; + } + } + } + else if (bitsPerSample == 32) + { + const unsigned int* src = (const unsigned int*) tempBuffer; + unsigned int* l = (unsigned int*) left; + unsigned int* r = (unsigned int*) right; - if (numChannels > 1) - { - if (l == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *r++ = ByteOrder::swapIfBigEndian (*src++); - } - } - else if (r == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = ByteOrder::swapIfBigEndian (*src++); - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = ByteOrder::swapIfBigEndian (*src++); - *r++ = ByteOrder::swapIfBigEndian (*src++); - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *l++ = ByteOrder::swapIfBigEndian (*src++); - } - } + if (numChannels > 1) + { + if (l == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *r++ = ByteOrder::swapIfBigEndian (*src++); + } + } + else if (r == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = ByteOrder::swapIfBigEndian (*src++); + ++src; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = ByteOrder::swapIfBigEndian (*src++); + *r++ = ByteOrder::swapIfBigEndian (*src++); + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *l++ = ByteOrder::swapIfBigEndian (*src++); + } + } - left = (int*)l; - right = (int*)r; - } - else if (bitsPerSample == 8) - { - const unsigned char* src = (const unsigned char*) tempBuffer; + left = (int*)l; + right = (int*)r; + } + else if (bitsPerSample == 8) + { + const unsigned char* src = (const unsigned char*) tempBuffer; - if (numChannels > 1) - { - if (left == 0) - { - for (int i = numThisTime; --i >= 0;) - { - ++src; - *right++ = ((int) *src++ - 128) << 24; - } - } - else if (right == 0) - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int) *src++ - 128) << 24; - ++src; - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int) *src++ - 128) << 24; - *right++ = ((int) *src++ - 128) << 24; - } - } - } - else - { - for (int i = numThisTime; --i >= 0;) - { - *left++ = ((int)*src++ - 128) << 24; - } - } - } + if (numChannels > 1) + { + if (left == 0) + { + for (int i = numThisTime; --i >= 0;) + { + ++src; + *right++ = ((int) *src++ - 128) << 24; + } + } + else if (right == 0) + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int) *src++ - 128) << 24; + ++src; + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int) *src++ - 128) << 24; + *right++ = ((int) *src++ - 128) << 24; + } + } + } + else + { + for (int i = numThisTime; --i >= 0;) + { + *left++ = ((int)*src++ - 128) << 24; + } + } + } - startOffsetInDestBuffer += numThisTime; - numSamples -= numThisTime; - } + startOffsetInDestBuffer += numThisTime; + numSamples -= numThisTime; + } - if (numSamples > 0) - { - for (int i = numDestChannels; --i >= 0;) - if (destSamples[i] != 0) - zeromem (destSamples[i] + startOffsetInDestBuffer, - sizeof (int) * numSamples); - } + if (numSamples > 0) + { + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); + } - return true; - } + return true; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; class WavAudioFormatWriter : public AudioFormatWriter { - MemoryBlock tempBlock, bwavChunk; - uint32 lengthInSamples, bytesWritten; - int64 headerPosition; - bool writeFailed; + MemoryBlock tempBlock, bwavChunk; + uint32 lengthInSamples, bytesWritten; + int64 headerPosition; + bool writeFailed; - static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } + static inline int chunkName (const char* const name) { return (int) ByteOrder::littleEndianInt (name); } - WavAudioFormatWriter (const WavAudioFormatWriter&); - const WavAudioFormatWriter& operator= (const WavAudioFormatWriter&); + WavAudioFormatWriter (const WavAudioFormatWriter&); + const WavAudioFormatWriter& operator= (const WavAudioFormatWriter&); - void writeHeader() - { - const bool seekedOk = output->setPosition (headerPosition); - (void) seekedOk; + void writeHeader() + { + const bool seekedOk = output->setPosition (headerPosition); + (void) seekedOk; - // if this fails, you've given it an output stream that can't seek! It needs - // to be able to seek back to write the header - jassert (seekedOk); + // if this fails, you've given it an output stream that can't seek! It needs + // to be able to seek back to write the header + jassert (seekedOk); - const int bytesPerFrame = numChannels * bitsPerSample / 8; - output->writeInt (chunkName ("RIFF")); - output->writeInt (lengthInSamples * bytesPerFrame - + ((bwavChunk.getSize() > 0) ? (44 + bwavChunk.getSize()) : 36)); + const int bytesPerFrame = numChannels * bitsPerSample / 8; + output->writeInt (chunkName ("RIFF")); + output->writeInt ((int) (lengthInSamples * bytesPerFrame + + ((bwavChunk.getSize() > 0) ? (44 + bwavChunk.getSize()) : 36))); - output->writeInt (chunkName ("WAVE")); - output->writeInt (chunkName ("fmt ")); - output->writeInt (16); - output->writeShort ((bitsPerSample < 32) ? (short) 1 /*WAVE_FORMAT_PCM*/ - : (short) 3 /*WAVE_FORMAT_IEEE_FLOAT*/); - output->writeShort ((short) numChannels); - output->writeInt ((int) sampleRate); - output->writeInt (bytesPerFrame * (int) sampleRate); - output->writeShort ((short) bytesPerFrame); - output->writeShort ((short) bitsPerSample); + output->writeInt (chunkName ("WAVE")); + output->writeInt (chunkName ("fmt ")); + output->writeInt (16); + output->writeShort ((bitsPerSample < 32) ? (short) 1 /*WAVE_FORMAT_PCM*/ + : (short) 3 /*WAVE_FORMAT_IEEE_FLOAT*/); + output->writeShort ((short) numChannels); + output->writeInt ((int) sampleRate); + output->writeInt (bytesPerFrame * (int) sampleRate); + output->writeShort ((short) bytesPerFrame); + output->writeShort ((short) bitsPerSample); - if (bwavChunk.getSize() > 0) - { - output->writeInt (chunkName ("bext")); - output->writeInt (bwavChunk.getSize()); - output->write (bwavChunk.getData(), bwavChunk.getSize()); - } + if (bwavChunk.getSize() > 0) + { + output->writeInt (chunkName ("bext")); + output->writeInt ((int) bwavChunk.getSize()); + output->write (bwavChunk.getData(), (int) bwavChunk.getSize()); + } - output->writeInt (chunkName ("data")); - output->writeInt (lengthInSamples * bytesPerFrame); + output->writeInt (chunkName ("data")); + output->writeInt (lengthInSamples * bytesPerFrame); - usesFloatingPointData = (bitsPerSample == 32); - } + usesFloatingPointData = (bitsPerSample == 32); + } public: - WavAudioFormatWriter (OutputStream* const out, - const double sampleRate_, - const unsigned int numChannels_, - const int bits, - const StringPairArray& metadataValues) - : AudioFormatWriter (out, - TRANS (wavFormatName), - sampleRate_, - numChannels_, - bits), - lengthInSamples (0), - bytesWritten (0), - writeFailed (false) - { - if (metadataValues.size() > 0) - bwavChunk = BWAVChunk::createFrom (metadataValues); + WavAudioFormatWriter (OutputStream* const out, + const double sampleRate_, + const unsigned int numChannels_, + const int bits, + const StringPairArray& metadataValues) + : AudioFormatWriter (out, + TRANS (wavFormatName), + sampleRate_, + numChannels_, + bits), + lengthInSamples (0), + bytesWritten (0), + writeFailed (false) + { + if (metadataValues.size() > 0) + bwavChunk = BWAVChunk::createFrom (metadataValues); - headerPosition = out->getPosition(); - writeHeader(); - } + headerPosition = out->getPosition(); + writeHeader(); + } - ~WavAudioFormatWriter() - { - writeHeader(); - } + ~WavAudioFormatWriter() + { + writeHeader(); + } - bool write (const int** data, int numSamples) - { - if (writeFailed) - return false; + bool write (const int** data, int numSamples) + { + if (writeFailed) + return false; - const int bytes = numChannels * numSamples * bitsPerSample / 8; - tempBlock.ensureSize (bytes, false); - char* buffer = (char*) tempBlock.getData(); + const int bytes = numChannels * numSamples * bitsPerSample / 8; + tempBlock.ensureSize (bytes, false); + char* buffer = (char*) tempBlock.getData(); - const int* left = data[0]; - const int* right = data[1]; - if (right == 0) - right = left; + const int* left = data[0]; + const int* right = data[1]; + if (right == 0) + right = left; - if (bitsPerSample == 16) - { - short* b = (short*) buffer; + if (bitsPerSample == 16) + { + short* b = (short*) buffer; - if (numChannels > 1) - { - for (int i = numSamples; --i >= 0;) - { - *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*left++ >> 16)); - *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*right++ >> 16)); - } - } - else - { - for (int i = numSamples; --i >= 0;) - { - *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*left++ >> 16)); - } - } - } - else if (bitsPerSample == 24) - { - char* b = (char*) buffer; + if (numChannels > 1) + { + for (int i = numSamples; --i >= 0;) + { + *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*left++ >> 16)); + *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*right++ >> 16)); + } + } + else + { + for (int i = numSamples; --i >= 0;) + { + *b++ = (short) ByteOrder::swapIfBigEndian ((unsigned short) (*left++ >> 16)); + } + } + } + else if (bitsPerSample == 24) + { + char* b = (char*) buffer; - if (numChannels > 1) - { - for (int i = numSamples; --i >= 0;) - { - ByteOrder::littleEndian24BitToChars ((*left++) >> 8, b); - b += 3; - ByteOrder::littleEndian24BitToChars ((*right++) >> 8, b); - b += 3; - } - } - else - { - for (int i = numSamples; --i >= 0;) - { - ByteOrder::littleEndian24BitToChars ((*left++) >> 8, b); - b += 3; - } - } - } - else if (bitsPerSample == 32) - { - unsigned int* b = (unsigned int*) buffer; + if (numChannels > 1) + { + for (int i = numSamples; --i >= 0;) + { + ByteOrder::littleEndian24BitToChars ((*left++) >> 8, b); + b += 3; + ByteOrder::littleEndian24BitToChars ((*right++) >> 8, b); + b += 3; + } + } + else + { + for (int i = numSamples; --i >= 0;) + { + ByteOrder::littleEndian24BitToChars ((*left++) >> 8, b); + b += 3; + } + } + } + else if (bitsPerSample == 32) + { + unsigned int* b = (unsigned int*) buffer; - if (numChannels > 1) - { - for (int i = numSamples; --i >= 0;) - { - *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *left++); - *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *right++); - } - } - else - { - for (int i = numSamples; --i >= 0;) - { - *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *left++); - } - } - } - else if (bitsPerSample == 8) - { - unsigned char* b = (unsigned char*) buffer; + if (numChannels > 1) + { + for (int i = numSamples; --i >= 0;) + { + *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *left++); + *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *right++); + } + } + else + { + for (int i = numSamples; --i >= 0;) + { + *b++ = ByteOrder::swapIfBigEndian ((unsigned int) *left++); + } + } + } + else if (bitsPerSample == 8) + { + unsigned char* b = (unsigned char*) buffer; - if (numChannels > 1) - { - for (int i = numSamples; --i >= 0;) - { - *b++ = (unsigned char) (128 + (*left++ >> 24)); - *b++ = (unsigned char) (128 + (*right++ >> 24)); - } - } - else - { - for (int i = numSamples; --i >= 0;) - { - *b++ = (unsigned char) (128 + (*left++ >> 24)); - } - } - } + if (numChannels > 1) + { + for (int i = numSamples; --i >= 0;) + { + *b++ = (unsigned char) (128 + (*left++ >> 24)); + *b++ = (unsigned char) (128 + (*right++ >> 24)); + } + } + else + { + for (int i = numSamples; --i >= 0;) + { + *b++ = (unsigned char) (128 + (*left++ >> 24)); + } + } + } - if (bytesWritten + bytes >= (uint32) 0xfff00000 - || ! output->write (buffer, bytes)) - { - // failed to write to disk, so let's try writing the header. - // If it's just run out of disk space, then if it does manage - // to write the header, we'll still have a useable file.. - writeHeader(); - writeFailed = true; - return false; - } - else - { - bytesWritten += bytes; - lengthInSamples += numSamples; + if (bytesWritten + bytes >= (uint32) 0xfff00000 + || ! output->write (buffer, bytes)) + { + // failed to write to disk, so let's try writing the header. + // If it's just run out of disk space, then if it does manage + // to write the header, we'll still have a useable file.. + writeHeader(); + writeFailed = true; + return false; + } + else + { + bytesWritten += bytes; + lengthInSamples += numSamples; - return true; - } - } + return true; + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; WavAudioFormat::WavAudioFormat() - : AudioFormat (TRANS (wavFormatName), (const tchar**) wavExtensions) + : AudioFormat (TRANS (wavFormatName), (const tchar**) wavExtensions) { } @@ -22598,131 +22343,131 @@ WavAudioFormat::~WavAudioFormat() const Array WavAudioFormat::getPossibleSampleRates() { - const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 }; - return Array (rates); + const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 }; + return Array (rates); } const Array WavAudioFormat::getPossibleBitDepths() { - const int depths[] = { 8, 16, 24, 32, 0 }; - return Array (depths); + const int depths[] = { 8, 16, 24, 32, 0 }; + return Array (depths); } bool WavAudioFormat::canDoStereo() { - return true; + return true; } bool WavAudioFormat::canDoMono() { - return true; + return true; } AudioFormatReader* WavAudioFormat::createReaderFor (InputStream* sourceStream, - const bool deleteStreamIfOpeningFails) + const bool deleteStreamIfOpeningFails) { - ScopedPointer r (new WavAudioFormatReader (sourceStream)); + ScopedPointer r (new WavAudioFormatReader (sourceStream)); - if (r->sampleRate != 0) - return r.release(); + if (r->sampleRate != 0) + return r.release(); - if (! deleteStreamIfOpeningFails) - r->input = 0; + if (! deleteStreamIfOpeningFails) + r->input = 0; - return 0; + return 0; } AudioFormatWriter* WavAudioFormat::createWriterFor (OutputStream* out, - double sampleRate, - unsigned int numChannels, - int bitsPerSample, - const StringPairArray& metadataValues, - int /*qualityOptionIndex*/) + double sampleRate, + unsigned int numChannels, + int bitsPerSample, + const StringPairArray& metadataValues, + int /*qualityOptionIndex*/) { - if (getPossibleBitDepths().contains (bitsPerSample)) - { - return new WavAudioFormatWriter (out, - sampleRate, - numChannels, - bitsPerSample, - metadataValues); - } + if (getPossibleBitDepths().contains (bitsPerSample)) + { + return new WavAudioFormatWriter (out, + sampleRate, + numChannels, + bitsPerSample, + metadataValues); + } - return 0; + return 0; } static bool juce_slowCopyOfWavFileWithNewMetadata (const File& file, const StringPairArray& metadata) { - bool ok = false; - WavAudioFormat wav; + bool ok = false; + WavAudioFormat wav; - const File dest (file.getNonexistentSibling()); + const File dest (file.getNonexistentSibling()); - { - ScopedPointer outStream (dest.createOutputStream()); + { + ScopedPointer outStream (dest.createOutputStream()); - if (outStream != 0) - { - ScopedPointer reader (wav.createReaderFor (file.createInputStream(), true)); + if (outStream != 0) + { + ScopedPointer reader (wav.createReaderFor (file.createInputStream(), true)); - if (reader != 0) - { - ScopedPointer writer (wav.createWriterFor (outStream, reader->sampleRate, - reader->numChannels, reader->bitsPerSample, - metadata, 0)); + if (reader != 0) + { + ScopedPointer writer (wav.createWriterFor (outStream, reader->sampleRate, + reader->numChannels, reader->bitsPerSample, + metadata, 0)); - if (writer != 0) - { - ok = writer->writeFromAudioReader (*reader, 0, -1); - outStream.release(); - } - } - } - } + if (writer != 0) + { + ok = writer->writeFromAudioReader (*reader, 0, -1); + outStream.release(); + } + } + } + } - if (ok) - ok = dest.moveFileTo (file); + if (ok) + ok = dest.moveFileTo (file); - if (! ok) - dest.deleteFile(); + if (! ok) + dest.deleteFile(); - return ok; + return ok; } bool WavAudioFormat::replaceMetadataInFile (const File& wavFile, const StringPairArray& newMetadata) { - ScopedPointer reader ((WavAudioFormatReader*) createReaderFor (wavFile.createInputStream(), true)); + ScopedPointer reader ((WavAudioFormatReader*) createReaderFor (wavFile.createInputStream(), true)); - if (reader != 0) - { - const int64 bwavPos = reader->bwavChunkStart; - const int64 bwavSize = reader->bwavSize; - reader = 0; + if (reader != 0) + { + const int64 bwavPos = reader->bwavChunkStart; + const int64 bwavSize = reader->bwavSize; + reader = 0; - if (bwavSize > 0) - { - MemoryBlock chunk = BWAVChunk::createFrom (newMetadata); + if (bwavSize > 0) + { + MemoryBlock chunk = BWAVChunk::createFrom (newMetadata); - if (chunk.getSize() <= bwavSize) - { - // the new one will fit in the space available, so write it directly.. - const int64 oldSize = wavFile.getSize(); + if (chunk.getSize() <= (size_t) bwavSize) + { + // the new one will fit in the space available, so write it directly.. + const int64 oldSize = wavFile.getSize(); - { - ScopedPointer out (wavFile.createOutputStream()); - out->setPosition (bwavPos); - out->write (chunk.getData(), chunk.getSize()); - out->setPosition (oldSize); - } + { + ScopedPointer out (wavFile.createOutputStream()); + out->setPosition (bwavPos); + out->write (chunk.getData(), (int) chunk.getSize()); + out->setPosition (oldSize); + } - jassert (wavFile.getSize() == oldSize); + jassert (wavFile.getSize() == oldSize); - return true; - } - } - } + return true; + } + } + } - return juce_slowCopyOfWavFileWithNewMetadata (wavFile, newMetadata); + return juce_slowCopyOfWavFileWithNewMetadata (wavFile, newMetadata); } END_JUCE_NAMESPACE @@ -22733,46 +22478,46 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioFormatReaderSource::AudioFormatReaderSource (AudioFormatReader* const reader_, - const bool deleteReaderWhenThisIsDeleted) - : reader (reader_), - deleteReader (deleteReaderWhenThisIsDeleted), - nextPlayPos (0), - looping (false) + const bool deleteReaderWhenThisIsDeleted) + : reader (reader_), + deleteReader (deleteReaderWhenThisIsDeleted), + nextPlayPos (0), + looping (false) { - jassert (reader != 0); + jassert (reader != 0); } AudioFormatReaderSource::~AudioFormatReaderSource() { - releaseResources(); + releaseResources(); - if (deleteReader) - delete reader; + if (deleteReader) + delete reader; } void AudioFormatReaderSource::setNextReadPosition (int newPosition) { - nextPlayPos = newPosition; + nextPlayPos = newPosition; } void AudioFormatReaderSource::setLooping (const bool shouldLoop) throw() { - looping = shouldLoop; + looping = shouldLoop; } int AudioFormatReaderSource::getNextReadPosition() const { - return (looping) ? (nextPlayPos % (int) reader->lengthInSamples) - : nextPlayPos; + return (looping) ? (nextPlayPos % (int) reader->lengthInSamples) + : nextPlayPos; } int AudioFormatReaderSource::getTotalLength() const { - return (int) reader->lengthInSamples; + return (int) reader->lengthInSamples; } void AudioFormatReaderSource::prepareToPlay (int /*samplesPerBlockExpected*/, - double /*sampleRate*/) + double /*sampleRate*/) { } @@ -22782,53 +22527,53 @@ void AudioFormatReaderSource::releaseResources() void AudioFormatReaderSource::getNextAudioBlock (const AudioSourceChannelInfo& info) { - if (info.numSamples > 0) - { - const int start = nextPlayPos; + if (info.numSamples > 0) + { + const int start = nextPlayPos; - if (looping) - { - const int newStart = start % (int) reader->lengthInSamples; - const int newEnd = (start + info.numSamples) % (int) reader->lengthInSamples; + if (looping) + { + const int newStart = start % (int) reader->lengthInSamples; + const int newEnd = (start + info.numSamples) % (int) reader->lengthInSamples; - if (newEnd > newStart) - { - info.buffer->readFromAudioReader (reader, - info.startSample, - newEnd - newStart, - newStart, - true, true); - } - else - { - const int endSamps = (int) reader->lengthInSamples - newStart; + if (newEnd > newStart) + { + info.buffer->readFromAudioReader (reader, + info.startSample, + newEnd - newStart, + newStart, + true, true); + } + else + { + const int endSamps = (int) reader->lengthInSamples - newStart; - info.buffer->readFromAudioReader (reader, - info.startSample, - endSamps, - newStart, - true, true); + info.buffer->readFromAudioReader (reader, + info.startSample, + endSamps, + newStart, + true, true); - info.buffer->readFromAudioReader (reader, - info.startSample + endSamps, - newEnd, - 0, - true, true); - } + info.buffer->readFromAudioReader (reader, + info.startSample + endSamps, + newEnd, + 0, + true, true); + } - nextPlayPos = newEnd; - } - else - { - info.buffer->readFromAudioReader (reader, - info.startSample, - info.numSamples, - start, - true, true); + nextPlayPos = newEnd; + } + else + { + info.buffer->readFromAudioReader (reader, + info.startSample, + info.numSamples, + start, + true, true); - nextPlayPos += info.numSamples; - } - } + nextPlayPos += info.numSamples; + } + } } END_JUCE_NAMESPACE @@ -22839,161 +22584,161 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioSourcePlayer::AudioSourcePlayer() - : source (0), - sampleRate (0), - bufferSize (0), - tempBuffer (2, 8), - lastGain (1.0f), - gain (1.0f) + : source (0), + sampleRate (0), + bufferSize (0), + tempBuffer (2, 8), + lastGain (1.0f), + gain (1.0f) { } AudioSourcePlayer::~AudioSourcePlayer() { - setSource (0); + setSource (0); } void AudioSourcePlayer::setSource (AudioSource* newSource) { - if (source != newSource) - { - AudioSource* const oldSource = source; + if (source != newSource) + { + AudioSource* const oldSource = source; - if (newSource != 0 && bufferSize > 0 && sampleRate > 0) - newSource->prepareToPlay (bufferSize, sampleRate); + if (newSource != 0 && bufferSize > 0 && sampleRate > 0) + newSource->prepareToPlay (bufferSize, sampleRate); - { - const ScopedLock sl (readLock); - source = newSource; - } + { + const ScopedLock sl (readLock); + source = newSource; + } - if (oldSource != 0) - oldSource->releaseResources(); - } + if (oldSource != 0) + oldSource->releaseResources(); + } } void AudioSourcePlayer::setGain (const float newGain) throw() { - gain = newGain; + gain = newGain; } void AudioSourcePlayer::audioDeviceIOCallback (const float** inputChannelData, - int totalNumInputChannels, - float** outputChannelData, - int totalNumOutputChannels, - int numSamples) + int totalNumInputChannels, + float** outputChannelData, + int totalNumOutputChannels, + int numSamples) { - // these should have been prepared by audioDeviceAboutToStart()... - jassert (sampleRate > 0 && bufferSize > 0); + // these should have been prepared by audioDeviceAboutToStart()... + jassert (sampleRate > 0 && bufferSize > 0); - const ScopedLock sl (readLock); + const ScopedLock sl (readLock); - if (source != 0) - { - AudioSourceChannelInfo info; - int i, numActiveChans = 0, numInputs = 0, numOutputs = 0; + if (source != 0) + { + AudioSourceChannelInfo info; + int i, numActiveChans = 0, numInputs = 0, numOutputs = 0; - // messy stuff needed to compact the channels down into an array - // of non-zero pointers.. - for (i = 0; i < totalNumInputChannels; ++i) - { - if (inputChannelData[i] != 0) - { - inputChans [numInputs++] = inputChannelData[i]; - if (numInputs >= numElementsInArray (inputChans)) - break; - } - } + // messy stuff needed to compact the channels down into an array + // of non-zero pointers.. + for (i = 0; i < totalNumInputChannels; ++i) + { + if (inputChannelData[i] != 0) + { + inputChans [numInputs++] = inputChannelData[i]; + if (numInputs >= numElementsInArray (inputChans)) + break; + } + } - for (i = 0; i < totalNumOutputChannels; ++i) - { - if (outputChannelData[i] != 0) - { - outputChans [numOutputs++] = outputChannelData[i]; - if (numOutputs >= numElementsInArray (outputChans)) - break; - } - } + for (i = 0; i < totalNumOutputChannels; ++i) + { + if (outputChannelData[i] != 0) + { + outputChans [numOutputs++] = outputChannelData[i]; + if (numOutputs >= numElementsInArray (outputChans)) + break; + } + } - if (numInputs > numOutputs) - { - // if there aren't enough output channels for the number of - // inputs, we need to create some temporary extra ones (can't - // use the input data in case it gets written to) - tempBuffer.setSize (numInputs - numOutputs, numSamples, - false, false, true); + if (numInputs > numOutputs) + { + // if there aren't enough output channels for the number of + // inputs, we need to create some temporary extra ones (can't + // use the input data in case it gets written to) + tempBuffer.setSize (numInputs - numOutputs, numSamples, + false, false, true); - for (i = 0; i < numOutputs; ++i) - { - channels[numActiveChans] = outputChans[i]; - memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples); - ++numActiveChans; - } + for (i = 0; i < numOutputs; ++i) + { + channels[numActiveChans] = outputChans[i]; + memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples); + ++numActiveChans; + } - for (i = numOutputs; i < numInputs; ++i) - { - channels[numActiveChans] = tempBuffer.getSampleData (i - numOutputs, 0); - memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples); - ++numActiveChans; - } - } - else - { - for (i = 0; i < numInputs; ++i) - { - channels[numActiveChans] = outputChans[i]; - memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples); - ++numActiveChans; - } + for (i = numOutputs; i < numInputs; ++i) + { + channels[numActiveChans] = tempBuffer.getSampleData (i - numOutputs, 0); + memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples); + ++numActiveChans; + } + } + else + { + for (i = 0; i < numInputs; ++i) + { + channels[numActiveChans] = outputChans[i]; + memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * numSamples); + ++numActiveChans; + } - for (i = numInputs; i < numOutputs; ++i) - { - channels[numActiveChans] = outputChans[i]; - zeromem (channels[numActiveChans], sizeof (float) * numSamples); - ++numActiveChans; - } - } + for (i = numInputs; i < numOutputs; ++i) + { + channels[numActiveChans] = outputChans[i]; + zeromem (channels[numActiveChans], sizeof (float) * numSamples); + ++numActiveChans; + } + } - AudioSampleBuffer buffer (channels, numActiveChans, numSamples); + AudioSampleBuffer buffer (channels, numActiveChans, numSamples); - info.buffer = &buffer; - info.startSample = 0; - info.numSamples = numSamples; + info.buffer = &buffer; + info.startSample = 0; + info.numSamples = numSamples; - source->getNextAudioBlock (info); + source->getNextAudioBlock (info); - for (i = info.buffer->getNumChannels(); --i >= 0;) - info.buffer->applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain); + for (i = info.buffer->getNumChannels(); --i >= 0;) + info.buffer->applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain); - lastGain = gain; - } - else - { - for (int i = 0; i < totalNumOutputChannels; ++i) - if (outputChannelData[i] != 0) - zeromem (outputChannelData[i], sizeof (float) * numSamples); - } + lastGain = gain; + } + else + { + for (int i = 0; i < totalNumOutputChannels; ++i) + if (outputChannelData[i] != 0) + zeromem (outputChannelData[i], sizeof (float) * numSamples); + } } void AudioSourcePlayer::audioDeviceAboutToStart (AudioIODevice* device) { - sampleRate = device->getCurrentSampleRate(); - bufferSize = device->getCurrentBufferSizeSamples(); - zeromem (channels, sizeof (channels)); + sampleRate = device->getCurrentSampleRate(); + bufferSize = device->getCurrentBufferSizeSamples(); + zeromem (channels, sizeof (channels)); - if (source != 0) - source->prepareToPlay (bufferSize, sampleRate); + if (source != 0) + source->prepareToPlay (bufferSize, sampleRate); } void AudioSourcePlayer::audioDeviceStopped() { - if (source != 0) - source->releaseResources(); + if (source != 0) + source->releaseResources(); - sampleRate = 0.0; - bufferSize = 0; + sampleRate = 0.0; + bufferSize = 0; - tempBuffer.setSize (2, 8); + tempBuffer.setSize (2, 8); } END_JUCE_NAMESPACE @@ -23004,260 +22749,260 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioTransportSource::AudioTransportSource() - : source (0), - resamplerSource (0), - bufferingSource (0), - positionableSource (0), - masterSource (0), - gain (1.0f), - lastGain (1.0f), - playing (false), - stopped (true), - sampleRate (44100.0), - sourceSampleRate (0.0), - blockSize (128), - readAheadBufferSize (0), - isPrepared (false), - inputStreamEOF (false) + : source (0), + resamplerSource (0), + bufferingSource (0), + positionableSource (0), + masterSource (0), + gain (1.0f), + lastGain (1.0f), + playing (false), + stopped (true), + sampleRate (44100.0), + sourceSampleRate (0.0), + blockSize (128), + readAheadBufferSize (0), + isPrepared (false), + inputStreamEOF (false) { } AudioTransportSource::~AudioTransportSource() { - setSource (0); + setSource (0); - releaseResources(); + releaseResources(); } void AudioTransportSource::setSource (PositionableAudioSource* const newSource, - int readAheadBufferSize_, - double sourceSampleRateToCorrectFor) + int readAheadBufferSize_, + double sourceSampleRateToCorrectFor) { - if (source == newSource) - { - if (source == 0) - return; + if (source == newSource) + { + if (source == 0) + return; - setSource (0, 0, 0); // deselect and reselect to avoid releasing resources wrongly - } + setSource (0, 0, 0); // deselect and reselect to avoid releasing resources wrongly + } - readAheadBufferSize = readAheadBufferSize_; - sourceSampleRate = sourceSampleRateToCorrectFor; + readAheadBufferSize = readAheadBufferSize_; + sourceSampleRate = sourceSampleRateToCorrectFor; - ResamplingAudioSource* newResamplerSource = 0; - BufferingAudioSource* newBufferingSource = 0; - PositionableAudioSource* newPositionableSource = 0; - AudioSource* newMasterSource = 0; + ResamplingAudioSource* newResamplerSource = 0; + BufferingAudioSource* newBufferingSource = 0; + PositionableAudioSource* newPositionableSource = 0; + AudioSource* newMasterSource = 0; - ScopedPointer oldResamplerSource (resamplerSource); - ScopedPointer oldBufferingSource (bufferingSource); - AudioSource* oldMasterSource = masterSource; + ScopedPointer oldResamplerSource (resamplerSource); + ScopedPointer oldBufferingSource (bufferingSource); + AudioSource* oldMasterSource = masterSource; - if (newSource != 0) - { - newPositionableSource = newSource; + if (newSource != 0) + { + newPositionableSource = newSource; - if (readAheadBufferSize_ > 0) - newPositionableSource = newBufferingSource - = new BufferingAudioSource (newPositionableSource, false, readAheadBufferSize_); + if (readAheadBufferSize_ > 0) + newPositionableSource = newBufferingSource + = new BufferingAudioSource (newPositionableSource, false, readAheadBufferSize_); - newPositionableSource->setNextReadPosition (0); + newPositionableSource->setNextReadPosition (0); - if (sourceSampleRateToCorrectFor != 0) - newMasterSource = newResamplerSource - = new ResamplingAudioSource (newPositionableSource, false); - else - newMasterSource = newPositionableSource; + if (sourceSampleRateToCorrectFor != 0) + newMasterSource = newResamplerSource + = new ResamplingAudioSource (newPositionableSource, false); + else + newMasterSource = newPositionableSource; - if (isPrepared) - { - if (newResamplerSource != 0 && sourceSampleRate > 0 && sampleRate > 0) - newResamplerSource->setResamplingRatio (sourceSampleRate / sampleRate); + if (isPrepared) + { + if (newResamplerSource != 0 && sourceSampleRate > 0 && sampleRate > 0) + newResamplerSource->setResamplingRatio (sourceSampleRate / sampleRate); - newMasterSource->prepareToPlay (blockSize, sampleRate); - } - } + newMasterSource->prepareToPlay (blockSize, sampleRate); + } + } - { - const ScopedLock sl (callbackLock); + { + const ScopedLock sl (callbackLock); - source = newSource; - resamplerSource = newResamplerSource; - bufferingSource = newBufferingSource; - masterSource = newMasterSource; - positionableSource = newPositionableSource; + source = newSource; + resamplerSource = newResamplerSource; + bufferingSource = newBufferingSource; + masterSource = newMasterSource; + positionableSource = newPositionableSource; - playing = false; - } + playing = false; + } - if (oldMasterSource != 0) - oldMasterSource->releaseResources(); + if (oldMasterSource != 0) + oldMasterSource->releaseResources(); } void AudioTransportSource::start() { - if ((! playing) && masterSource != 0) - { - callbackLock.enter(); - playing = true; - stopped = false; - inputStreamEOF = false; - callbackLock.exit(); + if ((! playing) && masterSource != 0) + { + callbackLock.enter(); + playing = true; + stopped = false; + inputStreamEOF = false; + callbackLock.exit(); - sendChangeMessage (this); - } + sendChangeMessage (this); + } } void AudioTransportSource::stop() { - if (playing) - { - callbackLock.enter(); - playing = false; - callbackLock.exit(); + if (playing) + { + callbackLock.enter(); + playing = false; + callbackLock.exit(); - int n = 500; - while (--n >= 0 && ! stopped) - Thread::sleep (2); + int n = 500; + while (--n >= 0 && ! stopped) + Thread::sleep (2); - sendChangeMessage (this); - } + sendChangeMessage (this); + } } void AudioTransportSource::setPosition (double newPosition) { - if (sampleRate > 0.0) - setNextReadPosition (roundDoubleToInt (newPosition * sampleRate)); + if (sampleRate > 0.0) + setNextReadPosition (roundToInt (newPosition * sampleRate)); } double AudioTransportSource::getCurrentPosition() const { - if (sampleRate > 0.0) - return getNextReadPosition() / sampleRate; - else - return 0.0; + if (sampleRate > 0.0) + return getNextReadPosition() / sampleRate; + else + return 0.0; } void AudioTransportSource::setNextReadPosition (int newPosition) { - if (positionableSource != 0) - { - if (sampleRate > 0 && sourceSampleRate > 0) - newPosition = roundDoubleToInt (newPosition * sourceSampleRate / sampleRate); + if (positionableSource != 0) + { + if (sampleRate > 0 && sourceSampleRate > 0) + newPosition = roundToInt (newPosition * sourceSampleRate / sampleRate); - positionableSource->setNextReadPosition (newPosition); - } + positionableSource->setNextReadPosition (newPosition); + } } int AudioTransportSource::getNextReadPosition() const { - if (positionableSource != 0) - { - const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0; + if (positionableSource != 0) + { + const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0; - return roundDoubleToInt (positionableSource->getNextReadPosition() * ratio); - } + return roundToInt (positionableSource->getNextReadPosition() * ratio); + } - return 0; + return 0; } int AudioTransportSource::getTotalLength() const { - const ScopedLock sl (callbackLock); + const ScopedLock sl (callbackLock); - if (positionableSource != 0) - { - const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0; + if (positionableSource != 0) + { + const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0; - return roundDoubleToInt (positionableSource->getTotalLength() * ratio); - } + return roundToInt (positionableSource->getTotalLength() * ratio); + } - return 0; + return 0; } bool AudioTransportSource::isLooping() const { - const ScopedLock sl (callbackLock); + const ScopedLock sl (callbackLock); - return positionableSource != 0 - && positionableSource->isLooping(); + return positionableSource != 0 + && positionableSource->isLooping(); } void AudioTransportSource::setGain (const float newGain) throw() { - gain = newGain; + gain = newGain; } void AudioTransportSource::prepareToPlay (int samplesPerBlockExpected, - double sampleRate_) + double sampleRate_) { - const ScopedLock sl (callbackLock); + const ScopedLock sl (callbackLock); - sampleRate = sampleRate_; - blockSize = samplesPerBlockExpected; + sampleRate = sampleRate_; + blockSize = samplesPerBlockExpected; - if (masterSource != 0) - masterSource->prepareToPlay (samplesPerBlockExpected, sampleRate); + if (masterSource != 0) + masterSource->prepareToPlay (samplesPerBlockExpected, sampleRate); - if (resamplerSource != 0 && sourceSampleRate != 0) - resamplerSource->setResamplingRatio (sourceSampleRate / sampleRate); + if (resamplerSource != 0 && sourceSampleRate != 0) + resamplerSource->setResamplingRatio (sourceSampleRate / sampleRate); - isPrepared = true; + isPrepared = true; } void AudioTransportSource::releaseResources() { - const ScopedLock sl (callbackLock); + const ScopedLock sl (callbackLock); - if (masterSource != 0) - masterSource->releaseResources(); + if (masterSource != 0) + masterSource->releaseResources(); - isPrepared = false; + isPrepared = false; } void AudioTransportSource::getNextAudioBlock (const AudioSourceChannelInfo& info) { - const ScopedLock sl (callbackLock); + const ScopedLock sl (callbackLock); - inputStreamEOF = false; + inputStreamEOF = false; - if (masterSource != 0 && ! stopped) - { - masterSource->getNextAudioBlock (info); + if (masterSource != 0 && ! stopped) + { + masterSource->getNextAudioBlock (info); - if (! playing) - { - // just stopped playing, so fade out the last block.. - for (int i = info.buffer->getNumChannels(); --i >= 0;) - info.buffer->applyGainRamp (i, info.startSample, jmin (256, info.numSamples), 1.0f, 0.0f); + if (! playing) + { + // just stopped playing, so fade out the last block.. + for (int i = info.buffer->getNumChannels(); --i >= 0;) + info.buffer->applyGainRamp (i, info.startSample, jmin (256, info.numSamples), 1.0f, 0.0f); - if (info.numSamples > 256) - info.buffer->clear (info.startSample + 256, info.numSamples - 256); - } + if (info.numSamples > 256) + info.buffer->clear (info.startSample + 256, info.numSamples - 256); + } - if (positionableSource->getNextReadPosition() > positionableSource->getTotalLength() + 1 - && ! positionableSource->isLooping()) - { - playing = false; - inputStreamEOF = true; - sendChangeMessage (this); - } + if (positionableSource->getNextReadPosition() > positionableSource->getTotalLength() + 1 + && ! positionableSource->isLooping()) + { + playing = false; + inputStreamEOF = true; + sendChangeMessage (this); + } - stopped = ! playing; + stopped = ! playing; - for (int i = info.buffer->getNumChannels(); --i >= 0;) - { - info.buffer->applyGainRamp (i, info.startSample, info.numSamples, - lastGain, gain); - } - } - else - { - info.clearActiveBufferRegion(); - stopped = true; - } + for (int i = info.buffer->getNumChannels(); --i >= 0;) + { + info.buffer->applyGainRamp (i, info.startSample, info.numSamples, + lastGain, gain); + } + } + else + { + info.clearActiveBufferRegion(); + stopped = true; + } - lastGain = gain; + lastGain = gain; } END_JUCE_NAMESPACE @@ -23268,325 +23013,324 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE class SharedBufferingAudioSourceThread : public DeletedAtShutdown, - public Thread, - private Timer + public Thread, + private Timer { public: - SharedBufferingAudioSourceThread() - : Thread ("Audio Buffer"), - sources (8) - { - } + SharedBufferingAudioSourceThread() + : Thread ("Audio Buffer") + { + } - ~SharedBufferingAudioSourceThread() - { - stopThread (10000); - clearSingletonInstance(); - } + ~SharedBufferingAudioSourceThread() + { + stopThread (10000); + clearSingletonInstance(); + } - juce_DeclareSingleton (SharedBufferingAudioSourceThread, false) + juce_DeclareSingleton (SharedBufferingAudioSourceThread, false) - void addSource (BufferingAudioSource* source) - { - const ScopedLock sl (lock); + void addSource (BufferingAudioSource* source) + { + const ScopedLock sl (lock); - if (! sources.contains ((void*) source)) - { - sources.add ((void*) source); - startThread(); + if (! sources.contains ((void*) source)) + { + sources.add ((void*) source); + startThread(); - stopTimer(); - } + stopTimer(); + } - notify(); - } + notify(); + } - void removeSource (BufferingAudioSource* source) - { - const ScopedLock sl (lock); - sources.removeValue ((void*) source); + void removeSource (BufferingAudioSource* source) + { + const ScopedLock sl (lock); + sources.removeValue ((void*) source); - if (sources.size() == 0) - startTimer (5000); - } + if (sources.size() == 0) + startTimer (5000); + } private: - VoidArray sources; - CriticalSection lock; + VoidArray sources; + CriticalSection lock; - void run() - { - while (! threadShouldExit()) - { - bool busy = false; + void run() + { + while (! threadShouldExit()) + { + bool busy = false; - for (int i = sources.size(); --i >= 0;) - { - if (threadShouldExit()) - return; + for (int i = sources.size(); --i >= 0;) + { + if (threadShouldExit()) + return; - const ScopedLock sl (lock); + const ScopedLock sl (lock); - BufferingAudioSource* const b = (BufferingAudioSource*) sources[i]; + BufferingAudioSource* const b = (BufferingAudioSource*) sources[i]; - if (b != 0 && b->readNextBufferChunk()) - busy = true; - } + if (b != 0 && b->readNextBufferChunk()) + busy = true; + } - if (! busy) - wait (500); - } - } + if (! busy) + wait (500); + } + } - void timerCallback() - { - stopTimer(); + void timerCallback() + { + stopTimer(); - if (sources.size() == 0) - deleteInstance(); - } + if (sources.size() == 0) + deleteInstance(); + } - SharedBufferingAudioSourceThread (const SharedBufferingAudioSourceThread&); - const SharedBufferingAudioSourceThread& operator= (const SharedBufferingAudioSourceThread&); + SharedBufferingAudioSourceThread (const SharedBufferingAudioSourceThread&); + const SharedBufferingAudioSourceThread& operator= (const SharedBufferingAudioSourceThread&); }; juce_ImplementSingleton (SharedBufferingAudioSourceThread) BufferingAudioSource::BufferingAudioSource (PositionableAudioSource* source_, - const bool deleteSourceWhenDeleted_, - int numberOfSamplesToBuffer_) - : source (source_), - deleteSourceWhenDeleted (deleteSourceWhenDeleted_), - numberOfSamplesToBuffer (jmax (1024, numberOfSamplesToBuffer_)), - buffer (2, 0), - bufferValidStart (0), - bufferValidEnd (0), - nextPlayPos (0), - wasSourceLooping (false) + const bool deleteSourceWhenDeleted_, + int numberOfSamplesToBuffer_) + : source (source_), + deleteSourceWhenDeleted (deleteSourceWhenDeleted_), + numberOfSamplesToBuffer (jmax (1024, numberOfSamplesToBuffer_)), + buffer (2, 0), + bufferValidStart (0), + bufferValidEnd (0), + nextPlayPos (0), + wasSourceLooping (false) { - jassert (source_ != 0); + jassert (source_ != 0); - jassert (numberOfSamplesToBuffer_ > 1024); // not much point using this class if you're - // not using a larger buffer.. + jassert (numberOfSamplesToBuffer_ > 1024); // not much point using this class if you're + // not using a larger buffer.. } BufferingAudioSource::~BufferingAudioSource() { - SharedBufferingAudioSourceThread* const thread = SharedBufferingAudioSourceThread::getInstanceWithoutCreating(); + SharedBufferingAudioSourceThread* const thread = SharedBufferingAudioSourceThread::getInstanceWithoutCreating(); - if (thread != 0) - thread->removeSource (this); + if (thread != 0) + thread->removeSource (this); - if (deleteSourceWhenDeleted) - delete source; + if (deleteSourceWhenDeleted) + delete source; } void BufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate_) { - source->prepareToPlay (samplesPerBlockExpected, sampleRate_); + source->prepareToPlay (samplesPerBlockExpected, sampleRate_); - sampleRate = sampleRate_; + sampleRate = sampleRate_; - buffer.setSize (2, jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer)); - buffer.clear(); + buffer.setSize (2, jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer)); + buffer.clear(); - bufferValidStart = 0; - bufferValidEnd = 0; + bufferValidStart = 0; + bufferValidEnd = 0; - SharedBufferingAudioSourceThread::getInstance()->addSource (this); + SharedBufferingAudioSourceThread::getInstance()->addSource (this); - while (bufferValidEnd - bufferValidStart < jmin (((int) sampleRate_) / 4, - buffer.getNumSamples() / 2)) - { - SharedBufferingAudioSourceThread::getInstance()->notify(); - Thread::sleep (5); - } + while (bufferValidEnd - bufferValidStart < jmin (((int) sampleRate_) / 4, + buffer.getNumSamples() / 2)) + { + SharedBufferingAudioSourceThread::getInstance()->notify(); + Thread::sleep (5); + } } void BufferingAudioSource::releaseResources() { - SharedBufferingAudioSourceThread* const thread = SharedBufferingAudioSourceThread::getInstanceWithoutCreating(); + SharedBufferingAudioSourceThread* const thread = SharedBufferingAudioSourceThread::getInstanceWithoutCreating(); - if (thread != 0) - thread->removeSource (this); + if (thread != 0) + thread->removeSource (this); - buffer.setSize (2, 0); - source->releaseResources(); + buffer.setSize (2, 0); + source->releaseResources(); } void BufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info) { - const ScopedLock sl (bufferStartPosLock); + const ScopedLock sl (bufferStartPosLock); - const int validStart = jlimit (bufferValidStart, bufferValidEnd, nextPlayPos) - nextPlayPos; - const int validEnd = jlimit (bufferValidStart, bufferValidEnd, nextPlayPos + info.numSamples) - nextPlayPos; + const int validStart = jlimit (bufferValidStart, bufferValidEnd, nextPlayPos) - nextPlayPos; + const int validEnd = jlimit (bufferValidStart, bufferValidEnd, nextPlayPos + info.numSamples) - nextPlayPos; - if (validStart == validEnd) - { - // total cache miss - info.clearActiveBufferRegion(); - } - else - { - if (validStart > 0) - info.buffer->clear (info.startSample, validStart); // partial cache miss at start + if (validStart == validEnd) + { + // total cache miss + info.clearActiveBufferRegion(); + } + else + { + if (validStart > 0) + info.buffer->clear (info.startSample, validStart); // partial cache miss at start - if (validEnd < info.numSamples) - info.buffer->clear (info.startSample + validEnd, - info.numSamples - validEnd); // partial cache miss at end + if (validEnd < info.numSamples) + info.buffer->clear (info.startSample + validEnd, + info.numSamples - validEnd); // partial cache miss at end - if (validStart < validEnd) - { - for (int chan = jmin (2, info.buffer->getNumChannels()); --chan >= 0;) - { - const int startBufferIndex = (validStart + nextPlayPos) % buffer.getNumSamples(); - const int endBufferIndex = (validEnd + nextPlayPos) % buffer.getNumSamples(); + if (validStart < validEnd) + { + for (int chan = jmin (2, info.buffer->getNumChannels()); --chan >= 0;) + { + const int startBufferIndex = (validStart + nextPlayPos) % buffer.getNumSamples(); + const int endBufferIndex = (validEnd + nextPlayPos) % buffer.getNumSamples(); - if (startBufferIndex < endBufferIndex) - { - info.buffer->copyFrom (chan, info.startSample + validStart, - buffer, - chan, startBufferIndex, - validEnd - validStart); - } - else - { - const int initialSize = buffer.getNumSamples() - startBufferIndex; + if (startBufferIndex < endBufferIndex) + { + info.buffer->copyFrom (chan, info.startSample + validStart, + buffer, + chan, startBufferIndex, + validEnd - validStart); + } + else + { + const int initialSize = buffer.getNumSamples() - startBufferIndex; - info.buffer->copyFrom (chan, info.startSample + validStart, - buffer, - chan, startBufferIndex, - initialSize); + info.buffer->copyFrom (chan, info.startSample + validStart, + buffer, + chan, startBufferIndex, + initialSize); - info.buffer->copyFrom (chan, info.startSample + validStart + initialSize, - buffer, - chan, 0, - (validEnd - validStart) - initialSize); - } - } - } + info.buffer->copyFrom (chan, info.startSample + validStart + initialSize, + buffer, + chan, 0, + (validEnd - validStart) - initialSize); + } + } + } - nextPlayPos += info.numSamples; + nextPlayPos += info.numSamples; - if (source->isLooping() && nextPlayPos > 0) - nextPlayPos %= source->getTotalLength(); - } + if (source->isLooping() && nextPlayPos > 0) + nextPlayPos %= source->getTotalLength(); + } - SharedBufferingAudioSourceThread* const thread = SharedBufferingAudioSourceThread::getInstanceWithoutCreating(); + SharedBufferingAudioSourceThread* const thread = SharedBufferingAudioSourceThread::getInstanceWithoutCreating(); - if (thread != 0) - thread->notify(); + if (thread != 0) + thread->notify(); } int BufferingAudioSource::getNextReadPosition() const { - return (source->isLooping() && nextPlayPos > 0) - ? nextPlayPos % source->getTotalLength() - : nextPlayPos; + return (source->isLooping() && nextPlayPos > 0) + ? nextPlayPos % source->getTotalLength() + : nextPlayPos; } void BufferingAudioSource::setNextReadPosition (int newPosition) { - const ScopedLock sl (bufferStartPosLock); + const ScopedLock sl (bufferStartPosLock); - nextPlayPos = newPosition; + nextPlayPos = newPosition; - SharedBufferingAudioSourceThread* const thread = SharedBufferingAudioSourceThread::getInstanceWithoutCreating(); + SharedBufferingAudioSourceThread* const thread = SharedBufferingAudioSourceThread::getInstanceWithoutCreating(); - if (thread != 0) - thread->notify(); + if (thread != 0) + thread->notify(); } bool BufferingAudioSource::readNextBufferChunk() { - bufferStartPosLock.enter(); + bufferStartPosLock.enter(); - if (wasSourceLooping != isLooping()) - { - wasSourceLooping = isLooping(); - bufferValidStart = 0; - bufferValidEnd = 0; - } + if (wasSourceLooping != isLooping()) + { + wasSourceLooping = isLooping(); + bufferValidStart = 0; + bufferValidEnd = 0; + } - int newBVS = jmax (0, nextPlayPos); - int newBVE = newBVS + buffer.getNumSamples() - 4; - int sectionToReadStart = 0; - int sectionToReadEnd = 0; + int newBVS = jmax (0, nextPlayPos); + int newBVE = newBVS + buffer.getNumSamples() - 4; + int sectionToReadStart = 0; + int sectionToReadEnd = 0; - const int maxChunkSize = 2048; + const int maxChunkSize = 2048; - if (newBVS < bufferValidStart || newBVS >= bufferValidEnd) - { - newBVE = jmin (newBVE, newBVS + maxChunkSize); + if (newBVS < bufferValidStart || newBVS >= bufferValidEnd) + { + newBVE = jmin (newBVE, newBVS + maxChunkSize); - sectionToReadStart = newBVS; - sectionToReadEnd = newBVE; + sectionToReadStart = newBVS; + sectionToReadEnd = newBVE; - bufferValidStart = 0; - bufferValidEnd = 0; - } - else if (abs (newBVS - bufferValidStart) > 512 - || abs (newBVE - bufferValidEnd) > 512) - { - newBVE = jmin (newBVE, bufferValidEnd + maxChunkSize); + bufferValidStart = 0; + bufferValidEnd = 0; + } + else if (abs (newBVS - bufferValidStart) > 512 + || abs (newBVE - bufferValidEnd) > 512) + { + newBVE = jmin (newBVE, bufferValidEnd + maxChunkSize); - sectionToReadStart = bufferValidEnd; - sectionToReadEnd = newBVE; + sectionToReadStart = bufferValidEnd; + sectionToReadEnd = newBVE; - bufferValidStart = newBVS; - bufferValidEnd = jmin (bufferValidEnd, newBVE); - } + bufferValidStart = newBVS; + bufferValidEnd = jmin (bufferValidEnd, newBVE); + } - bufferStartPosLock.exit(); + bufferStartPosLock.exit(); - if (sectionToReadStart != sectionToReadEnd) - { - const int bufferIndexStart = sectionToReadStart % buffer.getNumSamples(); - const int bufferIndexEnd = sectionToReadEnd % buffer.getNumSamples(); + if (sectionToReadStart != sectionToReadEnd) + { + const int bufferIndexStart = sectionToReadStart % buffer.getNumSamples(); + const int bufferIndexEnd = sectionToReadEnd % buffer.getNumSamples(); - if (bufferIndexStart < bufferIndexEnd) - { - readBufferSection (sectionToReadStart, - sectionToReadEnd - sectionToReadStart, - bufferIndexStart); - } - else - { - const int initialSize = buffer.getNumSamples() - bufferIndexStart; + if (bufferIndexStart < bufferIndexEnd) + { + readBufferSection (sectionToReadStart, + sectionToReadEnd - sectionToReadStart, + bufferIndexStart); + } + else + { + const int initialSize = buffer.getNumSamples() - bufferIndexStart; - readBufferSection (sectionToReadStart, - initialSize, - bufferIndexStart); + readBufferSection (sectionToReadStart, + initialSize, + bufferIndexStart); - readBufferSection (sectionToReadStart + initialSize, - (sectionToReadEnd - sectionToReadStart) - initialSize, - 0); - } + readBufferSection (sectionToReadStart + initialSize, + (sectionToReadEnd - sectionToReadStart) - initialSize, + 0); + } - const ScopedLock sl2 (bufferStartPosLock); + const ScopedLock sl2 (bufferStartPosLock); - bufferValidStart = newBVS; - bufferValidEnd = newBVE; + bufferValidStart = newBVS; + bufferValidEnd = newBVE; - return true; - } - else - { - return false; - } + return true; + } + else + { + return false; + } } void BufferingAudioSource::readBufferSection (int start, int length, int bufferOffset) { - if (source->getNextReadPosition() != start) - source->setNextReadPosition (start); + if (source->getNextReadPosition() != start) + source->setNextReadPosition (start); - AudioSourceChannelInfo info; - info.buffer = &buffer; - info.startSample = bufferOffset; - info.numSamples = length; + AudioSourceChannelInfo info; + info.buffer = &buffer; + info.startSample = bufferOffset; + info.numSamples = length; - source->getNextAudioBlock (info); + source->getNextAudioBlock (info); } END_JUCE_NAMESPACE @@ -23597,171 +23341,171 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ChannelRemappingAudioSource::ChannelRemappingAudioSource (AudioSource* const source_, - const bool deleteSourceWhenDeleted_) + const bool deleteSourceWhenDeleted_) : requiredNumberOfChannels (2), - source (source_), - deleteSourceWhenDeleted (deleteSourceWhenDeleted_), - buffer (2, 16) + source (source_), + deleteSourceWhenDeleted (deleteSourceWhenDeleted_), + buffer (2, 16) { - remappedInfo.buffer = &buffer; - remappedInfo.startSample = 0; + remappedInfo.buffer = &buffer; + remappedInfo.startSample = 0; } ChannelRemappingAudioSource::~ChannelRemappingAudioSource() { - if (deleteSourceWhenDeleted) - delete source; + if (deleteSourceWhenDeleted) + delete source; } void ChannelRemappingAudioSource::setNumberOfChannelsToProduce (const int requiredNumberOfChannels_) throw() { - const ScopedLock sl (lock); - requiredNumberOfChannels = requiredNumberOfChannels_; + const ScopedLock sl (lock); + requiredNumberOfChannels = requiredNumberOfChannels_; } void ChannelRemappingAudioSource::clearAllMappings() throw() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - remappedInputs.clear(); - remappedOutputs.clear(); + remappedInputs.clear(); + remappedOutputs.clear(); } void ChannelRemappingAudioSource::setInputChannelMapping (const int destIndex, const int sourceIndex) throw() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - while (remappedInputs.size() < destIndex) - remappedInputs.add (-1); + while (remappedInputs.size() < destIndex) + remappedInputs.add (-1); - remappedInputs.set (destIndex, sourceIndex); + remappedInputs.set (destIndex, sourceIndex); } void ChannelRemappingAudioSource::setOutputChannelMapping (const int sourceIndex, const int destIndex) throw() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - while (remappedOutputs.size() < sourceIndex) - remappedOutputs.add (-1); + while (remappedOutputs.size() < sourceIndex) + remappedOutputs.add (-1); - remappedOutputs.set (sourceIndex, destIndex); + remappedOutputs.set (sourceIndex, destIndex); } int ChannelRemappingAudioSource::getRemappedInputChannel (const int inputChannelIndex) const throw() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (inputChannelIndex >= 0 && inputChannelIndex < remappedInputs.size()) - return remappedInputs.getUnchecked (inputChannelIndex); + if (inputChannelIndex >= 0 && inputChannelIndex < remappedInputs.size()) + return remappedInputs.getUnchecked (inputChannelIndex); - return -1; + return -1; } int ChannelRemappingAudioSource::getRemappedOutputChannel (const int outputChannelIndex) const throw() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (outputChannelIndex >= 0 && outputChannelIndex < remappedOutputs.size()) - return remappedOutputs .getUnchecked (outputChannelIndex); + if (outputChannelIndex >= 0 && outputChannelIndex < remappedOutputs.size()) + return remappedOutputs .getUnchecked (outputChannelIndex); - return -1; + return -1; } void ChannelRemappingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate) { - source->prepareToPlay (samplesPerBlockExpected, sampleRate); + source->prepareToPlay (samplesPerBlockExpected, sampleRate); } void ChannelRemappingAudioSource::releaseResources() { - source->releaseResources(); + source->releaseResources(); } void ChannelRemappingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - buffer.setSize (requiredNumberOfChannels, bufferToFill.numSamples, false, false, true); + buffer.setSize (requiredNumberOfChannels, bufferToFill.numSamples, false, false, true); - const int numChans = bufferToFill.buffer->getNumChannels(); + const int numChans = bufferToFill.buffer->getNumChannels(); - int i; - for (i = 0; i < buffer.getNumChannels(); ++i) - { - const int remappedChan = getRemappedInputChannel (i); + int i; + for (i = 0; i < buffer.getNumChannels(); ++i) + { + const int remappedChan = getRemappedInputChannel (i); - if (remappedChan >= 0 && remappedChan < numChans) - { - buffer.copyFrom (i, 0, *bufferToFill.buffer, - remappedChan, - bufferToFill.startSample, - bufferToFill.numSamples); - } - else - { - buffer.clear (i, 0, bufferToFill.numSamples); - } - } + if (remappedChan >= 0 && remappedChan < numChans) + { + buffer.copyFrom (i, 0, *bufferToFill.buffer, + remappedChan, + bufferToFill.startSample, + bufferToFill.numSamples); + } + else + { + buffer.clear (i, 0, bufferToFill.numSamples); + } + } - remappedInfo.numSamples = bufferToFill.numSamples; + remappedInfo.numSamples = bufferToFill.numSamples; - source->getNextAudioBlock (remappedInfo); + source->getNextAudioBlock (remappedInfo); - bufferToFill.clearActiveBufferRegion(); + bufferToFill.clearActiveBufferRegion(); - for (i = 0; i < requiredNumberOfChannels; ++i) - { - const int remappedChan = getRemappedOutputChannel (i); + for (i = 0; i < requiredNumberOfChannels; ++i) + { + const int remappedChan = getRemappedOutputChannel (i); - if (remappedChan >= 0 && remappedChan < numChans) - { - bufferToFill.buffer->addFrom (remappedChan, bufferToFill.startSample, - buffer, i, 0, bufferToFill.numSamples); + if (remappedChan >= 0 && remappedChan < numChans) + { + bufferToFill.buffer->addFrom (remappedChan, bufferToFill.startSample, + buffer, i, 0, bufferToFill.numSamples); - } - } + } + } } XmlElement* ChannelRemappingAudioSource::createXml() const throw() { - XmlElement* e = new XmlElement (T("MAPPINGS")); + XmlElement* e = new XmlElement (T("MAPPINGS")); - String ins, outs; - int i; + String ins, outs; + int i; - const ScopedLock sl (lock); + const ScopedLock sl (lock); - for (i = 0; i < remappedInputs.size(); ++i) - ins << remappedInputs.getUnchecked(i) << T(' '); + for (i = 0; i < remappedInputs.size(); ++i) + ins << remappedInputs.getUnchecked(i) << T(' '); - for (i = 0; i < remappedOutputs.size(); ++i) - outs << remappedOutputs.getUnchecked(i) << T(' '); + for (i = 0; i < remappedOutputs.size(); ++i) + outs << remappedOutputs.getUnchecked(i) << T(' '); - e->setAttribute (T("inputs"), ins.trimEnd()); - e->setAttribute (T("outputs"), outs.trimEnd()); + e->setAttribute (T("inputs"), ins.trimEnd()); + e->setAttribute (T("outputs"), outs.trimEnd()); - return e; + return e; } void ChannelRemappingAudioSource::restoreFromXml (const XmlElement& e) throw() { - if (e.hasTagName (T("MAPPINGS"))) - { - const ScopedLock sl (lock); + if (e.hasTagName (T("MAPPINGS"))) + { + const ScopedLock sl (lock); - clearAllMappings(); + clearAllMappings(); - StringArray ins, outs; - ins.addTokens (e.getStringAttribute (T("inputs")), false); - outs.addTokens (e.getStringAttribute (T("outputs")), false); + StringArray ins, outs; + ins.addTokens (e.getStringAttribute (T("inputs")), false); + outs.addTokens (e.getStringAttribute (T("outputs")), false); - int i; - for (i = 0; i < ins.size(); ++i) - remappedInputs.add (ins[i].getIntValue()); + int i; + for (i = 0; i < ins.size(); ++i) + remappedInputs.add (ins[i].getIntValue()); - for (i = 0; i < outs.size(); ++i) - remappedOutputs.add (outs[i].getIntValue()); - } + for (i = 0; i < outs.size(); ++i) + remappedOutputs.add (outs[i].getIntValue()); + } } END_JUCE_NAMESPACE @@ -23772,54 +23516,54 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE IIRFilterAudioSource::IIRFilterAudioSource (AudioSource* const inputSource, - const bool deleteInputWhenDeleted_) - : input (inputSource), - deleteInputWhenDeleted (deleteInputWhenDeleted_) + const bool deleteInputWhenDeleted_) + : input (inputSource), + deleteInputWhenDeleted (deleteInputWhenDeleted_) { - jassert (inputSource != 0); + jassert (inputSource != 0); - for (int i = 2; --i >= 0;) - iirFilters.add (new IIRFilter()); + for (int i = 2; --i >= 0;) + iirFilters.add (new IIRFilter()); } IIRFilterAudioSource::~IIRFilterAudioSource() { - if (deleteInputWhenDeleted) - delete input; + if (deleteInputWhenDeleted) + delete input; } void IIRFilterAudioSource::setFilterParameters (const IIRFilter& newSettings) { - for (int i = iirFilters.size(); --i >= 0;) - iirFilters.getUnchecked(i)->copyCoefficientsFrom (newSettings); + for (int i = iirFilters.size(); --i >= 0;) + iirFilters.getUnchecked(i)->copyCoefficientsFrom (newSettings); } void IIRFilterAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate) { - input->prepareToPlay (samplesPerBlockExpected, sampleRate); + input->prepareToPlay (samplesPerBlockExpected, sampleRate); - for (int i = iirFilters.size(); --i >= 0;) - iirFilters.getUnchecked(i)->reset(); + for (int i = iirFilters.size(); --i >= 0;) + iirFilters.getUnchecked(i)->reset(); } void IIRFilterAudioSource::releaseResources() { - input->releaseResources(); + input->releaseResources(); } void IIRFilterAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) { - input->getNextAudioBlock (bufferToFill); + input->getNextAudioBlock (bufferToFill); - const int numChannels = bufferToFill.buffer->getNumChannels(); + const int numChannels = bufferToFill.buffer->getNumChannels(); - while (numChannels > iirFilters.size()) - iirFilters.add (new IIRFilter (*iirFilters.getUnchecked (0))); + while (numChannels > iirFilters.size()) + iirFilters.add (new IIRFilter (*iirFilters.getUnchecked (0))); - for (int i = 0; i < numChannels; ++i) - iirFilters.getUnchecked(i) - ->processSamples (bufferToFill.buffer->getSampleData (i, bufferToFill.startSample), - bufferToFill.numSamples); + for (int i = 0; i < numChannels; ++i) + iirFilters.getUnchecked(i) + ->processSamples (bufferToFill.buffer->getSampleData (i, bufferToFill.startSample), + bufferToFill.numSamples); } END_JUCE_NAMESPACE @@ -23830,132 +23574,132 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MixerAudioSource::MixerAudioSource() - : tempBuffer (2, 0), - currentSampleRate (0.0), - bufferSizeExpected (0) + : tempBuffer (2, 0), + currentSampleRate (0.0), + bufferSizeExpected (0) { } MixerAudioSource::~MixerAudioSource() { - removeAllInputs(); + removeAllInputs(); } void MixerAudioSource::addInputSource (AudioSource* input, const bool deleteWhenRemoved) { - if (input != 0 && ! inputs.contains (input)) - { - lock.enter(); - double localRate = currentSampleRate; - int localBufferSize = bufferSizeExpected; - lock.exit(); + if (input != 0 && ! inputs.contains (input)) + { + lock.enter(); + double localRate = currentSampleRate; + int localBufferSize = bufferSizeExpected; + lock.exit(); - if (localRate != 0.0) - input->prepareToPlay (localBufferSize, localRate); + if (localRate != 0.0) + input->prepareToPlay (localBufferSize, localRate); - const ScopedLock sl (lock); + const ScopedLock sl (lock); - inputsToDelete.setBit (inputs.size(), deleteWhenRemoved); - inputs.add (input); - } + inputsToDelete.setBit (inputs.size(), deleteWhenRemoved); + inputs.add (input); + } } void MixerAudioSource::removeInputSource (AudioSource* input, const bool deleteInput) { - if (input != 0) - { - lock.enter(); - const int index = inputs.indexOf ((void*) input); + if (input != 0) + { + lock.enter(); + const int index = inputs.indexOf ((void*) input); - if (index >= 0) - { - inputsToDelete.shiftBits (index, 1); - inputs.remove (index); - } + if (index >= 0) + { + inputsToDelete.shiftBits (index, 1); + inputs.remove (index); + } - lock.exit(); + lock.exit(); - if (index >= 0) - { - input->releaseResources(); + if (index >= 0) + { + input->releaseResources(); - if (deleteInput) - delete input; - } - } + if (deleteInput) + delete input; + } + } } void MixerAudioSource::removeAllInputs() { - lock.enter(); - VoidArray inputsCopy (inputs); - BitArray inputsToDeleteCopy (inputsToDelete); - inputs.clear(); - lock.exit(); + lock.enter(); + VoidArray inputsCopy (inputs); + BitArray inputsToDeleteCopy (inputsToDelete); + inputs.clear(); + lock.exit(); - for (int i = inputsCopy.size(); --i >= 0;) - if (inputsToDeleteCopy[i]) - delete (AudioSource*) inputsCopy[i]; + for (int i = inputsCopy.size(); --i >= 0;) + if (inputsToDeleteCopy[i]) + delete (AudioSource*) inputsCopy[i]; } void MixerAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate) { - tempBuffer.setSize (2, samplesPerBlockExpected); + tempBuffer.setSize (2, samplesPerBlockExpected); - const ScopedLock sl (lock); + const ScopedLock sl (lock); - currentSampleRate = sampleRate; - bufferSizeExpected = samplesPerBlockExpected; + currentSampleRate = sampleRate; + bufferSizeExpected = samplesPerBlockExpected; - for (int i = inputs.size(); --i >= 0;) - ((AudioSource*) inputs.getUnchecked(i))->prepareToPlay (samplesPerBlockExpected, - sampleRate); + for (int i = inputs.size(); --i >= 0;) + ((AudioSource*) inputs.getUnchecked(i))->prepareToPlay (samplesPerBlockExpected, + sampleRate); } void MixerAudioSource::releaseResources() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - for (int i = inputs.size(); --i >= 0;) - ((AudioSource*) inputs.getUnchecked(i))->releaseResources(); + for (int i = inputs.size(); --i >= 0;) + ((AudioSource*) inputs.getUnchecked(i))->releaseResources(); - tempBuffer.setSize (2, 0); + tempBuffer.setSize (2, 0); - currentSampleRate = 0; - bufferSizeExpected = 0; + currentSampleRate = 0; + bufferSizeExpected = 0; } void MixerAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (inputs.size() > 0) - { - ((AudioSource*) inputs.getUnchecked(0))->getNextAudioBlock (info); + if (inputs.size() > 0) + { + ((AudioSource*) inputs.getUnchecked(0))->getNextAudioBlock (info); - if (inputs.size() > 1) - { - tempBuffer.setSize (jmax (1, info.buffer->getNumChannels()), - info.buffer->getNumSamples()); + if (inputs.size() > 1) + { + tempBuffer.setSize (jmax (1, info.buffer->getNumChannels()), + info.buffer->getNumSamples()); - AudioSourceChannelInfo info2; - info2.buffer = &tempBuffer; - info2.numSamples = info.numSamples; - info2.startSample = 0; + AudioSourceChannelInfo info2; + info2.buffer = &tempBuffer; + info2.numSamples = info.numSamples; + info2.startSample = 0; - for (int i = 1; i < inputs.size(); ++i) - { - ((AudioSource*) inputs.getUnchecked(i))->getNextAudioBlock (info2); + for (int i = 1; i < inputs.size(); ++i) + { + ((AudioSource*) inputs.getUnchecked(i))->getNextAudioBlock (info2); - for (int chan = 0; chan < info.buffer->getNumChannels(); ++chan) - info.buffer->addFrom (chan, info.startSample, tempBuffer, chan, 0, info.numSamples); - } - } - } - else - { - info.clearActiveBufferRegion(); - } + for (int chan = 0; chan < info.buffer->getNumChannels(); ++chan) + info.buffer->addFrom (chan, info.startSample, tempBuffer, chan, 0, info.numSamples); + } + } + } + else + { + info.clearActiveBufferRegion(); + } } END_JUCE_NAMESPACE @@ -23966,235 +23710,235 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ResamplingAudioSource::ResamplingAudioSource (AudioSource* const inputSource, - const bool deleteInputWhenDeleted_) - : input (inputSource), - deleteInputWhenDeleted (deleteInputWhenDeleted_), - ratio (1.0), - lastRatio (1.0), - buffer (2, 0), - sampsInBuffer (0) + const bool deleteInputWhenDeleted_) + : input (inputSource), + deleteInputWhenDeleted (deleteInputWhenDeleted_), + ratio (1.0), + lastRatio (1.0), + buffer (2, 0), + sampsInBuffer (0) { - jassert (input != 0); + jassert (input != 0); } ResamplingAudioSource::~ResamplingAudioSource() { - if (deleteInputWhenDeleted) - delete input; + if (deleteInputWhenDeleted) + delete input; } void ResamplingAudioSource::setResamplingRatio (const double samplesInPerOutputSample) { - jassert (samplesInPerOutputSample > 0); + jassert (samplesInPerOutputSample > 0); - const ScopedLock sl (ratioLock); - ratio = jmax (0.0, samplesInPerOutputSample); + const ScopedLock sl (ratioLock); + ratio = jmax (0.0, samplesInPerOutputSample); } void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected, - double sampleRate) + double sampleRate) { - const ScopedLock sl (ratioLock); + const ScopedLock sl (ratioLock); - input->prepareToPlay (samplesPerBlockExpected, sampleRate); + input->prepareToPlay (samplesPerBlockExpected, sampleRate); - buffer.setSize (2, roundDoubleToInt (samplesPerBlockExpected * ratio) + 32); - buffer.clear(); - sampsInBuffer = 0; - bufferPos = 0; - subSampleOffset = 0.0; + buffer.setSize (2, roundToInt (samplesPerBlockExpected * ratio) + 32); + buffer.clear(); + sampsInBuffer = 0; + bufferPos = 0; + subSampleOffset = 0.0; - createLowPass (ratio); - resetFilters(); + createLowPass (ratio); + resetFilters(); } void ResamplingAudioSource::releaseResources() { - input->releaseResources(); - buffer.setSize (2, 0); + input->releaseResources(); + buffer.setSize (2, 0); } void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info) { - const ScopedLock sl (ratioLock); + const ScopedLock sl (ratioLock); - if (lastRatio != ratio) - { - createLowPass (ratio); - lastRatio = ratio; - } + if (lastRatio != ratio) + { + createLowPass (ratio); + lastRatio = ratio; + } - const int sampsNeeded = roundDoubleToInt (info.numSamples * ratio) + 2; + const int sampsNeeded = roundToInt (info.numSamples * ratio) + 2; - int bufferSize = buffer.getNumSamples(); + int bufferSize = buffer.getNumSamples(); - if (bufferSize < sampsNeeded + 8) - { - bufferPos %= bufferSize; - bufferSize = sampsNeeded + 32; - buffer.setSize (buffer.getNumChannels(), bufferSize, true, true); - } + if (bufferSize < sampsNeeded + 8) + { + bufferPos %= bufferSize; + bufferSize = sampsNeeded + 32; + buffer.setSize (buffer.getNumChannels(), bufferSize, true, true); + } - bufferPos %= bufferSize; + bufferPos %= bufferSize; - int endOfBufferPos = bufferPos + sampsInBuffer; + int endOfBufferPos = bufferPos + sampsInBuffer; - while (sampsNeeded > sampsInBuffer) - { - endOfBufferPos %= bufferSize; + while (sampsNeeded > sampsInBuffer) + { + endOfBufferPos %= bufferSize; - int numToDo = jmin (sampsNeeded - sampsInBuffer, - bufferSize - endOfBufferPos); + int numToDo = jmin (sampsNeeded - sampsInBuffer, + bufferSize - endOfBufferPos); - AudioSourceChannelInfo readInfo; - readInfo.buffer = &buffer; - readInfo.numSamples = numToDo; - readInfo.startSample = endOfBufferPos; + AudioSourceChannelInfo readInfo; + readInfo.buffer = &buffer; + readInfo.numSamples = numToDo; + readInfo.startSample = endOfBufferPos; - input->getNextAudioBlock (readInfo); + input->getNextAudioBlock (readInfo); - if (ratio > 1.0001) - { - // for down-sampling, pre-apply the filter.. + if (ratio > 1.0001) + { + // for down-sampling, pre-apply the filter.. - for (int i = jmin (2, info.buffer->getNumChannels()); --i >= 0;) - applyFilter (buffer.getSampleData (i, endOfBufferPos), numToDo, filterStates[i]); - } + for (int i = jmin (2, info.buffer->getNumChannels()); --i >= 0;) + applyFilter (buffer.getSampleData (i, endOfBufferPos), numToDo, filterStates[i]); + } - sampsInBuffer += numToDo; - endOfBufferPos += numToDo; - } + sampsInBuffer += numToDo; + endOfBufferPos += numToDo; + } - float* dl = info.buffer->getSampleData (0, info.startSample); - float* dr = (info.buffer->getNumChannels() > 1) ? info.buffer->getSampleData (1, info.startSample) : 0; + float* dl = info.buffer->getSampleData (0, info.startSample); + float* dr = (info.buffer->getNumChannels() > 1) ? info.buffer->getSampleData (1, info.startSample) : 0; - const float* const bl = buffer.getSampleData (0, 0); - const float* const br = buffer.getSampleData (1, 0); + const float* const bl = buffer.getSampleData (0, 0); + const float* const br = buffer.getSampleData (1, 0); - int nextPos = (bufferPos + 1) % bufferSize; + int nextPos = (bufferPos + 1) % bufferSize; - for (int m = info.numSamples; --m >= 0;) - { - const float alpha = (float) subSampleOffset; - const float invAlpha = 1.0f - alpha; + for (int m = info.numSamples; --m >= 0;) + { + const float alpha = (float) subSampleOffset; + const float invAlpha = 1.0f - alpha; - *dl++ = bl [bufferPos] * invAlpha + bl [nextPos] * alpha; + *dl++ = bl [bufferPos] * invAlpha + bl [nextPos] * alpha; - if (dr != 0) - *dr++ = br [bufferPos] * invAlpha + br [nextPos] * alpha; + if (dr != 0) + *dr++ = br [bufferPos] * invAlpha + br [nextPos] * alpha; - subSampleOffset += ratio; + subSampleOffset += ratio; - jassert (sampsInBuffer > 0); + jassert (sampsInBuffer > 0); - while (subSampleOffset >= 1.0) - { - if (++bufferPos >= bufferSize) - bufferPos = 0; + while (subSampleOffset >= 1.0) + { + if (++bufferPos >= bufferSize) + bufferPos = 0; - --sampsInBuffer; + --sampsInBuffer; - nextPos = (bufferPos + 1) % bufferSize; - subSampleOffset -= 1.0; - } - } + nextPos = (bufferPos + 1) % bufferSize; + subSampleOffset -= 1.0; + } + } - if (ratio < 0.9999) - { - // for up-sampling, apply the filter after transposing.. + if (ratio < 0.9999) + { + // for up-sampling, apply the filter after transposing.. - for (int i = jmin (2, info.buffer->getNumChannels()); --i >= 0;) - applyFilter (info.buffer->getSampleData (i, info.startSample), info.numSamples, filterStates[i]); - } - else if (ratio <= 1.0001) - { - // if the filter's not currently being applied, keep it stoked with the last couple of samples to avoid discontinuities - for (int i = jmin (2, info.buffer->getNumChannels()); --i >= 0;) - { - const float* const endOfBuffer = info.buffer->getSampleData (i, info.startSample + info.numSamples - 1); - FilterState& fs = filterStates[i]; + for (int i = jmin (2, info.buffer->getNumChannels()); --i >= 0;) + applyFilter (info.buffer->getSampleData (i, info.startSample), info.numSamples, filterStates[i]); + } + else if (ratio <= 1.0001) + { + // if the filter's not currently being applied, keep it stoked with the last couple of samples to avoid discontinuities + for (int i = jmin (2, info.buffer->getNumChannels()); --i >= 0;) + { + const float* const endOfBuffer = info.buffer->getSampleData (i, info.startSample + info.numSamples - 1); + FilterState& fs = filterStates[i]; - if (info.numSamples > 1) - { - fs.y2 = fs.x2 = *(endOfBuffer - 1); - } - else - { - fs.y2 = fs.y1; - fs.x2 = fs.x1; - } + if (info.numSamples > 1) + { + fs.y2 = fs.x2 = *(endOfBuffer - 1); + } + else + { + fs.y2 = fs.y1; + fs.x2 = fs.x1; + } - fs.y1 = fs.x1 = *endOfBuffer; - } - } + fs.y1 = fs.x1 = *endOfBuffer; + } + } - jassert (sampsInBuffer >= 0); + jassert (sampsInBuffer >= 0); } void ResamplingAudioSource::createLowPass (const double frequencyRatio) { - const double proportionalRate = (frequencyRatio > 1.0) ? 0.5 / frequencyRatio - : 0.5 * frequencyRatio; + const double proportionalRate = (frequencyRatio > 1.0) ? 0.5 / frequencyRatio + : 0.5 * frequencyRatio; - const double n = 1.0 / tan (double_Pi * jmax (0.001, proportionalRate)); - const double nSquared = n * n; - const double c1 = 1.0 / (1.0 + sqrt (2.0) * n + nSquared); + const double n = 1.0 / tan (double_Pi * jmax (0.001, proportionalRate)); + const double nSquared = n * n; + const double c1 = 1.0 / (1.0 + sqrt (2.0) * n + nSquared); - setFilterCoefficients (c1, - c1 * 2.0f, - c1, - 1.0, - c1 * 2.0 * (1.0 - nSquared), - c1 * (1.0 - sqrt (2.0) * n + nSquared)); + setFilterCoefficients (c1, + c1 * 2.0f, + c1, + 1.0, + c1 * 2.0 * (1.0 - nSquared), + c1 * (1.0 - sqrt (2.0) * n + nSquared)); } void ResamplingAudioSource::setFilterCoefficients (double c1, double c2, double c3, double c4, double c5, double c6) { - const double a = 1.0 / c4; + const double a = 1.0 / c4; - c1 *= a; - c2 *= a; - c3 *= a; - c5 *= a; - c6 *= a; + c1 *= a; + c2 *= a; + c3 *= a; + c5 *= a; + c6 *= a; - coefficients[0] = c1; - coefficients[1] = c2; - coefficients[2] = c3; - coefficients[3] = c4; - coefficients[4] = c5; - coefficients[5] = c6; + coefficients[0] = c1; + coefficients[1] = c2; + coefficients[2] = c3; + coefficients[3] = c4; + coefficients[4] = c5; + coefficients[5] = c6; } void ResamplingAudioSource::resetFilters() { - zeromem (filterStates, sizeof (filterStates)); + zeromem (filterStates, sizeof (filterStates)); } void ResamplingAudioSource::applyFilter (float* samples, int num, FilterState& fs) { - while (--num >= 0) - { - const double in = *samples; + while (--num >= 0) + { + const double in = *samples; - double out = coefficients[0] * in - + coefficients[1] * fs.x1 - + coefficients[2] * fs.x2 - - coefficients[4] * fs.y1 - - coefficients[5] * fs.y2; + double out = coefficients[0] * in + + coefficients[1] * fs.x1 + + coefficients[2] * fs.x2 + - coefficients[4] * fs.y1 + - coefficients[5] * fs.y2; #if JUCE_INTEL - if (! (out < -1.0e-8 || out > 1.0e-8)) - out = 0; + if (! (out < -1.0e-8 || out > 1.0e-8)) + out = 0; #endif - fs.x2 = fs.x1; - fs.x1 = in; - fs.y2 = fs.y1; - fs.y1 = out; + fs.x2 = fs.x1; + fs.x1 = in; + fs.y2 = fs.y1; + fs.y1 = out; - *samples++ = (float) out; - } + *samples++ = (float) out; + } } END_JUCE_NAMESPACE @@ -24205,11 +23949,11 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ToneGeneratorAudioSource::ToneGeneratorAudioSource() - : frequency (1000.0), - sampleRate (44100.0), - currentPhase (0.0), - phasePerSample (0.0), - amplitude (0.5f) + : frequency (1000.0), + sampleRate (44100.0), + currentPhase (0.0), + phasePerSample (0.0), + amplitude (0.5f) { } @@ -24219,21 +23963,21 @@ ToneGeneratorAudioSource::~ToneGeneratorAudioSource() void ToneGeneratorAudioSource::setAmplitude (const float newAmplitude) { - amplitude = newAmplitude; + amplitude = newAmplitude; } void ToneGeneratorAudioSource::setFrequency (const double newFrequencyHz) { - frequency = newFrequencyHz; - phasePerSample = 0.0; + frequency = newFrequencyHz; + phasePerSample = 0.0; } void ToneGeneratorAudioSource::prepareToPlay (int /*samplesPerBlockExpected*/, - double sampleRate_) + double sampleRate_) { - currentPhase = 0.0; - phasePerSample = 0.0; - sampleRate = sampleRate_; + currentPhase = 0.0; + phasePerSample = 0.0; + sampleRate = sampleRate_; } void ToneGeneratorAudioSource::releaseResources() @@ -24242,17 +23986,17 @@ void ToneGeneratorAudioSource::releaseResources() void ToneGeneratorAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info) { - if (phasePerSample == 0.0) - phasePerSample = double_Pi * 2.0 / (sampleRate / frequency); + if (phasePerSample == 0.0) + phasePerSample = double_Pi * 2.0 / (sampleRate / frequency); - for (int i = 0; i < info.numSamples; ++i) - { - const float sample = amplitude * (float) sin (currentPhase); - currentPhase += phasePerSample; + for (int i = 0; i < info.numSamples; ++i) + { + const float sample = amplitude * (float) sin (currentPhase); + currentPhase += phasePerSample; - for (int j = info.buffer->getNumChannels(); --j >= 0;) - *info.buffer->getSampleData (j, info.startSample + i) = sample; - } + for (int j = info.buffer->getNumChannels(); --j >= 0;) + *info.buffer->getSampleData (j, info.startSample + i) = sample; + } } END_JUCE_NAMESPACE @@ -24263,68 +24007,65 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioDeviceManager::AudioDeviceSetup::AudioDeviceSetup() - : sampleRate (0), - bufferSize (0), - useDefaultInputChannels (true), - useDefaultOutputChannels (true) + : sampleRate (0), + bufferSize (0), + useDefaultInputChannels (true), + useDefaultOutputChannels (true) { } bool AudioDeviceManager::AudioDeviceSetup::operator== (const AudioDeviceManager::AudioDeviceSetup& other) const { - return outputDeviceName == other.outputDeviceName - && inputDeviceName == other.inputDeviceName - && sampleRate == other.sampleRate - && bufferSize == other.bufferSize - && inputChannels == other.inputChannels - && useDefaultInputChannels == other.useDefaultInputChannels - && outputChannels == other.outputChannels - && useDefaultOutputChannels == other.useDefaultOutputChannels; + return outputDeviceName == other.outputDeviceName + && inputDeviceName == other.inputDeviceName + && sampleRate == other.sampleRate + && bufferSize == other.bufferSize + && inputChannels == other.inputChannels + && useDefaultInputChannels == other.useDefaultInputChannels + && outputChannels == other.outputChannels + && useDefaultOutputChannels == other.useDefaultOutputChannels; } AudioDeviceManager::AudioDeviceManager() - : currentAudioDevice (0), - numInputChansNeeded (0), - numOutputChansNeeded (2), - listNeedsScanning (true), - useInputNames (false), - inputLevelMeasurementEnabledCount (0), - inputLevel (0), - tempBuffer (2, 2), - enabledMidiInputs (4), - midiCallbacks (4), - midiCallbackDevices (4), - defaultMidiOutput (0), - cpuUsageMs (0), - timeToCpuScale (0) + : currentAudioDevice (0), + numInputChansNeeded (0), + numOutputChansNeeded (2), + listNeedsScanning (true), + useInputNames (false), + inputLevelMeasurementEnabledCount (0), + inputLevel (0), + tempBuffer (2, 2), + defaultMidiOutput (0), + cpuUsageMs (0), + timeToCpuScale (0) { - callbackHandler.owner = this; + callbackHandler.owner = this; } AudioDeviceManager::~AudioDeviceManager() { - currentAudioDevice = 0; - defaultMidiOutput = 0; + currentAudioDevice = 0; + defaultMidiOutput = 0; } void AudioDeviceManager::createDeviceTypesIfNeeded() { - if (availableDeviceTypes.size() == 0) - { - createAudioDeviceTypes (availableDeviceTypes); + if (availableDeviceTypes.size() == 0) + { + createAudioDeviceTypes (availableDeviceTypes); - while (lastDeviceTypeConfigs.size() < availableDeviceTypes.size()) - lastDeviceTypeConfigs.add (new AudioDeviceSetup()); + while (lastDeviceTypeConfigs.size() < availableDeviceTypes.size()) + lastDeviceTypeConfigs.add (new AudioDeviceSetup()); - if (availableDeviceTypes.size() > 0) - currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName(); - } + if (availableDeviceTypes.size() > 0) + currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName(); + } } const OwnedArray & AudioDeviceManager::getAvailableDeviceTypes() { - scanDevicesIfNeeded(); - return availableDeviceTypes; + scanDevicesIfNeeded(); + return availableDeviceTypes; } AudioIODeviceType* juce_createAudioIODeviceType_CoreAudio(); @@ -24337,860 +24078,860 @@ AudioIODeviceType* juce_createAudioIODeviceType_JACK(); void AudioDeviceManager::createAudioDeviceTypes (OwnedArray & list) { - #if JUCE_WINDOWS - #if JUCE_WASAPI - if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista) - list.add (juce_createAudioIODeviceType_WASAPI()); - #endif + #if JUCE_WINDOWS + #if JUCE_WASAPI + if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista) + list.add (juce_createAudioIODeviceType_WASAPI()); + #endif - #if JUCE_DIRECTSOUND - list.add (juce_createAudioIODeviceType_DirectSound()); - #endif + #if JUCE_DIRECTSOUND + list.add (juce_createAudioIODeviceType_DirectSound()); + #endif - #if JUCE_ASIO - list.add (juce_createAudioIODeviceType_ASIO()); - #endif - #endif + #if JUCE_ASIO + list.add (juce_createAudioIODeviceType_ASIO()); + #endif + #endif - #if JUCE_MAC - list.add (juce_createAudioIODeviceType_CoreAudio()); - #endif + #if JUCE_MAC + list.add (juce_createAudioIODeviceType_CoreAudio()); + #endif - #if JUCE_IPHONE - list.add (juce_createAudioIODeviceType_iPhoneAudio()); - #endif + #if JUCE_IPHONE + list.add (juce_createAudioIODeviceType_iPhoneAudio()); + #endif - #if JUCE_LINUX && JUCE_ALSA - list.add (juce_createAudioIODeviceType_ALSA()); - #endif + #if JUCE_LINUX && JUCE_ALSA + list.add (juce_createAudioIODeviceType_ALSA()); + #endif - #if JUCE_LINUX && JUCE_JACK - list.add (juce_createAudioIODeviceType_JACK()); - #endif + #if JUCE_LINUX && JUCE_JACK + list.add (juce_createAudioIODeviceType_JACK()); + #endif } const String AudioDeviceManager::initialise (const int numInputChannelsNeeded, - const int numOutputChannelsNeeded, - const XmlElement* const e, - const bool selectDefaultDeviceOnFailure, - const String& preferredDefaultDeviceName, - const AudioDeviceSetup* preferredSetupOptions) + const int numOutputChannelsNeeded, + const XmlElement* const e, + const bool selectDefaultDeviceOnFailure, + const String& preferredDefaultDeviceName, + const AudioDeviceSetup* preferredSetupOptions) { - scanDevicesIfNeeded(); + scanDevicesIfNeeded(); - numInputChansNeeded = numInputChannelsNeeded; - numOutputChansNeeded = numOutputChannelsNeeded; + numInputChansNeeded = numInputChannelsNeeded; + numOutputChansNeeded = numOutputChannelsNeeded; - if (e != 0 && e->hasTagName (T("DEVICESETUP"))) - { - lastExplicitSettings = new XmlElement (*e); + if (e != 0 && e->hasTagName (T("DEVICESETUP"))) + { + lastExplicitSettings = new XmlElement (*e); - String error; - AudioDeviceSetup setup; + String error; + AudioDeviceSetup setup; - if (preferredSetupOptions != 0) - setup = *preferredSetupOptions; + if (preferredSetupOptions != 0) + setup = *preferredSetupOptions; - if (e->getStringAttribute (T("audioDeviceName")).isNotEmpty()) - { - setup.inputDeviceName = setup.outputDeviceName - = e->getStringAttribute (T("audioDeviceName")); - } - else - { - setup.inputDeviceName = e->getStringAttribute (T("audioInputDeviceName")); - setup.outputDeviceName = e->getStringAttribute (T("audioOutputDeviceName")); - } + if (e->getStringAttribute (T("audioDeviceName")).isNotEmpty()) + { + setup.inputDeviceName = setup.outputDeviceName + = e->getStringAttribute (T("audioDeviceName")); + } + else + { + setup.inputDeviceName = e->getStringAttribute (T("audioInputDeviceName")); + setup.outputDeviceName = e->getStringAttribute (T("audioOutputDeviceName")); + } - currentDeviceType = e->getStringAttribute (T("deviceType")); - if (currentDeviceType.isEmpty()) - { - AudioIODeviceType* const type = findType (setup.inputDeviceName, setup.outputDeviceName); + currentDeviceType = e->getStringAttribute (T("deviceType")); + if (currentDeviceType.isEmpty()) + { + AudioIODeviceType* const type = findType (setup.inputDeviceName, setup.outputDeviceName); - if (type != 0) - currentDeviceType = type->getTypeName(); - else if (availableDeviceTypes.size() > 0) - currentDeviceType = availableDeviceTypes[0]->getTypeName(); - } + if (type != 0) + currentDeviceType = type->getTypeName(); + else if (availableDeviceTypes.size() > 0) + currentDeviceType = availableDeviceTypes[0]->getTypeName(); + } - setup.bufferSize = e->getIntAttribute (T("audioDeviceBufferSize")); - setup.sampleRate = e->getDoubleAttribute (T("audioDeviceRate")); + setup.bufferSize = e->getIntAttribute (T("audioDeviceBufferSize")); + setup.sampleRate = e->getDoubleAttribute (T("audioDeviceRate")); - setup.inputChannels.parseString (e->getStringAttribute (T("audioDeviceInChans"), T("11")), 2); - setup.outputChannels.parseString (e->getStringAttribute (T("audioDeviceOutChans"), T("11")), 2); + setup.inputChannels.parseString (e->getStringAttribute (T("audioDeviceInChans"), T("11")), 2); + setup.outputChannels.parseString (e->getStringAttribute (T("audioDeviceOutChans"), T("11")), 2); - setup.useDefaultInputChannels = ! e->hasAttribute (T("audioDeviceInChans")); - setup.useDefaultOutputChannels = ! e->hasAttribute (T("audioDeviceOutChans")); + setup.useDefaultInputChannels = ! e->hasAttribute (T("audioDeviceInChans")); + setup.useDefaultOutputChannels = ! e->hasAttribute (T("audioDeviceOutChans")); - error = setAudioDeviceSetup (setup, true); + error = setAudioDeviceSetup (setup, true); - midiInsFromXml.clear(); - forEachXmlChildElementWithTagName (*e, c, T("MIDIINPUT")) - midiInsFromXml.add (c->getStringAttribute (T("name"))); + midiInsFromXml.clear(); + forEachXmlChildElementWithTagName (*e, c, T("MIDIINPUT")) + midiInsFromXml.add (c->getStringAttribute (T("name"))); - const StringArray allMidiIns (MidiInput::getDevices()); + const StringArray allMidiIns (MidiInput::getDevices()); - for (int i = allMidiIns.size(); --i >= 0;) - setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i])); + for (int i = allMidiIns.size(); --i >= 0;) + setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i])); - if (error.isNotEmpty() && selectDefaultDeviceOnFailure) - error = initialise (numInputChannelsNeeded, numOutputChannelsNeeded, 0, - false, preferredDefaultDeviceName); + if (error.isNotEmpty() && selectDefaultDeviceOnFailure) + error = initialise (numInputChannelsNeeded, numOutputChannelsNeeded, 0, + false, preferredDefaultDeviceName); - setDefaultMidiOutput (e->getStringAttribute (T("defaultMidiOutput"))); + setDefaultMidiOutput (e->getStringAttribute (T("defaultMidiOutput"))); - return error; - } - else - { - AudioDeviceSetup setup; + return error; + } + else + { + AudioDeviceSetup setup; - if (preferredSetupOptions != 0) - { - setup = *preferredSetupOptions; - } - else if (preferredDefaultDeviceName.isNotEmpty()) - { - for (int j = availableDeviceTypes.size(); --j >= 0;) - { - AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(j); + if (preferredSetupOptions != 0) + { + setup = *preferredSetupOptions; + } + else if (preferredDefaultDeviceName.isNotEmpty()) + { + for (int j = availableDeviceTypes.size(); --j >= 0;) + { + AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(j); - StringArray outs (type->getDeviceNames (false)); + StringArray outs (type->getDeviceNames (false)); - int i; - for (i = 0; i < outs.size(); ++i) - { - if (outs[i].matchesWildcard (preferredDefaultDeviceName, true)) - { - setup.outputDeviceName = outs[i]; - break; - } - } + int i; + for (i = 0; i < outs.size(); ++i) + { + if (outs[i].matchesWildcard (preferredDefaultDeviceName, true)) + { + setup.outputDeviceName = outs[i]; + break; + } + } - StringArray ins (type->getDeviceNames (true)); + StringArray ins (type->getDeviceNames (true)); - for (i = 0; i < ins.size(); ++i) - { - if (ins[i].matchesWildcard (preferredDefaultDeviceName, true)) - { - setup.inputDeviceName = ins[i]; - break; - } - } - } - } + for (i = 0; i < ins.size(); ++i) + { + if (ins[i].matchesWildcard (preferredDefaultDeviceName, true)) + { + setup.inputDeviceName = ins[i]; + break; + } + } + } + } - insertDefaultDeviceNames (setup); - return setAudioDeviceSetup (setup, false); - } + insertDefaultDeviceNames (setup); + return setAudioDeviceSetup (setup, false); + } } void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const { - AudioIODeviceType* type = getCurrentDeviceTypeObject(); - if (type != 0) - { - if (setup.outputDeviceName.isEmpty()) - setup.outputDeviceName = type->getDeviceNames (false) [type->getDefaultDeviceIndex (false)]; + AudioIODeviceType* type = getCurrentDeviceTypeObject(); + if (type != 0) + { + if (setup.outputDeviceName.isEmpty()) + setup.outputDeviceName = type->getDeviceNames (false) [type->getDefaultDeviceIndex (false)]; - if (setup.inputDeviceName.isEmpty()) - setup.inputDeviceName = type->getDeviceNames (true) [type->getDefaultDeviceIndex (true)]; - } + if (setup.inputDeviceName.isEmpty()) + setup.inputDeviceName = type->getDeviceNames (true) [type->getDefaultDeviceIndex (true)]; + } } XmlElement* AudioDeviceManager::createStateXml() const { - return lastExplicitSettings != 0 ? new XmlElement (*lastExplicitSettings) : 0; + return lastExplicitSettings != 0 ? new XmlElement (*lastExplicitSettings) : 0; } void AudioDeviceManager::scanDevicesIfNeeded() { - if (listNeedsScanning) - { - listNeedsScanning = false; + if (listNeedsScanning) + { + listNeedsScanning = false; - createDeviceTypesIfNeeded(); + createDeviceTypesIfNeeded(); - for (int i = availableDeviceTypes.size(); --i >= 0;) - availableDeviceTypes.getUnchecked(i)->scanForDevices(); - } + for (int i = availableDeviceTypes.size(); --i >= 0;) + availableDeviceTypes.getUnchecked(i)->scanForDevices(); + } } AudioIODeviceType* AudioDeviceManager::findType (const String& inputName, const String& outputName) { - scanDevicesIfNeeded(); + scanDevicesIfNeeded(); - for (int i = availableDeviceTypes.size(); --i >= 0;) - { - AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(i); + for (int i = availableDeviceTypes.size(); --i >= 0;) + { + AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(i); - if ((inputName.isNotEmpty() && type->getDeviceNames (true).contains (inputName, true)) - || (outputName.isNotEmpty() && type->getDeviceNames (false).contains (outputName, true))) - { - return type; - } - } + if ((inputName.isNotEmpty() && type->getDeviceNames (true).contains (inputName, true)) + || (outputName.isNotEmpty() && type->getDeviceNames (false).contains (outputName, true))) + { + return type; + } + } - return 0; + return 0; } void AudioDeviceManager::getAudioDeviceSetup (AudioDeviceSetup& setup) { - setup = currentSetup; + setup = currentSetup; } void AudioDeviceManager::deleteCurrentDevice() { - currentAudioDevice = 0; - currentSetup.inputDeviceName = String::empty; - currentSetup.outputDeviceName = String::empty; + currentAudioDevice = 0; + currentSetup.inputDeviceName = String::empty; + currentSetup.outputDeviceName = String::empty; } void AudioDeviceManager::setCurrentAudioDeviceType (const String& type, - const bool treatAsChosenDevice) + const bool treatAsChosenDevice) { - for (int i = 0; i < availableDeviceTypes.size(); ++i) - { - if (availableDeviceTypes.getUnchecked(i)->getTypeName() == type - && currentDeviceType != type) - { - currentDeviceType = type; + for (int i = 0; i < availableDeviceTypes.size(); ++i) + { + if (availableDeviceTypes.getUnchecked(i)->getTypeName() == type + && currentDeviceType != type) + { + currentDeviceType = type; - AudioDeviceSetup s (*lastDeviceTypeConfigs.getUnchecked(i)); - insertDefaultDeviceNames (s); + AudioDeviceSetup s (*lastDeviceTypeConfigs.getUnchecked(i)); + insertDefaultDeviceNames (s); - setAudioDeviceSetup (s, treatAsChosenDevice); + setAudioDeviceSetup (s, treatAsChosenDevice); - sendChangeMessage (this); - break; - } - } + sendChangeMessage (this); + break; + } + } } AudioIODeviceType* AudioDeviceManager::getCurrentDeviceTypeObject() const { - for (int i = 0; i < availableDeviceTypes.size(); ++i) - if (availableDeviceTypes[i]->getTypeName() == currentDeviceType) - return availableDeviceTypes[i]; + for (int i = 0; i < availableDeviceTypes.size(); ++i) + if (availableDeviceTypes[i]->getTypeName() == currentDeviceType) + return availableDeviceTypes[i]; - return availableDeviceTypes[0]; + return availableDeviceTypes[0]; } const String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup, - const bool treatAsChosenDevice) + const bool treatAsChosenDevice) { - jassert (&newSetup != ¤tSetup); // this will have no effect + jassert (&newSetup != ¤tSetup); // this will have no effect - if (newSetup == currentSetup && currentAudioDevice != 0) - return String::empty; + if (newSetup == currentSetup && currentAudioDevice != 0) + return String::empty; - if (! (newSetup == currentSetup)) - sendChangeMessage (this); + if (! (newSetup == currentSetup)) + sendChangeMessage (this); - stopDevice(); + stopDevice(); - const String newInputDeviceName (numInputChansNeeded == 0 ? String::empty : newSetup.inputDeviceName); - const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName); + const String newInputDeviceName (numInputChansNeeded == 0 ? String::empty : newSetup.inputDeviceName); + const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName); - String error; - AudioIODeviceType* type = getCurrentDeviceTypeObject(); + String error; + AudioIODeviceType* type = getCurrentDeviceTypeObject(); - if (type == 0 || (newInputDeviceName.isEmpty() && newOutputDeviceName.isEmpty())) - { - deleteCurrentDevice(); + if (type == 0 || (newInputDeviceName.isEmpty() && newOutputDeviceName.isEmpty())) + { + deleteCurrentDevice(); - if (treatAsChosenDevice) - updateXml(); + if (treatAsChosenDevice) + updateXml(); - return String::empty; - } + return String::empty; + } - if (currentSetup.inputDeviceName != newInputDeviceName - || currentSetup.outputDeviceName != newOutputDeviceName - || currentAudioDevice == 0) - { - deleteCurrentDevice(); - scanDevicesIfNeeded(); + if (currentSetup.inputDeviceName != newInputDeviceName + || currentSetup.outputDeviceName != newOutputDeviceName + || currentAudioDevice == 0) + { + deleteCurrentDevice(); + scanDevicesIfNeeded(); - if (newOutputDeviceName.isNotEmpty() - && ! type->getDeviceNames (false).contains (newOutputDeviceName)) - { - return "No such device: " + newOutputDeviceName; - } + if (newOutputDeviceName.isNotEmpty() + && ! type->getDeviceNames (false).contains (newOutputDeviceName)) + { + return "No such device: " + newOutputDeviceName; + } - if (newInputDeviceName.isNotEmpty() - && ! type->getDeviceNames (true).contains (newInputDeviceName)) - { - return "No such device: " + newInputDeviceName; - } + if (newInputDeviceName.isNotEmpty() + && ! type->getDeviceNames (true).contains (newInputDeviceName)) + { + return "No such device: " + newInputDeviceName; + } - currentAudioDevice = type->createDevice (newOutputDeviceName, newInputDeviceName); + currentAudioDevice = type->createDevice (newOutputDeviceName, newInputDeviceName); - if (currentAudioDevice == 0) - error = "Can't open the audio device!\n\nThis may be because another application is currently using the same device - if so, you should close any other applications and try again!"; - else - error = currentAudioDevice->getLastError(); + if (currentAudioDevice == 0) + error = "Can't open the audio device!\n\nThis may be because another application is currently using the same device - if so, you should close any other applications and try again!"; + else + error = currentAudioDevice->getLastError(); - if (error.isNotEmpty()) - { - deleteCurrentDevice(); - return error; - } + if (error.isNotEmpty()) + { + deleteCurrentDevice(); + return error; + } - if (newSetup.useDefaultInputChannels) - { - inputChannels.clear(); - inputChannels.setRange (0, numInputChansNeeded, true); - } + if (newSetup.useDefaultInputChannels) + { + inputChannels.clear(); + inputChannels.setRange (0, numInputChansNeeded, true); + } - if (newSetup.useDefaultOutputChannels) - { - outputChannels.clear(); - outputChannels.setRange (0, numOutputChansNeeded, true); - } + if (newSetup.useDefaultOutputChannels) + { + outputChannels.clear(); + outputChannels.setRange (0, numOutputChansNeeded, true); + } - if (newInputDeviceName.isEmpty()) - inputChannels.clear(); + if (newInputDeviceName.isEmpty()) + inputChannels.clear(); - if (newOutputDeviceName.isEmpty()) - outputChannels.clear(); - } + if (newOutputDeviceName.isEmpty()) + outputChannels.clear(); + } - if (! newSetup.useDefaultInputChannels) - inputChannels = newSetup.inputChannels; + if (! newSetup.useDefaultInputChannels) + inputChannels = newSetup.inputChannels; - if (! newSetup.useDefaultOutputChannels) - outputChannels = newSetup.outputChannels; + if (! newSetup.useDefaultOutputChannels) + outputChannels = newSetup.outputChannels; - currentSetup = newSetup; + currentSetup = newSetup; - currentSetup.sampleRate = chooseBestSampleRate (newSetup.sampleRate); + currentSetup.sampleRate = chooseBestSampleRate (newSetup.sampleRate); - error = currentAudioDevice->open (inputChannels, - outputChannels, - currentSetup.sampleRate, - currentSetup.bufferSize); + error = currentAudioDevice->open (inputChannels, + outputChannels, + currentSetup.sampleRate, + currentSetup.bufferSize); - if (error.isEmpty()) - { - currentDeviceType = currentAudioDevice->getTypeName(); + if (error.isEmpty()) + { + currentDeviceType = currentAudioDevice->getTypeName(); - currentAudioDevice->start (&callbackHandler); + currentAudioDevice->start (&callbackHandler); - currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate(); - currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples(); - currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels(); - currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels(); + currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate(); + currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples(); + currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels(); + currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels(); - for (int i = 0; i < availableDeviceTypes.size(); ++i) - if (availableDeviceTypes.getUnchecked (i)->getTypeName() == currentDeviceType) - *(lastDeviceTypeConfigs.getUnchecked (i)) = currentSetup; + for (int i = 0; i < availableDeviceTypes.size(); ++i) + if (availableDeviceTypes.getUnchecked (i)->getTypeName() == currentDeviceType) + *(lastDeviceTypeConfigs.getUnchecked (i)) = currentSetup; - if (treatAsChosenDevice) - updateXml(); - } - else - { - deleteCurrentDevice(); - } + if (treatAsChosenDevice) + updateXml(); + } + else + { + deleteCurrentDevice(); + } - return error; + return error; } double AudioDeviceManager::chooseBestSampleRate (double rate) const { - jassert (currentAudioDevice != 0); + jassert (currentAudioDevice != 0); - if (rate > 0) - { - bool ok = false; + if (rate > 0) + { + bool ok = false; - for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) - { - const double sr = currentAudioDevice->getSampleRate (i); + for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) + { + const double sr = currentAudioDevice->getSampleRate (i); - if (sr == rate) - ok = true; - } + if (sr == rate) + ok = true; + } - if (! ok) - rate = 0; - } + if (! ok) + rate = 0; + } - if (rate == 0) - { - double lowestAbove44 = 0.0; + if (rate == 0) + { + double lowestAbove44 = 0.0; - for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) - { - const double sr = currentAudioDevice->getSampleRate (i); + for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;) + { + const double sr = currentAudioDevice->getSampleRate (i); - if (sr >= 44100.0 && (lowestAbove44 == 0 || sr < lowestAbove44)) - lowestAbove44 = sr; - } + if (sr >= 44100.0 && (lowestAbove44 == 0 || sr < lowestAbove44)) + lowestAbove44 = sr; + } - if (lowestAbove44 == 0.0) - rate = currentAudioDevice->getSampleRate (0); - else - rate = lowestAbove44; - } + if (lowestAbove44 == 0.0) + rate = currentAudioDevice->getSampleRate (0); + else + rate = lowestAbove44; + } - return rate; + return rate; } void AudioDeviceManager::stopDevice() { - if (currentAudioDevice != 0) - currentAudioDevice->stop(); + if (currentAudioDevice != 0) + currentAudioDevice->stop(); - testSound = 0; + testSound = 0; } void AudioDeviceManager::closeAudioDevice() { - stopDevice(); - currentAudioDevice = 0; + stopDevice(); + currentAudioDevice = 0; } void AudioDeviceManager::restartLastAudioDevice() { - if (currentAudioDevice == 0) - { - if (currentSetup.inputDeviceName.isEmpty() - && currentSetup.outputDeviceName.isEmpty()) - { - // This method will only reload the last device that was running - // before closeAudioDevice() was called - you need to actually open - // one first, with setAudioDevice(). - jassertfalse - return; - } + if (currentAudioDevice == 0) + { + if (currentSetup.inputDeviceName.isEmpty() + && currentSetup.outputDeviceName.isEmpty()) + { + // This method will only reload the last device that was running + // before closeAudioDevice() was called - you need to actually open + // one first, with setAudioDevice(). + jassertfalse + return; + } - AudioDeviceSetup s (currentSetup); - setAudioDeviceSetup (s, false); - } + AudioDeviceSetup s (currentSetup); + setAudioDeviceSetup (s, false); + } } void AudioDeviceManager::updateXml() { - lastExplicitSettings = new XmlElement (T("DEVICESETUP")); + lastExplicitSettings = new XmlElement (T("DEVICESETUP")); - lastExplicitSettings->setAttribute (T("deviceType"), currentDeviceType); - lastExplicitSettings->setAttribute (T("audioOutputDeviceName"), currentSetup.outputDeviceName); - lastExplicitSettings->setAttribute (T("audioInputDeviceName"), currentSetup.inputDeviceName); + lastExplicitSettings->setAttribute (T("deviceType"), currentDeviceType); + lastExplicitSettings->setAttribute (T("audioOutputDeviceName"), currentSetup.outputDeviceName); + lastExplicitSettings->setAttribute (T("audioInputDeviceName"), currentSetup.inputDeviceName); - if (currentAudioDevice != 0) - { - lastExplicitSettings->setAttribute (T("audioDeviceRate"), currentAudioDevice->getCurrentSampleRate()); + if (currentAudioDevice != 0) + { + lastExplicitSettings->setAttribute (T("audioDeviceRate"), currentAudioDevice->getCurrentSampleRate()); - if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples()) - lastExplicitSettings->setAttribute (T("audioDeviceBufferSize"), currentAudioDevice->getCurrentBufferSizeSamples()); + if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples()) + lastExplicitSettings->setAttribute (T("audioDeviceBufferSize"), currentAudioDevice->getCurrentBufferSizeSamples()); - if (! currentSetup.useDefaultInputChannels) - lastExplicitSettings->setAttribute (T("audioDeviceInChans"), currentSetup.inputChannels.toString (2)); + if (! currentSetup.useDefaultInputChannels) + lastExplicitSettings->setAttribute (T("audioDeviceInChans"), currentSetup.inputChannels.toString (2)); - if (! currentSetup.useDefaultOutputChannels) - lastExplicitSettings->setAttribute (T("audioDeviceOutChans"), currentSetup.outputChannels.toString (2)); - } + if (! currentSetup.useDefaultOutputChannels) + lastExplicitSettings->setAttribute (T("audioDeviceOutChans"), currentSetup.outputChannels.toString (2)); + } - for (int i = 0; i < enabledMidiInputs.size(); ++i) - { - XmlElement* const m = new XmlElement (T("MIDIINPUT")); - m->setAttribute (T("name"), enabledMidiInputs[i]->getName()); + for (int i = 0; i < enabledMidiInputs.size(); ++i) + { + XmlElement* const m = new XmlElement (T("MIDIINPUT")); + m->setAttribute (T("name"), enabledMidiInputs[i]->getName()); - lastExplicitSettings->addChildElement (m); - } + lastExplicitSettings->addChildElement (m); + } - if (midiInsFromXml.size() > 0) - { - // Add any midi devices that have been enabled before, but which aren't currently - // open because the device has been disconnected. - const StringArray availableMidiDevices (MidiInput::getDevices()); + if (midiInsFromXml.size() > 0) + { + // Add any midi devices that have been enabled before, but which aren't currently + // open because the device has been disconnected. + const StringArray availableMidiDevices (MidiInput::getDevices()); - for (int i = 0; i < midiInsFromXml.size(); ++i) - { - if (! availableMidiDevices.contains (midiInsFromXml[i], true)) - { - XmlElement* const m = new XmlElement (T("MIDIINPUT")); - m->setAttribute (T("name"), midiInsFromXml[i]); + for (int i = 0; i < midiInsFromXml.size(); ++i) + { + if (! availableMidiDevices.contains (midiInsFromXml[i], true)) + { + XmlElement* const m = new XmlElement (T("MIDIINPUT")); + m->setAttribute (T("name"), midiInsFromXml[i]); - lastExplicitSettings->addChildElement (m); - } - } - } + lastExplicitSettings->addChildElement (m); + } + } + } - if (defaultMidiOutputName.isNotEmpty()) - lastExplicitSettings->setAttribute (T("defaultMidiOutput"), defaultMidiOutputName); + if (defaultMidiOutputName.isNotEmpty()) + lastExplicitSettings->setAttribute (T("defaultMidiOutput"), defaultMidiOutputName); } void AudioDeviceManager::addAudioCallback (AudioIODeviceCallback* newCallback) { - { - const ScopedLock sl (audioCallbackLock); - if (callbacks.contains (newCallback)) - return; - } + { + const ScopedLock sl (audioCallbackLock); + if (callbacks.contains (newCallback)) + return; + } - if (currentAudioDevice != 0 && newCallback != 0) - newCallback->audioDeviceAboutToStart (currentAudioDevice); + if (currentAudioDevice != 0 && newCallback != 0) + newCallback->audioDeviceAboutToStart (currentAudioDevice); - const ScopedLock sl (audioCallbackLock); - callbacks.add (newCallback); + const ScopedLock sl (audioCallbackLock); + callbacks.add (newCallback); } void AudioDeviceManager::removeAudioCallback (AudioIODeviceCallback* callback) { - if (callback != 0) - { - bool needsDeinitialising = currentAudioDevice != 0; + if (callback != 0) + { + bool needsDeinitialising = currentAudioDevice != 0; - { - const ScopedLock sl (audioCallbackLock); + { + const ScopedLock sl (audioCallbackLock); - needsDeinitialising = needsDeinitialising && callbacks.contains (callback); - callbacks.removeValue (callback); - } + needsDeinitialising = needsDeinitialising && callbacks.contains (callback); + callbacks.removeValue (callback); + } - if (needsDeinitialising) - callback->audioDeviceStopped(); - } + if (needsDeinitialising) + callback->audioDeviceStopped(); + } } void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelData, - int numInputChannels, - float** outputChannelData, - int numOutputChannels, - int numSamples) + int numInputChannels, + float** outputChannelData, + int numOutputChannels, + int numSamples) { - const ScopedLock sl (audioCallbackLock); + const ScopedLock sl (audioCallbackLock); - if (inputLevelMeasurementEnabledCount > 0) - { - for (int j = 0; j < numSamples; ++j) - { - float s = 0; + if (inputLevelMeasurementEnabledCount > 0) + { + for (int j = 0; j < numSamples; ++j) + { + float s = 0; - for (int i = 0; i < numInputChannels; ++i) - s += fabsf (inputChannelData[i][j]); + for (int i = 0; i < numInputChannels; ++i) + s += fabsf (inputChannelData[i][j]); - s /= numInputChannels; + s /= numInputChannels; - const double decayFactor = 0.99992; + const double decayFactor = 0.99992; - if (s > inputLevel) - inputLevel = s; - else if (inputLevel > 0.001f) - inputLevel *= decayFactor; - else - inputLevel = 0; - } - } + if (s > inputLevel) + inputLevel = s; + else if (inputLevel > 0.001f) + inputLevel *= decayFactor; + else + inputLevel = 0; + } + } - if (callbacks.size() > 0) - { - const double callbackStartTime = Time::getMillisecondCounterHiRes(); + if (callbacks.size() > 0) + { + const double callbackStartTime = Time::getMillisecondCounterHiRes(); - tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true); + tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true); - callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels, - outputChannelData, numOutputChannels, numSamples); + callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels, + outputChannelData, numOutputChannels, numSamples); - float** const tempChans = tempBuffer.getArrayOfChannels(); + float** const tempChans = tempBuffer.getArrayOfChannels(); - for (int i = callbacks.size(); --i > 0;) - { - callbacks.getUnchecked(i)->audioDeviceIOCallback (inputChannelData, numInputChannels, - tempChans, numOutputChannels, numSamples); + for (int i = callbacks.size(); --i > 0;) + { + callbacks.getUnchecked(i)->audioDeviceIOCallback (inputChannelData, numInputChannels, + tempChans, numOutputChannels, numSamples); - for (int chan = 0; chan < numOutputChannels; ++chan) - { - const float* const src = tempChans [chan]; - float* const dst = outputChannelData [chan]; + for (int chan = 0; chan < numOutputChannels; ++chan) + { + const float* const src = tempChans [chan]; + float* const dst = outputChannelData [chan]; - if (src != 0 && dst != 0) - for (int j = 0; j < numSamples; ++j) - dst[j] += src[j]; - } - } + if (src != 0 && dst != 0) + for (int j = 0; j < numSamples; ++j) + dst[j] += src[j]; + } + } - const double msTaken = Time::getMillisecondCounterHiRes() - callbackStartTime; - const double filterAmount = 0.2; - cpuUsageMs += filterAmount * (msTaken - cpuUsageMs); - } - else - { - for (int i = 0; i < numOutputChannels; ++i) - zeromem (outputChannelData[i], sizeof (float) * numSamples); - } + const double msTaken = Time::getMillisecondCounterHiRes() - callbackStartTime; + const double filterAmount = 0.2; + cpuUsageMs += filterAmount * (msTaken - cpuUsageMs); + } + else + { + for (int i = 0; i < numOutputChannels; ++i) + zeromem (outputChannelData[i], sizeof (float) * numSamples); + } - if (testSound != 0) - { - const int numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition); - const float* const src = testSound->getSampleData (0, testSoundPosition); + if (testSound != 0) + { + const int numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition); + const float* const src = testSound->getSampleData (0, testSoundPosition); - for (int i = 0; i < numOutputChannels; ++i) - for (int j = 0; j < numSamps; ++j) - outputChannelData [i][j] += src[j]; + for (int i = 0; i < numOutputChannels; ++i) + for (int j = 0; j < numSamps; ++j) + outputChannelData [i][j] += src[j]; - testSoundPosition += numSamps; - if (testSoundPosition >= testSound->getNumSamples()) - testSound = 0; - } + testSoundPosition += numSamps; + if (testSoundPosition >= testSound->getNumSamples()) + testSound = 0; + } } void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device) { - cpuUsageMs = 0; + cpuUsageMs = 0; - const double sampleRate = device->getCurrentSampleRate(); - const int blockSize = device->getCurrentBufferSizeSamples(); + const double sampleRate = device->getCurrentSampleRate(); + const int blockSize = device->getCurrentBufferSizeSamples(); - if (sampleRate > 0.0 && blockSize > 0) - { - const double msPerBlock = 1000.0 * blockSize / sampleRate; - timeToCpuScale = (msPerBlock > 0.0) ? (1.0 / msPerBlock) : 0.0; - } + if (sampleRate > 0.0 && blockSize > 0) + { + const double msPerBlock = 1000.0 * blockSize / sampleRate; + timeToCpuScale = (msPerBlock > 0.0) ? (1.0 / msPerBlock) : 0.0; + } - { - const ScopedLock sl (audioCallbackLock); - for (int i = callbacks.size(); --i >= 0;) - callbacks.getUnchecked(i)->audioDeviceAboutToStart (device); - } + { + const ScopedLock sl (audioCallbackLock); + for (int i = callbacks.size(); --i >= 0;) + callbacks.getUnchecked(i)->audioDeviceAboutToStart (device); + } - sendChangeMessage (this); + sendChangeMessage (this); } void AudioDeviceManager::audioDeviceStoppedInt() { - cpuUsageMs = 0; - timeToCpuScale = 0; - sendChangeMessage (this); + cpuUsageMs = 0; + timeToCpuScale = 0; + sendChangeMessage (this); - const ScopedLock sl (audioCallbackLock); - for (int i = callbacks.size(); --i >= 0;) - callbacks.getUnchecked(i)->audioDeviceStopped(); + const ScopedLock sl (audioCallbackLock); + for (int i = callbacks.size(); --i >= 0;) + callbacks.getUnchecked(i)->audioDeviceStopped(); } double AudioDeviceManager::getCpuUsage() const { - return jlimit (0.0, 1.0, timeToCpuScale * cpuUsageMs); + return jlimit (0.0, 1.0, timeToCpuScale * cpuUsageMs); } void AudioDeviceManager::setMidiInputEnabled (const String& name, - const bool enabled) + const bool enabled) { - if (enabled != isMidiInputEnabled (name)) - { - if (enabled) - { - const int index = MidiInput::getDevices().indexOf (name); + if (enabled != isMidiInputEnabled (name)) + { + if (enabled) + { + const int index = MidiInput::getDevices().indexOf (name); - if (index >= 0) - { - MidiInput* const min = MidiInput::openDevice (index, &callbackHandler); + if (index >= 0) + { + MidiInput* const min = MidiInput::openDevice (index, &callbackHandler); - if (min != 0) - { - enabledMidiInputs.add (min); - min->start(); - } - } - } - else - { - for (int i = enabledMidiInputs.size(); --i >= 0;) - if (enabledMidiInputs[i]->getName() == name) - enabledMidiInputs.remove (i); - } + if (min != 0) + { + enabledMidiInputs.add (min); + min->start(); + } + } + } + else + { + for (int i = enabledMidiInputs.size(); --i >= 0;) + if (enabledMidiInputs[i]->getName() == name) + enabledMidiInputs.remove (i); + } - updateXml(); - sendChangeMessage (this); - } + updateXml(); + sendChangeMessage (this); + } } bool AudioDeviceManager::isMidiInputEnabled (const String& name) const { - for (int i = enabledMidiInputs.size(); --i >= 0;) - if (enabledMidiInputs[i]->getName() == name) - return true; + for (int i = enabledMidiInputs.size(); --i >= 0;) + if (enabledMidiInputs[i]->getName() == name) + return true; - return false; + return false; } void AudioDeviceManager::addMidiInputCallback (const String& name, - MidiInputCallback* callback) + MidiInputCallback* callback) { - removeMidiInputCallback (name, callback); + removeMidiInputCallback (name, callback); - if (name.isEmpty()) - { - midiCallbacks.add (callback); - midiCallbackDevices.add (0); - } - else - { - for (int i = enabledMidiInputs.size(); --i >= 0;) - { - if (enabledMidiInputs[i]->getName() == name) - { - const ScopedLock sl (midiCallbackLock); - midiCallbacks.add (callback); - midiCallbackDevices.add (enabledMidiInputs[i]); - break; - } - } - } + if (name.isEmpty()) + { + midiCallbacks.add (callback); + midiCallbackDevices.add (0); + } + else + { + for (int i = enabledMidiInputs.size(); --i >= 0;) + { + if (enabledMidiInputs[i]->getName() == name) + { + const ScopedLock sl (midiCallbackLock); + midiCallbacks.add (callback); + midiCallbackDevices.add (enabledMidiInputs[i]); + break; + } + } + } } void AudioDeviceManager::removeMidiInputCallback (const String& name, - MidiInputCallback* /*callback*/) + MidiInputCallback* /*callback*/) { - const ScopedLock sl (midiCallbackLock); + const ScopedLock sl (midiCallbackLock); - for (int i = midiCallbacks.size(); --i >= 0;) - { - String devName; + for (int i = midiCallbacks.size(); --i >= 0;) + { + String devName; - if (midiCallbackDevices.getUnchecked(i) != 0) - devName = midiCallbackDevices.getUnchecked(i)->getName(); + if (midiCallbackDevices.getUnchecked(i) != 0) + devName = midiCallbackDevices.getUnchecked(i)->getName(); - if (devName == name) - { - midiCallbacks.remove (i); - midiCallbackDevices.remove (i); - } - } + if (devName == name) + { + midiCallbacks.remove (i); + midiCallbackDevices.remove (i); + } + } } void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source, - const MidiMessage& message) + const MidiMessage& message) { - if (! message.isActiveSense()) - { - const bool isDefaultSource = (source == 0 || source == enabledMidiInputs.getFirst()); + if (! message.isActiveSense()) + { + const bool isDefaultSource = (source == 0 || source == enabledMidiInputs.getFirst()); - const ScopedLock sl (midiCallbackLock); + const ScopedLock sl (midiCallbackLock); - for (int i = midiCallbackDevices.size(); --i >= 0;) - { - MidiInput* const md = midiCallbackDevices.getUnchecked(i); + for (int i = midiCallbackDevices.size(); --i >= 0;) + { + MidiInput* const md = midiCallbackDevices.getUnchecked(i); - if (md == source || (md == 0 && isDefaultSource)) - midiCallbacks.getUnchecked(i)->handleIncomingMidiMessage (source, message); - } - } + if (md == source || (md == 0 && isDefaultSource)) + midiCallbacks.getUnchecked(i)->handleIncomingMidiMessage (source, message); + } + } } void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName) { - if (defaultMidiOutputName != deviceName) - { - SortedSet oldCallbacks; + if (defaultMidiOutputName != deviceName) + { + SortedSet oldCallbacks; - { - const ScopedLock sl (audioCallbackLock); - oldCallbacks = callbacks; - callbacks.clear(); - } + { + const ScopedLock sl (audioCallbackLock); + oldCallbacks = callbacks; + callbacks.clear(); + } - if (currentAudioDevice != 0) - for (int i = oldCallbacks.size(); --i >= 0;) - oldCallbacks.getUnchecked(i)->audioDeviceStopped(); + if (currentAudioDevice != 0) + for (int i = oldCallbacks.size(); --i >= 0;) + oldCallbacks.getUnchecked(i)->audioDeviceStopped(); - defaultMidiOutput = 0; - defaultMidiOutputName = deviceName; + defaultMidiOutput = 0; + defaultMidiOutputName = deviceName; - if (deviceName.isNotEmpty()) - defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName)); + if (deviceName.isNotEmpty()) + defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName)); - if (currentAudioDevice != 0) - for (int i = oldCallbacks.size(); --i >= 0;) - oldCallbacks.getUnchecked(i)->audioDeviceAboutToStart (currentAudioDevice); + if (currentAudioDevice != 0) + for (int i = oldCallbacks.size(); --i >= 0;) + oldCallbacks.getUnchecked(i)->audioDeviceAboutToStart (currentAudioDevice); - { - const ScopedLock sl (audioCallbackLock); - callbacks = oldCallbacks; - } + { + const ScopedLock sl (audioCallbackLock); + callbacks = oldCallbacks; + } - updateXml(); - sendChangeMessage (this); - } + updateXml(); + sendChangeMessage (this); + } } void AudioDeviceManager::CallbackHandler::audioDeviceIOCallback (const float** inputChannelData, - int numInputChannels, - float** outputChannelData, - int numOutputChannels, - int numSamples) + int numInputChannels, + float** outputChannelData, + int numOutputChannels, + int numSamples) { - owner->audioDeviceIOCallbackInt (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples); + owner->audioDeviceIOCallbackInt (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples); } void AudioDeviceManager::CallbackHandler::audioDeviceAboutToStart (AudioIODevice* device) { - owner->audioDeviceAboutToStartInt (device); + owner->audioDeviceAboutToStartInt (device); } void AudioDeviceManager::CallbackHandler::audioDeviceStopped() { - owner->audioDeviceStoppedInt(); + owner->audioDeviceStoppedInt(); } void AudioDeviceManager::CallbackHandler::handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message) { - owner->handleIncomingMidiMessageInt (source, message); + owner->handleIncomingMidiMessageInt (source, message); } void AudioDeviceManager::playTestSound() { - { - audioCallbackLock.enter(); - ScopedPointer oldSound (testSound); - audioCallbackLock.exit(); - } + { + audioCallbackLock.enter(); + ScopedPointer oldSound (testSound); + audioCallbackLock.exit(); + } - testSoundPosition = 0; + testSoundPosition = 0; - if (currentAudioDevice != 0) - { - const double sampleRate = currentAudioDevice->getCurrentSampleRate(); - const int soundLength = (int) sampleRate; + if (currentAudioDevice != 0) + { + const double sampleRate = currentAudioDevice->getCurrentSampleRate(); + const int soundLength = (int) sampleRate; - AudioSampleBuffer* const newSound = new AudioSampleBuffer (1, soundLength); - float* samples = newSound->getSampleData (0); + AudioSampleBuffer* const newSound = new AudioSampleBuffer (1, soundLength); + float* samples = newSound->getSampleData (0); - const double frequency = MidiMessage::getMidiNoteInHertz (80); - const float amplitude = 0.5f; + const double frequency = MidiMessage::getMidiNoteInHertz (80); + const float amplitude = 0.5f; - const double phasePerSample = double_Pi * 2.0 / (sampleRate / frequency); + const double phasePerSample = double_Pi * 2.0 / (sampleRate / frequency); - for (int i = 0; i < soundLength; ++i) - samples[i] = amplitude * (float) sin (i * phasePerSample); + for (int i = 0; i < soundLength; ++i) + samples[i] = amplitude * (float) sin (i * phasePerSample); - newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f); - newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f); + newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f); + newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f); - const ScopedLock sl (audioCallbackLock); - testSound = newSound; - } + const ScopedLock sl (audioCallbackLock); + testSound = newSound; + } } void AudioDeviceManager::enableInputLevelMeasurement (const bool enableMeasurement) { - const ScopedLock sl (audioCallbackLock); + const ScopedLock sl (audioCallbackLock); - if (enableMeasurement) - ++inputLevelMeasurementEnabledCount; - else - --inputLevelMeasurementEnabledCount; + if (enableMeasurement) + ++inputLevelMeasurementEnabledCount; + else + --inputLevelMeasurementEnabledCount; - inputLevel = 0; + inputLevel = 0; } double AudioDeviceManager::getCurrentInputLevel() const { - jassert (inputLevelMeasurementEnabledCount > 0); // you need to call enableInputLevelMeasurement() before using this! - return inputLevel; + jassert (inputLevelMeasurementEnabledCount > 0); // you need to call enableInputLevelMeasurement() before using this! + return inputLevel; } END_JUCE_NAMESPACE @@ -25201,8 +24942,8 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioIODevice::AudioIODevice (const String& deviceName, const String& typeName_) - : name (deviceName), - typeName (typeName_) + : name (deviceName), + typeName (typeName_) { } @@ -25212,14 +24953,14 @@ AudioIODevice::~AudioIODevice() bool AudioIODevice::hasControlPanel() const { - return false; + return false; } bool AudioIODevice::showControlPanel() { - jassertfalse // this should only be called for devices which return true from - // their hasControlPanel() method. - return false; + jassertfalse // this should only be called for devices which return true from + // their hasControlPanel() method. + return false; } END_JUCE_NAMESPACE @@ -25230,7 +24971,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioIODeviceType::AudioIODeviceType (const tchar* const name) - : typeName (name) + : typeName (name) { } @@ -25246,138 +24987,138 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MidiOutput::MidiOutput() throw() - : Thread ("midi out"), - internal (0), - firstMessage (0) + : Thread ("midi out"), + internal (0), + firstMessage (0) { } MidiOutput::PendingMessage::PendingMessage (const uint8* const data, - const int len, - const double sampleNumber) throw() - : message (data, len, sampleNumber) + const int len, + const double sampleNumber) throw() + : message (data, len, sampleNumber) { } void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer, - const double millisecondCounterToStartAt, - double samplesPerSecondForBuffer) throw() + const double millisecondCounterToStartAt, + double samplesPerSecondForBuffer) throw() { - // You've got to call startBackgroundThread() for this to actually work.. - jassert (isThreadRunning()); + // You've got to call startBackgroundThread() for this to actually work.. + jassert (isThreadRunning()); - // this needs to be a value in the future - RTFM for this method! - jassert (millisecondCounterToStartAt > 0); + // this needs to be a value in the future - RTFM for this method! + jassert (millisecondCounterToStartAt > 0); - const double timeScaleFactor = 1000.0 / samplesPerSecondForBuffer; + const double timeScaleFactor = 1000.0 / samplesPerSecondForBuffer; - MidiBuffer::Iterator i (buffer); + MidiBuffer::Iterator i (buffer); - const uint8* data; - int len, time; + const uint8* data; + int len, time; - while (i.getNextEvent (data, len, time)) - { - const double eventTime = millisecondCounterToStartAt + timeScaleFactor * time; + while (i.getNextEvent (data, len, time)) + { + const double eventTime = millisecondCounterToStartAt + timeScaleFactor * time; - PendingMessage* const m - = new PendingMessage (data, len, eventTime); + PendingMessage* const m + = new PendingMessage (data, len, eventTime); - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (firstMessage == 0 || firstMessage->message.getTimeStamp() > eventTime) - { - m->next = firstMessage; - firstMessage = m; - } - else - { - PendingMessage* mm = firstMessage; + if (firstMessage == 0 || firstMessage->message.getTimeStamp() > eventTime) + { + m->next = firstMessage; + firstMessage = m; + } + else + { + PendingMessage* mm = firstMessage; - while (mm->next != 0 && mm->next->message.getTimeStamp() <= eventTime) - mm = mm->next; + while (mm->next != 0 && mm->next->message.getTimeStamp() <= eventTime) + mm = mm->next; - m->next = mm->next; - mm->next = m; - } - } + m->next = mm->next; + mm->next = m; + } + } - notify(); + notify(); } void MidiOutput::clearAllPendingMessages() throw() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - while (firstMessage != 0) - { - PendingMessage* const m = firstMessage; - firstMessage = firstMessage->next; - delete m; - } + while (firstMessage != 0) + { + PendingMessage* const m = firstMessage; + firstMessage = firstMessage->next; + delete m; + } } void MidiOutput::startBackgroundThread() throw() { - startThread (9); + startThread (9); } void MidiOutput::stopBackgroundThread() throw() { - stopThread (5000); + stopThread (5000); } void MidiOutput::run() { - while (! threadShouldExit()) - { - uint32 now = Time::getMillisecondCounter(); - uint32 eventTime = 0; - uint32 timeToWait = 500; + while (! threadShouldExit()) + { + uint32 now = Time::getMillisecondCounter(); + uint32 eventTime = 0; + uint32 timeToWait = 500; - lock.enter(); - PendingMessage* message = firstMessage; + lock.enter(); + PendingMessage* message = firstMessage; - if (message != 0) - { - eventTime = roundDoubleToInt (message->message.getTimeStamp()); + if (message != 0) + { + eventTime = roundToInt (message->message.getTimeStamp()); - if (eventTime > now + 20) - { - timeToWait = jmax (10, eventTime - now - 100); - message = 0; - } - else - { - firstMessage = message->next; - } - } + if (eventTime > now + 20) + { + timeToWait = eventTime - (now + 20); + message = 0; + } + else + { + firstMessage = message->next; + } + } - lock.exit(); + lock.exit(); - if (message != 0) - { - if (eventTime > now) - { - Time::waitForMillisecondCounter (eventTime); + if (message != 0) + { + if (eventTime > now) + { + Time::waitForMillisecondCounter (eventTime); - if (threadShouldExit()) - break; - } + if (threadShouldExit()) + break; + } - if (eventTime > now - 200) - sendMessageNow (message->message); + if (eventTime > now - 200) + sendMessageNow (message->message); - delete message; - } - else - { - jassert (timeToWait < 1000 * 30); - wait (timeToWait); - } - } + delete message; + } + else + { + jassert (timeToWait < 1000 * 30); + wait (timeToWait); + } + } - clearAllPendingMessages(); + clearAllPendingMessages(); } END_JUCE_NAMESPACE @@ -25389,498 +25130,498 @@ BEGIN_JUCE_NAMESPACE void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { - const double maxVal = (double) 0x7fff; - char* intData = (char*) dest; + const double maxVal = (double) 0x7fff; + char* intData = (char*) dest; - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - *(uint16*)intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; + if (dest != (void*) source || destBytesPerSample <= 4) + { + for (int i = 0; i < numSamples; ++i) + { + *(uint16*)intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + intData += destBytesPerSample; + } + } + else + { + intData += destBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - *(uint16*)intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= destBytesPerSample; + *(uint16*)intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + } + } } void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { - const double maxVal = (double) 0x7fff; - char* intData = (char*) dest; + const double maxVal = (double) 0x7fff; + char* intData = (char*) dest; - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - *(uint16*) intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; + if (dest != (void*) source || destBytesPerSample <= 4) + { + for (int i = 0; i < numSamples; ++i) + { + *(uint16*) intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + intData += destBytesPerSample; + } + } + else + { + intData += destBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - *(uint16*)intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= destBytesPerSample; + *(uint16*)intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + } + } } void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { - const double maxVal = (double) 0x7fffff; - char* intData = (char*) dest; + const double maxVal = (double) 0x7fffff; + char* intData = (char*) dest; - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - ByteOrder::littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; + if (dest != (void*) source || destBytesPerSample <= 4) + { + for (int i = 0; i < numSamples; ++i) + { + ByteOrder::littleEndian24BitToChars ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + intData += destBytesPerSample; + } + } + else + { + intData += destBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - ByteOrder::littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= destBytesPerSample; + ByteOrder::littleEndian24BitToChars ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + } + } } void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { - const double maxVal = (double) 0x7fffff; - char* intData = (char*) dest; + const double maxVal = (double) 0x7fffff; + char* intData = (char*) dest; - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - ByteOrder::bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; + if (dest != (void*) source || destBytesPerSample <= 4) + { + for (int i = 0; i < numSamples; ++i) + { + ByteOrder::bigEndian24BitToChars ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + intData += destBytesPerSample; + } + } + else + { + intData += destBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - ByteOrder::bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= destBytesPerSample; + ByteOrder::bigEndian24BitToChars ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); + } + } } void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { - const double maxVal = (double) 0x7fffffff; - char* intData = (char*) dest; + const double maxVal = (double) 0x7fffffff; + char* intData = (char*) dest; - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - *(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; + if (dest != (void*) source || destBytesPerSample <= 4) + { + for (int i = 0; i < numSamples; ++i) + { + *(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + intData += destBytesPerSample; + } + } + else + { + intData += destBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - *(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= destBytesPerSample; + *(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + } + } } void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { - const double maxVal = (double) 0x7fffffff; - char* intData = (char*) dest; + const double maxVal = (double) 0x7fffffff; + char* intData = (char*) dest; - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - *(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; + if (dest != (void*) source || destBytesPerSample <= 4) + { + for (int i = 0; i < numSamples; ++i) + { + *(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + intData += destBytesPerSample; + } + } + else + { + intData += destBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - *(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= destBytesPerSample; + *(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); + } + } } void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { - jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data! + jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data! - char* d = (char*) dest; + char* d = (char*) dest; - for (int i = 0; i < numSamples; ++i) - { - *(float*) d = source[i]; + for (int i = 0; i < numSamples; ++i) + { + *(float*) d = source[i]; #if JUCE_BIG_ENDIAN - *(uint32*) d = ByteOrder::swap (*(uint32*) d); + *(uint32*) d = ByteOrder::swap (*(uint32*) d); #endif - d += destBytesPerSample; - } + d += destBytesPerSample; + } } void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { - jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data! + jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data! - char* d = (char*) dest; + char* d = (char*) dest; - for (int i = 0; i < numSamples; ++i) - { - *(float*) d = source[i]; + for (int i = 0; i < numSamples; ++i) + { + *(float*) d = source[i]; #if JUCE_LITTLE_ENDIAN - *(uint32*) d = ByteOrder::swap (*(uint32*) d); + *(uint32*) d = ByteOrder::swap (*(uint32*) d); #endif - d += destBytesPerSample; - } + d += destBytesPerSample; + } } void AudioDataConverters::convertInt16LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { - const float scale = 1.0f / 0x7fff; - const char* intData = (const char*) source; + const float scale = 1.0f / 0x7fff; + const char* intData = (const char*) source; - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; + if (source != (void*) dest || srcBytesPerSample >= 4) + { + for (int i = 0; i < numSamples; ++i) + { + dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData); + intData += srcBytesPerSample; + } + } + else + { + intData += srcBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= srcBytesPerSample; + dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData); + } + } } void AudioDataConverters::convertInt16BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { - const float scale = 1.0f / 0x7fff; - const char* intData = (const char*) source; + const float scale = 1.0f / 0x7fff; + const char* intData = (const char*) source; - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; + if (source != (void*) dest || srcBytesPerSample >= 4) + { + for (int i = 0; i < numSamples; ++i) + { + dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData); + intData += srcBytesPerSample; + } + } + else + { + intData += srcBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= srcBytesPerSample; + dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData); + } + } } void AudioDataConverters::convertInt24LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { - const float scale = 1.0f / 0x7fffff; - const char* intData = (const char*) source; + const float scale = 1.0f / 0x7fffff; + const char* intData = (const char*) source; - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; + if (source != (void*) dest || srcBytesPerSample >= 4) + { + for (int i = 0; i < numSamples; ++i) + { + dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData); + intData += srcBytesPerSample; + } + } + else + { + intData += srcBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= srcBytesPerSample; + dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData); + } + } } void AudioDataConverters::convertInt24BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { - const float scale = 1.0f / 0x7fffff; - const char* intData = (const char*) source; + const float scale = 1.0f / 0x7fffff; + const char* intData = (const char*) source; - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; + if (source != (void*) dest || srcBytesPerSample >= 4) + { + for (int i = 0; i < numSamples; ++i) + { + dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData); + intData += srcBytesPerSample; + } + } + else + { + intData += srcBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= srcBytesPerSample; + dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData); + } + } } void AudioDataConverters::convertInt32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { - const float scale = 1.0f / 0x7fffffff; - const char* intData = (const char*) source; + const float scale = 1.0f / 0x7fffffff; + const char* intData = (const char*) source; - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; + if (source != (void*) dest || srcBytesPerSample >= 4) + { + for (int i = 0; i < numSamples; ++i) + { + dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData); + intData += srcBytesPerSample; + } + } + else + { + intData += srcBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= srcBytesPerSample; + dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData); + } + } } void AudioDataConverters::convertInt32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { - const float scale = 1.0f / 0x7fffffff; - const char* intData = (const char*) source; + const float scale = 1.0f / 0x7fffffff; + const char* intData = (const char*) source; - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; + if (source != (void*) dest || srcBytesPerSample >= 4) + { + for (int i = 0; i < numSamples; ++i) + { + dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData); + intData += srcBytesPerSample; + } + } + else + { + intData += srcBytesPerSample * numSamples; - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData); - } - } + for (int i = numSamples; --i >= 0;) + { + intData -= srcBytesPerSample; + dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData); + } + } } void AudioDataConverters::convertFloat32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { - const char* s = (const char*) source; + const char* s = (const char*) source; - for (int i = 0; i < numSamples; ++i) - { - dest[i] = *(float*)s; + for (int i = 0; i < numSamples; ++i) + { + dest[i] = *(float*)s; #if JUCE_BIG_ENDIAN - uint32* const d = (uint32*) (dest + i); - *d = ByteOrder::swap (*d); + uint32* const d = (uint32*) (dest + i); + *d = ByteOrder::swap (*d); #endif - s += srcBytesPerSample; - } + s += srcBytesPerSample; + } } void AudioDataConverters::convertFloat32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { - const char* s = (const char*) source; + const char* s = (const char*) source; - for (int i = 0; i < numSamples; ++i) - { - dest[i] = *(float*)s; + for (int i = 0; i < numSamples; ++i) + { + dest[i] = *(float*)s; #if JUCE_LITTLE_ENDIAN - uint32* const d = (uint32*) (dest + i); - *d = ByteOrder::swap (*d); + uint32* const d = (uint32*) (dest + i); + *d = ByteOrder::swap (*d); #endif - s += srcBytesPerSample; - } + s += srcBytesPerSample; + } } void AudioDataConverters::convertFloatToFormat (const DataFormat destFormat, - const float* const source, - void* const dest, - const int numSamples) + const float* const source, + void* const dest, + const int numSamples) { - switch (destFormat) - { - case int16LE: - convertFloatToInt16LE (source, dest, numSamples); - break; + switch (destFormat) + { + case int16LE: + convertFloatToInt16LE (source, dest, numSamples); + break; - case int16BE: - convertFloatToInt16BE (source, dest, numSamples); - break; + case int16BE: + convertFloatToInt16BE (source, dest, numSamples); + break; - case int24LE: - convertFloatToInt24LE (source, dest, numSamples); - break; + case int24LE: + convertFloatToInt24LE (source, dest, numSamples); + break; - case int24BE: - convertFloatToInt24BE (source, dest, numSamples); - break; + case int24BE: + convertFloatToInt24BE (source, dest, numSamples); + break; - case int32LE: - convertFloatToInt32LE (source, dest, numSamples); - break; + case int32LE: + convertFloatToInt32LE (source, dest, numSamples); + break; - case int32BE: - convertFloatToInt32BE (source, dest, numSamples); - break; + case int32BE: + convertFloatToInt32BE (source, dest, numSamples); + break; - case float32LE: - convertFloatToFloat32LE (source, dest, numSamples); - break; + case float32LE: + convertFloatToFloat32LE (source, dest, numSamples); + break; - case float32BE: - convertFloatToFloat32BE (source, dest, numSamples); - break; + case float32BE: + convertFloatToFloat32BE (source, dest, numSamples); + break; - default: - jassertfalse - break; - } + default: + jassertfalse + break; + } } void AudioDataConverters::convertFormatToFloat (const DataFormat sourceFormat, - const void* const source, - float* const dest, - const int numSamples) + const void* const source, + float* const dest, + const int numSamples) { - switch (sourceFormat) - { - case int16LE: - convertInt16LEToFloat (source, dest, numSamples); - break; + switch (sourceFormat) + { + case int16LE: + convertInt16LEToFloat (source, dest, numSamples); + break; - case int16BE: - convertInt16BEToFloat (source, dest, numSamples); - break; + case int16BE: + convertInt16BEToFloat (source, dest, numSamples); + break; - case int24LE: - convertInt24LEToFloat (source, dest, numSamples); - break; + case int24LE: + convertInt24LEToFloat (source, dest, numSamples); + break; - case int24BE: - convertInt24BEToFloat (source, dest, numSamples); - break; + case int24BE: + convertInt24BEToFloat (source, dest, numSamples); + break; - case int32LE: - convertInt32LEToFloat (source, dest, numSamples); - break; + case int32LE: + convertInt32LEToFloat (source, dest, numSamples); + break; - case int32BE: - convertInt32BEToFloat (source, dest, numSamples); - break; + case int32BE: + convertInt32BEToFloat (source, dest, numSamples); + break; - case float32LE: - convertFloat32LEToFloat (source, dest, numSamples); - break; + case float32LE: + convertFloat32LEToFloat (source, dest, numSamples); + break; - case float32BE: - convertFloat32BEToFloat (source, dest, numSamples); - break; + case float32BE: + convertFloat32BEToFloat (source, dest, numSamples); + break; - default: - jassertfalse - break; - } + default: + jassertfalse + break; + } } void AudioDataConverters::interleaveSamples (const float** const source, - float* const dest, - const int numSamples, - const int numChannels) + float* const dest, + const int numSamples, + const int numChannels) { - for (int chan = 0; chan < numChannels; ++chan) - { - int i = chan; - const float* src = source [chan]; + for (int chan = 0; chan < numChannels; ++chan) + { + int i = chan; + const float* src = source [chan]; - for (int j = 0; j < numSamples; ++j) - { - dest [i] = src [j]; - i += numChannels; - } - } + for (int j = 0; j < numSamples; ++j) + { + dest [i] = src [j]; + i += numChannels; + } + } } void AudioDataConverters::deinterleaveSamples (const float* const source, - float** const dest, - const int numSamples, - const int numChannels) + float** const dest, + const int numSamples, + const int numChannels) { - for (int chan = 0; chan < numChannels; ++chan) - { - int i = chan; - float* dst = dest [chan]; + for (int chan = 0; chan < numChannels; ++chan) + { + int i = chan; + float* dst = dest [chan]; - for (int j = 0; j < numSamples; ++j) - { - dst [j] = source [i]; - i += numChannels; - } - } + for (int j = 0; j < numSamples; ++j) + { + dst [j] = source [i]; + i += numChannels; + } + } } END_JUCE_NAMESPACE @@ -25891,107 +25632,107 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioSampleBuffer::AudioSampleBuffer (const int numChannels_, - const int numSamples) throw() + const int numSamples) throw() : numChannels (numChannels_), - size (numSamples) + size (numSamples) { - jassert (numSamples >= 0); - jassert (numChannels_ > 0); + jassert (numSamples >= 0); + jassert (numChannels_ > 0); - allocateData(); + allocateData(); } AudioSampleBuffer::AudioSampleBuffer (const AudioSampleBuffer& other) throw() : numChannels (other.numChannels), - size (other.size) + size (other.size) { - allocateData(); - const int numBytes = size * sizeof (float); + allocateData(); + const size_t numBytes = size * sizeof (float); - for (int i = 0; i < numChannels; ++i) - memcpy (channels[i], other.channels[i], numBytes); + for (int i = 0; i < numChannels; ++i) + memcpy (channels[i], other.channels[i], numBytes); } void AudioSampleBuffer::allocateData() { - const int channelListSize = (numChannels + 1) * sizeof (float*); - allocatedBytes = numChannels * size * sizeof (float) + channelListSize + 32; - allocatedData.malloc (allocatedBytes); - channels = (float**) allocatedData; + const size_t channelListSize = (numChannels + 1) * sizeof (float*); + allocatedBytes = (int) (numChannels * size * sizeof (float) + channelListSize + 32); + allocatedData.malloc (allocatedBytes); + channels = (float**) allocatedData; - float* chan = (float*) (allocatedData + channelListSize); - for (int i = 0; i < numChannels; ++i) - { - channels[i] = chan; - chan += size; - } + float* chan = (float*) (allocatedData + channelListSize); + for (int i = 0; i < numChannels; ++i) + { + channels[i] = chan; + chan += size; + } - channels [numChannels] = 0; + channels [numChannels] = 0; } AudioSampleBuffer::AudioSampleBuffer (float** dataToReferTo, - const int numChannels_, - const int numSamples) throw() - : numChannels (numChannels_), - size (numSamples), - allocatedBytes (0) + const int numChannels_, + const int numSamples) throw() + : numChannels (numChannels_), + size (numSamples), + allocatedBytes (0) { - jassert (numChannels_ > 0); - allocateChannels (dataToReferTo); + jassert (numChannels_ > 0); + allocateChannels (dataToReferTo); } void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, - const int newNumChannels, - const int newNumSamples) throw() + const int newNumChannels, + const int newNumSamples) throw() { - jassert (newNumChannels > 0); + jassert (newNumChannels > 0); - allocatedBytes = 0; - allocatedData.free(); + allocatedBytes = 0; + allocatedData.free(); - numChannels = newNumChannels; - size = newNumSamples; + numChannels = newNumChannels; + size = newNumSamples; - allocateChannels (dataToReferTo); + allocateChannels (dataToReferTo); } void AudioSampleBuffer::allocateChannels (float** const dataToReferTo) { - // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) - if (numChannels < numElementsInArray (preallocatedChannelSpace)) - { - channels = (float**) preallocatedChannelSpace; - } - else - { - allocatedData.malloc (numChannels + 1, sizeof (float*)); - channels = (float**) allocatedData; - } + // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) + if (numChannels < numElementsInArray (preallocatedChannelSpace)) + { + channels = (float**) preallocatedChannelSpace; + } + else + { + allocatedData.malloc (numChannels + 1, sizeof (float*)); + channels = (float**) allocatedData; + } - for (int i = 0; i < numChannels; ++i) - { - // you have to pass in the same number of valid pointers as numChannels - jassert (dataToReferTo[i] != 0); + for (int i = 0; i < numChannels; ++i) + { + // you have to pass in the same number of valid pointers as numChannels + jassert (dataToReferTo[i] != 0); - channels[i] = dataToReferTo[i]; - } + channels[i] = dataToReferTo[i]; + } - channels [numChannels] = 0; + channels [numChannels] = 0; } const AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other) throw() { - if (this != &other) - { - setSize (other.getNumChannels(), other.getNumSamples(), false, false, false); + if (this != &other) + { + setSize (other.getNumChannels(), other.getNumSamples(), false, false, false); - const int numBytes = size * sizeof (float); + const size_t numBytes = size * sizeof (float); - for (int i = 0; i < numChannels; ++i) - memcpy (channels[i], other.channels[i], numBytes); - } + for (int i = 0; i < numChannels; ++i) + memcpy (channels[i], other.channels[i], numBytes); + } - return *this; + return *this; } AudioSampleBuffer::~AudioSampleBuffer() throw() @@ -25999,552 +25740,552 @@ AudioSampleBuffer::~AudioSampleBuffer() throw() } void AudioSampleBuffer::setSize (const int newNumChannels, - const int newNumSamples, - const bool keepExistingContent, - const bool clearExtraSpace, - const bool avoidReallocating) throw() + const int newNumSamples, + const bool keepExistingContent, + const bool clearExtraSpace, + const bool avoidReallocating) throw() { - jassert (newNumChannels > 0); + jassert (newNumChannels > 0); - if (newNumSamples != size || newNumChannels != numChannels) - { - const int channelListSize = (newNumChannels + 1) * sizeof (float*); - const int newTotalBytes = (newNumChannels * newNumSamples * sizeof (float)) + channelListSize + 32; + if (newNumSamples != size || newNumChannels != numChannels) + { + const size_t channelListSize = (newNumChannels + 1) * sizeof (float*); + const size_t newTotalBytes = (newNumChannels * newNumSamples * sizeof (float)) + channelListSize + 32; - if (keepExistingContent) - { - HeapBlock newData; - newData.allocate (newTotalBytes, clearExtraSpace); + if (keepExistingContent) + { + HeapBlock newData; + newData.allocate (newTotalBytes, clearExtraSpace); - const int numChansToCopy = jmin (numChannels, newNumChannels); - const int numBytesToCopy = sizeof (float) * jmin (newNumSamples, size); + const int numChansToCopy = jmin (numChannels, newNumChannels); + const size_t numBytesToCopy = sizeof (float) * jmin (newNumSamples, size); - float** const newChannels = (float**) newData; - float* newChan = (float*) (newData + channelListSize); - for (int i = 0; i < numChansToCopy; ++i) - { - memcpy (newChan, channels[i], numBytesToCopy); - newChannels[i] = newChan; - newChan += newNumSamples; - } + float** const newChannels = (float**) newData; + float* newChan = (float*) (newData + channelListSize); + for (int i = 0; i < numChansToCopy; ++i) + { + memcpy (newChan, channels[i], numBytesToCopy); + newChannels[i] = newChan; + newChan += newNumSamples; + } - allocatedData.swapWith (newData); - allocatedBytes = newTotalBytes; - channels = (float**) allocatedData; - } - else - { - if (avoidReallocating && allocatedBytes >= newTotalBytes) - { - if (clearExtraSpace) - zeromem (allocatedData, newTotalBytes); - } - else - { - allocatedBytes = newTotalBytes; - allocatedData.allocate (newTotalBytes, clearExtraSpace); - channels = (float**) allocatedData; - } + allocatedData.swapWith (newData); + allocatedBytes = (int) newTotalBytes; + channels = (float**) allocatedData; + } + else + { + if (avoidReallocating && allocatedBytes >= newTotalBytes) + { + if (clearExtraSpace) + zeromem (allocatedData, newTotalBytes); + } + else + { + allocatedBytes = newTotalBytes; + allocatedData.allocate (newTotalBytes, clearExtraSpace); + channels = (float**) allocatedData; + } - float* chan = (float*) (allocatedData + channelListSize); - for (int i = 0; i < newNumChannels; ++i) - { - channels[i] = chan; - chan += newNumSamples; - } - } + float* chan = (float*) (allocatedData + channelListSize); + for (int i = 0; i < newNumChannels; ++i) + { + channels[i] = chan; + chan += newNumSamples; + } + } - channels [newNumChannels] = 0; - size = newNumSamples; - numChannels = newNumChannels; - } + channels [newNumChannels] = 0; + size = newNumSamples; + numChannels = newNumChannels; + } } void AudioSampleBuffer::clear() throw() { - for (int i = 0; i < numChannels; ++i) - zeromem (channels[i], size * sizeof (float)); + for (int i = 0; i < numChannels; ++i) + zeromem (channels[i], size * sizeof (float)); } void AudioSampleBuffer::clear (const int startSample, - const int numSamples) throw() + const int numSamples) throw() { - jassert (startSample >= 0 && startSample + numSamples <= size); + jassert (startSample >= 0 && startSample + numSamples <= size); - for (int i = 0; i < numChannels; ++i) - zeromem (channels [i] + startSample, numSamples * sizeof (float)); + for (int i = 0; i < numChannels; ++i) + zeromem (channels [i] + startSample, numSamples * sizeof (float)); } void AudioSampleBuffer::clear (const int channel, - const int startSample, - const int numSamples) throw() + const int startSample, + const int numSamples) throw() { - jassert (((unsigned int) channel) < (unsigned int) numChannels); - jassert (startSample >= 0 && startSample + numSamples <= size); + jassert (((unsigned int) channel) < (unsigned int) numChannels); + jassert (startSample >= 0 && startSample + numSamples <= size); - zeromem (channels [channel] + startSample, numSamples * sizeof (float)); + zeromem (channels [channel] + startSample, numSamples * sizeof (float)); } void AudioSampleBuffer::applyGain (const int channel, - const int startSample, - int numSamples, - const float gain) throw() + const int startSample, + int numSamples, + const float gain) throw() { - jassert (((unsigned int) channel) < (unsigned int) numChannels); - jassert (startSample >= 0 && startSample + numSamples <= size); + jassert (((unsigned int) channel) < (unsigned int) numChannels); + jassert (startSample >= 0 && startSample + numSamples <= size); - if (gain != 1.0f) - { - float* d = channels [channel] + startSample; + if (gain != 1.0f) + { + float* d = channels [channel] + startSample; - if (gain == 0.0f) - { - zeromem (d, sizeof (float) * numSamples); - } - else - { - while (--numSamples >= 0) - *d++ *= gain; - } - } + if (gain == 0.0f) + { + zeromem (d, sizeof (float) * numSamples); + } + else + { + while (--numSamples >= 0) + *d++ *= gain; + } + } } void AudioSampleBuffer::applyGainRamp (const int channel, - const int startSample, - int numSamples, - float startGain, - float endGain) throw() + const int startSample, + int numSamples, + float startGain, + float endGain) throw() { - if (startGain == endGain) - { - applyGain (channel, startSample, numSamples, startGain); - } - else - { - jassert (((unsigned int) channel) < (unsigned int) numChannels); - jassert (startSample >= 0 && startSample + numSamples <= size); + if (startGain == endGain) + { + applyGain (channel, startSample, numSamples, startGain); + } + else + { + jassert (((unsigned int) channel) < (unsigned int) numChannels); + jassert (startSample >= 0 && startSample + numSamples <= size); - const float increment = (endGain - startGain) / numSamples; - float* d = channels [channel] + startSample; + const float increment = (endGain - startGain) / numSamples; + float* d = channels [channel] + startSample; - while (--numSamples >= 0) - { - *d++ *= startGain; - startGain += increment; - } - } + while (--numSamples >= 0) + { + *d++ *= startGain; + startGain += increment; + } + } } void AudioSampleBuffer::applyGain (const int startSample, - const int numSamples, - const float gain) throw() + const int numSamples, + const float gain) throw() { - for (int i = 0; i < numChannels; ++i) - applyGain (i, startSample, numSamples, gain); + for (int i = 0; i < numChannels; ++i) + applyGain (i, startSample, numSamples, gain); } void AudioSampleBuffer::addFrom (const int destChannel, - const int destStartSample, - const AudioSampleBuffer& source, - const int sourceChannel, - const int sourceStartSample, - int numSamples, - const float gain) throw() + const int destStartSample, + const AudioSampleBuffer& source, + const int sourceChannel, + const int sourceStartSample, + int numSamples, + const float gain) throw() { - jassert (&source != this || sourceChannel != destChannel); - jassert (((unsigned int) destChannel) < (unsigned int) numChannels); - jassert (destStartSample >= 0 && destStartSample + numSamples <= size); - jassert (((unsigned int) sourceChannel) < (unsigned int) source.numChannels); - jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size); + jassert (&source != this || sourceChannel != destChannel); + jassert (((unsigned int) destChannel) < (unsigned int) numChannels); + jassert (destStartSample >= 0 && destStartSample + numSamples <= size); + jassert (((unsigned int) sourceChannel) < (unsigned int) source.numChannels); + jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size); - if (gain != 0.0f && numSamples > 0) - { - float* d = channels [destChannel] + destStartSample; - const float* s = source.channels [sourceChannel] + sourceStartSample; + if (gain != 0.0f && numSamples > 0) + { + float* d = channels [destChannel] + destStartSample; + const float* s = source.channels [sourceChannel] + sourceStartSample; - if (gain != 1.0f) - { - while (--numSamples >= 0) - *d++ += gain * *s++; - } - else - { - while (--numSamples >= 0) - *d++ += *s++; - } - } + if (gain != 1.0f) + { + while (--numSamples >= 0) + *d++ += gain * *s++; + } + else + { + while (--numSamples >= 0) + *d++ += *s++; + } + } } void AudioSampleBuffer::addFrom (const int destChannel, - const int destStartSample, - const float* source, - int numSamples, - const float gain) throw() + const int destStartSample, + const float* source, + int numSamples, + const float gain) throw() { - jassert (((unsigned int) destChannel) < (unsigned int) numChannels); - jassert (destStartSample >= 0 && destStartSample + numSamples <= size); - jassert (source != 0); + jassert (((unsigned int) destChannel) < (unsigned int) numChannels); + jassert (destStartSample >= 0 && destStartSample + numSamples <= size); + jassert (source != 0); - if (gain != 0.0f && numSamples > 0) - { - float* d = channels [destChannel] + destStartSample; + if (gain != 0.0f && numSamples > 0) + { + float* d = channels [destChannel] + destStartSample; - if (gain != 1.0f) - { - while (--numSamples >= 0) - *d++ += gain * *source++; - } - else - { - while (--numSamples >= 0) - *d++ += *source++; - } - } + if (gain != 1.0f) + { + while (--numSamples >= 0) + *d++ += gain * *source++; + } + else + { + while (--numSamples >= 0) + *d++ += *source++; + } + } } void AudioSampleBuffer::addFromWithRamp (const int destChannel, - const int destStartSample, - const float* source, - int numSamples, - float startGain, - const float endGain) throw() + const int destStartSample, + const float* source, + int numSamples, + float startGain, + const float endGain) throw() { - jassert (((unsigned int) destChannel) < (unsigned int) numChannels); - jassert (destStartSample >= 0 && destStartSample + numSamples <= size); - jassert (source != 0); + jassert (((unsigned int) destChannel) < (unsigned int) numChannels); + jassert (destStartSample >= 0 && destStartSample + numSamples <= size); + jassert (source != 0); - if (startGain == endGain) - { - addFrom (destChannel, - destStartSample, - source, - numSamples, - startGain); - } - else - { - if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f)) - { - const float increment = (endGain - startGain) / numSamples; - float* d = channels [destChannel] + destStartSample; + if (startGain == endGain) + { + addFrom (destChannel, + destStartSample, + source, + numSamples, + startGain); + } + else + { + if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f)) + { + const float increment = (endGain - startGain) / numSamples; + float* d = channels [destChannel] + destStartSample; - while (--numSamples >= 0) - { - *d++ += startGain * *source++; - startGain += increment; - } - } - } + while (--numSamples >= 0) + { + *d++ += startGain * *source++; + startGain += increment; + } + } + } } void AudioSampleBuffer::copyFrom (const int destChannel, - const int destStartSample, - const AudioSampleBuffer& source, - const int sourceChannel, - const int sourceStartSample, - int numSamples) throw() + const int destStartSample, + const AudioSampleBuffer& source, + const int sourceChannel, + const int sourceStartSample, + int numSamples) throw() { - jassert (&source != this || sourceChannel != destChannel); - jassert (((unsigned int) destChannel) < (unsigned int) numChannels); - jassert (destStartSample >= 0 && destStartSample + numSamples <= size); - jassert (((unsigned int) sourceChannel) < (unsigned int) source.numChannels); - jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size); + jassert (&source != this || sourceChannel != destChannel); + jassert (((unsigned int) destChannel) < (unsigned int) numChannels); + jassert (destStartSample >= 0 && destStartSample + numSamples <= size); + jassert (((unsigned int) sourceChannel) < (unsigned int) source.numChannels); + jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size); - if (numSamples > 0) - { - memcpy (channels [destChannel] + destStartSample, - source.channels [sourceChannel] + sourceStartSample, - sizeof (float) * numSamples); - } + if (numSamples > 0) + { + memcpy (channels [destChannel] + destStartSample, + source.channels [sourceChannel] + sourceStartSample, + sizeof (float) * numSamples); + } } void AudioSampleBuffer::copyFrom (const int destChannel, - const int destStartSample, - const float* source, - int numSamples) throw() + const int destStartSample, + const float* source, + int numSamples) throw() { - jassert (((unsigned int) destChannel) < (unsigned int) numChannels); - jassert (destStartSample >= 0 && destStartSample + numSamples <= size); - jassert (source != 0); + jassert (((unsigned int) destChannel) < (unsigned int) numChannels); + jassert (destStartSample >= 0 && destStartSample + numSamples <= size); + jassert (source != 0); - if (numSamples > 0) - { - memcpy (channels [destChannel] + destStartSample, - source, - sizeof (float) * numSamples); - } + if (numSamples > 0) + { + memcpy (channels [destChannel] + destStartSample, + source, + sizeof (float) * numSamples); + } } void AudioSampleBuffer::copyFrom (const int destChannel, - const int destStartSample, - const float* source, - int numSamples, - const float gain) throw() + const int destStartSample, + const float* source, + int numSamples, + const float gain) throw() { - jassert (((unsigned int) destChannel) < (unsigned int) numChannels); - jassert (destStartSample >= 0 && destStartSample + numSamples <= size); - jassert (source != 0); + jassert (((unsigned int) destChannel) < (unsigned int) numChannels); + jassert (destStartSample >= 0 && destStartSample + numSamples <= size); + jassert (source != 0); - if (numSamples > 0) - { - float* d = channels [destChannel] + destStartSample; + if (numSamples > 0) + { + float* d = channels [destChannel] + destStartSample; - if (gain != 1.0f) - { - if (gain == 0) - { - zeromem (d, sizeof (float) * numSamples); - } - else - { - while (--numSamples >= 0) - *d++ = gain * *source++; - } - } - else - { - memcpy (d, source, sizeof (float) * numSamples); - } - } + if (gain != 1.0f) + { + if (gain == 0) + { + zeromem (d, sizeof (float) * numSamples); + } + else + { + while (--numSamples >= 0) + *d++ = gain * *source++; + } + } + else + { + memcpy (d, source, sizeof (float) * numSamples); + } + } } void AudioSampleBuffer::copyFromWithRamp (const int destChannel, - const int destStartSample, - const float* source, - int numSamples, - float startGain, - float endGain) throw() + const int destStartSample, + const float* source, + int numSamples, + float startGain, + float endGain) throw() { - jassert (((unsigned int) destChannel) < (unsigned int) numChannels); - jassert (destStartSample >= 0 && destStartSample + numSamples <= size); - jassert (source != 0); + jassert (((unsigned int) destChannel) < (unsigned int) numChannels); + jassert (destStartSample >= 0 && destStartSample + numSamples <= size); + jassert (source != 0); - if (startGain == endGain) - { - copyFrom (destChannel, - destStartSample, - source, - numSamples, - startGain); - } - else - { - if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f)) - { - const float increment = (endGain - startGain) / numSamples; - float* d = channels [destChannel] + destStartSample; + if (startGain == endGain) + { + copyFrom (destChannel, + destStartSample, + source, + numSamples, + startGain); + } + else + { + if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f)) + { + const float increment = (endGain - startGain) / numSamples; + float* d = channels [destChannel] + destStartSample; - while (--numSamples >= 0) - { - *d++ = startGain * *source++; - startGain += increment; - } - } - } + while (--numSamples >= 0) + { + *d++ = startGain * *source++; + startGain += increment; + } + } + } } void AudioSampleBuffer::findMinMax (const int channel, - const int startSample, - int numSamples, - float& minVal, - float& maxVal) const throw() + const int startSample, + int numSamples, + float& minVal, + float& maxVal) const throw() { - jassert (((unsigned int) channel) < (unsigned int) numChannels); - jassert (startSample >= 0 && startSample + numSamples <= size); + jassert (((unsigned int) channel) < (unsigned int) numChannels); + jassert (startSample >= 0 && startSample + numSamples <= size); - if (numSamples <= 0) - { - minVal = 0.0f; - maxVal = 0.0f; - } - else - { - const float* d = channels [channel] + startSample; + if (numSamples <= 0) + { + minVal = 0.0f; + maxVal = 0.0f; + } + else + { + const float* d = channels [channel] + startSample; - float mn = *d++; - float mx = mn; + float mn = *d++; + float mx = mn; - while (--numSamples > 0) // (> 0 rather than >= 0 because we've already taken the first sample) - { - const float samp = *d++; + while (--numSamples > 0) // (> 0 rather than >= 0 because we've already taken the first sample) + { + const float samp = *d++; - if (samp > mx) - mx = samp; + if (samp > mx) + mx = samp; - if (samp < mn) - mn = samp; - } + if (samp < mn) + mn = samp; + } - maxVal = mx; - minVal = mn; - } + maxVal = mx; + minVal = mn; + } } float AudioSampleBuffer::getMagnitude (const int channel, - const int startSample, - const int numSamples) const throw() + const int startSample, + const int numSamples) const throw() { - jassert (((unsigned int) channel) < (unsigned int) numChannels); - jassert (startSample >= 0 && startSample + numSamples <= size); + jassert (((unsigned int) channel) < (unsigned int) numChannels); + jassert (startSample >= 0 && startSample + numSamples <= size); - float mn, mx; - findMinMax (channel, startSample, numSamples, mn, mx); + float mn, mx; + findMinMax (channel, startSample, numSamples, mn, mx); - return jmax (mn, -mn, mx, -mx); + return jmax (mn, -mn, mx, -mx); } float AudioSampleBuffer::getMagnitude (const int startSample, - const int numSamples) const throw() + const int numSamples) const throw() { - float mag = 0.0f; + float mag = 0.0f; - for (int i = 0; i < numChannels; ++i) - mag = jmax (mag, getMagnitude (i, startSample, numSamples)); + for (int i = 0; i < numChannels; ++i) + mag = jmax (mag, getMagnitude (i, startSample, numSamples)); - return mag; + return mag; } float AudioSampleBuffer::getRMSLevel (const int channel, - const int startSample, - const int numSamples) const throw() + const int startSample, + const int numSamples) const throw() { - jassert (((unsigned int) channel) < (unsigned int) numChannels); - jassert (startSample >= 0 && startSample + numSamples <= size); + jassert (((unsigned int) channel) < (unsigned int) numChannels); + jassert (startSample >= 0 && startSample + numSamples <= size); - if (numSamples <= 0 || channel < 0 || channel >= numChannels) - return 0.0f; + if (numSamples <= 0 || channel < 0 || channel >= numChannels) + return 0.0f; - const float* const data = channels [channel] + startSample; - double sum = 0.0; + const float* const data = channels [channel] + startSample; + double sum = 0.0; - for (int i = 0; i < numSamples; ++i) - { - const float sample = data [i]; - sum += sample * sample; - } + for (int i = 0; i < numSamples; ++i) + { + const float sample = data [i]; + sum += sample * sample; + } - return (float) sqrt (sum / numSamples); + return (float) sqrt (sum / numSamples); } void AudioSampleBuffer::readFromAudioReader (AudioFormatReader* reader, - const int startSample, - const int numSamples, - const int readerStartSample, - const bool useLeftChan, - const bool useRightChan) throw() + const int startSample, + const int numSamples, + const int readerStartSample, + const bool useLeftChan, + const bool useRightChan) throw() { - jassert (reader != 0); - jassert (startSample >= 0 && startSample + numSamples <= size); + jassert (reader != 0); + jassert (startSample >= 0 && startSample + numSamples <= size); - if (numSamples > 0) - { - int* chans[3]; + if (numSamples > 0) + { + int* chans[3]; - if (useLeftChan == useRightChan) - { - chans[0] = (int*) getSampleData (0, startSample); - chans[1] = (reader->numChannels > 1 && getNumChannels() > 1) ? (int*) getSampleData (1, startSample) : 0; - } - else if (useLeftChan || (reader->numChannels == 1)) - { - chans[0] = (int*) getSampleData (0, startSample); - chans[1] = 0; - } - else if (useRightChan) - { - chans[0] = 0; - chans[1] = (int*) getSampleData (0, startSample); - } + if (useLeftChan == useRightChan) + { + chans[0] = (int*) getSampleData (0, startSample); + chans[1] = (reader->numChannels > 1 && getNumChannels() > 1) ? (int*) getSampleData (1, startSample) : 0; + } + else if (useLeftChan || (reader->numChannels == 1)) + { + chans[0] = (int*) getSampleData (0, startSample); + chans[1] = 0; + } + else if (useRightChan) + { + chans[0] = 0; + chans[1] = (int*) getSampleData (0, startSample); + } - chans[2] = 0; + chans[2] = 0; - reader->read (chans, 2, readerStartSample, numSamples, true); + reader->read (chans, 2, readerStartSample, numSamples, true); - if (! reader->usesFloatingPointData) - { - for (int j = 0; j < 2; ++j) - { - float* const d = (float*) (chans[j]); + if (! reader->usesFloatingPointData) + { + for (int j = 0; j < 2; ++j) + { + float* const d = (float*) (chans[j]); - if (d != 0) - { - const float multiplier = 1.0f / 0x7fffffff; + if (d != 0) + { + const float multiplier = 1.0f / 0x7fffffff; - for (int i = 0; i < numSamples; ++i) - d[i] = *(int*)(d + i) * multiplier; - } - } - } + for (int i = 0; i < numSamples; ++i) + d[i] = *(int*)(d + i) * multiplier; + } + } + } - if (numChannels > 1 && (chans[0] == 0 || chans[1] == 0)) - { - // if this is a stereo buffer and the source was mono, dupe the first channel.. - memcpy (getSampleData (1, startSample), - getSampleData (0, startSample), - sizeof (float) * numSamples); - } - } + if (numChannels > 1 && (chans[0] == 0 || chans[1] == 0)) + { + // if this is a stereo buffer and the source was mono, dupe the first channel.. + memcpy (getSampleData (1, startSample), + getSampleData (0, startSample), + sizeof (float) * numSamples); + } + } } void AudioSampleBuffer::writeToAudioWriter (AudioFormatWriter* writer, - const int startSample, - const int numSamples) const throw() + const int startSample, + const int numSamples) const throw() { - jassert (startSample >= 0 && startSample + numSamples <= size); + jassert (startSample >= 0 && startSample + numSamples <= size); - if (numSamples > 0) - { - int* chans [3]; + if (numSamples > 0) + { + int* chans [3]; - if (writer->isFloatingPoint()) - { - chans[0] = (int*) getSampleData (0, startSample); + if (writer->isFloatingPoint()) + { + chans[0] = (int*) getSampleData (0, startSample); - if (numChannels > 1) - chans[1] = (int*) getSampleData (1, startSample); - else - chans[1] = 0; + if (numChannels > 1) + chans[1] = (int*) getSampleData (1, startSample); + else + chans[1] = 0; - chans[2] = 0; - writer->write ((const int**) chans, numSamples); - } - else - { - HeapBlock tempBuffer (numSamples * 2); - chans[0] = tempBuffer; + chans[2] = 0; + writer->write ((const int**) chans, numSamples); + } + else + { + HeapBlock tempBuffer (numSamples * 2); + chans[0] = tempBuffer; - if (numChannels > 1) - chans[1] = chans[0] + numSamples; - else - chans[1] = 0; + if (numChannels > 1) + chans[1] = chans[0] + numSamples; + else + chans[1] = 0; - chans[2] = 0; + chans[2] = 0; - for (int j = 0; j < 2; ++j) - { - int* const dest = chans[j]; + for (int j = 0; j < 2; ++j) + { + int* const dest = chans[j]; - if (dest != 0) - { - const float* const src = channels [j] + startSample; + if (dest != 0) + { + const float* const src = channels [j] + startSample; - for (int i = 0; i < numSamples; ++i) - { - const double samp = src[i]; + for (int i = 0; i < numSamples; ++i) + { + const double samp = src[i]; - if (samp <= -1.0) - dest[i] = INT_MIN; - else if (samp >= 1.0) - dest[i] = INT_MAX; - else - dest[i] = roundDoubleToInt (INT_MAX * samp); - } - } - } + if (samp <= -1.0) + dest[i] = INT_MIN; + else if (samp >= 1.0) + dest[i] = INT_MAX; + else + dest[i] = roundToInt (INT_MAX * samp); + } + } + } - writer->write ((const int**) chans, numSamples); - } - } + writer->write ((const int**) chans, numSamples); + } + } } END_JUCE_NAMESPACE @@ -26555,17 +26296,17 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE IIRFilter::IIRFilter() throw() - : active (false) + : active (false) { - reset(); + reset(); } IIRFilter::IIRFilter (const IIRFilter& other) throw() - : active (other.active) + : active (other.active) { - const ScopedLock sl (other.processLock); - memcpy (coefficients, other.coefficients, sizeof (coefficients)); - reset(); + const ScopedLock sl (other.processLock); + memcpy (coefficients, other.coefficients, sizeof (coefficients)); + reset(); } IIRFilter::~IIRFilter() throw() @@ -26574,209 +26315,209 @@ IIRFilter::~IIRFilter() throw() void IIRFilter::reset() throw() { - const ScopedLock sl (processLock); + const ScopedLock sl (processLock); - x1 = 0; - x2 = 0; - y1 = 0; - y2 = 0; + x1 = 0; + x2 = 0; + y1 = 0; + y2 = 0; } float IIRFilter::processSingleSampleRaw (const float in) throw() { - float out = coefficients[0] * in - + coefficients[1] * x1 - + coefficients[2] * x2 - - coefficients[4] * y1 - - coefficients[5] * y2; + float out = coefficients[0] * in + + coefficients[1] * x1 + + coefficients[2] * x2 + - coefficients[4] * y1 + - coefficients[5] * y2; #if JUCE_INTEL - if (! (out < -1.0e-8 || out > 1.0e-8)) - out = 0; + if (! (out < -1.0e-8 || out > 1.0e-8)) + out = 0; #endif - x2 = x1; - x1 = in; - y2 = y1; - y1 = out; + x2 = x1; + x1 = in; + y2 = y1; + y1 = out; - return out; + return out; } void IIRFilter::processSamples (float* const samples, - const int numSamples) throw() + const int numSamples) throw() { - const ScopedLock sl (processLock); + const ScopedLock sl (processLock); - if (active) - { - for (int i = 0; i < numSamples; ++i) - { - const float in = samples[i]; + if (active) + { + for (int i = 0; i < numSamples; ++i) + { + const float in = samples[i]; - float out = coefficients[0] * in - + coefficients[1] * x1 - + coefficients[2] * x2 - - coefficients[4] * y1 - - coefficients[5] * y2; + float out = coefficients[0] * in + + coefficients[1] * x1 + + coefficients[2] * x2 + - coefficients[4] * y1 + - coefficients[5] * y2; #if JUCE_INTEL - if (! (out < -1.0e-8 || out > 1.0e-8)) - out = 0; + if (! (out < -1.0e-8 || out > 1.0e-8)) + out = 0; #endif - x2 = x1; - x1 = in; - y2 = y1; - y1 = out; + x2 = x1; + x1 = in; + y2 = y1; + y1 = out; - samples[i] = out; - } - } + samples[i] = out; + } + } } void IIRFilter::makeLowPass (const double sampleRate, - const double frequency) throw() + const double frequency) throw() { - jassert (sampleRate > 0); + jassert (sampleRate > 0); - const double n = 1.0 / tan (double_Pi * frequency / sampleRate); - const double nSquared = n * n; - const double c1 = 1.0 / (1.0 + sqrt (2.0) * n + nSquared); + const double n = 1.0 / tan (double_Pi * frequency / sampleRate); + const double nSquared = n * n; + const double c1 = 1.0 / (1.0 + sqrt (2.0) * n + nSquared); - setCoefficients (c1, - c1 * 2.0f, - c1, - 1.0, - c1 * 2.0 * (1.0 - nSquared), - c1 * (1.0 - sqrt (2.0) * n + nSquared)); + setCoefficients (c1, + c1 * 2.0f, + c1, + 1.0, + c1 * 2.0 * (1.0 - nSquared), + c1 * (1.0 - sqrt (2.0) * n + nSquared)); } void IIRFilter::makeHighPass (const double sampleRate, - const double frequency) throw() + const double frequency) throw() { - const double n = tan (double_Pi * frequency / sampleRate); - const double nSquared = n * n; - const double c1 = 1.0 / (1.0 + sqrt (2.0) * n + nSquared); + const double n = tan (double_Pi * frequency / sampleRate); + const double nSquared = n * n; + const double c1 = 1.0 / (1.0 + sqrt (2.0) * n + nSquared); - setCoefficients (c1, - c1 * -2.0f, - c1, - 1.0, - c1 * 2.0 * (nSquared - 1.0), - c1 * (1.0 - sqrt (2.0) * n + nSquared)); + setCoefficients (c1, + c1 * -2.0f, + c1, + 1.0, + c1 * 2.0 * (nSquared - 1.0), + c1 * (1.0 - sqrt (2.0) * n + nSquared)); } void IIRFilter::makeLowShelf (const double sampleRate, - const double cutOffFrequency, - const double Q, - const float gainFactor) throw() + const double cutOffFrequency, + const double Q, + const float gainFactor) throw() { - jassert (sampleRate > 0); - jassert (Q > 0); + jassert (sampleRate > 0); + jassert (Q > 0); - const double A = jmax (0.0f, gainFactor); - const double aminus1 = A - 1.0; - const double aplus1 = A + 1.0; - const double omega = (double_Pi * 2.0 * jmax (cutOffFrequency, 2.0)) / sampleRate; - const double coso = cos (omega); - const double beta = sin (omega) * sqrt (A) / Q; - const double aminus1TimesCoso = aminus1 * coso; + const double A = jmax (0.0f, gainFactor); + const double aminus1 = A - 1.0; + const double aplus1 = A + 1.0; + const double omega = (double_Pi * 2.0 * jmax (cutOffFrequency, 2.0)) / sampleRate; + const double coso = cos (omega); + const double beta = sin (omega) * sqrt (A) / Q; + const double aminus1TimesCoso = aminus1 * coso; - setCoefficients (A * (aplus1 - aminus1TimesCoso + beta), - A * 2.0 * (aminus1 - aplus1 * coso), - A * (aplus1 - aminus1TimesCoso - beta), - aplus1 + aminus1TimesCoso + beta, - -2.0 * (aminus1 + aplus1 * coso), - aplus1 + aminus1TimesCoso - beta); + setCoefficients (A * (aplus1 - aminus1TimesCoso + beta), + A * 2.0 * (aminus1 - aplus1 * coso), + A * (aplus1 - aminus1TimesCoso - beta), + aplus1 + aminus1TimesCoso + beta, + -2.0 * (aminus1 + aplus1 * coso), + aplus1 + aminus1TimesCoso - beta); } void IIRFilter::makeHighShelf (const double sampleRate, - const double cutOffFrequency, - const double Q, - const float gainFactor) throw() + const double cutOffFrequency, + const double Q, + const float gainFactor) throw() { - jassert (sampleRate > 0); - jassert (Q > 0); + jassert (sampleRate > 0); + jassert (Q > 0); - const double A = jmax (0.0f, gainFactor); - const double aminus1 = A - 1.0; - const double aplus1 = A + 1.0; - const double omega = (double_Pi * 2.0 * jmax (cutOffFrequency, 2.0)) / sampleRate; - const double coso = cos (omega); - const double beta = sin (omega) * sqrt (A) / Q; - const double aminus1TimesCoso = aminus1 * coso; + const double A = jmax (0.0f, gainFactor); + const double aminus1 = A - 1.0; + const double aplus1 = A + 1.0; + const double omega = (double_Pi * 2.0 * jmax (cutOffFrequency, 2.0)) / sampleRate; + const double coso = cos (omega); + const double beta = sin (omega) * sqrt (A) / Q; + const double aminus1TimesCoso = aminus1 * coso; - setCoefficients (A * (aplus1 + aminus1TimesCoso + beta), - A * -2.0 * (aminus1 + aplus1 * coso), - A * (aplus1 + aminus1TimesCoso - beta), - aplus1 - aminus1TimesCoso + beta, - 2.0 * (aminus1 - aplus1 * coso), - aplus1 - aminus1TimesCoso - beta); + setCoefficients (A * (aplus1 + aminus1TimesCoso + beta), + A * -2.0 * (aminus1 + aplus1 * coso), + A * (aplus1 + aminus1TimesCoso - beta), + aplus1 - aminus1TimesCoso + beta, + 2.0 * (aminus1 - aplus1 * coso), + aplus1 - aminus1TimesCoso - beta); } void IIRFilter::makeBandPass (const double sampleRate, - const double centreFrequency, - const double Q, - const float gainFactor) throw() + const double centreFrequency, + const double Q, + const float gainFactor) throw() { - jassert (sampleRate > 0); - jassert (Q > 0); + jassert (sampleRate > 0); + jassert (Q > 0); - const double A = jmax (0.0f, gainFactor); - const double omega = (double_Pi * 2.0 * jmax (centreFrequency, 2.0)) / sampleRate; - const double alpha = 0.5 * sin (omega) / Q; - const double c2 = -2.0 * cos (omega); - const double alphaTimesA = alpha * A; - const double alphaOverA = alpha / A; + const double A = jmax (0.0f, gainFactor); + const double omega = (double_Pi * 2.0 * jmax (centreFrequency, 2.0)) / sampleRate; + const double alpha = 0.5 * sin (omega) / Q; + const double c2 = -2.0 * cos (omega); + const double alphaTimesA = alpha * A; + const double alphaOverA = alpha / A; - setCoefficients (1.0 + alphaTimesA, - c2, - 1.0 - alphaTimesA, - 1.0 + alphaOverA, - c2, - 1.0 - alphaOverA); + setCoefficients (1.0 + alphaTimesA, + c2, + 1.0 - alphaTimesA, + 1.0 + alphaOverA, + c2, + 1.0 - alphaOverA); } void IIRFilter::makeInactive() throw() { - const ScopedLock sl (processLock); - active = false; + const ScopedLock sl (processLock); + active = false; } void IIRFilter::copyCoefficientsFrom (const IIRFilter& other) throw() { - const ScopedLock sl (processLock); + const ScopedLock sl (processLock); - memcpy (coefficients, other.coefficients, sizeof (coefficients)); - active = other.active; + memcpy (coefficients, other.coefficients, sizeof (coefficients)); + active = other.active; } void IIRFilter::setCoefficients (double c1, - double c2, - double c3, - double c4, - double c5, - double c6) throw() + double c2, + double c3, + double c4, + double c5, + double c6) throw() { - const double a = 1.0 / c4; + const double a = 1.0 / c4; - c1 *= a; - c2 *= a; - c3 *= a; - c5 *= a; - c6 *= a; + c1 *= a; + c2 *= a; + c3 *= a; + c5 *= a; + c6 *= a; - const ScopedLock sl (processLock); + const ScopedLock sl (processLock); - coefficients[0] = (float) c1; - coefficients[1] = (float) c2; - coefficients[2] = (float) c3; - coefficients[3] = (float) c4; - coefficients[4] = (float) c5; - coefficients[5] = (float) c6; + coefficients[0] = (float) c1; + coefficients[1] = (float) c2; + coefficients[2] = (float) c3; + coefficients[3] = (float) c4; + coefficients[4] = (float) c5; + coefficients[5] = (float) c6; - active = true; + active = true; } END_JUCE_NAMESPACE @@ -26787,45 +26528,37 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MidiBuffer::MidiBuffer() throw() - : data (32), - bytesUsed (0) + : bytesUsed (0) { } MidiBuffer::MidiBuffer (const MidiMessage& message) throw() - : data (32), - bytesUsed (0) + : bytesUsed (0) { - addEvent (message, 0); + addEvent (message, 0); } MidiBuffer::MidiBuffer (const MidiBuffer& other) throw() - : data (32), - bytesUsed (other.bytesUsed) + : data (other.data), + bytesUsed (other.bytesUsed) { - data.ensureAllocatedSize (bytesUsed); - memcpy (data.elements, other.data.elements, bytesUsed); } const MidiBuffer& MidiBuffer::operator= (const MidiBuffer& other) throw() { - if (this != &other) - { - bytesUsed = other.bytesUsed; - data.ensureAllocatedSize (bytesUsed); + if (this != &other) + { + bytesUsed = other.bytesUsed; + data = other.data; + } - if (bytesUsed > 0) - memcpy (data.elements, other.data.elements, bytesUsed); - } - - return *this; + return *this; } void MidiBuffer::swap (MidiBuffer& other) { - swapVariables (data.elements, other.data.elements); - swapVariables (data.numAllocated, other.data.numAllocated); - swapVariables (bytesUsed, other.bytesUsed); + data.swapWith (other.data); + swapVariables (bytesUsed, other.bytesUsed); } MidiBuffer::~MidiBuffer() throw() @@ -26834,171 +26567,172 @@ MidiBuffer::~MidiBuffer() throw() void MidiBuffer::clear() throw() { - bytesUsed = 0; + bytesUsed = 0; } void MidiBuffer::clear (const int startSample, - const int numSamples) throw() + const int numSamples) throw() { - uint8* const start = findEventAfter (data.elements, startSample - 1); - uint8* const end = findEventAfter (start, startSample + numSamples - 1); + uint8* const start = findEventAfter (data, startSample - 1); + uint8* const end = findEventAfter (start, startSample + numSamples - 1); - if (end > start) - { - const size_t bytesToMove = (size_t) (bytesUsed - (end - data.elements)); + if (end > start) + { + const size_t bytesToMove = (size_t) (bytesUsed - (end - (uint8*) data.getData())); - if (bytesToMove > 0) - memmove (start, end, bytesToMove); + if (bytesToMove > 0) + memmove (start, end, bytesToMove); - bytesUsed -= (int) (end - start); - } + bytesUsed -= (int) (end - start); + } } void MidiBuffer::addEvent (const MidiMessage& m, - const int sampleNumber) throw() + const int sampleNumber) throw() { - addEvent (m.getRawData(), m.getRawDataSize(), sampleNumber); + addEvent (m.getRawData(), m.getRawDataSize(), sampleNumber); } static int findActualEventLength (const uint8* const data, - const int maxBytes) throw() + const int maxBytes) throw() { - unsigned int byte = (unsigned int) *data; + unsigned int byte = (unsigned int) *data; - int size = 0; + int size = 0; - if (byte == 0xf0 || byte == 0xf7) - { - const uint8* d = data + 1; + if (byte == 0xf0 || byte == 0xf7) + { + const uint8* d = data + 1; - while (d < data + maxBytes) - if (*d++ == 0xf7) - break; + while (d < data + maxBytes) + if (*d++ == 0xf7) + break; - size = (int) (d - data); - } - else if (byte == 0xff) - { - int n; - const int bytesLeft = MidiMessage::readVariableLengthVal (data + 1, n); - size = jmin (maxBytes, n + 2 + bytesLeft); - } - else if (byte >= 0x80) - { - size = jmin (maxBytes, MidiMessage::getMessageLengthFromFirstByte ((uint8) byte)); - } + size = (int) (d - data); + } + else if (byte == 0xff) + { + int n; + const int bytesLeft = MidiMessage::readVariableLengthVal (data + 1, n); + size = jmin (maxBytes, n + 2 + bytesLeft); + } + else if (byte >= 0x80) + { + size = jmin (maxBytes, MidiMessage::getMessageLengthFromFirstByte ((uint8) byte)); + } - return size; + return size; } void MidiBuffer::addEvent (const uint8* const newData, - const int maxBytes, - const int sampleNumber) throw() + const int maxBytes, + const int sampleNumber) throw() { - const int numBytes = findActualEventLength (newData, maxBytes); + const int numBytes = findActualEventLength (newData, maxBytes); - if (numBytes > 0) - { - data.ensureAllocatedSize (bytesUsed + numBytes + 6); + if (numBytes > 0) + { + int spaceNeeded = bytesUsed + numBytes + 6; + data.ensureSize ((spaceNeeded + spaceNeeded / 2 + 8) & ~7); - uint8* d = findEventAfter (data.elements, sampleNumber); - const size_t bytesToMove = (size_t) (bytesUsed - (d - data.elements)); + uint8* d = findEventAfter ((uint8*) data.getData(), sampleNumber); + const size_t bytesToMove = (size_t) (bytesUsed - (d - (uint8*) data.getData())); - if (bytesToMove > 0) - memmove (d + numBytes + 6, - d, - bytesToMove); + if (bytesToMove > 0) + memmove (d + numBytes + 6, + d, + bytesToMove); - *(int*) d = sampleNumber; - d += 4; - *(uint16*) d = (uint16) numBytes; - d += 2; + *(int*) d = sampleNumber; + d += 4; + *(uint16*) d = (uint16) numBytes; + d += 2; - memcpy (d, newData, numBytes); + memcpy (d, newData, numBytes); - bytesUsed += numBytes + 6; - } + bytesUsed += numBytes + 6; + } } void MidiBuffer::addEvents (const MidiBuffer& otherBuffer, - const int startSample, - const int numSamples, - const int sampleDeltaToAdd) throw() + const int startSample, + const int numSamples, + const int sampleDeltaToAdd) throw() { - Iterator i (otherBuffer); - i.setNextSamplePosition (startSample); + Iterator i (otherBuffer); + i.setNextSamplePosition (startSample); - const uint8* data; - int size, position; + const uint8* eventData; + int eventSize, position; - while (i.getNextEvent (data, size, position) - && (position < startSample + numSamples || numSamples < 0)) - { - addEvent (data, size, position + sampleDeltaToAdd); - } + while (i.getNextEvent (eventData, eventSize, position) + && (position < startSample + numSamples || numSamples < 0)) + { + addEvent (eventData, eventSize, position + sampleDeltaToAdd); + } } bool MidiBuffer::isEmpty() const throw() { - return bytesUsed == 0; + return bytesUsed == 0; } int MidiBuffer::getNumEvents() const throw() { - int n = 0; - const uint8* d = data.elements; - const uint8* const end = data.elements + bytesUsed; + int n = 0; + const uint8* d = (uint8*) data.getData(); + const uint8* const end = d + bytesUsed; - while (d < end) - { - d += 4; - d += 2 + *(const uint16*) d; - ++n; - } + while (d < end) + { + d += 4; + d += 2 + *(const uint16*) d; + ++n; + } - return n; + return n; } int MidiBuffer::getFirstEventTime() const throw() { - return (bytesUsed > 0) ? *(const int*) data.elements : 0; + return (bytesUsed > 0) ? *(const int*) data.getData() : 0; } int MidiBuffer::getLastEventTime() const throw() { - if (bytesUsed == 0) - return 0; + if (bytesUsed == 0) + return 0; - const uint8* d = data.elements; - const uint8* const endData = d + bytesUsed; + const uint8* d = (uint8*) data.getData(); + const uint8* const endData = d + bytesUsed; - for (;;) - { - const uint8* nextOne = d + 6 + * (const uint16*) (d + 4); + for (;;) + { + const uint8* nextOne = d + 6 + * (const uint16*) (d + 4); - if (nextOne >= endData) - return *(const int*) d; + if (nextOne >= endData) + return *(const int*) d; - d = nextOne; - } + d = nextOne; + } } uint8* MidiBuffer::findEventAfter (uint8* d, const int samplePosition) const throw() { - const uint8* const endData = data.elements + bytesUsed; + const uint8* const endData = ((uint8*) data.getData()) + bytesUsed; - while (d < endData && *(int*) d <= samplePosition) - { - d += 4; - d += 2 + *(uint16*) d; - } + while (d < endData && *(int*) d <= samplePosition) + { + d += 4; + d += 2 + *(uint16*) d; + } - return d; + return d; } MidiBuffer::Iterator::Iterator (const MidiBuffer& buffer_) throw() - : buffer (buffer_), - data (buffer_.data.elements) + : buffer (buffer_), + data ((uint8*) buffer_.data.getData()) { } @@ -27008,47 +26742,47 @@ MidiBuffer::Iterator::~Iterator() throw() void MidiBuffer::Iterator::setNextSamplePosition (const int samplePosition) throw() { - data = buffer.data.elements; - const uint8* dataEnd = buffer.data.elements + buffer.bytesUsed; + data = buffer.data; + const uint8* dataEnd = ((uint8*) buffer.data.getData()) + buffer.bytesUsed; - while (data < dataEnd && *(int*) data < samplePosition) - { - data += 4; - data += 2 + *(uint16*) data; - } + while (data < dataEnd && *(int*) data < samplePosition) + { + data += 4; + data += 2 + *(uint16*) data; + } } bool MidiBuffer::Iterator::getNextEvent (const uint8* &midiData, - int& numBytes, - int& samplePosition) throw() + int& numBytes, + int& samplePosition) throw() { - if (data >= buffer.data.elements + buffer.bytesUsed) - return false; + if (data >= ((uint8*) buffer.data.getData()) + buffer.bytesUsed) + return false; - samplePosition = *(int*) data; - data += 4; - numBytes = *(uint16*) data; - data += 2; - midiData = data; - data += numBytes; + samplePosition = *(int*) data; + data += 4; + numBytes = *(uint16*) data; + data += 2; + midiData = data; + data += numBytes; - return true; + return true; } bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, - int& samplePosition) throw() + int& samplePosition) throw() { - if (data >= buffer.data.elements + buffer.bytesUsed) - return false; + if (data >= ((uint8*) buffer.data.getData()) + buffer.bytesUsed) + return false; - samplePosition = *(int*) data; - data += 4; - const int numBytes = *(uint16*) data; - data += 2; - result = MidiMessage (data, numBytes, samplePosition); - data += numBytes; + samplePosition = *(int*) data; + data += 4; + const int numBytes = *(uint16*) data; + data += 2; + result = MidiMessage (data, numBytes, samplePosition); + data += numBytes; - return true; + return true; } END_JUCE_NAMESPACE @@ -27060,13 +26794,13 @@ BEGIN_JUCE_NAMESPACE struct TempoInfo { - double bpm, timestamp; + double bpm, timestamp; }; struct TimeSigInfo { - int numerator, denominator; - double timestamp; + int numerator, denominator; + double timestamp; }; MidiFile::MidiFile() throw() @@ -27076,408 +26810,408 @@ MidiFile::MidiFile() throw() MidiFile::~MidiFile() throw() { - clear(); + clear(); } void MidiFile::clear() throw() { - tracks.clear(); + tracks.clear(); } int MidiFile::getNumTracks() const throw() { - return tracks.size(); + return tracks.size(); } const MidiMessageSequence* MidiFile::getTrack (const int index) const throw() { - return tracks [index]; + return tracks [index]; } void MidiFile::addTrack (const MidiMessageSequence& trackSequence) throw() { - tracks.add (new MidiMessageSequence (trackSequence)); + tracks.add (new MidiMessageSequence (trackSequence)); } short MidiFile::getTimeFormat() const throw() { - return timeFormat; + return timeFormat; } void MidiFile::setTicksPerQuarterNote (const int ticks) throw() { - timeFormat = (short)ticks; + timeFormat = (short)ticks; } void MidiFile::setSmpteTimeFormat (const int framesPerSecond, - const int subframeResolution) throw() + const int subframeResolution) throw() { - timeFormat = (short) (((-framesPerSecond) << 8) | subframeResolution); + timeFormat = (short) (((-framesPerSecond) << 8) | subframeResolution); } void MidiFile::findAllTempoEvents (MidiMessageSequence& tempoChangeEvents) const { - for (int i = tracks.size(); --i >= 0;) - { - const int numEvents = tracks.getUnchecked(i)->getNumEvents(); + for (int i = tracks.size(); --i >= 0;) + { + const int numEvents = tracks.getUnchecked(i)->getNumEvents(); - for (int j = 0; j < numEvents; ++j) - { - const MidiMessage& m = tracks.getUnchecked(i)->getEventPointer (j)->message; + for (int j = 0; j < numEvents; ++j) + { + const MidiMessage& m = tracks.getUnchecked(i)->getEventPointer (j)->message; - if (m.isTempoMetaEvent()) - tempoChangeEvents.addEvent (m); - } - } + if (m.isTempoMetaEvent()) + tempoChangeEvents.addEvent (m); + } + } } void MidiFile::findAllTimeSigEvents (MidiMessageSequence& timeSigEvents) const { - for (int i = tracks.size(); --i >= 0;) - { - const int numEvents = tracks.getUnchecked(i)->getNumEvents(); + for (int i = tracks.size(); --i >= 0;) + { + const int numEvents = tracks.getUnchecked(i)->getNumEvents(); - for (int j = 0; j < numEvents; ++j) - { - const MidiMessage& m = tracks.getUnchecked(i)->getEventPointer (j)->message; + for (int j = 0; j < numEvents; ++j) + { + const MidiMessage& m = tracks.getUnchecked(i)->getEventPointer (j)->message; - if (m.isTimeSignatureMetaEvent()) - timeSigEvents.addEvent (m); - } - } + if (m.isTimeSignatureMetaEvent()) + timeSigEvents.addEvent (m); + } + } } double MidiFile::getLastTimestamp() const { - double t = 0.0; + double t = 0.0; - for (int i = tracks.size(); --i >= 0;) - t = jmax (t, tracks.getUnchecked(i)->getEndTime()); + for (int i = tracks.size(); --i >= 0;) + t = jmax (t, tracks.getUnchecked(i)->getEndTime()); - return t; + return t; } static bool parseMidiHeader (const char* &data, - short& timeFormat, - short& fileType, - short& numberOfTracks) + short& timeFormat, + short& fileType, + short& numberOfTracks) { - unsigned int ch = (int) ByteOrder::bigEndianInt (data); - data += 4; + unsigned int ch = (int) ByteOrder::bigEndianInt (data); + data += 4; - if (ch != ByteOrder::bigEndianInt ("MThd")) - { - bool ok = false; + if (ch != ByteOrder::bigEndianInt ("MThd")) + { + bool ok = false; - if (ch == ByteOrder::bigEndianInt ("RIFF")) - { - for (int i = 0; i < 8; ++i) - { - ch = ByteOrder::bigEndianInt (data); - data += 4; + if (ch == ByteOrder::bigEndianInt ("RIFF")) + { + for (int i = 0; i < 8; ++i) + { + ch = ByteOrder::bigEndianInt (data); + data += 4; - if (ch == ByteOrder::bigEndianInt ("MThd")) - { - ok = true; - break; - } - } - } + if (ch == ByteOrder::bigEndianInt ("MThd")) + { + ok = true; + break; + } + } + } - if (! ok) - return false; - } + if (! ok) + return false; + } - unsigned int bytesRemaining = ByteOrder::bigEndianInt (data); - data += 4; - fileType = (short) ByteOrder::bigEndianShort (data); - data += 2; - numberOfTracks = (short) ByteOrder::bigEndianShort (data); - data += 2; - timeFormat = (short) ByteOrder::bigEndianShort (data); - data += 2; - bytesRemaining -= 6; - data += bytesRemaining; + unsigned int bytesRemaining = ByteOrder::bigEndianInt (data); + data += 4; + fileType = (short) ByteOrder::bigEndianShort (data); + data += 2; + numberOfTracks = (short) ByteOrder::bigEndianShort (data); + data += 2; + timeFormat = (short) ByteOrder::bigEndianShort (data); + data += 2; + bytesRemaining -= 6; + data += bytesRemaining; - return true; + return true; } bool MidiFile::readFrom (InputStream& sourceStream) { - clear(); - MemoryBlock data; + clear(); + MemoryBlock data; - const int maxSensibleMidiFileSize = 2 * 1024 * 1024; + const int maxSensibleMidiFileSize = 2 * 1024 * 1024; - // (put a sanity-check on the file size, as midi files are generally small) - if (sourceStream.readIntoMemoryBlock (data, maxSensibleMidiFileSize)) - { - int size = data.getSize(); - const char* d = (char*) data.getData(); - short fileType, expectedTracks; + // (put a sanity-check on the file size, as midi files are generally small) + if (sourceStream.readIntoMemoryBlock (data, maxSensibleMidiFileSize)) + { + size_t size = data.getSize(); + const char* d = (char*) data.getData(); + short fileType, expectedTracks; - if (size > 16 && parseMidiHeader (d, timeFormat, fileType, expectedTracks)) - { - size -= (int) (d - (char*) data.getData()); + if (size > 16 && parseMidiHeader (d, timeFormat, fileType, expectedTracks)) + { + size -= (int) (d - (char*) data.getData()); - int track = 0; + int track = 0; - while (size > 0 && track < expectedTracks) - { - const int chunkType = (int) ByteOrder::bigEndianInt (d); - d += 4; - const int chunkSize = (int) ByteOrder::bigEndianInt (d); - d += 4; + while (size > 0 && track < expectedTracks) + { + const int chunkType = (int) ByteOrder::bigEndianInt (d); + d += 4; + const int chunkSize = (int) ByteOrder::bigEndianInt (d); + d += 4; - if (chunkSize <= 0) - break; + if (chunkSize <= 0) + break; - if (size < 0) - return false; + if (size < 0) + return false; - if (chunkType == (int) ByteOrder::bigEndianInt ("MTrk")) - { - readNextTrack (d, chunkSize); - } + if (chunkType == (int) ByteOrder::bigEndianInt ("MTrk")) + { + readNextTrack (d, chunkSize); + } - size -= chunkSize + 8; - d += chunkSize; - ++track; - } + size -= chunkSize + 8; + d += chunkSize; + ++track; + } - return true; - } - } + return true; + } + } - return false; + return false; } // a comparator that puts all the note-offs before note-ons that have the same time int MidiFile::compareElements (const MidiMessageSequence::MidiEventHolder* const first, - const MidiMessageSequence::MidiEventHolder* const second) throw() + const MidiMessageSequence::MidiEventHolder* const second) throw() { - const double diff = (first->message.getTimeStamp() - second->message.getTimeStamp()); + const double diff = (first->message.getTimeStamp() - second->message.getTimeStamp()); - if (diff == 0) - { - if (first->message.isNoteOff() && second->message.isNoteOn()) - return -1; - else if (first->message.isNoteOn() && second->message.isNoteOff()) - return 1; - else - return 0; - } - else - { - return (diff > 0) ? 1 : -1; - } + if (diff == 0) + { + if (first->message.isNoteOff() && second->message.isNoteOn()) + return -1; + else if (first->message.isNoteOn() && second->message.isNoteOff()) + return 1; + else + return 0; + } + else + { + return (diff > 0) ? 1 : -1; + } } void MidiFile::readNextTrack (const char* data, int size) { - double time = 0; - char lastStatusByte = 0; + double time = 0; + char lastStatusByte = 0; - MidiMessageSequence result; + MidiMessageSequence result; - while (size > 0) - { - int bytesUsed; - const int delay = MidiMessage::readVariableLengthVal ((const uint8*) data, bytesUsed); - data += bytesUsed; - size -= bytesUsed; - time += delay; + while (size > 0) + { + int bytesUsed; + const int delay = MidiMessage::readVariableLengthVal ((const uint8*) data, bytesUsed); + data += bytesUsed; + size -= bytesUsed; + time += delay; - int messSize = 0; - const MidiMessage mm ((const uint8*) data, size, messSize, lastStatusByte, time); + int messSize = 0; + const MidiMessage mm ((const uint8*) data, size, messSize, lastStatusByte, time); - if (messSize <= 0) - break; + if (messSize <= 0) + break; - size -= messSize; - data += messSize; + size -= messSize; + data += messSize; - result.addEvent (mm); + result.addEvent (mm); - const char firstByte = *(mm.getRawData()); - if ((firstByte & 0xf0) != 0xf0) - lastStatusByte = firstByte; - } + const char firstByte = *(mm.getRawData()); + if ((firstByte & 0xf0) != 0xf0) + lastStatusByte = firstByte; + } - // use a sort that puts all the note-offs before note-ons that have the same time - result.list.sort (*this, true); + // use a sort that puts all the note-offs before note-ons that have the same time + result.list.sort (*this, true); - result.updateMatchedPairs(); + result.updateMatchedPairs(); - addTrack (result); + addTrack (result); } static double convertTicksToSeconds (const double time, - const MidiMessageSequence& tempoEvents, - const int timeFormat) + const MidiMessageSequence& tempoEvents, + const int timeFormat) { - if (timeFormat > 0) - { - int numer = 4, denom = 4; - double tempoTime = 0.0, correctedTempoTime = 0.0; - const double tickLen = 1.0 / (timeFormat & 0x7fff); - double secsPerTick = 0.5 * tickLen; - const int numEvents = tempoEvents.getNumEvents(); + if (timeFormat > 0) + { + int numer = 4, denom = 4; + double tempoTime = 0.0, correctedTempoTime = 0.0; + const double tickLen = 1.0 / (timeFormat & 0x7fff); + double secsPerTick = 0.5 * tickLen; + const int numEvents = tempoEvents.getNumEvents(); - for (int i = 0; i < numEvents; ++i) - { - const MidiMessage& m = tempoEvents.getEventPointer(i)->message; + for (int i = 0; i < numEvents; ++i) + { + const MidiMessage& m = tempoEvents.getEventPointer(i)->message; - if (time <= m.getTimeStamp()) - break; + if (time <= m.getTimeStamp()) + break; - if (timeFormat > 0) - { - correctedTempoTime = correctedTempoTime - + (m.getTimeStamp() - tempoTime) * secsPerTick; - } - else - { - correctedTempoTime = tickLen * m.getTimeStamp() / (((timeFormat & 0x7fff) >> 8) * (timeFormat & 0xff)); - } + if (timeFormat > 0) + { + correctedTempoTime = correctedTempoTime + + (m.getTimeStamp() - tempoTime) * secsPerTick; + } + else + { + correctedTempoTime = tickLen * m.getTimeStamp() / (((timeFormat & 0x7fff) >> 8) * (timeFormat & 0xff)); + } - tempoTime = m.getTimeStamp(); + tempoTime = m.getTimeStamp(); - if (m.isTempoMetaEvent()) - secsPerTick = tickLen * m.getTempoSecondsPerQuarterNote(); - else if (m.isTimeSignatureMetaEvent()) - m.getTimeSignatureInfo (numer, denom); + if (m.isTempoMetaEvent()) + secsPerTick = tickLen * m.getTempoSecondsPerQuarterNote(); + else if (m.isTimeSignatureMetaEvent()) + m.getTimeSignatureInfo (numer, denom); - while (i + 1 < numEvents) - { - const MidiMessage& m2 = tempoEvents.getEventPointer(i + 1)->message; - if (m2.getTimeStamp() == tempoTime) - { - ++i; + while (i + 1 < numEvents) + { + const MidiMessage& m2 = tempoEvents.getEventPointer(i + 1)->message; + if (m2.getTimeStamp() == tempoTime) + { + ++i; - if (m2.isTempoMetaEvent()) - secsPerTick = tickLen * m2.getTempoSecondsPerQuarterNote(); - else if (m2.isTimeSignatureMetaEvent()) - m2.getTimeSignatureInfo (numer, denom); - } - else - { - break; - } - } + if (m2.isTempoMetaEvent()) + secsPerTick = tickLen * m2.getTempoSecondsPerQuarterNote(); + else if (m2.isTimeSignatureMetaEvent()) + m2.getTimeSignatureInfo (numer, denom); + } + else + { + break; + } + } - } + } - return correctedTempoTime + (time - tempoTime) * secsPerTick; - } - else - { - return time / (((timeFormat & 0x7fff) >> 8) * (timeFormat & 0xff)); - } + return correctedTempoTime + (time - tempoTime) * secsPerTick; + } + else + { + return time / (((timeFormat & 0x7fff) >> 8) * (timeFormat & 0xff)); + } } void MidiFile::convertTimestampTicksToSeconds() { - MidiMessageSequence tempoEvents; - findAllTempoEvents (tempoEvents); - findAllTimeSigEvents (tempoEvents); + MidiMessageSequence tempoEvents; + findAllTempoEvents (tempoEvents); + findAllTimeSigEvents (tempoEvents); - for (int i = 0; i < tracks.size(); ++i) - { - MidiMessageSequence& ms = *tracks.getUnchecked(i); + for (int i = 0; i < tracks.size(); ++i) + { + MidiMessageSequence& ms = *tracks.getUnchecked(i); - for (int j = ms.getNumEvents(); --j >= 0;) - { - MidiMessage& m = ms.getEventPointer(j)->message; + for (int j = ms.getNumEvents(); --j >= 0;) + { + MidiMessage& m = ms.getEventPointer(j)->message; - m.setTimeStamp (convertTicksToSeconds (m.getTimeStamp(), - tempoEvents, - timeFormat)); - } - } + m.setTimeStamp (convertTicksToSeconds (m.getTimeStamp(), + tempoEvents, + timeFormat)); + } + } } static void writeVariableLengthInt (OutputStream& out, unsigned int v) { - unsigned int buffer = v & 0x7F; + unsigned int buffer = v & 0x7F; - while ((v >>= 7) != 0) - { - buffer <<= 8; - buffer |= ((v & 0x7F) | 0x80); - } + while ((v >>= 7) != 0) + { + buffer <<= 8; + buffer |= ((v & 0x7F) | 0x80); + } - for (;;) - { - out.writeByte ((char) buffer); + for (;;) + { + out.writeByte ((char) buffer); - if (buffer & 0x80) - buffer >>= 8; - else - break; - } + if (buffer & 0x80) + buffer >>= 8; + else + break; + } } bool MidiFile::writeTo (OutputStream& out) { - out.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MThd")); - out.writeIntBigEndian (6); - out.writeShortBigEndian (1); // type - out.writeShortBigEndian ((short) tracks.size()); - out.writeShortBigEndian (timeFormat); + out.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MThd")); + out.writeIntBigEndian (6); + out.writeShortBigEndian (1); // type + out.writeShortBigEndian ((short) tracks.size()); + out.writeShortBigEndian (timeFormat); - for (int i = 0; i < tracks.size(); ++i) - writeTrack (out, i); + for (int i = 0; i < tracks.size(); ++i) + writeTrack (out, i); - out.flush(); + out.flush(); - return true; + return true; } void MidiFile::writeTrack (OutputStream& mainOut, - const int trackNum) + const int trackNum) { - MemoryOutputStream out; + MemoryOutputStream out; - const MidiMessageSequence& ms = *tracks[trackNum]; + const MidiMessageSequence& ms = *tracks[trackNum]; - int lastTick = 0; - char lastStatusByte = 0; + int lastTick = 0; + char lastStatusByte = 0; - for (int i = 0; i < ms.getNumEvents(); ++i) - { - const MidiMessage& mm = ms.getEventPointer(i)->message; + for (int i = 0; i < ms.getNumEvents(); ++i) + { + const MidiMessage& mm = ms.getEventPointer(i)->message; - const int tick = roundDoubleToInt (mm.getTimeStamp()); - const int delta = jmax (0, tick - lastTick); - writeVariableLengthInt (out, delta); - lastTick = tick; + const int tick = roundToInt (mm.getTimeStamp()); + const int delta = jmax (0, tick - lastTick); + writeVariableLengthInt (out, delta); + lastTick = tick; - const char statusByte = *(mm.getRawData()); + const char statusByte = *(mm.getRawData()); - if ((statusByte == lastStatusByte) - && ((statusByte & 0xf0) != 0xf0) - && i > 0 - && mm.getRawDataSize() > 1) - { - out.write (mm.getRawData() + 1, mm.getRawDataSize() - 1); - } - else - { - out.write (mm.getRawData(), mm.getRawDataSize()); - } + if ((statusByte == lastStatusByte) + && ((statusByte & 0xf0) != 0xf0) + && i > 0 + && mm.getRawDataSize() > 1) + { + out.write (mm.getRawData() + 1, mm.getRawDataSize() - 1); + } + else + { + out.write (mm.getRawData(), mm.getRawDataSize()); + } - lastStatusByte = statusByte; - } + lastStatusByte = statusByte; + } - out.writeByte (0); - const MidiMessage m (MidiMessage::endOfTrack()); - out.write (m.getRawData(), - m.getRawDataSize()); + out.writeByte (0); + const MidiMessage m (MidiMessage::endOfTrack()); + out.write (m.getRawData(), + m.getRawDataSize()); - mainOut.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MTrk")); - mainOut.writeIntBigEndian (out.getDataSize()); - mainOut.write (out.getData(), out.getDataSize()); + mainOut.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MTrk")); + mainOut.writeIntBigEndian ((int) out.getDataSize()); + mainOut.write (out.getData(), (int) out.getDataSize()); } END_JUCE_NAMESPACE @@ -27488,9 +27222,8 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MidiKeyboardState::MidiKeyboardState() - : listeners (2) { - zeromem (noteStates, sizeof (noteStates)); + zeromem (noteStates, sizeof (noteStates)); } MidiKeyboardState::~MidiKeyboardState() @@ -27499,153 +27232,153 @@ MidiKeyboardState::~MidiKeyboardState() void MidiKeyboardState::reset() { - const ScopedLock sl (lock); - zeromem (noteStates, sizeof (noteStates)); - eventsToAdd.clear(); + const ScopedLock sl (lock); + zeromem (noteStates, sizeof (noteStates)); + eventsToAdd.clear(); } bool MidiKeyboardState::isNoteOn (const int midiChannel, const int n) const throw() { - jassert (midiChannel >= 0 && midiChannel <= 16); + jassert (midiChannel >= 0 && midiChannel <= 16); - return ((unsigned int) n) < 128 - && (noteStates[n] & (1 << (midiChannel - 1))) != 0; + return ((unsigned int) n) < 128 + && (noteStates[n] & (1 << (midiChannel - 1))) != 0; } bool MidiKeyboardState::isNoteOnForChannels (const int midiChannelMask, const int n) const throw() { - return ((unsigned int) n) < 128 - && (noteStates[n] & midiChannelMask) != 0; + return ((unsigned int) n) < 128 + && (noteStates[n] & midiChannelMask) != 0; } void MidiKeyboardState::noteOn (const int midiChannel, const int midiNoteNumber, const float velocity) { - jassert (midiChannel >= 0 && midiChannel <= 16); - jassert (((unsigned int) midiNoteNumber) < 128); + jassert (midiChannel >= 0 && midiChannel <= 16); + jassert (((unsigned int) midiNoteNumber) < 128); - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (((unsigned int) midiNoteNumber) < 128) - { - const int timeNow = (int) Time::getMillisecondCounter(); - eventsToAdd.addEvent (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity), timeNow); - eventsToAdd.clear (0, timeNow - 500); + if (((unsigned int) midiNoteNumber) < 128) + { + const int timeNow = (int) Time::getMillisecondCounter(); + eventsToAdd.addEvent (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity), timeNow); + eventsToAdd.clear (0, timeNow - 500); - noteOnInternal (midiChannel, midiNoteNumber, velocity); - } + noteOnInternal (midiChannel, midiNoteNumber, velocity); + } } void MidiKeyboardState::noteOnInternal (const int midiChannel, const int midiNoteNumber, const float velocity) { - if (((unsigned int) midiNoteNumber) < 128) - { - noteStates [midiNoteNumber] |= (1 << (midiChannel - 1)); + if (((unsigned int) midiNoteNumber) < 128) + { + noteStates [midiNoteNumber] |= (1 << (midiChannel - 1)); - for (int i = listeners.size(); --i >= 0;) - ((MidiKeyboardStateListener*) listeners.getUnchecked(i)) - ->handleNoteOn (this, midiChannel, midiNoteNumber, velocity); - } + for (int i = listeners.size(); --i >= 0;) + ((MidiKeyboardStateListener*) listeners.getUnchecked(i)) + ->handleNoteOn (this, midiChannel, midiNoteNumber, velocity); + } } void MidiKeyboardState::noteOff (const int midiChannel, const int midiNoteNumber) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (isNoteOn (midiChannel, midiNoteNumber)) - { - const int timeNow = (int) Time::getMillisecondCounter(); - eventsToAdd.addEvent (MidiMessage::noteOff (midiChannel, midiNoteNumber), timeNow); - eventsToAdd.clear (0, timeNow - 500); + if (isNoteOn (midiChannel, midiNoteNumber)) + { + const int timeNow = (int) Time::getMillisecondCounter(); + eventsToAdd.addEvent (MidiMessage::noteOff (midiChannel, midiNoteNumber), timeNow); + eventsToAdd.clear (0, timeNow - 500); - noteOffInternal (midiChannel, midiNoteNumber); - } + noteOffInternal (midiChannel, midiNoteNumber); + } } void MidiKeyboardState::noteOffInternal (const int midiChannel, const int midiNoteNumber) { - if (isNoteOn (midiChannel, midiNoteNumber)) - { - noteStates [midiNoteNumber] &= ~(1 << (midiChannel - 1)); + if (isNoteOn (midiChannel, midiNoteNumber)) + { + noteStates [midiNoteNumber] &= ~(1 << (midiChannel - 1)); - for (int i = listeners.size(); --i >= 0;) - ((MidiKeyboardStateListener*) listeners.getUnchecked(i)) - ->handleNoteOff (this, midiChannel, midiNoteNumber); - } + for (int i = listeners.size(); --i >= 0;) + ((MidiKeyboardStateListener*) listeners.getUnchecked(i)) + ->handleNoteOff (this, midiChannel, midiNoteNumber); + } } void MidiKeyboardState::allNotesOff (const int midiChannel) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (midiChannel <= 0) - { - for (int i = 1; i <= 16; ++i) - allNotesOff (i); - } - else - { - for (int i = 0; i < 128; ++i) - noteOff (midiChannel, i); - } + if (midiChannel <= 0) + { + for (int i = 1; i <= 16; ++i) + allNotesOff (i); + } + else + { + for (int i = 0; i < 128; ++i) + noteOff (midiChannel, i); + } } void MidiKeyboardState::processNextMidiEvent (const MidiMessage& message) { - if (message.isNoteOn()) - { - noteOnInternal (message.getChannel(), message.getNoteNumber(), message.getFloatVelocity()); - } - else if (message.isNoteOff()) - { - noteOffInternal (message.getChannel(), message.getNoteNumber()); - } - else if (message.isAllNotesOff()) - { - for (int i = 0; i < 128; ++i) - noteOffInternal (message.getChannel(), i); - } + if (message.isNoteOn()) + { + noteOnInternal (message.getChannel(), message.getNoteNumber(), message.getFloatVelocity()); + } + else if (message.isNoteOff()) + { + noteOffInternal (message.getChannel(), message.getNoteNumber()); + } + else if (message.isAllNotesOff()) + { + for (int i = 0; i < 128; ++i) + noteOffInternal (message.getChannel(), i); + } } void MidiKeyboardState::processNextMidiBuffer (MidiBuffer& buffer, - const int startSample, - const int numSamples, - const bool injectIndirectEvents) + const int startSample, + const int numSamples, + const bool injectIndirectEvents) { - MidiBuffer::Iterator i (buffer); - MidiMessage message (0xf4, 0.0); - int time; + MidiBuffer::Iterator i (buffer); + MidiMessage message (0xf4, 0.0); + int time; - const ScopedLock sl (lock); + const ScopedLock sl (lock); - while (i.getNextEvent (message, time)) - processNextMidiEvent (message); + while (i.getNextEvent (message, time)) + processNextMidiEvent (message); - if (injectIndirectEvents) - { - MidiBuffer::Iterator i2 (eventsToAdd); - const int firstEventToAdd = eventsToAdd.getFirstEventTime(); - const double scaleFactor = numSamples / (double) (eventsToAdd.getLastEventTime() + 1 - firstEventToAdd); + if (injectIndirectEvents) + { + MidiBuffer::Iterator i2 (eventsToAdd); + const int firstEventToAdd = eventsToAdd.getFirstEventTime(); + const double scaleFactor = numSamples / (double) (eventsToAdd.getLastEventTime() + 1 - firstEventToAdd); - while (i2.getNextEvent (message, time)) - { - const int pos = jlimit (0, numSamples - 1, roundDoubleToInt ((time - firstEventToAdd) * scaleFactor)); - buffer.addEvent (message, startSample + pos); - } - } + while (i2.getNextEvent (message, time)) + { + const int pos = jlimit (0, numSamples - 1, roundToInt ((time - firstEventToAdd) * scaleFactor)); + buffer.addEvent (message, startSample + pos); + } + } - eventsToAdd.clear(); + eventsToAdd.clear(); } void MidiKeyboardState::addListener (MidiKeyboardStateListener* const listener) throw() { - const ScopedLock sl (lock); - listeners.addIfNotAlreadyThere (listener); + const ScopedLock sl (lock); + listeners.addIfNotAlreadyThere (listener); } void MidiKeyboardState::removeListener (MidiKeyboardStateListener* const listener) throw() { - const ScopedLock sl (lock); - listeners.removeValue (listener); + const ScopedLock sl (lock); + listeners.removeValue (listener); } END_JUCE_NAMESPACE @@ -27656,1090 +27389,1090 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE int MidiMessage::readVariableLengthVal (const uint8* data, - int& numBytesUsed) throw() + int& numBytesUsed) throw() { - numBytesUsed = 0; - int v = 0; - int i; + numBytesUsed = 0; + int v = 0; + int i; - do - { - i = (int) *data++; + do + { + i = (int) *data++; - if (++numBytesUsed > 6) - break; + if (++numBytesUsed > 6) + break; - v = (v << 7) + (i & 0x7f); + v = (v << 7) + (i & 0x7f); - } while (i & 0x80); + } while (i & 0x80); - return v; + return v; } int MidiMessage::getMessageLengthFromFirstByte (const uint8 firstByte) throw() { - // this method only works for valid starting bytes of a short midi message - jassert (firstByte >= 0x80 - && firstByte != 0xf0 - && firstByte != 0xf7); + // this method only works for valid starting bytes of a short midi message + jassert (firstByte >= 0x80 + && firstByte != 0xf0 + && firstByte != 0xf7); - static const char messageLengths[] = - { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 1, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - }; + static const char messageLengths[] = + { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 1, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; - return messageLengths [firstByte & 0x7f]; + return messageLengths [firstByte & 0x7f]; } MidiMessage::MidiMessage (const uint8* const d, - const int dataSize, - const double t) throw() + const int dataSize, + const double t) throw() : timeStamp (t), - message (0), - size (dataSize) + message (0), + size (dataSize) { - jassert (dataSize > 0); + jassert (dataSize > 0); - if (dataSize <= 4) - data = (uint8*) &message; - else - data = (uint8*) juce_malloc (dataSize); + if (dataSize <= 4) + data = (uint8*) &message; + else + data = (uint8*) juce_malloc (dataSize); - memcpy (data, d, dataSize); + memcpy (data, d, dataSize); - // check that the length matches the data.. - jassert (size > 3 || *d >= 0xf0 || getMessageLengthFromFirstByte (*d) == size); + // check that the length matches the data.. + jassert (size > 3 || *d >= 0xf0 || getMessageLengthFromFirstByte (*d) == size); } MidiMessage::MidiMessage (const int byte1, - const double t) throw() + const double t) throw() : timeStamp (t), - data ((uint8*) &message), - size (1) + data ((uint8*) &message), + size (1) { - data[0] = (uint8) byte1; + data[0] = (uint8) byte1; - // check that the length matches the data.. - jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 1); + // check that the length matches the data.. + jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 1); } MidiMessage::MidiMessage (const int byte1, - const int byte2, - const double t) throw() + const int byte2, + const double t) throw() : timeStamp (t), - data ((uint8*) &message), - size (2) + data ((uint8*) &message), + size (2) { - data[0] = (uint8) byte1; - data[1] = (uint8) byte2; + data[0] = (uint8) byte1; + data[1] = (uint8) byte2; - // check that the length matches the data.. - jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 2); + // check that the length matches the data.. + jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 2); } MidiMessage::MidiMessage (const int byte1, - const int byte2, - const int byte3, - const double t) throw() + const int byte2, + const int byte3, + const double t) throw() : timeStamp (t), - data ((uint8*) &message), - size (3) + data ((uint8*) &message), + size (3) { - data[0] = (uint8) byte1; - data[1] = (uint8) byte2; - data[2] = (uint8) byte3; + data[0] = (uint8) byte1; + data[1] = (uint8) byte2; + data[2] = (uint8) byte3; - // check that the length matches the data.. - jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 3); + // check that the length matches the data.. + jassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 3); } MidiMessage::MidiMessage (const MidiMessage& other) throw() : timeStamp (other.timeStamp), - message (other.message), - size (other.size) + message (other.message), + size (other.size) { - if (other.data != (uint8*) &other.message) - { - data = (uint8*) juce_malloc (size); - memcpy (data, other.data, size); - } - else - { - data = (uint8*) &message; - } + if (other.data != (uint8*) &other.message) + { + data = (uint8*) juce_malloc (size); + memcpy (data, other.data, size); + } + else + { + data = (uint8*) &message; + } } MidiMessage::MidiMessage (const MidiMessage& other, - const double newTimeStamp) throw() + const double newTimeStamp) throw() : timeStamp (newTimeStamp), - message (other.message), - size (other.size) + message (other.message), + size (other.size) { - if (other.data != (uint8*) &other.message) - { - data = (uint8*) juce_malloc (size); - memcpy (data, other.data, size); - } - else - { - data = (uint8*) &message; - } + if (other.data != (uint8*) &other.message) + { + data = (uint8*) juce_malloc (size); + memcpy (data, other.data, size); + } + else + { + data = (uint8*) &message; + } } MidiMessage::MidiMessage (const uint8* src, - int sz, - int& numBytesUsed, - const uint8 lastStatusByte, - double t) throw() - : timeStamp (t), - data ((uint8*) &message), - message (0) + int sz, + int& numBytesUsed, + const uint8 lastStatusByte, + double t) throw() + : timeStamp (t), + data ((uint8*) &message), + message (0) { - unsigned int byte = (unsigned int) *src; + unsigned int byte = (unsigned int) *src; - if (byte < 0x80) - { - byte = (unsigned int) (uint8) lastStatusByte; - numBytesUsed = -1; - } - else - { - numBytesUsed = 0; - --sz; - ++src; - } + if (byte < 0x80) + { + byte = (unsigned int) (uint8) lastStatusByte; + numBytesUsed = -1; + } + else + { + numBytesUsed = 0; + --sz; + ++src; + } - if (byte >= 0x80) - { - if (byte == 0xf0) - { - const uint8* d = (const uint8*) src; + if (byte >= 0x80) + { + if (byte == 0xf0) + { + const uint8* d = (const uint8*) src; - while (d < src + sz) - { - if (*d >= 0x80) // stop if we hit a status byte, and don't include it in this message - { - if (*d == 0xf7) // include an 0xf7 if we hit one - ++d; + while (d < src + sz) + { + if (*d >= 0x80) // stop if we hit a status byte, and don't include it in this message + { + if (*d == 0xf7) // include an 0xf7 if we hit one + ++d; - break; - } + break; + } - ++d; - } + ++d; + } - size = 1 + (int) (d - src); + size = 1 + (int) (d - src); - data = (uint8*) juce_malloc (size); - *data = (uint8) byte; - memcpy (data + 1, src, size - 1); - } - else if (byte == 0xff) - { - int n; - const int bytesLeft = readVariableLengthVal (src + 1, n); - size = jmin (sz + 1, n + 2 + bytesLeft); + data = (uint8*) juce_malloc (size); + *data = (uint8) byte; + memcpy (data + 1, src, size - 1); + } + else if (byte == 0xff) + { + int n; + const int bytesLeft = readVariableLengthVal (src + 1, n); + size = jmin (sz + 1, n + 2 + bytesLeft); - data = (uint8*) juce_malloc (size); - *data = (uint8) byte; - memcpy (data + 1, src, size - 1); - } - else - { - size = getMessageLengthFromFirstByte ((uint8) byte); - *data = (uint8) byte; + data = (uint8*) juce_malloc (size); + *data = (uint8) byte; + memcpy (data + 1, src, size - 1); + } + else + { + size = getMessageLengthFromFirstByte ((uint8) byte); + *data = (uint8) byte; - if (size > 1) - { - data[1] = src[0]; + if (size > 1) + { + data[1] = src[0]; - if (size > 2) - data[2] = src[1]; - } - } + if (size > 2) + data[2] = src[1]; + } + } - numBytesUsed += size; - } - else - { - message = 0; - size = 0; - } + numBytesUsed += size; + } + else + { + message = 0; + size = 0; + } } const MidiMessage& MidiMessage::operator= (const MidiMessage& other) throw() { - if (this != &other) - { - timeStamp = other.timeStamp; - size = other.size; - message = other.message; + if (this != &other) + { + timeStamp = other.timeStamp; + size = other.size; + message = other.message; - if (data != (uint8*) &message) - juce_free (data); + if (data != (uint8*) &message) + juce_free (data); - if (other.data != (uint8*) &other.message) - { - data = (uint8*) juce_malloc (size); - memcpy (data, other.data, size); - } - else - { - data = (uint8*) &message; - } - } + if (other.data != (uint8*) &other.message) + { + data = (uint8*) juce_malloc (size); + memcpy (data, other.data, size); + } + else + { + data = (uint8*) &message; + } + } - return *this; + return *this; } MidiMessage::~MidiMessage() throw() { - if (data != (uint8*) &message) - juce_free (data); + if (data != (uint8*) &message) + juce_free (data); } int MidiMessage::getChannel() const throw() { - if ((data[0] & 0xf0) != 0xf0) - return (data[0] & 0xf) + 1; - else - return 0; + if ((data[0] & 0xf0) != 0xf0) + return (data[0] & 0xf) + 1; + else + return 0; } bool MidiMessage::isForChannel (const int channel) const throw() { - jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 + jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 - return ((data[0] & 0xf) == channel - 1) - && ((data[0] & 0xf0) != 0xf0); + return ((data[0] & 0xf) == channel - 1) + && ((data[0] & 0xf0) != 0xf0); } void MidiMessage::setChannel (const int channel) throw() { - jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 + jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 - if ((data[0] & 0xf0) != (uint8) 0xf0) - data[0] = (uint8) ((data[0] & (uint8)0xf0) - | (uint8)(channel - 1)); + if ((data[0] & 0xf0) != (uint8) 0xf0) + data[0] = (uint8) ((data[0] & (uint8)0xf0) + | (uint8)(channel - 1)); } bool MidiMessage::isNoteOn (const bool returnTrueForVelocity0) const throw() { - return ((data[0] & 0xf0) == 0x90) - && (returnTrueForVelocity0 || data[2] != 0); + return ((data[0] & 0xf0) == 0x90) + && (returnTrueForVelocity0 || data[2] != 0); } bool MidiMessage::isNoteOff (const bool returnTrueForNoteOnVelocity0) const throw() { - return ((data[0] & 0xf0) == 0x80) - || (returnTrueForNoteOnVelocity0 && (data[2] == 0) && ((data[0] & 0xf0) == 0x90)); + return ((data[0] & 0xf0) == 0x80) + || (returnTrueForNoteOnVelocity0 && (data[2] == 0) && ((data[0] & 0xf0) == 0x90)); } bool MidiMessage::isNoteOnOrOff() const throw() { - const int d = data[0] & 0xf0; - return (d == 0x90) || (d == 0x80); + const int d = data[0] & 0xf0; + return (d == 0x90) || (d == 0x80); } int MidiMessage::getNoteNumber() const throw() { - return data[1]; + return data[1]; } void MidiMessage::setNoteNumber (const int newNoteNumber) throw() { - if (isNoteOnOrOff()) - data[1] = (uint8) jlimit (0, 127, newNoteNumber); + if (isNoteOnOrOff()) + data[1] = (uint8) jlimit (0, 127, newNoteNumber); } uint8 MidiMessage::getVelocity() const throw() { - if (isNoteOnOrOff()) - return data[2]; - else - return 0; + if (isNoteOnOrOff()) + return data[2]; + else + return 0; } float MidiMessage::getFloatVelocity() const throw() { - return getVelocity() * (1.0f / 127.0f); + return getVelocity() * (1.0f / 127.0f); } void MidiMessage::setVelocity (const float newVelocity) throw() { - if (isNoteOnOrOff()) - data[2] = (uint8) jlimit (0, 0x7f, roundFloatToInt (newVelocity * 127.0f)); + if (isNoteOnOrOff()) + data[2] = (uint8) jlimit (0, 0x7f, roundToInt (newVelocity * 127.0f)); } void MidiMessage::multiplyVelocity (const float scaleFactor) throw() { - if (isNoteOnOrOff()) - data[2] = (uint8) jlimit (0, 0x7f, roundFloatToInt (scaleFactor * data[2])); + if (isNoteOnOrOff()) + data[2] = (uint8) jlimit (0, 0x7f, roundToInt (scaleFactor * data[2])); } bool MidiMessage::isAftertouch() const throw() { - return (data[0] & 0xf0) == 0xa0; + return (data[0] & 0xf0) == 0xa0; } int MidiMessage::getAfterTouchValue() const throw() { - return data[2]; + return data[2]; } const MidiMessage MidiMessage::aftertouchChange (const int channel, - const int noteNum, - const int aftertouchValue) throw() + const int noteNum, + const int aftertouchValue) throw() { - jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 - jassert (((unsigned int) noteNum) <= 127); - jassert (((unsigned int) aftertouchValue) <= 127); + jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 + jassert (((unsigned int) noteNum) <= 127); + jassert (((unsigned int) aftertouchValue) <= 127); - return MidiMessage (0xa0 | jlimit (0, 15, channel - 1), - noteNum & 0x7f, - aftertouchValue & 0x7f); + return MidiMessage (0xa0 | jlimit (0, 15, channel - 1), + noteNum & 0x7f, + aftertouchValue & 0x7f); } bool MidiMessage::isChannelPressure() const throw() { - return (data[0] & 0xf0) == 0xd0; + return (data[0] & 0xf0) == 0xd0; } int MidiMessage::getChannelPressureValue() const throw() { - jassert (isChannelPressure()); + jassert (isChannelPressure()); - return data[1]; + return data[1]; } const MidiMessage MidiMessage::channelPressureChange (const int channel, - const int pressure) throw() + const int pressure) throw() { - jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 - jassert (((unsigned int) pressure) <= 127); + jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 + jassert (((unsigned int) pressure) <= 127); - return MidiMessage (0xd0 | jlimit (0, 15, channel - 1), - pressure & 0x7f); + return MidiMessage (0xd0 | jlimit (0, 15, channel - 1), + pressure & 0x7f); } bool MidiMessage::isProgramChange() const throw() { - return (data[0] & 0xf0) == 0xc0; + return (data[0] & 0xf0) == 0xc0; } int MidiMessage::getProgramChangeNumber() const throw() { - return data[1]; + return data[1]; } const MidiMessage MidiMessage::programChange (const int channel, - const int programNumber) throw() + const int programNumber) throw() { - jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 + jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 - return MidiMessage (0xc0 | jlimit (0, 15, channel - 1), - programNumber & 0x7f); + return MidiMessage (0xc0 | jlimit (0, 15, channel - 1), + programNumber & 0x7f); } bool MidiMessage::isPitchWheel() const throw() { - return (data[0] & 0xf0) == 0xe0; + return (data[0] & 0xf0) == 0xe0; } int MidiMessage::getPitchWheelValue() const throw() { - return data[1] | (data[2] << 7); + return data[1] | (data[2] << 7); } const MidiMessage MidiMessage::pitchWheel (const int channel, - const int position) throw() + const int position) throw() { - jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 - jassert (((unsigned int) position) <= 0x3fff); + jassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16 + jassert (((unsigned int) position) <= 0x3fff); - return MidiMessage (0xe0 | jlimit (0, 15, channel - 1), - position & 127, - (position >> 7) & 127); + return MidiMessage (0xe0 | jlimit (0, 15, channel - 1), + position & 127, + (position >> 7) & 127); } bool MidiMessage::isController() const throw() { - return (data[0] & 0xf0) == 0xb0; + return (data[0] & 0xf0) == 0xb0; } int MidiMessage::getControllerNumber() const throw() { - jassert (isController()); + jassert (isController()); - return data[1]; + return data[1]; } int MidiMessage::getControllerValue() const throw() { - jassert (isController()); + jassert (isController()); - return data[2]; + return data[2]; } const MidiMessage MidiMessage::controllerEvent (const int channel, - const int controllerType, - const int value) throw() + const int controllerType, + const int value) throw() { - // the channel must be between 1 and 16 inclusive - jassert (channel > 0 && channel <= 16); + // the channel must be between 1 and 16 inclusive + jassert (channel > 0 && channel <= 16); - return MidiMessage (0xb0 | jlimit (0, 15, channel - 1), - controllerType & 127, - value & 127); + return MidiMessage (0xb0 | jlimit (0, 15, channel - 1), + controllerType & 127, + value & 127); } const MidiMessage MidiMessage::noteOn (const int channel, - const int noteNumber, - const float velocity) throw() + const int noteNumber, + const float velocity) throw() { - return noteOn (channel, noteNumber, (uint8)(velocity * 127.0f)); + return noteOn (channel, noteNumber, (uint8)(velocity * 127.0f)); } const MidiMessage MidiMessage::noteOn (const int channel, - const int noteNumber, - const uint8 velocity) throw() + const int noteNumber, + const uint8 velocity) throw() { - jassert (channel > 0 && channel <= 16); - jassert (((unsigned int) noteNumber) <= 127); + jassert (channel > 0 && channel <= 16); + jassert (((unsigned int) noteNumber) <= 127); - return MidiMessage (0x90 | jlimit (0, 15, channel - 1), - noteNumber & 127, - jlimit (0, 127, roundFloatToInt (velocity))); + return MidiMessage (0x90 | jlimit (0, 15, channel - 1), + noteNumber & 127, + jlimit (0, 127, roundToInt (velocity))); } const MidiMessage MidiMessage::noteOff (const int channel, - const int noteNumber) throw() + const int noteNumber) throw() { - jassert (channel > 0 && channel <= 16); - jassert (((unsigned int) noteNumber) <= 127); + jassert (channel > 0 && channel <= 16); + jassert (((unsigned int) noteNumber) <= 127); - return MidiMessage (0x80 | jlimit (0, 15, channel - 1), noteNumber & 127, 0); + return MidiMessage (0x80 | jlimit (0, 15, channel - 1), noteNumber & 127, 0); } const MidiMessage MidiMessage::allNotesOff (const int channel) throw() { - jassert (channel > 0 && channel <= 16); + jassert (channel > 0 && channel <= 16); - return controllerEvent (channel, 123, 0); + return controllerEvent (channel, 123, 0); } bool MidiMessage::isAllNotesOff() const throw() { - return (data[0] & 0xf0) == 0xb0 - && data[1] == 123; + return (data[0] & 0xf0) == 0xb0 + && data[1] == 123; } const MidiMessage MidiMessage::allSoundOff (const int channel) throw() { - return controllerEvent (channel, 120, 0); + return controllerEvent (channel, 120, 0); } bool MidiMessage::isAllSoundOff() const throw() { - return (data[0] & 0xf0) == 0xb0 - && data[1] == 120; + return (data[0] & 0xf0) == 0xb0 + && data[1] == 120; } const MidiMessage MidiMessage::allControllersOff (const int channel) throw() { - return controllerEvent (channel, 121, 0); + return controllerEvent (channel, 121, 0); } const MidiMessage MidiMessage::masterVolume (const float volume) throw() { - const int vol = jlimit (0, 0x3fff, roundFloatToInt (volume * 0x4000)); + const int vol = jlimit (0, 0x3fff, roundToInt (volume * 0x4000)); - uint8 buf[8]; - buf[0] = 0xf0; - buf[1] = 0x7f; - buf[2] = 0x7f; - buf[3] = 0x04; - buf[4] = 0x01; - buf[5] = (uint8) (vol & 0x7f); - buf[6] = (uint8) (vol >> 7); - buf[7] = 0xf7; + uint8 buf[8]; + buf[0] = 0xf0; + buf[1] = 0x7f; + buf[2] = 0x7f; + buf[3] = 0x04; + buf[4] = 0x01; + buf[5] = (uint8) (vol & 0x7f); + buf[6] = (uint8) (vol >> 7); + buf[7] = 0xf7; - return MidiMessage (buf, 8); + return MidiMessage (buf, 8); } bool MidiMessage::isSysEx() const throw() { - return *data == 0xf0; + return *data == 0xf0; } const MidiMessage MidiMessage::createSysExMessage (const uint8* sysexData, - const int dataSize) throw() + const int dataSize) throw() { - MemoryBlock mm (dataSize + 2); - uint8* const m = (uint8*) mm.getData(); + MemoryBlock mm (dataSize + 2); + uint8* const m = (uint8*) mm.getData(); - m[0] = 0xf0; - memcpy (m + 1, sysexData, dataSize); - m[dataSize + 1] = 0xf7; + m[0] = 0xf0; + memcpy (m + 1, sysexData, dataSize); + m[dataSize + 1] = 0xf7; - return MidiMessage (m, dataSize + 2); + return MidiMessage (m, dataSize + 2); } const uint8* MidiMessage::getSysExData() const throw() { - return (isSysEx()) ? getRawData() + 1 - : 0; + return (isSysEx()) ? getRawData() + 1 + : 0; } int MidiMessage::getSysExDataSize() const throw() { - return (isSysEx()) ? size - 2 - : 0; + return (isSysEx()) ? size - 2 + : 0; } bool MidiMessage::isMetaEvent() const throw() { - return *data == 0xff; + return *data == 0xff; } bool MidiMessage::isActiveSense() const throw() { - return *data == 0xfe; + return *data == 0xfe; } int MidiMessage::getMetaEventType() const throw() { - if (*data != 0xff) - return -1; - else - return data[1]; + if (*data != 0xff) + return -1; + else + return data[1]; } int MidiMessage::getMetaEventLength() const throw() { - if (*data == 0xff) - { - int n; - return jmin (size - 2, readVariableLengthVal (data + 2, n)); - } + if (*data == 0xff) + { + int n; + return jmin (size - 2, readVariableLengthVal (data + 2, n)); + } - return 0; + return 0; } const uint8* MidiMessage::getMetaEventData() const throw() { - int n; - const uint8* d = data + 2; - readVariableLengthVal (d, n); - return d + n; + int n; + const uint8* d = data + 2; + readVariableLengthVal (d, n); + return d + n; } bool MidiMessage::isTrackMetaEvent() const throw() { - return getMetaEventType() == 0; + return getMetaEventType() == 0; } bool MidiMessage::isEndOfTrackMetaEvent() const throw() { - return getMetaEventType() == 47; + return getMetaEventType() == 47; } bool MidiMessage::isTextMetaEvent() const throw() { - const int t = getMetaEventType(); + const int t = getMetaEventType(); - return t > 0 && t < 16; + return t > 0 && t < 16; } const String MidiMessage::getTextFromTextMetaEvent() const throw() { - return String ((const char*) getMetaEventData(), - getMetaEventLength()); + return String ((const char*) getMetaEventData(), + getMetaEventLength()); } bool MidiMessage::isTrackNameEvent() const throw() { - return (data[1] == 3) - && (*data == 0xff); + return (data[1] == 3) + && (*data == 0xff); } bool MidiMessage::isTempoMetaEvent() const throw() { - return (data[1] == 81) - && (*data == 0xff); + return (data[1] == 81) + && (*data == 0xff); } bool MidiMessage::isMidiChannelMetaEvent() const throw() { - return (data[1] == 0x20) - && (*data == 0xff) - && (data[2] == 1); + return (data[1] == 0x20) + && (*data == 0xff) + && (data[2] == 1); } int MidiMessage::getMidiChannelMetaEventChannel() const throw() { - return data[3] + 1; + return data[3] + 1; } double MidiMessage::getTempoSecondsPerQuarterNote() const throw() { - if (! isTempoMetaEvent()) - return 0.0; + if (! isTempoMetaEvent()) + return 0.0; - const uint8* const d = getMetaEventData(); + const uint8* const d = getMetaEventData(); - return (((unsigned int) d[0] << 16) - | ((unsigned int) d[1] << 8) - | d[2]) - / 1000000.0; + return (((unsigned int) d[0] << 16) + | ((unsigned int) d[1] << 8) + | d[2]) + / 1000000.0; } double MidiMessage::getTempoMetaEventTickLength (const short timeFormat) const throw() { - if (timeFormat > 0) - { - if (! isTempoMetaEvent()) - return 0.5 / timeFormat; + if (timeFormat > 0) + { + if (! isTempoMetaEvent()) + return 0.5 / timeFormat; - return getTempoSecondsPerQuarterNote() / timeFormat; - } - else - { - const int frameCode = (-timeFormat) >> 8; - double framesPerSecond; + return getTempoSecondsPerQuarterNote() / timeFormat; + } + else + { + const int frameCode = (-timeFormat) >> 8; + double framesPerSecond; - switch (frameCode) - { - case 24: framesPerSecond = 24.0; break; - case 25: framesPerSecond = 25.0; break; - case 29: framesPerSecond = 29.97; break; - case 30: framesPerSecond = 30.0; break; - default: framesPerSecond = 30.0; break; - } + switch (frameCode) + { + case 24: framesPerSecond = 24.0; break; + case 25: framesPerSecond = 25.0; break; + case 29: framesPerSecond = 29.97; break; + case 30: framesPerSecond = 30.0; break; + default: framesPerSecond = 30.0; break; + } - return (1.0 / framesPerSecond) / (timeFormat & 0xff); - } + return (1.0 / framesPerSecond) / (timeFormat & 0xff); + } } const MidiMessage MidiMessage::tempoMetaEvent (int microsecondsPerQuarterNote) throw() { - uint8 d[8]; - d[0] = 0xff; - d[1] = 81; - d[2] = 3; - d[3] = (uint8) (microsecondsPerQuarterNote >> 16); - d[4] = (uint8) ((microsecondsPerQuarterNote >> 8) & 0xff); - d[5] = (uint8) (microsecondsPerQuarterNote & 0xff); + uint8 d[8]; + d[0] = 0xff; + d[1] = 81; + d[2] = 3; + d[3] = (uint8) (microsecondsPerQuarterNote >> 16); + d[4] = (uint8) ((microsecondsPerQuarterNote >> 8) & 0xff); + d[5] = (uint8) (microsecondsPerQuarterNote & 0xff); - return MidiMessage (d, 6, 0.0); + return MidiMessage (d, 6, 0.0); } bool MidiMessage::isTimeSignatureMetaEvent() const throw() { - return (data[1] == 0x58) - && (*data == (uint8) 0xff); + return (data[1] == 0x58) + && (*data == (uint8) 0xff); } void MidiMessage::getTimeSignatureInfo (int& numerator, - int& denominator) const throw() + int& denominator) const throw() { - if (isTimeSignatureMetaEvent()) - { - const uint8* const d = getMetaEventData(); - numerator = d[0]; - denominator = 1 << d[1]; - } - else - { - numerator = 4; - denominator = 4; - } + if (isTimeSignatureMetaEvent()) + { + const uint8* const d = getMetaEventData(); + numerator = d[0]; + denominator = 1 << d[1]; + } + else + { + numerator = 4; + denominator = 4; + } } const MidiMessage MidiMessage::timeSignatureMetaEvent (const int numerator, - const int denominator) throw() + const int denominator) throw() { - uint8 d[8]; - d[0] = 0xff; - d[1] = 0x58; - d[2] = 0x04; - d[3] = (uint8) numerator; + uint8 d[8]; + d[0] = 0xff; + d[1] = 0x58; + d[2] = 0x04; + d[3] = (uint8) numerator; - int n = 1; - int powerOfTwo = 0; + int n = 1; + int powerOfTwo = 0; - while (n < denominator) - { - n <<= 1; - ++powerOfTwo; - } + while (n < denominator) + { + n <<= 1; + ++powerOfTwo; + } - d[4] = (uint8) powerOfTwo; - d[5] = 0x01; - d[6] = 96; + d[4] = (uint8) powerOfTwo; + d[5] = 0x01; + d[6] = 96; - return MidiMessage (d, 7, 0.0); + return MidiMessage (d, 7, 0.0); } const MidiMessage MidiMessage::midiChannelMetaEvent (const int channel) throw() { - uint8 d[8]; - d[0] = 0xff; - d[1] = 0x20; - d[2] = 0x01; - d[3] = (uint8) jlimit (0, 0xff, channel - 1); + uint8 d[8]; + d[0] = 0xff; + d[1] = 0x20; + d[2] = 0x01; + d[3] = (uint8) jlimit (0, 0xff, channel - 1); - return MidiMessage (d, 4, 0.0); + return MidiMessage (d, 4, 0.0); } bool MidiMessage::isKeySignatureMetaEvent() const throw() { - return getMetaEventType() == 89; + return getMetaEventType() == 89; } int MidiMessage::getKeySignatureNumberOfSharpsOrFlats() const throw() { - return (int) *getMetaEventData(); + return (int) *getMetaEventData(); } const MidiMessage MidiMessage::endOfTrack() throw() { - return MidiMessage (0xff, 0x2f, 0, 0.0); + return MidiMessage (0xff, 0x2f, 0, 0.0); } bool MidiMessage::isSongPositionPointer() const throw() { - return *data == 0xf2; + return *data == 0xf2; } int MidiMessage::getSongPositionPointerMidiBeat() const throw() { - return data[1] | (data[2] << 7); + return data[1] | (data[2] << 7); } const MidiMessage MidiMessage::songPositionPointer (const int positionInMidiBeats) throw() { - return MidiMessage (0xf2, - positionInMidiBeats & 127, - (positionInMidiBeats >> 7) & 127); + return MidiMessage (0xf2, + positionInMidiBeats & 127, + (positionInMidiBeats >> 7) & 127); } bool MidiMessage::isMidiStart() const throw() { - return *data == 0xfa; + return *data == 0xfa; } const MidiMessage MidiMessage::midiStart() throw() { - return MidiMessage (0xfa); + return MidiMessage (0xfa); } bool MidiMessage::isMidiContinue() const throw() { - return *data == 0xfb; + return *data == 0xfb; } const MidiMessage MidiMessage::midiContinue() throw() { - return MidiMessage (0xfb); + return MidiMessage (0xfb); } bool MidiMessage::isMidiStop() const throw() { - return *data == 0xfc; + return *data == 0xfc; } const MidiMessage MidiMessage::midiStop() throw() { - return MidiMessage (0xfc); + return MidiMessage (0xfc); } bool MidiMessage::isMidiClock() const throw() { - return *data == 0xf8; + return *data == 0xf8; } const MidiMessage MidiMessage::midiClock() throw() { - return MidiMessage (0xf8); + return MidiMessage (0xf8); } bool MidiMessage::isQuarterFrame() const throw() { - return *data == 0xf1; + return *data == 0xf1; } int MidiMessage::getQuarterFrameSequenceNumber() const throw() { - return ((int) data[1]) >> 4; + return ((int) data[1]) >> 4; } int MidiMessage::getQuarterFrameValue() const throw() { - return ((int) data[1]) & 0x0f; + return ((int) data[1]) & 0x0f; } const MidiMessage MidiMessage::quarterFrame (const int sequenceNumber, - const int value) throw() + const int value) throw() { - return MidiMessage (0xf1, (sequenceNumber << 4) | value); + return MidiMessage (0xf1, (sequenceNumber << 4) | value); } bool MidiMessage::isFullFrame() const throw() { - return data[0] == 0xf0 - && data[1] == 0x7f - && size >= 10 - && data[3] == 0x01 - && data[4] == 0x01; + return data[0] == 0xf0 + && data[1] == 0x7f + && size >= 10 + && data[3] == 0x01 + && data[4] == 0x01; } void MidiMessage::getFullFrameParameters (int& hours, - int& minutes, - int& seconds, - int& frames, - MidiMessage::SmpteTimecodeType& timecodeType) const throw() + int& minutes, + int& seconds, + int& frames, + MidiMessage::SmpteTimecodeType& timecodeType) const throw() { - jassert (isFullFrame()); + jassert (isFullFrame()); - timecodeType = (SmpteTimecodeType) (data[5] >> 5); - hours = data[5] & 0x1f; - minutes = data[6]; - seconds = data[7]; - frames = data[8]; + timecodeType = (SmpteTimecodeType) (data[5] >> 5); + hours = data[5] & 0x1f; + minutes = data[6]; + seconds = data[7]; + frames = data[8]; } const MidiMessage MidiMessage::fullFrame (const int hours, - const int minutes, - const int seconds, - const int frames, - MidiMessage::SmpteTimecodeType timecodeType) + const int minutes, + const int seconds, + const int frames, + MidiMessage::SmpteTimecodeType timecodeType) { - uint8 d[10]; - d[0] = 0xf0; - d[1] = 0x7f; - d[2] = 0x7f; - d[3] = 0x01; - d[4] = 0x01; - d[5] = (uint8) ((hours & 0x01f) | (timecodeType << 5)); - d[6] = (uint8) minutes; - d[7] = (uint8) seconds; - d[8] = (uint8) frames; - d[9] = 0xf7; + uint8 d[10]; + d[0] = 0xf0; + d[1] = 0x7f; + d[2] = 0x7f; + d[3] = 0x01; + d[4] = 0x01; + d[5] = (uint8) ((hours & 0x01f) | (timecodeType << 5)); + d[6] = (uint8) minutes; + d[7] = (uint8) seconds; + d[8] = (uint8) frames; + d[9] = 0xf7; - return MidiMessage (d, 10, 0.0); + return MidiMessage (d, 10, 0.0); } bool MidiMessage::isMidiMachineControlMessage() const throw() { - return data[0] == 0xf0 - && data[1] == 0x7f - && data[3] == 0x06 - && size > 5; + return data[0] == 0xf0 + && data[1] == 0x7f + && data[3] == 0x06 + && size > 5; } MidiMessage::MidiMachineControlCommand MidiMessage::getMidiMachineControlCommand() const throw() { - jassert (isMidiMachineControlMessage()); + jassert (isMidiMachineControlMessage()); - return (MidiMachineControlCommand) data[4]; + return (MidiMachineControlCommand) data[4]; } const MidiMessage MidiMessage::midiMachineControlCommand (MidiMessage::MidiMachineControlCommand command) { - uint8 d[6]; - d[0] = 0xf0; - d[1] = 0x7f; - d[2] = 0x00; - d[3] = 0x06; - d[4] = (uint8) command; - d[5] = 0xf7; + uint8 d[6]; + d[0] = 0xf0; + d[1] = 0x7f; + d[2] = 0x00; + d[3] = 0x06; + d[4] = (uint8) command; + d[5] = 0xf7; - return MidiMessage (d, 6, 0.0); + return MidiMessage (d, 6, 0.0); } bool MidiMessage::isMidiMachineControlGoto (int& hours, - int& minutes, - int& seconds, - int& frames) const throw() + int& minutes, + int& seconds, + int& frames) const throw() { - if (size >= 12 - && data[0] == 0xf0 - && data[1] == 0x7f - && data[3] == 0x06 - && data[4] == 0x44 - && data[5] == 0x06 - && data[6] == 0x01) - { - hours = data[7] % 24; // (that some machines send out hours > 24) - minutes = data[8]; - seconds = data[9]; - frames = data[10]; + if (size >= 12 + && data[0] == 0xf0 + && data[1] == 0x7f + && data[3] == 0x06 + && data[4] == 0x44 + && data[5] == 0x06 + && data[6] == 0x01) + { + hours = data[7] % 24; // (that some machines send out hours > 24) + minutes = data[8]; + seconds = data[9]; + frames = data[10]; - return true; - } + return true; + } - return false; + return false; } const MidiMessage MidiMessage::midiMachineControlGoto (int hours, - int minutes, - int seconds, - int frames) + int minutes, + int seconds, + int frames) { - uint8 d[12]; - d[0] = 0xf0; - d[1] = 0x7f; - d[2] = 0x00; - d[3] = 0x06; - d[4] = 0x44; - d[5] = 0x06; - d[6] = 0x01; - d[7] = (uint8) hours; - d[8] = (uint8) minutes; - d[9] = (uint8) seconds; - d[10] = (uint8) frames; - d[11] = 0xf7; + uint8 d[12]; + d[0] = 0xf0; + d[1] = 0x7f; + d[2] = 0x00; + d[3] = 0x06; + d[4] = 0x44; + d[5] = 0x06; + d[6] = 0x01; + d[7] = (uint8) hours; + d[8] = (uint8) minutes; + d[9] = (uint8) seconds; + d[10] = (uint8) frames; + d[11] = 0xf7; - return MidiMessage (d, 12, 0.0); + return MidiMessage (d, 12, 0.0); } const String MidiMessage::getMidiNoteName (int note, - bool useSharps, - bool includeOctaveNumber, - int octaveNumForMiddleC) throw() + bool useSharps, + bool includeOctaveNumber, + int octaveNumForMiddleC) throw() { - static const char* const sharpNoteNames[] = { "C", "C#", "D", "D#", "E", - "F", "F#", "G", "G#", "A", - "A#", "B" }; + static const char* const sharpNoteNames[] = { "C", "C#", "D", "D#", "E", + "F", "F#", "G", "G#", "A", + "A#", "B" }; - static const char* const flatNoteNames[] = { "C", "Db", "D", "Eb", "E", - "F", "Gb", "G", "Ab", "A", - "Bb", "B" }; + static const char* const flatNoteNames[] = { "C", "Db", "D", "Eb", "E", + "F", "Gb", "G", "Ab", "A", + "Bb", "B" }; - if (((unsigned int) note) < 128) - { - const String s ((useSharps) ? sharpNoteNames [note % 12] - : flatNoteNames [note % 12]); + if (((unsigned int) note) < 128) + { + const String s ((useSharps) ? sharpNoteNames [note % 12] + : flatNoteNames [note % 12]); - if (includeOctaveNumber) - return s + String (note / 12 + (octaveNumForMiddleC - 5)); - else - return s; - } + if (includeOctaveNumber) + return s + String (note / 12 + (octaveNumForMiddleC - 5)); + else + return s; + } - return String::empty; + return String::empty; } const double MidiMessage::getMidiNoteInHertz (int noteNumber) throw() { - noteNumber -= 12 * 6 + 9; // now 0 = A440 - return 440.0 * pow (2.0, noteNumber / 12.0); + noteNumber -= 12 * 6 + 9; // now 0 = A440 + return 440.0 * pow (2.0, noteNumber / 12.0); } const String MidiMessage::getGMInstrumentName (int n) throw() { - const char *names[] = - { - "Acoustic Grand Piano", "Bright Acoustic Piano", "Electric Grand Piano", "Honky-tonk Piano", - "Electric Piano 1", "Electric Piano 2", "Harpsichord", "Clavinet", "Celesta", "Glockenspiel", - "Music Box", "Vibraphone", "Marimba", "Xylophone", "Tubular Bells", "Dulcimer", "Drawbar Organ", - "Percussive Organ", "Rock Organ", "Church Organ", "Reed Organ", "Accordion", "Harmonica", - "Tango Accordion", "Acoustic Guitar (nylon)", "Acoustic Guitar (steel)", "Electric Guitar (jazz)", - "Electric Guitar (clean)", "Electric Guitar (mute)", "Overdriven Guitar", "Distortion Guitar", - "Guitar Harmonics", "Acoustic Bass", "Electric Bass (finger)", "Electric Bass (pick)", - "Fretless Bass", "Slap Bass 1", "Slap Bass 2", "Synth Bass 1", "Synth Bass 2", "Violin", - "Viola", "Cello", "Contrabass", "Tremolo Strings", "Pizzicato Strings", "Orchestral Harp", - "Timpani", "String Ensemble 1", "String Ensemble 2", "SynthStrings 1", "SynthStrings 2", - "Choir Aahs", "Voice Oohs", "Synth Voice", "Orchestra Hit", "Trumpet", "Trombone", "Tuba", - "Muted Trumpet", "French Horn", "Brass Section", "SynthBrass 1", "SynthBrass 2", "Soprano Sax", - "Alto Sax", "Tenor Sax", "Baritone Sax", "Oboe", "English Horn", "Bassoon", "Clarinet", - "Piccolo", "Flute", "Recorder", "Pan Flute", "Blown Bottle", "Shakuhachi", "Whistle", - "Ocarina", "Lead 1 (square)", "Lead 2 (sawtooth)", "Lead 3 (calliope)", "Lead 4 (chiff)", - "Lead 5 (charang)", "Lead 6 (voice)", "Lead 7 (fifths)", "Lead 8 (bass+lead)", "Pad 1 (new age)", - "Pad 2 (warm)", "Pad 3 (polysynth)", "Pad 4 (choir)", "Pad 5 (bowed)", "Pad 6 (metallic)", - "Pad 7 (halo)", "Pad 8 (sweep)", "FX 1 (rain)", "FX 2 (soundtrack)", "FX 3 (crystal)", - "FX 4 (atmosphere)", "FX 5 (brightness)", "FX 6 (goblins)", "FX 7 (echoes)", "FX 8 (sci-fi)", - "Sitar", "Banjo", "Shamisen", "Koto", "Kalimba", "Bag pipe", "Fiddle", "Shanai", "Tinkle Bell", - "Agogo", "Steel Drums", "Woodblock", "Taiko Drum", "Melodic Tom", "Synth Drum", "Reverse Cymbal", - "Guitar Fret Noise", "Breath Noise", "Seashore", "Bird Tweet", "Telephone Ring", "Helicopter", - "Applause", "Gunshot" - }; + const char *names[] = + { + "Acoustic Grand Piano", "Bright Acoustic Piano", "Electric Grand Piano", "Honky-tonk Piano", + "Electric Piano 1", "Electric Piano 2", "Harpsichord", "Clavinet", "Celesta", "Glockenspiel", + "Music Box", "Vibraphone", "Marimba", "Xylophone", "Tubular Bells", "Dulcimer", "Drawbar Organ", + "Percussive Organ", "Rock Organ", "Church Organ", "Reed Organ", "Accordion", "Harmonica", + "Tango Accordion", "Acoustic Guitar (nylon)", "Acoustic Guitar (steel)", "Electric Guitar (jazz)", + "Electric Guitar (clean)", "Electric Guitar (mute)", "Overdriven Guitar", "Distortion Guitar", + "Guitar Harmonics", "Acoustic Bass", "Electric Bass (finger)", "Electric Bass (pick)", + "Fretless Bass", "Slap Bass 1", "Slap Bass 2", "Synth Bass 1", "Synth Bass 2", "Violin", + "Viola", "Cello", "Contrabass", "Tremolo Strings", "Pizzicato Strings", "Orchestral Harp", + "Timpani", "String Ensemble 1", "String Ensemble 2", "SynthStrings 1", "SynthStrings 2", + "Choir Aahs", "Voice Oohs", "Synth Voice", "Orchestra Hit", "Trumpet", "Trombone", "Tuba", + "Muted Trumpet", "French Horn", "Brass Section", "SynthBrass 1", "SynthBrass 2", "Soprano Sax", + "Alto Sax", "Tenor Sax", "Baritone Sax", "Oboe", "English Horn", "Bassoon", "Clarinet", + "Piccolo", "Flute", "Recorder", "Pan Flute", "Blown Bottle", "Shakuhachi", "Whistle", + "Ocarina", "Lead 1 (square)", "Lead 2 (sawtooth)", "Lead 3 (calliope)", "Lead 4 (chiff)", + "Lead 5 (charang)", "Lead 6 (voice)", "Lead 7 (fifths)", "Lead 8 (bass+lead)", "Pad 1 (new age)", + "Pad 2 (warm)", "Pad 3 (polysynth)", "Pad 4 (choir)", "Pad 5 (bowed)", "Pad 6 (metallic)", + "Pad 7 (halo)", "Pad 8 (sweep)", "FX 1 (rain)", "FX 2 (soundtrack)", "FX 3 (crystal)", + "FX 4 (atmosphere)", "FX 5 (brightness)", "FX 6 (goblins)", "FX 7 (echoes)", "FX 8 (sci-fi)", + "Sitar", "Banjo", "Shamisen", "Koto", "Kalimba", "Bag pipe", "Fiddle", "Shanai", "Tinkle Bell", + "Agogo", "Steel Drums", "Woodblock", "Taiko Drum", "Melodic Tom", "Synth Drum", "Reverse Cymbal", + "Guitar Fret Noise", "Breath Noise", "Seashore", "Bird Tweet", "Telephone Ring", "Helicopter", + "Applause", "Gunshot" + }; - return (((unsigned int) n) < 128) ? names[n] - : (const char*)0; + return (((unsigned int) n) < 128) ? names[n] + : (const char*)0; } const String MidiMessage::getGMInstrumentBankName (int n) throw() { - const char* names[] = - { - "Piano", "Chromatic Percussion", "Organ", "Guitar", - "Bass", "Strings", "Ensemble", "Brass", - "Reed", "Pipe", "Synth Lead", "Synth Pad", - "Synth Effects", "Ethnic", "Percussive", "Sound Effects" - }; + const char* names[] = + { + "Piano", "Chromatic Percussion", "Organ", "Guitar", + "Bass", "Strings", "Ensemble", "Brass", + "Reed", "Pipe", "Synth Lead", "Synth Pad", + "Synth Effects", "Ethnic", "Percussive", "Sound Effects" + }; - return (((unsigned int) n) <= 15) ? names[n] - : (const char*)0; + return (((unsigned int) n) <= 15) ? names[n] + : (const char*)0; } const String MidiMessage::getRhythmInstrumentName (int n) throw() { - const char* names[] = - { - "Acoustic Bass Drum", "Bass Drum 1", "Side Stick", "Acoustic Snare", - "Hand Clap", "Electric Snare", "Low Floor Tom", "Closed Hi-Hat", "High Floor Tom", - "Pedal Hi-Hat", "Low Tom", "Open Hi-Hat", "Low-Mid Tom", "Hi-Mid Tom", "Crash Cymbal 1", - "High Tom", "Ride Cymbal 1", "Chinese Cymbal", "Ride Bell", "Tambourine", "Splash Cymbal", - "Cowbell", "Crash Cymbal 2", "Vibraslap", "Ride Cymbal 2", "Hi Bongo", "Low Bongo", - "Mute Hi Conga", "Open Hi Conga", "Low Conga", "High Timbale", "Low Timbale", "High Agogo", - "Low Agogo", "Cabasa", "Maracas", "Short Whistle", "Long Whistle", "Short Guiro", - "Long Guiro", "Claves", "Hi Wood Block", "Low Wood Block", "Mute Cuica", "Open Cuica", - "Mute Triangle", "Open Triangle" - }; + const char* names[] = + { + "Acoustic Bass Drum", "Bass Drum 1", "Side Stick", "Acoustic Snare", + "Hand Clap", "Electric Snare", "Low Floor Tom", "Closed Hi-Hat", "High Floor Tom", + "Pedal Hi-Hat", "Low Tom", "Open Hi-Hat", "Low-Mid Tom", "Hi-Mid Tom", "Crash Cymbal 1", + "High Tom", "Ride Cymbal 1", "Chinese Cymbal", "Ride Bell", "Tambourine", "Splash Cymbal", + "Cowbell", "Crash Cymbal 2", "Vibraslap", "Ride Cymbal 2", "Hi Bongo", "Low Bongo", + "Mute Hi Conga", "Open Hi Conga", "Low Conga", "High Timbale", "Low Timbale", "High Agogo", + "Low Agogo", "Cabasa", "Maracas", "Short Whistle", "Long Whistle", "Short Guiro", + "Long Guiro", "Claves", "Hi Wood Block", "Low Wood Block", "Mute Cuica", "Open Cuica", + "Mute Triangle", "Open Triangle" + }; - return (n >= 35 && n <= 81) ? names [n - 35] - : (const char*)0; + return (n >= 35 && n <= 81) ? names [n - 35] + : (const char*)0; } const String MidiMessage::getControllerName (int n) throw() { - const char* names[] = - { - "Bank Select", "Modulation Wheel (coarse)", "Breath controller (coarse)", - 0, "Foot Pedal (coarse)", "Portamento Time (coarse)", - "Data Entry (coarse)", "Volume (coarse)", "Balance (coarse)", - 0, "Pan position (coarse)", "Expression (coarse)", "Effect Control 1 (coarse)", - "Effect Control 2 (coarse)", 0, 0, "General Purpose Slider 1", "General Purpose Slider 2", - "General Purpose Slider 3", "General Purpose Slider 4", 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, "Bank Select (fine)", "Modulation Wheel (fine)", "Breath controller (fine)", - 0, "Foot Pedal (fine)", "Portamento Time (fine)", "Data Entry (fine)", "Volume (fine)", - "Balance (fine)", 0, "Pan position (fine)", "Expression (fine)", "Effect Control 1 (fine)", - "Effect Control 2 (fine)", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - "Hold Pedal (on/off)", "Portamento (on/off)", "Sustenuto Pedal (on/off)", "Soft Pedal (on/off)", - "Legato Pedal (on/off)", "Hold 2 Pedal (on/off)", "Sound Variation", "Sound Timbre", - "Sound Release Time", "Sound Attack Time", "Sound Brightness", "Sound Control 6", - "Sound Control 7", "Sound Control 8", "Sound Control 9", "Sound Control 10", - "General Purpose Button 1 (on/off)", "General Purpose Button 2 (on/off)", - "General Purpose Button 3 (on/off)", "General Purpose Button 4 (on/off)", - 0, 0, 0, 0, 0, 0, 0, "Reverb Level", "Tremolo Level", "Chorus Level", "Celeste Level", - "Phaser Level", "Data Button increment", "Data Button decrement", "Non-registered Parameter (fine)", - "Non-registered Parameter (coarse)", "Registered Parameter (fine)", "Registered Parameter (coarse)", - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "All Sound Off", "All Controllers Off", - "Local Keyboard (on/off)", "All Notes Off", "Omni Mode Off", "Omni Mode On", "Mono Operation", - "Poly Operation" - }; + const char* names[] = + { + "Bank Select", "Modulation Wheel (coarse)", "Breath controller (coarse)", + 0, "Foot Pedal (coarse)", "Portamento Time (coarse)", + "Data Entry (coarse)", "Volume (coarse)", "Balance (coarse)", + 0, "Pan position (coarse)", "Expression (coarse)", "Effect Control 1 (coarse)", + "Effect Control 2 (coarse)", 0, 0, "General Purpose Slider 1", "General Purpose Slider 2", + "General Purpose Slider 3", "General Purpose Slider 4", 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, "Bank Select (fine)", "Modulation Wheel (fine)", "Breath controller (fine)", + 0, "Foot Pedal (fine)", "Portamento Time (fine)", "Data Entry (fine)", "Volume (fine)", + "Balance (fine)", 0, "Pan position (fine)", "Expression (fine)", "Effect Control 1 (fine)", + "Effect Control 2 (fine)", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "Hold Pedal (on/off)", "Portamento (on/off)", "Sustenuto Pedal (on/off)", "Soft Pedal (on/off)", + "Legato Pedal (on/off)", "Hold 2 Pedal (on/off)", "Sound Variation", "Sound Timbre", + "Sound Release Time", "Sound Attack Time", "Sound Brightness", "Sound Control 6", + "Sound Control 7", "Sound Control 8", "Sound Control 9", "Sound Control 10", + "General Purpose Button 1 (on/off)", "General Purpose Button 2 (on/off)", + "General Purpose Button 3 (on/off)", "General Purpose Button 4 (on/off)", + 0, 0, 0, 0, 0, 0, 0, "Reverb Level", "Tremolo Level", "Chorus Level", "Celeste Level", + "Phaser Level", "Data Button increment", "Data Button decrement", "Non-registered Parameter (fine)", + "Non-registered Parameter (coarse)", "Registered Parameter (fine)", "Registered Parameter (coarse)", + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "All Sound Off", "All Controllers Off", + "Local Keyboard (on/off)", "All Notes Off", "Omni Mode Off", "Omni Mode On", "Mono Operation", + "Poly Operation" + }; - return (((unsigned int) n) < 128) ? names[n] - : (const char*)0; + return (((unsigned int) n) < 128) ? names[n] + : (const char*)0; } END_JUCE_NAMESPACE @@ -28750,8 +28483,8 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MidiMessageCollector::MidiMessageCollector() - : lastCallbackTime (0), - sampleRate (44100.0001) + : lastCallbackTime (0), + sampleRate (44100.0001) { } @@ -28761,119 +28494,119 @@ MidiMessageCollector::~MidiMessageCollector() void MidiMessageCollector::reset (const double sampleRate_) { - jassert (sampleRate_ > 0); + jassert (sampleRate_ > 0); - const ScopedLock sl (midiCallbackLock); - sampleRate = sampleRate_; - incomingMessages.clear(); - lastCallbackTime = Time::getMillisecondCounterHiRes(); + const ScopedLock sl (midiCallbackLock); + sampleRate = sampleRate_; + incomingMessages.clear(); + lastCallbackTime = Time::getMillisecondCounterHiRes(); } void MidiMessageCollector::addMessageToQueue (const MidiMessage& message) { - // you need to call reset() to set the correct sample rate before using this object - jassert (sampleRate != 44100.0001); + // you need to call reset() to set the correct sample rate before using this object + jassert (sampleRate != 44100.0001); - // the messages that come in here need to be time-stamped correctly - see MidiInput - // for details of what the number should be. - jassert (message.getTimeStamp() != 0); + // the messages that come in here need to be time-stamped correctly - see MidiInput + // for details of what the number should be. + jassert (message.getTimeStamp() != 0); - const ScopedLock sl (midiCallbackLock); + const ScopedLock sl (midiCallbackLock); - const int sampleNumber - = (int) ((message.getTimeStamp() - 0.001 * lastCallbackTime) * sampleRate); + const int sampleNumber + = (int) ((message.getTimeStamp() - 0.001 * lastCallbackTime) * sampleRate); - incomingMessages.addEvent (message, sampleNumber); + incomingMessages.addEvent (message, sampleNumber); - // if the messages don't get used for over a second, we'd better - // get rid of any old ones to avoid the queue getting too big - if (sampleNumber > sampleRate) - incomingMessages.clear (0, sampleNumber - (int) sampleRate); + // if the messages don't get used for over a second, we'd better + // get rid of any old ones to avoid the queue getting too big + if (sampleNumber > sampleRate) + incomingMessages.clear (0, sampleNumber - (int) sampleRate); } void MidiMessageCollector::removeNextBlockOfMessages (MidiBuffer& destBuffer, - const int numSamples) + const int numSamples) { - // you need to call reset() to set the correct sample rate before using this object - jassert (sampleRate != 44100.0001); + // you need to call reset() to set the correct sample rate before using this object + jassert (sampleRate != 44100.0001); - const double timeNow = Time::getMillisecondCounterHiRes(); - const double msElapsed = timeNow - lastCallbackTime; + const double timeNow = Time::getMillisecondCounterHiRes(); + const double msElapsed = timeNow - lastCallbackTime; - const ScopedLock sl (midiCallbackLock); - lastCallbackTime = timeNow; + const ScopedLock sl (midiCallbackLock); + lastCallbackTime = timeNow; - if (! incomingMessages.isEmpty()) - { - int numSourceSamples = jmax (1, roundDoubleToInt (msElapsed * 0.001 * sampleRate)); + if (! incomingMessages.isEmpty()) + { + int numSourceSamples = jmax (1, roundToInt (msElapsed * 0.001 * sampleRate)); - int startSample = 0; - int scale = 1 << 16; + int startSample = 0; + int scale = 1 << 16; - const uint8* midiData; - int numBytes, samplePosition; + const uint8* midiData; + int numBytes, samplePosition; - MidiBuffer::Iterator iter (incomingMessages); + MidiBuffer::Iterator iter (incomingMessages); - if (numSourceSamples > numSamples) - { - // if our list of events is longer than the buffer we're being - // asked for, scale them down to squeeze them all in.. - const int maxBlockLengthToUse = numSamples << 5; + if (numSourceSamples > numSamples) + { + // if our list of events is longer than the buffer we're being + // asked for, scale them down to squeeze them all in.. + const int maxBlockLengthToUse = numSamples << 5; - if (numSourceSamples > maxBlockLengthToUse) - { - startSample = numSourceSamples - maxBlockLengthToUse; - numSourceSamples = maxBlockLengthToUse; - iter.setNextSamplePosition (startSample); - } + if (numSourceSamples > maxBlockLengthToUse) + { + startSample = numSourceSamples - maxBlockLengthToUse; + numSourceSamples = maxBlockLengthToUse; + iter.setNextSamplePosition (startSample); + } - scale = (numSamples << 10) / numSourceSamples; + scale = (numSamples << 10) / numSourceSamples; - while (iter.getNextEvent (midiData, numBytes, samplePosition)) - { - samplePosition = ((samplePosition - startSample) * scale) >> 10; + while (iter.getNextEvent (midiData, numBytes, samplePosition)) + { + samplePosition = ((samplePosition - startSample) * scale) >> 10; - destBuffer.addEvent (midiData, numBytes, - jlimit (0, numSamples - 1, samplePosition)); - } - } - else - { - // if our event list is shorter than the number we need, put them - // towards the end of the buffer - startSample = numSamples - numSourceSamples; + destBuffer.addEvent (midiData, numBytes, + jlimit (0, numSamples - 1, samplePosition)); + } + } + else + { + // if our event list is shorter than the number we need, put them + // towards the end of the buffer + startSample = numSamples - numSourceSamples; - while (iter.getNextEvent (midiData, numBytes, samplePosition)) - { - destBuffer.addEvent (midiData, numBytes, - jlimit (0, numSamples - 1, samplePosition + startSample)); - } - } + while (iter.getNextEvent (midiData, numBytes, samplePosition)) + { + destBuffer.addEvent (midiData, numBytes, + jlimit (0, numSamples - 1, samplePosition + startSample)); + } + } - incomingMessages.clear(); - } + incomingMessages.clear(); + } } void MidiMessageCollector::handleNoteOn (MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity) { - MidiMessage m (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity)); - m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001); + MidiMessage m (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity)); + m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001); - addMessageToQueue (m); + addMessageToQueue (m); } void MidiMessageCollector::handleNoteOff (MidiKeyboardState*, int midiChannel, int midiNoteNumber) { - MidiMessage m (MidiMessage::noteOff (midiChannel, midiNoteNumber)); - m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001); + MidiMessage m (MidiMessage::noteOff (midiChannel, midiNoteNumber)); + m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001); - addMessageToQueue (m); + addMessageToQueue (m); } void MidiMessageCollector::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message) { - addMessageToQueue (message); + addMessageToQueue (message); } END_JUCE_NAMESPACE @@ -28889,23 +28622,23 @@ MidiMessageSequence::MidiMessageSequence() MidiMessageSequence::MidiMessageSequence (const MidiMessageSequence& other) { - list.ensureStorageAllocated (other.list.size()); + list.ensureStorageAllocated (other.list.size()); - for (int i = 0; i < other.list.size(); ++i) - list.add (new MidiEventHolder (other.list.getUnchecked(i)->message)); + for (int i = 0; i < other.list.size(); ++i) + list.add (new MidiEventHolder (other.list.getUnchecked(i)->message)); } const MidiMessageSequence& MidiMessageSequence::operator= (const MidiMessageSequence& other) { - if (this != &other) - { - clear(); + if (this != &other) + { + clear(); - for (int i = 0; i < other.list.size(); ++i) - list.add (new MidiEventHolder (other.list.getUnchecked(i)->message)); - } + for (int i = 0; i < other.list.size(); ++i) + list.add (new MidiEventHolder (other.list.getUnchecked(i)->message)); + } - return *this; + return *this; } MidiMessageSequence::~MidiMessageSequence() @@ -28914,275 +28647,276 @@ MidiMessageSequence::~MidiMessageSequence() void MidiMessageSequence::clear() { - list.clear(); + list.clear(); } int MidiMessageSequence::getNumEvents() const { - return list.size(); + return list.size(); } MidiMessageSequence::MidiEventHolder* MidiMessageSequence::getEventPointer (const int index) const { - return list [index]; + return list [index]; } double MidiMessageSequence::getTimeOfMatchingKeyUp (const int index) const { - const MidiEventHolder* const meh = list [index]; + const MidiEventHolder* const meh = list [index]; - if (meh != 0 && meh->noteOffObject != 0) - return meh->noteOffObject->message.getTimeStamp(); - else - return 0.0; + if (meh != 0 && meh->noteOffObject != 0) + return meh->noteOffObject->message.getTimeStamp(); + else + return 0.0; } int MidiMessageSequence::getIndexOfMatchingKeyUp (const int index) const { - const MidiEventHolder* const meh = list [index]; + const MidiEventHolder* const meh = list [index]; - return (meh != 0) ? list.indexOf (meh->noteOffObject) : -1; + return (meh != 0) ? list.indexOf (meh->noteOffObject) : -1; } int MidiMessageSequence::getIndexOf (MidiEventHolder* const event) const { - return list.indexOf (event); + return list.indexOf (event); } int MidiMessageSequence::getNextIndexAtTime (const double timeStamp) const { - const int numEvents = list.size(); + const int numEvents = list.size(); - int i; - for (i = 0; i < numEvents; ++i) - if (list.getUnchecked(i)->message.getTimeStamp() >= timeStamp) - break; + int i; + for (i = 0; i < numEvents; ++i) + if (list.getUnchecked(i)->message.getTimeStamp() >= timeStamp) + break; - return i; + return i; } double MidiMessageSequence::getStartTime() const { - if (list.size() > 0) - return list.getUnchecked(0)->message.getTimeStamp(); - else - return 0; + if (list.size() > 0) + return list.getUnchecked(0)->message.getTimeStamp(); + else + return 0; } double MidiMessageSequence::getEndTime() const { - if (list.size() > 0) - return list.getLast()->message.getTimeStamp(); - else - return 0; + if (list.size() > 0) + return list.getLast()->message.getTimeStamp(); + else + return 0; } double MidiMessageSequence::getEventTime (const int index) const { - if (((unsigned int) index) < (unsigned int) list.size()) - return list.getUnchecked (index)->message.getTimeStamp(); + if (((unsigned int) index) < (unsigned int) list.size()) + return list.getUnchecked (index)->message.getTimeStamp(); - return 0.0; + return 0.0; } void MidiMessageSequence::addEvent (const MidiMessage& newMessage, - double timeAdjustment) + double timeAdjustment) { - MidiEventHolder* const newOne = new MidiEventHolder (newMessage); + MidiEventHolder* const newOne = new MidiEventHolder (newMessage); - timeAdjustment += newMessage.getTimeStamp(); - newOne->message.setTimeStamp (timeAdjustment); + timeAdjustment += newMessage.getTimeStamp(); + newOne->message.setTimeStamp (timeAdjustment); - int i; - for (i = list.size(); --i >= 0;) - if (list.getUnchecked(i)->message.getTimeStamp() <= timeAdjustment) - break; + int i; + for (i = list.size(); --i >= 0;) + if (list.getUnchecked(i)->message.getTimeStamp() <= timeAdjustment) + break; - list.insert (i + 1, newOne); + list.insert (i + 1, newOne); } void MidiMessageSequence::deleteEvent (const int index, - const bool deleteMatchingNoteUp) + const bool deleteMatchingNoteUp) { - if (((unsigned int) index) < (unsigned int) list.size()) - { - if (deleteMatchingNoteUp) - deleteEvent (getIndexOfMatchingKeyUp (index), false); + if (((unsigned int) index) < (unsigned int) list.size()) + { + if (deleteMatchingNoteUp) + deleteEvent (getIndexOfMatchingKeyUp (index), false); - list.remove (index); - } + list.remove (index); + } } void MidiMessageSequence::addSequence (const MidiMessageSequence& other, - double timeAdjustment, - double firstAllowableTime, - double endOfAllowableDestTimes) + double timeAdjustment, + double firstAllowableTime, + double endOfAllowableDestTimes) { - firstAllowableTime -= timeAdjustment; - endOfAllowableDestTimes -= timeAdjustment; + firstAllowableTime -= timeAdjustment; + endOfAllowableDestTimes -= timeAdjustment; - for (int i = 0; i < other.list.size(); ++i) - { - const MidiMessage& m = other.list.getUnchecked(i)->message; - const double t = m.getTimeStamp(); + for (int i = 0; i < other.list.size(); ++i) + { + const MidiMessage& m = other.list.getUnchecked(i)->message; + const double t = m.getTimeStamp(); - if (t >= firstAllowableTime && t < endOfAllowableDestTimes) - { - MidiEventHolder* const newOne = new MidiEventHolder (m); - newOne->message.setTimeStamp (timeAdjustment + t); + if (t >= firstAllowableTime && t < endOfAllowableDestTimes) + { + MidiEventHolder* const newOne = new MidiEventHolder (m); + newOne->message.setTimeStamp (timeAdjustment + t); - list.add (newOne); - } - } + list.add (newOne); + } + } - sort(); + sort(); } int MidiMessageSequence::compareElements (const MidiMessageSequence::MidiEventHolder* const first, - const MidiMessageSequence::MidiEventHolder* const second) throw() + const MidiMessageSequence::MidiEventHolder* const second) throw() { - const double diff = first->message.getTimeStamp() - - second->message.getTimeStamp(); + const double diff = first->message.getTimeStamp() + - second->message.getTimeStamp(); - return (diff > 0) - (diff < 0); + return (diff > 0) - (diff < 0); } void MidiMessageSequence::sort() { - list.sort (*this, true); + list.sort (*this, true); } void MidiMessageSequence::updateMatchedPairs() { - for (int i = 0; i < list.size(); ++i) - { - const MidiMessage& m1 = list.getUnchecked(i)->message; + for (int i = 0; i < list.size(); ++i) + { + const MidiMessage& m1 = list.getUnchecked(i)->message; - if (m1.isNoteOn()) - { - list.getUnchecked(i)->noteOffObject = 0; - const int note = m1.getNoteNumber(); - const int chan = m1.getChannel(); - const int len = list.size(); + if (m1.isNoteOn()) + { + list.getUnchecked(i)->noteOffObject = 0; + const int note = m1.getNoteNumber(); + const int chan = m1.getChannel(); + const int len = list.size(); - for (int j = i + 1; j < len; ++j) - { - const MidiMessage& m = list.getUnchecked(j)->message; + for (int j = i + 1; j < len; ++j) + { + const MidiMessage& m = list.getUnchecked(j)->message; - if (m.getNoteNumber() == note && m.getChannel() == chan) - { - if (m.isNoteOff()) - { - list.getUnchecked(i)->noteOffObject = list[j]; - break; - } - else if (m.isNoteOn()) - { - list.insert (j, new MidiEventHolder (MidiMessage::noteOff (chan, note))); - list.getUnchecked(j)->message.setTimeStamp (m.getTimeStamp()); - list.getUnchecked(i)->noteOffObject = list[j]; - break; - } - } - } - } - } + if (m.getNoteNumber() == note && m.getChannel() == chan) + { + if (m.isNoteOff()) + { + list.getUnchecked(i)->noteOffObject = list[j]; + break; + } + else if (m.isNoteOn()) + { + list.insert (j, new MidiEventHolder (MidiMessage::noteOff (chan, note))); + list.getUnchecked(j)->message.setTimeStamp (m.getTimeStamp()); + list.getUnchecked(i)->noteOffObject = list[j]; + break; + } + } + } + } + } } void MidiMessageSequence::addTimeToMessages (const double delta) { - for (int i = list.size(); --i >= 0;) - list.getUnchecked (i)->message.setTimeStamp (list.getUnchecked (i)->message.getTimeStamp() - + delta); + for (int i = list.size(); --i >= 0;) + list.getUnchecked (i)->message.setTimeStamp (list.getUnchecked (i)->message.getTimeStamp() + + delta); } void MidiMessageSequence::extractMidiChannelMessages (const int channelNumberToExtract, - MidiMessageSequence& destSequence, - const bool alsoIncludeMetaEvents) const + MidiMessageSequence& destSequence, + const bool alsoIncludeMetaEvents) const { - for (int i = 0; i < list.size(); ++i) - { - const MidiMessage& mm = list.getUnchecked(i)->message; + for (int i = 0; i < list.size(); ++i) + { + const MidiMessage& mm = list.getUnchecked(i)->message; - if (mm.isForChannel (channelNumberToExtract) - || (alsoIncludeMetaEvents && mm.isMetaEvent())) - { - destSequence.addEvent (mm); - } - } + if (mm.isForChannel (channelNumberToExtract) + || (alsoIncludeMetaEvents && mm.isMetaEvent())) + { + destSequence.addEvent (mm); + } + } } void MidiMessageSequence::extractSysExMessages (MidiMessageSequence& destSequence) const { - for (int i = 0; i < list.size(); ++i) - { - const MidiMessage& mm = list.getUnchecked(i)->message; + for (int i = 0; i < list.size(); ++i) + { + const MidiMessage& mm = list.getUnchecked(i)->message; - if (mm.isSysEx()) - destSequence.addEvent (mm); - } + if (mm.isSysEx()) + destSequence.addEvent (mm); + } } void MidiMessageSequence::deleteMidiChannelMessages (const int channelNumberToRemove) { - for (int i = list.size(); --i >= 0;) - if (list.getUnchecked(i)->message.isForChannel (channelNumberToRemove)) - list.remove(i); + for (int i = list.size(); --i >= 0;) + if (list.getUnchecked(i)->message.isForChannel (channelNumberToRemove)) + list.remove(i); } void MidiMessageSequence::deleteSysExMessages() { - for (int i = list.size(); --i >= 0;) - if (list.getUnchecked(i)->message.isSysEx()) - list.remove(i); + for (int i = list.size(); --i >= 0;) + if (list.getUnchecked(i)->message.isSysEx()) + list.remove(i); } void MidiMessageSequence::createControllerUpdatesForTime (const int channelNumber, - const double time, - OwnedArray& dest) + const double time, + OwnedArray& dest) { - bool doneProg = false; - bool donePitchWheel = false; - Array doneControllers (32); + bool doneProg = false; + bool donePitchWheel = false; + Array doneControllers; + doneControllers.ensureStorageAllocated (32); - for (int i = list.size(); --i >= 0;) - { - const MidiMessage& mm = list.getUnchecked(i)->message; + for (int i = list.size(); --i >= 0;) + { + const MidiMessage& mm = list.getUnchecked(i)->message; - if (mm.isForChannel (channelNumber) - && mm.getTimeStamp() <= time) - { - if (mm.isProgramChange()) - { - if (! doneProg) - { - dest.add (new MidiMessage (mm, 0.0)); - doneProg = true; - } - } - else if (mm.isController()) - { - if (! doneControllers.contains (mm.getControllerNumber())) - { - dest.add (new MidiMessage (mm, 0.0)); - doneControllers.add (mm.getControllerNumber()); - } - } - else if (mm.isPitchWheel()) - { - if (! donePitchWheel) - { - dest.add (new MidiMessage (mm, 0.0)); - donePitchWheel = true; - } - } - } - } + if (mm.isForChannel (channelNumber) + && mm.getTimeStamp() <= time) + { + if (mm.isProgramChange()) + { + if (! doneProg) + { + dest.add (new MidiMessage (mm, 0.0)); + doneProg = true; + } + } + else if (mm.isController()) + { + if (! doneControllers.contains (mm.getControllerNumber())) + { + dest.add (new MidiMessage (mm, 0.0)); + doneControllers.add (mm.getControllerNumber()); + } + } + else if (mm.isPitchWheel()) + { + if (! donePitchWheel) + { + dest.add (new MidiMessage (mm, 0.0)); + donePitchWheel = true; + } + } + } + } } MidiMessageSequence::MidiEventHolder::MidiEventHolder (const MidiMessage& message_) : message (message_), - noteOffObject (0) + noteOffObject (0) { } @@ -29218,7 +28952,7 @@ AudioPluginFormatManager::AudioPluginFormatManager() throw() AudioPluginFormatManager::~AudioPluginFormatManager() throw() { - clearSingletonInstance(); + clearSingletonInstance(); } juce_ImplementSingleton_SingleThreaded (AudioPluginFormatManager); @@ -29226,90 +28960,90 @@ juce_ImplementSingleton_SingleThreaded (AudioPluginFormatManager); void AudioPluginFormatManager::addDefaultFormats() { #ifdef JUCE_DEBUG - // you should only call this method once! - for (int i = formats.size(); --i >= 0;) - { + // you should only call this method once! + for (int i = formats.size(); --i >= 0;) + { #if JUCE_PLUGINHOST_VST - jassert (dynamic_cast (formats[i]) == 0); + jassert (dynamic_cast (formats[i]) == 0); #endif #if JUCE_PLUGINHOST_AU && JUCE_MAC - jassert (dynamic_cast (formats[i]) == 0); + jassert (dynamic_cast (formats[i]) == 0); #endif #if JUCE_PLUGINHOST_DX && JUCE_WIN32 - jassert (dynamic_cast (formats[i]) == 0); + jassert (dynamic_cast (formats[i]) == 0); #endif #if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX - jassert (dynamic_cast (formats[i]) == 0); + jassert (dynamic_cast (formats[i]) == 0); #endif - } + } #endif #if JUCE_PLUGINHOST_AU && JUCE_MAC - formats.add (new AudioUnitPluginFormat()); + formats.add (new AudioUnitPluginFormat()); #endif #if JUCE_PLUGINHOST_VST - formats.add (new VSTPluginFormat()); + formats.add (new VSTPluginFormat()); #endif #if JUCE_PLUGINHOST_DX && JUCE_WIN32 - formats.add (new DirectXPluginFormat()); + formats.add (new DirectXPluginFormat()); #endif #if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX - formats.add (new LADSPAPluginFormat()); + formats.add (new LADSPAPluginFormat()); #endif } int AudioPluginFormatManager::getNumFormats() throw() { - return formats.size(); + return formats.size(); } AudioPluginFormat* AudioPluginFormatManager::getFormat (const int index) throw() { - return formats [index]; + return formats [index]; } void AudioPluginFormatManager::addFormat (AudioPluginFormat* const format) throw() { - formats.add (format); + formats.add (format); } AudioPluginInstance* AudioPluginFormatManager::createPluginInstance (const PluginDescription& description, - String& errorMessage) const + String& errorMessage) const { - AudioPluginInstance* result = 0; + AudioPluginInstance* result = 0; - for (int i = 0; i < formats.size(); ++i) - { - result = formats.getUnchecked(i)->createInstanceFromDescription (description); + for (int i = 0; i < formats.size(); ++i) + { + result = formats.getUnchecked(i)->createInstanceFromDescription (description); - if (result != 0) - break; - } + if (result != 0) + break; + } - if (result == 0) - { - if (! doesPluginStillExist (description)) - errorMessage = TRANS ("This plug-in file no longer exists"); - else - errorMessage = TRANS ("This plug-in failed to load correctly"); - } + if (result == 0) + { + if (! doesPluginStillExist (description)) + errorMessage = TRANS ("This plug-in file no longer exists"); + else + errorMessage = TRANS ("This plug-in failed to load correctly"); + } - return result; + return result; } bool AudioPluginFormatManager::doesPluginStillExist (const PluginDescription& description) const { - for (int i = 0; i < formats.size(); ++i) - if (formats.getUnchecked(i)->getName() == description.pluginFormatName) - return formats.getUnchecked(i)->doesPluginStillExist (description); + for (int i = 0; i < formats.size(); ++i) + if (formats.getUnchecked(i)->getName() == description.pluginFormatName) + return formats.getUnchecked(i)->doesPluginStillExist (description); - return false; + return false; } END_JUCE_NAMESPACE @@ -29345,240 +29079,240 @@ KnownPluginList::~KnownPluginList() void KnownPluginList::clear() { - if (types.size() > 0) - { - types.clear(); - sendChangeMessage (this); - } + if (types.size() > 0) + { + types.clear(); + sendChangeMessage (this); + } } PluginDescription* KnownPluginList::getTypeForFile (const String& fileOrIdentifier) const throw() { - for (int i = 0; i < types.size(); ++i) - if (types.getUnchecked(i)->fileOrIdentifier == fileOrIdentifier) - return types.getUnchecked(i); + for (int i = 0; i < types.size(); ++i) + if (types.getUnchecked(i)->fileOrIdentifier == fileOrIdentifier) + return types.getUnchecked(i); - return 0; + return 0; } PluginDescription* KnownPluginList::getTypeForIdentifierString (const String& identifierString) const throw() { - for (int i = 0; i < types.size(); ++i) - if (types.getUnchecked(i)->createIdentifierString() == identifierString) - return types.getUnchecked(i); + for (int i = 0; i < types.size(); ++i) + if (types.getUnchecked(i)->createIdentifierString() == identifierString) + return types.getUnchecked(i); - return 0; + return 0; } bool KnownPluginList::addType (const PluginDescription& type) { - for (int i = types.size(); --i >= 0;) - { - if (types.getUnchecked(i)->isDuplicateOf (type)) - { - // strange - found a duplicate plugin with different info.. - jassert (types.getUnchecked(i)->name == type.name); - jassert (types.getUnchecked(i)->isInstrument == type.isInstrument); + for (int i = types.size(); --i >= 0;) + { + if (types.getUnchecked(i)->isDuplicateOf (type)) + { + // strange - found a duplicate plugin with different info.. + jassert (types.getUnchecked(i)->name == type.name); + jassert (types.getUnchecked(i)->isInstrument == type.isInstrument); - *types.getUnchecked(i) = type; - return false; - } - } + *types.getUnchecked(i) = type; + return false; + } + } - types.add (new PluginDescription (type)); - sendChangeMessage (this); - return true; + types.add (new PluginDescription (type)); + sendChangeMessage (this); + return true; } void KnownPluginList::removeType (const int index) throw() { - types.remove (index); - sendChangeMessage (this); + types.remove (index); + sendChangeMessage (this); } static Time getFileModTime (const String& fileOrIdentifier) throw() { - if (fileOrIdentifier.startsWithChar (T('/')) - || fileOrIdentifier[1] == T(':')) - { - return File (fileOrIdentifier).getLastModificationTime(); - } + if (fileOrIdentifier.startsWithChar (T('/')) + || fileOrIdentifier[1] == T(':')) + { + return File (fileOrIdentifier).getLastModificationTime(); + } - return Time (0); + return Time (0); } static bool timesAreDifferent (const Time& t1, const Time& t2) throw() { - return t1 != t2 || t1 == Time (0); + return t1 != t2 || t1 == Time (0); } bool KnownPluginList::isListingUpToDate (const String& fileOrIdentifier) const throw() { - if (getTypeForFile (fileOrIdentifier) == 0) - return false; + if (getTypeForFile (fileOrIdentifier) == 0) + return false; - for (int i = types.size(); --i >= 0;) - { - const PluginDescription* const d = types.getUnchecked(i); + for (int i = types.size(); --i >= 0;) + { + const PluginDescription* const d = types.getUnchecked(i); - if (d->fileOrIdentifier == fileOrIdentifier - && timesAreDifferent (d->lastFileModTime, getFileModTime (fileOrIdentifier))) - { - return false; - } - } + if (d->fileOrIdentifier == fileOrIdentifier + && timesAreDifferent (d->lastFileModTime, getFileModTime (fileOrIdentifier))) + { + return false; + } + } - return true; + return true; } bool KnownPluginList::scanAndAddFile (const String& fileOrIdentifier, - const bool dontRescanIfAlreadyInList, - OwnedArray & typesFound, - AudioPluginFormat& format) + const bool dontRescanIfAlreadyInList, + OwnedArray & typesFound, + AudioPluginFormat& format) { - bool addedOne = false; + bool addedOne = false; - if (dontRescanIfAlreadyInList - && getTypeForFile (fileOrIdentifier) != 0) - { - bool needsRescanning = false; + if (dontRescanIfAlreadyInList + && getTypeForFile (fileOrIdentifier) != 0) + { + bool needsRescanning = false; - for (int i = types.size(); --i >= 0;) - { - const PluginDescription* const d = types.getUnchecked(i); + for (int i = types.size(); --i >= 0;) + { + const PluginDescription* const d = types.getUnchecked(i); - if (d->fileOrIdentifier == fileOrIdentifier) - { - if (timesAreDifferent (d->lastFileModTime, getFileModTime (fileOrIdentifier))) - needsRescanning = true; - else - typesFound.add (new PluginDescription (*d)); - } - } + if (d->fileOrIdentifier == fileOrIdentifier) + { + if (timesAreDifferent (d->lastFileModTime, getFileModTime (fileOrIdentifier))) + needsRescanning = true; + else + typesFound.add (new PluginDescription (*d)); + } + } - if (! needsRescanning) - return false; - } + if (! needsRescanning) + return false; + } - OwnedArray found; - format.findAllTypesForFile (found, fileOrIdentifier); + OwnedArray found; + format.findAllTypesForFile (found, fileOrIdentifier); - for (int i = 0; i < found.size(); ++i) - { - PluginDescription* const desc = found.getUnchecked(i); - jassert (desc != 0); + for (int i = 0; i < found.size(); ++i) + { + PluginDescription* const desc = found.getUnchecked(i); + jassert (desc != 0); - if (addType (*desc)) - addedOne = true; + if (addType (*desc)) + addedOne = true; - typesFound.add (new PluginDescription (*desc)); - } + typesFound.add (new PluginDescription (*desc)); + } - return addedOne; + return addedOne; } void KnownPluginList::scanAndAddDragAndDroppedFiles (const StringArray& files, - OwnedArray & typesFound) + OwnedArray & typesFound) { - for (int i = 0; i < files.size(); ++i) - { - bool loaded = false; + for (int i = 0; i < files.size(); ++i) + { + bool loaded = false; - for (int j = 0; j < AudioPluginFormatManager::getInstance()->getNumFormats(); ++j) - { - AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (j); + for (int j = 0; j < AudioPluginFormatManager::getInstance()->getNumFormats(); ++j) + { + AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (j); - if (scanAndAddFile (files[i], true, typesFound, *format)) - loaded = true; - } + if (scanAndAddFile (files[i], true, typesFound, *format)) + loaded = true; + } - if (! loaded) - { - const File f (files[i]); + if (! loaded) + { + const File f (files[i]); - if (f.isDirectory()) - { - StringArray s; + if (f.isDirectory()) + { + StringArray s; - { - OwnedArray subFiles; - f.findChildFiles (subFiles, File::findFilesAndDirectories, false); + { + OwnedArray subFiles; + f.findChildFiles (subFiles, File::findFilesAndDirectories, false); - for (int j = 0; j < subFiles.size(); ++j) - s.add (subFiles.getUnchecked (j)->getFullPathName()); - } + for (int j = 0; j < subFiles.size(); ++j) + s.add (subFiles.getUnchecked (j)->getFullPathName()); + } - scanAndAddDragAndDroppedFiles (s, typesFound); - } - } - } + scanAndAddDragAndDroppedFiles (s, typesFound); + } + } + } } class PluginSorter { public: - KnownPluginList::SortMethod method; + KnownPluginList::SortMethod method; - PluginSorter() throw() {} + PluginSorter() throw() {} - int compareElements (const PluginDescription* const first, - const PluginDescription* const second) const throw() - { - int diff = 0; + int compareElements (const PluginDescription* const first, + const PluginDescription* const second) const throw() + { + int diff = 0; - if (method == KnownPluginList::sortByCategory) - diff = first->category.compareLexicographically (second->category); - else if (method == KnownPluginList::sortByManufacturer) - diff = first->manufacturerName.compareLexicographically (second->manufacturerName); - else if (method == KnownPluginList::sortByFileSystemLocation) - diff = first->fileOrIdentifier.replaceCharacter (T('\\'), T('/')) - .upToLastOccurrenceOf (T("/"), false, false) - .compare (second->fileOrIdentifier.replaceCharacter (T('\\'), T('/')) - .upToLastOccurrenceOf (T("/"), false, false)); + if (method == KnownPluginList::sortByCategory) + diff = first->category.compareLexicographically (second->category); + else if (method == KnownPluginList::sortByManufacturer) + diff = first->manufacturerName.compareLexicographically (second->manufacturerName); + else if (method == KnownPluginList::sortByFileSystemLocation) + diff = first->fileOrIdentifier.replaceCharacter (T('\\'), T('/')) + .upToLastOccurrenceOf (T("/"), false, false) + .compare (second->fileOrIdentifier.replaceCharacter (T('\\'), T('/')) + .upToLastOccurrenceOf (T("/"), false, false)); - if (diff == 0) - diff = first->name.compareLexicographically (second->name); + if (diff == 0) + diff = first->name.compareLexicographically (second->name); - return diff; - } + return diff; + } }; void KnownPluginList::sort (const SortMethod method) { - if (method != defaultOrder) - { - PluginSorter sorter; - sorter.method = method; - types.sort (sorter, true); + if (method != defaultOrder) + { + PluginSorter sorter; + sorter.method = method; + types.sort (sorter, true); - sendChangeMessage (this); - } + sendChangeMessage (this); + } } XmlElement* KnownPluginList::createXml() const { - XmlElement* const e = new XmlElement (T("KNOWNPLUGINS")); + XmlElement* const e = new XmlElement (T("KNOWNPLUGINS")); - for (int i = 0; i < types.size(); ++i) - e->addChildElement (types.getUnchecked(i)->createXml()); + for (int i = 0; i < types.size(); ++i) + e->addChildElement (types.getUnchecked(i)->createXml()); - return e; + return e; } void KnownPluginList::recreateFromXml (const XmlElement& xml) { - clear(); + clear(); - if (xml.hasTagName (T("KNOWNPLUGINS"))) - { - forEachXmlChildElement (xml, e) - { - PluginDescription info; + if (xml.hasTagName (T("KNOWNPLUGINS"))) + { + forEachXmlChildElement (xml, e) + { + PluginDescription info; - if (info.loadFromXml (*e)) - addType (info); - } - } + if (info.loadFromXml (*e)) + addType (info); + } + } } const int menuIdBase = 0x324503f4; @@ -29587,169 +29321,169 @@ const int menuIdBase = 0x324503f4; struct PluginFilesystemTree { private: - String folder; - OwnedArray subFolders; - Array plugins; + String folder; + OwnedArray subFolders; + Array plugins; - void addPlugin (PluginDescription* const pd, const String& path) - { - if (path.isEmpty()) - { - plugins.add (pd); - } - else - { - const String firstSubFolder (path.upToFirstOccurrenceOf (T("/"), false, false)); - const String remainingPath (path.fromFirstOccurrenceOf (T("/"), false, false)); + void addPlugin (PluginDescription* const pd, const String& path) + { + if (path.isEmpty()) + { + plugins.add (pd); + } + else + { + const String firstSubFolder (path.upToFirstOccurrenceOf (T("/"), false, false)); + const String remainingPath (path.fromFirstOccurrenceOf (T("/"), false, false)); - for (int i = subFolders.size(); --i >= 0;) - { - if (subFolders.getUnchecked(i)->folder.equalsIgnoreCase (firstSubFolder)) - { - subFolders.getUnchecked(i)->addPlugin (pd, remainingPath); - return; - } - } + for (int i = subFolders.size(); --i >= 0;) + { + if (subFolders.getUnchecked(i)->folder.equalsIgnoreCase (firstSubFolder)) + { + subFolders.getUnchecked(i)->addPlugin (pd, remainingPath); + return; + } + } - PluginFilesystemTree* const newFolder = new PluginFilesystemTree(); - newFolder->folder = firstSubFolder; - subFolders.add (newFolder); + PluginFilesystemTree* const newFolder = new PluginFilesystemTree(); + newFolder->folder = firstSubFolder; + subFolders.add (newFolder); - newFolder->addPlugin (pd, remainingPath); - } - } + newFolder->addPlugin (pd, remainingPath); + } + } - // removes any deeply nested folders that don't contain any actual plugins - void optimise() - { - for (int i = subFolders.size(); --i >= 0;) - { - PluginFilesystemTree* const sub = subFolders.getUnchecked(i); + // removes any deeply nested folders that don't contain any actual plugins + void optimise() + { + for (int i = subFolders.size(); --i >= 0;) + { + PluginFilesystemTree* const sub = subFolders.getUnchecked(i); - sub->optimise(); + sub->optimise(); - if (sub->plugins.size() == 0) - { - for (int j = 0; j < sub->subFolders.size(); ++j) - subFolders.add (sub->subFolders.getUnchecked(j)); + if (sub->plugins.size() == 0) + { + for (int j = 0; j < sub->subFolders.size(); ++j) + subFolders.add (sub->subFolders.getUnchecked(j)); - sub->subFolders.clear (false); - subFolders.remove (i); - } - } - } + sub->subFolders.clear (false); + subFolders.remove (i); + } + } + } public: - void buildTree (const Array & allPlugins) - { - for (int i = 0; i < allPlugins.size(); ++i) - { - String path (allPlugins.getUnchecked(i) - ->fileOrIdentifier.replaceCharacter (T('\\'), T('/')) - .upToLastOccurrenceOf (T("/"), false, false)); + void buildTree (const Array & allPlugins) + { + for (int i = 0; i < allPlugins.size(); ++i) + { + String path (allPlugins.getUnchecked(i) + ->fileOrIdentifier.replaceCharacter (T('\\'), T('/')) + .upToLastOccurrenceOf (T("/"), false, false)); - if (path.substring (1, 2) == T(":")) - path = path.substring (2); + if (path.substring (1, 2) == T(":")) + path = path.substring (2); - addPlugin (allPlugins.getUnchecked(i), path); - } + addPlugin (allPlugins.getUnchecked(i), path); + } - optimise(); - } + optimise(); + } - void addToMenu (PopupMenu& m, const OwnedArray & allPlugins) const - { - int i; - for (i = 0; i < subFolders.size(); ++i) - { - const PluginFilesystemTree* const sub = subFolders.getUnchecked(i); + void addToMenu (PopupMenu& m, const OwnedArray & allPlugins) const + { + int i; + for (i = 0; i < subFolders.size(); ++i) + { + const PluginFilesystemTree* const sub = subFolders.getUnchecked(i); - PopupMenu subMenu; - sub->addToMenu (subMenu, allPlugins); + PopupMenu subMenu; + sub->addToMenu (subMenu, allPlugins); #if JUCE_MAC - // avoid the special AU formatting nonsense on Mac.. - m.addSubMenu (sub->folder.fromFirstOccurrenceOf (T(":"), false, false), subMenu); + // avoid the special AU formatting nonsense on Mac.. + m.addSubMenu (sub->folder.fromFirstOccurrenceOf (T(":"), false, false), subMenu); #else - m.addSubMenu (sub->folder, subMenu); + m.addSubMenu (sub->folder, subMenu); #endif - } + } - for (i = 0; i < plugins.size(); ++i) - { - PluginDescription* const plugin = plugins.getUnchecked(i); + for (i = 0; i < plugins.size(); ++i) + { + PluginDescription* const plugin = plugins.getUnchecked(i); - m.addItem (allPlugins.indexOf (plugin) + menuIdBase, - plugin->name, true, false); - } - } + m.addItem (allPlugins.indexOf (plugin) + menuIdBase, + plugin->name, true, false); + } + } }; void KnownPluginList::addToMenu (PopupMenu& menu, const SortMethod sortMethod) const { - Array sorted; + Array sorted; - { - PluginSorter sorter; - sorter.method = sortMethod; + { + PluginSorter sorter; + sorter.method = sortMethod; - for (int i = 0; i < types.size(); ++i) - sorted.addSorted (sorter, types.getUnchecked(i)); - } + for (int i = 0; i < types.size(); ++i) + sorted.addSorted (sorter, types.getUnchecked(i)); + } - if (sortMethod == sortByCategory - || sortMethod == sortByManufacturer) - { - String lastSubMenuName; - PopupMenu sub; + if (sortMethod == sortByCategory + || sortMethod == sortByManufacturer) + { + String lastSubMenuName; + PopupMenu sub; - for (int i = 0; i < sorted.size(); ++i) - { - const PluginDescription* const pd = sorted.getUnchecked(i); - String thisSubMenuName (sortMethod == sortByCategory ? pd->category - : pd->manufacturerName); + for (int i = 0; i < sorted.size(); ++i) + { + const PluginDescription* const pd = sorted.getUnchecked(i); + String thisSubMenuName (sortMethod == sortByCategory ? pd->category + : pd->manufacturerName); - if (! thisSubMenuName.containsNonWhitespaceChars()) - thisSubMenuName = T("Other"); + if (! thisSubMenuName.containsNonWhitespaceChars()) + thisSubMenuName = T("Other"); - if (thisSubMenuName != lastSubMenuName) - { - if (sub.getNumItems() > 0) - { - menu.addSubMenu (lastSubMenuName, sub); - sub.clear(); - } + if (thisSubMenuName != lastSubMenuName) + { + if (sub.getNumItems() > 0) + { + menu.addSubMenu (lastSubMenuName, sub); + sub.clear(); + } - lastSubMenuName = thisSubMenuName; - } + lastSubMenuName = thisSubMenuName; + } - sub.addItem (types.indexOf (pd) + menuIdBase, pd->name, true, false); - } + sub.addItem (types.indexOf (pd) + menuIdBase, pd->name, true, false); + } - if (sub.getNumItems() > 0) - menu.addSubMenu (lastSubMenuName, sub); - } - else if (sortMethod == sortByFileSystemLocation) - { - PluginFilesystemTree root; - root.buildTree (sorted); - root.addToMenu (menu, types); - } - else - { - for (int i = 0; i < sorted.size(); ++i) - { - const PluginDescription* const pd = sorted.getUnchecked(i); - menu.addItem (types.indexOf (pd) + menuIdBase, pd->name, true, false); - } - } + if (sub.getNumItems() > 0) + menu.addSubMenu (lastSubMenuName, sub); + } + else if (sortMethod == sortByFileSystemLocation) + { + PluginFilesystemTree root; + root.buildTree (sorted); + root.addToMenu (menu, types); + } + else + { + for (int i = 0; i < sorted.size(); ++i) + { + const PluginDescription* const pd = sorted.getUnchecked(i); + menu.addItem (types.indexOf (pd) + menuIdBase, pd->name, true, false); + } + } } int KnownPluginList::getIndexChosenByMenu (const int menuResultCode) const { - const int i = menuResultCode - menuIdBase; + const int i = menuResultCode - menuIdBase; - return (((unsigned int) i) < (unsigned int) types.size()) ? i : -1; + return (((unsigned int) i) < (unsigned int) types.size()) ? i : -1; } END_JUCE_NAMESPACE @@ -29760,10 +29494,10 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE PluginDescription::PluginDescription() throw() - : uid (0), - isInstrument (false), - numInputChannels (0), - numOutputChannels (0) + : uid (0), + isInstrument (false), + numInputChannels (0), + numOutputChannels (0) { } @@ -29772,89 +29506,89 @@ PluginDescription::~PluginDescription() throw() } PluginDescription::PluginDescription (const PluginDescription& other) throw() - : name (other.name), - pluginFormatName (other.pluginFormatName), - category (other.category), - manufacturerName (other.manufacturerName), - version (other.version), - fileOrIdentifier (other.fileOrIdentifier), - lastFileModTime (other.lastFileModTime), - uid (other.uid), - isInstrument (other.isInstrument), - numInputChannels (other.numInputChannels), - numOutputChannels (other.numOutputChannels) + : name (other.name), + pluginFormatName (other.pluginFormatName), + category (other.category), + manufacturerName (other.manufacturerName), + version (other.version), + fileOrIdentifier (other.fileOrIdentifier), + lastFileModTime (other.lastFileModTime), + uid (other.uid), + isInstrument (other.isInstrument), + numInputChannels (other.numInputChannels), + numOutputChannels (other.numOutputChannels) { } const PluginDescription& PluginDescription::operator= (const PluginDescription& other) throw() { - name = other.name; - pluginFormatName = other.pluginFormatName; - category = other.category; - manufacturerName = other.manufacturerName; - version = other.version; - fileOrIdentifier = other.fileOrIdentifier; - uid = other.uid; - isInstrument = other.isInstrument; - lastFileModTime = other.lastFileModTime; - numInputChannels = other.numInputChannels; - numOutputChannels = other.numOutputChannels; + name = other.name; + pluginFormatName = other.pluginFormatName; + category = other.category; + manufacturerName = other.manufacturerName; + version = other.version; + fileOrIdentifier = other.fileOrIdentifier; + uid = other.uid; + isInstrument = other.isInstrument; + lastFileModTime = other.lastFileModTime; + numInputChannels = other.numInputChannels; + numOutputChannels = other.numOutputChannels; - return *this; + return *this; } bool PluginDescription::isDuplicateOf (const PluginDescription& other) const { - return fileOrIdentifier == other.fileOrIdentifier - && uid == other.uid; + return fileOrIdentifier == other.fileOrIdentifier + && uid == other.uid; } const String PluginDescription::createIdentifierString() const throw() { - return pluginFormatName - + T("-") + name - + T("-") + String::toHexString (fileOrIdentifier.hashCode()) - + T("-") + String::toHexString (uid); + return pluginFormatName + + T("-") + name + + T("-") + String::toHexString (fileOrIdentifier.hashCode()) + + T("-") + String::toHexString (uid); } XmlElement* PluginDescription::createXml() const { - XmlElement* const e = new XmlElement (T("PLUGIN")); - e->setAttribute (T("name"), name); - e->setAttribute (T("format"), pluginFormatName); - e->setAttribute (T("category"), category); - e->setAttribute (T("manufacturer"), manufacturerName); - e->setAttribute (T("version"), version); - e->setAttribute (T("file"), fileOrIdentifier); - e->setAttribute (T("uid"), String::toHexString (uid)); - e->setAttribute (T("isInstrument"), isInstrument); - e->setAttribute (T("fileTime"), String::toHexString (lastFileModTime.toMilliseconds())); - e->setAttribute (T("numInputs"), numInputChannels); - e->setAttribute (T("numOutputs"), numOutputChannels); + XmlElement* const e = new XmlElement (T("PLUGIN")); + e->setAttribute (T("name"), name); + e->setAttribute (T("format"), pluginFormatName); + e->setAttribute (T("category"), category); + e->setAttribute (T("manufacturer"), manufacturerName); + e->setAttribute (T("version"), version); + e->setAttribute (T("file"), fileOrIdentifier); + e->setAttribute (T("uid"), String::toHexString (uid)); + e->setAttribute (T("isInstrument"), isInstrument); + e->setAttribute (T("fileTime"), String::toHexString (lastFileModTime.toMilliseconds())); + e->setAttribute (T("numInputs"), numInputChannels); + e->setAttribute (T("numOutputs"), numOutputChannels); - return e; + return e; } bool PluginDescription::loadFromXml (const XmlElement& xml) { - if (xml.hasTagName (T("PLUGIN"))) - { - name = xml.getStringAttribute (T("name")); - pluginFormatName = xml.getStringAttribute (T("format")); - category = xml.getStringAttribute (T("category")); - manufacturerName = xml.getStringAttribute (T("manufacturer")); - version = xml.getStringAttribute (T("version")); - fileOrIdentifier = xml.getStringAttribute (T("file")); - uid = xml.getStringAttribute (T("uid")).getHexValue32(); - isInstrument = xml.getBoolAttribute (T("isInstrument"), false); - lastFileModTime = Time (xml.getStringAttribute (T("fileTime")).getHexValue64()); - numInputChannels = xml.getIntAttribute (T("numInputs")); - numOutputChannels = xml.getIntAttribute (T("numOutputs")); + if (xml.hasTagName (T("PLUGIN"))) + { + name = xml.getStringAttribute (T("name")); + pluginFormatName = xml.getStringAttribute (T("format")); + category = xml.getStringAttribute (T("category")); + manufacturerName = xml.getStringAttribute (T("manufacturer")); + version = xml.getStringAttribute (T("version")); + fileOrIdentifier = xml.getStringAttribute (T("file")); + uid = xml.getStringAttribute (T("uid")).getHexValue32(); + isInstrument = xml.getBoolAttribute (T("isInstrument"), false); + lastFileModTime = Time (xml.getStringAttribute (T("fileTime")).getHexValue64()); + numInputChannels = xml.getIntAttribute (T("numInputs")); + numOutputChannels = xml.getIntAttribute (T("numOutputs")); - return true; - } + return true; + } - return false; + return false; } END_JUCE_NAMESPACE @@ -29865,32 +29599,32 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE PluginDirectoryScanner::PluginDirectoryScanner (KnownPluginList& listToAddTo, - AudioPluginFormat& formatToLookFor, - FileSearchPath directoriesToSearch, - const bool recursive, - const File& deadMansPedalFile_) - : list (listToAddTo), - format (formatToLookFor), - deadMansPedalFile (deadMansPedalFile_), - nextIndex (0), - progress (0) + AudioPluginFormat& formatToLookFor, + FileSearchPath directoriesToSearch, + const bool recursive, + const File& deadMansPedalFile_) + : list (listToAddTo), + format (formatToLookFor), + deadMansPedalFile (deadMansPedalFile_), + nextIndex (0), + progress (0) { - directoriesToSearch.removeRedundantPaths(); + directoriesToSearch.removeRedundantPaths(); - filesOrIdentifiersToScan = format.searchPathsForPlugins (directoriesToSearch, recursive); + filesOrIdentifiersToScan = format.searchPathsForPlugins (directoriesToSearch, recursive); - // If any plugins have crashed recently when being loaded, move them to the - // end of the list to give the others a chance to load correctly.. - const StringArray crashedPlugins (getDeadMansPedalFile()); + // If any plugins have crashed recently when being loaded, move them to the + // end of the list to give the others a chance to load correctly.. + const StringArray crashedPlugins (getDeadMansPedalFile()); - for (int i = 0; i < crashedPlugins.size(); ++i) - { - const String f = crashedPlugins[i]; + for (int i = 0; i < crashedPlugins.size(); ++i) + { + const String f = crashedPlugins[i]; - for (int j = filesOrIdentifiersToScan.size(); --j >= 0;) - if (f == filesOrIdentifiersToScan[j]) - filesOrIdentifiersToScan.move (j, -1); - } + for (int j = filesOrIdentifiersToScan.size(); --j >= 0;) + if (f == filesOrIdentifiersToScan[j]) + filesOrIdentifiersToScan.move (j, -1); + } } PluginDirectoryScanner::~PluginDirectoryScanner() @@ -29899,62 +29633,62 @@ PluginDirectoryScanner::~PluginDirectoryScanner() const String PluginDirectoryScanner::getNextPluginFileThatWillBeScanned() const throw() { - return format.getNameOfPluginFromIdentifier (filesOrIdentifiersToScan [nextIndex]); + return format.getNameOfPluginFromIdentifier (filesOrIdentifiersToScan [nextIndex]); } bool PluginDirectoryScanner::scanNextFile (const bool dontRescanIfAlreadyInList) { - String file (filesOrIdentifiersToScan [nextIndex]); + String file (filesOrIdentifiersToScan [nextIndex]); - if (file.isNotEmpty()) - { - if (! list.isListingUpToDate (file)) - { - OwnedArray typesFound; + if (file.isNotEmpty()) + { + if (! list.isListingUpToDate (file)) + { + OwnedArray typesFound; - // Add this plugin to the end of the dead-man's pedal list in case it crashes... - StringArray crashedPlugins (getDeadMansPedalFile()); - crashedPlugins.removeString (file); - crashedPlugins.add (file); - setDeadMansPedalFile (crashedPlugins); + // Add this plugin to the end of the dead-man's pedal list in case it crashes... + StringArray crashedPlugins (getDeadMansPedalFile()); + crashedPlugins.removeString (file); + crashedPlugins.add (file); + setDeadMansPedalFile (crashedPlugins); - list.scanAndAddFile (file, - dontRescanIfAlreadyInList, - typesFound, - format); + list.scanAndAddFile (file, + dontRescanIfAlreadyInList, + typesFound, + format); - // Managed to load without crashing, so remove it from the dead-man's-pedal.. - crashedPlugins.removeString (file); - setDeadMansPedalFile (crashedPlugins); + // Managed to load without crashing, so remove it from the dead-man's-pedal.. + crashedPlugins.removeString (file); + setDeadMansPedalFile (crashedPlugins); - if (typesFound.size() == 0) - failedFiles.add (file); - } + if (typesFound.size() == 0) + failedFiles.add (file); + } - ++nextIndex; - progress = nextIndex / (float) filesOrIdentifiersToScan.size(); - } + ++nextIndex; + progress = nextIndex / (float) filesOrIdentifiersToScan.size(); + } - return nextIndex < filesOrIdentifiersToScan.size(); + return nextIndex < filesOrIdentifiersToScan.size(); } const StringArray PluginDirectoryScanner::getDeadMansPedalFile() throw() { - StringArray lines; + StringArray lines; - if (deadMansPedalFile != File::nonexistent) - { - lines.addLines (deadMansPedalFile.loadFileAsString()); - lines.removeEmptyStrings(); - } + if (deadMansPedalFile != File::nonexistent) + { + lines.addLines (deadMansPedalFile.loadFileAsString()); + lines.removeEmptyStrings(); + } - return lines; + return lines; } void PluginDirectoryScanner::setDeadMansPedalFile (const StringArray& newContents) throw() { - if (deadMansPedalFile != File::nonexistent) - deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true); + if (deadMansPedalFile != File::nonexistent) + deadMansPedalFile.replaceWithText (newContents.joinIntoString ("\n"), true, true); } END_JUCE_NAMESPACE @@ -29965,265 +29699,265 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE PluginListComponent::PluginListComponent (KnownPluginList& listToEdit, - const File& deadMansPedalFile_, - PropertiesFile* const propertiesToUse_) - : list (listToEdit), - deadMansPedalFile (deadMansPedalFile_), - propertiesToUse (propertiesToUse_) + const File& deadMansPedalFile_, + PropertiesFile* const propertiesToUse_) + : list (listToEdit), + deadMansPedalFile (deadMansPedalFile_), + propertiesToUse (propertiesToUse_) { - addAndMakeVisible (listBox = new ListBox (String::empty, this)); + addAndMakeVisible (listBox = new ListBox (String::empty, this)); - addAndMakeVisible (optionsButton = new TextButton ("Options...")); - optionsButton->addButtonListener (this); - optionsButton->setTriggeredOnMouseDown (true); + addAndMakeVisible (optionsButton = new TextButton ("Options...")); + optionsButton->addButtonListener (this); + optionsButton->setTriggeredOnMouseDown (true); - setSize (400, 600); - list.addChangeListener (this); + setSize (400, 600); + list.addChangeListener (this); } PluginListComponent::~PluginListComponent() { - list.removeChangeListener (this); - deleteAllChildren(); + list.removeChangeListener (this); + deleteAllChildren(); } void PluginListComponent::resized() { - listBox->setBounds (0, 0, getWidth(), getHeight() - 30); - optionsButton->changeWidthToFitText (24); - optionsButton->setTopLeftPosition (8, getHeight() - 28); + listBox->setBounds (0, 0, getWidth(), getHeight() - 30); + optionsButton->changeWidthToFitText (24); + optionsButton->setTopLeftPosition (8, getHeight() - 28); } void PluginListComponent::changeListenerCallback (void*) { - listBox->updateContent(); - listBox->repaint(); + listBox->updateContent(); + listBox->repaint(); } int PluginListComponent::getNumRows() { - return list.getNumTypes(); + return list.getNumTypes(); } void PluginListComponent::paintListBoxItem (int row, - Graphics& g, - int width, int height, - bool rowIsSelected) + Graphics& g, + int width, int height, + bool rowIsSelected) { - if (rowIsSelected) - g.fillAll (findColour (TextEditor::highlightColourId)); + if (rowIsSelected) + g.fillAll (findColour (TextEditor::highlightColourId)); - const PluginDescription* const pd = list.getType (row); + const PluginDescription* const pd = list.getType (row); - if (pd != 0) - { - GlyphArrangement ga; - ga.addCurtailedLineOfText (Font (height * 0.7f, Font::bold), pd->name, 8.0f, height * 0.8f, width - 10.0f, true); + if (pd != 0) + { + GlyphArrangement ga; + ga.addCurtailedLineOfText (Font (height * 0.7f, Font::bold), pd->name, 8.0f, height * 0.8f, width - 10.0f, true); - g.setColour (Colours::black); - ga.draw (g); + g.setColour (Colours::black); + ga.draw (g); - float x, y, r, b; - ga.getBoundingBox (0, -1, x, y, r, b, false); + float x, y, r, b; + ga.getBoundingBox (0, -1, x, y, r, b, false); - String desc; - desc << pd->pluginFormatName - << (pd->isInstrument ? " instrument" : " effect") - << " - " - << pd->numInputChannels << (pd->numInputChannels == 1 ? " in" : " ins") - << " / " - << pd->numOutputChannels << (pd->numOutputChannels == 1 ? " out" : " outs"); + String desc; + desc << pd->pluginFormatName + << (pd->isInstrument ? " instrument" : " effect") + << " - " + << pd->numInputChannels << (pd->numInputChannels == 1 ? " in" : " ins") + << " / " + << pd->numOutputChannels << (pd->numOutputChannels == 1 ? " out" : " outs"); - if (pd->manufacturerName.isNotEmpty()) - desc << " - " << pd->manufacturerName; + if (pd->manufacturerName.isNotEmpty()) + desc << " - " << pd->manufacturerName; - if (pd->version.isNotEmpty()) - desc << " - " << pd->version; + if (pd->version.isNotEmpty()) + desc << " - " << pd->version; - if (pd->category.isNotEmpty()) - desc << " - category: '" << pd->category << '\''; + if (pd->category.isNotEmpty()) + desc << " - category: '" << pd->category << '\''; - g.setColour (Colours::grey); + g.setColour (Colours::grey); - ga.clear(); - ga.addCurtailedLineOfText (Font (height * 0.6f), desc, r + 10.0f, height * 0.8f, width - r - 12.0f, true); - ga.draw (g); - } + ga.clear(); + ga.addCurtailedLineOfText (Font (height * 0.6f), desc, r + 10.0f, height * 0.8f, width - r - 12.0f, true); + ga.draw (g); + } } void PluginListComponent::deleteKeyPressed (int lastRowSelected) { - list.removeType (lastRowSelected); + list.removeType (lastRowSelected); } void PluginListComponent::buttonClicked (Button* b) { - if (optionsButton == b) - { - PopupMenu menu; - menu.addItem (1, TRANS("Clear list")); - menu.addItem (5, TRANS("Remove selected plugin from list"), listBox->getNumSelectedRows() > 0); - menu.addItem (6, TRANS("Show folder containing selected plugin"), listBox->getNumSelectedRows() > 0); - menu.addItem (7, TRANS("Remove any plugins whose files no longer exist")); - menu.addSeparator(); - menu.addItem (2, TRANS("Sort alphabetically")); - menu.addItem (3, TRANS("Sort by category")); - menu.addItem (4, TRANS("Sort by manufacturer")); - menu.addSeparator(); + if (optionsButton == b) + { + PopupMenu menu; + menu.addItem (1, TRANS("Clear list")); + menu.addItem (5, TRANS("Remove selected plugin from list"), listBox->getNumSelectedRows() > 0); + menu.addItem (6, TRANS("Show folder containing selected plugin"), listBox->getNumSelectedRows() > 0); + menu.addItem (7, TRANS("Remove any plugins whose files no longer exist")); + menu.addSeparator(); + menu.addItem (2, TRANS("Sort alphabetically")); + menu.addItem (3, TRANS("Sort by category")); + menu.addItem (4, TRANS("Sort by manufacturer")); + menu.addSeparator(); - for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i) - { - AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i); + for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i) + { + AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i); - if (format->getDefaultLocationsToSearch().getNumPaths() > 0) - menu.addItem (10 + i, "Scan for new or updated " + format->getName() + " plugins..."); - } + if (format->getDefaultLocationsToSearch().getNumPaths() > 0) + menu.addItem (10 + i, "Scan for new or updated " + format->getName() + " plugins..."); + } - const int r = menu.showAt (optionsButton); + const int r = menu.showAt (optionsButton); - if (r == 1) - { - list.clear(); - } - else if (r == 2) - { - list.sort (KnownPluginList::sortAlphabetically); - } - else if (r == 3) - { - list.sort (KnownPluginList::sortByCategory); - } - else if (r == 4) - { - list.sort (KnownPluginList::sortByManufacturer); - } - else if (r == 5) - { - const SparseSet selected (listBox->getSelectedRows()); + if (r == 1) + { + list.clear(); + } + else if (r == 2) + { + list.sort (KnownPluginList::sortAlphabetically); + } + else if (r == 3) + { + list.sort (KnownPluginList::sortByCategory); + } + else if (r == 4) + { + list.sort (KnownPluginList::sortByManufacturer); + } + else if (r == 5) + { + const SparseSet selected (listBox->getSelectedRows()); - for (int i = list.getNumTypes(); --i >= 0;) - if (selected.contains (i)) - list.removeType (i); - } - else if (r == 6) - { - const PluginDescription* const desc = list.getType (listBox->getSelectedRow()); + for (int i = list.getNumTypes(); --i >= 0;) + if (selected.contains (i)) + list.removeType (i); + } + else if (r == 6) + { + const PluginDescription* const desc = list.getType (listBox->getSelectedRow()); - if (desc != 0) - { - if (File (desc->fileOrIdentifier).existsAsFile()) - File (desc->fileOrIdentifier).getParentDirectory().startAsProcess(); - } - } - else if (r == 7) - { - for (int i = list.getNumTypes(); --i >= 0;) - { - if (! AudioPluginFormatManager::getInstance()->doesPluginStillExist (*list.getType (i))) - { - list.removeType (i); - } - } - } - else if (r != 0) - { - typeToScan = r - 10; - startTimer (1); - } - } + if (desc != 0) + { + if (File (desc->fileOrIdentifier).existsAsFile()) + File (desc->fileOrIdentifier).getParentDirectory().startAsProcess(); + } + } + else if (r == 7) + { + for (int i = list.getNumTypes(); --i >= 0;) + { + if (! AudioPluginFormatManager::getInstance()->doesPluginStillExist (*list.getType (i))) + { + list.removeType (i); + } + } + } + else if (r != 0) + { + typeToScan = r - 10; + startTimer (1); + } + } } void PluginListComponent::timerCallback() { - stopTimer(); - scanFor (AudioPluginFormatManager::getInstance()->getFormat (typeToScan)); + stopTimer(); + scanFor (AudioPluginFormatManager::getInstance()->getFormat (typeToScan)); } bool PluginListComponent::isInterestedInFileDrag (const StringArray& /*files*/) { - return true; + return true; } void PluginListComponent::filesDropped (const StringArray& files, int, int) { - OwnedArray typesFound; - list.scanAndAddDragAndDroppedFiles (files, typesFound); + OwnedArray typesFound; + list.scanAndAddDragAndDroppedFiles (files, typesFound); } void PluginListComponent::scanFor (AudioPluginFormat* format) { - if (format == 0) - return; + if (format == 0) + return; - FileSearchPath path (format->getDefaultLocationsToSearch()); + FileSearchPath path (format->getDefaultLocationsToSearch()); - if (propertiesToUse != 0) - path = propertiesToUse->getValue ("lastPluginScanPath_" + format->getName(), path.toString()); + if (propertiesToUse != 0) + path = propertiesToUse->getValue ("lastPluginScanPath_" + format->getName(), path.toString()); - { - AlertWindow aw (TRANS("Select folders to scan..."), String::empty, AlertWindow::NoIcon); - FileSearchPathListComponent pathList; - pathList.setSize (500, 300); - pathList.setPath (path); + { + AlertWindow aw (TRANS("Select folders to scan..."), String::empty, AlertWindow::NoIcon); + FileSearchPathListComponent pathList; + pathList.setSize (500, 300); + pathList.setPath (path); - aw.addCustomComponent (&pathList); - aw.addButton (TRANS("Scan"), 1, KeyPress::returnKey); - aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); + aw.addCustomComponent (&pathList); + aw.addButton (TRANS("Scan"), 1, KeyPress::returnKey); + aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); - if (aw.runModalLoop() == 0) - return; + if (aw.runModalLoop() == 0) + return; - path = pathList.getPath(); - } + path = pathList.getPath(); + } - if (propertiesToUse != 0) - { - propertiesToUse->setValue ("lastPluginScanPath_" + format->getName(), path.toString()); - propertiesToUse->saveIfNeeded(); - } + if (propertiesToUse != 0) + { + propertiesToUse->setValue ("lastPluginScanPath_" + format->getName(), path.toString()); + propertiesToUse->saveIfNeeded(); + } - double progress = 0.0; + double progress = 0.0; - AlertWindow aw (TRANS("Scanning for plugins..."), - TRANS("Searching for all possible plugin files..."), AlertWindow::NoIcon); + AlertWindow aw (TRANS("Scanning for plugins..."), + TRANS("Searching for all possible plugin files..."), AlertWindow::NoIcon); - aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); - aw.addProgressBarComponent (progress); + aw.addButton (TRANS("Cancel"), 0, KeyPress (KeyPress::escapeKey)); + aw.addProgressBarComponent (progress); - aw.enterModalState(); + aw.enterModalState(); - MessageManager::getInstance()->runDispatchLoopUntil (300); + MessageManager::getInstance()->runDispatchLoopUntil (300); - PluginDirectoryScanner scanner (list, *format, path, true, deadMansPedalFile); + PluginDirectoryScanner scanner (list, *format, path, true, deadMansPedalFile); - for (;;) - { - aw.setMessage (TRANS("Testing:\n\n") - + scanner.getNextPluginFileThatWillBeScanned()); + for (;;) + { + aw.setMessage (TRANS("Testing:\n\n") + + scanner.getNextPluginFileThatWillBeScanned()); - MessageManager::getInstance()->runDispatchLoopUntil (20); + MessageManager::getInstance()->runDispatchLoopUntil (20); - if (! scanner.scanNextFile (true)) - break; + if (! scanner.scanNextFile (true)) + break; - if (! aw.isCurrentlyModal()) - break; + if (! aw.isCurrentlyModal()) + break; - progress = scanner.getProgress(); - } + progress = scanner.getProgress(); + } - if (scanner.getFailedFiles().size() > 0) - { - StringArray shortNames; + if (scanner.getFailedFiles().size() > 0) + { + StringArray shortNames; - for (int i = 0; i < scanner.getFailedFiles().size(); ++i) - shortNames.add (File (scanner.getFailedFiles()[i]).getFileName()); + for (int i = 0; i < scanner.getFailedFiles().size(); ++i) + shortNames.add (File (scanner.getFailedFiles()[i]).getFileName()); - AlertWindow::showMessageBox (AlertWindow::InfoIcon, - TRANS("Scan complete"), - TRANS("Note that the following files appeared to be plugin files, but failed to load correctly:\n\n") - + shortNames.joinIntoString (", ")); - } + AlertWindow::showMessageBox (AlertWindow::InfoIcon, + TRANS("Scan complete"), + TRANS("Note that the following files appeared to be plugin files, but failed to load correctly:\n\n") + + shortNames.joinIntoString (", ")); + } } END_JUCE_NAMESPACE @@ -30265,851 +29999,851 @@ static int insideCallback = 0; static const String osTypeToString (OSType type) throw() { - char s[4]; - s[0] = (char) (((uint32) type) >> 24); - s[1] = (char) (((uint32) type) >> 16); - s[2] = (char) (((uint32) type) >> 8); - s[3] = (char) ((uint32) type); - return String (s, 4); + char s[4]; + s[0] = (char) (((uint32) type) >> 24); + s[1] = (char) (((uint32) type) >> 16); + s[2] = (char) (((uint32) type) >> 8); + s[3] = (char) ((uint32) type); + return String (s, 4); } static OSType stringToOSType (const String& s1) throw() { - const String s (s1 + " "); + const String s (s1 + " "); - return (((OSType) (unsigned char) s[0]) << 24) - | (((OSType) (unsigned char) s[1]) << 16) - | (((OSType) (unsigned char) s[2]) << 8) - | ((OSType) (unsigned char) s[3]); + return (((OSType) (unsigned char) s[0]) << 24) + | (((OSType) (unsigned char) s[1]) << 16) + | (((OSType) (unsigned char) s[2]) << 8) + | ((OSType) (unsigned char) s[3]); } static const tchar* auIdentifierPrefix = T("AudioUnit:"); static const String createAUPluginIdentifier (const ComponentDescription& desc) { - jassert (osTypeToString ('abcd') == T("abcd")); // agh, must have got the endianness wrong.. - jassert (stringToOSType ("abcd") == (OSType) 'abcd'); // ditto + jassert (osTypeToString ('abcd') == T("abcd")); // agh, must have got the endianness wrong.. + jassert (stringToOSType ("abcd") == (OSType) 'abcd'); // ditto - String s (auIdentifierPrefix); + String s (auIdentifierPrefix); - if (desc.componentType == kAudioUnitType_MusicDevice) - s << "Synths/"; - else if (desc.componentType == kAudioUnitType_MusicEffect - || desc.componentType == kAudioUnitType_Effect) - s << "Effects/"; - else if (desc.componentType == kAudioUnitType_Generator) - s << "Generators/"; - else if (desc.componentType == kAudioUnitType_Panner) - s << "Panners/"; + if (desc.componentType == kAudioUnitType_MusicDevice) + s << "Synths/"; + else if (desc.componentType == kAudioUnitType_MusicEffect + || desc.componentType == kAudioUnitType_Effect) + s << "Effects/"; + else if (desc.componentType == kAudioUnitType_Generator) + s << "Generators/"; + else if (desc.componentType == kAudioUnitType_Panner) + s << "Panners/"; - s << osTypeToString (desc.componentType) - << T(",") - << osTypeToString (desc.componentSubType) - << T(",") - << osTypeToString (desc.componentManufacturer); + s << osTypeToString (desc.componentType) + << T(",") + << osTypeToString (desc.componentSubType) + << T(",") + << osTypeToString (desc.componentManufacturer); - return s; + return s; } static void getAUDetails (ComponentRecord* comp, String& name, String& manufacturer) { - Handle componentNameHandle = NewHandle (sizeof (void*)); - Handle componentInfoHandle = NewHandle (sizeof (void*)); + Handle componentNameHandle = NewHandle (sizeof (void*)); + Handle componentInfoHandle = NewHandle (sizeof (void*)); - if (componentNameHandle != 0 && componentInfoHandle != 0) - { - ComponentDescription desc; + if (componentNameHandle != 0 && componentInfoHandle != 0) + { + ComponentDescription desc; - if (GetComponentInfo (comp, &desc, componentNameHandle, componentInfoHandle, 0) == noErr) - { - ConstStr255Param nameString = (ConstStr255Param) (*componentNameHandle); - ConstStr255Param infoString = (ConstStr255Param) (*componentInfoHandle); + if (GetComponentInfo (comp, &desc, componentNameHandle, componentInfoHandle, 0) == noErr) + { + ConstStr255Param nameString = (ConstStr255Param) (*componentNameHandle); + ConstStr255Param infoString = (ConstStr255Param) (*componentInfoHandle); - if (nameString != 0 && nameString[0] != 0) - { - const String all ((const char*) nameString + 1, nameString[0]); + if (nameString != 0 && nameString[0] != 0) + { + const String all ((const char*) nameString + 1, nameString[0]); DBG ("name: "+ all); - manufacturer = all.upToFirstOccurrenceOf (T(":"), false, false).trim(); - name = all.fromFirstOccurrenceOf (T(":"), false, false).trim(); - } + manufacturer = all.upToFirstOccurrenceOf (T(":"), false, false).trim(); + name = all.fromFirstOccurrenceOf (T(":"), false, false).trim(); + } - if (infoString != 0 && infoString[0] != 0) - { - const String all ((const char*) infoString + 1, infoString[0]); + if (infoString != 0 && infoString[0] != 0) + { + const String all ((const char*) infoString + 1, infoString[0]); DBG ("info: " + all); - } + } - if (name.isEmpty()) - name = ""; - } + if (name.isEmpty()) + name = ""; + } - DisposeHandle (componentNameHandle); - DisposeHandle (componentInfoHandle); - } + DisposeHandle (componentNameHandle); + DisposeHandle (componentInfoHandle); + } } static bool getComponentDescFromIdentifier (const String& fileOrIdentifier, ComponentDescription& desc, - String& name, String& version, String& manufacturer) + String& name, String& version, String& manufacturer) { - zerostruct (desc); + zerostruct (desc); - if (fileOrIdentifier.startsWithIgnoreCase (auIdentifierPrefix)) - { - String s (fileOrIdentifier.substring (jmax (fileOrIdentifier.lastIndexOfChar (T(':')), - fileOrIdentifier.lastIndexOfChar (T('/'))) + 1)); + if (fileOrIdentifier.startsWithIgnoreCase (auIdentifierPrefix)) + { + String s (fileOrIdentifier.substring (jmax (fileOrIdentifier.lastIndexOfChar (T(':')), + fileOrIdentifier.lastIndexOfChar (T('/'))) + 1)); - StringArray tokens; - tokens.addTokens (s, T(","), 0); - tokens.trim(); - tokens.removeEmptyStrings(); + StringArray tokens; + tokens.addTokens (s, T(","), 0); + tokens.trim(); + tokens.removeEmptyStrings(); - if (tokens.size() == 3) - { - desc.componentType = stringToOSType (tokens[0]); - desc.componentSubType = stringToOSType (tokens[1]); - desc.componentManufacturer = stringToOSType (tokens[2]); + if (tokens.size() == 3) + { + desc.componentType = stringToOSType (tokens[0]); + desc.componentSubType = stringToOSType (tokens[1]); + desc.componentManufacturer = stringToOSType (tokens[2]); - ComponentRecord* comp = FindNextComponent (0, &desc); + ComponentRecord* comp = FindNextComponent (0, &desc); - if (comp != 0) - { - getAUDetails (comp, name, manufacturer); + if (comp != 0) + { + getAUDetails (comp, name, manufacturer); - return true; - } - } - } + return true; + } + } + } - return false; + return false; } class AudioUnitPluginWindowCarbon; class AudioUnitPluginWindowCocoa; -class AudioUnitPluginInstance : public AudioPluginInstance +class AudioUnitPluginInstance : public AudioPluginInstance { public: - ~AudioUnitPluginInstance(); + ~AudioUnitPluginInstance(); - // AudioPluginInstance methods: + // AudioPluginInstance methods: - void fillInPluginDescription (PluginDescription& desc) const - { - desc.name = pluginName; - desc.fileOrIdentifier = createAUPluginIdentifier (componentDesc); - desc.uid = ((int) componentDesc.componentType) - ^ ((int) componentDesc.componentSubType) - ^ ((int) componentDesc.componentManufacturer); - desc.lastFileModTime = 0; - desc.pluginFormatName = "AudioUnit"; - desc.category = getCategory(); - desc.manufacturerName = manufacturer; - desc.version = version; - desc.numInputChannels = getNumInputChannels(); - desc.numOutputChannels = getNumOutputChannels(); - desc.isInstrument = (componentDesc.componentType == kAudioUnitType_MusicDevice); - } + void fillInPluginDescription (PluginDescription& desc) const + { + desc.name = pluginName; + desc.fileOrIdentifier = createAUPluginIdentifier (componentDesc); + desc.uid = ((int) componentDesc.componentType) + ^ ((int) componentDesc.componentSubType) + ^ ((int) componentDesc.componentManufacturer); + desc.lastFileModTime = 0; + desc.pluginFormatName = "AudioUnit"; + desc.category = getCategory(); + desc.manufacturerName = manufacturer; + desc.version = version; + desc.numInputChannels = getNumInputChannels(); + desc.numOutputChannels = getNumOutputChannels(); + desc.isInstrument = (componentDesc.componentType == kAudioUnitType_MusicDevice); + } - const String getName() const { return pluginName; } - bool acceptsMidi() const { return wantsMidiMessages; } - bool producesMidi() const { return false; } + const String getName() const { return pluginName; } + bool acceptsMidi() const { return wantsMidiMessages; } + bool producesMidi() const { return false; } - // AudioProcessor methods: + // AudioProcessor methods: - void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); - void releaseResources(); - void processBlock (AudioSampleBuffer& buffer, - MidiBuffer& midiMessages); + void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); + void releaseResources(); + void processBlock (AudioSampleBuffer& buffer, + MidiBuffer& midiMessages); - AudioProcessorEditor* createEditor(); + AudioProcessorEditor* createEditor(); - const String getInputChannelName (const int index) const; - bool isInputChannelStereoPair (int index) const; + const String getInputChannelName (const int index) const; + bool isInputChannelStereoPair (int index) const; - const String getOutputChannelName (const int index) const; - bool isOutputChannelStereoPair (int index) const; + const String getOutputChannelName (const int index) const; + bool isOutputChannelStereoPair (int index) const; - int getNumParameters(); - float getParameter (int index); - void setParameter (int index, float newValue); - const String getParameterName (int index); - const String getParameterText (int index); - bool isParameterAutomatable (int index) const; + int getNumParameters(); + float getParameter (int index); + void setParameter (int index, float newValue); + const String getParameterName (int index); + const String getParameterText (int index); + bool isParameterAutomatable (int index) const; - int getNumPrograms(); - int getCurrentProgram(); - void setCurrentProgram (int index); - const String getProgramName (int index); - void changeProgramName (int index, const String& newName); + int getNumPrograms(); + int getCurrentProgram(); + void setCurrentProgram (int index); + const String getProgramName (int index); + void changeProgramName (int index, const String& newName); - void getStateInformation (MemoryBlock& destData); - void getCurrentProgramStateInformation (MemoryBlock& destData); - void setStateInformation (const void* data, int sizeInBytes); - void setCurrentProgramStateInformation (const void* data, int sizeInBytes); + void getStateInformation (MemoryBlock& destData); + void getCurrentProgramStateInformation (MemoryBlock& destData); + void setStateInformation (const void* data, int sizeInBytes); + void setCurrentProgramStateInformation (const void* data, int sizeInBytes); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class AudioUnitPluginWindowCarbon; - friend class AudioUnitPluginWindowCocoa; - friend class AudioUnitPluginFormat; + friend class AudioUnitPluginWindowCarbon; + friend class AudioUnitPluginWindowCocoa; + friend class AudioUnitPluginFormat; - ComponentDescription componentDesc; - String pluginName, manufacturer, version; - String fileOrIdentifier; - CriticalSection lock; - bool initialised, wantsMidiMessages, wasPlaying; + ComponentDescription componentDesc; + String pluginName, manufacturer, version; + String fileOrIdentifier; + CriticalSection lock; + bool initialised, wantsMidiMessages, wasPlaying; - HeapBlock outputBufferList; - AudioTimeStamp timeStamp; - AudioSampleBuffer* currentBuffer; + HeapBlock outputBufferList; + AudioTimeStamp timeStamp; + AudioSampleBuffer* currentBuffer; - AudioUnit audioUnit; - Array parameterIds; + AudioUnit audioUnit; + Array parameterIds; - bool getComponentDescFromFile (const String& fileOrIdentifier); - void initialise(); + bool getComponentDescFromFile (const String& fileOrIdentifier); + void initialise(); - OSStatus renderGetInput (AudioUnitRenderActionFlags* ioActionFlags, - const AudioTimeStamp* inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList* ioData) const; + OSStatus renderGetInput (AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) const; - static OSStatus renderGetInputCallback (void* inRefCon, - AudioUnitRenderActionFlags* ioActionFlags, - const AudioTimeStamp* inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList* ioData) - { - return ((AudioUnitPluginInstance*) inRefCon) - ->renderGetInput (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); - } + static OSStatus renderGetInputCallback (void* inRefCon, + AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) + { + return ((AudioUnitPluginInstance*) inRefCon) + ->renderGetInput (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); + } - OSStatus getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const; - OSStatus getMusicalTimeLocation (UInt32* outDeltaSampleOffsetToNextBeat, Float32* outTimeSig_Numerator, - UInt32* outTimeSig_Denominator, Float64* outCurrentMeasureDownBeat) const; - OSStatus getTransportState (Boolean* outIsPlaying, Boolean* outTransportStateChanged, - Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling, - Float64* outCycleStartBeat, Float64* outCycleEndBeat); + OSStatus getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const; + OSStatus getMusicalTimeLocation (UInt32* outDeltaSampleOffsetToNextBeat, Float32* outTimeSig_Numerator, + UInt32* outTimeSig_Denominator, Float64* outCurrentMeasureDownBeat) const; + OSStatus getTransportState (Boolean* outIsPlaying, Boolean* outTransportStateChanged, + Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling, + Float64* outCycleStartBeat, Float64* outCycleEndBeat); - static OSStatus getBeatAndTempoCallback (void* inHostUserData, Float64* outCurrentBeat, Float64* outCurrentTempo) - { - return ((AudioUnitPluginInstance*) inHostUserData)->getBeatAndTempo (outCurrentBeat, outCurrentTempo); - } + static OSStatus getBeatAndTempoCallback (void* inHostUserData, Float64* outCurrentBeat, Float64* outCurrentTempo) + { + return ((AudioUnitPluginInstance*) inHostUserData)->getBeatAndTempo (outCurrentBeat, outCurrentTempo); + } - static OSStatus getMusicalTimeLocationCallback (void* inHostUserData, UInt32* outDeltaSampleOffsetToNextBeat, - Float32* outTimeSig_Numerator, UInt32* outTimeSig_Denominator, - Float64* outCurrentMeasureDownBeat) - { - return ((AudioUnitPluginInstance*) inHostUserData) - ->getMusicalTimeLocation (outDeltaSampleOffsetToNextBeat, outTimeSig_Numerator, - outTimeSig_Denominator, outCurrentMeasureDownBeat); - } + static OSStatus getMusicalTimeLocationCallback (void* inHostUserData, UInt32* outDeltaSampleOffsetToNextBeat, + Float32* outTimeSig_Numerator, UInt32* outTimeSig_Denominator, + Float64* outCurrentMeasureDownBeat) + { + return ((AudioUnitPluginInstance*) inHostUserData) + ->getMusicalTimeLocation (outDeltaSampleOffsetToNextBeat, outTimeSig_Numerator, + outTimeSig_Denominator, outCurrentMeasureDownBeat); + } - static OSStatus getTransportStateCallback (void* inHostUserData, Boolean* outIsPlaying, Boolean* outTransportStateChanged, - Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling, - Float64* outCycleStartBeat, Float64* outCycleEndBeat) - { - return ((AudioUnitPluginInstance*) inHostUserData) - ->getTransportState (outIsPlaying, outTransportStateChanged, - outCurrentSampleInTimeLine, outIsCycling, - outCycleStartBeat, outCycleEndBeat); - } + static OSStatus getTransportStateCallback (void* inHostUserData, Boolean* outIsPlaying, Boolean* outTransportStateChanged, + Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling, + Float64* outCycleStartBeat, Float64* outCycleEndBeat) + { + return ((AudioUnitPluginInstance*) inHostUserData) + ->getTransportState (outIsPlaying, outTransportStateChanged, + outCurrentSampleInTimeLine, outIsCycling, + outCycleStartBeat, outCycleEndBeat); + } - void getNumChannels (int& numIns, int& numOuts) - { - numIns = 0; - numOuts = 0; + void getNumChannels (int& numIns, int& numOuts) + { + numIns = 0; + numOuts = 0; - AUChannelInfo supportedChannels [128]; - UInt32 supportedChannelsSize = sizeof (supportedChannels); + AUChannelInfo supportedChannels [128]; + UInt32 supportedChannelsSize = sizeof (supportedChannels); - if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SupportedNumChannels, kAudioUnitScope_Global, - 0, supportedChannels, &supportedChannelsSize) == noErr - && supportedChannelsSize > 0) - { - for (int i = 0; i < supportedChannelsSize / sizeof (AUChannelInfo); ++i) - { - numIns = jmax (numIns, supportedChannels[i].inChannels); - numOuts = jmax (numOuts, supportedChannels[i].outChannels); - } - } - else - { - // (this really means the plugin will take any number of ins/outs as long - // as they are the same) - numIns = numOuts = 2; - } - } + if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SupportedNumChannels, kAudioUnitScope_Global, + 0, supportedChannels, &supportedChannelsSize) == noErr + && supportedChannelsSize > 0) + { + for (int i = 0; i < supportedChannelsSize / sizeof (AUChannelInfo); ++i) + { + numIns = jmax (numIns, supportedChannels[i].inChannels); + numOuts = jmax (numOuts, supportedChannels[i].outChannels); + } + } + else + { + // (this really means the plugin will take any number of ins/outs as long + // as they are the same) + numIns = numOuts = 2; + } + } - const String getCategory() const; + const String getCategory() const; - AudioUnitPluginInstance (const String& fileOrIdentifier); + AudioUnitPluginInstance (const String& fileOrIdentifier); }; AudioUnitPluginInstance::AudioUnitPluginInstance (const String& fileOrIdentifier) - : fileOrIdentifier (fileOrIdentifier), - initialised (false), - wantsMidiMessages (false), - audioUnit (0), - currentBuffer (0) + : fileOrIdentifier (fileOrIdentifier), + initialised (false), + wantsMidiMessages (false), + audioUnit (0), + currentBuffer (0) { - try - { - ++insideCallback; + try + { + ++insideCallback; - log (T("Opening AU: ") + fileOrIdentifier); + log (T("Opening AU: ") + fileOrIdentifier); - if (getComponentDescFromFile (fileOrIdentifier)) - { - ComponentRecord* const comp = FindNextComponent (0, &componentDesc); + if (getComponentDescFromFile (fileOrIdentifier)) + { + ComponentRecord* const comp = FindNextComponent (0, &componentDesc); - if (comp != 0) - { - audioUnit = (AudioUnit) OpenComponent (comp); + if (comp != 0) + { + audioUnit = (AudioUnit) OpenComponent (comp); - wantsMidiMessages = componentDesc.componentType == kAudioUnitType_MusicDevice - || componentDesc.componentType == kAudioUnitType_MusicEffect; - } - } + wantsMidiMessages = componentDesc.componentType == kAudioUnitType_MusicDevice + || componentDesc.componentType == kAudioUnitType_MusicEffect; + } + } - --insideCallback; - } - catch (...) - { - --insideCallback; - } + --insideCallback; + } + catch (...) + { + --insideCallback; + } } AudioUnitPluginInstance::~AudioUnitPluginInstance() { - { - const ScopedLock sl (lock); + { + const ScopedLock sl (lock); - jassert (insideCallback == 0); + jassert (insideCallback == 0); - if (audioUnit != 0) - { - AudioUnitUninitialize (audioUnit); - CloseComponent (audioUnit); - audioUnit = 0; - } - } + if (audioUnit != 0) + { + AudioUnitUninitialize (audioUnit); + CloseComponent (audioUnit); + audioUnit = 0; + } + } } bool AudioUnitPluginInstance::getComponentDescFromFile (const String& fileOrIdentifier) { - zerostruct (componentDesc); + zerostruct (componentDesc); - if (getComponentDescFromIdentifier (fileOrIdentifier, componentDesc, pluginName, version, manufacturer)) - return true; + if (getComponentDescFromIdentifier (fileOrIdentifier, componentDesc, pluginName, version, manufacturer)) + return true; - const File file (fileOrIdentifier); - if (! file.hasFileExtension (T(".component"))) - return false; + const File file (fileOrIdentifier); + if (! file.hasFileExtension (T(".component"))) + return false; - const char* const utf8 = fileOrIdentifier.toUTF8(); - CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, - strlen (utf8), file.isDirectory()); - if (url != 0) - { - CFBundleRef bundleRef = CFBundleCreate (kCFAllocatorDefault, url); - CFRelease (url); + const char* const utf8 = fileOrIdentifier.toUTF8(); + CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, + strlen (utf8), file.isDirectory()); + if (url != 0) + { + CFBundleRef bundleRef = CFBundleCreate (kCFAllocatorDefault, url); + CFRelease (url); - if (bundleRef != 0) - { - CFTypeRef name = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleName")); + if (bundleRef != 0) + { + CFTypeRef name = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleName")); - if (name != 0 && CFGetTypeID (name) == CFStringGetTypeID()) - pluginName = PlatformUtilities::cfStringToJuceString ((CFStringRef) name); + if (name != 0 && CFGetTypeID (name) == CFStringGetTypeID()) + pluginName = PlatformUtilities::cfStringToJuceString ((CFStringRef) name); - if (pluginName.isEmpty()) - pluginName = file.getFileNameWithoutExtension(); + if (pluginName.isEmpty()) + pluginName = file.getFileNameWithoutExtension(); - CFTypeRef versionString = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleVersion")); + CFTypeRef versionString = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleVersion")); - if (versionString != 0 && CFGetTypeID (versionString) == CFStringGetTypeID()) - version = PlatformUtilities::cfStringToJuceString ((CFStringRef) versionString); + if (versionString != 0 && CFGetTypeID (versionString) == CFStringGetTypeID()) + version = PlatformUtilities::cfStringToJuceString ((CFStringRef) versionString); - CFTypeRef manuString = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleGetInfoString")); + CFTypeRef manuString = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleGetInfoString")); - if (manuString != 0 && CFGetTypeID (manuString) == CFStringGetTypeID()) - manufacturer = PlatformUtilities::cfStringToJuceString ((CFStringRef) manuString); + if (manuString != 0 && CFGetTypeID (manuString) == CFStringGetTypeID()) + manufacturer = PlatformUtilities::cfStringToJuceString ((CFStringRef) manuString); - short resFileId = CFBundleOpenBundleResourceMap (bundleRef); - UseResFile (resFileId); + short resFileId = CFBundleOpenBundleResourceMap (bundleRef); + UseResFile (resFileId); - for (int i = 1; i <= Count1Resources ('thng'); ++i) - { - Handle h = Get1IndResource ('thng', i); + for (int i = 1; i <= Count1Resources ('thng'); ++i) + { + Handle h = Get1IndResource ('thng', i); - if (h != 0) - { - HLock (h); - const uint32* const types = (const uint32*) *h; + if (h != 0) + { + HLock (h); + const uint32* const types = (const uint32*) *h; - if (types[0] == kAudioUnitType_MusicDevice - || types[0] == kAudioUnitType_MusicEffect - || types[0] == kAudioUnitType_Effect - || types[0] == kAudioUnitType_Generator - || types[0] == kAudioUnitType_Panner) - { - componentDesc.componentType = types[0]; - componentDesc.componentSubType = types[1]; - componentDesc.componentManufacturer = types[2]; - break; - } + if (types[0] == kAudioUnitType_MusicDevice + || types[0] == kAudioUnitType_MusicEffect + || types[0] == kAudioUnitType_Effect + || types[0] == kAudioUnitType_Generator + || types[0] == kAudioUnitType_Panner) + { + componentDesc.componentType = types[0]; + componentDesc.componentSubType = types[1]; + componentDesc.componentManufacturer = types[2]; + break; + } - HUnlock (h); - ReleaseResource (h); - } - } + HUnlock (h); + ReleaseResource (h); + } + } - CFBundleCloseBundleResourceMap (bundleRef, resFileId); - CFRelease (bundleRef); - } - } + CFBundleCloseBundleResourceMap (bundleRef, resFileId); + CFRelease (bundleRef); + } + } - return componentDesc.componentType != 0 && componentDesc.componentSubType != 0; + return componentDesc.componentType != 0 && componentDesc.componentSubType != 0; } void AudioUnitPluginInstance::initialise() { - if (initialised || audioUnit == 0) - return; + if (initialised || audioUnit == 0) + return; - log (T("Initialising AU: ") + pluginName); + log (T("Initialising AU: ") + pluginName); - parameterIds.clear(); + parameterIds.clear(); - { - UInt32 paramListSize = 0; - AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, - 0, 0, ¶mListSize); + { + UInt32 paramListSize = 0; + AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, + 0, 0, ¶mListSize); - if (paramListSize > 0) - { - parameterIds.insertMultiple (0, 0, paramListSize / sizeof (int)); + if (paramListSize > 0) + { + parameterIds.insertMultiple (0, 0, paramListSize / sizeof (int)); - AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, - 0, ¶meterIds.getReference(0), ¶mListSize); - } - } + AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, + 0, ¶meterIds.getReference(0), ¶mListSize); + } + } - { - AURenderCallbackStruct info; - zerostruct (info); - info.inputProcRefCon = this; - info.inputProc = renderGetInputCallback; + { + AURenderCallbackStruct info; + zerostruct (info); + info.inputProcRefCon = this; + info.inputProc = renderGetInputCallback; - AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, - 0, &info, sizeof (info)); - } + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, + 0, &info, sizeof (info)); + } - { - HostCallbackInfo info; - zerostruct (info); - info.hostUserData = this; - info.beatAndTempoProc = getBeatAndTempoCallback; - info.musicalTimeLocationProc = getMusicalTimeLocationCallback; - info.transportStateProc = getTransportStateCallback; + { + HostCallbackInfo info; + zerostruct (info); + info.hostUserData = this; + info.beatAndTempoProc = getBeatAndTempoCallback; + info.musicalTimeLocationProc = getMusicalTimeLocationCallback; + info.transportStateProc = getTransportStateCallback; - AudioUnitSetProperty (audioUnit, kAudioUnitProperty_HostCallbacks, kAudioUnitScope_Global, - 0, &info, sizeof (info)); - } + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_HostCallbacks, kAudioUnitScope_Global, + 0, &info, sizeof (info)); + } - int numIns, numOuts; - getNumChannels (numIns, numOuts); - setPlayConfigDetails (numIns, numOuts, 0, 0); + int numIns, numOuts; + getNumChannels (numIns, numOuts); + setPlayConfigDetails (numIns, numOuts, 0, 0); - initialised = AudioUnitInitialize (audioUnit) == noErr; + initialised = AudioUnitInitialize (audioUnit) == noErr; - setLatencySamples (0); + setLatencySamples (0); } void AudioUnitPluginInstance::prepareToPlay (double sampleRate_, - int samplesPerBlockExpected) + int samplesPerBlockExpected) { - initialise(); + initialise(); - if (initialised) - { - int numIns, numOuts; - getNumChannels (numIns, numOuts); + if (initialised) + { + int numIns, numOuts; + getNumChannels (numIns, numOuts); - setPlayConfigDetails (numIns, numOuts, sampleRate_, samplesPerBlockExpected); + setPlayConfigDetails (numIns, numOuts, sampleRate_, samplesPerBlockExpected); - Float64 latencySecs = 0.0; - UInt32 latencySize = sizeof (latencySecs); - AudioUnitGetProperty (audioUnit, kAudioUnitProperty_Latency, kAudioUnitScope_Global, - 0, &latencySecs, &latencySize); + Float64 latencySecs = 0.0; + UInt32 latencySize = sizeof (latencySecs); + AudioUnitGetProperty (audioUnit, kAudioUnitProperty_Latency, kAudioUnitScope_Global, + 0, &latencySecs, &latencySize); - setLatencySamples (roundDoubleToInt (latencySecs * sampleRate_)); + setLatencySamples (roundToInt (latencySecs * sampleRate_)); - AudioUnitReset (audioUnit, kAudioUnitScope_Input, 0); - AudioUnitReset (audioUnit, kAudioUnitScope_Output, 0); - AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0); + AudioUnitReset (audioUnit, kAudioUnitScope_Input, 0); + AudioUnitReset (audioUnit, kAudioUnitScope_Output, 0); + AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0); - AudioStreamBasicDescription stream; - zerostruct (stream); - stream.mSampleRate = sampleRate_; - stream.mFormatID = kAudioFormatLinearPCM; - stream.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; - stream.mFramesPerPacket = 1; - stream.mBytesPerPacket = 4; - stream.mBytesPerFrame = 4; - stream.mBitsPerChannel = 32; - stream.mChannelsPerFrame = numIns; + AudioStreamBasicDescription stream; + zerostruct (stream); + stream.mSampleRate = sampleRate_; + stream.mFormatID = kAudioFormatLinearPCM; + stream.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; + stream.mFramesPerPacket = 1; + stream.mBytesPerPacket = 4; + stream.mBytesPerFrame = 4; + stream.mBitsPerChannel = 32; + stream.mChannelsPerFrame = numIns; - OSStatus err = AudioUnitSetProperty (audioUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - 0, &stream, sizeof (stream)); + OSStatus err = AudioUnitSetProperty (audioUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, &stream, sizeof (stream)); - stream.mChannelsPerFrame = numOuts; + stream.mChannelsPerFrame = numOuts; - err = AudioUnitSetProperty (audioUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, - 0, &stream, sizeof (stream)); + err = AudioUnitSetProperty (audioUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, + 0, &stream, sizeof (stream)); - outputBufferList.calloc (sizeof (AudioBufferList) + sizeof (AudioBuffer) * (numOuts + 1), 1); - outputBufferList->mNumberBuffers = numOuts; + outputBufferList.calloc (sizeof (AudioBufferList) + sizeof (AudioBuffer) * (numOuts + 1), 1); + outputBufferList->mNumberBuffers = numOuts; - for (int i = numOuts; --i >= 0;) - outputBufferList->mBuffers[i].mNumberChannels = 1; + for (int i = numOuts; --i >= 0;) + outputBufferList->mBuffers[i].mNumberChannels = 1; - zerostruct (timeStamp); - timeStamp.mSampleTime = 0; - timeStamp.mHostTime = AudioGetCurrentHostTime(); - timeStamp.mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid; + zerostruct (timeStamp); + timeStamp.mSampleTime = 0; + timeStamp.mHostTime = AudioGetCurrentHostTime(); + timeStamp.mFlags = kAudioTimeStampSampleTimeValid | kAudioTimeStampHostTimeValid; - currentBuffer = 0; - wasPlaying = false; - } + currentBuffer = 0; + wasPlaying = false; + } } void AudioUnitPluginInstance::releaseResources() { - if (initialised) - { - AudioUnitReset (audioUnit, kAudioUnitScope_Input, 0); - AudioUnitReset (audioUnit, kAudioUnitScope_Output, 0); - AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0); + if (initialised) + { + AudioUnitReset (audioUnit, kAudioUnitScope_Input, 0); + AudioUnitReset (audioUnit, kAudioUnitScope_Output, 0); + AudioUnitReset (audioUnit, kAudioUnitScope_Global, 0); - outputBufferList.free(); - currentBuffer = 0; - } + outputBufferList.free(); + currentBuffer = 0; + } } OSStatus AudioUnitPluginInstance::renderGetInput (AudioUnitRenderActionFlags* ioActionFlags, - const AudioTimeStamp* inTimeStamp, - UInt32 inBusNumber, - UInt32 inNumberFrames, - AudioBufferList* ioData) const + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) const { - if (inBusNumber == 0 - && currentBuffer != 0) - { - jassert (inNumberFrames == currentBuffer->getNumSamples()); // if this ever happens, might need to add extra handling + if (inBusNumber == 0 + && currentBuffer != 0) + { + jassert (inNumberFrames == currentBuffer->getNumSamples()); // if this ever happens, might need to add extra handling - for (int i = 0; i < ioData->mNumberBuffers; ++i) - { - if (i < currentBuffer->getNumChannels()) - { - memcpy (ioData->mBuffers[i].mData, - currentBuffer->getSampleData (i, 0), - sizeof (float) * inNumberFrames); - } - else - { - zeromem (ioData->mBuffers[i].mData, sizeof (float) * inNumberFrames); - } - } - } + for (int i = 0; i < ioData->mNumberBuffers; ++i) + { + if (i < currentBuffer->getNumChannels()) + { + memcpy (ioData->mBuffers[i].mData, + currentBuffer->getSampleData (i, 0), + sizeof (float) * inNumberFrames); + } + else + { + zeromem (ioData->mBuffers[i].mData, sizeof (float) * inNumberFrames); + } + } + } - return noErr; + return noErr; } void AudioUnitPluginInstance::processBlock (AudioSampleBuffer& buffer, - MidiBuffer& midiMessages) + MidiBuffer& midiMessages) { - const int numSamples = buffer.getNumSamples(); + const int numSamples = buffer.getNumSamples(); - if (initialised) - { - AudioUnitRenderActionFlags flags = 0; + if (initialised) + { + AudioUnitRenderActionFlags flags = 0; - timeStamp.mHostTime = AudioGetCurrentHostTime(); + timeStamp.mHostTime = AudioGetCurrentHostTime(); - for (int i = getNumOutputChannels(); --i >= 0;) - { - outputBufferList->mBuffers[i].mDataByteSize = sizeof (float) * numSamples; - outputBufferList->mBuffers[i].mData = buffer.getSampleData (i, 0); - } + for (int i = getNumOutputChannels(); --i >= 0;) + { + outputBufferList->mBuffers[i].mDataByteSize = sizeof (float) * numSamples; + outputBufferList->mBuffers[i].mData = buffer.getSampleData (i, 0); + } - currentBuffer = &buffer; + currentBuffer = &buffer; - if (wantsMidiMessages) - { - const uint8* midiEventData; - int midiEventSize, midiEventPosition; - MidiBuffer::Iterator i (midiMessages); + if (wantsMidiMessages) + { + const uint8* midiEventData; + int midiEventSize, midiEventPosition; + MidiBuffer::Iterator i (midiMessages); - while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition)) - { - if (midiEventSize <= 3) - MusicDeviceMIDIEvent (audioUnit, - midiEventData[0], midiEventData[1], midiEventData[2], - midiEventPosition); - else - MusicDeviceSysEx (audioUnit, midiEventData, midiEventSize); - } + while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition)) + { + if (midiEventSize <= 3) + MusicDeviceMIDIEvent (audioUnit, + midiEventData[0], midiEventData[1], midiEventData[2], + midiEventPosition); + else + MusicDeviceSysEx (audioUnit, midiEventData, midiEventSize); + } - midiMessages.clear(); - } + midiMessages.clear(); + } - AudioUnitRender (audioUnit, &flags, &timeStamp, - 0, numSamples, outputBufferList); + AudioUnitRender (audioUnit, &flags, &timeStamp, + 0, numSamples, outputBufferList); - timeStamp.mSampleTime += numSamples; - } - else - { - // Not initialised, so just bypass.. - for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i) - buffer.clear (i, 0, buffer.getNumSamples()); - } + timeStamp.mSampleTime += numSamples; + } + else + { + // Not initialised, so just bypass.. + for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i) + buffer.clear (i, 0, buffer.getNumSamples()); + } } OSStatus AudioUnitPluginInstance::getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const { - AudioPlayHead* const ph = getPlayHead(); - AudioPlayHead::CurrentPositionInfo result; + AudioPlayHead* const ph = getPlayHead(); + AudioPlayHead::CurrentPositionInfo result; - if (ph != 0 && ph->getCurrentPosition (result)) - { - if (outCurrentBeat != 0) - *outCurrentBeat = result.ppqPosition; + if (ph != 0 && ph->getCurrentPosition (result)) + { + if (outCurrentBeat != 0) + *outCurrentBeat = result.ppqPosition; - if (outCurrentTempo != 0) - *outCurrentTempo = result.bpm; - } - else - { - if (outCurrentBeat != 0) - *outCurrentBeat = 0; + if (outCurrentTempo != 0) + *outCurrentTempo = result.bpm; + } + else + { + if (outCurrentBeat != 0) + *outCurrentBeat = 0; - if (outCurrentTempo != 0) - *outCurrentTempo = 120.0; - } + if (outCurrentTempo != 0) + *outCurrentTempo = 120.0; + } - return noErr; + return noErr; } OSStatus AudioUnitPluginInstance::getMusicalTimeLocation (UInt32* outDeltaSampleOffsetToNextBeat, - Float32* outTimeSig_Numerator, - UInt32* outTimeSig_Denominator, - Float64* outCurrentMeasureDownBeat) const + Float32* outTimeSig_Numerator, + UInt32* outTimeSig_Denominator, + Float64* outCurrentMeasureDownBeat) const { - AudioPlayHead* const ph = getPlayHead(); - AudioPlayHead::CurrentPositionInfo result; + AudioPlayHead* const ph = getPlayHead(); + AudioPlayHead::CurrentPositionInfo result; - if (ph != 0 && ph->getCurrentPosition (result)) - { - if (outTimeSig_Numerator != 0) - *outTimeSig_Numerator = result.timeSigNumerator; + if (ph != 0 && ph->getCurrentPosition (result)) + { + if (outTimeSig_Numerator != 0) + *outTimeSig_Numerator = result.timeSigNumerator; - if (outTimeSig_Denominator != 0) - *outTimeSig_Denominator = result.timeSigDenominator; + if (outTimeSig_Denominator != 0) + *outTimeSig_Denominator = result.timeSigDenominator; - if (outDeltaSampleOffsetToNextBeat != 0) - *outDeltaSampleOffsetToNextBeat = 0; //xxx + if (outDeltaSampleOffsetToNextBeat != 0) + *outDeltaSampleOffsetToNextBeat = 0; //xxx - if (outCurrentMeasureDownBeat != 0) - *outCurrentMeasureDownBeat = result.ppqPositionOfLastBarStart; //xxx wrong - } - else - { - if (outDeltaSampleOffsetToNextBeat != 0) - *outDeltaSampleOffsetToNextBeat = 0; + if (outCurrentMeasureDownBeat != 0) + *outCurrentMeasureDownBeat = result.ppqPositionOfLastBarStart; //xxx wrong + } + else + { + if (outDeltaSampleOffsetToNextBeat != 0) + *outDeltaSampleOffsetToNextBeat = 0; - if (outTimeSig_Numerator != 0) - *outTimeSig_Numerator = 4; + if (outTimeSig_Numerator != 0) + *outTimeSig_Numerator = 4; - if (outTimeSig_Denominator != 0) - *outTimeSig_Denominator = 4; + if (outTimeSig_Denominator != 0) + *outTimeSig_Denominator = 4; - if (outCurrentMeasureDownBeat != 0) - *outCurrentMeasureDownBeat = 0; - } + if (outCurrentMeasureDownBeat != 0) + *outCurrentMeasureDownBeat = 0; + } - return noErr; + return noErr; } OSStatus AudioUnitPluginInstance::getTransportState (Boolean* outIsPlaying, - Boolean* outTransportStateChanged, - Float64* outCurrentSampleInTimeLine, - Boolean* outIsCycling, - Float64* outCycleStartBeat, - Float64* outCycleEndBeat) + Boolean* outTransportStateChanged, + Float64* outCurrentSampleInTimeLine, + Boolean* outIsCycling, + Float64* outCycleStartBeat, + Float64* outCycleEndBeat) { - AudioPlayHead* const ph = getPlayHead(); - AudioPlayHead::CurrentPositionInfo result; + AudioPlayHead* const ph = getPlayHead(); + AudioPlayHead::CurrentPositionInfo result; - if (ph != 0 && ph->getCurrentPosition (result)) - { - if (outIsPlaying != 0) - *outIsPlaying = result.isPlaying; + if (ph != 0 && ph->getCurrentPosition (result)) + { + if (outIsPlaying != 0) + *outIsPlaying = result.isPlaying; - if (outTransportStateChanged != 0) - { - *outTransportStateChanged = result.isPlaying != wasPlaying; - wasPlaying = result.isPlaying; - } + if (outTransportStateChanged != 0) + { + *outTransportStateChanged = result.isPlaying != wasPlaying; + wasPlaying = result.isPlaying; + } - if (outCurrentSampleInTimeLine != 0) - *outCurrentSampleInTimeLine = roundDoubleToInt (result.timeInSeconds * getSampleRate()); + if (outCurrentSampleInTimeLine != 0) + *outCurrentSampleInTimeLine = roundToInt (result.timeInSeconds * getSampleRate()); - if (outIsCycling != 0) - *outIsCycling = false; + if (outIsCycling != 0) + *outIsCycling = false; - if (outCycleStartBeat != 0) - *outCycleStartBeat = 0; + if (outCycleStartBeat != 0) + *outCycleStartBeat = 0; - if (outCycleEndBeat != 0) - *outCycleEndBeat = 0; - } - else - { - if (outIsPlaying != 0) - *outIsPlaying = false; + if (outCycleEndBeat != 0) + *outCycleEndBeat = 0; + } + else + { + if (outIsPlaying != 0) + *outIsPlaying = false; - if (outTransportStateChanged != 0) - *outTransportStateChanged = false; + if (outTransportStateChanged != 0) + *outTransportStateChanged = false; - if (outCurrentSampleInTimeLine != 0) - *outCurrentSampleInTimeLine = 0; + if (outCurrentSampleInTimeLine != 0) + *outCurrentSampleInTimeLine = 0; - if (outIsCycling != 0) - *outIsCycling = false; + if (outIsCycling != 0) + *outIsCycling = false; - if (outCycleStartBeat != 0) - *outCycleStartBeat = 0; + if (outCycleStartBeat != 0) + *outCycleStartBeat = 0; - if (outCycleEndBeat != 0) - *outCycleEndBeat = 0; - } + if (outCycleEndBeat != 0) + *outCycleEndBeat = 0; + } - return noErr; + return noErr; } static VoidArray activeWindows; -class AudioUnitPluginWindowCocoa : public AudioProcessorEditor +class AudioUnitPluginWindowCocoa : public AudioProcessorEditor { public: - AudioUnitPluginWindowCocoa (AudioUnitPluginInstance& plugin_, const bool createGenericViewIfNeeded) - : AudioProcessorEditor (&plugin_), - plugin (plugin_), - wrapper (0) - { - addAndMakeVisible (wrapper = new NSViewComponent()); + AudioUnitPluginWindowCocoa (AudioUnitPluginInstance& plugin_, const bool createGenericViewIfNeeded) + : AudioProcessorEditor (&plugin_), + plugin (plugin_), + wrapper (0) + { + addAndMakeVisible (wrapper = new NSViewComponent()); - activeWindows.add (this); + activeWindows.add (this); - setOpaque (true); - setVisible (true); - setSize (100, 100); + setOpaque (true); + setVisible (true); + setSize (100, 100); - createView (createGenericViewIfNeeded); - } + createView (createGenericViewIfNeeded); + } - ~AudioUnitPluginWindowCocoa() - { - const bool wasValid = isValid(); + ~AudioUnitPluginWindowCocoa() + { + const bool wasValid = isValid(); - wrapper->setView (0); - activeWindows.removeValue (this); + wrapper->setView (0); + activeWindows.removeValue (this); - if (wasValid) - plugin.editorBeingDeleted (this); + if (wasValid) + plugin.editorBeingDeleted (this); - delete wrapper; - } + delete wrapper; + } - bool isValid() const { return wrapper->getView() != 0; } + bool isValid() const { return wrapper->getView() != 0; } - void paint (Graphics& g) - { - g.fillAll (Colours::white); - } + void paint (Graphics& g) + { + g.fillAll (Colours::white); + } - void resized() - { - wrapper->setSize (getWidth(), getHeight()); - } + void resized() + { + wrapper->setSize (getWidth(), getHeight()); + } private: - AudioUnitPluginInstance& plugin; - NSViewComponent* wrapper; + AudioUnitPluginInstance& plugin; + NSViewComponent* wrapper; - bool createView (const bool createGenericViewIfNeeded) - { - NSView* pluginView = 0; + bool createView (const bool createGenericViewIfNeeded) + { + NSView* pluginView = 0; - UInt32 dataSize = 0; - Boolean isWritable = false; + UInt32 dataSize = 0; + Boolean isWritable = false; - if (AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, - 0, &dataSize, &isWritable) == noErr - && dataSize != 0 - && AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, - 0, &dataSize, &isWritable) == noErr) - { - HeapBlock info; - info.calloc (dataSize, 1); + if (AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, + 0, &dataSize, &isWritable) == noErr + && dataSize != 0 + && AudioUnitGetPropertyInfo (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, + 0, &dataSize, &isWritable) == noErr) + { + HeapBlock info; + info.calloc (dataSize, 1); - if (AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, - 0, info, &dataSize) == noErr) - { - NSString* viewClassName = (NSString*) (info->mCocoaAUViewClass[0]); - NSString* path = (NSString*) CFURLCopyPath (info->mCocoaAUViewBundleLocation); - NSBundle* viewBundle = [NSBundle bundleWithPath: [path autorelease]]; - Class viewClass = [viewBundle classNamed: viewClassName]; + if (AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_CocoaUI, kAudioUnitScope_Global, + 0, info, &dataSize) == noErr) + { + NSString* viewClassName = (NSString*) (info->mCocoaAUViewClass[0]); + NSString* path = (NSString*) CFURLCopyPath (info->mCocoaAUViewBundleLocation); + NSBundle* viewBundle = [NSBundle bundleWithPath: [path autorelease]]; + Class viewClass = [viewBundle classNamed: viewClassName]; - if ([viewClass conformsToProtocol: @protocol (AUCocoaUIBase)] - && [viewClass instancesRespondToSelector: @selector (interfaceVersion)] - && [viewClass instancesRespondToSelector: @selector (uiViewForAudioUnit: withSize:)]) - { - id factory = [[[viewClass alloc] init] autorelease]; - pluginView = [factory uiViewForAudioUnit: plugin.audioUnit - withSize: NSMakeSize (getWidth(), getHeight())]; - } + if ([viewClass conformsToProtocol: @protocol (AUCocoaUIBase)] + && [viewClass instancesRespondToSelector: @selector (interfaceVersion)] + && [viewClass instancesRespondToSelector: @selector (uiViewForAudioUnit: withSize:)]) + { + id factory = [[[viewClass alloc] init] autorelease]; + pluginView = [factory uiViewForAudioUnit: plugin.audioUnit + withSize: NSMakeSize (getWidth(), getHeight())]; + } - for (int i = (dataSize - sizeof (CFURLRef)) / sizeof (CFStringRef); --i >= 0;) - { - CFRelease (info->mCocoaAUViewClass[i]); - CFRelease (info->mCocoaAUViewBundleLocation); - } - } - } + for (int i = (dataSize - sizeof (CFURLRef)) / sizeof (CFStringRef); --i >= 0;) + { + CFRelease (info->mCocoaAUViewClass[i]); + CFRelease (info->mCocoaAUViewBundleLocation); + } + } + } - if (createGenericViewIfNeeded && (pluginView == 0)) - pluginView = [[AUGenericView alloc] initWithAudioUnit: plugin.audioUnit]; + if (createGenericViewIfNeeded && (pluginView == 0)) + pluginView = [[AUGenericView alloc] initWithAudioUnit: plugin.audioUnit]; - wrapper->setView (pluginView); + wrapper->setView (pluginView); - if (pluginView != 0) - setSize ([pluginView frame].size.width, - [pluginView frame].size.height); + if (pluginView != 0) + setSize ([pluginView frame].size.width, + [pluginView frame].size.height); - return pluginView != 0; - } + return pluginView != 0; + } }; #if JUCE_SUPPORT_CARBON @@ -31118,441 +30852,441 @@ class AudioUnitPluginWindowCarbon : public AudioProcessorEditor { public: - AudioUnitPluginWindowCarbon (AudioUnitPluginInstance& plugin_) - : AudioProcessorEditor (&plugin_), - plugin (plugin_), - viewComponent (0) - { - addAndMakeVisible (innerWrapper = new InnerWrapperComponent (this)); + AudioUnitPluginWindowCarbon (AudioUnitPluginInstance& plugin_) + : AudioProcessorEditor (&plugin_), + plugin (plugin_), + viewComponent (0) + { + addAndMakeVisible (innerWrapper = new InnerWrapperComponent (this)); - activeWindows.add (this); + activeWindows.add (this); - setOpaque (true); - setVisible (true); - setSize (400, 300); + setOpaque (true); + setVisible (true); + setSize (400, 300); - ComponentDescription viewList [16]; - UInt32 viewListSize = sizeof (viewList); - AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, - 0, &viewList, &viewListSize); + ComponentDescription viewList [16]; + UInt32 viewListSize = sizeof (viewList); + AudioUnitGetProperty (plugin.audioUnit, kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, + 0, &viewList, &viewListSize); - componentRecord = FindNextComponent (0, &viewList[0]); - } + componentRecord = FindNextComponent (0, &viewList[0]); + } - ~AudioUnitPluginWindowCarbon() - { - deleteAndZero (innerWrapper); + ~AudioUnitPluginWindowCarbon() + { + deleteAndZero (innerWrapper); - activeWindows.removeValue (this); + activeWindows.removeValue (this); - if (isValid()) - plugin.editorBeingDeleted (this); - } + if (isValid()) + plugin.editorBeingDeleted (this); + } - bool isValid() const throw() { return componentRecord != 0; } + bool isValid() const throw() { return componentRecord != 0; } - void paint (Graphics& g) - { - g.fillAll (Colours::black); - } + void paint (Graphics& g) + { + g.fillAll (Colours::black); + } - void resized() - { - innerWrapper->setSize (getWidth(), getHeight()); - } + void resized() + { + innerWrapper->setSize (getWidth(), getHeight()); + } - bool keyStateChanged (const bool) - { - return false; - } + bool keyStateChanged (const bool) + { + return false; + } - bool keyPressed (const KeyPress&) - { - return false; - } + bool keyPressed (const KeyPress&) + { + return false; + } - void broughtToFront() - { - activeWindows.removeValue (this); - activeWindows.add (this); - } + void broughtToFront() + { + activeWindows.removeValue (this); + activeWindows.add (this); + } - AudioUnit getAudioUnit() const { return plugin.audioUnit; } + AudioUnit getAudioUnit() const { return plugin.audioUnit; } - AudioUnitCarbonView getViewComponent() - { - if (viewComponent == 0 && componentRecord != 0) - viewComponent = (AudioUnitCarbonView) OpenComponent (componentRecord); + AudioUnitCarbonView getViewComponent() + { + if (viewComponent == 0 && componentRecord != 0) + viewComponent = (AudioUnitCarbonView) OpenComponent (componentRecord); - return viewComponent; - } + return viewComponent; + } - void closeViewComponent() - { - if (viewComponent != 0) - { - CloseComponent (viewComponent); - viewComponent = 0; - } - } + void closeViewComponent() + { + if (viewComponent != 0) + { + CloseComponent (viewComponent); + viewComponent = 0; + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioUnitPluginInstance& plugin; - ComponentRecord* componentRecord; - AudioUnitCarbonView viewComponent; + AudioUnitPluginInstance& plugin; + ComponentRecord* componentRecord; + AudioUnitCarbonView viewComponent; - class InnerWrapperComponent : public CarbonViewWrapperComponent - { - public: - InnerWrapperComponent (AudioUnitPluginWindowCarbon* const owner_) - : owner (owner_) - { - } + class InnerWrapperComponent : public CarbonViewWrapperComponent + { + public: + InnerWrapperComponent (AudioUnitPluginWindowCarbon* const owner_) + : owner (owner_) + { + } - ~InnerWrapperComponent() - { - deleteWindow(); - } + ~InnerWrapperComponent() + { + deleteWindow(); + } - HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) - { - log (T("Opening AU GUI: ") + owner->plugin.getName()); + HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) + { + log (T("Opening AU GUI: ") + owner->plugin.getName()); - AudioUnitCarbonView viewComponent = owner->getViewComponent(); + AudioUnitCarbonView viewComponent = owner->getViewComponent(); - if (viewComponent == 0) - return 0; + if (viewComponent == 0) + return 0; - Float32Point pos = { 0, 0 }; - Float32Point size = { 250, 200 }; + Float32Point pos = { 0, 0 }; + Float32Point size = { 250, 200 }; - HIViewRef pluginView = 0; + HIViewRef pluginView = 0; - AudioUnitCarbonViewCreate (viewComponent, - owner->getAudioUnit(), - windowRef, - rootView, - &pos, - &size, - (ControlRef*) &pluginView); + AudioUnitCarbonViewCreate (viewComponent, + owner->getAudioUnit(), + windowRef, + rootView, + &pos, + &size, + (ControlRef*) &pluginView); - return pluginView; - } + return pluginView; + } - void removeView (HIViewRef) - { - log (T("Closing AU GUI: ") + owner->plugin.getName()); + void removeView (HIViewRef) + { + log (T("Closing AU GUI: ") + owner->plugin.getName()); - owner->closeViewComponent(); - } + owner->closeViewComponent(); + } - private: - AudioUnitPluginWindowCarbon* const owner; - }; + private: + AudioUnitPluginWindowCarbon* const owner; + }; - friend class InnerWrapperComponent; - InnerWrapperComponent* innerWrapper; + friend class InnerWrapperComponent; + InnerWrapperComponent* innerWrapper; }; #endif AudioProcessorEditor* AudioUnitPluginInstance::createEditor() { - ScopedPointer w (new AudioUnitPluginWindowCocoa (*this, false)); + ScopedPointer w (new AudioUnitPluginWindowCocoa (*this, false)); - if (! ((AudioUnitPluginWindowCocoa*) w)->isValid()) - w = 0; + if (! ((AudioUnitPluginWindowCocoa*) w)->isValid()) + w = 0; #if JUCE_SUPPORT_CARBON - if (w == 0) - { - w = new AudioUnitPluginWindowCarbon (*this); + if (w == 0) + { + w = new AudioUnitPluginWindowCarbon (*this); - if (! ((AudioUnitPluginWindowCarbon*) w)->isValid()) - w = 0; - } + if (! ((AudioUnitPluginWindowCarbon*) w)->isValid()) + w = 0; + } #endif - if (w == 0) - w = new AudioUnitPluginWindowCocoa (*this, true); // use AUGenericView as a fallback + if (w == 0) + w = new AudioUnitPluginWindowCocoa (*this, true); // use AUGenericView as a fallback - return w.release(); + return w.release(); } const String AudioUnitPluginInstance::getCategory() const { - const char* result = 0; + const char* result = 0; - switch (componentDesc.componentType) - { - case kAudioUnitType_Effect: - case kAudioUnitType_MusicEffect: - result = "Effect"; - break; - case kAudioUnitType_MusicDevice: - result = "Synth"; - break; - case kAudioUnitType_Generator: - result = "Generator"; - break; - case kAudioUnitType_Panner: - result = "Panner"; - break; - default: - break; - } + switch (componentDesc.componentType) + { + case kAudioUnitType_Effect: + case kAudioUnitType_MusicEffect: + result = "Effect"; + break; + case kAudioUnitType_MusicDevice: + result = "Synth"; + break; + case kAudioUnitType_Generator: + result = "Generator"; + break; + case kAudioUnitType_Panner: + result = "Panner"; + break; + default: + break; + } - return result; + return result; } int AudioUnitPluginInstance::getNumParameters() { - return parameterIds.size(); + return parameterIds.size(); } float AudioUnitPluginInstance::getParameter (int index) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - Float32 value = 0.0f; + Float32 value = 0.0f; - if (audioUnit != 0 && ((unsigned int) index) < (unsigned int) parameterIds.size()) - { - AudioUnitGetParameter (audioUnit, - (UInt32) parameterIds.getUnchecked (index), - kAudioUnitScope_Global, 0, - &value); - } + if (audioUnit != 0 && ((unsigned int) index) < (unsigned int) parameterIds.size()) + { + AudioUnitGetParameter (audioUnit, + (UInt32) parameterIds.getUnchecked (index), + kAudioUnitScope_Global, 0, + &value); + } - return value; + return value; } void AudioUnitPluginInstance::setParameter (int index, float newValue) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (audioUnit != 0 && ((unsigned int) index) < (unsigned int) parameterIds.size()) - { - AudioUnitSetParameter (audioUnit, - (UInt32) parameterIds.getUnchecked (index), - kAudioUnitScope_Global, 0, - newValue, 0); - } + if (audioUnit != 0 && ((unsigned int) index) < (unsigned int) parameterIds.size()) + { + AudioUnitSetParameter (audioUnit, + (UInt32) parameterIds.getUnchecked (index), + kAudioUnitScope_Global, 0, + newValue, 0); + } } const String AudioUnitPluginInstance::getParameterName (int index) { - AudioUnitParameterInfo info; - zerostruct (info); - UInt32 sz = sizeof (info); + AudioUnitParameterInfo info; + zerostruct (info); + UInt32 sz = sizeof (info); - String name; + String name; - if (AudioUnitGetProperty (audioUnit, - kAudioUnitProperty_ParameterInfo, - kAudioUnitScope_Global, - parameterIds [index], &info, &sz) == noErr) - { - if ((info.flags & kAudioUnitParameterFlag_HasCFNameString) != 0) - name = PlatformUtilities::cfStringToJuceString (info.cfNameString); - else - name = String (info.name, sizeof (info.name)); - } + if (AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_ParameterInfo, + kAudioUnitScope_Global, + parameterIds [index], &info, &sz) == noErr) + { + if ((info.flags & kAudioUnitParameterFlag_HasCFNameString) != 0) + name = PlatformUtilities::cfStringToJuceString (info.cfNameString); + else + name = String (info.name, sizeof (info.name)); + } - return name; + return name; } const String AudioUnitPluginInstance::getParameterText (int index) { - return String (getParameter (index)); + return String (getParameter (index)); } bool AudioUnitPluginInstance::isParameterAutomatable (int index) const { - AudioUnitParameterInfo info; - UInt32 sz = sizeof (info); + AudioUnitParameterInfo info; + UInt32 sz = sizeof (info); - if (AudioUnitGetProperty (audioUnit, - kAudioUnitProperty_ParameterInfo, - kAudioUnitScope_Global, - parameterIds [index], &info, &sz) == noErr) - { - return (info.flags & kAudioUnitParameterFlag_NonRealTime) == 0; - } + if (AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_ParameterInfo, + kAudioUnitScope_Global, + parameterIds [index], &info, &sz) == noErr) + { + return (info.flags & kAudioUnitParameterFlag_NonRealTime) == 0; + } - return true; + return true; } int AudioUnitPluginInstance::getNumPrograms() { - CFArrayRef presets; - UInt32 sz = sizeof (CFArrayRef); - int num = 0; + CFArrayRef presets; + UInt32 sz = sizeof (CFArrayRef); + int num = 0; - if (AudioUnitGetProperty (audioUnit, - kAudioUnitProperty_FactoryPresets, - kAudioUnitScope_Global, - 0, &presets, &sz) == noErr) - { - num = (int) CFArrayGetCount (presets); - CFRelease (presets); - } + if (AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_FactoryPresets, + kAudioUnitScope_Global, + 0, &presets, &sz) == noErr) + { + num = (int) CFArrayGetCount (presets); + CFRelease (presets); + } - return num; + return num; } int AudioUnitPluginInstance::getCurrentProgram() { - AUPreset current; - current.presetNumber = 0; - UInt32 sz = sizeof (AUPreset); + AUPreset current; + current.presetNumber = 0; + UInt32 sz = sizeof (AUPreset); - AudioUnitGetProperty (audioUnit, - kAudioUnitProperty_FactoryPresets, - kAudioUnitScope_Global, - 0, ¤t, &sz); + AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_FactoryPresets, + kAudioUnitScope_Global, + 0, ¤t, &sz); - return current.presetNumber; + return current.presetNumber; } void AudioUnitPluginInstance::setCurrentProgram (int newIndex) { - AUPreset current; - current.presetNumber = newIndex; - current.presetName = 0; + AUPreset current; + current.presetNumber = newIndex; + current.presetName = 0; - AudioUnitSetProperty (audioUnit, - kAudioUnitProperty_FactoryPresets, - kAudioUnitScope_Global, - 0, ¤t, sizeof (AUPreset)); + AudioUnitSetProperty (audioUnit, + kAudioUnitProperty_FactoryPresets, + kAudioUnitScope_Global, + 0, ¤t, sizeof (AUPreset)); } const String AudioUnitPluginInstance::getProgramName (int index) { - String s; - CFArrayRef presets; - UInt32 sz = sizeof (CFArrayRef); + String s; + CFArrayRef presets; + UInt32 sz = sizeof (CFArrayRef); - if (AudioUnitGetProperty (audioUnit, - kAudioUnitProperty_FactoryPresets, - kAudioUnitScope_Global, - 0, &presets, &sz) == noErr) - { - for (CFIndex i = 0; i < CFArrayGetCount (presets); ++i) - { - const AUPreset* p = (const AUPreset*) CFArrayGetValueAtIndex (presets, i); + if (AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_FactoryPresets, + kAudioUnitScope_Global, + 0, &presets, &sz) == noErr) + { + for (CFIndex i = 0; i < CFArrayGetCount (presets); ++i) + { + const AUPreset* p = (const AUPreset*) CFArrayGetValueAtIndex (presets, i); - if (p != 0 && p->presetNumber == index) - { - s = PlatformUtilities::cfStringToJuceString (p->presetName); - break; - } - } + if (p != 0 && p->presetNumber == index) + { + s = PlatformUtilities::cfStringToJuceString (p->presetName); + break; + } + } - CFRelease (presets); - } + CFRelease (presets); + } - return s; + return s; } void AudioUnitPluginInstance::changeProgramName (int index, const String& newName) { - jassertfalse // xxx not implemented! + jassertfalse // xxx not implemented! } const String AudioUnitPluginInstance::getInputChannelName (const int index) const { - if (((unsigned int) index) < (unsigned int) getNumInputChannels()) - return T("Input ") + String (index + 1); + if (((unsigned int) index) < (unsigned int) getNumInputChannels()) + return T("Input ") + String (index + 1); - return String::empty; + return String::empty; } bool AudioUnitPluginInstance::isInputChannelStereoPair (int index) const { - if (((unsigned int) index) >= (unsigned int) getNumInputChannels()) - return false; + if (((unsigned int) index) >= (unsigned int) getNumInputChannels()) + return false; - return true; + return true; } const String AudioUnitPluginInstance::getOutputChannelName (const int index) const { - if (((unsigned int) index) < (unsigned int) getNumOutputChannels()) - return T("Output ") + String (index + 1); + if (((unsigned int) index) < (unsigned int) getNumOutputChannels()) + return T("Output ") + String (index + 1); - return String::empty; + return String::empty; } bool AudioUnitPluginInstance::isOutputChannelStereoPair (int index) const { - if (((unsigned int) index) >= (unsigned int) getNumOutputChannels()) - return false; + if (((unsigned int) index) >= (unsigned int) getNumOutputChannels()) + return false; - return true; + return true; } void AudioUnitPluginInstance::getStateInformation (MemoryBlock& destData) { - getCurrentProgramStateInformation (destData); + getCurrentProgramStateInformation (destData); } void AudioUnitPluginInstance::getCurrentProgramStateInformation (MemoryBlock& destData) { - CFPropertyListRef propertyList = 0; - UInt32 sz = sizeof (CFPropertyListRef); + CFPropertyListRef propertyList = 0; + UInt32 sz = sizeof (CFPropertyListRef); - if (AudioUnitGetProperty (audioUnit, - kAudioUnitProperty_ClassInfo, - kAudioUnitScope_Global, - 0, &propertyList, &sz) == noErr) - { - CFWriteStreamRef stream = CFWriteStreamCreateWithAllocatedBuffers (kCFAllocatorDefault, kCFAllocatorDefault); - CFWriteStreamOpen (stream); + if (AudioUnitGetProperty (audioUnit, + kAudioUnitProperty_ClassInfo, + kAudioUnitScope_Global, + 0, &propertyList, &sz) == noErr) + { + CFWriteStreamRef stream = CFWriteStreamCreateWithAllocatedBuffers (kCFAllocatorDefault, kCFAllocatorDefault); + CFWriteStreamOpen (stream); - CFIndex bytesWritten = CFPropertyListWriteToStream (propertyList, stream, kCFPropertyListBinaryFormat_v1_0, 0); - CFWriteStreamClose (stream); + CFIndex bytesWritten = CFPropertyListWriteToStream (propertyList, stream, kCFPropertyListBinaryFormat_v1_0, 0); + CFWriteStreamClose (stream); - CFDataRef data = (CFDataRef) CFWriteStreamCopyProperty (stream, kCFStreamPropertyDataWritten); + CFDataRef data = (CFDataRef) CFWriteStreamCopyProperty (stream, kCFStreamPropertyDataWritten); - destData.setSize (bytesWritten); - destData.copyFrom (CFDataGetBytePtr (data), 0, destData.getSize()); - CFRelease (data); + destData.setSize (bytesWritten); + destData.copyFrom (CFDataGetBytePtr (data), 0, destData.getSize()); + CFRelease (data); - CFRelease (stream); - CFRelease (propertyList); - } + CFRelease (stream); + CFRelease (propertyList); + } } void AudioUnitPluginInstance::setStateInformation (const void* data, int sizeInBytes) { - setCurrentProgramStateInformation (data, sizeInBytes); + setCurrentProgramStateInformation (data, sizeInBytes); } void AudioUnitPluginInstance::setCurrentProgramStateInformation (const void* data, int sizeInBytes) { - CFReadStreamRef stream = CFReadStreamCreateWithBytesNoCopy (kCFAllocatorDefault, - (const UInt8*) data, - sizeInBytes, - kCFAllocatorNull); - CFReadStreamOpen (stream); + CFReadStreamRef stream = CFReadStreamCreateWithBytesNoCopy (kCFAllocatorDefault, + (const UInt8*) data, + sizeInBytes, + kCFAllocatorNull); + CFReadStreamOpen (stream); - CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0; - CFPropertyListRef propertyList = CFPropertyListCreateFromStream (kCFAllocatorDefault, - stream, - 0, - kCFPropertyListImmutable, - &format, - 0); - CFRelease (stream); + CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0; + CFPropertyListRef propertyList = CFPropertyListCreateFromStream (kCFAllocatorDefault, + stream, + 0, + kCFPropertyListImmutable, + &format, + 0); + CFRelease (stream); - if (propertyList != 0) - AudioUnitSetProperty (audioUnit, - kAudioUnitProperty_ClassInfo, - kAudioUnitScope_Global, - 0, &propertyList, sizeof (propertyList)); + if (propertyList != 0) + AudioUnitSetProperty (audioUnit, + kAudioUnitProperty_ClassInfo, + kAudioUnitScope_Global, + 0, &propertyList, sizeof (propertyList)); } AudioUnitPluginFormat::AudioUnitPluginFormat() @@ -31564,118 +31298,118 @@ AudioUnitPluginFormat::~AudioUnitPluginFormat() } void AudioUnitPluginFormat::findAllTypesForFile (OwnedArray & results, - const String& fileOrIdentifier) + const String& fileOrIdentifier) { - if (! fileMightContainThisPluginType (fileOrIdentifier)) - return; + if (! fileMightContainThisPluginType (fileOrIdentifier)) + return; - PluginDescription desc; - desc.fileOrIdentifier = fileOrIdentifier; - desc.uid = 0; + PluginDescription desc; + desc.fileOrIdentifier = fileOrIdentifier; + desc.uid = 0; - try - { - ScopedPointer createdInstance (createInstanceFromDescription (desc)); - AudioUnitPluginInstance* const auInstance = dynamic_cast ((AudioPluginInstance*) createdInstance); + try + { + ScopedPointer createdInstance (createInstanceFromDescription (desc)); + AudioUnitPluginInstance* const auInstance = dynamic_cast ((AudioPluginInstance*) createdInstance); - if (auInstance != 0) - { - auInstance->fillInPluginDescription (desc); - results.add (new PluginDescription (desc)); - } - } - catch (...) - { - // crashed while loading... - } + if (auInstance != 0) + { + auInstance->fillInPluginDescription (desc); + results.add (new PluginDescription (desc)); + } + } + catch (...) + { + // crashed while loading... + } } AudioPluginInstance* AudioUnitPluginFormat::createInstanceFromDescription (const PluginDescription& desc) { - if (fileMightContainThisPluginType (desc.fileOrIdentifier)) - { - ScopedPointer result (new AudioUnitPluginInstance (desc.fileOrIdentifier)); + if (fileMightContainThisPluginType (desc.fileOrIdentifier)) + { + ScopedPointer result (new AudioUnitPluginInstance (desc.fileOrIdentifier)); - if (result->audioUnit != 0) - { - result->initialise(); - return result.release(); - } - } + if (result->audioUnit != 0) + { + result->initialise(); + return result.release(); + } + } - return 0; + return 0; } const StringArray AudioUnitPluginFormat::searchPathsForPlugins (const FileSearchPath& /*directoriesToSearch*/, - const bool /*recursive*/) + const bool /*recursive*/) { - StringArray result; - ComponentRecord* comp = 0; - ComponentDescription desc; - zerostruct (desc); + StringArray result; + ComponentRecord* comp = 0; + ComponentDescription desc; + zerostruct (desc); - for (;;) - { - zerostruct (desc); - comp = FindNextComponent (comp, &desc); + for (;;) + { + zerostruct (desc); + comp = FindNextComponent (comp, &desc); - if (comp == 0) - break; + if (comp == 0) + break; - GetComponentInfo (comp, &desc, 0, 0, 0); + GetComponentInfo (comp, &desc, 0, 0, 0); - if (desc.componentType == kAudioUnitType_MusicDevice - || desc.componentType == kAudioUnitType_MusicEffect - || desc.componentType == kAudioUnitType_Effect - || desc.componentType == kAudioUnitType_Generator - || desc.componentType == kAudioUnitType_Panner) - { - const String s (createAUPluginIdentifier (desc)); - DBG (s); - result.add (s); - } - } + if (desc.componentType == kAudioUnitType_MusicDevice + || desc.componentType == kAudioUnitType_MusicEffect + || desc.componentType == kAudioUnitType_Effect + || desc.componentType == kAudioUnitType_Generator + || desc.componentType == kAudioUnitType_Panner) + { + const String s (createAUPluginIdentifier (desc)); + DBG (s); + result.add (s); + } + } - return result; + return result; } bool AudioUnitPluginFormat::fileMightContainThisPluginType (const String& fileOrIdentifier) { - ComponentDescription desc; + ComponentDescription desc; - String name, version, manufacturer; - if (getComponentDescFromIdentifier (fileOrIdentifier, desc, name, version, manufacturer)) - return FindNextComponent (0, &desc) != 0; + String name, version, manufacturer; + if (getComponentDescFromIdentifier (fileOrIdentifier, desc, name, version, manufacturer)) + return FindNextComponent (0, &desc) != 0; - const File f (fileOrIdentifier); + const File f (fileOrIdentifier); - return f.hasFileExtension (T(".component")) - && f.isDirectory(); + return f.hasFileExtension (T(".component")) + && f.isDirectory(); } const String AudioUnitPluginFormat::getNameOfPluginFromIdentifier (const String& fileOrIdentifier) { - ComponentDescription desc; - String name, version, manufacturer; - getComponentDescFromIdentifier (fileOrIdentifier, desc, name, version, manufacturer); + ComponentDescription desc; + String name, version, manufacturer; + getComponentDescFromIdentifier (fileOrIdentifier, desc, name, version, manufacturer); - if (name.isEmpty()) - name = fileOrIdentifier; + if (name.isEmpty()) + name = fileOrIdentifier; - return name; + return name; } bool AudioUnitPluginFormat::doesPluginStillExist (const PluginDescription& desc) { - if (desc.fileOrIdentifier.startsWithIgnoreCase (auIdentifierPrefix)) - return fileMightContainThisPluginType (desc.fileOrIdentifier); - else - return File (desc.fileOrIdentifier).exists(); + if (desc.fileOrIdentifier.startsWithIgnoreCase (auIdentifierPrefix)) + return fileMightContainThisPluginType (desc.fileOrIdentifier); + else + return File (desc.fileOrIdentifier).exists(); } const FileSearchPath AudioUnitPluginFormat::getDefaultLocationsToSearch() { - return FileSearchPath ("/(Default AudioUnit locations)"); + return FileSearchPath ("/(Default AudioUnit locations)"); } #endif @@ -31739,12 +31473,6 @@ BEGIN_JUCE_NAMESPACE #pragma warning (disable: 4996) #endif -/* Obviously you're going to need the Steinberg vstsdk2.4 folder in - your include path if you want to add VST support. - - If you're not interested in VSTs, you can disable them by changing the - JUCE_PLUGINHOST_VST flag in juce_Config.h -*/ #include "pluginterfaces/vst2.x/aeffectx.h" #ifdef _MSC_VER @@ -31752,10 +31480,10 @@ BEGIN_JUCE_NAMESPACE #endif #if JUCE_LINUX - #define Font JUCE_NAMESPACE::Font + #define Font JUCE_NAMESPACE::Font #define KeyPress JUCE_NAMESPACE::KeyPress #define Drawable JUCE_NAMESPACE::Drawable - #define Time JUCE_NAMESPACE::Time + #define Time JUCE_NAMESPACE::Time #endif /********* Start of inlined file: juce_VSTMidiEventList.h *********/ @@ -31764,153 +31492,148 @@ BEGIN_JUCE_NAMESPACE #ifndef __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ #define __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ -/** Holds a set of VSTMidiEvent objects and makes it easy to add - events to the list. - - This is used by both the VST hosting code and the plugin wrapper. -*/ class VSTMidiEventList { public: - VSTMidiEventList() - : numEventsUsed (0), numEventsAllocated (0) - { - } + VSTMidiEventList() + : numEventsUsed (0), numEventsAllocated (0) + { + } - ~VSTMidiEventList() - { - freeEvents(); - } + ~VSTMidiEventList() + { + freeEvents(); + } - void clear() - { - numEventsUsed = 0; + void clear() + { + numEventsUsed = 0; - if (events != 0) - events->numEvents = 0; - } + if (events != 0) + events->numEvents = 0; + } - void addEvent (const void* const midiData, const int numBytes, const int frameOffset) - { - ensureSize (numEventsUsed + 1); + void addEvent (const void* const midiData, const int numBytes, const int frameOffset) + { + ensureSize (numEventsUsed + 1); - VstMidiEvent* const e = (VstMidiEvent*) (events->events [numEventsUsed]); - events->numEvents = ++numEventsUsed; + VstMidiEvent* const e = (VstMidiEvent*) (events->events [numEventsUsed]); + events->numEvents = ++numEventsUsed; - if (numBytes <= 4) - { - if (e->type == kVstSysExType) - { - juce_free (((VstMidiSysexEvent*) e)->sysexDump); - e->type = kVstMidiType; - e->byteSize = sizeof (VstMidiEvent); - e->noteLength = 0; - e->noteOffset = 0; - e->detune = 0; - e->noteOffVelocity = 0; - } + if (numBytes <= 4) + { + if (e->type == kVstSysExType) + { + juce_free (((VstMidiSysexEvent*) e)->sysexDump); + e->type = kVstMidiType; + e->byteSize = sizeof (VstMidiEvent); + e->noteLength = 0; + e->noteOffset = 0; + e->detune = 0; + e->noteOffVelocity = 0; + } - e->deltaFrames = frameOffset; - memcpy (e->midiData, midiData, numBytes); - } - else - { - VstMidiSysexEvent* const se = (VstMidiSysexEvent*) e; + e->deltaFrames = frameOffset; + memcpy (e->midiData, midiData, numBytes); + } + else + { + VstMidiSysexEvent* const se = (VstMidiSysexEvent*) e; - if (se->type == kVstSysExType) - se->sysexDump = (char*) juce_realloc (se->sysexDump, numBytes); - else - se->sysexDump = (char*) juce_malloc (numBytes); + if (se->type == kVstSysExType) + se->sysexDump = (char*) juce_realloc (se->sysexDump, numBytes); + else + se->sysexDump = (char*) juce_malloc (numBytes); - memcpy (se->sysexDump, midiData, numBytes); + memcpy (se->sysexDump, midiData, numBytes); - se->type = kVstSysExType; - se->byteSize = sizeof (VstMidiSysexEvent); - se->deltaFrames = frameOffset; - se->flags = 0; - se->dumpBytes = numBytes; - se->resvd1 = 0; - se->resvd2 = 0; - } - } + se->type = kVstSysExType; + se->byteSize = sizeof (VstMidiSysexEvent); + se->deltaFrames = frameOffset; + se->flags = 0; + se->dumpBytes = numBytes; + se->resvd1 = 0; + se->resvd2 = 0; + } + } - // Handy method to pull the events out of an event buffer supplied by the host - // or plugin. - static void addEventsToMidiBuffer (const VstEvents* events, MidiBuffer& dest) - { - for (int i = 0; i < events->numEvents; ++i) - { - const VstEvent* const e = events->events[i]; + // Handy method to pull the events out of an event buffer supplied by the host + // or plugin. + static void addEventsToMidiBuffer (const VstEvents* events, MidiBuffer& dest) + { + for (int i = 0; i < events->numEvents; ++i) + { + const VstEvent* const e = events->events[i]; - if (e != 0) - { - if (e->type == kVstMidiType) - { - dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiEvent*) e)->midiData, - 4, e->deltaFrames); - } - else if (e->type == kVstSysExType) - { - dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiSysexEvent*) e)->sysexDump, - (int) ((const VstMidiSysexEvent*) e)->dumpBytes, - e->deltaFrames); - } - } - } - } + if (e != 0) + { + if (e->type == kVstMidiType) + { + dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiEvent*) e)->midiData, + 4, e->deltaFrames); + } + else if (e->type == kVstSysExType) + { + dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiSysexEvent*) e)->sysexDump, + (int) ((const VstMidiSysexEvent*) e)->dumpBytes, + e->deltaFrames); + } + } + } + } - void ensureSize (int numEventsNeeded) - { - if (numEventsNeeded > numEventsAllocated) - { - numEventsNeeded = (numEventsNeeded + 32) & ~31; + void ensureSize (int numEventsNeeded) + { + if (numEventsNeeded > numEventsAllocated) + { + numEventsNeeded = (numEventsNeeded + 32) & ~31; - const int size = 20 + sizeof (VstEvent*) * numEventsNeeded; + const int size = 20 + sizeof (VstEvent*) * numEventsNeeded; - if (events == 0) - events.calloc (size, 1); - else - events.realloc (size, 1); + if (events == 0) + events.calloc (size, 1); + else + events.realloc (size, 1); - for (int i = numEventsAllocated; i < numEventsNeeded; ++i) - { - VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (jmax ((int) sizeof (VstMidiEvent), - (int) sizeof (VstMidiSysexEvent))); - e->type = kVstMidiType; - e->byteSize = sizeof (VstMidiEvent); + for (int i = numEventsAllocated; i < numEventsNeeded; ++i) + { + VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (jmax ((int) sizeof (VstMidiEvent), + (int) sizeof (VstMidiSysexEvent))); + e->type = kVstMidiType; + e->byteSize = sizeof (VstMidiEvent); - events->events[i] = (VstEvent*) e; - } + events->events[i] = (VstEvent*) e; + } - numEventsAllocated = numEventsNeeded; - } - } + numEventsAllocated = numEventsNeeded; + } + } - void freeEvents() - { - if (events != 0) - { - for (int i = numEventsAllocated; --i >= 0;) - { - VstMidiEvent* const e = (VstMidiEvent*) (events->events[i]); + void freeEvents() + { + if (events != 0) + { + for (int i = numEventsAllocated; --i >= 0;) + { + VstMidiEvent* const e = (VstMidiEvent*) (events->events[i]); - if (e->type == kVstSysExType) - juce_free (((VstMidiSysexEvent*) e)->sysexDump); + if (e->type == kVstSysExType) + juce_free (((VstMidiSysexEvent*) e)->sysexDump); - juce_free (e); - } + juce_free (e); + } - events.free(); - numEventsUsed = 0; - numEventsAllocated = 0; - } - } + events.free(); + numEventsUsed = 0; + numEventsAllocated = 0; + } + } - HeapBlock events; + HeapBlock events; private: - int numEventsUsed, numEventsAllocated; + int numEventsUsed, numEventsAllocated; }; #endif // __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ @@ -31928,76 +31651,76 @@ const int fxbVersionNum = 1; struct fxProgram { - long chunkMagic; // 'CcnK' - long byteSize; // of this chunk, excl. magic + byteSize - long fxMagic; // 'FxCk' - long version; - long fxID; // fx unique id - long fxVersion; - long numParams; - char prgName[28]; - float params[1]; // variable no. of parameters + long chunkMagic; // 'CcnK' + long byteSize; // of this chunk, excl. magic + byteSize + long fxMagic; // 'FxCk' + long version; + long fxID; // fx unique id + long fxVersion; + long numParams; + char prgName[28]; + float params[1]; // variable no. of parameters }; struct fxSet { - long chunkMagic; // 'CcnK' - long byteSize; // of this chunk, excl. magic + byteSize - long fxMagic; // 'FxBk' - long version; - long fxID; // fx unique id - long fxVersion; - long numPrograms; - char future[128]; - fxProgram programs[1]; // variable no. of programs + long chunkMagic; // 'CcnK' + long byteSize; // of this chunk, excl. magic + byteSize + long fxMagic; // 'FxBk' + long version; + long fxID; // fx unique id + long fxVersion; + long numPrograms; + char future[128]; + fxProgram programs[1]; // variable no. of programs }; struct fxChunkSet { - long chunkMagic; // 'CcnK' - long byteSize; // of this chunk, excl. magic + byteSize - long fxMagic; // 'FxCh', 'FPCh', or 'FBCh' - long version; - long fxID; // fx unique id - long fxVersion; - long numPrograms; - char future[128]; - long chunkSize; - char chunk[8]; // variable + long chunkMagic; // 'CcnK' + long byteSize; // of this chunk, excl. magic + byteSize + long fxMagic; // 'FxCh', 'FPCh', or 'FBCh' + long version; + long fxID; // fx unique id + long fxVersion; + long numPrograms; + char future[128]; + long chunkSize; + char chunk[8]; // variable }; struct fxProgramSet { - long chunkMagic; // 'CcnK' - long byteSize; // of this chunk, excl. magic + byteSize - long fxMagic; // 'FxCh', 'FPCh', or 'FBCh' - long version; - long fxID; // fx unique id - long fxVersion; - long numPrograms; - char name[28]; - long chunkSize; - char chunk[8]; // variable + long chunkMagic; // 'CcnK' + long byteSize; // of this chunk, excl. magic + byteSize + long fxMagic; // 'FxCh', 'FPCh', or 'FBCh' + long version; + long fxID; // fx unique id + long fxVersion; + long numPrograms; + char name[28]; + long chunkSize; + char chunk[8]; // variable }; static long vst_swap (const long x) throw() { #ifdef JUCE_LITTLE_ENDIAN - return (long) ByteOrder::swap ((uint32) x); + return (long) ByteOrder::swap ((uint32) x); #else - return x; + return x; #endif } static float vst_swapFloat (const float x) throw() { #ifdef JUCE_LITTLE_ENDIAN - union { uint32 asInt; float asFloat; } n; - n.asFloat = x; - n.asInt = ByteOrder::swap (n.asInt); - return n.asFloat; + union { uint32 asInt; float asFloat; } n; + n.asFloat = x; + n.asInt = ByteOrder::swap (n.asInt); + return n.asFloat; #else - return x; + return x; #endif } @@ -32024,12 +31747,12 @@ class VSTPluginWindow; #if JUCE_MAC && JUCE_PPC static void* NewCFMFromMachO (void* const machofp) throw() { - void* result = juce_malloc (8); + void* result = juce_malloc (8); - ((void**) result)[0] = machofp; - ((void**) result)[1] = result; + ((void**) result)[0] = machofp; + ((void**) result)[1] = result; - return result; + return result; } #endif @@ -32044,1543 +31767,1529 @@ static bool xErrorTriggered; static int temporaryErrorHandler (Display*, XErrorEvent*) { - xErrorTriggered = true; - return 0; + xErrorTriggered = true; + return 0; } static int getPropertyFromXWindow (Window handle, Atom atom) { - XErrorHandler oldErrorHandler = XSetErrorHandler (temporaryErrorHandler); - xErrorTriggered = false; + XErrorHandler oldErrorHandler = XSetErrorHandler (temporaryErrorHandler); + xErrorTriggered = false; - int userSize; - unsigned long bytes, userCount; - unsigned char* data; - Atom userType; + int userSize; + unsigned long bytes, userCount; + unsigned char* data; + Atom userType; - XGetWindowProperty (display, handle, atom, 0, 1, false, AnyPropertyType, - &userType, &userSize, &userCount, &bytes, &data); + XGetWindowProperty (display, handle, atom, 0, 1, false, AnyPropertyType, + &userType, &userSize, &userCount, &bytes, &data); - XSetErrorHandler (oldErrorHandler); + XSetErrorHandler (oldErrorHandler); - return (userCount == 1 && ! xErrorTriggered) ? *(int*) data - : 0; + return (userCount == 1 && ! xErrorTriggered) ? *(int*) data + : 0; } static Window getChildWindow (Window windowToCheck) { - Window rootWindow, parentWindow; - Window* childWindows; - unsigned int numChildren; + Window rootWindow, parentWindow; + Window* childWindows; + unsigned int numChildren; - XQueryTree (display, - windowToCheck, - &rootWindow, - &parentWindow, - &childWindows, - &numChildren); + XQueryTree (display, + windowToCheck, + &rootWindow, + &parentWindow, + &childWindows, + &numChildren); - if (numChildren > 0) - return childWindows [0]; + if (numChildren > 0) + return childWindows [0]; - return 0; + return 0; } static void translateJuceToXButtonModifiers (const MouseEvent& e, XEvent& ev) throw() { - if (e.mods.isLeftButtonDown()) - { - ev.xbutton.button = Button1; - ev.xbutton.state |= Button1Mask; - } - else if (e.mods.isRightButtonDown()) - { - ev.xbutton.button = Button3; - ev.xbutton.state |= Button3Mask; - } - else if (e.mods.isMiddleButtonDown()) - { - ev.xbutton.button = Button2; - ev.xbutton.state |= Button2Mask; - } + if (e.mods.isLeftButtonDown()) + { + ev.xbutton.button = Button1; + ev.xbutton.state |= Button1Mask; + } + else if (e.mods.isRightButtonDown()) + { + ev.xbutton.button = Button3; + ev.xbutton.state |= Button3Mask; + } + else if (e.mods.isMiddleButtonDown()) + { + ev.xbutton.button = Button2; + ev.xbutton.state |= Button2Mask; + } } static void translateJuceToXMotionModifiers (const MouseEvent& e, XEvent& ev) throw() { - if (e.mods.isLeftButtonDown()) - ev.xmotion.state |= Button1Mask; - else if (e.mods.isRightButtonDown()) - ev.xmotion.state |= Button3Mask; - else if (e.mods.isMiddleButtonDown()) - ev.xmotion.state |= Button2Mask; + if (e.mods.isLeftButtonDown()) + ev.xmotion.state |= Button1Mask; + else if (e.mods.isRightButtonDown()) + ev.xmotion.state |= Button3Mask; + else if (e.mods.isMiddleButtonDown()) + ev.xmotion.state |= Button2Mask; } static void translateJuceToXCrossingModifiers (const MouseEvent& e, XEvent& ev) throw() { - if (e.mods.isLeftButtonDown()) - ev.xcrossing.state |= Button1Mask; - else if (e.mods.isRightButtonDown()) - ev.xcrossing.state |= Button3Mask; - else if (e.mods.isMiddleButtonDown()) - ev.xcrossing.state |= Button2Mask; + if (e.mods.isLeftButtonDown()) + ev.xcrossing.state |= Button1Mask; + else if (e.mods.isRightButtonDown()) + ev.xcrossing.state |= Button3Mask; + else if (e.mods.isMiddleButtonDown()) + ev.xcrossing.state |= Button2Mask; } static void translateJuceToXMouseWheelModifiers (const MouseEvent& e, const float increment, XEvent& ev) throw() { - if (increment < 0) - { - ev.xbutton.button = Button5; - ev.xbutton.state |= Button5Mask; - } - else if (increment > 0) - { - ev.xbutton.button = Button4; - ev.xbutton.state |= Button4Mask; - } + if (increment < 0) + { + ev.xbutton.button = Button5; + ev.xbutton.state |= Button5Mask; + } + else if (increment > 0) + { + ev.xbutton.button = Button4; + ev.xbutton.state |= Button4Mask; + } } #endif static VoidArray activeModules; -class ModuleHandle : public ReferenceCountedObject +class ModuleHandle : public ReferenceCountedObject { public: - File file; - MainCall moduleMain; - String pluginName; + File file; + MainCall moduleMain; + String pluginName; - static ModuleHandle* findOrCreateModule (const File& file) - { - for (int i = activeModules.size(); --i >= 0;) - { - ModuleHandle* const module = (ModuleHandle*) activeModules.getUnchecked(i); + static ModuleHandle* findOrCreateModule (const File& file) + { + for (int i = activeModules.size(); --i >= 0;) + { + ModuleHandle* const module = (ModuleHandle*) activeModules.getUnchecked(i); - if (module->file == file) - return module; - } + if (module->file == file) + return module; + } - _fpreset(); // (doesn't do any harm) - ++insideVSTCallback; - shellUIDToCreate = 0; + _fpreset(); // (doesn't do any harm) + ++insideVSTCallback; + shellUIDToCreate = 0; - log ("Attempting to load VST: " + file.getFullPathName()); + log ("Attempting to load VST: " + file.getFullPathName()); - ScopedPointer m (new ModuleHandle (file)); + ScopedPointer m (new ModuleHandle (file)); - if (! m->open()) - m = 0; + if (! m->open()) + m = 0; - --insideVSTCallback; - _fpreset(); // (doesn't do any harm) + --insideVSTCallback; + _fpreset(); // (doesn't do any harm) - return m.release(); - } + return m.release(); + } - ModuleHandle (const File& file_) - : file (file_), - moduleMain (0), + ModuleHandle (const File& file_) + : file (file_), + moduleMain (0), #if JUCE_WIN32 || JUCE_LINUX - hModule (0) + hModule (0) #elif JUCE_MAC - fragId (0), - resHandle (0), - bundleRef (0), - resFileId (0) + fragId (0), + resHandle (0), + bundleRef (0), + resFileId (0) #endif - { - activeModules.add (this); + { + activeModules.add (this); #if JUCE_WIN32 || JUCE_LINUX - fullParentDirectoryPathName = file_.getParentDirectory().getFullPathName(); + fullParentDirectoryPathName = file_.getParentDirectory().getFullPathName(); #elif JUCE_MAC - FSRef ref; - PlatformUtilities::makeFSRefFromPath (&ref, file_.getParentDirectory().getFullPathName()); - FSGetCatalogInfo (&ref, kFSCatInfoNone, 0, 0, &parentDirFSSpec, 0); + FSRef ref; + PlatformUtilities::makeFSRefFromPath (&ref, file_.getParentDirectory().getFullPathName()); + FSGetCatalogInfo (&ref, kFSCatInfoNone, 0, 0, &parentDirFSSpec, 0); #endif - } + } - ~ModuleHandle() - { - activeModules.removeValue (this); + ~ModuleHandle() + { + activeModules.removeValue (this); - close(); - } + close(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator #if JUCE_WIN32 || JUCE_LINUX - void* hModule; - String fullParentDirectoryPathName; + void* hModule; + String fullParentDirectoryPathName; - bool open() - { + bool open() + { #if JUCE_WIN32 - static bool timePeriodSet = false; + static bool timePeriodSet = false; - if (! timePeriodSet) - { - timePeriodSet = true; - timeBeginPeriod (2); - } + if (! timePeriodSet) + { + timePeriodSet = true; + timeBeginPeriod (2); + } #endif - pluginName = file.getFileNameWithoutExtension(); + pluginName = file.getFileNameWithoutExtension(); - hModule = PlatformUtilities::loadDynamicLibrary (file.getFullPathName()); + hModule = PlatformUtilities::loadDynamicLibrary (file.getFullPathName()); - moduleMain = (MainCall) PlatformUtilities::getProcedureEntryPoint (hModule, "VSTPluginMain"); + moduleMain = (MainCall) PlatformUtilities::getProcedureEntryPoint (hModule, "VSTPluginMain"); - if (moduleMain == 0) - moduleMain = (MainCall) PlatformUtilities::getProcedureEntryPoint (hModule, "main"); + if (moduleMain == 0) + moduleMain = (MainCall) PlatformUtilities::getProcedureEntryPoint (hModule, "main"); - return moduleMain != 0; - } + return moduleMain != 0; + } - void close() - { - _fpreset(); // (doesn't do any harm) + void close() + { + _fpreset(); // (doesn't do any harm) - PlatformUtilities::freeDynamicLibrary (hModule); - } + PlatformUtilities::freeDynamicLibrary (hModule); + } - void closeEffect (AEffect* eff) - { - eff->dispatcher (eff, effClose, 0, 0, 0, 0); - } + void closeEffect (AEffect* eff) + { + eff->dispatcher (eff, effClose, 0, 0, 0, 0); + } #else - CFragConnectionID fragId; - Handle resHandle; - CFBundleRef bundleRef; - FSSpec parentDirFSSpec; - short resFileId; + CFragConnectionID fragId; + Handle resHandle; + CFBundleRef bundleRef; + FSSpec parentDirFSSpec; + short resFileId; - bool open() - { - bool ok = false; - const String filename (file.getFullPathName()); + bool open() + { + bool ok = false; + const String filename (file.getFullPathName()); - if (file.hasFileExtension (T(".vst"))) - { - const char* const utf8 = filename.toUTF8(); - CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, - strlen (utf8), file.isDirectory()); + if (file.hasFileExtension (T(".vst"))) + { + const char* const utf8 = filename.toUTF8(); + CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, + strlen (utf8), file.isDirectory()); - if (url != 0) - { - bundleRef = CFBundleCreate (kCFAllocatorDefault, url); - CFRelease (url); + if (url != 0) + { + bundleRef = CFBundleCreate (kCFAllocatorDefault, url); + CFRelease (url); - if (bundleRef != 0) - { - if (CFBundleLoadExecutable (bundleRef)) - { - moduleMain = (MainCall) CFBundleGetFunctionPointerForName (bundleRef, CFSTR("main_macho")); + if (bundleRef != 0) + { + if (CFBundleLoadExecutable (bundleRef)) + { + moduleMain = (MainCall) CFBundleGetFunctionPointerForName (bundleRef, CFSTR("main_macho")); - if (moduleMain == 0) - moduleMain = (MainCall) CFBundleGetFunctionPointerForName (bundleRef, CFSTR("VSTPluginMain")); + if (moduleMain == 0) + moduleMain = (MainCall) CFBundleGetFunctionPointerForName (bundleRef, CFSTR("VSTPluginMain")); - if (moduleMain != 0) - { - CFTypeRef name = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleName")); + if (moduleMain != 0) + { + CFTypeRef name = CFBundleGetValueForInfoDictionaryKey (bundleRef, CFSTR("CFBundleName")); - if (name != 0) - { - if (CFGetTypeID (name) == CFStringGetTypeID()) - { - char buffer[1024]; + if (name != 0) + { + if (CFGetTypeID (name) == CFStringGetTypeID()) + { + char buffer[1024]; - if (CFStringGetCString ((CFStringRef) name, buffer, sizeof (buffer), CFStringGetSystemEncoding())) - pluginName = buffer; - } - } + if (CFStringGetCString ((CFStringRef) name, buffer, sizeof (buffer), CFStringGetSystemEncoding())) + pluginName = buffer; + } + } - if (pluginName.isEmpty()) - pluginName = file.getFileNameWithoutExtension(); + if (pluginName.isEmpty()) + pluginName = file.getFileNameWithoutExtension(); - resFileId = CFBundleOpenBundleResourceMap (bundleRef); + resFileId = CFBundleOpenBundleResourceMap (bundleRef); - ok = true; - } - } + ok = true; + } + } - if (! ok) - { - CFBundleUnloadExecutable (bundleRef); - CFRelease (bundleRef); - bundleRef = 0; - } - } - } - } + if (! ok) + { + CFBundleUnloadExecutable (bundleRef); + CFRelease (bundleRef); + bundleRef = 0; + } + } + } + } #if JUCE_PPC - else - { - FSRef fn; + else + { + FSRef fn; - if (FSPathMakeRef ((UInt8*) (const char*) filename, &fn, 0) == noErr) - { - resFileId = FSOpenResFile (&fn, fsRdPerm); + if (FSPathMakeRef ((UInt8*) (const char*) filename, &fn, 0) == noErr) + { + resFileId = FSOpenResFile (&fn, fsRdPerm); - if (resFileId != -1) - { - const int numEffs = Count1Resources ('aEff'); + if (resFileId != -1) + { + const int numEffs = Count1Resources ('aEff'); - for (int i = 0; i < numEffs; ++i) - { - resHandle = Get1IndResource ('aEff', i + 1); + for (int i = 0; i < numEffs; ++i) + { + resHandle = Get1IndResource ('aEff', i + 1); - if (resHandle != 0) - { - OSType type; - Str255 name; - SInt16 id; - GetResInfo (resHandle, &id, &type, name); - pluginName = String ((const char*) name + 1, name[0]); - DetachResource (resHandle); - HLock (resHandle); + if (resHandle != 0) + { + OSType type; + Str255 name; + SInt16 id; + GetResInfo (resHandle, &id, &type, name); + pluginName = String ((const char*) name + 1, name[0]); + DetachResource (resHandle); + HLock (resHandle); - Ptr ptr; - Str255 errorText; + Ptr ptr; + Str255 errorText; - OSErr err = GetMemFragment (*resHandle, GetHandleSize (resHandle), - name, kPrivateCFragCopy, - &fragId, &ptr, errorText); + OSErr err = GetMemFragment (*resHandle, GetHandleSize (resHandle), + name, kPrivateCFragCopy, + &fragId, &ptr, errorText); - if (err == noErr) - { - moduleMain = (MainCall) newMachOFromCFM (ptr); - ok = true; - } - else - { - HUnlock (resHandle); - } + if (err == noErr) + { + moduleMain = (MainCall) newMachOFromCFM (ptr); + ok = true; + } + else + { + HUnlock (resHandle); + } - break; - } - } + break; + } + } - if (! ok) - CloseResFile (resFileId); - } - } - } + if (! ok) + CloseResFile (resFileId); + } + } + } #endif - return ok; - } + return ok; + } - void close() - { + void close() + { #if JUCE_PPC - if (fragId != 0) - { - if (moduleMain != 0) - disposeMachOFromCFM ((void*) moduleMain); + if (fragId != 0) + { + if (moduleMain != 0) + disposeMachOFromCFM ((void*) moduleMain); - CloseConnection (&fragId); - HUnlock (resHandle); + CloseConnection (&fragId); + HUnlock (resHandle); - if (resFileId != 0) - CloseResFile (resFileId); - } - else + if (resFileId != 0) + CloseResFile (resFileId); + } + else #endif - if (bundleRef != 0) - { - CFBundleCloseBundleResourceMap (bundleRef, resFileId); + if (bundleRef != 0) + { + CFBundleCloseBundleResourceMap (bundleRef, resFileId); - if (CFGetRetainCount (bundleRef) == 1) - CFBundleUnloadExecutable (bundleRef); + if (CFGetRetainCount (bundleRef) == 1) + CFBundleUnloadExecutable (bundleRef); - if (CFGetRetainCount (bundleRef) > 0) - CFRelease (bundleRef); - } - } + if (CFGetRetainCount (bundleRef) > 0) + CFRelease (bundleRef); + } + } - void closeEffect (AEffect* eff) - { + void closeEffect (AEffect* eff) + { #if JUCE_PPC - if (fragId != 0) - { - VoidArray thingsToDelete; - thingsToDelete.add ((void*) eff->dispatcher); - thingsToDelete.add ((void*) eff->process); - thingsToDelete.add ((void*) eff->setParameter); - thingsToDelete.add ((void*) eff->getParameter); - thingsToDelete.add ((void*) eff->processReplacing); + if (fragId != 0) + { + VoidArray thingsToDelete; + thingsToDelete.add ((void*) eff->dispatcher); + thingsToDelete.add ((void*) eff->process); + thingsToDelete.add ((void*) eff->setParameter); + thingsToDelete.add ((void*) eff->getParameter); + thingsToDelete.add ((void*) eff->processReplacing); - eff->dispatcher (eff, effClose, 0, 0, 0, 0); + eff->dispatcher (eff, effClose, 0, 0, 0, 0); - for (int i = thingsToDelete.size(); --i >= 0;) - disposeMachOFromCFM (thingsToDelete[i]); - } - else + for (int i = thingsToDelete.size(); --i >= 0;) + disposeMachOFromCFM (thingsToDelete[i]); + } + else #endif - { - eff->dispatcher (eff, effClose, 0, 0, 0, 0); - } - } + { + eff->dispatcher (eff, effClose, 0, 0, 0, 0); + } + } #if JUCE_PPC - static void* newMachOFromCFM (void* cfmfp) - { - if (cfmfp == 0) - return 0; + static void* newMachOFromCFM (void* cfmfp) + { + if (cfmfp == 0) + return 0; - UInt32* const mfp = (UInt32*) juce_malloc (sizeof (UInt32) * 6); + UInt32* const mfp = (UInt32*) juce_malloc (sizeof (UInt32) * 6); - mfp[0] = 0x3d800000 | ((UInt32) cfmfp >> 16); - mfp[1] = 0x618c0000 | ((UInt32) cfmfp & 0xffff); - mfp[2] = 0x800c0000; - mfp[3] = 0x804c0004; - mfp[4] = 0x7c0903a6; - mfp[5] = 0x4e800420; + mfp[0] = 0x3d800000 | ((UInt32) cfmfp >> 16); + mfp[1] = 0x618c0000 | ((UInt32) cfmfp & 0xffff); + mfp[2] = 0x800c0000; + mfp[3] = 0x804c0004; + mfp[4] = 0x7c0903a6; + mfp[5] = 0x4e800420; - MakeDataExecutable (mfp, sizeof (UInt32) * 6); - return mfp; - } + MakeDataExecutable (mfp, sizeof (UInt32) * 6); + return mfp; + } - static void disposeMachOFromCFM (void* ptr) - { - juce_free (ptr); - } + static void disposeMachOFromCFM (void* ptr) + { + juce_free (ptr); + } - void coerceAEffectFunctionCalls (AEffect* eff) - { - if (fragId != 0) - { - eff->dispatcher = (AEffectDispatcherProc) newMachOFromCFM ((void*) eff->dispatcher); - eff->process = (AEffectProcessProc) newMachOFromCFM ((void*) eff->process); - eff->setParameter = (AEffectSetParameterProc) newMachOFromCFM ((void*) eff->setParameter); - eff->getParameter = (AEffectGetParameterProc) newMachOFromCFM ((void*) eff->getParameter); - eff->processReplacing = (AEffectProcessProc) newMachOFromCFM ((void*) eff->processReplacing); - } - } + void coerceAEffectFunctionCalls (AEffect* eff) + { + if (fragId != 0) + { + eff->dispatcher = (AEffectDispatcherProc) newMachOFromCFM ((void*) eff->dispatcher); + eff->process = (AEffectProcessProc) newMachOFromCFM ((void*) eff->process); + eff->setParameter = (AEffectSetParameterProc) newMachOFromCFM ((void*) eff->setParameter); + eff->getParameter = (AEffectGetParameterProc) newMachOFromCFM ((void*) eff->getParameter); + eff->processReplacing = (AEffectProcessProc) newMachOFromCFM ((void*) eff->processReplacing); + } + } #endif #endif }; -/** - An instance of a plugin, created by a VSTPluginFormat. - -*/ -class VSTPluginInstance : public AudioPluginInstance, - private Timer, - private AsyncUpdater +class VSTPluginInstance : public AudioPluginInstance, + private Timer, + private AsyncUpdater { public: - ~VSTPluginInstance(); + ~VSTPluginInstance(); - // AudioPluginInstance methods: + // AudioPluginInstance methods: - void fillInPluginDescription (PluginDescription& desc) const - { - desc.name = name; - desc.fileOrIdentifier = module->file.getFullPathName(); - desc.uid = getUID(); - desc.lastFileModTime = module->file.getLastModificationTime(); - desc.pluginFormatName = "VST"; - desc.category = getCategory(); + void fillInPluginDescription (PluginDescription& desc) const + { + desc.name = name; + desc.fileOrIdentifier = module->file.getFullPathName(); + desc.uid = getUID(); + desc.lastFileModTime = module->file.getLastModificationTime(); + desc.pluginFormatName = "VST"; + desc.category = getCategory(); - { - char buffer [kVstMaxVendorStrLen + 8]; - zerostruct (buffer); - dispatch (effGetVendorString, 0, 0, buffer, 0); - desc.manufacturerName = buffer; - } + { + char buffer [kVstMaxVendorStrLen + 8]; + zerostruct (buffer); + dispatch (effGetVendorString, 0, 0, buffer, 0); + desc.manufacturerName = buffer; + } - desc.version = getVersion(); - desc.numInputChannels = getNumInputChannels(); - desc.numOutputChannels = getNumOutputChannels(); - desc.isInstrument = (effect != 0 && (effect->flags & effFlagsIsSynth) != 0); - } + desc.version = getVersion(); + desc.numInputChannels = getNumInputChannels(); + desc.numOutputChannels = getNumOutputChannels(); + desc.isInstrument = (effect != 0 && (effect->flags & effFlagsIsSynth) != 0); + } - const String getName() const { return name; } - int getUID() const throw(); - bool acceptsMidi() const { return wantsMidiMessages; } - bool producesMidi() const { return dispatch (effCanDo, 0, 0, (void*) "sendVstMidiEvent", 0) > 0; } + const String getName() const { return name; } + int getUID() const throw(); + bool acceptsMidi() const { return wantsMidiMessages; } + bool producesMidi() const { return dispatch (effCanDo, 0, 0, (void*) "sendVstMidiEvent", 0) > 0; } - // AudioProcessor methods: + // AudioProcessor methods: - void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); - void releaseResources(); - void processBlock (AudioSampleBuffer& buffer, - MidiBuffer& midiMessages); + void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); + void releaseResources(); + void processBlock (AudioSampleBuffer& buffer, + MidiBuffer& midiMessages); - AudioProcessorEditor* createEditor(); + AudioProcessorEditor* createEditor(); - const String getInputChannelName (const int index) const; - bool isInputChannelStereoPair (int index) const; + const String getInputChannelName (const int index) const; + bool isInputChannelStereoPair (int index) const; - const String getOutputChannelName (const int index) const; - bool isOutputChannelStereoPair (int index) const; + const String getOutputChannelName (const int index) const; + bool isOutputChannelStereoPair (int index) const; - int getNumParameters() { return effect != 0 ? effect->numParams : 0; } - float getParameter (int index); - void setParameter (int index, float newValue); - const String getParameterName (int index); - const String getParameterText (int index); - bool isParameterAutomatable (int index) const; + int getNumParameters() { return effect != 0 ? effect->numParams : 0; } + float getParameter (int index); + void setParameter (int index, float newValue); + const String getParameterName (int index); + const String getParameterText (int index); + bool isParameterAutomatable (int index) const; - int getNumPrograms() { return effect != 0 ? effect->numPrograms : 0; } - int getCurrentProgram() { return dispatch (effGetProgram, 0, 0, 0, 0); } - void setCurrentProgram (int index); - const String getProgramName (int index); - void changeProgramName (int index, const String& newName); + int getNumPrograms() { return effect != 0 ? effect->numPrograms : 0; } + int getCurrentProgram() { return dispatch (effGetProgram, 0, 0, 0, 0); } + void setCurrentProgram (int index); + const String getProgramName (int index); + void changeProgramName (int index, const String& newName); - void getStateInformation (MemoryBlock& destData); - void getCurrentProgramStateInformation (MemoryBlock& destData); - void setStateInformation (const void* data, int sizeInBytes); - void setCurrentProgramStateInformation (const void* data, int sizeInBytes); + void getStateInformation (MemoryBlock& destData); + void getCurrentProgramStateInformation (MemoryBlock& destData); + void setStateInformation (const void* data, int sizeInBytes); + void setCurrentProgramStateInformation (const void* data, int sizeInBytes); - void timerCallback(); - void handleAsyncUpdate(); - VstIntPtr handleCallback (VstInt32 opcode, VstInt32 index, VstInt32 value, void *ptr, float opt); + void timerCallback(); + void handleAsyncUpdate(); + VstIntPtr handleCallback (VstInt32 opcode, VstInt32 index, VstInt32 value, void *ptr, float opt); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class VSTPluginWindow; - friend class VSTPluginFormat; + friend class VSTPluginWindow; + friend class VSTPluginFormat; - AEffect* effect; - String name; - CriticalSection lock; - bool wantsMidiMessages, initialised, isPowerOn; - mutable StringArray programNames; - AudioSampleBuffer tempBuffer; - CriticalSection midiInLock; - MidiBuffer incomingMidi; - VSTMidiEventList midiEventsToSend; - VstTimeInfo vstHostTime; - HeapBlock channels; + AEffect* effect; + String name; + CriticalSection lock; + bool wantsMidiMessages, initialised, isPowerOn; + mutable StringArray programNames; + AudioSampleBuffer tempBuffer; + CriticalSection midiInLock; + MidiBuffer incomingMidi; + VSTMidiEventList midiEventsToSend; + VstTimeInfo vstHostTime; + HeapBlock channels; - ReferenceCountedObjectPtr module; + ReferenceCountedObjectPtr module; - int dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) const; - bool restoreProgramSettings (const fxProgram* const prog); - const String getCurrentProgramName(); - void setParamsInProgramBlock (fxProgram* const prog) throw(); - void updateStoredProgramNames(); - void initialise(); - void handleMidiFromPlugin (const VstEvents* const events); - void createTempParameterStore (MemoryBlock& dest); - void restoreFromTempParameterStore (const MemoryBlock& mb); - const String getParameterLabel (int index) const; + int dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) const; + bool restoreProgramSettings (const fxProgram* const prog); + const String getCurrentProgramName(); + void setParamsInProgramBlock (fxProgram* const prog) throw(); + void updateStoredProgramNames(); + void initialise(); + void handleMidiFromPlugin (const VstEvents* const events); + void createTempParameterStore (MemoryBlock& dest); + void restoreFromTempParameterStore (const MemoryBlock& mb); + const String getParameterLabel (int index) const; - bool usesChunks() const throw() { return effect != 0 && (effect->flags & effFlagsProgramChunks) != 0; } - void getChunkData (MemoryBlock& mb, bool isPreset, int maxSizeMB) const; - void setChunkData (const char* data, int size, bool isPreset); - bool loadFromFXBFile (const void* data, int numBytes); - bool saveToFXBFile (MemoryBlock& dest, bool isFXB, int maxSizeMB); + bool usesChunks() const throw() { return effect != 0 && (effect->flags & effFlagsProgramChunks) != 0; } + void getChunkData (MemoryBlock& mb, bool isPreset, int maxSizeMB) const; + void setChunkData (const char* data, int size, bool isPreset); + bool loadFromFXBFile (const void* data, int numBytes); + bool saveToFXBFile (MemoryBlock& dest, bool isFXB, int maxSizeMB); - int getVersionNumber() const throw() { return effect != 0 ? effect->version : 0; } - const String getVersion() const throw(); - const String getCategory() const throw(); + int getVersionNumber() const throw() { return effect != 0 ? effect->version : 0; } + const String getVersion() const throw(); + const String getCategory() const throw(); - bool hasEditor() const throw() { return effect != 0 && (effect->flags & effFlagsHasEditor) != 0; } - void setPower (const bool on); + bool hasEditor() const throw() { return effect != 0 && (effect->flags & effFlagsHasEditor) != 0; } + void setPower (const bool on); - VSTPluginInstance (const ReferenceCountedObjectPtr & module); + VSTPluginInstance (const ReferenceCountedObjectPtr & module); }; VSTPluginInstance::VSTPluginInstance (const ReferenceCountedObjectPtr & module_) - : effect (0), - wantsMidiMessages (false), - initialised (false), - isPowerOn (false), - tempBuffer (1, 1), - module (module_) + : effect (0), + wantsMidiMessages (false), + initialised (false), + isPowerOn (false), + tempBuffer (1, 1), + module (module_) { - try - { - _fpreset(); + try + { + _fpreset(); - ++insideVSTCallback; + ++insideVSTCallback; - name = module->pluginName; - log (T("Creating VST instance: ") + name); + name = module->pluginName; + log (T("Creating VST instance: ") + name); #if JUCE_MAC - if (module->resFileId != 0) - UseResFile (module->resFileId); + if (module->resFileId != 0) + UseResFile (module->resFileId); #if JUCE_PPC - if (module->fragId != 0) - { - static void* audioMasterCoerced = 0; - if (audioMasterCoerced == 0) - audioMasterCoerced = NewCFMFromMachO ((void*) &audioMaster); + if (module->fragId != 0) + { + static void* audioMasterCoerced = 0; + if (audioMasterCoerced == 0) + audioMasterCoerced = NewCFMFromMachO ((void*) &audioMaster); - effect = module->moduleMain ((audioMasterCallback) audioMasterCoerced); - } - else + effect = module->moduleMain ((audioMasterCallback) audioMasterCoerced); + } + else #endif #endif - { - effect = module->moduleMain (&audioMaster); - } + { + effect = module->moduleMain (&audioMaster); + } - --insideVSTCallback; + --insideVSTCallback; - if (effect != 0 && effect->magic == kEffectMagic) - { + if (effect != 0 && effect->magic == kEffectMagic) + { #if JUCE_PPC - module->coerceAEffectFunctionCalls (effect); + module->coerceAEffectFunctionCalls (effect); #endif - jassert (effect->resvd2 == 0); - jassert (effect->object != 0); + jassert (effect->resvd2 == 0); + jassert (effect->object != 0); - _fpreset(); // some dodgy plugs fuck around with this - } - else - { - effect = 0; - } - } - catch (...) - { - --insideVSTCallback; - } + _fpreset(); // some dodgy plugs fuck around with this + } + else + { + effect = 0; + } + } + catch (...) + { + --insideVSTCallback; + } } VSTPluginInstance::~VSTPluginInstance() { - { - const ScopedLock sl (lock); + { + const ScopedLock sl (lock); - jassert (insideVSTCallback == 0); + jassert (insideVSTCallback == 0); - if (effect != 0 && effect->magic == kEffectMagic) - { - try - { + if (effect != 0 && effect->magic == kEffectMagic) + { + try + { #if JUCE_MAC - if (module->resFileId != 0) - UseResFile (module->resFileId); + if (module->resFileId != 0) + UseResFile (module->resFileId); #endif - // Must delete any editors before deleting the plugin instance! - jassert (getActiveEditor() == 0); + // Must delete any editors before deleting the plugin instance! + jassert (getActiveEditor() == 0); - _fpreset(); // some dodgy plugs fuck around with this + _fpreset(); // some dodgy plugs fuck around with this - module->closeEffect (effect); - } - catch (...) - {} - } + module->closeEffect (effect); + } + catch (...) + {} + } - module = 0; - effect = 0; - } + module = 0; + effect = 0; + } } void VSTPluginInstance::initialise() { - if (initialised || effect == 0) - return; + if (initialised || effect == 0) + return; - log (T("Initialising VST: ") + module->pluginName); - initialised = true; + log (T("Initialising VST: ") + module->pluginName); + initialised = true; - dispatch (effIdentify, 0, 0, 0, 0); + dispatch (effIdentify, 0, 0, 0, 0); - // this code would ask the plugin for its name, but so few plugins - // actually bother implementing this correctly, that it's better to - // just ignore it and use the file name instead. -/* { - char buffer [256]; - zerostruct (buffer); - dispatch (effGetEffectName, 0, 0, buffer, 0); + // this code would ask the plugin for its name, but so few plugins + // actually bother implementing this correctly, that it's better to + // just ignore it and use the file name instead. - name = String (buffer).trim(); - if (name.isEmpty()) - name = module->pluginName; - } -*/ + if (getSampleRate() > 0) + dispatch (effSetSampleRate, 0, 0, 0, (float) getSampleRate()); - if (getSampleRate() > 0) - dispatch (effSetSampleRate, 0, 0, 0, (float) getSampleRate()); + if (getBlockSize() > 0) + dispatch (effSetBlockSize, 0, jmax (32, getBlockSize()), 0, 0); - if (getBlockSize() > 0) - dispatch (effSetBlockSize, 0, jmax (32, getBlockSize()), 0, 0); + dispatch (effOpen, 0, 0, 0, 0); - dispatch (effOpen, 0, 0, 0, 0); + setPlayConfigDetails (effect->numInputs, effect->numOutputs, + getSampleRate(), getBlockSize()); - setPlayConfigDetails (effect->numInputs, effect->numOutputs, - getSampleRate(), getBlockSize()); + if (getNumPrograms() > 1) + setCurrentProgram (0); + else + dispatch (effSetProgram, 0, 0, 0, 0); - if (getNumPrograms() > 1) - setCurrentProgram (0); - else - dispatch (effSetProgram, 0, 0, 0, 0); + int i; + for (i = effect->numInputs; --i >= 0;) + dispatch (effConnectInput, i, 1, 0, 0); - int i; - for (i = effect->numInputs; --i >= 0;) - dispatch (effConnectInput, i, 1, 0, 0); + for (i = effect->numOutputs; --i >= 0;) + dispatch (effConnectOutput, i, 1, 0, 0); - for (i = effect->numOutputs; --i >= 0;) - dispatch (effConnectOutput, i, 1, 0, 0); + updateStoredProgramNames(); - updateStoredProgramNames(); + wantsMidiMessages = dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0; - wantsMidiMessages = dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0; - - setLatencySamples (effect->initialDelay); + setLatencySamples (effect->initialDelay); } void VSTPluginInstance::prepareToPlay (double sampleRate_, - int samplesPerBlockExpected) + int samplesPerBlockExpected) { - setPlayConfigDetails (effect->numInputs, effect->numOutputs, - sampleRate_, samplesPerBlockExpected); + setPlayConfigDetails (effect->numInputs, effect->numOutputs, + sampleRate_, samplesPerBlockExpected); - setLatencySamples (effect->initialDelay); + setLatencySamples (effect->initialDelay); - channels.calloc (jmax (16, getNumOutputChannels(), getNumInputChannels()) + 2); + channels.calloc (jmax (16, getNumOutputChannels(), getNumInputChannels()) + 2); - vstHostTime.tempo = 120.0; - vstHostTime.timeSigNumerator = 4; - vstHostTime.timeSigDenominator = 4; - vstHostTime.sampleRate = sampleRate_; - vstHostTime.samplePos = 0; - vstHostTime.flags = kVstNanosValid; /*| kVstTransportPlaying | kVstTempoValid | kVstTimeSigValid*/; + vstHostTime.tempo = 120.0; + vstHostTime.timeSigNumerator = 4; + vstHostTime.timeSigDenominator = 4; + vstHostTime.sampleRate = sampleRate_; + vstHostTime.samplePos = 0; + vstHostTime.flags = kVstNanosValid; /*| kVstTransportPlaying | kVstTempoValid | kVstTimeSigValid*/; - initialise(); + initialise(); - if (initialised) - { - wantsMidiMessages = wantsMidiMessages - || (dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0); + if (initialised) + { + wantsMidiMessages = wantsMidiMessages + || (dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0); - if (wantsMidiMessages) - midiEventsToSend.ensureSize (256); - else - midiEventsToSend.freeEvents(); + if (wantsMidiMessages) + midiEventsToSend.ensureSize (256); + else + midiEventsToSend.freeEvents(); - incomingMidi.clear(); + incomingMidi.clear(); - dispatch (effSetSampleRate, 0, 0, 0, (float) sampleRate_); - dispatch (effSetBlockSize, 0, jmax (16, samplesPerBlockExpected), 0, 0); + dispatch (effSetSampleRate, 0, 0, 0, (float) sampleRate_); + dispatch (effSetBlockSize, 0, jmax (16, samplesPerBlockExpected), 0, 0); - tempBuffer.setSize (jmax (1, effect->numOutputs), samplesPerBlockExpected); + tempBuffer.setSize (jmax (1, effect->numOutputs), samplesPerBlockExpected); - if (! isPowerOn) - setPower (true); + if (! isPowerOn) + setPower (true); - // dodgy hack to force some plugins to initialise the sample rate.. - if ((! hasEditor()) && getNumParameters() > 0) - { - const float old = getParameter (0); - setParameter (0, (old < 0.5f) ? 1.0f : 0.0f); - setParameter (0, old); - } + // dodgy hack to force some plugins to initialise the sample rate.. + if ((! hasEditor()) && getNumParameters() > 0) + { + const float old = getParameter (0); + setParameter (0, (old < 0.5f) ? 1.0f : 0.0f); + setParameter (0, old); + } - dispatch (effStartProcess, 0, 0, 0, 0); - } + dispatch (effStartProcess, 0, 0, 0, 0); + } } void VSTPluginInstance::releaseResources() { - if (initialised) - { - dispatch (effStopProcess, 0, 0, 0, 0); - setPower (false); - } + if (initialised) + { + dispatch (effStopProcess, 0, 0, 0, 0); + setPower (false); + } - tempBuffer.setSize (1, 1); - incomingMidi.clear(); + tempBuffer.setSize (1, 1); + incomingMidi.clear(); - midiEventsToSend.freeEvents(); - channels.free(); + midiEventsToSend.freeEvents(); + channels.free(); } void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, - MidiBuffer& midiMessages) + MidiBuffer& midiMessages) { - const int numSamples = buffer.getNumSamples(); + const int numSamples = buffer.getNumSamples(); - if (initialised) - { - AudioPlayHead* playHead = getPlayHead(); + if (initialised) + { + AudioPlayHead* playHead = getPlayHead(); - if (playHead != 0) - { - AudioPlayHead::CurrentPositionInfo position; - playHead->getCurrentPosition (position); + if (playHead != 0) + { + AudioPlayHead::CurrentPositionInfo position; + playHead->getCurrentPosition (position); - vstHostTime.tempo = position.bpm; - vstHostTime.timeSigNumerator = position.timeSigNumerator; - vstHostTime.timeSigDenominator = position.timeSigDenominator; - vstHostTime.ppqPos = position.ppqPosition; - vstHostTime.barStartPos = position.ppqPositionOfLastBarStart; - vstHostTime.flags |= kVstTempoValid | kVstTimeSigValid | kVstPpqPosValid | kVstBarsValid; + vstHostTime.tempo = position.bpm; + vstHostTime.timeSigNumerator = position.timeSigNumerator; + vstHostTime.timeSigDenominator = position.timeSigDenominator; + vstHostTime.ppqPos = position.ppqPosition; + vstHostTime.barStartPos = position.ppqPositionOfLastBarStart; + vstHostTime.flags |= kVstTempoValid | kVstTimeSigValid | kVstPpqPosValid | kVstBarsValid; - if (position.isPlaying) - vstHostTime.flags |= kVstTransportPlaying; - else - vstHostTime.flags &= ~kVstTransportPlaying; - } + if (position.isPlaying) + vstHostTime.flags |= kVstTransportPlaying; + else + vstHostTime.flags &= ~kVstTransportPlaying; + } #if JUCE_WIN32 - vstHostTime.nanoSeconds = timeGetTime() * 1000000.0; + vstHostTime.nanoSeconds = timeGetTime() * 1000000.0; #elif JUCE_LINUX - timeval micro; - gettimeofday (µ, 0); - vstHostTime.nanoSeconds = micro.tv_usec * 1000.0; + timeval micro; + gettimeofday (µ, 0); + vstHostTime.nanoSeconds = micro.tv_usec * 1000.0; #elif JUCE_MAC - UnsignedWide micro; - Microseconds (µ); - vstHostTime.nanoSeconds = micro.lo * 1000.0; + UnsignedWide micro; + Microseconds (µ); + vstHostTime.nanoSeconds = micro.lo * 1000.0; #endif - if (wantsMidiMessages) - { - midiEventsToSend.clear(); - midiEventsToSend.ensureSize (1); + if (wantsMidiMessages) + { + midiEventsToSend.clear(); + midiEventsToSend.ensureSize (1); - MidiBuffer::Iterator iter (midiMessages); - const uint8* midiData; - int numBytesOfMidiData, samplePosition; + MidiBuffer::Iterator iter (midiMessages); + const uint8* midiData; + int numBytesOfMidiData, samplePosition; - while (iter.getNextEvent (midiData, numBytesOfMidiData, samplePosition)) - { - midiEventsToSend.addEvent (midiData, numBytesOfMidiData, - jlimit (0, numSamples - 1, samplePosition)); - } + while (iter.getNextEvent (midiData, numBytesOfMidiData, samplePosition)) + { + midiEventsToSend.addEvent (midiData, numBytesOfMidiData, + jlimit (0, numSamples - 1, samplePosition)); + } - try - { - effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend.events, 0); - } - catch (...) - {} - } + try + { + effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend.events, 0); + } + catch (...) + {} + } - int i; - const int maxChans = jmax (effect->numInputs, effect->numOutputs); + int i; + const int maxChans = jmax (effect->numInputs, effect->numOutputs); - for (i = 0; i < maxChans; ++i) - channels[i] = buffer.getSampleData (i); + for (i = 0; i < maxChans; ++i) + channels[i] = buffer.getSampleData (i); - channels [maxChans] = 0; + channels [maxChans] = 0; - _clearfp(); + _clearfp(); - if ((effect->flags & effFlagsCanReplacing) != 0) - { - try - { - effect->processReplacing (effect, channels, channels, numSamples); - } - catch (...) - {} - } - else - { - tempBuffer.setSize (effect->numOutputs, numSamples); - tempBuffer.clear(); + if ((effect->flags & effFlagsCanReplacing) != 0) + { + try + { + effect->processReplacing (effect, channels, channels, numSamples); + } + catch (...) + {} + } + else + { + tempBuffer.setSize (effect->numOutputs, numSamples); + tempBuffer.clear(); - float* outs [64]; + float* outs [64]; - for (i = effect->numOutputs; --i >= 0;) - outs[i] = tempBuffer.getSampleData (i); + for (i = effect->numOutputs; --i >= 0;) + outs[i] = tempBuffer.getSampleData (i); - outs [effect->numOutputs] = 0; + outs [effect->numOutputs] = 0; - try - { - effect->process (effect, channels, outs, numSamples); - } - catch (...) - {} + try + { + effect->process (effect, channels, outs, numSamples); + } + catch (...) + {} - for (i = effect->numOutputs; --i >= 0;) - buffer.copyFrom (i, 0, outs[i], numSamples); - } - } - else - { - // Not initialised, so just bypass.. - for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i) - buffer.clear (i, 0, buffer.getNumSamples()); - } + for (i = effect->numOutputs; --i >= 0;) + buffer.copyFrom (i, 0, outs[i], numSamples); + } + } + else + { + // Not initialised, so just bypass.. + for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i) + buffer.clear (i, 0, buffer.getNumSamples()); + } - { - // copy any incoming midi.. - const ScopedLock sl (midiInLock); + { + // copy any incoming midi.. + const ScopedLock sl (midiInLock); - midiMessages = incomingMidi; - incomingMidi.clear(); - } + midiMessages = incomingMidi; + incomingMidi.clear(); + } } void VSTPluginInstance::handleMidiFromPlugin (const VstEvents* const events) { - if (events != 0) - { - const ScopedLock sl (midiInLock); - VSTMidiEventList::addEventsToMidiBuffer (events, incomingMidi); - } + if (events != 0) + { + const ScopedLock sl (midiInLock); + VSTMidiEventList::addEventsToMidiBuffer (events, incomingMidi); + } } static Array activeVSTWindows; class VSTPluginWindow : public AudioProcessorEditor, - #if ! JUCE_MAC - public ComponentMovementWatcher, - #endif - public Timer + #if ! JUCE_MAC + public ComponentMovementWatcher, + #endif + public Timer { public: - VSTPluginWindow (VSTPluginInstance& plugin_) - : AudioProcessorEditor (&plugin_), + VSTPluginWindow (VSTPluginInstance& plugin_) + : AudioProcessorEditor (&plugin_), #if ! JUCE_MAC - ComponentMovementWatcher (this), + ComponentMovementWatcher (this), #endif - plugin (plugin_), - isOpen (false), - wasShowing (false), - pluginRefusesToResize (false), - pluginWantsKeys (false), - alreadyInside (false), - recursiveResize (false) - { + plugin (plugin_), + isOpen (false), + wasShowing (false), + pluginRefusesToResize (false), + pluginWantsKeys (false), + alreadyInside (false), + recursiveResize (false) + { #if JUCE_WIN32 - sizeCheckCount = 0; - pluginHWND = 0; + sizeCheckCount = 0; + pluginHWND = 0; #elif JUCE_LINUX - pluginWindow = None; - pluginProc = None; + pluginWindow = None; + pluginProc = None; #else - addAndMakeVisible (innerWrapper = new InnerWrapperComponent (this)); + addAndMakeVisible (innerWrapper = new InnerWrapperComponent (this)); #endif - activeVSTWindows.add (this); + activeVSTWindows.add (this); - setSize (1, 1); - setOpaque (true); - setVisible (true); - } + setSize (1, 1); + setOpaque (true); + setVisible (true); + } - ~VSTPluginWindow() - { + ~VSTPluginWindow() + { #if JUCE_MAC - innerWrapper = 0; + innerWrapper = 0; #else - closePluginWindow(); + closePluginWindow(); #endif - activeVSTWindows.removeValue (this); - plugin.editorBeingDeleted (this); - } + activeVSTWindows.removeValue (this); + plugin.editorBeingDeleted (this); + } #if ! JUCE_MAC - void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) - { - if (recursiveResize) - return; + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) + { + if (recursiveResize) + return; - Component* const topComp = getTopLevelComponent(); + Component* const topComp = getTopLevelComponent(); - if (topComp->getPeer() != 0) - { - int x = 0, y = 0; - relativePositionToOtherComponent (topComp, x, y); + if (topComp->getPeer() != 0) + { + int x = 0, y = 0; + relativePositionToOtherComponent (topComp, x, y); - recursiveResize = true; + recursiveResize = true; #if JUCE_WIN32 - if (pluginHWND != 0) - MoveWindow (pluginHWND, x, y, getWidth(), getHeight(), TRUE); + if (pluginHWND != 0) + MoveWindow (pluginHWND, x, y, getWidth(), getHeight(), TRUE); #elif JUCE_LINUX - if (pluginWindow != 0) - { - XResizeWindow (display, pluginWindow, getWidth(), getHeight()); - XMoveWindow (display, pluginWindow, x, y); - XMapRaised (display, pluginWindow); - } + if (pluginWindow != 0) + { + XResizeWindow (display, pluginWindow, getWidth(), getHeight()); + XMoveWindow (display, pluginWindow, x, y); + XMapRaised (display, pluginWindow); + } #endif - recursiveResize = false; - } - } + recursiveResize = false; + } + } - void componentVisibilityChanged (Component&) - { - const bool isShowingNow = isShowing(); + void componentVisibilityChanged (Component&) + { + const bool isShowingNow = isShowing(); - if (wasShowing != isShowingNow) - { - wasShowing = isShowingNow; + if (wasShowing != isShowingNow) + { + wasShowing = isShowingNow; - if (isShowingNow) - openPluginWindow(); - else - closePluginWindow(); - } + if (isShowingNow) + openPluginWindow(); + else + closePluginWindow(); + } - componentMovedOrResized (true, true); - } + componentMovedOrResized (true, true); + } - void componentPeerChanged() - { - closePluginWindow(); - openPluginWindow(); - } + void componentPeerChanged() + { + closePluginWindow(); + openPluginWindow(); + } #endif - bool keyStateChanged (const bool) - { - return pluginWantsKeys; - } + bool keyStateChanged (const bool) + { + return pluginWantsKeys; + } - bool keyPressed (const KeyPress&) - { - return pluginWantsKeys; - } + bool keyPressed (const KeyPress&) + { + return pluginWantsKeys; + } #if JUCE_MAC - void paint (Graphics& g) - { - g.fillAll (Colours::black); - } + void paint (Graphics& g) + { + g.fillAll (Colours::black); + } #else - void paint (Graphics& g) - { - if (isOpen) - { - ComponentPeer* const peer = getPeer(); + void paint (Graphics& g) + { + if (isOpen) + { + ComponentPeer* const peer = getPeer(); - if (peer != 0) - { - peer->addMaskedRegion (getScreenX() - peer->getScreenX(), - getScreenY() - peer->getScreenY(), - getWidth(), getHeight()); + if (peer != 0) + { + peer->addMaskedRegion (getScreenX() - peer->getScreenX(), + getScreenY() - peer->getScreenY(), + getWidth(), getHeight()); #if JUCE_LINUX - if (pluginWindow != 0) - { - const Rectangle clip (g.getClipBounds()); + if (pluginWindow != 0) + { + const Rectangle clip (g.getClipBounds()); - XEvent ev; - zerostruct (ev); - ev.xexpose.type = Expose; - ev.xexpose.display = display; - ev.xexpose.window = pluginWindow; - ev.xexpose.x = clip.getX(); - ev.xexpose.y = clip.getY(); - ev.xexpose.width = clip.getWidth(); - ev.xexpose.height = clip.getHeight(); + XEvent ev; + zerostruct (ev); + ev.xexpose.type = Expose; + ev.xexpose.display = display; + ev.xexpose.window = pluginWindow; + ev.xexpose.x = clip.getX(); + ev.xexpose.y = clip.getY(); + ev.xexpose.width = clip.getWidth(); + ev.xexpose.height = clip.getHeight(); - sendEventToChild (&ev); - } + sendEventToChild (&ev); + } #endif - } - } - else - { - g.fillAll (Colours::black); - } - } + } + } + else + { + g.fillAll (Colours::black); + } + } #endif - void timerCallback() - { + void timerCallback() + { #if JUCE_WIN32 - if (--sizeCheckCount <= 0) - { - sizeCheckCount = 10; + if (--sizeCheckCount <= 0) + { + sizeCheckCount = 10; - checkPluginWindowSize(); - } + checkPluginWindowSize(); + } #endif - try - { - static bool reentrant = false; + try + { + static bool reentrant = false; - if (! reentrant) - { - reentrant = true; - plugin.dispatch (effEditIdle, 0, 0, 0, 0); - reentrant = false; - } - } - catch (...) - {} - } + if (! reentrant) + { + reentrant = true; + plugin.dispatch (effEditIdle, 0, 0, 0, 0); + reentrant = false; + } + } + catch (...) + {} + } - void mouseDown (const MouseEvent& e) - { + void mouseDown (const MouseEvent& e) + { #if JUCE_LINUX - if (pluginWindow == 0) - return; + if (pluginWindow == 0) + return; - toFront (true); + toFront (true); - XEvent ev; - zerostruct (ev); - ev.xbutton.display = display; - ev.xbutton.type = ButtonPress; - ev.xbutton.window = pluginWindow; - ev.xbutton.root = RootWindow (display, DefaultScreen (display)); - ev.xbutton.time = CurrentTime; - ev.xbutton.x = e.x; - ev.xbutton.y = e.y; - ev.xbutton.x_root = e.getScreenX(); - ev.xbutton.y_root = e.getScreenY(); + XEvent ev; + zerostruct (ev); + ev.xbutton.display = display; + ev.xbutton.type = ButtonPress; + ev.xbutton.window = pluginWindow; + ev.xbutton.root = RootWindow (display, DefaultScreen (display)); + ev.xbutton.time = CurrentTime; + ev.xbutton.x = e.x; + ev.xbutton.y = e.y; + ev.xbutton.x_root = e.getScreenX(); + ev.xbutton.y_root = e.getScreenY(); - translateJuceToXButtonModifiers (e, ev); + translateJuceToXButtonModifiers (e, ev); - sendEventToChild (&ev); + sendEventToChild (&ev); #elif JUCE_WIN32 - (void) e; + (void) e; - toFront (true); + toFront (true); #endif - } + } - void broughtToFront() - { - activeVSTWindows.removeValue (this); - activeVSTWindows.add (this); + void broughtToFront() + { + activeVSTWindows.removeValue (this); + activeVSTWindows.add (this); #if JUCE_MAC - dispatch (effEditTop, 0, 0, 0, 0); + dispatch (effEditTop, 0, 0, 0, 0); #endif - } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - VSTPluginInstance& plugin; - bool isOpen, wasShowing, recursiveResize; - bool pluginWantsKeys, pluginRefusesToResize, alreadyInside; + VSTPluginInstance& plugin; + bool isOpen, wasShowing, recursiveResize; + bool pluginWantsKeys, pluginRefusesToResize, alreadyInside; #if JUCE_WIN32 - HWND pluginHWND; - void* originalWndProc; - int sizeCheckCount; + HWND pluginHWND; + void* originalWndProc; + int sizeCheckCount; #elif JUCE_LINUX - Window pluginWindow; - EventProcPtr pluginProc; + Window pluginWindow; + EventProcPtr pluginProc; #endif #if JUCE_MAC - void openPluginWindow (WindowRef parentWindow) - { - if (isOpen || parentWindow == 0) - return; + void openPluginWindow (WindowRef parentWindow) + { + if (isOpen || parentWindow == 0) + return; - isOpen = true; + isOpen = true; - ERect* rect = 0; - dispatch (effEditGetRect, 0, 0, &rect, 0); - dispatch (effEditOpen, 0, 0, parentWindow, 0); + ERect* rect = 0; + dispatch (effEditGetRect, 0, 0, &rect, 0); + dispatch (effEditOpen, 0, 0, parentWindow, 0); - // do this before and after like in the steinberg example - dispatch (effEditGetRect, 0, 0, &rect, 0); - dispatch (effGetProgram, 0, 0, 0, 0); // also in steinberg code + // do this before and after like in the steinberg example + dispatch (effEditGetRect, 0, 0, &rect, 0); + dispatch (effGetProgram, 0, 0, 0, 0); // also in steinberg code - // Install keyboard hooks - pluginWantsKeys = (dispatch (effKeysRequired, 0, 0, 0, 0) == 0); + // Install keyboard hooks + pluginWantsKeys = (dispatch (effKeysRequired, 0, 0, 0, 0) == 0); - // double-check it's not too tiny - int w = 250, h = 150; + // double-check it's not too tiny + int w = 250, h = 150; - if (rect != 0) - { - w = rect->right - rect->left; - h = rect->bottom - rect->top; + if (rect != 0) + { + w = rect->right - rect->left; + h = rect->bottom - rect->top; - if (w == 0 || h == 0) - { - w = 250; - h = 150; - } - } + if (w == 0 || h == 0) + { + w = 250; + h = 150; + } + } - w = jmax (w, 32); - h = jmax (h, 32); + w = jmax (w, 32); + h = jmax (h, 32); - setSize (w, h); + setSize (w, h); - startTimer (18 + JUCE_NAMESPACE::Random::getSystemRandom().nextInt (5)); - repaint(); - } + startTimer (18 + JUCE_NAMESPACE::Random::getSystemRandom().nextInt (5)); + repaint(); + } #else - void openPluginWindow() - { - if (isOpen || getWindowHandle() == 0) - return; + void openPluginWindow() + { + if (isOpen || getWindowHandle() == 0) + return; - log (T("Opening VST UI: ") + plugin.name); - isOpen = true; + log (T("Opening VST UI: ") + plugin.name); + isOpen = true; - ERect* rect = 0; - dispatch (effEditGetRect, 0, 0, &rect, 0); - dispatch (effEditOpen, 0, 0, getWindowHandle(), 0); + ERect* rect = 0; + dispatch (effEditGetRect, 0, 0, &rect, 0); + dispatch (effEditOpen, 0, 0, getWindowHandle(), 0); - // do this before and after like in the steinberg example - dispatch (effEditGetRect, 0, 0, &rect, 0); - dispatch (effGetProgram, 0, 0, 0, 0); // also in steinberg code + // do this before and after like in the steinberg example + dispatch (effEditGetRect, 0, 0, &rect, 0); + dispatch (effGetProgram, 0, 0, 0, 0); // also in steinberg code - // Install keyboard hooks - pluginWantsKeys = (dispatch (effKeysRequired, 0, 0, 0, 0) == 0); + // Install keyboard hooks + pluginWantsKeys = (dispatch (effKeysRequired, 0, 0, 0, 0) == 0); #if JUCE_WIN32 - originalWndProc = 0; - pluginHWND = GetWindow ((HWND) getWindowHandle(), GW_CHILD); + originalWndProc = 0; + pluginHWND = GetWindow ((HWND) getWindowHandle(), GW_CHILD); - if (pluginHWND == 0) - { - isOpen = false; - setSize (300, 150); - return; - } + if (pluginHWND == 0) + { + isOpen = false; + setSize (300, 150); + return; + } - #pragma warning (push) - #pragma warning (disable: 4244) + #pragma warning (push) + #pragma warning (disable: 4244) - originalWndProc = (void*) GetWindowLongPtr (pluginHWND, GWL_WNDPROC); + originalWndProc = (void*) GetWindowLongPtr (pluginHWND, GWL_WNDPROC); - if (! pluginWantsKeys) - SetWindowLongPtr (pluginHWND, GWL_WNDPROC, (LONG_PTR) vstHookWndProc); + if (! pluginWantsKeys) + SetWindowLongPtr (pluginHWND, GWL_WNDPROC, (LONG_PTR) vstHookWndProc); - #pragma warning (pop) + #pragma warning (pop) - int w, h; - RECT r; - GetWindowRect (pluginHWND, &r); - w = r.right - r.left; - h = r.bottom - r.top; + int w, h; + RECT r; + GetWindowRect (pluginHWND, &r); + w = r.right - r.left; + h = r.bottom - r.top; - if (rect != 0) - { - const int rw = rect->right - rect->left; - const int rh = rect->bottom - rect->top; + if (rect != 0) + { + const int rw = rect->right - rect->left; + const int rh = rect->bottom - rect->top; - if ((rw > 50 && rh > 50 && rw < 2000 && rh < 2000 && rw != w && rh != h) - || ((w == 0 && rw > 0) || (h == 0 && rh > 0))) - { - // very dodgy logic to decide which size is right. - if (abs (rw - w) > 350 || abs (rh - h) > 350) - { - SetWindowPos (pluginHWND, 0, - 0, 0, rw, rh, - SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); + if ((rw > 50 && rh > 50 && rw < 2000 && rh < 2000 && rw != w && rh != h) + || ((w == 0 && rw > 0) || (h == 0 && rh > 0))) + { + // very dodgy logic to decide which size is right. + if (abs (rw - w) > 350 || abs (rh - h) > 350) + { + SetWindowPos (pluginHWND, 0, + 0, 0, rw, rh, + SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); - GetWindowRect (pluginHWND, &r); + GetWindowRect (pluginHWND, &r); - w = r.right - r.left; - h = r.bottom - r.top; + w = r.right - r.left; + h = r.bottom - r.top; - pluginRefusesToResize = (w != rw) || (h != rh); + pluginRefusesToResize = (w != rw) || (h != rh); - w = rw; - h = rh; - } - } - } + w = rw; + h = rh; + } + } + } #elif JUCE_LINUX - pluginWindow = getChildWindow ((Window) getWindowHandle()); + pluginWindow = getChildWindow ((Window) getWindowHandle()); - if (pluginWindow != 0) - pluginProc = (EventProcPtr) getPropertyFromXWindow (pluginWindow, - XInternAtom (display, "_XEventProc", False)); + if (pluginWindow != 0) + pluginProc = (EventProcPtr) getPropertyFromXWindow (pluginWindow, + XInternAtom (display, "_XEventProc", False)); - int w = 250, h = 150; + int w = 250, h = 150; - if (rect != 0) - { - w = rect->right - rect->left; - h = rect->bottom - rect->top; + if (rect != 0) + { + w = rect->right - rect->left; + h = rect->bottom - rect->top; - if (w == 0 || h == 0) - { - w = 250; - h = 150; - } - } + if (w == 0 || h == 0) + { + w = 250; + h = 150; + } + } - if (pluginWindow != 0) - XMapRaised (display, pluginWindow); + if (pluginWindow != 0) + XMapRaised (display, pluginWindow); #endif - // double-check it's not too tiny - w = jmax (w, 32); - h = jmax (h, 32); + // double-check it's not too tiny + w = jmax (w, 32); + h = jmax (h, 32); - setSize (w, h); + setSize (w, h); #if JUCE_WIN32 - checkPluginWindowSize(); + checkPluginWindowSize(); #endif - startTimer (18 + JUCE_NAMESPACE::Random::getSystemRandom().nextInt (5)); - repaint(); - } + startTimer (18 + JUCE_NAMESPACE::Random::getSystemRandom().nextInt (5)); + repaint(); + } #endif #if ! JUCE_MAC - void closePluginWindow() - { - if (isOpen) - { - log (T("Closing VST UI: ") + plugin.getName()); - isOpen = false; + void closePluginWindow() + { + if (isOpen) + { + log (T("Closing VST UI: ") + plugin.getName()); + isOpen = false; - dispatch (effEditClose, 0, 0, 0, 0); + dispatch (effEditClose, 0, 0, 0, 0); #if JUCE_WIN32 - #pragma warning (push) - #pragma warning (disable: 4244) + #pragma warning (push) + #pragma warning (disable: 4244) - if (pluginHWND != 0 && IsWindow (pluginHWND)) - SetWindowLongPtr (pluginHWND, GWL_WNDPROC, (LONG_PTR) originalWndProc); + if (pluginHWND != 0 && IsWindow (pluginHWND)) + SetWindowLongPtr (pluginHWND, GWL_WNDPROC, (LONG_PTR) originalWndProc); - #pragma warning (pop) + #pragma warning (pop) - stopTimer(); + stopTimer(); - if (pluginHWND != 0 && IsWindow (pluginHWND)) - DestroyWindow (pluginHWND); + if (pluginHWND != 0 && IsWindow (pluginHWND)) + DestroyWindow (pluginHWND); - pluginHWND = 0; + pluginHWND = 0; #elif JUCE_LINUX - stopTimer(); - pluginWindow = 0; - pluginProc = 0; + stopTimer(); + pluginWindow = 0; + pluginProc = 0; #endif - } - } + } + } #endif - int dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) - { - return plugin.dispatch (opcode, index, value, ptr, opt); - } + int dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) + { + return plugin.dispatch (opcode, index, value, ptr, opt); + } #if JUCE_WIN32 - void checkPluginWindowSize() throw() - { - RECT r; - GetWindowRect (pluginHWND, &r); - const int w = r.right - r.left; - const int h = r.bottom - r.top; + void checkPluginWindowSize() throw() + { + RECT r; + GetWindowRect (pluginHWND, &r); + const int w = r.right - r.left; + const int h = r.bottom - r.top; - if (isShowing() && w > 0 && h > 0 - && (w != getWidth() || h != getHeight()) - && ! pluginRefusesToResize) - { - setSize (w, h); - sizeCheckCount = 0; - } - } + if (isShowing() && w > 0 && h > 0 + && (w != getWidth() || h != getHeight()) + && ! pluginRefusesToResize) + { + setSize (w, h); + sizeCheckCount = 0; + } + } - // hooks to get keyboard events from VST windows.. - static LRESULT CALLBACK vstHookWndProc (HWND hW, UINT message, WPARAM wParam, LPARAM lParam) - { - for (int i = activeVSTWindows.size(); --i >= 0;) - { - const VSTPluginWindow* const w = (const VSTPluginWindow*) activeVSTWindows.getUnchecked (i); + // hooks to get keyboard events from VST windows.. + static LRESULT CALLBACK vstHookWndProc (HWND hW, UINT message, WPARAM wParam, LPARAM lParam) + { + for (int i = activeVSTWindows.size(); --i >= 0;) + { + const VSTPluginWindow* const w = (const VSTPluginWindow*) activeVSTWindows.getUnchecked (i); - if (w->pluginHWND == hW) - { - if (message == WM_CHAR - || message == WM_KEYDOWN - || message == WM_SYSKEYDOWN - || message == WM_KEYUP - || message == WM_SYSKEYUP - || message == WM_APPCOMMAND) - { - SendMessage ((HWND) w->getTopLevelComponent()->getWindowHandle(), - message, wParam, lParam); - } + if (w->pluginHWND == hW) + { + if (message == WM_CHAR + || message == WM_KEYDOWN + || message == WM_SYSKEYDOWN + || message == WM_KEYUP + || message == WM_SYSKEYUP + || message == WM_APPCOMMAND) + { + SendMessage ((HWND) w->getTopLevelComponent()->getWindowHandle(), + message, wParam, lParam); + } - return CallWindowProc ((WNDPROC) (w->originalWndProc), - (HWND) w->pluginHWND, - message, - wParam, - lParam); - } - } + return CallWindowProc ((WNDPROC) (w->originalWndProc), + (HWND) w->pluginHWND, + message, + wParam, + lParam); + } + } - return DefWindowProc (hW, message, wParam, lParam); - } + return DefWindowProc (hW, message, wParam, lParam); + } #endif #if JUCE_LINUX - // overload mouse/keyboard events to forward them to the plugin's inner window.. - void sendEventToChild (XEvent* event) - { - if (pluginProc != 0) - { - // if the plugin publishes an event procedure, pass the event directly.. - pluginProc (event); - } - else if (pluginWindow != 0) - { - // if the plugin has a window, then send the event to the window so that - // its message thread will pick it up.. - XSendEvent (display, pluginWindow, False, 0L, event); - XFlush (display); - } - } + // overload mouse/keyboard events to forward them to the plugin's inner window.. + void sendEventToChild (XEvent* event) + { + if (pluginProc != 0) + { + // if the plugin publishes an event procedure, pass the event directly.. + pluginProc (event); + } + else if (pluginWindow != 0) + { + // if the plugin has a window, then send the event to the window so that + // its message thread will pick it up.. + XSendEvent (display, pluginWindow, False, 0L, event); + XFlush (display); + } + } - void mouseEnter (const MouseEvent& e) - { - if (pluginWindow != 0) - { - XEvent ev; - zerostruct (ev); - ev.xcrossing.display = display; - ev.xcrossing.type = EnterNotify; - ev.xcrossing.window = pluginWindow; - ev.xcrossing.root = RootWindow (display, DefaultScreen (display)); - ev.xcrossing.time = CurrentTime; - ev.xcrossing.x = e.x; - ev.xcrossing.y = e.y; - ev.xcrossing.x_root = e.getScreenX(); - ev.xcrossing.y_root = e.getScreenY(); - ev.xcrossing.mode = NotifyNormal; // NotifyGrab, NotifyUngrab - ev.xcrossing.detail = NotifyAncestor; // NotifyVirtual, NotifyInferior, NotifyNonlinear,NotifyNonlinearVirtual + void mouseEnter (const MouseEvent& e) + { + if (pluginWindow != 0) + { + XEvent ev; + zerostruct (ev); + ev.xcrossing.display = display; + ev.xcrossing.type = EnterNotify; + ev.xcrossing.window = pluginWindow; + ev.xcrossing.root = RootWindow (display, DefaultScreen (display)); + ev.xcrossing.time = CurrentTime; + ev.xcrossing.x = e.x; + ev.xcrossing.y = e.y; + ev.xcrossing.x_root = e.getScreenX(); + ev.xcrossing.y_root = e.getScreenY(); + ev.xcrossing.mode = NotifyNormal; // NotifyGrab, NotifyUngrab + ev.xcrossing.detail = NotifyAncestor; // NotifyVirtual, NotifyInferior, NotifyNonlinear,NotifyNonlinearVirtual - translateJuceToXCrossingModifiers (e, ev); + translateJuceToXCrossingModifiers (e, ev); - sendEventToChild (&ev); - } - } + sendEventToChild (&ev); + } + } - void mouseExit (const MouseEvent& e) - { - if (pluginWindow != 0) - { - XEvent ev; - zerostruct (ev); - ev.xcrossing.display = display; - ev.xcrossing.type = LeaveNotify; - ev.xcrossing.window = pluginWindow; - ev.xcrossing.root = RootWindow (display, DefaultScreen (display)); - ev.xcrossing.time = CurrentTime; - ev.xcrossing.x = e.x; - ev.xcrossing.y = e.y; - ev.xcrossing.x_root = e.getScreenX(); - ev.xcrossing.y_root = e.getScreenY(); - ev.xcrossing.mode = NotifyNormal; // NotifyGrab, NotifyUngrab - ev.xcrossing.detail = NotifyAncestor; // NotifyVirtual, NotifyInferior, NotifyNonlinear,NotifyNonlinearVirtual - ev.xcrossing.focus = hasKeyboardFocus (true); // TODO - yes ? + void mouseExit (const MouseEvent& e) + { + if (pluginWindow != 0) + { + XEvent ev; + zerostruct (ev); + ev.xcrossing.display = display; + ev.xcrossing.type = LeaveNotify; + ev.xcrossing.window = pluginWindow; + ev.xcrossing.root = RootWindow (display, DefaultScreen (display)); + ev.xcrossing.time = CurrentTime; + ev.xcrossing.x = e.x; + ev.xcrossing.y = e.y; + ev.xcrossing.x_root = e.getScreenX(); + ev.xcrossing.y_root = e.getScreenY(); + ev.xcrossing.mode = NotifyNormal; // NotifyGrab, NotifyUngrab + ev.xcrossing.detail = NotifyAncestor; // NotifyVirtual, NotifyInferior, NotifyNonlinear,NotifyNonlinearVirtual + ev.xcrossing.focus = hasKeyboardFocus (true); // TODO - yes ? - translateJuceToXCrossingModifiers (e, ev); + translateJuceToXCrossingModifiers (e, ev); - sendEventToChild (&ev); - } - } + sendEventToChild (&ev); + } + } - void mouseMove (const MouseEvent& e) - { - if (pluginWindow != 0) - { - XEvent ev; - zerostruct (ev); - ev.xmotion.display = display; - ev.xmotion.type = MotionNotify; - ev.xmotion.window = pluginWindow; - ev.xmotion.root = RootWindow (display, DefaultScreen (display)); - ev.xmotion.time = CurrentTime; - ev.xmotion.is_hint = NotifyNormal; - ev.xmotion.x = e.x; - ev.xmotion.y = e.y; - ev.xmotion.x_root = e.getScreenX(); - ev.xmotion.y_root = e.getScreenY(); + void mouseMove (const MouseEvent& e) + { + if (pluginWindow != 0) + { + XEvent ev; + zerostruct (ev); + ev.xmotion.display = display; + ev.xmotion.type = MotionNotify; + ev.xmotion.window = pluginWindow; + ev.xmotion.root = RootWindow (display, DefaultScreen (display)); + ev.xmotion.time = CurrentTime; + ev.xmotion.is_hint = NotifyNormal; + ev.xmotion.x = e.x; + ev.xmotion.y = e.y; + ev.xmotion.x_root = e.getScreenX(); + ev.xmotion.y_root = e.getScreenY(); - sendEventToChild (&ev); - } - } + sendEventToChild (&ev); + } + } - void mouseDrag (const MouseEvent& e) - { - if (pluginWindow != 0) - { - XEvent ev; - zerostruct (ev); - ev.xmotion.display = display; - ev.xmotion.type = MotionNotify; - ev.xmotion.window = pluginWindow; - ev.xmotion.root = RootWindow (display, DefaultScreen (display)); - ev.xmotion.time = CurrentTime; - ev.xmotion.x = e.x ; - ev.xmotion.y = e.y; - ev.xmotion.x_root = e.getScreenX(); - ev.xmotion.y_root = e.getScreenY(); - ev.xmotion.is_hint = NotifyNormal; + void mouseDrag (const MouseEvent& e) + { + if (pluginWindow != 0) + { + XEvent ev; + zerostruct (ev); + ev.xmotion.display = display; + ev.xmotion.type = MotionNotify; + ev.xmotion.window = pluginWindow; + ev.xmotion.root = RootWindow (display, DefaultScreen (display)); + ev.xmotion.time = CurrentTime; + ev.xmotion.x = e.x ; + ev.xmotion.y = e.y; + ev.xmotion.x_root = e.getScreenX(); + ev.xmotion.y_root = e.getScreenY(); + ev.xmotion.is_hint = NotifyNormal; - translateJuceToXMotionModifiers (e, ev); - sendEventToChild (&ev); - } - } + translateJuceToXMotionModifiers (e, ev); + sendEventToChild (&ev); + } + } - void mouseUp (const MouseEvent& e) - { - if (pluginWindow != 0) - { - XEvent ev; - zerostruct (ev); - ev.xbutton.display = display; - ev.xbutton.type = ButtonRelease; - ev.xbutton.window = pluginWindow; - ev.xbutton.root = RootWindow (display, DefaultScreen (display)); - ev.xbutton.time = CurrentTime; - ev.xbutton.x = e.x; - ev.xbutton.y = e.y; - ev.xbutton.x_root = e.getScreenX(); - ev.xbutton.y_root = e.getScreenY(); + void mouseUp (const MouseEvent& e) + { + if (pluginWindow != 0) + { + XEvent ev; + zerostruct (ev); + ev.xbutton.display = display; + ev.xbutton.type = ButtonRelease; + ev.xbutton.window = pluginWindow; + ev.xbutton.root = RootWindow (display, DefaultScreen (display)); + ev.xbutton.time = CurrentTime; + ev.xbutton.x = e.x; + ev.xbutton.y = e.y; + ev.xbutton.x_root = e.getScreenX(); + ev.xbutton.y_root = e.getScreenY(); - translateJuceToXButtonModifiers (e, ev); - sendEventToChild (&ev); - } - } + translateJuceToXButtonModifiers (e, ev); + sendEventToChild (&ev); + } + } - void mouseWheelMove (const MouseEvent& e, - float incrementX, - float incrementY) - { - if (pluginWindow != 0) - { - XEvent ev; - zerostruct (ev); - ev.xbutton.display = display; - ev.xbutton.type = ButtonPress; - ev.xbutton.window = pluginWindow; - ev.xbutton.root = RootWindow (display, DefaultScreen (display)); - ev.xbutton.time = CurrentTime; - ev.xbutton.x = e.x; - ev.xbutton.y = e.y; - ev.xbutton.x_root = e.getScreenX(); - ev.xbutton.y_root = e.getScreenY(); + void mouseWheelMove (const MouseEvent& e, + float incrementX, + float incrementY) + { + if (pluginWindow != 0) + { + XEvent ev; + zerostruct (ev); + ev.xbutton.display = display; + ev.xbutton.type = ButtonPress; + ev.xbutton.window = pluginWindow; + ev.xbutton.root = RootWindow (display, DefaultScreen (display)); + ev.xbutton.time = CurrentTime; + ev.xbutton.x = e.x; + ev.xbutton.y = e.y; + ev.xbutton.x_root = e.getScreenX(); + ev.xbutton.y_root = e.getScreenY(); - translateJuceToXMouseWheelModifiers (e, incrementY, ev); - sendEventToChild (&ev); + translateJuceToXMouseWheelModifiers (e, incrementY, ev); + sendEventToChild (&ev); - // TODO - put a usleep here ? + // TODO - put a usleep here ? - ev.xbutton.type = ButtonRelease; - sendEventToChild (&ev); - } - } + ev.xbutton.type = ButtonRelease; + sendEventToChild (&ev); + } + } #endif #if JUCE_MAC @@ -33589,402 +33298,402 @@ private: #error "To build VSTs, you need to enable the JUCE_SUPPORT_CARBON flag in your config!" #endif - class InnerWrapperComponent : public CarbonViewWrapperComponent - { - public: - InnerWrapperComponent (VSTPluginWindow* const owner_) - : owner (owner_), - alreadyInside (false) - { - } + class InnerWrapperComponent : public CarbonViewWrapperComponent + { + public: + InnerWrapperComponent (VSTPluginWindow* const owner_) + : owner (owner_), + alreadyInside (false) + { + } - ~InnerWrapperComponent() - { - deleteWindow(); - } + ~InnerWrapperComponent() + { + deleteWindow(); + } - HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) - { - owner->openPluginWindow (windowRef); - return 0; - } + HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) + { + owner->openPluginWindow (windowRef); + return 0; + } - void removeView (HIViewRef) - { - owner->dispatch (effEditClose, 0, 0, 0, 0); - owner->dispatch (effEditSleep, 0, 0, 0, 0); - } + void removeView (HIViewRef) + { + owner->dispatch (effEditClose, 0, 0, 0, 0); + owner->dispatch (effEditSleep, 0, 0, 0, 0); + } - bool getEmbeddedViewSize (int& w, int& h) - { - ERect* rect = 0; - owner->dispatch (effEditGetRect, 0, 0, &rect, 0); - w = rect->right - rect->left; - h = rect->bottom - rect->top; - return true; - } + bool getEmbeddedViewSize (int& w, int& h) + { + ERect* rect = 0; + owner->dispatch (effEditGetRect, 0, 0, &rect, 0); + w = rect->right - rect->left; + h = rect->bottom - rect->top; + return true; + } - void mouseDown (int x, int y) - { - if (! alreadyInside) - { - alreadyInside = true; - getTopLevelComponent()->toFront (true); - owner->dispatch (effEditMouse, x, y, 0, 0); - alreadyInside = false; - } - else - { - PostEvent (::mouseDown, 0); - } - } + void mouseDown (int x, int y) + { + if (! alreadyInside) + { + alreadyInside = true; + getTopLevelComponent()->toFront (true); + owner->dispatch (effEditMouse, x, y, 0, 0); + alreadyInside = false; + } + else + { + PostEvent (::mouseDown, 0); + } + } - void paint() - { - ComponentPeer* const peer = getPeer(); + void paint() + { + ComponentPeer* const peer = getPeer(); - if (peer != 0) - { - ERect r; - r.left = getScreenX() - peer->getScreenX(); - r.right = r.left + getWidth(); - r.top = getScreenY() - peer->getScreenY(); - r.bottom = r.top + getHeight(); + if (peer != 0) + { + ERect r; + r.left = getScreenX() - peer->getScreenX(); + r.right = r.left + getWidth(); + r.top = getScreenY() - peer->getScreenY(); + r.bottom = r.top + getHeight(); - owner->dispatch (effEditDraw, 0, 0, &r, 0); - } - } + owner->dispatch (effEditDraw, 0, 0, &r, 0); + } + } - private: - VSTPluginWindow* const owner; - bool alreadyInside; - }; + private: + VSTPluginWindow* const owner; + bool alreadyInside; + }; - friend class InnerWrapperComponent; - ScopedPointer innerWrapper; + friend class InnerWrapperComponent; + ScopedPointer innerWrapper; - void resized() - { - innerWrapper->setSize (getWidth(), getHeight()); - } + void resized() + { + innerWrapper->setSize (getWidth(), getHeight()); + } #endif }; AudioProcessorEditor* VSTPluginInstance::createEditor() { - if (hasEditor()) - return new VSTPluginWindow (*this); + if (hasEditor()) + return new VSTPluginWindow (*this); - return 0; + return 0; } void VSTPluginInstance::handleAsyncUpdate() { - // indicates that something about the plugin has changed.. - updateHostDisplay(); + // indicates that something about the plugin has changed.. + updateHostDisplay(); } bool VSTPluginInstance::restoreProgramSettings (const fxProgram* const prog) { - if (vst_swap (prog->chunkMagic) == 'CcnK' && vst_swap (prog->fxMagic) == 'FxCk') - { - changeProgramName (getCurrentProgram(), prog->prgName); + if (vst_swap (prog->chunkMagic) == 'CcnK' && vst_swap (prog->fxMagic) == 'FxCk') + { + changeProgramName (getCurrentProgram(), prog->prgName); - for (int i = 0; i < vst_swap (prog->numParams); ++i) - setParameter (i, vst_swapFloat (prog->params[i])); + for (int i = 0; i < vst_swap (prog->numParams); ++i) + setParameter (i, vst_swapFloat (prog->params[i])); - return true; - } + return true; + } - return false; + return false; } bool VSTPluginInstance::loadFromFXBFile (const void* const data, - const int dataSize) + const int dataSize) { - if (dataSize < 28) - return false; + if (dataSize < 28) + return false; - const fxSet* const set = (const fxSet*) data; + const fxSet* const set = (const fxSet*) data; - if ((vst_swap (set->chunkMagic) != 'CcnK' && vst_swap (set->chunkMagic) != 'KncC') - || vst_swap (set->version) > fxbVersionNum) - return false; + if ((vst_swap (set->chunkMagic) != 'CcnK' && vst_swap (set->chunkMagic) != 'KncC') + || vst_swap (set->version) > fxbVersionNum) + return false; - if (vst_swap (set->fxMagic) == 'FxBk') - { - // bank of programs - if (vst_swap (set->numPrograms) >= 0) - { - const int oldProg = getCurrentProgram(); - const int numParams = vst_swap (((const fxProgram*) (set->programs))->numParams); - const int progLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); + if (vst_swap (set->fxMagic) == 'FxBk') + { + // bank of programs + if (vst_swap (set->numPrograms) >= 0) + { + const int oldProg = getCurrentProgram(); + const int numParams = vst_swap (((const fxProgram*) (set->programs))->numParams); + const int progLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); - for (int i = 0; i < vst_swap (set->numPrograms); ++i) - { - if (i != oldProg) - { - const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + i * progLen); - if (((const char*) prog) - ((const char*) set) >= dataSize) - return false; + for (int i = 0; i < vst_swap (set->numPrograms); ++i) + { + if (i != oldProg) + { + const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + i * progLen); + if (((const char*) prog) - ((const char*) set) >= dataSize) + return false; - if (vst_swap (set->numPrograms) > 0) - setCurrentProgram (i); + if (vst_swap (set->numPrograms) > 0) + setCurrentProgram (i); - if (! restoreProgramSettings (prog)) - return false; - } - } + if (! restoreProgramSettings (prog)) + return false; + } + } - if (vst_swap (set->numPrograms) > 0) - setCurrentProgram (oldProg); + if (vst_swap (set->numPrograms) > 0) + setCurrentProgram (oldProg); - const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + oldProg * progLen); - if (((const char*) prog) - ((const char*) set) >= dataSize) - return false; + const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + oldProg * progLen); + if (((const char*) prog) - ((const char*) set) >= dataSize) + return false; - if (! restoreProgramSettings (prog)) - return false; - } - } - else if (vst_swap (set->fxMagic) == 'FxCk') - { - // single program - const fxProgram* const prog = (const fxProgram*) data; + if (! restoreProgramSettings (prog)) + return false; + } + } + else if (vst_swap (set->fxMagic) == 'FxCk') + { + // single program + const fxProgram* const prog = (const fxProgram*) data; - if (vst_swap (prog->chunkMagic) != 'CcnK') - return false; + if (vst_swap (prog->chunkMagic) != 'CcnK') + return false; - changeProgramName (getCurrentProgram(), prog->prgName); + changeProgramName (getCurrentProgram(), prog->prgName); - for (int i = 0; i < vst_swap (prog->numParams); ++i) - setParameter (i, vst_swapFloat (prog->params[i])); - } - else if (vst_swap (set->fxMagic) == 'FBCh' || vst_swap (set->fxMagic) == 'hCBF') - { - // non-preset chunk - const fxChunkSet* const cset = (const fxChunkSet*) data; + for (int i = 0; i < vst_swap (prog->numParams); ++i) + setParameter (i, vst_swapFloat (prog->params[i])); + } + else if (vst_swap (set->fxMagic) == 'FBCh' || vst_swap (set->fxMagic) == 'hCBF') + { + // non-preset chunk + const fxChunkSet* const cset = (const fxChunkSet*) data; - if (vst_swap (cset->chunkSize) + sizeof (fxChunkSet) - 8 > (unsigned int) dataSize) - return false; + if (vst_swap (cset->chunkSize) + sizeof (fxChunkSet) - 8 > (unsigned int) dataSize) + return false; - setChunkData (cset->chunk, vst_swap (cset->chunkSize), false); - } - else if (vst_swap (set->fxMagic) == 'FPCh' || vst_swap (set->fxMagic) == 'hCPF') - { - // preset chunk - const fxProgramSet* const cset = (const fxProgramSet*) data; + setChunkData (cset->chunk, vst_swap (cset->chunkSize), false); + } + else if (vst_swap (set->fxMagic) == 'FPCh' || vst_swap (set->fxMagic) == 'hCPF') + { + // preset chunk + const fxProgramSet* const cset = (const fxProgramSet*) data; - if (vst_swap (cset->chunkSize) + sizeof (fxProgramSet) - 8 > (unsigned int) dataSize) - return false; + if (vst_swap (cset->chunkSize) + sizeof (fxProgramSet) - 8 > (unsigned int) dataSize) + return false; - setChunkData (cset->chunk, vst_swap (cset->chunkSize), true); + setChunkData (cset->chunk, vst_swap (cset->chunkSize), true); - changeProgramName (getCurrentProgram(), cset->name); - } - else - { - return false; - } + changeProgramName (getCurrentProgram(), cset->name); + } + else + { + return false; + } - return true; + return true; } void VSTPluginInstance::setParamsInProgramBlock (fxProgram* const prog) throw() { - const int numParams = getNumParameters(); + const int numParams = getNumParameters(); - prog->chunkMagic = vst_swap ('CcnK'); - prog->byteSize = 0; - prog->fxMagic = vst_swap ('FxCk'); - prog->version = vst_swap (fxbVersionNum); - prog->fxID = vst_swap (getUID()); - prog->fxVersion = vst_swap (getVersionNumber()); - prog->numParams = vst_swap (numParams); + prog->chunkMagic = vst_swap ('CcnK'); + prog->byteSize = 0; + prog->fxMagic = vst_swap ('FxCk'); + prog->version = vst_swap (fxbVersionNum); + prog->fxID = vst_swap (getUID()); + prog->fxVersion = vst_swap (getVersionNumber()); + prog->numParams = vst_swap (numParams); - getCurrentProgramName().copyToBuffer (prog->prgName, sizeof (prog->prgName) - 1); + getCurrentProgramName().copyToBuffer (prog->prgName, sizeof (prog->prgName) - 1); - for (int i = 0; i < numParams; ++i) - prog->params[i] = vst_swapFloat (getParameter (i)); + for (int i = 0; i < numParams; ++i) + prog->params[i] = vst_swapFloat (getParameter (i)); } bool VSTPluginInstance::saveToFXBFile (MemoryBlock& dest, bool isFXB, int maxSizeMB) { - const int numPrograms = getNumPrograms(); - const int numParams = getNumParameters(); + const int numPrograms = getNumPrograms(); + const int numParams = getNumParameters(); - if (usesChunks()) - { - if (isFXB) - { - MemoryBlock chunk; - getChunkData (chunk, false, maxSizeMB); + if (usesChunks()) + { + if (isFXB) + { + MemoryBlock chunk; + getChunkData (chunk, false, maxSizeMB); - const int totalLen = sizeof (fxChunkSet) + chunk.getSize() - 8; - dest.setSize (totalLen, true); + const int totalLen = sizeof (fxChunkSet) + chunk.getSize() - 8; + dest.setSize (totalLen, true); - fxChunkSet* const set = (fxChunkSet*) dest.getData(); - set->chunkMagic = vst_swap ('CcnK'); - set->byteSize = 0; - set->fxMagic = vst_swap ('FBCh'); - set->version = vst_swap (fxbVersionNum); - set->fxID = vst_swap (getUID()); - set->fxVersion = vst_swap (getVersionNumber()); - set->numPrograms = vst_swap (numPrograms); - set->chunkSize = vst_swap (chunk.getSize()); + fxChunkSet* const set = (fxChunkSet*) dest.getData(); + set->chunkMagic = vst_swap ('CcnK'); + set->byteSize = 0; + set->fxMagic = vst_swap ('FBCh'); + set->version = vst_swap (fxbVersionNum); + set->fxID = vst_swap (getUID()); + set->fxVersion = vst_swap (getVersionNumber()); + set->numPrograms = vst_swap (numPrograms); + set->chunkSize = vst_swap (chunk.getSize()); - chunk.copyTo (set->chunk, 0, chunk.getSize()); - } - else - { - MemoryBlock chunk; - getChunkData (chunk, true, maxSizeMB); + chunk.copyTo (set->chunk, 0, chunk.getSize()); + } + else + { + MemoryBlock chunk; + getChunkData (chunk, true, maxSizeMB); - const int totalLen = sizeof (fxProgramSet) + chunk.getSize() - 8; - dest.setSize (totalLen, true); + const int totalLen = sizeof (fxProgramSet) + chunk.getSize() - 8; + dest.setSize (totalLen, true); - fxProgramSet* const set = (fxProgramSet*) dest.getData(); - set->chunkMagic = vst_swap ('CcnK'); - set->byteSize = 0; - set->fxMagic = vst_swap ('FPCh'); - set->version = vst_swap (fxbVersionNum); - set->fxID = vst_swap (getUID()); - set->fxVersion = vst_swap (getVersionNumber()); - set->numPrograms = vst_swap (numPrograms); - set->chunkSize = vst_swap (chunk.getSize()); + fxProgramSet* const set = (fxProgramSet*) dest.getData(); + set->chunkMagic = vst_swap ('CcnK'); + set->byteSize = 0; + set->fxMagic = vst_swap ('FPCh'); + set->version = vst_swap (fxbVersionNum); + set->fxID = vst_swap (getUID()); + set->fxVersion = vst_swap (getVersionNumber()); + set->numPrograms = vst_swap (numPrograms); + set->chunkSize = vst_swap (chunk.getSize()); - getCurrentProgramName().copyToBuffer (set->name, sizeof (set->name) - 1); - chunk.copyTo (set->chunk, 0, chunk.getSize()); - } - } - else - { - if (isFXB) - { - const int progLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); - const int len = (sizeof (fxSet) - sizeof (fxProgram)) + progLen * jmax (1, numPrograms); - dest.setSize (len, true); + getCurrentProgramName().copyToBuffer (set->name, sizeof (set->name) - 1); + chunk.copyTo (set->chunk, 0, chunk.getSize()); + } + } + else + { + if (isFXB) + { + const int progLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); + const int len = (sizeof (fxSet) - sizeof (fxProgram)) + progLen * jmax (1, numPrograms); + dest.setSize (len, true); - fxSet* const set = (fxSet*) dest.getData(); - set->chunkMagic = vst_swap ('CcnK'); - set->byteSize = 0; - set->fxMagic = vst_swap ('FxBk'); - set->version = vst_swap (fxbVersionNum); - set->fxID = vst_swap (getUID()); - set->fxVersion = vst_swap (getVersionNumber()); - set->numPrograms = vst_swap (numPrograms); + fxSet* const set = (fxSet*) dest.getData(); + set->chunkMagic = vst_swap ('CcnK'); + set->byteSize = 0; + set->fxMagic = vst_swap ('FxBk'); + set->version = vst_swap (fxbVersionNum); + set->fxID = vst_swap (getUID()); + set->fxVersion = vst_swap (getVersionNumber()); + set->numPrograms = vst_swap (numPrograms); - const int oldProgram = getCurrentProgram(); - MemoryBlock oldSettings; - createTempParameterStore (oldSettings); + const int oldProgram = getCurrentProgram(); + MemoryBlock oldSettings; + createTempParameterStore (oldSettings); - setParamsInProgramBlock ((fxProgram*) (((char*) (set->programs)) + oldProgram * progLen)); + setParamsInProgramBlock ((fxProgram*) (((char*) (set->programs)) + oldProgram * progLen)); - for (int i = 0; i < numPrograms; ++i) - { - if (i != oldProgram) - { - setCurrentProgram (i); - setParamsInProgramBlock ((fxProgram*) (((char*) (set->programs)) + i * progLen)); - } - } + for (int i = 0; i < numPrograms; ++i) + { + if (i != oldProgram) + { + setCurrentProgram (i); + setParamsInProgramBlock ((fxProgram*) (((char*) (set->programs)) + i * progLen)); + } + } - setCurrentProgram (oldProgram); - restoreFromTempParameterStore (oldSettings); - } - else - { - const int totalLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); - dest.setSize (totalLen, true); + setCurrentProgram (oldProgram); + restoreFromTempParameterStore (oldSettings); + } + else + { + const int totalLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); + dest.setSize (totalLen, true); - setParamsInProgramBlock ((fxProgram*) dest.getData()); - } - } + setParamsInProgramBlock ((fxProgram*) dest.getData()); + } + } - return true; + return true; } void VSTPluginInstance::getChunkData (MemoryBlock& mb, bool isPreset, int maxSizeMB) const { - if (usesChunks()) - { - void* data = 0; - const int bytes = dispatch (effGetChunk, isPreset ? 1 : 0, 0, &data, 0.0f); + if (usesChunks()) + { + void* data = 0; + const int bytes = dispatch (effGetChunk, isPreset ? 1 : 0, 0, &data, 0.0f); - if (data != 0 && bytes <= maxSizeMB * 1024 * 1024) - { - mb.setSize (bytes); - mb.copyFrom (data, 0, bytes); - } - } + if (data != 0 && bytes <= maxSizeMB * 1024 * 1024) + { + mb.setSize (bytes); + mb.copyFrom (data, 0, bytes); + } + } } void VSTPluginInstance::setChunkData (const char* data, int size, bool isPreset) { - if (size > 0 && usesChunks()) - { - dispatch (effSetChunk, isPreset ? 1 : 0, size, (void*) data, 0.0f); + if (size > 0 && usesChunks()) + { + dispatch (effSetChunk, isPreset ? 1 : 0, size, (void*) data, 0.0f); - if (! isPreset) - updateStoredProgramNames(); - } + if (! isPreset) + updateStoredProgramNames(); + } } void VSTPluginInstance::timerCallback() { - if (dispatch (effIdle, 0, 0, 0, 0) == 0) - stopTimer(); + if (dispatch (effIdle, 0, 0, 0, 0) == 0) + stopTimer(); } int VSTPluginInstance::dispatch (const int opcode, const int index, const int value, void* const ptr, float opt) const { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - ++insideVSTCallback; - int result = 0; + ++insideVSTCallback; + int result = 0; - try - { - if (effect != 0) - { + try + { + if (effect != 0) + { #if JUCE_MAC - if (module->resFileId != 0) - UseResFile (module->resFileId); + if (module->resFileId != 0) + UseResFile (module->resFileId); - CGrafPtr oldPort; + CGrafPtr oldPort; - if (getActiveEditor() != 0) - { - int x = 0, y = 0; - getActiveEditor()->relativePositionToOtherComponent (getActiveEditor()->getTopLevelComponent(), x, y); + if (getActiveEditor() != 0) + { + int x = 0, y = 0; + getActiveEditor()->relativePositionToOtherComponent (getActiveEditor()->getTopLevelComponent(), x, y); - GetPort (&oldPort); - SetPortWindowPort ((WindowRef) getActiveEditor()->getWindowHandle()); - SetOrigin (-x, -y); - } + GetPort (&oldPort); + SetPortWindowPort ((WindowRef) getActiveEditor()->getWindowHandle()); + SetOrigin (-x, -y); + } #endif - result = effect->dispatcher (effect, opcode, index, value, ptr, opt); + result = effect->dispatcher (effect, opcode, index, value, ptr, opt); #if JUCE_MAC - if (getActiveEditor() != 0) - SetPort (oldPort); + if (getActiveEditor() != 0) + SetPort (oldPort); - module->resFileId = CurResFile(); + module->resFileId = CurResFile(); #endif - --insideVSTCallback; - return result; - } - } - catch (...) - { - //char s[512]; - //sprintf (s, "dispatcher (%d, %d, %d, %x, %f)", opcode, index, value, (int)ptr, opt); - } + --insideVSTCallback; + return result; + } + } + catch (...) + { + //char s[512]; + //sprintf (s, "dispatcher (%d, %d, %d, %x, %f)", opcode, index, value, (int)ptr, opt); + } - --insideVSTCallback; - return result; + --insideVSTCallback; + return result; } // handles non plugin-specific callbacks.. @@ -33994,573 +33703,573 @@ static const int defaultVSTBlockSizeValue = 512; static VstIntPtr handleGeneralCallback (VstInt32 opcode, VstInt32 index, VstInt32 value, void *ptr, float opt) { - (void) index; - (void) value; - (void) opt; + (void) index; + (void) value; + (void) opt; - switch (opcode) - { - case audioMasterCanDo: - { - static const char* canDos[] = { "supplyIdle", - "sendVstEvents", - "sendVstMidiEvent", - "sendVstTimeInfo", - "receiveVstEvents", - "receiveVstMidiEvent", - "supportShell", - "shellCategory" }; + switch (opcode) + { + case audioMasterCanDo: + { + static const char* canDos[] = { "supplyIdle", + "sendVstEvents", + "sendVstMidiEvent", + "sendVstTimeInfo", + "receiveVstEvents", + "receiveVstMidiEvent", + "supportShell", + "shellCategory" }; - for (int i = 0; i < numElementsInArray (canDos); ++i) - if (strcmp (canDos[i], (const char*) ptr) == 0) - return 1; + for (int i = 0; i < numElementsInArray (canDos); ++i) + if (strcmp (canDos[i], (const char*) ptr) == 0) + return 1; - return 0; - } + return 0; + } - case audioMasterVersion: - return 0x2400; - case audioMasterCurrentId: - return shellUIDToCreate; - case audioMasterGetNumAutomatableParameters: - return 0; - case audioMasterGetAutomationState: - return 1; + case audioMasterVersion: + return 0x2400; + case audioMasterCurrentId: + return shellUIDToCreate; + case audioMasterGetNumAutomatableParameters: + return 0; + case audioMasterGetAutomationState: + return 1; - case audioMasterGetVendorVersion: - return 0x0101; - case audioMasterGetVendorString: - case audioMasterGetProductString: - { - String hostName ("Juce VST Host"); + case audioMasterGetVendorVersion: + return 0x0101; + case audioMasterGetVendorString: + case audioMasterGetProductString: + { + String hostName ("Juce VST Host"); - if (JUCEApplication::getInstance() != 0) - hostName = JUCEApplication::getInstance()->getApplicationName(); + if (JUCEApplication::getInstance() != 0) + hostName = JUCEApplication::getInstance()->getApplicationName(); - hostName.copyToBuffer ((char*) ptr, jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1); - } - break; + hostName.copyToBuffer ((char*) ptr, jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1); + } + break; - case audioMasterGetSampleRate: - return (VstIntPtr) defaultVSTSampleRateValue; + case audioMasterGetSampleRate: + return (VstIntPtr) defaultVSTSampleRateValue; - case audioMasterGetBlockSize: - return (VstIntPtr) defaultVSTBlockSizeValue; + case audioMasterGetBlockSize: + return (VstIntPtr) defaultVSTBlockSizeValue; - case audioMasterSetOutputSampleRate: - return 0; + case audioMasterSetOutputSampleRate: + return 0; - default: - DBG ("*** Unhandled VST Callback: " + String ((int) opcode)); - break; - } + default: + DBG ("*** Unhandled VST Callback: " + String ((int) opcode)); + break; + } - return 0; + return 0; } // handles callbacks for a specific plugin VstIntPtr VSTPluginInstance::handleCallback (VstInt32 opcode, VstInt32 index, VstInt32 value, void *ptr, float opt) { - switch (opcode) - { - case audioMasterAutomate: - sendParamChangeMessageToListeners (index, opt); - break; + switch (opcode) + { + case audioMasterAutomate: + sendParamChangeMessageToListeners (index, opt); + break; - case audioMasterProcessEvents: - handleMidiFromPlugin ((const VstEvents*) ptr); - break; + case audioMasterProcessEvents: + handleMidiFromPlugin ((const VstEvents*) ptr); + break; - case audioMasterGetTime: - #ifdef _MSC_VER - #pragma warning (push) - #pragma warning (disable: 4311) - #endif + case audioMasterGetTime: + #ifdef _MSC_VER + #pragma warning (push) + #pragma warning (disable: 4311) + #endif - return (VstIntPtr) &vstHostTime; + return (VstIntPtr) &vstHostTime; - #ifdef _MSC_VER - #pragma warning (pop) - #endif - break; + #ifdef _MSC_VER + #pragma warning (pop) + #endif + break; - case audioMasterIdle: - if (insideVSTCallback == 0 && MessageManager::getInstance()->isThisTheMessageThread()) - { - ++insideVSTCallback; + case audioMasterIdle: + if (insideVSTCallback == 0 && MessageManager::getInstance()->isThisTheMessageThread()) + { + ++insideVSTCallback; #if JUCE_MAC - if (getActiveEditor() != 0) - dispatch (effEditIdle, 0, 0, 0, 0); + if (getActiveEditor() != 0) + dispatch (effEditIdle, 0, 0, 0, 0); #endif - juce_callAnyTimersSynchronously(); + juce_callAnyTimersSynchronously(); - handleUpdateNowIfNeeded(); + handleUpdateNowIfNeeded(); - for (int i = ComponentPeer::getNumPeers(); --i >= 0;) - ComponentPeer::getPeer (i)->performAnyPendingRepaintsNow(); + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) + ComponentPeer::getPeer (i)->performAnyPendingRepaintsNow(); - --insideVSTCallback; - } - break; + --insideVSTCallback; + } + break; - case audioMasterUpdateDisplay: - triggerAsyncUpdate(); - break; + case audioMasterUpdateDisplay: + triggerAsyncUpdate(); + break; - case audioMasterTempoAt: - // returns (10000 * bpm) - break; + case audioMasterTempoAt: + // returns (10000 * bpm) + break; - case audioMasterNeedIdle: - startTimer (50); - break; + case audioMasterNeedIdle: + startTimer (50); + break; - case audioMasterSizeWindow: - if (getActiveEditor() != 0) - getActiveEditor()->setSize (index, value); + case audioMasterSizeWindow: + if (getActiveEditor() != 0) + getActiveEditor()->setSize (index, value); - return 1; + return 1; - case audioMasterGetSampleRate: - return (VstIntPtr) (getSampleRate() > 0 ? getSampleRate() : defaultVSTSampleRateValue); + case audioMasterGetSampleRate: + return (VstIntPtr) (getSampleRate() > 0 ? getSampleRate() : defaultVSTSampleRateValue); - case audioMasterGetBlockSize: - return (VstIntPtr) (getBlockSize() > 0 ? getBlockSize() : defaultVSTBlockSizeValue); + case audioMasterGetBlockSize: + return (VstIntPtr) (getBlockSize() > 0 ? getBlockSize() : defaultVSTBlockSizeValue); - case audioMasterWantMidi: - wantsMidiMessages = true; - break; + case audioMasterWantMidi: + wantsMidiMessages = true; + break; - case audioMasterGetDirectory: - #if JUCE_MAC - return (VstIntPtr) (void*) &module->parentDirFSSpec; - #else - return (VstIntPtr) (pointer_sized_uint) (const char*) module->fullParentDirectoryPathName; - #endif + case audioMasterGetDirectory: + #if JUCE_MAC + return (VstIntPtr) (void*) &module->parentDirFSSpec; + #else + return (VstIntPtr) (pointer_sized_uint) (const char*) module->fullParentDirectoryPathName; + #endif - case audioMasterGetAutomationState: - // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write - break; + case audioMasterGetAutomationState: + // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write + break; - // none of these are handled (yet).. - case audioMasterBeginEdit: - case audioMasterEndEdit: - case audioMasterSetTime: - case audioMasterPinConnected: - case audioMasterGetParameterQuantization: - case audioMasterIOChanged: - case audioMasterGetInputLatency: - case audioMasterGetOutputLatency: - case audioMasterGetPreviousPlug: - case audioMasterGetNextPlug: - case audioMasterWillReplaceOrAccumulate: - case audioMasterGetCurrentProcessLevel: - case audioMasterOfflineStart: - case audioMasterOfflineRead: - case audioMasterOfflineWrite: - case audioMasterOfflineGetCurrentPass: - case audioMasterOfflineGetCurrentMetaPass: - case audioMasterVendorSpecific: - case audioMasterSetIcon: - case audioMasterGetLanguage: - case audioMasterOpenWindow: - case audioMasterCloseWindow: - break; + // none of these are handled (yet).. + case audioMasterBeginEdit: + case audioMasterEndEdit: + case audioMasterSetTime: + case audioMasterPinConnected: + case audioMasterGetParameterQuantization: + case audioMasterIOChanged: + case audioMasterGetInputLatency: + case audioMasterGetOutputLatency: + case audioMasterGetPreviousPlug: + case audioMasterGetNextPlug: + case audioMasterWillReplaceOrAccumulate: + case audioMasterGetCurrentProcessLevel: + case audioMasterOfflineStart: + case audioMasterOfflineRead: + case audioMasterOfflineWrite: + case audioMasterOfflineGetCurrentPass: + case audioMasterOfflineGetCurrentMetaPass: + case audioMasterVendorSpecific: + case audioMasterSetIcon: + case audioMasterGetLanguage: + case audioMasterOpenWindow: + case audioMasterCloseWindow: + break; - default: - return handleGeneralCallback (opcode, index, value, ptr, opt); - } + default: + return handleGeneralCallback (opcode, index, value, ptr, opt); + } - return 0; + return 0; } // entry point for all callbacks from the plugin static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt) { - try - { - if (effect != 0 && effect->resvd2 != 0) - { - return ((VSTPluginInstance*)(effect->resvd2)) - ->handleCallback (opcode, index, value, ptr, opt); - } + try + { + if (effect != 0 && effect->resvd2 != 0) + { + return ((VSTPluginInstance*)(effect->resvd2)) + ->handleCallback (opcode, index, value, ptr, opt); + } - return handleGeneralCallback (opcode, index, value, ptr, opt); - } - catch (...) - { - return 0; - } + return handleGeneralCallback (opcode, index, value, ptr, opt); + } + catch (...) + { + return 0; + } } const String VSTPluginInstance::getVersion() const throw() { - unsigned int v = dispatch (effGetVendorVersion, 0, 0, 0, 0); + unsigned int v = dispatch (effGetVendorVersion, 0, 0, 0, 0); - String s; + String s; - if (v == 0 || v == -1) - v = getVersionNumber(); + if (v == 0 || v == -1) + v = getVersionNumber(); - if (v != 0) - { - int versionBits[4]; - int n = 0; + if (v != 0) + { + int versionBits[4]; + int n = 0; - while (v != 0) - { - versionBits [n++] = (v & 0xff); - v >>= 8; - } + while (v != 0) + { + versionBits [n++] = (v & 0xff); + v >>= 8; + } - s << 'V'; + s << 'V'; - while (n > 0) - { - s << versionBits [--n]; + while (n > 0) + { + s << versionBits [--n]; - if (n > 0) - s << '.'; - } - } + if (n > 0) + s << '.'; + } + } - return s; + return s; } int VSTPluginInstance::getUID() const throw() { - int uid = effect != 0 ? effect->uniqueID : 0; + int uid = effect != 0 ? effect->uniqueID : 0; - if (uid == 0) - uid = module->file.hashCode(); + if (uid == 0) + uid = module->file.hashCode(); - return uid; + return uid; } const String VSTPluginInstance::getCategory() const throw() { - const char* result = 0; + const char* result = 0; - switch (dispatch (effGetPlugCategory, 0, 0, 0, 0)) - { - case kPlugCategEffect: - result = "Effect"; - break; + switch (dispatch (effGetPlugCategory, 0, 0, 0, 0)) + { + case kPlugCategEffect: + result = "Effect"; + break; - case kPlugCategSynth: - result = "Synth"; - break; + case kPlugCategSynth: + result = "Synth"; + break; - case kPlugCategAnalysis: - result = "Anaylsis"; - break; + case kPlugCategAnalysis: + result = "Anaylsis"; + break; - case kPlugCategMastering: - result = "Mastering"; - break; + case kPlugCategMastering: + result = "Mastering"; + break; - case kPlugCategSpacializer: - result = "Spacial"; - break; + case kPlugCategSpacializer: + result = "Spacial"; + break; - case kPlugCategRoomFx: - result = "Reverb"; - break; + case kPlugCategRoomFx: + result = "Reverb"; + break; - case kPlugSurroundFx: - result = "Surround"; - break; + case kPlugSurroundFx: + result = "Surround"; + break; - case kPlugCategRestoration: - result = "Restoration"; - break; + case kPlugCategRestoration: + result = "Restoration"; + break; - case kPlugCategGenerator: - result = "Tone generation"; - break; + case kPlugCategGenerator: + result = "Tone generation"; + break; - default: - break; - } + default: + break; + } - return result; + return result; } float VSTPluginInstance::getParameter (int index) { - if (effect != 0 && ((unsigned int) index) < (unsigned int) effect->numParams) - { - try - { - const ScopedLock sl (lock); - return effect->getParameter (effect, index); - } - catch (...) - { - } - } + if (effect != 0 && ((unsigned int) index) < (unsigned int) effect->numParams) + { + try + { + const ScopedLock sl (lock); + return effect->getParameter (effect, index); + } + catch (...) + { + } + } - return 0.0f; + return 0.0f; } void VSTPluginInstance::setParameter (int index, float newValue) { - if (effect != 0 && ((unsigned int) index) < (unsigned int) effect->numParams) - { - try - { - const ScopedLock sl (lock); + if (effect != 0 && ((unsigned int) index) < (unsigned int) effect->numParams) + { + try + { + const ScopedLock sl (lock); - if (effect->getParameter (effect, index) != newValue) - effect->setParameter (effect, index, newValue); - } - catch (...) - { - } - } + if (effect->getParameter (effect, index) != newValue) + effect->setParameter (effect, index, newValue); + } + catch (...) + { + } + } } const String VSTPluginInstance::getParameterName (int index) { - if (effect != 0) - { - jassert (index >= 0 && index < effect->numParams); + if (effect != 0) + { + jassert (index >= 0 && index < effect->numParams); - char nm [256]; - zerostruct (nm); - dispatch (effGetParamName, index, 0, nm, 0); - return String (nm).trim(); - } + char nm [256]; + zerostruct (nm); + dispatch (effGetParamName, index, 0, nm, 0); + return String (nm).trim(); + } - return String::empty; + return String::empty; } const String VSTPluginInstance::getParameterLabel (int index) const { - if (effect != 0) - { - jassert (index >= 0 && index < effect->numParams); + if (effect != 0) + { + jassert (index >= 0 && index < effect->numParams); - char nm [256]; - zerostruct (nm); - dispatch (effGetParamLabel, index, 0, nm, 0); - return String (nm).trim(); - } + char nm [256]; + zerostruct (nm); + dispatch (effGetParamLabel, index, 0, nm, 0); + return String (nm).trim(); + } - return String::empty; + return String::empty; } const String VSTPluginInstance::getParameterText (int index) { - if (effect != 0) - { - jassert (index >= 0 && index < effect->numParams); + if (effect != 0) + { + jassert (index >= 0 && index < effect->numParams); - char nm [256]; - zerostruct (nm); - dispatch (effGetParamDisplay, index, 0, nm, 0); - return String (nm).trim(); - } + char nm [256]; + zerostruct (nm); + dispatch (effGetParamDisplay, index, 0, nm, 0); + return String (nm).trim(); + } - return String::empty; + return String::empty; } bool VSTPluginInstance::isParameterAutomatable (int index) const { - if (effect != 0) - { - jassert (index >= 0 && index < effect->numParams); - return dispatch (effCanBeAutomated, index, 0, 0, 0) != 0; - } + if (effect != 0) + { + jassert (index >= 0 && index < effect->numParams); + return dispatch (effCanBeAutomated, index, 0, 0, 0) != 0; + } - return false; + return false; } void VSTPluginInstance::createTempParameterStore (MemoryBlock& dest) { - dest.setSize (64 + 4 * getNumParameters()); - dest.fillWith (0); + dest.setSize (64 + 4 * getNumParameters()); + dest.fillWith (0); - getCurrentProgramName().copyToBuffer ((char*) dest.getData(), 63); + getCurrentProgramName().copyToBuffer ((char*) dest.getData(), 63); - float* const p = (float*) (((char*) dest.getData()) + 64); - for (int i = 0; i < getNumParameters(); ++i) - p[i] = getParameter(i); + float* const p = (float*) (((char*) dest.getData()) + 64); + for (int i = 0; i < getNumParameters(); ++i) + p[i] = getParameter(i); } void VSTPluginInstance::restoreFromTempParameterStore (const MemoryBlock& m) { - changeProgramName (getCurrentProgram(), (const char*) m.getData()); + changeProgramName (getCurrentProgram(), (const char*) m.getData()); - float* p = (float*) (((char*) m.getData()) + 64); - for (int i = 0; i < getNumParameters(); ++i) - setParameter (i, p[i]); + float* p = (float*) (((char*) m.getData()) + 64); + for (int i = 0; i < getNumParameters(); ++i) + setParameter (i, p[i]); } void VSTPluginInstance::setCurrentProgram (int newIndex) { - if (getNumPrograms() > 0 && newIndex != getCurrentProgram()) - dispatch (effSetProgram, 0, jlimit (0, getNumPrograms() - 1, newIndex), 0, 0); + if (getNumPrograms() > 0 && newIndex != getCurrentProgram()) + dispatch (effSetProgram, 0, jlimit (0, getNumPrograms() - 1, newIndex), 0, 0); } const String VSTPluginInstance::getProgramName (int index) { - if (index == getCurrentProgram()) - { - return getCurrentProgramName(); - } - else if (effect != 0) - { - char nm [256]; - zerostruct (nm); + if (index == getCurrentProgram()) + { + return getCurrentProgramName(); + } + else if (effect != 0) + { + char nm [256]; + zerostruct (nm); - if (dispatch (effGetProgramNameIndexed, - jlimit (0, getNumPrograms(), index), - -1, nm, 0) != 0) - { - return String (nm).trim(); - } - } + if (dispatch (effGetProgramNameIndexed, + jlimit (0, getNumPrograms(), index), + -1, nm, 0) != 0) + { + return String (nm).trim(); + } + } - return programNames [index]; + return programNames [index]; } void VSTPluginInstance::changeProgramName (int index, const String& newName) { - if (index == getCurrentProgram()) - { - if (getNumPrograms() > 0 && newName != getCurrentProgramName()) - dispatch (effSetProgramName, 0, 0, (void*) (const char*) newName.substring (0, 24), 0.0f); - } - else - { - jassertfalse // xxx not implemented! - } + if (index == getCurrentProgram()) + { + if (getNumPrograms() > 0 && newName != getCurrentProgramName()) + dispatch (effSetProgramName, 0, 0, (void*) (const char*) newName.substring (0, 24), 0.0f); + } + else + { + jassertfalse // xxx not implemented! + } } void VSTPluginInstance::updateStoredProgramNames() { - if (effect != 0 && getNumPrograms() > 0) - { - char nm [256]; - zerostruct (nm); + if (effect != 0 && getNumPrograms() > 0) + { + char nm [256]; + zerostruct (nm); - // only do this if the plugin can't use indexed names.. - if (dispatch (effGetProgramNameIndexed, 0, -1, nm, 0) == 0) - { - const int oldProgram = getCurrentProgram(); - MemoryBlock oldSettings; - createTempParameterStore (oldSettings); + // only do this if the plugin can't use indexed names.. + if (dispatch (effGetProgramNameIndexed, 0, -1, nm, 0) == 0) + { + const int oldProgram = getCurrentProgram(); + MemoryBlock oldSettings; + createTempParameterStore (oldSettings); - for (int i = 0; i < getNumPrograms(); ++i) - { - setCurrentProgram (i); - getCurrentProgramName(); // (this updates the list) - } + for (int i = 0; i < getNumPrograms(); ++i) + { + setCurrentProgram (i); + getCurrentProgramName(); // (this updates the list) + } - setCurrentProgram (oldProgram); - restoreFromTempParameterStore (oldSettings); - } - } + setCurrentProgram (oldProgram); + restoreFromTempParameterStore (oldSettings); + } + } } const String VSTPluginInstance::getCurrentProgramName() { - if (effect != 0) - { - char nm [256]; - zerostruct (nm); - dispatch (effGetProgramName, 0, 0, nm, 0); + if (effect != 0) + { + char nm [256]; + zerostruct (nm); + dispatch (effGetProgramName, 0, 0, nm, 0); - const int index = getCurrentProgram(); - if (programNames[index].isEmpty()) - { - while (programNames.size() < index) - programNames.add (String::empty); + const int index = getCurrentProgram(); + if (programNames[index].isEmpty()) + { + while (programNames.size() < index) + programNames.add (String::empty); - programNames.set (index, String (nm).trim()); - } + programNames.set (index, String (nm).trim()); + } - return String (nm).trim(); - } + return String (nm).trim(); + } - return String::empty; + return String::empty; } const String VSTPluginInstance::getInputChannelName (const int index) const { - if (index >= 0 && index < getNumInputChannels()) - { - VstPinProperties pinProps; - if (dispatch (effGetInputProperties, index, 0, &pinProps, 0.0f) != 0) - return String (pinProps.label, sizeof (pinProps.label)); - } + if (index >= 0 && index < getNumInputChannels()) + { + VstPinProperties pinProps; + if (dispatch (effGetInputProperties, index, 0, &pinProps, 0.0f) != 0) + return String (pinProps.label, sizeof (pinProps.label)); + } - return String::empty; + return String::empty; } bool VSTPluginInstance::isInputChannelStereoPair (int index) const { - if (index < 0 || index >= getNumInputChannels()) - return false; + if (index < 0 || index >= getNumInputChannels()) + return false; - VstPinProperties pinProps; - if (dispatch (effGetInputProperties, index, 0, &pinProps, 0.0f) != 0) - return (pinProps.flags & kVstPinIsStereo) != 0; + VstPinProperties pinProps; + if (dispatch (effGetInputProperties, index, 0, &pinProps, 0.0f) != 0) + return (pinProps.flags & kVstPinIsStereo) != 0; - return true; + return true; } const String VSTPluginInstance::getOutputChannelName (const int index) const { - if (index >= 0 && index < getNumOutputChannels()) - { - VstPinProperties pinProps; - if (dispatch (effGetOutputProperties, index, 0, &pinProps, 0.0f) != 0) - return String (pinProps.label, sizeof (pinProps.label)); - } + if (index >= 0 && index < getNumOutputChannels()) + { + VstPinProperties pinProps; + if (dispatch (effGetOutputProperties, index, 0, &pinProps, 0.0f) != 0) + return String (pinProps.label, sizeof (pinProps.label)); + } - return String::empty; + return String::empty; } bool VSTPluginInstance::isOutputChannelStereoPair (int index) const { - if (index < 0 || index >= getNumOutputChannels()) - return false; + if (index < 0 || index >= getNumOutputChannels()) + return false; - VstPinProperties pinProps; - if (dispatch (effGetOutputProperties, index, 0, &pinProps, 0.0f) != 0) - return (pinProps.flags & kVstPinIsStereo) != 0; + VstPinProperties pinProps; + if (dispatch (effGetOutputProperties, index, 0, &pinProps, 0.0f) != 0) + return (pinProps.flags & kVstPinIsStereo) != 0; - return true; + return true; } void VSTPluginInstance::setPower (const bool on) { - dispatch (effMainsChanged, 0, on ? 1 : 0, 0, 0); - isPowerOn = on; + dispatch (effMainsChanged, 0, on ? 1 : 0, 0, 0); + isPowerOn = on; } const int defaultMaxSizeMB = 64; void VSTPluginInstance::getStateInformation (MemoryBlock& destData) { - saveToFXBFile (destData, true, defaultMaxSizeMB); + saveToFXBFile (destData, true, defaultMaxSizeMB); } void VSTPluginInstance::getCurrentProgramStateInformation (MemoryBlock& destData) { - saveToFXBFile (destData, false, defaultMaxSizeMB); + saveToFXBFile (destData, false, defaultMaxSizeMB); } void VSTPluginInstance::setStateInformation (const void* data, int sizeInBytes) { - loadFromFXBFile (data, sizeInBytes); + loadFromFXBFile (data, sizeInBytes); } void VSTPluginInstance::setCurrentProgramStateInformation (const void* data, int sizeInBytes) { - loadFromFXBFile (data, sizeInBytes); + loadFromFXBFile (data, sizeInBytes); } VSTPluginFormat::VSTPluginFormat() @@ -34572,207 +34281,207 @@ VSTPluginFormat::~VSTPluginFormat() } void VSTPluginFormat::findAllTypesForFile (OwnedArray & results, - const String& fileOrIdentifier) + const String& fileOrIdentifier) { - if (! fileMightContainThisPluginType (fileOrIdentifier)) - return; + if (! fileMightContainThisPluginType (fileOrIdentifier)) + return; - PluginDescription desc; - desc.fileOrIdentifier = fileOrIdentifier; - desc.uid = 0; + PluginDescription desc; + desc.fileOrIdentifier = fileOrIdentifier; + desc.uid = 0; - ScopedPointer instance (dynamic_cast (createInstanceFromDescription (desc))); + ScopedPointer instance (dynamic_cast (createInstanceFromDescription (desc))); - if (instance == 0) - return; + if (instance == 0) + return; - try - { + try + { #if JUCE_MAC - if (instance->module->resFileId != 0) - UseResFile (instance->module->resFileId); + if (instance->module->resFileId != 0) + UseResFile (instance->module->resFileId); #endif - instance->fillInPluginDescription (desc); + instance->fillInPluginDescription (desc); - VstPlugCategory category = (VstPlugCategory) instance->dispatch (effGetPlugCategory, 0, 0, 0, 0); + VstPlugCategory category = (VstPlugCategory) instance->dispatch (effGetPlugCategory, 0, 0, 0, 0); - if (category != kPlugCategShell) - { - // Normal plugin... - results.add (new PluginDescription (desc)); + if (category != kPlugCategShell) + { + // Normal plugin... + results.add (new PluginDescription (desc)); - ++insideVSTCallback; - instance->dispatch (effOpen, 0, 0, 0, 0); - --insideVSTCallback; - } - else - { - // It's a shell plugin, so iterate all the subtypes... - char shellEffectName [64]; + ++insideVSTCallback; + instance->dispatch (effOpen, 0, 0, 0, 0); + --insideVSTCallback; + } + else + { + // It's a shell plugin, so iterate all the subtypes... + char shellEffectName [64]; - for (;;) - { - zerostruct (shellEffectName); - const int uid = instance->dispatch (effShellGetNextPlugin, 0, 0, shellEffectName, 0); + for (;;) + { + zerostruct (shellEffectName); + const int uid = instance->dispatch (effShellGetNextPlugin, 0, 0, shellEffectName, 0); - if (uid == 0) - { - break; - } - else - { - desc.uid = uid; - desc.name = shellEffectName; + if (uid == 0) + { + break; + } + else + { + desc.uid = uid; + desc.name = shellEffectName; - bool alreadyThere = false; + bool alreadyThere = false; - for (int i = results.size(); --i >= 0;) - { - PluginDescription* const d = results.getUnchecked(i); + for (int i = results.size(); --i >= 0;) + { + PluginDescription* const d = results.getUnchecked(i); - if (d->isDuplicateOf (desc)) - { - alreadyThere = true; - break; - } - } + if (d->isDuplicateOf (desc)) + { + alreadyThere = true; + break; + } + } - if (! alreadyThere) - results.add (new PluginDescription (desc)); - } - } - } - } - catch (...) - { - // crashed while loading... - } + if (! alreadyThere) + results.add (new PluginDescription (desc)); + } + } + } + } + catch (...) + { + // crashed while loading... + } } AudioPluginInstance* VSTPluginFormat::createInstanceFromDescription (const PluginDescription& desc) { - ScopedPointer result; + ScopedPointer result; - if (fileMightContainThisPluginType (desc.fileOrIdentifier)) - { - File file (desc.fileOrIdentifier); + if (fileMightContainThisPluginType (desc.fileOrIdentifier)) + { + File file (desc.fileOrIdentifier); - const File previousWorkingDirectory (File::getCurrentWorkingDirectory()); - file.getParentDirectory().setAsCurrentWorkingDirectory(); + const File previousWorkingDirectory (File::getCurrentWorkingDirectory()); + file.getParentDirectory().setAsCurrentWorkingDirectory(); - const ReferenceCountedObjectPtr module (ModuleHandle::findOrCreateModule (file)); + const ReferenceCountedObjectPtr module (ModuleHandle::findOrCreateModule (file)); - if (module != 0) - { - shellUIDToCreate = desc.uid; + if (module != 0) + { + shellUIDToCreate = desc.uid; - result = new VSTPluginInstance (module); + result = new VSTPluginInstance (module); - if (result->effect != 0) - { - result->effect->resvd2 = (VstIntPtr) (pointer_sized_int) (VSTPluginInstance*) result; - result->initialise(); - } - else - { - result = 0; - } - } + if (result->effect != 0) + { + result->effect->resvd2 = (VstIntPtr) (pointer_sized_int) (VSTPluginInstance*) result; + result->initialise(); + } + else + { + result = 0; + } + } - previousWorkingDirectory.setAsCurrentWorkingDirectory(); - } + previousWorkingDirectory.setAsCurrentWorkingDirectory(); + } - return result.release(); + return result.release(); } bool VSTPluginFormat::fileMightContainThisPluginType (const String& fileOrIdentifier) { - const File f (fileOrIdentifier); + const File f (fileOrIdentifier); #if JUCE_MAC - if (f.isDirectory() && f.hasFileExtension (T(".vst"))) - return true; + if (f.isDirectory() && f.hasFileExtension (T(".vst"))) + return true; #if JUCE_PPC - FSRef fileRef; - if (PlatformUtilities::makeFSRefFromPath (&fileRef, f.getFullPathName())) - { - const short resFileId = FSOpenResFile (&fileRef, fsRdPerm); + FSRef fileRef; + if (PlatformUtilities::makeFSRefFromPath (&fileRef, f.getFullPathName())) + { + const short resFileId = FSOpenResFile (&fileRef, fsRdPerm); - if (resFileId != -1) - { - const int numEffects = Count1Resources ('aEff'); - CloseResFile (resFileId); + if (resFileId != -1) + { + const int numEffects = Count1Resources ('aEff'); + CloseResFile (resFileId); - if (numEffects > 0) - return true; - } - } + if (numEffects > 0) + return true; + } + } #endif - return false; + return false; #elif JUCE_WIN32 - return f.existsAsFile() - && f.hasFileExtension (T(".dll")); + return f.existsAsFile() + && f.hasFileExtension (T(".dll")); #elif JUCE_LINUX - return f.existsAsFile() - && f.hasFileExtension (T(".so")); + return f.existsAsFile() + && f.hasFileExtension (T(".so")); #endif } const String VSTPluginFormat::getNameOfPluginFromIdentifier (const String& fileOrIdentifier) { - return fileOrIdentifier; + return fileOrIdentifier; } bool VSTPluginFormat::doesPluginStillExist (const PluginDescription& desc) { - return File (desc.fileOrIdentifier).exists(); + return File (desc.fileOrIdentifier).exists(); } const StringArray VSTPluginFormat::searchPathsForPlugins (const FileSearchPath& directoriesToSearch, const bool recursive) { - StringArray results; + StringArray results; - for (int j = 0; j < directoriesToSearch.getNumPaths(); ++j) - recursiveFileSearch (results, directoriesToSearch [j], recursive); + for (int j = 0; j < directoriesToSearch.getNumPaths(); ++j) + recursiveFileSearch (results, directoriesToSearch [j], recursive); - return results; + return results; } void VSTPluginFormat::recursiveFileSearch (StringArray& results, const File& dir, const bool recursive) { - // avoid allowing the dir iterator to be recursive, because we want to avoid letting it delve inside - // .component or .vst directories. - DirectoryIterator iter (dir, false, "*", File::findFilesAndDirectories); + // avoid allowing the dir iterator to be recursive, because we want to avoid letting it delve inside + // .component or .vst directories. + DirectoryIterator iter (dir, false, "*", File::findFilesAndDirectories); - while (iter.next()) - { - const File f (iter.getFile()); - bool isPlugin = false; + while (iter.next()) + { + const File f (iter.getFile()); + bool isPlugin = false; - if (fileMightContainThisPluginType (f.getFullPathName())) - { - isPlugin = true; - results.add (f.getFullPathName()); - } + if (fileMightContainThisPluginType (f.getFullPathName())) + { + isPlugin = true; + results.add (f.getFullPathName()); + } - if (recursive && (! isPlugin) && f.isDirectory()) - recursiveFileSearch (results, f, true); - } + if (recursive && (! isPlugin) && f.isDirectory()) + recursiveFileSearch (results, f, true); + } } const FileSearchPath VSTPluginFormat::getDefaultLocationsToSearch() { #if JUCE_MAC - return FileSearchPath ("~/Library/Audio/Plug-Ins/VST;/Library/Audio/Plug-Ins/VST"); + return FileSearchPath ("~/Library/Audio/Plug-Ins/VST;/Library/Audio/Plug-Ins/VST"); #elif JUCE_WIN32 - const String programFiles (File::getSpecialLocation (File::globalApplicationsDirectory).getFullPathName()); + const String programFiles (File::getSpecialLocation (File::globalApplicationsDirectory).getFullPathName()); - return FileSearchPath (programFiles + "\\Steinberg\\VstPlugins"); + return FileSearchPath (programFiles + "\\Steinberg\\VstPlugins"); #elif JUCE_LINUX - return FileSearchPath ("/usr/lib/vst"); + return FileSearchPath ("/usr/lib/vst"); #endif } @@ -34792,167 +34501,167 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioProcessor::AudioProcessor() - : playHead (0), - activeEditor (0), - sampleRate (0), - blockSize (0), - numInputChannels (0), - numOutputChannels (0), - latencySamples (0), - suspended (false), - nonRealtime (false) + : playHead (0), + activeEditor (0), + sampleRate (0), + blockSize (0), + numInputChannels (0), + numOutputChannels (0), + latencySamples (0), + suspended (false), + nonRealtime (false) { } AudioProcessor::~AudioProcessor() { - // ooh, nasty - the editor should have been deleted before the filter - // that it refers to is deleted.. - jassert (activeEditor == 0); + // ooh, nasty - the editor should have been deleted before the filter + // that it refers to is deleted.. + jassert (activeEditor == 0); #ifdef JUCE_DEBUG - // This will fail if you've called beginParameterChangeGesture() for one - // or more parameters without having made a corresponding call to endParameterChangeGesture... - jassert (changingParams.countNumberOfSetBits() == 0); + // This will fail if you've called beginParameterChangeGesture() for one + // or more parameters without having made a corresponding call to endParameterChangeGesture... + jassert (changingParams.countNumberOfSetBits() == 0); #endif } void AudioProcessor::setPlayHead (AudioPlayHead* const newPlayHead) throw() { - playHead = newPlayHead; + playHead = newPlayHead; } void AudioProcessor::addListener (AudioProcessorListener* const newListener) throw() { - const ScopedLock sl (listenerLock); - listeners.addIfNotAlreadyThere (newListener); + const ScopedLock sl (listenerLock); + listeners.addIfNotAlreadyThere (newListener); } void AudioProcessor::removeListener (AudioProcessorListener* const listenerToRemove) throw() { - const ScopedLock sl (listenerLock); - listeners.removeValue (listenerToRemove); + const ScopedLock sl (listenerLock); + listeners.removeValue (listenerToRemove); } void AudioProcessor::setPlayConfigDetails (const int numIns, - const int numOuts, - const double sampleRate_, - const int blockSize_) throw() + const int numOuts, + const double sampleRate_, + const int blockSize_) throw() { - numInputChannels = numIns; - numOutputChannels = numOuts; - sampleRate = sampleRate_; - blockSize = blockSize_; + numInputChannels = numIns; + numOutputChannels = numOuts; + sampleRate = sampleRate_; + blockSize = blockSize_; } void AudioProcessor::setNonRealtime (const bool nonRealtime_) throw() { - nonRealtime = nonRealtime_; + nonRealtime = nonRealtime_; } void AudioProcessor::setLatencySamples (const int newLatency) { - if (latencySamples != newLatency) - { - latencySamples = newLatency; - updateHostDisplay(); - } + if (latencySamples != newLatency) + { + latencySamples = newLatency; + updateHostDisplay(); + } } void AudioProcessor::setParameterNotifyingHost (const int parameterIndex, - const float newValue) + const float newValue) { - setParameter (parameterIndex, newValue); - sendParamChangeMessageToListeners (parameterIndex, newValue); + setParameter (parameterIndex, newValue); + sendParamChangeMessageToListeners (parameterIndex, newValue); } void AudioProcessor::sendParamChangeMessageToListeners (const int parameterIndex, const float newValue) { - jassert (((unsigned int) parameterIndex) < (unsigned int) getNumParameters()); + jassert (((unsigned int) parameterIndex) < (unsigned int) getNumParameters()); - for (int i = listeners.size(); --i >= 0;) - { - listenerLock.enter(); - AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i]; - listenerLock.exit(); + for (int i = listeners.size(); --i >= 0;) + { + listenerLock.enter(); + AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i]; + listenerLock.exit(); - if (l != 0) - l->audioProcessorParameterChanged (this, parameterIndex, newValue); - } + if (l != 0) + l->audioProcessorParameterChanged (this, parameterIndex, newValue); + } } void AudioProcessor::beginParameterChangeGesture (int parameterIndex) { - jassert (((unsigned int) parameterIndex) < (unsigned int) getNumParameters()); + jassert (((unsigned int) parameterIndex) < (unsigned int) getNumParameters()); #ifdef JUCE_DEBUG - // This means you've called beginParameterChangeGesture twice in succession without a matching - // call to endParameterChangeGesture. That might be fine in most hosts, but better to avoid doing it. - jassert (! changingParams [parameterIndex]); - changingParams.setBit (parameterIndex); + // This means you've called beginParameterChangeGesture twice in succession without a matching + // call to endParameterChangeGesture. That might be fine in most hosts, but better to avoid doing it. + jassert (! changingParams [parameterIndex]); + changingParams.setBit (parameterIndex); #endif - for (int i = listeners.size(); --i >= 0;) - { - listenerLock.enter(); - AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i]; - listenerLock.exit(); + for (int i = listeners.size(); --i >= 0;) + { + listenerLock.enter(); + AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i]; + listenerLock.exit(); - if (l != 0) - l->audioProcessorParameterChangeGestureBegin (this, parameterIndex); - } + if (l != 0) + l->audioProcessorParameterChangeGestureBegin (this, parameterIndex); + } } void AudioProcessor::endParameterChangeGesture (int parameterIndex) { - jassert (((unsigned int) parameterIndex) < (unsigned int) getNumParameters()); + jassert (((unsigned int) parameterIndex) < (unsigned int) getNumParameters()); #ifdef JUCE_DEBUG - // This means you've called endParameterChangeGesture without having previously called - // endParameterChangeGesture. That might be fine in most hosts, but better to keep the - // calls matched correctly. - jassert (changingParams [parameterIndex]); - changingParams.clearBit (parameterIndex); + // This means you've called endParameterChangeGesture without having previously called + // endParameterChangeGesture. That might be fine in most hosts, but better to keep the + // calls matched correctly. + jassert (changingParams [parameterIndex]); + changingParams.clearBit (parameterIndex); #endif - for (int i = listeners.size(); --i >= 0;) - { - listenerLock.enter(); - AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i]; - listenerLock.exit(); + for (int i = listeners.size(); --i >= 0;) + { + listenerLock.enter(); + AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i]; + listenerLock.exit(); - if (l != 0) - l->audioProcessorParameterChangeGestureEnd (this, parameterIndex); - } + if (l != 0) + l->audioProcessorParameterChangeGestureEnd (this, parameterIndex); + } } void AudioProcessor::updateHostDisplay() { - for (int i = listeners.size(); --i >= 0;) - { - listenerLock.enter(); - AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i]; - listenerLock.exit(); + for (int i = listeners.size(); --i >= 0;) + { + listenerLock.enter(); + AudioProcessorListener* const l = (AudioProcessorListener*) listeners [i]; + listenerLock.exit(); - if (l != 0) - l->audioProcessorChanged (this); - } + if (l != 0) + l->audioProcessorChanged (this); + } } bool AudioProcessor::isParameterAutomatable (int /*parameterIndex*/) const { - return true; + return true; } bool AudioProcessor::isMetaParameter (int /*parameterIndex*/) const { - return false; + return false; } void AudioProcessor::suspendProcessing (const bool shouldBeSuspended) { - const ScopedLock sl (callbackLock); - suspended = shouldBeSuspended; + const ScopedLock sl (callbackLock); + suspended = shouldBeSuspended; } void AudioProcessor::reset() @@ -34961,79 +34670,79 @@ void AudioProcessor::reset() void AudioProcessor::editorBeingDeleted (AudioProcessorEditor* const editor) throw() { - const ScopedLock sl (callbackLock); + const ScopedLock sl (callbackLock); - jassert (activeEditor == editor); + jassert (activeEditor == editor); - if (activeEditor == editor) - activeEditor = 0; + if (activeEditor == editor) + activeEditor = 0; } AudioProcessorEditor* AudioProcessor::createEditorIfNeeded() { - if (activeEditor != 0) - return activeEditor; + if (activeEditor != 0) + return activeEditor; - AudioProcessorEditor* const ed = createEditor(); + AudioProcessorEditor* const ed = createEditor(); - if (ed != 0) - { - // you must give your editor comp a size before returning it.. - jassert (ed->getWidth() > 0 && ed->getHeight() > 0); + if (ed != 0) + { + // you must give your editor comp a size before returning it.. + jassert (ed->getWidth() > 0 && ed->getHeight() > 0); - const ScopedLock sl (callbackLock); - activeEditor = ed; - } + const ScopedLock sl (callbackLock); + activeEditor = ed; + } - return ed; + return ed; } void AudioProcessor::getCurrentProgramStateInformation (JUCE_NAMESPACE::MemoryBlock& destData) { - getStateInformation (destData); + getStateInformation (destData); } void AudioProcessor::setCurrentProgramStateInformation (const void* data, int sizeInBytes) { - setStateInformation (data, sizeInBytes); + setStateInformation (data, sizeInBytes); } // magic number to identify memory blocks that we've stored as XML const uint32 magicXmlNumber = 0x21324356; void AudioProcessor::copyXmlToBinary (const XmlElement& xml, - JUCE_NAMESPACE::MemoryBlock& destData) + JUCE_NAMESPACE::MemoryBlock& destData) { - const String xmlString (xml.createDocument (String::empty, true, false)); - const int stringLength = xmlString.length(); + const String xmlString (xml.createDocument (String::empty, true, false)); + const int stringLength = xmlString.length(); - destData.setSize (stringLength + 10); + destData.setSize (stringLength + 10); - char* const d = (char*) destData.getData(); - *(uint32*) d = ByteOrder::swapIfBigEndian ((const uint32) magicXmlNumber); - *(uint32*) (d + 4) = ByteOrder::swapIfBigEndian ((const uint32) stringLength); + char* const d = (char*) destData.getData(); + *(uint32*) d = ByteOrder::swapIfBigEndian ((const uint32) magicXmlNumber); + *(uint32*) (d + 4) = ByteOrder::swapIfBigEndian ((const uint32) stringLength); - xmlString.copyToBuffer (d + 8, stringLength); + xmlString.copyToBuffer (d + 8, stringLength); } XmlElement* AudioProcessor::getXmlFromBinary (const void* data, - const int sizeInBytes) + const int sizeInBytes) { - if (sizeInBytes > 8 - && ByteOrder::littleEndianInt ((const char*) data) == magicXmlNumber) - { - const uint32 stringLength = ByteOrder::littleEndianInt (((const char*) data) + 4); + if (sizeInBytes > 8 + && ByteOrder::littleEndianInt ((const char*) data) == magicXmlNumber) + { + const int stringLength = (int) ByteOrder::littleEndianInt (((const char*) data) + 4); - if (stringLength > 0) - { - XmlDocument doc (String (((const char*) data) + 8, - jmin ((sizeInBytes - 8), stringLength))); + if (stringLength > 0) + { + XmlDocument doc (String (((const char*) data) + 8, + jmin ((sizeInBytes - 8), stringLength))); - return doc.getDocumentElement(); - } - } + return doc.getDocumentElement(); + } + } - return 0; + return 0; } void AudioProcessorListener::audioProcessorParameterChangeGestureBegin (AudioProcessor*, int) @@ -35052,17 +34761,17 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioProcessorEditor::AudioProcessorEditor (AudioProcessor* const owner_) - : owner (owner_) + : owner (owner_) { - // the filter must be valid.. - jassert (owner != 0); + // the filter must be valid.. + jassert (owner != 0); } AudioProcessorEditor::~AudioProcessorEditor() { - // if this fails, then the wrapper hasn't called editorBeingDeleted() on the - // filter for some reason.. - jassert (owner->getActiveEditor() != this); + // if this fails, then the wrapper hasn't called editorBeingDeleted() on the + // filter for some reason.. + jassert (owner->getActiveEditor() != this); } END_JUCE_NAMESPACE @@ -35075,304 +34784,304 @@ BEGIN_JUCE_NAMESPACE const int AudioProcessorGraph::midiChannelIndex = 0x1000; AudioProcessorGraph::Node::Node (const uint32 id_, AudioProcessor* const processor_) - : id (id_), - processor (processor_), - isPrepared (false) + : id (id_), + processor (processor_), + isPrepared (false) { - jassert (processor_ != 0); + jassert (processor_ != 0); } AudioProcessorGraph::Node::~Node() { - delete processor; + delete processor; } void AudioProcessorGraph::Node::prepare (const double sampleRate, const int blockSize, - AudioProcessorGraph* const graph) + AudioProcessorGraph* const graph) { - if (! isPrepared) - { - isPrepared = true; + if (! isPrepared) + { + isPrepared = true; - AudioProcessorGraph::AudioGraphIOProcessor* const ioProc - = dynamic_cast (processor); + AudioProcessorGraph::AudioGraphIOProcessor* const ioProc + = dynamic_cast (processor); - if (ioProc != 0) - ioProc->setParentGraph (graph); + if (ioProc != 0) + ioProc->setParentGraph (graph); - processor->setPlayConfigDetails (processor->getNumInputChannels(), - processor->getNumOutputChannels(), - sampleRate, blockSize); + processor->setPlayConfigDetails (processor->getNumInputChannels(), + processor->getNumOutputChannels(), + sampleRate, blockSize); - processor->prepareToPlay (sampleRate, blockSize); - } + processor->prepareToPlay (sampleRate, blockSize); + } } void AudioProcessorGraph::Node::unprepare() { - if (isPrepared) - { - isPrepared = false; - processor->releaseResources(); - } + if (isPrepared) + { + isPrepared = false; + processor->releaseResources(); + } } AudioProcessorGraph::AudioProcessorGraph() - : lastNodeId (0), - renderingBuffers (1, 1), - currentAudioOutputBuffer (1, 1) + : lastNodeId (0), + renderingBuffers (1, 1), + currentAudioOutputBuffer (1, 1) { } AudioProcessorGraph::~AudioProcessorGraph() { - clearRenderingSequence(); - clear(); + clearRenderingSequence(); + clear(); } const String AudioProcessorGraph::getName() const { - return "Audio Graph"; + return "Audio Graph"; } void AudioProcessorGraph::clear() { - nodes.clear(); - connections.clear(); - triggerAsyncUpdate(); + nodes.clear(); + connections.clear(); + triggerAsyncUpdate(); } AudioProcessorGraph::Node* AudioProcessorGraph::getNodeForId (const uint32 nodeId) const { - for (int i = nodes.size(); --i >= 0;) - if (nodes.getUnchecked(i)->id == nodeId) - return nodes.getUnchecked(i); + for (int i = nodes.size(); --i >= 0;) + if (nodes.getUnchecked(i)->id == nodeId) + return nodes.getUnchecked(i); - return 0; + return 0; } AudioProcessorGraph::Node* AudioProcessorGraph::addNode (AudioProcessor* const newProcessor, - uint32 nodeId) + uint32 nodeId) { - if (newProcessor == 0) - { - jassertfalse - return 0; - } + if (newProcessor == 0) + { + jassertfalse + return 0; + } - if (nodeId == 0) - { - nodeId = ++lastNodeId; - } - else - { - // you can't add a node with an id that already exists in the graph.. - jassert (getNodeForId (nodeId) == 0); - removeNode (nodeId); - } + if (nodeId == 0) + { + nodeId = ++lastNodeId; + } + else + { + // you can't add a node with an id that already exists in the graph.. + jassert (getNodeForId (nodeId) == 0); + removeNode (nodeId); + } - lastNodeId = nodeId; + lastNodeId = nodeId; - Node* const n = new Node (nodeId, newProcessor); - nodes.add (n); - triggerAsyncUpdate(); + Node* const n = new Node (nodeId, newProcessor); + nodes.add (n); + triggerAsyncUpdate(); - AudioProcessorGraph::AudioGraphIOProcessor* const ioProc - = dynamic_cast (n->processor); + AudioProcessorGraph::AudioGraphIOProcessor* const ioProc + = dynamic_cast (n->processor); - if (ioProc != 0) - ioProc->setParentGraph (this); + if (ioProc != 0) + ioProc->setParentGraph (this); - return n; + return n; } bool AudioProcessorGraph::removeNode (const uint32 nodeId) { - disconnectNode (nodeId); + disconnectNode (nodeId); - for (int i = nodes.size(); --i >= 0;) - { - if (nodes.getUnchecked(i)->id == nodeId) - { - AudioProcessorGraph::AudioGraphIOProcessor* const ioProc - = dynamic_cast (nodes.getUnchecked(i)->processor); + for (int i = nodes.size(); --i >= 0;) + { + if (nodes.getUnchecked(i)->id == nodeId) + { + AudioProcessorGraph::AudioGraphIOProcessor* const ioProc + = dynamic_cast (nodes.getUnchecked(i)->processor); - if (ioProc != 0) - ioProc->setParentGraph (0); + if (ioProc != 0) + ioProc->setParentGraph (0); - nodes.remove (i); - triggerAsyncUpdate(); + nodes.remove (i); + triggerAsyncUpdate(); - return true; - } - } + return true; + } + } - return false; + return false; } const AudioProcessorGraph::Connection* AudioProcessorGraph::getConnectionBetween (const uint32 sourceNodeId, - const int sourceChannelIndex, - const uint32 destNodeId, - const int destChannelIndex) const + const int sourceChannelIndex, + const uint32 destNodeId, + const int destChannelIndex) const { - for (int i = connections.size(); --i >= 0;) - { - const Connection* const c = connections.getUnchecked(i); + for (int i = connections.size(); --i >= 0;) + { + const Connection* const c = connections.getUnchecked(i); - if (c->sourceNodeId == sourceNodeId - && c->destNodeId == destNodeId - && c->sourceChannelIndex == sourceChannelIndex - && c->destChannelIndex == destChannelIndex) - { - return c; - } - } + if (c->sourceNodeId == sourceNodeId + && c->destNodeId == destNodeId + && c->sourceChannelIndex == sourceChannelIndex + && c->destChannelIndex == destChannelIndex) + { + return c; + } + } - return 0; + return 0; } bool AudioProcessorGraph::isConnected (const uint32 possibleSourceNodeId, - const uint32 possibleDestNodeId) const + const uint32 possibleDestNodeId) const { - for (int i = connections.size(); --i >= 0;) - { - const Connection* const c = connections.getUnchecked(i); + for (int i = connections.size(); --i >= 0;) + { + const Connection* const c = connections.getUnchecked(i); - if (c->sourceNodeId == possibleSourceNodeId - && c->destNodeId == possibleDestNodeId) - { - return true; - } - } + if (c->sourceNodeId == possibleSourceNodeId + && c->destNodeId == possibleDestNodeId) + { + return true; + } + } - return false; + return false; } bool AudioProcessorGraph::canConnect (const uint32 sourceNodeId, - const int sourceChannelIndex, - const uint32 destNodeId, - const int destChannelIndex) const + const int sourceChannelIndex, + const uint32 destNodeId, + const int destChannelIndex) const { - if (sourceChannelIndex < 0 - || destChannelIndex < 0 - || sourceNodeId == destNodeId - || (destChannelIndex == midiChannelIndex) != (sourceChannelIndex == midiChannelIndex)) - return false; + if (sourceChannelIndex < 0 + || destChannelIndex < 0 + || sourceNodeId == destNodeId + || (destChannelIndex == midiChannelIndex) != (sourceChannelIndex == midiChannelIndex)) + return false; - const Node* const source = getNodeForId (sourceNodeId); + const Node* const source = getNodeForId (sourceNodeId); - if (source == 0 - || (sourceChannelIndex != midiChannelIndex && sourceChannelIndex >= source->processor->getNumOutputChannels()) - || (sourceChannelIndex == midiChannelIndex && ! source->processor->producesMidi())) - return false; + if (source == 0 + || (sourceChannelIndex != midiChannelIndex && sourceChannelIndex >= source->processor->getNumOutputChannels()) + || (sourceChannelIndex == midiChannelIndex && ! source->processor->producesMidi())) + return false; - const Node* const dest = getNodeForId (destNodeId); + const Node* const dest = getNodeForId (destNodeId); - if (dest == 0 - || (destChannelIndex != midiChannelIndex && destChannelIndex >= dest->processor->getNumInputChannels()) - || (destChannelIndex == midiChannelIndex && ! dest->processor->acceptsMidi())) - return false; + if (dest == 0 + || (destChannelIndex != midiChannelIndex && destChannelIndex >= dest->processor->getNumInputChannels()) + || (destChannelIndex == midiChannelIndex && ! dest->processor->acceptsMidi())) + return false; - return getConnectionBetween (sourceNodeId, sourceChannelIndex, - destNodeId, destChannelIndex) == 0; + return getConnectionBetween (sourceNodeId, sourceChannelIndex, + destNodeId, destChannelIndex) == 0; } bool AudioProcessorGraph::addConnection (const uint32 sourceNodeId, - const int sourceChannelIndex, - const uint32 destNodeId, - const int destChannelIndex) + const int sourceChannelIndex, + const uint32 destNodeId, + const int destChannelIndex) { - if (! canConnect (sourceNodeId, sourceChannelIndex, destNodeId, destChannelIndex)) - return false; + if (! canConnect (sourceNodeId, sourceChannelIndex, destNodeId, destChannelIndex)) + return false; - Connection* const c = new Connection(); - c->sourceNodeId = sourceNodeId; - c->sourceChannelIndex = sourceChannelIndex; - c->destNodeId = destNodeId; - c->destChannelIndex = destChannelIndex; + Connection* const c = new Connection(); + c->sourceNodeId = sourceNodeId; + c->sourceChannelIndex = sourceChannelIndex; + c->destNodeId = destNodeId; + c->destChannelIndex = destChannelIndex; - connections.add (c); - triggerAsyncUpdate(); + connections.add (c); + triggerAsyncUpdate(); - return true; + return true; } void AudioProcessorGraph::removeConnection (const int index) { - connections.remove (index); - triggerAsyncUpdate(); + connections.remove (index); + triggerAsyncUpdate(); } bool AudioProcessorGraph::removeConnection (const uint32 sourceNodeId, const int sourceChannelIndex, - const uint32 destNodeId, const int destChannelIndex) + const uint32 destNodeId, const int destChannelIndex) { - bool doneAnything = false; + bool doneAnything = false; - for (int i = connections.size(); --i >= 0;) - { - const Connection* const c = connections.getUnchecked(i); + for (int i = connections.size(); --i >= 0;) + { + const Connection* const c = connections.getUnchecked(i); - if (c->sourceNodeId == sourceNodeId - && c->destNodeId == destNodeId - && c->sourceChannelIndex == sourceChannelIndex - && c->destChannelIndex == destChannelIndex) - { - removeConnection (i); - doneAnything = true; - triggerAsyncUpdate(); - } - } + if (c->sourceNodeId == sourceNodeId + && c->destNodeId == destNodeId + && c->sourceChannelIndex == sourceChannelIndex + && c->destChannelIndex == destChannelIndex) + { + removeConnection (i); + doneAnything = true; + triggerAsyncUpdate(); + } + } - return doneAnything; + return doneAnything; } bool AudioProcessorGraph::disconnectNode (const uint32 nodeId) { - bool doneAnything = false; + bool doneAnything = false; - for (int i = connections.size(); --i >= 0;) - { - const Connection* const c = connections.getUnchecked(i); + for (int i = connections.size(); --i >= 0;) + { + const Connection* const c = connections.getUnchecked(i); - if (c->sourceNodeId == nodeId || c->destNodeId == nodeId) - { - removeConnection (i); - doneAnything = true; - triggerAsyncUpdate(); - } - } + if (c->sourceNodeId == nodeId || c->destNodeId == nodeId) + { + removeConnection (i); + doneAnything = true; + triggerAsyncUpdate(); + } + } - return doneAnything; + return doneAnything; } bool AudioProcessorGraph::removeIllegalConnections() { - bool doneAnything = false; + bool doneAnything = false; - for (int i = connections.size(); --i >= 0;) - { - const Connection* const c = connections.getUnchecked(i); + for (int i = connections.size(); --i >= 0;) + { + const Connection* const c = connections.getUnchecked(i); - const Node* const source = getNodeForId (c->sourceNodeId); - const Node* const dest = getNodeForId (c->destNodeId); + const Node* const source = getNodeForId (c->sourceNodeId); + const Node* const dest = getNodeForId (c->destNodeId); - if (source == 0 || dest == 0 - || (c->sourceChannelIndex != midiChannelIndex - && (((unsigned int) c->sourceChannelIndex) >= (unsigned int) source->processor->getNumOutputChannels())) - || (c->sourceChannelIndex == midiChannelIndex - && ! source->processor->producesMidi()) - || (c->destChannelIndex != midiChannelIndex - && (((unsigned int) c->destChannelIndex) >= (unsigned int) dest->processor->getNumInputChannels())) - || (c->destChannelIndex == midiChannelIndex - && ! dest->processor->acceptsMidi())) - { - removeConnection (i); - doneAnything = true; - triggerAsyncUpdate(); - } - } + if (source == 0 || dest == 0 + || (c->sourceChannelIndex != midiChannelIndex + && (((unsigned int) c->sourceChannelIndex) >= (unsigned int) source->processor->getNumOutputChannels())) + || (c->sourceChannelIndex == midiChannelIndex + && ! source->processor->producesMidi()) + || (c->destChannelIndex != midiChannelIndex + && (((unsigned int) c->destChannelIndex) >= (unsigned int) dest->processor->getNumInputChannels())) + || (c->destChannelIndex == midiChannelIndex + && ! dest->processor->acceptsMidi())) + { + removeConnection (i); + doneAnything = true; + triggerAsyncUpdate(); + } + } - return doneAnything; + return doneAnything; } namespace GraphRenderingOps @@ -35381,786 +35090,783 @@ namespace GraphRenderingOps class AudioGraphRenderingOp { public: - AudioGraphRenderingOp() {} - virtual ~AudioGraphRenderingOp() {} + AudioGraphRenderingOp() {} + virtual ~AudioGraphRenderingOp() {} - virtual void perform (AudioSampleBuffer& sharedBufferChans, - const OwnedArray & sharedMidiBuffers, - const int numSamples) = 0; + virtual void perform (AudioSampleBuffer& sharedBufferChans, + const OwnedArray & sharedMidiBuffers, + const int numSamples) = 0; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; class ClearChannelOp : public AudioGraphRenderingOp { public: - ClearChannelOp (const int channelNum_) - : channelNum (channelNum_) - {} + ClearChannelOp (const int channelNum_) + : channelNum (channelNum_) + {} - ~ClearChannelOp() {} + ~ClearChannelOp() {} - void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray &, const int numSamples) - { - sharedBufferChans.clear (channelNum, 0, numSamples); - } + void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray &, const int numSamples) + { + sharedBufferChans.clear (channelNum, 0, numSamples); + } private: - const int channelNum; + const int channelNum; - ClearChannelOp (const ClearChannelOp&); - const ClearChannelOp& operator= (const ClearChannelOp&); + ClearChannelOp (const ClearChannelOp&); + const ClearChannelOp& operator= (const ClearChannelOp&); }; class CopyChannelOp : public AudioGraphRenderingOp { public: - CopyChannelOp (const int srcChannelNum_, const int dstChannelNum_) - : srcChannelNum (srcChannelNum_), - dstChannelNum (dstChannelNum_) - {} + CopyChannelOp (const int srcChannelNum_, const int dstChannelNum_) + : srcChannelNum (srcChannelNum_), + dstChannelNum (dstChannelNum_) + {} - ~CopyChannelOp() {} + ~CopyChannelOp() {} - void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray &, const int numSamples) - { - sharedBufferChans.copyFrom (dstChannelNum, 0, sharedBufferChans, srcChannelNum, 0, numSamples); - } + void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray &, const int numSamples) + { + sharedBufferChans.copyFrom (dstChannelNum, 0, sharedBufferChans, srcChannelNum, 0, numSamples); + } private: - const int srcChannelNum, dstChannelNum; + const int srcChannelNum, dstChannelNum; - CopyChannelOp (const CopyChannelOp&); - const CopyChannelOp& operator= (const CopyChannelOp&); + CopyChannelOp (const CopyChannelOp&); + const CopyChannelOp& operator= (const CopyChannelOp&); }; class AddChannelOp : public AudioGraphRenderingOp { public: - AddChannelOp (const int srcChannelNum_, const int dstChannelNum_) - : srcChannelNum (srcChannelNum_), - dstChannelNum (dstChannelNum_) - {} + AddChannelOp (const int srcChannelNum_, const int dstChannelNum_) + : srcChannelNum (srcChannelNum_), + dstChannelNum (dstChannelNum_) + {} - ~AddChannelOp() {} + ~AddChannelOp() {} - void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray &, const int numSamples) - { - sharedBufferChans.addFrom (dstChannelNum, 0, sharedBufferChans, srcChannelNum, 0, numSamples); - } + void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray &, const int numSamples) + { + sharedBufferChans.addFrom (dstChannelNum, 0, sharedBufferChans, srcChannelNum, 0, numSamples); + } private: - const int srcChannelNum, dstChannelNum; + const int srcChannelNum, dstChannelNum; - AddChannelOp (const AddChannelOp&); - const AddChannelOp& operator= (const AddChannelOp&); + AddChannelOp (const AddChannelOp&); + const AddChannelOp& operator= (const AddChannelOp&); }; class ClearMidiBufferOp : public AudioGraphRenderingOp { public: - ClearMidiBufferOp (const int bufferNum_) - : bufferNum (bufferNum_) - {} + ClearMidiBufferOp (const int bufferNum_) + : bufferNum (bufferNum_) + {} - ~ClearMidiBufferOp() {} + ~ClearMidiBufferOp() {} - void perform (AudioSampleBuffer&, const OwnedArray & sharedMidiBuffers, const int) - { - sharedMidiBuffers.getUnchecked (bufferNum)->clear(); - } + void perform (AudioSampleBuffer&, const OwnedArray & sharedMidiBuffers, const int) + { + sharedMidiBuffers.getUnchecked (bufferNum)->clear(); + } private: - const int bufferNum; + const int bufferNum; - ClearMidiBufferOp (const ClearMidiBufferOp&); - const ClearMidiBufferOp& operator= (const ClearMidiBufferOp&); + ClearMidiBufferOp (const ClearMidiBufferOp&); + const ClearMidiBufferOp& operator= (const ClearMidiBufferOp&); }; class CopyMidiBufferOp : public AudioGraphRenderingOp { public: - CopyMidiBufferOp (const int srcBufferNum_, const int dstBufferNum_) - : srcBufferNum (srcBufferNum_), - dstBufferNum (dstBufferNum_) - {} + CopyMidiBufferOp (const int srcBufferNum_, const int dstBufferNum_) + : srcBufferNum (srcBufferNum_), + dstBufferNum (dstBufferNum_) + {} - ~CopyMidiBufferOp() {} + ~CopyMidiBufferOp() {} - void perform (AudioSampleBuffer&, const OwnedArray & sharedMidiBuffers, const int) - { - *sharedMidiBuffers.getUnchecked (dstBufferNum) = *sharedMidiBuffers.getUnchecked (srcBufferNum); - } + void perform (AudioSampleBuffer&, const OwnedArray & sharedMidiBuffers, const int) + { + *sharedMidiBuffers.getUnchecked (dstBufferNum) = *sharedMidiBuffers.getUnchecked (srcBufferNum); + } private: - const int srcBufferNum, dstBufferNum; + const int srcBufferNum, dstBufferNum; - CopyMidiBufferOp (const CopyMidiBufferOp&); - const CopyMidiBufferOp& operator= (const CopyMidiBufferOp&); + CopyMidiBufferOp (const CopyMidiBufferOp&); + const CopyMidiBufferOp& operator= (const CopyMidiBufferOp&); }; class AddMidiBufferOp : public AudioGraphRenderingOp { public: - AddMidiBufferOp (const int srcBufferNum_, const int dstBufferNum_) - : srcBufferNum (srcBufferNum_), - dstBufferNum (dstBufferNum_) - {} + AddMidiBufferOp (const int srcBufferNum_, const int dstBufferNum_) + : srcBufferNum (srcBufferNum_), + dstBufferNum (dstBufferNum_) + {} - ~AddMidiBufferOp() {} + ~AddMidiBufferOp() {} - void perform (AudioSampleBuffer&, const OwnedArray & sharedMidiBuffers, const int numSamples) - { - sharedMidiBuffers.getUnchecked (dstBufferNum) - ->addEvents (*sharedMidiBuffers.getUnchecked (srcBufferNum), 0, numSamples, 0); - } + void perform (AudioSampleBuffer&, const OwnedArray & sharedMidiBuffers, const int numSamples) + { + sharedMidiBuffers.getUnchecked (dstBufferNum) + ->addEvents (*sharedMidiBuffers.getUnchecked (srcBufferNum), 0, numSamples, 0); + } private: - const int srcBufferNum, dstBufferNum; + const int srcBufferNum, dstBufferNum; - AddMidiBufferOp (const AddMidiBufferOp&); - const AddMidiBufferOp& operator= (const AddMidiBufferOp&); + AddMidiBufferOp (const AddMidiBufferOp&); + const AddMidiBufferOp& operator= (const AddMidiBufferOp&); }; class ProcessBufferOp : public AudioGraphRenderingOp { public: - ProcessBufferOp (const AudioProcessorGraph::Node::Ptr& node_, - const Array & audioChannelsToUse_, - const int totalChans_, - const int midiBufferToUse_) - : node (node_), - processor (node_->processor), - audioChannelsToUse (audioChannelsToUse_), - totalChans (jmax (1, totalChans_)), - midiBufferToUse (midiBufferToUse_) - { - channels.calloc (totalChans); + ProcessBufferOp (const AudioProcessorGraph::Node::Ptr& node_, + const Array & audioChannelsToUse_, + const int totalChans_, + const int midiBufferToUse_) + : node (node_), + processor (node_->processor), + audioChannelsToUse (audioChannelsToUse_), + totalChans (jmax (1, totalChans_)), + midiBufferToUse (midiBufferToUse_) + { + channels.calloc (totalChans); - while (audioChannelsToUse.size() < totalChans) - audioChannelsToUse.add (0); - } + while (audioChannelsToUse.size() < totalChans) + audioChannelsToUse.add (0); + } - ~ProcessBufferOp() - { - } + ~ProcessBufferOp() + { + } - void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray & sharedMidiBuffers, const int numSamples) - { - for (int i = totalChans; --i >= 0;) - channels[i] = sharedBufferChans.getSampleData (audioChannelsToUse.getUnchecked (i), 0); + void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray & sharedMidiBuffers, const int numSamples) + { + for (int i = totalChans; --i >= 0;) + channels[i] = sharedBufferChans.getSampleData (audioChannelsToUse.getUnchecked (i), 0); - AudioSampleBuffer buffer (channels, totalChans, numSamples); + AudioSampleBuffer buffer (channels, totalChans, numSamples); - processor->processBlock (buffer, *sharedMidiBuffers.getUnchecked (midiBufferToUse)); - } + processor->processBlock (buffer, *sharedMidiBuffers.getUnchecked (midiBufferToUse)); + } - const AudioProcessorGraph::Node::Ptr node; - AudioProcessor* const processor; + const AudioProcessorGraph::Node::Ptr node; + AudioProcessor* const processor; private: - Array audioChannelsToUse; - HeapBlock channels; - int totalChans; - int midiBufferToUse; + Array audioChannelsToUse; + HeapBlock channels; + int totalChans; + int midiBufferToUse; - ProcessBufferOp (const ProcessBufferOp&); - const ProcessBufferOp& operator= (const ProcessBufferOp&); + ProcessBufferOp (const ProcessBufferOp&); + const ProcessBufferOp& operator= (const ProcessBufferOp&); }; -/** Used to calculate the correct sequence of rendering ops needed, based on - the best re-use of shared buffers at each stage. -*/ class RenderingOpSequenceCalculator { public: - RenderingOpSequenceCalculator (AudioProcessorGraph& graph_, - const VoidArray& orderedNodes_, - VoidArray& renderingOps) - : graph (graph_), - orderedNodes (orderedNodes_) - { - nodeIds.add (-2); // first buffer is read-only zeros - channels.add (0); + RenderingOpSequenceCalculator (AudioProcessorGraph& graph_, + const VoidArray& orderedNodes_, + VoidArray& renderingOps) + : graph (graph_), + orderedNodes (orderedNodes_) + { + nodeIds.add (-2); // first buffer is read-only zeros + channels.add (0); - midiNodeIds.add (-2); + midiNodeIds.add (-2); - for (int i = 0; i < orderedNodes.size(); ++i) - { - createRenderingOpsForNode ((AudioProcessorGraph::Node*) orderedNodes.getUnchecked(i), - renderingOps, i); + for (int i = 0; i < orderedNodes.size(); ++i) + { + createRenderingOpsForNode ((AudioProcessorGraph::Node*) orderedNodes.getUnchecked(i), + renderingOps, i); - markAnyUnusedBuffersAsFree (i); - } - } + markAnyUnusedBuffersAsFree (i); + } + } - int getNumBuffersNeeded() const { return nodeIds.size(); } + int getNumBuffersNeeded() const { return nodeIds.size(); } - int getNumMidiBuffersNeeded() const { return midiNodeIds.size(); } + int getNumMidiBuffersNeeded() const { return midiNodeIds.size(); } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioProcessorGraph& graph; - const VoidArray& orderedNodes; - Array nodeIds, channels, midiNodeIds; + AudioProcessorGraph& graph; + const VoidArray& orderedNodes; + Array nodeIds, channels, midiNodeIds; - void createRenderingOpsForNode (AudioProcessorGraph::Node* const node, - VoidArray& renderingOps, - const int ourRenderingIndex) - { - const int numIns = node->processor->getNumInputChannels(); - const int numOuts = node->processor->getNumOutputChannels(); - const int totalChans = jmax (numIns, numOuts); + void createRenderingOpsForNode (AudioProcessorGraph::Node* const node, + VoidArray& renderingOps, + const int ourRenderingIndex) + { + const int numIns = node->processor->getNumInputChannels(); + const int numOuts = node->processor->getNumOutputChannels(); + const int totalChans = jmax (numIns, numOuts); - Array audioChannelsToUse; - int midiBufferToUse = -1; + Array audioChannelsToUse; + int midiBufferToUse = -1; - for (int inputChan = 0; inputChan < numIns; ++inputChan) - { - // get a list of all the inputs to this node - Array sourceNodes, sourceOutputChans; + for (int inputChan = 0; inputChan < numIns; ++inputChan) + { + // get a list of all the inputs to this node + Array sourceNodes, sourceOutputChans; - for (int i = graph.getNumConnections(); --i >= 0;) - { - const AudioProcessorGraph::Connection* const c = graph.getConnection (i); + for (int i = graph.getNumConnections(); --i >= 0;) + { + const AudioProcessorGraph::Connection* const c = graph.getConnection (i); - if (c->destNodeId == node->id && c->destChannelIndex == inputChan) - { - sourceNodes.add (c->sourceNodeId); - sourceOutputChans.add (c->sourceChannelIndex); - } - } + if (c->destNodeId == node->id && c->destChannelIndex == inputChan) + { + sourceNodes.add (c->sourceNodeId); + sourceOutputChans.add (c->sourceChannelIndex); + } + } - int bufIndex = -1; + int bufIndex = -1; - if (sourceNodes.size() == 0) - { - // unconnected input channel + if (sourceNodes.size() == 0) + { + // unconnected input channel - if (inputChan >= numOuts) - { - bufIndex = getReadOnlyEmptyBuffer(); - jassert (bufIndex >= 0); - } - else - { - bufIndex = getFreeBuffer (false); - renderingOps.add (new ClearChannelOp (bufIndex)); - } - } - else if (sourceNodes.size() == 1) - { - // channel with a straightforward single input.. - const int srcNode = sourceNodes.getUnchecked(0); - const int srcChan = sourceOutputChans.getUnchecked(0); + if (inputChan >= numOuts) + { + bufIndex = getReadOnlyEmptyBuffer(); + jassert (bufIndex >= 0); + } + else + { + bufIndex = getFreeBuffer (false); + renderingOps.add (new ClearChannelOp (bufIndex)); + } + } + else if (sourceNodes.size() == 1) + { + // channel with a straightforward single input.. + const int srcNode = sourceNodes.getUnchecked(0); + const int srcChan = sourceOutputChans.getUnchecked(0); - bufIndex = getBufferContaining (srcNode, srcChan); + bufIndex = getBufferContaining (srcNode, srcChan); - if (bufIndex < 0) - { - // if not found, this is probably a feedback loop - bufIndex = getReadOnlyEmptyBuffer(); - jassert (bufIndex >= 0); - } + if (bufIndex < 0) + { + // if not found, this is probably a feedback loop + bufIndex = getReadOnlyEmptyBuffer(); + jassert (bufIndex >= 0); + } - if (inputChan < numOuts - && isBufferNeededLater (ourRenderingIndex, - inputChan, - srcNode, srcChan)) - { - // can't mess up this channel because it's needed later by another node, so we - // need to use a copy of it.. - const int newFreeBuffer = getFreeBuffer (false); + if (inputChan < numOuts + && isBufferNeededLater (ourRenderingIndex, + inputChan, + srcNode, srcChan)) + { + // can't mess up this channel because it's needed later by another node, so we + // need to use a copy of it.. + const int newFreeBuffer = getFreeBuffer (false); - renderingOps.add (new CopyChannelOp (bufIndex, newFreeBuffer)); + renderingOps.add (new CopyChannelOp (bufIndex, newFreeBuffer)); - bufIndex = newFreeBuffer; - } - } - else - { - // channel with a mix of several inputs.. + bufIndex = newFreeBuffer; + } + } + else + { + // channel with a mix of several inputs.. - // try to find a re-usable channel from our inputs.. - int reusableInputIndex = -1; + // try to find a re-usable channel from our inputs.. + int reusableInputIndex = -1; - for (int i = 0; i < sourceNodes.size(); ++i) - { - const int sourceBufIndex = getBufferContaining (sourceNodes.getUnchecked(i), - sourceOutputChans.getUnchecked(i)); + for (int i = 0; i < sourceNodes.size(); ++i) + { + const int sourceBufIndex = getBufferContaining (sourceNodes.getUnchecked(i), + sourceOutputChans.getUnchecked(i)); - if (sourceBufIndex >= 0 - && ! isBufferNeededLater (ourRenderingIndex, - inputChan, - sourceNodes.getUnchecked(i), - sourceOutputChans.getUnchecked(i))) - { - // we've found one of our input chans that can be re-used.. - reusableInputIndex = i; - bufIndex = sourceBufIndex; - break; - } - } + if (sourceBufIndex >= 0 + && ! isBufferNeededLater (ourRenderingIndex, + inputChan, + sourceNodes.getUnchecked(i), + sourceOutputChans.getUnchecked(i))) + { + // we've found one of our input chans that can be re-used.. + reusableInputIndex = i; + bufIndex = sourceBufIndex; + break; + } + } - if (reusableInputIndex < 0) - { - // can't re-use any of our input chans, so get a new one and copy everything into it.. - bufIndex = getFreeBuffer (false); - jassert (bufIndex != 0); + if (reusableInputIndex < 0) + { + // can't re-use any of our input chans, so get a new one and copy everything into it.. + bufIndex = getFreeBuffer (false); + jassert (bufIndex != 0); - const int srcIndex = getBufferContaining (sourceNodes.getUnchecked (0), - sourceOutputChans.getUnchecked (0)); - if (srcIndex < 0) - { - // if not found, this is probably a feedback loop - renderingOps.add (new ClearChannelOp (bufIndex)); - } - else - { - renderingOps.add (new CopyChannelOp (srcIndex, bufIndex)); - } + const int srcIndex = getBufferContaining (sourceNodes.getUnchecked (0), + sourceOutputChans.getUnchecked (0)); + if (srcIndex < 0) + { + // if not found, this is probably a feedback loop + renderingOps.add (new ClearChannelOp (bufIndex)); + } + else + { + renderingOps.add (new CopyChannelOp (srcIndex, bufIndex)); + } - reusableInputIndex = 0; - } + reusableInputIndex = 0; + } - for (int j = 0; j < sourceNodes.size(); ++j) - { - if (j != reusableInputIndex) - { - const int srcIndex = getBufferContaining (sourceNodes.getUnchecked(j), - sourceOutputChans.getUnchecked(j)); - if (srcIndex >= 0) - renderingOps.add (new AddChannelOp (srcIndex, bufIndex)); - } - } - } + for (int j = 0; j < sourceNodes.size(); ++j) + { + if (j != reusableInputIndex) + { + const int srcIndex = getBufferContaining (sourceNodes.getUnchecked(j), + sourceOutputChans.getUnchecked(j)); + if (srcIndex >= 0) + renderingOps.add (new AddChannelOp (srcIndex, bufIndex)); + } + } + } - jassert (bufIndex >= 0); - audioChannelsToUse.add (bufIndex); + jassert (bufIndex >= 0); + audioChannelsToUse.add (bufIndex); - if (inputChan < numOuts) - markBufferAsContaining (bufIndex, node->id, inputChan); - } + if (inputChan < numOuts) + markBufferAsContaining (bufIndex, node->id, inputChan); + } - for (int outputChan = numIns; outputChan < numOuts; ++outputChan) - { - const int bufIndex = getFreeBuffer (false); - jassert (bufIndex != 0); - audioChannelsToUse.add (bufIndex); + for (int outputChan = numIns; outputChan < numOuts; ++outputChan) + { + const int bufIndex = getFreeBuffer (false); + jassert (bufIndex != 0); + audioChannelsToUse.add (bufIndex); - markBufferAsContaining (bufIndex, node->id, outputChan); - } + markBufferAsContaining (bufIndex, node->id, outputChan); + } - // Now the same thing for midi.. - Array midiSourceNodes; + // Now the same thing for midi.. + Array midiSourceNodes; - for (int i = graph.getNumConnections(); --i >= 0;) - { - const AudioProcessorGraph::Connection* const c = graph.getConnection (i); + for (int i = graph.getNumConnections(); --i >= 0;) + { + const AudioProcessorGraph::Connection* const c = graph.getConnection (i); - if (c->destNodeId == node->id && c->destChannelIndex == AudioProcessorGraph::midiChannelIndex) - midiSourceNodes.add (c->sourceNodeId); - } + if (c->destNodeId == node->id && c->destChannelIndex == AudioProcessorGraph::midiChannelIndex) + midiSourceNodes.add (c->sourceNodeId); + } - if (midiSourceNodes.size() == 0) - { - // No midi inputs.. - midiBufferToUse = getFreeBuffer (true); // need to pick a buffer even if the processor doesn't use midi + if (midiSourceNodes.size() == 0) + { + // No midi inputs.. + midiBufferToUse = getFreeBuffer (true); // need to pick a buffer even if the processor doesn't use midi - if (node->processor->acceptsMidi() || node->processor->producesMidi()) - renderingOps.add (new ClearMidiBufferOp (midiBufferToUse)); - } - else if (midiSourceNodes.size() == 1) - { - // One midi input.. - midiBufferToUse = getBufferContaining (midiSourceNodes.getUnchecked(0), - AudioProcessorGraph::midiChannelIndex); + if (node->processor->acceptsMidi() || node->processor->producesMidi()) + renderingOps.add (new ClearMidiBufferOp (midiBufferToUse)); + } + else if (midiSourceNodes.size() == 1) + { + // One midi input.. + midiBufferToUse = getBufferContaining (midiSourceNodes.getUnchecked(0), + AudioProcessorGraph::midiChannelIndex); - if (midiBufferToUse >= 0) - { - if (isBufferNeededLater (ourRenderingIndex, - AudioProcessorGraph::midiChannelIndex, - midiSourceNodes.getUnchecked(0), - AudioProcessorGraph::midiChannelIndex)) - { - // can't mess up this channel because it's needed later by another node, so we - // need to use a copy of it.. - const int newFreeBuffer = getFreeBuffer (true); - renderingOps.add (new CopyMidiBufferOp (midiBufferToUse, newFreeBuffer)); - midiBufferToUse = newFreeBuffer; - } - } - else - { - // probably a feedback loop, so just use an empty one.. - midiBufferToUse = getFreeBuffer (true); // need to pick a buffer even if the processor doesn't use midi - } - } - else - { - // More than one midi input being mixed.. - int reusableInputIndex = -1; + if (midiBufferToUse >= 0) + { + if (isBufferNeededLater (ourRenderingIndex, + AudioProcessorGraph::midiChannelIndex, + midiSourceNodes.getUnchecked(0), + AudioProcessorGraph::midiChannelIndex)) + { + // can't mess up this channel because it's needed later by another node, so we + // need to use a copy of it.. + const int newFreeBuffer = getFreeBuffer (true); + renderingOps.add (new CopyMidiBufferOp (midiBufferToUse, newFreeBuffer)); + midiBufferToUse = newFreeBuffer; + } + } + else + { + // probably a feedback loop, so just use an empty one.. + midiBufferToUse = getFreeBuffer (true); // need to pick a buffer even if the processor doesn't use midi + } + } + else + { + // More than one midi input being mixed.. + int reusableInputIndex = -1; - for (int i = 0; i < midiSourceNodes.size(); ++i) - { - const int sourceBufIndex = getBufferContaining (midiSourceNodes.getUnchecked(i), - AudioProcessorGraph::midiChannelIndex); + for (int i = 0; i < midiSourceNodes.size(); ++i) + { + const int sourceBufIndex = getBufferContaining (midiSourceNodes.getUnchecked(i), + AudioProcessorGraph::midiChannelIndex); - if (sourceBufIndex >= 0 - && ! isBufferNeededLater (ourRenderingIndex, - AudioProcessorGraph::midiChannelIndex, - midiSourceNodes.getUnchecked(i), - AudioProcessorGraph::midiChannelIndex)) - { - // we've found one of our input buffers that can be re-used.. - reusableInputIndex = i; - midiBufferToUse = sourceBufIndex; - break; - } - } + if (sourceBufIndex >= 0 + && ! isBufferNeededLater (ourRenderingIndex, + AudioProcessorGraph::midiChannelIndex, + midiSourceNodes.getUnchecked(i), + AudioProcessorGraph::midiChannelIndex)) + { + // we've found one of our input buffers that can be re-used.. + reusableInputIndex = i; + midiBufferToUse = sourceBufIndex; + break; + } + } - if (reusableInputIndex < 0) - { - // can't re-use any of our input buffers, so get a new one and copy everything into it.. - midiBufferToUse = getFreeBuffer (true); - jassert (midiBufferToUse >= 0); + if (reusableInputIndex < 0) + { + // can't re-use any of our input buffers, so get a new one and copy everything into it.. + midiBufferToUse = getFreeBuffer (true); + jassert (midiBufferToUse >= 0); - const int srcIndex = getBufferContaining (midiSourceNodes.getUnchecked(0), - AudioProcessorGraph::midiChannelIndex); - if (srcIndex >= 0) - renderingOps.add (new CopyMidiBufferOp (srcIndex, midiBufferToUse)); - else - renderingOps.add (new ClearMidiBufferOp (midiBufferToUse)); + const int srcIndex = getBufferContaining (midiSourceNodes.getUnchecked(0), + AudioProcessorGraph::midiChannelIndex); + if (srcIndex >= 0) + renderingOps.add (new CopyMidiBufferOp (srcIndex, midiBufferToUse)); + else + renderingOps.add (new ClearMidiBufferOp (midiBufferToUse)); - reusableInputIndex = 0; - } + reusableInputIndex = 0; + } - for (int j = 0; j < midiSourceNodes.size(); ++j) - { - if (j != reusableInputIndex) - { - const int srcIndex = getBufferContaining (midiSourceNodes.getUnchecked(j), - AudioProcessorGraph::midiChannelIndex); - if (srcIndex >= 0) - renderingOps.add (new AddMidiBufferOp (srcIndex, midiBufferToUse)); - } - } - } + for (int j = 0; j < midiSourceNodes.size(); ++j) + { + if (j != reusableInputIndex) + { + const int srcIndex = getBufferContaining (midiSourceNodes.getUnchecked(j), + AudioProcessorGraph::midiChannelIndex); + if (srcIndex >= 0) + renderingOps.add (new AddMidiBufferOp (srcIndex, midiBufferToUse)); + } + } + } - if (node->processor->producesMidi()) - markBufferAsContaining (midiBufferToUse, node->id, - AudioProcessorGraph::midiChannelIndex); + if (node->processor->producesMidi()) + markBufferAsContaining (midiBufferToUse, node->id, + AudioProcessorGraph::midiChannelIndex); - renderingOps.add (new ProcessBufferOp (node, audioChannelsToUse, - totalChans, midiBufferToUse)); - } + renderingOps.add (new ProcessBufferOp (node, audioChannelsToUse, + totalChans, midiBufferToUse)); + } - int getFreeBuffer (const bool forMidi) - { - if (forMidi) - { - for (int i = 1; i < midiNodeIds.size(); ++i) - if (midiNodeIds.getUnchecked(i) < 0) - return i; + int getFreeBuffer (const bool forMidi) + { + if (forMidi) + { + for (int i = 1; i < midiNodeIds.size(); ++i) + if (midiNodeIds.getUnchecked(i) < 0) + return i; - midiNodeIds.add (-1); - return midiNodeIds.size() - 1; - } - else - { - for (int i = 1; i < nodeIds.size(); ++i) - if (nodeIds.getUnchecked(i) < 0) - return i; + midiNodeIds.add (-1); + return midiNodeIds.size() - 1; + } + else + { + for (int i = 1; i < nodeIds.size(); ++i) + if (nodeIds.getUnchecked(i) < 0) + return i; - nodeIds.add (-1); - channels.add (0); - return nodeIds.size() - 1; - } - } + nodeIds.add (-1); + channels.add (0); + return nodeIds.size() - 1; + } + } - int getReadOnlyEmptyBuffer() const - { - return 0; - } + int getReadOnlyEmptyBuffer() const + { + return 0; + } - int getBufferContaining (const int nodeId, const int outputChannel) const - { - if (outputChannel == AudioProcessorGraph::midiChannelIndex) - { - for (int i = midiNodeIds.size(); --i >= 0;) - if (midiNodeIds.getUnchecked(i) == nodeId) - return i; - } - else - { - for (int i = nodeIds.size(); --i >= 0;) - if (nodeIds.getUnchecked(i) == nodeId - && channels.getUnchecked(i) == outputChannel) - return i; - } + int getBufferContaining (const int nodeId, const int outputChannel) const + { + if (outputChannel == AudioProcessorGraph::midiChannelIndex) + { + for (int i = midiNodeIds.size(); --i >= 0;) + if (midiNodeIds.getUnchecked(i) == nodeId) + return i; + } + else + { + for (int i = nodeIds.size(); --i >= 0;) + if (nodeIds.getUnchecked(i) == nodeId + && channels.getUnchecked(i) == outputChannel) + return i; + } - return -1; - } + return -1; + } - void markAnyUnusedBuffersAsFree (const int stepIndex) - { - int i; - for (i = 0; i < nodeIds.size(); ++i) - { - if (nodeIds.getUnchecked(i) >= 0 - && ! isBufferNeededLater (stepIndex, -1, - nodeIds.getUnchecked(i), - channels.getUnchecked(i))) - { - nodeIds.set (i, -1); - } - } + void markAnyUnusedBuffersAsFree (const int stepIndex) + { + int i; + for (i = 0; i < nodeIds.size(); ++i) + { + if (nodeIds.getUnchecked(i) >= 0 + && ! isBufferNeededLater (stepIndex, -1, + nodeIds.getUnchecked(i), + channels.getUnchecked(i))) + { + nodeIds.set (i, -1); + } + } - for (i = 0; i < midiNodeIds.size(); ++i) - { - if (midiNodeIds.getUnchecked(i) >= 0 - && ! isBufferNeededLater (stepIndex, -1, - midiNodeIds.getUnchecked(i), - AudioProcessorGraph::midiChannelIndex)) - { - midiNodeIds.set (i, -1); - } - } - } + for (i = 0; i < midiNodeIds.size(); ++i) + { + if (midiNodeIds.getUnchecked(i) >= 0 + && ! isBufferNeededLater (stepIndex, -1, + midiNodeIds.getUnchecked(i), + AudioProcessorGraph::midiChannelIndex)) + { + midiNodeIds.set (i, -1); + } + } + } - bool isBufferNeededLater (int stepIndexToSearchFrom, - int inputChannelOfIndexToIgnore, - const int nodeId, - const int outputChanIndex) const - { - while (stepIndexToSearchFrom < orderedNodes.size()) - { - const AudioProcessorGraph::Node* const node = (const AudioProcessorGraph::Node*) orderedNodes.getUnchecked (stepIndexToSearchFrom); + bool isBufferNeededLater (int stepIndexToSearchFrom, + int inputChannelOfIndexToIgnore, + const int nodeId, + const int outputChanIndex) const + { + while (stepIndexToSearchFrom < orderedNodes.size()) + { + const AudioProcessorGraph::Node* const node = (const AudioProcessorGraph::Node*) orderedNodes.getUnchecked (stepIndexToSearchFrom); - if (outputChanIndex == AudioProcessorGraph::midiChannelIndex) - { - if (inputChannelOfIndexToIgnore != AudioProcessorGraph::midiChannelIndex - && graph.getConnectionBetween (nodeId, AudioProcessorGraph::midiChannelIndex, - node->id, AudioProcessorGraph::midiChannelIndex) != 0) - return true; - } - else - { - for (int i = 0; i < node->processor->getNumInputChannels(); ++i) - if (i != inputChannelOfIndexToIgnore - && graph.getConnectionBetween (nodeId, outputChanIndex, - node->id, i) != 0) - return true; - } + if (outputChanIndex == AudioProcessorGraph::midiChannelIndex) + { + if (inputChannelOfIndexToIgnore != AudioProcessorGraph::midiChannelIndex + && graph.getConnectionBetween (nodeId, AudioProcessorGraph::midiChannelIndex, + node->id, AudioProcessorGraph::midiChannelIndex) != 0) + return true; + } + else + { + for (int i = 0; i < node->processor->getNumInputChannels(); ++i) + if (i != inputChannelOfIndexToIgnore + && graph.getConnectionBetween (nodeId, outputChanIndex, + node->id, i) != 0) + return true; + } - inputChannelOfIndexToIgnore = -1; - ++stepIndexToSearchFrom; - } + inputChannelOfIndexToIgnore = -1; + ++stepIndexToSearchFrom; + } - return false; - } + return false; + } - void markBufferAsContaining (int bufferNum, int nodeId, int outputIndex) - { - if (outputIndex == AudioProcessorGraph::midiChannelIndex) - { - jassert (bufferNum > 0 && bufferNum < midiNodeIds.size()); + void markBufferAsContaining (int bufferNum, int nodeId, int outputIndex) + { + if (outputIndex == AudioProcessorGraph::midiChannelIndex) + { + jassert (bufferNum > 0 && bufferNum < midiNodeIds.size()); - midiNodeIds.set (bufferNum, nodeId); - } - else - { - jassert (bufferNum >= 0 && bufferNum < nodeIds.size()); + midiNodeIds.set (bufferNum, nodeId); + } + else + { + jassert (bufferNum >= 0 && bufferNum < nodeIds.size()); - nodeIds.set (bufferNum, nodeId); - channels.set (bufferNum, outputIndex); - } - } + nodeIds.set (bufferNum, nodeId); + channels.set (bufferNum, outputIndex); + } + } - RenderingOpSequenceCalculator (const RenderingOpSequenceCalculator&); - const RenderingOpSequenceCalculator& operator= (const RenderingOpSequenceCalculator&); + RenderingOpSequenceCalculator (const RenderingOpSequenceCalculator&); + const RenderingOpSequenceCalculator& operator= (const RenderingOpSequenceCalculator&); }; } void AudioProcessorGraph::clearRenderingSequence() { - const ScopedLock sl (renderLock); + const ScopedLock sl (renderLock); - for (int i = renderingOps.size(); --i >= 0;) - { - GraphRenderingOps::AudioGraphRenderingOp* const r - = (GraphRenderingOps::AudioGraphRenderingOp*) renderingOps.getUnchecked(i); + for (int i = renderingOps.size(); --i >= 0;) + { + GraphRenderingOps::AudioGraphRenderingOp* const r + = (GraphRenderingOps::AudioGraphRenderingOp*) renderingOps.getUnchecked(i); - renderingOps.remove (i); - delete r; - } + renderingOps.remove (i); + delete r; + } } bool AudioProcessorGraph::isAnInputTo (const uint32 possibleInputId, - const uint32 possibleDestinationId, - const int recursionCheck) const + const uint32 possibleDestinationId, + const int recursionCheck) const { - if (recursionCheck > 0) - { - for (int i = connections.size(); --i >= 0;) - { - const AudioProcessorGraph::Connection* const c = connections.getUnchecked (i); + if (recursionCheck > 0) + { + for (int i = connections.size(); --i >= 0;) + { + const AudioProcessorGraph::Connection* const c = connections.getUnchecked (i); - if (c->destNodeId == possibleDestinationId - && (c->sourceNodeId == possibleInputId - || isAnInputTo (possibleInputId, c->sourceNodeId, recursionCheck - 1))) - return true; - } - } + if (c->destNodeId == possibleDestinationId + && (c->sourceNodeId == possibleInputId + || isAnInputTo (possibleInputId, c->sourceNodeId, recursionCheck - 1))) + return true; + } + } - return false; + return false; } void AudioProcessorGraph::buildRenderingSequence() { - VoidArray newRenderingOps; - int numRenderingBuffersNeeded = 2; - int numMidiBuffersNeeded = 1; + VoidArray newRenderingOps; + int numRenderingBuffersNeeded = 2; + int numMidiBuffersNeeded = 1; - { - MessageManagerLock mml; + { + MessageManagerLock mml; - VoidArray orderedNodes; + VoidArray orderedNodes; - int i; - for (i = 0; i < nodes.size(); ++i) - { - Node* const node = nodes.getUnchecked(i); + int i; + for (i = 0; i < nodes.size(); ++i) + { + Node* const node = nodes.getUnchecked(i); - node->prepare (getSampleRate(), getBlockSize(), this); + node->prepare (getSampleRate(), getBlockSize(), this); - int j = 0; - for (; j < orderedNodes.size(); ++j) - if (isAnInputTo (node->id, - ((Node*) orderedNodes.getUnchecked (j))->id, - nodes.size() + 1)) - break; + int j = 0; + for (; j < orderedNodes.size(); ++j) + if (isAnInputTo (node->id, + ((Node*) orderedNodes.getUnchecked (j))->id, + nodes.size() + 1)) + break; - orderedNodes.insert (j, node); - } + orderedNodes.insert (j, node); + } - GraphRenderingOps::RenderingOpSequenceCalculator calculator (*this, orderedNodes, newRenderingOps); + GraphRenderingOps::RenderingOpSequenceCalculator calculator (*this, orderedNodes, newRenderingOps); - numRenderingBuffersNeeded = calculator.getNumBuffersNeeded(); - numMidiBuffersNeeded = calculator.getNumMidiBuffersNeeded(); - } + numRenderingBuffersNeeded = calculator.getNumBuffersNeeded(); + numMidiBuffersNeeded = calculator.getNumMidiBuffersNeeded(); + } - VoidArray oldRenderingOps (renderingOps); + VoidArray oldRenderingOps (renderingOps); - { - // swap over to the new rendering sequence.. - const ScopedLock sl (renderLock); + { + // swap over to the new rendering sequence.. + const ScopedLock sl (renderLock); - renderingBuffers.setSize (numRenderingBuffersNeeded, getBlockSize()); - renderingBuffers.clear(); + renderingBuffers.setSize (numRenderingBuffersNeeded, getBlockSize()); + renderingBuffers.clear(); - for (int i = midiBuffers.size(); --i >= 0;) - midiBuffers.getUnchecked(i)->clear(); + for (int i = midiBuffers.size(); --i >= 0;) + midiBuffers.getUnchecked(i)->clear(); - while (midiBuffers.size() < numMidiBuffersNeeded) - midiBuffers.add (new MidiBuffer()); + while (midiBuffers.size() < numMidiBuffersNeeded) + midiBuffers.add (new MidiBuffer()); - renderingOps = newRenderingOps; - } + renderingOps = newRenderingOps; + } - for (int i = oldRenderingOps.size(); --i >= 0;) - delete (GraphRenderingOps::AudioGraphRenderingOp*) oldRenderingOps.getUnchecked(i); + for (int i = oldRenderingOps.size(); --i >= 0;) + delete (GraphRenderingOps::AudioGraphRenderingOp*) oldRenderingOps.getUnchecked(i); } void AudioProcessorGraph::handleAsyncUpdate() { - buildRenderingSequence(); + buildRenderingSequence(); } void AudioProcessorGraph::prepareToPlay (double /*sampleRate*/, int estimatedSamplesPerBlock) { - currentAudioInputBuffer = 0; - currentAudioOutputBuffer.setSize (jmax (1, getNumOutputChannels()), estimatedSamplesPerBlock); - currentMidiInputBuffer = 0; - currentMidiOutputBuffer.clear(); + currentAudioInputBuffer = 0; + currentAudioOutputBuffer.setSize (jmax (1, getNumOutputChannels()), estimatedSamplesPerBlock); + currentMidiInputBuffer = 0; + currentMidiOutputBuffer.clear(); - clearRenderingSequence(); - buildRenderingSequence(); + clearRenderingSequence(); + buildRenderingSequence(); } void AudioProcessorGraph::releaseResources() { - for (int i = 0; i < nodes.size(); ++i) - nodes.getUnchecked(i)->unprepare(); + for (int i = 0; i < nodes.size(); ++i) + nodes.getUnchecked(i)->unprepare(); - renderingBuffers.setSize (1, 1); - midiBuffers.clear(); + renderingBuffers.setSize (1, 1); + midiBuffers.clear(); - currentAudioInputBuffer = 0; - currentAudioOutputBuffer.setSize (1, 1); - currentMidiInputBuffer = 0; - currentMidiOutputBuffer.clear(); + currentAudioInputBuffer = 0; + currentAudioOutputBuffer.setSize (1, 1); + currentMidiInputBuffer = 0; + currentMidiOutputBuffer.clear(); } void AudioProcessorGraph::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { - const int numSamples = buffer.getNumSamples(); + const int numSamples = buffer.getNumSamples(); - const ScopedLock sl (renderLock); + const ScopedLock sl (renderLock); - currentAudioInputBuffer = &buffer; - currentAudioOutputBuffer.setSize (jmax (1, buffer.getNumChannels()), numSamples); - currentAudioOutputBuffer.clear(); - currentMidiInputBuffer = &midiMessages; - currentMidiOutputBuffer.clear(); + currentAudioInputBuffer = &buffer; + currentAudioOutputBuffer.setSize (jmax (1, buffer.getNumChannels()), numSamples); + currentAudioOutputBuffer.clear(); + currentMidiInputBuffer = &midiMessages; + currentMidiOutputBuffer.clear(); - int i; - for (i = 0; i < renderingOps.size(); ++i) - { - GraphRenderingOps::AudioGraphRenderingOp* const op - = (GraphRenderingOps::AudioGraphRenderingOp*) renderingOps.getUnchecked(i); + int i; + for (i = 0; i < renderingOps.size(); ++i) + { + GraphRenderingOps::AudioGraphRenderingOp* const op + = (GraphRenderingOps::AudioGraphRenderingOp*) renderingOps.getUnchecked(i); - op->perform (renderingBuffers, midiBuffers, numSamples); - } + op->perform (renderingBuffers, midiBuffers, numSamples); + } - for (i = 0; i < buffer.getNumChannels(); ++i) - buffer.copyFrom (i, 0, currentAudioOutputBuffer, i, 0, numSamples); + for (i = 0; i < buffer.getNumChannels(); ++i) + buffer.copyFrom (i, 0, currentAudioOutputBuffer, i, 0, numSamples); - midiMessages.clear(); - midiMessages.addEvents (currentMidiOutputBuffer, 0, buffer.getNumSamples(), 0); + midiMessages.clear(); + midiMessages.addEvents (currentMidiOutputBuffer, 0, buffer.getNumSamples(), 0); } const String AudioProcessorGraph::getInputChannelName (const int channelIndex) const { - return "Input " + String (channelIndex + 1); + return "Input " + String (channelIndex + 1); } const String AudioProcessorGraph::getOutputChannelName (const int channelIndex) const { - return "Output " + String (channelIndex + 1); + return "Output " + String (channelIndex + 1); } bool AudioProcessorGraph::isInputChannelStereoPair (int /*index*/) const { - return true; + return true; } bool AudioProcessorGraph::isOutputChannelStereoPair (int /*index*/) const { - return true; + return true; } bool AudioProcessorGraph::acceptsMidi() const { - return true; + return true; } bool AudioProcessorGraph::producesMidi() const { - return true; + return true; } void AudioProcessorGraph::getStateInformation (JUCE_NAMESPACE::MemoryBlock& /*destData*/) @@ -36172,8 +35878,8 @@ void AudioProcessorGraph::setStateInformation (const void* /*data*/, int /*sizeI } AudioProcessorGraph::AudioGraphIOProcessor::AudioGraphIOProcessor (const IODeviceType type_) - : type (type_), - graph (0) + : type (type_), + graph (0) { } @@ -36183,45 +35889,45 @@ AudioProcessorGraph::AudioGraphIOProcessor::~AudioGraphIOProcessor() const String AudioProcessorGraph::AudioGraphIOProcessor::getName() const { - switch (type) - { - case audioOutputNode: - return "Audio Output"; - case audioInputNode: - return "Audio Input"; - case midiOutputNode: - return "Midi Output"; - case midiInputNode: - return "Midi Input"; - default: - break; - } + switch (type) + { + case audioOutputNode: + return "Audio Output"; + case audioInputNode: + return "Audio Input"; + case midiOutputNode: + return "Midi Output"; + case midiInputNode: + return "Midi Input"; + default: + break; + } - return String::empty; + return String::empty; } void AudioProcessorGraph::AudioGraphIOProcessor::fillInPluginDescription (PluginDescription& d) const { - d.name = getName(); - d.uid = d.name.hashCode(); - d.category = "I/O devices"; - d.pluginFormatName = "Internal"; - d.manufacturerName = "Raw Material Software"; - d.version = "1.0"; - d.isInstrument = false; + d.name = getName(); + d.uid = d.name.hashCode(); + d.category = "I/O devices"; + d.pluginFormatName = "Internal"; + d.manufacturerName = "Raw Material Software"; + d.version = "1.0"; + d.isInstrument = false; - d.numInputChannels = getNumInputChannels(); - if (type == audioOutputNode && graph != 0) - d.numInputChannels = graph->getNumInputChannels(); + d.numInputChannels = getNumInputChannels(); + if (type == audioOutputNode && graph != 0) + d.numInputChannels = graph->getNumInputChannels(); - d.numOutputChannels = getNumOutputChannels(); - if (type == audioInputNode && graph != 0) - d.numOutputChannels = graph->getNumOutputChannels(); + d.numOutputChannels = getNumOutputChannels(); + if (type == audioInputNode && graph != 0) + d.numOutputChannels = graph->getNumOutputChannels(); } void AudioProcessorGraph::AudioGraphIOProcessor::prepareToPlay (double, int) { - jassert (graph != 0); + jassert (graph != 0); } void AudioProcessorGraph::AudioGraphIOProcessor::releaseResources() @@ -36229,124 +35935,124 @@ void AudioProcessorGraph::AudioGraphIOProcessor::releaseResources() } void AudioProcessorGraph::AudioGraphIOProcessor::processBlock (AudioSampleBuffer& buffer, - MidiBuffer& midiMessages) + MidiBuffer& midiMessages) { - jassert (graph != 0); + jassert (graph != 0); - switch (type) - { - case audioOutputNode: - { - for (int i = jmin (graph->currentAudioOutputBuffer.getNumChannels(), - buffer.getNumChannels()); --i >= 0;) - { - graph->currentAudioOutputBuffer.addFrom (i, 0, buffer, i, 0, buffer.getNumSamples()); - } + switch (type) + { + case audioOutputNode: + { + for (int i = jmin (graph->currentAudioOutputBuffer.getNumChannels(), + buffer.getNumChannels()); --i >= 0;) + { + graph->currentAudioOutputBuffer.addFrom (i, 0, buffer, i, 0, buffer.getNumSamples()); + } - break; - } + break; + } - case audioInputNode: - { - for (int i = jmin (graph->currentAudioInputBuffer->getNumChannels(), - buffer.getNumChannels()); --i >= 0;) - { - buffer.copyFrom (i, 0, *graph->currentAudioInputBuffer, i, 0, buffer.getNumSamples()); - } + case audioInputNode: + { + for (int i = jmin (graph->currentAudioInputBuffer->getNumChannels(), + buffer.getNumChannels()); --i >= 0;) + { + buffer.copyFrom (i, 0, *graph->currentAudioInputBuffer, i, 0, buffer.getNumSamples()); + } - break; - } + break; + } - case midiOutputNode: - graph->currentMidiOutputBuffer.addEvents (midiMessages, 0, buffer.getNumSamples(), 0); - break; + case midiOutputNode: + graph->currentMidiOutputBuffer.addEvents (midiMessages, 0, buffer.getNumSamples(), 0); + break; - case midiInputNode: - midiMessages.addEvents (*graph->currentMidiInputBuffer, 0, buffer.getNumSamples(), 0); - break; + case midiInputNode: + midiMessages.addEvents (*graph->currentMidiInputBuffer, 0, buffer.getNumSamples(), 0); + break; - default: - break; - } + default: + break; + } } bool AudioProcessorGraph::AudioGraphIOProcessor::acceptsMidi() const { - return type == midiOutputNode; + return type == midiOutputNode; } bool AudioProcessorGraph::AudioGraphIOProcessor::producesMidi() const { - return type == midiInputNode; + return type == midiInputNode; } const String AudioProcessorGraph::AudioGraphIOProcessor::getInputChannelName (const int channelIndex) const { - switch (type) - { - case audioOutputNode: - return "Output " + String (channelIndex + 1); - case midiOutputNode: - return "Midi Output"; - default: - break; - } + switch (type) + { + case audioOutputNode: + return "Output " + String (channelIndex + 1); + case midiOutputNode: + return "Midi Output"; + default: + break; + } - return String::empty; + return String::empty; } const String AudioProcessorGraph::AudioGraphIOProcessor::getOutputChannelName (const int channelIndex) const { - switch (type) - { - case audioInputNode: - return "Input " + String (channelIndex + 1); - case midiInputNode: - return "Midi Input"; - default: - break; - } + switch (type) + { + case audioInputNode: + return "Input " + String (channelIndex + 1); + case midiInputNode: + return "Midi Input"; + default: + break; + } - return String::empty; + return String::empty; } bool AudioProcessorGraph::AudioGraphIOProcessor::isInputChannelStereoPair (int /*index*/) const { - return type == audioInputNode || type == audioOutputNode; + return type == audioInputNode || type == audioOutputNode; } bool AudioProcessorGraph::AudioGraphIOProcessor::isOutputChannelStereoPair (int index) const { - return isInputChannelStereoPair (index); + return isInputChannelStereoPair (index); } bool AudioProcessorGraph::AudioGraphIOProcessor::isInput() const { - return type == audioInputNode || type == midiInputNode; + return type == audioInputNode || type == midiInputNode; } bool AudioProcessorGraph::AudioGraphIOProcessor::isOutput() const { - return type == audioOutputNode || type == midiOutputNode; + return type == audioOutputNode || type == midiOutputNode; } AudioProcessorEditor* AudioProcessorGraph::AudioGraphIOProcessor::createEditor() { - return 0; + return 0; } -int AudioProcessorGraph::AudioGraphIOProcessor::getNumParameters() { return 0; } -const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterName (int) { return String::empty; } +int AudioProcessorGraph::AudioGraphIOProcessor::getNumParameters() { return 0; } +const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterName (int) { return String::empty; } -float AudioProcessorGraph::AudioGraphIOProcessor::getParameter (int) { return 0.0f; } -const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterText (int) { return String::empty; } -void AudioProcessorGraph::AudioGraphIOProcessor::setParameter (int, float) { } +float AudioProcessorGraph::AudioGraphIOProcessor::getParameter (int) { return 0.0f; } +const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterText (int) { return String::empty; } +void AudioProcessorGraph::AudioGraphIOProcessor::setParameter (int, float) { } -int AudioProcessorGraph::AudioGraphIOProcessor::getNumPrograms() { return 0; } -int AudioProcessorGraph::AudioGraphIOProcessor::getCurrentProgram() { return 0; } -void AudioProcessorGraph::AudioGraphIOProcessor::setCurrentProgram (int) { } +int AudioProcessorGraph::AudioGraphIOProcessor::getNumPrograms() { return 0; } +int AudioProcessorGraph::AudioGraphIOProcessor::getCurrentProgram() { return 0; } +void AudioProcessorGraph::AudioGraphIOProcessor::setCurrentProgram (int) { } -const String AudioProcessorGraph::AudioGraphIOProcessor::getProgramName (int) { return String::empty; } +const String AudioProcessorGraph::AudioGraphIOProcessor::getProgramName (int) { return String::empty; } void AudioProcessorGraph::AudioGraphIOProcessor::changeProgramName (int, const String&) { } void AudioProcessorGraph::AudioGraphIOProcessor::getStateInformation (JUCE_NAMESPACE::MemoryBlock&) @@ -36359,17 +36065,17 @@ void AudioProcessorGraph::AudioGraphIOProcessor::setStateInformation (const void void AudioProcessorGraph::AudioGraphIOProcessor::setParentGraph (AudioProcessorGraph* const newGraph) { - graph = newGraph; + graph = newGraph; - if (graph != 0) - { - setPlayConfigDetails (type == audioOutputNode ? graph->getNumOutputChannels() : 0, - type == audioInputNode ? graph->getNumInputChannels() : 0, - getSampleRate(), - getBlockSize()); + if (graph != 0) + { + setPlayConfigDetails (type == audioOutputNode ? graph->getNumOutputChannels() : 0, + type == audioInputNode ? graph->getNumInputChannels() : 0, + getSampleRate(), + getBlockSize()); - updateHostDisplay(); - } + updateHostDisplay(); + } } END_JUCE_NAMESPACE @@ -36380,143 +36086,143 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioProcessorPlayer::AudioProcessorPlayer() - : processor (0), - sampleRate (0), - blockSize (0), - isPrepared (false), - numInputChans (0), - numOutputChans (0), - tempBuffer (1, 1) + : processor (0), + sampleRate (0), + blockSize (0), + isPrepared (false), + numInputChans (0), + numOutputChans (0), + tempBuffer (1, 1) { } AudioProcessorPlayer::~AudioProcessorPlayer() { - setProcessor (0); + setProcessor (0); } void AudioProcessorPlayer::setProcessor (AudioProcessor* const processorToPlay) { - if (processor != processorToPlay) - { - if (processorToPlay != 0 && sampleRate > 0 && blockSize > 0) - { - processorToPlay->setPlayConfigDetails (numInputChans, numOutputChans, - sampleRate, blockSize); + if (processor != processorToPlay) + { + if (processorToPlay != 0 && sampleRate > 0 && blockSize > 0) + { + processorToPlay->setPlayConfigDetails (numInputChans, numOutputChans, + sampleRate, blockSize); - processorToPlay->prepareToPlay (sampleRate, blockSize); - } + processorToPlay->prepareToPlay (sampleRate, blockSize); + } - lock.enter(); - AudioProcessor* const oldOne = isPrepared ? processor : 0; - processor = processorToPlay; - isPrepared = true; - lock.exit(); + lock.enter(); + AudioProcessor* const oldOne = isPrepared ? processor : 0; + processor = processorToPlay; + isPrepared = true; + lock.exit(); - if (oldOne != 0) - oldOne->releaseResources(); - } + if (oldOne != 0) + oldOne->releaseResources(); + } } void AudioProcessorPlayer::audioDeviceIOCallback (const float** inputChannelData, - int numInputChannels, - float** outputChannelData, - int numOutputChannels, - int numSamples) + int numInputChannels, + float** outputChannelData, + int numOutputChannels, + int numSamples) { - // these should have been prepared by audioDeviceAboutToStart()... - jassert (sampleRate > 0 && blockSize > 0); + // these should have been prepared by audioDeviceAboutToStart()... + jassert (sampleRate > 0 && blockSize > 0); - incomingMidi.clear(); - messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples); - int i, totalNumChans = 0; + incomingMidi.clear(); + messageCollector.removeNextBlockOfMessages (incomingMidi, numSamples); + int i, totalNumChans = 0; - if (numInputChannels > numOutputChannels) - { - // if there aren't enough output channels for the number of - // inputs, we need to create some temporary extra ones (can't - // use the input data in case it gets written to) - tempBuffer.setSize (numInputChannels - numOutputChannels, numSamples, - false, false, true); + if (numInputChannels > numOutputChannels) + { + // if there aren't enough output channels for the number of + // inputs, we need to create some temporary extra ones (can't + // use the input data in case it gets written to) + tempBuffer.setSize (numInputChannels - numOutputChannels, numSamples, + false, false, true); - for (i = 0; i < numOutputChannels; ++i) - { - channels[totalNumChans] = outputChannelData[i]; - memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * numSamples); - ++totalNumChans; - } + for (i = 0; i < numOutputChannels; ++i) + { + channels[totalNumChans] = outputChannelData[i]; + memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * numSamples); + ++totalNumChans; + } - for (i = numOutputChannels; i < numInputChannels; ++i) - { - channels[totalNumChans] = tempBuffer.getSampleData (i - numOutputChannels, 0); - memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * numSamples); - ++totalNumChans; - } - } - else - { - for (i = 0; i < numInputChannels; ++i) - { - channels[totalNumChans] = outputChannelData[i]; - memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * numSamples); - ++totalNumChans; - } + for (i = numOutputChannels; i < numInputChannels; ++i) + { + channels[totalNumChans] = tempBuffer.getSampleData (i - numOutputChannels, 0); + memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * numSamples); + ++totalNumChans; + } + } + else + { + for (i = 0; i < numInputChannels; ++i) + { + channels[totalNumChans] = outputChannelData[i]; + memcpy (channels[totalNumChans], inputChannelData[i], sizeof (float) * numSamples); + ++totalNumChans; + } - for (i = numInputChannels; i < numOutputChannels; ++i) - { - channels[totalNumChans] = outputChannelData[i]; - zeromem (channels[totalNumChans], sizeof (float) * numSamples); - ++totalNumChans; - } - } + for (i = numInputChannels; i < numOutputChannels; ++i) + { + channels[totalNumChans] = outputChannelData[i]; + zeromem (channels[totalNumChans], sizeof (float) * numSamples); + ++totalNumChans; + } + } - AudioSampleBuffer buffer (channels, totalNumChans, numSamples); + AudioSampleBuffer buffer (channels, totalNumChans, numSamples); - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (processor != 0) - processor->processBlock (buffer, incomingMidi); + if (processor != 0) + processor->processBlock (buffer, incomingMidi); } void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* device) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - sampleRate = device->getCurrentSampleRate(); - blockSize = device->getCurrentBufferSizeSamples(); - numInputChans = device->getActiveInputChannels().countNumberOfSetBits(); - numOutputChans = device->getActiveOutputChannels().countNumberOfSetBits(); + sampleRate = device->getCurrentSampleRate(); + blockSize = device->getCurrentBufferSizeSamples(); + numInputChans = device->getActiveInputChannels().countNumberOfSetBits(); + numOutputChans = device->getActiveOutputChannels().countNumberOfSetBits(); - messageCollector.reset (sampleRate); - zeromem (channels, sizeof (channels)); + messageCollector.reset (sampleRate); + zeromem (channels, sizeof (channels)); - if (processor != 0) - { - if (isPrepared) - processor->releaseResources(); + if (processor != 0) + { + if (isPrepared) + processor->releaseResources(); - AudioProcessor* const oldProcessor = processor; - setProcessor (0); - setProcessor (oldProcessor); - } + AudioProcessor* const oldProcessor = processor; + setProcessor (0); + setProcessor (oldProcessor); + } } void AudioProcessorPlayer::audioDeviceStopped() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if (processor != 0 && isPrepared) - processor->releaseResources(); + if (processor != 0 && isPrepared) + processor->releaseResources(); - sampleRate = 0.0; - blockSize = 0; - isPrepared = false; - tempBuffer.setSize (1, 1); + sampleRate = 0.0; + blockSize = 0; + isPrepared = false; + tempBuffer.setSize (1, 1); } void AudioProcessorPlayer::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message) { - messageCollector.addMessageToQueue (message); + messageCollector.addMessageToQueue (message); } END_JUCE_NAMESPACE @@ -36527,132 +36233,132 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE class ProcessorParameterPropertyComp : public PropertyComponent, - public AudioProcessorListener, - public AsyncUpdater + public AudioProcessorListener, + public AsyncUpdater { public: - ProcessorParameterPropertyComp (const String& name, - AudioProcessor* const owner_, - const int index_) - : PropertyComponent (name), - owner (owner_), - index (index_) - { - addAndMakeVisible (slider = new ParamSlider (owner_, index_)); - owner_->addListener (this); - } + ProcessorParameterPropertyComp (const String& name, + AudioProcessor* const owner_, + const int index_) + : PropertyComponent (name), + owner (owner_), + index (index_) + { + addAndMakeVisible (slider = new ParamSlider (owner_, index_)); + owner_->addListener (this); + } - ~ProcessorParameterPropertyComp() - { - owner->removeListener (this); - deleteAllChildren(); - } + ~ProcessorParameterPropertyComp() + { + owner->removeListener (this); + deleteAllChildren(); + } - void refresh() - { - slider->setValue (owner->getParameter (index), false); - } + void refresh() + { + slider->setValue (owner->getParameter (index), false); + } - void audioProcessorChanged (AudioProcessor*) {} + void audioProcessorChanged (AudioProcessor*) {} - void audioProcessorParameterChanged (AudioProcessor*, int parameterIndex, float) - { - if (parameterIndex == index) - triggerAsyncUpdate(); - } + void audioProcessorParameterChanged (AudioProcessor*, int parameterIndex, float) + { + if (parameterIndex == index) + triggerAsyncUpdate(); + } - void handleAsyncUpdate() - { - refresh(); - } + void handleAsyncUpdate() + { + refresh(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioProcessor* const owner; - const int index; - Slider* slider; + AudioProcessor* const owner; + const int index; + Slider* slider; - class ParamSlider : public Slider - { - public: - ParamSlider (AudioProcessor* const owner_, const int index_) - : Slider (String::empty), - owner (owner_), - index (index_) - { - setRange (0.0, 1.0, 0.0); - setSliderStyle (Slider::LinearBar); - setTextBoxIsEditable (false); - setScrollWheelEnabled (false); - } + class ParamSlider : public Slider + { + public: + ParamSlider (AudioProcessor* const owner_, const int index_) + : Slider (String::empty), + owner (owner_), + index (index_) + { + setRange (0.0, 1.0, 0.0); + setSliderStyle (Slider::LinearBar); + setTextBoxIsEditable (false); + setScrollWheelEnabled (false); + } - ~ParamSlider() - { - } + ~ParamSlider() + { + } - void valueChanged() - { - const float newVal = (float) getValue(); + void valueChanged() + { + const float newVal = (float) getValue(); - if (owner->getParameter (index) != newVal) - owner->setParameter (index, newVal); - } + if (owner->getParameter (index) != newVal) + owner->setParameter (index, newVal); + } - const String getTextFromValue (double /*value*/) - { - return owner->getParameterText (index); - } + const String getTextFromValue (double /*value*/) + { + return owner->getParameterText (index); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - private: - AudioProcessor* const owner; - const int index; - }; + private: + AudioProcessor* const owner; + const int index; + }; }; GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor* const owner_) - : AudioProcessorEditor (owner_) + : AudioProcessorEditor (owner_) { - setOpaque (true); + setOpaque (true); - addAndMakeVisible (panel = new PropertyPanel()); + addAndMakeVisible (panel = new PropertyPanel()); - Array params; + Array params; - const int numParams = owner_->getNumParameters(); - int totalHeight = 0; + const int numParams = owner_->getNumParameters(); + int totalHeight = 0; - for (int i = 0; i < numParams; ++i) - { - String name (owner_->getParameterName (i)); - if (name.trim().isEmpty()) - name = "Unnamed"; + for (int i = 0; i < numParams; ++i) + { + String name (owner_->getParameterName (i)); + if (name.trim().isEmpty()) + name = "Unnamed"; - ProcessorParameterPropertyComp* const pc = new ProcessorParameterPropertyComp (name, owner_, i); - params.add (pc); - totalHeight += pc->getPreferredHeight(); - } + ProcessorParameterPropertyComp* const pc = new ProcessorParameterPropertyComp (name, owner_, i); + params.add (pc); + totalHeight += pc->getPreferredHeight(); + } - panel->addProperties (params); + panel->addProperties (params); - setSize (400, jlimit (25, 400, totalHeight)); + setSize (400, jlimit (25, 400, totalHeight)); } GenericAudioProcessorEditor::~GenericAudioProcessorEditor() { - deleteAllChildren(); + deleteAllChildren(); } void GenericAudioProcessorEditor::paint (Graphics& g) { - g.fillAll (Colours::white); + g.fillAll (Colours::white); } void GenericAudioProcessorEditor::resized() { - panel->setSize (getWidth(), getHeight()); + panel->setSize (getWidth(), getHeight()); } END_JUCE_NAMESPACE @@ -36663,36 +36369,36 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE SamplerSound::SamplerSound (const String& name_, - AudioFormatReader& source, - const BitArray& midiNotes_, - const int midiNoteForNormalPitch, - const double attackTimeSecs, - const double releaseTimeSecs, - const double maxSampleLengthSeconds) - : name (name_), - midiNotes (midiNotes_), - midiRootNote (midiNoteForNormalPitch) + AudioFormatReader& source, + const BitArray& midiNotes_, + const int midiNoteForNormalPitch, + const double attackTimeSecs, + const double releaseTimeSecs, + const double maxSampleLengthSeconds) + : name (name_), + midiNotes (midiNotes_), + midiRootNote (midiNoteForNormalPitch) { - sourceSampleRate = source.sampleRate; + sourceSampleRate = source.sampleRate; - if (sourceSampleRate <= 0 || source.lengthInSamples <= 0) - { - length = 0; - attackSamples = 0; - releaseSamples = 0; - } - else - { - length = jmin ((int) source.lengthInSamples, - (int) (maxSampleLengthSeconds * sourceSampleRate)); + if (sourceSampleRate <= 0 || source.lengthInSamples <= 0) + { + length = 0; + attackSamples = 0; + releaseSamples = 0; + } + else + { + length = jmin ((int) source.lengthInSamples, + (int) (maxSampleLengthSeconds * sourceSampleRate)); - data = new AudioSampleBuffer (jmin (2, source.numChannels), length + 4); + data = new AudioSampleBuffer (jmin (2, (int) source.numChannels), length + 4); - data->readFromAudioReader (&source, 0, length + 4, 0, true, true); + data->readFromAudioReader (&source, 0, length + 4, 0, true, true); - attackSamples = roundDoubleToInt (attackTimeSecs * sourceSampleRate); - releaseSamples = roundDoubleToInt (releaseTimeSecs * sourceSampleRate); - } + attackSamples = roundToInt (attackTimeSecs * sourceSampleRate); + releaseSamples = roundToInt (releaseTimeSecs * sourceSampleRate); + } } SamplerSound::~SamplerSound() @@ -36701,21 +36407,21 @@ SamplerSound::~SamplerSound() bool SamplerSound::appliesToNote (const int midiNoteNumber) { - return midiNotes [midiNoteNumber]; + return midiNotes [midiNoteNumber]; } bool SamplerSound::appliesToChannel (const int /*midiChannel*/) { - return true; + return true; } SamplerVoice::SamplerVoice() - : pitchRatio (0.0), - sourceSamplePosition (0.0), - lgain (0.0f), - rgain (0.0f), - isInAttack (false), - isInRelease (false) + : pitchRatio (0.0), + sourceSamplePosition (0.0), + lgain (0.0f), + rgain (0.0f), + isInAttack (false), + isInRelease (false) { } @@ -36725,64 +36431,64 @@ SamplerVoice::~SamplerVoice() bool SamplerVoice::canPlaySound (SynthesiserSound* sound) { - return dynamic_cast (sound) != 0; + return dynamic_cast (sound) != 0; } void SamplerVoice::startNote (const int midiNoteNumber, - const float velocity, - SynthesiserSound* s, - const int /*currentPitchWheelPosition*/) + const float velocity, + SynthesiserSound* s, + const int /*currentPitchWheelPosition*/) { - const SamplerSound* const sound = dynamic_cast (s); - jassert (sound != 0); // this object can only play SamplerSounds! + const SamplerSound* const sound = dynamic_cast (s); + jassert (sound != 0); // this object can only play SamplerSounds! - if (sound != 0) - { - const double targetFreq = MidiMessage::getMidiNoteInHertz (midiNoteNumber); - const double naturalFreq = MidiMessage::getMidiNoteInHertz (sound->midiRootNote); + if (sound != 0) + { + const double targetFreq = MidiMessage::getMidiNoteInHertz (midiNoteNumber); + const double naturalFreq = MidiMessage::getMidiNoteInHertz (sound->midiRootNote); - pitchRatio = (targetFreq * sound->sourceSampleRate) / (naturalFreq * getSampleRate()); + pitchRatio = (targetFreq * sound->sourceSampleRate) / (naturalFreq * getSampleRate()); - sourceSamplePosition = 0.0; - lgain = velocity; - rgain = velocity; + sourceSamplePosition = 0.0; + lgain = velocity; + rgain = velocity; - isInAttack = (sound->attackSamples > 0); - isInRelease = false; + isInAttack = (sound->attackSamples > 0); + isInRelease = false; - if (isInAttack) - { - attackReleaseLevel = 0.0f; - attackDelta = (float) (pitchRatio / sound->attackSamples); - } - else - { - attackReleaseLevel = 1.0f; - attackDelta = 0.0f; - } + if (isInAttack) + { + attackReleaseLevel = 0.0f; + attackDelta = (float) (pitchRatio / sound->attackSamples); + } + else + { + attackReleaseLevel = 1.0f; + attackDelta = 0.0f; + } - if (sound->releaseSamples > 0) - { - releaseDelta = (float) (-pitchRatio / sound->releaseSamples); - } - else - { - releaseDelta = 0.0f; - } - } + if (sound->releaseSamples > 0) + { + releaseDelta = (float) (-pitchRatio / sound->releaseSamples); + } + else + { + releaseDelta = 0.0f; + } + } } void SamplerVoice::stopNote (const bool allowTailOff) { - if (allowTailOff) - { - isInAttack = false; - isInRelease = true; - } - else - { - clearCurrentNote(); - } + if (allowTailOff) + { + isInAttack = false; + isInRelease = true; + } + else + { + clearCurrentNote(); + } } void SamplerVoice::pitchWheelMoved (const int /*newValue*/) @@ -36790,83 +36496,83 @@ void SamplerVoice::pitchWheelMoved (const int /*newValue*/) } void SamplerVoice::controllerMoved (const int /*controllerNumber*/, - const int /*newValue*/) + const int /*newValue*/) { } void SamplerVoice::renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples) { - const SamplerSound* const playingSound = (SamplerSound*) (SynthesiserSound*) getCurrentlyPlayingSound(); + const SamplerSound* const playingSound = (SamplerSound*) (SynthesiserSound*) getCurrentlyPlayingSound(); - if (playingSound != 0) - { - const float* const inL = playingSound->data->getSampleData (0, 0); - const float* const inR = playingSound->data->getNumChannels() > 1 - ? playingSound->data->getSampleData (1, 0) : 0; + if (playingSound != 0) + { + const float* const inL = playingSound->data->getSampleData (0, 0); + const float* const inR = playingSound->data->getNumChannels() > 1 + ? playingSound->data->getSampleData (1, 0) : 0; - float* outL = outputBuffer.getSampleData (0, startSample); - float* outR = outputBuffer.getNumChannels() > 1 ? outputBuffer.getSampleData (1, startSample) : 0; + float* outL = outputBuffer.getSampleData (0, startSample); + float* outR = outputBuffer.getNumChannels() > 1 ? outputBuffer.getSampleData (1, startSample) : 0; - while (--numSamples >= 0) - { - const int pos = (int) sourceSamplePosition; - const float alpha = (float) (sourceSamplePosition - pos); - const float invAlpha = 1.0f - alpha; + while (--numSamples >= 0) + { + const int pos = (int) sourceSamplePosition; + const float alpha = (float) (sourceSamplePosition - pos); + const float invAlpha = 1.0f - alpha; - // just using a very simple linear interpolation here.. - float l = (inL [pos] * invAlpha + inL [pos + 1] * alpha); - float r = (inR != 0) ? (inR [pos] * invAlpha + inR [pos + 1] * alpha) - : l; + // just using a very simple linear interpolation here.. + float l = (inL [pos] * invAlpha + inL [pos + 1] * alpha); + float r = (inR != 0) ? (inR [pos] * invAlpha + inR [pos + 1] * alpha) + : l; - l *= lgain; - r *= rgain; + l *= lgain; + r *= rgain; - if (isInAttack) - { - l *= attackReleaseLevel; - r *= attackReleaseLevel; + if (isInAttack) + { + l *= attackReleaseLevel; + r *= attackReleaseLevel; - attackReleaseLevel += attackDelta; + attackReleaseLevel += attackDelta; - if (attackReleaseLevel >= 1.0f) - { - attackReleaseLevel = 1.0f; - isInAttack = false; - } - } - else if (isInRelease) - { - l *= attackReleaseLevel; - r *= attackReleaseLevel; + if (attackReleaseLevel >= 1.0f) + { + attackReleaseLevel = 1.0f; + isInAttack = false; + } + } + else if (isInRelease) + { + l *= attackReleaseLevel; + r *= attackReleaseLevel; - attackReleaseLevel += releaseDelta; + attackReleaseLevel += releaseDelta; - if (attackReleaseLevel <= 0.0f) - { - stopNote (false); - break; - } - } + if (attackReleaseLevel <= 0.0f) + { + stopNote (false); + break; + } + } - if (outR != 0) - { - *outL++ += l; - *outR++ += r; - } - else - { - *outL++ += (l + r) * 0.5f; - } + if (outR != 0) + { + *outL++ += l; + *outR++ += r; + } + else + { + *outL++ += (l + r) * 0.5f; + } - sourceSamplePosition += pitchRatio; + sourceSamplePosition += pitchRatio; - if (sourceSamplePosition > playingSound->length) - { - stopNote (false); - break; - } - } - } + if (sourceSamplePosition > playingSound->length) + { + stopNote (false); + break; + } + } + } } END_JUCE_NAMESPACE @@ -36885,10 +36591,10 @@ SynthesiserSound::~SynthesiserSound() } SynthesiserVoice::SynthesiserVoice() - : currentSampleRate (44100.0), - currentlyPlayingNote (-1), - noteOnTime (0), - currentlyPlayingSound (0) + : currentSampleRate (44100.0), + currentlyPlayingNote (-1), + noteOnTime (0), + currentlyPlayingSound (0) { } @@ -36898,30 +36604,28 @@ SynthesiserVoice::~SynthesiserVoice() bool SynthesiserVoice::isPlayingChannel (const int midiChannel) const { - return currentlyPlayingSound != 0 - && currentlyPlayingSound->appliesToChannel (midiChannel); + return currentlyPlayingSound != 0 + && currentlyPlayingSound->appliesToChannel (midiChannel); } void SynthesiserVoice::setCurrentPlaybackSampleRate (const double newRate) { - currentSampleRate = newRate; + currentSampleRate = newRate; } void SynthesiserVoice::clearCurrentNote() { - currentlyPlayingNote = -1; - currentlyPlayingSound = 0; + currentlyPlayingNote = -1; + currentlyPlayingSound = 0; } Synthesiser::Synthesiser() - : voices (2), - sounds (2), - sampleRate (0), - lastNoteOnCounter (0), - shouldStealNotes (true) + : sampleRate (0), + lastNoteOnCounter (0), + shouldStealNotes (true) { - for (int i = 0; i < numElementsInArray (lastPitchWheelValues); ++i) - lastPitchWheelValues[i] = 0x2000; + for (int i = 0; i < numElementsInArray (lastPitchWheelValues); ++i) + lastPitchWheelValues[i] = 0x2000; } Synthesiser::~Synthesiser() @@ -36930,278 +36634,278 @@ Synthesiser::~Synthesiser() SynthesiserVoice* Synthesiser::getVoice (const int index) const { - const ScopedLock sl (lock); - return voices [index]; + const ScopedLock sl (lock); + return voices [index]; } void Synthesiser::clearVoices() { - const ScopedLock sl (lock); - voices.clear(); + const ScopedLock sl (lock); + voices.clear(); } void Synthesiser::addVoice (SynthesiserVoice* const newVoice) { - const ScopedLock sl (lock); - voices.add (newVoice); + const ScopedLock sl (lock); + voices.add (newVoice); } void Synthesiser::removeVoice (const int index) { - const ScopedLock sl (lock); - voices.remove (index); + const ScopedLock sl (lock); + voices.remove (index); } void Synthesiser::clearSounds() { - const ScopedLock sl (lock); - sounds.clear(); + const ScopedLock sl (lock); + sounds.clear(); } void Synthesiser::addSound (const SynthesiserSound::Ptr& newSound) { - const ScopedLock sl (lock); - sounds.add (newSound); + const ScopedLock sl (lock); + sounds.add (newSound); } void Synthesiser::removeSound (const int index) { - const ScopedLock sl (lock); - sounds.remove (index); + const ScopedLock sl (lock); + sounds.remove (index); } void Synthesiser::setNoteStealingEnabled (const bool shouldStealNotes_) { - shouldStealNotes = shouldStealNotes_; + shouldStealNotes = shouldStealNotes_; } void Synthesiser::setCurrentPlaybackSampleRate (const double newRate) { - if (sampleRate != newRate) - { - const ScopedLock sl (lock); + if (sampleRate != newRate) + { + const ScopedLock sl (lock); - allNotesOff (0, false); + allNotesOff (0, false); - sampleRate = newRate; + sampleRate = newRate; - for (int i = voices.size(); --i >= 0;) - voices.getUnchecked (i)->setCurrentPlaybackSampleRate (newRate); - } + for (int i = voices.size(); --i >= 0;) + voices.getUnchecked (i)->setCurrentPlaybackSampleRate (newRate); + } } void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer, - const MidiBuffer& midiData, - int startSample, - int numSamples) + const MidiBuffer& midiData, + int startSample, + int numSamples) { - // must set the sample rate before using this! - jassert (sampleRate != 0); + // must set the sample rate before using this! + jassert (sampleRate != 0); - const ScopedLock sl (lock); + const ScopedLock sl (lock); - MidiBuffer::Iterator midiIterator (midiData); - midiIterator.setNextSamplePosition (startSample); - MidiMessage m (0xf4, 0.0); + MidiBuffer::Iterator midiIterator (midiData); + midiIterator.setNextSamplePosition (startSample); + MidiMessage m (0xf4, 0.0); - while (numSamples > 0) - { - int midiEventPos; - const bool useEvent = midiIterator.getNextEvent (m, midiEventPos) - && midiEventPos < startSample + numSamples; + while (numSamples > 0) + { + int midiEventPos; + const bool useEvent = midiIterator.getNextEvent (m, midiEventPos) + && midiEventPos < startSample + numSamples; - const int numThisTime = useEvent ? midiEventPos - startSample - : numSamples; + const int numThisTime = useEvent ? midiEventPos - startSample + : numSamples; - if (numThisTime > 0) - { - for (int i = voices.size(); --i >= 0;) - voices.getUnchecked (i)->renderNextBlock (outputBuffer, startSample, numThisTime); - } + if (numThisTime > 0) + { + for (int i = voices.size(); --i >= 0;) + voices.getUnchecked (i)->renderNextBlock (outputBuffer, startSample, numThisTime); + } - if (useEvent) - { - if (m.isNoteOn()) - { - const int channel = m.getChannel(); + if (useEvent) + { + if (m.isNoteOn()) + { + const int channel = m.getChannel(); - noteOn (channel, - m.getNoteNumber(), - m.getFloatVelocity()); - } - else if (m.isNoteOff()) - { - noteOff (m.getChannel(), - m.getNoteNumber(), - true); - } - else if (m.isAllNotesOff() || m.isAllSoundOff()) - { - allNotesOff (m.getChannel(), true); - } - else if (m.isPitchWheel()) - { - const int channel = m.getChannel(); - const int wheelPos = m.getPitchWheelValue(); - lastPitchWheelValues [channel - 1] = wheelPos; + noteOn (channel, + m.getNoteNumber(), + m.getFloatVelocity()); + } + else if (m.isNoteOff()) + { + noteOff (m.getChannel(), + m.getNoteNumber(), + true); + } + else if (m.isAllNotesOff() || m.isAllSoundOff()) + { + allNotesOff (m.getChannel(), true); + } + else if (m.isPitchWheel()) + { + const int channel = m.getChannel(); + const int wheelPos = m.getPitchWheelValue(); + lastPitchWheelValues [channel - 1] = wheelPos; - handlePitchWheel (channel, wheelPos); - } - else if (m.isController()) - { - handleController (m.getChannel(), - m.getControllerNumber(), - m.getControllerValue()); - } - } + handlePitchWheel (channel, wheelPos); + } + else if (m.isController()) + { + handleController (m.getChannel(), + m.getControllerNumber(), + m.getControllerValue()); + } + } - startSample += numThisTime; - numSamples -= numThisTime; - } + startSample += numThisTime; + numSamples -= numThisTime; + } } void Synthesiser::noteOn (const int midiChannel, - const int midiNoteNumber, - const float velocity) + const int midiNoteNumber, + const float velocity) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - for (int i = sounds.size(); --i >= 0;) - { - SynthesiserSound* const sound = sounds.getUnchecked(i); + for (int i = sounds.size(); --i >= 0;) + { + SynthesiserSound* const sound = sounds.getUnchecked(i); - if (sound->appliesToNote (midiNoteNumber) - && sound->appliesToChannel (midiChannel)) - { - startVoice (findFreeVoice (sound, shouldStealNotes), - sound, midiChannel, midiNoteNumber, velocity); - } - } + if (sound->appliesToNote (midiNoteNumber) + && sound->appliesToChannel (midiChannel)) + { + startVoice (findFreeVoice (sound, shouldStealNotes), + sound, midiChannel, midiNoteNumber, velocity); + } + } } void Synthesiser::startVoice (SynthesiserVoice* const voice, - SynthesiserSound* const sound, - const int midiChannel, - const int midiNoteNumber, - const float velocity) + SynthesiserSound* const sound, + const int midiChannel, + const int midiNoteNumber, + const float velocity) { - if (voice != 0 && sound != 0) - { - if (voice->currentlyPlayingSound != 0) - voice->stopNote (false); + if (voice != 0 && sound != 0) + { + if (voice->currentlyPlayingSound != 0) + voice->stopNote (false); - voice->startNote (midiNoteNumber, - velocity, - sound, - lastPitchWheelValues [midiChannel - 1]); + voice->startNote (midiNoteNumber, + velocity, + sound, + lastPitchWheelValues [midiChannel - 1]); - voice->currentlyPlayingNote = midiNoteNumber; - voice->noteOnTime = ++lastNoteOnCounter; - voice->currentlyPlayingSound = sound; - } + voice->currentlyPlayingNote = midiNoteNumber; + voice->noteOnTime = ++lastNoteOnCounter; + voice->currentlyPlayingSound = sound; + } } void Synthesiser::noteOff (const int midiChannel, - const int midiNoteNumber, - const bool allowTailOff) + const int midiNoteNumber, + const bool allowTailOff) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - for (int i = voices.size(); --i >= 0;) - { - SynthesiserVoice* const voice = voices.getUnchecked (i); + for (int i = voices.size(); --i >= 0;) + { + SynthesiserVoice* const voice = voices.getUnchecked (i); - if (voice->getCurrentlyPlayingNote() == midiNoteNumber) - { - SynthesiserSound* const sound = voice->getCurrentlyPlayingSound(); + if (voice->getCurrentlyPlayingNote() == midiNoteNumber) + { + SynthesiserSound* const sound = voice->getCurrentlyPlayingSound(); - if (sound != 0 - && sound->appliesToNote (midiNoteNumber) - && sound->appliesToChannel (midiChannel)) - { - voice->stopNote (allowTailOff); + if (sound != 0 + && sound->appliesToNote (midiNoteNumber) + && sound->appliesToChannel (midiChannel)) + { + voice->stopNote (allowTailOff); - // the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()! - jassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == 0)); - } - } - } + // the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()! + jassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == 0)); + } + } + } } void Synthesiser::allNotesOff (const int midiChannel, - const bool allowTailOff) + const bool allowTailOff) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - for (int i = voices.size(); --i >= 0;) - { - SynthesiserVoice* const voice = voices.getUnchecked (i); + for (int i = voices.size(); --i >= 0;) + { + SynthesiserVoice* const voice = voices.getUnchecked (i); - if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)) - voice->stopNote (allowTailOff); - } + if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)) + voice->stopNote (allowTailOff); + } } void Synthesiser::handlePitchWheel (const int midiChannel, - const int wheelValue) + const int wheelValue) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - for (int i = voices.size(); --i >= 0;) - { - SynthesiserVoice* const voice = voices.getUnchecked (i); + for (int i = voices.size(); --i >= 0;) + { + SynthesiserVoice* const voice = voices.getUnchecked (i); - if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)) - { - voice->pitchWheelMoved (wheelValue); - } - } + if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)) + { + voice->pitchWheelMoved (wheelValue); + } + } } void Synthesiser::handleController (const int midiChannel, - const int controllerNumber, - const int controllerValue) + const int controllerNumber, + const int controllerValue) { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - for (int i = voices.size(); --i >= 0;) - { - SynthesiserVoice* const voice = voices.getUnchecked (i); + for (int i = voices.size(); --i >= 0;) + { + SynthesiserVoice* const voice = voices.getUnchecked (i); - if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)) - voice->controllerMoved (controllerNumber, controllerValue); - } + if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)) + voice->controllerMoved (controllerNumber, controllerValue); + } } SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay, - const bool stealIfNoneAvailable) const + const bool stealIfNoneAvailable) const { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - for (int i = voices.size(); --i >= 0;) - if (voices.getUnchecked (i)->getCurrentlyPlayingNote() < 0 - && voices.getUnchecked (i)->canPlaySound (soundToPlay)) - return voices.getUnchecked (i); + for (int i = voices.size(); --i >= 0;) + if (voices.getUnchecked (i)->getCurrentlyPlayingNote() < 0 + && voices.getUnchecked (i)->canPlaySound (soundToPlay)) + return voices.getUnchecked (i); - if (stealIfNoneAvailable) - { - // currently this just steals the one that's been playing the longest, but could be made a bit smarter.. - SynthesiserVoice* oldest = 0; + if (stealIfNoneAvailable) + { + // currently this just steals the one that's been playing the longest, but could be made a bit smarter.. + SynthesiserVoice* oldest = 0; - for (int i = voices.size(); --i >= 0;) - { - SynthesiserVoice* const voice = voices.getUnchecked (i); + for (int i = voices.size(); --i >= 0;) + { + SynthesiserVoice* const voice = voices.getUnchecked (i); - if (voice->canPlaySound (soundToPlay) - && (oldest == 0 || oldest->noteOnTime > voice->noteOnTime)) - oldest = voice; - } + if (voice->canPlaySound (soundToPlay) + && (oldest == 0 || oldest->noteOnTime > voice->noteOnTime)) + oldest = voice; + } - jassert (oldest != 0); - return oldest; - } + jassert (oldest != 0); + return oldest; + } - return 0; + return 0; } END_JUCE_NAMESPACE @@ -37213,37 +36917,37 @@ BEGIN_JUCE_NAMESPACE ActionBroadcaster::ActionBroadcaster() throw() { - // are you trying to create this object before or after juce has been intialised?? - jassert (MessageManager::instance != 0); + // are you trying to create this object before or after juce has been intialised?? + jassert (MessageManager::instance != 0); } ActionBroadcaster::~ActionBroadcaster() { - // all event-based objects must be deleted BEFORE juce is shut down! - jassert (MessageManager::instance != 0); + // all event-based objects must be deleted BEFORE juce is shut down! + jassert (MessageManager::instance != 0); } void ActionBroadcaster::addActionListener (ActionListener* const listener) { - actionListenerList.addActionListener (listener); + actionListenerList.addActionListener (listener); } void ActionBroadcaster::removeActionListener (ActionListener* const listener) { - jassert (actionListenerList.isValidMessageListener()); + jassert (actionListenerList.isValidMessageListener()); - if (actionListenerList.isValidMessageListener()) - actionListenerList.removeActionListener (listener); + if (actionListenerList.isValidMessageListener()) + actionListenerList.removeActionListener (listener); } void ActionBroadcaster::removeAllActionListeners() { - actionListenerList.removeAllActionListeners(); + actionListenerList.removeAllActionListeners(); } void ActionBroadcaster::sendActionMessage (const String& message) const { - actionListenerList.sendActionMessage (message); + actionListenerList.sendActionMessage (message); } END_JUCE_NAMESPACE @@ -37257,22 +36961,22 @@ BEGIN_JUCE_NAMESPACE class ActionMessage : public Message { public: - const String message; + const String message; - ActionMessage (const String& messageText, - void* const listener_) throw() - : message (messageText) - { - pointerParameter = listener_; - } + ActionMessage (const String& messageText, + void* const listener_) throw() + : message (messageText) + { + pointerParameter = listener_; + } - ~ActionMessage() throw() - { - } + ~ActionMessage() throw() + { + } private: - ActionMessage (const ActionMessage&); - const ActionMessage& operator= (const ActionMessage&); + ActionMessage (const ActionMessage&); + const ActionMessage& operator= (const ActionMessage&); }; ActionListenerList::ActionListenerList() throw() @@ -37285,47 +36989,47 @@ ActionListenerList::~ActionListenerList() throw() void ActionListenerList::addActionListener (ActionListener* const listener) throw() { - const ScopedLock sl (actionListenerLock_); + const ScopedLock sl (actionListenerLock_); - jassert (listener != 0); - jassert (! actionListeners_.contains (listener)); // trying to add a listener to the list twice! + jassert (listener != 0); + jassert (! actionListeners_.contains (listener)); // trying to add a listener to the list twice! - if (listener != 0) - actionListeners_.add (listener); + if (listener != 0) + actionListeners_.add (listener); } void ActionListenerList::removeActionListener (ActionListener* const listener) throw() { - const ScopedLock sl (actionListenerLock_); + const ScopedLock sl (actionListenerLock_); - jassert (actionListeners_.contains (listener)); // trying to remove a listener that isn't on the list! + jassert (actionListeners_.contains (listener)); // trying to remove a listener that isn't on the list! - actionListeners_.removeValue (listener); + actionListeners_.removeValue (listener); } void ActionListenerList::removeAllActionListeners() throw() { - const ScopedLock sl (actionListenerLock_); - actionListeners_.clear(); + const ScopedLock sl (actionListenerLock_); + actionListeners_.clear(); } void ActionListenerList::sendActionMessage (const String& message) const { - const ScopedLock sl (actionListenerLock_); + const ScopedLock sl (actionListenerLock_); - for (int i = actionListeners_.size(); --i >= 0;) - { - postMessage (new ActionMessage (message, - (ActionListener*) actionListeners_.getUnchecked(i))); - } + for (int i = actionListeners_.size(); --i >= 0;) + { + postMessage (new ActionMessage (message, + (ActionListener*) actionListeners_.getUnchecked(i))); + } } void ActionListenerList::handleMessage (const Message& message) { - const ActionMessage& am = (const ActionMessage&) message; + const ActionMessage& am = (const ActionMessage&) message; - if (actionListeners_.contains (am.pointerParameter)) - ((ActionListener*) am.pointerParameter)->actionListenerCallback (am.message); + if (actionListeners_.contains (am.pointerParameter)) + ((ActionListener*) am.pointerParameter)->actionListenerCallback (am.message); } END_JUCE_NAMESPACE @@ -37338,7 +37042,7 @@ BEGIN_JUCE_NAMESPACE AsyncUpdater::AsyncUpdater() throw() : asyncMessagePending (false) { - internalAsyncHandler.owner = this; + internalAsyncHandler.owner = this; } AsyncUpdater::~AsyncUpdater() @@ -37347,30 +37051,30 @@ AsyncUpdater::~AsyncUpdater() void AsyncUpdater::triggerAsyncUpdate() throw() { - if (! asyncMessagePending) - { - asyncMessagePending = true; - internalAsyncHandler.postMessage (new Message()); - } + if (! asyncMessagePending) + { + asyncMessagePending = true; + internalAsyncHandler.postMessage (new Message()); + } } void AsyncUpdater::cancelPendingUpdate() throw() { - asyncMessagePending = false; + asyncMessagePending = false; } void AsyncUpdater::handleUpdateNowIfNeeded() { - if (asyncMessagePending) - { - asyncMessagePending = false; - handleAsyncUpdate(); - } + if (asyncMessagePending) + { + asyncMessagePending = false; + handleAsyncUpdate(); + } } void AsyncUpdater::AsyncUpdaterInternal::handleMessage (const Message&) { - owner->handleUpdateNowIfNeeded(); + owner->handleUpdateNowIfNeeded(); } END_JUCE_NAMESPACE @@ -37382,47 +37086,47 @@ BEGIN_JUCE_NAMESPACE ChangeBroadcaster::ChangeBroadcaster() throw() { - // are you trying to create this object before or after juce has been intialised?? - jassert (MessageManager::instance != 0); + // are you trying to create this object before or after juce has been intialised?? + jassert (MessageManager::instance != 0); } ChangeBroadcaster::~ChangeBroadcaster() { - // all event-based objects must be deleted BEFORE juce is shut down! - jassert (MessageManager::instance != 0); + // all event-based objects must be deleted BEFORE juce is shut down! + jassert (MessageManager::instance != 0); } void ChangeBroadcaster::addChangeListener (ChangeListener* const listener) throw() { - changeListenerList.addChangeListener (listener); + changeListenerList.addChangeListener (listener); } void ChangeBroadcaster::removeChangeListener (ChangeListener* const listener) throw() { - jassert (changeListenerList.isValidMessageListener()); + jassert (changeListenerList.isValidMessageListener()); - if (changeListenerList.isValidMessageListener()) - changeListenerList.removeChangeListener (listener); + if (changeListenerList.isValidMessageListener()) + changeListenerList.removeChangeListener (listener); } void ChangeBroadcaster::removeAllChangeListeners() throw() { - changeListenerList.removeAllChangeListeners(); + changeListenerList.removeAllChangeListeners(); } void ChangeBroadcaster::sendChangeMessage (void* objectThatHasChanged) throw() { - changeListenerList.sendChangeMessage (objectThatHasChanged); + changeListenerList.sendChangeMessage (objectThatHasChanged); } void ChangeBroadcaster::sendSynchronousChangeMessage (void* objectThatHasChanged) { - changeListenerList.sendSynchronousChangeMessage (objectThatHasChanged); + changeListenerList.sendSynchronousChangeMessage (objectThatHasChanged); } void ChangeBroadcaster::dispatchPendingMessages() { - changeListenerList.dispatchPendingMessages(); + changeListenerList.dispatchPendingMessages(); } END_JUCE_NAMESPACE @@ -37434,7 +37138,7 @@ BEGIN_JUCE_NAMESPACE ChangeListenerList::ChangeListenerList() throw() : lastChangedObject (0), - messagePending (false) + messagePending (false) { } @@ -37444,65 +37148,65 @@ ChangeListenerList::~ChangeListenerList() throw() void ChangeListenerList::addChangeListener (ChangeListener* const listener) throw() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - jassert (listener != 0); + jassert (listener != 0); - if (listener != 0) - listeners.add (listener); + if (listener != 0) + listeners.add (listener); } void ChangeListenerList::removeChangeListener (ChangeListener* const listener) throw() { - const ScopedLock sl (lock); - listeners.removeValue (listener); + const ScopedLock sl (lock); + listeners.removeValue (listener); } void ChangeListenerList::removeAllChangeListeners() throw() { - const ScopedLock sl (lock); - listeners.clear(); + const ScopedLock sl (lock); + listeners.clear(); } void ChangeListenerList::sendChangeMessage (void* const objectThatHasChanged) throw() { - const ScopedLock sl (lock); + const ScopedLock sl (lock); - if ((! messagePending) && (listeners.size() > 0)) - { - lastChangedObject = objectThatHasChanged; - postMessage (new Message (0, 0, 0, objectThatHasChanged)); - messagePending = true; - } + if ((! messagePending) && (listeners.size() > 0)) + { + lastChangedObject = objectThatHasChanged; + postMessage (new Message (0, 0, 0, objectThatHasChanged)); + messagePending = true; + } } void ChangeListenerList::handleMessage (const Message& message) { - sendSynchronousChangeMessage (message.pointerParameter); + sendSynchronousChangeMessage (message.pointerParameter); } void ChangeListenerList::sendSynchronousChangeMessage (void* const objectThatHasChanged) { - const ScopedLock sl (lock); - messagePending = false; + const ScopedLock sl (lock); + messagePending = false; - for (int i = listeners.size(); --i >= 0;) - { - ChangeListener* const l = (ChangeListener*) listeners.getUnchecked (i); + for (int i = listeners.size(); --i >= 0;) + { + ChangeListener* const l = (ChangeListener*) listeners.getUnchecked (i); - { - const ScopedUnlock tempUnlocker (lock); - l->changeListenerCallback (objectThatHasChanged); - } + { + const ScopedUnlock tempUnlocker (lock); + l->changeListenerCallback (objectThatHasChanged); + } - i = jmin (i, listeners.size()); - } + i = jmin (i, listeners.size()); + } } void ChangeListenerList::dispatchPendingMessages() { - if (messagePending) - sendSynchronousChangeMessage (lastChangedObject); + if (messagePending) + sendSynchronousChangeMessage (lastChangedObject); } END_JUCE_NAMESPACE @@ -37513,340 +37217,340 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE InterprocessConnection::InterprocessConnection (const bool callbacksOnMessageThread, - const uint32 magicMessageHeaderNumber) - : Thread ("Juce IPC connection"), - callbackConnectionState (false), - useMessageThread (callbacksOnMessageThread), - magicMessageHeader (magicMessageHeaderNumber), - pipeReceiveMessageTimeout (-1) + const uint32 magicMessageHeaderNumber) + : Thread ("Juce IPC connection"), + callbackConnectionState (false), + useMessageThread (callbacksOnMessageThread), + magicMessageHeader (magicMessageHeaderNumber), + pipeReceiveMessageTimeout (-1) { } InterprocessConnection::~InterprocessConnection() { - callbackConnectionState = false; - disconnect(); + callbackConnectionState = false; + disconnect(); } bool InterprocessConnection::connectToSocket (const String& hostName, - const int portNumber, - const int timeOutMillisecs) + const int portNumber, + const int timeOutMillisecs) { - disconnect(); + disconnect(); - const ScopedLock sl (pipeAndSocketLock); - socket = new StreamingSocket(); + const ScopedLock sl (pipeAndSocketLock); + socket = new StreamingSocket(); - if (socket->connect (hostName, portNumber, timeOutMillisecs)) - { - connectionMadeInt(); - startThread(); - return true; - } - else - { - socket = 0; - return false; - } + if (socket->connect (hostName, portNumber, timeOutMillisecs)) + { + connectionMadeInt(); + startThread(); + return true; + } + else + { + socket = 0; + return false; + } } bool InterprocessConnection::connectToPipe (const String& pipeName, - const int pipeReceiveMessageTimeoutMs) + const int pipeReceiveMessageTimeoutMs) { - disconnect(); + disconnect(); - ScopedPointer newPipe (new NamedPipe()); + ScopedPointer newPipe (new NamedPipe()); - if (newPipe->openExisting (pipeName)) - { - const ScopedLock sl (pipeAndSocketLock); - pipeReceiveMessageTimeout = pipeReceiveMessageTimeoutMs; - initialiseWithPipe (newPipe.release()); - return true; - } + if (newPipe->openExisting (pipeName)) + { + const ScopedLock sl (pipeAndSocketLock); + pipeReceiveMessageTimeout = pipeReceiveMessageTimeoutMs; + initialiseWithPipe (newPipe.release()); + return true; + } - return false; + return false; } bool InterprocessConnection::createPipe (const String& pipeName, - const int pipeReceiveMessageTimeoutMs) + const int pipeReceiveMessageTimeoutMs) { - disconnect(); + disconnect(); - ScopedPointer newPipe (new NamedPipe()); + ScopedPointer newPipe (new NamedPipe()); - if (newPipe->createNewPipe (pipeName)) - { - const ScopedLock sl (pipeAndSocketLock); - pipeReceiveMessageTimeout = pipeReceiveMessageTimeoutMs; - initialiseWithPipe (newPipe.release()); - return true; - } + if (newPipe->createNewPipe (pipeName)) + { + const ScopedLock sl (pipeAndSocketLock); + pipeReceiveMessageTimeout = pipeReceiveMessageTimeoutMs; + initialiseWithPipe (newPipe.release()); + return true; + } - return false; + return false; } void InterprocessConnection::disconnect() { - if (socket != 0) - socket->close(); + if (socket != 0) + socket->close(); - if (pipe != 0) - { - pipe->cancelPendingReads(); - pipe->close(); - } + if (pipe != 0) + { + pipe->cancelPendingReads(); + pipe->close(); + } - stopThread (4000); + stopThread (4000); - { - const ScopedLock sl (pipeAndSocketLock); - socket = 0; - pipe = 0; - } + { + const ScopedLock sl (pipeAndSocketLock); + socket = 0; + pipe = 0; + } - connectionLostInt(); + connectionLostInt(); } bool InterprocessConnection::isConnected() const { - const ScopedLock sl (pipeAndSocketLock); + const ScopedLock sl (pipeAndSocketLock); - return ((socket != 0 && socket->isConnected()) - || (pipe != 0 && pipe->isOpen())) - && isThreadRunning(); + return ((socket != 0 && socket->isConnected()) + || (pipe != 0 && pipe->isOpen())) + && isThreadRunning(); } const String InterprocessConnection::getConnectedHostName() const { - if (pipe != 0) - { - return "localhost"; - } - else if (socket != 0) - { - if (! socket->isLocal()) - return socket->getHostName(); + if (pipe != 0) + { + return "localhost"; + } + else if (socket != 0) + { + if (! socket->isLocal()) + return socket->getHostName(); - return "localhost"; - } + return "localhost"; + } - return String::empty; + return String::empty; } bool InterprocessConnection::sendMessage (const MemoryBlock& message) { - uint32 messageHeader[2]; - messageHeader [0] = ByteOrder::swapIfBigEndian (magicMessageHeader); - messageHeader [1] = ByteOrder::swapIfBigEndian ((uint32) message.getSize()); + uint32 messageHeader[2]; + messageHeader [0] = ByteOrder::swapIfBigEndian (magicMessageHeader); + messageHeader [1] = ByteOrder::swapIfBigEndian ((uint32) message.getSize()); - MemoryBlock messageData (sizeof (messageHeader) + message.getSize()); - messageData.copyFrom (messageHeader, 0, sizeof (messageHeader)); - messageData.copyFrom (message.getData(), sizeof (messageHeader), message.getSize()); + MemoryBlock messageData (sizeof (messageHeader) + message.getSize()); + messageData.copyFrom (messageHeader, 0, sizeof (messageHeader)); + messageData.copyFrom (message.getData(), sizeof (messageHeader), message.getSize()); - int bytesWritten = 0; + size_t bytesWritten = 0; - const ScopedLock sl (pipeAndSocketLock); + const ScopedLock sl (pipeAndSocketLock); - if (socket != 0) - { - bytesWritten = socket->write (messageData.getData(), messageData.getSize()); - } - else if (pipe != 0) - { - bytesWritten = pipe->write (messageData.getData(), messageData.getSize()); - } + if (socket != 0) + { + bytesWritten = socket->write (messageData.getData(), (int) messageData.getSize()); + } + else if (pipe != 0) + { + bytesWritten = pipe->write (messageData.getData(), (int) messageData.getSize()); + } - if (bytesWritten < 0) - { - // error.. - return false; - } + if (bytesWritten < 0) + { + // error.. + return false; + } - return (bytesWritten == messageData.getSize()); + return (bytesWritten == messageData.getSize()); } void InterprocessConnection::initialiseWithSocket (StreamingSocket* const socket_) { - jassert (socket == 0); - socket = socket_; - connectionMadeInt(); - startThread(); + jassert (socket == 0); + socket = socket_; + connectionMadeInt(); + startThread(); } void InterprocessConnection::initialiseWithPipe (NamedPipe* const pipe_) { - jassert (pipe == 0); - pipe = pipe_; - connectionMadeInt(); - startThread(); + jassert (pipe == 0); + pipe = pipe_; + connectionMadeInt(); + startThread(); } const int messageMagicNumber = 0xb734128b; void InterprocessConnection::handleMessage (const Message& message) { - if (message.intParameter1 == messageMagicNumber) - { - switch (message.intParameter2) - { - case 0: - { - ScopedPointer data ((MemoryBlock*) message.pointerParameter); - messageReceived (*data); - break; - } + if (message.intParameter1 == messageMagicNumber) + { + switch (message.intParameter2) + { + case 0: + { + ScopedPointer data ((MemoryBlock*) message.pointerParameter); + messageReceived (*data); + break; + } - case 1: - connectionMade(); - break; + case 1: + connectionMade(); + break; - case 2: - connectionLost(); - break; - } - } + case 2: + connectionLost(); + break; + } + } } void InterprocessConnection::connectionMadeInt() { - if (! callbackConnectionState) - { - callbackConnectionState = true; + if (! callbackConnectionState) + { + callbackConnectionState = true; - if (useMessageThread) - postMessage (new Message (messageMagicNumber, 1, 0, 0)); - else - connectionMade(); - } + if (useMessageThread) + postMessage (new Message (messageMagicNumber, 1, 0, 0)); + else + connectionMade(); + } } void InterprocessConnection::connectionLostInt() { - if (callbackConnectionState) - { - callbackConnectionState = false; + if (callbackConnectionState) + { + callbackConnectionState = false; - if (useMessageThread) - postMessage (new Message (messageMagicNumber, 2, 0, 0)); - else - connectionLost(); - } + if (useMessageThread) + postMessage (new Message (messageMagicNumber, 2, 0, 0)); + else + connectionLost(); + } } void InterprocessConnection::deliverDataInt (const MemoryBlock& data) { - jassert (callbackConnectionState); + jassert (callbackConnectionState); - if (useMessageThread) - postMessage (new Message (messageMagicNumber, 0, 0, new MemoryBlock (data))); - else - messageReceived (data); + if (useMessageThread) + postMessage (new Message (messageMagicNumber, 0, 0, new MemoryBlock (data))); + else + messageReceived (data); } bool InterprocessConnection::readNextMessageInt() { - const int maximumMessageSize = 1024 * 1024 * 10; // sanity check + const int maximumMessageSize = 1024 * 1024 * 10; // sanity check - uint32 messageHeader[2]; - const int bytes = (socket != 0) ? socket->read (messageHeader, sizeof (messageHeader), true) - : pipe->read (messageHeader, sizeof (messageHeader), pipeReceiveMessageTimeout); + uint32 messageHeader[2]; + const int bytes = (socket != 0) ? socket->read (messageHeader, sizeof (messageHeader), true) + : pipe->read (messageHeader, sizeof (messageHeader), pipeReceiveMessageTimeout); - if (bytes == sizeof (messageHeader) - && ByteOrder::swapIfBigEndian (messageHeader[0]) == magicMessageHeader) - { - const int bytesInMessage = (int) ByteOrder::swapIfBigEndian (messageHeader[1]); + if (bytes == sizeof (messageHeader) + && ByteOrder::swapIfBigEndian (messageHeader[0]) == magicMessageHeader) + { + const int bytesInMessage = (int) ByteOrder::swapIfBigEndian (messageHeader[1]); - if (bytesInMessage > 0 && bytesInMessage < maximumMessageSize) - { - MemoryBlock messageData (bytesInMessage, true); - int bytesRead = 0; + if (bytesInMessage > 0 && bytesInMessage < maximumMessageSize) + { + MemoryBlock messageData (bytesInMessage, true); + int bytesRead = 0; - while (bytesRead < bytesInMessage) - { - if (threadShouldExit()) - return false; + while (bytesRead < bytesInMessage) + { + if (threadShouldExit()) + return false; - const int numThisTime = jmin (bytesInMessage, 65536); - const int bytesIn = (socket != 0) ? socket->read (((char*) messageData.getData()) + bytesRead, numThisTime, true) - : pipe->read (((char*) messageData.getData()) + bytesRead, numThisTime, - pipeReceiveMessageTimeout); + const int numThisTime = jmin (bytesInMessage, 65536); + const int bytesIn = (socket != 0) ? socket->read (((char*) messageData.getData()) + bytesRead, numThisTime, true) + : pipe->read (((char*) messageData.getData()) + bytesRead, numThisTime, + pipeReceiveMessageTimeout); - if (bytesIn <= 0) - break; + if (bytesIn <= 0) + break; - bytesRead += bytesIn; - } + bytesRead += bytesIn; + } - if (bytesRead >= 0) - deliverDataInt (messageData); - } - } - else if (bytes < 0) - { - { - const ScopedLock sl (pipeAndSocketLock); - socket = 0; - } + if (bytesRead >= 0) + deliverDataInt (messageData); + } + } + else if (bytes < 0) + { + { + const ScopedLock sl (pipeAndSocketLock); + socket = 0; + } - connectionLostInt(); - return false; - } + connectionLostInt(); + return false; + } - return true; + return true; } void InterprocessConnection::run() { - while (! threadShouldExit()) - { - if (socket != 0) - { - const int ready = socket->waitUntilReady (true, 0); + while (! threadShouldExit()) + { + if (socket != 0) + { + const int ready = socket->waitUntilReady (true, 0); - if (ready < 0) - { - { - const ScopedLock sl (pipeAndSocketLock); - socket = 0; - } + if (ready < 0) + { + { + const ScopedLock sl (pipeAndSocketLock); + socket = 0; + } - connectionLostInt(); - break; - } - else if (ready > 0) - { - if (! readNextMessageInt()) - break; - } - else - { - Thread::sleep (2); - } - } - else if (pipe != 0) - { - if (! pipe->isOpen()) - { - { - const ScopedLock sl (pipeAndSocketLock); - pipe = 0; - } + connectionLostInt(); + break; + } + else if (ready > 0) + { + if (! readNextMessageInt()) + break; + } + else + { + Thread::sleep (2); + } + } + else if (pipe != 0) + { + if (! pipe->isOpen()) + { + { + const ScopedLock sl (pipeAndSocketLock); + pipe = 0; + } - connectionLostInt(); - break; - } - else - { - if (! readNextMessageInt()) - break; - } - } - else - { - break; - } - } + connectionLostInt(); + break; + } + else + { + if (! readNextMessageInt()) + break; + } + } + else + { + break; + } + } } END_JUCE_NAMESPACE @@ -37857,56 +37561,56 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE InterprocessConnectionServer::InterprocessConnectionServer() - : Thread ("Juce IPC server") + : Thread ("Juce IPC server") { } InterprocessConnectionServer::~InterprocessConnectionServer() { - stop(); + stop(); } bool InterprocessConnectionServer::beginWaitingForSocket (const int portNumber) { - stop(); + stop(); - socket = new StreamingSocket(); + socket = new StreamingSocket(); - if (socket->createListener (portNumber)) - { - startThread(); - return true; - } + if (socket->createListener (portNumber)) + { + startThread(); + return true; + } - socket = 0; - return false; + socket = 0; + return false; } void InterprocessConnectionServer::stop() { - signalThreadShouldExit(); + signalThreadShouldExit(); - if (socket != 0) - socket->close(); + if (socket != 0) + socket->close(); - stopThread (4000); - socket = 0; + stopThread (4000); + socket = 0; } void InterprocessConnectionServer::run() { - while ((! threadShouldExit()) && socket != 0) - { - ScopedPointer clientSocket (socket->waitForNextConnection()); + while ((! threadShouldExit()) && socket != 0) + { + ScopedPointer clientSocket (socket->waitForNextConnection()); - if (clientSocket != 0) - { - InterprocessConnection* newConnection = createConnectionObject(); + if (clientSocket != 0) + { + InterprocessConnection* newConnection = createConnectionObject(); - if (newConnection != 0) - newConnection->initialiseWithSocket (clientSocket.release()); - } - } + if (newConnection != 0) + newConnection->initialiseWithSocket (clientSocket.release()); + } + } } END_JUCE_NAMESPACE @@ -37925,13 +37629,13 @@ Message::~Message() throw() } Message::Message (const int intParameter1_, - const int intParameter2_, - const int intParameter3_, - void* const pointerParameter_) throw() - : intParameter1 (intParameter1_), - intParameter2 (intParameter2_), - intParameter3 (intParameter3_), - pointerParameter (pointerParameter_) + const int intParameter2_, + const int intParameter3_, + void* const pointerParameter_) throw() + : intParameter1 (intParameter1_), + intParameter2 (intParameter2_), + intParameter3 (intParameter3_), + pointerParameter (pointerParameter_) { } @@ -37944,33 +37648,33 @@ BEGIN_JUCE_NAMESPACE MessageListener::MessageListener() throw() { - // are you trying to create a messagelistener before or after juce has been intialised?? - jassert (MessageManager::instance != 0); + // are you trying to create a messagelistener before or after juce has been intialised?? + jassert (MessageManager::instance != 0); - if (MessageManager::instance != 0) - MessageManager::instance->messageListeners.add (this); + if (MessageManager::instance != 0) + MessageManager::instance->messageListeners.add (this); } MessageListener::~MessageListener() { - if (MessageManager::instance != 0) - MessageManager::instance->messageListeners.removeValue (this); + if (MessageManager::instance != 0) + MessageManager::instance->messageListeners.removeValue (this); } void MessageListener::postMessage (Message* const message) const throw() { - message->messageRecipient = const_cast (this); + message->messageRecipient = const_cast (this); - if (MessageManager::instance == 0) - MessageManager::getInstance(); + if (MessageManager::instance == 0) + MessageManager::getInstance(); - MessageManager::instance->postMessageToQueue (message); + MessageManager::instance->postMessageToQueue (message); } bool MessageListener::isValidMessageListener() const throw() { - return (MessageManager::instance != 0) - && MessageManager::instance->messageListeners.contains (this); + return (MessageManager::instance != 0) + && MessageManager::instance->messageListeners.contains (this); } END_JUCE_NAMESPACE @@ -37990,37 +37694,37 @@ static const int quitMessageId = 0xfffff321; MessageManager::MessageManager() throw() : quitMessagePosted (false), - quitMessageReceived (false), - threadWithLock (0) + quitMessageReceived (false), + threadWithLock (0) { - messageThreadId = Thread::getCurrentThreadId(); + messageThreadId = Thread::getCurrentThreadId(); } MessageManager::~MessageManager() throw() { - broadcastListeners = 0; + broadcastListeners = 0; - doPlatformSpecificShutdown(); + doPlatformSpecificShutdown(); - jassert (instance == this); - instance = 0; // do this last in case this instance is still needed by doPlatformSpecificShutdown() + jassert (instance == this); + instance = 0; // do this last in case this instance is still needed by doPlatformSpecificShutdown() } MessageManager* MessageManager::getInstance() throw() { - if (instance == 0) - { - instance = new MessageManager(); - doPlatformSpecificInitialisation(); - } + if (instance == 0) + { + instance = new MessageManager(); + doPlatformSpecificInitialisation(); + } - return instance; + return instance; } void MessageManager::postMessageToQueue (Message* const message) { - if (quitMessagePosted || ! juce_postMessageToSystemQueue (message)) - delete message; + if (quitMessagePosted || ! juce_postMessageToSystemQueue (message)) + delete message; } CallbackMessage::CallbackMessage() throw() {} @@ -38028,248 +37732,236 @@ CallbackMessage::~CallbackMessage() throw() {} void CallbackMessage::post() { - if (MessageManager::instance != 0) - MessageManager::instance->postCallbackMessage (this); + if (MessageManager::instance != 0) + MessageManager::instance->postCallbackMessage (this); } void MessageManager::postCallbackMessage (Message* const message) { - message->messageRecipient = 0; - postMessageToQueue (message); + message->messageRecipient = 0; + postMessageToQueue (message); } // not for public use.. void MessageManager::deliverMessage (void* message) { - const ScopedPointer m ((Message*) message); - MessageListener* const recipient = m->messageRecipient; + const ScopedPointer m ((Message*) message); + MessageListener* const recipient = m->messageRecipient; - JUCE_TRY - { - if (messageListeners.contains (recipient)) - { - recipient->handleMessage (*m); - } - else if (recipient == 0) - { - if (m->intParameter1 == quitMessageId) - { - quitMessageReceived = true; - } - else - { - CallbackMessage* const cm = dynamic_cast ((Message*) m); + JUCE_TRY + { + if (messageListeners.contains (recipient)) + { + recipient->handleMessage (*m); + } + else if (recipient == 0) + { + if (m->intParameter1 == quitMessageId) + { + quitMessageReceived = true; + } + else + { + CallbackMessage* const cm = dynamic_cast ((Message*) m); - if (cm != 0) - cm->messageCallback(); - } - } - } - JUCE_CATCH_EXCEPTION + if (cm != 0) + cm->messageCallback(); + } + } + } + JUCE_CATCH_EXCEPTION } #if ! (JUCE_MAC || JUCE_IPHONE) void MessageManager::runDispatchLoop() { - jassert (isThisTheMessageThread()); // must only be called by the message thread + jassert (isThisTheMessageThread()); // must only be called by the message thread - runDispatchLoopUntil (-1); + runDispatchLoopUntil (-1); } void MessageManager::stopDispatchLoop() { - Message* const m = new Message (quitMessageId, 0, 0, 0); - m->messageRecipient = 0; - postMessageToQueue (m); + Message* const m = new Message (quitMessageId, 0, 0, 0); + m->messageRecipient = 0; + postMessageToQueue (m); - quitMessagePosted = true; + quitMessagePosted = true; } bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) { - jassert (isThisTheMessageThread()); // must only be called by the message thread + jassert (isThisTheMessageThread()); // must only be called by the message thread - const int64 endTime = Time::currentTimeMillis() + millisecondsToRunFor; + const int64 endTime = Time::currentTimeMillis() + millisecondsToRunFor; - while ((millisecondsToRunFor < 0 || endTime > Time::currentTimeMillis()) - && ! quitMessageReceived) - { - JUCE_TRY - { - if (! juce_dispatchNextMessageOnSystemQueue (millisecondsToRunFor >= 0)) - { - const int msToWait = (int) (endTime - Time::currentTimeMillis()); + while ((millisecondsToRunFor < 0 || endTime > Time::currentTimeMillis()) + && ! quitMessageReceived) + { + JUCE_TRY + { + if (! juce_dispatchNextMessageOnSystemQueue (millisecondsToRunFor >= 0)) + { + const int msToWait = (int) (endTime - Time::currentTimeMillis()); - if (msToWait > 0) - Thread::sleep (jmin (5, msToWait)); - } - } - JUCE_CATCH_EXCEPTION - } + if (msToWait > 0) + Thread::sleep (jmin (5, msToWait)); + } + } + JUCE_CATCH_EXCEPTION + } - return ! quitMessageReceived; + return ! quitMessageReceived; } #endif void MessageManager::deliverBroadcastMessage (const String& value) { - if (broadcastListeners != 0) - broadcastListeners->sendActionMessage (value); + if (broadcastListeners != 0) + broadcastListeners->sendActionMessage (value); } void MessageManager::registerBroadcastListener (ActionListener* const listener) throw() { - if (broadcastListeners == 0) - broadcastListeners = new ActionListenerList(); + if (broadcastListeners == 0) + broadcastListeners = new ActionListenerList(); - broadcastListeners->addActionListener (listener); + broadcastListeners->addActionListener (listener); } void MessageManager::deregisterBroadcastListener (ActionListener* const listener) throw() { - if (broadcastListeners != 0) - broadcastListeners->removeActionListener (listener); + if (broadcastListeners != 0) + broadcastListeners->removeActionListener (listener); } bool MessageManager::isThisTheMessageThread() const throw() { - return Thread::getCurrentThreadId() == messageThreadId; + return Thread::getCurrentThreadId() == messageThreadId; } void MessageManager::setCurrentMessageThread (const Thread::ThreadID threadId) throw() { - messageThreadId = threadId; + messageThreadId = threadId; } bool MessageManager::currentThreadHasLockedMessageManager() const throw() { - const Thread::ThreadID thisThread = Thread::getCurrentThreadId(); - return thisThread == messageThreadId || thisThread == threadWithLock; + const Thread::ThreadID thisThread = Thread::getCurrentThreadId(); + return thisThread == messageThreadId || thisThread == threadWithLock; } -/* The only safe way to lock the message thread while another thread does - some work is by posting a special message, whose purpose is to tie up the event - loop until the other thread has finished its business. - - Any other approach can get horribly deadlocked if the OS uses its own hidden locks which - get locked before making an event callback, because if the same OS lock gets indirectly - accessed from another thread inside a MM lock, you're screwed. (this is exactly what happens - in Cocoa). -*/ class SharedLockingEvents : public ReferenceCountedObject { public: - SharedLockingEvents() throw() {} - ~SharedLockingEvents() {} + SharedLockingEvents() throw() {} + ~SharedLockingEvents() {} - /* This class just holds a couple of events to communicate between the MMLockMessage - and the MessageManagerLock. Because both of these objects may be deleted at any time, - this shared data must be kept in a separate, ref-counted container. */ - WaitableEvent lockedEvent, releaseEvent; + WaitableEvent lockedEvent, releaseEvent; }; class MMLockMessage : public CallbackMessage { public: - MMLockMessage (SharedLockingEvents* const events_) throw() - : events (events_) - {} + MMLockMessage (SharedLockingEvents* const events_) throw() + : events (events_) + {} - ~MMLockMessage() throw() {} + ~MMLockMessage() throw() {} - ReferenceCountedObjectPtr events; + ReferenceCountedObjectPtr events; - void messageCallback() - { - events->lockedEvent.signal(); - events->releaseEvent.wait(); - } + void messageCallback() + { + events->lockedEvent.signal(); + events->releaseEvent.wait(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - MMLockMessage (const MMLockMessage&); - const MMLockMessage& operator= (const MMLockMessage&); + MMLockMessage (const MMLockMessage&); + const MMLockMessage& operator= (const MMLockMessage&); }; MessageManagerLock::MessageManagerLock (Thread* const threadToCheck) throw() - : locked (false), - needsUnlocking (false) + : locked (false), + needsUnlocking (false) { - init (threadToCheck, 0); + init (threadToCheck, 0); } MessageManagerLock::MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal) throw() - : locked (false), - needsUnlocking (false) + : locked (false), + needsUnlocking (false) { - init (0, jobToCheckForExitSignal); + init (0, jobToCheckForExitSignal); } void MessageManagerLock::init (Thread* const threadToCheck, ThreadPoolJob* const job) throw() { - if (MessageManager::instance != 0) - { - if (MessageManager::instance->currentThreadHasLockedMessageManager()) - { - locked = true; // either we're on the message thread, or this is a re-entrant call. - } - else - { - if (threadToCheck == 0 && job == 0) - { - MessageManager::instance->lockingLock.enter(); - } - else - { - while (! MessageManager::instance->lockingLock.tryEnter()) - { - if ((threadToCheck != 0 && threadToCheck->threadShouldExit()) - || (job != 0 && job->shouldExit())) - return; + if (MessageManager::instance != 0) + { + if (MessageManager::instance->currentThreadHasLockedMessageManager()) + { + locked = true; // either we're on the message thread, or this is a re-entrant call. + } + else + { + if (threadToCheck == 0 && job == 0) + { + MessageManager::instance->lockingLock.enter(); + } + else + { + while (! MessageManager::instance->lockingLock.tryEnter()) + { + if ((threadToCheck != 0 && threadToCheck->threadShouldExit()) + || (job != 0 && job->shouldExit())) + return; - Thread::sleep (1); - } - } + Thread::sleep (1); + } + } - SharedLockingEvents* const events = new SharedLockingEvents(); - sharedEvents = events; - events->incReferenceCount(); + SharedLockingEvents* const events = new SharedLockingEvents(); + sharedEvents = events; + events->incReferenceCount(); - (new MMLockMessage (events))->post(); + (new MMLockMessage (events))->post(); - while (! events->lockedEvent.wait (50)) - { - if ((threadToCheck != 0 && threadToCheck->threadShouldExit()) - || (job != 0 && job->shouldExit())) - { - events->releaseEvent.signal(); - events->decReferenceCount(); - MessageManager::instance->lockingLock.exit(); - return; - } - } + while (! events->lockedEvent.wait (50)) + { + if ((threadToCheck != 0 && threadToCheck->threadShouldExit()) + || (job != 0 && job->shouldExit())) + { + events->releaseEvent.signal(); + events->decReferenceCount(); + MessageManager::instance->lockingLock.exit(); + return; + } + } - jassert (MessageManager::instance->threadWithLock == 0); + jassert (MessageManager::instance->threadWithLock == 0); - MessageManager::instance->threadWithLock = Thread::getCurrentThreadId(); - locked = true; - needsUnlocking = true; - } - } + MessageManager::instance->threadWithLock = Thread::getCurrentThreadId(); + locked = true; + needsUnlocking = true; + } + } } MessageManagerLock::~MessageManagerLock() throw() { - if (needsUnlocking && MessageManager::instance != 0) - { - jassert (MessageManager::instance->currentThreadHasLockedMessageManager()); + if (needsUnlocking && MessageManager::instance != 0) + { + jassert (MessageManager::instance->currentThreadHasLockedMessageManager()); - ((SharedLockingEvents*) sharedEvents)->releaseEvent.signal(); - ((SharedLockingEvents*) sharedEvents)->decReferenceCount(); - MessageManager::instance->threadWithLock = 0; - MessageManager::instance->lockingLock.exit(); - } + ((SharedLockingEvents*) sharedEvents)->releaseEvent.signal(); + ((SharedLockingEvents*) sharedEvents)->decReferenceCount(); + MessageManager::instance->threadWithLock = 0; + MessageManager::instance->lockingLock.exit(); + } } END_JUCE_NAMESPACE @@ -38279,28 +37971,28 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -class MultiTimer::MultiTimerCallback : public Timer +class MultiTimer::MultiTimerCallback : public Timer { public: - MultiTimerCallback (const int timerId_, MultiTimer& owner_) - : timerId (timerId_), - owner (owner_) - { - } + MultiTimerCallback (const int timerId_, MultiTimer& owner_) + : timerId (timerId_), + owner (owner_) + { + } - ~MultiTimerCallback() - { - } + ~MultiTimerCallback() + { + } - void timerCallback() - { - owner.timerCallback (timerId); - } + void timerCallback() + { + owner.timerCallback (timerId); + } - const int timerId; + const int timerId; private: - MultiTimer& owner; + MultiTimer& owner; }; MultiTimer::MultiTimer() throw() @@ -38313,69 +38005,69 @@ MultiTimer::MultiTimer (const MultiTimer&) throw() MultiTimer::~MultiTimer() { - const ScopedLock sl (timerListLock); - timers.clear(); + const ScopedLock sl (timerListLock); + timers.clear(); } void MultiTimer::startTimer (const int timerId, const int intervalInMilliseconds) throw() { - const ScopedLock sl (timerListLock); + const ScopedLock sl (timerListLock); - for (int i = timers.size(); --i >= 0;) - { - MultiTimerCallback* const t = timers.getUnchecked(i); + for (int i = timers.size(); --i >= 0;) + { + MultiTimerCallback* const t = timers.getUnchecked(i); - if (t->timerId == timerId) - { - t->startTimer (intervalInMilliseconds); - return; - } - } + if (t->timerId == timerId) + { + t->startTimer (intervalInMilliseconds); + return; + } + } - MultiTimerCallback* const newTimer = new MultiTimerCallback (timerId, *this); - timers.add (newTimer); - newTimer->startTimer (intervalInMilliseconds); + MultiTimerCallback* const newTimer = new MultiTimerCallback (timerId, *this); + timers.add (newTimer); + newTimer->startTimer (intervalInMilliseconds); } void MultiTimer::stopTimer (const int timerId) throw() { - const ScopedLock sl (timerListLock); + const ScopedLock sl (timerListLock); - for (int i = timers.size(); --i >= 0;) - { - MultiTimerCallback* const t = timers.getUnchecked(i); + for (int i = timers.size(); --i >= 0;) + { + MultiTimerCallback* const t = timers.getUnchecked(i); - if (t->timerId == timerId) - t->stopTimer(); - } + if (t->timerId == timerId) + t->stopTimer(); + } } bool MultiTimer::isTimerRunning (const int timerId) const throw() { - const ScopedLock sl (timerListLock); + const ScopedLock sl (timerListLock); - for (int i = timers.size(); --i >= 0;) - { - const MultiTimerCallback* const t = timers.getUnchecked(i); - if (t->timerId == timerId) - return t->isTimerRunning(); - } + for (int i = timers.size(); --i >= 0;) + { + const MultiTimerCallback* const t = timers.getUnchecked(i); + if (t->timerId == timerId) + return t->isTimerRunning(); + } - return false; + return false; } int MultiTimer::getTimerInterval (const int timerId) const throw() { - const ScopedLock sl (timerListLock); + const ScopedLock sl (timerListLock); - for (int i = timers.size(); --i >= 0;) - { - const MultiTimerCallback* const t = timers.getUnchecked(i); - if (t->timerId == timerId) - return t->getTimerInterval(); - } + for (int i = timers.size(); --i >= 0;) + { + const MultiTimerCallback* const t = timers.getUnchecked(i); + if (t->timerId == timerId) + return t->getTimerInterval(); + } - return 0; + return 0; } END_JUCE_NAMESPACE @@ -38386,262 +38078,262 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE class InternalTimerThread : private Thread, - private MessageListener, - private DeletedAtShutdown, - private AsyncUpdater + private MessageListener, + private DeletedAtShutdown, + private AsyncUpdater { private: - friend class Timer; - static InternalTimerThread* instance; - static CriticalSection lock; + friend class Timer; + static InternalTimerThread* instance; + static CriticalSection lock; - Timer* volatile firstTimer; - bool volatile callbackNeeded; + Timer* volatile firstTimer; + bool volatile callbackNeeded; - InternalTimerThread (const InternalTimerThread&); - const InternalTimerThread& operator= (const InternalTimerThread&); + InternalTimerThread (const InternalTimerThread&); + const InternalTimerThread& operator= (const InternalTimerThread&); - void addTimer (Timer* const t) throw() - { + void addTimer (Timer* const t) throw() + { #ifdef JUCE_DEBUG - Timer* tt = firstTimer; + Timer* tt = firstTimer; - while (tt != 0) - { - // trying to add a timer that's already here - shouldn't get to this point, - // so if you get this assertion, let me know! - jassert (tt != t); + while (tt != 0) + { + // trying to add a timer that's already here - shouldn't get to this point, + // so if you get this assertion, let me know! + jassert (tt != t); - tt = tt->next; - } + tt = tt->next; + } - jassert (t->previous == 0 && t->next == 0); + jassert (t->previous == 0 && t->next == 0); #endif - Timer* i = firstTimer; + Timer* i = firstTimer; - if (i == 0 || i->countdownMs > t->countdownMs) - { - t->next = firstTimer; - firstTimer = t; - } - else - { - while (i->next != 0 && i->next->countdownMs <= t->countdownMs) - i = i->next; + if (i == 0 || i->countdownMs > t->countdownMs) + { + t->next = firstTimer; + firstTimer = t; + } + else + { + while (i->next != 0 && i->next->countdownMs <= t->countdownMs) + i = i->next; - jassert (i != 0); + jassert (i != 0); - t->next = i->next; - t->previous = i; - i->next = t; - } + t->next = i->next; + t->previous = i; + i->next = t; + } - if (t->next != 0) - t->next->previous = t; + if (t->next != 0) + t->next->previous = t; - jassert ((t->next == 0 || t->next->countdownMs >= t->countdownMs) - && (t->previous == 0 || t->previous->countdownMs <= t->countdownMs)); + jassert ((t->next == 0 || t->next->countdownMs >= t->countdownMs) + && (t->previous == 0 || t->previous->countdownMs <= t->countdownMs)); - notify(); - } + notify(); + } - void removeTimer (Timer* const t) throw() - { + void removeTimer (Timer* const t) throw() + { #ifdef JUCE_DEBUG - Timer* tt = firstTimer; - bool found = false; + Timer* tt = firstTimer; + bool found = false; - while (tt != 0) - { - if (tt == t) - { - found = true; - break; - } + while (tt != 0) + { + if (tt == t) + { + found = true; + break; + } - tt = tt->next; - } + tt = tt->next; + } - // trying to remove a timer that's not here - shouldn't get to this point, - // so if you get this assertion, let me know! - jassert (found); + // trying to remove a timer that's not here - shouldn't get to this point, + // so if you get this assertion, let me know! + jassert (found); #endif - if (t->previous != 0) - { - jassert (firstTimer != t); - t->previous->next = t->next; - } - else - { - jassert (firstTimer == t); - firstTimer = t->next; - } + if (t->previous != 0) + { + jassert (firstTimer != t); + t->previous->next = t->next; + } + else + { + jassert (firstTimer == t); + firstTimer = t->next; + } - if (t->next != 0) - t->next->previous = t->previous; + if (t->next != 0) + t->next->previous = t->previous; - t->next = 0; - t->previous = 0; - } + t->next = 0; + t->previous = 0; + } - void decrementAllCounters (const int numMillisecs) const - { - Timer* t = firstTimer; + void decrementAllCounters (const int numMillisecs) const + { + Timer* t = firstTimer; - while (t != 0) - { - t->countdownMs -= numMillisecs; - t = t->next; - } - } + while (t != 0) + { + t->countdownMs -= numMillisecs; + t = t->next; + } + } - void handleAsyncUpdate() - { - startThread (7); - } + void handleAsyncUpdate() + { + startThread (7); + } public: - InternalTimerThread() - : Thread ("Juce Timer"), - firstTimer (0), - callbackNeeded (false) - { - triggerAsyncUpdate(); - } + InternalTimerThread() + : Thread ("Juce Timer"), + firstTimer (0), + callbackNeeded (false) + { + triggerAsyncUpdate(); + } - ~InternalTimerThread() throw() - { - stopThread (4000); + ~InternalTimerThread() throw() + { + stopThread (4000); - jassert (instance == this || instance == 0); - if (instance == this) - instance = 0; - } + jassert (instance == this || instance == 0); + if (instance == this) + instance = 0; + } - void run() - { - uint32 lastTime = Time::getMillisecondCounter(); + void run() + { + uint32 lastTime = Time::getMillisecondCounter(); - while (! threadShouldExit()) - { - uint32 now = Time::getMillisecondCounter(); + while (! threadShouldExit()) + { + uint32 now = Time::getMillisecondCounter(); - if (now <= lastTime) - { - wait (2); - continue; - } + if (now <= lastTime) + { + wait (2); + continue; + } - const int elapsed = now - lastTime; - lastTime = now; + const int elapsed = now - lastTime; + lastTime = now; - lock.enter(); - decrementAllCounters (elapsed); - const int timeUntilFirstTimer = (firstTimer != 0) ? firstTimer->countdownMs - : 1000; - lock.exit(); + lock.enter(); + decrementAllCounters (elapsed); + const int timeUntilFirstTimer = (firstTimer != 0) ? firstTimer->countdownMs + : 1000; + lock.exit(); - if (timeUntilFirstTimer <= 0) - { - callbackNeeded = true; - postMessage (new Message()); + if (timeUntilFirstTimer <= 0) + { + callbackNeeded = true; + postMessage (new Message()); - // sometimes, our message could get discarded by the OS (particularly when running as an RTAS when the app has a modal loop), - // so this is how long to wait before assuming the message has been lost and trying again. - const uint32 messageDeliveryTimeout = now + 2000; + // sometimes, our message could get discarded by the OS (particularly when running as an RTAS when the app has a modal loop), + // so this is how long to wait before assuming the message has been lost and trying again. + const uint32 messageDeliveryTimeout = now + 2000; - while (callbackNeeded) - { - wait (4); + while (callbackNeeded) + { + wait (4); - if (threadShouldExit()) - return; + if (threadShouldExit()) + return; - now = Time::getMillisecondCounter(); + now = Time::getMillisecondCounter(); - if (now > messageDeliveryTimeout) - break; - } - } - else - { - // don't wait for too long because running this loop also helps keep the - // Time::getApproximateMillisecondTimer value stay up-to-date - wait (jlimit (1, 50, timeUntilFirstTimer)); - } - } - } + if (now > messageDeliveryTimeout) + break; + } + } + else + { + // don't wait for too long because running this loop also helps keep the + // Time::getApproximateMillisecondTimer value stay up-to-date + wait (jlimit (1, 50, timeUntilFirstTimer)); + } + } + } - void handleMessage (const Message&) - { - const ScopedLock sl (lock); + void handleMessage (const Message&) + { + const ScopedLock sl (lock); - while (firstTimer != 0 && firstTimer->countdownMs <= 0) - { - Timer* const t = firstTimer; - t->countdownMs = t->periodMs; + while (firstTimer != 0 && firstTimer->countdownMs <= 0) + { + Timer* const t = firstTimer; + t->countdownMs = t->periodMs; - removeTimer (t); - addTimer (t); + removeTimer (t); + addTimer (t); - const ScopedUnlock ul (lock); + const ScopedUnlock ul (lock); - JUCE_TRY - { - t->timerCallback(); - } - JUCE_CATCH_EXCEPTION - } + JUCE_TRY + { + t->timerCallback(); + } + JUCE_CATCH_EXCEPTION + } - callbackNeeded = false; - } + callbackNeeded = false; + } - static void callAnyTimersSynchronously() - { - if (InternalTimerThread::instance != 0) - { - const Message m; - InternalTimerThread::instance->handleMessage (m); - } - } + static void callAnyTimersSynchronously() + { + if (InternalTimerThread::instance != 0) + { + const Message m; + InternalTimerThread::instance->handleMessage (m); + } + } - static inline void add (Timer* const tim) throw() - { - if (instance == 0) - instance = new InternalTimerThread(); + static inline void add (Timer* const tim) throw() + { + if (instance == 0) + instance = new InternalTimerThread(); - const ScopedLock sl (instance->lock); - instance->addTimer (tim); - } + const ScopedLock sl (instance->lock); + instance->addTimer (tim); + } - static inline void remove (Timer* const tim) throw() - { - if (instance != 0) - { - const ScopedLock sl (instance->lock); - instance->removeTimer (tim); - } - } + static inline void remove (Timer* const tim) throw() + { + if (instance != 0) + { + const ScopedLock sl (instance->lock); + instance->removeTimer (tim); + } + } - static inline void resetCounter (Timer* const tim, - const int newCounter) throw() - { - if (instance != 0) - { - tim->countdownMs = newCounter; - tim->periodMs = newCounter; + static inline void resetCounter (Timer* const tim, + const int newCounter) throw() + { + if (instance != 0) + { + tim->countdownMs = newCounter; + tim->periodMs = newCounter; - if ((tim->next != 0 && tim->next->countdownMs < tim->countdownMs) - || (tim->previous != 0 && tim->previous->countdownMs > tim->countdownMs)) - { - const ScopedLock sl (instance->lock); - instance->removeTimer (tim); - instance->addTimer (tim); - } - } - } + if ((tim->next != 0 && tim->next->countdownMs < tim->countdownMs) + || (tim->previous != 0 && tim->previous->countdownMs > tim->countdownMs)) + { + const ScopedLock sl (instance->lock); + instance->removeTimer (tim); + instance->addTimer (tim); + } + } + } }; InternalTimerThread* InternalTimerThread::instance = 0; @@ -38649,7 +38341,7 @@ CriticalSection InternalTimerThread::lock; void juce_callAnyTimersSynchronously() { - InternalTimerThread::callAnyTimersSynchronously(); + InternalTimerThread::callAnyTimersSynchronously(); } #ifdef JUCE_DEBUG @@ -38658,70 +38350,70 @@ static SortedSet activeTimers; Timer::Timer() throw() : countdownMs (0), - periodMs (0), - previous (0), - next (0) + periodMs (0), + previous (0), + next (0) { #ifdef JUCE_DEBUG - activeTimers.add (this); + activeTimers.add (this); #endif } Timer::Timer (const Timer&) throw() : countdownMs (0), - periodMs (0), - previous (0), - next (0) + periodMs (0), + previous (0), + next (0) { #ifdef JUCE_DEBUG - activeTimers.add (this); + activeTimers.add (this); #endif } Timer::~Timer() { - stopTimer(); + stopTimer(); #ifdef JUCE_DEBUG - activeTimers.removeValue (this); + activeTimers.removeValue (this); #endif } void Timer::startTimer (const int interval) throw() { - const ScopedLock sl (InternalTimerThread::lock); + const ScopedLock sl (InternalTimerThread::lock); #ifdef JUCE_DEBUG - // this isn't a valid object! Your timer might be a dangling pointer or something.. - jassert (activeTimers.contains (this)); + // this isn't a valid object! Your timer might be a dangling pointer or something.. + jassert (activeTimers.contains (this)); #endif - if (periodMs == 0) - { - countdownMs = interval; - periodMs = jmax (1, interval); - InternalTimerThread::add (this); - } - else - { - InternalTimerThread::resetCounter (this, interval); - } + if (periodMs == 0) + { + countdownMs = interval; + periodMs = jmax (1, interval); + InternalTimerThread::add (this); + } + else + { + InternalTimerThread::resetCounter (this, interval); + } } void Timer::stopTimer() throw() { - const ScopedLock sl (InternalTimerThread::lock); + const ScopedLock sl (InternalTimerThread::lock); #ifdef JUCE_DEBUG - // this isn't a valid object! Your timer might be a dangling pointer or something.. - jassert (activeTimers.contains (this)); + // this isn't a valid object! Your timer might be a dangling pointer or something.. + jassert (activeTimers.contains (this)); #endif - if (periodMs > 0) - { - InternalTimerThread::remove (this); - periodMs = 0; - } + if (periodMs > 0) + { + InternalTimerThread::remove (this); + periodMs = 0; + } } END_JUCE_NAMESPACE @@ -38734,17 +38426,17 @@ BEGIN_JUCE_NAMESPACE Component* Component::componentUnderMouse = 0; Component* Component::currentlyFocusedComponent = 0; -static Array modalComponentStack (4), modalComponentReturnValueKeys (4); -static Array modalReturnValues (4); +static Array modalComponentStack, modalComponentReturnValueKeys; +static Array modalReturnValues; static const int customCommandMessage = 0x7fff0001; static const int exitModalStateMessage = 0x7fff0002; // these are also used by ComponentPeer -int64 juce_recentMouseDownTimes [4] = { 0, 0, 0, 0 }; -int juce_recentMouseDownX [4] = { 0, 0, 0, 0 }; -int juce_recentMouseDownY [4] = { 0, 0, 0, 0 }; -Component* juce_recentMouseDownComponent [4] = { 0, 0, 0, 0 }; +int64 juce_recentMouseDownTimes [4] = { 0, 0, 0, 0 }; +int juce_recentMouseDownX [4] = { 0, 0, 0, 0 }; +int juce_recentMouseDownY [4] = { 0, 0, 0, 0 }; +Component* juce_recentMouseDownComponent [4] = { 0, 0, 0, 0 }; int juce_LastMousePosX = 0; int juce_LastMousePosY = 0; int juce_MouseClickCounter = 0; @@ -38752,31 +38444,31 @@ bool juce_MouseHasMovedSignificantlySincePressed = false; static int countMouseClicks() throw() { - int numClicks = 0; + int numClicks = 0; - if (juce_recentMouseDownTimes[0] != 0) - { - if (! juce_MouseHasMovedSignificantlySincePressed) - ++numClicks; + if (juce_recentMouseDownTimes[0] != 0) + { + if (! juce_MouseHasMovedSignificantlySincePressed) + ++numClicks; - for (int i = 1; i < numElementsInArray (juce_recentMouseDownTimes); ++i) - { - if (juce_recentMouseDownTimes[0] - juce_recentMouseDownTimes [i] - < (int) (MouseEvent::getDoubleClickTimeout() * (1.0 + 0.25 * (i - 1))) - && abs (juce_recentMouseDownX[0] - juce_recentMouseDownX[i]) < 8 - && abs (juce_recentMouseDownY[0] - juce_recentMouseDownY[i]) < 8 - && juce_recentMouseDownComponent[0] == juce_recentMouseDownComponent [i]) - { - ++numClicks; - } - else - { - break; - } - } - } + for (int i = 1; i < numElementsInArray (juce_recentMouseDownTimes); ++i) + { + if (juce_recentMouseDownTimes[0] - juce_recentMouseDownTimes [i] + < (int) (MouseEvent::getDoubleClickTimeout() * (1.0 + 0.25 * (i - 1))) + && abs (juce_recentMouseDownX[0] - juce_recentMouseDownX[i]) < 8 + && abs (juce_recentMouseDownY[0] - juce_recentMouseDownY[i]) < 8 + && juce_recentMouseDownComponent[0] == juce_recentMouseDownComponent [i]) + { + ++numClicks; + } + else + { + break; + } + } + } - return numClicks; + return numClicks; } static int unboundedMouseOffsetX = 0; @@ -38784,153 +38476,151 @@ static int unboundedMouseOffsetY = 0; static bool isUnboundedMouseModeOn = false; static bool isCursorVisibleUntilOffscreen; -#define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); +#define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); static uint32 nextComponentUID = 0; Component::Component() throw() : parentComponent_ (0), - componentUID (++nextComponentUID), - numDeepMouseListeners (0), - childComponentList_ (16), - lookAndFeel_ (0), - effect_ (0), - bufferedImage_ (0), - mouseListeners_ (0), - keyListeners_ (0), - componentListeners_ (0), - propertySet_ (0), - componentFlags_ (0) + componentUID (++nextComponentUID), + numDeepMouseListeners (0), + lookAndFeel_ (0), + effect_ (0), + bufferedImage_ (0), + mouseListeners_ (0), + keyListeners_ (0), + componentListeners_ (0), + propertySet_ (0), + componentFlags_ (0) { } Component::Component (const String& name) throw() : componentName_ (name), - parentComponent_ (0), - componentUID (++nextComponentUID), - numDeepMouseListeners (0), - childComponentList_ (16), - lookAndFeel_ (0), - effect_ (0), - bufferedImage_ (0), - mouseListeners_ (0), - keyListeners_ (0), - componentListeners_ (0), - propertySet_ (0), - componentFlags_ (0) + parentComponent_ (0), + componentUID (++nextComponentUID), + numDeepMouseListeners (0), + lookAndFeel_ (0), + effect_ (0), + bufferedImage_ (0), + mouseListeners_ (0), + keyListeners_ (0), + componentListeners_ (0), + propertySet_ (0), + componentFlags_ (0) { } Component::~Component() { - if (parentComponent_ != 0) - { - parentComponent_->removeChildComponent (this); - } - else if ((currentlyFocusedComponent == this) - || isParentOf (currentlyFocusedComponent)) - { - giveAwayFocus(); - } + if (parentComponent_ != 0) + { + parentComponent_->removeChildComponent (this); + } + else if ((currentlyFocusedComponent == this) + || isParentOf (currentlyFocusedComponent)) + { + giveAwayFocus(); + } - if (componentUnderMouse == this) - componentUnderMouse = 0; + if (componentUnderMouse == this) + componentUnderMouse = 0; - if (flags.hasHeavyweightPeerFlag) - removeFromDesktop(); + if (flags.hasHeavyweightPeerFlag) + removeFromDesktop(); - modalComponentStack.removeValue (this); + modalComponentStack.removeValue (this); - for (int i = childComponentList_.size(); --i >= 0;) - childComponentList_.getUnchecked(i)->parentComponent_ = 0; + for (int i = childComponentList_.size(); --i >= 0;) + childComponentList_.getUnchecked(i)->parentComponent_ = 0; - delete bufferedImage_; - delete mouseListeners_; - delete keyListeners_; - delete componentListeners_; - delete propertySet_; + delete bufferedImage_; + delete mouseListeners_; + delete keyListeners_; + delete componentListeners_; + delete propertySet_; } void Component::setName (const String& name) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - if (componentName_ != name) - { - componentName_ = name; + if (componentName_ != name) + { + componentName_ = name; - if (flags.hasHeavyweightPeerFlag) - { - ComponentPeer* const peer = getPeer(); + if (flags.hasHeavyweightPeerFlag) + { + ComponentPeer* const peer = getPeer(); - jassert (peer != 0); - if (peer != 0) - peer->setTitle (name); - } + jassert (peer != 0); + if (peer != 0) + peer->setTitle (name); + } - if (componentListeners_ != 0) - { - const ComponentDeletionWatcher deletionChecker (this); + if (componentListeners_ != 0) + { + const ComponentDeletionWatcher deletionChecker (this); - for (int i = componentListeners_->size(); --i >= 0;) - { - ((ComponentListener*) componentListeners_->getUnchecked (i)) - ->componentNameChanged (*this); + for (int i = componentListeners_->size(); --i >= 0;) + { + ((ComponentListener*) componentListeners_->getUnchecked (i)) + ->componentNameChanged (*this); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, componentListeners_->size()); - } - } + i = jmin (i, componentListeners_->size()); + } + } - } + } } void Component::setVisible (bool shouldBeVisible) { - if (flags.visibleFlag != shouldBeVisible) - { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + if (flags.visibleFlag != shouldBeVisible) + { + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - flags.visibleFlag = shouldBeVisible; + flags.visibleFlag = shouldBeVisible; - internalRepaint (0, 0, getWidth(), getHeight()); + internalRepaint (0, 0, getWidth(), getHeight()); - sendFakeMouseMove(); + sendFakeMouseMove(); - if (! shouldBeVisible) - { - if (currentlyFocusedComponent == this - || isParentOf (currentlyFocusedComponent)) - { - if (parentComponent_ != 0) - parentComponent_->grabKeyboardFocus(); - else - giveAwayFocus(); - } - } + if (! shouldBeVisible) + { + if (currentlyFocusedComponent == this + || isParentOf (currentlyFocusedComponent)) + { + if (parentComponent_ != 0) + parentComponent_->grabKeyboardFocus(); + else + giveAwayFocus(); + } + } - sendVisibilityChangeMessage(); + sendVisibilityChangeMessage(); - if ((! deletionChecker.hasBeenDeleted()) && flags.hasHeavyweightPeerFlag) - { - ComponentPeer* const peer = getPeer(); + if ((! deletionChecker.hasBeenDeleted()) && flags.hasHeavyweightPeerFlag) + { + ComponentPeer* const peer = getPeer(); - jassert (peer != 0); - if (peer != 0) - { - peer->setVisible (shouldBeVisible); - internalHierarchyChanged(); - } - } - } + jassert (peer != 0); + if (peer != 0) + { + peer->setVisible (shouldBeVisible); + internalHierarchyChanged(); + } + } + } } void Component::visibilityChanged() @@ -38939,293 +38629,293 @@ void Component::visibilityChanged() void Component::sendVisibilityChangeMessage() { - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - visibilityChanged(); + visibilityChanged(); - if ((! deletionChecker.hasBeenDeleted()) && componentListeners_ != 0) - { - for (int i = componentListeners_->size(); --i >= 0;) - { - ((ComponentListener*) componentListeners_->getUnchecked (i)) - ->componentVisibilityChanged (*this); + if ((! deletionChecker.hasBeenDeleted()) && componentListeners_ != 0) + { + for (int i = componentListeners_->size(); --i >= 0;) + { + ((ComponentListener*) componentListeners_->getUnchecked (i)) + ->componentVisibilityChanged (*this); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, componentListeners_->size()); - } - } + i = jmin (i, componentListeners_->size()); + } + } } bool Component::isShowing() const throw() { - if (flags.visibleFlag) - { - if (parentComponent_ != 0) - { - return parentComponent_->isShowing(); - } - else - { - const ComponentPeer* const peer = getPeer(); + if (flags.visibleFlag) + { + if (parentComponent_ != 0) + { + return parentComponent_->isShowing(); + } + else + { + const ComponentPeer* const peer = getPeer(); - return peer != 0 && ! peer->isMinimised(); - } - } + return peer != 0 && ! peer->isMinimised(); + } + } - return false; + return false; } class FadeOutProxyComponent : public Component, - public Timer + public Timer { public: - FadeOutProxyComponent (Component* comp, - const int fadeLengthMs, - const int deltaXToMove, - const int deltaYToMove, - const float scaleFactorAtEnd) - : lastTime (0), - alpha (1.0f), - scale (1.0f) - { - image = comp->createComponentSnapshot (Rectangle (0, 0, comp->getWidth(), comp->getHeight())); - setBounds (comp->getBounds()); - comp->getParentComponent()->addAndMakeVisible (this); - toBehind (comp); + FadeOutProxyComponent (Component* comp, + const int fadeLengthMs, + const int deltaXToMove, + const int deltaYToMove, + const float scaleFactorAtEnd) + : lastTime (0), + alpha (1.0f), + scale (1.0f) + { + image = comp->createComponentSnapshot (Rectangle (0, 0, comp->getWidth(), comp->getHeight())); + setBounds (comp->getBounds()); + comp->getParentComponent()->addAndMakeVisible (this); + toBehind (comp); - alphaChangePerMs = -1.0f / (float)fadeLengthMs; + alphaChangePerMs = -1.0f / (float)fadeLengthMs; - centreX = comp->getX() + comp->getWidth() * 0.5f; - xChangePerMs = deltaXToMove / (float)fadeLengthMs; + centreX = comp->getX() + comp->getWidth() * 0.5f; + xChangePerMs = deltaXToMove / (float)fadeLengthMs; - centreY = comp->getY() + comp->getHeight() * 0.5f; - yChangePerMs = deltaYToMove / (float)fadeLengthMs; + centreY = comp->getY() + comp->getHeight() * 0.5f; + yChangePerMs = deltaYToMove / (float)fadeLengthMs; - scaleChangePerMs = (scaleFactorAtEnd - 1.0f) / (float)fadeLengthMs; + scaleChangePerMs = (scaleFactorAtEnd - 1.0f) / (float)fadeLengthMs; - setInterceptsMouseClicks (false, false); + setInterceptsMouseClicks (false, false); - // 30 fps is enough for a fade, but we need a higher rate if it's moving as well.. - startTimer (1000 / ((deltaXToMove == 0 && deltaYToMove == 0) ? 30 : 50)); - } + // 30 fps is enough for a fade, but we need a higher rate if it's moving as well.. + startTimer (1000 / ((deltaXToMove == 0 && deltaYToMove == 0) ? 30 : 50)); + } - ~FadeOutProxyComponent() - { - delete image; - } + ~FadeOutProxyComponent() + { + delete image; + } - void paint (Graphics& g) - { - g.setOpacity (alpha); + void paint (Graphics& g) + { + g.setOpacity (alpha); - g.drawImage (image, - 0, 0, getWidth(), getHeight(), - 0, 0, image->getWidth(), image->getHeight()); - } + g.drawImage (image, + 0, 0, getWidth(), getHeight(), + 0, 0, image->getWidth(), image->getHeight()); + } - void timerCallback() - { - const uint32 now = Time::getMillisecondCounter(); + void timerCallback() + { + const uint32 now = Time::getMillisecondCounter(); - if (lastTime == 0) - lastTime = now; + if (lastTime == 0) + lastTime = now; - const int msPassed = (now > lastTime) ? now - lastTime : 0; - lastTime = now; + const int msPassed = (now > lastTime) ? now - lastTime : 0; + lastTime = now; - alpha += alphaChangePerMs * msPassed; + alpha += alphaChangePerMs * msPassed; - if (alpha > 0) - { - if (xChangePerMs != 0.0f || yChangePerMs != 0.0f || scaleChangePerMs != 0.0f) - { - centreX += xChangePerMs * msPassed; - centreY += yChangePerMs * msPassed; - scale += scaleChangePerMs * msPassed; + if (alpha > 0) + { + if (xChangePerMs != 0.0f || yChangePerMs != 0.0f || scaleChangePerMs != 0.0f) + { + centreX += xChangePerMs * msPassed; + centreY += yChangePerMs * msPassed; + scale += scaleChangePerMs * msPassed; - const int w = roundFloatToInt (image->getWidth() * scale); - const int h = roundFloatToInt (image->getHeight() * scale); + const int w = roundToInt (image->getWidth() * scale); + const int h = roundToInt (image->getHeight() * scale); - setBounds (roundFloatToInt (centreX) - w / 2, - roundFloatToInt (centreY) - h / 2, - w, h); - } + setBounds (roundToInt (centreX) - w / 2, + roundToInt (centreY) - h / 2, + w, h); + } - repaint(); - } - else - { - delete this; - } - } + repaint(); + } + else + { + delete this; + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - Image* image; - uint32 lastTime; - float alpha, alphaChangePerMs; - float centreX, xChangePerMs; - float centreY, yChangePerMs; - float scale, scaleChangePerMs; + Image* image; + uint32 lastTime; + float alpha, alphaChangePerMs; + float centreX, xChangePerMs; + float centreY, yChangePerMs; + float scale, scaleChangePerMs; - FadeOutProxyComponent (const FadeOutProxyComponent&); - const FadeOutProxyComponent& operator= (const FadeOutProxyComponent&); + FadeOutProxyComponent (const FadeOutProxyComponent&); + const FadeOutProxyComponent& operator= (const FadeOutProxyComponent&); }; void Component::fadeOutComponent (const int millisecondsToFade, - const int deltaXToMove, - const int deltaYToMove, - const float scaleFactorAtEnd) + const int deltaXToMove, + const int deltaYToMove, + const float scaleFactorAtEnd) { - //xxx won't work for comps without parents - if (isShowing() && millisecondsToFade > 0) - new FadeOutProxyComponent (this, millisecondsToFade, - deltaXToMove, deltaYToMove, scaleFactorAtEnd); + //xxx won't work for comps without parents + if (isShowing() && millisecondsToFade > 0) + new FadeOutProxyComponent (this, millisecondsToFade, + deltaXToMove, deltaYToMove, scaleFactorAtEnd); - setVisible (false); + setVisible (false); } bool Component::isValidComponent() const throw() { - return (this != 0) && isValidMessageListener(); + return (this != 0) && isValidMessageListener(); } void* Component::getWindowHandle() const throw() { - const ComponentPeer* const peer = getPeer(); + const ComponentPeer* const peer = getPeer(); - if (peer != 0) - return peer->getNativeHandle(); + if (peer != 0) + return peer->getNativeHandle(); - return 0; + return 0; } void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - if (isOpaque()) - styleWanted &= ~ComponentPeer::windowIsSemiTransparent; - else - styleWanted |= ComponentPeer::windowIsSemiTransparent; + if (isOpaque()) + styleWanted &= ~ComponentPeer::windowIsSemiTransparent; + else + styleWanted |= ComponentPeer::windowIsSemiTransparent; - int currentStyleFlags = 0; + int currentStyleFlags = 0; - // don't use getPeer(), so that we only get the peer that's specifically - // for this comp, and not for one of its parents. - ComponentPeer* peer = ComponentPeer::getPeerFor (this); + // don't use getPeer(), so that we only get the peer that's specifically + // for this comp, and not for one of its parents. + ComponentPeer* peer = ComponentPeer::getPeerFor (this); - if (peer != 0) - currentStyleFlags = peer->getStyleFlags(); + if (peer != 0) + currentStyleFlags = peer->getStyleFlags(); - if (styleWanted != currentStyleFlags || ! flags.hasHeavyweightPeerFlag) - { - const ComponentDeletionWatcher deletionChecker (this); + if (styleWanted != currentStyleFlags || ! flags.hasHeavyweightPeerFlag) + { + const ComponentDeletionWatcher deletionChecker (this); #if JUCE_LINUX - // it's wise to give the component a non-zero size before - // putting it on the desktop, as X windows get confused by this, and - // a (1, 1) minimum size is enforced here. - setSize (jmax (1, getWidth()), - jmax (1, getHeight())); + // it's wise to give the component a non-zero size before + // putting it on the desktop, as X windows get confused by this, and + // a (1, 1) minimum size is enforced here. + setSize (jmax (1, getWidth()), + jmax (1, getHeight())); #endif - int x = 0, y = 0; - relativePositionToGlobal (x, y); + int x = 0, y = 0; + relativePositionToGlobal (x, y); - bool wasFullscreen = false; - bool wasMinimised = false; - ComponentBoundsConstrainer* currentConstainer = 0; - Rectangle oldNonFullScreenBounds; + bool wasFullscreen = false; + bool wasMinimised = false; + ComponentBoundsConstrainer* currentConstainer = 0; + Rectangle oldNonFullScreenBounds; - if (peer != 0) - { - wasFullscreen = peer->isFullScreen(); - wasMinimised = peer->isMinimised(); - currentConstainer = peer->getConstrainer(); - oldNonFullScreenBounds = peer->getNonFullScreenBounds(); + if (peer != 0) + { + wasFullscreen = peer->isFullScreen(); + wasMinimised = peer->isMinimised(); + currentConstainer = peer->getConstrainer(); + oldNonFullScreenBounds = peer->getNonFullScreenBounds(); - removeFromDesktop(); + removeFromDesktop(); - setTopLeftPosition (x, y); - } + setTopLeftPosition (x, y); + } - if (parentComponent_ != 0) - parentComponent_->removeChildComponent (this); + if (parentComponent_ != 0) + parentComponent_->removeChildComponent (this); - if (! deletionChecker.hasBeenDeleted()) - { - flags.hasHeavyweightPeerFlag = true; + if (! deletionChecker.hasBeenDeleted()) + { + flags.hasHeavyweightPeerFlag = true; - peer = createNewPeer (styleWanted, nativeWindowToAttachTo); + peer = createNewPeer (styleWanted, nativeWindowToAttachTo); - Desktop::getInstance().addDesktopComponent (this); + Desktop::getInstance().addDesktopComponent (this); - bounds_.setPosition (x, y); - peer->setBounds (x, y, getWidth(), getHeight(), false); + bounds_.setPosition (x, y); + peer->setBounds (x, y, getWidth(), getHeight(), false); - peer->setVisible (isVisible()); + peer->setVisible (isVisible()); - if (wasFullscreen) - { - peer->setFullScreen (true); - peer->setNonFullScreenBounds (oldNonFullScreenBounds); - } + if (wasFullscreen) + { + peer->setFullScreen (true); + peer->setNonFullScreenBounds (oldNonFullScreenBounds); + } - if (wasMinimised) - peer->setMinimised (true); + if (wasMinimised) + peer->setMinimised (true); - if (isAlwaysOnTop()) - peer->setAlwaysOnTop (true); + if (isAlwaysOnTop()) + peer->setAlwaysOnTop (true); - peer->setConstrainer (currentConstainer); + peer->setConstrainer (currentConstainer); - repaint(); - } + repaint(); + } - internalHierarchyChanged(); - } + internalHierarchyChanged(); + } } void Component::removeFromDesktop() { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - if (flags.hasHeavyweightPeerFlag) - { - ComponentPeer* const peer = ComponentPeer::getPeerFor (this); + if (flags.hasHeavyweightPeerFlag) + { + ComponentPeer* const peer = ComponentPeer::getPeerFor (this); - flags.hasHeavyweightPeerFlag = false; + flags.hasHeavyweightPeerFlag = false; - jassert (peer != 0); - delete peer; + jassert (peer != 0); + delete peer; - Desktop::getInstance().removeDesktopComponent (this); - } + Desktop::getInstance().removeDesktopComponent (this); + } } bool Component::isOnDesktop() const throw() { - return flags.hasHeavyweightPeerFlag; + return flags.hasHeavyweightPeerFlag; } void Component::userTriedToCloseWindow() { - /* This means that the user's trying to get rid of your window with the 'close window' system - menu option (on windows) or possibly the task manager - you should really handle this - and delete or hide your component in an appropriate way. + /* This means that the user's trying to get rid of your window with the 'close window' system + menu option (on windows) or possibly the task manager - you should really handle this + and delete or hide your component in an appropriate way. - If you want to ignore the event and don't want to trigger this assertion, just override - this method and do nothing. - */ - jassertfalse + If you want to ignore the event and don't want to trigger this assertion, just override + this method and do nothing. + */ + jassertfalse } void Component::minimisationStateChanged (bool) @@ -39234,766 +38924,766 @@ void Component::minimisationStateChanged (bool) void Component::setOpaque (const bool shouldBeOpaque) throw() { - if (shouldBeOpaque != flags.opaqueFlag) - { - flags.opaqueFlag = shouldBeOpaque; + if (shouldBeOpaque != flags.opaqueFlag) + { + flags.opaqueFlag = shouldBeOpaque; - if (flags.hasHeavyweightPeerFlag) - { - const ComponentPeer* const peer = ComponentPeer::getPeerFor (this); + if (flags.hasHeavyweightPeerFlag) + { + const ComponentPeer* const peer = ComponentPeer::getPeerFor (this); - if (peer != 0) - { - // to make it recreate the heavyweight window - addToDesktop (peer->getStyleFlags()); - } - } + if (peer != 0) + { + // to make it recreate the heavyweight window + addToDesktop (peer->getStyleFlags()); + } + } - repaint(); - } + repaint(); + } } bool Component::isOpaque() const throw() { - return flags.opaqueFlag; + return flags.opaqueFlag; } void Component::setBufferedToImage (const bool shouldBeBuffered) throw() { - if (shouldBeBuffered != flags.bufferToImageFlag) - { - deleteAndZero (bufferedImage_); - flags.bufferToImageFlag = shouldBeBuffered; - } + if (shouldBeBuffered != flags.bufferToImageFlag) + { + deleteAndZero (bufferedImage_); + flags.bufferToImageFlag = shouldBeBuffered; + } } void Component::toFront (const bool setAsForeground) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - if (flags.hasHeavyweightPeerFlag) - { - ComponentPeer* const peer = getPeer(); + if (flags.hasHeavyweightPeerFlag) + { + ComponentPeer* const peer = getPeer(); - if (peer != 0) - { - peer->toFront (setAsForeground); + if (peer != 0) + { + peer->toFront (setAsForeground); - if (setAsForeground && ! hasKeyboardFocus (true)) - grabKeyboardFocus(); - } - } - else if (parentComponent_ != 0) - { - if (parentComponent_->childComponentList_.getLast() != this) - { - const int index = parentComponent_->childComponentList_.indexOf (this); + if (setAsForeground && ! hasKeyboardFocus (true)) + grabKeyboardFocus(); + } + } + else if (parentComponent_ != 0) + { + if (parentComponent_->childComponentList_.getLast() != this) + { + const int index = parentComponent_->childComponentList_.indexOf (this); - if (index >= 0) - { - int insertIndex = -1; + if (index >= 0) + { + int insertIndex = -1; - if (! flags.alwaysOnTopFlag) - { - insertIndex = parentComponent_->childComponentList_.size() - 1; + if (! flags.alwaysOnTopFlag) + { + insertIndex = parentComponent_->childComponentList_.size() - 1; - while (insertIndex > 0 - && parentComponent_->childComponentList_.getUnchecked (insertIndex)->isAlwaysOnTop()) - { - --insertIndex; - } - } + while (insertIndex > 0 + && parentComponent_->childComponentList_.getUnchecked (insertIndex)->isAlwaysOnTop()) + { + --insertIndex; + } + } - if (index != insertIndex) - { - parentComponent_->childComponentList_.move (index, insertIndex); - sendFakeMouseMove(); + if (index != insertIndex) + { + parentComponent_->childComponentList_.move (index, insertIndex); + sendFakeMouseMove(); - repaintParent(); - } - } - } + repaintParent(); + } + } + } - if (setAsForeground) - { - internalBroughtToFront(); - grabKeyboardFocus(); - } - } + if (setAsForeground) + { + internalBroughtToFront(); + grabKeyboardFocus(); + } + } } void Component::toBehind (Component* const other) { - if (other != 0) - { - // the two components must belong to the same parent.. - jassert (parentComponent_ == other->parentComponent_); + if (other != 0) + { + // the two components must belong to the same parent.. + jassert (parentComponent_ == other->parentComponent_); - if (parentComponent_ != 0) - { - const int index = parentComponent_->childComponentList_.indexOf (this); - int otherIndex = parentComponent_->childComponentList_.indexOf (other); + if (parentComponent_ != 0) + { + const int index = parentComponent_->childComponentList_.indexOf (this); + int otherIndex = parentComponent_->childComponentList_.indexOf (other); - if (index >= 0 - && otherIndex >= 0 - && index != otherIndex - 1 - && other != this) - { - if (index < otherIndex) - --otherIndex; + if (index >= 0 + && otherIndex >= 0 + && index != otherIndex - 1 + && other != this) + { + if (index < otherIndex) + --otherIndex; - parentComponent_->childComponentList_.move (index, otherIndex); + parentComponent_->childComponentList_.move (index, otherIndex); - sendFakeMouseMove(); - repaintParent(); - } - } - else if (isOnDesktop()) - { - jassert (other->isOnDesktop()); + sendFakeMouseMove(); + repaintParent(); + } + } + else if (isOnDesktop()) + { + jassert (other->isOnDesktop()); - if (other->isOnDesktop()) - { - ComponentPeer* const us = getPeer(); - ComponentPeer* const them = other->getPeer(); + if (other->isOnDesktop()) + { + ComponentPeer* const us = getPeer(); + ComponentPeer* const them = other->getPeer(); - jassert (us != 0 && them != 0); - if (us != 0 && them != 0) - us->toBehind (them); - } - } - } + jassert (us != 0 && them != 0); + if (us != 0 && them != 0) + us->toBehind (them); + } + } + } } void Component::toBack() { - if (isOnDesktop()) - { - jassertfalse //xxx need to add this to native window - } - else if (parentComponent_ != 0 - && parentComponent_->childComponentList_.getFirst() != this) - { - const int index = parentComponent_->childComponentList_.indexOf (this); + if (isOnDesktop()) + { + jassertfalse //xxx need to add this to native window + } + else if (parentComponent_ != 0 + && parentComponent_->childComponentList_.getFirst() != this) + { + const int index = parentComponent_->childComponentList_.indexOf (this); - if (index > 0) - { - int insertIndex = 0; + if (index > 0) + { + int insertIndex = 0; - if (flags.alwaysOnTopFlag) - { - while (insertIndex < parentComponent_->childComponentList_.size() - && ! parentComponent_->childComponentList_.getUnchecked (insertIndex)->isAlwaysOnTop()) - { - ++insertIndex; - } - } + if (flags.alwaysOnTopFlag) + { + while (insertIndex < parentComponent_->childComponentList_.size() + && ! parentComponent_->childComponentList_.getUnchecked (insertIndex)->isAlwaysOnTop()) + { + ++insertIndex; + } + } - if (index != insertIndex) - { - parentComponent_->childComponentList_.move (index, insertIndex); + if (index != insertIndex) + { + parentComponent_->childComponentList_.move (index, insertIndex); - sendFakeMouseMove(); - repaintParent(); - } - } - } + sendFakeMouseMove(); + repaintParent(); + } + } + } } void Component::setAlwaysOnTop (const bool shouldStayOnTop) { - if (shouldStayOnTop != flags.alwaysOnTopFlag) - { - flags.alwaysOnTopFlag = shouldStayOnTop; + if (shouldStayOnTop != flags.alwaysOnTopFlag) + { + flags.alwaysOnTopFlag = shouldStayOnTop; - if (isOnDesktop()) - { - ComponentPeer* const peer = getPeer(); + if (isOnDesktop()) + { + ComponentPeer* const peer = getPeer(); - jassert (peer != 0); - if (peer != 0) - { - if (! peer->setAlwaysOnTop (shouldStayOnTop)) - { - // some kinds of peer can't change their always-on-top status, so - // for these, we'll need to create a new window - const int oldFlags = peer->getStyleFlags(); - removeFromDesktop(); - addToDesktop (oldFlags); - } - } - } + jassert (peer != 0); + if (peer != 0) + { + if (! peer->setAlwaysOnTop (shouldStayOnTop)) + { + // some kinds of peer can't change their always-on-top status, so + // for these, we'll need to create a new window + const int oldFlags = peer->getStyleFlags(); + removeFromDesktop(); + addToDesktop (oldFlags); + } + } + } - if (shouldStayOnTop) - toFront (false); + if (shouldStayOnTop) + toFront (false); - internalHierarchyChanged(); - } + internalHierarchyChanged(); + } } bool Component::isAlwaysOnTop() const throw() { - return flags.alwaysOnTopFlag; + return flags.alwaysOnTopFlag; } int Component::proportionOfWidth (const float proportion) const throw() { - return roundDoubleToInt (proportion * bounds_.getWidth()); + return roundToInt (proportion * bounds_.getWidth()); } int Component::proportionOfHeight (const float proportion) const throw() { - return roundDoubleToInt (proportion * bounds_.getHeight()); + return roundToInt (proportion * bounds_.getHeight()); } int Component::getParentWidth() const throw() { - return (parentComponent_ != 0) ? parentComponent_->getWidth() - : getParentMonitorArea().getWidth(); + return (parentComponent_ != 0) ? parentComponent_->getWidth() + : getParentMonitorArea().getWidth(); } int Component::getParentHeight() const throw() { - return (parentComponent_ != 0) ? parentComponent_->getHeight() - : getParentMonitorArea().getHeight(); + return (parentComponent_ != 0) ? parentComponent_->getHeight() + : getParentMonitorArea().getHeight(); } int Component::getScreenX() const throw() { - return (parentComponent_ != 0) ? parentComponent_->getScreenX() + getX() - : (flags.hasHeavyweightPeerFlag ? getPeer()->getScreenX() - : getX()); + return (parentComponent_ != 0) ? parentComponent_->getScreenX() + getX() + : (flags.hasHeavyweightPeerFlag ? getPeer()->getScreenX() + : getX()); } int Component::getScreenY() const throw() { - return (parentComponent_ != 0) ? parentComponent_->getScreenY() + getY() - : (flags.hasHeavyweightPeerFlag ? getPeer()->getScreenY() - : getY()); + return (parentComponent_ != 0) ? parentComponent_->getScreenY() + getY() + : (flags.hasHeavyweightPeerFlag ? getPeer()->getScreenY() + : getY()); } void Component::relativePositionToGlobal (int& x, int& y) const throw() { - const Component* c = this; + const Component* c = this; - do - { - if (c->flags.hasHeavyweightPeerFlag) - { - c->getPeer()->relativePositionToGlobal (x, y); - break; - } + do + { + if (c->flags.hasHeavyweightPeerFlag) + { + c->getPeer()->relativePositionToGlobal (x, y); + break; + } - x += c->getX(); - y += c->getY(); - c = c->parentComponent_; - } - while (c != 0); + x += c->getX(); + y += c->getY(); + c = c->parentComponent_; + } + while (c != 0); } void Component::globalPositionToRelative (int& x, int& y) const throw() { - if (flags.hasHeavyweightPeerFlag) - { - getPeer()->globalPositionToRelative (x, y); - } - else - { - if (parentComponent_ != 0) - parentComponent_->globalPositionToRelative (x, y); + if (flags.hasHeavyweightPeerFlag) + { + getPeer()->globalPositionToRelative (x, y); + } + else + { + if (parentComponent_ != 0) + parentComponent_->globalPositionToRelative (x, y); - x -= getX(); - y -= getY(); - } + x -= getX(); + y -= getY(); + } } void Component::relativePositionToOtherComponent (const Component* const targetComponent, int& x, int& y) const throw() { - if (targetComponent != 0) - { - const Component* c = this; + if (targetComponent != 0) + { + const Component* c = this; - do - { - if (c == targetComponent) - return; + do + { + if (c == targetComponent) + return; - if (c->flags.hasHeavyweightPeerFlag) - { - c->getPeer()->relativePositionToGlobal (x, y); - break; - } + if (c->flags.hasHeavyweightPeerFlag) + { + c->getPeer()->relativePositionToGlobal (x, y); + break; + } - x += c->getX(); - y += c->getY(); - c = c->parentComponent_; - } - while (c != 0); + x += c->getX(); + y += c->getY(); + c = c->parentComponent_; + } + while (c != 0); - targetComponent->globalPositionToRelative (x, y); - } + targetComponent->globalPositionToRelative (x, y); + } } void Component::setBounds (int x, int y, int w, int h) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - if (w < 0) w = 0; - if (h < 0) h = 0; + if (w < 0) w = 0; + if (h < 0) h = 0; - const bool wasResized = (getWidth() != w || getHeight() != h); - const bool wasMoved = (getX() != x || getY() != y); + const bool wasResized = (getWidth() != w || getHeight() != h); + const bool wasMoved = (getX() != x || getY() != y); #ifdef JUCE_DEBUG - // It's a very bad idea to try to resize a window during its paint() method! - jassert (! (flags.isInsidePaintCall && wasResized && isOnDesktop())); + // It's a very bad idea to try to resize a window during its paint() method! + jassert (! (flags.isInsidePaintCall && wasResized && isOnDesktop())); #endif - if (wasMoved || wasResized) - { - if (flags.visibleFlag) - { - // send a fake mouse move to trigger enter/exit messages if needed.. - sendFakeMouseMove(); + if (wasMoved || wasResized) + { + if (flags.visibleFlag) + { + // send a fake mouse move to trigger enter/exit messages if needed.. + sendFakeMouseMove(); - if (! flags.hasHeavyweightPeerFlag) - repaintParent(); - } + if (! flags.hasHeavyweightPeerFlag) + repaintParent(); + } - bounds_.setBounds (x, y, w, h); + bounds_.setBounds (x, y, w, h); - if (wasResized) - repaint(); - else if (! flags.hasHeavyweightPeerFlag) - repaintParent(); + if (wasResized) + repaint(); + else if (! flags.hasHeavyweightPeerFlag) + repaintParent(); - if (flags.hasHeavyweightPeerFlag) - { - ComponentPeer* const peer = getPeer(); + if (flags.hasHeavyweightPeerFlag) + { + ComponentPeer* const peer = getPeer(); - if (peer != 0) - { - if (wasMoved && wasResized) - peer->setBounds (getX(), getY(), getWidth(), getHeight(), false); - else if (wasMoved) - peer->setPosition (getX(), getY()); - else if (wasResized) - peer->setSize (getWidth(), getHeight()); - } - } + if (peer != 0) + { + if (wasMoved && wasResized) + peer->setBounds (getX(), getY(), getWidth(), getHeight(), false); + else if (wasMoved) + peer->setPosition (getX(), getY()); + else if (wasResized) + peer->setSize (getWidth(), getHeight()); + } + } - sendMovedResizedMessages (wasMoved, wasResized); - } + sendMovedResizedMessages (wasMoved, wasResized); + } } void Component::sendMovedResizedMessages (const bool wasMoved, const bool wasResized) { - JUCE_TRY - { - if (wasMoved) - moved(); + JUCE_TRY + { + if (wasMoved) + moved(); - if (wasResized) - { - resized(); + if (wasResized) + { + resized(); - for (int i = childComponentList_.size(); --i >= 0;) - { - childComponentList_.getUnchecked(i)->parentSizeChanged(); + for (int i = childComponentList_.size(); --i >= 0;) + { + childComponentList_.getUnchecked(i)->parentSizeChanged(); - i = jmin (i, childComponentList_.size()); - } - } + i = jmin (i, childComponentList_.size()); + } + } - if (parentComponent_ != 0) - parentComponent_->childBoundsChanged (this); + if (parentComponent_ != 0) + parentComponent_->childBoundsChanged (this); - if (componentListeners_ != 0) - { - const ComponentDeletionWatcher deletionChecker (this); + if (componentListeners_ != 0) + { + const ComponentDeletionWatcher deletionChecker (this); - for (int i = componentListeners_->size(); --i >= 0;) - { - ((ComponentListener*) componentListeners_->getUnchecked (i)) - ->componentMovedOrResized (*this, wasMoved, wasResized); + for (int i = componentListeners_->size(); --i >= 0;) + { + ((ComponentListener*) componentListeners_->getUnchecked (i)) + ->componentMovedOrResized (*this, wasMoved, wasResized); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, componentListeners_->size()); - } - } - } - JUCE_CATCH_EXCEPTION + i = jmin (i, componentListeners_->size()); + } + } + } + JUCE_CATCH_EXCEPTION } void Component::setSize (const int w, const int h) { - setBounds (getX(), getY(), w, h); + setBounds (getX(), getY(), w, h); } void Component::setTopLeftPosition (const int x, const int y) { - setBounds (x, y, getWidth(), getHeight()); + setBounds (x, y, getWidth(), getHeight()); } void Component::setTopRightPosition (const int x, const int y) { - setTopLeftPosition (x - getWidth(), y); + setTopLeftPosition (x - getWidth(), y); } void Component::setBounds (const Rectangle& r) { - setBounds (r.getX(), - r.getY(), - r.getWidth(), - r.getHeight()); + setBounds (r.getX(), + r.getY(), + r.getWidth(), + r.getHeight()); } void Component::setBoundsRelative (const float x, const float y, - const float w, const float h) + const float w, const float h) { - const int pw = getParentWidth(); - const int ph = getParentHeight(); + const int pw = getParentWidth(); + const int ph = getParentHeight(); - setBounds (roundFloatToInt (x * pw), - roundFloatToInt (y * ph), - roundFloatToInt (w * pw), - roundFloatToInt (h * ph)); + setBounds (roundToInt (x * pw), + roundToInt (y * ph), + roundToInt (w * pw), + roundToInt (h * ph)); } void Component::setCentrePosition (const int x, const int y) { - setTopLeftPosition (x - getWidth() / 2, - y - getHeight() / 2); + setTopLeftPosition (x - getWidth() / 2, + y - getHeight() / 2); } void Component::setCentreRelative (const float x, const float y) { - setCentrePosition (roundFloatToInt (getParentWidth() * x), - roundFloatToInt (getParentHeight() * y)); + setCentrePosition (roundToInt (getParentWidth() * x), + roundToInt (getParentHeight() * y)); } void Component::centreWithSize (const int width, const int height) { - setBounds ((getParentWidth() - width) / 2, - (getParentHeight() - height) / 2, - width, - height); + setBounds ((getParentWidth() - width) / 2, + (getParentHeight() - height) / 2, + width, + height); } void Component::setBoundsInset (const BorderSize& borders) { - setBounds (borders.getLeft(), - borders.getTop(), - getParentWidth() - (borders.getLeftAndRight()), - getParentHeight() - (borders.getTopAndBottom())); + setBounds (borders.getLeft(), + borders.getTop(), + getParentWidth() - (borders.getLeftAndRight()), + getParentHeight() - (borders.getTopAndBottom())); } void Component::setBoundsToFit (int x, int y, int width, int height, - const Justification& justification, - const bool onlyReduceInSize) + const Justification& justification, + const bool onlyReduceInSize) { - // it's no good calling this method unless both the component and - // target rectangle have a finite size. - jassert (getWidth() > 0 && getHeight() > 0 && width > 0 && height > 0); + // it's no good calling this method unless both the component and + // target rectangle have a finite size. + jassert (getWidth() > 0 && getHeight() > 0 && width > 0 && height > 0); - if (getWidth() > 0 && getHeight() > 0 - && width > 0 && height > 0) - { - int newW, newH; + if (getWidth() > 0 && getHeight() > 0 + && width > 0 && height > 0) + { + int newW, newH; - if (onlyReduceInSize && getWidth() <= width && getHeight() <= height) - { - newW = getWidth(); - newH = getHeight(); - } - else - { - const double imageRatio = getHeight() / (double) getWidth(); - const double targetRatio = height / (double) width; + if (onlyReduceInSize && getWidth() <= width && getHeight() <= height) + { + newW = getWidth(); + newH = getHeight(); + } + else + { + const double imageRatio = getHeight() / (double) getWidth(); + const double targetRatio = height / (double) width; - if (imageRatio <= targetRatio) - { - newW = width; - newH = jmin (height, roundDoubleToInt (newW * imageRatio)); - } - else - { - newH = height; - newW = jmin (width, roundDoubleToInt (newH / imageRatio)); - } - } + if (imageRatio <= targetRatio) + { + newW = width; + newH = jmin (height, roundToInt (newW * imageRatio)); + } + else + { + newH = height; + newW = jmin (width, roundToInt (newH / imageRatio)); + } + } - if (newW > 0 && newH > 0) - { - int newX, newY; - justification.applyToRectangle (newX, newY, newW, newH, - x, y, width, height); + if (newW > 0 && newH > 0) + { + int newX, newY; + justification.applyToRectangle (newX, newY, newW, newH, + x, y, width, height); - setBounds (newX, newY, newW, newH); - } - } + setBounds (newX, newY, newW, newH); + } + } } bool Component::hitTest (int x, int y) { - if (! flags.ignoresMouseClicksFlag) - return true; + if (! flags.ignoresMouseClicksFlag) + return true; - if (flags.allowChildMouseClicksFlag) - { - for (int i = getNumChildComponents(); --i >= 0;) - { - Component* const c = getChildComponent (i); + if (flags.allowChildMouseClicksFlag) + { + for (int i = getNumChildComponents(); --i >= 0;) + { + Component* const c = getChildComponent (i); - if (c->isVisible() - && c->bounds_.contains (x, y) - && c->hitTest (x - c->getX(), - y - c->getY())) - { - return true; - } - } - } + if (c->isVisible() + && c->bounds_.contains (x, y) + && c->hitTest (x - c->getX(), + y - c->getY())) + { + return true; + } + } + } - return false; + return false; } void Component::setInterceptsMouseClicks (const bool allowClicks, - const bool allowClicksOnChildComponents) throw() + const bool allowClicksOnChildComponents) throw() { - flags.ignoresMouseClicksFlag = ! allowClicks; - flags.allowChildMouseClicksFlag = allowClicksOnChildComponents; + flags.ignoresMouseClicksFlag = ! allowClicks; + flags.allowChildMouseClicksFlag = allowClicksOnChildComponents; } void Component::getInterceptsMouseClicks (bool& allowsClicksOnThisComponent, - bool& allowsClicksOnChildComponents) const throw() + bool& allowsClicksOnChildComponents) const throw() { - allowsClicksOnThisComponent = ! flags.ignoresMouseClicksFlag; - allowsClicksOnChildComponents = flags.allowChildMouseClicksFlag; + allowsClicksOnThisComponent = ! flags.ignoresMouseClicksFlag; + allowsClicksOnChildComponents = flags.allowChildMouseClicksFlag; } bool Component::contains (const int x, const int y) { - if (((unsigned int) x) < (unsigned int) getWidth() - && ((unsigned int) y) < (unsigned int) getHeight() - && hitTest (x, y)) - { - if (parentComponent_ != 0) - { - return parentComponent_->contains (x + getX(), - y + getY()); - } - else if (flags.hasHeavyweightPeerFlag) - { - const ComponentPeer* const peer = getPeer(); + if (((unsigned int) x) < (unsigned int) getWidth() + && ((unsigned int) y) < (unsigned int) getHeight() + && hitTest (x, y)) + { + if (parentComponent_ != 0) + { + return parentComponent_->contains (x + getX(), + y + getY()); + } + else if (flags.hasHeavyweightPeerFlag) + { + const ComponentPeer* const peer = getPeer(); - if (peer != 0) - return peer->contains (x, y, true); - } - } + if (peer != 0) + return peer->contains (x, y, true); + } + } - return false; + return false; } bool Component::reallyContains (int x, int y, const bool returnTrueIfWithinAChild) { - if (! contains (x, y)) - return false; + if (! contains (x, y)) + return false; - Component* p = this; + Component* p = this; - while (p->parentComponent_ != 0) - { - x += p->getX(); - y += p->getY(); + while (p->parentComponent_ != 0) + { + x += p->getX(); + y += p->getY(); - p = p->parentComponent_; - } + p = p->parentComponent_; + } - const Component* const c = p->getComponentAt (x, y); + const Component* const c = p->getComponentAt (x, y); - return (c == this) || (returnTrueIfWithinAChild && isParentOf (c)); + return (c == this) || (returnTrueIfWithinAChild && isParentOf (c)); } Component* Component::getComponentAt (const int x, const int y) { - if (flags.visibleFlag - && ((unsigned int) x) < (unsigned int) getWidth() - && ((unsigned int) y) < (unsigned int) getHeight() - && hitTest (x, y)) - { - for (int i = childComponentList_.size(); --i >= 0;) - { - Component* const child = childComponentList_.getUnchecked(i); + if (flags.visibleFlag + && ((unsigned int) x) < (unsigned int) getWidth() + && ((unsigned int) y) < (unsigned int) getHeight() + && hitTest (x, y)) + { + for (int i = childComponentList_.size(); --i >= 0;) + { + Component* const child = childComponentList_.getUnchecked(i); - Component* const c = child->getComponentAt (x - child->getX(), - y - child->getY()); + Component* const c = child->getComponentAt (x - child->getX(), + y - child->getY()); - if (c != 0) - return c; - } + if (c != 0) + return c; + } - return this; - } + return this; + } - return 0; + return 0; } void Component::addChildComponent (Component* const child, int zOrder) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - if (child != 0 && child->parentComponent_ != this) - { - if (child->parentComponent_ != 0) - child->parentComponent_->removeChildComponent (child); - else - child->removeFromDesktop(); + if (child != 0 && child->parentComponent_ != this) + { + if (child->parentComponent_ != 0) + child->parentComponent_->removeChildComponent (child); + else + child->removeFromDesktop(); - child->parentComponent_ = this; + child->parentComponent_ = this; - if (child->isVisible()) - child->repaintParent(); + if (child->isVisible()) + child->repaintParent(); - if (! child->isAlwaysOnTop()) - { - if (zOrder < 0 || zOrder > childComponentList_.size()) - zOrder = childComponentList_.size(); + if (! child->isAlwaysOnTop()) + { + if (zOrder < 0 || zOrder > childComponentList_.size()) + zOrder = childComponentList_.size(); - while (zOrder > 0) - { - if (! childComponentList_.getUnchecked (zOrder - 1)->isAlwaysOnTop()) - break; + while (zOrder > 0) + { + if (! childComponentList_.getUnchecked (zOrder - 1)->isAlwaysOnTop()) + break; - --zOrder; - } - } + --zOrder; + } + } - childComponentList_.insert (zOrder, child); + childComponentList_.insert (zOrder, child); - child->internalHierarchyChanged(); - internalChildrenChanged(); - } + child->internalHierarchyChanged(); + internalChildrenChanged(); + } } void Component::addAndMakeVisible (Component* const child, int zOrder) { - if (child != 0) - { - child->setVisible (true); - addChildComponent (child, zOrder); - } + if (child != 0) + { + child->setVisible (true); + addChildComponent (child, zOrder); + } } void Component::removeChildComponent (Component* const child) { - removeChildComponent (childComponentList_.indexOf (child)); + removeChildComponent (childComponentList_.indexOf (child)); } Component* Component::removeChildComponent (const int index) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - Component* const child = childComponentList_ [index]; + Component* const child = childComponentList_ [index]; - if (child != 0) - { - sendFakeMouseMove(); - child->repaintParent(); + if (child != 0) + { + sendFakeMouseMove(); + child->repaintParent(); - childComponentList_.remove (index); - child->parentComponent_ = 0; + childComponentList_.remove (index); + child->parentComponent_ = 0; - JUCE_TRY - { - if ((currentlyFocusedComponent == child) - || child->isParentOf (currentlyFocusedComponent)) - { - // get rid first to force the grabKeyboardFocus to change to us. - giveAwayFocus(); - grabKeyboardFocus(); - } - } + JUCE_TRY + { + if ((currentlyFocusedComponent == child) + || child->isParentOf (currentlyFocusedComponent)) + { + // get rid first to force the grabKeyboardFocus to change to us. + giveAwayFocus(); + grabKeyboardFocus(); + } + } #if JUCE_CATCH_UNHANDLED_EXCEPTIONS - catch (const std::exception& e) - { - currentlyFocusedComponent = 0; - Desktop::getInstance().triggerFocusCallback(); - JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); - } - catch (...) - { - currentlyFocusedComponent = 0; - Desktop::getInstance().triggerFocusCallback(); - JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); - } + catch (const std::exception& e) + { + currentlyFocusedComponent = 0; + Desktop::getInstance().triggerFocusCallback(); + JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); + } + catch (...) + { + currentlyFocusedComponent = 0; + Desktop::getInstance().triggerFocusCallback(); + JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); + } #endif - child->internalHierarchyChanged(); - internalChildrenChanged(); - } + child->internalHierarchyChanged(); + internalChildrenChanged(); + } - return child; + return child; } void Component::removeAllChildren() { - for (int i = childComponentList_.size(); --i >= 0;) - removeChildComponent (i); + for (int i = childComponentList_.size(); --i >= 0;) + removeChildComponent (i); } void Component::deleteAllChildren() { - for (int i = childComponentList_.size(); --i >= 0;) - delete (removeChildComponent (i)); + for (int i = childComponentList_.size(); --i >= 0;) + delete (removeChildComponent (i)); } int Component::getNumChildComponents() const throw() { - return childComponentList_.size(); + return childComponentList_.size(); } Component* Component::getChildComponent (const int index) const throw() { - return childComponentList_ [index]; + return childComponentList_ [index]; } int Component::getIndexOfChildComponent (const Component* const child) const throw() { - return childComponentList_.indexOf (const_cast (child)); + return childComponentList_.indexOf (const_cast (child)); } Component* Component::getTopLevelComponent() const throw() { - const Component* comp = this; + const Component* comp = this; - while (comp->parentComponent_ != 0) - comp = comp->parentComponent_; + while (comp->parentComponent_ != 0) + comp = comp->parentComponent_; - return (Component*) comp; + return (Component*) comp; } bool Component::isParentOf (const Component* possibleChild) const throw() { - while (possibleChild->isValidComponent()) - { - possibleChild = possibleChild->parentComponent_; + while (possibleChild->isValidComponent()) + { + possibleChild = possibleChild->parentComponent_; - if (possibleChild == this) - return true; - } + if (possibleChild == this) + return true; + } - return false; + return false; } void Component::parentHierarchyChanged() @@ -40006,538 +39696,538 @@ void Component::childrenChanged() void Component::internalChildrenChanged() { - const ComponentDeletionWatcher deletionChecker (this); - const bool hasListeners = componentListeners_ != 0; + const ComponentDeletionWatcher deletionChecker (this); + const bool hasListeners = componentListeners_ != 0; - childrenChanged(); + childrenChanged(); - if (hasListeners) - { - if (deletionChecker.hasBeenDeleted()) - return; + if (hasListeners) + { + if (deletionChecker.hasBeenDeleted()) + return; - for (int i = componentListeners_->size(); --i >= 0;) - { - ((ComponentListener*) componentListeners_->getUnchecked (i)) - ->componentChildrenChanged (*this); + for (int i = componentListeners_->size(); --i >= 0;) + { + ((ComponentListener*) componentListeners_->getUnchecked (i)) + ->componentChildrenChanged (*this); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, componentListeners_->size()); - } - } + i = jmin (i, componentListeners_->size()); + } + } } void Component::internalHierarchyChanged() { - parentHierarchyChanged(); + parentHierarchyChanged(); - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - if (componentListeners_ != 0) - { - for (int i = componentListeners_->size(); --i >= 0;) - { - ((ComponentListener*) componentListeners_->getUnchecked (i)) - ->componentParentHierarchyChanged (*this); + if (componentListeners_ != 0) + { + for (int i = componentListeners_->size(); --i >= 0;) + { + ((ComponentListener*) componentListeners_->getUnchecked (i)) + ->componentParentHierarchyChanged (*this); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, componentListeners_->size()); - } - } + i = jmin (i, componentListeners_->size()); + } + } - for (int i = childComponentList_.size(); --i >= 0;) - { - childComponentList_.getUnchecked (i)->internalHierarchyChanged(); + for (int i = childComponentList_.size(); --i >= 0;) + { + childComponentList_.getUnchecked (i)->internalHierarchyChanged(); - // you really shouldn't delete the parent component during a callback telling you - // that it's changed.. - jassert (! deletionChecker.hasBeenDeleted()); - if (deletionChecker.hasBeenDeleted()) - return; + // you really shouldn't delete the parent component during a callback telling you + // that it's changed.. + jassert (! deletionChecker.hasBeenDeleted()); + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, childComponentList_.size()); - } + i = jmin (i, childComponentList_.size()); + } } void* Component::runModalLoopCallback (void* userData) { - return (void*) (pointer_sized_int) ((Component*) userData)->runModalLoop(); + return (void*) (pointer_sized_int) ((Component*) userData)->runModalLoop(); } int Component::runModalLoop() { - if (! MessageManager::getInstance()->isThisTheMessageThread()) - { - // use a callback so this can be called from non-gui threads - return (int) (pointer_sized_int) - MessageManager::getInstance() - ->callFunctionOnMessageThread (&runModalLoopCallback, (void*) this); - } + if (! MessageManager::getInstance()->isThisTheMessageThread()) + { + // use a callback so this can be called from non-gui threads + return (int) (pointer_sized_int) + MessageManager::getInstance() + ->callFunctionOnMessageThread (&runModalLoopCallback, (void*) this); + } - Component* const prevFocused = getCurrentlyFocusedComponent(); + Component* const prevFocused = getCurrentlyFocusedComponent(); - ScopedPointer deletionChecker; - if (prevFocused != 0) - deletionChecker = new ComponentDeletionWatcher (prevFocused); + ScopedPointer deletionChecker; + if (prevFocused != 0) + deletionChecker = new ComponentDeletionWatcher (prevFocused); - if (! isCurrentlyModal()) - enterModalState(); + if (! isCurrentlyModal()) + enterModalState(); - JUCE_TRY - { - while (flags.currentlyModalFlag && flags.visibleFlag) - { - if (! MessageManager::getInstance()->runDispatchLoopUntil (20)) - break; + JUCE_TRY + { + while (flags.currentlyModalFlag && flags.visibleFlag) + { + if (! MessageManager::getInstance()->runDispatchLoopUntil (20)) + break; - // check whether this component was deleted during the last message - if (! isValidMessageListener()) - break; - } - } + // check whether this component was deleted during the last message + if (! isValidMessageListener()) + break; + } + } #if JUCE_CATCH_UNHANDLED_EXCEPTIONS - catch (const std::exception& e) - { - JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); - return 0; - } - catch (...) - { - JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); - return 0; - } + catch (const std::exception& e) + { + JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); + return 0; + } + catch (...) + { + JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); + return 0; + } #endif - const int modalIndex = modalComponentReturnValueKeys.indexOf (this); - int returnValue = 0; + const int modalIndex = modalComponentReturnValueKeys.indexOf (this); + int returnValue = 0; - if (modalIndex >= 0) - { - modalComponentReturnValueKeys.remove (modalIndex); - returnValue = modalReturnValues.remove (modalIndex); - } + if (modalIndex >= 0) + { + modalComponentReturnValueKeys.remove (modalIndex); + returnValue = modalReturnValues.remove (modalIndex); + } - modalComponentStack.removeValue (this); + modalComponentStack.removeValue (this); - if (deletionChecker != 0 && ! deletionChecker->hasBeenDeleted()) - prevFocused->grabKeyboardFocus(); + if (deletionChecker != 0 && ! deletionChecker->hasBeenDeleted()) + prevFocused->grabKeyboardFocus(); - return returnValue; + return returnValue; } void Component::enterModalState (const bool takeKeyboardFocus_) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - // Check for an attempt to make a component modal when it already is! - // This can cause nasty problems.. - jassert (! flags.currentlyModalFlag); + // Check for an attempt to make a component modal when it already is! + // This can cause nasty problems.. + jassert (! flags.currentlyModalFlag); - if (! isCurrentlyModal()) - { - modalComponentStack.add (this); - modalComponentReturnValueKeys.add (this); - modalReturnValues.add (0); + if (! isCurrentlyModal()) + { + modalComponentStack.add (this); + modalComponentReturnValueKeys.add (this); + modalReturnValues.add (0); - flags.currentlyModalFlag = true; - setVisible (true); + flags.currentlyModalFlag = true; + setVisible (true); - if (takeKeyboardFocus_) - grabKeyboardFocus(); - } + if (takeKeyboardFocus_) + grabKeyboardFocus(); + } } void Component::exitModalState (const int returnValue) { - if (isCurrentlyModal()) - { - if (MessageManager::getInstance()->isThisTheMessageThread()) - { - const int modalIndex = modalComponentReturnValueKeys.indexOf (this); + if (isCurrentlyModal()) + { + if (MessageManager::getInstance()->isThisTheMessageThread()) + { + const int modalIndex = modalComponentReturnValueKeys.indexOf (this); - if (modalIndex >= 0) - { - modalReturnValues.set (modalIndex, returnValue); - } - else - { - modalComponentReturnValueKeys.add (this); - modalReturnValues.add (returnValue); - } + if (modalIndex >= 0) + { + modalReturnValues.set (modalIndex, returnValue); + } + else + { + modalComponentReturnValueKeys.add (this); + modalReturnValues.add (returnValue); + } - modalComponentStack.removeValue (this); + modalComponentStack.removeValue (this); - flags.currentlyModalFlag = false; + flags.currentlyModalFlag = false; - bringModalComponentToFront(); - } - else - { - postMessage (new Message (exitModalStateMessage, returnValue, 0, 0)); - } - } + bringModalComponentToFront(); + } + else + { + postMessage (new Message (exitModalStateMessage, returnValue, 0, 0)); + } + } } bool Component::isCurrentlyModal() const throw() { - return flags.currentlyModalFlag - && getCurrentlyModalComponent() == this; + return flags.currentlyModalFlag + && getCurrentlyModalComponent() == this; } bool Component::isCurrentlyBlockedByAnotherModalComponent() const throw() { - Component* const mc = getCurrentlyModalComponent(); + Component* const mc = getCurrentlyModalComponent(); - return mc != 0 - && mc != this - && (! mc->isParentOf (this)) - && ! mc->canModalEventBeSentToComponent (this); + return mc != 0 + && mc != this + && (! mc->isParentOf (this)) + && ! mc->canModalEventBeSentToComponent (this); } int JUCE_CALLTYPE Component::getNumCurrentlyModalComponents() throw() { - return modalComponentStack.size(); + return modalComponentStack.size(); } Component* JUCE_CALLTYPE Component::getCurrentlyModalComponent (int index) throw() { - Component* const c = (Component*) (modalComponentStack [modalComponentStack.size() - index - 1]); + Component* const c = (Component*) (modalComponentStack [modalComponentStack.size() - index - 1]); - return c->isValidComponent() ? c : 0; + return c->isValidComponent() ? c : 0; } void Component::bringModalComponentToFront() { - ComponentPeer* lastOne = 0; + ComponentPeer* lastOne = 0; - for (int i = 0; i < getNumCurrentlyModalComponents(); ++i) - { - Component* const c = getCurrentlyModalComponent (i); + for (int i = 0; i < getNumCurrentlyModalComponents(); ++i) + { + Component* const c = getCurrentlyModalComponent (i); - if (c == 0) - break; + if (c == 0) + break; - ComponentPeer* peer = c->getPeer(); + ComponentPeer* peer = c->getPeer(); - if (peer != 0 && peer != lastOne) - { - if (lastOne == 0) - { - peer->toFront (true); - peer->grabFocus(); - } - else - peer->toBehind (lastOne); + if (peer != 0 && peer != lastOne) + { + if (lastOne == 0) + { + peer->toFront (true); + peer->grabFocus(); + } + else + peer->toBehind (lastOne); - lastOne = peer; - } - } + lastOne = peer; + } + } } void Component::setBroughtToFrontOnMouseClick (const bool shouldBeBroughtToFront) throw() { - flags.bringToFrontOnClickFlag = shouldBeBroughtToFront; + flags.bringToFrontOnClickFlag = shouldBeBroughtToFront; } bool Component::isBroughtToFrontOnMouseClick() const throw() { - return flags.bringToFrontOnClickFlag; + return flags.bringToFrontOnClickFlag; } void Component::setMouseCursor (const MouseCursor& cursor) throw() { - cursor_ = cursor; + cursor_ = cursor; - if (flags.visibleFlag) - { - int mx, my; - getMouseXYRelative (mx, my); + if (flags.visibleFlag) + { + int mx, my; + getMouseXYRelative (mx, my); - if (flags.draggingFlag || reallyContains (mx, my, false)) - { - internalUpdateMouseCursor (false); - } - } + if (flags.draggingFlag || reallyContains (mx, my, false)) + { + internalUpdateMouseCursor (false); + } + } } const MouseCursor Component::getMouseCursor() { - return cursor_; + return cursor_; } void Component::updateMouseCursor() const throw() { - sendFakeMouseMove(); + sendFakeMouseMove(); } void Component::internalUpdateMouseCursor (bool forcedUpdate) throw() { - ComponentPeer* const peer = getPeer(); + ComponentPeer* const peer = getPeer(); - if (peer != 0) - { - MouseCursor mc (getLookAndFeel().getMouseCursorFor (*this)); + if (peer != 0) + { + MouseCursor mc (getLookAndFeel().getMouseCursorFor (*this)); - if (isUnboundedMouseModeOn && (unboundedMouseOffsetX != 0 - || unboundedMouseOffsetY != 0 - || ! isCursorVisibleUntilOffscreen)) - { - mc = MouseCursor::NoCursor; - forcedUpdate = true; - } + if (isUnboundedMouseModeOn && (unboundedMouseOffsetX != 0 + || unboundedMouseOffsetY != 0 + || ! isCursorVisibleUntilOffscreen)) + { + mc = MouseCursor::NoCursor; + forcedUpdate = true; + } - static void* currentCursorHandle = 0; + static void* currentCursorHandle = 0; - if (forcedUpdate || mc.getHandle() != currentCursorHandle) - { - currentCursorHandle = mc.getHandle(); - mc.showInWindow (peer); - } - } + if (forcedUpdate || mc.getHandle() != currentCursorHandle) + { + currentCursorHandle = mc.getHandle(); + mc.showInWindow (peer); + } + } } void Component::setRepaintsOnMouseActivity (const bool shouldRepaint) throw() { - flags.repaintOnMouseActivityFlag = shouldRepaint; + flags.repaintOnMouseActivityFlag = shouldRepaint; } void Component::repaintParent() throw() { - if (flags.visibleFlag) - internalRepaint (0, 0, getWidth(), getHeight()); + if (flags.visibleFlag) + internalRepaint (0, 0, getWidth(), getHeight()); } void Component::repaint() throw() { - repaint (0, 0, getWidth(), getHeight()); + repaint (0, 0, getWidth(), getHeight()); } void Component::repaint (const int x, const int y, - const int w, const int h) throw() + const int w, const int h) throw() { - deleteAndZero (bufferedImage_); + deleteAndZero (bufferedImage_); - if (flags.visibleFlag) - internalRepaint (x, y, w, h); + if (flags.visibleFlag) + internalRepaint (x, y, w, h); } void Component::internalRepaint (int x, int y, int w, int h) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - if (x < 0) - { - w += x; - x = 0; - } + if (x < 0) + { + w += x; + x = 0; + } - if (x + w > getWidth()) - w = getWidth() - x; + if (x + w > getWidth()) + w = getWidth() - x; - if (w > 0) - { - if (y < 0) - { - h += y; - y = 0; - } + if (w > 0) + { + if (y < 0) + { + h += y; + y = 0; + } - if (y + h > getHeight()) - h = getHeight() - y; + if (y + h > getHeight()) + h = getHeight() - y; - if (h > 0) - { - if (parentComponent_ != 0) - { - x += getX(); - y += getY(); + if (h > 0) + { + if (parentComponent_ != 0) + { + x += getX(); + y += getY(); - if (parentComponent_->flags.visibleFlag) - parentComponent_->internalRepaint (x, y, w, h); - } - else if (flags.hasHeavyweightPeerFlag) - { - ComponentPeer* const peer = getPeer(); + if (parentComponent_->flags.visibleFlag) + parentComponent_->internalRepaint (x, y, w, h); + } + else if (flags.hasHeavyweightPeerFlag) + { + ComponentPeer* const peer = getPeer(); - if (peer != 0) - peer->repaint (x, y, w, h); - } - } - } + if (peer != 0) + peer->repaint (x, y, w, h); + } + } + } } void Component::paintEntireComponent (Graphics& originalContext) { - jassert (! originalContext.isClipEmpty()); + jassert (! originalContext.isClipEmpty()); #ifdef JUCE_DEBUG - flags.isInsidePaintCall = true; + flags.isInsidePaintCall = true; #endif - Graphics* g = &originalContext; - Image* effectImage = 0; + Graphics* g = &originalContext; + Image* effectImage = 0; - if (effect_ != 0) - { - effectImage = Image::createNativeImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, - getWidth(), getHeight(), - ! flags.opaqueFlag); + if (effect_ != 0) + { + effectImage = Image::createNativeImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, + getWidth(), getHeight(), + ! flags.opaqueFlag); - g = new Graphics (*effectImage); - } + g = new Graphics (*effectImage); + } - g->saveState(); - clipObscuredRegions (*g, g->getClipBounds(), 0, 0); + g->saveState(); + clipObscuredRegions (*g, g->getClipBounds(), 0, 0); - if (! g->isClipEmpty()) - { - if (bufferedImage_ != 0) - { - g->setColour (Colours::black); - g->drawImageAt (bufferedImage_, 0, 0); - } - else - { - if (flags.bufferToImageFlag) - { - if (bufferedImage_ == 0) - { - bufferedImage_ = Image::createNativeImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, - getWidth(), getHeight(), ! flags.opaqueFlag); + if (! g->isClipEmpty()) + { + if (bufferedImage_ != 0) + { + g->setColour (Colours::black); + g->drawImageAt (bufferedImage_, 0, 0); + } + else + { + if (flags.bufferToImageFlag) + { + if (bufferedImage_ == 0) + { + bufferedImage_ = Image::createNativeImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, + getWidth(), getHeight(), ! flags.opaqueFlag); - Graphics imG (*bufferedImage_); - paint (imG); - } + Graphics imG (*bufferedImage_); + paint (imG); + } - g->setColour (Colours::black); - g->drawImageAt (bufferedImage_, 0, 0); - } - else - { - paint (*g); - g->resetToDefaultState(); - } - } - } + g->setColour (Colours::black); + g->drawImageAt (bufferedImage_, 0, 0); + } + else + { + paint (*g); + g->resetToDefaultState(); + } + } + } - g->restoreState(); + g->restoreState(); - for (int i = 0; i < childComponentList_.size(); ++i) - { - Component* const child = childComponentList_.getUnchecked (i); + for (int i = 0; i < childComponentList_.size(); ++i) + { + Component* const child = childComponentList_.getUnchecked (i); - if (child->isVisible()) - { - g->saveState(); + if (child->isVisible()) + { + g->saveState(); - if (g->reduceClipRegion (child->getX(), child->getY(), - child->getWidth(), child->getHeight())) - { - for (int j = i + 1; j < childComponentList_.size(); ++j) - { - const Component* const sibling = childComponentList_.getUnchecked (j); + if (g->reduceClipRegion (child->getX(), child->getY(), + child->getWidth(), child->getHeight())) + { + for (int j = i + 1; j < childComponentList_.size(); ++j) + { + const Component* const sibling = childComponentList_.getUnchecked (j); - if (sibling->flags.opaqueFlag && sibling->isVisible()) - g->excludeClipRegion (sibling->getX(), sibling->getY(), - sibling->getWidth(), sibling->getHeight()); - } + if (sibling->flags.opaqueFlag && sibling->isVisible()) + g->excludeClipRegion (sibling->getX(), sibling->getY(), + sibling->getWidth(), sibling->getHeight()); + } - if (! g->isClipEmpty()) - { - g->setOrigin (child->getX(), child->getY()); + if (! g->isClipEmpty()) + { + g->setOrigin (child->getX(), child->getY()); - child->paintEntireComponent (*g); - } - } + child->paintEntireComponent (*g); + } + } - g->restoreState(); - } - } + g->restoreState(); + } + } - JUCE_TRY - { - g->saveState(); - paintOverChildren (*g); - g->restoreState(); - } - JUCE_CATCH_EXCEPTION + JUCE_TRY + { + g->saveState(); + paintOverChildren (*g); + g->restoreState(); + } + JUCE_CATCH_EXCEPTION - if (effect_ != 0) - { - delete g; + if (effect_ != 0) + { + delete g; - effect_->applyEffect (*effectImage, originalContext); - delete effectImage; - } + effect_->applyEffect (*effectImage, originalContext); + delete effectImage; + } #ifdef JUCE_DEBUG - flags.isInsidePaintCall = false; + flags.isInsidePaintCall = false; #endif } Image* Component::createComponentSnapshot (const Rectangle& areaToGrab, - const bool clipImageToComponentBounds) + const bool clipImageToComponentBounds) { - Rectangle r (areaToGrab); + Rectangle r (areaToGrab); - if (clipImageToComponentBounds) - r = r.getIntersection (Rectangle (0, 0, getWidth(), getHeight())); + if (clipImageToComponentBounds) + r = r.getIntersection (Rectangle (0, 0, getWidth(), getHeight())); - Image* const componentImage = Image::createNativeImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, - jmax (1, r.getWidth()), - jmax (1, r.getHeight()), - true); + Image* const componentImage = Image::createNativeImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, + jmax (1, r.getWidth()), + jmax (1, r.getHeight()), + true); - Graphics imageContext (*componentImage); - imageContext.setOrigin (-r.getX(), - -r.getY()); + Graphics imageContext (*componentImage); + imageContext.setOrigin (-r.getX(), + -r.getY()); - paintEntireComponent (imageContext); + paintEntireComponent (imageContext); - return componentImage; + return componentImage; } void Component::setComponentEffect (ImageEffectFilter* const effect) { - if (effect_ != effect) - { - effect_ = effect; - repaint(); - } + if (effect_ != effect) + { + effect_ = effect; + repaint(); + } } LookAndFeel& Component::getLookAndFeel() const throw() { - const Component* c = this; + const Component* c = this; - do - { - if (c->lookAndFeel_ != 0) - return *(c->lookAndFeel_); + do + { + if (c->lookAndFeel_ != 0) + return *(c->lookAndFeel_); - c = c->parentComponent_; - } - while (c != 0); + c = c->parentComponent_; + } + while (c != 0); - return LookAndFeel::getDefaultLookAndFeel(); + return LookAndFeel::getDefaultLookAndFeel(); } void Component::setLookAndFeel (LookAndFeel* const newLookAndFeel) { - if (lookAndFeel_ != newLookAndFeel) - { - lookAndFeel_ = newLookAndFeel; + if (lookAndFeel_ != newLookAndFeel) + { + lookAndFeel_ = newLookAndFeel; - sendLookAndFeelChange(); - } + sendLookAndFeelChange(); + } } void Component::lookAndFeelChanged() @@ -40546,93 +40236,93 @@ void Component::lookAndFeelChanged() void Component::sendLookAndFeelChange() { - repaint(); + repaint(); - lookAndFeelChanged(); + lookAndFeelChanged(); - // (it's not a great idea to do anything that would delete this component - // during the lookAndFeelChanged() callback) - jassert (isValidComponent()); + // (it's not a great idea to do anything that would delete this component + // during the lookAndFeelChanged() callback) + jassert (isValidComponent()); - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - for (int i = childComponentList_.size(); --i >= 0;) - { - childComponentList_.getUnchecked (i)->sendLookAndFeelChange(); + for (int i = childComponentList_.size(); --i >= 0;) + { + childComponentList_.getUnchecked (i)->sendLookAndFeelChange(); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, childComponentList_.size()); - } + i = jmin (i, childComponentList_.size()); + } } static const String getColourPropertyName (const int colourId) throw() { - String s; - s.preallocateStorage (18); - s << T("jcclr_") << colourId; - return s; + String s; + s.preallocateStorage (18); + s << T("jcclr_") << colourId; + return s; } const Colour Component::findColour (const int colourId, const bool inheritFromParent) const throw() { - const String customColour (getComponentProperty (getColourPropertyName (colourId), - inheritFromParent, - String::empty)); + const String customColour (getComponentProperty (getColourPropertyName (colourId), + inheritFromParent, + String::empty)); - if (customColour.isNotEmpty()) - return Colour (customColour.getIntValue()); + if (customColour.isNotEmpty()) + return Colour (customColour.getIntValue()); - return getLookAndFeel().findColour (colourId); + return getLookAndFeel().findColour (colourId); } bool Component::isColourSpecified (const int colourId) const throw() { - return getComponentProperty (getColourPropertyName (colourId), - false, - String::empty).isNotEmpty(); + return getComponentProperty (getColourPropertyName (colourId), + false, + String::empty).isNotEmpty(); } void Component::removeColour (const int colourId) { - if (isColourSpecified (colourId)) - { - removeComponentProperty (getColourPropertyName (colourId)); - colourChanged(); - } + if (isColourSpecified (colourId)) + { + removeComponentProperty (getColourPropertyName (colourId)); + colourChanged(); + } } void Component::setColour (const int colourId, const Colour& colour) { - const String colourName (getColourPropertyName (colourId)); - const String customColour (getComponentProperty (colourName, false, String::empty)); + const String colourName (getColourPropertyName (colourId)); + const String customColour (getComponentProperty (colourName, false, String::empty)); - if (customColour.isEmpty() || Colour (customColour.getIntValue()) != colour) - { - setComponentProperty (colourName, colour); - colourChanged(); - } + if (customColour.isEmpty() || Colour (customColour.getIntValue()) != colour) + { + setComponentProperty (colourName, colour); + colourChanged(); + } } void Component::copyAllExplicitColoursTo (Component& target) const throw() { - if (propertySet_ != 0) - { - const StringPairArray& props = propertySet_->getAllProperties(); - const StringArray& keys = props.getAllKeys(); + if (propertySet_ != 0) + { + const StringPairArray& props = propertySet_->getAllProperties(); + const StringArray& keys = props.getAllKeys(); - for (int i = 0; i < keys.size(); ++i) - { - if (keys[i].startsWith (T("jcclr_"))) - { - target.setComponentProperty (keys[i], - props.getAllValues() [i]); - } - } + for (int i = 0; i < keys.size(); ++i) + { + if (keys[i].startsWith (T("jcclr_"))) + { + target.setComponentProperty (keys[i], + props.getAllValues() [i]); + } + } - target.colourChanged(); - } + target.colourChanged(); + } } void Component::colourChanged() @@ -40641,1079 +40331,1079 @@ void Component::colourChanged() const Rectangle Component::getUnclippedArea() const { - int x = 0, y = 0, w = getWidth(), h = getHeight(); + int x = 0, y = 0, w = getWidth(), h = getHeight(); - Component* p = parentComponent_; - int px = getX(); - int py = getY(); + Component* p = parentComponent_; + int px = getX(); + int py = getY(); - while (p != 0) - { - if (! Rectangle::intersectRectangles (x, y, w, h, -px, -py, p->getWidth(), p->getHeight())) - return Rectangle(); + while (p != 0) + { + if (! Rectangle::intersectRectangles (x, y, w, h, -px, -py, p->getWidth(), p->getHeight())) + return Rectangle(); - px += p->getX(); - py += p->getY(); - p = p->parentComponent_; - } + px += p->getX(); + py += p->getY(); + p = p->parentComponent_; + } - return Rectangle (x, y, w, h); + return Rectangle (x, y, w, h); } void Component::clipObscuredRegions (Graphics& g, const Rectangle& clipRect, - const int deltaX, const int deltaY) const throw() + const int deltaX, const int deltaY) const throw() { - for (int i = childComponentList_.size(); --i >= 0;) - { - const Component* const c = childComponentList_.getUnchecked(i); + for (int i = childComponentList_.size(); --i >= 0;) + { + const Component* const c = childComponentList_.getUnchecked(i); - if (c->isVisible()) - { - Rectangle newClip (clipRect.getIntersection (c->bounds_)); + if (c->isVisible()) + { + Rectangle newClip (clipRect.getIntersection (c->bounds_)); - if (! newClip.isEmpty()) - { - if (c->isOpaque()) - { - g.excludeClipRegion (deltaX + newClip.getX(), - deltaY + newClip.getY(), - newClip.getWidth(), - newClip.getHeight()); - } - else - { - newClip.translate (-c->getX(), -c->getY()); - c->clipObscuredRegions (g, newClip, - c->getX() + deltaX, - c->getY() + deltaY); - } - } - } - } + if (! newClip.isEmpty()) + { + if (c->isOpaque()) + { + g.excludeClipRegion (deltaX + newClip.getX(), + deltaY + newClip.getY(), + newClip.getWidth(), + newClip.getHeight()); + } + else + { + newClip.translate (-c->getX(), -c->getY()); + c->clipObscuredRegions (g, newClip, + c->getX() + deltaX, + c->getY() + deltaY); + } + } + } + } } void Component::getVisibleArea (RectangleList& result, - const bool includeSiblings) const + const bool includeSiblings) const { - result.clear(); - const Rectangle unclipped (getUnclippedArea()); + result.clear(); + const Rectangle unclipped (getUnclippedArea()); - if (! unclipped.isEmpty()) - { - result.add (unclipped); + if (! unclipped.isEmpty()) + { + result.add (unclipped); - if (includeSiblings) - { - const Component* const c = getTopLevelComponent(); + if (includeSiblings) + { + const Component* const c = getTopLevelComponent(); - int x = 0, y = 0; - c->relativePositionToOtherComponent (this, x, y); + int x = 0, y = 0; + c->relativePositionToOtherComponent (this, x, y); - c->subtractObscuredRegions (result, x, y, - Rectangle (0, 0, c->getWidth(), c->getHeight()), - this); - } + c->subtractObscuredRegions (result, x, y, + Rectangle (0, 0, c->getWidth(), c->getHeight()), + this); + } - subtractObscuredRegions (result, 0, 0, unclipped, 0); - result.consolidate(); - } + subtractObscuredRegions (result, 0, 0, unclipped, 0); + result.consolidate(); + } } void Component::subtractObscuredRegions (RectangleList& result, - const int deltaX, - const int deltaY, - const Rectangle& clipRect, - const Component* const compToAvoid) const throw() + const int deltaX, + const int deltaY, + const Rectangle& clipRect, + const Component* const compToAvoid) const throw() { - for (int i = childComponentList_.size(); --i >= 0;) - { - const Component* const c = childComponentList_.getUnchecked(i); + for (int i = childComponentList_.size(); --i >= 0;) + { + const Component* const c = childComponentList_.getUnchecked(i); - if (c != compToAvoid && c->isVisible()) - { - if (c->isOpaque()) - { - Rectangle childBounds (c->bounds_.getIntersection (clipRect)); - childBounds.translate (deltaX, deltaY); + if (c != compToAvoid && c->isVisible()) + { + if (c->isOpaque()) + { + Rectangle childBounds (c->bounds_.getIntersection (clipRect)); + childBounds.translate (deltaX, deltaY); - result.subtract (childBounds); - } - else - { - Rectangle newClip (clipRect.getIntersection (c->bounds_)); - newClip.translate (-c->getX(), -c->getY()); + result.subtract (childBounds); + } + else + { + Rectangle newClip (clipRect.getIntersection (c->bounds_)); + newClip.translate (-c->getX(), -c->getY()); - c->subtractObscuredRegions (result, - c->getX() + deltaX, - c->getY() + deltaY, - newClip, - compToAvoid); - } - } - } + c->subtractObscuredRegions (result, + c->getX() + deltaX, + c->getY() + deltaY, + newClip, + compToAvoid); + } + } + } } void Component::mouseEnter (const MouseEvent&) { - // base class does nothing + // base class does nothing } void Component::mouseExit (const MouseEvent&) { - // base class does nothing + // base class does nothing } void Component::mouseDown (const MouseEvent&) { - // base class does nothing + // base class does nothing } void Component::mouseUp (const MouseEvent&) { - // base class does nothing + // base class does nothing } void Component::mouseDrag (const MouseEvent&) { - // base class does nothing + // base class does nothing } void Component::mouseMove (const MouseEvent&) { - // base class does nothing + // base class does nothing } void Component::mouseDoubleClick (const MouseEvent&) { - // base class does nothing + // base class does nothing } void Component::mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY) { - // the base class just passes this event up to its parent.. + // the base class just passes this event up to its parent.. - if (parentComponent_ != 0) - parentComponent_->mouseWheelMove (e.getEventRelativeTo (parentComponent_), - wheelIncrementX, wheelIncrementY); + if (parentComponent_ != 0) + parentComponent_->mouseWheelMove (e.getEventRelativeTo (parentComponent_), + wheelIncrementX, wheelIncrementY); } void Component::resized() { - // base class does nothing + // base class does nothing } void Component::moved() { - // base class does nothing + // base class does nothing } void Component::childBoundsChanged (Component*) { - // base class does nothing + // base class does nothing } void Component::parentSizeChanged() { - // base class does nothing + // base class does nothing } void Component::addComponentListener (ComponentListener* const newListener) throw() { - if (componentListeners_ == 0) - componentListeners_ = new VoidArray (4); + if (componentListeners_ == 0) + componentListeners_ = new VoidArray(); - componentListeners_->addIfNotAlreadyThere (newListener); + componentListeners_->addIfNotAlreadyThere (newListener); } void Component::removeComponentListener (ComponentListener* const listenerToRemove) throw() { - jassert (isValidComponent()); + jassert (isValidComponent()); - if (componentListeners_ != 0) - componentListeners_->removeValue (listenerToRemove); + if (componentListeners_ != 0) + componentListeners_->removeValue (listenerToRemove); } void Component::inputAttemptWhenModal() { - bringModalComponentToFront(); - getLookAndFeel().playAlertSound(); + bringModalComponentToFront(); + getLookAndFeel().playAlertSound(); } bool Component::canModalEventBeSentToComponent (const Component*) { - return false; + return false; } void Component::internalModalInputAttempt() { - Component* const current = getCurrentlyModalComponent(); + Component* const current = getCurrentlyModalComponent(); - if (current != 0) - current->inputAttemptWhenModal(); + if (current != 0) + current->inputAttemptWhenModal(); } void Component::paint (Graphics&) { - // all painting is done in the subclasses + // all painting is done in the subclasses - jassert (! isOpaque()); // if your component's opaque, you've gotta paint it! + jassert (! isOpaque()); // if your component's opaque, you've gotta paint it! } void Component::paintOverChildren (Graphics&) { - // all painting is done in the subclasses + // all painting is done in the subclasses } void Component::handleMessage (const Message& message) { - if (message.intParameter1 == exitModalStateMessage) - { - exitModalState (message.intParameter2); - } - else if (message.intParameter1 == customCommandMessage) - { - handleCommandMessage (message.intParameter2); - } + if (message.intParameter1 == exitModalStateMessage) + { + exitModalState (message.intParameter2); + } + else if (message.intParameter1 == customCommandMessage) + { + handleCommandMessage (message.intParameter2); + } } void Component::postCommandMessage (const int commandId) throw() { - postMessage (new Message (customCommandMessage, commandId, 0, 0)); + postMessage (new Message (customCommandMessage, commandId, 0, 0)); } void Component::handleCommandMessage (int) { - // used by subclasses + // used by subclasses } void Component::addMouseListener (MouseListener* const newListener, - const bool wantsEventsForAllNestedChildComponents) throw() + const bool wantsEventsForAllNestedChildComponents) throw() { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - if (mouseListeners_ == 0) - mouseListeners_ = new VoidArray (4); + if (mouseListeners_ == 0) + mouseListeners_ = new VoidArray(); - if (! mouseListeners_->contains (newListener)) - { - if (wantsEventsForAllNestedChildComponents) - { - mouseListeners_->insert (0, newListener); - ++numDeepMouseListeners; - } - else - { - mouseListeners_->add (newListener); - } - } + if (! mouseListeners_->contains (newListener)) + { + if (wantsEventsForAllNestedChildComponents) + { + mouseListeners_->insert (0, newListener); + ++numDeepMouseListeners; + } + else + { + mouseListeners_->add (newListener); + } + } } void Component::removeMouseListener (MouseListener* const listenerToRemove) throw() { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - if (mouseListeners_ != 0) - { - const int index = mouseListeners_->indexOf (listenerToRemove); + if (mouseListeners_ != 0) + { + const int index = mouseListeners_->indexOf (listenerToRemove); - if (index >= 0) - { - if (index < numDeepMouseListeners) - --numDeepMouseListeners; + if (index >= 0) + { + if (index < numDeepMouseListeners) + --numDeepMouseListeners; - mouseListeners_->remove (index); - } - } + mouseListeners_->remove (index); + } + } } void Component::internalMouseEnter (int x, int y, int64 time) { - if (isCurrentlyBlockedByAnotherModalComponent()) - { - // if something else is modal, always just show a normal mouse cursor - if (componentUnderMouse == this) - { - ComponentPeer* const peer = getPeer(); + if (isCurrentlyBlockedByAnotherModalComponent()) + { + // if something else is modal, always just show a normal mouse cursor + if (componentUnderMouse == this) + { + ComponentPeer* const peer = getPeer(); - if (peer != 0) - { - MouseCursor mc (MouseCursor::NormalCursor); - mc.showInWindow (peer); - } - } + if (peer != 0) + { + MouseCursor mc (MouseCursor::NormalCursor); + mc.showInWindow (peer); + } + } - return; - } + return; + } - if (! flags.mouseInsideFlag) - { - flags.mouseInsideFlag = true; - flags.mouseOverFlag = true; - flags.draggingFlag = false; + if (! flags.mouseInsideFlag) + { + flags.mouseInsideFlag = true; + flags.mouseOverFlag = true; + flags.draggingFlag = false; - if (isValidComponent()) - { - const ComponentDeletionWatcher deletionChecker (this); + if (isValidComponent()) + { + const ComponentDeletionWatcher deletionChecker (this); - if (flags.repaintOnMouseActivityFlag) - repaint(); + if (flags.repaintOnMouseActivityFlag) + repaint(); - const MouseEvent me (x, y, - ModifierKeys::getCurrentModifiers(), - this, - Time (time), - x, y, - Time (time), - 0, false); + const MouseEvent me (x, y, + ModifierKeys::getCurrentModifiers(), + this, + Time (time), + x, y, + Time (time), + 0, false); - mouseEnter (me); + mouseEnter (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - Desktop::getInstance().resetTimer(); + Desktop::getInstance().resetTimer(); - for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseEnter (me); + for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseEnter (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, Desktop::getInstance().mouseListeners.size()); - } + i = jmin (i, Desktop::getInstance().mouseListeners.size()); + } - if (mouseListeners_ != 0) - { - for (int i = mouseListeners_->size(); --i >= 0;) - { - ((MouseListener*) mouseListeners_->getUnchecked(i))->mouseEnter (me); + if (mouseListeners_ != 0) + { + for (int i = mouseListeners_->size(); --i >= 0;) + { + ((MouseListener*) mouseListeners_->getUnchecked(i))->mouseEnter (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, mouseListeners_->size()); - } - } + i = jmin (i, mouseListeners_->size()); + } + } - const Component* p = parentComponent_; + const Component* p = parentComponent_; - while (p != 0) - { - const ComponentDeletionWatcher parentDeletionChecker (p); + while (p != 0) + { + const ComponentDeletionWatcher parentDeletionChecker (p); - for (int i = p->numDeepMouseListeners; --i >= 0;) - { - ((MouseListener*) (p->mouseListeners_->getUnchecked(i)))->mouseEnter (me); + for (int i = p->numDeepMouseListeners; --i >= 0;) + { + ((MouseListener*) (p->mouseListeners_->getUnchecked(i)))->mouseEnter (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + return; - i = jmin (i, p->numDeepMouseListeners); - } + i = jmin (i, p->numDeepMouseListeners); + } - p = p->parentComponent_; - } - } - } + p = p->parentComponent_; + } + } + } - if (componentUnderMouse == this) - internalUpdateMouseCursor (true); + if (componentUnderMouse == this) + internalUpdateMouseCursor (true); } void Component::internalMouseExit (int x, int y, int64 time) { - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - if (flags.draggingFlag) - { - internalMouseUp (ModifierKeys::getCurrentModifiers().getRawFlags(), x, y, time); + if (flags.draggingFlag) + { + internalMouseUp (ModifierKeys::getCurrentModifiers().getRawFlags(), x, y, time); - if (deletionChecker.hasBeenDeleted()) - return; - } + if (deletionChecker.hasBeenDeleted()) + return; + } - enableUnboundedMouseMovement (false); + enableUnboundedMouseMovement (false); - if (flags.mouseInsideFlag || flags.mouseOverFlag) - { - flags.mouseInsideFlag = false; - flags.mouseOverFlag = false; - flags.draggingFlag = false; + if (flags.mouseInsideFlag || flags.mouseOverFlag) + { + flags.mouseInsideFlag = false; + flags.mouseOverFlag = false; + flags.draggingFlag = false; - if (flags.repaintOnMouseActivityFlag) - repaint(); + if (flags.repaintOnMouseActivityFlag) + repaint(); - const MouseEvent me (x, y, - ModifierKeys::getCurrentModifiers(), - this, - Time (time), - x, y, - Time (time), - 0, false); - mouseExit (me); + const MouseEvent me (x, y, + ModifierKeys::getCurrentModifiers(), + this, + Time (time), + x, y, + Time (time), + 0, false); + mouseExit (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - Desktop::getInstance().resetTimer(); + Desktop::getInstance().resetTimer(); - for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseExit (me); + for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseExit (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, Desktop::getInstance().mouseListeners.size()); - } + i = jmin (i, Desktop::getInstance().mouseListeners.size()); + } - if (mouseListeners_ != 0) - { - for (int i = mouseListeners_->size(); --i >= 0;) - { - ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseExit (me); + if (mouseListeners_ != 0) + { + for (int i = mouseListeners_->size(); --i >= 0;) + { + ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseExit (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, mouseListeners_->size()); - } - } + i = jmin (i, mouseListeners_->size()); + } + } - const Component* p = parentComponent_; + const Component* p = parentComponent_; - while (p != 0) - { - const ComponentDeletionWatcher parentDeletionChecker (p); + while (p != 0) + { + const ComponentDeletionWatcher parentDeletionChecker (p); - for (int i = p->numDeepMouseListeners; --i >= 0;) - { - ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseExit (me); + for (int i = p->numDeepMouseListeners; --i >= 0;) + { + ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseExit (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + return; - i = jmin (i, p->numDeepMouseListeners); - } + i = jmin (i, p->numDeepMouseListeners); + } - p = p->parentComponent_; - } - } + p = p->parentComponent_; + } + } } class InternalDragRepeater : public Timer { public: - InternalDragRepeater() - {} + InternalDragRepeater() + {} - ~InternalDragRepeater() - {} + ~InternalDragRepeater() + {} - void timerCallback() - { - Component* const c = Component::getComponentUnderMouse(); + void timerCallback() + { + Component* const c = Component::getComponentUnderMouse(); - if (c != 0 && c->isMouseButtonDown()) - { - int x, y; - c->getMouseXYRelative (x, y); + if (c != 0 && c->isMouseButtonDown()) + { + int x, y; + c->getMouseXYRelative (x, y); - // the offsets have been added on, so must be taken off before calling the - // drag.. otherwise they'll be added twice - x -= unboundedMouseOffsetX; - y -= unboundedMouseOffsetY; + // the offsets have been added on, so must be taken off before calling the + // drag.. otherwise they'll be added twice + x -= unboundedMouseOffsetX; + y -= unboundedMouseOffsetY; - c->internalMouseDrag (x, y, Time::currentTimeMillis()); - } - } + c->internalMouseDrag (x, y, Time::currentTimeMillis()); + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; static InternalDragRepeater* dragRepeater = 0; void Component::beginDragAutoRepeat (const int interval) { - if (interval > 0) - { - if (dragRepeater == 0) - dragRepeater = new InternalDragRepeater(); + if (interval > 0) + { + if (dragRepeater == 0) + dragRepeater = new InternalDragRepeater(); - if (dragRepeater->getTimerInterval() != interval) - dragRepeater->startTimer (interval); - } - else - { - deleteAndZero (dragRepeater); - } + if (dragRepeater->getTimerInterval() != interval) + dragRepeater->startTimer (interval); + } + else + { + deleteAndZero (dragRepeater); + } } void Component::internalMouseDown (const int x, const int y) { - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - if (isCurrentlyBlockedByAnotherModalComponent()) - { - internalModalInputAttempt(); + if (isCurrentlyBlockedByAnotherModalComponent()) + { + internalModalInputAttempt(); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - // If processing the input attempt has exited the modal loop, we'll allow the event - // to be delivered.. - if (isCurrentlyBlockedByAnotherModalComponent()) - { - // allow blocked mouse-events to go to global listeners.. - const MouseEvent me (x, y, - ModifierKeys::getCurrentModifiers(), - this, - Time (juce_recentMouseDownTimes[0]), - x, y, - Time (juce_recentMouseDownTimes[0]), - countMouseClicks(), - false); + // If processing the input attempt has exited the modal loop, we'll allow the event + // to be delivered.. + if (isCurrentlyBlockedByAnotherModalComponent()) + { + // allow blocked mouse-events to go to global listeners.. + const MouseEvent me (x, y, + ModifierKeys::getCurrentModifiers(), + this, + Time (juce_recentMouseDownTimes[0]), + x, y, + Time (juce_recentMouseDownTimes[0]), + countMouseClicks(), + false); - Desktop::getInstance().resetTimer(); + Desktop::getInstance().resetTimer(); - for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseDown (me); + for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseDown (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, Desktop::getInstance().mouseListeners.size()); - } + i = jmin (i, Desktop::getInstance().mouseListeners.size()); + } - return; - } - } + return; + } + } - { - Component* c = this; + { + Component* c = this; - while (c != 0) - { - if (c->isBroughtToFrontOnMouseClick()) - { - c->toFront (true); + while (c != 0) + { + if (c->isBroughtToFrontOnMouseClick()) + { + c->toFront (true); - if (deletionChecker.hasBeenDeleted()) - return; - } + if (deletionChecker.hasBeenDeleted()) + return; + } - c = c->parentComponent_; - } - } + c = c->parentComponent_; + } + } - if (! flags.dontFocusOnMouseClickFlag) - grabFocusInternal (focusChangedByMouseClick); + if (! flags.dontFocusOnMouseClickFlag) + grabFocusInternal (focusChangedByMouseClick); - if (! deletionChecker.hasBeenDeleted()) - { - flags.draggingFlag = true; - flags.mouseOverFlag = true; + if (! deletionChecker.hasBeenDeleted()) + { + flags.draggingFlag = true; + flags.mouseOverFlag = true; - if (flags.repaintOnMouseActivityFlag) - repaint(); + if (flags.repaintOnMouseActivityFlag) + repaint(); - const MouseEvent me (x, y, - ModifierKeys::getCurrentModifiers(), - this, - Time (juce_recentMouseDownTimes[0]), - x, y, - Time (juce_recentMouseDownTimes[0]), - countMouseClicks(), - false); - mouseDown (me); + const MouseEvent me (x, y, + ModifierKeys::getCurrentModifiers(), + this, + Time (juce_recentMouseDownTimes[0]), + x, y, + Time (juce_recentMouseDownTimes[0]), + countMouseClicks(), + false); + mouseDown (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - Desktop::getInstance().resetTimer(); + Desktop::getInstance().resetTimer(); - for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseDown (me); + for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseDown (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, Desktop::getInstance().mouseListeners.size()); - } + i = jmin (i, Desktop::getInstance().mouseListeners.size()); + } - if (mouseListeners_ != 0) - { - for (int i = mouseListeners_->size(); --i >= 0;) - { - ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseDown (me); + if (mouseListeners_ != 0) + { + for (int i = mouseListeners_->size(); --i >= 0;) + { + ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseDown (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, mouseListeners_->size()); - } - } + i = jmin (i, mouseListeners_->size()); + } + } - const Component* p = parentComponent_; + const Component* p = parentComponent_; - while (p != 0) - { - const ComponentDeletionWatcher parentDeletionChecker (p); + while (p != 0) + { + const ComponentDeletionWatcher parentDeletionChecker (p); - for (int i = p->numDeepMouseListeners; --i >= 0;) - { - ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDown (me); + for (int i = p->numDeepMouseListeners; --i >= 0;) + { + ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDown (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + return; - i = jmin (i, p->numDeepMouseListeners); - } + i = jmin (i, p->numDeepMouseListeners); + } - p = p->parentComponent_; - } - } + p = p->parentComponent_; + } + } } void Component::internalMouseUp (const int oldModifiers, int x, int y, const int64 time) { - if (isValidComponent() && flags.draggingFlag) - { - flags.draggingFlag = false; - deleteAndZero (dragRepeater); + if (isValidComponent() && flags.draggingFlag) + { + flags.draggingFlag = false; + deleteAndZero (dragRepeater); - x += unboundedMouseOffsetX; - y += unboundedMouseOffsetY; - juce_LastMousePosX = x; - juce_LastMousePosY = y; - relativePositionToGlobal (juce_LastMousePosX, juce_LastMousePosY); + x += unboundedMouseOffsetX; + y += unboundedMouseOffsetY; + juce_LastMousePosX = x; + juce_LastMousePosY = y; + relativePositionToGlobal (juce_LastMousePosX, juce_LastMousePosY); - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - if (flags.repaintOnMouseActivityFlag) - repaint(); + if (flags.repaintOnMouseActivityFlag) + repaint(); - int mdx = juce_recentMouseDownX[0]; - int mdy = juce_recentMouseDownY[0]; - globalPositionToRelative (mdx, mdy); + int mdx = juce_recentMouseDownX[0]; + int mdy = juce_recentMouseDownY[0]; + globalPositionToRelative (mdx, mdy); - const MouseEvent me (x, y, - oldModifiers, - this, - Time (time), - mdx, mdy, - Time (juce_recentMouseDownTimes [0]), - countMouseClicks(), - juce_MouseHasMovedSignificantlySincePressed - || juce_recentMouseDownTimes[0] + 300 < time); + const MouseEvent me (x, y, + oldModifiers, + this, + Time (time), + mdx, mdy, + Time (juce_recentMouseDownTimes [0]), + countMouseClicks(), + juce_MouseHasMovedSignificantlySincePressed + || juce_recentMouseDownTimes[0] + 300 < time); - mouseUp (me); + mouseUp (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - Desktop::getInstance().resetTimer(); + Desktop::getInstance().resetTimer(); - for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseUp (me); + for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseUp (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, Desktop::getInstance().mouseListeners.size()); - } + i = jmin (i, Desktop::getInstance().mouseListeners.size()); + } - if (mouseListeners_ != 0) - { - for (int i = mouseListeners_->size(); --i >= 0;) - { - ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseUp (me); + if (mouseListeners_ != 0) + { + for (int i = mouseListeners_->size(); --i >= 0;) + { + ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseUp (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, mouseListeners_->size()); - } - } + i = jmin (i, mouseListeners_->size()); + } + } - { - const Component* p = parentComponent_; + { + const Component* p = parentComponent_; - while (p != 0) - { - const ComponentDeletionWatcher parentDeletionChecker (p); + while (p != 0) + { + const ComponentDeletionWatcher parentDeletionChecker (p); - for (int i = p->numDeepMouseListeners; --i >= 0;) - { - ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseUp (me); + for (int i = p->numDeepMouseListeners; --i >= 0;) + { + ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseUp (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + return; - i = jmin (i, p->numDeepMouseListeners); - } + i = jmin (i, p->numDeepMouseListeners); + } - p = p->parentComponent_; - } - } + p = p->parentComponent_; + } + } - // check for double-click - if (me.getNumberOfClicks() >= 2) - { - const int numListeners = (mouseListeners_ != 0) ? mouseListeners_->size() : 0; + // check for double-click + if (me.getNumberOfClicks() >= 2) + { + const int numListeners = (mouseListeners_ != 0) ? mouseListeners_->size() : 0; - mouseDoubleClick (me); + mouseDoubleClick (me); - int i; - for (i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseDoubleClick (me); + int i; + for (i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseDoubleClick (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, Desktop::getInstance().mouseListeners.size()); - } + i = jmin (i, Desktop::getInstance().mouseListeners.size()); + } - for (i = numListeners; --i >= 0;) - { - if (deletionChecker.hasBeenDeleted() || mouseListeners_ == 0) - return; + for (i = numListeners; --i >= 0;) + { + if (deletionChecker.hasBeenDeleted() || mouseListeners_ == 0) + return; - MouseListener* const ml = (MouseListener*)((*mouseListeners_)[i]); - if (ml != 0) - ml->mouseDoubleClick (me); - } + MouseListener* const ml = (MouseListener*)((*mouseListeners_)[i]); + if (ml != 0) + ml->mouseDoubleClick (me); + } - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - const Component* p = parentComponent_; + const Component* p = parentComponent_; - while (p != 0) - { - const ComponentDeletionWatcher parentDeletionChecker (p); + while (p != 0) + { + const ComponentDeletionWatcher parentDeletionChecker (p); - for (i = p->numDeepMouseListeners; --i >= 0;) - { - ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDoubleClick (me); + for (i = p->numDeepMouseListeners; --i >= 0;) + { + ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDoubleClick (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + return; - i = jmin (i, p->numDeepMouseListeners); - } + i = jmin (i, p->numDeepMouseListeners); + } - p = p->parentComponent_; - } - } - } + p = p->parentComponent_; + } + } + } - enableUnboundedMouseMovement (false); + enableUnboundedMouseMovement (false); } void Component::internalMouseDrag (int x, int y, const int64 time) { - if (isValidComponent() && flags.draggingFlag) - { - flags.mouseOverFlag = reallyContains (x, y, false); + if (isValidComponent() && flags.draggingFlag) + { + flags.mouseOverFlag = reallyContains (x, y, false); - x += unboundedMouseOffsetX; - y += unboundedMouseOffsetY; - juce_LastMousePosX = x; - juce_LastMousePosY = y; - relativePositionToGlobal (juce_LastMousePosX, juce_LastMousePosY); + x += unboundedMouseOffsetX; + y += unboundedMouseOffsetY; + juce_LastMousePosX = x; + juce_LastMousePosY = y; + relativePositionToGlobal (juce_LastMousePosX, juce_LastMousePosY); - juce_MouseHasMovedSignificantlySincePressed - = juce_MouseHasMovedSignificantlySincePressed - || abs (juce_recentMouseDownX[0] - juce_LastMousePosX) >= 4 - || abs (juce_recentMouseDownY[0] - juce_LastMousePosY) >= 4; + juce_MouseHasMovedSignificantlySincePressed + = juce_MouseHasMovedSignificantlySincePressed + || abs (juce_recentMouseDownX[0] - juce_LastMousePosX) >= 4 + || abs (juce_recentMouseDownY[0] - juce_LastMousePosY) >= 4; - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - int mdx = juce_recentMouseDownX[0]; - int mdy = juce_recentMouseDownY[0]; - globalPositionToRelative (mdx, mdy); + int mdx = juce_recentMouseDownX[0]; + int mdy = juce_recentMouseDownY[0]; + globalPositionToRelative (mdx, mdy); - const MouseEvent me (x, y, - ModifierKeys::getCurrentModifiers(), - this, - Time (time), - mdx, mdy, - Time (juce_recentMouseDownTimes[0]), - countMouseClicks(), - juce_MouseHasMovedSignificantlySincePressed - || juce_recentMouseDownTimes[0] + 300 < time); + const MouseEvent me (x, y, + ModifierKeys::getCurrentModifiers(), + this, + Time (time), + mdx, mdy, + Time (juce_recentMouseDownTimes[0]), + countMouseClicks(), + juce_MouseHasMovedSignificantlySincePressed + || juce_recentMouseDownTimes[0] + 300 < time); - mouseDrag (me); + mouseDrag (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - Desktop::getInstance().resetTimer(); + Desktop::getInstance().resetTimer(); - for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseDrag (me); + for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseDrag (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, Desktop::getInstance().mouseListeners.size()); - } + i = jmin (i, Desktop::getInstance().mouseListeners.size()); + } - if (mouseListeners_ != 0) - { - for (int i = mouseListeners_->size(); --i >= 0;) - { - ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseDrag (me); + if (mouseListeners_ != 0) + { + for (int i = mouseListeners_->size(); --i >= 0;) + { + ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseDrag (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, mouseListeners_->size()); - } - } + i = jmin (i, mouseListeners_->size()); + } + } - const Component* p = parentComponent_; + const Component* p = parentComponent_; - while (p != 0) - { - const ComponentDeletionWatcher parentDeletionChecker (p); + while (p != 0) + { + const ComponentDeletionWatcher parentDeletionChecker (p); - for (int i = p->numDeepMouseListeners; --i >= 0;) - { - ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDrag (me); + for (int i = p->numDeepMouseListeners; --i >= 0;) + { + ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseDrag (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + return; - i = jmin (i, p->numDeepMouseListeners); - } + i = jmin (i, p->numDeepMouseListeners); + } - p = p->parentComponent_; - } + p = p->parentComponent_; + } - if (this == componentUnderMouse) - { - if (isUnboundedMouseModeOn) - { - Rectangle screenArea (getParentMonitorArea().expanded (-2, -2)); + if (this == componentUnderMouse) + { + if (isUnboundedMouseModeOn) + { + Rectangle screenArea (getParentMonitorArea().expanded (-2, -2)); - int mx, my; - Desktop::getMousePosition (mx, my); + int mx, my; + Desktop::getMousePosition (mx, my); - if (! screenArea.contains (mx, my)) - { - int deltaX = 0, deltaY = 0; + if (! screenArea.contains (mx, my)) + { + int deltaX = 0, deltaY = 0; - if (mx <= screenArea.getX() || mx >= screenArea.getRight()) - deltaX = getScreenX() + getWidth() / 2 - mx; + if (mx <= screenArea.getX() || mx >= screenArea.getRight()) + deltaX = getScreenX() + getWidth() / 2 - mx; - if (my <= screenArea.getY() || my >= screenArea.getBottom()) - deltaY = getScreenY() + getHeight() / 2 - my; + if (my <= screenArea.getY() || my >= screenArea.getBottom()) + deltaY = getScreenY() + getHeight() / 2 - my; - unboundedMouseOffsetX -= deltaX; - unboundedMouseOffsetY -= deltaY; + unboundedMouseOffsetX -= deltaX; + unboundedMouseOffsetY -= deltaY; - Desktop::setMousePosition (mx + deltaX, - my + deltaY); - } - else if (isCursorVisibleUntilOffscreen - && (unboundedMouseOffsetX != 0 || unboundedMouseOffsetY != 0) - && screenArea.contains (mx + unboundedMouseOffsetX, - my + unboundedMouseOffsetY)) - { - mx += unboundedMouseOffsetX; - my += unboundedMouseOffsetY; - unboundedMouseOffsetX = 0; - unboundedMouseOffsetY = 0; + Desktop::setMousePosition (mx + deltaX, + my + deltaY); + } + else if (isCursorVisibleUntilOffscreen + && (unboundedMouseOffsetX != 0 || unboundedMouseOffsetY != 0) + && screenArea.contains (mx + unboundedMouseOffsetX, + my + unboundedMouseOffsetY)) + { + mx += unboundedMouseOffsetX; + my += unboundedMouseOffsetY; + unboundedMouseOffsetX = 0; + unboundedMouseOffsetY = 0; - Desktop::setMousePosition (mx, my); - } - } + Desktop::setMousePosition (mx, my); + } + } - internalUpdateMouseCursor (false); - } - } + internalUpdateMouseCursor (false); + } + } } void Component::internalMouseMove (const int x, const int y, const int64 time) { - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - if (isValidComponent()) - { - const MouseEvent me (x, y, - ModifierKeys::getCurrentModifiers(), - this, - Time (time), - x, y, - Time (time), - 0, false); + if (isValidComponent()) + { + const MouseEvent me (x, y, + ModifierKeys::getCurrentModifiers(), + this, + Time (time), + x, y, + Time (time), + 0, false); - if (isCurrentlyBlockedByAnotherModalComponent()) - { - // allow blocked mouse-events to go to global listeners.. - Desktop::getInstance().sendMouseMove(); - } - else - { - if (this == componentUnderMouse) - internalUpdateMouseCursor (false); + if (isCurrentlyBlockedByAnotherModalComponent()) + { + // allow blocked mouse-events to go to global listeners.. + Desktop::getInstance().sendMouseMove(); + } + else + { + if (this == componentUnderMouse) + internalUpdateMouseCursor (false); - flags.mouseOverFlag = true; + flags.mouseOverFlag = true; - mouseMove (me); + mouseMove (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - Desktop::getInstance().resetTimer(); + Desktop::getInstance().resetTimer(); - for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseMove (me); + for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseMove (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, Desktop::getInstance().mouseListeners.size()); - } + i = jmin (i, Desktop::getInstance().mouseListeners.size()); + } - if (mouseListeners_ != 0) - { - for (int i = mouseListeners_->size(); --i >= 0;) - { - ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseMove (me); + if (mouseListeners_ != 0) + { + for (int i = mouseListeners_->size(); --i >= 0;) + { + ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseMove (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, mouseListeners_->size()); - } - } + i = jmin (i, mouseListeners_->size()); + } + } - const Component* p = parentComponent_; + const Component* p = parentComponent_; - while (p != 0) - { - const ComponentDeletionWatcher parentDeletionChecker (p); + while (p != 0) + { + const ComponentDeletionWatcher parentDeletionChecker (p); - for (int i = p->numDeepMouseListeners; --i >= 0;) - { - ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseMove (me); + for (int i = p->numDeepMouseListeners; --i >= 0;) + { + ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseMove (me); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + return; - i = jmin (i, p->numDeepMouseListeners); - } + i = jmin (i, p->numDeepMouseListeners); + } - p = p->parentComponent_; - } - } - } + p = p->parentComponent_; + } + } + } } void Component::internalMouseWheel (const int intAmountX, const int intAmountY, const int64 time) { - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - const float wheelIncrementX = intAmountX * (1.0f / 256.0f); - const float wheelIncrementY = intAmountY * (1.0f / 256.0f); + const float wheelIncrementX = intAmountX * (1.0f / 256.0f); + const float wheelIncrementY = intAmountY * (1.0f / 256.0f); - int mx, my; - getMouseXYRelative (mx, my); + int mx, my; + getMouseXYRelative (mx, my); - const MouseEvent me (mx, my, - ModifierKeys::getCurrentModifiers(), - this, - Time (time), - mx, my, - Time (time), - 0, false); + const MouseEvent me (mx, my, + ModifierKeys::getCurrentModifiers(), + this, + Time (time), + mx, my, + Time (time), + 0, false); - if (isCurrentlyBlockedByAnotherModalComponent()) - { - // allow blocked mouse-events to go to global listeners.. - for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); + if (isCurrentlyBlockedByAnotherModalComponent()) + { + // allow blocked mouse-events to go to global listeners.. + for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, Desktop::getInstance().mouseListeners.size()); - } - } - else - { - mouseWheelMove (me, wheelIncrementX, wheelIncrementY); + i = jmin (i, Desktop::getInstance().mouseListeners.size()); + } + } + else + { + mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) - { - ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); + for (int i = Desktop::getInstance().mouseListeners.size(); --i >= 0;) + { + ((MouseListener*) Desktop::getInstance().mouseListeners[i])->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, Desktop::getInstance().mouseListeners.size()); - } + i = jmin (i, Desktop::getInstance().mouseListeners.size()); + } - if (mouseListeners_ != 0) - { - for (int i = mouseListeners_->size(); --i >= 0;) - { - ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); + if (mouseListeners_ != 0) + { + for (int i = mouseListeners_->size(); --i >= 0;) + { + ((MouseListener*) mouseListeners_->getUnchecked (i))->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, mouseListeners_->size()); - } - } + i = jmin (i, mouseListeners_->size()); + } + } - const Component* p = parentComponent_; + const Component* p = parentComponent_; - while (p != 0) - { - const ComponentDeletionWatcher parentDeletionChecker (p); + while (p != 0) + { + const ComponentDeletionWatcher parentDeletionChecker (p); - for (int i = p->numDeepMouseListeners; --i >= 0;) - { - ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); + for (int i = p->numDeepMouseListeners; --i >= 0;) + { + ((MouseListener*) (p->mouseListeners_->getUnchecked (i)))->mouseWheelMove (me, wheelIncrementX, wheelIncrementY); - if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted() || parentDeletionChecker.hasBeenDeleted()) + return; - i = jmin (i, p->numDeepMouseListeners); - } + i = jmin (i, p->numDeepMouseListeners); + } - p = p->parentComponent_; - } + p = p->parentComponent_; + } - sendFakeMouseMove(); - } + sendFakeMouseMove(); + } } void Component::sendFakeMouseMove() const { - ComponentPeer* const peer = getPeer(); + ComponentPeer* const peer = getPeer(); - if (peer != 0) - peer->sendFakeMouseMove(); + if (peer != 0) + peer->sendFakeMouseMove(); } void Component::broughtToFront() @@ -41722,135 +41412,135 @@ void Component::broughtToFront() void Component::internalBroughtToFront() { - if (isValidComponent()) - { - if (flags.hasHeavyweightPeerFlag) - Desktop::getInstance().componentBroughtToFront (this); + if (isValidComponent()) + { + if (flags.hasHeavyweightPeerFlag) + Desktop::getInstance().componentBroughtToFront (this); - const ComponentDeletionWatcher deletionChecker (this); - broughtToFront(); + const ComponentDeletionWatcher deletionChecker (this); + broughtToFront(); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - if (componentListeners_ != 0) - { - for (int i = componentListeners_->size(); --i >= 0;) - { - ((ComponentListener*) componentListeners_->getUnchecked (i)) - ->componentBroughtToFront (*this); + if (componentListeners_ != 0) + { + for (int i = componentListeners_->size(); --i >= 0;) + { + ((ComponentListener*) componentListeners_->getUnchecked (i)) + ->componentBroughtToFront (*this); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, componentListeners_->size()); - } - } + i = jmin (i, componentListeners_->size()); + } + } - // when brought to the front and there's a modal component blocking this one, - // we need to bring the modal one to the front instead.. + // when brought to the front and there's a modal component blocking this one, + // we need to bring the modal one to the front instead.. - Component* const cm = getCurrentlyModalComponent(); + Component* const cm = getCurrentlyModalComponent(); - if (cm != 0 && cm->getTopLevelComponent() != getTopLevelComponent()) - bringModalComponentToFront(); - } + if (cm != 0 && cm->getTopLevelComponent() != getTopLevelComponent()) + bringModalComponentToFront(); + } } void Component::focusGained (FocusChangeType) { - // base class does nothing + // base class does nothing } void Component::internalFocusGain (const FocusChangeType cause) { - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - focusGained (cause); + focusGained (cause); - if (! deletionChecker.hasBeenDeleted()) - internalChildFocusChange (cause); + if (! deletionChecker.hasBeenDeleted()) + internalChildFocusChange (cause); } void Component::focusLost (FocusChangeType) { - // base class does nothing + // base class does nothing } void Component::internalFocusLoss (const FocusChangeType cause) { - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - focusLost (focusChangedDirectly); + focusLost (focusChangedDirectly); - if (! deletionChecker.hasBeenDeleted()) - internalChildFocusChange (cause); + if (! deletionChecker.hasBeenDeleted()) + internalChildFocusChange (cause); } void Component::focusOfChildComponentChanged (FocusChangeType /*cause*/) { - // base class does nothing + // base class does nothing } void Component::internalChildFocusChange (FocusChangeType cause) { - const bool childIsNowFocused = hasKeyboardFocus (true); + const bool childIsNowFocused = hasKeyboardFocus (true); - if (flags.childCompFocusedFlag != childIsNowFocused) - { - flags.childCompFocusedFlag = childIsNowFocused; + if (flags.childCompFocusedFlag != childIsNowFocused) + { + flags.childCompFocusedFlag = childIsNowFocused; - const ComponentDeletionWatcher deletionChecker (this); - focusOfChildComponentChanged (cause); + const ComponentDeletionWatcher deletionChecker (this); + focusOfChildComponentChanged (cause); - if (deletionChecker.hasBeenDeleted()) - return; - } + if (deletionChecker.hasBeenDeleted()) + return; + } - if (parentComponent_ != 0) - parentComponent_->internalChildFocusChange (cause); + if (parentComponent_ != 0) + parentComponent_->internalChildFocusChange (cause); } bool Component::isEnabled() const throw() { - return (! flags.isDisabledFlag) - && (parentComponent_ == 0 || parentComponent_->isEnabled()); + return (! flags.isDisabledFlag) + && (parentComponent_ == 0 || parentComponent_->isEnabled()); } void Component::setEnabled (const bool shouldBeEnabled) { - if (flags.isDisabledFlag == shouldBeEnabled) - { - flags.isDisabledFlag = ! shouldBeEnabled; + if (flags.isDisabledFlag == shouldBeEnabled) + { + flags.isDisabledFlag = ! shouldBeEnabled; - // if any parent components are disabled, setting our flag won't make a difference, - // so no need to send a change message - if (parentComponent_ == 0 || parentComponent_->isEnabled()) - sendEnablementChangeMessage(); - } + // if any parent components are disabled, setting our flag won't make a difference, + // so no need to send a change message + if (parentComponent_ == 0 || parentComponent_->isEnabled()) + sendEnablementChangeMessage(); + } } void Component::sendEnablementChangeMessage() { - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - enablementChanged(); + enablementChanged(); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - for (int i = getNumChildComponents(); --i >= 0;) - { - Component* const c = getChildComponent (i); + for (int i = getNumChildComponents(); --i >= 0;) + { + Component* const c = getChildComponent (i); - if (c != 0) - { - c->sendEnablementChangeMessage(); + if (c != 0) + { + c->sendEnablementChangeMessage(); - if (deletionChecker.hasBeenDeleted()) - return; - } - } + if (deletionChecker.hasBeenDeleted()) + return; + } + } } void Component::enablementChanged() @@ -41859,465 +41549,465 @@ void Component::enablementChanged() void Component::setWantsKeyboardFocus (const bool wantsFocus) throw() { - flags.wantsFocusFlag = wantsFocus; + flags.wantsFocusFlag = wantsFocus; } void Component::setMouseClickGrabsKeyboardFocus (const bool shouldGrabFocus) { - flags.dontFocusOnMouseClickFlag = ! shouldGrabFocus; + flags.dontFocusOnMouseClickFlag = ! shouldGrabFocus; } bool Component::getMouseClickGrabsKeyboardFocus() const throw() { - return ! flags.dontFocusOnMouseClickFlag; + return ! flags.dontFocusOnMouseClickFlag; } bool Component::getWantsKeyboardFocus() const throw() { - return flags.wantsFocusFlag && ! flags.isDisabledFlag; + return flags.wantsFocusFlag && ! flags.isDisabledFlag; } void Component::setFocusContainer (const bool shouldBeFocusContainer) throw() { - flags.isFocusContainerFlag = shouldBeFocusContainer; + flags.isFocusContainerFlag = shouldBeFocusContainer; } bool Component::isFocusContainer() const throw() { - return flags.isFocusContainerFlag; + return flags.isFocusContainerFlag; } int Component::getExplicitFocusOrder() const throw() { - return getComponentPropertyInt (T("_jexfo"), false, 0); + return getComponentPropertyInt (T("_jexfo"), false, 0); } void Component::setExplicitFocusOrder (const int newFocusOrderIndex) throw() { - setComponentProperty (T("_jexfo"), newFocusOrderIndex); + setComponentProperty (T("_jexfo"), newFocusOrderIndex); } KeyboardFocusTraverser* Component::createFocusTraverser() { - if (flags.isFocusContainerFlag || parentComponent_ == 0) - return new KeyboardFocusTraverser(); + if (flags.isFocusContainerFlag || parentComponent_ == 0) + return new KeyboardFocusTraverser(); - return parentComponent_->createFocusTraverser(); + return parentComponent_->createFocusTraverser(); } void Component::takeKeyboardFocus (const FocusChangeType cause) { - // give the focus to this component - if (currentlyFocusedComponent != this) - { - JUCE_TRY - { - // get the focus onto our desktop window - ComponentPeer* const peer = getPeer(); + // give the focus to this component + if (currentlyFocusedComponent != this) + { + JUCE_TRY + { + // get the focus onto our desktop window + ComponentPeer* const peer = getPeer(); - if (peer != 0) - { - const ComponentDeletionWatcher deletionChecker (this); + if (peer != 0) + { + const ComponentDeletionWatcher deletionChecker (this); - peer->grabFocus(); + peer->grabFocus(); - if (peer->isFocused() && currentlyFocusedComponent != this) - { - Component* const componentLosingFocus = currentlyFocusedComponent; + if (peer->isFocused() && currentlyFocusedComponent != this) + { + Component* const componentLosingFocus = currentlyFocusedComponent; - currentlyFocusedComponent = this; + currentlyFocusedComponent = this; - Desktop::getInstance().triggerFocusCallback(); + Desktop::getInstance().triggerFocusCallback(); - // call this after setting currentlyFocusedComponent so that the one that's - // losing it has a chance to see where focus is going - if (componentLosingFocus->isValidComponent()) - componentLosingFocus->internalFocusLoss (cause); + // call this after setting currentlyFocusedComponent so that the one that's + // losing it has a chance to see where focus is going + if (componentLosingFocus->isValidComponent()) + componentLosingFocus->internalFocusLoss (cause); - if (currentlyFocusedComponent == this) - { - focusGained (cause); + if (currentlyFocusedComponent == this) + { + focusGained (cause); - if (! deletionChecker.hasBeenDeleted()) - internalChildFocusChange (cause); - } - } - } - } + if (! deletionChecker.hasBeenDeleted()) + internalChildFocusChange (cause); + } + } + } + } #if JUCE_CATCH_UNHANDLED_EXCEPTIONS - catch (const std::exception& e) - { - currentlyFocusedComponent = 0; - Desktop::getInstance().triggerFocusCallback(); - JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); - } - catch (...) - { - currentlyFocusedComponent = 0; - Desktop::getInstance().triggerFocusCallback(); - JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); - } + catch (const std::exception& e) + { + currentlyFocusedComponent = 0; + Desktop::getInstance().triggerFocusCallback(); + JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); + } + catch (...) + { + currentlyFocusedComponent = 0; + Desktop::getInstance().triggerFocusCallback(); + JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); + } #endif - } + } } void Component::grabFocusInternal (const FocusChangeType cause, const bool canTryParent) { - if (isShowing()) - { - if (flags.wantsFocusFlag && (isEnabled() || parentComponent_ == 0)) - { - takeKeyboardFocus (cause); - } - else - { - if (isParentOf (currentlyFocusedComponent) - && currentlyFocusedComponent->isShowing()) - { - // do nothing if the focused component is actually a child of ours.. - } - else - { - // find the default child component.. - ScopedPointer traverser (createFocusTraverser()); + if (isShowing()) + { + if (flags.wantsFocusFlag && (isEnabled() || parentComponent_ == 0)) + { + takeKeyboardFocus (cause); + } + else + { + if (isParentOf (currentlyFocusedComponent) + && currentlyFocusedComponent->isShowing()) + { + // do nothing if the focused component is actually a child of ours.. + } + else + { + // find the default child component.. + ScopedPointer traverser (createFocusTraverser()); - if (traverser != 0) - { - Component* const defaultComp = traverser->getDefaultComponent (this); - traverser = 0; + if (traverser != 0) + { + Component* const defaultComp = traverser->getDefaultComponent (this); + traverser = 0; - if (defaultComp != 0) - { - defaultComp->grabFocusInternal (cause, false); - return; - } - } + if (defaultComp != 0) + { + defaultComp->grabFocusInternal (cause, false); + return; + } + } - if (canTryParent && parentComponent_ != 0) - { - // if no children want it and we're allowed to try our parent comp, - // then pass up to parent, which will try our siblings. - parentComponent_->grabFocusInternal (cause, true); - } - } - } - } + if (canTryParent && parentComponent_ != 0) + { + // if no children want it and we're allowed to try our parent comp, + // then pass up to parent, which will try our siblings. + parentComponent_->grabFocusInternal (cause, true); + } + } + } + } } void Component::grabKeyboardFocus() { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - grabFocusInternal (focusChangedDirectly); + grabFocusInternal (focusChangedDirectly); } void Component::moveKeyboardFocusToSibling (const bool moveToNext) { - // if component methods are being called from threads other than the message - // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - checkMessageManagerIsLocked + // if component methods are being called from threads other than the message + // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. + checkMessageManagerIsLocked - if (parentComponent_ != 0) - { - ScopedPointer traverser (createFocusTraverser()); + if (parentComponent_ != 0) + { + ScopedPointer traverser (createFocusTraverser()); - if (traverser != 0) - { - Component* const nextComp = moveToNext ? traverser->getNextComponent (this) - : traverser->getPreviousComponent (this); - traverser = 0; + if (traverser != 0) + { + Component* const nextComp = moveToNext ? traverser->getNextComponent (this) + : traverser->getPreviousComponent (this); + traverser = 0; - if (nextComp != 0) - { - if (nextComp->isCurrentlyBlockedByAnotherModalComponent()) - { - const ComponentDeletionWatcher deletionChecker (nextComp); - internalModalInputAttempt(); + if (nextComp != 0) + { + if (nextComp->isCurrentlyBlockedByAnotherModalComponent()) + { + const ComponentDeletionWatcher deletionChecker (nextComp); + internalModalInputAttempt(); - if (deletionChecker.hasBeenDeleted() - || nextComp->isCurrentlyBlockedByAnotherModalComponent()) - return; - } + if (deletionChecker.hasBeenDeleted() + || nextComp->isCurrentlyBlockedByAnotherModalComponent()) + return; + } - nextComp->grabFocusInternal (focusChangedByTabKey); - return; - } - } + nextComp->grabFocusInternal (focusChangedByTabKey); + return; + } + } - parentComponent_->moveKeyboardFocusToSibling (moveToNext); - } + parentComponent_->moveKeyboardFocusToSibling (moveToNext); + } } bool Component::hasKeyboardFocus (const bool trueIfChildIsFocused) const throw() { - return (currentlyFocusedComponent == this) - || (trueIfChildIsFocused && isParentOf (currentlyFocusedComponent)); + return (currentlyFocusedComponent == this) + || (trueIfChildIsFocused && isParentOf (currentlyFocusedComponent)); } Component* JUCE_CALLTYPE Component::getCurrentlyFocusedComponent() throw() { - return currentlyFocusedComponent; + return currentlyFocusedComponent; } void Component::giveAwayFocus() { - // use a copy so we can clear the value before the call - Component* const componentLosingFocus = currentlyFocusedComponent; - currentlyFocusedComponent = 0; - Desktop::getInstance().triggerFocusCallback(); + // use a copy so we can clear the value before the call + Component* const componentLosingFocus = currentlyFocusedComponent; + currentlyFocusedComponent = 0; + Desktop::getInstance().triggerFocusCallback(); - if (componentLosingFocus->isValidComponent()) - componentLosingFocus->internalFocusLoss (focusChangedDirectly); + if (componentLosingFocus->isValidComponent()) + componentLosingFocus->internalFocusLoss (focusChangedDirectly); } bool Component::isMouseOver() const throw() { - return flags.mouseOverFlag; + return flags.mouseOverFlag; } bool Component::isMouseButtonDown() const throw() { - return flags.draggingFlag; + return flags.draggingFlag; } bool Component::isMouseOverOrDragging() const throw() { - return flags.mouseOverFlag || flags.draggingFlag; + return flags.mouseOverFlag || flags.draggingFlag; } bool JUCE_CALLTYPE Component::isMouseButtonDownAnywhere() throw() { - return ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown(); + return ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown(); } void Component::getMouseXYRelative (int& mx, int& my) const throw() { - Desktop::getMousePosition (mx, my); - globalPositionToRelative (mx, my); + Desktop::getMousePosition (mx, my); + globalPositionToRelative (mx, my); - mx += unboundedMouseOffsetX; - my += unboundedMouseOffsetY; + mx += unboundedMouseOffsetX; + my += unboundedMouseOffsetY; } void Component::enableUnboundedMouseMovement (bool enable, - bool keepCursorVisibleUntilOffscreen) throw() + bool keepCursorVisibleUntilOffscreen) throw() { - enable = enable && isMouseButtonDown(); - isCursorVisibleUntilOffscreen = keepCursorVisibleUntilOffscreen; + enable = enable && isMouseButtonDown(); + isCursorVisibleUntilOffscreen = keepCursorVisibleUntilOffscreen; - if (enable != isUnboundedMouseModeOn) - { - if ((! enable) && ((! isCursorVisibleUntilOffscreen) - || unboundedMouseOffsetX != 0 - || unboundedMouseOffsetY != 0)) - { - // when released, return the mouse to within the component's bounds + if (enable != isUnboundedMouseModeOn) + { + if ((! enable) && ((! isCursorVisibleUntilOffscreen) + || unboundedMouseOffsetX != 0 + || unboundedMouseOffsetY != 0)) + { + // when released, return the mouse to within the component's bounds - int mx, my; - getMouseXYRelative (mx, my); + int mx, my; + getMouseXYRelative (mx, my); - mx = jlimit (0, getWidth(), mx); - my = jlimit (0, getHeight(), my); + mx = jlimit (0, getWidth(), mx); + my = jlimit (0, getHeight(), my); - relativePositionToGlobal (mx, my); + relativePositionToGlobal (mx, my); - Desktop::setMousePosition (mx, my); - } + Desktop::setMousePosition (mx, my); + } - isUnboundedMouseModeOn = enable; - unboundedMouseOffsetX = 0; - unboundedMouseOffsetY = 0; + isUnboundedMouseModeOn = enable; + unboundedMouseOffsetX = 0; + unboundedMouseOffsetY = 0; - internalUpdateMouseCursor (true); - } + internalUpdateMouseCursor (true); + } } Component* JUCE_CALLTYPE Component::getComponentUnderMouse() throw() { - return componentUnderMouse; + return componentUnderMouse; } const Rectangle Component::getParentMonitorArea() const throw() { - int centreX = getWidth() / 2; - int centreY = getHeight() / 2; - relativePositionToGlobal (centreX, centreY); + int centreX = getWidth() / 2; + int centreY = getHeight() / 2; + relativePositionToGlobal (centreX, centreY); - return Desktop::getInstance().getMonitorAreaContaining (centreX, centreY); + return Desktop::getInstance().getMonitorAreaContaining (centreX, centreY); } void Component::addKeyListener (KeyListener* const newListener) throw() { - if (keyListeners_ == 0) - keyListeners_ = new VoidArray (4); + if (keyListeners_ == 0) + keyListeners_ = new VoidArray(); - keyListeners_->addIfNotAlreadyThere (newListener); + keyListeners_->addIfNotAlreadyThere (newListener); } void Component::removeKeyListener (KeyListener* const listenerToRemove) throw() { - if (keyListeners_ != 0) - keyListeners_->removeValue (listenerToRemove); + if (keyListeners_ != 0) + keyListeners_->removeValue (listenerToRemove); } bool Component::keyPressed (const KeyPress&) { - return false; + return false; } bool Component::keyStateChanged (const bool /*isKeyDown*/) { - return false; + return false; } void Component::modifierKeysChanged (const ModifierKeys& modifiers) { - if (parentComponent_ != 0) - parentComponent_->modifierKeysChanged (modifiers); + if (parentComponent_ != 0) + parentComponent_->modifierKeysChanged (modifiers); } void Component::internalModifierKeysChanged() { - sendFakeMouseMove(); + sendFakeMouseMove(); - modifierKeysChanged (ModifierKeys::getCurrentModifiers()); + modifierKeysChanged (ModifierKeys::getCurrentModifiers()); } ComponentPeer* Component::getPeer() const throw() { - if (flags.hasHeavyweightPeerFlag) - return ComponentPeer::getPeerFor (this); - else if (parentComponent_ != 0) - return parentComponent_->getPeer(); - else - return 0; + if (flags.hasHeavyweightPeerFlag) + return ComponentPeer::getPeerFor (this); + else if (parentComponent_ != 0) + return parentComponent_->getPeer(); + else + return 0; } const String Component::getComponentProperty (const String& keyName, - const bool useParentComponentIfNotFound, - const String& defaultReturnValue) const throw() + const bool useParentComponentIfNotFound, + const String& defaultReturnValue) const throw() { - if (propertySet_ != 0 && ((! useParentComponentIfNotFound) || propertySet_->containsKey (keyName))) - return propertySet_->getValue (keyName, defaultReturnValue); + if (propertySet_ != 0 && ((! useParentComponentIfNotFound) || propertySet_->containsKey (keyName))) + return propertySet_->getValue (keyName, defaultReturnValue); - if (useParentComponentIfNotFound && (parentComponent_ != 0)) - return parentComponent_->getComponentProperty (keyName, true, defaultReturnValue); + if (useParentComponentIfNotFound && (parentComponent_ != 0)) + return parentComponent_->getComponentProperty (keyName, true, defaultReturnValue); - return defaultReturnValue; + return defaultReturnValue; } int Component::getComponentPropertyInt (const String& keyName, - const bool useParentComponentIfNotFound, - const int defaultReturnValue) const throw() + const bool useParentComponentIfNotFound, + const int defaultReturnValue) const throw() { - if (propertySet_ != 0 && ((! useParentComponentIfNotFound) || propertySet_->containsKey (keyName))) - return propertySet_->getIntValue (keyName, defaultReturnValue); + if (propertySet_ != 0 && ((! useParentComponentIfNotFound) || propertySet_->containsKey (keyName))) + return propertySet_->getIntValue (keyName, defaultReturnValue); - if (useParentComponentIfNotFound && (parentComponent_ != 0)) - return parentComponent_->getComponentPropertyInt (keyName, true, defaultReturnValue); + if (useParentComponentIfNotFound && (parentComponent_ != 0)) + return parentComponent_->getComponentPropertyInt (keyName, true, defaultReturnValue); - return defaultReturnValue; + return defaultReturnValue; } double Component::getComponentPropertyDouble (const String& keyName, - const bool useParentComponentIfNotFound, - const double defaultReturnValue) const throw() + const bool useParentComponentIfNotFound, + const double defaultReturnValue) const throw() { - if (propertySet_ != 0 && ((! useParentComponentIfNotFound) || propertySet_->containsKey (keyName))) - return propertySet_->getDoubleValue (keyName, defaultReturnValue); + if (propertySet_ != 0 && ((! useParentComponentIfNotFound) || propertySet_->containsKey (keyName))) + return propertySet_->getDoubleValue (keyName, defaultReturnValue); - if (useParentComponentIfNotFound && (parentComponent_ != 0)) - return parentComponent_->getComponentPropertyDouble (keyName, true, defaultReturnValue); + if (useParentComponentIfNotFound && (parentComponent_ != 0)) + return parentComponent_->getComponentPropertyDouble (keyName, true, defaultReturnValue); - return defaultReturnValue; + return defaultReturnValue; } bool Component::getComponentPropertyBool (const String& keyName, - const bool useParentComponentIfNotFound, - const bool defaultReturnValue) const throw() + const bool useParentComponentIfNotFound, + const bool defaultReturnValue) const throw() { - if (propertySet_ != 0 && ((! useParentComponentIfNotFound) || propertySet_->containsKey (keyName))) - return propertySet_->getBoolValue (keyName, defaultReturnValue); + if (propertySet_ != 0 && ((! useParentComponentIfNotFound) || propertySet_->containsKey (keyName))) + return propertySet_->getBoolValue (keyName, defaultReturnValue); - if (useParentComponentIfNotFound && (parentComponent_ != 0)) - return parentComponent_->getComponentPropertyBool (keyName, true, defaultReturnValue); + if (useParentComponentIfNotFound && (parentComponent_ != 0)) + return parentComponent_->getComponentPropertyBool (keyName, true, defaultReturnValue); - return defaultReturnValue; + return defaultReturnValue; } const Colour Component::getComponentPropertyColour (const String& keyName, - const bool useParentComponentIfNotFound, - const Colour& defaultReturnValue) const throw() + const bool useParentComponentIfNotFound, + const Colour& defaultReturnValue) const throw() { - return Colour ((uint32) getComponentPropertyInt (keyName, - useParentComponentIfNotFound, - defaultReturnValue.getARGB())); + return Colour ((uint32) getComponentPropertyInt (keyName, + useParentComponentIfNotFound, + defaultReturnValue.getARGB())); } void Component::setComponentProperty (const String& keyName, const String& value) throw() { - if (propertySet_ == 0) - propertySet_ = new PropertySet(); + if (propertySet_ == 0) + propertySet_ = new PropertySet(); - propertySet_->setValue (keyName, value); + propertySet_->setValue (keyName, value); } void Component::setComponentProperty (const String& keyName, const int value) throw() { - if (propertySet_ == 0) - propertySet_ = new PropertySet(); + if (propertySet_ == 0) + propertySet_ = new PropertySet(); - propertySet_->setValue (keyName, value); + propertySet_->setValue (keyName, value); } void Component::setComponentProperty (const String& keyName, const double value) throw() { - if (propertySet_ == 0) - propertySet_ = new PropertySet(); + if (propertySet_ == 0) + propertySet_ = new PropertySet(); - propertySet_->setValue (keyName, value); + propertySet_->setValue (keyName, value); } void Component::setComponentProperty (const String& keyName, const bool value) throw() { - if (propertySet_ == 0) - propertySet_ = new PropertySet(); + if (propertySet_ == 0) + propertySet_ = new PropertySet(); - propertySet_->setValue (keyName, value); + propertySet_->setValue (keyName, value); } void Component::setComponentProperty (const String& keyName, const Colour& colour) throw() { - setComponentProperty (keyName, (int) colour.getARGB()); + setComponentProperty (keyName, (int) colour.getARGB()); } void Component::removeComponentProperty (const String& keyName) throw() { - if (propertySet_ != 0) - propertySet_->removeValue (keyName); + if (propertySet_ != 0) + propertySet_->removeValue (keyName); } ComponentDeletionWatcher::ComponentDeletionWatcher (const Component* const componentToWatch_) throw() - : componentToWatch (componentToWatch_), - componentUID (componentToWatch_->getComponentUID()) + : componentToWatch (componentToWatch_), + componentUID (componentToWatch_->getComponentUID()) { - // not possible to check on an already-deleted object.. - jassert (componentToWatch_->isValidComponent()); + // not possible to check on an already-deleted object.. + jassert (componentToWatch_->isValidComponent()); } ComponentDeletionWatcher::~ComponentDeletionWatcher() throw() {} bool ComponentDeletionWatcher::hasBeenDeleted() const throw() { - return ! (componentToWatch->isValidComponent() - && componentToWatch->getComponentUID() == componentUID); + return ! (componentToWatch->isValidComponent() + && componentToWatch->getComponentUID() == componentUID); } const Component* ComponentDeletionWatcher::getComponent() const throw() { - return hasBeenDeleted() ? 0 : componentToWatch; + return hasBeenDeleted() ? 0 : componentToWatch; } END_JUCE_NAMESPACE @@ -42359,161 +42049,157 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE extern void juce_updateMultiMonitorInfo (Array & monitorCoords, - const bool clipToWorkArea) throw(); + const bool clipToWorkArea); static Desktop* juce_desktopInstance = 0; Desktop::Desktop() throw() - : mouseListeners (2), - desktopComponents (4), - monitorCoordsClipped (2), - monitorCoordsUnclipped (2), - lastMouseX (0), - lastMouseY (0), - kioskModeComponent (0) + : lastMouseX (0), + lastMouseY (0), + kioskModeComponent (0) { - refreshMonitorSizes(); + refreshMonitorSizes(); } Desktop::~Desktop() throw() { - jassert (juce_desktopInstance == this); - juce_desktopInstance = 0; + jassert (juce_desktopInstance == this); + juce_desktopInstance = 0; - // doh! If you don't delete all your windows before exiting, you're going to - // be leaking memory! - jassert (desktopComponents.size() == 0); + // doh! If you don't delete all your windows before exiting, you're going to + // be leaking memory! + jassert (desktopComponents.size() == 0); } Desktop& JUCE_CALLTYPE Desktop::getInstance() throw() { - if (juce_desktopInstance == 0) - juce_desktopInstance = new Desktop(); + if (juce_desktopInstance == 0) + juce_desktopInstance = new Desktop(); - return *juce_desktopInstance; + return *juce_desktopInstance; } void Desktop::refreshMonitorSizes() throw() { - const Array oldClipped (monitorCoordsClipped); - const Array oldUnclipped (monitorCoordsUnclipped); + const Array oldClipped (monitorCoordsClipped); + const Array oldUnclipped (monitorCoordsUnclipped); - monitorCoordsClipped.clear(); - monitorCoordsUnclipped.clear(); - juce_updateMultiMonitorInfo (monitorCoordsClipped, true); - juce_updateMultiMonitorInfo (monitorCoordsUnclipped, false); - jassert (monitorCoordsClipped.size() > 0 - && monitorCoordsClipped.size() == monitorCoordsUnclipped.size()); + monitorCoordsClipped.clear(); + monitorCoordsUnclipped.clear(); + juce_updateMultiMonitorInfo (monitorCoordsClipped, true); + juce_updateMultiMonitorInfo (monitorCoordsUnclipped, false); + jassert (monitorCoordsClipped.size() > 0 + && monitorCoordsClipped.size() == monitorCoordsUnclipped.size()); - if (oldClipped != monitorCoordsClipped - || oldUnclipped != monitorCoordsUnclipped) - { - for (int i = ComponentPeer::getNumPeers(); --i >= 0;) - { - ComponentPeer* const p = ComponentPeer::getPeer (i); - if (p != 0) - p->handleScreenSizeChange(); - } - } + if (oldClipped != monitorCoordsClipped + || oldUnclipped != monitorCoordsUnclipped) + { + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) + { + ComponentPeer* const p = ComponentPeer::getPeer (i); + if (p != 0) + p->handleScreenSizeChange(); + } + } } int Desktop::getNumDisplayMonitors() const throw() { - return monitorCoordsClipped.size(); + return monitorCoordsClipped.size(); } const Rectangle Desktop::getDisplayMonitorCoordinates (const int index, const bool clippedToWorkArea) const throw() { - return clippedToWorkArea ? monitorCoordsClipped [index] - : monitorCoordsUnclipped [index]; + return clippedToWorkArea ? monitorCoordsClipped [index] + : monitorCoordsUnclipped [index]; } const RectangleList Desktop::getAllMonitorDisplayAreas (const bool clippedToWorkArea) const throw() { - RectangleList rl; + RectangleList rl; - for (int i = 0; i < getNumDisplayMonitors(); ++i) - rl.addWithoutMerging (getDisplayMonitorCoordinates (i, clippedToWorkArea)); + for (int i = 0; i < getNumDisplayMonitors(); ++i) + rl.addWithoutMerging (getDisplayMonitorCoordinates (i, clippedToWorkArea)); - return rl; + return rl; } const Rectangle Desktop::getMainMonitorArea (const bool clippedToWorkArea) const throw() { - return getDisplayMonitorCoordinates (0, clippedToWorkArea); + return getDisplayMonitorCoordinates (0, clippedToWorkArea); } const Rectangle Desktop::getMonitorAreaContaining (int cx, int cy, const bool clippedToWorkArea) const throw() { - Rectangle best (getMainMonitorArea (clippedToWorkArea)); - double bestDistance = 1.0e10; + Rectangle best (getMainMonitorArea (clippedToWorkArea)); + double bestDistance = 1.0e10; - for (int i = getNumDisplayMonitors(); --i >= 0;) - { - const Rectangle rect (getDisplayMonitorCoordinates (i, clippedToWorkArea)); + for (int i = getNumDisplayMonitors(); --i >= 0;) + { + const Rectangle rect (getDisplayMonitorCoordinates (i, clippedToWorkArea)); - if (rect.contains (cx, cy)) - return rect; + if (rect.contains (cx, cy)) + return rect; - const double distance = juce_hypot ((double) (rect.getCentreX() - cx), - (double) (rect.getCentreY() - cy)); + const double distance = juce_hypot ((double) (rect.getCentreX() - cx), + (double) (rect.getCentreY() - cy)); - if (distance < bestDistance) - { - bestDistance = distance; - best = rect; - } - } + if (distance < bestDistance) + { + bestDistance = distance; + best = rect; + } + } - return best; + return best; } int Desktop::getNumComponents() const throw() { - return desktopComponents.size(); + return desktopComponents.size(); } Component* Desktop::getComponent (const int index) const throw() { - return (Component*) desktopComponents [index]; + return (Component*) desktopComponents [index]; } Component* Desktop::findComponentAt (const int screenX, - const int screenY) const + const int screenY) const { - for (int i = desktopComponents.size(); --i >= 0;) - { - Component* const c = (Component*) desktopComponents.getUnchecked(i); + for (int i = desktopComponents.size(); --i >= 0;) + { + Component* const c = (Component*) desktopComponents.getUnchecked(i); - int x = screenX, y = screenY; - c->globalPositionToRelative (x, y); + int x = screenX, y = screenY; + c->globalPositionToRelative (x, y); - if (c->contains (x, y)) - return c->getComponentAt (x, y); - } + if (c->contains (x, y)) + return c->getComponentAt (x, y); + } - return 0; + return 0; } void Desktop::addDesktopComponent (Component* const c) throw() { - jassert (c != 0); - jassert (! desktopComponents.contains (c)); - desktopComponents.addIfNotAlreadyThere (c); + jassert (c != 0); + jassert (! desktopComponents.contains (c)); + desktopComponents.addIfNotAlreadyThere (c); } void Desktop::removeDesktopComponent (Component* const c) throw() { - desktopComponents.removeValue (c); + desktopComponents.removeValue (c); } void Desktop::componentBroughtToFront (Component* const c) throw() { - const int index = desktopComponents.indexOf (c); - jassert (index >= 0); + const int index = desktopComponents.indexOf (c); + jassert (index >= 0); - if (index >= 0) - desktopComponents.move (index, -1); + if (index >= 0) + desktopComponents.move (index, -1); } // from Component.cpp @@ -42523,153 +42209,153 @@ extern int juce_MouseClickCounter; void Desktop::getLastMouseDownPosition (int& x, int& y) throw() { - x = juce_recentMouseDownX [0]; - y = juce_recentMouseDownY [0]; + x = juce_recentMouseDownX [0]; + y = juce_recentMouseDownY [0]; } int Desktop::getMouseButtonClickCounter() throw() { - return juce_MouseClickCounter; + return juce_MouseClickCounter; } void Desktop::addGlobalMouseListener (MouseListener* const listener) throw() { - jassert (listener != 0); + jassert (listener != 0); - if (listener != 0) - { - mouseListeners.add (listener); - resetTimer(); - } + if (listener != 0) + { + mouseListeners.add (listener); + resetTimer(); + } } void Desktop::removeGlobalMouseListener (MouseListener* const listener) throw() { - mouseListeners.removeValue (listener); - resetTimer(); + mouseListeners.removeValue (listener); + resetTimer(); } void Desktop::addFocusChangeListener (FocusChangeListener* const listener) throw() { - jassert (listener != 0); + jassert (listener != 0); - if (listener != 0) - focusListeners.add (listener); + if (listener != 0) + focusListeners.add (listener); } void Desktop::removeFocusChangeListener (FocusChangeListener* const listener) throw() { - focusListeners.removeValue (listener); + focusListeners.removeValue (listener); } void Desktop::triggerFocusCallback() throw() { - triggerAsyncUpdate(); + triggerAsyncUpdate(); } void Desktop::handleAsyncUpdate() { - for (int i = focusListeners.size(); --i >= 0;) - { - ((FocusChangeListener*) focusListeners.getUnchecked (i))->globalFocusChanged (Component::getCurrentlyFocusedComponent()); - i = jmin (i, focusListeners.size()); - } + for (int i = focusListeners.size(); --i >= 0;) + { + ((FocusChangeListener*) focusListeners.getUnchecked (i))->globalFocusChanged (Component::getCurrentlyFocusedComponent()); + i = jmin (i, focusListeners.size()); + } } void Desktop::timerCallback() { - int x, y; - getMousePosition (x, y); + int x, y; + getMousePosition (x, y); - if (lastMouseX != x || lastMouseY != y) - sendMouseMove(); + if (lastMouseX != x || lastMouseY != y) + sendMouseMove(); } void Desktop::sendMouseMove() { - if (mouseListeners.size() > 0) - { - startTimer (20); + if (mouseListeners.size() > 0) + { + startTimer (20); - int x, y; - getMousePosition (x, y); - lastMouseX = x; - lastMouseY = y; + int x, y; + getMousePosition (x, y); + lastMouseX = x; + lastMouseY = y; - Component* const target = findComponentAt (x, y); + Component* const target = findComponentAt (x, y); - if (target != 0) - { - target->globalPositionToRelative (x, y); + if (target != 0) + { + target->globalPositionToRelative (x, y); - ComponentDeletionWatcher deletionChecker (target); + ComponentDeletionWatcher deletionChecker (target); - const MouseEvent me (x, y, - ModifierKeys::getCurrentModifiers(), - target, - Time::getCurrentTime(), - x, y, - Time::getCurrentTime(), - 0, false); + const MouseEvent me (x, y, + ModifierKeys::getCurrentModifiers(), + target, + Time::getCurrentTime(), + x, y, + Time::getCurrentTime(), + 0, false); - for (int i = mouseListeners.size(); --i >= 0;) - { - if (ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown()) - ((MouseListener*) mouseListeners[i])->mouseDrag (me); - else - ((MouseListener*) mouseListeners[i])->mouseMove (me); + for (int i = mouseListeners.size(); --i >= 0;) + { + if (ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown()) + ((MouseListener*) mouseListeners[i])->mouseDrag (me); + else + ((MouseListener*) mouseListeners[i])->mouseMove (me); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - i = jmin (i, mouseListeners.size()); - } - } - } + i = jmin (i, mouseListeners.size()); + } + } + } } void Desktop::resetTimer() throw() { - if (mouseListeners.size() == 0) - stopTimer(); - else - startTimer (100); + if (mouseListeners.size() == 0) + stopTimer(); + else + startTimer (100); - getMousePosition (lastMouseX, lastMouseY); + getMousePosition (lastMouseX, lastMouseY); } extern void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool allowMenusAndBars); void Desktop::setKioskModeComponent (Component* componentToUse, const bool allowMenusAndBars) { - if (kioskModeComponent != componentToUse) - { - // agh! Don't delete a component without first stopping it being the kiosk comp - jassert (kioskModeComponent == 0 || kioskModeComponent->isValidComponent()); - // agh! Don't remove a component from the desktop if it's the kiosk comp! - jassert (kioskModeComponent == 0 || kioskModeComponent->isOnDesktop()); + if (kioskModeComponent != componentToUse) + { + // agh! Don't delete a component without first stopping it being the kiosk comp + jassert (kioskModeComponent == 0 || kioskModeComponent->isValidComponent()); + // agh! Don't remove a component from the desktop if it's the kiosk comp! + jassert (kioskModeComponent == 0 || kioskModeComponent->isOnDesktop()); - if (kioskModeComponent->isValidComponent()) - { - juce_setKioskComponent (kioskModeComponent, false, allowMenusAndBars); + if (kioskModeComponent->isValidComponent()) + { + juce_setKioskComponent (kioskModeComponent, false, allowMenusAndBars); - kioskModeComponent->setBounds (kioskComponentOriginalBounds); - } + kioskModeComponent->setBounds (kioskComponentOriginalBounds); + } - kioskModeComponent = componentToUse; + kioskModeComponent = componentToUse; - if (kioskModeComponent != 0) - { - jassert (kioskModeComponent->isValidComponent()); + if (kioskModeComponent != 0) + { + jassert (kioskModeComponent->isValidComponent()); - // Only components that are already on the desktop can be put into kiosk mode! - jassert (kioskModeComponent->isOnDesktop()); + // Only components that are already on the desktop can be put into kiosk mode! + jassert (kioskModeComponent->isOnDesktop()); - kioskComponentOriginalBounds = kioskModeComponent->getBounds(); + kioskComponentOriginalBounds = kioskModeComponent->getBounds(); - juce_setKioskComponent (kioskModeComponent, true, allowMenusAndBars); - } - } + juce_setKioskComponent (kioskModeComponent, true, allowMenusAndBars); + } + } } END_JUCE_NAMESPACE @@ -42680,20 +42366,20 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ArrowButton::ArrowButton (const String& name, - float arrowDirectionInRadians, - const Colour& arrowColour) + float arrowDirectionInRadians, + const Colour& arrowColour) : Button (name), - colour (arrowColour) + colour (arrowColour) { - path.lineTo (0.0f, 1.0f); - path.lineTo (1.0f, 0.5f); - path.closeSubPath(); + path.lineTo (0.0f, 1.0f); + path.lineTo (1.0f, 0.5f); + path.closeSubPath(); - path.applyTransform (AffineTransform::rotation (float_Pi * 2.0f * arrowDirectionInRadians, - 0.5f, 0.5f)); + path.applyTransform (AffineTransform::rotation (float_Pi * 2.0f * arrowDirectionInRadians, + 0.5f, 0.5f)); - setComponentEffect (&shadow); - buttonStateChanged(); + setComponentEffect (&shadow); + buttonStateChanged(); } ArrowButton::~ArrowButton() @@ -42701,24 +42387,24 @@ ArrowButton::~ArrowButton() } void ArrowButton::paintButton (Graphics& g, - bool /*isMouseOverButton*/, - bool /*isButtonDown*/) + bool /*isMouseOverButton*/, + bool /*isButtonDown*/) { - g.setColour (colour); + g.setColour (colour); - g.fillPath (path, path.getTransformToScaleToFit ((float) offset, - (float) offset, - (float) (getWidth() - 3), - (float) (getHeight() - 3), - false)); + g.fillPath (path, path.getTransformToScaleToFit ((float) offset, + (float) offset, + (float) (getWidth() - 3), + (float) (getHeight() - 3), + false)); } void ArrowButton::buttonStateChanged() { - offset = (isDown()) ? 1 : 0; + offset = (isDown()) ? 1 : 0; - shadow.setShadowProperties ((isDown()) ? 1.2f : 3.0f, - 0.3f, -1, 0); + shadow.setShadowProperties ((isDown()) ? 1.2f : 3.0f, + 0.3f, -1, 0); } END_JUCE_NAMESPACE @@ -42730,236 +42416,234 @@ BEGIN_JUCE_NAMESPACE Button::Button (const String& name) : Component (name), - shortcuts (2), - keySource (0), - text (name), - buttonListeners (2), - buttonPressTime (0), - lastTimeCallbackTime (0), - commandManagerToUse (0), - autoRepeatDelay (-1), - autoRepeatSpeed (0), - autoRepeatMinimumDelay (-1), - radioGroupId (0), - commandID (0), - connectedEdgeFlags (0), - buttonState (buttonNormal), - lastToggleState (false), - clickTogglesState (false), - needsToRelease (false), - needsRepainting (false), - isKeyDown (false), - triggerOnMouseDown (false), - generateTooltip (false) + keySource (0), + text (name), + buttonPressTime (0), + lastTimeCallbackTime (0), + commandManagerToUse (0), + autoRepeatDelay (-1), + autoRepeatSpeed (0), + autoRepeatMinimumDelay (-1), + radioGroupId (0), + commandID (0), + connectedEdgeFlags (0), + buttonState (buttonNormal), + lastToggleState (false), + clickTogglesState (false), + needsToRelease (false), + needsRepainting (false), + isKeyDown (false), + triggerOnMouseDown (false), + generateTooltip (false) { - setWantsKeyboardFocus (true); - isOn.addListener (this); + setWantsKeyboardFocus (true); + isOn.addListener (this); } Button::~Button() { - isOn.removeListener (this); + isOn.removeListener (this); - if (commandManagerToUse != 0) - commandManagerToUse->removeListener (this); + if (commandManagerToUse != 0) + commandManagerToUse->removeListener (this); - repeatTimer = 0; - clearShortcuts(); + repeatTimer = 0; + clearShortcuts(); } void Button::setButtonText (const String& newText) throw() { - if (text != newText) - { - text = newText; - repaint(); - } + if (text != newText) + { + text = newText; + repaint(); + } } void Button::setTooltip (const String& newTooltip) { - SettableTooltipClient::setTooltip (newTooltip); - generateTooltip = false; + SettableTooltipClient::setTooltip (newTooltip); + generateTooltip = false; } const String Button::getTooltip() { - if (generateTooltip && commandManagerToUse != 0 && commandID != 0) - { - String tt (commandManagerToUse->getDescriptionOfCommand (commandID)); + if (generateTooltip && commandManagerToUse != 0 && commandID != 0) + { + String tt (commandManagerToUse->getDescriptionOfCommand (commandID)); - Array keyPresses (commandManagerToUse->getKeyMappings()->getKeyPressesAssignedToCommand (commandID)); + Array keyPresses (commandManagerToUse->getKeyMappings()->getKeyPressesAssignedToCommand (commandID)); - for (int i = 0; i < keyPresses.size(); ++i) - { - const String key (keyPresses.getReference(i).getTextDescription()); + for (int i = 0; i < keyPresses.size(); ++i) + { + const String key (keyPresses.getReference(i).getTextDescription()); - tt << " ["; + tt << " ["; - if (key.length() == 1) - tt << TRANS("shortcut") << ": '" << key << "']"; - else - tt << key << ']'; - } + if (key.length() == 1) + tt << TRANS("shortcut") << ": '" << key << "']"; + else + tt << key << ']'; + } - return tt; - } + return tt; + } - return SettableTooltipClient::getTooltip(); + return SettableTooltipClient::getTooltip(); } void Button::setConnectedEdges (const int connectedEdgeFlags_) throw() { - if (connectedEdgeFlags != connectedEdgeFlags_) - { - connectedEdgeFlags = connectedEdgeFlags_; - repaint(); - } + if (connectedEdgeFlags != connectedEdgeFlags_) + { + connectedEdgeFlags = connectedEdgeFlags_; + repaint(); + } } void Button::setToggleState (const bool shouldBeOn, - const bool sendChangeNotification) + const bool sendChangeNotification) { - if (shouldBeOn != lastToggleState) - { - const ComponentDeletionWatcher deletionWatcher (this); + if (shouldBeOn != lastToggleState) + { + const ComponentDeletionWatcher deletionWatcher (this); - isOn = shouldBeOn; - lastToggleState = shouldBeOn; - repaint(); + isOn = shouldBeOn; + lastToggleState = shouldBeOn; + repaint(); - if (sendChangeNotification) - sendClickMessage (ModifierKeys()); + if (sendChangeNotification) + sendClickMessage (ModifierKeys()); - if ((! deletionWatcher.hasBeenDeleted()) && getToggleState()) - turnOffOtherButtonsInGroup (sendChangeNotification); - } + if ((! deletionWatcher.hasBeenDeleted()) && lastToggleState) + turnOffOtherButtonsInGroup (sendChangeNotification); + } } void Button::setClickingTogglesState (const bool shouldToggle) throw() { - clickTogglesState = shouldToggle; + clickTogglesState = shouldToggle; - // if you've got clickTogglesState turned on, you shouldn't also connect the button - // up to be a command invoker. Instead, your command handler must flip the state of whatever - // it is that this button represents, and the button will update its state to reflect this - // in the applicationCommandListChanged() method. - jassert (commandManagerToUse == 0 || ! clickTogglesState); + // if you've got clickTogglesState turned on, you shouldn't also connect the button + // up to be a command invoker. Instead, your command handler must flip the state of whatever + // it is that this button represents, and the button will update its state to reflect this + // in the applicationCommandListChanged() method. + jassert (commandManagerToUse == 0 || ! clickTogglesState); } bool Button::getClickingTogglesState() const throw() { - return clickTogglesState; + return clickTogglesState; } void Button::valueChanged (Value& value) { - if (value.refersToSameSourceAs (isOn)) - setToggleState (isOn.getValue(), true); + if (value.refersToSameSourceAs (isOn)) + setToggleState (isOn.getValue(), true); } void Button::setRadioGroupId (const int newGroupId) { - if (radioGroupId != newGroupId) - { - radioGroupId = newGroupId; + if (radioGroupId != newGroupId) + { + radioGroupId = newGroupId; - if (getToggleState()) - turnOffOtherButtonsInGroup (true); - } + if (lastToggleState) + turnOffOtherButtonsInGroup (true); + } } void Button::turnOffOtherButtonsInGroup (const bool sendChangeNotification) { - Component* const p = getParentComponent(); + Component* const p = getParentComponent(); - if (p != 0 && radioGroupId != 0) - { - const ComponentDeletionWatcher deletionWatcher (this); + if (p != 0 && radioGroupId != 0) + { + const ComponentDeletionWatcher deletionWatcher (this); - for (int i = p->getNumChildComponents(); --i >= 0;) - { - Component* const c = p->getChildComponent (i); + for (int i = p->getNumChildComponents(); --i >= 0;) + { + Component* const c = p->getChildComponent (i); - if (c != this) - { - Button* const b = dynamic_cast (c); + if (c != this) + { + Button* const b = dynamic_cast (c); - if (b != 0 && b->getRadioGroupId() == radioGroupId) - { - b->setToggleState (false, sendChangeNotification); + if (b != 0 && b->getRadioGroupId() == radioGroupId) + { + b->setToggleState (false, sendChangeNotification); - if (deletionWatcher.hasBeenDeleted()) - return; - } - } - } - } + if (deletionWatcher.hasBeenDeleted()) + return; + } + } + } + } } void Button::enablementChanged() { - updateState (0); - repaint(); + updateState (0); + repaint(); } Button::ButtonState Button::updateState (const MouseEvent* const e) throw() { - ButtonState state = buttonNormal; + ButtonState state = buttonNormal; - if (isEnabled() && isVisible() && ! isCurrentlyBlockedByAnotherModalComponent()) - { - int mx, my; + if (isEnabled() && isVisible() && ! isCurrentlyBlockedByAnotherModalComponent()) + { + int mx, my; - if (e == 0) - { - getMouseXYRelative (mx, my); - } - else - { - const MouseEvent e2 (e->getEventRelativeTo (this)); - mx = e2.x; - my = e2.y; - } + if (e == 0) + { + getMouseXYRelative (mx, my); + } + else + { + const MouseEvent e2 (e->getEventRelativeTo (this)); + mx = e2.x; + my = e2.y; + } - const bool over = reallyContains (mx, my, true); - const bool down = isMouseButtonDown(); + const bool over = reallyContains (mx, my, true); + const bool down = isMouseButtonDown(); - if ((down && (over || (triggerOnMouseDown && buttonState == buttonDown))) || isKeyDown) - state = buttonDown; - else if (over) - state = buttonOver; - } + if ((down && (over || (triggerOnMouseDown && buttonState == buttonDown))) || isKeyDown) + state = buttonDown; + else if (over) + state = buttonOver; + } - setState (state); - return state; + setState (state); + return state; } void Button::setState (const ButtonState newState) { - if (buttonState != newState) - { - buttonState = newState; - repaint(); + if (buttonState != newState) + { + buttonState = newState; + repaint(); - if (buttonState == buttonDown) - { - buttonPressTime = Time::getApproximateMillisecondCounter(); - lastTimeCallbackTime = buttonPressTime; - } + if (buttonState == buttonDown) + { + buttonPressTime = Time::getApproximateMillisecondCounter(); + lastTimeCallbackTime = buttonPressTime; + } - sendStateMessage(); - } + sendStateMessage(); + } } bool Button::isDown() const throw() { - return buttonState == buttonDown; + return buttonState == buttonDown; } bool Button::isOver() const throw() { - return buttonState != buttonNormal; + return buttonState != buttonNormal; } void Button::buttonStateChanged() @@ -42968,13 +42652,13 @@ void Button::buttonStateChanged() uint32 Button::getMillisecondsSinceButtonDown() const throw() { - const uint32 now = Time::getApproximateMillisecondCounter(); - return now > buttonPressTime ? now - buttonPressTime : 0; + const uint32 now = Time::getApproximateMillisecondCounter(); + return now > buttonPressTime ? now - buttonPressTime : 0; } void Button::setTriggeredOnMouseDown (const bool isTriggeredOnMouseDown) throw() { - triggerOnMouseDown = isTriggeredOnMouseDown; + triggerOnMouseDown = isTriggeredOnMouseDown; } void Button::clicked() @@ -42983,438 +42667,437 @@ void Button::clicked() void Button::clicked (const ModifierKeys& /*modifiers*/) { - clicked(); + clicked(); } static const int clickMessageId = 0x2f3f4f99; void Button::triggerClick() { - postCommandMessage (clickMessageId); + postCommandMessage (clickMessageId); } void Button::internalClickCallback (const ModifierKeys& modifiers) { - if (clickTogglesState) - setToggleState ((radioGroupId != 0) || ! getToggleState(), false); + if (clickTogglesState) + setToggleState ((radioGroupId != 0) || ! lastToggleState, false); - sendClickMessage (modifiers); + sendClickMessage (modifiers); } void Button::flashButtonState() throw() { - if (isEnabled()) - { - needsToRelease = true; - setState (buttonDown); - getRepeatTimer().startTimer (100); - } + if (isEnabled()) + { + needsToRelease = true; + setState (buttonDown); + getRepeatTimer().startTimer (100); + } } void Button::handleCommandMessage (int commandId) { - if (commandId == clickMessageId) - { - if (isEnabled()) - { - flashButtonState(); - internalClickCallback (ModifierKeys::getCurrentModifiers()); - } - } - else - { - Component::handleCommandMessage (commandId); - } + if (commandId == clickMessageId) + { + if (isEnabled()) + { + flashButtonState(); + internalClickCallback (ModifierKeys::getCurrentModifiers()); + } + } + else + { + Component::handleCommandMessage (commandId); + } } void Button::addButtonListener (ButtonListener* const newListener) throw() { - jassert (newListener != 0); - jassert (! buttonListeners.contains (newListener)); // trying to add a listener to the list twice! + jassert (newListener != 0); + jassert (! buttonListeners.contains (newListener)); // trying to add a listener to the list twice! - if (newListener != 0) - buttonListeners.add (newListener); + if (newListener != 0) + buttonListeners.add (newListener); } void Button::removeButtonListener (ButtonListener* const listener) throw() { - jassert (buttonListeners.contains (listener)); // trying to remove a listener that isn't on the list! + jassert (buttonListeners.contains (listener)); // trying to remove a listener that isn't on the list! - buttonListeners.removeValue (listener); + buttonListeners.removeValue (listener); } void Button::sendClickMessage (const ModifierKeys& modifiers) { - const ComponentDeletionWatcher cdw (this); + const ComponentDeletionWatcher cdw (this); - if (commandManagerToUse != 0 && commandID != 0) - { - ApplicationCommandTarget::InvocationInfo info (commandID); - info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromButton; - info.originatingComponent = this; + if (commandManagerToUse != 0 && commandID != 0) + { + ApplicationCommandTarget::InvocationInfo info (commandID); + info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromButton; + info.originatingComponent = this; - commandManagerToUse->invoke (info, true); - } + commandManagerToUse->invoke (info, true); + } - clicked (modifiers); + clicked (modifiers); - if (! cdw.hasBeenDeleted()) - { - for (int i = buttonListeners.size(); --i >= 0;) - { - ButtonListener* const bl = (ButtonListener*) buttonListeners[i]; + if (! cdw.hasBeenDeleted()) + { + for (int i = buttonListeners.size(); --i >= 0;) + { + ButtonListener* const bl = (ButtonListener*) buttonListeners[i]; - if (bl != 0) - { - bl->buttonClicked (this); + if (bl != 0) + { + bl->buttonClicked (this); - if (cdw.hasBeenDeleted()) - return; - } - } - } + if (cdw.hasBeenDeleted()) + return; + } + } + } } void Button::sendStateMessage() { - const ComponentDeletionWatcher cdw (this); + const ComponentDeletionWatcher cdw (this); - buttonStateChanged(); + buttonStateChanged(); - if (cdw.hasBeenDeleted()) - return; + if (cdw.hasBeenDeleted()) + return; - for (int i = buttonListeners.size(); --i >= 0;) - { - ButtonListener* const bl = (ButtonListener*) buttonListeners[i]; + for (int i = buttonListeners.size(); --i >= 0;) + { + ButtonListener* const bl = (ButtonListener*) buttonListeners[i]; - if (bl != 0) - { - bl->buttonStateChanged (this); + if (bl != 0) + { + bl->buttonStateChanged (this); - if (cdw.hasBeenDeleted()) - return; - } - } + if (cdw.hasBeenDeleted()) + return; + } + } } void Button::paint (Graphics& g) { - if (needsToRelease && isEnabled()) - { - needsToRelease = false; - needsRepainting = true; - } + if (needsToRelease && isEnabled()) + { + needsToRelease = false; + needsRepainting = true; + } - paintButton (g, isOver(), isDown()); + paintButton (g, isOver(), isDown()); } void Button::mouseEnter (const MouseEvent& e) { - updateState (&e); + updateState (&e); } void Button::mouseExit (const MouseEvent& e) { - updateState (&e); + updateState (&e); } void Button::mouseDown (const MouseEvent& e) { - updateState (&e); + updateState (&e); - if (isDown()) - { - if (autoRepeatDelay >= 0) - getRepeatTimer().startTimer (autoRepeatDelay); + if (isDown()) + { + if (autoRepeatDelay >= 0) + getRepeatTimer().startTimer (autoRepeatDelay); - if (triggerOnMouseDown) - internalClickCallback (e.mods); - } + if (triggerOnMouseDown) + internalClickCallback (e.mods); + } } void Button::mouseUp (const MouseEvent& e) { - const bool wasDown = isDown(); - updateState (&e); + const bool wasDown = isDown(); + updateState (&e); - if (wasDown && isOver() && ! triggerOnMouseDown) - internalClickCallback (e.mods); + if (wasDown && isOver() && ! triggerOnMouseDown) + internalClickCallback (e.mods); } void Button::mouseDrag (const MouseEvent& e) { - const ButtonState oldState = buttonState; - updateState (&e); + const ButtonState oldState = buttonState; + updateState (&e); - if (autoRepeatDelay >= 0 && buttonState != oldState && isDown()) - getRepeatTimer().startTimer (autoRepeatSpeed); + if (autoRepeatDelay >= 0 && buttonState != oldState && isDown()) + getRepeatTimer().startTimer (autoRepeatSpeed); } void Button::focusGained (FocusChangeType) { - updateState (0); - repaint(); + updateState (0); + repaint(); } void Button::focusLost (FocusChangeType) { - updateState (0); - repaint(); + updateState (0); + repaint(); } void Button::setVisible (bool shouldBeVisible) { - if (shouldBeVisible != isVisible()) - { - Component::setVisible (shouldBeVisible); + if (shouldBeVisible != isVisible()) + { + Component::setVisible (shouldBeVisible); - if (! shouldBeVisible) - needsToRelease = false; + if (! shouldBeVisible) + needsToRelease = false; - updateState (0); - } - else - { - Component::setVisible (shouldBeVisible); - } + updateState (0); + } + else + { + Component::setVisible (shouldBeVisible); + } } void Button::parentHierarchyChanged() { - Component* const newKeySource = (shortcuts.size() == 0) ? 0 : getTopLevelComponent(); + Component* const newKeySource = (shortcuts.size() == 0) ? 0 : getTopLevelComponent(); - if (newKeySource != keySource) - { - if (keySource->isValidComponent()) - keySource->removeKeyListener (this); + if (newKeySource != keySource) + { + if (keySource->isValidComponent()) + keySource->removeKeyListener (this); - keySource = newKeySource; + keySource = newKeySource; - if (keySource->isValidComponent()) - keySource->addKeyListener (this); - } + if (keySource->isValidComponent()) + keySource->addKeyListener (this); + } } void Button::setCommandToTrigger (ApplicationCommandManager* const commandManagerToUse_, - const int commandID_, - const bool generateTooltip_) + const int commandID_, + const bool generateTooltip_) { - commandID = commandID_; - generateTooltip = generateTooltip_; + commandID = commandID_; + generateTooltip = generateTooltip_; - if (commandManagerToUse != commandManagerToUse_) - { - if (commandManagerToUse != 0) - commandManagerToUse->removeListener (this); + if (commandManagerToUse != commandManagerToUse_) + { + if (commandManagerToUse != 0) + commandManagerToUse->removeListener (this); - commandManagerToUse = commandManagerToUse_; + commandManagerToUse = commandManagerToUse_; - if (commandManagerToUse != 0) - commandManagerToUse->addListener (this); + if (commandManagerToUse != 0) + commandManagerToUse->addListener (this); - // if you've got clickTogglesState turned on, you shouldn't also connect the button - // up to be a command invoker. Instead, your command handler must flip the state of whatever - // it is that this button represents, and the button will update its state to reflect this - // in the applicationCommandListChanged() method. - jassert (commandManagerToUse == 0 || ! clickTogglesState); - } + // if you've got clickTogglesState turned on, you shouldn't also connect the button + // up to be a command invoker. Instead, your command handler must flip the state of whatever + // it is that this button represents, and the button will update its state to reflect this + // in the applicationCommandListChanged() method. + jassert (commandManagerToUse == 0 || ! clickTogglesState); + } - if (commandManagerToUse != 0) - applicationCommandListChanged(); - else - setEnabled (true); + if (commandManagerToUse != 0) + applicationCommandListChanged(); + else + setEnabled (true); } void Button::applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info) { - if (info.commandID == commandID - && (info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) == 0) - { - flashButtonState(); - } + if (info.commandID == commandID + && (info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) == 0) + { + flashButtonState(); + } } void Button::applicationCommandListChanged() { - if (commandManagerToUse != 0) - { - ApplicationCommandInfo info (0); + if (commandManagerToUse != 0) + { + ApplicationCommandInfo info (0); - ApplicationCommandTarget* const target = commandManagerToUse->getTargetForCommand (commandID, info); + ApplicationCommandTarget* const target = commandManagerToUse->getTargetForCommand (commandID, info); - setEnabled (target != 0 && (info.flags & ApplicationCommandInfo::isDisabled) == 0); + setEnabled (target != 0 && (info.flags & ApplicationCommandInfo::isDisabled) == 0); - if (target != 0) - setToggleState ((info.flags & ApplicationCommandInfo::isTicked) != 0, false); - } + if (target != 0) + setToggleState ((info.flags & ApplicationCommandInfo::isTicked) != 0, false); + } } void Button::addShortcut (const KeyPress& key) { - if (key.isValid()) - { - jassert (! isRegisteredForShortcut (key)); // already registered! + if (key.isValid()) + { + jassert (! isRegisteredForShortcut (key)); // already registered! - shortcuts.add (key); - parentHierarchyChanged(); - } + shortcuts.add (key); + parentHierarchyChanged(); + } } void Button::clearShortcuts() { - shortcuts.clear(); + shortcuts.clear(); - parentHierarchyChanged(); + parentHierarchyChanged(); } bool Button::isShortcutPressed() const throw() { - if (! isCurrentlyBlockedByAnotherModalComponent()) - { - for (int i = shortcuts.size(); --i >= 0;) - if (shortcuts.getReference(i).isCurrentlyDown()) - return true; - } + if (! isCurrentlyBlockedByAnotherModalComponent()) + { + for (int i = shortcuts.size(); --i >= 0;) + if (shortcuts.getReference(i).isCurrentlyDown()) + return true; + } - return false; + return false; } bool Button::isRegisteredForShortcut (const KeyPress& key) const throw() { - for (int i = shortcuts.size(); --i >= 0;) - if (key == shortcuts.getReference(i)) - return true; + for (int i = shortcuts.size(); --i >= 0;) + if (key == shortcuts.getReference(i)) + return true; - return false; + return false; } bool Button::keyStateChanged (const bool, Component*) { - if (! isEnabled()) - return false; + if (! isEnabled()) + return false; - const bool wasDown = isKeyDown; - isKeyDown = isShortcutPressed(); + const bool wasDown = isKeyDown; + isKeyDown = isShortcutPressed(); - if (autoRepeatDelay >= 0 && (isKeyDown && ! wasDown)) - getRepeatTimer().startTimer (autoRepeatDelay); + if (autoRepeatDelay >= 0 && (isKeyDown && ! wasDown)) + getRepeatTimer().startTimer (autoRepeatDelay); - updateState (0); + updateState (0); - if (isEnabled() && wasDown && ! isKeyDown) - { - internalClickCallback (ModifierKeys::getCurrentModifiers()); + if (isEnabled() && wasDown && ! isKeyDown) + { + internalClickCallback (ModifierKeys::getCurrentModifiers()); - // (return immediately - this button may now have been deleted) - return true; - } + // (return immediately - this button may now have been deleted) + return true; + } - return wasDown || isKeyDown; + return wasDown || isKeyDown; } bool Button::keyPressed (const KeyPress&, Component*) { - // returning true will avoid forwarding events for keys that we're using as shortcuts - return isShortcutPressed(); + // returning true will avoid forwarding events for keys that we're using as shortcuts + return isShortcutPressed(); } bool Button::keyPressed (const KeyPress& key) { - if (isEnabled() && key.isKeyCode (KeyPress::returnKey)) - { - triggerClick(); - return true; - } + if (isEnabled() && key.isKeyCode (KeyPress::returnKey)) + { + triggerClick(); + return true; + } - return false; + return false; } void Button::setRepeatSpeed (const int initialDelayMillisecs, - const int repeatMillisecs, - const int minimumDelayInMillisecs) throw() + const int repeatMillisecs, + const int minimumDelayInMillisecs) throw() { - autoRepeatDelay = initialDelayMillisecs; - autoRepeatSpeed = repeatMillisecs; - autoRepeatMinimumDelay = jmin (autoRepeatSpeed, minimumDelayInMillisecs); + autoRepeatDelay = initialDelayMillisecs; + autoRepeatSpeed = repeatMillisecs; + autoRepeatMinimumDelay = jmin (autoRepeatSpeed, minimumDelayInMillisecs); } void Button::repeatTimerCallback() throw() { - if (needsRepainting) - { - getRepeatTimer().stopTimer(); - updateState (0); - needsRepainting = false; - } - else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState (0) == buttonDown))) - { - int repeatSpeed = autoRepeatSpeed; + if (needsRepainting) + { + getRepeatTimer().stopTimer(); + updateState (0); + needsRepainting = false; + } + else if (autoRepeatSpeed > 0 && (isKeyDown || (updateState (0) == buttonDown))) + { + int repeatSpeed = autoRepeatSpeed; - if (autoRepeatMinimumDelay >= 0) - { - double timeHeldDown = jmin (1.0, getMillisecondsSinceButtonDown() / 4000.0); - timeHeldDown *= timeHeldDown; + if (autoRepeatMinimumDelay >= 0) + { + double timeHeldDown = jmin (1.0, getMillisecondsSinceButtonDown() / 4000.0); + timeHeldDown *= timeHeldDown; - repeatSpeed = repeatSpeed + (int) (timeHeldDown * (autoRepeatMinimumDelay - repeatSpeed)); - } + repeatSpeed = repeatSpeed + (int) (timeHeldDown * (autoRepeatMinimumDelay - repeatSpeed)); + } - repeatSpeed = jmax (1, repeatSpeed); + repeatSpeed = jmax (1, repeatSpeed); - getRepeatTimer().startTimer (repeatSpeed); + getRepeatTimer().startTimer (repeatSpeed); - const uint32 now = Time::getApproximateMillisecondCounter(); - const int numTimesToCallback - = (now > lastTimeCallbackTime) ? jmax (1, (now - lastTimeCallbackTime) / repeatSpeed) : 1; + const uint32 now = Time::getApproximateMillisecondCounter(); + const int numTimesToCallback = (now > lastTimeCallbackTime) ? jmax (1, (int) (now - lastTimeCallbackTime) / repeatSpeed) : 1; - lastTimeCallbackTime = now; + lastTimeCallbackTime = now; - const ComponentDeletionWatcher cdw (this); + const ComponentDeletionWatcher cdw (this); - for (int i = numTimesToCallback; --i >= 0;) - { - internalClickCallback (ModifierKeys::getCurrentModifiers()); + for (int i = numTimesToCallback; --i >= 0;) + { + internalClickCallback (ModifierKeys::getCurrentModifiers()); - if (cdw.hasBeenDeleted() || ! isDown()) - return; - } - } - else if (! needsToRelease) - { - getRepeatTimer().stopTimer(); - } + if (cdw.hasBeenDeleted() || ! isDown()) + return; + } + } + else if (! needsToRelease) + { + getRepeatTimer().stopTimer(); + } } class InternalButtonRepeatTimer : public Timer { public: - InternalButtonRepeatTimer (Button& owner_) throw() - : owner (owner_) - { - } + InternalButtonRepeatTimer (Button& owner_) throw() + : owner (owner_) + { + } - ~InternalButtonRepeatTimer() - { - } + ~InternalButtonRepeatTimer() + { + } - void timerCallback() - { - owner.repeatTimerCallback(); - } + void timerCallback() + { + owner.repeatTimerCallback(); + } private: - Button& owner; + Button& owner; - InternalButtonRepeatTimer (const InternalButtonRepeatTimer&); - const InternalButtonRepeatTimer& operator= (const InternalButtonRepeatTimer&); + InternalButtonRepeatTimer (const InternalButtonRepeatTimer&); + const InternalButtonRepeatTimer& operator= (const InternalButtonRepeatTimer&); }; Timer& Button::getRepeatTimer() throw() { - if (repeatTimer == 0) - repeatTimer = new InternalButtonRepeatTimer (*this); + if (repeatTimer == 0) + repeatTimer = new InternalButtonRepeatTimer (*this); - return *repeatTimer; + return *repeatTimer; } END_JUCE_NAMESPACE @@ -43425,26 +43108,26 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE DrawableButton::DrawableButton (const String& name, - const DrawableButton::ButtonStyle buttonStyle) - : Button (name), - style (buttonStyle), - edgeIndent (3) + const DrawableButton::ButtonStyle buttonStyle) + : Button (name), + style (buttonStyle), + edgeIndent (3) { - if (buttonStyle == ImageOnButtonBackground) - { - backgroundOff = Colour (0xffbbbbff); - backgroundOn = Colour (0xff3333ff); - } - else - { - backgroundOff = Colours::transparentBlack; - backgroundOn = Colour (0xaabbbbff); - } + if (buttonStyle == ImageOnButtonBackground) + { + backgroundOff = Colour (0xffbbbbff); + backgroundOn = Colour (0xff3333ff); + } + else + { + backgroundOff = Colours::transparentBlack; + backgroundOn = Colour (0xaabbbbff); + } } DrawableButton::~DrawableButton() { - deleteImages(); + deleteImages(); } void DrawableButton::deleteImages() @@ -43452,229 +43135,229 @@ void DrawableButton::deleteImages() } void DrawableButton::setImages (const Drawable* normal, - const Drawable* over, - const Drawable* down, - const Drawable* disabled, - const Drawable* normalOn, - const Drawable* overOn, - const Drawable* downOn, - const Drawable* disabledOn) + const Drawable* over, + const Drawable* down, + const Drawable* disabled, + const Drawable* normalOn, + const Drawable* overOn, + const Drawable* downOn, + const Drawable* disabledOn) { - deleteImages(); + deleteImages(); - jassert (normal != 0); // you really need to give it at least a normal image.. + jassert (normal != 0); // you really need to give it at least a normal image.. - if (normal != 0) - normalImage = normal->createCopy(); + if (normal != 0) + normalImage = normal->createCopy(); - if (over != 0) - overImage = over->createCopy(); + if (over != 0) + overImage = over->createCopy(); - if (down != 0) - downImage = down->createCopy(); + if (down != 0) + downImage = down->createCopy(); - if (disabled != 0) - disabledImage = disabled->createCopy(); + if (disabled != 0) + disabledImage = disabled->createCopy(); - if (normalOn != 0) - normalImageOn = normalOn->createCopy(); + if (normalOn != 0) + normalImageOn = normalOn->createCopy(); - if (overOn != 0) - overImageOn = overOn->createCopy(); + if (overOn != 0) + overImageOn = overOn->createCopy(); - if (downOn != 0) - downImageOn = downOn->createCopy(); + if (downOn != 0) + downImageOn = downOn->createCopy(); - if (disabledOn != 0) - disabledImageOn = disabledOn->createCopy(); + if (disabledOn != 0) + disabledImageOn = disabledOn->createCopy(); - repaint(); + repaint(); } void DrawableButton::setButtonStyle (const DrawableButton::ButtonStyle newStyle) { - if (style != newStyle) - { - style = newStyle; - repaint(); - } + if (style != newStyle) + { + style = newStyle; + repaint(); + } } void DrawableButton::setBackgroundColours (const Colour& toggledOffColour, - const Colour& toggledOnColour) + const Colour& toggledOnColour) { - if (backgroundOff != toggledOffColour - || backgroundOn != toggledOnColour) - { - backgroundOff = toggledOffColour; - backgroundOn = toggledOnColour; + if (backgroundOff != toggledOffColour + || backgroundOn != toggledOnColour) + { + backgroundOff = toggledOffColour; + backgroundOn = toggledOnColour; - repaint(); - } + repaint(); + } } const Colour& DrawableButton::getBackgroundColour() const throw() { - return getToggleState() ? backgroundOn - : backgroundOff; + return getToggleState() ? backgroundOn + : backgroundOff; } void DrawableButton::setEdgeIndent (const int numPixelsIndent) { - edgeIndent = numPixelsIndent; - repaint(); + edgeIndent = numPixelsIndent; + repaint(); } void DrawableButton::paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown) + bool isMouseOverButton, + bool isButtonDown) { - Rectangle imageSpace; + Rectangle imageSpace; - if (style == ImageOnButtonBackground) - { - const int insetX = getWidth() / 4; - const int insetY = getHeight() / 4; + if (style == ImageOnButtonBackground) + { + const int insetX = getWidth() / 4; + const int insetY = getHeight() / 4; - imageSpace.setBounds (insetX, insetY, getWidth() - insetX * 2, getHeight() - insetY * 2); + imageSpace.setBounds (insetX, insetY, getWidth() - insetX * 2, getHeight() - insetY * 2); - getLookAndFeel().drawButtonBackground (g, *this, - getBackgroundColour(), - isMouseOverButton, - isButtonDown); - } - else - { - g.fillAll (getBackgroundColour()); + getLookAndFeel().drawButtonBackground (g, *this, + getBackgroundColour(), + isMouseOverButton, + isButtonDown); + } + else + { + g.fillAll (getBackgroundColour()); - const int textH = (style == ImageAboveTextLabel) - ? jmin (16, proportionOfHeight (0.25f)) - : 0; + const int textH = (style == ImageAboveTextLabel) + ? jmin (16, proportionOfHeight (0.25f)) + : 0; - const int indentX = jmin (edgeIndent, proportionOfWidth (0.3f)); - const int indentY = jmin (edgeIndent, proportionOfHeight (0.3f)); + const int indentX = jmin (edgeIndent, proportionOfWidth (0.3f)); + const int indentY = jmin (edgeIndent, proportionOfHeight (0.3f)); - imageSpace.setBounds (indentX, indentY, - getWidth() - indentX * 2, - getHeight() - indentY * 2 - textH); + imageSpace.setBounds (indentX, indentY, + getWidth() - indentX * 2, + getHeight() - indentY * 2 - textH); - if (textH > 0) - { - g.setFont ((float) textH); + if (textH > 0) + { + g.setFont ((float) textH); - g.setColour (Colours::black.withAlpha (isEnabled() ? 1.0f : 0.4f)); - g.drawFittedText (getButtonText(), - 2, getHeight() - textH - 1, - getWidth() - 4, textH, - Justification::centred, 1); - } - } + g.setColour (Colours::black.withAlpha (isEnabled() ? 1.0f : 0.4f)); + g.drawFittedText (getButtonText(), + 2, getHeight() - textH - 1, + getWidth() - 4, textH, + Justification::centred, 1); + } + } - g.setImageResamplingQuality (Graphics::mediumResamplingQuality); - g.setOpacity (1.0f); + g.setImageResamplingQuality (Graphics::mediumResamplingQuality); + g.setOpacity (1.0f); - const Drawable* imageToDraw = 0; + const Drawable* imageToDraw = 0; - if (isEnabled()) - { - imageToDraw = getCurrentImage(); - } - else - { - imageToDraw = getToggleState() ? disabledImageOn - : disabledImage; + if (isEnabled()) + { + imageToDraw = getCurrentImage(); + } + else + { + imageToDraw = getToggleState() ? disabledImageOn + : disabledImage; - if (imageToDraw == 0) - { - g.setOpacity (0.4f); - imageToDraw = getNormalImage(); - } - } + if (imageToDraw == 0) + { + g.setOpacity (0.4f); + imageToDraw = getNormalImage(); + } + } - if (imageToDraw != 0) - { - if (style == ImageRaw) - { - imageToDraw->draw (g, 1.0f); - } - else - { - imageToDraw->drawWithin (g, - imageSpace.getX(), - imageSpace.getY(), - imageSpace.getWidth(), - imageSpace.getHeight(), - RectanglePlacement::centred, - 1.0f); - } - } + if (imageToDraw != 0) + { + if (style == ImageRaw) + { + imageToDraw->draw (g, 1.0f); + } + else + { + imageToDraw->drawWithin (g, + imageSpace.getX(), + imageSpace.getY(), + imageSpace.getWidth(), + imageSpace.getHeight(), + RectanglePlacement::centred, + 1.0f); + } + } } const Drawable* DrawableButton::getCurrentImage() const throw() { - if (isDown()) - return getDownImage(); + if (isDown()) + return getDownImage(); - if (isOver()) - return getOverImage(); + if (isOver()) + return getOverImage(); - return getNormalImage(); + return getNormalImage(); } const Drawable* DrawableButton::getNormalImage() const throw() { - return (getToggleState() && normalImageOn != 0) ? normalImageOn - : normalImage; + return (getToggleState() && normalImageOn != 0) ? normalImageOn + : normalImage; } const Drawable* DrawableButton::getOverImage() const throw() { - const Drawable* d = normalImage; + const Drawable* d = normalImage; - if (getToggleState()) - { - if (overImageOn != 0) - d = overImageOn; - else if (normalImageOn != 0) - d = normalImageOn; - else if (overImage != 0) - d = overImage; - } - else - { - if (overImage != 0) - d = overImage; - } + if (getToggleState()) + { + if (overImageOn != 0) + d = overImageOn; + else if (normalImageOn != 0) + d = normalImageOn; + else if (overImage != 0) + d = overImage; + } + else + { + if (overImage != 0) + d = overImage; + } - return d; + return d; } const Drawable* DrawableButton::getDownImage() const throw() { - const Drawable* d = normalImage; + const Drawable* d = normalImage; - if (getToggleState()) - { - if (downImageOn != 0) - d = downImageOn; - else if (overImageOn != 0) - d = overImageOn; - else if (normalImageOn != 0) - d = normalImageOn; - else if (downImage != 0) - d = downImage; - else - d = getOverImage(); - } - else - { - if (downImage != 0) - d = downImage; - else - d = getOverImage(); - } + if (getToggleState()) + { + if (downImageOn != 0) + d = downImageOn; + else if (overImageOn != 0) + d = overImageOn; + else if (normalImageOn != 0) + d = normalImageOn; + else if (downImage != 0) + d = downImage; + else + d = getOverImage(); + } + else + { + if (downImage != 0) + d = downImage; + else + d = getOverImage(); + } - return d; + return d; } END_JUCE_NAMESPACE @@ -43685,15 +43368,15 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE HyperlinkButton::HyperlinkButton (const String& linkText, - const URL& linkURL) + const URL& linkURL) : Button (linkText), - url (linkURL), - font (14.0f, Font::underlined), - resizeFont (true), - justification (Justification::centred) + url (linkURL), + font (14.0f, Font::underlined), + resizeFont (true), + justification (Justification::centred) { - setMouseCursor (MouseCursor::PointingHandCursor); - setTooltip (linkURL.toString (false)); + setMouseCursor (MouseCursor::PointingHandCursor); + setTooltip (linkURL.toString (false)); } HyperlinkButton::~HyperlinkButton() @@ -43701,65 +43384,65 @@ HyperlinkButton::~HyperlinkButton() } void HyperlinkButton::setFont (const Font& newFont, - const bool resizeToMatchComponentHeight, - const Justification& justificationType) + const bool resizeToMatchComponentHeight, + const Justification& justificationType) { - font = newFont; - resizeFont = resizeToMatchComponentHeight; - justification = justificationType; - repaint(); + font = newFont; + resizeFont = resizeToMatchComponentHeight; + justification = justificationType; + repaint(); } void HyperlinkButton::setURL (const URL& newURL) throw() { - url = newURL; - setTooltip (newURL.toString (false)); + url = newURL; + setTooltip (newURL.toString (false)); } const Font HyperlinkButton::getFontToUse() const { - Font f (font); + Font f (font); - if (resizeFont) - f.setHeight (getHeight() * 0.7f); + if (resizeFont) + f.setHeight (getHeight() * 0.7f); - return f; + return f; } void HyperlinkButton::changeWidthToFitText() { - setSize (getFontToUse().getStringWidth (getName()) + 6, getHeight()); + setSize (getFontToUse().getStringWidth (getName()) + 6, getHeight()); } void HyperlinkButton::colourChanged() { - repaint(); + repaint(); } void HyperlinkButton::clicked() { - if (url.isWellFormed()) - url.launchInDefaultBrowser(); + if (url.isWellFormed()) + url.launchInDefaultBrowser(); } void HyperlinkButton::paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown) + bool isMouseOverButton, + bool isButtonDown) { - const Colour textColour (findColour (textColourId)); + const Colour textColour (findColour (textColourId)); - if (isEnabled()) - g.setColour ((isMouseOverButton) ? textColour.darker ((isButtonDown) ? 1.3f : 0.4f) - : textColour); - else - g.setColour (textColour.withMultipliedAlpha (0.4f)); + if (isEnabled()) + g.setColour ((isMouseOverButton) ? textColour.darker ((isButtonDown) ? 1.3f : 0.4f) + : textColour); + else + g.setColour (textColour.withMultipliedAlpha (0.4f)); - g.setFont (getFontToUse()); + g.setFont (getFontToUse()); - g.drawText (getButtonText(), - 2, 0, getWidth() - 2, getHeight(), - justification.getOnlyHorizontalFlags() | Justification::verticallyCentred, - true); + g.drawText (getButtonText(), + 2, 0, getWidth() - 2, getHeight(), + justification.getOnlyHorizontalFlags() | Justification::verticallyCentred, + true); } END_JUCE_NAMESPACE @@ -43770,183 +43453,183 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ImageButton::ImageButton (const String& text_) - : Button (text_), - scaleImageToFit (true), - preserveProportions (true), - alphaThreshold (0), - imageX (0), - imageY (0), - imageW (0), - imageH (0), - normalImage (0), - overImage (0), - downImage (0) + : Button (text_), + scaleImageToFit (true), + preserveProportions (true), + alphaThreshold (0), + imageX (0), + imageY (0), + imageW (0), + imageH (0), + normalImage (0), + overImage (0), + downImage (0) { } ImageButton::~ImageButton() { - deleteImages(); + deleteImages(); } void ImageButton::deleteImages() { - ImageCache::releaseOrDelete (normalImage); - ImageCache::releaseOrDelete (overImage); - ImageCache::releaseOrDelete (downImage); + ImageCache::releaseOrDelete (normalImage); + ImageCache::releaseOrDelete (overImage); + ImageCache::releaseOrDelete (downImage); } void ImageButton::setImages (const bool resizeButtonNowToFitThisImage, - const bool rescaleImagesWhenButtonSizeChanges, - const bool preserveImageProportions, - Image* const normalImage_, - const float imageOpacityWhenNormal, - const Colour& overlayColourWhenNormal, - Image* const overImage_, - const float imageOpacityWhenOver, - const Colour& overlayColourWhenOver, - Image* const downImage_, - const float imageOpacityWhenDown, - const Colour& overlayColourWhenDown, - const float hitTestAlphaThreshold) + const bool rescaleImagesWhenButtonSizeChanges, + const bool preserveImageProportions, + Image* const normalImage_, + const float imageOpacityWhenNormal, + const Colour& overlayColourWhenNormal, + Image* const overImage_, + const float imageOpacityWhenOver, + const Colour& overlayColourWhenOver, + Image* const downImage_, + const float imageOpacityWhenDown, + const Colour& overlayColourWhenDown, + const float hitTestAlphaThreshold) { - deleteImages(); + deleteImages(); - normalImage = normalImage_; - overImage = overImage_; - downImage = downImage_; + normalImage = normalImage_; + overImage = overImage_; + downImage = downImage_; - if (resizeButtonNowToFitThisImage && normalImage != 0) - { - imageW = normalImage->getWidth(); - imageH = normalImage->getHeight(); + if (resizeButtonNowToFitThisImage && normalImage != 0) + { + imageW = normalImage->getWidth(); + imageH = normalImage->getHeight(); - setSize (imageW, imageH); - } + setSize (imageW, imageH); + } - scaleImageToFit = rescaleImagesWhenButtonSizeChanges; - preserveProportions = preserveImageProportions; + scaleImageToFit = rescaleImagesWhenButtonSizeChanges; + preserveProportions = preserveImageProportions; - normalOpacity = imageOpacityWhenNormal; - normalOverlay = overlayColourWhenNormal; - overOpacity = imageOpacityWhenOver; - overOverlay = overlayColourWhenOver; - downOpacity = imageOpacityWhenDown; - downOverlay = overlayColourWhenDown; + normalOpacity = imageOpacityWhenNormal; + normalOverlay = overlayColourWhenNormal; + overOpacity = imageOpacityWhenOver; + overOverlay = overlayColourWhenOver; + downOpacity = imageOpacityWhenDown; + downOverlay = overlayColourWhenDown; - alphaThreshold = (unsigned char) jlimit (0, 0xff, roundFloatToInt (255.0f * hitTestAlphaThreshold)); + alphaThreshold = (unsigned char) jlimit (0, 0xff, roundToInt (255.0f * hitTestAlphaThreshold)); - repaint(); + repaint(); } Image* ImageButton::getCurrentImage() const { - if (isDown() || getToggleState()) - return getDownImage(); + if (isDown() || getToggleState()) + return getDownImage(); - if (isOver()) - return getOverImage(); + if (isOver()) + return getOverImage(); - return getNormalImage(); + return getNormalImage(); } Image* ImageButton::getNormalImage() const throw() { - return normalImage; + return normalImage; } Image* ImageButton::getOverImage() const throw() { - return (overImage != 0) ? overImage - : normalImage; + return (overImage != 0) ? overImage + : normalImage; } Image* ImageButton::getDownImage() const throw() { - return (downImage != 0) ? downImage - : getOverImage(); + return (downImage != 0) ? downImage + : getOverImage(); } void ImageButton::paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown) + bool isMouseOverButton, + bool isButtonDown) { - if (! isEnabled()) - { - isMouseOverButton = false; - isButtonDown = false; - } + if (! isEnabled()) + { + isMouseOverButton = false; + isButtonDown = false; + } - Image* const im = getCurrentImage(); + Image* const im = getCurrentImage(); - if (im != 0) - { - const int iw = im->getWidth(); - const int ih = im->getHeight(); - imageW = getWidth(); - imageH = getHeight(); - imageX = (imageW - iw) >> 1; - imageY = (imageH - ih) >> 1; + if (im != 0) + { + const int iw = im->getWidth(); + const int ih = im->getHeight(); + imageW = getWidth(); + imageH = getHeight(); + imageX = (imageW - iw) >> 1; + imageY = (imageH - ih) >> 1; - if (scaleImageToFit) - { - if (preserveProportions) - { - int newW, newH; - const float imRatio = ih / (float)iw; - const float destRatio = imageH / (float)imageW; + if (scaleImageToFit) + { + if (preserveProportions) + { + int newW, newH; + const float imRatio = ih / (float)iw; + const float destRatio = imageH / (float)imageW; - if (imRatio > destRatio) - { - newW = roundFloatToInt (imageH / imRatio); - newH = imageH; - } - else - { - newW = imageW; - newH = roundFloatToInt (imageW * imRatio); - } + if (imRatio > destRatio) + { + newW = roundToInt (imageH / imRatio); + newH = imageH; + } + else + { + newW = imageW; + newH = roundToInt (imageW * imRatio); + } - imageX = (imageW - newW) / 2; - imageY = (imageH - newH) / 2; - imageW = newW; - imageH = newH; - } - else - { - imageX = 0; - imageY = 0; - } - } + imageX = (imageW - newW) / 2; + imageY = (imageH - newH) / 2; + imageW = newW; + imageH = newH; + } + else + { + imageX = 0; + imageY = 0; + } + } - if (! scaleImageToFit) - { - imageW = iw; - imageH = ih; - } + if (! scaleImageToFit) + { + imageW = iw; + imageH = ih; + } - getLookAndFeel().drawImageButton (g, im, imageX, imageY, imageW, imageH, - isButtonDown ? downOverlay - : (isMouseOverButton ? overOverlay - : normalOverlay), - isButtonDown ? downOpacity - : (isMouseOverButton ? overOpacity - : normalOpacity), - *this); - } + getLookAndFeel().drawImageButton (g, im, imageX, imageY, imageW, imageH, + isButtonDown ? downOverlay + : (isMouseOverButton ? overOverlay + : normalOverlay), + isButtonDown ? downOpacity + : (isMouseOverButton ? overOpacity + : normalOpacity), + *this); + } } bool ImageButton::hitTest (int x, int y) { - if (alphaThreshold == 0) - return true; + if (alphaThreshold == 0) + return true; - Image* const im = getCurrentImage(); + Image* const im = getCurrentImage(); - return im == 0 - || (imageW > 0 && imageH > 0 - && alphaThreshold < im->getPixelAt (((x - imageX) * im->getWidth()) / imageW, - ((y - imageY) * im->getHeight()) / imageH).getAlpha()); + return im == 0 + || (imageW > 0 && imageH > 0 + && alphaThreshold < im->getPixelAt (((x - imageX) * im->getWidth()) / imageW, + ((y - imageY) * im->getHeight()) / imageH).getAlpha()); } END_JUCE_NAMESPACE @@ -43957,15 +43640,15 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ShapeButton::ShapeButton (const String& text_, - const Colour& normalColour_, - const Colour& overColour_, - const Colour& downColour_) + const Colour& normalColour_, + const Colour& overColour_, + const Colour& downColour_) : Button (text_), - normalColour (normalColour_), - overColour (overColour_), - downColour (downColour_), - maintainShapeProportions (false), - outlineWidth (0.0f) + normalColour (normalColour_), + overColour (overColour_), + downColour (downColour_), + maintainShapeProportions (false), + outlineWidth (0.0f) { } @@ -43974,84 +43657,84 @@ ShapeButton::~ShapeButton() } void ShapeButton::setColours (const Colour& newNormalColour, - const Colour& newOverColour, - const Colour& newDownColour) + const Colour& newOverColour, + const Colour& newDownColour) { - normalColour = newNormalColour; - overColour = newOverColour; - downColour = newDownColour; + normalColour = newNormalColour; + overColour = newOverColour; + downColour = newDownColour; } void ShapeButton::setOutline (const Colour& newOutlineColour, - const float newOutlineWidth) + const float newOutlineWidth) { - outlineColour = newOutlineColour; - outlineWidth = newOutlineWidth; + outlineColour = newOutlineColour; + outlineWidth = newOutlineWidth; } void ShapeButton::setShape (const Path& newShape, - const bool resizeNowToFitThisShape, - const bool maintainShapeProportions_, - const bool hasShadow) + const bool resizeNowToFitThisShape, + const bool maintainShapeProportions_, + const bool hasShadow) { - shape = newShape; - maintainShapeProportions = maintainShapeProportions_; + shape = newShape; + maintainShapeProportions = maintainShapeProportions_; - shadow.setShadowProperties (3.0f, 0.5f, 0, 0); - setComponentEffect ((hasShadow) ? &shadow : 0); + shadow.setShadowProperties (3.0f, 0.5f, 0, 0); + setComponentEffect ((hasShadow) ? &shadow : 0); - if (resizeNowToFitThisShape) - { - float x, y, w, h; - shape.getBounds (x, y, w, h); - shape.applyTransform (AffineTransform::translation (-x, -y)); + if (resizeNowToFitThisShape) + { + float x, y, w, h; + shape.getBounds (x, y, w, h); + shape.applyTransform (AffineTransform::translation (-x, -y)); - if (hasShadow) - { - w += 4.0f; - h += 4.0f; - shape.applyTransform (AffineTransform::translation (2.0f, 2.0f)); - } + if (hasShadow) + { + w += 4.0f; + h += 4.0f; + shape.applyTransform (AffineTransform::translation (2.0f, 2.0f)); + } - setSize (1 + (int) (w + outlineWidth), - 1 + (int) (h + outlineWidth)); - } + setSize (1 + (int) (w + outlineWidth), + 1 + (int) (h + outlineWidth)); + } } void ShapeButton::paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) { - if (! isEnabled()) - { - isMouseOverButton = false; - isButtonDown = false; - } + if (! isEnabled()) + { + isMouseOverButton = false; + isButtonDown = false; + } - g.setColour ((isButtonDown) ? downColour - : (isMouseOverButton) ? overColour - : normalColour); + g.setColour ((isButtonDown) ? downColour + : (isMouseOverButton) ? overColour + : normalColour); - int w = getWidth(); - int h = getHeight(); + int w = getWidth(); + int h = getHeight(); - if (getComponentEffect() != 0) - { - w -= 4; - h -= 4; - } + if (getComponentEffect() != 0) + { + w -= 4; + h -= 4; + } - const float offset = (outlineWidth * 0.5f) + (isButtonDown ? 1.5f : 0.0f); + const float offset = (outlineWidth * 0.5f) + (isButtonDown ? 1.5f : 0.0f); - const AffineTransform trans (shape.getTransformToScaleToFit (offset, offset, - w - offset - outlineWidth, - h - offset - outlineWidth, - maintainShapeProportions)); - g.fillPath (shape, trans); + const AffineTransform trans (shape.getTransformToScaleToFit (offset, offset, + w - offset - outlineWidth, + h - offset - outlineWidth, + maintainShapeProportions)); + g.fillPath (shape, trans); - if (outlineWidth > 0.0f) - { - g.setColour (outlineColour); - g.strokePath (shape, PathStrokeType (outlineWidth), trans); - } + if (outlineWidth > 0.0f) + { + g.setColour (outlineColour); + g.strokePath (shape, PathStrokeType (outlineWidth), trans); + } } END_JUCE_NAMESPACE @@ -44062,10 +43745,10 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE TextButton::TextButton (const String& name, - const String& toolTip) - : Button (name) + const String& toolTip) + : Button (name) { - setTooltip (toolTip); + setTooltip (toolTip); } TextButton::~TextButton() @@ -44073,37 +43756,37 @@ TextButton::~TextButton() } void TextButton::paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown) + bool isMouseOverButton, + bool isButtonDown) { - getLookAndFeel().drawButtonBackground (g, *this, - findColour (getToggleState() ? buttonOnColourId - : buttonColourId), - isMouseOverButton, - isButtonDown); + getLookAndFeel().drawButtonBackground (g, *this, + findColour (getToggleState() ? buttonOnColourId + : buttonColourId), + isMouseOverButton, + isButtonDown); - getLookAndFeel().drawButtonText (g, *this, - isMouseOverButton, - isButtonDown); + getLookAndFeel().drawButtonText (g, *this, + isMouseOverButton, + isButtonDown); } void TextButton::colourChanged() { - repaint(); + repaint(); } const Font TextButton::getFont() { - return Font (jmin (15.0f, getHeight() * 0.6f)); + return Font (jmin (15.0f, getHeight() * 0.6f)); } void TextButton::changeWidthToFitText (const int newHeight) { - if (newHeight >= 0) - setSize (jmax (1, getWidth()), newHeight); + if (newHeight >= 0) + setSize (jmax (1, getWidth()), newHeight); - setSize (getFont().getStringWidth (getButtonText()) + getHeight(), - getHeight()); + setSize (getFont().getStringWidth (getButtonText()) + getHeight(), + getHeight()); } END_JUCE_NAMESPACE @@ -44114,9 +43797,9 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ToggleButton::ToggleButton (const String& buttonText) - : Button (buttonText) + : Button (buttonText) { - setClickingTogglesState (true); + setClickingTogglesState (true); } ToggleButton::~ToggleButton() @@ -44124,22 +43807,22 @@ ToggleButton::~ToggleButton() } void ToggleButton::paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown) + bool isMouseOverButton, + bool isButtonDown) { - getLookAndFeel().drawToggleButton (g, *this, - isMouseOverButton, - isButtonDown); + getLookAndFeel().drawToggleButton (g, *this, + isMouseOverButton, + isButtonDown); } void ToggleButton::changeWidthToFitText() { - getLookAndFeel().changeToggleButtonWidthToFitText (*this); + getLookAndFeel().changeToggleButtonWidthToFitText (*this); } void ToggleButton::colourChanged() { - repaint(); + repaint(); } END_JUCE_NAMESPACE @@ -44150,12 +43833,12 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ToolbarButton::ToolbarButton (const int itemId_, - const String& buttonText, - Drawable* const normalImage_, - Drawable* const toggledOnImage_) + const String& buttonText, + Drawable* const normalImage_, + Drawable* const toggledOnImage_) : ToolbarItemComponent (itemId_, buttonText, true), - normalImage (normalImage_), - toggledOnImage (toggledOnImage_) + normalImage (normalImage_), + toggledOnImage (toggledOnImage_) { } @@ -44164,37 +43847,37 @@ ToolbarButton::~ToolbarButton() } bool ToolbarButton::getToolbarItemSizes (int toolbarDepth, - bool /*isToolbarVertical*/, - int& preferredSize, - int& minSize, int& maxSize) + bool /*isToolbarVertical*/, + int& preferredSize, + int& minSize, int& maxSize) { - preferredSize = minSize = maxSize = toolbarDepth; - return true; + preferredSize = minSize = maxSize = toolbarDepth; + return true; } void ToolbarButton::paintButtonArea (Graphics& g, - int width, int height, - bool /*isMouseOver*/, - bool /*isMouseDown*/) + int width, int height, + bool /*isMouseOver*/, + bool /*isMouseDown*/) { - Drawable* d = normalImage; + Drawable* d = normalImage; - if (getToggleState() && toggledOnImage != 0) - d = toggledOnImage; + if (getToggleState() && toggledOnImage != 0) + d = toggledOnImage; - if (! isEnabled()) - { - Image im (Image::ARGB, width, height, true); - Graphics g2 (im); - d->drawWithin (g2, 0, 0, width, height, RectanglePlacement::centred, 1.0f); - im.desaturate(); + if (! isEnabled()) + { + Image im (Image::ARGB, width, height, true); + Graphics g2 (im); + d->drawWithin (g2, 0, 0, width, height, RectanglePlacement::centred, 1.0f); + im.desaturate(); - g.drawImageAt (&im, 0, 0); - } - else - { - d->drawWithin (g, 0, 0, width, height, RectanglePlacement::centred, 1.0f); - } + g.drawImageAt (&im, 0, 0); + } + else + { + d->drawWithin (g, 0, 0, width, height, RectanglePlacement::centred, 1.0f); + } } void ToolbarButton::contentAreaChanged (const Rectangle&) @@ -44211,106 +43894,106 @@ BEGIN_JUCE_NAMESPACE class CodeDocumentLine { public: - CodeDocumentLine (const String& line_, - const int lineLength_, - const int lineStartInFile_) throw() - : line (line_), - lineStartInFile (lineStartInFile_), - lineLength (lineLength_) - { - lineLengthWithoutNewLines = lineLength; + CodeDocumentLine (const String& line_, + const int lineLength_, + const int lineStartInFile_) throw() + : line (line_), + lineStartInFile (lineStartInFile_), + lineLength (lineLength_) + { + lineLengthWithoutNewLines = lineLength; - while (lineLengthWithoutNewLines > 0 - && (line [lineLengthWithoutNewLines - 1] == '\n' - || line [lineLengthWithoutNewLines - 1] == '\r')) - { - --lineLengthWithoutNewLines; - } - } + while (lineLengthWithoutNewLines > 0 + && (line [lineLengthWithoutNewLines - 1] == '\n' + || line [lineLengthWithoutNewLines - 1] == '\r')) + { + --lineLengthWithoutNewLines; + } + } - ~CodeDocumentLine() throw() - { - } + ~CodeDocumentLine() throw() + { + } - static void createLines (Array & newLines, const String& text) throw() - { - const tchar* const t = (const tchar*) text; - int pos = 0; + static void createLines (Array & newLines, const String& text) throw() + { + const tchar* const t = (const tchar*) text; + int pos = 0; - while (t [pos] != 0) - { - const int startOfLine = pos; + while (t [pos] != 0) + { + const int startOfLine = pos; - while (t[pos] != 0) - { - if (t[pos] == T('\r')) - { - ++pos; - if (t[pos] == T('\n')) - ++pos; + while (t[pos] != 0) + { + if (t[pos] == T('\r')) + { + ++pos; + if (t[pos] == T('\n')) + ++pos; - break; - } + break; + } - if (t[pos] == T('\n')) - { - ++pos; - break; - } + if (t[pos] == T('\n')) + { + ++pos; + break; + } - ++pos; - } + ++pos; + } - newLines.add (new CodeDocumentLine (String (t + startOfLine, pos - startOfLine), - pos - startOfLine, - startOfLine)); - } + newLines.add (new CodeDocumentLine (String (t + startOfLine, pos - startOfLine), + pos - startOfLine, + startOfLine)); + } - jassert (pos == text.length()); - } + jassert (pos == text.length()); + } - bool endsWithLineBreak() const throw() - { - return lineLengthWithoutNewLines != lineLength; - } + bool endsWithLineBreak() const throw() + { + return lineLengthWithoutNewLines != lineLength; + } - void updateLength() throw() - { - lineLengthWithoutNewLines = lineLength = line.length(); + void updateLength() throw() + { + lineLengthWithoutNewLines = lineLength = line.length(); - while (lineLengthWithoutNewLines > 0 - && (line [lineLengthWithoutNewLines - 1] == '\n' - || line [lineLengthWithoutNewLines - 1] == '\r')) - { - --lineLengthWithoutNewLines; - } - } + while (lineLengthWithoutNewLines > 0 + && (line [lineLengthWithoutNewLines - 1] == '\n' + || line [lineLengthWithoutNewLines - 1] == '\r')) + { + --lineLengthWithoutNewLines; + } + } - String line; - int lineStartInFile, lineLength, lineLengthWithoutNewLines; + String line; + int lineStartInFile, lineLength, lineLengthWithoutNewLines; }; CodeDocument::Iterator::Iterator (CodeDocument* const document_) throw() - : document (document_), - line (0), - position (0) + : document (document_), + line (0), + position (0) { } CodeDocument::Iterator::Iterator (const CodeDocument::Iterator& other) - : document (other.document), - line (other.line), - position (other.position) + : document (other.document), + line (other.line), + position (other.position) { } const CodeDocument::Iterator& CodeDocument::Iterator::operator= (const CodeDocument::Iterator& other) throw() { - document = other.document; - line = other.line; - position = other.position; + document = other.document; + line = other.line; + position = other.position; - return *this; + return *this; } CodeDocument::Iterator::~Iterator() throw() @@ -44319,302 +44002,302 @@ CodeDocument::Iterator::~Iterator() throw() juce_wchar CodeDocument::Iterator::nextChar() throw() { - if (line >= document->lines.size()) - return 0; + if (line >= document->lines.size()) + return 0; - const CodeDocumentLine* const currentLine = document->lines.getUnchecked (line); - const juce_wchar result = currentLine->line [position - currentLine->lineStartInFile]; + const CodeDocumentLine* const currentLine = document->lines.getUnchecked (line); + const juce_wchar result = currentLine->line [position - currentLine->lineStartInFile]; - if (++position >= currentLine->lineStartInFile + currentLine->lineLength) - ++line; + if (++position >= currentLine->lineStartInFile + currentLine->lineLength) + ++line; - return result; + return result; } void CodeDocument::Iterator::skip() throw() { - if (line < document->lines.size()) - { - const CodeDocumentLine* const currentLine = document->lines.getUnchecked (line); + if (line < document->lines.size()) + { + const CodeDocumentLine* const currentLine = document->lines.getUnchecked (line); - if (++position >= currentLine->lineStartInFile + currentLine->lineLength) - ++line; - } + if (++position >= currentLine->lineStartInFile + currentLine->lineLength) + ++line; + } } juce_wchar CodeDocument::Iterator::peekNextChar() const throw() { - if (line >= document->lines.size()) - return 0; + if (line >= document->lines.size()) + return 0; - const CodeDocumentLine* const currentLine = document->lines.getUnchecked (line); - return currentLine->line [position - currentLine->lineStartInFile]; + const CodeDocumentLine* const currentLine = document->lines.getUnchecked (line); + return currentLine->line [position - currentLine->lineStartInFile]; } void CodeDocument::Iterator::skipWhitespace() { - while (line < document->lines.size()) - { - const CodeDocumentLine* const currentLine = document->lines.getUnchecked (line); + while (line < document->lines.size()) + { + const CodeDocumentLine* const currentLine = document->lines.getUnchecked (line); - for (;;) - { - if (! CharacterFunctions::isWhitespace (currentLine->line [position - currentLine->lineStartInFile])) - return; + for (;;) + { + if (! CharacterFunctions::isWhitespace (currentLine->line [position - currentLine->lineStartInFile])) + return; - if (++position >= currentLine->lineStartInFile + currentLine->lineLength) - { - ++line; - break; - } - } - } + if (++position >= currentLine->lineStartInFile + currentLine->lineLength) + { + ++line; + break; + } + } + } } void CodeDocument::Iterator::skipToEndOfLine() { - if (line < document->lines.size()) - { - const CodeDocumentLine* const currentLine = document->lines.getUnchecked (line); - position = currentLine->lineStartInFile + currentLine->lineLength; - ++line; - } + if (line < document->lines.size()) + { + const CodeDocumentLine* const currentLine = document->lines.getUnchecked (line); + position = currentLine->lineStartInFile + currentLine->lineLength; + ++line; + } } bool CodeDocument::Iterator::isEOF() const throw() { - return position >= document->getNumCharacters(); + return position >= document->getNumCharacters(); } CodeDocument::Position::Position() throw() - : owner (0), characterPos (0), line (0), - indexInLine (0), positionMaintained (false) + : owner (0), characterPos (0), line (0), + indexInLine (0), positionMaintained (false) { } CodeDocument::Position::Position (const CodeDocument* const ownerDocument, - const int line_, const int indexInLine_) throw() - : owner (const_cast (ownerDocument)), - characterPos (0), line (line_), - indexInLine (indexInLine_), positionMaintained (false) + const int line_, const int indexInLine_) throw() + : owner (const_cast (ownerDocument)), + characterPos (0), line (line_), + indexInLine (indexInLine_), positionMaintained (false) { - setLineAndIndex (line_, indexInLine_); + setLineAndIndex (line_, indexInLine_); } CodeDocument::Position::Position (const CodeDocument* const ownerDocument, - const int characterPos_) throw() - : owner (const_cast (ownerDocument)), - positionMaintained (false) + const int characterPos_) throw() + : owner (const_cast (ownerDocument)), + positionMaintained (false) { - setPosition (characterPos_); + setPosition (characterPos_); } CodeDocument::Position::Position (const Position& other) throw() - : owner (other.owner), characterPos (other.characterPos), line (other.line), - indexInLine (other.indexInLine), positionMaintained (false) + : owner (other.owner), characterPos (other.characterPos), line (other.line), + indexInLine (other.indexInLine), positionMaintained (false) { - jassert (*this == other); + jassert (*this == other); } CodeDocument::Position::~Position() throw() { - setPositionMaintained (false); + setPositionMaintained (false); } const CodeDocument::Position& CodeDocument::Position::operator= (const Position& other) throw() { - if (this != &other) - { - const bool wasPositionMaintained = positionMaintained; - if (owner != other.owner) - setPositionMaintained (false); + if (this != &other) + { + const bool wasPositionMaintained = positionMaintained; + if (owner != other.owner) + setPositionMaintained (false); - owner = other.owner; - line = other.line; - indexInLine = other.indexInLine; - characterPos = other.characterPos; - setPositionMaintained (wasPositionMaintained); + owner = other.owner; + line = other.line; + indexInLine = other.indexInLine; + characterPos = other.characterPos; + setPositionMaintained (wasPositionMaintained); - jassert (*this == other); - } + jassert (*this == other); + } - return *this; + return *this; } bool CodeDocument::Position::operator== (const Position& other) const throw() { - jassert ((characterPos == other.characterPos) - == (line == other.line && indexInLine == other.indexInLine)); + jassert ((characterPos == other.characterPos) + == (line == other.line && indexInLine == other.indexInLine)); - return characterPos == other.characterPos - && line == other.line - && indexInLine == other.indexInLine - && owner == other.owner; + return characterPos == other.characterPos + && line == other.line + && indexInLine == other.indexInLine + && owner == other.owner; } bool CodeDocument::Position::operator!= (const Position& other) const throw() { - return ! operator== (other); + return ! operator== (other); } void CodeDocument::Position::setLineAndIndex (const int newLine, const int newIndexInLine) throw() { - jassert (owner != 0); + jassert (owner != 0); - if (owner->lines.size() == 0) - { - line = 0; - indexInLine = 0; - characterPos = 0; - } - else - { - if (newLine >= owner->lines.size()) - { - line = owner->lines.size() - 1; + if (owner->lines.size() == 0) + { + line = 0; + indexInLine = 0; + characterPos = 0; + } + else + { + if (newLine >= owner->lines.size()) + { + line = owner->lines.size() - 1; - CodeDocumentLine* const l = owner->lines.getUnchecked (line); - jassert (l != 0); + CodeDocumentLine* const l = owner->lines.getUnchecked (line); + jassert (l != 0); - indexInLine = l->lineLengthWithoutNewLines; - characterPos = l->lineStartInFile + indexInLine; - } - else - { - line = jmax (0, newLine); + indexInLine = l->lineLengthWithoutNewLines; + characterPos = l->lineStartInFile + indexInLine; + } + else + { + line = jmax (0, newLine); - CodeDocumentLine* const l = owner->lines.getUnchecked (line); - jassert (l != 0); + CodeDocumentLine* const l = owner->lines.getUnchecked (line); + jassert (l != 0); - if (l->lineLengthWithoutNewLines > 0) - indexInLine = jlimit (0, l->lineLengthWithoutNewLines, newIndexInLine); - else - indexInLine = 0; + if (l->lineLengthWithoutNewLines > 0) + indexInLine = jlimit (0, l->lineLengthWithoutNewLines, newIndexInLine); + else + indexInLine = 0; - characterPos = l->lineStartInFile + indexInLine; - } - } + characterPos = l->lineStartInFile + indexInLine; + } + } } void CodeDocument::Position::setPosition (const int newPosition) throw() { - jassert (owner != 0); + jassert (owner != 0); - line = 0; - indexInLine = 0; - characterPos = 0; + line = 0; + indexInLine = 0; + characterPos = 0; - if (newPosition > 0) - { - int lineStart = 0; - int lineEnd = owner->lines.size(); + if (newPosition > 0) + { + int lineStart = 0; + int lineEnd = owner->lines.size(); - for (;;) - { - if (lineEnd - lineStart < 4) - { - for (int i = lineStart; i < lineEnd; ++i) - { - CodeDocumentLine* const l = owner->lines.getUnchecked (i); + for (;;) + { + if (lineEnd - lineStart < 4) + { + for (int i = lineStart; i < lineEnd; ++i) + { + CodeDocumentLine* const l = owner->lines.getUnchecked (i); - int index = newPosition - l->lineStartInFile; + int index = newPosition - l->lineStartInFile; - if (index >= 0 && (index < l->lineLength || i == lineEnd - 1)) - { - line = i; - indexInLine = jmin (l->lineLengthWithoutNewLines, index); - characterPos = l->lineStartInFile + indexInLine; - } - } + if (index >= 0 && (index < l->lineLength || i == lineEnd - 1)) + { + line = i; + indexInLine = jmin (l->lineLengthWithoutNewLines, index); + characterPos = l->lineStartInFile + indexInLine; + } + } - break; - } - else - { - const int midIndex = (lineStart + lineEnd + 1) / 2; - CodeDocumentLine* const mid = owner->lines.getUnchecked (midIndex); + break; + } + else + { + const int midIndex = (lineStart + lineEnd + 1) / 2; + CodeDocumentLine* const mid = owner->lines.getUnchecked (midIndex); - if (newPosition >= mid->lineStartInFile) - lineStart = midIndex; - else - lineEnd = midIndex; - } - } - } + if (newPosition >= mid->lineStartInFile) + lineStart = midIndex; + else + lineEnd = midIndex; + } + } + } } void CodeDocument::Position::moveBy (int characterDelta) throw() { - jassert (owner != 0); + jassert (owner != 0); - if (characterDelta == 1) - { - setPosition (getPosition()); + if (characterDelta == 1) + { + setPosition (getPosition()); - // If moving right, make sure we don't get stuck between the \r and \n characters.. - CodeDocumentLine* const l = owner->lines.getUnchecked (line); - if (indexInLine + characterDelta < l->lineLength - && indexInLine + characterDelta >= l->lineLengthWithoutNewLines + 1) - ++characterDelta; - } + // If moving right, make sure we don't get stuck between the \r and \n characters.. + CodeDocumentLine* const l = owner->lines.getUnchecked (line); + if (indexInLine + characterDelta < l->lineLength + && indexInLine + characterDelta >= l->lineLengthWithoutNewLines + 1) + ++characterDelta; + } - setPosition (characterPos + characterDelta); + setPosition (characterPos + characterDelta); } const CodeDocument::Position CodeDocument::Position::movedBy (const int characterDelta) const throw() { - CodeDocument::Position p (*this); - p.moveBy (characterDelta); - return p; + CodeDocument::Position p (*this); + p.moveBy (characterDelta); + return p; } const CodeDocument::Position CodeDocument::Position::movedByLines (const int deltaLines) const throw() { - CodeDocument::Position p (*this); - p.setLineAndIndex (getLineNumber() + deltaLines, getIndexInLine()); - return p; + CodeDocument::Position p (*this); + p.setLineAndIndex (getLineNumber() + deltaLines, getIndexInLine()); + return p; } const tchar CodeDocument::Position::getCharacter() const throw() { - const CodeDocumentLine* const l = owner->lines [line]; - return l == 0 ? 0 : l->line [getIndexInLine()]; + const CodeDocumentLine* const l = owner->lines [line]; + return l == 0 ? 0 : l->line [getIndexInLine()]; } const String CodeDocument::Position::getLineText() const throw() { - const CodeDocumentLine* const l = owner->lines [line]; - return l == 0 ? String::empty : l->line; + const CodeDocumentLine* const l = owner->lines [line]; + return l == 0 ? String::empty : l->line; } void CodeDocument::Position::setPositionMaintained (const bool isMaintained) throw() { - if (isMaintained != positionMaintained) - { - positionMaintained = isMaintained; + if (isMaintained != positionMaintained) + { + positionMaintained = isMaintained; - if (owner != 0) - { - if (isMaintained) - { - jassert (! owner->positionsToMaintain.contains (this)); - owner->positionsToMaintain.add (this); - } - else - { - jassert (owner->positionsToMaintain.contains (this)); - owner->positionsToMaintain.removeValue (this); - } - } - } + if (owner != 0) + { + if (isMaintained) + { + jassert (! owner->positionsToMaintain.contains (this)); + owner->positionsToMaintain.add (this); + } + else + { + jassert (owner->positionsToMaintain.contains (this)); + owner->positionsToMaintain.removeValue (this); + } + } + } } CodeDocument::CodeDocument() - : undoManager (INT_MAX, 10000), - currentActionIndex (0), - indexOfSavedState (-1), - maximumLineLength (-1), - newLineChars ("\r\n") + : undoManager (INT_MAX, 10000), + currentActionIndex (0), + indexOfSavedState (-1), + maximumLineLength (-1), + newLineChars ("\r\n") { } @@ -44624,445 +44307,445 @@ CodeDocument::~CodeDocument() const String CodeDocument::getAllContent() const throw() { - return getTextBetween (Position (this, 0), - Position (this, lines.size(), 0)); + return getTextBetween (Position (this, 0), + Position (this, lines.size(), 0)); } const String CodeDocument::getTextBetween (const Position& start, const Position& end) const throw() { - if (end.getPosition() <= start.getPosition()) - return String::empty; + if (end.getPosition() <= start.getPosition()) + return String::empty; - const int startLine = start.getLineNumber(); - const int endLine = end.getLineNumber(); + const int startLine = start.getLineNumber(); + const int endLine = end.getLineNumber(); - if (startLine == endLine) - { - CodeDocumentLine* const line = lines [startLine]; - return (line == 0) ? String::empty : line->line.substring (start.getIndexInLine(), end.getIndexInLine()); - } + if (startLine == endLine) + { + CodeDocumentLine* const line = lines [startLine]; + return (line == 0) ? String::empty : line->line.substring (start.getIndexInLine(), end.getIndexInLine()); + } - String result; - result.preallocateStorage (end.getPosition() - start.getPosition() + 4); - String::Concatenator concatenator (result); + String result; + result.preallocateStorage (end.getPosition() - start.getPosition() + 4); + String::Concatenator concatenator (result); - const int maxLine = jmin (lines.size() - 1, endLine); + const int maxLine = jmin (lines.size() - 1, endLine); - for (int i = jmax (0, startLine); i <= maxLine; ++i) - { - const CodeDocumentLine* line = lines.getUnchecked(i); - int len = line->lineLength; + for (int i = jmax (0, startLine); i <= maxLine; ++i) + { + const CodeDocumentLine* line = lines.getUnchecked(i); + int len = line->lineLength; - if (i == startLine) - { - const int index = start.getIndexInLine(); - concatenator.append (line->line.substring (index, len)); - } - else if (i == endLine) - { - len = end.getIndexInLine(); - concatenator.append (line->line.substring (0, len)); - } - else - { - concatenator.append (line->line); - } - } + if (i == startLine) + { + const int index = start.getIndexInLine(); + concatenator.append (line->line.substring (index, len)); + } + else if (i == endLine) + { + len = end.getIndexInLine(); + concatenator.append (line->line.substring (0, len)); + } + else + { + concatenator.append (line->line); + } + } - return result; + return result; } int CodeDocument::getNumCharacters() const throw() { - const CodeDocumentLine* const lastLine = lines.getLast(); - return (lastLine == 0) ? 0 : lastLine->lineStartInFile + lastLine->lineLength; + const CodeDocumentLine* const lastLine = lines.getLast(); + return (lastLine == 0) ? 0 : lastLine->lineStartInFile + lastLine->lineLength; } const String CodeDocument::getLine (const int lineIndex) const throw() { - const CodeDocumentLine* const line = lines [lineIndex]; - return (line == 0) ? String::empty : line->line; + const CodeDocumentLine* const line = lines [lineIndex]; + return (line == 0) ? String::empty : line->line; } int CodeDocument::getMaximumLineLength() throw() { - if (maximumLineLength < 0) - { - maximumLineLength = 0; + if (maximumLineLength < 0) + { + maximumLineLength = 0; - for (int i = lines.size(); --i >= 0;) - maximumLineLength = jmax (maximumLineLength, lines.getUnchecked(i)->lineLength); - } + for (int i = lines.size(); --i >= 0;) + maximumLineLength = jmax (maximumLineLength, lines.getUnchecked(i)->lineLength); + } - return maximumLineLength; + return maximumLineLength; } void CodeDocument::deleteSection (const Position& startPosition, const Position& endPosition) { - remove (startPosition.getPosition(), endPosition.getPosition(), true); + remove (startPosition.getPosition(), endPosition.getPosition(), true); } void CodeDocument::insertText (const Position& position, const String& text) { - insert (text, position.getPosition(), true); + insert (text, position.getPosition(), true); } void CodeDocument::replaceAllContent (const String& newContent) { - remove (0, getNumCharacters(), true); - insert (newContent, 0, true); + remove (0, getNumCharacters(), true); + insert (newContent, 0, true); } void CodeDocument::setNewLineCharacters (const String& newLine) throw() { - jassert (newLine == T("\r\n") || newLine == T("\n") || newLine == T("\r")); - newLineChars = newLine; + jassert (newLine == T("\r\n") || newLine == T("\n") || newLine == T("\r")); + newLineChars = newLine; } void CodeDocument::newTransaction() { - undoManager.beginNewTransaction (String::empty); + undoManager.beginNewTransaction (String::empty); } void CodeDocument::undo() { - newTransaction(); - undoManager.undo(); + newTransaction(); + undoManager.undo(); } void CodeDocument::redo() { - undoManager.redo(); + undoManager.redo(); } void CodeDocument::clearUndoHistory() { - undoManager.clearUndoHistory(); + undoManager.clearUndoHistory(); } void CodeDocument::setSavePoint() throw() { - indexOfSavedState = currentActionIndex; + indexOfSavedState = currentActionIndex; } bool CodeDocument::hasChangedSinceSavePoint() const throw() { - return currentActionIndex != indexOfSavedState; + return currentActionIndex != indexOfSavedState; } static int getCodeCharacterCategory (const tchar character) throw() { - return (CharacterFunctions::isLetterOrDigit (character) || character == '_') - ? 2 : (CharacterFunctions::isWhitespace (character) ? 0 : 1); + return (CharacterFunctions::isLetterOrDigit (character) || character == '_') + ? 2 : (CharacterFunctions::isWhitespace (character) ? 0 : 1); } const CodeDocument::Position CodeDocument::findWordBreakAfter (const Position& position) const throw() { - Position p (position); - const int maxDistance = 256; - int i = 0; + Position p (position); + const int maxDistance = 256; + int i = 0; - while (i < maxDistance - && CharacterFunctions::isWhitespace (p.getCharacter()) - && (i == 0 || (p.getCharacter() != T('\n') - && p.getCharacter() != T('\r')))) - { - ++i; - p.moveBy (1); - } + while (i < maxDistance + && CharacterFunctions::isWhitespace (p.getCharacter()) + && (i == 0 || (p.getCharacter() != T('\n') + && p.getCharacter() != T('\r')))) + { + ++i; + p.moveBy (1); + } - if (i == 0) - { - const int type = getCodeCharacterCategory (p.getCharacter()); + if (i == 0) + { + const int type = getCodeCharacterCategory (p.getCharacter()); - while (i < maxDistance && type == getCodeCharacterCategory (p.getCharacter())) - { - ++i; - p.moveBy (1); - } + while (i < maxDistance && type == getCodeCharacterCategory (p.getCharacter())) + { + ++i; + p.moveBy (1); + } - while (i < maxDistance - && CharacterFunctions::isWhitespace (p.getCharacter()) - && (i == 0 || (p.getCharacter() != T('\n') - && p.getCharacter() != T('\r')))) - { - ++i; - p.moveBy (1); - } - } + while (i < maxDistance + && CharacterFunctions::isWhitespace (p.getCharacter()) + && (i == 0 || (p.getCharacter() != T('\n') + && p.getCharacter() != T('\r')))) + { + ++i; + p.moveBy (1); + } + } - return p; + return p; } const CodeDocument::Position CodeDocument::findWordBreakBefore (const Position& position) const throw() { - Position p (position); - const int maxDistance = 256; - int i = 0; - bool stoppedAtLineStart = false; + Position p (position); + const int maxDistance = 256; + int i = 0; + bool stoppedAtLineStart = false; - while (i < maxDistance) - { - const tchar c = p.movedBy (-1).getCharacter(); + while (i < maxDistance) + { + const tchar c = p.movedBy (-1).getCharacter(); - if (c == T('\r') || c == T('\n')) - { - stoppedAtLineStart = true; + if (c == T('\r') || c == T('\n')) + { + stoppedAtLineStart = true; - if (i > 0) - break; - } + if (i > 0) + break; + } - if (! CharacterFunctions::isWhitespace (c)) - break; + if (! CharacterFunctions::isWhitespace (c)) + break; - p.moveBy (-1); - ++i; - } + p.moveBy (-1); + ++i; + } - if (i < maxDistance && ! stoppedAtLineStart) - { - const int type = getCodeCharacterCategory (p.movedBy (-1).getCharacter()); + if (i < maxDistance && ! stoppedAtLineStart) + { + const int type = getCodeCharacterCategory (p.movedBy (-1).getCharacter()); - while (i < maxDistance && type == getCodeCharacterCategory (p.movedBy (-1).getCharacter())) - { - p.moveBy (-1); - ++i; - } - } + while (i < maxDistance && type == getCodeCharacterCategory (p.movedBy (-1).getCharacter())) + { + p.moveBy (-1); + ++i; + } + } - return p; + return p; } void CodeDocument::addListener (CodeDocument::Listener* const listener) throw() { - listeners.addIfNotAlreadyThere (listener); + listeners.addIfNotAlreadyThere (listener); } void CodeDocument::removeListener (CodeDocument::Listener* const listener) throw() { - listeners.removeValue (listener); + listeners.removeValue (listener); } void CodeDocument::sendListenerChangeMessage (const int startLine, const int endLine) { - const Position startPos (this, startLine, 0); - const Position endPos (this, endLine, 0); + const Position startPos (this, startLine, 0); + const Position endPos (this, endLine, 0); - for (int i = listeners.size(); --i >= 0;) - { - Listener* const l = (Listener*) listeners[i]; + for (int i = listeners.size(); --i >= 0;) + { + Listener* const l = (Listener*) listeners[i]; - if (l != 0) - l->codeDocumentChanged (startPos, endPos); - } + if (l != 0) + l->codeDocumentChanged (startPos, endPos); + } } class CodeDocumentInsertAction : public UndoableAction { - CodeDocument& owner; - const String text; - int insertPos; + CodeDocument& owner; + const String text; + int insertPos; - CodeDocumentInsertAction (const CodeDocumentInsertAction&); - const CodeDocumentInsertAction& operator= (const CodeDocumentInsertAction&); + CodeDocumentInsertAction (const CodeDocumentInsertAction&); + const CodeDocumentInsertAction& operator= (const CodeDocumentInsertAction&); public: - CodeDocumentInsertAction (CodeDocument& owner_, const String& text_, const int insertPos_) throw() - : owner (owner_), - text (text_), - insertPos (insertPos_) - { - } + CodeDocumentInsertAction (CodeDocument& owner_, const String& text_, const int insertPos_) throw() + : owner (owner_), + text (text_), + insertPos (insertPos_) + { + } - ~CodeDocumentInsertAction() {} + ~CodeDocumentInsertAction() {} - bool perform() - { - owner.currentActionIndex++; - owner.insert (text, insertPos, false); - return true; - } + bool perform() + { + owner.currentActionIndex++; + owner.insert (text, insertPos, false); + return true; + } - bool undo() - { - owner.currentActionIndex--; - owner.remove (insertPos, insertPos + text.length(), false); - return true; - } + bool undo() + { + owner.currentActionIndex--; + owner.remove (insertPos, insertPos + text.length(), false); + return true; + } - int getSizeInUnits() { return text.length() + 32; } + int getSizeInUnits() { return text.length() + 32; } }; void CodeDocument::insert (const String& text, const int insertPos, const bool undoable) { - if (text.isEmpty()) - return; + if (text.isEmpty()) + return; - if (undoable) - { - undoManager.perform (new CodeDocumentInsertAction (*this, text, insertPos)); - } - else - { - Position pos (this, insertPos); - const int firstAffectedLine = pos.getLineNumber(); - int lastAffectedLine = firstAffectedLine + 1; + if (undoable) + { + undoManager.perform (new CodeDocumentInsertAction (*this, text, insertPos)); + } + else + { + Position pos (this, insertPos); + const int firstAffectedLine = pos.getLineNumber(); + int lastAffectedLine = firstAffectedLine + 1; - CodeDocumentLine* const firstLine = lines [firstAffectedLine]; - String textInsideOriginalLine (text); + CodeDocumentLine* const firstLine = lines [firstAffectedLine]; + String textInsideOriginalLine (text); - if (firstLine != 0) - { - const int index = pos.getIndexInLine(); - textInsideOriginalLine = firstLine->line.substring (0, index) - + textInsideOriginalLine - + firstLine->line.substring (index); - } + if (firstLine != 0) + { + const int index = pos.getIndexInLine(); + textInsideOriginalLine = firstLine->line.substring (0, index) + + textInsideOriginalLine + + firstLine->line.substring (index); + } - maximumLineLength = -1; - Array newLines; - CodeDocumentLine::createLines (newLines, textInsideOriginalLine); - jassert (newLines.size() > 0); + maximumLineLength = -1; + Array newLines; + CodeDocumentLine::createLines (newLines, textInsideOriginalLine); + jassert (newLines.size() > 0); - CodeDocumentLine* const newFirstLine = newLines.getUnchecked (0); - newFirstLine->lineStartInFile = firstLine != 0 ? firstLine->lineStartInFile : 0; - lines.set (firstAffectedLine, newFirstLine); + CodeDocumentLine* const newFirstLine = newLines.getUnchecked (0); + newFirstLine->lineStartInFile = firstLine != 0 ? firstLine->lineStartInFile : 0; + lines.set (firstAffectedLine, newFirstLine); - if (newLines.size() > 1) - { - for (int i = 1; i < newLines.size(); ++i) - { - CodeDocumentLine* const l = newLines.getUnchecked (i); - lines.insert (firstAffectedLine + i, l); - } + if (newLines.size() > 1) + { + for (int i = 1; i < newLines.size(); ++i) + { + CodeDocumentLine* const l = newLines.getUnchecked (i); + lines.insert (firstAffectedLine + i, l); + } - lastAffectedLine = lines.size(); - } + lastAffectedLine = lines.size(); + } - int i, lineStart = newFirstLine->lineStartInFile; - for (i = firstAffectedLine; i < lines.size(); ++i) - { - CodeDocumentLine* const l = lines.getUnchecked (i); - l->lineStartInFile = lineStart; - lineStart += l->lineLength; - } + int i, lineStart = newFirstLine->lineStartInFile; + for (i = firstAffectedLine; i < lines.size(); ++i) + { + CodeDocumentLine* const l = lines.getUnchecked (i); + l->lineStartInFile = lineStart; + lineStart += l->lineLength; + } - const int newTextLength = text.length(); - for (i = 0; i < positionsToMaintain.size(); ++i) - { - CodeDocument::Position* const p = positionsToMaintain.getUnchecked(i); + const int newTextLength = text.length(); + for (i = 0; i < positionsToMaintain.size(); ++i) + { + CodeDocument::Position* const p = positionsToMaintain.getUnchecked(i); - if (p->getPosition() >= insertPos) - p->setPosition (p->getPosition() + newTextLength); - } + if (p->getPosition() >= insertPos) + p->setPosition (p->getPosition() + newTextLength); + } - sendListenerChangeMessage (firstAffectedLine, lastAffectedLine); - } + sendListenerChangeMessage (firstAffectedLine, lastAffectedLine); + } } class CodeDocumentDeleteAction : public UndoableAction { - CodeDocument& owner; - int startPos, endPos; - String removedText; + CodeDocument& owner; + int startPos, endPos; + String removedText; - CodeDocumentDeleteAction (const CodeDocumentDeleteAction&); - const CodeDocumentDeleteAction& operator= (const CodeDocumentDeleteAction&); + CodeDocumentDeleteAction (const CodeDocumentDeleteAction&); + const CodeDocumentDeleteAction& operator= (const CodeDocumentDeleteAction&); public: - CodeDocumentDeleteAction (CodeDocument& owner_, const int startPos_, const int endPos_) throw() - : owner (owner_), - startPos (startPos_), - endPos (endPos_) - { - removedText = owner.getTextBetween (CodeDocument::Position (&owner, startPos), - CodeDocument::Position (&owner, endPos)); - } + CodeDocumentDeleteAction (CodeDocument& owner_, const int startPos_, const int endPos_) throw() + : owner (owner_), + startPos (startPos_), + endPos (endPos_) + { + removedText = owner.getTextBetween (CodeDocument::Position (&owner, startPos), + CodeDocument::Position (&owner, endPos)); + } - ~CodeDocumentDeleteAction() {} + ~CodeDocumentDeleteAction() {} - bool perform() - { - owner.currentActionIndex++; - owner.remove (startPos, endPos, false); - return true; - } + bool perform() + { + owner.currentActionIndex++; + owner.remove (startPos, endPos, false); + return true; + } - bool undo() - { - owner.currentActionIndex--; - owner.insert (removedText, startPos, false); - return true; - } + bool undo() + { + owner.currentActionIndex--; + owner.insert (removedText, startPos, false); + return true; + } - int getSizeInUnits() { return removedText.length() + 32; } + int getSizeInUnits() { return removedText.length() + 32; } }; void CodeDocument::remove (const int startPos, const int endPos, const bool undoable) { - if (endPos <= startPos) - return; + if (endPos <= startPos) + return; - if (undoable) - { - undoManager.perform (new CodeDocumentDeleteAction (*this, startPos, endPos)); - } - else - { - Position startPosition (this, startPos); - Position endPosition (this, endPos); + if (undoable) + { + undoManager.perform (new CodeDocumentDeleteAction (*this, startPos, endPos)); + } + else + { + Position startPosition (this, startPos); + Position endPosition (this, endPos); - maximumLineLength = -1; - const int firstAffectedLine = startPosition.getLineNumber(); - const int endLine = endPosition.getLineNumber(); - int lastAffectedLine = firstAffectedLine + 1; - CodeDocumentLine* const firstLine = lines.getUnchecked (firstAffectedLine); + maximumLineLength = -1; + const int firstAffectedLine = startPosition.getLineNumber(); + const int endLine = endPosition.getLineNumber(); + int lastAffectedLine = firstAffectedLine + 1; + CodeDocumentLine* const firstLine = lines.getUnchecked (firstAffectedLine); - if (firstAffectedLine == endLine) - { - firstLine->line = firstLine->line.substring (0, startPosition.getIndexInLine()) - + firstLine->line.substring (endPosition.getIndexInLine()); - firstLine->updateLength(); - } - else - { - lastAffectedLine = lines.size(); + if (firstAffectedLine == endLine) + { + firstLine->line = firstLine->line.substring (0, startPosition.getIndexInLine()) + + firstLine->line.substring (endPosition.getIndexInLine()); + firstLine->updateLength(); + } + else + { + lastAffectedLine = lines.size(); - CodeDocumentLine* const lastLine = lines.getUnchecked (endLine); - jassert (lastLine != 0); + CodeDocumentLine* const lastLine = lines.getUnchecked (endLine); + jassert (lastLine != 0); - firstLine->line = firstLine->line.substring (0, startPosition.getIndexInLine()) - + lastLine->line.substring (endPosition.getIndexInLine()); - firstLine->updateLength(); + firstLine->line = firstLine->line.substring (0, startPosition.getIndexInLine()) + + lastLine->line.substring (endPosition.getIndexInLine()); + firstLine->updateLength(); - int numLinesToRemove = endLine - firstAffectedLine; - lines.removeRange (firstAffectedLine + 1, numLinesToRemove); - } + int numLinesToRemove = endLine - firstAffectedLine; + lines.removeRange (firstAffectedLine + 1, numLinesToRemove); + } - int i; - for (i = firstAffectedLine + 1; i < lines.size(); ++i) - { - CodeDocumentLine* const l = lines.getUnchecked (i); - const CodeDocumentLine* const previousLine = lines.getUnchecked (i - 1); - l->lineStartInFile = previousLine->lineStartInFile + previousLine->lineLength; - } + int i; + for (i = firstAffectedLine + 1; i < lines.size(); ++i) + { + CodeDocumentLine* const l = lines.getUnchecked (i); + const CodeDocumentLine* const previousLine = lines.getUnchecked (i - 1); + l->lineStartInFile = previousLine->lineStartInFile + previousLine->lineLength; + } - const int totalChars = getNumCharacters(); + const int totalChars = getNumCharacters(); - for (i = 0; i < positionsToMaintain.size(); ++i) - { - CodeDocument::Position* p = positionsToMaintain.getUnchecked(i); + for (i = 0; i < positionsToMaintain.size(); ++i) + { + CodeDocument::Position* p = positionsToMaintain.getUnchecked(i); - if (p->getPosition() > startPosition.getPosition()) - p->setPosition (jmax (startPos, p->getPosition() + startPos - endPos)); + if (p->getPosition() > startPosition.getPosition()) + p->setPosition (jmax (startPos, p->getPosition() + startPos - endPos)); - if (p->getPosition() > totalChars) - p->setPosition (totalChars); - } + if (p->getPosition() > totalChars) + p->setPosition (totalChars); + } - sendListenerChangeMessage (firstAffectedLine, lastAffectedLine); - } + sendListenerChangeMessage (firstAffectedLine, lastAffectedLine); + } } END_JUCE_NAMESPACE @@ -45073,1163 +44756,1155 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE class CaretComponent : public Component, - public Timer + public Timer { public: - CaretComponent() - { - setAlwaysOnTop (true); - setInterceptsMouseClicks (false, false); - } + CaretComponent() + { + setAlwaysOnTop (true); + setInterceptsMouseClicks (false, false); + } - ~CaretComponent() - { - } + ~CaretComponent() + { + } - void paint (Graphics& g) - { - if (getParentComponent()->hasKeyboardFocus (true)) - g.fillAll (findColour (CodeEditorComponent::caretColourId)); - } + void paint (Graphics& g) + { + if (getParentComponent()->hasKeyboardFocus (true)) + g.fillAll (findColour (CodeEditorComponent::caretColourId)); + } - void timerCallback() - { - setVisible (! isVisible()); - } + void timerCallback() + { + setVisible (! isVisible()); + } - void updatePosition (CodeEditorComponent& owner) - { - startTimer (400); - setVisible (true); + void updatePosition (CodeEditorComponent& owner) + { + startTimer (400); + setVisible (true); - const Rectangle pos (owner.getCharacterBounds (owner.getCaretPos())); - setBounds (pos.getX(), pos.getY(), 2, pos.getHeight()); - } + const Rectangle pos (owner.getCharacterBounds (owner.getCaretPos())); + setBounds (pos.getX(), pos.getY(), 2, pos.getHeight()); + } }; class CodeEditorLine { public: - CodeEditorLine() throw() - { - } + CodeEditorLine() throw() + { + } - ~CodeEditorLine() throw() - { - } + ~CodeEditorLine() throw() + { + } - bool update (CodeDocument& document, int lineNum, - CodeDocument::Iterator& source, - CodeTokeniser* analyser, const int spacesPerTab, - const CodeDocument::Position& selectionStart, - const CodeDocument::Position& selectionEnd) - { - OwnedArray newTokens; + bool update (CodeDocument& document, int lineNum, + CodeDocument::Iterator& source, + CodeTokeniser* analyser, const int spacesPerTab, + const CodeDocument::Position& selectionStart, + const CodeDocument::Position& selectionEnd) + { + OwnedArray newTokens; - if (analyser == 0) - { - newTokens.add (new SyntaxToken (document.getLine (lineNum), -1)); - } - else if (lineNum < document.getNumLines()) - { - const CodeDocument::Position pos (&document, lineNum, 0); - createTokens (document, pos.getPosition(), pos.getLineText(), - source, analyser, newTokens); - } + if (analyser == 0) + { + newTokens.add (new SyntaxToken (document.getLine (lineNum), -1)); + } + else if (lineNum < document.getNumLines()) + { + const CodeDocument::Position pos (&document, lineNum, 0); + createTokens (document, pos.getPosition(), pos.getLineText(), + source, analyser, newTokens); + } - replaceTabsWithSpaces (newTokens, spacesPerTab); + replaceTabsWithSpaces (newTokens, spacesPerTab); - int newHighlightStart = 0; - int newHighlightEnd = 0; + int newHighlightStart = 0; + int newHighlightEnd = 0; - if (selectionStart.getLineNumber() <= lineNum && selectionEnd.getLineNumber() >= lineNum) - { - const String line (document.getLine (lineNum)); + if (selectionStart.getLineNumber() <= lineNum && selectionEnd.getLineNumber() >= lineNum) + { + const String line (document.getLine (lineNum)); - CodeDocument::Position lineStart (&document, lineNum, 0), lineEnd (&document, lineNum + 1, 0); - newHighlightStart = indexToColumn (jmax (0, selectionStart.getPosition() - lineStart.getPosition()), - line, spacesPerTab); - newHighlightEnd = indexToColumn (jmin (lineEnd.getPosition() - lineStart.getPosition(), selectionEnd.getPosition() - lineStart.getPosition()), - line, spacesPerTab); - } + CodeDocument::Position lineStart (&document, lineNum, 0), lineEnd (&document, lineNum + 1, 0); + newHighlightStart = indexToColumn (jmax (0, selectionStart.getPosition() - lineStart.getPosition()), + line, spacesPerTab); + newHighlightEnd = indexToColumn (jmin (lineEnd.getPosition() - lineStart.getPosition(), selectionEnd.getPosition() - lineStart.getPosition()), + line, spacesPerTab); + } - if (newHighlightStart != highlightColumnStart || newHighlightEnd != highlightColumnEnd) - { - highlightColumnStart = newHighlightStart; - highlightColumnEnd = newHighlightEnd; - } - else - { - if (tokens.size() == newTokens.size()) - { - bool allTheSame = true; + if (newHighlightStart != highlightColumnStart || newHighlightEnd != highlightColumnEnd) + { + highlightColumnStart = newHighlightStart; + highlightColumnEnd = newHighlightEnd; + } + else + { + if (tokens.size() == newTokens.size()) + { + bool allTheSame = true; - for (int i = newTokens.size(); --i >= 0;) - { - if (*tokens.getUnchecked(i) != *newTokens.getUnchecked(i)) - { - allTheSame = false; - break; - } - } + for (int i = newTokens.size(); --i >= 0;) + { + if (*tokens.getUnchecked(i) != *newTokens.getUnchecked(i)) + { + allTheSame = false; + break; + } + } - if (allTheSame) - return false; - } - } + if (allTheSame) + return false; + } + } - tokens.swapWithArray (newTokens); - return true; - } + tokens.swapWithArray (newTokens); + return true; + } - void draw (CodeEditorComponent& owner, Graphics& g, const Font& font, - float x, const int y, const int baselineOffset, const int lineHeight, - const Colour& highlightColour) const throw() - { - if (highlightColumnStart < highlightColumnEnd) - { - g.setColour (highlightColour); - g.fillRect (roundFloatToInt (x + highlightColumnStart * owner.getCharWidth()), y, - roundFloatToInt ((highlightColumnEnd - highlightColumnStart) * owner.getCharWidth()), lineHeight); - } + void draw (CodeEditorComponent& owner, Graphics& g, const Font& font, + float x, const int y, const int baselineOffset, const int lineHeight, + const Colour& highlightColour) const throw() + { + if (highlightColumnStart < highlightColumnEnd) + { + g.setColour (highlightColour); + g.fillRect (roundToInt (x + highlightColumnStart * owner.getCharWidth()), y, + roundToInt ((highlightColumnEnd - highlightColumnStart) * owner.getCharWidth()), lineHeight); + } - int lastType = INT_MIN; + int lastType = INT_MIN; - for (int i = 0; i < tokens.size(); ++i) - { - SyntaxToken* const token = tokens.getUnchecked(i); + for (int i = 0; i < tokens.size(); ++i) + { + SyntaxToken* const token = tokens.getUnchecked(i); - if (lastType != token->tokenType) - { - lastType = token->tokenType; - g.setColour (owner.getColourForTokenType (lastType)); - } + if (lastType != token->tokenType) + { + lastType = token->tokenType; + g.setColour (owner.getColourForTokenType (lastType)); + } - g.drawSingleLineText (token->text, roundFloatToInt (x), y + baselineOffset); + g.drawSingleLineText (token->text, roundToInt (x), y + baselineOffset); - if (i < tokens.size() - 1) - { - if (token->width < 0) - token->width = font.getStringWidthFloat (token->text); + if (i < tokens.size() - 1) + { + if (token->width < 0) + token->width = font.getStringWidthFloat (token->text); - x += token->width; - } - } - } + x += token->width; + } + } + } private: - struct SyntaxToken - { - String text; - int tokenType; - float width; + struct SyntaxToken + { + String text; + int tokenType; + float width; - SyntaxToken (const String& text_, const int type) throw() - : text (text_), tokenType (type), width (-1.0f) - { - } + SyntaxToken (const String& text_, const int type) throw() + : text (text_), tokenType (type), width (-1.0f) + { + } - bool operator!= (const SyntaxToken& other) const throw() - { - return text != other.text || tokenType != other.tokenType; - } - }; + bool operator!= (const SyntaxToken& other) const throw() + { + return text != other.text || tokenType != other.tokenType; + } + }; - OwnedArray tokens; - int highlightColumnStart, highlightColumnEnd; + OwnedArray tokens; + int highlightColumnStart, highlightColumnEnd; - static void createTokens (CodeDocument& document, int startPosition, const String& lineText, - CodeDocument::Iterator& source, - CodeTokeniser* analyser, - OwnedArray & newTokens) - { - CodeDocument::Iterator lastIterator (source); - const int lineLength = lineText.length(); + static void createTokens (CodeDocument& document, int startPosition, const String& lineText, + CodeDocument::Iterator& source, + CodeTokeniser* analyser, + OwnedArray & newTokens) + { + CodeDocument::Iterator lastIterator (source); + const int lineLength = lineText.length(); - for (;;) - { - int tokenType = analyser->readNextToken (source); - int tokenStart = lastIterator.getPosition(); - int tokenEnd = source.getPosition(); + for (;;) + { + int tokenType = analyser->readNextToken (source); + int tokenStart = lastIterator.getPosition(); + int tokenEnd = source.getPosition(); - if (tokenEnd <= tokenStart) - break; + if (tokenEnd <= tokenStart) + break; - tokenEnd -= startPosition; + tokenEnd -= startPosition; - if (tokenEnd > 0) - { - tokenStart -= startPosition; - newTokens.add (new SyntaxToken (lineText.substring (jmax (0, tokenStart), tokenEnd), - tokenType)); + if (tokenEnd > 0) + { + tokenStart -= startPosition; + newTokens.add (new SyntaxToken (lineText.substring (jmax (0, tokenStart), tokenEnd), + tokenType)); - if (tokenEnd >= lineLength) - break; - } + if (tokenEnd >= lineLength) + break; + } - lastIterator = source; - } + lastIterator = source; + } - source = lastIterator; - } + source = lastIterator; + } - static void replaceTabsWithSpaces (OwnedArray & tokens, const int spacesPerTab) throw() - { - int x = 0; - for (int i = 0; i < tokens.size(); ++i) - { - SyntaxToken* const t = tokens.getUnchecked(i); + static void replaceTabsWithSpaces (OwnedArray & tokens, const int spacesPerTab) throw() + { + int x = 0; + for (int i = 0; i < tokens.size(); ++i) + { + SyntaxToken* const t = tokens.getUnchecked(i); - for (;;) - { - int tabPos = t->text.indexOfChar (T('\t')); - if (tabPos < 0) - break; + for (;;) + { + int tabPos = t->text.indexOfChar (T('\t')); + if (tabPos < 0) + break; - const int spacesNeeded = spacesPerTab - ((tabPos + x) % spacesPerTab); - t->text = t->text.replaceSection (tabPos, 1, String::repeatedString (T(" "), spacesNeeded)); - } + const int spacesNeeded = spacesPerTab - ((tabPos + x) % spacesPerTab); + t->text = t->text.replaceSection (tabPos, 1, String::repeatedString (T(" "), spacesNeeded)); + } - x += t->text.length(); - } - } + x += t->text.length(); + } + } - int indexToColumn (int index, const String& line, int spacesPerTab) const throw() - { - jassert (index <= line.length()); + int indexToColumn (int index, const String& line, int spacesPerTab) const throw() + { + jassert (index <= line.length()); - int col = 0; - for (int i = 0; i < index; ++i) - { - if (line[i] != T('\t')) - ++col; - else - col += spacesPerTab - (col % spacesPerTab); - } + int col = 0; + for (int i = 0; i < index; ++i) + { + if (line[i] != T('\t')) + ++col; + else + col += spacesPerTab - (col % spacesPerTab); + } - return col; - } + return col; + } }; CodeEditorComponent::CodeEditorComponent (CodeDocument& document_, - CodeTokeniser* const codeTokeniser_) - : document (document_), - firstLineOnScreen (0), - gutter (5), - spacesPerTab (4), - lineHeight (0), - linesOnScreen (0), - columnsOnScreen (0), - scrollbarThickness (16), - useSpacesForTabs (false), - xOffset (0), - codeTokeniser (codeTokeniser_) + CodeTokeniser* const codeTokeniser_) + : document (document_), + firstLineOnScreen (0), + gutter (5), + spacesPerTab (4), + lineHeight (0), + linesOnScreen (0), + columnsOnScreen (0), + scrollbarThickness (16), + useSpacesForTabs (false), + xOffset (0), + codeTokeniser (codeTokeniser_) { - caretPos = CodeDocument::Position (&document_, 0, 0); - caretPos.setPositionMaintained (true); + caretPos = CodeDocument::Position (&document_, 0, 0); + caretPos.setPositionMaintained (true); - selectionStart = CodeDocument::Position (&document_, 0, 0); - selectionStart.setPositionMaintained (true); + selectionStart = CodeDocument::Position (&document_, 0, 0); + selectionStart.setPositionMaintained (true); - selectionEnd = CodeDocument::Position (&document_, 0, 0); - selectionEnd.setPositionMaintained (true); + selectionEnd = CodeDocument::Position (&document_, 0, 0); + selectionEnd.setPositionMaintained (true); - setOpaque (true); - setMouseCursor (MouseCursor (MouseCursor::IBeamCursor)); - setWantsKeyboardFocus (true); + setOpaque (true); + setMouseCursor (MouseCursor (MouseCursor::IBeamCursor)); + setWantsKeyboardFocus (true); - addAndMakeVisible (verticalScrollBar = new ScrollBar (true)); - verticalScrollBar->setSingleStepSize (1.0); + addAndMakeVisible (verticalScrollBar = new ScrollBar (true)); + verticalScrollBar->setSingleStepSize (1.0); - addAndMakeVisible (horizontalScrollBar = new ScrollBar (false)); - horizontalScrollBar->setSingleStepSize (1.0); + addAndMakeVisible (horizontalScrollBar = new ScrollBar (false)); + horizontalScrollBar->setSingleStepSize (1.0); - addAndMakeVisible (caret = new CaretComponent()); + addAndMakeVisible (caret = new CaretComponent()); - Font f (12.0f); - f.setTypefaceName (Font::getDefaultMonospacedFontName()); - setFont (f); + Font f (12.0f); + f.setTypefaceName (Font::getDefaultMonospacedFontName()); + setFont (f); - resetToDefaultColours(); + resetToDefaultColours(); - verticalScrollBar->addListener (this); - horizontalScrollBar->addListener (this); - document.addListener (this); + verticalScrollBar->addListener (this); + horizontalScrollBar->addListener (this); + document.addListener (this); } CodeEditorComponent::~CodeEditorComponent() { - document.removeListener (this); - deleteAllChildren(); + document.removeListener (this); + deleteAllChildren(); } void CodeEditorComponent::loadContent (const String& newContent) { - clearCachedIterators (0); - document.replaceAllContent (newContent); - document.clearUndoHistory(); - document.setSavePoint(); - caretPos.setPosition (0); - selectionStart.setPosition (0); - selectionEnd.setPosition (0); - scrollToLine (0); + clearCachedIterators (0); + document.replaceAllContent (newContent); + document.clearUndoHistory(); + document.setSavePoint(); + caretPos.setPosition (0); + selectionStart.setPosition (0); + selectionEnd.setPosition (0); + scrollToLine (0); } void CodeEditorComponent::codeDocumentChanged (const CodeDocument::Position& affectedTextStart, - const CodeDocument::Position& affectedTextEnd) + const CodeDocument::Position& affectedTextEnd) { - clearCachedIterators (affectedTextStart.getLineNumber()); + clearCachedIterators (affectedTextStart.getLineNumber()); - triggerAsyncUpdate(); + triggerAsyncUpdate(); - ((CaretComponent*) caret)->updatePosition (*this); + ((CaretComponent*) caret)->updatePosition (*this); - if (affectedTextEnd.getPosition() >= selectionStart.getPosition() - && affectedTextStart.getPosition() <= selectionEnd.getPosition()) - deselectAll(); + if (affectedTextEnd.getPosition() >= selectionStart.getPosition() + && affectedTextStart.getPosition() <= selectionEnd.getPosition()) + deselectAll(); - if (caretPos.getPosition() > affectedTextEnd.getPosition() - || caretPos.getPosition() < affectedTextStart.getPosition()) - moveCaretTo (affectedTextStart, false); + if (caretPos.getPosition() > affectedTextEnd.getPosition() + || caretPos.getPosition() < affectedTextStart.getPosition()) + moveCaretTo (affectedTextStart, false); - updateScrollBars(); + updateScrollBars(); } void CodeEditorComponent::resized() { - linesOnScreen = (getHeight() - scrollbarThickness) / lineHeight; - columnsOnScreen = (int) ((getWidth() - scrollbarThickness) / charWidth); - lines.clear(); - rebuildLineTokens(); - ((CaretComponent*) caret)->updatePosition (*this); + linesOnScreen = (getHeight() - scrollbarThickness) / lineHeight; + columnsOnScreen = (int) ((getWidth() - scrollbarThickness) / charWidth); + lines.clear(); + rebuildLineTokens(); + ((CaretComponent*) caret)->updatePosition (*this); - verticalScrollBar->setBounds (getWidth() - scrollbarThickness, 0, scrollbarThickness, getHeight() - scrollbarThickness); - horizontalScrollBar->setBounds (gutter, getHeight() - scrollbarThickness, getWidth() - scrollbarThickness - gutter, scrollbarThickness); - updateScrollBars(); + verticalScrollBar->setBounds (getWidth() - scrollbarThickness, 0, scrollbarThickness, getHeight() - scrollbarThickness); + horizontalScrollBar->setBounds (gutter, getHeight() - scrollbarThickness, getWidth() - scrollbarThickness - gutter, scrollbarThickness); + updateScrollBars(); } void CodeEditorComponent::paint (Graphics& g) { - handleUpdateNowIfNeeded(); + handleUpdateNowIfNeeded(); - g.fillAll (findColour (CodeEditorComponent::backgroundColourId)); + g.fillAll (findColour (CodeEditorComponent::backgroundColourId)); - g.reduceClipRegion (gutter, 0, verticalScrollBar->getX() - gutter, horizontalScrollBar->getY()); + g.reduceClipRegion (gutter, 0, verticalScrollBar->getX() - gutter, horizontalScrollBar->getY()); - g.setFont (font); - const int baselineOffset = (int) font.getAscent(); - const Colour defaultColour (findColour (CodeEditorComponent::defaultTextColourId)); - const Colour highlightColour (findColour (CodeEditorComponent::highlightColourId)); + g.setFont (font); + const int baselineOffset = (int) font.getAscent(); + const Colour defaultColour (findColour (CodeEditorComponent::defaultTextColourId)); + const Colour highlightColour (findColour (CodeEditorComponent::highlightColourId)); - const Rectangle clip (g.getClipBounds()); - const int firstLineToDraw = jmax (0, clip.getY() / lineHeight); - const int lastLineToDraw = jmin (lines.size(), clip.getBottom() / lineHeight + 1); + const Rectangle clip (g.getClipBounds()); + const int firstLineToDraw = jmax (0, clip.getY() / lineHeight); + const int lastLineToDraw = jmin (lines.size(), clip.getBottom() / lineHeight + 1); - for (int j = firstLineToDraw; j < lastLineToDraw; ++j) - { - lines.getUnchecked(j)->draw (*this, g, font, - (float) (gutter - xOffset * charWidth), - lineHeight * j, baselineOffset, lineHeight, - highlightColour); - } + for (int j = firstLineToDraw; j < lastLineToDraw; ++j) + { + lines.getUnchecked(j)->draw (*this, g, font, + (float) (gutter - xOffset * charWidth), + lineHeight * j, baselineOffset, lineHeight, + highlightColour); + } } void CodeEditorComponent::setScrollbarThickness (const int thickness) throw() { - if (scrollbarThickness != thickness) - { - scrollbarThickness = thickness; - resized(); - } + if (scrollbarThickness != thickness) + { + scrollbarThickness = thickness; + resized(); + } } void CodeEditorComponent::handleAsyncUpdate() { - rebuildLineTokens(); + rebuildLineTokens(); } void CodeEditorComponent::rebuildLineTokens() { - cancelPendingUpdate(); + cancelPendingUpdate(); - const int numNeeded = linesOnScreen + 1; + const int numNeeded = linesOnScreen + 1; - int minLineToRepaint = numNeeded; - int maxLineToRepaint = 0; + int minLineToRepaint = numNeeded; + int maxLineToRepaint = 0; - if (numNeeded != lines.size()) - { - lines.clear(); + if (numNeeded != lines.size()) + { + lines.clear(); - for (int i = numNeeded; --i >= 0;) - lines.add (new CodeEditorLine()); + for (int i = numNeeded; --i >= 0;) + lines.add (new CodeEditorLine()); - minLineToRepaint = 0; - maxLineToRepaint = numNeeded; - } + minLineToRepaint = 0; + maxLineToRepaint = numNeeded; + } - jassert (numNeeded == lines.size()); + jassert (numNeeded == lines.size()); - CodeDocument::Iterator source (&document); - getIteratorForPosition (CodeDocument::Position (&document, firstLineOnScreen, 0).getPosition(), source); + CodeDocument::Iterator source (&document); + getIteratorForPosition (CodeDocument::Position (&document, firstLineOnScreen, 0).getPosition(), source); - for (int i = 0; i < numNeeded; ++i) - { - CodeEditorLine* const line = lines.getUnchecked(i); + for (int i = 0; i < numNeeded; ++i) + { + CodeEditorLine* const line = lines.getUnchecked(i); - if (line->update (document, firstLineOnScreen + i, source, codeTokeniser, spacesPerTab, - selectionStart, selectionEnd)) - { - minLineToRepaint = jmin (minLineToRepaint, i); - maxLineToRepaint = jmax (maxLineToRepaint, i); - } - } + if (line->update (document, firstLineOnScreen + i, source, codeTokeniser, spacesPerTab, + selectionStart, selectionEnd)) + { + minLineToRepaint = jmin (minLineToRepaint, i); + maxLineToRepaint = jmax (maxLineToRepaint, i); + } + } - if (minLineToRepaint <= maxLineToRepaint) - { - repaint (gutter, lineHeight * minLineToRepaint - 1, - verticalScrollBar->getX() - gutter, - lineHeight * (1 + maxLineToRepaint - minLineToRepaint) + 2); - } + if (minLineToRepaint <= maxLineToRepaint) + { + repaint (gutter, lineHeight * minLineToRepaint - 1, + verticalScrollBar->getX() - gutter, + lineHeight * (1 + maxLineToRepaint - minLineToRepaint) + 2); + } } void CodeEditorComponent::moveCaretTo (const CodeDocument::Position& newPos, const bool highlighting) { - caretPos = newPos; + caretPos = newPos; - if (highlighting) - { - if (dragType == notDragging) - { - if (abs (caretPos.getPosition() - selectionStart.getPosition()) - < abs (caretPos.getPosition() - selectionEnd.getPosition())) - dragType = draggingSelectionStart; - else - dragType = draggingSelectionEnd; - } + if (highlighting) + { + if (dragType == notDragging) + { + if (abs (caretPos.getPosition() - selectionStart.getPosition()) + < abs (caretPos.getPosition() - selectionEnd.getPosition())) + dragType = draggingSelectionStart; + else + dragType = draggingSelectionEnd; + } - if (dragType == draggingSelectionStart) - { - selectionStart = caretPos; + if (dragType == draggingSelectionStart) + { + selectionStart = caretPos; - if (selectionEnd.getPosition() < selectionStart.getPosition()) - { - const CodeDocument::Position temp (selectionStart); - selectionStart = selectionEnd; - selectionEnd = temp; + if (selectionEnd.getPosition() < selectionStart.getPosition()) + { + const CodeDocument::Position temp (selectionStart); + selectionStart = selectionEnd; + selectionEnd = temp; - dragType = draggingSelectionEnd; - } - } - else - { - selectionEnd = caretPos; + dragType = draggingSelectionEnd; + } + } + else + { + selectionEnd = caretPos; - if (selectionEnd.getPosition() < selectionStart.getPosition()) - { - const CodeDocument::Position temp (selectionStart); - selectionStart = selectionEnd; - selectionEnd = temp; + if (selectionEnd.getPosition() < selectionStart.getPosition()) + { + const CodeDocument::Position temp (selectionStart); + selectionStart = selectionEnd; + selectionEnd = temp; - dragType = draggingSelectionStart; - } - } + dragType = draggingSelectionStart; + } + } - triggerAsyncUpdate(); - } - else - { - deselectAll(); - } + triggerAsyncUpdate(); + } + else + { + deselectAll(); + } - ((CaretComponent*) caret)->updatePosition (*this); - scrollToKeepCaretOnScreen(); - updateScrollBars(); + ((CaretComponent*) caret)->updatePosition (*this); + scrollToKeepCaretOnScreen(); + updateScrollBars(); } void CodeEditorComponent::deselectAll() { - if (selectionStart != selectionEnd) - triggerAsyncUpdate(); + if (selectionStart != selectionEnd) + triggerAsyncUpdate(); - selectionStart = caretPos; - selectionEnd = caretPos; + selectionStart = caretPos; + selectionEnd = caretPos; } void CodeEditorComponent::updateScrollBars() { - verticalScrollBar->setRangeLimits (0, jmax (document.getNumLines(), firstLineOnScreen + linesOnScreen)); - verticalScrollBar->setCurrentRange (firstLineOnScreen, linesOnScreen); + verticalScrollBar->setRangeLimits (0, jmax (document.getNumLines(), firstLineOnScreen + linesOnScreen)); + verticalScrollBar->setCurrentRange (firstLineOnScreen, linesOnScreen); - horizontalScrollBar->setRangeLimits (0, jmax ((double) document.getMaximumLineLength(), xOffset + columnsOnScreen)); - horizontalScrollBar->setCurrentRange (xOffset, columnsOnScreen); + horizontalScrollBar->setRangeLimits (0, jmax ((double) document.getMaximumLineLength(), xOffset + columnsOnScreen)); + horizontalScrollBar->setCurrentRange (xOffset, columnsOnScreen); } void CodeEditorComponent::scrollToLineInternal (int newFirstLineOnScreen) { - newFirstLineOnScreen = jlimit (0, jmax (0, document.getNumLines() - 1), - newFirstLineOnScreen); + newFirstLineOnScreen = jlimit (0, jmax (0, document.getNumLines() - 1), + newFirstLineOnScreen); - if (newFirstLineOnScreen != firstLineOnScreen) - { - firstLineOnScreen = newFirstLineOnScreen; - ((CaretComponent*) caret)->updatePosition (*this); + if (newFirstLineOnScreen != firstLineOnScreen) + { + firstLineOnScreen = newFirstLineOnScreen; + ((CaretComponent*) caret)->updatePosition (*this); - updateCachedIterators (firstLineOnScreen); - triggerAsyncUpdate(); - } + updateCachedIterators (firstLineOnScreen); + triggerAsyncUpdate(); + } } void CodeEditorComponent::scrollToColumnInternal (double column) { - const double newOffset = jlimit (0.0, document.getMaximumLineLength() + 3.0, column); + const double newOffset = jlimit (0.0, document.getMaximumLineLength() + 3.0, column); - if (xOffset != newOffset) - { - xOffset = newOffset; - ((CaretComponent*) caret)->updatePosition (*this); - repaint(); - } + if (xOffset != newOffset) + { + xOffset = newOffset; + ((CaretComponent*) caret)->updatePosition (*this); + repaint(); + } } void CodeEditorComponent::scrollToLine (int newFirstLineOnScreen) { - scrollToLineInternal (newFirstLineOnScreen); - updateScrollBars(); + scrollToLineInternal (newFirstLineOnScreen); + updateScrollBars(); } void CodeEditorComponent::scrollToColumn (int newFirstColumnOnScreen) { - scrollToColumnInternal (newFirstColumnOnScreen); - updateScrollBars(); + scrollToColumnInternal (newFirstColumnOnScreen); + updateScrollBars(); } void CodeEditorComponent::scrollBy (int deltaLines) { - scrollToLine (firstLineOnScreen + deltaLines); + scrollToLine (firstLineOnScreen + deltaLines); } void CodeEditorComponent::scrollToKeepCaretOnScreen() { - if (caretPos.getLineNumber() < firstLineOnScreen) - scrollBy (caretPos.getLineNumber() - firstLineOnScreen); - else if (caretPos.getLineNumber() >= firstLineOnScreen + linesOnScreen) - scrollBy (caretPos.getLineNumber() - (firstLineOnScreen + linesOnScreen - 1)); + if (caretPos.getLineNumber() < firstLineOnScreen) + scrollBy (caretPos.getLineNumber() - firstLineOnScreen); + else if (caretPos.getLineNumber() >= firstLineOnScreen + linesOnScreen) + scrollBy (caretPos.getLineNumber() - (firstLineOnScreen + linesOnScreen - 1)); - const int column = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine()); - if (column >= xOffset + columnsOnScreen - 1) - scrollToColumn (column + 1 - columnsOnScreen); - else if (column < xOffset) - scrollToColumn (column); + const int column = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine()); + if (column >= xOffset + columnsOnScreen - 1) + scrollToColumn (column + 1 - columnsOnScreen); + else if (column < xOffset) + scrollToColumn (column); } const Rectangle CodeEditorComponent::getCharacterBounds (const CodeDocument::Position& pos) const throw() { - return Rectangle (roundDoubleToInt ((gutter - xOffset * charWidth) + indexToColumn (pos.getLineNumber(), pos.getIndexInLine()) * charWidth), - (pos.getLineNumber() - firstLineOnScreen) * lineHeight, - roundFloatToInt (charWidth), - lineHeight); + return Rectangle (roundToInt ((gutter - xOffset * charWidth) + indexToColumn (pos.getLineNumber(), pos.getIndexInLine()) * charWidth), + (pos.getLineNumber() - firstLineOnScreen) * lineHeight, + roundToInt (charWidth), + lineHeight); } const CodeDocument::Position CodeEditorComponent::getPositionAt (int x, int y) { - const int line = y / lineHeight + firstLineOnScreen; - const int column = roundDoubleToInt ((x - (gutter - xOffset * charWidth)) / charWidth); - const int index = columnToIndex (line, column); + const int line = y / lineHeight + firstLineOnScreen; + const int column = roundToInt ((x - (gutter - xOffset * charWidth)) / charWidth); + const int index = columnToIndex (line, column); - return CodeDocument::Position (&document, line, index); + return CodeDocument::Position (&document, line, index); } void CodeEditorComponent::insertTextAtCaret (const String& newText) { - document.deleteSection (selectionStart, selectionEnd); + document.deleteSection (selectionStart, selectionEnd); - if (newText.isNotEmpty()) - document.insertText (caretPos, newText); + if (newText.isNotEmpty()) + document.insertText (caretPos, newText); - scrollToKeepCaretOnScreen(); + scrollToKeepCaretOnScreen(); } void CodeEditorComponent::insertTabAtCaret() { - if (CharacterFunctions::isWhitespace (caretPos.getCharacter()) - && caretPos.getLineNumber() == caretPos.movedBy (1).getLineNumber()) - { - moveCaretTo (document.findWordBreakAfter (caretPos), false); - } + if (CharacterFunctions::isWhitespace (caretPos.getCharacter()) + && caretPos.getLineNumber() == caretPos.movedBy (1).getLineNumber()) + { + moveCaretTo (document.findWordBreakAfter (caretPos), false); + } - if (useSpacesForTabs) - { - const int caretCol = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine()); - const int spacesNeeded = spacesPerTab - (caretCol % spacesPerTab); - insertTextAtCaret (String::repeatedString (T(" "), spacesNeeded)); - } - else - { - insertTextAtCaret (T("\t")); - } + if (useSpacesForTabs) + { + const int caretCol = indexToColumn (caretPos.getLineNumber(), caretPos.getIndexInLine()); + const int spacesNeeded = spacesPerTab - (caretCol % spacesPerTab); + insertTextAtCaret (String::repeatedString (T(" "), spacesNeeded)); + } + else + { + insertTextAtCaret (T("\t")); + } } void CodeEditorComponent::cut() { - insertTextAtCaret (String::empty); + insertTextAtCaret (String::empty); } void CodeEditorComponent::copy() { - newTransaction(); + newTransaction(); - const String selection (document.getTextBetween (selectionStart, selectionEnd)); + const String selection (document.getTextBetween (selectionStart, selectionEnd)); - if (selection.isNotEmpty()) - SystemClipboard::copyTextToClipboard (selection); + if (selection.isNotEmpty()) + SystemClipboard::copyTextToClipboard (selection); } void CodeEditorComponent::copyThenCut() { - copy(); - cut(); - newTransaction(); + copy(); + cut(); + newTransaction(); } void CodeEditorComponent::paste() { - newTransaction(); - const String clip (SystemClipboard::getTextFromClipboard()); + newTransaction(); + const String clip (SystemClipboard::getTextFromClipboard()); - if (clip.isNotEmpty()) - insertTextAtCaret (clip); + if (clip.isNotEmpty()) + insertTextAtCaret (clip); - newTransaction(); + newTransaction(); } void CodeEditorComponent::cursorLeft (const bool moveInWholeWordSteps, const bool selecting) { - newTransaction(); + newTransaction(); - if (moveInWholeWordSteps) - moveCaretTo (document.findWordBreakBefore (caretPos), selecting); - else - moveCaretTo (caretPos.movedBy (-1), selecting); + if (moveInWholeWordSteps) + moveCaretTo (document.findWordBreakBefore (caretPos), selecting); + else + moveCaretTo (caretPos.movedBy (-1), selecting); } void CodeEditorComponent::cursorRight (const bool moveInWholeWordSteps, const bool selecting) { - newTransaction(); + newTransaction(); - if (moveInWholeWordSteps) - moveCaretTo (document.findWordBreakAfter (caretPos), selecting); - else - moveCaretTo (caretPos.movedBy (1), selecting); + if (moveInWholeWordSteps) + moveCaretTo (document.findWordBreakAfter (caretPos), selecting); + else + moveCaretTo (caretPos.movedBy (1), selecting); } void CodeEditorComponent::cursorDown (const bool selecting) { - newTransaction(); + newTransaction(); - if (caretPos.getLineNumber() == document.getNumLines() - 1) - moveCaretTo (CodeDocument::Position (&document, INT_MAX, INT_MAX), selecting); - else - moveCaretTo (caretPos.movedByLines (1), selecting); + if (caretPos.getLineNumber() == document.getNumLines() - 1) + moveCaretTo (CodeDocument::Position (&document, INT_MAX, INT_MAX), selecting); + else + moveCaretTo (caretPos.movedByLines (1), selecting); } void CodeEditorComponent::cursorUp (const bool selecting) { - newTransaction(); + newTransaction(); - if (caretPos.getLineNumber() == 0) - moveCaretTo (CodeDocument::Position (&document, 0, 0), selecting); - else - moveCaretTo (caretPos.movedByLines (-1), selecting); + if (caretPos.getLineNumber() == 0) + moveCaretTo (CodeDocument::Position (&document, 0, 0), selecting); + else + moveCaretTo (caretPos.movedByLines (-1), selecting); } void CodeEditorComponent::pageDown (const bool selecting) { - newTransaction(); + newTransaction(); - scrollBy (jlimit (0, linesOnScreen, 1 + document.getNumLines() - firstLineOnScreen - linesOnScreen)); - moveCaretTo (caretPos.movedByLines (linesOnScreen), selecting); + scrollBy (jlimit (0, linesOnScreen, 1 + document.getNumLines() - firstLineOnScreen - linesOnScreen)); + moveCaretTo (caretPos.movedByLines (linesOnScreen), selecting); } void CodeEditorComponent::pageUp (const bool selecting) { - newTransaction(); + newTransaction(); - scrollBy (-linesOnScreen); - moveCaretTo (caretPos.movedByLines (-linesOnScreen), selecting); + scrollBy (-linesOnScreen); + moveCaretTo (caretPos.movedByLines (-linesOnScreen), selecting); } void CodeEditorComponent::scrollUp() { - newTransaction(); - scrollBy (1); + newTransaction(); + scrollBy (1); - if (caretPos.getLineNumber() < firstLineOnScreen) - moveCaretTo (caretPos.movedByLines (1), false); + if (caretPos.getLineNumber() < firstLineOnScreen) + moveCaretTo (caretPos.movedByLines (1), false); } void CodeEditorComponent::scrollDown() { - newTransaction(); - scrollBy (-1); + newTransaction(); + scrollBy (-1); - if (caretPos.getLineNumber() >= firstLineOnScreen + linesOnScreen) - moveCaretTo (caretPos.movedByLines (-1), false); + if (caretPos.getLineNumber() >= firstLineOnScreen + linesOnScreen) + moveCaretTo (caretPos.movedByLines (-1), false); } void CodeEditorComponent::goToStartOfDocument (const bool selecting) { - newTransaction(); - moveCaretTo (CodeDocument::Position (&document, 0, 0), selecting); + newTransaction(); + moveCaretTo (CodeDocument::Position (&document, 0, 0), selecting); } static int findFirstNonWhitespaceChar (const String& line) throw() { - const int len = line.length(); + const int len = line.length(); - for (int i = 0; i < len; ++i) - if (! CharacterFunctions::isWhitespace (line [i])) - return i; + for (int i = 0; i < len; ++i) + if (! CharacterFunctions::isWhitespace (line [i])) + return i; - return 0; + return 0; } void CodeEditorComponent::goToStartOfLine (const bool selecting) { - newTransaction(); + newTransaction(); - int index = findFirstNonWhitespaceChar (caretPos.getLineText()); + int index = findFirstNonWhitespaceChar (caretPos.getLineText()); - if (index >= caretPos.getIndexInLine() && caretPos.getIndexInLine() > 0) - index = 0; + if (index >= caretPos.getIndexInLine() && caretPos.getIndexInLine() > 0) + index = 0; - moveCaretTo (CodeDocument::Position (&document, caretPos.getLineNumber(), index), selecting); + moveCaretTo (CodeDocument::Position (&document, caretPos.getLineNumber(), index), selecting); } void CodeEditorComponent::goToEndOfDocument (const bool selecting) { - newTransaction(); - moveCaretTo (CodeDocument::Position (&document, INT_MAX, INT_MAX), selecting); + newTransaction(); + moveCaretTo (CodeDocument::Position (&document, INT_MAX, INT_MAX), selecting); } void CodeEditorComponent::goToEndOfLine (const bool selecting) { - newTransaction(); - moveCaretTo (CodeDocument::Position (&document, caretPos.getLineNumber(), INT_MAX), selecting); + newTransaction(); + moveCaretTo (CodeDocument::Position (&document, caretPos.getLineNumber(), INT_MAX), selecting); } void CodeEditorComponent::backspace (const bool moveInWholeWordSteps) { - if (moveInWholeWordSteps) - { - cut(); // in case something is already highlighted - moveCaretTo (document.findWordBreakBefore (caretPos), true); - } - else - { - if (selectionStart == selectionEnd) - selectionStart.moveBy (-1); - } + if (moveInWholeWordSteps) + { + cut(); // in case something is already highlighted + moveCaretTo (document.findWordBreakBefore (caretPos), true); + } + else + { + if (selectionStart == selectionEnd) + selectionStart.moveBy (-1); + } - cut(); + cut(); } void CodeEditorComponent::deleteForward (const bool moveInWholeWordSteps) { - if (moveInWholeWordSteps) - { - cut(); // in case something is already highlighted - moveCaretTo (document.findWordBreakAfter (caretPos), true); - } - else - { - if (selectionStart == selectionEnd) - selectionEnd.moveBy (1); - else - newTransaction(); - } + if (moveInWholeWordSteps) + { + cut(); // in case something is already highlighted + moveCaretTo (document.findWordBreakAfter (caretPos), true); + } + else + { + if (selectionStart == selectionEnd) + selectionEnd.moveBy (1); + else + newTransaction(); + } - cut(); + cut(); } void CodeEditorComponent::selectAll() { - newTransaction(); - moveCaretTo (CodeDocument::Position (&document, INT_MAX, INT_MAX), false); - moveCaretTo (CodeDocument::Position (&document, 0, 0), true); + newTransaction(); + moveCaretTo (CodeDocument::Position (&document, INT_MAX, INT_MAX), false); + moveCaretTo (CodeDocument::Position (&document, 0, 0), true); } void CodeEditorComponent::undo() { - document.undo(); - scrollToKeepCaretOnScreen(); + document.undo(); + scrollToKeepCaretOnScreen(); } void CodeEditorComponent::redo() { - document.redo(); - scrollToKeepCaretOnScreen(); + document.redo(); + scrollToKeepCaretOnScreen(); } void CodeEditorComponent::newTransaction() { - document.newTransaction(); - startTimer (600); + document.newTransaction(); + startTimer (600); } void CodeEditorComponent::timerCallback() { - newTransaction(); + newTransaction(); } bool CodeEditorComponent::keyPressed (const KeyPress& key) { - const bool moveInWholeWordSteps = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown(); - const bool shiftDown = key.getModifiers().isShiftDown(); + const bool moveInWholeWordSteps = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown(); + const bool shiftDown = key.getModifiers().isShiftDown(); - if (key.isKeyCode (KeyPress::leftKey)) - { - cursorLeft (moveInWholeWordSteps, shiftDown); - } - else if (key.isKeyCode (KeyPress::rightKey)) - { - cursorRight (moveInWholeWordSteps, shiftDown); - } - else if (key.isKeyCode (KeyPress::upKey)) - { - if (key.getModifiers().isCtrlDown() && ! shiftDown) - scrollDown(); + if (key.isKeyCode (KeyPress::leftKey)) + { + cursorLeft (moveInWholeWordSteps, shiftDown); + } + else if (key.isKeyCode (KeyPress::rightKey)) + { + cursorRight (moveInWholeWordSteps, shiftDown); + } + else if (key.isKeyCode (KeyPress::upKey)) + { + if (key.getModifiers().isCtrlDown() && ! shiftDown) + scrollDown(); #if JUCE_MAC - else if (key.getModifiers().isCommandDown()) - goToStartOfDocument (shiftDown); + else if (key.getModifiers().isCommandDown()) + goToStartOfDocument (shiftDown); #endif - else - cursorUp (shiftDown); - } - else if (key.isKeyCode (KeyPress::downKey)) - { - if (key.getModifiers().isCtrlDown() && ! shiftDown) - scrollUp(); + else + cursorUp (shiftDown); + } + else if (key.isKeyCode (KeyPress::downKey)) + { + if (key.getModifiers().isCtrlDown() && ! shiftDown) + scrollUp(); #if JUCE_MAC - else if (key.getModifiers().isCommandDown()) - goToEndOfDocument (shiftDown); + else if (key.getModifiers().isCommandDown()) + goToEndOfDocument (shiftDown); #endif - else - cursorDown (shiftDown); - } - else if (key.isKeyCode (KeyPress::pageDownKey)) - { - pageDown (shiftDown); - } - else if (key.isKeyCode (KeyPress::pageUpKey)) - { - pageUp (shiftDown); - } - else if (key.isKeyCode (KeyPress::homeKey)) - { - if (moveInWholeWordSteps) - goToStartOfDocument (shiftDown); - else - goToStartOfLine (shiftDown); - } - else if (key.isKeyCode (KeyPress::endKey)) - { - if (moveInWholeWordSteps) - goToEndOfDocument (shiftDown); - else - goToEndOfLine (shiftDown); - } - else if (key.isKeyCode (KeyPress::backspaceKey)) - { - backspace (moveInWholeWordSteps); - } - else if (key.isKeyCode (KeyPress::deleteKey)) - { - deleteForward (moveInWholeWordSteps); - } - else if (key == KeyPress (T('c'), ModifierKeys::commandModifier, 0)) - { - copy(); - } - else if (key == KeyPress (T('x'), ModifierKeys::commandModifier, 0)) - { - copyThenCut(); - } - else if (key == KeyPress (T('v'), ModifierKeys::commandModifier, 0)) - { - paste(); - } - else if (key == KeyPress (T('z'), ModifierKeys::commandModifier, 0)) - { - undo(); - } - else if (key == KeyPress (T('y'), ModifierKeys::commandModifier, 0) - || key == KeyPress (T('z'), ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0)) - { - redo(); - } - else if (key == KeyPress (T('a'), ModifierKeys::commandModifier, 0)) - { - selectAll(); - } - else if (key == KeyPress::tabKey || key.getTextCharacter() == '\t') - { - insertTabAtCaret(); - } - else if (key == KeyPress::returnKey) - { - newTransaction(); - insertTextAtCaret (document.getNewLineCharacters()); - } - else if (key.isKeyCode (KeyPress::escapeKey)) - { - newTransaction(); - } - else if (key.getTextCharacter() >= ' ') - { - insertTextAtCaret (String::charToString (key.getTextCharacter())); - } - else - { - return false; - } + else + cursorDown (shiftDown); + } + else if (key.isKeyCode (KeyPress::pageDownKey)) + { + pageDown (shiftDown); + } + else if (key.isKeyCode (KeyPress::pageUpKey)) + { + pageUp (shiftDown); + } + else if (key.isKeyCode (KeyPress::homeKey)) + { + if (moveInWholeWordSteps) + goToStartOfDocument (shiftDown); + else + goToStartOfLine (shiftDown); + } + else if (key.isKeyCode (KeyPress::endKey)) + { + if (moveInWholeWordSteps) + goToEndOfDocument (shiftDown); + else + goToEndOfLine (shiftDown); + } + else if (key.isKeyCode (KeyPress::backspaceKey)) + { + backspace (moveInWholeWordSteps); + } + else if (key.isKeyCode (KeyPress::deleteKey)) + { + deleteForward (moveInWholeWordSteps); + } + else if (key == KeyPress (T('c'), ModifierKeys::commandModifier, 0)) + { + copy(); + } + else if (key == KeyPress (T('x'), ModifierKeys::commandModifier, 0)) + { + copyThenCut(); + } + else if (key == KeyPress (T('v'), ModifierKeys::commandModifier, 0)) + { + paste(); + } + else if (key == KeyPress (T('z'), ModifierKeys::commandModifier, 0)) + { + undo(); + } + else if (key == KeyPress (T('y'), ModifierKeys::commandModifier, 0) + || key == KeyPress (T('z'), ModifierKeys::commandModifier | ModifierKeys::shiftModifier, 0)) + { + redo(); + } + else if (key == KeyPress (T('a'), ModifierKeys::commandModifier, 0)) + { + selectAll(); + } + else if (key == KeyPress::tabKey || key.getTextCharacter() == '\t') + { + insertTabAtCaret(); + } + else if (key == KeyPress::returnKey) + { + newTransaction(); + insertTextAtCaret (document.getNewLineCharacters()); + } + else if (key.isKeyCode (KeyPress::escapeKey)) + { + newTransaction(); + } + else if (key.getTextCharacter() >= ' ') + { + insertTextAtCaret (String::charToString (key.getTextCharacter())); + } + else + { + return false; + } - return true; + return true; } void CodeEditorComponent::mouseDown (const MouseEvent& e) { - newTransaction(); - dragType = notDragging; + newTransaction(); + dragType = notDragging; - if (! e.mods.isPopupMenu()) - { - beginDragAutoRepeat (100); - moveCaretTo (getPositionAt (e.x, e.y), e.mods.isShiftDown()); - } - else - { - /*PopupMenu m; - addPopupMenuItems (m, &e); - - const int result = m.show(); - - if (result != 0) - performPopupMenuAction (result); - */ - } + if (! e.mods.isPopupMenu()) + { + beginDragAutoRepeat (100); + moveCaretTo (getPositionAt (e.x, e.y), e.mods.isShiftDown()); + } + else + { + } } void CodeEditorComponent::mouseDrag (const MouseEvent& e) { - if (! e.mods.isPopupMenu()) - moveCaretTo (getPositionAt (e.x, e.y), true); + if (! e.mods.isPopupMenu()) + moveCaretTo (getPositionAt (e.x, e.y), true); } void CodeEditorComponent::mouseUp (const MouseEvent& e) { - newTransaction(); - beginDragAutoRepeat (0); - dragType = notDragging; + newTransaction(); + beginDragAutoRepeat (0); + dragType = notDragging; } void CodeEditorComponent::mouseDoubleClick (const MouseEvent& e) { - CodeDocument::Position tokenStart (getPositionAt (e.x, e.y)); - CodeDocument::Position tokenEnd (tokenStart); + CodeDocument::Position tokenStart (getPositionAt (e.x, e.y)); + CodeDocument::Position tokenEnd (tokenStart); - if (e.getNumberOfClicks() > 2) - { - tokenStart.setLineAndIndex (tokenStart.getLineNumber(), 0); - tokenEnd.setLineAndIndex (tokenStart.getLineNumber() + 1, 0); - } - else - { - while (CharacterFunctions::isLetterOrDigit (tokenEnd.getCharacter())) - tokenEnd.moveBy (1); + if (e.getNumberOfClicks() > 2) + { + tokenStart.setLineAndIndex (tokenStart.getLineNumber(), 0); + tokenEnd.setLineAndIndex (tokenStart.getLineNumber() + 1, 0); + } + else + { + while (CharacterFunctions::isLetterOrDigit (tokenEnd.getCharacter())) + tokenEnd.moveBy (1); - tokenStart = tokenEnd; + tokenStart = tokenEnd; - while (tokenStart.getIndexInLine() > 0 - && CharacterFunctions::isLetterOrDigit (tokenStart.movedBy (-1).getCharacter())) - tokenStart.moveBy (-1); - } + while (tokenStart.getIndexInLine() > 0 + && CharacterFunctions::isLetterOrDigit (tokenStart.movedBy (-1).getCharacter())) + tokenStart.moveBy (-1); + } - moveCaretTo (tokenEnd, false); - moveCaretTo (tokenStart, true); + moveCaretTo (tokenEnd, false); + moveCaretTo (tokenStart, true); } void CodeEditorComponent::mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY) { - verticalScrollBar->mouseWheelMove (e, 0, wheelIncrementY); - horizontalScrollBar->mouseWheelMove (e, wheelIncrementX, 0); + verticalScrollBar->mouseWheelMove (e, 0, wheelIncrementY); + horizontalScrollBar->mouseWheelMove (e, wheelIncrementX, 0); } void CodeEditorComponent::scrollBarMoved (ScrollBar* scrollBarThatHasMoved, const double newRangeStart) { - if (scrollBarThatHasMoved == verticalScrollBar) - scrollToLineInternal ((int) newRangeStart); - else - scrollToColumnInternal (newRangeStart); + if (scrollBarThatHasMoved == verticalScrollBar) + scrollToLineInternal ((int) newRangeStart); + else + scrollToColumnInternal (newRangeStart); } void CodeEditorComponent::setTabSize (const int numSpaces, const bool insertSpaces) throw() { - useSpacesForTabs = insertSpaces; + useSpacesForTabs = insertSpaces; - if (spacesPerTab != numSpaces) - { - spacesPerTab = numSpaces; - triggerAsyncUpdate(); - } + if (spacesPerTab != numSpaces) + { + spacesPerTab = numSpaces; + triggerAsyncUpdate(); + } } int CodeEditorComponent::indexToColumn (int lineNum, int index) const throw() { - const String line (document.getLine (lineNum)); - jassert (index <= line.length()); + const String line (document.getLine (lineNum)); + jassert (index <= line.length()); - int col = 0; - for (int i = 0; i < index; ++i) - { - if (line[i] != T('\t')) - ++col; - else - col += getTabSize() - (col % getTabSize()); - } + int col = 0; + for (int i = 0; i < index; ++i) + { + if (line[i] != T('\t')) + ++col; + else + col += getTabSize() - (col % getTabSize()); + } - return col; + return col; } int CodeEditorComponent::columnToIndex (int lineNum, int column) const throw() { - const String line (document.getLine (lineNum)); - const int lineLength = line.length(); + const String line (document.getLine (lineNum)); + const int lineLength = line.length(); - int i, col = 0; - for (i = 0; i < lineLength; ++i) - { - if (line[i] != T('\t')) - ++col; - else - col += getTabSize() - (col % getTabSize()); + int i, col = 0; + for (i = 0; i < lineLength; ++i) + { + if (line[i] != T('\t')) + ++col; + else + col += getTabSize() - (col % getTabSize()); - if (col > column) - break; - } + if (col > column) + break; + } - return i; + return i; } void CodeEditorComponent::setFont (const Font& newFont) { - font = newFont; - charWidth = font.getStringWidthFloat (T("0")); - lineHeight = roundFloatToInt (font.getHeight()); - resized(); + font = newFont; + charWidth = font.getStringWidthFloat (T("0")); + lineHeight = roundToInt (font.getHeight()); + resized(); } void CodeEditorComponent::resetToDefaultColours() { - coloursForTokenCategories.clear(); + coloursForTokenCategories.clear(); - if (codeTokeniser != 0) - { - for (int i = codeTokeniser->getTokenTypes().size(); --i >= 0;) - setColourForTokenType (i, codeTokeniser->getDefaultColour (i)); - } + if (codeTokeniser != 0) + { + for (int i = codeTokeniser->getTokenTypes().size(); --i >= 0;) + setColourForTokenType (i, codeTokeniser->getDefaultColour (i)); + } } void CodeEditorComponent::setColourForTokenType (const int tokenType, const Colour& colour) { - jassert (tokenType < 256); + jassert (tokenType < 256); - while (coloursForTokenCategories.size() < tokenType) - coloursForTokenCategories.add (Colours::black); + while (coloursForTokenCategories.size() < tokenType) + coloursForTokenCategories.add (Colours::black); - coloursForTokenCategories.set (tokenType, colour); - repaint(); + coloursForTokenCategories.set (tokenType, colour); + repaint(); } const Colour CodeEditorComponent::getColourForTokenType (const int tokenType) const throw() { - if (((unsigned int) tokenType) >= (unsigned int) coloursForTokenCategories.size()) - return findColour (CodeEditorComponent::defaultTextColourId); + if (((unsigned int) tokenType) >= (unsigned int) coloursForTokenCategories.size()) + return findColour (CodeEditorComponent::defaultTextColourId); - return coloursForTokenCategories.getReference (tokenType); + return coloursForTokenCategories.getReference (tokenType); } void CodeEditorComponent::clearCachedIterators (const int firstLineToBeInvalid) throw() { - for (int i = cachedIterators.size(); --i >= 0;) - if (cachedIterators.getUnchecked (i)->getLine() >= firstLineToBeInvalid) - cachedIterators.remove (i); + for (int i = cachedIterators.size(); --i >= 0;) + if (cachedIterators.getUnchecked (i)->getLine() >= firstLineToBeInvalid) + cachedIterators.remove (i); - // need to also clear the one before the invalid line - cachedIterators.removeLast(); + // need to also clear the one before the invalid line + cachedIterators.removeLast(); } void CodeEditorComponent::updateCachedIterators (int maxLineNum) { - const int maxNumCachedPositions = 5000; - const int linesBetweenCachedSources = jmax (10, document.getNumLines() / maxNumCachedPositions); + const int maxNumCachedPositions = 5000; + const int linesBetweenCachedSources = jmax (10, document.getNumLines() / maxNumCachedPositions); - if (cachedIterators.size() == 0) - cachedIterators.add (new CodeDocument::Iterator (&document)); + if (cachedIterators.size() == 0) + cachedIterators.add (new CodeDocument::Iterator (&document)); - if (codeTokeniser == 0) - return; + if (codeTokeniser == 0) + return; - for (;;) - { - CodeDocument::Iterator* last = cachedIterators.getLast(); + for (;;) + { + CodeDocument::Iterator* last = cachedIterators.getLast(); - if (last->getLine() >= maxLineNum) - break; + if (last->getLine() >= maxLineNum) + break; - CodeDocument::Iterator* t = new CodeDocument::Iterator (*last); - cachedIterators.add (t); - const int targetLine = last->getLine() + linesBetweenCachedSources; + CodeDocument::Iterator* t = new CodeDocument::Iterator (*last); + cachedIterators.add (t); + const int targetLine = last->getLine() + linesBetweenCachedSources; - for (;;) - { - codeTokeniser->readNextToken (*t); + for (;;) + { + codeTokeniser->readNextToken (*t); - if (t->getLine() >= targetLine) - break; + if (t->getLine() >= targetLine) + break; - if (t->isEOF()) - return; - } - } + if (t->isEOF()) + return; + } + } } void CodeEditorComponent::getIteratorForPosition (int position, CodeDocument::Iterator& source) { - if (codeTokeniser == 0) - return; + if (codeTokeniser == 0) + return; - for (int i = cachedIterators.size(); --i >= 0;) - { - CodeDocument::Iterator* t = cachedIterators.getUnchecked (i); - if (t->getPosition() <= position) - { - source = *t; - break; - } - } + for (int i = cachedIterators.size(); --i >= 0;) + { + CodeDocument::Iterator* t = cachedIterators.getUnchecked (i); + if (t->getPosition() <= position) + { + source = *t; + break; + } + } - while (source.getPosition() < position) - { - const CodeDocument::Iterator original (source); - codeTokeniser->readNextToken (source); + while (source.getPosition() < position) + { + const CodeDocument::Iterator original (source); + codeTokeniser->readNextToken (source); - if (source.getPosition() > position || source.isEOF()) - { - source = original; - break; - } - } + if (source.getPosition() > position || source.isEOF()) + { + source = original; + break; + } + } } END_JUCE_NAMESPACE @@ -46252,553 +45927,553 @@ namespace CppTokeniser static bool isIdentifierStart (const tchar c) throw() { - return CharacterFunctions::isLetter (c) - || c == T('_') || c == T('@'); + return CharacterFunctions::isLetter (c) + || c == T('_') || c == T('@'); } static bool isIdentifierBody (const tchar c) throw() { - return CharacterFunctions::isLetter (c) - || CharacterFunctions::isDigit (c) - || c == T('_') || c == T('@'); + return CharacterFunctions::isLetter (c) + || CharacterFunctions::isDigit (c) + || c == T('_') || c == T('@'); } static int parseIdentifier (CodeDocument::Iterator& source) throw() { - static const tchar* keywords2Char[] = - { T("if"), T("do"), T("or"), 0 }; + static const tchar* keywords2Char[] = + { T("if"), T("do"), T("or"), 0 }; - static const tchar* keywords3Char[] = - { T("for"), T("int"), T("new"), T("try"), T("xor"), T("and"), T("asm"), T("not"), 0 }; + static const tchar* keywords3Char[] = + { T("for"), T("int"), T("new"), T("try"), T("xor"), T("and"), T("asm"), T("not"), 0 }; - static const tchar* keywords4Char[] = - { T("bool"), T("void"), T("this"), T("true"), T("long"), T("else"), T("char"), - T("enum"), T("case"), T("goto"), T("auto"), 0 }; + static const tchar* keywords4Char[] = + { T("bool"), T("void"), T("this"), T("true"), T("long"), T("else"), T("char"), + T("enum"), T("case"), T("goto"), T("auto"), 0 }; - static const tchar* keywords5Char[] = - { T("while"), T("bitor"), T("break"), T("catch"), T("class"), T("compl"), T("const"), T("false"), - T("float"), T("short"), T("throw"), T("union"), T("using"), T("or_eq"), 0 }; + static const tchar* keywords5Char[] = + { T("while"), T("bitor"), T("break"), T("catch"), T("class"), T("compl"), T("const"), T("false"), + T("float"), T("short"), T("throw"), T("union"), T("using"), T("or_eq"), 0 }; - static const tchar* keywords6Char[] = - { T("return"), T("struct"), T("and_eq"), T("bitand"), T("delete"), T("double"), T("extern"), - T("friend"), T("inline"), T("not_eq"), T("public"), T("sizeof"), T("static"), T("signed"), - T("switch"), T("typeid"), T("wchar_t"), T("xor_eq"), 0}; + static const tchar* keywords6Char[] = + { T("return"), T("struct"), T("and_eq"), T("bitand"), T("delete"), T("double"), T("extern"), + T("friend"), T("inline"), T("not_eq"), T("public"), T("sizeof"), T("static"), T("signed"), + T("switch"), T("typeid"), T("wchar_t"), T("xor_eq"), 0}; - static const tchar* keywordsOther[] = - { T("const_cast"), T("continue"), T("default"), T("explicit"), T("mutable"), T("namespace"), - T("operator"), T("private"), T("protected"), T("register"), T("reinterpret_cast"), T("static_cast"), - T("template"), T("typedef"), T("typename"), T("unsigned"), T("virtual"), T("volatile"), - T("@implementation"), T("@interface"), T("@end"), T("@synthesize"), T("@dynamic"), T("@public"), - T("@private"), T("@property"), T("@protected"), T("@class"), 0 }; + static const tchar* keywordsOther[] = + { T("const_cast"), T("continue"), T("default"), T("explicit"), T("mutable"), T("namespace"), + T("operator"), T("private"), T("protected"), T("register"), T("reinterpret_cast"), T("static_cast"), + T("template"), T("typedef"), T("typename"), T("unsigned"), T("virtual"), T("volatile"), + T("@implementation"), T("@interface"), T("@end"), T("@synthesize"), T("@dynamic"), T("@public"), + T("@private"), T("@property"), T("@protected"), T("@class"), 0 }; - int tokenLength = 0; - tchar possibleIdentifier [19]; + int tokenLength = 0; + tchar possibleIdentifier [19]; - while (isIdentifierBody (source.peekNextChar())) - { - const tchar c = source.nextChar(); + while (isIdentifierBody (source.peekNextChar())) + { + const tchar c = source.nextChar(); - if (tokenLength < numElementsInArray (possibleIdentifier) - 1) - possibleIdentifier [tokenLength] = c; + if (tokenLength < numElementsInArray (possibleIdentifier) - 1) + possibleIdentifier [tokenLength] = c; - ++tokenLength; - } + ++tokenLength; + } - if (tokenLength > 1 && tokenLength <= 16) - { - possibleIdentifier [tokenLength] = 0; - const tchar** k; + if (tokenLength > 1 && tokenLength <= 16) + { + possibleIdentifier [tokenLength] = 0; + const tchar** k; - switch (tokenLength) - { - case 2: k = keywords2Char; break; - case 3: k = keywords3Char; break; - case 4: k = keywords4Char; break; - case 5: k = keywords5Char; break; - case 6: k = keywords6Char; break; - default: k = keywordsOther; break; - } + switch (tokenLength) + { + case 2: k = keywords2Char; break; + case 3: k = keywords3Char; break; + case 4: k = keywords4Char; break; + case 5: k = keywords5Char; break; + case 6: k = keywords6Char; break; + default: k = keywordsOther; break; + } - int i = 0; - while (k[i] != 0) - { - if (k[i][0] == possibleIdentifier[0] && CharacterFunctions::compare (k[i], possibleIdentifier) == 0) - return CPlusPlusCodeTokeniser::tokenType_builtInKeyword; + int i = 0; + while (k[i] != 0) + { + if (k[i][0] == possibleIdentifier[0] && CharacterFunctions::compare (k[i], possibleIdentifier) == 0) + return CPlusPlusCodeTokeniser::tokenType_builtInKeyword; - ++i; - } - } + ++i; + } + } - return CPlusPlusCodeTokeniser::tokenType_identifier; + return CPlusPlusCodeTokeniser::tokenType_identifier; } static bool skipNumberSuffix (CodeDocument::Iterator& source) { - const juce_wchar c = source.peekNextChar(); - if (c == 'l' || c == 'L' || c == 'u' || c == 'U') - source.skip(); + const juce_wchar c = source.peekNextChar(); + if (c == 'l' || c == 'L' || c == 'u' || c == 'U') + source.skip(); - if (CharacterFunctions::isLetterOrDigit (source.peekNextChar())) - return false; + if (CharacterFunctions::isLetterOrDigit (source.peekNextChar())) + return false; - return true; + return true; } static bool isHexDigit (const juce_wchar c) throw() { - return (c >= '0' && c <= '9') - || (c >= 'a' && c <= 'f') - || (c >= 'A' && c <= 'F'); + return (c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F'); } static bool parseHexLiteral (CodeDocument::Iterator& source) throw() { - if (source.nextChar() != '0') - return false; + if (source.nextChar() != '0') + return false; - juce_wchar c = source.nextChar(); - if (c != 'x' && c != 'X') - return false; + juce_wchar c = source.nextChar(); + if (c != 'x' && c != 'X') + return false; - int numDigits = 0; - while (isHexDigit (source.peekNextChar())) - { - ++numDigits; - source.skip(); - } + int numDigits = 0; + while (isHexDigit (source.peekNextChar())) + { + ++numDigits; + source.skip(); + } - if (numDigits == 0) - return false; + if (numDigits == 0) + return false; - return skipNumberSuffix (source); + return skipNumberSuffix (source); } static bool isOctalDigit (const juce_wchar c) throw() { - return c >= '0' && c <= '7'; + return c >= '0' && c <= '7'; } static bool parseOctalLiteral (CodeDocument::Iterator& source) throw() { - if (source.nextChar() != '0') - return false; + if (source.nextChar() != '0') + return false; - if (! isOctalDigit (source.nextChar())) - return false; + if (! isOctalDigit (source.nextChar())) + return false; - while (isOctalDigit (source.peekNextChar())) - source.skip(); + while (isOctalDigit (source.peekNextChar())) + source.skip(); - return skipNumberSuffix (source); + return skipNumberSuffix (source); } static bool isDecimalDigit (const juce_wchar c) throw() { - return c >= '0' && c <= '9'; + return c >= '0' && c <= '9'; } static bool parseDecimalLiteral (CodeDocument::Iterator& source) throw() { - int numChars = 0; - while (isDecimalDigit (source.peekNextChar())) - { - ++numChars; - source.skip(); - } + int numChars = 0; + while (isDecimalDigit (source.peekNextChar())) + { + ++numChars; + source.skip(); + } - if (numChars == 0) - return false; + if (numChars == 0) + return false; - return skipNumberSuffix (source); + return skipNumberSuffix (source); } static bool parseFloatLiteral (CodeDocument::Iterator& source) throw() { - int numDigits = 0; + int numDigits = 0; - while (isDecimalDigit (source.peekNextChar())) - { - source.skip(); - ++numDigits; - } + while (isDecimalDigit (source.peekNextChar())) + { + source.skip(); + ++numDigits; + } - const bool hasPoint = (source.peekNextChar() == '.'); + const bool hasPoint = (source.peekNextChar() == '.'); - if (hasPoint) - { - source.skip(); + if (hasPoint) + { + source.skip(); - while (isDecimalDigit (source.peekNextChar())) - { - source.skip(); - ++numDigits; - } - } + while (isDecimalDigit (source.peekNextChar())) + { + source.skip(); + ++numDigits; + } + } - if (numDigits == 0) - return false; + if (numDigits == 0) + return false; - juce_wchar c = source.peekNextChar(); - const bool hasExponent = (c == 'e' || c == 'E'); + juce_wchar c = source.peekNextChar(); + const bool hasExponent = (c == 'e' || c == 'E'); - if (hasExponent) - { - source.skip(); + if (hasExponent) + { + source.skip(); - c = source.peekNextChar(); - if (c == '+' || c == '-') - source.skip(); + c = source.peekNextChar(); + if (c == '+' || c == '-') + source.skip(); - int numExpDigits = 0; - while (isDecimalDigit (source.peekNextChar())) - { - source.skip(); - ++numExpDigits; - } + int numExpDigits = 0; + while (isDecimalDigit (source.peekNextChar())) + { + source.skip(); + ++numExpDigits; + } - if (numExpDigits == 0) - return false; - } + if (numExpDigits == 0) + return false; + } - c = source.peekNextChar(); - if (c == 'f' || c == 'F') - source.skip(); - else if (! (hasExponent || hasPoint)) - return false; + c = source.peekNextChar(); + if (c == 'f' || c == 'F') + source.skip(); + else if (! (hasExponent || hasPoint)) + return false; - return true; + return true; } static int parseNumber (CodeDocument::Iterator& source) { - const CodeDocument::Iterator original (source); + const CodeDocument::Iterator original (source); - if (parseFloatLiteral (source)) - return CPlusPlusCodeTokeniser::tokenType_floatLiteral; + if (parseFloatLiteral (source)) + return CPlusPlusCodeTokeniser::tokenType_floatLiteral; - source = original; + source = original; - if (parseHexLiteral (source)) - return CPlusPlusCodeTokeniser::tokenType_integerLiteral; + if (parseHexLiteral (source)) + return CPlusPlusCodeTokeniser::tokenType_integerLiteral; - source = original; + source = original; - if (parseOctalLiteral (source)) - return CPlusPlusCodeTokeniser::tokenType_integerLiteral; + if (parseOctalLiteral (source)) + return CPlusPlusCodeTokeniser::tokenType_integerLiteral; - source = original; + source = original; - if (parseDecimalLiteral (source)) - return CPlusPlusCodeTokeniser::tokenType_integerLiteral; + if (parseDecimalLiteral (source)) + return CPlusPlusCodeTokeniser::tokenType_integerLiteral; - source = original; - source.skip(); + source = original; + source.skip(); - return CPlusPlusCodeTokeniser::tokenType_error; + return CPlusPlusCodeTokeniser::tokenType_error; } static void skipQuotedString (CodeDocument::Iterator& source) throw() { - const juce_wchar quote = source.nextChar(); + const juce_wchar quote = source.nextChar(); - for (;;) - { - const juce_wchar c = source.nextChar(); + for (;;) + { + const juce_wchar c = source.nextChar(); - if (c == quote || c == 0) - break; + if (c == quote || c == 0) + break; - if (c == '\\') - source.skip(); - } + if (c == '\\') + source.skip(); + } } static void skipComment (CodeDocument::Iterator& source) throw() { - bool lastWasStar = false; + bool lastWasStar = false; - for (;;) - { - const juce_wchar c = source.nextChar(); + for (;;) + { + const juce_wchar c = source.nextChar(); - if (c == 0 || (c == T('/') && lastWasStar)) - break; + if (c == 0 || (c == T('/') && lastWasStar)) + break; - lastWasStar = (c == '*'); - } + lastWasStar = (c == '*'); + } } } int CPlusPlusCodeTokeniser::readNextToken (CodeDocument::Iterator& source) { - int result = tokenType_error; - source.skipWhitespace(); + int result = tokenType_error; + source.skipWhitespace(); - tchar firstChar = source.peekNextChar(); + tchar firstChar = source.peekNextChar(); - switch (firstChar) - { - case 0: - source.skip(); - break; + switch (firstChar) + { + case 0: + source.skip(); + break; - case T('0'): - case T('1'): - case T('2'): - case T('3'): - case T('4'): - case T('5'): - case T('6'): - case T('7'): - case T('8'): - case T('9'): - result = CppTokeniser::parseNumber (source); - break; + case T('0'): + case T('1'): + case T('2'): + case T('3'): + case T('4'): + case T('5'): + case T('6'): + case T('7'): + case T('8'): + case T('9'): + result = CppTokeniser::parseNumber (source); + break; - case T('.'): - result = CppTokeniser::parseNumber (source); + case T('.'): + result = CppTokeniser::parseNumber (source); - if (result == tokenType_error) - result = tokenType_punctuation; + if (result == tokenType_error) + result = tokenType_punctuation; - break; + break; - case T(','): - case T(';'): - case T(':'): - source.skip(); - result = tokenType_punctuation; - break; + case T(','): + case T(';'): + case T(':'): + source.skip(); + result = tokenType_punctuation; + break; - case T('('): - case T(')'): - case T('{'): - case T('}'): - case T('['): - case T(']'): - source.skip(); - result = tokenType_bracket; - break; + case T('('): + case T(')'): + case T('{'): + case T('}'): + case T('['): + case T(']'): + source.skip(); + result = tokenType_bracket; + break; - case T('"'): - case T('\''): - CppTokeniser::skipQuotedString (source); - result = tokenType_stringLiteral; - break; + case T('"'): + case T('\''): + CppTokeniser::skipQuotedString (source); + result = tokenType_stringLiteral; + break; - case T('+'): - result = tokenType_operator; - source.skip(); + case T('+'): + result = tokenType_operator; + source.skip(); - if (source.peekNextChar() == T('+')) - source.skip(); - else if (source.peekNextChar() == T('=')) - source.skip(); + if (source.peekNextChar() == T('+')) + source.skip(); + else if (source.peekNextChar() == T('=')) + source.skip(); - break; + break; - case T('-'): - source.skip(); - result = CppTokeniser::parseNumber (source); + case T('-'): + source.skip(); + result = CppTokeniser::parseNumber (source); - if (result == tokenType_error) - { - result = tokenType_operator; + if (result == tokenType_error) + { + result = tokenType_operator; - if (source.peekNextChar() == T('-')) - source.skip(); - else if (source.peekNextChar() == T('=')) - source.skip(); - } - break; + if (source.peekNextChar() == T('-')) + source.skip(); + else if (source.peekNextChar() == T('=')) + source.skip(); + } + break; - case T('*'): - case T('%'): - case T('='): - case T('!'): - result = tokenType_operator; - source.skip(); + case T('*'): + case T('%'): + case T('='): + case T('!'): + result = tokenType_operator; + source.skip(); - if (source.peekNextChar() == T('=')) - source.skip(); + if (source.peekNextChar() == T('=')) + source.skip(); - break; + break; - case T('/'): - result = tokenType_operator; - source.skip(); + case T('/'): + result = tokenType_operator; + source.skip(); - if (source.peekNextChar() == T('=')) - { - source.skip(); - } - else if (source.peekNextChar() == T('/')) - { - result = tokenType_comment; - source.skipToEndOfLine(); - } - else if (source.peekNextChar() == T('*')) - { - source.skip(); - result = tokenType_comment; - CppTokeniser::skipComment (source); - } + if (source.peekNextChar() == T('=')) + { + source.skip(); + } + else if (source.peekNextChar() == T('/')) + { + result = tokenType_comment; + source.skipToEndOfLine(); + } + else if (source.peekNextChar() == T('*')) + { + source.skip(); + result = tokenType_comment; + CppTokeniser::skipComment (source); + } - break; + break; - case T('?'): - case T('~'): - source.skip(); - result = tokenType_operator; - break; + case T('?'): + case T('~'): + source.skip(); + result = tokenType_operator; + break; - case T('<'): - source.skip(); - result = tokenType_operator; + case T('<'): + source.skip(); + result = tokenType_operator; - if (source.peekNextChar() == T('=')) - { - source.skip(); - } - else if (source.peekNextChar() == T('<')) - { - source.skip(); + if (source.peekNextChar() == T('=')) + { + source.skip(); + } + else if (source.peekNextChar() == T('<')) + { + source.skip(); - if (source.peekNextChar() == T('=')) - source.skip(); - } + if (source.peekNextChar() == T('=')) + source.skip(); + } - break; + break; - case T('>'): - source.skip(); - result = tokenType_operator; + case T('>'): + source.skip(); + result = tokenType_operator; - if (source.peekNextChar() == T('=')) - { - source.skip(); - } - else if (source.peekNextChar() == T('<')) - { - source.skip(); + if (source.peekNextChar() == T('=')) + { + source.skip(); + } + else if (source.peekNextChar() == T('<')) + { + source.skip(); - if (source.peekNextChar() == T('=')) - source.skip(); - } + if (source.peekNextChar() == T('=')) + source.skip(); + } - break; + break; - case T('|'): - source.skip(); - result = tokenType_operator; + case T('|'): + source.skip(); + result = tokenType_operator; - if (source.peekNextChar() == T('=')) - { - source.skip(); - } - else if (source.peekNextChar() == T('|')) - { - source.skip(); + if (source.peekNextChar() == T('=')) + { + source.skip(); + } + else if (source.peekNextChar() == T('|')) + { + source.skip(); - if (source.peekNextChar() == T('=')) - source.skip(); - } + if (source.peekNextChar() == T('=')) + source.skip(); + } - break; + break; - case T('&'): - source.skip(); - result = tokenType_operator; + case T('&'): + source.skip(); + result = tokenType_operator; - if (source.peekNextChar() == T('=')) - { - source.skip(); - } - else if (source.peekNextChar() == T('&')) - { - source.skip(); + if (source.peekNextChar() == T('=')) + { + source.skip(); + } + else if (source.peekNextChar() == T('&')) + { + source.skip(); - if (source.peekNextChar() == T('=')) - source.skip(); - } + if (source.peekNextChar() == T('=')) + source.skip(); + } - break; + break; - case T('^'): - source.skip(); - result = tokenType_operator; + case T('^'): + source.skip(); + result = tokenType_operator; - if (source.peekNextChar() == T('=')) - { - source.skip(); - } - else if (source.peekNextChar() == T('^')) - { - source.skip(); + if (source.peekNextChar() == T('=')) + { + source.skip(); + } + else if (source.peekNextChar() == T('^')) + { + source.skip(); - if (source.peekNextChar() == T('=')) - source.skip(); - } + if (source.peekNextChar() == T('=')) + source.skip(); + } - break; + break; - case T('#'): - result = tokenType_preprocessor; - source.skipToEndOfLine(); - break; + case T('#'): + result = tokenType_preprocessor; + source.skipToEndOfLine(); + break; - default: - if (CppTokeniser::isIdentifierStart (firstChar)) - result = CppTokeniser::parseIdentifier (source); - else - source.skip(); + default: + if (CppTokeniser::isIdentifierStart (firstChar)) + result = CppTokeniser::parseIdentifier (source); + else + source.skip(); - break; - } + break; + } - //jassert (result != tokenType_unknown); - return result; + //jassert (result != tokenType_unknown); + return result; } const StringArray CPlusPlusCodeTokeniser::getTokenTypes() { - StringArray s; - s.add ("Error"); - s.add ("Comment"); - s.add ("C++ keyword"); - s.add ("Identifier"); - s.add ("Integer literal"); - s.add ("Float literal"); - s.add ("String literal"); - s.add ("Operator"); - s.add ("Bracket"); - s.add ("Punctuation"); - s.add ("Preprocessor line"); - return s; + StringArray s; + s.add ("Error"); + s.add ("Comment"); + s.add ("C++ keyword"); + s.add ("Identifier"); + s.add ("Integer literal"); + s.add ("Float literal"); + s.add ("String literal"); + s.add ("Operator"); + s.add ("Bracket"); + s.add ("Punctuation"); + s.add ("Preprocessor line"); + return s; } const Colour CPlusPlusCodeTokeniser::getDefaultColour (const int tokenType) { - const uint32 colours[] = - { - 0xffcc0000, // error - 0xff00aa00, // comment - 0xff0000cc, // keyword - 0xff000000, // identifier - 0xff880000, // int literal - 0xff885500, // float literal - 0xff990099, // string literal - 0xff225500, // operator - 0xff000055, // bracket - 0xff004400, // punctuation - 0xff660000 // preprocessor - }; + const uint32 colours[] = + { + 0xffcc0000, // error + 0xff00aa00, // comment + 0xff0000cc, // keyword + 0xff000000, // identifier + 0xff880000, // int literal + 0xff885500, // float literal + 0xff990099, // string literal + 0xff225500, // operator + 0xff000055, // bracket + 0xff004400, // punctuation + 0xff660000 // preprocessor + }; - if (tokenType >= 0 && tokenType < numElementsInArray (colours)) - return Colour (colours [tokenType]); + if (tokenType >= 0 && tokenType < numElementsInArray (colours)) + return Colour (colours [tokenType]); - return Colours::black; + return Colours::black; } END_JUCE_NAMESPACE @@ -46809,559 +46484,578 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ComboBox::ComboBox (const String& name) - : Component (name), - items (4), - currentIndex (-1), - isButtonDown (false), - separatorPending (false), - menuActive (false), - listeners (2), - label (0) + : Component (name), + lastCurrentId (0), + isButtonDown (false), + separatorPending (false), + menuActive (false), + label (0) { - noChoicesMessage = TRANS("(no choices)"); - setRepaintsOnMouseActivity (true); + noChoicesMessage = TRANS("(no choices)"); + setRepaintsOnMouseActivity (true); - lookAndFeelChanged(); + lookAndFeelChanged(); + + currentId.addListener (this); } ComboBox::~ComboBox() { - if (menuActive) - PopupMenu::dismissAllActiveMenus(); + currentId.removeListener (this); - deleteAllChildren(); + if (menuActive) + PopupMenu::dismissAllActiveMenus(); + + deleteAllChildren(); } void ComboBox::setEditableText (const bool isEditable) { - label->setEditable (isEditable, isEditable, false); + label->setEditable (isEditable, isEditable, false); - setWantsKeyboardFocus (! isEditable); - resized(); + setWantsKeyboardFocus (! isEditable); + resized(); } bool ComboBox::isTextEditable() const throw() { - return label->isEditable(); + return label->isEditable(); } void ComboBox::setJustificationType (const Justification& justification) throw() { - label->setJustificationType (justification); + label->setJustificationType (justification); } const Justification ComboBox::getJustificationType() const throw() { - return label->getJustificationType(); + return label->getJustificationType(); } void ComboBox::setTooltip (const String& newTooltip) { - SettableTooltipClient::setTooltip (newTooltip); - label->setTooltip (newTooltip); + SettableTooltipClient::setTooltip (newTooltip); + label->setTooltip (newTooltip); } void ComboBox::addItem (const String& newItemText, - const int newItemId) throw() + const int newItemId) throw() { - // you can't add empty strings to the list.. - jassert (newItemText.isNotEmpty()); + // you can't add empty strings to the list.. + jassert (newItemText.isNotEmpty()); - // IDs must be non-zero, as zero is used to indicate a lack of selecion. - jassert (newItemId != 0); + // IDs must be non-zero, as zero is used to indicate a lack of selecion. + jassert (newItemId != 0); - // you shouldn't use duplicate item IDs! - jassert (getItemForId (newItemId) == 0); + // you shouldn't use duplicate item IDs! + jassert (getItemForId (newItemId) == 0); - if (newItemText.isNotEmpty() && newItemId != 0) - { - if (separatorPending) - { - separatorPending = false; + if (newItemText.isNotEmpty() && newItemId != 0) + { + if (separatorPending) + { + separatorPending = false; - ItemInfo* const item = new ItemInfo(); - item->itemId = 0; - item->isEnabled = false; - item->isHeading = false; - items.add (item); - } + ItemInfo* const item = new ItemInfo(); + item->itemId = 0; + item->isEnabled = false; + item->isHeading = false; + items.add (item); + } - ItemInfo* const item = new ItemInfo(); - item->name = newItemText; - item->itemId = newItemId; - item->isEnabled = true; - item->isHeading = false; - items.add (item); - } + ItemInfo* const item = new ItemInfo(); + item->name = newItemText; + item->itemId = newItemId; + item->isEnabled = true; + item->isHeading = false; + items.add (item); + } } void ComboBox::addSeparator() throw() { - separatorPending = (items.size() > 0); + separatorPending = (items.size() > 0); } void ComboBox::addSectionHeading (const String& headingName) throw() { - // you can't add empty strings to the list.. - jassert (headingName.isNotEmpty()); + // you can't add empty strings to the list.. + jassert (headingName.isNotEmpty()); - if (headingName.isNotEmpty()) - { - if (separatorPending) - { - separatorPending = false; + if (headingName.isNotEmpty()) + { + if (separatorPending) + { + separatorPending = false; - ItemInfo* const item = new ItemInfo(); - item->itemId = 0; - item->isEnabled = false; - item->isHeading = false; - items.add (item); - } + ItemInfo* const item = new ItemInfo(); + item->itemId = 0; + item->isEnabled = false; + item->isHeading = false; + items.add (item); + } - ItemInfo* const item = new ItemInfo(); - item->name = headingName; - item->itemId = 0; - item->isEnabled = true; - item->isHeading = true; - items.add (item); - } + ItemInfo* const item = new ItemInfo(); + item->name = headingName; + item->itemId = 0; + item->isEnabled = true; + item->isHeading = true; + items.add (item); + } } void ComboBox::setItemEnabled (const int itemId, - const bool shouldBeEnabled) throw() + const bool shouldBeEnabled) throw() { - ItemInfo* const item = getItemForId (itemId); + ItemInfo* const item = getItemForId (itemId); - if (item != 0) - item->isEnabled = shouldBeEnabled; + if (item != 0) + item->isEnabled = shouldBeEnabled; } void ComboBox::changeItemText (const int itemId, - const String& newText) throw() + const String& newText) throw() { - ItemInfo* const item = getItemForId (itemId); + ItemInfo* const item = getItemForId (itemId); - jassert (item != 0); + jassert (item != 0); - if (item != 0) - item->name = newText; + if (item != 0) + item->name = newText; } void ComboBox::clear (const bool dontSendChangeMessage) { - items.clear(); - separatorPending = false; + items.clear(); + separatorPending = false; - if (! label->isEditable()) - setSelectedItemIndex (-1, dontSendChangeMessage); -} - -ComboBox::ItemInfo* ComboBox::getItemForId (const int itemId) const throw() -{ - jassert (itemId != 0); - - if (itemId != 0) - { - for (int i = items.size(); --i >= 0;) - if (items.getUnchecked(i)->itemId == itemId) - return items.getUnchecked(i); - } - - return 0; -} - -ComboBox::ItemInfo* ComboBox::getItemForIndex (const int index) const throw() -{ - int n = 0; - - for (int i = 0; i < items.size(); ++i) - { - ItemInfo* const item = items.getUnchecked(i); - - if (item->isRealItem()) - { - if (n++ == index) - return item; - } - } - - return 0; -} - -int ComboBox::getNumItems() const throw() -{ - int n = 0; - - for (int i = items.size(); --i >= 0;) - { - ItemInfo* const item = items.getUnchecked(i); - - if (item->isRealItem()) - ++n; - } - - return n; -} - -const String ComboBox::getItemText (const int index) const throw() -{ - ItemInfo* const item = getItemForIndex (index); - - if (item != 0) - return item->name; - - return String::empty; -} - -int ComboBox::getItemId (const int index) const throw() -{ - ItemInfo* const item = getItemForIndex (index); - - return (item != 0) ? item->itemId : 0; + if (! label->isEditable()) + setSelectedItemIndex (-1, dontSendChangeMessage); } bool ComboBox::ItemInfo::isSeparator() const throw() { - return name.isEmpty(); + return name.isEmpty(); } bool ComboBox::ItemInfo::isRealItem() const throw() { - return ! (isHeading || name.isEmpty()); + return ! (isHeading || name.isEmpty()); +} + +ComboBox::ItemInfo* ComboBox::getItemForId (const int itemId) const throw() +{ + if (itemId != 0) + { + for (int i = items.size(); --i >= 0;) + if (items.getUnchecked(i)->itemId == itemId) + return items.getUnchecked(i); + } + + return 0; +} + +ComboBox::ItemInfo* ComboBox::getItemForIndex (const int index) const throw() +{ + int n = 0; + + for (int i = 0; i < items.size(); ++i) + { + ItemInfo* const item = items.getUnchecked(i); + + if (item->isRealItem()) + if (n++ == index) + return item; + } + + return 0; +} + +int ComboBox::getNumItems() const throw() +{ + int n = 0; + + for (int i = items.size(); --i >= 0;) + if (items.getUnchecked(i)->isRealItem()) + ++n; + + return n; +} + +const String ComboBox::getItemText (const int index) const throw() +{ + const ItemInfo* const item = getItemForIndex (index); + + if (item != 0) + return item->name; + + return String::empty; +} + +int ComboBox::getItemId (const int index) const throw() +{ + const ItemInfo* const item = getItemForIndex (index); + + return (item != 0) ? item->itemId : 0; +} + +int ComboBox::indexOfItemId (const int itemId) const throw() +{ + int n = 0; + + for (int i = 0; i < items.size(); ++i) + { + const ItemInfo* const item = items.getUnchecked(i); + + if (item->isRealItem()) + { + if (item->itemId == itemId) + return n; + + ++n; + } + } + + return -1; } int ComboBox::getSelectedItemIndex() const throw() { - return (currentIndex >= 0 && getText() == getItemText (currentIndex)) - ? currentIndex - : -1; + int index = indexOfItemId (currentId.getValue()); + + if (getText() != getItemText (index)) + index = -1; + + return index; } void ComboBox::setSelectedItemIndex (const int index, - const bool dontSendChangeMessage) throw() + const bool dontSendChangeMessage) throw() { - if (currentIndex != index || label->getText() != getItemText (currentIndex)) - { - if (((unsigned int) index) < (unsigned int) getNumItems()) - currentIndex = index; - else - currentIndex = -1; - - label->setText (getItemText (currentIndex), false); - - if (! dontSendChangeMessage) - triggerAsyncUpdate(); - } -} - -void ComboBox::setSelectedId (const int newItemId, - const bool dontSendChangeMessage) throw() -{ - for (int i = getNumItems(); --i >= 0;) - { - if (getItemId(i) == newItemId) - { - setSelectedItemIndex (i, dontSendChangeMessage); - break; - } - } + setSelectedId (getItemId (index), dontSendChangeMessage); } int ComboBox::getSelectedId() const throw() { - const ItemInfo* const item = getItemForIndex (currentIndex); + const ItemInfo* const item = getItemForId (currentId.getValue()); - return (item != 0 && getText() == item->name) - ? item->itemId - : 0; + return (item != 0 && getText() == item->name) + ? item->itemId + : 0; } -void ComboBox::addListener (ComboBoxListener* const listener) throw() +void ComboBox::setSelectedId (const int newItemId, + const bool dontSendChangeMessage) throw() { - jassert (listener != 0); - if (listener != 0) - listeners.add (listener); + const ItemInfo* const item = getItemForId (newItemId); + const String newItemText (item != 0 ? item->name : String::empty); + + if (lastCurrentId != newItemId || label->getText() != newItemText) + { + if (! dontSendChangeMessage) + triggerAsyncUpdate(); + + label->setText (newItemText, false); + lastCurrentId = newItemId; + currentId = newItemId; + + repaint(); // for the benefit of the 'none selected' text + } } -void ComboBox::removeListener (ComboBoxListener* const listener) throw() +void ComboBox::valueChanged (Value&) { - listeners.removeValue (listener); -} - -void ComboBox::handleAsyncUpdate() -{ - for (int i = listeners.size(); --i >= 0;) - { - ((ComboBoxListener*) listeners.getUnchecked (i))->comboBoxChanged (this); - i = jmin (i, listeners.size()); - } + if (lastCurrentId != (int) currentId.getValue()) + setSelectedId (currentId.getValue(), false); } const String ComboBox::getText() const throw() { - return label->getText(); + return label->getText(); } void ComboBox::setText (const String& newText, - const bool dontSendChangeMessage) throw() + const bool dontSendChangeMessage) throw() { - for (int i = items.size(); --i >= 0;) - { - ItemInfo* const item = items.getUnchecked(i); + for (int i = items.size(); --i >= 0;) + { + const ItemInfo* const item = items.getUnchecked(i); - if (item->isRealItem() - && item->name == newText) - { - setSelectedId (item->itemId, dontSendChangeMessage); - return; - } - } + if (item->isRealItem() + && item->name == newText) + { + setSelectedId (item->itemId, dontSendChangeMessage); + return; + } + } - currentIndex = -1; + lastCurrentId = 0; + currentId = 0; - if (label->getText() != newText) - { - label->setText (newText, false); + if (label->getText() != newText) + { + label->setText (newText, false); - if (! dontSendChangeMessage) - triggerAsyncUpdate(); - } + if (! dontSendChangeMessage) + triggerAsyncUpdate(); + } - repaint(); + repaint(); } void ComboBox::showEditor() { - jassert (isTextEditable()); // you probably shouldn't do this to a non-editable combo box? + jassert (isTextEditable()); // you probably shouldn't do this to a non-editable combo box? - label->showEditor(); + label->showEditor(); } void ComboBox::setTextWhenNothingSelected (const String& newMessage) throw() { - textWhenNothingSelected = newMessage; - repaint(); + textWhenNothingSelected = newMessage; + repaint(); } const String ComboBox::getTextWhenNothingSelected() const throw() { - return textWhenNothingSelected; + return textWhenNothingSelected; } void ComboBox::setTextWhenNoChoicesAvailable (const String& newMessage) throw() { - noChoicesMessage = newMessage; + noChoicesMessage = newMessage; } const String ComboBox::getTextWhenNoChoicesAvailable() const throw() { - return noChoicesMessage; + return noChoicesMessage; } void ComboBox::paint (Graphics& g) { - getLookAndFeel().drawComboBox (g, - getWidth(), - getHeight(), - isButtonDown, - label->getRight(), - 0, - getWidth() - label->getRight(), - getHeight(), - *this); + getLookAndFeel().drawComboBox (g, + getWidth(), + getHeight(), + isButtonDown, + label->getRight(), + 0, + getWidth() - label->getRight(), + getHeight(), + *this); - if (textWhenNothingSelected.isNotEmpty() - && label->getText().isEmpty() - && ! label->isBeingEdited()) - { - g.setColour (findColour (textColourId).withMultipliedAlpha (0.5f)); - g.setFont (label->getFont()); - g.drawFittedText (textWhenNothingSelected, - label->getX() + 2, label->getY() + 1, - label->getWidth() - 4, label->getHeight() - 2, - label->getJustificationType(), - jmax (1, (int) (label->getHeight() / label->getFont().getHeight()))); - } + if (textWhenNothingSelected.isNotEmpty() + && label->getText().isEmpty() + && ! label->isBeingEdited()) + { + g.setColour (findColour (textColourId).withMultipliedAlpha (0.5f)); + g.setFont (label->getFont()); + g.drawFittedText (textWhenNothingSelected, + label->getX() + 2, label->getY() + 1, + label->getWidth() - 4, label->getHeight() - 2, + label->getJustificationType(), + jmax (1, (int) (label->getHeight() / label->getFont().getHeight()))); + } } void ComboBox::resized() { - if (getHeight() > 0 && getWidth() > 0) - getLookAndFeel().positionComboBoxText (*this, *label); + if (getHeight() > 0 && getWidth() > 0) + getLookAndFeel().positionComboBoxText (*this, *label); } void ComboBox::enablementChanged() { - repaint(); + repaint(); } void ComboBox::lookAndFeelChanged() { - repaint(); + repaint(); - Label* const newLabel = getLookAndFeel().createComboBoxTextBox (*this); + Label* const newLabel = getLookAndFeel().createComboBoxTextBox (*this); - if (label != 0) - { - newLabel->setEditable (label->isEditable()); - newLabel->setJustificationType (label->getJustificationType()); - newLabel->setTooltip (label->getTooltip()); - newLabel->setText (label->getText(), false); - } + if (label != 0) + { + newLabel->setEditable (label->isEditable()); + newLabel->setJustificationType (label->getJustificationType()); + newLabel->setTooltip (label->getTooltip()); + newLabel->setText (label->getText(), false); + } - delete label; - label = newLabel; + delete label; + label = newLabel; - addAndMakeVisible (newLabel); + addAndMakeVisible (newLabel); - newLabel->addListener (this); - newLabel->addMouseListener (this, false); + newLabel->addListener (this); + newLabel->addMouseListener (this, false); - newLabel->setColour (Label::backgroundColourId, Colours::transparentBlack); - newLabel->setColour (Label::textColourId, findColour (ComboBox::textColourId)); + newLabel->setColour (Label::backgroundColourId, Colours::transparentBlack); + newLabel->setColour (Label::textColourId, findColour (ComboBox::textColourId)); - newLabel->setColour (TextEditor::textColourId, findColour (ComboBox::textColourId)); - newLabel->setColour (TextEditor::backgroundColourId, Colours::transparentBlack); - newLabel->setColour (TextEditor::highlightColourId, findColour (TextEditor::highlightColourId)); - newLabel->setColour (TextEditor::outlineColourId, Colours::transparentBlack); + newLabel->setColour (TextEditor::textColourId, findColour (ComboBox::textColourId)); + newLabel->setColour (TextEditor::backgroundColourId, Colours::transparentBlack); + newLabel->setColour (TextEditor::highlightColourId, findColour (TextEditor::highlightColourId)); + newLabel->setColour (TextEditor::outlineColourId, Colours::transparentBlack); - resized(); + resized(); } void ComboBox::colourChanged() { - lookAndFeelChanged(); + lookAndFeelChanged(); } bool ComboBox::keyPressed (const KeyPress& key) { - bool used = false; + bool used = false; - if (key.isKeyCode (KeyPress::upKey) - || key.isKeyCode (KeyPress::leftKey)) - { - setSelectedItemIndex (jmax (0, currentIndex - 1)); - used = true; - } - else if (key.isKeyCode (KeyPress::downKey) - || key.isKeyCode (KeyPress::rightKey)) - { - setSelectedItemIndex (jmin (currentIndex + 1, getNumItems() - 1)); - used = true; - } - else if (key.isKeyCode (KeyPress::returnKey)) - { - showPopup(); - used = true; - } + if (key.isKeyCode (KeyPress::upKey) + || key.isKeyCode (KeyPress::leftKey)) + { + setSelectedItemIndex (jmax (0, getSelectedItemIndex() - 1)); + used = true; + } + else if (key.isKeyCode (KeyPress::downKey) + || key.isKeyCode (KeyPress::rightKey)) + { + setSelectedItemIndex (jmin (getSelectedItemIndex() + 1, getNumItems() - 1)); + used = true; + } + else if (key.isKeyCode (KeyPress::returnKey)) + { + showPopup(); + used = true; + } - return used; + return used; } bool ComboBox::keyStateChanged (const bool isKeyDown) { - // only forward key events that aren't used by this component - return isKeyDown - && (KeyPress::isKeyCurrentlyDown (KeyPress::upKey) - || KeyPress::isKeyCurrentlyDown (KeyPress::leftKey) - || KeyPress::isKeyCurrentlyDown (KeyPress::downKey) - || KeyPress::isKeyCurrentlyDown (KeyPress::rightKey)); + // only forward key events that aren't used by this component + return isKeyDown + && (KeyPress::isKeyCurrentlyDown (KeyPress::upKey) + || KeyPress::isKeyCurrentlyDown (KeyPress::leftKey) + || KeyPress::isKeyCurrentlyDown (KeyPress::downKey) + || KeyPress::isKeyCurrentlyDown (KeyPress::rightKey)); } void ComboBox::focusGained (FocusChangeType) { - repaint(); + repaint(); } void ComboBox::focusLost (FocusChangeType) { - repaint(); + repaint(); } void ComboBox::labelTextChanged (Label*) { - triggerAsyncUpdate(); + triggerAsyncUpdate(); } void ComboBox::showPopup() { - if (! menuActive) - { - const int currentId = getSelectedId(); - ComponentDeletionWatcher deletionWatcher (this); + if (! menuActive) + { + const int selectedId = getSelectedId(); + ComponentDeletionWatcher deletionWatcher (this); - PopupMenu menu; + PopupMenu menu; - menu.setLookAndFeel (&getLookAndFeel()); + menu.setLookAndFeel (&getLookAndFeel()); - for (int i = 0; i < items.size(); ++i) - { - const ItemInfo* const item = items.getUnchecked(i); + for (int i = 0; i < items.size(); ++i) + { + const ItemInfo* const item = items.getUnchecked(i); - if (item->isSeparator()) - menu.addSeparator(); - else if (item->isHeading) - menu.addSectionHeader (item->name); - else - menu.addItem (item->itemId, item->name, - item->isEnabled, item->itemId == currentId); - } + if (item->isSeparator()) + menu.addSeparator(); + else if (item->isHeading) + menu.addSectionHeader (item->name); + else + menu.addItem (item->itemId, item->name, + item->isEnabled, item->itemId == selectedId); + } - if (items.size() == 0) - menu.addItem (1, noChoicesMessage, false); + if (items.size() == 0) + menu.addItem (1, noChoicesMessage, false); - const int itemHeight = jlimit (12, 24, getHeight()); + const int itemHeight = jlimit (12, 24, getHeight()); - menuActive = true; - const int resultId = menu.showAt (this, currentId, - getWidth(), 1, itemHeight); + menuActive = true; + const int resultId = menu.showAt (this, selectedId, + getWidth(), 1, itemHeight); - if (deletionWatcher.hasBeenDeleted()) - return; + if (deletionWatcher.hasBeenDeleted()) + return; - menuActive = false; + menuActive = false; - if (resultId != 0) - setSelectedId (resultId); - } + if (resultId != 0) + setSelectedId (resultId); + } } void ComboBox::mouseDown (const MouseEvent& e) { - beginDragAutoRepeat (300); + beginDragAutoRepeat (300); - isButtonDown = isEnabled(); + isButtonDown = isEnabled(); - if (isButtonDown - && (e.eventComponent == this || ! label->isEditable())) - { - showPopup(); - } + if (isButtonDown + && (e.eventComponent == this || ! label->isEditable())) + { + showPopup(); + } } void ComboBox::mouseDrag (const MouseEvent& e) { - beginDragAutoRepeat (50); + beginDragAutoRepeat (50); - if (isButtonDown && ! e.mouseWasClicked()) - showPopup(); + if (isButtonDown && ! e.mouseWasClicked()) + showPopup(); } void ComboBox::mouseUp (const MouseEvent& e2) { - if (isButtonDown) - { - isButtonDown = false; - repaint(); + if (isButtonDown) + { + isButtonDown = false; + repaint(); - const MouseEvent e (e2.getEventRelativeTo (this)); + const MouseEvent e (e2.getEventRelativeTo (this)); - if (reallyContains (e.x, e.y, true) - && (e2.eventComponent == this || ! label->isEditable())) - { - showPopup(); - } - } + if (reallyContains (e.x, e.y, true) + && (e2.eventComponent == this || ! label->isEditable())) + { + showPopup(); + } + } +} + +void ComboBox::addListener (ComboBoxListener* const listener) throw() +{ + jassert (listener != 0); + if (listener != 0) + listeners.add (listener); +} + +void ComboBox::removeListener (ComboBoxListener* const listener) throw() +{ + listeners.removeValue (listener); +} + +void ComboBox::handleAsyncUpdate() +{ + for (int i = listeners.size(); --i >= 0;) + { + ((ComboBoxListener*) listeners.getUnchecked (i))->comboBoxChanged (this); + i = jmin (i, listeners.size()); + } } END_JUCE_NAMESPACE @@ -47372,147 +47066,158 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE Label::Label (const String& componentName, - const String& labelText) - : Component (componentName), - text (labelText), - font (15.0f), - justification (Justification::centredLeft), - listeners (2), - ownerComponent (0), - horizontalBorderSize (3), - verticalBorderSize (1), - minimumHorizontalScale (0.7f), - editSingleClick (false), - editDoubleClick (false), - lossOfFocusDiscardsChanges (false) + const String& labelText) + : Component (componentName), + textValue (labelText), + lastTextValue (labelText), + font (15.0f), + justification (Justification::centredLeft), + ownerComponent (0), + horizontalBorderSize (3), + verticalBorderSize (1), + minimumHorizontalScale (0.7f), + editSingleClick (false), + editDoubleClick (false), + lossOfFocusDiscardsChanges (false) { - setColour (TextEditor::textColourId, Colours::black); - setColour (TextEditor::backgroundColourId, Colours::transparentBlack); - setColour (TextEditor::outlineColourId, Colours::transparentBlack); + setColour (TextEditor::textColourId, Colours::black); + setColour (TextEditor::backgroundColourId, Colours::transparentBlack); + setColour (TextEditor::outlineColourId, Colours::transparentBlack); + + textValue.addListener (this); } Label::~Label() { - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) - ownerComponent->removeComponentListener (this); + textValue.removeListener (this); - editor = 0; + if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + ownerComponent->removeComponentListener (this); + + editor = 0; } void Label::setText (const String& newText, - const bool broadcastChangeMessage) + const bool broadcastChangeMessage) { - hideEditor (true); + hideEditor (true); - if (text != newText) - { - text = newText; - repaint(); + if (lastTextValue != newText) + { + lastTextValue = newText; + textValue = newText; + repaint(); - textWasChanged(); + textWasChanged(); - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) - componentMovedOrResized (*ownerComponent, true, true); + if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + componentMovedOrResized (*ownerComponent, true, true); - if (broadcastChangeMessage) - callChangeListeners(); - } + if (broadcastChangeMessage) + callChangeListeners(); + } } const String Label::getText (const bool returnActiveEditorContents) const throw() { - return (returnActiveEditorContents && isBeingEdited()) - ? editor->getText() - : text; + return (returnActiveEditorContents && isBeingEdited()) + ? editor->getText() + : textValue.toString(); +} + +void Label::valueChanged (Value&) +{ + if (lastTextValue != textValue.toString()) + setText (textValue.toString(), true); } void Label::setFont (const Font& newFont) throw() { - font = newFont; - repaint(); + font = newFont; + repaint(); } const Font& Label::getFont() const throw() { - return font; + return font; } void Label::setEditable (const bool editOnSingleClick, - const bool editOnDoubleClick, - const bool lossOfFocusDiscardsChanges_) throw() + const bool editOnDoubleClick, + const bool lossOfFocusDiscardsChanges_) throw() { - editSingleClick = editOnSingleClick; - editDoubleClick = editOnDoubleClick; - lossOfFocusDiscardsChanges = lossOfFocusDiscardsChanges_; + editSingleClick = editOnSingleClick; + editDoubleClick = editOnDoubleClick; + lossOfFocusDiscardsChanges = lossOfFocusDiscardsChanges_; - setWantsKeyboardFocus (editOnSingleClick || editOnDoubleClick); - setFocusContainer (editOnSingleClick || editOnDoubleClick); + setWantsKeyboardFocus (editOnSingleClick || editOnDoubleClick); + setFocusContainer (editOnSingleClick || editOnDoubleClick); } void Label::setJustificationType (const Justification& justification_) throw() { - justification = justification_; - repaint(); + justification = justification_; + repaint(); } void Label::setBorderSize (int h, int v) { - horizontalBorderSize = h; - verticalBorderSize = v; - repaint(); + horizontalBorderSize = h; + verticalBorderSize = v; + repaint(); } void Label::attachToComponent (Component* owner, - const bool onLeft) + const bool onLeft) { - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) - ownerComponent->removeComponentListener (this); + if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + ownerComponent->removeComponentListener (this); - deletionWatcher = 0; - ownerComponent = owner; + deletionWatcher = 0; + ownerComponent = owner; - leftOfOwnerComp = onLeft; + leftOfOwnerComp = onLeft; - if (ownerComponent != 0) - { - deletionWatcher = new ComponentDeletionWatcher (owner); + if (ownerComponent != 0) + { + deletionWatcher = new ComponentDeletionWatcher (owner); - setVisible (owner->isVisible()); - ownerComponent->addComponentListener (this); - componentParentHierarchyChanged (*ownerComponent); - componentMovedOrResized (*ownerComponent, true, true); - } + setVisible (owner->isVisible()); + ownerComponent->addComponentListener (this); + componentParentHierarchyChanged (*ownerComponent); + componentMovedOrResized (*ownerComponent, true, true); + } } void Label::componentMovedOrResized (Component& component, - bool /*wasMoved*/, - bool /*wasResized*/) + bool /*wasMoved*/, + bool /*wasResized*/) { - if (leftOfOwnerComp) - { - setSize (jmin (getFont().getStringWidth (text) + 8, component.getX()), - component.getHeight()); + if (leftOfOwnerComp) + { + setSize (jmin (getFont().getStringWidth (textValue.toString()) + 8, component.getX()), + component.getHeight()); - setTopRightPosition (component.getX(), component.getY()); - } - else - { - setSize (component.getWidth(), - 8 + roundFloatToInt (getFont().getHeight())); + setTopRightPosition (component.getX(), component.getY()); + } + else + { + setSize (component.getWidth(), + 8 + roundToInt (getFont().getHeight())); - setTopLeftPosition (component.getX(), component.getY() - getHeight()); - } + setTopLeftPosition (component.getX(), component.getY() - getHeight()); + } } void Label::componentParentHierarchyChanged (Component& component) { - if (component.getParentComponent() != 0) - component.getParentComponent()->addChildComponent (this); + if (component.getParentComponent() != 0) + component.getParentComponent()->addChildComponent (this); } void Label::componentVisibilityChanged (Component& component) { - setVisible (component.isVisible()); + setVisible (component.isVisible()); } void Label::textWasEdited() @@ -47525,23 +47230,23 @@ void Label::textWasChanged() void Label::showEditor() { - if (editor == 0) - { - addAndMakeVisible (editor = createEditorComponent()); - editor->setText (getText(), false); - editor->addListener (this); - editor->grabKeyboardFocus(); - editor->setHighlightedRegion (0, text.length()); - editor->addListener (this); + if (editor == 0) + { + addAndMakeVisible (editor = createEditorComponent()); + editor->setText (getText(), false); + editor->addListener (this); + editor->grabKeyboardFocus(); + editor->setHighlightedRegion (0, textValue.toString().length()); + editor->addListener (this); - resized(); - repaint(); + resized(); + repaint(); - editorShown (editor); + editorShown (editor); - enterModalState(); - editor->grabKeyboardFocus(); - } + enterModalState(); + editor->grabKeyboardFocus(); + } } void Label::editorShown (TextEditor* editorComponent) @@ -47554,135 +47259,136 @@ void Label::editorAboutToBeHidden (TextEditor* editorComponent) bool Label::updateFromTextEditorContents() { - jassert (editor != 0); - const String newText (editor->getText()); + jassert (editor != 0); + const String newText (editor->getText()); - if (text != newText) - { - text = newText; - repaint(); + if (textValue.toString() != newText) + { + lastTextValue = newText; + textValue = newText; + repaint(); - textWasChanged(); + textWasChanged(); - if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) - componentMovedOrResized (*ownerComponent, true, true); + if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) + componentMovedOrResized (*ownerComponent, true, true); - return true; - } + return true; + } - return false; + return false; } void Label::hideEditor (const bool discardCurrentEditorContents) { - if (editor != 0) - { - editorAboutToBeHidden (editor); + if (editor != 0) + { + editorAboutToBeHidden (editor); - const bool changed = (! discardCurrentEditorContents) - && updateFromTextEditorContents(); + const bool changed = (! discardCurrentEditorContents) + && updateFromTextEditorContents(); - editor = 0; - repaint(); + editor = 0; + repaint(); - if (changed) - textWasEdited(); + if (changed) + textWasEdited(); - exitModalState (0); + exitModalState (0); - if (changed && isValidComponent()) - callChangeListeners(); - } + if (changed && isValidComponent()) + callChangeListeners(); + } } void Label::inputAttemptWhenModal() { - if (editor != 0) - { - if (lossOfFocusDiscardsChanges) - textEditorEscapeKeyPressed (*editor); - else - textEditorReturnKeyPressed (*editor); - } + if (editor != 0) + { + if (lossOfFocusDiscardsChanges) + textEditorEscapeKeyPressed (*editor); + else + textEditorReturnKeyPressed (*editor); + } } bool Label::isBeingEdited() const throw() { - return editor != 0; + return editor != 0; } TextEditor* Label::createEditorComponent() { - TextEditor* const ed = new TextEditor (getName()); - ed->setFont (font); + TextEditor* const ed = new TextEditor (getName()); + ed->setFont (font); - // copy these colours from our own settings.. - const int cols[] = { TextEditor::backgroundColourId, - TextEditor::textColourId, - TextEditor::highlightColourId, - TextEditor::highlightedTextColourId, - TextEditor::caretColourId, - TextEditor::outlineColourId, - TextEditor::focusedOutlineColourId, - TextEditor::shadowColourId }; + // copy these colours from our own settings.. + const int cols[] = { TextEditor::backgroundColourId, + TextEditor::textColourId, + TextEditor::highlightColourId, + TextEditor::highlightedTextColourId, + TextEditor::caretColourId, + TextEditor::outlineColourId, + TextEditor::focusedOutlineColourId, + TextEditor::shadowColourId }; - for (int i = 0; i < numElementsInArray (cols); ++i) - ed->setColour (cols[i], findColour (cols[i])); + for (int i = 0; i < numElementsInArray (cols); ++i) + ed->setColour (cols[i], findColour (cols[i])); - return ed; + return ed; } void Label::paint (Graphics& g) { - getLookAndFeel().drawLabel (g, *this); + getLookAndFeel().drawLabel (g, *this); } void Label::mouseUp (const MouseEvent& e) { - if (editSingleClick - && e.mouseWasClicked() - && contains (e.x, e.y) - && ! e.mods.isPopupMenu()) - { - showEditor(); - } + if (editSingleClick + && e.mouseWasClicked() + && contains (e.x, e.y) + && ! e.mods.isPopupMenu()) + { + showEditor(); + } } void Label::mouseDoubleClick (const MouseEvent& e) { - if (editDoubleClick && ! e.mods.isPopupMenu()) - showEditor(); + if (editDoubleClick && ! e.mods.isPopupMenu()) + showEditor(); } void Label::resized() { - if (editor != 0) - editor->setBoundsInset (BorderSize (0)); + if (editor != 0) + editor->setBoundsInset (BorderSize (0)); } void Label::focusGained (FocusChangeType cause) { - if (editSingleClick && cause == focusChangedByTabKey) - showEditor(); + if (editSingleClick && cause == focusChangedByTabKey) + showEditor(); } void Label::enablementChanged() { - repaint(); + repaint(); } void Label::colourChanged() { - repaint(); + repaint(); } void Label::setMinimumHorizontalScale (const float newScale) { - if (minimumHorizontalScale != newScale) - { - minimumHorizontalScale = newScale; - repaint(); - } + if (minimumHorizontalScale != newScale) + { + minimumHorizontalScale = newScale; + repaint(); + } } // We'll use a custom focus traverser here to make sure focus goes from the @@ -47690,98 +47396,98 @@ void Label::setMinimumHorizontalScale (const float newScale) class LabelKeyboardFocusTraverser : public KeyboardFocusTraverser { public: - LabelKeyboardFocusTraverser() {} + LabelKeyboardFocusTraverser() {} - Component* getNextComponent (Component* current) - { - return KeyboardFocusTraverser::getNextComponent (dynamic_cast (current) != 0 - ? current->getParentComponent() : current); - } + Component* getNextComponent (Component* current) + { + return KeyboardFocusTraverser::getNextComponent (dynamic_cast (current) != 0 + ? current->getParentComponent() : current); + } - Component* getPreviousComponent (Component* current) - { - return KeyboardFocusTraverser::getPreviousComponent (dynamic_cast (current) != 0 - ? current->getParentComponent() : current); - } + Component* getPreviousComponent (Component* current) + { + return KeyboardFocusTraverser::getPreviousComponent (dynamic_cast (current) != 0 + ? current->getParentComponent() : current); + } }; KeyboardFocusTraverser* Label::createFocusTraverser() { - return new LabelKeyboardFocusTraverser(); + return new LabelKeyboardFocusTraverser(); } void Label::addListener (LabelListener* const listener) throw() { - jassert (listener != 0); - if (listener != 0) - listeners.add (listener); + jassert (listener != 0); + if (listener != 0) + listeners.add (listener); } void Label::removeListener (LabelListener* const listener) throw() { - listeners.removeValue (listener); + listeners.removeValue (listener); } void Label::callChangeListeners() { - for (int i = listeners.size(); --i >= 0;) - { - ((LabelListener*) listeners.getUnchecked (i))->labelTextChanged (this); - i = jmin (i, listeners.size()); - } + for (int i = listeners.size(); --i >= 0;) + { + ((LabelListener*) listeners.getUnchecked (i))->labelTextChanged (this); + i = jmin (i, listeners.size()); + } } void Label::textEditorTextChanged (TextEditor& ed) { - if (editor != 0) - { - jassert (&ed == editor); + if (editor != 0) + { + jassert (&ed == editor); - if (! (hasKeyboardFocus (true) || isCurrentlyBlockedByAnotherModalComponent())) - { - if (lossOfFocusDiscardsChanges) - textEditorEscapeKeyPressed (ed); - else - textEditorReturnKeyPressed (ed); - } - } + if (! (hasKeyboardFocus (true) || isCurrentlyBlockedByAnotherModalComponent())) + { + if (lossOfFocusDiscardsChanges) + textEditorEscapeKeyPressed (ed); + else + textEditorReturnKeyPressed (ed); + } + } } void Label::textEditorReturnKeyPressed (TextEditor& ed) { - if (editor != 0) - { - jassert (&ed == editor); - (void) ed; + if (editor != 0) + { + jassert (&ed == editor); + (void) ed; - const bool changed = updateFromTextEditorContents(); - hideEditor (true); + const bool changed = updateFromTextEditorContents(); + hideEditor (true); - if (changed) - { - textWasEdited(); + if (changed) + { + textWasEdited(); - if (isValidComponent()) - callChangeListeners(); - } - } + if (isValidComponent()) + callChangeListeners(); + } + } } void Label::textEditorEscapeKeyPressed (TextEditor& ed) { - if (editor != 0) - { - jassert (&ed == editor); - (void) ed; + if (editor != 0) + { + jassert (&ed == editor); + (void) ed; - editor->setText (text, false); - hideEditor (true); - } + editor->setText (textValue.toString(), false); + hideEditor (true); + } } void Label::textEditorFocusLost (TextEditor& ed) { - textEditorTextChanged (ed); + textEditorTextChanged (ed); } END_JUCE_NAMESPACE @@ -47792,921 +47498,921 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE class ListBoxRowComponent : public Component, - public TooltipClient + public TooltipClient { public: - ListBoxRowComponent (ListBox& owner_) - : owner (owner_), - row (-1), - selected (false), - isDragging (false) - { - } + ListBoxRowComponent (ListBox& owner_) + : owner (owner_), + row (-1), + selected (false), + isDragging (false) + { + } - ~ListBoxRowComponent() - { - deleteAllChildren(); - } + ~ListBoxRowComponent() + { + deleteAllChildren(); + } - void paint (Graphics& g) - { - if (owner.getModel() != 0) - owner.getModel()->paintListBoxItem (row, g, getWidth(), getHeight(), selected); - } + void paint (Graphics& g) + { + if (owner.getModel() != 0) + owner.getModel()->paintListBoxItem (row, g, getWidth(), getHeight(), selected); + } - void update (const int row_, const bool selected_) - { - if (row != row_ || selected != selected_) - { - repaint(); - row = row_; - selected = selected_; - } + void update (const int row_, const bool selected_) + { + if (row != row_ || selected != selected_) + { + repaint(); + row = row_; + selected = selected_; + } - if (owner.getModel() != 0) - { - Component* const customComp = owner.getModel()->refreshComponentForRow (row_, selected_, getChildComponent (0)); + if (owner.getModel() != 0) + { + Component* const customComp = owner.getModel()->refreshComponentForRow (row_, selected_, getChildComponent (0)); - if (customComp != 0) - { - addAndMakeVisible (customComp); - customComp->setBounds (0, 0, getWidth(), getHeight()); + if (customComp != 0) + { + addAndMakeVisible (customComp); + customComp->setBounds (0, 0, getWidth(), getHeight()); - for (int i = getNumChildComponents(); --i >= 0;) - if (getChildComponent (i) != customComp) - delete getChildComponent (i); - } - else - { - deleteAllChildren(); - } - } - } + for (int i = getNumChildComponents(); --i >= 0;) + if (getChildComponent (i) != customComp) + delete getChildComponent (i); + } + else + { + deleteAllChildren(); + } + } + } - void mouseDown (const MouseEvent& e) - { - isDragging = false; - selectRowOnMouseUp = false; + void mouseDown (const MouseEvent& e) + { + isDragging = false; + selectRowOnMouseUp = false; - if (isEnabled()) - { - if (! selected) - { - owner.selectRowsBasedOnModifierKeys (row, e.mods); + if (isEnabled()) + { + if (! selected) + { + owner.selectRowsBasedOnModifierKeys (row, e.mods); - if (owner.getModel() != 0) - owner.getModel()->listBoxItemClicked (row, e); - } - else - { - selectRowOnMouseUp = true; - } - } - } + if (owner.getModel() != 0) + owner.getModel()->listBoxItemClicked (row, e); + } + else + { + selectRowOnMouseUp = true; + } + } + } - void mouseUp (const MouseEvent& e) - { - if (isEnabled() && selectRowOnMouseUp && ! isDragging) - { - owner.selectRowsBasedOnModifierKeys (row, e.mods); + void mouseUp (const MouseEvent& e) + { + if (isEnabled() && selectRowOnMouseUp && ! isDragging) + { + owner.selectRowsBasedOnModifierKeys (row, e.mods); - if (owner.getModel() != 0) - owner.getModel()->listBoxItemClicked (row, e); - } - } + if (owner.getModel() != 0) + owner.getModel()->listBoxItemClicked (row, e); + } + } - void mouseDoubleClick (const MouseEvent& e) - { - if (owner.getModel() != 0 && isEnabled()) - owner.getModel()->listBoxItemDoubleClicked (row, e); - } + void mouseDoubleClick (const MouseEvent& e) + { + if (owner.getModel() != 0 && isEnabled()) + owner.getModel()->listBoxItemDoubleClicked (row, e); + } - void mouseDrag (const MouseEvent& e) - { - if (isEnabled() && owner.getModel() != 0 && ! (e.mouseWasClicked() || isDragging)) - { - const SparseSet selectedRows (owner.getSelectedRows()); + void mouseDrag (const MouseEvent& e) + { + if (isEnabled() && owner.getModel() != 0 && ! (e.mouseWasClicked() || isDragging)) + { + const SparseSet selectedRows (owner.getSelectedRows()); - if (selectedRows.size() > 0) - { - const String dragDescription (owner.getModel()->getDragSourceDescription (selectedRows)); + if (selectedRows.size() > 0) + { + const String dragDescription (owner.getModel()->getDragSourceDescription (selectedRows)); - if (dragDescription.isNotEmpty()) - { - isDragging = true; - owner.startDragAndDrop (e, dragDescription); - } - } - } - } + if (dragDescription.isNotEmpty()) + { + isDragging = true; + owner.startDragAndDrop (e, dragDescription); + } + } + } + } - void resized() - { - if (getNumChildComponents() > 0) - getChildComponent(0)->setBounds (0, 0, getWidth(), getHeight()); - } + void resized() + { + if (getNumChildComponents() > 0) + getChildComponent(0)->setBounds (0, 0, getWidth(), getHeight()); + } - const String getTooltip() - { - if (owner.getModel() != 0) - return owner.getModel()->getTooltipForRow (row); + const String getTooltip() + { + if (owner.getModel() != 0) + return owner.getModel()->getTooltipForRow (row); - return String::empty; - } + return String::empty; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - bool neededFlag; + bool neededFlag; private: - ListBox& owner; - int row; - bool selected, isDragging, selectRowOnMouseUp; + ListBox& owner; + int row; + bool selected, isDragging, selectRowOnMouseUp; - ListBoxRowComponent (const ListBoxRowComponent&); - const ListBoxRowComponent& operator= (const ListBoxRowComponent&); + ListBoxRowComponent (const ListBoxRowComponent&); + const ListBoxRowComponent& operator= (const ListBoxRowComponent&); }; class ListViewport : public Viewport { public: - int firstIndex, firstWholeIndex, lastWholeIndex; - bool hasUpdated; + int firstIndex, firstWholeIndex, lastWholeIndex; + bool hasUpdated; - ListViewport (ListBox& owner_) - : owner (owner_) - { - setWantsKeyboardFocus (false); + ListViewport (ListBox& owner_) + : owner (owner_) + { + setWantsKeyboardFocus (false); - setViewedComponent (new Component()); - getViewedComponent()->addMouseListener (this, false); - getViewedComponent()->setWantsKeyboardFocus (false); - } + setViewedComponent (new Component()); + getViewedComponent()->addMouseListener (this, false); + getViewedComponent()->setWantsKeyboardFocus (false); + } - ~ListViewport() - { - getViewedComponent()->removeMouseListener (this); - getViewedComponent()->deleteAllChildren(); - } + ~ListViewport() + { + getViewedComponent()->removeMouseListener (this); + getViewedComponent()->deleteAllChildren(); + } - ListBoxRowComponent* getComponentForRow (const int row) const throw() - { - return (ListBoxRowComponent*) getViewedComponent() - ->getChildComponent (row % jmax (1, getViewedComponent()->getNumChildComponents())); - } + ListBoxRowComponent* getComponentForRow (const int row) const throw() + { + return (ListBoxRowComponent*) getViewedComponent() + ->getChildComponent (row % jmax (1, getViewedComponent()->getNumChildComponents())); + } - int getRowNumberOfComponent (Component* const rowComponent) const throw() - { - const int index = getIndexOfChildComponent (rowComponent); - const int num = getViewedComponent()->getNumChildComponents(); + int getRowNumberOfComponent (Component* const rowComponent) const throw() + { + const int index = getIndexOfChildComponent (rowComponent); + const int num = getViewedComponent()->getNumChildComponents(); - for (int i = num; --i >= 0;) - if (((firstIndex + i) % jmax (1, num)) == index) - return firstIndex + i; + for (int i = num; --i >= 0;) + if (((firstIndex + i) % jmax (1, num)) == index) + return firstIndex + i; - return -1; - } + return -1; + } - Component* getComponentForRowIfOnscreen (const int row) const throw() - { - return (row >= firstIndex && row < firstIndex + getViewedComponent()->getNumChildComponents()) - ? getComponentForRow (row) : 0; - } + Component* getComponentForRowIfOnscreen (const int row) const throw() + { + return (row >= firstIndex && row < firstIndex + getViewedComponent()->getNumChildComponents()) + ? getComponentForRow (row) : 0; + } - void visibleAreaChanged (int, int, int, int) - { - updateVisibleArea (true); + void visibleAreaChanged (int, int, int, int) + { + updateVisibleArea (true); - if (owner.getModel() != 0) - owner.getModel()->listWasScrolled(); - } + if (owner.getModel() != 0) + owner.getModel()->listWasScrolled(); + } - void updateVisibleArea (const bool makeSureItUpdatesContent) - { - hasUpdated = false; + void updateVisibleArea (const bool makeSureItUpdatesContent) + { + hasUpdated = false; - const int newX = getViewedComponent()->getX(); - int newY = getViewedComponent()->getY(); - const int newW = jmax (owner.minimumRowWidth, getMaximumVisibleWidth()); - const int newH = owner.totalItems * owner.getRowHeight(); + const int newX = getViewedComponent()->getX(); + int newY = getViewedComponent()->getY(); + const int newW = jmax (owner.minimumRowWidth, getMaximumVisibleWidth()); + const int newH = owner.totalItems * owner.getRowHeight(); - if (newY + newH < getMaximumVisibleHeight() && newH > getMaximumVisibleHeight()) - newY = getMaximumVisibleHeight() - newH; + if (newY + newH < getMaximumVisibleHeight() && newH > getMaximumVisibleHeight()) + newY = getMaximumVisibleHeight() - newH; - getViewedComponent()->setBounds (newX, newY, newW, newH); + getViewedComponent()->setBounds (newX, newY, newW, newH); - if (makeSureItUpdatesContent && ! hasUpdated) - updateContents(); - } + if (makeSureItUpdatesContent && ! hasUpdated) + updateContents(); + } - void updateContents() - { - hasUpdated = true; - const int rowHeight = owner.getRowHeight(); + void updateContents() + { + hasUpdated = true; + const int rowHeight = owner.getRowHeight(); - if (rowHeight > 0) - { - const int y = getViewPositionY(); - const int w = getViewedComponent()->getWidth(); + if (rowHeight > 0) + { + const int y = getViewPositionY(); + const int w = getViewedComponent()->getWidth(); - const int numNeeded = 2 + getMaximumVisibleHeight() / rowHeight; + const int numNeeded = 2 + getMaximumVisibleHeight() / rowHeight; - while (numNeeded > getViewedComponent()->getNumChildComponents()) - getViewedComponent()->addAndMakeVisible (new ListBoxRowComponent (owner)); + while (numNeeded > getViewedComponent()->getNumChildComponents()) + getViewedComponent()->addAndMakeVisible (new ListBoxRowComponent (owner)); - jassert (numNeeded >= 0); + jassert (numNeeded >= 0); - while (numNeeded < getViewedComponent()->getNumChildComponents()) - { - Component* const rowToRemove - = getViewedComponent()->getChildComponent (getViewedComponent()->getNumChildComponents() - 1); + while (numNeeded < getViewedComponent()->getNumChildComponents()) + { + Component* const rowToRemove + = getViewedComponent()->getChildComponent (getViewedComponent()->getNumChildComponents() - 1); - delete rowToRemove; - } + delete rowToRemove; + } - firstIndex = y / rowHeight; - firstWholeIndex = (y + rowHeight - 1) / rowHeight; - lastWholeIndex = (y + getMaximumVisibleHeight() - 1) / rowHeight; + firstIndex = y / rowHeight; + firstWholeIndex = (y + rowHeight - 1) / rowHeight; + lastWholeIndex = (y + getMaximumVisibleHeight() - 1) / rowHeight; - for (int i = 0; i < numNeeded; ++i) - { - const int row = i + firstIndex; - ListBoxRowComponent* const rowComp = getComponentForRow (row); + for (int i = 0; i < numNeeded; ++i) + { + const int row = i + firstIndex; + ListBoxRowComponent* const rowComp = getComponentForRow (row); - if (rowComp != 0) - { - rowComp->setBounds (0, row * rowHeight, w, rowHeight); - rowComp->update (row, owner.isRowSelected (row)); - } - } - } + if (rowComp != 0) + { + rowComp->setBounds (0, row * rowHeight, w, rowHeight); + rowComp->update (row, owner.isRowSelected (row)); + } + } + } - if (owner.headerComponent != 0) - owner.headerComponent->setBounds (owner.outlineThickness + getViewedComponent()->getX(), - owner.outlineThickness, - jmax (owner.getWidth() - owner.outlineThickness * 2, - getViewedComponent()->getWidth()), - owner.headerComponent->getHeight()); - } + if (owner.headerComponent != 0) + owner.headerComponent->setBounds (owner.outlineThickness + getViewedComponent()->getX(), + owner.outlineThickness, + jmax (owner.getWidth() - owner.outlineThickness * 2, + getViewedComponent()->getWidth()), + owner.headerComponent->getHeight()); + } - void paint (Graphics& g) - { - if (isOpaque()) - g.fillAll (owner.findColour (ListBox::backgroundColourId)); - } + void paint (Graphics& g) + { + if (isOpaque()) + g.fillAll (owner.findColour (ListBox::backgroundColourId)); + } - bool keyPressed (const KeyPress& key) - { - if (key.isKeyCode (KeyPress::upKey) - || key.isKeyCode (KeyPress::downKey) - || key.isKeyCode (KeyPress::pageUpKey) - || key.isKeyCode (KeyPress::pageDownKey) - || key.isKeyCode (KeyPress::homeKey) - || key.isKeyCode (KeyPress::endKey)) - { - // we want to avoid these keypresses going to the viewport, and instead allow - // them to pass up to our listbox.. - return false; - } + bool keyPressed (const KeyPress& key) + { + if (key.isKeyCode (KeyPress::upKey) + || key.isKeyCode (KeyPress::downKey) + || key.isKeyCode (KeyPress::pageUpKey) + || key.isKeyCode (KeyPress::pageDownKey) + || key.isKeyCode (KeyPress::homeKey) + || key.isKeyCode (KeyPress::endKey)) + { + // we want to avoid these keypresses going to the viewport, and instead allow + // them to pass up to our listbox.. + return false; + } - return Viewport::keyPressed (key); - } + return Viewport::keyPressed (key); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ListBox& owner; + ListBox& owner; - ListViewport (const ListViewport&); - const ListViewport& operator= (const ListViewport&); + ListViewport (const ListViewport&); + const ListViewport& operator= (const ListViewport&); }; ListBox::ListBox (const String& name, ListBoxModel* const model_) - : Component (name), - model (model_), - headerComponent (0), - totalItems (0), - rowHeight (22), - minimumRowWidth (0), - outlineThickness (0), - lastRowSelected (-1), - mouseMoveSelects (false), - multipleSelection (false), - hasDoneInitialUpdate (false) + : Component (name), + model (model_), + headerComponent (0), + totalItems (0), + rowHeight (22), + minimumRowWidth (0), + outlineThickness (0), + lastRowSelected (-1), + mouseMoveSelects (false), + multipleSelection (false), + hasDoneInitialUpdate (false) { - addAndMakeVisible (viewport = new ListViewport (*this)); + addAndMakeVisible (viewport = new ListViewport (*this)); - setWantsKeyboardFocus (true); - colourChanged(); + setWantsKeyboardFocus (true); + colourChanged(); } ListBox::~ListBox() { - deleteAllChildren(); + deleteAllChildren(); } void ListBox::setModel (ListBoxModel* const newModel) { - if (model != newModel) - { - model = newModel; - updateContent(); - } + if (model != newModel) + { + model = newModel; + updateContent(); + } } void ListBox::setMultipleSelectionEnabled (bool b) { - multipleSelection = b; + multipleSelection = b; } void ListBox::setMouseMoveSelectsRows (bool b) { - mouseMoveSelects = b; + mouseMoveSelects = b; - if (b) - addMouseListener (this, true); + if (b) + addMouseListener (this, true); } void ListBox::paint (Graphics& g) { - if (! hasDoneInitialUpdate) - updateContent(); + if (! hasDoneInitialUpdate) + updateContent(); - g.fillAll (findColour (backgroundColourId)); + g.fillAll (findColour (backgroundColourId)); } void ListBox::paintOverChildren (Graphics& g) { - if (outlineThickness > 0) - { - g.setColour (findColour (outlineColourId)); - g.drawRect (0, 0, getWidth(), getHeight(), outlineThickness); - } + if (outlineThickness > 0) + { + g.setColour (findColour (outlineColourId)); + g.drawRect (0, 0, getWidth(), getHeight(), outlineThickness); + } } void ListBox::resized() { - viewport->setBoundsInset (BorderSize (outlineThickness + ((headerComponent != 0) ? headerComponent->getHeight() : 0), - outlineThickness, - outlineThickness, - outlineThickness)); + viewport->setBoundsInset (BorderSize (outlineThickness + ((headerComponent != 0) ? headerComponent->getHeight() : 0), + outlineThickness, + outlineThickness, + outlineThickness)); - viewport->setSingleStepSizes (20, getRowHeight()); + viewport->setSingleStepSizes (20, getRowHeight()); - viewport->updateVisibleArea (false); + viewport->updateVisibleArea (false); } void ListBox::visibilityChanged() { - viewport->updateVisibleArea (true); + viewport->updateVisibleArea (true); } Viewport* ListBox::getViewport() const throw() { - return viewport; + return viewport; } void ListBox::updateContent() { - hasDoneInitialUpdate = true; - totalItems = (model != 0) ? model->getNumRows() : 0; + hasDoneInitialUpdate = true; + totalItems = (model != 0) ? model->getNumRows() : 0; - bool selectionChanged = false; + bool selectionChanged = false; - if (selected [selected.size() - 1] >= totalItems) - { - selected.removeRange (totalItems, INT_MAX - totalItems); - lastRowSelected = getSelectedRow (0); - selectionChanged = true; - } + if (selected [selected.size() - 1] >= totalItems) + { + selected.removeRange (totalItems, INT_MAX - totalItems); + lastRowSelected = getSelectedRow (0); + selectionChanged = true; + } - viewport->updateVisibleArea (isVisible()); - viewport->resized(); + viewport->updateVisibleArea (isVisible()); + viewport->resized(); - if (selectionChanged && model != 0) - model->selectedRowsChanged (lastRowSelected); + if (selectionChanged && model != 0) + model->selectedRowsChanged (lastRowSelected); } void ListBox::selectRow (const int row, - bool dontScroll, - bool deselectOthersFirst) + bool dontScroll, + bool deselectOthersFirst) { - selectRowInternal (row, dontScroll, deselectOthersFirst, false); + selectRowInternal (row, dontScroll, deselectOthersFirst, false); } void ListBox::selectRowInternal (const int row, - bool dontScroll, - bool deselectOthersFirst, - bool isMouseClick) + bool dontScroll, + bool deselectOthersFirst, + bool isMouseClick) { - if (! multipleSelection) - deselectOthersFirst = true; + if (! multipleSelection) + deselectOthersFirst = true; - if ((! isRowSelected (row)) - || (deselectOthersFirst && getNumSelectedRows() > 1)) - { - if (((unsigned int) row) < (unsigned int) totalItems) - { - if (deselectOthersFirst) - selected.clear(); + if ((! isRowSelected (row)) + || (deselectOthersFirst && getNumSelectedRows() > 1)) + { + if (((unsigned int) row) < (unsigned int) totalItems) + { + if (deselectOthersFirst) + selected.clear(); - selected.addRange (row, 1); + selected.addRange (row, 1); - if (getHeight() == 0 || getWidth() == 0) - dontScroll = true; + if (getHeight() == 0 || getWidth() == 0) + dontScroll = true; - viewport->hasUpdated = false; + viewport->hasUpdated = false; - if (row < viewport->firstWholeIndex && ! dontScroll) - { - viewport->setViewPosition (viewport->getViewPositionX(), - row * getRowHeight()); - } - else if (row >= viewport->lastWholeIndex && ! dontScroll) - { - const int rowsOnScreen = viewport->lastWholeIndex - viewport->firstWholeIndex; + if (row < viewport->firstWholeIndex && ! dontScroll) + { + viewport->setViewPosition (viewport->getViewPositionX(), + row * getRowHeight()); + } + else if (row >= viewport->lastWholeIndex && ! dontScroll) + { + const int rowsOnScreen = viewport->lastWholeIndex - viewport->firstWholeIndex; - if (row >= lastRowSelected + rowsOnScreen - && rowsOnScreen < totalItems - 1 - && ! isMouseClick) - { - viewport->setViewPosition (viewport->getViewPositionX(), - jlimit (0, jmax (0, totalItems - rowsOnScreen), row) - * getRowHeight()); - } - else - { - viewport->setViewPosition (viewport->getViewPositionX(), - jmax (0, (row + 1) * getRowHeight() - viewport->getMaximumVisibleHeight())); - } - } + if (row >= lastRowSelected + rowsOnScreen + && rowsOnScreen < totalItems - 1 + && ! isMouseClick) + { + viewport->setViewPosition (viewport->getViewPositionX(), + jlimit (0, jmax (0, totalItems - rowsOnScreen), row) + * getRowHeight()); + } + else + { + viewport->setViewPosition (viewport->getViewPositionX(), + jmax (0, (row + 1) * getRowHeight() - viewport->getMaximumVisibleHeight())); + } + } - if (! viewport->hasUpdated) - viewport->updateContents(); + if (! viewport->hasUpdated) + viewport->updateContents(); - lastRowSelected = row; - model->selectedRowsChanged (row); - } - else - { - if (deselectOthersFirst) - deselectAllRows(); - } - } + lastRowSelected = row; + model->selectedRowsChanged (row); + } + else + { + if (deselectOthersFirst) + deselectAllRows(); + } + } } void ListBox::deselectRow (const int row) { - if (selected.contains (row)) - { - selected.removeRange (row, 1); + if (selected.contains (row)) + { + selected.removeRange (row, 1); - if (row == lastRowSelected) - lastRowSelected = getSelectedRow (0); + if (row == lastRowSelected) + lastRowSelected = getSelectedRow (0); - viewport->updateContents(); - model->selectedRowsChanged (lastRowSelected); - } + viewport->updateContents(); + model->selectedRowsChanged (lastRowSelected); + } } void ListBox::setSelectedRows (const SparseSet& setOfRowsToBeSelected, - const bool sendNotificationEventToModel) + const bool sendNotificationEventToModel) { - selected = setOfRowsToBeSelected; - selected.removeRange (totalItems, INT_MAX - totalItems); + selected = setOfRowsToBeSelected; + selected.removeRange (totalItems, INT_MAX - totalItems); - if (! isRowSelected (lastRowSelected)) - lastRowSelected = getSelectedRow (0); + if (! isRowSelected (lastRowSelected)) + lastRowSelected = getSelectedRow (0); - viewport->updateContents(); + viewport->updateContents(); - if ((model != 0) && sendNotificationEventToModel) - model->selectedRowsChanged (lastRowSelected); + if ((model != 0) && sendNotificationEventToModel) + model->selectedRowsChanged (lastRowSelected); } const SparseSet ListBox::getSelectedRows() const { - return selected; + return selected; } void ListBox::selectRangeOfRows (int firstRow, int lastRow) { - if (multipleSelection && (firstRow != lastRow)) - { - const int numRows = totalItems - 1; - firstRow = jlimit (0, jmax (0, numRows), firstRow); - lastRow = jlimit (0, jmax (0, numRows), lastRow); + if (multipleSelection && (firstRow != lastRow)) + { + const int numRows = totalItems - 1; + firstRow = jlimit (0, jmax (0, numRows), firstRow); + lastRow = jlimit (0, jmax (0, numRows), lastRow); - selected.addRange (jmin (firstRow, lastRow), - abs (firstRow - lastRow) + 1); + selected.addRange (jmin (firstRow, lastRow), + abs (firstRow - lastRow) + 1); - selected.removeRange (lastRow, 1); - } + selected.removeRange (lastRow, 1); + } - selectRowInternal (lastRow, false, false, true); + selectRowInternal (lastRow, false, false, true); } void ListBox::flipRowSelection (const int row) { - if (isRowSelected (row)) - deselectRow (row); - else - selectRowInternal (row, false, false, true); + if (isRowSelected (row)) + deselectRow (row); + else + selectRowInternal (row, false, false, true); } void ListBox::deselectAllRows() { - if (! selected.isEmpty()) - { - selected.clear(); - lastRowSelected = -1; + if (! selected.isEmpty()) + { + selected.clear(); + lastRowSelected = -1; - viewport->updateContents(); + viewport->updateContents(); - if (model != 0) - model->selectedRowsChanged (lastRowSelected); - } + if (model != 0) + model->selectedRowsChanged (lastRowSelected); + } } void ListBox::selectRowsBasedOnModifierKeys (const int row, - const ModifierKeys& mods) + const ModifierKeys& mods) { - if (multipleSelection && mods.isCommandDown()) - { - flipRowSelection (row); - } - else if (multipleSelection && mods.isShiftDown() && lastRowSelected >= 0) - { - selectRangeOfRows (lastRowSelected, row); - } - else if ((! mods.isPopupMenu()) || ! isRowSelected (row)) - { - selectRowInternal (row, false, true, true); - } + if (multipleSelection && mods.isCommandDown()) + { + flipRowSelection (row); + } + else if (multipleSelection && mods.isShiftDown() && lastRowSelected >= 0) + { + selectRangeOfRows (lastRowSelected, row); + } + else if ((! mods.isPopupMenu()) || ! isRowSelected (row)) + { + selectRowInternal (row, false, true, true); + } } int ListBox::getNumSelectedRows() const { - return selected.size(); + return selected.size(); } int ListBox::getSelectedRow (const int index) const { - return (((unsigned int) index) < (unsigned int) selected.size()) - ? selected [index] : -1; + return (((unsigned int) index) < (unsigned int) selected.size()) + ? selected [index] : -1; } bool ListBox::isRowSelected (const int row) const { - return selected.contains (row); + return selected.contains (row); } int ListBox::getLastRowSelected() const { - return (isRowSelected (lastRowSelected)) ? lastRowSelected : -1; + return (isRowSelected (lastRowSelected)) ? lastRowSelected : -1; } int ListBox::getRowContainingPosition (const int x, const int y) const throw() { - if (((unsigned int) x) < (unsigned int) getWidth()) - { - const int row = (viewport->getViewPositionY() + y - viewport->getY()) / rowHeight; + if (((unsigned int) x) < (unsigned int) getWidth()) + { + const int row = (viewport->getViewPositionY() + y - viewport->getY()) / rowHeight; - if (((unsigned int) row) < (unsigned int) totalItems) - return row; - } + if (((unsigned int) row) < (unsigned int) totalItems) + return row; + } - return -1; + return -1; } int ListBox::getInsertionIndexForPosition (const int x, const int y) const throw() { - if (((unsigned int) x) < (unsigned int) getWidth()) - { - const int row = (viewport->getViewPositionY() + y + rowHeight / 2 - viewport->getY()) / rowHeight; - return jlimit (0, totalItems, row); - } + if (((unsigned int) x) < (unsigned int) getWidth()) + { + const int row = (viewport->getViewPositionY() + y + rowHeight / 2 - viewport->getY()) / rowHeight; + return jlimit (0, totalItems, row); + } - return -1; + return -1; } Component* ListBox::getComponentForRowNumber (const int row) const throw() { - Component* const listRowComp = viewport->getComponentForRowIfOnscreen (row); - return listRowComp != 0 ? listRowComp->getChildComponent (0) : 0; + Component* const listRowComp = viewport->getComponentForRowIfOnscreen (row); + return listRowComp != 0 ? listRowComp->getChildComponent (0) : 0; } int ListBox::getRowNumberOfComponent (Component* const rowComponent) const throw() { - return viewport->getRowNumberOfComponent (rowComponent); + return viewport->getRowNumberOfComponent (rowComponent); } const Rectangle ListBox::getRowPosition (const int rowNumber, - const bool relativeToComponentTopLeft) const throw() + const bool relativeToComponentTopLeft) const throw() { - const int rowHeight = getRowHeight(); - int y = viewport->getY() + rowHeight * rowNumber; + const int rowHeight = getRowHeight(); + int y = viewport->getY() + rowHeight * rowNumber; - if (relativeToComponentTopLeft) - y -= viewport->getViewPositionY(); + if (relativeToComponentTopLeft) + y -= viewport->getViewPositionY(); - return Rectangle (viewport->getX(), y, - viewport->getViewedComponent()->getWidth(), rowHeight); + return Rectangle (viewport->getX(), y, + viewport->getViewedComponent()->getWidth(), rowHeight); } void ListBox::setVerticalPosition (const double proportion) { - const int offscreen = viewport->getViewedComponent()->getHeight() - viewport->getHeight(); + const int offscreen = viewport->getViewedComponent()->getHeight() - viewport->getHeight(); - viewport->setViewPosition (viewport->getViewPositionX(), - jmax (0, roundDoubleToInt (proportion * offscreen))); + viewport->setViewPosition (viewport->getViewPositionX(), + jmax (0, roundToInt (proportion * offscreen))); } double ListBox::getVerticalPosition() const { - const int offscreen = viewport->getViewedComponent()->getHeight() - viewport->getHeight(); + const int offscreen = viewport->getViewedComponent()->getHeight() - viewport->getHeight(); - return (offscreen > 0) ? viewport->getViewPositionY() / (double) offscreen - : 0; + return (offscreen > 0) ? viewport->getViewPositionY() / (double) offscreen + : 0; } int ListBox::getVisibleRowWidth() const throw() { - return viewport->getViewWidth(); + return viewport->getViewWidth(); } void ListBox::scrollToEnsureRowIsOnscreen (const int row) { - if (row < viewport->firstWholeIndex) - { - viewport->setViewPosition (viewport->getViewPositionX(), - row * getRowHeight()); - } - else if (row >= viewport->lastWholeIndex) - { - viewport->setViewPosition (viewport->getViewPositionX(), - jmax (0, (row + 1) * getRowHeight() - viewport->getMaximumVisibleHeight())); - } + if (row < viewport->firstWholeIndex) + { + viewport->setViewPosition (viewport->getViewPositionX(), + row * getRowHeight()); + } + else if (row >= viewport->lastWholeIndex) + { + viewport->setViewPosition (viewport->getViewPositionX(), + jmax (0, (row + 1) * getRowHeight() - viewport->getMaximumVisibleHeight())); + } } bool ListBox::keyPressed (const KeyPress& key) { - const int numVisibleRows = viewport->getHeight() / getRowHeight(); + const int numVisibleRows = viewport->getHeight() / getRowHeight(); - const bool multiple = multipleSelection - && (lastRowSelected >= 0) - && (key.getModifiers().isShiftDown() - || key.getModifiers().isCtrlDown() - || key.getModifiers().isCommandDown()); + const bool multiple = multipleSelection + && (lastRowSelected >= 0) + && (key.getModifiers().isShiftDown() + || key.getModifiers().isCtrlDown() + || key.getModifiers().isCommandDown()); - if (key.isKeyCode (KeyPress::upKey)) - { - if (multiple) - selectRangeOfRows (lastRowSelected, lastRowSelected - 1); - else - selectRow (jmax (0, lastRowSelected - 1)); - } - else if (key.isKeyCode (KeyPress::returnKey) - && isRowSelected (lastRowSelected)) - { - if (model != 0) - model->returnKeyPressed (lastRowSelected); - } - else if (key.isKeyCode (KeyPress::pageUpKey)) - { - if (multiple) - selectRangeOfRows (lastRowSelected, lastRowSelected - numVisibleRows); - else - selectRow (jmax (0, jmax (0, lastRowSelected) - numVisibleRows)); - } - else if (key.isKeyCode (KeyPress::pageDownKey)) - { - if (multiple) - selectRangeOfRows (lastRowSelected, lastRowSelected + numVisibleRows); - else - selectRow (jmin (totalItems - 1, jmax (0, lastRowSelected) + numVisibleRows)); - } - else if (key.isKeyCode (KeyPress::homeKey)) - { - if (multiple && key.getModifiers().isShiftDown()) - selectRangeOfRows (lastRowSelected, 0); - else - selectRow (0); - } - else if (key.isKeyCode (KeyPress::endKey)) - { - if (multiple && key.getModifiers().isShiftDown()) - selectRangeOfRows (lastRowSelected, totalItems - 1); - else - selectRow (totalItems - 1); - } - else if (key.isKeyCode (KeyPress::downKey)) - { - if (multiple) - selectRangeOfRows (lastRowSelected, lastRowSelected + 1); - else - selectRow (jmin (totalItems - 1, jmax (0, lastRowSelected) + 1)); - } - else if ((key.isKeyCode (KeyPress::deleteKey) || key.isKeyCode (KeyPress::backspaceKey)) - && isRowSelected (lastRowSelected)) - { - if (model != 0) - model->deleteKeyPressed (lastRowSelected); - } - else if (multiple && key == KeyPress (T('a'), ModifierKeys::commandModifier, 0)) - { - selectRangeOfRows (0, INT_MAX); - } - else - { - return false; - } + if (key.isKeyCode (KeyPress::upKey)) + { + if (multiple) + selectRangeOfRows (lastRowSelected, lastRowSelected - 1); + else + selectRow (jmax (0, lastRowSelected - 1)); + } + else if (key.isKeyCode (KeyPress::returnKey) + && isRowSelected (lastRowSelected)) + { + if (model != 0) + model->returnKeyPressed (lastRowSelected); + } + else if (key.isKeyCode (KeyPress::pageUpKey)) + { + if (multiple) + selectRangeOfRows (lastRowSelected, lastRowSelected - numVisibleRows); + else + selectRow (jmax (0, jmax (0, lastRowSelected) - numVisibleRows)); + } + else if (key.isKeyCode (KeyPress::pageDownKey)) + { + if (multiple) + selectRangeOfRows (lastRowSelected, lastRowSelected + numVisibleRows); + else + selectRow (jmin (totalItems - 1, jmax (0, lastRowSelected) + numVisibleRows)); + } + else if (key.isKeyCode (KeyPress::homeKey)) + { + if (multiple && key.getModifiers().isShiftDown()) + selectRangeOfRows (lastRowSelected, 0); + else + selectRow (0); + } + else if (key.isKeyCode (KeyPress::endKey)) + { + if (multiple && key.getModifiers().isShiftDown()) + selectRangeOfRows (lastRowSelected, totalItems - 1); + else + selectRow (totalItems - 1); + } + else if (key.isKeyCode (KeyPress::downKey)) + { + if (multiple) + selectRangeOfRows (lastRowSelected, lastRowSelected + 1); + else + selectRow (jmin (totalItems - 1, jmax (0, lastRowSelected) + 1)); + } + else if ((key.isKeyCode (KeyPress::deleteKey) || key.isKeyCode (KeyPress::backspaceKey)) + && isRowSelected (lastRowSelected)) + { + if (model != 0) + model->deleteKeyPressed (lastRowSelected); + } + else if (multiple && key == KeyPress (T('a'), ModifierKeys::commandModifier, 0)) + { + selectRangeOfRows (0, INT_MAX); + } + else + { + return false; + } - return true; + return true; } bool ListBox::keyStateChanged (const bool isKeyDown) { - return isKeyDown - && (KeyPress::isKeyCurrentlyDown (KeyPress::upKey) - || KeyPress::isKeyCurrentlyDown (KeyPress::pageUpKey) - || KeyPress::isKeyCurrentlyDown (KeyPress::downKey) - || KeyPress::isKeyCurrentlyDown (KeyPress::pageDownKey) - || KeyPress::isKeyCurrentlyDown (KeyPress::homeKey) - || KeyPress::isKeyCurrentlyDown (KeyPress::endKey) - || KeyPress::isKeyCurrentlyDown (KeyPress::returnKey)); + return isKeyDown + && (KeyPress::isKeyCurrentlyDown (KeyPress::upKey) + || KeyPress::isKeyCurrentlyDown (KeyPress::pageUpKey) + || KeyPress::isKeyCurrentlyDown (KeyPress::downKey) + || KeyPress::isKeyCurrentlyDown (KeyPress::pageDownKey) + || KeyPress::isKeyCurrentlyDown (KeyPress::homeKey) + || KeyPress::isKeyCurrentlyDown (KeyPress::endKey) + || KeyPress::isKeyCurrentlyDown (KeyPress::returnKey)); } void ListBox::mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY) { - getHorizontalScrollBar()->mouseWheelMove (e, wheelIncrementX, 0); - getVerticalScrollBar()->mouseWheelMove (e, 0, wheelIncrementY); + getHorizontalScrollBar()->mouseWheelMove (e, wheelIncrementX, 0); + getVerticalScrollBar()->mouseWheelMove (e, 0, wheelIncrementY); } void ListBox::mouseMove (const MouseEvent& e) { - if (mouseMoveSelects) - { - const MouseEvent e2 (e.getEventRelativeTo (this)); + if (mouseMoveSelects) + { + const MouseEvent e2 (e.getEventRelativeTo (this)); - selectRow (getRowContainingPosition (e2.x, e2.y), true); + selectRow (getRowContainingPosition (e2.x, e2.y), true); - lastMouseX = e2.x; - lastMouseY = e2.y; - } + lastMouseX = e2.x; + lastMouseY = e2.y; + } } void ListBox::mouseExit (const MouseEvent& e) { - mouseMove (e); + mouseMove (e); } void ListBox::mouseUp (const MouseEvent& e) { - if (e.mouseWasClicked() && model != 0) - model->backgroundClicked(); + if (e.mouseWasClicked() && model != 0) + model->backgroundClicked(); } void ListBox::setRowHeight (const int newHeight) { - rowHeight = jmax (1, newHeight); - viewport->setSingleStepSizes (20, rowHeight); - updateContent(); + rowHeight = jmax (1, newHeight); + viewport->setSingleStepSizes (20, rowHeight); + updateContent(); } int ListBox::getNumRowsOnScreen() const throw() { - return viewport->getMaximumVisibleHeight() / rowHeight; + return viewport->getMaximumVisibleHeight() / rowHeight; } void ListBox::setMinimumContentWidth (const int newMinimumWidth) { - minimumRowWidth = newMinimumWidth; - updateContent(); + minimumRowWidth = newMinimumWidth; + updateContent(); } int ListBox::getVisibleContentWidth() const throw() { - return viewport->getMaximumVisibleWidth(); + return viewport->getMaximumVisibleWidth(); } ScrollBar* ListBox::getVerticalScrollBar() const throw() { - return viewport->getVerticalScrollBar(); + return viewport->getVerticalScrollBar(); } ScrollBar* ListBox::getHorizontalScrollBar() const throw() { - return viewport->getHorizontalScrollBar(); + return viewport->getHorizontalScrollBar(); } void ListBox::colourChanged() { - setOpaque (findColour (backgroundColourId).isOpaque()); - viewport->setOpaque (isOpaque()); - repaint(); + setOpaque (findColour (backgroundColourId).isOpaque()); + viewport->setOpaque (isOpaque()); + repaint(); } void ListBox::setOutlineThickness (const int outlineThickness_) { - outlineThickness = outlineThickness_; - resized(); + outlineThickness = outlineThickness_; + resized(); } void ListBox::setHeaderComponent (Component* const newHeaderComponent) { - if (headerComponent != newHeaderComponent) - { - delete headerComponent; - headerComponent = newHeaderComponent; + if (headerComponent != newHeaderComponent) + { + delete headerComponent; + headerComponent = newHeaderComponent; - addAndMakeVisible (newHeaderComponent); - ListBox::resized(); - } + addAndMakeVisible (newHeaderComponent); + ListBox::resized(); + } } void ListBox::repaintRow (const int rowNumber) throw() { - const Rectangle r (getRowPosition (rowNumber, true)); - repaint (r.getX(), r.getY(), r.getWidth(), r.getHeight()); + const Rectangle r (getRowPosition (rowNumber, true)); + repaint (r.getX(), r.getY(), r.getWidth(), r.getHeight()); } Image* ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) { - Rectangle imageArea; - const int firstRow = getRowContainingPosition (0, 0); + Rectangle imageArea; + const int firstRow = getRowContainingPosition (0, 0); - int i; - for (i = getNumRowsOnScreen() + 2; --i >= 0;) - { - Component* rowComp = viewport->getComponentForRowIfOnscreen (firstRow + i); + int i; + for (i = getNumRowsOnScreen() + 2; --i >= 0;) + { + Component* rowComp = viewport->getComponentForRowIfOnscreen (firstRow + i); - if (rowComp != 0 && isRowSelected (firstRow + i)) - { - int x = 0, y = 0; - rowComp->relativePositionToOtherComponent (this, x, y); + if (rowComp != 0 && isRowSelected (firstRow + i)) + { + int x = 0, y = 0; + rowComp->relativePositionToOtherComponent (this, x, y); - const Rectangle rowRect (x, y, rowComp->getWidth(), rowComp->getHeight()); + const Rectangle rowRect (x, y, rowComp->getWidth(), rowComp->getHeight()); - if (imageArea.isEmpty()) - imageArea = rowRect; - else - imageArea = imageArea.getUnion (rowRect); - } - } + if (imageArea.isEmpty()) + imageArea = rowRect; + else + imageArea = imageArea.getUnion (rowRect); + } + } - imageArea = imageArea.getIntersection (Rectangle (0, 0, getWidth(), getHeight())); - imageX = imageArea.getX(); - imageY = imageArea.getY(); - Image* snapshot = Image::createNativeImage (Image::ARGB, imageArea.getWidth(), imageArea.getHeight(), true); + imageArea = imageArea.getIntersection (Rectangle (0, 0, getWidth(), getHeight())); + imageX = imageArea.getX(); + imageY = imageArea.getY(); + Image* snapshot = Image::createNativeImage (Image::ARGB, imageArea.getWidth(), imageArea.getHeight(), true); - for (i = getNumRowsOnScreen() + 2; --i >= 0;) - { - Component* rowComp = viewport->getComponentForRowIfOnscreen (firstRow + i); + for (i = getNumRowsOnScreen() + 2; --i >= 0;) + { + Component* rowComp = viewport->getComponentForRowIfOnscreen (firstRow + i); - if (rowComp != 0 && isRowSelected (firstRow + i)) - { - int x = 0, y = 0; - rowComp->relativePositionToOtherComponent (this, x, y); + if (rowComp != 0 && isRowSelected (firstRow + i)) + { + int x = 0, y = 0; + rowComp->relativePositionToOtherComponent (this, x, y); - Graphics g (*snapshot); - g.setOrigin (x - imageX, y - imageY); - if (g.reduceClipRegion (0, 0, rowComp->getWidth(), rowComp->getHeight())) - rowComp->paintEntireComponent (g); - } - } + Graphics g (*snapshot); + g.setOrigin (x - imageX, y - imageY); + if (g.reduceClipRegion (0, 0, rowComp->getWidth(), rowComp->getHeight())) + rowComp->paintEntireComponent (g); + } + } - return snapshot; + return snapshot; } void ListBox::startDragAndDrop (const MouseEvent& e, const String& dragDescription) { - DragAndDropContainer* const dragContainer - = DragAndDropContainer::findParentDragContainerFor (this); + DragAndDropContainer* const dragContainer + = DragAndDropContainer::findParentDragContainerFor (this); - if (dragContainer != 0) - { - int x, y; - Image* dragImage = createSnapshotOfSelectedRows (x, y); - dragImage->multiplyAllAlphas (0.6f); + if (dragContainer != 0) + { + int x, y; + Image* dragImage = createSnapshotOfSelectedRows (x, y); + dragImage->multiplyAllAlphas (0.6f); - MouseEvent e2 (e.getEventRelativeTo (this)); - const Point p ((float) (x - e2.x), (float) (y - e2.y)); - dragContainer->startDragging (dragDescription, this, dragImage, true, &p); - } - else - { - // to be able to do a drag-and-drop operation, the listbox needs to - // be inside a component which is also a DragAndDropContainer. - jassertfalse - } + MouseEvent e2 (e.getEventRelativeTo (this)); + const Point p ((float) (x - e2.x), (float) (y - e2.y)); + dragContainer->startDragging (dragDescription, this, dragImage, true, &p); + } + else + { + // to be able to do a drag-and-drop operation, the listbox needs to + // be inside a component which is also a DragAndDropContainer. + jassertfalse + } } Component* ListBoxModel::refreshComponentForRow (int, bool, Component* existingComponentToUpdate) { - (void) existingComponentToUpdate; - jassert (existingComponentToUpdate == 0); // indicates a failure in the code the recycles the components - return 0; + (void) existingComponentToUpdate; + jassert (existingComponentToUpdate == 0); // indicates a failure in the code the recycles the components + return 0; } void ListBoxModel::listBoxItemClicked (int, const MouseEvent&) @@ -48739,12 +48445,12 @@ void ListBoxModel::listWasScrolled() const String ListBoxModel::getDragSourceDescription (const SparseSet&) { - return String::empty; + return String::empty; } const String ListBoxModel::getTooltipForRow (int row) { - return String::empty; + return String::empty; } END_JUCE_NAMESPACE @@ -48756,10 +48462,10 @@ BEGIN_JUCE_NAMESPACE ProgressBar::ProgressBar (double& progress_) : progress (progress_), - displayPercentage (true), - lastCallbackTime (0) + displayPercentage (true), + lastCallbackTime (0) { - currentValue = jlimit (0.0, 1.0, progress); + currentValue = jlimit (0.0, 1.0, progress); } ProgressBar::~ProgressBar() @@ -48768,77 +48474,77 @@ ProgressBar::~ProgressBar() void ProgressBar::setPercentageDisplay (const bool shouldDisplayPercentage) { - displayPercentage = shouldDisplayPercentage; - repaint(); + displayPercentage = shouldDisplayPercentage; + repaint(); } void ProgressBar::setTextToDisplay (const String& text) { - displayPercentage = false; - displayedMessage = text; + displayPercentage = false; + displayedMessage = text; } void ProgressBar::lookAndFeelChanged() { - setOpaque (findColour (backgroundColourId).isOpaque()); + setOpaque (findColour (backgroundColourId).isOpaque()); } void ProgressBar::colourChanged() { - lookAndFeelChanged(); + lookAndFeelChanged(); } void ProgressBar::paint (Graphics& g) { - String text; + String text; - if (displayPercentage) - { - if (currentValue >= 0 && currentValue <= 1.0) - text << roundDoubleToInt (currentValue * 100.0) << T("%"); - } - else - { - text = displayedMessage; - } + if (displayPercentage) + { + if (currentValue >= 0 && currentValue <= 1.0) + text << roundToInt (currentValue * 100.0) << T("%"); + } + else + { + text = displayedMessage; + } - getLookAndFeel().drawProgressBar (g, *this, - getWidth(), getHeight(), - currentValue, text); + getLookAndFeel().drawProgressBar (g, *this, + getWidth(), getHeight(), + currentValue, text); } void ProgressBar::visibilityChanged() { - if (isVisible()) - startTimer (30); - else - stopTimer(); + if (isVisible()) + startTimer (30); + else + stopTimer(); } void ProgressBar::timerCallback() { - double newProgress = progress; + double newProgress = progress; - const uint32 now = Time::getMillisecondCounter(); - const int timeSinceLastCallback = (int) (now - lastCallbackTime); - lastCallbackTime = now; + const uint32 now = Time::getMillisecondCounter(); + const int timeSinceLastCallback = (int) (now - lastCallbackTime); + lastCallbackTime = now; - if (currentValue != newProgress - || newProgress < 0 || newProgress >= 1.0 - || currentMessage != displayedMessage) - { - if (currentValue < newProgress - && newProgress >= 0 && newProgress < 1.0 - && currentValue >= 0 && currentValue < 1.0) - { - newProgress = jmin (currentValue + 0.0008 * timeSinceLastCallback, - newProgress); - } + if (currentValue != newProgress + || newProgress < 0 || newProgress >= 1.0 + || currentMessage != displayedMessage) + { + if (currentValue < newProgress + && newProgress >= 0 && newProgress < 1.0 + && currentValue >= 0 && currentValue < 1.0) + { + newProgress = jmin (currentValue + 0.0008 * timeSinceLastCallback, + newProgress); + } - currentValue = newProgress; - currentMessage = displayedMessage; - repaint(); - } + currentValue = newProgress; + currentMessage = displayedMessage; + repaint(); + } } END_JUCE_NAMESPACE @@ -48852,636 +48558,635 @@ class SliderPopupDisplayComponent : public BubbleComponent { public: - SliderPopupDisplayComponent (Slider* const owner_) - : owner (owner_), - font (15.0f, Font::bold) - { - setAlwaysOnTop (true); - } + SliderPopupDisplayComponent (Slider* const owner_) + : owner (owner_), + font (15.0f, Font::bold) + { + setAlwaysOnTop (true); + } - ~SliderPopupDisplayComponent() - { - } + ~SliderPopupDisplayComponent() + { + } - void paintContent (Graphics& g, int w, int h) - { - g.setFont (font); - g.setColour (Colours::black); + void paintContent (Graphics& g, int w, int h) + { + g.setFont (font); + g.setColour (Colours::black); - g.drawFittedText (text, 0, 0, w, h, Justification::centred, 1); - } + g.drawFittedText (text, 0, 0, w, h, Justification::centred, 1); + } - void getContentSize (int& w, int& h) - { - w = font.getStringWidth (text) + 18; - h = (int) (font.getHeight() * 1.6f); - } + void getContentSize (int& w, int& h) + { + w = font.getStringWidth (text) + 18; + h = (int) (font.getHeight() * 1.6f); + } - void updatePosition (const String& newText) - { - if (text != newText) - { - text = newText; - repaint(); - } + void updatePosition (const String& newText) + { + if (text != newText) + { + text = newText; + repaint(); + } - BubbleComponent::setPosition (owner); - } + BubbleComponent::setPosition (owner); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - Slider* owner; - Font font; - String text; + Slider* owner; + Font font; + String text; - SliderPopupDisplayComponent (const SliderPopupDisplayComponent&); - const SliderPopupDisplayComponent& operator= (const SliderPopupDisplayComponent&); + SliderPopupDisplayComponent (const SliderPopupDisplayComponent&); + const SliderPopupDisplayComponent& operator= (const SliderPopupDisplayComponent&); }; Slider::Slider (const String& name) : Component (name), - listeners (2), - lastCurrentValue (0), - lastValueMin (0), - lastValueMax (0), - minimum (0), - maximum (10), - interval (0), - skewFactor (1.0), - velocityModeSensitivity (1.0), - velocityModeOffset (0.0), - velocityModeThreshold (1), - rotaryStart (float_Pi * 1.2f), - rotaryEnd (float_Pi * 2.8f), - numDecimalPlaces (7), - sliderRegionStart (0), - sliderRegionSize (1), - sliderBeingDragged (-1), - pixelsForFullDragExtent (250), - style (LinearHorizontal), - textBoxPos (TextBoxLeft), - textBoxWidth (80), - textBoxHeight (20), - incDecButtonMode (incDecButtonsNotDraggable), - editableText (true), - doubleClickToValue (false), - isVelocityBased (false), - userKeyOverridesVelocity (true), - rotaryStop (true), - incDecButtonsSideBySide (false), - sendChangeOnlyOnRelease (false), - popupDisplayEnabled (false), - menuEnabled (false), - menuShown (false), - scrollWheelEnabled (true), - snapsToMousePos (true), - valueBox (0), - incButton (0), - decButton (0), - popupDisplay (0), - parentForPopupDisplay (0) + lastCurrentValue (0), + lastValueMin (0), + lastValueMax (0), + minimum (0), + maximum (10), + interval (0), + skewFactor (1.0), + velocityModeSensitivity (1.0), + velocityModeOffset (0.0), + velocityModeThreshold (1), + rotaryStart (float_Pi * 1.2f), + rotaryEnd (float_Pi * 2.8f), + numDecimalPlaces (7), + sliderRegionStart (0), + sliderRegionSize (1), + sliderBeingDragged (-1), + pixelsForFullDragExtent (250), + style (LinearHorizontal), + textBoxPos (TextBoxLeft), + textBoxWidth (80), + textBoxHeight (20), + incDecButtonMode (incDecButtonsNotDraggable), + editableText (true), + doubleClickToValue (false), + isVelocityBased (false), + userKeyOverridesVelocity (true), + rotaryStop (true), + incDecButtonsSideBySide (false), + sendChangeOnlyOnRelease (false), + popupDisplayEnabled (false), + menuEnabled (false), + menuShown (false), + scrollWheelEnabled (true), + snapsToMousePos (true), + valueBox (0), + incButton (0), + decButton (0), + popupDisplay (0), + parentForPopupDisplay (0) { - setWantsKeyboardFocus (false); - setRepaintsOnMouseActivity (true); + setWantsKeyboardFocus (false); + setRepaintsOnMouseActivity (true); - lookAndFeelChanged(); - updateText(); + lookAndFeelChanged(); + updateText(); - currentValue.addListener (this); - valueMin.addListener (this); - valueMax.addListener (this); + currentValue.addListener (this); + valueMin.addListener (this); + valueMax.addListener (this); } Slider::~Slider() { - currentValue.removeListener (this); - valueMin.removeListener (this); - valueMax.removeListener (this); - popupDisplay = 0; - deleteAllChildren(); + currentValue.removeListener (this); + valueMin.removeListener (this); + valueMax.removeListener (this); + popupDisplay = 0; + deleteAllChildren(); } void Slider::handleAsyncUpdate() { - cancelPendingUpdate(); + cancelPendingUpdate(); - for (int i = listeners.size(); --i >= 0;) - { - ((SliderListener*) listeners.getUnchecked (i))->sliderValueChanged (this); - i = jmin (i, listeners.size()); - } + for (int i = listeners.size(); --i >= 0;) + { + ((SliderListener*) listeners.getUnchecked (i))->sliderValueChanged (this); + i = jmin (i, listeners.size()); + } } void Slider::sendDragStart() { - startedDragging(); + startedDragging(); - for (int i = listeners.size(); --i >= 0;) - { - ((SliderListener*) listeners.getUnchecked (i))->sliderDragStarted (this); - i = jmin (i, listeners.size()); - } + for (int i = listeners.size(); --i >= 0;) + { + ((SliderListener*) listeners.getUnchecked (i))->sliderDragStarted (this); + i = jmin (i, listeners.size()); + } } void Slider::sendDragEnd() { - stoppedDragging(); + stoppedDragging(); - sliderBeingDragged = -1; + sliderBeingDragged = -1; - for (int i = listeners.size(); --i >= 0;) - { - ((SliderListener*) listeners.getUnchecked (i))->sliderDragEnded (this); - i = jmin (i, listeners.size()); - } + for (int i = listeners.size(); --i >= 0;) + { + ((SliderListener*) listeners.getUnchecked (i))->sliderDragEnded (this); + i = jmin (i, listeners.size()); + } } void Slider::addListener (SliderListener* const listener) { - jassert (listener != 0); - if (listener != 0) - listeners.add (listener); + jassert (listener != 0); + if (listener != 0) + listeners.add (listener); } void Slider::removeListener (SliderListener* const listener) { - listeners.removeValue (listener); + listeners.removeValue (listener); } void Slider::setSliderStyle (const SliderStyle newStyle) { - if (style != newStyle) - { - style = newStyle; - repaint(); - lookAndFeelChanged(); - } + if (style != newStyle) + { + style = newStyle; + repaint(); + lookAndFeelChanged(); + } } void Slider::setRotaryParameters (const float startAngleRadians, - const float endAngleRadians, - const bool stopAtEnd) + const float endAngleRadians, + const bool stopAtEnd) { - // make sure the values are sensible.. - jassert (rotaryStart >= 0 && rotaryEnd >= 0); - jassert (rotaryStart < float_Pi * 4.0f && rotaryEnd < float_Pi * 4.0f); - jassert (rotaryStart < rotaryEnd); + // make sure the values are sensible.. + jassert (rotaryStart >= 0 && rotaryEnd >= 0); + jassert (rotaryStart < float_Pi * 4.0f && rotaryEnd < float_Pi * 4.0f); + jassert (rotaryStart < rotaryEnd); - rotaryStart = startAngleRadians; - rotaryEnd = endAngleRadians; - rotaryStop = stopAtEnd; + rotaryStart = startAngleRadians; + rotaryEnd = endAngleRadians; + rotaryStop = stopAtEnd; } void Slider::setVelocityBasedMode (const bool velBased) { - isVelocityBased = velBased; + isVelocityBased = velBased; } void Slider::setVelocityModeParameters (const double sensitivity, - const int threshold, - const double offset, - const bool userCanPressKeyToSwapMode) + const int threshold, + const double offset, + const bool userCanPressKeyToSwapMode) { - jassert (threshold >= 0); - jassert (sensitivity > 0); - jassert (offset >= 0); + jassert (threshold >= 0); + jassert (sensitivity > 0); + jassert (offset >= 0); - velocityModeSensitivity = sensitivity; - velocityModeOffset = offset; - velocityModeThreshold = threshold; - userKeyOverridesVelocity = userCanPressKeyToSwapMode; + velocityModeSensitivity = sensitivity; + velocityModeOffset = offset; + velocityModeThreshold = threshold; + userKeyOverridesVelocity = userCanPressKeyToSwapMode; } void Slider::setSkewFactor (const double factor) { - skewFactor = factor; + skewFactor = factor; } void Slider::setSkewFactorFromMidPoint (const double sliderValueToShowAtMidPoint) { - if (maximum > minimum) - skewFactor = log (0.5) / log ((sliderValueToShowAtMidPoint - minimum) - / (maximum - minimum)); + if (maximum > minimum) + skewFactor = log (0.5) / log ((sliderValueToShowAtMidPoint - minimum) + / (maximum - minimum)); } void Slider::setMouseDragSensitivity (const int distanceForFullScaleDrag) { - jassert (distanceForFullScaleDrag > 0); + jassert (distanceForFullScaleDrag > 0); - pixelsForFullDragExtent = distanceForFullScaleDrag; + pixelsForFullDragExtent = distanceForFullScaleDrag; } void Slider::setIncDecButtonsMode (const IncDecButtonMode mode) { - if (incDecButtonMode != mode) - { - incDecButtonMode = mode; - lookAndFeelChanged(); - } + if (incDecButtonMode != mode) + { + incDecButtonMode = mode; + lookAndFeelChanged(); + } } void Slider::setTextBoxStyle (const TextEntryBoxPosition newPosition, - const bool isReadOnly, - const int textEntryBoxWidth, - const int textEntryBoxHeight) + const bool isReadOnly, + const int textEntryBoxWidth, + const int textEntryBoxHeight) { - textBoxPos = newPosition; - editableText = ! isReadOnly; - textBoxWidth = textEntryBoxWidth; - textBoxHeight = textEntryBoxHeight; + textBoxPos = newPosition; + editableText = ! isReadOnly; + textBoxWidth = textEntryBoxWidth; + textBoxHeight = textEntryBoxHeight; - repaint(); - lookAndFeelChanged(); + repaint(); + lookAndFeelChanged(); } void Slider::setTextBoxIsEditable (const bool shouldBeEditable) { - editableText = shouldBeEditable; + editableText = shouldBeEditable; - if (valueBox != 0) - valueBox->setEditable (shouldBeEditable && isEnabled()); + if (valueBox != 0) + valueBox->setEditable (shouldBeEditable && isEnabled()); } void Slider::showTextBox() { - jassert (editableText); // this should probably be avoided in read-only sliders. + jassert (editableText); // this should probably be avoided in read-only sliders. - if (valueBox != 0) - valueBox->showEditor(); + if (valueBox != 0) + valueBox->showEditor(); } void Slider::hideTextBox (const bool discardCurrentEditorContents) { - if (valueBox != 0) - { - valueBox->hideEditor (discardCurrentEditorContents); + if (valueBox != 0) + { + valueBox->hideEditor (discardCurrentEditorContents); - if (discardCurrentEditorContents) - updateText(); - } + if (discardCurrentEditorContents) + updateText(); + } } void Slider::setChangeNotificationOnlyOnRelease (const bool onlyNotifyOnRelease) { - sendChangeOnlyOnRelease = onlyNotifyOnRelease; + sendChangeOnlyOnRelease = onlyNotifyOnRelease; } void Slider::setSliderSnapsToMousePosition (const bool shouldSnapToMouse) { - snapsToMousePos = shouldSnapToMouse; + snapsToMousePos = shouldSnapToMouse; } void Slider::setPopupDisplayEnabled (const bool enabled, - Component* const parentComponentToUse) + Component* const parentComponentToUse) { - popupDisplayEnabled = enabled; - parentForPopupDisplay = parentComponentToUse; + popupDisplayEnabled = enabled; + parentForPopupDisplay = parentComponentToUse; } void Slider::colourChanged() { - lookAndFeelChanged(); + lookAndFeelChanged(); } void Slider::lookAndFeelChanged() { - const String previousTextBoxContent (valueBox != 0 ? valueBox->getText() - : getTextFromValue (currentValue.getValue())); + const String previousTextBoxContent (valueBox != 0 ? valueBox->getText() + : getTextFromValue (currentValue.getValue())); - deleteAllChildren(); - valueBox = 0; + deleteAllChildren(); + valueBox = 0; - LookAndFeel& lf = getLookAndFeel(); + LookAndFeel& lf = getLookAndFeel(); - if (textBoxPos != NoTextBox) - { - addAndMakeVisible (valueBox = getLookAndFeel().createSliderTextBox (*this)); + if (textBoxPos != NoTextBox) + { + addAndMakeVisible (valueBox = getLookAndFeel().createSliderTextBox (*this)); - valueBox->setWantsKeyboardFocus (false); - valueBox->setText (previousTextBoxContent, false); + valueBox->setWantsKeyboardFocus (false); + valueBox->setText (previousTextBoxContent, false); - valueBox->setEditable (editableText && isEnabled()); - valueBox->addListener (this); + valueBox->setEditable (editableText && isEnabled()); + valueBox->addListener (this); - if (style == LinearBar) - valueBox->addMouseListener (this, false); + if (style == LinearBar) + valueBox->addMouseListener (this, false); - valueBox->setTooltip (getTooltip()); - } + valueBox->setTooltip (getTooltip()); + } - if (style == IncDecButtons) - { - addAndMakeVisible (incButton = lf.createSliderButton (true)); - incButton->addButtonListener (this); + if (style == IncDecButtons) + { + addAndMakeVisible (incButton = lf.createSliderButton (true)); + incButton->addButtonListener (this); - addAndMakeVisible (decButton = lf.createSliderButton (false)); - decButton->addButtonListener (this); + addAndMakeVisible (decButton = lf.createSliderButton (false)); + decButton->addButtonListener (this); - if (incDecButtonMode != incDecButtonsNotDraggable) - { - incButton->addMouseListener (this, false); - decButton->addMouseListener (this, false); - } - else - { - incButton->setRepeatSpeed (300, 100, 20); - incButton->addMouseListener (decButton, false); + if (incDecButtonMode != incDecButtonsNotDraggable) + { + incButton->addMouseListener (this, false); + decButton->addMouseListener (this, false); + } + else + { + incButton->setRepeatSpeed (300, 100, 20); + incButton->addMouseListener (decButton, false); - decButton->setRepeatSpeed (300, 100, 20); - decButton->addMouseListener (incButton, false); - } + decButton->setRepeatSpeed (300, 100, 20); + decButton->addMouseListener (incButton, false); + } - incButton->setTooltip (getTooltip()); - decButton->setTooltip (getTooltip()); - } + incButton->setTooltip (getTooltip()); + decButton->setTooltip (getTooltip()); + } - setComponentEffect (lf.getSliderEffect()); + setComponentEffect (lf.getSliderEffect()); - resized(); - repaint(); + resized(); + repaint(); } void Slider::setRange (const double newMin, - const double newMax, - const double newInt) + const double newMax, + const double newInt) { - if (minimum != newMin - || maximum != newMax - || interval != newInt) - { - minimum = newMin; - maximum = newMax; - interval = newInt; + if (minimum != newMin + || maximum != newMax + || interval != newInt) + { + minimum = newMin; + maximum = newMax; + interval = newInt; - // figure out the number of DPs needed to display all values at this - // interval setting. - numDecimalPlaces = 7; + // figure out the number of DPs needed to display all values at this + // interval setting. + numDecimalPlaces = 7; - if (newInt != 0) - { - int v = abs ((int) (newInt * 10000000)); + if (newInt != 0) + { + int v = abs ((int) (newInt * 10000000)); - while ((v % 10) == 0) - { - --numDecimalPlaces; - v /= 10; - } - } + while ((v % 10) == 0) + { + --numDecimalPlaces; + v /= 10; + } + } - // keep the current values inside the new range.. - if (style != TwoValueHorizontal && style != TwoValueVertical) - { - setValue (getValue(), false, false); - } - else - { - setMinValue (getMinValue(), false, false); - setMaxValue (getMaxValue(), false, false); - } + // keep the current values inside the new range.. + if (style != TwoValueHorizontal && style != TwoValueVertical) + { + setValue (getValue(), false, false); + } + else + { + setMinValue (getMinValue(), false, false); + setMaxValue (getMaxValue(), false, false); + } - updateText(); - } + updateText(); + } } void Slider::triggerChangeMessage (const bool synchronous) { - if (synchronous) - handleAsyncUpdate(); - else - triggerAsyncUpdate(); + if (synchronous) + handleAsyncUpdate(); + else + triggerAsyncUpdate(); - valueChanged(); + valueChanged(); } void Slider::valueChanged (Value& value) { - if (value.refersToSameSourceAs (currentValue)) - { - if (style != TwoValueHorizontal && style != TwoValueVertical) - setValue (currentValue.getValue(), false, false); - } - else if (value.refersToSameSourceAs (valueMin)) - setMinValue (valueMin.getValue(), false, false, true); - else if (value.refersToSameSourceAs (valueMax)) - setMaxValue (valueMax.getValue(), false, false, true); + if (value.refersToSameSourceAs (currentValue)) + { + if (style != TwoValueHorizontal && style != TwoValueVertical) + setValue (currentValue.getValue(), false, false); + } + else if (value.refersToSameSourceAs (valueMin)) + setMinValue (valueMin.getValue(), false, false, true); + else if (value.refersToSameSourceAs (valueMax)) + setMaxValue (valueMax.getValue(), false, false, true); } double Slider::getValue() const { - // for a two-value style slider, you should use the getMinValue() and getMaxValue() - // methods to get the two values. - jassert (style != TwoValueHorizontal && style != TwoValueVertical); + // for a two-value style slider, you should use the getMinValue() and getMaxValue() + // methods to get the two values. + jassert (style != TwoValueHorizontal && style != TwoValueVertical); - return currentValue.getValue(); + return currentValue.getValue(); } void Slider::setValue (double newValue, - const bool sendUpdateMessage, - const bool sendMessageSynchronously) + const bool sendUpdateMessage, + const bool sendMessageSynchronously) { - // for a two-value style slider, you should use the setMinValue() and setMaxValue() - // methods to set the two values. - jassert (style != TwoValueHorizontal && style != TwoValueVertical); + // for a two-value style slider, you should use the setMinValue() and setMaxValue() + // methods to set the two values. + jassert (style != TwoValueHorizontal && style != TwoValueVertical); - newValue = constrainedValue (newValue); + newValue = constrainedValue (newValue); - if (style == ThreeValueHorizontal || style == ThreeValueVertical) - { - jassert ((double) valueMin.getValue() <= (double) valueMax.getValue()); + if (style == ThreeValueHorizontal || style == ThreeValueVertical) + { + jassert ((double) valueMin.getValue() <= (double) valueMax.getValue()); - newValue = jlimit ((double) valueMin.getValue(), - (double) valueMax.getValue(), - newValue); - } + newValue = jlimit ((double) valueMin.getValue(), + (double) valueMax.getValue(), + newValue); + } - if (newValue != lastCurrentValue) - { - if (valueBox != 0) - valueBox->hideEditor (true); + if (newValue != lastCurrentValue) + { + if (valueBox != 0) + valueBox->hideEditor (true); - lastCurrentValue = newValue; - currentValue = newValue; - updateText(); - repaint(); + lastCurrentValue = newValue; + currentValue = newValue; + updateText(); + repaint(); - if (popupDisplay != 0) - { - ((SliderPopupDisplayComponent*) popupDisplay)->updatePosition (getTextFromValue (newValue)); - popupDisplay->repaint(); - } + if (popupDisplay != 0) + { + ((SliderPopupDisplayComponent*) popupDisplay)->updatePosition (getTextFromValue (newValue)); + popupDisplay->repaint(); + } - if (sendUpdateMessage) - triggerChangeMessage (sendMessageSynchronously); - } + if (sendUpdateMessage) + triggerChangeMessage (sendMessageSynchronously); + } } double Slider::getMinValue() const { - // The minimum value only applies to sliders that are in two- or three-value mode. - jassert (style == TwoValueHorizontal || style == TwoValueVertical - || style == ThreeValueHorizontal || style == ThreeValueVertical); + // The minimum value only applies to sliders that are in two- or three-value mode. + jassert (style == TwoValueHorizontal || style == TwoValueVertical + || style == ThreeValueHorizontal || style == ThreeValueVertical); - return valueMin.getValue(); + return valueMin.getValue(); } double Slider::getMaxValue() const { - // The maximum value only applies to sliders that are in two- or three-value mode. - jassert (style == TwoValueHorizontal || style == TwoValueVertical - || style == ThreeValueHorizontal || style == ThreeValueVertical); + // The maximum value only applies to sliders that are in two- or three-value mode. + jassert (style == TwoValueHorizontal || style == TwoValueVertical + || style == ThreeValueHorizontal || style == ThreeValueVertical); - return valueMax.getValue(); + return valueMax.getValue(); } void Slider::setMinValue (double newValue, const bool sendUpdateMessage, const bool sendMessageSynchronously, const bool allowNudgingOfOtherValues) { - // The minimum value only applies to sliders that are in two- or three-value mode. - jassert (style == TwoValueHorizontal || style == TwoValueVertical - || style == ThreeValueHorizontal || style == ThreeValueVertical); + // The minimum value only applies to sliders that are in two- or three-value mode. + jassert (style == TwoValueHorizontal || style == TwoValueVertical + || style == ThreeValueHorizontal || style == ThreeValueVertical); - newValue = constrainedValue (newValue); + newValue = constrainedValue (newValue); - if (style == TwoValueHorizontal || style == TwoValueVertical) - { - if (allowNudgingOfOtherValues && newValue > (double) valueMax.getValue()) - setMaxValue (newValue, sendUpdateMessage, sendMessageSynchronously); + if (style == TwoValueHorizontal || style == TwoValueVertical) + { + if (allowNudgingOfOtherValues && newValue > (double) valueMax.getValue()) + setMaxValue (newValue, sendUpdateMessage, sendMessageSynchronously); - newValue = jmin ((double) valueMax.getValue(), newValue); - } - else - { - if (allowNudgingOfOtherValues && newValue > lastCurrentValue) - setValue (newValue, sendUpdateMessage, sendMessageSynchronously); + newValue = jmin ((double) valueMax.getValue(), newValue); + } + else + { + if (allowNudgingOfOtherValues && newValue > lastCurrentValue) + setValue (newValue, sendUpdateMessage, sendMessageSynchronously); - newValue = jmin (lastCurrentValue, newValue); - } + newValue = jmin (lastCurrentValue, newValue); + } - if (lastValueMin != newValue) - { - lastValueMin = newValue; - valueMin = newValue; - repaint(); + if (lastValueMin != newValue) + { + lastValueMin = newValue; + valueMin = newValue; + repaint(); - if (popupDisplay != 0) - { - ((SliderPopupDisplayComponent*) popupDisplay)->updatePosition (getTextFromValue (newValue)); - popupDisplay->repaint(); - } + if (popupDisplay != 0) + { + ((SliderPopupDisplayComponent*) popupDisplay)->updatePosition (getTextFromValue (newValue)); + popupDisplay->repaint(); + } - if (sendUpdateMessage) - triggerChangeMessage (sendMessageSynchronously); - } + if (sendUpdateMessage) + triggerChangeMessage (sendMessageSynchronously); + } } void Slider::setMaxValue (double newValue, const bool sendUpdateMessage, const bool sendMessageSynchronously, const bool allowNudgingOfOtherValues) { - // The maximum value only applies to sliders that are in two- or three-value mode. - jassert (style == TwoValueHorizontal || style == TwoValueVertical - || style == ThreeValueHorizontal || style == ThreeValueVertical); + // The maximum value only applies to sliders that are in two- or three-value mode. + jassert (style == TwoValueHorizontal || style == TwoValueVertical + || style == ThreeValueHorizontal || style == ThreeValueVertical); - newValue = constrainedValue (newValue); + newValue = constrainedValue (newValue); - if (style == TwoValueHorizontal || style == TwoValueVertical) - { - if (allowNudgingOfOtherValues && newValue < (double) valueMin.getValue()) - setMinValue (newValue, sendUpdateMessage, sendMessageSynchronously); + if (style == TwoValueHorizontal || style == TwoValueVertical) + { + if (allowNudgingOfOtherValues && newValue < (double) valueMin.getValue()) + setMinValue (newValue, sendUpdateMessage, sendMessageSynchronously); - newValue = jmax ((double) valueMin.getValue(), newValue); - } - else - { - if (allowNudgingOfOtherValues && newValue < lastCurrentValue) - setValue (newValue, sendUpdateMessage, sendMessageSynchronously); + newValue = jmax ((double) valueMin.getValue(), newValue); + } + else + { + if (allowNudgingOfOtherValues && newValue < lastCurrentValue) + setValue (newValue, sendUpdateMessage, sendMessageSynchronously); - newValue = jmax (lastCurrentValue, newValue); - } + newValue = jmax (lastCurrentValue, newValue); + } - if (lastValueMax != newValue) - { - lastValueMax = newValue; - valueMax = newValue; - repaint(); + if (lastValueMax != newValue) + { + lastValueMax = newValue; + valueMax = newValue; + repaint(); - if (popupDisplay != 0) - { - ((SliderPopupDisplayComponent*) popupDisplay)->updatePosition (getTextFromValue (valueMax.getValue())); - popupDisplay->repaint(); - } + if (popupDisplay != 0) + { + ((SliderPopupDisplayComponent*) popupDisplay)->updatePosition (getTextFromValue (valueMax.getValue())); + popupDisplay->repaint(); + } - if (sendUpdateMessage) - triggerChangeMessage (sendMessageSynchronously); - } + if (sendUpdateMessage) + triggerChangeMessage (sendMessageSynchronously); + } } void Slider::setDoubleClickReturnValue (const bool isDoubleClickEnabled, - const double valueToSetOnDoubleClick) + const double valueToSetOnDoubleClick) { - doubleClickToValue = isDoubleClickEnabled; - doubleClickReturnValue = valueToSetOnDoubleClick; + doubleClickToValue = isDoubleClickEnabled; + doubleClickReturnValue = valueToSetOnDoubleClick; } double Slider::getDoubleClickReturnValue (bool& isEnabled_) const { - isEnabled_ = doubleClickToValue; - return doubleClickReturnValue; + isEnabled_ = doubleClickToValue; + return doubleClickReturnValue; } void Slider::updateText() { - if (valueBox != 0) - valueBox->setText (getTextFromValue (currentValue.getValue()), false); + if (valueBox != 0) + valueBox->setText (getTextFromValue (currentValue.getValue()), false); } void Slider::setTextValueSuffix (const String& suffix) { - if (textSuffix != suffix) - { - textSuffix = suffix; - updateText(); - } + if (textSuffix != suffix) + { + textSuffix = suffix; + updateText(); + } } const String Slider::getTextFromValue (double v) { - if (numDecimalPlaces > 0) - return String (v, numDecimalPlaces) + textSuffix; - else - return String (roundDoubleToInt (v)) + textSuffix; + if (numDecimalPlaces > 0) + return String (v, numDecimalPlaces) + textSuffix; + else + return String (roundToInt (v)) + textSuffix; } double Slider::getValueFromText (const String& text) { - String t (text.trimStart()); + String t (text.trimStart()); - if (t.endsWith (textSuffix)) - t = t.substring (0, t.length() - textSuffix.length()); + if (t.endsWith (textSuffix)) + t = t.substring (0, t.length() - textSuffix.length()); - while (t.startsWithChar (T('+'))) - t = t.substring (1).trimStart(); + while (t.startsWithChar (T('+'))) + t = t.substring (1).trimStart(); - return t.initialSectionContainingOnly (T("0123456789.,-")) - .getDoubleValue(); + return t.initialSectionContainingOnly (T("0123456789.,-")) + .getDoubleValue(); } double Slider::proportionOfLengthToValue (double proportion) { - if (skewFactor != 1.0 && proportion > 0.0) - proportion = exp (log (proportion) / skewFactor); + if (skewFactor != 1.0 && proportion > 0.0) + proportion = exp (log (proportion) / skewFactor); - return minimum + (maximum - minimum) * proportion; + return minimum + (maximum - minimum) * proportion; } double Slider::valueToProportionOfLength (double value) { - const double n = (value - minimum) / (maximum - minimum); + const double n = (value - minimum) / (maximum - minimum); - return skewFactor == 1.0 ? n : pow (n, skewFactor); + return skewFactor == 1.0 ? n : pow (n, skewFactor); } double Slider::snapValue (double attemptedValue, const bool) { - return attemptedValue; + return attemptedValue; } void Slider::startedDragging() @@ -49498,732 +49203,732 @@ void Slider::valueChanged() void Slider::enablementChanged() { - repaint(); + repaint(); } void Slider::setPopupMenuEnabled (const bool menuEnabled_) { - menuEnabled = menuEnabled_; + menuEnabled = menuEnabled_; } void Slider::setScrollWheelEnabled (const bool enabled) { - scrollWheelEnabled = enabled; + scrollWheelEnabled = enabled; } void Slider::labelTextChanged (Label* label) { - const double newValue = snapValue (getValueFromText (label->getText()), false); + const double newValue = snapValue (getValueFromText (label->getText()), false); - if (newValue != (double) currentValue.getValue()) - { - sendDragStart(); - setValue (newValue, true, true); - sendDragEnd(); - } + if (newValue != (double) currentValue.getValue()) + { + sendDragStart(); + setValue (newValue, true, true); + sendDragEnd(); + } - updateText(); // force a clean-up of the text, needed in case setValue() hasn't done this. + updateText(); // force a clean-up of the text, needed in case setValue() hasn't done this. } void Slider::buttonClicked (Button* button) { - if (style == IncDecButtons) - { - sendDragStart(); + if (style == IncDecButtons) + { + sendDragStart(); - if (button == incButton) - setValue (snapValue (getValue() + interval, false), true, true); - else if (button == decButton) - setValue (snapValue (getValue() - interval, false), true, true); + if (button == incButton) + setValue (snapValue (getValue() + interval, false), true, true); + else if (button == decButton) + setValue (snapValue (getValue() - interval, false), true, true); - sendDragEnd(); - } + sendDragEnd(); + } } double Slider::constrainedValue (double value) const { - if (interval > 0) - value = minimum + interval * floor ((value - minimum) / interval + 0.5); + if (interval > 0) + value = minimum + interval * floor ((value - minimum) / interval + 0.5); - if (value <= minimum || maximum <= minimum) - value = minimum; - else if (value >= maximum) - value = maximum; + if (value <= minimum || maximum <= minimum) + value = minimum; + else if (value >= maximum) + value = maximum; - return value; + return value; } float Slider::getLinearSliderPos (const double value) { - double sliderPosProportional; + double sliderPosProportional; - if (maximum > minimum) - { - if (value < minimum) - { - sliderPosProportional = 0.0; - } - else if (value > maximum) - { - sliderPosProportional = 1.0; - } - else - { - sliderPosProportional = valueToProportionOfLength (value); - jassert (sliderPosProportional >= 0 && sliderPosProportional <= 1.0); - } - } - else - { - sliderPosProportional = 0.5; - } + if (maximum > minimum) + { + if (value < minimum) + { + sliderPosProportional = 0.0; + } + else if (value > maximum) + { + sliderPosProportional = 1.0; + } + else + { + sliderPosProportional = valueToProportionOfLength (value); + jassert (sliderPosProportional >= 0 && sliderPosProportional <= 1.0); + } + } + else + { + sliderPosProportional = 0.5; + } - if (isVertical() || style == IncDecButtons) - sliderPosProportional = 1.0 - sliderPosProportional; + if (isVertical() || style == IncDecButtons) + sliderPosProportional = 1.0 - sliderPosProportional; - return (float) (sliderRegionStart + sliderPosProportional * sliderRegionSize); + return (float) (sliderRegionStart + sliderPosProportional * sliderRegionSize); } bool Slider::isHorizontal() const { - return style == LinearHorizontal - || style == LinearBar - || style == TwoValueHorizontal - || style == ThreeValueHorizontal; + return style == LinearHorizontal + || style == LinearBar + || style == TwoValueHorizontal + || style == ThreeValueHorizontal; } bool Slider::isVertical() const { - return style == LinearVertical - || style == TwoValueVertical - || style == ThreeValueVertical; + return style == LinearVertical + || style == TwoValueVertical + || style == ThreeValueVertical; } bool Slider::incDecDragDirectionIsHorizontal() const { - return incDecButtonMode == incDecButtonsDraggable_Horizontal - || (incDecButtonMode == incDecButtonsDraggable_AutoDirection && incDecButtonsSideBySide); + return incDecButtonMode == incDecButtonsDraggable_Horizontal + || (incDecButtonMode == incDecButtonsDraggable_AutoDirection && incDecButtonsSideBySide); } float Slider::getPositionOfValue (const double value) { - if (isHorizontal() || isVertical()) - { - return getLinearSliderPos (value); - } - else - { - jassertfalse // not a valid call on a slider that doesn't work linearly! - return 0.0f; - } + if (isHorizontal() || isVertical()) + { + return getLinearSliderPos (value); + } + else + { + jassertfalse // not a valid call on a slider that doesn't work linearly! + return 0.0f; + } } void Slider::paint (Graphics& g) { - if (style != IncDecButtons) - { - if (style == Rotary || style == RotaryHorizontalDrag || style == RotaryVerticalDrag) - { - const float sliderPos = (float) valueToProportionOfLength (lastCurrentValue); - jassert (sliderPos >= 0 && sliderPos <= 1.0f); + if (style != IncDecButtons) + { + if (style == Rotary || style == RotaryHorizontalDrag || style == RotaryVerticalDrag) + { + const float sliderPos = (float) valueToProportionOfLength (lastCurrentValue); + jassert (sliderPos >= 0 && sliderPos <= 1.0f); - getLookAndFeel().drawRotarySlider (g, - sliderRect.getX(), - sliderRect.getY(), - sliderRect.getWidth(), - sliderRect.getHeight(), - sliderPos, - rotaryStart, rotaryEnd, - *this); - } - else - { - getLookAndFeel().drawLinearSlider (g, - sliderRect.getX(), - sliderRect.getY(), - sliderRect.getWidth(), - sliderRect.getHeight(), - getLinearSliderPos (lastCurrentValue), - getLinearSliderPos (lastValueMin), - getLinearSliderPos (lastValueMax), - style, - *this); - } + getLookAndFeel().drawRotarySlider (g, + sliderRect.getX(), + sliderRect.getY(), + sliderRect.getWidth(), + sliderRect.getHeight(), + sliderPos, + rotaryStart, rotaryEnd, + *this); + } + else + { + getLookAndFeel().drawLinearSlider (g, + sliderRect.getX(), + sliderRect.getY(), + sliderRect.getWidth(), + sliderRect.getHeight(), + getLinearSliderPos (lastCurrentValue), + getLinearSliderPos (lastValueMin), + getLinearSliderPos (lastValueMax), + style, + *this); + } - if (style == LinearBar && valueBox == 0) - { - g.setColour (findColour (Slider::textBoxOutlineColourId)); - g.drawRect (0, 0, getWidth(), getHeight(), 1); - } - } + if (style == LinearBar && valueBox == 0) + { + g.setColour (findColour (Slider::textBoxOutlineColourId)); + g.drawRect (0, 0, getWidth(), getHeight(), 1); + } + } } void Slider::resized() { - int minXSpace = 0; - int minYSpace = 0; + int minXSpace = 0; + int minYSpace = 0; - if (textBoxPos == TextBoxLeft || textBoxPos == TextBoxRight) - minXSpace = 30; - else - minYSpace = 15; + if (textBoxPos == TextBoxLeft || textBoxPos == TextBoxRight) + minXSpace = 30; + else + minYSpace = 15; - const int tbw = jmax (0, jmin (textBoxWidth, getWidth() - minXSpace)); - const int tbh = jmax (0, jmin (textBoxHeight, getHeight() - minYSpace)); + const int tbw = jmax (0, jmin (textBoxWidth, getWidth() - minXSpace)); + const int tbh = jmax (0, jmin (textBoxHeight, getHeight() - minYSpace)); - if (style == LinearBar) - { - if (valueBox != 0) - valueBox->setBounds (0, 0, getWidth(), getHeight()); - } - else - { - if (textBoxPos == NoTextBox) - { - sliderRect.setBounds (0, 0, getWidth(), getHeight()); - } - else if (textBoxPos == TextBoxLeft) - { - valueBox->setBounds (0, (getHeight() - tbh) / 2, tbw, tbh); - sliderRect.setBounds (tbw, 0, getWidth() - tbw, getHeight()); - } - else if (textBoxPos == TextBoxRight) - { - valueBox->setBounds (getWidth() - tbw, (getHeight() - tbh) / 2, tbw, tbh); - sliderRect.setBounds (0, 0, getWidth() - tbw, getHeight()); - } - else if (textBoxPos == TextBoxAbove) - { - valueBox->setBounds ((getWidth() - tbw) / 2, 0, tbw, tbh); - sliderRect.setBounds (0, tbh, getWidth(), getHeight() - tbh); - } - else if (textBoxPos == TextBoxBelow) - { - valueBox->setBounds ((getWidth() - tbw) / 2, getHeight() - tbh, tbw, tbh); - sliderRect.setBounds (0, 0, getWidth(), getHeight() - tbh); - } - } + if (style == LinearBar) + { + if (valueBox != 0) + valueBox->setBounds (0, 0, getWidth(), getHeight()); + } + else + { + if (textBoxPos == NoTextBox) + { + sliderRect.setBounds (0, 0, getWidth(), getHeight()); + } + else if (textBoxPos == TextBoxLeft) + { + valueBox->setBounds (0, (getHeight() - tbh) / 2, tbw, tbh); + sliderRect.setBounds (tbw, 0, getWidth() - tbw, getHeight()); + } + else if (textBoxPos == TextBoxRight) + { + valueBox->setBounds (getWidth() - tbw, (getHeight() - tbh) / 2, tbw, tbh); + sliderRect.setBounds (0, 0, getWidth() - tbw, getHeight()); + } + else if (textBoxPos == TextBoxAbove) + { + valueBox->setBounds ((getWidth() - tbw) / 2, 0, tbw, tbh); + sliderRect.setBounds (0, tbh, getWidth(), getHeight() - tbh); + } + else if (textBoxPos == TextBoxBelow) + { + valueBox->setBounds ((getWidth() - tbw) / 2, getHeight() - tbh, tbw, tbh); + sliderRect.setBounds (0, 0, getWidth(), getHeight() - tbh); + } + } - const int indent = getLookAndFeel().getSliderThumbRadius (*this); + const int indent = getLookAndFeel().getSliderThumbRadius (*this); - if (style == LinearBar) - { - const int barIndent = 1; - sliderRegionStart = barIndent; - sliderRegionSize = getWidth() - barIndent * 2; + if (style == LinearBar) + { + const int barIndent = 1; + sliderRegionStart = barIndent; + sliderRegionSize = getWidth() - barIndent * 2; - sliderRect.setBounds (sliderRegionStart, barIndent, - sliderRegionSize, getHeight() - barIndent * 2); - } - else if (isHorizontal()) - { - sliderRegionStart = sliderRect.getX() + indent; - sliderRegionSize = jmax (1, sliderRect.getWidth() - indent * 2); + sliderRect.setBounds (sliderRegionStart, barIndent, + sliderRegionSize, getHeight() - barIndent * 2); + } + else if (isHorizontal()) + { + sliderRegionStart = sliderRect.getX() + indent; + sliderRegionSize = jmax (1, sliderRect.getWidth() - indent * 2); - sliderRect.setBounds (sliderRegionStart, sliderRect.getY(), - sliderRegionSize, sliderRect.getHeight()); - } - else if (isVertical()) - { - sliderRegionStart = sliderRect.getY() + indent; - sliderRegionSize = jmax (1, sliderRect.getHeight() - indent * 2); + sliderRect.setBounds (sliderRegionStart, sliderRect.getY(), + sliderRegionSize, sliderRect.getHeight()); + } + else if (isVertical()) + { + sliderRegionStart = sliderRect.getY() + indent; + sliderRegionSize = jmax (1, sliderRect.getHeight() - indent * 2); - sliderRect.setBounds (sliderRect.getX(), sliderRegionStart, - sliderRect.getWidth(), sliderRegionSize); - } - else - { - sliderRegionStart = 0; - sliderRegionSize = 100; - } + sliderRect.setBounds (sliderRect.getX(), sliderRegionStart, + sliderRect.getWidth(), sliderRegionSize); + } + else + { + sliderRegionStart = 0; + sliderRegionSize = 100; + } - if (style == IncDecButtons) - { - Rectangle buttonRect (sliderRect); + if (style == IncDecButtons) + { + Rectangle buttonRect (sliderRect); - if (textBoxPos == TextBoxLeft || textBoxPos == TextBoxRight) - buttonRect.expand (-2, 0); - else - buttonRect.expand (0, -2); + if (textBoxPos == TextBoxLeft || textBoxPos == TextBoxRight) + buttonRect.expand (-2, 0); + else + buttonRect.expand (0, -2); - incDecButtonsSideBySide = buttonRect.getWidth() > buttonRect.getHeight(); + incDecButtonsSideBySide = buttonRect.getWidth() > buttonRect.getHeight(); - if (incDecButtonsSideBySide) - { - decButton->setBounds (buttonRect.getX(), - buttonRect.getY(), - buttonRect.getWidth() / 2, - buttonRect.getHeight()); + if (incDecButtonsSideBySide) + { + decButton->setBounds (buttonRect.getX(), + buttonRect.getY(), + buttonRect.getWidth() / 2, + buttonRect.getHeight()); - decButton->setConnectedEdges (Button::ConnectedOnRight); + decButton->setConnectedEdges (Button::ConnectedOnRight); - incButton->setBounds (buttonRect.getCentreX(), - buttonRect.getY(), - buttonRect.getWidth() / 2, - buttonRect.getHeight()); + incButton->setBounds (buttonRect.getCentreX(), + buttonRect.getY(), + buttonRect.getWidth() / 2, + buttonRect.getHeight()); - incButton->setConnectedEdges (Button::ConnectedOnLeft); - } - else - { - incButton->setBounds (buttonRect.getX(), - buttonRect.getY(), - buttonRect.getWidth(), - buttonRect.getHeight() / 2); + incButton->setConnectedEdges (Button::ConnectedOnLeft); + } + else + { + incButton->setBounds (buttonRect.getX(), + buttonRect.getY(), + buttonRect.getWidth(), + buttonRect.getHeight() / 2); - incButton->setConnectedEdges (Button::ConnectedOnBottom); + incButton->setConnectedEdges (Button::ConnectedOnBottom); - decButton->setBounds (buttonRect.getX(), - buttonRect.getCentreY(), - buttonRect.getWidth(), - buttonRect.getHeight() / 2); + decButton->setBounds (buttonRect.getX(), + buttonRect.getCentreY(), + buttonRect.getWidth(), + buttonRect.getHeight() / 2); - decButton->setConnectedEdges (Button::ConnectedOnTop); - } - } + decButton->setConnectedEdges (Button::ConnectedOnTop); + } + } } void Slider::focusOfChildComponentChanged (FocusChangeType) { - repaint(); + repaint(); } void Slider::mouseDown (const MouseEvent& e) { - mouseWasHidden = false; - incDecDragged = false; - mouseXWhenLastDragged = e.x; - mouseYWhenLastDragged = e.y; - mouseDragStartX = e.getMouseDownX(); - mouseDragStartY = e.getMouseDownY(); + mouseWasHidden = false; + incDecDragged = false; + mouseXWhenLastDragged = e.x; + mouseYWhenLastDragged = e.y; + mouseDragStartX = e.getMouseDownX(); + mouseDragStartY = e.getMouseDownY(); - if (isEnabled()) - { - if (e.mods.isPopupMenu() && menuEnabled) - { - menuShown = true; + if (isEnabled()) + { + if (e.mods.isPopupMenu() && menuEnabled) + { + menuShown = true; - PopupMenu m; - m.setLookAndFeel (&getLookAndFeel()); - m.addItem (1, TRANS ("velocity-sensitive mode"), true, isVelocityBased); - m.addSeparator(); + PopupMenu m; + m.setLookAndFeel (&getLookAndFeel()); + m.addItem (1, TRANS ("velocity-sensitive mode"), true, isVelocityBased); + m.addSeparator(); - if (style == Rotary || style == RotaryHorizontalDrag || style == RotaryVerticalDrag) - { - PopupMenu rotaryMenu; - rotaryMenu.addItem (2, TRANS ("use circular dragging"), true, style == Rotary); - rotaryMenu.addItem (3, TRANS ("use left-right dragging"), true, style == RotaryHorizontalDrag); - rotaryMenu.addItem (4, TRANS ("use up-down dragging"), true, style == RotaryVerticalDrag); + if (style == Rotary || style == RotaryHorizontalDrag || style == RotaryVerticalDrag) + { + PopupMenu rotaryMenu; + rotaryMenu.addItem (2, TRANS ("use circular dragging"), true, style == Rotary); + rotaryMenu.addItem (3, TRANS ("use left-right dragging"), true, style == RotaryHorizontalDrag); + rotaryMenu.addItem (4, TRANS ("use up-down dragging"), true, style == RotaryVerticalDrag); - m.addSubMenu (TRANS ("rotary mode"), rotaryMenu); - } + m.addSubMenu (TRANS ("rotary mode"), rotaryMenu); + } - const int r = m.show(); + const int r = m.show(); - if (r == 1) - { - setVelocityBasedMode (! isVelocityBased); - } - else if (r == 2) - { - setSliderStyle (Rotary); - } - else if (r == 3) - { - setSliderStyle (RotaryHorizontalDrag); - } - else if (r == 4) - { - setSliderStyle (RotaryVerticalDrag); - } - } - else if (maximum > minimum) - { - menuShown = false; + if (r == 1) + { + setVelocityBasedMode (! isVelocityBased); + } + else if (r == 2) + { + setSliderStyle (Rotary); + } + else if (r == 3) + { + setSliderStyle (RotaryHorizontalDrag); + } + else if (r == 4) + { + setSliderStyle (RotaryVerticalDrag); + } + } + else if (maximum > minimum) + { + menuShown = false; - if (valueBox != 0) - valueBox->hideEditor (true); + if (valueBox != 0) + valueBox->hideEditor (true); - sliderBeingDragged = 0; + sliderBeingDragged = 0; - if (style == TwoValueHorizontal - || style == TwoValueVertical - || style == ThreeValueHorizontal - || style == ThreeValueVertical) - { - const float mousePos = (float) (isVertical() ? e.y : e.x); + if (style == TwoValueHorizontal + || style == TwoValueVertical + || style == ThreeValueHorizontal + || style == ThreeValueVertical) + { + const float mousePos = (float) (isVertical() ? e.y : e.x); - const float normalPosDistance = fabsf (getLinearSliderPos (currentValue.getValue()) - mousePos); - const float minPosDistance = fabsf (getLinearSliderPos (valueMin.getValue()) - 0.1f - mousePos); - const float maxPosDistance = fabsf (getLinearSliderPos (valueMax.getValue()) + 0.1f - mousePos); + const float normalPosDistance = fabsf (getLinearSliderPos (currentValue.getValue()) - mousePos); + const float minPosDistance = fabsf (getLinearSliderPos (valueMin.getValue()) - 0.1f - mousePos); + const float maxPosDistance = fabsf (getLinearSliderPos (valueMax.getValue()) + 0.1f - mousePos); - if (style == TwoValueHorizontal || style == TwoValueVertical) - { - if (maxPosDistance <= minPosDistance) - sliderBeingDragged = 2; - else - sliderBeingDragged = 1; - } - else if (style == ThreeValueHorizontal || style == ThreeValueVertical) - { - if (normalPosDistance >= minPosDistance && maxPosDistance >= minPosDistance) - sliderBeingDragged = 1; - else if (normalPosDistance >= maxPosDistance) - sliderBeingDragged = 2; - } - } + if (style == TwoValueHorizontal || style == TwoValueVertical) + { + if (maxPosDistance <= minPosDistance) + sliderBeingDragged = 2; + else + sliderBeingDragged = 1; + } + else if (style == ThreeValueHorizontal || style == ThreeValueVertical) + { + if (normalPosDistance >= minPosDistance && maxPosDistance >= minPosDistance) + sliderBeingDragged = 1; + else if (normalPosDistance >= maxPosDistance) + sliderBeingDragged = 2; + } + } - minMaxDiff = (double) valueMax.getValue() - (double) valueMin.getValue(); + minMaxDiff = (double) valueMax.getValue() - (double) valueMin.getValue(); - lastAngle = rotaryStart + (rotaryEnd - rotaryStart) - * valueToProportionOfLength (currentValue.getValue()); + lastAngle = rotaryStart + (rotaryEnd - rotaryStart) + * valueToProportionOfLength (currentValue.getValue()); - valueWhenLastDragged = ((sliderBeingDragged == 2) ? valueMax - : ((sliderBeingDragged == 1) ? valueMin - : currentValue)).getValue(); + valueWhenLastDragged = ((sliderBeingDragged == 2) ? valueMax + : ((sliderBeingDragged == 1) ? valueMin + : currentValue)).getValue(); - valueOnMouseDown = valueWhenLastDragged; + valueOnMouseDown = valueWhenLastDragged; - if (popupDisplayEnabled) - { - SliderPopupDisplayComponent* const popup = new SliderPopupDisplayComponent (this); - popupDisplay = popup; + if (popupDisplayEnabled) + { + SliderPopupDisplayComponent* const popup = new SliderPopupDisplayComponent (this); + popupDisplay = popup; - if (parentForPopupDisplay != 0) - { - parentForPopupDisplay->addChildComponent (popup); - } - else - { - popup->addToDesktop (0); - } + if (parentForPopupDisplay != 0) + { + parentForPopupDisplay->addChildComponent (popup); + } + else + { + popup->addToDesktop (0); + } - popup->setVisible (true); - } + popup->setVisible (true); + } - sendDragStart(); + sendDragStart(); - mouseDrag (e); - } - } + mouseDrag (e); + } + } } void Slider::mouseUp (const MouseEvent&) { - if (isEnabled() - && (! menuShown) - && (maximum > minimum) - && (style != IncDecButtons || incDecDragged)) - { - restoreMouseIfHidden(); + if (isEnabled() + && (! menuShown) + && (maximum > minimum) + && (style != IncDecButtons || incDecDragged)) + { + restoreMouseIfHidden(); - if (sendChangeOnlyOnRelease && valueOnMouseDown != (double) currentValue.getValue()) - triggerChangeMessage (false); + if (sendChangeOnlyOnRelease && valueOnMouseDown != (double) currentValue.getValue()) + triggerChangeMessage (false); - sendDragEnd(); + sendDragEnd(); - popupDisplay = 0; + popupDisplay = 0; - if (style == IncDecButtons) - { - incButton->setState (Button::buttonNormal); - decButton->setState (Button::buttonNormal); - } - } + if (style == IncDecButtons) + { + incButton->setState (Button::buttonNormal); + decButton->setState (Button::buttonNormal); + } + } } void Slider::restoreMouseIfHidden() { - if (mouseWasHidden) - { - mouseWasHidden = false; + if (mouseWasHidden) + { + mouseWasHidden = false; - Component* c = Component::getComponentUnderMouse(); + Component* c = Component::getComponentUnderMouse(); - if (c == 0) - c = this; + if (c == 0) + c = this; - c->enableUnboundedMouseMovement (false); + c->enableUnboundedMouseMovement (false); - const double pos = (sliderBeingDragged == 2) ? getMaxValue() - : ((sliderBeingDragged == 1) ? getMinValue() - : (double) currentValue.getValue()); + const double pos = (sliderBeingDragged == 2) ? getMaxValue() + : ((sliderBeingDragged == 1) ? getMinValue() + : (double) currentValue.getValue()); - if (style == RotaryHorizontalDrag || style == RotaryVerticalDrag) - { - int x, y, downX, downY; - Desktop::getMousePosition (x, y); - Desktop::getLastMouseDownPosition (downX, downY); + if (style == RotaryHorizontalDrag || style == RotaryVerticalDrag) + { + int x, y, downX, downY; + Desktop::getMousePosition (x, y); + Desktop::getLastMouseDownPosition (downX, downY); - if (style == RotaryHorizontalDrag) - { - const double posDiff = valueToProportionOfLength (pos) - valueToProportionOfLength (valueOnMouseDown); - x = roundDoubleToInt (pixelsForFullDragExtent * posDiff + downX); - y = downY; - } - else - { - const double posDiff = valueToProportionOfLength (valueOnMouseDown) - valueToProportionOfLength (pos); - x = downX; - y = roundDoubleToInt (pixelsForFullDragExtent * posDiff + downY); - } + if (style == RotaryHorizontalDrag) + { + const double posDiff = valueToProportionOfLength (pos) - valueToProportionOfLength (valueOnMouseDown); + x = roundToInt (pixelsForFullDragExtent * posDiff + downX); + y = downY; + } + else + { + const double posDiff = valueToProportionOfLength (valueOnMouseDown) - valueToProportionOfLength (pos); + x = downX; + y = roundToInt (pixelsForFullDragExtent * posDiff + downY); + } - Desktop::setMousePosition (x, y); - } - else - { - const int pixelPos = (int) getLinearSliderPos (pos); + Desktop::setMousePosition (x, y); + } + else + { + const int pixelPos = (int) getLinearSliderPos (pos); - int x = isHorizontal() ? pixelPos : (getWidth() / 2); - int y = isVertical() ? pixelPos : (getHeight() / 2); + int x = isHorizontal() ? pixelPos : (getWidth() / 2); + int y = isVertical() ? pixelPos : (getHeight() / 2); - relativePositionToGlobal (x, y); - Desktop::setMousePosition (x, y); - } - } + relativePositionToGlobal (x, y); + Desktop::setMousePosition (x, y); + } + } } void Slider::modifierKeysChanged (const ModifierKeys& modifiers) { - if (isEnabled() - && style != IncDecButtons - && style != Rotary - && isVelocityBased == modifiers.isAnyModifierKeyDown()) - { - restoreMouseIfHidden(); - } + if (isEnabled() + && style != IncDecButtons + && style != Rotary + && isVelocityBased == modifiers.isAnyModifierKeyDown()) + { + restoreMouseIfHidden(); + } } static double smallestAngleBetween (double a1, double a2) { - return jmin (fabs (a1 - a2), - fabs (a1 + double_Pi * 2.0 - a2), - fabs (a2 + double_Pi * 2.0 - a1)); + return jmin (fabs (a1 - a2), + fabs (a1 + double_Pi * 2.0 - a2), + fabs (a2 + double_Pi * 2.0 - a1)); } void Slider::mouseDrag (const MouseEvent& e) { - if (isEnabled() - && (! menuShown) - && (maximum > minimum)) - { - if (style == Rotary) - { - int dx = e.x - sliderRect.getCentreX(); - int dy = e.y - sliderRect.getCentreY(); + if (isEnabled() + && (! menuShown) + && (maximum > minimum)) + { + if (style == Rotary) + { + int dx = e.x - sliderRect.getCentreX(); + int dy = e.y - sliderRect.getCentreY(); - if (dx * dx + dy * dy > 25) - { - double angle = atan2 ((double) dx, (double) -dy); - while (angle < 0.0) - angle += double_Pi * 2.0; + if (dx * dx + dy * dy > 25) + { + double angle = atan2 ((double) dx, (double) -dy); + while (angle < 0.0) + angle += double_Pi * 2.0; - if (rotaryStop && ! e.mouseWasClicked()) - { - if (fabs (angle - lastAngle) > double_Pi) - { - if (angle >= lastAngle) - angle -= double_Pi * 2.0; - else - angle += double_Pi * 2.0; - } + if (rotaryStop && ! e.mouseWasClicked()) + { + if (fabs (angle - lastAngle) > double_Pi) + { + if (angle >= lastAngle) + angle -= double_Pi * 2.0; + else + angle += double_Pi * 2.0; + } - if (angle >= lastAngle) - angle = jmin (angle, (double) jmax (rotaryStart, rotaryEnd)); - else - angle = jmax (angle, (double) jmin (rotaryStart, rotaryEnd)); - } - else - { - while (angle < rotaryStart) - angle += double_Pi * 2.0; + if (angle >= lastAngle) + angle = jmin (angle, (double) jmax (rotaryStart, rotaryEnd)); + else + angle = jmax (angle, (double) jmin (rotaryStart, rotaryEnd)); + } + else + { + while (angle < rotaryStart) + angle += double_Pi * 2.0; - if (angle > rotaryEnd) - { - if (smallestAngleBetween (angle, rotaryStart) <= smallestAngleBetween (angle, rotaryEnd)) - angle = rotaryStart; - else - angle = rotaryEnd; - } - } + if (angle > rotaryEnd) + { + if (smallestAngleBetween (angle, rotaryStart) <= smallestAngleBetween (angle, rotaryEnd)) + angle = rotaryStart; + else + angle = rotaryEnd; + } + } - const double proportion = (angle - rotaryStart) / (rotaryEnd - rotaryStart); + const double proportion = (angle - rotaryStart) / (rotaryEnd - rotaryStart); - valueWhenLastDragged = proportionOfLengthToValue (jlimit (0.0, 1.0, proportion)); + valueWhenLastDragged = proportionOfLengthToValue (jlimit (0.0, 1.0, proportion)); - lastAngle = angle; - } - } - else - { - if (style == LinearBar && e.mouseWasClicked() - && valueBox != 0 && valueBox->isEditable()) - return; + lastAngle = angle; + } + } + else + { + if (style == LinearBar && e.mouseWasClicked() + && valueBox != 0 && valueBox->isEditable()) + return; - if (style == IncDecButtons && ! incDecDragged) - { - if (e.getDistanceFromDragStart() < 10 || e.mouseWasClicked()) - return; + if (style == IncDecButtons && ! incDecDragged) + { + if (e.getDistanceFromDragStart() < 10 || e.mouseWasClicked()) + return; - incDecDragged = true; - mouseDragStartX = e.x; - mouseDragStartY = e.y; - } + incDecDragged = true; + mouseDragStartX = e.x; + mouseDragStartY = e.y; + } - if ((isVelocityBased == (userKeyOverridesVelocity ? e.mods.testFlags (ModifierKeys::ctrlModifier | ModifierKeys::commandModifier | ModifierKeys::altModifier) - : false)) - || ((maximum - minimum) / sliderRegionSize < interval)) - { - const int mousePos = (isHorizontal() || style == RotaryHorizontalDrag) ? e.x : e.y; + if ((isVelocityBased == (userKeyOverridesVelocity ? e.mods.testFlags (ModifierKeys::ctrlModifier | ModifierKeys::commandModifier | ModifierKeys::altModifier) + : false)) + || ((maximum - minimum) / sliderRegionSize < interval)) + { + const int mousePos = (isHorizontal() || style == RotaryHorizontalDrag) ? e.x : e.y; - double scaledMousePos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; + double scaledMousePos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; - if (style == RotaryHorizontalDrag - || style == RotaryVerticalDrag - || style == IncDecButtons - || ((style == LinearHorizontal || style == LinearVertical || style == LinearBar) - && ! snapsToMousePos)) - { - const int mouseDiff = (style == RotaryHorizontalDrag - || style == LinearHorizontal - || style == LinearBar - || (style == IncDecButtons && incDecDragDirectionIsHorizontal())) - ? e.x - mouseDragStartX - : mouseDragStartY - e.y; + if (style == RotaryHorizontalDrag + || style == RotaryVerticalDrag + || style == IncDecButtons + || ((style == LinearHorizontal || style == LinearVertical || style == LinearBar) + && ! snapsToMousePos)) + { + const int mouseDiff = (style == RotaryHorizontalDrag + || style == LinearHorizontal + || style == LinearBar + || (style == IncDecButtons && incDecDragDirectionIsHorizontal())) + ? e.x - mouseDragStartX + : mouseDragStartY - e.y; - double newPos = valueToProportionOfLength (valueOnMouseDown) - + mouseDiff * (1.0 / pixelsForFullDragExtent); + double newPos = valueToProportionOfLength (valueOnMouseDown) + + mouseDiff * (1.0 / pixelsForFullDragExtent); - valueWhenLastDragged = proportionOfLengthToValue (jlimit (0.0, 1.0, newPos)); + valueWhenLastDragged = proportionOfLengthToValue (jlimit (0.0, 1.0, newPos)); - if (style == IncDecButtons) - { - incButton->setState (mouseDiff < 0 ? Button::buttonNormal : Button::buttonDown); - decButton->setState (mouseDiff > 0 ? Button::buttonNormal : Button::buttonDown); - } - } - else - { - if (isVertical()) - scaledMousePos = 1.0 - scaledMousePos; + if (style == IncDecButtons) + { + incButton->setState (mouseDiff < 0 ? Button::buttonNormal : Button::buttonDown); + decButton->setState (mouseDiff > 0 ? Button::buttonNormal : Button::buttonDown); + } + } + else + { + if (isVertical()) + scaledMousePos = 1.0 - scaledMousePos; - valueWhenLastDragged = proportionOfLengthToValue (jlimit (0.0, 1.0, scaledMousePos)); - } - } - else - { - const int mouseDiff = (isHorizontal() || style == RotaryHorizontalDrag - || (style == IncDecButtons && incDecDragDirectionIsHorizontal())) - ? e.x - mouseXWhenLastDragged - : e.y - mouseYWhenLastDragged; + valueWhenLastDragged = proportionOfLengthToValue (jlimit (0.0, 1.0, scaledMousePos)); + } + } + else + { + const int mouseDiff = (isHorizontal() || style == RotaryHorizontalDrag + || (style == IncDecButtons && incDecDragDirectionIsHorizontal())) + ? e.x - mouseXWhenLastDragged + : e.y - mouseYWhenLastDragged; - const double maxSpeed = jmax (200, sliderRegionSize); - double speed = jlimit (0.0, maxSpeed, (double) abs (mouseDiff)); + const double maxSpeed = jmax (200, sliderRegionSize); + double speed = jlimit (0.0, maxSpeed, (double) abs (mouseDiff)); - if (speed != 0) - { - speed = 0.2 * velocityModeSensitivity - * (1.0 + sin (double_Pi * (1.5 + jmin (0.5, velocityModeOffset - + jmax (0.0, (double) (speed - velocityModeThreshold)) - / maxSpeed)))); + if (speed != 0) + { + speed = 0.2 * velocityModeSensitivity + * (1.0 + sin (double_Pi * (1.5 + jmin (0.5, velocityModeOffset + + jmax (0.0, (double) (speed - velocityModeThreshold)) + / maxSpeed)))); - if (mouseDiff < 0) - speed = -speed; + if (mouseDiff < 0) + speed = -speed; - if (isVertical() || style == RotaryVerticalDrag - || (style == IncDecButtons && ! incDecDragDirectionIsHorizontal())) - speed = -speed; + if (isVertical() || style == RotaryVerticalDrag + || (style == IncDecButtons && ! incDecDragDirectionIsHorizontal())) + speed = -speed; - const double currentPos = valueToProportionOfLength (valueWhenLastDragged); + const double currentPos = valueToProportionOfLength (valueWhenLastDragged); - valueWhenLastDragged = proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + speed)); + valueWhenLastDragged = proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + speed)); - e.originalComponent->enableUnboundedMouseMovement (true, false); - mouseWasHidden = true; - } - } - } + e.originalComponent->enableUnboundedMouseMovement (true, false); + mouseWasHidden = true; + } + } + } - valueWhenLastDragged = jlimit (minimum, maximum, valueWhenLastDragged); + valueWhenLastDragged = jlimit (minimum, maximum, valueWhenLastDragged); - if (sliderBeingDragged == 0) - { - setValue (snapValue (valueWhenLastDragged, true), - ! sendChangeOnlyOnRelease, true); - } - else if (sliderBeingDragged == 1) - { - setMinValue (snapValue (valueWhenLastDragged, true), - ! sendChangeOnlyOnRelease, false, true); + if (sliderBeingDragged == 0) + { + setValue (snapValue (valueWhenLastDragged, true), + ! sendChangeOnlyOnRelease, true); + } + else if (sliderBeingDragged == 1) + { + setMinValue (snapValue (valueWhenLastDragged, true), + ! sendChangeOnlyOnRelease, false, true); - if (e.mods.isShiftDown()) - setMaxValue (getMinValue() + minMaxDiff, false, false, true); - else - minMaxDiff = (double) valueMax.getValue() - (double) valueMin.getValue(); - } - else - { - jassert (sliderBeingDragged == 2); + if (e.mods.isShiftDown()) + setMaxValue (getMinValue() + minMaxDiff, false, false, true); + else + minMaxDiff = (double) valueMax.getValue() - (double) valueMin.getValue(); + } + else + { + jassert (sliderBeingDragged == 2); - setMaxValue (snapValue (valueWhenLastDragged, true), - ! sendChangeOnlyOnRelease, false, true); + setMaxValue (snapValue (valueWhenLastDragged, true), + ! sendChangeOnlyOnRelease, false, true); - if (e.mods.isShiftDown()) - setMinValue (getMaxValue() - minMaxDiff, false, false, true); - else - minMaxDiff = (double) valueMax.getValue() - (double) valueMin.getValue(); - } + if (e.mods.isShiftDown()) + setMinValue (getMaxValue() - minMaxDiff, false, false, true); + else + minMaxDiff = (double) valueMax.getValue() - (double) valueMin.getValue(); + } - mouseXWhenLastDragged = e.x; - mouseYWhenLastDragged = e.y; - } + mouseXWhenLastDragged = e.x; + mouseYWhenLastDragged = e.y; + } } void Slider::mouseDoubleClick (const MouseEvent&) { - if (doubleClickToValue - && isEnabled() - && style != IncDecButtons - && minimum <= doubleClickReturnValue - && maximum >= doubleClickReturnValue) - { - sendDragStart(); - setValue (doubleClickReturnValue, true, true); - sendDragEnd(); - } + if (doubleClickToValue + && isEnabled() + && style != IncDecButtons + && minimum <= doubleClickReturnValue + && maximum >= doubleClickReturnValue) + { + sendDragStart(); + setValue (doubleClickReturnValue, true, true); + sendDragEnd(); + } } void Slider::mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY) { - if (scrollWheelEnabled && isEnabled() - && style != TwoValueHorizontal - && style != TwoValueVertical) - { - if (maximum > minimum && ! isMouseButtonDownAnywhere()) - { - if (valueBox != 0) - valueBox->hideEditor (false); + if (scrollWheelEnabled && isEnabled() + && style != TwoValueHorizontal + && style != TwoValueVertical) + { + if (maximum > minimum && ! isMouseButtonDownAnywhere()) + { + if (valueBox != 0) + valueBox->hideEditor (false); - const double value = (double) currentValue.getValue(); - const double proportionDelta = (wheelIncrementX != 0 ? -wheelIncrementX : wheelIncrementY) * 0.15f; - const double currentPos = valueToProportionOfLength (value); - const double newValue = proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + proportionDelta)); + const double value = (double) currentValue.getValue(); + const double proportionDelta = (wheelIncrementX != 0 ? -wheelIncrementX : wheelIncrementY) * 0.15f; + const double currentPos = valueToProportionOfLength (value); + const double newValue = proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + proportionDelta)); - double delta = (newValue != value) - ? jmax (fabs (newValue - value), interval) : 0; + double delta = (newValue != value) + ? jmax (fabs (newValue - value), interval) : 0; - if (value > newValue) - delta = -delta; + if (value > newValue) + delta = -delta; - sendDragStart(); - setValue (snapValue (value + delta, false), true, true); - sendDragEnd(); - } - } - else - { - Component::mouseWheelMove (e, wheelIncrementX, wheelIncrementY); - } + sendDragStart(); + setValue (snapValue (value + delta, false), true, true); + sendDragEnd(); + } + } + else + { + Component::mouseWheelMove (e, wheelIncrementX, wheelIncrementY); + } } void SliderListener::sliderDragStarted (Slider*) @@ -50244,528 +49949,527 @@ BEGIN_JUCE_NAMESPACE class DragOverlayComp : public Component { public: - DragOverlayComp (Image* const image_) - : image (image_) - { - image->multiplyAllAlphas (0.8f); - setAlwaysOnTop (true); - } + DragOverlayComp (Image* const image_) + : image (image_) + { + image->multiplyAllAlphas (0.8f); + setAlwaysOnTop (true); + } - ~DragOverlayComp() - { - } + ~DragOverlayComp() + { + } - void paint (Graphics& g) - { - g.drawImageAt (image, 0, 0); - } + void paint (Graphics& g) + { + g.drawImageAt (image, 0, 0); + } private: - ScopedPointer image; + ScopedPointer image; - DragOverlayComp (const DragOverlayComp&); - const DragOverlayComp& operator= (const DragOverlayComp&); + DragOverlayComp (const DragOverlayComp&); + const DragOverlayComp& operator= (const DragOverlayComp&); }; TableHeaderComponent::TableHeaderComponent() - : listeners (2), - columnsChanged (false), - columnsResized (false), - sortChanged (false), - menuActive (true), - stretchToFit (false), - columnIdBeingResized (0), - columnIdBeingDragged (0), - columnIdUnderMouse (0), - lastDeliberateWidth (0) + : columnsChanged (false), + columnsResized (false), + sortChanged (false), + menuActive (true), + stretchToFit (false), + columnIdBeingResized (0), + columnIdBeingDragged (0), + columnIdUnderMouse (0), + lastDeliberateWidth (0) { } TableHeaderComponent::~TableHeaderComponent() { - dragOverlayComp = 0; + dragOverlayComp = 0; } void TableHeaderComponent::setPopupMenuActive (const bool hasMenu) { - menuActive = hasMenu; + menuActive = hasMenu; } -bool TableHeaderComponent::isPopupMenuActive() const { return menuActive; } +bool TableHeaderComponent::isPopupMenuActive() const { return menuActive; } int TableHeaderComponent::getNumColumns (const bool onlyCountVisibleColumns) const { - if (onlyCountVisibleColumns) - { - int num = 0; + if (onlyCountVisibleColumns) + { + int num = 0; - for (int i = columns.size(); --i >= 0;) - if (columns.getUnchecked(i)->isVisible()) - ++num; + for (int i = columns.size(); --i >= 0;) + if (columns.getUnchecked(i)->isVisible()) + ++num; - return num; - } - else - { - return columns.size(); - } + return num; + } + else + { + return columns.size(); + } } const String TableHeaderComponent::getColumnName (const int columnId) const { - const ColumnInfo* const ci = getInfoForId (columnId); - return ci != 0 ? ci->name : String::empty; + const ColumnInfo* const ci = getInfoForId (columnId); + return ci != 0 ? ci->name : String::empty; } void TableHeaderComponent::setColumnName (const int columnId, const String& newName) { - ColumnInfo* const ci = getInfoForId (columnId); + ColumnInfo* const ci = getInfoForId (columnId); - if (ci != 0 && ci->name != newName) - { - ci->name = newName; - sendColumnsChanged(); - } + if (ci != 0 && ci->name != newName) + { + ci->name = newName; + sendColumnsChanged(); + } } void TableHeaderComponent::addColumn (const String& columnName, - const int columnId, - const int width, - const int minimumWidth, - const int maximumWidth, - const int propertyFlags, - const int insertIndex) + const int columnId, + const int width, + const int minimumWidth, + const int maximumWidth, + const int propertyFlags, + const int insertIndex) { - // can't have a duplicate or null ID! - jassert (columnId != 0 && getIndexOfColumnId (columnId, false) < 0); - jassert (width > 0); + // can't have a duplicate or null ID! + jassert (columnId != 0 && getIndexOfColumnId (columnId, false) < 0); + jassert (width > 0); - ColumnInfo* const ci = new ColumnInfo(); - ci->name = columnName; - ci->id = columnId; - ci->width = width; - ci->lastDeliberateWidth = width; - ci->minimumWidth = minimumWidth; - ci->maximumWidth = maximumWidth; - if (ci->maximumWidth < 0) - ci->maximumWidth = INT_MAX; - jassert (ci->maximumWidth >= ci->minimumWidth); - ci->propertyFlags = propertyFlags; + ColumnInfo* const ci = new ColumnInfo(); + ci->name = columnName; + ci->id = columnId; + ci->width = width; + ci->lastDeliberateWidth = width; + ci->minimumWidth = minimumWidth; + ci->maximumWidth = maximumWidth; + if (ci->maximumWidth < 0) + ci->maximumWidth = INT_MAX; + jassert (ci->maximumWidth >= ci->minimumWidth); + ci->propertyFlags = propertyFlags; - columns.insert (insertIndex, ci); - sendColumnsChanged(); + columns.insert (insertIndex, ci); + sendColumnsChanged(); } void TableHeaderComponent::removeColumn (const int columnIdToRemove) { - const int index = getIndexOfColumnId (columnIdToRemove, false); + const int index = getIndexOfColumnId (columnIdToRemove, false); - if (index >= 0) - { - columns.remove (index); - sortChanged = true; - sendColumnsChanged(); - } + if (index >= 0) + { + columns.remove (index); + sortChanged = true; + sendColumnsChanged(); + } } void TableHeaderComponent::removeAllColumns() { - if (columns.size() > 0) - { - columns.clear(); - sendColumnsChanged(); - } + if (columns.size() > 0) + { + columns.clear(); + sendColumnsChanged(); + } } void TableHeaderComponent::moveColumn (const int columnId, int newIndex) { - const int currentIndex = getIndexOfColumnId (columnId, false); - newIndex = visibleIndexToTotalIndex (newIndex); + const int currentIndex = getIndexOfColumnId (columnId, false); + newIndex = visibleIndexToTotalIndex (newIndex); - if (columns [currentIndex] != 0 && currentIndex != newIndex) - { - columns.move (currentIndex, newIndex); - sendColumnsChanged(); - } + if (columns [currentIndex] != 0 && currentIndex != newIndex) + { + columns.move (currentIndex, newIndex); + sendColumnsChanged(); + } } int TableHeaderComponent::getColumnWidth (const int columnId) const { - const ColumnInfo* const ci = getInfoForId (columnId); - return ci != 0 ? ci->width : 0; + const ColumnInfo* const ci = getInfoForId (columnId); + return ci != 0 ? ci->width : 0; } void TableHeaderComponent::setColumnWidth (const int columnId, const int newWidth) { - ColumnInfo* const ci = getInfoForId (columnId); + ColumnInfo* const ci = getInfoForId (columnId); - if (ci != 0 && ci->width != newWidth) - { - const int numColumns = getNumColumns (true); + if (ci != 0 && ci->width != newWidth) + { + const int numColumns = getNumColumns (true); - ci->lastDeliberateWidth = ci->width - = jlimit (ci->minimumWidth, ci->maximumWidth, newWidth); + ci->lastDeliberateWidth = ci->width + = jlimit (ci->minimumWidth, ci->maximumWidth, newWidth); - if (stretchToFit) - { - const int index = getIndexOfColumnId (columnId, true) + 1; + if (stretchToFit) + { + const int index = getIndexOfColumnId (columnId, true) + 1; - if (((unsigned int) index) < (unsigned int) numColumns) - { - const int x = getColumnPosition (index).getX(); + if (((unsigned int) index) < (unsigned int) numColumns) + { + const int x = getColumnPosition (index).getX(); - if (lastDeliberateWidth == 0) - lastDeliberateWidth = getTotalWidth(); + if (lastDeliberateWidth == 0) + lastDeliberateWidth = getTotalWidth(); - resizeColumnsToFit (visibleIndexToTotalIndex (index), lastDeliberateWidth - x); - } - } + resizeColumnsToFit (visibleIndexToTotalIndex (index), lastDeliberateWidth - x); + } + } - repaint(); - columnsResized = true; - triggerAsyncUpdate(); - } + repaint(); + columnsResized = true; + triggerAsyncUpdate(); + } } int TableHeaderComponent::getIndexOfColumnId (const int columnId, const bool onlyCountVisibleColumns) const { - int n = 0; + int n = 0; - for (int i = 0; i < columns.size(); ++i) - { - if ((! onlyCountVisibleColumns) || columns.getUnchecked(i)->isVisible()) - { - if (columns.getUnchecked(i)->id == columnId) - return n; + for (int i = 0; i < columns.size(); ++i) + { + if ((! onlyCountVisibleColumns) || columns.getUnchecked(i)->isVisible()) + { + if (columns.getUnchecked(i)->id == columnId) + return n; - ++n; - } - } + ++n; + } + } - return -1; + return -1; } int TableHeaderComponent::getColumnIdOfIndex (int index, const bool onlyCountVisibleColumns) const { - if (onlyCountVisibleColumns) - index = visibleIndexToTotalIndex (index); + if (onlyCountVisibleColumns) + index = visibleIndexToTotalIndex (index); - const ColumnInfo* const ci = columns [index]; - return (ci != 0) ? ci->id : 0; + const ColumnInfo* const ci = columns [index]; + return (ci != 0) ? ci->id : 0; } const Rectangle TableHeaderComponent::getColumnPosition (const int index) const { - int x = 0, width = 0, n = 0; + int x = 0, width = 0, n = 0; - for (int i = 0; i < columns.size(); ++i) - { - x += width; + for (int i = 0; i < columns.size(); ++i) + { + x += width; - if (columns.getUnchecked(i)->isVisible()) - { - width = columns.getUnchecked(i)->width; + if (columns.getUnchecked(i)->isVisible()) + { + width = columns.getUnchecked(i)->width; - if (n++ == index) - break; - } - else - { - width = 0; - } - } + if (n++ == index) + break; + } + else + { + width = 0; + } + } - return Rectangle (x, 0, width, getHeight()); + return Rectangle (x, 0, width, getHeight()); } int TableHeaderComponent::getColumnIdAtX (const int xToFind) const { - if (xToFind >= 0) - { - int x = 0; + if (xToFind >= 0) + { + int x = 0; - for (int i = 0; i < columns.size(); ++i) - { - const ColumnInfo* const ci = columns.getUnchecked(i); + for (int i = 0; i < columns.size(); ++i) + { + const ColumnInfo* const ci = columns.getUnchecked(i); - if (ci->isVisible()) - { - x += ci->width; + if (ci->isVisible()) + { + x += ci->width; - if (xToFind < x) - return ci->id; - } - } - } + if (xToFind < x) + return ci->id; + } + } + } - return 0; + return 0; } int TableHeaderComponent::getTotalWidth() const { - int w = 0; + int w = 0; - for (int i = columns.size(); --i >= 0;) - if (columns.getUnchecked(i)->isVisible()) - w += columns.getUnchecked(i)->width; + for (int i = columns.size(); --i >= 0;) + if (columns.getUnchecked(i)->isVisible()) + w += columns.getUnchecked(i)->width; - return w; + return w; } void TableHeaderComponent::setStretchToFitActive (const bool shouldStretchToFit) { - stretchToFit = shouldStretchToFit; - lastDeliberateWidth = getTotalWidth(); - resized(); + stretchToFit = shouldStretchToFit; + lastDeliberateWidth = getTotalWidth(); + resized(); } bool TableHeaderComponent::isStretchToFitActive() const { - return stretchToFit; + return stretchToFit; } void TableHeaderComponent::resizeAllColumnsToFit (int targetTotalWidth) { - if (stretchToFit && getWidth() > 0 - && columnIdBeingResized == 0 && columnIdBeingDragged == 0) - { - lastDeliberateWidth = targetTotalWidth; - resizeColumnsToFit (0, targetTotalWidth); - } + if (stretchToFit && getWidth() > 0 + && columnIdBeingResized == 0 && columnIdBeingDragged == 0) + { + lastDeliberateWidth = targetTotalWidth; + resizeColumnsToFit (0, targetTotalWidth); + } } void TableHeaderComponent::resizeColumnsToFit (int firstColumnIndex, int targetTotalWidth) { - targetTotalWidth = jmax (targetTotalWidth, 0); + targetTotalWidth = jmax (targetTotalWidth, 0); - StretchableObjectResizer sor; - int i; - for (i = firstColumnIndex; i < columns.size(); ++i) - { - ColumnInfo* const ci = columns.getUnchecked(i); + StretchableObjectResizer sor; + int i; + for (i = firstColumnIndex; i < columns.size(); ++i) + { + ColumnInfo* const ci = columns.getUnchecked(i); - if (ci->isVisible()) - sor.addItem (ci->lastDeliberateWidth, ci->minimumWidth, ci->maximumWidth); - } + if (ci->isVisible()) + sor.addItem (ci->lastDeliberateWidth, ci->minimumWidth, ci->maximumWidth); + } - sor.resizeToFit (targetTotalWidth); + sor.resizeToFit (targetTotalWidth); - int visIndex = 0; - for (i = firstColumnIndex; i < columns.size(); ++i) - { - ColumnInfo* const ci = columns.getUnchecked(i); + int visIndex = 0; + for (i = firstColumnIndex; i < columns.size(); ++i) + { + ColumnInfo* const ci = columns.getUnchecked(i); - if (ci->isVisible()) - { - const int newWidth = jlimit (ci->minimumWidth, ci->maximumWidth, - (int) floor (sor.getItemSize (visIndex++))); + if (ci->isVisible()) + { + const int newWidth = jlimit (ci->minimumWidth, ci->maximumWidth, + (int) floor (sor.getItemSize (visIndex++))); - if (newWidth != ci->width) - { - ci->width = newWidth; - repaint(); - columnsResized = true; - triggerAsyncUpdate(); - } - } - } + if (newWidth != ci->width) + { + ci->width = newWidth; + repaint(); + columnsResized = true; + triggerAsyncUpdate(); + } + } + } } void TableHeaderComponent::setColumnVisible (const int columnId, const bool shouldBeVisible) { - ColumnInfo* const ci = getInfoForId (columnId); + ColumnInfo* const ci = getInfoForId (columnId); - if (ci != 0 && shouldBeVisible != ci->isVisible()) - { - if (shouldBeVisible) - ci->propertyFlags |= visible; - else - ci->propertyFlags &= ~visible; + if (ci != 0 && shouldBeVisible != ci->isVisible()) + { + if (shouldBeVisible) + ci->propertyFlags |= visible; + else + ci->propertyFlags &= ~visible; - sendColumnsChanged(); - resized(); - } + sendColumnsChanged(); + resized(); + } } bool TableHeaderComponent::isColumnVisible (const int columnId) const { - const ColumnInfo* const ci = getInfoForId (columnId); - return ci != 0 && ci->isVisible(); + const ColumnInfo* const ci = getInfoForId (columnId); + return ci != 0 && ci->isVisible(); } void TableHeaderComponent::setSortColumnId (const int columnId, const bool sortForwards) { - if (getSortColumnId() != columnId || isSortedForwards() != sortForwards) - { - for (int i = columns.size(); --i >= 0;) - columns.getUnchecked(i)->propertyFlags &= ~(sortedForwards | sortedBackwards); + if (getSortColumnId() != columnId || isSortedForwards() != sortForwards) + { + for (int i = columns.size(); --i >= 0;) + columns.getUnchecked(i)->propertyFlags &= ~(sortedForwards | sortedBackwards); - ColumnInfo* const ci = getInfoForId (columnId); + ColumnInfo* const ci = getInfoForId (columnId); - if (ci != 0) - ci->propertyFlags |= (sortForwards ? sortedForwards : sortedBackwards); + if (ci != 0) + ci->propertyFlags |= (sortForwards ? sortedForwards : sortedBackwards); - reSortTable(); - } + reSortTable(); + } } int TableHeaderComponent::getSortColumnId() const { - for (int i = columns.size(); --i >= 0;) - if ((columns.getUnchecked(i)->propertyFlags & (sortedForwards | sortedBackwards)) != 0) - return columns.getUnchecked(i)->id; + for (int i = columns.size(); --i >= 0;) + if ((columns.getUnchecked(i)->propertyFlags & (sortedForwards | sortedBackwards)) != 0) + return columns.getUnchecked(i)->id; - return 0; + return 0; } bool TableHeaderComponent::isSortedForwards() const { - for (int i = columns.size(); --i >= 0;) - if ((columns.getUnchecked(i)->propertyFlags & (sortedForwards | sortedBackwards)) != 0) - return (columns.getUnchecked(i)->propertyFlags & sortedForwards) != 0; + for (int i = columns.size(); --i >= 0;) + if ((columns.getUnchecked(i)->propertyFlags & (sortedForwards | sortedBackwards)) != 0) + return (columns.getUnchecked(i)->propertyFlags & sortedForwards) != 0; - return true; + return true; } void TableHeaderComponent::reSortTable() { - sortChanged = true; - repaint(); - triggerAsyncUpdate(); + sortChanged = true; + repaint(); + triggerAsyncUpdate(); } const String TableHeaderComponent::toString() const { - String s; + String s; - XmlElement doc (T("TABLELAYOUT")); + XmlElement doc (T("TABLELAYOUT")); - doc.setAttribute (T("sortedCol"), getSortColumnId()); - doc.setAttribute (T("sortForwards"), isSortedForwards()); + doc.setAttribute (T("sortedCol"), getSortColumnId()); + doc.setAttribute (T("sortForwards"), isSortedForwards()); - for (int i = 0; i < columns.size(); ++i) - { - const ColumnInfo* const ci = columns.getUnchecked (i); + for (int i = 0; i < columns.size(); ++i) + { + const ColumnInfo* const ci = columns.getUnchecked (i); - XmlElement* const e = new XmlElement (T("COLUMN")); - doc.addChildElement (e); + XmlElement* const e = new XmlElement (T("COLUMN")); + doc.addChildElement (e); - e->setAttribute (T("id"), ci->id); - e->setAttribute (T("visible"), ci->isVisible()); - e->setAttribute (T("width"), ci->width); - } + e->setAttribute (T("id"), ci->id); + e->setAttribute (T("visible"), ci->isVisible()); + e->setAttribute (T("width"), ci->width); + } - return doc.createDocument (String::empty, true, false); + return doc.createDocument (String::empty, true, false); } void TableHeaderComponent::restoreFromString (const String& storedVersion) { - XmlDocument doc (storedVersion); - ScopedPointer storedXml (doc.getDocumentElement()); + XmlDocument doc (storedVersion); + ScopedPointer storedXml (doc.getDocumentElement()); - int index = 0; + int index = 0; - if (storedXml != 0 && storedXml->hasTagName (T("TABLELAYOUT"))) - { - forEachXmlChildElement (*storedXml, col) - { - const int tabId = col->getIntAttribute (T("id")); + if (storedXml != 0 && storedXml->hasTagName (T("TABLELAYOUT"))) + { + forEachXmlChildElement (*storedXml, col) + { + const int tabId = col->getIntAttribute (T("id")); - ColumnInfo* const ci = getInfoForId (tabId); + ColumnInfo* const ci = getInfoForId (tabId); - if (ci != 0) - { - columns.move (columns.indexOf (ci), index); - ci->width = col->getIntAttribute (T("width")); - setColumnVisible (tabId, col->getBoolAttribute (T("visible"))); - } + if (ci != 0) + { + columns.move (columns.indexOf (ci), index); + ci->width = col->getIntAttribute (T("width")); + setColumnVisible (tabId, col->getBoolAttribute (T("visible"))); + } - ++index; - } + ++index; + } - columnsResized = true; - sendColumnsChanged(); + columnsResized = true; + sendColumnsChanged(); - setSortColumnId (storedXml->getIntAttribute (T("sortedCol")), - storedXml->getBoolAttribute (T("sortForwards"), true)); - } + setSortColumnId (storedXml->getIntAttribute (T("sortedCol")), + storedXml->getBoolAttribute (T("sortForwards"), true)); + } } void TableHeaderComponent::addListener (TableHeaderListener* const newListener) { - listeners.addIfNotAlreadyThere (newListener); + listeners.addIfNotAlreadyThere (newListener); } void TableHeaderComponent::removeListener (TableHeaderListener* const listenerToRemove) { - listeners.removeValue (listenerToRemove); + listeners.removeValue (listenerToRemove); } void TableHeaderComponent::columnClicked (int columnId, const ModifierKeys& mods) { - const ColumnInfo* const ci = getInfoForId (columnId); + const ColumnInfo* const ci = getInfoForId (columnId); - if (ci != 0 && (ci->propertyFlags & sortable) != 0 && ! mods.isPopupMenu()) - setSortColumnId (columnId, (ci->propertyFlags & sortedForwards) == 0); + if (ci != 0 && (ci->propertyFlags & sortable) != 0 && ! mods.isPopupMenu()) + setSortColumnId (columnId, (ci->propertyFlags & sortedForwards) == 0); } void TableHeaderComponent::addMenuItems (PopupMenu& menu, const int /*columnIdClicked*/) { - for (int i = 0; i < columns.size(); ++i) - { - const ColumnInfo* const ci = columns.getUnchecked(i); + for (int i = 0; i < columns.size(); ++i) + { + const ColumnInfo* const ci = columns.getUnchecked(i); - if ((ci->propertyFlags & appearsOnColumnMenu) != 0) - menu.addItem (ci->id, ci->name, - (ci->propertyFlags & (sortedForwards | sortedBackwards)) == 0, - isColumnVisible (ci->id)); - } + if ((ci->propertyFlags & appearsOnColumnMenu) != 0) + menu.addItem (ci->id, ci->name, + (ci->propertyFlags & (sortedForwards | sortedBackwards)) == 0, + isColumnVisible (ci->id)); + } } void TableHeaderComponent::reactToMenuItem (const int menuReturnId, const int /*columnIdClicked*/) { - if (getIndexOfColumnId (menuReturnId, false) >= 0) - setColumnVisible (menuReturnId, ! isColumnVisible (menuReturnId)); + if (getIndexOfColumnId (menuReturnId, false) >= 0) + setColumnVisible (menuReturnId, ! isColumnVisible (menuReturnId)); } void TableHeaderComponent::paint (Graphics& g) { - LookAndFeel& lf = getLookAndFeel(); + LookAndFeel& lf = getLookAndFeel(); - lf.drawTableHeaderBackground (g, *this); + lf.drawTableHeaderBackground (g, *this); - const Rectangle clip (g.getClipBounds()); + const Rectangle clip (g.getClipBounds()); - int x = 0; - for (int i = 0; i < columns.size(); ++i) - { - const ColumnInfo* const ci = columns.getUnchecked(i); + int x = 0; + for (int i = 0; i < columns.size(); ++i) + { + const ColumnInfo* const ci = columns.getUnchecked(i); - if (ci->isVisible()) - { - if (x + ci->width > clip.getX() - && (ci->id != columnIdBeingDragged - || dragOverlayComp == 0 - || ! dragOverlayComp->isVisible())) - { - g.saveState(); - g.setOrigin (x, 0); - g.reduceClipRegion (0, 0, ci->width, getHeight()); + if (ci->isVisible()) + { + if (x + ci->width > clip.getX() + && (ci->id != columnIdBeingDragged + || dragOverlayComp == 0 + || ! dragOverlayComp->isVisible())) + { + g.saveState(); + g.setOrigin (x, 0); + g.reduceClipRegion (0, 0, ci->width, getHeight()); - lf.drawTableHeaderColumn (g, ci->name, ci->id, ci->width, getHeight(), - ci->id == columnIdUnderMouse, - ci->id == columnIdUnderMouse && isMouseButtonDown(), - ci->propertyFlags); + lf.drawTableHeaderColumn (g, ci->name, ci->id, ci->width, getHeight(), + ci->id == columnIdUnderMouse, + ci->id == columnIdUnderMouse && isMouseButtonDown(), + ci->propertyFlags); - g.restoreState(); - } + g.restoreState(); + } - x += ci->width; + x += ci->width; - if (x >= clip.getRight()) - break; - } - } + if (x >= clip.getRight()) + break; + } + } } void TableHeaderComponent::resized() @@ -50774,367 +50478,367 @@ void TableHeaderComponent::resized() void TableHeaderComponent::mouseMove (const MouseEvent& e) { - updateColumnUnderMouse (e.x, e.y); + updateColumnUnderMouse (e.x, e.y); } void TableHeaderComponent::mouseEnter (const MouseEvent& e) { - updateColumnUnderMouse (e.x, e.y); + updateColumnUnderMouse (e.x, e.y); } void TableHeaderComponent::mouseExit (const MouseEvent& e) { - updateColumnUnderMouse (e.x, e.y); + updateColumnUnderMouse (e.x, e.y); } void TableHeaderComponent::mouseDown (const MouseEvent& e) { - repaint(); - columnIdBeingResized = 0; - columnIdBeingDragged = 0; + repaint(); + columnIdBeingResized = 0; + columnIdBeingDragged = 0; - if (columnIdUnderMouse != 0) - { - draggingColumnOffset = e.x - getColumnPosition (getIndexOfColumnId (columnIdUnderMouse, true)).getX(); + if (columnIdUnderMouse != 0) + { + draggingColumnOffset = e.x - getColumnPosition (getIndexOfColumnId (columnIdUnderMouse, true)).getX(); - if (e.mods.isPopupMenu()) - columnClicked (columnIdUnderMouse, e.mods); - } + if (e.mods.isPopupMenu()) + columnClicked (columnIdUnderMouse, e.mods); + } - if (menuActive && e.mods.isPopupMenu()) - showColumnChooserMenu (columnIdUnderMouse); + if (menuActive && e.mods.isPopupMenu()) + showColumnChooserMenu (columnIdUnderMouse); } void TableHeaderComponent::mouseDrag (const MouseEvent& e) { - if (columnIdBeingResized == 0 - && columnIdBeingDragged == 0 - && ! (e.mouseWasClicked() || e.mods.isPopupMenu())) - { - dragOverlayComp = 0; + if (columnIdBeingResized == 0 + && columnIdBeingDragged == 0 + && ! (e.mouseWasClicked() || e.mods.isPopupMenu())) + { + dragOverlayComp = 0; - columnIdBeingResized = getResizeDraggerAt (e.getMouseDownX()); + columnIdBeingResized = getResizeDraggerAt (e.getMouseDownX()); - if (columnIdBeingResized != 0) - { - const ColumnInfo* const ci = getInfoForId (columnIdBeingResized); - initialColumnWidth = ci->width; - } - else - { - beginDrag (e); - } - } + if (columnIdBeingResized != 0) + { + const ColumnInfo* const ci = getInfoForId (columnIdBeingResized); + initialColumnWidth = ci->width; + } + else + { + beginDrag (e); + } + } - if (columnIdBeingResized != 0) - { - const ColumnInfo* const ci = getInfoForId (columnIdBeingResized); + if (columnIdBeingResized != 0) + { + const ColumnInfo* const ci = getInfoForId (columnIdBeingResized); - if (ci != 0) - { - int w = jlimit (ci->minimumWidth, ci->maximumWidth, - initialColumnWidth + e.getDistanceFromDragStartX()); + if (ci != 0) + { + int w = jlimit (ci->minimumWidth, ci->maximumWidth, + initialColumnWidth + e.getDistanceFromDragStartX()); - if (stretchToFit) - { - // prevent us dragging a column too far right if we're in stretch-to-fit mode - int minWidthOnRight = 0; - for (int i = getIndexOfColumnId (columnIdBeingResized, false) + 1; i < columns.size(); ++i) - if (columns.getUnchecked (i)->isVisible()) - minWidthOnRight += columns.getUnchecked (i)->minimumWidth; + if (stretchToFit) + { + // prevent us dragging a column too far right if we're in stretch-to-fit mode + int minWidthOnRight = 0; + for (int i = getIndexOfColumnId (columnIdBeingResized, false) + 1; i < columns.size(); ++i) + if (columns.getUnchecked (i)->isVisible()) + minWidthOnRight += columns.getUnchecked (i)->minimumWidth; - const Rectangle currentPos (getColumnPosition (getIndexOfColumnId (columnIdBeingResized, true))); - w = jmax (ci->minimumWidth, jmin (w, getWidth() - minWidthOnRight - currentPos.getX())); - } + const Rectangle currentPos (getColumnPosition (getIndexOfColumnId (columnIdBeingResized, true))); + w = jmax (ci->minimumWidth, jmin (w, getWidth() - minWidthOnRight - currentPos.getX())); + } - setColumnWidth (columnIdBeingResized, w); - } - } - else if (columnIdBeingDragged != 0) - { - if (e.y >= -50 && e.y < getHeight() + 50) - { - if (dragOverlayComp != 0) - { - dragOverlayComp->setVisible (true); - dragOverlayComp->setBounds (jlimit (0, - jmax (0, getTotalWidth() - dragOverlayComp->getWidth()), - e.x - draggingColumnOffset), - 0, - dragOverlayComp->getWidth(), - getHeight()); + setColumnWidth (columnIdBeingResized, w); + } + } + else if (columnIdBeingDragged != 0) + { + if (e.y >= -50 && e.y < getHeight() + 50) + { + if (dragOverlayComp != 0) + { + dragOverlayComp->setVisible (true); + dragOverlayComp->setBounds (jlimit (0, + jmax (0, getTotalWidth() - dragOverlayComp->getWidth()), + e.x - draggingColumnOffset), + 0, + dragOverlayComp->getWidth(), + getHeight()); - for (int i = columns.size(); --i >= 0;) - { - const int currentIndex = getIndexOfColumnId (columnIdBeingDragged, true); - int newIndex = currentIndex; + for (int i = columns.size(); --i >= 0;) + { + const int currentIndex = getIndexOfColumnId (columnIdBeingDragged, true); + int newIndex = currentIndex; - if (newIndex > 0) - { - // if the previous column isn't draggable, we can't move our column - // past it, because that'd change the undraggable column's position.. - const ColumnInfo* const previous = columns.getUnchecked (newIndex - 1); + if (newIndex > 0) + { + // if the previous column isn't draggable, we can't move our column + // past it, because that'd change the undraggable column's position.. + const ColumnInfo* const previous = columns.getUnchecked (newIndex - 1); - if ((previous->propertyFlags & draggable) != 0) - { - const int leftOfPrevious = getColumnPosition (newIndex - 1).getX(); - const int rightOfCurrent = getColumnPosition (newIndex).getRight(); + if ((previous->propertyFlags & draggable) != 0) + { + const int leftOfPrevious = getColumnPosition (newIndex - 1).getX(); + const int rightOfCurrent = getColumnPosition (newIndex).getRight(); - if (abs (dragOverlayComp->getX() - leftOfPrevious) - < abs (dragOverlayComp->getRight() - rightOfCurrent)) - { - --newIndex; - } - } - } + if (abs (dragOverlayComp->getX() - leftOfPrevious) + < abs (dragOverlayComp->getRight() - rightOfCurrent)) + { + --newIndex; + } + } + } - if (newIndex < columns.size() - 1) - { - // if the next column isn't draggable, we can't move our column - // past it, because that'd change the undraggable column's position.. - const ColumnInfo* const nextCol = columns.getUnchecked (newIndex + 1); + if (newIndex < columns.size() - 1) + { + // if the next column isn't draggable, we can't move our column + // past it, because that'd change the undraggable column's position.. + const ColumnInfo* const nextCol = columns.getUnchecked (newIndex + 1); - if ((nextCol->propertyFlags & draggable) != 0) - { - const int leftOfCurrent = getColumnPosition (newIndex).getX(); - const int rightOfNext = getColumnPosition (newIndex + 1).getRight(); + if ((nextCol->propertyFlags & draggable) != 0) + { + const int leftOfCurrent = getColumnPosition (newIndex).getX(); + const int rightOfNext = getColumnPosition (newIndex + 1).getRight(); - if (abs (dragOverlayComp->getX() - leftOfCurrent) - > abs (dragOverlayComp->getRight() - rightOfNext)) - { - ++newIndex; - } - } - } + if (abs (dragOverlayComp->getX() - leftOfCurrent) + > abs (dragOverlayComp->getRight() - rightOfNext)) + { + ++newIndex; + } + } + } - if (newIndex != currentIndex) - moveColumn (columnIdBeingDragged, newIndex); - else - break; - } - } - } - else - { - endDrag (draggingColumnOriginalIndex); - } - } + if (newIndex != currentIndex) + moveColumn (columnIdBeingDragged, newIndex); + else + break; + } + } + } + else + { + endDrag (draggingColumnOriginalIndex); + } + } } void TableHeaderComponent::beginDrag (const MouseEvent& e) { - if (columnIdBeingDragged == 0) - { - columnIdBeingDragged = getColumnIdAtX (e.getMouseDownX()); + if (columnIdBeingDragged == 0) + { + columnIdBeingDragged = getColumnIdAtX (e.getMouseDownX()); - const ColumnInfo* const ci = getInfoForId (columnIdBeingDragged); + const ColumnInfo* const ci = getInfoForId (columnIdBeingDragged); - if (ci == 0 || (ci->propertyFlags & draggable) == 0) - { - columnIdBeingDragged = 0; - } - else - { - draggingColumnOriginalIndex = getIndexOfColumnId (columnIdBeingDragged, true); + if (ci == 0 || (ci->propertyFlags & draggable) == 0) + { + columnIdBeingDragged = 0; + } + else + { + draggingColumnOriginalIndex = getIndexOfColumnId (columnIdBeingDragged, true); - const Rectangle columnRect (getColumnPosition (draggingColumnOriginalIndex)); + const Rectangle columnRect (getColumnPosition (draggingColumnOriginalIndex)); - const int temp = columnIdBeingDragged; - columnIdBeingDragged = 0; + const int temp = columnIdBeingDragged; + columnIdBeingDragged = 0; - addAndMakeVisible (dragOverlayComp = new DragOverlayComp (createComponentSnapshot (columnRect, false))); - columnIdBeingDragged = temp; + addAndMakeVisible (dragOverlayComp = new DragOverlayComp (createComponentSnapshot (columnRect, false))); + columnIdBeingDragged = temp; - dragOverlayComp->setBounds (columnRect); + dragOverlayComp->setBounds (columnRect); - for (int i = listeners.size(); --i >= 0;) - { - listeners.getUnchecked(i)->tableColumnDraggingChanged (this, columnIdBeingDragged); - i = jmin (i, listeners.size() - 1); - } - } - } + for (int i = listeners.size(); --i >= 0;) + { + listeners.getUnchecked(i)->tableColumnDraggingChanged (this, columnIdBeingDragged); + i = jmin (i, listeners.size() - 1); + } + } + } } void TableHeaderComponent::endDrag (const int finalIndex) { - if (columnIdBeingDragged != 0) - { - moveColumn (columnIdBeingDragged, finalIndex); + if (columnIdBeingDragged != 0) + { + moveColumn (columnIdBeingDragged, finalIndex); - columnIdBeingDragged = 0; - repaint(); + columnIdBeingDragged = 0; + repaint(); - for (int i = listeners.size(); --i >= 0;) - { - listeners.getUnchecked(i)->tableColumnDraggingChanged (this, 0); - i = jmin (i, listeners.size() - 1); - } - } + for (int i = listeners.size(); --i >= 0;) + { + listeners.getUnchecked(i)->tableColumnDraggingChanged (this, 0); + i = jmin (i, listeners.size() - 1); + } + } } void TableHeaderComponent::mouseUp (const MouseEvent& e) { - mouseDrag (e); + mouseDrag (e); - for (int i = columns.size(); --i >= 0;) - if (columns.getUnchecked (i)->isVisible()) - columns.getUnchecked (i)->lastDeliberateWidth = columns.getUnchecked (i)->width; + for (int i = columns.size(); --i >= 0;) + if (columns.getUnchecked (i)->isVisible()) + columns.getUnchecked (i)->lastDeliberateWidth = columns.getUnchecked (i)->width; - columnIdBeingResized = 0; - repaint(); + columnIdBeingResized = 0; + repaint(); - endDrag (getIndexOfColumnId (columnIdBeingDragged, true)); + endDrag (getIndexOfColumnId (columnIdBeingDragged, true)); - updateColumnUnderMouse (e.x, e.y); + updateColumnUnderMouse (e.x, e.y); - if (columnIdUnderMouse != 0 && e.mouseWasClicked() && ! e.mods.isPopupMenu()) - columnClicked (columnIdUnderMouse, e.mods); + if (columnIdUnderMouse != 0 && e.mouseWasClicked() && ! e.mods.isPopupMenu()) + columnClicked (columnIdUnderMouse, e.mods); - dragOverlayComp = 0; + dragOverlayComp = 0; } const MouseCursor TableHeaderComponent::getMouseCursor() { - int x, y; - getMouseXYRelative (x, y); + int x, y; + getMouseXYRelative (x, y); - if (columnIdBeingResized != 0 || (getResizeDraggerAt (x) != 0 && ! isMouseButtonDown())) - return MouseCursor (MouseCursor::LeftRightResizeCursor); + if (columnIdBeingResized != 0 || (getResizeDraggerAt (x) != 0 && ! isMouseButtonDown())) + return MouseCursor (MouseCursor::LeftRightResizeCursor); - return Component::getMouseCursor(); + return Component::getMouseCursor(); } bool TableHeaderComponent::ColumnInfo::isVisible() const { - return (propertyFlags & TableHeaderComponent::visible) != 0; + return (propertyFlags & TableHeaderComponent::visible) != 0; } TableHeaderComponent::ColumnInfo* TableHeaderComponent::getInfoForId (const int id) const { - for (int i = columns.size(); --i >= 0;) - if (columns.getUnchecked(i)->id == id) - return columns.getUnchecked(i); + for (int i = columns.size(); --i >= 0;) + if (columns.getUnchecked(i)->id == id) + return columns.getUnchecked(i); - return 0; + return 0; } int TableHeaderComponent::visibleIndexToTotalIndex (const int visibleIndex) const { - int n = 0; + int n = 0; - for (int i = 0; i < columns.size(); ++i) - { - if (columns.getUnchecked(i)->isVisible()) - { - if (n == visibleIndex) - return i; + for (int i = 0; i < columns.size(); ++i) + { + if (columns.getUnchecked(i)->isVisible()) + { + if (n == visibleIndex) + return i; - ++n; - } - } + ++n; + } + } - return -1; + return -1; } void TableHeaderComponent::sendColumnsChanged() { - if (stretchToFit && lastDeliberateWidth > 0) - resizeAllColumnsToFit (lastDeliberateWidth); + if (stretchToFit && lastDeliberateWidth > 0) + resizeAllColumnsToFit (lastDeliberateWidth); - repaint(); - columnsChanged = true; - triggerAsyncUpdate(); + repaint(); + columnsChanged = true; + triggerAsyncUpdate(); } void TableHeaderComponent::handleAsyncUpdate() { - const bool changed = columnsChanged || sortChanged; - const bool sized = columnsResized || changed; - const bool sorted = sortChanged; - columnsChanged = false; - columnsResized = false; - sortChanged = false; + const bool changed = columnsChanged || sortChanged; + const bool sized = columnsResized || changed; + const bool sorted = sortChanged; + columnsChanged = false; + columnsResized = false; + sortChanged = false; - if (sorted) - { - for (int i = listeners.size(); --i >= 0;) - { - listeners.getUnchecked(i)->tableSortOrderChanged (this); - i = jmin (i, listeners.size() - 1); - } - } + if (sorted) + { + for (int i = listeners.size(); --i >= 0;) + { + listeners.getUnchecked(i)->tableSortOrderChanged (this); + i = jmin (i, listeners.size() - 1); + } + } - if (changed) - { - for (int i = listeners.size(); --i >= 0;) - { - listeners.getUnchecked(i)->tableColumnsChanged (this); - i = jmin (i, listeners.size() - 1); - } - } + if (changed) + { + for (int i = listeners.size(); --i >= 0;) + { + listeners.getUnchecked(i)->tableColumnsChanged (this); + i = jmin (i, listeners.size() - 1); + } + } - if (sized) - { - for (int i = listeners.size(); --i >= 0;) - { - listeners.getUnchecked(i)->tableColumnsResized (this); - i = jmin (i, listeners.size() - 1); - } - } + if (sized) + { + for (int i = listeners.size(); --i >= 0;) + { + listeners.getUnchecked(i)->tableColumnsResized (this); + i = jmin (i, listeners.size() - 1); + } + } } int TableHeaderComponent::getResizeDraggerAt (const int mouseX) const { - if (((unsigned int) mouseX) < (unsigned int) getWidth()) - { - const int draggableDistance = 3; - int x = 0; + if (((unsigned int) mouseX) < (unsigned int) getWidth()) + { + const int draggableDistance = 3; + int x = 0; - for (int i = 0; i < columns.size(); ++i) - { - const ColumnInfo* const ci = columns.getUnchecked(i); + for (int i = 0; i < columns.size(); ++i) + { + const ColumnInfo* const ci = columns.getUnchecked(i); - if (ci->isVisible()) - { - if (abs (mouseX - (x + ci->width)) <= draggableDistance - && (ci->propertyFlags & resizable) != 0) - return ci->id; + if (ci->isVisible()) + { + if (abs (mouseX - (x + ci->width)) <= draggableDistance + && (ci->propertyFlags & resizable) != 0) + return ci->id; - x += ci->width; - } - } - } + x += ci->width; + } + } + } - return 0; + return 0; } void TableHeaderComponent::updateColumnUnderMouse (int x, int y) { - const int newCol = (reallyContains (x, y, true) && getResizeDraggerAt (x) == 0) - ? getColumnIdAtX (x) : 0; + const int newCol = (reallyContains (x, y, true) && getResizeDraggerAt (x) == 0) + ? getColumnIdAtX (x) : 0; - if (newCol != columnIdUnderMouse) - { - columnIdUnderMouse = newCol; - repaint(); - } + if (newCol != columnIdUnderMouse) + { + columnIdUnderMouse = newCol; + repaint(); + } } void TableHeaderComponent::showColumnChooserMenu (const int columnIdClicked) { - PopupMenu m; - addMenuItems (m, columnIdClicked); + PopupMenu m; + addMenuItems (m, columnIdClicked); - if (m.getNumItems() > 0) - { - m.setLookAndFeel (&getLookAndFeel()); + if (m.getNumItems() > 0) + { + m.setLookAndFeel (&getLookAndFeel()); - const int result = m.show(); + const int result = m.show(); - if (result != 0) - reactToMenuItem (result, columnIdClicked); - } + if (result != 0) + reactToMenuItem (result, columnIdClicked); + } } void TableHeaderListener::tableColumnDraggingChanged (TableHeaderComponent*, int) @@ -51151,382 +50855,382 @@ BEGIN_JUCE_NAMESPACE static const tchar* const tableColumnPropertyTag = T("_tableColumnID"); class TableListRowComp : public Component, - public TooltipClient + public TooltipClient { public: - TableListRowComp (TableListBox& owner_) - : owner (owner_), - row (-1), - isSelected (false) - { - } + TableListRowComp (TableListBox& owner_) + : owner (owner_), + row (-1), + isSelected (false) + { + } - ~TableListRowComp() - { - deleteAllChildren(); - } + ~TableListRowComp() + { + deleteAllChildren(); + } - void paint (Graphics& g) - { - TableListBoxModel* const model = owner.getModel(); + void paint (Graphics& g) + { + TableListBoxModel* const model = owner.getModel(); - if (model != 0) - { - const TableHeaderComponent* const header = owner.getHeader(); + if (model != 0) + { + const TableHeaderComponent* const header = owner.getHeader(); - model->paintRowBackground (g, row, getWidth(), getHeight(), isSelected); + model->paintRowBackground (g, row, getWidth(), getHeight(), isSelected); - const int numColumns = header->getNumColumns (true); + const int numColumns = header->getNumColumns (true); - for (int i = 0; i < numColumns; ++i) - { - if (! columnsWithComponents [i]) - { - const int columnId = header->getColumnIdOfIndex (i, true); - Rectangle columnRect (header->getColumnPosition (i)); - columnRect.setSize (columnRect.getWidth(), getHeight()); + for (int i = 0; i < numColumns; ++i) + { + if (! columnsWithComponents [i]) + { + const int columnId = header->getColumnIdOfIndex (i, true); + Rectangle columnRect (header->getColumnPosition (i)); + columnRect.setSize (columnRect.getWidth(), getHeight()); - g.saveState(); + g.saveState(); - g.reduceClipRegion (columnRect); - g.setOrigin (columnRect.getX(), 0); + g.reduceClipRegion (columnRect); + g.setOrigin (columnRect.getX(), 0); - model->paintCell (g, row, columnId, columnRect.getWidth(), columnRect.getHeight(), isSelected); + model->paintCell (g, row, columnId, columnRect.getWidth(), columnRect.getHeight(), isSelected); - g.restoreState(); - } - } - } - } + g.restoreState(); + } + } + } + } - void update (const int newRow, const bool isNowSelected) - { - if (newRow != row || isNowSelected != isSelected) - { - row = newRow; - isSelected = isNowSelected; - repaint(); - } + void update (const int newRow, const bool isNowSelected) + { + if (newRow != row || isNowSelected != isSelected) + { + row = newRow; + isSelected = isNowSelected; + repaint(); + } - if (row < owner.getNumRows()) - { - jassert (row >= 0); + if (row < owner.getNumRows()) + { + jassert (row >= 0); - const tchar* const tagPropertyName = T("_tableLastUseNum"); - const int newTag = Random::getSystemRandom().nextInt(); + const tchar* const tagPropertyName = T("_tableLastUseNum"); + const int newTag = Random::getSystemRandom().nextInt(); - const TableHeaderComponent* const header = owner.getHeader(); - const int numColumns = header->getNumColumns (true); - int i; + const TableHeaderComponent* const header = owner.getHeader(); + const int numColumns = header->getNumColumns (true); + int i; - columnsWithComponents.clear(); + columnsWithComponents.clear(); - if (owner.getModel() != 0) - { - for (i = 0; i < numColumns; ++i) - { - const int columnId = header->getColumnIdOfIndex (i, true); + if (owner.getModel() != 0) + { + for (i = 0; i < numColumns; ++i) + { + const int columnId = header->getColumnIdOfIndex (i, true); - Component* const newComp - = owner.getModel()->refreshComponentForCell (row, columnId, isSelected, - findChildComponentForColumn (columnId)); + Component* const newComp + = owner.getModel()->refreshComponentForCell (row, columnId, isSelected, + findChildComponentForColumn (columnId)); - if (newComp != 0) - { - addAndMakeVisible (newComp); - newComp->setComponentProperty (tagPropertyName, newTag); - newComp->setComponentProperty (tableColumnPropertyTag, columnId); + if (newComp != 0) + { + addAndMakeVisible (newComp); + newComp->setComponentProperty (tagPropertyName, newTag); + newComp->setComponentProperty (tableColumnPropertyTag, columnId); - const Rectangle columnRect (header->getColumnPosition (i)); - newComp->setBounds (columnRect.getX(), 0, columnRect.getWidth(), getHeight()); + const Rectangle columnRect (header->getColumnPosition (i)); + newComp->setBounds (columnRect.getX(), 0, columnRect.getWidth(), getHeight()); - columnsWithComponents.setBit (i); - } - } - } + columnsWithComponents.setBit (i); + } + } + } - for (i = getNumChildComponents(); --i >= 0;) - { - Component* const c = getChildComponent (i); + for (i = getNumChildComponents(); --i >= 0;) + { + Component* const c = getChildComponent (i); - if (c->getComponentPropertyInt (tagPropertyName, false, 0) != newTag) - delete c; - } - } - else - { - columnsWithComponents.clear(); - deleteAllChildren(); - } - } + if (c->getComponentPropertyInt (tagPropertyName, false, 0) != newTag) + delete c; + } + } + else + { + columnsWithComponents.clear(); + deleteAllChildren(); + } + } - void resized() - { - for (int i = getNumChildComponents(); --i >= 0;) - { - Component* const c = getChildComponent (i); + void resized() + { + for (int i = getNumChildComponents(); --i >= 0;) + { + Component* const c = getChildComponent (i); - const int columnId = c->getComponentPropertyInt (tableColumnPropertyTag, false, 0); + const int columnId = c->getComponentPropertyInt (tableColumnPropertyTag, false, 0); - if (columnId != 0) - { - const Rectangle columnRect (owner.getHeader()->getColumnPosition (owner.getHeader()->getIndexOfColumnId (columnId, true))); - c->setBounds (columnRect.getX(), 0, columnRect.getWidth(), getHeight()); - } - } - } + if (columnId != 0) + { + const Rectangle columnRect (owner.getHeader()->getColumnPosition (owner.getHeader()->getIndexOfColumnId (columnId, true))); + c->setBounds (columnRect.getX(), 0, columnRect.getWidth(), getHeight()); + } + } + } - void mouseDown (const MouseEvent& e) - { - isDragging = false; - selectRowOnMouseUp = false; + void mouseDown (const MouseEvent& e) + { + isDragging = false; + selectRowOnMouseUp = false; - if (isEnabled()) - { - if (! isSelected) - { - owner.selectRowsBasedOnModifierKeys (row, e.mods); + if (isEnabled()) + { + if (! isSelected) + { + owner.selectRowsBasedOnModifierKeys (row, e.mods); - const int columnId = owner.getHeader()->getColumnIdAtX (e.x); + const int columnId = owner.getHeader()->getColumnIdAtX (e.x); - if (columnId != 0 && owner.getModel() != 0) - owner.getModel()->cellClicked (row, columnId, e); - } - else - { - selectRowOnMouseUp = true; - } - } - } + if (columnId != 0 && owner.getModel() != 0) + owner.getModel()->cellClicked (row, columnId, e); + } + else + { + selectRowOnMouseUp = true; + } + } + } - void mouseDrag (const MouseEvent& e) - { - if (isEnabled() && owner.getModel() != 0 && ! (e.mouseWasClicked() || isDragging)) - { - const SparseSet selectedRows (owner.getSelectedRows()); + void mouseDrag (const MouseEvent& e) + { + if (isEnabled() && owner.getModel() != 0 && ! (e.mouseWasClicked() || isDragging)) + { + const SparseSet selectedRows (owner.getSelectedRows()); - if (selectedRows.size() > 0) - { - const String dragDescription (owner.getModel()->getDragSourceDescription (selectedRows)); + if (selectedRows.size() > 0) + { + const String dragDescription (owner.getModel()->getDragSourceDescription (selectedRows)); - if (dragDescription.isNotEmpty()) - { - isDragging = true; - owner.startDragAndDrop (e, dragDescription); - } - } - } - } + if (dragDescription.isNotEmpty()) + { + isDragging = true; + owner.startDragAndDrop (e, dragDescription); + } + } + } + } - void mouseUp (const MouseEvent& e) - { - if (selectRowOnMouseUp && e.mouseWasClicked() && isEnabled()) - { - owner.selectRowsBasedOnModifierKeys (row, e.mods); + void mouseUp (const MouseEvent& e) + { + if (selectRowOnMouseUp && e.mouseWasClicked() && isEnabled()) + { + owner.selectRowsBasedOnModifierKeys (row, e.mods); - const int columnId = owner.getHeader()->getColumnIdAtX (e.x); + const int columnId = owner.getHeader()->getColumnIdAtX (e.x); - if (columnId != 0 && owner.getModel() != 0) - owner.getModel()->cellClicked (row, columnId, e); - } - } + if (columnId != 0 && owner.getModel() != 0) + owner.getModel()->cellClicked (row, columnId, e); + } + } - void mouseDoubleClick (const MouseEvent& e) - { - const int columnId = owner.getHeader()->getColumnIdAtX (e.x); + void mouseDoubleClick (const MouseEvent& e) + { + const int columnId = owner.getHeader()->getColumnIdAtX (e.x); - if (columnId != 0 && owner.getModel() != 0) - owner.getModel()->cellDoubleClicked (row, columnId, e); - } + if (columnId != 0 && owner.getModel() != 0) + owner.getModel()->cellDoubleClicked (row, columnId, e); + } - const String getTooltip() - { - int x, y; - getMouseXYRelative (x, y); + const String getTooltip() + { + int x, y; + getMouseXYRelative (x, y); - const int columnId = owner.getHeader()->getColumnIdAtX (x); + const int columnId = owner.getHeader()->getColumnIdAtX (x); - if (columnId != 0 && owner.getModel() != 0) - return owner.getModel()->getCellTooltip (row, columnId); + if (columnId != 0 && owner.getModel() != 0) + return owner.getModel()->getCellTooltip (row, columnId); - return String::empty; - } + return String::empty; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - TableListBox& owner; - int row; - bool isSelected, isDragging, selectRowOnMouseUp; - BitArray columnsWithComponents; + TableListBox& owner; + int row; + bool isSelected, isDragging, selectRowOnMouseUp; + BitArray columnsWithComponents; - Component* findChildComponentForColumn (const int columnId) const - { - for (int i = getNumChildComponents(); --i >= 0;) - { - Component* const c = getChildComponent (i); + Component* findChildComponentForColumn (const int columnId) const + { + for (int i = getNumChildComponents(); --i >= 0;) + { + Component* const c = getChildComponent (i); - if (c->getComponentPropertyInt (tableColumnPropertyTag, false, 0) == columnId) - return c; - } + if (c->getComponentPropertyInt (tableColumnPropertyTag, false, 0) == columnId) + return c; + } - return 0; - } + return 0; + } - TableListRowComp (const TableListRowComp&); - const TableListRowComp& operator= (const TableListRowComp&); + TableListRowComp (const TableListRowComp&); + const TableListRowComp& operator= (const TableListRowComp&); }; class TableListBoxHeader : public TableHeaderComponent { public: - TableListBoxHeader (TableListBox& owner_) - : owner (owner_) - { - } + TableListBoxHeader (TableListBox& owner_) + : owner (owner_) + { + } - ~TableListBoxHeader() - { - } + ~TableListBoxHeader() + { + } - void addMenuItems (PopupMenu& menu, const int columnIdClicked) - { - if (owner.isAutoSizeMenuOptionShown()) - { - menu.addItem (0xf836743, TRANS("Auto-size this column"), columnIdClicked != 0); - menu.addItem (0xf836744, TRANS("Auto-size all columns"), owner.getHeader()->getNumColumns (true) > 0); - menu.addSeparator(); - } + void addMenuItems (PopupMenu& menu, const int columnIdClicked) + { + if (owner.isAutoSizeMenuOptionShown()) + { + menu.addItem (0xf836743, TRANS("Auto-size this column"), columnIdClicked != 0); + menu.addItem (0xf836744, TRANS("Auto-size all columns"), owner.getHeader()->getNumColumns (true) > 0); + menu.addSeparator(); + } - TableHeaderComponent::addMenuItems (menu, columnIdClicked); - } + TableHeaderComponent::addMenuItems (menu, columnIdClicked); + } - void reactToMenuItem (const int menuReturnId, const int columnIdClicked) - { - if (menuReturnId == 0xf836743) - { - owner.autoSizeColumn (columnIdClicked); - } - else if (menuReturnId == 0xf836744) - { - owner.autoSizeAllColumns(); - } - else - { - TableHeaderComponent::reactToMenuItem (menuReturnId, columnIdClicked); - } - } + void reactToMenuItem (const int menuReturnId, const int columnIdClicked) + { + if (menuReturnId == 0xf836743) + { + owner.autoSizeColumn (columnIdClicked); + } + else if (menuReturnId == 0xf836744) + { + owner.autoSizeAllColumns(); + } + else + { + TableHeaderComponent::reactToMenuItem (menuReturnId, columnIdClicked); + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - TableListBox& owner; + TableListBox& owner; - TableListBoxHeader (const TableListBoxHeader&); - const TableListBoxHeader& operator= (const TableListBoxHeader&); + TableListBoxHeader (const TableListBoxHeader&); + const TableListBoxHeader& operator= (const TableListBoxHeader&); }; TableListBox::TableListBox (const String& name, TableListBoxModel* const model_) - : ListBox (name, 0), - model (model_), - autoSizeOptionsShown (true) + : ListBox (name, 0), + model (model_), + autoSizeOptionsShown (true) { - ListBox::model = this; + ListBox::model = this; - header = new TableListBoxHeader (*this); - header->setSize (100, 28); - header->addListener (this); + header = new TableListBoxHeader (*this); + header->setSize (100, 28); + header->addListener (this); - setHeaderComponent (header); + setHeaderComponent (header); } TableListBox::~TableListBox() { - deleteAllChildren(); + deleteAllChildren(); } void TableListBox::setModel (TableListBoxModel* const newModel) { - if (model != newModel) - { - model = newModel; - updateContent(); - } + if (model != newModel) + { + model = newModel; + updateContent(); + } } int TableListBox::getHeaderHeight() const { - return header->getHeight(); + return header->getHeight(); } void TableListBox::setHeaderHeight (const int newHeight) { - header->setSize (header->getWidth(), newHeight); - resized(); + header->setSize (header->getWidth(), newHeight); + resized(); } void TableListBox::autoSizeColumn (const int columnId) { - const int width = model != 0 ? model->getColumnAutoSizeWidth (columnId) : 0; + const int width = model != 0 ? model->getColumnAutoSizeWidth (columnId) : 0; - if (width > 0) - header->setColumnWidth (columnId, width); + if (width > 0) + header->setColumnWidth (columnId, width); } void TableListBox::autoSizeAllColumns() { - for (int i = 0; i < header->getNumColumns (true); ++i) - autoSizeColumn (header->getColumnIdOfIndex (i, true)); + for (int i = 0; i < header->getNumColumns (true); ++i) + autoSizeColumn (header->getColumnIdOfIndex (i, true)); } void TableListBox::setAutoSizeMenuOptionShown (const bool shouldBeShown) { - autoSizeOptionsShown = shouldBeShown; + autoSizeOptionsShown = shouldBeShown; } bool TableListBox::isAutoSizeMenuOptionShown() const { - return autoSizeOptionsShown; + return autoSizeOptionsShown; } const Rectangle TableListBox::getCellPosition (const int columnId, - const int rowNumber, - const bool relativeToComponentTopLeft) const + const int rowNumber, + const bool relativeToComponentTopLeft) const { - Rectangle headerCell (header->getColumnPosition (header->getIndexOfColumnId (columnId, true))); + Rectangle headerCell (header->getColumnPosition (header->getIndexOfColumnId (columnId, true))); - if (relativeToComponentTopLeft) - headerCell.translate (header->getX(), 0); + if (relativeToComponentTopLeft) + headerCell.translate (header->getX(), 0); - const Rectangle row (getRowPosition (rowNumber, relativeToComponentTopLeft)); + const Rectangle row (getRowPosition (rowNumber, relativeToComponentTopLeft)); - return Rectangle (headerCell.getX(), row.getY(), - headerCell.getWidth(), row.getHeight()); + return Rectangle (headerCell.getX(), row.getY(), + headerCell.getWidth(), row.getHeight()); } void TableListBox::scrollToEnsureColumnIsOnscreen (const int columnId) { - ScrollBar* const scrollbar = getHorizontalScrollBar(); + ScrollBar* const scrollbar = getHorizontalScrollBar(); - if (scrollbar != 0) - { - const Rectangle pos (header->getColumnPosition (header->getIndexOfColumnId (columnId, true))); + if (scrollbar != 0) + { + const Rectangle pos (header->getColumnPosition (header->getIndexOfColumnId (columnId, true))); - double x = scrollbar->getCurrentRangeStart(); - const double w = scrollbar->getCurrentRangeSize(); + double x = scrollbar->getCurrentRangeStart(); + const double w = scrollbar->getCurrentRangeSize(); - if (pos.getX() < x) - x = pos.getX(); - else if (pos.getRight() > x + w) - x += jmax (0.0, pos.getRight() - (x + w)); + if (pos.getX() < x) + x = pos.getX(); + else if (pos.getRight() > x + w) + x += jmax (0.0, pos.getRight() - (x + w)); - scrollbar->setCurrentRangeStart (x); - } + scrollbar->setCurrentRangeStart (x); + } } int TableListBox::getNumRows() { - return model != 0 ? model->getNumRows() : 0; + return model != 0 ? model->getNumRows() : 0; } void TableListBox::paintListBoxItem (int, Graphics&, int, int, bool) @@ -51535,90 +51239,90 @@ void TableListBox::paintListBoxItem (int, Graphics&, int, int, bool) Component* TableListBox::refreshComponentForRow (int rowNumber, bool isRowSelected_, Component* existingComponentToUpdate) { - if (existingComponentToUpdate == 0) - existingComponentToUpdate = new TableListRowComp (*this); + if (existingComponentToUpdate == 0) + existingComponentToUpdate = new TableListRowComp (*this); - ((TableListRowComp*) existingComponentToUpdate)->update (rowNumber, isRowSelected_); + ((TableListRowComp*) existingComponentToUpdate)->update (rowNumber, isRowSelected_); - return existingComponentToUpdate; + return existingComponentToUpdate; } void TableListBox::selectedRowsChanged (int row) { - if (model != 0) - model->selectedRowsChanged (row); + if (model != 0) + model->selectedRowsChanged (row); } void TableListBox::deleteKeyPressed (int row) { - if (model != 0) - model->deleteKeyPressed (row); + if (model != 0) + model->deleteKeyPressed (row); } void TableListBox::returnKeyPressed (int row) { - if (model != 0) - model->returnKeyPressed (row); + if (model != 0) + model->returnKeyPressed (row); } void TableListBox::backgroundClicked() { - if (model != 0) - model->backgroundClicked(); + if (model != 0) + model->backgroundClicked(); } void TableListBox::listWasScrolled() { - if (model != 0) - model->listWasScrolled(); + if (model != 0) + model->listWasScrolled(); } void TableListBox::tableColumnsChanged (TableHeaderComponent*) { - setMinimumContentWidth (header->getTotalWidth()); - repaint(); - updateColumnComponents(); + setMinimumContentWidth (header->getTotalWidth()); + repaint(); + updateColumnComponents(); } void TableListBox::tableColumnsResized (TableHeaderComponent*) { - setMinimumContentWidth (header->getTotalWidth()); - repaint(); - updateColumnComponents(); + setMinimumContentWidth (header->getTotalWidth()); + repaint(); + updateColumnComponents(); } void TableListBox::tableSortOrderChanged (TableHeaderComponent*) { - if (model != 0) - model->sortOrderChanged (header->getSortColumnId(), - header->isSortedForwards()); + if (model != 0) + model->sortOrderChanged (header->getSortColumnId(), + header->isSortedForwards()); } void TableListBox::tableColumnDraggingChanged (TableHeaderComponent*, int columnIdNowBeingDragged_) { - columnIdNowBeingDragged = columnIdNowBeingDragged_; - repaint(); + columnIdNowBeingDragged = columnIdNowBeingDragged_; + repaint(); } void TableListBox::resized() { - ListBox::resized(); + ListBox::resized(); - header->resizeAllColumnsToFit (getVisibleContentWidth()); - setMinimumContentWidth (header->getTotalWidth()); + header->resizeAllColumnsToFit (getVisibleContentWidth()); + setMinimumContentWidth (header->getTotalWidth()); } void TableListBox::updateColumnComponents() const { - const int firstRow = getRowContainingPosition (0, 0); + const int firstRow = getRowContainingPosition (0, 0); - for (int i = firstRow + getNumRowsOnScreen() + 2; --i >= firstRow;) - { - TableListRowComp* const rowComp = dynamic_cast (getComponentForRowNumber (i)); + for (int i = firstRow + getNumRowsOnScreen() + 2; --i >= firstRow;) + { + TableListRowComp* const rowComp = dynamic_cast (getComponentForRowNumber (i)); - if (rowComp != 0) - rowComp->resized(); - } + if (rowComp != 0) + rowComp->resized(); + } } void TableListBoxModel::cellClicked (int, int, const MouseEvent&) @@ -51639,7 +51343,7 @@ void TableListBoxModel::sortOrderChanged (int, const bool) int TableListBoxModel::getColumnAutoSizeWidth (int) { - return 0; + return 0; } void TableListBoxModel::selectedRowsChanged (int) @@ -51660,19 +51364,19 @@ void TableListBoxModel::listWasScrolled() const String TableListBoxModel::getCellTooltip (int /*rowNumber*/, int /*columnId*/) { - return String::empty; + return String::empty; } const String TableListBoxModel::getDragSourceDescription (const SparseSet&) { - return String::empty; + return String::empty; } Component* TableListBoxModel::refreshComponentForCell (int, int, bool, Component* existingComponentToUpdate) { - (void) existingComponentToUpdate; - jassert (existingComponentToUpdate == 0); // indicates a failure in the code the recycles the components - return 0; + (void) existingComponentToUpdate; + jassert (existingComponentToUpdate == 0); // indicates a failure in the code the recycles the components + return 0; } END_JUCE_NAMESPACE @@ -51686,31 +51390,31 @@ BEGIN_JUCE_NAMESPACE struct TextAtom { - String atomText; - float width; - uint16 numChars; + String atomText; + float width; + uint16 numChars; - bool isWhitespace() const { return CharacterFunctions::isWhitespace (atomText[0]); } - bool isNewLine() const { return atomText[0] == T('\r') || atomText[0] == T('\n'); } + bool isWhitespace() const { return CharacterFunctions::isWhitespace (atomText[0]); } + bool isNewLine() const { return atomText[0] == T('\r') || atomText[0] == T('\n'); } - const String getText (const tchar passwordCharacter) const - { - if (passwordCharacter == 0) - return atomText; - else - return String::repeatedString (String::charToString (passwordCharacter), - atomText.length()); - } + const String getText (const tchar passwordCharacter) const + { + if (passwordCharacter == 0) + return atomText; + else + return String::repeatedString (String::charToString (passwordCharacter), + atomText.length()); + } - const String getTrimmedText (const tchar passwordCharacter) const - { - if (passwordCharacter == 0) - return atomText.substring (0, numChars); - else if (isNewLine()) - return String::empty; - else - return String::repeatedString (String::charToString (passwordCharacter), numChars); - } + const String getTrimmedText (const tchar passwordCharacter) const + { + if (passwordCharacter == 0) + return atomText.substring (0, numChars); + else if (isNewLine()) + return String::empty; + else + return String::repeatedString (String::charToString (passwordCharacter), numChars); + } }; // a run of text with a single font and colour @@ -51718,867 +51422,869 @@ class UniformTextSection { public: - UniformTextSection (const String& text, - const Font& font_, - const Colour& colour_, - const tchar passwordCharacter) - : font (font_), - colour (colour_), - atoms (64) - { - initialiseAtoms (text, passwordCharacter); - } + UniformTextSection (const String& text, + const Font& font_, + const Colour& colour_, + const tchar passwordCharacter) + : font (font_), + colour (colour_) + { + initialiseAtoms (text, passwordCharacter); + } - UniformTextSection (const UniformTextSection& other) - : font (other.font), - colour (other.colour), - atoms (64) - { - for (int i = 0; i < other.atoms.size(); ++i) - atoms.add (new TextAtom (*(const TextAtom*) other.atoms.getUnchecked(i))); - } + UniformTextSection (const UniformTextSection& other) + : font (other.font), + colour (other.colour) + { + atoms.ensureStorageAllocated (other.atoms.size()); - ~UniformTextSection() - { - // (no need to delete the atoms, as they're explicitly deleted by the caller) - } + for (int i = 0; i < other.atoms.size(); ++i) + atoms.add (new TextAtom (*(const TextAtom*) other.atoms.getUnchecked(i))); + } - void clear() - { - for (int i = atoms.size(); --i >= 0;) - delete getAtom(i); + ~UniformTextSection() + { + // (no need to delete the atoms, as they're explicitly deleted by the caller) + } - atoms.clear(); - } + void clear() + { + for (int i = atoms.size(); --i >= 0;) + delete getAtom(i); - int getNumAtoms() const - { - return atoms.size(); - } + atoms.clear(); + } - TextAtom* getAtom (const int index) const - { - return (TextAtom*) atoms.getUnchecked (index); - } + int getNumAtoms() const + { + return atoms.size(); + } - void append (const UniformTextSection& other, const tchar passwordCharacter) - { - if (other.atoms.size() > 0) - { - TextAtom* const lastAtom = (TextAtom*) atoms.getLast(); - int i = 0; + TextAtom* getAtom (const int index) const + { + return (TextAtom*) atoms.getUnchecked (index); + } - if (lastAtom != 0) - { - if (! CharacterFunctions::isWhitespace (lastAtom->atomText.getLastCharacter())) - { - TextAtom* const first = other.getAtom(0); + void append (const UniformTextSection& other, const tchar passwordCharacter) + { + if (other.atoms.size() > 0) + { + TextAtom* const lastAtom = (TextAtom*) atoms.getLast(); + int i = 0; - if (! CharacterFunctions::isWhitespace (first->atomText[0])) - { - lastAtom->atomText += first->atomText; - lastAtom->numChars = (uint16) (lastAtom->numChars + first->numChars); - lastAtom->width = font.getStringWidthFloat (lastAtom->getText (passwordCharacter)); - delete first; - ++i; - } - } - } + if (lastAtom != 0) + { + if (! CharacterFunctions::isWhitespace (lastAtom->atomText.getLastCharacter())) + { + TextAtom* const first = other.getAtom(0); - while (i < other.atoms.size()) - { - atoms.add (other.getAtom(i)); - ++i; - } - } - } + if (! CharacterFunctions::isWhitespace (first->atomText[0])) + { + lastAtom->atomText += first->atomText; + lastAtom->numChars = (uint16) (lastAtom->numChars + first->numChars); + lastAtom->width = font.getStringWidthFloat (lastAtom->getText (passwordCharacter)); + delete first; + ++i; + } + } + } - UniformTextSection* split (const int indexToBreakAt, - const tchar passwordCharacter) - { - UniformTextSection* const section2 = new UniformTextSection (String::empty, - font, colour, - passwordCharacter); - int index = 0; + atoms.ensureStorageAllocated (atoms.size() + other.atoms.size() - i); - for (int i = 0; i < atoms.size(); ++i) - { - TextAtom* const atom = getAtom(i); + while (i < other.atoms.size()) + { + atoms.add (other.getAtom(i)); + ++i; + } + } + } - const int nextIndex = index + atom->numChars; + UniformTextSection* split (const int indexToBreakAt, + const tchar passwordCharacter) + { + UniformTextSection* const section2 = new UniformTextSection (String::empty, + font, colour, + passwordCharacter); + int index = 0; - if (index == indexToBreakAt) - { - int j; - for (j = i; j < atoms.size(); ++j) - section2->atoms.add (getAtom (j)); + for (int i = 0; i < atoms.size(); ++i) + { + TextAtom* const atom = getAtom(i); - for (j = atoms.size(); --j >= i;) - atoms.remove (j); + const int nextIndex = index + atom->numChars; - break; - } - else if (indexToBreakAt >= index && indexToBreakAt < nextIndex) - { - TextAtom* const secondAtom = new TextAtom(); + if (index == indexToBreakAt) + { + int j; + for (j = i; j < atoms.size(); ++j) + section2->atoms.add (getAtom (j)); - secondAtom->atomText = atom->atomText.substring (indexToBreakAt - index); - secondAtom->width = font.getStringWidthFloat (secondAtom->getText (passwordCharacter)); - secondAtom->numChars = (uint16) secondAtom->atomText.length(); + for (j = atoms.size(); --j >= i;) + atoms.remove (j); - section2->atoms.add (secondAtom); + break; + } + else if (indexToBreakAt >= index && indexToBreakAt < nextIndex) + { + TextAtom* const secondAtom = new TextAtom(); - atom->atomText = atom->atomText.substring (0, indexToBreakAt - index); - atom->width = font.getStringWidthFloat (atom->getText (passwordCharacter)); - atom->numChars = (uint16) (indexToBreakAt - index); + secondAtom->atomText = atom->atomText.substring (indexToBreakAt - index); + secondAtom->width = font.getStringWidthFloat (secondAtom->getText (passwordCharacter)); + secondAtom->numChars = (uint16) secondAtom->atomText.length(); - int j; - for (j = i + 1; j < atoms.size(); ++j) - section2->atoms.add (getAtom (j)); + section2->atoms.add (secondAtom); - for (j = atoms.size(); --j > i;) - atoms.remove (j); + atom->atomText = atom->atomText.substring (0, indexToBreakAt - index); + atom->width = font.getStringWidthFloat (atom->getText (passwordCharacter)); + atom->numChars = (uint16) (indexToBreakAt - index); - break; - } + int j; + for (j = i + 1; j < atoms.size(); ++j) + section2->atoms.add (getAtom (j)); - index = nextIndex; - } + for (j = atoms.size(); --j > i;) + atoms.remove (j); - return section2; - } + break; + } - void appendAllText (String::Concatenator& concatenator) const - { - for (int i = 0; i < atoms.size(); ++i) - concatenator.append (getAtom(i)->atomText); - } + index = nextIndex; + } - void appendSubstring (String::Concatenator& concatenator, - const int startCharacter, - const int endCharacter) const - { - int index = 0; - for (int i = 0; i < atoms.size(); ++i) - { - const TextAtom* const atom = getAtom (i); - const int nextIndex = index + atom->numChars; + return section2; + } - if (startCharacter < nextIndex) - { - if (endCharacter <= index) - break; + void appendAllText (String::Concatenator& concatenator) const + { + for (int i = 0; i < atoms.size(); ++i) + concatenator.append (getAtom(i)->atomText); + } - const int start = jmax (0, startCharacter - index); - const int end = jmin (endCharacter - index, atom->numChars); + void appendSubstring (String::Concatenator& concatenator, + const int startCharacter, + const int endCharacter) const + { + int index = 0; + for (int i = 0; i < atoms.size(); ++i) + { + const TextAtom* const atom = getAtom (i); + const int nextIndex = index + atom->numChars; - if (start < end) - concatenator.append (atom->atomText.substring (start, end)); - } + if (startCharacter < nextIndex) + { + if (endCharacter <= index) + break; - index = nextIndex; - } - } + const int start = jmax (0, startCharacter - index); + const int end = jmin (endCharacter - index, (int) atom->numChars); - int getTotalLength() const - { - int total = 0; + if (start < end) + concatenator.append (atom->atomText.substring (start, end)); + } - for (int i = atoms.size(); --i >= 0;) - total += getAtom(i)->numChars; + index = nextIndex; + } + } - return total; - } + int getTotalLength() const + { + int total = 0; - void setFont (const Font& newFont, - const tchar passwordCharacter) - { - if (font != newFont) - { - font = newFont; + for (int i = atoms.size(); --i >= 0;) + total += getAtom(i)->numChars; - for (int i = atoms.size(); --i >= 0;) - { - TextAtom* const atom = (TextAtom*) atoms.getUnchecked(i); - atom->width = newFont.getStringWidthFloat (atom->getText (passwordCharacter)); - } - } - } + return total; + } - juce_UseDebuggingNewOperator + void setFont (const Font& newFont, + const tchar passwordCharacter) + { + if (font != newFont) + { + font = newFont; - Font font; - Colour colour; + for (int i = atoms.size(); --i >= 0;) + { + TextAtom* const atom = (TextAtom*) atoms.getUnchecked(i); + atom->width = newFont.getStringWidthFloat (atom->getText (passwordCharacter)); + } + } + } + + juce_UseDebuggingNewOperator + + Font font; + Colour colour; private: - VoidArray atoms; + VoidArray atoms; - void initialiseAtoms (const String& textToParse, - const tchar passwordCharacter) - { - int i = 0; - const int len = textToParse.length(); - const tchar* const text = (const tchar*) textToParse; + void initialiseAtoms (const String& textToParse, + const tchar passwordCharacter) + { + int i = 0; + const int len = textToParse.length(); + const tchar* const text = (const tchar*) textToParse; - while (i < len) - { - int start = i; + while (i < len) + { + int start = i; - // create a whitespace atom unless it starts with non-ws - if (CharacterFunctions::isWhitespace (text[i]) - && text[i] != T('\r') - && text[i] != T('\n')) - { - while (i < len - && CharacterFunctions::isWhitespace (text[i]) - && text[i] != T('\r') - && text[i] != T('\n')) - { - ++i; - } - } - else - { - if (text[i] == T('\r')) - { - ++i; + // create a whitespace atom unless it starts with non-ws + if (CharacterFunctions::isWhitespace (text[i]) + && text[i] != T('\r') + && text[i] != T('\n')) + { + while (i < len + && CharacterFunctions::isWhitespace (text[i]) + && text[i] != T('\r') + && text[i] != T('\n')) + { + ++i; + } + } + else + { + if (text[i] == T('\r')) + { + ++i; - if ((i < len) && (text[i] == T('\n'))) - { - ++start; - ++i; - } - } - else if (text[i] == T('\n')) - { - ++i; - } - else - { - while ((i < len) && ! CharacterFunctions::isWhitespace (text[i])) - ++i; - } - } + if ((i < len) && (text[i] == T('\n'))) + { + ++start; + ++i; + } + } + else if (text[i] == T('\n')) + { + ++i; + } + else + { + while ((i < len) && ! CharacterFunctions::isWhitespace (text[i])) + ++i; + } + } - TextAtom* const atom = new TextAtom(); - atom->atomText = String (text + start, i - start); + TextAtom* const atom = new TextAtom(); + atom->atomText = String (text + start, i - start); - atom->width = font.getStringWidthFloat (atom->getText (passwordCharacter)); - atom->numChars = (uint16) (i - start); + atom->width = font.getStringWidthFloat (atom->getText (passwordCharacter)); + atom->numChars = (uint16) (i - start); - atoms.add (atom); - } - } + atoms.add (atom); + } + } - const UniformTextSection& operator= (const UniformTextSection& other); + const UniformTextSection& operator= (const UniformTextSection& other); }; class TextEditorIterator { public: - TextEditorIterator (const VoidArray& sections_, - const float wordWrapWidth_, - const tchar passwordCharacter_) - : indexInText (0), - lineY (0), - lineHeight (0), - maxDescent (0), - atomX (0), - atomRight (0), - atom (0), - currentSection (0), - sections (sections_), - sectionIndex (0), - atomIndex (0), - wordWrapWidth (wordWrapWidth_), - passwordCharacter (passwordCharacter_) - { - jassert (wordWrapWidth_ > 0); - - if (sections.size() > 0) - { - currentSection = (const UniformTextSection*) sections.getUnchecked (sectionIndex); - - if (currentSection != 0) - beginNewLine(); - } - } - - TextEditorIterator (const TextEditorIterator& other) - : indexInText (other.indexInText), - lineY (other.lineY), - lineHeight (other.lineHeight), - maxDescent (other.maxDescent), - atomX (other.atomX), - atomRight (other.atomRight), - atom (other.atom), - currentSection (other.currentSection), - sections (other.sections), - sectionIndex (other.sectionIndex), - atomIndex (other.atomIndex), - wordWrapWidth (other.wordWrapWidth), - passwordCharacter (other.passwordCharacter), - tempAtom (other.tempAtom) - { - } - - ~TextEditorIterator() - { - } - - bool next() - { - if (atom == &tempAtom) - { - const int numRemaining = tempAtom.atomText.length() - tempAtom.numChars; - - if (numRemaining > 0) - { - tempAtom.atomText = tempAtom.atomText.substring (tempAtom.numChars); - - atomX = 0; - - if (tempAtom.numChars > 0) - lineY += lineHeight; - - indexInText += tempAtom.numChars; - - GlyphArrangement g; - g.addLineOfText (currentSection->font, atom->getText (passwordCharacter), 0.0f, 0.0f); - - int split; - for (split = 0; split < g.getNumGlyphs(); ++split) - if (shouldWrap (g.getGlyph (split).getRight())) - break; - - if (split > 0 && split <= numRemaining) - { - tempAtom.numChars = (uint16) split; - tempAtom.width = g.getGlyph (split - 1).getRight(); - atomRight = atomX + tempAtom.width; - return true; - } - } - } - - bool forceNewLine = false; - - if (sectionIndex >= sections.size()) - { - moveToEndOfLastAtom(); - return false; - } - else if (atomIndex >= currentSection->getNumAtoms() - 1) - { - if (atomIndex >= currentSection->getNumAtoms()) - { - if (++sectionIndex >= sections.size()) - { - moveToEndOfLastAtom(); - return false; - } - - atomIndex = 0; - currentSection = (const UniformTextSection*) sections.getUnchecked (sectionIndex); - } - else - { - const TextAtom* const lastAtom = currentSection->getAtom (atomIndex); - - if (! lastAtom->isWhitespace()) - { - // handle the case where the last atom in a section is actually part of the same - // word as the first atom of the next section... - float right = atomRight + lastAtom->width; - float lineHeight2 = lineHeight; - float maxDescent2 = maxDescent; - - for (int section = sectionIndex + 1; section < sections.size(); ++section) - { - const UniformTextSection* const s = (const UniformTextSection*) sections.getUnchecked (section); - - if (s->getNumAtoms() == 0) - break; - - const TextAtom* const nextAtom = s->getAtom (0); - - if (nextAtom->isWhitespace()) - break; - - right += nextAtom->width; - - lineHeight2 = jmax (lineHeight2, s->font.getHeight()); - maxDescent2 = jmax (maxDescent2, s->font.getDescent()); - - if (shouldWrap (right)) - { - lineHeight = lineHeight2; - maxDescent = maxDescent2; - - forceNewLine = true; - break; - } - - if (s->getNumAtoms() > 1) - break; - } - } - } - } - - if (atom != 0) - { - atomX = atomRight; - indexInText += atom->numChars; - - if (atom->isNewLine()) - beginNewLine(); - } - - atom = currentSection->getAtom (atomIndex); - atomRight = atomX + atom->width; - ++atomIndex; - - if (shouldWrap (atomRight) || forceNewLine) - { - if (atom->isWhitespace()) - { - // leave whitespace at the end of a line, but truncate it to avoid scrolling - atomRight = jmin (atomRight, wordWrapWidth); - } - else - { - atomRight = atom->width; - - if (shouldWrap (atomRight)) // atom too big to fit on a line, so break it up.. - { - tempAtom = *atom; - tempAtom.width = 0; - tempAtom.numChars = 0; - atom = &tempAtom; - - if (atomX > 0) - beginNewLine(); - - return next(); - } - - beginNewLine(); - return true; - } - } - - return true; - } - - void beginNewLine() - { - atomX = 0; - lineY += lineHeight; - - int tempSectionIndex = sectionIndex; - int tempAtomIndex = atomIndex; - const UniformTextSection* section = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); - - lineHeight = section->font.getHeight(); - maxDescent = section->font.getDescent(); - - float x = (atom != 0) ? atom->width : 0; - - while (! shouldWrap (x)) - { - if (tempSectionIndex >= sections.size()) - break; - - bool checkSize = false; - - if (tempAtomIndex >= section->getNumAtoms()) - { - if (++tempSectionIndex >= sections.size()) - break; - - tempAtomIndex = 0; - section = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); - checkSize = true; - } - - const TextAtom* const nextAtom = section->getAtom (tempAtomIndex); - - if (nextAtom == 0) - break; - - x += nextAtom->width; - - if (shouldWrap (x) || nextAtom->isNewLine()) - break; - - if (checkSize) - { - lineHeight = jmax (lineHeight, section->font.getHeight()); - maxDescent = jmax (maxDescent, section->font.getDescent()); - } - - ++tempAtomIndex; - } - } - - void draw (Graphics& g, const UniformTextSection*& lastSection) const - { - if (passwordCharacter != 0 || ! atom->isWhitespace()) - { - if (lastSection != currentSection) - { - lastSection = currentSection; - g.setColour (currentSection->colour); - g.setFont (currentSection->font); - } - - jassert (atom->getTrimmedText (passwordCharacter).isNotEmpty()); - - GlyphArrangement ga; - ga.addLineOfText (currentSection->font, - atom->getTrimmedText (passwordCharacter), - atomX, - (float) roundFloatToInt (lineY + lineHeight - maxDescent)); - ga.draw (g); - } - } - - void drawSelection (Graphics& g, - const int selectionStart, - const int selectionEnd) const - { - const int startX = roundFloatToInt (indexToX (selectionStart)); - const int endX = roundFloatToInt (indexToX (selectionEnd)); - - const int y = roundFloatToInt (lineY); - const int nextY = roundFloatToInt (lineY + lineHeight); - - g.fillRect (startX, y, endX - startX, nextY - y); - } - - void drawSelectedText (Graphics& g, - const int selectionStart, - const int selectionEnd, - const Colour& selectedTextColour) const - { - if (passwordCharacter != 0 || ! atom->isWhitespace()) - { - GlyphArrangement ga; - ga.addLineOfText (currentSection->font, - atom->getTrimmedText (passwordCharacter), - atomX, - (float) roundFloatToInt (lineY + lineHeight - maxDescent)); - - if (selectionEnd < indexInText + atom->numChars) - { - GlyphArrangement ga2 (ga); - ga2.removeRangeOfGlyphs (0, selectionEnd - indexInText); - ga.removeRangeOfGlyphs (selectionEnd - indexInText, -1); - - g.setColour (currentSection->colour); - ga2.draw (g); - } - - if (selectionStart > indexInText) - { - GlyphArrangement ga2 (ga); - ga2.removeRangeOfGlyphs (selectionStart - indexInText, -1); - ga.removeRangeOfGlyphs (0, selectionStart - indexInText); - - g.setColour (currentSection->colour); - ga2.draw (g); - } - - g.setColour (selectedTextColour); - ga.draw (g); - } - } - - float indexToX (const int indexToFind) const - { - if (indexToFind <= indexInText) - return atomX; - - if (indexToFind >= indexInText + atom->numChars) - return atomRight; - - GlyphArrangement g; - g.addLineOfText (currentSection->font, - atom->getText (passwordCharacter), - atomX, 0.0f); - - if (indexToFind - indexInText >= g.getNumGlyphs()) - return atomRight; - - return jmin (atomRight, g.getGlyph (indexToFind - indexInText).getLeft()); - } - - int xToIndex (const float xToFind) const - { - if (xToFind <= atomX || atom->isNewLine()) - return indexInText; - - if (xToFind >= atomRight) - return indexInText + atom->numChars; - - GlyphArrangement g; - g.addLineOfText (currentSection->font, - atom->getText (passwordCharacter), - atomX, 0.0f); - - int j; - for (j = 0; j < g.getNumGlyphs(); ++j) - if ((g.getGlyph(j).getLeft() + g.getGlyph(j).getRight()) / 2 > xToFind) - break; - - return indexInText + j; - } - - bool getCharPosition (const int index, float& cx, float& cy, float& lineHeight_) - { - while (next()) - { - if (indexInText + atom->numChars > index) - { - cx = indexToX (index); - cy = lineY; - lineHeight_ = lineHeight; - return true; - } - } - - cx = atomX; - cy = lineY; - lineHeight_ = lineHeight; - return false; - } - - juce_UseDebuggingNewOperator - - int indexInText; - float lineY, lineHeight, maxDescent; - float atomX, atomRight; - const TextAtom* atom; - const UniformTextSection* currentSection; + TextEditorIterator (const VoidArray& sections_, + const float wordWrapWidth_, + const tchar passwordCharacter_) + : indexInText (0), + lineY (0), + lineHeight (0), + maxDescent (0), + atomX (0), + atomRight (0), + atom (0), + currentSection (0), + sections (sections_), + sectionIndex (0), + atomIndex (0), + wordWrapWidth (wordWrapWidth_), + passwordCharacter (passwordCharacter_) + { + jassert (wordWrapWidth_ > 0); + + if (sections.size() > 0) + { + currentSection = (const UniformTextSection*) sections.getUnchecked (sectionIndex); + + if (currentSection != 0) + beginNewLine(); + } + } + + TextEditorIterator (const TextEditorIterator& other) + : indexInText (other.indexInText), + lineY (other.lineY), + lineHeight (other.lineHeight), + maxDescent (other.maxDescent), + atomX (other.atomX), + atomRight (other.atomRight), + atom (other.atom), + currentSection (other.currentSection), + sections (other.sections), + sectionIndex (other.sectionIndex), + atomIndex (other.atomIndex), + wordWrapWidth (other.wordWrapWidth), + passwordCharacter (other.passwordCharacter), + tempAtom (other.tempAtom) + { + } + + ~TextEditorIterator() + { + } + + bool next() + { + if (atom == &tempAtom) + { + const int numRemaining = tempAtom.atomText.length() - tempAtom.numChars; + + if (numRemaining > 0) + { + tempAtom.atomText = tempAtom.atomText.substring (tempAtom.numChars); + + atomX = 0; + + if (tempAtom.numChars > 0) + lineY += lineHeight; + + indexInText += tempAtom.numChars; + + GlyphArrangement g; + g.addLineOfText (currentSection->font, atom->getText (passwordCharacter), 0.0f, 0.0f); + + int split; + for (split = 0; split < g.getNumGlyphs(); ++split) + if (shouldWrap (g.getGlyph (split).getRight())) + break; + + if (split > 0 && split <= numRemaining) + { + tempAtom.numChars = (uint16) split; + tempAtom.width = g.getGlyph (split - 1).getRight(); + atomRight = atomX + tempAtom.width; + return true; + } + } + } + + bool forceNewLine = false; + + if (sectionIndex >= sections.size()) + { + moveToEndOfLastAtom(); + return false; + } + else if (atomIndex >= currentSection->getNumAtoms() - 1) + { + if (atomIndex >= currentSection->getNumAtoms()) + { + if (++sectionIndex >= sections.size()) + { + moveToEndOfLastAtom(); + return false; + } + + atomIndex = 0; + currentSection = (const UniformTextSection*) sections.getUnchecked (sectionIndex); + } + else + { + const TextAtom* const lastAtom = currentSection->getAtom (atomIndex); + + if (! lastAtom->isWhitespace()) + { + // handle the case where the last atom in a section is actually part of the same + // word as the first atom of the next section... + float right = atomRight + lastAtom->width; + float lineHeight2 = lineHeight; + float maxDescent2 = maxDescent; + + for (int section = sectionIndex + 1; section < sections.size(); ++section) + { + const UniformTextSection* const s = (const UniformTextSection*) sections.getUnchecked (section); + + if (s->getNumAtoms() == 0) + break; + + const TextAtom* const nextAtom = s->getAtom (0); + + if (nextAtom->isWhitespace()) + break; + + right += nextAtom->width; + + lineHeight2 = jmax (lineHeight2, s->font.getHeight()); + maxDescent2 = jmax (maxDescent2, s->font.getDescent()); + + if (shouldWrap (right)) + { + lineHeight = lineHeight2; + maxDescent = maxDescent2; + + forceNewLine = true; + break; + } + + if (s->getNumAtoms() > 1) + break; + } + } + } + } + + if (atom != 0) + { + atomX = atomRight; + indexInText += atom->numChars; + + if (atom->isNewLine()) + beginNewLine(); + } + + atom = currentSection->getAtom (atomIndex); + atomRight = atomX + atom->width; + ++atomIndex; + + if (shouldWrap (atomRight) || forceNewLine) + { + if (atom->isWhitespace()) + { + // leave whitespace at the end of a line, but truncate it to avoid scrolling + atomRight = jmin (atomRight, wordWrapWidth); + } + else + { + atomRight = atom->width; + + if (shouldWrap (atomRight)) // atom too big to fit on a line, so break it up.. + { + tempAtom = *atom; + tempAtom.width = 0; + tempAtom.numChars = 0; + atom = &tempAtom; + + if (atomX > 0) + beginNewLine(); + + return next(); + } + + beginNewLine(); + return true; + } + } + + return true; + } + + void beginNewLine() + { + atomX = 0; + lineY += lineHeight; + + int tempSectionIndex = sectionIndex; + int tempAtomIndex = atomIndex; + const UniformTextSection* section = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); + + lineHeight = section->font.getHeight(); + maxDescent = section->font.getDescent(); + + float x = (atom != 0) ? atom->width : 0; + + while (! shouldWrap (x)) + { + if (tempSectionIndex >= sections.size()) + break; + + bool checkSize = false; + + if (tempAtomIndex >= section->getNumAtoms()) + { + if (++tempSectionIndex >= sections.size()) + break; + + tempAtomIndex = 0; + section = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); + checkSize = true; + } + + const TextAtom* const nextAtom = section->getAtom (tempAtomIndex); + + if (nextAtom == 0) + break; + + x += nextAtom->width; + + if (shouldWrap (x) || nextAtom->isNewLine()) + break; + + if (checkSize) + { + lineHeight = jmax (lineHeight, section->font.getHeight()); + maxDescent = jmax (maxDescent, section->font.getDescent()); + } + + ++tempAtomIndex; + } + } + + void draw (Graphics& g, const UniformTextSection*& lastSection) const + { + if (passwordCharacter != 0 || ! atom->isWhitespace()) + { + if (lastSection != currentSection) + { + lastSection = currentSection; + g.setColour (currentSection->colour); + g.setFont (currentSection->font); + } + + jassert (atom->getTrimmedText (passwordCharacter).isNotEmpty()); + + GlyphArrangement ga; + ga.addLineOfText (currentSection->font, + atom->getTrimmedText (passwordCharacter), + atomX, + (float) roundToInt (lineY + lineHeight - maxDescent)); + ga.draw (g); + } + } + + void drawSelection (Graphics& g, + const int selectionStart, + const int selectionEnd) const + { + const int startX = roundToInt (indexToX (selectionStart)); + const int endX = roundToInt (indexToX (selectionEnd)); + + const int y = roundToInt (lineY); + const int nextY = roundToInt (lineY + lineHeight); + + g.fillRect (startX, y, endX - startX, nextY - y); + } + + void drawSelectedText (Graphics& g, + const int selectionStart, + const int selectionEnd, + const Colour& selectedTextColour) const + { + if (passwordCharacter != 0 || ! atom->isWhitespace()) + { + GlyphArrangement ga; + ga.addLineOfText (currentSection->font, + atom->getTrimmedText (passwordCharacter), + atomX, + (float) roundToInt (lineY + lineHeight - maxDescent)); + + if (selectionEnd < indexInText + atom->numChars) + { + GlyphArrangement ga2 (ga); + ga2.removeRangeOfGlyphs (0, selectionEnd - indexInText); + ga.removeRangeOfGlyphs (selectionEnd - indexInText, -1); + + g.setColour (currentSection->colour); + ga2.draw (g); + } + + if (selectionStart > indexInText) + { + GlyphArrangement ga2 (ga); + ga2.removeRangeOfGlyphs (selectionStart - indexInText, -1); + ga.removeRangeOfGlyphs (0, selectionStart - indexInText); + + g.setColour (currentSection->colour); + ga2.draw (g); + } + + g.setColour (selectedTextColour); + ga.draw (g); + } + } + + float indexToX (const int indexToFind) const + { + if (indexToFind <= indexInText) + return atomX; + + if (indexToFind >= indexInText + atom->numChars) + return atomRight; + + GlyphArrangement g; + g.addLineOfText (currentSection->font, + atom->getText (passwordCharacter), + atomX, 0.0f); + + if (indexToFind - indexInText >= g.getNumGlyphs()) + return atomRight; + + return jmin (atomRight, g.getGlyph (indexToFind - indexInText).getLeft()); + } + + int xToIndex (const float xToFind) const + { + if (xToFind <= atomX || atom->isNewLine()) + return indexInText; + + if (xToFind >= atomRight) + return indexInText + atom->numChars; + + GlyphArrangement g; + g.addLineOfText (currentSection->font, + atom->getText (passwordCharacter), + atomX, 0.0f); + + int j; + for (j = 0; j < g.getNumGlyphs(); ++j) + if ((g.getGlyph(j).getLeft() + g.getGlyph(j).getRight()) / 2 > xToFind) + break; + + return indexInText + j; + } + + bool getCharPosition (const int index, float& cx, float& cy, float& lineHeight_) + { + while (next()) + { + if (indexInText + atom->numChars > index) + { + cx = indexToX (index); + cy = lineY; + lineHeight_ = lineHeight; + return true; + } + } + + cx = atomX; + cy = lineY; + lineHeight_ = lineHeight; + return false; + } + + juce_UseDebuggingNewOperator + + int indexInText; + float lineY, lineHeight, maxDescent; + float atomX, atomRight; + const TextAtom* atom; + const UniformTextSection* currentSection; private: - const VoidArray& sections; - int sectionIndex, atomIndex; - const float wordWrapWidth; - const tchar passwordCharacter; - TextAtom tempAtom; + const VoidArray& sections; + int sectionIndex, atomIndex; + const float wordWrapWidth; + const tchar passwordCharacter; + TextAtom tempAtom; - const TextEditorIterator& operator= (const TextEditorIterator&); + const TextEditorIterator& operator= (const TextEditorIterator&); - void moveToEndOfLastAtom() - { - if (atom != 0) - { - atomX = atomRight; + void moveToEndOfLastAtom() + { + if (atom != 0) + { + atomX = atomRight; - if (atom->isNewLine()) - { - atomX = 0.0f; - lineY += lineHeight; - } - } - } + if (atom->isNewLine()) + { + atomX = 0.0f; + lineY += lineHeight; + } + } + } - bool shouldWrap (const float x) const - { - return (x - 0.0001f) >= wordWrapWidth; - } + bool shouldWrap (const float x) const + { + return (x - 0.0001f) >= wordWrapWidth; + } }; class TextEditorInsertAction : public UndoableAction { - TextEditor& owner; - const String text; - const int insertIndex, oldCaretPos, newCaretPos; - const Font font; - const Colour colour; + TextEditor& owner; + const String text; + const int insertIndex, oldCaretPos, newCaretPos; + const Font font; + const Colour colour; - TextEditorInsertAction (const TextEditorInsertAction&); - const TextEditorInsertAction& operator= (const TextEditorInsertAction&); + TextEditorInsertAction (const TextEditorInsertAction&); + const TextEditorInsertAction& operator= (const TextEditorInsertAction&); public: - TextEditorInsertAction (TextEditor& owner_, - const String& text_, - const int insertIndex_, - const Font& font_, - const Colour& colour_, - const int oldCaretPos_, - const int newCaretPos_) - : owner (owner_), - text (text_), - insertIndex (insertIndex_), - oldCaretPos (oldCaretPos_), - newCaretPos (newCaretPos_), - font (font_), - colour (colour_) - { - } + TextEditorInsertAction (TextEditor& owner_, + const String& text_, + const int insertIndex_, + const Font& font_, + const Colour& colour_, + const int oldCaretPos_, + const int newCaretPos_) + : owner (owner_), + text (text_), + insertIndex (insertIndex_), + oldCaretPos (oldCaretPos_), + newCaretPos (newCaretPos_), + font (font_), + colour (colour_) + { + } - ~TextEditorInsertAction() - { - } + ~TextEditorInsertAction() + { + } - bool perform() - { - owner.insert (text, insertIndex, font, colour, 0, newCaretPos); - return true; - } + bool perform() + { + owner.insert (text, insertIndex, font, colour, 0, newCaretPos); + return true; + } - bool undo() - { - owner.remove (insertIndex, insertIndex + text.length(), 0, oldCaretPos); - return true; - } + bool undo() + { + owner.remove (insertIndex, insertIndex + text.length(), 0, oldCaretPos); + return true; + } - int getSizeInUnits() - { - return text.length() + 16; - } + int getSizeInUnits() + { + return text.length() + 16; + } }; class TextEditorRemoveAction : public UndoableAction { - TextEditor& owner; - const int startIndex, endIndex, oldCaretPos, newCaretPos; - VoidArray removedSections; + TextEditor& owner; + const int startIndex, endIndex, oldCaretPos, newCaretPos; + VoidArray removedSections; - TextEditorRemoveAction (const TextEditorRemoveAction&); - const TextEditorRemoveAction& operator= (const TextEditorRemoveAction&); + TextEditorRemoveAction (const TextEditorRemoveAction&); + const TextEditorRemoveAction& operator= (const TextEditorRemoveAction&); public: - TextEditorRemoveAction (TextEditor& owner_, - const int startIndex_, - const int endIndex_, - const int oldCaretPos_, - const int newCaretPos_, - const VoidArray& removedSections_) - : owner (owner_), - startIndex (startIndex_), - endIndex (endIndex_), - oldCaretPos (oldCaretPos_), - newCaretPos (newCaretPos_), - removedSections (removedSections_) - { - } + TextEditorRemoveAction (TextEditor& owner_, + const int startIndex_, + const int endIndex_, + const int oldCaretPos_, + const int newCaretPos_, + const VoidArray& removedSections_) + : owner (owner_), + startIndex (startIndex_), + endIndex (endIndex_), + oldCaretPos (oldCaretPos_), + newCaretPos (newCaretPos_), + removedSections (removedSections_) + { + } - ~TextEditorRemoveAction() - { - for (int i = removedSections.size(); --i >= 0;) - { - UniformTextSection* const section = (UniformTextSection*) removedSections.getUnchecked (i); - section->clear(); - delete section; - } - } + ~TextEditorRemoveAction() + { + for (int i = removedSections.size(); --i >= 0;) + { + UniformTextSection* const section = (UniformTextSection*) removedSections.getUnchecked (i); + section->clear(); + delete section; + } + } - bool perform() - { - owner.remove (startIndex, endIndex, 0, newCaretPos); - return true; - } + bool perform() + { + owner.remove (startIndex, endIndex, 0, newCaretPos); + return true; + } - bool undo() - { - owner.reinsert (startIndex, removedSections); - owner.moveCursorTo (oldCaretPos, false); - return true; - } + bool undo() + { + owner.reinsert (startIndex, removedSections); + owner.moveCursorTo (oldCaretPos, false); + return true; + } - int getSizeInUnits() - { - int n = 0; + int getSizeInUnits() + { + int n = 0; - for (int i = removedSections.size(); --i >= 0;) - { - UniformTextSection* const section = (UniformTextSection*) removedSections.getUnchecked (i); - n += section->getTotalLength(); - } + for (int i = removedSections.size(); --i >= 0;) + { + UniformTextSection* const section = (UniformTextSection*) removedSections.getUnchecked (i); + n += section->getTotalLength(); + } - return n + 16; - } + return n + 16; + } }; class TextHolderComponent : public Component, - public Timer, - public Value::Listener + public Timer, + public Value::Listener { - TextEditor& owner; + TextEditor& owner; - TextHolderComponent (const TextHolderComponent&); - const TextHolderComponent& operator= (const TextHolderComponent&); + TextHolderComponent (const TextHolderComponent&); + const TextHolderComponent& operator= (const TextHolderComponent&); public: - TextHolderComponent (TextEditor& owner_) - : owner (owner_) - { - setWantsKeyboardFocus (false); - setInterceptsMouseClicks (false, true); + TextHolderComponent (TextEditor& owner_) + : owner (owner_) + { + setWantsKeyboardFocus (false); + setInterceptsMouseClicks (false, true); - owner.getTextValue().addListener (this); - } + owner.getTextValue().addListener (this); + } - ~TextHolderComponent() - { - owner.getTextValue().removeListener (this); - } + ~TextHolderComponent() + { + owner.getTextValue().removeListener (this); + } - void paint (Graphics& g) - { - owner.drawContent (g); - } + void paint (Graphics& g) + { + owner.drawContent (g); + } - void timerCallback() - { - owner.timerCallbackInt(); - } + void timerCallback() + { + owner.timerCallbackInt(); + } - const MouseCursor getMouseCursor() - { - return owner.getMouseCursor(); - } + const MouseCursor getMouseCursor() + { + return owner.getMouseCursor(); + } - void valueChanged (Value&) - { - owner.textWasChangedByValue(); - } + void valueChanged (Value&) + { + owner.textWasChangedByValue(); + } }; class TextEditorViewport : public Viewport { - TextEditor* const owner; - float lastWordWrapWidth; + TextEditor* const owner; + float lastWordWrapWidth; - TextEditorViewport (const TextEditorViewport&); - const TextEditorViewport& operator= (const TextEditorViewport&); + TextEditorViewport (const TextEditorViewport&); + const TextEditorViewport& operator= (const TextEditorViewport&); public: - TextEditorViewport (TextEditor* const owner_) - : owner (owner_), - lastWordWrapWidth (0) - { - } + TextEditorViewport (TextEditor* const owner_) + : owner (owner_), + lastWordWrapWidth (0) + { + } - ~TextEditorViewport() - { - } + ~TextEditorViewport() + { + } - void visibleAreaChanged (int, int, int, int) - { - const float wordWrapWidth = owner->getWordWrapWidth(); + void visibleAreaChanged (int, int, int, int) + { + const float wordWrapWidth = owner->getWordWrapWidth(); - if (wordWrapWidth != lastWordWrapWidth) - { - lastWordWrapWidth = wordWrapWidth; - owner->updateTextHolderSize(); - } - } + if (wordWrapWidth != lastWordWrapWidth) + { + lastWordWrapWidth = wordWrapWidth; + owner->updateTextHolderSize(); + } + } }; const int flashSpeedIntervalMs = 380; @@ -52589,1650 +52295,1648 @@ const int escapeKeyMessageId = 0x10003003; const int focusLossMessageId = 0x10003004; TextEditor::TextEditor (const String& name, - const tchar passwordCharacter_) - : Component (name), - borderSize (1, 1, 1, 3), - readOnly (false), - multiline (false), - wordWrap (false), - returnKeyStartsNewLine (false), - caretVisible (true), - popupMenuEnabled (true), - selectAllTextWhenFocused (false), - scrollbarVisible (true), - wasFocused (false), - caretFlashState (true), - keepCursorOnScreen (true), - tabKeyUsed (false), - menuActive (false), - valueTextNeedsUpdating (false), - cursorX (0), - cursorY (0), - cursorHeight (0), - maxTextLength (0), - selectionStart (0), - selectionEnd (0), - leftIndent (4), - topIndent (4), - lastTransactionTime (0), - currentFont (14.0f), - totalNumChars (0), - caretPosition (0), - sections (8), - passwordCharacter (passwordCharacter_), - dragType (notDragging), - listeners (2) + const tchar passwordCharacter_) + : Component (name), + borderSize (1, 1, 1, 3), + readOnly (false), + multiline (false), + wordWrap (false), + returnKeyStartsNewLine (false), + caretVisible (true), + popupMenuEnabled (true), + selectAllTextWhenFocused (false), + scrollbarVisible (true), + wasFocused (false), + caretFlashState (true), + keepCursorOnScreen (true), + tabKeyUsed (false), + menuActive (false), + valueTextNeedsUpdating (false), + cursorX (0), + cursorY (0), + cursorHeight (0), + maxTextLength (0), + selectionStart (0), + selectionEnd (0), + leftIndent (4), + topIndent (4), + lastTransactionTime (0), + currentFont (14.0f), + totalNumChars (0), + caretPosition (0), + passwordCharacter (passwordCharacter_), + dragType (notDragging) { - setOpaque (true); + setOpaque (true); - addAndMakeVisible (viewport = new TextEditorViewport (this)); - viewport->setViewedComponent (textHolder = new TextHolderComponent (*this)); - viewport->setWantsKeyboardFocus (false); - viewport->setScrollBarsShown (false, false); + addAndMakeVisible (viewport = new TextEditorViewport (this)); + viewport->setViewedComponent (textHolder = new TextHolderComponent (*this)); + viewport->setWantsKeyboardFocus (false); + viewport->setScrollBarsShown (false, false); - setMouseCursor (MouseCursor::IBeamCursor); - setWantsKeyboardFocus (true); + setMouseCursor (MouseCursor::IBeamCursor); + setWantsKeyboardFocus (true); } TextEditor::~TextEditor() { - clearInternal (0); - viewport = 0; - textHolder = 0; + clearInternal (0); + viewport = 0; + textHolder = 0; } void TextEditor::newTransaction() { - lastTransactionTime = Time::getApproximateMillisecondCounter(); - undoManager.beginNewTransaction(); + lastTransactionTime = Time::getApproximateMillisecondCounter(); + undoManager.beginNewTransaction(); } void TextEditor::doUndoRedo (const bool isRedo) { - if (! isReadOnly()) - { - if ((isRedo) ? undoManager.redo() - : undoManager.undo()) - { - scrollToMakeSureCursorIsVisible(); - repaint(); - textChanged(); - } - } + if (! isReadOnly()) + { + if ((isRedo) ? undoManager.redo() + : undoManager.undo()) + { + scrollToMakeSureCursorIsVisible(); + repaint(); + textChanged(); + } + } } void TextEditor::setMultiLine (const bool shouldBeMultiLine, - const bool shouldWordWrap) + const bool shouldWordWrap) { - multiline = shouldBeMultiLine; - wordWrap = shouldWordWrap && shouldBeMultiLine; + multiline = shouldBeMultiLine; + wordWrap = shouldWordWrap && shouldBeMultiLine; - setScrollbarsShown (scrollbarVisible); + setScrollbarsShown (scrollbarVisible); - viewport->setViewPosition (0, 0); + viewport->setViewPosition (0, 0); - resized(); - scrollToMakeSureCursorIsVisible(); + resized(); + scrollToMakeSureCursorIsVisible(); } bool TextEditor::isMultiLine() const { - return multiline; + return multiline; } void TextEditor::setScrollbarsShown (bool enabled) { - scrollbarVisible = enabled; + scrollbarVisible = enabled; - enabled = enabled && isMultiLine(); + enabled = enabled && isMultiLine(); - viewport->setScrollBarsShown (enabled, enabled); + viewport->setScrollBarsShown (enabled, enabled); } void TextEditor::setReadOnly (const bool shouldBeReadOnly) { - readOnly = shouldBeReadOnly; - enablementChanged(); + readOnly = shouldBeReadOnly; + enablementChanged(); } bool TextEditor::isReadOnly() const { - return readOnly || ! isEnabled(); + return readOnly || ! isEnabled(); } void TextEditor::setReturnKeyStartsNewLine (const bool shouldStartNewLine) { - returnKeyStartsNewLine = shouldStartNewLine; + returnKeyStartsNewLine = shouldStartNewLine; } void TextEditor::setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) { - tabKeyUsed = shouldTabKeyBeUsed; + tabKeyUsed = shouldTabKeyBeUsed; } void TextEditor::setPopupMenuEnabled (const bool b) { - popupMenuEnabled = b; + popupMenuEnabled = b; } void TextEditor::setSelectAllWhenFocused (const bool b) { - selectAllTextWhenFocused = b; + selectAllTextWhenFocused = b; } const Font TextEditor::getFont() const { - return currentFont; + return currentFont; } void TextEditor::setFont (const Font& newFont) { - currentFont = newFont; - scrollToMakeSureCursorIsVisible(); + currentFont = newFont; + scrollToMakeSureCursorIsVisible(); } void TextEditor::applyFontToAllText (const Font& newFont) { - currentFont = newFont; + currentFont = newFont; - const Colour overallColour (findColour (textColourId)); + const Colour overallColour (findColour (textColourId)); - for (int i = sections.size(); --i >= 0;) - { - UniformTextSection* const uts = (UniformTextSection*) sections.getUnchecked(i); - uts->setFont (newFont, passwordCharacter); - uts->colour = overallColour; - } + for (int i = sections.size(); --i >= 0;) + { + UniformTextSection* const uts = (UniformTextSection*) sections.getUnchecked(i); + uts->setFont (newFont, passwordCharacter); + uts->colour = overallColour; + } - coalesceSimilarSections(); - updateTextHolderSize(); - scrollToMakeSureCursorIsVisible(); - repaint(); + coalesceSimilarSections(); + updateTextHolderSize(); + scrollToMakeSureCursorIsVisible(); + repaint(); } void TextEditor::colourChanged() { - setOpaque (findColour (backgroundColourId).isOpaque()); - repaint(); + setOpaque (findColour (backgroundColourId).isOpaque()); + repaint(); } void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) { - caretVisible = shouldCaretBeVisible; + caretVisible = shouldCaretBeVisible; - if (shouldCaretBeVisible) - textHolder->startTimer (flashSpeedIntervalMs); + if (shouldCaretBeVisible) + textHolder->startTimer (flashSpeedIntervalMs); - setMouseCursor (shouldCaretBeVisible ? MouseCursor::IBeamCursor - : MouseCursor::NormalCursor); + setMouseCursor (shouldCaretBeVisible ? MouseCursor::IBeamCursor + : MouseCursor::NormalCursor); } void TextEditor::setInputRestrictions (const int maxLen, - const String& chars) + const String& chars) { - maxTextLength = jmax (0, maxLen); - allowedCharacters = chars; + maxTextLength = jmax (0, maxLen); + allowedCharacters = chars; } void TextEditor::setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) { - textToShowWhenEmpty = text; - colourForTextWhenEmpty = colourToUse; + textToShowWhenEmpty = text; + colourForTextWhenEmpty = colourToUse; } void TextEditor::setPasswordCharacter (const tchar newPasswordCharacter) { - if (passwordCharacter != newPasswordCharacter) - { - passwordCharacter = newPasswordCharacter; - resized(); - repaint(); - } + if (passwordCharacter != newPasswordCharacter) + { + passwordCharacter = newPasswordCharacter; + resized(); + repaint(); + } } void TextEditor::setScrollBarThickness (const int newThicknessPixels) { - viewport->setScrollBarThickness (newThicknessPixels); + viewport->setScrollBarThickness (newThicknessPixels); } void TextEditor::setScrollBarButtonVisibility (const bool buttonsVisible) { - viewport->setScrollBarButtonVisibility (buttonsVisible); + viewport->setScrollBarButtonVisibility (buttonsVisible); } void TextEditor::clear() { - clearInternal (0); - updateTextHolderSize(); - undoManager.clearUndoHistory(); + clearInternal (0); + updateTextHolderSize(); + undoManager.clearUndoHistory(); } void TextEditor::setText (const String& newText, - const bool sendTextChangeMessage) + const bool sendTextChangeMessage) { - const int newLength = newText.length(); + const int newLength = newText.length(); - if (newLength != getTotalNumChars() || getText() != newText) - { - const int oldCursorPos = caretPosition; - const bool cursorWasAtEnd = oldCursorPos >= getTotalNumChars(); + if (newLength != getTotalNumChars() || getText() != newText) + { + const int oldCursorPos = caretPosition; + const bool cursorWasAtEnd = oldCursorPos >= getTotalNumChars(); - clearInternal (0); - insert (newText, 0, currentFont, findColour (textColourId), 0, caretPosition); + clearInternal (0); + insert (newText, 0, currentFont, findColour (textColourId), 0, caretPosition); - // if you're adding text with line-feeds to a single-line text editor, it - // ain't gonna look right! - jassert (multiline || ! newText.containsAnyOf (T("\r\n"))); + // if you're adding text with line-feeds to a single-line text editor, it + // ain't gonna look right! + jassert (multiline || ! newText.containsAnyOf (T("\r\n"))); - if (cursorWasAtEnd && ! isMultiLine()) - moveCursorTo (getTotalNumChars(), false); - else - moveCursorTo (oldCursorPos, false); + if (cursorWasAtEnd && ! isMultiLine()) + moveCursorTo (getTotalNumChars(), false); + else + moveCursorTo (oldCursorPos, false); - if (sendTextChangeMessage) - textChanged(); + if (sendTextChangeMessage) + textChanged(); - repaint(); - } + repaint(); + } - updateTextHolderSize(); - scrollToMakeSureCursorIsVisible(); - undoManager.clearUndoHistory(); + updateTextHolderSize(); + scrollToMakeSureCursorIsVisible(); + undoManager.clearUndoHistory(); } Value& TextEditor::getTextValue() { - if (valueTextNeedsUpdating) - { - valueTextNeedsUpdating = false; - textValue = getText(); - } + if (valueTextNeedsUpdating) + { + valueTextNeedsUpdating = false; + textValue = getText(); + } - return textValue; + return textValue; } void TextEditor::textWasChangedByValue() { - if (textValue.getValueSource().getReferenceCount() > 1) - setText (textValue.getValue()); + if (textValue.getValueSource().getReferenceCount() > 1) + setText (textValue.getValue()); } void TextEditor::textChanged() { - updateTextHolderSize(); - postCommandMessage (textChangeMessageId); + updateTextHolderSize(); + postCommandMessage (textChangeMessageId); - if (textValue.getValueSource().getReferenceCount() > 1) - { - valueTextNeedsUpdating = false; - textValue = getText(); - } + if (textValue.getValueSource().getReferenceCount() > 1) + { + valueTextNeedsUpdating = false; + textValue = getText(); + } } void TextEditor::returnPressed() { - postCommandMessage (returnKeyMessageId); + postCommandMessage (returnKeyMessageId); } void TextEditor::escapePressed() { - postCommandMessage (escapeKeyMessageId); + postCommandMessage (escapeKeyMessageId); } void TextEditor::addListener (TextEditorListener* const newListener) { - jassert (newListener != 0) + jassert (newListener != 0) - if (newListener != 0) - listeners.add (newListener); + if (newListener != 0) + listeners.add (newListener); } void TextEditor::removeListener (TextEditorListener* const listenerToRemove) { - listeners.removeValue (listenerToRemove); + listeners.removeValue (listenerToRemove); } void TextEditor::timerCallbackInt() { - const bool newState = (! caretFlashState) && ! isCurrentlyBlockedByAnotherModalComponent(); + const bool newState = (! caretFlashState) && ! isCurrentlyBlockedByAnotherModalComponent(); - if (caretFlashState != newState) - { - caretFlashState = newState; + if (caretFlashState != newState) + { + caretFlashState = newState; - if (caretFlashState) - wasFocused = true; + if (caretFlashState) + wasFocused = true; - if (caretVisible - && hasKeyboardFocus (false) - && ! isReadOnly()) - { - repaintCaret(); - } - } + if (caretVisible + && hasKeyboardFocus (false) + && ! isReadOnly()) + { + repaintCaret(); + } + } - const unsigned int now = Time::getApproximateMillisecondCounter(); + const unsigned int now = Time::getApproximateMillisecondCounter(); - if (now > lastTransactionTime + 200) - newTransaction(); + if (now > lastTransactionTime + 200) + newTransaction(); } void TextEditor::repaintCaret() { - if (! findColour (caretColourId).isTransparent()) - repaint (borderSize.getLeft() + textHolder->getX() + leftIndent + roundFloatToInt (cursorX) - 1, - borderSize.getTop() + textHolder->getY() + topIndent + roundFloatToInt (cursorY) - 1, - 4, - roundFloatToInt (cursorHeight) + 2); + if (! findColour (caretColourId).isTransparent()) + repaint (borderSize.getLeft() + textHolder->getX() + leftIndent + roundToInt (cursorX) - 1, + borderSize.getTop() + textHolder->getY() + topIndent + roundToInt (cursorY) - 1, + 4, + roundToInt (cursorHeight) + 2); } void TextEditor::repaintText (int textStartIndex, int textEndIndex) { - if (textStartIndex > textEndIndex && textEndIndex > 0) - swapVariables (textStartIndex, textEndIndex); + if (textStartIndex > textEndIndex && textEndIndex > 0) + swapVariables (textStartIndex, textEndIndex); - float x = 0, y = 0, lh = currentFont.getHeight(); + float x = 0, y = 0, lh = currentFont.getHeight(); - const float wordWrapWidth = getWordWrapWidth(); + const float wordWrapWidth = getWordWrapWidth(); - if (wordWrapWidth > 0) - { - TextEditorIterator i (sections, wordWrapWidth, passwordCharacter); + if (wordWrapWidth > 0) + { + TextEditorIterator i (sections, wordWrapWidth, passwordCharacter); - i.getCharPosition (textStartIndex, x, y, lh); + i.getCharPosition (textStartIndex, x, y, lh); - const int y1 = (int) y; - int y2; + const int y1 = (int) y; + int y2; - if (textEndIndex >= 0) - { - i.getCharPosition (textEndIndex, x, y, lh); - y2 = (int) (y + lh * 2.0f); - } - else - { - y2 = textHolder->getHeight(); - } + if (textEndIndex >= 0) + { + i.getCharPosition (textEndIndex, x, y, lh); + y2 = (int) (y + lh * 2.0f); + } + else + { + y2 = textHolder->getHeight(); + } - textHolder->repaint (0, y1, textHolder->getWidth(), y2 - y1); - } + textHolder->repaint (0, y1, textHolder->getWidth(), y2 - y1); + } } void TextEditor::moveCaret (int newCaretPos) { - if (newCaretPos < 0) - newCaretPos = 0; - else if (newCaretPos > getTotalNumChars()) - newCaretPos = getTotalNumChars(); + if (newCaretPos < 0) + newCaretPos = 0; + else if (newCaretPos > getTotalNumChars()) + newCaretPos = getTotalNumChars(); - if (newCaretPos != getCaretPosition()) - { - repaintCaret(); - caretFlashState = true; - caretPosition = newCaretPos; - textHolder->startTimer (flashSpeedIntervalMs); - scrollToMakeSureCursorIsVisible(); - repaintCaret(); - } + if (newCaretPos != getCaretPosition()) + { + repaintCaret(); + caretFlashState = true; + caretPosition = newCaretPos; + textHolder->startTimer (flashSpeedIntervalMs); + scrollToMakeSureCursorIsVisible(); + repaintCaret(); + } } void TextEditor::setCaretPosition (const int newIndex) { - moveCursorTo (newIndex, false); + moveCursorTo (newIndex, false); } int TextEditor::getCaretPosition() const { - return caretPosition; + return caretPosition; } void TextEditor::scrollEditorToPositionCaret (const int desiredCaretX, - const int desiredCaretY) + const int desiredCaretY) { - updateCaretPosition(); + updateCaretPosition(); - int vx = roundFloatToInt (cursorX) - desiredCaretX; - int vy = roundFloatToInt (cursorY) - desiredCaretY; + int vx = roundToInt (cursorX) - desiredCaretX; + int vy = roundToInt (cursorY) - desiredCaretY; - if (desiredCaretX < jmax (1, proportionOfWidth (0.05f))) - { - vx += desiredCaretX - proportionOfWidth (0.2f); - } - else if (desiredCaretX > jmax (0, viewport->getMaximumVisibleWidth() - (wordWrap ? 2 : 10))) - { - vx += desiredCaretX + (isMultiLine() ? proportionOfWidth (0.2f) : 10) - viewport->getMaximumVisibleWidth(); - } + if (desiredCaretX < jmax (1, proportionOfWidth (0.05f))) + { + vx += desiredCaretX - proportionOfWidth (0.2f); + } + else if (desiredCaretX > jmax (0, viewport->getMaximumVisibleWidth() - (wordWrap ? 2 : 10))) + { + vx += desiredCaretX + (isMultiLine() ? proportionOfWidth (0.2f) : 10) - viewport->getMaximumVisibleWidth(); + } - vx = jlimit (0, jmax (0, textHolder->getWidth() + 8 - viewport->getMaximumVisibleWidth()), vx); + vx = jlimit (0, jmax (0, textHolder->getWidth() + 8 - viewport->getMaximumVisibleWidth()), vx); - if (! isMultiLine()) - { - vy = viewport->getViewPositionY(); - } - else - { - vy = jlimit (0, jmax (0, textHolder->getHeight() - viewport->getMaximumVisibleHeight()), vy); + if (! isMultiLine()) + { + vy = viewport->getViewPositionY(); + } + else + { + vy = jlimit (0, jmax (0, textHolder->getHeight() - viewport->getMaximumVisibleHeight()), vy); - const int curH = roundFloatToInt (cursorHeight); + const int curH = roundToInt (cursorHeight); - if (desiredCaretY < 0) - { - vy = jmax (0, desiredCaretY + vy); - } - else if (desiredCaretY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - curH)) - { - vy += desiredCaretY + 2 + curH + topIndent - viewport->getMaximumVisibleHeight(); - } - } + if (desiredCaretY < 0) + { + vy = jmax (0, desiredCaretY + vy); + } + else if (desiredCaretY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - curH)) + { + vy += desiredCaretY + 2 + curH + topIndent - viewport->getMaximumVisibleHeight(); + } + } - viewport->setViewPosition (vx, vy); + viewport->setViewPosition (vx, vy); } const Rectangle TextEditor::getCaretRectangle() { - updateCaretPosition(); + updateCaretPosition(); - return Rectangle (roundFloatToInt (cursorX) - viewport->getX(), - roundFloatToInt (cursorY) - viewport->getY(), - 1, roundFloatToInt (cursorHeight)); + return Rectangle (roundToInt (cursorX) - viewport->getX(), + roundToInt (cursorY) - viewport->getY(), + 1, roundToInt (cursorHeight)); } float TextEditor::getWordWrapWidth() const { - return (wordWrap) ? (float) (viewport->getMaximumVisibleWidth() - leftIndent - leftIndent / 2) - : 1.0e10f; + return (wordWrap) ? (float) (viewport->getMaximumVisibleWidth() - leftIndent - leftIndent / 2) + : 1.0e10f; } void TextEditor::updateTextHolderSize() { - const float wordWrapWidth = getWordWrapWidth(); + const float wordWrapWidth = getWordWrapWidth(); - if (wordWrapWidth > 0) - { - float maxWidth = 0.0f; + if (wordWrapWidth > 0) + { + float maxWidth = 0.0f; - TextEditorIterator i (sections, wordWrapWidth, passwordCharacter); + TextEditorIterator i (sections, wordWrapWidth, passwordCharacter); - while (i.next()) - maxWidth = jmax (maxWidth, i.atomRight); + while (i.next()) + maxWidth = jmax (maxWidth, i.atomRight); - const int w = leftIndent + roundFloatToInt (maxWidth); - const int h = topIndent + roundFloatToInt (jmax (i.lineY + i.lineHeight, - currentFont.getHeight())); + const int w = leftIndent + roundToInt (maxWidth); + const int h = topIndent + roundToInt (jmax (i.lineY + i.lineHeight, + currentFont.getHeight())); - textHolder->setSize (w + 1, h + 1); - } + textHolder->setSize (w + 1, h + 1); + } } int TextEditor::getTextWidth() const { - return textHolder->getWidth(); + return textHolder->getWidth(); } int TextEditor::getTextHeight() const { - return textHolder->getHeight(); + return textHolder->getHeight(); } void TextEditor::setIndents (const int newLeftIndent, - const int newTopIndent) + const int newTopIndent) { - leftIndent = newLeftIndent; - topIndent = newTopIndent; + leftIndent = newLeftIndent; + topIndent = newTopIndent; } void TextEditor::setBorder (const BorderSize& border) { - borderSize = border; - resized(); + borderSize = border; + resized(); } const BorderSize TextEditor::getBorder() const { - return borderSize; + return borderSize; } void TextEditor::setScrollToShowCursor (const bool shouldScrollToShowCursor) { - keepCursorOnScreen = shouldScrollToShowCursor; + keepCursorOnScreen = shouldScrollToShowCursor; } void TextEditor::updateCaretPosition() { - cursorHeight = currentFont.getHeight(); // (in case the text is empty and the call below doesn't set this value) - getCharPosition (caretPosition, cursorX, cursorY, cursorHeight); + cursorHeight = currentFont.getHeight(); // (in case the text is empty and the call below doesn't set this value) + getCharPosition (caretPosition, cursorX, cursorY, cursorHeight); } void TextEditor::scrollToMakeSureCursorIsVisible() { - updateCaretPosition(); + updateCaretPosition(); - if (keepCursorOnScreen) - { - int x = viewport->getViewPositionX(); - int y = viewport->getViewPositionY(); + if (keepCursorOnScreen) + { + int x = viewport->getViewPositionX(); + int y = viewport->getViewPositionY(); - const int relativeCursorX = roundFloatToInt (cursorX) - x; - const int relativeCursorY = roundFloatToInt (cursorY) - y; + const int relativeCursorX = roundToInt (cursorX) - x; + const int relativeCursorY = roundToInt (cursorY) - y; - if (relativeCursorX < jmax (1, proportionOfWidth (0.05f))) - { - x += relativeCursorX - proportionOfWidth (0.2f); - } - else if (relativeCursorX > jmax (0, viewport->getMaximumVisibleWidth() - (wordWrap ? 2 : 10))) - { - x += relativeCursorX + (isMultiLine() ? proportionOfWidth (0.2f) : 10) - viewport->getMaximumVisibleWidth(); - } + if (relativeCursorX < jmax (1, proportionOfWidth (0.05f))) + { + x += relativeCursorX - proportionOfWidth (0.2f); + } + else if (relativeCursorX > jmax (0, viewport->getMaximumVisibleWidth() - (wordWrap ? 2 : 10))) + { + x += relativeCursorX + (isMultiLine() ? proportionOfWidth (0.2f) : 10) - viewport->getMaximumVisibleWidth(); + } - x = jlimit (0, jmax (0, textHolder->getWidth() + 8 - viewport->getMaximumVisibleWidth()), x); + x = jlimit (0, jmax (0, textHolder->getWidth() + 8 - viewport->getMaximumVisibleWidth()), x); - if (! isMultiLine()) - { - y = (getHeight() - textHolder->getHeight() - topIndent) / -2; - } - else - { - const int curH = roundFloatToInt (cursorHeight); + if (! isMultiLine()) + { + y = (getHeight() - textHolder->getHeight() - topIndent) / -2; + } + else + { + const int curH = roundToInt (cursorHeight); - if (relativeCursorY < 0) - { - y = jmax (0, relativeCursorY + y); - } - else if (relativeCursorY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - curH)) - { - y += relativeCursorY + 2 + curH + topIndent - viewport->getMaximumVisibleHeight(); - } - } + if (relativeCursorY < 0) + { + y = jmax (0, relativeCursorY + y); + } + else if (relativeCursorY > jmax (0, viewport->getMaximumVisibleHeight() - topIndent - curH)) + { + y += relativeCursorY + 2 + curH + topIndent - viewport->getMaximumVisibleHeight(); + } + } - viewport->setViewPosition (x, y); - } + viewport->setViewPosition (x, y); + } } void TextEditor::moveCursorTo (const int newPosition, - const bool isSelecting) + const bool isSelecting) { - if (isSelecting) - { - moveCaret (newPosition); + if (isSelecting) + { + moveCaret (newPosition); - const int oldSelStart = selectionStart; - const int oldSelEnd = selectionEnd; + const int oldSelStart = selectionStart; + const int oldSelEnd = selectionEnd; - if (dragType == notDragging) - { - if (abs (getCaretPosition() - selectionStart) < abs (getCaretPosition() - selectionEnd)) - dragType = draggingSelectionStart; - else - dragType = draggingSelectionEnd; - } + if (dragType == notDragging) + { + if (abs (getCaretPosition() - selectionStart) < abs (getCaretPosition() - selectionEnd)) + dragType = draggingSelectionStart; + else + dragType = draggingSelectionEnd; + } - if (dragType == draggingSelectionStart) - { - selectionStart = getCaretPosition(); + if (dragType == draggingSelectionStart) + { + selectionStart = getCaretPosition(); - if (selectionEnd < selectionStart) - { - swapVariables (selectionStart, selectionEnd); - dragType = draggingSelectionEnd; - } - } - else - { - selectionEnd = getCaretPosition(); + if (selectionEnd < selectionStart) + { + swapVariables (selectionStart, selectionEnd); + dragType = draggingSelectionEnd; + } + } + else + { + selectionEnd = getCaretPosition(); - if (selectionEnd < selectionStart) - { - swapVariables (selectionStart, selectionEnd); - dragType = draggingSelectionStart; - } - } + if (selectionEnd < selectionStart) + { + swapVariables (selectionStart, selectionEnd); + dragType = draggingSelectionStart; + } + } - jassert (selectionStart <= selectionEnd); - jassert (oldSelStart <= oldSelEnd); + jassert (selectionStart <= selectionEnd); + jassert (oldSelStart <= oldSelEnd); - repaintText (jmin (oldSelStart, selectionStart), - jmax (oldSelEnd, selectionEnd)); - } - else - { - dragType = notDragging; + repaintText (jmin (oldSelStart, selectionStart), + jmax (oldSelEnd, selectionEnd)); + } + else + { + dragType = notDragging; - if (selectionEnd > selectionStart) - repaintText (selectionStart, selectionEnd); + if (selectionEnd > selectionStart) + repaintText (selectionStart, selectionEnd); - moveCaret (newPosition); - selectionStart = getCaretPosition(); - selectionEnd = getCaretPosition(); - } + moveCaret (newPosition); + selectionStart = getCaretPosition(); + selectionEnd = getCaretPosition(); + } } int TextEditor::getTextIndexAt (const int x, - const int y) + const int y) { - return indexAtPosition ((float) (x + viewport->getViewPositionX() - leftIndent), - (float) (y + viewport->getViewPositionY() - topIndent)); + return indexAtPosition ((float) (x + viewport->getViewPositionX() - leftIndent), + (float) (y + viewport->getViewPositionY() - topIndent)); } void TextEditor::insertTextAtCursor (String newText) { - if (allowedCharacters.isNotEmpty()) - newText = newText.retainCharacters (allowedCharacters); + if (allowedCharacters.isNotEmpty()) + newText = newText.retainCharacters (allowedCharacters); - if (! isMultiLine()) - newText = newText.replaceCharacters (T("\r\n"), T(" ")); - else - newText = newText.replace (T("\r\n"), T("\n")); + if (! isMultiLine()) + newText = newText.replaceCharacters (T("\r\n"), T(" ")); + else + newText = newText.replace (T("\r\n"), T("\n")); - const int newCaretPos = selectionStart + newText.length(); - const int insertIndex = selectionStart; + const int newCaretPos = selectionStart + newText.length(); + const int insertIndex = selectionStart; - remove (selectionStart, selectionEnd, - &undoManager, - newText.isNotEmpty() ? newCaretPos - 1 : newCaretPos); + remove (selectionStart, selectionEnd, + &undoManager, + newText.isNotEmpty() ? newCaretPos - 1 : newCaretPos); - if (maxTextLength > 0) - newText = newText.substring (0, maxTextLength - getTotalNumChars()); + if (maxTextLength > 0) + newText = newText.substring (0, maxTextLength - getTotalNumChars()); - if (newText.isNotEmpty()) - insert (newText, - insertIndex, - currentFont, - findColour (textColourId), - &undoManager, - newCaretPos); + if (newText.isNotEmpty()) + insert (newText, + insertIndex, + currentFont, + findColour (textColourId), + &undoManager, + newCaretPos); - textChanged(); + textChanged(); } void TextEditor::setHighlightedRegion (int startPos, int numChars) { - moveCursorTo (startPos, false); - moveCursorTo (startPos + numChars, true); + moveCursorTo (startPos, false); + moveCursorTo (startPos + numChars, true); } void TextEditor::copy() { - if (passwordCharacter == 0) - { - const String selection (getTextSubstring (selectionStart, selectionEnd)); + if (passwordCharacter == 0) + { + const String selection (getTextSubstring (selectionStart, selectionEnd)); - if (selection.isNotEmpty()) - SystemClipboard::copyTextToClipboard (selection); - } + if (selection.isNotEmpty()) + SystemClipboard::copyTextToClipboard (selection); + } } void TextEditor::paste() { - if (! isReadOnly()) - { - const String clip (SystemClipboard::getTextFromClipboard()); + if (! isReadOnly()) + { + const String clip (SystemClipboard::getTextFromClipboard()); - if (clip.isNotEmpty()) - insertTextAtCursor (clip); - } + if (clip.isNotEmpty()) + insertTextAtCursor (clip); + } } void TextEditor::cut() { - if (! isReadOnly()) - { - moveCaret (selectionEnd); - insertTextAtCursor (String::empty); - } + if (! isReadOnly()) + { + moveCaret (selectionEnd); + insertTextAtCursor (String::empty); + } } void TextEditor::drawContent (Graphics& g) { - const float wordWrapWidth = getWordWrapWidth(); + const float wordWrapWidth = getWordWrapWidth(); - if (wordWrapWidth > 0) - { - g.setOrigin (leftIndent, topIndent); - const Rectangle clip (g.getClipBounds()); - Colour selectedTextColour; + if (wordWrapWidth > 0) + { + g.setOrigin (leftIndent, topIndent); + const Rectangle clip (g.getClipBounds()); + Colour selectedTextColour; - TextEditorIterator i (sections, wordWrapWidth, passwordCharacter); + TextEditorIterator i (sections, wordWrapWidth, passwordCharacter); - while (i.lineY + 200.0 < clip.getY() && i.next()) - {} + while (i.lineY + 200.0 < clip.getY() && i.next()) + {} - if (selectionStart < selectionEnd) - { - g.setColour (findColour (highlightColourId) - .withMultipliedAlpha (hasKeyboardFocus (true) ? 1.0f : 0.5f)); + if (selectionStart < selectionEnd) + { + g.setColour (findColour (highlightColourId) + .withMultipliedAlpha (hasKeyboardFocus (true) ? 1.0f : 0.5f)); - selectedTextColour = findColour (highlightedTextColourId); + selectedTextColour = findColour (highlightedTextColourId); - TextEditorIterator i2 (i); + TextEditorIterator i2 (i); - while (i2.next() && i2.lineY < clip.getBottom()) - { - if (i2.lineY + i2.lineHeight >= clip.getY() - && selectionEnd >= i2.indexInText - && selectionStart <= i2.indexInText + i2.atom->numChars) - { - i2.drawSelection (g, selectionStart, selectionEnd); - } - } - } + while (i2.next() && i2.lineY < clip.getBottom()) + { + if (i2.lineY + i2.lineHeight >= clip.getY() + && selectionEnd >= i2.indexInText + && selectionStart <= i2.indexInText + i2.atom->numChars) + { + i2.drawSelection (g, selectionStart, selectionEnd); + } + } + } - const UniformTextSection* lastSection = 0; + const UniformTextSection* lastSection = 0; - while (i.next() && i.lineY < clip.getBottom()) - { - if (i.lineY + i.lineHeight >= clip.getY()) - { - if (selectionEnd >= i.indexInText - && selectionStart <= i.indexInText + i.atom->numChars) - { - i.drawSelectedText (g, selectionStart, selectionEnd, selectedTextColour); - lastSection = 0; - } - else - { - i.draw (g, lastSection); - } - } - } - } + while (i.next() && i.lineY < clip.getBottom()) + { + if (i.lineY + i.lineHeight >= clip.getY()) + { + if (selectionEnd >= i.indexInText + && selectionStart <= i.indexInText + i.atom->numChars) + { + i.drawSelectedText (g, selectionStart, selectionEnd, selectedTextColour); + lastSection = 0; + } + else + { + i.draw (g, lastSection); + } + } + } + } } void TextEditor::paint (Graphics& g) { - getLookAndFeel().fillTextEditorBackground (g, getWidth(), getHeight(), *this); + getLookAndFeel().fillTextEditorBackground (g, getWidth(), getHeight(), *this); } void TextEditor::paintOverChildren (Graphics& g) { - if (caretFlashState - && hasKeyboardFocus (false) - && caretVisible - && ! isReadOnly()) - { - g.setColour (findColour (caretColourId)); + if (caretFlashState + && hasKeyboardFocus (false) + && caretVisible + && ! isReadOnly()) + { + g.setColour (findColour (caretColourId)); - g.fillRect (borderSize.getLeft() + textHolder->getX() + leftIndent + cursorX, - borderSize.getTop() + textHolder->getY() + topIndent + cursorY, - 2.0f, cursorHeight); - } + g.fillRect (borderSize.getLeft() + textHolder->getX() + leftIndent + cursorX, + borderSize.getTop() + textHolder->getY() + topIndent + cursorY, + 2.0f, cursorHeight); + } - if (textToShowWhenEmpty.isNotEmpty() - && (! hasKeyboardFocus (false)) - && getTotalNumChars() == 0) - { - g.setColour (colourForTextWhenEmpty); - g.setFont (getFont()); + if (textToShowWhenEmpty.isNotEmpty() + && (! hasKeyboardFocus (false)) + && getTotalNumChars() == 0) + { + g.setColour (colourForTextWhenEmpty); + g.setFont (getFont()); - if (isMultiLine()) - { - g.drawText (textToShowWhenEmpty, - 0, 0, getWidth(), getHeight(), - Justification::centred, true); - } - else - { - g.drawText (textToShowWhenEmpty, - leftIndent, topIndent, - viewport->getWidth() - leftIndent, - viewport->getHeight() - topIndent, - Justification::centredLeft, true); - } - } + if (isMultiLine()) + { + g.drawText (textToShowWhenEmpty, + 0, 0, getWidth(), getHeight(), + Justification::centred, true); + } + else + { + g.drawText (textToShowWhenEmpty, + leftIndent, topIndent, + viewport->getWidth() - leftIndent, + viewport->getHeight() - topIndent, + Justification::centredLeft, true); + } + } - getLookAndFeel().drawTextEditorOutline (g, getWidth(), getHeight(), *this); + getLookAndFeel().drawTextEditorOutline (g, getWidth(), getHeight(), *this); } void TextEditor::mouseDown (const MouseEvent& e) { - beginDragAutoRepeat (100); - newTransaction(); + beginDragAutoRepeat (100); + newTransaction(); - if (wasFocused || ! selectAllTextWhenFocused) - { - if (! (popupMenuEnabled && e.mods.isPopupMenu())) - { - moveCursorTo (getTextIndexAt (e.x, e.y), - e.mods.isShiftDown()); - } - else - { - PopupMenu m; - m.setLookAndFeel (&getLookAndFeel()); - addPopupMenuItems (m, &e); + if (wasFocused || ! selectAllTextWhenFocused) + { + if (! (popupMenuEnabled && e.mods.isPopupMenu())) + { + moveCursorTo (getTextIndexAt (e.x, e.y), + e.mods.isShiftDown()); + } + else + { + PopupMenu m; + m.setLookAndFeel (&getLookAndFeel()); + addPopupMenuItems (m, &e); - menuActive = true; - const int result = m.show(); - menuActive = false; + menuActive = true; + const int result = m.show(); + menuActive = false; - if (result != 0) - performPopupMenuAction (result); - } - } + if (result != 0) + performPopupMenuAction (result); + } + } } void TextEditor::mouseDrag (const MouseEvent& e) { - if (wasFocused || ! selectAllTextWhenFocused) - { - if (! (popupMenuEnabled && e.mods.isPopupMenu())) - { - moveCursorTo (getTextIndexAt (e.x, e.y), true); - } - } + if (wasFocused || ! selectAllTextWhenFocused) + { + if (! (popupMenuEnabled && e.mods.isPopupMenu())) + { + moveCursorTo (getTextIndexAt (e.x, e.y), true); + } + } } void TextEditor::mouseUp (const MouseEvent& e) { - newTransaction(); - textHolder->startTimer (flashSpeedIntervalMs); + newTransaction(); + textHolder->startTimer (flashSpeedIntervalMs); - if (wasFocused || ! selectAllTextWhenFocused) - { - if (e.mouseWasClicked() && ! (popupMenuEnabled && e.mods.isPopupMenu())) - { - moveCaret (getTextIndexAt (e.x, e.y)); - } - } + if (wasFocused || ! selectAllTextWhenFocused) + { + if (e.mouseWasClicked() && ! (popupMenuEnabled && e.mods.isPopupMenu())) + { + moveCaret (getTextIndexAt (e.x, e.y)); + } + } - wasFocused = true; + wasFocused = true; } void TextEditor::mouseDoubleClick (const MouseEvent& e) { - int tokenEnd = getTextIndexAt (e.x, e.y); - int tokenStart = tokenEnd; + int tokenEnd = getTextIndexAt (e.x, e.y); + int tokenStart = tokenEnd; - if (e.getNumberOfClicks() > 3) - { - tokenStart = 0; - tokenEnd = getTotalNumChars(); - } - else - { - const String t (getText()); - const int totalLength = getTotalNumChars(); + if (e.getNumberOfClicks() > 3) + { + tokenStart = 0; + tokenEnd = getTotalNumChars(); + } + else + { + const String t (getText()); + const int totalLength = getTotalNumChars(); - while (tokenEnd < totalLength) - { - if (CharacterFunctions::isLetterOrDigit (t [tokenEnd])) - ++tokenEnd; - else - break; - } + while (tokenEnd < totalLength) + { + if (CharacterFunctions::isLetterOrDigit (t [tokenEnd])) + ++tokenEnd; + else + break; + } - tokenStart = tokenEnd; + tokenStart = tokenEnd; - while (tokenStart > 0) - { - if (CharacterFunctions::isLetterOrDigit (t [tokenStart - 1])) - --tokenStart; - else - break; - } + while (tokenStart > 0) + { + if (CharacterFunctions::isLetterOrDigit (t [tokenStart - 1])) + --tokenStart; + else + break; + } - if (e.getNumberOfClicks() > 2) - { - while (tokenEnd < totalLength) - { - if (t [tokenEnd] != T('\r') && t [tokenEnd] != T('\n')) - ++tokenEnd; - else - break; - } + if (e.getNumberOfClicks() > 2) + { + while (tokenEnd < totalLength) + { + if (t [tokenEnd] != T('\r') && t [tokenEnd] != T('\n')) + ++tokenEnd; + else + break; + } - while (tokenStart > 0) - { - if (t [tokenStart - 1] != T('\r') && t [tokenStart - 1] != T('\n')) - --tokenStart; - else - break; - } - } - } + while (tokenStart > 0) + { + if (t [tokenStart - 1] != T('\r') && t [tokenStart - 1] != T('\n')) + --tokenStart; + else + break; + } + } + } - moveCursorTo (tokenEnd, false); - moveCursorTo (tokenStart, true); + moveCursorTo (tokenEnd, false); + moveCursorTo (tokenStart, true); } void TextEditor::mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY) { - if (! viewport->useMouseWheelMoveIfNeeded (e, wheelIncrementX, wheelIncrementY)) - Component::mouseWheelMove (e, wheelIncrementX, wheelIncrementY); + if (! viewport->useMouseWheelMoveIfNeeded (e, wheelIncrementX, wheelIncrementY)) + Component::mouseWheelMove (e, wheelIncrementX, wheelIncrementY); } bool TextEditor::keyPressed (const KeyPress& key) { - if (isReadOnly() && key != KeyPress (T('c'), ModifierKeys::commandModifier, 0)) - return false; + if (isReadOnly() && key != KeyPress (T('c'), ModifierKeys::commandModifier, 0)) + return false; - const bool moveInWholeWordSteps = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown(); + const bool moveInWholeWordSteps = key.getModifiers().isCtrlDown() || key.getModifiers().isAltDown(); - if (key.isKeyCode (KeyPress::leftKey) - || key.isKeyCode (KeyPress::upKey)) - { - newTransaction(); + if (key.isKeyCode (KeyPress::leftKey) + || key.isKeyCode (KeyPress::upKey)) + { + newTransaction(); - int newPos; + int newPos; - if (isMultiLine() && key.isKeyCode (KeyPress::upKey)) - newPos = indexAtPosition (cursorX, cursorY - 1); - else if (moveInWholeWordSteps) - newPos = findWordBreakBefore (getCaretPosition()); - else - newPos = getCaretPosition() - 1; + if (isMultiLine() && key.isKeyCode (KeyPress::upKey)) + newPos = indexAtPosition (cursorX, cursorY - 1); + else if (moveInWholeWordSteps) + newPos = findWordBreakBefore (getCaretPosition()); + else + newPos = getCaretPosition() - 1; - moveCursorTo (newPos, key.getModifiers().isShiftDown()); - } - else if (key.isKeyCode (KeyPress::rightKey) - || key.isKeyCode (KeyPress::downKey)) - { - newTransaction(); + moveCursorTo (newPos, key.getModifiers().isShiftDown()); + } + else if (key.isKeyCode (KeyPress::rightKey) + || key.isKeyCode (KeyPress::downKey)) + { + newTransaction(); - int newPos; + int newPos; - if (isMultiLine() && key.isKeyCode (KeyPress::downKey)) - newPos = indexAtPosition (cursorX, cursorY + cursorHeight + 1); - else if (moveInWholeWordSteps) - newPos = findWordBreakAfter (getCaretPosition()); - else - newPos = getCaretPosition() + 1; + if (isMultiLine() && key.isKeyCode (KeyPress::downKey)) + newPos = indexAtPosition (cursorX, cursorY + cursorHeight + 1); + else if (moveInWholeWordSteps) + newPos = findWordBreakAfter (getCaretPosition()); + else + newPos = getCaretPosition() + 1; - moveCursorTo (newPos, key.getModifiers().isShiftDown()); - } - else if (key.isKeyCode (KeyPress::pageDownKey) && isMultiLine()) - { - newTransaction(); + moveCursorTo (newPos, key.getModifiers().isShiftDown()); + } + else if (key.isKeyCode (KeyPress::pageDownKey) && isMultiLine()) + { + newTransaction(); - moveCursorTo (indexAtPosition (cursorX, cursorY + cursorHeight + viewport->getViewHeight()), - key.getModifiers().isShiftDown()); - } - else if (key.isKeyCode (KeyPress::pageUpKey) && isMultiLine()) - { - newTransaction(); + moveCursorTo (indexAtPosition (cursorX, cursorY + cursorHeight + viewport->getViewHeight()), + key.getModifiers().isShiftDown()); + } + else if (key.isKeyCode (KeyPress::pageUpKey) && isMultiLine()) + { + newTransaction(); - moveCursorTo (indexAtPosition (cursorX, cursorY - viewport->getViewHeight()), - key.getModifiers().isShiftDown()); - } - else if (key.isKeyCode (KeyPress::homeKey)) - { - newTransaction(); + moveCursorTo (indexAtPosition (cursorX, cursorY - viewport->getViewHeight()), + key.getModifiers().isShiftDown()); + } + else if (key.isKeyCode (KeyPress::homeKey)) + { + newTransaction(); - if (isMultiLine() && ! moveInWholeWordSteps) - moveCursorTo (indexAtPosition (0.0f, cursorY), - key.getModifiers().isShiftDown()); - else - moveCursorTo (0, key.getModifiers().isShiftDown()); - } - else if (key.isKeyCode (KeyPress::endKey)) - { - newTransaction(); + if (isMultiLine() && ! moveInWholeWordSteps) + moveCursorTo (indexAtPosition (0.0f, cursorY), + key.getModifiers().isShiftDown()); + else + moveCursorTo (0, key.getModifiers().isShiftDown()); + } + else if (key.isKeyCode (KeyPress::endKey)) + { + newTransaction(); - if (isMultiLine() && ! moveInWholeWordSteps) - moveCursorTo (indexAtPosition ((float) textHolder->getWidth(), cursorY), - key.getModifiers().isShiftDown()); - else - moveCursorTo (getTotalNumChars(), key.getModifiers().isShiftDown()); - } - else if (key.isKeyCode (KeyPress::backspaceKey)) - { - if (moveInWholeWordSteps) - { - moveCursorTo (findWordBreakBefore (getCaretPosition()), true); - } - else - { - if (selectionStart == selectionEnd && selectionStart > 0) - --selectionStart; - } + if (isMultiLine() && ! moveInWholeWordSteps) + moveCursorTo (indexAtPosition ((float) textHolder->getWidth(), cursorY), + key.getModifiers().isShiftDown()); + else + moveCursorTo (getTotalNumChars(), key.getModifiers().isShiftDown()); + } + else if (key.isKeyCode (KeyPress::backspaceKey)) + { + if (moveInWholeWordSteps) + { + moveCursorTo (findWordBreakBefore (getCaretPosition()), true); + } + else + { + if (selectionStart == selectionEnd && selectionStart > 0) + --selectionStart; + } - cut(); - } - else if (key.isKeyCode (KeyPress::deleteKey)) - { - if (key.getModifiers().isShiftDown()) - copy(); + cut(); + } + else if (key.isKeyCode (KeyPress::deleteKey)) + { + if (key.getModifiers().isShiftDown()) + copy(); - if (selectionStart == selectionEnd - && selectionEnd < getTotalNumChars()) - { - ++selectionEnd; - } + if (selectionStart == selectionEnd + && selectionEnd < getTotalNumChars()) + { + ++selectionEnd; + } - cut(); - } - else if (key == KeyPress (T('c'), ModifierKeys::commandModifier, 0) - || key == KeyPress (KeyPress::insertKey, ModifierKeys::ctrlModifier, 0)) - { - newTransaction(); - copy(); - } - else if (key == KeyPress (T('x'), ModifierKeys::commandModifier, 0)) - { - newTransaction(); - copy(); - cut(); - } - else if (key == KeyPress (T('v'), ModifierKeys::commandModifier, 0) - || key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0)) - { - newTransaction(); - paste(); - } - else if (key == KeyPress (T('z'), ModifierKeys::commandModifier, 0)) - { - newTransaction(); - doUndoRedo (false); - } - else if (key == KeyPress (T('y'), ModifierKeys::commandModifier, 0)) - { - newTransaction(); - doUndoRedo (true); - } - else if (key == KeyPress (T('a'), ModifierKeys::commandModifier, 0)) - { - newTransaction(); - moveCursorTo (getTotalNumChars(), false); - moveCursorTo (0, true); - } - else if (key == KeyPress::returnKey) - { - newTransaction(); + cut(); + } + else if (key == KeyPress (T('c'), ModifierKeys::commandModifier, 0) + || key == KeyPress (KeyPress::insertKey, ModifierKeys::ctrlModifier, 0)) + { + newTransaction(); + copy(); + } + else if (key == KeyPress (T('x'), ModifierKeys::commandModifier, 0)) + { + newTransaction(); + copy(); + cut(); + } + else if (key == KeyPress (T('v'), ModifierKeys::commandModifier, 0) + || key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0)) + { + newTransaction(); + paste(); + } + else if (key == KeyPress (T('z'), ModifierKeys::commandModifier, 0)) + { + newTransaction(); + doUndoRedo (false); + } + else if (key == KeyPress (T('y'), ModifierKeys::commandModifier, 0)) + { + newTransaction(); + doUndoRedo (true); + } + else if (key == KeyPress (T('a'), ModifierKeys::commandModifier, 0)) + { + newTransaction(); + moveCursorTo (getTotalNumChars(), false); + moveCursorTo (0, true); + } + else if (key == KeyPress::returnKey) + { + newTransaction(); - if (returnKeyStartsNewLine) - insertTextAtCursor (T("\n")); - else - returnPressed(); - } - else if (key.isKeyCode (KeyPress::escapeKey)) - { - newTransaction(); - moveCursorTo (getCaretPosition(), false); - escapePressed(); - } - else if (key.getTextCharacter() >= ' ' - || (tabKeyUsed && (key.getTextCharacter() == '\t'))) - { - insertTextAtCursor (String::charToString (key.getTextCharacter())); + if (returnKeyStartsNewLine) + insertTextAtCursor (T("\n")); + else + returnPressed(); + } + else if (key.isKeyCode (KeyPress::escapeKey)) + { + newTransaction(); + moveCursorTo (getCaretPosition(), false); + escapePressed(); + } + else if (key.getTextCharacter() >= ' ' + || (tabKeyUsed && (key.getTextCharacter() == '\t'))) + { + insertTextAtCursor (String::charToString (key.getTextCharacter())); - lastTransactionTime = Time::getApproximateMillisecondCounter(); - } - else - { - return false; - } + lastTransactionTime = Time::getApproximateMillisecondCounter(); + } + else + { + return false; + } - return true; + return true; } bool TextEditor::keyStateChanged (const bool isKeyDown) { - if (! isKeyDown) - return false; + if (! isKeyDown) + return false; #if JUCE_WIN32 - if (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0).isCurrentlyDown()) - return false; // We need to explicitly allow alt-F4 to pass through on Windows + if (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0).isCurrentlyDown()) + return false; // We need to explicitly allow alt-F4 to pass through on Windows #endif - // (overridden to avoid forwarding key events to the parent) - return ! ModifierKeys::getCurrentModifiers().isCommandDown(); + // (overridden to avoid forwarding key events to the parent) + return ! ModifierKeys::getCurrentModifiers().isCommandDown(); } const int baseMenuItemID = 0x7fff0000; void TextEditor::addPopupMenuItems (PopupMenu& m, const MouseEvent*) { - const bool writable = ! isReadOnly(); + const bool writable = ! isReadOnly(); - if (passwordCharacter == 0) - { - m.addItem (baseMenuItemID + 1, TRANS("cut"), writable); - m.addItem (baseMenuItemID + 2, TRANS("copy"), selectionStart < selectionEnd); - m.addItem (baseMenuItemID + 3, TRANS("paste"), writable); - } + if (passwordCharacter == 0) + { + m.addItem (baseMenuItemID + 1, TRANS("cut"), writable); + m.addItem (baseMenuItemID + 2, TRANS("copy"), selectionStart < selectionEnd); + m.addItem (baseMenuItemID + 3, TRANS("paste"), writable); + } - m.addItem (baseMenuItemID + 4, TRANS("delete"), writable); - m.addSeparator(); - m.addItem (baseMenuItemID + 5, TRANS("select all")); - m.addSeparator(); - m.addItem (baseMenuItemID + 6, TRANS("undo"), undoManager.canUndo()); - m.addItem (baseMenuItemID + 7, TRANS("redo"), undoManager.canRedo()); + m.addItem (baseMenuItemID + 4, TRANS("delete"), writable); + m.addSeparator(); + m.addItem (baseMenuItemID + 5, TRANS("select all")); + m.addSeparator(); + m.addItem (baseMenuItemID + 6, TRANS("undo"), undoManager.canUndo()); + m.addItem (baseMenuItemID + 7, TRANS("redo"), undoManager.canRedo()); } void TextEditor::performPopupMenuAction (const int menuItemID) { - switch (menuItemID) - { - case baseMenuItemID + 1: - copy(); - cut(); - break; + switch (menuItemID) + { + case baseMenuItemID + 1: + copy(); + cut(); + break; - case baseMenuItemID + 2: - copy(); - break; + case baseMenuItemID + 2: + copy(); + break; - case baseMenuItemID + 3: - paste(); - break; + case baseMenuItemID + 3: + paste(); + break; - case baseMenuItemID + 4: - cut(); - break; + case baseMenuItemID + 4: + cut(); + break; - case baseMenuItemID + 5: - moveCursorTo (getTotalNumChars(), false); - moveCursorTo (0, true); - break; + case baseMenuItemID + 5: + moveCursorTo (getTotalNumChars(), false); + moveCursorTo (0, true); + break; - case baseMenuItemID + 6: - doUndoRedo (false); - break; + case baseMenuItemID + 6: + doUndoRedo (false); + break; - case baseMenuItemID + 7: - doUndoRedo (true); - break; + case baseMenuItemID + 7: + doUndoRedo (true); + break; - default: - break; - } + default: + break; + } } void TextEditor::focusGained (FocusChangeType) { - newTransaction(); + newTransaction(); - caretFlashState = true; + caretFlashState = true; - if (selectAllTextWhenFocused) - { - moveCursorTo (0, false); - moveCursorTo (getTotalNumChars(), true); - } + if (selectAllTextWhenFocused) + { + moveCursorTo (0, false); + moveCursorTo (getTotalNumChars(), true); + } - repaint(); + repaint(); - if (caretVisible) - textHolder->startTimer (flashSpeedIntervalMs); + if (caretVisible) + textHolder->startTimer (flashSpeedIntervalMs); - ComponentPeer* const peer = getPeer(); - if (peer != 0 && ! isReadOnly()) - peer->textInputRequired (getScreenX() - peer->getScreenX(), - getScreenY() - peer->getScreenY()); + ComponentPeer* const peer = getPeer(); + if (peer != 0 && ! isReadOnly()) + peer->textInputRequired (getScreenX() - peer->getScreenX(), + getScreenY() - peer->getScreenY()); } void TextEditor::focusLost (FocusChangeType) { - newTransaction(); + newTransaction(); - wasFocused = false; - textHolder->stopTimer(); - caretFlashState = false; + wasFocused = false; + textHolder->stopTimer(); + caretFlashState = false; - postCommandMessage (focusLossMessageId); - repaint(); + postCommandMessage (focusLossMessageId); + repaint(); } void TextEditor::resized() { - viewport->setBoundsInset (borderSize); - viewport->setSingleStepSizes (16, roundFloatToInt (currentFont.getHeight())); + viewport->setBoundsInset (borderSize); + viewport->setSingleStepSizes (16, roundToInt (currentFont.getHeight())); - updateTextHolderSize(); + updateTextHolderSize(); - if (! isMultiLine()) - { - scrollToMakeSureCursorIsVisible(); - } - else - { - updateCaretPosition(); - } + if (! isMultiLine()) + { + scrollToMakeSureCursorIsVisible(); + } + else + { + updateCaretPosition(); + } } void TextEditor::handleCommandMessage (const int commandId) { - const ComponentDeletionWatcher deletionChecker (this); + const ComponentDeletionWatcher deletionChecker (this); - for (int i = listeners.size(); --i >= 0;) - { - TextEditorListener* const tl = (TextEditorListener*) listeners [i]; + for (int i = listeners.size(); --i >= 0;) + { + TextEditorListener* const tl = (TextEditorListener*) listeners [i]; - if (tl != 0) - { - switch (commandId) - { - case textChangeMessageId: - tl->textEditorTextChanged (*this); - break; + if (tl != 0) + { + switch (commandId) + { + case textChangeMessageId: + tl->textEditorTextChanged (*this); + break; - case returnKeyMessageId: - tl->textEditorReturnKeyPressed (*this); - break; + case returnKeyMessageId: + tl->textEditorReturnKeyPressed (*this); + break; - case escapeKeyMessageId: - tl->textEditorEscapeKeyPressed (*this); - break; + case escapeKeyMessageId: + tl->textEditorEscapeKeyPressed (*this); + break; - case focusLossMessageId: - tl->textEditorFocusLost (*this); - break; + case focusLossMessageId: + tl->textEditorFocusLost (*this); + break; - default: - jassertfalse - break; - } + default: + jassertfalse + break; + } - if (i > 0 && deletionChecker.hasBeenDeleted()) - return; - } - } + if (i > 0 && deletionChecker.hasBeenDeleted()) + return; + } + } } void TextEditor::enablementChanged() { - setMouseCursor (MouseCursor (isReadOnly() ? MouseCursor::NormalCursor - : MouseCursor::IBeamCursor)); - repaint(); + setMouseCursor (MouseCursor (isReadOnly() ? MouseCursor::NormalCursor + : MouseCursor::IBeamCursor)); + repaint(); } void TextEditor::clearInternal (UndoManager* const um) { - remove (0, getTotalNumChars(), um, caretPosition); + remove (0, getTotalNumChars(), um, caretPosition); } void TextEditor::insert (const String& text, - const int insertIndex, - const Font& font, - const Colour& colour, - UndoManager* const um, - const int caretPositionToMoveTo) + const int insertIndex, + const Font& font, + const Colour& colour, + UndoManager* const um, + const int caretPositionToMoveTo) { - if (text.isNotEmpty()) - { - if (um != 0) - { - um->perform (new TextEditorInsertAction (*this, - text, - insertIndex, - font, - colour, - caretPosition, - caretPositionToMoveTo)); - } - else - { - repaintText (insertIndex, -1); // must do this before and after changing the data, in case - // a line gets moved due to word wrap + if (text.isNotEmpty()) + { + if (um != 0) + { + um->perform (new TextEditorInsertAction (*this, + text, + insertIndex, + font, + colour, + caretPosition, + caretPositionToMoveTo)); + } + else + { + repaintText (insertIndex, -1); // must do this before and after changing the data, in case + // a line gets moved due to word wrap - int index = 0; - int nextIndex = 0; + int index = 0; + int nextIndex = 0; - for (int i = 0; i < sections.size(); ++i) - { - nextIndex = index + ((UniformTextSection*) sections.getUnchecked(i))->getTotalLength(); + for (int i = 0; i < sections.size(); ++i) + { + nextIndex = index + ((UniformTextSection*) sections.getUnchecked(i))->getTotalLength(); - if (insertIndex == index) - { - sections.insert (i, new UniformTextSection (text, - font, colour, - passwordCharacter)); - break; - } - else if (insertIndex > index && insertIndex < nextIndex) - { - splitSection (i, insertIndex - index); - sections.insert (i + 1, new UniformTextSection (text, - font, colour, - passwordCharacter)); - break; - } + if (insertIndex == index) + { + sections.insert (i, new UniformTextSection (text, + font, colour, + passwordCharacter)); + break; + } + else if (insertIndex > index && insertIndex < nextIndex) + { + splitSection (i, insertIndex - index); + sections.insert (i + 1, new UniformTextSection (text, + font, colour, + passwordCharacter)); + break; + } - index = nextIndex; - } + index = nextIndex; + } - if (nextIndex == insertIndex) - sections.add (new UniformTextSection (text, - font, colour, - passwordCharacter)); + if (nextIndex == insertIndex) + sections.add (new UniformTextSection (text, + font, colour, + passwordCharacter)); - coalesceSimilarSections(); - totalNumChars = -1; - valueTextNeedsUpdating = true; + coalesceSimilarSections(); + totalNumChars = -1; + valueTextNeedsUpdating = true; - moveCursorTo (caretPositionToMoveTo, false); + moveCursorTo (caretPositionToMoveTo, false); - repaintText (insertIndex, -1); - } - } + repaintText (insertIndex, -1); + } + } } void TextEditor::reinsert (const int insertIndex, - const VoidArray& sectionsToInsert) + const VoidArray& sectionsToInsert) { - int index = 0; - int nextIndex = 0; + int index = 0; + int nextIndex = 0; - for (int i = 0; i < sections.size(); ++i) - { - nextIndex = index + ((UniformTextSection*) sections.getUnchecked(i))->getTotalLength(); + for (int i = 0; i < sections.size(); ++i) + { + nextIndex = index + ((UniformTextSection*) sections.getUnchecked(i))->getTotalLength(); - if (insertIndex == index) - { - for (int j = sectionsToInsert.size(); --j >= 0;) - sections.insert (i, new UniformTextSection (*(UniformTextSection*) sectionsToInsert.getUnchecked(j))); + if (insertIndex == index) + { + for (int j = sectionsToInsert.size(); --j >= 0;) + sections.insert (i, new UniformTextSection (*(UniformTextSection*) sectionsToInsert.getUnchecked(j))); - break; - } - else if (insertIndex > index && insertIndex < nextIndex) - { - splitSection (i, insertIndex - index); + break; + } + else if (insertIndex > index && insertIndex < nextIndex) + { + splitSection (i, insertIndex - index); - for (int j = sectionsToInsert.size(); --j >= 0;) - sections.insert (i + 1, new UniformTextSection (*(UniformTextSection*) sectionsToInsert.getUnchecked(j))); + for (int j = sectionsToInsert.size(); --j >= 0;) + sections.insert (i + 1, new UniformTextSection (*(UniformTextSection*) sectionsToInsert.getUnchecked(j))); - break; - } + break; + } - index = nextIndex; - } + index = nextIndex; + } - if (nextIndex == insertIndex) - { - for (int j = 0; j < sectionsToInsert.size(); ++j) - sections.add (new UniformTextSection (*(UniformTextSection*) sectionsToInsert.getUnchecked(j))); - } + if (nextIndex == insertIndex) + { + for (int j = 0; j < sectionsToInsert.size(); ++j) + sections.add (new UniformTextSection (*(UniformTextSection*) sectionsToInsert.getUnchecked(j))); + } - coalesceSimilarSections(); - totalNumChars = -1; - valueTextNeedsUpdating = true; + coalesceSimilarSections(); + totalNumChars = -1; + valueTextNeedsUpdating = true; } void TextEditor::remove (const int startIndex, - int endIndex, - UndoManager* const um, - const int caretPositionToMoveTo) + int endIndex, + UndoManager* const um, + const int caretPositionToMoveTo) { - if (endIndex > startIndex) - { - int index = 0; + if (endIndex > startIndex) + { + int index = 0; - for (int i = 0; i < sections.size(); ++i) - { - const int nextIndex = index + ((UniformTextSection*) sections[i])->getTotalLength(); + for (int i = 0; i < sections.size(); ++i) + { + const int nextIndex = index + ((UniformTextSection*) sections[i])->getTotalLength(); - if (startIndex > index && startIndex < nextIndex) - { - splitSection (i, startIndex - index); - --i; - } - else if (endIndex > index && endIndex < nextIndex) - { - splitSection (i, endIndex - index); - --i; - } - else - { - index = nextIndex; + if (startIndex > index && startIndex < nextIndex) + { + splitSection (i, startIndex - index); + --i; + } + else if (endIndex > index && endIndex < nextIndex) + { + splitSection (i, endIndex - index); + --i; + } + else + { + index = nextIndex; - if (index > endIndex) - break; - } - } + if (index > endIndex) + break; + } + } - index = 0; + index = 0; - if (um != 0) - { - VoidArray removedSections; + if (um != 0) + { + VoidArray removedSections; - for (int i = 0; i < sections.size(); ++i) - { - if (endIndex <= startIndex) - break; + for (int i = 0; i < sections.size(); ++i) + { + if (endIndex <= startIndex) + break; - UniformTextSection* const section = (UniformTextSection*) sections.getUnchecked (i); + UniformTextSection* const section = (UniformTextSection*) sections.getUnchecked (i); - const int nextIndex = index + section->getTotalLength(); + const int nextIndex = index + section->getTotalLength(); - if (startIndex <= index && endIndex >= nextIndex) - removedSections.add (new UniformTextSection (*section)); + if (startIndex <= index && endIndex >= nextIndex) + removedSections.add (new UniformTextSection (*section)); - index = nextIndex; - } + index = nextIndex; + } - um->perform (new TextEditorRemoveAction (*this, - startIndex, - endIndex, - caretPosition, - caretPositionToMoveTo, - removedSections)); - } - else - { - for (int i = 0; i < sections.size(); ++i) - { - if (endIndex <= startIndex) - break; + um->perform (new TextEditorRemoveAction (*this, + startIndex, + endIndex, + caretPosition, + caretPositionToMoveTo, + removedSections)); + } + else + { + for (int i = 0; i < sections.size(); ++i) + { + if (endIndex <= startIndex) + break; - UniformTextSection* const section = (UniformTextSection*) sections.getUnchecked (i); + UniformTextSection* const section = (UniformTextSection*) sections.getUnchecked (i); - const int nextIndex = index + section->getTotalLength(); + const int nextIndex = index + section->getTotalLength(); - if (startIndex <= index && endIndex >= nextIndex) - { - sections.remove(i); - endIndex -= (nextIndex - index); - section->clear(); - delete section; - --i; - } - else - { - index = nextIndex; - } - } + if (startIndex <= index && endIndex >= nextIndex) + { + sections.remove(i); + endIndex -= (nextIndex - index); + section->clear(); + delete section; + --i; + } + else + { + index = nextIndex; + } + } - coalesceSimilarSections(); - totalNumChars = -1; - valueTextNeedsUpdating = true; + coalesceSimilarSections(); + totalNumChars = -1; + valueTextNeedsUpdating = true; - moveCursorTo (caretPositionToMoveTo, false); + moveCursorTo (caretPositionToMoveTo, false); - repaintText (startIndex, -1); - } - } + repaintText (startIndex, -1); + } + } } const String TextEditor::getText() const { - String t; - t.preallocateStorage (getTotalNumChars()); - String::Concatenator concatenator (t); + String t; + t.preallocateStorage (getTotalNumChars()); + String::Concatenator concatenator (t); - for (int i = 0; i < sections.size(); ++i) - ((const UniformTextSection*) sections.getUnchecked(i))->appendAllText (concatenator); + for (int i = 0; i < sections.size(); ++i) + ((const UniformTextSection*) sections.getUnchecked(i))->appendAllText (concatenator); - return t; + return t; } const String TextEditor::getTextSubstring (const int startCharacter, const int endCharacter) const { - String t; + String t; - if (endCharacter > startCharacter) - { - t.preallocateStorage (jmin (getTotalNumChars(), endCharacter - startCharacter)); - String::Concatenator concatenator (t); - int index = 0; + if (endCharacter > startCharacter) + { + t.preallocateStorage (jmin (getTotalNumChars(), endCharacter - startCharacter)); + String::Concatenator concatenator (t); + int index = 0; - for (int i = 0; i < sections.size(); ++i) - { - const UniformTextSection* const s = (const UniformTextSection*) sections.getUnchecked(i); - const int nextIndex = index + s->getTotalLength(); + for (int i = 0; i < sections.size(); ++i) + { + const UniformTextSection* const s = (const UniformTextSection*) sections.getUnchecked(i); + const int nextIndex = index + s->getTotalLength(); - if (startCharacter < nextIndex) - { - if (endCharacter <= index) - break; + if (startCharacter < nextIndex) + { + if (endCharacter <= index) + break; - s->appendSubstring (concatenator, - startCharacter - index, - endCharacter - index); - } + s->appendSubstring (concatenator, + startCharacter - index, + endCharacter - index); + } - index = nextIndex; - } - } + index = nextIndex; + } + } - return t; + return t; } const String TextEditor::getHighlightedText() const { - return getTextSubstring (selectionStart, selectionEnd); + return getTextSubstring (selectionStart, selectionEnd); } int TextEditor::getTotalNumChars() const { - if (totalNumChars < 0) - { - totalNumChars = 0; + if (totalNumChars < 0) + { + totalNumChars = 0; - for (int i = sections.size(); --i >= 0;) - totalNumChars += ((const UniformTextSection*) sections.getUnchecked(i))->getTotalLength(); - } + for (int i = sections.size(); --i >= 0;) + totalNumChars += ((const UniformTextSection*) sections.getUnchecked(i))->getTotalLength(); + } - return totalNumChars; + return totalNumChars; } bool TextEditor::isEmpty() const { - return getTotalNumChars() == 0; + return getTotalNumChars() == 0; } void TextEditor::getCharPosition (const int index, float& cx, float& cy, float& lineHeight) const { - const float wordWrapWidth = getWordWrapWidth(); + const float wordWrapWidth = getWordWrapWidth(); - if (wordWrapWidth > 0 && sections.size() > 0) - { - TextEditorIterator i (sections, wordWrapWidth, passwordCharacter); + if (wordWrapWidth > 0 && sections.size() > 0) + { + TextEditorIterator i (sections, wordWrapWidth, passwordCharacter); - i.getCharPosition (index, cx, cy, lineHeight); - } - else - { - cx = cy = 0; - lineHeight = currentFont.getHeight(); - } + i.getCharPosition (index, cx, cy, lineHeight); + } + else + { + cx = cy = 0; + lineHeight = currentFont.getHeight(); + } } int TextEditor::indexAtPosition (const float x, const float y) { - const float wordWrapWidth = getWordWrapWidth(); + const float wordWrapWidth = getWordWrapWidth(); - if (wordWrapWidth > 0) - { - TextEditorIterator i (sections, wordWrapWidth, passwordCharacter); + if (wordWrapWidth > 0) + { + TextEditorIterator i (sections, wordWrapWidth, passwordCharacter); - while (i.next()) - { - if (i.lineY + i.lineHeight > y) - { - if (i.lineY > y) - return jmax (0, i.indexInText - 1); + while (i.next()) + { + if (i.lineY + i.lineHeight > y) + { + if (i.lineY > y) + return jmax (0, i.indexInText - 1); - if (i.atomX >= x) - return i.indexInText; + if (i.atomX >= x) + return i.indexInText; - if (x < i.atomRight) - return i.xToIndex (x); - } - } - } + if (x < i.atomRight) + return i.xToIndex (x); + } + } + } - return getTotalNumChars(); + return getTotalNumChars(); } static int getCharacterCategory (const tchar character) { - return CharacterFunctions::isLetterOrDigit (character) - ? 2 : (CharacterFunctions::isWhitespace (character) ? 0 : 1); + return CharacterFunctions::isLetterOrDigit (character) + ? 2 : (CharacterFunctions::isWhitespace (character) ? 0 : 1); } int TextEditor::findWordBreakAfter (const int position) const { - const String t (getTextSubstring (position, position + 512)); - const int totalLength = t.length(); - int i = 0; + const String t (getTextSubstring (position, position + 512)); + const int totalLength = t.length(); + int i = 0; - while (i < totalLength && CharacterFunctions::isWhitespace (t[i])) - ++i; + while (i < totalLength && CharacterFunctions::isWhitespace (t[i])) + ++i; - const int type = getCharacterCategory (t[i]); + const int type = getCharacterCategory (t[i]); - while (i < totalLength && type == getCharacterCategory (t[i])) - ++i; + while (i < totalLength && type == getCharacterCategory (t[i])) + ++i; - while (i < totalLength && CharacterFunctions::isWhitespace (t[i])) - ++i; + while (i < totalLength && CharacterFunctions::isWhitespace (t[i])) + ++i; - return position + i; + return position + i; } int TextEditor::findWordBreakBefore (const int position) const { - if (position <= 0) - return 0; + if (position <= 0) + return 0; - const int startOfBuffer = jmax (0, position - 512); - const String t (getTextSubstring (startOfBuffer, position)); + const int startOfBuffer = jmax (0, position - 512); + const String t (getTextSubstring (startOfBuffer, position)); - int i = position - startOfBuffer; + int i = position - startOfBuffer; - while (i > 0 && CharacterFunctions::isWhitespace (t [i - 1])) - --i; + while (i > 0 && CharacterFunctions::isWhitespace (t [i - 1])) + --i; - if (i > 0) - { - const int type = getCharacterCategory (t [i - 1]); + if (i > 0) + { + const int type = getCharacterCategory (t [i - 1]); - while (i > 0 && type == getCharacterCategory (t [i - 1])) - --i; - } + while (i > 0 && type == getCharacterCategory (t [i - 1])) + --i; + } - jassert (startOfBuffer + i >= 0); - return startOfBuffer + i; + jassert (startOfBuffer + i >= 0); + return startOfBuffer + i; } void TextEditor::splitSection (const int sectionIndex, - const int charToSplitAt) + const int charToSplitAt) { - jassert (sections[sectionIndex] != 0); + jassert (sections[sectionIndex] != 0); - sections.insert (sectionIndex + 1, - ((UniformTextSection*) sections.getUnchecked (sectionIndex)) - ->split (charToSplitAt, passwordCharacter)); + sections.insert (sectionIndex + 1, + ((UniformTextSection*) sections.getUnchecked (sectionIndex)) + ->split (charToSplitAt, passwordCharacter)); } void TextEditor::coalesceSimilarSections() { - for (int i = 0; i < sections.size() - 1; ++i) - { - UniformTextSection* const s1 = (UniformTextSection*) sections.getUnchecked (i); - UniformTextSection* const s2 = (UniformTextSection*) sections.getUnchecked (i + 1); + for (int i = 0; i < sections.size() - 1; ++i) + { + UniformTextSection* const s1 = (UniformTextSection*) sections.getUnchecked (i); + UniformTextSection* const s2 = (UniformTextSection*) sections.getUnchecked (i + 1); - if (s1->font == s2->font - && s1->colour == s2->colour) - { - s1->append (*s2, passwordCharacter); - sections.remove (i + 1); - delete s2; - --i; - } - } + if (s1->font == s2->font + && s1->colour == s2->colour) + { + s1->append (*s2, passwordCharacter); + sections.remove (i + 1); + delete s2; + --i; + } + } } END_JUCE_NAMESPACE @@ -54247,653 +53951,653 @@ const tchar* const Toolbar::toolbarDragDescriptor = T("_toolbarItem_"); class ToolbarSpacerComp : public ToolbarItemComponent { public: - ToolbarSpacerComp (const int itemId_, const float fixedSize_, const bool drawBar_) - : ToolbarItemComponent (itemId_, String::empty, false), - fixedSize (fixedSize_), - drawBar (drawBar_) - { - } + ToolbarSpacerComp (const int itemId_, const float fixedSize_, const bool drawBar_) + : ToolbarItemComponent (itemId_, String::empty, false), + fixedSize (fixedSize_), + drawBar (drawBar_) + { + } - ~ToolbarSpacerComp() - { - } + ~ToolbarSpacerComp() + { + } - bool getToolbarItemSizes (int toolbarThickness, bool /*isToolbarVertical*/, - int& preferredSize, int& minSize, int& maxSize) - { - if (fixedSize <= 0) - { - preferredSize = toolbarThickness * 2; - minSize = 4; - maxSize = 32768; - } - else - { - maxSize = roundFloatToInt (toolbarThickness * fixedSize); - minSize = drawBar ? maxSize : jmin (4, maxSize); - preferredSize = maxSize; + bool getToolbarItemSizes (int toolbarThickness, bool /*isToolbarVertical*/, + int& preferredSize, int& minSize, int& maxSize) + { + if (fixedSize <= 0) + { + preferredSize = toolbarThickness * 2; + minSize = 4; + maxSize = 32768; + } + else + { + maxSize = roundToInt (toolbarThickness * fixedSize); + minSize = drawBar ? maxSize : jmin (4, maxSize); + preferredSize = maxSize; - if (getEditingMode() == editableOnPalette) - preferredSize = maxSize = toolbarThickness / (drawBar ? 3 : 2); - } + if (getEditingMode() == editableOnPalette) + preferredSize = maxSize = toolbarThickness / (drawBar ? 3 : 2); + } - return true; - } + return true; + } - void paintButtonArea (Graphics&, int, int, bool, bool) - { - } + void paintButtonArea (Graphics&, int, int, bool, bool) + { + } - void contentAreaChanged (const Rectangle&) - { - } + void contentAreaChanged (const Rectangle&) + { + } - int getResizeOrder() const throw() - { - return fixedSize <= 0 ? 0 : 1; - } + int getResizeOrder() const throw() + { + return fixedSize <= 0 ? 0 : 1; + } - void paint (Graphics& g) - { - const int w = getWidth(); - const int h = getHeight(); + void paint (Graphics& g) + { + const int w = getWidth(); + const int h = getHeight(); - if (drawBar) - { - g.setColour (findColour (Toolbar::separatorColourId, true)); + if (drawBar) + { + g.setColour (findColour (Toolbar::separatorColourId, true)); - const float thickness = 0.2f; + const float thickness = 0.2f; - if (isToolbarVertical()) - g.fillRect (w * 0.1f, h * (0.5f - thickness * 0.5f), w * 0.8f, h * thickness); - else - g.fillRect (w * (0.5f - thickness * 0.5f), h * 0.1f, w * thickness, h * 0.8f); - } + if (isToolbarVertical()) + g.fillRect (w * 0.1f, h * (0.5f - thickness * 0.5f), w * 0.8f, h * thickness); + else + g.fillRect (w * (0.5f - thickness * 0.5f), h * 0.1f, w * thickness, h * 0.8f); + } - if (getEditingMode() != normalMode && ! drawBar) - { - g.setColour (findColour (Toolbar::separatorColourId, true)); + if (getEditingMode() != normalMode && ! drawBar) + { + g.setColour (findColour (Toolbar::separatorColourId, true)); - const int indentX = jmin (2, (w - 3) / 2); - const int indentY = jmin (2, (h - 3) / 2); - g.drawRect (indentX, indentY, w - indentX * 2, h - indentY * 2, 1); + const int indentX = jmin (2, (w - 3) / 2); + const int indentY = jmin (2, (h - 3) / 2); + g.drawRect (indentX, indentY, w - indentX * 2, h - indentY * 2, 1); - if (fixedSize <= 0) - { - float x1, y1, x2, y2, x3, y3, x4, y4, hw, hl; + if (fixedSize <= 0) + { + float x1, y1, x2, y2, x3, y3, x4, y4, hw, hl; - if (isToolbarVertical()) - { - x1 = w * 0.5f; - y1 = h * 0.4f; - x2 = x1; - y2 = indentX * 2.0f; + if (isToolbarVertical()) + { + x1 = w * 0.5f; + y1 = h * 0.4f; + x2 = x1; + y2 = indentX * 2.0f; - x3 = x1; - y3 = h * 0.6f; - x4 = x1; - y4 = h - y2; + x3 = x1; + y3 = h * 0.6f; + x4 = x1; + y4 = h - y2; - hw = w * 0.15f; - hl = w * 0.2f; - } - else - { - x1 = w * 0.4f; - y1 = h * 0.5f; - x2 = indentX * 2.0f; - y2 = y1; + hw = w * 0.15f; + hl = w * 0.2f; + } + else + { + x1 = w * 0.4f; + y1 = h * 0.5f; + x2 = indentX * 2.0f; + y2 = y1; - x3 = w * 0.6f; - y3 = y1; - x4 = w - x2; - y4 = y1; + x3 = w * 0.6f; + y3 = y1; + x4 = w - x2; + y4 = y1; - hw = h * 0.15f; - hl = h * 0.2f; - } + hw = h * 0.15f; + hl = h * 0.2f; + } - Path p; - p.addArrow (x1, y1, x2, y2, 1.5f, hw, hl); - p.addArrow (x3, y3, x4, y4, 1.5f, hw, hl); - g.fillPath (p); - } - } - } + Path p; + p.addArrow (x1, y1, x2, y2, 1.5f, hw, hl); + p.addArrow (x3, y3, x4, y4, 1.5f, hw, hl); + g.fillPath (p); + } + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - const float fixedSize; - const bool drawBar; + const float fixedSize; + const bool drawBar; - ToolbarSpacerComp (const ToolbarSpacerComp&); - const ToolbarSpacerComp& operator= (const ToolbarSpacerComp&); + ToolbarSpacerComp (const ToolbarSpacerComp&); + const ToolbarSpacerComp& operator= (const ToolbarSpacerComp&); }; class MissingItemsComponent : public PopupMenuCustomComponent { public: - MissingItemsComponent (Toolbar& owner_, const int height_) - : PopupMenuCustomComponent (true), - owner (owner_), - height (height_) - { - for (int i = owner_.items.size(); --i >= 0;) - { - ToolbarItemComponent* const tc = owner_.items.getUnchecked(i); + MissingItemsComponent (Toolbar& owner_, const int height_) + : PopupMenuCustomComponent (true), + owner (owner_), + height (height_) + { + for (int i = owner_.items.size(); --i >= 0;) + { + ToolbarItemComponent* const tc = owner_.items.getUnchecked(i); - if (dynamic_cast (tc) == 0 && ! tc->isVisible()) - { - oldIndexes.insert (0, i); - addAndMakeVisible (tc, 0); - } - } + if (dynamic_cast (tc) == 0 && ! tc->isVisible()) + { + oldIndexes.insert (0, i); + addAndMakeVisible (tc, 0); + } + } - layout (400); - } + layout (400); + } - ~MissingItemsComponent() - { - // deleting the toolbar while its menu it open?? - jassert (owner.isValidComponent()); + ~MissingItemsComponent() + { + // deleting the toolbar while its menu it open?? + jassert (owner.isValidComponent()); - for (int i = 0; i < getNumChildComponents(); ++i) - { - ToolbarItemComponent* const tc = dynamic_cast (getChildComponent (i)); + for (int i = 0; i < getNumChildComponents(); ++i) + { + ToolbarItemComponent* const tc = dynamic_cast (getChildComponent (i)); - if (tc != 0) - { - tc->setVisible (false); - const int index = oldIndexes.remove (i); - owner.addChildComponent (tc, index); - --i; - } - } + if (tc != 0) + { + tc->setVisible (false); + const int index = oldIndexes.remove (i); + owner.addChildComponent (tc, index); + --i; + } + } - owner.resized(); - } + owner.resized(); + } - void layout (const int preferredWidth) - { - const int indent = 8; - int x = indent; - int y = indent; - int maxX = 0; + void layout (const int preferredWidth) + { + const int indent = 8; + int x = indent; + int y = indent; + int maxX = 0; - for (int i = 0; i < getNumChildComponents(); ++i) - { - ToolbarItemComponent* const tc = dynamic_cast (getChildComponent (i)); + for (int i = 0; i < getNumChildComponents(); ++i) + { + ToolbarItemComponent* const tc = dynamic_cast (getChildComponent (i)); - if (tc != 0) - { - int preferredSize = 1, minSize = 1, maxSize = 1; + if (tc != 0) + { + int preferredSize = 1, minSize = 1, maxSize = 1; - if (tc->getToolbarItemSizes (height, false, preferredSize, minSize, maxSize)) - { - if (x + preferredSize > preferredWidth && x > indent) - { - x = indent; - y += height; - } + if (tc->getToolbarItemSizes (height, false, preferredSize, minSize, maxSize)) + { + if (x + preferredSize > preferredWidth && x > indent) + { + x = indent; + y += height; + } - tc->setBounds (x, y, preferredSize, height); + tc->setBounds (x, y, preferredSize, height); - x += preferredSize; - maxX = jmax (maxX, x); - } - } - } + x += preferredSize; + maxX = jmax (maxX, x); + } + } + } - setSize (maxX + 8, y + height + 8); - } + setSize (maxX + 8, y + height + 8); + } - void getIdealSize (int& idealWidth, int& idealHeight) - { - idealWidth = getWidth(); - idealHeight = getHeight(); - } + void getIdealSize (int& idealWidth, int& idealHeight) + { + idealWidth = getWidth(); + idealHeight = getHeight(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - Toolbar& owner; - const int height; - Array oldIndexes; + Toolbar& owner; + const int height; + Array oldIndexes; - MissingItemsComponent (const MissingItemsComponent&); - const MissingItemsComponent& operator= (const MissingItemsComponent&); + MissingItemsComponent (const MissingItemsComponent&); + const MissingItemsComponent& operator= (const MissingItemsComponent&); }; Toolbar::Toolbar() - : vertical (false), - isEditingActive (false), - toolbarStyle (Toolbar::iconsOnly) + : vertical (false), + isEditingActive (false), + toolbarStyle (Toolbar::iconsOnly) { - addChildComponent (missingItemsButton = getLookAndFeel().createToolbarMissingItemsButton (*this)); + addChildComponent (missingItemsButton = getLookAndFeel().createToolbarMissingItemsButton (*this)); - missingItemsButton->setAlwaysOnTop (true); - missingItemsButton->addButtonListener (this); + missingItemsButton->setAlwaysOnTop (true); + missingItemsButton->addButtonListener (this); } Toolbar::~Toolbar() { - animator.cancelAllAnimations (true); - deleteAllChildren(); + animator.cancelAllAnimations (true); + deleteAllChildren(); } void Toolbar::setVertical (const bool shouldBeVertical) { - if (vertical != shouldBeVertical) - { - vertical = shouldBeVertical; - resized(); - } + if (vertical != shouldBeVertical) + { + vertical = shouldBeVertical; + resized(); + } } void Toolbar::clear() { - for (int i = items.size(); --i >= 0;) - { - ToolbarItemComponent* const tc = items.getUnchecked(i); - items.remove (i); - delete tc; - } + for (int i = items.size(); --i >= 0;) + { + ToolbarItemComponent* const tc = items.getUnchecked(i); + items.remove (i); + delete tc; + } - resized(); + resized(); } ToolbarItemComponent* Toolbar::createItem (ToolbarItemFactory& factory, const int itemId) { - if (itemId == ToolbarItemFactory::separatorBarId) - return new ToolbarSpacerComp (itemId, 0.1f, true); - else if (itemId == ToolbarItemFactory::spacerId) - return new ToolbarSpacerComp (itemId, 0.5f, false); - else if (itemId == ToolbarItemFactory::flexibleSpacerId) - return new ToolbarSpacerComp (itemId, 0, false); + if (itemId == ToolbarItemFactory::separatorBarId) + return new ToolbarSpacerComp (itemId, 0.1f, true); + else if (itemId == ToolbarItemFactory::spacerId) + return new ToolbarSpacerComp (itemId, 0.5f, false); + else if (itemId == ToolbarItemFactory::flexibleSpacerId) + return new ToolbarSpacerComp (itemId, 0, false); - return factory.createItem (itemId); + return factory.createItem (itemId); } void Toolbar::addItemInternal (ToolbarItemFactory& factory, - const int itemId, - const int insertIndex) + const int itemId, + const int insertIndex) { - // An ID can't be zero - this might indicate a mistake somewhere? - jassert (itemId != 0); + // An ID can't be zero - this might indicate a mistake somewhere? + jassert (itemId != 0); - ToolbarItemComponent* const tc = createItem (factory, itemId); + ToolbarItemComponent* const tc = createItem (factory, itemId); - if (tc != 0) - { + if (tc != 0) + { #ifdef JUCE_DEBUG - Array allowedIds; - factory.getAllToolbarItemIds (allowedIds); + Array allowedIds; + factory.getAllToolbarItemIds (allowedIds); - // If your factory can create an item for a given ID, it must also return - // that ID from its getAllToolbarItemIds() method! - jassert (allowedIds.contains (itemId)); + // If your factory can create an item for a given ID, it must also return + // that ID from its getAllToolbarItemIds() method! + jassert (allowedIds.contains (itemId)); #endif - items.insert (insertIndex, tc); - addAndMakeVisible (tc, insertIndex); - } + items.insert (insertIndex, tc); + addAndMakeVisible (tc, insertIndex); + } } void Toolbar::addItem (ToolbarItemFactory& factory, - const int itemId, - const int insertIndex) + const int itemId, + const int insertIndex) { - addItemInternal (factory, itemId, insertIndex); - resized(); + addItemInternal (factory, itemId, insertIndex); + resized(); } void Toolbar::addDefaultItems (ToolbarItemFactory& factoryToUse) { - Array ids; - factoryToUse.getDefaultItemSet (ids); + Array ids; + factoryToUse.getDefaultItemSet (ids); - clear(); + clear(); - for (int i = 0; i < ids.size(); ++i) - addItemInternal (factoryToUse, ids.getUnchecked (i), -1); + for (int i = 0; i < ids.size(); ++i) + addItemInternal (factoryToUse, ids.getUnchecked (i), -1); - resized(); + resized(); } void Toolbar::removeToolbarItem (const int itemIndex) { - ToolbarItemComponent* const tc = getItemComponent (itemIndex); + ToolbarItemComponent* const tc = getItemComponent (itemIndex); - if (tc != 0) - { - items.removeValue (tc); - delete tc; - resized(); - } + if (tc != 0) + { + items.removeValue (tc); + delete tc; + resized(); + } } int Toolbar::getNumItems() const throw() { - return items.size(); + return items.size(); } int Toolbar::getItemId (const int itemIndex) const throw() { - ToolbarItemComponent* const tc = getItemComponent (itemIndex); - return tc != 0 ? tc->getItemId() : 0; + ToolbarItemComponent* const tc = getItemComponent (itemIndex); + return tc != 0 ? tc->getItemId() : 0; } ToolbarItemComponent* Toolbar::getItemComponent (const int itemIndex) const throw() { - return items [itemIndex]; + return items [itemIndex]; } ToolbarItemComponent* Toolbar::getNextActiveComponent (int index, const int delta) const { - for (;;) - { - index += delta; - ToolbarItemComponent* const tc = getItemComponent (index); + for (;;) + { + index += delta; + ToolbarItemComponent* const tc = getItemComponent (index); - if (tc == 0) - break; + if (tc == 0) + break; - if (tc->isActive) - return tc; - } + if (tc->isActive) + return tc; + } - return 0; + return 0; } void Toolbar::setStyle (const ToolbarItemStyle& newStyle) { - if (toolbarStyle != newStyle) - { - toolbarStyle = newStyle; - updateAllItemPositions (false); - } + if (toolbarStyle != newStyle) + { + toolbarStyle = newStyle; + updateAllItemPositions (false); + } } const String Toolbar::toString() const { - String s (T("TB:")); + String s (T("TB:")); - for (int i = 0; i < getNumItems(); ++i) - s << getItemId(i) << T(' '); + for (int i = 0; i < getNumItems(); ++i) + s << getItemId(i) << T(' '); - return s.trimEnd(); + return s.trimEnd(); } bool Toolbar::restoreFromString (ToolbarItemFactory& factoryToUse, - const String& savedVersion) + const String& savedVersion) { - if (! savedVersion.startsWith (T("TB:"))) - return false; + if (! savedVersion.startsWith (T("TB:"))) + return false; - StringArray tokens; - tokens.addTokens (savedVersion.substring (3), false); + StringArray tokens; + tokens.addTokens (savedVersion.substring (3), false); - clear(); + clear(); - for (int i = 0; i < tokens.size(); ++i) - addItemInternal (factoryToUse, tokens[i].getIntValue(), -1); + for (int i = 0; i < tokens.size(); ++i) + addItemInternal (factoryToUse, tokens[i].getIntValue(), -1); - resized(); - return true; + resized(); + return true; } void Toolbar::paint (Graphics& g) { - getLookAndFeel().paintToolbarBackground (g, getWidth(), getHeight(), *this); + getLookAndFeel().paintToolbarBackground (g, getWidth(), getHeight(), *this); } int Toolbar::getThickness() const throw() { - return vertical ? getWidth() : getHeight(); + return vertical ? getWidth() : getHeight(); } int Toolbar::getLength() const throw() { - return vertical ? getHeight() : getWidth(); + return vertical ? getHeight() : getWidth(); } void Toolbar::setEditingActive (const bool active) { - if (isEditingActive != active) - { - isEditingActive = active; - updateAllItemPositions (false); - } + if (isEditingActive != active) + { + isEditingActive = active; + updateAllItemPositions (false); + } } void Toolbar::resized() { - updateAllItemPositions (false); + updateAllItemPositions (false); } void Toolbar::updateAllItemPositions (const bool animate) { - if (getWidth() > 0 && getHeight() > 0) - { - StretchableObjectResizer resizer; + if (getWidth() > 0 && getHeight() > 0) + { + StretchableObjectResizer resizer; - int i; - for (i = 0; i < items.size(); ++i) - { - ToolbarItemComponent* const tc = items.getUnchecked(i); + int i; + for (i = 0; i < items.size(); ++i) + { + ToolbarItemComponent* const tc = items.getUnchecked(i); - tc->setEditingMode (isEditingActive ? ToolbarItemComponent::editableOnToolbar - : ToolbarItemComponent::normalMode); + tc->setEditingMode (isEditingActive ? ToolbarItemComponent::editableOnToolbar + : ToolbarItemComponent::normalMode); - tc->setStyle (toolbarStyle); + tc->setStyle (toolbarStyle); - ToolbarSpacerComp* const spacer = dynamic_cast (tc); + ToolbarSpacerComp* const spacer = dynamic_cast (tc); - int preferredSize = 1, minSize = 1, maxSize = 1; + int preferredSize = 1, minSize = 1, maxSize = 1; - if (tc->getToolbarItemSizes (getThickness(), isVertical(), - preferredSize, minSize, maxSize)) - { - tc->isActive = true; - resizer.addItem (preferredSize, minSize, maxSize, - spacer != 0 ? spacer->getResizeOrder() : 2); - } - else - { - tc->isActive = false; - tc->setVisible (false); - } - } + if (tc->getToolbarItemSizes (getThickness(), isVertical(), + preferredSize, minSize, maxSize)) + { + tc->isActive = true; + resizer.addItem (preferredSize, minSize, maxSize, + spacer != 0 ? spacer->getResizeOrder() : 2); + } + else + { + tc->isActive = false; + tc->setVisible (false); + } + } - resizer.resizeToFit (getLength()); + resizer.resizeToFit (getLength()); - int totalLength = 0; + int totalLength = 0; - for (i = 0; i < resizer.getNumItems(); ++i) - totalLength += (int) resizer.getItemSize (i); + for (i = 0; i < resizer.getNumItems(); ++i) + totalLength += (int) resizer.getItemSize (i); - const bool itemsOffTheEnd = totalLength > getLength(); + const bool itemsOffTheEnd = totalLength > getLength(); - const int extrasButtonSize = getThickness() / 2; - missingItemsButton->setSize (extrasButtonSize, extrasButtonSize); - missingItemsButton->setVisible (itemsOffTheEnd); - missingItemsButton->setEnabled (! isEditingActive); + const int extrasButtonSize = getThickness() / 2; + missingItemsButton->setSize (extrasButtonSize, extrasButtonSize); + missingItemsButton->setVisible (itemsOffTheEnd); + missingItemsButton->setEnabled (! isEditingActive); - if (vertical) - missingItemsButton->setCentrePosition (getWidth() / 2, - getHeight() - 4 - extrasButtonSize / 2); - else - missingItemsButton->setCentrePosition (getWidth() - 4 - extrasButtonSize / 2, - getHeight() / 2); + if (vertical) + missingItemsButton->setCentrePosition (getWidth() / 2, + getHeight() - 4 - extrasButtonSize / 2); + else + missingItemsButton->setCentrePosition (getWidth() - 4 - extrasButtonSize / 2, + getHeight() / 2); - const int maxLength = itemsOffTheEnd ? (vertical ? missingItemsButton->getY() - : missingItemsButton->getX()) - 4 - : getLength(); + const int maxLength = itemsOffTheEnd ? (vertical ? missingItemsButton->getY() + : missingItemsButton->getX()) - 4 + : getLength(); - int pos = 0, activeIndex = 0; - for (i = 0; i < items.size(); ++i) - { - ToolbarItemComponent* const tc = items.getUnchecked(i); + int pos = 0, activeIndex = 0; + for (i = 0; i < items.size(); ++i) + { + ToolbarItemComponent* const tc = items.getUnchecked(i); - if (tc->isActive) - { - const int size = (int) resizer.getItemSize (activeIndex++); + if (tc->isActive) + { + const int size = (int) resizer.getItemSize (activeIndex++); - Rectangle newBounds; - if (vertical) - newBounds.setBounds (0, pos, getWidth(), size); - else - newBounds.setBounds (pos, 0, size, getHeight()); + Rectangle newBounds; + if (vertical) + newBounds.setBounds (0, pos, getWidth(), size); + else + newBounds.setBounds (pos, 0, size, getHeight()); - if (animate) - { - animator.animateComponent (tc, newBounds, 200, 3.0, 0.0); - } - else - { - animator.cancelAnimation (tc, false); - tc->setBounds (newBounds); - } + if (animate) + { + animator.animateComponent (tc, newBounds, 200, 3.0, 0.0); + } + else + { + animator.cancelAnimation (tc, false); + tc->setBounds (newBounds); + } - pos += size; - tc->setVisible (pos <= maxLength - && ((! tc->isBeingDragged) - || tc->getEditingMode() == ToolbarItemComponent::editableOnPalette)); - } - } - } + pos += size; + tc->setVisible (pos <= maxLength + && ((! tc->isBeingDragged) + || tc->getEditingMode() == ToolbarItemComponent::editableOnPalette)); + } + } + } } void Toolbar::buttonClicked (Button*) { - jassert (missingItemsButton->isShowing()); + jassert (missingItemsButton->isShowing()); - if (missingItemsButton->isShowing()) - { - PopupMenu m; - m.addCustomItem (1, new MissingItemsComponent (*this, getThickness())); - m.showAt (missingItemsButton); - } + if (missingItemsButton->isShowing()) + { + PopupMenu m; + m.addCustomItem (1, new MissingItemsComponent (*this, getThickness())); + m.showAt (missingItemsButton); + } } bool Toolbar::isInterestedInDragSource (const String& sourceDescription, - Component* /*sourceComponent*/) + Component* /*sourceComponent*/) { - return sourceDescription == toolbarDragDescriptor && isEditingActive; + return sourceDescription == toolbarDragDescriptor && isEditingActive; } void Toolbar::itemDragMove (const String&, Component* sourceComponent, int x, int y) { - ToolbarItemComponent* const tc = dynamic_cast (sourceComponent); + ToolbarItemComponent* const tc = dynamic_cast (sourceComponent); - if (tc != 0) - { - if (getNumItems() == 0) - { - if (tc->getEditingMode() == ToolbarItemComponent::editableOnPalette) - { - ToolbarItemPalette* const palette = tc->findParentComponentOfClass ((ToolbarItemPalette*) 0); + if (tc != 0) + { + if (getNumItems() == 0) + { + if (tc->getEditingMode() == ToolbarItemComponent::editableOnPalette) + { + ToolbarItemPalette* const palette = tc->findParentComponentOfClass ((ToolbarItemPalette*) 0); - if (palette != 0) - palette->replaceComponent (tc); - } - else - { - jassert (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar); - } + if (palette != 0) + palette->replaceComponent (tc); + } + else + { + jassert (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar); + } - items.add (tc); - addChildComponent (tc); - updateAllItemPositions (false); - } - else - { - for (int i = getNumItems(); --i >= 0;) - { - int currentIndex = getIndexOfChildComponent (tc); + items.add (tc); + addChildComponent (tc); + updateAllItemPositions (false); + } + else + { + for (int i = getNumItems(); --i >= 0;) + { + int currentIndex = getIndexOfChildComponent (tc); - if (currentIndex < 0) - { - if (tc->getEditingMode() == ToolbarItemComponent::editableOnPalette) - { - ToolbarItemPalette* const palette = tc->findParentComponentOfClass ((ToolbarItemPalette*) 0); + if (currentIndex < 0) + { + if (tc->getEditingMode() == ToolbarItemComponent::editableOnPalette) + { + ToolbarItemPalette* const palette = tc->findParentComponentOfClass ((ToolbarItemPalette*) 0); - if (palette != 0) - palette->replaceComponent (tc); - } - else - { - jassert (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar); - } + if (palette != 0) + palette->replaceComponent (tc); + } + else + { + jassert (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar); + } - items.add (tc); - addChildComponent (tc); - currentIndex = getIndexOfChildComponent (tc); - updateAllItemPositions (true); - } + items.add (tc); + addChildComponent (tc); + currentIndex = getIndexOfChildComponent (tc); + updateAllItemPositions (true); + } - int newIndex = currentIndex; + int newIndex = currentIndex; - const int dragObjectLeft = vertical ? (y - tc->dragOffsetY) : (x - tc->dragOffsetX); - const int dragObjectRight = dragObjectLeft + (vertical ? tc->getHeight() : tc->getWidth()); + const int dragObjectLeft = vertical ? (y - tc->dragOffsetY) : (x - tc->dragOffsetX); + const int dragObjectRight = dragObjectLeft + (vertical ? tc->getHeight() : tc->getWidth()); - const Rectangle current (animator.getComponentDestination (getChildComponent (newIndex))); - ToolbarItemComponent* const prev = getNextActiveComponent (newIndex, -1); + const Rectangle current (animator.getComponentDestination (getChildComponent (newIndex))); + ToolbarItemComponent* const prev = getNextActiveComponent (newIndex, -1); - if (prev != 0) - { - const Rectangle previousPos (animator.getComponentDestination (prev)); + if (prev != 0) + { + const Rectangle previousPos (animator.getComponentDestination (prev)); - if (abs (dragObjectLeft - (vertical ? previousPos.getY() : previousPos.getX()) - < abs (dragObjectRight - (vertical ? current.getBottom() : current.getRight())))) - { - newIndex = getIndexOfChildComponent (prev); - } - } + if (abs (dragObjectLeft - (vertical ? previousPos.getY() : previousPos.getX()) + < abs (dragObjectRight - (vertical ? current.getBottom() : current.getRight())))) + { + newIndex = getIndexOfChildComponent (prev); + } + } - ToolbarItemComponent* const next = getNextActiveComponent (newIndex, 1); - if (next != 0) - { - const Rectangle nextPos (animator.getComponentDestination (next)); + ToolbarItemComponent* const next = getNextActiveComponent (newIndex, 1); + if (next != 0) + { + const Rectangle nextPos (animator.getComponentDestination (next)); - if (abs (dragObjectLeft - (vertical ? current.getY() : current.getX()) - > abs (dragObjectRight - (vertical ? nextPos.getBottom() : nextPos.getRight())))) - { - newIndex = getIndexOfChildComponent (next) + 1; - } - } + if (abs (dragObjectLeft - (vertical ? current.getY() : current.getX()) + > abs (dragObjectRight - (vertical ? nextPos.getBottom() : nextPos.getRight())))) + { + newIndex = getIndexOfChildComponent (next) + 1; + } + } - if (newIndex != currentIndex) - { - items.removeValue (tc); - removeChildComponent (tc); - addChildComponent (tc, newIndex); - items.insert (newIndex, tc); - updateAllItemPositions (true); - } - else - { - break; - } - } - } - } + if (newIndex != currentIndex) + { + items.removeValue (tc); + removeChildComponent (tc); + addChildComponent (tc, newIndex); + items.insert (newIndex, tc); + updateAllItemPositions (true); + } + else + { + break; + } + } + } + } } void Toolbar::itemDragExit (const String&, Component* sourceComponent) { - ToolbarItemComponent* const tc = dynamic_cast (sourceComponent); + ToolbarItemComponent* const tc = dynamic_cast (sourceComponent); - if (tc != 0) - { - if (isParentOf (tc)) - { - items.removeValue (tc); - removeChildComponent (tc); - updateAllItemPositions (true); - } - } + if (tc != 0) + { + if (isParentOf (tc)) + { + items.removeValue (tc); + removeChildComponent (tc); + updateAllItemPositions (true); + } + } } void Toolbar::itemDropped (const String&, Component*, int, int) @@ -54902,198 +54606,198 @@ void Toolbar::itemDropped (const String&, Component*, int, int) void Toolbar::mouseDown (const MouseEvent& e) { - if (e.mods.isPopupMenu()) - { - } + if (e.mods.isPopupMenu()) + { + } } class ToolbarCustomisationDialog : public DialogWindow { public: - ToolbarCustomisationDialog (ToolbarItemFactory& factory, - Toolbar* const toolbar_, - const int optionFlags) - : DialogWindow (TRANS("Add/remove items from toolbar"), Colours::white, true, true), - toolbar (toolbar_) - { - setContentComponent (new CustomiserPanel (factory, toolbar, optionFlags), true, true); - setResizable (true, true); - setResizeLimits (400, 300, 1500, 1000); - positionNearBar(); - } + ToolbarCustomisationDialog (ToolbarItemFactory& factory, + Toolbar* const toolbar_, + const int optionFlags) + : DialogWindow (TRANS("Add/remove items from toolbar"), Colours::white, true, true), + toolbar (toolbar_) + { + setContentComponent (new CustomiserPanel (factory, toolbar, optionFlags), true, true); + setResizable (true, true); + setResizeLimits (400, 300, 1500, 1000); + positionNearBar(); + } - ~ToolbarCustomisationDialog() - { - setContentComponent (0, true); - } + ~ToolbarCustomisationDialog() + { + setContentComponent (0, true); + } - void closeButtonPressed() - { - setVisible (false); - } + void closeButtonPressed() + { + setVisible (false); + } - bool canModalEventBeSentToComponent (const Component* comp) - { - return toolbar->isParentOf (comp); - } + bool canModalEventBeSentToComponent (const Component* comp) + { + return toolbar->isParentOf (comp); + } - void positionNearBar() - { - const Rectangle screenSize (toolbar->getParentMonitorArea()); - const int tbx = toolbar->getScreenX(); - const int tby = toolbar->getScreenY(); - const int gap = 8; + void positionNearBar() + { + const Rectangle screenSize (toolbar->getParentMonitorArea()); + const int tbx = toolbar->getScreenX(); + const int tby = toolbar->getScreenY(); + const int gap = 8; - int x, y; + int x, y; - if (toolbar->isVertical()) - { - y = tby; + if (toolbar->isVertical()) + { + y = tby; - if (tbx > screenSize.getCentreX()) - x = tbx - getWidth() - gap; - else - x = tbx + toolbar->getWidth() + gap; - } - else - { - x = tbx + (toolbar->getWidth() - getWidth()) / 2; + if (tbx > screenSize.getCentreX()) + x = tbx - getWidth() - gap; + else + x = tbx + toolbar->getWidth() + gap; + } + else + { + x = tbx + (toolbar->getWidth() - getWidth()) / 2; - if (tby > screenSize.getCentreY()) - y = tby - getHeight() - gap; - else - y = tby + toolbar->getHeight() + gap; - } + if (tby > screenSize.getCentreY()) + y = tby - getHeight() - gap; + else + y = tby + toolbar->getHeight() + gap; + } - setTopLeftPosition (x, y); - } + setTopLeftPosition (x, y); + } private: - Toolbar* const toolbar; + Toolbar* const toolbar; - class CustomiserPanel : public Component, - private ComboBoxListener, - private ButtonListener - { - public: - CustomiserPanel (ToolbarItemFactory& factory_, - Toolbar* const toolbar_, - const int optionFlags) - : factory (factory_), - toolbar (toolbar_), - styleBox (0), - defaultButton (0) - { - addAndMakeVisible (palette = new ToolbarItemPalette (factory, toolbar)); + class CustomiserPanel : public Component, + private ComboBoxListener, + private ButtonListener + { + public: + CustomiserPanel (ToolbarItemFactory& factory_, + Toolbar* const toolbar_, + const int optionFlags) + : factory (factory_), + toolbar (toolbar_), + styleBox (0), + defaultButton (0) + { + addAndMakeVisible (palette = new ToolbarItemPalette (factory, toolbar)); - if ((optionFlags & (Toolbar::allowIconsOnlyChoice - | Toolbar::allowIconsWithTextChoice - | Toolbar::allowTextOnlyChoice)) != 0) - { - addAndMakeVisible (styleBox = new ComboBox (String::empty)); - styleBox->setEditableText (false); + if ((optionFlags & (Toolbar::allowIconsOnlyChoice + | Toolbar::allowIconsWithTextChoice + | Toolbar::allowTextOnlyChoice)) != 0) + { + addAndMakeVisible (styleBox = new ComboBox (String::empty)); + styleBox->setEditableText (false); - if ((optionFlags & Toolbar::allowIconsOnlyChoice) != 0) - styleBox->addItem (TRANS("Show icons only"), 1); - if ((optionFlags & Toolbar::allowIconsWithTextChoice) != 0) - styleBox->addItem (TRANS("Show icons and descriptions"), 2); - if ((optionFlags & Toolbar::allowTextOnlyChoice) != 0) - styleBox->addItem (TRANS("Show descriptions only"), 3); + if ((optionFlags & Toolbar::allowIconsOnlyChoice) != 0) + styleBox->addItem (TRANS("Show icons only"), 1); + if ((optionFlags & Toolbar::allowIconsWithTextChoice) != 0) + styleBox->addItem (TRANS("Show icons and descriptions"), 2); + if ((optionFlags & Toolbar::allowTextOnlyChoice) != 0) + styleBox->addItem (TRANS("Show descriptions only"), 3); - if (toolbar_->getStyle() == Toolbar::iconsOnly) - styleBox->setSelectedId (1); - else if (toolbar_->getStyle() == Toolbar::iconsWithText) - styleBox->setSelectedId (2); - else if (toolbar_->getStyle() == Toolbar::textOnly) - styleBox->setSelectedId (3); + if (toolbar_->getStyle() == Toolbar::iconsOnly) + styleBox->setSelectedId (1); + else if (toolbar_->getStyle() == Toolbar::iconsWithText) + styleBox->setSelectedId (2); + else if (toolbar_->getStyle() == Toolbar::textOnly) + styleBox->setSelectedId (3); - styleBox->addListener (this); - } + styleBox->addListener (this); + } - if ((optionFlags & Toolbar::showResetToDefaultsButton) != 0) - { - addAndMakeVisible (defaultButton = new TextButton (TRANS ("Restore to default set of items"))); - defaultButton->addButtonListener (this); - } + if ((optionFlags & Toolbar::showResetToDefaultsButton) != 0) + { + addAndMakeVisible (defaultButton = new TextButton (TRANS ("Restore to default set of items"))); + defaultButton->addButtonListener (this); + } - addAndMakeVisible (instructions = new Label (String::empty, - TRANS ("You can drag the items above and drop them onto a toolbar to add them.\n\nItems on the toolbar can also be dragged around to change their order, or dragged off the edge to delete them."))); - instructions->setFont (Font (13.0f)); + addAndMakeVisible (instructions = new Label (String::empty, + TRANS ("You can drag the items above and drop them onto a toolbar to add them.\n\nItems on the toolbar can also be dragged around to change their order, or dragged off the edge to delete them."))); + instructions->setFont (Font (13.0f)); - setSize (500, 300); - } + setSize (500, 300); + } - ~CustomiserPanel() - { - deleteAllChildren(); - } + ~CustomiserPanel() + { + deleteAllChildren(); + } - void comboBoxChanged (ComboBox*) - { - if (styleBox->getSelectedId() == 1) - toolbar->setStyle (Toolbar::iconsOnly); - else if (styleBox->getSelectedId() == 2) - toolbar->setStyle (Toolbar::iconsWithText); - else if (styleBox->getSelectedId() == 3) - toolbar->setStyle (Toolbar::textOnly); + void comboBoxChanged (ComboBox*) + { + if (styleBox->getSelectedId() == 1) + toolbar->setStyle (Toolbar::iconsOnly); + else if (styleBox->getSelectedId() == 2) + toolbar->setStyle (Toolbar::iconsWithText); + else if (styleBox->getSelectedId() == 3) + toolbar->setStyle (Toolbar::textOnly); - palette->resized(); // to make it update the styles - } + palette->resized(); // to make it update the styles + } - void buttonClicked (Button*) - { - toolbar->addDefaultItems (factory); - } + void buttonClicked (Button*) + { + toolbar->addDefaultItems (factory); + } - void paint (Graphics& g) - { - Colour background; + void paint (Graphics& g) + { + Colour background; - DialogWindow* const dw = findParentComponentOfClass ((DialogWindow*) 0); + DialogWindow* const dw = findParentComponentOfClass ((DialogWindow*) 0); - if (dw != 0) - background = dw->getBackgroundColour(); + if (dw != 0) + background = dw->getBackgroundColour(); - g.setColour (background.contrasting().withAlpha (0.3f)); - g.fillRect (palette->getX(), palette->getBottom() - 1, palette->getWidth(), 1); - } + g.setColour (background.contrasting().withAlpha (0.3f)); + g.fillRect (palette->getX(), palette->getBottom() - 1, palette->getWidth(), 1); + } - void resized() - { - palette->setBounds (0, 0, getWidth(), getHeight() - 120); + void resized() + { + palette->setBounds (0, 0, getWidth(), getHeight() - 120); - if (styleBox != 0) - styleBox->setBounds (10, getHeight() - 110, 200, 22); + if (styleBox != 0) + styleBox->setBounds (10, getHeight() - 110, 200, 22); - if (defaultButton != 0) - { - defaultButton->changeWidthToFitText (22); - defaultButton->setTopLeftPosition (240, getHeight() - 110); - } + if (defaultButton != 0) + { + defaultButton->changeWidthToFitText (22); + defaultButton->setTopLeftPosition (240, getHeight() - 110); + } - instructions->setBounds (10, getHeight() - 80, getWidth() - 20, 80); - } + instructions->setBounds (10, getHeight() - 80, getWidth() - 20, 80); + } - private: - ToolbarItemFactory& factory; - Toolbar* const toolbar; + private: + ToolbarItemFactory& factory; + Toolbar* const toolbar; - Label* instructions; - ToolbarItemPalette* palette; - ComboBox* styleBox; - TextButton* defaultButton; - }; + Label* instructions; + ToolbarItemPalette* palette; + ComboBox* styleBox; + TextButton* defaultButton; + }; }; void Toolbar::showCustomisationDialog (ToolbarItemFactory& factory, const int optionFlags) { - setEditingActive (true); + setEditingActive (true); - ToolbarCustomisationDialog dw (factory, this, optionFlags); - dw.runModalLoop(); + ToolbarCustomisationDialog dw (factory, this, optionFlags); + dw.runModalLoop(); - jassert (isValidComponent()); // ? deleting the toolbar while it's being edited? - setEditingActive (false); + jassert (isValidComponent()); // ? deleting the toolbar while it's being edited? + setEditingActive (false); } END_JUCE_NAMESPACE @@ -55111,221 +54815,221 @@ ToolbarItemFactory::~ToolbarItemFactory() { } -class ItemDragAndDropOverlayComponent : public Component +class ItemDragAndDropOverlayComponent : public Component { public: - ItemDragAndDropOverlayComponent() - : isDragging (false) - { - setAlwaysOnTop (true); - setRepaintsOnMouseActivity (true); - setMouseCursor (MouseCursor::DraggingHandCursor); - } + ItemDragAndDropOverlayComponent() + : isDragging (false) + { + setAlwaysOnTop (true); + setRepaintsOnMouseActivity (true); + setMouseCursor (MouseCursor::DraggingHandCursor); + } - ~ItemDragAndDropOverlayComponent() - { - } + ~ItemDragAndDropOverlayComponent() + { + } - void paint (Graphics& g) - { - ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); + void paint (Graphics& g) + { + ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); - if (isMouseOverOrDragging() - && tc != 0 - && tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar) - { - g.setColour (findColour (Toolbar::editingModeOutlineColourId, true)); - g.drawRect (0, 0, getWidth(), getHeight(), - jmin (2, (getWidth() - 1) / 2, (getHeight() - 1) / 2)); - } - } + if (isMouseOverOrDragging() + && tc != 0 + && tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar) + { + g.setColour (findColour (Toolbar::editingModeOutlineColourId, true)); + g.drawRect (0, 0, getWidth(), getHeight(), + jmin (2, (getWidth() - 1) / 2, (getHeight() - 1) / 2)); + } + } - void mouseDown (const MouseEvent& e) - { - isDragging = false; - ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); + void mouseDown (const MouseEvent& e) + { + isDragging = false; + ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); - if (tc != 0) - { - tc->dragOffsetX = e.x; - tc->dragOffsetY = e.y; - } - } + if (tc != 0) + { + tc->dragOffsetX = e.x; + tc->dragOffsetY = e.y; + } + } - void mouseDrag (const MouseEvent& e) - { - if (! (isDragging || e.mouseWasClicked())) - { - isDragging = true; - DragAndDropContainer* const dnd = DragAndDropContainer::findParentDragContainerFor (this); + void mouseDrag (const MouseEvent& e) + { + if (! (isDragging || e.mouseWasClicked())) + { + isDragging = true; + DragAndDropContainer* const dnd = DragAndDropContainer::findParentDragContainerFor (this); - if (dnd != 0) - { - dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), 0, true); + if (dnd != 0) + { + dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), 0, true); - ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); + ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); - if (tc != 0) - { - tc->isBeingDragged = true; + if (tc != 0) + { + tc->isBeingDragged = true; - if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar) - tc->setVisible (false); - } - } - } - } + if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar) + tc->setVisible (false); + } + } + } + } - void mouseUp (const MouseEvent&) - { - isDragging = false; - ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); + void mouseUp (const MouseEvent&) + { + isDragging = false; + ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); - if (tc != 0) - { - tc->isBeingDragged = false; + if (tc != 0) + { + tc->isBeingDragged = false; - Toolbar* const tb = tc->getToolbar(); + Toolbar* const tb = tc->getToolbar(); - if (tb != 0) - tb->updateAllItemPositions (true); - else if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar) - delete tc; - } - } + if (tb != 0) + tb->updateAllItemPositions (true); + else if (tc->getEditingMode() == ToolbarItemComponent::editableOnToolbar) + delete tc; + } + } - void parentSizeChanged() - { - setBounds (0, 0, getParentWidth(), getParentHeight()); - } + void parentSizeChanged() + { + setBounds (0, 0, getParentWidth(), getParentHeight()); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - bool isDragging; + bool isDragging; - ItemDragAndDropOverlayComponent (const ItemDragAndDropOverlayComponent&); - const ItemDragAndDropOverlayComponent& operator= (const ItemDragAndDropOverlayComponent&); + ItemDragAndDropOverlayComponent (const ItemDragAndDropOverlayComponent&); + const ItemDragAndDropOverlayComponent& operator= (const ItemDragAndDropOverlayComponent&); }; ToolbarItemComponent::ToolbarItemComponent (const int itemId_, - const String& labelText, - const bool isBeingUsedAsAButton_) - : Button (labelText), - itemId (itemId_), - mode (normalMode), - toolbarStyle (Toolbar::iconsOnly), - dragOffsetX (0), - dragOffsetY (0), - isActive (true), - isBeingDragged (false), - isBeingUsedAsAButton (isBeingUsedAsAButton_) + const String& labelText, + const bool isBeingUsedAsAButton_) + : Button (labelText), + itemId (itemId_), + mode (normalMode), + toolbarStyle (Toolbar::iconsOnly), + dragOffsetX (0), + dragOffsetY (0), + isActive (true), + isBeingDragged (false), + isBeingUsedAsAButton (isBeingUsedAsAButton_) { - // Your item ID can't be 0! - jassert (itemId_ != 0); + // Your item ID can't be 0! + jassert (itemId_ != 0); } ToolbarItemComponent::~ToolbarItemComponent() { - jassert (overlayComp == 0 || overlayComp->isValidComponent()); - overlayComp = 0; + jassert (overlayComp == 0 || overlayComp->isValidComponent()); + overlayComp = 0; } Toolbar* ToolbarItemComponent::getToolbar() const { - return dynamic_cast (getParentComponent()); + return dynamic_cast (getParentComponent()); } bool ToolbarItemComponent::isToolbarVertical() const { - const Toolbar* const t = getToolbar(); - return t != 0 && t->isVertical(); + const Toolbar* const t = getToolbar(); + return t != 0 && t->isVertical(); } void ToolbarItemComponent::setStyle (const Toolbar::ToolbarItemStyle& newStyle) { - if (toolbarStyle != newStyle) - { - toolbarStyle = newStyle; - repaint(); - resized(); - } + if (toolbarStyle != newStyle) + { + toolbarStyle = newStyle; + repaint(); + resized(); + } } void ToolbarItemComponent::paintButton (Graphics& g, bool isMouseOver, bool isMouseDown) { - if (isBeingUsedAsAButton) - getLookAndFeel().paintToolbarButtonBackground (g, getWidth(), getHeight(), - isMouseOver, isMouseDown, *this); + if (isBeingUsedAsAButton) + getLookAndFeel().paintToolbarButtonBackground (g, getWidth(), getHeight(), + isMouseOver, isMouseDown, *this); - if (toolbarStyle != Toolbar::iconsOnly) - { - const int indent = contentArea.getX(); - int y = indent; - int h = getHeight() - indent * 2; + if (toolbarStyle != Toolbar::iconsOnly) + { + const int indent = contentArea.getX(); + int y = indent; + int h = getHeight() - indent * 2; - if (toolbarStyle == Toolbar::iconsWithText) - { - y = contentArea.getBottom() + indent / 2; - h -= contentArea.getHeight(); - } + if (toolbarStyle == Toolbar::iconsWithText) + { + y = contentArea.getBottom() + indent / 2; + h -= contentArea.getHeight(); + } - getLookAndFeel().paintToolbarButtonLabel (g, indent, y, getWidth() - indent * 2, h, - getButtonText(), *this); - } + getLookAndFeel().paintToolbarButtonLabel (g, indent, y, getWidth() - indent * 2, h, + getButtonText(), *this); + } - if (! contentArea.isEmpty()) - { - g.saveState(); - g.setOrigin (contentArea.getX(), contentArea.getY()); - g.reduceClipRegion (0, 0, contentArea.getWidth(), contentArea.getHeight()); + if (! contentArea.isEmpty()) + { + g.saveState(); + g.setOrigin (contentArea.getX(), contentArea.getY()); + g.reduceClipRegion (0, 0, contentArea.getWidth(), contentArea.getHeight()); - paintButtonArea (g, contentArea.getWidth(), contentArea.getHeight(), isMouseOver, isMouseDown); + paintButtonArea (g, contentArea.getWidth(), contentArea.getHeight(), isMouseOver, isMouseDown); - g.restoreState(); - } + g.restoreState(); + } } void ToolbarItemComponent::resized() { - if (toolbarStyle != Toolbar::textOnly) - { - const int indent = jmin (proportionOfWidth (0.08f), - proportionOfHeight (0.08f)); + if (toolbarStyle != Toolbar::textOnly) + { + const int indent = jmin (proportionOfWidth (0.08f), + proportionOfHeight (0.08f)); - contentArea = Rectangle (indent, indent, - getWidth() - indent * 2, - toolbarStyle == Toolbar::iconsWithText ? proportionOfHeight (0.55f) - : (getHeight() - indent * 2)); - } - else - { - contentArea = Rectangle(); - } + contentArea = Rectangle (indent, indent, + getWidth() - indent * 2, + toolbarStyle == Toolbar::iconsWithText ? proportionOfHeight (0.55f) + : (getHeight() - indent * 2)); + } + else + { + contentArea = Rectangle(); + } - contentAreaChanged (contentArea); + contentAreaChanged (contentArea); } void ToolbarItemComponent::setEditingMode (const ToolbarEditingMode newMode) { - if (mode != newMode) - { - mode = newMode; - repaint(); + if (mode != newMode) + { + mode = newMode; + repaint(); - if (mode == normalMode) - { - jassert (overlayComp == 0 || overlayComp->isValidComponent()); - overlayComp = 0; - } - else if (overlayComp == 0) - { - addAndMakeVisible (overlayComp = new ItemDragAndDropOverlayComponent()); - overlayComp->parentSizeChanged(); - } + if (mode == normalMode) + { + jassert (overlayComp == 0 || overlayComp->isValidComponent()); + overlayComp = 0; + } + else if (overlayComp == 0) + { + addAndMakeVisible (overlayComp = new ItemDragAndDropOverlayComponent()); + overlayComp->parentSizeChanged(); + } - resized(); - } + resized(); + } } END_JUCE_NAMESPACE @@ -55336,93 +55040,93 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ToolbarItemPalette::ToolbarItemPalette (ToolbarItemFactory& factory_, - Toolbar* const toolbar_) - : factory (factory_), - toolbar (toolbar_) + Toolbar* const toolbar_) + : factory (factory_), + toolbar (toolbar_) { - Component* const itemHolder = new Component(); + Component* const itemHolder = new Component(); - Array allIds; - factory_.getAllToolbarItemIds (allIds); + Array allIds; + factory_.getAllToolbarItemIds (allIds); - for (int i = 0; i < allIds.size(); ++i) - { - ToolbarItemComponent* const tc = Toolbar::createItem (factory_, allIds.getUnchecked (i)); + for (int i = 0; i < allIds.size(); ++i) + { + ToolbarItemComponent* const tc = Toolbar::createItem (factory_, allIds.getUnchecked (i)); - jassert (tc != 0); - if (tc != 0) - { - itemHolder->addAndMakeVisible (tc); - tc->setEditingMode (ToolbarItemComponent::editableOnPalette); - } - } + jassert (tc != 0); + if (tc != 0) + { + itemHolder->addAndMakeVisible (tc); + tc->setEditingMode (ToolbarItemComponent::editableOnPalette); + } + } - viewport = new Viewport(); - viewport->setViewedComponent (itemHolder); - addAndMakeVisible (viewport); + viewport = new Viewport(); + viewport->setViewedComponent (itemHolder); + addAndMakeVisible (viewport); } ToolbarItemPalette::~ToolbarItemPalette() { - viewport->getViewedComponent()->deleteAllChildren(); - deleteAllChildren(); + viewport->getViewedComponent()->deleteAllChildren(); + deleteAllChildren(); } void ToolbarItemPalette::resized() { - viewport->setBoundsInset (BorderSize (1)); + viewport->setBoundsInset (BorderSize (1)); - Component* const itemHolder = viewport->getViewedComponent(); + Component* const itemHolder = viewport->getViewedComponent(); - const int indent = 8; - const int preferredWidth = viewport->getWidth() - viewport->getScrollBarThickness() - indent; - const int height = toolbar->getThickness(); - int x = indent; - int y = indent; - int maxX = 0; + const int indent = 8; + const int preferredWidth = viewport->getWidth() - viewport->getScrollBarThickness() - indent; + const int height = toolbar->getThickness(); + int x = indent; + int y = indent; + int maxX = 0; - for (int i = 0; i < itemHolder->getNumChildComponents(); ++i) - { - ToolbarItemComponent* const tc = dynamic_cast (itemHolder->getChildComponent (i)); + for (int i = 0; i < itemHolder->getNumChildComponents(); ++i) + { + ToolbarItemComponent* const tc = dynamic_cast (itemHolder->getChildComponent (i)); - if (tc != 0) - { - tc->setStyle (toolbar->getStyle()); + if (tc != 0) + { + tc->setStyle (toolbar->getStyle()); - int preferredSize = 1, minSize = 1, maxSize = 1; + int preferredSize = 1, minSize = 1, maxSize = 1; - if (tc->getToolbarItemSizes (height, false, preferredSize, minSize, maxSize)) - { - if (x + preferredSize > preferredWidth && x > indent) - { - x = indent; - y += height; - } + if (tc->getToolbarItemSizes (height, false, preferredSize, minSize, maxSize)) + { + if (x + preferredSize > preferredWidth && x > indent) + { + x = indent; + y += height; + } - tc->setBounds (x, y, preferredSize, height); + tc->setBounds (x, y, preferredSize, height); - x += preferredSize + 8; - maxX = jmax (maxX, x); - } - } - } + x += preferredSize + 8; + maxX = jmax (maxX, x); + } + } + } - itemHolder->setSize (maxX, y + height + 8); + itemHolder->setSize (maxX, y + height + 8); } void ToolbarItemPalette::replaceComponent (ToolbarItemComponent* const comp) { - ToolbarItemComponent* const tc = Toolbar::createItem (factory, comp->getItemId()); + ToolbarItemComponent* const tc = Toolbar::createItem (factory, comp->getItemId()); - jassert (tc != 0); + jassert (tc != 0); - if (tc != 0) - { - tc->setBounds (comp->getBounds()); - tc->setStyle (toolbar->getStyle()); - tc->setEditingMode (comp->getEditingMode()); - viewport->getViewedComponent()->addAndMakeVisible (tc, getIndexOfChildComponent (comp)); - } + if (tc != 0) + { + tc->setBounds (comp->getBounds()); + tc->setStyle (toolbar->getStyle()); + tc->setEditingMode (comp->getEditingMode()); + viewport->getViewedComponent()->addAndMakeVisible (tc, getIndexOfChildComponent (comp)); + } } END_JUCE_NAMESPACE @@ -55433,1055 +55137,1054 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE class TreeViewContentComponent : public Component, - public TooltipClient + public TooltipClient { public: - TreeViewContentComponent (TreeView* const owner_) - : owner (owner_), - buttonUnderMouse (0), - isDragging (false) - { - } + TreeViewContentComponent (TreeView* const owner_) + : owner (owner_), + buttonUnderMouse (0), + isDragging (false) + { + } - ~TreeViewContentComponent() - { - deleteAllChildren(); - } + ~TreeViewContentComponent() + { + deleteAllChildren(); + } - void mouseDown (const MouseEvent& e) - { - updateButtonUnderMouse (e); + void mouseDown (const MouseEvent& e) + { + updateButtonUnderMouse (e); - isDragging = false; - needSelectionOnMouseUp = false; + isDragging = false; + needSelectionOnMouseUp = false; - Rectangle pos; - TreeViewItem* const item = findItemAt (e.y, pos); + Rectangle pos; + TreeViewItem* const item = findItemAt (e.y, pos); - if (item == 0) - return; + if (item == 0) + return; - // (if the open/close buttons are hidden, we'll treat clicks to the left of the item - // as selection clicks) - if (e.x < pos.getX() && owner->openCloseButtonsVisible) - { - if (e.x >= pos.getX() - owner->getIndentSize()) - item->setOpen (! item->isOpen()); + // (if the open/close buttons are hidden, we'll treat clicks to the left of the item + // as selection clicks) + if (e.x < pos.getX() && owner->openCloseButtonsVisible) + { + if (e.x >= pos.getX() - owner->getIndentSize()) + item->setOpen (! item->isOpen()); - // (clicks to the left of an open/close button are ignored) - } - else - { - // mouse-down inside the body of the item.. - if (! owner->isMultiSelectEnabled()) - item->setSelected (true, true); - else if (item->isSelected()) - needSelectionOnMouseUp = ! e.mods.isPopupMenu(); - else - selectBasedOnModifiers (item, e.mods); + // (clicks to the left of an open/close button are ignored) + } + else + { + // mouse-down inside the body of the item.. + if (! owner->isMultiSelectEnabled()) + item->setSelected (true, true); + else if (item->isSelected()) + needSelectionOnMouseUp = ! e.mods.isPopupMenu(); + else + selectBasedOnModifiers (item, e.mods); - MouseEvent e2 (e); - e2.x -= pos.getX(); - e2.y -= pos.getY(); + MouseEvent e2 (e); + e2.x -= pos.getX(); + e2.y -= pos.getY(); - if (e2.x >= 0) - item->itemClicked (e2); - } - } + if (e2.x >= 0) + item->itemClicked (e2); + } + } - void mouseUp (const MouseEvent& e) - { - updateButtonUnderMouse (e); + void mouseUp (const MouseEvent& e) + { + updateButtonUnderMouse (e); - if (needSelectionOnMouseUp && e.mouseWasClicked()) - { - Rectangle pos; - TreeViewItem* const item = findItemAt (e.y, pos); + if (needSelectionOnMouseUp && e.mouseWasClicked()) + { + Rectangle pos; + TreeViewItem* const item = findItemAt (e.y, pos); - if (item != 0) - selectBasedOnModifiers (item, e.mods); - } - } + if (item != 0) + selectBasedOnModifiers (item, e.mods); + } + } - void mouseDoubleClick (const MouseEvent& e) - { - if (e.getNumberOfClicks() != 3) // ignore triple clicks - { - Rectangle pos; - TreeViewItem* const item = findItemAt (e.y, pos); + void mouseDoubleClick (const MouseEvent& e) + { + if (e.getNumberOfClicks() != 3) // ignore triple clicks + { + Rectangle pos; + TreeViewItem* const item = findItemAt (e.y, pos); - if (item != 0 && (e.x >= pos.getX() || ! owner->openCloseButtonsVisible)) - { - MouseEvent e2 (e); - e2.x -= pos.getX(); - e2.y -= pos.getY(); - item->itemDoubleClicked (e2); - } - } - } + if (item != 0 && (e.x >= pos.getX() || ! owner->openCloseButtonsVisible)) + { + MouseEvent e2 (e); + e2.x -= pos.getX(); + e2.y -= pos.getY(); + item->itemDoubleClicked (e2); + } + } + } - void mouseDrag (const MouseEvent& e) - { - if (isEnabled() - && ! (isDragging || e.mouseWasClicked() - || e.getDistanceFromDragStart() < 5 - || e.mods.isPopupMenu())) - { - isDragging = true; + void mouseDrag (const MouseEvent& e) + { + if (isEnabled() + && ! (isDragging || e.mouseWasClicked() + || e.getDistanceFromDragStart() < 5 + || e.mods.isPopupMenu())) + { + isDragging = true; - Rectangle pos; - TreeViewItem* const item = findItemAt (e.getMouseDownY(), pos); + Rectangle pos; + TreeViewItem* const item = findItemAt (e.getMouseDownY(), pos); - if (item != 0 && e.getMouseDownX() >= pos.getX()) - { - const String dragDescription (item->getDragSourceDescription()); + if (item != 0 && e.getMouseDownX() >= pos.getX()) + { + const String dragDescription (item->getDragSourceDescription()); - if (dragDescription.isNotEmpty()) - { - DragAndDropContainer* const dragContainer - = DragAndDropContainer::findParentDragContainerFor (this); + if (dragDescription.isNotEmpty()) + { + DragAndDropContainer* const dragContainer + = DragAndDropContainer::findParentDragContainerFor (this); - if (dragContainer != 0) - { - pos.setSize (pos.getWidth(), item->itemHeight); - Image* dragImage = Component::createComponentSnapshot (pos, true); - dragImage->multiplyAllAlphas (0.6f); + if (dragContainer != 0) + { + pos.setSize (pos.getWidth(), item->itemHeight); + Image* dragImage = Component::createComponentSnapshot (pos, true); + dragImage->multiplyAllAlphas (0.6f); - Point imageOffset ((float) (pos.getX() - e.x), (float) (pos.getY() - e.y)); - dragContainer->startDragging (dragDescription, owner, dragImage, true, &imageOffset); - } - else - { - // to be able to do a drag-and-drop operation, the treeview needs to - // be inside a component which is also a DragAndDropContainer. - jassertfalse - } - } - } - } - } + Point imageOffset ((float) (pos.getX() - e.x), (float) (pos.getY() - e.y)); + dragContainer->startDragging (dragDescription, owner, dragImage, true, &imageOffset); + } + else + { + // to be able to do a drag-and-drop operation, the treeview needs to + // be inside a component which is also a DragAndDropContainer. + jassertfalse + } + } + } + } + } - void mouseMove (const MouseEvent& e) - { - updateButtonUnderMouse (e); - } + void mouseMove (const MouseEvent& e) + { + updateButtonUnderMouse (e); + } - void mouseExit (const MouseEvent& e) - { - updateButtonUnderMouse (e); - } + void mouseExit (const MouseEvent& e) + { + updateButtonUnderMouse (e); + } - void paint (Graphics& g); - TreeViewItem* findItemAt (int y, Rectangle& itemPosition) const; + void paint (Graphics& g); + TreeViewItem* findItemAt (int y, Rectangle& itemPosition) const; - void updateComponents() - { - const int visibleTop = -getY(); - const int visibleBottom = visibleTop + getParentHeight(); + void updateComponents() + { + const int visibleTop = -getY(); + const int visibleBottom = visibleTop + getParentHeight(); - BitArray itemsToKeep; - TreeViewItem* item = owner->rootItem; - int y = (item != 0 && !owner->rootItemVisible) ? -item->itemHeight : 0; + BitArray itemsToKeep; + TreeViewItem* item = owner->rootItem; + int y = (item != 0 && !owner->rootItemVisible) ? -item->itemHeight : 0; - while (item != 0 && y < visibleBottom) - { - y += item->itemHeight; + while (item != 0 && y < visibleBottom) + { + y += item->itemHeight; - if (y >= visibleTop) - { - const int index = rowComponentIds.indexOf (item->uid); + if (y >= visibleTop) + { + const int index = rowComponentIds.indexOf (item->uid); - if (index < 0) - { - Component* const comp = item->createItemComponent(); + if (index < 0) + { + Component* const comp = item->createItemComponent(); - if (comp != 0) - { - addAndMakeVisible (comp); - itemsToKeep.setBit (rowComponentItems.size()); - rowComponentItems.add (item); - rowComponentIds.add (item->uid); - rowComponents.add (comp); - } - } - else - { - itemsToKeep.setBit (index); - } - } + if (comp != 0) + { + addAndMakeVisible (comp); + itemsToKeep.setBit (rowComponentItems.size()); + rowComponentItems.add (item); + rowComponentIds.add (item->uid); + rowComponents.add (comp); + } + } + else + { + itemsToKeep.setBit (index); + } + } - item = item->getNextVisibleItem (true); - } + item = item->getNextVisibleItem (true); + } - for (int i = rowComponentItems.size(); --i >= 0;) - { - Component* const comp = (Component*) rowComponents.getUnchecked(i); + for (int i = rowComponentItems.size(); --i >= 0;) + { + Component* const comp = (Component*) rowComponents.getUnchecked(i); - bool keep = false; + bool keep = false; - if (isParentOf (comp)) - { - if (itemsToKeep[i]) - { - const TreeViewItem* const item = (TreeViewItem*) rowComponentItems.getUnchecked(i); + if (isParentOf (comp)) + { + if (itemsToKeep[i]) + { + const TreeViewItem* const item = (TreeViewItem*) rowComponentItems.getUnchecked(i); - Rectangle pos (item->getItemPosition (false)); - pos.setSize (pos.getWidth(), item->itemHeight); + Rectangle pos (item->getItemPosition (false)); + pos.setSize (pos.getWidth(), item->itemHeight); - if (pos.getBottom() >= visibleTop && pos.getY() < visibleBottom) - { - keep = true; - comp->setBounds (pos); - } - } + if (pos.getBottom() >= visibleTop && pos.getY() < visibleBottom) + { + keep = true; + comp->setBounds (pos); + } + } - if ((! keep) - && Component::isMouseButtonDownAnywhere() - && (comp == Component::getComponentUnderMouse() - || comp->isParentOf (Component::getComponentUnderMouse()))) - { - keep = true; - comp->setSize (0, 0); - } - } + if ((! keep) + && Component::isMouseButtonDownAnywhere() + && (comp == Component::getComponentUnderMouse() + || comp->isParentOf (Component::getComponentUnderMouse()))) + { + keep = true; + comp->setSize (0, 0); + } + } - if (! keep) - { - delete comp; - rowComponents.remove (i); - rowComponentIds.remove (i); - rowComponentItems.remove (i); - } - } - } + if (! keep) + { + delete comp; + rowComponents.remove (i); + rowComponentIds.remove (i); + rowComponentItems.remove (i); + } + } + } - void updateButtonUnderMouse (const MouseEvent& e) - { - TreeViewItem* newItem = 0; + void updateButtonUnderMouse (const MouseEvent& e) + { + TreeViewItem* newItem = 0; - if (owner->openCloseButtonsVisible) - { - Rectangle pos; - TreeViewItem* item = findItemAt (e.y, pos); + if (owner->openCloseButtonsVisible) + { + Rectangle pos; + TreeViewItem* item = findItemAt (e.y, pos); - if (item != 0 && e.x < pos.getX() && e.x >= pos.getX() - owner->getIndentSize()) - { - newItem = item; + if (item != 0 && e.x < pos.getX() && e.x >= pos.getX() - owner->getIndentSize()) + { + newItem = item; - if (! newItem->mightContainSubItems()) - newItem = 0; - } - } + if (! newItem->mightContainSubItems()) + newItem = 0; + } + } - if (buttonUnderMouse != newItem) - { - if (buttonUnderMouse != 0 && containsItem (buttonUnderMouse)) - { - const Rectangle r (buttonUnderMouse->getItemPosition (false)); - repaint (0, r.getY(), r.getX(), buttonUnderMouse->getItemHeight()); - } + if (buttonUnderMouse != newItem) + { + if (buttonUnderMouse != 0 && containsItem (buttonUnderMouse)) + { + const Rectangle r (buttonUnderMouse->getItemPosition (false)); + repaint (0, r.getY(), r.getX(), buttonUnderMouse->getItemHeight()); + } - buttonUnderMouse = newItem; + buttonUnderMouse = newItem; - if (buttonUnderMouse != 0) - { - const Rectangle r (buttonUnderMouse->getItemPosition (false)); - repaint (0, r.getY(), r.getX(), buttonUnderMouse->getItemHeight()); - } - } - } + if (buttonUnderMouse != 0) + { + const Rectangle r (buttonUnderMouse->getItemPosition (false)); + repaint (0, r.getY(), r.getX(), buttonUnderMouse->getItemHeight()); + } + } + } - bool isMouseOverButton (TreeViewItem* item) const throw() - { - return item == buttonUnderMouse; - } + bool isMouseOverButton (TreeViewItem* item) const throw() + { + return item == buttonUnderMouse; + } - void resized() - { - owner->itemsChanged(); - } + void resized() + { + owner->itemsChanged(); + } - const String getTooltip() - { - int x, y; - getMouseXYRelative (x, y); - Rectangle pos; + const String getTooltip() + { + int x, y; + getMouseXYRelative (x, y); + Rectangle pos; - TreeViewItem* const item = findItemAt (y, pos); + TreeViewItem* const item = findItemAt (y, pos); - if (item != 0) - return item->getTooltip(); + if (item != 0) + return item->getTooltip(); - return owner->getTooltip(); - } + return owner->getTooltip(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - TreeView* const owner; + TreeView* const owner; - VoidArray rowComponentItems; - Array rowComponentIds; - VoidArray rowComponents; - TreeViewItem* buttonUnderMouse; - bool isDragging, needSelectionOnMouseUp; + VoidArray rowComponentItems; + Array rowComponentIds; + VoidArray rowComponents; + TreeViewItem* buttonUnderMouse; + bool isDragging, needSelectionOnMouseUp; - TreeViewContentComponent (const TreeViewContentComponent&); - const TreeViewContentComponent& operator= (const TreeViewContentComponent&); + TreeViewContentComponent (const TreeViewContentComponent&); + const TreeViewContentComponent& operator= (const TreeViewContentComponent&); - void selectBasedOnModifiers (TreeViewItem* const item, const ModifierKeys& modifiers) - { - TreeViewItem* firstSelected = 0; + void selectBasedOnModifiers (TreeViewItem* const item, const ModifierKeys& modifiers) + { + TreeViewItem* firstSelected = 0; - if (modifiers.isShiftDown() && ((firstSelected = owner->getSelectedItem (0)) != 0)) - { - TreeViewItem* const lastSelected = owner->getSelectedItem (owner->getNumSelectedItems() - 1); - jassert (lastSelected != 0); + if (modifiers.isShiftDown() && ((firstSelected = owner->getSelectedItem (0)) != 0)) + { + TreeViewItem* const lastSelected = owner->getSelectedItem (owner->getNumSelectedItems() - 1); + jassert (lastSelected != 0); - int rowStart = firstSelected->getRowNumberInTree(); - int rowEnd = lastSelected->getRowNumberInTree(); - if (rowStart > rowEnd) - swapVariables (rowStart, rowEnd); + int rowStart = firstSelected->getRowNumberInTree(); + int rowEnd = lastSelected->getRowNumberInTree(); + if (rowStart > rowEnd) + swapVariables (rowStart, rowEnd); - int ourRow = item->getRowNumberInTree(); - int otherEnd = ourRow < rowEnd ? rowStart : rowEnd; + int ourRow = item->getRowNumberInTree(); + int otherEnd = ourRow < rowEnd ? rowStart : rowEnd; - if (ourRow > otherEnd) - swapVariables (ourRow, otherEnd); + if (ourRow > otherEnd) + swapVariables (ourRow, otherEnd); - for (int i = ourRow; i <= otherEnd; ++i) - owner->getItemOnRow (i)->setSelected (true, false); - } - else - { - const bool cmd = modifiers.isCommandDown(); + for (int i = ourRow; i <= otherEnd; ++i) + owner->getItemOnRow (i)->setSelected (true, false); + } + else + { + const bool cmd = modifiers.isCommandDown(); - item->setSelected ((! cmd) || (! item->isSelected()), ! cmd); - } - } + item->setSelected ((! cmd) || (! item->isSelected()), ! cmd); + } + } - bool containsItem (TreeViewItem* const item) const - { - for (int i = rowComponentItems.size(); --i >= 0;) - if ((TreeViewItem*) rowComponentItems.getUnchecked (i) == item) - return true; + bool containsItem (TreeViewItem* const item) const + { + for (int i = rowComponentItems.size(); --i >= 0;) + if ((TreeViewItem*) rowComponentItems.getUnchecked (i) == item) + return true; - return false; - } + return false; + } }; class TreeViewport : public Viewport { public: - TreeViewport() throw() {} - ~TreeViewport() throw() {} + TreeViewport() throw() {} + ~TreeViewport() throw() {} - void updateComponents() - { - if (getViewedComponent() != 0) - ((TreeViewContentComponent*) getViewedComponent())->updateComponents(); + void updateComponents() + { + if (getViewedComponent() != 0) + ((TreeViewContentComponent*) getViewedComponent())->updateComponents(); - repaint(); - } + repaint(); + } - void visibleAreaChanged (int, int, int, int) - { - updateComponents(); - } + void visibleAreaChanged (int, int, int, int) + { + updateComponents(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - TreeViewport (const TreeViewport&); - const TreeViewport& operator= (const TreeViewport&); + TreeViewport (const TreeViewport&); + const TreeViewport& operator= (const TreeViewport&); }; TreeView::TreeView (const String& componentName) - : Component (componentName), - rootItem (0), - dragInsertPointHighlight (0), - dragTargetGroupHighlight (0), - indentSize (24), - defaultOpenness (false), - needsRecalculating (true), - rootItemVisible (true), - multiSelectEnabled (false), - openCloseButtonsVisible (true) + : Component (componentName), + rootItem (0), + dragInsertPointHighlight (0), + dragTargetGroupHighlight (0), + indentSize (24), + defaultOpenness (false), + needsRecalculating (true), + rootItemVisible (true), + multiSelectEnabled (false), + openCloseButtonsVisible (true) { - addAndMakeVisible (viewport = new TreeViewport()); - viewport->setViewedComponent (new TreeViewContentComponent (this)); - viewport->setWantsKeyboardFocus (false); - setWantsKeyboardFocus (true); + addAndMakeVisible (viewport = new TreeViewport()); + viewport->setViewedComponent (new TreeViewContentComponent (this)); + viewport->setWantsKeyboardFocus (false); + setWantsKeyboardFocus (true); } TreeView::~TreeView() { - if (rootItem != 0) - rootItem->setOwnerView (0); + if (rootItem != 0) + rootItem->setOwnerView (0); - deleteAllChildren(); + deleteAllChildren(); } void TreeView::setRootItem (TreeViewItem* const newRootItem) { - if (rootItem != newRootItem) - { - if (newRootItem != 0) - { - jassert (newRootItem->ownerView == 0); // can't use a tree item in more than one tree at once.. + if (rootItem != newRootItem) + { + if (newRootItem != 0) + { + jassert (newRootItem->ownerView == 0); // can't use a tree item in more than one tree at once.. - if (newRootItem->ownerView != 0) - newRootItem->ownerView->setRootItem (0); - } + if (newRootItem->ownerView != 0) + newRootItem->ownerView->setRootItem (0); + } - if (rootItem != 0) - rootItem->setOwnerView (0); + if (rootItem != 0) + rootItem->setOwnerView (0); - rootItem = newRootItem; + rootItem = newRootItem; - if (newRootItem != 0) - newRootItem->setOwnerView (this); + if (newRootItem != 0) + newRootItem->setOwnerView (this); - needsRecalculating = true; - handleAsyncUpdate(); + needsRecalculating = true; + handleAsyncUpdate(); - if (rootItem != 0 && (defaultOpenness || ! rootItemVisible)) - { - rootItem->setOpen (false); // force a re-open - rootItem->setOpen (true); - } - } + if (rootItem != 0 && (defaultOpenness || ! rootItemVisible)) + { + rootItem->setOpen (false); // force a re-open + rootItem->setOpen (true); + } + } } void TreeView::deleteRootItem() { - const ScopedPointer deleter (rootItem); - setRootItem (0); + const ScopedPointer deleter (rootItem); + setRootItem (0); } void TreeView::setRootItemVisible (const bool shouldBeVisible) { - rootItemVisible = shouldBeVisible; + rootItemVisible = shouldBeVisible; - if (rootItem != 0 && (defaultOpenness || ! rootItemVisible)) - { - rootItem->setOpen (false); // force a re-open - rootItem->setOpen (true); - } + if (rootItem != 0 && (defaultOpenness || ! rootItemVisible)) + { + rootItem->setOpen (false); // force a re-open + rootItem->setOpen (true); + } - itemsChanged(); + itemsChanged(); } void TreeView::colourChanged() { - setOpaque (findColour (backgroundColourId).isOpaque()); - repaint(); + setOpaque (findColour (backgroundColourId).isOpaque()); + repaint(); } void TreeView::setIndentSize (const int newIndentSize) { - if (indentSize != newIndentSize) - { - indentSize = newIndentSize; - resized(); - } + if (indentSize != newIndentSize) + { + indentSize = newIndentSize; + resized(); + } } void TreeView::setDefaultOpenness (const bool isOpenByDefault) { - if (defaultOpenness != isOpenByDefault) - { - defaultOpenness = isOpenByDefault; - itemsChanged(); - } + if (defaultOpenness != isOpenByDefault) + { + defaultOpenness = isOpenByDefault; + itemsChanged(); + } } void TreeView::setMultiSelectEnabled (const bool canMultiSelect) { - multiSelectEnabled = canMultiSelect; + multiSelectEnabled = canMultiSelect; } void TreeView::setOpenCloseButtonsVisible (const bool shouldBeVisible) { - if (openCloseButtonsVisible != shouldBeVisible) - { - openCloseButtonsVisible = shouldBeVisible; - itemsChanged(); - } + if (openCloseButtonsVisible != shouldBeVisible) + { + openCloseButtonsVisible = shouldBeVisible; + itemsChanged(); + } } void TreeView::clearSelectedItems() { - if (rootItem != 0) - rootItem->deselectAllRecursively(); + if (rootItem != 0) + rootItem->deselectAllRecursively(); } int TreeView::getNumSelectedItems() const throw() { - return (rootItem != 0) ? rootItem->countSelectedItemsRecursively() : 0; + return (rootItem != 0) ? rootItem->countSelectedItemsRecursively() : 0; } TreeViewItem* TreeView::getSelectedItem (const int index) const throw() { - return (rootItem != 0) ? rootItem->getSelectedItemWithIndex (index) : 0; + return (rootItem != 0) ? rootItem->getSelectedItemWithIndex (index) : 0; } int TreeView::getNumRowsInTree() const { - if (rootItem != 0) - return rootItem->getNumRows() - (rootItemVisible ? 0 : 1); + if (rootItem != 0) + return rootItem->getNumRows() - (rootItemVisible ? 0 : 1); - return 0; + return 0; } TreeViewItem* TreeView::getItemOnRow (int index) const { - if (! rootItemVisible) - ++index; + if (! rootItemVisible) + ++index; - if (rootItem != 0 && index >= 0) - return rootItem->getItemOnRow (index); + if (rootItem != 0 && index >= 0) + return rootItem->getItemOnRow (index); - return 0; + return 0; } TreeViewItem* TreeView::getItemAt (int y) const throw() { - TreeViewContentComponent* const tc = (TreeViewContentComponent*) viewport->getViewedComponent(); - int x; - relativePositionToOtherComponent (tc, x, y); - Rectangle pos; - return tc->findItemAt (y, pos); + TreeViewContentComponent* const tc = (TreeViewContentComponent*) viewport->getViewedComponent(); + int x; + relativePositionToOtherComponent (tc, x, y); + Rectangle pos; + return tc->findItemAt (y, pos); } TreeViewItem* TreeView::findItemFromIdentifierString (const String& identifierString) const { - if (rootItem == 0) - return 0; + if (rootItem == 0) + return 0; - return rootItem->findItemFromIdentifierString (identifierString); + return rootItem->findItemFromIdentifierString (identifierString); } XmlElement* TreeView::getOpennessState (const bool alsoIncludeScrollPosition) const { - XmlElement* e = 0; + XmlElement* e = 0; - if (rootItem != 0) - { - e = rootItem->getOpennessState(); + if (rootItem != 0) + { + e = rootItem->getOpennessState(); - if (e != 0 && alsoIncludeScrollPosition) - e->setAttribute (T("scrollPos"), viewport->getViewPositionY()); - } + if (e != 0 && alsoIncludeScrollPosition) + e->setAttribute (T("scrollPos"), viewport->getViewPositionY()); + } - return e; + return e; } void TreeView::restoreOpennessState (const XmlElement& newState) { - if (rootItem != 0) - { - rootItem->restoreOpennessState (newState); + if (rootItem != 0) + { + rootItem->restoreOpennessState (newState); - if (newState.hasAttribute (T("scrollPos"))) - viewport->setViewPosition (viewport->getViewPositionX(), - newState.getIntAttribute (T("scrollPos"))); - } + if (newState.hasAttribute (T("scrollPos"))) + viewport->setViewPosition (viewport->getViewPositionX(), + newState.getIntAttribute (T("scrollPos"))); + } } void TreeView::paint (Graphics& g) { - g.fillAll (findColour (backgroundColourId)); + g.fillAll (findColour (backgroundColourId)); } void TreeView::resized() { - viewport->setBounds (0, 0, getWidth(), getHeight()); + viewport->setBounds (0, 0, getWidth(), getHeight()); - itemsChanged(); - handleAsyncUpdate(); + itemsChanged(); + handleAsyncUpdate(); } void TreeView::enablementChanged() { - repaint(); + repaint(); } void TreeView::moveSelectedRow (int delta) { - if (delta == 0) - return; + if (delta == 0) + return; - int rowSelected = 0; + int rowSelected = 0; - TreeViewItem* const firstSelected = getSelectedItem (0); - if (firstSelected != 0) - rowSelected = firstSelected->getRowNumberInTree(); + TreeViewItem* const firstSelected = getSelectedItem (0); + if (firstSelected != 0) + rowSelected = firstSelected->getRowNumberInTree(); - rowSelected = jlimit (0, getNumRowsInTree() - 1, rowSelected + delta); + rowSelected = jlimit (0, getNumRowsInTree() - 1, rowSelected + delta); - for (;;) - { - TreeViewItem* item = getItemOnRow (rowSelected); + for (;;) + { + TreeViewItem* item = getItemOnRow (rowSelected); - if (item != 0) - { - if (! item->canBeSelected()) - { - // if the row we want to highlight doesn't allow it, try skipping - // to the next item.. - const int nextRowToTry = jlimit (0, getNumRowsInTree() - 1, - rowSelected + (delta < 0 ? -1 : 1)); + if (item != 0) + { + if (! item->canBeSelected()) + { + // if the row we want to highlight doesn't allow it, try skipping + // to the next item.. + const int nextRowToTry = jlimit (0, getNumRowsInTree() - 1, + rowSelected + (delta < 0 ? -1 : 1)); - if (rowSelected != nextRowToTry) - { - rowSelected = nextRowToTry; - continue; - } - else - { - break; - } - } + if (rowSelected != nextRowToTry) + { + rowSelected = nextRowToTry; + continue; + } + else + { + break; + } + } - item->setSelected (true, true); + item->setSelected (true, true); - scrollToKeepItemVisible (item); - } + scrollToKeepItemVisible (item); + } - break; - } + break; + } } void TreeView::scrollToKeepItemVisible (TreeViewItem* item) { - if (item != 0 && item->ownerView == this) - { - handleAsyncUpdate(); + if (item != 0 && item->ownerView == this) + { + handleAsyncUpdate(); - item = item->getDeepestOpenParentItem(); + item = item->getDeepestOpenParentItem(); - int y = item->y; - int viewTop = viewport->getViewPositionY(); + int y = item->y; + int viewTop = viewport->getViewPositionY(); - if (y < viewTop) - { - viewport->setViewPosition (viewport->getViewPositionX(), y); - } - else if (y + item->itemHeight > viewTop + viewport->getViewHeight()) - { - viewport->setViewPosition (viewport->getViewPositionX(), - (y + item->itemHeight) - viewport->getViewHeight()); - } - } + if (y < viewTop) + { + viewport->setViewPosition (viewport->getViewPositionX(), y); + } + else if (y + item->itemHeight > viewTop + viewport->getViewHeight()) + { + viewport->setViewPosition (viewport->getViewPositionX(), + (y + item->itemHeight) - viewport->getViewHeight()); + } + } } bool TreeView::keyPressed (const KeyPress& key) { - if (key.isKeyCode (KeyPress::upKey)) - { - moveSelectedRow (-1); - } - else if (key.isKeyCode (KeyPress::downKey)) - { - moveSelectedRow (1); - } - else if (key.isKeyCode (KeyPress::pageDownKey) || key.isKeyCode (KeyPress::pageUpKey)) - { - if (rootItem != 0) - { - int rowsOnScreen = getHeight() / jmax (1, rootItem->itemHeight); + if (key.isKeyCode (KeyPress::upKey)) + { + moveSelectedRow (-1); + } + else if (key.isKeyCode (KeyPress::downKey)) + { + moveSelectedRow (1); + } + else if (key.isKeyCode (KeyPress::pageDownKey) || key.isKeyCode (KeyPress::pageUpKey)) + { + if (rootItem != 0) + { + int rowsOnScreen = getHeight() / jmax (1, rootItem->itemHeight); - if (key.isKeyCode (KeyPress::pageUpKey)) - rowsOnScreen = -rowsOnScreen; + if (key.isKeyCode (KeyPress::pageUpKey)) + rowsOnScreen = -rowsOnScreen; - moveSelectedRow (rowsOnScreen); - } - } - else if (key.isKeyCode (KeyPress::homeKey)) - { - moveSelectedRow (-0x3fffffff); - } - else if (key.isKeyCode (KeyPress::endKey)) - { - moveSelectedRow (0x3fffffff); - } - else if (key.isKeyCode (KeyPress::returnKey)) - { - TreeViewItem* const firstSelected = getSelectedItem (0); - if (firstSelected != 0) - firstSelected->setOpen (! firstSelected->isOpen()); - } - else if (key.isKeyCode (KeyPress::leftKey)) - { - TreeViewItem* const firstSelected = getSelectedItem (0); + moveSelectedRow (rowsOnScreen); + } + } + else if (key.isKeyCode (KeyPress::homeKey)) + { + moveSelectedRow (-0x3fffffff); + } + else if (key.isKeyCode (KeyPress::endKey)) + { + moveSelectedRow (0x3fffffff); + } + else if (key.isKeyCode (KeyPress::returnKey)) + { + TreeViewItem* const firstSelected = getSelectedItem (0); + if (firstSelected != 0) + firstSelected->setOpen (! firstSelected->isOpen()); + } + else if (key.isKeyCode (KeyPress::leftKey)) + { + TreeViewItem* const firstSelected = getSelectedItem (0); - if (firstSelected != 0) - { - if (firstSelected->isOpen()) - { - firstSelected->setOpen (false); - } - else - { - TreeViewItem* parent = firstSelected->parentItem; + if (firstSelected != 0) + { + if (firstSelected->isOpen()) + { + firstSelected->setOpen (false); + } + else + { + TreeViewItem* parent = firstSelected->parentItem; - if ((! rootItemVisible) && parent == rootItem) - parent = 0; + if ((! rootItemVisible) && parent == rootItem) + parent = 0; - if (parent != 0) - { - parent->setSelected (true, true); - scrollToKeepItemVisible (parent); - } - } - } - } - else if (key.isKeyCode (KeyPress::rightKey)) - { - TreeViewItem* const firstSelected = getSelectedItem (0); + if (parent != 0) + { + parent->setSelected (true, true); + scrollToKeepItemVisible (parent); + } + } + } + } + else if (key.isKeyCode (KeyPress::rightKey)) + { + TreeViewItem* const firstSelected = getSelectedItem (0); - if (firstSelected != 0) - { - if (firstSelected->isOpen() || ! firstSelected->mightContainSubItems()) - moveSelectedRow (1); - else - firstSelected->setOpen (true); - } - } - else - { - return false; - } + if (firstSelected != 0) + { + if (firstSelected->isOpen() || ! firstSelected->mightContainSubItems()) + moveSelectedRow (1); + else + firstSelected->setOpen (true); + } + } + else + { + return false; + } - return true; + return true; } void TreeView::itemsChanged() throw() { - needsRecalculating = true; - repaint(); - triggerAsyncUpdate(); + needsRecalculating = true; + repaint(); + triggerAsyncUpdate(); } void TreeView::handleAsyncUpdate() { - if (needsRecalculating) - { - needsRecalculating = false; + if (needsRecalculating) + { + needsRecalculating = false; - const ScopedLock sl (nodeAlterationLock); + const ScopedLock sl (nodeAlterationLock); - if (rootItem != 0) - rootItem->updatePositions (rootItemVisible ? 0 : -rootItem->itemHeight); + if (rootItem != 0) + rootItem->updatePositions (rootItemVisible ? 0 : -rootItem->itemHeight); - ((TreeViewport*) viewport)->updateComponents(); + ((TreeViewport*) viewport)->updateComponents(); - if (rootItem != 0) - { - viewport->getViewedComponent() - ->setSize (jmax (viewport->getMaximumVisibleWidth(), rootItem->totalWidth), - rootItem->totalHeight - (rootItemVisible ? 0 : rootItem->itemHeight)); - } - else - { - viewport->getViewedComponent()->setSize (0, 0); - } - } + if (rootItem != 0) + { + viewport->getViewedComponent() + ->setSize (jmax (viewport->getMaximumVisibleWidth(), rootItem->totalWidth), + rootItem->totalHeight - (rootItemVisible ? 0 : rootItem->itemHeight)); + } + else + { + viewport->getViewedComponent()->setSize (0, 0); + } + } } class TreeViewDragInsertPointHighlight : public Component { public: - TreeViewDragInsertPointHighlight() - : lastItem (0) - { - setSize (100, 12); - setAlwaysOnTop (true); - setInterceptsMouseClicks (false, false); - } + TreeViewDragInsertPointHighlight() + : lastItem (0) + { + setSize (100, 12); + setAlwaysOnTop (true); + setInterceptsMouseClicks (false, false); + } - ~TreeViewDragInsertPointHighlight() {} + ~TreeViewDragInsertPointHighlight() {} - void setTargetPosition (TreeViewItem* const item, int insertIndex, const int x, const int y, const int width) throw() - { - lastItem = item; - lastIndex = insertIndex; - const int offset = getHeight() / 2; - setBounds (x - offset, y - offset, width - (x - offset), getHeight()); - } + void setTargetPosition (TreeViewItem* const item, int insertIndex, const int x, const int y, const int width) throw() + { + lastItem = item; + lastIndex = insertIndex; + const int offset = getHeight() / 2; + setBounds (x - offset, y - offset, width - (x - offset), getHeight()); + } - void paint (Graphics& g) - { - Path p; - const float h = (float) getHeight(); - p.addEllipse (2.0f, 2.0f, h - 4.0f, h - 4.0f); - p.startNewSubPath (h - 2.0f, h / 2.0f); - p.lineTo ((float) getWidth(), h / 2.0f); + void paint (Graphics& g) + { + Path p; + const float h = (float) getHeight(); + p.addEllipse (2.0f, 2.0f, h - 4.0f, h - 4.0f); + p.startNewSubPath (h - 2.0f, h / 2.0f); + p.lineTo ((float) getWidth(), h / 2.0f); - g.setColour (findColour (TreeView::dragAndDropIndicatorColourId, true)); - g.strokePath (p, PathStrokeType (2.0f)); - } + g.setColour (findColour (TreeView::dragAndDropIndicatorColourId, true)); + g.strokePath (p, PathStrokeType (2.0f)); + } - TreeViewItem* lastItem; - int lastIndex; + TreeViewItem* lastItem; + int lastIndex; }; class TreeViewDragTargetGroupHighlight : public Component { public: - TreeViewDragTargetGroupHighlight() - { - setAlwaysOnTop (true); - setInterceptsMouseClicks (false, false); - } + TreeViewDragTargetGroupHighlight() + { + setAlwaysOnTop (true); + setInterceptsMouseClicks (false, false); + } - ~TreeViewDragTargetGroupHighlight() {} + ~TreeViewDragTargetGroupHighlight() {} - void setTargetPosition (TreeViewItem* const item) throw() - { - Rectangle r (item->getItemPosition (true)); - r.setHeight (item->getItemHeight()); - setBounds (r); - } + void setTargetPosition (TreeViewItem* const item) throw() + { + Rectangle r (item->getItemPosition (true)); + r.setHeight (item->getItemHeight()); + setBounds (r); + } - void paint (Graphics& g) - { - g.setColour (findColour (TreeView::dragAndDropIndicatorColourId, true)); - g.drawRoundedRectangle (1.0f, 1.0f, getWidth() - 2.0f, getHeight() - 2.0f, 3.0f, 2.0f); - } + void paint (Graphics& g) + { + g.setColour (findColour (TreeView::dragAndDropIndicatorColourId, true)); + g.drawRoundedRectangle (1.0f, 1.0f, getWidth() - 2.0f, getHeight() - 2.0f, 3.0f, 2.0f); + } }; void TreeView::showDragHighlight (TreeViewItem* item, int insertIndex, int x, int y) throw() { - beginDragAutoRepeat (1000 / 30); + beginDragAutoRepeat (1000 / 30); - if (dragInsertPointHighlight == 0) - { - addAndMakeVisible (dragInsertPointHighlight = new TreeViewDragInsertPointHighlight()); - addAndMakeVisible (dragTargetGroupHighlight = new TreeViewDragTargetGroupHighlight()); - } + if (dragInsertPointHighlight == 0) + { + addAndMakeVisible (dragInsertPointHighlight = new TreeViewDragInsertPointHighlight()); + addAndMakeVisible (dragTargetGroupHighlight = new TreeViewDragTargetGroupHighlight()); + } - ((TreeViewDragInsertPointHighlight*) dragInsertPointHighlight) - ->setTargetPosition (item, insertIndex, x, y, viewport->getViewWidth()); + ((TreeViewDragInsertPointHighlight*) dragInsertPointHighlight) + ->setTargetPosition (item, insertIndex, x, y, viewport->getViewWidth()); - ((TreeViewDragTargetGroupHighlight*) dragTargetGroupHighlight) - ->setTargetPosition (item); + ((TreeViewDragTargetGroupHighlight*) dragTargetGroupHighlight) + ->setTargetPosition (item); } void TreeView::hideDragHighlight() throw() { - deleteAndZero (dragInsertPointHighlight); - deleteAndZero (dragTargetGroupHighlight); + deleteAndZero (dragInsertPointHighlight); + deleteAndZero (dragTargetGroupHighlight); } TreeViewItem* TreeView::getInsertPosition (int& x, int& y, int& insertIndex, - const StringArray& files, const String& sourceDescription, - Component* sourceComponent) const throw() + const StringArray& files, const String& sourceDescription, + Component* sourceComponent) const throw() { - insertIndex = 0; - TreeViewItem* item = getItemAt (y); + insertIndex = 0; + TreeViewItem* item = getItemAt (y); - if (item == 0) - return 0; + if (item == 0) + return 0; - Rectangle itemPos (item->getItemPosition (true)); - insertIndex = item->getIndexInParent(); - const int oldY = y; - y = itemPos.getY(); + Rectangle itemPos (item->getItemPosition (true)); + insertIndex = item->getIndexInParent(); + const int oldY = y; + y = itemPos.getY(); - if (item->getNumSubItems() == 0 || ! item->isOpen()) - { - if (files.size() > 0 ? item->isInterestedInFileDrag (files) - : item->isInterestedInDragSource (sourceDescription, sourceComponent)) - { - // Check if we're trying to drag into an empty group item.. - if (oldY > itemPos.getY() + itemPos.getHeight() / 4 - && oldY < itemPos.getBottom() - itemPos.getHeight() / 4) - { - insertIndex = 0; - x = itemPos.getX() + getIndentSize(); - y = itemPos.getBottom(); - return item; - } - } - } + if (item->getNumSubItems() == 0 || ! item->isOpen()) + { + if (files.size() > 0 ? item->isInterestedInFileDrag (files) + : item->isInterestedInDragSource (sourceDescription, sourceComponent)) + { + // Check if we're trying to drag into an empty group item.. + if (oldY > itemPos.getY() + itemPos.getHeight() / 4 + && oldY < itemPos.getBottom() - itemPos.getHeight() / 4) + { + insertIndex = 0; + x = itemPos.getX() + getIndentSize(); + y = itemPos.getBottom(); + return item; + } + } + } - if (oldY > itemPos.getCentreY()) - { - y += item->getItemHeight(); + if (oldY > itemPos.getCentreY()) + { + y += item->getItemHeight(); - while (item->isLastOfSiblings() && item->parentItem != 0 - && item->parentItem->parentItem != 0) - { - if (x > itemPos.getX()) - break; + while (item->isLastOfSiblings() && item->parentItem != 0 + && item->parentItem->parentItem != 0) + { + if (x > itemPos.getX()) + break; - item = item->parentItem; - itemPos = item->getItemPosition (true); - insertIndex = item->getIndexInParent(); - } + item = item->parentItem; + itemPos = item->getItemPosition (true); + insertIndex = item->getIndexInParent(); + } - ++insertIndex; - } + ++insertIndex; + } - x = itemPos.getX(); - return item->parentItem; + x = itemPos.getX(); + return item->parentItem; } void TreeView::handleDrag (const StringArray& files, const String& sourceDescription, Component* sourceComponent, int x, int y) { - const bool scrolled = viewport->autoScroll (x, y, 20, 10); + const bool scrolled = viewport->autoScroll (x, y, 20, 10); - int insertIndex; - TreeViewItem* const item = getInsertPosition (x, y, insertIndex, files, sourceDescription, sourceComponent); + int insertIndex; + TreeViewItem* const item = getInsertPosition (x, y, insertIndex, files, sourceDescription, sourceComponent); - if (item != 0) - { - if (scrolled || dragInsertPointHighlight == 0 - || ((TreeViewDragInsertPointHighlight*) dragInsertPointHighlight)->lastItem != item - || ((TreeViewDragInsertPointHighlight*) dragInsertPointHighlight)->lastIndex != insertIndex) - { - if (files.size() > 0 ? item->isInterestedInFileDrag (files) - : item->isInterestedInDragSource (sourceDescription, sourceComponent)) - showDragHighlight (item, insertIndex, x, y); - else - hideDragHighlight(); - } - } - else - { - hideDragHighlight(); - } + if (item != 0) + { + if (scrolled || dragInsertPointHighlight == 0 + || ((TreeViewDragInsertPointHighlight*) dragInsertPointHighlight)->lastItem != item + || ((TreeViewDragInsertPointHighlight*) dragInsertPointHighlight)->lastIndex != insertIndex) + { + if (files.size() > 0 ? item->isInterestedInFileDrag (files) + : item->isInterestedInDragSource (sourceDescription, sourceComponent)) + showDragHighlight (item, insertIndex, x, y); + else + hideDragHighlight(); + } + } + else + { + hideDragHighlight(); + } } void TreeView::handleDrop (const StringArray& files, const String& sourceDescription, Component* sourceComponent, int x, int y) { - hideDragHighlight(); + hideDragHighlight(); - int insertIndex; - TreeViewItem* const item = getInsertPosition (x, y, insertIndex, files, sourceDescription, sourceComponent); + int insertIndex; + TreeViewItem* const item = getInsertPosition (x, y, insertIndex, files, sourceDescription, sourceComponent); - if (item != 0) - { - if (files.size() > 0) - { - if (item->isInterestedInFileDrag (files)) - item->filesDropped (files, insertIndex); - } - else - { - if (item->isInterestedInDragSource (sourceDescription, sourceComponent)) - item->itemDropped (sourceDescription, sourceComponent, insertIndex); - } - } + if (item != 0) + { + if (files.size() > 0) + { + if (item->isInterestedInFileDrag (files)) + item->filesDropped (files, insertIndex); + } + else + { + if (item->isInterestedInDragSource (sourceDescription, sourceComponent)) + item->itemDropped (sourceDescription, sourceComponent, insertIndex); + } + } } bool TreeView::isInterestedInFileDrag (const StringArray& files) { - return true; + return true; } void TreeView::fileDragEnter (const StringArray& files, int x, int y) { - fileDragMove (files, x, y); + fileDragMove (files, x, y); } void TreeView::fileDragMove (const StringArray& files, int x, int y) { - handleDrag (files, String::empty, 0, x, y); + handleDrag (files, String::empty, 0, x, y); } void TreeView::fileDragExit (const StringArray& files) { - hideDragHighlight(); + hideDragHighlight(); } void TreeView::filesDropped (const StringArray& files, int x, int y) { - handleDrop (files, String::empty, 0, x, y); + handleDrop (files, String::empty, 0, x, y); } bool TreeView::isInterestedInDragSource (const String& sourceDescription, Component* sourceComponent) { - return true; + return true; } void TreeView::itemDragEnter (const String& sourceDescription, Component* sourceComponent, int x, int y) { - itemDragMove (sourceDescription, sourceComponent, x, y); + itemDragMove (sourceDescription, sourceComponent, x, y); } void TreeView::itemDragMove (const String& sourceDescription, Component* sourceComponent, int x, int y) { - handleDrag (StringArray(), sourceDescription, sourceComponent, x, y); + handleDrag (StringArray(), sourceDescription, sourceComponent, x, y); } void TreeView::itemDragExit (const String& sourceDescription, Component* sourceComponent) { - hideDragHighlight(); + hideDragHighlight(); } void TreeView::itemDropped (const String& sourceDescription, Component* sourceComponent, int x, int y) { - handleDrop (StringArray(), sourceDescription, sourceComponent, x, y); + handleDrop (StringArray(), sourceDescription, sourceComponent, x, y); } void TreeViewContentComponent::paint (Graphics& g) { - if (owner->rootItem != 0) - { - owner->handleAsyncUpdate(); + if (owner->rootItem != 0) + { + owner->handleAsyncUpdate(); - if (! owner->rootItemVisible) - g.setOrigin (0, -owner->rootItem->itemHeight); + if (! owner->rootItemVisible) + g.setOrigin (0, -owner->rootItem->itemHeight); - owner->rootItem->paintRecursively (g, getWidth()); - } + owner->rootItem->paintRecursively (g, getWidth()); + } } TreeViewItem* TreeViewContentComponent::findItemAt (int y, Rectangle& itemPosition) const { - if (owner->rootItem != 0) - { - owner->handleAsyncUpdate(); + if (owner->rootItem != 0) + { + owner->handleAsyncUpdate(); - if (! owner->rootItemVisible) - y += owner->rootItem->itemHeight; + if (! owner->rootItemVisible) + y += owner->rootItem->itemHeight; - TreeViewItem* const ti = owner->rootItem->findItemRecursively (y); + TreeViewItem* const ti = owner->rootItem->findItemRecursively (y); - if (ti != 0) - itemPosition = ti->getItemPosition (false); + if (ti != 0) + itemPosition = ti->getItemPosition (false); - return ti; - } + return ti; + } - return 0; + return 0; } enum TreeViewOpenness { - opennessDefault = 0, - opennessClosed = 1, - opennessOpen = 2 + opennessDefault = 0, + opennessClosed = 1, + opennessOpen = 2 }; TreeViewItem::TreeViewItem() - : ownerView (0), - parentItem (0), - subItems (8), - y (0), - itemHeight (0), - totalHeight (0), - selected (false), - redrawNeeded (true), - drawLinesInside (true), - drawsInLeftMargin (false), - openness (opennessDefault) + : ownerView (0), + parentItem (0), + y (0), + itemHeight (0), + totalHeight (0), + selected (false), + redrawNeeded (true), + drawLinesInside (true), + drawsInLeftMargin (false), + openness (opennessDefault) { - static int nextUID = 0; - uid = nextUID++; + static int nextUID = 0; + uid = nextUID++; } TreeViewItem::~TreeViewItem() @@ -56490,7 +56193,7 @@ TreeViewItem::~TreeViewItem() const String TreeViewItem::getUniqueName() const { - return String::empty; + return String::empty; } void TreeViewItem::itemOpennessChanged (bool) @@ -56499,128 +56202,128 @@ void TreeViewItem::itemOpennessChanged (bool) int TreeViewItem::getNumSubItems() const throw() { - return subItems.size(); + return subItems.size(); } TreeViewItem* TreeViewItem::getSubItem (const int index) const throw() { - return subItems [index]; + return subItems [index]; } void TreeViewItem::clearSubItems() { - if (subItems.size() > 0) - { - if (ownerView != 0) - { - const ScopedLock sl (ownerView->nodeAlterationLock); - subItems.clear(); - treeHasChanged(); - } - else - { - subItems.clear(); - } - } + if (subItems.size() > 0) + { + if (ownerView != 0) + { + const ScopedLock sl (ownerView->nodeAlterationLock); + subItems.clear(); + treeHasChanged(); + } + else + { + subItems.clear(); + } + } } void TreeViewItem::addSubItem (TreeViewItem* const newItem, const int insertPosition) { - if (newItem != 0) - { - newItem->parentItem = this; - newItem->setOwnerView (ownerView); - newItem->y = 0; - newItem->itemHeight = newItem->getItemHeight(); - newItem->totalHeight = 0; - newItem->itemWidth = newItem->getItemWidth(); - newItem->totalWidth = 0; + if (newItem != 0) + { + newItem->parentItem = this; + newItem->setOwnerView (ownerView); + newItem->y = 0; + newItem->itemHeight = newItem->getItemHeight(); + newItem->totalHeight = 0; + newItem->itemWidth = newItem->getItemWidth(); + newItem->totalWidth = 0; - if (ownerView != 0) - { - const ScopedLock sl (ownerView->nodeAlterationLock); - subItems.insert (insertPosition, newItem); - treeHasChanged(); + if (ownerView != 0) + { + const ScopedLock sl (ownerView->nodeAlterationLock); + subItems.insert (insertPosition, newItem); + treeHasChanged(); - if (newItem->isOpen()) - newItem->itemOpennessChanged (true); - } - else - { - subItems.insert (insertPosition, newItem); + if (newItem->isOpen()) + newItem->itemOpennessChanged (true); + } + else + { + subItems.insert (insertPosition, newItem); - if (newItem->isOpen()) - newItem->itemOpennessChanged (true); - } - } + if (newItem->isOpen()) + newItem->itemOpennessChanged (true); + } + } } void TreeViewItem::removeSubItem (const int index, const bool deleteItem) { - if (ownerView != 0) - ownerView->nodeAlterationLock.enter(); + if (ownerView != 0) + ownerView->nodeAlterationLock.enter(); - if (((unsigned int) index) < (unsigned int) subItems.size()) - { - subItems.remove (index, deleteItem); - treeHasChanged(); - } + if (((unsigned int) index) < (unsigned int) subItems.size()) + { + subItems.remove (index, deleteItem); + treeHasChanged(); + } - if (ownerView != 0) - ownerView->nodeAlterationLock.exit(); + if (ownerView != 0) + ownerView->nodeAlterationLock.exit(); } bool TreeViewItem::isOpen() const throw() { - if (openness == opennessDefault) - return ownerView != 0 && ownerView->defaultOpenness; - else - return openness == opennessOpen; + if (openness == opennessDefault) + return ownerView != 0 && ownerView->defaultOpenness; + else + return openness == opennessOpen; } void TreeViewItem::setOpen (const bool shouldBeOpen) { - if (isOpen() != shouldBeOpen) - { - openness = shouldBeOpen ? opennessOpen - : opennessClosed; + if (isOpen() != shouldBeOpen) + { + openness = shouldBeOpen ? opennessOpen + : opennessClosed; - treeHasChanged(); + treeHasChanged(); - itemOpennessChanged (isOpen()); - } + itemOpennessChanged (isOpen()); + } } bool TreeViewItem::isSelected() const throw() { - return selected; + return selected; } void TreeViewItem::deselectAllRecursively() { - setSelected (false, false); + setSelected (false, false); - for (int i = 0; i < subItems.size(); ++i) - subItems.getUnchecked(i)->deselectAllRecursively(); + for (int i = 0; i < subItems.size(); ++i) + subItems.getUnchecked(i)->deselectAllRecursively(); } void TreeViewItem::setSelected (const bool shouldBeSelected, - const bool deselectOtherItemsFirst) + const bool deselectOtherItemsFirst) { - if (shouldBeSelected && ! canBeSelected()) - return; + if (shouldBeSelected && ! canBeSelected()) + return; - if (deselectOtherItemsFirst) - getTopLevelItem()->deselectAllRecursively(); + if (deselectOtherItemsFirst) + getTopLevelItem()->deselectAllRecursively(); - if (shouldBeSelected != selected) - { - selected = shouldBeSelected; - if (ownerView != 0) - ownerView->repaint(); + if (shouldBeSelected != selected) + { + selected = shouldBeSelected; + if (ownerView != 0) + ownerView->repaint(); - itemSelectionChanged (shouldBeSelected); - } + itemSelectionChanged (shouldBeSelected); + } } void TreeViewItem::paintItem (Graphics&, int, int) @@ -56629,8 +56332,8 @@ void TreeViewItem::paintItem (Graphics&, int, int) void TreeViewItem::paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver) { - ownerView->getLookAndFeel() - .drawTreeviewPlusMinusBox (g, 0, 0, width, height, ! isOpen(), isMouseOver); + ownerView->getLookAndFeel() + .drawTreeviewPlusMinusBox (g, 0, 0, width, height, ! isOpen(), isMouseOver); } void TreeViewItem::itemClicked (const MouseEvent&) @@ -56639,8 +56342,8 @@ void TreeViewItem::itemClicked (const MouseEvent&) void TreeViewItem::itemDoubleClicked (const MouseEvent&) { - if (mightContainSubItems()) - setOpen (! isOpen()); + if (mightContainSubItems()) + setOpen (! isOpen()); } void TreeViewItem::itemSelectionChanged (bool) @@ -56649,17 +56352,17 @@ void TreeViewItem::itemSelectionChanged (bool) const String TreeViewItem::getTooltip() { - return String::empty; + return String::empty; } const String TreeViewItem::getDragSourceDescription() { - return String::empty; + return String::empty; } bool TreeViewItem::isInterestedInFileDrag (const StringArray& files) { - return false; + return false; } void TreeViewItem::filesDropped (const StringArray& files, int insertIndex) @@ -56668,7 +56371,7 @@ void TreeViewItem::filesDropped (const StringArray& files, int insertIndex) bool TreeViewItem::isInterestedInDragSource (const String& sourceDescription, Component* sourceComponent) { - return false; + return false; } void TreeViewItem::itemDropped (const String& sourceDescription, Component* sourceComponent, int insertIndex) @@ -56677,498 +56380,498 @@ void TreeViewItem::itemDropped (const String& sourceDescription, Component* sour const Rectangle TreeViewItem::getItemPosition (const bool relativeToTreeViewTopLeft) const throw() { - const int indentX = getIndentX(); + const int indentX = getIndentX(); - int width = itemWidth; + int width = itemWidth; - if (ownerView != 0 && width < 0) - width = ownerView->viewport->getViewWidth() - indentX; + if (ownerView != 0 && width < 0) + width = ownerView->viewport->getViewWidth() - indentX; - Rectangle r (indentX, y, jmax (0, width), totalHeight); + Rectangle r (indentX, y, jmax (0, width), totalHeight); - if (relativeToTreeViewTopLeft) - r.setPosition (r.getX() - ownerView->viewport->getViewPositionX(), - r.getY() - ownerView->viewport->getViewPositionY()); + if (relativeToTreeViewTopLeft) + r.setPosition (r.getX() - ownerView->viewport->getViewPositionX(), + r.getY() - ownerView->viewport->getViewPositionY()); - return r; + return r; } void TreeViewItem::treeHasChanged() const throw() { - if (ownerView != 0) - ownerView->itemsChanged(); + if (ownerView != 0) + ownerView->itemsChanged(); } void TreeViewItem::repaintItem() const { - if (ownerView != 0 && areAllParentsOpen()) - { - const Rectangle r (getItemPosition (true)); - ownerView->viewport->repaint (0, r.getY(), r.getRight(), r.getHeight()); - } + if (ownerView != 0 && areAllParentsOpen()) + { + const Rectangle r (getItemPosition (true)); + ownerView->viewport->repaint (0, r.getY(), r.getRight(), r.getHeight()); + } } bool TreeViewItem::areAllParentsOpen() const throw() { - return parentItem == 0 - || (parentItem->isOpen() && parentItem->areAllParentsOpen()); + return parentItem == 0 + || (parentItem->isOpen() && parentItem->areAllParentsOpen()); } void TreeViewItem::updatePositions (int newY) { - y = newY; - itemHeight = getItemHeight(); - totalHeight = itemHeight; - itemWidth = getItemWidth(); - totalWidth = jmax (itemWidth, 0) + getIndentX(); + y = newY; + itemHeight = getItemHeight(); + totalHeight = itemHeight; + itemWidth = getItemWidth(); + totalWidth = jmax (itemWidth, 0) + getIndentX(); - if (isOpen()) - { - newY += totalHeight; + if (isOpen()) + { + newY += totalHeight; - for (int i = 0; i < subItems.size(); ++i) - { - TreeViewItem* const ti = subItems.getUnchecked(i); + for (int i = 0; i < subItems.size(); ++i) + { + TreeViewItem* const ti = subItems.getUnchecked(i); - ti->updatePositions (newY); - newY += ti->totalHeight; - totalHeight += ti->totalHeight; - totalWidth = jmax (totalWidth, ti->totalWidth); - } - } + ti->updatePositions (newY); + newY += ti->totalHeight; + totalHeight += ti->totalHeight; + totalWidth = jmax (totalWidth, ti->totalWidth); + } + } } TreeViewItem* TreeViewItem::getDeepestOpenParentItem() throw() { - TreeViewItem* result = this; - TreeViewItem* item = this; + TreeViewItem* result = this; + TreeViewItem* item = this; - while (item->parentItem != 0) - { - item = item->parentItem; + while (item->parentItem != 0) + { + item = item->parentItem; - if (! item->isOpen()) - result = item; - } + if (! item->isOpen()) + result = item; + } - return result; + return result; } void TreeViewItem::setOwnerView (TreeView* const newOwner) throw() { - ownerView = newOwner; + ownerView = newOwner; - for (int i = subItems.size(); --i >= 0;) - subItems.getUnchecked(i)->setOwnerView (newOwner); + for (int i = subItems.size(); --i >= 0;) + subItems.getUnchecked(i)->setOwnerView (newOwner); } int TreeViewItem::getIndentX() const throw() { - const int indentWidth = ownerView->getIndentSize(); - int x = ownerView->rootItemVisible ? indentWidth : 0; + const int indentWidth = ownerView->getIndentSize(); + int x = ownerView->rootItemVisible ? indentWidth : 0; - if (! ownerView->openCloseButtonsVisible) - x -= indentWidth; + if (! ownerView->openCloseButtonsVisible) + x -= indentWidth; - TreeViewItem* p = parentItem; + TreeViewItem* p = parentItem; - while (p != 0) - { - x += indentWidth; - p = p->parentItem; - } + while (p != 0) + { + x += indentWidth; + p = p->parentItem; + } - return x; + return x; } void TreeViewItem::setDrawsInLeftMargin (bool canDrawInLeftMargin) throw() { - drawsInLeftMargin = canDrawInLeftMargin; + drawsInLeftMargin = canDrawInLeftMargin; } void TreeViewItem::paintRecursively (Graphics& g, int width) { - jassert (ownerView != 0); - if (ownerView == 0) - return; + jassert (ownerView != 0); + if (ownerView == 0) + return; - const int indent = getIndentX(); - const int itemW = itemWidth < 0 ? width - indent : itemWidth; + const int indent = getIndentX(); + const int itemW = itemWidth < 0 ? width - indent : itemWidth; - g.setColour (ownerView->findColour (TreeView::linesColourId)); + g.setColour (ownerView->findColour (TreeView::linesColourId)); - const float halfH = itemHeight * 0.5f; - int depth = 0; - TreeViewItem* p = parentItem; + const float halfH = itemHeight * 0.5f; + int depth = 0; + TreeViewItem* p = parentItem; - while (p != 0) - { - ++depth; - p = p->parentItem; - } + while (p != 0) + { + ++depth; + p = p->parentItem; + } - if (! ownerView->rootItemVisible) - --depth; + if (! ownerView->rootItemVisible) + --depth; - const int indentWidth = ownerView->getIndentSize(); + const int indentWidth = ownerView->getIndentSize(); - if (depth >= 0 && ownerView->openCloseButtonsVisible) - { - float x = (depth + 0.5f) * indentWidth; + if (depth >= 0 && ownerView->openCloseButtonsVisible) + { + float x = (depth + 0.5f) * indentWidth; - if (depth >= 0) - { - if (parentItem != 0 && parentItem->drawLinesInside) - g.drawLine (x, 0, x, isLastOfSiblings() ? halfH : (float) itemHeight); + if (depth >= 0) + { + if (parentItem != 0 && parentItem->drawLinesInside) + g.drawLine (x, 0, x, isLastOfSiblings() ? halfH : (float) itemHeight); - if ((parentItem != 0 && parentItem->drawLinesInside) - || (parentItem == 0 && drawLinesInside)) - g.drawLine (x, halfH, x + indentWidth / 2, halfH); - } + if ((parentItem != 0 && parentItem->drawLinesInside) + || (parentItem == 0 && drawLinesInside)) + g.drawLine (x, halfH, x + indentWidth / 2, halfH); + } - p = parentItem; - int d = depth; + p = parentItem; + int d = depth; - while (p != 0 && --d >= 0) - { - x -= (float) indentWidth; + while (p != 0 && --d >= 0) + { + x -= (float) indentWidth; - if ((p->parentItem == 0 || p->parentItem->drawLinesInside) - && ! p->isLastOfSiblings()) - { - g.drawLine (x, 0, x, (float) itemHeight); - } + if ((p->parentItem == 0 || p->parentItem->drawLinesInside) + && ! p->isLastOfSiblings()) + { + g.drawLine (x, 0, x, (float) itemHeight); + } - p = p->parentItem; - } + p = p->parentItem; + } - if (mightContainSubItems()) - { - g.saveState(); - g.setOrigin (depth * indentWidth, 0); - g.reduceClipRegion (0, 0, indentWidth, itemHeight); + if (mightContainSubItems()) + { + g.saveState(); + g.setOrigin (depth * indentWidth, 0); + g.reduceClipRegion (0, 0, indentWidth, itemHeight); - paintOpenCloseButton (g, indentWidth, itemHeight, - ((TreeViewContentComponent*) ownerView->viewport->getViewedComponent()) - ->isMouseOverButton (this)); + paintOpenCloseButton (g, indentWidth, itemHeight, + ((TreeViewContentComponent*) ownerView->viewport->getViewedComponent()) + ->isMouseOverButton (this)); - g.restoreState(); - } - } + g.restoreState(); + } + } - { - g.saveState(); - g.setOrigin (indent, 0); + { + g.saveState(); + g.setOrigin (indent, 0); - if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, - drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) - paintItem (g, itemW, itemHeight); + if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, + drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) + paintItem (g, itemW, itemHeight); - g.restoreState(); - } + g.restoreState(); + } - if (isOpen()) - { - const Rectangle clip (g.getClipBounds()); + if (isOpen()) + { + const Rectangle clip (g.getClipBounds()); - for (int i = 0; i < subItems.size(); ++i) - { - TreeViewItem* const ti = subItems.getUnchecked(i); + for (int i = 0; i < subItems.size(); ++i) + { + TreeViewItem* const ti = subItems.getUnchecked(i); - const int relY = ti->y - y; + const int relY = ti->y - y; - if (relY >= clip.getBottom()) - break; + if (relY >= clip.getBottom()) + break; - if (relY + ti->totalHeight >= clip.getY()) - { - g.saveState(); - g.setOrigin (0, relY); + if (relY + ti->totalHeight >= clip.getY()) + { + g.saveState(); + g.setOrigin (0, relY); - if (g.reduceClipRegion (0, 0, width, ti->totalHeight)) - ti->paintRecursively (g, width); + if (g.reduceClipRegion (0, 0, width, ti->totalHeight)) + ti->paintRecursively (g, width); - g.restoreState(); - } - } - } + g.restoreState(); + } + } + } } bool TreeViewItem::isLastOfSiblings() const throw() { - return parentItem == 0 - || parentItem->subItems.getLast() == this; + return parentItem == 0 + || parentItem->subItems.getLast() == this; } int TreeViewItem::getIndexInParent() const throw() { - if (parentItem == 0) - return 0; + if (parentItem == 0) + return 0; - return parentItem->subItems.indexOf (this); + return parentItem->subItems.indexOf (this); } TreeViewItem* TreeViewItem::getTopLevelItem() throw() { - return (parentItem == 0) ? this - : parentItem->getTopLevelItem(); + return (parentItem == 0) ? this + : parentItem->getTopLevelItem(); } int TreeViewItem::getNumRows() const throw() { - int num = 1; + int num = 1; - if (isOpen()) - { - for (int i = subItems.size(); --i >= 0;) - num += subItems.getUnchecked(i)->getNumRows(); - } + if (isOpen()) + { + for (int i = subItems.size(); --i >= 0;) + num += subItems.getUnchecked(i)->getNumRows(); + } - return num; + return num; } TreeViewItem* TreeViewItem::getItemOnRow (int index) throw() { - if (index == 0) - return this; + if (index == 0) + return this; - if (index > 0 && isOpen()) - { - --index; + if (index > 0 && isOpen()) + { + --index; - for (int i = 0; i < subItems.size(); ++i) - { - TreeViewItem* const item = subItems.getUnchecked(i); + for (int i = 0; i < subItems.size(); ++i) + { + TreeViewItem* const item = subItems.getUnchecked(i); - if (index == 0) - return item; + if (index == 0) + return item; - const int numRows = item->getNumRows(); + const int numRows = item->getNumRows(); - if (numRows > index) - return item->getItemOnRow (index); + if (numRows > index) + return item->getItemOnRow (index); - index -= numRows; - } - } + index -= numRows; + } + } - return 0; + return 0; } TreeViewItem* TreeViewItem::findItemRecursively (int targetY) throw() { - if (((unsigned int) targetY) < (unsigned int) totalHeight) - { - const int h = itemHeight; + if (((unsigned int) targetY) < (unsigned int) totalHeight) + { + const int h = itemHeight; - if (targetY < h) - return this; + if (targetY < h) + return this; - if (isOpen()) - { - targetY -= h; + if (isOpen()) + { + targetY -= h; - for (int i = 0; i < subItems.size(); ++i) - { - TreeViewItem* const ti = subItems.getUnchecked(i); + for (int i = 0; i < subItems.size(); ++i) + { + TreeViewItem* const ti = subItems.getUnchecked(i); - if (targetY < ti->totalHeight) - return ti->findItemRecursively (targetY); + if (targetY < ti->totalHeight) + return ti->findItemRecursively (targetY); - targetY -= ti->totalHeight; - } - } - } + targetY -= ti->totalHeight; + } + } + } - return 0; + return 0; } int TreeViewItem::countSelectedItemsRecursively() const throw() { - int total = 0; + int total = 0; - if (isSelected()) - ++total; + if (isSelected()) + ++total; - for (int i = subItems.size(); --i >= 0;) - total += subItems.getUnchecked(i)->countSelectedItemsRecursively(); + for (int i = subItems.size(); --i >= 0;) + total += subItems.getUnchecked(i)->countSelectedItemsRecursively(); - return total; + return total; } TreeViewItem* TreeViewItem::getSelectedItemWithIndex (int index) throw() { - if (isSelected()) - { - if (index == 0) - return this; + if (isSelected()) + { + if (index == 0) + return this; - --index; - } + --index; + } - if (index >= 0) - { - for (int i = 0; i < subItems.size(); ++i) - { - TreeViewItem* const item = subItems.getUnchecked(i); + if (index >= 0) + { + for (int i = 0; i < subItems.size(); ++i) + { + TreeViewItem* const item = subItems.getUnchecked(i); - TreeViewItem* const found = item->getSelectedItemWithIndex (index); + TreeViewItem* const found = item->getSelectedItemWithIndex (index); - if (found != 0) - return found; + if (found != 0) + return found; - index -= item->countSelectedItemsRecursively(); - } - } + index -= item->countSelectedItemsRecursively(); + } + } - return 0; + return 0; } int TreeViewItem::getRowNumberInTree() const throw() { - if (parentItem != 0 && ownerView != 0) - { - int n = 1 + parentItem->getRowNumberInTree(); + if (parentItem != 0 && ownerView != 0) + { + int n = 1 + parentItem->getRowNumberInTree(); - int ourIndex = parentItem->subItems.indexOf (this); - jassert (ourIndex >= 0); + int ourIndex = parentItem->subItems.indexOf (this); + jassert (ourIndex >= 0); - while (--ourIndex >= 0) - n += parentItem->subItems [ourIndex]->getNumRows(); + while (--ourIndex >= 0) + n += parentItem->subItems [ourIndex]->getNumRows(); - if (parentItem->parentItem == 0 - && ! ownerView->rootItemVisible) - --n; + if (parentItem->parentItem == 0 + && ! ownerView->rootItemVisible) + --n; - return n; - } - else - { - return 0; - } + return n; + } + else + { + return 0; + } } void TreeViewItem::setLinesDrawnForSubItems (const bool drawLines) throw() { - drawLinesInside = drawLines; + drawLinesInside = drawLines; } TreeViewItem* TreeViewItem::getNextVisibleItem (const bool recurse) const throw() { - if (recurse && isOpen() && subItems.size() > 0) - return subItems [0]; + if (recurse && isOpen() && subItems.size() > 0) + return subItems [0]; - if (parentItem != 0) - { - const int nextIndex = parentItem->subItems.indexOf (this) + 1; + if (parentItem != 0) + { + const int nextIndex = parentItem->subItems.indexOf (this) + 1; - if (nextIndex >= parentItem->subItems.size()) - return parentItem->getNextVisibleItem (false); + if (nextIndex >= parentItem->subItems.size()) + return parentItem->getNextVisibleItem (false); - return parentItem->subItems [nextIndex]; - } + return parentItem->subItems [nextIndex]; + } - return 0; + return 0; } const String TreeViewItem::getItemIdentifierString() const { - String s; + String s; - if (parentItem != 0) - s = parentItem->getItemIdentifierString(); + if (parentItem != 0) + s = parentItem->getItemIdentifierString(); - return s + T("/") + getUniqueName().replaceCharacter (T('/'), T('\\')); + return s + T("/") + getUniqueName().replaceCharacter (T('/'), T('\\')); } TreeViewItem* TreeViewItem::findItemFromIdentifierString (const String& identifierString) { - const String uid (getUniqueName()); + const String uid (getUniqueName()); - if (uid == identifierString) - return this; + if (uid == identifierString) + return this; - if (identifierString.startsWith (uid + T("/"))) - { - const String remainingPath (identifierString.substring (uid.length() + 1)); + if (identifierString.startsWith (uid + T("/"))) + { + const String remainingPath (identifierString.substring (uid.length() + 1)); - bool wasOpen = isOpen(); - setOpen (true); + bool wasOpen = isOpen(); + setOpen (true); - for (int i = subItems.size(); --i >= 0;) - { - TreeViewItem* item = subItems.getUnchecked(i)->findItemFromIdentifierString (remainingPath); + for (int i = subItems.size(); --i >= 0;) + { + TreeViewItem* item = subItems.getUnchecked(i)->findItemFromIdentifierString (remainingPath); - if (item != 0) - return item; - } + if (item != 0) + return item; + } - setOpen (wasOpen); - } + setOpen (wasOpen); + } - return 0; + return 0; } void TreeViewItem::restoreOpennessState (const XmlElement& e) throw() { - if (e.hasTagName (T("CLOSED"))) - { - setOpen (false); - } - else if (e.hasTagName (T("OPEN"))) - { - setOpen (true); + if (e.hasTagName (T("CLOSED"))) + { + setOpen (false); + } + else if (e.hasTagName (T("OPEN"))) + { + setOpen (true); - forEachXmlChildElement (e, n) - { - const String id (n->getStringAttribute (T("id"))); + forEachXmlChildElement (e, n) + { + const String id (n->getStringAttribute (T("id"))); - for (int i = 0; i < subItems.size(); ++i) - { - TreeViewItem* const ti = subItems.getUnchecked(i); + for (int i = 0; i < subItems.size(); ++i) + { + TreeViewItem* const ti = subItems.getUnchecked(i); - if (ti->getUniqueName() == id) - { - ti->restoreOpennessState (*n); - break; - } - } - } - } + if (ti->getUniqueName() == id) + { + ti->restoreOpennessState (*n); + break; + } + } + } + } } XmlElement* TreeViewItem::getOpennessState() const throw() { - const String name (getUniqueName()); + const String name (getUniqueName()); - if (name.isNotEmpty()) - { - XmlElement* e; + if (name.isNotEmpty()) + { + XmlElement* e; - if (isOpen()) - { - e = new XmlElement (T("OPEN")); + if (isOpen()) + { + e = new XmlElement (T("OPEN")); - for (int i = 0; i < subItems.size(); ++i) - e->addChildElement (subItems.getUnchecked(i)->getOpennessState()); - } - else - { - e = new XmlElement (T("CLOSED")); - } + for (int i = 0; i < subItems.size(); ++i) + e->addChildElement (subItems.getUnchecked(i)->getOpennessState()); + } + else + { + e = new XmlElement (T("CLOSED")); + } - e->setAttribute (T("id"), name); + e->setAttribute (T("id"), name); - return e; - } - else - { - // trying to save the openness for an element that has no name - this won't - // work because it needs the names to identify what to open. - jassertfalse - } + return e; + } + else + { + // trying to save the openness for an element that has no name - this won't + // work because it needs the names to identify what to open. + jassertfalse + } - return 0; + return 0; } END_JUCE_NAMESPACE @@ -57179,8 +56882,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE DirectoryContentsDisplayComponent::DirectoryContentsDisplayComponent (DirectoryContentsList& listToShow) - : fileList (listToShow), - listeners (2) + : fileList (listToShow) { } @@ -57194,66 +56896,66 @@ FileBrowserListener::~FileBrowserListener() void DirectoryContentsDisplayComponent::addListener (FileBrowserListener* const listener) throw() { - jassert (listener != 0); + jassert (listener != 0); - if (listener != 0) - listeners.add (listener); + if (listener != 0) + listeners.add (listener); } void DirectoryContentsDisplayComponent::removeListener (FileBrowserListener* const listener) throw() { - listeners.removeValue (listener); + listeners.removeValue (listener); } void DirectoryContentsDisplayComponent::sendSelectionChangeMessage() { - const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); + const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); - for (int i = listeners.size(); --i >= 0;) - { - ((FileBrowserListener*) listeners.getUnchecked (i))->selectionChanged(); + for (int i = listeners.size(); --i >= 0;) + { + ((FileBrowserListener*) listeners.getUnchecked (i))->selectionChanged(); - if (deletionWatcher.hasBeenDeleted()) - return; + if (deletionWatcher.hasBeenDeleted()) + return; - i = jmin (i, listeners.size() - 1); - } + i = jmin (i, listeners.size() - 1); + } } void DirectoryContentsDisplayComponent::sendMouseClickMessage (const File& file, const MouseEvent& e) { - if (fileList.getDirectory().exists()) - { - const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); + if (fileList.getDirectory().exists()) + { + const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); - for (int i = listeners.size(); --i >= 0;) - { - ((FileBrowserListener*) listeners.getUnchecked (i))->fileClicked (file, e); + for (int i = listeners.size(); --i >= 0;) + { + ((FileBrowserListener*) listeners.getUnchecked (i))->fileClicked (file, e); - if (deletionWatcher.hasBeenDeleted()) - return; + if (deletionWatcher.hasBeenDeleted()) + return; - i = jmin (i, listeners.size() - 1); - } - } + i = jmin (i, listeners.size() - 1); + } + } } void DirectoryContentsDisplayComponent::sendDoubleClickMessage (const File& file) { - if (fileList.getDirectory().exists()) - { - const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); + if (fileList.getDirectory().exists()) + { + const ComponentDeletionWatcher deletionWatcher (dynamic_cast (this)); - for (int i = listeners.size(); --i >= 0;) - { - ((FileBrowserListener*) listeners.getUnchecked (i))->fileDoubleClicked (file); + for (int i = listeners.size(); --i >= 0;) + { + ((FileBrowserListener*) listeners.getUnchecked (i))->fileDoubleClicked (file); - if (deletionWatcher.hasBeenDeleted()) - return; + if (deletionWatcher.hasBeenDeleted()) + return; - i = jmin (i, listeners.size() - 1); - } - } + i = jmin (i, listeners.size() - 1); + } + } } END_JUCE_NAMESPACE @@ -57264,267 +56966,267 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile, - bool* isDirectory, bool* isHidden, int64* fileSize, Time* modTime, - Time* creationTime, bool* isReadOnly); + bool* isDirectory, bool* isHidden, int64* fileSize, Time* modTime, + Time* creationTime, bool* isReadOnly); bool juce_findFileNext (void* handle, String& resultFile, - bool* isDirectory, bool* isHidden, int64* fileSize, - Time* modTime, Time* creationTime, bool* isReadOnly); + bool* isDirectory, bool* isHidden, int64* fileSize, + Time* modTime, Time* creationTime, bool* isReadOnly); void juce_findFileClose (void* handle); DirectoryContentsList::DirectoryContentsList (const FileFilter* const fileFilter_, - TimeSliceThread& thread_) + TimeSliceThread& thread_) : fileFilter (fileFilter_), - thread (thread_), - includeDirectories (false), - includeFiles (false), - ignoreHiddenFiles (true), - fileFindHandle (0), - shouldStop (true) + thread (thread_), + includeDirectories (false), + includeFiles (false), + ignoreHiddenFiles (true), + fileFindHandle (0), + shouldStop (true) { } DirectoryContentsList::~DirectoryContentsList() { - clear(); + clear(); } void DirectoryContentsList::setIgnoresHiddenFiles (const bool shouldIgnoreHiddenFiles) { - ignoreHiddenFiles = shouldIgnoreHiddenFiles; + ignoreHiddenFiles = shouldIgnoreHiddenFiles; } const File& DirectoryContentsList::getDirectory() const { - return root; + return root; } void DirectoryContentsList::setDirectory (const File& directory, - const bool includeDirectories_, - const bool includeFiles_) + const bool includeDirectories_, + const bool includeFiles_) { - if (directory != root - || includeDirectories != includeDirectories_ - || includeFiles != includeFiles_) - { - clear(); + if (directory != root + || includeDirectories != includeDirectories_ + || includeFiles != includeFiles_) + { + clear(); - root = directory; - includeDirectories = includeDirectories_; - includeFiles = includeFiles_; + root = directory; + includeDirectories = includeDirectories_; + includeFiles = includeFiles_; - refresh(); - } + refresh(); + } } void DirectoryContentsList::clear() { - shouldStop = true; - thread.removeTimeSliceClient (this); + shouldStop = true; + thread.removeTimeSliceClient (this); - if (fileFindHandle != 0) - { - juce_findFileClose (fileFindHandle); - fileFindHandle = 0; - } + if (fileFindHandle != 0) + { + juce_findFileClose (fileFindHandle); + fileFindHandle = 0; + } - if (files.size() > 0) - { - files.clear(); - changed(); - } + if (files.size() > 0) + { + files.clear(); + changed(); + } } void DirectoryContentsList::refresh() { - clear(); + clear(); - if (root.isDirectory()) - { - String fileFound; - bool fileFoundIsDir, isHidden, isReadOnly; - int64 fileSize; - Time modTime, creationTime; + if (root.isDirectory()) + { + String fileFound; + bool fileFoundIsDir, isHidden, isReadOnly; + int64 fileSize; + Time modTime, creationTime; - String path (root.getFullPathName()); - if (! path.endsWithChar (File::separator)) - path += File::separator; + String path (root.getFullPathName()); + if (! path.endsWithChar (File::separator)) + path += File::separator; - jassert (fileFindHandle == 0); + jassert (fileFindHandle == 0); - fileFindHandle = juce_findFileStart (path, T("*"), fileFound, - &fileFoundIsDir, - &isHidden, - &fileSize, - &modTime, - &creationTime, - &isReadOnly); + fileFindHandle = juce_findFileStart (path, T("*"), fileFound, + &fileFoundIsDir, + &isHidden, + &fileSize, + &modTime, + &creationTime, + &isReadOnly); - if (fileFindHandle != 0 && fileFound.isNotEmpty()) - { - if (addFile (fileFound, fileFoundIsDir, isHidden, - fileSize, modTime, creationTime, isReadOnly)) - { - changed(); - } - } + if (fileFindHandle != 0 && fileFound.isNotEmpty()) + { + if (addFile (fileFound, fileFoundIsDir, isHidden, + fileSize, modTime, creationTime, isReadOnly)) + { + changed(); + } + } - shouldStop = false; + shouldStop = false; - thread.addTimeSliceClient (this); - } + thread.addTimeSliceClient (this); + } } int DirectoryContentsList::getNumFiles() const { - return files.size(); + return files.size(); } bool DirectoryContentsList::getFileInfo (const int index, - FileInfo& result) const + FileInfo& result) const { - const ScopedLock sl (fileListLock); - const FileInfo* const info = files [index]; + const ScopedLock sl (fileListLock); + const FileInfo* const info = files [index]; - if (info != 0) - { - result = *info; - return true; - } + if (info != 0) + { + result = *info; + return true; + } - return false; + return false; } const File DirectoryContentsList::getFile (const int index) const { - const ScopedLock sl (fileListLock); - const FileInfo* const info = files [index]; + const ScopedLock sl (fileListLock); + const FileInfo* const info = files [index]; - if (info != 0) - return root.getChildFile (info->filename); + if (info != 0) + return root.getChildFile (info->filename); - return File::nonexistent; + return File::nonexistent; } bool DirectoryContentsList::isStillLoading() const { - return fileFindHandle != 0; + return fileFindHandle != 0; } void DirectoryContentsList::changed() { - sendChangeMessage (this); + sendChangeMessage (this); } bool DirectoryContentsList::useTimeSlice() { - const uint32 startTime = Time::getApproximateMillisecondCounter(); - bool hasChanged = false; + const uint32 startTime = Time::getApproximateMillisecondCounter(); + bool hasChanged = false; - for (int i = 100; --i >= 0;) - { - if (! checkNextFile (hasChanged)) - { - if (hasChanged) - changed(); + for (int i = 100; --i >= 0;) + { + if (! checkNextFile (hasChanged)) + { + if (hasChanged) + changed(); - return false; - } + return false; + } - if (shouldStop || (Time::getApproximateMillisecondCounter() > startTime + 150)) - break; - } + if (shouldStop || (Time::getApproximateMillisecondCounter() > startTime + 150)) + break; + } - if (hasChanged) - changed(); + if (hasChanged) + changed(); - return true; + return true; } bool DirectoryContentsList::checkNextFile (bool& hasChanged) { - if (fileFindHandle != 0) - { - String fileFound; - bool fileFoundIsDir, isHidden, isReadOnly; - int64 fileSize; - Time modTime, creationTime; + if (fileFindHandle != 0) + { + String fileFound; + bool fileFoundIsDir, isHidden, isReadOnly; + int64 fileSize; + Time modTime, creationTime; - if (juce_findFileNext (fileFindHandle, fileFound, - &fileFoundIsDir, &isHidden, - &fileSize, - &modTime, - &creationTime, - &isReadOnly)) - { - if (addFile (fileFound, fileFoundIsDir, isHidden, fileSize, - modTime, creationTime, isReadOnly)) - { - hasChanged = true; - } + if (juce_findFileNext (fileFindHandle, fileFound, + &fileFoundIsDir, &isHidden, + &fileSize, + &modTime, + &creationTime, + &isReadOnly)) + { + if (addFile (fileFound, fileFoundIsDir, isHidden, fileSize, + modTime, creationTime, isReadOnly)) + { + hasChanged = true; + } - return true; - } - else - { - juce_findFileClose (fileFindHandle); - fileFindHandle = 0; - } - } + return true; + } + else + { + juce_findFileClose (fileFindHandle); + fileFindHandle = 0; + } + } - return false; + return false; } int DirectoryContentsList::compareElements (const DirectoryContentsList::FileInfo* const first, - const DirectoryContentsList::FileInfo* const second) + const DirectoryContentsList::FileInfo* const second) { #if JUCE_WINDOWS - if (first->isDirectory != second->isDirectory) - return first->isDirectory ? -1 : 1; + if (first->isDirectory != second->isDirectory) + return first->isDirectory ? -1 : 1; #endif - return first->filename.compareIgnoreCase (second->filename); + return first->filename.compareIgnoreCase (second->filename); } bool DirectoryContentsList::addFile (const String& filename, - const bool isDir, - const bool isHidden, - const int64 fileSize, - const Time& modTime, - const Time& creationTime, - const bool isReadOnly) + const bool isDir, + const bool isHidden, + const int64 fileSize, + const Time& modTime, + const Time& creationTime, + const bool isReadOnly) { - if (filename == T("..") - || filename == T(".") - || (ignoreHiddenFiles && isHidden)) - return false; + if (filename == T("..") + || filename == T(".") + || (ignoreHiddenFiles && isHidden)) + return false; - const File file (root.getChildFile (filename)); + const File file (root.getChildFile (filename)); - if (((isDir && includeDirectories) || ((! isDir) && includeFiles)) - && (fileFilter == 0 - || ((! isDir) && fileFilter->isFileSuitable (file)) - || (isDir && fileFilter->isDirectorySuitable (file)))) - { - ScopedPointer info (new FileInfo()); + if (((isDir && includeDirectories) || ((! isDir) && includeFiles)) + && (fileFilter == 0 + || ((! isDir) && fileFilter->isFileSuitable (file)) + || (isDir && fileFilter->isDirectorySuitable (file)))) + { + ScopedPointer info (new FileInfo()); - info->filename = filename; - info->fileSize = fileSize; - info->modificationTime = modTime; - info->creationTime = creationTime; - info->isDirectory = isDir; - info->isReadOnly = isReadOnly; + info->filename = filename; + info->fileSize = fileSize; + info->modificationTime = modTime; + info->creationTime = creationTime; + info->isDirectory = isDir; + info->isReadOnly = isReadOnly; - const ScopedLock sl (fileListLock); + const ScopedLock sl (fileListLock); - for (int i = files.size(); --i >= 0;) - if (files.getUnchecked(i)->filename == info->filename) - return false; + for (int i = files.size(); --i >= 0;) + if (files.getUnchecked(i)->filename == info->filename) + return false; - files.addSorted (*this, info.release()); - return true; - } + files.addSorted (*this, info.release()); + return true; + } - return false; + return false; } END_JUCE_NAMESPACE @@ -57535,392 +57237,391 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE FileBrowserComponent::FileBrowserComponent (int flags_, - const File& initialFileOrDirectory, - const FileFilter* fileFilter_, - FilePreviewComponent* previewComp_) + const File& initialFileOrDirectory, + const FileFilter* fileFilter_, + FilePreviewComponent* previewComp_) : FileFilter (String::empty), - fileFilter (fileFilter_), - flags (flags_), - listeners (2), - previewComp (previewComp_), - thread ("Juce FileBrowser") + fileFilter (fileFilter_), + flags (flags_), + previewComp (previewComp_), + thread ("Juce FileBrowser") { - // You need to specify one or other of the open/save flags.. - jassert ((flags & (saveMode | openMode)) != 0); - jassert ((flags & (saveMode | openMode)) != (saveMode | openMode)); + // You need to specify one or other of the open/save flags.. + jassert ((flags & (saveMode | openMode)) != 0); + jassert ((flags & (saveMode | openMode)) != (saveMode | openMode)); - // You need to specify at least one of these flags.. - jassert ((flags & (canSelectFiles | canSelectDirectories)) != 0); + // You need to specify at least one of these flags.. + jassert ((flags & (canSelectFiles | canSelectDirectories)) != 0); - String filename; + String filename; - if (initialFileOrDirectory == File::nonexistent) - { - currentRoot = File::getCurrentWorkingDirectory(); - } - else if (initialFileOrDirectory.isDirectory()) - { - currentRoot = initialFileOrDirectory; - } - else - { - chosenFiles.add (new File (initialFileOrDirectory)); - currentRoot = initialFileOrDirectory.getParentDirectory(); - filename = initialFileOrDirectory.getFileName(); - } + if (initialFileOrDirectory == File::nonexistent) + { + currentRoot = File::getCurrentWorkingDirectory(); + } + else if (initialFileOrDirectory.isDirectory()) + { + currentRoot = initialFileOrDirectory; + } + else + { + chosenFiles.add (new File (initialFileOrDirectory)); + currentRoot = initialFileOrDirectory.getParentDirectory(); + filename = initialFileOrDirectory.getFileName(); + } - fileList = new DirectoryContentsList (this, thread); + fileList = new DirectoryContentsList (this, thread); - if ((flags & useTreeView) != 0) - { - FileTreeComponent* const tree = new FileTreeComponent (*fileList); + if ((flags & useTreeView) != 0) + { + FileTreeComponent* const tree = new FileTreeComponent (*fileList); - if ((flags & canSelectMultipleItems) != 0) - tree->setMultiSelectEnabled (true); + if ((flags & canSelectMultipleItems) != 0) + tree->setMultiSelectEnabled (true); - addAndMakeVisible (tree); - fileListComponent = tree; - } - else - { - FileListComponent* const list = new FileListComponent (*fileList); - list->setOutlineThickness (1); + addAndMakeVisible (tree); + fileListComponent = tree; + } + else + { + FileListComponent* const list = new FileListComponent (*fileList); + list->setOutlineThickness (1); - if ((flags & canSelectMultipleItems) != 0) - list->setMultipleSelectionEnabled (true); + if ((flags & canSelectMultipleItems) != 0) + list->setMultipleSelectionEnabled (true); - addAndMakeVisible (list); - fileListComponent = list; - } + addAndMakeVisible (list); + fileListComponent = list; + } - fileListComponent->addListener (this); + fileListComponent->addListener (this); - addAndMakeVisible (currentPathBox = new ComboBox ("path")); - currentPathBox->setEditableText (true); + addAndMakeVisible (currentPathBox = new ComboBox ("path")); + currentPathBox->setEditableText (true); - StringArray rootNames, rootPaths; - const BitArray separators (getRoots (rootNames, rootPaths)); + StringArray rootNames, rootPaths; + const BitArray separators (getRoots (rootNames, rootPaths)); - for (int i = 0; i < rootNames.size(); ++i) - { - if (separators [i]) - currentPathBox->addSeparator(); + for (int i = 0; i < rootNames.size(); ++i) + { + if (separators [i]) + currentPathBox->addSeparator(); - currentPathBox->addItem (rootNames[i], i + 1); - } + currentPathBox->addItem (rootNames[i], i + 1); + } - currentPathBox->addSeparator(); - currentPathBox->addListener (this); + currentPathBox->addSeparator(); + currentPathBox->addListener (this); - addAndMakeVisible (filenameBox = new TextEditor()); - filenameBox->setMultiLine (false); - filenameBox->setSelectAllWhenFocused (true); - filenameBox->setText (filename, false); + addAndMakeVisible (filenameBox = new TextEditor()); + filenameBox->setMultiLine (false); + filenameBox->setSelectAllWhenFocused (true); + filenameBox->setText (filename, false); - filenameBox->addListener (this); - filenameBox->setReadOnly ((flags & (filenameBoxIsReadOnly | canSelectMultipleItems)) != 0); + filenameBox->addListener (this); + filenameBox->setReadOnly ((flags & (filenameBoxIsReadOnly | canSelectMultipleItems)) != 0); - Label* label = new Label ("f", TRANS("file:")); - addAndMakeVisible (label); - label->attachToComponent (filenameBox, true); + Label* label = new Label ("f", TRANS("file:")); + addAndMakeVisible (label); + label->attachToComponent (filenameBox, true); - addAndMakeVisible (goUpButton = getLookAndFeel().createFileBrowserGoUpButton()); + addAndMakeVisible (goUpButton = getLookAndFeel().createFileBrowserGoUpButton()); - goUpButton->addButtonListener (this); - goUpButton->setTooltip (TRANS ("go up to parent directory")); + goUpButton->addButtonListener (this); + goUpButton->setTooltip (TRANS ("go up to parent directory")); - if (previewComp != 0) - addAndMakeVisible (previewComp); + if (previewComp != 0) + addAndMakeVisible (previewComp); - setRoot (currentRoot); + setRoot (currentRoot); - thread.startThread (4); + thread.startThread (4); } FileBrowserComponent::~FileBrowserComponent() { - if (previewComp != 0) - removeChildComponent (previewComp); + if (previewComp != 0) + removeChildComponent (previewComp); - deleteAllChildren(); - fileList = 0; - thread.stopThread (10000); + deleteAllChildren(); + fileList = 0; + thread.stopThread (10000); } void FileBrowserComponent::addListener (FileBrowserListener* const newListener) throw() { - jassert (newListener != 0) + jassert (newListener != 0) - if (newListener != 0) - listeners.add (newListener); + if (newListener != 0) + listeners.add (newListener); } void FileBrowserComponent::removeListener (FileBrowserListener* const listener) throw() { - listeners.removeValue (listener); + listeners.removeValue (listener); } bool FileBrowserComponent::isSaveMode() const throw() { - return (flags & saveMode) != 0; + return (flags & saveMode) != 0; } int FileBrowserComponent::getNumSelectedFiles() const throw() { - if (chosenFiles.size() == 0 && currentFileIsValid()) - return 1; + if (chosenFiles.size() == 0 && currentFileIsValid()) + return 1; - return chosenFiles.size(); + return chosenFiles.size(); } const File FileBrowserComponent::getSelectedFile (int index) const throw() { - if (! filenameBox->isReadOnly()) - return currentRoot.getChildFile (filenameBox->getText()); - else - return chosenFiles[index] != 0 ? *chosenFiles[index] : File::nonexistent; + if (! filenameBox->isReadOnly()) + return currentRoot.getChildFile (filenameBox->getText()); + else + return chosenFiles[index] != 0 ? *chosenFiles[index] : File::nonexistent; } bool FileBrowserComponent::currentFileIsValid() const { - if (isSaveMode()) - return ! getSelectedFile (0).isDirectory(); - else - return getSelectedFile (0).exists(); + if (isSaveMode()) + return ! getSelectedFile (0).isDirectory(); + else + return getSelectedFile (0).exists(); } const File FileBrowserComponent::getHighlightedFile() const throw() { - return fileListComponent->getSelectedFile (0); + return fileListComponent->getSelectedFile (0); } bool FileBrowserComponent::isFileSuitable (const File& file) const { - return (flags & canSelectFiles) != 0 ? (fileFilter == 0 || fileFilter->isFileSuitable (file)) - : false; + return (flags & canSelectFiles) != 0 ? (fileFilter == 0 || fileFilter->isFileSuitable (file)) + : false; } bool FileBrowserComponent::isDirectorySuitable (const File&) const { - return true; + return true; } bool FileBrowserComponent::isFileOrDirSuitable (const File& f) const { - if (f.isDirectory()) - return (flags & canSelectDirectories) != 0 && (fileFilter == 0 || fileFilter->isDirectorySuitable (f)); + if (f.isDirectory()) + return (flags & canSelectDirectories) != 0 && (fileFilter == 0 || fileFilter->isDirectorySuitable (f)); - return (flags & canSelectFiles) != 0 && f.exists() - && (fileFilter == 0 || fileFilter->isFileSuitable (f)); + return (flags & canSelectFiles) != 0 && f.exists() + && (fileFilter == 0 || fileFilter->isFileSuitable (f)); } const File FileBrowserComponent::getRoot() const { - return currentRoot; + return currentRoot; } void FileBrowserComponent::setRoot (const File& newRootDirectory) { - if (currentRoot != newRootDirectory) - { - fileListComponent->scrollToTop(); + if (currentRoot != newRootDirectory) + { + fileListComponent->scrollToTop(); - String path (newRootDirectory.getFullPathName()); + String path (newRootDirectory.getFullPathName()); - if (path.isEmpty()) - path += File::separator; + if (path.isEmpty()) + path += File::separator; - StringArray rootNames, rootPaths; - getRoots (rootNames, rootPaths); + StringArray rootNames, rootPaths; + getRoots (rootNames, rootPaths); - if (! rootPaths.contains (path, true)) - { - bool alreadyListed = false; + if (! rootPaths.contains (path, true)) + { + bool alreadyListed = false; - for (int i = currentPathBox->getNumItems(); --i >= 0;) - { - if (currentPathBox->getItemText (i).equalsIgnoreCase (path)) - { - alreadyListed = true; - break; - } - } + for (int i = currentPathBox->getNumItems(); --i >= 0;) + { + if (currentPathBox->getItemText (i).equalsIgnoreCase (path)) + { + alreadyListed = true; + break; + } + } - if (! alreadyListed) - currentPathBox->addItem (path, currentPathBox->getNumItems() + 2); - } - } + if (! alreadyListed) + currentPathBox->addItem (path, currentPathBox->getNumItems() + 2); + } + } - currentRoot = newRootDirectory; - fileList->setDirectory (currentRoot, true, true); + currentRoot = newRootDirectory; + fileList->setDirectory (currentRoot, true, true); - String currentRootName (currentRoot.getFullPathName()); - if (currentRootName.isEmpty()) - currentRootName += File::separator; + String currentRootName (currentRoot.getFullPathName()); + if (currentRootName.isEmpty()) + currentRootName += File::separator; - currentPathBox->setText (currentRootName, true); + currentPathBox->setText (currentRootName, true); - goUpButton->setEnabled (currentRoot.getParentDirectory().isDirectory() - && currentRoot.getParentDirectory() != currentRoot); + goUpButton->setEnabled (currentRoot.getParentDirectory().isDirectory() + && currentRoot.getParentDirectory() != currentRoot); } void FileBrowserComponent::goUp() { - setRoot (getRoot().getParentDirectory()); + setRoot (getRoot().getParentDirectory()); } void FileBrowserComponent::refresh() { - fileList->refresh(); + fileList->refresh(); } const String FileBrowserComponent::getActionVerb() const { - return isSaveMode() ? TRANS("Save") : TRANS("Open"); + return isSaveMode() ? TRANS("Save") : TRANS("Open"); } FilePreviewComponent* FileBrowserComponent::getPreviewComponent() const throw() { - return previewComp; + return previewComp; } void FileBrowserComponent::resized() { - getLookAndFeel() - .layoutFileBrowserComponent (*this, fileListComponent, - previewComp, currentPathBox, - filenameBox, goUpButton); + getLookAndFeel() + .layoutFileBrowserComponent (*this, fileListComponent, + previewComp, currentPathBox, + filenameBox, goUpButton); } void FileBrowserComponent::sendListenerChangeMessage() { - ComponentDeletionWatcher deletionWatcher (this); + ComponentDeletionWatcher deletionWatcher (this); - if (previewComp != 0) - previewComp->selectedFileChanged (getSelectedFile (0)); + if (previewComp != 0) + previewComp->selectedFileChanged (getSelectedFile (0)); - jassert (! deletionWatcher.hasBeenDeleted()); + jassert (! deletionWatcher.hasBeenDeleted()); - for (int i = listeners.size(); --i >= 0;) - { - ((FileBrowserListener*) listeners.getUnchecked (i))->selectionChanged(); + for (int i = listeners.size(); --i >= 0;) + { + ((FileBrowserListener*) listeners.getUnchecked (i))->selectionChanged(); - if (deletionWatcher.hasBeenDeleted()) - return; + if (deletionWatcher.hasBeenDeleted()) + return; - i = jmin (i, listeners.size() - 1); - } + i = jmin (i, listeners.size() - 1); + } } void FileBrowserComponent::selectionChanged() { - StringArray newFilenames; - bool resetChosenFiles = true; + StringArray newFilenames; + bool resetChosenFiles = true; - for (int i = 0; i < fileListComponent->getNumSelectedFiles(); ++i) - { - const File f (fileListComponent->getSelectedFile (i)); + for (int i = 0; i < fileListComponent->getNumSelectedFiles(); ++i) + { + const File f (fileListComponent->getSelectedFile (i)); - if (isFileOrDirSuitable (f)) - { - if (resetChosenFiles) - { - chosenFiles.clear(); - resetChosenFiles = false; - } + if (isFileOrDirSuitable (f)) + { + if (resetChosenFiles) + { + chosenFiles.clear(); + resetChosenFiles = false; + } - chosenFiles.add (new File (f)); - newFilenames.add (f.getRelativePathFrom (getRoot())); - } - } + chosenFiles.add (new File (f)); + newFilenames.add (f.getRelativePathFrom (getRoot())); + } + } - if (newFilenames.size() > 0) - filenameBox->setText (newFilenames.joinIntoString (T(", ")), false); + if (newFilenames.size() > 0) + filenameBox->setText (newFilenames.joinIntoString (T(", ")), false); - sendListenerChangeMessage(); + sendListenerChangeMessage(); } void FileBrowserComponent::fileClicked (const File& f, const MouseEvent& e) { - ComponentDeletionWatcher deletionWatcher (this); + ComponentDeletionWatcher deletionWatcher (this); - for (int i = listeners.size(); --i >= 0;) - { - ((FileBrowserListener*) listeners.getUnchecked (i))->fileClicked (f, e); + for (int i = listeners.size(); --i >= 0;) + { + ((FileBrowserListener*) listeners.getUnchecked (i))->fileClicked (f, e); - if (deletionWatcher.hasBeenDeleted()) - return; + if (deletionWatcher.hasBeenDeleted()) + return; - i = jmin (i, listeners.size() - 1); - } + i = jmin (i, listeners.size() - 1); + } } void FileBrowserComponent::fileDoubleClicked (const File& f) { - if (f.isDirectory()) - { - setRoot (f); - } - else - { - ComponentDeletionWatcher deletionWatcher (this); + if (f.isDirectory()) + { + setRoot (f); + } + else + { + ComponentDeletionWatcher deletionWatcher (this); - for (int i = listeners.size(); --i >= 0;) - { - ((FileBrowserListener*) listeners.getUnchecked (i))->fileDoubleClicked (f); + for (int i = listeners.size(); --i >= 0;) + { + ((FileBrowserListener*) listeners.getUnchecked (i))->fileDoubleClicked (f); - if (deletionWatcher.hasBeenDeleted()) - return; + if (deletionWatcher.hasBeenDeleted()) + return; - i = jmin (i, listeners.size() - 1); - } - } + i = jmin (i, listeners.size() - 1); + } + } } bool FileBrowserComponent::keyPressed (const KeyPress& key) { #if JUCE_LINUX || JUCE_WINDOWS - if (key.getModifiers().isCommandDown() - && (key.getKeyCode() == 'H' || key.getKeyCode() == 'h')) - { - fileList->setIgnoresHiddenFiles (! fileList->ignoresHiddenFiles()); - fileList->refresh(); - return true; - } + if (key.getModifiers().isCommandDown() + && (key.getKeyCode() == 'H' || key.getKeyCode() == 'h')) + { + fileList->setIgnoresHiddenFiles (! fileList->ignoresHiddenFiles()); + fileList->refresh(); + return true; + } #endif - return false; + return false; } void FileBrowserComponent::textEditorTextChanged (TextEditor&) { - sendListenerChangeMessage(); + sendListenerChangeMessage(); } void FileBrowserComponent::textEditorReturnKeyPressed (TextEditor&) { - if (filenameBox->getText().containsChar (File::separator)) - { - const File f (currentRoot.getChildFile (filenameBox->getText())); + if (filenameBox->getText().containsChar (File::separator)) + { + const File f (currentRoot.getChildFile (filenameBox->getText())); - if (f.isDirectory()) - { - setRoot (f); - chosenFiles.clear(); - filenameBox->setText (String::empty); - } - else - { - setRoot (f.getParentDirectory()); - chosenFiles.clear(); - chosenFiles.add (new File (f)); - filenameBox->setText (f.getFileName()); - } - } - else - { - fileDoubleClicked (getSelectedFile (0)); - } + if (f.isDirectory()) + { + setRoot (f); + chosenFiles.clear(); + filenameBox->setText (String::empty); + } + else + { + setRoot (f.getParentDirectory()); + chosenFiles.clear(); + chosenFiles.add (new File (f)); + filenameBox->setText (f.getFileName()); + } + } + else + { + fileDoubleClicked (getSelectedFile (0)); + } } void FileBrowserComponent::textEditorEscapeKeyPressed (TextEditor&) @@ -57929,128 +57630,128 @@ void FileBrowserComponent::textEditorEscapeKeyPressed (TextEditor&) void FileBrowserComponent::textEditorFocusLost (TextEditor&) { - if (! isSaveMode()) - selectionChanged(); + if (! isSaveMode()) + selectionChanged(); } void FileBrowserComponent::buttonClicked (Button*) { - goUp(); + goUp(); } void FileBrowserComponent::comboBoxChanged (ComboBox*) { - const String newText (currentPathBox->getText().trim().unquoted()); + const String newText (currentPathBox->getText().trim().unquoted()); - if (newText.isNotEmpty()) - { - const int index = currentPathBox->getSelectedId() - 1; + if (newText.isNotEmpty()) + { + const int index = currentPathBox->getSelectedId() - 1; - StringArray rootNames, rootPaths; - getRoots (rootNames, rootPaths); + StringArray rootNames, rootPaths; + getRoots (rootNames, rootPaths); - if (rootPaths [index].isNotEmpty()) - { - setRoot (File (rootPaths [index])); - } - else - { - File f (newText); + if (rootPaths [index].isNotEmpty()) + { + setRoot (File (rootPaths [index])); + } + else + { + File f (newText); - for (;;) - { - if (f.isDirectory()) - { - setRoot (f); - break; - } + for (;;) + { + if (f.isDirectory()) + { + setRoot (f); + break; + } - if (f.getParentDirectory() == f) - break; + if (f.getParentDirectory() == f) + break; - f = f.getParentDirectory(); - } - } - } + f = f.getParentDirectory(); + } + } + } } const BitArray FileBrowserComponent::getRoots (StringArray& rootNames, StringArray& rootPaths) { - BitArray separators; + BitArray separators; #if JUCE_WINDOWS - OwnedArray roots; - File::findFileSystemRoots (roots); - rootPaths.clear(); + OwnedArray roots; + File::findFileSystemRoots (roots); + rootPaths.clear(); - for (int i = 0; i < roots.size(); ++i) - { - const File* const drive = roots.getUnchecked(i); + for (int i = 0; i < roots.size(); ++i) + { + const File* const drive = roots.getUnchecked(i); - String name (drive->getFullPathName()); - rootPaths.add (name); + String name (drive->getFullPathName()); + rootPaths.add (name); - if (drive->isOnHardDisk()) - { - String volume (drive->getVolumeLabel()); + if (drive->isOnHardDisk()) + { + String volume (drive->getVolumeLabel()); - if (volume.isEmpty()) - volume = TRANS("Hard Drive"); + if (volume.isEmpty()) + volume = TRANS("Hard Drive"); - name << " [" << drive->getVolumeLabel() << ']'; - } - else if (drive->isOnCDRomDrive()) - { - name << TRANS(" [CD/DVD drive]"); - } + name << " [" << drive->getVolumeLabel() << ']'; + } + else if (drive->isOnCDRomDrive()) + { + name << TRANS(" [CD/DVD drive]"); + } - rootNames.add (name); - } + rootNames.add (name); + } - separators.setBit (rootPaths.size()); + separators.setBit (rootPaths.size()); - rootPaths.add (File::getSpecialLocation (File::userDocumentsDirectory).getFullPathName()); - rootNames.add ("Documents"); - rootPaths.add (File::getSpecialLocation (File::userDesktopDirectory).getFullPathName()); - rootNames.add ("Desktop"); + rootPaths.add (File::getSpecialLocation (File::userDocumentsDirectory).getFullPathName()); + rootNames.add ("Documents"); + rootPaths.add (File::getSpecialLocation (File::userDesktopDirectory).getFullPathName()); + rootNames.add ("Desktop"); #endif #if JUCE_MAC - rootPaths.add (File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); - rootNames.add ("Home folder"); - rootPaths.add (File::getSpecialLocation (File::userDocumentsDirectory).getFullPathName()); - rootNames.add ("Documents"); - rootPaths.add (File::getSpecialLocation (File::userDesktopDirectory).getFullPathName()); - rootNames.add ("Desktop"); + rootPaths.add (File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); + rootNames.add ("Home folder"); + rootPaths.add (File::getSpecialLocation (File::userDocumentsDirectory).getFullPathName()); + rootNames.add ("Documents"); + rootPaths.add (File::getSpecialLocation (File::userDesktopDirectory).getFullPathName()); + rootNames.add ("Desktop"); - separators.setBit (rootPaths.size()); + separators.setBit (rootPaths.size()); - OwnedArray volumes; - File vol ("/Volumes"); - vol.findChildFiles (volumes, File::findDirectories, false); + OwnedArray volumes; + File vol ("/Volumes"); + vol.findChildFiles (volumes, File::findDirectories, false); - for (int i = 0; i < volumes.size(); ++i) - { - const File* const volume = volumes.getUnchecked(i); + for (int i = 0; i < volumes.size(); ++i) + { + const File* const volume = volumes.getUnchecked(i); - if (volume->isDirectory() && ! volume->getFileName().startsWithChar (T('.'))) - { - rootPaths.add (volume->getFullPathName()); - rootNames.add (volume->getFileName()); - } - } + if (volume->isDirectory() && ! volume->getFileName().startsWithChar (T('.'))) + { + rootPaths.add (volume->getFullPathName()); + rootNames.add (volume->getFileName()); + } + } #endif #if JUCE_LINUX - rootPaths.add ("/"); - rootNames.add ("/"); - rootPaths.add (File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); - rootNames.add ("Home folder"); - rootPaths.add (File::getSpecialLocation (File::userDesktopDirectory).getFullPathName()); - rootNames.add ("Desktop"); + rootPaths.add ("/"); + rootNames.add ("/"); + rootPaths.add (File::getSpecialLocation (File::userHomeDirectory).getFullPathName()); + rootNames.add ("Home folder"); + rootPaths.add (File::getSpecialLocation (File::userDesktopDirectory).getFullPathName()); + rootNames.add ("Desktop"); #endif - return separators; + return separators; } END_JUCE_NAMESPACE @@ -58061,20 +57762,20 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE FileChooser::FileChooser (const String& chooserBoxTitle, - const File& currentFileOrDirectory, - const String& fileFilters, - const bool useNativeDialogBox_) - : title (chooserBoxTitle), - filters (fileFilters), - startingFile (currentFileOrDirectory), - useNativeDialogBox (useNativeDialogBox_) + const File& currentFileOrDirectory, + const String& fileFilters, + const bool useNativeDialogBox_) + : title (chooserBoxTitle), + filters (fileFilters), + startingFile (currentFileOrDirectory), + useNativeDialogBox (useNativeDialogBox_) { #if JUCE_LINUX - useNativeDialogBox = false; + useNativeDialogBox = false; #endif - if (! fileFilters.containsNonWhitespaceChars()) - filters = T("*"); + if (! fileFilters.containsNonWhitespaceChars()) + filters = T("*"); } FileChooser::~FileChooser() @@ -58083,117 +57784,117 @@ FileChooser::~FileChooser() bool FileChooser::browseForFileToOpen (FilePreviewComponent* previewComponent) { - return showDialog (false, true, false, false, false, previewComponent); + return showDialog (false, true, false, false, false, previewComponent); } bool FileChooser::browseForMultipleFilesToOpen (FilePreviewComponent* previewComponent) { - return showDialog (false, true, false, false, true, previewComponent); + return showDialog (false, true, false, false, true, previewComponent); } bool FileChooser::browseForMultipleFilesOrDirectories (FilePreviewComponent* previewComponent) { - return showDialog (true, true, false, false, true, previewComponent); + return showDialog (true, true, false, false, true, previewComponent); } bool FileChooser::browseForFileToSave (const bool warnAboutOverwritingExistingFiles) { - return showDialog (false, true, true, warnAboutOverwritingExistingFiles, false, 0); + return showDialog (false, true, true, warnAboutOverwritingExistingFiles, false, 0); } bool FileChooser::browseForDirectory() { - return showDialog (true, false, false, false, false, 0); + return showDialog (true, false, false, false, false, 0); } const File FileChooser::getResult() const { - // if you've used a multiple-file select, you should use the getResults() method - // to retrieve all the files that were chosen. - jassert (results.size() <= 1); + // if you've used a multiple-file select, you should use the getResults() method + // to retrieve all the files that were chosen. + jassert (results.size() <= 1); - const File* const f = results.getFirst(); + const File* const f = results.getFirst(); - if (f != 0) - return *f; + if (f != 0) + return *f; - return File::nonexistent; + return File::nonexistent; } const OwnedArray & FileChooser::getResults() const { - return results; + return results; } bool FileChooser::showDialog (const bool selectsDirectories, - const bool selectsFiles, - const bool isSave, - const bool warnAboutOverwritingExistingFiles, - const bool selectMultipleFiles, - FilePreviewComponent* const previewComponent) + const bool selectsFiles, + const bool isSave, + const bool warnAboutOverwritingExistingFiles, + const bool selectMultipleFiles, + FilePreviewComponent* const previewComponent) { - ScopedPointer currentlyFocusedChecker; - Component* const currentlyFocused = Component::getCurrentlyFocusedComponent(); + ScopedPointer currentlyFocusedChecker; + Component* const currentlyFocused = Component::getCurrentlyFocusedComponent(); - if (currentlyFocused != 0) - currentlyFocusedChecker = new ComponentDeletionWatcher (currentlyFocused); + if (currentlyFocused != 0) + currentlyFocusedChecker = new ComponentDeletionWatcher (currentlyFocused); - results.clear(); + results.clear(); - // the preview component needs to be the right size before you pass it in here.. - jassert (previewComponent == 0 || (previewComponent->getWidth() > 10 - && previewComponent->getHeight() > 10)); + // the preview component needs to be the right size before you pass it in here.. + jassert (previewComponent == 0 || (previewComponent->getWidth() > 10 + && previewComponent->getHeight() > 10)); #if JUCE_WINDOWS - if (useNativeDialogBox && ! (selectsFiles && selectsDirectories)) + if (useNativeDialogBox && ! (selectsFiles && selectsDirectories)) #elif JUCE_MAC - if (useNativeDialogBox && (previewComponent == 0)) + if (useNativeDialogBox && (previewComponent == 0)) #else - if (false) + if (false) #endif - { - showPlatformDialog (results, title, startingFile, filters, - selectsDirectories, selectsFiles, isSave, - warnAboutOverwritingExistingFiles, - selectMultipleFiles, - previewComponent); - } - else - { - WildcardFileFilter wildcard (selectsFiles ? filters : String::empty, - selectsDirectories ? "*" : String::empty, - String::empty); + { + showPlatformDialog (results, title, startingFile, filters, + selectsDirectories, selectsFiles, isSave, + warnAboutOverwritingExistingFiles, + selectMultipleFiles, + previewComponent); + } + else + { + WildcardFileFilter wildcard (selectsFiles ? filters : String::empty, + selectsDirectories ? "*" : String::empty, + String::empty); - int flags = isSave ? FileBrowserComponent::saveMode - : FileBrowserComponent::openMode; + int flags = isSave ? FileBrowserComponent::saveMode + : FileBrowserComponent::openMode; - if (selectsFiles) - flags |= FileBrowserComponent::canSelectFiles; + if (selectsFiles) + flags |= FileBrowserComponent::canSelectFiles; - if (selectsDirectories) - flags |= FileBrowserComponent::canSelectDirectories; + if (selectsDirectories) + flags |= FileBrowserComponent::canSelectDirectories; - if (selectMultipleFiles) - flags |= FileBrowserComponent::canSelectMultipleItems; + if (selectMultipleFiles) + flags |= FileBrowserComponent::canSelectMultipleItems; - FileBrowserComponent browserComponent (flags, startingFile, &wildcard, previewComponent); + FileBrowserComponent browserComponent (flags, startingFile, &wildcard, previewComponent); - FileChooserDialogBox box (title, String::empty, - browserComponent, - warnAboutOverwritingExistingFiles, - browserComponent.findColour (AlertWindow::backgroundColourId)); + FileChooserDialogBox box (title, String::empty, + browserComponent, + warnAboutOverwritingExistingFiles, + browserComponent.findColour (AlertWindow::backgroundColourId)); - if (box.show()) - { - for (int i = 0; i < browserComponent.getNumSelectedFiles(); ++i) - results.add (new File (browserComponent.getSelectedFile (i))); - } - } + if (box.show()) + { + for (int i = 0; i < browserComponent.getNumSelectedFiles(); ++i) + results.add (new File (browserComponent.getSelectedFile (i))); + } + } - if (currentlyFocused != 0 && ! currentlyFocusedChecker->hasBeenDeleted()) - currentlyFocused->grabKeyboardFocus(); + if (currentlyFocused != 0 && ! currentlyFocusedChecker->hasBeenDeleted()) + currentlyFocused->grabKeyboardFocus(); - return results.size() > 0; + return results.size() > 0; } FilePreviewComponent::FilePreviewComponent() @@ -58212,99 +57913,99 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE FileChooserDialogBox::FileChooserDialogBox (const String& name, - const String& instructions, - FileBrowserComponent& chooserComponent, - const bool warnAboutOverwritingExistingFiles_, - const Colour& backgroundColour) - : ResizableWindow (name, backgroundColour, true), - warnAboutOverwritingExistingFiles (warnAboutOverwritingExistingFiles_) + const String& instructions, + FileBrowserComponent& chooserComponent, + const bool warnAboutOverwritingExistingFiles_, + const Colour& backgroundColour) + : ResizableWindow (name, backgroundColour, true), + warnAboutOverwritingExistingFiles (warnAboutOverwritingExistingFiles_) { - content = new ContentComponent(); - content->setName (name); - content->instructions = instructions; - content->chooserComponent = &chooserComponent; + content = new ContentComponent(); + content->setName (name); + content->instructions = instructions; + content->chooserComponent = &chooserComponent; - content->addAndMakeVisible (&chooserComponent); + content->addAndMakeVisible (&chooserComponent); - content->okButton = new TextButton (chooserComponent.getActionVerb()); - content->addAndMakeVisible (content->okButton); - content->okButton->addButtonListener (this); - content->okButton->setEnabled (chooserComponent.currentFileIsValid()); - content->okButton->addShortcut (KeyPress (KeyPress::returnKey, 0, 0)); + content->okButton = new TextButton (chooserComponent.getActionVerb()); + content->addAndMakeVisible (content->okButton); + content->okButton->addButtonListener (this); + content->okButton->setEnabled (chooserComponent.currentFileIsValid()); + content->okButton->addShortcut (KeyPress (KeyPress::returnKey, 0, 0)); - content->cancelButton = new TextButton (TRANS("Cancel")); - content->addAndMakeVisible (content->cancelButton); - content->cancelButton->addButtonListener (this); - content->cancelButton->addShortcut (KeyPress (KeyPress::escapeKey, 0, 0)); + content->cancelButton = new TextButton (TRANS("Cancel")); + content->addAndMakeVisible (content->cancelButton); + content->cancelButton->addButtonListener (this); + content->cancelButton->addShortcut (KeyPress (KeyPress::escapeKey, 0, 0)); - setContentComponent (content); + setContentComponent (content); - setResizable (true, true); - setResizeLimits (300, 300, 1200, 1000); + setResizable (true, true); + setResizeLimits (300, 300, 1200, 1000); - content->chooserComponent->addListener (this); + content->chooserComponent->addListener (this); } FileChooserDialogBox::~FileChooserDialogBox() { - content->chooserComponent->removeListener (this); + content->chooserComponent->removeListener (this); } bool FileChooserDialogBox::show (int w, int h) { - if (w <= 0) - { - Component* const previewComp = content->chooserComponent->getPreviewComponent(); - if (previewComp != 0) - w = 400 + previewComp->getWidth(); - else - w = 600; - } + if (w <= 0) + { + Component* const previewComp = content->chooserComponent->getPreviewComponent(); + if (previewComp != 0) + w = 400 + previewComp->getWidth(); + else + w = 600; + } - if (h <= 0) - h = 500; + if (h <= 0) + h = 500; - centreWithSize (w, h); + centreWithSize (w, h); - const bool ok = (runModalLoop() != 0); - setVisible (false); - return ok; + const bool ok = (runModalLoop() != 0); + setVisible (false); + return ok; } void FileChooserDialogBox::buttonClicked (Button* button) { - if (button == content->okButton) - { - if (warnAboutOverwritingExistingFiles - && content->chooserComponent->isSaveMode() - && content->chooserComponent->getSelectedFile(0).exists()) - { - if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, - TRANS("File already exists"), - TRANS("There's already a file called:\n\n") - + content->chooserComponent->getSelectedFile(0).getFullPathName() - + T("\n\nAre you sure you want to overwrite it?"), - TRANS("overwrite"), - TRANS("cancel"))) - { - return; - } - } + if (button == content->okButton) + { + if (warnAboutOverwritingExistingFiles + && content->chooserComponent->isSaveMode() + && content->chooserComponent->getSelectedFile(0).exists()) + { + if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, + TRANS("File already exists"), + TRANS("There's already a file called:\n\n") + + content->chooserComponent->getSelectedFile(0).getFullPathName() + + T("\n\nAre you sure you want to overwrite it?"), + TRANS("overwrite"), + TRANS("cancel"))) + { + return; + } + } - exitModalState (1); - } - else if (button == content->cancelButton) - closeButtonPressed(); + exitModalState (1); + } + else if (button == content->cancelButton) + closeButtonPressed(); } void FileChooserDialogBox::closeButtonPressed() { - setVisible (false); + setVisible (false); } void FileChooserDialogBox::selectionChanged() { - content->okButton->setEnabled (content->chooserComponent->currentFileIsValid()); + content->okButton->setEnabled (content->chooserComponent->currentFileIsValid()); } void FileChooserDialogBox::fileClicked (const File&, const MouseEvent&) @@ -58313,45 +58014,45 @@ void FileChooserDialogBox::fileClicked (const File&, const MouseEvent&) void FileChooserDialogBox::fileDoubleClicked (const File&) { - selectionChanged(); - content->okButton->triggerClick(); + selectionChanged(); + content->okButton->triggerClick(); } FileChooserDialogBox::ContentComponent::ContentComponent() { - setInterceptsMouseClicks (false, true); + setInterceptsMouseClicks (false, true); } FileChooserDialogBox::ContentComponent::~ContentComponent() { - delete okButton; - delete cancelButton; + delete okButton; + delete cancelButton; } void FileChooserDialogBox::ContentComponent::paint (Graphics& g) { - g.setColour (Colours::black); - text.draw (g); + g.setColour (Colours::black); + text.draw (g); } void FileChooserDialogBox::ContentComponent::resized() { - getLookAndFeel().createFileChooserHeaderText (getName(), instructions, text, getWidth()); + getLookAndFeel().createFileChooserHeaderText (getName(), instructions, text, getWidth()); - float left, top, right, bottom; - text.getBoundingBox (0, text.getNumGlyphs(), left, top, right, bottom, false); + float left, top, right, bottom; + text.getBoundingBox (0, text.getNumGlyphs(), left, top, right, bottom, false); - const int y = roundFloatToInt (bottom) + 10; - const int buttonHeight = 26; - const int buttonY = getHeight() - buttonHeight - 8; + const int y = roundToInt (bottom) + 10; + const int buttonHeight = 26; + const int buttonY = getHeight() - buttonHeight - 8; - chooserComponent->setBounds (0, y, getWidth(), buttonY - y - 20); + chooserComponent->setBounds (0, y, getWidth(), buttonY - y - 20); - okButton->setBounds (proportionOfWidth (0.25f), buttonY, - proportionOfWidth (0.2f), buttonHeight); + okButton->setBounds (proportionOfWidth (0.25f), buttonY, + proportionOfWidth (0.2f), buttonHeight); - cancelButton->setBounds (proportionOfWidth (0.55f), buttonY, - proportionOfWidth (0.2f), buttonHeight); + cancelButton->setBounds (proportionOfWidth (0.55f), buttonY, + proportionOfWidth (0.2f), buttonHeight); } END_JUCE_NAMESPACE @@ -58362,7 +58063,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE FileFilter::FileFilter (const String& filterDescription) - : description (filterDescription) + : description (filterDescription) { } @@ -58372,7 +58073,7 @@ FileFilter::~FileFilter() const String& FileFilter::getDescription() const throw() { - return description; + return description; } END_JUCE_NAMESPACE @@ -58385,194 +58086,194 @@ BEGIN_JUCE_NAMESPACE Image* juce_createIconForFile (const File& file); FileListComponent::FileListComponent (DirectoryContentsList& listToShow) - : ListBox (String::empty, 0), - DirectoryContentsDisplayComponent (listToShow) + : ListBox (String::empty, 0), + DirectoryContentsDisplayComponent (listToShow) { - setModel (this); - fileList.addChangeListener (this); + setModel (this); + fileList.addChangeListener (this); } FileListComponent::~FileListComponent() { - fileList.removeChangeListener (this); - deleteAllChildren(); + fileList.removeChangeListener (this); + deleteAllChildren(); } int FileListComponent::getNumSelectedFiles() const { - return getNumSelectedRows(); + return getNumSelectedRows(); } const File FileListComponent::getSelectedFile (int index) const { - return fileList.getFile (getSelectedRow (index)); + return fileList.getFile (getSelectedRow (index)); } void FileListComponent::scrollToTop() { - getVerticalScrollBar()->setCurrentRangeStart (0); + getVerticalScrollBar()->setCurrentRangeStart (0); } void FileListComponent::changeListenerCallback (void*) { - updateContent(); + updateContent(); - if (lastDirectory != fileList.getDirectory()) - { - lastDirectory = fileList.getDirectory(); - deselectAllRows(); - } + if (lastDirectory != fileList.getDirectory()) + { + lastDirectory = fileList.getDirectory(); + deselectAllRows(); + } } class FileListItemComponent : public Component, - public TimeSliceClient, - public AsyncUpdater + public TimeSliceClient, + public AsyncUpdater { public: - FileListItemComponent (FileListComponent& owner_, - TimeSliceThread& thread_) throw() - : owner (owner_), - thread (thread_), - icon (0) - { - } + FileListItemComponent (FileListComponent& owner_, + TimeSliceThread& thread_) throw() + : owner (owner_), + thread (thread_), + icon (0) + { + } - ~FileListItemComponent() throw() - { - thread.removeTimeSliceClient (this); + ~FileListItemComponent() throw() + { + thread.removeTimeSliceClient (this); - clearIcon(); - } + clearIcon(); + } - void paint (Graphics& g) - { - getLookAndFeel().drawFileBrowserRow (g, getWidth(), getHeight(), - file.getFileName(), - icon, - fileSize, modTime, - isDirectory, highlighted, - index); - } + void paint (Graphics& g) + { + getLookAndFeel().drawFileBrowserRow (g, getWidth(), getHeight(), + file.getFileName(), + icon, + fileSize, modTime, + isDirectory, highlighted, + index); + } - void mouseDown (const MouseEvent& e) - { - owner.selectRowsBasedOnModifierKeys (index, e.mods); - owner.sendMouseClickMessage (file, e); - } + void mouseDown (const MouseEvent& e) + { + owner.selectRowsBasedOnModifierKeys (index, e.mods); + owner.sendMouseClickMessage (file, e); + } - void mouseDoubleClick (const MouseEvent&) - { - owner.sendDoubleClickMessage (file); - } + void mouseDoubleClick (const MouseEvent&) + { + owner.sendDoubleClickMessage (file); + } - void update (const File& root, - const DirectoryContentsList::FileInfo* const fileInfo, - const int index_, - const bool highlighted_) throw() - { - thread.removeTimeSliceClient (this); + void update (const File& root, + const DirectoryContentsList::FileInfo* const fileInfo, + const int index_, + const bool highlighted_) throw() + { + thread.removeTimeSliceClient (this); - if (highlighted_ != highlighted - || index_ != index) - { - index = index_; - highlighted = highlighted_; - repaint(); - } + if (highlighted_ != highlighted + || index_ != index) + { + index = index_; + highlighted = highlighted_; + repaint(); + } - File newFile; - String newFileSize; - String newModTime; + File newFile; + String newFileSize; + String newModTime; - if (fileInfo != 0) - { - newFile = root.getChildFile (fileInfo->filename); - newFileSize = File::descriptionOfSizeInBytes (fileInfo->fileSize); - newModTime = fileInfo->modificationTime.formatted (T("%d %b '%y %H:%M")); - } + if (fileInfo != 0) + { + newFile = root.getChildFile (fileInfo->filename); + newFileSize = File::descriptionOfSizeInBytes (fileInfo->fileSize); + newModTime = fileInfo->modificationTime.formatted (T("%d %b '%y %H:%M")); + } - if (newFile != file - || fileSize != newFileSize - || modTime != newModTime) - { - file = newFile; - fileSize = newFileSize; - modTime = newModTime; + if (newFile != file + || fileSize != newFileSize + || modTime != newModTime) + { + file = newFile; + fileSize = newFileSize; + modTime = newModTime; - isDirectory = fileInfo != 0 && fileInfo->isDirectory; - repaint(); + isDirectory = fileInfo != 0 && fileInfo->isDirectory; + repaint(); - clearIcon(); - } + clearIcon(); + } - if (file != File::nonexistent - && icon == 0 && ! isDirectory) - { - updateIcon (true); + if (file != File::nonexistent + && icon == 0 && ! isDirectory) + { + updateIcon (true); - if (icon == 0) - thread.addTimeSliceClient (this); - } - } + if (icon == 0) + thread.addTimeSliceClient (this); + } + } - bool useTimeSlice() - { - updateIcon (false); - return false; - } + bool useTimeSlice() + { + updateIcon (false); + return false; + } - void handleAsyncUpdate() - { - repaint(); - } + void handleAsyncUpdate() + { + repaint(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - FileListComponent& owner; - TimeSliceThread& thread; - bool highlighted; - int index; - File file; - String fileSize; - String modTime; - Image* icon; - bool isDirectory; + FileListComponent& owner; + TimeSliceThread& thread; + bool highlighted; + int index; + File file; + String fileSize; + String modTime; + Image* icon; + bool isDirectory; - void clearIcon() throw() - { - ImageCache::release (icon); - icon = 0; - } + void clearIcon() throw() + { + ImageCache::release (icon); + icon = 0; + } - void updateIcon (const bool onlyUpdateIfCached) throw() - { - if (icon == 0) - { - const int hashCode = (file.getFullPathName() + T("_iconCacheSalt")).hashCode(); - Image* im = ImageCache::getFromHashCode (hashCode); + void updateIcon (const bool onlyUpdateIfCached) throw() + { + if (icon == 0) + { + const int hashCode = (file.getFullPathName() + T("_iconCacheSalt")).hashCode(); + Image* im = ImageCache::getFromHashCode (hashCode); - if (im == 0 && ! onlyUpdateIfCached) - { - im = juce_createIconForFile (file); + if (im == 0 && ! onlyUpdateIfCached) + { + im = juce_createIconForFile (file); - if (im != 0) - ImageCache::addImageToCache (im, hashCode); - } + if (im != 0) + ImageCache::addImageToCache (im, hashCode); + } - if (im != 0) - { - icon = im; - triggerAsyncUpdate(); - } - } - } + if (im != 0) + { + icon = im; + triggerAsyncUpdate(); + } + } + } }; int FileListComponent::getNumRows() { - return fileList.getNumFiles(); + return fileList.getNumFiles(); } void FileListComponent::paintListBoxItem (int, Graphics&, int, int, bool) @@ -58581,27 +58282,27 @@ void FileListComponent::paintListBoxItem (int, Graphics&, int, int, bool) Component* FileListComponent::refreshComponentForRow (int row, bool isSelected, Component* existingComponentToUpdate) { - FileListItemComponent* comp = dynamic_cast (existingComponentToUpdate); + FileListItemComponent* comp = dynamic_cast (existingComponentToUpdate); - if (comp == 0) - { - delete existingComponentToUpdate; - comp = new FileListItemComponent (*this, fileList.getTimeSliceThread()); - } + if (comp == 0) + { + delete existingComponentToUpdate; + comp = new FileListItemComponent (*this, fileList.getTimeSliceThread()); + } - DirectoryContentsList::FileInfo fileInfo; + DirectoryContentsList::FileInfo fileInfo; - if (fileList.getFileInfo (row, fileInfo)) - comp->update (fileList.getDirectory(), &fileInfo, row, isSelected); - else - comp->update (fileList.getDirectory(), 0, row, isSelected); + if (fileList.getFileInfo (row, fileInfo)) + comp->update (fileList.getDirectory(), &fileInfo, row, isSelected); + else + comp->update (fileList.getDirectory(), 0, row, isSelected); - return comp; + return comp; } void FileListComponent::selectedRowsChanged (int /*lastRowSelected*/) { - sendSelectionChangeMessage(); + sendSelectionChangeMessage(); } void FileListComponent::deleteKeyPressed (int /*currentSelectedRow*/) @@ -58610,7 +58311,7 @@ void FileListComponent::deleteKeyPressed (int /*currentSelectedRow*/) void FileListComponent::returnKeyPressed (int currentSelectedRow) { - sendDoubleClickMessage (fileList.getFile (currentSelectedRow)); + sendDoubleClickMessage (fileList.getFile (currentSelectedRow)); } END_JUCE_NAMESPACE @@ -58621,225 +58322,225 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE FilenameComponent::FilenameComponent (const String& name, - const File& currentFile, - const bool canEditFilename, - const bool isDirectory, - const bool isForSaving, - const String& fileBrowserWildcard, - const String& enforcedSuffix_, - const String& textWhenNothingSelected) - : Component (name), - maxRecentFiles (30), - isDir (isDirectory), - isSaving (isForSaving), - isFileDragOver (false), - wildcard (fileBrowserWildcard), - enforcedSuffix (enforcedSuffix_) + const File& currentFile, + const bool canEditFilename, + const bool isDirectory, + const bool isForSaving, + const String& fileBrowserWildcard, + const String& enforcedSuffix_, + const String& textWhenNothingSelected) + : Component (name), + maxRecentFiles (30), + isDir (isDirectory), + isSaving (isForSaving), + isFileDragOver (false), + wildcard (fileBrowserWildcard), + enforcedSuffix (enforcedSuffix_) { - addAndMakeVisible (filenameBox = new ComboBox (T("fn"))); - filenameBox->setEditableText (canEditFilename); - filenameBox->addListener (this); - filenameBox->setTextWhenNothingSelected (textWhenNothingSelected); - filenameBox->setTextWhenNoChoicesAvailable (TRANS("(no recently seleced files)")); + addAndMakeVisible (filenameBox = new ComboBox (T("fn"))); + filenameBox->setEditableText (canEditFilename); + filenameBox->addListener (this); + filenameBox->setTextWhenNothingSelected (textWhenNothingSelected); + filenameBox->setTextWhenNoChoicesAvailable (TRANS("(no recently seleced files)")); - browseButton = 0; - setBrowseButtonText (T("...")); + browseButton = 0; + setBrowseButtonText (T("...")); - setCurrentFile (currentFile, true); + setCurrentFile (currentFile, true); } FilenameComponent::~FilenameComponent() { - deleteAllChildren(); + deleteAllChildren(); } void FilenameComponent::paintOverChildren (Graphics& g) { - if (isFileDragOver) - { - g.setColour (Colours::red.withAlpha (0.2f)); - g.drawRect (0, 0, getWidth(), getHeight(), 3); - } + if (isFileDragOver) + { + g.setColour (Colours::red.withAlpha (0.2f)); + g.drawRect (0, 0, getWidth(), getHeight(), 3); + } } void FilenameComponent::resized() { - getLookAndFeel().layoutFilenameComponent (*this, filenameBox, browseButton); + getLookAndFeel().layoutFilenameComponent (*this, filenameBox, browseButton); } void FilenameComponent::setBrowseButtonText (const String& newBrowseButtonText) { - browseButtonText = newBrowseButtonText; - lookAndFeelChanged(); + browseButtonText = newBrowseButtonText; + lookAndFeelChanged(); } void FilenameComponent::lookAndFeelChanged() { - deleteAndZero (browseButton); + deleteAndZero (browseButton); - addAndMakeVisible (browseButton = getLookAndFeel().createFilenameComponentBrowseButton (browseButtonText)); - browseButton->setConnectedEdges (Button::ConnectedOnLeft); - resized(); + addAndMakeVisible (browseButton = getLookAndFeel().createFilenameComponentBrowseButton (browseButtonText)); + browseButton->setConnectedEdges (Button::ConnectedOnLeft); + resized(); - browseButton->addButtonListener (this); + browseButton->addButtonListener (this); } void FilenameComponent::setTooltip (const String& newTooltip) { - SettableTooltipClient::setTooltip (newTooltip); - filenameBox->setTooltip (newTooltip); + SettableTooltipClient::setTooltip (newTooltip); + filenameBox->setTooltip (newTooltip); } void FilenameComponent::setDefaultBrowseTarget (const File& newDefaultDirectory) throw() { - defaultBrowseFile = newDefaultDirectory; + defaultBrowseFile = newDefaultDirectory; } void FilenameComponent::buttonClicked (Button*) { - FileChooser fc (TRANS("Choose a new file"), - getCurrentFile() == File::nonexistent ? defaultBrowseFile - : getCurrentFile(), - wildcard); + FileChooser fc (TRANS("Choose a new file"), + getCurrentFile() == File::nonexistent ? defaultBrowseFile + : getCurrentFile(), + wildcard); - if (isDir ? fc.browseForDirectory() - : (isSaving ? fc.browseForFileToSave (false) - : fc.browseForFileToOpen())) - { - setCurrentFile (fc.getResult(), true); - } + if (isDir ? fc.browseForDirectory() + : (isSaving ? fc.browseForFileToSave (false) + : fc.browseForFileToOpen())) + { + setCurrentFile (fc.getResult(), true); + } } void FilenameComponent::comboBoxChanged (ComboBox*) { - setCurrentFile (getCurrentFile(), true); + setCurrentFile (getCurrentFile(), true); } bool FilenameComponent::isInterestedInFileDrag (const StringArray&) { - return true; + return true; } void FilenameComponent::filesDropped (const StringArray& filenames, int, int) { - isFileDragOver = false; - repaint(); + isFileDragOver = false; + repaint(); - const File f (filenames[0]); + const File f (filenames[0]); - if (f.exists() && (f.isDirectory() == isDir)) - setCurrentFile (f, true); + if (f.exists() && (f.isDirectory() == isDir)) + setCurrentFile (f, true); } void FilenameComponent::fileDragEnter (const StringArray&, int, int) { - isFileDragOver = true; - repaint(); + isFileDragOver = true; + repaint(); } void FilenameComponent::fileDragExit (const StringArray&) { - isFileDragOver = false; - repaint(); + isFileDragOver = false; + repaint(); } const File FilenameComponent::getCurrentFile() const { - File f (filenameBox->getText()); + File f (filenameBox->getText()); - if (enforcedSuffix.isNotEmpty()) - f = f.withFileExtension (enforcedSuffix); + if (enforcedSuffix.isNotEmpty()) + f = f.withFileExtension (enforcedSuffix); - return f; + return f; } void FilenameComponent::setCurrentFile (File newFile, - const bool addToRecentlyUsedList, - const bool sendChangeNotification) + const bool addToRecentlyUsedList, + const bool sendChangeNotification) { - if (enforcedSuffix.isNotEmpty()) - newFile = newFile.withFileExtension (enforcedSuffix); + if (enforcedSuffix.isNotEmpty()) + newFile = newFile.withFileExtension (enforcedSuffix); - if (newFile.getFullPathName() != lastFilename) - { - lastFilename = newFile.getFullPathName(); + if (newFile.getFullPathName() != lastFilename) + { + lastFilename = newFile.getFullPathName(); - if (addToRecentlyUsedList) - addRecentlyUsedFile (newFile); + if (addToRecentlyUsedList) + addRecentlyUsedFile (newFile); - filenameBox->setText (lastFilename, true); + filenameBox->setText (lastFilename, true); - if (sendChangeNotification) - triggerAsyncUpdate(); - } + if (sendChangeNotification) + triggerAsyncUpdate(); + } } void FilenameComponent::setFilenameIsEditable (const bool shouldBeEditable) { - filenameBox->setEditableText (shouldBeEditable); + filenameBox->setEditableText (shouldBeEditable); } const StringArray FilenameComponent::getRecentlyUsedFilenames() const { - StringArray names; + StringArray names; - for (int i = 0; i < filenameBox->getNumItems(); ++i) - names.add (filenameBox->getItemText (i)); + for (int i = 0; i < filenameBox->getNumItems(); ++i) + names.add (filenameBox->getItemText (i)); - return names; + return names; } void FilenameComponent::setRecentlyUsedFilenames (const StringArray& filenames) { - if (filenames != getRecentlyUsedFilenames()) - { - filenameBox->clear(); + if (filenames != getRecentlyUsedFilenames()) + { + filenameBox->clear(); - for (int i = 0; i < jmin (filenames.size(), maxRecentFiles); ++i) - filenameBox->addItem (filenames[i], i + 1); - } + for (int i = 0; i < jmin (filenames.size(), maxRecentFiles); ++i) + filenameBox->addItem (filenames[i], i + 1); + } } void FilenameComponent::setMaxNumberOfRecentFiles (const int newMaximum) { - maxRecentFiles = jmax (1, newMaximum); + maxRecentFiles = jmax (1, newMaximum); - setRecentlyUsedFilenames (getRecentlyUsedFilenames()); + setRecentlyUsedFilenames (getRecentlyUsedFilenames()); } void FilenameComponent::addRecentlyUsedFile (const File& file) { - StringArray files (getRecentlyUsedFilenames()); + StringArray files (getRecentlyUsedFilenames()); - if (file.getFullPathName().isNotEmpty()) - { - files.removeString (file.getFullPathName(), true); - files.insert (0, file.getFullPathName()); + if (file.getFullPathName().isNotEmpty()) + { + files.removeString (file.getFullPathName(), true); + files.insert (0, file.getFullPathName()); - setRecentlyUsedFilenames (files); - } + setRecentlyUsedFilenames (files); + } } void FilenameComponent::addListener (FilenameComponentListener* const listener) throw() { - jassert (listener != 0); + jassert (listener != 0); - if (listener != 0) - listeners.add (listener); + if (listener != 0) + listeners.add (listener); } void FilenameComponent::removeListener (FilenameComponentListener* const listener) throw() { - listeners.removeValue (listener); + listeners.removeValue (listener); } void FilenameComponent::handleAsyncUpdate() { - for (int i = listeners.size(); --i >= 0;) - { - ((FilenameComponentListener*) listeners.getUnchecked (i))->filenameComponentChanged (this); - i = jmin (i, listeners.size()); - } + for (int i = listeners.size(); --i >= 0;) + { + ((FilenameComponentListener*) listeners.getUnchecked (i))->filenameComponentChanged (this); + i = jmin (i, listeners.size()); + } } END_JUCE_NAMESPACE @@ -58851,232 +58552,232 @@ BEGIN_JUCE_NAMESPACE FileSearchPathListComponent::FileSearchPathListComponent() { - addAndMakeVisible (listBox = new ListBox (String::empty, this)); - listBox->setColour (ListBox::backgroundColourId, Colours::black.withAlpha (0.02f)); - listBox->setColour (ListBox::outlineColourId, Colours::black.withAlpha (0.1f)); - listBox->setOutlineThickness (1); + addAndMakeVisible (listBox = new ListBox (String::empty, this)); + listBox->setColour (ListBox::backgroundColourId, Colours::black.withAlpha (0.02f)); + listBox->setColour (ListBox::outlineColourId, Colours::black.withAlpha (0.1f)); + listBox->setOutlineThickness (1); - addAndMakeVisible (addButton = new TextButton ("+")); - addButton->addButtonListener (this); - addButton->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop); + addAndMakeVisible (addButton = new TextButton ("+")); + addButton->addButtonListener (this); + addButton->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop); - addAndMakeVisible (removeButton = new TextButton ("-")); - removeButton->addButtonListener (this); - removeButton->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop); + addAndMakeVisible (removeButton = new TextButton ("-")); + removeButton->addButtonListener (this); + removeButton->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnRight | Button::ConnectedOnBottom | Button::ConnectedOnTop); - addAndMakeVisible (changeButton = new TextButton (TRANS("change..."))); - changeButton->addButtonListener (this); + addAndMakeVisible (changeButton = new TextButton (TRANS("change..."))); + changeButton->addButtonListener (this); - addAndMakeVisible (upButton = new DrawableButton (String::empty, DrawableButton::ImageOnButtonBackground)); - upButton->addButtonListener (this); + addAndMakeVisible (upButton = new DrawableButton (String::empty, DrawableButton::ImageOnButtonBackground)); + upButton->addButtonListener (this); - { - Path arrowPath; - arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0f, 40.0f, 100.0f, 50.0f); - DrawablePath arrowImage; - arrowImage.setFill (Colours::black.withAlpha (0.4f)); - arrowImage.setPath (arrowPath); + { + Path arrowPath; + arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0f, 40.0f, 100.0f, 50.0f); + DrawablePath arrowImage; + arrowImage.setFill (Colours::black.withAlpha (0.4f)); + arrowImage.setPath (arrowPath); - ((DrawableButton*) upButton)->setImages (&arrowImage); - } + ((DrawableButton*) upButton)->setImages (&arrowImage); + } - addAndMakeVisible (downButton = new DrawableButton (String::empty, DrawableButton::ImageOnButtonBackground)); - downButton->addButtonListener (this); + addAndMakeVisible (downButton = new DrawableButton (String::empty, DrawableButton::ImageOnButtonBackground)); + downButton->addButtonListener (this); - { - Path arrowPath; - arrowPath.addArrow (50.0f, 0.0f, 50.0f, 100.0f, 40.0f, 100.0f, 50.0f); - DrawablePath arrowImage; - arrowImage.setFill (Colours::black.withAlpha (0.4f)); - arrowImage.setPath (arrowPath); + { + Path arrowPath; + arrowPath.addArrow (50.0f, 0.0f, 50.0f, 100.0f, 40.0f, 100.0f, 50.0f); + DrawablePath arrowImage; + arrowImage.setFill (Colours::black.withAlpha (0.4f)); + arrowImage.setPath (arrowPath); - ((DrawableButton*) downButton)->setImages (&arrowImage); - } + ((DrawableButton*) downButton)->setImages (&arrowImage); + } - updateButtons(); + updateButtons(); } FileSearchPathListComponent::~FileSearchPathListComponent() { - deleteAllChildren(); + deleteAllChildren(); } void FileSearchPathListComponent::updateButtons() throw() { - const bool anythingSelected = listBox->getNumSelectedRows() > 0; + const bool anythingSelected = listBox->getNumSelectedRows() > 0; - removeButton->setEnabled (anythingSelected); - changeButton->setEnabled (anythingSelected); - upButton->setEnabled (anythingSelected); - downButton->setEnabled (anythingSelected); + removeButton->setEnabled (anythingSelected); + changeButton->setEnabled (anythingSelected); + upButton->setEnabled (anythingSelected); + downButton->setEnabled (anythingSelected); } void FileSearchPathListComponent::changed() throw() { - listBox->updateContent(); - listBox->repaint(); - updateButtons(); + listBox->updateContent(); + listBox->repaint(); + updateButtons(); } void FileSearchPathListComponent::setPath (const FileSearchPath& newPath) { - if (newPath.toString() != path.toString()) - { - path = newPath; - changed(); - } + if (newPath.toString() != path.toString()) + { + path = newPath; + changed(); + } } void FileSearchPathListComponent::setDefaultBrowseTarget (const File& newDefaultDirectory) throw() { - defaultBrowseTarget = newDefaultDirectory; + defaultBrowseTarget = newDefaultDirectory; } int FileSearchPathListComponent::getNumRows() { - return path.getNumPaths(); + return path.getNumPaths(); } void FileSearchPathListComponent::paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) { - if (rowIsSelected) - g.fillAll (findColour (TextEditor::highlightColourId)); + if (rowIsSelected) + g.fillAll (findColour (TextEditor::highlightColourId)); - g.setColour (findColour (ListBox::textColourId)); - Font f (height * 0.7f); - f.setHorizontalScale (0.9f); - g.setFont (f); + g.setColour (findColour (ListBox::textColourId)); + Font f (height * 0.7f); + f.setHorizontalScale (0.9f); + g.setFont (f); - g.drawText (path [rowNumber].getFullPathName(), - 4, 0, width - 6, height, - Justification::centredLeft, true); + g.drawText (path [rowNumber].getFullPathName(), + 4, 0, width - 6, height, + Justification::centredLeft, true); } void FileSearchPathListComponent::deleteKeyPressed (int row) { - if (((unsigned int) row) < (unsigned int) path.getNumPaths()) - { - path.remove (row); - changed(); - } + if (((unsigned int) row) < (unsigned int) path.getNumPaths()) + { + path.remove (row); + changed(); + } } void FileSearchPathListComponent::returnKeyPressed (int row) { - FileChooser chooser (TRANS("Change folder..."), path [row], T("*")); + FileChooser chooser (TRANS("Change folder..."), path [row], T("*")); - if (chooser.browseForDirectory()) - { - path.remove (row); - path.add (chooser.getResult(), row); - changed(); - } + if (chooser.browseForDirectory()) + { + path.remove (row); + path.add (chooser.getResult(), row); + changed(); + } } void FileSearchPathListComponent::listBoxItemDoubleClicked (int row, const MouseEvent&) { - returnKeyPressed (row); + returnKeyPressed (row); } void FileSearchPathListComponent::selectedRowsChanged (int) { - updateButtons(); + updateButtons(); } void FileSearchPathListComponent::paint (Graphics& g) { - g.fillAll (findColour (backgroundColourId)); + g.fillAll (findColour (backgroundColourId)); } void FileSearchPathListComponent::resized() { - const int buttonH = 22; - const int buttonY = getHeight() - buttonH - 4; - listBox->setBounds (2, 2, getWidth() - 4, buttonY - 5); + const int buttonH = 22; + const int buttonY = getHeight() - buttonH - 4; + listBox->setBounds (2, 2, getWidth() - 4, buttonY - 5); - addButton->setBounds (2, buttonY, buttonH, buttonH); - removeButton->setBounds (addButton->getRight(), buttonY, buttonH, buttonH); + addButton->setBounds (2, buttonY, buttonH, buttonH); + removeButton->setBounds (addButton->getRight(), buttonY, buttonH, buttonH); - ((TextButton*) changeButton)->changeWidthToFitText (buttonH); - downButton->setSize (buttonH * 2, buttonH); - upButton->setSize (buttonH * 2, buttonH); + ((TextButton*) changeButton)->changeWidthToFitText (buttonH); + downButton->setSize (buttonH * 2, buttonH); + upButton->setSize (buttonH * 2, buttonH); - downButton->setTopRightPosition (getWidth() - 2, buttonY); - upButton->setTopRightPosition (downButton->getX() - 4, buttonY); - changeButton->setTopRightPosition (upButton->getX() - 8, buttonY); + downButton->setTopRightPosition (getWidth() - 2, buttonY); + upButton->setTopRightPosition (downButton->getX() - 4, buttonY); + changeButton->setTopRightPosition (upButton->getX() - 8, buttonY); } bool FileSearchPathListComponent::isInterestedInFileDrag (const StringArray&) { - return true; + return true; } void FileSearchPathListComponent::filesDropped (const StringArray& filenames, int, int mouseY) { - for (int i = filenames.size(); --i >= 0;) - { - const File f (filenames[i]); + for (int i = filenames.size(); --i >= 0;) + { + const File f (filenames[i]); - if (f.isDirectory()) - { - const int row = listBox->getRowContainingPosition (0, mouseY - listBox->getY()); - path.add (f, row); - changed(); - } - } + if (f.isDirectory()) + { + const int row = listBox->getRowContainingPosition (0, mouseY - listBox->getY()); + path.add (f, row); + changed(); + } + } } void FileSearchPathListComponent::buttonClicked (Button* button) { - const int currentRow = listBox->getSelectedRow(); + const int currentRow = listBox->getSelectedRow(); - if (button == removeButton) - { - deleteKeyPressed (currentRow); - } - else if (button == addButton) - { - File start (defaultBrowseTarget); + if (button == removeButton) + { + deleteKeyPressed (currentRow); + } + else if (button == addButton) + { + File start (defaultBrowseTarget); - if (start == File::nonexistent) - start = path [0]; + if (start == File::nonexistent) + start = path [0]; - if (start == File::nonexistent) - start = File::getCurrentWorkingDirectory(); + if (start == File::nonexistent) + start = File::getCurrentWorkingDirectory(); - FileChooser chooser (TRANS("Add a folder..."), start, T("*")); + FileChooser chooser (TRANS("Add a folder..."), start, T("*")); - if (chooser.browseForDirectory()) - { - path.add (chooser.getResult(), currentRow); - } - } - else if (button == changeButton) - { - returnKeyPressed (currentRow); - } - else if (button == upButton) - { - if (currentRow > 0 && currentRow < path.getNumPaths()) - { - const File f (path[currentRow]); - path.remove (currentRow); - path.add (f, currentRow - 1); - listBox->selectRow (currentRow - 1); - } - } - else if (button == downButton) - { - if (currentRow >= 0 && currentRow < path.getNumPaths() - 1) - { - const File f (path[currentRow]); - path.remove (currentRow); - path.add (f, currentRow + 1); - listBox->selectRow (currentRow + 1); - } - } + if (chooser.browseForDirectory()) + { + path.add (chooser.getResult(), currentRow); + } + } + else if (button == changeButton) + { + returnKeyPressed (currentRow); + } + else if (button == upButton) + { + if (currentRow > 0 && currentRow < path.getNumPaths()) + { + const File f (path[currentRow]); + path.remove (currentRow); + path.add (f, currentRow - 1); + listBox->selectRow (currentRow - 1); + } + } + else if (button == downButton) + { + if (currentRow >= 0 && currentRow < path.getNumPaths() - 1) + { + const File f (path[currentRow]); + path.remove (currentRow); + path.add (f, currentRow + 1); + listBox->selectRow (currentRow + 1); + } + } - changed(); + changed(); } END_JUCE_NAMESPACE @@ -59089,229 +58790,229 @@ BEGIN_JUCE_NAMESPACE Image* juce_createIconForFile (const File& file); class FileListTreeItem : public TreeViewItem, - public TimeSliceClient, - public AsyncUpdater, - public ChangeListener + public TimeSliceClient, + public AsyncUpdater, + public ChangeListener { public: - FileListTreeItem (FileTreeComponent& owner_, - DirectoryContentsList* const parentContentsList_, - const int indexInContentsList_, - const File& file_, - TimeSliceThread& thread_) throw() - : file (file_), - owner (owner_), - parentContentsList (parentContentsList_), - indexInContentsList (indexInContentsList_), - subContentsList (0), - canDeleteSubContentsList (false), - thread (thread_), - icon (0) - { - DirectoryContentsList::FileInfo fileInfo; + FileListTreeItem (FileTreeComponent& owner_, + DirectoryContentsList* const parentContentsList_, + const int indexInContentsList_, + const File& file_, + TimeSliceThread& thread_) throw() + : file (file_), + owner (owner_), + parentContentsList (parentContentsList_), + indexInContentsList (indexInContentsList_), + subContentsList (0), + canDeleteSubContentsList (false), + thread (thread_), + icon (0) + { + DirectoryContentsList::FileInfo fileInfo; - if (parentContentsList_ != 0 - && parentContentsList_->getFileInfo (indexInContentsList_, fileInfo)) - { - fileSize = File::descriptionOfSizeInBytes (fileInfo.fileSize); - modTime = fileInfo.modificationTime.formatted (T("%d %b '%y %H:%M")); - isDirectory = fileInfo.isDirectory; - } - else - { - isDirectory = true; - } - } + if (parentContentsList_ != 0 + && parentContentsList_->getFileInfo (indexInContentsList_, fileInfo)) + { + fileSize = File::descriptionOfSizeInBytes (fileInfo.fileSize); + modTime = fileInfo.modificationTime.formatted (T("%d %b '%y %H:%M")); + isDirectory = fileInfo.isDirectory; + } + else + { + isDirectory = true; + } + } - ~FileListTreeItem() throw() - { - thread.removeTimeSliceClient (this); + ~FileListTreeItem() throw() + { + thread.removeTimeSliceClient (this); - clearSubItems(); - ImageCache::release (icon); + clearSubItems(); + ImageCache::release (icon); - if (canDeleteSubContentsList) - delete subContentsList; - } + if (canDeleteSubContentsList) + delete subContentsList; + } - bool mightContainSubItems() { return isDirectory; } - const String getUniqueName() const { return file.getFullPathName(); } - int getItemHeight() const { return 22; } + bool mightContainSubItems() { return isDirectory; } + const String getUniqueName() const { return file.getFullPathName(); } + int getItemHeight() const { return 22; } - const String getDragSourceDescription() { return owner.getDragAndDropDescription(); } + const String getDragSourceDescription() { return owner.getDragAndDropDescription(); } - void itemOpennessChanged (bool isNowOpen) - { - if (isNowOpen) - { - clearSubItems(); + void itemOpennessChanged (bool isNowOpen) + { + if (isNowOpen) + { + clearSubItems(); - isDirectory = file.isDirectory(); + isDirectory = file.isDirectory(); - if (isDirectory) - { - if (subContentsList == 0) - { - jassert (parentContentsList != 0); + if (isDirectory) + { + if (subContentsList == 0) + { + jassert (parentContentsList != 0); - DirectoryContentsList* const l = new DirectoryContentsList (parentContentsList->getFilter(), thread); - l->setDirectory (file, true, true); + DirectoryContentsList* const l = new DirectoryContentsList (parentContentsList->getFilter(), thread); + l->setDirectory (file, true, true); - setSubContentsList (l); - canDeleteSubContentsList = true; - } + setSubContentsList (l); + canDeleteSubContentsList = true; + } - changeListenerCallback (0); - } - } - } + changeListenerCallback (0); + } + } + } - void setSubContentsList (DirectoryContentsList* newList) throw() - { - jassert (subContentsList == 0); - subContentsList = newList; - newList->addChangeListener (this); - } + void setSubContentsList (DirectoryContentsList* newList) throw() + { + jassert (subContentsList == 0); + subContentsList = newList; + newList->addChangeListener (this); + } - void changeListenerCallback (void*) - { - clearSubItems(); + void changeListenerCallback (void*) + { + clearSubItems(); - if (isOpen() && subContentsList != 0) - { - for (int i = 0; i < subContentsList->getNumFiles(); ++i) - { - FileListTreeItem* const item - = new FileListTreeItem (owner, subContentsList, i, subContentsList->getFile(i), thread); + if (isOpen() && subContentsList != 0) + { + for (int i = 0; i < subContentsList->getNumFiles(); ++i) + { + FileListTreeItem* const item + = new FileListTreeItem (owner, subContentsList, i, subContentsList->getFile(i), thread); - addSubItem (item); - } - } - } + addSubItem (item); + } + } + } - void paintItem (Graphics& g, int width, int height) - { - if (file != File::nonexistent) - { - updateIcon (true); + void paintItem (Graphics& g, int width, int height) + { + if (file != File::nonexistent) + { + updateIcon (true); - if (icon == 0) - thread.addTimeSliceClient (this); - } + if (icon == 0) + thread.addTimeSliceClient (this); + } - owner.getLookAndFeel() - .drawFileBrowserRow (g, width, height, - file.getFileName(), - icon, - fileSize, modTime, - isDirectory, isSelected(), - indexInContentsList); - } + owner.getLookAndFeel() + .drawFileBrowserRow (g, width, height, + file.getFileName(), + icon, + fileSize, modTime, + isDirectory, isSelected(), + indexInContentsList); + } - void itemClicked (const MouseEvent& e) - { - owner.sendMouseClickMessage (file, e); - } + void itemClicked (const MouseEvent& e) + { + owner.sendMouseClickMessage (file, e); + } - void itemDoubleClicked (const MouseEvent& e) - { - TreeViewItem::itemDoubleClicked (e); + void itemDoubleClicked (const MouseEvent& e) + { + TreeViewItem::itemDoubleClicked (e); - owner.sendDoubleClickMessage (file); - } + owner.sendDoubleClickMessage (file); + } - void itemSelectionChanged (bool) - { - owner.sendSelectionChangeMessage(); - } + void itemSelectionChanged (bool) + { + owner.sendSelectionChangeMessage(); + } - bool useTimeSlice() - { - updateIcon (false); - thread.removeTimeSliceClient (this); - return false; - } + bool useTimeSlice() + { + updateIcon (false); + thread.removeTimeSliceClient (this); + return false; + } - void handleAsyncUpdate() - { - owner.repaint(); - } + void handleAsyncUpdate() + { + owner.repaint(); + } - const File file; + const File file; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - FileTreeComponent& owner; - DirectoryContentsList* parentContentsList; - int indexInContentsList; - DirectoryContentsList* subContentsList; - bool isDirectory, canDeleteSubContentsList; - TimeSliceThread& thread; - Image* icon; - String fileSize; - String modTime; + FileTreeComponent& owner; + DirectoryContentsList* parentContentsList; + int indexInContentsList; + DirectoryContentsList* subContentsList; + bool isDirectory, canDeleteSubContentsList; + TimeSliceThread& thread; + Image* icon; + String fileSize; + String modTime; - void updateIcon (const bool onlyUpdateIfCached) throw() - { - if (icon == 0) - { - const int hashCode = (file.getFullPathName() + T("_iconCacheSalt")).hashCode(); - Image* im = ImageCache::getFromHashCode (hashCode); + void updateIcon (const bool onlyUpdateIfCached) throw() + { + if (icon == 0) + { + const int hashCode = (file.getFullPathName() + T("_iconCacheSalt")).hashCode(); + Image* im = ImageCache::getFromHashCode (hashCode); - if (im == 0 && ! onlyUpdateIfCached) - { - im = juce_createIconForFile (file); + if (im == 0 && ! onlyUpdateIfCached) + { + im = juce_createIconForFile (file); - if (im != 0) - ImageCache::addImageToCache (im, hashCode); - } + if (im != 0) + ImageCache::addImageToCache (im, hashCode); + } - if (im != 0) - { - icon = im; - triggerAsyncUpdate(); - } - } - } + if (im != 0) + { + icon = im; + triggerAsyncUpdate(); + } + } + } }; FileTreeComponent::FileTreeComponent (DirectoryContentsList& listToShow) - : DirectoryContentsDisplayComponent (listToShow) + : DirectoryContentsDisplayComponent (listToShow) { - FileListTreeItem* const root - = new FileListTreeItem (*this, 0, 0, listToShow.getDirectory(), - listToShow.getTimeSliceThread()); + FileListTreeItem* const root + = new FileListTreeItem (*this, 0, 0, listToShow.getDirectory(), + listToShow.getTimeSliceThread()); - root->setSubContentsList (&listToShow); - setRootItemVisible (false); - setRootItem (root); + root->setSubContentsList (&listToShow); + setRootItemVisible (false); + setRootItem (root); } FileTreeComponent::~FileTreeComponent() { - deleteRootItem(); + deleteRootItem(); } const File FileTreeComponent::getSelectedFile (const int index) const { - const FileListTreeItem* const item = dynamic_cast (getSelectedItem (index)); + const FileListTreeItem* const item = dynamic_cast (getSelectedItem (index)); - if (item != 0) - return item->file; + if (item != 0) + return item->file; - return File::nonexistent; + return File::nonexistent; } void FileTreeComponent::scrollToTop() { - getViewport()->getVerticalScrollBar()->setCurrentRangeStart (0); + getViewport()->getVerticalScrollBar()->setCurrentRangeStart (0); } void FileTreeComponent::setDragAndDropDescription (const String& description) throw() { - dragAndDropDescription = description; + dragAndDropDescription = description; } END_JUCE_NAMESPACE @@ -59331,86 +59032,86 @@ ImagePreviewComponent::~ImagePreviewComponent() void ImagePreviewComponent::getThumbSize (int& w, int& h) const { - const int availableW = proportionOfWidth (0.97f); - const int availableH = getHeight() - 13 * 4; + const int availableW = proportionOfWidth (0.97f); + const int availableH = getHeight() - 13 * 4; - const double scale = jmin (1.0, - availableW / (double) w, - availableH / (double) h); + const double scale = jmin (1.0, + availableW / (double) w, + availableH / (double) h); - w = roundDoubleToInt (scale * w); - h = roundDoubleToInt (scale * h); + w = roundToInt (scale * w); + h = roundToInt (scale * h); } void ImagePreviewComponent::selectedFileChanged (const File& file) { - if (fileToLoad != file) - { - fileToLoad = file; - startTimer (100); - } + if (fileToLoad != file) + { + fileToLoad = file; + startTimer (100); + } } void ImagePreviewComponent::timerCallback() { - stopTimer(); + stopTimer(); - currentThumbnail = 0; - currentDetails = String::empty; - repaint(); + currentThumbnail = 0; + currentDetails = String::empty; + repaint(); - ScopedPointer in (fileToLoad.createInputStream()); + ScopedPointer in (fileToLoad.createInputStream()); - if (in != 0) - { - ImageFileFormat* const format = ImageFileFormat::findImageFormatForStream (*in); + if (in != 0) + { + ImageFileFormat* const format = ImageFileFormat::findImageFormatForStream (*in); - if (format != 0) - { - currentThumbnail = format->decodeImage (*in); + if (format != 0) + { + currentThumbnail = format->decodeImage (*in); - if (currentThumbnail != 0) - { - int w = currentThumbnail->getWidth(); - int h = currentThumbnail->getHeight(); + if (currentThumbnail != 0) + { + int w = currentThumbnail->getWidth(); + int h = currentThumbnail->getHeight(); - currentDetails - << fileToLoad.getFileName() << "\n" - << format->getFormatName() << "\n" - << w << " x " << h << " pixels\n" - << File::descriptionOfSizeInBytes (fileToLoad.getSize()); + currentDetails + << fileToLoad.getFileName() << "\n" + << format->getFormatName() << "\n" + << w << " x " << h << " pixels\n" + << File::descriptionOfSizeInBytes (fileToLoad.getSize()); - getThumbSize (w, h); + getThumbSize (w, h); - currentThumbnail = currentThumbnail->createCopy (w, h); - } - } - } + currentThumbnail = currentThumbnail->createCopy (w, h); + } + } + } } void ImagePreviewComponent::paint (Graphics& g) { - if (currentThumbnail != 0) - { - g.setFont (13.0f); + if (currentThumbnail != 0) + { + g.setFont (13.0f); - int w = currentThumbnail->getWidth(); - int h = currentThumbnail->getHeight(); - getThumbSize (w, h); + int w = currentThumbnail->getWidth(); + int h = currentThumbnail->getHeight(); + getThumbSize (w, h); - const int numLines = 4; - const int totalH = 13 * numLines + h + 4; - const int y = (getHeight() - totalH) / 2; + const int numLines = 4; + const int totalH = 13 * numLines + h + 4; + const int y = (getHeight() - totalH) / 2; - g.drawImageWithin (currentThumbnail, - (getWidth() - w) / 2, y, w, h, - RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, - false); + g.drawImageWithin (currentThumbnail, + (getWidth() - w) / 2, y, w, h, + RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, + false); - g.drawFittedText (currentDetails, - 0, y + h + 4, getWidth(), 100, - Justification::centredTop, numLines); - } + g.drawFittedText (currentDetails, + 0, y + h + 4, getWidth(), 100, + Justification::centredTop, numLines); + } } END_JUCE_NAMESPACE @@ -59421,13 +59122,13 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE WildcardFileFilter::WildcardFileFilter (const String& fileWildcardPatterns, - const String& directoryWildcardPatterns, - const String& description_) - : FileFilter (description_.isEmpty() ? fileWildcardPatterns - : (description_ + T(" (") + fileWildcardPatterns + T(")"))) + const String& directoryWildcardPatterns, + const String& description_) + : FileFilter (description_.isEmpty() ? fileWildcardPatterns + : (description_ + T(" (") + fileWildcardPatterns + T(")"))) { - parse (fileWildcardPatterns, fileWildcards); - parse (directoryWildcardPatterns, directoryWildcards); + parse (fileWildcardPatterns, fileWildcards); + parse (directoryWildcardPatterns, directoryWildcards); } WildcardFileFilter::~WildcardFileFilter() @@ -59436,37 +59137,37 @@ WildcardFileFilter::~WildcardFileFilter() bool WildcardFileFilter::isFileSuitable (const File& file) const { - return match (file, fileWildcards); + return match (file, fileWildcards); } bool WildcardFileFilter::isDirectorySuitable (const File& file) const { - return match (file, directoryWildcards); + return match (file, directoryWildcards); } void WildcardFileFilter::parse (const String& pattern, StringArray& result) throw() { - result.addTokens (pattern.toLowerCase(), T(";,"), T("\"'")); + result.addTokens (pattern.toLowerCase(), T(";,"), T("\"'")); - result.trim(); - result.removeEmptyStrings(); + result.trim(); + result.removeEmptyStrings(); - // special case for *.*, because people use it to mean "any file", but it - // would actually ignore files with no extension. - for (int i = result.size(); --i >= 0;) - if (result[i] == T("*.*")) - result.set (i, T("*")); + // special case for *.*, because people use it to mean "any file", but it + // would actually ignore files with no extension. + for (int i = result.size(); --i >= 0;) + if (result[i] == T("*.*")) + result.set (i, T("*")); } bool WildcardFileFilter::match (const File& file, const StringArray& wildcards) throw() { - const String filename (file.getFileName()); + const String filename (file.getFileName()); - for (int i = wildcards.size(); --i >= 0;) - if (filename.matchesWildcard (wildcards[i], true)) - return true; + for (int i = wildcards.size(); --i >= 0;) + if (filename.matchesWildcard (wildcards[i], true)) + return true; - return false; + return false; } END_JUCE_NAMESPACE @@ -59489,100 +59190,100 @@ KeyboardFocusTraverser::~KeyboardFocusTraverser() class ScreenPositionComparator { public: - ScreenPositionComparator() {} + ScreenPositionComparator() {} - static int compareElements (const Component* const first, const Component* const second) throw() - { - int explicitOrder1 = first->getExplicitFocusOrder(); - if (explicitOrder1 <= 0) - explicitOrder1 = INT_MAX / 2; + static int compareElements (const Component* const first, const Component* const second) throw() + { + int explicitOrder1 = first->getExplicitFocusOrder(); + if (explicitOrder1 <= 0) + explicitOrder1 = INT_MAX / 2; - int explicitOrder2 = second->getExplicitFocusOrder(); - if (explicitOrder2 <= 0) - explicitOrder2 = INT_MAX / 2; + int explicitOrder2 = second->getExplicitFocusOrder(); + if (explicitOrder2 <= 0) + explicitOrder2 = INT_MAX / 2; - if (explicitOrder1 != explicitOrder2) - return explicitOrder1 - explicitOrder2; + if (explicitOrder1 != explicitOrder2) + return explicitOrder1 - explicitOrder2; - const int diff = first->getY() - second->getY(); + const int diff = first->getY() - second->getY(); - return (diff == 0) ? first->getX() - second->getX() - : diff; - } + return (diff == 0) ? first->getX() - second->getX() + : diff; + } }; static void findAllFocusableComponents (Component* const parent, Array & comps) { - if (parent->getNumChildComponents() > 0) - { - Array localComps; - ScreenPositionComparator comparator; + if (parent->getNumChildComponents() > 0) + { + Array localComps; + ScreenPositionComparator comparator; - int i; - for (i = parent->getNumChildComponents(); --i >= 0;) - { - Component* const c = parent->getChildComponent (i); + int i; + for (i = parent->getNumChildComponents(); --i >= 0;) + { + Component* const c = parent->getChildComponent (i); - if (c->isVisible() && c->isEnabled()) - localComps.addSorted (comparator, c); - } + if (c->isVisible() && c->isEnabled()) + localComps.addSorted (comparator, c); + } - for (i = 0; i < localComps.size(); ++i) - { - Component* const c = localComps.getUnchecked (i); + for (i = 0; i < localComps.size(); ++i) + { + Component* const c = localComps.getUnchecked (i); - if (c->getWantsKeyboardFocus()) - comps.add (c); + if (c->getWantsKeyboardFocus()) + comps.add (c); - if (! c->isFocusContainer()) - findAllFocusableComponents (c, comps); - } - } + if (! c->isFocusContainer()) + findAllFocusableComponents (c, comps); + } + } } static Component* getIncrementedComponent (Component* const current, const int delta) throw() { - Component* focusContainer = current->getParentComponent(); + Component* focusContainer = current->getParentComponent(); - if (focusContainer != 0) - { - while (focusContainer->getParentComponent() != 0 && ! focusContainer->isFocusContainer()) - focusContainer = focusContainer->getParentComponent(); + if (focusContainer != 0) + { + while (focusContainer->getParentComponent() != 0 && ! focusContainer->isFocusContainer()) + focusContainer = focusContainer->getParentComponent(); - if (focusContainer != 0) - { - Array comps; - findAllFocusableComponents (focusContainer, comps); + if (focusContainer != 0) + { + Array comps; + findAllFocusableComponents (focusContainer, comps); - if (comps.size() > 0) - { - const int index = comps.indexOf (current); - return comps [(index + comps.size() + delta) % comps.size()]; - } - } - } + if (comps.size() > 0) + { + const int index = comps.indexOf (current); + return comps [(index + comps.size() + delta) % comps.size()]; + } + } + } - return 0; + return 0; } Component* KeyboardFocusTraverser::getNextComponent (Component* current) { - return getIncrementedComponent (current, 1); + return getIncrementedComponent (current, 1); } Component* KeyboardFocusTraverser::getPreviousComponent (Component* current) { - return getIncrementedComponent (current, -1); + return getIncrementedComponent (current, -1); } Component* KeyboardFocusTraverser::getDefaultComponent (Component* parentComponent) { - Array comps; + Array comps; - if (parentComponent != 0) - findAllFocusableComponents (parentComponent, comps); + if (parentComponent != 0) + findAllFocusableComponents (parentComponent, comps); - return comps.getFirst(); + return comps.getFirst(); } END_JUCE_NAMESPACE @@ -59594,7 +59295,7 @@ BEGIN_JUCE_NAMESPACE bool KeyListener::keyStateChanged (const bool, Component*) { - return false; + return false; } END_JUCE_NAMESPACE @@ -59612,472 +59313,472 @@ const int maxKeys = 3; class KeyMappingChangeButton : public Button { public: - KeyMappingChangeButton (KeyMappingEditorComponent* const owner_, - const CommandID commandID_, - const String& keyName, - const int keyNum_) - : Button (keyName), - owner (owner_), - commandID (commandID_), - keyNum (keyNum_) - { - setWantsKeyboardFocus (false); - setTriggeredOnMouseDown (keyNum >= 0); + KeyMappingChangeButton (KeyMappingEditorComponent* const owner_, + const CommandID commandID_, + const String& keyName, + const int keyNum_) + : Button (keyName), + owner (owner_), + commandID (commandID_), + keyNum (keyNum_) + { + setWantsKeyboardFocus (false); + setTriggeredOnMouseDown (keyNum >= 0); - if (keyNum_ < 0) - setTooltip (TRANS("adds a new key-mapping")); - else - setTooltip (TRANS("click to change this key-mapping")); - } + if (keyNum_ < 0) + setTooltip (TRANS("adds a new key-mapping")); + else + setTooltip (TRANS("click to change this key-mapping")); + } - ~KeyMappingChangeButton() - { - } + ~KeyMappingChangeButton() + { + } - void paintButton (Graphics& g, bool isOver, bool isDown) - { - getLookAndFeel().drawKeymapChangeButton (g, getWidth(), getHeight(), *this, - keyNum >= 0 ? getName() : String::empty); - } + void paintButton (Graphics& g, bool isOver, bool isDown) + { + getLookAndFeel().drawKeymapChangeButton (g, getWidth(), getHeight(), *this, + keyNum >= 0 ? getName() : String::empty); + } - void clicked() - { - if (keyNum >= 0) - { - // existing key clicked.. - PopupMenu m; - m.addItem (1, TRANS("change this key-mapping")); - m.addSeparator(); - m.addItem (2, TRANS("remove this key-mapping")); + void clicked() + { + if (keyNum >= 0) + { + // existing key clicked.. + PopupMenu m; + m.addItem (1, TRANS("change this key-mapping")); + m.addSeparator(); + m.addItem (2, TRANS("remove this key-mapping")); - const int res = m.show(); + const int res = m.show(); - if (res == 1) - { - owner->assignNewKey (commandID, keyNum); - } - else if (res == 2) - { - owner->getMappings()->removeKeyPress (commandID, keyNum); - } - } - else - { - // + button pressed.. - owner->assignNewKey (commandID, -1); - } - } + if (res == 1) + { + owner->assignNewKey (commandID, keyNum); + } + else if (res == 2) + { + owner->getMappings()->removeKeyPress (commandID, keyNum); + } + } + else + { + // + button pressed.. + owner->assignNewKey (commandID, -1); + } + } - void fitToContent (const int h) throw() - { - if (keyNum < 0) - { - setSize (h, h); - } - else - { - Font f (h * 0.6f); - setSize (jlimit (h * 4, h * 8, 6 + f.getStringWidth (getName())), h); - } - } + void fitToContent (const int h) throw() + { + if (keyNum < 0) + { + setSize (h, h); + } + else + { + Font f (h * 0.6f); + setSize (jlimit (h * 4, h * 8, 6 + f.getStringWidth (getName())), h); + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - KeyMappingEditorComponent* const owner; - const CommandID commandID; - const int keyNum; + KeyMappingEditorComponent* const owner; + const CommandID commandID; + const int keyNum; - KeyMappingChangeButton (const KeyMappingChangeButton&); - const KeyMappingChangeButton& operator= (const KeyMappingChangeButton&); + KeyMappingChangeButton (const KeyMappingChangeButton&); + const KeyMappingChangeButton& operator= (const KeyMappingChangeButton&); }; class KeyMappingItemComponent : public Component { public: - KeyMappingItemComponent (KeyMappingEditorComponent* const owner_, - const CommandID commandID_) - : owner (owner_), - commandID (commandID_) - { - setInterceptsMouseClicks (false, true); + KeyMappingItemComponent (KeyMappingEditorComponent* const owner_, + const CommandID commandID_) + : owner (owner_), + commandID (commandID_) + { + setInterceptsMouseClicks (false, true); - const bool isReadOnly = owner_->isCommandReadOnly (commandID); + const bool isReadOnly = owner_->isCommandReadOnly (commandID); - const Array keyPresses (owner_->getMappings()->getKeyPressesAssignedToCommand (commandID)); + const Array keyPresses (owner_->getMappings()->getKeyPressesAssignedToCommand (commandID)); - for (int i = 0; i < jmin (maxKeys, keyPresses.size()); ++i) - { - KeyMappingChangeButton* const kb - = new KeyMappingChangeButton (owner_, commandID, - owner_->getDescriptionForKeyPress (keyPresses.getReference (i)), i); + for (int i = 0; i < jmin (maxKeys, keyPresses.size()); ++i) + { + KeyMappingChangeButton* const kb + = new KeyMappingChangeButton (owner_, commandID, + owner_->getDescriptionForKeyPress (keyPresses.getReference (i)), i); - kb->setEnabled (! isReadOnly); - addAndMakeVisible (kb); - } + kb->setEnabled (! isReadOnly); + addAndMakeVisible (kb); + } - KeyMappingChangeButton* const kb - = new KeyMappingChangeButton (owner_, commandID, String::empty, -1); + KeyMappingChangeButton* const kb + = new KeyMappingChangeButton (owner_, commandID, String::empty, -1); - addChildComponent (kb); - kb->setVisible (keyPresses.size() < maxKeys && ! isReadOnly); - } + addChildComponent (kb); + kb->setVisible (keyPresses.size() < maxKeys && ! isReadOnly); + } - ~KeyMappingItemComponent() - { - deleteAllChildren(); - } + ~KeyMappingItemComponent() + { + deleteAllChildren(); + } - void paint (Graphics& g) - { - g.setFont (getHeight() * 0.7f); - g.setColour (findColour (KeyMappingEditorComponent::textColourId)); + void paint (Graphics& g) + { + g.setFont (getHeight() * 0.7f); + g.setColour (findColour (KeyMappingEditorComponent::textColourId)); - g.drawFittedText (owner->getMappings()->getCommandManager()->getNameOfCommand (commandID), - 4, 0, jmax (40, getChildComponent (0)->getX() - 5), getHeight(), - Justification::centredLeft, true); - } + g.drawFittedText (owner->getMappings()->getCommandManager()->getNameOfCommand (commandID), + 4, 0, jmax (40, getChildComponent (0)->getX() - 5), getHeight(), + Justification::centredLeft, true); + } - void resized() - { - int x = getWidth() - 4; + void resized() + { + int x = getWidth() - 4; - for (int i = getNumChildComponents(); --i >= 0;) - { - KeyMappingChangeButton* const kb = dynamic_cast (getChildComponent (i)); + for (int i = getNumChildComponents(); --i >= 0;) + { + KeyMappingChangeButton* const kb = dynamic_cast (getChildComponent (i)); - kb->fitToContent (getHeight() - 2); - kb->setTopRightPosition (x, 1); - x -= kb->getWidth() + 5; - } - } + kb->fitToContent (getHeight() - 2); + kb->setTopRightPosition (x, 1); + x -= kb->getWidth() + 5; + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - KeyMappingEditorComponent* const owner; - const CommandID commandID; + KeyMappingEditorComponent* const owner; + const CommandID commandID; - KeyMappingItemComponent (const KeyMappingItemComponent&); - const KeyMappingItemComponent& operator= (const KeyMappingItemComponent&); + KeyMappingItemComponent (const KeyMappingItemComponent&); + const KeyMappingItemComponent& operator= (const KeyMappingItemComponent&); }; class KeyMappingTreeViewItem : public TreeViewItem { public: - KeyMappingTreeViewItem (KeyMappingEditorComponent* const owner_, - const CommandID commandID_) - : owner (owner_), - commandID (commandID_) - { - } + KeyMappingTreeViewItem (KeyMappingEditorComponent* const owner_, + const CommandID commandID_) + : owner (owner_), + commandID (commandID_) + { + } - ~KeyMappingTreeViewItem() - { - } + ~KeyMappingTreeViewItem() + { + } - const String getUniqueName() const { return String ((int) commandID) + "_id"; } - bool mightContainSubItems() { return false; } - int getItemHeight() const { return 20; } + const String getUniqueName() const { return String ((int) commandID) + "_id"; } + bool mightContainSubItems() { return false; } + int getItemHeight() const { return 20; } - Component* createItemComponent() - { - return new KeyMappingItemComponent (owner, commandID); - } + Component* createItemComponent() + { + return new KeyMappingItemComponent (owner, commandID); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - KeyMappingEditorComponent* const owner; - const CommandID commandID; + KeyMappingEditorComponent* const owner; + const CommandID commandID; - KeyMappingTreeViewItem (const KeyMappingTreeViewItem&); - const KeyMappingTreeViewItem& operator= (const KeyMappingTreeViewItem&); + KeyMappingTreeViewItem (const KeyMappingTreeViewItem&); + const KeyMappingTreeViewItem& operator= (const KeyMappingTreeViewItem&); }; class KeyCategoryTreeViewItem : public TreeViewItem { public: - KeyCategoryTreeViewItem (KeyMappingEditorComponent* const owner_, - const String& name) - : owner (owner_), - categoryName (name) - { - } + KeyCategoryTreeViewItem (KeyMappingEditorComponent* const owner_, + const String& name) + : owner (owner_), + categoryName (name) + { + } - ~KeyCategoryTreeViewItem() - { - } + ~KeyCategoryTreeViewItem() + { + } - const String getUniqueName() const { return categoryName + "_cat"; } - bool mightContainSubItems() { return true; } - int getItemHeight() const { return 28; } + const String getUniqueName() const { return categoryName + "_cat"; } + bool mightContainSubItems() { return true; } + int getItemHeight() const { return 28; } - void paintItem (Graphics& g, int width, int height) - { - g.setFont (height * 0.6f, Font::bold); - g.setColour (owner->findColour (KeyMappingEditorComponent::textColourId)); + void paintItem (Graphics& g, int width, int height) + { + g.setFont (height * 0.6f, Font::bold); + g.setColour (owner->findColour (KeyMappingEditorComponent::textColourId)); - g.drawText (categoryName, - 2, 0, width - 2, height, - Justification::centredLeft, true); - } + g.drawText (categoryName, + 2, 0, width - 2, height, + Justification::centredLeft, true); + } - void itemOpennessChanged (bool isNowOpen) - { - if (isNowOpen) - { - if (getNumSubItems() == 0) - { - Array commands (owner->getMappings()->getCommandManager()->getCommandsInCategory (categoryName)); + void itemOpennessChanged (bool isNowOpen) + { + if (isNowOpen) + { + if (getNumSubItems() == 0) + { + Array commands (owner->getMappings()->getCommandManager()->getCommandsInCategory (categoryName)); - for (int i = 0; i < commands.size(); ++i) - { - if (owner->shouldCommandBeIncluded (commands[i])) - addSubItem (new KeyMappingTreeViewItem (owner, commands[i])); - } - } - } - else - { - clearSubItems(); - } - } + for (int i = 0; i < commands.size(); ++i) + { + if (owner->shouldCommandBeIncluded (commands[i])) + addSubItem (new KeyMappingTreeViewItem (owner, commands[i])); + } + } + } + else + { + clearSubItems(); + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - KeyMappingEditorComponent* owner; - String categoryName; + KeyMappingEditorComponent* owner; + String categoryName; - KeyCategoryTreeViewItem (const KeyCategoryTreeViewItem&); - const KeyCategoryTreeViewItem& operator= (const KeyCategoryTreeViewItem&); + KeyCategoryTreeViewItem (const KeyCategoryTreeViewItem&); + const KeyCategoryTreeViewItem& operator= (const KeyCategoryTreeViewItem&); }; KeyMappingEditorComponent::KeyMappingEditorComponent (KeyPressMappingSet* const mappingManager, - const bool showResetToDefaultButton) - : mappings (mappingManager) + const bool showResetToDefaultButton) + : mappings (mappingManager) { - jassert (mappingManager != 0); // can't be null! + jassert (mappingManager != 0); // can't be null! - mappingManager->addChangeListener (this); + mappingManager->addChangeListener (this); - setLinesDrawnForSubItems (false); + setLinesDrawnForSubItems (false); - resetButton = 0; + resetButton = 0; - if (showResetToDefaultButton) - { - addAndMakeVisible (resetButton = new TextButton (TRANS("reset to defaults"))); - resetButton->addButtonListener (this); - } + if (showResetToDefaultButton) + { + addAndMakeVisible (resetButton = new TextButton (TRANS("reset to defaults"))); + resetButton->addButtonListener (this); + } - addAndMakeVisible (tree = new TreeView()); - tree->setColour (TreeView::backgroundColourId, findColour (backgroundColourId)); - tree->setRootItemVisible (false); - tree->setDefaultOpenness (true); - tree->setRootItem (this); + addAndMakeVisible (tree = new TreeView()); + tree->setColour (TreeView::backgroundColourId, findColour (backgroundColourId)); + tree->setRootItemVisible (false); + tree->setDefaultOpenness (true); + tree->setRootItem (this); } KeyMappingEditorComponent::~KeyMappingEditorComponent() { - mappings->removeChangeListener (this); - deleteAllChildren(); + mappings->removeChangeListener (this); + deleteAllChildren(); } bool KeyMappingEditorComponent::mightContainSubItems() { - return true; + return true; } const String KeyMappingEditorComponent::getUniqueName() const { - return T("keys"); + return T("keys"); } void KeyMappingEditorComponent::setColours (const Colour& mainBackground, - const Colour& textColour) + const Colour& textColour) { - setColour (backgroundColourId, mainBackground); - setColour (textColourId, textColour); - tree->setColour (TreeView::backgroundColourId, mainBackground); + setColour (backgroundColourId, mainBackground); + setColour (textColourId, textColour); + tree->setColour (TreeView::backgroundColourId, mainBackground); } void KeyMappingEditorComponent::parentHierarchyChanged() { - changeListenerCallback (0); + changeListenerCallback (0); } void KeyMappingEditorComponent::resized() { - int h = getHeight(); + int h = getHeight(); - if (resetButton != 0) - { - const int buttonHeight = 20; - h -= buttonHeight + 8; - int x = getWidth() - 8; - const int y = h + 6; + if (resetButton != 0) + { + const int buttonHeight = 20; + h -= buttonHeight + 8; + int x = getWidth() - 8; + const int y = h + 6; - resetButton->changeWidthToFitText (buttonHeight); - resetButton->setTopRightPosition (x, y); - } + resetButton->changeWidthToFitText (buttonHeight); + resetButton->setTopRightPosition (x, y); + } - tree->setBounds (0, 0, getWidth(), h); + tree->setBounds (0, 0, getWidth(), h); } void KeyMappingEditorComponent::buttonClicked (Button* button) { - if (button == resetButton) - { - if (AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon, - TRANS("Reset to defaults"), - TRANS("Are you sure you want to reset all the key-mappings to their default state?"), - TRANS("Reset"))) - { - mappings->resetToDefaultMappings(); - } - } + if (button == resetButton) + { + if (AlertWindow::showOkCancelBox (AlertWindow::QuestionIcon, + TRANS("Reset to defaults"), + TRANS("Are you sure you want to reset all the key-mappings to their default state?"), + TRANS("Reset"))) + { + mappings->resetToDefaultMappings(); + } + } } void KeyMappingEditorComponent::changeListenerCallback (void*) { - ScopedPointer openness (tree->getOpennessState (true)); + ScopedPointer openness (tree->getOpennessState (true)); - clearSubItems(); + clearSubItems(); - const StringArray categories (mappings->getCommandManager()->getCommandCategories()); + const StringArray categories (mappings->getCommandManager()->getCommandCategories()); - for (int i = 0; i < categories.size(); ++i) - { - const Array commands (mappings->getCommandManager()->getCommandsInCategory (categories[i])); - int count = 0; + for (int i = 0; i < categories.size(); ++i) + { + const Array commands (mappings->getCommandManager()->getCommandsInCategory (categories[i])); + int count = 0; - for (int j = 0; j < commands.size(); ++j) - if (shouldCommandBeIncluded (commands[j])) - ++count; + for (int j = 0; j < commands.size(); ++j) + if (shouldCommandBeIncluded (commands[j])) + ++count; - if (count > 0) - addSubItem (new KeyCategoryTreeViewItem (this, categories[i])); - } + if (count > 0) + addSubItem (new KeyCategoryTreeViewItem (this, categories[i])); + } - if (openness != 0) - tree->restoreOpennessState (*openness); + if (openness != 0) + tree->restoreOpennessState (*openness); } class KeyEntryWindow : public AlertWindow { public: - KeyEntryWindow (KeyMappingEditorComponent* const owner_) - : AlertWindow (TRANS("New key-mapping"), - TRANS("Please press a key combination now..."), - AlertWindow::NoIcon), - owner (owner_) - { - addButton (TRANS("ok"), 1); - addButton (TRANS("cancel"), 0); + KeyEntryWindow (KeyMappingEditorComponent* const owner_) + : AlertWindow (TRANS("New key-mapping"), + TRANS("Please press a key combination now..."), + AlertWindow::NoIcon), + owner (owner_) + { + addButton (TRANS("ok"), 1); + addButton (TRANS("cancel"), 0); - // (avoid return + escape keys getting processed by the buttons..) - for (int i = getNumChildComponents(); --i >= 0;) - getChildComponent (i)->setWantsKeyboardFocus (false); + // (avoid return + escape keys getting processed by the buttons..) + for (int i = getNumChildComponents(); --i >= 0;) + getChildComponent (i)->setWantsKeyboardFocus (false); - setWantsKeyboardFocus (true); - grabKeyboardFocus(); - } + setWantsKeyboardFocus (true); + grabKeyboardFocus(); + } - ~KeyEntryWindow() - { - } + ~KeyEntryWindow() + { + } - bool keyPressed (const KeyPress& key) - { - lastPress = key; - String message (TRANS("Key: ") + owner->getDescriptionForKeyPress (key)); + bool keyPressed (const KeyPress& key) + { + lastPress = key; + String message (TRANS("Key: ") + owner->getDescriptionForKeyPress (key)); - const CommandID previousCommand = owner->getMappings()->findCommandForKeyPress (key); + const CommandID previousCommand = owner->getMappings()->findCommandForKeyPress (key); - if (previousCommand != 0) - { - message << "\n\n" - << TRANS("(Currently assigned to \"") - << owner->getMappings()->getCommandManager()->getNameOfCommand (previousCommand) - << "\")"; - } + if (previousCommand != 0) + { + message << "\n\n" + << TRANS("(Currently assigned to \"") + << owner->getMappings()->getCommandManager()->getNameOfCommand (previousCommand) + << "\")"; + } - setMessage (message); + setMessage (message); - return true; - } + return true; + } - bool keyStateChanged (const bool) - { - return true; - } + bool keyStateChanged (const bool) + { + return true; + } - KeyPress lastPress; + KeyPress lastPress; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - KeyMappingEditorComponent* owner; + KeyMappingEditorComponent* owner; - KeyEntryWindow (const KeyEntryWindow&); - const KeyEntryWindow& operator= (const KeyEntryWindow&); + KeyEntryWindow (const KeyEntryWindow&); + const KeyEntryWindow& operator= (const KeyEntryWindow&); }; void KeyMappingEditorComponent::assignNewKey (const CommandID commandID, const int index) { - KeyEntryWindow entryWindow (this); + KeyEntryWindow entryWindow (this); - if (entryWindow.runModalLoop() != 0) - { - entryWindow.setVisible (false); + if (entryWindow.runModalLoop() != 0) + { + entryWindow.setVisible (false); - if (entryWindow.lastPress.isValid()) - { - const CommandID previousCommand = mappings->findCommandForKeyPress (entryWindow.lastPress); + if (entryWindow.lastPress.isValid()) + { + const CommandID previousCommand = mappings->findCommandForKeyPress (entryWindow.lastPress); - if (previousCommand != 0) - { - if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, - TRANS("Change key-mapping"), - TRANS("This key is already assigned to the command \"") - + mappings->getCommandManager()->getNameOfCommand (previousCommand) - + TRANS("\"\n\nDo you want to re-assign it to this new command instead?"), - TRANS("re-assign"), - TRANS("cancel"))) - { - return; - } - } + if (previousCommand != 0) + { + if (! AlertWindow::showOkCancelBox (AlertWindow::WarningIcon, + TRANS("Change key-mapping"), + TRANS("This key is already assigned to the command \"") + + mappings->getCommandManager()->getNameOfCommand (previousCommand) + + TRANS("\"\n\nDo you want to re-assign it to this new command instead?"), + TRANS("re-assign"), + TRANS("cancel"))) + { + return; + } + } - mappings->removeKeyPress (entryWindow.lastPress); + mappings->removeKeyPress (entryWindow.lastPress); - if (index >= 0) - mappings->removeKeyPress (commandID, index); + if (index >= 0) + mappings->removeKeyPress (commandID, index); - mappings->addKeyPress (commandID, entryWindow.lastPress, index); - } - } + mappings->addKeyPress (commandID, entryWindow.lastPress, index); + } + } } bool KeyMappingEditorComponent::shouldCommandBeIncluded (const CommandID commandID) { - const ApplicationCommandInfo* const ci = mappings->getCommandManager()->getCommandForID (commandID); + const ApplicationCommandInfo* const ci = mappings->getCommandManager()->getCommandForID (commandID); - return (ci != 0) && ((ci->flags & ApplicationCommandInfo::hiddenFromKeyEditor) == 0); + return (ci != 0) && ((ci->flags & ApplicationCommandInfo::hiddenFromKeyEditor) == 0); } bool KeyMappingEditorComponent::isCommandReadOnly (const CommandID commandID) { - const ApplicationCommandInfo* const ci = mappings->getCommandManager()->getCommandForID (commandID); + const ApplicationCommandInfo* const ci = mappings->getCommandManager()->getCommandForID (commandID); - return (ci != 0) && ((ci->flags & ApplicationCommandInfo::readOnlyInKeyEditor) != 0); + return (ci != 0) && ((ci->flags & ApplicationCommandInfo::readOnlyInKeyEditor) != 0); } const String KeyMappingEditorComponent::getDescriptionForKeyPress (const KeyPress& key) { - return key.getTextDescription(); + return key.getTextDescription(); } END_JUCE_NAMESPACE @@ -60088,243 +59789,243 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE KeyPress::KeyPress() throw() - : keyCode (0), - mods (0), - textCharacter (0) + : keyCode (0), + mods (0), + textCharacter (0) { } KeyPress::KeyPress (const int keyCode_, - const ModifierKeys& mods_, - const juce_wchar textCharacter_) throw() - : keyCode (keyCode_), - mods (mods_), - textCharacter (textCharacter_) + const ModifierKeys& mods_, + const juce_wchar textCharacter_) throw() + : keyCode (keyCode_), + mods (mods_), + textCharacter (textCharacter_) { } KeyPress::KeyPress (const int keyCode_) throw() - : keyCode (keyCode_), - textCharacter (0) + : keyCode (keyCode_), + textCharacter (0) { } KeyPress::KeyPress (const KeyPress& other) throw() - : keyCode (other.keyCode), - mods (other.mods), - textCharacter (other.textCharacter) + : keyCode (other.keyCode), + mods (other.mods), + textCharacter (other.textCharacter) { } const KeyPress& KeyPress::operator= (const KeyPress& other) throw() { - keyCode = other.keyCode; - mods = other.mods; - textCharacter = other.textCharacter; + keyCode = other.keyCode; + mods = other.mods; + textCharacter = other.textCharacter; - return *this; + return *this; } bool KeyPress::operator== (const KeyPress& other) const throw() { - return mods.getRawFlags() == other.mods.getRawFlags() - && (textCharacter == other.textCharacter - || textCharacter == 0 - || other.textCharacter == 0) - && (keyCode == other.keyCode - || (keyCode < 256 - && other.keyCode < 256 - && CharacterFunctions::toLowerCase ((tchar) keyCode) - == CharacterFunctions::toLowerCase ((tchar) other.keyCode))); + return mods.getRawFlags() == other.mods.getRawFlags() + && (textCharacter == other.textCharacter + || textCharacter == 0 + || other.textCharacter == 0) + && (keyCode == other.keyCode + || (keyCode < 256 + && other.keyCode < 256 + && CharacterFunctions::toLowerCase ((tchar) keyCode) + == CharacterFunctions::toLowerCase ((tchar) other.keyCode))); } bool KeyPress::operator!= (const KeyPress& other) const throw() { - return ! operator== (other); + return ! operator== (other); } bool KeyPress::isCurrentlyDown() const throw() { - return isKeyCurrentlyDown (keyCode) - && (ModifierKeys::getCurrentModifiers().getRawFlags() & ModifierKeys::allKeyboardModifiers) - == (mods.getRawFlags() & ModifierKeys::allKeyboardModifiers); + return isKeyCurrentlyDown (keyCode) + && (ModifierKeys::getCurrentModifiers().getRawFlags() & ModifierKeys::allKeyboardModifiers) + == (mods.getRawFlags() & ModifierKeys::allKeyboardModifiers); } struct KeyNameAndCode { - const char* name; - int code; + const char* name; + int code; }; static const KeyNameAndCode keyNameTranslations[] = { - { "spacebar", KeyPress::spaceKey }, - { "return", KeyPress::returnKey }, - { "escape", KeyPress::escapeKey }, - { "backspace", KeyPress::backspaceKey }, - { "cursor left", KeyPress::leftKey }, - { "cursor right", KeyPress::rightKey }, - { "cursor up", KeyPress::upKey }, - { "cursor down", KeyPress::downKey }, - { "page up", KeyPress::pageUpKey }, - { "page down", KeyPress::pageDownKey }, - { "home", KeyPress::homeKey }, - { "end", KeyPress::endKey }, - { "delete", KeyPress::deleteKey }, - { "insert", KeyPress::insertKey }, - { "tab", KeyPress::tabKey }, - { "play", KeyPress::playKey }, - { "stop", KeyPress::stopKey }, - { "fast forward", KeyPress::fastForwardKey }, - { "rewind", KeyPress::rewindKey } + { "spacebar", KeyPress::spaceKey }, + { "return", KeyPress::returnKey }, + { "escape", KeyPress::escapeKey }, + { "backspace", KeyPress::backspaceKey }, + { "cursor left", KeyPress::leftKey }, + { "cursor right", KeyPress::rightKey }, + { "cursor up", KeyPress::upKey }, + { "cursor down", KeyPress::downKey }, + { "page up", KeyPress::pageUpKey }, + { "page down", KeyPress::pageDownKey }, + { "home", KeyPress::homeKey }, + { "end", KeyPress::endKey }, + { "delete", KeyPress::deleteKey }, + { "insert", KeyPress::insertKey }, + { "tab", KeyPress::tabKey }, + { "play", KeyPress::playKey }, + { "stop", KeyPress::stopKey }, + { "fast forward", KeyPress::fastForwardKey }, + { "rewind", KeyPress::rewindKey } }; static const tchar* const numberPadPrefix = T("numpad "); const KeyPress KeyPress::createFromDescription (const String& desc) throw() { - int modifiers = 0; + int modifiers = 0; - if (desc.containsWholeWordIgnoreCase (T("ctrl")) - || desc.containsWholeWordIgnoreCase (T("control")) - || desc.containsWholeWordIgnoreCase (T("ctl"))) - modifiers |= ModifierKeys::ctrlModifier; + if (desc.containsWholeWordIgnoreCase (T("ctrl")) + || desc.containsWholeWordIgnoreCase (T("control")) + || desc.containsWholeWordIgnoreCase (T("ctl"))) + modifiers |= ModifierKeys::ctrlModifier; - if (desc.containsWholeWordIgnoreCase (T("shift")) - || desc.containsWholeWordIgnoreCase (T("shft"))) - modifiers |= ModifierKeys::shiftModifier; + if (desc.containsWholeWordIgnoreCase (T("shift")) + || desc.containsWholeWordIgnoreCase (T("shft"))) + modifiers |= ModifierKeys::shiftModifier; - if (desc.containsWholeWordIgnoreCase (T("alt")) - || desc.containsWholeWordIgnoreCase (T("option"))) - modifiers |= ModifierKeys::altModifier; + if (desc.containsWholeWordIgnoreCase (T("alt")) + || desc.containsWholeWordIgnoreCase (T("option"))) + modifiers |= ModifierKeys::altModifier; - if (desc.containsWholeWordIgnoreCase (T("command")) - || desc.containsWholeWordIgnoreCase (T("cmd"))) - modifiers |= ModifierKeys::commandModifier; + if (desc.containsWholeWordIgnoreCase (T("command")) + || desc.containsWholeWordIgnoreCase (T("cmd"))) + modifiers |= ModifierKeys::commandModifier; - int key = 0; + int key = 0; - for (int i = 0; i < numElementsInArray (keyNameTranslations); ++i) - { - if (desc.containsWholeWordIgnoreCase (String (keyNameTranslations[i].name))) - { - key = keyNameTranslations[i].code; - break; - } - } + for (int i = 0; i < numElementsInArray (keyNameTranslations); ++i) + { + if (desc.containsWholeWordIgnoreCase (String (keyNameTranslations[i].name))) + { + key = keyNameTranslations[i].code; + break; + } + } - if (key == 0) - { - // see if it's a numpad key.. - if (desc.containsIgnoreCase (numberPadPrefix)) - { - const tchar lastChar = desc.trimEnd().getLastCharacter(); + if (key == 0) + { + // see if it's a numpad key.. + if (desc.containsIgnoreCase (numberPadPrefix)) + { + const tchar lastChar = desc.trimEnd().getLastCharacter(); - if (lastChar >= T('0') && lastChar <= T('9')) - key = numberPad0 + lastChar - T('0'); - else if (lastChar == T('+')) - key = numberPadAdd; - else if (lastChar == T('-')) - key = numberPadSubtract; - else if (lastChar == T('*')) - key = numberPadMultiply; - else if (lastChar == T('/')) - key = numberPadDivide; - else if (lastChar == T('.')) - key = numberPadDecimalPoint; - else if (lastChar == T('=')) - key = numberPadEquals; - else if (desc.endsWith (T("separator"))) - key = numberPadSeparator; - else if (desc.endsWith (T("delete"))) - key = numberPadDelete; - } + if (lastChar >= T('0') && lastChar <= T('9')) + key = numberPad0 + lastChar - T('0'); + else if (lastChar == T('+')) + key = numberPadAdd; + else if (lastChar == T('-')) + key = numberPadSubtract; + else if (lastChar == T('*')) + key = numberPadMultiply; + else if (lastChar == T('/')) + key = numberPadDivide; + else if (lastChar == T('.')) + key = numberPadDecimalPoint; + else if (lastChar == T('=')) + key = numberPadEquals; + else if (desc.endsWith (T("separator"))) + key = numberPadSeparator; + else if (desc.endsWith (T("delete"))) + key = numberPadDelete; + } - if (key == 0) - { - // see if it's a function key.. - for (int i = 1; i <= 12; ++i) - if (desc.containsWholeWordIgnoreCase (T("f") + String (i))) - key = F1Key + i - 1; + if (key == 0) + { + // see if it's a function key.. + for (int i = 1; i <= 12; ++i) + if (desc.containsWholeWordIgnoreCase (T("f") + String (i))) + key = F1Key + i - 1; - if (key == 0) - { - // give up and use the hex code.. - const int hexCode = desc.fromFirstOccurrenceOf (T("#"), false, false) - .toLowerCase() - .retainCharacters (T("0123456789abcdef")) - .getHexValue32(); + if (key == 0) + { + // give up and use the hex code.. + const int hexCode = desc.fromFirstOccurrenceOf (T("#"), false, false) + .toLowerCase() + .retainCharacters (T("0123456789abcdef")) + .getHexValue32(); - if (hexCode > 0) - key = hexCode; - else - key = CharacterFunctions::toUpperCase (desc.getLastCharacter()); - } - } - } + if (hexCode > 0) + key = hexCode; + else + key = CharacterFunctions::toUpperCase (desc.getLastCharacter()); + } + } + } - return KeyPress (key, ModifierKeys (modifiers), 0); + return KeyPress (key, ModifierKeys (modifiers), 0); } const String KeyPress::getTextDescription() const throw() { - String desc; + String desc; - if (keyCode > 0) - { - // some keyboard layouts use a shift-key to get the slash, but in those cases, we - // want to store it as being a slash, not shift+whatever. - if (textCharacter == T('/')) - return "/"; + if (keyCode > 0) + { + // some keyboard layouts use a shift-key to get the slash, but in those cases, we + // want to store it as being a slash, not shift+whatever. + if (textCharacter == T('/')) + return "/"; - if (mods.isCtrlDown()) - desc << "ctrl + "; + if (mods.isCtrlDown()) + desc << "ctrl + "; - if (mods.isShiftDown()) - desc << "shift + "; + if (mods.isShiftDown()) + desc << "shift + "; #if JUCE_MAC - // only do this on the mac, because on Windows ctrl and command are the same, - // and this would get confusing - if (mods.isCommandDown()) - desc << "command + "; + // only do this on the mac, because on Windows ctrl and command are the same, + // and this would get confusing + if (mods.isCommandDown()) + desc << "command + "; - if (mods.isAltDown()) - desc << "option + "; + if (mods.isAltDown()) + desc << "option + "; #else - if (mods.isAltDown()) - desc << "alt + "; + if (mods.isAltDown()) + desc << "alt + "; #endif - for (int i = 0; i < numElementsInArray (keyNameTranslations); ++i) - if (keyCode == keyNameTranslations[i].code) - return desc + keyNameTranslations[i].name; + for (int i = 0; i < numElementsInArray (keyNameTranslations); ++i) + if (keyCode == keyNameTranslations[i].code) + return desc + keyNameTranslations[i].name; - if (keyCode >= F1Key && keyCode <= F16Key) - desc << 'F' << (1 + keyCode - F1Key); - else if (keyCode >= numberPad0 && keyCode <= numberPad9) - desc << numberPadPrefix << (keyCode - numberPad0); - else if (keyCode >= 33 && keyCode < 176) - desc += CharacterFunctions::toUpperCase ((tchar) keyCode); - else if (keyCode == numberPadAdd) - desc << numberPadPrefix << '+'; - else if (keyCode == numberPadSubtract) - desc << numberPadPrefix << '-'; - else if (keyCode == numberPadMultiply) - desc << numberPadPrefix << '*'; - else if (keyCode == numberPadDivide) - desc << numberPadPrefix << '/'; - else if (keyCode == numberPadSeparator) - desc << numberPadPrefix << "separator"; - else if (keyCode == numberPadDecimalPoint) - desc << numberPadPrefix << '.'; - else if (keyCode == numberPadDelete) - desc << numberPadPrefix << "delete"; - else - desc << '#' << String::toHexString (keyCode); - } + if (keyCode >= F1Key && keyCode <= F16Key) + desc << 'F' << (1 + keyCode - F1Key); + else if (keyCode >= numberPad0 && keyCode <= numberPad9) + desc << numberPadPrefix << (keyCode - numberPad0); + else if (keyCode >= 33 && keyCode < 176) + desc += CharacterFunctions::toUpperCase ((tchar) keyCode); + else if (keyCode == numberPadAdd) + desc << numberPadPrefix << '+'; + else if (keyCode == numberPadSubtract) + desc << numberPadPrefix << '-'; + else if (keyCode == numberPadMultiply) + desc << numberPadPrefix << '*'; + else if (keyCode == numberPadDivide) + desc << numberPadPrefix << '/'; + else if (keyCode == numberPadSeparator) + desc << numberPadPrefix << "separator"; + else if (keyCode == numberPadDecimalPoint) + desc << numberPadPrefix << '.'; + else if (keyCode == numberPadDelete) + desc << numberPadPrefix << "delete"; + else + desc << '#' << String::toHexString (keyCode); + } - return desc; + return desc; } END_JUCE_NAMESPACE @@ -60335,398 +60036,398 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE KeyPressMappingSet::KeyPressMappingSet (ApplicationCommandManager* const commandManager_) throw() - : commandManager (commandManager_) + : commandManager (commandManager_) { - // A manager is needed to get the descriptions of commands, and will be called when - // a command is invoked. So you can't leave this null.. - jassert (commandManager_ != 0); + // A manager is needed to get the descriptions of commands, and will be called when + // a command is invoked. So you can't leave this null.. + jassert (commandManager_ != 0); - Desktop::getInstance().addFocusChangeListener (this); + Desktop::getInstance().addFocusChangeListener (this); } KeyPressMappingSet::KeyPressMappingSet (const KeyPressMappingSet& other) throw() - : commandManager (other.commandManager) + : commandManager (other.commandManager) { - Desktop::getInstance().addFocusChangeListener (this); + Desktop::getInstance().addFocusChangeListener (this); } KeyPressMappingSet::~KeyPressMappingSet() { - Desktop::getInstance().removeFocusChangeListener (this); + Desktop::getInstance().removeFocusChangeListener (this); } const Array KeyPressMappingSet::getKeyPressesAssignedToCommand (const CommandID commandID) const throw() { - for (int i = 0; i < mappings.size(); ++i) - if (mappings.getUnchecked(i)->commandID == commandID) - return mappings.getUnchecked (i)->keypresses; + for (int i = 0; i < mappings.size(); ++i) + if (mappings.getUnchecked(i)->commandID == commandID) + return mappings.getUnchecked (i)->keypresses; - return Array (); + return Array (); } void KeyPressMappingSet::addKeyPress (const CommandID commandID, - const KeyPress& newKeyPress, - int insertIndex) throw() + const KeyPress& newKeyPress, + int insertIndex) throw() { - // If you specify an upper-case letter but no shift key, how is the user supposed to press it!? - // Stick to lower-case letters when defining a keypress, to avoid ambiguity. - jassert (! (CharacterFunctions::isUpperCase (newKeyPress.getTextCharacter()) - && ! newKeyPress.getModifiers().isShiftDown())); + // If you specify an upper-case letter but no shift key, how is the user supposed to press it!? + // Stick to lower-case letters when defining a keypress, to avoid ambiguity. + jassert (! (CharacterFunctions::isUpperCase (newKeyPress.getTextCharacter()) + && ! newKeyPress.getModifiers().isShiftDown())); - if (findCommandForKeyPress (newKeyPress) != commandID) - { - removeKeyPress (newKeyPress); + if (findCommandForKeyPress (newKeyPress) != commandID) + { + removeKeyPress (newKeyPress); - if (newKeyPress.isValid()) - { - for (int i = mappings.size(); --i >= 0;) - { - if (mappings.getUnchecked(i)->commandID == commandID) - { - mappings.getUnchecked(i)->keypresses.insert (insertIndex, newKeyPress); + if (newKeyPress.isValid()) + { + for (int i = mappings.size(); --i >= 0;) + { + if (mappings.getUnchecked(i)->commandID == commandID) + { + mappings.getUnchecked(i)->keypresses.insert (insertIndex, newKeyPress); - sendChangeMessage (this); - return; - } - } + sendChangeMessage (this); + return; + } + } - const ApplicationCommandInfo* const ci = commandManager->getCommandForID (commandID); + const ApplicationCommandInfo* const ci = commandManager->getCommandForID (commandID); - if (ci != 0) - { - CommandMapping* const cm = new CommandMapping(); - cm->commandID = commandID; - cm->keypresses.add (newKeyPress); - cm->wantsKeyUpDownCallbacks = (ci->flags & ApplicationCommandInfo::wantsKeyUpDownCallbacks) != 0; + if (ci != 0) + { + CommandMapping* const cm = new CommandMapping(); + cm->commandID = commandID; + cm->keypresses.add (newKeyPress); + cm->wantsKeyUpDownCallbacks = (ci->flags & ApplicationCommandInfo::wantsKeyUpDownCallbacks) != 0; - mappings.add (cm); - sendChangeMessage (this); - } - } - } + mappings.add (cm); + sendChangeMessage (this); + } + } + } } void KeyPressMappingSet::resetToDefaultMappings() throw() { - mappings.clear(); + mappings.clear(); - for (int i = 0; i < commandManager->getNumCommands(); ++i) - { - const ApplicationCommandInfo* const ci = commandManager->getCommandForIndex (i); + for (int i = 0; i < commandManager->getNumCommands(); ++i) + { + const ApplicationCommandInfo* const ci = commandManager->getCommandForIndex (i); - for (int j = 0; j < ci->defaultKeypresses.size(); ++j) - { - addKeyPress (ci->commandID, - ci->defaultKeypresses.getReference (j)); - } - } + for (int j = 0; j < ci->defaultKeypresses.size(); ++j) + { + addKeyPress (ci->commandID, + ci->defaultKeypresses.getReference (j)); + } + } - sendChangeMessage (this); + sendChangeMessage (this); } void KeyPressMappingSet::resetToDefaultMapping (const CommandID commandID) throw() { - clearAllKeyPresses (commandID); + clearAllKeyPresses (commandID); - const ApplicationCommandInfo* const ci = commandManager->getCommandForID (commandID); + const ApplicationCommandInfo* const ci = commandManager->getCommandForID (commandID); - for (int j = 0; j < ci->defaultKeypresses.size(); ++j) - { - addKeyPress (ci->commandID, - ci->defaultKeypresses.getReference (j)); - } + for (int j = 0; j < ci->defaultKeypresses.size(); ++j) + { + addKeyPress (ci->commandID, + ci->defaultKeypresses.getReference (j)); + } } void KeyPressMappingSet::clearAllKeyPresses() throw() { - if (mappings.size() > 0) - { - sendChangeMessage (this); - mappings.clear(); - } + if (mappings.size() > 0) + { + sendChangeMessage (this); + mappings.clear(); + } } void KeyPressMappingSet::clearAllKeyPresses (const CommandID commandID) throw() { - for (int i = mappings.size(); --i >= 0;) - { - if (mappings.getUnchecked(i)->commandID == commandID) - { - mappings.remove (i); - sendChangeMessage (this); - } - } + for (int i = mappings.size(); --i >= 0;) + { + if (mappings.getUnchecked(i)->commandID == commandID) + { + mappings.remove (i); + sendChangeMessage (this); + } + } } void KeyPressMappingSet::removeKeyPress (const KeyPress& keypress) throw() { - if (keypress.isValid()) - { - for (int i = mappings.size(); --i >= 0;) - { - CommandMapping* const cm = mappings.getUnchecked(i); + if (keypress.isValid()) + { + for (int i = mappings.size(); --i >= 0;) + { + CommandMapping* const cm = mappings.getUnchecked(i); - for (int j = cm->keypresses.size(); --j >= 0;) - { - if (keypress == cm->keypresses [j]) - { - cm->keypresses.remove (j); - sendChangeMessage (this); - } - } - } - } + for (int j = cm->keypresses.size(); --j >= 0;) + { + if (keypress == cm->keypresses [j]) + { + cm->keypresses.remove (j); + sendChangeMessage (this); + } + } + } + } } void KeyPressMappingSet::removeKeyPress (const CommandID commandID, - const int keyPressIndex) throw() + const int keyPressIndex) throw() { - for (int i = mappings.size(); --i >= 0;) - { - if (mappings.getUnchecked(i)->commandID == commandID) - { - mappings.getUnchecked(i)->keypresses.remove (keyPressIndex); - sendChangeMessage (this); - break; - } - } + for (int i = mappings.size(); --i >= 0;) + { + if (mappings.getUnchecked(i)->commandID == commandID) + { + mappings.getUnchecked(i)->keypresses.remove (keyPressIndex); + sendChangeMessage (this); + break; + } + } } CommandID KeyPressMappingSet::findCommandForKeyPress (const KeyPress& keyPress) const throw() { - for (int i = 0; i < mappings.size(); ++i) - if (mappings.getUnchecked(i)->keypresses.contains (keyPress)) - return mappings.getUnchecked(i)->commandID; + for (int i = 0; i < mappings.size(); ++i) + if (mappings.getUnchecked(i)->keypresses.contains (keyPress)) + return mappings.getUnchecked(i)->commandID; - return 0; + return 0; } bool KeyPressMappingSet::containsMapping (const CommandID commandID, - const KeyPress& keyPress) const throw() + const KeyPress& keyPress) const throw() { - for (int i = mappings.size(); --i >= 0;) - if (mappings.getUnchecked(i)->commandID == commandID) - return mappings.getUnchecked(i)->keypresses.contains (keyPress); + for (int i = mappings.size(); --i >= 0;) + if (mappings.getUnchecked(i)->commandID == commandID) + return mappings.getUnchecked(i)->keypresses.contains (keyPress); - return false; + return false; } void KeyPressMappingSet::invokeCommand (const CommandID commandID, - const KeyPress& key, - const bool isKeyDown, - const int millisecsSinceKeyPressed, - Component* const originatingComponent) const + const KeyPress& key, + const bool isKeyDown, + const int millisecsSinceKeyPressed, + Component* const originatingComponent) const { - ApplicationCommandTarget::InvocationInfo info (commandID); + ApplicationCommandTarget::InvocationInfo info (commandID); - info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromKeyPress; - info.isKeyDown = isKeyDown; - info.keyPress = key; - info.millisecsSinceKeyPressed = millisecsSinceKeyPressed; - info.originatingComponent = originatingComponent; + info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromKeyPress; + info.isKeyDown = isKeyDown; + info.keyPress = key; + info.millisecsSinceKeyPressed = millisecsSinceKeyPressed; + info.originatingComponent = originatingComponent; - commandManager->invoke (info, false); + commandManager->invoke (info, false); } bool KeyPressMappingSet::restoreFromXml (const XmlElement& xmlVersion) { - if (xmlVersion.hasTagName (T("KEYMAPPINGS"))) - { - if (xmlVersion.getBoolAttribute (T("basedOnDefaults"), true)) - { - // if the XML was created as a set of differences from the default mappings, - // (i.e. by calling createXml (true)), then we need to first restore the defaults. - resetToDefaultMappings(); - } - else - { - // if the XML was created calling createXml (false), then we need to clear all - // the keys and treat the xml as describing the entire set of mappings. - clearAllKeyPresses(); - } + if (xmlVersion.hasTagName (T("KEYMAPPINGS"))) + { + if (xmlVersion.getBoolAttribute (T("basedOnDefaults"), true)) + { + // if the XML was created as a set of differences from the default mappings, + // (i.e. by calling createXml (true)), then we need to first restore the defaults. + resetToDefaultMappings(); + } + else + { + // if the XML was created calling createXml (false), then we need to clear all + // the keys and treat the xml as describing the entire set of mappings. + clearAllKeyPresses(); + } - forEachXmlChildElement (xmlVersion, map) - { - const CommandID commandId = map->getStringAttribute (T("commandId")).getHexValue32(); + forEachXmlChildElement (xmlVersion, map) + { + const CommandID commandId = map->getStringAttribute (T("commandId")).getHexValue32(); - if (commandId != 0) - { - const KeyPress key (KeyPress::createFromDescription (map->getStringAttribute (T("key")))); + if (commandId != 0) + { + const KeyPress key (KeyPress::createFromDescription (map->getStringAttribute (T("key")))); - if (map->hasTagName (T("MAPPING"))) - { - addKeyPress (commandId, key); - } - else if (map->hasTagName (T("UNMAPPING"))) - { - if (containsMapping (commandId, key)) - removeKeyPress (key); - } - } - } + if (map->hasTagName (T("MAPPING"))) + { + addKeyPress (commandId, key); + } + else if (map->hasTagName (T("UNMAPPING"))) + { + if (containsMapping (commandId, key)) + removeKeyPress (key); + } + } + } - return true; - } + return true; + } - return false; + return false; } XmlElement* KeyPressMappingSet::createXml (const bool saveDifferencesFromDefaultSet) const { - ScopedPointer defaultSet; + ScopedPointer defaultSet; - if (saveDifferencesFromDefaultSet) - { - defaultSet = new KeyPressMappingSet (commandManager); - defaultSet->resetToDefaultMappings(); - } + if (saveDifferencesFromDefaultSet) + { + defaultSet = new KeyPressMappingSet (commandManager); + defaultSet->resetToDefaultMappings(); + } - XmlElement* const doc = new XmlElement (T("KEYMAPPINGS")); + XmlElement* const doc = new XmlElement (T("KEYMAPPINGS")); - doc->setAttribute (T("basedOnDefaults"), saveDifferencesFromDefaultSet); + doc->setAttribute (T("basedOnDefaults"), saveDifferencesFromDefaultSet); - int i; - for (i = 0; i < mappings.size(); ++i) - { - const CommandMapping* const cm = mappings.getUnchecked(i); + int i; + for (i = 0; i < mappings.size(); ++i) + { + const CommandMapping* const cm = mappings.getUnchecked(i); - for (int j = 0; j < cm->keypresses.size(); ++j) - { - if (defaultSet == 0 - || ! defaultSet->containsMapping (cm->commandID, cm->keypresses.getReference (j))) - { - XmlElement* const map = new XmlElement (T("MAPPING")); + for (int j = 0; j < cm->keypresses.size(); ++j) + { + if (defaultSet == 0 + || ! defaultSet->containsMapping (cm->commandID, cm->keypresses.getReference (j))) + { + XmlElement* const map = new XmlElement (T("MAPPING")); - map->setAttribute (T("commandId"), String::toHexString ((int) cm->commandID)); - map->setAttribute (T("description"), commandManager->getDescriptionOfCommand (cm->commandID)); - map->setAttribute (T("key"), cm->keypresses.getReference (j).getTextDescription()); + map->setAttribute (T("commandId"), String::toHexString ((int) cm->commandID)); + map->setAttribute (T("description"), commandManager->getDescriptionOfCommand (cm->commandID)); + map->setAttribute (T("key"), cm->keypresses.getReference (j).getTextDescription()); - doc->addChildElement (map); - } - } - } + doc->addChildElement (map); + } + } + } - if (defaultSet != 0) - { - for (i = 0; i < defaultSet->mappings.size(); ++i) - { - const CommandMapping* const cm = defaultSet->mappings.getUnchecked(i); + if (defaultSet != 0) + { + for (i = 0; i < defaultSet->mappings.size(); ++i) + { + const CommandMapping* const cm = defaultSet->mappings.getUnchecked(i); - for (int j = 0; j < cm->keypresses.size(); ++j) - { - if (! containsMapping (cm->commandID, cm->keypresses.getReference (j))) - { - XmlElement* const map = new XmlElement (T("UNMAPPING")); + for (int j = 0; j < cm->keypresses.size(); ++j) + { + if (! containsMapping (cm->commandID, cm->keypresses.getReference (j))) + { + XmlElement* const map = new XmlElement (T("UNMAPPING")); - map->setAttribute (T("commandId"), String::toHexString ((int) cm->commandID)); - map->setAttribute (T("description"), commandManager->getDescriptionOfCommand (cm->commandID)); - map->setAttribute (T("key"), cm->keypresses.getReference (j).getTextDescription()); + map->setAttribute (T("commandId"), String::toHexString ((int) cm->commandID)); + map->setAttribute (T("description"), commandManager->getDescriptionOfCommand (cm->commandID)); + map->setAttribute (T("key"), cm->keypresses.getReference (j).getTextDescription()); - doc->addChildElement (map); - } - } - } - } + doc->addChildElement (map); + } + } + } + } - return doc; + return doc; } bool KeyPressMappingSet::keyPressed (const KeyPress& key, - Component* originatingComponent) + Component* originatingComponent) { - bool used = false; + bool used = false; - const CommandID commandID = findCommandForKeyPress (key); + const CommandID commandID = findCommandForKeyPress (key); - const ApplicationCommandInfo* const ci = commandManager->getCommandForID (commandID); + const ApplicationCommandInfo* const ci = commandManager->getCommandForID (commandID); - if (ci != 0 - && (ci->flags & ApplicationCommandInfo::wantsKeyUpDownCallbacks) == 0) - { - ApplicationCommandInfo info (0); + if (ci != 0 + && (ci->flags & ApplicationCommandInfo::wantsKeyUpDownCallbacks) == 0) + { + ApplicationCommandInfo info (0); - if (commandManager->getTargetForCommand (commandID, info) != 0 - && (info.flags & ApplicationCommandInfo::isDisabled) == 0) - { - invokeCommand (commandID, key, true, 0, originatingComponent); - used = true; - } - else - { - if (originatingComponent != 0) - originatingComponent->getLookAndFeel().playAlertSound(); - } - } + if (commandManager->getTargetForCommand (commandID, info) != 0 + && (info.flags & ApplicationCommandInfo::isDisabled) == 0) + { + invokeCommand (commandID, key, true, 0, originatingComponent); + used = true; + } + else + { + if (originatingComponent != 0) + originatingComponent->getLookAndFeel().playAlertSound(); + } + } - return used; + return used; } bool KeyPressMappingSet::keyStateChanged (const bool /*isKeyDown*/, Component* originatingComponent) { - bool used = false; - const uint32 now = Time::getMillisecondCounter(); + bool used = false; + const uint32 now = Time::getMillisecondCounter(); - for (int i = mappings.size(); --i >= 0;) - { - CommandMapping* const cm = mappings.getUnchecked(i); + for (int i = mappings.size(); --i >= 0;) + { + CommandMapping* const cm = mappings.getUnchecked(i); - if (cm->wantsKeyUpDownCallbacks) - { - for (int j = cm->keypresses.size(); --j >= 0;) - { - const KeyPress key (cm->keypresses.getReference (j)); - const bool isDown = key.isCurrentlyDown(); + if (cm->wantsKeyUpDownCallbacks) + { + for (int j = cm->keypresses.size(); --j >= 0;) + { + const KeyPress key (cm->keypresses.getReference (j)); + const bool isDown = key.isCurrentlyDown(); - int keyPressEntryIndex = 0; - bool wasDown = false; + int keyPressEntryIndex = 0; + bool wasDown = false; - for (int k = keysDown.size(); --k >= 0;) - { - if (key == keysDown.getUnchecked(k)->key) - { - keyPressEntryIndex = k; - wasDown = true; - used = true; - break; - } - } + for (int k = keysDown.size(); --k >= 0;) + { + if (key == keysDown.getUnchecked(k)->key) + { + keyPressEntryIndex = k; + wasDown = true; + used = true; + break; + } + } - if (isDown != wasDown) - { - int millisecs = 0; + if (isDown != wasDown) + { + int millisecs = 0; - if (isDown) - { - KeyPressTime* const k = new KeyPressTime(); - k->key = key; - k->timeWhenPressed = now; + if (isDown) + { + KeyPressTime* const k = new KeyPressTime(); + k->key = key; + k->timeWhenPressed = now; - keysDown.add (k); - } - else - { - const uint32 pressTime = keysDown.getUnchecked (keyPressEntryIndex)->timeWhenPressed; + keysDown.add (k); + } + else + { + const uint32 pressTime = keysDown.getUnchecked (keyPressEntryIndex)->timeWhenPressed; - if (now > pressTime) - millisecs = now - pressTime; + if (now > pressTime) + millisecs = now - pressTime; - keysDown.remove (keyPressEntryIndex); - } + keysDown.remove (keyPressEntryIndex); + } - invokeCommand (cm->commandID, key, isDown, millisecs, originatingComponent); - used = true; - } - } - } - } + invokeCommand (cm->commandID, key, isDown, millisecs, originatingComponent); + used = true; + } + } + } + } - return used; + return used; } void KeyPressMappingSet::globalFocusChanged (Component* focusedComponent) { - if (focusedComponent != 0) - focusedComponent->keyStateChanged (false); + if (focusedComponent != 0) + focusedComponent->keyStateChanged (false); } END_JUCE_NAMESPACE @@ -60737,26 +60438,26 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ModifierKeys::ModifierKeys (const int flags_) throw() - : flags (flags_) + : flags (flags_) { } ModifierKeys::ModifierKeys (const ModifierKeys& other) throw() - : flags (other.flags) + : flags (other.flags) { } const ModifierKeys& ModifierKeys::operator= (const ModifierKeys& other) throw() { - flags = other.flags; - return *this; + flags = other.flags; + return *this; } int ModifierKeys::currentModifierFlags = 0; const ModifierKeys ModifierKeys::getCurrentModifiers() throw() { - return ModifierKeys (currentModifierFlags); + return ModifierKeys (currentModifierFlags); } END_JUCE_NAMESPACE @@ -60768,209 +60469,209 @@ BEGIN_JUCE_NAMESPACE struct AnimationTask { - AnimationTask (Component* const comp) - : component (comp), - watcher (comp) - { - } + AnimationTask (Component* const comp) + : component (comp), + watcher (comp) + { + } - Component* component; - ComponentDeletionWatcher watcher; - Rectangle destination; - int msElapsed, msTotal; - double startSpeed, midSpeed, endSpeed, lastProgress; - double left, top, right, bottom; + Component* component; + ComponentDeletionWatcher watcher; + Rectangle destination; + int msElapsed, msTotal; + double startSpeed, midSpeed, endSpeed, lastProgress; + double left, top, right, bottom; - bool useTimeslice (const int elapsed) - { - if (watcher.hasBeenDeleted()) - return false; + bool useTimeslice (const int elapsed) + { + if (watcher.hasBeenDeleted()) + return false; - msElapsed += elapsed; - double newProgress = msElapsed / (double) msTotal; + msElapsed += elapsed; + double newProgress = msElapsed / (double) msTotal; - if (newProgress >= 0 && newProgress < 1.0) - { - newProgress = timeToDistance (newProgress); - const double delta = (newProgress - lastProgress) / (1.0 - lastProgress); - jassert (newProgress >= lastProgress); - lastProgress = newProgress; + if (newProgress >= 0 && newProgress < 1.0) + { + newProgress = timeToDistance (newProgress); + const double delta = (newProgress - lastProgress) / (1.0 - lastProgress); + jassert (newProgress >= lastProgress); + lastProgress = newProgress; - left += (destination.getX() - left) * delta; - top += (destination.getY() - top) * delta; - right += (destination.getRight() - right) * delta; - bottom += (destination.getBottom() - bottom) * delta; + left += (destination.getX() - left) * delta; + top += (destination.getY() - top) * delta; + right += (destination.getRight() - right) * delta; + bottom += (destination.getBottom() - bottom) * delta; - if (delta < 1.0) - { - const Rectangle newBounds (roundDoubleToInt (left), - roundDoubleToInt (top), - roundDoubleToInt (right - left), - roundDoubleToInt (bottom - top)); + if (delta < 1.0) + { + const Rectangle newBounds (roundToInt (left), + roundToInt (top), + roundToInt (right - left), + roundToInt (bottom - top)); - if (newBounds != destination) - { - component->setBounds (newBounds); - return true; - } - } - } + if (newBounds != destination) + { + component->setBounds (newBounds); + return true; + } + } + } - component->setBounds (destination); - return false; - } + component->setBounds (destination); + return false; + } - void moveToFinalDestination() - { - if (! watcher.hasBeenDeleted()) - component->setBounds (destination); - } + void moveToFinalDestination() + { + if (! watcher.hasBeenDeleted()) + component->setBounds (destination); + } private: - inline double timeToDistance (const double time) const - { - return (time < 0.5) ? time * (startSpeed + time * (midSpeed - startSpeed)) - : 0.5 * (startSpeed + 0.5 * (midSpeed - startSpeed)) - + (time - 0.5) * (midSpeed + (time - 0.5) * (endSpeed - midSpeed)); - } + inline double timeToDistance (const double time) const + { + return (time < 0.5) ? time * (startSpeed + time * (midSpeed - startSpeed)) + : 0.5 * (startSpeed + 0.5 * (midSpeed - startSpeed)) + + (time - 0.5) * (midSpeed + (time - 0.5) * (endSpeed - midSpeed)); + } }; ComponentAnimator::ComponentAnimator() - : lastTime (0) + : lastTime (0) { } ComponentAnimator::~ComponentAnimator() { - cancelAllAnimations (false); - jassert (tasks.size() == 0); + cancelAllAnimations (false); + jassert (tasks.size() == 0); } void* ComponentAnimator::findTaskFor (Component* const component) const { - for (int i = tasks.size(); --i >= 0;) - if (component == ((AnimationTask*) tasks.getUnchecked(i))->component) - return tasks.getUnchecked(i); + for (int i = tasks.size(); --i >= 0;) + if (component == ((AnimationTask*) tasks.getUnchecked(i))->component) + return tasks.getUnchecked(i); - return 0; + return 0; } void ComponentAnimator::animateComponent (Component* const component, - const Rectangle& finalPosition, - const int millisecondsToSpendMoving, - const double startSpeed, - const double endSpeed) + const Rectangle& finalPosition, + const int millisecondsToSpendMoving, + const double startSpeed, + const double endSpeed) { - if (component != 0) - { - AnimationTask* at = (AnimationTask*) findTaskFor (component); + if (component != 0) + { + AnimationTask* at = (AnimationTask*) findTaskFor (component); - if (at == 0) - { - at = new AnimationTask (component); - tasks.add (at); - sendChangeMessage (this); - } + if (at == 0) + { + at = new AnimationTask (component); + tasks.add (at); + sendChangeMessage (this); + } - at->msElapsed = 0; - at->lastProgress = 0; - at->msTotal = jmax (1, millisecondsToSpendMoving); - at->destination = finalPosition; + at->msElapsed = 0; + at->lastProgress = 0; + at->msTotal = jmax (1, millisecondsToSpendMoving); + at->destination = finalPosition; - // the speeds must be 0 or greater! - jassert (startSpeed >= 0 && endSpeed >= 0) + // the speeds must be 0 or greater! + jassert (startSpeed >= 0 && endSpeed >= 0) - const double invTotalDistance = 4.0 / (startSpeed + endSpeed + 2.0); - at->startSpeed = jmax (0.0, startSpeed * invTotalDistance); - at->midSpeed = invTotalDistance; - at->endSpeed = jmax (0.0, endSpeed * invTotalDistance); + const double invTotalDistance = 4.0 / (startSpeed + endSpeed + 2.0); + at->startSpeed = jmax (0.0, startSpeed * invTotalDistance); + at->midSpeed = invTotalDistance; + at->endSpeed = jmax (0.0, endSpeed * invTotalDistance); - at->left = component->getX(); - at->top = component->getY(); - at->right = component->getRight(); - at->bottom = component->getBottom(); + at->left = component->getX(); + at->top = component->getY(); + at->right = component->getRight(); + at->bottom = component->getBottom(); - if (! isTimerRunning()) - { - lastTime = Time::getMillisecondCounter(); - startTimer (1000 / 50); - } - } + if (! isTimerRunning()) + { + lastTime = Time::getMillisecondCounter(); + startTimer (1000 / 50); + } + } } void ComponentAnimator::cancelAllAnimations (const bool moveComponentsToTheirFinalPositions) { - for (int i = tasks.size(); --i >= 0;) - { - AnimationTask* const at = (AnimationTask*) tasks.getUnchecked(i); + for (int i = tasks.size(); --i >= 0;) + { + AnimationTask* const at = (AnimationTask*) tasks.getUnchecked(i); - if (moveComponentsToTheirFinalPositions) - at->moveToFinalDestination(); + if (moveComponentsToTheirFinalPositions) + at->moveToFinalDestination(); - delete at; - tasks.remove (i); - sendChangeMessage (this); - } + delete at; + tasks.remove (i); + sendChangeMessage (this); + } } void ComponentAnimator::cancelAnimation (Component* const component, - const bool moveComponentToItsFinalPosition) + const bool moveComponentToItsFinalPosition) { - AnimationTask* const at = (AnimationTask*) findTaskFor (component); + AnimationTask* const at = (AnimationTask*) findTaskFor (component); - if (at != 0) - { - if (moveComponentToItsFinalPosition) - at->moveToFinalDestination(); + if (at != 0) + { + if (moveComponentToItsFinalPosition) + at->moveToFinalDestination(); - tasks.removeValue (at); - delete at; - sendChangeMessage (this); - } + tasks.removeValue (at); + delete at; + sendChangeMessage (this); + } } const Rectangle ComponentAnimator::getComponentDestination (Component* const component) { - AnimationTask* const at = (AnimationTask*) findTaskFor (component); + AnimationTask* const at = (AnimationTask*) findTaskFor (component); - if (at != 0) - return at->destination; - else if (component != 0) - return component->getBounds(); + if (at != 0) + return at->destination; + else if (component != 0) + return component->getBounds(); - return Rectangle(); + return Rectangle(); } bool ComponentAnimator::isAnimating (Component* component) const { - return findTaskFor (component) != 0; + return findTaskFor (component) != 0; } void ComponentAnimator::timerCallback() { - const uint32 timeNow = Time::getMillisecondCounter(); + const uint32 timeNow = Time::getMillisecondCounter(); - if (lastTime == 0 || lastTime == timeNow) - lastTime = timeNow; + if (lastTime == 0 || lastTime == timeNow) + lastTime = timeNow; - const int elapsed = timeNow - lastTime; + const int elapsed = timeNow - lastTime; - for (int i = tasks.size(); --i >= 0;) - { - AnimationTask* const at = (AnimationTask*) tasks.getUnchecked(i); + for (int i = tasks.size(); --i >= 0;) + { + AnimationTask* const at = (AnimationTask*) tasks.getUnchecked(i); - if (! at->useTimeslice (elapsed)) - { - tasks.remove (i); - delete at; - sendChangeMessage (this); - } - } + if (! at->useTimeslice (elapsed)) + { + tasks.remove (i); + delete at; + sendChangeMessage (this); + } + } - lastTime = timeNow; + lastTime = timeNow; - if (tasks.size() == 0) - stopTimer(); + if (tasks.size() == 0) + stopTimer(); } END_JUCE_NAMESPACE @@ -60981,15 +60682,15 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ComponentBoundsConstrainer::ComponentBoundsConstrainer() throw() - : minW (0), - maxW (0x3fffffff), - minH (0), - maxH (0x3fffffff), - minOffTop (0), - minOffLeft (0), - minOffBottom (0), - minOffRight (0), - aspectRatio (0.0) + : minW (0), + maxW (0x3fffffff), + minH (0), + maxH (0x3fffffff), + minOffTop (0), + minOffLeft (0), + minOffBottom (0), + minOffRight (0), + aspectRatio (0.0) { } @@ -60999,147 +60700,147 @@ ComponentBoundsConstrainer::~ComponentBoundsConstrainer() void ComponentBoundsConstrainer::setMinimumWidth (const int minimumWidth) throw() { - minW = minimumWidth; + minW = minimumWidth; } void ComponentBoundsConstrainer::setMaximumWidth (const int maximumWidth) throw() { - maxW = maximumWidth; + maxW = maximumWidth; } void ComponentBoundsConstrainer::setMinimumHeight (const int minimumHeight) throw() { - minH = minimumHeight; + minH = minimumHeight; } void ComponentBoundsConstrainer::setMaximumHeight (const int maximumHeight) throw() { - maxH = maximumHeight; + maxH = maximumHeight; } void ComponentBoundsConstrainer::setMinimumSize (const int minimumWidth, const int minimumHeight) throw() { - jassert (maxW >= minimumWidth); - jassert (maxH >= minimumHeight); - jassert (minimumWidth > 0 && minimumHeight > 0); + jassert (maxW >= minimumWidth); + jassert (maxH >= minimumHeight); + jassert (minimumWidth > 0 && minimumHeight > 0); - minW = minimumWidth; - minH = minimumHeight; + minW = minimumWidth; + minH = minimumHeight; - if (minW > maxW) - maxW = minW; + if (minW > maxW) + maxW = minW; - if (minH > maxH) - maxH = minH; + if (minH > maxH) + maxH = minH; } void ComponentBoundsConstrainer::setMaximumSize (const int maximumWidth, const int maximumHeight) throw() { - jassert (maximumWidth >= minW); - jassert (maximumHeight >= minH); - jassert (maximumWidth > 0 && maximumHeight > 0); + jassert (maximumWidth >= minW); + jassert (maximumHeight >= minH); + jassert (maximumWidth > 0 && maximumHeight > 0); - maxW = jmax (minW, maximumWidth); - maxH = jmax (minH, maximumHeight); + maxW = jmax (minW, maximumWidth); + maxH = jmax (minH, maximumHeight); } void ComponentBoundsConstrainer::setSizeLimits (const int minimumWidth, - const int minimumHeight, - const int maximumWidth, - const int maximumHeight) throw() + const int minimumHeight, + const int maximumWidth, + const int maximumHeight) throw() { - jassert (maximumWidth >= minimumWidth); - jassert (maximumHeight >= minimumHeight); - jassert (maximumWidth > 0 && maximumHeight > 0); - jassert (minimumWidth > 0 && minimumHeight > 0); + jassert (maximumWidth >= minimumWidth); + jassert (maximumHeight >= minimumHeight); + jassert (maximumWidth > 0 && maximumHeight > 0); + jassert (minimumWidth > 0 && minimumHeight > 0); - minW = jmax (0, minimumWidth); - minH = jmax (0, minimumHeight); - maxW = jmax (minW, maximumWidth); - maxH = jmax (minH, maximumHeight); + minW = jmax (0, minimumWidth); + minH = jmax (0, minimumHeight); + maxW = jmax (minW, maximumWidth); + maxH = jmax (minH, maximumHeight); } void ComponentBoundsConstrainer::setMinimumOnscreenAmounts (const int minimumWhenOffTheTop, - const int minimumWhenOffTheLeft, - const int minimumWhenOffTheBottom, - const int minimumWhenOffTheRight) throw() + const int minimumWhenOffTheLeft, + const int minimumWhenOffTheBottom, + const int minimumWhenOffTheRight) throw() { - minOffTop = minimumWhenOffTheTop; - minOffLeft = minimumWhenOffTheLeft; - minOffBottom = minimumWhenOffTheBottom; - minOffRight = minimumWhenOffTheRight; + minOffTop = minimumWhenOffTheTop; + minOffLeft = minimumWhenOffTheLeft; + minOffBottom = minimumWhenOffTheBottom; + minOffRight = minimumWhenOffTheRight; } void ComponentBoundsConstrainer::setFixedAspectRatio (const double widthOverHeight) throw() { - aspectRatio = jmax (0.0, widthOverHeight); + aspectRatio = jmax (0.0, widthOverHeight); } double ComponentBoundsConstrainer::getFixedAspectRatio() const throw() { - return aspectRatio; + return aspectRatio; } void ComponentBoundsConstrainer::setBoundsForComponent (Component* const component, - int x, int y, int w, int h, - const bool isStretchingTop, - const bool isStretchingLeft, - const bool isStretchingBottom, - const bool isStretchingRight) + int x, int y, int w, int h, + const bool isStretchingTop, + const bool isStretchingLeft, + const bool isStretchingBottom, + const bool isStretchingRight) { - jassert (component != 0); + jassert (component != 0); - Rectangle limits; - Component* const p = component->getParentComponent(); + Rectangle limits; + Component* const p = component->getParentComponent(); - if (p == 0) - limits = Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(); - else - limits.setSize (p->getWidth(), p->getHeight()); + if (p == 0) + limits = Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(); + else + limits.setSize (p->getWidth(), p->getHeight()); - if (component->isOnDesktop()) - { - ComponentPeer* const peer = component->getPeer(); - const BorderSize border (peer->getFrameSize()); + if (component->isOnDesktop()) + { + ComponentPeer* const peer = component->getPeer(); + const BorderSize border (peer->getFrameSize()); - x -= border.getLeft(); - y -= border.getTop(); - w += border.getLeftAndRight(); - h += border.getTopAndBottom(); + x -= border.getLeft(); + y -= border.getTop(); + w += border.getLeftAndRight(); + h += border.getTopAndBottom(); - checkBounds (x, y, w, h, - border.addedTo (component->getBounds()), limits, - isStretchingTop, isStretchingLeft, - isStretchingBottom, isStretchingRight); + checkBounds (x, y, w, h, + border.addedTo (component->getBounds()), limits, + isStretchingTop, isStretchingLeft, + isStretchingBottom, isStretchingRight); - x += border.getLeft(); - y += border.getTop(); - w -= border.getLeftAndRight(); - h -= border.getTopAndBottom(); - } - else - { - checkBounds (x, y, w, h, - component->getBounds(), limits, - isStretchingTop, isStretchingLeft, - isStretchingBottom, isStretchingRight); - } + x += border.getLeft(); + y += border.getTop(); + w -= border.getLeftAndRight(); + h -= border.getTopAndBottom(); + } + else + { + checkBounds (x, y, w, h, + component->getBounds(), limits, + isStretchingTop, isStretchingLeft, + isStretchingBottom, isStretchingRight); + } - applyBoundsToComponent (component, x, y, w, h); + applyBoundsToComponent (component, x, y, w, h); } void ComponentBoundsConstrainer::checkComponentBounds (Component* component) { - setBoundsForComponent (component, - component->getX(), component->getY(), - component->getWidth(), component->getHeight(), - false, false, false, false); + setBoundsForComponent (component, + component->getX(), component->getY(), + component->getWidth(), component->getHeight(), + false, false, false, false); } void ComponentBoundsConstrainer::applyBoundsToComponent (Component* component, - int x, int y, int w, int h) + int x, int y, int w, int h) { - component->setBounds (x, y, w, h); + component->setBounds (x, y, w, h); } void ComponentBoundsConstrainer::resizeStart() @@ -61151,153 +60852,153 @@ void ComponentBoundsConstrainer::resizeEnd() } void ComponentBoundsConstrainer::checkBounds (int& x, int& y, int& w, int& h, - const Rectangle& old, - const Rectangle& limits, - const bool isStretchingTop, - const bool isStretchingLeft, - const bool isStretchingBottom, - const bool isStretchingRight) + const Rectangle& old, + const Rectangle& limits, + const bool isStretchingTop, + const bool isStretchingLeft, + const bool isStretchingBottom, + const bool isStretchingRight) { - // constrain the size if it's being stretched.. - if (isStretchingLeft) - { - x = jlimit (old.getRight() - maxW, old.getRight() - minW, x); - w = old.getRight() - x; - } + // constrain the size if it's being stretched.. + if (isStretchingLeft) + { + x = jlimit (old.getRight() - maxW, old.getRight() - minW, x); + w = old.getRight() - x; + } - if (isStretchingRight) - { - w = jlimit (minW, maxW, w); - } + if (isStretchingRight) + { + w = jlimit (minW, maxW, w); + } - if (isStretchingTop) - { - y = jlimit (old.getBottom() - maxH, old.getBottom() - minH, y); - h = old.getBottom() - y; - } + if (isStretchingTop) + { + y = jlimit (old.getBottom() - maxH, old.getBottom() - minH, y); + h = old.getBottom() - y; + } - if (isStretchingBottom) - { - h = jlimit (minH, maxH, h); - } + if (isStretchingBottom) + { + h = jlimit (minH, maxH, h); + } - // constrain the aspect ratio if one has been specified.. - if (aspectRatio > 0.0 && w > 0 && h > 0) - { - bool adjustWidth; + // constrain the aspect ratio if one has been specified.. + if (aspectRatio > 0.0 && w > 0 && h > 0) + { + bool adjustWidth; - if ((isStretchingTop || isStretchingBottom) && ! (isStretchingLeft || isStretchingRight)) - { - adjustWidth = true; - } - else if ((isStretchingLeft || isStretchingRight) && ! (isStretchingTop || isStretchingBottom)) - { - adjustWidth = false; - } - else - { - const double oldRatio = (old.getHeight() > 0) ? fabs (old.getWidth() / (double) old.getHeight()) : 0.0; - const double newRatio = fabs (w / (double) h); + if ((isStretchingTop || isStretchingBottom) && ! (isStretchingLeft || isStretchingRight)) + { + adjustWidth = true; + } + else if ((isStretchingLeft || isStretchingRight) && ! (isStretchingTop || isStretchingBottom)) + { + adjustWidth = false; + } + else + { + const double oldRatio = (old.getHeight() > 0) ? fabs (old.getWidth() / (double) old.getHeight()) : 0.0; + const double newRatio = fabs (w / (double) h); - adjustWidth = (oldRatio > newRatio); - } + adjustWidth = (oldRatio > newRatio); + } - if (adjustWidth) - { - w = roundDoubleToInt (h * aspectRatio); + if (adjustWidth) + { + w = roundToInt (h * aspectRatio); - if (w > maxW || w < minW) - { - w = jlimit (minW, maxW, w); - h = roundDoubleToInt (w / aspectRatio); - } - } - else - { - h = roundDoubleToInt (w / aspectRatio); + if (w > maxW || w < minW) + { + w = jlimit (minW, maxW, w); + h = roundToInt (w / aspectRatio); + } + } + else + { + h = roundToInt (w / aspectRatio); - if (h > maxH || h < minH) - { - h = jlimit (minH, maxH, h); - w = roundDoubleToInt (h * aspectRatio); - } - } + if (h > maxH || h < minH) + { + h = jlimit (minH, maxH, h); + w = roundToInt (h * aspectRatio); + } + } - if ((isStretchingTop || isStretchingBottom) && ! (isStretchingLeft || isStretchingRight)) - { - x = old.getX() + (old.getWidth() - w) / 2; - } - else if ((isStretchingLeft || isStretchingRight) && ! (isStretchingTop || isStretchingBottom)) - { - y = old.getY() + (old.getHeight() - h) / 2; - } - else - { - if (isStretchingLeft) - x = old.getRight() - w; + if ((isStretchingTop || isStretchingBottom) && ! (isStretchingLeft || isStretchingRight)) + { + x = old.getX() + (old.getWidth() - w) / 2; + } + else if ((isStretchingLeft || isStretchingRight) && ! (isStretchingTop || isStretchingBottom)) + { + y = old.getY() + (old.getHeight() - h) / 2; + } + else + { + if (isStretchingLeft) + x = old.getRight() - w; - if (isStretchingTop) - y = old.getBottom() - h; - } - } + if (isStretchingTop) + y = old.getBottom() - h; + } + } - // ...and constrain the position if limits have been set for that. - if (minOffTop > 0 || minOffLeft > 0 || minOffBottom > 0 || minOffRight > 0) - { - if (minOffTop > 0) - { - const int limit = limits.getY() + jmin (minOffTop - h, 0); + // ...and constrain the position if limits have been set for that. + if (minOffTop > 0 || minOffLeft > 0 || minOffBottom > 0 || minOffRight > 0) + { + if (minOffTop > 0) + { + const int limit = limits.getY() + jmin (minOffTop - h, 0); - if (y < limit) - { - if (isStretchingTop) - h -= (limit - y); + if (y < limit) + { + if (isStretchingTop) + h -= (limit - y); - y = limit; - } - } + y = limit; + } + } - if (minOffLeft > 0) - { - const int limit = limits.getX() + jmin (minOffLeft - w, 0); + if (minOffLeft > 0) + { + const int limit = limits.getX() + jmin (minOffLeft - w, 0); - if (x < limit) - { - if (isStretchingLeft) - w -= (limit - x); + if (x < limit) + { + if (isStretchingLeft) + w -= (limit - x); - x = limit; - } - } + x = limit; + } + } - if (minOffBottom > 0) - { - const int limit = limits.getBottom() - jmin (minOffBottom, h); + if (minOffBottom > 0) + { + const int limit = limits.getBottom() - jmin (minOffBottom, h); - if (y > limit) - { - if (isStretchingBottom) - h += (limit - y); - else - y = limit; - } - } + if (y > limit) + { + if (isStretchingBottom) + h += (limit - y); + else + y = limit; + } + } - if (minOffRight > 0) - { - const int limit = limits.getRight() - jmin (minOffRight, w); + if (minOffRight > 0) + { + const int limit = limits.getRight() - jmin (minOffRight, w); - if (x > limit) - { - if (isStretchingRight) - w += (limit - x); - else - x = limit; - } - } - } + if (x > limit) + { + if (isStretchingRight) + w += (limit - x); + else + x = limit; + } + } + } - jassert (w >= 0 && h >= 0); + jassert (w >= 0 && h >= 0); } @@ -61309,106 +61010,105 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ComponentMovementWatcher::ComponentMovementWatcher (Component* const component_) - : component (component_), - lastPeer (0), - registeredParentComps (4), - reentrant (false) + : component (component_), + lastPeer (0), + reentrant (false) { - jassert (component != 0); // can't use this with a null pointer.. + jassert (component != 0); // can't use this with a null pointer.. #ifdef JUCE_DEBUG - deletionWatcher = new ComponentDeletionWatcher (component_); + deletionWatcher = new ComponentDeletionWatcher (component_); #endif - component->addComponentListener (this); + component->addComponentListener (this); - registerWithParentComps(); + registerWithParentComps(); } ComponentMovementWatcher::~ComponentMovementWatcher() { - component->removeComponentListener (this); + component->removeComponentListener (this); - unregister(); + unregister(); } void ComponentMovementWatcher::componentParentHierarchyChanged (Component&) { #ifdef JUCE_DEBUG - // agh! don't delete the target component without deleting this object first! - jassert (! deletionWatcher->hasBeenDeleted()); + // agh! don't delete the target component without deleting this object first! + jassert (! deletionWatcher->hasBeenDeleted()); #endif - if (! reentrant) - { - reentrant = true; + if (! reentrant) + { + reentrant = true; - ComponentPeer* const peer = component->getPeer(); + ComponentPeer* const peer = component->getPeer(); - if (peer != lastPeer) - { - ComponentDeletionWatcher watcher (component); + if (peer != lastPeer) + { + ComponentDeletionWatcher watcher (component); - componentPeerChanged(); + componentPeerChanged(); - if (watcher.hasBeenDeleted()) - return; + if (watcher.hasBeenDeleted()) + return; - lastPeer = peer; - } + lastPeer = peer; + } - unregister(); - registerWithParentComps(); + unregister(); + registerWithParentComps(); - reentrant = false; + reentrant = false; - componentMovedOrResized (*component, true, true); - } + componentMovedOrResized (*component, true, true); + } } void ComponentMovementWatcher::componentMovedOrResized (Component&, bool wasMoved, bool wasResized) { #ifdef JUCE_DEBUG - // agh! don't delete the target component without deleting this object first! - jassert (! deletionWatcher->hasBeenDeleted()); + // agh! don't delete the target component without deleting this object first! + jassert (! deletionWatcher->hasBeenDeleted()); #endif - if (wasMoved) - { - int x = 0, y = 0; - component->relativePositionToOtherComponent (component->getTopLevelComponent(), x, y); + if (wasMoved) + { + int x = 0, y = 0; + component->relativePositionToOtherComponent (component->getTopLevelComponent(), x, y); - wasMoved = (lastX != x || lastY != y); - lastX = x; - lastY = y; - } + wasMoved = (lastX != x || lastY != y); + lastX = x; + lastY = y; + } - wasResized = (lastWidth != component->getWidth() || lastHeight != component->getHeight()); - lastWidth = component->getWidth(); - lastHeight = component->getHeight(); + wasResized = (lastWidth != component->getWidth() || lastHeight != component->getHeight()); + lastWidth = component->getWidth(); + lastHeight = component->getHeight(); - if (wasMoved || wasResized) - componentMovedOrResized (wasMoved, wasResized); + if (wasMoved || wasResized) + componentMovedOrResized (wasMoved, wasResized); } void ComponentMovementWatcher::registerWithParentComps() throw() { - Component* p = component->getParentComponent(); + Component* p = component->getParentComponent(); - while (p != 0) - { - p->addComponentListener (this); - registeredParentComps.add (p); - p = p->getParentComponent(); - } + while (p != 0) + { + p->addComponentListener (this); + registeredParentComps.add (p); + p = p->getParentComponent(); + } } void ComponentMovementWatcher::unregister() throw() { - for (int i = registeredParentComps.size(); --i >= 0;) - ((Component*) registeredParentComps.getUnchecked(i))->removeComponentListener (this); + for (int i = registeredParentComps.size(); --i >= 0;) + ((Component*) registeredParentComps.getUnchecked(i))->removeComponentListener (this); - registeredParentComps.clear(); + registeredParentComps.clear(); } END_JUCE_NAMESPACE @@ -61419,12 +61119,12 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE GroupComponent::GroupComponent (const String& componentName, - const String& labelText) - : Component (componentName), - text (labelText), - justification (Justification::left) + const String& labelText) + : Component (componentName), + text (labelText), + justification (Justification::left) { - setInterceptsMouseClicks (false, true); + setInterceptsMouseClicks (false, true); } GroupComponent::~GroupComponent() @@ -61433,43 +61133,43 @@ GroupComponent::~GroupComponent() void GroupComponent::setText (const String& newText) throw() { - if (text != newText) - { - text = newText; - repaint(); - } + if (text != newText) + { + text = newText; + repaint(); + } } const String GroupComponent::getText() const throw() { - return text; + return text; } void GroupComponent::setTextLabelPosition (const Justification& newJustification) { - if (justification.getFlags() != newJustification.getFlags()) - { - justification = newJustification; - repaint(); - } + if (justification.getFlags() != newJustification.getFlags()) + { + justification = newJustification; + repaint(); + } } void GroupComponent::paint (Graphics& g) { - getLookAndFeel() - .drawGroupComponentOutline (g, getWidth(), getHeight(), - text, justification, - *this); + getLookAndFeel() + .drawGroupComponentOutline (g, getWidth(), getHeight(), + text, justification, + *this); } void GroupComponent::enablementChanged() { - repaint(); + repaint(); } void GroupComponent::colourChanged() { - repaint(); + repaint(); } END_JUCE_NAMESPACE @@ -61480,8 +61180,8 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MultiDocumentPanelWindow::MultiDocumentPanelWindow (const Colour& backgroundColour) - : DocumentWindow (String::empty, backgroundColour, - DocumentWindow::maximiseButton | DocumentWindow::closeButton, false) + : DocumentWindow (String::empty, backgroundColour, + DocumentWindow::maximiseButton | DocumentWindow::closeButton, false) { } @@ -61491,333 +61191,333 @@ MultiDocumentPanelWindow::~MultiDocumentPanelWindow() void MultiDocumentPanelWindow::maximiseButtonPressed() { - MultiDocumentPanel* const owner = getOwner(); + MultiDocumentPanel* const owner = getOwner(); - jassert (owner != 0); // these windows are only designed to be used inside a MultiDocumentPanel! - if (owner != 0) - owner->setLayoutMode (MultiDocumentPanel::MaximisedWindowsWithTabs); + jassert (owner != 0); // these windows are only designed to be used inside a MultiDocumentPanel! + if (owner != 0) + owner->setLayoutMode (MultiDocumentPanel::MaximisedWindowsWithTabs); } void MultiDocumentPanelWindow::closeButtonPressed() { - MultiDocumentPanel* const owner = getOwner(); + MultiDocumentPanel* const owner = getOwner(); - jassert (owner != 0); // these windows are only designed to be used inside a MultiDocumentPanel! - if (owner != 0) - owner->closeDocument (getContentComponent(), true); + jassert (owner != 0); // these windows are only designed to be used inside a MultiDocumentPanel! + if (owner != 0) + owner->closeDocument (getContentComponent(), true); } void MultiDocumentPanelWindow::activeWindowStatusChanged() { - DocumentWindow::activeWindowStatusChanged(); - updateOrder(); + DocumentWindow::activeWindowStatusChanged(); + updateOrder(); } void MultiDocumentPanelWindow::broughtToFront() { - DocumentWindow::broughtToFront(); - updateOrder(); + DocumentWindow::broughtToFront(); + updateOrder(); } void MultiDocumentPanelWindow::updateOrder() { - MultiDocumentPanel* const owner = getOwner(); + MultiDocumentPanel* const owner = getOwner(); - if (owner != 0) - owner->updateOrder(); + if (owner != 0) + owner->updateOrder(); } MultiDocumentPanel* MultiDocumentPanelWindow::getOwner() const throw() { - // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) - return findParentComponentOfClass ((MultiDocumentPanel*) 0); + // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) + return findParentComponentOfClass ((MultiDocumentPanel*) 0); } class MDITabbedComponentInternal : public TabbedComponent { public: - MDITabbedComponentInternal() - : TabbedComponent (TabbedButtonBar::TabsAtTop) - { - } + MDITabbedComponentInternal() + : TabbedComponent (TabbedButtonBar::TabsAtTop) + { + } - ~MDITabbedComponentInternal() - { - } + ~MDITabbedComponentInternal() + { + } - void currentTabChanged (const int, const String&) - { - // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) - MultiDocumentPanel* const owner = findParentComponentOfClass ((MultiDocumentPanel*) 0); + void currentTabChanged (const int, const String&) + { + // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) + MultiDocumentPanel* const owner = findParentComponentOfClass ((MultiDocumentPanel*) 0); - if (owner != 0) - owner->updateOrder(); - } + if (owner != 0) + owner->updateOrder(); + } }; MultiDocumentPanel::MultiDocumentPanel() - : mode (MaximisedWindowsWithTabs), - tabComponent (0), - backgroundColour (Colours::lightblue), - maximumNumDocuments (0), - numDocsBeforeTabsUsed (0) + : mode (MaximisedWindowsWithTabs), + tabComponent (0), + backgroundColour (Colours::lightblue), + maximumNumDocuments (0), + numDocsBeforeTabsUsed (0) { - setOpaque (true); + setOpaque (true); } MultiDocumentPanel::~MultiDocumentPanel() { - closeAllDocuments (false); + closeAllDocuments (false); } static bool shouldDeleteComp (Component* const c) { - return c->getComponentPropertyBool (T("mdiDocumentDelete_"), false); + return c->getComponentPropertyBool (T("mdiDocumentDelete_"), false); } bool MultiDocumentPanel::closeAllDocuments (const bool checkItsOkToCloseFirst) { - while (components.size() > 0) - if (! closeDocument (components.getLast(), checkItsOkToCloseFirst)) - return false; + while (components.size() > 0) + if (! closeDocument (components.getLast(), checkItsOkToCloseFirst)) + return false; - return true; + return true; } MultiDocumentPanelWindow* MultiDocumentPanel::createNewDocumentWindow() { - return new MultiDocumentPanelWindow (backgroundColour); + return new MultiDocumentPanelWindow (backgroundColour); } void MultiDocumentPanel::addWindow (Component* component) { - MultiDocumentPanelWindow* const dw = createNewDocumentWindow(); + MultiDocumentPanelWindow* const dw = createNewDocumentWindow(); - dw->setResizable (true, false); - dw->setContentComponent (component, false, true); - dw->setName (component->getName()); - dw->setBackgroundColour (component->getComponentPropertyColour (T("mdiDocumentBkg_"), false, backgroundColour)); + dw->setResizable (true, false); + dw->setContentComponent (component, false, true); + dw->setName (component->getName()); + dw->setBackgroundColour (component->getComponentPropertyColour (T("mdiDocumentBkg_"), false, backgroundColour)); - int x = 4; - Component* const topComp = getChildComponent (getNumChildComponents() - 1); + int x = 4; + Component* const topComp = getChildComponent (getNumChildComponents() - 1); - if (topComp != 0 && topComp->getX() == x && topComp->getY() == x) - x += 16; + if (topComp != 0 && topComp->getX() == x && topComp->getY() == x) + x += 16; - dw->setTopLeftPosition (x, x); + dw->setTopLeftPosition (x, x); - if (component->getComponentProperty (T("mdiDocumentPos_"), false, String::empty).isNotEmpty()) - dw->restoreWindowStateFromString (component->getComponentProperty (T("mdiDocumentPos_"), false, String::empty)); + if (component->getComponentProperty (T("mdiDocumentPos_"), false, String::empty).isNotEmpty()) + dw->restoreWindowStateFromString (component->getComponentProperty (T("mdiDocumentPos_"), false, String::empty)); - addAndMakeVisible (dw); - dw->toFront (true); + addAndMakeVisible (dw); + dw->toFront (true); } bool MultiDocumentPanel::addDocument (Component* const component, - const Colour& docColour, - const bool deleteWhenRemoved) + const Colour& docColour, + const bool deleteWhenRemoved) { - // If you try passing a full DocumentWindow or ResizableWindow in here, you'll end up - // with a frame-within-a-frame! Just pass in the bare content component. - jassert (dynamic_cast (component) == 0); + // If you try passing a full DocumentWindow or ResizableWindow in here, you'll end up + // with a frame-within-a-frame! Just pass in the bare content component. + jassert (dynamic_cast (component) == 0); - if (component == 0 || (maximumNumDocuments > 0 && components.size() >= maximumNumDocuments)) - return false; + if (component == 0 || (maximumNumDocuments > 0 && components.size() >= maximumNumDocuments)) + return false; - components.add (component); - component->setComponentProperty (T("mdiDocumentDelete_"), deleteWhenRemoved); - component->setComponentProperty (T("mdiDocumentBkg_"), docColour); - component->addComponentListener (this); + components.add (component); + component->setComponentProperty (T("mdiDocumentDelete_"), deleteWhenRemoved); + component->setComponentProperty (T("mdiDocumentBkg_"), docColour); + component->addComponentListener (this); - if (mode == FloatingWindows) - { - if (isFullscreenWhenOneDocument()) - { - if (components.size() == 1) - { - addAndMakeVisible (component); - } - else - { - if (components.size() == 2) - addWindow (components.getFirst()); + if (mode == FloatingWindows) + { + if (isFullscreenWhenOneDocument()) + { + if (components.size() == 1) + { + addAndMakeVisible (component); + } + else + { + if (components.size() == 2) + addWindow (components.getFirst()); - addWindow (component); - } - } - else - { - addWindow (component); - } - } - else - { - if (tabComponent == 0 && components.size() > numDocsBeforeTabsUsed) - { - addAndMakeVisible (tabComponent = new MDITabbedComponentInternal()); + addWindow (component); + } + } + else + { + addWindow (component); + } + } + else + { + if (tabComponent == 0 && components.size() > numDocsBeforeTabsUsed) + { + addAndMakeVisible (tabComponent = new MDITabbedComponentInternal()); - Array temp (components); + Array temp (components); - for (int i = 0; i < temp.size(); ++i) - tabComponent->addTab (temp[i]->getName(), docColour, temp[i], false); + for (int i = 0; i < temp.size(); ++i) + tabComponent->addTab (temp[i]->getName(), docColour, temp[i], false); - resized(); - } - else - { - if (tabComponent != 0) - tabComponent->addTab (component->getName(), docColour, component, false); - else - addAndMakeVisible (component); - } + resized(); + } + else + { + if (tabComponent != 0) + tabComponent->addTab (component->getName(), docColour, component, false); + else + addAndMakeVisible (component); + } - setActiveDocument (component); - } + setActiveDocument (component); + } - resized(); - activeDocumentChanged(); - return true; + resized(); + activeDocumentChanged(); + return true; } bool MultiDocumentPanel::closeDocument (Component* component, - const bool checkItsOkToCloseFirst) + const bool checkItsOkToCloseFirst) { - if (components.contains (component)) - { - if (checkItsOkToCloseFirst && ! tryToCloseDocument (component)) - return false; + if (components.contains (component)) + { + if (checkItsOkToCloseFirst && ! tryToCloseDocument (component)) + return false; - component->removeComponentListener (this); + component->removeComponentListener (this); - const bool shouldDelete = shouldDeleteComp (component); - component->removeComponentProperty (T("mdiDocumentDelete_")); - component->removeComponentProperty (T("mdiDocumentBkg_")); + const bool shouldDelete = shouldDeleteComp (component); + component->removeComponentProperty (T("mdiDocumentDelete_")); + component->removeComponentProperty (T("mdiDocumentBkg_")); - if (mode == FloatingWindows) - { - for (int i = getNumChildComponents(); --i >= 0;) - { - MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); + if (mode == FloatingWindows) + { + for (int i = getNumChildComponents(); --i >= 0;) + { + MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); - if (dw != 0 && dw->getContentComponent() == component) - { - dw->setContentComponent (0, false); - delete dw; - break; - } - } + if (dw != 0 && dw->getContentComponent() == component) + { + dw->setContentComponent (0, false); + delete dw; + break; + } + } - if (shouldDelete) - delete component; + if (shouldDelete) + delete component; - components.removeValue (component); + components.removeValue (component); - if (isFullscreenWhenOneDocument() && components.size() == 1) - { - for (int i = getNumChildComponents(); --i >= 0;) - { - MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); + if (isFullscreenWhenOneDocument() && components.size() == 1) + { + for (int i = getNumChildComponents(); --i >= 0;) + { + MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); - if (dw != 0) - { - dw->setContentComponent (0, false); - delete dw; - } - } + if (dw != 0) + { + dw->setContentComponent (0, false); + delete dw; + } + } - addAndMakeVisible (components.getFirst()); - } - } - else - { - jassert (components.indexOf (component) >= 0); + addAndMakeVisible (components.getFirst()); + } + } + else + { + jassert (components.indexOf (component) >= 0); - if (tabComponent != 0) - { - for (int i = tabComponent->getNumTabs(); --i >= 0;) - if (tabComponent->getTabContentComponent (i) == component) - tabComponent->removeTab (i); - } - else - { - removeChildComponent (component); - } + if (tabComponent != 0) + { + for (int i = tabComponent->getNumTabs(); --i >= 0;) + if (tabComponent->getTabContentComponent (i) == component) + tabComponent->removeTab (i); + } + else + { + removeChildComponent (component); + } - if (shouldDelete) - delete component; + if (shouldDelete) + delete component; - if (tabComponent != 0 && tabComponent->getNumTabs() <= numDocsBeforeTabsUsed) - deleteAndZero (tabComponent); + if (tabComponent != 0 && tabComponent->getNumTabs() <= numDocsBeforeTabsUsed) + deleteAndZero (tabComponent); - components.removeValue (component); + components.removeValue (component); - if (components.size() > 0 && tabComponent == 0) - addAndMakeVisible (components.getFirst()); - } + if (components.size() > 0 && tabComponent == 0) + addAndMakeVisible (components.getFirst()); + } - resized(); - activeDocumentChanged(); - } - else - { - jassertfalse - } + resized(); + activeDocumentChanged(); + } + else + { + jassertfalse + } - return true; + return true; } int MultiDocumentPanel::getNumDocuments() const throw() { - return components.size(); + return components.size(); } Component* MultiDocumentPanel::getDocument (const int index) const throw() { - return components [index]; + return components [index]; } Component* MultiDocumentPanel::getActiveDocument() const throw() { - if (mode == FloatingWindows) - { - for (int i = getNumChildComponents(); --i >= 0;) - { - MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); + if (mode == FloatingWindows) + { + for (int i = getNumChildComponents(); --i >= 0;) + { + MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); - if (dw != 0 && dw->isActiveWindow()) - return dw->getContentComponent(); - } - } + if (dw != 0 && dw->isActiveWindow()) + return dw->getContentComponent(); + } + } - return components.getLast(); + return components.getLast(); } void MultiDocumentPanel::setActiveDocument (Component* component) { - if (mode == FloatingWindows) - { - component = getContainerComp (component); + if (mode == FloatingWindows) + { + component = getContainerComp (component); - if (component != 0) - component->toFront (true); - } - else if (tabComponent != 0) - { - jassert (components.indexOf (component) >= 0); + if (component != 0) + component->toFront (true); + } + else if (tabComponent != 0) + { + jassert (components.indexOf (component) >= 0); - for (int i = tabComponent->getNumTabs(); --i >= 0;) - { - if (tabComponent->getTabContentComponent (i) == component) - { - tabComponent->setCurrentTabIndex (i); - break; - } - } - } - else - { - component->grabKeyboardFocus(); - } + for (int i = tabComponent->getNumTabs(); --i >= 0;) + { + if (tabComponent->getTabContentComponent (i) == component) + { + tabComponent->setCurrentTabIndex (i); + break; + } + } + } + else + { + component->grabKeyboardFocus(); + } } void MultiDocumentPanel::activeDocumentChanged() @@ -61826,155 +61526,155 @@ void MultiDocumentPanel::activeDocumentChanged() void MultiDocumentPanel::setMaximumNumDocuments (const int newNumber) { - maximumNumDocuments = newNumber; + maximumNumDocuments = newNumber; } void MultiDocumentPanel::useFullscreenWhenOneDocument (const bool shouldUseTabs) { - numDocsBeforeTabsUsed = shouldUseTabs ? 1 : 0; + numDocsBeforeTabsUsed = shouldUseTabs ? 1 : 0; } bool MultiDocumentPanel::isFullscreenWhenOneDocument() const throw() { - return numDocsBeforeTabsUsed != 0; + return numDocsBeforeTabsUsed != 0; } void MultiDocumentPanel::setLayoutMode (const LayoutMode newLayoutMode) { - if (mode != newLayoutMode) - { - mode = newLayoutMode; + if (mode != newLayoutMode) + { + mode = newLayoutMode; - if (mode == FloatingWindows) - { - deleteAndZero (tabComponent); - } - else - { - for (int i = getNumChildComponents(); --i >= 0;) - { - MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); + if (mode == FloatingWindows) + { + deleteAndZero (tabComponent); + } + else + { + for (int i = getNumChildComponents(); --i >= 0;) + { + MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); - if (dw != 0) - { - dw->getContentComponent()->setComponentProperty (T("mdiDocumentPos_"), dw->getWindowStateAsString()); - dw->setContentComponent (0, false); - delete dw; - } - } - } + if (dw != 0) + { + dw->getContentComponent()->setComponentProperty (T("mdiDocumentPos_"), dw->getWindowStateAsString()); + dw->setContentComponent (0, false); + delete dw; + } + } + } - resized(); + resized(); - const Array tempComps (components); - components.clear(); + const Array tempComps (components); + components.clear(); - for (int i = 0; i < tempComps.size(); ++i) - { - Component* const c = tempComps.getUnchecked(i); - addDocument (c, - c->getComponentPropertyColour (T("mdiDocumentBkg_"), false, Colours::white), - shouldDeleteComp (c)); - } - } + for (int i = 0; i < tempComps.size(); ++i) + { + Component* const c = tempComps.getUnchecked(i); + addDocument (c, + c->getComponentPropertyColour (T("mdiDocumentBkg_"), false, Colours::white), + shouldDeleteComp (c)); + } + } } void MultiDocumentPanel::setBackgroundColour (const Colour& newBackgroundColour) { - if (backgroundColour != newBackgroundColour) - { - backgroundColour = newBackgroundColour; - setOpaque (newBackgroundColour.isOpaque()); - repaint(); - } + if (backgroundColour != newBackgroundColour) + { + backgroundColour = newBackgroundColour; + setOpaque (newBackgroundColour.isOpaque()); + repaint(); + } } void MultiDocumentPanel::paint (Graphics& g) { - g.fillAll (backgroundColour); + g.fillAll (backgroundColour); } void MultiDocumentPanel::resized() { - if (mode == MaximisedWindowsWithTabs || components.size() == numDocsBeforeTabsUsed) - { - for (int i = getNumChildComponents(); --i >= 0;) - getChildComponent (i)->setBounds (0, 0, getWidth(), getHeight()); - } + if (mode == MaximisedWindowsWithTabs || components.size() == numDocsBeforeTabsUsed) + { + for (int i = getNumChildComponents(); --i >= 0;) + getChildComponent (i)->setBounds (0, 0, getWidth(), getHeight()); + } - setWantsKeyboardFocus (components.size() == 0); + setWantsKeyboardFocus (components.size() == 0); } Component* MultiDocumentPanel::getContainerComp (Component* c) const { - if (mode == FloatingWindows) - { - for (int i = 0; i < getNumChildComponents(); ++i) - { - MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); + if (mode == FloatingWindows) + { + for (int i = 0; i < getNumChildComponents(); ++i) + { + MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); - if (dw != 0 && dw->getContentComponent() == c) - { - c = dw; - break; - } - } - } + if (dw != 0 && dw->getContentComponent() == c) + { + c = dw; + break; + } + } + } - return c; + return c; } void MultiDocumentPanel::componentNameChanged (Component&) { - if (mode == FloatingWindows) - { - for (int i = 0; i < getNumChildComponents(); ++i) - { - MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); + if (mode == FloatingWindows) + { + for (int i = 0; i < getNumChildComponents(); ++i) + { + MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); - if (dw != 0) - dw->setName (dw->getContentComponent()->getName()); - } - } - else if (tabComponent != 0) - { - for (int i = tabComponent->getNumTabs(); --i >= 0;) - tabComponent->setTabName (i, tabComponent->getTabContentComponent (i)->getName()); - } + if (dw != 0) + dw->setName (dw->getContentComponent()->getName()); + } + } + else if (tabComponent != 0) + { + for (int i = tabComponent->getNumTabs(); --i >= 0;) + tabComponent->setTabName (i, tabComponent->getTabContentComponent (i)->getName()); + } } void MultiDocumentPanel::updateOrder() { - const Array oldList (components); + const Array oldList (components); - if (mode == FloatingWindows) - { - components.clear(); + if (mode == FloatingWindows) + { + components.clear(); - for (int i = 0; i < getNumChildComponents(); ++i) - { - MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); + for (int i = 0; i < getNumChildComponents(); ++i) + { + MultiDocumentPanelWindow* const dw = dynamic_cast (getChildComponent (i)); - if (dw != 0) - components.add (dw->getContentComponent()); - } - } - else - { - if (tabComponent != 0) - { - Component* const current = tabComponent->getCurrentContentComponent(); + if (dw != 0) + components.add (dw->getContentComponent()); + } + } + else + { + if (tabComponent != 0) + { + Component* const current = tabComponent->getCurrentContentComponent(); - if (current != 0) - { - components.removeValue (current); - components.add (current); - } - } - } + if (current != 0) + { + components.removeValue (current); + components.add (current); + } + } + } - if (components != oldList) - activeDocumentChanged(); + if (components != oldList) + activeDocumentChanged(); } END_JUCE_NAMESPACE @@ -61990,11 +61690,11 @@ const int zoneT = 4; const int zoneB = 8; ResizableBorderComponent::ResizableBorderComponent (Component* const componentToResize, - ComponentBoundsConstrainer* const constrainer_) + ComponentBoundsConstrainer* const constrainer_) : component (componentToResize), - constrainer (constrainer_), - borderSize (5), - mouseZone (0) + constrainer (constrainer_), + borderSize (5), + mouseZone (0) { } @@ -62004,183 +61704,183 @@ ResizableBorderComponent::~ResizableBorderComponent() void ResizableBorderComponent::paint (Graphics& g) { - getLookAndFeel().drawResizableFrame (g, getWidth(), getHeight(), borderSize); + getLookAndFeel().drawResizableFrame (g, getWidth(), getHeight(), borderSize); } void ResizableBorderComponent::mouseEnter (const MouseEvent& e) { - updateMouseZone (e); + updateMouseZone (e); } void ResizableBorderComponent::mouseMove (const MouseEvent& e) { - updateMouseZone (e); + updateMouseZone (e); } void ResizableBorderComponent::mouseDown (const MouseEvent& e) { - if (component->isValidComponent()) - { - updateMouseZone (e); + if (component->isValidComponent()) + { + updateMouseZone (e); - originalX = component->getX(); - originalY = component->getY(); - originalW = component->getWidth(); - originalH = component->getHeight(); + originalX = component->getX(); + originalY = component->getY(); + originalW = component->getWidth(); + originalH = component->getHeight(); - if (constrainer != 0) - constrainer->resizeStart(); - } - else - { - jassertfalse - } + if (constrainer != 0) + constrainer->resizeStart(); + } + else + { + jassertfalse + } } void ResizableBorderComponent::mouseDrag (const MouseEvent& e) { - if (! component->isValidComponent()) - { - jassertfalse - return; - } + if (! component->isValidComponent()) + { + jassertfalse + return; + } - int x = originalX; - int y = originalY; - int w = originalW; - int h = originalH; + int x = originalX; + int y = originalY; + int w = originalW; + int h = originalH; - const int dx = e.getDistanceFromDragStartX(); - const int dy = e.getDistanceFromDragStartY(); + const int dx = e.getDistanceFromDragStartX(); + const int dy = e.getDistanceFromDragStartY(); - if ((mouseZone & zoneL) != 0) - { - x += dx; - w -= dx; - } + if ((mouseZone & zoneL) != 0) + { + x += dx; + w -= dx; + } - if ((mouseZone & zoneT) != 0) - { - y += dy; - h -= dy; - } + if ((mouseZone & zoneT) != 0) + { + y += dy; + h -= dy; + } - if ((mouseZone & zoneR) != 0) - w += dx; + if ((mouseZone & zoneR) != 0) + w += dx; - if ((mouseZone & zoneB) != 0) - h += dy; + if ((mouseZone & zoneB) != 0) + h += dy; - if (constrainer != 0) - constrainer->setBoundsForComponent (component, - x, y, w, h, - (mouseZone & zoneT) != 0, - (mouseZone & zoneL) != 0, - (mouseZone & zoneB) != 0, - (mouseZone & zoneR) != 0); - else - component->setBounds (x, y, w, h); + if (constrainer != 0) + constrainer->setBoundsForComponent (component, + x, y, w, h, + (mouseZone & zoneT) != 0, + (mouseZone & zoneL) != 0, + (mouseZone & zoneB) != 0, + (mouseZone & zoneR) != 0); + else + component->setBounds (x, y, w, h); } void ResizableBorderComponent::mouseUp (const MouseEvent&) { - if (constrainer != 0) - constrainer->resizeEnd(); + if (constrainer != 0) + constrainer->resizeEnd(); } bool ResizableBorderComponent::hitTest (int x, int y) { - return x < borderSize.getLeft() - || x >= getWidth() - borderSize.getRight() - || y < borderSize.getTop() - || y >= getHeight() - borderSize.getBottom(); + return x < borderSize.getLeft() + || x >= getWidth() - borderSize.getRight() + || y < borderSize.getTop() + || y >= getHeight() - borderSize.getBottom(); } void ResizableBorderComponent::setBorderThickness (const BorderSize& newBorderSize) throw() { - if (borderSize != newBorderSize) - { - borderSize = newBorderSize; - repaint(); - } + if (borderSize != newBorderSize) + { + borderSize = newBorderSize; + repaint(); + } } const BorderSize ResizableBorderComponent::getBorderThickness() const throw() { - return borderSize; + return borderSize; } void ResizableBorderComponent::updateMouseZone (const MouseEvent& e) throw() { - int newZone = 0; + int newZone = 0; - if (ResizableBorderComponent::hitTest (e.x, e.y)) - { - if (e.x < jmax (borderSize.getLeft(), - proportionOfWidth (0.1f), - jmin (10, proportionOfWidth (0.33f)))) - newZone |= zoneL; - else if (e.x >= jmin (getWidth() - borderSize.getRight(), - proportionOfWidth (0.9f), - getWidth() - jmin (10, proportionOfWidth (0.33f)))) - newZone |= zoneR; + if (ResizableBorderComponent::hitTest (e.x, e.y)) + { + if (e.x < jmax (borderSize.getLeft(), + proportionOfWidth (0.1f), + jmin (10, proportionOfWidth (0.33f)))) + newZone |= zoneL; + else if (e.x >= jmin (getWidth() - borderSize.getRight(), + proportionOfWidth (0.9f), + getWidth() - jmin (10, proportionOfWidth (0.33f)))) + newZone |= zoneR; - if (e.y < jmax (borderSize.getTop(), - proportionOfHeight (0.1f), - jmin (10, proportionOfHeight (0.33f)))) - newZone |= zoneT; - else if (e.y >= jmin (getHeight() - borderSize.getBottom(), - proportionOfHeight (0.9f), - getHeight() - jmin (10, proportionOfHeight (0.33f)))) - newZone |= zoneB; - } + if (e.y < jmax (borderSize.getTop(), + proportionOfHeight (0.1f), + jmin (10, proportionOfHeight (0.33f)))) + newZone |= zoneT; + else if (e.y >= jmin (getHeight() - borderSize.getBottom(), + proportionOfHeight (0.9f), + getHeight() - jmin (10, proportionOfHeight (0.33f)))) + newZone |= zoneB; + } - if (mouseZone != newZone) - { - mouseZone = newZone; + if (mouseZone != newZone) + { + mouseZone = newZone; - MouseCursor::StandardCursorType mc = MouseCursor::NormalCursor; + MouseCursor::StandardCursorType mc = MouseCursor::NormalCursor; - switch (newZone) - { - case (zoneL | zoneT): - mc = MouseCursor::TopLeftCornerResizeCursor; - break; + switch (newZone) + { + case (zoneL | zoneT): + mc = MouseCursor::TopLeftCornerResizeCursor; + break; - case zoneT: - mc = MouseCursor::TopEdgeResizeCursor; - break; + case zoneT: + mc = MouseCursor::TopEdgeResizeCursor; + break; - case (zoneR | zoneT): - mc = MouseCursor::TopRightCornerResizeCursor; - break; + case (zoneR | zoneT): + mc = MouseCursor::TopRightCornerResizeCursor; + break; - case zoneL: - mc = MouseCursor::LeftEdgeResizeCursor; - break; + case zoneL: + mc = MouseCursor::LeftEdgeResizeCursor; + break; - case zoneR: - mc = MouseCursor::RightEdgeResizeCursor; - break; + case zoneR: + mc = MouseCursor::RightEdgeResizeCursor; + break; - case (zoneL | zoneB): - mc = MouseCursor::BottomLeftCornerResizeCursor; - break; + case (zoneL | zoneB): + mc = MouseCursor::BottomLeftCornerResizeCursor; + break; - case zoneB: - mc = MouseCursor::BottomEdgeResizeCursor; - break; + case zoneB: + mc = MouseCursor::BottomEdgeResizeCursor; + break; - case (zoneR | zoneB): - mc = MouseCursor::BottomRightCornerResizeCursor; - break; + case (zoneR | zoneB): + mc = MouseCursor::BottomRightCornerResizeCursor; + break; - default: - break; - } + default: + break; + } - setMouseCursor (mc); - } + setMouseCursor (mc); + } } END_JUCE_NAMESPACE @@ -62191,12 +61891,12 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ResizableCornerComponent::ResizableCornerComponent (Component* const componentToResize, - ComponentBoundsConstrainer* const constrainer_) + ComponentBoundsConstrainer* const constrainer_) : component (componentToResize), - constrainer (constrainer_) + constrainer (constrainer_) { - setRepaintsOnMouseActivity (true); - setMouseCursor (MouseCursor::BottomRightCornerResizeCursor); + setRepaintsOnMouseActivity (true); + setMouseCursor (MouseCursor::BottomRightCornerResizeCursor); } ResizableCornerComponent::~ResizableCornerComponent() @@ -62205,64 +61905,64 @@ ResizableCornerComponent::~ResizableCornerComponent() void ResizableCornerComponent::paint (Graphics& g) { - getLookAndFeel() - .drawCornerResizer (g, getWidth(), getHeight(), - isMouseOverOrDragging(), - isMouseButtonDown()); + getLookAndFeel() + .drawCornerResizer (g, getWidth(), getHeight(), + isMouseOverOrDragging(), + isMouseButtonDown()); } void ResizableCornerComponent::mouseDown (const MouseEvent&) { - if (component->isValidComponent()) - { - originalX = component->getX(); - originalY = component->getY(); - originalW = component->getWidth(); - originalH = component->getHeight(); + if (component->isValidComponent()) + { + originalX = component->getX(); + originalY = component->getY(); + originalW = component->getWidth(); + originalH = component->getHeight(); - if (constrainer != 0) - constrainer->resizeStart(); - } - else - { - jassertfalse - } + if (constrainer != 0) + constrainer->resizeStart(); + } + else + { + jassertfalse + } } void ResizableCornerComponent::mouseDrag (const MouseEvent& e) { - if (! component->isValidComponent()) - { - jassertfalse - return; - } + if (! component->isValidComponent()) + { + jassertfalse + return; + } - int x = originalX; - int y = originalY; - int w = originalW + e.getDistanceFromDragStartX(); - int h = originalH + e.getDistanceFromDragStartY(); + int x = originalX; + int y = originalY; + int w = originalW + e.getDistanceFromDragStartX(); + int h = originalH + e.getDistanceFromDragStartY(); - if (constrainer != 0) - constrainer->setBoundsForComponent (component, x, y, w, h, - false, false, true, true); - else - component->setBounds (x, y, w, h); + if (constrainer != 0) + constrainer->setBoundsForComponent (component, x, y, w, h, + false, false, true, true); + else + component->setBounds (x, y, w, h); } void ResizableCornerComponent::mouseUp (const MouseEvent&) { - if (constrainer != 0) - constrainer->resizeStart(); + if (constrainer != 0) + constrainer->resizeStart(); } bool ResizableCornerComponent::hitTest (int x, int y) { - if (getWidth() <= 0) - return false; + if (getWidth() <= 0) + return false; - const int yAtX = getHeight() - (getHeight() * x / getWidth()); + const int yAtX = getHeight() - (getHeight() * x / getWidth()); - return y >= yAtX - getHeight() / 4; + return y >= yAtX - getHeight() / 4; } END_JUCE_NAMESPACE @@ -62275,417 +61975,416 @@ BEGIN_JUCE_NAMESPACE class ScrollbarButton : public Button { public: - int direction; + int direction; - ScrollbarButton (const int direction_, - ScrollBar& owner_) throw() - : Button (String::empty), - direction (direction_), - owner (owner_) - { - setWantsKeyboardFocus (false); - } + ScrollbarButton (const int direction_, + ScrollBar& owner_) throw() + : Button (String::empty), + direction (direction_), + owner (owner_) + { + setWantsKeyboardFocus (false); + } - ~ScrollbarButton() - { - } + ~ScrollbarButton() + { + } - void paintButton (Graphics& g, - bool isMouseOver, - bool isMouseDown) - { - getLookAndFeel() - .drawScrollbarButton (g, owner, - getWidth(), getHeight(), - direction, - owner.isVertical(), - isMouseOver, isMouseDown); - } + void paintButton (Graphics& g, + bool isMouseOver, + bool isMouseDown) + { + getLookAndFeel() + .drawScrollbarButton (g, owner, + getWidth(), getHeight(), + direction, + owner.isVertical(), + isMouseOver, isMouseDown); + } - void clicked() - { - owner.moveScrollbarInSteps ((direction == 1 || direction == 2) ? 1 : -1); - } + void clicked() + { + owner.moveScrollbarInSteps ((direction == 1 || direction == 2) ? 1 : -1); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ScrollBar& owner; + ScrollBar& owner; - ScrollbarButton (const ScrollbarButton&); - const ScrollbarButton& operator= (const ScrollbarButton&); + ScrollbarButton (const ScrollbarButton&); + const ScrollbarButton& operator= (const ScrollbarButton&); }; ScrollBar::ScrollBar (const bool vertical_, - const bool buttonsAreVisible) - : minimum (0.0), - maximum (1.0), - rangeStart (0.0), - rangeSize (0.1), - singleStepSize (0.1), - thumbAreaStart (0), - thumbAreaSize (0), - thumbStart (0), - thumbSize (0), - initialDelayInMillisecs (100), - repeatDelayInMillisecs (50), - minimumDelayInMillisecs (10), - vertical (vertical_), - isDraggingThumb (false), - alwaysVisible (false), - upButton (0), - downButton (0), - listeners (2) + const bool buttonsAreVisible) + : minimum (0.0), + maximum (1.0), + rangeStart (0.0), + rangeSize (0.1), + singleStepSize (0.1), + thumbAreaStart (0), + thumbAreaSize (0), + thumbStart (0), + thumbSize (0), + initialDelayInMillisecs (100), + repeatDelayInMillisecs (50), + minimumDelayInMillisecs (10), + vertical (vertical_), + isDraggingThumb (false), + alwaysVisible (false), + upButton (0), + downButton (0) { - setButtonVisibility (buttonsAreVisible); + setButtonVisibility (buttonsAreVisible); - setRepaintsOnMouseActivity (true); - setFocusContainer (true); + setRepaintsOnMouseActivity (true); + setFocusContainer (true); } ScrollBar::~ScrollBar() { - deleteAllChildren(); + deleteAllChildren(); } void ScrollBar::setRangeLimits (const double newMinimum, - const double newMaximum) throw() + const double newMaximum) throw() { - minimum = newMinimum; - maximum = newMaximum; + minimum = newMinimum; + maximum = newMaximum; - jassert (maximum >= minimum); // these can't be the wrong way round! + jassert (maximum >= minimum); // these can't be the wrong way round! - setCurrentRangeStart (rangeStart); - updateThumbPosition(); + setCurrentRangeStart (rangeStart); + updateThumbPosition(); } void ScrollBar::setCurrentRange (double newStart, - double newSize) throw() + double newSize) throw() { - newSize = jlimit (0.0, maximum - minimum, newSize); - newStart = jlimit (minimum, maximum - newSize, newStart); + newSize = jlimit (0.0, maximum - minimum, newSize); + newStart = jlimit (minimum, maximum - newSize, newStart); - if (rangeStart != newStart - || rangeSize != newSize) - { - rangeStart = newStart; - rangeSize = newSize; + if (rangeStart != newStart + || rangeSize != newSize) + { + rangeStart = newStart; + rangeSize = newSize; - updateThumbPosition(); - triggerAsyncUpdate(); - } + updateThumbPosition(); + triggerAsyncUpdate(); + } } void ScrollBar::setCurrentRangeStart (double newStart) throw() { - setCurrentRange (newStart, rangeSize); + setCurrentRange (newStart, rangeSize); } void ScrollBar::setSingleStepSize (const double newSingleStepSize) throw() { - singleStepSize = newSingleStepSize; + singleStepSize = newSingleStepSize; } void ScrollBar::moveScrollbarInSteps (const int howManySteps) throw() { - setCurrentRangeStart (rangeStart + howManySteps * singleStepSize); + setCurrentRangeStart (rangeStart + howManySteps * singleStepSize); } void ScrollBar::moveScrollbarInPages (const int howManyPages) throw() { - setCurrentRangeStart (rangeStart + howManyPages * rangeSize); + setCurrentRangeStart (rangeStart + howManyPages * rangeSize); } void ScrollBar::scrollToTop() throw() { - setCurrentRangeStart (minimum); + setCurrentRangeStart (minimum); } void ScrollBar::scrollToBottom() throw() { - setCurrentRangeStart (maximum - rangeSize); + setCurrentRangeStart (maximum - rangeSize); } void ScrollBar::setButtonRepeatSpeed (const int initialDelayInMillisecs_, - const int repeatDelayInMillisecs_, - const int minimumDelayInMillisecs_) throw() + const int repeatDelayInMillisecs_, + const int minimumDelayInMillisecs_) throw() { - initialDelayInMillisecs = initialDelayInMillisecs_; - repeatDelayInMillisecs = repeatDelayInMillisecs_; - minimumDelayInMillisecs = minimumDelayInMillisecs_; + initialDelayInMillisecs = initialDelayInMillisecs_; + repeatDelayInMillisecs = repeatDelayInMillisecs_; + minimumDelayInMillisecs = minimumDelayInMillisecs_; - if (upButton != 0) - { - upButton->setRepeatSpeed (initialDelayInMillisecs, repeatDelayInMillisecs, minimumDelayInMillisecs); - downButton->setRepeatSpeed (initialDelayInMillisecs, repeatDelayInMillisecs, minimumDelayInMillisecs); - } + if (upButton != 0) + { + upButton->setRepeatSpeed (initialDelayInMillisecs, repeatDelayInMillisecs, minimumDelayInMillisecs); + downButton->setRepeatSpeed (initialDelayInMillisecs, repeatDelayInMillisecs, minimumDelayInMillisecs); + } } void ScrollBar::addListener (ScrollBarListener* const listener) throw() { - jassert (listener != 0); - if (listener != 0) - listeners.add (listener); + jassert (listener != 0); + if (listener != 0) + listeners.add (listener); } void ScrollBar::removeListener (ScrollBarListener* const listener) throw() { - listeners.removeValue (listener); + listeners.removeValue (listener); } void ScrollBar::handleAsyncUpdate() { - const double value = getCurrentRangeStart(); + const double value = getCurrentRangeStart(); - for (int i = listeners.size(); --i >= 0;) - { - ((ScrollBarListener*) listeners.getUnchecked (i))->scrollBarMoved (this, value); - i = jmin (i, listeners.size()); - } + for (int i = listeners.size(); --i >= 0;) + { + ((ScrollBarListener*) listeners.getUnchecked (i))->scrollBarMoved (this, value); + i = jmin (i, listeners.size()); + } } void ScrollBar::updateThumbPosition() throw() { - int newThumbSize = roundDoubleToInt ((maximum > minimum) ? (rangeSize * thumbAreaSize) / (maximum - minimum) - : thumbAreaSize); + int newThumbSize = roundToInt ((maximum > minimum) ? (rangeSize * thumbAreaSize) / (maximum - minimum) + : thumbAreaSize); - if (newThumbSize < getLookAndFeel().getMinimumScrollbarThumbSize (*this)) - newThumbSize = jmin (getLookAndFeel().getMinimumScrollbarThumbSize (*this), thumbAreaSize - 1); + if (newThumbSize < getLookAndFeel().getMinimumScrollbarThumbSize (*this)) + newThumbSize = jmin (getLookAndFeel().getMinimumScrollbarThumbSize (*this), thumbAreaSize - 1); - if (newThumbSize > thumbAreaSize) - newThumbSize = thumbAreaSize; + if (newThumbSize > thumbAreaSize) + newThumbSize = thumbAreaSize; - int newThumbStart = thumbAreaStart; + int newThumbStart = thumbAreaStart; - if (maximum - minimum > rangeSize) - newThumbStart += roundDoubleToInt (((rangeStart - minimum) * (thumbAreaSize - newThumbSize)) - / ((maximum - minimum) - rangeSize)); + if (maximum - minimum > rangeSize) + newThumbStart += roundToInt (((rangeStart - minimum) * (thumbAreaSize - newThumbSize)) + / ((maximum - minimum) - rangeSize)); - setVisible (alwaysVisible || (maximum - minimum > rangeSize && rangeSize > 0.0)); + setVisible (alwaysVisible || (maximum - minimum > rangeSize && rangeSize > 0.0)); - if (thumbStart != newThumbStart || thumbSize != newThumbSize) - { - const int repaintStart = jmin (thumbStart, newThumbStart) - 4; - const int repaintSize = jmax (thumbStart + thumbSize, newThumbStart + newThumbSize) + 8 - repaintStart; + if (thumbStart != newThumbStart || thumbSize != newThumbSize) + { + const int repaintStart = jmin (thumbStart, newThumbStart) - 4; + const int repaintSize = jmax (thumbStart + thumbSize, newThumbStart + newThumbSize) + 8 - repaintStart; - if (vertical) - repaint (0, repaintStart, getWidth(), repaintSize); - else - repaint (repaintStart, 0, repaintSize, getHeight()); + if (vertical) + repaint (0, repaintStart, getWidth(), repaintSize); + else + repaint (repaintStart, 0, repaintSize, getHeight()); - thumbStart = newThumbStart; - thumbSize = newThumbSize; - } + thumbStart = newThumbStart; + thumbSize = newThumbSize; + } } void ScrollBar::setOrientation (const bool shouldBeVertical) throw() { - if (vertical != shouldBeVertical) - { - vertical = shouldBeVertical; + if (vertical != shouldBeVertical) + { + vertical = shouldBeVertical; - if (upButton != 0) - { - ((ScrollbarButton*) upButton)->direction = (vertical) ? 0 : 3; - ((ScrollbarButton*) downButton)->direction = (vertical) ? 2 : 1; - } + if (upButton != 0) + { + ((ScrollbarButton*) upButton)->direction = (vertical) ? 0 : 3; + ((ScrollbarButton*) downButton)->direction = (vertical) ? 2 : 1; + } - updateThumbPosition(); - } + updateThumbPosition(); + } } void ScrollBar::setButtonVisibility (const bool buttonsAreVisible) { - deleteAndZero (upButton); - deleteAndZero (downButton); + deleteAndZero (upButton); + deleteAndZero (downButton); - if (buttonsAreVisible) - { - addAndMakeVisible (upButton = new ScrollbarButton ((vertical) ? 0 : 3, *this)); - addAndMakeVisible (downButton = new ScrollbarButton ((vertical) ? 2 : 1, *this)); + if (buttonsAreVisible) + { + addAndMakeVisible (upButton = new ScrollbarButton ((vertical) ? 0 : 3, *this)); + addAndMakeVisible (downButton = new ScrollbarButton ((vertical) ? 2 : 1, *this)); - setButtonRepeatSpeed (initialDelayInMillisecs, repeatDelayInMillisecs, minimumDelayInMillisecs); - } + setButtonRepeatSpeed (initialDelayInMillisecs, repeatDelayInMillisecs, minimumDelayInMillisecs); + } - updateThumbPosition(); + updateThumbPosition(); } void ScrollBar::setAutoHide (const bool shouldHideWhenFullRange) { - alwaysVisible = ! shouldHideWhenFullRange; - updateThumbPosition(); + alwaysVisible = ! shouldHideWhenFullRange; + updateThumbPosition(); } void ScrollBar::paint (Graphics& g) { - if (thumbAreaSize > 0) - { - LookAndFeel& lf = getLookAndFeel(); + if (thumbAreaSize > 0) + { + LookAndFeel& lf = getLookAndFeel(); - const int thumb = (thumbAreaSize > lf.getMinimumScrollbarThumbSize (*this)) - ? thumbSize : 0; + const int thumb = (thumbAreaSize > lf.getMinimumScrollbarThumbSize (*this)) + ? thumbSize : 0; - if (vertical) - { - lf.drawScrollbar (g, *this, - 0, thumbAreaStart, - getWidth(), thumbAreaSize, - vertical, - thumbStart, thumb, - isMouseOver(), isMouseButtonDown()); - } - else - { - lf.drawScrollbar (g, *this, - thumbAreaStart, 0, - thumbAreaSize, getHeight(), - vertical, - thumbStart, thumb, - isMouseOver(), isMouseButtonDown()); - } - } + if (vertical) + { + lf.drawScrollbar (g, *this, + 0, thumbAreaStart, + getWidth(), thumbAreaSize, + vertical, + thumbStart, thumb, + isMouseOver(), isMouseButtonDown()); + } + else + { + lf.drawScrollbar (g, *this, + thumbAreaStart, 0, + thumbAreaSize, getHeight(), + vertical, + thumbStart, thumb, + isMouseOver(), isMouseButtonDown()); + } + } } void ScrollBar::lookAndFeelChanged() { - setComponentEffect (getLookAndFeel().getScrollbarEffect()); + setComponentEffect (getLookAndFeel().getScrollbarEffect()); } void ScrollBar::resized() { - const int length = ((vertical) ? getHeight() : getWidth()); + const int length = ((vertical) ? getHeight() : getWidth()); - const int buttonSize = (upButton != 0) ? jmin (getLookAndFeel().getScrollbarButtonSize (*this), (length >> 1)) - : 0; + const int buttonSize = (upButton != 0) ? jmin (getLookAndFeel().getScrollbarButtonSize (*this), (length >> 1)) + : 0; - if (length < 32 + getLookAndFeel().getMinimumScrollbarThumbSize (*this)) - { - thumbAreaStart = length >> 1; - thumbAreaSize = 0; - } - else - { - thumbAreaStart = buttonSize; - thumbAreaSize = length - (buttonSize << 1); - } + if (length < 32 + getLookAndFeel().getMinimumScrollbarThumbSize (*this)) + { + thumbAreaStart = length >> 1; + thumbAreaSize = 0; + } + else + { + thumbAreaStart = buttonSize; + thumbAreaSize = length - (buttonSize << 1); + } - if (upButton != 0) - { - if (vertical) - { - upButton->setBounds (0, 0, getWidth(), buttonSize); - downButton->setBounds (0, thumbAreaStart + thumbAreaSize, getWidth(), buttonSize); - } - else - { - upButton->setBounds (0, 0, buttonSize, getHeight()); - downButton->setBounds (thumbAreaStart + thumbAreaSize, 0, buttonSize, getHeight()); - } - } + if (upButton != 0) + { + if (vertical) + { + upButton->setBounds (0, 0, getWidth(), buttonSize); + downButton->setBounds (0, thumbAreaStart + thumbAreaSize, getWidth(), buttonSize); + } + else + { + upButton->setBounds (0, 0, buttonSize, getHeight()); + downButton->setBounds (thumbAreaStart + thumbAreaSize, 0, buttonSize, getHeight()); + } + } - updateThumbPosition(); + updateThumbPosition(); } void ScrollBar::mouseDown (const MouseEvent& e) { - isDraggingThumb = false; - lastMousePos = vertical ? e.y : e.x; - dragStartMousePos = lastMousePos; - dragStartRange = rangeStart; + isDraggingThumb = false; + lastMousePos = vertical ? e.y : e.x; + dragStartMousePos = lastMousePos; + dragStartRange = rangeStart; - if (dragStartMousePos < thumbStart) - { - moveScrollbarInPages (-1); - startTimer (400); - } - else if (dragStartMousePos >= thumbStart + thumbSize) - { - moveScrollbarInPages (1); - startTimer (400); - } - else - { - isDraggingThumb = (thumbAreaSize > getLookAndFeel().getMinimumScrollbarThumbSize (*this)) - && (thumbAreaSize > thumbSize); - } + if (dragStartMousePos < thumbStart) + { + moveScrollbarInPages (-1); + startTimer (400); + } + else if (dragStartMousePos >= thumbStart + thumbSize) + { + moveScrollbarInPages (1); + startTimer (400); + } + else + { + isDraggingThumb = (thumbAreaSize > getLookAndFeel().getMinimumScrollbarThumbSize (*this)) + && (thumbAreaSize > thumbSize); + } } void ScrollBar::mouseDrag (const MouseEvent& e) { - if (isDraggingThumb) - { - const int deltaPixels = ((vertical) ? e.y : e.x) - dragStartMousePos; + if (isDraggingThumb) + { + const int deltaPixels = ((vertical) ? e.y : e.x) - dragStartMousePos; - setCurrentRangeStart (dragStartRange - + deltaPixels * ((maximum - minimum) - rangeSize) - / (thumbAreaSize - thumbSize)); - } - else - { - lastMousePos = (vertical) ? e.y : e.x; - } + setCurrentRangeStart (dragStartRange + + deltaPixels * ((maximum - minimum) - rangeSize) + / (thumbAreaSize - thumbSize)); + } + else + { + lastMousePos = (vertical) ? e.y : e.x; + } } void ScrollBar::mouseUp (const MouseEvent&) { - isDraggingThumb = false; - stopTimer(); - repaint(); + isDraggingThumb = false; + stopTimer(); + repaint(); } void ScrollBar::mouseWheelMove (const MouseEvent&, - float wheelIncrementX, - float wheelIncrementY) + float wheelIncrementX, + float wheelIncrementY) { - float increment = vertical ? wheelIncrementY : wheelIncrementX; + float increment = vertical ? wheelIncrementY : wheelIncrementX; - if (increment < 0) - increment = jmin (increment * 10.0f, -1.0f); - else if (increment > 0) - increment = jmax (increment * 10.0f, 1.0f); + if (increment < 0) + increment = jmin (increment * 10.0f, -1.0f); + else if (increment > 0) + increment = jmax (increment * 10.0f, 1.0f); - setCurrentRangeStart (rangeStart - singleStepSize * increment); + setCurrentRangeStart (rangeStart - singleStepSize * increment); } void ScrollBar::timerCallback() { - if (isMouseButtonDown()) - { - startTimer (40); + if (isMouseButtonDown()) + { + startTimer (40); - if (lastMousePos < thumbStart) - setCurrentRangeStart (rangeStart - rangeSize); - else if (lastMousePos > thumbStart + thumbSize) - setCurrentRangeStart (rangeStart + rangeSize); - } - else - { - stopTimer(); - } + if (lastMousePos < thumbStart) + setCurrentRangeStart (rangeStart - rangeSize); + else if (lastMousePos > thumbStart + thumbSize) + setCurrentRangeStart (rangeStart + rangeSize); + } + else + { + stopTimer(); + } } bool ScrollBar::keyPressed (const KeyPress& key) { - if (! isVisible()) - return false; + if (! isVisible()) + return false; - if (key.isKeyCode (KeyPress::upKey) || key.isKeyCode (KeyPress::leftKey)) - moveScrollbarInSteps (-1); - else if (key.isKeyCode (KeyPress::downKey) || key.isKeyCode (KeyPress::rightKey)) - moveScrollbarInSteps (1); - else if (key.isKeyCode (KeyPress::pageUpKey)) - moveScrollbarInPages (-1); - else if (key.isKeyCode (KeyPress::pageDownKey)) - moveScrollbarInPages (1); - else if (key.isKeyCode (KeyPress::homeKey)) - scrollToTop(); - else if (key.isKeyCode (KeyPress::endKey)) - scrollToBottom(); - else - return false; + if (key.isKeyCode (KeyPress::upKey) || key.isKeyCode (KeyPress::leftKey)) + moveScrollbarInSteps (-1); + else if (key.isKeyCode (KeyPress::downKey) || key.isKeyCode (KeyPress::rightKey)) + moveScrollbarInSteps (1); + else if (key.isKeyCode (KeyPress::pageUpKey)) + moveScrollbarInPages (-1); + else if (key.isKeyCode (KeyPress::pageDownKey)) + moveScrollbarInPages (1); + else if (key.isKeyCode (KeyPress::homeKey)) + scrollToTop(); + else if (key.isKeyCode (KeyPress::endKey)) + scrollToBottom(); + else + return false; - return true; + return true; } END_JUCE_NAMESPACE @@ -62696,7 +62395,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE StretchableLayoutManager::StretchableLayoutManager() - : totalSize (0) + : totalSize (0) { } @@ -62706,322 +62405,322 @@ StretchableLayoutManager::~StretchableLayoutManager() void StretchableLayoutManager::clearAllItems() { - items.clear(); - totalSize = 0; + items.clear(); + totalSize = 0; } void StretchableLayoutManager::setItemLayout (const int itemIndex, - const double minimumSize, - const double maximumSize, - const double preferredSize) + const double minimumSize, + const double maximumSize, + const double preferredSize) { - ItemLayoutProperties* layout = getInfoFor (itemIndex); + ItemLayoutProperties* layout = getInfoFor (itemIndex); - if (layout == 0) - { - layout = new ItemLayoutProperties(); - layout->itemIndex = itemIndex; + if (layout == 0) + { + layout = new ItemLayoutProperties(); + layout->itemIndex = itemIndex; - int i; - for (i = 0; i < items.size(); ++i) - if (items.getUnchecked (i)->itemIndex > itemIndex) - break; + int i; + for (i = 0; i < items.size(); ++i) + if (items.getUnchecked (i)->itemIndex > itemIndex) + break; - items.insert (i, layout); - } + items.insert (i, layout); + } - layout->minSize = minimumSize; - layout->maxSize = maximumSize; - layout->preferredSize = preferredSize; - layout->currentSize = 0; + layout->minSize = minimumSize; + layout->maxSize = maximumSize; + layout->preferredSize = preferredSize; + layout->currentSize = 0; } bool StretchableLayoutManager::getItemLayout (const int itemIndex, - double& minimumSize, - double& maximumSize, - double& preferredSize) const + double& minimumSize, + double& maximumSize, + double& preferredSize) const { - const ItemLayoutProperties* const layout = getInfoFor (itemIndex); + const ItemLayoutProperties* const layout = getInfoFor (itemIndex); - if (layout != 0) - { - minimumSize = layout->minSize; - maximumSize = layout->maxSize; - preferredSize = layout->preferredSize; - return true; - } + if (layout != 0) + { + minimumSize = layout->minSize; + maximumSize = layout->maxSize; + preferredSize = layout->preferredSize; + return true; + } - return false; + return false; } void StretchableLayoutManager::setTotalSize (const int newTotalSize) { - totalSize = newTotalSize; + totalSize = newTotalSize; - fitComponentsIntoSpace (0, items.size(), totalSize, 0); + fitComponentsIntoSpace (0, items.size(), totalSize, 0); } int StretchableLayoutManager::getItemCurrentPosition (const int itemIndex) const { - int pos = 0; + int pos = 0; - for (int i = 0; i < itemIndex; ++i) - { - const ItemLayoutProperties* const layout = getInfoFor (i); + for (int i = 0; i < itemIndex; ++i) + { + const ItemLayoutProperties* const layout = getInfoFor (i); - if (layout != 0) - pos += layout->currentSize; - } + if (layout != 0) + pos += layout->currentSize; + } - return pos; + return pos; } int StretchableLayoutManager::getItemCurrentAbsoluteSize (const int itemIndex) const { - const ItemLayoutProperties* const layout = getInfoFor (itemIndex); + const ItemLayoutProperties* const layout = getInfoFor (itemIndex); - if (layout != 0) - return layout->currentSize; + if (layout != 0) + return layout->currentSize; - return 0; + return 0; } double StretchableLayoutManager::getItemCurrentRelativeSize (const int itemIndex) const { - const ItemLayoutProperties* const layout = getInfoFor (itemIndex); + const ItemLayoutProperties* const layout = getInfoFor (itemIndex); - if (layout != 0) - return -layout->currentSize / (double) totalSize; + if (layout != 0) + return -layout->currentSize / (double) totalSize; - return 0; + return 0; } void StretchableLayoutManager::setItemPosition (const int itemIndex, - int newPosition) + int newPosition) { - for (int i = items.size(); --i >= 0;) - { - const ItemLayoutProperties* const layout = items.getUnchecked(i); + for (int i = items.size(); --i >= 0;) + { + const ItemLayoutProperties* const layout = items.getUnchecked(i); - if (layout->itemIndex == itemIndex) - { - int realTotalSize = jmax (totalSize, getMinimumSizeOfItems (0, items.size())); - const int minSizeAfterThisComp = getMinimumSizeOfItems (i, items.size()); - const int maxSizeAfterThisComp = getMaximumSizeOfItems (i + 1, items.size()); + if (layout->itemIndex == itemIndex) + { + int realTotalSize = jmax (totalSize, getMinimumSizeOfItems (0, items.size())); + const int minSizeAfterThisComp = getMinimumSizeOfItems (i, items.size()); + const int maxSizeAfterThisComp = getMaximumSizeOfItems (i + 1, items.size()); - newPosition = jmax (newPosition, totalSize - maxSizeAfterThisComp - layout->currentSize); - newPosition = jmin (newPosition, realTotalSize - minSizeAfterThisComp); + newPosition = jmax (newPosition, totalSize - maxSizeAfterThisComp - layout->currentSize); + newPosition = jmin (newPosition, realTotalSize - minSizeAfterThisComp); - int endPos = fitComponentsIntoSpace (0, i, newPosition, 0); + int endPos = fitComponentsIntoSpace (0, i, newPosition, 0); - endPos += layout->currentSize; + endPos += layout->currentSize; - fitComponentsIntoSpace (i + 1, items.size(), totalSize - endPos, endPos); - updatePrefSizesToMatchCurrentPositions(); - break; - } - } + fitComponentsIntoSpace (i + 1, items.size(), totalSize - endPos, endPos); + updatePrefSizesToMatchCurrentPositions(); + break; + } + } } void StretchableLayoutManager::layOutComponents (Component** const components, - int numComponents, - int x, int y, int w, int h, - const bool vertically, - const bool resizeOtherDimension) + int numComponents, + int x, int y, int w, int h, + const bool vertically, + const bool resizeOtherDimension) { - setTotalSize (vertically ? h : w); - int pos = vertically ? y : x; + setTotalSize (vertically ? h : w); + int pos = vertically ? y : x; - for (int i = 0; i < numComponents; ++i) - { - const ItemLayoutProperties* const layout = getInfoFor (i); + for (int i = 0; i < numComponents; ++i) + { + const ItemLayoutProperties* const layout = getInfoFor (i); - if (layout != 0) - { - Component* const c = components[i]; + if (layout != 0) + { + Component* const c = components[i]; - if (c != 0) - { - if (i == numComponents - 1) - { - // if it's the last item, crop it to exactly fit the available space.. - if (resizeOtherDimension) - { - if (vertically) - c->setBounds (x, pos, w, jmax (layout->currentSize, h - pos)); - else - c->setBounds (pos, y, jmax (layout->currentSize, w - pos), h); - } - else - { - if (vertically) - c->setBounds (c->getX(), pos, c->getWidth(), jmax (layout->currentSize, h - pos)); - else - c->setBounds (pos, c->getY(), jmax (layout->currentSize, w - pos), c->getHeight()); - } - } - else - { - if (resizeOtherDimension) - { - if (vertically) - c->setBounds (x, pos, w, layout->currentSize); - else - c->setBounds (pos, y, layout->currentSize, h); - } - else - { - if (vertically) - c->setBounds (c->getX(), pos, c->getWidth(), layout->currentSize); - else - c->setBounds (pos, c->getY(), layout->currentSize, c->getHeight()); - } - } - } + if (c != 0) + { + if (i == numComponents - 1) + { + // if it's the last item, crop it to exactly fit the available space.. + if (resizeOtherDimension) + { + if (vertically) + c->setBounds (x, pos, w, jmax (layout->currentSize, h - pos)); + else + c->setBounds (pos, y, jmax (layout->currentSize, w - pos), h); + } + else + { + if (vertically) + c->setBounds (c->getX(), pos, c->getWidth(), jmax (layout->currentSize, h - pos)); + else + c->setBounds (pos, c->getY(), jmax (layout->currentSize, w - pos), c->getHeight()); + } + } + else + { + if (resizeOtherDimension) + { + if (vertically) + c->setBounds (x, pos, w, layout->currentSize); + else + c->setBounds (pos, y, layout->currentSize, h); + } + else + { + if (vertically) + c->setBounds (c->getX(), pos, c->getWidth(), layout->currentSize); + else + c->setBounds (pos, c->getY(), layout->currentSize, c->getHeight()); + } + } + } - pos += layout->currentSize; - } - } + pos += layout->currentSize; + } + } } StretchableLayoutManager::ItemLayoutProperties* StretchableLayoutManager::getInfoFor (const int itemIndex) const { - for (int i = items.size(); --i >= 0;) - if (items.getUnchecked(i)->itemIndex == itemIndex) - return items.getUnchecked(i); + for (int i = items.size(); --i >= 0;) + if (items.getUnchecked(i)->itemIndex == itemIndex) + return items.getUnchecked(i); - return 0; + return 0; } int StretchableLayoutManager::fitComponentsIntoSpace (const int startIndex, - const int endIndex, - const int availableSpace, - int startPos) + const int endIndex, + const int availableSpace, + int startPos) { - // calculate the total sizes - int i; - double totalIdealSize = 0.0; - int totalMinimums = 0; + // calculate the total sizes + int i; + double totalIdealSize = 0.0; + int totalMinimums = 0; - for (i = startIndex; i < endIndex; ++i) - { - ItemLayoutProperties* const layout = items.getUnchecked (i); + for (i = startIndex; i < endIndex; ++i) + { + ItemLayoutProperties* const layout = items.getUnchecked (i); - layout->currentSize = sizeToRealSize (layout->minSize, totalSize); + layout->currentSize = sizeToRealSize (layout->minSize, totalSize); - totalMinimums += layout->currentSize; - totalIdealSize += sizeToRealSize (layout->preferredSize, availableSpace); - } + totalMinimums += layout->currentSize; + totalIdealSize += sizeToRealSize (layout->preferredSize, availableSpace); + } - if (totalIdealSize <= 0) - totalIdealSize = 1.0; + if (totalIdealSize <= 0) + totalIdealSize = 1.0; - // now calc the best sizes.. - int extraSpace = availableSpace - totalMinimums; + // now calc the best sizes.. + int extraSpace = availableSpace - totalMinimums; - while (extraSpace > 0) - { - int numWantingMoreSpace = 0; - int numHavingTakenExtraSpace = 0; + while (extraSpace > 0) + { + int numWantingMoreSpace = 0; + int numHavingTakenExtraSpace = 0; - // first figure out how many comps want a slice of the extra space.. - for (i = startIndex; i < endIndex; ++i) - { - ItemLayoutProperties* const layout = items.getUnchecked (i); + // first figure out how many comps want a slice of the extra space.. + for (i = startIndex; i < endIndex; ++i) + { + ItemLayoutProperties* const layout = items.getUnchecked (i); - double sizeWanted = sizeToRealSize (layout->preferredSize, availableSpace); + double sizeWanted = sizeToRealSize (layout->preferredSize, availableSpace); - const int bestSize = jlimit (layout->currentSize, - jmax (layout->currentSize, - sizeToRealSize (layout->maxSize, totalSize)), - roundDoubleToInt (sizeWanted * availableSpace / totalIdealSize)); + const int bestSize = jlimit (layout->currentSize, + jmax (layout->currentSize, + sizeToRealSize (layout->maxSize, totalSize)), + roundToInt (sizeWanted * availableSpace / totalIdealSize)); - if (bestSize > layout->currentSize) - ++numWantingMoreSpace; - } + if (bestSize > layout->currentSize) + ++numWantingMoreSpace; + } - // ..share out the extra space.. - for (i = startIndex; i < endIndex; ++i) - { - ItemLayoutProperties* const layout = items.getUnchecked (i); + // ..share out the extra space.. + for (i = startIndex; i < endIndex; ++i) + { + ItemLayoutProperties* const layout = items.getUnchecked (i); - double sizeWanted = sizeToRealSize (layout->preferredSize, availableSpace); + double sizeWanted = sizeToRealSize (layout->preferredSize, availableSpace); - int bestSize = jlimit (layout->currentSize, - jmax (layout->currentSize, sizeToRealSize (layout->maxSize, totalSize)), - roundDoubleToInt (sizeWanted * availableSpace / totalIdealSize)); + int bestSize = jlimit (layout->currentSize, + jmax (layout->currentSize, sizeToRealSize (layout->maxSize, totalSize)), + roundToInt (sizeWanted * availableSpace / totalIdealSize)); - const int extraWanted = bestSize - layout->currentSize; + const int extraWanted = bestSize - layout->currentSize; - if (extraWanted > 0) - { - const int extraAllowed = jmin (extraWanted, - extraSpace / jmax (1, numWantingMoreSpace)); + if (extraWanted > 0) + { + const int extraAllowed = jmin (extraWanted, + extraSpace / jmax (1, numWantingMoreSpace)); - if (extraAllowed > 0) - { - ++numHavingTakenExtraSpace; - --numWantingMoreSpace; + if (extraAllowed > 0) + { + ++numHavingTakenExtraSpace; + --numWantingMoreSpace; - layout->currentSize += extraAllowed; - extraSpace -= extraAllowed; - } - } - } + layout->currentSize += extraAllowed; + extraSpace -= extraAllowed; + } + } + } - if (numHavingTakenExtraSpace <= 0) - break; - } + if (numHavingTakenExtraSpace <= 0) + break; + } - // ..and calculate the end position - for (i = startIndex; i < endIndex; ++i) - { - ItemLayoutProperties* const layout = items.getUnchecked(i); - startPos += layout->currentSize; - } + // ..and calculate the end position + for (i = startIndex; i < endIndex; ++i) + { + ItemLayoutProperties* const layout = items.getUnchecked(i); + startPos += layout->currentSize; + } - return startPos; + return startPos; } int StretchableLayoutManager::getMinimumSizeOfItems (const int startIndex, - const int endIndex) const + const int endIndex) const { - int totalMinimums = 0; + int totalMinimums = 0; - for (int i = startIndex; i < endIndex; ++i) - totalMinimums += sizeToRealSize (items.getUnchecked (i)->minSize, totalSize); + for (int i = startIndex; i < endIndex; ++i) + totalMinimums += sizeToRealSize (items.getUnchecked (i)->minSize, totalSize); - return totalMinimums; + return totalMinimums; } int StretchableLayoutManager::getMaximumSizeOfItems (const int startIndex, const int endIndex) const { - int totalMaximums = 0; + int totalMaximums = 0; - for (int i = startIndex; i < endIndex; ++i) - totalMaximums += sizeToRealSize (items.getUnchecked (i)->maxSize, totalSize); + for (int i = startIndex; i < endIndex; ++i) + totalMaximums += sizeToRealSize (items.getUnchecked (i)->maxSize, totalSize); - return totalMaximums; + return totalMaximums; } void StretchableLayoutManager::updatePrefSizesToMatchCurrentPositions() { - for (int i = 0; i < items.size(); ++i) - { - ItemLayoutProperties* const layout = items.getUnchecked (i); + for (int i = 0; i < items.size(); ++i) + { + ItemLayoutProperties* const layout = items.getUnchecked (i); - layout->preferredSize - = (layout->preferredSize < 0) ? getItemCurrentRelativeSize (i) - : getItemCurrentAbsoluteSize (i); - } + layout->preferredSize + = (layout->preferredSize < 0) ? getItemCurrentRelativeSize (i) + : getItemCurrentAbsoluteSize (i); + } } int StretchableLayoutManager::sizeToRealSize (double size, int totalSpace) { - if (size < 0) - size *= -totalSpace; + if (size < 0) + size *= -totalSpace; - return roundDoubleToInt (size); + return roundToInt (size); } END_JUCE_NAMESPACE @@ -63032,15 +62731,15 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE StretchableLayoutResizerBar::StretchableLayoutResizerBar (StretchableLayoutManager* layout_, - const int itemIndex_, - const bool isVertical_) - : layout (layout_), - itemIndex (itemIndex_), - isVertical (isVertical_) + const int itemIndex_, + const bool isVertical_) + : layout (layout_), + itemIndex (itemIndex_), + isVertical (isVertical_) { - setRepaintsOnMouseActivity (true); - setMouseCursor (MouseCursor (isVertical_ ? MouseCursor::LeftRightResizeCursor - : MouseCursor::UpDownResizeCursor)); + setRepaintsOnMouseActivity (true); + setMouseCursor (MouseCursor (isVertical_ ? MouseCursor::LeftRightResizeCursor + : MouseCursor::UpDownResizeCursor)); } StretchableLayoutResizerBar::~StretchableLayoutResizerBar() @@ -63049,32 +62748,32 @@ StretchableLayoutResizerBar::~StretchableLayoutResizerBar() void StretchableLayoutResizerBar::paint (Graphics& g) { - getLookAndFeel().drawStretchableLayoutResizerBar (g, - getWidth(), getHeight(), - isVertical, - isMouseOver(), - isMouseButtonDown()); + getLookAndFeel().drawStretchableLayoutResizerBar (g, + getWidth(), getHeight(), + isVertical, + isMouseOver(), + isMouseButtonDown()); } void StretchableLayoutResizerBar::mouseDown (const MouseEvent&) { - mouseDownPos = layout->getItemCurrentPosition (itemIndex); + mouseDownPos = layout->getItemCurrentPosition (itemIndex); } void StretchableLayoutResizerBar::mouseDrag (const MouseEvent& e) { - const int desiredPos = mouseDownPos + (isVertical ? e.getDistanceFromDragStartX() - : e.getDistanceFromDragStartY()); + const int desiredPos = mouseDownPos + (isVertical ? e.getDistanceFromDragStartX() + : e.getDistanceFromDragStartY()); - layout->setItemPosition (itemIndex, desiredPos); + layout->setItemPosition (itemIndex, desiredPos); - hasBeenMoved(); + hasBeenMoved(); } void StretchableLayoutResizerBar::hasBeenMoved() { - if (getParentComponent() != 0) - getParentComponent()->resized(); + if (getParentComponent() != 0) + getParentComponent()->resized(); } END_JUCE_NAMESPACE @@ -63093,91 +62792,91 @@ StretchableObjectResizer::~StretchableObjectResizer() } void StretchableObjectResizer::addItem (const double size, - const double minSize, const double maxSize, - const int order) + const double minSize, const double maxSize, + const int order) { - jassert (order >= 0 && order < INT_MAX); // the order must be >= 0 and less than INT_MAX + jassert (order >= 0 && order < INT_MAX); // the order must be >= 0 and less than INT_MAX - Item* const item = new Item(); - item->size = size; - item->minSize = minSize; - item->maxSize = maxSize; - item->order = order; - items.add (item); + Item* const item = new Item(); + item->size = size; + item->minSize = minSize; + item->maxSize = maxSize; + item->order = order; + items.add (item); } double StretchableObjectResizer::getItemSize (const int index) const throw() { - const Item* const it = items [index]; - return it != 0 ? it->size : 0; + const Item* const it = items [index]; + return it != 0 ? it->size : 0; } void StretchableObjectResizer::resizeToFit (const double targetSize) { - int order = 0; + int order = 0; - for (;;) - { - double currentSize = 0; - double minSize = 0; - double maxSize = 0; + for (;;) + { + double currentSize = 0; + double minSize = 0; + double maxSize = 0; - int nextHighestOrder = INT_MAX; + int nextHighestOrder = INT_MAX; - for (int i = 0; i < items.size(); ++i) - { - const Item* const it = items.getUnchecked(i); - currentSize += it->size; + for (int i = 0; i < items.size(); ++i) + { + const Item* const it = items.getUnchecked(i); + currentSize += it->size; - if (it->order <= order) - { - minSize += it->minSize; - maxSize += it->maxSize; - } - else - { - minSize += it->size; - maxSize += it->size; - nextHighestOrder = jmin (nextHighestOrder, it->order); - } - } + if (it->order <= order) + { + minSize += it->minSize; + maxSize += it->maxSize; + } + else + { + minSize += it->size; + maxSize += it->size; + nextHighestOrder = jmin (nextHighestOrder, it->order); + } + } - const double thisIterationTarget = jlimit (minSize, maxSize, targetSize); + const double thisIterationTarget = jlimit (minSize, maxSize, targetSize); - if (thisIterationTarget >= currentSize) - { - const double availableExtraSpace = maxSize - currentSize; - const double targetAmountOfExtraSpace = thisIterationTarget - currentSize; - const double scale = targetAmountOfExtraSpace / availableExtraSpace; + if (thisIterationTarget >= currentSize) + { + const double availableExtraSpace = maxSize - currentSize; + const double targetAmountOfExtraSpace = thisIterationTarget - currentSize; + const double scale = targetAmountOfExtraSpace / availableExtraSpace; - for (int i = 0; i < items.size(); ++i) - { - Item* const it = items.getUnchecked(i); + for (int i = 0; i < items.size(); ++i) + { + Item* const it = items.getUnchecked(i); - if (it->order <= order) - it->size = jmin (it->maxSize, it->size + (it->maxSize - it->size) * scale); - } - } - else - { - const double amountOfSlack = currentSize - minSize; - const double targetAmountOfSlack = thisIterationTarget - minSize; - const double scale = targetAmountOfSlack / amountOfSlack; + if (it->order <= order) + it->size = jmin (it->maxSize, it->size + (it->maxSize - it->size) * scale); + } + } + else + { + const double amountOfSlack = currentSize - minSize; + const double targetAmountOfSlack = thisIterationTarget - minSize; + const double scale = targetAmountOfSlack / amountOfSlack; - for (int i = 0; i < items.size(); ++i) - { - Item* const it = items.getUnchecked(i); + for (int i = 0; i < items.size(); ++i) + { + Item* const it = items.getUnchecked(i); - if (it->order <= order) - it->size = jmax (it->minSize, it->minSize + (it->size - it->minSize) * scale); - } - } + if (it->order <= order) + it->size = jmax (it->minSize, it->minSize + (it->size - it->minSize) * scale); + } + } - if (nextHighestOrder < INT_MAX) - order = nextHighestOrder; - else - break; - } + if (nextHighestOrder < INT_MAX) + order = nextHighestOrder; + else + break; + } } END_JUCE_NAMESPACE @@ -63188,16 +62887,16 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE TabBarButton::TabBarButton (const String& name, - TabbedButtonBar* const owner_, - const int index) - : Button (name), - owner (owner_), - tabIndex (index), - overlapPixels (0) + TabbedButtonBar* const owner_, + const int index) + : Button (name), + owner (owner_), + tabIndex (index), + overlapPixels (0) { - shadow.setShadowProperties (2.2f, 0.7f, 0, 0); - setComponentEffect (&shadow); - setWantsKeyboardFocus (false); + shadow.setShadowProperties (2.2f, 0.7f, 0, 0); + setComponentEffect (&shadow); + setWantsKeyboardFocus (false); } TabBarButton::~TabBarButton() @@ -63205,475 +62904,475 @@ TabBarButton::~TabBarButton() } void TabBarButton::paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown) + bool isMouseOverButton, + bool isButtonDown) { - int x, y, w, h; - getActiveArea (x, y, w, h); + int x, y, w, h; + getActiveArea (x, y, w, h); - g.setOrigin (x, y); + g.setOrigin (x, y); - getLookAndFeel() - .drawTabButton (g, w, h, - owner->getTabBackgroundColour (tabIndex), - tabIndex, getButtonText(), *this, - owner->getOrientation(), - isMouseOverButton, isButtonDown, - getToggleState()); + getLookAndFeel() + .drawTabButton (g, w, h, + owner->getTabBackgroundColour (tabIndex), + tabIndex, getButtonText(), *this, + owner->getOrientation(), + isMouseOverButton, isButtonDown, + getToggleState()); } void TabBarButton::clicked (const ModifierKeys& mods) { - if (mods.isPopupMenu()) - owner->popupMenuClickOnTab (tabIndex, getButtonText()); - else - owner->setCurrentTabIndex (tabIndex); + if (mods.isPopupMenu()) + owner->popupMenuClickOnTab (tabIndex, getButtonText()); + else + owner->setCurrentTabIndex (tabIndex); } bool TabBarButton::hitTest (int mx, int my) { - int x, y, w, h; - getActiveArea (x, y, w, h); + int x, y, w, h; + getActiveArea (x, y, w, h); - if (owner->getOrientation() == TabbedButtonBar::TabsAtLeft - || owner->getOrientation() == TabbedButtonBar::TabsAtRight) - { - if (((unsigned int) mx) < (unsigned int) getWidth() - && my >= y + overlapPixels - && my < y + h - overlapPixels) - return true; - } - else - { - if (mx >= x + overlapPixels && mx < x + w - overlapPixels - && ((unsigned int) my) < (unsigned int) getHeight()) - return true; - } + if (owner->getOrientation() == TabbedButtonBar::TabsAtLeft + || owner->getOrientation() == TabbedButtonBar::TabsAtRight) + { + if (((unsigned int) mx) < (unsigned int) getWidth() + && my >= y + overlapPixels + && my < y + h - overlapPixels) + return true; + } + else + { + if (mx >= x + overlapPixels && mx < x + w - overlapPixels + && ((unsigned int) my) < (unsigned int) getHeight()) + return true; + } - Path p; - getLookAndFeel() - .createTabButtonShape (p, w, h, tabIndex, getButtonText(), *this, - owner->getOrientation(), - false, false, getToggleState()); + Path p; + getLookAndFeel() + .createTabButtonShape (p, w, h, tabIndex, getButtonText(), *this, + owner->getOrientation(), + false, false, getToggleState()); - return p.contains ((float) (mx - x), - (float) (my - y)); + return p.contains ((float) (mx - x), + (float) (my - y)); } int TabBarButton::getBestTabLength (const int depth) { - return jlimit (depth * 2, - depth * 7, - getLookAndFeel().getTabButtonBestWidth (tabIndex, getButtonText(), depth, *this)); + return jlimit (depth * 2, + depth * 7, + getLookAndFeel().getTabButtonBestWidth (tabIndex, getButtonText(), depth, *this)); } void TabBarButton::getActiveArea (int& x, int& y, int& w, int& h) { - x = 0; - y = 0; - int r = getWidth(); - int b = getHeight(); + x = 0; + y = 0; + int r = getWidth(); + int b = getHeight(); - const int spaceAroundImage = getLookAndFeel().getTabButtonSpaceAroundImage(); + const int spaceAroundImage = getLookAndFeel().getTabButtonSpaceAroundImage(); - if (owner->getOrientation() != TabbedButtonBar::TabsAtLeft) - r -= spaceAroundImage; + if (owner->getOrientation() != TabbedButtonBar::TabsAtLeft) + r -= spaceAroundImage; - if (owner->getOrientation() != TabbedButtonBar::TabsAtRight) - x += spaceAroundImage; + if (owner->getOrientation() != TabbedButtonBar::TabsAtRight) + x += spaceAroundImage; - if (owner->getOrientation() != TabbedButtonBar::TabsAtBottom) - y += spaceAroundImage; + if (owner->getOrientation() != TabbedButtonBar::TabsAtBottom) + y += spaceAroundImage; - if (owner->getOrientation() != TabbedButtonBar::TabsAtTop) - b -= spaceAroundImage; + if (owner->getOrientation() != TabbedButtonBar::TabsAtTop) + b -= spaceAroundImage; - w = r - x; - h = b - y; + w = r - x; + h = b - y; } class TabAreaBehindFrontButtonComponent : public Component { public: - TabAreaBehindFrontButtonComponent (TabbedButtonBar* const owner_) - : owner (owner_) - { - setInterceptsMouseClicks (false, false); - } + TabAreaBehindFrontButtonComponent (TabbedButtonBar* const owner_) + : owner (owner_) + { + setInterceptsMouseClicks (false, false); + } - ~TabAreaBehindFrontButtonComponent() - { - } + ~TabAreaBehindFrontButtonComponent() + { + } - void paint (Graphics& g) - { - getLookAndFeel() - .drawTabAreaBehindFrontButton (g, getWidth(), getHeight(), - *owner, owner->getOrientation()); - } + void paint (Graphics& g) + { + getLookAndFeel() + .drawTabAreaBehindFrontButton (g, getWidth(), getHeight(), + *owner, owner->getOrientation()); + } - void enablementChanged() - { - repaint(); - } + void enablementChanged() + { + repaint(); + } private: - TabbedButtonBar* const owner; + TabbedButtonBar* const owner; - TabAreaBehindFrontButtonComponent (const TabAreaBehindFrontButtonComponent&); - const TabAreaBehindFrontButtonComponent& operator= (const TabAreaBehindFrontButtonComponent&); + TabAreaBehindFrontButtonComponent (const TabAreaBehindFrontButtonComponent&); + const TabAreaBehindFrontButtonComponent& operator= (const TabAreaBehindFrontButtonComponent&); }; TabbedButtonBar::TabbedButtonBar (const Orientation orientation_) - : orientation (orientation_), - currentTabIndex (-1), - extraTabsButton (0) + : orientation (orientation_), + currentTabIndex (-1), + extraTabsButton (0) { - setInterceptsMouseClicks (false, true); - addAndMakeVisible (behindFrontTab = new TabAreaBehindFrontButtonComponent (this)); - setFocusContainer (true); + setInterceptsMouseClicks (false, true); + addAndMakeVisible (behindFrontTab = new TabAreaBehindFrontButtonComponent (this)); + setFocusContainer (true); } TabbedButtonBar::~TabbedButtonBar() { - deleteAllChildren(); + deleteAllChildren(); } void TabbedButtonBar::setOrientation (const Orientation newOrientation) { - orientation = newOrientation; + orientation = newOrientation; - for (int i = getNumChildComponents(); --i >= 0;) - getChildComponent (i)->resized(); + for (int i = getNumChildComponents(); --i >= 0;) + getChildComponent (i)->resized(); - resized(); + resized(); } TabBarButton* TabbedButtonBar::createTabButton (const String& name, const int index) { - return new TabBarButton (name, this, index); + return new TabBarButton (name, this, index); } void TabbedButtonBar::clearTabs() { - tabs.clear(); - tabColours.clear(); - currentTabIndex = -1; + tabs.clear(); + tabColours.clear(); + currentTabIndex = -1; - deleteAndZero (extraTabsButton); - removeChildComponent (behindFrontTab); - deleteAllChildren(); - addChildComponent (behindFrontTab); + deleteAndZero (extraTabsButton); + removeChildComponent (behindFrontTab); + deleteAllChildren(); + addChildComponent (behindFrontTab); - setCurrentTabIndex (-1); + setCurrentTabIndex (-1); } void TabbedButtonBar::addTab (const String& tabName, - const Colour& tabBackgroundColour, - int insertIndex) + const Colour& tabBackgroundColour, + int insertIndex) { - jassert (tabName.isNotEmpty()); // you have to give them all a name.. + jassert (tabName.isNotEmpty()); // you have to give them all a name.. - if (tabName.isNotEmpty()) - { - if (((unsigned int) insertIndex) > (unsigned int) tabs.size()) - insertIndex = tabs.size(); + if (tabName.isNotEmpty()) + { + if (((unsigned int) insertIndex) > (unsigned int) tabs.size()) + insertIndex = tabs.size(); - for (int i = tabs.size(); --i >= insertIndex;) - { - TabBarButton* const tb = getTabButton (i); + for (int i = tabs.size(); --i >= insertIndex;) + { + TabBarButton* const tb = getTabButton (i); - if (tb != 0) - tb->tabIndex++; - } + if (tb != 0) + tb->tabIndex++; + } - tabs.insert (insertIndex, tabName); - tabColours.insert (insertIndex, tabBackgroundColour); + tabs.insert (insertIndex, tabName); + tabColours.insert (insertIndex, tabBackgroundColour); - TabBarButton* const tb = createTabButton (tabName, insertIndex); - jassert (tb != 0); // your createTabButton() mustn't return zero! + TabBarButton* const tb = createTabButton (tabName, insertIndex); + jassert (tb != 0); // your createTabButton() mustn't return zero! - addAndMakeVisible (tb, insertIndex); + addAndMakeVisible (tb, insertIndex); - resized(); + resized(); - if (currentTabIndex < 0) - setCurrentTabIndex (0); - } + if (currentTabIndex < 0) + setCurrentTabIndex (0); + } } void TabbedButtonBar::setTabName (const int tabIndex, - const String& newName) + const String& newName) { - if (((unsigned int) tabIndex) < (unsigned int) tabs.size() - && tabs[tabIndex] != newName) - { - tabs.set (tabIndex, newName); + if (((unsigned int) tabIndex) < (unsigned int) tabs.size() + && tabs[tabIndex] != newName) + { + tabs.set (tabIndex, newName); - TabBarButton* const tb = getTabButton (tabIndex); + TabBarButton* const tb = getTabButton (tabIndex); - if (tb != 0) - tb->setButtonText (newName); + if (tb != 0) + tb->setButtonText (newName); - resized(); - } + resized(); + } } void TabbedButtonBar::removeTab (const int tabIndex) { - if (((unsigned int) tabIndex) < (unsigned int) tabs.size()) - { - const int oldTabIndex = currentTabIndex; - if (currentTabIndex == tabIndex) - currentTabIndex = -1; + if (((unsigned int) tabIndex) < (unsigned int) tabs.size()) + { + const int oldTabIndex = currentTabIndex; + if (currentTabIndex == tabIndex) + currentTabIndex = -1; - tabs.remove (tabIndex); - tabColours.remove (tabIndex); + tabs.remove (tabIndex); + tabColours.remove (tabIndex); - delete getTabButton (tabIndex); + delete getTabButton (tabIndex); - for (int i = tabIndex + 1; i <= tabs.size(); ++i) - { - TabBarButton* const tb = getTabButton (i); + for (int i = tabIndex + 1; i <= tabs.size(); ++i) + { + TabBarButton* const tb = getTabButton (i); - if (tb != 0) - tb->tabIndex--; - } + if (tb != 0) + tb->tabIndex--; + } - resized(); + resized(); - setCurrentTabIndex (jlimit (0, jmax (0, tabs.size() - 1), oldTabIndex)); - } + setCurrentTabIndex (jlimit (0, jmax (0, tabs.size() - 1), oldTabIndex)); + } } void TabbedButtonBar::moveTab (const int currentIndex, - const int newIndex) + const int newIndex) { - tabs.move (currentIndex, newIndex); - tabColours.move (currentIndex, newIndex); - resized(); + tabs.move (currentIndex, newIndex); + tabColours.move (currentIndex, newIndex); + resized(); } int TabbedButtonBar::getNumTabs() const { - return tabs.size(); + return tabs.size(); } const StringArray TabbedButtonBar::getTabNames() const { - return tabs; + return tabs; } void TabbedButtonBar::setCurrentTabIndex (int newIndex, const bool sendChangeMessage_) { - if (currentTabIndex != newIndex) - { - if (((unsigned int) newIndex) >= (unsigned int) tabs.size()) - newIndex = -1; + if (currentTabIndex != newIndex) + { + if (((unsigned int) newIndex) >= (unsigned int) tabs.size()) + newIndex = -1; - currentTabIndex = newIndex; + currentTabIndex = newIndex; - for (int i = 0; i < getNumChildComponents(); ++i) - { - TabBarButton* const tb = dynamic_cast (getChildComponent (i)); + for (int i = 0; i < getNumChildComponents(); ++i) + { + TabBarButton* const tb = dynamic_cast (getChildComponent (i)); - if (tb != 0) - tb->setToggleState (tb->tabIndex == newIndex, false); - } + if (tb != 0) + tb->setToggleState (tb->tabIndex == newIndex, false); + } - resized(); + resized(); - if (sendChangeMessage_) - sendChangeMessage (this); + if (sendChangeMessage_) + sendChangeMessage (this); - currentTabChanged (newIndex, newIndex >= 0 ? tabs [newIndex] : String::empty); - } + currentTabChanged (newIndex, newIndex >= 0 ? tabs [newIndex] : String::empty); + } } TabBarButton* TabbedButtonBar::getTabButton (const int index) const { - for (int i = getNumChildComponents(); --i >= 0;) - { - TabBarButton* const tb = dynamic_cast (getChildComponent (i)); + for (int i = getNumChildComponents(); --i >= 0;) + { + TabBarButton* const tb = dynamic_cast (getChildComponent (i)); - if (tb != 0 && tb->tabIndex == index) - return tb; - } + if (tb != 0 && tb->tabIndex == index) + return tb; + } - return 0; + return 0; } void TabbedButtonBar::lookAndFeelChanged() { - deleteAndZero (extraTabsButton); - resized(); + deleteAndZero (extraTabsButton); + resized(); } void TabbedButtonBar::resized() { - const double minimumScale = 0.7; - int depth = getWidth(); - int length = getHeight(); + const double minimumScale = 0.7; + int depth = getWidth(); + int length = getHeight(); - if (orientation == TabsAtTop || orientation == TabsAtBottom) - swapVariables (depth, length); + if (orientation == TabsAtTop || orientation == TabsAtBottom) + swapVariables (depth, length); - const int overlap = getLookAndFeel().getTabButtonOverlap (depth) - + getLookAndFeel().getTabButtonSpaceAroundImage() * 2; + const int overlap = getLookAndFeel().getTabButtonOverlap (depth) + + getLookAndFeel().getTabButtonSpaceAroundImage() * 2; - int i, totalLength = overlap; - int numVisibleButtons = tabs.size(); + int i, totalLength = overlap; + int numVisibleButtons = tabs.size(); - for (i = 0; i < getNumChildComponents(); ++i) - { - TabBarButton* const tb = dynamic_cast (getChildComponent (i)); + for (i = 0; i < getNumChildComponents(); ++i) + { + TabBarButton* const tb = dynamic_cast (getChildComponent (i)); - if (tb != 0) - { - totalLength += tb->getBestTabLength (depth) - overlap; - tb->overlapPixels = overlap / 2; - } - } + if (tb != 0) + { + totalLength += tb->getBestTabLength (depth) - overlap; + tb->overlapPixels = overlap / 2; + } + } - double scale = 1.0; + double scale = 1.0; - if (totalLength > length) - scale = jmax (minimumScale, length / (double) totalLength); + if (totalLength > length) + scale = jmax (minimumScale, length / (double) totalLength); - const bool isTooBig = totalLength * scale > length; - int tabsButtonPos = 0; + const bool isTooBig = totalLength * scale > length; + int tabsButtonPos = 0; - if (isTooBig) - { - if (extraTabsButton == 0) - { - addAndMakeVisible (extraTabsButton = getLookAndFeel().createTabBarExtrasButton()); - extraTabsButton->addButtonListener (this); - extraTabsButton->setAlwaysOnTop (true); - extraTabsButton->setTriggeredOnMouseDown (true); - } + if (isTooBig) + { + if (extraTabsButton == 0) + { + addAndMakeVisible (extraTabsButton = getLookAndFeel().createTabBarExtrasButton()); + extraTabsButton->addButtonListener (this); + extraTabsButton->setAlwaysOnTop (true); + extraTabsButton->setTriggeredOnMouseDown (true); + } - const int buttonSize = jmin (proportionOfWidth (0.7f), proportionOfHeight (0.7f)); - extraTabsButton->setSize (buttonSize, buttonSize); + const int buttonSize = jmin (proportionOfWidth (0.7f), proportionOfHeight (0.7f)); + extraTabsButton->setSize (buttonSize, buttonSize); - if (orientation == TabsAtTop || orientation == TabsAtBottom) - { - tabsButtonPos = getWidth() - buttonSize / 2 - 1; - extraTabsButton->setCentrePosition (tabsButtonPos, getHeight() / 2); - } - else - { - tabsButtonPos = getHeight() - buttonSize / 2 - 1; - extraTabsButton->setCentrePosition (getWidth() / 2, tabsButtonPos); - } + if (orientation == TabsAtTop || orientation == TabsAtBottom) + { + tabsButtonPos = getWidth() - buttonSize / 2 - 1; + extraTabsButton->setCentrePosition (tabsButtonPos, getHeight() / 2); + } + else + { + tabsButtonPos = getHeight() - buttonSize / 2 - 1; + extraTabsButton->setCentrePosition (getWidth() / 2, tabsButtonPos); + } - totalLength = 0; + totalLength = 0; - for (i = 0; i < tabs.size(); ++i) - { - TabBarButton* const tb = getTabButton (i); + for (i = 0; i < tabs.size(); ++i) + { + TabBarButton* const tb = getTabButton (i); - if (tb != 0) - { - const int newLength = totalLength + tb->getBestTabLength (depth); + if (tb != 0) + { + const int newLength = totalLength + tb->getBestTabLength (depth); - if (i > 0 && newLength * minimumScale > tabsButtonPos) - { - totalLength += overlap; - break; - } + if (i > 0 && newLength * minimumScale > tabsButtonPos) + { + totalLength += overlap; + break; + } - numVisibleButtons = i + 1; - totalLength = newLength - overlap; + numVisibleButtons = i + 1; + totalLength = newLength - overlap; - } - } + } + } - scale = jmax (minimumScale, tabsButtonPos / (double) totalLength); - } - else - { - deleteAndZero (extraTabsButton); - } + scale = jmax (minimumScale, tabsButtonPos / (double) totalLength); + } + else + { + deleteAndZero (extraTabsButton); + } - int pos = 0; + int pos = 0; - TabBarButton* frontTab = 0; + TabBarButton* frontTab = 0; - for (i = 0; i < tabs.size(); ++i) - { - TabBarButton* const tb = getTabButton (i); + for (i = 0; i < tabs.size(); ++i) + { + TabBarButton* const tb = getTabButton (i); - if (tb != 0) - { - const int bestLength = roundDoubleToInt (scale * tb->getBestTabLength (depth)); + if (tb != 0) + { + const int bestLength = roundToInt (scale * tb->getBestTabLength (depth)); - if (i < numVisibleButtons) - { - if (orientation == TabsAtTop || orientation == TabsAtBottom) - tb->setBounds (pos, 0, bestLength, getHeight()); - else - tb->setBounds (0, pos, getWidth(), bestLength); + if (i < numVisibleButtons) + { + if (orientation == TabsAtTop || orientation == TabsAtBottom) + tb->setBounds (pos, 0, bestLength, getHeight()); + else + tb->setBounds (0, pos, getWidth(), bestLength); - tb->toBack(); + tb->toBack(); - if (tb->tabIndex == currentTabIndex) - frontTab = tb; + if (tb->tabIndex == currentTabIndex) + frontTab = tb; - tb->setVisible (true); - } - else - { - tb->setVisible (false); - } + tb->setVisible (true); + } + else + { + tb->setVisible (false); + } - pos += bestLength - overlap; - } - } + pos += bestLength - overlap; + } + } - behindFrontTab->setBounds (0, 0, getWidth(), getHeight()); + behindFrontTab->setBounds (0, 0, getWidth(), getHeight()); - if (frontTab != 0) - { - frontTab->toFront (false); - behindFrontTab->toBehind (frontTab); - } + if (frontTab != 0) + { + frontTab->toFront (false); + behindFrontTab->toBehind (frontTab); + } } const Colour TabbedButtonBar::getTabBackgroundColour (const int tabIndex) { - return tabColours [tabIndex]; + return tabColours [tabIndex]; } void TabbedButtonBar::setTabBackgroundColour (const int tabIndex, const Colour& newColour) { - if (((unsigned int) tabIndex) < (unsigned int) tabColours.size() - && tabColours [tabIndex] != newColour) - { - tabColours.set (tabIndex, newColour); - repaint(); - } + if (((unsigned int) tabIndex) < (unsigned int) tabColours.size() + && tabColours [tabIndex] != newColour) + { + tabColours.set (tabIndex, newColour); + repaint(); + } } void TabbedButtonBar::buttonClicked (Button* button) { - if (extraTabsButton == button) - { - PopupMenu m; + if (extraTabsButton == button) + { + PopupMenu m; - for (int i = 0; i < tabs.size(); ++i) - { - TabBarButton* const tb = getTabButton (i); + for (int i = 0; i < tabs.size(); ++i) + { + TabBarButton* const tb = getTabButton (i); - if (tb != 0 && ! tb->isVisible()) - m.addItem (tb->tabIndex + 1, tabs[i], true, i == currentTabIndex); - } + if (tb != 0 && ! tb->isVisible()) + m.addItem (tb->tabIndex + 1, tabs[i], true, i == currentTabIndex); + } - const int res = m.showAt (extraTabsButton); + const int res = m.showAt (extraTabsButton); - if (res != 0) - setCurrentTabIndex (res - 1); - } + if (res != 0) + setCurrentTabIndex (res - 1); + } } void TabbedButtonBar::currentTabChanged (const int, const String&) @@ -63694,313 +63393,313 @@ BEGIN_JUCE_NAMESPACE class TabCompButtonBar : public TabbedButtonBar { public: - TabCompButtonBar (TabbedComponent* const owner_, - const TabbedButtonBar::Orientation orientation) - : TabbedButtonBar (orientation), - owner (owner_) - { - } + TabCompButtonBar (TabbedComponent* const owner_, + const TabbedButtonBar::Orientation orientation) + : TabbedButtonBar (orientation), + owner (owner_) + { + } - ~TabCompButtonBar() - { - } + ~TabCompButtonBar() + { + } - void currentTabChanged (const int newCurrentTabIndex, - const String& newTabName) - { - owner->changeCallback (newCurrentTabIndex, newTabName); - } + void currentTabChanged (const int newCurrentTabIndex, + const String& newTabName) + { + owner->changeCallback (newCurrentTabIndex, newTabName); + } - void popupMenuClickOnTab (const int tabIndex, - const String& tabName) - { - owner->popupMenuClickOnTab (tabIndex, tabName); - } + void popupMenuClickOnTab (const int tabIndex, + const String& tabName) + { + owner->popupMenuClickOnTab (tabIndex, tabName); + } - const Colour getTabBackgroundColour (const int tabIndex) - { - return owner->tabs->getTabBackgroundColour (tabIndex); - } + const Colour getTabBackgroundColour (const int tabIndex) + { + return owner->tabs->getTabBackgroundColour (tabIndex); + } - TabBarButton* createTabButton (const String& tabName, const int tabIndex) - { - return owner->createTabButton (tabName, tabIndex); - } + TabBarButton* createTabButton (const String& tabName, const int tabIndex) + { + return owner->createTabButton (tabName, tabIndex); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - TabbedComponent* const owner; + TabbedComponent* const owner; - TabCompButtonBar (const TabCompButtonBar&); - const TabCompButtonBar& operator= (const TabCompButtonBar&); + TabCompButtonBar (const TabCompButtonBar&); + const TabCompButtonBar& operator= (const TabCompButtonBar&); }; TabbedComponent::TabbedComponent (const TabbedButtonBar::Orientation orientation) - : panelComponent (0), - tabDepth (30), - outlineThickness (1), - edgeIndent (0) + : panelComponent (0), + tabDepth (30), + outlineThickness (1), + edgeIndent (0) { - addAndMakeVisible (tabs = new TabCompButtonBar (this, orientation)); + addAndMakeVisible (tabs = new TabCompButtonBar (this, orientation)); } TabbedComponent::~TabbedComponent() { - clearTabs(); - delete tabs; + clearTabs(); + delete tabs; } void TabbedComponent::setOrientation (const TabbedButtonBar::Orientation orientation) { - tabs->setOrientation (orientation); - resized(); + tabs->setOrientation (orientation); + resized(); } TabbedButtonBar::Orientation TabbedComponent::getOrientation() const throw() { - return tabs->getOrientation(); + return tabs->getOrientation(); } void TabbedComponent::setTabBarDepth (const int newDepth) { - if (tabDepth != newDepth) - { - tabDepth = newDepth; - resized(); - } + if (tabDepth != newDepth) + { + tabDepth = newDepth; + resized(); + } } TabBarButton* TabbedComponent::createTabButton (const String& tabName, const int tabIndex) { - return new TabBarButton (tabName, tabs, tabIndex); + return new TabBarButton (tabName, tabs, tabIndex); } void TabbedComponent::clearTabs() { - if (panelComponent != 0) - { - panelComponent->setVisible (false); - removeChildComponent (panelComponent); - panelComponent = 0; - } + if (panelComponent != 0) + { + panelComponent->setVisible (false); + removeChildComponent (panelComponent); + panelComponent = 0; + } - tabs->clearTabs(); + tabs->clearTabs(); - for (int i = contentComponents.size(); --i >= 0;) - { - Component* const c = contentComponents.getUnchecked(i); + for (int i = contentComponents.size(); --i >= 0;) + { + Component* const c = contentComponents.getUnchecked(i); - // be careful not to delete these components until they've been removed from the tab component - jassert (c == 0 || c->isValidComponent()); + // be careful not to delete these components until they've been removed from the tab component + jassert (c == 0 || c->isValidComponent()); - if (c != 0 && c->getComponentPropertyBool (T("deleteByTabComp_"), false, false)) - delete c; - } + if (c != 0 && c->getComponentPropertyBool (T("deleteByTabComp_"), false, false)) + delete c; + } - contentComponents.clear(); + contentComponents.clear(); } void TabbedComponent::addTab (const String& tabName, - const Colour& tabBackgroundColour, - Component* const contentComponent, - const bool deleteComponentWhenNotNeeded, - const int insertIndex) + const Colour& tabBackgroundColour, + Component* const contentComponent, + const bool deleteComponentWhenNotNeeded, + const int insertIndex) { - contentComponents.insert (insertIndex, contentComponent); + contentComponents.insert (insertIndex, contentComponent); - if (contentComponent != 0) - contentComponent->setComponentProperty (T("deleteByTabComp_"), deleteComponentWhenNotNeeded); + if (contentComponent != 0) + contentComponent->setComponentProperty (T("deleteByTabComp_"), deleteComponentWhenNotNeeded); - tabs->addTab (tabName, tabBackgroundColour, insertIndex); + tabs->addTab (tabName, tabBackgroundColour, insertIndex); } void TabbedComponent::setTabName (const int tabIndex, - const String& newName) + const String& newName) { - tabs->setTabName (tabIndex, newName); + tabs->setTabName (tabIndex, newName); } void TabbedComponent::removeTab (const int tabIndex) { - Component* const c = contentComponents [tabIndex]; + Component* const c = contentComponents [tabIndex]; - if (c != 0 && c->getComponentPropertyBool (T("deleteByTabComp_"), false, false)) - { - if (c == panelComponent) - panelComponent = 0; + if (c != 0 && c->getComponentPropertyBool (T("deleteByTabComp_"), false, false)) + { + if (c == panelComponent) + panelComponent = 0; - delete c; - } + delete c; + } - contentComponents.remove (tabIndex); + contentComponents.remove (tabIndex); - tabs->removeTab (tabIndex); + tabs->removeTab (tabIndex); } int TabbedComponent::getNumTabs() const { - return tabs->getNumTabs(); + return tabs->getNumTabs(); } const StringArray TabbedComponent::getTabNames() const { - return tabs->getTabNames(); + return tabs->getTabNames(); } Component* TabbedComponent::getTabContentComponent (const int tabIndex) const throw() { - return contentComponents [tabIndex]; + return contentComponents [tabIndex]; } const Colour TabbedComponent::getTabBackgroundColour (const int tabIndex) const throw() { - return tabs->getTabBackgroundColour (tabIndex); + return tabs->getTabBackgroundColour (tabIndex); } void TabbedComponent::setTabBackgroundColour (const int tabIndex, const Colour& newColour) { - tabs->setTabBackgroundColour (tabIndex, newColour); + tabs->setTabBackgroundColour (tabIndex, newColour); - if (getCurrentTabIndex() == tabIndex) - repaint(); + if (getCurrentTabIndex() == tabIndex) + repaint(); } void TabbedComponent::setCurrentTabIndex (const int newTabIndex, const bool sendChangeMessage) { - tabs->setCurrentTabIndex (newTabIndex, sendChangeMessage); + tabs->setCurrentTabIndex (newTabIndex, sendChangeMessage); } int TabbedComponent::getCurrentTabIndex() const { - return tabs->getCurrentTabIndex(); + return tabs->getCurrentTabIndex(); } const String& TabbedComponent::getCurrentTabName() const { - return tabs->getCurrentTabName(); + return tabs->getCurrentTabName(); } void TabbedComponent::setOutline (int thickness) { - outlineThickness = thickness; - repaint(); + outlineThickness = thickness; + repaint(); } void TabbedComponent::setIndent (const int indentThickness) { - edgeIndent = indentThickness; + edgeIndent = indentThickness; } void TabbedComponent::paint (Graphics& g) { - g.fillAll (findColour (backgroundColourId)); + g.fillAll (findColour (backgroundColourId)); - const TabbedButtonBar::Orientation o = getOrientation(); + const TabbedButtonBar::Orientation o = getOrientation(); - int x = 0; - int y = 0; - int r = getWidth(); - int b = getHeight(); + int x = 0; + int y = 0; + int r = getWidth(); + int b = getHeight(); - if (o == TabbedButtonBar::TabsAtTop) - y += tabDepth; - else if (o == TabbedButtonBar::TabsAtBottom) - b -= tabDepth; - else if (o == TabbedButtonBar::TabsAtLeft) - x += tabDepth; - else if (o == TabbedButtonBar::TabsAtRight) - r -= tabDepth; + if (o == TabbedButtonBar::TabsAtTop) + y += tabDepth; + else if (o == TabbedButtonBar::TabsAtBottom) + b -= tabDepth; + else if (o == TabbedButtonBar::TabsAtLeft) + x += tabDepth; + else if (o == TabbedButtonBar::TabsAtRight) + r -= tabDepth; - g.reduceClipRegion (x, y, r - x, b - y); - g.fillAll (tabs->getTabBackgroundColour (getCurrentTabIndex())); + g.reduceClipRegion (x, y, r - x, b - y); + g.fillAll (tabs->getTabBackgroundColour (getCurrentTabIndex())); - if (outlineThickness > 0) - { - if (o == TabbedButtonBar::TabsAtTop) - --y; - else if (o == TabbedButtonBar::TabsAtBottom) - ++b; - else if (o == TabbedButtonBar::TabsAtLeft) - --x; - else if (o == TabbedButtonBar::TabsAtRight) - ++r; + if (outlineThickness > 0) + { + if (o == TabbedButtonBar::TabsAtTop) + --y; + else if (o == TabbedButtonBar::TabsAtBottom) + ++b; + else if (o == TabbedButtonBar::TabsAtLeft) + --x; + else if (o == TabbedButtonBar::TabsAtRight) + ++r; - g.setColour (findColour (outlineColourId)); - g.drawRect (x, y, r - x, b - y, outlineThickness); - } + g.setColour (findColour (outlineColourId)); + g.drawRect (x, y, r - x, b - y, outlineThickness); + } } void TabbedComponent::resized() { - const TabbedButtonBar::Orientation o = getOrientation(); - const int indent = edgeIndent + outlineThickness; - BorderSize indents (indent); + const TabbedButtonBar::Orientation o = getOrientation(); + const int indent = edgeIndent + outlineThickness; + BorderSize indents (indent); - if (o == TabbedButtonBar::TabsAtTop) - { - tabs->setBounds (0, 0, getWidth(), tabDepth); - indents.setTop (tabDepth + edgeIndent); - } - else if (o == TabbedButtonBar::TabsAtBottom) - { - tabs->setBounds (0, getHeight() - tabDepth, getWidth(), tabDepth); - indents.setBottom (tabDepth + edgeIndent); - } - else if (o == TabbedButtonBar::TabsAtLeft) - { - tabs->setBounds (0, 0, tabDepth, getHeight()); - indents.setLeft (tabDepth + edgeIndent); - } - else if (o == TabbedButtonBar::TabsAtRight) - { - tabs->setBounds (getWidth() - tabDepth, 0, tabDepth, getHeight()); - indents.setRight (tabDepth + edgeIndent); - } + if (o == TabbedButtonBar::TabsAtTop) + { + tabs->setBounds (0, 0, getWidth(), tabDepth); + indents.setTop (tabDepth + edgeIndent); + } + else if (o == TabbedButtonBar::TabsAtBottom) + { + tabs->setBounds (0, getHeight() - tabDepth, getWidth(), tabDepth); + indents.setBottom (tabDepth + edgeIndent); + } + else if (o == TabbedButtonBar::TabsAtLeft) + { + tabs->setBounds (0, 0, tabDepth, getHeight()); + indents.setLeft (tabDepth + edgeIndent); + } + else if (o == TabbedButtonBar::TabsAtRight) + { + tabs->setBounds (getWidth() - tabDepth, 0, tabDepth, getHeight()); + indents.setRight (tabDepth + edgeIndent); + } - const Rectangle bounds (indents.subtractedFrom (Rectangle (0, 0, getWidth(), getHeight()))); + const Rectangle bounds (indents.subtractedFrom (Rectangle (0, 0, getWidth(), getHeight()))); - for (int i = contentComponents.size(); --i >= 0;) - if (contentComponents.getUnchecked (i) != 0) - contentComponents.getUnchecked (i)->setBounds (bounds); + for (int i = contentComponents.size(); --i >= 0;) + if (contentComponents.getUnchecked (i) != 0) + contentComponents.getUnchecked (i)->setBounds (bounds); } void TabbedComponent::lookAndFeelChanged() { - for (int i = contentComponents.size(); --i >= 0;) - if (contentComponents.getUnchecked (i) != 0) - contentComponents.getUnchecked (i)->lookAndFeelChanged(); + for (int i = contentComponents.size(); --i >= 0;) + if (contentComponents.getUnchecked (i) != 0) + contentComponents.getUnchecked (i)->lookAndFeelChanged(); } void TabbedComponent::changeCallback (const int newCurrentTabIndex, - const String& newTabName) + const String& newTabName) { - if (panelComponent != 0) - { - panelComponent->setVisible (false); - removeChildComponent (panelComponent); - panelComponent = 0; - } + if (panelComponent != 0) + { + panelComponent->setVisible (false); + removeChildComponent (panelComponent); + panelComponent = 0; + } - if (getCurrentTabIndex() >= 0) - { - panelComponent = contentComponents [getCurrentTabIndex()]; + if (getCurrentTabIndex() >= 0) + { + panelComponent = contentComponents [getCurrentTabIndex()]; - if (panelComponent != 0) - { - // do these ops as two stages instead of addAndMakeVisible() so that the - // component has always got a parent when it gets the visibilityChanged() callback - addChildComponent (panelComponent); - panelComponent->setVisible (true); - panelComponent->toFront (true); - } + if (panelComponent != 0) + { + // do these ops as two stages instead of addAndMakeVisible() so that the + // component has always got a parent when it gets the visibilityChanged() callback + addChildComponent (panelComponent); + panelComponent->setVisible (true); + panelComponent->toFront (true); + } - repaint(); - } + repaint(); + } - resized(); + resized(); - currentTabChanged (newCurrentTabIndex, newTabName); + currentTabChanged (newCurrentTabIndex, newTabName); } void TabbedComponent::currentTabChanged (const int, const String&) @@ -64020,38 +63719,38 @@ BEGIN_JUCE_NAMESPACE Viewport::Viewport (const String& componentName) : Component (componentName), - contentComp (0), - lastVX (0), - lastVY (0), - lastVW (0), - lastVH (0), - scrollBarThickness (0), - singleStepX (16), - singleStepY (16), - showHScrollbar (true), - showVScrollbar (true) + contentComp (0), + lastVX (0), + lastVY (0), + lastVW (0), + lastVH (0), + scrollBarThickness (0), + singleStepX (16), + singleStepY (16), + showHScrollbar (true), + showVScrollbar (true) { - // content holder is used to clip the contents so they don't overlap the scrollbars - addAndMakeVisible (contentHolder = new Component()); - contentHolder->setInterceptsMouseClicks (false, true); + // content holder is used to clip the contents so they don't overlap the scrollbars + addAndMakeVisible (contentHolder = new Component()); + contentHolder->setInterceptsMouseClicks (false, true); - verticalScrollBar = new ScrollBar (true); - horizontalScrollBar = new ScrollBar (false); + verticalScrollBar = new ScrollBar (true); + horizontalScrollBar = new ScrollBar (false); - addChildComponent (verticalScrollBar); - addChildComponent (horizontalScrollBar); + addChildComponent (verticalScrollBar); + addChildComponent (horizontalScrollBar); - verticalScrollBar->addListener (this); - horizontalScrollBar->addListener (this); + verticalScrollBar->addListener (this); + horizontalScrollBar->addListener (this); - setInterceptsMouseClicks (false, true); - setWantsKeyboardFocus (true); + setInterceptsMouseClicks (false, true); + setWantsKeyboardFocus (true); } Viewport::~Viewport() { - contentHolder->deleteAllChildren(); - deleteAllChildren(); + contentHolder->deleteAllChildren(); + deleteAllChildren(); } void Viewport::visibleAreaChanged (int, int, int, int) @@ -64060,277 +63759,277 @@ void Viewport::visibleAreaChanged (int, int, int, int) void Viewport::setViewedComponent (Component* const newViewedComponent) { - if (contentComp != newViewedComponent) - { - if (contentComp->isValidComponent()) - { - Component* const oldComp = contentComp; - contentComp = 0; - delete oldComp; - } + if (contentComp != newViewedComponent) + { + if (contentComp->isValidComponent()) + { + Component* const oldComp = contentComp; + contentComp = 0; + delete oldComp; + } - contentComp = newViewedComponent; + contentComp = newViewedComponent; - if (contentComp != 0) - { - contentComp->setTopLeftPosition (0, 0); - contentHolder->addAndMakeVisible (contentComp); - contentComp->addComponentListener (this); - } + if (contentComp != 0) + { + contentComp->setTopLeftPosition (0, 0); + contentHolder->addAndMakeVisible (contentComp); + contentComp->addComponentListener (this); + } - updateVisibleRegion(); - } + updateVisibleRegion(); + } } int Viewport::getMaximumVisibleWidth() const throw() { - return jmax (0, getWidth() - (verticalScrollBar->isVisible() ? getScrollBarThickness() : 0)); + return jmax (0, getWidth() - (verticalScrollBar->isVisible() ? getScrollBarThickness() : 0)); } int Viewport::getMaximumVisibleHeight() const throw() { - return jmax (0, getHeight() - (horizontalScrollBar->isVisible() ? getScrollBarThickness() : 0)); + return jmax (0, getHeight() - (horizontalScrollBar->isVisible() ? getScrollBarThickness() : 0)); } void Viewport::setViewPosition (const int xPixelsOffset, - const int yPixelsOffset) + const int yPixelsOffset) { - if (contentComp != 0) - contentComp->setTopLeftPosition (-xPixelsOffset, - -yPixelsOffset); + if (contentComp != 0) + contentComp->setTopLeftPosition (-xPixelsOffset, + -yPixelsOffset); } void Viewport::setViewPositionProportionately (const double x, - const double y) + const double y) { - if (contentComp != 0) - setViewPosition (jmax (0, roundDoubleToInt (x * (contentComp->getWidth() - getWidth()))), - jmax (0, roundDoubleToInt (y * (contentComp->getHeight() - getHeight())))); + if (contentComp != 0) + setViewPosition (jmax (0, roundToInt (x * (contentComp->getWidth() - getWidth()))), + jmax (0, roundToInt (y * (contentComp->getHeight() - getHeight())))); } bool Viewport::autoScroll (int mouseX, int mouseY, int activeBorderThickness, int maximumSpeed) { - if (contentComp != 0) - { - int dx = 0, dy = 0; + if (contentComp != 0) + { + int dx = 0, dy = 0; - if (mouseX < activeBorderThickness) - dx = activeBorderThickness - mouseX; - else if (mouseX >= contentHolder->getWidth() - activeBorderThickness) - dx = (contentHolder->getWidth() - activeBorderThickness) - mouseX; + if (mouseX < activeBorderThickness) + dx = activeBorderThickness - mouseX; + else if (mouseX >= contentHolder->getWidth() - activeBorderThickness) + dx = (contentHolder->getWidth() - activeBorderThickness) - mouseX; - if (dx < 0) - dx = jmax (dx, -maximumSpeed, contentHolder->getWidth() - contentComp->getRight()); - else - dx = jmin (dx, maximumSpeed, -contentComp->getX()); + if (dx < 0) + dx = jmax (dx, -maximumSpeed, contentHolder->getWidth() - contentComp->getRight()); + else + dx = jmin (dx, maximumSpeed, -contentComp->getX()); - if (mouseY < activeBorderThickness) - dy = activeBorderThickness - mouseY; - else if (mouseY >= contentHolder->getHeight() - activeBorderThickness) - dy = (contentHolder->getHeight() - activeBorderThickness) - mouseY; + if (mouseY < activeBorderThickness) + dy = activeBorderThickness - mouseY; + else if (mouseY >= contentHolder->getHeight() - activeBorderThickness) + dy = (contentHolder->getHeight() - activeBorderThickness) - mouseY; - if (dy < 0) - dy = jmax (dy, -maximumSpeed, contentHolder->getHeight() - contentComp->getBottom()); - else - dy = jmin (dy, maximumSpeed, -contentComp->getY()); + if (dy < 0) + dy = jmax (dy, -maximumSpeed, contentHolder->getHeight() - contentComp->getBottom()); + else + dy = jmin (dy, maximumSpeed, -contentComp->getY()); - if (dx != 0 || dy != 0) - { - contentComp->setTopLeftPosition (contentComp->getX() + dx, - contentComp->getY() + dy); + if (dx != 0 || dy != 0) + { + contentComp->setTopLeftPosition (contentComp->getX() + dx, + contentComp->getY() + dy); - return true; - } - } + return true; + } + } - return false; + return false; } void Viewport::componentMovedOrResized (Component&, bool, bool) { - updateVisibleRegion(); + updateVisibleRegion(); } void Viewport::resized() { - updateVisibleRegion(); + updateVisibleRegion(); } void Viewport::updateVisibleRegion() { - if (contentComp != 0) - { - const int newVX = -contentComp->getX(); - const int newVY = -contentComp->getY(); + if (contentComp != 0) + { + const int newVX = -contentComp->getX(); + const int newVY = -contentComp->getY(); - if (newVX == 0 && newVY == 0 - && contentComp->getWidth() <= getWidth() - && contentComp->getHeight() <= getHeight()) - { - horizontalScrollBar->setVisible (false); - verticalScrollBar->setVisible (false); - } + if (newVX == 0 && newVY == 0 + && contentComp->getWidth() <= getWidth() + && contentComp->getHeight() <= getHeight()) + { + horizontalScrollBar->setVisible (false); + verticalScrollBar->setVisible (false); + } - horizontalScrollBar->setRangeLimits (0.0, contentComp->getWidth()); - horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); - horizontalScrollBar->setSingleStepSize (singleStepX); + horizontalScrollBar->setRangeLimits (0.0, contentComp->getWidth()); + horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); + horizontalScrollBar->setSingleStepSize (singleStepX); - if (! (contentComp->getWidth() > 0 && showHScrollbar && getHeight() > getScrollBarThickness())) - horizontalScrollBar->setVisible (false); + if (! (contentComp->getWidth() > 0 && showHScrollbar && getHeight() > getScrollBarThickness())) + horizontalScrollBar->setVisible (false); - verticalScrollBar->setRangeLimits (0.0, contentComp->getHeight()); - verticalScrollBar->setCurrentRange (newVY, getMaximumVisibleHeight()); - verticalScrollBar->setSingleStepSize (singleStepY); + verticalScrollBar->setRangeLimits (0.0, contentComp->getHeight()); + verticalScrollBar->setCurrentRange (newVY, getMaximumVisibleHeight()); + verticalScrollBar->setSingleStepSize (singleStepY); - if (! (contentComp->getHeight() > 0 && showVScrollbar && getWidth() > getScrollBarThickness())) - verticalScrollBar->setVisible (false); + if (! (contentComp->getHeight() > 0 && showVScrollbar && getWidth() > getScrollBarThickness())) + verticalScrollBar->setVisible (false); - if (verticalScrollBar->isVisible()) - { - horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); - verticalScrollBar->setCurrentRange (newVY, getMaximumVisibleHeight()); + if (verticalScrollBar->isVisible()) + { + horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); + verticalScrollBar->setCurrentRange (newVY, getMaximumVisibleHeight()); - verticalScrollBar - ->setBounds (getMaximumVisibleWidth(), 0, - getScrollBarThickness(), getMaximumVisibleHeight()); - } + verticalScrollBar + ->setBounds (getMaximumVisibleWidth(), 0, + getScrollBarThickness(), getMaximumVisibleHeight()); + } - if (horizontalScrollBar->isVisible()) - { - horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); + if (horizontalScrollBar->isVisible()) + { + horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth()); - horizontalScrollBar - ->setBounds (0, getMaximumVisibleHeight(), - getMaximumVisibleWidth(), getScrollBarThickness()); - } + horizontalScrollBar + ->setBounds (0, getMaximumVisibleHeight(), + getMaximumVisibleWidth(), getScrollBarThickness()); + } - contentHolder->setSize (getMaximumVisibleWidth(), - getMaximumVisibleHeight()); + contentHolder->setSize (getMaximumVisibleWidth(), + getMaximumVisibleHeight()); - const int newVW = jmin (contentComp->getRight(), getMaximumVisibleWidth()); - const int newVH = jmin (contentComp->getBottom(), getMaximumVisibleHeight()); + const int newVW = jmin (contentComp->getRight(), getMaximumVisibleWidth()); + const int newVH = jmin (contentComp->getBottom(), getMaximumVisibleHeight()); - if (newVX != lastVX - || newVY != lastVY - || newVW != lastVW - || newVH != lastVH) - { - lastVX = newVX; - lastVY = newVY; - lastVW = newVW; - lastVH = newVH; + if (newVX != lastVX + || newVY != lastVY + || newVW != lastVW + || newVH != lastVH) + { + lastVX = newVX; + lastVY = newVY; + lastVW = newVW; + lastVH = newVH; - visibleAreaChanged (newVX, newVY, newVW, newVH); - } + visibleAreaChanged (newVX, newVY, newVW, newVH); + } - horizontalScrollBar->handleUpdateNowIfNeeded(); - verticalScrollBar->handleUpdateNowIfNeeded(); - } - else - { - horizontalScrollBar->setVisible (false); - verticalScrollBar->setVisible (false); - } + horizontalScrollBar->handleUpdateNowIfNeeded(); + verticalScrollBar->handleUpdateNowIfNeeded(); + } + else + { + horizontalScrollBar->setVisible (false); + verticalScrollBar->setVisible (false); + } } void Viewport::setSingleStepSizes (const int stepX, - const int stepY) + const int stepY) { - singleStepX = stepX; - singleStepY = stepY; - updateVisibleRegion(); + singleStepX = stepX; + singleStepY = stepY; + updateVisibleRegion(); } void Viewport::setScrollBarsShown (const bool showVerticalScrollbarIfNeeded, - const bool showHorizontalScrollbarIfNeeded) + const bool showHorizontalScrollbarIfNeeded) { - showVScrollbar = showVerticalScrollbarIfNeeded; - showHScrollbar = showHorizontalScrollbarIfNeeded; - updateVisibleRegion(); + showVScrollbar = showVerticalScrollbarIfNeeded; + showHScrollbar = showHorizontalScrollbarIfNeeded; + updateVisibleRegion(); } void Viewport::setScrollBarThickness (const int thickness) { - scrollBarThickness = thickness; - updateVisibleRegion(); + scrollBarThickness = thickness; + updateVisibleRegion(); } int Viewport::getScrollBarThickness() const throw() { - return (scrollBarThickness > 0) ? scrollBarThickness - : getLookAndFeel().getDefaultScrollbarWidth(); + return (scrollBarThickness > 0) ? scrollBarThickness + : getLookAndFeel().getDefaultScrollbarWidth(); } void Viewport::setScrollBarButtonVisibility (const bool buttonsVisible) { - verticalScrollBar->setButtonVisibility (buttonsVisible); - horizontalScrollBar->setButtonVisibility (buttonsVisible); + verticalScrollBar->setButtonVisibility (buttonsVisible); + horizontalScrollBar->setButtonVisibility (buttonsVisible); } void Viewport::scrollBarMoved (ScrollBar* scrollBarThatHasMoved, const double newRangeStart) { - if (scrollBarThatHasMoved == horizontalScrollBar) - { - setViewPosition (roundDoubleToInt (newRangeStart), getViewPositionY()); - } - else if (scrollBarThatHasMoved == verticalScrollBar) - { - setViewPosition (getViewPositionX(), roundDoubleToInt (newRangeStart)); - } + if (scrollBarThatHasMoved == horizontalScrollBar) + { + setViewPosition (roundToInt (newRangeStart), getViewPositionY()); + } + else if (scrollBarThatHasMoved == verticalScrollBar) + { + setViewPosition (getViewPositionX(), roundToInt (newRangeStart)); + } } void Viewport::mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY) { - if (! useMouseWheelMoveIfNeeded (e, wheelIncrementX, wheelIncrementY)) - Component::mouseWheelMove (e, wheelIncrementX, wheelIncrementY); + if (! useMouseWheelMoveIfNeeded (e, wheelIncrementX, wheelIncrementY)) + Component::mouseWheelMove (e, wheelIncrementX, wheelIncrementY); } bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY) { - if (! (e.mods.isAltDown() || e.mods.isCtrlDown())) - { - const bool hasVertBar = verticalScrollBar->isVisible(); - const bool hasHorzBar = horizontalScrollBar->isVisible(); + if (! (e.mods.isAltDown() || e.mods.isCtrlDown())) + { + const bool hasVertBar = verticalScrollBar->isVisible(); + const bool hasHorzBar = horizontalScrollBar->isVisible(); - if (hasHorzBar && (wheelIncrementX != 0 || e.mods.isShiftDown() || ! hasVertBar)) - { - if (wheelIncrementX == 0 && ! hasVertBar) - wheelIncrementX = wheelIncrementY; + if (hasHorzBar && (wheelIncrementX != 0 || e.mods.isShiftDown() || ! hasVertBar)) + { + if (wheelIncrementX == 0 && ! hasVertBar) + wheelIncrementX = wheelIncrementY; - horizontalScrollBar->mouseWheelMove (e.getEventRelativeTo (horizontalScrollBar), - wheelIncrementX, wheelIncrementY); - return true; - } - else if (hasVertBar && wheelIncrementY != 0) - { - verticalScrollBar->mouseWheelMove (e.getEventRelativeTo (verticalScrollBar), - wheelIncrementX, wheelIncrementY); - return true; - } - } + horizontalScrollBar->mouseWheelMove (e.getEventRelativeTo (horizontalScrollBar), + wheelIncrementX, wheelIncrementY); + return true; + } + else if (hasVertBar && wheelIncrementY != 0) + { + verticalScrollBar->mouseWheelMove (e.getEventRelativeTo (verticalScrollBar), + wheelIncrementX, wheelIncrementY); + return true; + } + } - return false; + return false; } bool Viewport::keyPressed (const KeyPress& key) { - const bool isUpDownKey = key.isKeyCode (KeyPress::upKey) - || key.isKeyCode (KeyPress::downKey) - || key.isKeyCode (KeyPress::pageUpKey) - || key.isKeyCode (KeyPress::pageDownKey) - || key.isKeyCode (KeyPress::homeKey) - || key.isKeyCode (KeyPress::endKey); + const bool isUpDownKey = key.isKeyCode (KeyPress::upKey) + || key.isKeyCode (KeyPress::downKey) + || key.isKeyCode (KeyPress::pageUpKey) + || key.isKeyCode (KeyPress::pageDownKey) + || key.isKeyCode (KeyPress::homeKey) + || key.isKeyCode (KeyPress::endKey); - if (verticalScrollBar->isVisible() && isUpDownKey) - return verticalScrollBar->keyPressed (key); + if (verticalScrollBar->isVisible() && isUpDownKey) + return verticalScrollBar->keyPressed (key); - const bool isLeftRightKey = key.isKeyCode (KeyPress::leftKey) - || key.isKeyCode (KeyPress::rightKey); + const bool isLeftRightKey = key.isKeyCode (KeyPress::leftKey) + || key.isKeyCode (KeyPress::rightKey); - if (horizontalScrollBar->isVisible() && (isUpDownKey || isLeftRightKey)) - return horizontalScrollBar->keyPressed (key); + if (horizontalScrollBar->isVisible() && (isUpDownKey || isLeftRightKey)) + return horizontalScrollBar->keyPressed (key); - return false; + return false; } END_JUCE_NAMESPACE @@ -64341,170 +64040,170 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE static const Colour createBaseColour (const Colour& buttonColour, - const bool hasKeyboardFocus, - const bool isMouseOverButton, - const bool isButtonDown) throw() + const bool hasKeyboardFocus, + const bool isMouseOverButton, + const bool isButtonDown) throw() { - const float sat = hasKeyboardFocus ? 1.3f : 0.9f; - const Colour baseColour (buttonColour.withMultipliedSaturation (sat)); + const float sat = hasKeyboardFocus ? 1.3f : 0.9f; + const Colour baseColour (buttonColour.withMultipliedSaturation (sat)); - if (isButtonDown) - return baseColour.contrasting (0.2f); - else if (isMouseOverButton) - return baseColour.contrasting (0.1f); + if (isButtonDown) + return baseColour.contrasting (0.2f); + else if (isMouseOverButton) + return baseColour.contrasting (0.1f); - return baseColour; + return baseColour; } static String defaultSansName, defaultSerifName, defaultFixedName; void clearUpDefaultFontNames() throw() { - defaultSansName = String::empty; - defaultSerifName = String::empty; - defaultFixedName = String::empty; + defaultSansName = String::empty; + defaultSerifName = String::empty; + defaultFixedName = String::empty; } LookAndFeel::LookAndFeel() { - /* if this fails it means you're trying to create a LookAndFeel object before - the static Colours have been initialised. That ain't gonna work. It probably - means that you're using a static LookAndFeel object and that your compiler has - decided to intialise it before the Colours class. - */ - jassert (Colours::white == Colour (0xffffffff)); + /* if this fails it means you're trying to create a LookAndFeel object before + the static Colours have been initialised. That ain't gonna work. It probably + means that you're using a static LookAndFeel object and that your compiler has + decided to intialise it before the Colours class. + */ + jassert (Colours::white == Colour (0xffffffff)); - // set up the standard set of colours.. - const int textButtonColour = 0xffbbbbff; - const int textHighlightColour = 0x401111ee; - const int standardOutlineColour = 0xb2808080; + // set up the standard set of colours.. + const int textButtonColour = 0xffbbbbff; + const int textHighlightColour = 0x401111ee; + const int standardOutlineColour = 0xb2808080; - static const int standardColours[] = - { - TextButton::buttonColourId, textButtonColour, - TextButton::buttonOnColourId, 0xff4444ff, - TextButton::textColourOnId, 0xff000000, - TextButton::textColourOffId, 0xff000000, + static const int standardColours[] = + { + TextButton::buttonColourId, textButtonColour, + TextButton::buttonOnColourId, 0xff4444ff, + TextButton::textColourOnId, 0xff000000, + TextButton::textColourOffId, 0xff000000, - ComboBox::buttonColourId, 0xffbbbbff, - ComboBox::outlineColourId, standardOutlineColour, + ComboBox::buttonColourId, 0xffbbbbff, + ComboBox::outlineColourId, standardOutlineColour, - ToggleButton::textColourId, 0xff000000, + ToggleButton::textColourId, 0xff000000, - TextEditor::backgroundColourId, 0xffffffff, - TextEditor::textColourId, 0xff000000, - TextEditor::highlightColourId, textHighlightColour, - TextEditor::highlightedTextColourId, 0xff000000, - TextEditor::caretColourId, 0xff000000, - TextEditor::outlineColourId, 0x00000000, - TextEditor::focusedOutlineColourId, textButtonColour, - TextEditor::shadowColourId, 0x38000000, + TextEditor::backgroundColourId, 0xffffffff, + TextEditor::textColourId, 0xff000000, + TextEditor::highlightColourId, textHighlightColour, + TextEditor::highlightedTextColourId, 0xff000000, + TextEditor::caretColourId, 0xff000000, + TextEditor::outlineColourId, 0x00000000, + TextEditor::focusedOutlineColourId, textButtonColour, + TextEditor::shadowColourId, 0x38000000, - Label::backgroundColourId, 0x00000000, - Label::textColourId, 0xff000000, - Label::outlineColourId, 0x00000000, + Label::backgroundColourId, 0x00000000, + Label::textColourId, 0xff000000, + Label::outlineColourId, 0x00000000, - ScrollBar::backgroundColourId, 0x00000000, - ScrollBar::thumbColourId, 0xffffffff, - ScrollBar::trackColourId, 0xffffffff, + ScrollBar::backgroundColourId, 0x00000000, + ScrollBar::thumbColourId, 0xffffffff, + ScrollBar::trackColourId, 0xffffffff, - TreeView::linesColourId, 0x4c000000, - TreeView::backgroundColourId, 0x00000000, - TreeView::dragAndDropIndicatorColourId, 0x80ff0000, + TreeView::linesColourId, 0x4c000000, + TreeView::backgroundColourId, 0x00000000, + TreeView::dragAndDropIndicatorColourId, 0x80ff0000, - PopupMenu::backgroundColourId, 0xffffffff, - PopupMenu::textColourId, 0xff000000, - PopupMenu::headerTextColourId, 0xff000000, - PopupMenu::highlightedTextColourId, 0xffffffff, - PopupMenu::highlightedBackgroundColourId, 0x991111aa, + PopupMenu::backgroundColourId, 0xffffffff, + PopupMenu::textColourId, 0xff000000, + PopupMenu::headerTextColourId, 0xff000000, + PopupMenu::highlightedTextColourId, 0xffffffff, + PopupMenu::highlightedBackgroundColourId, 0x991111aa, - ComboBox::textColourId, 0xff000000, - ComboBox::backgroundColourId, 0xffffffff, - ComboBox::arrowColourId, 0x99000000, + ComboBox::textColourId, 0xff000000, + ComboBox::backgroundColourId, 0xffffffff, + ComboBox::arrowColourId, 0x99000000, - ListBox::backgroundColourId, 0xffffffff, - ListBox::outlineColourId, standardOutlineColour, - ListBox::textColourId, 0xff000000, + ListBox::backgroundColourId, 0xffffffff, + ListBox::outlineColourId, standardOutlineColour, + ListBox::textColourId, 0xff000000, - Slider::backgroundColourId, 0x00000000, - Slider::thumbColourId, textButtonColour, - Slider::trackColourId, 0x7fffffff, - Slider::rotarySliderFillColourId, 0x7f0000ff, - Slider::rotarySliderOutlineColourId, 0x66000000, - Slider::textBoxTextColourId, 0xff000000, - Slider::textBoxBackgroundColourId, 0xffffffff, - Slider::textBoxHighlightColourId, textHighlightColour, - Slider::textBoxOutlineColourId, standardOutlineColour, + Slider::backgroundColourId, 0x00000000, + Slider::thumbColourId, textButtonColour, + Slider::trackColourId, 0x7fffffff, + Slider::rotarySliderFillColourId, 0x7f0000ff, + Slider::rotarySliderOutlineColourId, 0x66000000, + Slider::textBoxTextColourId, 0xff000000, + Slider::textBoxBackgroundColourId, 0xffffffff, + Slider::textBoxHighlightColourId, textHighlightColour, + Slider::textBoxOutlineColourId, standardOutlineColour, - ResizableWindow::backgroundColourId, 0xff777777, - //DocumentWindow::textColourId, 0xff000000, // (this is deliberately not set) + ResizableWindow::backgroundColourId, 0xff777777, + //DocumentWindow::textColourId, 0xff000000, // (this is deliberately not set) - AlertWindow::backgroundColourId, 0xffededed, - AlertWindow::textColourId, 0xff000000, - AlertWindow::outlineColourId, 0xff666666, + AlertWindow::backgroundColourId, 0xffededed, + AlertWindow::textColourId, 0xff000000, + AlertWindow::outlineColourId, 0xff666666, - ProgressBar::backgroundColourId, 0xffeeeeee, - ProgressBar::foregroundColourId, 0xffaaaaee, + ProgressBar::backgroundColourId, 0xffeeeeee, + ProgressBar::foregroundColourId, 0xffaaaaee, - TooltipWindow::backgroundColourId, 0xffeeeebb, - TooltipWindow::textColourId, 0xff000000, - TooltipWindow::outlineColourId, 0x4c000000, + TooltipWindow::backgroundColourId, 0xffeeeebb, + TooltipWindow::textColourId, 0xff000000, + TooltipWindow::outlineColourId, 0x4c000000, - TabbedComponent::backgroundColourId, 0x00000000, - TabbedComponent::outlineColourId, 0xff777777, - TabbedButtonBar::tabOutlineColourId, 0x80000000, - TabbedButtonBar::frontOutlineColourId, 0x90000000, + TabbedComponent::backgroundColourId, 0x00000000, + TabbedComponent::outlineColourId, 0xff777777, + TabbedButtonBar::tabOutlineColourId, 0x80000000, + TabbedButtonBar::frontOutlineColourId, 0x90000000, - Toolbar::backgroundColourId, 0xfff6f8f9, - Toolbar::separatorColourId, 0x4c000000, - Toolbar::buttonMouseOverBackgroundColourId, 0x4c0000ff, - Toolbar::buttonMouseDownBackgroundColourId, 0x800000ff, - Toolbar::labelTextColourId, 0xff000000, - Toolbar::editingModeOutlineColourId, 0xffff0000, + Toolbar::backgroundColourId, 0xfff6f8f9, + Toolbar::separatorColourId, 0x4c000000, + Toolbar::buttonMouseOverBackgroundColourId, 0x4c0000ff, + Toolbar::buttonMouseDownBackgroundColourId, 0x800000ff, + Toolbar::labelTextColourId, 0xff000000, + Toolbar::editingModeOutlineColourId, 0xffff0000, - HyperlinkButton::textColourId, 0xcc1111ee, + HyperlinkButton::textColourId, 0xcc1111ee, - GroupComponent::outlineColourId, 0x66000000, - GroupComponent::textColourId, 0xff000000, + GroupComponent::outlineColourId, 0x66000000, + GroupComponent::textColourId, 0xff000000, - DirectoryContentsDisplayComponent::highlightColourId, textHighlightColour, - DirectoryContentsDisplayComponent::textColourId, 0xff000000, + DirectoryContentsDisplayComponent::highlightColourId, textHighlightColour, + DirectoryContentsDisplayComponent::textColourId, 0xff000000, - 0x1000440, /*LassoComponent::lassoFillColourId*/ 0x66dddddd, - 0x1000441, /*LassoComponent::lassoOutlineColourId*/ 0x99111111, + 0x1000440, /*LassoComponent::lassoFillColourId*/ 0x66dddddd, + 0x1000441, /*LassoComponent::lassoOutlineColourId*/ 0x99111111, - MidiKeyboardComponent::whiteNoteColourId, 0xffffffff, - MidiKeyboardComponent::blackNoteColourId, 0xff000000, - MidiKeyboardComponent::keySeparatorLineColourId, 0x66000000, - MidiKeyboardComponent::mouseOverKeyOverlayColourId, 0x80ffff00, - MidiKeyboardComponent::keyDownOverlayColourId, 0xffb6b600, - MidiKeyboardComponent::textLabelColourId, 0xff000000, - MidiKeyboardComponent::upDownButtonBackgroundColourId, 0xffd3d3d3, - MidiKeyboardComponent::upDownButtonArrowColourId, 0xff000000, + MidiKeyboardComponent::whiteNoteColourId, 0xffffffff, + MidiKeyboardComponent::blackNoteColourId, 0xff000000, + MidiKeyboardComponent::keySeparatorLineColourId, 0x66000000, + MidiKeyboardComponent::mouseOverKeyOverlayColourId, 0x80ffff00, + MidiKeyboardComponent::keyDownOverlayColourId, 0xffb6b600, + MidiKeyboardComponent::textLabelColourId, 0xff000000, + MidiKeyboardComponent::upDownButtonBackgroundColourId, 0xffd3d3d3, + MidiKeyboardComponent::upDownButtonArrowColourId, 0xff000000, - CodeEditorComponent::backgroundColourId, 0xffffffff, - CodeEditorComponent::caretColourId, 0xff000000, - CodeEditorComponent::highlightColourId, textHighlightColour, - CodeEditorComponent::defaultTextColourId, 0xff000000, + CodeEditorComponent::backgroundColourId, 0xffffffff, + CodeEditorComponent::caretColourId, 0xff000000, + CodeEditorComponent::highlightColourId, textHighlightColour, + CodeEditorComponent::defaultTextColourId, 0xff000000, - ColourSelector::backgroundColourId, 0xffe5e5e5, - ColourSelector::labelTextColourId, 0xff000000, + ColourSelector::backgroundColourId, 0xffe5e5e5, + ColourSelector::labelTextColourId, 0xff000000, - KeyMappingEditorComponent::backgroundColourId, 0x00000000, - KeyMappingEditorComponent::textColourId, 0xff000000, + KeyMappingEditorComponent::backgroundColourId, 0x00000000, + KeyMappingEditorComponent::textColourId, 0xff000000, - FileSearchPathListComponent::backgroundColourId, 0xffffffff, - }; + FileSearchPathListComponent::backgroundColourId, 0xffffffff, + }; - for (int i = 0; i < numElementsInArray (standardColours); i += 2) - setColour (standardColours [i], Colour (standardColours [i + 1])); + for (int i = 0; i < numElementsInArray (standardColours); i += 2) + setColour (standardColours [i], Colour (standardColours [i + 1])); - if (defaultSansName.isEmpty()) - Font::getPlatformDefaultFontNames (defaultSansName, defaultSerifName, defaultFixedName); + if (defaultSansName.isEmpty()) + Font::getPlatformDefaultFontNames (defaultSansName, defaultSerifName, defaultFixedName); - defaultSans = defaultSansName; - defaultSerif = defaultSerifName; - defaultFixed = defaultFixedName; + defaultSans = defaultSansName; + defaultSerif = defaultSerifName; + defaultFixed = defaultFixedName; } LookAndFeel::~LookAndFeel() @@ -64513,29 +64212,29 @@ LookAndFeel::~LookAndFeel() const Colour LookAndFeel::findColour (const int colourId) const throw() { - const int index = colourIds.indexOf (colourId); + const int index = colourIds.indexOf (colourId); - if (index >= 0) - return colours [index]; + if (index >= 0) + return colours [index]; - jassertfalse - return Colours::black; + jassertfalse + return Colours::black; } void LookAndFeel::setColour (const int colourId, const Colour& colour) throw() { - const int index = colourIds.indexOf (colourId); + const int index = colourIds.indexOf (colourId); - if (index >= 0) - colours.set (index, colour); + if (index >= 0) + colours.set (index, colour); - colourIds.add (colourId); - colours.add (colour); + colourIds.add (colourId); + colours.add (colour); } bool LookAndFeel::isColourSpecified (const int colourId) const throw() { - return colourIds.contains (colourId); + return colourIds.contains (colourId); } static LookAndFeel* defaultLF = 0; @@ -64543,2769 +64242,2769 @@ static LookAndFeel* currentDefaultLF = 0; LookAndFeel& LookAndFeel::getDefaultLookAndFeel() throw() { - // if this happens, your app hasn't initialised itself properly.. if you're - // trying to hack your own main() function, have a look at - // JUCEApplication::initialiseForGUI() - jassert (currentDefaultLF != 0); + // if this happens, your app hasn't initialised itself properly.. if you're + // trying to hack your own main() function, have a look at + // JUCEApplication::initialiseForGUI() + jassert (currentDefaultLF != 0); - return *currentDefaultLF; + return *currentDefaultLF; } void LookAndFeel::setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) throw() { - if (newDefaultLookAndFeel == 0) - { - if (defaultLF == 0) - defaultLF = new LookAndFeel(); + if (newDefaultLookAndFeel == 0) + { + if (defaultLF == 0) + defaultLF = new LookAndFeel(); - newDefaultLookAndFeel = defaultLF; - } + newDefaultLookAndFeel = defaultLF; + } - currentDefaultLF = newDefaultLookAndFeel; + currentDefaultLF = newDefaultLookAndFeel; - for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) - { - Component* const c = Desktop::getInstance().getComponent (i); + for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) + { + Component* const c = Desktop::getInstance().getComponent (i); - if (c != 0) - c->sendLookAndFeelChange(); - } + if (c != 0) + c->sendLookAndFeelChange(); + } } void LookAndFeel::clearDefaultLookAndFeel() throw() { - if (currentDefaultLF == defaultLF) - currentDefaultLF = 0; + if (currentDefaultLF == defaultLF) + currentDefaultLF = 0; - deleteAndZero (defaultLF); + deleteAndZero (defaultLF); } const Typeface::Ptr LookAndFeel::getTypefaceForFont (const Font& font) { - String faceName (font.getTypefaceName()); + String faceName (font.getTypefaceName()); - if (faceName == Font::getDefaultSansSerifFontName()) - faceName = defaultSans; - else if (faceName == Font::getDefaultSerifFontName()) - faceName = defaultSerif; - else if (faceName == Font::getDefaultMonospacedFontName()) - faceName = defaultFixed; + if (faceName == Font::getDefaultSansSerifFontName()) + faceName = defaultSans; + else if (faceName == Font::getDefaultSerifFontName()) + faceName = defaultSerif; + else if (faceName == Font::getDefaultMonospacedFontName()) + faceName = defaultFixed; - Font f (font); - f.setTypefaceName (faceName); - return Typeface::createSystemTypefaceFor (f); + Font f (font); + f.setTypefaceName (faceName); + return Typeface::createSystemTypefaceFor (f); } void LookAndFeel::setDefaultSansSerifTypefaceName (const String& newName) { - defaultSans = newName; + defaultSans = newName; } const MouseCursor LookAndFeel::getMouseCursorFor (Component& component) { - return component.getMouseCursor(); + return component.getMouseCursor(); } void LookAndFeel::drawButtonBackground (Graphics& g, - Button& button, - const Colour& backgroundColour, - bool isMouseOverButton, - bool isButtonDown) + Button& button, + const Colour& backgroundColour, + bool isMouseOverButton, + bool isButtonDown) { - const int width = button.getWidth(); - const int height = button.getHeight(); + const int width = button.getWidth(); + const int height = button.getHeight(); - const float outlineThickness = button.isEnabled() ? ((isButtonDown || isMouseOverButton) ? 1.2f : 0.7f) : 0.4f; - const float halfThickness = outlineThickness * 0.5f; + const float outlineThickness = button.isEnabled() ? ((isButtonDown || isMouseOverButton) ? 1.2f : 0.7f) : 0.4f; + const float halfThickness = outlineThickness * 0.5f; - const float indentL = button.isConnectedOnLeft() ? 0.1f : halfThickness; - const float indentR = button.isConnectedOnRight() ? 0.1f : halfThickness; - const float indentT = button.isConnectedOnTop() ? 0.1f : halfThickness; - const float indentB = button.isConnectedOnBottom() ? 0.1f : halfThickness; + const float indentL = button.isConnectedOnLeft() ? 0.1f : halfThickness; + const float indentR = button.isConnectedOnRight() ? 0.1f : halfThickness; + const float indentT = button.isConnectedOnTop() ? 0.1f : halfThickness; + const float indentB = button.isConnectedOnBottom() ? 0.1f : halfThickness; - const Colour baseColour (createBaseColour (backgroundColour, - button.hasKeyboardFocus (true), - isMouseOverButton, isButtonDown) - .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f)); + const Colour baseColour (createBaseColour (backgroundColour, + button.hasKeyboardFocus (true), + isMouseOverButton, isButtonDown) + .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f)); - drawGlassLozenge (g, - indentL, - indentT, - width - indentL - indentR, - height - indentT - indentB, - baseColour, outlineThickness, -1.0f, - button.isConnectedOnLeft(), - button.isConnectedOnRight(), - button.isConnectedOnTop(), - button.isConnectedOnBottom()); + drawGlassLozenge (g, + indentL, + indentT, + width - indentL - indentR, + height - indentT - indentB, + baseColour, outlineThickness, -1.0f, + button.isConnectedOnLeft(), + button.isConnectedOnRight(), + button.isConnectedOnTop(), + button.isConnectedOnBottom()); } const Font LookAndFeel::getFontForTextButton (TextButton& button) { - return button.getFont(); + return button.getFont(); } void LookAndFeel::drawButtonText (Graphics& g, TextButton& button, - bool /*isMouseOverButton*/, bool /*isButtonDown*/) + bool /*isMouseOverButton*/, bool /*isButtonDown*/) { - Font font (getFontForTextButton (button)); - g.setFont (font); - g.setColour (button.findColour (button.getToggleState() ? TextButton::textColourOnId - : TextButton::textColourOffId) - .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f)); + Font font (getFontForTextButton (button)); + g.setFont (font); + g.setColour (button.findColour (button.getToggleState() ? TextButton::textColourOnId + : TextButton::textColourOffId) + .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f)); - const int yIndent = jmin (4, button.proportionOfHeight (0.3f)); - const int cornerSize = jmin (button.getHeight(), button.getWidth()) / 2; + const int yIndent = jmin (4, button.proportionOfHeight (0.3f)); + const int cornerSize = jmin (button.getHeight(), button.getWidth()) / 2; - const int fontHeight = roundFloatToInt (font.getHeight() * 0.6f); - const int leftIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnLeft() ? 4 : 2)); - const int rightIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnRight() ? 4 : 2)); + const int fontHeight = roundToInt (font.getHeight() * 0.6f); + const int leftIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnLeft() ? 4 : 2)); + const int rightIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnRight() ? 4 : 2)); - g.drawFittedText (button.getButtonText(), - leftIndent, - yIndent, - button.getWidth() - leftIndent - rightIndent, - button.getHeight() - yIndent * 2, - Justification::centred, 2); + g.drawFittedText (button.getButtonText(), + leftIndent, + yIndent, + button.getWidth() - leftIndent - rightIndent, + button.getHeight() - yIndent * 2, + Justification::centred, 2); } void LookAndFeel::drawTickBox (Graphics& g, - Component& component, - int x, int y, int w, int h, - const bool ticked, - const bool isEnabled, - const bool isMouseOverButton, - const bool isButtonDown) + Component& component, + int x, int y, int w, int h, + const bool ticked, + const bool isEnabled, + const bool isMouseOverButton, + const bool isButtonDown) { - const float boxSize = w * 0.7f; + const float boxSize = w * 0.7f; - drawGlassSphere (g, (float) x, y + (h - boxSize) * 0.5f, boxSize, - createBaseColour (component.findColour (TextButton::buttonColourId) - .withMultipliedAlpha (isEnabled ? 1.0f : 0.5f), - true, - isMouseOverButton, - isButtonDown), - isEnabled ? ((isButtonDown || isMouseOverButton) ? 1.1f : 0.5f) : 0.3f); + drawGlassSphere (g, (float) x, y + (h - boxSize) * 0.5f, boxSize, + createBaseColour (component.findColour (TextButton::buttonColourId) + .withMultipliedAlpha (isEnabled ? 1.0f : 0.5f), + true, + isMouseOverButton, + isButtonDown), + isEnabled ? ((isButtonDown || isMouseOverButton) ? 1.1f : 0.5f) : 0.3f); - if (ticked) - { - Path tick; - tick.startNewSubPath (1.5f, 3.0f); - tick.lineTo (3.0f, 6.0f); - tick.lineTo (6.0f, 0.0f); + if (ticked) + { + Path tick; + tick.startNewSubPath (1.5f, 3.0f); + tick.lineTo (3.0f, 6.0f); + tick.lineTo (6.0f, 0.0f); - g.setColour (isEnabled ? Colours::black : Colours::grey); + g.setColour (isEnabled ? Colours::black : Colours::grey); - const AffineTransform trans (AffineTransform::scale (w / 9.0f, h / 9.0f) - .translated ((float) x, (float) y)); + const AffineTransform trans (AffineTransform::scale (w / 9.0f, h / 9.0f) + .translated ((float) x, (float) y)); - g.strokePath (tick, PathStrokeType (2.5f), trans); - } + g.strokePath (tick, PathStrokeType (2.5f), trans); + } } void LookAndFeel::drawToggleButton (Graphics& g, - ToggleButton& button, - bool isMouseOverButton, - bool isButtonDown) + ToggleButton& button, + bool isMouseOverButton, + bool isButtonDown) { - if (button.hasKeyboardFocus (true)) - { - g.setColour (button.findColour (TextEditor::focusedOutlineColourId)); - g.drawRect (0, 0, button.getWidth(), button.getHeight()); - } + if (button.hasKeyboardFocus (true)) + { + g.setColour (button.findColour (TextEditor::focusedOutlineColourId)); + g.drawRect (0, 0, button.getWidth(), button.getHeight()); + } - const int tickWidth = jmin (20, button.getHeight() - 4); + const int tickWidth = jmin (20, button.getHeight() - 4); - drawTickBox (g, button, 4, (button.getHeight() - tickWidth) / 2, - tickWidth, tickWidth, - button.getToggleState(), - button.isEnabled(), - isMouseOverButton, - isButtonDown); + drawTickBox (g, button, 4, (button.getHeight() - tickWidth) / 2, + tickWidth, tickWidth, + button.getToggleState(), + button.isEnabled(), + isMouseOverButton, + isButtonDown); - g.setColour (button.findColour (ToggleButton::textColourId)); - g.setFont (jmin (15.0f, button.getHeight() * 0.6f)); + g.setColour (button.findColour (ToggleButton::textColourId)); + g.setFont (jmin (15.0f, button.getHeight() * 0.6f)); - if (! button.isEnabled()) - g.setOpacity (0.5f); + if (! button.isEnabled()) + g.setOpacity (0.5f); - const int textX = tickWidth + 5; + const int textX = tickWidth + 5; - g.drawFittedText (button.getButtonText(), - textX, 4, - button.getWidth() - textX - 2, button.getHeight() - 8, - Justification::centredLeft, 10); + g.drawFittedText (button.getButtonText(), + textX, 4, + button.getWidth() - textX - 2, button.getHeight() - 8, + Justification::centredLeft, 10); } void LookAndFeel::changeToggleButtonWidthToFitText (ToggleButton& button) { - Font font (jmin (15.0f, button.getHeight() * 0.6f)); + Font font (jmin (15.0f, button.getHeight() * 0.6f)); - const int tickWidth = jmin (24, button.getHeight()); + const int tickWidth = jmin (24, button.getHeight()); - button.setSize (font.getStringWidth (button.getButtonText()) + tickWidth + 8, - button.getHeight()); + button.setSize (font.getStringWidth (button.getButtonText()) + tickWidth + 8, + button.getHeight()); } AlertWindow* LookAndFeel::createAlertWindow (const String& title, - const String& message, - const String& button1, - const String& button2, - const String& button3, - AlertWindow::AlertIconType iconType, - int numButtons, - Component* associatedComponent) + const String& message, + const String& button1, + const String& button2, + const String& button3, + AlertWindow::AlertIconType iconType, + int numButtons, + Component* associatedComponent) { - AlertWindow* aw = new AlertWindow (title, message, iconType, associatedComponent); + AlertWindow* aw = new AlertWindow (title, message, iconType, associatedComponent); - if (numButtons == 1) - { - aw->addButton (button1, 0, - KeyPress (KeyPress::escapeKey, 0, 0), - KeyPress (KeyPress::returnKey, 0, 0)); - } - else - { - const KeyPress button1ShortCut (CharacterFunctions::toLowerCase (button1[0]), 0, 0); - KeyPress button2ShortCut (CharacterFunctions::toLowerCase (button2[0]), 0, 0); - if (button1ShortCut == button2ShortCut) - button2ShortCut = KeyPress(); + if (numButtons == 1) + { + aw->addButton (button1, 0, + KeyPress (KeyPress::escapeKey, 0, 0), + KeyPress (KeyPress::returnKey, 0, 0)); + } + else + { + const KeyPress button1ShortCut (CharacterFunctions::toLowerCase (button1[0]), 0, 0); + KeyPress button2ShortCut (CharacterFunctions::toLowerCase (button2[0]), 0, 0); + if (button1ShortCut == button2ShortCut) + button2ShortCut = KeyPress(); - if (numButtons == 2) - { - aw->addButton (button1, 1, KeyPress (KeyPress::returnKey, 0, 0), button1ShortCut); - aw->addButton (button2, 0, KeyPress (KeyPress::escapeKey, 0, 0), button2ShortCut); - } - else if (numButtons == 3) - { - aw->addButton (button1, 1, button1ShortCut); - aw->addButton (button2, 2, button2ShortCut); - aw->addButton (button3, 0, KeyPress (KeyPress::escapeKey, 0, 0)); - } - } + if (numButtons == 2) + { + aw->addButton (button1, 1, KeyPress (KeyPress::returnKey, 0, 0), button1ShortCut); + aw->addButton (button2, 0, KeyPress (KeyPress::escapeKey, 0, 0), button2ShortCut); + } + else if (numButtons == 3) + { + aw->addButton (button1, 1, button1ShortCut); + aw->addButton (button2, 2, button2ShortCut); + aw->addButton (button3, 0, KeyPress (KeyPress::escapeKey, 0, 0)); + } + } - return aw; + return aw; } void LookAndFeel::drawAlertBox (Graphics& g, - AlertWindow& alert, - const Rectangle& textArea, - TextLayout& textLayout) + AlertWindow& alert, + const Rectangle& textArea, + TextLayout& textLayout) { - g.fillAll (alert.findColour (AlertWindow::backgroundColourId)); + g.fillAll (alert.findColour (AlertWindow::backgroundColourId)); - int iconSpaceUsed = 0; - Justification alignment (Justification::horizontallyCentred); + int iconSpaceUsed = 0; + Justification alignment (Justification::horizontallyCentred); - const int iconWidth = 80; - int iconSize = jmin (iconWidth + 50, alert.getHeight() + 20); + const int iconWidth = 80; + int iconSize = jmin (iconWidth + 50, alert.getHeight() + 20); - if (alert.containsAnyExtraComponents() || alert.getNumButtons() > 2) - iconSize = jmin (iconSize, textArea.getHeight() + 50); + if (alert.containsAnyExtraComponents() || alert.getNumButtons() > 2) + iconSize = jmin (iconSize, textArea.getHeight() + 50); - const Rectangle iconRect (iconSize / -10, iconSize / -10, - iconSize, iconSize); + const Rectangle iconRect (iconSize / -10, iconSize / -10, + iconSize, iconSize); - if (alert.getAlertType() != AlertWindow::NoIcon) - { - Path icon; - uint32 colour; - char character; + if (alert.getAlertType() != AlertWindow::NoIcon) + { + Path icon; + uint32 colour; + char character; - if (alert.getAlertType() == AlertWindow::WarningIcon) - { - colour = 0x55ff5555; - character = '!'; + if (alert.getAlertType() == AlertWindow::WarningIcon) + { + colour = 0x55ff5555; + character = '!'; - icon.addTriangle (iconRect.getX() + iconRect.getWidth() * 0.5f, (float) iconRect.getY(), - (float) iconRect.getRight(), (float) iconRect.getBottom(), - (float) iconRect.getX(), (float) iconRect.getBottom()); + icon.addTriangle (iconRect.getX() + iconRect.getWidth() * 0.5f, (float) iconRect.getY(), + (float) iconRect.getRight(), (float) iconRect.getBottom(), + (float) iconRect.getX(), (float) iconRect.getBottom()); - icon = icon.createPathWithRoundedCorners (5.0f); - } - else - { - colour = alert.getAlertType() == AlertWindow::InfoIcon ? 0x605555ff : 0x40b69900; - character = alert.getAlertType() == AlertWindow::InfoIcon ? 'i' : '?'; + icon = icon.createPathWithRoundedCorners (5.0f); + } + else + { + colour = alert.getAlertType() == AlertWindow::InfoIcon ? 0x605555ff : 0x40b69900; + character = alert.getAlertType() == AlertWindow::InfoIcon ? 'i' : '?'; - icon.addEllipse ((float) iconRect.getX(), (float) iconRect.getY(), - (float) iconRect.getWidth(), (float) iconRect.getHeight()); - } + icon.addEllipse ((float) iconRect.getX(), (float) iconRect.getY(), + (float) iconRect.getWidth(), (float) iconRect.getHeight()); + } - GlyphArrangement ga; - ga.addFittedText (Font (iconRect.getHeight() * 0.9f, Font::bold), - String::charToString (character), - (float) iconRect.getX(), (float) iconRect.getY(), - (float) iconRect.getWidth(), (float) iconRect.getHeight(), - Justification::centred, false); - ga.createPath (icon); + GlyphArrangement ga; + ga.addFittedText (Font (iconRect.getHeight() * 0.9f, Font::bold), + String::charToString (character), + (float) iconRect.getX(), (float) iconRect.getY(), + (float) iconRect.getWidth(), (float) iconRect.getHeight(), + Justification::centred, false); + ga.createPath (icon); - icon.setUsingNonZeroWinding (false); - g.setColour (Colour (colour)); - g.fillPath (icon); + icon.setUsingNonZeroWinding (false); + g.setColour (Colour (colour)); + g.fillPath (icon); - iconSpaceUsed = iconWidth; - alignment = Justification::left; - } + iconSpaceUsed = iconWidth; + alignment = Justification::left; + } - g.setColour (alert.findColour (AlertWindow::textColourId)); + g.setColour (alert.findColour (AlertWindow::textColourId)); - textLayout.drawWithin (g, - textArea.getX() + iconSpaceUsed, textArea.getY(), - textArea.getWidth() - iconSpaceUsed, textArea.getHeight(), - alignment.getFlags() | Justification::top); + textLayout.drawWithin (g, + textArea.getX() + iconSpaceUsed, textArea.getY(), + textArea.getWidth() - iconSpaceUsed, textArea.getHeight(), + alignment.getFlags() | Justification::top); - g.setColour (alert.findColour (AlertWindow::outlineColourId)); - g.drawRect (0, 0, alert.getWidth(), alert.getHeight()); + g.setColour (alert.findColour (AlertWindow::outlineColourId)); + g.drawRect (0, 0, alert.getWidth(), alert.getHeight()); } int LookAndFeel::getAlertBoxWindowFlags() { - return ComponentPeer::windowAppearsOnTaskbar - | ComponentPeer::windowHasDropShadow; + return ComponentPeer::windowAppearsOnTaskbar + | ComponentPeer::windowHasDropShadow; } int LookAndFeel::getAlertWindowButtonHeight() { - return 28; + return 28; } const Font LookAndFeel::getAlertWindowFont() { - return Font (12.0f); + return Font (12.0f); } void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar, - int width, int height, - double progress, const String& textToShow) + int width, int height, + double progress, const String& textToShow) { - const Colour background (progressBar.findColour (ProgressBar::backgroundColourId)); - const Colour foreground (progressBar.findColour (ProgressBar::foregroundColourId)); + const Colour background (progressBar.findColour (ProgressBar::backgroundColourId)); + const Colour foreground (progressBar.findColour (ProgressBar::foregroundColourId)); - g.fillAll (background); + g.fillAll (background); - if (progress >= 0.0f && progress < 1.0f) - { - drawGlassLozenge (g, 1.0f, 1.0f, - (float) jlimit (0.0, width - 2.0, progress * (width - 2.0)), - (float) (height - 2), - foreground, - 0.5f, 0.0f, - true, true, true, true); - } - else - { - // spinning bar.. - g.setColour (foreground); + if (progress >= 0.0f && progress < 1.0f) + { + drawGlassLozenge (g, 1.0f, 1.0f, + (float) jlimit (0.0, width - 2.0, progress * (width - 2.0)), + (float) (height - 2), + foreground, + 0.5f, 0.0f, + true, true, true, true); + } + else + { + // spinning bar.. + g.setColour (foreground); - const int stripeWidth = height * 2; - const int position = (Time::getMillisecondCounter() / 15) % stripeWidth; + const int stripeWidth = height * 2; + const int position = (Time::getMillisecondCounter() / 15) % stripeWidth; - Path p; + Path p; - for (float x = (float) (- position); x < width + stripeWidth; x += stripeWidth) - p.addQuadrilateral (x, 0.0f, - x + stripeWidth * 0.5f, 0.0f, - x, (float) height, - x - stripeWidth * 0.5f, (float) height); + for (float x = (float) (- position); x < width + stripeWidth; x += stripeWidth) + p.addQuadrilateral (x, 0.0f, + x + stripeWidth * 0.5f, 0.0f, + x, (float) height, + x - stripeWidth * 0.5f, (float) height); - Image im (Image::ARGB, width, height, true); + Image im (Image::ARGB, width, height, true); - { - Graphics g2 (im); - drawGlassLozenge (g2, 1.0f, 1.0f, - (float) (width - 2), - (float) (height - 2), - foreground, - 0.5f, 0.0f, - true, true, true, true); - } + { + Graphics g2 (im); + drawGlassLozenge (g2, 1.0f, 1.0f, + (float) (width - 2), + (float) (height - 2), + foreground, + 0.5f, 0.0f, + true, true, true, true); + } - g.setTiledImageFill (im, 0, 0, 0.85f); - g.fillPath (p); - } + g.setTiledImageFill (im, 0, 0, 0.85f); + g.fillPath (p); + } - if (textToShow.isNotEmpty()) - { - g.setColour (Colour::contrasting (background, foreground)); - g.setFont (height * 0.6f); + if (textToShow.isNotEmpty()) + { + g.setColour (Colour::contrasting (background, foreground)); + g.setFont (height * 0.6f); - g.drawText (textToShow, 0, 0, width, height, Justification::centred, false); - } + g.drawText (textToShow, 0, 0, width, height, Justification::centred, false); + } } void LookAndFeel::drawSpinningWaitAnimation (Graphics& g, const Colour& colour, int x, int y, int w, int h) { - const float radius = jmin (w, h) * 0.4f; - const float thickness = radius * 0.15f; - Path p; - p.addRoundedRectangle (radius * 0.4f, thickness * -0.5f, - radius * 0.6f, thickness, - thickness * 0.5f); + const float radius = jmin (w, h) * 0.4f; + const float thickness = radius * 0.15f; + Path p; + p.addRoundedRectangle (radius * 0.4f, thickness * -0.5f, + radius * 0.6f, thickness, + thickness * 0.5f); - const float cx = x + w * 0.5f; - const float cy = y + h * 0.5f; + const float cx = x + w * 0.5f; + const float cy = y + h * 0.5f; - const uint32 animationIndex = (Time::getMillisecondCounter() / (1000 / 10)) % 12; + const uint32 animationIndex = (Time::getMillisecondCounter() / (1000 / 10)) % 12; - for (int i = 0; i < 12; ++i) - { - const int n = (i + 12 - animationIndex) % 12; - g.setColour (colour.withMultipliedAlpha ((n + 1) / 12.0f)); + for (int i = 0; i < 12; ++i) + { + const int n = (i + 12 - animationIndex) % 12; + g.setColour (colour.withMultipliedAlpha ((n + 1) / 12.0f)); - g.fillPath (p, AffineTransform::rotation (i * (float_Pi / 6.0f)) - .translated (cx, cy)); - } + g.fillPath (p, AffineTransform::rotation (i * (float_Pi / 6.0f)) + .translated (cx, cy)); + } } void LookAndFeel::drawScrollbarButton (Graphics& g, - ScrollBar& scrollbar, - int width, int height, - int buttonDirection, - bool /*isScrollbarVertical*/, - bool /*isMouseOverButton*/, - bool isButtonDown) + ScrollBar& scrollbar, + int width, int height, + int buttonDirection, + bool /*isScrollbarVertical*/, + bool /*isMouseOverButton*/, + bool isButtonDown) { - Path p; + Path p; - if (buttonDirection == 0) - p.addTriangle (width * 0.5f, height * 0.2f, - width * 0.1f, height * 0.7f, - width * 0.9f, height * 0.7f); - else if (buttonDirection == 1) - p.addTriangle (width * 0.8f, height * 0.5f, - width * 0.3f, height * 0.1f, - width * 0.3f, height * 0.9f); - else if (buttonDirection == 2) - p.addTriangle (width * 0.5f, height * 0.8f, - width * 0.1f, height * 0.3f, - width * 0.9f, height * 0.3f); - else if (buttonDirection == 3) - p.addTriangle (width * 0.2f, height * 0.5f, - width * 0.7f, height * 0.1f, - width * 0.7f, height * 0.9f); + if (buttonDirection == 0) + p.addTriangle (width * 0.5f, height * 0.2f, + width * 0.1f, height * 0.7f, + width * 0.9f, height * 0.7f); + else if (buttonDirection == 1) + p.addTriangle (width * 0.8f, height * 0.5f, + width * 0.3f, height * 0.1f, + width * 0.3f, height * 0.9f); + else if (buttonDirection == 2) + p.addTriangle (width * 0.5f, height * 0.8f, + width * 0.1f, height * 0.3f, + width * 0.9f, height * 0.3f); + else if (buttonDirection == 3) + p.addTriangle (width * 0.2f, height * 0.5f, + width * 0.7f, height * 0.1f, + width * 0.7f, height * 0.9f); - if (isButtonDown) - g.setColour (scrollbar.findColour (ScrollBar::thumbColourId).contrasting (0.2f)); - else - g.setColour (scrollbar.findColour (ScrollBar::thumbColourId)); + if (isButtonDown) + g.setColour (scrollbar.findColour (ScrollBar::thumbColourId).contrasting (0.2f)); + else + g.setColour (scrollbar.findColour (ScrollBar::thumbColourId)); - g.fillPath (p); + g.fillPath (p); - g.setColour (Colour (0x80000000)); - g.strokePath (p, PathStrokeType (0.5f)); + g.setColour (Colour (0x80000000)); + g.strokePath (p, PathStrokeType (0.5f)); } void LookAndFeel::drawScrollbar (Graphics& g, - ScrollBar& scrollbar, - int x, int y, - int width, int height, - bool isScrollbarVertical, - int thumbStartPosition, - int thumbSize, - bool /*isMouseOver*/, - bool /*isMouseDown*/) + ScrollBar& scrollbar, + int x, int y, + int width, int height, + bool isScrollbarVertical, + int thumbStartPosition, + int thumbSize, + bool /*isMouseOver*/, + bool /*isMouseDown*/) { - g.fillAll (scrollbar.findColour (ScrollBar::backgroundColourId)); + g.fillAll (scrollbar.findColour (ScrollBar::backgroundColourId)); - Path slotPath, thumbPath; + Path slotPath, thumbPath; - const float slotIndent = jmin (width, height) > 15 ? 1.0f : 0.0f; - const float slotIndentx2 = slotIndent * 2.0f; - const float thumbIndent = slotIndent + 1.0f; - const float thumbIndentx2 = thumbIndent * 2.0f; + const float slotIndent = jmin (width, height) > 15 ? 1.0f : 0.0f; + const float slotIndentx2 = slotIndent * 2.0f; + const float thumbIndent = slotIndent + 1.0f; + const float thumbIndentx2 = thumbIndent * 2.0f; - float gx1 = 0.0f, gy1 = 0.0f, gx2 = 0.0f, gy2 = 0.0f; + float gx1 = 0.0f, gy1 = 0.0f, gx2 = 0.0f, gy2 = 0.0f; - if (isScrollbarVertical) - { - slotPath.addRoundedRectangle (x + slotIndent, - y + slotIndent, - width - slotIndentx2, - height - slotIndentx2, - (width - slotIndentx2) * 0.5f); + if (isScrollbarVertical) + { + slotPath.addRoundedRectangle (x + slotIndent, + y + slotIndent, + width - slotIndentx2, + height - slotIndentx2, + (width - slotIndentx2) * 0.5f); - if (thumbSize > 0) - thumbPath.addRoundedRectangle (x + thumbIndent, - thumbStartPosition + thumbIndent, - width - thumbIndentx2, - thumbSize - thumbIndentx2, - (width - thumbIndentx2) * 0.5f); - gx1 = (float) x; - gx2 = x + width * 0.7f; - } - else - { - slotPath.addRoundedRectangle (x + slotIndent, - y + slotIndent, - width - slotIndentx2, - height - slotIndentx2, - (height - slotIndentx2) * 0.5f); + if (thumbSize > 0) + thumbPath.addRoundedRectangle (x + thumbIndent, + thumbStartPosition + thumbIndent, + width - thumbIndentx2, + thumbSize - thumbIndentx2, + (width - thumbIndentx2) * 0.5f); + gx1 = (float) x; + gx2 = x + width * 0.7f; + } + else + { + slotPath.addRoundedRectangle (x + slotIndent, + y + slotIndent, + width - slotIndentx2, + height - slotIndentx2, + (height - slotIndentx2) * 0.5f); - if (thumbSize > 0) - thumbPath.addRoundedRectangle (thumbStartPosition + thumbIndent, - y + thumbIndent, - thumbSize - thumbIndentx2, - height - thumbIndentx2, - (height - thumbIndentx2) * 0.5f); - gy1 = (float) y; - gy2 = y + height * 0.7f; - } + if (thumbSize > 0) + thumbPath.addRoundedRectangle (thumbStartPosition + thumbIndent, + y + thumbIndent, + thumbSize - thumbIndentx2, + height - thumbIndentx2, + (height - thumbIndentx2) * 0.5f); + gy1 = (float) y; + gy2 = y + height * 0.7f; + } - const Colour thumbColour (scrollbar.findColour (ScrollBar::thumbColourId)); + const Colour thumbColour (scrollbar.findColour (ScrollBar::thumbColourId)); - g.setGradientFill (ColourGradient (thumbColour.overlaidWith (Colour (0x44000000)), gx1, gy1, - thumbColour.overlaidWith (Colour (0x19000000)), gx2, gy2, false)); - g.fillPath (slotPath); + g.setGradientFill (ColourGradient (thumbColour.overlaidWith (Colour (0x44000000)), gx1, gy1, + thumbColour.overlaidWith (Colour (0x19000000)), gx2, gy2, false)); + g.fillPath (slotPath); - if (isScrollbarVertical) - { - gx1 = x + width * 0.6f; - gx2 = (float) x + width; - } - else - { - gy1 = y + height * 0.6f; - gy2 = (float) y + height; - } + if (isScrollbarVertical) + { + gx1 = x + width * 0.6f; + gx2 = (float) x + width; + } + else + { + gy1 = y + height * 0.6f; + gy2 = (float) y + height; + } - g.setGradientFill (ColourGradient (Colours::transparentBlack,gx1, gy1, - Colour (0x19000000), gx2, gy2, false)); - g.fillPath (slotPath); + g.setGradientFill (ColourGradient (Colours::transparentBlack,gx1, gy1, + Colour (0x19000000), gx2, gy2, false)); + g.fillPath (slotPath); - g.setColour (thumbColour); - g.fillPath (thumbPath); + g.setColour (thumbColour); + g.fillPath (thumbPath); - g.setGradientFill (ColourGradient (Colour (0x10000000), gx1, gy1, - Colours::transparentBlack, gx2, gy2, false)); + g.setGradientFill (ColourGradient (Colour (0x10000000), gx1, gy1, + Colours::transparentBlack, gx2, gy2, false)); - g.saveState(); + g.saveState(); - if (isScrollbarVertical) - g.reduceClipRegion (x + width / 2, y, width, height); - else - g.reduceClipRegion (x, y + height / 2, width, height); + if (isScrollbarVertical) + g.reduceClipRegion (x + width / 2, y, width, height); + else + g.reduceClipRegion (x, y + height / 2, width, height); - g.fillPath (thumbPath); - g.restoreState(); + g.fillPath (thumbPath); + g.restoreState(); - g.setColour (Colour (0x4c000000)); - g.strokePath (thumbPath, PathStrokeType (0.4f)); + g.setColour (Colour (0x4c000000)); + g.strokePath (thumbPath, PathStrokeType (0.4f)); } ImageEffectFilter* LookAndFeel::getScrollbarEffect() { - return 0; + return 0; } int LookAndFeel::getMinimumScrollbarThumbSize (ScrollBar& scrollbar) { - return jmin (scrollbar.getWidth(), scrollbar.getHeight()) * 2; + return jmin (scrollbar.getWidth(), scrollbar.getHeight()) * 2; } int LookAndFeel::getDefaultScrollbarWidth() { - return 18; + return 18; } int LookAndFeel::getScrollbarButtonSize (ScrollBar& scrollbar) { - return 2 + (scrollbar.isVertical() ? scrollbar.getWidth() - : scrollbar.getHeight()); + return 2 + (scrollbar.isVertical() ? scrollbar.getWidth() + : scrollbar.getHeight()); } const Path LookAndFeel::getTickShape (const float height) { - static const unsigned char tickShapeData[] = - { - 109,0,224,168,68,0,0,119,67,108,0,224,172,68,0,128,146,67,113,0,192,148,68,0,0,219,67,0,96,110,68,0,224,56,68,113,0,64,51,68,0,32,130,68,0,64,20,68,0,224, - 162,68,108,0,128,3,68,0,128,168,68,113,0,128,221,67,0,192,175,68,0,0,207,67,0,32,179,68,113,0,0,201,67,0,224,173,68,0,0,181,67,0,224,161,68,108,0,128,168,67, - 0,128,154,68,113,0,128,141,67,0,192,138,68,0,128,108,67,0,64,131,68,113,0,0,62,67,0,128,119,68,0,0,5,67,0,128,114,68,113,0,0,102,67,0,192,88,68,0,128,155, - 67,0,192,88,68,113,0,0,190,67,0,192,88,68,0,128,232,67,0,224,131,68,108,0,128,246,67,0,192,139,68,113,0,64,33,68,0,128,87,68,0,0,93,68,0,224,26,68,113,0, - 96,140,68,0,128,188,67,0,224,168,68,0,0,119,67,99,101 - }; + static const unsigned char tickShapeData[] = + { + 109,0,224,168,68,0,0,119,67,108,0,224,172,68,0,128,146,67,113,0,192,148,68,0,0,219,67,0,96,110,68,0,224,56,68,113,0,64,51,68,0,32,130,68,0,64,20,68,0,224, + 162,68,108,0,128,3,68,0,128,168,68,113,0,128,221,67,0,192,175,68,0,0,207,67,0,32,179,68,113,0,0,201,67,0,224,173,68,0,0,181,67,0,224,161,68,108,0,128,168,67, + 0,128,154,68,113,0,128,141,67,0,192,138,68,0,128,108,67,0,64,131,68,113,0,0,62,67,0,128,119,68,0,0,5,67,0,128,114,68,113,0,0,102,67,0,192,88,68,0,128,155, + 67,0,192,88,68,113,0,0,190,67,0,192,88,68,0,128,232,67,0,224,131,68,108,0,128,246,67,0,192,139,68,113,0,64,33,68,0,128,87,68,0,0,93,68,0,224,26,68,113,0, + 96,140,68,0,128,188,67,0,224,168,68,0,0,119,67,99,101 + }; - Path p; - p.loadPathFromData (tickShapeData, sizeof (tickShapeData)); - p.scaleToFit (0, 0, height * 2.0f, height, true); - return p; + Path p; + p.loadPathFromData (tickShapeData, sizeof (tickShapeData)); + p.scaleToFit (0, 0, height * 2.0f, height, true); + return p; } const Path LookAndFeel::getCrossShape (const float height) { - static const unsigned char crossShapeData[] = - { - 109,0,0,17,68,0,96,145,68,108,0,192,13,68,0,192,147,68,113,0,0,213,67,0,64,174,68,0,0,168,67,0,64,174,68,113,0,0,104,67,0,64,174,68,0,0,5,67,0,64, - 153,68,113,0,0,18,67,0,64,153,68,0,0,24,67,0,64,153,68,113,0,0,135,67,0,64,153,68,0,128,207,67,0,224,130,68,108,0,0,220,67,0,0,126,68,108,0,0,204,67, - 0,128,117,68,113,0,0,138,67,0,64,82,68,0,0,138,67,0,192,57,68,113,0,0,138,67,0,192,37,68,0,128,210,67,0,64,10,68,113,0,128,220,67,0,64,45,68,0,0,8, - 68,0,128,78,68,108,0,192,14,68,0,0,87,68,108,0,64,20,68,0,0,80,68,113,0,192,57,68,0,0,32,68,0,128,88,68,0,0,32,68,113,0,64,112,68,0,0,32,68,0, - 128,124,68,0,64,68,68,113,0,0,121,68,0,192,67,68,0,128,119,68,0,192,67,68,113,0,192,108,68,0,192,67,68,0,32,89,68,0,96,82,68,113,0,128,69,68,0,0,97,68, - 0,0,56,68,0,64,115,68,108,0,64,49,68,0,128,124,68,108,0,192,55,68,0,96,129,68,113,0,0,92,68,0,224,146,68,0,192,129,68,0,224,146,68,113,0,64,110,68,0,64, - 168,68,0,64,87,68,0,64,168,68,113,0,128,66,68,0,64,168,68,0,64,27,68,0,32,150,68,99,101 - }; + static const unsigned char crossShapeData[] = + { + 109,0,0,17,68,0,96,145,68,108,0,192,13,68,0,192,147,68,113,0,0,213,67,0,64,174,68,0,0,168,67,0,64,174,68,113,0,0,104,67,0,64,174,68,0,0,5,67,0,64, + 153,68,113,0,0,18,67,0,64,153,68,0,0,24,67,0,64,153,68,113,0,0,135,67,0,64,153,68,0,128,207,67,0,224,130,68,108,0,0,220,67,0,0,126,68,108,0,0,204,67, + 0,128,117,68,113,0,0,138,67,0,64,82,68,0,0,138,67,0,192,57,68,113,0,0,138,67,0,192,37,68,0,128,210,67,0,64,10,68,113,0,128,220,67,0,64,45,68,0,0,8, + 68,0,128,78,68,108,0,192,14,68,0,0,87,68,108,0,64,20,68,0,0,80,68,113,0,192,57,68,0,0,32,68,0,128,88,68,0,0,32,68,113,0,64,112,68,0,0,32,68,0, + 128,124,68,0,64,68,68,113,0,0,121,68,0,192,67,68,0,128,119,68,0,192,67,68,113,0,192,108,68,0,192,67,68,0,32,89,68,0,96,82,68,113,0,128,69,68,0,0,97,68, + 0,0,56,68,0,64,115,68,108,0,64,49,68,0,128,124,68,108,0,192,55,68,0,96,129,68,113,0,0,92,68,0,224,146,68,0,192,129,68,0,224,146,68,113,0,64,110,68,0,64, + 168,68,0,64,87,68,0,64,168,68,113,0,128,66,68,0,64,168,68,0,64,27,68,0,32,150,68,99,101 + }; - Path p; - p.loadPathFromData (crossShapeData, sizeof (crossShapeData)); - p.scaleToFit (0, 0, height * 2.0f, height, true); - return p; + Path p; + p.loadPathFromData (crossShapeData, sizeof (crossShapeData)); + p.scaleToFit (0, 0, height * 2.0f, height, true); + return p; } void LookAndFeel::drawTreeviewPlusMinusBox (Graphics& g, int x, int y, int w, int h, bool isPlus, bool /*isMouseOver*/) { - const int boxSize = ((jmin (16, w, h) << 1) / 3) | 1; + const int boxSize = ((jmin (16, w, h) << 1) / 3) | 1; - x += (w - boxSize) >> 1; - y += (h - boxSize) >> 1; - w = boxSize; - h = boxSize; + x += (w - boxSize) >> 1; + y += (h - boxSize) >> 1; + w = boxSize; + h = boxSize; - g.setColour (Colour (0xe5ffffff)); - g.fillRect (x, y, w, h); + g.setColour (Colour (0xe5ffffff)); + g.fillRect (x, y, w, h); - g.setColour (Colour (0x80000000)); - g.drawRect (x, y, w, h); + g.setColour (Colour (0x80000000)); + g.drawRect (x, y, w, h); - const float size = boxSize / 2 + 1.0f; - const float centre = (float) (boxSize / 2); + const float size = boxSize / 2 + 1.0f; + const float centre = (float) (boxSize / 2); - g.fillRect (x + (w - size) * 0.5f, y + centre, size, 1.0f); + g.fillRect (x + (w - size) * 0.5f, y + centre, size, 1.0f); - if (isPlus) - g.fillRect (x + centre, y + (h - size) * 0.5f, 1.0f, size); + if (isPlus) + g.fillRect (x + centre, y + (h - size) * 0.5f, 1.0f, size); } void LookAndFeel::drawBubble (Graphics& g, - float tipX, float tipY, - float boxX, float boxY, - float boxW, float boxH) + float tipX, float tipY, + float boxX, float boxY, + float boxW, float boxH) { - int side = 0; + int side = 0; - if (tipX < boxX) - side = 1; - else if (tipX > boxX + boxW) - side = 3; - else if (tipY > boxY + boxH) - side = 2; + if (tipX < boxX) + side = 1; + else if (tipX > boxX + boxW) + side = 3; + else if (tipY > boxY + boxH) + side = 2; - const float indent = 2.0f; - Path p; - p.addBubble (boxX + indent, - boxY + indent, - boxW - indent * 2.0f, - boxH - indent * 2.0f, - 5.0f, - tipX, tipY, - side, - 0.5f, - jmin (15.0f, boxW * 0.3f, boxH * 0.3f)); + const float indent = 2.0f; + Path p; + p.addBubble (boxX + indent, + boxY + indent, + boxW - indent * 2.0f, + boxH - indent * 2.0f, + 5.0f, + tipX, tipY, + side, + 0.5f, + jmin (15.0f, boxW * 0.3f, boxH * 0.3f)); - //xxx need to take comp as param for colour - g.setColour (findColour (TooltipWindow::backgroundColourId).withAlpha (0.9f)); - g.fillPath (p); + //xxx need to take comp as param for colour + g.setColour (findColour (TooltipWindow::backgroundColourId).withAlpha (0.9f)); + g.fillPath (p); - //xxx as above - g.setColour (findColour (TooltipWindow::textColourId).withAlpha (0.4f)); - g.strokePath (p, PathStrokeType (1.33f)); + //xxx as above + g.setColour (findColour (TooltipWindow::textColourId).withAlpha (0.4f)); + g.strokePath (p, PathStrokeType (1.33f)); } const Font LookAndFeel::getPopupMenuFont() { - return Font (17.0f); + return Font (17.0f); } void LookAndFeel::getIdealPopupMenuItemSize (const String& text, - const bool isSeparator, - int standardMenuItemHeight, - int& idealWidth, - int& idealHeight) + const bool isSeparator, + int standardMenuItemHeight, + int& idealWidth, + int& idealHeight) { - if (isSeparator) - { - idealWidth = 50; - idealHeight = standardMenuItemHeight > 0 ? standardMenuItemHeight / 2 : 10; - } - else - { - Font font (getPopupMenuFont()); + if (isSeparator) + { + idealWidth = 50; + idealHeight = standardMenuItemHeight > 0 ? standardMenuItemHeight / 2 : 10; + } + else + { + Font font (getPopupMenuFont()); - if (standardMenuItemHeight > 0 && font.getHeight() > standardMenuItemHeight / 1.3f) - font.setHeight (standardMenuItemHeight / 1.3f); + if (standardMenuItemHeight > 0 && font.getHeight() > standardMenuItemHeight / 1.3f) + font.setHeight (standardMenuItemHeight / 1.3f); - idealHeight = standardMenuItemHeight > 0 ? standardMenuItemHeight : roundFloatToInt (font.getHeight() * 1.3f); - idealWidth = font.getStringWidth (text) + idealHeight * 2; - } + idealHeight = standardMenuItemHeight > 0 ? standardMenuItemHeight : roundToInt (font.getHeight() * 1.3f); + idealWidth = font.getStringWidth (text) + idealHeight * 2; + } } void LookAndFeel::drawPopupMenuBackground (Graphics& g, int width, int height) { - const Colour background (findColour (PopupMenu::backgroundColourId)); + const Colour background (findColour (PopupMenu::backgroundColourId)); - g.fillAll (background); - g.setColour (background.overlaidWith (Colour (0x2badd8e6))); + g.fillAll (background); + g.setColour (background.overlaidWith (Colour (0x2badd8e6))); - for (int i = 0; i < height; i += 3) - g.fillRect (0, i, width, 1); + for (int i = 0; i < height; i += 3) + g.fillRect (0, i, width, 1); #if ! JUCE_MAC - g.setColour (findColour (PopupMenu::textColourId).withAlpha (0.6f)); - g.drawRect (0, 0, width, height); + g.setColour (findColour (PopupMenu::textColourId).withAlpha (0.6f)); + g.drawRect (0, 0, width, height); #endif } void LookAndFeel::drawPopupMenuUpDownArrow (Graphics& g, - int width, int height, - bool isScrollUpArrow) + int width, int height, + bool isScrollUpArrow) { - const Colour background (findColour (PopupMenu::backgroundColourId)); + const Colour background (findColour (PopupMenu::backgroundColourId)); - g.setGradientFill (ColourGradient (background, 0.0f, height * 0.5f, - background.withAlpha (0.0f), - 0.0f, isScrollUpArrow ? ((float) height) : 0.0f, - false)); + g.setGradientFill (ColourGradient (background, 0.0f, height * 0.5f, + background.withAlpha (0.0f), + 0.0f, isScrollUpArrow ? ((float) height) : 0.0f, + false)); - g.fillRect (1, 1, width - 2, height - 2); + g.fillRect (1, 1, width - 2, height - 2); - const float hw = width * 0.5f; - const float arrowW = height * 0.3f; - const float y1 = height * (isScrollUpArrow ? 0.6f : 0.3f); - const float y2 = height * (isScrollUpArrow ? 0.3f : 0.6f); + const float hw = width * 0.5f; + const float arrowW = height * 0.3f; + const float y1 = height * (isScrollUpArrow ? 0.6f : 0.3f); + const float y2 = height * (isScrollUpArrow ? 0.3f : 0.6f); - Path p; - p.addTriangle (hw - arrowW, y1, - hw + arrowW, y1, - hw, y2); + Path p; + p.addTriangle (hw - arrowW, y1, + hw + arrowW, y1, + hw, y2); - g.setColour (findColour (PopupMenu::textColourId).withAlpha (0.5f)); - g.fillPath (p); + g.setColour (findColour (PopupMenu::textColourId).withAlpha (0.5f)); + g.fillPath (p); } void LookAndFeel::drawPopupMenuItem (Graphics& g, - int width, int height, - const bool isSeparator, - const bool isActive, - const bool isHighlighted, - const bool isTicked, - const bool hasSubMenu, - const String& text, - const String& shortcutKeyText, - Image* image, - const Colour* const textColourToUse) + int width, int height, + const bool isSeparator, + const bool isActive, + const bool isHighlighted, + const bool isTicked, + const bool hasSubMenu, + const String& text, + const String& shortcutKeyText, + Image* image, + const Colour* const textColourToUse) { - const float halfH = height * 0.5f; + const float halfH = height * 0.5f; - if (isSeparator) - { - const float separatorIndent = 5.5f; + if (isSeparator) + { + const float separatorIndent = 5.5f; - g.setColour (Colour (0x33000000)); - g.drawLine (separatorIndent, halfH, width - separatorIndent, halfH); + g.setColour (Colour (0x33000000)); + g.drawLine (separatorIndent, halfH, width - separatorIndent, halfH); - g.setColour (Colour (0x66ffffff)); - g.drawLine (separatorIndent, halfH + 1.0f, width - separatorIndent, halfH + 1.0f); - } - else - { - Colour textColour (findColour (PopupMenu::textColourId)); + g.setColour (Colour (0x66ffffff)); + g.drawLine (separatorIndent, halfH + 1.0f, width - separatorIndent, halfH + 1.0f); + } + else + { + Colour textColour (findColour (PopupMenu::textColourId)); - if (textColourToUse != 0) - textColour = *textColourToUse; + if (textColourToUse != 0) + textColour = *textColourToUse; - if (isHighlighted) - { - g.setColour (findColour (PopupMenu::highlightedBackgroundColourId)); - g.fillRect (1, 1, width - 2, height - 2); + if (isHighlighted) + { + g.setColour (findColour (PopupMenu::highlightedBackgroundColourId)); + g.fillRect (1, 1, width - 2, height - 2); - g.setColour (findColour (PopupMenu::highlightedTextColourId)); - } - else - { - g.setColour (textColour); - } + g.setColour (findColour (PopupMenu::highlightedTextColourId)); + } + else + { + g.setColour (textColour); + } - if (! isActive) - g.setOpacity (0.3f); + if (! isActive) + g.setOpacity (0.3f); - Font font (getPopupMenuFont()); + Font font (getPopupMenuFont()); - if (font.getHeight() > height / 1.3f) - font.setHeight (height / 1.3f); + if (font.getHeight() > height / 1.3f) + font.setHeight (height / 1.3f); - g.setFont (font); + g.setFont (font); - const int leftBorder = (height * 5) / 4; - const int rightBorder = 4; + const int leftBorder = (height * 5) / 4; + const int rightBorder = 4; - if (image != 0) - { - g.drawImageWithin (image, - 2, 1, leftBorder - 4, height - 2, - RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, false); - } - else if (isTicked) - { - const Path tick (getTickShape (1.0f)); - const float th = font.getAscent(); - const float ty = halfH - th * 0.5f; + if (image != 0) + { + g.drawImageWithin (image, + 2, 1, leftBorder - 4, height - 2, + RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, false); + } + else if (isTicked) + { + const Path tick (getTickShape (1.0f)); + const float th = font.getAscent(); + const float ty = halfH - th * 0.5f; - g.fillPath (tick, tick.getTransformToScaleToFit (2.0f, ty, (float) (leftBorder - 4), - th, true)); - } + g.fillPath (tick, tick.getTransformToScaleToFit (2.0f, ty, (float) (leftBorder - 4), + th, true)); + } - g.drawFittedText (text, - leftBorder, 0, - width - (leftBorder + rightBorder), height, - Justification::centredLeft, 1); + g.drawFittedText (text, + leftBorder, 0, + width - (leftBorder + rightBorder), height, + Justification::centredLeft, 1); - if (shortcutKeyText.isNotEmpty()) - { - Font f2 (font); - f2.setHeight (f2.getHeight() * 0.75f); - f2.setHorizontalScale (0.95f); - g.setFont (f2); + if (shortcutKeyText.isNotEmpty()) + { + Font f2 (font); + f2.setHeight (f2.getHeight() * 0.75f); + f2.setHorizontalScale (0.95f); + g.setFont (f2); - g.drawText (shortcutKeyText, - leftBorder, - 0, - width - (leftBorder + rightBorder + 4), - height, - Justification::centredRight, - true); - } + g.drawText (shortcutKeyText, + leftBorder, + 0, + width - (leftBorder + rightBorder + 4), + height, + Justification::centredRight, + true); + } - if (hasSubMenu) - { - const float arrowH = 0.6f * getPopupMenuFont().getAscent(); - const float x = width - height * 0.6f; + if (hasSubMenu) + { + const float arrowH = 0.6f * getPopupMenuFont().getAscent(); + const float x = width - height * 0.6f; - Path p; - p.addTriangle (x, halfH - arrowH * 0.5f, - x, halfH + arrowH * 0.5f, - x + arrowH * 0.6f, halfH); + Path p; + p.addTriangle (x, halfH - arrowH * 0.5f, + x, halfH + arrowH * 0.5f, + x + arrowH * 0.6f, halfH); - g.fillPath (p); - } - } + g.fillPath (p); + } + } } int LookAndFeel::getMenuWindowFlags() { - return ComponentPeer::windowHasDropShadow; + return ComponentPeer::windowHasDropShadow; } void LookAndFeel::drawMenuBarBackground (Graphics& g, int width, int height, - bool, MenuBarComponent& menuBar) + bool, MenuBarComponent& menuBar) { - const Colour baseColour (createBaseColour (menuBar.findColour (PopupMenu::backgroundColourId), false, false, false)); + const Colour baseColour (createBaseColour (menuBar.findColour (PopupMenu::backgroundColourId), false, false, false)); - if (menuBar.isEnabled()) - { - drawShinyButtonShape (g, - -4.0f, 0.0f, - width + 8.0f, (float) height, - 0.0f, - baseColour, - 0.4f, - true, true, true, true); - } - else - { - g.fillAll (baseColour); - } + if (menuBar.isEnabled()) + { + drawShinyButtonShape (g, + -4.0f, 0.0f, + width + 8.0f, (float) height, + 0.0f, + baseColour, + 0.4f, + true, true, true, true); + } + else + { + g.fillAll (baseColour); + } } const Font LookAndFeel::getMenuBarFont (MenuBarComponent& menuBar, int /*itemIndex*/, const String& /*itemText*/) { - return Font (menuBar.getHeight() * 0.7f); + return Font (menuBar.getHeight() * 0.7f); } int LookAndFeel::getMenuBarItemWidth (MenuBarComponent& menuBar, int itemIndex, const String& itemText) { - return getMenuBarFont (menuBar, itemIndex, itemText) - .getStringWidth (itemText) + menuBar.getHeight(); + return getMenuBarFont (menuBar, itemIndex, itemText) + .getStringWidth (itemText) + menuBar.getHeight(); } void LookAndFeel::drawMenuBarItem (Graphics& g, - int width, int height, - int itemIndex, - const String& itemText, - bool isMouseOverItem, - bool isMenuOpen, - bool /*isMouseOverBar*/, - MenuBarComponent& menuBar) + int width, int height, + int itemIndex, + const String& itemText, + bool isMouseOverItem, + bool isMenuOpen, + bool /*isMouseOverBar*/, + MenuBarComponent& menuBar) { - if (! menuBar.isEnabled()) - { - g.setColour (menuBar.findColour (PopupMenu::textColourId) - .withMultipliedAlpha (0.5f)); - } - else if (isMenuOpen || isMouseOverItem) - { - g.fillAll (menuBar.findColour (PopupMenu::highlightedBackgroundColourId)); - g.setColour (menuBar.findColour (PopupMenu::highlightedTextColourId)); - } - else - { - g.setColour (menuBar.findColour (PopupMenu::textColourId)); - } + if (! menuBar.isEnabled()) + { + g.setColour (menuBar.findColour (PopupMenu::textColourId) + .withMultipliedAlpha (0.5f)); + } + else if (isMenuOpen || isMouseOverItem) + { + g.fillAll (menuBar.findColour (PopupMenu::highlightedBackgroundColourId)); + g.setColour (menuBar.findColour (PopupMenu::highlightedTextColourId)); + } + else + { + g.setColour (menuBar.findColour (PopupMenu::textColourId)); + } - g.setFont (getMenuBarFont (menuBar, itemIndex, itemText)); - g.drawFittedText (itemText, 0, 0, width, height, Justification::centred, 1); + g.setFont (getMenuBarFont (menuBar, itemIndex, itemText)); + g.drawFittedText (itemText, 0, 0, width, height, Justification::centred, 1); } void LookAndFeel::fillTextEditorBackground (Graphics& g, int /*width*/, int /*height*/, - TextEditor& textEditor) + TextEditor& textEditor) { - g.fillAll (textEditor.findColour (TextEditor::backgroundColourId)); + g.fillAll (textEditor.findColour (TextEditor::backgroundColourId)); } void LookAndFeel::drawTextEditorOutline (Graphics& g, int width, int height, TextEditor& textEditor) { - if (textEditor.isEnabled()) - { - if (textEditor.hasKeyboardFocus (true) && ! textEditor.isReadOnly()) - { - const int border = 2; + if (textEditor.isEnabled()) + { + if (textEditor.hasKeyboardFocus (true) && ! textEditor.isReadOnly()) + { + const int border = 2; - g.setColour (textEditor.findColour (TextEditor::focusedOutlineColourId)); - g.drawRect (0, 0, width, height, border); + g.setColour (textEditor.findColour (TextEditor::focusedOutlineColourId)); + g.drawRect (0, 0, width, height, border); - g.setOpacity (1.0f); - const Colour shadowColour (textEditor.findColour (TextEditor::shadowColourId).withMultipliedAlpha (0.75f)); - g.drawBevel (0, 0, width, height + 2, border + 2, shadowColour, shadowColour); - } - else - { - g.setColour (textEditor.findColour (TextEditor::outlineColourId)); - g.drawRect (0, 0, width, height); + g.setOpacity (1.0f); + const Colour shadowColour (textEditor.findColour (TextEditor::shadowColourId).withMultipliedAlpha (0.75f)); + g.drawBevel (0, 0, width, height + 2, border + 2, shadowColour, shadowColour); + } + else + { + g.setColour (textEditor.findColour (TextEditor::outlineColourId)); + g.drawRect (0, 0, width, height); - g.setOpacity (1.0f); - const Colour shadowColour (textEditor.findColour (TextEditor::shadowColourId)); - g.drawBevel (0, 0, width, height + 2, 3, shadowColour, shadowColour); - } - } + g.setOpacity (1.0f); + const Colour shadowColour (textEditor.findColour (TextEditor::shadowColourId)); + g.drawBevel (0, 0, width, height + 2, 3, shadowColour, shadowColour); + } + } } void LookAndFeel::drawComboBox (Graphics& g, int width, int height, - const bool isButtonDown, - int buttonX, int buttonY, - int buttonW, int buttonH, - ComboBox& box) + const bool isButtonDown, + int buttonX, int buttonY, + int buttonW, int buttonH, + ComboBox& box) { - g.fillAll (box.findColour (ComboBox::backgroundColourId)); + g.fillAll (box.findColour (ComboBox::backgroundColourId)); - if (box.isEnabled() && box.hasKeyboardFocus (false)) - { - g.setColour (box.findColour (TextButton::buttonColourId)); - g.drawRect (0, 0, width, height, 2); - } - else - { - g.setColour (box.findColour (ComboBox::outlineColourId)); - g.drawRect (0, 0, width, height); - } + if (box.isEnabled() && box.hasKeyboardFocus (false)) + { + g.setColour (box.findColour (TextButton::buttonColourId)); + g.drawRect (0, 0, width, height, 2); + } + else + { + g.setColour (box.findColour (ComboBox::outlineColourId)); + g.drawRect (0, 0, width, height); + } - const float outlineThickness = box.isEnabled() ? (isButtonDown ? 1.2f : 0.5f) : 0.3f; + const float outlineThickness = box.isEnabled() ? (isButtonDown ? 1.2f : 0.5f) : 0.3f; - const Colour baseColour (createBaseColour (box.findColour (ComboBox::buttonColourId), - box.hasKeyboardFocus (true), - false, isButtonDown) - .withMultipliedAlpha (box.isEnabled() ? 1.0f : 0.5f)); + const Colour baseColour (createBaseColour (box.findColour (ComboBox::buttonColourId), + box.hasKeyboardFocus (true), + false, isButtonDown) + .withMultipliedAlpha (box.isEnabled() ? 1.0f : 0.5f)); - drawGlassLozenge (g, - buttonX + outlineThickness, buttonY + outlineThickness, - buttonW - outlineThickness * 2.0f, buttonH - outlineThickness * 2.0f, - baseColour, outlineThickness, -1.0f, - true, true, true, true); + drawGlassLozenge (g, + buttonX + outlineThickness, buttonY + outlineThickness, + buttonW - outlineThickness * 2.0f, buttonH - outlineThickness * 2.0f, + baseColour, outlineThickness, -1.0f, + true, true, true, true); - if (box.isEnabled()) - { - const float arrowX = 0.3f; - const float arrowH = 0.2f; + if (box.isEnabled()) + { + const float arrowX = 0.3f; + const float arrowH = 0.2f; - Path p; - p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.45f - arrowH), - buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.45f, - buttonX + buttonW * arrowX, buttonY + buttonH * 0.45f); + Path p; + p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.45f - arrowH), + buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.45f, + buttonX + buttonW * arrowX, buttonY + buttonH * 0.45f); - p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.55f + arrowH), - buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.55f, - buttonX + buttonW * arrowX, buttonY + buttonH * 0.55f); + p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.55f + arrowH), + buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.55f, + buttonX + buttonW * arrowX, buttonY + buttonH * 0.55f); - g.setColour (box.findColour (ComboBox::arrowColourId)); - g.fillPath (p); - } + g.setColour (box.findColour (ComboBox::arrowColourId)); + g.fillPath (p); + } } const Font LookAndFeel::getComboBoxFont (ComboBox& box) { - return Font (jmin (15.0f, box.getHeight() * 0.85f)); + return Font (jmin (15.0f, box.getHeight() * 0.85f)); } Label* LookAndFeel::createComboBoxTextBox (ComboBox&) { - return new Label (String::empty, String::empty); + return new Label (String::empty, String::empty); } void LookAndFeel::positionComboBoxText (ComboBox& box, Label& label) { - label.setBounds (1, 1, - box.getWidth() + 3 - box.getHeight(), - box.getHeight() - 2); + label.setBounds (1, 1, + box.getWidth() + 3 - box.getHeight(), + box.getHeight() - 2); - label.setFont (getComboBoxFont (box)); + label.setFont (getComboBoxFont (box)); } void LookAndFeel::drawLabel (Graphics& g, Label& label) { - g.fillAll (label.findColour (Label::backgroundColourId)); + g.fillAll (label.findColour (Label::backgroundColourId)); - if (! label.isBeingEdited()) - { - const float alpha = label.isEnabled() ? 1.0f : 0.5f; + if (! label.isBeingEdited()) + { + const float alpha = label.isEnabled() ? 1.0f : 0.5f; - g.setColour (label.findColour (Label::textColourId).withMultipliedAlpha (alpha)); - g.setFont (label.getFont()); - g.drawFittedText (label.getText(), - label.getHorizontalBorderSize(), - label.getVerticalBorderSize(), - label.getWidth() - 2 * label.getHorizontalBorderSize(), - label.getHeight() - 2 * label.getVerticalBorderSize(), - label.getJustificationType(), - jmax (1, (int) (label.getHeight() / label.getFont().getHeight())), - label.getMinimumHorizontalScale()); + g.setColour (label.findColour (Label::textColourId).withMultipliedAlpha (alpha)); + g.setFont (label.getFont()); + g.drawFittedText (label.getText(), + label.getHorizontalBorderSize(), + label.getVerticalBorderSize(), + label.getWidth() - 2 * label.getHorizontalBorderSize(), + label.getHeight() - 2 * label.getVerticalBorderSize(), + label.getJustificationType(), + jmax (1, (int) (label.getHeight() / label.getFont().getHeight())), + label.getMinimumHorizontalScale()); - g.setColour (label.findColour (Label::outlineColourId).withMultipliedAlpha (alpha)); - g.drawRect (0, 0, label.getWidth(), label.getHeight()); - } - else if (label.isEnabled()) - { - g.setColour (label.findColour (Label::outlineColourId)); - g.drawRect (0, 0, label.getWidth(), label.getHeight()); - } + g.setColour (label.findColour (Label::outlineColourId).withMultipliedAlpha (alpha)); + g.drawRect (0, 0, label.getWidth(), label.getHeight()); + } + else if (label.isEnabled()) + { + g.setColour (label.findColour (Label::outlineColourId)); + g.drawRect (0, 0, label.getWidth(), label.getHeight()); + } } void LookAndFeel::drawLinearSliderBackground (Graphics& g, - int x, int y, - int width, int height, - float /*sliderPos*/, - float /*minSliderPos*/, - float /*maxSliderPos*/, - const Slider::SliderStyle /*style*/, - Slider& slider) + int x, int y, + int width, int height, + float /*sliderPos*/, + float /*minSliderPos*/, + float /*maxSliderPos*/, + const Slider::SliderStyle /*style*/, + Slider& slider) { - const float sliderRadius = (float) (getSliderThumbRadius (slider) - 2); + const float sliderRadius = (float) (getSliderThumbRadius (slider) - 2); - const Colour trackColour (slider.findColour (Slider::trackColourId)); - const Colour gradCol1 (trackColour.overlaidWith (Colours::black.withAlpha (slider.isEnabled() ? 0.25f : 0.13f))); - const Colour gradCol2 (trackColour.overlaidWith (Colour (0x14000000))); - Path indent; + const Colour trackColour (slider.findColour (Slider::trackColourId)); + const Colour gradCol1 (trackColour.overlaidWith (Colours::black.withAlpha (slider.isEnabled() ? 0.25f : 0.13f))); + const Colour gradCol2 (trackColour.overlaidWith (Colour (0x14000000))); + Path indent; - if (slider.isHorizontal()) - { - const float iy = y + height * 0.5f - sliderRadius * 0.5f; - const float ih = sliderRadius; + if (slider.isHorizontal()) + { + const float iy = y + height * 0.5f - sliderRadius * 0.5f; + const float ih = sliderRadius; - g.setGradientFill (ColourGradient (gradCol1, 0.0f, iy, - gradCol2, 0.0f, iy + ih, false)); + g.setGradientFill (ColourGradient (gradCol1, 0.0f, iy, + gradCol2, 0.0f, iy + ih, false)); - indent.addRoundedRectangle (x - sliderRadius * 0.5f, iy, - width + sliderRadius, ih, - 5.0f); - g.fillPath (indent); - } - else - { - const float ix = x + width * 0.5f - sliderRadius * 0.5f; - const float iw = sliderRadius; + indent.addRoundedRectangle (x - sliderRadius * 0.5f, iy, + width + sliderRadius, ih, + 5.0f); + g.fillPath (indent); + } + else + { + const float ix = x + width * 0.5f - sliderRadius * 0.5f; + const float iw = sliderRadius; - g.setGradientFill (ColourGradient (gradCol1, ix, 0.0f, - gradCol2, ix + iw, 0.0f, false)); + g.setGradientFill (ColourGradient (gradCol1, ix, 0.0f, + gradCol2, ix + iw, 0.0f, false)); - indent.addRoundedRectangle (ix, y - sliderRadius * 0.5f, - iw, height + sliderRadius, - 5.0f); - g.fillPath (indent); - } + indent.addRoundedRectangle (ix, y - sliderRadius * 0.5f, + iw, height + sliderRadius, + 5.0f); + g.fillPath (indent); + } - g.setColour (Colour (0x4c000000)); - g.strokePath (indent, PathStrokeType (0.5f)); + g.setColour (Colour (0x4c000000)); + g.strokePath (indent, PathStrokeType (0.5f)); } void LookAndFeel::drawLinearSliderThumb (Graphics& g, - int x, int y, - int width, int height, - float sliderPos, - float minSliderPos, - float maxSliderPos, - const Slider::SliderStyle style, - Slider& slider) + int x, int y, + int width, int height, + float sliderPos, + float minSliderPos, + float maxSliderPos, + const Slider::SliderStyle style, + Slider& slider) { - const float sliderRadius = (float) (getSliderThumbRadius (slider) - 2); + const float sliderRadius = (float) (getSliderThumbRadius (slider) - 2); - Colour knobColour (createBaseColour (slider.findColour (Slider::thumbColourId), - slider.hasKeyboardFocus (false) && slider.isEnabled(), - slider.isMouseOverOrDragging() && slider.isEnabled(), - slider.isMouseButtonDown() && slider.isEnabled())); + Colour knobColour (createBaseColour (slider.findColour (Slider::thumbColourId), + slider.hasKeyboardFocus (false) && slider.isEnabled(), + slider.isMouseOverOrDragging() && slider.isEnabled(), + slider.isMouseButtonDown() && slider.isEnabled())); - const float outlineThickness = slider.isEnabled() ? 0.8f : 0.3f; + const float outlineThickness = slider.isEnabled() ? 0.8f : 0.3f; - if (style == Slider::LinearHorizontal || style == Slider::LinearVertical) - { - float kx, ky; + if (style == Slider::LinearHorizontal || style == Slider::LinearVertical) + { + float kx, ky; - if (style == Slider::LinearVertical) - { - kx = x + width * 0.5f; - ky = sliderPos; - } - else - { - kx = sliderPos; - ky = y + height * 0.5f; - } + if (style == Slider::LinearVertical) + { + kx = x + width * 0.5f; + ky = sliderPos; + } + else + { + kx = sliderPos; + ky = y + height * 0.5f; + } - drawGlassSphere (g, - kx - sliderRadius, - ky - sliderRadius, - sliderRadius * 2.0f, - knobColour, outlineThickness); - } - else - { - if (style == Slider::ThreeValueVertical) - { - drawGlassSphere (g, x + width * 0.5f - sliderRadius, - sliderPos - sliderRadius, - sliderRadius * 2.0f, - knobColour, outlineThickness); - } - else if (style == Slider::ThreeValueHorizontal) - { - drawGlassSphere (g,sliderPos - sliderRadius, - y + height * 0.5f - sliderRadius, - sliderRadius * 2.0f, - knobColour, outlineThickness); - } + drawGlassSphere (g, + kx - sliderRadius, + ky - sliderRadius, + sliderRadius * 2.0f, + knobColour, outlineThickness); + } + else + { + if (style == Slider::ThreeValueVertical) + { + drawGlassSphere (g, x + width * 0.5f - sliderRadius, + sliderPos - sliderRadius, + sliderRadius * 2.0f, + knobColour, outlineThickness); + } + else if (style == Slider::ThreeValueHorizontal) + { + drawGlassSphere (g,sliderPos - sliderRadius, + y + height * 0.5f - sliderRadius, + sliderRadius * 2.0f, + knobColour, outlineThickness); + } - if (style == Slider::TwoValueVertical || style == Slider::ThreeValueVertical) - { - const float sr = jmin (sliderRadius, width * 0.4f); + if (style == Slider::TwoValueVertical || style == Slider::ThreeValueVertical) + { + const float sr = jmin (sliderRadius, width * 0.4f); - drawGlassPointer (g, jmax (0.0f, x + width * 0.5f - sliderRadius * 2.0f), - minSliderPos - sliderRadius, - sliderRadius * 2.0f, knobColour, outlineThickness, 1); + drawGlassPointer (g, jmax (0.0f, x + width * 0.5f - sliderRadius * 2.0f), + minSliderPos - sliderRadius, + sliderRadius * 2.0f, knobColour, outlineThickness, 1); - drawGlassPointer (g, jmin (x + width - sliderRadius * 2.0f, x + width * 0.5f), maxSliderPos - sr, - sliderRadius * 2.0f, knobColour, outlineThickness, 3); - } - else if (style == Slider::TwoValueHorizontal || style == Slider::ThreeValueHorizontal) - { - const float sr = jmin (sliderRadius, height * 0.4f); + drawGlassPointer (g, jmin (x + width - sliderRadius * 2.0f, x + width * 0.5f), maxSliderPos - sr, + sliderRadius * 2.0f, knobColour, outlineThickness, 3); + } + else if (style == Slider::TwoValueHorizontal || style == Slider::ThreeValueHorizontal) + { + const float sr = jmin (sliderRadius, height * 0.4f); - drawGlassPointer (g, minSliderPos - sr, - jmax (0.0f, y + height * 0.5f - sliderRadius * 2.0f), - sliderRadius * 2.0f, knobColour, outlineThickness, 2); + drawGlassPointer (g, minSliderPos - sr, + jmax (0.0f, y + height * 0.5f - sliderRadius * 2.0f), + sliderRadius * 2.0f, knobColour, outlineThickness, 2); - drawGlassPointer (g, maxSliderPos - sliderRadius, - jmin (y + height - sliderRadius * 2.0f, y + height * 0.5f), - sliderRadius * 2.0f, knobColour, outlineThickness, 4); - } - } + drawGlassPointer (g, maxSliderPos - sliderRadius, + jmin (y + height - sliderRadius * 2.0f, y + height * 0.5f), + sliderRadius * 2.0f, knobColour, outlineThickness, 4); + } + } } void LookAndFeel::drawLinearSlider (Graphics& g, - int x, int y, - int width, int height, - float sliderPos, - float minSliderPos, - float maxSliderPos, - const Slider::SliderStyle style, - Slider& slider) + int x, int y, + int width, int height, + float sliderPos, + float minSliderPos, + float maxSliderPos, + const Slider::SliderStyle style, + Slider& slider) { - g.fillAll (slider.findColour (Slider::backgroundColourId)); + g.fillAll (slider.findColour (Slider::backgroundColourId)); - if (style == Slider::LinearBar) - { - const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled(); + if (style == Slider::LinearBar) + { + const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled(); - Colour baseColour (createBaseColour (slider.findColour (Slider::thumbColourId) - .withMultipliedSaturation (slider.isEnabled() ? 1.0f : 0.5f), - false, - isMouseOver, - isMouseOver || slider.isMouseButtonDown())); + Colour baseColour (createBaseColour (slider.findColour (Slider::thumbColourId) + .withMultipliedSaturation (slider.isEnabled() ? 1.0f : 0.5f), + false, + isMouseOver, + isMouseOver || slider.isMouseButtonDown())); - drawShinyButtonShape (g, - (float) x, (float) y, sliderPos - (float) x, (float) height, 0.0f, - baseColour, - slider.isEnabled() ? 0.9f : 0.3f, - true, true, true, true); - } - else - { - drawLinearSliderBackground (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider); - drawLinearSliderThumb (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider); - } + drawShinyButtonShape (g, + (float) x, (float) y, sliderPos - (float) x, (float) height, 0.0f, + baseColour, + slider.isEnabled() ? 0.9f : 0.3f, + true, true, true, true); + } + else + { + drawLinearSliderBackground (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider); + drawLinearSliderThumb (g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider); + } } int LookAndFeel::getSliderThumbRadius (Slider& slider) { - return jmin (7, - slider.getHeight() / 2, - slider.getWidth() / 2) + 2; + return jmin (7, + slider.getHeight() / 2, + slider.getWidth() / 2) + 2; } void LookAndFeel::drawRotarySlider (Graphics& g, - int x, int y, - int width, int height, - float sliderPos, - const float rotaryStartAngle, - const float rotaryEndAngle, - Slider& slider) + int x, int y, + int width, int height, + float sliderPos, + const float rotaryStartAngle, + const float rotaryEndAngle, + Slider& slider) { - const float radius = jmin (width / 2, height / 2) - 2.0f; - const float centreX = x + width * 0.5f; - const float centreY = y + height * 0.5f; - const float rx = centreX - radius; - const float ry = centreY - radius; - const float rw = radius * 2.0f; - const float angle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle); - const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled(); + const float radius = jmin (width / 2, height / 2) - 2.0f; + const float centreX = x + width * 0.5f; + const float centreY = y + height * 0.5f; + const float rx = centreX - radius; + const float ry = centreY - radius; + const float rw = radius * 2.0f; + const float angle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle); + const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled(); - if (radius > 12.0f) - { - if (slider.isEnabled()) - g.setColour (slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 1.0f : 0.7f)); - else - g.setColour (Colour (0x80808080)); + if (radius > 12.0f) + { + if (slider.isEnabled()) + g.setColour (slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 1.0f : 0.7f)); + else + g.setColour (Colour (0x80808080)); - const float thickness = 0.7f; + const float thickness = 0.7f; - { - Path filledArc; - filledArc.addPieSegment (rx, ry, rw, rw, - rotaryStartAngle, - angle, - thickness); + { + Path filledArc; + filledArc.addPieSegment (rx, ry, rw, rw, + rotaryStartAngle, + angle, + thickness); - g.fillPath (filledArc); - } + g.fillPath (filledArc); + } - if (thickness > 0) - { - const float innerRadius = radius * 0.2f; - Path p; - p.addTriangle (-innerRadius, 0.0f, - 0.0f, -radius * thickness * 1.1f, - innerRadius, 0.0f); + if (thickness > 0) + { + const float innerRadius = radius * 0.2f; + Path p; + p.addTriangle (-innerRadius, 0.0f, + 0.0f, -radius * thickness * 1.1f, + innerRadius, 0.0f); - p.addEllipse (-innerRadius, -innerRadius, innerRadius * 2.0f, innerRadius * 2.0f); + p.addEllipse (-innerRadius, -innerRadius, innerRadius * 2.0f, innerRadius * 2.0f); - g.fillPath (p, AffineTransform::rotation (angle).translated (centreX, centreY)); - } + g.fillPath (p, AffineTransform::rotation (angle).translated (centreX, centreY)); + } - if (slider.isEnabled()) - g.setColour (slider.findColour (Slider::rotarySliderOutlineColourId)); - else - g.setColour (Colour (0x80808080)); + if (slider.isEnabled()) + g.setColour (slider.findColour (Slider::rotarySliderOutlineColourId)); + else + g.setColour (Colour (0x80808080)); - Path outlineArc; - outlineArc.addPieSegment (rx, ry, rw, rw, rotaryStartAngle, rotaryEndAngle, thickness); - outlineArc.closeSubPath(); + Path outlineArc; + outlineArc.addPieSegment (rx, ry, rw, rw, rotaryStartAngle, rotaryEndAngle, thickness); + outlineArc.closeSubPath(); - g.strokePath (outlineArc, PathStrokeType (slider.isEnabled() ? (isMouseOver ? 2.0f : 1.2f) : 0.3f)); - } - else - { - if (slider.isEnabled()) - g.setColour (slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 1.0f : 0.7f)); - else - g.setColour (Colour (0x80808080)); + g.strokePath (outlineArc, PathStrokeType (slider.isEnabled() ? (isMouseOver ? 2.0f : 1.2f) : 0.3f)); + } + else + { + if (slider.isEnabled()) + g.setColour (slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 1.0f : 0.7f)); + else + g.setColour (Colour (0x80808080)); - Path p; - p.addEllipse (-0.4f * rw, -0.4f * rw, rw * 0.8f, rw * 0.8f); - PathStrokeType (rw * 0.1f).createStrokedPath (p, p); + Path p; + p.addEllipse (-0.4f * rw, -0.4f * rw, rw * 0.8f, rw * 0.8f); + PathStrokeType (rw * 0.1f).createStrokedPath (p, p); - p.addLineSegment (0.0f, 0.0f, 0.0f, -radius, rw * 0.2f); + p.addLineSegment (0.0f, 0.0f, 0.0f, -radius, rw * 0.2f); - g.fillPath (p, AffineTransform::rotation (angle).translated (centreX, centreY)); - } + g.fillPath (p, AffineTransform::rotation (angle).translated (centreX, centreY)); + } } Button* LookAndFeel::createSliderButton (const bool isIncrement) { - return new TextButton (isIncrement ? "+" : "-", String::empty); + return new TextButton (isIncrement ? "+" : "-", String::empty); } class SliderLabelComp : public Label { public: - SliderLabelComp() : Label (String::empty, String::empty) {} - ~SliderLabelComp() {} + SliderLabelComp() : Label (String::empty, String::empty) {} + ~SliderLabelComp() {} - void mouseWheelMove (const MouseEvent&, float, float) {} + void mouseWheelMove (const MouseEvent&, float, float) {} }; Label* LookAndFeel::createSliderTextBox (Slider& slider) { - Label* const l = new SliderLabelComp(); + Label* const l = new SliderLabelComp(); - l->setJustificationType (Justification::centred); + l->setJustificationType (Justification::centred); - l->setColour (Label::textColourId, slider.findColour (Slider::textBoxTextColourId)); + l->setColour (Label::textColourId, slider.findColour (Slider::textBoxTextColourId)); - l->setColour (Label::backgroundColourId, - (slider.getSliderStyle() == Slider::LinearBar) ? Colours::transparentBlack - : slider.findColour (Slider::textBoxBackgroundColourId)); - l->setColour (Label::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId)); + l->setColour (Label::backgroundColourId, + (slider.getSliderStyle() == Slider::LinearBar) ? Colours::transparentBlack + : slider.findColour (Slider::textBoxBackgroundColourId)); + l->setColour (Label::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId)); - l->setColour (TextEditor::textColourId, slider.findColour (Slider::textBoxTextColourId)); + l->setColour (TextEditor::textColourId, slider.findColour (Slider::textBoxTextColourId)); - l->setColour (TextEditor::backgroundColourId, - slider.findColour (Slider::textBoxBackgroundColourId) - .withAlpha (slider.getSliderStyle() == Slider::LinearBar ? 0.7f : 1.0f)); + l->setColour (TextEditor::backgroundColourId, + slider.findColour (Slider::textBoxBackgroundColourId) + .withAlpha (slider.getSliderStyle() == Slider::LinearBar ? 0.7f : 1.0f)); - l->setColour (TextEditor::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId)); + l->setColour (TextEditor::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId)); - return l; + return l; } ImageEffectFilter* LookAndFeel::getSliderEffect() { - return 0; + return 0; } static const TextLayout layoutTooltipText (const String& text) throw() { - const float tooltipFontSize = 12.0f; - const int maxToolTipWidth = 400; + const float tooltipFontSize = 12.0f; + const int maxToolTipWidth = 400; - const Font f (tooltipFontSize, Font::bold); - TextLayout tl (text, f); - tl.layout (maxToolTipWidth, Justification::left, true); + const Font f (tooltipFontSize, Font::bold); + TextLayout tl (text, f); + tl.layout (maxToolTipWidth, Justification::left, true); - return tl; + return tl; } void LookAndFeel::getTooltipSize (const String& tipText, int& width, int& height) { - const TextLayout tl (layoutTooltipText (tipText)); + const TextLayout tl (layoutTooltipText (tipText)); - width = tl.getWidth() + 14; - height = tl.getHeight() + 6; + width = tl.getWidth() + 14; + height = tl.getHeight() + 6; } void LookAndFeel::drawTooltip (Graphics& g, const String& text, int width, int height) { - g.fillAll (findColour (TooltipWindow::backgroundColourId)); + g.fillAll (findColour (TooltipWindow::backgroundColourId)); - const Colour textCol (findColour (TooltipWindow::textColourId)); + const Colour textCol (findColour (TooltipWindow::textColourId)); #if ! JUCE_MAC // The mac windows already have a non-optional 1 pix outline, so don't double it here.. - g.setColour (findColour (TooltipWindow::outlineColourId)); - g.drawRect (0, 0, width, height, 1); + g.setColour (findColour (TooltipWindow::outlineColourId)); + g.drawRect (0, 0, width, height, 1); #endif - const TextLayout tl (layoutTooltipText (text)); + const TextLayout tl (layoutTooltipText (text)); - g.setColour (findColour (TooltipWindow::textColourId)); - tl.drawWithin (g, 0, 0, width, height, Justification::centred); + g.setColour (findColour (TooltipWindow::textColourId)); + tl.drawWithin (g, 0, 0, width, height, Justification::centred); } Button* LookAndFeel::createFilenameComponentBrowseButton (const String& text) { - return new TextButton (text, TRANS("click to browse for a different file")); + return new TextButton (text, TRANS("click to browse for a different file")); } void LookAndFeel::layoutFilenameComponent (FilenameComponent& filenameComp, - ComboBox* filenameBox, - Button* browseButton) + ComboBox* filenameBox, + Button* browseButton) { - browseButton->setSize (80, filenameComp.getHeight()); + browseButton->setSize (80, filenameComp.getHeight()); - TextButton* const tb = dynamic_cast (browseButton); + TextButton* const tb = dynamic_cast (browseButton); - if (tb != 0) - tb->changeWidthToFitText(); + if (tb != 0) + tb->changeWidthToFitText(); - browseButton->setTopRightPosition (filenameComp.getWidth(), 0); + browseButton->setTopRightPosition (filenameComp.getWidth(), 0); - filenameBox->setBounds (0, 0, browseButton->getX(), filenameComp.getHeight()); + filenameBox->setBounds (0, 0, browseButton->getX(), filenameComp.getHeight()); } void LookAndFeel::drawImageButton (Graphics& g, Image* image, - int imageX, int imageY, int imageW, int imageH, - const Colour& overlayColour, - float imageOpacity, - ImageButton& button) + int imageX, int imageY, int imageW, int imageH, + const Colour& overlayColour, + float imageOpacity, + ImageButton& button) { - if (! button.isEnabled()) - imageOpacity *= 0.3f; + if (! button.isEnabled()) + imageOpacity *= 0.3f; - if (! overlayColour.isOpaque()) - { - g.setOpacity (imageOpacity); + if (! overlayColour.isOpaque()) + { + g.setOpacity (imageOpacity); - g.drawImage (image, imageX, imageY, imageW, imageH, - 0, 0, image->getWidth(), image->getHeight(), false); - } + g.drawImage (image, imageX, imageY, imageW, imageH, + 0, 0, image->getWidth(), image->getHeight(), false); + } - if (! overlayColour.isTransparent()) - { - g.setColour (overlayColour); + if (! overlayColour.isTransparent()) + { + g.setColour (overlayColour); - g.drawImage (image, imageX, imageY, imageW, imageH, - 0, 0, image->getWidth(), image->getHeight(), true); - } + g.drawImage (image, imageX, imageY, imageW, imageH, + 0, 0, image->getWidth(), image->getHeight(), true); + } } void LookAndFeel::drawCornerResizer (Graphics& g, - int w, int h, - bool /*isMouseOver*/, - bool /*isMouseDragging*/) + int w, int h, + bool /*isMouseOver*/, + bool /*isMouseDragging*/) { - const float lineThickness = jmin (w, h) * 0.075f; + const float lineThickness = jmin (w, h) * 0.075f; - for (float i = 0.0f; i < 1.0f; i += 0.3f) - { - g.setColour (Colours::lightgrey); + for (float i = 0.0f; i < 1.0f; i += 0.3f) + { + g.setColour (Colours::lightgrey); - g.drawLine (w * i, - h + 1.0f, - w + 1.0f, - h * i, - lineThickness); + g.drawLine (w * i, + h + 1.0f, + w + 1.0f, + h * i, + lineThickness); - g.setColour (Colours::darkgrey); + g.setColour (Colours::darkgrey); - g.drawLine (w * i + lineThickness, - h + 1.0f, - w + 1.0f, - h * i + lineThickness, - lineThickness); - } + g.drawLine (w * i + lineThickness, + h + 1.0f, + w + 1.0f, + h * i + lineThickness, + lineThickness); + } } void LookAndFeel::drawResizableFrame (Graphics&, int /*w*/, int /*h*/, - const BorderSize& /*borders*/) + const BorderSize& /*borders*/) { } void LookAndFeel::fillResizableWindowBackground (Graphics& g, int /*w*/, int /*h*/, - const BorderSize& /*border*/, ResizableWindow& window) + const BorderSize& /*border*/, ResizableWindow& window) { g.fillAll (window.getBackgroundColour()); } void LookAndFeel::drawResizableWindowBorder (Graphics& g, int w, int h, - const BorderSize& border, ResizableWindow&) + const BorderSize& border, ResizableWindow&) { - g.setColour (Colour (0x80000000)); - g.drawRect (0, 0, w, h); + g.setColour (Colour (0x80000000)); + g.drawRect (0, 0, w, h); - g.setColour (Colour (0x19000000)); - g.drawRect (border.getLeft() - 1, - border.getTop() - 1, - w + 2 - border.getLeftAndRight(), - h + 2 - border.getTopAndBottom()); + g.setColour (Colour (0x19000000)); + g.drawRect (border.getLeft() - 1, + border.getTop() - 1, + w + 2 - border.getLeftAndRight(), + h + 2 - border.getTopAndBottom()); } void LookAndFeel::drawDocumentWindowTitleBar (DocumentWindow& window, - Graphics& g, int w, int h, - int titleSpaceX, int titleSpaceW, - const Image* icon, - bool drawTitleTextOnLeft) + Graphics& g, int w, int h, + int titleSpaceX, int titleSpaceW, + const Image* icon, + bool drawTitleTextOnLeft) { - const bool isActive = window.isActiveWindow(); + const bool isActive = window.isActiveWindow(); - g.setGradientFill (ColourGradient (window.getBackgroundColour(), - 0.0f, 0.0f, - window.getBackgroundColour().contrasting (isActive ? 0.15f : 0.05f), - 0.0f, (float) h, false)); - g.fillAll(); + g.setGradientFill (ColourGradient (window.getBackgroundColour(), + 0.0f, 0.0f, + window.getBackgroundColour().contrasting (isActive ? 0.15f : 0.05f), + 0.0f, (float) h, false)); + g.fillAll(); - Font font (h * 0.65f, Font::bold); - g.setFont (font); + Font font (h * 0.65f, Font::bold); + g.setFont (font); - int textW = font.getStringWidth (window.getName()); - int iconW = 0; - int iconH = 0; + int textW = font.getStringWidth (window.getName()); + int iconW = 0; + int iconH = 0; - if (icon != 0) - { - iconH = (int) font.getHeight(); - iconW = icon->getWidth() * iconH / icon->getHeight() + 4; - } + if (icon != 0) + { + iconH = (int) font.getHeight(); + iconW = icon->getWidth() * iconH / icon->getHeight() + 4; + } - textW = jmin (titleSpaceW, textW + iconW); - int textX = drawTitleTextOnLeft ? titleSpaceX - : jmax (titleSpaceX, (w - textW) / 2); + textW = jmin (titleSpaceW, textW + iconW); + int textX = drawTitleTextOnLeft ? titleSpaceX + : jmax (titleSpaceX, (w - textW) / 2); - if (textX + textW > titleSpaceX + titleSpaceW) - textX = titleSpaceX + titleSpaceW - textW; + if (textX + textW > titleSpaceX + titleSpaceW) + textX = titleSpaceX + titleSpaceW - textW; - if (icon != 0) - { - g.setOpacity (isActive ? 1.0f : 0.6f); - g.drawImageWithin (icon, textX, (h - iconH) / 2, iconW, iconH, - RectanglePlacement::centred, false); - textX += iconW; - textW -= iconW; - } + if (icon != 0) + { + g.setOpacity (isActive ? 1.0f : 0.6f); + g.drawImageWithin (icon, textX, (h - iconH) / 2, iconW, iconH, + RectanglePlacement::centred, false); + textX += iconW; + textW -= iconW; + } - if (window.isColourSpecified (DocumentWindow::textColourId) || isColourSpecified (DocumentWindow::textColourId)) - g.setColour (findColour (DocumentWindow::textColourId)); - else - g.setColour (window.getBackgroundColour().contrasting (isActive ? 0.7f : 0.4f)); + if (window.isColourSpecified (DocumentWindow::textColourId) || isColourSpecified (DocumentWindow::textColourId)) + g.setColour (findColour (DocumentWindow::textColourId)); + else + g.setColour (window.getBackgroundColour().contrasting (isActive ? 0.7f : 0.4f)); - g.drawText (window.getName(), textX, 0, textW, h, Justification::centredLeft, true); + g.drawText (window.getName(), textX, 0, textW, h, Justification::centredLeft, true); } class GlassWindowButton : public Button { public: - GlassWindowButton (const String& name, const Colour& col, - const Path& normalShape_, - const Path& toggledShape_) throw() - : Button (name), - colour (col), - normalShape (normalShape_), - toggledShape (toggledShape_) - { - } + GlassWindowButton (const String& name, const Colour& col, + const Path& normalShape_, + const Path& toggledShape_) throw() + : Button (name), + colour (col), + normalShape (normalShape_), + toggledShape (toggledShape_) + { + } - ~GlassWindowButton() - { - } + ~GlassWindowButton() + { + } - void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) - { - float alpha = isMouseOverButton ? (isButtonDown ? 1.0f : 0.8f) : 0.55f; + void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) + { + float alpha = isMouseOverButton ? (isButtonDown ? 1.0f : 0.8f) : 0.55f; - if (! isEnabled()) - alpha *= 0.5f; + if (! isEnabled()) + alpha *= 0.5f; - float x = 0, y = 0, diam; + float x = 0, y = 0, diam; - if (getWidth() < getHeight()) - { - diam = (float) getWidth(); - y = (getHeight() - getWidth()) * 0.5f; - } - else - { - diam = (float) getHeight(); - y = (getWidth() - getHeight()) * 0.5f; - } + if (getWidth() < getHeight()) + { + diam = (float) getWidth(); + y = (getHeight() - getWidth()) * 0.5f; + } + else + { + diam = (float) getHeight(); + y = (getWidth() - getHeight()) * 0.5f; + } - x += diam * 0.05f; - y += diam * 0.05f; - diam *= 0.9f; + x += diam * 0.05f; + y += diam * 0.05f; + diam *= 0.9f; - g.setGradientFill (ColourGradient (Colour::greyLevel (0.9f).withAlpha (alpha), 0, y + diam, - Colour::greyLevel (0.6f).withAlpha (alpha), 0, y, false)); - g.fillEllipse (x, y, diam, diam); + g.setGradientFill (ColourGradient (Colour::greyLevel (0.9f).withAlpha (alpha), 0, y + diam, + Colour::greyLevel (0.6f).withAlpha (alpha), 0, y, false)); + g.fillEllipse (x, y, diam, diam); - x += 2.0f; - y += 2.0f; - diam -= 4.0f; + x += 2.0f; + y += 2.0f; + diam -= 4.0f; - LookAndFeel::drawGlassSphere (g, x, y, diam, colour.withAlpha (alpha), 1.0f); + LookAndFeel::drawGlassSphere (g, x, y, diam, colour.withAlpha (alpha), 1.0f); - Path& p = getToggleState() ? toggledShape : normalShape; + Path& p = getToggleState() ? toggledShape : normalShape; - const AffineTransform t (p.getTransformToScaleToFit (x + diam * 0.3f, y + diam * 0.3f, - diam * 0.4f, diam * 0.4f, true)); + const AffineTransform t (p.getTransformToScaleToFit (x + diam * 0.3f, y + diam * 0.3f, + diam * 0.4f, diam * 0.4f, true)); - g.setColour (Colours::black.withAlpha (alpha * 0.6f)); - g.fillPath (p, t); - } + g.setColour (Colours::black.withAlpha (alpha * 0.6f)); + g.fillPath (p, t); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - Colour colour; - Path normalShape, toggledShape; + Colour colour; + Path normalShape, toggledShape; - GlassWindowButton (const GlassWindowButton&); - const GlassWindowButton& operator= (const GlassWindowButton&); + GlassWindowButton (const GlassWindowButton&); + const GlassWindowButton& operator= (const GlassWindowButton&); }; Button* LookAndFeel::createDocumentWindowButton (int buttonType) { - Path shape; - const float crossThickness = 0.25f; + Path shape; + const float crossThickness = 0.25f; - if (buttonType == DocumentWindow::closeButton) - { - shape.addLineSegment (0.0f, 0.0f, 1.0f, 1.0f, crossThickness * 1.4f); - shape.addLineSegment (1.0f, 0.0f, 0.0f, 1.0f, crossThickness * 1.4f); + if (buttonType == DocumentWindow::closeButton) + { + shape.addLineSegment (0.0f, 0.0f, 1.0f, 1.0f, crossThickness * 1.4f); + shape.addLineSegment (1.0f, 0.0f, 0.0f, 1.0f, crossThickness * 1.4f); - return new GlassWindowButton ("close", Colour (0xffdd1100), shape, shape); - } - else if (buttonType == DocumentWindow::minimiseButton) - { - shape.addLineSegment (0.0f, 0.5f, 1.0f, 0.5f, crossThickness); + return new GlassWindowButton ("close", Colour (0xffdd1100), shape, shape); + } + else if (buttonType == DocumentWindow::minimiseButton) + { + shape.addLineSegment (0.0f, 0.5f, 1.0f, 0.5f, crossThickness); - return new GlassWindowButton ("minimise", Colour (0xffaa8811), shape, shape); - } - else if (buttonType == DocumentWindow::maximiseButton) - { - shape.addLineSegment (0.5f, 0.0f, 0.5f, 1.0f, crossThickness); - shape.addLineSegment (0.0f, 0.5f, 1.0f, 0.5f, crossThickness); + return new GlassWindowButton ("minimise", Colour (0xffaa8811), shape, shape); + } + else if (buttonType == DocumentWindow::maximiseButton) + { + shape.addLineSegment (0.5f, 0.0f, 0.5f, 1.0f, crossThickness); + shape.addLineSegment (0.0f, 0.5f, 1.0f, 0.5f, crossThickness); - Path fullscreenShape; - fullscreenShape.startNewSubPath (45.0f, 100.0f); - fullscreenShape.lineTo (0.0f, 100.0f); - fullscreenShape.lineTo (0.0f, 0.0f); - fullscreenShape.lineTo (100.0f, 0.0f); - fullscreenShape.lineTo (100.0f, 45.0f); - fullscreenShape.addRectangle (45.0f, 45.0f, 100.0f, 100.0f); - PathStrokeType (30.0f).createStrokedPath (fullscreenShape, fullscreenShape); + Path fullscreenShape; + fullscreenShape.startNewSubPath (45.0f, 100.0f); + fullscreenShape.lineTo (0.0f, 100.0f); + fullscreenShape.lineTo (0.0f, 0.0f); + fullscreenShape.lineTo (100.0f, 0.0f); + fullscreenShape.lineTo (100.0f, 45.0f); + fullscreenShape.addRectangle (45.0f, 45.0f, 100.0f, 100.0f); + PathStrokeType (30.0f).createStrokedPath (fullscreenShape, fullscreenShape); - return new GlassWindowButton ("maximise", Colour (0xff119911), shape, fullscreenShape); - } + return new GlassWindowButton ("maximise", Colour (0xff119911), shape, fullscreenShape); + } - jassertfalse - return 0; + jassertfalse + return 0; } void LookAndFeel::positionDocumentWindowButtons (DocumentWindow&, - int titleBarX, - int titleBarY, - int titleBarW, - int titleBarH, - Button* minimiseButton, - Button* maximiseButton, - Button* closeButton, - bool positionTitleBarButtonsOnLeft) + int titleBarX, + int titleBarY, + int titleBarW, + int titleBarH, + Button* minimiseButton, + Button* maximiseButton, + Button* closeButton, + bool positionTitleBarButtonsOnLeft) { - const int buttonW = titleBarH - titleBarH / 8; + const int buttonW = titleBarH - titleBarH / 8; - int x = positionTitleBarButtonsOnLeft ? titleBarX + 4 - : titleBarX + titleBarW - buttonW - buttonW / 4; + int x = positionTitleBarButtonsOnLeft ? titleBarX + 4 + : titleBarX + titleBarW - buttonW - buttonW / 4; - if (closeButton != 0) - { - closeButton->setBounds (x, titleBarY, buttonW, titleBarH); - x += positionTitleBarButtonsOnLeft ? buttonW : -(buttonW + buttonW / 4); - } + if (closeButton != 0) + { + closeButton->setBounds (x, titleBarY, buttonW, titleBarH); + x += positionTitleBarButtonsOnLeft ? buttonW : -(buttonW + buttonW / 4); + } - if (positionTitleBarButtonsOnLeft) - swapVariables (minimiseButton, maximiseButton); + if (positionTitleBarButtonsOnLeft) + swapVariables (minimiseButton, maximiseButton); - if (maximiseButton != 0) - { - maximiseButton->setBounds (x, titleBarY, buttonW, titleBarH); - x += positionTitleBarButtonsOnLeft ? buttonW : -buttonW; - } + if (maximiseButton != 0) + { + maximiseButton->setBounds (x, titleBarY, buttonW, titleBarH); + x += positionTitleBarButtonsOnLeft ? buttonW : -buttonW; + } - if (minimiseButton != 0) - minimiseButton->setBounds (x, titleBarY, buttonW, titleBarH); + if (minimiseButton != 0) + minimiseButton->setBounds (x, titleBarY, buttonW, titleBarH); } int LookAndFeel::getDefaultMenuBarHeight() { - return 24; + return 24; } DropShadower* LookAndFeel::createDropShadowerForComponent (Component*) { - return new DropShadower (0.4f, 1, 5, 10); + return new DropShadower (0.4f, 1, 5, 10); } void LookAndFeel::drawStretchableLayoutResizerBar (Graphics& g, - int w, int h, - bool /*isVerticalBar*/, - bool isMouseOver, - bool isMouseDragging) + int w, int h, + bool /*isVerticalBar*/, + bool isMouseOver, + bool isMouseDragging) { - float alpha = 0.5f; + float alpha = 0.5f; - if (isMouseOver || isMouseDragging) - { - g.fillAll (Colour (0x190000ff)); - alpha = 1.0f; - } + if (isMouseOver || isMouseDragging) + { + g.fillAll (Colour (0x190000ff)); + alpha = 1.0f; + } - const float cx = w * 0.5f; - const float cy = h * 0.5f; - const float cr = jmin (w, h) * 0.4f; + const float cx = w * 0.5f; + const float cy = h * 0.5f; + const float cr = jmin (w, h) * 0.4f; - g.setGradientFill (ColourGradient (Colours::white.withAlpha (alpha), cx + cr * 0.1f, cy + cr, - Colours::black.withAlpha (alpha), cx, cy - cr * 4.0f, - true)); + g.setGradientFill (ColourGradient (Colours::white.withAlpha (alpha), cx + cr * 0.1f, cy + cr, + Colours::black.withAlpha (alpha), cx, cy - cr * 4.0f, + true)); - g.fillEllipse (cx - cr, cy - cr, cr * 2.0f, cr * 2.0f); + g.fillEllipse (cx - cr, cy - cr, cr * 2.0f, cr * 2.0f); } void LookAndFeel::drawGroupComponentOutline (Graphics& g, int width, int height, - const String& text, - const Justification& position, - GroupComponent& group) + const String& text, + const Justification& position, + GroupComponent& group) { - const float textH = 15.0f; - const float indent = 3.0f; - const float textEdgeGap = 4.0f; - float cs = 5.0f; + const float textH = 15.0f; + const float indent = 3.0f; + const float textEdgeGap = 4.0f; + float cs = 5.0f; - Font f (textH); + Font f (textH); - Path p; - float x = indent; - float y = f.getAscent() - 3.0f; - float w = jmax (0.0f, width - x * 2.0f); - float h = jmax (0.0f, height - y - indent); - cs = jmin (cs, w * 0.5f, h * 0.5f); - const float cs2 = 2.0f * cs; + Path p; + float x = indent; + float y = f.getAscent() - 3.0f; + float w = jmax (0.0f, width - x * 2.0f); + float h = jmax (0.0f, height - y - indent); + cs = jmin (cs, w * 0.5f, h * 0.5f); + const float cs2 = 2.0f * cs; - float textW = text.isEmpty() ? 0 : jlimit (0.0f, jmax (0.0f, w - cs2 - textEdgeGap * 2), f.getStringWidth (text) + textEdgeGap * 2.0f); - float textX = cs + textEdgeGap; + float textW = text.isEmpty() ? 0 : jlimit (0.0f, jmax (0.0f, w - cs2 - textEdgeGap * 2), f.getStringWidth (text) + textEdgeGap * 2.0f); + float textX = cs + textEdgeGap; - if (position.testFlags (Justification::horizontallyCentred)) - textX = cs + (w - cs2 - textW) * 0.5f; - else if (position.testFlags (Justification::right)) - textX = w - cs - textW - textEdgeGap; + if (position.testFlags (Justification::horizontallyCentred)) + textX = cs + (w - cs2 - textW) * 0.5f; + else if (position.testFlags (Justification::right)) + textX = w - cs - textW - textEdgeGap; - p.startNewSubPath (x + textX + textW, y); - p.lineTo (x + w - cs, y); + p.startNewSubPath (x + textX + textW, y); + p.lineTo (x + w - cs, y); - p.addArc (x + w - cs2, y, cs2, cs2, 0, float_Pi * 0.5f); - p.lineTo (x + w, y + h - cs); + p.addArc (x + w - cs2, y, cs2, cs2, 0, float_Pi * 0.5f); + p.lineTo (x + w, y + h - cs); - p.addArc (x + w - cs2, y + h - cs2, cs2, cs2, float_Pi * 0.5f, float_Pi); - p.lineTo (x + cs, y + h); + p.addArc (x + w - cs2, y + h - cs2, cs2, cs2, float_Pi * 0.5f, float_Pi); + p.lineTo (x + cs, y + h); - p.addArc (x, y + h - cs2, cs2, cs2, float_Pi, float_Pi * 1.5f); - p.lineTo (x, y + cs); + p.addArc (x, y + h - cs2, cs2, cs2, float_Pi, float_Pi * 1.5f); + p.lineTo (x, y + cs); - p.addArc (x, y, cs2, cs2, float_Pi * 1.5f, float_Pi * 2.0f); - p.lineTo (x + textX, y); + p.addArc (x, y, cs2, cs2, float_Pi * 1.5f, float_Pi * 2.0f); + p.lineTo (x + textX, y); - const float alpha = group.isEnabled() ? 1.0f : 0.5f; + const float alpha = group.isEnabled() ? 1.0f : 0.5f; - g.setColour (group.findColour (GroupComponent::outlineColourId) - .withMultipliedAlpha (alpha)); + g.setColour (group.findColour (GroupComponent::outlineColourId) + .withMultipliedAlpha (alpha)); - g.strokePath (p, PathStrokeType (2.0f)); + g.strokePath (p, PathStrokeType (2.0f)); - g.setColour (group.findColour (GroupComponent::textColourId) - .withMultipliedAlpha (alpha)); - g.setFont (f); - g.drawText (text, - roundFloatToInt (x + textX), 0, - roundFloatToInt (textW), - roundFloatToInt (textH), - Justification::centred, true); + g.setColour (group.findColour (GroupComponent::textColourId) + .withMultipliedAlpha (alpha)); + g.setFont (f); + g.drawText (text, + roundToInt (x + textX), 0, + roundToInt (textW), + roundToInt (textH), + Justification::centred, true); } int LookAndFeel::getTabButtonOverlap (int tabDepth) { - return 1 + tabDepth / 3; + return 1 + tabDepth / 3; } int LookAndFeel::getTabButtonSpaceAroundImage() { - return 4; + return 4; } void LookAndFeel::createTabButtonShape (Path& p, - int width, int height, - int /*tabIndex*/, - const String& /*text*/, - Button& /*button*/, - TabbedButtonBar::Orientation orientation, - const bool /*isMouseOver*/, - const bool /*isMouseDown*/, - const bool /*isFrontTab*/) + int width, int height, + int /*tabIndex*/, + const String& /*text*/, + Button& /*button*/, + TabbedButtonBar::Orientation orientation, + const bool /*isMouseOver*/, + const bool /*isMouseDown*/, + const bool /*isFrontTab*/) { - const float w = (float) width; - const float h = (float) height; + const float w = (float) width; + const float h = (float) height; - float length = w; - float depth = h; + float length = w; + float depth = h; - if (orientation == TabbedButtonBar::TabsAtLeft - || orientation == TabbedButtonBar::TabsAtRight) - { - swapVariables (length, depth); - } + if (orientation == TabbedButtonBar::TabsAtLeft + || orientation == TabbedButtonBar::TabsAtRight) + { + swapVariables (length, depth); + } - const float indent = (float) getTabButtonOverlap ((int) depth); - const float overhang = 4.0f; + const float indent = (float) getTabButtonOverlap ((int) depth); + const float overhang = 4.0f; - if (orientation == TabbedButtonBar::TabsAtLeft) - { - p.startNewSubPath (w, 0.0f); - p.lineTo (0.0f, indent); - p.lineTo (0.0f, h - indent); - p.lineTo (w, h); - p.lineTo (w + overhang, h + overhang); - p.lineTo (w + overhang, -overhang); - } - else if (orientation == TabbedButtonBar::TabsAtRight) - { - p.startNewSubPath (0.0f, 0.0f); - p.lineTo (w, indent); - p.lineTo (w, h - indent); - p.lineTo (0.0f, h); - p.lineTo (-overhang, h + overhang); - p.lineTo (-overhang, -overhang); - } - else if (orientation == TabbedButtonBar::TabsAtBottom) - { - p.startNewSubPath (0.0f, 0.0f); - p.lineTo (indent, h); - p.lineTo (w - indent, h); - p.lineTo (w, 0.0f); - p.lineTo (w + overhang, -overhang); - p.lineTo (-overhang, -overhang); - } - else - { - p.startNewSubPath (0.0f, h); - p.lineTo (indent, 0.0f); - p.lineTo (w - indent, 0.0f); - p.lineTo (w, h); - p.lineTo (w + overhang, h + overhang); - p.lineTo (-overhang, h + overhang); - } + if (orientation == TabbedButtonBar::TabsAtLeft) + { + p.startNewSubPath (w, 0.0f); + p.lineTo (0.0f, indent); + p.lineTo (0.0f, h - indent); + p.lineTo (w, h); + p.lineTo (w + overhang, h + overhang); + p.lineTo (w + overhang, -overhang); + } + else if (orientation == TabbedButtonBar::TabsAtRight) + { + p.startNewSubPath (0.0f, 0.0f); + p.lineTo (w, indent); + p.lineTo (w, h - indent); + p.lineTo (0.0f, h); + p.lineTo (-overhang, h + overhang); + p.lineTo (-overhang, -overhang); + } + else if (orientation == TabbedButtonBar::TabsAtBottom) + { + p.startNewSubPath (0.0f, 0.0f); + p.lineTo (indent, h); + p.lineTo (w - indent, h); + p.lineTo (w, 0.0f); + p.lineTo (w + overhang, -overhang); + p.lineTo (-overhang, -overhang); + } + else + { + p.startNewSubPath (0.0f, h); + p.lineTo (indent, 0.0f); + p.lineTo (w - indent, 0.0f); + p.lineTo (w, h); + p.lineTo (w + overhang, h + overhang); + p.lineTo (-overhang, h + overhang); + } - p.closeSubPath(); + p.closeSubPath(); - p = p.createPathWithRoundedCorners (3.0f); + p = p.createPathWithRoundedCorners (3.0f); } void LookAndFeel::fillTabButtonShape (Graphics& g, - const Path& path, - const Colour& preferredColour, - int /*tabIndex*/, - const String& /*text*/, - Button& button, - TabbedButtonBar::Orientation /*orientation*/, - const bool /*isMouseOver*/, - const bool /*isMouseDown*/, - const bool isFrontTab) + const Path& path, + const Colour& preferredColour, + int /*tabIndex*/, + const String& /*text*/, + Button& button, + TabbedButtonBar::Orientation /*orientation*/, + const bool /*isMouseOver*/, + const bool /*isMouseDown*/, + const bool isFrontTab) { - g.setColour (isFrontTab ? preferredColour - : preferredColour.withMultipliedAlpha (0.9f)); + g.setColour (isFrontTab ? preferredColour + : preferredColour.withMultipliedAlpha (0.9f)); - g.fillPath (path); + g.fillPath (path); - g.setColour (button.findColour (isFrontTab ? TabbedButtonBar::frontOutlineColourId - : TabbedButtonBar::tabOutlineColourId, false) - .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f)); + g.setColour (button.findColour (isFrontTab ? TabbedButtonBar::frontOutlineColourId + : TabbedButtonBar::tabOutlineColourId, false) + .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f)); - g.strokePath (path, PathStrokeType (isFrontTab ? 1.0f : 0.5f)); + g.strokePath (path, PathStrokeType (isFrontTab ? 1.0f : 0.5f)); } void LookAndFeel::drawTabButtonText (Graphics& g, - int x, int y, int w, int h, - const Colour& preferredBackgroundColour, - int /*tabIndex*/, - const String& text, - Button& button, - TabbedButtonBar::Orientation orientation, - const bool isMouseOver, - const bool isMouseDown, - const bool isFrontTab) + int x, int y, int w, int h, + const Colour& preferredBackgroundColour, + int /*tabIndex*/, + const String& text, + Button& button, + TabbedButtonBar::Orientation orientation, + const bool isMouseOver, + const bool isMouseDown, + const bool isFrontTab) { - int length = w; - int depth = h; + int length = w; + int depth = h; - if (orientation == TabbedButtonBar::TabsAtLeft - || orientation == TabbedButtonBar::TabsAtRight) - { - swapVariables (length, depth); - } + if (orientation == TabbedButtonBar::TabsAtLeft + || orientation == TabbedButtonBar::TabsAtRight) + { + swapVariables (length, depth); + } - Font font (depth * 0.6f); - font.setUnderline (button.hasKeyboardFocus (false)); + Font font (depth * 0.6f); + font.setUnderline (button.hasKeyboardFocus (false)); - GlyphArrangement textLayout; - textLayout.addFittedText (font, text.trim(), - 0.0f, 0.0f, (float) length, (float) depth, - Justification::centred, - jmax (1, depth / 12)); + GlyphArrangement textLayout; + textLayout.addFittedText (font, text.trim(), + 0.0f, 0.0f, (float) length, (float) depth, + Justification::centred, + jmax (1, depth / 12)); - AffineTransform transform; + AffineTransform transform; - if (orientation == TabbedButtonBar::TabsAtLeft) - { - transform = transform.rotated (float_Pi * -0.5f) - .translated ((float) x, (float) (y + h)); - } - else if (orientation == TabbedButtonBar::TabsAtRight) - { - transform = transform.rotated (float_Pi * 0.5f) - .translated ((float) (x + w), (float) y); - } - else - { - transform = transform.translated ((float) x, (float) y); - } + if (orientation == TabbedButtonBar::TabsAtLeft) + { + transform = transform.rotated (float_Pi * -0.5f) + .translated ((float) x, (float) (y + h)); + } + else if (orientation == TabbedButtonBar::TabsAtRight) + { + transform = transform.rotated (float_Pi * 0.5f) + .translated ((float) (x + w), (float) y); + } + else + { + transform = transform.translated ((float) x, (float) y); + } - if (isFrontTab && (button.isColourSpecified (TabbedButtonBar::frontTextColourId) || isColourSpecified (TabbedButtonBar::frontTextColourId))) - g.setColour (findColour (TabbedButtonBar::frontTextColourId)); - else if (button.isColourSpecified (TabbedButtonBar::tabTextColourId) || isColourSpecified (TabbedButtonBar::tabTextColourId)) - g.setColour (findColour (TabbedButtonBar::tabTextColourId)); - else - g.setColour (preferredBackgroundColour.contrasting()); + if (isFrontTab && (button.isColourSpecified (TabbedButtonBar::frontTextColourId) || isColourSpecified (TabbedButtonBar::frontTextColourId))) + g.setColour (findColour (TabbedButtonBar::frontTextColourId)); + else if (button.isColourSpecified (TabbedButtonBar::tabTextColourId) || isColourSpecified (TabbedButtonBar::tabTextColourId)) + g.setColour (findColour (TabbedButtonBar::tabTextColourId)); + else + g.setColour (preferredBackgroundColour.contrasting()); - if (! (isMouseOver || isMouseDown)) - g.setOpacity (0.8f); + if (! (isMouseOver || isMouseDown)) + g.setOpacity (0.8f); - if (! button.isEnabled()) - g.setOpacity (0.3f); + if (! button.isEnabled()) + g.setOpacity (0.3f); - textLayout.draw (g, transform); + textLayout.draw (g, transform); } int LookAndFeel::getTabButtonBestWidth (int /*tabIndex*/, - const String& text, - int tabDepth, - Button&) + const String& text, + int tabDepth, + Button&) { - Font f (tabDepth * 0.6f); - return f.getStringWidth (text.trim()) + getTabButtonOverlap (tabDepth) * 2; + Font f (tabDepth * 0.6f); + return f.getStringWidth (text.trim()) + getTabButtonOverlap (tabDepth) * 2; } void LookAndFeel::drawTabButton (Graphics& g, - int w, int h, - const Colour& preferredColour, - int tabIndex, - const String& text, - Button& button, - TabbedButtonBar::Orientation orientation, - const bool isMouseOver, - const bool isMouseDown, - const bool isFrontTab) + int w, int h, + const Colour& preferredColour, + int tabIndex, + const String& text, + Button& button, + TabbedButtonBar::Orientation orientation, + const bool isMouseOver, + const bool isMouseDown, + const bool isFrontTab) { - int length = w; - int depth = h; + int length = w; + int depth = h; - if (orientation == TabbedButtonBar::TabsAtLeft - || orientation == TabbedButtonBar::TabsAtRight) - { - swapVariables (length, depth); - } + if (orientation == TabbedButtonBar::TabsAtLeft + || orientation == TabbedButtonBar::TabsAtRight) + { + swapVariables (length, depth); + } - Path tabShape; + Path tabShape; - createTabButtonShape (tabShape, w, h, - tabIndex, text, button, orientation, - isMouseOver, isMouseDown, isFrontTab); + createTabButtonShape (tabShape, w, h, + tabIndex, text, button, orientation, + isMouseOver, isMouseDown, isFrontTab); - fillTabButtonShape (g, tabShape, preferredColour, - tabIndex, text, button, orientation, - isMouseOver, isMouseDown, isFrontTab); + fillTabButtonShape (g, tabShape, preferredColour, + tabIndex, text, button, orientation, + isMouseOver, isMouseDown, isFrontTab); - const int indent = getTabButtonOverlap (depth); - int x = 0, y = 0; + const int indent = getTabButtonOverlap (depth); + int x = 0, y = 0; - if (orientation == TabbedButtonBar::TabsAtLeft - || orientation == TabbedButtonBar::TabsAtRight) - { - y += indent; - h -= indent * 2; - } - else - { - x += indent; - w -= indent * 2; - } + if (orientation == TabbedButtonBar::TabsAtLeft + || orientation == TabbedButtonBar::TabsAtRight) + { + y += indent; + h -= indent * 2; + } + else + { + x += indent; + w -= indent * 2; + } - drawTabButtonText (g, x, y, w, h, preferredColour, - tabIndex, text, button, orientation, - isMouseOver, isMouseDown, isFrontTab); + drawTabButtonText (g, x, y, w, h, preferredColour, + tabIndex, text, button, orientation, + isMouseOver, isMouseDown, isFrontTab); } void LookAndFeel::drawTabAreaBehindFrontButton (Graphics& g, - int w, int h, - TabbedButtonBar& tabBar, - TabbedButtonBar::Orientation orientation) + int w, int h, + TabbedButtonBar& tabBar, + TabbedButtonBar::Orientation orientation) { - const float shadowSize = 0.2f; + const float shadowSize = 0.2f; - float x1 = 0.0f, y1 = 0.0f, x2 = 0.0f, y2 = 0.0f; - Rectangle shadowRect; + float x1 = 0.0f, y1 = 0.0f, x2 = 0.0f, y2 = 0.0f; + Rectangle shadowRect; - if (orientation == TabbedButtonBar::TabsAtLeft) - { - x1 = (float) w; - x2 = w * (1.0f - shadowSize); - shadowRect.setBounds ((int) x2, 0, w - (int) x2, h); - } - else if (orientation == TabbedButtonBar::TabsAtRight) - { - x2 = w * shadowSize; - shadowRect.setBounds (0, 0, (int) x2, h); - } - else if (orientation == TabbedButtonBar::TabsAtBottom) - { - y2 = h * shadowSize; - shadowRect.setBounds (0, 0, w, (int) y2); - } - else - { - y1 = (float) h; - y2 = h * (1.0f - shadowSize); - shadowRect.setBounds (0, (int) y2, w, h - (int) y2); - } + if (orientation == TabbedButtonBar::TabsAtLeft) + { + x1 = (float) w; + x2 = w * (1.0f - shadowSize); + shadowRect.setBounds ((int) x2, 0, w - (int) x2, h); + } + else if (orientation == TabbedButtonBar::TabsAtRight) + { + x2 = w * shadowSize; + shadowRect.setBounds (0, 0, (int) x2, h); + } + else if (orientation == TabbedButtonBar::TabsAtBottom) + { + y2 = h * shadowSize; + shadowRect.setBounds (0, 0, w, (int) y2); + } + else + { + y1 = (float) h; + y2 = h * (1.0f - shadowSize); + shadowRect.setBounds (0, (int) y2, w, h - (int) y2); + } - g.setGradientFill (ColourGradient (Colours::black.withAlpha (tabBar.isEnabled() ? 0.3f : 0.15f), x1, y1, - Colours::transparentBlack, x2, y2, false)); + g.setGradientFill (ColourGradient (Colours::black.withAlpha (tabBar.isEnabled() ? 0.3f : 0.15f), x1, y1, + Colours::transparentBlack, x2, y2, false)); - shadowRect.expand (2, 2); - g.fillRect (shadowRect); + shadowRect.expand (2, 2); + g.fillRect (shadowRect); - g.setColour (Colour (0x80000000)); + g.setColour (Colour (0x80000000)); - if (orientation == TabbedButtonBar::TabsAtLeft) - { - g.fillRect (w - 1, 0, 1, h); - } - else if (orientation == TabbedButtonBar::TabsAtRight) - { - g.fillRect (0, 0, 1, h); - } - else if (orientation == TabbedButtonBar::TabsAtBottom) - { - g.fillRect (0, 0, w, 1); - } - else - { - g.fillRect (0, h - 1, w, 1); - } + if (orientation == TabbedButtonBar::TabsAtLeft) + { + g.fillRect (w - 1, 0, 1, h); + } + else if (orientation == TabbedButtonBar::TabsAtRight) + { + g.fillRect (0, 0, 1, h); + } + else if (orientation == TabbedButtonBar::TabsAtBottom) + { + g.fillRect (0, 0, w, 1); + } + else + { + g.fillRect (0, h - 1, w, 1); + } } Button* LookAndFeel::createTabBarExtrasButton() { - const float thickness = 7.0f; - const float indent = 22.0f; + const float thickness = 7.0f; + const float indent = 22.0f; - Path p; - p.addEllipse (-10.0f, -10.0f, 120.0f, 120.0f); + Path p; + p.addEllipse (-10.0f, -10.0f, 120.0f, 120.0f); - DrawablePath ellipse; - ellipse.setPath (p); - ellipse.setFill (Colour (0x99ffffff)); + DrawablePath ellipse; + ellipse.setPath (p); + ellipse.setFill (Colour (0x99ffffff)); - p.clear(); - p.addEllipse (0.0f, 0.0f, 100.0f, 100.0f); - p.addRectangle (indent, 50.0f - thickness, 100.0f - indent * 2.0f, thickness * 2.0f); - p.addRectangle (50.0f - thickness, indent, thickness * 2.0f, 50.0f - indent - thickness); - p.addRectangle (50.0f - thickness, 50.0f + thickness, thickness * 2.0f, 50.0f - indent - thickness); - p.setUsingNonZeroWinding (false); + p.clear(); + p.addEllipse (0.0f, 0.0f, 100.0f, 100.0f); + p.addRectangle (indent, 50.0f - thickness, 100.0f - indent * 2.0f, thickness * 2.0f); + p.addRectangle (50.0f - thickness, indent, thickness * 2.0f, 50.0f - indent - thickness); + p.addRectangle (50.0f - thickness, 50.0f + thickness, thickness * 2.0f, 50.0f - indent - thickness); + p.setUsingNonZeroWinding (false); - DrawablePath dp; - dp.setPath (p); - dp.setFill (Colour (0x59000000)); + DrawablePath dp; + dp.setPath (p); + dp.setFill (Colour (0x59000000)); - DrawableComposite normalImage; - normalImage.insertDrawable (ellipse); - normalImage.insertDrawable (dp); + DrawableComposite normalImage; + normalImage.insertDrawable (ellipse); + normalImage.insertDrawable (dp); - dp.setFill (Colour (0xcc000000)); + dp.setFill (Colour (0xcc000000)); - DrawableComposite overImage; - overImage.insertDrawable (ellipse); - overImage.insertDrawable (dp); + DrawableComposite overImage; + overImage.insertDrawable (ellipse); + overImage.insertDrawable (dp); - DrawableButton* db = new DrawableButton (T("tabs"), DrawableButton::ImageFitted); - db->setImages (&normalImage, &overImage, 0); - return db; + DrawableButton* db = new DrawableButton (T("tabs"), DrawableButton::ImageFitted); + db->setImages (&normalImage, &overImage, 0); + return db; } void LookAndFeel::drawTableHeaderBackground (Graphics& g, TableHeaderComponent& header) { - g.fillAll (Colours::white); + g.fillAll (Colours::white); - const int w = header.getWidth(); - const int h = header.getHeight(); + const int w = header.getWidth(); + const int h = header.getHeight(); - g.setGradientFill (ColourGradient (Colour (0xffe8ebf9), 0.0f, h * 0.5f, - Colour (0xfff6f8f9), 0.0f, h - 1.0f, - false)); - g.fillRect (0, h / 2, w, h); + g.setGradientFill (ColourGradient (Colour (0xffe8ebf9), 0.0f, h * 0.5f, + Colour (0xfff6f8f9), 0.0f, h - 1.0f, + false)); + g.fillRect (0, h / 2, w, h); - g.setColour (Colour (0x33000000)); - g.fillRect (0, h - 1, w, 1); + g.setColour (Colour (0x33000000)); + g.fillRect (0, h - 1, w, 1); - for (int i = header.getNumColumns (true); --i >= 0;) - g.fillRect (header.getColumnPosition (i).getRight() - 1, 0, 1, h - 1); + for (int i = header.getNumColumns (true); --i >= 0;) + g.fillRect (header.getColumnPosition (i).getRight() - 1, 0, 1, h - 1); } void LookAndFeel::drawTableHeaderColumn (Graphics& g, const String& columnName, int /*columnId*/, - int width, int height, - bool isMouseOver, bool isMouseDown, - int columnFlags) + int width, int height, + bool isMouseOver, bool isMouseDown, + int columnFlags) { - if (isMouseDown) - g.fillAll (Colour (0x8899aadd)); - else if (isMouseOver) - g.fillAll (Colour (0x5599aadd)); + if (isMouseDown) + g.fillAll (Colour (0x8899aadd)); + else if (isMouseOver) + g.fillAll (Colour (0x5599aadd)); - int rightOfText = width - 4; + int rightOfText = width - 4; - if ((columnFlags & (TableHeaderComponent::sortedForwards | TableHeaderComponent::sortedBackwards)) != 0) - { - const float top = height * ((columnFlags & TableHeaderComponent::sortedForwards) != 0 ? 0.35f : (1.0f - 0.35f)); - const float bottom = height - top; + if ((columnFlags & (TableHeaderComponent::sortedForwards | TableHeaderComponent::sortedBackwards)) != 0) + { + const float top = height * ((columnFlags & TableHeaderComponent::sortedForwards) != 0 ? 0.35f : (1.0f - 0.35f)); + const float bottom = height - top; - const float w = height * 0.5f; - const float x = rightOfText - (w * 1.25f); - rightOfText = (int) x; + const float w = height * 0.5f; + const float x = rightOfText - (w * 1.25f); + rightOfText = (int) x; - Path sortArrow; - sortArrow.addTriangle (x, bottom, x + w * 0.5f, top, x + w, bottom); + Path sortArrow; + sortArrow.addTriangle (x, bottom, x + w * 0.5f, top, x + w, bottom); - g.setColour (Colour (0x99000000)); - g.fillPath (sortArrow); - } + g.setColour (Colour (0x99000000)); + g.fillPath (sortArrow); + } - g.setColour (Colours::black); - g.setFont (height * 0.5f, Font::bold); - const int textX = 4; - g.drawFittedText (columnName, textX, 0, rightOfText - textX, height, Justification::centredLeft, 1); + g.setColour (Colours::black); + g.setFont (height * 0.5f, Font::bold); + const int textX = 4; + g.drawFittedText (columnName, textX, 0, rightOfText - textX, height, Justification::centredLeft, 1); } void LookAndFeel::paintToolbarBackground (Graphics& g, int w, int h, Toolbar& toolbar) { - const Colour background (toolbar.findColour (Toolbar::backgroundColourId)); + const Colour background (toolbar.findColour (Toolbar::backgroundColourId)); - g.setGradientFill (ColourGradient (background, 0.0f, 0.0f, - background.darker (0.1f), - toolbar.isVertical() ? w - 1.0f : 0.0f, - toolbar.isVertical() ? 0.0f : h - 1.0f, - false)); - g.fillAll(); + g.setGradientFill (ColourGradient (background, 0.0f, 0.0f, + background.darker (0.1f), + toolbar.isVertical() ? w - 1.0f : 0.0f, + toolbar.isVertical() ? 0.0f : h - 1.0f, + false)); + g.fillAll(); } Button* LookAndFeel::createToolbarMissingItemsButton (Toolbar& /*toolbar*/) { - return createTabBarExtrasButton(); + return createTabBarExtrasButton(); } void LookAndFeel::paintToolbarButtonBackground (Graphics& g, int /*width*/, int /*height*/, - bool isMouseOver, bool isMouseDown, - ToolbarItemComponent& component) + bool isMouseOver, bool isMouseDown, + ToolbarItemComponent& component) { - if (isMouseDown) - g.fillAll (component.findColour (Toolbar::buttonMouseDownBackgroundColourId, true)); - else if (isMouseOver) - g.fillAll (component.findColour (Toolbar::buttonMouseOverBackgroundColourId, true)); + if (isMouseDown) + g.fillAll (component.findColour (Toolbar::buttonMouseDownBackgroundColourId, true)); + else if (isMouseOver) + g.fillAll (component.findColour (Toolbar::buttonMouseOverBackgroundColourId, true)); } void LookAndFeel::paintToolbarButtonLabel (Graphics& g, int x, int y, int width, int height, - const String& text, ToolbarItemComponent& component) + const String& text, ToolbarItemComponent& component) { - g.setColour (component.findColour (Toolbar::labelTextColourId, true) - .withAlpha (component.isEnabled() ? 1.0f : 0.25f)); + g.setColour (component.findColour (Toolbar::labelTextColourId, true) + .withAlpha (component.isEnabled() ? 1.0f : 0.25f)); - const float fontHeight = jmin (14.0f, height * 0.85f); - g.setFont (fontHeight); + const float fontHeight = jmin (14.0f, height * 0.85f); + g.setFont (fontHeight); - g.drawFittedText (text, - x, y, width, height, - Justification::centred, - jmax (1, height / (int) fontHeight)); + g.drawFittedText (text, + x, y, width, height, + Justification::centred, + jmax (1, height / (int) fontHeight)); } void LookAndFeel::drawPropertyPanelSectionHeader (Graphics& g, const String& name, - bool isOpen, int width, int height) + bool isOpen, int width, int height) { - const int buttonSize = (height * 3) / 4; - const int buttonIndent = (height - buttonSize) / 2; + const int buttonSize = (height * 3) / 4; + const int buttonIndent = (height - buttonSize) / 2; - drawTreeviewPlusMinusBox (g, buttonIndent, buttonIndent, buttonSize, buttonSize, ! isOpen, false); + drawTreeviewPlusMinusBox (g, buttonIndent, buttonIndent, buttonSize, buttonSize, ! isOpen, false); - const int textX = buttonIndent * 2 + buttonSize + 2; + const int textX = buttonIndent * 2 + buttonSize + 2; - g.setColour (Colours::black); - g.setFont (height * 0.7f, Font::bold); - g.drawText (name, textX, 0, width - textX - 4, height, Justification::centredLeft, true); + g.setColour (Colours::black); + g.setFont (height * 0.7f, Font::bold); + g.drawText (name, textX, 0, width - textX - 4, height, Justification::centredLeft, true); } void LookAndFeel::drawPropertyComponentBackground (Graphics& g, int width, int height, - PropertyComponent&) + PropertyComponent&) { - g.setColour (Colour (0x66ffffff)); - g.fillRect (0, 0, width, height - 1); + g.setColour (Colour (0x66ffffff)); + g.fillRect (0, 0, width, height - 1); } void LookAndFeel::drawPropertyComponentLabel (Graphics& g, int, int height, - PropertyComponent& component) + PropertyComponent& component) { - g.setColour (Colours::black); + g.setColour (Colours::black); - if (! component.isEnabled()) - g.setOpacity (0.6f); + if (! component.isEnabled()) + g.setOpacity (0.6f); - g.setFont (jmin (height, 24) * 0.65f); + g.setFont (jmin (height, 24) * 0.65f); - const Rectangle r (getPropertyComponentContentPosition (component)); + const Rectangle r (getPropertyComponentContentPosition (component)); - g.drawFittedText (component.getName(), - 3, r.getY(), r.getX() - 5, r.getHeight(), - Justification::centredLeft, 2); + g.drawFittedText (component.getName(), + 3, r.getY(), r.getX() - 5, r.getHeight(), + Justification::centredLeft, 2); } const Rectangle LookAndFeel::getPropertyComponentContentPosition (PropertyComponent& component) { - return Rectangle (component.getWidth() / 3, 1, - component.getWidth() - component.getWidth() / 3 - 1, component.getHeight() - 3); + return Rectangle (component.getWidth() / 3, 1, + component.getWidth() - component.getWidth() / 3 - 1, component.getHeight() - 3); } void LookAndFeel::createFileChooserHeaderText (const String& title, - const String& instructions, - GlyphArrangement& text, - int width) + const String& instructions, + GlyphArrangement& text, + int width) { - text.clear(); + text.clear(); - text.addJustifiedText (Font (17.0f, Font::bold), title, - 8.0f, 22.0f, width - 16.0f, - Justification::centred); + text.addJustifiedText (Font (17.0f, Font::bold), title, + 8.0f, 22.0f, width - 16.0f, + Justification::centred); - text.addJustifiedText (Font (14.0f), instructions, - 8.0f, 24.0f + 16.0f, width - 16.0f, - Justification::centred); + text.addJustifiedText (Font (14.0f), instructions, + 8.0f, 24.0f + 16.0f, width - 16.0f, + Justification::centred); } void LookAndFeel::drawFileBrowserRow (Graphics& g, int width, int height, - const String& filename, Image* icon, - const String& fileSizeDescription, - const String& fileTimeDescription, - const bool isDirectory, - const bool isItemSelected, - const int /*itemIndex*/) + const String& filename, Image* icon, + const String& fileSizeDescription, + const String& fileTimeDescription, + const bool isDirectory, + const bool isItemSelected, + const int /*itemIndex*/) { - if (isItemSelected) - g.fillAll (findColour (DirectoryContentsDisplayComponent::highlightColourId)); + if (isItemSelected) + g.fillAll (findColour (DirectoryContentsDisplayComponent::highlightColourId)); - g.setColour (findColour (DirectoryContentsDisplayComponent::textColourId)); - g.setFont (height * 0.7f); + g.setColour (findColour (DirectoryContentsDisplayComponent::textColourId)); + g.setFont (height * 0.7f); - Image* im = icon; - Image* toRelease = 0; + Image* im = icon; + Image* toRelease = 0; - if (im == 0) - { - toRelease = im = (isDirectory ? getDefaultFolderImage() - : getDefaultDocumentFileImage()); - } + if (im == 0) + { + toRelease = im = (isDirectory ? getDefaultFolderImage() + : getDefaultDocumentFileImage()); + } - const int x = 32; + const int x = 32; - if (im != 0) - { - g.drawImageWithin (im, 2, 2, x - 4, height - 4, - RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, - false); + if (im != 0) + { + g.drawImageWithin (im, 2, 2, x - 4, height - 4, + RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, + false); - ImageCache::release (toRelease); - } + ImageCache::release (toRelease); + } - if (width > 450 && ! isDirectory) - { - const int sizeX = roundFloatToInt (width * 0.7f); - const int dateX = roundFloatToInt (width * 0.8f); + if (width > 450 && ! isDirectory) + { + const int sizeX = roundToInt (width * 0.7f); + const int dateX = roundToInt (width * 0.8f); - g.drawFittedText (filename, - x, 0, sizeX - x, height, - Justification::centredLeft, 1); + g.drawFittedText (filename, + x, 0, sizeX - x, height, + Justification::centredLeft, 1); - g.setFont (height * 0.5f); - g.setColour (Colours::darkgrey); + g.setFont (height * 0.5f); + g.setColour (Colours::darkgrey); - if (! isDirectory) - { - g.drawFittedText (fileSizeDescription, - sizeX, 0, dateX - sizeX - 8, height, - Justification::centredRight, 1); + if (! isDirectory) + { + g.drawFittedText (fileSizeDescription, + sizeX, 0, dateX - sizeX - 8, height, + Justification::centredRight, 1); - g.drawFittedText (fileTimeDescription, - dateX, 0, width - 8 - dateX, height, - Justification::centredRight, 1); - } - } - else - { - g.drawFittedText (filename, - x, 0, width - x, height, - Justification::centredLeft, 1); + g.drawFittedText (fileTimeDescription, + dateX, 0, width - 8 - dateX, height, + Justification::centredRight, 1); + } + } + else + { + g.drawFittedText (filename, + x, 0, width - x, height, + Justification::centredLeft, 1); - } + } } Button* LookAndFeel::createFileBrowserGoUpButton() { - DrawableButton* goUpButton = new DrawableButton ("up", DrawableButton::ImageOnButtonBackground); + DrawableButton* goUpButton = new DrawableButton ("up", DrawableButton::ImageOnButtonBackground); - Path arrowPath; - arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0f, 40.0f, 100.0f, 50.0f); + Path arrowPath; + arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0f, 40.0f, 100.0f, 50.0f); - DrawablePath arrowImage; - arrowImage.setFill (Colours::black.withAlpha (0.4f)); - arrowImage.setPath (arrowPath); + DrawablePath arrowImage; + arrowImage.setFill (Colours::black.withAlpha (0.4f)); + arrowImage.setPath (arrowPath); - goUpButton->setImages (&arrowImage); + goUpButton->setImages (&arrowImage); - return goUpButton; + return goUpButton; } void LookAndFeel::layoutFileBrowserComponent (FileBrowserComponent& browserComp, - DirectoryContentsDisplayComponent* fileListComponent, - FilePreviewComponent* previewComp, - ComboBox* currentPathBox, - TextEditor* filenameBox, - Button* goUpButton) + DirectoryContentsDisplayComponent* fileListComponent, + FilePreviewComponent* previewComp, + ComboBox* currentPathBox, + TextEditor* filenameBox, + Button* goUpButton) { - const int x = 8; - int w = browserComp.getWidth() - x - x; + const int x = 8; + int w = browserComp.getWidth() - x - x; - if (previewComp != 0) - { - const int previewWidth = w / 3; - previewComp->setBounds (x + w - previewWidth, 0, previewWidth, browserComp.getHeight()); + if (previewComp != 0) + { + const int previewWidth = w / 3; + previewComp->setBounds (x + w - previewWidth, 0, previewWidth, browserComp.getHeight()); - w -= previewWidth + 4; - } + w -= previewWidth + 4; + } - int y = 4; + int y = 4; - const int controlsHeight = 22; - const int bottomSectionHeight = controlsHeight + 8; - const int upButtonWidth = 50; + const int controlsHeight = 22; + const int bottomSectionHeight = controlsHeight + 8; + const int upButtonWidth = 50; - currentPathBox->setBounds (x, y, w - upButtonWidth - 6, controlsHeight); - goUpButton->setBounds (x + w - upButtonWidth, y, upButtonWidth, controlsHeight); + currentPathBox->setBounds (x, y, w - upButtonWidth - 6, controlsHeight); + goUpButton->setBounds (x + w - upButtonWidth, y, upButtonWidth, controlsHeight); - y += controlsHeight + 4; + y += controlsHeight + 4; - Component* const listAsComp = dynamic_cast (fileListComponent); - listAsComp->setBounds (x, y, w, browserComp.getHeight() - y - bottomSectionHeight); + Component* const listAsComp = dynamic_cast (fileListComponent); + listAsComp->setBounds (x, y, w, browserComp.getHeight() - y - bottomSectionHeight); - y = listAsComp->getBottom() + 4; - filenameBox->setBounds (x + 50, y, w - 50, controlsHeight); + y = listAsComp->getBottom() + 4; + filenameBox->setBounds (x + 50, y, w - 50, controlsHeight); } Image* LookAndFeel::getDefaultFolderImage() { - static const unsigned char foldericon_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,28,8,6,0,0,0,0,194,189,34,0,0,0,4,103,65,77,65,0,0,175,200,55,5, - 138,233,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,100,121,113,201,101,60,0,0,9,46,73,68,65,84,120,218,98,252,255,255,63,3,50,240,41,95,192, - 197,205,198,32,202,204,202,33,241,254,235,47,133,47,191,24,180,213,164,133,152,69,24,222,44,234,42,77,188,245,31,170,129,145,145,145,1,29,128,164,226,91,86,113,252,248,207,200,171,37,39,204,239,170,43, - 254,206,218,88,231,61,62,61,0,1,196,2,149,96,116,200,158,102,194,202,201,227,197,193,206,166,194,204,193,33,195,202,204,38,42,197,197,42,196,193,202,33,240,241,231,15,134,151,95,127,9,2,149,22,0,241,47, - 152,230,128,134,245,204,63,191,188,103,83,144,16,16,228,229,102,151,76,239,217,32,199,204,198,169,205,254,159,65,245,203,79,6,169,131,151,30,47,1,42,91,10,196,127,208,236,101,76,235,90,43,101,160,40,242, - 19,32,128,64,78,98,52,12,41,149,145,215,52,89,162,38,35,107,39,196,203,203,192,206,194,206,192,197,198,202,192,203,197,198,192,205,193,206,240,252,227,103,134,139,55,175,191,127,243,242,78,219,187,207, - 63,215,255,98,23,48,228,227,96,83,98,102,102,85,225,224,228,80,20,224,230,86,226,225,228,150,103,101,97,101,230,227,228,96,224,0,234,191,243,252,5,195,222,19,199,38,191,127,112,161,83,66,199,86,141,131, - 149,69,146,133,153,69,137,149,133,89,157,141,131,77,83,140,143,243,219,255,31,159,123,0,2,136,69,90,207,129,157,71,68,42,66,71,73,209,210,81,91,27,24,142,140,12,127,255,253,103,0,185,236,31,3,144,6,50, - 148,68,216,25,216,24,117,4,239,11,243,214,49,50,51,84,178,48,114,240,112,177,114,177,240,115,113,49,241,112,112,48,176,179,178,51,176,48,49,3,85,255,99,248,253,247,15,195,247,159,191,25,30,191,126,253, - 71,74,76,200,66,75,197,119,138,168,144,160,150,168,0,183,160,152,32,15,175,188,184,32,199,175,191,127,25,214,31,184,120,247,236,209,253,159,0,2,136,133,95,70,93,74,88,80,196,83,69,66,130,149,9,104,219, - 151,31,191,193,150,194,146,6,136,102,102,98,100,16,227,231,103,16,23,210,230,101,101,102,100,248,255,143,137,225,223,63,6,6,22,102,38,134,239,191,126,49,220,123,241,134,225,227,247,175,64,7,252,101,96, - 97,249,207,192,193,198,200,160,171,34,192,108,165,235,104,42,204,207,101,42,194,199,197,192,199,201,198,192,197,193,202,192,198,202,194,176,247,194,3,134,155,183,110,61,188,127,124,221,19,128,0,92,146, - 49,14,64,64,16,69,63,153,85,16,52,18,74,71,112,6,87,119,0,165,160,86,138,32,172,216,29,49,182,84,253,169,94,94,230,127,17,87,133,34,146,174,3,88,126,240,219,164,147,113,31,145,244,152,112,179,211,130, - 34,31,203,113,162,233,6,36,49,163,174,74,124,140,60,141,144,165,161,220,228,25,3,24,105,255,17,168,101,1,139,245,188,93,104,251,73,239,235,50,90,189,111,175,0,98,249,254,254,249,175,239,223,190,126,6, - 5,27,19,47,90,170,102,0,249,158,129,129,141,133,25,228,20,6,38,38,72,74,7,185,243,243,247,239,12,23,31,60,98,228,231,253,207,144,227,107,206,32,202,199,193,240,249,251,127,134,95,191,255,49,124,249,250, - 159,225,237,239,95,12,63,127,1,35,229,31,194,71,32,71,63,123,251,245,223,197,27,183,159,189,187,178,103,61,80,232,59,64,0,177,48,252,5,134,225,255,191,223,126,254,250,13,182,132,1,41,167,176,3,53,128, - 188,254,226,253,103,96,212,252,96,120,247,249,203,255,79,223,191,254,255,250,235,199,191,239,63,191,255,87,145,17,100,73,116,181,100,252,249,243,63,195,149,123,223,193,14,132,101,55,96,52,3,125,255,15, - 204,254,15,132,160,232,253,13,20,124,248,226,227,223,23,207,30,221,120,119,255,226,109,160,210,31,0,1,196,242,231,219,135,175,140,255,126,190,7,197,37,35,19,34,216,65,248,211,143,111,255,79,223,121,240, - 255,211,183,79,76,220,156,172,12,236,204,140,140,252,124,28,140,250,226,82,140,106,82,34,140,124,156,156,12,175,222,253,1,90,4,137,162,63,127,33,161,6,178,242,215,239,255,224,160,255,15,198,12,64,7,48, - 128,211,200,253,151,111,254,254,248,240,236,44,80,217,71,80,246,4,8,32,160,31,255,255,100,102,248,243,238,199,159,63,16,221,16,19,128,248,31,195,181,199,207,254,255,253,247,133,49,212,78,27,104,8,11,40, - 94,25,184,216,89,129,108,38,70,144,242,183,31,17,105,230,63,148,248,15,97,49,252,248,249,15,20,85,72,105,9,148,187,254,49,220,127,254,242,207,243,75,135,14,128,130,31,84,64,1,4,16,203,247,143,175,127, - 48,253,254,246,234,7,48,206,96,137,13,4,64,65,248,234,195,7,6,7,3,57,70,33,46,97,134,111,63,254,50,252,5,250,244,51,216,103,255,192,185,0,150,91,80,44,135,242,127,253,129,164,23,24,96,102,250,207,112, - 255,213,219,255,247,31,63,188,251,246,201,173,199,176,2,13,32,128,88,62,188,121,241,243,211,231,207,31,126,2,147,236,63,168,6,144,193,223,190,255,254,207,198,198,192,40,35,44,206,240,252,205,79,6,132, - 223,24,224,150,32,251,28,25,128,211,29,19,170,24,51,48,88,111,61,127,206,248,254,245,179,139,192,18,247,219,239,239,95,192,249,9,32,128,88,126,124,249,248,231,203,183,111,159,128,33,240,15,24,68,160,180, - 2,204,223,140,12,111,63,127,102,16,228,229,4,6,53,35,195,31,176,119,25,112,3,70,84,55,0,203,50,112,33,134,108,249,103,160,7,159,189,126,253,235,235,227,203,7,255,255,251,247,13,86,63,0,4,16,168,46,248, - 199,250,231,243,235,159,191,126,254,248,245,251,47,23,11,51,51,48,184,152,24,94,127,250,248,95,68,136,151,241,243,55,96,208,51,160,218,255,31,139,27,144,197,254,98,201,202,79,223,124,96,120,245,232,250, - 185,119,143,174,95,250,243,243,219,119,152,60,64,0,129,2,234,223,183,215,15,95,48,254,255,253,3,146,109,192,229,5,195,135,47,159,25,248,184,121,24,126,0,227,29,88,240,49,252,101,36,14,255,1,90,249,7,156, - 222,17,24,24,164,12,207,223,189,99,248,250,252,230,97,96,229,245,2,104,231,111,152,3,0,2,8,228,128,191,15,239,220,120,255,255,223,159,47,160,116,0,42,44,222,124,250,244,239,207,255,63,12,236,108,236,64, - 67,65,81,0,52,244,63,113,248,47,52,10,96,14,98,2,230,191,119,223,127,48,60,121,254,248,235,151,55,207,46,1,163,252,35,114,128,1,4,16,40,10,254,191,121,249,252,199,175,159,63,191,254,2,230,45,118,22,22, - 134,219,207,94,252,231,224,100,103,250,247,15,148,32,64,85,12,34,14,254,227,72,6,255,225,9,240,63,138,26,46,96,214,189,249,244,37,195,139,167,143,30,124,253,246,253,9,40,245,255,71,202,30,0,1,196,2,226, - 0,243,232,159,239,63,127,124,253,11,202,94,64,169,23,31,62,50,138,137,242,49,50,0,211,195,223,255,80,7,252,199,159,6,224,137,145,9,146,231,153,160,165,218,23,96,29,240,244,237,59,134,111,175,31,95,250, - 252,230,241,83,244,182,1,64,0,177,192,28,14,76,132,31,128,169,19,88,220,126,253,207,206,198,196,32,38,36,0,244,61,11,176,148,251,139,145,3,208,29,0,178,16,82,228,66,42,174,223,192,26,8,152,162,25,222, - 125,248,200,240,242,253,39,134,151,79,238,126,254,242,242,238,177,15,47,30,190,5,215,242,72,0,32,128,224,14,96,254,255,231,61,168,92,123,241,254,253,127,1,62,78,6,78,110,78,134,223,64,195,254,50,98,183, - 24,36,12,202,179,224,202,9,88,228,253,132,90,250,246,211,71,134,55,175,94,254,122,255,250,249,247,15,175,159,126,249,251,237,195,135,95,175,110,31,122,117,251,244,49,160,150,111,255,209,218,128,0,1,152, - 44,183,21,0,65,32,136,110,247,254,255,243,122,9,187,64,105,174,74,22,138,25,173,80,208,194,188,238,156,151,217,217,15,32,182,197,37,83,201,4,31,243,178,169,232,242,214,224,223,252,103,175,35,85,1,41,129, - 228,148,142,8,214,30,32,149,6,161,204,109,182,53,236,184,156,78,142,147,195,153,89,35,198,3,87,166,249,220,227,198,59,218,48,252,223,185,111,30,1,132,228,128,127,31,222,124,248,248,27,24,152,28,60,220, - 220,12,44,172,172,224,224,103,5,102,98,144,133,160,236,244,229,231,47,134,239,223,127,49,188,121,251,158,225,241,179,103,12,31,223,189,254,251,227,221,139,55,191,62,188,120,246,235,205,189,59,207,238, - 94,58,241,228,254,109,144,101,159,128,248,51,40,9,32,97,80,217,255,15,221,1,0,1,4,143,130,207,159,191,126,252,246,234,213,111,94,126,94,118,73,94,9,198,127,64,223,126,252,246,147,225,243,215,239,12,223, - 128,229,198,251,15,239,24,62,189,126,249,227,203,171,135,47,63,189,122,252,228,235,155,199,247,95,63,188,118,227,197,227,123,247,127,255,250,249,30,104,198,7,32,126,11,181,252,7,212,183,160,4,247,7,155, - 197,48,0,16,64,112,7,60,121,241,238,189,16,207,15,134,63,63,216,25,95,125,248,198,112,227,241,27,134,15,239,223,50,124,126,245,228,253,143,55,143,158,191,123,116,237,226,171,135,55,175,126,253,252,225, - 229,183,47,159,95,254,253,245,227,253,175,159,223,223,193,124,7,181,20,84,105,252,70,143,103,124,0,32,128,224,14,224,102,253,251,81,144,253,223,235,167,207,30,254,124,127,231,252,155,143,175,159,188,250, - 246,254,249,125,96,60,62,248,250,233,253,147,119,207,238,221,6,150,214,175,129,106,191,130,18,19,146,133,120,125,72,8,0,4,16,34,27,190,121,112,251,3,211,159,69,143,110,223,229,120,255,232,230,221,215, - 79,239,62,4,102,203,207,72,241,9,11,218,63,72,89,137,20,207,98,100,93,16,0,8,32,70,144,1,64,14,168,209,199,7,196,194,160,166,27,212,135,95,96,65,10,173,95,254,34,219,6,51,128,88,7,96,235,21,129,0,64,0, - 193,28,192,8,174,53,33,152,1,155,133,184,12,196,165,4,151,133,232,0,32,192,0,151,97,210,163,246,134,208,52,0,0,0,0,73,69,78,68,174,66,96,130,0,0}; + static const unsigned char foldericon_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,28,8,6,0,0,0,0,194,189,34,0,0,0,4,103,65,77,65,0,0,175,200,55,5, + 138,233,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,100,121,113,201,101,60,0,0,9,46,73,68,65,84,120,218,98,252,255,255,63,3,50,240,41,95,192, + 197,205,198,32,202,204,202,33,241,254,235,47,133,47,191,24,180,213,164,133,152,69,24,222,44,234,42,77,188,245,31,170,129,145,145,145,1,29,128,164,226,91,86,113,252,248,207,200,171,37,39,204,239,170,43, + 254,206,218,88,231,61,62,61,0,1,196,2,149,96,116,200,158,102,194,202,201,227,197,193,206,166,194,204,193,33,195,202,204,38,42,197,197,42,196,193,202,33,240,241,231,15,134,151,95,127,9,2,149,22,0,241,47, + 152,230,128,134,245,204,63,191,188,103,83,144,16,16,228,229,102,151,76,239,217,32,199,204,198,169,205,254,159,65,245,203,79,6,169,131,151,30,47,1,42,91,10,196,127,208,236,101,76,235,90,43,101,160,40,242, + 19,32,128,64,78,98,52,12,41,149,145,215,52,89,162,38,35,107,39,196,203,203,192,206,194,206,192,197,198,202,192,203,197,198,192,205,193,206,240,252,227,103,134,139,55,175,191,127,243,242,78,219,187,207, + 63,215,255,98,23,48,228,227,96,83,98,102,102,85,225,224,228,80,20,224,230,86,226,225,228,150,103,101,97,101,230,227,228,96,224,0,234,191,243,252,5,195,222,19,199,38,191,127,112,161,83,66,199,86,141,131, + 149,69,146,133,153,69,137,149,133,89,157,141,131,77,83,140,143,243,219,255,31,159,123,0,2,136,69,90,207,129,157,71,68,42,66,71,73,209,210,81,91,27,24,142,140,12,127,255,253,103,0,185,236,31,3,144,6,50, + 148,68,216,25,216,24,117,4,239,11,243,214,49,50,51,84,178,48,114,240,112,177,114,177,240,115,113,49,241,112,112,48,176,179,178,51,176,48,49,3,85,255,99,248,253,247,15,195,247,159,191,25,30,191,126,253, + 71,74,76,200,66,75,197,119,138,168,144,160,150,168,0,183,160,152,32,15,175,188,184,32,199,175,191,127,25,214,31,184,120,247,236,209,253,159,0,2,136,133,95,70,93,74,88,80,196,83,69,66,130,149,9,104,219, + 151,31,191,193,150,194,146,6,136,102,102,98,100,16,227,231,103,16,23,210,230,101,101,102,100,248,255,143,137,225,223,63,6,6,22,102,38,134,239,191,126,49,220,123,241,134,225,227,247,175,64,7,252,101,96, + 97,249,207,192,193,198,200,160,171,34,192,108,165,235,104,42,204,207,101,42,194,199,197,192,199,201,198,192,197,193,202,192,198,202,194,176,247,194,3,134,155,183,110,61,188,127,124,221,19,128,0,92,146, + 49,14,64,64,16,69,63,153,85,16,52,18,74,71,112,6,87,119,0,165,160,86,138,32,172,216,29,49,182,84,253,169,94,94,230,127,17,87,133,34,146,174,3,88,126,240,219,164,147,113,31,145,244,152,112,179,211,130, + 34,31,203,113,162,233,6,36,49,163,174,74,124,140,60,141,144,165,161,220,228,25,3,24,105,255,17,168,101,1,139,245,188,93,104,251,73,239,235,50,90,189,111,175,0,98,249,254,254,249,175,239,223,190,126,6, + 5,27,19,47,90,170,102,0,249,158,129,129,141,133,25,228,20,6,38,38,72,74,7,185,243,243,247,239,12,23,31,60,98,228,231,253,207,144,227,107,206,32,202,199,193,240,249,251,127,134,95,191,255,49,124,249,250, + 159,225,237,239,95,12,63,127,1,35,229,31,194,71,32,71,63,123,251,245,223,197,27,183,159,189,187,178,103,61,80,232,59,64,0,177,48,252,5,134,225,255,191,223,126,254,250,13,182,132,1,41,167,176,3,53,128, + 188,254,226,253,103,96,212,252,96,120,247,249,203,255,79,223,191,254,255,250,235,199,191,239,63,191,255,87,145,17,100,73,116,181,100,252,249,243,63,195,149,123,223,193,14,132,101,55,96,52,3,125,255,15, + 204,254,15,132,160,232,253,13,20,124,248,226,227,223,23,207,30,221,120,119,255,226,109,160,210,31,0,1,196,242,231,219,135,175,140,255,126,190,7,197,37,35,19,34,216,65,248,211,143,111,255,79,223,121,240, + 255,211,183,79,76,220,156,172,12,236,204,140,140,252,124,28,140,250,226,82,140,106,82,34,140,124,156,156,12,175,222,253,1,90,4,137,162,63,127,33,161,6,178,242,215,239,255,224,160,255,15,198,12,64,7,48, + 128,211,200,253,151,111,254,254,248,240,236,44,80,217,71,80,246,4,8,32,160,31,255,255,100,102,248,243,238,199,159,63,16,221,16,19,128,248,31,195,181,199,207,254,255,253,247,133,49,212,78,27,104,8,11,40, + 94,25,184,216,89,129,108,38,70,144,242,183,31,17,105,230,63,148,248,15,97,49,252,248,249,15,20,85,72,105,9,148,187,254,49,220,127,254,242,207,243,75,135,14,128,130,31,84,64,1,4,16,203,247,143,175,127, + 48,253,254,246,234,7,48,206,96,137,13,4,64,65,248,234,195,7,6,7,3,57,70,33,46,97,134,111,63,254,50,252,5,250,244,51,216,103,255,192,185,0,150,91,80,44,135,242,127,253,129,164,23,24,96,102,250,207,112, + 255,213,219,255,247,31,63,188,251,246,201,173,199,176,2,13,32,128,88,62,188,121,241,243,211,231,207,31,126,2,147,236,63,168,6,144,193,223,190,255,254,207,198,198,192,40,35,44,206,240,252,205,79,6,132, + 223,24,224,150,32,251,28,25,128,211,29,19,170,24,51,48,88,111,61,127,206,248,254,245,179,139,192,18,247,219,239,239,95,192,249,9,32,128,88,126,124,249,248,231,203,183,111,159,128,33,240,15,24,68,160,180, + 2,204,223,140,12,111,63,127,102,16,228,229,4,6,53,35,195,31,176,119,25,112,3,70,84,55,0,203,50,112,33,134,108,249,103,160,7,159,189,126,253,235,235,227,203,7,255,255,251,247,13,86,63,0,4,16,168,46,248, + 199,250,231,243,235,159,191,126,254,248,245,251,47,23,11,51,51,48,184,152,24,94,127,250,248,95,68,136,151,241,243,55,96,208,51,160,218,255,31,139,27,144,197,254,98,201,202,79,223,124,96,120,245,232,250, + 185,119,143,174,95,250,243,243,219,119,152,60,64,0,129,2,234,223,183,215,15,95,48,254,255,253,3,146,109,192,229,5,195,135,47,159,25,248,184,121,24,126,0,227,29,88,240,49,252,101,36,14,255,1,90,249,7,156, + 222,17,24,24,164,12,207,223,189,99,248,250,252,230,97,96,229,245,2,104,231,111,152,3,0,2,8,228,128,191,15,239,220,120,255,255,223,159,47,160,116,0,42,44,222,124,250,244,239,207,255,63,12,236,108,236,64, + 67,65,81,0,52,244,63,113,248,47,52,10,96,14,98,2,230,191,119,223,127,48,60,121,254,248,235,151,55,207,46,1,163,252,35,114,128,1,4,16,40,10,254,191,121,249,252,199,175,159,63,191,254,2,230,45,118,22,22, + 134,219,207,94,252,231,224,100,103,250,247,15,148,32,64,85,12,34,14,254,227,72,6,255,225,9,240,63,138,26,46,96,214,189,249,244,37,195,139,167,143,30,124,253,246,253,9,40,245,255,71,202,30,0,1,196,2,226, + 0,243,232,159,239,63,127,124,253,11,202,94,64,169,23,31,62,50,138,137,242,49,50,0,211,195,223,255,80,7,252,199,159,6,224,137,145,9,146,231,153,160,165,218,23,96,29,240,244,237,59,134,111,175,31,95,250, + 252,230,241,83,244,182,1,64,0,177,192,28,14,76,132,31,128,169,19,88,220,126,253,207,206,198,196,32,38,36,0,244,61,11,176,148,251,139,145,3,208,29,0,178,16,82,228,66,42,174,223,192,26,8,152,162,25,222, + 125,248,200,240,242,253,39,134,151,79,238,126,254,242,242,238,177,15,47,30,190,5,215,242,72,0,32,128,224,14,96,254,255,231,61,168,92,123,241,254,253,127,1,62,78,6,78,110,78,134,223,64,195,254,50,98,183, + 24,36,12,202,179,224,202,9,88,228,253,132,90,250,246,211,71,134,55,175,94,254,122,255,250,249,247,15,175,159,126,249,251,237,195,135,95,175,110,31,122,117,251,244,49,160,150,111,255,209,218,128,0,1,152, + 44,183,21,0,65,32,136,110,247,254,255,243,122,9,187,64,105,174,74,22,138,25,173,80,208,194,188,238,156,151,217,217,15,32,182,197,37,83,201,4,31,243,178,169,232,242,214,224,223,252,103,175,35,85,1,41,129, + 228,148,142,8,214,30,32,149,6,161,204,109,182,53,236,184,156,78,142,147,195,153,89,35,198,3,87,166,249,220,227,198,59,218,48,252,223,185,111,30,1,132,228,128,127,31,222,124,248,248,27,24,152,28,60,220, + 220,12,44,172,172,224,224,103,5,102,98,144,133,160,236,244,229,231,47,134,239,223,127,49,188,121,251,158,225,241,179,103,12,31,223,189,254,251,227,221,139,55,191,62,188,120,246,235,205,189,59,207,238, + 94,58,241,228,254,109,144,101,159,128,248,51,40,9,32,97,80,217,255,15,221,1,0,1,4,143,130,207,159,191,126,252,246,234,213,111,94,126,94,118,73,94,9,198,127,64,223,126,252,246,147,225,243,215,239,12,223, + 128,229,198,251,15,239,24,62,189,126,249,227,203,171,135,47,63,189,122,252,228,235,155,199,247,95,63,188,118,227,197,227,123,247,127,255,250,249,30,104,198,7,32,126,11,181,252,7,212,183,160,4,247,7,155, + 197,48,0,16,64,112,7,60,121,241,238,189,16,207,15,134,63,63,216,25,95,125,248,198,112,227,241,27,134,15,239,223,50,124,126,245,228,253,143,55,143,158,191,123,116,237,226,171,135,55,175,126,253,252,225, + 229,183,47,159,95,254,253,245,227,253,175,159,223,223,193,124,7,181,20,84,105,252,70,143,103,124,0,32,128,224,14,224,102,253,251,81,144,253,223,235,167,207,30,254,124,127,231,252,155,143,175,159,188,250, + 246,254,249,125,96,60,62,248,250,233,253,147,119,207,238,221,6,150,214,175,129,106,191,130,18,19,146,133,120,125,72,8,0,4,16,34,27,190,121,112,251,3,211,159,69,143,110,223,229,120,255,232,230,221,215, + 79,239,62,4,102,203,207,72,241,9,11,218,63,72,89,137,20,207,98,100,93,16,0,8,32,70,144,1,64,14,168,209,199,7,196,194,160,166,27,212,135,95,96,65,10,173,95,254,34,219,6,51,128,88,7,96,235,21,129,0,64,0, + 193,28,192,8,174,53,33,152,1,155,133,184,12,196,165,4,151,133,232,0,32,192,0,151,97,210,163,246,134,208,52,0,0,0,0,73,69,78,68,174,66,96,130,0,0}; - return ImageCache::getFromMemory (foldericon_png, sizeof (foldericon_png)); + return ImageCache::getFromMemory (foldericon_png, sizeof (foldericon_png)); } Image* LookAndFeel::getDefaultDocumentFileImage() { - static const unsigned char fileicon_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0,115,122,122,244,0,0,0,4,103,65,77,65,0,0,175,200,55,5, - 138,233,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,100,121,113,201,101,60,0,0,4,99,73,68,65,84,120,218,98,252,255,255,63,3,12,48,50,50,50,1, - 169,127,200,98,148,2,160,153,204,64,243,254,226,146,7,8,32,22,52,203,255,107,233,233,91,76,93,176,184,232,239,239,95,127,24,40,112,8,19,51,203,255,179,23,175,108,1,90,190,28,104,54,43,80,232,207,127,44, - 62,3,8,32,6,144,24,84,156,25,132,189,252,3,146,255,83,9,220,127,254,242,134,162,138,170,10,208,92,144,3,152,97,118,33,99,128,0,98,66,114,11,200,1,92,255,254,252,225,32,215,215,32,127,64,240,127,80,60, - 50,40,72,136,169,47,95,179,118,130,136,148,140,0,40,80,128,33,193,136,174,7,32,128,144,29,192,8,117,41,59,209,22,66,241,191,255,16,12,244,19,195,63,48,134,240,255,0,9,115,125,93,239,252,130,130,108,168, - 249,44,232,102,0,4,16,19,22,62,51,33,11,255,195,44,4,211,255,25,96,16,33,6,117,24,56,226,25,24,202,139,10,75,226,51,115,66,160,105,13,197,17,0,1,196,68,172,79,255,33,91,206,192,192,128,176,22,17,10,200, - 234,32,161,240,31,24,10,255,24,152,153,153,184,39,244,247,117,107,234,234,105,131,66,1,154,224,193,0,32,128,240,58,0,22,180,255,144,18,13,40,136,33,113,140,36,255,15,17,26,48,12,81,15,145,255,254,251, - 31,131,0,59,171,84,81,73,105,33,208,216,191,200,161,12,16,64,44,248,131,251,63,10,31,198,253,143,38,6,83,7,11,33,228,232,2,123,4,202,226,228,96,151,132,166,49,144,35,126,131,196,0,2,136,5,103,60,51,252, - 71,49,12,213,130,255,168,226,232,150,254,255,15,143,6,80,202,3,133,16,200,198,63,127,193,229,17,39,16,127,135,217,7,16,64,88,67,0,28,143,255,25,225,46,135,249,18,155,133,240,178,4,205,145,8,62,52,186, - 32,234,152,160,118,194,179,35,64,0,177,96,11,123,144,236,95,104,92,162,228,113,36,11,81,125,140,112,56,186,131,96,226,176,172,137,148,229,193,0,32,128,88,112,167,248,255,112,223,48,34,165,110,6,124,190, - 253,143,61,106,192,9,19,73,28,25,0,4,16,206,40,248,251,15,45,104,209,130,21,51,222,145,18,238,127,180,68,8,244,250,95,164,16,66,6,0,1,196,130,45,253,195,12,250,135,53,206,255,195,131,18,213,98,236,81, - 243,31,154,11,144,115,8,50,0,8,32,156,81,0,203,227,12,80,223,98,230,4,68,72,96,38,78,84,11,65,9,250,47,146,3,145,1,64,0,97,117,192,95,112,34,68,138,130,255,176,224,251,143,226,51,6,6,68,29,192,136,20, - 77,200,69,54,35,3,36,49,255,69,77,132,112,0,16,64,44,56,139,94,36,7,96,102,59,164,108,249,31,181,82,98,64,203,174,255,144,234,142,127,88,146,33,64,0,97,205,134,240,120,67,75,76,136,224,198,140,22,6,44, - 142,66,201,41,255,177,231,2,128,0,194,25,5,255,254,161,134,192,127,6,28,229,0,129,242,1,150,56,33,81,138,209,28,96,0,8,32,172,81,0,78,3,104,190,68,182,224,31,146,197,224,56,6,146,140,176,202,135,17,169, - 96,130,40,64,56,0,139,93,0,1,132,61,10,64,248,31,106,156,162,199,55,204,65,255,144,178,38,74,84,252,71,51,239,63,246,68,8,16,64,44,216,74,1,88,217,13,203,191,32,1,80,58,7,133,224,127,6,68,114,6,241,65, - 81,197,8,101,255,71,114,33,92,237,127,228,52,128,233,2,128,0,98,193,149,3,64,117,193,255,127,255,81,75,191,127,168,5,18,136,255,31,45,161,49,32,151,134,72,252,127,12,216,203,98,128,0,98,193,210,144,135, - 248,30,201,242,127,208,252,140,145,27,160,113,206,136,148,197,192,121,159,17,53,184,225,149,17,22,23,0,4,16,11,182,150,237,63,168,207,96,142,248,143,163,72,6,203,253,67,13,61,6,104,14,66,46,17,254,65, - 19,40,182,16,0,8,32,22,108,109,235,255,176,234,24,35,79,255,199,222,30,64,81,135,90,35,194,211,4,142,92,0,16,64,88,29,0,107,7,254,251,247,31,53,78,241,54,207,80,29,135,209,96,249,143,189,46,0,8,32,116, - 7,252,101,102,103,103,228,103,99,96,248,193,198,137,53,248,49,125,204,128,225,227,255,88,18,54,47,176,25,202,205,195,205,6,109,11,194,149,0,4,16,35,204,85,208,254,27,159,128,176,176,142,166,182,142,21, - 48,4,248,129,41,143,13,217,16,70,52,95,147,0,254,0,187,69,95,223,188,122,125,235,206,141,107,7,129,252,247,64,123,193,237,66,128,0,66,118,0,168,189,198,3,196,252,32,135,64,105,54,228,230,19,185,29,100, - 168,175,191,0,241,7,32,254,4,196,159,129,246,254,2,73,2,4,16,11,90,72,125,135,210,63,161,138,153,169,212,75,255,15,117,196,15,40,134,119,215,1,2,12,0,187,0,132,247,216,161,197,124,0,0,0,0,73,69,78,68, - 174,66,96,130,0,0}; + static const unsigned char fileicon_png[] = { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,32,0,0,0,32,8,6,0,0,0,115,122,122,244,0,0,0,4,103,65,77,65,0,0,175,200,55,5, + 138,233,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,100,121,113,201,101,60,0,0,4,99,73,68,65,84,120,218,98,252,255,255,63,3,12,48,50,50,50,1, + 169,127,200,98,148,2,160,153,204,64,243,254,226,146,7,8,32,22,52,203,255,107,233,233,91,76,93,176,184,232,239,239,95,127,24,40,112,8,19,51,203,255,179,23,175,108,1,90,190,28,104,54,43,80,232,207,127,44, + 62,3,8,32,6,144,24,84,156,25,132,189,252,3,146,255,83,9,220,127,254,242,134,162,138,170,10,208,92,144,3,152,97,118,33,99,128,0,98,66,114,11,200,1,92,255,254,252,225,32,215,215,32,127,64,240,127,80,60, + 50,40,72,136,169,47,95,179,118,130,136,148,140,0,40,80,128,33,193,136,174,7,32,128,144,29,192,8,117,41,59,209,22,66,241,191,255,16,12,244,19,195,63,48,134,240,255,0,9,115,125,93,239,252,130,130,108,168, + 249,44,232,102,0,4,16,19,22,62,51,33,11,255,195,44,4,211,255,25,96,16,33,6,117,24,56,226,25,24,202,139,10,75,226,51,115,66,160,105,13,197,17,0,1,196,68,172,79,255,33,91,206,192,192,128,176,22,17,10,200, + 234,32,161,240,31,24,10,255,24,152,153,153,184,39,244,247,117,107,234,234,105,131,66,1,154,224,193,0,32,128,240,58,0,22,180,255,144,18,13,40,136,33,113,140,36,255,15,17,26,48,12,81,15,145,255,254,251, + 31,131,0,59,171,84,81,73,105,33,208,216,191,200,161,12,16,64,44,248,131,251,63,10,31,198,253,143,38,6,83,7,11,33,228,232,2,123,4,202,226,228,96,151,132,166,49,144,35,126,131,196,0,2,136,5,103,60,51,252, + 71,49,12,213,130,255,168,226,232,150,254,255,15,143,6,80,202,3,133,16,200,198,63,127,193,229,17,39,16,127,135,217,7,16,64,88,67,0,28,143,255,25,225,46,135,249,18,155,133,240,178,4,205,145,8,62,52,186, + 32,234,152,160,118,194,179,35,64,0,177,96,11,123,144,236,95,104,92,162,228,113,36,11,81,125,140,112,56,186,131,96,226,176,172,137,148,229,193,0,32,128,88,112,167,248,255,112,223,48,34,165,110,6,124,190, + 253,143,61,106,192,9,19,73,28,25,0,4,16,206,40,248,251,15,45,104,209,130,21,51,222,145,18,238,127,180,68,8,244,250,95,164,16,66,6,0,1,196,130,45,253,195,12,250,135,53,206,255,195,131,18,213,98,236,81, + 243,31,154,11,144,115,8,50,0,8,32,156,81,0,203,227,12,80,223,98,230,4,68,72,96,38,78,84,11,65,9,250,47,146,3,145,1,64,0,97,117,192,95,112,34,68,138,130,255,176,224,251,143,226,51,6,6,68,29,192,136,20, + 77,200,69,54,35,3,36,49,255,69,77,132,112,0,16,64,44,56,139,94,36,7,96,102,59,164,108,249,31,181,82,98,64,203,174,255,144,234,142,127,88,146,33,64,0,97,205,134,240,120,67,75,76,136,224,198,140,22,6,44, + 142,66,201,41,255,177,231,2,128,0,194,25,5,255,254,161,134,192,127,6,28,229,0,129,242,1,150,56,33,81,138,209,28,96,0,8,32,172,81,0,78,3,104,190,68,182,224,31,146,197,224,56,6,146,140,176,202,135,17,169, + 96,130,40,64,56,0,139,93,0,1,132,61,10,64,248,31,106,156,162,199,55,204,65,255,144,178,38,74,84,252,71,51,239,63,246,68,8,16,64,44,216,74,1,88,217,13,203,191,32,1,80,58,7,133,224,127,6,68,114,6,241,65, + 81,197,8,101,255,71,114,33,92,237,127,228,52,128,233,2,128,0,98,193,149,3,64,117,193,255,127,255,81,75,191,127,168,5,18,136,255,31,45,161,49,32,151,134,72,252,127,12,216,203,98,128,0,98,193,210,144,135, + 248,30,201,242,127,208,252,140,145,27,160,113,206,136,148,197,192,121,159,17,53,184,225,149,17,22,23,0,4,16,11,182,150,237,63,168,207,96,142,248,143,163,72,6,203,253,67,13,61,6,104,14,66,46,17,254,65, + 19,40,182,16,0,8,32,22,108,109,235,255,176,234,24,35,79,255,199,222,30,64,81,135,90,35,194,211,4,142,92,0,16,64,88,29,0,107,7,254,251,247,31,53,78,241,54,207,80,29,135,209,96,249,143,189,46,0,8,32,116, + 7,252,101,102,103,103,228,103,99,96,248,193,198,137,53,248,49,125,204,128,225,227,255,88,18,54,47,176,25,202,205,195,205,6,109,11,194,149,0,4,16,35,204,85,208,254,27,159,128,176,176,142,166,182,142,21, + 48,4,248,129,41,143,13,217,16,70,52,95,147,0,254,0,187,69,95,223,188,122,125,235,206,141,107,7,129,252,247,64,123,193,237,66,128,0,66,118,0,168,189,198,3,196,252,32,135,64,105,54,228,230,19,185,29,100, + 168,175,191,0,241,7,32,254,4,196,159,129,246,254,2,73,2,4,16,11,90,72,125,135,210,63,161,138,153,169,212,75,255,15,117,196,15,40,134,119,215,1,2,12,0,187,0,132,247,216,161,197,124,0,0,0,0,73,69,78,68, + 174,66,96,130,0,0}; - return ImageCache::getFromMemory (fileicon_png, sizeof (fileicon_png)); + return ImageCache::getFromMemory (fileicon_png, sizeof (fileicon_png)); } void LookAndFeel::playAlertSound() { - PlatformUtilities::beep(); + PlatformUtilities::beep(); } void LookAndFeel::drawLevelMeter (Graphics& g, int width, int height, float level) { - g.setColour (Colours::white.withAlpha (0.7f)); - g.fillRoundedRectangle (0.0f, 0.0f, (float) width, (float) height, 3.0f); - g.setColour (Colours::black.withAlpha (0.2f)); - g.drawRoundedRectangle (1.0f, 1.0f, width - 2.0f, height - 2.0f, 3.0f, 1.0f); + g.setColour (Colours::white.withAlpha (0.7f)); + g.fillRoundedRectangle (0.0f, 0.0f, (float) width, (float) height, 3.0f); + g.setColour (Colours::black.withAlpha (0.2f)); + g.drawRoundedRectangle (1.0f, 1.0f, width - 2.0f, height - 2.0f, 3.0f, 1.0f); - const int totalBlocks = 7; - const int numBlocks = roundDoubleToInt (totalBlocks * level); - const float w = (width - 6.0f) / (float) totalBlocks; + const int totalBlocks = 7; + const int numBlocks = roundToInt (totalBlocks * level); + const float w = (width - 6.0f) / (float) totalBlocks; - for (int i = 0; i < totalBlocks; ++i) - { - if (i >= numBlocks) - g.setColour (Colours::lightblue.withAlpha (0.6f)); - else - g.setColour (i < totalBlocks - 1 ? Colours::blue.withAlpha (0.5f) - : Colours::red); + for (int i = 0; i < totalBlocks; ++i) + { + if (i >= numBlocks) + g.setColour (Colours::lightblue.withAlpha (0.6f)); + else + g.setColour (i < totalBlocks - 1 ? Colours::blue.withAlpha (0.5f) + : Colours::red); - g.fillRoundedRectangle (3.0f + i * w + w * 0.1f, 3.0f, w * 0.8f, height - 6.0f, w * 0.4f); - } + g.fillRoundedRectangle (3.0f + i * w + w * 0.1f, 3.0f, w * 0.8f, height - 6.0f, w * 0.4f); + } } void LookAndFeel::drawKeymapChangeButton (Graphics& g, int width, int height, Button& button, const String& keyDescription) { - const Colour textColour (button.findColour (KeyMappingEditorComponent::textColourId, true)); + const Colour textColour (button.findColour (KeyMappingEditorComponent::textColourId, true)); - if (keyDescription.isNotEmpty()) - { - if (button.isEnabled()) - { - const float alpha = button.isDown() ? 0.3f : (button.isOver() ? 0.15f : 0.08f); - g.fillAll (textColour.withAlpha (alpha)); + if (keyDescription.isNotEmpty()) + { + if (button.isEnabled()) + { + const float alpha = button.isDown() ? 0.3f : (button.isOver() ? 0.15f : 0.08f); + g.fillAll (textColour.withAlpha (alpha)); - g.setOpacity (0.3f); - g.drawBevel (0, 0, width, height, 2); - } + g.setOpacity (0.3f); + g.drawBevel (0, 0, width, height, 2); + } - g.setColour (textColour); - g.setFont (height * 0.6f); - g.drawFittedText (keyDescription, - 3, 0, width - 6, height, - Justification::centred, 1); - } - else - { - const float thickness = 7.0f; - const float indent = 22.0f; + g.setColour (textColour); + g.setFont (height * 0.6f); + g.drawFittedText (keyDescription, + 3, 0, width - 6, height, + Justification::centred, 1); + } + else + { + const float thickness = 7.0f; + const float indent = 22.0f; - Path p; - p.addEllipse (0.0f, 0.0f, 100.0f, 100.0f); - p.addRectangle (indent, 50.0f - thickness, 100.0f - indent * 2.0f, thickness * 2.0f); - p.addRectangle (50.0f - thickness, indent, thickness * 2.0f, 50.0f - indent - thickness); - p.addRectangle (50.0f - thickness, 50.0f + thickness, thickness * 2.0f, 50.0f - indent - thickness); - p.setUsingNonZeroWinding (false); + Path p; + p.addEllipse (0.0f, 0.0f, 100.0f, 100.0f); + p.addRectangle (indent, 50.0f - thickness, 100.0f - indent * 2.0f, thickness * 2.0f); + p.addRectangle (50.0f - thickness, indent, thickness * 2.0f, 50.0f - indent - thickness); + p.addRectangle (50.0f - thickness, 50.0f + thickness, thickness * 2.0f, 50.0f - indent - thickness); + p.setUsingNonZeroWinding (false); - g.setColour (textColour.withAlpha (button.isDown() ? 0.7f : (button.isOver() ? 0.5f : 0.3f))); - g.fillPath (p, p.getTransformToScaleToFit (2.0f, 2.0f, width - 4.0f, height - 4.0f, true)); - } + g.setColour (textColour.withAlpha (button.isDown() ? 0.7f : (button.isOver() ? 0.5f : 0.3f))); + g.fillPath (p, p.getTransformToScaleToFit (2.0f, 2.0f, width - 4.0f, height - 4.0f, true)); + } - if (button.hasKeyboardFocus (false)) - { - g.setColour (textColour.withAlpha (0.4f)); - g.drawRect (0, 0, width, height); - } + if (button.hasKeyboardFocus (false)) + { + g.setColour (textColour.withAlpha (0.4f)); + g.drawRect (0, 0, width, height); + } } static void createRoundedPath (Path& p, - const float x, const float y, - const float w, const float h, - const float cs, - const bool curveTopLeft, const bool curveTopRight, - const bool curveBottomLeft, const bool curveBottomRight) throw() + const float x, const float y, + const float w, const float h, + const float cs, + const bool curveTopLeft, const bool curveTopRight, + const bool curveBottomLeft, const bool curveBottomRight) throw() { - const float cs2 = 2.0f * cs; + const float cs2 = 2.0f * cs; - if (curveTopLeft) - { - p.startNewSubPath (x, y + cs); - p.addArc (x, y, cs2, cs2, float_Pi * 1.5f, float_Pi * 2.0f); - } - else - { - p.startNewSubPath (x, y); - } + if (curveTopLeft) + { + p.startNewSubPath (x, y + cs); + p.addArc (x, y, cs2, cs2, float_Pi * 1.5f, float_Pi * 2.0f); + } + else + { + p.startNewSubPath (x, y); + } - if (curveTopRight) - { - p.lineTo (x + w - cs, y); - p.addArc (x + w - cs2, y, cs2, cs2, 0.0f, float_Pi * 0.5f); - } - else - { - p.lineTo (x + w, y); - } + if (curveTopRight) + { + p.lineTo (x + w - cs, y); + p.addArc (x + w - cs2, y, cs2, cs2, 0.0f, float_Pi * 0.5f); + } + else + { + p.lineTo (x + w, y); + } - if (curveBottomRight) - { - p.lineTo (x + w, y + h - cs); - p.addArc (x + w - cs2, y + h - cs2, cs2, cs2, float_Pi * 0.5f, float_Pi); - } - else - { - p.lineTo (x + w, y + h); - } + if (curveBottomRight) + { + p.lineTo (x + w, y + h - cs); + p.addArc (x + w - cs2, y + h - cs2, cs2, cs2, float_Pi * 0.5f, float_Pi); + } + else + { + p.lineTo (x + w, y + h); + } - if (curveBottomLeft) - { - p.lineTo (x + cs, y + h); - p.addArc (x, y + h - cs2, cs2, cs2, float_Pi, float_Pi * 1.5f); - } - else - { - p.lineTo (x, y + h); - } + if (curveBottomLeft) + { + p.lineTo (x + cs, y + h); + p.addArc (x, y + h - cs2, cs2, cs2, float_Pi, float_Pi * 1.5f); + } + else + { + p.lineTo (x, y + h); + } - p.closeSubPath(); + p.closeSubPath(); } void LookAndFeel::drawShinyButtonShape (Graphics& g, - float x, float y, float w, float h, - float maxCornerSize, - const Colour& baseColour, - const float strokeWidth, - const bool flatOnLeft, - const bool flatOnRight, - const bool flatOnTop, - const bool flatOnBottom) throw() + float x, float y, float w, float h, + float maxCornerSize, + const Colour& baseColour, + const float strokeWidth, + const bool flatOnLeft, + const bool flatOnRight, + const bool flatOnTop, + const bool flatOnBottom) throw() { - if (w <= strokeWidth * 1.1f || h <= strokeWidth * 1.1f) - return; + if (w <= strokeWidth * 1.1f || h <= strokeWidth * 1.1f) + return; - const float cs = jmin (maxCornerSize, w * 0.5f, h * 0.5f); + const float cs = jmin (maxCornerSize, w * 0.5f, h * 0.5f); - Path outline; - createRoundedPath (outline, x, y, w, h, cs, - ! (flatOnLeft || flatOnTop), - ! (flatOnRight || flatOnTop), - ! (flatOnLeft || flatOnBottom), - ! (flatOnRight || flatOnBottom)); + Path outline; + createRoundedPath (outline, x, y, w, h, cs, + ! (flatOnLeft || flatOnTop), + ! (flatOnRight || flatOnTop), + ! (flatOnLeft || flatOnBottom), + ! (flatOnRight || flatOnBottom)); - ColourGradient cg (baseColour, 0.0f, y, - baseColour.overlaidWith (Colour (0x070000ff)), 0.0f, y + h, - false); + ColourGradient cg (baseColour, 0.0f, y, + baseColour.overlaidWith (Colour (0x070000ff)), 0.0f, y + h, + false); - cg.addColour (0.5, baseColour.overlaidWith (Colour (0x33ffffff))); - cg.addColour (0.51, baseColour.overlaidWith (Colour (0x110000ff))); + cg.addColour (0.5, baseColour.overlaidWith (Colour (0x33ffffff))); + cg.addColour (0.51, baseColour.overlaidWith (Colour (0x110000ff))); - g.setGradientFill (cg); - g.fillPath (outline); + g.setGradientFill (cg); + g.fillPath (outline); - g.setColour (Colour (0x80000000)); - g.strokePath (outline, PathStrokeType (strokeWidth)); + g.setColour (Colour (0x80000000)); + g.strokePath (outline, PathStrokeType (strokeWidth)); } void LookAndFeel::drawGlassSphere (Graphics& g, - const float x, const float y, - const float diameter, - const Colour& colour, - const float outlineThickness) throw() + const float x, const float y, + const float diameter, + const Colour& colour, + const float outlineThickness) throw() { - if (diameter <= outlineThickness) - return; + if (diameter <= outlineThickness) + return; - Path p; - p.addEllipse (x, y, diameter, diameter); + Path p; + p.addEllipse (x, y, diameter, diameter); - { - ColourGradient cg (Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y, - Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y + diameter, false); + { + ColourGradient cg (Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y, + Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y + diameter, false); - cg.addColour (0.4, Colours::white.overlaidWith (colour)); + cg.addColour (0.4, Colours::white.overlaidWith (colour)); - g.setGradientFill (cg); - g.fillPath (p); - } + g.setGradientFill (cg); + g.fillPath (p); + } - g.setGradientFill (ColourGradient (Colours::white, 0, y + diameter * 0.06f, - Colours::transparentWhite, 0, y + diameter * 0.3f, false)); - g.fillEllipse (x + diameter * 0.2f, y + diameter * 0.05f, diameter * 0.6f, diameter * 0.4f); + g.setGradientFill (ColourGradient (Colours::white, 0, y + diameter * 0.06f, + Colours::transparentWhite, 0, y + diameter * 0.3f, false)); + g.fillEllipse (x + diameter * 0.2f, y + diameter * 0.05f, diameter * 0.6f, diameter * 0.4f); - ColourGradient cg (Colours::transparentBlack, - x + diameter * 0.5f, y + diameter * 0.5f, - Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), - x, y + diameter * 0.5f, true); + ColourGradient cg (Colours::transparentBlack, + x + diameter * 0.5f, y + diameter * 0.5f, + Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), + x, y + diameter * 0.5f, true); - cg.addColour (0.7, Colours::transparentBlack); - cg.addColour (0.8, Colours::black.withAlpha (0.1f * outlineThickness)); + cg.addColour (0.7, Colours::transparentBlack); + cg.addColour (0.8, Colours::black.withAlpha (0.1f * outlineThickness)); - g.setGradientFill (cg); - g.fillPath (p); + g.setGradientFill (cg); + g.fillPath (p); - g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha())); - g.drawEllipse (x, y, diameter, diameter, outlineThickness); + g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha())); + g.drawEllipse (x, y, diameter, diameter, outlineThickness); } void LookAndFeel::drawGlassPointer (Graphics& g, - const float x, const float y, - const float diameter, - const Colour& colour, const float outlineThickness, - const int direction) throw() + const float x, const float y, + const float diameter, + const Colour& colour, const float outlineThickness, + const int direction) throw() { - if (diameter <= outlineThickness) - return; + if (diameter <= outlineThickness) + return; - Path p; - p.startNewSubPath (x + diameter * 0.5f, y); - p.lineTo (x + diameter, y + diameter * 0.6f); - p.lineTo (x + diameter, y + diameter); - p.lineTo (x, y + diameter); - p.lineTo (x, y + diameter * 0.6f); - p.closeSubPath(); + Path p; + p.startNewSubPath (x + diameter * 0.5f, y); + p.lineTo (x + diameter, y + diameter * 0.6f); + p.lineTo (x + diameter, y + diameter); + p.lineTo (x, y + diameter); + p.lineTo (x, y + diameter * 0.6f); + p.closeSubPath(); - p.applyTransform (AffineTransform::rotation (direction * (float_Pi * 0.5f), x + diameter * 0.5f, y + diameter * 0.5f)); + p.applyTransform (AffineTransform::rotation (direction * (float_Pi * 0.5f), x + diameter * 0.5f, y + diameter * 0.5f)); - { - ColourGradient cg (Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y, - Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y + diameter, false); + { + ColourGradient cg (Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y, + Colours::white.overlaidWith (colour.withMultipliedAlpha (0.3f)), 0, y + diameter, false); - cg.addColour (0.4, Colours::white.overlaidWith (colour)); + cg.addColour (0.4, Colours::white.overlaidWith (colour)); - g.setGradientFill (cg); - g.fillPath (p); - } + g.setGradientFill (cg); + g.fillPath (p); + } - ColourGradient cg (Colours::transparentBlack, - x + diameter * 0.5f, y + diameter * 0.5f, - Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), - x - diameter * 0.2f, y + diameter * 0.5f, true); + ColourGradient cg (Colours::transparentBlack, + x + diameter * 0.5f, y + diameter * 0.5f, + Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), + x - diameter * 0.2f, y + diameter * 0.5f, true); - cg.addColour (0.5, Colours::transparentBlack); - cg.addColour (0.7, Colours::black.withAlpha (0.07f * outlineThickness)); + cg.addColour (0.5, Colours::transparentBlack); + cg.addColour (0.7, Colours::black.withAlpha (0.07f * outlineThickness)); - g.setGradientFill (cg); - g.fillPath (p); + g.setGradientFill (cg); + g.fillPath (p); - g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha())); - g.strokePath (p, PathStrokeType (outlineThickness)); + g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha())); + g.strokePath (p, PathStrokeType (outlineThickness)); } void LookAndFeel::drawGlassLozenge (Graphics& g, - const float x, const float y, - const float width, const float height, - const Colour& colour, - const float outlineThickness, - const float cornerSize, - const bool flatOnLeft, - const bool flatOnRight, - const bool flatOnTop, - const bool flatOnBottom) throw() + const float x, const float y, + const float width, const float height, + const Colour& colour, + const float outlineThickness, + const float cornerSize, + const bool flatOnLeft, + const bool flatOnRight, + const bool flatOnTop, + const bool flatOnBottom) throw() { - if (width <= outlineThickness || height <= outlineThickness) - return; + if (width <= outlineThickness || height <= outlineThickness) + return; - const int intX = (int) x; - const int intY = (int) y; - const int intW = (int) width; - const int intH = (int) height; + const int intX = (int) x; + const int intY = (int) y; + const int intW = (int) width; + const int intH = (int) height; - const float cs = cornerSize < 0 ? jmin (width * 0.5f, height * 0.5f) : cornerSize; - const float edgeBlurRadius = height * 0.75f + (height - cs * 2.0f); - const int intEdge = (int) edgeBlurRadius; + const float cs = cornerSize < 0 ? jmin (width * 0.5f, height * 0.5f) : cornerSize; + const float edgeBlurRadius = height * 0.75f + (height - cs * 2.0f); + const int intEdge = (int) edgeBlurRadius; - Path outline; - createRoundedPath (outline, x, y, width, height, cs, - ! (flatOnLeft || flatOnTop), - ! (flatOnRight || flatOnTop), - ! (flatOnLeft || flatOnBottom), - ! (flatOnRight || flatOnBottom)); + Path outline; + createRoundedPath (outline, x, y, width, height, cs, + ! (flatOnLeft || flatOnTop), + ! (flatOnRight || flatOnTop), + ! (flatOnLeft || flatOnBottom), + ! (flatOnRight || flatOnBottom)); - { - ColourGradient cg (colour.darker (0.2f), 0, y, - colour.darker (0.2f), 0, y + height, false); + { + ColourGradient cg (colour.darker (0.2f), 0, y, + colour.darker (0.2f), 0, y + height, false); - cg.addColour (0.03, colour.withMultipliedAlpha (0.3f)); - cg.addColour (0.4, colour); - cg.addColour (0.97, colour.withMultipliedAlpha (0.3f)); + cg.addColour (0.03, colour.withMultipliedAlpha (0.3f)); + cg.addColour (0.4, colour); + cg.addColour (0.97, colour.withMultipliedAlpha (0.3f)); - g.setGradientFill (cg); - g.fillPath (outline); - } + g.setGradientFill (cg); + g.fillPath (outline); + } - ColourGradient cg (Colours::transparentBlack, x + edgeBlurRadius, y + height * 0.5f, - colour.darker (0.2f), x, y + height * 0.5f, true); + ColourGradient cg (Colours::transparentBlack, x + edgeBlurRadius, y + height * 0.5f, + colour.darker (0.2f), x, y + height * 0.5f, true); - cg.addColour (jlimit (0.0, 1.0, 1.0 - (cs * 0.5f) / edgeBlurRadius), Colours::transparentBlack); - cg.addColour (jlimit (0.0, 1.0, 1.0 - (cs * 0.25f) / edgeBlurRadius), colour.darker (0.2f).withMultipliedAlpha (0.3f)); + cg.addColour (jlimit (0.0, 1.0, 1.0 - (cs * 0.5f) / edgeBlurRadius), Colours::transparentBlack); + cg.addColour (jlimit (0.0, 1.0, 1.0 - (cs * 0.25f) / edgeBlurRadius), colour.darker (0.2f).withMultipliedAlpha (0.3f)); - if (! (flatOnLeft || flatOnTop || flatOnBottom)) - { - g.saveState(); - g.setGradientFill (cg); - g.reduceClipRegion (intX, intY, intEdge, intH); - g.fillPath (outline); - g.restoreState(); - } + if (! (flatOnLeft || flatOnTop || flatOnBottom)) + { + g.saveState(); + g.setGradientFill (cg); + g.reduceClipRegion (intX, intY, intEdge, intH); + g.fillPath (outline); + g.restoreState(); + } - if (! (flatOnRight || flatOnTop || flatOnBottom)) - { - cg.x1 = x + width - edgeBlurRadius; - cg.x2 = x + width; + if (! (flatOnRight || flatOnTop || flatOnBottom)) + { + cg.x1 = x + width - edgeBlurRadius; + cg.x2 = x + width; - g.saveState(); - g.setGradientFill (cg); - g.reduceClipRegion (intX + intW - intEdge, intY, 2 + intEdge, intH); - g.fillPath (outline); - g.restoreState(); - } + g.saveState(); + g.setGradientFill (cg); + g.reduceClipRegion (intX + intW - intEdge, intY, 2 + intEdge, intH); + g.fillPath (outline); + g.restoreState(); + } - { - const float leftIndent = flatOnLeft ? 0.0f : cs * 0.4f; - const float rightIndent = flatOnRight ? 0.0f : cs * 0.4f; + { + const float leftIndent = flatOnLeft ? 0.0f : cs * 0.4f; + const float rightIndent = flatOnRight ? 0.0f : cs * 0.4f; - Path highlight; - createRoundedPath (highlight, - x + leftIndent, - y + cs * 0.1f, - width - (leftIndent + rightIndent), - height * 0.4f, cs * 0.4f, - ! (flatOnLeft || flatOnTop), - ! (flatOnRight || flatOnTop), - ! (flatOnLeft || flatOnBottom), - ! (flatOnRight || flatOnBottom)); + Path highlight; + createRoundedPath (highlight, + x + leftIndent, + y + cs * 0.1f, + width - (leftIndent + rightIndent), + height * 0.4f, cs * 0.4f, + ! (flatOnLeft || flatOnTop), + ! (flatOnRight || flatOnTop), + ! (flatOnLeft || flatOnBottom), + ! (flatOnRight || flatOnBottom)); - g.setGradientFill (ColourGradient (colour.brighter (10.0f), 0, y + height * 0.06f, - Colours::transparentWhite, 0, y + height * 0.4f, false)); - g.fillPath (highlight); - } + g.setGradientFill (ColourGradient (colour.brighter (10.0f), 0, y + height * 0.06f, + Colours::transparentWhite, 0, y + height * 0.4f, false)); + g.fillPath (highlight); + } - g.setColour (colour.darker().withMultipliedAlpha (1.5f)); - g.strokePath (outline, PathStrokeType (outlineThickness)); + g.setColour (colour.darker().withMultipliedAlpha (1.5f)); + g.strokePath (outline, PathStrokeType (outlineThickness)); } END_JUCE_NAMESPACE @@ -67317,21 +67016,21 @@ BEGIN_JUCE_NAMESPACE OldSchoolLookAndFeel::OldSchoolLookAndFeel() { - setColour (TextButton::buttonColourId, Colour (0xffbbbbff)); - setColour (ListBox::outlineColourId, findColour (ComboBox::outlineColourId)); - setColour (ScrollBar::thumbColourId, Colour (0xffbbbbdd)); - setColour (ScrollBar::backgroundColourId, Colours::transparentBlack); - setColour (Slider::thumbColourId, Colours::white); - setColour (Slider::trackColourId, Colour (0x7f000000)); - setColour (Slider::textBoxOutlineColourId, Colours::grey); - setColour (ProgressBar::backgroundColourId, Colours::white.withAlpha (0.6f)); - setColour (ProgressBar::foregroundColourId, Colours::green.withAlpha (0.7f)); - setColour (PopupMenu::backgroundColourId, Colour (0xffeef5f8)); - setColour (PopupMenu::highlightedBackgroundColourId, Colour (0xbfa4c2ce)); - setColour (PopupMenu::highlightedTextColourId, Colours::black); - setColour (TextEditor::focusedOutlineColourId, findColour (TextButton::buttonColourId)); + setColour (TextButton::buttonColourId, Colour (0xffbbbbff)); + setColour (ListBox::outlineColourId, findColour (ComboBox::outlineColourId)); + setColour (ScrollBar::thumbColourId, Colour (0xffbbbbdd)); + setColour (ScrollBar::backgroundColourId, Colours::transparentBlack); + setColour (Slider::thumbColourId, Colours::white); + setColour (Slider::trackColourId, Colour (0x7f000000)); + setColour (Slider::textBoxOutlineColourId, Colours::grey); + setColour (ProgressBar::backgroundColourId, Colours::white.withAlpha (0.6f)); + setColour (ProgressBar::foregroundColourId, Colours::green.withAlpha (0.7f)); + setColour (PopupMenu::backgroundColourId, Colour (0xffeef5f8)); + setColour (PopupMenu::highlightedBackgroundColourId, Colour (0xbfa4c2ce)); + setColour (PopupMenu::highlightedTextColourId, Colours::black); + setColour (TextEditor::focusedOutlineColourId, findColour (TextButton::buttonColourId)); - scrollbarShadow.setShadowProperties (2.2f, 0.5f, 0, 0); + scrollbarShadow.setShadowProperties (2.2f, 0.5f, 0, 0); } OldSchoolLookAndFeel::~OldSchoolLookAndFeel() @@ -67339,541 +67038,541 @@ OldSchoolLookAndFeel::~OldSchoolLookAndFeel() } void OldSchoolLookAndFeel::drawButtonBackground (Graphics& g, - Button& button, - const Colour& backgroundColour, - bool isMouseOverButton, - bool isButtonDown) + Button& button, + const Colour& backgroundColour, + bool isMouseOverButton, + bool isButtonDown) { - const int width = button.getWidth(); - const int height = button.getHeight(); + const int width = button.getWidth(); + const int height = button.getHeight(); - const float indent = 2.0f; - const int cornerSize = jmin (roundFloatToInt (width * 0.4f), - roundFloatToInt (height * 0.4f)); + const float indent = 2.0f; + const int cornerSize = jmin (roundToInt (width * 0.4f), + roundToInt (height * 0.4f)); - Path p; - p.addRoundedRectangle (indent, indent, - width - indent * 2.0f, - height - indent * 2.0f, - (float) cornerSize); + Path p; + p.addRoundedRectangle (indent, indent, + width - indent * 2.0f, + height - indent * 2.0f, + (float) cornerSize); - Colour bc (backgroundColour.withMultipliedSaturation (0.3f)); + Colour bc (backgroundColour.withMultipliedSaturation (0.3f)); - if (isMouseOverButton) - { - if (isButtonDown) - bc = bc.brighter(); - else if (bc.getBrightness() > 0.5f) - bc = bc.darker (0.1f); - else - bc = bc.brighter (0.1f); - } + if (isMouseOverButton) + { + if (isButtonDown) + bc = bc.brighter(); + else if (bc.getBrightness() > 0.5f) + bc = bc.darker (0.1f); + else + bc = bc.brighter (0.1f); + } - g.setColour (bc); - g.fillPath (p); + g.setColour (bc); + g.fillPath (p); - g.setColour (bc.contrasting().withAlpha ((isMouseOverButton) ? 0.6f : 0.4f)); - g.strokePath (p, PathStrokeType ((isMouseOverButton) ? 2.0f : 1.4f)); + g.setColour (bc.contrasting().withAlpha ((isMouseOverButton) ? 0.6f : 0.4f)); + g.strokePath (p, PathStrokeType ((isMouseOverButton) ? 2.0f : 1.4f)); } void OldSchoolLookAndFeel::drawTickBox (Graphics& g, - Component& /*component*/, - int x, int y, int w, int h, - const bool ticked, - const bool isEnabled, - const bool /*isMouseOverButton*/, - const bool isButtonDown) + Component& /*component*/, + int x, int y, int w, int h, + const bool ticked, + const bool isEnabled, + const bool /*isMouseOverButton*/, + const bool isButtonDown) { - Path box; - box.addRoundedRectangle (0.0f, 2.0f, 6.0f, 6.0f, 1.0f); + Path box; + box.addRoundedRectangle (0.0f, 2.0f, 6.0f, 6.0f, 1.0f); - g.setColour (isEnabled ? Colours::blue.withAlpha (isButtonDown ? 0.3f : 0.1f) - : Colours::lightgrey.withAlpha (0.1f)); + g.setColour (isEnabled ? Colours::blue.withAlpha (isButtonDown ? 0.3f : 0.1f) + : Colours::lightgrey.withAlpha (0.1f)); - AffineTransform trans (AffineTransform::scale (w / 9.0f, h / 9.0f) - .translated ((float) x, (float) y)); + AffineTransform trans (AffineTransform::scale (w / 9.0f, h / 9.0f) + .translated ((float) x, (float) y)); - g.fillPath (box, trans); + g.fillPath (box, trans); - g.setColour (Colours::black.withAlpha (0.6f)); - g.strokePath (box, PathStrokeType (0.9f), trans); + g.setColour (Colours::black.withAlpha (0.6f)); + g.strokePath (box, PathStrokeType (0.9f), trans); - if (ticked) - { - Path tick; - tick.startNewSubPath (1.5f, 3.0f); - tick.lineTo (3.0f, 6.0f); - tick.lineTo (6.0f, 0.0f); + if (ticked) + { + Path tick; + tick.startNewSubPath (1.5f, 3.0f); + tick.lineTo (3.0f, 6.0f); + tick.lineTo (6.0f, 0.0f); - g.setColour (isEnabled ? Colours::black : Colours::grey); - g.strokePath (tick, PathStrokeType (2.5f), trans); - } + g.setColour (isEnabled ? Colours::black : Colours::grey); + g.strokePath (tick, PathStrokeType (2.5f), trans); + } } void OldSchoolLookAndFeel::drawToggleButton (Graphics& g, - ToggleButton& button, - bool isMouseOverButton, - bool isButtonDown) + ToggleButton& button, + bool isMouseOverButton, + bool isButtonDown) { - if (button.hasKeyboardFocus (true)) - { - g.setColour (button.findColour (TextEditor::focusedOutlineColourId)); - g.drawRect (0, 0, button.getWidth(), button.getHeight()); - } + if (button.hasKeyboardFocus (true)) + { + g.setColour (button.findColour (TextEditor::focusedOutlineColourId)); + g.drawRect (0, 0, button.getWidth(), button.getHeight()); + } - const int tickWidth = jmin (20, button.getHeight() - 4); + const int tickWidth = jmin (20, button.getHeight() - 4); - drawTickBox (g, button, 4, (button.getHeight() - tickWidth) / 2, - tickWidth, tickWidth, - button.getToggleState(), - button.isEnabled(), - isMouseOverButton, - isButtonDown); + drawTickBox (g, button, 4, (button.getHeight() - tickWidth) / 2, + tickWidth, tickWidth, + button.getToggleState(), + button.isEnabled(), + isMouseOverButton, + isButtonDown); - g.setColour (button.findColour (ToggleButton::textColourId)); - g.setFont (jmin (15.0f, button.getHeight() * 0.6f)); + g.setColour (button.findColour (ToggleButton::textColourId)); + g.setFont (jmin (15.0f, button.getHeight() * 0.6f)); - if (! button.isEnabled()) - g.setOpacity (0.5f); + if (! button.isEnabled()) + g.setOpacity (0.5f); - const int textX = tickWidth + 5; + const int textX = tickWidth + 5; - g.drawFittedText (button.getButtonText(), - textX, 4, - button.getWidth() - textX - 2, button.getHeight() - 8, - Justification::centredLeft, 10); + g.drawFittedText (button.getButtonText(), + textX, 4, + button.getWidth() - textX - 2, button.getHeight() - 8, + Justification::centredLeft, 10); } void OldSchoolLookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar, - int width, int height, - double progress, const String& textToShow) + int width, int height, + double progress, const String& textToShow) { - if (progress < 0 || progress >= 1.0) - { - LookAndFeel::drawProgressBar (g, progressBar, width, height, progress, textToShow); - } - else - { - const Colour background (progressBar.findColour (ProgressBar::backgroundColourId)); - const Colour foreground (progressBar.findColour (ProgressBar::foregroundColourId)); + if (progress < 0 || progress >= 1.0) + { + LookAndFeel::drawProgressBar (g, progressBar, width, height, progress, textToShow); + } + else + { + const Colour background (progressBar.findColour (ProgressBar::backgroundColourId)); + const Colour foreground (progressBar.findColour (ProgressBar::foregroundColourId)); - g.fillAll (background); - g.setColour (foreground); + g.fillAll (background); + g.setColour (foreground); - g.fillRect (1, 1, - jlimit (0, width - 2, roundDoubleToInt (progress * (width - 2))), - height - 2); + g.fillRect (1, 1, + jlimit (0, width - 2, roundToInt (progress * (width - 2))), + height - 2); - if (textToShow.isNotEmpty()) - { - g.setColour (Colour::contrasting (background, foreground)); - g.setFont (height * 0.6f); + if (textToShow.isNotEmpty()) + { + g.setColour (Colour::contrasting (background, foreground)); + g.setFont (height * 0.6f); - g.drawText (textToShow, 0, 0, width, height, Justification::centred, false); - } - } + g.drawText (textToShow, 0, 0, width, height, Justification::centred, false); + } + } } void OldSchoolLookAndFeel::drawScrollbarButton (Graphics& g, - ScrollBar& bar, - int width, int height, - int buttonDirection, - bool isScrollbarVertical, - bool isMouseOverButton, - bool isButtonDown) + ScrollBar& bar, + int width, int height, + int buttonDirection, + bool isScrollbarVertical, + bool isMouseOverButton, + bool isButtonDown) { - if (isScrollbarVertical) - width -= 2; - else - height -= 2; + if (isScrollbarVertical) + width -= 2; + else + height -= 2; - Path p; + Path p; - if (buttonDirection == 0) - p.addTriangle (width * 0.5f, height * 0.2f, - width * 0.1f, height * 0.7f, - width * 0.9f, height * 0.7f); - else if (buttonDirection == 1) - p.addTriangle (width * 0.8f, height * 0.5f, - width * 0.3f, height * 0.1f, - width * 0.3f, height * 0.9f); - else if (buttonDirection == 2) - p.addTriangle (width * 0.5f, height * 0.8f, - width * 0.1f, height * 0.3f, - width * 0.9f, height * 0.3f); - else if (buttonDirection == 3) - p.addTriangle (width * 0.2f, height * 0.5f, - width * 0.7f, height * 0.1f, - width * 0.7f, height * 0.9f); + if (buttonDirection == 0) + p.addTriangle (width * 0.5f, height * 0.2f, + width * 0.1f, height * 0.7f, + width * 0.9f, height * 0.7f); + else if (buttonDirection == 1) + p.addTriangle (width * 0.8f, height * 0.5f, + width * 0.3f, height * 0.1f, + width * 0.3f, height * 0.9f); + else if (buttonDirection == 2) + p.addTriangle (width * 0.5f, height * 0.8f, + width * 0.1f, height * 0.3f, + width * 0.9f, height * 0.3f); + else if (buttonDirection == 3) + p.addTriangle (width * 0.2f, height * 0.5f, + width * 0.7f, height * 0.1f, + width * 0.7f, height * 0.9f); - if (isButtonDown) - g.setColour (Colours::white); - else if (isMouseOverButton) - g.setColour (Colours::white.withAlpha (0.7f)); - else - g.setColour (bar.findColour (ScrollBar::thumbColourId).withAlpha (0.5f)); + if (isButtonDown) + g.setColour (Colours::white); + else if (isMouseOverButton) + g.setColour (Colours::white.withAlpha (0.7f)); + else + g.setColour (bar.findColour (ScrollBar::thumbColourId).withAlpha (0.5f)); - g.fillPath (p); + g.fillPath (p); - g.setColour (Colours::black.withAlpha (0.5f)); - g.strokePath (p, PathStrokeType (0.5f)); + g.setColour (Colours::black.withAlpha (0.5f)); + g.strokePath (p, PathStrokeType (0.5f)); } void OldSchoolLookAndFeel::drawScrollbar (Graphics& g, - ScrollBar& bar, - int x, int y, - int width, int height, - bool isScrollbarVertical, - int thumbStartPosition, - int thumbSize, - bool isMouseOver, - bool isMouseDown) + ScrollBar& bar, + int x, int y, + int width, int height, + bool isScrollbarVertical, + int thumbStartPosition, + int thumbSize, + bool isMouseOver, + bool isMouseDown) { - g.fillAll (bar.findColour (ScrollBar::backgroundColourId)); + g.fillAll (bar.findColour (ScrollBar::backgroundColourId)); - g.setColour (bar.findColour (ScrollBar::thumbColourId) - .withAlpha ((isMouseOver || isMouseDown) ? 0.4f : 0.15f)); + g.setColour (bar.findColour (ScrollBar::thumbColourId) + .withAlpha ((isMouseOver || isMouseDown) ? 0.4f : 0.15f)); - if (thumbSize > 0.0f) - { - Rectangle thumb; + if (thumbSize > 0.0f) + { + Rectangle thumb; - if (isScrollbarVertical) - { - width -= 2; - g.fillRect (x + roundFloatToInt (width * 0.35f), y, - roundFloatToInt (width * 0.3f), height); + if (isScrollbarVertical) + { + width -= 2; + g.fillRect (x + roundToInt (width * 0.35f), y, + roundToInt (width * 0.3f), height); - thumb.setBounds (x + 1, thumbStartPosition, - width - 2, thumbSize); - } - else - { - height -= 2; - g.fillRect (x, y + roundFloatToInt (height * 0.35f), - width, roundFloatToInt (height * 0.3f)); + thumb.setBounds (x + 1, thumbStartPosition, + width - 2, thumbSize); + } + else + { + height -= 2; + g.fillRect (x, y + roundToInt (height * 0.35f), + width, roundToInt (height * 0.3f)); - thumb.setBounds (thumbStartPosition, y + 1, - thumbSize, height - 2); - } + thumb.setBounds (thumbStartPosition, y + 1, + thumbSize, height - 2); + } - g.setColour (bar.findColour (ScrollBar::thumbColourId) - .withAlpha ((isMouseOver || isMouseDown) ? 0.95f : 0.7f)); + g.setColour (bar.findColour (ScrollBar::thumbColourId) + .withAlpha ((isMouseOver || isMouseDown) ? 0.95f : 0.7f)); - g.fillRect (thumb); + g.fillRect (thumb); - g.setColour (Colours::black.withAlpha ((isMouseOver || isMouseDown) ? 0.4f : 0.25f)); - g.drawRect (thumb.getX(), thumb.getY(), thumb.getWidth(), thumb.getHeight()); + g.setColour (Colours::black.withAlpha ((isMouseOver || isMouseDown) ? 0.4f : 0.25f)); + g.drawRect (thumb.getX(), thumb.getY(), thumb.getWidth(), thumb.getHeight()); - if (thumbSize > 16) - { - for (int i = 3; --i >= 0;) - { - const float linePos = thumbStartPosition + thumbSize / 2 + (i - 1) * 4.0f; - g.setColour (Colours::black.withAlpha (0.15f)); + if (thumbSize > 16) + { + for (int i = 3; --i >= 0;) + { + const float linePos = thumbStartPosition + thumbSize / 2 + (i - 1) * 4.0f; + g.setColour (Colours::black.withAlpha (0.15f)); - if (isScrollbarVertical) - { - g.drawLine (x + width * 0.2f, linePos, width * 0.8f, linePos); - g.setColour (Colours::white.withAlpha (0.15f)); - g.drawLine (width * 0.2f, linePos - 1, width * 0.8f, linePos - 1); - } - else - { - g.drawLine (linePos, height * 0.2f, linePos, height * 0.8f); - g.setColour (Colours::white.withAlpha (0.15f)); - g.drawLine (linePos - 1, height * 0.2f, linePos - 1, height * 0.8f); - } - } - } - } + if (isScrollbarVertical) + { + g.drawLine (x + width * 0.2f, linePos, width * 0.8f, linePos); + g.setColour (Colours::white.withAlpha (0.15f)); + g.drawLine (width * 0.2f, linePos - 1, width * 0.8f, linePos - 1); + } + else + { + g.drawLine (linePos, height * 0.2f, linePos, height * 0.8f); + g.setColour (Colours::white.withAlpha (0.15f)); + g.drawLine (linePos - 1, height * 0.2f, linePos - 1, height * 0.8f); + } + } + } + } } ImageEffectFilter* OldSchoolLookAndFeel::getScrollbarEffect() { - return &scrollbarShadow; + return &scrollbarShadow; } void OldSchoolLookAndFeel::drawPopupMenuBackground (Graphics& g, int width, int height) { - g.fillAll (findColour (PopupMenu::backgroundColourId)); + g.fillAll (findColour (PopupMenu::backgroundColourId)); - g.setColour (Colours::black.withAlpha (0.6f)); - g.drawRect (0, 0, width, height); + g.setColour (Colours::black.withAlpha (0.6f)); + g.drawRect (0, 0, width, height); } void OldSchoolLookAndFeel::drawMenuBarBackground (Graphics& g, int /*width*/, int /*height*/, - bool, MenuBarComponent& menuBar) + bool, MenuBarComponent& menuBar) { - g.fillAll (menuBar.findColour (PopupMenu::backgroundColourId)); + g.fillAll (menuBar.findColour (PopupMenu::backgroundColourId)); } void OldSchoolLookAndFeel::drawTextEditorOutline (Graphics& g, int width, int height, TextEditor& textEditor) { - if (textEditor.isEnabled()) - { - g.setColour (textEditor.findColour (TextEditor::outlineColourId)); - g.drawRect (0, 0, width, height); - } + if (textEditor.isEnabled()) + { + g.setColour (textEditor.findColour (TextEditor::outlineColourId)); + g.drawRect (0, 0, width, height); + } } void OldSchoolLookAndFeel::drawComboBox (Graphics& g, int width, int height, - const bool isButtonDown, - int buttonX, int buttonY, - int buttonW, int buttonH, - ComboBox& box) + const bool isButtonDown, + int buttonX, int buttonY, + int buttonW, int buttonH, + ComboBox& box) { - g.fillAll (box.findColour (ComboBox::backgroundColourId)); + g.fillAll (box.findColour (ComboBox::backgroundColourId)); - g.setColour (box.findColour ((isButtonDown) ? ComboBox::buttonColourId - : ComboBox::backgroundColourId)); - g.fillRect (buttonX, buttonY, buttonW, buttonH); + g.setColour (box.findColour ((isButtonDown) ? ComboBox::buttonColourId + : ComboBox::backgroundColourId)); + g.fillRect (buttonX, buttonY, buttonW, buttonH); - g.setColour (box.findColour (ComboBox::outlineColourId)); - g.drawRect (0, 0, width, height); + g.setColour (box.findColour (ComboBox::outlineColourId)); + g.drawRect (0, 0, width, height); - const float arrowX = 0.2f; - const float arrowH = 0.3f; + const float arrowX = 0.2f; + const float arrowH = 0.3f; - if (box.isEnabled()) - { - Path p; - p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.45f - arrowH), - buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.45f, - buttonX + buttonW * arrowX, buttonY + buttonH * 0.45f); + if (box.isEnabled()) + { + Path p; + p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.45f - arrowH), + buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.45f, + buttonX + buttonW * arrowX, buttonY + buttonH * 0.45f); - p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.55f + arrowH), - buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.55f, - buttonX + buttonW * arrowX, buttonY + buttonH * 0.55f); + p.addTriangle (buttonX + buttonW * 0.5f, buttonY + buttonH * (0.55f + arrowH), + buttonX + buttonW * (1.0f - arrowX), buttonY + buttonH * 0.55f, + buttonX + buttonW * arrowX, buttonY + buttonH * 0.55f); - g.setColour (box.findColour ((isButtonDown) ? ComboBox::backgroundColourId - : ComboBox::buttonColourId)); - g.fillPath (p); - } + g.setColour (box.findColour ((isButtonDown) ? ComboBox::backgroundColourId + : ComboBox::buttonColourId)); + g.fillPath (p); + } } const Font OldSchoolLookAndFeel::getComboBoxFont (ComboBox& box) { - Font f (jmin (15.0f, box.getHeight() * 0.85f)); - f.setHorizontalScale (0.9f); - return f; + Font f (jmin (15.0f, box.getHeight() * 0.85f)); + f.setHorizontalScale (0.9f); + return f; } static void drawTriangle (Graphics& g, float x1, float y1, float x2, float y2, float x3, float y3, const Colour& fill, const Colour& outline) throw() { - Path p; - p.addTriangle (x1, y1, x2, y2, x3, y3); - g.setColour (fill); - g.fillPath (p); + Path p; + p.addTriangle (x1, y1, x2, y2, x3, y3); + g.setColour (fill); + g.fillPath (p); - g.setColour (outline); - g.strokePath (p, PathStrokeType (0.3f)); + g.setColour (outline); + g.strokePath (p, PathStrokeType (0.3f)); } void OldSchoolLookAndFeel::drawLinearSlider (Graphics& g, - int x, int y, - int w, int h, - float sliderPos, - float minSliderPos, - float maxSliderPos, - const Slider::SliderStyle style, - Slider& slider) + int x, int y, + int w, int h, + float sliderPos, + float minSliderPos, + float maxSliderPos, + const Slider::SliderStyle style, + Slider& slider) { - g.fillAll (slider.findColour (Slider::backgroundColourId)); + g.fillAll (slider.findColour (Slider::backgroundColourId)); - if (style == Slider::LinearBar) - { - g.setColour (slider.findColour (Slider::thumbColourId)); - g.fillRect (x, y, (int) sliderPos - x, h); + if (style == Slider::LinearBar) + { + g.setColour (slider.findColour (Slider::thumbColourId)); + g.fillRect (x, y, (int) sliderPos - x, h); - g.setColour (slider.findColour (Slider::textBoxTextColourId).withMultipliedAlpha (0.5f)); - g.drawRect (x, y, (int) sliderPos - x, h); - } - else - { - g.setColour (slider.findColour (Slider::trackColourId) - .withMultipliedAlpha (slider.isEnabled() ? 1.0f : 0.3f)); + g.setColour (slider.findColour (Slider::textBoxTextColourId).withMultipliedAlpha (0.5f)); + g.drawRect (x, y, (int) sliderPos - x, h); + } + else + { + g.setColour (slider.findColour (Slider::trackColourId) + .withMultipliedAlpha (slider.isEnabled() ? 1.0f : 0.3f)); - if (slider.isHorizontal()) - { - g.fillRect (x, y + roundFloatToInt (h * 0.6f), - w, roundFloatToInt (h * 0.2f)); - } - else - { - g.fillRect (x + roundFloatToInt (w * 0.5f - jmin (3.0f, w * 0.1f)), y, - jmin (4, roundFloatToInt (w * 0.2f)), h); - } + if (slider.isHorizontal()) + { + g.fillRect (x, y + roundToInt (h * 0.6f), + w, roundToInt (h * 0.2f)); + } + else + { + g.fillRect (x + roundToInt (w * 0.5f - jmin (3.0f, w * 0.1f)), y, + jmin (4, roundToInt (w * 0.2f)), h); + } - float alpha = 0.35f; + float alpha = 0.35f; - if (slider.isEnabled()) - alpha = slider.isMouseOverOrDragging() ? 1.0f : 0.7f; + if (slider.isEnabled()) + alpha = slider.isMouseOverOrDragging() ? 1.0f : 0.7f; - const Colour fill (slider.findColour (Slider::thumbColourId).withAlpha (alpha)); - const Colour outline (Colours::black.withAlpha (slider.isEnabled() ? 0.7f : 0.35f)); + const Colour fill (slider.findColour (Slider::thumbColourId).withAlpha (alpha)); + const Colour outline (Colours::black.withAlpha (slider.isEnabled() ? 0.7f : 0.35f)); - if (style == Slider::TwoValueVertical || style == Slider::ThreeValueVertical) - { - drawTriangle (g, x + w * 0.5f + jmin (4.0f, w * 0.3f), minSliderPos, - x + w * 0.5f - jmin (8.0f, w * 0.4f), minSliderPos - 7.0f, - x + w * 0.5f - jmin (8.0f, w * 0.4f), minSliderPos, - fill, outline); + if (style == Slider::TwoValueVertical || style == Slider::ThreeValueVertical) + { + drawTriangle (g, x + w * 0.5f + jmin (4.0f, w * 0.3f), minSliderPos, + x + w * 0.5f - jmin (8.0f, w * 0.4f), minSliderPos - 7.0f, + x + w * 0.5f - jmin (8.0f, w * 0.4f), minSliderPos, + fill, outline); - drawTriangle (g, x + w * 0.5f + jmin (4.0f, w * 0.3f), maxSliderPos, - x + w * 0.5f - jmin (8.0f, w * 0.4f), maxSliderPos, - x + w * 0.5f - jmin (8.0f, w * 0.4f), maxSliderPos + 7.0f, - fill, outline); - } - else if (style == Slider::TwoValueHorizontal || style == Slider::ThreeValueHorizontal) - { - drawTriangle (g, minSliderPos, y + h * 0.6f - jmin (4.0f, h * 0.3f), - minSliderPos - 7.0f, y + h * 0.9f , - minSliderPos, y + h * 0.9f, - fill, outline); + drawTriangle (g, x + w * 0.5f + jmin (4.0f, w * 0.3f), maxSliderPos, + x + w * 0.5f - jmin (8.0f, w * 0.4f), maxSliderPos, + x + w * 0.5f - jmin (8.0f, w * 0.4f), maxSliderPos + 7.0f, + fill, outline); + } + else if (style == Slider::TwoValueHorizontal || style == Slider::ThreeValueHorizontal) + { + drawTriangle (g, minSliderPos, y + h * 0.6f - jmin (4.0f, h * 0.3f), + minSliderPos - 7.0f, y + h * 0.9f , + minSliderPos, y + h * 0.9f, + fill, outline); - drawTriangle (g, maxSliderPos, y + h * 0.6f - jmin (4.0f, h * 0.3f), - maxSliderPos, y + h * 0.9f, - maxSliderPos + 7.0f, y + h * 0.9f, - fill, outline); - } + drawTriangle (g, maxSliderPos, y + h * 0.6f - jmin (4.0f, h * 0.3f), + maxSliderPos, y + h * 0.9f, + maxSliderPos + 7.0f, y + h * 0.9f, + fill, outline); + } - if (style == Slider::LinearHorizontal || style == Slider::ThreeValueHorizontal) - { - drawTriangle (g, sliderPos, y + h * 0.9f, - sliderPos - 7.0f, y + h * 0.2f, - sliderPos + 7.0f, y + h * 0.2f, - fill, outline); - } - else if (style == Slider::LinearVertical || style == Slider::ThreeValueVertical) - { - drawTriangle (g, x + w * 0.5f - jmin (4.0f, w * 0.3f), sliderPos, - x + w * 0.5f + jmin (8.0f, w * 0.4f), sliderPos - 7.0f, - x + w * 0.5f + jmin (8.0f, w * 0.4f), sliderPos + 7.0f, - fill, outline); - } - } + if (style == Slider::LinearHorizontal || style == Slider::ThreeValueHorizontal) + { + drawTriangle (g, sliderPos, y + h * 0.9f, + sliderPos - 7.0f, y + h * 0.2f, + sliderPos + 7.0f, y + h * 0.2f, + fill, outline); + } + else if (style == Slider::LinearVertical || style == Slider::ThreeValueVertical) + { + drawTriangle (g, x + w * 0.5f - jmin (4.0f, w * 0.3f), sliderPos, + x + w * 0.5f + jmin (8.0f, w * 0.4f), sliderPos - 7.0f, + x + w * 0.5f + jmin (8.0f, w * 0.4f), sliderPos + 7.0f, + fill, outline); + } + } } Button* OldSchoolLookAndFeel::createSliderButton (const bool isIncrement) { - if (isIncrement) - return new ArrowButton ("u", 0.75f, Colours::white.withAlpha (0.8f)); - else - return new ArrowButton ("d", 0.25f, Colours::white.withAlpha (0.8f)); + if (isIncrement) + return new ArrowButton ("u", 0.75f, Colours::white.withAlpha (0.8f)); + else + return new ArrowButton ("d", 0.25f, Colours::white.withAlpha (0.8f)); } ImageEffectFilter* OldSchoolLookAndFeel::getSliderEffect() { - return &scrollbarShadow; + return &scrollbarShadow; } int OldSchoolLookAndFeel::getSliderThumbRadius (Slider&) { - return 8; + return 8; } void OldSchoolLookAndFeel::drawCornerResizer (Graphics& g, - int w, int h, - bool isMouseOver, - bool isMouseDragging) + int w, int h, + bool isMouseOver, + bool isMouseDragging) { - g.setColour ((isMouseOver || isMouseDragging) ? Colours::lightgrey - : Colours::darkgrey); + g.setColour ((isMouseOver || isMouseDragging) ? Colours::lightgrey + : Colours::darkgrey); - const float lineThickness = jmin (w, h) * 0.1f; + const float lineThickness = jmin (w, h) * 0.1f; - for (float i = 0.0f; i < 1.0f; i += 0.3f) - { - g.drawLine (w * i, - h + 1.0f, - w + 1.0f, - h * i, - lineThickness); - } + for (float i = 0.0f; i < 1.0f; i += 0.3f) + { + g.drawLine (w * i, + h + 1.0f, + w + 1.0f, + h * i, + lineThickness); + } } Button* OldSchoolLookAndFeel::createDocumentWindowButton (int buttonType) { - Path shape; + Path shape; - if (buttonType == DocumentWindow::closeButton) - { - shape.addLineSegment (0.0f, 0.0f, 1.0f, 1.0f, 0.35f); - shape.addLineSegment (1.0f, 0.0f, 0.0f, 1.0f, 0.35f); + if (buttonType == DocumentWindow::closeButton) + { + shape.addLineSegment (0.0f, 0.0f, 1.0f, 1.0f, 0.35f); + shape.addLineSegment (1.0f, 0.0f, 0.0f, 1.0f, 0.35f); - ShapeButton* const b = new ShapeButton ("close", - Colour (0x7fff3333), - Colour (0xd7ff3333), - Colour (0xf7ff3333)); + ShapeButton* const b = new ShapeButton ("close", + Colour (0x7fff3333), + Colour (0xd7ff3333), + Colour (0xf7ff3333)); - b->setShape (shape, true, true, true); - return b; - } - else if (buttonType == DocumentWindow::minimiseButton) - { - shape.addLineSegment (0.0f, 0.5f, 1.0f, 0.5f, 0.25f); + b->setShape (shape, true, true, true); + return b; + } + else if (buttonType == DocumentWindow::minimiseButton) + { + shape.addLineSegment (0.0f, 0.5f, 1.0f, 0.5f, 0.25f); - DrawableButton* b = new DrawableButton ("minimise", DrawableButton::ImageFitted); - DrawablePath dp; - dp.setPath (shape); - dp.setFill (Colours::black.withAlpha (0.3f)); - b->setImages (&dp); - return b; - } - else if (buttonType == DocumentWindow::maximiseButton) - { - shape.addLineSegment (0.5f, 0.0f, 0.5f, 1.0f, 0.25f); - shape.addLineSegment (0.0f, 0.5f, 1.0f, 0.5f, 0.25f); + DrawableButton* b = new DrawableButton ("minimise", DrawableButton::ImageFitted); + DrawablePath dp; + dp.setPath (shape); + dp.setFill (Colours::black.withAlpha (0.3f)); + b->setImages (&dp); + return b; + } + else if (buttonType == DocumentWindow::maximiseButton) + { + shape.addLineSegment (0.5f, 0.0f, 0.5f, 1.0f, 0.25f); + shape.addLineSegment (0.0f, 0.5f, 1.0f, 0.5f, 0.25f); - DrawableButton* b = new DrawableButton ("maximise", DrawableButton::ImageFitted); - DrawablePath dp; - dp.setPath (shape); - dp.setFill (Colours::black.withAlpha (0.3f)); - b->setImages (&dp); - return b; - } + DrawableButton* b = new DrawableButton ("maximise", DrawableButton::ImageFitted); + DrawablePath dp; + dp.setPath (shape); + dp.setFill (Colours::black.withAlpha (0.3f)); + b->setImages (&dp); + return b; + } - jassertfalse - return 0; + jassertfalse + return 0; } void OldSchoolLookAndFeel::positionDocumentWindowButtons (DocumentWindow&, - int titleBarX, - int titleBarY, - int titleBarW, - int titleBarH, - Button* minimiseButton, - Button* maximiseButton, - Button* closeButton, - bool positionTitleBarButtonsOnLeft) + int titleBarX, + int titleBarY, + int titleBarW, + int titleBarH, + Button* minimiseButton, + Button* maximiseButton, + Button* closeButton, + bool positionTitleBarButtonsOnLeft) { - titleBarY += titleBarH / 8; - titleBarH -= titleBarH / 4; + titleBarY += titleBarH / 8; + titleBarH -= titleBarH / 4; - const int buttonW = titleBarH; + const int buttonW = titleBarH; - int x = positionTitleBarButtonsOnLeft ? titleBarX + 4 - : titleBarX + titleBarW - buttonW - 4; + int x = positionTitleBarButtonsOnLeft ? titleBarX + 4 + : titleBarX + titleBarW - buttonW - 4; - if (closeButton != 0) - { - closeButton->setBounds (x, titleBarY, buttonW, titleBarH); - x += positionTitleBarButtonsOnLeft ? buttonW + buttonW / 5 - : -(buttonW + buttonW / 5); - } + if (closeButton != 0) + { + closeButton->setBounds (x, titleBarY, buttonW, titleBarH); + x += positionTitleBarButtonsOnLeft ? buttonW + buttonW / 5 + : -(buttonW + buttonW / 5); + } - if (positionTitleBarButtonsOnLeft) - swapVariables (minimiseButton, maximiseButton); + if (positionTitleBarButtonsOnLeft) + swapVariables (minimiseButton, maximiseButton); - if (maximiseButton != 0) - { - maximiseButton->setBounds (x, titleBarY - 2, buttonW, titleBarH); - x += positionTitleBarButtonsOnLeft ? buttonW : -buttonW; - } + if (maximiseButton != 0) + { + maximiseButton->setBounds (x, titleBarY - 2, buttonW, titleBarH); + x += positionTitleBarButtonsOnLeft ? buttonW : -buttonW; + } - if (minimiseButton != 0) - minimiseButton->setBounds (x, titleBarY - 2, buttonW, titleBarH); + if (minimiseButton != 0) + minimiseButton->setBounds (x, titleBarY - 2, buttonW, titleBarH); } END_JUCE_NAMESPACE @@ -67885,411 +67584,411 @@ BEGIN_JUCE_NAMESPACE class DummyMenuComponent : public Component { - DummyMenuComponent (const DummyMenuComponent&); - const DummyMenuComponent& operator= (const DummyMenuComponent&); + DummyMenuComponent (const DummyMenuComponent&); + const DummyMenuComponent& operator= (const DummyMenuComponent&); public: - DummyMenuComponent() {} - ~DummyMenuComponent() {} + DummyMenuComponent() {} + ~DummyMenuComponent() {} - void inputAttemptWhenModal() - { - exitModalState (0); - } + void inputAttemptWhenModal() + { + exitModalState (0); + } }; MenuBarComponent::MenuBarComponent (MenuBarModel* model_) - : model (0), - itemUnderMouse (-1), - currentPopupIndex (-1), - indexToShowAgain (-1), - lastMouseX (0), - lastMouseY (0), - inModalState (false) + : model (0), + itemUnderMouse (-1), + currentPopupIndex (-1), + indexToShowAgain (-1), + lastMouseX (0), + lastMouseY (0), + inModalState (false) { - setRepaintsOnMouseActivity (true); - setWantsKeyboardFocus (false); - setMouseClickGrabsKeyboardFocus (false); + setRepaintsOnMouseActivity (true); + setWantsKeyboardFocus (false); + setMouseClickGrabsKeyboardFocus (false); - setModel (model_); + setModel (model_); } MenuBarComponent::~MenuBarComponent() { - setModel (0); + setModel (0); - Desktop::getInstance().removeGlobalMouseListener (this); - currentPopup = 0; + Desktop::getInstance().removeGlobalMouseListener (this); + currentPopup = 0; } void MenuBarComponent::setModel (MenuBarModel* const newModel) { - if (model != newModel) - { - if (model != 0) - model->removeListener (this); + if (model != newModel) + { + if (model != 0) + model->removeListener (this); - model = newModel; + model = newModel; - if (model != 0) - model->addListener (this); + if (model != 0) + model->addListener (this); - repaint(); - menuBarItemsChanged (0); - } + repaint(); + menuBarItemsChanged (0); + } } void MenuBarComponent::paint (Graphics& g) { - const bool isMouseOverBar = currentPopupIndex >= 0 || itemUnderMouse >= 0 || isMouseOver(); + const bool isMouseOverBar = currentPopupIndex >= 0 || itemUnderMouse >= 0 || isMouseOver(); - getLookAndFeel().drawMenuBarBackground (g, - getWidth(), - getHeight(), - isMouseOverBar, - *this); + getLookAndFeel().drawMenuBarBackground (g, + getWidth(), + getHeight(), + isMouseOverBar, + *this); - if (model != 0) - { - for (int i = 0; i < menuNames.size(); ++i) - { - g.saveState(); - g.setOrigin (xPositions [i], 0); - g.reduceClipRegion (0, 0, xPositions[i + 1] - xPositions[i], getHeight()); + if (model != 0) + { + for (int i = 0; i < menuNames.size(); ++i) + { + g.saveState(); + g.setOrigin (xPositions [i], 0); + g.reduceClipRegion (0, 0, xPositions[i + 1] - xPositions[i], getHeight()); - getLookAndFeel().drawMenuBarItem (g, - xPositions[i + 1] - xPositions[i], - getHeight(), - i, - menuNames[i], - i == itemUnderMouse, - i == currentPopupIndex, - isMouseOverBar, - *this); + getLookAndFeel().drawMenuBarItem (g, + xPositions[i + 1] - xPositions[i], + getHeight(), + i, + menuNames[i], + i == itemUnderMouse, + i == currentPopupIndex, + isMouseOverBar, + *this); - g.restoreState(); - } - } + g.restoreState(); + } + } } void MenuBarComponent::resized() { - xPositions.clear(); - int x = 2; - xPositions.add (x); + xPositions.clear(); + int x = 2; + xPositions.add (x); - for (int i = 0; i < menuNames.size(); ++i) - { - x += getLookAndFeel().getMenuBarItemWidth (*this, i, menuNames[i]); + for (int i = 0; i < menuNames.size(); ++i) + { + x += getLookAndFeel().getMenuBarItemWidth (*this, i, menuNames[i]); - xPositions.add (x); - } + xPositions.add (x); + } } int MenuBarComponent::getItemAt (const int x, const int y) { - for (int i = 0; i < xPositions.size(); ++i) - if (x >= xPositions[i] && x < xPositions[i + 1]) - return reallyContains (x, y, true) ? i : -1; + for (int i = 0; i < xPositions.size(); ++i) + if (x >= xPositions[i] && x < xPositions[i + 1]) + return reallyContains (x, y, true) ? i : -1; - return -1; + return -1; } void MenuBarComponent::repaintMenuItem (int index) { - if (((unsigned int) index) < (unsigned int) xPositions.size()) - { - const int x1 = xPositions [index]; - const int x2 = xPositions [index + 1]; + if (((unsigned int) index) < (unsigned int) xPositions.size()) + { + const int x1 = xPositions [index]; + const int x2 = xPositions [index + 1]; - repaint (x1 - 2, 0, x2 - x1 + 4, getHeight()); - } + repaint (x1 - 2, 0, x2 - x1 + 4, getHeight()); + } } void MenuBarComponent::updateItemUnderMouse (int x, int y) { - const int newItem = getItemAt (x, y); + const int newItem = getItemAt (x, y); - if (itemUnderMouse != newItem) - { - repaintMenuItem (itemUnderMouse); - itemUnderMouse = newItem; - repaintMenuItem (itemUnderMouse); - } + if (itemUnderMouse != newItem) + { + repaintMenuItem (itemUnderMouse); + itemUnderMouse = newItem; + repaintMenuItem (itemUnderMouse); + } } void MenuBarComponent::hideCurrentMenu() { - currentPopup = 0; - repaint(); + currentPopup = 0; + repaint(); } void MenuBarComponent::showMenu (int index) { - if (index != currentPopupIndex) - { - if (inModalState) - { - hideCurrentMenu(); - indexToShowAgain = index; - return; - } + if (index != currentPopupIndex) + { + if (inModalState) + { + hideCurrentMenu(); + indexToShowAgain = index; + return; + } - indexToShowAgain = -1; - currentPopupIndex = -1; - itemUnderMouse = index; - currentPopup = 0; - menuBarItemsChanged (0); + indexToShowAgain = -1; + currentPopupIndex = -1; + itemUnderMouse = index; + currentPopup = 0; + menuBarItemsChanged (0); - Component* const prevFocused = getCurrentlyFocusedComponent(); + Component* const prevFocused = getCurrentlyFocusedComponent(); - ScopedPointer prevCompDeletionChecker; - if (prevFocused != 0) - prevCompDeletionChecker = new ComponentDeletionWatcher (prevFocused); + ScopedPointer prevCompDeletionChecker; + if (prevFocused != 0) + prevCompDeletionChecker = new ComponentDeletionWatcher (prevFocused); - ComponentDeletionWatcher deletionChecker (this); + ComponentDeletionWatcher deletionChecker (this); - enterModalState (false); - inModalState = true; - int result = 0; - ApplicationCommandManager* managerOfChosenCommand = 0; + enterModalState (false); + inModalState = true; + int result = 0; + ApplicationCommandManager* managerOfChosenCommand = 0; - Desktop::getInstance().addGlobalMouseListener (this); + Desktop::getInstance().addGlobalMouseListener (this); - for (;;) - { - const int x = getScreenX() + xPositions [itemUnderMouse]; - const int w = xPositions [itemUnderMouse + 1] - xPositions [itemUnderMouse]; + for (;;) + { + const int x = getScreenX() + xPositions [itemUnderMouse]; + const int w = xPositions [itemUnderMouse + 1] - xPositions [itemUnderMouse]; - currentPopupIndex = itemUnderMouse; - indexToShowAgain = -1; - repaint(); + currentPopupIndex = itemUnderMouse; + indexToShowAgain = -1; + repaint(); - if (((unsigned int) itemUnderMouse) < (unsigned int) menuNames.size()) - { - PopupMenu m (model->getMenuForIndex (itemUnderMouse, - menuNames [itemUnderMouse])); + if (((unsigned int) itemUnderMouse) < (unsigned int) menuNames.size()) + { + PopupMenu m (model->getMenuForIndex (itemUnderMouse, + menuNames [itemUnderMouse])); - if (m.lookAndFeel == 0) - m.setLookAndFeel (&getLookAndFeel()); + if (m.lookAndFeel == 0) + m.setLookAndFeel (&getLookAndFeel()); - currentPopup = m.createMenuComponent (x, getScreenY(), - w, getHeight(), - 0, w, 0, 0, - true, this, - &managerOfChosenCommand, - this); - } + currentPopup = m.createMenuComponent (x, getScreenY(), + w, getHeight(), + 0, w, 0, 0, + true, this, + &managerOfChosenCommand, + this); + } - if (currentPopup == 0) - { - currentPopup = new DummyMenuComponent(); - addAndMakeVisible (currentPopup); - } + if (currentPopup == 0) + { + currentPopup = new DummyMenuComponent(); + addAndMakeVisible (currentPopup); + } - currentPopup->enterModalState (false); - currentPopup->toFront (false); // need to do this after making it modal, or it could - // be stuck behind other comps that are already modal.. - result = currentPopup->runModalLoop(); + currentPopup->enterModalState (false); + currentPopup->toFront (false); // need to do this after making it modal, or it could + // be stuck behind other comps that are already modal.. + result = currentPopup->runModalLoop(); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - const int lastPopupIndex = currentPopupIndex; - currentPopup = 0; - currentPopupIndex = -1; + const int lastPopupIndex = currentPopupIndex; + currentPopup = 0; + currentPopupIndex = -1; - if (result != 0) - { - topLevelIndexClicked = lastPopupIndex; - break; - } - else if (indexToShowAgain >= 0) - { - menuBarItemsChanged (0); - repaint(); - itemUnderMouse = indexToShowAgain; + if (result != 0) + { + topLevelIndexClicked = lastPopupIndex; + break; + } + else if (indexToShowAgain >= 0) + { + menuBarItemsChanged (0); + repaint(); + itemUnderMouse = indexToShowAgain; - if (((unsigned int) itemUnderMouse) >= (unsigned int) menuNames.size()) - break; - } - else - { - break; - } - } + if (((unsigned int) itemUnderMouse) >= (unsigned int) menuNames.size()) + break; + } + else + { + break; + } + } - Desktop::getInstance().removeGlobalMouseListener (this); + Desktop::getInstance().removeGlobalMouseListener (this); - inModalState = false; - exitModalState (0); + inModalState = false; + exitModalState (0); - if (prevCompDeletionChecker != 0 && ! prevCompDeletionChecker->hasBeenDeleted()) - prevFocused->grabKeyboardFocus(); + if (prevCompDeletionChecker != 0 && ! prevCompDeletionChecker->hasBeenDeleted()) + prevFocused->grabKeyboardFocus(); - int mx, my; - getMouseXYRelative (mx, my); - updateItemUnderMouse (mx, my); - repaint(); + int mx, my; + getMouseXYRelative (mx, my); + updateItemUnderMouse (mx, my); + repaint(); - if (result != 0) - { - if (managerOfChosenCommand != 0) - { - ApplicationCommandTarget::InvocationInfo info (result); - info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu; + if (result != 0) + { + if (managerOfChosenCommand != 0) + { + ApplicationCommandTarget::InvocationInfo info (result); + info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu; - managerOfChosenCommand->invoke (info, true); - } + managerOfChosenCommand->invoke (info, true); + } - postCommandMessage (result); - } - } + postCommandMessage (result); + } + } } void MenuBarComponent::handleCommandMessage (int commandId) { - if (model != 0) - model->menuItemSelected (commandId, topLevelIndexClicked); + if (model != 0) + model->menuItemSelected (commandId, topLevelIndexClicked); } void MenuBarComponent::mouseEnter (const MouseEvent& e) { - if (e.eventComponent == this) - updateItemUnderMouse (e.x, e.y); + if (e.eventComponent == this) + updateItemUnderMouse (e.x, e.y); } void MenuBarComponent::mouseExit (const MouseEvent& e) { - if (e.eventComponent == this) - updateItemUnderMouse (e.x, e.y); + if (e.eventComponent == this) + updateItemUnderMouse (e.x, e.y); } void MenuBarComponent::mouseDown (const MouseEvent& e) { - const MouseEvent e2 (e.getEventRelativeTo (this)); + const MouseEvent e2 (e.getEventRelativeTo (this)); - if (currentPopupIndex < 0) - { - updateItemUnderMouse (e2.x, e2.y); + if (currentPopupIndex < 0) + { + updateItemUnderMouse (e2.x, e2.y); - currentPopupIndex = -2; - showMenu (itemUnderMouse); - } + currentPopupIndex = -2; + showMenu (itemUnderMouse); + } } void MenuBarComponent::mouseDrag (const MouseEvent& e) { - const MouseEvent e2 (e.getEventRelativeTo (this)); + const MouseEvent e2 (e.getEventRelativeTo (this)); - const int item = getItemAt (e2.x, e2.y); + const int item = getItemAt (e2.x, e2.y); - if (item >= 0) - showMenu (item); + if (item >= 0) + showMenu (item); } void MenuBarComponent::mouseUp (const MouseEvent& e) { - const MouseEvent e2 (e.getEventRelativeTo (this)); + const MouseEvent e2 (e.getEventRelativeTo (this)); - updateItemUnderMouse (e2.x, e2.y); + updateItemUnderMouse (e2.x, e2.y); - if (itemUnderMouse < 0 && dynamic_cast ((Component*) currentPopup) != 0) - hideCurrentMenu(); + if (itemUnderMouse < 0 && dynamic_cast ((Component*) currentPopup) != 0) + hideCurrentMenu(); } void MenuBarComponent::mouseMove (const MouseEvent& e) { - const MouseEvent e2 (e.getEventRelativeTo (this)); + const MouseEvent e2 (e.getEventRelativeTo (this)); - if (lastMouseX != e2.x || lastMouseY != e2.y) - { - if (currentPopupIndex >= 0) - { - const int item = getItemAt (e2.x, e2.y); + if (lastMouseX != e2.x || lastMouseY != e2.y) + { + if (currentPopupIndex >= 0) + { + const int item = getItemAt (e2.x, e2.y); - if (item >= 0) - showMenu (item); - } - else - { - updateItemUnderMouse (e2.x, e2.y); - } + if (item >= 0) + showMenu (item); + } + else + { + updateItemUnderMouse (e2.x, e2.y); + } - lastMouseX = e2.x; - lastMouseY = e2.y; - } + lastMouseX = e2.x; + lastMouseY = e2.y; + } } bool MenuBarComponent::keyPressed (const KeyPress& key) { - bool used = false; - const int numMenus = menuNames.size(); - const int currentIndex = jlimit (0, menuNames.size() - 1, currentPopupIndex); + bool used = false; + const int numMenus = menuNames.size(); + const int currentIndex = jlimit (0, menuNames.size() - 1, currentPopupIndex); - if (key.isKeyCode (KeyPress::leftKey)) - { - showMenu ((currentIndex + numMenus - 1) % numMenus); - used = true; - } - else if (key.isKeyCode (KeyPress::rightKey)) - { - showMenu ((currentIndex + 1) % numMenus); - used = true; - } + if (key.isKeyCode (KeyPress::leftKey)) + { + showMenu ((currentIndex + numMenus - 1) % numMenus); + used = true; + } + else if (key.isKeyCode (KeyPress::rightKey)) + { + showMenu ((currentIndex + 1) % numMenus); + used = true; + } - return used; + return used; } void MenuBarComponent::inputAttemptWhenModal() { - hideCurrentMenu(); + hideCurrentMenu(); } void MenuBarComponent::menuBarItemsChanged (MenuBarModel* /*menuBarModel*/) { - StringArray newNames; + StringArray newNames; - if (model != 0) - newNames = model->getMenuBarNames(); + if (model != 0) + newNames = model->getMenuBarNames(); - if (newNames != menuNames) - { - menuNames = newNames; - repaint(); - resized(); - } + if (newNames != menuNames) + { + menuNames = newNames; + repaint(); + resized(); + } } void MenuBarComponent::menuCommandInvoked (MenuBarModel* /*menuBarModel*/, - const ApplicationCommandTarget::InvocationInfo& info) + const ApplicationCommandTarget::InvocationInfo& info) { - if (model == 0 - || (info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) != 0) - return; + if (model == 0 + || (info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) != 0) + return; - for (int i = 0; i < menuNames.size(); ++i) - { - const PopupMenu menu (model->getMenuForIndex (i, menuNames [i])); + for (int i = 0; i < menuNames.size(); ++i) + { + const PopupMenu menu (model->getMenuForIndex (i, menuNames [i])); - if (menu.containsCommandItem (info.commandID)) - { - itemUnderMouse = i; - repaintMenuItem (i); - startTimer (200); + if (menu.containsCommandItem (info.commandID)) + { + itemUnderMouse = i; + repaintMenuItem (i); + startTimer (200); - break; - } - } + break; + } + } } void MenuBarComponent::timerCallback() { - stopTimer(); + stopTimer(); - int mx, my; - getMouseXYRelative (mx, my); - updateItemUnderMouse (mx, my); + int mx, my; + getMouseXYRelative (mx, my); + updateItemUnderMouse (mx, my); } END_JUCE_NAMESPACE @@ -68300,74 +67999,74 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MenuBarModel::MenuBarModel() throw() - : manager (0) + : manager (0) { } MenuBarModel::~MenuBarModel() { - setApplicationCommandManagerToWatch (0); + setApplicationCommandManagerToWatch (0); } void MenuBarModel::menuItemsChanged() { - triggerAsyncUpdate(); + triggerAsyncUpdate(); } void MenuBarModel::setApplicationCommandManagerToWatch (ApplicationCommandManager* const newManager) throw() { - if (manager != newManager) - { - if (manager != 0) - manager->removeListener (this); + if (manager != newManager) + { + if (manager != 0) + manager->removeListener (this); - manager = newManager; + manager = newManager; - if (manager != 0) - manager->addListener (this); - } + if (manager != 0) + manager->addListener (this); + } } void MenuBarModel::addListener (MenuBarModelListener* const newListener) throw() { - jassert (newListener != 0); - jassert (! listeners.contains (newListener)); // trying to add a listener to the list twice! + jassert (newListener != 0); + jassert (! listeners.contains (newListener)); // trying to add a listener to the list twice! - if (newListener != 0) - listeners.add (newListener); + if (newListener != 0) + listeners.add (newListener); } void MenuBarModel::removeListener (MenuBarModelListener* const listenerToRemove) throw() { - // Trying to remove a listener that isn't on the list! - // If this assertion happens because this object is a dangling pointer, make sure you've not - // deleted this menu model while it's still being used by something (e.g. by a MenuBarComponent) - jassert (listeners.contains (listenerToRemove)); + // Trying to remove a listener that isn't on the list! + // If this assertion happens because this object is a dangling pointer, make sure you've not + // deleted this menu model while it's still being used by something (e.g. by a MenuBarComponent) + jassert (listeners.contains (listenerToRemove)); - listeners.removeValue (listenerToRemove); + listeners.removeValue (listenerToRemove); } void MenuBarModel::handleAsyncUpdate() { - for (int i = listeners.size(); --i >= 0;) - { - ((MenuBarModelListener*) listeners.getUnchecked (i))->menuBarItemsChanged (this); - i = jmin (i, listeners.size()); - } + for (int i = listeners.size(); --i >= 0;) + { + ((MenuBarModelListener*) listeners.getUnchecked (i))->menuBarItemsChanged (this); + i = jmin (i, listeners.size()); + } } void MenuBarModel::applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info) { - for (int i = listeners.size(); --i >= 0;) - { - ((MenuBarModelListener*) listeners.getUnchecked (i))->menuCommandInvoked (this, info); - i = jmin (i, listeners.size()); - } + for (int i = listeners.size(); --i >= 0;) + { + ((MenuBarModelListener*) listeners.getUnchecked (i))->menuCommandInvoked (this, info); + i = jmin (i, listeners.size()); + } } void MenuBarModel::applicationCommandListChanged() { - menuItemsChanged(); + menuItemsChanged(); } END_JUCE_NAMESPACE @@ -68383,218 +68082,218 @@ class MenuItemInfo { public: - const int itemId; - String text; - const Colour textColour; - const bool active, isSeparator, isTicked, usesColour; - ScopedPointer image; - PopupMenuCustomComponent* const customComp; - ScopedPointer subMenu; - ApplicationCommandManager* const commandManager; + const int itemId; + String text; + const Colour textColour; + const bool active, isSeparator, isTicked, usesColour; + ScopedPointer image; + PopupMenuCustomComponent* const customComp; + ScopedPointer subMenu; + ApplicationCommandManager* const commandManager; - MenuItemInfo() - : itemId (0), - active (true), - isSeparator (true), - isTicked (false), - usesColour (false), - customComp (0), - commandManager (0) - { - } + MenuItemInfo() + : itemId (0), + active (true), + isSeparator (true), + isTicked (false), + usesColour (false), + customComp (0), + commandManager (0) + { + } - MenuItemInfo (const int itemId_, - const String& text_, - const bool active_, - const bool isTicked_, - const Image* im, - const Colour& textColour_, - const bool usesColour_, - PopupMenuCustomComponent* const customComp_, - const PopupMenu* const subMenu_, - ApplicationCommandManager* const commandManager_) - : itemId (itemId_), - text (text_), - textColour (textColour_), - active (active_), - isSeparator (false), - isTicked (isTicked_), - usesColour (usesColour_), - customComp (customComp_), - commandManager (commandManager_) - { - if (subMenu_ != 0) - subMenu = new PopupMenu (*subMenu_); + MenuItemInfo (const int itemId_, + const String& text_, + const bool active_, + const bool isTicked_, + const Image* im, + const Colour& textColour_, + const bool usesColour_, + PopupMenuCustomComponent* const customComp_, + const PopupMenu* const subMenu_, + ApplicationCommandManager* const commandManager_) + : itemId (itemId_), + text (text_), + textColour (textColour_), + active (active_), + isSeparator (false), + isTicked (isTicked_), + usesColour (usesColour_), + customComp (customComp_), + commandManager (commandManager_) + { + if (subMenu_ != 0) + subMenu = new PopupMenu (*subMenu_); - if (customComp != 0) - customComp->refCount_++; + if (customComp != 0) + customComp->refCount_++; - if (im != 0) - image = im->createCopy(); + if (im != 0) + image = im->createCopy(); - if (commandManager_ != 0 && itemId_ != 0) - { - String shortcutKey; + if (commandManager_ != 0 && itemId_ != 0) + { + String shortcutKey; - Array keyPresses (commandManager_->getKeyMappings() - ->getKeyPressesAssignedToCommand (itemId_)); + Array keyPresses (commandManager_->getKeyMappings() + ->getKeyPressesAssignedToCommand (itemId_)); - for (int i = 0; i < keyPresses.size(); ++i) - { - const String key (keyPresses.getReference(i).getTextDescription()); + for (int i = 0; i < keyPresses.size(); ++i) + { + const String key (keyPresses.getReference(i).getTextDescription()); - if (shortcutKey.isNotEmpty()) - shortcutKey << ", "; + if (shortcutKey.isNotEmpty()) + shortcutKey << ", "; - if (key.length() == 1) - shortcutKey << "shortcut: '" << key << '\''; - else - shortcutKey << key; - } + if (key.length() == 1) + shortcutKey << "shortcut: '" << key << '\''; + else + shortcutKey << key; + } - shortcutKey = shortcutKey.trim(); + shortcutKey = shortcutKey.trim(); - if (shortcutKey.isNotEmpty()) - text << "" << shortcutKey; - } - } + if (shortcutKey.isNotEmpty()) + text << "" << shortcutKey; + } + } - MenuItemInfo (const MenuItemInfo& other) - : itemId (other.itemId), - text (other.text), - textColour (other.textColour), - active (other.active), - isSeparator (other.isSeparator), - isTicked (other.isTicked), - usesColour (other.usesColour), - customComp (other.customComp), - commandManager (other.commandManager) - { - if (other.subMenu != 0) - subMenu = new PopupMenu (*(other.subMenu)); + MenuItemInfo (const MenuItemInfo& other) + : itemId (other.itemId), + text (other.text), + textColour (other.textColour), + active (other.active), + isSeparator (other.isSeparator), + isTicked (other.isTicked), + usesColour (other.usesColour), + customComp (other.customComp), + commandManager (other.commandManager) + { + if (other.subMenu != 0) + subMenu = new PopupMenu (*(other.subMenu)); - if (other.image != 0) - image = other.image->createCopy(); + if (other.image != 0) + image = other.image->createCopy(); - if (customComp != 0) - customComp->refCount_++; - } + if (customComp != 0) + customComp->refCount_++; + } - ~MenuItemInfo() - { - if (customComp != 0 && --(customComp->refCount_) == 0) - delete customComp; - } + ~MenuItemInfo() + { + if (customComp != 0 && --(customComp->refCount_) == 0) + delete customComp; + } - bool canBeTriggered() const - { - return active && ! (isSeparator || (subMenu != 0)); - } + bool canBeTriggered() const + { + return active && ! (isSeparator || (subMenu != 0)); + } - bool hasActiveSubMenu() const - { - return active && (subMenu != 0); - } + bool hasActiveSubMenu() const + { + return active && (subMenu != 0); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - const MenuItemInfo& operator= (const MenuItemInfo&); + const MenuItemInfo& operator= (const MenuItemInfo&); }; class MenuItemComponent : public Component { - bool isHighlighted; + bool isHighlighted; public: - MenuItemInfo itemInfo; + MenuItemInfo itemInfo; - MenuItemComponent (const MenuItemInfo& itemInfo_) - : isHighlighted (false), - itemInfo (itemInfo_) - { - if (itemInfo.customComp != 0) - addAndMakeVisible (itemInfo.customComp); - } + MenuItemComponent (const MenuItemInfo& itemInfo_) + : isHighlighted (false), + itemInfo (itemInfo_) + { + if (itemInfo.customComp != 0) + addAndMakeVisible (itemInfo.customComp); + } - ~MenuItemComponent() - { - if (itemInfo.customComp != 0) - removeChildComponent (itemInfo.customComp); - } + ~MenuItemComponent() + { + if (itemInfo.customComp != 0) + removeChildComponent (itemInfo.customComp); + } - void getIdealSize (int& idealWidth, - int& idealHeight, - const int standardItemHeight) - { - if (itemInfo.customComp != 0) - { - itemInfo.customComp->getIdealSize (idealWidth, idealHeight); - } - else - { - getLookAndFeel().getIdealPopupMenuItemSize (itemInfo.text, - itemInfo.isSeparator, - standardItemHeight, - idealWidth, - idealHeight); - } - } + void getIdealSize (int& idealWidth, + int& idealHeight, + const int standardItemHeight) + { + if (itemInfo.customComp != 0) + { + itemInfo.customComp->getIdealSize (idealWidth, idealHeight); + } + else + { + getLookAndFeel().getIdealPopupMenuItemSize (itemInfo.text, + itemInfo.isSeparator, + standardItemHeight, + idealWidth, + idealHeight); + } + } - void paint (Graphics& g) - { - if (itemInfo.customComp == 0) - { - String mainText (itemInfo.text); - String endText; - const int endIndex = mainText.indexOf (T("")); + void paint (Graphics& g) + { + if (itemInfo.customComp == 0) + { + String mainText (itemInfo.text); + String endText; + const int endIndex = mainText.indexOf (T("")); - if (endIndex >= 0) - { - endText = mainText.substring (endIndex + 5).trim(); - mainText = mainText.substring (0, endIndex); - } + if (endIndex >= 0) + { + endText = mainText.substring (endIndex + 5).trim(); + mainText = mainText.substring (0, endIndex); + } - getLookAndFeel() - .drawPopupMenuItem (g, getWidth(), getHeight(), - itemInfo.isSeparator, - itemInfo.active, - isHighlighted, - itemInfo.isTicked, - itemInfo.subMenu != 0, - mainText, endText, - itemInfo.image, - itemInfo.usesColour ? &(itemInfo.textColour) : 0); - } - } + getLookAndFeel() + .drawPopupMenuItem (g, getWidth(), getHeight(), + itemInfo.isSeparator, + itemInfo.active, + isHighlighted, + itemInfo.isTicked, + itemInfo.subMenu != 0, + mainText, endText, + itemInfo.image, + itemInfo.usesColour ? &(itemInfo.textColour) : 0); + } + } - void resized() - { - if (getNumChildComponents() > 0) - getChildComponent(0)->setBounds (2, 0, getWidth() - 4, getHeight()); - } + void resized() + { + if (getNumChildComponents() > 0) + getChildComponent(0)->setBounds (2, 0, getWidth() - 4, getHeight()); + } - void setHighlighted (bool shouldBeHighlighted) - { - shouldBeHighlighted = shouldBeHighlighted && itemInfo.active; + void setHighlighted (bool shouldBeHighlighted) + { + shouldBeHighlighted = shouldBeHighlighted && itemInfo.active; - if (isHighlighted != shouldBeHighlighted) - { - isHighlighted = shouldBeHighlighted; + if (isHighlighted != shouldBeHighlighted) + { + isHighlighted = shouldBeHighlighted; - if (itemInfo.customComp != 0) - { - itemInfo.customComp->isHighlighted = shouldBeHighlighted; - itemInfo.customComp->repaint(); - } + if (itemInfo.customComp != 0) + { + itemInfo.customComp->isHighlighted = shouldBeHighlighted; + itemInfo.customComp->repaint(); + } - repaint(); - } - } + repaint(); + } + } private: - MenuItemComponent (const MenuItemComponent&); - const MenuItemComponent& operator= (const MenuItemComponent&); + MenuItemComponent (const MenuItemComponent&); + const MenuItemComponent& operator= (const MenuItemComponent&); }; static const int scrollZone = 24; @@ -68605,1531 +68304,1529 @@ static const int dismissCommandId = 0x6287345f; static bool wasHiddenBecauseOfAppChange = false; class PopupMenuWindow : public Component, - private Timer + private Timer { public: - PopupMenuWindow() - : Component (T("menu")), - owner (0), - currentChild (0), - activeSubMenu (0), - menuBarComponent (0), - managerOfChosenCommand (0), - componentAttachedTo (0), - lastMouseX (0), - lastMouseY (0), - minimumWidth (0), - maximumNumColumns (7), - standardItemHeight (0), - isOver (false), - hasBeenOver (false), - isDown (false), - needsToScroll (false), - hideOnExit (false), - disableMouseMoves (false), - hasAnyJuceCompHadFocus (false), - numColumns (0), - contentHeight (0), - childYOffset (0), - timeEnteredCurrentChildComp (0), - scrollAcceleration (1.0) - { - menuCreationTime = lastFocused = lastScroll = Time::getMillisecondCounter(); - setWantsKeyboardFocus (true); - setMouseClickGrabsKeyboardFocus (false); - - setOpaque (true); - setAlwaysOnTop (true); - - Desktop::getInstance().addGlobalMouseListener (this); - - activeMenuWindows.add (this); - } - - ~PopupMenuWindow() - { - activeMenuWindows.removeValue (this); - - Desktop::getInstance().removeGlobalMouseListener (this); - - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - delete activeSubMenu; - - deleteAllChildren(); - attachedCompWatcher = 0; - } - - static PopupMenuWindow* create (const PopupMenu& menu, - const bool dismissOnMouseUp, - PopupMenuWindow* const owner_, - const int minX, const int maxX, - const int minY, const int maxY, - const int minimumWidth, - const int maximumNumColumns, - const int standardItemHeight, - const bool alignToRectangle, - const int itemIdThatMustBeVisible, - Component* const menuBarComponent, - ApplicationCommandManager** managerOfChosenCommand, - Component* const componentAttachedTo) - { - if (menu.items.size() > 0) - { - int totalItems = 0; - - ScopedPointer mw (new PopupMenuWindow()); - mw->setLookAndFeel (menu.lookAndFeel); - mw->setWantsKeyboardFocus (false); - mw->minimumWidth = minimumWidth; - mw->maximumNumColumns = maximumNumColumns; - mw->standardItemHeight = standardItemHeight; - mw->dismissOnMouseUp = dismissOnMouseUp; - - for (int i = 0; i < menu.items.size(); ++i) - { - MenuItemInfo* const item = (MenuItemInfo*) menu.items.getUnchecked(i); - - mw->addItem (*item); - ++totalItems; - } - - if (totalItems > 0) - { - mw->owner = owner_; - mw->menuBarComponent = menuBarComponent; - mw->managerOfChosenCommand = managerOfChosenCommand; - mw->componentAttachedTo = componentAttachedTo; - mw->attachedCompWatcher = componentAttachedTo != 0 ? new ComponentDeletionWatcher (componentAttachedTo) : 0; - - mw->calculateWindowPos (minX, maxX, minY, maxY, alignToRectangle); - mw->setTopLeftPosition (mw->windowPos.getX(), - mw->windowPos.getY()); - mw->updateYPositions(); - - if (itemIdThatMustBeVisible != 0) - { - const int y = minY - mw->windowPos.getY(); - mw->ensureItemIsVisible (itemIdThatMustBeVisible, - (((unsigned int) y) < (unsigned int) mw->windowPos.getHeight()) ? y : -1); - } - - mw->resizeToBestWindowPos(); - mw->addToDesktop (ComponentPeer::windowIsTemporary - | mw->getLookAndFeel().getMenuWindowFlags()); - - return mw.release(); - } - } - - return 0; - } - - void paint (Graphics& g) - { - getLookAndFeel().drawPopupMenuBackground (g, getWidth(), getHeight()); - } - - void paintOverChildren (Graphics& g) - { - if (isScrolling()) - { - LookAndFeel& lf = getLookAndFeel(); - - if (isScrollZoneActive (false)) - lf.drawPopupMenuUpDownArrow (g, getWidth(), scrollZone, true); - - if (isScrollZoneActive (true)) - { - g.setOrigin (0, getHeight() - scrollZone); - lf.drawPopupMenuUpDownArrow (g, getWidth(), scrollZone, false); - } - } - } - - bool isScrollZoneActive (bool bottomOne) const - { - return isScrolling() - && (bottomOne - ? childYOffset < contentHeight - windowPos.getHeight() - : childYOffset > 0); - } - - void addItem (const MenuItemInfo& item) - { - MenuItemComponent* const mic = new MenuItemComponent (item); - addAndMakeVisible (mic); - - int itemW = 80; - int itemH = 16; - mic->getIdealSize (itemW, itemH, standardItemHeight); - mic->setSize (itemW, jlimit (2, 600, itemH)); - mic->addMouseListener (this, false); - } - - // hide this and all sub-comps - void hide (const MenuItemInfo* const item) - { - if (isVisible()) - { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - - deleteAndZero (activeSubMenu); - currentChild = 0; - - exitModalState (item != 0 ? item->itemId : 0); - setVisible (false); - - if (item != 0 - && item->commandManager != 0 - && item->itemId != 0) - { - *managerOfChosenCommand = item->commandManager; - } - } - } - - void dismissMenu (const MenuItemInfo* const item) - { - if (owner != 0) - { - owner->dismissMenu (item); - } - else - { - if (item != 0) - { - // need a copy of this on the stack as the one passed in will get deleted during this call - const MenuItemInfo mi (*item); - hide (&mi); - } - else - { - hide (0); - } - } - } - - void mouseMove (const MouseEvent&) - { - timerCallback(); - } - - void mouseDown (const MouseEvent&) - { - timerCallback(); - } - - void mouseDrag (const MouseEvent&) - { - timerCallback(); - } - - void mouseUp (const MouseEvent&) - { - timerCallback(); - } - - void mouseWheelMove (const MouseEvent&, float /*amountX*/, float amountY) - { - alterChildYPos (roundFloatToInt (-10.0f * amountY * scrollZone)); - lastMouseX = -1; - } - - bool keyPressed (const KeyPress& key) - { - if (key.isKeyCode (KeyPress::downKey)) - { - selectNextItem (1); - } - else if (key.isKeyCode (KeyPress::upKey)) - { - selectNextItem (-1); - } - else if (key.isKeyCode (KeyPress::leftKey)) - { - PopupMenuWindow* parentWindow = owner; - - if (parentWindow != 0) - { - MenuItemComponent* currentChildOfParent - = (parentWindow != 0) ? parentWindow->currentChild : 0; - - hide (0); - - if (parentWindow->isValidComponent()) - parentWindow->setCurrentlyHighlightedChild (currentChildOfParent); - - disableTimerUntilMouseMoves(); - } - else if (menuBarComponent != 0) - { - menuBarComponent->keyPressed (key); - } - } - else if (key.isKeyCode (KeyPress::rightKey)) - { - disableTimerUntilMouseMoves(); - - if (showSubMenuFor (currentChild)) - { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - - if (activeSubMenu != 0 && activeSubMenu->isVisible()) - activeSubMenu->selectNextItem (1); - } - else if (menuBarComponent != 0) - { - menuBarComponent->keyPressed (key); - } - } - else if (key.isKeyCode (KeyPress::returnKey)) - { - triggerCurrentlyHighlightedItem(); - } - else if (key.isKeyCode (KeyPress::escapeKey)) - { - dismissMenu (0); - } - else - { - return false; - } - - return true; - } - - void inputAttemptWhenModal() - { - timerCallback(); - - if (! isOverAnyMenu()) - { - if (componentAttachedTo != 0 && ! attachedCompWatcher->hasBeenDeleted()) - { - // we want to dismiss the menu, but if we do it synchronously, then - // the mouse-click will be allowed to pass through. That's good, except - // when the user clicks on the button that orginally popped the menu up, - // as they'll expect the menu to go away, and in fact it'll just - // come back. So only dismiss synchronously if they're not on the original - // comp that we're attached to. - int mx, my; - componentAttachedTo->getMouseXYRelative (mx, my); - - if (componentAttachedTo->reallyContains (mx, my, true)) - { - postCommandMessage (dismissCommandId); // dismiss asynchrounously - return; - } - } - - dismissMenu (0); - } - } - - void handleCommandMessage (int commandId) - { - Component::handleCommandMessage (commandId); - - if (commandId == dismissCommandId) - dismissMenu (0); - } - - void timerCallback() - { - if (! isVisible()) - return; - - if (attachedCompWatcher != 0 && attachedCompWatcher->hasBeenDeleted()) - { - dismissMenu (0); - return; - } - - PopupMenuWindow* currentlyModalWindow = dynamic_cast (Component::getCurrentlyModalComponent()); - - if (currentlyModalWindow != 0 && ! treeContains (currentlyModalWindow)) - return; - - startTimer (timerInterval); // do this in case it was called from a mouse - // move rather than a real timer callback - - int mx, my; - Desktop::getMousePosition (mx, my); - - int x = mx, y = my; - globalPositionToRelative (x, y); - - const uint32 now = Time::getMillisecondCounter(); - - if (now > timeEnteredCurrentChildComp + 100 - && reallyContains (x, y, true) - && currentChild->isValidComponent() - && (! disableMouseMoves) - && ! (activeSubMenu != 0 && activeSubMenu->isVisible())) - { - showSubMenuFor (currentChild); - } - - if (mx != lastMouseX || my != lastMouseY || now > lastMouseMoveTime + 350) - { - highlightItemUnderMouse (mx, my, x, y); - } - - bool overScrollArea = false; - - if (isScrolling() - && (isOver || (isDown && ((unsigned int) x) < (unsigned int) getWidth())) - && ((isScrollZoneActive (false) && y < scrollZone) - || (isScrollZoneActive (true) && y > getHeight() - scrollZone))) - { - if (now > lastScroll + 20) - { - scrollAcceleration = jmin (4.0, scrollAcceleration * 1.04); - int amount = 0; - - for (int i = 0; i < getNumChildComponents() && amount == 0; ++i) - amount = ((int) scrollAcceleration) * getChildComponent (i)->getHeight(); - - alterChildYPos (y < scrollZone ? -amount : amount); - - lastScroll = now; - } - - overScrollArea = true; - lastMouseX = -1; // trigger a mouse-move - } - else - { - scrollAcceleration = 1.0; - } - - const bool wasDown = isDown; - bool isOverAny = isOverAnyMenu(); - - if (hideOnExit && hasBeenOver && (! isOverAny) && activeSubMenu != 0) - { - activeSubMenu->updateMouseOverStatus (mx, my); - isOverAny = isOverAnyMenu(); - } - - if (hideOnExit && hasBeenOver && ! isOverAny) - { - hide (0); - } - else - { - isDown = hasBeenOver - && (ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown() - || ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()); - - bool anyFocused = Process::isForegroundProcess(); - - if (anyFocused && Component::getCurrentlyFocusedComponent() == 0) - { - // because no component at all may have focus, our test here will - // only be triggered when something has focus and then loses it. - anyFocused = ! hasAnyJuceCompHadFocus; - - for (int i = ComponentPeer::getNumPeers(); --i >= 0;) - { - if (ComponentPeer::getPeer (i)->isFocused()) - { - anyFocused = true; - hasAnyJuceCompHadFocus = true; - break; - } - } - } - - if (! anyFocused) - { - if (now > lastFocused + 10) - { - wasHiddenBecauseOfAppChange = true; - dismissMenu (0); - - return; // may have been deleted by the previous call.. - } - } - else if (wasDown && now > menuCreationTime + 250 - && ! (isDown || overScrollArea)) - { - isOver = reallyContains (x, y, true); - - if (isOver) - { - triggerCurrentlyHighlightedItem(); - } - else if ((hasBeenOver || ! dismissOnMouseUp) && ! isOverAny) - { - dismissMenu (0); - } - - return; // may have been deleted by the previous calls.. - } - else - { - lastFocused = now; - } - } - } - - juce_UseDebuggingNewOperator + PopupMenuWindow() + : Component (T("menu")), + owner (0), + currentChild (0), + activeSubMenu (0), + menuBarComponent (0), + managerOfChosenCommand (0), + componentAttachedTo (0), + lastMouseX (0), + lastMouseY (0), + minimumWidth (0), + maximumNumColumns (7), + standardItemHeight (0), + isOver (false), + hasBeenOver (false), + isDown (false), + needsToScroll (false), + hideOnExit (false), + disableMouseMoves (false), + hasAnyJuceCompHadFocus (false), + numColumns (0), + contentHeight (0), + childYOffset (0), + timeEnteredCurrentChildComp (0), + scrollAcceleration (1.0) + { + menuCreationTime = lastFocused = lastScroll = Time::getMillisecondCounter(); + setWantsKeyboardFocus (true); + setMouseClickGrabsKeyboardFocus (false); + + setOpaque (true); + setAlwaysOnTop (true); + + Desktop::getInstance().addGlobalMouseListener (this); + + activeMenuWindows.add (this); + } + + ~PopupMenuWindow() + { + activeMenuWindows.removeValue (this); + + Desktop::getInstance().removeGlobalMouseListener (this); + + jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); + delete activeSubMenu; + + deleteAllChildren(); + attachedCompWatcher = 0; + } + + static PopupMenuWindow* create (const PopupMenu& menu, + const bool dismissOnMouseUp, + PopupMenuWindow* const owner_, + const int minX, const int maxX, + const int minY, const int maxY, + const int minimumWidth, + const int maximumNumColumns, + const int standardItemHeight, + const bool alignToRectangle, + const int itemIdThatMustBeVisible, + Component* const menuBarComponent, + ApplicationCommandManager** managerOfChosenCommand, + Component* const componentAttachedTo) + { + if (menu.items.size() > 0) + { + int totalItems = 0; + + ScopedPointer mw (new PopupMenuWindow()); + mw->setLookAndFeel (menu.lookAndFeel); + mw->setWantsKeyboardFocus (false); + mw->minimumWidth = minimumWidth; + mw->maximumNumColumns = maximumNumColumns; + mw->standardItemHeight = standardItemHeight; + mw->dismissOnMouseUp = dismissOnMouseUp; + + for (int i = 0; i < menu.items.size(); ++i) + { + MenuItemInfo* const item = (MenuItemInfo*) menu.items.getUnchecked(i); + + mw->addItem (*item); + ++totalItems; + } + + if (totalItems > 0) + { + mw->owner = owner_; + mw->menuBarComponent = menuBarComponent; + mw->managerOfChosenCommand = managerOfChosenCommand; + mw->componentAttachedTo = componentAttachedTo; + mw->attachedCompWatcher = componentAttachedTo != 0 ? new ComponentDeletionWatcher (componentAttachedTo) : 0; + + mw->calculateWindowPos (minX, maxX, minY, maxY, alignToRectangle); + mw->setTopLeftPosition (mw->windowPos.getX(), + mw->windowPos.getY()); + mw->updateYPositions(); + + if (itemIdThatMustBeVisible != 0) + { + const int y = minY - mw->windowPos.getY(); + mw->ensureItemIsVisible (itemIdThatMustBeVisible, + (((unsigned int) y) < (unsigned int) mw->windowPos.getHeight()) ? y : -1); + } + + mw->resizeToBestWindowPos(); + mw->addToDesktop (ComponentPeer::windowIsTemporary + | mw->getLookAndFeel().getMenuWindowFlags()); + + return mw.release(); + } + } + + return 0; + } + + void paint (Graphics& g) + { + getLookAndFeel().drawPopupMenuBackground (g, getWidth(), getHeight()); + } + + void paintOverChildren (Graphics& g) + { + if (isScrolling()) + { + LookAndFeel& lf = getLookAndFeel(); + + if (isScrollZoneActive (false)) + lf.drawPopupMenuUpDownArrow (g, getWidth(), scrollZone, true); + + if (isScrollZoneActive (true)) + { + g.setOrigin (0, getHeight() - scrollZone); + lf.drawPopupMenuUpDownArrow (g, getWidth(), scrollZone, false); + } + } + } + + bool isScrollZoneActive (bool bottomOne) const + { + return isScrolling() + && (bottomOne + ? childYOffset < contentHeight - windowPos.getHeight() + : childYOffset > 0); + } + + void addItem (const MenuItemInfo& item) + { + MenuItemComponent* const mic = new MenuItemComponent (item); + addAndMakeVisible (mic); + + int itemW = 80; + int itemH = 16; + mic->getIdealSize (itemW, itemH, standardItemHeight); + mic->setSize (itemW, jlimit (2, 600, itemH)); + mic->addMouseListener (this, false); + } + + // hide this and all sub-comps + void hide (const MenuItemInfo* const item) + { + if (isVisible()) + { + jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); + + deleteAndZero (activeSubMenu); + currentChild = 0; + + exitModalState (item != 0 ? item->itemId : 0); + setVisible (false); + + if (item != 0 + && item->commandManager != 0 + && item->itemId != 0) + { + *managerOfChosenCommand = item->commandManager; + } + } + } + + void dismissMenu (const MenuItemInfo* const item) + { + if (owner != 0) + { + owner->dismissMenu (item); + } + else + { + if (item != 0) + { + // need a copy of this on the stack as the one passed in will get deleted during this call + const MenuItemInfo mi (*item); + hide (&mi); + } + else + { + hide (0); + } + } + } + + void mouseMove (const MouseEvent&) + { + timerCallback(); + } + + void mouseDown (const MouseEvent&) + { + timerCallback(); + } + + void mouseDrag (const MouseEvent&) + { + timerCallback(); + } + + void mouseUp (const MouseEvent&) + { + timerCallback(); + } + + void mouseWheelMove (const MouseEvent&, float /*amountX*/, float amountY) + { + alterChildYPos (roundToInt (-10.0f * amountY * scrollZone)); + lastMouseX = -1; + } + + bool keyPressed (const KeyPress& key) + { + if (key.isKeyCode (KeyPress::downKey)) + { + selectNextItem (1); + } + else if (key.isKeyCode (KeyPress::upKey)) + { + selectNextItem (-1); + } + else if (key.isKeyCode (KeyPress::leftKey)) + { + PopupMenuWindow* parentWindow = owner; + + if (parentWindow != 0) + { + MenuItemComponent* currentChildOfParent + = (parentWindow != 0) ? parentWindow->currentChild : 0; + + hide (0); + + if (parentWindow->isValidComponent()) + parentWindow->setCurrentlyHighlightedChild (currentChildOfParent); + + disableTimerUntilMouseMoves(); + } + else if (menuBarComponent != 0) + { + menuBarComponent->keyPressed (key); + } + } + else if (key.isKeyCode (KeyPress::rightKey)) + { + disableTimerUntilMouseMoves(); + + if (showSubMenuFor (currentChild)) + { + jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); + + if (activeSubMenu != 0 && activeSubMenu->isVisible()) + activeSubMenu->selectNextItem (1); + } + else if (menuBarComponent != 0) + { + menuBarComponent->keyPressed (key); + } + } + else if (key.isKeyCode (KeyPress::returnKey)) + { + triggerCurrentlyHighlightedItem(); + } + else if (key.isKeyCode (KeyPress::escapeKey)) + { + dismissMenu (0); + } + else + { + return false; + } + + return true; + } + + void inputAttemptWhenModal() + { + timerCallback(); + + if (! isOverAnyMenu()) + { + if (componentAttachedTo != 0 && ! attachedCompWatcher->hasBeenDeleted()) + { + // we want to dismiss the menu, but if we do it synchronously, then + // the mouse-click will be allowed to pass through. That's good, except + // when the user clicks on the button that orginally popped the menu up, + // as they'll expect the menu to go away, and in fact it'll just + // come back. So only dismiss synchronously if they're not on the original + // comp that we're attached to. + int mx, my; + componentAttachedTo->getMouseXYRelative (mx, my); + + if (componentAttachedTo->reallyContains (mx, my, true)) + { + postCommandMessage (dismissCommandId); // dismiss asynchrounously + return; + } + } + + dismissMenu (0); + } + } + + void handleCommandMessage (int commandId) + { + Component::handleCommandMessage (commandId); + + if (commandId == dismissCommandId) + dismissMenu (0); + } + + void timerCallback() + { + if (! isVisible()) + return; + + if (attachedCompWatcher != 0 && attachedCompWatcher->hasBeenDeleted()) + { + dismissMenu (0); + return; + } + + PopupMenuWindow* currentlyModalWindow = dynamic_cast (Component::getCurrentlyModalComponent()); + + if (currentlyModalWindow != 0 && ! treeContains (currentlyModalWindow)) + return; + + startTimer (timerInterval); // do this in case it was called from a mouse + // move rather than a real timer callback + + int mx, my; + Desktop::getMousePosition (mx, my); + + int x = mx, y = my; + globalPositionToRelative (x, y); + + const uint32 now = Time::getMillisecondCounter(); + + if (now > timeEnteredCurrentChildComp + 100 + && reallyContains (x, y, true) + && currentChild->isValidComponent() + && (! disableMouseMoves) + && ! (activeSubMenu != 0 && activeSubMenu->isVisible())) + { + showSubMenuFor (currentChild); + } + + if (mx != lastMouseX || my != lastMouseY || now > lastMouseMoveTime + 350) + { + highlightItemUnderMouse (mx, my, x, y); + } + + bool overScrollArea = false; + + if (isScrolling() + && (isOver || (isDown && ((unsigned int) x) < (unsigned int) getWidth())) + && ((isScrollZoneActive (false) && y < scrollZone) + || (isScrollZoneActive (true) && y > getHeight() - scrollZone))) + { + if (now > lastScroll + 20) + { + scrollAcceleration = jmin (4.0, scrollAcceleration * 1.04); + int amount = 0; + + for (int i = 0; i < getNumChildComponents() && amount == 0; ++i) + amount = ((int) scrollAcceleration) * getChildComponent (i)->getHeight(); + + alterChildYPos (y < scrollZone ? -amount : amount); + + lastScroll = now; + } + + overScrollArea = true; + lastMouseX = -1; // trigger a mouse-move + } + else + { + scrollAcceleration = 1.0; + } + + const bool wasDown = isDown; + bool isOverAny = isOverAnyMenu(); + + if (hideOnExit && hasBeenOver && (! isOverAny) && activeSubMenu != 0) + { + activeSubMenu->updateMouseOverStatus (mx, my); + isOverAny = isOverAnyMenu(); + } + + if (hideOnExit && hasBeenOver && ! isOverAny) + { + hide (0); + } + else + { + isDown = hasBeenOver + && (ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown() + || ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()); + + bool anyFocused = Process::isForegroundProcess(); + + if (anyFocused && Component::getCurrentlyFocusedComponent() == 0) + { + // because no component at all may have focus, our test here will + // only be triggered when something has focus and then loses it. + anyFocused = ! hasAnyJuceCompHadFocus; + + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) + { + if (ComponentPeer::getPeer (i)->isFocused()) + { + anyFocused = true; + hasAnyJuceCompHadFocus = true; + break; + } + } + } + + if (! anyFocused) + { + if (now > lastFocused + 10) + { + wasHiddenBecauseOfAppChange = true; + dismissMenu (0); + + return; // may have been deleted by the previous call.. + } + } + else if (wasDown && now > menuCreationTime + 250 + && ! (isDown || overScrollArea)) + { + isOver = reallyContains (x, y, true); + + if (isOver) + { + triggerCurrentlyHighlightedItem(); + } + else if ((hasBeenOver || ! dismissOnMouseUp) && ! isOverAny) + { + dismissMenu (0); + } + + return; // may have been deleted by the previous calls.. + } + else + { + lastFocused = now; + } + } + } + + juce_UseDebuggingNewOperator private: - PopupMenuWindow* owner; - MenuItemComponent* currentChild; - PopupMenuWindow* activeSubMenu; - Component* menuBarComponent; - ApplicationCommandManager** managerOfChosenCommand; - Component* componentAttachedTo; - ScopedPointer attachedCompWatcher; - Rectangle windowPos; - int lastMouseX, lastMouseY; - int minimumWidth, maximumNumColumns, standardItemHeight; - bool isOver, hasBeenOver, isDown, needsToScroll; - bool dismissOnMouseUp, hideOnExit, disableMouseMoves, hasAnyJuceCompHadFocus; - int numColumns, contentHeight, childYOffset; - Array columnWidths; - uint32 menuCreationTime, lastFocused, lastScroll, lastMouseMoveTime, timeEnteredCurrentChildComp; - double scrollAcceleration; + PopupMenuWindow* owner; + MenuItemComponent* currentChild; + PopupMenuWindow* activeSubMenu; + Component* menuBarComponent; + ApplicationCommandManager** managerOfChosenCommand; + Component* componentAttachedTo; + ScopedPointer attachedCompWatcher; + Rectangle windowPos; + int lastMouseX, lastMouseY; + int minimumWidth, maximumNumColumns, standardItemHeight; + bool isOver, hasBeenOver, isDown, needsToScroll; + bool dismissOnMouseUp, hideOnExit, disableMouseMoves, hasAnyJuceCompHadFocus; + int numColumns, contentHeight, childYOffset; + Array columnWidths; + uint32 menuCreationTime, lastFocused, lastScroll, lastMouseMoveTime, timeEnteredCurrentChildComp; + double scrollAcceleration; - bool overlaps (const Rectangle& r) const - { - return r.intersects (getBounds()) - || (owner != 0 && owner->overlaps (r)); - } + bool overlaps (const Rectangle& r) const + { + return r.intersects (getBounds()) + || (owner != 0 && owner->overlaps (r)); + } - bool isOverAnyMenu() const - { - return (owner != 0) ? owner->isOverAnyMenu() - : isOverChildren(); - } + bool isOverAnyMenu() const + { + return (owner != 0) ? owner->isOverAnyMenu() + : isOverChildren(); + } - bool isOverChildren() const - { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); + bool isOverChildren() const + { + jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - return isVisible() - && (isOver || (activeSubMenu != 0 && activeSubMenu->isOverChildren())); - } + return isVisible() + && (isOver || (activeSubMenu != 0 && activeSubMenu->isOverChildren())); + } - void updateMouseOverStatus (const int mx, const int my) - { - int rx = mx, ry = my; - globalPositionToRelative (rx, ry); - isOver = reallyContains (rx, ry, true); + void updateMouseOverStatus (const int mx, const int my) + { + int rx = mx, ry = my; + globalPositionToRelative (rx, ry); + isOver = reallyContains (rx, ry, true); - if (activeSubMenu != 0) - activeSubMenu->updateMouseOverStatus (mx, my); - } + if (activeSubMenu != 0) + activeSubMenu->updateMouseOverStatus (mx, my); + } - bool treeContains (const PopupMenuWindow* const window) const - { - const PopupMenuWindow* mw = this; + bool treeContains (const PopupMenuWindow* const window) const + { + const PopupMenuWindow* mw = this; - while (mw->owner != 0) - mw = mw->owner; + while (mw->owner != 0) + mw = mw->owner; - while (mw != 0) - { - if (mw == window) - return true; + while (mw != 0) + { + if (mw == window) + return true; - mw = mw->activeSubMenu; - } + mw = mw->activeSubMenu; + } - return false; - } + return false; + } - void calculateWindowPos (const int minX, const int maxX, - const int minY, const int maxY, - const bool alignToRectangle) - { - const Rectangle mon (Desktop::getInstance() - .getMonitorAreaContaining ((minX + maxX) / 2, - (minY + maxY) / 2, + void calculateWindowPos (const int minX, const int maxX, + const int minY, const int maxY, + const bool alignToRectangle) + { + const Rectangle mon (Desktop::getInstance() + .getMonitorAreaContaining ((minX + maxX) / 2, + (minY + maxY) / 2, #if JUCE_MAC - true)); + true)); #else - false)); // on windows, don't stop the menu overlapping the taskbar + false)); // on windows, don't stop the menu overlapping the taskbar #endif - int x, y, widthToUse, heightToUse; - layoutMenuItems (mon.getWidth() - 24, widthToUse, heightToUse); - - if (alignToRectangle) - { - x = minX; - - const int spaceUnder = mon.getHeight() - (maxY - mon.getY()); - const int spaceOver = minY - mon.getY(); - - if (heightToUse < spaceUnder - 30 || spaceUnder >= spaceOver) - y = maxY; - else - y = minY - heightToUse; - } - else - { - bool tendTowardsRight = (minX + maxX) / 2 < mon.getCentreX(); - - if (owner != 0) - { - if (owner->owner != 0) - { - const bool ownerGoingRight = (owner->getX() + owner->getWidth() / 2 - > owner->owner->getX() + owner->owner->getWidth() / 2); - - if (ownerGoingRight && maxX + widthToUse < mon.getRight() - 4) - tendTowardsRight = true; - else if ((! ownerGoingRight) && minX > widthToUse + 4) - tendTowardsRight = false; - } - else if (maxX + widthToUse < mon.getRight() - 32) - { - tendTowardsRight = true; - } - } - - const int biggestSpace = jmax (mon.getRight() - maxX, - minX - mon.getX()) - 32; - - if (biggestSpace < widthToUse) - { - layoutMenuItems (biggestSpace + (maxX - minX) / 3, widthToUse, heightToUse); - - if (numColumns > 1) - layoutMenuItems (biggestSpace - 4, widthToUse, heightToUse); - - tendTowardsRight = (mon.getRight() - maxX) >= (minX - mon.getX()); - } - - if (tendTowardsRight) - x = jmin (mon.getRight() - widthToUse - 4, maxX); - else - x = jmax (mon.getX() + 4, minX - widthToUse); - - y = minY; - if ((minY + maxY) / 2 > mon.getCentreY()) - y = jmax (mon.getY(), maxY - heightToUse); - } - - x = jmax (mon.getX() + 1, jmin (mon.getRight() - (widthToUse + 6), x)); - y = jmax (mon.getY() + 1, jmin (mon.getBottom() - (heightToUse + 6), y)); - - windowPos.setBounds (x, y, widthToUse, heightToUse); - - // sets this flag if it's big enough to obscure any of its parent menus - hideOnExit = (owner != 0) - && owner->windowPos.intersects (windowPos.expanded (-4, -4)); - } - - void layoutMenuItems (const int maxMenuW, int& width, int& height) - { - numColumns = 0; - contentHeight = 0; - const int maxMenuH = getParentHeight() - 24; - int totalW; - - do - { - ++numColumns; - totalW = workOutBestSize (maxMenuW); - - if (totalW > maxMenuW) - { - numColumns = jmax (1, numColumns - 1); - totalW = workOutBestSize (maxMenuW); // to update col widths - break; - } - else if (totalW > maxMenuW / 2 || contentHeight < maxMenuH) - { - break; - } - - } while (numColumns < maximumNumColumns); - - const int actualH = jmin (contentHeight, maxMenuH); - - needsToScroll = contentHeight > actualH; - - width = updateYPositions(); - height = actualH + borderSize * 2; - } - - int workOutBestSize (const int maxMenuW) - { - int totalW = 0; - contentHeight = 0; - int childNum = 0; - - for (int col = 0; col < numColumns; ++col) - { - int i, colW = 50, colH = 0; - - const int numChildren = jmin (getNumChildComponents() - childNum, - (getNumChildComponents() + numColumns - 1) / numColumns); - - for (i = numChildren; --i >= 0;) - { - colW = jmax (colW, getChildComponent (childNum + i)->getWidth()); - colH += getChildComponent (childNum + i)->getHeight(); - } - - colW = jmin (maxMenuW / jmax (1, numColumns - 2), colW + borderSize * 2); - - columnWidths.set (col, colW); - totalW += colW; - contentHeight = jmax (contentHeight, colH); - - childNum += numChildren; - } - - if (totalW < minimumWidth) - { - totalW = minimumWidth; - - for (int col = 0; col < numColumns; ++col) - columnWidths.set (0, totalW / numColumns); - } - - return totalW; - } - - void ensureItemIsVisible (const int itemId, int wantedY) - { - jassert (itemId != 0) - - for (int i = getNumChildComponents(); --i >= 0;) - { - MenuItemComponent* const m = (MenuItemComponent*) getChildComponent (i); - - if (m != 0 - && m->itemInfo.itemId == itemId - && windowPos.getHeight() > scrollZone * 4) - { - const int currentY = m->getY(); - - if (wantedY > 0 || currentY < 0 || m->getBottom() > windowPos.getHeight()) - { - if (wantedY < 0) - wantedY = jlimit (scrollZone, - jmax (scrollZone, windowPos.getHeight() - (scrollZone + m->getHeight())), - currentY); - - const Rectangle mon (Desktop::getInstance() - .getMonitorAreaContaining (windowPos.getX(), - windowPos.getY(), - true)); - - int deltaY = wantedY - currentY; - - const int newY = jlimit (mon.getY(), - mon.getBottom() - windowPos.getHeight(), - windowPos.getY() + deltaY); - - deltaY -= newY - windowPos.getY(); - - childYOffset -= deltaY; - windowPos.setPosition (windowPos.getX(), newY); - - updateYPositions(); - } - - break; - } - } - } - - void resizeToBestWindowPos() - { - Rectangle r (windowPos); - - if (childYOffset < 0) - { - r.setBounds (r.getX(), r.getY() - childYOffset, - r.getWidth(), r.getHeight() + childYOffset); - } - else if (childYOffset > 0) - { - const int spaceAtBottom = r.getHeight() - (contentHeight - childYOffset); - - if (spaceAtBottom > 0) - r.setSize (r.getWidth(), r.getHeight() - spaceAtBottom); - } - - setBounds (r); - updateYPositions(); - } - - void alterChildYPos (const int delta) - { - if (isScrolling()) - { - childYOffset += delta; - - if (delta < 0) - { - childYOffset = jmax (childYOffset, 0); - } - else if (delta > 0) - { - childYOffset = jmin (childYOffset, - contentHeight - windowPos.getHeight() + borderSize); - } - - updateYPositions(); - } - else - { - childYOffset = 0; - } - - resizeToBestWindowPos(); - repaint(); - } - - int updateYPositions() - { - int x = 0; - int childNum = 0; - - for (int col = 0; col < numColumns; ++col) - { - const int numChildren = jmin (getNumChildComponents() - childNum, - (getNumChildComponents() + numColumns - 1) / numColumns); - - const int colW = columnWidths [col]; - - int y = borderSize - (childYOffset + (getY() - windowPos.getY())); - - for (int i = 0; i < numChildren; ++i) - { - Component* const c = getChildComponent (childNum + i); - c->setBounds (x, y, colW, c->getHeight()); - y += c->getHeight(); - } - - x += colW; - childNum += numChildren; - } - - return x; - } - - bool isScrolling() const - { - return childYOffset != 0 || needsToScroll; - } - - void setCurrentlyHighlightedChild (MenuItemComponent* const child) - { - if (currentChild->isValidComponent()) - currentChild->setHighlighted (false); - - currentChild = child; - - if (currentChild != 0) - { - currentChild->setHighlighted (true); - timeEnteredCurrentChildComp = Time::getApproximateMillisecondCounter(); - } - } - - bool showSubMenuFor (MenuItemComponent* const childComp) - { - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); - deleteAndZero (activeSubMenu); - - if (childComp->isValidComponent() && childComp->itemInfo.hasActiveSubMenu()) - { - int left = 0, top = 0; - childComp->relativePositionToGlobal (left, top); - int right = childComp->getWidth(), bottom = childComp->getHeight(); - childComp->relativePositionToGlobal (right, bottom); - - activeSubMenu = PopupMenuWindow::create (*(childComp->itemInfo.subMenu), - dismissOnMouseUp, - this, - left, right, top, bottom, - 0, maximumNumColumns, - standardItemHeight, - false, 0, menuBarComponent, - managerOfChosenCommand, - componentAttachedTo); - - if (activeSubMenu != 0) - { - activeSubMenu->setVisible (true); - activeSubMenu->enterModalState (false); - activeSubMenu->toFront (false); - return true; - } - } - - return false; - } - - void highlightItemUnderMouse (const int mx, const int my, const int x, const int y) - { - isOver = reallyContains (x, y, true); - - if (isOver) - hasBeenOver = true; - - if (abs (lastMouseX - mx) > 2 || abs (lastMouseY - my) > 2) - { - lastMouseMoveTime = Time::getApproximateMillisecondCounter(); - - if (disableMouseMoves && isOver) - disableMouseMoves = false; - } - - if (disableMouseMoves) - return; - - bool isMovingTowardsMenu = false; - - jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()) - - if (isOver && (activeSubMenu != 0) && (mx != lastMouseX || my != lastMouseY)) - { - // try to intelligently guess whether the user is moving the mouse towards a currently-open - // submenu. To do this, look at whether the mouse stays inside a triangular region that - // extends from the last mouse pos to the submenu's rectangle.. - - float subX = (float) activeSubMenu->getScreenX(); - - if (activeSubMenu->getX() > getX()) - { - lastMouseX -= 2; // to enlarge the triangle a bit, in case the mouse only moves a couple of pixels - } - else - { - lastMouseX += 2; - subX += activeSubMenu->getWidth(); - } - - Path areaTowardsSubMenu; - areaTowardsSubMenu.addTriangle ((float) lastMouseX, - (float) lastMouseY, - subX, - (float) activeSubMenu->getScreenY(), - subX, - (float) (activeSubMenu->getScreenY() + activeSubMenu->getHeight())); - - isMovingTowardsMenu = areaTowardsSubMenu.contains ((float) mx, (float) my); - } - - lastMouseX = mx; - lastMouseY = my; - - if (! isMovingTowardsMenu) - { - Component* c = getComponentAt (x, y); - if (c == this) - c = 0; - - MenuItemComponent* mic = dynamic_cast (c); - - if (mic == 0 && c != 0) - mic = c->findParentComponentOfClass ((MenuItemComponent*) 0); - - if (mic != currentChild - && (isOver || (activeSubMenu == 0) || ! activeSubMenu->isVisible())) - { - if (isOver && (c != 0) && (activeSubMenu != 0)) - { - activeSubMenu->hide (0); - } - - if (! isOver) - mic = 0; - - setCurrentlyHighlightedChild (mic); - } - } - } - - void triggerCurrentlyHighlightedItem() - { - if (currentChild->isValidComponent() - && currentChild->itemInfo.canBeTriggered() - && (currentChild->itemInfo.customComp == 0 - || currentChild->itemInfo.customComp->isTriggeredAutomatically)) - { - dismissMenu (¤tChild->itemInfo); - } - } - - void selectNextItem (const int delta) - { - disableTimerUntilMouseMoves(); - MenuItemComponent* mic = 0; - bool wasLastOne = (currentChild == 0); - const int numItems = getNumChildComponents(); - - for (int i = 0; i < numItems + 1; ++i) - { - int index = (delta > 0) ? i : (numItems - 1 - i); - index = (index + numItems) % numItems; - - mic = dynamic_cast (getChildComponent (index)); - - if (mic != 0 && (mic->itemInfo.canBeTriggered() || mic->itemInfo.hasActiveSubMenu()) - && wasLastOne) - break; - - if (mic == currentChild) - wasLastOne = true; - } - - setCurrentlyHighlightedChild (mic); - } - - void disableTimerUntilMouseMoves() - { - disableMouseMoves = true; - - if (owner != 0) - owner->disableTimerUntilMouseMoves(); - } - - PopupMenuWindow (const PopupMenuWindow&); - const PopupMenuWindow& operator= (const PopupMenuWindow&); + int x, y, widthToUse, heightToUse; + layoutMenuItems (mon.getWidth() - 24, widthToUse, heightToUse); + + if (alignToRectangle) + { + x = minX; + + const int spaceUnder = mon.getHeight() - (maxY - mon.getY()); + const int spaceOver = minY - mon.getY(); + + if (heightToUse < spaceUnder - 30 || spaceUnder >= spaceOver) + y = maxY; + else + y = minY - heightToUse; + } + else + { + bool tendTowardsRight = (minX + maxX) / 2 < mon.getCentreX(); + + if (owner != 0) + { + if (owner->owner != 0) + { + const bool ownerGoingRight = (owner->getX() + owner->getWidth() / 2 + > owner->owner->getX() + owner->owner->getWidth() / 2); + + if (ownerGoingRight && maxX + widthToUse < mon.getRight() - 4) + tendTowardsRight = true; + else if ((! ownerGoingRight) && minX > widthToUse + 4) + tendTowardsRight = false; + } + else if (maxX + widthToUse < mon.getRight() - 32) + { + tendTowardsRight = true; + } + } + + const int biggestSpace = jmax (mon.getRight() - maxX, + minX - mon.getX()) - 32; + + if (biggestSpace < widthToUse) + { + layoutMenuItems (biggestSpace + (maxX - minX) / 3, widthToUse, heightToUse); + + if (numColumns > 1) + layoutMenuItems (biggestSpace - 4, widthToUse, heightToUse); + + tendTowardsRight = (mon.getRight() - maxX) >= (minX - mon.getX()); + } + + if (tendTowardsRight) + x = jmin (mon.getRight() - widthToUse - 4, maxX); + else + x = jmax (mon.getX() + 4, minX - widthToUse); + + y = minY; + if ((minY + maxY) / 2 > mon.getCentreY()) + y = jmax (mon.getY(), maxY - heightToUse); + } + + x = jmax (mon.getX() + 1, jmin (mon.getRight() - (widthToUse + 6), x)); + y = jmax (mon.getY() + 1, jmin (mon.getBottom() - (heightToUse + 6), y)); + + windowPos.setBounds (x, y, widthToUse, heightToUse); + + // sets this flag if it's big enough to obscure any of its parent menus + hideOnExit = (owner != 0) + && owner->windowPos.intersects (windowPos.expanded (-4, -4)); + } + + void layoutMenuItems (const int maxMenuW, int& width, int& height) + { + numColumns = 0; + contentHeight = 0; + const int maxMenuH = getParentHeight() - 24; + int totalW; + + do + { + ++numColumns; + totalW = workOutBestSize (maxMenuW); + + if (totalW > maxMenuW) + { + numColumns = jmax (1, numColumns - 1); + totalW = workOutBestSize (maxMenuW); // to update col widths + break; + } + else if (totalW > maxMenuW / 2 || contentHeight < maxMenuH) + { + break; + } + + } while (numColumns < maximumNumColumns); + + const int actualH = jmin (contentHeight, maxMenuH); + + needsToScroll = contentHeight > actualH; + + width = updateYPositions(); + height = actualH + borderSize * 2; + } + + int workOutBestSize (const int maxMenuW) + { + int totalW = 0; + contentHeight = 0; + int childNum = 0; + + for (int col = 0; col < numColumns; ++col) + { + int i, colW = 50, colH = 0; + + const int numChildren = jmin (getNumChildComponents() - childNum, + (getNumChildComponents() + numColumns - 1) / numColumns); + + for (i = numChildren; --i >= 0;) + { + colW = jmax (colW, getChildComponent (childNum + i)->getWidth()); + colH += getChildComponent (childNum + i)->getHeight(); + } + + colW = jmin (maxMenuW / jmax (1, numColumns - 2), colW + borderSize * 2); + + columnWidths.set (col, colW); + totalW += colW; + contentHeight = jmax (contentHeight, colH); + + childNum += numChildren; + } + + if (totalW < minimumWidth) + { + totalW = minimumWidth; + + for (int col = 0; col < numColumns; ++col) + columnWidths.set (0, totalW / numColumns); + } + + return totalW; + } + + void ensureItemIsVisible (const int itemId, int wantedY) + { + jassert (itemId != 0) + + for (int i = getNumChildComponents(); --i >= 0;) + { + MenuItemComponent* const m = (MenuItemComponent*) getChildComponent (i); + + if (m != 0 + && m->itemInfo.itemId == itemId + && windowPos.getHeight() > scrollZone * 4) + { + const int currentY = m->getY(); + + if (wantedY > 0 || currentY < 0 || m->getBottom() > windowPos.getHeight()) + { + if (wantedY < 0) + wantedY = jlimit (scrollZone, + jmax (scrollZone, windowPos.getHeight() - (scrollZone + m->getHeight())), + currentY); + + const Rectangle mon (Desktop::getInstance() + .getMonitorAreaContaining (windowPos.getX(), + windowPos.getY(), + true)); + + int deltaY = wantedY - currentY; + + const int newY = jlimit (mon.getY(), + mon.getBottom() - windowPos.getHeight(), + windowPos.getY() + deltaY); + + deltaY -= newY - windowPos.getY(); + + childYOffset -= deltaY; + windowPos.setPosition (windowPos.getX(), newY); + + updateYPositions(); + } + + break; + } + } + } + + void resizeToBestWindowPos() + { + Rectangle r (windowPos); + + if (childYOffset < 0) + { + r.setBounds (r.getX(), r.getY() - childYOffset, + r.getWidth(), r.getHeight() + childYOffset); + } + else if (childYOffset > 0) + { + const int spaceAtBottom = r.getHeight() - (contentHeight - childYOffset); + + if (spaceAtBottom > 0) + r.setSize (r.getWidth(), r.getHeight() - spaceAtBottom); + } + + setBounds (r); + updateYPositions(); + } + + void alterChildYPos (const int delta) + { + if (isScrolling()) + { + childYOffset += delta; + + if (delta < 0) + { + childYOffset = jmax (childYOffset, 0); + } + else if (delta > 0) + { + childYOffset = jmin (childYOffset, + contentHeight - windowPos.getHeight() + borderSize); + } + + updateYPositions(); + } + else + { + childYOffset = 0; + } + + resizeToBestWindowPos(); + repaint(); + } + + int updateYPositions() + { + int x = 0; + int childNum = 0; + + for (int col = 0; col < numColumns; ++col) + { + const int numChildren = jmin (getNumChildComponents() - childNum, + (getNumChildComponents() + numColumns - 1) / numColumns); + + const int colW = columnWidths [col]; + + int y = borderSize - (childYOffset + (getY() - windowPos.getY())); + + for (int i = 0; i < numChildren; ++i) + { + Component* const c = getChildComponent (childNum + i); + c->setBounds (x, y, colW, c->getHeight()); + y += c->getHeight(); + } + + x += colW; + childNum += numChildren; + } + + return x; + } + + bool isScrolling() const + { + return childYOffset != 0 || needsToScroll; + } + + void setCurrentlyHighlightedChild (MenuItemComponent* const child) + { + if (currentChild->isValidComponent()) + currentChild->setHighlighted (false); + + currentChild = child; + + if (currentChild != 0) + { + currentChild->setHighlighted (true); + timeEnteredCurrentChildComp = Time::getApproximateMillisecondCounter(); + } + } + + bool showSubMenuFor (MenuItemComponent* const childComp) + { + jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()); + deleteAndZero (activeSubMenu); + + if (childComp->isValidComponent() && childComp->itemInfo.hasActiveSubMenu()) + { + int left = 0, top = 0; + childComp->relativePositionToGlobal (left, top); + int right = childComp->getWidth(), bottom = childComp->getHeight(); + childComp->relativePositionToGlobal (right, bottom); + + activeSubMenu = PopupMenuWindow::create (*(childComp->itemInfo.subMenu), + dismissOnMouseUp, + this, + left, right, top, bottom, + 0, maximumNumColumns, + standardItemHeight, + false, 0, menuBarComponent, + managerOfChosenCommand, + componentAttachedTo); + + if (activeSubMenu != 0) + { + activeSubMenu->setVisible (true); + activeSubMenu->enterModalState (false); + activeSubMenu->toFront (false); + return true; + } + } + + return false; + } + + void highlightItemUnderMouse (const int mx, const int my, const int x, const int y) + { + isOver = reallyContains (x, y, true); + + if (isOver) + hasBeenOver = true; + + if (abs (lastMouseX - mx) > 2 || abs (lastMouseY - my) > 2) + { + lastMouseMoveTime = Time::getApproximateMillisecondCounter(); + + if (disableMouseMoves && isOver) + disableMouseMoves = false; + } + + if (disableMouseMoves) + return; + + bool isMovingTowardsMenu = false; + + jassert (activeSubMenu == 0 || activeSubMenu->isValidComponent()) + + if (isOver && (activeSubMenu != 0) && (mx != lastMouseX || my != lastMouseY)) + { + // try to intelligently guess whether the user is moving the mouse towards a currently-open + // submenu. To do this, look at whether the mouse stays inside a triangular region that + // extends from the last mouse pos to the submenu's rectangle.. + + float subX = (float) activeSubMenu->getScreenX(); + + if (activeSubMenu->getX() > getX()) + { + lastMouseX -= 2; // to enlarge the triangle a bit, in case the mouse only moves a couple of pixels + } + else + { + lastMouseX += 2; + subX += activeSubMenu->getWidth(); + } + + Path areaTowardsSubMenu; + areaTowardsSubMenu.addTriangle ((float) lastMouseX, + (float) lastMouseY, + subX, + (float) activeSubMenu->getScreenY(), + subX, + (float) (activeSubMenu->getScreenY() + activeSubMenu->getHeight())); + + isMovingTowardsMenu = areaTowardsSubMenu.contains ((float) mx, (float) my); + } + + lastMouseX = mx; + lastMouseY = my; + + if (! isMovingTowardsMenu) + { + Component* c = getComponentAt (x, y); + if (c == this) + c = 0; + + MenuItemComponent* mic = dynamic_cast (c); + + if (mic == 0 && c != 0) + mic = c->findParentComponentOfClass ((MenuItemComponent*) 0); + + if (mic != currentChild + && (isOver || (activeSubMenu == 0) || ! activeSubMenu->isVisible())) + { + if (isOver && (c != 0) && (activeSubMenu != 0)) + { + activeSubMenu->hide (0); + } + + if (! isOver) + mic = 0; + + setCurrentlyHighlightedChild (mic); + } + } + } + + void triggerCurrentlyHighlightedItem() + { + if (currentChild->isValidComponent() + && currentChild->itemInfo.canBeTriggered() + && (currentChild->itemInfo.customComp == 0 + || currentChild->itemInfo.customComp->isTriggeredAutomatically)) + { + dismissMenu (¤tChild->itemInfo); + } + } + + void selectNextItem (const int delta) + { + disableTimerUntilMouseMoves(); + MenuItemComponent* mic = 0; + bool wasLastOne = (currentChild == 0); + const int numItems = getNumChildComponents(); + + for (int i = 0; i < numItems + 1; ++i) + { + int index = (delta > 0) ? i : (numItems - 1 - i); + index = (index + numItems) % numItems; + + mic = dynamic_cast (getChildComponent (index)); + + if (mic != 0 && (mic->itemInfo.canBeTriggered() || mic->itemInfo.hasActiveSubMenu()) + && wasLastOne) + break; + + if (mic == currentChild) + wasLastOne = true; + } + + setCurrentlyHighlightedChild (mic); + } + + void disableTimerUntilMouseMoves() + { + disableMouseMoves = true; + + if (owner != 0) + owner->disableTimerUntilMouseMoves(); + } + + PopupMenuWindow (const PopupMenuWindow&); + const PopupMenuWindow& operator= (const PopupMenuWindow&); }; PopupMenu::PopupMenu() - : items (8), - lookAndFeel (0), - separatorPending (false) + : lookAndFeel (0), + separatorPending (false) { } PopupMenu::PopupMenu (const PopupMenu& other) - : items (8), - lookAndFeel (other.lookAndFeel), - separatorPending (false) + : lookAndFeel (other.lookAndFeel), + separatorPending (false) { - items.ensureStorageAllocated (other.items.size()); + items.ensureStorageAllocated (other.items.size()); - for (int i = 0; i < other.items.size(); ++i) - items.add (new MenuItemInfo (*(const MenuItemInfo*) other.items.getUnchecked(i))); + for (int i = 0; i < other.items.size(); ++i) + items.add (new MenuItemInfo (*(const MenuItemInfo*) other.items.getUnchecked(i))); } const PopupMenu& PopupMenu::operator= (const PopupMenu& other) { - if (this != &other) - { - lookAndFeel = other.lookAndFeel; + if (this != &other) + { + lookAndFeel = other.lookAndFeel; - clear(); - items.ensureStorageAllocated (other.items.size()); + clear(); + items.ensureStorageAllocated (other.items.size()); - for (int i = 0; i < other.items.size(); ++i) - items.add (new MenuItemInfo (*(const MenuItemInfo*) other.items.getUnchecked(i))); - } + for (int i = 0; i < other.items.size(); ++i) + items.add (new MenuItemInfo (*(const MenuItemInfo*) other.items.getUnchecked(i))); + } - return *this; + return *this; } PopupMenu::~PopupMenu() { - clear(); + clear(); } void PopupMenu::clear() { - for (int i = items.size(); --i >= 0;) - delete (MenuItemInfo*) items.getUnchecked(i); + for (int i = items.size(); --i >= 0;) + delete (MenuItemInfo*) items.getUnchecked(i); - items.clear(); - separatorPending = false; + items.clear(); + separatorPending = false; } void PopupMenu::addSeparatorIfPending() { - if (separatorPending) - { - separatorPending = false; + if (separatorPending) + { + separatorPending = false; - if (items.size() > 0) - items.add (new MenuItemInfo()); - } + if (items.size() > 0) + items.add (new MenuItemInfo()); + } } void PopupMenu::addItem (const int itemResultId, - const String& itemText, - const bool isActive, - const bool isTicked, - const Image* const iconToUse) + const String& itemText, + const bool isActive, + const bool isTicked, + const Image* const iconToUse) { - jassert (itemResultId != 0); // 0 is used as a return value to indicate that the user - // didn't pick anything, so you shouldn't use it as the id - // for an item.. + jassert (itemResultId != 0); // 0 is used as a return value to indicate that the user + // didn't pick anything, so you shouldn't use it as the id + // for an item.. - addSeparatorIfPending(); + addSeparatorIfPending(); - items.add (new MenuItemInfo (itemResultId, - itemText, - isActive, - isTicked, - iconToUse, - Colours::black, - false, - 0, 0, 0)); + items.add (new MenuItemInfo (itemResultId, + itemText, + isActive, + isTicked, + iconToUse, + Colours::black, + false, + 0, 0, 0)); } void PopupMenu::addCommandItem (ApplicationCommandManager* commandManager, - const int commandID, - const String& displayName) + const int commandID, + const String& displayName) { - jassert (commandManager != 0 && commandID != 0); + jassert (commandManager != 0 && commandID != 0); - const ApplicationCommandInfo* const registeredInfo = commandManager->getCommandForID (commandID); + const ApplicationCommandInfo* const registeredInfo = commandManager->getCommandForID (commandID); - if (registeredInfo != 0) - { - ApplicationCommandInfo info (*registeredInfo); - ApplicationCommandTarget* const target = commandManager->getTargetForCommand (commandID, info); + if (registeredInfo != 0) + { + ApplicationCommandInfo info (*registeredInfo); + ApplicationCommandTarget* const target = commandManager->getTargetForCommand (commandID, info); - addSeparatorIfPending(); + addSeparatorIfPending(); - items.add (new MenuItemInfo (commandID, - displayName.isNotEmpty() ? displayName - : info.shortName, - target != 0 && (info.flags & ApplicationCommandInfo::isDisabled) == 0, - (info.flags & ApplicationCommandInfo::isTicked) != 0, - 0, - Colours::black, - false, - 0, 0, - commandManager)); - } + items.add (new MenuItemInfo (commandID, + displayName.isNotEmpty() ? displayName + : info.shortName, + target != 0 && (info.flags & ApplicationCommandInfo::isDisabled) == 0, + (info.flags & ApplicationCommandInfo::isTicked) != 0, + 0, + Colours::black, + false, + 0, 0, + commandManager)); + } } void PopupMenu::addColouredItem (const int itemResultId, - const String& itemText, - const Colour& itemTextColour, - const bool isActive, - const bool isTicked, - const Image* const iconToUse) + const String& itemText, + const Colour& itemTextColour, + const bool isActive, + const bool isTicked, + const Image* const iconToUse) { - jassert (itemResultId != 0); // 0 is used as a return value to indicate that the user - // didn't pick anything, so you shouldn't use it as the id - // for an item.. + jassert (itemResultId != 0); // 0 is used as a return value to indicate that the user + // didn't pick anything, so you shouldn't use it as the id + // for an item.. - addSeparatorIfPending(); + addSeparatorIfPending(); - items.add (new MenuItemInfo (itemResultId, - itemText, - isActive, - isTicked, - iconToUse, - itemTextColour, - true, - 0, 0, 0)); + items.add (new MenuItemInfo (itemResultId, + itemText, + isActive, + isTicked, + iconToUse, + itemTextColour, + true, + 0, 0, 0)); } void PopupMenu::addCustomItem (const int itemResultId, - PopupMenuCustomComponent* const customComponent) + PopupMenuCustomComponent* const customComponent) { - jassert (itemResultId != 0); // 0 is used as a return value to indicate that the user - // didn't pick anything, so you shouldn't use it as the id - // for an item.. + jassert (itemResultId != 0); // 0 is used as a return value to indicate that the user + // didn't pick anything, so you shouldn't use it as the id + // for an item.. - addSeparatorIfPending(); + addSeparatorIfPending(); - items.add (new MenuItemInfo (itemResultId, - String::empty, - true, - false, - 0, - Colours::black, - false, - customComponent, - 0, 0)); + items.add (new MenuItemInfo (itemResultId, + String::empty, + true, + false, + 0, + Colours::black, + false, + customComponent, + 0, 0)); } class NormalComponentWrapper : public PopupMenuCustomComponent { public: - NormalComponentWrapper (Component* const comp, - const int w, const int h, - const bool triggerMenuItemAutomaticallyWhenClicked) - : PopupMenuCustomComponent (triggerMenuItemAutomaticallyWhenClicked), - width (w), - height (h) - { - addAndMakeVisible (comp); - } + NormalComponentWrapper (Component* const comp, + const int w, const int h, + const bool triggerMenuItemAutomaticallyWhenClicked) + : PopupMenuCustomComponent (triggerMenuItemAutomaticallyWhenClicked), + width (w), + height (h) + { + addAndMakeVisible (comp); + } - ~NormalComponentWrapper() {} + ~NormalComponentWrapper() {} - void getIdealSize (int& idealWidth, int& idealHeight) - { - idealWidth = width; - idealHeight = height; - } + void getIdealSize (int& idealWidth, int& idealHeight) + { + idealWidth = width; + idealHeight = height; + } - void resized() - { - if (getChildComponent(0) != 0) - getChildComponent(0)->setBounds (0, 0, getWidth(), getHeight()); - } + void resized() + { + if (getChildComponent(0) != 0) + getChildComponent(0)->setBounds (0, 0, getWidth(), getHeight()); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - const int width, height; + const int width, height; - NormalComponentWrapper (const NormalComponentWrapper&); - const NormalComponentWrapper& operator= (const NormalComponentWrapper&); + NormalComponentWrapper (const NormalComponentWrapper&); + const NormalComponentWrapper& operator= (const NormalComponentWrapper&); }; void PopupMenu::addCustomItem (const int itemResultId, - Component* customComponent, - int idealWidth, int idealHeight, - const bool triggerMenuItemAutomaticallyWhenClicked) + Component* customComponent, + int idealWidth, int idealHeight, + const bool triggerMenuItemAutomaticallyWhenClicked) { - addCustomItem (itemResultId, - new NormalComponentWrapper (customComponent, - idealWidth, idealHeight, - triggerMenuItemAutomaticallyWhenClicked)); + addCustomItem (itemResultId, + new NormalComponentWrapper (customComponent, + idealWidth, idealHeight, + triggerMenuItemAutomaticallyWhenClicked)); } void PopupMenu::addSubMenu (const String& subMenuName, - const PopupMenu& subMenu, - const bool isActive, - Image* const iconToUse, - const bool isTicked) + const PopupMenu& subMenu, + const bool isActive, + Image* const iconToUse, + const bool isTicked) { - addSeparatorIfPending(); + addSeparatorIfPending(); - items.add (new MenuItemInfo (0, - subMenuName, - isActive && (subMenu.getNumItems() > 0), - isTicked, - iconToUse, - Colours::black, - false, - 0, - &subMenu, - 0)); + items.add (new MenuItemInfo (0, + subMenuName, + isActive && (subMenu.getNumItems() > 0), + isTicked, + iconToUse, + Colours::black, + false, + 0, + &subMenu, + 0)); } void PopupMenu::addSeparator() { - separatorPending = true; + separatorPending = true; } class HeaderItemComponent : public PopupMenuCustomComponent { public: - HeaderItemComponent (const String& name) - : PopupMenuCustomComponent (false) - { - setName (name); - } + HeaderItemComponent (const String& name) + : PopupMenuCustomComponent (false) + { + setName (name); + } - ~HeaderItemComponent() - { - } + ~HeaderItemComponent() + { + } - void paint (Graphics& g) - { - Font f (getLookAndFeel().getPopupMenuFont()); - f.setBold (true); - g.setFont (f); + void paint (Graphics& g) + { + Font f (getLookAndFeel().getPopupMenuFont()); + f.setBold (true); + g.setFont (f); - g.setColour (findColour (PopupMenu::headerTextColourId)); + g.setColour (findColour (PopupMenu::headerTextColourId)); - g.drawFittedText (getName(), - 12, 0, getWidth() - 16, proportionOfHeight (0.8f), - Justification::bottomLeft, 1); - } + g.drawFittedText (getName(), + 12, 0, getWidth() - 16, proportionOfHeight (0.8f), + Justification::bottomLeft, 1); + } - void getIdealSize (int& idealWidth, - int& idealHeight) - { - getLookAndFeel().getIdealPopupMenuItemSize (getName(), false, -1, idealWidth, idealHeight); - idealHeight += idealHeight / 2; - idealWidth += idealWidth / 4; - } + void getIdealSize (int& idealWidth, + int& idealHeight) + { + getLookAndFeel().getIdealPopupMenuItemSize (getName(), false, -1, idealWidth, idealHeight); + idealHeight += idealHeight / 2; + idealWidth += idealWidth / 4; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; void PopupMenu::addSectionHeader (const String& title) { - addCustomItem (0X4734a34f, new HeaderItemComponent (title)); + addCustomItem (0X4734a34f, new HeaderItemComponent (title)); } Component* PopupMenu::createMenuComponent (const int x, const int y, const int w, const int h, - const int itemIdThatMustBeVisible, - const int minimumWidth, - const int maximumNumColumns, - const int standardItemHeight, - const bool alignToRectangle, - Component* menuBarComponent, - ApplicationCommandManager** managerOfChosenCommand, - Component* const componentAttachedTo) + const int itemIdThatMustBeVisible, + const int minimumWidth, + const int maximumNumColumns, + const int standardItemHeight, + const bool alignToRectangle, + Component* menuBarComponent, + ApplicationCommandManager** managerOfChosenCommand, + Component* const componentAttachedTo) { - PopupMenuWindow* const pw - = PopupMenuWindow::create (*this, - ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown(), - 0, - x, x + w, - y, y + h, - minimumWidth, - maximumNumColumns, - standardItemHeight, - alignToRectangle, - itemIdThatMustBeVisible, - menuBarComponent, - managerOfChosenCommand, - componentAttachedTo); + PopupMenuWindow* const pw + = PopupMenuWindow::create (*this, + ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown(), + 0, + x, x + w, + y, y + h, + minimumWidth, + maximumNumColumns, + standardItemHeight, + alignToRectangle, + itemIdThatMustBeVisible, + menuBarComponent, + managerOfChosenCommand, + componentAttachedTo); - if (pw != 0) - pw->setVisible (true); + if (pw != 0) + pw->setVisible (true); - return pw; + return pw; } int PopupMenu::showMenu (const int x, const int y, const int w, const int h, - const int itemIdThatMustBeVisible, - const int minimumWidth, - const int maximumNumColumns, - const int standardItemHeight, - const bool alignToRectangle, - Component* const componentAttachedTo) + const int itemIdThatMustBeVisible, + const int minimumWidth, + const int maximumNumColumns, + const int standardItemHeight, + const bool alignToRectangle, + Component* const componentAttachedTo) { - Component* const prevFocused = Component::getCurrentlyFocusedComponent(); + Component* const prevFocused = Component::getCurrentlyFocusedComponent(); - ScopedPointer deletionChecker[2]; - if (prevFocused != 0) - deletionChecker[0] = new ComponentDeletionWatcher (prevFocused); + ScopedPointer deletionChecker[2]; + if (prevFocused != 0) + deletionChecker[0] = new ComponentDeletionWatcher (prevFocused); - Component* const prevTopLevel = (prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0; + Component* const prevTopLevel = (prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0; - if (prevTopLevel != 0) - deletionChecker[1] = new ComponentDeletionWatcher (prevTopLevel); + if (prevTopLevel != 0) + deletionChecker[1] = new ComponentDeletionWatcher (prevTopLevel); - wasHiddenBecauseOfAppChange = false; + wasHiddenBecauseOfAppChange = false; - int result = 0; - ApplicationCommandManager* managerOfChosenCommand = 0; + int result = 0; + ApplicationCommandManager* managerOfChosenCommand = 0; - ScopedPointer popupComp (createMenuComponent (x, y, w, h, - itemIdThatMustBeVisible, - minimumWidth, - maximumNumColumns > 0 ? maximumNumColumns : 7, - standardItemHeight, - alignToRectangle, 0, - &managerOfChosenCommand, - componentAttachedTo)); + ScopedPointer popupComp (createMenuComponent (x, y, w, h, + itemIdThatMustBeVisible, + minimumWidth, + maximumNumColumns > 0 ? maximumNumColumns : 7, + standardItemHeight, + alignToRectangle, 0, + &managerOfChosenCommand, + componentAttachedTo)); - if (popupComp != 0) - { - popupComp->enterModalState (false); - popupComp->toFront (false); // need to do this after making it modal, or it could - // be stuck behind other comps that are already modal.. + if (popupComp != 0) + { + popupComp->enterModalState (false); + popupComp->toFront (false); // need to do this after making it modal, or it could + // be stuck behind other comps that are already modal.. - result = popupComp->runModalLoop(); - popupComp = 0; + result = popupComp->runModalLoop(); + popupComp = 0; - if (! wasHiddenBecauseOfAppChange) - { - if (deletionChecker[1] != 0 && ! deletionChecker[1]->hasBeenDeleted()) - prevTopLevel->toFront (true); + if (! wasHiddenBecauseOfAppChange) + { + if (deletionChecker[1] != 0 && ! deletionChecker[1]->hasBeenDeleted()) + prevTopLevel->toFront (true); - if (deletionChecker[0] != 0 && ! deletionChecker[0]->hasBeenDeleted()) - prevFocused->grabKeyboardFocus(); - } - } + if (deletionChecker[0] != 0 && ! deletionChecker[0]->hasBeenDeleted()) + prevFocused->grabKeyboardFocus(); + } + } - if (managerOfChosenCommand != 0 && result != 0) - { - ApplicationCommandTarget::InvocationInfo info (result); - info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu; + if (managerOfChosenCommand != 0 && result != 0) + { + ApplicationCommandTarget::InvocationInfo info (result); + info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu; - managerOfChosenCommand->invoke (info, true); - } + managerOfChosenCommand->invoke (info, true); + } - return result; + return result; } int PopupMenu::show (const int itemIdThatMustBeVisible, - const int minimumWidth, - const int maximumNumColumns, - const int standardItemHeight) + const int minimumWidth, + const int maximumNumColumns, + const int standardItemHeight) { - int x, y; - Desktop::getMousePosition (x, y); + int x, y; + Desktop::getMousePosition (x, y); - return showAt (x, y, - itemIdThatMustBeVisible, - minimumWidth, - maximumNumColumns, - standardItemHeight); + return showAt (x, y, + itemIdThatMustBeVisible, + minimumWidth, + maximumNumColumns, + standardItemHeight); } int PopupMenu::showAt (const int screenX, - const int screenY, - const int itemIdThatMustBeVisible, - const int minimumWidth, - const int maximumNumColumns, - const int standardItemHeight) + const int screenY, + const int itemIdThatMustBeVisible, + const int minimumWidth, + const int maximumNumColumns, + const int standardItemHeight) { - return showMenu (screenX, screenY, 1, 1, - itemIdThatMustBeVisible, - minimumWidth, maximumNumColumns, - standardItemHeight, - false, 0); + return showMenu (screenX, screenY, 1, 1, + itemIdThatMustBeVisible, + minimumWidth, maximumNumColumns, + standardItemHeight, + false, 0); } int PopupMenu::showAt (Component* componentToAttachTo, - const int itemIdThatMustBeVisible, - const int minimumWidth, - const int maximumNumColumns, - const int standardItemHeight) + const int itemIdThatMustBeVisible, + const int minimumWidth, + const int maximumNumColumns, + const int standardItemHeight) { - if (componentToAttachTo != 0) - { - return showMenu (componentToAttachTo->getScreenX(), - componentToAttachTo->getScreenY(), - componentToAttachTo->getWidth(), - componentToAttachTo->getHeight(), - itemIdThatMustBeVisible, - minimumWidth, - maximumNumColumns, - standardItemHeight, - true, componentToAttachTo); - } - else - { - return show (itemIdThatMustBeVisible, - minimumWidth, - maximumNumColumns, - standardItemHeight); - } + if (componentToAttachTo != 0) + { + return showMenu (componentToAttachTo->getScreenX(), + componentToAttachTo->getScreenY(), + componentToAttachTo->getWidth(), + componentToAttachTo->getHeight(), + itemIdThatMustBeVisible, + minimumWidth, + maximumNumColumns, + standardItemHeight, + true, componentToAttachTo); + } + else + { + return show (itemIdThatMustBeVisible, + minimumWidth, + maximumNumColumns, + standardItemHeight); + } } void JUCE_CALLTYPE PopupMenu::dismissAllActiveMenus() { - for (int i = activeMenuWindows.size(); --i >= 0;) - { - PopupMenuWindow* const pmw = (PopupMenuWindow*) activeMenuWindows[i]; + for (int i = activeMenuWindows.size(); --i >= 0;) + { + PopupMenuWindow* const pmw = (PopupMenuWindow*) activeMenuWindows[i]; - if (pmw != 0) - pmw->dismissMenu (0); - } + if (pmw != 0) + pmw->dismissMenu (0); + } } int PopupMenu::getNumItems() const { - int num = 0; + int num = 0; - for (int i = items.size(); --i >= 0;) - if (! ((MenuItemInfo*) items.getUnchecked(i))->isSeparator) - ++num; + for (int i = items.size(); --i >= 0;) + if (! ((MenuItemInfo*) items.getUnchecked(i))->isSeparator) + ++num; - return num; + return num; } bool PopupMenu::containsCommandItem (const int commandID) const { - for (int i = items.size(); --i >= 0;) - { - const MenuItemInfo* mi = (const MenuItemInfo*) items.getUnchecked (i); + for (int i = items.size(); --i >= 0;) + { + const MenuItemInfo* mi = (const MenuItemInfo*) items.getUnchecked (i); - if ((mi->itemId == commandID && mi->commandManager != 0) - || (mi->subMenu != 0 && mi->subMenu->containsCommandItem (commandID))) - { - return true; - } - } + if ((mi->itemId == commandID && mi->commandManager != 0) + || (mi->subMenu != 0 && mi->subMenu->containsCommandItem (commandID))) + { + return true; + } + } - return false; + return false; } bool PopupMenu::containsAnyActiveItems() const { - for (int i = items.size(); --i >= 0;) - { - const MenuItemInfo* const mi = (const MenuItemInfo*) items.getUnchecked (i); + for (int i = items.size(); --i >= 0;) + { + const MenuItemInfo* const mi = (const MenuItemInfo*) items.getUnchecked (i); - if (mi->subMenu != 0) - { - if (mi->subMenu->containsAnyActiveItems()) - return true; - } - else if (mi->active) - { - return true; - } - } + if (mi->subMenu != 0) + { + if (mi->subMenu->containsAnyActiveItems()) + return true; + } + else if (mi->active) + { + return true; + } + } - return false; + return false; } void PopupMenu::setLookAndFeel (LookAndFeel* const newLookAndFeel) { - lookAndFeel = newLookAndFeel; + lookAndFeel = newLookAndFeel; } PopupMenuCustomComponent::PopupMenuCustomComponent (const bool isTriggeredAutomatically_) - : refCount_ (0), - isHighlighted (false), - isTriggeredAutomatically (isTriggeredAutomatically_) + : refCount_ (0), + isHighlighted (false), + isTriggeredAutomatically (isTriggeredAutomatically_) { } PopupMenuCustomComponent::~PopupMenuCustomComponent() { - jassert (refCount_ == 0); // should be deleted only by the menu component, as they keep a ref-count. + jassert (refCount_ == 0); // should be deleted only by the menu component, as they keep a ref-count. } void PopupMenuCustomComponent::triggerMenuItem() { - MenuItemComponent* const mic = dynamic_cast (getParentComponent()); + MenuItemComponent* const mic = dynamic_cast (getParentComponent()); - if (mic != 0) - { - PopupMenuWindow* const pmw = dynamic_cast (mic->getParentComponent()); + if (mic != 0) + { + PopupMenuWindow* const pmw = dynamic_cast (mic->getParentComponent()); - if (pmw != 0) - { - pmw->dismissMenu (&mic->itemInfo); - } - else - { - // something must have gone wrong with the component hierarchy if this happens.. - jassertfalse - } - } - else - { - // why isn't this component inside a menu? Not much point triggering the item if - // there's no menu. - jassertfalse - } + if (pmw != 0) + { + pmw->dismissMenu (&mic->itemInfo); + } + else + { + // something must have gone wrong with the component hierarchy if this happens.. + jassertfalse + } + } + else + { + // why isn't this component inside a menu? Not much point triggering the item if + // there's no menu. + jassertfalse + } } PopupMenu::MenuItemIterator::MenuItemIterator (const PopupMenu& menu_) - : subMenu (0), - itemId (0), - isSeparator (false), - isTicked (false), - isEnabled (false), - isCustomComponent (false), - isSectionHeader (false), - customColour (0), - customImage (0), - menu (menu_), - index (0) + : subMenu (0), + itemId (0), + isSeparator (false), + isTicked (false), + isEnabled (false), + isCustomComponent (false), + isSectionHeader (false), + customColour (0), + customImage (0), + menu (menu_), + index (0) { } @@ -70139,26 +69836,26 @@ PopupMenu::MenuItemIterator::~MenuItemIterator() bool PopupMenu::MenuItemIterator::next() { - if (index >= menu.items.size()) - return false; + if (index >= menu.items.size()) + return false; - const MenuItemInfo* const item = (const MenuItemInfo*) menu.items.getUnchecked (index); - ++index; + const MenuItemInfo* const item = (const MenuItemInfo*) menu.items.getUnchecked (index); + ++index; - itemName = item->customComp != 0 ? item->customComp->getName() : item->text; - subMenu = item->subMenu; - itemId = item->itemId; + itemName = item->customComp != 0 ? item->customComp->getName() : item->text; + subMenu = item->subMenu; + itemId = item->itemId; - isSeparator = item->isSeparator; - isTicked = item->isTicked; - isEnabled = item->active; - isSectionHeader = dynamic_cast (item->customComp) != 0; - isCustomComponent = (! isSectionHeader) && item->customComp != 0; - customColour = item->usesColour ? &(item->textColour) : 0; - customImage = item->image; - commandManager = item->commandManager; + isSeparator = item->isSeparator; + isTicked = item->isTicked; + isEnabled = item->active; + isSectionHeader = dynamic_cast (item->customComp) != 0; + isCustomComponent = (! isSectionHeader) && item->customComp != 0; + customColour = item->usesColour ? &(item->textColour) : 0; + customImage = item->image; + commandManager = item->commandManager; - return true; + return true; } END_JUCE_NAMESPACE @@ -70169,9 +69866,9 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ComponentDragger::ComponentDragger() - : constrainer (0), - originalX (0), - originalY (0) + : constrainer (0), + originalX (0), + originalY (0) { } @@ -70180,44 +69877,44 @@ ComponentDragger::~ComponentDragger() } void ComponentDragger::startDraggingComponent (Component* const componentToDrag, - ComponentBoundsConstrainer* const constrainer_) + ComponentBoundsConstrainer* const constrainer_) { - jassert (componentToDrag->isValidComponent()); + jassert (componentToDrag->isValidComponent()); - if (componentToDrag->isValidComponent()) - { - constrainer = constrainer_; - originalX = 0; - originalY = 0; - componentToDrag->relativePositionToGlobal (originalX, originalY); - } + if (componentToDrag->isValidComponent()) + { + constrainer = constrainer_; + originalX = 0; + originalY = 0; + componentToDrag->relativePositionToGlobal (originalX, originalY); + } } void ComponentDragger::dragComponent (Component* const componentToDrag, const MouseEvent& e) { - jassert (componentToDrag->isValidComponent()); - jassert (e.mods.isAnyMouseButtonDown()); // (the event has to be a drag event..) + jassert (componentToDrag->isValidComponent()); + jassert (e.mods.isAnyMouseButtonDown()); // (the event has to be a drag event..) - if (componentToDrag->isValidComponent()) - { - int x = originalX; - int y = originalY; - int w = componentToDrag->getWidth(); - int h = componentToDrag->getHeight(); + if (componentToDrag->isValidComponent()) + { + int x = originalX; + int y = originalY; + int w = componentToDrag->getWidth(); + int h = componentToDrag->getHeight(); - const Component* const parentComp = componentToDrag->getParentComponent(); - if (parentComp != 0) - parentComp->globalPositionToRelative (x, y); + const Component* const parentComp = componentToDrag->getParentComponent(); + if (parentComp != 0) + parentComp->globalPositionToRelative (x, y); - x += e.getDistanceFromDragStartX(); - y += e.getDistanceFromDragStartY(); + x += e.getDistanceFromDragStartX(); + y += e.getDistanceFromDragStartY(); - if (constrainer != 0) - constrainer->setBoundsForComponent (componentToDrag, x, y, w, h, - false, false, false, false); - else - componentToDrag->setBounds (x, y, w, h); - } + if (constrainer != 0) + constrainer->setBoundsForComponent (componentToDrag, x, y, w, h, + false, false, false, false); + else + componentToDrag->setBounds (x, y, w, h); + } } END_JUCE_NAMESPACE @@ -70231,293 +69928,293 @@ bool juce_performDragDropFiles (const StringArray& files, const bool copyFiles, bool juce_performDragDropText (const String& text, bool& shouldStop); class DragImageComponent : public Component, - public Timer + public Timer { private: - ScopedPointer image; - Component* const source; - DragAndDropContainer* const owner; + ScopedPointer image; + Component* const source; + DragAndDropContainer* const owner; - ScopedPointer sourceWatcher, mouseDragSourceWatcher, currentlyOverWatcher; - Component* mouseDragSource; - DragAndDropTarget* currentlyOver; + ScopedPointer sourceWatcher, mouseDragSourceWatcher, currentlyOverWatcher; + Component* mouseDragSource; + DragAndDropTarget* currentlyOver; - String dragDesc; - const int imageX, imageY; - bool hasCheckedForExternalDrag, drawImage; + String dragDesc; + const int imageX, imageY; + bool hasCheckedForExternalDrag, drawImage; - DragImageComponent (const DragImageComponent&); - const DragImageComponent& operator= (const DragImageComponent&); + DragImageComponent (const DragImageComponent&); + const DragImageComponent& operator= (const DragImageComponent&); public: - DragImageComponent (Image* const im, - const String& desc, - Component* const s, - DragAndDropContainer* const o, - const int imageX_, const int imageY_) - : image (im), - source (s), - owner (o), - currentlyOver (0), - dragDesc (desc), - imageX (imageX_), - imageY (imageY_), - hasCheckedForExternalDrag (false), - drawImage (true) - { - setSize (im->getWidth(), im->getHeight()); + DragImageComponent (Image* const im, + const String& desc, + Component* const s, + DragAndDropContainer* const o, + const int imageX_, const int imageY_) + : image (im), + source (s), + owner (o), + currentlyOver (0), + dragDesc (desc), + imageX (imageX_), + imageY (imageY_), + hasCheckedForExternalDrag (false), + drawImage (true) + { + setSize (im->getWidth(), im->getHeight()); - sourceWatcher = new ComponentDeletionWatcher (source); + sourceWatcher = new ComponentDeletionWatcher (source); - mouseDragSource = Component::getComponentUnderMouse(); + mouseDragSource = Component::getComponentUnderMouse(); - if (mouseDragSource == 0) - mouseDragSource = source; + if (mouseDragSource == 0) + mouseDragSource = source; - mouseDragSourceWatcher = new ComponentDeletionWatcher (mouseDragSource); - mouseDragSource->addMouseListener (this, false); + mouseDragSourceWatcher = new ComponentDeletionWatcher (mouseDragSource); + mouseDragSource->addMouseListener (this, false); - startTimer (200); + startTimer (200); - setInterceptsMouseClicks (false, false); - setAlwaysOnTop (true); - } + setInterceptsMouseClicks (false, false); + setAlwaysOnTop (true); + } - ~DragImageComponent() - { - if ((DragImageComponent*) owner->dragImageComponent == this) - owner->dragImageComponent.release(); + ~DragImageComponent() + { + if ((DragImageComponent*) owner->dragImageComponent == this) + owner->dragImageComponent.release(); - if (! mouseDragSourceWatcher->hasBeenDeleted()) - { - mouseDragSource->removeMouseListener (this); + if (! mouseDragSourceWatcher->hasBeenDeleted()) + { + mouseDragSource->removeMouseListener (this); - if (currentlyOverWatcher != 0 && ! currentlyOverWatcher->hasBeenDeleted()) - if (currentlyOver->isInterestedInDragSource (dragDesc, source)) - currentlyOver->itemDragExit (dragDesc, source); - } - } + if (currentlyOverWatcher != 0 && ! currentlyOverWatcher->hasBeenDeleted()) + if (currentlyOver->isInterestedInDragSource (dragDesc, source)) + currentlyOver->itemDragExit (dragDesc, source); + } + } - void paint (Graphics& g) - { - if (isOpaque()) - g.fillAll (Colours::white); + void paint (Graphics& g) + { + if (isOpaque()) + g.fillAll (Colours::white); - if (drawImage) - { - g.setOpacity (1.0f); - g.drawImageAt (image, 0, 0); - } - } + if (drawImage) + { + g.setOpacity (1.0f); + g.drawImageAt (image, 0, 0); + } + } - DragAndDropTarget* findTarget (const int screenX, const int screenY, - int& relX, int& relY) const - { - Component* hit = getParentComponent(); + DragAndDropTarget* findTarget (const int screenX, const int screenY, + int& relX, int& relY) const + { + Component* hit = getParentComponent(); - if (hit == 0) - { - hit = Desktop::getInstance().findComponentAt (screenX, screenY); - } - else - { - int rx = screenX, ry = screenY; - hit->globalPositionToRelative (rx, ry); + if (hit == 0) + { + hit = Desktop::getInstance().findComponentAt (screenX, screenY); + } + else + { + int rx = screenX, ry = screenY; + hit->globalPositionToRelative (rx, ry); - hit = hit->getComponentAt (rx, ry); - } + hit = hit->getComponentAt (rx, ry); + } - // (note: use a local copy of the dragDesc member in case the callback runs - // a modal loop and deletes this object before the method completes) - const String dragDescLocal (dragDesc); + // (note: use a local copy of the dragDesc member in case the callback runs + // a modal loop and deletes this object before the method completes) + const String dragDescLocal (dragDesc); - while (hit != 0) - { - DragAndDropTarget* const ddt = dynamic_cast (hit); + while (hit != 0) + { + DragAndDropTarget* const ddt = dynamic_cast (hit); - if (ddt != 0 && ddt->isInterestedInDragSource (dragDescLocal, source)) - { - relX = screenX; - relY = screenY; - hit->globalPositionToRelative (relX, relY); - return ddt; - } + if (ddt != 0 && ddt->isInterestedInDragSource (dragDescLocal, source)) + { + relX = screenX; + relY = screenY; + hit->globalPositionToRelative (relX, relY); + return ddt; + } - hit = hit->getParentComponent(); - } + hit = hit->getParentComponent(); + } - return 0; - } + return 0; + } - void mouseUp (const MouseEvent& e) - { - if (e.originalComponent != this) - { - if (! mouseDragSourceWatcher->hasBeenDeleted()) - mouseDragSource->removeMouseListener (this); + void mouseUp (const MouseEvent& e) + { + if (e.originalComponent != this) + { + if (! mouseDragSourceWatcher->hasBeenDeleted()) + mouseDragSource->removeMouseListener (this); - bool dropAccepted = false; - DragAndDropTarget* ddt = 0; - int relX = 0, relY = 0; + bool dropAccepted = false; + DragAndDropTarget* ddt = 0; + int relX = 0, relY = 0; - if (isVisible()) - { - setVisible (false); - ddt = findTarget (e.getScreenX(), - e.getScreenY(), - relX, relY); + if (isVisible()) + { + setVisible (false); + ddt = findTarget (e.getScreenX(), + e.getScreenY(), + relX, relY); - // fade this component and remove it - it'll be deleted later by the timer callback + // fade this component and remove it - it'll be deleted later by the timer callback - dropAccepted = ddt != 0; + dropAccepted = ddt != 0; - setVisible (true); + setVisible (true); - if (dropAccepted || sourceWatcher->hasBeenDeleted()) - { - fadeOutComponent (120); - } - else - { - int targetX = source->getWidth() / 2; - int targetY = source->getHeight() / 2; - source->relativePositionToGlobal (targetX, targetY); + if (dropAccepted || sourceWatcher->hasBeenDeleted()) + { + fadeOutComponent (120); + } + else + { + int targetX = source->getWidth() / 2; + int targetY = source->getHeight() / 2; + source->relativePositionToGlobal (targetX, targetY); - int ourCentreX = getWidth() / 2; - int ourCentreY = getHeight() / 2; - relativePositionToGlobal (ourCentreX, ourCentreY); + int ourCentreX = getWidth() / 2; + int ourCentreY = getHeight() / 2; + relativePositionToGlobal (ourCentreX, ourCentreY); - fadeOutComponent (120, - targetX - ourCentreX, - targetY - ourCentreY); - } - } + fadeOutComponent (120, + targetX - ourCentreX, + targetY - ourCentreY); + } + } - if (getParentComponent() != 0) - getParentComponent()->removeChildComponent (this); + if (getParentComponent() != 0) + getParentComponent()->removeChildComponent (this); - if (dropAccepted && ddt != 0) - { - // (note: use a local copy of the dragDesc member in case the callback runs - // a modal loop and deletes this object before the method completes) - const String dragDescLocal (dragDesc); + if (dropAccepted && ddt != 0) + { + // (note: use a local copy of the dragDesc member in case the callback runs + // a modal loop and deletes this object before the method completes) + const String dragDescLocal (dragDesc); - currentlyOverWatcher = 0; - currentlyOver = 0; + currentlyOverWatcher = 0; + currentlyOver = 0; - ddt->itemDropped (dragDescLocal, source, relX, relY); - } + ddt->itemDropped (dragDescLocal, source, relX, relY); + } - // careful - this object could now be deleted.. - } - } + // careful - this object could now be deleted.. + } + } - void updateLocation (const bool canDoExternalDrag, int x, int y) - { - // (note: use a local copy of the dragDesc member in case the callback runs - // a modal loop and deletes this object before it returns) - const String dragDescLocal (dragDesc); + void updateLocation (const bool canDoExternalDrag, int x, int y) + { + // (note: use a local copy of the dragDesc member in case the callback runs + // a modal loop and deletes this object before it returns) + const String dragDescLocal (dragDesc); - int newX = x + imageX; - int newY = y + imageY; + int newX = x + imageX; + int newY = y + imageY; - if (getParentComponent() != 0) - getParentComponent()->globalPositionToRelative (newX, newY); + if (getParentComponent() != 0) + getParentComponent()->globalPositionToRelative (newX, newY); - //if (newX != getX() || newY != getY()) - { - setTopLeftPosition (newX, newY); + //if (newX != getX() || newY != getY()) + { + setTopLeftPosition (newX, newY); - int relX = 0, relY = 0; - DragAndDropTarget* const ddt = findTarget (x, y, relX, relY); + int relX = 0, relY = 0; + DragAndDropTarget* const ddt = findTarget (x, y, relX, relY); - drawImage = (ddt == 0) || ddt->shouldDrawDragImageWhenOver(); + drawImage = (ddt == 0) || ddt->shouldDrawDragImageWhenOver(); - if (ddt != currentlyOver) - { - if (currentlyOverWatcher != 0 && ! currentlyOverWatcher->hasBeenDeleted()) - { - Component* const over = dynamic_cast (currentlyOver); + if (ddt != currentlyOver) + { + if (currentlyOverWatcher != 0 && ! currentlyOverWatcher->hasBeenDeleted()) + { + Component* const over = dynamic_cast (currentlyOver); - if (over != 0 - && over->isValidComponent() - && ! (sourceWatcher->hasBeenDeleted()) - && currentlyOver->isInterestedInDragSource (dragDescLocal, source)) - { - currentlyOver->itemDragExit (dragDescLocal, source); - } - } + if (over != 0 + && over->isValidComponent() + && ! (sourceWatcher->hasBeenDeleted()) + && currentlyOver->isInterestedInDragSource (dragDescLocal, source)) + { + currentlyOver->itemDragExit (dragDescLocal, source); + } + } - currentlyOver = ddt; - currentlyOverWatcher = 0; + currentlyOver = ddt; + currentlyOverWatcher = 0; - if (ddt != 0) - { - currentlyOverWatcher = new ComponentDeletionWatcher (dynamic_cast (ddt)); + if (ddt != 0) + { + currentlyOverWatcher = new ComponentDeletionWatcher (dynamic_cast (ddt)); - if (currentlyOver->isInterestedInDragSource (dragDescLocal, source)) - currentlyOver->itemDragEnter (dragDescLocal, source, relX, relY); - } - } - else if (currentlyOverWatcher != 0 && currentlyOverWatcher->hasBeenDeleted()) - { - currentlyOver = 0; - currentlyOverWatcher = 0; - } + if (currentlyOver->isInterestedInDragSource (dragDescLocal, source)) + currentlyOver->itemDragEnter (dragDescLocal, source, relX, relY); + } + } + else if (currentlyOverWatcher != 0 && currentlyOverWatcher->hasBeenDeleted()) + { + currentlyOver = 0; + currentlyOverWatcher = 0; + } - if (currentlyOver != 0 - && currentlyOver->isInterestedInDragSource (dragDescLocal, source)) - currentlyOver->itemDragMove (dragDescLocal, source, relX, relY); + if (currentlyOver != 0 + && currentlyOver->isInterestedInDragSource (dragDescLocal, source)) + currentlyOver->itemDragMove (dragDescLocal, source, relX, relY); - if (currentlyOver == 0 - && canDoExternalDrag - && ! hasCheckedForExternalDrag) - { - if (Desktop::getInstance().findComponentAt (x, y) == 0) - { - hasCheckedForExternalDrag = true; - StringArray files; - bool canMoveFiles = false; + if (currentlyOver == 0 + && canDoExternalDrag + && ! hasCheckedForExternalDrag) + { + if (Desktop::getInstance().findComponentAt (x, y) == 0) + { + hasCheckedForExternalDrag = true; + StringArray files; + bool canMoveFiles = false; - if (owner->shouldDropFilesWhenDraggedExternally (dragDescLocal, source, files, canMoveFiles) - && files.size() > 0) - { - ComponentDeletionWatcher cdw (this); - setVisible (false); + if (owner->shouldDropFilesWhenDraggedExternally (dragDescLocal, source, files, canMoveFiles) + && files.size() > 0) + { + ComponentDeletionWatcher cdw (this); + setVisible (false); - if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) - DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles); + if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) + DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles); - if (! cdw.hasBeenDeleted()) - delete this; + if (! cdw.hasBeenDeleted()) + delete this; - return; - } - } - } - } - } + return; + } + } + } + } + } - void mouseDrag (const MouseEvent& e) - { - if (e.originalComponent != this) - updateLocation (true, e.getScreenX(), e.getScreenY()); - } + void mouseDrag (const MouseEvent& e) + { + if (e.originalComponent != this) + updateLocation (true, e.getScreenX(), e.getScreenY()); + } - void timerCallback() - { - if (sourceWatcher->hasBeenDeleted()) - { - delete this; - } - else if (! isMouseButtonDownAnywhere()) - { - if (! mouseDragSourceWatcher->hasBeenDeleted()) - mouseDragSource->removeMouseListener (this); + void timerCallback() + { + if (sourceWatcher->hasBeenDeleted()) + { + delete this; + } + else if (! isMouseButtonDownAnywhere()) + { + if (! mouseDragSourceWatcher->hasBeenDeleted()) + mouseDragSource->removeMouseListener (this); - delete this; - } - } + delete this; + } + } }; DragAndDropContainer::DragAndDropContainer() @@ -70526,139 +70223,139 @@ DragAndDropContainer::DragAndDropContainer() DragAndDropContainer::~DragAndDropContainer() { - dragImageComponent = 0; + dragImageComponent = 0; } void DragAndDropContainer::startDragging (const String& sourceDescription, - Component* sourceComponent, - Image* dragImage_, - const bool allowDraggingToExternalWindows, - const Point* imageOffsetFromMouse) + Component* sourceComponent, + Image* dragImage_, + const bool allowDraggingToExternalWindows, + const Point* imageOffsetFromMouse) { - ScopedPointer dragImage (dragImage_); + ScopedPointer dragImage (dragImage_); - if (dragImageComponent == 0) - { - Component* const thisComp = dynamic_cast (this); + if (dragImageComponent == 0) + { + Component* const thisComp = dynamic_cast (this); - if (thisComp != 0) - { - int mx, my; - Desktop::getLastMouseDownPosition (mx, my); - int imageX = 0, imageY = 0; + if (thisComp != 0) + { + int mx, my; + Desktop::getLastMouseDownPosition (mx, my); + int imageX = 0, imageY = 0; - if (dragImage == 0) - { - dragImage = sourceComponent->createComponentSnapshot (Rectangle (0, 0, sourceComponent->getWidth(), sourceComponent->getHeight())); + if (dragImage == 0) + { + dragImage = sourceComponent->createComponentSnapshot (Rectangle (0, 0, sourceComponent->getWidth(), sourceComponent->getHeight())); - if (dragImage->getFormat() != Image::ARGB) - { - Image* newIm = Image::createNativeImage (Image::ARGB, dragImage->getWidth(), dragImage->getHeight(), true); - Graphics g2 (*newIm); - g2.drawImageAt (dragImage, 0, 0); + if (dragImage->getFormat() != Image::ARGB) + { + Image* newIm = Image::createNativeImage (Image::ARGB, dragImage->getWidth(), dragImage->getHeight(), true); + Graphics g2 (*newIm); + g2.drawImageAt (dragImage, 0, 0); - dragImage = newIm; - } + dragImage = newIm; + } - dragImage->multiplyAllAlphas (0.6f); + dragImage->multiplyAllAlphas (0.6f); - const int lo = 150; - const int hi = 400; + const int lo = 150; + const int hi = 400; - int rx = mx, ry = my; - sourceComponent->globalPositionToRelative (rx, ry); - const int cx = jlimit (0, dragImage->getWidth(), rx); - const int cy = jlimit (0, dragImage->getHeight(), ry); + int rx = mx, ry = my; + sourceComponent->globalPositionToRelative (rx, ry); + const int cx = jlimit (0, dragImage->getWidth(), rx); + const int cy = jlimit (0, dragImage->getHeight(), ry); - for (int y = dragImage->getHeight(); --y >= 0;) - { - const double dy = (y - cy) * (y - cy); + for (int y = dragImage->getHeight(); --y >= 0;) + { + const double dy = (y - cy) * (y - cy); - for (int x = dragImage->getWidth(); --x >= 0;) - { - const int dx = x - cx; - const int distance = roundDoubleToInt (sqrt (dx * dx + dy)); + for (int x = dragImage->getWidth(); --x >= 0;) + { + const int dx = x - cx; + const int distance = roundToInt (sqrt (dx * dx + dy)); - if (distance > lo) - { - const float alpha = (distance > hi) ? 0 - : (hi - distance) / (float) (hi - lo) - + Random::getSystemRandom().nextFloat() * 0.008f; + if (distance > lo) + { + const float alpha = (distance > hi) ? 0 + : (hi - distance) / (float) (hi - lo) + + Random::getSystemRandom().nextFloat() * 0.008f; - dragImage->multiplyAlphaAt (x, y, alpha); - } - } - } + dragImage->multiplyAlphaAt (x, y, alpha); + } + } + } - imageX = -cx; - imageY = -cy; - } - else - { - if (imageOffsetFromMouse == 0) - { - imageX = dragImage->getWidth() / -2; - imageY = dragImage->getHeight() / -2; - } - else - { - imageX = (int) imageOffsetFromMouse->getX(); - imageY = (int) imageOffsetFromMouse->getY(); - } - } + imageX = -cx; + imageY = -cy; + } + else + { + if (imageOffsetFromMouse == 0) + { + imageX = dragImage->getWidth() / -2; + imageY = dragImage->getHeight() / -2; + } + else + { + imageX = (int) imageOffsetFromMouse->getX(); + imageY = (int) imageOffsetFromMouse->getY(); + } + } - dragImageComponent = new DragImageComponent (dragImage.release(), sourceDescription, sourceComponent, - this, imageX, imageY); + dragImageComponent = new DragImageComponent (dragImage.release(), sourceDescription, sourceComponent, + this, imageX, imageY); - currentDragDesc = sourceDescription; + currentDragDesc = sourceDescription; - if (allowDraggingToExternalWindows) - { - if (! Desktop::canUseSemiTransparentWindows()) - dragImageComponent->setOpaque (true); + if (allowDraggingToExternalWindows) + { + if (! Desktop::canUseSemiTransparentWindows()) + dragImageComponent->setOpaque (true); - dragImageComponent->addToDesktop (ComponentPeer::windowIgnoresMouseClicks - | ComponentPeer::windowIsTemporary - | ComponentPeer::windowIgnoresKeyPresses); - } - else - thisComp->addChildComponent (dragImageComponent); + dragImageComponent->addToDesktop (ComponentPeer::windowIgnoresMouseClicks + | ComponentPeer::windowIsTemporary + | ComponentPeer::windowIgnoresKeyPresses); + } + else + thisComp->addChildComponent (dragImageComponent); - ((DragImageComponent*) dragImageComponent)->updateLocation (false, mx, my); - dragImageComponent->setVisible (true); - } - else - { - // this class must only be implemented by an object that - // is also a Component. - jassertfalse - } - } + ((DragImageComponent*) dragImageComponent)->updateLocation (false, mx, my); + dragImageComponent->setVisible (true); + } + else + { + // this class must only be implemented by an object that + // is also a Component. + jassertfalse + } + } } bool DragAndDropContainer::isDragAndDropActive() const { - return dragImageComponent != 0; + return dragImageComponent != 0; } const String DragAndDropContainer::getCurrentDragDescription() const { - return (dragImageComponent != 0) ? currentDragDesc - : String::empty; + return (dragImageComponent != 0) ? currentDragDesc + : String::empty; } DragAndDropContainer* DragAndDropContainer::findParentDragContainerFor (Component* c) { - if (c == 0) - return 0; + if (c == 0) + return 0; - // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) - return c->findParentComponentOfClass ((DragAndDropContainer*) 0); + // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) + return c->findParentComponentOfClass ((DragAndDropContainer*) 0); } bool DragAndDropContainer::shouldDropFilesWhenDraggedExternally (const String&, Component*, StringArray&, bool&) { - return false; + return false; } void DragAndDropTarget::itemDragEnter (const String&, Component*, int, int) @@ -70675,7 +70372,7 @@ void DragAndDropTarget::itemDragExit (const String&, Component*) bool DragAndDropTarget::shouldDrawDragImageWhenOver() { - return true; + return true; } void FileDragAndDropTarget::fileDragEnter (const StringArray&, int, int) @@ -70703,80 +70400,80 @@ void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type) thro void juce_deleteMouseCursor (void* const cursorHandle, const bool isStandard) throw(); static CriticalSection activeCursorListLock; -static VoidArray activeCursors (2); +static VoidArray activeCursors; class SharedMouseCursorInternal : public ReferenceCountedObject { public: - SharedMouseCursorInternal (const MouseCursor::StandardCursorType type) throw() - : standardType (type), - isStandard (true) - { - handle = juce_createStandardMouseCursor (standardType); - activeCursors.add (this); - } + SharedMouseCursorInternal (const MouseCursor::StandardCursorType type) throw() + : standardType (type), + isStandard (true) + { + handle = juce_createStandardMouseCursor (standardType); + activeCursors.add (this); + } - SharedMouseCursorInternal (const Image& image, const int hotSpotX, const int hotSpotY) throw() - : standardType (MouseCursor::NormalCursor), - isStandard (false) - { - handle = juce_createMouseCursorFromImage (image, hotSpotX, hotSpotY); - } + SharedMouseCursorInternal (const Image& image, const int hotSpotX, const int hotSpotY) throw() + : standardType (MouseCursor::NormalCursor), + isStandard (false) + { + handle = juce_createMouseCursorFromImage (image, hotSpotX, hotSpotY); + } - ~SharedMouseCursorInternal() throw() - { - juce_deleteMouseCursor (handle, isStandard); - activeCursors.removeValue (this); - } + ~SharedMouseCursorInternal() throw() + { + juce_deleteMouseCursor (handle, isStandard); + activeCursors.removeValue (this); + } - void* getHandle() const throw() - { - return handle; - } + void* getHandle() const throw() + { + return handle; + } - static SharedMouseCursorInternal* findInstance (MouseCursor::StandardCursorType type) throw() - { - for (int i = activeCursors.size(); --i >= 0;) - { - SharedMouseCursorInternal* const r = (SharedMouseCursorInternal*) activeCursors.getUnchecked(i); + static SharedMouseCursorInternal* findInstance (MouseCursor::StandardCursorType type) throw() + { + for (int i = activeCursors.size(); --i >= 0;) + { + SharedMouseCursorInternal* const r = (SharedMouseCursorInternal*) activeCursors.getUnchecked(i); - if (r->standardType == type) - return r; - } + if (r->standardType == type) + return r; + } - return new SharedMouseCursorInternal (type); - } + return new SharedMouseCursorInternal (type); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - void* handle; - const MouseCursor::StandardCursorType standardType; - const bool isStandard; + void* handle; + const MouseCursor::StandardCursorType standardType; + const bool isStandard; - const SharedMouseCursorInternal& operator= (const SharedMouseCursorInternal&); + const SharedMouseCursorInternal& operator= (const SharedMouseCursorInternal&); }; MouseCursor::MouseCursor() throw() { - const ScopedLock sl (activeCursorListLock); - cursorHandle = SharedMouseCursorInternal::findInstance (NormalCursor); + const ScopedLock sl (activeCursorListLock); + cursorHandle = SharedMouseCursorInternal::findInstance (NormalCursor); } MouseCursor::MouseCursor (const StandardCursorType type) throw() { - const ScopedLock sl (activeCursorListLock); - cursorHandle = SharedMouseCursorInternal::findInstance (type); + const ScopedLock sl (activeCursorListLock); + cursorHandle = SharedMouseCursorInternal::findInstance (type); } MouseCursor::MouseCursor (const Image& image, const int hotSpotX, const int hotSpotY) throw() { - const ScopedLock sl (activeCursorListLock); - cursorHandle = new SharedMouseCursorInternal (image, hotSpotX, hotSpotY); + const ScopedLock sl (activeCursorListLock); + cursorHandle = new SharedMouseCursorInternal (image, hotSpotX, hotSpotY); } MouseCursor::MouseCursor (const MouseCursor& other) throw() - : cursorHandle (other.cursorHandle) + : cursorHandle (other.cursorHandle) { } @@ -70786,39 +70483,39 @@ MouseCursor::~MouseCursor() throw() const MouseCursor& MouseCursor::operator= (const MouseCursor& other) throw() { - cursorHandle = other.cursorHandle; - return *this; + cursorHandle = other.cursorHandle; + return *this; } bool MouseCursor::operator== (const MouseCursor& other) const throw() { - return cursorHandle == other.cursorHandle; + return cursorHandle == other.cursorHandle; } bool MouseCursor::operator!= (const MouseCursor& other) const throw() { - return cursorHandle != other.cursorHandle; + return cursorHandle != other.cursorHandle; } void* MouseCursor::getHandle() const throw() { - return cursorHandle->getHandle(); + return cursorHandle->getHandle(); } void MouseCursor::showWaitCursor() throw() { - const MouseCursor mc (MouseCursor::WaitCursor); - mc.showInAllWindows(); + const MouseCursor mc (MouseCursor::WaitCursor); + mc.showInAllWindows(); } void MouseCursor::hideWaitCursor() throw() { - Component* const c = Component::getComponentUnderMouse(); + Component* const c = Component::getComponentUnderMouse(); - MouseCursor mc (c->isValidComponent() ? c->getLookAndFeel().getMouseCursorFor (*c) - : MouseCursor::NormalCursor); + MouseCursor mc (c->isValidComponent() ? c->getLookAndFeel().getMouseCursorFor (*c) + : MouseCursor::NormalCursor); - mc.showInAllWindows(); + mc.showInAllWindows(); } END_JUCE_NAMESPACE @@ -70829,26 +70526,26 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MouseEvent::MouseEvent (const int x_, - const int y_, - const ModifierKeys& mods_, - Component* const originator, - const Time& eventTime_, - const int mouseDownX_, - const int mouseDownY_, - const Time& mouseDownTime_, - const int numberOfClicks_, - const bool mouseWasDragged) throw() - : x (x_), - y (y_), - mods (mods_), - eventComponent (originator), - originalComponent (originator), - eventTime (eventTime_), - mouseDownX (mouseDownX_), - mouseDownY (mouseDownY_), - mouseDownTime (mouseDownTime_), - numberOfClicks (numberOfClicks_), - wasMovedSinceMouseDown (mouseWasDragged) + const int y_, + const ModifierKeys& mods_, + Component* const originator, + const Time& eventTime_, + const int mouseDownX_, + const int mouseDownY_, + const Time& mouseDownTime_, + const int numberOfClicks_, + const bool mouseWasDragged) throw() + : x (x_), + y (y_), + mods (mods_), + eventComponent (originator), + originalComponent (originator), + eventTime (eventTime_), + mouseDownX (mouseDownX_), + mouseDownY (mouseDownY_), + mouseDownTime (mouseDownTime_), + numberOfClicks (numberOfClicks_), + wasMovedSinceMouseDown (mouseWasDragged) { } @@ -70858,98 +70555,98 @@ MouseEvent::~MouseEvent() throw() bool MouseEvent::mouseWasClicked() const throw() { - return ! wasMovedSinceMouseDown; + return ! wasMovedSinceMouseDown; } int MouseEvent::getMouseDownX() const throw() { - return mouseDownX; + return mouseDownX; } int MouseEvent::getMouseDownY() const throw() { - return mouseDownY; + return mouseDownY; } int MouseEvent::getDistanceFromDragStartX() const throw() { - return x - mouseDownX; + return x - mouseDownX; } int MouseEvent::getDistanceFromDragStartY() const throw() { - return y - mouseDownY; + return y - mouseDownY; } int MouseEvent::getDistanceFromDragStart() const throw() { - return roundDoubleToInt (juce_hypot (getDistanceFromDragStartX(), - getDistanceFromDragStartY())); + return roundToInt (juce_hypot (getDistanceFromDragStartX(), + getDistanceFromDragStartY())); } int MouseEvent::getLengthOfMousePress() const throw() { - if (mouseDownTime.toMilliseconds() > 0) - return jmax (0, (int) (eventTime - mouseDownTime).inMilliseconds()); + if (mouseDownTime.toMilliseconds() > 0) + return jmax (0, (int) (eventTime - mouseDownTime).inMilliseconds()); - return 0; + return 0; } int MouseEvent::getScreenX() const throw() { - int sx = x, sy = y; - eventComponent->relativePositionToGlobal (sx, sy); - return sx; + int sx = x, sy = y; + eventComponent->relativePositionToGlobal (sx, sy); + return sx; } int MouseEvent::getScreenY() const throw() { - int sx = x, sy = y; - eventComponent->relativePositionToGlobal (sx, sy); - return sy; + int sx = x, sy = y; + eventComponent->relativePositionToGlobal (sx, sy); + return sy; } int MouseEvent::getMouseDownScreenX() const throw() { - int sx = mouseDownX, sy = mouseDownY; - eventComponent->relativePositionToGlobal (sx, sy); - return sx; + int sx = mouseDownX, sy = mouseDownY; + eventComponent->relativePositionToGlobal (sx, sy); + return sx; } int MouseEvent::getMouseDownScreenY() const throw() { - int sx = mouseDownX, sy = mouseDownY; - eventComponent->relativePositionToGlobal (sx, sy); - return sy; + int sx = mouseDownX, sy = mouseDownY; + eventComponent->relativePositionToGlobal (sx, sy); + return sy; } const MouseEvent MouseEvent::getEventRelativeTo (Component* const otherComponent) const throw() { - if (otherComponent == 0) - { - jassertfalse - return *this; - } + if (otherComponent == 0) + { + jassertfalse + return *this; + } - MouseEvent me (*this); + MouseEvent me (*this); - eventComponent->relativePositionToOtherComponent (otherComponent, me.x, me.y); - eventComponent->relativePositionToOtherComponent (otherComponent, me.mouseDownX, me.mouseDownY); - me.eventComponent = otherComponent; + eventComponent->relativePositionToOtherComponent (otherComponent, me.x, me.y); + eventComponent->relativePositionToOtherComponent (otherComponent, me.mouseDownX, me.mouseDownY); + me.eventComponent = otherComponent; - return me; + return me; } static int doubleClickTimeOutMs = 400; void MouseEvent::setDoubleClickTimeout (const int newTime) throw() { - doubleClickTimeOutMs = newTime; + doubleClickTimeOutMs = newTime; } int MouseEvent::getDoubleClickTimeout() throw() { - return doubleClickTimeOutMs; + return doubleClickTimeOutMs; } END_JUCE_NAMESPACE @@ -70960,118 +70657,118 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE MouseHoverDetector::MouseHoverDetector (const int hoverTimeMillisecs_) - : source (0), - hoverTimeMillisecs (hoverTimeMillisecs_), - hasJustHovered (false) + : source (0), + hoverTimeMillisecs (hoverTimeMillisecs_), + hasJustHovered (false) { - internalTimer.owner = this; + internalTimer.owner = this; } MouseHoverDetector::~MouseHoverDetector() { - setHoverComponent (0); + setHoverComponent (0); } void MouseHoverDetector::setHoverTimeMillisecs (const int newTimeInMillisecs) { - hoverTimeMillisecs = newTimeInMillisecs; + hoverTimeMillisecs = newTimeInMillisecs; } void MouseHoverDetector::setHoverComponent (Component* const newSourceComponent) { - if (source != newSourceComponent) - { - internalTimer.stopTimer(); - hasJustHovered = false; + if (source != newSourceComponent) + { + internalTimer.stopTimer(); + hasJustHovered = false; - if (source != 0) - { - // ! you need to delete the hover detector before deleting its component - jassert (source->isValidComponent()); + if (source != 0) + { + // ! you need to delete the hover detector before deleting its component + jassert (source->isValidComponent()); - source->removeMouseListener (&internalTimer); - } + source->removeMouseListener (&internalTimer); + } - source = newSourceComponent; + source = newSourceComponent; - if (newSourceComponent != 0) - newSourceComponent->addMouseListener (&internalTimer, false); - } + if (newSourceComponent != 0) + newSourceComponent->addMouseListener (&internalTimer, false); + } } void MouseHoverDetector::hoverTimerCallback() { - internalTimer.stopTimer(); + internalTimer.stopTimer(); - if (source != 0) - { - int mx, my; - source->getMouseXYRelative (mx, my); + if (source != 0) + { + int mx, my; + source->getMouseXYRelative (mx, my); - if (source->reallyContains (mx, my, false)) - { - hasJustHovered = true; - mouseHovered (mx, my); - } - } + if (source->reallyContains (mx, my, false)) + { + hasJustHovered = true; + mouseHovered (mx, my); + } + } } void MouseHoverDetector::checkJustHoveredCallback() { - if (hasJustHovered) - { - hasJustHovered = false; - mouseMovedAfterHover(); - } + if (hasJustHovered) + { + hasJustHovered = false; + mouseMovedAfterHover(); + } } void MouseHoverDetector::HoverDetectorInternal::timerCallback() { - owner->hoverTimerCallback(); + owner->hoverTimerCallback(); } void MouseHoverDetector::HoverDetectorInternal::mouseEnter (const MouseEvent&) { - stopTimer(); - owner->checkJustHoveredCallback(); + stopTimer(); + owner->checkJustHoveredCallback(); } void MouseHoverDetector::HoverDetectorInternal::mouseExit (const MouseEvent&) { - stopTimer(); - owner->checkJustHoveredCallback(); + stopTimer(); + owner->checkJustHoveredCallback(); } void MouseHoverDetector::HoverDetectorInternal::mouseDown (const MouseEvent&) { - stopTimer(); - owner->checkJustHoveredCallback(); + stopTimer(); + owner->checkJustHoveredCallback(); } void MouseHoverDetector::HoverDetectorInternal::mouseUp (const MouseEvent&) { - stopTimer(); - owner->checkJustHoveredCallback(); + stopTimer(); + owner->checkJustHoveredCallback(); } void MouseHoverDetector::HoverDetectorInternal::mouseMove (const MouseEvent& e) { - if (lastX != e.x || lastY != e.y) // to avoid fake mouse-moves setting it off - { - lastX = e.x; - lastY = e.y; + if (lastX != e.x || lastY != e.y) // to avoid fake mouse-moves setting it off + { + lastX = e.x; + lastY = e.y; - if (owner->source != 0) - startTimer (owner->hoverTimeMillisecs); + if (owner->source != 0) + startTimer (owner->hoverTimeMillisecs); - owner->checkJustHoveredCallback(); - } + owner->checkJustHoveredCallback(); + } } void MouseHoverDetector::HoverDetectorInternal::mouseWheelMove (const MouseEvent&, float, float) { - stopTimer(); - owner->checkJustHoveredCallback(); + stopTimer(); + owner->checkJustHoveredCallback(); } END_JUCE_NAMESPACE @@ -71121,43 +70818,69 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE BooleanPropertyComponent::BooleanPropertyComponent (const String& name, - const String& buttonTextWhenTrue, - const String& buttonTextWhenFalse) - : PropertyComponent (name), - onText (buttonTextWhenTrue), - offText (buttonTextWhenFalse) + const String& buttonTextWhenTrue, + const String& buttonTextWhenFalse) + : PropertyComponent (name), + onText (buttonTextWhenTrue), + offText (buttonTextWhenFalse) { - addAndMakeVisible (button = new ToggleButton (String::empty)); - button->setClickingTogglesState (false); - button->addButtonListener (this); + createButton(); + button->addButtonListener (this); +} + +BooleanPropertyComponent::BooleanPropertyComponent (const Value& valueToControl, + const String& name, + const String& buttonText) + : PropertyComponent (name) +{ + createButton(); + button->setButtonText (buttonText); + button->getToggleStateValue().referTo (valueToControl); + button->setClickingTogglesState (true); } BooleanPropertyComponent::~BooleanPropertyComponent() { - deleteAllChildren(); + deleteAllChildren(); +} + +void BooleanPropertyComponent::createButton() +{ + addAndMakeVisible (button = new ToggleButton (String::empty)); + button->setClickingTogglesState (false); +} + +void BooleanPropertyComponent::setState (const bool newState) +{ + button->setToggleState (newState, true); +} + +bool BooleanPropertyComponent::getState() const +{ + return button->getToggleState(); } void BooleanPropertyComponent::paint (Graphics& g) { - PropertyComponent::paint (g); + PropertyComponent::paint (g); - const Rectangle r (button->getBounds()); - g.setColour (Colours::white); - g.fillRect (r); + const Rectangle r (button->getBounds()); + g.setColour (Colours::white); + g.fillRect (r); - g.setColour (findColour (ComboBox::outlineColourId)); - g.drawRect (r.getX(), r.getY(), r.getWidth(), r.getHeight()); + g.setColour (findColour (ComboBox::outlineColourId)); + g.drawRect (r.getX(), r.getY(), r.getWidth(), r.getHeight()); } void BooleanPropertyComponent::refresh() { - button->setToggleState (getState(), false); - button->setButtonText (button->getToggleState() ? onText : offText); + button->setToggleState (getState(), false); + button->setButtonText (button->getToggleState() ? onText : offText); } void BooleanPropertyComponent::buttonClicked (Button*) { - setState (! getState()); + setState (! getState()); } END_JUCE_NAMESPACE @@ -71168,27 +70891,27 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ButtonPropertyComponent::ButtonPropertyComponent (const String& name, - const bool triggerOnMouseDown) - : PropertyComponent (name) + const bool triggerOnMouseDown) + : PropertyComponent (name) { - addAndMakeVisible (button = new TextButton (String::empty)); - button->setTriggeredOnMouseDown (triggerOnMouseDown); - button->addButtonListener (this); + addAndMakeVisible (button = new TextButton (String::empty)); + button->setTriggeredOnMouseDown (triggerOnMouseDown); + button->addButtonListener (this); } ButtonPropertyComponent::~ButtonPropertyComponent() { - deleteAllChildren(); + deleteAllChildren(); } void ButtonPropertyComponent::refresh() { - button->setButtonText (getButtonText()); + button->setButtonText (getButtonText()); } void ButtonPropertyComponent::buttonClicked (Button*) { - buttonClicked(); + buttonClicked(); } END_JUCE_NAMESPACE @@ -71199,48 +70922,75 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ChoicePropertyComponent::ChoicePropertyComponent (const String& name) - : PropertyComponent (name), - comboBox (0) + : PropertyComponent (name), + comboBox (0) { } +ChoicePropertyComponent::ChoicePropertyComponent (const Value& valueToControl, + const String& name, + const StringArray& choices_) + : PropertyComponent (name), + choices (choices_), + comboBox (0) +{ + createComboBox(); + + comboBox->getSelectedIdAsValue().referTo (valueToControl); +} + ChoicePropertyComponent::~ChoicePropertyComponent() { - deleteAllChildren(); + deleteAllChildren(); +} + +void ChoicePropertyComponent::createComboBox() +{ + addAndMakeVisible (comboBox = new ComboBox (String::empty)); + + for (int i = 0; i < choices.size(); ++i) + { + if (choices[i].isNotEmpty()) + comboBox->addItem (choices[i], i + 1); + else + comboBox->addSeparator(); + } + + comboBox->setEditableText (false); +} + +void ChoicePropertyComponent::setIndex (const int newIndex) +{ + comboBox->setSelectedId (comboBox->getItemId (newIndex)); +} + +int ChoicePropertyComponent::getIndex() const +{ + return comboBox->getSelectedItemIndex(); } const StringArray& ChoicePropertyComponent::getChoices() const { - return choices; + return choices; } void ChoicePropertyComponent::refresh() { - if (comboBox == 0) - { - addAndMakeVisible (comboBox = new ComboBox (String::empty)); + if (comboBox == 0) + { + createComboBox(); + comboBox->addListener (this); + } - for (int i = 0; i < choices.size(); ++i) - { - if (choices[i].isNotEmpty()) - comboBox->addItem (choices[i], i + 1); - else - comboBox->addSeparator(); - } - - comboBox->setEditableText (false); - comboBox->addListener (this); - } - - comboBox->setSelectedId (getIndex() + 1, true); + comboBox->setSelectedId (getIndex() + 1, true); } void ChoicePropertyComponent::comboBoxChanged (ComboBox*) { - const int newIndex = comboBox->getSelectedId() - 1; + const int newIndex = comboBox->getSelectedId() - 1; - if (newIndex != getIndex()) - setIndex (newIndex); + if (newIndex != getIndex()) + setIndex (newIndex); } END_JUCE_NAMESPACE @@ -71251,11 +71001,11 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE PropertyComponent::PropertyComponent (const String& name, - const int preferredHeight_) - : Component (name), - preferredHeight (preferredHeight_) + const int preferredHeight_) + : Component (name), + preferredHeight (preferredHeight_) { - jassert (name.isNotEmpty()); + jassert (name.isNotEmpty()); } PropertyComponent::~PropertyComponent() @@ -71264,19 +71014,19 @@ PropertyComponent::~PropertyComponent() void PropertyComponent::paint (Graphics& g) { - getLookAndFeel().drawPropertyComponentBackground (g, getWidth(), getHeight(), *this); - getLookAndFeel().drawPropertyComponentLabel (g, getWidth(), getHeight(), *this); + getLookAndFeel().drawPropertyComponentBackground (g, getWidth(), getHeight(), *this); + getLookAndFeel().drawPropertyComponentLabel (g, getWidth(), getHeight(), *this); } void PropertyComponent::resized() { - if (getNumChildComponents() > 0) - getChildComponent (0)->setBounds (getLookAndFeel().getPropertyComponentContentPosition (*this)); + if (getNumChildComponents() > 0) + getChildComponent (0)->setBounds (getLookAndFeel().getPropertyComponentContentPosition (*this)); } void PropertyComponent::enablementChanged() { - repaint(); + repaint(); } END_JUCE_NAMESPACE @@ -71289,393 +71039,393 @@ BEGIN_JUCE_NAMESPACE class PropertyHolderComponent : public Component { public: - PropertyHolderComponent() - { - } + PropertyHolderComponent() + { + } - ~PropertyHolderComponent() - { - deleteAllChildren(); - } + ~PropertyHolderComponent() + { + deleteAllChildren(); + } - void paint (Graphics&) - { - } + void paint (Graphics&) + { + } - void updateLayout (const int width); + void updateLayout (const int width); - void refreshAll() const; + void refreshAll() const; }; class PropertySectionComponent : public Component { public: - PropertySectionComponent (const String& sectionTitle, - const Array & newProperties, - const bool open) - : Component (sectionTitle), - titleHeight (sectionTitle.isNotEmpty() ? 22 : 0), - isOpen_ (open) - { - for (int i = newProperties.size(); --i >= 0;) - { - addAndMakeVisible (newProperties.getUnchecked(i)); - newProperties.getUnchecked(i)->refresh(); - } - } + PropertySectionComponent (const String& sectionTitle, + const Array & newProperties, + const bool open) + : Component (sectionTitle), + titleHeight (sectionTitle.isNotEmpty() ? 22 : 0), + isOpen_ (open) + { + for (int i = newProperties.size(); --i >= 0;) + { + addAndMakeVisible (newProperties.getUnchecked(i)); + newProperties.getUnchecked(i)->refresh(); + } + } - ~PropertySectionComponent() - { - deleteAllChildren(); - } + ~PropertySectionComponent() + { + deleteAllChildren(); + } - void paint (Graphics& g) - { - if (titleHeight > 0) - getLookAndFeel().drawPropertyPanelSectionHeader (g, getName(), isOpen(), getWidth(), titleHeight); - } + void paint (Graphics& g) + { + if (titleHeight > 0) + getLookAndFeel().drawPropertyPanelSectionHeader (g, getName(), isOpen(), getWidth(), titleHeight); + } - void resized() - { - int y = titleHeight; + void resized() + { + int y = titleHeight; - for (int i = getNumChildComponents(); --i >= 0;) - { - PropertyComponent* const pec = dynamic_cast (getChildComponent (i)); + for (int i = getNumChildComponents(); --i >= 0;) + { + PropertyComponent* const pec = dynamic_cast (getChildComponent (i)); - if (pec != 0) - { - const int prefH = pec->getPreferredHeight(); - pec->setBounds (1, y, getWidth() - 2, prefH); - y += prefH; - } - } - } + if (pec != 0) + { + const int prefH = pec->getPreferredHeight(); + pec->setBounds (1, y, getWidth() - 2, prefH); + y += prefH; + } + } + } - int getPreferredHeight() const - { - int y = titleHeight; + int getPreferredHeight() const + { + int y = titleHeight; - if (isOpen()) - { - for (int i = 0; i < getNumChildComponents(); ++i) - { - PropertyComponent* pec = dynamic_cast (getChildComponent (i)); + if (isOpen()) + { + for (int i = 0; i < getNumChildComponents(); ++i) + { + PropertyComponent* pec = dynamic_cast (getChildComponent (i)); - if (pec != 0) - y += pec->getPreferredHeight(); - } - } + if (pec != 0) + y += pec->getPreferredHeight(); + } + } - return y; - } + return y; + } - void setOpen (const bool open) - { - if (isOpen_ != open) - { - isOpen_ = open; + void setOpen (const bool open) + { + if (isOpen_ != open) + { + isOpen_ = open; - for (int i = 0; i < getNumChildComponents(); ++i) - { - PropertyComponent* pec = dynamic_cast (getChildComponent (i)); + for (int i = 0; i < getNumChildComponents(); ++i) + { + PropertyComponent* pec = dynamic_cast (getChildComponent (i)); - if (pec != 0) - pec->setVisible (open); - } + if (pec != 0) + pec->setVisible (open); + } - // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) - PropertyPanel* const pp = findParentComponentOfClass ((PropertyPanel*) 0); + // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) + PropertyPanel* const pp = findParentComponentOfClass ((PropertyPanel*) 0); - if (pp != 0) - pp->resized(); - } - } + if (pp != 0) + pp->resized(); + } + } - bool isOpen() const - { - return isOpen_; - } + bool isOpen() const + { + return isOpen_; + } - void refreshAll() const - { - for (int i = 0; i < getNumChildComponents(); ++i) - { - PropertyComponent* pec = dynamic_cast (getChildComponent (i)); + void refreshAll() const + { + for (int i = 0; i < getNumChildComponents(); ++i) + { + PropertyComponent* pec = dynamic_cast (getChildComponent (i)); - if (pec != 0) - pec->refresh(); - } - } + if (pec != 0) + pec->refresh(); + } + } - void mouseDown (const MouseEvent&) - { - } + void mouseDown (const MouseEvent&) + { + } - void mouseUp (const MouseEvent& e) - { - if (e.getMouseDownX() < titleHeight - && e.x < titleHeight - && e.y < titleHeight - && e.getNumberOfClicks() != 2) - { - setOpen (! isOpen()); - } - } + void mouseUp (const MouseEvent& e) + { + if (e.getMouseDownX() < titleHeight + && e.x < titleHeight + && e.y < titleHeight + && e.getNumberOfClicks() != 2) + { + setOpen (! isOpen()); + } + } - void mouseDoubleClick (const MouseEvent& e) - { - if (e.y < titleHeight) - setOpen (! isOpen()); - } + void mouseDoubleClick (const MouseEvent& e) + { + if (e.y < titleHeight) + setOpen (! isOpen()); + } private: - int titleHeight; - bool isOpen_; + int titleHeight; + bool isOpen_; }; void PropertyHolderComponent::updateLayout (const int width) { - int y = 0; + int y = 0; - for (int i = getNumChildComponents(); --i >= 0;) - { - PropertySectionComponent* const section - = dynamic_cast (getChildComponent (i)); + for (int i = getNumChildComponents(); --i >= 0;) + { + PropertySectionComponent* const section + = dynamic_cast (getChildComponent (i)); - if (section != 0) - { - const int prefH = section->getPreferredHeight(); - section->setBounds (0, y, width, prefH); - y += prefH; - } - } + if (section != 0) + { + const int prefH = section->getPreferredHeight(); + section->setBounds (0, y, width, prefH); + y += prefH; + } + } - setSize (width, y); - repaint(); + setSize (width, y); + repaint(); } void PropertyHolderComponent::refreshAll() const { - for (int i = getNumChildComponents(); --i >= 0;) - { - PropertySectionComponent* const section - = dynamic_cast (getChildComponent (i)); + for (int i = getNumChildComponents(); --i >= 0;) + { + PropertySectionComponent* const section + = dynamic_cast (getChildComponent (i)); - if (section != 0) - section->refreshAll(); - } + if (section != 0) + section->refreshAll(); + } } PropertyPanel::PropertyPanel() { - messageWhenEmpty = TRANS("(nothing selected)"); + messageWhenEmpty = TRANS("(nothing selected)"); - addAndMakeVisible (viewport = new Viewport()); - viewport->setViewedComponent (propertyHolderComponent = new PropertyHolderComponent()); - viewport->setFocusContainer (true); + addAndMakeVisible (viewport = new Viewport()); + viewport->setViewedComponent (propertyHolderComponent = new PropertyHolderComponent()); + viewport->setFocusContainer (true); } PropertyPanel::~PropertyPanel() { - clear(); - deleteAllChildren(); + clear(); + deleteAllChildren(); } void PropertyPanel::paint (Graphics& g) { - if (propertyHolderComponent->getNumChildComponents() == 0) - { - g.setColour (Colours::black.withAlpha (0.5f)); - g.setFont (14.0f); - g.drawText (messageWhenEmpty, 0, 0, getWidth(), 30, - Justification::centred, true); - } + if (propertyHolderComponent->getNumChildComponents() == 0) + { + g.setColour (Colours::black.withAlpha (0.5f)); + g.setFont (14.0f); + g.drawText (messageWhenEmpty, 0, 0, getWidth(), 30, + Justification::centred, true); + } } void PropertyPanel::resized() { - viewport->setBounds (0, 0, getWidth(), getHeight()); - updatePropHolderLayout(); + viewport->setBounds (0, 0, getWidth(), getHeight()); + updatePropHolderLayout(); } void PropertyPanel::clear() { - if (propertyHolderComponent->getNumChildComponents() > 0) - { - propertyHolderComponent->deleteAllChildren(); - repaint(); - } + if (propertyHolderComponent->getNumChildComponents() > 0) + { + propertyHolderComponent->deleteAllChildren(); + repaint(); + } } void PropertyPanel::addProperties (const Array & newProperties) { - if (propertyHolderComponent->getNumChildComponents() == 0) - repaint(); + if (propertyHolderComponent->getNumChildComponents() == 0) + repaint(); - propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (String::empty, - newProperties, - true), 0); - updatePropHolderLayout(); + propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (String::empty, + newProperties, + true), 0); + updatePropHolderLayout(); } void PropertyPanel::addSection (const String& sectionTitle, - const Array & newProperties, - const bool shouldBeOpen) + const Array & newProperties, + const bool shouldBeOpen) { - jassert (sectionTitle.isNotEmpty()); + jassert (sectionTitle.isNotEmpty()); - if (propertyHolderComponent->getNumChildComponents() == 0) - repaint(); + if (propertyHolderComponent->getNumChildComponents() == 0) + repaint(); - propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (sectionTitle, - newProperties, - shouldBeOpen), 0); + propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (sectionTitle, + newProperties, + shouldBeOpen), 0); - updatePropHolderLayout(); + updatePropHolderLayout(); } void PropertyPanel::updatePropHolderLayout() const { - const int maxWidth = viewport->getMaximumVisibleWidth(); - ((PropertyHolderComponent*) propertyHolderComponent)->updateLayout (maxWidth); + const int maxWidth = viewport->getMaximumVisibleWidth(); + ((PropertyHolderComponent*) propertyHolderComponent)->updateLayout (maxWidth); - const int newMaxWidth = viewport->getMaximumVisibleWidth(); - if (maxWidth != newMaxWidth) - { - // need to do this twice because of scrollbars changing the size, etc. - ((PropertyHolderComponent*) propertyHolderComponent)->updateLayout (newMaxWidth); - } + const int newMaxWidth = viewport->getMaximumVisibleWidth(); + if (maxWidth != newMaxWidth) + { + // need to do this twice because of scrollbars changing the size, etc. + ((PropertyHolderComponent*) propertyHolderComponent)->updateLayout (newMaxWidth); + } } void PropertyPanel::refreshAll() const { - ((PropertyHolderComponent*) propertyHolderComponent)->refreshAll(); + ((PropertyHolderComponent*) propertyHolderComponent)->refreshAll(); } const StringArray PropertyPanel::getSectionNames() const { - StringArray s; + StringArray s; - for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i) - { - PropertySectionComponent* const section = dynamic_cast (propertyHolderComponent->getChildComponent (i)); + for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i) + { + PropertySectionComponent* const section = dynamic_cast (propertyHolderComponent->getChildComponent (i)); - if (section != 0 && section->getName().isNotEmpty()) - s.add (section->getName()); - } + if (section != 0 && section->getName().isNotEmpty()) + s.add (section->getName()); + } - return s; + return s; } bool PropertyPanel::isSectionOpen (const int sectionIndex) const { - int index = 0; + int index = 0; - for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i) - { - PropertySectionComponent* const section = dynamic_cast (propertyHolderComponent->getChildComponent (i)); + for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i) + { + PropertySectionComponent* const section = dynamic_cast (propertyHolderComponent->getChildComponent (i)); - if (section != 0 && section->getName().isNotEmpty()) - { - if (index == sectionIndex) - return section->isOpen(); + if (section != 0 && section->getName().isNotEmpty()) + { + if (index == sectionIndex) + return section->isOpen(); - ++index; - } - } + ++index; + } + } - return false; + return false; } void PropertyPanel::setSectionOpen (const int sectionIndex, const bool shouldBeOpen) { - int index = 0; + int index = 0; - for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i) - { - PropertySectionComponent* const section = dynamic_cast (propertyHolderComponent->getChildComponent (i)); + for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i) + { + PropertySectionComponent* const section = dynamic_cast (propertyHolderComponent->getChildComponent (i)); - if (section != 0 && section->getName().isNotEmpty()) - { - if (index == sectionIndex) - { - section->setOpen (shouldBeOpen); - break; - } + if (section != 0 && section->getName().isNotEmpty()) + { + if (index == sectionIndex) + { + section->setOpen (shouldBeOpen); + break; + } - ++index; - } - } + ++index; + } + } } void PropertyPanel::setSectionEnabled (const int sectionIndex, const bool shouldBeEnabled) { - int index = 0; + int index = 0; - for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i) - { - PropertySectionComponent* const section = dynamic_cast (propertyHolderComponent->getChildComponent (i)); + for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i) + { + PropertySectionComponent* const section = dynamic_cast (propertyHolderComponent->getChildComponent (i)); - if (section != 0 && section->getName().isNotEmpty()) - { - if (index == sectionIndex) - { - section->setEnabled (shouldBeEnabled); - break; - } + if (section != 0 && section->getName().isNotEmpty()) + { + if (index == sectionIndex) + { + section->setEnabled (shouldBeEnabled); + break; + } - ++index; - } - } + ++index; + } + } } XmlElement* PropertyPanel::getOpennessState() const { - XmlElement* const xml = new XmlElement (T("PROPERTYPANELSTATE")); + XmlElement* const xml = new XmlElement (T("PROPERTYPANELSTATE")); - const StringArray sections (getSectionNames()); + const StringArray sections (getSectionNames()); - for (int i = 0; i < sections.size(); ++i) - { - if (sections[i].isNotEmpty()) - { - XmlElement* const e = new XmlElement (T("SECTION")); - e->setAttribute (T("name"), sections[i]); - e->setAttribute (T("open"), isSectionOpen (i) ? 1 : 0); - xml->addChildElement (e); - } - } + for (int i = 0; i < sections.size(); ++i) + { + if (sections[i].isNotEmpty()) + { + XmlElement* const e = new XmlElement (T("SECTION")); + e->setAttribute (T("name"), sections[i]); + e->setAttribute (T("open"), isSectionOpen (i) ? 1 : 0); + xml->addChildElement (e); + } + } - return xml; + return xml; } void PropertyPanel::restoreOpennessState (const XmlElement& xml) { - if (xml.hasTagName (T("PROPERTYPANELSTATE"))) - { - const StringArray sections (getSectionNames()); + if (xml.hasTagName (T("PROPERTYPANELSTATE"))) + { + const StringArray sections (getSectionNames()); - forEachXmlChildElementWithTagName (xml, e, T("SECTION")) - { - setSectionOpen (sections.indexOf (e->getStringAttribute (T("name"))), - e->getBoolAttribute (T("open"))); - } - } + forEachXmlChildElementWithTagName (xml, e, T("SECTION")) + { + setSectionOpen (sections.indexOf (e->getStringAttribute (T("name"))), + e->getBoolAttribute (T("open"))); + } + } } void PropertyPanel::setMessageWhenEmpty (const String& newMessage) { - if (messageWhenEmpty != newMessage) - { - messageWhenEmpty = newMessage; - repaint(); - } + if (messageWhenEmpty != newMessage) + { + messageWhenEmpty = newMessage; + repaint(); + } } const String& PropertyPanel::getMessageWhenEmpty() const { - return messageWhenEmpty; + return messageWhenEmpty; } END_JUCE_NAMESPACE @@ -71686,35 +71436,61 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE SliderPropertyComponent::SliderPropertyComponent (const String& name, - const double rangeMin, - const double rangeMax, - const double interval, - const double skewFactor) - : PropertyComponent (name) + const double rangeMin, + const double rangeMax, + const double interval, + const double skewFactor) + : PropertyComponent (name) { - addAndMakeVisible (slider = new Slider (name)); + addAndMakeVisible (slider = new Slider (name)); - slider->setRange (rangeMin, rangeMax, interval); - slider->setSkewFactor (skewFactor); - slider->setSliderStyle (Slider::LinearBar); + slider->setRange (rangeMin, rangeMax, interval); + slider->setSkewFactor (skewFactor); + slider->setSliderStyle (Slider::LinearBar); - slider->addListener (this); + slider->addListener (this); +} + +SliderPropertyComponent::SliderPropertyComponent (Value& valueToControl, + const String& name, + const double rangeMin, + const double rangeMax, + const double interval, + const double skewFactor) + : PropertyComponent (name) +{ + addAndMakeVisible (slider = new Slider (name)); + + slider->setRange (rangeMin, rangeMax, interval); + slider->setSkewFactor (skewFactor); + slider->setSliderStyle (Slider::LinearBar); + + slider->getValueObject().referTo (valueToControl); } SliderPropertyComponent::~SliderPropertyComponent() { - deleteAllChildren(); + deleteAllChildren(); +} + +void SliderPropertyComponent::setValue (const double newValue) +{ +} + +const double SliderPropertyComponent::getValue() const +{ + return slider->getValue(); } void SliderPropertyComponent::refresh() { - slider->setValue (getValue(), false); + slider->setValue (getValue(), false); } void SliderPropertyComponent::sliderValueChanged (Slider*) { - if (getValue() != slider->getValue()) - setValue (slider->getValue()); + if (getValue() != slider->getValue()) + setValue (slider->getValue()); } END_JUCE_NAMESPACE @@ -71726,79 +71502,105 @@ BEGIN_JUCE_NAMESPACE class TextPropLabel : public Label { - TextPropertyComponent& owner; - int maxChars; - bool isMultiline; + TextPropertyComponent& owner; + int maxChars; + bool isMultiline; public: - TextPropLabel (TextPropertyComponent& owner_, - const int maxChars_, const bool isMultiline_) - : Label (String::empty, String::empty), - owner (owner_), - maxChars (maxChars_), - isMultiline (isMultiline_) - { - setEditable (true, true, false); + TextPropLabel (TextPropertyComponent& owner_, + const int maxChars_, const bool isMultiline_) + : Label (String::empty, String::empty), + owner (owner_), + maxChars (maxChars_), + isMultiline (isMultiline_) + { + setEditable (true, true, false); - setColour (backgroundColourId, Colours::white); - setColour (outlineColourId, findColour (ComboBox::outlineColourId)); - } + setColour (backgroundColourId, Colours::white); + setColour (outlineColourId, findColour (ComboBox::outlineColourId)); + } - ~TextPropLabel() - { - } + ~TextPropLabel() + { + } - TextEditor* createEditorComponent() - { - TextEditor* const textEditor = Label::createEditorComponent(); + TextEditor* createEditorComponent() + { + TextEditor* const textEditor = Label::createEditorComponent(); - textEditor->setInputRestrictions (maxChars); + textEditor->setInputRestrictions (maxChars); - if (isMultiline) - { - textEditor->setMultiLine (true, true); - textEditor->setReturnKeyStartsNewLine (true); - } + if (isMultiline) + { + textEditor->setMultiLine (true, true); + textEditor->setReturnKeyStartsNewLine (true); + } - return textEditor; - } + return textEditor; + } - void textWasEdited() - { - owner.textWasEdited(); - } + void textWasEdited() + { + owner.textWasEdited(); + } }; TextPropertyComponent::TextPropertyComponent (const String& name, - const int maxNumChars, - const bool isMultiLine) - : PropertyComponent (name) + const int maxNumChars, + const bool isMultiLine) + : PropertyComponent (name) { - addAndMakeVisible (textEditor = new TextPropLabel (*this, maxNumChars, isMultiLine)); + createEditor (maxNumChars, isMultiLine); +} - if (isMultiLine) - { - textEditor->setJustificationType (Justification::topLeft); - preferredHeight = 120; - } +TextPropertyComponent::TextPropertyComponent (const Value& valueToControl, + const String& name, + const int maxNumChars, + const bool isMultiLine) + : PropertyComponent (name) +{ + createEditor (maxNumChars, isMultiLine); + + textEditor->getTextValue().referTo (valueToControl); } TextPropertyComponent::~TextPropertyComponent() { - deleteAllChildren(); + deleteAllChildren(); +} + +void TextPropertyComponent::setText (const String& newText) +{ + textEditor->setText (newText, true); +} + +const String TextPropertyComponent::getText() const +{ + return textEditor->getText(); +} + +void TextPropertyComponent::createEditor (const int maxNumChars, const bool isMultiLine) +{ + addAndMakeVisible (textEditor = new TextPropLabel (*this, maxNumChars, isMultiLine)); + + if (isMultiLine) + { + textEditor->setJustificationType (Justification::topLeft); + preferredHeight = 120; + } } void TextPropertyComponent::refresh() { - textEditor->setText (getText(), false); + textEditor->setText (getText(), false); } void TextPropertyComponent::textWasEdited() { - const String newText (textEditor->getText()); + const String newText (textEditor->getText()); - if (getText() != newText) - setText (newText); + if (getText() != newText) + setText (newText); } END_JUCE_NAMESPACE @@ -71809,1118 +71611,1121 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE class SimpleDeviceManagerInputLevelMeter : public Component, - public Timer + public Timer { public: - SimpleDeviceManagerInputLevelMeter (AudioDeviceManager* const manager_) - : manager (manager_), - level (0) - { - startTimer (50); - manager->enableInputLevelMeasurement (true); - } + SimpleDeviceManagerInputLevelMeter (AudioDeviceManager* const manager_) + : manager (manager_), + level (0) + { + startTimer (50); + manager->enableInputLevelMeasurement (true); + } - ~SimpleDeviceManagerInputLevelMeter() - { - manager->enableInputLevelMeasurement (false); - } + ~SimpleDeviceManagerInputLevelMeter() + { + manager->enableInputLevelMeasurement (false); + } - void timerCallback() - { - const float newLevel = (float) manager->getCurrentInputLevel(); + void timerCallback() + { + const float newLevel = (float) manager->getCurrentInputLevel(); - if (fabsf (level - newLevel) > 0.005f) - { - level = newLevel; - repaint(); - } - } + if (fabsf (level - newLevel) > 0.005f) + { + level = newLevel; + repaint(); + } + } - void paint (Graphics& g) - { - getLookAndFeel().drawLevelMeter (g, getWidth(), getHeight(), - (float) exp (log (level) / 3.0)); // (add a bit of a skew to make the level more obvious) - } + void paint (Graphics& g) + { + getLookAndFeel().drawLevelMeter (g, getWidth(), getHeight(), + (float) exp (log (level) / 3.0)); // (add a bit of a skew to make the level more obvious) + } private: - AudioDeviceManager* const manager; - float level; + AudioDeviceManager* const manager; + float level; }; class MidiInputSelectorComponentListBox : public ListBox, - public ListBoxModel + public ListBoxModel { public: - MidiInputSelectorComponentListBox (AudioDeviceManager& deviceManager_, - const String& noItemsMessage_, - const int minNumber_, - const int maxNumber_) - : ListBox (String::empty, 0), - deviceManager (deviceManager_), - noItemsMessage (noItemsMessage_), - minNumber (minNumber_), - maxNumber (maxNumber_) - { - items = MidiInput::getDevices(); + MidiInputSelectorComponentListBox (AudioDeviceManager& deviceManager_, + const String& noItemsMessage_, + const int minNumber_, + const int maxNumber_) + : ListBox (String::empty, 0), + deviceManager (deviceManager_), + noItemsMessage (noItemsMessage_), + minNumber (minNumber_), + maxNumber (maxNumber_) + { + items = MidiInput::getDevices(); - setModel (this); - setOutlineThickness (1); - } + setModel (this); + setOutlineThickness (1); + } - ~MidiInputSelectorComponentListBox() - { - } + ~MidiInputSelectorComponentListBox() + { + } - int getNumRows() - { - return items.size(); - } + int getNumRows() + { + return items.size(); + } - void paintListBoxItem (int row, - Graphics& g, - int width, int height, - bool rowIsSelected) - { - if (((unsigned int) row) < (unsigned int) items.size()) - { - if (rowIsSelected) - g.fillAll (findColour (TextEditor::highlightColourId) - .withMultipliedAlpha (0.3f)); + void paintListBoxItem (int row, + Graphics& g, + int width, int height, + bool rowIsSelected) + { + if (((unsigned int) row) < (unsigned int) items.size()) + { + if (rowIsSelected) + g.fillAll (findColour (TextEditor::highlightColourId) + .withMultipliedAlpha (0.3f)); - const String item (items [row]); - bool enabled = deviceManager.isMidiInputEnabled (item); + const String item (items [row]); + bool enabled = deviceManager.isMidiInputEnabled (item); - const int x = getTickX(); - const int tickW = height - height / 4; + const int x = getTickX(); + const int tickW = height - height / 4; - getLookAndFeel().drawTickBox (g, *this, x - tickW, (height - tickW) / 2, tickW, tickW, - enabled, true, true, false); + getLookAndFeel().drawTickBox (g, *this, x - tickW, (height - tickW) / 2, tickW, tickW, + enabled, true, true, false); - g.setFont (height * 0.6f); - g.setColour (findColour (ListBox::textColourId, true).withMultipliedAlpha (enabled ? 1.0f : 0.6f)); - g.drawText (item, x, 0, width - x - 2, height, Justification::centredLeft, true); - } - } + g.setFont (height * 0.6f); + g.setColour (findColour (ListBox::textColourId, true).withMultipliedAlpha (enabled ? 1.0f : 0.6f)); + g.drawText (item, x, 0, width - x - 2, height, Justification::centredLeft, true); + } + } - void listBoxItemClicked (int row, const MouseEvent& e) - { - selectRow (row); + void listBoxItemClicked (int row, const MouseEvent& e) + { + selectRow (row); - if (e.x < getTickX()) - flipEnablement (row); - } + if (e.x < getTickX()) + flipEnablement (row); + } - void listBoxItemDoubleClicked (int row, const MouseEvent&) - { - flipEnablement (row); - } + void listBoxItemDoubleClicked (int row, const MouseEvent&) + { + flipEnablement (row); + } - void returnKeyPressed (int row) - { - flipEnablement (row); - } + void returnKeyPressed (int row) + { + flipEnablement (row); + } - void paint (Graphics& g) - { - ListBox::paint (g); + void paint (Graphics& g) + { + ListBox::paint (g); - if (items.size() == 0) - { - g.setColour (Colours::grey); - g.setFont (13.0f); - g.drawText (noItemsMessage, - 0, 0, getWidth(), getHeight() / 2, - Justification::centred, true); - } - } + if (items.size() == 0) + { + g.setColour (Colours::grey); + g.setFont (13.0f); + g.drawText (noItemsMessage, + 0, 0, getWidth(), getHeight() / 2, + Justification::centred, true); + } + } - int getBestHeight (const int preferredHeight) - { - const int extra = getOutlineThickness() * 2; + int getBestHeight (const int preferredHeight) + { + const int extra = getOutlineThickness() * 2; - return jmax (getRowHeight() * 2 + extra, - jmin (getRowHeight() * getNumRows() + extra, - preferredHeight)); - } + return jmax (getRowHeight() * 2 + extra, + jmin (getRowHeight() * getNumRows() + extra, + preferredHeight)); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioDeviceManager& deviceManager; - const String noItemsMessage; - StringArray items; - int minNumber, maxNumber; + AudioDeviceManager& deviceManager; + const String noItemsMessage; + StringArray items; + int minNumber, maxNumber; - void flipEnablement (const int row) - { - if (((unsigned int) row) < (unsigned int) items.size()) - { - const String item (items [row]); - deviceManager.setMidiInputEnabled (item, ! deviceManager.isMidiInputEnabled (item)); - } - } + void flipEnablement (const int row) + { + if (((unsigned int) row) < (unsigned int) items.size()) + { + const String item (items [row]); + deviceManager.setMidiInputEnabled (item, ! deviceManager.isMidiInputEnabled (item)); + } + } - int getTickX() const - { - return getRowHeight() + 5; - } + int getTickX() const + { + return getRowHeight() + 5; + } - MidiInputSelectorComponentListBox (const MidiInputSelectorComponentListBox&); - const MidiInputSelectorComponentListBox& operator= (const MidiInputSelectorComponentListBox&); + MidiInputSelectorComponentListBox (const MidiInputSelectorComponentListBox&); + const MidiInputSelectorComponentListBox& operator= (const MidiInputSelectorComponentListBox&); }; class AudioDeviceSettingsPanel : public Component, - public ComboBoxListener, - public ChangeListener, - public ButtonListener + public ComboBoxListener, + public ChangeListener, + public ButtonListener { public: - AudioDeviceSettingsPanel (AudioIODeviceType* type_, - AudioIODeviceType::DeviceSetupDetails& setup_, - const bool hideAdvancedOptionsWithButton) - : type (type_), - setup (setup_) - { - sampleRateDropDown = 0; - sampleRateLabel = 0; - bufferSizeDropDown = 0; - bufferSizeLabel = 0; - outputDeviceDropDown = 0; - outputDeviceLabel = 0; - inputDeviceDropDown = 0; - inputDeviceLabel = 0; - testButton = 0; - inputLevelMeter = 0; - showUIButton = 0; - inputChanList = 0; - outputChanList = 0; - inputChanLabel = 0; - outputChanLabel = 0; - showAdvancedSettingsButton = 0; + AudioDeviceSettingsPanel (AudioIODeviceType* type_, + AudioIODeviceType::DeviceSetupDetails& setup_, + const bool hideAdvancedOptionsWithButton) + : type (type_), + setup (setup_) + { + sampleRateDropDown = 0; + sampleRateLabel = 0; + bufferSizeDropDown = 0; + bufferSizeLabel = 0; + outputDeviceDropDown = 0; + outputDeviceLabel = 0; + inputDeviceDropDown = 0; + inputDeviceLabel = 0; + testButton = 0; + inputLevelMeter = 0; + showUIButton = 0; + inputChanList = 0; + outputChanList = 0; + inputChanLabel = 0; + outputChanLabel = 0; + showAdvancedSettingsButton = 0; - if (hideAdvancedOptionsWithButton) - { - addAndMakeVisible (showAdvancedSettingsButton = new TextButton (TRANS("Show advanced settings..."))); - showAdvancedSettingsButton->addButtonListener (this); - } + if (hideAdvancedOptionsWithButton) + { + addAndMakeVisible (showAdvancedSettingsButton = new TextButton (TRANS("Show advanced settings..."))); + showAdvancedSettingsButton->addButtonListener (this); + } - type->scanForDevices(); + type->scanForDevices(); - setup.manager->addChangeListener (this); - changeListenerCallback (0); - } + setup.manager->addChangeListener (this); + changeListenerCallback (0); + } - ~AudioDeviceSettingsPanel() - { - setup.manager->removeChangeListener (this); + ~AudioDeviceSettingsPanel() + { + setup.manager->removeChangeListener (this); - deleteAndZero (outputDeviceLabel); - deleteAndZero (inputDeviceLabel); - deleteAndZero (sampleRateLabel); - deleteAndZero (bufferSizeLabel); - deleteAndZero (showUIButton); - deleteAndZero (inputChanLabel); - deleteAndZero (outputChanLabel); - deleteAndZero (showAdvancedSettingsButton); + deleteAndZero (outputDeviceLabel); + deleteAndZero (inputDeviceLabel); + deleteAndZero (sampleRateLabel); + deleteAndZero (bufferSizeLabel); + deleteAndZero (showUIButton); + deleteAndZero (inputChanLabel); + deleteAndZero (outputChanLabel); + deleteAndZero (showAdvancedSettingsButton); - deleteAllChildren(); - } + deleteAllChildren(); + } - void resized() - { - const int lx = proportionOfWidth (0.35f); - const int w = proportionOfWidth (0.4f); - const int h = 24; - const int space = 6; - const int dh = h + space; - int y = 0; + void resized() + { + const int lx = proportionOfWidth (0.35f); + const int w = proportionOfWidth (0.4f); + const int h = 24; + const int space = 6; + const int dh = h + space; + int y = 0; - if (outputDeviceDropDown != 0) - { - outputDeviceDropDown->setBounds (lx, y, w, h); + if (outputDeviceDropDown != 0) + { + outputDeviceDropDown->setBounds (lx, y, w, h); - if (testButton != 0) - testButton->setBounds (proportionOfWidth (0.77f), - outputDeviceDropDown->getY(), - proportionOfWidth (0.18f), - h); - y += dh; - } + if (testButton != 0) + testButton->setBounds (proportionOfWidth (0.77f), + outputDeviceDropDown->getY(), + proportionOfWidth (0.18f), + h); + y += dh; + } - if (inputDeviceDropDown != 0) - { - inputDeviceDropDown->setBounds (lx, y, w, h); + if (inputDeviceDropDown != 0) + { + inputDeviceDropDown->setBounds (lx, y, w, h); - inputLevelMeter->setBounds (proportionOfWidth (0.77f), - inputDeviceDropDown->getY(), - proportionOfWidth (0.18f), - h); - y += dh; - } + inputLevelMeter->setBounds (proportionOfWidth (0.77f), + inputDeviceDropDown->getY(), + proportionOfWidth (0.18f), + h); + y += dh; + } - const int maxBoxHeight = 100;//(getHeight() - y - dh * 2) / numBoxes; + const int maxBoxHeight = 100;//(getHeight() - y - dh * 2) / numBoxes; - if (outputChanList != 0) - { - const int bh = outputChanList->getBestHeight (maxBoxHeight); - outputChanList->setBounds (lx, y, proportionOfWidth (0.55f), bh); - y += bh + space; - } + if (outputChanList != 0) + { + const int bh = outputChanList->getBestHeight (maxBoxHeight); + outputChanList->setBounds (lx, y, proportionOfWidth (0.55f), bh); + y += bh + space; + } - if (inputChanList != 0) - { - const int bh = inputChanList->getBestHeight (maxBoxHeight); - inputChanList->setBounds (lx, y, proportionOfWidth (0.55f), bh); - y += bh + space; - } + if (inputChanList != 0) + { + const int bh = inputChanList->getBestHeight (maxBoxHeight); + inputChanList->setBounds (lx, y, proportionOfWidth (0.55f), bh); + y += bh + space; + } - y += space * 2; + y += space * 2; - if (showAdvancedSettingsButton != 0) - { - showAdvancedSettingsButton->changeWidthToFitText (h); - showAdvancedSettingsButton->setTopLeftPosition (lx, y); - } + if (showAdvancedSettingsButton != 0) + { + showAdvancedSettingsButton->changeWidthToFitText (h); + showAdvancedSettingsButton->setTopLeftPosition (lx, y); + } - if (sampleRateDropDown != 0) - { - sampleRateDropDown->setVisible (showAdvancedSettingsButton == 0 - || ! showAdvancedSettingsButton->isVisible()); + if (sampleRateDropDown != 0) + { + sampleRateDropDown->setVisible (showAdvancedSettingsButton == 0 + || ! showAdvancedSettingsButton->isVisible()); - sampleRateDropDown->setBounds (lx, y, w, h); - y += dh; - } + sampleRateDropDown->setBounds (lx, y, w, h); + y += dh; + } - if (bufferSizeDropDown != 0) - { - bufferSizeDropDown->setVisible (showAdvancedSettingsButton == 0 - || ! showAdvancedSettingsButton->isVisible()); - bufferSizeDropDown->setBounds (lx, y, w, h); - y += dh; - } + if (bufferSizeDropDown != 0) + { + bufferSizeDropDown->setVisible (showAdvancedSettingsButton == 0 + || ! showAdvancedSettingsButton->isVisible()); + bufferSizeDropDown->setBounds (lx, y, w, h); + y += dh; + } - if (showUIButton != 0) - { - showUIButton->setVisible (showAdvancedSettingsButton == 0 - || ! showAdvancedSettingsButton->isVisible()); - showUIButton->changeWidthToFitText (h); - showUIButton->setTopLeftPosition (lx, y); - } - } + if (showUIButton != 0) + { + showUIButton->setVisible (showAdvancedSettingsButton == 0 + || ! showAdvancedSettingsButton->isVisible()); + showUIButton->changeWidthToFitText (h); + showUIButton->setTopLeftPosition (lx, y); + } + } - void comboBoxChanged (ComboBox* comboBoxThatHasChanged) - { - if (comboBoxThatHasChanged == 0) - return; + void comboBoxChanged (ComboBox* comboBoxThatHasChanged) + { + if (comboBoxThatHasChanged == 0) + return; - AudioDeviceManager::AudioDeviceSetup config; - setup.manager->getAudioDeviceSetup (config); - String error; + AudioDeviceManager::AudioDeviceSetup config; + setup.manager->getAudioDeviceSetup (config); + String error; - if (comboBoxThatHasChanged == outputDeviceDropDown - || comboBoxThatHasChanged == inputDeviceDropDown) - { - if (outputDeviceDropDown != 0) - config.outputDeviceName = outputDeviceDropDown->getSelectedId() < 0 ? String::empty - : outputDeviceDropDown->getText(); + if (comboBoxThatHasChanged == outputDeviceDropDown + || comboBoxThatHasChanged == inputDeviceDropDown) + { + if (outputDeviceDropDown != 0) + config.outputDeviceName = outputDeviceDropDown->getSelectedId() < 0 ? String::empty + : outputDeviceDropDown->getText(); - if (inputDeviceDropDown != 0) - config.inputDeviceName = inputDeviceDropDown->getSelectedId() < 0 ? String::empty - : inputDeviceDropDown->getText(); + if (inputDeviceDropDown != 0) + config.inputDeviceName = inputDeviceDropDown->getSelectedId() < 0 ? String::empty + : inputDeviceDropDown->getText(); - if (! type->hasSeparateInputsAndOutputs()) - config.inputDeviceName = config.outputDeviceName; + if (! type->hasSeparateInputsAndOutputs()) + config.inputDeviceName = config.outputDeviceName; - if (comboBoxThatHasChanged == inputDeviceDropDown) - config.useDefaultInputChannels = true; - else - config.useDefaultOutputChannels = true; + if (comboBoxThatHasChanged == inputDeviceDropDown) + config.useDefaultInputChannels = true; + else + config.useDefaultOutputChannels = true; - error = setup.manager->setAudioDeviceSetup (config, true); + error = setup.manager->setAudioDeviceSetup (config, true); - showCorrectDeviceName (inputDeviceDropDown, true); - showCorrectDeviceName (outputDeviceDropDown, false); + showCorrectDeviceName (inputDeviceDropDown, true); + showCorrectDeviceName (outputDeviceDropDown, false); - updateControlPanelButton(); - resized(); - } - else if (comboBoxThatHasChanged == sampleRateDropDown) - { - if (sampleRateDropDown->getSelectedId() > 0) - { - config.sampleRate = sampleRateDropDown->getSelectedId(); - error = setup.manager->setAudioDeviceSetup (config, true); - } - } - else if (comboBoxThatHasChanged == bufferSizeDropDown) - { - if (bufferSizeDropDown->getSelectedId() > 0) - { - config.bufferSize = bufferSizeDropDown->getSelectedId(); - error = setup.manager->setAudioDeviceSetup (config, true); - } - } + updateControlPanelButton(); + resized(); + } + else if (comboBoxThatHasChanged == sampleRateDropDown) + { + if (sampleRateDropDown->getSelectedId() > 0) + { + config.sampleRate = sampleRateDropDown->getSelectedId(); + error = setup.manager->setAudioDeviceSetup (config, true); + } + } + else if (comboBoxThatHasChanged == bufferSizeDropDown) + { + if (bufferSizeDropDown->getSelectedId() > 0) + { + config.bufferSize = bufferSizeDropDown->getSelectedId(); + error = setup.manager->setAudioDeviceSetup (config, true); + } + } - if (error.isNotEmpty()) - { - AlertWindow::showMessageBox (AlertWindow::WarningIcon, - T("Error when trying to open audio device!"), - error); - } - } + if (error.isNotEmpty()) + { + AlertWindow::showMessageBox (AlertWindow::WarningIcon, + T("Error when trying to open audio device!"), + error); + } + } - void buttonClicked (Button* button) - { - if (button == showAdvancedSettingsButton) - { - showAdvancedSettingsButton->setVisible (false); - resized(); - } - else if (button == showUIButton) - { - AudioIODevice* const device = setup.manager->getCurrentAudioDevice(); + void buttonClicked (Button* button) + { + if (button == showAdvancedSettingsButton) + { + showAdvancedSettingsButton->setVisible (false); + resized(); + } + else if (button == showUIButton) + { + AudioIODevice* const device = setup.manager->getCurrentAudioDevice(); - if (device != 0 && device->showControlPanel()) - { - setup.manager->closeAudioDevice(); - setup.manager->restartLastAudioDevice(); - getTopLevelComponent()->toFront (true); - } - } - else if (button == testButton && testButton != 0) - { - setup.manager->playTestSound(); - } - } + if (device != 0 && device->showControlPanel()) + { + setup.manager->closeAudioDevice(); + setup.manager->restartLastAudioDevice(); + getTopLevelComponent()->toFront (true); + } + } + else if (button == testButton && testButton != 0) + { + setup.manager->playTestSound(); + } + } - void updateControlPanelButton() - { - AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice(); + void updateControlPanelButton() + { + AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice(); - deleteAndZero (showUIButton); + deleteAndZero (showUIButton); - if (currentDevice != 0 && currentDevice->hasControlPanel()) - { - addAndMakeVisible (showUIButton = new TextButton (TRANS ("show this device's control panel"), - TRANS ("opens the device's own control panel"))); - showUIButton->addButtonListener (this); - } + if (currentDevice != 0 && currentDevice->hasControlPanel()) + { + addAndMakeVisible (showUIButton = new TextButton (TRANS ("show this device's control panel"), + TRANS ("opens the device's own control panel"))); + showUIButton->addButtonListener (this); + } - resized(); - } + resized(); + } - void changeListenerCallback (void*) - { - AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice(); + void changeListenerCallback (void*) + { + AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice(); - if (setup.maxNumOutputChannels > 0 || ! type->hasSeparateInputsAndOutputs()) - { - if (outputDeviceDropDown == 0) - { - outputDeviceDropDown = new ComboBox (String::empty); - outputDeviceDropDown->addListener (this); - addAndMakeVisible (outputDeviceDropDown); + if (setup.maxNumOutputChannels > 0 || ! type->hasSeparateInputsAndOutputs()) + { + if (outputDeviceDropDown == 0) + { + outputDeviceDropDown = new ComboBox (String::empty); + outputDeviceDropDown->addListener (this); + addAndMakeVisible (outputDeviceDropDown); - outputDeviceLabel = new Label (String::empty, - type->hasSeparateInputsAndOutputs() ? TRANS ("output:") - : TRANS ("device:")); - outputDeviceLabel->attachToComponent (outputDeviceDropDown, true); + outputDeviceLabel = new Label (String::empty, + type->hasSeparateInputsAndOutputs() ? TRANS ("output:") + : TRANS ("device:")); + outputDeviceLabel->attachToComponent (outputDeviceDropDown, true); - if (setup.maxNumOutputChannels > 0) - { - addAndMakeVisible (testButton = new TextButton (TRANS ("Test"))); - testButton->addButtonListener (this); - } - } + if (setup.maxNumOutputChannels > 0) + { + addAndMakeVisible (testButton = new TextButton (TRANS ("Test"))); + testButton->addButtonListener (this); + } + } - addNamesToDeviceBox (*outputDeviceDropDown, false); - } + addNamesToDeviceBox (*outputDeviceDropDown, false); + } - if (setup.maxNumInputChannels > 0 && type->hasSeparateInputsAndOutputs()) - { - if (inputDeviceDropDown == 0) - { - inputDeviceDropDown = new ComboBox (String::empty); - inputDeviceDropDown->addListener (this); - addAndMakeVisible (inputDeviceDropDown); + if (setup.maxNumInputChannels > 0 && type->hasSeparateInputsAndOutputs()) + { + if (inputDeviceDropDown == 0) + { + inputDeviceDropDown = new ComboBox (String::empty); + inputDeviceDropDown->addListener (this); + addAndMakeVisible (inputDeviceDropDown); - inputDeviceLabel = new Label (String::empty, TRANS ("input:")); - inputDeviceLabel->attachToComponent (inputDeviceDropDown, true); + inputDeviceLabel = new Label (String::empty, TRANS ("input:")); + inputDeviceLabel->attachToComponent (inputDeviceDropDown, true); - addAndMakeVisible (inputLevelMeter - = new SimpleDeviceManagerInputLevelMeter (setup.manager)); - } + addAndMakeVisible (inputLevelMeter + = new SimpleDeviceManagerInputLevelMeter (setup.manager)); + } - addNamesToDeviceBox (*inputDeviceDropDown, true); - } + addNamesToDeviceBox (*inputDeviceDropDown, true); + } - updateControlPanelButton(); - showCorrectDeviceName (inputDeviceDropDown, true); - showCorrectDeviceName (outputDeviceDropDown, false); + updateControlPanelButton(); + showCorrectDeviceName (inputDeviceDropDown, true); + showCorrectDeviceName (outputDeviceDropDown, false); - if (currentDevice != 0) - { - if (setup.maxNumOutputChannels > 0 - && setup.minNumOutputChannels < setup.manager->getCurrentAudioDevice()->getOutputChannelNames().size()) - { - if (outputChanList == 0) - { - addAndMakeVisible (outputChanList - = new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioOutputType, - TRANS ("(no audio output channels found)"))); - outputChanLabel = new Label (String::empty, TRANS ("active output channels:")); - outputChanLabel->attachToComponent (outputChanList, true); - } + if (currentDevice != 0) + { + if (setup.maxNumOutputChannels > 0 + && setup.minNumOutputChannels < setup.manager->getCurrentAudioDevice()->getOutputChannelNames().size()) + { + if (outputChanList == 0) + { + addAndMakeVisible (outputChanList + = new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioOutputType, + TRANS ("(no audio output channels found)"))); + outputChanLabel = new Label (String::empty, TRANS ("active output channels:")); + outputChanLabel->attachToComponent (outputChanList, true); + } - outputChanList->refresh(); - } - else - { - deleteAndZero (outputChanLabel); - deleteAndZero (outputChanList); - } + outputChanList->refresh(); + } + else + { + deleteAndZero (outputChanLabel); + deleteAndZero (outputChanList); + } - if (setup.maxNumInputChannels > 0 - && setup.minNumInputChannels < setup.manager->getCurrentAudioDevice()->getInputChannelNames().size()) - { - if (inputChanList == 0) - { - addAndMakeVisible (inputChanList - = new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioInputType, - TRANS ("(no audio input channels found)"))); - inputChanLabel = new Label (String::empty, TRANS ("active input channels:")); - inputChanLabel->attachToComponent (inputChanList, true); - } + if (setup.maxNumInputChannels > 0 + && setup.minNumInputChannels < setup.manager->getCurrentAudioDevice()->getInputChannelNames().size()) + { + if (inputChanList == 0) + { + addAndMakeVisible (inputChanList + = new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioInputType, + TRANS ("(no audio input channels found)"))); + inputChanLabel = new Label (String::empty, TRANS ("active input channels:")); + inputChanLabel->attachToComponent (inputChanList, true); + } - inputChanList->refresh(); - } - else - { - deleteAndZero (inputChanLabel); - deleteAndZero (inputChanList); - } + inputChanList->refresh(); + } + else + { + deleteAndZero (inputChanLabel); + deleteAndZero (inputChanList); + } - // sample rate.. - { - if (sampleRateDropDown == 0) - { - addAndMakeVisible (sampleRateDropDown = new ComboBox (String::empty)); - sampleRateDropDown->addListener (this); + // sample rate.. + { + if (sampleRateDropDown == 0) + { + addAndMakeVisible (sampleRateDropDown = new ComboBox (String::empty)); + sampleRateDropDown->addListener (this); - delete sampleRateLabel; - sampleRateLabel = new Label (String::empty, TRANS ("sample rate:")); - sampleRateLabel->attachToComponent (sampleRateDropDown, true); - } - else - { - sampleRateDropDown->clear(); - sampleRateDropDown->removeListener (this); - } + delete sampleRateLabel; + sampleRateLabel = new Label (String::empty, TRANS ("sample rate:")); + sampleRateLabel->attachToComponent (sampleRateDropDown, true); + } + else + { + sampleRateDropDown->clear(); + sampleRateDropDown->removeListener (this); + } - const int numRates = currentDevice->getNumSampleRates(); + const int numRates = currentDevice->getNumSampleRates(); - for (int i = 0; i < numRates; ++i) - { - const int rate = roundDoubleToInt (currentDevice->getSampleRate (i)); - sampleRateDropDown->addItem (String (rate) + T(" Hz"), rate); - } + for (int i = 0; i < numRates; ++i) + { + const int rate = roundToInt (currentDevice->getSampleRate (i)); + sampleRateDropDown->addItem (String (rate) + T(" Hz"), rate); + } - sampleRateDropDown->setSelectedId (roundDoubleToInt (currentDevice->getCurrentSampleRate()), true); - sampleRateDropDown->addListener (this); - } + sampleRateDropDown->setSelectedId (roundToInt (currentDevice->getCurrentSampleRate()), true); + sampleRateDropDown->addListener (this); + } - // buffer size - { - if (bufferSizeDropDown == 0) - { - addAndMakeVisible (bufferSizeDropDown = new ComboBox (String::empty)); - bufferSizeDropDown->addListener (this); + // buffer size + { + if (bufferSizeDropDown == 0) + { + addAndMakeVisible (bufferSizeDropDown = new ComboBox (String::empty)); + bufferSizeDropDown->addListener (this); - delete bufferSizeLabel; - bufferSizeLabel = new Label (String::empty, TRANS ("audio buffer size:")); - bufferSizeLabel->attachToComponent (bufferSizeDropDown, true); - } - else - { - bufferSizeDropDown->clear(); - } + delete bufferSizeLabel; + bufferSizeLabel = new Label (String::empty, TRANS ("audio buffer size:")); + bufferSizeLabel->attachToComponent (bufferSizeDropDown, true); + } + else + { + bufferSizeDropDown->clear(); + } - const int numBufferSizes = currentDevice->getNumBufferSizesAvailable(); - double currentRate = currentDevice->getCurrentSampleRate(); - if (currentRate == 0) - currentRate = 48000.0; + const int numBufferSizes = currentDevice->getNumBufferSizesAvailable(); + double currentRate = currentDevice->getCurrentSampleRate(); + if (currentRate == 0) + currentRate = 48000.0; - for (int i = 0; i < numBufferSizes; ++i) - { - const int bs = currentDevice->getBufferSizeSamples (i); - bufferSizeDropDown->addItem (String (bs) - + T(" samples (") - + String (bs * 1000.0 / currentRate, 1) - + T(" ms)"), - bs); - } + for (int i = 0; i < numBufferSizes; ++i) + { + const int bs = currentDevice->getBufferSizeSamples (i); + bufferSizeDropDown->addItem (String (bs) + + T(" samples (") + + String (bs * 1000.0 / currentRate, 1) + + T(" ms)"), + bs); + } - bufferSizeDropDown->setSelectedId (currentDevice->getCurrentBufferSizeSamples(), true); - } - } - else - { - jassert (setup.manager->getCurrentAudioDevice() == 0); // not the correct device type! + bufferSizeDropDown->setSelectedId (currentDevice->getCurrentBufferSizeSamples(), true); + } + } + else + { + jassert (setup.manager->getCurrentAudioDevice() == 0); // not the correct device type! - deleteAndZero (sampleRateLabel); - deleteAndZero (bufferSizeLabel); - deleteAndZero (sampleRateDropDown); - deleteAndZero (bufferSizeDropDown); + deleteAndZero (sampleRateLabel); + deleteAndZero (bufferSizeLabel); + deleteAndZero (sampleRateDropDown); + deleteAndZero (bufferSizeDropDown); - if (outputDeviceDropDown != 0) - outputDeviceDropDown->setSelectedId (-1, true); + if (outputDeviceDropDown != 0) + outputDeviceDropDown->setSelectedId (-1, true); - if (inputDeviceDropDown != 0) - inputDeviceDropDown->setSelectedId (-1, true); - } + if (inputDeviceDropDown != 0) + inputDeviceDropDown->setSelectedId (-1, true); + } - resized(); - setSize (getWidth(), getLowestY() + 4); - } + resized(); + setSize (getWidth(), getLowestY() + 4); + } private: - AudioIODeviceType* const type; - const AudioIODeviceType::DeviceSetupDetails setup; + AudioIODeviceType* const type; + const AudioIODeviceType::DeviceSetupDetails setup; - ComboBox* outputDeviceDropDown; - ComboBox* inputDeviceDropDown; - ComboBox* sampleRateDropDown; - ComboBox* bufferSizeDropDown; - Label* outputDeviceLabel; - Label* inputDeviceLabel; - Label* sampleRateLabel; - Label* bufferSizeLabel; - Label* inputChanLabel; - Label* outputChanLabel; - TextButton* testButton; - Component* inputLevelMeter; - TextButton* showUIButton; - TextButton* showAdvancedSettingsButton; + ComboBox* outputDeviceDropDown; + ComboBox* inputDeviceDropDown; + ComboBox* sampleRateDropDown; + ComboBox* bufferSizeDropDown; + Label* outputDeviceLabel; + Label* inputDeviceLabel; + Label* sampleRateLabel; + Label* bufferSizeLabel; + Label* inputChanLabel; + Label* outputChanLabel; + TextButton* testButton; + Component* inputLevelMeter; + TextButton* showUIButton; + TextButton* showAdvancedSettingsButton; - void showCorrectDeviceName (ComboBox* const box, const bool isInput) - { - if (box != 0) - { - AudioIODevice* const currentDevice = dynamic_cast (setup.manager->getCurrentAudioDevice()); + void showCorrectDeviceName (ComboBox* const box, const bool isInput) + { + if (box != 0) + { + AudioIODevice* const currentDevice = dynamic_cast (setup.manager->getCurrentAudioDevice()); - const int index = type->getIndexOfDevice (currentDevice, isInput); + const int index = type->getIndexOfDevice (currentDevice, isInput); - box->setSelectedId (index + 1, true); + box->setSelectedId (index + 1, true); - if (testButton != 0 && ! isInput) - testButton->setEnabled (index >= 0); - } - } + if (testButton != 0 && ! isInput) + testButton->setEnabled (index >= 0); + } + } - void addNamesToDeviceBox (ComboBox& combo, bool isInputs) - { - const StringArray devs (type->getDeviceNames (isInputs)); + void addNamesToDeviceBox (ComboBox& combo, bool isInputs) + { + const StringArray devs (type->getDeviceNames (isInputs)); - combo.clear (true); + combo.clear (true); - for (int i = 0; i < devs.size(); ++i) - combo.addItem (devs[i], i + 1); + for (int i = 0; i < devs.size(); ++i) + combo.addItem (devs[i], i + 1); - combo.addItem (TRANS("<< none >>"), -1); - combo.setSelectedId (-1, true); - } + combo.addItem (TRANS("<< none >>"), -1); + combo.setSelectedId (-1, true); + } - int getLowestY() const - { - int y = 0; + int getLowestY() const + { + int y = 0; - for (int i = getNumChildComponents(); --i >= 0;) - y = jmax (y, getChildComponent (i)->getBottom()); + for (int i = getNumChildComponents(); --i >= 0;) + y = jmax (y, getChildComponent (i)->getBottom()); - return y; - } + return y; + } - class ChannelSelectorListBox : public ListBox, - public ListBoxModel - { - public: - enum BoxType - { - audioInputType, - audioOutputType - }; +public: - ChannelSelectorListBox (const AudioIODeviceType::DeviceSetupDetails& setup_, - const BoxType type_, - const String& noItemsMessage_) - : ListBox (String::empty, 0), - setup (setup_), - type (type_), - noItemsMessage (noItemsMessage_) - { - refresh(); - setModel (this); - setOutlineThickness (1); - } + class ChannelSelectorListBox : public ListBox, + public ListBoxModel + { + public: + enum BoxType + { + audioInputType, + audioOutputType + }; - ~ChannelSelectorListBox() - { - } + ChannelSelectorListBox (const AudioIODeviceType::DeviceSetupDetails& setup_, + const BoxType type_, + const String& noItemsMessage_) + : ListBox (String::empty, 0), + setup (setup_), + type (type_), + noItemsMessage (noItemsMessage_) + { + refresh(); + setModel (this); + setOutlineThickness (1); + } - void refresh() - { - items.clear(); + ~ChannelSelectorListBox() + { + } - AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice(); + void refresh() + { + items.clear(); - if (currentDevice != 0) - { - if (type == audioInputType) - items = currentDevice->getInputChannelNames(); - else if (type == audioOutputType) - items = currentDevice->getOutputChannelNames(); + AudioIODevice* const currentDevice = setup.manager->getCurrentAudioDevice(); - if (setup.useStereoPairs) - { - StringArray pairs; + if (currentDevice != 0) + { + if (type == audioInputType) + items = currentDevice->getInputChannelNames(); + else if (type == audioOutputType) + items = currentDevice->getOutputChannelNames(); - for (int i = 0; i < items.size(); i += 2) - { - String name (items[i]); - String name2 (items[i + 1]); + if (setup.useStereoPairs) + { + StringArray pairs; - String commonBit; + for (int i = 0; i < items.size(); i += 2) + { + String name (items[i]); + String name2 (items[i + 1]); - for (int j = 0; j < name.length(); ++j) - if (name.substring (0, j).equalsIgnoreCase (name2.substring (0, j))) - commonBit = name.substring (0, j); + String commonBit; - pairs.add (name.trim() - + " + " - + name2.substring (commonBit.length()).trim()); - } + for (int j = 0; j < name.length(); ++j) + if (name.substring (0, j).equalsIgnoreCase (name2.substring (0, j))) + commonBit = name.substring (0, j); - items = pairs; - } - } + pairs.add (name.trim() + + " + " + + name2.substring (commonBit.length()).trim()); + } - updateContent(); - repaint(); - } + items = pairs; + } + } - int getNumRows() - { - return items.size(); - } + updateContent(); + repaint(); + } - void paintListBoxItem (int row, - Graphics& g, - int width, int height, - bool rowIsSelected) - { - if (((unsigned int) row) < (unsigned int) items.size()) - { - if (rowIsSelected) - g.fillAll (findColour (TextEditor::highlightColourId) - .withMultipliedAlpha (0.3f)); + int getNumRows() + { + return items.size(); + } - const String item (items [row]); - bool enabled = false; + void paintListBoxItem (int row, + Graphics& g, + int width, int height, + bool rowIsSelected) + { + if (((unsigned int) row) < (unsigned int) items.size()) + { + if (rowIsSelected) + g.fillAll (findColour (TextEditor::highlightColourId) + .withMultipliedAlpha (0.3f)); - AudioDeviceManager::AudioDeviceSetup config; - setup.manager->getAudioDeviceSetup (config); + const String item (items [row]); + bool enabled = false; - if (setup.useStereoPairs) - { - if (type == audioInputType) - enabled = config.inputChannels [row * 2] || config.inputChannels [row * 2 + 1]; - else if (type == audioOutputType) - enabled = config.outputChannels [row * 2] || config.outputChannels [row * 2 + 1]; - } - else - { - if (type == audioInputType) - enabled = config.inputChannels [row]; - else if (type == audioOutputType) - enabled = config.outputChannels [row]; - } + AudioDeviceManager::AudioDeviceSetup config; + setup.manager->getAudioDeviceSetup (config); - const int x = getTickX(); - const int tickW = height - height / 4; + if (setup.useStereoPairs) + { + if (type == audioInputType) + enabled = config.inputChannels [row * 2] || config.inputChannels [row * 2 + 1]; + else if (type == audioOutputType) + enabled = config.outputChannels [row * 2] || config.outputChannels [row * 2 + 1]; + } + else + { + if (type == audioInputType) + enabled = config.inputChannels [row]; + else if (type == audioOutputType) + enabled = config.outputChannels [row]; + } - getLookAndFeel().drawTickBox (g, *this, x - tickW, (height - tickW) / 2, tickW, tickW, - enabled, true, true, false); + const int x = getTickX(); + const int tickW = height - height / 4; - g.setFont (height * 0.6f); - g.setColour (findColour (ListBox::textColourId, true).withMultipliedAlpha (enabled ? 1.0f : 0.6f)); - g.drawText (item, x, 0, width - x - 2, height, Justification::centredLeft, true); - } - } + getLookAndFeel().drawTickBox (g, *this, x - tickW, (height - tickW) / 2, tickW, tickW, + enabled, true, true, false); - void listBoxItemClicked (int row, const MouseEvent& e) - { - selectRow (row); + g.setFont (height * 0.6f); + g.setColour (findColour (ListBox::textColourId, true).withMultipliedAlpha (enabled ? 1.0f : 0.6f)); + g.drawText (item, x, 0, width - x - 2, height, Justification::centredLeft, true); + } + } - if (e.x < getTickX()) - flipEnablement (row); - } + void listBoxItemClicked (int row, const MouseEvent& e) + { + selectRow (row); - void listBoxItemDoubleClicked (int row, const MouseEvent&) - { - flipEnablement (row); - } + if (e.x < getTickX()) + flipEnablement (row); + } - void returnKeyPressed (int row) - { - flipEnablement (row); - } + void listBoxItemDoubleClicked (int row, const MouseEvent&) + { + flipEnablement (row); + } - void paint (Graphics& g) - { - ListBox::paint (g); + void returnKeyPressed (int row) + { + flipEnablement (row); + } - if (items.size() == 0) - { - g.setColour (Colours::grey); - g.setFont (13.0f); - g.drawText (noItemsMessage, - 0, 0, getWidth(), getHeight() / 2, - Justification::centred, true); - } - } + void paint (Graphics& g) + { + ListBox::paint (g); - int getBestHeight (int maxHeight) - { - return getRowHeight() * jlimit (2, jmax (2, maxHeight / getRowHeight()), - getNumRows()) - + getOutlineThickness() * 2; - } + if (items.size() == 0) + { + g.setColour (Colours::grey); + g.setFont (13.0f); + g.drawText (noItemsMessage, + 0, 0, getWidth(), getHeight() / 2, + Justification::centred, true); + } + } - juce_UseDebuggingNewOperator + int getBestHeight (int maxHeight) + { + return getRowHeight() * jlimit (2, jmax (2, maxHeight / getRowHeight()), + getNumRows()) + + getOutlineThickness() * 2; + } - private: - const AudioIODeviceType::DeviceSetupDetails setup; - const BoxType type; - const String noItemsMessage; - StringArray items; + juce_UseDebuggingNewOperator - void flipEnablement (const int row) - { - jassert (type == audioInputType || type == audioOutputType); + private: + const AudioIODeviceType::DeviceSetupDetails setup; + const BoxType type; + const String noItemsMessage; + StringArray items; - if (((unsigned int) row) < (unsigned int) items.size()) - { - AudioDeviceManager::AudioDeviceSetup config; - setup.manager->getAudioDeviceSetup (config); + void flipEnablement (const int row) + { + jassert (type == audioInputType || type == audioOutputType); - if (setup.useStereoPairs) - { - BitArray bits; - BitArray& original = (type == audioInputType ? config.inputChannels - : config.outputChannels); + if (((unsigned int) row) < (unsigned int) items.size()) + { + AudioDeviceManager::AudioDeviceSetup config; + setup.manager->getAudioDeviceSetup (config); - int i; - for (i = 0; i < 256; i += 2) - bits.setBit (i / 2, original [i] || original [i + 1]); + if (setup.useStereoPairs) + { + BitArray bits; + BitArray& original = (type == audioInputType ? config.inputChannels + : config.outputChannels); - if (type == audioInputType) - { - config.useDefaultInputChannels = false; - flipBit (bits, row, setup.minNumInputChannels / 2, setup.maxNumInputChannels / 2); - } - else - { - config.useDefaultOutputChannels = false; - flipBit (bits, row, setup.minNumOutputChannels / 2, setup.maxNumOutputChannels / 2); - } + int i; + for (i = 0; i < 256; i += 2) + bits.setBit (i / 2, original [i] || original [i + 1]); - for (i = 0; i < 256; ++i) - original.setBit (i, bits [i / 2]); - } - else - { - if (type == audioInputType) - { - config.useDefaultInputChannels = false; - flipBit (config.inputChannels, row, setup.minNumInputChannels, setup.maxNumInputChannels); - } - else - { - config.useDefaultOutputChannels = false; - flipBit (config.outputChannels, row, setup.minNumOutputChannels, setup.maxNumOutputChannels); - } - } + if (type == audioInputType) + { + config.useDefaultInputChannels = false; + flipBit (bits, row, setup.minNumInputChannels / 2, setup.maxNumInputChannels / 2); + } + else + { + config.useDefaultOutputChannels = false; + flipBit (bits, row, setup.minNumOutputChannels / 2, setup.maxNumOutputChannels / 2); + } - String error (setup.manager->setAudioDeviceSetup (config, true)); + for (i = 0; i < 256; ++i) + original.setBit (i, bits [i / 2]); + } + else + { + if (type == audioInputType) + { + config.useDefaultInputChannels = false; + flipBit (config.inputChannels, row, setup.minNumInputChannels, setup.maxNumInputChannels); + } + else + { + config.useDefaultOutputChannels = false; + flipBit (config.outputChannels, row, setup.minNumOutputChannels, setup.maxNumOutputChannels); + } + } - if (! error.isEmpty()) - { - //xxx - } - } - } + String error (setup.manager->setAudioDeviceSetup (config, true)); - static void flipBit (BitArray& chans, int index, int minNumber, int maxNumber) - { - const int numActive = chans.countNumberOfSetBits(); + if (! error.isEmpty()) + { + //xxx + } + } + } - if (chans [index]) - { - if (numActive > minNumber) - chans.setBit (index, false); - } - else - { - if (numActive >= maxNumber) - { - const int firstActiveChan = chans.findNextSetBit(); + static void flipBit (BitArray& chans, int index, int minNumber, int maxNumber) + { + const int numActive = chans.countNumberOfSetBits(); - chans.setBit (index > firstActiveChan - ? firstActiveChan : chans.getHighestBit(), - false); - } + if (chans [index]) + { + if (numActive > minNumber) + chans.setBit (index, false); + } + else + { + if (numActive >= maxNumber) + { + const int firstActiveChan = chans.findNextSetBit(); - chans.setBit (index, true); - } - } + chans.setBit (index > firstActiveChan + ? firstActiveChan : chans.getHighestBit(), + false); + } - int getTickX() const - { - return getRowHeight() + 5; - } + chans.setBit (index, true); + } + } - ChannelSelectorListBox (const ChannelSelectorListBox&); - const ChannelSelectorListBox& operator= (const ChannelSelectorListBox&); - }; + int getTickX() const + { + return getRowHeight() + 5; + } - ChannelSelectorListBox* inputChanList; - ChannelSelectorListBox* outputChanList; + ChannelSelectorListBox (const ChannelSelectorListBox&); + const ChannelSelectorListBox& operator= (const ChannelSelectorListBox&); + }; - AudioDeviceSettingsPanel (const AudioDeviceSettingsPanel&); - const AudioDeviceSettingsPanel& operator= (const AudioDeviceSettingsPanel&); +private: + ChannelSelectorListBox* inputChanList; + ChannelSelectorListBox* outputChanList; + + AudioDeviceSettingsPanel (const AudioDeviceSettingsPanel&); + const AudioDeviceSettingsPanel& operator= (const AudioDeviceSettingsPanel&); }; AudioDeviceSelectorComponent::AudioDeviceSelectorComponent (AudioDeviceManager& deviceManager_, - const int minInputChannels_, - const int maxInputChannels_, - const int minOutputChannels_, - const int maxOutputChannels_, - const bool showMidiInputOptions, - const bool showMidiOutputSelector, - const bool showChannelsAsStereoPairs_, - const bool hideAdvancedOptionsWithButton_) - : deviceManager (deviceManager_), - deviceTypeDropDown (0), - deviceTypeDropDownLabel (0), - audioDeviceSettingsComp (0), - minOutputChannels (minOutputChannels_), - maxOutputChannels (maxOutputChannels_), - minInputChannels (minInputChannels_), - maxInputChannels (maxInputChannels_), - showChannelsAsStereoPairs (showChannelsAsStereoPairs_), - hideAdvancedOptionsWithButton (hideAdvancedOptionsWithButton_) + const int minInputChannels_, + const int maxInputChannels_, + const int minOutputChannels_, + const int maxOutputChannels_, + const bool showMidiInputOptions, + const bool showMidiOutputSelector, + const bool showChannelsAsStereoPairs_, + const bool hideAdvancedOptionsWithButton_) + : deviceManager (deviceManager_), + deviceTypeDropDown (0), + deviceTypeDropDownLabel (0), + audioDeviceSettingsComp (0), + minOutputChannels (minOutputChannels_), + maxOutputChannels (maxOutputChannels_), + minInputChannels (minInputChannels_), + maxInputChannels (maxInputChannels_), + showChannelsAsStereoPairs (showChannelsAsStereoPairs_), + hideAdvancedOptionsWithButton (hideAdvancedOptionsWithButton_) { - jassert (minOutputChannels >= 0 && minOutputChannels <= maxOutputChannels); - jassert (minInputChannels >= 0 && minInputChannels <= maxInputChannels); + jassert (minOutputChannels >= 0 && minOutputChannels <= maxOutputChannels); + jassert (minInputChannels >= 0 && minInputChannels <= maxInputChannels); - if (deviceManager_.getAvailableDeviceTypes().size() > 1) - { - deviceTypeDropDown = new ComboBox (String::empty); + if (deviceManager_.getAvailableDeviceTypes().size() > 1) + { + deviceTypeDropDown = new ComboBox (String::empty); - for (int i = 0; i < deviceManager_.getAvailableDeviceTypes().size(); ++i) - { - deviceTypeDropDown - ->addItem (deviceManager_.getAvailableDeviceTypes().getUnchecked(i)->getTypeName(), - i + 1); - } + for (int i = 0; i < deviceManager_.getAvailableDeviceTypes().size(); ++i) + { + deviceTypeDropDown + ->addItem (deviceManager_.getAvailableDeviceTypes().getUnchecked(i)->getTypeName(), + i + 1); + } - addAndMakeVisible (deviceTypeDropDown); - deviceTypeDropDown->addListener (this); + addAndMakeVisible (deviceTypeDropDown); + deviceTypeDropDown->addListener (this); - deviceTypeDropDownLabel = new Label (String::empty, TRANS ("audio device type:")); - deviceTypeDropDownLabel->setJustificationType (Justification::centredRight); - deviceTypeDropDownLabel->attachToComponent (deviceTypeDropDown, true); - } + deviceTypeDropDownLabel = new Label (String::empty, TRANS ("audio device type:")); + deviceTypeDropDownLabel->setJustificationType (Justification::centredRight); + deviceTypeDropDownLabel->attachToComponent (deviceTypeDropDown, true); + } - if (showMidiInputOptions) - { - addAndMakeVisible (midiInputsList - = new MidiInputSelectorComponentListBox (deviceManager, - TRANS("(no midi inputs available)"), - 0, 0)); + if (showMidiInputOptions) + { + addAndMakeVisible (midiInputsList + = new MidiInputSelectorComponentListBox (deviceManager, + TRANS("(no midi inputs available)"), + 0, 0)); - midiInputsLabel = new Label (String::empty, TRANS ("active midi inputs:")); - midiInputsLabel->setJustificationType (Justification::topRight); - midiInputsLabel->attachToComponent (midiInputsList, true); - } - else - { - midiInputsList = 0; - midiInputsLabel = 0; - } + midiInputsLabel = new Label (String::empty, TRANS ("active midi inputs:")); + midiInputsLabel->setJustificationType (Justification::topRight); + midiInputsLabel->attachToComponent (midiInputsList, true); + } + else + { + midiInputsList = 0; + midiInputsLabel = 0; + } - if (showMidiOutputSelector) - { - addAndMakeVisible (midiOutputSelector = new ComboBox (String::empty)); - midiOutputSelector->addListener (this); + if (showMidiOutputSelector) + { + addAndMakeVisible (midiOutputSelector = new ComboBox (String::empty)); + midiOutputSelector->addListener (this); - midiOutputLabel = new Label ("lm", TRANS("Midi Output:")); - midiOutputLabel->attachToComponent (midiOutputSelector, true); - } - else - { - midiOutputSelector = 0; - midiOutputLabel = 0; - } + midiOutputLabel = new Label ("lm", TRANS("Midi Output:")); + midiOutputLabel->attachToComponent (midiOutputSelector, true); + } + else + { + midiOutputSelector = 0; + midiOutputLabel = 0; + } - deviceManager_.addChangeListener (this); - changeListenerCallback (0); + deviceManager_.addChangeListener (this); + changeListenerCallback (0); } AudioDeviceSelectorComponent::~AudioDeviceSelectorComponent() { - deviceManager.removeChangeListener (this); - deleteAllChildren(); + deviceManager.removeChangeListener (this); + deleteAllChildren(); } void AudioDeviceSelectorComponent::resized() { - const int lx = proportionOfWidth (0.35f); - const int w = proportionOfWidth (0.4f); - const int h = 24; - const int space = 6; - const int dh = h + space; - int y = 15; + const int lx = proportionOfWidth (0.35f); + const int w = proportionOfWidth (0.4f); + const int h = 24; + const int space = 6; + const int dh = h + space; + int y = 15; - if (deviceTypeDropDown != 0) - { - deviceTypeDropDown->setBounds (lx, y, proportionOfWidth (0.3f), h); - y += dh + space * 2; - } + if (deviceTypeDropDown != 0) + { + deviceTypeDropDown->setBounds (lx, y, proportionOfWidth (0.3f), h); + y += dh + space * 2; + } - if (audioDeviceSettingsComp != 0) - { - audioDeviceSettingsComp->setBounds (0, y, getWidth(), audioDeviceSettingsComp->getHeight()); - y += audioDeviceSettingsComp->getHeight() + space; - } + if (audioDeviceSettingsComp != 0) + { + audioDeviceSettingsComp->setBounds (0, y, getWidth(), audioDeviceSettingsComp->getHeight()); + y += audioDeviceSettingsComp->getHeight() + space; + } - if (midiInputsList != 0) - { - const int bh = midiInputsList->getBestHeight (jmin (h * 8, getHeight() - y - space - h)); - midiInputsList->setBounds (lx, y, w, bh); - y += bh + space; - } + if (midiInputsList != 0) + { + const int bh = midiInputsList->getBestHeight (jmin (h * 8, getHeight() - y - space - h)); + midiInputsList->setBounds (lx, y, w, bh); + y += bh + space; + } - if (midiOutputSelector != 0) - midiOutputSelector->setBounds (lx, y, w, h); + if (midiOutputSelector != 0) + midiOutputSelector->setBounds (lx, y, w, h); } void AudioDeviceSelectorComponent::childBoundsChanged (Component* child) { - if (child == audioDeviceSettingsComp) - resized(); + if (child == audioDeviceSettingsComp) + resized(); } void AudioDeviceSelectorComponent::buttonClicked (Button*) { - AudioIODevice* const device = deviceManager.getCurrentAudioDevice(); + AudioIODevice* const device = deviceManager.getCurrentAudioDevice(); - if (device != 0 && device->hasControlPanel()) - { - if (device->showControlPanel()) - deviceManager.restartLastAudioDevice(); + if (device != 0 && device->hasControlPanel()) + { + if (device->showControlPanel()) + deviceManager.restartLastAudioDevice(); - getTopLevelComponent()->toFront (true); - } + getTopLevelComponent()->toFront (true); + } } void AudioDeviceSelectorComponent::comboBoxChanged (ComboBox* comboBoxThatHasChanged) { - if (comboBoxThatHasChanged == deviceTypeDropDown) - { - AudioIODeviceType* const type = deviceManager.getAvailableDeviceTypes() [deviceTypeDropDown->getSelectedId() - 1]; + if (comboBoxThatHasChanged == deviceTypeDropDown) + { + AudioIODeviceType* const type = deviceManager.getAvailableDeviceTypes() [deviceTypeDropDown->getSelectedId() - 1]; - if (type != 0) - { - deleteAndZero (audioDeviceSettingsComp); + if (type != 0) + { + deleteAndZero (audioDeviceSettingsComp); - deviceManager.setCurrentAudioDeviceType (type->getTypeName(), true); + deviceManager.setCurrentAudioDeviceType (type->getTypeName(), true); - changeListenerCallback (0); // needed in case the type hasn't actally changed - } - } - else if (comboBoxThatHasChanged == midiOutputSelector) - { - deviceManager.setDefaultMidiOutput (midiOutputSelector->getText()); - } + changeListenerCallback (0); // needed in case the type hasn't actally changed + } + } + else if (comboBoxThatHasChanged == midiOutputSelector) + { + deviceManager.setDefaultMidiOutput (midiOutputSelector->getText()); + } } void AudioDeviceSelectorComponent::changeListenerCallback (void*) { - if (deviceTypeDropDown != 0) - { - deviceTypeDropDown->setText (deviceManager.getCurrentAudioDeviceType(), false); - } + if (deviceTypeDropDown != 0) + { + deviceTypeDropDown->setText (deviceManager.getCurrentAudioDeviceType(), false); + } - if (audioDeviceSettingsComp == 0 - || audioDeviceSettingsCompType != deviceManager.getCurrentAudioDeviceType()) - { - audioDeviceSettingsCompType = deviceManager.getCurrentAudioDeviceType(); + if (audioDeviceSettingsComp == 0 + || audioDeviceSettingsCompType != deviceManager.getCurrentAudioDeviceType()) + { + audioDeviceSettingsCompType = deviceManager.getCurrentAudioDeviceType(); - deleteAndZero (audioDeviceSettingsComp); + deleteAndZero (audioDeviceSettingsComp); - AudioIODeviceType* const type - = deviceManager.getAvailableDeviceTypes() [deviceTypeDropDown == 0 - ? 0 : deviceTypeDropDown->getSelectedId() - 1]; + AudioIODeviceType* const type + = deviceManager.getAvailableDeviceTypes() [deviceTypeDropDown == 0 + ? 0 : deviceTypeDropDown->getSelectedId() - 1]; - if (type != 0) - { - AudioIODeviceType::DeviceSetupDetails details; - details.manager = &deviceManager; - details.minNumInputChannels = minInputChannels; - details.maxNumInputChannels = maxInputChannels; - details.minNumOutputChannels = minOutputChannels; - details.maxNumOutputChannels = maxOutputChannels; - details.useStereoPairs = showChannelsAsStereoPairs; + if (type != 0) + { + AudioIODeviceType::DeviceSetupDetails details; + details.manager = &deviceManager; + details.minNumInputChannels = minInputChannels; + details.maxNumInputChannels = maxInputChannels; + details.minNumOutputChannels = minOutputChannels; + details.maxNumOutputChannels = maxOutputChannels; + details.useStereoPairs = showChannelsAsStereoPairs; - audioDeviceSettingsComp = new AudioDeviceSettingsPanel (type, details, hideAdvancedOptionsWithButton); + audioDeviceSettingsComp = new AudioDeviceSettingsPanel (type, details, hideAdvancedOptionsWithButton); - if (audioDeviceSettingsComp != 0) - { - addAndMakeVisible (audioDeviceSettingsComp); - audioDeviceSettingsComp->resized(); - } - } - } + if (audioDeviceSettingsComp != 0) + { + addAndMakeVisible (audioDeviceSettingsComp); + audioDeviceSettingsComp->resized(); + } + } + } - if (midiInputsList != 0) - { - midiInputsList->updateContent(); - midiInputsList->repaint(); - } + if (midiInputsList != 0) + { + midiInputsList->updateContent(); + midiInputsList->repaint(); + } - if (midiOutputSelector != 0) - { - midiOutputSelector->clear(); + if (midiOutputSelector != 0) + { + midiOutputSelector->clear(); - const StringArray midiOuts (MidiOutput::getDevices()); + const StringArray midiOuts (MidiOutput::getDevices()); - midiOutputSelector->addItem (TRANS("<< none >>"), -1); - midiOutputSelector->addSeparator(); + midiOutputSelector->addItem (TRANS("<< none >>"), -1); + midiOutputSelector->addSeparator(); - for (int i = 0; i < midiOuts.size(); ++i) - midiOutputSelector->addItem (midiOuts[i], i + 1); + for (int i = 0; i < midiOuts.size(); ++i) + midiOutputSelector->addItem (midiOuts[i], i + 1); - int current = -1; + int current = -1; - if (deviceManager.getDefaultMidiOutput() != 0) - current = 1 + midiOuts.indexOf (deviceManager.getDefaultMidiOutputName()); + if (deviceManager.getDefaultMidiOutput() != 0) + current = 1 + midiOuts.indexOf (deviceManager.getDefaultMidiOutputName()); - midiOutputSelector->setSelectedId (current, true); - } + midiOutputSelector->setSelectedId (current, true); + } - resized(); + resized(); } END_JUCE_NAMESPACE @@ -72932,14 +72737,14 @@ BEGIN_JUCE_NAMESPACE BubbleComponent::BubbleComponent() : side (0), - allowablePlacements (above | below | left | right), - arrowTipX (0.0f), - arrowTipY (0.0f) + allowablePlacements (above | below | left | right), + arrowTipX (0.0f), + arrowTipY (0.0f) { - setInterceptsMouseClicks (false, false); + setInterceptsMouseClicks (false, false); - shadow.setShadowProperties (5.0f, 0.35f, 0, 0); - setComponentEffect (&shadow); + shadow.setShadowProperties (5.0f, 0.35f, 0, 0); + setComponentEffect (&shadow); } BubbleComponent::~BubbleComponent() @@ -72948,160 +72753,160 @@ BubbleComponent::~BubbleComponent() void BubbleComponent::paint (Graphics& g) { - int x = content.getX(); - int y = content.getY(); - int w = content.getWidth(); - int h = content.getHeight(); + int x = content.getX(); + int y = content.getY(); + int w = content.getWidth(); + int h = content.getHeight(); - int cw, ch; - getContentSize (cw, ch); + int cw, ch; + getContentSize (cw, ch); - if (side == 3) - x += w - cw; - else if (side != 1) - x += (w - cw) / 2; + if (side == 3) + x += w - cw; + else if (side != 1) + x += (w - cw) / 2; - w = cw; + w = cw; - if (side == 2) - y += h - ch; - else if (side != 0) - y += (h - ch) / 2; + if (side == 2) + y += h - ch; + else if (side != 0) + y += (h - ch) / 2; - h = ch; + h = ch; - getLookAndFeel().drawBubble (g, arrowTipX, arrowTipY, - (float) x, (float) y, - (float) w, (float) h); + getLookAndFeel().drawBubble (g, arrowTipX, arrowTipY, + (float) x, (float) y, + (float) w, (float) h); - const int cx = x + (w - cw) / 2; - const int cy = y + (h - ch) / 2; + const int cx = x + (w - cw) / 2; + const int cy = y + (h - ch) / 2; - const int indent = 3; + const int indent = 3; - g.setOrigin (cx + indent, cy + indent); - g.reduceClipRegion (0, 0, cw - indent * 2, ch - indent * 2); + g.setOrigin (cx + indent, cy + indent); + g.reduceClipRegion (0, 0, cw - indent * 2, ch - indent * 2); - paintContent (g, cw - indent * 2, ch - indent * 2); + paintContent (g, cw - indent * 2, ch - indent * 2); } void BubbleComponent::setAllowedPlacement (const int newPlacement) { - allowablePlacements = newPlacement; + allowablePlacements = newPlacement; } void BubbleComponent::setPosition (Component* componentToPointTo) { - jassert (componentToPointTo->isValidComponent()); + jassert (componentToPointTo->isValidComponent()); - int tx = 0; - int ty = 0; + int tx = 0; + int ty = 0; - if (getParentComponent() != 0) - componentToPointTo->relativePositionToOtherComponent (getParentComponent(), tx, ty); - else - componentToPointTo->relativePositionToGlobal (tx, ty); + if (getParentComponent() != 0) + componentToPointTo->relativePositionToOtherComponent (getParentComponent(), tx, ty); + else + componentToPointTo->relativePositionToGlobal (tx, ty); - setPosition (Rectangle (tx, ty, componentToPointTo->getWidth(), componentToPointTo->getHeight())); + setPosition (Rectangle (tx, ty, componentToPointTo->getWidth(), componentToPointTo->getHeight())); } void BubbleComponent::setPosition (const int arrowTipX_, - const int arrowTipY_) + const int arrowTipY_) { - setPosition (Rectangle (arrowTipX_, arrowTipY_, 1, 1)); + setPosition (Rectangle (arrowTipX_, arrowTipY_, 1, 1)); } void BubbleComponent::setPosition (const Rectangle& rectangleToPointTo) { - Rectangle availableSpace; + Rectangle availableSpace; - if (getParentComponent() != 0) - { - availableSpace.setSize (getParentComponent()->getWidth(), - getParentComponent()->getHeight()); - } - else - { - availableSpace = getParentMonitorArea(); - } + if (getParentComponent() != 0) + { + availableSpace.setSize (getParentComponent()->getWidth(), + getParentComponent()->getHeight()); + } + else + { + availableSpace = getParentMonitorArea(); + } - int x = 0; - int y = 0; - int w = 150; - int h = 30; + int x = 0; + int y = 0; + int w = 150; + int h = 30; - getContentSize (w, h); - w += 30; - h += 30; + getContentSize (w, h); + w += 30; + h += 30; - const float edgeIndent = 2.0f; - const int arrowLength = jmin (10, h / 3, w / 3); + const float edgeIndent = 2.0f; + const int arrowLength = jmin (10, h / 3, w / 3); - int spaceAbove = ((allowablePlacements & above) != 0) ? jmax (0, rectangleToPointTo.getY() - availableSpace.getY()) : -1; - int spaceBelow = ((allowablePlacements & below) != 0) ? jmax (0, availableSpace.getBottom() - rectangleToPointTo.getBottom()) : -1; - int spaceLeft = ((allowablePlacements & left) != 0) ? jmax (0, rectangleToPointTo.getX() - availableSpace.getX()) : -1; - int spaceRight = ((allowablePlacements & right) != 0) ? jmax (0, availableSpace.getRight() - rectangleToPointTo.getRight()) : -1; + int spaceAbove = ((allowablePlacements & above) != 0) ? jmax (0, rectangleToPointTo.getY() - availableSpace.getY()) : -1; + int spaceBelow = ((allowablePlacements & below) != 0) ? jmax (0, availableSpace.getBottom() - rectangleToPointTo.getBottom()) : -1; + int spaceLeft = ((allowablePlacements & left) != 0) ? jmax (0, rectangleToPointTo.getX() - availableSpace.getX()) : -1; + int spaceRight = ((allowablePlacements & right) != 0) ? jmax (0, availableSpace.getRight() - rectangleToPointTo.getRight()) : -1; - // look at whether the component is elongated, and if so, try to position next to its longer dimension. - if (rectangleToPointTo.getWidth() > rectangleToPointTo.getHeight() * 2 - && (spaceAbove > h + 20 || spaceBelow > h + 20)) - { - spaceLeft = spaceRight = 0; - } - else if (rectangleToPointTo.getWidth() < rectangleToPointTo.getHeight() / 2 - && (spaceLeft > w + 20 || spaceRight > w + 20)) - { - spaceAbove = spaceBelow = 0; - } + // look at whether the component is elongated, and if so, try to position next to its longer dimension. + if (rectangleToPointTo.getWidth() > rectangleToPointTo.getHeight() * 2 + && (spaceAbove > h + 20 || spaceBelow > h + 20)) + { + spaceLeft = spaceRight = 0; + } + else if (rectangleToPointTo.getWidth() < rectangleToPointTo.getHeight() / 2 + && (spaceLeft > w + 20 || spaceRight > w + 20)) + { + spaceAbove = spaceBelow = 0; + } - if (jmax (spaceAbove, spaceBelow) >= jmax (spaceLeft, spaceRight)) - { - x = rectangleToPointTo.getX() + (rectangleToPointTo.getWidth() - w) / 2; - arrowTipX = w * 0.5f; - content.setSize (w, h - arrowLength); + if (jmax (spaceAbove, spaceBelow) >= jmax (spaceLeft, spaceRight)) + { + x = rectangleToPointTo.getX() + (rectangleToPointTo.getWidth() - w) / 2; + arrowTipX = w * 0.5f; + content.setSize (w, h - arrowLength); - if (spaceAbove >= spaceBelow) - { - // above - y = rectangleToPointTo.getY() - h; - content.setPosition (0, 0); - arrowTipY = h - edgeIndent; - side = 2; - } - else - { - // below - y = rectangleToPointTo.getBottom(); - content.setPosition (0, arrowLength); - arrowTipY = edgeIndent; - side = 0; - } - } - else - { - y = rectangleToPointTo.getY() + (rectangleToPointTo.getHeight() - h) / 2; - arrowTipY = h * 0.5f; - content.setSize (w - arrowLength, h); + if (spaceAbove >= spaceBelow) + { + // above + y = rectangleToPointTo.getY() - h; + content.setPosition (0, 0); + arrowTipY = h - edgeIndent; + side = 2; + } + else + { + // below + y = rectangleToPointTo.getBottom(); + content.setPosition (0, arrowLength); + arrowTipY = edgeIndent; + side = 0; + } + } + else + { + y = rectangleToPointTo.getY() + (rectangleToPointTo.getHeight() - h) / 2; + arrowTipY = h * 0.5f; + content.setSize (w - arrowLength, h); - if (spaceLeft > spaceRight) - { - // on the left - x = rectangleToPointTo.getX() - w; - content.setPosition (0, 0); - arrowTipX = w - edgeIndent; - side = 3; - } - else - { - // on the right - x = rectangleToPointTo.getRight(); - content.setPosition (arrowLength, 0); - arrowTipX = edgeIndent; - side = 1; - } - } + if (spaceLeft > spaceRight) + { + // on the left + x = rectangleToPointTo.getX() - w; + content.setPosition (0, 0); + arrowTipX = w - edgeIndent; + side = 3; + } + else + { + // on the right + x = rectangleToPointTo.getRight(); + content.setPosition (arrowLength, 0); + arrowTipX = edgeIndent; + side = 1; + } + } - setBounds (x, y, w, h); + setBounds (x, y, w, h); } END_JUCE_NAMESPACE @@ -73112,100 +72917,100 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE BubbleMessageComponent::BubbleMessageComponent (int fadeOutLengthMs) - : fadeOutLength (fadeOutLengthMs), - deleteAfterUse (false) + : fadeOutLength (fadeOutLengthMs), + deleteAfterUse (false) { } BubbleMessageComponent::~BubbleMessageComponent() { - fadeOutComponent (fadeOutLength); + fadeOutComponent (fadeOutLength); } void BubbleMessageComponent::showAt (int x, int y, - const String& text, - const int numMillisecondsBeforeRemoving, - const bool removeWhenMouseClicked, - const bool deleteSelfAfterUse) + const String& text, + const int numMillisecondsBeforeRemoving, + const bool removeWhenMouseClicked, + const bool deleteSelfAfterUse) { - textLayout.clear(); - textLayout.setText (text, Font (14.0f)); - textLayout.layout (256, Justification::centredLeft, true); + textLayout.clear(); + textLayout.setText (text, Font (14.0f)); + textLayout.layout (256, Justification::centredLeft, true); - setPosition (x, y); + setPosition (x, y); - init (numMillisecondsBeforeRemoving, removeWhenMouseClicked, deleteSelfAfterUse); + init (numMillisecondsBeforeRemoving, removeWhenMouseClicked, deleteSelfAfterUse); } void BubbleMessageComponent::showAt (Component* const component, - const String& text, - const int numMillisecondsBeforeRemoving, - const bool removeWhenMouseClicked, - const bool deleteSelfAfterUse) + const String& text, + const int numMillisecondsBeforeRemoving, + const bool removeWhenMouseClicked, + const bool deleteSelfAfterUse) { - textLayout.clear(); - textLayout.setText (text, Font (14.0f)); - textLayout.layout (256, Justification::centredLeft, true); + textLayout.clear(); + textLayout.setText (text, Font (14.0f)); + textLayout.layout (256, Justification::centredLeft, true); - setPosition (component); + setPosition (component); - init (numMillisecondsBeforeRemoving, removeWhenMouseClicked, deleteSelfAfterUse); + init (numMillisecondsBeforeRemoving, removeWhenMouseClicked, deleteSelfAfterUse); } void BubbleMessageComponent::init (const int numMillisecondsBeforeRemoving, - const bool removeWhenMouseClicked, - const bool deleteSelfAfterUse) + const bool removeWhenMouseClicked, + const bool deleteSelfAfterUse) { - setVisible (true); + setVisible (true); - deleteAfterUse = deleteSelfAfterUse; + deleteAfterUse = deleteSelfAfterUse; - if (numMillisecondsBeforeRemoving > 0) - expiryTime = Time::getMillisecondCounter() + numMillisecondsBeforeRemoving; - else - expiryTime = 0; + if (numMillisecondsBeforeRemoving > 0) + expiryTime = Time::getMillisecondCounter() + numMillisecondsBeforeRemoving; + else + expiryTime = 0; - startTimer (77); + startTimer (77); - mouseClickCounter = Desktop::getInstance().getMouseButtonClickCounter(); + mouseClickCounter = Desktop::getInstance().getMouseButtonClickCounter(); - if (! (removeWhenMouseClicked && isShowing())) - mouseClickCounter += 0xfffff; + if (! (removeWhenMouseClicked && isShowing())) + mouseClickCounter += 0xfffff; - repaint(); + repaint(); } void BubbleMessageComponent::getContentSize (int& w, int& h) { - w = textLayout.getWidth() + 16; - h = textLayout.getHeight() + 16; + w = textLayout.getWidth() + 16; + h = textLayout.getHeight() + 16; } void BubbleMessageComponent::paintContent (Graphics& g, int w, int h) { - g.setColour (findColour (TooltipWindow::textColourId)); + g.setColour (findColour (TooltipWindow::textColourId)); - textLayout.drawWithin (g, 0, 0, w, h, Justification::centred); + textLayout.drawWithin (g, 0, 0, w, h, Justification::centred); } void BubbleMessageComponent::timerCallback() { - if (Desktop::getInstance().getMouseButtonClickCounter() > mouseClickCounter) - { - stopTimer(); - setVisible (false); + if (Desktop::getInstance().getMouseButtonClickCounter() > mouseClickCounter) + { + stopTimer(); + setVisible (false); - if (deleteAfterUse) - delete this; - } - else if (expiryTime != 0 && Time::getMillisecondCounter() > expiryTime) - { - stopTimer(); - fadeOutComponent (fadeOutLength); + if (deleteAfterUse) + delete this; + } + else if (expiryTime != 0 && Time::getMillisecondCounter() > expiryTime) + { + stopTimer(); + fadeOutComponent (fadeOutLength); - if (deleteAfterUse) - delete this; - } + if (deleteAfterUse) + delete this; + } } END_JUCE_NAMESPACE @@ -73221,588 +73026,588 @@ static const int swatchHeight = 22; class ColourComponentSlider : public Slider { public: - ColourComponentSlider (const String& name) - : Slider (name) - { - setRange (0.0, 255.0, 1.0); - } + ColourComponentSlider (const String& name) + : Slider (name) + { + setRange (0.0, 255.0, 1.0); + } - ~ColourComponentSlider() - { - } + ~ColourComponentSlider() + { + } - const String getTextFromValue (double value) - { - return String::formatted (T("%02X"), (int) value); - } + const String getTextFromValue (double value) + { + return String::formatted (T("%02X"), (int) value); + } - double getValueFromText (const String& text) - { - return (double) text.getHexValue32(); - } + double getValueFromText (const String& text) + { + return (double) text.getHexValue32(); + } private: - ColourComponentSlider (const ColourComponentSlider&); - const ColourComponentSlider& operator= (const ColourComponentSlider&); + ColourComponentSlider (const ColourComponentSlider&); + const ColourComponentSlider& operator= (const ColourComponentSlider&); }; class ColourSpaceMarker : public Component { public: - ColourSpaceMarker() - { - setInterceptsMouseClicks (false, false); - } + ColourSpaceMarker() + { + setInterceptsMouseClicks (false, false); + } - ~ColourSpaceMarker() - { - } + ~ColourSpaceMarker() + { + } - void paint (Graphics& g) - { - g.setColour (Colour::greyLevel (0.1f)); - g.drawEllipse (1.0f, 1.0f, getWidth() - 2.0f, getHeight() - 2.0f, 1.0f); - g.setColour (Colour::greyLevel (0.9f)); - g.drawEllipse (2.0f, 2.0f, getWidth() - 4.0f, getHeight() - 4.0f, 1.0f); - } + void paint (Graphics& g) + { + g.setColour (Colour::greyLevel (0.1f)); + g.drawEllipse (1.0f, 1.0f, getWidth() - 2.0f, getHeight() - 2.0f, 1.0f); + g.setColour (Colour::greyLevel (0.9f)); + g.drawEllipse (2.0f, 2.0f, getWidth() - 4.0f, getHeight() - 4.0f, 1.0f); + } private: - ColourSpaceMarker (const ColourSpaceMarker&); - const ColourSpaceMarker& operator= (const ColourSpaceMarker&); + ColourSpaceMarker (const ColourSpaceMarker&); + const ColourSpaceMarker& operator= (const ColourSpaceMarker&); }; class ColourSpaceView : public Component { - ColourSelector* const owner; - float& h; - float& s; - float& v; - float lastHue; - ColourSpaceMarker* marker; - const int edge; + ColourSelector* const owner; + float& h; + float& s; + float& v; + float lastHue; + ColourSpaceMarker* marker; + const int edge; public: - ColourSpaceView (ColourSelector* owner_, - float& h_, float& s_, float& v_, - const int edgeSize) - : owner (owner_), - h (h_), s (s_), v (v_), - lastHue (0.0f), - edge (edgeSize) - { - addAndMakeVisible (marker = new ColourSpaceMarker()); - setMouseCursor (MouseCursor::CrosshairCursor); - } + ColourSpaceView (ColourSelector* owner_, + float& h_, float& s_, float& v_, + const int edgeSize) + : owner (owner_), + h (h_), s (s_), v (v_), + lastHue (0.0f), + edge (edgeSize) + { + addAndMakeVisible (marker = new ColourSpaceMarker()); + setMouseCursor (MouseCursor::CrosshairCursor); + } - ~ColourSpaceView() - { - deleteAllChildren(); - } + ~ColourSpaceView() + { + deleteAllChildren(); + } - void paint (Graphics& g) - { - if (colours == 0) - { - const int width = getWidth() / 2; - const int height = getHeight() / 2; - colours = new Image (Image::RGB, width, height, false); + void paint (Graphics& g) + { + if (colours == 0) + { + const int width = getWidth() / 2; + const int height = getHeight() / 2; + colours = new Image (Image::RGB, width, height, false); - Image::BitmapData pixels (*colours, 0, 0, width, height, true); + Image::BitmapData pixels (*colours, 0, 0, width, height, true); - for (int y = 0; y < height; ++y) - { - const float v = 1.0f - y / (float) height; + for (int y = 0; y < height; ++y) + { + const float v = 1.0f - y / (float) height; - for (int x = 0; x < width; ++x) - { - const float s = x / (float) width; - const Colour col (h, s, v, 1.0f); + for (int x = 0; x < width; ++x) + { + const float s = x / (float) width; + const Colour col (h, s, v, 1.0f); - PixelRGB* const pix = (PixelRGB*) pixels.getPixelPointer (x, y); - pix->set (col.getPixelARGB()); - } - } - } + PixelRGB* const pix = (PixelRGB*) pixels.getPixelPointer (x, y); + pix->set (col.getPixelARGB()); + } + } + } - g.setOpacity (1.0f); - g.drawImage (colours, edge, edge, getWidth() - edge * 2, getHeight() - edge * 2, - 0, 0, colours->getWidth(), colours->getHeight()); - } + g.setOpacity (1.0f); + g.drawImage (colours, edge, edge, getWidth() - edge * 2, getHeight() - edge * 2, + 0, 0, colours->getWidth(), colours->getHeight()); + } - void mouseDown (const MouseEvent& e) - { - mouseDrag (e); - } + void mouseDown (const MouseEvent& e) + { + mouseDrag (e); + } - void mouseDrag (const MouseEvent& e) - { - const float s = (e.x - edge) / (float) (getWidth() - edge * 2); - const float v = 1.0f - (e.y - edge) / (float) (getHeight() - edge * 2); + void mouseDrag (const MouseEvent& e) + { + const float s = (e.x - edge) / (float) (getWidth() - edge * 2); + const float v = 1.0f - (e.y - edge) / (float) (getHeight() - edge * 2); - owner->setSV (s, v); - } + owner->setSV (s, v); + } - void updateIfNeeded() - { - if (lastHue != h) - { - lastHue = h; - colours = 0; - repaint(); - } + void updateIfNeeded() + { + if (lastHue != h) + { + lastHue = h; + colours = 0; + repaint(); + } - updateMarker(); - } + updateMarker(); + } - void resized() - { - colours = 0; - updateMarker(); - } + void resized() + { + colours = 0; + updateMarker(); + } private: - ScopedPointer colours; + ScopedPointer colours; - void updateMarker() const throw() - { - marker->setBounds (roundFloatToInt ((getWidth() - edge * 2) * s), - roundFloatToInt ((getHeight() - edge * 2) * (1.0f - v)), - edge * 2, edge * 2); - } + void updateMarker() const throw() + { + marker->setBounds (roundToInt ((getWidth() - edge * 2) * s), + roundToInt ((getHeight() - edge * 2) * (1.0f - v)), + edge * 2, edge * 2); + } - ColourSpaceView (const ColourSpaceView&); - const ColourSpaceView& operator= (const ColourSpaceView&); + ColourSpaceView (const ColourSpaceView&); + const ColourSpaceView& operator= (const ColourSpaceView&); }; class HueSelectorMarker : public Component { public: - HueSelectorMarker() - { - setInterceptsMouseClicks (false, false); - } + HueSelectorMarker() + { + setInterceptsMouseClicks (false, false); + } - ~HueSelectorMarker() - { - } + ~HueSelectorMarker() + { + } - void paint (Graphics& g) - { - Path p; - p.addTriangle (1.0f, 1.0f, - getWidth() * 0.3f, getHeight() * 0.5f, - 1.0f, getHeight() - 1.0f); + void paint (Graphics& g) + { + Path p; + p.addTriangle (1.0f, 1.0f, + getWidth() * 0.3f, getHeight() * 0.5f, + 1.0f, getHeight() - 1.0f); - p.addTriangle (getWidth() - 1.0f, 1.0f, - getWidth() * 0.7f, getHeight() * 0.5f, - getWidth() - 1.0f, getHeight() - 1.0f); + p.addTriangle (getWidth() - 1.0f, 1.0f, + getWidth() * 0.7f, getHeight() * 0.5f, + getWidth() - 1.0f, getHeight() - 1.0f); - g.setColour (Colours::white.withAlpha (0.75f)); - g.fillPath (p); + g.setColour (Colours::white.withAlpha (0.75f)); + g.fillPath (p); - g.setColour (Colours::black.withAlpha (0.75f)); - g.strokePath (p, PathStrokeType (1.2f)); - } + g.setColour (Colours::black.withAlpha (0.75f)); + g.strokePath (p, PathStrokeType (1.2f)); + } private: - HueSelectorMarker (const HueSelectorMarker&); - const HueSelectorMarker& operator= (const HueSelectorMarker&); + HueSelectorMarker (const HueSelectorMarker&); + const HueSelectorMarker& operator= (const HueSelectorMarker&); }; class HueSelectorComp : public Component { public: - HueSelectorComp (ColourSelector* owner_, - float& h_, float& s_, float& v_, - const int edgeSize) - : owner (owner_), - h (h_), s (s_), v (v_), - lastHue (0.0f), - edge (edgeSize) - { - addAndMakeVisible (marker = new HueSelectorMarker()); - } + HueSelectorComp (ColourSelector* owner_, + float& h_, float& s_, float& v_, + const int edgeSize) + : owner (owner_), + h (h_), s (s_), v (v_), + lastHue (0.0f), + edge (edgeSize) + { + addAndMakeVisible (marker = new HueSelectorMarker()); + } - ~HueSelectorComp() - { - deleteAllChildren(); - } + ~HueSelectorComp() + { + deleteAllChildren(); + } - void paint (Graphics& g) - { - const float yScale = 1.0f / (getHeight() - edge * 2); + void paint (Graphics& g) + { + const float yScale = 1.0f / (getHeight() - edge * 2); - const Rectangle clip (g.getClipBounds()); + const Rectangle clip (g.getClipBounds()); - for (int y = jmin (clip.getBottom(), getHeight() - edge); --y >= jmax (edge, clip.getY());) - { - g.setColour (Colour ((y - edge) * yScale, 1.0f, 1.0f, 1.0f)); - g.fillRect (edge, y, getWidth() - edge * 2, 1); - } - } + for (int y = jmin (clip.getBottom(), getHeight() - edge); --y >= jmax (edge, clip.getY());) + { + g.setColour (Colour ((y - edge) * yScale, 1.0f, 1.0f, 1.0f)); + g.fillRect (edge, y, getWidth() - edge * 2, 1); + } + } - void resized() - { - marker->setBounds (0, roundFloatToInt ((getHeight() - edge * 2) * h), - getWidth(), edge * 2); - } + void resized() + { + marker->setBounds (0, roundToInt ((getHeight() - edge * 2) * h), + getWidth(), edge * 2); + } - void mouseDown (const MouseEvent& e) - { - mouseDrag (e); - } + void mouseDown (const MouseEvent& e) + { + mouseDrag (e); + } - void mouseDrag (const MouseEvent& e) - { - const float hue = (e.y - edge) / (float) (getHeight() - edge * 2); + void mouseDrag (const MouseEvent& e) + { + const float hue = (e.y - edge) / (float) (getHeight() - edge * 2); - owner->setHue (hue); - } + owner->setHue (hue); + } - void updateIfNeeded() - { - resized(); - } + void updateIfNeeded() + { + resized(); + } private: - ColourSelector* const owner; - float& h; - float& s; - float& v; - float lastHue; - HueSelectorMarker* marker; - const int edge; + ColourSelector* const owner; + float& h; + float& s; + float& v; + float lastHue; + HueSelectorMarker* marker; + const int edge; - HueSelectorComp (const HueSelectorComp&); - const HueSelectorComp& operator= (const HueSelectorComp&); + HueSelectorComp (const HueSelectorComp&); + const HueSelectorComp& operator= (const HueSelectorComp&); }; class ColourSelector::SwatchComponent : public Component { public: - SwatchComponent (ColourSelector* owner_, int index_) - : owner (owner_), - index (index_) - { - } + SwatchComponent (ColourSelector* owner_, int index_) + : owner (owner_), + index (index_) + { + } - ~SwatchComponent() - { - } + ~SwatchComponent() + { + } - void paint (Graphics& g) - { - const Colour colour (owner->getSwatchColour (index)); + void paint (Graphics& g) + { + const Colour colour (owner->getSwatchColour (index)); - g.fillCheckerBoard (0, 0, getWidth(), getHeight(), - 6, 6, - Colour (0xffdddddd).overlaidWith (colour), - Colour (0xffffffff).overlaidWith (colour)); - } + g.fillCheckerBoard (0, 0, getWidth(), getHeight(), + 6, 6, + Colour (0xffdddddd).overlaidWith (colour), + Colour (0xffffffff).overlaidWith (colour)); + } - void mouseDown (const MouseEvent&) - { - PopupMenu m; - m.addItem (1, TRANS("Use this swatch as the current colour")); - m.addSeparator(); - m.addItem (2, TRANS("Set this swatch to the current colour")); + void mouseDown (const MouseEvent&) + { + PopupMenu m; + m.addItem (1, TRANS("Use this swatch as the current colour")); + m.addSeparator(); + m.addItem (2, TRANS("Set this swatch to the current colour")); - const int r = m.showAt (this); + const int r = m.showAt (this); - if (r == 1) - { - owner->setCurrentColour (owner->getSwatchColour (index)); - } - else if (r == 2) - { - if (owner->getSwatchColour (index) != owner->getCurrentColour()) - { - owner->setSwatchColour (index, owner->getCurrentColour()); - repaint(); - } - } - } + if (r == 1) + { + owner->setCurrentColour (owner->getSwatchColour (index)); + } + else if (r == 2) + { + if (owner->getSwatchColour (index) != owner->getCurrentColour()) + { + owner->setSwatchColour (index, owner->getCurrentColour()); + repaint(); + } + } + } private: - ColourSelector* const owner; - const int index; + ColourSelector* const owner; + const int index; - SwatchComponent (const SwatchComponent&); - const SwatchComponent& operator= (const SwatchComponent&); + SwatchComponent (const SwatchComponent&); + const SwatchComponent& operator= (const SwatchComponent&); }; ColourSelector::ColourSelector (const int flags_, - const int edgeGap_, - const int gapAroundColourSpaceComponent) - : colour (Colours::white), - flags (flags_), - topSpace (0), - edgeGap (edgeGap_) + const int edgeGap_, + const int gapAroundColourSpaceComponent) + : colour (Colours::white), + flags (flags_), + topSpace (0), + edgeGap (edgeGap_) { - // not much point having a selector with no components in it! - jassert ((flags_ & (showColourAtTop | showSliders | showColourspace)) != 0); + // not much point having a selector with no components in it! + jassert ((flags_ & (showColourAtTop | showSliders | showColourspace)) != 0); - updateHSV(); + updateHSV(); - if ((flags & showSliders) != 0) - { - addAndMakeVisible (sliders[0] = new ColourComponentSlider (TRANS ("red"))); - addAndMakeVisible (sliders[1] = new ColourComponentSlider (TRANS ("green"))); - addAndMakeVisible (sliders[2] = new ColourComponentSlider (TRANS ("blue"))); - addChildComponent (sliders[3] = new ColourComponentSlider (TRANS ("alpha"))); + if ((flags & showSliders) != 0) + { + addAndMakeVisible (sliders[0] = new ColourComponentSlider (TRANS ("red"))); + addAndMakeVisible (sliders[1] = new ColourComponentSlider (TRANS ("green"))); + addAndMakeVisible (sliders[2] = new ColourComponentSlider (TRANS ("blue"))); + addChildComponent (sliders[3] = new ColourComponentSlider (TRANS ("alpha"))); - sliders[3]->setVisible ((flags & showAlphaChannel) != 0); + sliders[3]->setVisible ((flags & showAlphaChannel) != 0); - for (int i = 4; --i >= 0;) - sliders[i]->addListener (this); - } - else - { - zeromem (sliders, sizeof (sliders)); - } + for (int i = 4; --i >= 0;) + sliders[i]->addListener (this); + } + else + { + zeromem (sliders, sizeof (sliders)); + } - if ((flags & showColourspace) != 0) - { - addAndMakeVisible (colourSpace = new ColourSpaceView (this, h, s, v, gapAroundColourSpaceComponent)); - addAndMakeVisible (hueSelector = new HueSelectorComp (this, h, s, v, gapAroundColourSpaceComponent)); - } - else - { - colourSpace = 0; - hueSelector = 0; - } + if ((flags & showColourspace) != 0) + { + addAndMakeVisible (colourSpace = new ColourSpaceView (this, h, s, v, gapAroundColourSpaceComponent)); + addAndMakeVisible (hueSelector = new HueSelectorComp (this, h, s, v, gapAroundColourSpaceComponent)); + } + else + { + colourSpace = 0; + hueSelector = 0; + } - update(); + update(); } ColourSelector::~ColourSelector() { - dispatchPendingMessages(); - swatchComponents.clear(); - deleteAllChildren(); + dispatchPendingMessages(); + swatchComponents.clear(); + deleteAllChildren(); } const Colour ColourSelector::getCurrentColour() const { - return ((flags & showAlphaChannel) != 0) ? colour - : colour.withAlpha ((uint8) 0xff); + return ((flags & showAlphaChannel) != 0) ? colour + : colour.withAlpha ((uint8) 0xff); } void ColourSelector::setCurrentColour (const Colour& c) { - if (c != colour) - { - colour = ((flags & showAlphaChannel) != 0) ? c : c.withAlpha ((uint8) 0xff); + if (c != colour) + { + colour = ((flags & showAlphaChannel) != 0) ? c : c.withAlpha ((uint8) 0xff); - updateHSV(); - update(); - } + updateHSV(); + update(); + } } void ColourSelector::setHue (float newH) { - newH = jlimit (0.0f, 1.0f, newH); + newH = jlimit (0.0f, 1.0f, newH); - if (h != newH) - { - h = newH; - colour = Colour (h, s, v, colour.getFloatAlpha()); - update(); - } + if (h != newH) + { + h = newH; + colour = Colour (h, s, v, colour.getFloatAlpha()); + update(); + } } void ColourSelector::setSV (float newS, float newV) { - newS = jlimit (0.0f, 1.0f, newS); - newV = jlimit (0.0f, 1.0f, newV); + newS = jlimit (0.0f, 1.0f, newS); + newV = jlimit (0.0f, 1.0f, newV); - if (s != newS || v != newV) - { - s = newS; - v = newV; - colour = Colour (h, s, v, colour.getFloatAlpha()); - update(); - } + if (s != newS || v != newV) + { + s = newS; + v = newV; + colour = Colour (h, s, v, colour.getFloatAlpha()); + update(); + } } void ColourSelector::updateHSV() { - colour.getHSB (h, s, v); + colour.getHSB (h, s, v); } void ColourSelector::update() { - if (sliders[0] != 0) - { - sliders[0]->setValue ((int) colour.getRed()); - sliders[1]->setValue ((int) colour.getGreen()); - sliders[2]->setValue ((int) colour.getBlue()); - sliders[3]->setValue ((int) colour.getAlpha()); - } + if (sliders[0] != 0) + { + sliders[0]->setValue ((int) colour.getRed()); + sliders[1]->setValue ((int) colour.getGreen()); + sliders[2]->setValue ((int) colour.getBlue()); + sliders[3]->setValue ((int) colour.getAlpha()); + } - if (colourSpace != 0) - { - ((ColourSpaceView*) colourSpace)->updateIfNeeded(); - ((HueSelectorComp*) hueSelector)->updateIfNeeded(); - } + if (colourSpace != 0) + { + ((ColourSpaceView*) colourSpace)->updateIfNeeded(); + ((HueSelectorComp*) hueSelector)->updateIfNeeded(); + } - if ((flags & showColourAtTop) != 0) - repaint (0, edgeGap, getWidth(), topSpace - edgeGap); + if ((flags & showColourAtTop) != 0) + repaint (0, edgeGap, getWidth(), topSpace - edgeGap); - sendChangeMessage (this); + sendChangeMessage (this); } void ColourSelector::paint (Graphics& g) { - g.fillAll (findColour (backgroundColourId)); + g.fillAll (findColour (backgroundColourId)); - if ((flags & showColourAtTop) != 0) - { - const Colour colour (getCurrentColour()); + if ((flags & showColourAtTop) != 0) + { + const Colour colour (getCurrentColour()); - g.fillCheckerBoard (edgeGap, edgeGap, getWidth() - edgeGap - edgeGap, topSpace - edgeGap - edgeGap, - 10, 10, - Colour (0xffdddddd).overlaidWith (colour), - Colour (0xffffffff).overlaidWith (colour)); + g.fillCheckerBoard (edgeGap, edgeGap, getWidth() - edgeGap - edgeGap, topSpace - edgeGap - edgeGap, + 10, 10, + Colour (0xffdddddd).overlaidWith (colour), + Colour (0xffffffff).overlaidWith (colour)); - g.setColour (Colours::white.overlaidWith (colour).contrasting()); - g.setFont (14.0f, true); - g.drawText (((flags & showAlphaChannel) != 0) - ? String::formatted (T("#%02X%02X%02X%02X"), - (int) colour.getAlpha(), - (int) colour.getRed(), - (int) colour.getGreen(), - (int) colour.getBlue()) - : String::formatted (T("#%02X%02X%02X"), - (int) colour.getRed(), - (int) colour.getGreen(), - (int) colour.getBlue()), - 0, edgeGap, getWidth(), topSpace - edgeGap * 2, - Justification::centred, false); - } + g.setColour (Colours::white.overlaidWith (colour).contrasting()); + g.setFont (14.0f, true); + g.drawText (((flags & showAlphaChannel) != 0) + ? String::formatted (T("#%02X%02X%02X%02X"), + (int) colour.getAlpha(), + (int) colour.getRed(), + (int) colour.getGreen(), + (int) colour.getBlue()) + : String::formatted (T("#%02X%02X%02X"), + (int) colour.getRed(), + (int) colour.getGreen(), + (int) colour.getBlue()), + 0, edgeGap, getWidth(), topSpace - edgeGap * 2, + Justification::centred, false); + } - if ((flags & showSliders) != 0) - { - g.setColour (findColour (labelTextColourId)); - g.setFont (11.0f); + if ((flags & showSliders) != 0) + { + g.setColour (findColour (labelTextColourId)); + g.setFont (11.0f); - for (int i = 4; --i >= 0;) - { - if (sliders[i]->isVisible()) - g.drawText (sliders[i]->getName() + T(":"), - 0, sliders[i]->getY(), - sliders[i]->getX() - 8, sliders[i]->getHeight(), - Justification::centredRight, false); - } - } + for (int i = 4; --i >= 0;) + { + if (sliders[i]->isVisible()) + g.drawText (sliders[i]->getName() + T(":"), + 0, sliders[i]->getY(), + sliders[i]->getX() - 8, sliders[i]->getHeight(), + Justification::centredRight, false); + } + } } void ColourSelector::resized() { - const int numSliders = ((flags & showAlphaChannel) != 0) ? 4 : 3; - const int numSwatches = getNumSwatches(); + const int numSliders = ((flags & showAlphaChannel) != 0) ? 4 : 3; + const int numSwatches = getNumSwatches(); - const int swatchSpace = numSwatches > 0 ? edgeGap + swatchHeight * ((numSwatches + 7) / swatchesPerRow) : 0; - const int sliderSpace = ((flags & showSliders) != 0) ? jmin (22 * numSliders + edgeGap, proportionOfHeight (0.3f)) : 0; - topSpace = ((flags & showColourAtTop) != 0) ? jmin (30 + edgeGap * 2, proportionOfHeight (0.2f)) : edgeGap; + const int swatchSpace = numSwatches > 0 ? edgeGap + swatchHeight * ((numSwatches + 7) / swatchesPerRow) : 0; + const int sliderSpace = ((flags & showSliders) != 0) ? jmin (22 * numSliders + edgeGap, proportionOfHeight (0.3f)) : 0; + topSpace = ((flags & showColourAtTop) != 0) ? jmin (30 + edgeGap * 2, proportionOfHeight (0.2f)) : edgeGap; - int y = topSpace; + int y = topSpace; - if ((flags & showColourspace) != 0) - { - const int hueWidth = jmin (50, proportionOfWidth (0.15f)); + if ((flags & showColourspace) != 0) + { + const int hueWidth = jmin (50, proportionOfWidth (0.15f)); - colourSpace->setBounds (edgeGap, y, - getWidth() - hueWidth - edgeGap - 4, - getHeight() - topSpace - sliderSpace - swatchSpace - edgeGap); + colourSpace->setBounds (edgeGap, y, + getWidth() - hueWidth - edgeGap - 4, + getHeight() - topSpace - sliderSpace - swatchSpace - edgeGap); - hueSelector->setBounds (colourSpace->getRight() + 4, y, - getWidth() - edgeGap - (colourSpace->getRight() + 4), - colourSpace->getHeight()); + hueSelector->setBounds (colourSpace->getRight() + 4, y, + getWidth() - edgeGap - (colourSpace->getRight() + 4), + colourSpace->getHeight()); - y = getHeight() - sliderSpace - swatchSpace - edgeGap; - } + y = getHeight() - sliderSpace - swatchSpace - edgeGap; + } - if ((flags & showSliders) != 0) - { - const int sliderHeight = jmax (4, sliderSpace / numSliders); + if ((flags & showSliders) != 0) + { + const int sliderHeight = jmax (4, sliderSpace / numSliders); - for (int i = 0; i < numSliders; ++i) - { - sliders[i]->setBounds (proportionOfWidth (0.2f), y, - proportionOfWidth (0.72f), sliderHeight - 2); + for (int i = 0; i < numSliders; ++i) + { + sliders[i]->setBounds (proportionOfWidth (0.2f), y, + proportionOfWidth (0.72f), sliderHeight - 2); - y += sliderHeight; - } - } + y += sliderHeight; + } + } - if (numSwatches > 0) - { - const int startX = 8; - const int xGap = 4; - const int yGap = 4; - const int swatchWidth = (getWidth() - startX * 2) / swatchesPerRow; - y += edgeGap; + if (numSwatches > 0) + { + const int startX = 8; + const int xGap = 4; + const int yGap = 4; + const int swatchWidth = (getWidth() - startX * 2) / swatchesPerRow; + y += edgeGap; - if (swatchComponents.size() != numSwatches) - { - swatchComponents.clear(); + if (swatchComponents.size() != numSwatches) + { + swatchComponents.clear(); - for (int i = 0; i < numSwatches; ++i) - { - SwatchComponent* const sc = new SwatchComponent (this, i); - swatchComponents.add (sc); - addAndMakeVisible (sc); - } - } + for (int i = 0; i < numSwatches; ++i) + { + SwatchComponent* const sc = new SwatchComponent (this, i); + swatchComponents.add (sc); + addAndMakeVisible (sc); + } + } - int x = startX; + int x = startX; - for (int i = 0; i < swatchComponents.size(); ++i) - { - SwatchComponent* const sc = swatchComponents.getUnchecked(i); + for (int i = 0; i < swatchComponents.size(); ++i) + { + SwatchComponent* const sc = swatchComponents.getUnchecked(i); - sc->setBounds (x + xGap / 2, - y + yGap / 2, - swatchWidth - xGap, - swatchHeight - yGap); + sc->setBounds (x + xGap / 2, + y + yGap / 2, + swatchWidth - xGap, + swatchHeight - yGap); - if (((i + 1) % swatchesPerRow) == 0) - { - x = startX; - y += swatchHeight; - } - else - { - x += swatchWidth; - } - } - } + if (((i + 1) % swatchesPerRow) == 0) + { + x = startX; + y += swatchHeight; + } + else + { + x += swatchWidth; + } + } + } } void ColourSelector::sliderValueChanged (Slider*) { - if (sliders[0] != 0) - setCurrentColour (Colour ((uint8) sliders[0]->getValue(), - (uint8) sliders[1]->getValue(), - (uint8) sliders[2]->getValue(), - (uint8) sliders[3]->getValue())); + if (sliders[0] != 0) + setCurrentColour (Colour ((uint8) sliders[0]->getValue(), + (uint8) sliders[1]->getValue(), + (uint8) sliders[2]->getValue(), + (uint8) sliders[3]->getValue())); } int ColourSelector::getNumSwatches() const { - return 0; + return 0; } const Colour ColourSelector::getSwatchColour (const int) const { - jassertfalse // if you've overridden getNumSwatches(), you also need to implement this method - return Colours::black; + jassertfalse // if you've overridden getNumSwatches(), you also need to implement this method + return Colours::black; } void ColourSelector::setSwatchColour (const int, const Colour&) const { - jassertfalse // if you've overridden getNumSwatches(), you also need to implement this method + jassertfalse // if you've overridden getNumSwatches(), you also need to implement this method } END_JUCE_NAMESPACE @@ -73814,157 +73619,157 @@ BEGIN_JUCE_NAMESPACE class ShadowWindow : public Component { - Component* owner; - Image** shadowImageSections; - const int type; // 0 = left, 1 = right, 2 = top, 3 = bottom. left + right are full-height + Component* owner; + Image** shadowImageSections; + const int type; // 0 = left, 1 = right, 2 = top, 3 = bottom. left + right are full-height public: - ShadowWindow (Component* const owner_, - const int type_, - Image** const shadowImageSections_) - : owner (owner_), - shadowImageSections (shadowImageSections_), - type (type_) - { - setInterceptsMouseClicks (false, false); + ShadowWindow (Component* const owner_, + const int type_, + Image** const shadowImageSections_) + : owner (owner_), + shadowImageSections (shadowImageSections_), + type (type_) + { + setInterceptsMouseClicks (false, false); - if (owner_->isOnDesktop()) - { - setSize (1, 1); // to keep the OS happy by not having zero-size windows - addToDesktop (ComponentPeer::windowIgnoresMouseClicks - | ComponentPeer::windowIsTemporary - | ComponentPeer::windowIgnoresKeyPresses); - } - else if (owner_->getParentComponent() != 0) - { - owner_->getParentComponent()->addChildComponent (this); - } - } + if (owner_->isOnDesktop()) + { + setSize (1, 1); // to keep the OS happy by not having zero-size windows + addToDesktop (ComponentPeer::windowIgnoresMouseClicks + | ComponentPeer::windowIsTemporary + | ComponentPeer::windowIgnoresKeyPresses); + } + else if (owner_->getParentComponent() != 0) + { + owner_->getParentComponent()->addChildComponent (this); + } + } - ~ShadowWindow() - { - } + ~ShadowWindow() + { + } - void paint (Graphics& g) - { - Image* const topLeft = shadowImageSections [type * 3]; - Image* const bottomRight = shadowImageSections [type * 3 + 1]; - Image* const filler = shadowImageSections [type * 3 + 2]; + void paint (Graphics& g) + { + Image* const topLeft = shadowImageSections [type * 3]; + Image* const bottomRight = shadowImageSections [type * 3 + 1]; + Image* const filler = shadowImageSections [type * 3 + 2]; - g.setOpacity (1.0f); + g.setOpacity (1.0f); - if (type < 2) - { - int imH = jmin (topLeft->getHeight(), getHeight() / 2); - g.drawImage (topLeft, - 0, 0, topLeft->getWidth(), imH, - 0, 0, topLeft->getWidth(), imH); + if (type < 2) + { + int imH = jmin (topLeft->getHeight(), getHeight() / 2); + g.drawImage (topLeft, + 0, 0, topLeft->getWidth(), imH, + 0, 0, topLeft->getWidth(), imH); - imH = jmin (bottomRight->getHeight(), getHeight() - getHeight() / 2); - g.drawImage (bottomRight, - 0, getHeight() - imH, bottomRight->getWidth(), imH, - 0, bottomRight->getHeight() - imH, bottomRight->getWidth(), imH); + imH = jmin (bottomRight->getHeight(), getHeight() - getHeight() / 2); + g.drawImage (bottomRight, + 0, getHeight() - imH, bottomRight->getWidth(), imH, + 0, bottomRight->getHeight() - imH, bottomRight->getWidth(), imH); - g.setTiledImageFill (*filler, 0, 0, 1.0f); - g.fillRect (0, topLeft->getHeight(), getWidth(), getHeight() - (topLeft->getHeight() + bottomRight->getHeight())); - } - else - { - int imW = jmin (topLeft->getWidth(), getWidth() / 2); - g.drawImage (topLeft, - 0, 0, imW, topLeft->getHeight(), - 0, 0, imW, topLeft->getHeight()); + g.setTiledImageFill (*filler, 0, 0, 1.0f); + g.fillRect (0, topLeft->getHeight(), getWidth(), getHeight() - (topLeft->getHeight() + bottomRight->getHeight())); + } + else + { + int imW = jmin (topLeft->getWidth(), getWidth() / 2); + g.drawImage (topLeft, + 0, 0, imW, topLeft->getHeight(), + 0, 0, imW, topLeft->getHeight()); - imW = jmin (bottomRight->getWidth(), getWidth() - getWidth() / 2); - g.drawImage (bottomRight, - getWidth() - imW, 0, imW, bottomRight->getHeight(), - bottomRight->getWidth() - imW, 0, imW, bottomRight->getHeight()); + imW = jmin (bottomRight->getWidth(), getWidth() - getWidth() / 2); + g.drawImage (bottomRight, + getWidth() - imW, 0, imW, bottomRight->getHeight(), + bottomRight->getWidth() - imW, 0, imW, bottomRight->getHeight()); - g.setTiledImageFill (*filler, 0, 0, 1.0f); - g.fillRect (topLeft->getWidth(), 0, getWidth() - (topLeft->getWidth() + bottomRight->getWidth()), getHeight()); - } - } + g.setTiledImageFill (*filler, 0, 0, 1.0f); + g.fillRect (topLeft->getWidth(), 0, getWidth() - (topLeft->getWidth() + bottomRight->getWidth()), getHeight()); + } + } - void resized() - { - repaint(); // (needed for correct repainting) - } + void resized() + { + repaint(); // (needed for correct repainting) + } private: - ShadowWindow (const ShadowWindow&); - const ShadowWindow& operator= (const ShadowWindow&); + ShadowWindow (const ShadowWindow&); + const ShadowWindow& operator= (const ShadowWindow&); }; DropShadower::DropShadower (const float alpha_, - const int xOffset_, - const int yOffset_, - const float blurRadius_) + const int xOffset_, + const int yOffset_, + const float blurRadius_) : owner (0), - numShadows (0), - shadowEdge (jmax (xOffset_, yOffset_) + (int) blurRadius_), - xOffset (xOffset_), - yOffset (yOffset_), - alpha (alpha_), - blurRadius (blurRadius_), - inDestructor (false), - reentrant (false) + numShadows (0), + shadowEdge (jmax (xOffset_, yOffset_) + (int) blurRadius_), + xOffset (xOffset_), + yOffset (yOffset_), + alpha (alpha_), + blurRadius (blurRadius_), + inDestructor (false), + reentrant (false) { } DropShadower::~DropShadower() { - if (owner != 0) - owner->removeComponentListener (this); + if (owner != 0) + owner->removeComponentListener (this); - inDestructor = true; + inDestructor = true; - deleteShadowWindows(); + deleteShadowWindows(); } void DropShadower::deleteShadowWindows() { - if (numShadows > 0) - { - int i; - for (i = numShadows; --i >= 0;) - delete shadowWindows[i]; + if (numShadows > 0) + { + int i; + for (i = numShadows; --i >= 0;) + delete shadowWindows[i]; - for (i = 12; --i >= 0;) - delete shadowImageSections[i]; + for (i = 12; --i >= 0;) + delete shadowImageSections[i]; - numShadows = 0; - } + numShadows = 0; + } } void DropShadower::setOwner (Component* componentToFollow) { - if (componentToFollow != owner) - { - if (owner != 0) - owner->removeComponentListener (this); + if (componentToFollow != owner) + { + if (owner != 0) + owner->removeComponentListener (this); - // (the component can't be null) - jassert (componentToFollow != 0); + // (the component can't be null) + jassert (componentToFollow != 0); - owner = componentToFollow; + owner = componentToFollow; - jassert (owner != 0); - jassert (owner->isOpaque()); // doesn't work properly for semi-transparent comps! + jassert (owner != 0); + jassert (owner->isOpaque()); // doesn't work properly for semi-transparent comps! - owner->addComponentListener (this); + owner->addComponentListener (this); - updateShadows(); - } + updateShadows(); + } } void DropShadower::componentMovedOrResized (Component&, bool /*wasMoved*/, bool /*wasResized*/) { - updateShadows(); + updateShadows(); } void DropShadower::componentBroughtToFront (Component&) { - bringShadowWindowsToFront(); + bringShadowWindowsToFront(); } void DropShadower::componentChildrenChanged (Component&) @@ -73973,162 +73778,162 @@ void DropShadower::componentChildrenChanged (Component&) void DropShadower::componentParentHierarchyChanged (Component&) { - deleteShadowWindows(); - updateShadows(); + deleteShadowWindows(); + updateShadows(); } void DropShadower::componentVisibilityChanged (Component&) { - updateShadows(); + updateShadows(); } void DropShadower::updateShadows() { - if (reentrant || inDestructor || (owner == 0)) - return; + if (reentrant || inDestructor || (owner == 0)) + return; - reentrant = true; + reentrant = true; - ComponentPeer* const nw = owner->getPeer(); + ComponentPeer* const nw = owner->getPeer(); - const bool isOwnerVisible = owner->isVisible() - && (nw == 0 || ! nw->isMinimised()); + const bool isOwnerVisible = owner->isVisible() + && (nw == 0 || ! nw->isMinimised()); - const bool createShadowWindows = numShadows == 0 - && owner->getWidth() > 0 - && owner->getHeight() > 0 - && isOwnerVisible - && (Desktop::canUseSemiTransparentWindows() - || owner->getParentComponent() != 0); + const bool createShadowWindows = numShadows == 0 + && owner->getWidth() > 0 + && owner->getHeight() > 0 + && isOwnerVisible + && (Desktop::canUseSemiTransparentWindows() + || owner->getParentComponent() != 0); - if (createShadowWindows) - { - // keep a cached version of the image to save doing the gaussian too often - String imageId; - imageId << shadowEdge << T(',') - << xOffset << T(',') - << yOffset << T(',') - << alpha; + if (createShadowWindows) + { + // keep a cached version of the image to save doing the gaussian too often + String imageId; + imageId << shadowEdge << T(',') + << xOffset << T(',') + << yOffset << T(',') + << alpha; - const int hash = imageId.hashCode(); + const int hash = imageId.hashCode(); - Image* bigIm = ImageCache::getFromHashCode (hash); + Image* bigIm = ImageCache::getFromHashCode (hash); - if (bigIm == 0) - { - bigIm = Image::createNativeImage (Image::ARGB, shadowEdge * 5, shadowEdge * 5, true); + if (bigIm == 0) + { + bigIm = Image::createNativeImage (Image::ARGB, shadowEdge * 5, shadowEdge * 5, true); - Graphics bigG (*bigIm); - bigG.setColour (Colours::black.withAlpha (alpha)); - bigG.fillRect (shadowEdge + xOffset, - shadowEdge + yOffset, - bigIm->getWidth() - (shadowEdge * 2), - bigIm->getHeight() - (shadowEdge * 2)); + Graphics bigG (*bigIm); + bigG.setColour (Colours::black.withAlpha (alpha)); + bigG.fillRect (shadowEdge + xOffset, + shadowEdge + yOffset, + bigIm->getWidth() - (shadowEdge * 2), + bigIm->getHeight() - (shadowEdge * 2)); - ImageConvolutionKernel blurKernel (roundFloatToInt (blurRadius * 2.0f)); - blurKernel.createGaussianBlur (blurRadius); + ImageConvolutionKernel blurKernel (roundToInt (blurRadius * 2.0f)); + blurKernel.createGaussianBlur (blurRadius); - blurKernel.applyToImage (*bigIm, 0, - xOffset, - yOffset, - bigIm->getWidth(), - bigIm->getHeight()); + blurKernel.applyToImage (*bigIm, 0, + xOffset, + yOffset, + bigIm->getWidth(), + bigIm->getHeight()); - ImageCache::addImageToCache (bigIm, hash); - } + ImageCache::addImageToCache (bigIm, hash); + } - const int iw = bigIm->getWidth(); - const int ih = bigIm->getHeight(); - const int shadowEdge2 = shadowEdge * 2; + const int iw = bigIm->getWidth(); + const int ih = bigIm->getHeight(); + const int shadowEdge2 = shadowEdge * 2; - setShadowImage (bigIm, 0, shadowEdge, shadowEdge2, 0, 0); - setShadowImage (bigIm, 1, shadowEdge, shadowEdge2, 0, ih - shadowEdge2); - setShadowImage (bigIm, 2, shadowEdge, shadowEdge, 0, shadowEdge2); - setShadowImage (bigIm, 3, shadowEdge, shadowEdge2, iw - shadowEdge, 0); - setShadowImage (bigIm, 4, shadowEdge, shadowEdge2, iw - shadowEdge, ih - shadowEdge2); - setShadowImage (bigIm, 5, shadowEdge, shadowEdge, iw - shadowEdge, shadowEdge2); - setShadowImage (bigIm, 6, shadowEdge, shadowEdge, shadowEdge, 0); - setShadowImage (bigIm, 7, shadowEdge, shadowEdge, iw - shadowEdge2, 0); - setShadowImage (bigIm, 8, shadowEdge, shadowEdge, shadowEdge2, 0); - setShadowImage (bigIm, 9, shadowEdge, shadowEdge, shadowEdge, ih - shadowEdge); - setShadowImage (bigIm, 10, shadowEdge, shadowEdge, iw - shadowEdge2, ih - shadowEdge); - setShadowImage (bigIm, 11, shadowEdge, shadowEdge, shadowEdge2, ih - shadowEdge); + setShadowImage (bigIm, 0, shadowEdge, shadowEdge2, 0, 0); + setShadowImage (bigIm, 1, shadowEdge, shadowEdge2, 0, ih - shadowEdge2); + setShadowImage (bigIm, 2, shadowEdge, shadowEdge, 0, shadowEdge2); + setShadowImage (bigIm, 3, shadowEdge, shadowEdge2, iw - shadowEdge, 0); + setShadowImage (bigIm, 4, shadowEdge, shadowEdge2, iw - shadowEdge, ih - shadowEdge2); + setShadowImage (bigIm, 5, shadowEdge, shadowEdge, iw - shadowEdge, shadowEdge2); + setShadowImage (bigIm, 6, shadowEdge, shadowEdge, shadowEdge, 0); + setShadowImage (bigIm, 7, shadowEdge, shadowEdge, iw - shadowEdge2, 0); + setShadowImage (bigIm, 8, shadowEdge, shadowEdge, shadowEdge2, 0); + setShadowImage (bigIm, 9, shadowEdge, shadowEdge, shadowEdge, ih - shadowEdge); + setShadowImage (bigIm, 10, shadowEdge, shadowEdge, iw - shadowEdge2, ih - shadowEdge); + setShadowImage (bigIm, 11, shadowEdge, shadowEdge, shadowEdge2, ih - shadowEdge); - ImageCache::release (bigIm); + ImageCache::release (bigIm); - for (int i = 0; i < 4; ++i) - { - shadowWindows[numShadows] = new ShadowWindow (owner, i, shadowImageSections); - ++numShadows; - } - } + for (int i = 0; i < 4; ++i) + { + shadowWindows[numShadows] = new ShadowWindow (owner, i, shadowImageSections); + ++numShadows; + } + } - if (numShadows > 0) - { - for (int i = numShadows; --i >= 0;) - { - shadowWindows[i]->setAlwaysOnTop (owner->isAlwaysOnTop()); - shadowWindows[i]->setVisible (isOwnerVisible); - } + if (numShadows > 0) + { + for (int i = numShadows; --i >= 0;) + { + shadowWindows[i]->setAlwaysOnTop (owner->isAlwaysOnTop()); + shadowWindows[i]->setVisible (isOwnerVisible); + } - const int x = owner->getX(); - const int y = owner->getY() - shadowEdge; - const int w = owner->getWidth(); - const int h = owner->getHeight() + shadowEdge + shadowEdge; + const int x = owner->getX(); + const int y = owner->getY() - shadowEdge; + const int w = owner->getWidth(); + const int h = owner->getHeight() + shadowEdge + shadowEdge; - shadowWindows[0]->setBounds (x - shadowEdge, - y, - shadowEdge, - h); + shadowWindows[0]->setBounds (x - shadowEdge, + y, + shadowEdge, + h); - shadowWindows[1]->setBounds (x + w, - y, - shadowEdge, - h); + shadowWindows[1]->setBounds (x + w, + y, + shadowEdge, + h); - shadowWindows[2]->setBounds (x, - y, - w, - shadowEdge); + shadowWindows[2]->setBounds (x, + y, + w, + shadowEdge); - shadowWindows[3]->setBounds (x, - owner->getBottom(), - w, - shadowEdge); - } + shadowWindows[3]->setBounds (x, + owner->getBottom(), + w, + shadowEdge); + } - reentrant = false; + reentrant = false; - if (createShadowWindows) - bringShadowWindowsToFront(); + if (createShadowWindows) + bringShadowWindowsToFront(); } void DropShadower::setShadowImage (Image* const src, - const int num, - const int w, - const int h, - const int sx, - const int sy) + const int num, + const int w, + const int h, + const int sx, + const int sy) { - shadowImageSections[num] = new Image (Image::ARGB, w, h, true); + shadowImageSections[num] = new Image (Image::ARGB, w, h, true); - Graphics g (*shadowImageSections[num]); - g.drawImage (src, 0, 0, w, h, sx, sy, w, h); + Graphics g (*shadowImageSections[num]); + g.drawImage (src, 0, 0, w, h, sx, sy, w, h); } void DropShadower::bringShadowWindowsToFront() { - if (! (inDestructor || reentrant)) - { - updateShadows(); + if (! (inDestructor || reentrant)) + { + updateShadows(); - reentrant = true; + reentrant = true; - for (int i = numShadows; --i >= 0;) - shadowWindows[i]->toBehind (owner); + for (int i = numShadows; --i >= 0;) + shadowWindows[i]->toBehind (owner); - reentrant = false; - } + reentrant = false; + } } END_JUCE_NAMESPACE @@ -74138,303 +73943,303 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -class MagnifyingPeer : public ComponentPeer +class MagnifyingPeer : public ComponentPeer { public: - MagnifyingPeer (Component* const component_, - MagnifierComponent* const magnifierComp_) - : ComponentPeer (component_, 0), - magnifierComp (magnifierComp_) - { - } + MagnifyingPeer (Component* const component_, + MagnifierComponent* const magnifierComp_) + : ComponentPeer (component_, 0), + magnifierComp (magnifierComp_) + { + } - ~MagnifyingPeer() - { - } + ~MagnifyingPeer() + { + } - void* getNativeHandle() const { return 0; } - void setVisible (bool) {} - void setTitle (const String&) {} - void setPosition (int, int) {} - void setSize (int, int) {} - void setBounds (int, int, int, int, const bool) {} - void setMinimised (bool) {} - bool isMinimised() const { return false; } - void setFullScreen (bool) {} - bool isFullScreen() const { return false; } - const BorderSize getFrameSize() const { return BorderSize (0); } - bool setAlwaysOnTop (bool) { return true; } - void toFront (bool) {} - void toBehind (ComponentPeer*) {} - void setIcon (const Image&) {} + void* getNativeHandle() const { return 0; } + void setVisible (bool) {} + void setTitle (const String&) {} + void setPosition (int, int) {} + void setSize (int, int) {} + void setBounds (int, int, int, int, const bool) {} + void setMinimised (bool) {} + bool isMinimised() const { return false; } + void setFullScreen (bool) {} + bool isFullScreen() const { return false; } + const BorderSize getFrameSize() const { return BorderSize (0); } + bool setAlwaysOnTop (bool) { return true; } + void toFront (bool) {} + void toBehind (ComponentPeer*) {} + void setIcon (const Image&) {} - bool isFocused() const - { - return magnifierComp->hasKeyboardFocus (true); - } + bool isFocused() const + { + return magnifierComp->hasKeyboardFocus (true); + } - void grabFocus() - { - ComponentPeer* peer = magnifierComp->getPeer(); - if (peer != 0) - peer->grabFocus(); - } + void grabFocus() + { + ComponentPeer* peer = magnifierComp->getPeer(); + if (peer != 0) + peer->grabFocus(); + } - void textInputRequired (int x, int y) - { - ComponentPeer* peer = magnifierComp->getPeer(); - if (peer != 0) - peer->textInputRequired (x, y); - } + void textInputRequired (int x, int y) + { + ComponentPeer* peer = magnifierComp->getPeer(); + if (peer != 0) + peer->textInputRequired (x, y); + } - void getBounds (int& x, int& y, int& w, int& h) const - { - x = magnifierComp->getScreenX(); - y = magnifierComp->getScreenY(); - w = component->getWidth(); - h = component->getHeight(); - } + void getBounds (int& x, int& y, int& w, int& h) const + { + x = magnifierComp->getScreenX(); + y = magnifierComp->getScreenY(); + w = component->getWidth(); + h = component->getHeight(); + } - int getScreenX() const { return magnifierComp->getScreenX(); } - int getScreenY() const { return magnifierComp->getScreenY(); } + int getScreenX() const { return magnifierComp->getScreenX(); } + int getScreenY() const { return magnifierComp->getScreenY(); } - void relativePositionToGlobal (int& x, int& y) - { - const double zoom = magnifierComp->getScaleFactor(); - x = roundDoubleToInt (x * zoom); - y = roundDoubleToInt (y * zoom); + void relativePositionToGlobal (int& x, int& y) + { + const double zoom = magnifierComp->getScaleFactor(); + x = roundToInt (x * zoom); + y = roundToInt (y * zoom); - magnifierComp->relativePositionToGlobal (x, y); - } + magnifierComp->relativePositionToGlobal (x, y); + } - void globalPositionToRelative (int& x, int& y) - { - magnifierComp->globalPositionToRelative (x, y); + void globalPositionToRelative (int& x, int& y) + { + magnifierComp->globalPositionToRelative (x, y); - const double zoom = magnifierComp->getScaleFactor(); - x = roundDoubleToInt (x / zoom); - y = roundDoubleToInt (y / zoom); - } + const double zoom = magnifierComp->getScaleFactor(); + x = roundToInt (x / zoom); + y = roundToInt (y / zoom); + } - bool contains (int x, int y, bool) const - { - return ((unsigned int) x) < (unsigned int) magnifierComp->getWidth() - && ((unsigned int) y) < (unsigned int) magnifierComp->getHeight(); - } + bool contains (int x, int y, bool) const + { + return ((unsigned int) x) < (unsigned int) magnifierComp->getWidth() + && ((unsigned int) y) < (unsigned int) magnifierComp->getHeight(); + } - void repaint (int x, int y, int w, int h) - { - const double zoom = magnifierComp->getScaleFactor(); + void repaint (int x, int y, int w, int h) + { + const double zoom = magnifierComp->getScaleFactor(); - magnifierComp->repaint ((int) (x * zoom), - (int) (y * zoom), - roundDoubleToInt (w * zoom) + 1, - roundDoubleToInt (h * zoom) + 1); - } + magnifierComp->repaint ((int) (x * zoom), + (int) (y * zoom), + roundToInt (w * zoom) + 1, + roundToInt (h * zoom) + 1); + } - void performAnyPendingRepaintsNow() - { - } + void performAnyPendingRepaintsNow() + { + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - MagnifierComponent* const magnifierComp; + MagnifierComponent* const magnifierComp; - MagnifyingPeer (const MagnifyingPeer&); - const MagnifyingPeer& operator= (const MagnifyingPeer&); + MagnifyingPeer (const MagnifyingPeer&); + const MagnifyingPeer& operator= (const MagnifyingPeer&); }; -class PeerHolderComp : public Component +class PeerHolderComp : public Component { public: - PeerHolderComp (MagnifierComponent* const magnifierComp_) - : magnifierComp (magnifierComp_) - { - setVisible (true); - } + PeerHolderComp (MagnifierComponent* const magnifierComp_) + : magnifierComp (magnifierComp_) + { + setVisible (true); + } - ~PeerHolderComp() - { - } + ~PeerHolderComp() + { + } - ComponentPeer* createNewPeer (int, void*) - { - return new MagnifyingPeer (this, magnifierComp); - } + ComponentPeer* createNewPeer (int, void*) + { + return new MagnifyingPeer (this, magnifierComp); + } - void childBoundsChanged (Component* c) - { - if (c != 0) - { - setSize (c->getWidth(), c->getHeight()); - magnifierComp->childBoundsChanged (this); - } - } + void childBoundsChanged (Component* c) + { + if (c != 0) + { + setSize (c->getWidth(), c->getHeight()); + magnifierComp->childBoundsChanged (this); + } + } - void mouseWheelMove (const MouseEvent& e, float ix, float iy) - { - // unhandled mouse wheel moves can be referred upwards to the parent comp.. - Component* const p = magnifierComp->getParentComponent(); + void mouseWheelMove (const MouseEvent& e, float ix, float iy) + { + // unhandled mouse wheel moves can be referred upwards to the parent comp.. + Component* const p = magnifierComp->getParentComponent(); - if (p != 0) - p->mouseWheelMove (e.getEventRelativeTo (p), ix, iy); - } + if (p != 0) + p->mouseWheelMove (e.getEventRelativeTo (p), ix, iy); + } private: - MagnifierComponent* const magnifierComp; + MagnifierComponent* const magnifierComp; - PeerHolderComp (const PeerHolderComp&); - const PeerHolderComp& operator= (const PeerHolderComp&); + PeerHolderComp (const PeerHolderComp&); + const PeerHolderComp& operator= (const PeerHolderComp&); }; MagnifierComponent::MagnifierComponent (Component* const content_, - const bool deleteContentCompWhenNoLongerNeeded) - : content (content_), - scaleFactor (0.0), - peer (0), - deleteContent (deleteContentCompWhenNoLongerNeeded), - quality (Graphics::lowResamplingQuality) + const bool deleteContentCompWhenNoLongerNeeded) + : content (content_), + scaleFactor (0.0), + peer (0), + deleteContent (deleteContentCompWhenNoLongerNeeded), + quality (Graphics::lowResamplingQuality) { - holderComp = new PeerHolderComp (this); - setScaleFactor (1.0); + holderComp = new PeerHolderComp (this); + setScaleFactor (1.0); } MagnifierComponent::~MagnifierComponent() { - delete holderComp; + delete holderComp; - if (deleteContent) - delete content; + if (deleteContent) + delete content; } void MagnifierComponent::setScaleFactor (double newScaleFactor) { - jassert (newScaleFactor > 0.0); // hmm - unlikely to work well with a negative scale factor + jassert (newScaleFactor > 0.0); // hmm - unlikely to work well with a negative scale factor - newScaleFactor = jlimit (1.0 / 8.0, 1000.0, newScaleFactor); + newScaleFactor = jlimit (1.0 / 8.0, 1000.0, newScaleFactor); - if (scaleFactor != newScaleFactor) - { - scaleFactor = newScaleFactor; + if (scaleFactor != newScaleFactor) + { + scaleFactor = newScaleFactor; - if (scaleFactor == 1.0) - { - holderComp->removeFromDesktop(); - peer = 0; - addChildComponent (content); - childBoundsChanged (content); - } - else - { - holderComp->addAndMakeVisible (content); - holderComp->childBoundsChanged (content); - childBoundsChanged (holderComp); - holderComp->addToDesktop (0); - peer = holderComp->getPeer(); - } + if (scaleFactor == 1.0) + { + holderComp->removeFromDesktop(); + peer = 0; + addChildComponent (content); + childBoundsChanged (content); + } + else + { + holderComp->addAndMakeVisible (content); + holderComp->childBoundsChanged (content); + childBoundsChanged (holderComp); + holderComp->addToDesktop (0); + peer = holderComp->getPeer(); + } - repaint(); - } + repaint(); + } } void MagnifierComponent::setResamplingQuality (Graphics::ResamplingQuality newQuality) { - quality = newQuality; + quality = newQuality; } void MagnifierComponent::paint (Graphics& g) { - const int w = holderComp->getWidth(); - const int h = holderComp->getHeight(); + const int w = holderComp->getWidth(); + const int h = holderComp->getHeight(); - if (w == 0 || h == 0) - return; + if (w == 0 || h == 0) + return; - const Rectangle r (g.getClipBounds()); + const Rectangle r (g.getClipBounds()); - const int srcX = (int) (r.getX() / scaleFactor); - const int srcY = (int) (r.getY() / scaleFactor); - int srcW = roundDoubleToInt (r.getRight() / scaleFactor) - srcX; - int srcH = roundDoubleToInt (r.getBottom() / scaleFactor) - srcY; + const int srcX = (int) (r.getX() / scaleFactor); + const int srcY = (int) (r.getY() / scaleFactor); + int srcW = roundToInt (r.getRight() / scaleFactor) - srcX; + int srcH = roundToInt (r.getBottom() / scaleFactor) - srcY; - if (scaleFactor >= 1.0) - { - ++srcW; - ++srcH; - } + if (scaleFactor >= 1.0) + { + ++srcW; + ++srcH; + } - Image temp (Image::ARGB, jmax (w, srcX + srcW), jmax (h, srcY + srcH), false); - temp.clear (srcX, srcY, srcW, srcH); + Image temp (Image::ARGB, jmax (w, srcX + srcW), jmax (h, srcY + srcH), false); + temp.clear (srcX, srcY, srcW, srcH); - Graphics g2 (temp); - g2.reduceClipRegion (srcX, srcY, srcW, srcH); - holderComp->paintEntireComponent (g2); + Graphics g2 (temp); + g2.reduceClipRegion (srcX, srcY, srcW, srcH); + holderComp->paintEntireComponent (g2); - g.setImageResamplingQuality (quality); - g.drawImage (&temp, - 0, 0, (int) (w * scaleFactor), (int) (h * scaleFactor), - 0, 0, w, h, - false); + g.setImageResamplingQuality (quality); + g.drawImage (&temp, + 0, 0, (int) (w * scaleFactor), (int) (h * scaleFactor), + 0, 0, w, h, + false); } void MagnifierComponent::childBoundsChanged (Component* c) { - if (c != 0) - setSize (roundDoubleToInt (c->getWidth() * scaleFactor), - roundDoubleToInt (c->getHeight() * scaleFactor)); + if (c != 0) + setSize (roundToInt (c->getWidth() * scaleFactor), + roundToInt (c->getHeight() * scaleFactor)); } void MagnifierComponent::mouseDown (const MouseEvent& e) { - if (peer != 0) - peer->handleMouseDown (scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); + if (peer != 0) + peer->handleMouseDown (scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); } void MagnifierComponent::mouseUp (const MouseEvent& e) { - if (peer != 0) - peer->handleMouseUp (e.mods.getRawFlags(), scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); + if (peer != 0) + peer->handleMouseUp (e.mods.getRawFlags(), scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); } void MagnifierComponent::mouseDrag (const MouseEvent& e) { - if (peer != 0) - peer->handleMouseDrag (scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); + if (peer != 0) + peer->handleMouseDrag (scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); } void MagnifierComponent::mouseMove (const MouseEvent& e) { - if (peer != 0) - peer->handleMouseMove (scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); + if (peer != 0) + peer->handleMouseMove (scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); } void MagnifierComponent::mouseEnter (const MouseEvent& e) { - if (peer != 0) - peer->handleMouseEnter (scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); + if (peer != 0) + peer->handleMouseEnter (scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); } void MagnifierComponent::mouseExit (const MouseEvent& e) { - if (peer != 0) - peer->handleMouseExit (scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); + if (peer != 0) + peer->handleMouseExit (scaleInt (e.x), scaleInt (e.y), e.eventTime.toMilliseconds()); } void MagnifierComponent::mouseWheelMove (const MouseEvent& e, float ix, float iy) { - if (peer != 0) - peer->handleMouseWheel (roundFloatToInt (ix * 256.0f), - roundFloatToInt (iy * 256.0f), - e.eventTime.toMilliseconds()); - else - Component::mouseWheelMove (e, ix, iy); + if (peer != 0) + peer->handleMouseWheel (roundToInt (ix * 256.0f), + roundToInt (iy * 256.0f), + e.eventTime.toMilliseconds()); + else + Component::mouseWheelMove (e, ix, iy); } int MagnifierComponent::scaleInt (const int n) const { - return roundDoubleToInt (n / scaleFactor); + return roundToInt (n / scaleFactor); } END_JUCE_NAMESPACE @@ -74447,216 +74252,214 @@ BEGIN_JUCE_NAMESPACE class MidiKeyboardUpDownButton : public Button { public: - MidiKeyboardUpDownButton (MidiKeyboardComponent* const owner_, - const int delta_) - : Button (String::empty), - owner (owner_), - delta (delta_) - { - setOpaque (true); - } + MidiKeyboardUpDownButton (MidiKeyboardComponent* const owner_, + const int delta_) + : Button (String::empty), + owner (owner_), + delta (delta_) + { + setOpaque (true); + } - ~MidiKeyboardUpDownButton() - { - } + ~MidiKeyboardUpDownButton() + { + } - void clicked() - { - int note = owner->getLowestVisibleKey(); + void clicked() + { + int note = owner->getLowestVisibleKey(); - if (delta < 0) - note = (note - 1) / 12; - else - note = note / 12 + 1; + if (delta < 0) + note = (note - 1) / 12; + else + note = note / 12 + 1; - owner->setLowestVisibleKey (note * 12); - } + owner->setLowestVisibleKey (note * 12); + } - void paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown) - { - owner->drawUpDownButton (g, getWidth(), getHeight(), - isMouseOverButton, isButtonDown, - delta > 0); - } + void paintButton (Graphics& g, + bool isMouseOverButton, + bool isButtonDown) + { + owner->drawUpDownButton (g, getWidth(), getHeight(), + isMouseOverButton, isButtonDown, + delta > 0); + } private: - MidiKeyboardComponent* const owner; - const int delta; + MidiKeyboardComponent* const owner; + const int delta; - MidiKeyboardUpDownButton (const MidiKeyboardUpDownButton&); - const MidiKeyboardUpDownButton& operator= (const MidiKeyboardUpDownButton&); + MidiKeyboardUpDownButton (const MidiKeyboardUpDownButton&); + const MidiKeyboardUpDownButton& operator= (const MidiKeyboardUpDownButton&); }; MidiKeyboardComponent::MidiKeyboardComponent (MidiKeyboardState& state_, - const Orientation orientation_) - : state (state_), - xOffset (0), - blackNoteLength (1), - keyWidth (16.0f), - orientation (orientation_), - midiChannel (1), - midiInChannelMask (0xffff), - velocity (1.0f), - noteUnderMouse (-1), - mouseDownNote (-1), - rangeStart (0), - rangeEnd (127), - firstKey (12 * 4), - canScroll (true), - mouseDragging (false), - useMousePositionForVelocity (true), - keyPresses (4), - keyPressNotes (16), - keyMappingOctave (6), - octaveNumForMiddleC (3) + const Orientation orientation_) + : state (state_), + xOffset (0), + blackNoteLength (1), + keyWidth (16.0f), + orientation (orientation_), + midiChannel (1), + midiInChannelMask (0xffff), + velocity (1.0f), + noteUnderMouse (-1), + mouseDownNote (-1), + rangeStart (0), + rangeEnd (127), + firstKey (12 * 4), + canScroll (true), + mouseDragging (false), + useMousePositionForVelocity (true), + keyMappingOctave (6), + octaveNumForMiddleC (3) { - addChildComponent (scrollDown = new MidiKeyboardUpDownButton (this, -1)); - addChildComponent (scrollUp = new MidiKeyboardUpDownButton (this, 1)); + addChildComponent (scrollDown = new MidiKeyboardUpDownButton (this, -1)); + addChildComponent (scrollUp = new MidiKeyboardUpDownButton (this, 1)); - // initialise with a default set of querty key-mappings.. - const char* const keymap = "awsedftgyhujkolp;"; + // initialise with a default set of querty key-mappings.. + const char* const keymap = "awsedftgyhujkolp;"; - for (int i = String (keymap).length(); --i >= 0;) - setKeyPressForNote (KeyPress (keymap[i], 0, 0), i); + for (int i = String (keymap).length(); --i >= 0;) + setKeyPressForNote (KeyPress (keymap[i], 0, 0), i); - setOpaque (true); - setWantsKeyboardFocus (true); + setOpaque (true); + setWantsKeyboardFocus (true); - state.addListener (this); + state.addListener (this); } MidiKeyboardComponent::~MidiKeyboardComponent() { - state.removeListener (this); - jassert (mouseDownNote < 0 && keysPressed.countNumberOfSetBits() == 0); // leaving stuck notes! + state.removeListener (this); + jassert (mouseDownNote < 0 && keysPressed.countNumberOfSetBits() == 0); // leaving stuck notes! - deleteAllChildren(); + deleteAllChildren(); } void MidiKeyboardComponent::setKeyWidth (const float widthInPixels) { - keyWidth = widthInPixels; - resized(); + keyWidth = widthInPixels; + resized(); } void MidiKeyboardComponent::setOrientation (const Orientation newOrientation) { - if (orientation != newOrientation) - { - orientation = newOrientation; - resized(); - } + if (orientation != newOrientation) + { + orientation = newOrientation; + resized(); + } } void MidiKeyboardComponent::setAvailableRange (const int lowestNote, - const int highestNote) + const int highestNote) { - jassert (lowestNote >= 0 && lowestNote <= 127); - jassert (highestNote >= 0 && highestNote <= 127); - jassert (lowestNote <= highestNote); + jassert (lowestNote >= 0 && lowestNote <= 127); + jassert (highestNote >= 0 && highestNote <= 127); + jassert (lowestNote <= highestNote); - if (rangeStart != lowestNote || rangeEnd != highestNote) - { - rangeStart = jlimit (0, 127, lowestNote); - rangeEnd = jlimit (0, 127, highestNote); - firstKey = jlimit (rangeStart, rangeEnd, firstKey); - resized(); - } + if (rangeStart != lowestNote || rangeEnd != highestNote) + { + rangeStart = jlimit (0, 127, lowestNote); + rangeEnd = jlimit (0, 127, highestNote); + firstKey = jlimit (rangeStart, rangeEnd, firstKey); + resized(); + } } void MidiKeyboardComponent::setLowestVisibleKey (int noteNumber) { - noteNumber = jlimit (rangeStart, rangeEnd, noteNumber); + noteNumber = jlimit (rangeStart, rangeEnd, noteNumber); - if (noteNumber != firstKey) - { - firstKey = noteNumber; - sendChangeMessage (this); - resized(); - } + if (noteNumber != firstKey) + { + firstKey = noteNumber; + sendChangeMessage (this); + resized(); + } } void MidiKeyboardComponent::setScrollButtonsVisible (const bool canScroll_) { - if (canScroll != canScroll_) - { - canScroll = canScroll_; - resized(); - } + if (canScroll != canScroll_) + { + canScroll = canScroll_; + resized(); + } } void MidiKeyboardComponent::colourChanged() { - repaint(); + repaint(); } void MidiKeyboardComponent::setMidiChannel (const int midiChannelNumber) { - jassert (midiChannelNumber > 0 && midiChannelNumber <= 16); + jassert (midiChannelNumber > 0 && midiChannelNumber <= 16); - if (midiChannel != midiChannelNumber) - { - resetAnyKeysInUse(); - midiChannel = jlimit (1, 16, midiChannelNumber); - } + if (midiChannel != midiChannelNumber) + { + resetAnyKeysInUse(); + midiChannel = jlimit (1, 16, midiChannelNumber); + } } void MidiKeyboardComponent::setMidiChannelsToDisplay (const int midiChannelMask) { - midiInChannelMask = midiChannelMask; - triggerAsyncUpdate(); + midiInChannelMask = midiChannelMask; + triggerAsyncUpdate(); } void MidiKeyboardComponent::setVelocity (const float velocity_, const bool useMousePositionForVelocity_) { - velocity = jlimit (0.0f, 1.0f, velocity_); - useMousePositionForVelocity = useMousePositionForVelocity_; + velocity = jlimit (0.0f, 1.0f, velocity_); + useMousePositionForVelocity = useMousePositionForVelocity_; } void MidiKeyboardComponent::getKeyPosition (int midiNoteNumber, const float keyWidth, int& x, int& w) const { - jassert (midiNoteNumber >= 0 && midiNoteNumber < 128); + jassert (midiNoteNumber >= 0 && midiNoteNumber < 128); - static const float blackNoteWidth = 0.7f; + static const float blackNoteWidth = 0.7f; - static const float notePos[] = { 0.0f, 1 - blackNoteWidth * 0.6f, - 1.0f, 2 - blackNoteWidth * 0.4f, - 2.0f, 3.0f, 4 - blackNoteWidth * 0.7f, - 4.0f, 5 - blackNoteWidth * 0.5f, - 5.0f, 6 - blackNoteWidth * 0.3f, - 6.0f }; + static const float notePos[] = { 0.0f, 1 - blackNoteWidth * 0.6f, + 1.0f, 2 - blackNoteWidth * 0.4f, + 2.0f, 3.0f, 4 - blackNoteWidth * 0.7f, + 4.0f, 5 - blackNoteWidth * 0.5f, + 5.0f, 6 - blackNoteWidth * 0.3f, + 6.0f }; - static const float widths[] = { 1.0f, blackNoteWidth, - 1.0f, blackNoteWidth, - 1.0f, 1.0f, blackNoteWidth, - 1.0f, blackNoteWidth, - 1.0f, blackNoteWidth, - 1.0f }; + static const float widths[] = { 1.0f, blackNoteWidth, + 1.0f, blackNoteWidth, + 1.0f, 1.0f, blackNoteWidth, + 1.0f, blackNoteWidth, + 1.0f, blackNoteWidth, + 1.0f }; - const int octave = midiNoteNumber / 12; - const int note = midiNoteNumber % 12; + const int octave = midiNoteNumber / 12; + const int note = midiNoteNumber % 12; - x = roundFloatToInt (octave * 7.0f * keyWidth + notePos [note] * keyWidth); - w = roundFloatToInt (widths [note] * keyWidth); + x = roundToInt (octave * 7.0f * keyWidth + notePos [note] * keyWidth); + w = roundToInt (widths [note] * keyWidth); } void MidiKeyboardComponent::getKeyPos (int midiNoteNumber, int& x, int& w) const { - getKeyPosition (midiNoteNumber, keyWidth, x, w); + getKeyPosition (midiNoteNumber, keyWidth, x, w); - int rx, rw; - getKeyPosition (rangeStart, keyWidth, rx, rw); + int rx, rw; + getKeyPosition (rangeStart, keyWidth, rx, rw); - x -= xOffset + rx; + x -= xOffset + rx; } int MidiKeyboardComponent::getKeyStartPosition (const int midiNoteNumber) const { - int x, y; - getKeyPos (midiNoteNumber, x, y); - return x; + int x, y; + getKeyPos (midiNoteNumber, x, y); + return x; } static const uint8 whiteNotes[] = { 0, 2, 4, 5, 7, 9, 11 }; @@ -74664,502 +74467,502 @@ static const uint8 blackNotes[] = { 1, 3, 6, 8, 10 }; int MidiKeyboardComponent::xyToNote (int x, int y, float& mousePositionVelocity) { - if (! reallyContains (x, y, false)) - return -1; + if (! reallyContains (x, y, false)) + return -1; - if (orientation != horizontalKeyboard) - { - swapVariables (x, y); + if (orientation != horizontalKeyboard) + { + swapVariables (x, y); - if (orientation == verticalKeyboardFacingLeft) - y = getWidth() - y; - else - x = getHeight() - x; - } + if (orientation == verticalKeyboardFacingLeft) + y = getWidth() - y; + else + x = getHeight() - x; + } - return remappedXYToNote (x + xOffset, y, mousePositionVelocity); + return remappedXYToNote (x + xOffset, y, mousePositionVelocity); } int MidiKeyboardComponent::remappedXYToNote (int x, int y, float& mousePositionVelocity) const { - if (y < blackNoteLength) - { - for (int octaveStart = 12 * (rangeStart / 12); octaveStart <= rangeEnd; octaveStart += 12) - { - for (int i = 0; i < 5; ++i) - { - const int note = octaveStart + blackNotes [i]; + if (y < blackNoteLength) + { + for (int octaveStart = 12 * (rangeStart / 12); octaveStart <= rangeEnd; octaveStart += 12) + { + for (int i = 0; i < 5; ++i) + { + const int note = octaveStart + blackNotes [i]; - if (note >= rangeStart && note <= rangeEnd) - { - int kx, kw; - getKeyPos (note, kx, kw); - kx += xOffset; + if (note >= rangeStart && note <= rangeEnd) + { + int kx, kw; + getKeyPos (note, kx, kw); + kx += xOffset; - if (x >= kx && x < kx + kw) - { - mousePositionVelocity = y / (float) blackNoteLength; - return note; - } - } - } - } - } + if (x >= kx && x < kx + kw) + { + mousePositionVelocity = y / (float) blackNoteLength; + return note; + } + } + } + } + } - for (int octaveStart = 12 * (rangeStart / 12); octaveStart <= rangeEnd; octaveStart += 12) - { - for (int i = 0; i < 7; ++i) - { - const int note = octaveStart + whiteNotes [i]; + for (int octaveStart = 12 * (rangeStart / 12); octaveStart <= rangeEnd; octaveStart += 12) + { + for (int i = 0; i < 7; ++i) + { + const int note = octaveStart + whiteNotes [i]; - if (note >= rangeStart && note <= rangeEnd) - { - int kx, kw; - getKeyPos (note, kx, kw); - kx += xOffset; + if (note >= rangeStart && note <= rangeEnd) + { + int kx, kw; + getKeyPos (note, kx, kw); + kx += xOffset; - if (x >= kx && x < kx + kw) - { - mousePositionVelocity = y / (float) getHeight(); - return note; - } - } - } - } + if (x >= kx && x < kx + kw) + { + mousePositionVelocity = y / (float) getHeight(); + return note; + } + } + } + } - mousePositionVelocity = 0; - return -1; + mousePositionVelocity = 0; + return -1; } void MidiKeyboardComponent::repaintNote (const int noteNum) { - if (noteNum >= rangeStart && noteNum <= rangeEnd) - { - int x, w; - getKeyPos (noteNum, x, w); + if (noteNum >= rangeStart && noteNum <= rangeEnd) + { + int x, w; + getKeyPos (noteNum, x, w); - if (orientation == horizontalKeyboard) - repaint (x, 0, w, getHeight()); - else if (orientation == verticalKeyboardFacingLeft) - repaint (0, x, getWidth(), w); - else if (orientation == verticalKeyboardFacingRight) - repaint (0, getHeight() - x - w, getWidth(), w); - } + if (orientation == horizontalKeyboard) + repaint (x, 0, w, getHeight()); + else if (orientation == verticalKeyboardFacingLeft) + repaint (0, x, getWidth(), w); + else if (orientation == verticalKeyboardFacingRight) + repaint (0, getHeight() - x - w, getWidth(), w); + } } void MidiKeyboardComponent::paint (Graphics& g) { - g.fillAll (Colours::white.overlaidWith (findColour (whiteNoteColourId))); + g.fillAll (Colours::white.overlaidWith (findColour (whiteNoteColourId))); - const Colour lineColour (findColour (keySeparatorLineColourId)); - const Colour textColour (findColour (textLabelColourId)); + const Colour lineColour (findColour (keySeparatorLineColourId)); + const Colour textColour (findColour (textLabelColourId)); - int x, w, octave; + int x, w, octave; - for (octave = 0; octave < 128; octave += 12) - { - for (int white = 0; white < 7; ++white) - { - const int noteNum = octave + whiteNotes [white]; + for (octave = 0; octave < 128; octave += 12) + { + for (int white = 0; white < 7; ++white) + { + const int noteNum = octave + whiteNotes [white]; - if (noteNum >= rangeStart && noteNum <= rangeEnd) - { - getKeyPos (noteNum, x, w); + if (noteNum >= rangeStart && noteNum <= rangeEnd) + { + getKeyPos (noteNum, x, w); - if (orientation == horizontalKeyboard) - drawWhiteNote (noteNum, g, x, 0, w, getHeight(), - state.isNoteOnForChannels (midiInChannelMask, noteNum), - noteUnderMouse == noteNum, - lineColour, textColour); - else if (orientation == verticalKeyboardFacingLeft) - drawWhiteNote (noteNum, g, 0, x, getWidth(), w, - state.isNoteOnForChannels (midiInChannelMask, noteNum), - noteUnderMouse == noteNum, - lineColour, textColour); - else if (orientation == verticalKeyboardFacingRight) - drawWhiteNote (noteNum, g, 0, getHeight() - x - w, getWidth(), w, - state.isNoteOnForChannels (midiInChannelMask, noteNum), - noteUnderMouse == noteNum, - lineColour, textColour); - } - } - } + if (orientation == horizontalKeyboard) + drawWhiteNote (noteNum, g, x, 0, w, getHeight(), + state.isNoteOnForChannels (midiInChannelMask, noteNum), + noteUnderMouse == noteNum, + lineColour, textColour); + else if (orientation == verticalKeyboardFacingLeft) + drawWhiteNote (noteNum, g, 0, x, getWidth(), w, + state.isNoteOnForChannels (midiInChannelMask, noteNum), + noteUnderMouse == noteNum, + lineColour, textColour); + else if (orientation == verticalKeyboardFacingRight) + drawWhiteNote (noteNum, g, 0, getHeight() - x - w, getWidth(), w, + state.isNoteOnForChannels (midiInChannelMask, noteNum), + noteUnderMouse == noteNum, + lineColour, textColour); + } + } + } - float x1 = 0.0f, y1 = 0.0f, x2 = 0.0f, y2 = 0.0f; + float x1 = 0.0f, y1 = 0.0f, x2 = 0.0f, y2 = 0.0f; - if (orientation == verticalKeyboardFacingLeft) - { - x1 = getWidth() - 1.0f; - x2 = getWidth() - 5.0f; - } - else if (orientation == verticalKeyboardFacingRight) - x2 = 5.0f; - else - y2 = 5.0f; + if (orientation == verticalKeyboardFacingLeft) + { + x1 = getWidth() - 1.0f; + x2 = getWidth() - 5.0f; + } + else if (orientation == verticalKeyboardFacingRight) + x2 = 5.0f; + else + y2 = 5.0f; - g.setGradientFill (ColourGradient (Colours::black.withAlpha (0.3f), x1, y1, - Colours::transparentBlack, x2, y2, false)); + g.setGradientFill (ColourGradient (Colours::black.withAlpha (0.3f), x1, y1, + Colours::transparentBlack, x2, y2, false)); - getKeyPos (rangeEnd, x, w); - x += w; + getKeyPos (rangeEnd, x, w); + x += w; - if (orientation == verticalKeyboardFacingLeft) - g.fillRect (getWidth() - 5, 0, 5, x); - else if (orientation == verticalKeyboardFacingRight) - g.fillRect (0, 0, 5, x); - else - g.fillRect (0, 0, x, 5); + if (orientation == verticalKeyboardFacingLeft) + g.fillRect (getWidth() - 5, 0, 5, x); + else if (orientation == verticalKeyboardFacingRight) + g.fillRect (0, 0, 5, x); + else + g.fillRect (0, 0, x, 5); - g.setColour (lineColour); + g.setColour (lineColour); - if (orientation == verticalKeyboardFacingLeft) - g.fillRect (0, 0, 1, x); - else if (orientation == verticalKeyboardFacingRight) - g.fillRect (getWidth() - 1, 0, 1, x); - else - g.fillRect (0, getHeight() - 1, x, 1); + if (orientation == verticalKeyboardFacingLeft) + g.fillRect (0, 0, 1, x); + else if (orientation == verticalKeyboardFacingRight) + g.fillRect (getWidth() - 1, 0, 1, x); + else + g.fillRect (0, getHeight() - 1, x, 1); - const Colour blackNoteColour (findColour (blackNoteColourId)); + const Colour blackNoteColour (findColour (blackNoteColourId)); - for (octave = 0; octave < 128; octave += 12) - { - for (int black = 0; black < 5; ++black) - { - const int noteNum = octave + blackNotes [black]; + for (octave = 0; octave < 128; octave += 12) + { + for (int black = 0; black < 5; ++black) + { + const int noteNum = octave + blackNotes [black]; - if (noteNum >= rangeStart && noteNum <= rangeEnd) - { - getKeyPos (noteNum, x, w); + if (noteNum >= rangeStart && noteNum <= rangeEnd) + { + getKeyPos (noteNum, x, w); - if (orientation == horizontalKeyboard) - drawBlackNote (noteNum, g, x, 0, w, blackNoteLength, - state.isNoteOnForChannels (midiInChannelMask, noteNum), - noteUnderMouse == noteNum, - blackNoteColour); - else if (orientation == verticalKeyboardFacingLeft) - drawBlackNote (noteNum, g, getWidth() - blackNoteLength, x, blackNoteLength, w, - state.isNoteOnForChannels (midiInChannelMask, noteNum), - noteUnderMouse == noteNum, - blackNoteColour); - else if (orientation == verticalKeyboardFacingRight) - drawBlackNote (noteNum, g, 0, getHeight() - x - w, blackNoteLength, w, - state.isNoteOnForChannels (midiInChannelMask, noteNum), - noteUnderMouse == noteNum, - blackNoteColour); - } - } - } + if (orientation == horizontalKeyboard) + drawBlackNote (noteNum, g, x, 0, w, blackNoteLength, + state.isNoteOnForChannels (midiInChannelMask, noteNum), + noteUnderMouse == noteNum, + blackNoteColour); + else if (orientation == verticalKeyboardFacingLeft) + drawBlackNote (noteNum, g, getWidth() - blackNoteLength, x, blackNoteLength, w, + state.isNoteOnForChannels (midiInChannelMask, noteNum), + noteUnderMouse == noteNum, + blackNoteColour); + else if (orientation == verticalKeyboardFacingRight) + drawBlackNote (noteNum, g, 0, getHeight() - x - w, blackNoteLength, w, + state.isNoteOnForChannels (midiInChannelMask, noteNum), + noteUnderMouse == noteNum, + blackNoteColour); + } + } + } } void MidiKeyboardComponent::drawWhiteNote (int midiNoteNumber, - Graphics& g, int x, int y, int w, int h, - bool isDown, bool isOver, - const Colour& lineColour, - const Colour& textColour) + Graphics& g, int x, int y, int w, int h, + bool isDown, bool isOver, + const Colour& lineColour, + const Colour& textColour) { - Colour c (Colours::transparentWhite); + Colour c (Colours::transparentWhite); - if (isDown) - c = findColour (keyDownOverlayColourId); + if (isDown) + c = findColour (keyDownOverlayColourId); - if (isOver) - c = c.overlaidWith (findColour (mouseOverKeyOverlayColourId)); + if (isOver) + c = c.overlaidWith (findColour (mouseOverKeyOverlayColourId)); - g.setColour (c); - g.fillRect (x, y, w, h); + g.setColour (c); + g.fillRect (x, y, w, h); - const String text (getWhiteNoteText (midiNoteNumber)); + const String text (getWhiteNoteText (midiNoteNumber)); - if (! text.isEmpty()) - { - g.setColour (textColour); + if (! text.isEmpty()) + { + g.setColour (textColour); - Font f (jmin (12.0f, keyWidth * 0.9f)); - f.setHorizontalScale (0.8f); - g.setFont (f); - Justification justification (Justification::centredBottom); + Font f (jmin (12.0f, keyWidth * 0.9f)); + f.setHorizontalScale (0.8f); + g.setFont (f); + Justification justification (Justification::centredBottom); - if (orientation == verticalKeyboardFacingLeft) - justification = Justification::centredLeft; - else if (orientation == verticalKeyboardFacingRight) - justification = Justification::centredRight; + if (orientation == verticalKeyboardFacingLeft) + justification = Justification::centredLeft; + else if (orientation == verticalKeyboardFacingRight) + justification = Justification::centredRight; - g.drawFittedText (text, x + 2, y + 2, w - 4, h - 4, justification, 1); - } + g.drawFittedText (text, x + 2, y + 2, w - 4, h - 4, justification, 1); + } - g.setColour (lineColour); + g.setColour (lineColour); - if (orientation == horizontalKeyboard) - g.fillRect (x, y, 1, h); - else if (orientation == verticalKeyboardFacingLeft) - g.fillRect (x, y, w, 1); - else if (orientation == verticalKeyboardFacingRight) - g.fillRect (x, y + h - 1, w, 1); + if (orientation == horizontalKeyboard) + g.fillRect (x, y, 1, h); + else if (orientation == verticalKeyboardFacingLeft) + g.fillRect (x, y, w, 1); + else if (orientation == verticalKeyboardFacingRight) + g.fillRect (x, y + h - 1, w, 1); - if (midiNoteNumber == rangeEnd) - { - if (orientation == horizontalKeyboard) - g.fillRect (x + w, y, 1, h); - else if (orientation == verticalKeyboardFacingLeft) - g.fillRect (x, y + h, w, 1); - else if (orientation == verticalKeyboardFacingRight) - g.fillRect (x, y - 1, w, 1); - } + if (midiNoteNumber == rangeEnd) + { + if (orientation == horizontalKeyboard) + g.fillRect (x + w, y, 1, h); + else if (orientation == verticalKeyboardFacingLeft) + g.fillRect (x, y + h, w, 1); + else if (orientation == verticalKeyboardFacingRight) + g.fillRect (x, y - 1, w, 1); + } } void MidiKeyboardComponent::drawBlackNote (int /*midiNoteNumber*/, - Graphics& g, int x, int y, int w, int h, - bool isDown, bool isOver, - const Colour& noteFillColour) + Graphics& g, int x, int y, int w, int h, + bool isDown, bool isOver, + const Colour& noteFillColour) { - Colour c (noteFillColour); + Colour c (noteFillColour); - if (isDown) - c = c.overlaidWith (findColour (keyDownOverlayColourId)); + if (isDown) + c = c.overlaidWith (findColour (keyDownOverlayColourId)); - if (isOver) - c = c.overlaidWith (findColour (mouseOverKeyOverlayColourId)); + if (isOver) + c = c.overlaidWith (findColour (mouseOverKeyOverlayColourId)); - g.setColour (c); - g.fillRect (x, y, w, h); + g.setColour (c); + g.fillRect (x, y, w, h); - if (isDown) - { - g.setColour (noteFillColour); - g.drawRect (x, y, w, h); - } - else - { - const int xIndent = jmax (1, jmin (w, h) / 8); + if (isDown) + { + g.setColour (noteFillColour); + g.drawRect (x, y, w, h); + } + else + { + const int xIndent = jmax (1, jmin (w, h) / 8); - g.setColour (c.brighter()); + g.setColour (c.brighter()); - if (orientation == horizontalKeyboard) - g.fillRect (x + xIndent, y, w - xIndent * 2, 7 * h / 8); - else if (orientation == verticalKeyboardFacingLeft) - g.fillRect (x + w / 8, y + xIndent, w - w / 8, h - xIndent * 2); - else if (orientation == verticalKeyboardFacingRight) - g.fillRect (x, y + xIndent, 7 * w / 8, h - xIndent * 2); - } + if (orientation == horizontalKeyboard) + g.fillRect (x + xIndent, y, w - xIndent * 2, 7 * h / 8); + else if (orientation == verticalKeyboardFacingLeft) + g.fillRect (x + w / 8, y + xIndent, w - w / 8, h - xIndent * 2); + else if (orientation == verticalKeyboardFacingRight) + g.fillRect (x, y + xIndent, 7 * w / 8, h - xIndent * 2); + } } void MidiKeyboardComponent::setOctaveForMiddleC (const int octaveNumForMiddleC_) throw() { - octaveNumForMiddleC = octaveNumForMiddleC_; - repaint(); + octaveNumForMiddleC = octaveNumForMiddleC_; + repaint(); } const String MidiKeyboardComponent::getWhiteNoteText (const int midiNoteNumber) { - if (keyWidth > 14.0f && midiNoteNumber % 12 == 0) - return MidiMessage::getMidiNoteName (midiNoteNumber, true, true, octaveNumForMiddleC); + if (keyWidth > 14.0f && midiNoteNumber % 12 == 0) + return MidiMessage::getMidiNoteName (midiNoteNumber, true, true, octaveNumForMiddleC); - return String::empty; + return String::empty; } void MidiKeyboardComponent::drawUpDownButton (Graphics& g, int w, int h, - const bool isMouseOver, - const bool isButtonDown, - const bool movesOctavesUp) + const bool isMouseOver, + const bool isButtonDown, + const bool movesOctavesUp) { - g.fillAll (findColour (upDownButtonBackgroundColourId)); + g.fillAll (findColour (upDownButtonBackgroundColourId)); - float angle; + float angle; - if (orientation == MidiKeyboardComponent::horizontalKeyboard) - angle = movesOctavesUp ? 0.0f : 0.5f; - else if (orientation == MidiKeyboardComponent::verticalKeyboardFacingLeft) - angle = movesOctavesUp ? 0.25f : 0.75f; - else - angle = movesOctavesUp ? 0.75f : 0.25f; + if (orientation == MidiKeyboardComponent::horizontalKeyboard) + angle = movesOctavesUp ? 0.0f : 0.5f; + else if (orientation == MidiKeyboardComponent::verticalKeyboardFacingLeft) + angle = movesOctavesUp ? 0.25f : 0.75f; + else + angle = movesOctavesUp ? 0.75f : 0.25f; - Path path; - path.lineTo (0.0f, 1.0f); - path.lineTo (1.0f, 0.5f); - path.closeSubPath(); + Path path; + path.lineTo (0.0f, 1.0f); + path.lineTo (1.0f, 0.5f); + path.closeSubPath(); - path.applyTransform (AffineTransform::rotation (float_Pi * 2.0f * angle, 0.5f, 0.5f)); + path.applyTransform (AffineTransform::rotation (float_Pi * 2.0f * angle, 0.5f, 0.5f)); - g.setColour (findColour (upDownButtonArrowColourId) - .withAlpha (isButtonDown ? 1.0f : (isMouseOver ? 0.6f : 0.4f))); + g.setColour (findColour (upDownButtonArrowColourId) + .withAlpha (isButtonDown ? 1.0f : (isMouseOver ? 0.6f : 0.4f))); - g.fillPath (path, path.getTransformToScaleToFit (1.0f, 1.0f, - w - 2.0f, - h - 2.0f, - true)); + g.fillPath (path, path.getTransformToScaleToFit (1.0f, 1.0f, + w - 2.0f, + h - 2.0f, + true)); } void MidiKeyboardComponent::resized() { - int w = getWidth(); - int h = getHeight(); + int w = getWidth(); + int h = getHeight(); - if (w > 0 && h > 0) - { - if (orientation != horizontalKeyboard) - swapVariables (w, h); + if (w > 0 && h > 0) + { + if (orientation != horizontalKeyboard) + swapVariables (w, h); - blackNoteLength = roundFloatToInt (h * 0.7f); + blackNoteLength = roundToInt (h * 0.7f); - int kx2, kw2; - getKeyPos (rangeEnd, kx2, kw2); + int kx2, kw2; + getKeyPos (rangeEnd, kx2, kw2); - kx2 += kw2; + kx2 += kw2; - if (firstKey != rangeStart) - { - int kx1, kw1; - getKeyPos (rangeStart, kx1, kw1); + if (firstKey != rangeStart) + { + int kx1, kw1; + getKeyPos (rangeStart, kx1, kw1); - if (kx2 - kx1 <= w) - { - firstKey = rangeStart; - sendChangeMessage (this); - repaint(); - } - } + if (kx2 - kx1 <= w) + { + firstKey = rangeStart; + sendChangeMessage (this); + repaint(); + } + } - const bool showScrollButtons = canScroll && (firstKey > rangeStart || kx2 > w + xOffset * 2); + const bool showScrollButtons = canScroll && (firstKey > rangeStart || kx2 > w + xOffset * 2); - scrollDown->setVisible (showScrollButtons); - scrollUp->setVisible (showScrollButtons); + scrollDown->setVisible (showScrollButtons); + scrollUp->setVisible (showScrollButtons); - xOffset = 0; + xOffset = 0; - if (showScrollButtons) - { - const int scrollButtonW = jmin (12, w / 2); + if (showScrollButtons) + { + const int scrollButtonW = jmin (12, w / 2); - if (orientation == horizontalKeyboard) - { - scrollDown->setBounds (0, 0, scrollButtonW, getHeight()); - scrollUp->setBounds (getWidth() - scrollButtonW, 0, scrollButtonW, getHeight()); - } - else if (orientation == verticalKeyboardFacingLeft) - { - scrollDown->setBounds (0, 0, getWidth(), scrollButtonW); - scrollUp->setBounds (0, getHeight() - scrollButtonW, getWidth(), scrollButtonW); - } - else if (orientation == verticalKeyboardFacingRight) - { - scrollDown->setBounds (0, getHeight() - scrollButtonW, getWidth(), scrollButtonW); - scrollUp->setBounds (0, 0, getWidth(), scrollButtonW); - } + if (orientation == horizontalKeyboard) + { + scrollDown->setBounds (0, 0, scrollButtonW, getHeight()); + scrollUp->setBounds (getWidth() - scrollButtonW, 0, scrollButtonW, getHeight()); + } + else if (orientation == verticalKeyboardFacingLeft) + { + scrollDown->setBounds (0, 0, getWidth(), scrollButtonW); + scrollUp->setBounds (0, getHeight() - scrollButtonW, getWidth(), scrollButtonW); + } + else if (orientation == verticalKeyboardFacingRight) + { + scrollDown->setBounds (0, getHeight() - scrollButtonW, getWidth(), scrollButtonW); + scrollUp->setBounds (0, 0, getWidth(), scrollButtonW); + } - int endOfLastKey, kw; - getKeyPos (rangeEnd, endOfLastKey, kw); - endOfLastKey += kw; + int endOfLastKey, kw; + getKeyPos (rangeEnd, endOfLastKey, kw); + endOfLastKey += kw; - float mousePositionVelocity; - const int spaceAvailable = w - scrollButtonW * 2; - const int lastStartKey = remappedXYToNote (endOfLastKey - spaceAvailable, 0, mousePositionVelocity) + 1; + float mousePositionVelocity; + const int spaceAvailable = w - scrollButtonW * 2; + const int lastStartKey = remappedXYToNote (endOfLastKey - spaceAvailable, 0, mousePositionVelocity) + 1; - if (lastStartKey >= 0 && firstKey > lastStartKey) - { - firstKey = jlimit (rangeStart, rangeEnd, lastStartKey); - sendChangeMessage (this); - } + if (lastStartKey >= 0 && firstKey > lastStartKey) + { + firstKey = jlimit (rangeStart, rangeEnd, lastStartKey); + sendChangeMessage (this); + } - int newOffset = 0; - getKeyPos (firstKey, newOffset, kw); - xOffset = newOffset - scrollButtonW; - } - else - { - firstKey = rangeStart; - } + int newOffset = 0; + getKeyPos (firstKey, newOffset, kw); + xOffset = newOffset - scrollButtonW; + } + else + { + firstKey = rangeStart; + } - timerCallback(); - repaint(); - } + timerCallback(); + repaint(); + } } void MidiKeyboardComponent::handleNoteOn (MidiKeyboardState*, int /*midiChannel*/, int /*midiNoteNumber*/, float /*velocity*/) { - triggerAsyncUpdate(); + triggerAsyncUpdate(); } void MidiKeyboardComponent::handleNoteOff (MidiKeyboardState*, int /*midiChannel*/, int /*midiNoteNumber*/) { - triggerAsyncUpdate(); + triggerAsyncUpdate(); } void MidiKeyboardComponent::handleAsyncUpdate() { - for (int i = rangeStart; i <= rangeEnd; ++i) - { - if (keysCurrentlyDrawnDown[i] != state.isNoteOnForChannels (midiInChannelMask, i)) - { - keysCurrentlyDrawnDown.setBit (i, state.isNoteOnForChannels (midiInChannelMask, i)); - repaintNote (i); - } - } + for (int i = rangeStart; i <= rangeEnd; ++i) + { + if (keysCurrentlyDrawnDown[i] != state.isNoteOnForChannels (midiInChannelMask, i)) + { + keysCurrentlyDrawnDown.setBit (i, state.isNoteOnForChannels (midiInChannelMask, i)); + repaintNote (i); + } + } } void MidiKeyboardComponent::resetAnyKeysInUse() { - if (keysPressed.countNumberOfSetBits() > 0 || mouseDownNote > 0) - { - state.allNotesOff (midiChannel); - keysPressed.clear(); - mouseDownNote = -1; - } + if (keysPressed.countNumberOfSetBits() > 0 || mouseDownNote > 0) + { + state.allNotesOff (midiChannel); + keysPressed.clear(); + mouseDownNote = -1; + } } void MidiKeyboardComponent::updateNoteUnderMouse (int x, int y) { - float mousePositionVelocity = 0.0f; - const int newNote = (mouseDragging || isMouseOver()) - ? xyToNote (x, y, mousePositionVelocity) : -1; + float mousePositionVelocity = 0.0f; + const int newNote = (mouseDragging || isMouseOver()) + ? xyToNote (x, y, mousePositionVelocity) : -1; - if (noteUnderMouse != newNote) - { - if (mouseDownNote >= 0) - { - state.noteOff (midiChannel, mouseDownNote); - mouseDownNote = -1; - } + if (noteUnderMouse != newNote) + { + if (mouseDownNote >= 0) + { + state.noteOff (midiChannel, mouseDownNote); + mouseDownNote = -1; + } - if (mouseDragging && newNote >= 0) - { - if (! useMousePositionForVelocity) - mousePositionVelocity = 1.0f; + if (mouseDragging && newNote >= 0) + { + if (! useMousePositionForVelocity) + mousePositionVelocity = 1.0f; - state.noteOn (midiChannel, newNote, mousePositionVelocity * velocity); - mouseDownNote = newNote; - } + state.noteOn (midiChannel, newNote, mousePositionVelocity * velocity); + mouseDownNote = newNote; + } - repaintNote (noteUnderMouse); - noteUnderMouse = newNote; - repaintNote (noteUnderMouse); - } - else if (mouseDownNote >= 0 && ! mouseDragging) - { - state.noteOff (midiChannel, mouseDownNote); - mouseDownNote = -1; - } + repaintNote (noteUnderMouse); + noteUnderMouse = newNote; + repaintNote (noteUnderMouse); + } + else if (mouseDownNote >= 0 && ! mouseDragging) + { + state.noteOff (midiChannel, mouseDownNote); + mouseDownNote = -1; + } } void MidiKeyboardComponent::mouseMove (const MouseEvent& e) { - updateNoteUnderMouse (e.x, e.y); - stopTimer(); + updateNoteUnderMouse (e.x, e.y); + stopTimer(); } void MidiKeyboardComponent::mouseDrag (const MouseEvent& e) { - float mousePositionVelocity; - const int newNote = xyToNote (e.x, e.y, mousePositionVelocity); + float mousePositionVelocity; + const int newNote = xyToNote (e.x, e.y, mousePositionVelocity); - if (newNote >= 0) - mouseDraggedToKey (newNote, e); + if (newNote >= 0) + mouseDraggedToKey (newNote, e); - updateNoteUnderMouse (e.x, e.y); + updateNoteUnderMouse (e.x, e.y); } bool MidiKeyboardComponent::mouseDownOnKey (int /*midiNoteNumber*/, const MouseEvent&) { - return true; + return true; } void MidiKeyboardComponent::mouseDraggedToKey (int /*midiNoteNumber*/, const MouseEvent&) @@ -75168,121 +74971,121 @@ void MidiKeyboardComponent::mouseDraggedToKey (int /*midiNoteNumber*/, const Mou void MidiKeyboardComponent::mouseDown (const MouseEvent& e) { - float mousePositionVelocity; - const int newNote = xyToNote (e.x, e.y, mousePositionVelocity); - mouseDragging = false; + float mousePositionVelocity; + const int newNote = xyToNote (e.x, e.y, mousePositionVelocity); + mouseDragging = false; - if (newNote >= 0 && mouseDownOnKey (newNote, e)) - { - repaintNote (noteUnderMouse); - noteUnderMouse = -1; - mouseDragging = true; + if (newNote >= 0 && mouseDownOnKey (newNote, e)) + { + repaintNote (noteUnderMouse); + noteUnderMouse = -1; + mouseDragging = true; - updateNoteUnderMouse (e.x, e.y); - startTimer (500); - } + updateNoteUnderMouse (e.x, e.y); + startTimer (500); + } } void MidiKeyboardComponent::mouseUp (const MouseEvent& e) { - mouseDragging = false; - updateNoteUnderMouse (e.x, e.y); + mouseDragging = false; + updateNoteUnderMouse (e.x, e.y); - stopTimer(); + stopTimer(); } void MidiKeyboardComponent::mouseEnter (const MouseEvent& e) { - updateNoteUnderMouse (e.x, e.y); + updateNoteUnderMouse (e.x, e.y); } void MidiKeyboardComponent::mouseExit (const MouseEvent& e) { - updateNoteUnderMouse (e.x, e.y); + updateNoteUnderMouse (e.x, e.y); } void MidiKeyboardComponent::mouseWheelMove (const MouseEvent&, float ix, float iy) { - setLowestVisibleKey (getLowestVisibleKey() + roundFloatToInt ((ix != 0 ? ix : iy) * 5.0f)); + setLowestVisibleKey (getLowestVisibleKey() + roundToInt ((ix != 0 ? ix : iy) * 5.0f)); } void MidiKeyboardComponent::timerCallback() { - int mx, my; - getMouseXYRelative (mx, my); + int mx, my; + getMouseXYRelative (mx, my); - updateNoteUnderMouse (mx, my); + updateNoteUnderMouse (mx, my); } void MidiKeyboardComponent::clearKeyMappings() { - resetAnyKeysInUse(); - keyPressNotes.clear(); - keyPresses.clear(); + resetAnyKeysInUse(); + keyPressNotes.clear(); + keyPresses.clear(); } void MidiKeyboardComponent::setKeyPressForNote (const KeyPress& key, - const int midiNoteOffsetFromC) + const int midiNoteOffsetFromC) { - removeKeyPressForNote (midiNoteOffsetFromC); + removeKeyPressForNote (midiNoteOffsetFromC); - keyPressNotes.add (midiNoteOffsetFromC); - keyPresses.add (key); + keyPressNotes.add (midiNoteOffsetFromC); + keyPresses.add (key); } void MidiKeyboardComponent::removeKeyPressForNote (const int midiNoteOffsetFromC) { - for (int i = keyPressNotes.size(); --i >= 0;) - { - if (keyPressNotes.getUnchecked (i) == midiNoteOffsetFromC) - { - keyPressNotes.remove (i); - keyPresses.remove (i); - } - } + for (int i = keyPressNotes.size(); --i >= 0;) + { + if (keyPressNotes.getUnchecked (i) == midiNoteOffsetFromC) + { + keyPressNotes.remove (i); + keyPresses.remove (i); + } + } } void MidiKeyboardComponent::setKeyPressBaseOctave (const int newOctaveNumber) { - jassert (newOctaveNumber >= 0 && newOctaveNumber <= 10); + jassert (newOctaveNumber >= 0 && newOctaveNumber <= 10); - keyMappingOctave = newOctaveNumber; + keyMappingOctave = newOctaveNumber; } bool MidiKeyboardComponent::keyStateChanged (const bool /*isKeyDown*/) { - bool keyPressUsed = false; + bool keyPressUsed = false; - for (int i = keyPresses.size(); --i >= 0;) - { - const int note = 12 * keyMappingOctave + keyPressNotes.getUnchecked (i); + for (int i = keyPresses.size(); --i >= 0;) + { + const int note = 12 * keyMappingOctave + keyPressNotes.getUnchecked (i); - if (keyPresses.getReference(i).isCurrentlyDown()) - { - if (! keysPressed [note]) - { - keysPressed.setBit (note); - state.noteOn (midiChannel, note, velocity); - keyPressUsed = true; - } - } - else - { - if (keysPressed [note]) - { - keysPressed.clearBit (note); - state.noteOff (midiChannel, note); - keyPressUsed = true; - } - } - } + if (keyPresses.getReference(i).isCurrentlyDown()) + { + if (! keysPressed [note]) + { + keysPressed.setBit (note); + state.noteOn (midiChannel, note, velocity); + keyPressUsed = true; + } + } + else + { + if (keysPressed [note]) + { + keysPressed.clearBit (note); + state.noteOff (midiChannel, note); + keyPressUsed = true; + } + } + } - return keyPressUsed; + return keyPressUsed; } void MidiKeyboardComponent::focusLost (FocusChangeType) { - resetAnyKeysInUse(); + resetAnyKeysInUse(); } END_JUCE_NAMESPACE @@ -75297,251 +75100,251 @@ BEGIN_JUCE_NAMESPACE extern void juce_glViewport (const int w, const int h); OpenGLPixelFormat::OpenGLPixelFormat (const int bitsPerRGBComponent, - const int alphaBits_, - const int depthBufferBits_, - const int stencilBufferBits_) throw() - : redBits (bitsPerRGBComponent), - greenBits (bitsPerRGBComponent), - blueBits (bitsPerRGBComponent), - alphaBits (alphaBits_), - depthBufferBits (depthBufferBits_), - stencilBufferBits (stencilBufferBits_), - accumulationBufferRedBits (0), - accumulationBufferGreenBits (0), - accumulationBufferBlueBits (0), - accumulationBufferAlphaBits (0), - fullSceneAntiAliasingNumSamples (0) + const int alphaBits_, + const int depthBufferBits_, + const int stencilBufferBits_) throw() + : redBits (bitsPerRGBComponent), + greenBits (bitsPerRGBComponent), + blueBits (bitsPerRGBComponent), + alphaBits (alphaBits_), + depthBufferBits (depthBufferBits_), + stencilBufferBits (stencilBufferBits_), + accumulationBufferRedBits (0), + accumulationBufferGreenBits (0), + accumulationBufferBlueBits (0), + accumulationBufferAlphaBits (0), + fullSceneAntiAliasingNumSamples (0) { } bool OpenGLPixelFormat::operator== (const OpenGLPixelFormat& other) const throw() { - return memcmp (this, &other, sizeof (other)) == 0; + return memcmp (this, &other, sizeof (other)) == 0; } static VoidArray knownContexts; OpenGLContext::OpenGLContext() throw() { - knownContexts.add (this); + knownContexts.add (this); } OpenGLContext::~OpenGLContext() { - knownContexts.removeValue (this); + knownContexts.removeValue (this); } OpenGLContext* OpenGLContext::getCurrentContext() { - for (int i = knownContexts.size(); --i >= 0;) - { - OpenGLContext* const oglc = (OpenGLContext*) knownContexts.getUnchecked(i); + for (int i = knownContexts.size(); --i >= 0;) + { + OpenGLContext* const oglc = (OpenGLContext*) knownContexts.getUnchecked(i); - if (oglc->isActive()) - return oglc; - } + if (oglc->isActive()) + return oglc; + } - return 0; + return 0; } class OpenGLComponentWatcher : public ComponentMovementWatcher { public: - OpenGLComponentWatcher (OpenGLComponent* const owner_) - : ComponentMovementWatcher (owner_), - owner (owner_), - wasShowing (false) - { - } + OpenGLComponentWatcher (OpenGLComponent* const owner_) + : ComponentMovementWatcher (owner_), + owner (owner_), + wasShowing (false) + { + } - ~OpenGLComponentWatcher() {} + ~OpenGLComponentWatcher() {} - void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) - { - owner->updateContextPosition(); - } + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) + { + owner->updateContextPosition(); + } - void componentPeerChanged() - { - const ScopedLock sl (owner->getContextLock()); - owner->deleteContext(); - } + void componentPeerChanged() + { + const ScopedLock sl (owner->getContextLock()); + owner->deleteContext(); + } - void componentVisibilityChanged (Component&) - { - const bool isShowingNow = owner->isShowing(); + void componentVisibilityChanged (Component&) + { + const bool isShowingNow = owner->isShowing(); - if (wasShowing != isShowingNow) - { - wasShowing = isShowingNow; - owner->updateContextPosition(); - } - } + if (wasShowing != isShowingNow) + { + wasShowing = isShowingNow; + owner->updateContextPosition(); + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OpenGLComponent* const owner; - bool wasShowing; + OpenGLComponent* const owner; + bool wasShowing; }; OpenGLComponent::OpenGLComponent() - : context (0), - contextToShareListsWith (0), - needToUpdateViewport (true) + : context (0), + contextToShareListsWith (0), + needToUpdateViewport (true) { - setOpaque (true); - componentWatcher = new OpenGLComponentWatcher (this); + setOpaque (true); + componentWatcher = new OpenGLComponentWatcher (this); } OpenGLComponent::~OpenGLComponent() { - deleteContext(); - delete componentWatcher; + deleteContext(); + delete componentWatcher; } void OpenGLComponent::deleteContext() { - const ScopedLock sl (contextLock); - deleteAndZero (context); + const ScopedLock sl (contextLock); + deleteAndZero (context); } void OpenGLComponent::updateContextPosition() { - needToUpdateViewport = true; + needToUpdateViewport = true; - if (getWidth() > 0 && getHeight() > 0) - { - Component* const topComp = getTopLevelComponent(); + if (getWidth() > 0 && getHeight() > 0) + { + Component* const topComp = getTopLevelComponent(); - if (topComp->getPeer() != 0) - { - const ScopedLock sl (contextLock); + if (topComp->getPeer() != 0) + { + const ScopedLock sl (contextLock); - if (context != 0) - context->updateWindowPosition (getScreenX() - topComp->getScreenX(), - getScreenY() - topComp->getScreenY(), - getWidth(), - getHeight(), - topComp->getHeight()); - } - } + if (context != 0) + context->updateWindowPosition (getScreenX() - topComp->getScreenX(), + getScreenY() - topComp->getScreenY(), + getWidth(), + getHeight(), + topComp->getHeight()); + } + } } const OpenGLPixelFormat OpenGLComponent::getPixelFormat() const { - OpenGLPixelFormat pf; + OpenGLPixelFormat pf; - const ScopedLock sl (contextLock); - if (context != 0) - pf = context->getPixelFormat(); + const ScopedLock sl (contextLock); + if (context != 0) + pf = context->getPixelFormat(); - return pf; + return pf; } void OpenGLComponent::setPixelFormat (const OpenGLPixelFormat& formatToUse) { - if (! (preferredPixelFormat == formatToUse)) - { - const ScopedLock sl (contextLock); - deleteContext(); - preferredPixelFormat = formatToUse; - } + if (! (preferredPixelFormat == formatToUse)) + { + const ScopedLock sl (contextLock); + deleteContext(); + preferredPixelFormat = formatToUse; + } } void OpenGLComponent::shareWith (OpenGLContext* c) { - if (contextToShareListsWith != c) - { - const ScopedLock sl (contextLock); - deleteContext(); - contextToShareListsWith = c; - } + if (contextToShareListsWith != c) + { + const ScopedLock sl (contextLock); + deleteContext(); + contextToShareListsWith = c; + } } bool OpenGLComponent::makeCurrentContextActive() { - if (context == 0) - { - const ScopedLock sl (contextLock); + if (context == 0) + { + const ScopedLock sl (contextLock); - if (isShowing() && getTopLevelComponent()->getPeer() != 0) - { - context = OpenGLContext::createContextForWindow (this, - preferredPixelFormat, - contextToShareListsWith); + if (isShowing() && getTopLevelComponent()->getPeer() != 0) + { + context = OpenGLContext::createContextForWindow (this, + preferredPixelFormat, + contextToShareListsWith); - if (context != 0) - { - updateContextPosition(); + if (context != 0) + { + updateContextPosition(); - if (context->makeActive()) - newOpenGLContextCreated(); - } - } - } + if (context->makeActive()) + newOpenGLContextCreated(); + } + } + } - return context != 0 && context->makeActive(); + return context != 0 && context->makeActive(); } void OpenGLComponent::makeCurrentContextInactive() { - if (context != 0) - context->makeInactive(); + if (context != 0) + context->makeInactive(); } bool OpenGLComponent::isActiveContext() const throw() { - return context != 0 && context->isActive(); + return context != 0 && context->isActive(); } void OpenGLComponent::swapBuffers() { - if (context != 0) - context->swapBuffers(); + if (context != 0) + context->swapBuffers(); } void OpenGLComponent::paint (Graphics&) { - if (renderAndSwapBuffers()) - { - ComponentPeer* const peer = getPeer(); + if (renderAndSwapBuffers()) + { + ComponentPeer* const peer = getPeer(); - if (peer != 0) - { - peer->addMaskedRegion (getScreenX() - peer->getScreenX(), - getScreenY() - peer->getScreenY(), - getWidth(), getHeight()); - } - } + if (peer != 0) + { + peer->addMaskedRegion (getScreenX() - peer->getScreenX(), + getScreenY() - peer->getScreenY(), + getWidth(), getHeight()); + } + } } bool OpenGLComponent::renderAndSwapBuffers() { - const ScopedLock sl (contextLock); + const ScopedLock sl (contextLock); - if (! makeCurrentContextActive()) - return false; + if (! makeCurrentContextActive()) + return false; - if (needToUpdateViewport) - { - needToUpdateViewport = false; - juce_glViewport (getWidth(), getHeight()); - } + if (needToUpdateViewport) + { + needToUpdateViewport = false; + juce_glViewport (getWidth(), getHeight()); + } - renderOpenGL(); - swapBuffers(); + renderOpenGL(); + swapBuffers(); - return true; + return true; } void OpenGLComponent::internalRepaint (int x, int y, int w, int h) { - Component::internalRepaint (x, y, w, h); + Component::internalRepaint (x, y, w, h); - if (context != 0) - context->repaint(); + if (context != 0) + context->repaint(); } END_JUCE_NAMESPACE @@ -75554,156 +75357,156 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE PreferencesPanel::PreferencesPanel() - : buttonSize (70) + : buttonSize (70) { } PreferencesPanel::~PreferencesPanel() { - currentPage = 0; - deleteAllChildren(); + currentPage = 0; + deleteAllChildren(); } void PreferencesPanel::addSettingsPage (const String& title, - const Drawable* icon, - const Drawable* overIcon, - const Drawable* downIcon) + const Drawable* icon, + const Drawable* overIcon, + const Drawable* downIcon) { - DrawableButton* button = new DrawableButton (title, DrawableButton::ImageAboveTextLabel); - button->setImages (icon, overIcon, downIcon); - button->setRadioGroupId (1); - button->addButtonListener (this); - button->setClickingTogglesState (true); - button->setWantsKeyboardFocus (false); - addAndMakeVisible (button); + DrawableButton* button = new DrawableButton (title, DrawableButton::ImageAboveTextLabel); + button->setImages (icon, overIcon, downIcon); + button->setRadioGroupId (1); + button->addButtonListener (this); + button->setClickingTogglesState (true); + button->setWantsKeyboardFocus (false); + addAndMakeVisible (button); - resized(); + resized(); - if (currentPage == 0) - setCurrentPage (title); + if (currentPage == 0) + setCurrentPage (title); } void PreferencesPanel::addSettingsPage (const String& title, - const char* imageData, - const int imageDataSize) + const char* imageData, + const int imageDataSize) { - DrawableImage icon, iconOver, iconDown; - icon.setImage (ImageCache::getFromMemory (imageData, imageDataSize), true); + DrawableImage icon, iconOver, iconDown; + icon.setImage (ImageCache::getFromMemory (imageData, imageDataSize), true); - iconOver.setImage (ImageCache::getFromMemory (imageData, imageDataSize), true); - iconOver.setOverlayColour (Colours::black.withAlpha (0.12f)); + iconOver.setImage (ImageCache::getFromMemory (imageData, imageDataSize), true); + iconOver.setOverlayColour (Colours::black.withAlpha (0.12f)); - iconDown.setImage (ImageCache::getFromMemory (imageData, imageDataSize), true); - iconDown.setOverlayColour (Colours::black.withAlpha (0.25f)); + iconDown.setImage (ImageCache::getFromMemory (imageData, imageDataSize), true); + iconDown.setOverlayColour (Colours::black.withAlpha (0.25f)); - addSettingsPage (title, &icon, &iconOver, &iconDown); + addSettingsPage (title, &icon, &iconOver, &iconDown); } class PrefsDialogWindow : public DialogWindow { public: - PrefsDialogWindow (const String& dialogtitle, - const Colour& backgroundColour) - : DialogWindow (dialogtitle, backgroundColour, true) - { - } + PrefsDialogWindow (const String& dialogtitle, + const Colour& backgroundColour) + : DialogWindow (dialogtitle, backgroundColour, true) + { + } - ~PrefsDialogWindow() - { - } + ~PrefsDialogWindow() + { + } - void closeButtonPressed() - { - exitModalState (0); - } + void closeButtonPressed() + { + exitModalState (0); + } private: - PrefsDialogWindow (const PrefsDialogWindow&); - const PrefsDialogWindow& operator= (const PrefsDialogWindow&); + PrefsDialogWindow (const PrefsDialogWindow&); + const PrefsDialogWindow& operator= (const PrefsDialogWindow&); }; void PreferencesPanel::showInDialogBox (const String& dialogtitle, - int dialogWidth, - int dialogHeight, - const Colour& backgroundColour) + int dialogWidth, + int dialogHeight, + const Colour& backgroundColour) { - setSize (dialogWidth, dialogHeight); + setSize (dialogWidth, dialogHeight); - PrefsDialogWindow dw (dialogtitle, backgroundColour); + PrefsDialogWindow dw (dialogtitle, backgroundColour); - dw.setContentComponent (this, true, true); - dw.centreAroundComponent (0, dw.getWidth(), dw.getHeight()); - dw.runModalLoop(); - dw.setContentComponent (0, false, false); + dw.setContentComponent (this, true, true); + dw.centreAroundComponent (0, dw.getWidth(), dw.getHeight()); + dw.runModalLoop(); + dw.setContentComponent (0, false, false); } void PreferencesPanel::resized() { - int x = 0; + int x = 0; - for (int i = 0; i < getNumChildComponents(); ++i) - { - Component* c = getChildComponent (i); + for (int i = 0; i < getNumChildComponents(); ++i) + { + Component* c = getChildComponent (i); - if (dynamic_cast (c) == 0) - { - c->setBounds (0, buttonSize + 5, getWidth(), getHeight() - buttonSize - 5); - } - else - { - c->setBounds (x, 0, buttonSize, buttonSize); - x += buttonSize; - } - } + if (dynamic_cast (c) == 0) + { + c->setBounds (0, buttonSize + 5, getWidth(), getHeight() - buttonSize - 5); + } + else + { + c->setBounds (x, 0, buttonSize, buttonSize); + x += buttonSize; + } + } } void PreferencesPanel::paint (Graphics& g) { - g.setColour (Colours::grey); - g.fillRect (0, buttonSize + 2, getWidth(), 1); + g.setColour (Colours::grey); + g.fillRect (0, buttonSize + 2, getWidth(), 1); } void PreferencesPanel::setCurrentPage (const String& pageName) { - if (currentPageName != pageName) - { - currentPageName = pageName; + if (currentPageName != pageName) + { + currentPageName = pageName; - currentPage = 0; - currentPage = createComponentForPage (pageName); + currentPage = 0; + currentPage = createComponentForPage (pageName); - if (currentPage != 0) - { - addAndMakeVisible (currentPage); - currentPage->toBack(); - resized(); - } + if (currentPage != 0) + { + addAndMakeVisible (currentPage); + currentPage->toBack(); + resized(); + } - for (int i = 0; i < getNumChildComponents(); ++i) - { - DrawableButton* db = dynamic_cast (getChildComponent (i)); + for (int i = 0; i < getNumChildComponents(); ++i) + { + DrawableButton* db = dynamic_cast (getChildComponent (i)); - if (db != 0 && db->getName() == pageName) - { - db->setToggleState (true, false); - break; - } - } - } + if (db != 0 && db->getName() == pageName) + { + db->setToggleState (true, false); + break; + } + } + } } void PreferencesPanel::buttonClicked (Button*) { - for (int i = 0; i < getNumChildComponents(); ++i) - { - DrawableButton* db = dynamic_cast (getChildComponent (i)); + for (int i = 0; i < getNumChildComponents(); ++i) + { + DrawableButton* db = dynamic_cast (getChildComponent (i)); - if (db != 0 && db->getToggleState()) - { - setCurrentPage (db->getName()); - break; - } - } + if (db != 0 && db->getToggleState()) + { + setCurrentPage (db->getName()); + break; + } + } } END_JUCE_NAMESPACE @@ -75717,7 +75520,7 @@ BEGIN_JUCE_NAMESPACE SystemTrayIconComponent::SystemTrayIconComponent() { - addToDesktop (0); + addToDesktop (0); } SystemTrayIconComponent::~SystemTrayIconComponent() @@ -75739,33 +75542,33 @@ static const int iconWidth = 80; class AlertWindowTextEditor : public TextEditor { public: - static const tchar passwordChar; + static const tchar passwordChar; - AlertWindowTextEditor (const String& name, const bool isPasswordBox) - : TextEditor (name, isPasswordBox ? passwordChar : 0) - { - setSelectAllWhenFocused (true); - } + AlertWindowTextEditor (const String& name, const bool isPasswordBox) + : TextEditor (name, isPasswordBox ? passwordChar : 0) + { + setSelectAllWhenFocused (true); + } - ~AlertWindowTextEditor() - { - } + ~AlertWindowTextEditor() + { + } - void returnPressed() - { - // pass these up the component hierarchy to be trigger the buttons - getParentComponent()->keyPressed (KeyPress (KeyPress::returnKey, 0, T('\n'))); - } + void returnPressed() + { + // pass these up the component hierarchy to be trigger the buttons + getParentComponent()->keyPressed (KeyPress (KeyPress::returnKey, 0, T('\n'))); + } - void escapePressed() - { - // pass these up the component hierarchy to be trigger the buttons - getParentComponent()->keyPressed (KeyPress (KeyPress::escapeKey, 0, 0)); - } + void escapePressed() + { + // pass these up the component hierarchy to be trigger the buttons + getParentComponent()->keyPressed (KeyPress (KeyPress::escapeKey, 0, 0)); + } private: - AlertWindowTextEditor (const AlertWindowTextEditor&); - const AlertWindowTextEditor& operator= (const AlertWindowTextEditor&); + AlertWindowTextEditor (const AlertWindowTextEditor&); + const AlertWindowTextEditor& operator= (const AlertWindowTextEditor&); }; #if JUCE_LINUX @@ -75775,593 +75578,593 @@ const tchar AlertWindowTextEditor::passwordChar = 0x25cf; #endif AlertWindow::AlertWindow (const String& title, - const String& message, - AlertIconType iconType, - Component* associatedComponent_) + const String& message, + AlertIconType iconType, + Component* associatedComponent_) : TopLevelWindow (title, true), - alertIconType (iconType), - associatedComponent (associatedComponent_) + alertIconType (iconType), + associatedComponent (associatedComponent_) { - if (message.isEmpty()) - text = T(" "); // to force an update if the message is empty + if (message.isEmpty()) + text = T(" "); // to force an update if the message is empty - setMessage (message); + setMessage (message); - for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) - { - Component* const c = Desktop::getInstance().getComponent (i); + for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) + { + Component* const c = Desktop::getInstance().getComponent (i); - if (c != 0 && c->isAlwaysOnTop() && c->isShowing()) - { - setAlwaysOnTop (true); - break; - } - } + if (c != 0 && c->isAlwaysOnTop() && c->isShowing()) + { + setAlwaysOnTop (true); + break; + } + } - if (JUCEApplication::getInstance() == 0) - setAlwaysOnTop (true); // for a plugin, make it always-on-top because the host windows are often top-level + if (JUCEApplication::getInstance() == 0) + setAlwaysOnTop (true); // for a plugin, make it always-on-top because the host windows are often top-level - lookAndFeelChanged(); + lookAndFeelChanged(); - constrainer.setMinimumOnscreenAmounts (0x10000, 0x10000, 0x10000, 0x10000); + constrainer.setMinimumOnscreenAmounts (0x10000, 0x10000, 0x10000, 0x10000); } AlertWindow::~AlertWindow() { - for (int i = customComps.size(); --i >= 0;) - removeChildComponent ((Component*) customComps[i]); + for (int i = customComps.size(); --i >= 0;) + removeChildComponent ((Component*) customComps[i]); - deleteAllChildren(); + deleteAllChildren(); } void AlertWindow::userTriedToCloseWindow() { - exitModalState (0); + exitModalState (0); } void AlertWindow::setMessage (const String& message) { - const String newMessage (message.substring (0, 2048)); + const String newMessage (message.substring (0, 2048)); - if (text != newMessage) - { - text = newMessage; + if (text != newMessage) + { + text = newMessage; - font.setHeight (15.0f); + font.setHeight (15.0f); - Font titleFont (font.getHeight() * 1.1f, Font::bold); - textLayout.setText (getName() + T("\n\n"), titleFont); + Font titleFont (font.getHeight() * 1.1f, Font::bold); + textLayout.setText (getName() + T("\n\n"), titleFont); - textLayout.appendText (text, font); + textLayout.appendText (text, font); - updateLayout (true); - repaint(); - } + updateLayout (true); + repaint(); + } } void AlertWindow::buttonClicked (Button* button) { - for (int i = 0; i < buttons.size(); i++) - { - TextButton* const c = (TextButton*) buttons[i]; + for (int i = 0; i < buttons.size(); i++) + { + TextButton* const c = (TextButton*) buttons[i]; - if (button->getName() == c->getName()) - { - if (c->getParentComponent() != 0) - c->getParentComponent()->exitModalState (c->getCommandID()); + if (button->getName() == c->getName()) + { + if (c->getParentComponent() != 0) + c->getParentComponent()->exitModalState (c->getCommandID()); - break; - } - } + break; + } + } } void AlertWindow::addButton (const String& name, - const int returnValue, - const KeyPress& shortcutKey1, - const KeyPress& shortcutKey2) + const int returnValue, + const KeyPress& shortcutKey1, + const KeyPress& shortcutKey2) { - TextButton* const b = new TextButton (name, String::empty); + TextButton* const b = new TextButton (name, String::empty); - b->setWantsKeyboardFocus (true); - b->setMouseClickGrabsKeyboardFocus (false); - b->setCommandToTrigger (0, returnValue, false); - b->addShortcut (shortcutKey1); - b->addShortcut (shortcutKey2); - b->addButtonListener (this); - b->changeWidthToFitText (getLookAndFeel().getAlertWindowButtonHeight()); + b->setWantsKeyboardFocus (true); + b->setMouseClickGrabsKeyboardFocus (false); + b->setCommandToTrigger (0, returnValue, false); + b->addShortcut (shortcutKey1); + b->addShortcut (shortcutKey2); + b->addButtonListener (this); + b->changeWidthToFitText (getLookAndFeel().getAlertWindowButtonHeight()); - addAndMakeVisible (b, 0); - buttons.add (b); + addAndMakeVisible (b, 0); + buttons.add (b); - updateLayout (false); + updateLayout (false); } int AlertWindow::getNumButtons() const { - return buttons.size(); + return buttons.size(); } void AlertWindow::addTextEditor (const String& name, - const String& initialContents, - const String& onScreenLabel, - const bool isPasswordBox) + const String& initialContents, + const String& onScreenLabel, + const bool isPasswordBox) { - AlertWindowTextEditor* const tc = new AlertWindowTextEditor (name, isPasswordBox); + AlertWindowTextEditor* const tc = new AlertWindowTextEditor (name, isPasswordBox); - tc->setColour (TextEditor::outlineColourId, findColour (ComboBox::outlineColourId)); - tc->setFont (font); - tc->setText (initialContents); - tc->setCaretPosition (initialContents.length()); - addAndMakeVisible (tc); - textBoxes.add (tc); - allComps.add (tc); - textboxNames.add (onScreenLabel); + tc->setColour (TextEditor::outlineColourId, findColour (ComboBox::outlineColourId)); + tc->setFont (font); + tc->setText (initialContents); + tc->setCaretPosition (initialContents.length()); + addAndMakeVisible (tc); + textBoxes.add (tc); + allComps.add (tc); + textboxNames.add (onScreenLabel); - updateLayout (false); + updateLayout (false); } const String AlertWindow::getTextEditorContents (const String& nameOfTextEditor) const { - for (int i = textBoxes.size(); --i >= 0;) - if (((TextEditor*)textBoxes[i])->getName() == nameOfTextEditor) - return ((TextEditor*)textBoxes[i])->getText(); + for (int i = textBoxes.size(); --i >= 0;) + if (((TextEditor*)textBoxes[i])->getName() == nameOfTextEditor) + return ((TextEditor*)textBoxes[i])->getText(); - return String::empty; + return String::empty; } void AlertWindow::addComboBox (const String& name, - const StringArray& items, - const String& onScreenLabel) + const StringArray& items, + const String& onScreenLabel) { - ComboBox* const cb = new ComboBox (name); + ComboBox* const cb = new ComboBox (name); - for (int i = 0; i < items.size(); ++i) - cb->addItem (items[i], i + 1); + for (int i = 0; i < items.size(); ++i) + cb->addItem (items[i], i + 1); - addAndMakeVisible (cb); - cb->setSelectedItemIndex (0); + addAndMakeVisible (cb); + cb->setSelectedItemIndex (0); - comboBoxes.add (cb); - allComps.add (cb); + comboBoxes.add (cb); + allComps.add (cb); - comboBoxNames.add (onScreenLabel); + comboBoxNames.add (onScreenLabel); - updateLayout (false); + updateLayout (false); } ComboBox* AlertWindow::getComboBoxComponent (const String& nameOfList) const { - for (int i = comboBoxes.size(); --i >= 0;) - if (((ComboBox*) comboBoxes[i])->getName() == nameOfList) - return (ComboBox*) comboBoxes[i]; + for (int i = comboBoxes.size(); --i >= 0;) + if (((ComboBox*) comboBoxes[i])->getName() == nameOfList) + return (ComboBox*) comboBoxes[i]; - return 0; + return 0; } class AlertTextComp : public TextEditor { - AlertTextComp (const AlertTextComp&); - const AlertTextComp& operator= (const AlertTextComp&); + AlertTextComp (const AlertTextComp&); + const AlertTextComp& operator= (const AlertTextComp&); - int bestWidth; + int bestWidth; public: - AlertTextComp (const String& message, - const Font& font) - { - setReadOnly (true); - setMultiLine (true, true); - setCaretVisible (false); - setScrollbarsShown (true); - lookAndFeelChanged(); - setWantsKeyboardFocus (false); + AlertTextComp (const String& message, + const Font& font) + { + setReadOnly (true); + setMultiLine (true, true); + setCaretVisible (false); + setScrollbarsShown (true); + lookAndFeelChanged(); + setWantsKeyboardFocus (false); - setFont (font); - setText (message, false); + setFont (font); + setText (message, false); - bestWidth = 2 * (int) sqrt (font.getHeight() * font.getStringWidth (message)); + bestWidth = 2 * (int) sqrt (font.getHeight() * font.getStringWidth (message)); - setColour (TextEditor::backgroundColourId, Colours::transparentBlack); - setColour (TextEditor::outlineColourId, Colours::transparentBlack); - setColour (TextEditor::shadowColourId, Colours::transparentBlack); - } + setColour (TextEditor::backgroundColourId, Colours::transparentBlack); + setColour (TextEditor::outlineColourId, Colours::transparentBlack); + setColour (TextEditor::shadowColourId, Colours::transparentBlack); + } - ~AlertTextComp() - { - } + ~AlertTextComp() + { + } - int getPreferredWidth() const throw() { return bestWidth; } + int getPreferredWidth() const throw() { return bestWidth; } - void updateLayout (const int width) - { - TextLayout text; - text.appendText (getText(), getFont()); - text.layout (width - 8, Justification::topLeft, true); - setSize (width, jmin (width, text.getHeight() + (int) getFont().getHeight())); - } + void updateLayout (const int width) + { + TextLayout text; + text.appendText (getText(), getFont()); + text.layout (width - 8, Justification::topLeft, true); + setSize (width, jmin (width, text.getHeight() + (int) getFont().getHeight())); + } }; void AlertWindow::addTextBlock (const String& text) { - AlertTextComp* const c = new AlertTextComp (text, font); + AlertTextComp* const c = new AlertTextComp (text, font); - textBlocks.add (c); - allComps.add (c); + textBlocks.add (c); + allComps.add (c); - addAndMakeVisible (c); + addAndMakeVisible (c); - updateLayout (false); + updateLayout (false); } void AlertWindow::addProgressBarComponent (double& progressValue) { - ProgressBar* const pb = new ProgressBar (progressValue); + ProgressBar* const pb = new ProgressBar (progressValue); - progressBars.add (pb); - allComps.add (pb); + progressBars.add (pb); + allComps.add (pb); - addAndMakeVisible (pb); + addAndMakeVisible (pb); - updateLayout (false); + updateLayout (false); } void AlertWindow::addCustomComponent (Component* const component) { - customComps.add (component); - allComps.add (component); + customComps.add (component); + allComps.add (component); - addAndMakeVisible (component); + addAndMakeVisible (component); - updateLayout (false); + updateLayout (false); } int AlertWindow::getNumCustomComponents() const { - return customComps.size(); + return customComps.size(); } Component* AlertWindow::getCustomComponent (const int index) const { - return (Component*) customComps [index]; + return (Component*) customComps [index]; } Component* AlertWindow::removeCustomComponent (const int index) { - Component* const c = getCustomComponent (index); + Component* const c = getCustomComponent (index); - if (c != 0) - { - customComps.removeValue (c); - allComps.removeValue (c); - removeChildComponent (c); + if (c != 0) + { + customComps.removeValue (c); + allComps.removeValue (c); + removeChildComponent (c); - updateLayout (false); - } + updateLayout (false); + } - return c; + return c; } void AlertWindow::paint (Graphics& g) { - getLookAndFeel().drawAlertBox (g, *this, textArea, textLayout); + getLookAndFeel().drawAlertBox (g, *this, textArea, textLayout); - g.setColour (findColour (textColourId)); - g.setFont (getLookAndFeel().getAlertWindowFont()); + g.setColour (findColour (textColourId)); + g.setFont (getLookAndFeel().getAlertWindowFont()); - int i; - for (i = textBoxes.size(); --i >= 0;) - { - if (textboxNames[i].isNotEmpty()) - { - const TextEditor* const te = (TextEditor*) textBoxes[i]; + int i; + for (i = textBoxes.size(); --i >= 0;) + { + if (textboxNames[i].isNotEmpty()) + { + const TextEditor* const te = (TextEditor*) textBoxes[i]; - g.drawFittedText (textboxNames[i], - te->getX(), te->getY() - 14, - te->getWidth(), 14, - Justification::centredLeft, 1); - } - } + g.drawFittedText (textboxNames[i], + te->getX(), te->getY() - 14, + te->getWidth(), 14, + Justification::centredLeft, 1); + } + } - for (i = comboBoxNames.size(); --i >= 0;) - { - if (comboBoxNames[i].isNotEmpty()) - { - const ComboBox* const cb = (ComboBox*) comboBoxes[i]; + for (i = comboBoxNames.size(); --i >= 0;) + { + if (comboBoxNames[i].isNotEmpty()) + { + const ComboBox* const cb = (ComboBox*) comboBoxes[i]; - g.drawFittedText (comboBoxNames[i], - cb->getX(), cb->getY() - 14, - cb->getWidth(), 14, - Justification::centredLeft, 1); - } - } + g.drawFittedText (comboBoxNames[i], + cb->getX(), cb->getY() - 14, + cb->getWidth(), 14, + Justification::centredLeft, 1); + } + } } void AlertWindow::updateLayout (const bool onlyIncreaseSize) { - const int wid = jmax (font.getStringWidth (text), - font.getStringWidth (getName())); + const int wid = jmax (font.getStringWidth (text), + font.getStringWidth (getName())); - const int sw = (int) sqrt (font.getHeight() * wid); - int w = jmin (300 + sw * 2, (int) (getParentWidth() * 0.7f)); - const int edgeGap = 10; - int iconSpace; + const int sw = (int) sqrt (font.getHeight() * wid); + int w = jmin (300 + sw * 2, (int) (getParentWidth() * 0.7f)); + const int edgeGap = 10; + int iconSpace; - if (alertIconType == NoIcon) - { - textLayout.layout (w, Justification::horizontallyCentred, true); - iconSpace = 0; - } - else - { - textLayout.layout (w, Justification::left, true); - iconSpace = iconWidth; - } + if (alertIconType == NoIcon) + { + textLayout.layout (w, Justification::horizontallyCentred, true); + iconSpace = 0; + } + else + { + textLayout.layout (w, Justification::left, true); + iconSpace = iconWidth; + } - w = jmax (350, textLayout.getWidth() + iconSpace + edgeGap * 4); - w = jmin (w, (int) (getParentWidth() * 0.7f)); + w = jmax (350, textLayout.getWidth() + iconSpace + edgeGap * 4); + w = jmin (w, (int) (getParentWidth() * 0.7f)); - const int textLayoutH = textLayout.getHeight(); - const int textBottom = 16 + titleH + textLayoutH; - int h = textBottom; + const int textLayoutH = textLayout.getHeight(); + const int textBottom = 16 + titleH + textLayoutH; + int h = textBottom; - int buttonW = 40; - int i; - for (i = 0; i < buttons.size(); ++i) - buttonW += 16 + ((const TextButton*) buttons[i])->getWidth(); + int buttonW = 40; + int i; + for (i = 0; i < buttons.size(); ++i) + buttonW += 16 + ((const TextButton*) buttons[i])->getWidth(); - w = jmax (buttonW, w); + w = jmax (buttonW, w); - h += (textBoxes.size() + comboBoxes.size() + progressBars.size()) * 50; + h += (textBoxes.size() + comboBoxes.size() + progressBars.size()) * 50; - if (buttons.size() > 0) - h += 20 + ((TextButton*) buttons[0])->getHeight(); + if (buttons.size() > 0) + h += 20 + ((TextButton*) buttons[0])->getHeight(); - for (i = customComps.size(); --i >= 0;) - { - w = jmax (w, ((Component*) customComps[i])->getWidth() + 40); - h += 10 + ((Component*) customComps[i])->getHeight(); - } + for (i = customComps.size(); --i >= 0;) + { + w = jmax (w, ((Component*) customComps[i])->getWidth() + 40); + h += 10 + ((Component*) customComps[i])->getHeight(); + } - for (i = textBlocks.size(); --i >= 0;) - { - const AlertTextComp* const ac = (AlertTextComp*) textBlocks[i]; - w = jmax (w, ac->getPreferredWidth()); - } + for (i = textBlocks.size(); --i >= 0;) + { + const AlertTextComp* const ac = (AlertTextComp*) textBlocks[i]; + w = jmax (w, ac->getPreferredWidth()); + } - w = jmin (w, (int) (getParentWidth() * 0.7f)); + w = jmin (w, (int) (getParentWidth() * 0.7f)); - for (i = textBlocks.size(); --i >= 0;) - { - AlertTextComp* const ac = (AlertTextComp*) textBlocks[i]; - ac->updateLayout ((int) (w * 0.8f)); - h += ac->getHeight() + 10; - } + for (i = textBlocks.size(); --i >= 0;) + { + AlertTextComp* const ac = (AlertTextComp*) textBlocks[i]; + ac->updateLayout ((int) (w * 0.8f)); + h += ac->getHeight() + 10; + } - h = jmin (getParentHeight() - 50, h); + h = jmin (getParentHeight() - 50, h); - if (onlyIncreaseSize) - { - w = jmax (w, getWidth()); - h = jmax (h, getHeight()); - } + if (onlyIncreaseSize) + { + w = jmax (w, getWidth()); + h = jmax (h, getHeight()); + } - if (! isVisible()) - { - centreAroundComponent (associatedComponent, w, h); - } - else - { - const int cx = getX() + getWidth() / 2; - const int cy = getY() + getHeight() / 2; + if (! isVisible()) + { + centreAroundComponent (associatedComponent, w, h); + } + else + { + const int cx = getX() + getWidth() / 2; + const int cy = getY() + getHeight() / 2; - setBounds (cx - w / 2, - cy - h / 2, - w, h); - } + setBounds (cx - w / 2, + cy - h / 2, + w, h); + } - textArea.setBounds (edgeGap, edgeGap, w - (edgeGap * 2), h - edgeGap); + textArea.setBounds (edgeGap, edgeGap, w - (edgeGap * 2), h - edgeGap); - const int spacer = 16; - int totalWidth = -spacer; + const int spacer = 16; + int totalWidth = -spacer; - for (i = buttons.size(); --i >= 0;) - totalWidth += ((TextButton*) buttons[i])->getWidth() + spacer; + for (i = buttons.size(); --i >= 0;) + totalWidth += ((TextButton*) buttons[i])->getWidth() + spacer; - int x = (w - totalWidth) / 2; - int y = (int) (getHeight() * 0.95f); + int x = (w - totalWidth) / 2; + int y = (int) (getHeight() * 0.95f); - for (i = 0; i < buttons.size(); ++i) - { - TextButton* const c = (TextButton*) buttons[i]; - int ny = proportionOfHeight (0.95f) - c->getHeight(); - c->setTopLeftPosition (x, ny); - if (ny < y) - y = ny; + for (i = 0; i < buttons.size(); ++i) + { + TextButton* const c = (TextButton*) buttons[i]; + int ny = proportionOfHeight (0.95f) - c->getHeight(); + c->setTopLeftPosition (x, ny); + if (ny < y) + y = ny; - x += c->getWidth() + spacer; + x += c->getWidth() + spacer; - c->toFront (false); - } + c->toFront (false); + } - y = textBottom; + y = textBottom; - for (i = 0; i < allComps.size(); ++i) - { - Component* const c = (Component*) allComps[i]; + for (i = 0; i < allComps.size(); ++i) + { + Component* const c = (Component*) allComps[i]; - const int h = 22; + const int h = 22; - const int comboIndex = comboBoxes.indexOf (c); - if (comboIndex >= 0 && comboBoxNames [comboIndex].isNotEmpty()) - y += 18; + const int comboIndex = comboBoxes.indexOf (c); + if (comboIndex >= 0 && comboBoxNames [comboIndex].isNotEmpty()) + y += 18; - const int tbIndex = textBoxes.indexOf (c); - if (tbIndex >= 0 && textboxNames[tbIndex].isNotEmpty()) - y += 18; + const int tbIndex = textBoxes.indexOf (c); + if (tbIndex >= 0 && textboxNames[tbIndex].isNotEmpty()) + y += 18; - if (customComps.contains (c) || textBlocks.contains (c)) - { - c->setTopLeftPosition ((getWidth() - c->getWidth()) / 2, y); - y += c->getHeight() + 10; - } - else - { - c->setBounds (proportionOfWidth (0.1f), y, proportionOfWidth (0.8f), h); - y += h + 10; - } - } + if (customComps.contains (c) || textBlocks.contains (c)) + { + c->setTopLeftPosition ((getWidth() - c->getWidth()) / 2, y); + y += c->getHeight() + 10; + } + else + { + c->setBounds (proportionOfWidth (0.1f), y, proportionOfWidth (0.8f), h); + y += h + 10; + } + } - setWantsKeyboardFocus (getNumChildComponents() == 0); + setWantsKeyboardFocus (getNumChildComponents() == 0); } bool AlertWindow::containsAnyExtraComponents() const { - return textBoxes.size() - + comboBoxes.size() - + progressBars.size() - + customComps.size() > 0; + return textBoxes.size() + + comboBoxes.size() + + progressBars.size() + + customComps.size() > 0; } void AlertWindow::mouseDown (const MouseEvent&) { - dragger.startDraggingComponent (this, &constrainer); + dragger.startDraggingComponent (this, &constrainer); } void AlertWindow::mouseDrag (const MouseEvent& e) { - dragger.dragComponent (this, e); + dragger.dragComponent (this, e); } bool AlertWindow::keyPressed (const KeyPress& key) { - for (int i = buttons.size(); --i >= 0;) - { - TextButton* const b = (TextButton*) buttons[i]; + for (int i = buttons.size(); --i >= 0;) + { + TextButton* const b = (TextButton*) buttons[i]; - if (b->isRegisteredForShortcut (key)) - { - b->triggerClick(); - return true; - } - } + if (b->isRegisteredForShortcut (key)) + { + b->triggerClick(); + return true; + } + } - if (key.isKeyCode (KeyPress::escapeKey) && buttons.size() == 0) - { - exitModalState (0); - return true; - } - else if (key.isKeyCode (KeyPress::returnKey) && buttons.size() == 1) - { - ((TextButton*) buttons.getFirst())->triggerClick(); - return true; - } + if (key.isKeyCode (KeyPress::escapeKey) && buttons.size() == 0) + { + exitModalState (0); + return true; + } + else if (key.isKeyCode (KeyPress::returnKey) && buttons.size() == 1) + { + ((TextButton*) buttons.getFirst())->triggerClick(); + return true; + } - return false; + return false; } void AlertWindow::lookAndFeelChanged() { - const int flags = getLookAndFeel().getAlertBoxWindowFlags(); + const int flags = getLookAndFeel().getAlertBoxWindowFlags(); - setUsingNativeTitleBar ((flags & ComponentPeer::windowHasTitleBar) != 0); - setDropShadowEnabled (isOpaque() && (flags & ComponentPeer::windowHasDropShadow) != 0); + setUsingNativeTitleBar ((flags & ComponentPeer::windowHasTitleBar) != 0); + setDropShadowEnabled (isOpaque() && (flags & ComponentPeer::windowHasDropShadow) != 0); } int AlertWindow::getDesktopWindowStyleFlags() const { - return getLookAndFeel().getAlertBoxWindowFlags(); + return getLookAndFeel().getAlertBoxWindowFlags(); } struct AlertWindowInfo { - String title, message, button1, button2, button3; - AlertWindow::AlertIconType iconType; - int numButtons; - Component* associatedComponent; + String title, message, button1, button2, button3; + AlertWindow::AlertIconType iconType; + int numButtons; + Component* associatedComponent; - int run() const - { - return (int) (pointer_sized_int) - MessageManager::getInstance()->callFunctionOnMessageThread (showCallback, (void*) this); - } + int run() const + { + return (int) (pointer_sized_int) + MessageManager::getInstance()->callFunctionOnMessageThread (showCallback, (void*) this); + } private: - int show() const - { - jassert (associatedComponent == 0 || associatedComponent->isValidComponent()); // has your comp been deleted? + int show() const + { + jassert (associatedComponent == 0 || associatedComponent->isValidComponent()); // has your comp been deleted? - LookAndFeel& lf = associatedComponent->isValidComponent() ? associatedComponent->getLookAndFeel() - : LookAndFeel::getDefaultLookAndFeel(); + LookAndFeel& lf = associatedComponent->isValidComponent() ? associatedComponent->getLookAndFeel() + : LookAndFeel::getDefaultLookAndFeel(); - ScopedPointer alertBox (lf.createAlertWindow (title, message, button1, button2, button3, - iconType, numButtons, associatedComponent)); + ScopedPointer alertBox (lf.createAlertWindow (title, message, button1, button2, button3, + iconType, numButtons, associatedComponent)); - jassert (alertBox != 0); // you have to return one of these! + jassert (alertBox != 0); // you have to return one of these! - return alertBox->runModalLoop(); - } + return alertBox->runModalLoop(); + } - static void* showCallback (void* userData) - { - return (void*) (pointer_sized_int) ((const AlertWindowInfo*) userData)->show(); - } + static void* showCallback (void* userData) + { + return (void*) (pointer_sized_int) ((const AlertWindowInfo*) userData)->show(); + } }; void AlertWindow::showMessageBox (AlertIconType iconType, - const String& title, - const String& message, - const String& buttonText, - Component* associatedComponent) + const String& title, + const String& message, + const String& buttonText, + Component* associatedComponent) { - AlertWindowInfo info; - info.title = title; - info.message = message; - info.button1 = buttonText.isEmpty() ? TRANS("ok") : buttonText; - info.iconType = iconType; - info.numButtons = 1; - info.associatedComponent = associatedComponent; + AlertWindowInfo info; + info.title = title; + info.message = message; + info.button1 = buttonText.isEmpty() ? TRANS("ok") : buttonText; + info.iconType = iconType; + info.numButtons = 1; + info.associatedComponent = associatedComponent; - info.run(); + info.run(); } bool AlertWindow::showOkCancelBox (AlertIconType iconType, - const String& title, - const String& message, - const String& button1Text, - const String& button2Text, - Component* associatedComponent) + const String& title, + const String& message, + const String& button1Text, + const String& button2Text, + Component* associatedComponent) { - AlertWindowInfo info; - info.title = title; - info.message = message; - info.button1 = button1Text.isEmpty() ? TRANS("ok") : button1Text; - info.button2 = button2Text.isEmpty() ? TRANS("cancel") : button2Text; - info.iconType = iconType; - info.numButtons = 2; - info.associatedComponent = associatedComponent; + AlertWindowInfo info; + info.title = title; + info.message = message; + info.button1 = button1Text.isEmpty() ? TRANS("ok") : button1Text; + info.button2 = button2Text.isEmpty() ? TRANS("cancel") : button2Text; + info.iconType = iconType; + info.numButtons = 2; + info.associatedComponent = associatedComponent; - return info.run() != 0; + return info.run() != 0; } int AlertWindow::showYesNoCancelBox (AlertIconType iconType, - const String& title, - const String& message, - const String& button1Text, - const String& button2Text, - const String& button3Text, - Component* associatedComponent) + const String& title, + const String& message, + const String& button1Text, + const String& button2Text, + const String& button3Text, + Component* associatedComponent) { - AlertWindowInfo info; - info.title = title; - info.message = message; - info.button1 = button1Text.isEmpty() ? TRANS("yes") : button1Text; - info.button2 = button2Text.isEmpty() ? TRANS("no") : button2Text; - info.button3 = button3Text.isEmpty() ? TRANS("cancel") : button3Text; - info.iconType = iconType; - info.numButtons = 3; - info.associatedComponent = associatedComponent; + AlertWindowInfo info; + info.title = title; + info.message = message; + info.button1 = button1Text.isEmpty() ? TRANS("yes") : button1Text; + info.button2 = button2Text.isEmpty() ? TRANS("no") : button2Text; + info.button3 = button3Text.isEmpty() ? TRANS("cancel") : button3Text; + info.iconType = iconType; + info.numButtons = 3; + info.associatedComponent = associatedComponent; - return info.run(); + return info.run(); } END_JUCE_NAMESPACE @@ -76385,727 +76188,727 @@ extern bool juce_MouseHasMovedSignificantlySincePressed; static const int fakeMouseMoveMessage = 0x7fff00ff; -static VoidArray heavyweightPeers (4); +static VoidArray heavyweightPeers; ComponentPeer::ComponentPeer (Component* const component_, - const int styleFlags_) throw() - : component (component_), - styleFlags (styleFlags_), - lastPaintTime (0), - constrainer (0), - lastFocusedComponent (0), - lastDragAndDropCompUnderMouse (0), - fakeMouseMessageSent (false), - isWindowMinimised (false) + const int styleFlags_) throw() + : component (component_), + styleFlags (styleFlags_), + lastPaintTime (0), + constrainer (0), + lastFocusedComponent (0), + lastDragAndDropCompUnderMouse (0), + fakeMouseMessageSent (false), + isWindowMinimised (false) { - heavyweightPeers.add (this); + heavyweightPeers.add (this); } ComponentPeer::~ComponentPeer() { - heavyweightPeers.removeValue (this); + heavyweightPeers.removeValue (this); - Desktop::getInstance().triggerFocusCallback(); + Desktop::getInstance().triggerFocusCallback(); } int ComponentPeer::getNumPeers() throw() { - return heavyweightPeers.size(); + return heavyweightPeers.size(); } ComponentPeer* ComponentPeer::getPeer (const int index) throw() { - return (ComponentPeer*) heavyweightPeers [index]; + return (ComponentPeer*) heavyweightPeers [index]; } ComponentPeer* ComponentPeer::getPeerFor (const Component* const component) throw() { - for (int i = heavyweightPeers.size(); --i >= 0;) - { - ComponentPeer* const peer = (ComponentPeer*) heavyweightPeers.getUnchecked(i); + for (int i = heavyweightPeers.size(); --i >= 0;) + { + ComponentPeer* const peer = (ComponentPeer*) heavyweightPeers.getUnchecked(i); - if (peer->getComponent() == component) - return peer; - } + if (peer->getComponent() == component) + return peer; + } - return 0; + return 0; } bool ComponentPeer::isValidPeer (const ComponentPeer* const peer) throw() { - return heavyweightPeers.contains (const_cast (peer)); + return heavyweightPeers.contains (const_cast (peer)); } void ComponentPeer::updateCurrentModifiers() throw() { - ModifierKeys::updateCurrentModifiers(); + ModifierKeys::updateCurrentModifiers(); } void ComponentPeer::handleMouseEnter (int x, int y, const int64 time) { - jassert (component->isValidComponent()); - updateCurrentModifiers(); + jassert (component->isValidComponent()); + updateCurrentModifiers(); - Component* c = component->getComponentAt (x, y); - const ComponentDeletionWatcher deletionChecker (component); + Component* c = component->getComponentAt (x, y); + const ComponentDeletionWatcher deletionChecker (component); - if (c != Component::componentUnderMouse && Component::componentUnderMouse != 0) - { - jassert (Component::componentUnderMouse->isValidComponent()); + if (c != Component::componentUnderMouse && Component::componentUnderMouse != 0) + { + jassert (Component::componentUnderMouse->isValidComponent()); - const int oldX = x; - const int oldY = y; - component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); - Component::componentUnderMouse->internalMouseExit (x, y, time); - Component::componentUnderMouse = 0; + const int oldX = x; + const int oldY = y; + component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); + Component::componentUnderMouse->internalMouseExit (x, y, time); + Component::componentUnderMouse = 0; - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - c = component->getComponentAt (oldX, oldY); - } + c = component->getComponentAt (oldX, oldY); + } - Component::componentUnderMouse = c; + Component::componentUnderMouse = c; - if (Component::componentUnderMouse != 0) - { - component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); - Component::componentUnderMouse->internalMouseEnter (x, y, time); - } + if (Component::componentUnderMouse != 0) + { + component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); + Component::componentUnderMouse->internalMouseEnter (x, y, time); + } } void ComponentPeer::handleMouseMove (int x, int y, const int64 time) { - jassert (component->isValidComponent()); - updateCurrentModifiers(); + jassert (component->isValidComponent()); + updateCurrentModifiers(); - fakeMouseMessageSent = false; + fakeMouseMessageSent = false; - const ComponentDeletionWatcher deletionChecker (component); - Component* c = component->getComponentAt (x, y); + const ComponentDeletionWatcher deletionChecker (component); + Component* c = component->getComponentAt (x, y); - if (c != Component::componentUnderMouse) - { - const int oldX = x; - const int oldY = y; + if (c != Component::componentUnderMouse) + { + const int oldX = x; + const int oldY = y; - if (Component::componentUnderMouse != 0) - { - component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); - Component::componentUnderMouse->internalMouseExit (x, y, time); - x = oldX; - y = oldY; + if (Component::componentUnderMouse != 0) + { + component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); + Component::componentUnderMouse->internalMouseExit (x, y, time); + x = oldX; + y = oldY; - Component::componentUnderMouse = 0; + Component::componentUnderMouse = 0; - if (deletionChecker.hasBeenDeleted()) - return; // if this window has just been deleted.. + if (deletionChecker.hasBeenDeleted()) + return; // if this window has just been deleted.. - c = component->getComponentAt (x, y); - } + c = component->getComponentAt (x, y); + } - Component::componentUnderMouse = c; + Component::componentUnderMouse = c; - if (c != 0) - { - component->relativePositionToOtherComponent (c, x, y); - c->internalMouseEnter (x, y, time); - x = oldX; - y = oldY; + if (c != 0) + { + component->relativePositionToOtherComponent (c, x, y); + c->internalMouseEnter (x, y, time); + x = oldX; + y = oldY; - if (deletionChecker.hasBeenDeleted()) - return; // if this window has just been deleted.. - } - } + if (deletionChecker.hasBeenDeleted()) + return; // if this window has just been deleted.. + } + } - if (Component::componentUnderMouse != 0) - { - component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); - Component::componentUnderMouse->internalMouseMove (x, y, time); - } + if (Component::componentUnderMouse != 0) + { + component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); + Component::componentUnderMouse->internalMouseMove (x, y, time); + } } void ComponentPeer::handleMouseDown (int x, int y, const int64 time) { - ++juce_MouseClickCounter; + ++juce_MouseClickCounter; - updateCurrentModifiers(); + updateCurrentModifiers(); - int numMouseButtonsDown = 0; + int numMouseButtonsDown = 0; - if (ModifierKeys::getCurrentModifiers().isLeftButtonDown()) - ++numMouseButtonsDown; + if (ModifierKeys::getCurrentModifiers().isLeftButtonDown()) + ++numMouseButtonsDown; - if (ModifierKeys::getCurrentModifiers().isRightButtonDown()) - ++numMouseButtonsDown; + if (ModifierKeys::getCurrentModifiers().isRightButtonDown()) + ++numMouseButtonsDown; - if (ModifierKeys::getCurrentModifiers().isMiddleButtonDown()) - ++numMouseButtonsDown; + if (ModifierKeys::getCurrentModifiers().isMiddleButtonDown()) + ++numMouseButtonsDown; - if (numMouseButtonsDown == 1) - { - Component::componentUnderMouse = component->getComponentAt (x, y); + if (numMouseButtonsDown == 1) + { + Component::componentUnderMouse = component->getComponentAt (x, y); - if (Component::componentUnderMouse != 0) - { - // can't set these in the mouseDownInt() method, because it's re-entrant, so do it here.. + if (Component::componentUnderMouse != 0) + { + // can't set these in the mouseDownInt() method, because it's re-entrant, so do it here.. - for (int i = numElementsInArray (juce_recentMouseDownTimes); --i > 0;) - { - juce_recentMouseDownTimes [i] = juce_recentMouseDownTimes [i - 1]; - juce_recentMouseDownX [i] = juce_recentMouseDownX [i - 1]; - juce_recentMouseDownY [i] = juce_recentMouseDownY [i - 1]; - juce_recentMouseDownComponent [i] = juce_recentMouseDownComponent [i - 1]; - } + for (int i = numElementsInArray (juce_recentMouseDownTimes); --i > 0;) + { + juce_recentMouseDownTimes [i] = juce_recentMouseDownTimes [i - 1]; + juce_recentMouseDownX [i] = juce_recentMouseDownX [i - 1]; + juce_recentMouseDownY [i] = juce_recentMouseDownY [i - 1]; + juce_recentMouseDownComponent [i] = juce_recentMouseDownComponent [i - 1]; + } - juce_recentMouseDownTimes[0] = time; - juce_recentMouseDownX[0] = x; - juce_recentMouseDownY[0] = y; - juce_recentMouseDownComponent[0] = Component::componentUnderMouse; - relativePositionToGlobal (juce_recentMouseDownX[0], juce_recentMouseDownY[0]); - juce_MouseHasMovedSignificantlySincePressed = false; + juce_recentMouseDownTimes[0] = time; + juce_recentMouseDownX[0] = x; + juce_recentMouseDownY[0] = y; + juce_recentMouseDownComponent[0] = Component::componentUnderMouse; + relativePositionToGlobal (juce_recentMouseDownX[0], juce_recentMouseDownY[0]); + juce_MouseHasMovedSignificantlySincePressed = false; - component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); - Component::componentUnderMouse->internalMouseDown (x, y); - } - } + component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); + Component::componentUnderMouse->internalMouseDown (x, y); + } + } } void ComponentPeer::handleMouseDrag (int x, int y, const int64 time) { - updateCurrentModifiers(); + updateCurrentModifiers(); - if (Component::componentUnderMouse != 0) - { - component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); + if (Component::componentUnderMouse != 0) + { + component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); - Component::componentUnderMouse->internalMouseDrag (x, y, time); - } + Component::componentUnderMouse->internalMouseDrag (x, y, time); + } } void ComponentPeer::handleMouseUp (const int oldModifiers, int x, int y, const int64 time) { - updateCurrentModifiers(); + updateCurrentModifiers(); - int numMouseButtonsDown = 0; + int numMouseButtonsDown = 0; - if ((oldModifiers & ModifierKeys::leftButtonModifier) != 0) - ++numMouseButtonsDown; + if ((oldModifiers & ModifierKeys::leftButtonModifier) != 0) + ++numMouseButtonsDown; - if ((oldModifiers & ModifierKeys::rightButtonModifier) != 0) - ++numMouseButtonsDown; + if ((oldModifiers & ModifierKeys::rightButtonModifier) != 0) + ++numMouseButtonsDown; - if ((oldModifiers & ModifierKeys::middleButtonModifier) != 0) - ++numMouseButtonsDown; + if ((oldModifiers & ModifierKeys::middleButtonModifier) != 0) + ++numMouseButtonsDown; - if (numMouseButtonsDown == 1) - { - const ComponentDeletionWatcher deletionChecker (component); - Component* c = component->getComponentAt (x, y); + if (numMouseButtonsDown == 1) + { + const ComponentDeletionWatcher deletionChecker (component); + Component* c = component->getComponentAt (x, y); - if (c != Component::componentUnderMouse) - { - const int oldX = x; - const int oldY = y; + if (c != Component::componentUnderMouse) + { + const int oldX = x; + const int oldY = y; - if (Component::componentUnderMouse != 0) - { - component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); - Component::componentUnderMouse->internalMouseUp (oldModifiers, x, y, time); - x = oldX; - y = oldY; + if (Component::componentUnderMouse != 0) + { + component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); + Component::componentUnderMouse->internalMouseUp (oldModifiers, x, y, time); + x = oldX; + y = oldY; - if (Component::componentUnderMouse != 0) - Component::componentUnderMouse->internalMouseExit (x, y, time); + if (Component::componentUnderMouse != 0) + Component::componentUnderMouse->internalMouseExit (x, y, time); - if (deletionChecker.hasBeenDeleted()) - return; + if (deletionChecker.hasBeenDeleted()) + return; - c = component->getComponentAt (oldX, oldY); - } + c = component->getComponentAt (oldX, oldY); + } - Component::componentUnderMouse = c; + Component::componentUnderMouse = c; - if (Component::componentUnderMouse != 0) - { - component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); - Component::componentUnderMouse->internalMouseEnter (x, y, time); - } - } - else - { - if (Component::componentUnderMouse != 0) - { - component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); - Component::componentUnderMouse->internalMouseUp (oldModifiers, x, y, time); - } - } - } + if (Component::componentUnderMouse != 0) + { + component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); + Component::componentUnderMouse->internalMouseEnter (x, y, time); + } + } + else + { + if (Component::componentUnderMouse != 0) + { + component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); + Component::componentUnderMouse->internalMouseUp (oldModifiers, x, y, time); + } + } + } } void ComponentPeer::handleMouseExit (int x, int y, const int64 time) { - jassert (component->isValidComponent()); - updateCurrentModifiers(); + jassert (component->isValidComponent()); + updateCurrentModifiers(); - if (Component::componentUnderMouse != 0) - { - component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); + if (Component::componentUnderMouse != 0) + { + component->relativePositionToOtherComponent (Component::componentUnderMouse, x, y); - Component::componentUnderMouse->internalMouseExit (x, y, time); - Component::componentUnderMouse = 0; - } + Component::componentUnderMouse->internalMouseExit (x, y, time); + Component::componentUnderMouse = 0; + } } void ComponentPeer::handleMouseWheel (const int amountX, const int amountY, const int64 time) { - updateCurrentModifiers(); + updateCurrentModifiers(); - if (Component::componentUnderMouse != 0) - Component::componentUnderMouse->internalMouseWheel (amountX, amountY, time); + if (Component::componentUnderMouse != 0) + Component::componentUnderMouse->internalMouseWheel (amountX, amountY, time); } void ComponentPeer::sendFakeMouseMove() throw() { - if ((! fakeMouseMessageSent) - && component->flags.hasHeavyweightPeerFlag - && ! ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown()) - { - if (! isMinimised()) - { - int realX, realY, realW, realH; - getBounds (realX, realY, realW, realH); + if ((! fakeMouseMessageSent) + && component->flags.hasHeavyweightPeerFlag + && ! ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown()) + { + if (! isMinimised()) + { + int realX, realY, realW, realH; + getBounds (realX, realY, realW, realH); - component->bounds_.setBounds (realX, realY, realW, realH); - } + component->bounds_.setBounds (realX, realY, realW, realH); + } - int x, y; - component->getMouseXYRelative (x, y); + int x, y; + component->getMouseXYRelative (x, y); - if (((unsigned int) x) < (unsigned int) component->getWidth() - && ((unsigned int) y) < (unsigned int) component->getHeight() - && contains (x, y, false)) - { - postMessage (new Message (fakeMouseMoveMessage, x, y, 0)); - } + if (((unsigned int) x) < (unsigned int) component->getWidth() + && ((unsigned int) y) < (unsigned int) component->getHeight() + && contains (x, y, false)) + { + postMessage (new Message (fakeMouseMoveMessage, x, y, 0)); + } - fakeMouseMessageSent = true; - } + fakeMouseMessageSent = true; + } } void ComponentPeer::handleMessage (const Message& message) { - if (message.intParameter1 == fakeMouseMoveMessage) - { - if (! ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown()) - handleMouseMove (message.intParameter2, - message.intParameter3, - Time::currentTimeMillis()); - } + if (message.intParameter1 == fakeMouseMoveMessage) + { + if (! ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown()) + handleMouseMove (message.intParameter2, + message.intParameter3, + Time::currentTimeMillis()); + } } void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo) { - Graphics g (&contextToPaintTo); + Graphics g (&contextToPaintTo); #if JUCE_ENABLE_REPAINT_DEBUGGING - g.saveState(); + g.saveState(); #endif - JUCE_TRY - { - component->paintEntireComponent (g); - } - JUCE_CATCH_EXCEPTION + JUCE_TRY + { + component->paintEntireComponent (g); + } + JUCE_CATCH_EXCEPTION #if JUCE_ENABLE_REPAINT_DEBUGGING - // enabling this code will fill all areas that get repainted with a colour overlay, to show - // clearly when things are being repainted. - { - g.restoreState(); + // enabling this code will fill all areas that get repainted with a colour overlay, to show + // clearly when things are being repainted. + { + g.restoreState(); - g.fillAll (Colour ((uint8) Random::getSystemRandom().nextInt (255), - (uint8) Random::getSystemRandom().nextInt (255), - (uint8) Random::getSystemRandom().nextInt (255), - (uint8) 0x50)); - } + g.fillAll (Colour ((uint8) Random::getSystemRandom().nextInt (255), + (uint8) Random::getSystemRandom().nextInt (255), + (uint8) Random::getSystemRandom().nextInt (255), + (uint8) 0x50)); + } #endif } bool ComponentPeer::handleKeyPress (const int keyCode, - const juce_wchar textCharacter) + const juce_wchar textCharacter) { - updateCurrentModifiers(); + updateCurrentModifiers(); - Component* target = Component::currentlyFocusedComponent->isValidComponent() - ? Component::currentlyFocusedComponent - : component; + Component* target = Component::currentlyFocusedComponent->isValidComponent() + ? Component::currentlyFocusedComponent + : component; - if (target->isCurrentlyBlockedByAnotherModalComponent()) - { - Component* const currentModalComp = Component::getCurrentlyModalComponent(); + if (target->isCurrentlyBlockedByAnotherModalComponent()) + { + Component* const currentModalComp = Component::getCurrentlyModalComponent(); - if (currentModalComp != 0) - target = currentModalComp; - } + if (currentModalComp != 0) + target = currentModalComp; + } - const KeyPress keyInfo (keyCode, - ModifierKeys::getCurrentModifiers().getRawFlags() - & ModifierKeys::allKeyboardModifiers, - textCharacter); + const KeyPress keyInfo (keyCode, + ModifierKeys::getCurrentModifiers().getRawFlags() + & ModifierKeys::allKeyboardModifiers, + textCharacter); - bool keyWasUsed = false; + bool keyWasUsed = false; - while (target != 0) - { - const ComponentDeletionWatcher deletionChecker (target); + while (target != 0) + { + const ComponentDeletionWatcher deletionChecker (target); - if (target->keyListeners_ != 0) - { - for (int i = target->keyListeners_->size(); --i >= 0;) - { - keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyPressed (keyInfo, target); + if (target->keyListeners_ != 0) + { + for (int i = target->keyListeners_->size(); --i >= 0;) + { + keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyPressed (keyInfo, target); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) - return keyWasUsed; + if (keyWasUsed || deletionChecker.hasBeenDeleted()) + return keyWasUsed; - i = jmin (i, target->keyListeners_->size()); - } - } + i = jmin (i, target->keyListeners_->size()); + } + } - keyWasUsed = target->keyPressed (keyInfo); + keyWasUsed = target->keyPressed (keyInfo); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) - break; + if (keyWasUsed || deletionChecker.hasBeenDeleted()) + break; - if (keyInfo.isKeyCode (KeyPress::tabKey) && Component::getCurrentlyFocusedComponent() != 0) - { - Component* const currentlyFocused = Component::getCurrentlyFocusedComponent(); - currentlyFocused->moveKeyboardFocusToSibling (! keyInfo.getModifiers().isShiftDown()); - keyWasUsed = (currentlyFocused != Component::getCurrentlyFocusedComponent()); - break; - } + if (keyInfo.isKeyCode (KeyPress::tabKey) && Component::getCurrentlyFocusedComponent() != 0) + { + Component* const currentlyFocused = Component::getCurrentlyFocusedComponent(); + currentlyFocused->moveKeyboardFocusToSibling (! keyInfo.getModifiers().isShiftDown()); + keyWasUsed = (currentlyFocused != Component::getCurrentlyFocusedComponent()); + break; + } - target = target->parentComponent_; - } + target = target->parentComponent_; + } - return keyWasUsed; + return keyWasUsed; } bool ComponentPeer::handleKeyUpOrDown (const bool isKeyDown) { - updateCurrentModifiers(); + updateCurrentModifiers(); - Component* target = Component::currentlyFocusedComponent->isValidComponent() - ? Component::currentlyFocusedComponent - : component; + Component* target = Component::currentlyFocusedComponent->isValidComponent() + ? Component::currentlyFocusedComponent + : component; - if (target->isCurrentlyBlockedByAnotherModalComponent()) - { - Component* const currentModalComp = Component::getCurrentlyModalComponent(); + if (target->isCurrentlyBlockedByAnotherModalComponent()) + { + Component* const currentModalComp = Component::getCurrentlyModalComponent(); - if (currentModalComp != 0) - target = currentModalComp; - } + if (currentModalComp != 0) + target = currentModalComp; + } - bool keyWasUsed = false; + bool keyWasUsed = false; - while (target != 0) - { - const ComponentDeletionWatcher deletionChecker (target); + while (target != 0) + { + const ComponentDeletionWatcher deletionChecker (target); - keyWasUsed = target->keyStateChanged (isKeyDown); + keyWasUsed = target->keyStateChanged (isKeyDown); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) - break; + if (keyWasUsed || deletionChecker.hasBeenDeleted()) + break; - if (target->keyListeners_ != 0) - { - for (int i = target->keyListeners_->size(); --i >= 0;) - { - keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyStateChanged (isKeyDown, target); + if (target->keyListeners_ != 0) + { + for (int i = target->keyListeners_->size(); --i >= 0;) + { + keyWasUsed = ((KeyListener*) target->keyListeners_->getUnchecked(i))->keyStateChanged (isKeyDown, target); - if (keyWasUsed || deletionChecker.hasBeenDeleted()) - return keyWasUsed; + if (keyWasUsed || deletionChecker.hasBeenDeleted()) + return keyWasUsed; - i = jmin (i, target->keyListeners_->size()); - } - } + i = jmin (i, target->keyListeners_->size()); + } + } - target = target->parentComponent_; - } + target = target->parentComponent_; + } - return keyWasUsed; + return keyWasUsed; } void ComponentPeer::handleModifierKeysChange() { - updateCurrentModifiers(); + updateCurrentModifiers(); - Component* target = Component::getComponentUnderMouse(); + Component* target = Component::getComponentUnderMouse(); - if (target == 0) - target = Component::getCurrentlyFocusedComponent(); + if (target == 0) + target = Component::getCurrentlyFocusedComponent(); - if (target == 0) - target = component; + if (target == 0) + target = component; - if (target->isValidComponent()) - target->internalModifierKeysChanged(); + if (target->isValidComponent()) + target->internalModifierKeysChanged(); } void ComponentPeer::handleBroughtToFront() { - updateCurrentModifiers(); + updateCurrentModifiers(); - if (component != 0) - component->internalBroughtToFront(); + if (component != 0) + component->internalBroughtToFront(); } void ComponentPeer::setConstrainer (ComponentBoundsConstrainer* const newConstrainer) throw() { - constrainer = newConstrainer; + constrainer = newConstrainer; } void ComponentPeer::handleMovedOrResized() { - jassert (component->isValidComponent()); - updateCurrentModifiers(); + jassert (component->isValidComponent()); + updateCurrentModifiers(); - const bool nowMinimised = isMinimised(); + const bool nowMinimised = isMinimised(); - if (component->flags.hasHeavyweightPeerFlag && ! nowMinimised) - { - const ComponentDeletionWatcher deletionChecker (component); + if (component->flags.hasHeavyweightPeerFlag && ! nowMinimised) + { + const ComponentDeletionWatcher deletionChecker (component); - int realX, realY, realW, realH; - getBounds (realX, realY, realW, realH); + int realX, realY, realW, realH; + getBounds (realX, realY, realW, realH); - const bool wasMoved = (component->getX() != realX || component->getY() != realY); - const bool wasResized = (component->getWidth() != realW || component->getHeight() != realH); + const bool wasMoved = (component->getX() != realX || component->getY() != realY); + const bool wasResized = (component->getWidth() != realW || component->getHeight() != realH); - if (wasMoved || wasResized) - { - component->bounds_.setBounds (realX, realY, realW, realH); + if (wasMoved || wasResized) + { + component->bounds_.setBounds (realX, realY, realW, realH); - if (wasResized) - component->repaint(); + if (wasResized) + component->repaint(); - component->sendMovedResizedMessages (wasMoved, wasResized); + component->sendMovedResizedMessages (wasMoved, wasResized); - if (deletionChecker.hasBeenDeleted()) - return; - } - } + if (deletionChecker.hasBeenDeleted()) + return; + } + } - if (isWindowMinimised != nowMinimised) - { - isWindowMinimised = nowMinimised; - component->minimisationStateChanged (nowMinimised); - component->sendVisibilityChangeMessage(); - } + if (isWindowMinimised != nowMinimised) + { + isWindowMinimised = nowMinimised; + component->minimisationStateChanged (nowMinimised); + component->sendVisibilityChangeMessage(); + } - if (! isFullScreen()) - lastNonFullscreenBounds = component->getBounds(); + if (! isFullScreen()) + lastNonFullscreenBounds = component->getBounds(); } void ComponentPeer::handleFocusGain() { - updateCurrentModifiers(); + updateCurrentModifiers(); - if (component->isParentOf (lastFocusedComponent)) - { - Component::currentlyFocusedComponent = lastFocusedComponent; - Desktop::getInstance().triggerFocusCallback(); - lastFocusedComponent->internalFocusGain (Component::focusChangedDirectly); - } - else - { - if (! component->isCurrentlyBlockedByAnotherModalComponent()) - component->grabKeyboardFocus(); - else - Component::bringModalComponentToFront(); - } + if (component->isParentOf (lastFocusedComponent)) + { + Component::currentlyFocusedComponent = lastFocusedComponent; + Desktop::getInstance().triggerFocusCallback(); + lastFocusedComponent->internalFocusGain (Component::focusChangedDirectly); + } + else + { + if (! component->isCurrentlyBlockedByAnotherModalComponent()) + component->grabKeyboardFocus(); + else + Component::bringModalComponentToFront(); + } } void ComponentPeer::handleFocusLoss() { - updateCurrentModifiers(); + updateCurrentModifiers(); - if (component->hasKeyboardFocus (true)) - { - lastFocusedComponent = Component::currentlyFocusedComponent; + if (component->hasKeyboardFocus (true)) + { + lastFocusedComponent = Component::currentlyFocusedComponent; - if (lastFocusedComponent != 0) - { - Component::currentlyFocusedComponent = 0; - Desktop::getInstance().triggerFocusCallback(); - lastFocusedComponent->internalFocusLoss (Component::focusChangedByMouseClick); - } - } + if (lastFocusedComponent != 0) + { + Component::currentlyFocusedComponent = 0; + Desktop::getInstance().triggerFocusCallback(); + lastFocusedComponent->internalFocusLoss (Component::focusChangedByMouseClick); + } + } } Component* ComponentPeer::getLastFocusedSubcomponent() const throw() { - return (component->isParentOf (lastFocusedComponent) && lastFocusedComponent->isShowing()) - ? lastFocusedComponent - : component; + return (component->isParentOf (lastFocusedComponent) && lastFocusedComponent->isShowing()) + ? lastFocusedComponent + : component; } void ComponentPeer::handleScreenSizeChange() { - updateCurrentModifiers(); + updateCurrentModifiers(); - component->parentSizeChanged(); - handleMovedOrResized(); + component->parentSizeChanged(); + handleMovedOrResized(); } void ComponentPeer::setNonFullScreenBounds (const Rectangle& newBounds) throw() { - lastNonFullscreenBounds = newBounds; + lastNonFullscreenBounds = newBounds; } const Rectangle& ComponentPeer::getNonFullScreenBounds() const throw() { - return lastNonFullscreenBounds; + return lastNonFullscreenBounds; } static FileDragAndDropTarget* findDragAndDropTarget (Component* c, - const StringArray& files, - FileDragAndDropTarget* const lastOne) + const StringArray& files, + FileDragAndDropTarget* const lastOne) { - while (c != 0) - { - FileDragAndDropTarget* const t = dynamic_cast (c); + while (c != 0) + { + FileDragAndDropTarget* const t = dynamic_cast (c); - if (t != 0 && (t == lastOne || t->isInterestedInFileDrag (files))) - return t; + if (t != 0 && (t == lastOne || t->isInterestedInFileDrag (files))) + return t; - c = c->getParentComponent(); - } + c = c->getParentComponent(); + } - return 0; + return 0; } void ComponentPeer::handleFileDragMove (const StringArray& files, int x, int y) { - updateCurrentModifiers(); + updateCurrentModifiers(); - FileDragAndDropTarget* lastTarget = 0; + FileDragAndDropTarget* lastTarget = 0; - if (dragAndDropTargetComponent != 0 && ! dragAndDropTargetComponent->hasBeenDeleted()) - lastTarget = const_cast (dynamic_cast (dragAndDropTargetComponent->getComponent())); + if (dragAndDropTargetComponent != 0 && ! dragAndDropTargetComponent->hasBeenDeleted()) + lastTarget = const_cast (dynamic_cast (dragAndDropTargetComponent->getComponent())); - FileDragAndDropTarget* newTarget = 0; + FileDragAndDropTarget* newTarget = 0; - Component* const compUnderMouse = component->getComponentAt (x, y); + Component* const compUnderMouse = component->getComponentAt (x, y); - if (compUnderMouse != lastDragAndDropCompUnderMouse) - { - lastDragAndDropCompUnderMouse = compUnderMouse; - newTarget = findDragAndDropTarget (compUnderMouse, files, lastTarget); + if (compUnderMouse != lastDragAndDropCompUnderMouse) + { + lastDragAndDropCompUnderMouse = compUnderMouse; + newTarget = findDragAndDropTarget (compUnderMouse, files, lastTarget); - if (newTarget != lastTarget) - { - if (lastTarget != 0) - lastTarget->fileDragExit (files); + if (newTarget != lastTarget) + { + if (lastTarget != 0) + lastTarget->fileDragExit (files); - dragAndDropTargetComponent = 0; + dragAndDropTargetComponent = 0; - if (newTarget != 0) - { - Component* const targetComp = dynamic_cast (newTarget); - int mx = x, my = y; - component->relativePositionToOtherComponent (targetComp, mx, my); + if (newTarget != 0) + { + Component* const targetComp = dynamic_cast (newTarget); + int mx = x, my = y; + component->relativePositionToOtherComponent (targetComp, mx, my); - dragAndDropTargetComponent = new ComponentDeletionWatcher (dynamic_cast (newTarget)); - newTarget->fileDragEnter (files, mx, my); - } - } - } - else - { - newTarget = lastTarget; - } + dragAndDropTargetComponent = new ComponentDeletionWatcher (dynamic_cast (newTarget)); + newTarget->fileDragEnter (files, mx, my); + } + } + } + else + { + newTarget = lastTarget; + } - if (newTarget != 0) - { - Component* const targetComp = dynamic_cast (newTarget); - component->relativePositionToOtherComponent (targetComp, x, y); + if (newTarget != 0) + { + Component* const targetComp = dynamic_cast (newTarget); + component->relativePositionToOtherComponent (targetComp, x, y); - newTarget->fileDragMove (files, x, y); - } + newTarget->fileDragMove (files, x, y); + } } void ComponentPeer::handleFileDragExit (const StringArray& files) { - handleFileDragMove (files, -1, -1); + handleFileDragMove (files, -1, -1); - jassert (dragAndDropTargetComponent == 0); - lastDragAndDropCompUnderMouse = 0; + jassert (dragAndDropTargetComponent == 0); + lastDragAndDropCompUnderMouse = 0; } void ComponentPeer::handleFileDragDrop (const StringArray& files, int x, int y) { - handleFileDragMove (files, x, y); + handleFileDragMove (files, x, y); - if (dragAndDropTargetComponent != 0 && ! dragAndDropTargetComponent->hasBeenDeleted()) - { - FileDragAndDropTarget* const target = const_cast (dynamic_cast (dragAndDropTargetComponent->getComponent())); + if (dragAndDropTargetComponent != 0 && ! dragAndDropTargetComponent->hasBeenDeleted()) + { + FileDragAndDropTarget* const target = const_cast (dynamic_cast (dragAndDropTargetComponent->getComponent())); - dragAndDropTargetComponent = 0; - lastDragAndDropCompUnderMouse = 0; + dragAndDropTargetComponent = 0; + lastDragAndDropCompUnderMouse = 0; - if (target != 0) - { - Component* const targetComp = dynamic_cast (target); + if (target != 0) + { + Component* const targetComp = dynamic_cast (target); - if (targetComp->isCurrentlyBlockedByAnotherModalComponent()) - { - targetComp->internalModalInputAttempt(); + if (targetComp->isCurrentlyBlockedByAnotherModalComponent()) + { + targetComp->internalModalInputAttempt(); - if (targetComp->isCurrentlyBlockedByAnotherModalComponent()) - return; - } + if (targetComp->isCurrentlyBlockedByAnotherModalComponent()) + return; + } - component->relativePositionToOtherComponent (targetComp, x, y); - target->filesDropped (files, x, y); - } - } + component->relativePositionToOtherComponent (targetComp, x, y); + target->filesDropped (files, x, y); + } + } } void ComponentPeer::handleUserClosingWindow() { - updateCurrentModifiers(); + updateCurrentModifiers(); - component->userTriedToCloseWindow(); + component->userTriedToCloseWindow(); } void ComponentPeer::bringModalComponentToFront() { - Component::bringModalComponentToFront(); + Component::bringModalComponentToFront(); } void ComponentPeer::clearMaskedRegion() throw() { - maskedRegion.clear(); + maskedRegion.clear(); } void ComponentPeer::addMaskedRegion (int x, int y, int w, int h) throw() { - maskedRegion.add (x, y, w, h); + maskedRegion.add (x, y, w, h); } const StringArray ComponentPeer::getAvailableRenderingEngines() throw() { - StringArray s; - s.add ("Software Renderer"); - return s; + StringArray s; + s.add ("Software Renderer"); + return s; } int ComponentPeer::getCurrentRenderingEngine() throw() { - return 0; + return 0; } void ComponentPeer::setCurrentRenderingEngine (int /*index*/) throw() @@ -77120,11 +76923,11 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE DialogWindow::DialogWindow (const String& name, - const Colour& backgroundColour_, - const bool escapeKeyTriggersCloseButton_, - const bool addToDesktop_) - : DocumentWindow (name, backgroundColour_, DocumentWindow::closeButton, addToDesktop_), - escapeKeyTriggersCloseButton (escapeKeyTriggersCloseButton_) + const Colour& backgroundColour_, + const bool escapeKeyTriggersCloseButton_, + const bool addToDesktop_) + : DocumentWindow (name, backgroundColour_, DocumentWindow::closeButton, addToDesktop_), + escapeKeyTriggersCloseButton (escapeKeyTriggersCloseButton_) { } @@ -77134,57 +76937,57 @@ DialogWindow::~DialogWindow() void DialogWindow::resized() { - DocumentWindow::resized(); + DocumentWindow::resized(); - const KeyPress esc (KeyPress::escapeKey, 0, 0); + const KeyPress esc (KeyPress::escapeKey, 0, 0); - if (escapeKeyTriggersCloseButton - && getCloseButton() != 0 - && ! getCloseButton()->isRegisteredForShortcut (esc)) - { - getCloseButton()->addShortcut (esc); - } + if (escapeKeyTriggersCloseButton + && getCloseButton() != 0 + && ! getCloseButton()->isRegisteredForShortcut (esc)) + { + getCloseButton()->addShortcut (esc); + } } class TempDialogWindow : public DialogWindow { public: - TempDialogWindow (const String& title, const Colour& colour, const bool escapeCloses) - : DialogWindow (title, colour, escapeCloses, true) - { - } + TempDialogWindow (const String& title, const Colour& colour, const bool escapeCloses) + : DialogWindow (title, colour, escapeCloses, true) + { + } - ~TempDialogWindow() - { - } + ~TempDialogWindow() + { + } - void closeButtonPressed() - { - setVisible (false); - } + void closeButtonPressed() + { + setVisible (false); + } private: - TempDialogWindow (const TempDialogWindow&); - const TempDialogWindow& operator= (const TempDialogWindow&); + TempDialogWindow (const TempDialogWindow&); + const TempDialogWindow& operator= (const TempDialogWindow&); }; int DialogWindow::showModalDialog (const String& dialogTitle, - Component* contentComponent, - Component* componentToCentreAround, - const Colour& colour, - const bool escapeKeyTriggersCloseButton, - const bool shouldBeResizable, - const bool useBottomRightCornerResizer) + Component* contentComponent, + Component* componentToCentreAround, + const Colour& colour, + const bool escapeKeyTriggersCloseButton, + const bool shouldBeResizable, + const bool useBottomRightCornerResizer) { - TempDialogWindow dw (dialogTitle, colour, escapeKeyTriggersCloseButton); + TempDialogWindow dw (dialogTitle, colour, escapeKeyTriggersCloseButton); - dw.setContentComponent (contentComponent, true, true); - dw.centreAroundComponent (componentToCentreAround, dw.getWidth(), dw.getHeight()); - dw.setResizable (shouldBeResizable, useBottomRightCornerResizer); - const int result = dw.runModalLoop(); - dw.setContentComponent (0, false); - return result; + dw.setContentComponent (contentComponent, true, true); + dw.centreAroundComponent (componentToCentreAround, dw.getWidth(), dw.getHeight()); + dw.setResizable (shouldBeResizable, useBottomRightCornerResizer); + const int result = dw.runModalLoop(); + dw.setContentComponent (0, false); + return result; } END_JUCE_NAMESPACE @@ -77195,330 +76998,330 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE DocumentWindow::DocumentWindow (const String& title, - const Colour& backgroundColour, - const int requiredButtons_, - const bool addToDesktop_) - : ResizableWindow (title, backgroundColour, addToDesktop_), - titleBarHeight (26), - menuBarHeight (24), - requiredButtons (requiredButtons_), + const Colour& backgroundColour, + const int requiredButtons_, + const bool addToDesktop_) + : ResizableWindow (title, backgroundColour, addToDesktop_), + titleBarHeight (26), + menuBarHeight (24), + requiredButtons (requiredButtons_), #if JUCE_MAC - positionTitleBarButtonsOnLeft (true), + positionTitleBarButtonsOnLeft (true), #else - positionTitleBarButtonsOnLeft (false), + positionTitleBarButtonsOnLeft (false), #endif - drawTitleTextCentred (true), - menuBarModel (0) + drawTitleTextCentred (true), + menuBarModel (0) { - setResizeLimits (128, 128, 32768, 32768); + setResizeLimits (128, 128, 32768, 32768); - lookAndFeelChanged(); + lookAndFeelChanged(); } DocumentWindow::~DocumentWindow() { - for (int i = numElementsInArray (titleBarButtons); --i >= 0;) - titleBarButtons[i] = 0; + for (int i = numElementsInArray (titleBarButtons); --i >= 0;) + titleBarButtons[i] = 0; - menuBar = 0; + menuBar = 0; } void DocumentWindow::repaintTitleBar() { - const Rectangle titleBarArea (getTitleBarArea()); - repaint (titleBarArea.getX(), titleBarArea.getY(), - titleBarArea.getWidth(), titleBarArea.getHeight()); + const Rectangle titleBarArea (getTitleBarArea()); + repaint (titleBarArea.getX(), titleBarArea.getY(), + titleBarArea.getWidth(), titleBarArea.getHeight()); } void DocumentWindow::setName (const String& newName) { - if (newName != getName()) - { - Component::setName (newName); - repaintTitleBar(); - } + if (newName != getName()) + { + Component::setName (newName); + repaintTitleBar(); + } } void DocumentWindow::setIcon (const Image* imageToUse) { - titleBarIcon = imageToUse != 0 ? imageToUse->createCopy() : 0; - repaintTitleBar(); + titleBarIcon = imageToUse != 0 ? imageToUse->createCopy() : 0; + repaintTitleBar(); } void DocumentWindow::setTitleBarHeight (const int newHeight) { - titleBarHeight = newHeight; - resized(); - repaintTitleBar(); + titleBarHeight = newHeight; + resized(); + repaintTitleBar(); } void DocumentWindow::setTitleBarButtonsRequired (const int requiredButtons_, - const bool positionTitleBarButtonsOnLeft_) + const bool positionTitleBarButtonsOnLeft_) { - requiredButtons = requiredButtons_; - positionTitleBarButtonsOnLeft = positionTitleBarButtonsOnLeft_; - lookAndFeelChanged(); + requiredButtons = requiredButtons_; + positionTitleBarButtonsOnLeft = positionTitleBarButtonsOnLeft_; + lookAndFeelChanged(); } void DocumentWindow::setTitleBarTextCentred (const bool textShouldBeCentred) { - drawTitleTextCentred = textShouldBeCentred; - repaintTitleBar(); + drawTitleTextCentred = textShouldBeCentred; + repaintTitleBar(); } void DocumentWindow::setMenuBar (MenuBarModel* menuBarModel_, - const int menuBarHeight_) + const int menuBarHeight_) { - if (menuBarModel != menuBarModel_) - { - menuBar = 0; + if (menuBarModel != menuBarModel_) + { + menuBar = 0; - menuBarModel = menuBarModel_; - menuBarHeight = (menuBarHeight_ > 0) ? menuBarHeight_ - : getLookAndFeel().getDefaultMenuBarHeight(); + menuBarModel = menuBarModel_; + menuBarHeight = (menuBarHeight_ > 0) ? menuBarHeight_ + : getLookAndFeel().getDefaultMenuBarHeight(); - if (menuBarModel != 0) - { - // (call the Component method directly to avoid the assertion in ResizableWindow) - Component::addAndMakeVisible (menuBar = new MenuBarComponent (menuBarModel)); - menuBar->setEnabled (isActiveWindow()); - } + if (menuBarModel != 0) + { + // (call the Component method directly to avoid the assertion in ResizableWindow) + Component::addAndMakeVisible (menuBar = new MenuBarComponent (menuBarModel)); + menuBar->setEnabled (isActiveWindow()); + } - resized(); - } + resized(); + } } void DocumentWindow::closeButtonPressed() { - /* If you've got a close button, you have to override this method to get - rid of your window! + /* If you've got a close button, you have to override this method to get + rid of your window! - If the window is just a pop-up, you should override this method and make - it delete the window in whatever way is appropriate for your app. E.g. you - might just want to call "delete this". + If the window is just a pop-up, you should override this method and make + it delete the window in whatever way is appropriate for your app. E.g. you + might just want to call "delete this". - If your app is centred around this window such that the whole app should quit when - the window is closed, then you will probably want to use this method as an opportunity - to call JUCEApplication::quit(), and leave the window to be deleted later by your - JUCEApplication::shutdown() method. (Doing it this way means that your window will - still get cleaned-up if the app is quit by some other means (e.g. a cmd-Q on the mac - or closing it via the taskbar icon on Windows). - */ - jassertfalse + If your app is centred around this window such that the whole app should quit when + the window is closed, then you will probably want to use this method as an opportunity + to call JUCEApplication::quit(), and leave the window to be deleted later by your + JUCEApplication::shutdown() method. (Doing it this way means that your window will + still get cleaned-up if the app is quit by some other means (e.g. a cmd-Q on the mac + or closing it via the taskbar icon on Windows). + */ + jassertfalse } void DocumentWindow::minimiseButtonPressed() { - setMinimised (true); + setMinimised (true); } void DocumentWindow::maximiseButtonPressed() { - setFullScreen (! isFullScreen()); + setFullScreen (! isFullScreen()); } void DocumentWindow::paint (Graphics& g) { - ResizableWindow::paint (g); + ResizableWindow::paint (g); - if (resizableBorder == 0) - { - g.setColour (getBackgroundColour().overlaidWith (Colour (0x80000000))); + if (resizableBorder == 0) + { + g.setColour (getBackgroundColour().overlaidWith (Colour (0x80000000))); - const BorderSize border (getBorderThickness()); + const BorderSize border (getBorderThickness()); - g.fillRect (0, 0, getWidth(), border.getTop()); - g.fillRect (0, border.getTop(), border.getLeft(), getHeight() - border.getTopAndBottom()); - g.fillRect (getWidth() - border.getRight(), border.getTop(), border.getRight(), getHeight() - border.getTopAndBottom()); - g.fillRect (0, getHeight() - border.getBottom(), getWidth(), border.getBottom()); - } + g.fillRect (0, 0, getWidth(), border.getTop()); + g.fillRect (0, border.getTop(), border.getLeft(), getHeight() - border.getTopAndBottom()); + g.fillRect (getWidth() - border.getRight(), border.getTop(), border.getRight(), getHeight() - border.getTopAndBottom()); + g.fillRect (0, getHeight() - border.getBottom(), getWidth(), border.getBottom()); + } - const Rectangle titleBarArea (getTitleBarArea()); - g.setOrigin (titleBarArea.getX(), titleBarArea.getY()); - g.reduceClipRegion (0, 0, titleBarArea.getWidth(), titleBarArea.getHeight()); + const Rectangle titleBarArea (getTitleBarArea()); + g.setOrigin (titleBarArea.getX(), titleBarArea.getY()); + g.reduceClipRegion (0, 0, titleBarArea.getWidth(), titleBarArea.getHeight()); - int titleSpaceX1 = 6; - int titleSpaceX2 = titleBarArea.getWidth() - 6; + int titleSpaceX1 = 6; + int titleSpaceX2 = titleBarArea.getWidth() - 6; - for (int i = 0; i < 3; ++i) - { - if (titleBarButtons[i] != 0) - { - if (positionTitleBarButtonsOnLeft) - titleSpaceX1 = jmax (titleSpaceX1, titleBarButtons[i]->getRight() + (getWidth() - titleBarButtons[i]->getRight()) / 8); - else - titleSpaceX2 = jmin (titleSpaceX2, titleBarButtons[i]->getX() - (titleBarButtons[i]->getX() / 8)); - } - } + for (int i = 0; i < 3; ++i) + { + if (titleBarButtons[i] != 0) + { + if (positionTitleBarButtonsOnLeft) + titleSpaceX1 = jmax (titleSpaceX1, titleBarButtons[i]->getRight() + (getWidth() - titleBarButtons[i]->getRight()) / 8); + else + titleSpaceX2 = jmin (titleSpaceX2, titleBarButtons[i]->getX() - (titleBarButtons[i]->getX() / 8)); + } + } - getLookAndFeel().drawDocumentWindowTitleBar (*this, g, - titleBarArea.getWidth(), - titleBarArea.getHeight(), - titleSpaceX1, - jmax (1, titleSpaceX2 - titleSpaceX1), - titleBarIcon, - ! drawTitleTextCentred); + getLookAndFeel().drawDocumentWindowTitleBar (*this, g, + titleBarArea.getWidth(), + titleBarArea.getHeight(), + titleSpaceX1, + jmax (1, titleSpaceX2 - titleSpaceX1), + titleBarIcon, + ! drawTitleTextCentred); } void DocumentWindow::resized() { - ResizableWindow::resized(); + ResizableWindow::resized(); - if (titleBarButtons[1] != 0) - titleBarButtons[1]->setToggleState (isFullScreen(), false); + if (titleBarButtons[1] != 0) + titleBarButtons[1]->setToggleState (isFullScreen(), false); - const Rectangle titleBarArea (getTitleBarArea()); + const Rectangle titleBarArea (getTitleBarArea()); - getLookAndFeel() - .positionDocumentWindowButtons (*this, - titleBarArea.getX(), titleBarArea.getY(), - titleBarArea.getWidth(), titleBarArea.getHeight(), - titleBarButtons[0], - titleBarButtons[1], - titleBarButtons[2], - positionTitleBarButtonsOnLeft); + getLookAndFeel() + .positionDocumentWindowButtons (*this, + titleBarArea.getX(), titleBarArea.getY(), + titleBarArea.getWidth(), titleBarArea.getHeight(), + titleBarButtons[0], + titleBarButtons[1], + titleBarButtons[2], + positionTitleBarButtonsOnLeft); - if (menuBar != 0) - menuBar->setBounds (titleBarArea.getX(), titleBarArea.getBottom(), - titleBarArea.getWidth(), menuBarHeight); + if (menuBar != 0) + menuBar->setBounds (titleBarArea.getX(), titleBarArea.getBottom(), + titleBarArea.getWidth(), menuBarHeight); } const BorderSize DocumentWindow::getBorderThickness() { - return BorderSize ((isFullScreen() || isUsingNativeTitleBar()) - ? 0 : (resizableBorder != 0 ? 4 : 1)); + return BorderSize ((isFullScreen() || isUsingNativeTitleBar()) + ? 0 : (resizableBorder != 0 ? 4 : 1)); } const BorderSize DocumentWindow::getContentComponentBorder() { - BorderSize border (getBorderThickness()); + BorderSize border (getBorderThickness()); - border.setTop (border.getTop() - + (isUsingNativeTitleBar() ? 0 : titleBarHeight) - + (menuBar != 0 ? menuBarHeight : 0)); + border.setTop (border.getTop() + + (isUsingNativeTitleBar() ? 0 : titleBarHeight) + + (menuBar != 0 ? menuBarHeight : 0)); - return border; + return border; } int DocumentWindow::getTitleBarHeight() const { - return isUsingNativeTitleBar() ? 0 : jmin (titleBarHeight, getHeight() - 4); + return isUsingNativeTitleBar() ? 0 : jmin (titleBarHeight, getHeight() - 4); } const Rectangle DocumentWindow::getTitleBarArea() { - const BorderSize border (getBorderThickness()); + const BorderSize border (getBorderThickness()); - return Rectangle (border.getLeft(), border.getTop(), - getWidth() - border.getLeftAndRight(), - getTitleBarHeight()); + return Rectangle (border.getLeft(), border.getTop(), + getWidth() - border.getLeftAndRight(), + getTitleBarHeight()); } Button* DocumentWindow::getCloseButton() const throw() { - return titleBarButtons[2]; + return titleBarButtons[2]; } Button* DocumentWindow::getMinimiseButton() const throw() { - return titleBarButtons[0]; + return titleBarButtons[0]; } Button* DocumentWindow::getMaximiseButton() const throw() { - return titleBarButtons[1]; + return titleBarButtons[1]; } int DocumentWindow::getDesktopWindowStyleFlags() const { - int flags = ResizableWindow::getDesktopWindowStyleFlags(); + int flags = ResizableWindow::getDesktopWindowStyleFlags(); - if ((requiredButtons & minimiseButton) != 0) - flags |= ComponentPeer::windowHasMinimiseButton; + if ((requiredButtons & minimiseButton) != 0) + flags |= ComponentPeer::windowHasMinimiseButton; - if ((requiredButtons & maximiseButton) != 0) - flags |= ComponentPeer::windowHasMaximiseButton; + if ((requiredButtons & maximiseButton) != 0) + flags |= ComponentPeer::windowHasMaximiseButton; - if ((requiredButtons & closeButton) != 0) - flags |= ComponentPeer::windowHasCloseButton; + if ((requiredButtons & closeButton) != 0) + flags |= ComponentPeer::windowHasCloseButton; - return flags; + return flags; } void DocumentWindow::lookAndFeelChanged() { - int i; - for (i = numElementsInArray (titleBarButtons); --i >= 0;) - titleBarButtons[i] = 0; + int i; + for (i = numElementsInArray (titleBarButtons); --i >= 0;) + titleBarButtons[i] = 0; - if (! isUsingNativeTitleBar()) - { - titleBarButtons[0] = ((requiredButtons & minimiseButton) != 0) - ? getLookAndFeel().createDocumentWindowButton (minimiseButton) : 0; + if (! isUsingNativeTitleBar()) + { + titleBarButtons[0] = ((requiredButtons & minimiseButton) != 0) + ? getLookAndFeel().createDocumentWindowButton (minimiseButton) : 0; - titleBarButtons[1] = ((requiredButtons & maximiseButton) != 0) - ? getLookAndFeel().createDocumentWindowButton (maximiseButton) : 0; + titleBarButtons[1] = ((requiredButtons & maximiseButton) != 0) + ? getLookAndFeel().createDocumentWindowButton (maximiseButton) : 0; - titleBarButtons[2] = ((requiredButtons & closeButton) != 0) - ? getLookAndFeel().createDocumentWindowButton (closeButton) : 0; + titleBarButtons[2] = ((requiredButtons & closeButton) != 0) + ? getLookAndFeel().createDocumentWindowButton (closeButton) : 0; - for (i = 0; i < 3; ++i) - { - if (titleBarButtons[i] != 0) - { - buttonListener.owner = this; - titleBarButtons[i]->addButtonListener (&buttonListener); - titleBarButtons[i]->setWantsKeyboardFocus (false); + for (i = 0; i < 3; ++i) + { + if (titleBarButtons[i] != 0) + { + buttonListener.owner = this; + titleBarButtons[i]->addButtonListener (&buttonListener); + titleBarButtons[i]->setWantsKeyboardFocus (false); - // (call the Component method directly to avoid the assertion in ResizableWindow) - Component::addAndMakeVisible (titleBarButtons[i]); - } - } + // (call the Component method directly to avoid the assertion in ResizableWindow) + Component::addAndMakeVisible (titleBarButtons[i]); + } + } - if (getCloseButton() != 0) - { + if (getCloseButton() != 0) + { #if JUCE_MAC - getCloseButton()->addShortcut (KeyPress (T('w'), ModifierKeys::commandModifier, 0)); + getCloseButton()->addShortcut (KeyPress (T('w'), ModifierKeys::commandModifier, 0)); #else - getCloseButton()->addShortcut (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0)); + getCloseButton()->addShortcut (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0)); #endif - } - } + } + } - activeWindowStatusChanged(); + activeWindowStatusChanged(); - ResizableWindow::lookAndFeelChanged(); + ResizableWindow::lookAndFeelChanged(); } void DocumentWindow::parentHierarchyChanged() { - lookAndFeelChanged(); + lookAndFeelChanged(); } void DocumentWindow::activeWindowStatusChanged() { - ResizableWindow::activeWindowStatusChanged(); + ResizableWindow::activeWindowStatusChanged(); - for (int i = numElementsInArray (titleBarButtons); --i >= 0;) - if (titleBarButtons[i] != 0) - titleBarButtons[i]->setEnabled (isActiveWindow()); + for (int i = numElementsInArray (titleBarButtons); --i >= 0;) + if (titleBarButtons[i] != 0) + titleBarButtons[i]->setEnabled (isActiveWindow()); - if (menuBar != 0) - menuBar->setEnabled (isActiveWindow()); + if (menuBar != 0) + menuBar->setEnabled (isActiveWindow()); } void DocumentWindow::mouseDoubleClick (const MouseEvent& e) { - if (getTitleBarArea().contains (e.x, e.y) - && getMaximiseButton() != 0) - { - getMaximiseButton()->triggerClick(); - } + if (getTitleBarArea().contains (e.x, e.y) + && getMaximiseButton() != 0) + { + getMaximiseButton()->triggerClick(); + } } void DocumentWindow::userTriedToCloseWindow() { - closeButtonPressed(); + closeButtonPressed(); } DocumentWindow::ButtonListenerProxy::ButtonListenerProxy() @@ -77527,18 +77330,18 @@ DocumentWindow::ButtonListenerProxy::ButtonListenerProxy() void DocumentWindow::ButtonListenerProxy::buttonClicked (Button* button) { - if (button == owner->getMinimiseButton()) - { - owner->minimiseButtonPressed(); - } - else if (button == owner->getMaximiseButton()) - { - owner->maximiseButtonPressed(); - } - else if (button == owner->getCloseButton()) - { - owner->closeButtonPressed(); - } + if (button == owner->getMinimiseButton()) + { + owner->minimiseButtonPressed(); + } + else if (button == owner->getMaximiseButton()) + { + owner->maximiseButtonPressed(); + } + else if (button == owner->getCloseButton()) + { + owner->closeButtonPressed(); + } } END_JUCE_NAMESPACE @@ -77549,526 +77352,526 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ResizableWindow::ResizableWindow (const String& name, - const bool addToDesktop_) - : TopLevelWindow (name, addToDesktop_), - resizeToFitContent (false), - fullscreen (false), - lastNonFullScreenPos (50, 50, 256, 256), - constrainer (0) + const bool addToDesktop_) + : TopLevelWindow (name, addToDesktop_), + resizeToFitContent (false), + fullscreen (false), + lastNonFullScreenPos (50, 50, 256, 256), + constrainer (0) #ifdef JUCE_DEBUG - , hasBeenResized (false) + , hasBeenResized (false) #endif { - defaultConstrainer.setMinimumOnscreenAmounts (0x10000, 16, 24, 16); + defaultConstrainer.setMinimumOnscreenAmounts (0x10000, 16, 24, 16); - lastNonFullScreenPos.setBounds (50, 50, 256, 256); + lastNonFullScreenPos.setBounds (50, 50, 256, 256); - if (addToDesktop_) - Component::addToDesktop (getDesktopWindowStyleFlags()); + if (addToDesktop_) + Component::addToDesktop (getDesktopWindowStyleFlags()); } ResizableWindow::ResizableWindow (const String& name, - const Colour& backgroundColour_, - const bool addToDesktop_) - : TopLevelWindow (name, addToDesktop_), - resizeToFitContent (false), - fullscreen (false), - lastNonFullScreenPos (50, 50, 256, 256), - constrainer (0) + const Colour& backgroundColour_, + const bool addToDesktop_) + : TopLevelWindow (name, addToDesktop_), + resizeToFitContent (false), + fullscreen (false), + lastNonFullScreenPos (50, 50, 256, 256), + constrainer (0) #ifdef JUCE_DEBUG - , hasBeenResized (false) + , hasBeenResized (false) #endif { - setBackgroundColour (backgroundColour_); + setBackgroundColour (backgroundColour_); - defaultConstrainer.setMinimumOnscreenAmounts (0x10000, 16, 24, 16); + defaultConstrainer.setMinimumOnscreenAmounts (0x10000, 16, 24, 16); - if (addToDesktop_) - Component::addToDesktop (getDesktopWindowStyleFlags()); + if (addToDesktop_) + Component::addToDesktop (getDesktopWindowStyleFlags()); } ResizableWindow::~ResizableWindow() { - resizableCorner = 0; - resizableBorder = 0; - contentComponent = 0; + resizableCorner = 0; + resizableBorder = 0; + contentComponent = 0; - // have you been adding your own components directly to this window..? tut tut tut. - // Read the instructions for using a ResizableWindow! - jassert (getNumChildComponents() == 0); + // have you been adding your own components directly to this window..? tut tut tut. + // Read the instructions for using a ResizableWindow! + jassert (getNumChildComponents() == 0); } int ResizableWindow::getDesktopWindowStyleFlags() const { - int flags = TopLevelWindow::getDesktopWindowStyleFlags(); + int flags = TopLevelWindow::getDesktopWindowStyleFlags(); - if (isResizable() && (flags & ComponentPeer::windowHasTitleBar) != 0) - flags |= ComponentPeer::windowIsResizable; + if (isResizable() && (flags & ComponentPeer::windowHasTitleBar) != 0) + flags |= ComponentPeer::windowIsResizable; - return flags; + return flags; } void ResizableWindow::setContentComponent (Component* const newContentComponent, - const bool deleteOldOne, - const bool resizeToFit) + const bool deleteOldOne, + const bool resizeToFit) { - resizeToFitContent = resizeToFit; + resizeToFitContent = resizeToFit; - if (newContentComponent != (Component*) contentComponent) - { - if (! deleteOldOne) - removeChildComponent (contentComponent.release()); + if (newContentComponent != (Component*) contentComponent) + { + if (! deleteOldOne) + removeChildComponent (contentComponent.release()); - contentComponent = newContentComponent; + contentComponent = newContentComponent; - Component::addAndMakeVisible (contentComponent); - } + Component::addAndMakeVisible (contentComponent); + } - if (resizeToFit) - childBoundsChanged (contentComponent); + if (resizeToFit) + childBoundsChanged (contentComponent); - resized(); // must always be called to position the new content comp + resized(); // must always be called to position the new content comp } void ResizableWindow::setContentComponentSize (int width, int height) { - jassert (width > 0 && height > 0); // not a great idea to give it a zero size.. + jassert (width > 0 && height > 0); // not a great idea to give it a zero size.. - const BorderSize border (getContentComponentBorder()); + const BorderSize border (getContentComponentBorder()); - setSize (width + border.getLeftAndRight(), - height + border.getTopAndBottom()); + setSize (width + border.getLeftAndRight(), + height + border.getTopAndBottom()); } const BorderSize ResizableWindow::getBorderThickness() { - return BorderSize (isUsingNativeTitleBar() ? 0 : ((resizableBorder != 0 && ! isFullScreen()) ? 5 : 3)); + return BorderSize (isUsingNativeTitleBar() ? 0 : ((resizableBorder != 0 && ! isFullScreen()) ? 5 : 3)); } const BorderSize ResizableWindow::getContentComponentBorder() { - return getBorderThickness(); + return getBorderThickness(); } void ResizableWindow::moved() { - updateLastPos(); + updateLastPos(); } void ResizableWindow::visibilityChanged() { - TopLevelWindow::visibilityChanged(); + TopLevelWindow::visibilityChanged(); - updateLastPos(); + updateLastPos(); } void ResizableWindow::resized() { - if (resizableBorder != 0) - { - resizableBorder->setVisible (! isFullScreen()); - resizableBorder->setBorderThickness (getBorderThickness()); + if (resizableBorder != 0) + { + resizableBorder->setVisible (! isFullScreen()); + resizableBorder->setBorderThickness (getBorderThickness()); - resizableBorder->setSize (getWidth(), getHeight()); - resizableBorder->toBack(); - } + resizableBorder->setSize (getWidth(), getHeight()); + resizableBorder->toBack(); + } - if (resizableCorner != 0) - { - resizableCorner->setVisible (! isFullScreen()); + if (resizableCorner != 0) + { + resizableCorner->setVisible (! isFullScreen()); - const int resizerSize = 18; - resizableCorner->setBounds (getWidth() - resizerSize, - getHeight() - resizerSize, - resizerSize, resizerSize); - } + const int resizerSize = 18; + resizableCorner->setBounds (getWidth() - resizerSize, + getHeight() - resizerSize, + resizerSize, resizerSize); + } - if (contentComponent != 0) - contentComponent->setBoundsInset (getContentComponentBorder()); + if (contentComponent != 0) + contentComponent->setBoundsInset (getContentComponentBorder()); - updateLastPos(); + updateLastPos(); #ifdef JUCE_DEBUG - hasBeenResized = true; + hasBeenResized = true; #endif } void ResizableWindow::childBoundsChanged (Component* child) { - if ((child == contentComponent) && (child != 0) && resizeToFitContent) - { - // not going to look very good if this component has a zero size.. - jassert (child->getWidth() > 0); - jassert (child->getHeight() > 0); + if ((child == contentComponent) && (child != 0) && resizeToFitContent) + { + // not going to look very good if this component has a zero size.. + jassert (child->getWidth() > 0); + jassert (child->getHeight() > 0); - const BorderSize borders (getContentComponentBorder()); + const BorderSize borders (getContentComponentBorder()); - setSize (child->getWidth() + borders.getLeftAndRight(), - child->getHeight() + borders.getTopAndBottom()); - } + setSize (child->getWidth() + borders.getLeftAndRight(), + child->getHeight() + borders.getTopAndBottom()); + } } void ResizableWindow::activeWindowStatusChanged() { - const BorderSize borders (getContentComponentBorder()); + const BorderSize borders (getContentComponentBorder()); - repaint (0, 0, getWidth(), borders.getTop()); - repaint (0, borders.getTop(), borders.getLeft(), getHeight() - borders.getBottom() - borders.getTop()); - repaint (0, getHeight() - borders.getBottom(), getWidth(), borders.getBottom()); - repaint (getWidth() - borders.getRight(), borders.getTop(), borders.getRight(), getHeight() - borders.getBottom() - borders.getTop()); + repaint (0, 0, getWidth(), borders.getTop()); + repaint (0, borders.getTop(), borders.getLeft(), getHeight() - borders.getBottom() - borders.getTop()); + repaint (0, getHeight() - borders.getBottom(), getWidth(), borders.getBottom()); + repaint (getWidth() - borders.getRight(), borders.getTop(), borders.getRight(), getHeight() - borders.getBottom() - borders.getTop()); } void ResizableWindow::setResizable (const bool shouldBeResizable, - const bool useBottomRightCornerResizer) + const bool useBottomRightCornerResizer) { - if (shouldBeResizable) - { - if (useBottomRightCornerResizer) - { - resizableBorder = 0; + if (shouldBeResizable) + { + if (useBottomRightCornerResizer) + { + resizableBorder = 0; - if (resizableCorner == 0) - { - Component::addChildComponent (resizableCorner = new ResizableCornerComponent (this, constrainer)); - resizableCorner->setAlwaysOnTop (true); - } - } - else - { - resizableCorner = 0; + if (resizableCorner == 0) + { + Component::addChildComponent (resizableCorner = new ResizableCornerComponent (this, constrainer)); + resizableCorner->setAlwaysOnTop (true); + } + } + else + { + resizableCorner = 0; - if (resizableBorder == 0) - Component::addChildComponent (resizableBorder = new ResizableBorderComponent (this, constrainer)); - } - } - else - { - resizableCorner = 0; - resizableBorder = 0; - } + if (resizableBorder == 0) + Component::addChildComponent (resizableBorder = new ResizableBorderComponent (this, constrainer)); + } + } + else + { + resizableCorner = 0; + resizableBorder = 0; + } - if (isUsingNativeTitleBar()) - recreateDesktopWindow(); + if (isUsingNativeTitleBar()) + recreateDesktopWindow(); - childBoundsChanged (contentComponent); - resized(); + childBoundsChanged (contentComponent); + resized(); } bool ResizableWindow::isResizable() const throw() { - return resizableCorner != 0 - || resizableBorder != 0; + return resizableCorner != 0 + || resizableBorder != 0; } void ResizableWindow::setResizeLimits (const int newMinimumWidth, - const int newMinimumHeight, - const int newMaximumWidth, - const int newMaximumHeight) throw() + const int newMinimumHeight, + const int newMaximumWidth, + const int newMaximumHeight) throw() { - // if you've set up a custom constrainer then these settings won't have any effect.. - jassert (constrainer == &defaultConstrainer || constrainer == 0); + // if you've set up a custom constrainer then these settings won't have any effect.. + jassert (constrainer == &defaultConstrainer || constrainer == 0); - if (constrainer == 0) - setConstrainer (&defaultConstrainer); + if (constrainer == 0) + setConstrainer (&defaultConstrainer); - defaultConstrainer.setSizeLimits (newMinimumWidth, newMinimumHeight, - newMaximumWidth, newMaximumHeight); + defaultConstrainer.setSizeLimits (newMinimumWidth, newMinimumHeight, + newMaximumWidth, newMaximumHeight); - setBoundsConstrained (getX(), getY(), getWidth(), getHeight()); + setBoundsConstrained (getX(), getY(), getWidth(), getHeight()); } void ResizableWindow::setConstrainer (ComponentBoundsConstrainer* newConstrainer) { - if (constrainer != newConstrainer) - { - constrainer = newConstrainer; + if (constrainer != newConstrainer) + { + constrainer = newConstrainer; - const bool useBottomRightCornerResizer = resizableCorner != 0; - const bool shouldBeResizable = useBottomRightCornerResizer || resizableBorder != 0; + const bool useBottomRightCornerResizer = resizableCorner != 0; + const bool shouldBeResizable = useBottomRightCornerResizer || resizableBorder != 0; - resizableCorner = 0; - resizableBorder = 0; + resizableCorner = 0; + resizableBorder = 0; - setResizable (shouldBeResizable, useBottomRightCornerResizer); + setResizable (shouldBeResizable, useBottomRightCornerResizer); - ComponentPeer* const peer = getPeer(); - if (peer != 0) - peer->setConstrainer (newConstrainer); - } + ComponentPeer* const peer = getPeer(); + if (peer != 0) + peer->setConstrainer (newConstrainer); + } } void ResizableWindow::setBoundsConstrained (int x, int y, int w, int h) { - if (constrainer != 0) - constrainer->setBoundsForComponent (this, x, y, w, h, false, false, false, false); - else - setBounds (x, y, w, h); + if (constrainer != 0) + constrainer->setBoundsForComponent (this, x, y, w, h, false, false, false, false); + else + setBounds (x, y, w, h); } void ResizableWindow::paint (Graphics& g) { - getLookAndFeel().fillResizableWindowBackground (g, getWidth(), getHeight(), - getBorderThickness(), *this); + getLookAndFeel().fillResizableWindowBackground (g, getWidth(), getHeight(), + getBorderThickness(), *this); - if (! isFullScreen()) - { - getLookAndFeel().drawResizableWindowBorder (g, getWidth(), getHeight(), - getBorderThickness(), *this); - } + if (! isFullScreen()) + { + getLookAndFeel().drawResizableWindowBorder (g, getWidth(), getHeight(), + getBorderThickness(), *this); + } #ifdef JUCE_DEBUG - /* If this fails, then you've probably written a subclass with a resized() - callback but forgotten to make it call its parent class's resized() method. + /* If this fails, then you've probably written a subclass with a resized() + callback but forgotten to make it call its parent class's resized() method. - It's important when you override methods like resized(), moved(), - etc., that you make sure the base class methods also get called. + It's important when you override methods like resized(), moved(), + etc., that you make sure the base class methods also get called. - Of course you shouldn't really be overriding ResizableWindow::resized() anyway, - because your content should all be inside the content component - and it's the - content component's resized() method that you should be using to do your - layout. - */ - jassert (hasBeenResized || (getWidth() == 0 && getHeight() == 0)); + Of course you shouldn't really be overriding ResizableWindow::resized() anyway, + because your content should all be inside the content component - and it's the + content component's resized() method that you should be using to do your + layout. + */ + jassert (hasBeenResized || (getWidth() == 0 && getHeight() == 0)); #endif } void ResizableWindow::lookAndFeelChanged() { - resized(); + resized(); - if (isOnDesktop()) - { - Component::addToDesktop (getDesktopWindowStyleFlags()); + if (isOnDesktop()) + { + Component::addToDesktop (getDesktopWindowStyleFlags()); - ComponentPeer* const peer = getPeer(); - if (peer != 0) - peer->setConstrainer (constrainer); - } + ComponentPeer* const peer = getPeer(); + if (peer != 0) + peer->setConstrainer (constrainer); + } } const Colour ResizableWindow::getBackgroundColour() const throw() { - return findColour (backgroundColourId, false); + return findColour (backgroundColourId, false); } void ResizableWindow::setBackgroundColour (const Colour& newColour) { - Colour backgroundColour (newColour); + Colour backgroundColour (newColour); - if (! Desktop::canUseSemiTransparentWindows()) - backgroundColour = newColour.withAlpha (1.0f); + if (! Desktop::canUseSemiTransparentWindows()) + backgroundColour = newColour.withAlpha (1.0f); - setColour (backgroundColourId, backgroundColour); + setColour (backgroundColourId, backgroundColour); - setOpaque (backgroundColour.isOpaque()); - repaint(); + setOpaque (backgroundColour.isOpaque()); + repaint(); } bool ResizableWindow::isFullScreen() const { - if (isOnDesktop()) - { - ComponentPeer* const peer = getPeer(); - return peer != 0 && peer->isFullScreen(); - } + if (isOnDesktop()) + { + ComponentPeer* const peer = getPeer(); + return peer != 0 && peer->isFullScreen(); + } - return fullscreen; + return fullscreen; } void ResizableWindow::setFullScreen (const bool shouldBeFullScreen) { - if (shouldBeFullScreen != isFullScreen()) - { - updateLastPos(); - fullscreen = shouldBeFullScreen; + if (shouldBeFullScreen != isFullScreen()) + { + updateLastPos(); + fullscreen = shouldBeFullScreen; - if (isOnDesktop()) - { - ComponentPeer* const peer = getPeer(); + if (isOnDesktop()) + { + ComponentPeer* const peer = getPeer(); - if (peer != 0) - { - // keep a copy of this intact in case the real one gets messed-up while we're un-maximising - const Rectangle lastPos (lastNonFullScreenPos); + if (peer != 0) + { + // keep a copy of this intact in case the real one gets messed-up while we're un-maximising + const Rectangle lastPos (lastNonFullScreenPos); - peer->setFullScreen (shouldBeFullScreen); + peer->setFullScreen (shouldBeFullScreen); - if (! shouldBeFullScreen) - setBounds (lastPos); - } - else - { - jassertfalse - } - } - else - { - if (shouldBeFullScreen) - setBounds (0, 0, getParentWidth(), getParentHeight()); - else - setBounds (lastNonFullScreenPos); - } + if (! shouldBeFullScreen) + setBounds (lastPos); + } + else + { + jassertfalse + } + } + else + { + if (shouldBeFullScreen) + setBounds (0, 0, getParentWidth(), getParentHeight()); + else + setBounds (lastNonFullScreenPos); + } - resized(); - } + resized(); + } } bool ResizableWindow::isMinimised() const { - ComponentPeer* const peer = getPeer(); + ComponentPeer* const peer = getPeer(); - return (peer != 0) && peer->isMinimised(); + return (peer != 0) && peer->isMinimised(); } void ResizableWindow::setMinimised (const bool shouldMinimise) { - if (shouldMinimise != isMinimised()) - { - ComponentPeer* const peer = getPeer(); + if (shouldMinimise != isMinimised()) + { + ComponentPeer* const peer = getPeer(); - if (peer != 0) - { - updateLastPos(); - peer->setMinimised (shouldMinimise); - } - else - { - jassertfalse - } - } + if (peer != 0) + { + updateLastPos(); + peer->setMinimised (shouldMinimise); + } + else + { + jassertfalse + } + } } void ResizableWindow::updateLastPos() { - if (isShowing() && ! (isFullScreen() || isMinimised())) - { - lastNonFullScreenPos = getBounds(); - } + if (isShowing() && ! (isFullScreen() || isMinimised())) + { + lastNonFullScreenPos = getBounds(); + } } void ResizableWindow::parentSizeChanged() { - if (isFullScreen() && getParentComponent() != 0) - { - setBounds (0, 0, getParentWidth(), getParentHeight()); - } + if (isFullScreen() && getParentComponent() != 0) + { + setBounds (0, 0, getParentWidth(), getParentHeight()); + } } const String ResizableWindow::getWindowStateAsString() { - updateLastPos(); + updateLastPos(); - String s; + String s; - if (isFullScreen()) - s << "fs "; + if (isFullScreen()) + s << "fs "; - s << lastNonFullScreenPos.getX() << T(' ') - << lastNonFullScreenPos.getY() << T(' ') - << lastNonFullScreenPos.getWidth() << T(' ') - << lastNonFullScreenPos.getHeight(); + s << lastNonFullScreenPos.getX() << T(' ') + << lastNonFullScreenPos.getY() << T(' ') + << lastNonFullScreenPos.getWidth() << T(' ') + << lastNonFullScreenPos.getHeight(); - return s; + return s; } bool ResizableWindow::restoreWindowStateFromString (const String& s) { - StringArray tokens; - tokens.addTokens (s, false); - tokens.removeEmptyStrings(); - tokens.trim(); + StringArray tokens; + tokens.addTokens (s, false); + tokens.removeEmptyStrings(); + tokens.trim(); - const bool fs = tokens[0].startsWithIgnoreCase (T("fs")); - const int n = fs ? 1 : 0; + const bool fs = tokens[0].startsWithIgnoreCase (T("fs")); + const int n = fs ? 1 : 0; - if (tokens.size() != 4 + n) - return false; + if (tokens.size() != 4 + n) + return false; - Rectangle r (tokens[n].getIntValue(), - tokens[n + 1].getIntValue(), - tokens[n + 2].getIntValue(), - tokens[n + 3].getIntValue()); + Rectangle r (tokens[n].getIntValue(), + tokens[n + 1].getIntValue(), + tokens[n + 2].getIntValue(), + tokens[n + 3].getIntValue()); - if (r.isEmpty()) - return false; + if (r.isEmpty()) + return false; - const Rectangle screen (Desktop::getInstance().getMonitorAreaContaining (r.getX(), r.getY())); + const Rectangle screen (Desktop::getInstance().getMonitorAreaContaining (r.getX(), r.getY())); - if (! screen.contains (r)) - { - r.setSize (jmin (r.getWidth(), screen.getWidth()), - jmin (r.getHeight(), screen.getHeight())); + if (! screen.contains (r)) + { + r.setSize (jmin (r.getWidth(), screen.getWidth()), + jmin (r.getHeight(), screen.getHeight())); - r.setPosition (jlimit (screen.getX(), screen.getRight() - r.getWidth(), r.getX()), - jlimit (screen.getY(), screen.getBottom() - r.getHeight(), r.getY())); - } + r.setPosition (jlimit (screen.getX(), screen.getRight() - r.getWidth(), r.getX()), + jlimit (screen.getY(), screen.getBottom() - r.getHeight(), r.getY())); + } - lastNonFullScreenPos = r; + lastNonFullScreenPos = r; - if (isOnDesktop()) - { - ComponentPeer* const peer = getPeer(); + if (isOnDesktop()) + { + ComponentPeer* const peer = getPeer(); - if (peer != 0) - peer->setNonFullScreenBounds (r); - } + if (peer != 0) + peer->setNonFullScreenBounds (r); + } - setFullScreen (fs); + setFullScreen (fs); - if (! fs) - setBoundsConstrained (r.getX(), - r.getY(), - r.getWidth(), - r.getHeight()); + if (! fs) + setBoundsConstrained (r.getX(), + r.getY(), + r.getWidth(), + r.getHeight()); - return true; + return true; } void ResizableWindow::mouseDown (const MouseEvent&) { - if (! isFullScreen()) - dragger.startDraggingComponent (this, constrainer); + if (! isFullScreen()) + dragger.startDraggingComponent (this, constrainer); } void ResizableWindow::mouseDrag (const MouseEvent& e) { - if (! isFullScreen()) - dragger.dragComponent (this, e); + if (! isFullScreen()) + dragger.dragComponent (this, e); } #ifdef JUCE_DEBUG void ResizableWindow::addChildComponent (Component* const child, int zOrder) { - /* Agh! You shouldn't add components directly to a ResizableWindow - this class - manages its child components automatically, and if you add your own it'll cause - trouble. Instead, use setContentComponent() to give it a component which - will be automatically resized and kept in the right place - then you can add - subcomponents to the content comp. See the notes for the ResizableWindow class - for more info. + /* Agh! You shouldn't add components directly to a ResizableWindow - this class + manages its child components automatically, and if you add your own it'll cause + trouble. Instead, use setContentComponent() to give it a component which + will be automatically resized and kept in the right place - then you can add + subcomponents to the content comp. See the notes for the ResizableWindow class + for more info. - If you really know what you're doing and want to avoid this assertion, just call - Component::addChildComponent directly. + If you really know what you're doing and want to avoid this assertion, just call + Component::addChildComponent directly. */ - jassertfalse + jassertfalse - Component::addChildComponent (child, zOrder); + Component::addChildComponent (child, zOrder); } void ResizableWindow::addAndMakeVisible (Component* const child, int zOrder) { - /* Agh! You shouldn't add components directly to a ResizableWindow - this class - manages its child components automatically, and if you add your own it'll cause - trouble. Instead, use setContentComponent() to give it a component which - will be automatically resized and kept in the right place - then you can add - subcomponents to the content comp. See the notes for the ResizableWindow class - for more info. + /* Agh! You shouldn't add components directly to a ResizableWindow - this class + manages its child components automatically, and if you add your own it'll cause + trouble. Instead, use setContentComponent() to give it a component which + will be automatically resized and kept in the right place - then you can add + subcomponents to the content comp. See the notes for the ResizableWindow class + for more info. - If you really know what you're doing and want to avoid this assertion, just call - Component::addAndMakeVisible directly. + If you really know what you're doing and want to avoid this assertion, just call + Component::addAndMakeVisible directly. */ - jassertfalse + jassertfalse - Component::addAndMakeVisible (child, zOrder); + Component::addAndMakeVisible (child, zOrder); } #endif @@ -78080,86 +77883,86 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE SplashScreen::SplashScreen() - : backgroundImage (0) + : backgroundImage (0) { - setOpaque (true); + setOpaque (true); } SplashScreen::~SplashScreen() { - ImageCache::releaseOrDelete (backgroundImage); + ImageCache::releaseOrDelete (backgroundImage); } void SplashScreen::show (const String& title, - Image* const backgroundImage_, - const int minimumTimeToDisplayFor, - const bool useDropShadow, - const bool removeOnMouseClick) + Image* const backgroundImage_, + const int minimumTimeToDisplayFor, + const bool useDropShadow, + const bool removeOnMouseClick) { - backgroundImage = backgroundImage_; + backgroundImage = backgroundImage_; - jassert (backgroundImage_ != 0); + jassert (backgroundImage_ != 0); - if (backgroundImage_ != 0) - { - setOpaque (! backgroundImage_->hasAlphaChannel()); + if (backgroundImage_ != 0) + { + setOpaque (! backgroundImage_->hasAlphaChannel()); - show (title, - backgroundImage_->getWidth(), - backgroundImage_->getHeight(), - minimumTimeToDisplayFor, - useDropShadow, - removeOnMouseClick); - } + show (title, + backgroundImage_->getWidth(), + backgroundImage_->getHeight(), + minimumTimeToDisplayFor, + useDropShadow, + removeOnMouseClick); + } } void SplashScreen::show (const String& title, - const int width, - const int height, - const int minimumTimeToDisplayFor, - const bool useDropShadow, - const bool removeOnMouseClick) + const int width, + const int height, + const int minimumTimeToDisplayFor, + const bool useDropShadow, + const bool removeOnMouseClick) { - setName (title); - setAlwaysOnTop (true); - setVisible (true); - centreWithSize (width, height); + setName (title); + setAlwaysOnTop (true); + setVisible (true); + centreWithSize (width, height); - addToDesktop (useDropShadow ? ComponentPeer::windowHasDropShadow : 0); - toFront (false); + addToDesktop (useDropShadow ? ComponentPeer::windowHasDropShadow : 0); + toFront (false); - MessageManager::getInstance()->runDispatchLoopUntil (300); + MessageManager::getInstance()->runDispatchLoopUntil (300); - repaint(); + repaint(); - originalClickCounter = removeOnMouseClick - ? Desktop::getMouseButtonClickCounter() - : INT_MAX; + originalClickCounter = removeOnMouseClick + ? Desktop::getMouseButtonClickCounter() + : INT_MAX; - earliestTimeToDelete = Time::getCurrentTime() + RelativeTime::milliseconds (minimumTimeToDisplayFor); + earliestTimeToDelete = Time::getCurrentTime() + RelativeTime::milliseconds (minimumTimeToDisplayFor); - startTimer (50); + startTimer (50); } void SplashScreen::paint (Graphics& g) { - if (backgroundImage != 0) - { - g.setOpacity (1.0f); + if (backgroundImage != 0) + { + g.setOpacity (1.0f); - g.drawImage (backgroundImage, - 0, 0, getWidth(), getHeight(), - 0, 0, backgroundImage->getWidth(), backgroundImage->getHeight()); - } + g.drawImage (backgroundImage, + 0, 0, getWidth(), getHeight(), + 0, 0, backgroundImage->getWidth(), backgroundImage->getHeight()); + } } void SplashScreen::timerCallback() { - if (Time::getCurrentTime() > earliestTimeToDelete - || Desktop::getMouseButtonClickCounter() > originalClickCounter) - { - delete this; - } + if (Time::getCurrentTime() > earliestTimeToDelete + || Desktop::getMouseButtonClickCounter() > originalClickCounter) + { + delete this; + } } END_JUCE_NAMESPACE @@ -78170,71 +77973,71 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ThreadWithProgressWindow::ThreadWithProgressWindow (const String& title, - const bool hasProgressBar, - const bool hasCancelButton, - const int timeOutMsWhenCancelling_, - const String& cancelButtonText) + const bool hasProgressBar, + const bool hasCancelButton, + const int timeOutMsWhenCancelling_, + const String& cancelButtonText) : Thread ("Juce Progress Window"), - progress (0.0), - timeOutMsWhenCancelling (timeOutMsWhenCancelling_) + progress (0.0), + timeOutMsWhenCancelling (timeOutMsWhenCancelling_) { - alertWindow = LookAndFeel::getDefaultLookAndFeel() - .createAlertWindow (title, String::empty, cancelButtonText, - String::empty, String::empty, - AlertWindow::NoIcon, hasCancelButton ? 1 : 0, 0); + alertWindow = LookAndFeel::getDefaultLookAndFeel() + .createAlertWindow (title, String::empty, cancelButtonText, + String::empty, String::empty, + AlertWindow::NoIcon, hasCancelButton ? 1 : 0, 0); - if (hasProgressBar) - alertWindow->addProgressBarComponent (progress); + if (hasProgressBar) + alertWindow->addProgressBarComponent (progress); } ThreadWithProgressWindow::~ThreadWithProgressWindow() { - stopThread (timeOutMsWhenCancelling); + stopThread (timeOutMsWhenCancelling); } bool ThreadWithProgressWindow::runThread (const int priority) { - startThread (priority); - startTimer (100); + startThread (priority); + startTimer (100); - { - const ScopedLock sl (messageLock); - alertWindow->setMessage (message); - } + { + const ScopedLock sl (messageLock); + alertWindow->setMessage (message); + } - const bool finishedNaturally = alertWindow->runModalLoop() != 0; + const bool finishedNaturally = alertWindow->runModalLoop() != 0; - stopThread (timeOutMsWhenCancelling); + stopThread (timeOutMsWhenCancelling); - alertWindow->setVisible (false); + alertWindow->setVisible (false); - return finishedNaturally; + return finishedNaturally; } void ThreadWithProgressWindow::setProgress (const double newProgress) { - progress = newProgress; + progress = newProgress; } void ThreadWithProgressWindow::setStatusMessage (const String& newStatusMessage) { - const ScopedLock sl (messageLock); - message = newStatusMessage; + const ScopedLock sl (messageLock); + message = newStatusMessage; } void ThreadWithProgressWindow::timerCallback() { - if (! isThreadRunning()) - { - // thread has finished normally.. - alertWindow->exitModalState (1); - alertWindow->setVisible (false); - } - else - { - const ScopedLock sl (messageLock); - alertWindow->setMessage (message); - } + if (! isThreadRunning()) + { + // thread has finished normally.. + alertWindow->exitModalState (1); + alertWindow->setVisible (false); + } + else + { + const ScopedLock sl (messageLock); + alertWindow->setMessage (message); + } } END_JUCE_NAMESPACE @@ -78245,154 +78048,154 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE TooltipWindow::TooltipWindow (Component* const parentComponent, - const int millisecondsBeforeTipAppears_) - : Component ("tooltip"), - millisecondsBeforeTipAppears (millisecondsBeforeTipAppears_), - mouseX (0), - mouseY (0), - lastHideTime (0), - lastComponentUnderMouse (0), - changedCompsSinceShown (true) + const int millisecondsBeforeTipAppears_) + : Component ("tooltip"), + millisecondsBeforeTipAppears (millisecondsBeforeTipAppears_), + mouseX (0), + mouseY (0), + lastHideTime (0), + lastComponentUnderMouse (0), + changedCompsSinceShown (true) { - startTimer (123); + startTimer (123); - setAlwaysOnTop (true); - setOpaque (true); + setAlwaysOnTop (true); + setOpaque (true); - if (parentComponent != 0) - parentComponent->addChildComponent (this); + if (parentComponent != 0) + parentComponent->addChildComponent (this); } TooltipWindow::~TooltipWindow() { - hide(); + hide(); } void TooltipWindow::setMillisecondsBeforeTipAppears (const int newTimeMs) throw() { - millisecondsBeforeTipAppears = newTimeMs; + millisecondsBeforeTipAppears = newTimeMs; } void TooltipWindow::paint (Graphics& g) { - getLookAndFeel().drawTooltip (g, tipShowing, getWidth(), getHeight()); + getLookAndFeel().drawTooltip (g, tipShowing, getWidth(), getHeight()); } void TooltipWindow::mouseEnter (const MouseEvent&) { - hide(); + hide(); } void TooltipWindow::showFor (Component* const c, const String& tip) { - jassert (tip.isNotEmpty()); - tipShowing = tip; + jassert (tip.isNotEmpty()); + tipShowing = tip; - int mx, my; - Desktop::getMousePosition (mx, my); + int mx, my; + Desktop::getMousePosition (mx, my); - if (getParentComponent() != 0) - getParentComponent()->globalPositionToRelative (mx, my); + if (getParentComponent() != 0) + getParentComponent()->globalPositionToRelative (mx, my); - int x, y, w, h; - getLookAndFeel().getTooltipSize (tip, w, h); + int x, y, w, h; + getLookAndFeel().getTooltipSize (tip, w, h); - if (mx > getParentWidth() / 2) - x = mx - (w + 12); - else - x = mx + 24; + if (mx > getParentWidth() / 2) + x = mx - (w + 12); + else + x = mx + 24; - if (my > getParentHeight() / 2) - y = my - (h + 6); - else - y = my + 6; + if (my > getParentHeight() / 2) + y = my - (h + 6); + else + y = my + 6; - setBounds (x, y, w, h); - setVisible (true); + setBounds (x, y, w, h); + setVisible (true); - if (getParentComponent() == 0) - { - addToDesktop (ComponentPeer::windowHasDropShadow - | ComponentPeer::windowIsTemporary - | ComponentPeer::windowIgnoresKeyPresses); - } + if (getParentComponent() == 0) + { + addToDesktop (ComponentPeer::windowHasDropShadow + | ComponentPeer::windowIsTemporary + | ComponentPeer::windowIgnoresKeyPresses); + } - toFront (false); + toFront (false); } const String TooltipWindow::getTipFor (Component* const c) { - if (c->isValidComponent() - && Process::isForegroundProcess() - && ! Component::isMouseButtonDownAnywhere()) - { - TooltipClient* const ttc = dynamic_cast (c); + if (c->isValidComponent() + && Process::isForegroundProcess() + && ! Component::isMouseButtonDownAnywhere()) + { + TooltipClient* const ttc = dynamic_cast (c); - if (ttc != 0 && ! c->isCurrentlyBlockedByAnotherModalComponent()) - return ttc->getTooltip(); - } + if (ttc != 0 && ! c->isCurrentlyBlockedByAnotherModalComponent()) + return ttc->getTooltip(); + } - return String::empty; + return String::empty; } void TooltipWindow::hide() { - tipShowing = String::empty; - removeFromDesktop(); - setVisible (false); + tipShowing = String::empty; + removeFromDesktop(); + setVisible (false); } void TooltipWindow::timerCallback() { - const unsigned int now = Time::getApproximateMillisecondCounter(); - Component* const newComp = Component::getComponentUnderMouse(); - const String newTip (getTipFor (newComp)); + const unsigned int now = Time::getApproximateMillisecondCounter(); + Component* const newComp = Component::getComponentUnderMouse(); + const String newTip (getTipFor (newComp)); - const bool tipChanged = (newTip != lastTipUnderMouse || newComp != lastComponentUnderMouse); - lastComponentUnderMouse = newComp; - lastTipUnderMouse = newTip; + const bool tipChanged = (newTip != lastTipUnderMouse || newComp != lastComponentUnderMouse); + lastComponentUnderMouse = newComp; + lastTipUnderMouse = newTip; - const int clickCount = Desktop::getInstance().getMouseButtonClickCounter(); - const bool mouseWasClicked = clickCount > mouseClicks; - mouseClicks = clickCount; + const int clickCount = Desktop::getInstance().getMouseButtonClickCounter(); + const bool mouseWasClicked = clickCount > mouseClicks; + mouseClicks = clickCount; - int mx, my; - Desktop::getMousePosition (mx, my); - const bool mouseMovedQuickly = (abs (mx - mouseX) + abs (my - mouseY) > 12); - mouseX = mx; - mouseY = my; + int mx, my; + Desktop::getMousePosition (mx, my); + const bool mouseMovedQuickly = (abs (mx - mouseX) + abs (my - mouseY) > 12); + mouseX = mx; + mouseY = my; - if (tipChanged || mouseWasClicked || mouseMovedQuickly) - lastCompChangeTime = now; + if (tipChanged || mouseWasClicked || mouseMovedQuickly) + lastCompChangeTime = now; - if (isVisible() || now < lastHideTime + 500) - { - // if a tip is currently visible (or has just disappeared), update to a new one - // immediately if needed.. - if (newComp == 0 || mouseWasClicked || newTip.isEmpty()) - { - if (isVisible()) - { - lastHideTime = now; - hide(); - } - } - else if (tipChanged) - { - showFor (newComp, newTip); - } - } - else - { - // if there isn't currently a tip, but one is needed, only let it - // appear after a timeout.. - if (newTip.isNotEmpty() - && newTip != tipShowing - && now > lastCompChangeTime + millisecondsBeforeTipAppears) - { - showFor (newComp, newTip); - } - } + if (isVisible() || now < lastHideTime + 500) + { + // if a tip is currently visible (or has just disappeared), update to a new one + // immediately if needed.. + if (newComp == 0 || mouseWasClicked || newTip.isEmpty()) + { + if (isVisible()) + { + lastHideTime = now; + hide(); + } + } + else if (tipChanged) + { + showFor (newComp, newTip); + } + } + else + { + // if there isn't currently a tip, but one is needed, only let it + // appear after a timeout.. + if (newTip.isNotEmpty() + && newTip != tipShowing + && now > lastCompChangeTime + millisecondsBeforeTipAppears) + { + showFor (newComp, newTip); + } + } } END_JUCE_NAMESPACE @@ -78402,150 +78205,147 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -/** Keeps track of the active top level window. -*/ class TopLevelWindowManager : public Timer, - public DeletedAtShutdown + public DeletedAtShutdown { public: - TopLevelWindowManager() - : windows (8), - currentActive (0) - { - } + TopLevelWindowManager() + : currentActive (0) + { + } - ~TopLevelWindowManager() - { - clearSingletonInstance(); - } + ~TopLevelWindowManager() + { + clearSingletonInstance(); + } - juce_DeclareSingleton_SingleThreaded_Minimal (TopLevelWindowManager) + juce_DeclareSingleton_SingleThreaded_Minimal (TopLevelWindowManager) - void timerCallback() - { - startTimer (jmin (1731, getTimerInterval() * 2)); + void timerCallback() + { + startTimer (jmin (1731, getTimerInterval() * 2)); - TopLevelWindow* active = 0; + TopLevelWindow* active = 0; - if (Process::isForegroundProcess()) - { - active = currentActive; + if (Process::isForegroundProcess()) + { + active = currentActive; - Component* const c = Component::getCurrentlyFocusedComponent(); + Component* const c = Component::getCurrentlyFocusedComponent(); - TopLevelWindow* tlw = dynamic_cast (c); + TopLevelWindow* tlw = dynamic_cast (c); - if (tlw == 0 && c != 0) - // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) - tlw = c->findParentComponentOfClass ((TopLevelWindow*) 0); + if (tlw == 0 && c != 0) + // (unable to use the syntax findParentComponentOfClass () because of a VC6 compiler bug) + tlw = c->findParentComponentOfClass ((TopLevelWindow*) 0); - if (tlw != 0) - active = tlw; - } + if (tlw != 0) + active = tlw; + } - if (active != currentActive) - { - currentActive = active; + if (active != currentActive) + { + currentActive = active; - for (int i = windows.size(); --i >= 0;) - { - TopLevelWindow* const tlw = (TopLevelWindow*) windows.getUnchecked (i); - tlw->setWindowActive (isWindowActive (tlw)); + for (int i = windows.size(); --i >= 0;) + { + TopLevelWindow* const tlw = (TopLevelWindow*) windows.getUnchecked (i); + tlw->setWindowActive (isWindowActive (tlw)); - i = jmin (i, windows.size() - 1); - } + i = jmin (i, windows.size() - 1); + } - Desktop::getInstance().triggerFocusCallback(); - } - } + Desktop::getInstance().triggerFocusCallback(); + } + } - bool addWindow (TopLevelWindow* const w) throw() - { - windows.add (w); - startTimer (10); + bool addWindow (TopLevelWindow* const w) throw() + { + windows.add (w); + startTimer (10); - return isWindowActive (w); - } + return isWindowActive (w); + } - void removeWindow (TopLevelWindow* const w) throw() - { - startTimer (10); + void removeWindow (TopLevelWindow* const w) throw() + { + startTimer (10); - if (currentActive == w) - currentActive = 0; + if (currentActive == w) + currentActive = 0; - windows.removeValue (w); + windows.removeValue (w); - if (windows.size() == 0) - deleteInstance(); - } + if (windows.size() == 0) + deleteInstance(); + } - VoidArray windows; + VoidArray windows; private: - TopLevelWindow* currentActive; + TopLevelWindow* currentActive; - bool isWindowActive (TopLevelWindow* const tlw) const throw() - { - return (tlw == currentActive - || tlw->isParentOf (currentActive) - || tlw->hasKeyboardFocus (true)) - && tlw->isShowing(); - } + bool isWindowActive (TopLevelWindow* const tlw) const throw() + { + return (tlw == currentActive + || tlw->isParentOf (currentActive) + || tlw->hasKeyboardFocus (true)) + && tlw->isShowing(); + } - TopLevelWindowManager (const TopLevelWindowManager&); - const TopLevelWindowManager& operator= (const TopLevelWindowManager&); + TopLevelWindowManager (const TopLevelWindowManager&); + const TopLevelWindowManager& operator= (const TopLevelWindowManager&); }; juce_ImplementSingleton_SingleThreaded (TopLevelWindowManager) -void juce_CheckCurrentlyFocusedTopLevelWindow() throw() +void juce_CheckCurrentlyFocusedTopLevelWindow() { - if (TopLevelWindowManager::getInstanceWithoutCreating() != 0) - TopLevelWindowManager::getInstanceWithoutCreating()->startTimer (20); + if (TopLevelWindowManager::getInstanceWithoutCreating() != 0) + TopLevelWindowManager::getInstanceWithoutCreating()->startTimer (20); } TopLevelWindow::TopLevelWindow (const String& name, - const bool addToDesktop_) - : Component (name), - useDropShadow (true), - useNativeTitleBar (false), - windowIsActive_ (false) + const bool addToDesktop_) + : Component (name), + useDropShadow (true), + useNativeTitleBar (false), + windowIsActive_ (false) { - setOpaque (true); + setOpaque (true); - if (addToDesktop_) - Component::addToDesktop (getDesktopWindowStyleFlags()); - else - setDropShadowEnabled (true); + if (addToDesktop_) + Component::addToDesktop (getDesktopWindowStyleFlags()); + else + setDropShadowEnabled (true); - setWantsKeyboardFocus (true); - setBroughtToFrontOnMouseClick (true); - windowIsActive_ = TopLevelWindowManager::getInstance()->addWindow (this); + setWantsKeyboardFocus (true); + setBroughtToFrontOnMouseClick (true); + windowIsActive_ = TopLevelWindowManager::getInstance()->addWindow (this); } TopLevelWindow::~TopLevelWindow() { - shadower = 0; - TopLevelWindowManager::getInstance()->removeWindow (this); + shadower = 0; + TopLevelWindowManager::getInstance()->removeWindow (this); } void TopLevelWindow::focusOfChildComponentChanged (FocusChangeType) { - if (hasKeyboardFocus (true)) - TopLevelWindowManager::getInstance()->timerCallback(); - else - TopLevelWindowManager::getInstance()->startTimer (10); + if (hasKeyboardFocus (true)) + TopLevelWindowManager::getInstance()->timerCallback(); + else + TopLevelWindowManager::getInstance()->startTimer (10); } void TopLevelWindow::setWindowActive (const bool isNowActive) throw() { - if (windowIsActive_ != isNowActive) - { - windowIsActive_ = isNowActive; - activeWindowStatusChanged(); - } + if (windowIsActive_ != isNowActive) + { + windowIsActive_ = isNowActive; + activeWindowStatusChanged(); + } } void TopLevelWindow::activeWindowStatusChanged() @@ -78554,168 +78354,168 @@ void TopLevelWindow::activeWindowStatusChanged() void TopLevelWindow::parentHierarchyChanged() { - setDropShadowEnabled (useDropShadow); + setDropShadowEnabled (useDropShadow); } void TopLevelWindow::visibilityChanged() { - if (isShowing()) - toFront (true); + if (isShowing()) + toFront (true); } int TopLevelWindow::getDesktopWindowStyleFlags() const { - int flags = ComponentPeer::windowAppearsOnTaskbar; + int flags = ComponentPeer::windowAppearsOnTaskbar; - if (useDropShadow) - flags |= ComponentPeer::windowHasDropShadow; + if (useDropShadow) + flags |= ComponentPeer::windowHasDropShadow; - if (useNativeTitleBar) - flags |= ComponentPeer::windowHasTitleBar; + if (useNativeTitleBar) + flags |= ComponentPeer::windowHasTitleBar; - return flags; + return flags; } void TopLevelWindow::setDropShadowEnabled (const bool useShadow) { - useDropShadow = useShadow; + useDropShadow = useShadow; - if (isOnDesktop()) - { - shadower = 0; - Component::addToDesktop (getDesktopWindowStyleFlags()); - } - else - { - if (useShadow && isOpaque()) - { - if (shadower == 0) - { - shadower = getLookAndFeel().createDropShadowerForComponent (this); + if (isOnDesktop()) + { + shadower = 0; + Component::addToDesktop (getDesktopWindowStyleFlags()); + } + else + { + if (useShadow && isOpaque()) + { + if (shadower == 0) + { + shadower = getLookAndFeel().createDropShadowerForComponent (this); - if (shadower != 0) - shadower->setOwner (this); - } - } - else - { - shadower = 0; - } - } + if (shadower != 0) + shadower->setOwner (this); + } + } + else + { + shadower = 0; + } + } } void TopLevelWindow::setUsingNativeTitleBar (const bool useNativeTitleBar_) { - if (useNativeTitleBar != useNativeTitleBar_) - { - useNativeTitleBar = useNativeTitleBar_; - recreateDesktopWindow(); - sendLookAndFeelChange(); - } + if (useNativeTitleBar != useNativeTitleBar_) + { + useNativeTitleBar = useNativeTitleBar_; + recreateDesktopWindow(); + sendLookAndFeelChange(); + } } void TopLevelWindow::recreateDesktopWindow() { - if (isOnDesktop()) - { - Component::addToDesktop (getDesktopWindowStyleFlags()); - toFront (true); - } + if (isOnDesktop()) + { + Component::addToDesktop (getDesktopWindowStyleFlags()); + toFront (true); + } } void TopLevelWindow::addToDesktop (int windowStyleFlags, void* nativeWindowToAttachTo) { - /* It's not recommended to change the desktop window flags directly for a TopLevelWindow, - because this class needs to make sure its layout corresponds with settings like whether - it's got a native title bar or not. + /* It's not recommended to change the desktop window flags directly for a TopLevelWindow, + because this class needs to make sure its layout corresponds with settings like whether + it's got a native title bar or not. - If you need custom flags for your window, you can override the getDesktopWindowStyleFlags() - method. If you do this, it's best to call the base class's getDesktopWindowStyleFlags() - method, then add or remove whatever flags are necessary from this value before returning it. - */ + If you need custom flags for your window, you can override the getDesktopWindowStyleFlags() + method. If you do this, it's best to call the base class's getDesktopWindowStyleFlags() + method, then add or remove whatever flags are necessary from this value before returning it. + */ - jassert ((windowStyleFlags & ~ComponentPeer::windowIsSemiTransparent) - == (getDesktopWindowStyleFlags() & ~ComponentPeer::windowIsSemiTransparent)); + jassert ((windowStyleFlags & ~ComponentPeer::windowIsSemiTransparent) + == (getDesktopWindowStyleFlags() & ~ComponentPeer::windowIsSemiTransparent)); - Component::addToDesktop (windowStyleFlags, nativeWindowToAttachTo); + Component::addToDesktop (windowStyleFlags, nativeWindowToAttachTo); - if (windowStyleFlags != getDesktopWindowStyleFlags()) - sendLookAndFeelChange(); + if (windowStyleFlags != getDesktopWindowStyleFlags()) + sendLookAndFeelChange(); } void TopLevelWindow::centreAroundComponent (Component* c, const int width, const int height) { - if (c == 0) - c = TopLevelWindow::getActiveTopLevelWindow(); + if (c == 0) + c = TopLevelWindow::getActiveTopLevelWindow(); - if (c == 0) - { - centreWithSize (width, height); - } - else - { - int x = (c->getWidth() - width) / 2; - int y = (c->getHeight() - height) / 2; - c->relativePositionToGlobal (x, y); + if (c == 0) + { + centreWithSize (width, height); + } + else + { + int x = (c->getWidth() - width) / 2; + int y = (c->getHeight() - height) / 2; + c->relativePositionToGlobal (x, y); - Rectangle parentArea (c->getParentMonitorArea()); + Rectangle parentArea (c->getParentMonitorArea()); - if (getParentComponent() != 0) - { - getParentComponent()->globalPositionToRelative (x, y); - parentArea.setBounds (0, 0, getParentWidth(), getParentHeight()); - } + if (getParentComponent() != 0) + { + getParentComponent()->globalPositionToRelative (x, y); + parentArea.setBounds (0, 0, getParentWidth(), getParentHeight()); + } - parentArea.reduce (12, 12); + parentArea.reduce (12, 12); - setBounds (jlimit (parentArea.getX(), jmax (parentArea.getX(), parentArea.getRight() - width), x), - jlimit (parentArea.getY(), jmax (parentArea.getY(), parentArea.getBottom() - height), y), - width, height); - } + setBounds (jlimit (parentArea.getX(), jmax (parentArea.getX(), parentArea.getRight() - width), x), + jlimit (parentArea.getY(), jmax (parentArea.getY(), parentArea.getBottom() - height), y), + width, height); + } } int TopLevelWindow::getNumTopLevelWindows() throw() { - return TopLevelWindowManager::getInstance()->windows.size(); + return TopLevelWindowManager::getInstance()->windows.size(); } TopLevelWindow* TopLevelWindow::getTopLevelWindow (const int index) throw() { - return (TopLevelWindow*) TopLevelWindowManager::getInstance()->windows [index]; + return (TopLevelWindow*) TopLevelWindowManager::getInstance()->windows [index]; } TopLevelWindow* TopLevelWindow::getActiveTopLevelWindow() throw() { - TopLevelWindow* best = 0; - int bestNumTWLParents = -1; + TopLevelWindow* best = 0; + int bestNumTWLParents = -1; - for (int i = TopLevelWindow::getNumTopLevelWindows(); --i >= 0;) - { - TopLevelWindow* const tlw = TopLevelWindow::getTopLevelWindow (i); + for (int i = TopLevelWindow::getNumTopLevelWindows(); --i >= 0;) + { + TopLevelWindow* const tlw = TopLevelWindow::getTopLevelWindow (i); - if (tlw->isActiveWindow()) - { - int numTWLParents = 0; + if (tlw->isActiveWindow()) + { + int numTWLParents = 0; - const Component* c = tlw->getParentComponent(); + const Component* c = tlw->getParentComponent(); - while (c != 0) - { - if (dynamic_cast (c) != 0) - ++numTWLParents; + while (c != 0) + { + if (dynamic_cast (c) != 0) + ++numTWLParents; - c = c->getParentComponent(); - } + c = c->getParentComponent(); + } - if (bestNumTWLParents < numTWLParents) - { - best = tlw; - bestNumTWLParents = numTWLParents; - } - } - } + if (bestNumTWLParents < numTWLParents) + { + best = tlw; + bestNumTWLParents = numTWLParents; + } + } + } - return best; + return best; } END_JUCE_NAMESPACE @@ -78725,187 +78525,187 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -static forcedinline uint8 floatAlphaToInt (const float alpha) +static uint8 floatAlphaToInt (const float alpha) { - return (uint8) jlimit (0, 0xff, roundFloatToInt (alpha * 255.0f)); + return (uint8) jlimit (0, 0xff, roundToInt (alpha * 255.0f)); } static const float oneOver255 = 1.0f / 255.0f; Colour::Colour() throw() - : argb (0) + : argb (0) { } Colour::Colour (const Colour& other) throw() - : argb (other.argb) + : argb (other.argb) { } const Colour& Colour::operator= (const Colour& other) throw() { - argb = other.argb; - return *this; + argb = other.argb; + return *this; } bool Colour::operator== (const Colour& other) const throw() { - return argb.getARGB() == other.argb.getARGB(); + return argb.getARGB() == other.argb.getARGB(); } bool Colour::operator!= (const Colour& other) const throw() { - return argb.getARGB() != other.argb.getARGB(); + return argb.getARGB() != other.argb.getARGB(); } Colour::Colour (const uint32 argb_) throw() - : argb (argb_) + : argb (argb_) { } Colour::Colour (const uint8 red, - const uint8 green, - const uint8 blue) throw() + const uint8 green, + const uint8 blue) throw() { - argb.setARGB (0xff, red, green, blue); + argb.setARGB (0xff, red, green, blue); } const Colour Colour::fromRGB (const uint8 red, - const uint8 green, - const uint8 blue) throw() + const uint8 green, + const uint8 blue) throw() { - return Colour (red, green, blue); + return Colour (red, green, blue); } Colour::Colour (const uint8 red, - const uint8 green, - const uint8 blue, - const uint8 alpha) throw() + const uint8 green, + const uint8 blue, + const uint8 alpha) throw() { - argb.setARGB (alpha, red, green, blue); + argb.setARGB (alpha, red, green, blue); } const Colour Colour::fromRGBA (const uint8 red, - const uint8 green, - const uint8 blue, - const uint8 alpha) throw() + const uint8 green, + const uint8 blue, + const uint8 alpha) throw() { - return Colour (red, green, blue, alpha); + return Colour (red, green, blue, alpha); } Colour::Colour (const uint8 red, - const uint8 green, - const uint8 blue, - const float alpha) throw() + const uint8 green, + const uint8 blue, + const float alpha) throw() { - argb.setARGB (floatAlphaToInt (alpha), red, green, blue); + argb.setARGB (floatAlphaToInt (alpha), red, green, blue); } const Colour Colour::fromRGBAFloat (const uint8 red, - const uint8 green, - const uint8 blue, - const float alpha) throw() + const uint8 green, + const uint8 blue, + const float alpha) throw() { - return Colour (red, green, blue, alpha); + return Colour (red, green, blue, alpha); } static void convertHSBtoRGB (float h, float s, float v, - uint8& r, uint8& g, uint8& b) throw() + uint8& r, uint8& g, uint8& b) throw() { - v = jlimit (0.0f, 1.0f, v); - v *= 255.0f; - const uint8 intV = (uint8) roundFloatToInt (v); + v = jlimit (0.0f, 1.0f, v); + v *= 255.0f; + const uint8 intV = (uint8) roundToInt (v); - if (s <= 0) - { - r = intV; - g = intV; - b = intV; - } - else - { - s = jmin (1.0f, s); - h = jlimit (0.0f, 1.0f, h); - h = (h - floorf (h)) * 6.0f + 0.00001f; // need a small adjustment to compensate for rounding errors - const float f = h - floorf (h); + if (s <= 0) + { + r = intV; + g = intV; + b = intV; + } + else + { + s = jmin (1.0f, s); + h = jlimit (0.0f, 1.0f, h); + h = (h - floorf (h)) * 6.0f + 0.00001f; // need a small adjustment to compensate for rounding errors + const float f = h - floorf (h); - const uint8 x = (uint8) roundFloatToInt (v * (1.0f - s)); - const float y = v * (1.0f - s * f); - const float z = v * (1.0f - (s * (1.0f - f))); + const uint8 x = (uint8) roundToInt (v * (1.0f - s)); + const float y = v * (1.0f - s * f); + const float z = v * (1.0f - (s * (1.0f - f))); - if (h < 1.0f) - { - r = intV; - g = (uint8) roundFloatToInt (z); - b = x; - } - else if (h < 2.0f) - { - r = (uint8) roundFloatToInt (y); - g = intV; - b = x; - } - else if (h < 3.0f) - { - r = x; - g = intV; - b = (uint8) roundFloatToInt (z); - } - else if (h < 4.0f) - { - r = x; - g = (uint8) roundFloatToInt (y); - b = intV; - } - else if (h < 5.0f) - { - r = (uint8) roundFloatToInt (z); - g = x; - b = intV; - } - else if (h < 6.0f) - { - r = intV; - g = x; - b = (uint8) roundFloatToInt (y); - } - else - { - r = 0; - g = 0; - b = 0; - } - } + if (h < 1.0f) + { + r = intV; + g = (uint8) roundToInt (z); + b = x; + } + else if (h < 2.0f) + { + r = (uint8) roundToInt (y); + g = intV; + b = x; + } + else if (h < 3.0f) + { + r = x; + g = intV; + b = (uint8) roundToInt (z); + } + else if (h < 4.0f) + { + r = x; + g = (uint8) roundToInt (y); + b = intV; + } + else if (h < 5.0f) + { + r = (uint8) roundToInt (z); + g = x; + b = intV; + } + else if (h < 6.0f) + { + r = intV; + g = x; + b = (uint8) roundToInt (y); + } + else + { + r = 0; + g = 0; + b = 0; + } + } } Colour::Colour (const float hue, - const float saturation, - const float brightness, - const float alpha) throw() + const float saturation, + const float brightness, + const float alpha) throw() { - uint8 r = getRed(), g = getGreen(), b = getBlue(); - convertHSBtoRGB (hue, saturation, brightness, r, g, b); + uint8 r = getRed(), g = getGreen(), b = getBlue(); + convertHSBtoRGB (hue, saturation, brightness, r, g, b); - argb.setARGB (floatAlphaToInt (alpha), r, g, b); + argb.setARGB (floatAlphaToInt (alpha), r, g, b); } const Colour Colour::fromHSV (const float hue, - const float saturation, - const float brightness, - const float alpha) throw() + const float saturation, + const float brightness, + const float alpha) throw() { - return Colour (hue, saturation, brightness, alpha); + return Colour (hue, saturation, brightness, alpha); } Colour::Colour (const float hue, - const float saturation, - const float brightness, - const uint8 alpha) throw() + const float saturation, + const float brightness, + const uint8 alpha) throw() { - uint8 r = getRed(), g = getGreen(), b = getBlue(); - convertHSBtoRGB (hue, saturation, brightness, r, g, b); + uint8 r = getRed(), g = getGreen(), b = getBlue(); + convertHSBtoRGB (hue, saturation, brightness, r, g, b); - argb.setARGB (alpha, r, g, b); + argb.setARGB (alpha, r, g, b); } Colour::~Colour() throw() @@ -78914,306 +78714,306 @@ Colour::~Colour() throw() const PixelARGB Colour::getPixelARGB() const throw() { - PixelARGB p (argb); - p.premultiply(); - return p; + PixelARGB p (argb); + p.premultiply(); + return p; } uint32 Colour::getARGB() const throw() { - return argb.getARGB(); + return argb.getARGB(); } bool Colour::isTransparent() const throw() { - return getAlpha() == 0; + return getAlpha() == 0; } bool Colour::isOpaque() const throw() { - return getAlpha() == 0xff; + return getAlpha() == 0xff; } const Colour Colour::withAlpha (const uint8 newAlpha) const throw() { - PixelARGB newCol (argb); - newCol.setAlpha (newAlpha); - return Colour (newCol.getARGB()); + PixelARGB newCol (argb); + newCol.setAlpha (newAlpha); + return Colour (newCol.getARGB()); } const Colour Colour::withAlpha (const float newAlpha) const throw() { - jassert (newAlpha >= 0 && newAlpha <= 1.0f); + jassert (newAlpha >= 0 && newAlpha <= 1.0f); - PixelARGB newCol (argb); - newCol.setAlpha (floatAlphaToInt (newAlpha)); - return Colour (newCol.getARGB()); + PixelARGB newCol (argb); + newCol.setAlpha (floatAlphaToInt (newAlpha)); + return Colour (newCol.getARGB()); } const Colour Colour::withMultipliedAlpha (const float alphaMultiplier) const throw() { - jassert (alphaMultiplier >= 0); + jassert (alphaMultiplier >= 0); - PixelARGB newCol (argb); - newCol.setAlpha ((uint8) jmin (0xff, roundFloatToInt (alphaMultiplier * newCol.getAlpha()))); - return Colour (newCol.getARGB()); + PixelARGB newCol (argb); + newCol.setAlpha ((uint8) jmin (0xff, roundToInt (alphaMultiplier * newCol.getAlpha()))); + return Colour (newCol.getARGB()); } const Colour Colour::overlaidWith (const Colour& src) const throw() { - const int destAlpha = getAlpha(); + const int destAlpha = getAlpha(); - if (destAlpha > 0) - { - const int invA = 0xff - (int) src.getAlpha(); - const int resA = 0xff - (((0xff - destAlpha) * invA) >> 8); + if (destAlpha > 0) + { + const int invA = 0xff - (int) src.getAlpha(); + const int resA = 0xff - (((0xff - destAlpha) * invA) >> 8); - if (resA > 0) - { - const int da = (invA * destAlpha) / resA; + if (resA > 0) + { + const int da = (invA * destAlpha) / resA; - return Colour ((uint8) (src.getRed() + ((((int) getRed() - src.getRed()) * da) >> 8)), - (uint8) (src.getGreen() + ((((int) getGreen() - src.getGreen()) * da) >> 8)), - (uint8) (src.getBlue() + ((((int) getBlue() - src.getBlue()) * da) >> 8)), - (uint8) resA); - } + return Colour ((uint8) (src.getRed() + ((((int) getRed() - src.getRed()) * da) >> 8)), + (uint8) (src.getGreen() + ((((int) getGreen() - src.getGreen()) * da) >> 8)), + (uint8) (src.getBlue() + ((((int) getBlue() - src.getBlue()) * da) >> 8)), + (uint8) resA); + } - return *this; - } - else - { - return src; - } + return *this; + } + else + { + return src; + } } const Colour Colour::interpolatedWith (const Colour& other, float proportionOfOther) const throw() { - if (proportionOfOther <= 0) - return *this; + if (proportionOfOther <= 0) + return *this; - if (proportionOfOther >= 1.0f) - return other; + if (proportionOfOther >= 1.0f) + return other; - PixelARGB c1 (getPixelARGB()); - const PixelARGB c2 (other.getPixelARGB()); - c1.tween (c2, roundFloatToInt (proportionOfOther * 255.0f)); - c1.unpremultiply(); + PixelARGB c1 (getPixelARGB()); + const PixelARGB c2 (other.getPixelARGB()); + c1.tween (c2, roundToInt (proportionOfOther * 255.0f)); + c1.unpremultiply(); - return Colour (c1.getARGB()); + return Colour (c1.getARGB()); } float Colour::getFloatRed() const throw() { - return getRed() * oneOver255; + return getRed() * oneOver255; } float Colour::getFloatGreen() const throw() { - return getGreen() * oneOver255; + return getGreen() * oneOver255; } float Colour::getFloatBlue() const throw() { - return getBlue() * oneOver255; + return getBlue() * oneOver255; } float Colour::getFloatAlpha() const throw() { - return getAlpha() * oneOver255; + return getAlpha() * oneOver255; } void Colour::getHSB (float& h, float& s, float& v) const throw() { - const int r = getRed(); - const int g = getGreen(); - const int b = getBlue(); + const int r = getRed(); + const int g = getGreen(); + const int b = getBlue(); - const int hi = jmax (r, g, b); - const int lo = jmin (r, g, b); + const int hi = jmax (r, g, b); + const int lo = jmin (r, g, b); - if (hi != 0) - { - s = (hi - lo) / (float) hi; + if (hi != 0) + { + s = (hi - lo) / (float) hi; - if (s != 0) - { - const float invDiff = 1.0f / (hi - lo); + if (s != 0) + { + const float invDiff = 1.0f / (hi - lo); - const float red = (hi - r) * invDiff; - const float green = (hi - g) * invDiff; - const float blue = (hi - b) * invDiff; + const float red = (hi - r) * invDiff; + const float green = (hi - g) * invDiff; + const float blue = (hi - b) * invDiff; - if (r == hi) - h = blue - green; - else if (g == hi) - h = 2.0f + red - blue; - else - h = 4.0f + green - red; + if (r == hi) + h = blue - green; + else if (g == hi) + h = 2.0f + red - blue; + else + h = 4.0f + green - red; - h *= 1.0f / 6.0f; + h *= 1.0f / 6.0f; - if (h < 0) - ++h; - } - else - { - h = 0; - } - } - else - { - s = 0; - h = 0; - } + if (h < 0) + ++h; + } + else + { + h = 0; + } + } + else + { + s = 0; + h = 0; + } - v = hi * oneOver255; + v = hi * oneOver255; } float Colour::getHue() const throw() { - float h, s, b; - getHSB (h, s, b); - return h; + float h, s, b; + getHSB (h, s, b); + return h; } const Colour Colour::withHue (const float hue) const throw() { - float h, s, b; - getHSB (h, s, b); + float h, s, b; + getHSB (h, s, b); - return Colour (hue, s, b, getAlpha()); + return Colour (hue, s, b, getAlpha()); } const Colour Colour::withRotatedHue (const float amountToRotate) const throw() { - float h, s, b; - getHSB (h, s, b); + float h, s, b; + getHSB (h, s, b); - h += amountToRotate; - h -= floorf (h); + h += amountToRotate; + h -= floorf (h); - return Colour (h, s, b, getAlpha()); + return Colour (h, s, b, getAlpha()); } float Colour::getSaturation() const throw() { - float h, s, b; - getHSB (h, s, b); - return s; + float h, s, b; + getHSB (h, s, b); + return s; } const Colour Colour::withSaturation (const float saturation) const throw() { - float h, s, b; - getHSB (h, s, b); + float h, s, b; + getHSB (h, s, b); - return Colour (h, saturation, b, getAlpha()); + return Colour (h, saturation, b, getAlpha()); } const Colour Colour::withMultipliedSaturation (const float amount) const throw() { - float h, s, b; - getHSB (h, s, b); + float h, s, b; + getHSB (h, s, b); - return Colour (h, jmin (1.0f, s * amount), b, getAlpha()); + return Colour (h, jmin (1.0f, s * amount), b, getAlpha()); } float Colour::getBrightness() const throw() { - float h, s, b; - getHSB (h, s, b); - return b; + float h, s, b; + getHSB (h, s, b); + return b; } const Colour Colour::withBrightness (const float brightness) const throw() { - float h, s, b; - getHSB (h, s, b); + float h, s, b; + getHSB (h, s, b); - return Colour (h, s, brightness, getAlpha()); + return Colour (h, s, brightness, getAlpha()); } const Colour Colour::withMultipliedBrightness (const float amount) const throw() { - float h, s, b; - getHSB (h, s, b); + float h, s, b; + getHSB (h, s, b); - b *= amount; + b *= amount; - if (b > 1.0f) - b = 1.0f; + if (b > 1.0f) + b = 1.0f; - return Colour (h, s, b, getAlpha()); + return Colour (h, s, b, getAlpha()); } const Colour Colour::brighter (float amount) const throw() { - amount = 1.0f / (1.0f + amount); + amount = 1.0f / (1.0f + amount); - return Colour ((uint8) (255 - (amount * (255 - getRed()))), - (uint8) (255 - (amount * (255 - getGreen()))), - (uint8) (255 - (amount * (255 - getBlue()))), - getAlpha()); + return Colour ((uint8) (255 - (amount * (255 - getRed()))), + (uint8) (255 - (amount * (255 - getGreen()))), + (uint8) (255 - (amount * (255 - getBlue()))), + getAlpha()); } const Colour Colour::darker (float amount) const throw() { - amount = 1.0f / (1.0f + amount); + amount = 1.0f / (1.0f + amount); - return Colour ((uint8) (amount * getRed()), - (uint8) (amount * getGreen()), - (uint8) (amount * getBlue()), - getAlpha()); + return Colour ((uint8) (amount * getRed()), + (uint8) (amount * getGreen()), + (uint8) (amount * getBlue()), + getAlpha()); } const Colour Colour::greyLevel (const float brightness) throw() { - const uint8 level - = (uint8) jlimit (0x00, 0xff, roundFloatToInt (brightness * 255.0f)); + const uint8 level + = (uint8) jlimit (0x00, 0xff, roundToInt (brightness * 255.0f)); - return Colour (level, level, level); + return Colour (level, level, level); } const Colour Colour::contrasting (const float amount) const throw() { - return overlaidWith ((((int) getRed() + (int) getGreen() + (int) getBlue() >= 3 * 128) - ? Colours::black - : Colours::white).withAlpha (amount)); + return overlaidWith ((((int) getRed() + (int) getGreen() + (int) getBlue() >= 3 * 128) + ? Colours::black + : Colours::white).withAlpha (amount)); } const Colour Colour::contrasting (const Colour& colour1, - const Colour& colour2) throw() + const Colour& colour2) throw() { - const float b1 = colour1.getBrightness(); - const float b2 = colour2.getBrightness(); - float best = 0.0f; - float bestDist = 0.0f; + const float b1 = colour1.getBrightness(); + const float b2 = colour2.getBrightness(); + float best = 0.0f; + float bestDist = 0.0f; - for (float i = 0.0f; i < 1.0f; i += 0.02f) - { - const float d1 = fabsf (i - b1); - const float d2 = fabsf (i - b2); - const float dist = jmin (d1, d2, 1.0f - d1, 1.0f - d2); + for (float i = 0.0f; i < 1.0f; i += 0.02f) + { + const float d1 = fabsf (i - b1); + const float d2 = fabsf (i - b2); + const float dist = jmin (d1, d2, 1.0f - d1, 1.0f - d2); - if (dist > bestDist) - { - best = i; - bestDist = dist; - } - } + if (dist > bestDist) + { + best = i; + bestDist = dist; + } + } - return colour1.overlaidWith (colour2.withMultipliedAlpha (0.5f)) - .withBrightness (best); + return colour1.overlaidWith (colour2.withMultipliedAlpha (0.5f)) + .withBrightness (best); } const String Colour::toString() const throw() { - return String::toHexString ((int) argb.getARGB()); + return String::toHexString ((int) argb.getARGB()); } const Colour Colour::fromString (const String& encodedColourString) { - return Colour ((uint32) encodedColourString.getHexValue32()); + return Colour ((uint32) encodedColourString.getHexValue32()); } END_JUCE_NAMESPACE @@ -79224,32 +79024,30 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ColourGradient::ColourGradient() throw() - : colours (4) { #ifdef JUCE_DEBUG - x1 = 987654.0f; + x1 = 987654.0f; #endif } ColourGradient::ColourGradient (const Colour& colour1, - const float x1_, - const float y1_, - const Colour& colour2, - const float x2_, - const float y2_, - const bool isRadial_) throw() - : x1 (x1_), - y1 (y1_), - x2 (x2_), - y2 (y2_), - isRadial (isRadial_), - colours (4) + const float x1_, + const float y1_, + const Colour& colour2, + const float x2_, + const float y2_, + const bool isRadial_) throw() + : x1 (x1_), + y1 (y1_), + x2 (x2_), + y2 (y2_), + isRadial (isRadial_) { - colours.add (0); - colours.add (colour1.getARGB()); + colours.add (0); + colours.add (colour1.getARGB()); - colours.add (1 << 16); - colours.add (colour2.getARGB()); + colours.add (1 << 16); + colours.add (colour2.getARGB()); } ColourGradient::~ColourGradient() throw() @@ -79258,146 +79056,146 @@ ColourGradient::~ColourGradient() throw() void ColourGradient::clearColours() throw() { - colours.clear(); + colours.clear(); } void ColourGradient::addColour (const double proportionAlongGradient, - const Colour& colour) throw() + const Colour& colour) throw() { - // must be within the two end-points - jassert (proportionAlongGradient >= 0 && proportionAlongGradient <= 1.0); + // must be within the two end-points + jassert (proportionAlongGradient >= 0 && proportionAlongGradient <= 1.0); - const uint32 pos = jlimit (0, 65535, roundDoubleToInt (proportionAlongGradient * 65536.0)); + const uint32 pos = jlimit (0, 65535, roundToInt (proportionAlongGradient * 65536.0)); - int i; - for (i = 0; i < colours.size(); i += 2) - if (colours.getUnchecked(i) > pos) - break; + int i; + for (i = 0; i < colours.size(); i += 2) + if (colours.getUnchecked(i) > pos) + break; - colours.insert (i, pos); - colours.insert (i + 1, colour.getARGB()); + colours.insert (i, pos); + colours.insert (i + 1, colour.getARGB()); } void ColourGradient::multiplyOpacity (const float multiplier) throw() { - for (int i = 1; i < colours.size(); i += 2) - { - const Colour c (colours.getUnchecked(i)); - colours.set (i, c.withMultipliedAlpha (multiplier).getARGB()); - } + for (int i = 1; i < colours.size(); i += 2) + { + const Colour c (colours.getUnchecked(i)); + colours.set (i, c.withMultipliedAlpha (multiplier).getARGB()); + } } int ColourGradient::getNumColours() const throw() { - return colours.size() >> 1; + return colours.size() >> 1; } double ColourGradient::getColourPosition (const int index) const throw() { - return jlimit (0.0, 1.0, colours [index << 1] / 65535.0); + return jlimit (0.0, 1.0, colours [index << 1] / 65535.0); } const Colour ColourGradient::getColour (const int index) const throw() { - return Colour (colours [(index << 1) + 1]); + return Colour (colours [(index << 1) + 1]); } const Colour ColourGradient::getColourAtPosition (const float position) const throw() { - jassert (colours.getUnchecked (0) == 0); // the first colour specified has to go at position 0 + jassert (colours.getUnchecked (0) == 0); // the first colour specified has to go at position 0 - const int integerPos = jlimit (0, 65535, roundFloatToInt (position * 65536.0f)); + const int integerPos = jlimit (0, 65535, roundToInt (position * 65536.0f)); - if (integerPos <= 0 || colours.size() <= 2) - return getColour (0); + if (integerPos <= 0 || colours.size() <= 2) + return getColour (0); - int i = colours.size() - 2; - while (integerPos < (int) colours.getUnchecked(i)) - i -= 2; + int i = colours.size() - 2; + while (integerPos < (int) colours.getUnchecked(i)) + i -= 2; - if (i >= colours.size() - 2) - return Colour (colours.getUnchecked(i)); + if (i >= colours.size() - 2) + return Colour (colours.getUnchecked(i)); - const int pos1 = colours.getUnchecked (i); - const Colour col1 (colours.getUnchecked (i + 1)); + const int pos1 = colours.getUnchecked (i); + const Colour col1 (colours.getUnchecked (i + 1)); - const int pos2 = colours.getUnchecked (i + 2); - const Colour col2 (colours.getUnchecked (i + 3)); + const int pos2 = colours.getUnchecked (i + 2); + const Colour col2 (colours.getUnchecked (i + 3)); - return col1.interpolatedWith (col2, (integerPos - pos1) / (float) (pos2 - pos1)); + return col1.interpolatedWith (col2, (integerPos - pos1) / (float) (pos2 - pos1)); } int ColourGradient::createLookupTable (const AffineTransform& transform, HeapBlock & lookupTable) const throw() { #ifdef JUCE_DEBUG - // trying to use the object without setting its co-ordinates? Have a careful read of - // the comments for the constructors. - jassert (x1 != 987654.0f); + // trying to use the object without setting its co-ordinates? Have a careful read of + // the comments for the constructors. + jassert (x1 != 987654.0f); #endif - const int numColours = colours.size() >> 1; + const int numColours = colours.size() >> 1; - float tx1 = x1, ty1 = y1, tx2 = x2, ty2 = y2; - transform.transformPoint (tx1, ty1); - transform.transformPoint (tx2, ty2); - const double distance = juce_hypot (tx1 - tx2, ty1 - ty2); + float tx1 = x1, ty1 = y1, tx2 = x2, ty2 = y2; + transform.transformPoint (tx1, ty1); + transform.transformPoint (tx2, ty2); + const double distance = juce_hypot (tx1 - tx2, ty1 - ty2); - const int numEntries = jlimit (1, (numColours - 1) << 8, 3 * (int) distance); - lookupTable.malloc (numEntries); + const int numEntries = jlimit (1, (numColours - 1) << 8, 3 * (int) distance); + lookupTable.malloc (numEntries); - if (numColours >= 2) - { - jassert (colours.getUnchecked (0) == 0); // the first colour specified has to go at position 0 + if (numColours >= 2) + { + jassert (colours.getUnchecked (0) == 0); // the first colour specified has to go at position 0 - PixelARGB pix1 (colours.getUnchecked (1)); - pix1.premultiply(); - int index = 0; + PixelARGB pix1 (colours.getUnchecked (1)); + pix1.premultiply(); + int index = 0; - for (int j = 2; j < colours.size(); j += 2) - { - const int numToDo = ((colours.getUnchecked (j) * (numEntries - 1)) >> 16) - index; - PixelARGB pix2 (colours.getUnchecked (j + 1)); - pix2.premultiply(); + for (int j = 2; j < colours.size(); j += 2) + { + const int numToDo = ((colours.getUnchecked (j) * (numEntries - 1)) >> 16) - index; + PixelARGB pix2 (colours.getUnchecked (j + 1)); + pix2.premultiply(); - for (int i = 0; i < numToDo; ++i) - { - jassert (index >= 0 && index < numEntries); + for (int i = 0; i < numToDo; ++i) + { + jassert (index >= 0 && index < numEntries); - lookupTable[index] = pix1; - lookupTable[index].tween (pix2, (i << 8) / numToDo); - ++index; - } + lookupTable[index] = pix1; + lookupTable[index].tween (pix2, (i << 8) / numToDo); + ++index; + } - pix1 = pix2; - } + pix1 = pix2; + } - while (index < numEntries) - lookupTable [index++] = pix1; - } - else - { - jassertfalse // no colours specified! - } + while (index < numEntries) + lookupTable [index++] = pix1; + } + else + { + jassertfalse // no colours specified! + } - return numEntries; + return numEntries; } bool ColourGradient::isOpaque() const throw() { - for (int i = 1; i < colours.size(); i += 2) - if (PixelARGB (colours.getUnchecked(i)).getAlpha() < 0xff) - return false; + for (int i = 1; i < colours.size(); i += 2) + if (PixelARGB (colours.getUnchecked(i)).getAlpha() < 0xff) + return false; - return true; + return true; } bool ColourGradient::isInvisible() const throw() { - for (int i = 1; i < colours.size(); i += 2) - if (PixelARGB (colours.getUnchecked(i)).getAlpha() > 0) - return false; + for (int i = 1; i < colours.size(); i += 2) + if (PixelARGB (colours.getUnchecked(i)).getAlpha() > 0) + return false; - return true; + return true; } END_JUCE_NAMESPACE @@ -79549,158 +79347,158 @@ const Colour Colours::yellow (0xffffff00); const Colour Colours::yellowgreen (0xff9acd32); const Colour Colours::findColourForName (const String& colourName, - const Colour& defaultColour) + const Colour& defaultColour) { - static const int presets[] = - { - // (first value is the string's hashcode, second is ARGB) + static const int presets[] = + { + // (first value is the string's hashcode, second is ARGB) - 0x05978fff, 0xff000000, /* black */ - 0x06bdcc29, 0xffffffff, /* white */ - 0x002e305a, 0xff0000ff, /* blue */ - 0x00308adf, 0xff808080, /* grey */ - 0x05e0cf03, 0xff008000, /* green */ - 0x0001b891, 0xffff0000, /* red */ - 0xd43c6474, 0xffffff00, /* yellow */ - 0x620886da, 0xfff0f8ff, /* aliceblue */ - 0x20a2676a, 0xfffaebd7, /* antiquewhite */ - 0x002dcebc, 0xff00ffff, /* aqua */ - 0x46bb5f7e, 0xff7fffd4, /* aquamarine */ - 0x0590228f, 0xfff0ffff, /* azure */ - 0x05947fe4, 0xfff5f5dc, /* beige */ - 0xad388e35, 0xffffe4c4, /* bisque */ - 0x00674f7e, 0xffffebcd, /* blanchedalmond */ - 0x39129959, 0xff8a2be2, /* blueviolet */ - 0x059a8136, 0xffa52a2a, /* brown */ - 0x89cea8f9, 0xffdeb887, /* burlywood */ - 0x0fa260cf, 0xff5f9ea0, /* cadetblue */ - 0x6b748956, 0xff7fff00, /* chartreuse */ - 0x2903623c, 0xffd2691e, /* chocolate */ - 0x05a74431, 0xffff7f50, /* coral */ - 0x618d42dd, 0xff6495ed, /* cornflowerblue */ - 0xe4b479fd, 0xfffff8dc, /* cornsilk */ - 0x3d8c4edf, 0xffdc143c, /* crimson */ - 0x002ed323, 0xff00ffff, /* cyan */ - 0x67cc74d0, 0xff00008b, /* darkblue */ - 0x67cd1799, 0xff008b8b, /* darkcyan */ - 0x31bbd168, 0xffb8860b, /* darkgoldenrod */ - 0x67cecf55, 0xff555555, /* darkgrey */ - 0x920b194d, 0xff006400, /* darkgreen */ - 0x923edd4c, 0xffbdb76b, /* darkkhaki */ - 0x5c293873, 0xff8b008b, /* darkmagenta */ - 0x6b6671fe, 0xff556b2f, /* darkolivegreen */ - 0xbcfd2524, 0xffff8c00, /* darkorange */ - 0xbcfdf799, 0xff9932cc, /* darkorchid */ - 0x55ee0d5b, 0xff8b0000, /* darkred */ - 0xc2e5f564, 0xffe9967a, /* darksalmon */ - 0x61be858a, 0xff8fbc8f, /* darkseagreen */ - 0xc2b0f2bd, 0xff483d8b, /* darkslateblue */ - 0xc2b34d42, 0xff2f4f4f, /* darkslategrey */ - 0x7cf2b06b, 0xff00ced1, /* darkturquoise */ - 0xc8769375, 0xff9400d3, /* darkviolet */ - 0x25832862, 0xffff1493, /* deeppink */ - 0xfcad568f, 0xff00bfff, /* deepskyblue */ - 0x634c8b67, 0xff696969, /* dimgrey */ - 0x45c1ce55, 0xff1e90ff, /* dodgerblue */ - 0xef19e3cb, 0xffb22222, /* firebrick */ - 0xb852b195, 0xfffffaf0, /* floralwhite */ - 0xd086fd06, 0xff228b22, /* forestgreen */ - 0xe106b6d7, 0xffff00ff, /* fuchsia */ - 0x7880d61e, 0xffdcdcdc, /* gainsboro */ - 0x00308060, 0xffffd700, /* gold */ - 0xb3b3bc1e, 0xffdaa520, /* goldenrod */ - 0xbab8a537, 0xffadff2f, /* greenyellow */ - 0xe4cacafb, 0xfff0fff0, /* honeydew */ - 0x41892743, 0xffff69b4, /* hotpink */ - 0xd5796f1a, 0xffcd5c5c, /* indianred */ - 0xb969fed2, 0xff4b0082, /* indigo */ - 0x05fef6a9, 0xfffffff0, /* ivory */ - 0x06149302, 0xfff0e68c, /* khaki */ - 0xad5a05c7, 0xffe6e6fa, /* lavender */ - 0x7c4d5b99, 0xfffff0f5, /* lavenderblush */ - 0x195756f0, 0xfffffacd, /* lemonchiffon */ - 0x28e4ea70, 0xffadd8e6, /* lightblue */ - 0xf3c7ccdb, 0xfff08080, /* lightcoral */ - 0x28e58d39, 0xffe0ffff, /* lightcyan */ - 0x21234e3c, 0xfffafad2, /* lightgoldenrodyellow */ - 0xf40157ad, 0xff90ee90, /* lightgreen */ - 0x28e744f5, 0xffd3d3d3, /* lightgrey */ - 0x28eb3b8c, 0xffffb6c1, /* lightpink */ - 0x9fb78304, 0xffffa07a, /* lightsalmon */ - 0x50632b2a, 0xff20b2aa, /* lightseagreen */ - 0x68fb7b25, 0xff87cefa, /* lightskyblue */ - 0xa8a35ba2, 0xff778899, /* lightslategrey */ - 0xa20d484f, 0xffb0c4de, /* lightsteelblue */ - 0xaa2cf10a, 0xffffffe0, /* lightyellow */ - 0x0032afd5, 0xff00ff00, /* lime */ - 0x607bbc4e, 0xff32cd32, /* limegreen */ - 0x06234efa, 0xfffaf0e6, /* linen */ - 0x316858a9, 0xffff00ff, /* magenta */ - 0xbf8ca470, 0xff800000, /* maroon */ - 0xbd58e0b3, 0xff66cdaa, /* mediumaquamarine */ - 0x967dfd4f, 0xff0000cd, /* mediumblue */ - 0x056f5c58, 0xffba55d3, /* mediumorchid */ - 0x07556b71, 0xff9370db, /* mediumpurple */ - 0x5369b689, 0xff3cb371, /* mediumseagreen */ - 0x066be19e, 0xff7b68ee, /* mediumslateblue */ - 0x3256b281, 0xff00fa9a, /* mediumspringgreen */ - 0xc0ad9f4c, 0xff48d1cc, /* mediumturquoise */ - 0x628e63dd, 0xffc71585, /* mediumvioletred */ - 0x168eb32a, 0xff191970, /* midnightblue */ - 0x4306b960, 0xfff5fffa, /* mintcream */ - 0x4cbc0e6b, 0xffffe4e1, /* mistyrose */ - 0xe97218a6, 0xffffdead, /* navajowhite */ - 0x00337bb6, 0xff000080, /* navy */ - 0xadd2d33e, 0xfffdf5e6, /* oldlace */ - 0x064ee1db, 0xff808000, /* olive */ - 0x9e33a98a, 0xff6b8e23, /* olivedrab */ - 0xc3de262e, 0xffffa500, /* orange */ - 0x58bebba3, 0xffff4500, /* orangered */ - 0xc3def8a3, 0xffda70d6, /* orchid */ - 0x28cb4834, 0xffeee8aa, /* palegoldenrod */ - 0x3d9dd619, 0xff98fb98, /* palegreen */ - 0x74022737, 0xffafeeee, /* paleturquoise */ - 0x15e2ebc8, 0xffdb7093, /* palevioletred */ - 0x5fd898e2, 0xffffefd5, /* papayawhip */ - 0x93e1b776, 0xffffdab9, /* peachpuff */ - 0x003472f8, 0xffcd853f, /* peru */ - 0x00348176, 0xffffc0cb, /* pink */ - 0x00348d94, 0xffdda0dd, /* plum */ - 0xd036be93, 0xffb0e0e6, /* powderblue */ - 0xc5c507bc, 0xff800080, /* purple */ - 0xa89d65b3, 0xffbc8f8f, /* rosybrown */ - 0xbd9413e1, 0xff4169e1, /* royalblue */ - 0xf456044f, 0xff8b4513, /* saddlebrown */ - 0xc9c6f66e, 0xfffa8072, /* salmon */ - 0x0bb131e1, 0xfff4a460, /* sandybrown */ - 0x34636c14, 0xff2e8b57, /* seagreen */ - 0x3507fb41, 0xfffff5ee, /* seashell */ - 0xca348772, 0xffa0522d, /* sienna */ - 0xca37d30d, 0xffc0c0c0, /* silver */ - 0x80da74fb, 0xff87ceeb, /* skyblue */ - 0x44a8dd73, 0xff6a5acd, /* slateblue */ - 0x44ab37f8, 0xff708090, /* slategrey */ - 0x0035f183, 0xfffffafa, /* snow */ - 0xd5440d16, 0xff00ff7f, /* springgreen */ - 0x3e1524a5, 0xff4682b4, /* steelblue */ - 0x0001bfa1, 0xffd2b48c, /* tan */ - 0x0036425c, 0xff008080, /* teal */ - 0xafc8858f, 0xffd8bfd8, /* thistle */ - 0xcc41600a, 0xffff6347, /* tomato */ - 0xfeea9b21, 0xff40e0d0, /* turquoise */ - 0xcf57947f, 0xffee82ee, /* violet */ - 0x06bdbae7, 0xfff5deb3, /* wheat */ - 0x10802ee6, 0xfff5f5f5, /* whitesmoke */ - 0xe1b5130f, 0xff9acd32 /* yellowgreen */ - }; + 0x05978fff, 0xff000000, /* black */ + 0x06bdcc29, 0xffffffff, /* white */ + 0x002e305a, 0xff0000ff, /* blue */ + 0x00308adf, 0xff808080, /* grey */ + 0x05e0cf03, 0xff008000, /* green */ + 0x0001b891, 0xffff0000, /* red */ + 0xd43c6474, 0xffffff00, /* yellow */ + 0x620886da, 0xfff0f8ff, /* aliceblue */ + 0x20a2676a, 0xfffaebd7, /* antiquewhite */ + 0x002dcebc, 0xff00ffff, /* aqua */ + 0x46bb5f7e, 0xff7fffd4, /* aquamarine */ + 0x0590228f, 0xfff0ffff, /* azure */ + 0x05947fe4, 0xfff5f5dc, /* beige */ + 0xad388e35, 0xffffe4c4, /* bisque */ + 0x00674f7e, 0xffffebcd, /* blanchedalmond */ + 0x39129959, 0xff8a2be2, /* blueviolet */ + 0x059a8136, 0xffa52a2a, /* brown */ + 0x89cea8f9, 0xffdeb887, /* burlywood */ + 0x0fa260cf, 0xff5f9ea0, /* cadetblue */ + 0x6b748956, 0xff7fff00, /* chartreuse */ + 0x2903623c, 0xffd2691e, /* chocolate */ + 0x05a74431, 0xffff7f50, /* coral */ + 0x618d42dd, 0xff6495ed, /* cornflowerblue */ + 0xe4b479fd, 0xfffff8dc, /* cornsilk */ + 0x3d8c4edf, 0xffdc143c, /* crimson */ + 0x002ed323, 0xff00ffff, /* cyan */ + 0x67cc74d0, 0xff00008b, /* darkblue */ + 0x67cd1799, 0xff008b8b, /* darkcyan */ + 0x31bbd168, 0xffb8860b, /* darkgoldenrod */ + 0x67cecf55, 0xff555555, /* darkgrey */ + 0x920b194d, 0xff006400, /* darkgreen */ + 0x923edd4c, 0xffbdb76b, /* darkkhaki */ + 0x5c293873, 0xff8b008b, /* darkmagenta */ + 0x6b6671fe, 0xff556b2f, /* darkolivegreen */ + 0xbcfd2524, 0xffff8c00, /* darkorange */ + 0xbcfdf799, 0xff9932cc, /* darkorchid */ + 0x55ee0d5b, 0xff8b0000, /* darkred */ + 0xc2e5f564, 0xffe9967a, /* darksalmon */ + 0x61be858a, 0xff8fbc8f, /* darkseagreen */ + 0xc2b0f2bd, 0xff483d8b, /* darkslateblue */ + 0xc2b34d42, 0xff2f4f4f, /* darkslategrey */ + 0x7cf2b06b, 0xff00ced1, /* darkturquoise */ + 0xc8769375, 0xff9400d3, /* darkviolet */ + 0x25832862, 0xffff1493, /* deeppink */ + 0xfcad568f, 0xff00bfff, /* deepskyblue */ + 0x634c8b67, 0xff696969, /* dimgrey */ + 0x45c1ce55, 0xff1e90ff, /* dodgerblue */ + 0xef19e3cb, 0xffb22222, /* firebrick */ + 0xb852b195, 0xfffffaf0, /* floralwhite */ + 0xd086fd06, 0xff228b22, /* forestgreen */ + 0xe106b6d7, 0xffff00ff, /* fuchsia */ + 0x7880d61e, 0xffdcdcdc, /* gainsboro */ + 0x00308060, 0xffffd700, /* gold */ + 0xb3b3bc1e, 0xffdaa520, /* goldenrod */ + 0xbab8a537, 0xffadff2f, /* greenyellow */ + 0xe4cacafb, 0xfff0fff0, /* honeydew */ + 0x41892743, 0xffff69b4, /* hotpink */ + 0xd5796f1a, 0xffcd5c5c, /* indianred */ + 0xb969fed2, 0xff4b0082, /* indigo */ + 0x05fef6a9, 0xfffffff0, /* ivory */ + 0x06149302, 0xfff0e68c, /* khaki */ + 0xad5a05c7, 0xffe6e6fa, /* lavender */ + 0x7c4d5b99, 0xfffff0f5, /* lavenderblush */ + 0x195756f0, 0xfffffacd, /* lemonchiffon */ + 0x28e4ea70, 0xffadd8e6, /* lightblue */ + 0xf3c7ccdb, 0xfff08080, /* lightcoral */ + 0x28e58d39, 0xffe0ffff, /* lightcyan */ + 0x21234e3c, 0xfffafad2, /* lightgoldenrodyellow */ + 0xf40157ad, 0xff90ee90, /* lightgreen */ + 0x28e744f5, 0xffd3d3d3, /* lightgrey */ + 0x28eb3b8c, 0xffffb6c1, /* lightpink */ + 0x9fb78304, 0xffffa07a, /* lightsalmon */ + 0x50632b2a, 0xff20b2aa, /* lightseagreen */ + 0x68fb7b25, 0xff87cefa, /* lightskyblue */ + 0xa8a35ba2, 0xff778899, /* lightslategrey */ + 0xa20d484f, 0xffb0c4de, /* lightsteelblue */ + 0xaa2cf10a, 0xffffffe0, /* lightyellow */ + 0x0032afd5, 0xff00ff00, /* lime */ + 0x607bbc4e, 0xff32cd32, /* limegreen */ + 0x06234efa, 0xfffaf0e6, /* linen */ + 0x316858a9, 0xffff00ff, /* magenta */ + 0xbf8ca470, 0xff800000, /* maroon */ + 0xbd58e0b3, 0xff66cdaa, /* mediumaquamarine */ + 0x967dfd4f, 0xff0000cd, /* mediumblue */ + 0x056f5c58, 0xffba55d3, /* mediumorchid */ + 0x07556b71, 0xff9370db, /* mediumpurple */ + 0x5369b689, 0xff3cb371, /* mediumseagreen */ + 0x066be19e, 0xff7b68ee, /* mediumslateblue */ + 0x3256b281, 0xff00fa9a, /* mediumspringgreen */ + 0xc0ad9f4c, 0xff48d1cc, /* mediumturquoise */ + 0x628e63dd, 0xffc71585, /* mediumvioletred */ + 0x168eb32a, 0xff191970, /* midnightblue */ + 0x4306b960, 0xfff5fffa, /* mintcream */ + 0x4cbc0e6b, 0xffffe4e1, /* mistyrose */ + 0xe97218a6, 0xffffdead, /* navajowhite */ + 0x00337bb6, 0xff000080, /* navy */ + 0xadd2d33e, 0xfffdf5e6, /* oldlace */ + 0x064ee1db, 0xff808000, /* olive */ + 0x9e33a98a, 0xff6b8e23, /* olivedrab */ + 0xc3de262e, 0xffffa500, /* orange */ + 0x58bebba3, 0xffff4500, /* orangered */ + 0xc3def8a3, 0xffda70d6, /* orchid */ + 0x28cb4834, 0xffeee8aa, /* palegoldenrod */ + 0x3d9dd619, 0xff98fb98, /* palegreen */ + 0x74022737, 0xffafeeee, /* paleturquoise */ + 0x15e2ebc8, 0xffdb7093, /* palevioletred */ + 0x5fd898e2, 0xffffefd5, /* papayawhip */ + 0x93e1b776, 0xffffdab9, /* peachpuff */ + 0x003472f8, 0xffcd853f, /* peru */ + 0x00348176, 0xffffc0cb, /* pink */ + 0x00348d94, 0xffdda0dd, /* plum */ + 0xd036be93, 0xffb0e0e6, /* powderblue */ + 0xc5c507bc, 0xff800080, /* purple */ + 0xa89d65b3, 0xffbc8f8f, /* rosybrown */ + 0xbd9413e1, 0xff4169e1, /* royalblue */ + 0xf456044f, 0xff8b4513, /* saddlebrown */ + 0xc9c6f66e, 0xfffa8072, /* salmon */ + 0x0bb131e1, 0xfff4a460, /* sandybrown */ + 0x34636c14, 0xff2e8b57, /* seagreen */ + 0x3507fb41, 0xfffff5ee, /* seashell */ + 0xca348772, 0xffa0522d, /* sienna */ + 0xca37d30d, 0xffc0c0c0, /* silver */ + 0x80da74fb, 0xff87ceeb, /* skyblue */ + 0x44a8dd73, 0xff6a5acd, /* slateblue */ + 0x44ab37f8, 0xff708090, /* slategrey */ + 0x0035f183, 0xfffffafa, /* snow */ + 0xd5440d16, 0xff00ff7f, /* springgreen */ + 0x3e1524a5, 0xff4682b4, /* steelblue */ + 0x0001bfa1, 0xffd2b48c, /* tan */ + 0x0036425c, 0xff008080, /* teal */ + 0xafc8858f, 0xffd8bfd8, /* thistle */ + 0xcc41600a, 0xffff6347, /* tomato */ + 0xfeea9b21, 0xff40e0d0, /* turquoise */ + 0xcf57947f, 0xffee82ee, /* violet */ + 0x06bdbae7, 0xfff5deb3, /* wheat */ + 0x10802ee6, 0xfff5f5f5, /* whitesmoke */ + 0xe1b5130f, 0xff9acd32 /* yellowgreen */ + }; - const int hash = colourName.trim().toLowerCase().hashCode(); + const int hash = colourName.trim().toLowerCase().hashCode(); - for (int i = 0; i < numElementsInArray (presets); i += 2) - if (presets [i] == hash) - return Colour (presets [i + 1]); + for (int i = 0; i < numElementsInArray (presets); i += 2) + if (presets [i] == hash) + return Colour (presets [i + 1]); - return defaultColour; + return defaultColour; } END_JUCE_NAMESPACE @@ -79714,238 +79512,238 @@ const int juce_edgeTableDefaultEdgesPerLine = 32; static void copyEdgeTableData (int* dest, const int destLineStride, const int* src, const int srcLineStride, int numLines) throw() { - while (--numLines >= 0) - { - memcpy (dest, src, (src[0] * 2 + 1) * sizeof (int)); - src += srcLineStride; - dest += destLineStride; - } + while (--numLines >= 0) + { + memcpy (dest, src, (src[0] * 2 + 1) * sizeof (int)); + src += srcLineStride; + dest += destLineStride; + } } EdgeTable::EdgeTable (const Rectangle& bounds_, - const Path& path, const AffineTransform& transform) throw() + const Path& path, const AffineTransform& transform) throw() : bounds (bounds_), - maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), - lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), - needToCheckEmptinesss (true) + maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), + lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), + needToCheckEmptinesss (true) { - table.malloc ((bounds.getHeight() + 1) * lineStrideElements); - int* t = table; + table.malloc ((bounds.getHeight() + 1) * lineStrideElements); + int* t = table; - for (int i = bounds.getHeight(); --i >= 0;) - { - *t = 0; - t += lineStrideElements; - } + for (int i = bounds.getHeight(); --i >= 0;) + { + *t = 0; + t += lineStrideElements; + } - const int topLimit = bounds.getY() << 8; - const int heightLimit = bounds.getHeight() << 8; - const int leftLimit = bounds.getX() << 8; - const int rightLimit = bounds.getRight() << 8; + const int topLimit = bounds.getY() << 8; + const int heightLimit = bounds.getHeight() << 8; + const int leftLimit = bounds.getX() << 8; + const int rightLimit = bounds.getRight() << 8; - PathFlatteningIterator iter (path, transform); + PathFlatteningIterator iter (path, transform); - while (iter.next()) - { - int y1 = roundFloatToInt (iter.y1 * 256.0f); - int y2 = roundFloatToInt (iter.y2 * 256.0f); + while (iter.next()) + { + int y1 = roundToInt (iter.y1 * 256.0f); + int y2 = roundToInt (iter.y2 * 256.0f); - if (y1 != y2) - { - y1 -= topLimit; - y2 -= topLimit; + if (y1 != y2) + { + y1 -= topLimit; + y2 -= topLimit; - const int startY = y1; - int direction = -1; + const int startY = y1; + int direction = -1; - if (y1 > y2) - { - swapVariables (y1, y2); - direction = 1; - } + if (y1 > y2) + { + swapVariables (y1, y2); + direction = 1; + } - if (y1 < 0) - y1 = 0; + if (y1 < 0) + y1 = 0; - if (y2 > heightLimit) - y2 = heightLimit; + if (y2 > heightLimit) + y2 = heightLimit; - if (y1 < y2) - { - const double startX = 256.0f * iter.x1; - const double multiplier = (iter.x2 - iter.x1) / (iter.y2 - iter.y1); - const int stepSize = jlimit (1, 256, 256 / (1 + (int) fabs (multiplier))); + if (y1 < y2) + { + const double startX = 256.0f * iter.x1; + const double multiplier = (iter.x2 - iter.x1) / (iter.y2 - iter.y1); + const int stepSize = jlimit (1, 256, 256 / (1 + (int) fabs (multiplier))); - do - { - const int step = jmin (stepSize, y2 - y1, 256 - (y1 & 255)); - int x = roundDoubleToInt (startX + multiplier * ((y1 + (step >> 1)) - startY)); + do + { + const int step = jmin (stepSize, y2 - y1, 256 - (y1 & 255)); + int x = roundToInt (startX + multiplier * ((y1 + (step >> 1)) - startY)); - if (x < leftLimit) - x = leftLimit; - else if (x >= rightLimit) - x = rightLimit - 1; + if (x < leftLimit) + x = leftLimit; + else if (x >= rightLimit) + x = rightLimit - 1; - addEdgePoint (x, y1 >> 8, direction * step); - y1 += step; - } - while (y1 < y2); - } - } - } + addEdgePoint (x, y1 >> 8, direction * step); + y1 += step; + } + while (y1 < y2); + } + } + } - sanitiseLevels (path.isUsingNonZeroWinding()); + sanitiseLevels (path.isUsingNonZeroWinding()); } EdgeTable::EdgeTable (const Rectangle& rectangleToAdd) throw() : bounds (rectangleToAdd), - maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), - lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), - needToCheckEmptinesss (true) + maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), + lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), + needToCheckEmptinesss (true) { - table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); - table[0] = 0; + table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); + table[0] = 0; - const int x1 = rectangleToAdd.getX() << 8; - const int x2 = rectangleToAdd.getRight() << 8; + const int x1 = rectangleToAdd.getX() << 8; + const int x2 = rectangleToAdd.getRight() << 8; - int* t = table; - for (int i = rectangleToAdd.getHeight(); --i >= 0;) - { - t[0] = 2; - t[1] = x1; - t[2] = 255; - t[3] = x2; - t[4] = 0; - t += lineStrideElements; - } + int* t = table; + for (int i = rectangleToAdd.getHeight(); --i >= 0;) + { + t[0] = 2; + t[1] = x1; + t[2] = 255; + t[3] = x2; + t[4] = 0; + t += lineStrideElements; + } } EdgeTable::EdgeTable (const RectangleList& rectanglesToAdd) throw() : bounds (rectanglesToAdd.getBounds()), - maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), - lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), - needToCheckEmptinesss (true) + maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), + lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), + needToCheckEmptinesss (true) { - table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); + table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); - int* t = table; - for (int i = bounds.getHeight(); --i >= 0;) - { - *t = 0; - t += lineStrideElements; - } + int* t = table; + for (int i = bounds.getHeight(); --i >= 0;) + { + *t = 0; + t += lineStrideElements; + } - for (RectangleList::Iterator iter (rectanglesToAdd); iter.next();) - { - const Rectangle* const r = iter.getRectangle(); + for (RectangleList::Iterator iter (rectanglesToAdd); iter.next();) + { + const Rectangle* const r = iter.getRectangle(); - const int x1 = r->getX() << 8; - const int x2 = r->getRight() << 8; - int y = r->getY() - bounds.getY(); + const int x1 = r->getX() << 8; + const int x2 = r->getRight() << 8; + int y = r->getY() - bounds.getY(); - for (int j = r->getHeight(); --j >= 0;) - { - addEdgePoint (x1, y, 255); - addEdgePoint (x2, y, -255); - ++y; - } - } + for (int j = r->getHeight(); --j >= 0;) + { + addEdgePoint (x1, y, 255); + addEdgePoint (x2, y, -255); + ++y; + } + } - sanitiseLevels (true); + sanitiseLevels (true); } EdgeTable::EdgeTable (const float x, const float y, const float w, const float h) throw() - : bounds (Rectangle ((int) floorf (x), roundFloatToInt (y * 256.0f) >> 8, 2 + (int) w, 2 + (int) h)), - maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), - lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), - needToCheckEmptinesss (true) + : bounds (Rectangle ((int) floorf (x), roundToInt (y * 256.0f) >> 8, 2 + (int) w, 2 + (int) h)), + maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), + lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), + needToCheckEmptinesss (true) { - jassert (w > 0 && h > 0); - table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); - table[0] = 0; + jassert (w > 0 && h > 0); + table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); + table[0] = 0; - const int x1 = roundFloatToInt (x * 256.0f); - const int x2 = roundFloatToInt ((x + w) * 256.0f); + const int x1 = roundToInt (x * 256.0f); + const int x2 = roundToInt ((x + w) * 256.0f); - int y1 = roundFloatToInt (y * 256.0f) - (bounds.getY() << 8); - jassert (y1 < 256); - int y2 = roundFloatToInt ((y + h) * 256.0f) - (bounds.getY() << 8); + int y1 = roundToInt (y * 256.0f) - (bounds.getY() << 8); + jassert (y1 < 256); + int y2 = roundToInt ((y + h) * 256.0f) - (bounds.getY() << 8); - if (x2 <= x1 || y2 <= y1) - { - bounds.setHeight (0); - return; - } + if (x2 <= x1 || y2 <= y1) + { + bounds.setHeight (0); + return; + } - int lineY = 0; - int* t = table; + int lineY = 0; + int* t = table; - if ((y1 >> 8) == (y2 >> 8)) - { - t[0] = 2; - t[1] = x1; - t[2] = y2 - y1; - t[3] = x2; - t[4] = 0; - ++lineY; - t += lineStrideElements; - } - else - { - t[0] = 2; - t[1] = x1; - t[2] = 255 - (y1 & 255); - t[3] = x2; - t[4] = 0; - ++lineY; - t += lineStrideElements; + if ((y1 >> 8) == (y2 >> 8)) + { + t[0] = 2; + t[1] = x1; + t[2] = y2 - y1; + t[3] = x2; + t[4] = 0; + ++lineY; + t += lineStrideElements; + } + else + { + t[0] = 2; + t[1] = x1; + t[2] = 255 - (y1 & 255); + t[3] = x2; + t[4] = 0; + ++lineY; + t += lineStrideElements; - while (lineY < (y2 >> 8)) - { - t[0] = 2; - t[1] = x1; - t[2] = 255; - t[3] = x2; - t[4] = 0; - ++lineY; - t += lineStrideElements; - } + while (lineY < (y2 >> 8)) + { + t[0] = 2; + t[1] = x1; + t[2] = 255; + t[3] = x2; + t[4] = 0; + ++lineY; + t += lineStrideElements; + } - jassert (lineY < bounds.getHeight()); - t[0] = 2; - t[1] = x1; - t[2] = y2 & 255; - t[3] = x2; - t[4] = 0; - ++lineY; - t += lineStrideElements; - } + jassert (lineY < bounds.getHeight()); + t[0] = 2; + t[1] = x1; + t[2] = y2 & 255; + t[3] = x2; + t[4] = 0; + ++lineY; + t += lineStrideElements; + } - while (lineY < bounds.getHeight()) - { - t[0] = 0; - t += lineStrideElements; - ++lineY; - } + while (lineY < bounds.getHeight()) + { + t[0] = 0; + t += lineStrideElements; + ++lineY; + } } EdgeTable::EdgeTable (const EdgeTable& other) throw() : table (0) { - operator= (other); + operator= (other); } const EdgeTable& EdgeTable::operator= (const EdgeTable& other) throw() { - bounds = other.bounds; - maxEdgesPerLine = other.maxEdgesPerLine; - lineStrideElements = other.lineStrideElements; - needToCheckEmptinesss = other.needToCheckEmptinesss; + bounds = other.bounds; + maxEdgesPerLine = other.maxEdgesPerLine; + lineStrideElements = other.lineStrideElements; + needToCheckEmptinesss = other.needToCheckEmptinesss; - table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); - copyEdgeTableData (table, lineStrideElements, other.table, lineStrideElements, bounds.getHeight()); - return *this; + table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); + copyEdgeTableData (table, lineStrideElements, other.table, lineStrideElements, bounds.getHeight()); + return *this; } EdgeTable::~EdgeTable() throw() @@ -79954,418 +79752,418 @@ EdgeTable::~EdgeTable() throw() void EdgeTable::sanitiseLevels (const bool useNonZeroWinding) throw() { - // Convert the table from relative windings to absolute levels.. - int* lineStart = table; + // Convert the table from relative windings to absolute levels.. + int* lineStart = table; - for (int i = bounds.getHeight(); --i >= 0;) - { - int* line = lineStart; - lineStart += lineStrideElements; + for (int i = bounds.getHeight(); --i >= 0;) + { + int* line = lineStart; + lineStart += lineStrideElements; - int num = *line; - if (num == 0) - continue; + int num = *line; + if (num == 0) + continue; - int level = 0; + int level = 0; - if (useNonZeroWinding) - { - while (--num > 0) - { - line += 2; - level += *line; - int corrected = abs (level); - if (corrected >> 8) - corrected = 255; + if (useNonZeroWinding) + { + while (--num > 0) + { + line += 2; + level += *line; + int corrected = abs (level); + if (corrected >> 8) + corrected = 255; - *line = corrected; - } - } - else - { - while (--num > 0) - { - line += 2; - level += *line; - int corrected = abs (level); - if (corrected >> 8) - { - corrected &= 511; - if (corrected >> 8) - corrected = 511 - corrected; - } + *line = corrected; + } + } + else + { + while (--num > 0) + { + line += 2; + level += *line; + int corrected = abs (level); + if (corrected >> 8) + { + corrected &= 511; + if (corrected >> 8) + corrected = 511 - corrected; + } - *line = corrected; - } - } + *line = corrected; + } + } - line[2] = 0; // force the last level to 0, just in case something went wrong in creating the table - } + line[2] = 0; // force the last level to 0, just in case something went wrong in creating the table + } } void EdgeTable::remapTableForNumEdges (const int newNumEdgesPerLine) throw() { - if (newNumEdgesPerLine != maxEdgesPerLine) - { - maxEdgesPerLine = newNumEdgesPerLine; + if (newNumEdgesPerLine != maxEdgesPerLine) + { + maxEdgesPerLine = newNumEdgesPerLine; - jassert (bounds.getHeight() > 0); - const int newLineStrideElements = maxEdgesPerLine * 2 + 1; + jassert (bounds.getHeight() > 0); + const int newLineStrideElements = maxEdgesPerLine * 2 + 1; - HeapBlock newTable (bounds.getHeight() * newLineStrideElements); + HeapBlock newTable (bounds.getHeight() * newLineStrideElements); - copyEdgeTableData (newTable, newLineStrideElements, table, lineStrideElements, bounds.getHeight()); + copyEdgeTableData (newTable, newLineStrideElements, table, lineStrideElements, bounds.getHeight()); - table.swapWith (newTable); - lineStrideElements = newLineStrideElements; - } + table.swapWith (newTable); + lineStrideElements = newLineStrideElements; + } } void EdgeTable::optimiseTable() throw() { - int maxLineElements = 0; + int maxLineElements = 0; - for (int i = bounds.getHeight(); --i >= 0;) - maxLineElements = jmax (maxLineElements, table [i * lineStrideElements]); + for (int i = bounds.getHeight(); --i >= 0;) + maxLineElements = jmax (maxLineElements, table [i * lineStrideElements]); - remapTableForNumEdges (maxLineElements); + remapTableForNumEdges (maxLineElements); } void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw() { - jassert (y >= 0 && y < bounds.getHeight()); + jassert (y >= 0 && y < bounds.getHeight()); - int* line = table + lineStrideElements * y; - const int numPoints = line[0]; - int n = numPoints << 1; + int* line = table + lineStrideElements * y; + const int numPoints = line[0]; + int n = numPoints << 1; - if (n > 0) - { - while (n > 0) - { - const int cx = line [n - 1]; + if (n > 0) + { + while (n > 0) + { + const int cx = line [n - 1]; - if (cx <= x) - { - if (cx == x) - { - line [n] += winding; - return; - } + if (cx <= x) + { + if (cx == x) + { + line [n] += winding; + return; + } - break; - } + break; + } - n -= 2; - } + n -= 2; + } - if (numPoints >= maxEdgesPerLine) - { - remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); - jassert (numPoints < maxEdgesPerLine); - line = table + lineStrideElements * y; - } + if (numPoints >= maxEdgesPerLine) + { + remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); + jassert (numPoints < maxEdgesPerLine); + line = table + lineStrideElements * y; + } - memmove (line + (n + 3), line + (n + 1), sizeof (int) * ((numPoints << 1) - n)); - } + memmove (line + (n + 3), line + (n + 1), sizeof (int) * ((numPoints << 1) - n)); + } - line [n + 1] = x; - line [n + 2] = winding; - line[0]++; + line [n + 1] = x; + line [n + 2] = winding; + line[0]++; } void EdgeTable::translate (float dx, int dy) throw() { - bounds.setPosition (bounds.getX() + (int) floorf (dx), bounds.getY() + dy); + bounds.setPosition (bounds.getX() + (int) floorf (dx), bounds.getY() + dy); - int* lineStart = table; - const int intDx = (int) (dx * 256.0f); + int* lineStart = table; + const int intDx = (int) (dx * 256.0f); - for (int i = bounds.getHeight(); --i >= 0;) - { - int* line = lineStart; - lineStart += lineStrideElements; - int num = *line++; + for (int i = bounds.getHeight(); --i >= 0;) + { + int* line = lineStart; + lineStart += lineStrideElements; + int num = *line++; - while (--num >= 0) - { - *line += intDx; - line += 2; - } - } + while (--num >= 0) + { + *line += intDx; + line += 2; + } + } } void EdgeTable::intersectWithEdgeTableLine (const int y, const int* otherLine) throw() { - jassert (y >= 0 && y < bounds.getHeight()); + jassert (y >= 0 && y < bounds.getHeight()); - int* dest = table + lineStrideElements * y; - if (dest[0] == 0) - return; + int* dest = table + lineStrideElements * y; + if (dest[0] == 0) + return; - int otherNumPoints = *otherLine; - if (otherNumPoints == 0) - { - *dest = 0; - return; - } + int otherNumPoints = *otherLine; + if (otherNumPoints == 0) + { + *dest = 0; + return; + } - ++otherLine; - const int lineSizeBytes = (dest[0] * 2 + 1) * sizeof (int); - int* temp = (int*) alloca (lineSizeBytes); - memcpy (temp, dest, lineSizeBytes); + ++otherLine; + const size_t lineSizeBytes = (dest[0] * 2 + 1) * sizeof (int); + int* temp = (int*) alloca (lineSizeBytes); + memcpy (temp, dest, lineSizeBytes); - const int* src1 = temp; - int srcNum1 = *src1++; - int x1 = *src1++; + const int* src1 = temp; + int srcNum1 = *src1++; + int x1 = *src1++; - const int* src2 = otherLine; - int srcNum2 = otherNumPoints; - int x2 = *src2++; + const int* src2 = otherLine; + int srcNum2 = otherNumPoints; + int x2 = *src2++; - int destIndex = 0, destTotal = 0; - int level1 = 0, level2 = 0; - int lastX = INT_MIN, lastLevel = 0; - const int right = bounds.getRight() << 8; + int destIndex = 0, destTotal = 0; + int level1 = 0, level2 = 0; + int lastX = INT_MIN, lastLevel = 0; + const int right = bounds.getRight() << 8; - while (srcNum1 > 0 && srcNum2 > 0) - { - int nextX; + while (srcNum1 > 0 && srcNum2 > 0) + { + int nextX; - if (x1 < x2) - { - nextX = x1; - level1 = *src1++; - x1 = *src1++; - --srcNum1; - } - else if (x1 == x2) - { - nextX = x1; - level1 = *src1++; - level2 = *src2++; - x1 = *src1++; - x2 = *src2++; - --srcNum1; - --srcNum2; - } - else - { - nextX = x2; - level2 = *src2++; - x2 = *src2++; - --srcNum2; - } + if (x1 < x2) + { + nextX = x1; + level1 = *src1++; + x1 = *src1++; + --srcNum1; + } + else if (x1 == x2) + { + nextX = x1; + level1 = *src1++; + level2 = *src2++; + x1 = *src1++; + x2 = *src2++; + --srcNum1; + --srcNum2; + } + else + { + nextX = x2; + level2 = *src2++; + x2 = *src2++; + --srcNum2; + } - if (nextX > lastX) - { - if (nextX >= right) - break; + if (nextX > lastX) + { + if (nextX >= right) + break; - lastX = nextX; + lastX = nextX; - const int nextLevel = (level1 * (level2 + 1)) >> 8; - jassert (((unsigned int) nextLevel) < (unsigned int) 256); + const int nextLevel = (level1 * (level2 + 1)) >> 8; + jassert (((unsigned int) nextLevel) < (unsigned int) 256); - if (nextLevel != lastLevel) - { - if (destTotal >= maxEdgesPerLine) - { - dest[0] = destTotal; - remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); - dest = table + lineStrideElements * y; - } + if (nextLevel != lastLevel) + { + if (destTotal >= maxEdgesPerLine) + { + dest[0] = destTotal; + remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); + dest = table + lineStrideElements * y; + } - ++destTotal; - lastLevel = nextLevel; - dest[++destIndex] = nextX; - dest[++destIndex] = nextLevel; - } - } - } + ++destTotal; + lastLevel = nextLevel; + dest[++destIndex] = nextX; + dest[++destIndex] = nextLevel; + } + } + } - if (lastLevel > 0) - { - if (destTotal >= maxEdgesPerLine) - { - dest[0] = destTotal; - remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); - dest = table + lineStrideElements * y; - } + if (lastLevel > 0) + { + if (destTotal >= maxEdgesPerLine) + { + dest[0] = destTotal; + remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); + dest = table + lineStrideElements * y; + } - ++destTotal; - dest[++destIndex] = right; - dest[++destIndex] = 0; - } + ++destTotal; + dest[++destIndex] = right; + dest[++destIndex] = 0; + } - dest[0] = destTotal; + dest[0] = destTotal; #if JUCE_DEBUG - int last = INT_MIN; - for (int i = 0; i < dest[0]; ++i) - { - jassert (dest[i * 2 + 1] > last); - last = dest[i * 2 + 1]; - } + int last = INT_MIN; + for (int i = 0; i < dest[0]; ++i) + { + jassert (dest[i * 2 + 1] > last); + last = dest[i * 2 + 1]; + } - jassert (dest [dest[0] * 2] == 0); + jassert (dest [dest[0] * 2] == 0); #endif } void EdgeTable::clipToRectangle (const Rectangle& r) throw() { - const Rectangle clipped (r.getIntersection (bounds)); + const Rectangle clipped (r.getIntersection (bounds)); - if (clipped.isEmpty()) - { - needToCheckEmptinesss = false; - bounds.setHeight (0); - } - else - { - const int top = clipped.getY() - bounds.getY(); - const int bottom = clipped.getBottom() - bounds.getY(); + if (clipped.isEmpty()) + { + needToCheckEmptinesss = false; + bounds.setHeight (0); + } + else + { + const int top = clipped.getY() - bounds.getY(); + const int bottom = clipped.getBottom() - bounds.getY(); - if (bottom < bounds.getHeight()) - bounds.setHeight (bottom); + if (bottom < bounds.getHeight()) + bounds.setHeight (bottom); - if (clipped.getRight() < bounds.getRight()) - bounds.setRight (clipped.getRight()); + if (clipped.getRight() < bounds.getRight()) + bounds.setRight (clipped.getRight()); - for (int i = top; --i >= 0;) - table [lineStrideElements * i] = 0; + for (int i = top; --i >= 0;) + table [lineStrideElements * i] = 0; - if (clipped.getX() > bounds.getX()) - { - const int rectLine[] = { 2, clipped.getX() << 8, 255, clipped.getRight() << 8, 0 }; + if (clipped.getX() > bounds.getX()) + { + const int rectLine[] = { 2, clipped.getX() << 8, 255, clipped.getRight() << 8, 0 }; - for (int i = top; i < bottom; ++i) - intersectWithEdgeTableLine (i, rectLine); - } + for (int i = top; i < bottom; ++i) + intersectWithEdgeTableLine (i, rectLine); + } - needToCheckEmptinesss = true; - } + needToCheckEmptinesss = true; + } } void EdgeTable::excludeRectangle (const Rectangle& r) throw() { - const Rectangle clipped (r.getIntersection (bounds)); + const Rectangle clipped (r.getIntersection (bounds)); - if (! clipped.isEmpty()) - { - const int top = clipped.getY() - bounds.getY(); - const int bottom = clipped.getBottom() - bounds.getY(); + if (! clipped.isEmpty()) + { + const int top = clipped.getY() - bounds.getY(); + const int bottom = clipped.getBottom() - bounds.getY(); - //XXX optimise here by shortening the table if it fills top or bottom + //XXX optimise here by shortening the table if it fills top or bottom - const int rectLine[] = { 4, INT_MIN, 255, clipped.getX() << 8, 0, clipped.getRight() << 8, 255, INT_MAX, 0 }; + const int rectLine[] = { 4, INT_MIN, 255, clipped.getX() << 8, 0, clipped.getRight() << 8, 255, INT_MAX, 0 }; - for (int i = top; i < bottom; ++i) - intersectWithEdgeTableLine (i, rectLine); + for (int i = top; i < bottom; ++i) + intersectWithEdgeTableLine (i, rectLine); - needToCheckEmptinesss = true; - } + needToCheckEmptinesss = true; + } } void EdgeTable::clipToEdgeTable (const EdgeTable& other) { - const Rectangle clipped (other.bounds.getIntersection (bounds)); + const Rectangle clipped (other.bounds.getIntersection (bounds)); - if (clipped.isEmpty()) - { - needToCheckEmptinesss = false; - bounds.setHeight (0); - } - else - { - const int top = clipped.getY() - bounds.getY(); - const int bottom = clipped.getBottom() - bounds.getY(); + if (clipped.isEmpty()) + { + needToCheckEmptinesss = false; + bounds.setHeight (0); + } + else + { + const int top = clipped.getY() - bounds.getY(); + const int bottom = clipped.getBottom() - bounds.getY(); - if (bottom < bounds.getHeight()) - bounds.setHeight (bottom); + if (bottom < bounds.getHeight()) + bounds.setHeight (bottom); - if (clipped.getRight() < bounds.getRight()) - bounds.setRight (clipped.getRight()); + if (clipped.getRight() < bounds.getRight()) + bounds.setRight (clipped.getRight()); - int i = 0; - for (i = top; --i >= 0;) - table [lineStrideElements * i] = 0; + int i = 0; + for (i = top; --i >= 0;) + table [lineStrideElements * i] = 0; - const int* otherLine = other.table + other.lineStrideElements * (clipped.getY() - other.bounds.getY()); + const int* otherLine = other.table + other.lineStrideElements * (clipped.getY() - other.bounds.getY()); - for (i = top; i < bottom; ++i) - { - intersectWithEdgeTableLine (i, otherLine); - otherLine += other.lineStrideElements; - } + for (i = top; i < bottom; ++i) + { + intersectWithEdgeTableLine (i, otherLine); + otherLine += other.lineStrideElements; + } - needToCheckEmptinesss = true; - } + needToCheckEmptinesss = true; + } } void EdgeTable::clipLineToMask (int x, int y, uint8* mask, int maskStride, int numPixels) throw() { - y -= bounds.getY(); + y -= bounds.getY(); - if (y < 0 || y >= bounds.getHeight()) - return; + if (y < 0 || y >= bounds.getHeight()) + return; - needToCheckEmptinesss = true; + needToCheckEmptinesss = true; - if (numPixels <= 0) - { - table [lineStrideElements * y] = 0; - return; - } + if (numPixels <= 0) + { + table [lineStrideElements * y] = 0; + return; + } - int* tempLine = (int*) alloca ((numPixels * 2 + 4) * sizeof (int)); - int destIndex = 0, lastLevel = 0; + int* tempLine = (int*) alloca ((numPixels * 2 + 4) * sizeof (int)); + int destIndex = 0, lastLevel = 0; - while (--numPixels >= 0) - { - const int alpha = *mask; - mask += maskStride; + while (--numPixels >= 0) + { + const int alpha = *mask; + mask += maskStride; - if (alpha != lastLevel) - { - tempLine[++destIndex] = (x << 8); - tempLine[++destIndex] = alpha; - lastLevel = alpha; - } + if (alpha != lastLevel) + { + tempLine[++destIndex] = (x << 8); + tempLine[++destIndex] = alpha; + lastLevel = alpha; + } - ++x; - } + ++x; + } - if (lastLevel > 0) - { - tempLine[++destIndex] = (x << 8); - tempLine[++destIndex] = 0; - } + if (lastLevel > 0) + { + tempLine[++destIndex] = (x << 8); + tempLine[++destIndex] = 0; + } - tempLine[0] = destIndex >> 1; + tempLine[0] = destIndex >> 1; - intersectWithEdgeTableLine (y, tempLine); + intersectWithEdgeTableLine (y, tempLine); } bool EdgeTable::isEmpty() throw() { - if (needToCheckEmptinesss) - { - needToCheckEmptinesss = false; - int* t = table; + if (needToCheckEmptinesss) + { + needToCheckEmptinesss = false; + int* t = table; - for (int i = bounds.getHeight(); --i >= 0;) - { - if (t[0] > 1) - return false; + for (int i = bounds.getHeight(); --i >= 0;) + { + if (t[0] > 1) + return false; - t += lineStrideElements; - } + t += lineStrideElements; + } - bounds.setHeight (0); - } + bounds.setHeight (0); + } - return bounds.getHeight() == 0; + return bounds.getHeight() == 0; } END_JUCE_NAMESPACE @@ -80376,43 +80174,43 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE FillType::FillType() throw() - : colour (0xff000000), image (0) + : colour (0xff000000), image (0) { } FillType::FillType (const Colour& colour_) throw() - : colour (colour_), image (0) + : colour (colour_), image (0) { } FillType::FillType (const ColourGradient& gradient_) throw() - : colour (0xff000000), gradient (new ColourGradient (gradient_)), image (0) + : colour (0xff000000), gradient (new ColourGradient (gradient_)), image (0) { } FillType::FillType (const Image& image_, const AffineTransform& transform_) throw() - : colour (0xff000000), image (&image_), transform (transform_) + : colour (0xff000000), image (&image_), transform (transform_) { } FillType::FillType (const FillType& other) throw() - : colour (other.colour), - gradient (other.gradient != 0 ? new ColourGradient (*other.gradient) : 0), - image (other.image), transform (other.transform) + : colour (other.colour), + gradient (other.gradient != 0 ? new ColourGradient (*other.gradient) : 0), + image (other.image), transform (other.transform) { } const FillType& FillType::operator= (const FillType& other) throw() { - if (this != &other) - { - colour = other.colour; - gradient = (other.gradient != 0 ? new ColourGradient (*other.gradient) : 0); - image = other.image; - transform = other.transform; - } + if (this != &other) + { + colour = other.colour; + gradient = (other.gradient != 0 ? new ColourGradient (*other.gradient) : 0); + image = other.image; + transform = other.transform; + } - return *this; + return *this; } FillType::~FillType() throw() @@ -80421,36 +80219,36 @@ FillType::~FillType() throw() void FillType::setColour (const Colour& newColour) throw() { - gradient = 0; - image = 0; - colour = newColour; + gradient = 0; + image = 0; + colour = newColour; } void FillType::setGradient (const ColourGradient& newGradient) throw() { - if (gradient != 0) - { - *gradient = newGradient; - } - else - { - image = 0; - gradient = new ColourGradient (newGradient); - colour = Colours::black; - } + if (gradient != 0) + { + *gradient = newGradient; + } + else + { + image = 0; + gradient = new ColourGradient (newGradient); + colour = Colours::black; + } } void FillType::setTiledImage (const Image& image_, const AffineTransform& transform_) throw() { - gradient = 0; - image = &image_; - transform = transform_; - colour = Colours::black; + gradient = 0; + image = &image_; + transform = transform_; + colour = Colours::black; } void FillType::setOpacity (const float newOpacity) throw() { - colour = colour.withAlpha (newOpacity); + colour = colour.withAlpha (newOpacity); } END_JUCE_NAMESPACE @@ -80462,19 +80260,16 @@ BEGIN_JUCE_NAMESPACE static const Graphics::ResamplingQuality defaultQuality = Graphics::mediumResamplingQuality; -#define MINIMUM_COORD -0x3fffffff -#define MAXIMUM_COORD 0x3fffffff +template +static bool areCoordsSensibleNumbers (Type x, Type y, Type w, Type h) +{ + const int maxVal = 0x3fffffff; -#undef ASSERT_COORDS_ARE_SENSIBLE_NUMBERS -#define ASSERT_COORDS_ARE_SENSIBLE_NUMBERS(x, y, w, h) \ - jassert ((int) x >= MINIMUM_COORD \ - && (int) x <= MAXIMUM_COORD \ - && (int) y >= MINIMUM_COORD \ - && (int) y <= MAXIMUM_COORD \ - && (int) w >= MINIMUM_COORD \ - && (int) w <= MAXIMUM_COORD \ - && (int) h >= MINIMUM_COORD \ - && (int) h <= MAXIMUM_COORD); + return (int) x >= -maxVal && (int) x <= maxVal + && (int) y >= -maxVal && (int) y <= maxVal + && (int) w >= -maxVal && (int) w <= maxVal + && (int) h >= -maxVal && (int) h <= maxVal; +} LowLevelGraphicsContext::LowLevelGraphicsContext() { @@ -80485,722 +80280,719 @@ LowLevelGraphicsContext::~LowLevelGraphicsContext() } Graphics::Graphics (Image& imageToDrawOnto) throw() - : context (imageToDrawOnto.createLowLevelContext()), - ownsContext (true), - saveStatePending (false) + : context (imageToDrawOnto.createLowLevelContext()), + contextToDelete (context), + saveStatePending (false) { - resetToDefaultState(); + resetToDefaultState(); } Graphics::Graphics (LowLevelGraphicsContext* const internalContext) throw() - : context (internalContext), - ownsContext (false), - saveStatePending (false) + : context (internalContext), + saveStatePending (false) { - resetToDefaultState(); + resetToDefaultState(); } Graphics::~Graphics() throw() { - if (ownsContext) - delete context; } void Graphics::resetToDefaultState() throw() { - saveStateIfPending(); - context->setFill (FillType()); - context->setFont (Font()); - context->setInterpolationQuality (defaultQuality); + saveStateIfPending(); + context->setFill (FillType()); + context->setFont (Font()); + context->setInterpolationQuality (defaultQuality); } bool Graphics::isVectorDevice() const throw() { - return context->isVectorDevice(); + return context->isVectorDevice(); } bool Graphics::reduceClipRegion (const int x, const int y, - const int w, const int h) throw() + const int w, const int h) throw() { - saveStateIfPending(); - return context->clipToRectangle (Rectangle (x, y, w, h)); + saveStateIfPending(); + return context->clipToRectangle (Rectangle (x, y, w, h)); } bool Graphics::reduceClipRegion (const RectangleList& clipRegion) throw() { - saveStateIfPending(); - return context->clipToRectangleList (clipRegion); + saveStateIfPending(); + return context->clipToRectangleList (clipRegion); } bool Graphics::reduceClipRegion (const Path& path, const AffineTransform& transform) throw() { - saveStateIfPending(); - context->clipToPath (path, transform); - return ! context->isClipEmpty(); + saveStateIfPending(); + context->clipToPath (path, transform); + return ! context->isClipEmpty(); } bool Graphics::reduceClipRegion (const Image& image, const Rectangle& sourceClipRegion, const AffineTransform& transform) throw() { - saveStateIfPending(); - context->clipToImageAlpha (image, sourceClipRegion, transform); - return ! context->isClipEmpty(); + saveStateIfPending(); + context->clipToImageAlpha (image, sourceClipRegion, transform); + return ! context->isClipEmpty(); } void Graphics::excludeClipRegion (const int x, const int y, - const int w, const int h) throw() + const int w, const int h) throw() { - saveStateIfPending(); - context->excludeClipRectangle (Rectangle (x, y, w, h)); + saveStateIfPending(); + context->excludeClipRectangle (Rectangle (x, y, w, h)); } bool Graphics::isClipEmpty() const throw() { - return context->isClipEmpty(); + return context->isClipEmpty(); } const Rectangle Graphics::getClipBounds() const throw() { - return context->getClipBounds(); + return context->getClipBounds(); } void Graphics::saveState() throw() { - saveStateIfPending(); - saveStatePending = true; + saveStateIfPending(); + saveStatePending = true; } void Graphics::restoreState() throw() { - if (saveStatePending) - saveStatePending = false; - else - context->restoreState(); + if (saveStatePending) + saveStatePending = false; + else + context->restoreState(); } void Graphics::saveStateIfPending() throw() { - if (saveStatePending) - { - saveStatePending = false; - context->saveState(); - } + if (saveStatePending) + { + saveStatePending = false; + context->saveState(); + } } void Graphics::setOrigin (const int newOriginX, - const int newOriginY) throw() + const int newOriginY) throw() { - saveStateIfPending(); - context->setOrigin (newOriginX, newOriginY); + saveStateIfPending(); + context->setOrigin (newOriginX, newOriginY); } bool Graphics::clipRegionIntersects (const int x, const int y, - const int w, const int h) const throw() + const int w, const int h) const throw() { - return context->clipRegionIntersects (Rectangle (x, y, w, h)); + return context->clipRegionIntersects (Rectangle (x, y, w, h)); } void Graphics::setColour (const Colour& newColour) throw() { - saveStateIfPending(); - context->setFill (FillType (newColour)); + saveStateIfPending(); + context->setFill (FillType (newColour)); } void Graphics::setOpacity (const float newOpacity) throw() { - saveStateIfPending(); - context->setOpacity (newOpacity); + saveStateIfPending(); + context->setOpacity (newOpacity); } void Graphics::setGradientFill (const ColourGradient& gradient) throw() { - saveStateIfPending(); - context->setFill (FillType (gradient)); + saveStateIfPending(); + context->setFill (FillType (gradient)); } void Graphics::setTiledImageFill (const Image& imageToUse, - const int anchorX, - const int anchorY, - const float opacity) throw() + const int anchorX, + const int anchorY, + const float opacity) throw() { - saveStateIfPending(); - context->setFill (FillType (imageToUse, AffineTransform::translation ((float) anchorX, (float) anchorY))); - context->setOpacity (opacity); + saveStateIfPending(); + context->setFill (FillType (imageToUse, AffineTransform::translation ((float) anchorX, (float) anchorY))); + context->setOpacity (opacity); } void Graphics::setFillType (const FillType& newFill) throw() { - saveStateIfPending(); - context->setFill (newFill); + saveStateIfPending(); + context->setFill (newFill); } void Graphics::setFont (const Font& newFont) throw() { - saveStateIfPending(); - context->setFont (newFont); + saveStateIfPending(); + context->setFont (newFont); } void Graphics::setFont (const float newFontHeight, - const int newFontStyleFlags) throw() + const int newFontStyleFlags) throw() { - saveStateIfPending(); - Font f (context->getFont()); - f.setSizeAndStyle (newFontHeight, newFontStyleFlags, 1.0f, 0); - context->setFont (f); + saveStateIfPending(); + Font f (context->getFont()); + f.setSizeAndStyle (newFontHeight, newFontStyleFlags, 1.0f, 0); + context->setFont (f); } void Graphics::drawSingleLineText (const String& text, - const int startX, - const int baselineY) const throw() + const int startX, + const int baselineY) const throw() { - if (text.isNotEmpty() - && startX < context->getClipBounds().getRight()) - { - GlyphArrangement arr; - arr.addLineOfText (context->getFont(), text, (float) startX, (float) baselineY); - arr.draw (*this); - } + if (text.isNotEmpty() + && startX < context->getClipBounds().getRight()) + { + GlyphArrangement arr; + arr.addLineOfText (context->getFont(), text, (float) startX, (float) baselineY); + arr.draw (*this); + } } void Graphics::drawTextAsPath (const String& text, - const AffineTransform& transform) const throw() + const AffineTransform& transform) const throw() { - if (text.isNotEmpty()) - { - GlyphArrangement arr; - arr.addLineOfText (context->getFont(), text, 0.0f, 0.0f); - arr.draw (*this, transform); - } + if (text.isNotEmpty()) + { + GlyphArrangement arr; + arr.addLineOfText (context->getFont(), text, 0.0f, 0.0f); + arr.draw (*this, transform); + } } void Graphics::drawMultiLineText (const String& text, - const int startX, - const int baselineY, - const int maximumLineWidth) const throw() + const int startX, + const int baselineY, + const int maximumLineWidth) const throw() { - if (text.isNotEmpty() - && startX < context->getClipBounds().getRight()) - { - GlyphArrangement arr; - arr.addJustifiedText (context->getFont(), text, - (float) startX, (float) baselineY, (float) maximumLineWidth, - Justification::left); - arr.draw (*this); - } + if (text.isNotEmpty() + && startX < context->getClipBounds().getRight()) + { + GlyphArrangement arr; + arr.addJustifiedText (context->getFont(), text, + (float) startX, (float) baselineY, (float) maximumLineWidth, + Justification::left); + arr.draw (*this); + } } void Graphics::drawText (const String& text, - const int x, - const int y, - const int width, - const int height, - const Justification& justificationType, - const bool useEllipsesIfTooBig) const throw() + const int x, + const int y, + const int width, + const int height, + const Justification& justificationType, + const bool useEllipsesIfTooBig) const throw() { - if (text.isNotEmpty() && context->clipRegionIntersects (Rectangle (x, y, width, height))) - { - GlyphArrangement arr; + if (text.isNotEmpty() && context->clipRegionIntersects (Rectangle (x, y, width, height))) + { + GlyphArrangement arr; - arr.addCurtailedLineOfText (context->getFont(), text, - 0.0f, 0.0f, (float)width, - useEllipsesIfTooBig); + arr.addCurtailedLineOfText (context->getFont(), text, + 0.0f, 0.0f, (float)width, + useEllipsesIfTooBig); - arr.justifyGlyphs (0, arr.getNumGlyphs(), - (float) x, (float) y, - (float) width, (float) height, - justificationType); - arr.draw (*this); - } + arr.justifyGlyphs (0, arr.getNumGlyphs(), + (float) x, (float) y, + (float) width, (float) height, + justificationType); + arr.draw (*this); + } } void Graphics::drawFittedText (const String& text, - const int x, - const int y, - const int width, - const int height, - const Justification& justification, - const int maximumNumberOfLines, - const float minimumHorizontalScale) const throw() + const int x, + const int y, + const int width, + const int height, + const Justification& justification, + const int maximumNumberOfLines, + const float minimumHorizontalScale) const throw() { - if (text.isNotEmpty() - && width > 0 && height > 0 - && context->clipRegionIntersects (Rectangle (x, y, width, height))) - { - GlyphArrangement arr; + if (text.isNotEmpty() + && width > 0 && height > 0 + && context->clipRegionIntersects (Rectangle (x, y, width, height))) + { + GlyphArrangement arr; - arr.addFittedText (context->getFont(), text, - (float) x, (float) y, - (float) width, (float) height, - justification, - maximumNumberOfLines, - minimumHorizontalScale); + arr.addFittedText (context->getFont(), text, + (float) x, (float) y, + (float) width, (float) height, + justification, + maximumNumberOfLines, + minimumHorizontalScale); - arr.draw (*this); - } + arr.draw (*this); + } } void Graphics::fillRect (int x, - int y, - int width, - int height) const throw() + int y, + int width, + int height) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (x, y, width, height)); - context->fillRect (Rectangle (x, y, width, height), false); + context->fillRect (Rectangle (x, y, width, height), false); } void Graphics::fillRect (const Rectangle& r) const throw() { - context->fillRect (r, false); + context->fillRect (r, false); } void Graphics::fillRect (const float x, - const float y, - const float width, - const float height) const throw() + const float y, + const float width, + const float height) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (x, y, width, height)); - Path p; - p.addRectangle (x, y, width, height); - fillPath (p); + Path p; + p.addRectangle (x, y, width, height); + fillPath (p); } void Graphics::setPixel (int x, int y) const throw() { - context->fillRect (Rectangle (x, y, 1, 1), false); + context->fillRect (Rectangle (x, y, 1, 1), false); } void Graphics::fillAll() const throw() { - fillRect (context->getClipBounds()); + fillRect (context->getClipBounds()); } void Graphics::fillAll (const Colour& colourToUse) const throw() { - if (! colourToUse.isTransparent()) - { - const Rectangle clip (context->getClipBounds()); + if (! colourToUse.isTransparent()) + { + const Rectangle clip (context->getClipBounds()); - context->saveState(); - context->setFill (FillType (colourToUse)); - context->fillRect (clip, false); - context->restoreState(); - } + context->saveState(); + context->setFill (FillType (colourToUse)); + context->fillRect (clip, false); + context->restoreState(); + } } void Graphics::fillPath (const Path& path, - const AffineTransform& transform) const throw() + const AffineTransform& transform) const throw() { - if ((! context->isClipEmpty()) && ! path.isEmpty()) - context->fillPath (path, transform); + if ((! context->isClipEmpty()) && ! path.isEmpty()) + context->fillPath (path, transform); } void Graphics::strokePath (const Path& path, - const PathStrokeType& strokeType, - const AffineTransform& transform) const throw() + const PathStrokeType& strokeType, + const AffineTransform& transform) const throw() { - Path stroke; - strokeType.createStrokedPath (stroke, path, transform); - fillPath (stroke); + Path stroke; + strokeType.createStrokedPath (stroke, path, transform); + fillPath (stroke); } void Graphics::drawRect (const int x, - const int y, - const int width, - const int height, - const int lineThickness) const throw() + const int y, + const int width, + const int height, + const int lineThickness) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (x, y, width, height)); - context->fillRect (Rectangle (x, y, width, lineThickness), false); - context->fillRect (Rectangle (x, y + lineThickness, lineThickness, height - lineThickness * 2), false); - context->fillRect (Rectangle (x + width - lineThickness, y + lineThickness, lineThickness, height - lineThickness * 2), false); - context->fillRect (Rectangle (x, y + height - lineThickness, width, lineThickness), false); + context->fillRect (Rectangle (x, y, width, lineThickness), false); + context->fillRect (Rectangle (x, y + lineThickness, lineThickness, height - lineThickness * 2), false); + context->fillRect (Rectangle (x + width - lineThickness, y + lineThickness, lineThickness, height - lineThickness * 2), false); + context->fillRect (Rectangle (x, y + height - lineThickness, width, lineThickness), false); } void Graphics::drawRect (const float x, - const float y, - const float width, - const float height, - const float lineThickness) const throw() + const float y, + const float width, + const float height, + const float lineThickness) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (x, y, width, height)); - Path p; - p.addRectangle (x, y, width, lineThickness); - p.addRectangle (x, y + lineThickness, lineThickness, height - lineThickness * 2.0f); - p.addRectangle (x + width - lineThickness, y + lineThickness, lineThickness, height - lineThickness * 2.0f); - p.addRectangle (x, y + height - lineThickness, width, lineThickness); - fillPath (p); + Path p; + p.addRectangle (x, y, width, lineThickness); + p.addRectangle (x, y + lineThickness, lineThickness, height - lineThickness * 2.0f); + p.addRectangle (x + width - lineThickness, y + lineThickness, lineThickness, height - lineThickness * 2.0f); + p.addRectangle (x, y + height - lineThickness, width, lineThickness); + fillPath (p); } void Graphics::drawRect (const Rectangle& r, - const int lineThickness) const throw() + const int lineThickness) const throw() { - drawRect (r.getX(), r.getY(), - r.getWidth(), r.getHeight(), - lineThickness); + drawRect (r.getX(), r.getY(), + r.getWidth(), r.getHeight(), + lineThickness); } void Graphics::drawBevel (const int x, - const int y, - const int width, - const int height, - const int bevelThickness, - const Colour& topLeftColour, - const Colour& bottomRightColour, - const bool useGradient, - const bool sharpEdgeOnOutside) const throw() + const int y, + const int width, + const int height, + const int bevelThickness, + const Colour& topLeftColour, + const Colour& bottomRightColour, + const bool useGradient, + const bool sharpEdgeOnOutside) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (x, y, width, height)); - if (clipRegionIntersects (x, y, width, height)) - { - context->saveState(); + if (clipRegionIntersects (x, y, width, height)) + { + context->saveState(); - const float oldOpacity = 1.0f;//xxx state->colour.getFloatAlpha(); - const float ramp = oldOpacity / bevelThickness; + const float oldOpacity = 1.0f;//xxx state->colour.getFloatAlpha(); + const float ramp = oldOpacity / bevelThickness; - for (int i = bevelThickness; --i >= 0;) - { - const float op = useGradient ? ramp * (sharpEdgeOnOutside ? bevelThickness - i : i) - : oldOpacity; + for (int i = bevelThickness; --i >= 0;) + { + const float op = useGradient ? ramp * (sharpEdgeOnOutside ? bevelThickness - i : i) + : oldOpacity; - context->setFill (FillType (topLeftColour.withMultipliedAlpha (op))); - context->fillRect (Rectangle (x + i, y + i, width - i * 2, 1), false); - context->setFill (FillType (topLeftColour.withMultipliedAlpha (op * 0.75f))); - context->fillRect (Rectangle (x + i, y + i + 1, 1, height - i * 2 - 2), false); - context->setFill (FillType (bottomRightColour.withMultipliedAlpha (op))); - context->fillRect (Rectangle (x + i, y + height - i - 1, width - i * 2, 1), false); - context->setFill (FillType (bottomRightColour.withMultipliedAlpha (op * 0.75f))); - context->fillRect (Rectangle (x + width - i - 1, y + i + 1, 1, height - i * 2 - 2), false); - } + context->setFill (FillType (topLeftColour.withMultipliedAlpha (op))); + context->fillRect (Rectangle (x + i, y + i, width - i * 2, 1), false); + context->setFill (FillType (topLeftColour.withMultipliedAlpha (op * 0.75f))); + context->fillRect (Rectangle (x + i, y + i + 1, 1, height - i * 2 - 2), false); + context->setFill (FillType (bottomRightColour.withMultipliedAlpha (op))); + context->fillRect (Rectangle (x + i, y + height - i - 1, width - i * 2, 1), false); + context->setFill (FillType (bottomRightColour.withMultipliedAlpha (op * 0.75f))); + context->fillRect (Rectangle (x + width - i - 1, y + i + 1, 1, height - i * 2 - 2), false); + } - context->restoreState(); - } + context->restoreState(); + } } void Graphics::fillEllipse (const float x, - const float y, - const float width, - const float height) const throw() + const float y, + const float width, + const float height) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (x, y, width, height)); - Path p; - p.addEllipse (x, y, width, height); - fillPath (p); + Path p; + p.addEllipse (x, y, width, height); + fillPath (p); } void Graphics::drawEllipse (const float x, - const float y, - const float width, - const float height, - const float lineThickness) const throw() + const float y, + const float width, + const float height, + const float lineThickness) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (x, y, width, height)); - Path p; - p.addEllipse (x, y, width, height); - strokePath (p, PathStrokeType (lineThickness)); + Path p; + p.addEllipse (x, y, width, height); + strokePath (p, PathStrokeType (lineThickness)); } void Graphics::fillRoundedRectangle (const float x, - const float y, - const float width, - const float height, - const float cornerSize) const throw() + const float y, + const float width, + const float height, + const float cornerSize) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (x, y, width, height)); - Path p; - p.addRoundedRectangle (x, y, width, height, cornerSize); - fillPath (p); + Path p; + p.addRoundedRectangle (x, y, width, height, cornerSize); + fillPath (p); } void Graphics::fillRoundedRectangle (const Rectangle& r, - const float cornerSize) const throw() + const float cornerSize) const throw() { - fillRoundedRectangle ((float) r.getX(), - (float) r.getY(), - (float) r.getWidth(), - (float) r.getHeight(), - cornerSize); + fillRoundedRectangle ((float) r.getX(), + (float) r.getY(), + (float) r.getWidth(), + (float) r.getHeight(), + cornerSize); } void Graphics::drawRoundedRectangle (const float x, - const float y, - const float width, - const float height, - const float cornerSize, - const float lineThickness) const throw() + const float y, + const float width, + const float height, + const float cornerSize, + const float lineThickness) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (x, y, width, height)); - Path p; - p.addRoundedRectangle (x, y, width, height, cornerSize); - strokePath (p, PathStrokeType (lineThickness)); + Path p; + p.addRoundedRectangle (x, y, width, height, cornerSize); + strokePath (p, PathStrokeType (lineThickness)); } void Graphics::drawRoundedRectangle (const Rectangle& r, - const float cornerSize, - const float lineThickness) const throw() + const float cornerSize, + const float lineThickness) const throw() { - drawRoundedRectangle ((float) r.getX(), - (float) r.getY(), - (float) r.getWidth(), - (float) r.getHeight(), - cornerSize, lineThickness); + drawRoundedRectangle ((float) r.getX(), + (float) r.getY(), + (float) r.getWidth(), + (float) r.getHeight(), + cornerSize, lineThickness); } void Graphics::drawArrow (const float startX, - const float startY, - const float endX, - const float endY, - const float lineThickness, - const float arrowheadWidth, - const float arrowheadLength) const throw() + const float startY, + const float endX, + const float endY, + const float lineThickness, + const float arrowheadWidth, + const float arrowheadLength) const throw() { - Path p; - p.addArrow (startX, startY, endX, endY, - lineThickness, arrowheadWidth, arrowheadLength); - fillPath (p); + Path p; + p.addArrow (startX, startY, endX, endY, + lineThickness, arrowheadWidth, arrowheadLength); + fillPath (p); } void Graphics::fillCheckerBoard (int x, int y, - int width, int height, - const int checkWidth, - const int checkHeight, - const Colour& colour1, - const Colour& colour2) const throw() + int width, int height, + const int checkWidth, + const int checkHeight, + const Colour& colour1, + const Colour& colour2) const throw() { - jassert (checkWidth > 0 && checkHeight > 0); // can't be zero or less! + jassert (checkWidth > 0 && checkHeight > 0); // can't be zero or less! - if (checkWidth > 0 && checkHeight > 0) - { - context->saveState(); + if (checkWidth > 0 && checkHeight > 0) + { + context->saveState(); - if (colour1 == colour2) - { - context->setFill (FillType (colour1)); - context->fillRect (Rectangle (x, y, width, height), false); - } - else - { - const Rectangle clip (context->getClipBounds()); + if (colour1 == colour2) + { + context->setFill (FillType (colour1)); + context->fillRect (Rectangle (x, y, width, height), false); + } + else + { + const Rectangle clip (context->getClipBounds()); - const int right = jmin (x + width, clip.getRight()); - const int bottom = jmin (y + height, clip.getBottom()); + const int right = jmin (x + width, clip.getRight()); + const int bottom = jmin (y + height, clip.getBottom()); - int cy = 0; - while (y < bottom) - { - int cx = cy; + int cy = 0; + while (y < bottom) + { + int cx = cy; - for (int xx = x; xx < right; xx += checkWidth) - { - context->setFill (FillType (((cx++ & 1) == 0) ? colour1 : colour2)); - context->fillRect (Rectangle (xx, y, jmin (checkWidth, right - xx), jmin (checkHeight, bottom - y)), - false); - } + for (int xx = x; xx < right; xx += checkWidth) + { + context->setFill (FillType (((cx++ & 1) == 0) ? colour1 : colour2)); + context->fillRect (Rectangle (xx, y, jmin (checkWidth, right - xx), jmin (checkHeight, bottom - y)), + false); + } - ++cy; - y += checkHeight; - } - } + ++cy; + y += checkHeight; + } + } - context->restoreState(); - } + context->restoreState(); + } } void Graphics::drawVerticalLine (const int x, float top, float bottom) const throw() { - context->drawVerticalLine (x, top, bottom); + context->drawVerticalLine (x, top, bottom); } void Graphics::drawHorizontalLine (const int y, float left, float right) const throw() { - context->drawHorizontalLine (y, left, right); + context->drawHorizontalLine (y, left, right); } void Graphics::drawLine (float x1, float y1, float x2, float y2) const throw() { - context->drawLine (x1, y1, x2, y2); + context->drawLine (x1, y1, x2, y2); } void Graphics::drawLine (const float startX, - const float startY, - const float endX, - const float endY, - const float lineThickness) const throw() + const float startY, + const float endX, + const float endY, + const float lineThickness) const throw() { - Path p; - p.addLineSegment (startX, startY, endX, endY, lineThickness); - fillPath (p); + Path p; + p.addLineSegment (startX, startY, endX, endY, lineThickness); + fillPath (p); } void Graphics::drawLine (const Line& line) const throw() { - drawLine (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY()); + drawLine (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY()); } void Graphics::drawLine (const Line& line, - const float lineThickness) const throw() + const float lineThickness) const throw() { - drawLine (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY(), lineThickness); + drawLine (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY(), lineThickness); } void Graphics::drawDashedLine (const float startX, - const float startY, - const float endX, - const float endY, - const float* const dashLengths, - const int numDashLengths, - const float lineThickness) const throw() + const float startY, + const float endX, + const float endY, + const float* const dashLengths, + const int numDashLengths, + const float lineThickness) const throw() { - const double dx = endX - startX; - const double dy = endY - startY; - const double totalLen = juce_hypot (dx, dy); + const double dx = endX - startX; + const double dy = endY - startY; + const double totalLen = juce_hypot (dx, dy); - if (totalLen >= 0.5) - { - const double onePixAlpha = 1.0 / totalLen; + if (totalLen >= 0.5) + { + const double onePixAlpha = 1.0 / totalLen; - double alpha = 0.0; - float x = startX; - float y = startY; - int n = 0; + double alpha = 0.0; + float x = startX; + float y = startY; + int n = 0; - while (alpha < 1.0f) - { - alpha = jmin (1.0, alpha + dashLengths[n++] * onePixAlpha); - n = n % numDashLengths; + while (alpha < 1.0f) + { + alpha = jmin (1.0, alpha + dashLengths[n++] * onePixAlpha); + n = n % numDashLengths; - const float oldX = x; - const float oldY = y; + const float oldX = x; + const float oldY = y; - x = (float) (startX + dx * alpha); - y = (float) (startY + dy * alpha); + x = (float) (startX + dx * alpha); + y = (float) (startY + dy * alpha); - if ((n & 1) != 0) - { - if (lineThickness != 1.0f) - drawLine (oldX, oldY, x, y, lineThickness); - else - drawLine (oldX, oldY, x, y); - } - } - } + if ((n & 1) != 0) + { + if (lineThickness != 1.0f) + drawLine (oldX, oldY, x, y, lineThickness); + else + drawLine (oldX, oldY, x, y); + } + } + } } void Graphics::setImageResamplingQuality (const Graphics::ResamplingQuality newQuality) throw() { - saveStateIfPending(); - context->setInterpolationQuality (newQuality); + saveStateIfPending(); + context->setInterpolationQuality (newQuality); } void Graphics::drawImageAt (const Image* const imageToDraw, - const int topLeftX, - const int topLeftY, - const bool fillAlphaChannelWithCurrentBrush) const throw() + const int topLeftX, + const int topLeftY, + const bool fillAlphaChannelWithCurrentBrush) const throw() { - if (imageToDraw != 0) - { - const int imageW = imageToDraw->getWidth(); - const int imageH = imageToDraw->getHeight(); + if (imageToDraw != 0) + { + const int imageW = imageToDraw->getWidth(); + const int imageH = imageToDraw->getHeight(); - drawImage (imageToDraw, - topLeftX, topLeftY, imageW, imageH, - 0, 0, imageW, imageH, - fillAlphaChannelWithCurrentBrush); - } + drawImage (imageToDraw, + topLeftX, topLeftY, imageW, imageH, + 0, 0, imageW, imageH, + fillAlphaChannelWithCurrentBrush); + } } void Graphics::drawImageWithin (const Image* const imageToDraw, - const int destX, - const int destY, - const int destW, - const int destH, - const RectanglePlacement& placementWithinTarget, - const bool fillAlphaChannelWithCurrentBrush) const throw() + const int destX, + const int destY, + const int destW, + const int destH, + const RectanglePlacement& placementWithinTarget, + const bool fillAlphaChannelWithCurrentBrush) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (destX, destY, destW, destH); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (destX, destY, destW, destH)); - if (imageToDraw != 0) - { - const int imageW = imageToDraw->getWidth(); - const int imageH = imageToDraw->getHeight(); + if (imageToDraw != 0) + { + const int imageW = imageToDraw->getWidth(); + const int imageH = imageToDraw->getHeight(); - if (imageW > 0 && imageH > 0) - { - double newX = 0.0, newY = 0.0; - double newW = imageW; - double newH = imageH; + if (imageW > 0 && imageH > 0) + { + double newX = 0.0, newY = 0.0; + double newW = imageW; + double newH = imageH; - placementWithinTarget.applyTo (newX, newY, newW, newH, - destX, destY, destW, destH); + placementWithinTarget.applyTo (newX, newY, newW, newH, + destX, destY, destW, destH); - if (newW > 0 && newH > 0) - { - drawImage (imageToDraw, - roundDoubleToInt (newX), roundDoubleToInt (newY), - roundDoubleToInt (newW), roundDoubleToInt (newH), - 0, 0, imageW, imageH, - fillAlphaChannelWithCurrentBrush); - } - } - } + if (newW > 0 && newH > 0) + { + drawImage (imageToDraw, + roundToInt (newX), roundToInt (newY), + roundToInt (newW), roundToInt (newH), + 0, 0, imageW, imageH, + fillAlphaChannelWithCurrentBrush); + } + } + } } void Graphics::drawImage (const Image* const imageToDraw, - int dx, int dy, int dw, int dh, - int sx, int sy, int sw, int sh, - const bool fillAlphaChannelWithCurrentBrush) const throw() + int dx, int dy, int dw, int dh, + int sx, int sy, int sw, int sh, + const bool fillAlphaChannelWithCurrentBrush) const throw() { - // passing in a silly number can cause maths problems in rendering! - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (dx, dy, dw, dh); - ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (sx, sy, sw, sh); + // passing in a silly number can cause maths problems in rendering! + jassert (areCoordsSensibleNumbers (dx, dy, dw, dh)); + jassert (areCoordsSensibleNumbers (sx, sy, sw, sh)); - if (context->clipRegionIntersects (Rectangle (dx, dy, dw, dh))) - { - drawImageTransformed (imageToDraw, Rectangle (sx, sy, sw, sh), - AffineTransform::scale (dw / (float) sw, dh / (float) sh) - .translated ((float) dx, (float) dy), - fillAlphaChannelWithCurrentBrush); - } + if (context->clipRegionIntersects (Rectangle (dx, dy, dw, dh))) + { + drawImageTransformed (imageToDraw, Rectangle (sx, sy, sw, sh), + AffineTransform::scale (dw / (float) sw, dh / (float) sh) + .translated ((float) dx, (float) dy), + fillAlphaChannelWithCurrentBrush); + } } void Graphics::drawImageTransformed (const Image* const imageToDraw, - const Rectangle& imageSubRegion, - const AffineTransform& transform, - const bool fillAlphaChannelWithCurrentBrush) const throw() + const Rectangle& imageSubRegion, + const AffineTransform& transform, + const bool fillAlphaChannelWithCurrentBrush) const throw() { - if (imageToDraw != 0 && ! context->isClipEmpty()) - { - const Rectangle srcClip (imageSubRegion.getIntersection (imageToDraw->getBounds())); + if (imageToDraw != 0 && ! context->isClipEmpty()) + { + const Rectangle srcClip (imageSubRegion.getIntersection (imageToDraw->getBounds())); - if (fillAlphaChannelWithCurrentBrush) - { - context->saveState(); - context->clipToImageAlpha (*imageToDraw, srcClip, transform); - fillAll(); - context->restoreState(); - } - else - { - context->drawImage (*imageToDraw, srcClip, transform, false); - } - } + if (fillAlphaChannelWithCurrentBrush) + { + context->saveState(); + context->clipToImageAlpha (*imageToDraw, srcClip, transform); + fillAll(); + context->restoreState(); + } + else + { + context->drawImage (*imageToDraw, srcClip, transform, false); + } + } } END_JUCE_NAMESPACE @@ -81211,56 +81003,56 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE Justification::Justification (const Justification& other) throw() - : flags (other.flags) + : flags (other.flags) { } const Justification& Justification::operator= (const Justification& other) throw() { - flags = other.flags; - return *this; + flags = other.flags; + return *this; } int Justification::getOnlyVerticalFlags() const throw() { - return flags & (top | bottom | verticallyCentred); + return flags & (top | bottom | verticallyCentred); } int Justification::getOnlyHorizontalFlags() const throw() { - return flags & (left | right | horizontallyCentred | horizontallyJustified); + return flags & (left | right | horizontallyCentred | horizontallyJustified); } void Justification::applyToRectangle (int& x, int& y, - const int w, const int h, - const int spaceX, const int spaceY, - const int spaceW, const int spaceH) const throw() + const int w, const int h, + const int spaceX, const int spaceY, + const int spaceW, const int spaceH) const throw() { - if ((flags & horizontallyCentred) != 0) - { - x = spaceX + ((spaceW - w) >> 1); - } - else if ((flags & right) != 0) - { - x = spaceX + spaceW - w; - } - else - { - x = spaceX; - } + if ((flags & horizontallyCentred) != 0) + { + x = spaceX + ((spaceW - w) >> 1); + } + else if ((flags & right) != 0) + { + x = spaceX + spaceW - w; + } + else + { + x = spaceX; + } - if ((flags & verticallyCentred) != 0) - { - y = spaceY + ((spaceH - h) >> 1); - } - else if ((flags & bottom) != 0) - { - y = spaceY + spaceH - h; - } - else - { - y = spaceY; - } + if ((flags & verticallyCentred) != 0) + { + y = spaceY + ((spaceH - h) >> 1); + } + else if ((flags & bottom) != 0) + { + y = spaceY + spaceH - h; + } + else + { + y = spaceY; + } } END_JUCE_NAMESPACE @@ -81285,48 +81077,48 @@ BEGIN_JUCE_NAMESPACE #endif LowLevelGraphicsPostScriptRenderer::LowLevelGraphicsPostScriptRenderer (OutputStream& resultingPostScript, - const String& documentTitle, - const int totalWidth_, - const int totalHeight_) - : out (resultingPostScript), - totalWidth (totalWidth_), - totalHeight (totalHeight_), - needToClip (true) + const String& documentTitle, + const int totalWidth_, + const int totalHeight_) + : out (resultingPostScript), + totalWidth (totalWidth_), + totalHeight (totalHeight_), + needToClip (true) { - stateStack.add (new SavedState()); - stateStack.getLast()->clip = Rectangle (0, 0, totalWidth_, totalHeight_); + stateStack.add (new SavedState()); + stateStack.getLast()->clip = Rectangle (0, 0, totalWidth_, totalHeight_); - const float scale = jmin ((520.0f / totalWidth_), (750.0f / totalHeight)); + const float scale = jmin ((520.0f / totalWidth_), (750.0f / totalHeight)); - out << "%!PS-Adobe-3.0 EPSF-3.0" - "\n%%BoundingBox: 0 0 600 824" - "\n%%Pages: 0" - "\n%%Creator: Raw Material Software JUCE" - "\n%%Title: " << documentTitle << - "\n%%CreationDate: none" - "\n%%LanguageLevel: 2" - "\n%%EndComments" - "\n%%BeginProlog" - "\n%%BeginResource: JRes" - "\n/bd {bind def} bind def" - "\n/c {setrgbcolor} bd" - "\n/m {moveto} bd" - "\n/l {lineto} bd" - "\n/rl {rlineto} bd" - "\n/ct {curveto} bd" - "\n/cp {closepath} bd" - "\n/pr {3 index 3 index moveto 1 index 0 rlineto 0 1 index rlineto pop neg 0 rlineto pop pop closepath} bd" - "\n/doclip {initclip newpath} bd" - "\n/endclip {clip newpath} bd" - "\n%%EndResource" - "\n%%EndProlog" - "\n%%BeginSetup" - "\n%%EndSetup" - "\n%%Page: 1 1" - "\n%%BeginPageSetup" - "\n%%EndPageSetup\n\n" - << "40 800 translate\n" - << scale << ' ' << scale << " scale\n\n"; + out << "%!PS-Adobe-3.0 EPSF-3.0" + "\n%%BoundingBox: 0 0 600 824" + "\n%%Pages: 0" + "\n%%Creator: Raw Material Software JUCE" + "\n%%Title: " << documentTitle << + "\n%%CreationDate: none" + "\n%%LanguageLevel: 2" + "\n%%EndComments" + "\n%%BeginProlog" + "\n%%BeginResource: JRes" + "\n/bd {bind def} bind def" + "\n/c {setrgbcolor} bd" + "\n/m {moveto} bd" + "\n/l {lineto} bd" + "\n/rl {rlineto} bd" + "\n/ct {curveto} bd" + "\n/cp {closepath} bd" + "\n/pr {3 index 3 index moveto 1 index 0 rlineto 0 1 index rlineto pop neg 0 rlineto pop pop closepath} bd" + "\n/doclip {initclip newpath} bd" + "\n/endclip {clip newpath} bd" + "\n%%EndResource" + "\n%%EndProlog" + "\n%%BeginSetup" + "\n%%EndSetup" + "\n%%Page: 1 1" + "\n%%BeginPageSetup" + "\n%%EndPageSetup\n\n" + << "40 800 translate\n" + << scale << ' ' << scale << " scale\n\n"; } LowLevelGraphicsPostScriptRenderer::~LowLevelGraphicsPostScriptRenderer() @@ -81335,72 +81127,72 @@ LowLevelGraphicsPostScriptRenderer::~LowLevelGraphicsPostScriptRenderer() bool LowLevelGraphicsPostScriptRenderer::isVectorDevice() const { - return true; + return true; } void LowLevelGraphicsPostScriptRenderer::setOrigin (int x, int y) { - if (x != 0 || y != 0) - { - stateStack.getLast()->xOffset += x; - stateStack.getLast()->yOffset += y; - needToClip = true; - } + if (x != 0 || y != 0) + { + stateStack.getLast()->xOffset += x; + stateStack.getLast()->yOffset += y; + needToClip = true; + } } bool LowLevelGraphicsPostScriptRenderer::clipToRectangle (const Rectangle& r) { - needToClip = true; - return stateStack.getLast()->clip.clipTo (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset)); + needToClip = true; + return stateStack.getLast()->clip.clipTo (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset)); } bool LowLevelGraphicsPostScriptRenderer::clipToRectangleList (const RectangleList& clipRegion) { - needToClip = true; - return stateStack.getLast()->clip.clipTo (clipRegion); + needToClip = true; + return stateStack.getLast()->clip.clipTo (clipRegion); } void LowLevelGraphicsPostScriptRenderer::excludeClipRectangle (const Rectangle& r) { - needToClip = true; - stateStack.getLast()->clip.subtract (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset)); + needToClip = true; + stateStack.getLast()->clip.subtract (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset)); } void LowLevelGraphicsPostScriptRenderer::clipToPath (const Path& path, const AffineTransform& transform) { - writeClip(); + writeClip(); - Path p (path); - p.applyTransform (transform.translated ((float) stateStack.getLast()->xOffset, (float) stateStack.getLast()->yOffset)); - writePath (p); - out << "clip\n"; + Path p (path); + p.applyTransform (transform.translated ((float) stateStack.getLast()->xOffset, (float) stateStack.getLast()->yOffset)); + writePath (p); + out << "clip\n"; } void LowLevelGraphicsPostScriptRenderer::clipToImageAlpha (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform) { - needToClip = true; - jassertfalse // xxx + needToClip = true; + jassertfalse // xxx } bool LowLevelGraphicsPostScriptRenderer::clipRegionIntersects (const Rectangle& r) { - return stateStack.getLast()->clip.intersectsRectangle (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset)); + return stateStack.getLast()->clip.intersectsRectangle (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset)); } const Rectangle LowLevelGraphicsPostScriptRenderer::getClipBounds() const { - return stateStack.getLast()->clip.getBounds().translated (-stateStack.getLast()->xOffset, - -stateStack.getLast()->yOffset); + return stateStack.getLast()->clip.getBounds().translated (-stateStack.getLast()->xOffset, + -stateStack.getLast()->yOffset); } bool LowLevelGraphicsPostScriptRenderer::isClipEmpty() const { - return stateStack.getLast()->clip.isEmpty(); + return stateStack.getLast()->clip.isEmpty(); } LowLevelGraphicsPostScriptRenderer::SavedState::SavedState() - : xOffset (0), - yOffset (0) + : xOffset (0), + yOffset (0) { } @@ -81410,151 +81202,151 @@ LowLevelGraphicsPostScriptRenderer::SavedState::~SavedState() void LowLevelGraphicsPostScriptRenderer::saveState() { - stateStack.add (new SavedState (*stateStack.getLast())); + stateStack.add (new SavedState (*stateStack.getLast())); } void LowLevelGraphicsPostScriptRenderer::restoreState() { - jassert (stateStack.size() > 0); + jassert (stateStack.size() > 0); - if (stateStack.size() > 0) - stateStack.removeLast(); + if (stateStack.size() > 0) + stateStack.removeLast(); } void LowLevelGraphicsPostScriptRenderer::writeClip() { - if (needToClip) - { - needToClip = false; + if (needToClip) + { + needToClip = false; - out << "doclip "; + out << "doclip "; - int itemsOnLine = 0; + int itemsOnLine = 0; - for (RectangleList::Iterator i (stateStack.getLast()->clip); i.next();) - { - if (++itemsOnLine == 6) - { - itemsOnLine = 0; - out << '\n'; - } + for (RectangleList::Iterator i (stateStack.getLast()->clip); i.next();) + { + if (++itemsOnLine == 6) + { + itemsOnLine = 0; + out << '\n'; + } - const Rectangle& r = *i.getRectangle(); + const Rectangle& r = *i.getRectangle(); - out << r.getX() << ' ' << -r.getY() << ' ' - << r.getWidth() << ' ' << -r.getHeight() << " pr "; - } + out << r.getX() << ' ' << -r.getY() << ' ' + << r.getWidth() << ' ' << -r.getHeight() << " pr "; + } - out << "endclip\n"; - } + out << "endclip\n"; + } } void LowLevelGraphicsPostScriptRenderer::writeColour (const Colour& colour) { - Colour c (Colours::white.overlaidWith (colour)); + Colour c (Colours::white.overlaidWith (colour)); - if (lastColour != c) - { - lastColour = c; + if (lastColour != c) + { + lastColour = c; - out << String (c.getFloatRed(), 3) << ' ' - << String (c.getFloatGreen(), 3) << ' ' - << String (c.getFloatBlue(), 3) << " c\n"; - } + out << String (c.getFloatRed(), 3) << ' ' + << String (c.getFloatGreen(), 3) << ' ' + << String (c.getFloatBlue(), 3) << " c\n"; + } } void LowLevelGraphicsPostScriptRenderer::writeXY (const float x, const float y) const { - out << String (x, 2) << ' ' - << String (-y, 2) << ' '; + out << String (x, 2) << ' ' + << String (-y, 2) << ' '; } void LowLevelGraphicsPostScriptRenderer::writePath (const Path& path) const { - out << "newpath "; + out << "newpath "; - float lastX = 0.0f; - float lastY = 0.0f; - int itemsOnLine = 0; + float lastX = 0.0f; + float lastY = 0.0f; + int itemsOnLine = 0; - Path::Iterator i (path); + Path::Iterator i (path); - while (i.next()) - { - if (++itemsOnLine == 4) - { - itemsOnLine = 0; - out << '\n'; - } + while (i.next()) + { + if (++itemsOnLine == 4) + { + itemsOnLine = 0; + out << '\n'; + } - switch (i.elementType) - { - case Path::Iterator::startNewSubPath: - writeXY (i.x1, i.y1); - lastX = i.x1; - lastY = i.y1; - out << "m "; - break; + switch (i.elementType) + { + case Path::Iterator::startNewSubPath: + writeXY (i.x1, i.y1); + lastX = i.x1; + lastY = i.y1; + out << "m "; + break; - case Path::Iterator::lineTo: - writeXY (i.x1, i.y1); - lastX = i.x1; - lastY = i.y1; - out << "l "; - break; + case Path::Iterator::lineTo: + writeXY (i.x1, i.y1); + lastX = i.x1; + lastY = i.y1; + out << "l "; + break; - case Path::Iterator::quadraticTo: - { - const float cp1x = lastX + (i.x1 - lastX) * 2.0f / 3.0f; - const float cp1y = lastY + (i.y1 - lastY) * 2.0f / 3.0f; - const float cp2x = cp1x + (i.x2 - lastX) / 3.0f; - const float cp2y = cp1y + (i.y2 - lastY) / 3.0f; + case Path::Iterator::quadraticTo: + { + const float cp1x = lastX + (i.x1 - lastX) * 2.0f / 3.0f; + const float cp1y = lastY + (i.y1 - lastY) * 2.0f / 3.0f; + const float cp2x = cp1x + (i.x2 - lastX) / 3.0f; + const float cp2y = cp1y + (i.y2 - lastY) / 3.0f; - writeXY (cp1x, cp1y); - writeXY (cp2x, cp2y); - writeXY (i.x2, i.y2); - out << "ct "; - lastX = i.x2; - lastY = i.y2; - } - break; + writeXY (cp1x, cp1y); + writeXY (cp2x, cp2y); + writeXY (i.x2, i.y2); + out << "ct "; + lastX = i.x2; + lastY = i.y2; + } + break; - case Path::Iterator::cubicTo: - writeXY (i.x1, i.y1); - writeXY (i.x2, i.y2); - writeXY (i.x3, i.y3); - out << "ct "; - lastX = i.x3; - lastY = i.y3; - break; + case Path::Iterator::cubicTo: + writeXY (i.x1, i.y1); + writeXY (i.x2, i.y2); + writeXY (i.x3, i.y3); + out << "ct "; + lastX = i.x3; + lastY = i.y3; + break; - case Path::Iterator::closePath: - out << "cp "; - break; + case Path::Iterator::closePath: + out << "cp "; + break; - default: - jassertfalse - break; - } - } + default: + jassertfalse + break; + } + } - out << '\n'; + out << '\n'; } void LowLevelGraphicsPostScriptRenderer::writeTransform (const AffineTransform& trans) const { - out << "[ " - << trans.mat00 << ' ' - << trans.mat10 << ' ' - << trans.mat01 << ' ' - << trans.mat11 << ' ' - << trans.mat02 << ' ' - << trans.mat12 << " ] concat "; + out << "[ " + << trans.mat00 << ' ' + << trans.mat10 << ' ' + << trans.mat01 << ' ' + << trans.mat11 << ' ' + << trans.mat02 << ' ' + << trans.mat12 << " ] concat "; } void LowLevelGraphicsPostScriptRenderer::setFill (const FillType& fillType) { - stateStack.getLast()->fillType = fillType; + stateStack.getLast()->fillType = fillType; } void LowLevelGraphicsPostScriptRenderer::setOpacity (float opacity) @@ -81567,200 +81359,199 @@ void LowLevelGraphicsPostScriptRenderer::setInterpolationQuality (Graphics::Resa void LowLevelGraphicsPostScriptRenderer::fillRect (const Rectangle& r, const bool /*replaceExistingContents*/) { - if (stateStack.getLast()->fillType.isColour()) - { - writeClip(); - writeColour (stateStack.getLast()->fillType.colour); + if (stateStack.getLast()->fillType.isColour()) + { + writeClip(); + writeColour (stateStack.getLast()->fillType.colour); - Rectangle r2 (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset)); + Rectangle r2 (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset)); - out << r2.getX() << ' ' << -r2.getBottom() << ' ' << r2.getWidth() << ' ' << r2.getHeight() << " rectfill\n"; - } - else - { - Path p; - p.addRectangle (r); - fillPath (p, AffineTransform::identity); - } + out << r2.getX() << ' ' << -r2.getBottom() << ' ' << r2.getWidth() << ' ' << r2.getHeight() << " rectfill\n"; + } + else + { + Path p; + p.addRectangle (r); + fillPath (p, AffineTransform::identity); + } } void LowLevelGraphicsPostScriptRenderer::fillPath (const Path& path, const AffineTransform& t) { - if (stateStack.getLast()->fillType.isColour()) - { - writeClip(); + if (stateStack.getLast()->fillType.isColour()) + { + writeClip(); - Path p (path); - p.applyTransform (t.translated ((float) stateStack.getLast()->xOffset, - (float) stateStack.getLast()->yOffset)); - writePath (p); + Path p (path); + p.applyTransform (t.translated ((float) stateStack.getLast()->xOffset, + (float) stateStack.getLast()->yOffset)); + writePath (p); - writeColour (stateStack.getLast()->fillType.colour); + writeColour (stateStack.getLast()->fillType.colour); - out << "fill\n"; - } - else if (stateStack.getLast()->fillType.isGradient()) - { - // this doesn't work correctly yet - it could be improved to handle solid gradients, but - // postscript can't do semi-transparent ones. - notPossibleInPostscriptAssert // you can disable this warning by setting the WARN_ABOUT_NON_POSTSCRIPT_OPERATIONS flag at the top of this file + out << "fill\n"; + } + else if (stateStack.getLast()->fillType.isGradient()) + { + // this doesn't work correctly yet - it could be improved to handle solid gradients, but + // postscript can't do semi-transparent ones. + notPossibleInPostscriptAssert // you can disable this warning by setting the WARN_ABOUT_NON_POSTSCRIPT_OPERATIONS flag at the top of this file - writeClip(); - out << "gsave "; + writeClip(); + out << "gsave "; - { - Path p (path); - p.applyTransform (t.translated ((float) stateStack.getLast()->xOffset, (float) stateStack.getLast()->yOffset)); - writePath (p); - out << "clip\n"; - } + { + Path p (path); + p.applyTransform (t.translated ((float) stateStack.getLast()->xOffset, (float) stateStack.getLast()->yOffset)); + writePath (p); + out << "clip\n"; + } - const Rectangle bounds (stateStack.getLast()->clip.getBounds()); + const Rectangle bounds (stateStack.getLast()->clip.getBounds()); - // ideally this would draw lots of lines or ellipses to approximate the gradient, but for the - // time-being, this just fills it with the average colour.. - writeColour (stateStack.getLast()->fillType.gradient->getColourAtPosition (0.5f)); - out << bounds.getX() << ' ' << -bounds.getBottom() << ' ' << bounds.getWidth() << ' ' << bounds.getHeight() << " rectfill\n"; + // ideally this would draw lots of lines or ellipses to approximate the gradient, but for the + // time-being, this just fills it with the average colour.. + writeColour (stateStack.getLast()->fillType.gradient->getColourAtPosition (0.5f)); + out << bounds.getX() << ' ' << -bounds.getBottom() << ' ' << bounds.getWidth() << ' ' << bounds.getHeight() << " rectfill\n"; - out << "grestore\n"; - } + out << "grestore\n"; + } } void LowLevelGraphicsPostScriptRenderer::writeImage (const Image& im, - const int sx, const int sy, - const int maxW, const int maxH) const + const int sx, const int sy, + const int maxW, const int maxH) const { - out << "{<\n"; + out << "{<\n"; - const int w = jmin (maxW, im.getWidth()); - const int h = jmin (maxH, im.getHeight()); + const int w = jmin (maxW, im.getWidth()); + const int h = jmin (maxH, im.getHeight()); - int charsOnLine = 0; - const Image::BitmapData srcData (im, 0, 0, w, h); - Colour pixel; + int charsOnLine = 0; + const Image::BitmapData srcData (im, 0, 0, w, h); + Colour pixel; - for (int y = h; --y >= 0;) - { - for (int x = 0; x < w; ++x) - { - const uint8* pixelData = srcData.getPixelPointer (x, y); + for (int y = h; --y >= 0;) + { + for (int x = 0; x < w; ++x) + { + const uint8* pixelData = srcData.getPixelPointer (x, y); - if (x >= sx && y >= sy) - { - if (im.isARGB()) - { - PixelARGB p (*(const PixelARGB*) pixelData); - p.unpremultiply(); - pixel = Colours::white.overlaidWith (Colour (p.getARGB())); - } - else if (im.isRGB()) - { - pixel = Colour (((const PixelRGB*) pixelData)->getARGB()); - } - else - { - pixel = Colour ((uint8) 0, (uint8) 0, (uint8) 0, *pixelData); - } - } - else - { - pixel = Colours::transparentWhite; - } + if (x >= sx && y >= sy) + { + if (im.isARGB()) + { + PixelARGB p (*(const PixelARGB*) pixelData); + p.unpremultiply(); + pixel = Colours::white.overlaidWith (Colour (p.getARGB())); + } + else if (im.isRGB()) + { + pixel = Colour (((const PixelRGB*) pixelData)->getARGB()); + } + else + { + pixel = Colour ((uint8) 0, (uint8) 0, (uint8) 0, *pixelData); + } + } + else + { + pixel = Colours::transparentWhite; + } - char colourString [16]; - sprintf (colourString, "%x%x%x", pixel.getRed(), pixel.getGreen(), pixel.getBlue()); + const uint8 pixelValues[3] = { pixel.getRed(), pixel.getGreen(), pixel.getBlue() }; - out << (const char*) colourString; - charsOnLine += 3; + out << String::toHexString (pixelValues, 3, 0); + charsOnLine += 3; - if (charsOnLine > 100) - { - out << '\n'; - charsOnLine = 0; - } - } - } + if (charsOnLine > 100) + { + out << '\n'; + charsOnLine = 0; + } + } + } - out << "\n>}\n"; + out << "\n>}\n"; } void LowLevelGraphicsPostScriptRenderer::drawImage (const Image& sourceImage, const Rectangle& srcClip, - const AffineTransform& transform, const bool fillEntireClipAsTiles) + const AffineTransform& transform, const bool fillEntireClipAsTiles) { - const int w = jmin (sourceImage.getWidth(), srcClip.getRight()); - const int h = jmin (sourceImage.getHeight(), srcClip.getBottom()); + const int w = jmin (sourceImage.getWidth(), srcClip.getRight()); + const int h = jmin (sourceImage.getHeight(), srcClip.getBottom()); - writeClip(); + writeClip(); - out << "gsave "; - writeTransform (transform.translated ((float) stateStack.getLast()->xOffset, (float) stateStack.getLast()->yOffset) - .scaled (1.0f, -1.0f)); + out << "gsave "; + writeTransform (transform.translated ((float) stateStack.getLast()->xOffset, (float) stateStack.getLast()->yOffset) + .scaled (1.0f, -1.0f)); - RectangleList imageClip; - sourceImage.createSolidAreaMask (imageClip, 0.5f); - imageClip.clipTo (srcClip); + RectangleList imageClip; + sourceImage.createSolidAreaMask (imageClip, 0.5f); + imageClip.clipTo (srcClip); - out << "newpath "; - int itemsOnLine = 0; + out << "newpath "; + int itemsOnLine = 0; - for (RectangleList::Iterator i (imageClip); i.next();) - { - if (++itemsOnLine == 6) - { - out << '\n'; - itemsOnLine = 0; - } + for (RectangleList::Iterator i (imageClip); i.next();) + { + if (++itemsOnLine == 6) + { + out << '\n'; + itemsOnLine = 0; + } - const Rectangle& r = *i.getRectangle(); + const Rectangle& r = *i.getRectangle(); - out << r.getX() << ' ' << r.getY() << ' ' << r.getWidth() << ' ' << r.getHeight() << " pr "; - } + out << r.getX() << ' ' << r.getY() << ' ' << r.getWidth() << ' ' << r.getHeight() << " pr "; + } - out << " clip newpath\n"; + out << " clip newpath\n"; - out << w << ' ' << h << " scale\n"; - out << w << ' ' << h << " 8 [" << w << " 0 0 -" << h << ' ' << (int) 0 << ' ' << h << " ]\n"; + out << w << ' ' << h << " scale\n"; + out << w << ' ' << h << " 8 [" << w << " 0 0 -" << h << ' ' << (int) 0 << ' ' << h << " ]\n"; - writeImage (sourceImage, srcClip.getX(), srcClip.getY(), srcClip.getWidth(), srcClip.getHeight()); + writeImage (sourceImage, srcClip.getX(), srcClip.getY(), srcClip.getWidth(), srcClip.getHeight()); - out << "false 3 colorimage grestore\n"; - needToClip = true; + out << "false 3 colorimage grestore\n"; + needToClip = true; } void LowLevelGraphicsPostScriptRenderer::drawLine (double x1, double y1, double x2, double y2) { - Path p; - p.addLineSegment ((float) x1, (float) y1, (float) x2, (float) y2, 1.0f); - fillPath (p, AffineTransform::identity); + Path p; + p.addLineSegment ((float) x1, (float) y1, (float) x2, (float) y2, 1.0f); + fillPath (p, AffineTransform::identity); } void LowLevelGraphicsPostScriptRenderer::drawVerticalLine (const int x, double top, double bottom) { - drawLine (x, top, x, bottom); + drawLine (x, top, x, bottom); } void LowLevelGraphicsPostScriptRenderer::drawHorizontalLine (const int y, double left, double right) { - drawLine (left, y, right, y); + drawLine (left, y, right, y); } void LowLevelGraphicsPostScriptRenderer::setFont (const Font& newFont) { - stateStack.getLast()->font = newFont; + stateStack.getLast()->font = newFont; } const Font LowLevelGraphicsPostScriptRenderer::getFont() { - return stateStack.getLast()->font; + return stateStack.getLast()->font; } void LowLevelGraphicsPostScriptRenderer::drawGlyph (int glyphNumber, const AffineTransform& transform) { - Path p; - Font& font = stateStack.getLast()->font; - font.getTypeface()->getOutlineForGlyph (glyphNumber, p); - fillPath (p, AffineTransform::scale (font.getHeight() * font.getHorizontalScale(), font.getHeight()).followedBy (transform)); + Path p; + Font& font = stateStack.getLast()->font; + font.getTypeface()->getOutlineForGlyph (glyphNumber, p); + fillPath (p, AffineTransform::scale (font.getHeight() * font.getHorizontalScale(), font.getHeight()).followedBy (transform)); } END_JUCE_NAMESPACE @@ -81787,1276 +81578,1276 @@ template class SolidColourEdgeTableRenderer { public: - SolidColourEdgeTableRenderer (const Image::BitmapData& data_, const PixelARGB& colour) throw() - : data (data_), - sourceColour (colour) - { - if (sizeof (PixelType) == 3) - { - areRGBComponentsEqual = sourceColour.getRed() == sourceColour.getGreen() - && sourceColour.getGreen() == sourceColour.getBlue(); - filler[0].set (sourceColour); - filler[1].set (sourceColour); - filler[2].set (sourceColour); - filler[3].set (sourceColour); - } - } + SolidColourEdgeTableRenderer (const Image::BitmapData& data_, const PixelARGB& colour) throw() + : data (data_), + sourceColour (colour) + { + if (sizeof (PixelType) == 3) + { + areRGBComponentsEqual = sourceColour.getRed() == sourceColour.getGreen() + && sourceColour.getGreen() == sourceColour.getBlue(); + filler[0].set (sourceColour); + filler[1].set (sourceColour); + filler[2].set (sourceColour); + filler[3].set (sourceColour); + } + } - forcedinline void setEdgeTableYPos (const int y) throw() - { - linePixels = (PixelType*) data.getLinePointer (y); - } + forcedinline void setEdgeTableYPos (const int y) throw() + { + linePixels = (PixelType*) data.getLinePointer (y); + } - forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const throw() - { - if (replaceExisting) - linePixels[x].set (sourceColour); - else - linePixels[x].blend (sourceColour, alphaLevel); - } + forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const throw() + { + if (replaceExisting) + linePixels[x].set (sourceColour); + else + linePixels[x].blend (sourceColour, alphaLevel); + } - forcedinline void handleEdgeTableLine (const int x, int width, const int alphaLevel) const throw() - { - PixelARGB p (sourceColour); - p.multiplyAlpha (alphaLevel); + forcedinline void handleEdgeTableLine (const int x, int width, const int alphaLevel) const throw() + { + PixelARGB p (sourceColour); + p.multiplyAlpha (alphaLevel); - PixelType* dest = linePixels + x; + PixelType* dest = linePixels + x; - if (replaceExisting || p.getAlpha() >= 0xff) - replaceLine (dest, p, width); - else - blendLine (dest, p, width); - } + if (replaceExisting || p.getAlpha() >= 0xff) + replaceLine (dest, p, width); + else + blendLine (dest, p, width); + } private: - const Image::BitmapData& data; - PixelType* linePixels; - PixelARGB sourceColour; - PixelRGB filler [4]; - bool areRGBComponentsEqual; + const Image::BitmapData& data; + PixelType* linePixels; + PixelARGB sourceColour; + PixelRGB filler [4]; + bool areRGBComponentsEqual; - forcedinline void blendLine (PixelType* dest, const PixelARGB& colour, int width) const - { - do - { - dest->blend (colour); - ++dest; - } while (--width > 0); - } + forcedinline void blendLine (PixelType* dest, const PixelARGB& colour, int width) const + { + do + { + dest->blend (colour); + ++dest; + } while (--width > 0); + } - forcedinline void replaceLine (PixelRGB* dest, const PixelARGB& colour, int width) const throw() - { - if (areRGBComponentsEqual) // if all the component values are the same, we can cheat.. - { - memset (dest, colour.getRed(), width * 3); - } - else - { - if (width >> 5) - { - const int* const intFiller = (const int*) filler; + forcedinline void replaceLine (PixelRGB* dest, const PixelARGB& colour, int width) const throw() + { + if (areRGBComponentsEqual) // if all the component values are the same, we can cheat.. + { + memset (dest, colour.getRed(), width * 3); + } + else + { + if (width >> 5) + { + const int* const intFiller = (const int*) filler; - while (width > 8 && (((pointer_sized_int) dest) & 7) != 0) - { - dest->set (colour); - ++dest; - --width; - } + while (width > 8 && (((pointer_sized_int) dest) & 7) != 0) + { + dest->set (colour); + ++dest; + --width; + } - while (width > 4) - { - ((int*) dest) [0] = intFiller[0]; - ((int*) dest) [1] = intFiller[1]; - ((int*) dest) [2] = intFiller[2]; - dest = (PixelRGB*) (((uint8*) dest) + 12); - width -= 4; - } - } + while (width > 4) + { + ((int*) dest) [0] = intFiller[0]; + ((int*) dest) [1] = intFiller[1]; + ((int*) dest) [2] = intFiller[2]; + dest = (PixelRGB*) (((uint8*) dest) + 12); + width -= 4; + } + } - while (--width >= 0) - { - dest->set (colour); - ++dest; - } - } - } + while (--width >= 0) + { + dest->set (colour); + ++dest; + } + } + } - forcedinline void replaceLine (PixelAlpha* dest, const PixelARGB& colour, int width) const throw() - { - memset (dest, colour.getAlpha(), width); - } + forcedinline void replaceLine (PixelAlpha* dest, const PixelARGB& colour, int width) const throw() + { + memset (dest, colour.getAlpha(), width); + } - forcedinline void replaceLine (PixelARGB* dest, const PixelARGB& colour, int width) const throw() - { - do - { - dest->set (colour); - ++dest; + forcedinline void replaceLine (PixelARGB* dest, const PixelARGB& colour, int width) const throw() + { + do + { + dest->set (colour); + ++dest; - } while (--width > 0); - } + } while (--width > 0); + } - SolidColourEdgeTableRenderer (const SolidColourEdgeTableRenderer&); - const SolidColourEdgeTableRenderer& operator= (const SolidColourEdgeTableRenderer&); + SolidColourEdgeTableRenderer (const SolidColourEdgeTableRenderer&); + const SolidColourEdgeTableRenderer& operator= (const SolidColourEdgeTableRenderer&); }; class LinearGradientPixelGenerator { public: - LinearGradientPixelGenerator (const ColourGradient& gradient, const AffineTransform& transform, const PixelARGB* const lookupTable_, const int numEntries_) - : lookupTable (lookupTable_), numEntries (numEntries_) - { - jassert (numEntries_ >= 0); - float x1 = gradient.x1; - float y1 = gradient.y1; - float x2 = gradient.x2; - float y2 = gradient.y2; + LinearGradientPixelGenerator (const ColourGradient& gradient, const AffineTransform& transform, const PixelARGB* const lookupTable_, const int numEntries_) + : lookupTable (lookupTable_), numEntries (numEntries_) + { + jassert (numEntries_ >= 0); + float x1 = gradient.x1; + float y1 = gradient.y1; + float x2 = gradient.x2; + float y2 = gradient.y2; - if (! transform.isIdentity()) - { - const Line l (x2, y2, x1, y1); - const Point p3 = l.getPointAlongLine (0.0f, 100.0f); - float x3 = p3.getX(); - float y3 = p3.getY(); + if (! transform.isIdentity()) + { + const Line l (x2, y2, x1, y1); + const Point p3 = l.getPointAlongLine (0.0f, 100.0f); + float x3 = p3.getX(); + float y3 = p3.getY(); - transform.transformPoint (x1, y1); - transform.transformPoint (x2, y2); - transform.transformPoint (x3, y3); + transform.transformPoint (x1, y1); + transform.transformPoint (x2, y2); + transform.transformPoint (x3, y3); - const Line l2 (x2, y2, x3, y3); - const float prop = l2.findNearestPointTo (x1, y1); - const Point newP2 (l2.getPointAlongLineProportionally (prop)); + const Line l2 (x2, y2, x3, y3); + const float prop = l2.findNearestPointTo (x1, y1); + const Point newP2 (l2.getPointAlongLineProportionally (prop)); - x2 = newP2.getX(); - y2 = newP2.getY(); - } + x2 = newP2.getX(); + y2 = newP2.getY(); + } - vertical = fabs (x1 - x2) < 0.001f; - horizontal = fabs (y1 - y2) < 0.001f; + vertical = fabs (x1 - x2) < 0.001f; + horizontal = fabs (y1 - y2) < 0.001f; - if (vertical) - { - scale = roundDoubleToInt ((numEntries << (int) numScaleBits) / (double) (y2 - y1)); - start = roundDoubleToInt (y1 * scale); - } - else if (horizontal) - { - scale = roundDoubleToInt ((numEntries << (int) numScaleBits) / (double) (x2 - x1)); - start = roundDoubleToInt (x1 * scale); - } - else - { - grad = (y2 - y1) / (double) (x1 - x2); - yTerm = y1 - x1 / grad; - scale = roundDoubleToInt ((numEntries << (int) numScaleBits) / (yTerm * grad - (y2 * grad - x2))); - grad *= scale; - } - } + if (vertical) + { + scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (y2 - y1)); + start = roundToInt (y1 * scale); + } + else if (horizontal) + { + scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (x2 - x1)); + start = roundToInt (x1 * scale); + } + else + { + grad = (y2 - y1) / (double) (x1 - x2); + yTerm = y1 - x1 / grad; + scale = roundToInt ((numEntries << (int) numScaleBits) / (yTerm * grad - (y2 * grad - x2))); + grad *= scale; + } + } - forcedinline void setY (const int y) throw() - { - if (vertical) - linePix = lookupTable [jlimit (0, numEntries, (y * scale - start) >> (int) numScaleBits)]; - else if (! horizontal) - start = roundDoubleToInt ((y - yTerm) * grad); - } + forcedinline void setY (const int y) throw() + { + if (vertical) + linePix = lookupTable [jlimit (0, numEntries, (y * scale - start) >> (int) numScaleBits)]; + else if (! horizontal) + start = roundToInt ((y - yTerm) * grad); + } - forcedinline const PixelARGB getPixel (const int x) const throw() - { - return vertical ? linePix - : lookupTable [jlimit (0, numEntries, (x * scale - start) >> (int) numScaleBits)]; - } + forcedinline const PixelARGB getPixel (const int x) const throw() + { + return vertical ? linePix + : lookupTable [jlimit (0, numEntries, (x * scale - start) >> (int) numScaleBits)]; + } private: - const PixelARGB* const lookupTable; - const int numEntries; - PixelARGB linePix; - int start, scale; - double grad, yTerm; - bool vertical, horizontal; - enum { numScaleBits = 12 }; + const PixelARGB* const lookupTable; + const int numEntries; + PixelARGB linePix; + int start, scale; + double grad, yTerm; + bool vertical, horizontal; + enum { numScaleBits = 12 }; - LinearGradientPixelGenerator (const LinearGradientPixelGenerator&); - const LinearGradientPixelGenerator& operator= (const LinearGradientPixelGenerator&); + LinearGradientPixelGenerator (const LinearGradientPixelGenerator&); + const LinearGradientPixelGenerator& operator= (const LinearGradientPixelGenerator&); }; class RadialGradientPixelGenerator { public: - RadialGradientPixelGenerator (const ColourGradient& gradient, const AffineTransform&, - const PixelARGB* const lookupTable_, const int numEntries_) throw() - : lookupTable (lookupTable_), - numEntries (numEntries_), - gx1 (gradient.x1), - gy1 (gradient.y1) - { - jassert (numEntries_ >= 0); - const float gdx = gradient.x1 - gradient.x2; - const float gdy = gradient.y1 - gradient.y2; - maxDist = gdx * gdx + gdy * gdy; - invScale = numEntries / sqrt (maxDist); - jassert (roundDoubleToInt (sqrt (maxDist) * invScale) <= numEntries); - } + RadialGradientPixelGenerator (const ColourGradient& gradient, const AffineTransform&, + const PixelARGB* const lookupTable_, const int numEntries_) throw() + : lookupTable (lookupTable_), + numEntries (numEntries_), + gx1 (gradient.x1), + gy1 (gradient.y1) + { + jassert (numEntries_ >= 0); + const float gdx = gradient.x1 - gradient.x2; + const float gdy = gradient.y1 - gradient.y2; + maxDist = gdx * gdx + gdy * gdy; + invScale = numEntries / sqrt (maxDist); + jassert (roundToInt (sqrt (maxDist) * invScale) <= numEntries); + } - forcedinline void setY (const int y) throw() - { - dy = y - gy1; - dy *= dy; - } + forcedinline void setY (const int y) throw() + { + dy = y - gy1; + dy *= dy; + } - forcedinline const PixelARGB getPixel (const int px) const throw() - { - double x = px - gx1; - x *= x; - x += dy; + forcedinline const PixelARGB getPixel (const int px) const throw() + { + double x = px - gx1; + x *= x; + x += dy; - return lookupTable [x >= maxDist ? numEntries : roundDoubleToInt (sqrt (x) * invScale)]; - } + return lookupTable [x >= maxDist ? numEntries : roundToInt (sqrt (x) * invScale)]; + } protected: - const PixelARGB* const lookupTable; - const int numEntries; - const double gx1, gy1; - double maxDist, invScale, dy; + const PixelARGB* const lookupTable; + const int numEntries; + const double gx1, gy1; + double maxDist, invScale, dy; - RadialGradientPixelGenerator (const RadialGradientPixelGenerator&); - const RadialGradientPixelGenerator& operator= (const RadialGradientPixelGenerator&); + RadialGradientPixelGenerator (const RadialGradientPixelGenerator&); + const RadialGradientPixelGenerator& operator= (const RadialGradientPixelGenerator&); }; class TransformedRadialGradientPixelGenerator : public RadialGradientPixelGenerator { public: - TransformedRadialGradientPixelGenerator (const ColourGradient& gradient, const AffineTransform& transform, - const PixelARGB* const lookupTable_, const int numEntries_) throw() - : RadialGradientPixelGenerator (gradient, transform, lookupTable_, numEntries_), - inverseTransform (transform.inverted()) - { - tM10 = inverseTransform.mat10; - tM00 = inverseTransform.mat00; - } + TransformedRadialGradientPixelGenerator (const ColourGradient& gradient, const AffineTransform& transform, + const PixelARGB* const lookupTable_, const int numEntries_) throw() + : RadialGradientPixelGenerator (gradient, transform, lookupTable_, numEntries_), + inverseTransform (transform.inverted()) + { + tM10 = inverseTransform.mat10; + tM00 = inverseTransform.mat00; + } - forcedinline void setY (const int y) throw() - { - lineYM01 = inverseTransform.mat01 * y + inverseTransform.mat02 - gx1; - lineYM11 = inverseTransform.mat11 * y + inverseTransform.mat12 - gy1; - } + forcedinline void setY (const int y) throw() + { + lineYM01 = inverseTransform.mat01 * y + inverseTransform.mat02 - gx1; + lineYM11 = inverseTransform.mat11 * y + inverseTransform.mat12 - gy1; + } - forcedinline const PixelARGB getPixel (const int px) const throw() - { - double x = px; - const double y = tM10 * x + lineYM11; - x = tM00 * x + lineYM01; - x *= x; - x += y * y; + forcedinline const PixelARGB getPixel (const int px) const throw() + { + double x = px; + const double y = tM10 * x + lineYM11; + x = tM00 * x + lineYM01; + x *= x; + x += y * y; - if (x >= maxDist) - return lookupTable [numEntries]; - else - return lookupTable [jmin (numEntries, roundDoubleToInt (sqrt (x) * invScale))]; - } + if (x >= maxDist) + return lookupTable [numEntries]; + else + return lookupTable [jmin (numEntries, roundToInt (sqrt (x) * invScale))]; + } private: - double tM10, tM00, lineYM01, lineYM11; - const AffineTransform inverseTransform; + double tM10, tM00, lineYM01, lineYM11; + const AffineTransform inverseTransform; - TransformedRadialGradientPixelGenerator (const TransformedRadialGradientPixelGenerator&); - const TransformedRadialGradientPixelGenerator& operator= (const TransformedRadialGradientPixelGenerator&); + TransformedRadialGradientPixelGenerator (const TransformedRadialGradientPixelGenerator&); + const TransformedRadialGradientPixelGenerator& operator= (const TransformedRadialGradientPixelGenerator&); }; template class GradientEdgeTableRenderer : public GradientType { public: - GradientEdgeTableRenderer (const Image::BitmapData& destData_, const ColourGradient& gradient, const AffineTransform& transform, - const PixelARGB* const lookupTable_, const int numEntries_) throw() - : GradientType (gradient, transform, lookupTable_, numEntries_ - 1), - destData (destData_) - { - } + GradientEdgeTableRenderer (const Image::BitmapData& destData_, const ColourGradient& gradient, const AffineTransform& transform, + const PixelARGB* const lookupTable_, const int numEntries_) throw() + : GradientType (gradient, transform, lookupTable_, numEntries_ - 1), + destData (destData_) + { + } - forcedinline void setEdgeTableYPos (const int y) throw() - { - linePixels = (PixelType*) destData.getLinePointer (y); - GradientType::setY (y); - } + forcedinline void setEdgeTableYPos (const int y) throw() + { + linePixels = (PixelType*) destData.getLinePointer (y); + GradientType::setY (y); + } - forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const throw() - { - linePixels[x].blend (GradientType::getPixel (x), alphaLevel); - } + forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const throw() + { + linePixels[x].blend (GradientType::getPixel (x), alphaLevel); + } - forcedinline void handleEdgeTableLine (int x, int width, const int alphaLevel) const throw() - { - PixelType* dest = linePixels + x; + forcedinline void handleEdgeTableLine (int x, int width, const int alphaLevel) const throw() + { + PixelType* dest = linePixels + x; - if (alphaLevel < 0xff) - { - do - { - (dest++)->blend (GradientType::getPixel (x++), alphaLevel); - } while (--width > 0); - } - else - { - do - { - (dest++)->blend (GradientType::getPixel (x++)); - } while (--width > 0); - } - } + if (alphaLevel < 0xff) + { + do + { + (dest++)->blend (GradientType::getPixel (x++), alphaLevel); + } while (--width > 0); + } + else + { + do + { + (dest++)->blend (GradientType::getPixel (x++)); + } while (--width > 0); + } + } private: - const Image::BitmapData& destData; - PixelType* linePixels; + const Image::BitmapData& destData; + PixelType* linePixels; - GradientEdgeTableRenderer (const GradientEdgeTableRenderer&); - const GradientEdgeTableRenderer& operator= (const GradientEdgeTableRenderer&); + GradientEdgeTableRenderer (const GradientEdgeTableRenderer&); + const GradientEdgeTableRenderer& operator= (const GradientEdgeTableRenderer&); }; static forcedinline int safeModulo (int n, const int divisor) throw() { - jassert (divisor > 0); - n %= divisor; - return (n < 0) ? (n + divisor) : n; + jassert (divisor > 0); + n %= divisor; + return (n < 0) ? (n + divisor) : n; } template class ImageFillEdgeTableRenderer { public: - ImageFillEdgeTableRenderer (const Image::BitmapData& destData_, - const Image::BitmapData& srcData_, - const int extraAlpha_, - const int x, const int y) throw() - : destData (destData_), - srcData (srcData_), - extraAlpha (extraAlpha_ + 1), - xOffset (repeatPattern ? safeModulo (x, srcData_.width) - srcData_.width : x), - yOffset (repeatPattern ? safeModulo (y, srcData_.height) - srcData_.height : y) - { - } + ImageFillEdgeTableRenderer (const Image::BitmapData& destData_, + const Image::BitmapData& srcData_, + const int extraAlpha_, + const int x, const int y) throw() + : destData (destData_), + srcData (srcData_), + extraAlpha (extraAlpha_ + 1), + xOffset (repeatPattern ? safeModulo (x, srcData_.width) - srcData_.width : x), + yOffset (repeatPattern ? safeModulo (y, srcData_.height) - srcData_.height : y) + { + } - forcedinline void setEdgeTableYPos (int y) throw() - { - linePixels = (DestPixelType*) destData.getLinePointer (y); + forcedinline void setEdgeTableYPos (int y) throw() + { + linePixels = (DestPixelType*) destData.getLinePointer (y); - y -= yOffset; - if (repeatPattern) - { - jassert (y >= 0); - y %= srcData.height; - } + y -= yOffset; + if (repeatPattern) + { + jassert (y >= 0); + y %= srcData.height; + } - sourceLineStart = (SrcPixelType*) srcData.getLinePointer (y); - } + sourceLineStart = (SrcPixelType*) srcData.getLinePointer (y); + } - forcedinline void handleEdgeTablePixel (int x, int alphaLevel) const throw() - { - alphaLevel = (alphaLevel * extraAlpha) >> 8; + forcedinline void handleEdgeTablePixel (int x, int alphaLevel) const throw() + { + alphaLevel = (alphaLevel * extraAlpha) >> 8; - linePixels[x].blend (sourceLineStart [repeatPattern ? ((x - xOffset) % srcData.width) : (x - xOffset)], alphaLevel); - } + linePixels[x].blend (sourceLineStart [repeatPattern ? ((x - xOffset) % srcData.width) : (x - xOffset)], alphaLevel); + } - forcedinline void handleEdgeTableLine (int x, int width, int alphaLevel) const throw() - { - DestPixelType* dest = linePixels + x; - alphaLevel = (alphaLevel * extraAlpha) >> 8; - x -= xOffset; + forcedinline void handleEdgeTableLine (int x, int width, int alphaLevel) const throw() + { + DestPixelType* dest = linePixels + x; + alphaLevel = (alphaLevel * extraAlpha) >> 8; + x -= xOffset; - jassert (repeatPattern || (x >= 0 && x + width <= srcData.width)); + jassert (repeatPattern || (x >= 0 && x + width <= srcData.width)); - if (alphaLevel < 0xfe) - { - do - { - dest++ ->blend (sourceLineStart [repeatPattern ? (x++ % srcData.width) : x++], alphaLevel); - } while (--width > 0); - } - else - { - if (repeatPattern) - { - do - { - dest++ ->blend (sourceLineStart [x++ % srcData.width]); - } while (--width > 0); - } - else - { - copyRow (dest, sourceLineStart + x, width); - } - } - } + if (alphaLevel < 0xfe) + { + do + { + dest++ ->blend (sourceLineStart [repeatPattern ? (x++ % srcData.width) : x++], alphaLevel); + } while (--width > 0); + } + else + { + if (repeatPattern) + { + do + { + dest++ ->blend (sourceLineStart [x++ % srcData.width]); + } while (--width > 0); + } + else + { + copyRow (dest, sourceLineStart + x, width); + } + } + } - void clipEdgeTableLine (EdgeTable& et, int x, int y, int width) throw() - { - jassert (x - xOffset >= 0 && x + width - xOffset <= srcData.width); - SrcPixelType* s = (SrcPixelType*) srcData.getLinePointer (y - yOffset); - uint8* mask = (uint8*) (s + x - xOffset); + void clipEdgeTableLine (EdgeTable& et, int x, int y, int width) throw() + { + jassert (x - xOffset >= 0 && x + width - xOffset <= srcData.width); + SrcPixelType* s = (SrcPixelType*) srcData.getLinePointer (y - yOffset); + uint8* mask = (uint8*) (s + x - xOffset); - if (sizeof (SrcPixelType) == sizeof (PixelARGB)) - mask += PixelARGB::indexA; + if (sizeof (SrcPixelType) == sizeof (PixelARGB)) + mask += PixelARGB::indexA; - et.clipLineToMask (x, y, mask, sizeof (SrcPixelType), width); - } + et.clipLineToMask (x, y, mask, sizeof (SrcPixelType), width); + } private: - const Image::BitmapData& destData; - const Image::BitmapData& srcData; - const int extraAlpha, xOffset, yOffset; - DestPixelType* linePixels; - SrcPixelType* sourceLineStart; + const Image::BitmapData& destData; + const Image::BitmapData& srcData; + const int extraAlpha, xOffset, yOffset; + DestPixelType* linePixels; + SrcPixelType* sourceLineStart; - template - forcedinline static void copyRow (PixelType1* dest, PixelType2* src, int width) throw() - { - do - { - dest++ ->blend (*src++); - } while (--width > 0); - } + template + forcedinline static void copyRow (PixelType1* dest, PixelType2* src, int width) throw() + { + do + { + dest++ ->blend (*src++); + } while (--width > 0); + } - forcedinline static void copyRow (PixelRGB* dest, PixelRGB* src, int width) throw() - { - memcpy (dest, src, width * sizeof (PixelRGB)); - } + forcedinline static void copyRow (PixelRGB* dest, PixelRGB* src, int width) throw() + { + memcpy (dest, src, width * sizeof (PixelRGB)); + } - ImageFillEdgeTableRenderer (const ImageFillEdgeTableRenderer&); - const ImageFillEdgeTableRenderer& operator= (const ImageFillEdgeTableRenderer&); + ImageFillEdgeTableRenderer (const ImageFillEdgeTableRenderer&); + const ImageFillEdgeTableRenderer& operator= (const ImageFillEdgeTableRenderer&); }; template class TransformedImageFillEdgeTableRenderer { public: - TransformedImageFillEdgeTableRenderer (const Image::BitmapData& destData_, - const Image::BitmapData& srcData_, - const AffineTransform& transform, - const int extraAlpha_, - const bool betterQuality_) throw() - : interpolator (transform), - destData (destData_), - srcData (srcData_), - extraAlpha (extraAlpha_ + 1), - betterQuality (betterQuality_), - pixelOffset (betterQuality_ ? 0.5f : 0.0f), - pixelOffsetInt (betterQuality_ ? -128 : 0), - maxX (srcData_.width - 1), - maxY (srcData_.height - 1), - scratchSize (2048) - { - scratchBuffer.malloc (scratchSize); - } + TransformedImageFillEdgeTableRenderer (const Image::BitmapData& destData_, + const Image::BitmapData& srcData_, + const AffineTransform& transform, + const int extraAlpha_, + const bool betterQuality_) throw() + : interpolator (transform), + destData (destData_), + srcData (srcData_), + extraAlpha (extraAlpha_ + 1), + betterQuality (betterQuality_), + pixelOffset (betterQuality_ ? 0.5f : 0.0f), + pixelOffsetInt (betterQuality_ ? -128 : 0), + maxX (srcData_.width - 1), + maxY (srcData_.height - 1), + scratchSize (2048) + { + scratchBuffer.malloc (scratchSize); + } - ~TransformedImageFillEdgeTableRenderer() throw() - { - } + ~TransformedImageFillEdgeTableRenderer() throw() + { + } - forcedinline void setEdgeTableYPos (const int newY) throw() - { - y = newY; - linePixels = (DestPixelType*) destData.getLinePointer (newY); - } + forcedinline void setEdgeTableYPos (const int newY) throw() + { + y = newY; + linePixels = (DestPixelType*) destData.getLinePointer (newY); + } - forcedinline void handleEdgeTablePixel (const int x, int alphaLevel) throw() - { - alphaLevel *= extraAlpha; - alphaLevel >>= 8; + forcedinline void handleEdgeTablePixel (const int x, int alphaLevel) throw() + { + alphaLevel *= extraAlpha; + alphaLevel >>= 8; - SrcPixelType p; - generate (&p, x, 1); + SrcPixelType p; + generate (&p, x, 1); - linePixels[x].blend (p, alphaLevel); - } + linePixels[x].blend (p, alphaLevel); + } - forcedinline void handleEdgeTableLine (const int x, int width, int alphaLevel) throw() - { - if (width > scratchSize) - { - scratchSize = width; - scratchBuffer.malloc (scratchSize); - } + forcedinline void handleEdgeTableLine (const int x, int width, int alphaLevel) throw() + { + if (width > scratchSize) + { + scratchSize = width; + scratchBuffer.malloc (scratchSize); + } - SrcPixelType* span = scratchBuffer; - generate (span, x, width); + SrcPixelType* span = scratchBuffer; + generate (span, x, width); - DestPixelType* dest = linePixels + x; - alphaLevel *= extraAlpha; - alphaLevel >>= 8; + DestPixelType* dest = linePixels + x; + alphaLevel *= extraAlpha; + alphaLevel >>= 8; - if (alphaLevel < 0xfe) - { - do - { - dest++ ->blend (*span++, alphaLevel); - } while (--width > 0); - } - else - { - do - { - dest++ ->blend (*span++); - } while (--width > 0); - } - } + if (alphaLevel < 0xfe) + { + do + { + dest++ ->blend (*span++, alphaLevel); + } while (--width > 0); + } + else + { + do + { + dest++ ->blend (*span++); + } while (--width > 0); + } + } - void clipEdgeTableLine (EdgeTable& et, int x, int y_, int width) throw() - { - if (width > scratchSize) - { - scratchSize = width; - scratchBuffer.malloc (scratchSize); - } + void clipEdgeTableLine (EdgeTable& et, int x, int y_, int width) throw() + { + if (width > scratchSize) + { + scratchSize = width; + scratchBuffer.malloc (scratchSize); + } - uint8* mask = (uint8*) scratchBuffer; - y = y_; - generate ((SrcPixelType*) mask, x, width); + uint8* mask = (uint8*) scratchBuffer; + y = y_; + generate ((SrcPixelType*) mask, x, width); - if (sizeof (SrcPixelType) == sizeof (PixelARGB)) - mask += PixelARGB::indexA; + if (sizeof (SrcPixelType) == sizeof (PixelARGB)) + mask += PixelARGB::indexA; - et.clipLineToMask (x, y_, mask, sizeof (SrcPixelType), width); - } + et.clipLineToMask (x, y_, mask, sizeof (SrcPixelType), width); + } private: - void generate (PixelARGB* dest, const int x, int numPixels) throw() - { - this->interpolator.setStartOfLine (x + pixelOffset, y + pixelOffset, numPixels); + void generate (PixelARGB* dest, const int x, int numPixels) throw() + { + this->interpolator.setStartOfLine (x + pixelOffset, y + pixelOffset, numPixels); - do - { - int hiResX, hiResY; - this->interpolator.next (hiResX, hiResY); - hiResX += pixelOffsetInt; - hiResY += pixelOffsetInt; + do + { + int hiResX, hiResY; + this->interpolator.next (hiResX, hiResY); + hiResX += pixelOffsetInt; + hiResY += pixelOffsetInt; - int loResX = hiResX >> 8; - int loResY = hiResY >> 8; + int loResX = hiResX >> 8; + int loResY = hiResY >> 8; - if (repeatPattern) - { - loResX = safeModulo (loResX, srcData.width); - loResY = safeModulo (loResY, srcData.height); - } + if (repeatPattern) + { + loResX = safeModulo (loResX, srcData.width); + loResY = safeModulo (loResY, srcData.height); + } - if (betterQuality - && ((unsigned int) loResX) < (unsigned int) maxX - && ((unsigned int) loResY) < (unsigned int) maxY) - { - uint32 c[4] = { 256 * 128, 256 * 128, 256 * 128, 256 * 128 }; - hiResX &= 255; - hiResY &= 255; + if (betterQuality + && ((unsigned int) loResX) < (unsigned int) maxX + && ((unsigned int) loResY) < (unsigned int) maxY) + { + uint32 c[4] = { 256 * 128, 256 * 128, 256 * 128, 256 * 128 }; + hiResX &= 255; + hiResY &= 255; - const uint8* src = this->srcData.getPixelPointer (loResX, loResY); + const uint8* src = this->srcData.getPixelPointer (loResX, loResY); - uint32 weight = (256 - hiResX) * (256 - hiResY); - c[0] += weight * src[0]; - c[1] += weight * src[1]; - c[2] += weight * src[2]; - c[3] += weight * src[3]; + uint32 weight = (256 - hiResX) * (256 - hiResY); + c[0] += weight * src[0]; + c[1] += weight * src[1]; + c[2] += weight * src[2]; + c[3] += weight * src[3]; - weight = hiResX * (256 - hiResY); - c[0] += weight * src[4]; - c[1] += weight * src[5]; - c[2] += weight * src[6]; - c[3] += weight * src[7]; + weight = hiResX * (256 - hiResY); + c[0] += weight * src[4]; + c[1] += weight * src[5]; + c[2] += weight * src[6]; + c[3] += weight * src[7]; - src += this->srcData.lineStride; + src += this->srcData.lineStride; - weight = (256 - hiResX) * hiResY; - c[0] += weight * src[0]; - c[1] += weight * src[1]; - c[2] += weight * src[2]; - c[3] += weight * src[3]; + weight = (256 - hiResX) * hiResY; + c[0] += weight * src[0]; + c[1] += weight * src[1]; + c[2] += weight * src[2]; + c[3] += weight * src[3]; - weight = hiResX * hiResY; - c[0] += weight * src[4]; - c[1] += weight * src[5]; - c[2] += weight * src[6]; - c[3] += weight * src[7]; + weight = hiResX * hiResY; + c[0] += weight * src[4]; + c[1] += weight * src[5]; + c[2] += weight * src[6]; + c[3] += weight * src[7]; - dest->setARGB ((uint8) (c[PixelARGB::indexA] >> 16), - (uint8) (c[PixelARGB::indexR] >> 16), - (uint8) (c[PixelARGB::indexG] >> 16), - (uint8) (c[PixelARGB::indexB] >> 16)); - } - else - { - if (! repeatPattern) - { - // Beyond the edges, just repeat the edge pixels and leave the anti-aliasing to be handled by the edgetable - if (loResX < 0) loResX = 0; - if (loResY < 0) loResY = 0; - if (loResX > maxX) loResX = maxX; - if (loResY > maxY) loResY = maxY; - } + dest->setARGB ((uint8) (c[PixelARGB::indexA] >> 16), + (uint8) (c[PixelARGB::indexR] >> 16), + (uint8) (c[PixelARGB::indexG] >> 16), + (uint8) (c[PixelARGB::indexB] >> 16)); + } + else + { + if (! repeatPattern) + { + // Beyond the edges, just repeat the edge pixels and leave the anti-aliasing to be handled by the edgetable + if (loResX < 0) loResX = 0; + if (loResY < 0) loResY = 0; + if (loResX > maxX) loResX = maxX; + if (loResY > maxY) loResY = maxY; + } - dest->set (*(const PixelARGB*) this->srcData.getPixelPointer (loResX, loResY)); - } + dest->set (*(const PixelARGB*) this->srcData.getPixelPointer (loResX, loResY)); + } - ++dest; + ++dest; - } while (--numPixels > 0); - } + } while (--numPixels > 0); + } - void generate (PixelRGB* dest, const int x, int numPixels) throw() - { - this->interpolator.setStartOfLine (x + pixelOffset, y + pixelOffset, numPixels); + void generate (PixelRGB* dest, const int x, int numPixels) throw() + { + this->interpolator.setStartOfLine (x + pixelOffset, y + pixelOffset, numPixels); - do - { - int hiResX, hiResY; - this->interpolator.next (hiResX, hiResY); - hiResX += pixelOffsetInt; - hiResY += pixelOffsetInt; - int loResX = hiResX >> 8; - int loResY = hiResY >> 8; + do + { + int hiResX, hiResY; + this->interpolator.next (hiResX, hiResY); + hiResX += pixelOffsetInt; + hiResY += pixelOffsetInt; + int loResX = hiResX >> 8; + int loResY = hiResY >> 8; - if (repeatPattern) - { - loResX = safeModulo (loResX, srcData.width); - loResY = safeModulo (loResY, srcData.height); - } + if (repeatPattern) + { + loResX = safeModulo (loResX, srcData.width); + loResY = safeModulo (loResY, srcData.height); + } - if (betterQuality - && ((unsigned int) loResX) < (unsigned int) maxX - && ((unsigned int) loResY) < (unsigned int) maxY) - { - uint32 c[3] = { 256 * 128, 256 * 128, 256 * 128 }; - hiResX &= 255; - hiResY &= 255; + if (betterQuality + && ((unsigned int) loResX) < (unsigned int) maxX + && ((unsigned int) loResY) < (unsigned int) maxY) + { + uint32 c[3] = { 256 * 128, 256 * 128, 256 * 128 }; + hiResX &= 255; + hiResY &= 255; - const uint8* src = this->srcData.getPixelPointer (loResX, loResY); + const uint8* src = this->srcData.getPixelPointer (loResX, loResY); - unsigned int weight = (256 - hiResX) * (256 - hiResY); - c[0] += weight * src[0]; - c[1] += weight * src[1]; - c[2] += weight * src[2]; + unsigned int weight = (256 - hiResX) * (256 - hiResY); + c[0] += weight * src[0]; + c[1] += weight * src[1]; + c[2] += weight * src[2]; - weight = hiResX * (256 - hiResY); - c[0] += weight * src[3]; - c[1] += weight * src[4]; - c[2] += weight * src[5]; + weight = hiResX * (256 - hiResY); + c[0] += weight * src[3]; + c[1] += weight * src[4]; + c[2] += weight * src[5]; - src += this->srcData.lineStride; + src += this->srcData.lineStride; - weight = (256 - hiResX) * hiResY; - c[0] += weight * src[0]; - c[1] += weight * src[1]; - c[2] += weight * src[2]; + weight = (256 - hiResX) * hiResY; + c[0] += weight * src[0]; + c[1] += weight * src[1]; + c[2] += weight * src[2]; - weight = hiResX * hiResY; - c[0] += weight * src[3]; - c[1] += weight * src[4]; - c[2] += weight * src[5]; + weight = hiResX * hiResY; + c[0] += weight * src[3]; + c[1] += weight * src[4]; + c[2] += weight * src[5]; - dest->setARGB ((uint8) 255, - (uint8) (c[PixelRGB::indexR] >> 16), - (uint8) (c[PixelRGB::indexG] >> 16), - (uint8) (c[PixelRGB::indexB] >> 16)); - } - else - { - if (! repeatPattern) - { - // Beyond the edges, just repeat the edge pixels and leave the anti-aliasing to be handled by the edgetable - if (loResX < 0) loResX = 0; - if (loResY < 0) loResY = 0; - if (loResX > maxX) loResX = maxX; - if (loResY > maxY) loResY = maxY; - } + dest->setARGB ((uint8) 255, + (uint8) (c[PixelRGB::indexR] >> 16), + (uint8) (c[PixelRGB::indexG] >> 16), + (uint8) (c[PixelRGB::indexB] >> 16)); + } + else + { + if (! repeatPattern) + { + // Beyond the edges, just repeat the edge pixels and leave the anti-aliasing to be handled by the edgetable + if (loResX < 0) loResX = 0; + if (loResY < 0) loResY = 0; + if (loResX > maxX) loResX = maxX; + if (loResY > maxY) loResY = maxY; + } - dest->set (*(const PixelRGB*) this->srcData.getPixelPointer (loResX, loResY)); - } + dest->set (*(const PixelRGB*) this->srcData.getPixelPointer (loResX, loResY)); + } - ++dest; + ++dest; - } while (--numPixels > 0); - } + } while (--numPixels > 0); + } - void generate (PixelAlpha* dest, const int x, int numPixels) throw() - { - this->interpolator.setStartOfLine (x + pixelOffset, y + pixelOffset, numPixels); + void generate (PixelAlpha* dest, const int x, int numPixels) throw() + { + this->interpolator.setStartOfLine (x + pixelOffset, y + pixelOffset, numPixels); - do - { - int hiResX, hiResY; - this->interpolator.next (hiResX, hiResY); - hiResX += pixelOffsetInt; - hiResY += pixelOffsetInt; - int loResX = hiResX >> 8; - int loResY = hiResY >> 8; + do + { + int hiResX, hiResY; + this->interpolator.next (hiResX, hiResY); + hiResX += pixelOffsetInt; + hiResY += pixelOffsetInt; + int loResX = hiResX >> 8; + int loResY = hiResY >> 8; - if (repeatPattern) - { - loResX = safeModulo (loResX, srcData.width); - loResY = safeModulo (loResY, srcData.height); - } + if (repeatPattern) + { + loResX = safeModulo (loResX, srcData.width); + loResY = safeModulo (loResY, srcData.height); + } - if (betterQuality - && ((unsigned int) loResX) < (unsigned int) maxX - && ((unsigned int) loResY) < (unsigned int) maxY) - { - hiResX &= 255; - hiResY &= 255; + if (betterQuality + && ((unsigned int) loResX) < (unsigned int) maxX + && ((unsigned int) loResY) < (unsigned int) maxY) + { + hiResX &= 255; + hiResY &= 255; - const uint8* src = this->srcData.getPixelPointer (loResX, loResY); - uint32 c = 256 * 128; - c += src[0] * ((256 - hiResX) * (256 - hiResY)); - c += src[1] * (hiResX * (256 - hiResY)); - src += this->srcData.lineStride; - c += src[0] * ((256 - hiResX) * hiResY); - c += src[1] * (hiResX * hiResY); + const uint8* src = this->srcData.getPixelPointer (loResX, loResY); + uint32 c = 256 * 128; + c += src[0] * ((256 - hiResX) * (256 - hiResY)); + c += src[1] * (hiResX * (256 - hiResY)); + src += this->srcData.lineStride; + c += src[0] * ((256 - hiResX) * hiResY); + c += src[1] * (hiResX * hiResY); - *((uint8*) dest) = (uint8) c; - } - else - { - if (! repeatPattern) - { - // Beyond the edges, just repeat the edge pixels and leave the anti-aliasing to be handled by the edgetable - if (loResX < 0) loResX = 0; - if (loResY < 0) loResY = 0; - if (loResX > maxX) loResX = maxX; - if (loResY > maxY) loResY = maxY; - } + *((uint8*) dest) = (uint8) c; + } + else + { + if (! repeatPattern) + { + // Beyond the edges, just repeat the edge pixels and leave the anti-aliasing to be handled by the edgetable + if (loResX < 0) loResX = 0; + if (loResY < 0) loResY = 0; + if (loResX > maxX) loResX = maxX; + if (loResY > maxY) loResY = maxY; + } - *((uint8*) dest) = *(this->srcData.getPixelPointer (loResX, loResY)); - } + *((uint8*) dest) = *(this->srcData.getPixelPointer (loResX, loResY)); + } - ++dest; + ++dest; - } while (--numPixels > 0); - } + } while (--numPixels > 0); + } - class TransformedImageSpanInterpolator - { - public: - TransformedImageSpanInterpolator (const AffineTransform& transform) throw() - : inverseTransform (transform.inverted()) - {} + class TransformedImageSpanInterpolator + { + public: + TransformedImageSpanInterpolator (const AffineTransform& transform) throw() + : inverseTransform (transform.inverted()) + {} - void setStartOfLine (float x, float y, const int numPixels) throw() - { - float x1 = x, y1 = y; - inverseTransform.transformPoint (x1, y1); - x += numPixels; - inverseTransform.transformPoint (x, y); + void setStartOfLine (float x, float y, const int numPixels) throw() + { + float x1 = x, y1 = y; + inverseTransform.transformPoint (x1, y1); + x += numPixels; + inverseTransform.transformPoint (x, y); - xBresenham.set ((int) (x1 * 256.0f), (int) (x * 256.0f), numPixels); - yBresenham.set ((int) (y1 * 256.0f), (int) (y * 256.0f), numPixels); - } + xBresenham.set ((int) (x1 * 256.0f), (int) (x * 256.0f), numPixels); + yBresenham.set ((int) (y1 * 256.0f), (int) (y * 256.0f), numPixels); + } - void next (int& x, int& y) throw() - { - x = xBresenham.n; - xBresenham.stepToNext(); - y = yBresenham.n; - yBresenham.stepToNext(); - } + void next (int& x, int& y) throw() + { + x = xBresenham.n; + xBresenham.stepToNext(); + y = yBresenham.n; + yBresenham.stepToNext(); + } - private: - class BresenhamInterpolator - { - public: - BresenhamInterpolator() throw() {} + private: + class BresenhamInterpolator + { + public: + BresenhamInterpolator() throw() {} - void set (const int n1, const int n2, const int numSteps_) throw() - { - numSteps = jmax (1, numSteps_); - step = (n2 - n1) / numSteps; - remainder = modulo = (n2 - n1) % numSteps; - n = n1; + void set (const int n1, const int n2, const int numSteps_) throw() + { + numSteps = jmax (1, numSteps_); + step = (n2 - n1) / numSteps; + remainder = modulo = (n2 - n1) % numSteps; + n = n1; - if (modulo <= 0) - { - modulo += numSteps; - remainder += numSteps; - --step; - } + if (modulo <= 0) + { + modulo += numSteps; + remainder += numSteps; + --step; + } - modulo -= numSteps; - } + modulo -= numSteps; + } - forcedinline void stepToNext() throw() - { - modulo += remainder; - n += step; + forcedinline void stepToNext() throw() + { + modulo += remainder; + n += step; - if (modulo > 0) - { - modulo -= numSteps; - ++n; - } - } + if (modulo > 0) + { + modulo -= numSteps; + ++n; + } + } - int n; + int n; - private: - int numSteps, step, modulo, remainder; - }; + private: + int numSteps, step, modulo, remainder; + }; - const AffineTransform inverseTransform; - BresenhamInterpolator xBresenham, yBresenham; + const AffineTransform inverseTransform; + BresenhamInterpolator xBresenham, yBresenham; - TransformedImageSpanInterpolator (const TransformedImageSpanInterpolator&); - const TransformedImageSpanInterpolator& operator= (const TransformedImageSpanInterpolator&); - }; + TransformedImageSpanInterpolator (const TransformedImageSpanInterpolator&); + const TransformedImageSpanInterpolator& operator= (const TransformedImageSpanInterpolator&); + }; - TransformedImageSpanInterpolator interpolator; - const Image::BitmapData& destData; - const Image::BitmapData& srcData; - const int extraAlpha; - const bool betterQuality; - const float pixelOffset; - const int pixelOffsetInt, maxX, maxY; - int y; - DestPixelType* linePixels; - HeapBlock scratchBuffer; - int scratchSize; + TransformedImageSpanInterpolator interpolator; + const Image::BitmapData& destData; + const Image::BitmapData& srcData; + const int extraAlpha; + const bool betterQuality; + const float pixelOffset; + const int pixelOffsetInt, maxX, maxY; + int y; + DestPixelType* linePixels; + HeapBlock scratchBuffer; + int scratchSize; - TransformedImageFillEdgeTableRenderer (const TransformedImageFillEdgeTableRenderer&); - const TransformedImageFillEdgeTableRenderer& operator= (const TransformedImageFillEdgeTableRenderer&); + TransformedImageFillEdgeTableRenderer (const TransformedImageFillEdgeTableRenderer&); + const TransformedImageFillEdgeTableRenderer& operator= (const TransformedImageFillEdgeTableRenderer&); }; class LLGCSavedState { public: - LLGCSavedState (const Rectangle& clip_, const int xOffset_, const int yOffset_, - const Font& font_, const FillType& fillType_, - const Graphics::ResamplingQuality interpolationQuality_) throw() - : edgeTable (new EdgeTableHolder (EdgeTable (clip_))), - xOffset (xOffset_), yOffset (yOffset_), - font (font_), fillType (fillType_), - interpolationQuality (interpolationQuality_) - { - } + LLGCSavedState (const Rectangle& clip_, const int xOffset_, const int yOffset_, + const Font& font_, const FillType& fillType_, + const Graphics::ResamplingQuality interpolationQuality_) throw() + : edgeTable (new EdgeTableHolder (EdgeTable (clip_))), + xOffset (xOffset_), yOffset (yOffset_), + font (font_), fillType (fillType_), + interpolationQuality (interpolationQuality_) + { + } - LLGCSavedState (const LLGCSavedState& other) throw() - : edgeTable (other.edgeTable), xOffset (other.xOffset), - yOffset (other.yOffset), font (other.font), - fillType (other.fillType), interpolationQuality (other.interpolationQuality) - { - } + LLGCSavedState (const LLGCSavedState& other) throw() + : edgeTable (other.edgeTable), xOffset (other.xOffset), + yOffset (other.yOffset), font (other.font), + fillType (other.fillType), interpolationQuality (other.interpolationQuality) + { + } - ~LLGCSavedState() throw() - { - } + ~LLGCSavedState() throw() + { + } - bool clipToRectangle (const Rectangle& r) throw() - { - dupeEdgeTableIfMultiplyReferenced(); - edgeTable->edgeTable.clipToRectangle (r.translated (xOffset, yOffset)); - return ! edgeTable->edgeTable.isEmpty(); - } + bool clipToRectangle (const Rectangle& r) throw() + { + dupeEdgeTableIfMultiplyReferenced(); + edgeTable->edgeTable.clipToRectangle (r.translated (xOffset, yOffset)); + return ! edgeTable->edgeTable.isEmpty(); + } - bool clipToRectangleList (const RectangleList& r) throw() - { - dupeEdgeTableIfMultiplyReferenced(); - RectangleList offsetList (r); - offsetList.offsetAll (xOffset, yOffset); - EdgeTable e2 (offsetList); - edgeTable->edgeTable.clipToEdgeTable (e2); + bool clipToRectangleList (const RectangleList& r) throw() + { + dupeEdgeTableIfMultiplyReferenced(); + RectangleList offsetList (r); + offsetList.offsetAll (xOffset, yOffset); + EdgeTable e2 (offsetList); + edgeTable->edgeTable.clipToEdgeTable (e2); - return ! edgeTable->edgeTable.isEmpty(); - } + return ! edgeTable->edgeTable.isEmpty(); + } - bool excludeClipRectangle (const Rectangle& r) throw() - { - dupeEdgeTableIfMultiplyReferenced(); - edgeTable->edgeTable.excludeRectangle (r.translated (xOffset, yOffset)); - return ! edgeTable->edgeTable.isEmpty(); - } + bool excludeClipRectangle (const Rectangle& r) throw() + { + dupeEdgeTableIfMultiplyReferenced(); + edgeTable->edgeTable.excludeRectangle (r.translated (xOffset, yOffset)); + return ! edgeTable->edgeTable.isEmpty(); + } - void clipToPath (const Path& p, const AffineTransform& transform) throw() - { - dupeEdgeTableIfMultiplyReferenced(); - EdgeTable et (edgeTable->edgeTable.getMaximumBounds(), p, transform.translated ((float) xOffset, (float) yOffset)); - edgeTable->edgeTable.clipToEdgeTable (et); - } + void clipToPath (const Path& p, const AffineTransform& transform) throw() + { + dupeEdgeTableIfMultiplyReferenced(); + EdgeTable et (edgeTable->edgeTable.getMaximumBounds(), p, transform.translated ((float) xOffset, (float) yOffset)); + edgeTable->edgeTable.clipToEdgeTable (et); + } - void fillEdgeTable (Image& image, EdgeTable& et, const bool replaceContents = false) throw() - { - et.clipToEdgeTable (edgeTable->edgeTable); + void fillEdgeTable (Image& image, EdgeTable& et, const bool replaceContents = false) throw() + { + et.clipToEdgeTable (edgeTable->edgeTable); - Image::BitmapData destData (image, 0, 0, image.getWidth(), image.getHeight(), true); + Image::BitmapData destData (image, 0, 0, image.getWidth(), image.getHeight(), true); - if (fillType.isGradient()) - { - jassert (! replaceContents); // that option is just for solid colours + if (fillType.isGradient()) + { + jassert (! replaceContents); // that option is just for solid colours - ColourGradient g2 (*(fillType.gradient)); - g2.multiplyOpacity (fillType.getOpacity()); - g2.x1 -= 0.5f; g2.y1 -= 0.5f; - g2.x2 -= 0.5f; g2.y2 -= 0.5f; - AffineTransform transform (fillType.transform.translated ((float) xOffset, (float) yOffset)); - const bool isIdentity = transform.isOnlyTranslation(); + ColourGradient g2 (*(fillType.gradient)); + g2.multiplyOpacity (fillType.getOpacity()); + g2.x1 -= 0.5f; g2.y1 -= 0.5f; + g2.x2 -= 0.5f; g2.y2 -= 0.5f; + AffineTransform transform (fillType.transform.translated ((float) xOffset, (float) yOffset)); + const bool isIdentity = transform.isOnlyTranslation(); - if (isIdentity) - { - // If our translation doesn't involve any distortion, we can speed it up.. - transform.transformPoint (g2.x1, g2.y1); - transform.transformPoint (g2.x2, g2.y2); - transform = AffineTransform::identity; - } + if (isIdentity) + { + // If our translation doesn't involve any distortion, we can speed it up.. + transform.transformPoint (g2.x1, g2.y1); + transform.transformPoint (g2.x2, g2.y2); + transform = AffineTransform::identity; + } - HeapBlock lookupTable; - const int numLookupEntries = g2.createLookupTable (transform, lookupTable); - jassert (numLookupEntries > 0); + HeapBlock lookupTable; + const int numLookupEntries = g2.createLookupTable (transform, lookupTable); + jassert (numLookupEntries > 0); - switch (image.getFormat()) - { - case Image::ARGB: renderGradient (et, destData, g2, transform, lookupTable, numLookupEntries, isIdentity, (PixelARGB*) 0); break; - case Image::RGB: renderGradient (et, destData, g2, transform, lookupTable, numLookupEntries, isIdentity, (PixelRGB*) 0); break; - default: renderGradient (et, destData, g2, transform, lookupTable, numLookupEntries, isIdentity, (PixelAlpha*) 0); break; - } - } - else if (fillType.isTiledImage()) - { - renderImage (image, *(fillType.image), fillType.image->getBounds(), fillType.transform, &et); - } - else - { - const PixelARGB fillColour (fillType.colour.getPixelARGB()); + switch (image.getFormat()) + { + case Image::ARGB: renderGradient (et, destData, g2, transform, lookupTable, numLookupEntries, isIdentity, (PixelARGB*) 0); break; + case Image::RGB: renderGradient (et, destData, g2, transform, lookupTable, numLookupEntries, isIdentity, (PixelRGB*) 0); break; + default: renderGradient (et, destData, g2, transform, lookupTable, numLookupEntries, isIdentity, (PixelAlpha*) 0); break; + } + } + else if (fillType.isTiledImage()) + { + renderImage (image, *(fillType.image), fillType.image->getBounds(), fillType.transform, &et); + } + else + { + const PixelARGB fillColour (fillType.colour.getPixelARGB()); - switch (image.getFormat()) - { - case Image::ARGB: renderSolidFill (et, destData, fillColour, replaceContents, (PixelARGB*) 0); break; - case Image::RGB: renderSolidFill (et, destData, fillColour, replaceContents, (PixelRGB*) 0); break; - default: renderSolidFill (et, destData, fillColour, replaceContents, (PixelAlpha*) 0); break; - } - } - } + switch (image.getFormat()) + { + case Image::ARGB: renderSolidFill (et, destData, fillColour, replaceContents, (PixelARGB*) 0); break; + case Image::RGB: renderSolidFill (et, destData, fillColour, replaceContents, (PixelRGB*) 0); break; + default: renderSolidFill (et, destData, fillColour, replaceContents, (PixelAlpha*) 0); break; + } + } + } - void renderImage (Image& destImage, const Image& sourceImage, const Rectangle& srcClip, - const AffineTransform& t, const EdgeTable* const tiledFillClipRegion) throw() - { - const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset)); + void renderImage (Image& destImage, const Image& sourceImage, const Rectangle& srcClip, + const AffineTransform& t, const EdgeTable* const tiledFillClipRegion) throw() + { + const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset)); - const Image::BitmapData destData (destImage, 0, 0, destImage.getWidth(), destImage.getHeight(), true); - const Image::BitmapData srcData (sourceImage, srcClip.getX(), srcClip.getY(), srcClip.getWidth(), srcClip.getHeight()); - const int alpha = fillType.colour.getAlpha(); - const bool betterQuality = (interpolationQuality != Graphics::lowResamplingQuality); + const Image::BitmapData destData (destImage, 0, 0, destImage.getWidth(), destImage.getHeight(), true); + const Image::BitmapData srcData (sourceImage, srcClip.getX(), srcClip.getY(), srcClip.getWidth(), srcClip.getHeight()); + const int alpha = fillType.colour.getAlpha(); + const bool betterQuality = (interpolationQuality != Graphics::lowResamplingQuality); - if (transform.isOnlyTranslation()) - { - // If our translation doesn't involve any distortion, just use a simple blit.. - int tx = (int) (transform.getTranslationX() * 256.0f); - int ty = (int) (transform.getTranslationY() * 256.0f); + if (transform.isOnlyTranslation()) + { + // If our translation doesn't involve any distortion, just use a simple blit.. + int tx = (int) (transform.getTranslationX() * 256.0f); + int ty = (int) (transform.getTranslationY() * 256.0f); - if ((! betterQuality) || ((tx | ty) & 224) == 0) - { - tx = ((tx + 128) >> 8); - ty = ((ty + 128) >> 8); + if ((! betterQuality) || ((tx | ty) & 224) == 0) + { + tx = ((tx + 128) >> 8); + ty = ((ty + 128) >> 8); - if (tiledFillClipRegion != 0) - { - blittedRenderImage (sourceImage, destImage, *tiledFillClipRegion, destData, srcData, alpha, tx, ty, true); - } - else - { - EdgeTable et (Rectangle (tx, ty, srcClip.getWidth(), srcClip.getHeight()).getIntersection (destImage.getBounds())); - et.clipToEdgeTable (edgeTable->edgeTable); + if (tiledFillClipRegion != 0) + { + blittedRenderImage (sourceImage, destImage, *tiledFillClipRegion, destData, srcData, alpha, tx, ty, true); + } + else + { + EdgeTable et (Rectangle (tx, ty, srcClip.getWidth(), srcClip.getHeight()).getIntersection (destImage.getBounds())); + et.clipToEdgeTable (edgeTable->edgeTable); - if (! et.isEmpty()) - blittedRenderImage (sourceImage, destImage, et, destData, srcData, alpha, tx, ty, false); - } + if (! et.isEmpty()) + blittedRenderImage (sourceImage, destImage, et, destData, srcData, alpha, tx, ty, false); + } - return; - } - } + return; + } + } - if (transform.isSingularity()) - return; + if (transform.isSingularity()) + return; - if (tiledFillClipRegion != 0) - { - transformedRenderImage (sourceImage, destImage, *tiledFillClipRegion, destData, srcData, alpha, transform, betterQuality, true); - } - else - { - Path p; - p.addRectangle (0.0f, 0.0f, (float) srcClip.getWidth(), (float) srcClip.getHeight()); + if (tiledFillClipRegion != 0) + { + transformedRenderImage (sourceImage, destImage, *tiledFillClipRegion, destData, srcData, alpha, transform, betterQuality, true); + } + else + { + Path p; + p.addRectangle (0.0f, 0.0f, (float) srcClip.getWidth(), (float) srcClip.getHeight()); - EdgeTable et (edgeTable->edgeTable.getMaximumBounds(), p, transform); - et.clipToEdgeTable (edgeTable->edgeTable); + EdgeTable et (edgeTable->edgeTable.getMaximumBounds(), p, transform); + et.clipToEdgeTable (edgeTable->edgeTable); - if (! et.isEmpty()) - transformedRenderImage (sourceImage, destImage, et, destData, srcData, alpha, transform, betterQuality, false); - } - } + if (! et.isEmpty()) + transformedRenderImage (sourceImage, destImage, et, destData, srcData, alpha, transform, betterQuality, false); + } + } - void clipToImageAlpha (const Image& image, const Rectangle& srcClip, const AffineTransform& t) throw() - { - if (! image.hasAlphaChannel()) - { - Path p; - p.addRectangle (srcClip); - clipToPath (p, t); - return; - } + void clipToImageAlpha (const Image& image, const Rectangle& srcClip, const AffineTransform& t) throw() + { + if (! image.hasAlphaChannel()) + { + Path p; + p.addRectangle (srcClip); + clipToPath (p, t); + return; + } - dupeEdgeTableIfMultiplyReferenced(); + dupeEdgeTableIfMultiplyReferenced(); - const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset)); - const Image::BitmapData srcData (image, srcClip.getX(), srcClip.getY(), srcClip.getWidth(), srcClip.getHeight()); - const bool betterQuality = (interpolationQuality != Graphics::lowResamplingQuality); - EdgeTable& et = edgeTable->edgeTable; + const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset)); + const Image::BitmapData srcData (image, srcClip.getX(), srcClip.getY(), srcClip.getWidth(), srcClip.getHeight()); + const bool betterQuality = (interpolationQuality != Graphics::lowResamplingQuality); + EdgeTable& et = edgeTable->edgeTable; - if (transform.isOnlyTranslation()) - { - // If our translation doesn't involve any distortion, just use a simple blit.. - const int tx = (int) (transform.getTranslationX() * 256.0f); - const int ty = (int) (transform.getTranslationY() * 256.0f); + if (transform.isOnlyTranslation()) + { + // If our translation doesn't involve any distortion, just use a simple blit.. + const int tx = (int) (transform.getTranslationX() * 256.0f); + const int ty = (int) (transform.getTranslationY() * 256.0f); - if ((! betterQuality) || ((tx | ty) & 224) == 0) - { - const int imageX = ((tx + 128) >> 8); - const int imageY = ((ty + 128) >> 8); + if ((! betterQuality) || ((tx | ty) & 224) == 0) + { + const int imageX = ((tx + 128) >> 8); + const int imageY = ((ty + 128) >> 8); - if (image.getFormat() == Image::ARGB) - straightClipImage (et, srcData, imageX, imageY, (PixelARGB*)0); - else - straightClipImage (et, srcData, imageX, imageY, (PixelAlpha*)0); + if (image.getFormat() == Image::ARGB) + straightClipImage (et, srcData, imageX, imageY, (PixelARGB*)0); + else + straightClipImage (et, srcData, imageX, imageY, (PixelAlpha*)0); - return; - } - } + return; + } + } - if (transform.isSingularity()) - { - et.clipToRectangle (Rectangle()); - return; - } + if (transform.isSingularity()) + { + et.clipToRectangle (Rectangle()); + return; + } - { - Path p; - p.addRectangle (0, 0, (float) srcData.width, (float) srcData.height); - EdgeTable et2 (et.getMaximumBounds(), p, transform); - et.clipToEdgeTable (et2); - } + { + Path p; + p.addRectangle (0, 0, (float) srcData.width, (float) srcData.height); + EdgeTable et2 (et.getMaximumBounds(), p, transform); + et.clipToEdgeTable (et2); + } - if (! et.isEmpty()) - { - if (image.getFormat() == Image::ARGB) - transformedClipImage (et, srcData, transform, betterQuality, (PixelARGB*)0); - else - transformedClipImage (et, srcData, transform, betterQuality, (PixelAlpha*)0); - } - } + if (! et.isEmpty()) + { + if (image.getFormat() == Image::ARGB) + transformedClipImage (et, srcData, transform, betterQuality, (PixelARGB*)0); + else + transformedClipImage (et, srcData, transform, betterQuality, (PixelAlpha*)0); + } + } - template - void transformedClipImage (EdgeTable& et, const Image::BitmapData& srcData, const AffineTransform& transform, const bool betterQuality, const SrcPixelType *) throw() - { - TransformedImageFillEdgeTableRenderer renderer (srcData, srcData, transform, 255, betterQuality); + template + void transformedClipImage (EdgeTable& et, const Image::BitmapData& srcData, const AffineTransform& transform, const bool betterQuality, const SrcPixelType *) throw() + { + TransformedImageFillEdgeTableRenderer renderer (srcData, srcData, transform, 255, betterQuality); - for (int y = 0; y < et.getMaximumBounds().getHeight(); ++y) - renderer.clipEdgeTableLine (et, et.getMaximumBounds().getX(), y + et.getMaximumBounds().getY(), - et.getMaximumBounds().getWidth()); - } + for (int y = 0; y < et.getMaximumBounds().getHeight(); ++y) + renderer.clipEdgeTableLine (et, et.getMaximumBounds().getX(), y + et.getMaximumBounds().getY(), + et.getMaximumBounds().getWidth()); + } - template - void straightClipImage (EdgeTable& et, const Image::BitmapData& srcData, int imageX, int imageY, const SrcPixelType *) throw() - { - Rectangle r (imageX, imageY, srcData.width, srcData.height); - et.clipToRectangle (r); + template + void straightClipImage (EdgeTable& et, const Image::BitmapData& srcData, int imageX, int imageY, const SrcPixelType *) throw() + { + Rectangle r (imageX, imageY, srcData.width, srcData.height); + et.clipToRectangle (r); - ImageFillEdgeTableRenderer renderer (srcData, srcData, 255, imageX, imageY); + ImageFillEdgeTableRenderer renderer (srcData, srcData, 255, imageX, imageY); - for (int y = 0; y < r.getHeight(); ++y) - renderer.clipEdgeTableLine (et, r.getX(), y + r.getY(), r.getWidth()); - } + for (int y = 0; y < r.getHeight(); ++y) + renderer.clipEdgeTableLine (et, r.getX(), y + r.getY(), r.getWidth()); + } - class EdgeTableHolder : public ReferenceCountedObject - { - public: - EdgeTableHolder (const EdgeTable& e) throw() : edgeTable (e) {} + class EdgeTableHolder : public ReferenceCountedObject + { + public: + EdgeTableHolder (const EdgeTable& e) throw() : edgeTable (e) {} - EdgeTable edgeTable; - }; + EdgeTable edgeTable; + }; - ReferenceCountedObjectPtr edgeTable; - int xOffset, yOffset; - Font font; - FillType fillType; - Graphics::ResamplingQuality interpolationQuality; + ReferenceCountedObjectPtr edgeTable; + int xOffset, yOffset; + Font font; + FillType fillType; + Graphics::ResamplingQuality interpolationQuality; private: - const LLGCSavedState& operator= (const LLGCSavedState&); + const LLGCSavedState& operator= (const LLGCSavedState&); - void dupeEdgeTableIfMultiplyReferenced() throw() - { - if (edgeTable->getReferenceCount() > 1) - edgeTable = new EdgeTableHolder (edgeTable->edgeTable); - } + void dupeEdgeTableIfMultiplyReferenced() throw() + { + if (edgeTable->getReferenceCount() > 1) + edgeTable = new EdgeTableHolder (edgeTable->edgeTable); + } - template - void renderGradient (EdgeTable& et, const Image::BitmapData& destData, const ColourGradient& g, const AffineTransform& transform, - const PixelARGB* const lookupTable, const int numLookupEntries, const bool isIdentity, DestPixelType*) throw() - { - jassert (destData.pixelStride == sizeof (DestPixelType)); + template + void renderGradient (EdgeTable& et, const Image::BitmapData& destData, const ColourGradient& g, const AffineTransform& transform, + const PixelARGB* const lookupTable, const int numLookupEntries, const bool isIdentity, DestPixelType*) throw() + { + jassert (destData.pixelStride == sizeof (DestPixelType)); - if (g.isRadial) - { - if (isIdentity) - { - GradientEdgeTableRenderer renderer (destData, g, transform, lookupTable, numLookupEntries); - et.iterate (renderer); - } - else - { - GradientEdgeTableRenderer renderer (destData, g, transform, lookupTable, numLookupEntries); - et.iterate (renderer); - } - } - else - { - GradientEdgeTableRenderer renderer (destData, g, transform, lookupTable, numLookupEntries); - et.iterate (renderer); - } - } + if (g.isRadial) + { + if (isIdentity) + { + GradientEdgeTableRenderer renderer (destData, g, transform, lookupTable, numLookupEntries); + et.iterate (renderer); + } + else + { + GradientEdgeTableRenderer renderer (destData, g, transform, lookupTable, numLookupEntries); + et.iterate (renderer); + } + } + else + { + GradientEdgeTableRenderer renderer (destData, g, transform, lookupTable, numLookupEntries); + et.iterate (renderer); + } + } - template - void renderSolidFill (EdgeTable& et, const Image::BitmapData& destData, const PixelARGB& fillColour, const bool replaceContents, DestPixelType*) throw() - { - jassert (destData.pixelStride == sizeof (DestPixelType)); - if (replaceContents) - { - SolidColourEdgeTableRenderer r (destData, fillColour); - et.iterate (r); - } - else - { - SolidColourEdgeTableRenderer r (destData, fillColour); - et.iterate (r); - } - } + template + void renderSolidFill (EdgeTable& et, const Image::BitmapData& destData, const PixelARGB& fillColour, const bool replaceContents, DestPixelType*) throw() + { + jassert (destData.pixelStride == sizeof (DestPixelType)); + if (replaceContents) + { + SolidColourEdgeTableRenderer r (destData, fillColour); + et.iterate (r); + } + else + { + SolidColourEdgeTableRenderer r (destData, fillColour); + et.iterate (r); + } + } - void transformedRenderImage (const Image& srcImage, Image& destImage, const EdgeTable& et, const Image::BitmapData& destData, const Image::BitmapData& srcData, - const int alpha, const AffineTransform& transform, const bool betterQuality, const bool repeatPattern) throw() - { - switch (destImage.getFormat()) - { - case Image::ARGB: - switch (srcImage.getFormat()) - { - case Image::ARGB: - if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - break; - case Image::RGB: - if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - break; - default: - if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - break; - } - break; - case Image::RGB: - switch (srcImage.getFormat()) - { - case Image::ARGB: - if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - break; - case Image::RGB: - if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - break; - default: - if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - break; - } - break; - default: - switch (srcImage.getFormat()) - { - case Image::ARGB: - if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - break; - case Image::RGB: - if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - break; - default: - if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } - break; - } - break; - } - } + void transformedRenderImage (const Image& srcImage, Image& destImage, const EdgeTable& et, const Image::BitmapData& destData, const Image::BitmapData& srcData, + const int alpha, const AffineTransform& transform, const bool betterQuality, const bool repeatPattern) throw() + { + switch (destImage.getFormat()) + { + case Image::ARGB: + switch (srcImage.getFormat()) + { + case Image::ARGB: + if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + break; + case Image::RGB: + if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + break; + default: + if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + break; + } + break; + case Image::RGB: + switch (srcImage.getFormat()) + { + case Image::ARGB: + if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + break; + case Image::RGB: + if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + break; + default: + if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + break; + } + break; + default: + switch (srcImage.getFormat()) + { + case Image::ARGB: + if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + break; + case Image::RGB: + if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + break; + default: + if (repeatPattern) { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + else { TransformedImageFillEdgeTableRenderer r (destData, srcData, transform, alpha, betterQuality); et.iterate (r); } + break; + } + break; + } + } - void blittedRenderImage (const Image& srcImage, Image& destImage, const EdgeTable& et, const Image::BitmapData& destData, - const Image::BitmapData& srcData, const int alpha, int x, int y, const bool repeatPattern) throw() - { - switch (destImage.getFormat()) - { - case Image::ARGB: - switch (srcImage.getFormat()) - { - case Image::ARGB: - if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - break; - case Image::RGB: - if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - break; - default: - if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - break; - } - break; - case Image::RGB: - switch (srcImage.getFormat()) - { - case Image::ARGB: - if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - break; - case Image::RGB: - if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - break; - default: - if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - break; - } - break; - default: - switch (srcImage.getFormat()) - { - case Image::ARGB: - if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - break; - case Image::RGB: - if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - break; - default: - if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } - break; - } - break; - } - } + void blittedRenderImage (const Image& srcImage, Image& destImage, const EdgeTable& et, const Image::BitmapData& destData, + const Image::BitmapData& srcData, const int alpha, int x, int y, const bool repeatPattern) throw() + { + switch (destImage.getFormat()) + { + case Image::ARGB: + switch (srcImage.getFormat()) + { + case Image::ARGB: + if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + break; + case Image::RGB: + if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + break; + default: + if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + break; + } + break; + case Image::RGB: + switch (srcImage.getFormat()) + { + case Image::ARGB: + if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + break; + case Image::RGB: + if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + break; + default: + if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + break; + } + break; + default: + switch (srcImage.getFormat()) + { + case Image::ARGB: + if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + break; + case Image::RGB: + if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + break; + default: + if (repeatPattern) { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + else { ImageFillEdgeTableRenderer r (destData, srcData, alpha, x, y); et.iterate (r); } + break; + } + break; + } + } }; LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (Image& image_) - : image (image_), - stateStack (20) + : image (image_) { - currentState = new LLGCSavedState (image_.getBounds(), 0, 0, Font(), FillType(), Graphics::mediumResamplingQuality); + currentState = new LLGCSavedState (image_.getBounds(), 0, 0, Font(), + FillType(), Graphics::mediumResamplingQuality); } LowLevelGraphicsSoftwareRenderer::~LowLevelGraphicsSoftwareRenderer() @@ -83065,297 +82856,297 @@ LowLevelGraphicsSoftwareRenderer::~LowLevelGraphicsSoftwareRenderer() bool LowLevelGraphicsSoftwareRenderer::isVectorDevice() const { - return false; + return false; } void LowLevelGraphicsSoftwareRenderer::setOrigin (int x, int y) { - currentState->xOffset += x; - currentState->yOffset += y; + currentState->xOffset += x; + currentState->yOffset += y; } bool LowLevelGraphicsSoftwareRenderer::clipToRectangle (const Rectangle& r) { - return currentState->clipToRectangle (r); + return currentState->clipToRectangle (r); } bool LowLevelGraphicsSoftwareRenderer::clipToRectangleList (const RectangleList& clipRegion) { - return currentState->clipToRectangleList (clipRegion); + return currentState->clipToRectangleList (clipRegion); } void LowLevelGraphicsSoftwareRenderer::excludeClipRectangle (const Rectangle& r) { - currentState->excludeClipRectangle (r); + currentState->excludeClipRectangle (r); } void LowLevelGraphicsSoftwareRenderer::clipToPath (const Path& path, const AffineTransform& transform) { - currentState->clipToPath (path, transform); + currentState->clipToPath (path, transform); } void LowLevelGraphicsSoftwareRenderer::clipToImageAlpha (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform) { - currentState->clipToImageAlpha (sourceImage, srcClip, transform); + currentState->clipToImageAlpha (sourceImage, srcClip, transform); } bool LowLevelGraphicsSoftwareRenderer::clipRegionIntersects (const Rectangle& r) { - return currentState->edgeTable->edgeTable.getMaximumBounds() - .intersects (r.translated (currentState->xOffset, currentState->yOffset)); + return currentState->edgeTable->edgeTable.getMaximumBounds() + .intersects (r.translated (currentState->xOffset, currentState->yOffset)); } const Rectangle LowLevelGraphicsSoftwareRenderer::getClipBounds() const { - return currentState->edgeTable->edgeTable.getMaximumBounds().translated (-currentState->xOffset, -currentState->yOffset); + return currentState->edgeTable->edgeTable.getMaximumBounds().translated (-currentState->xOffset, -currentState->yOffset); } bool LowLevelGraphicsSoftwareRenderer::isClipEmpty() const { - return currentState->edgeTable->edgeTable.isEmpty(); + return currentState->edgeTable->edgeTable.isEmpty(); } void LowLevelGraphicsSoftwareRenderer::saveState() { - stateStack.add (new LLGCSavedState (*currentState)); + stateStack.add (new LLGCSavedState (*currentState)); } void LowLevelGraphicsSoftwareRenderer::restoreState() { - LLGCSavedState* const top = stateStack.getLast(); + LLGCSavedState* const top = stateStack.getLast(); - if (top != 0) - { - currentState = top; - stateStack.removeLast (1, false); - } - else - { - jassertfalse // trying to pop with an empty stack! - } + if (top != 0) + { + currentState = top; + stateStack.removeLast (1, false); + } + else + { + jassertfalse // trying to pop with an empty stack! + } } void LowLevelGraphicsSoftwareRenderer::setFill (const FillType& fillType) { - currentState->fillType = fillType; + currentState->fillType = fillType; } void LowLevelGraphicsSoftwareRenderer::setOpacity (float newOpacity) { - currentState->fillType.setOpacity (newOpacity); + currentState->fillType.setOpacity (newOpacity); } void LowLevelGraphicsSoftwareRenderer::setInterpolationQuality (Graphics::ResamplingQuality quality) { - currentState->interpolationQuality = quality; + currentState->interpolationQuality = quality; } void LowLevelGraphicsSoftwareRenderer::fillRect (const Rectangle& r, const bool replaceExistingContents) { - const Rectangle& totalClip = currentState->edgeTable->edgeTable.getMaximumBounds(); - const Rectangle clipped (totalClip.getIntersection (r.translated (currentState->xOffset, currentState->yOffset))); + const Rectangle& totalClip = currentState->edgeTable->edgeTable.getMaximumBounds(); + const Rectangle clipped (totalClip.getIntersection (r.translated (currentState->xOffset, currentState->yOffset))); - if (! clipped.isEmpty()) - { - EdgeTable et (clipped); - currentState->fillEdgeTable (image, et, replaceExistingContents); - } + if (! clipped.isEmpty()) + { + EdgeTable et (clipped); + currentState->fillEdgeTable (image, et, replaceExistingContents); + } } void LowLevelGraphicsSoftwareRenderer::fillPath (const Path& path, const AffineTransform& transform) { - EdgeTable et (currentState->edgeTable->edgeTable.getMaximumBounds(), - path, transform.translated ((float) currentState->xOffset, - (float) currentState->yOffset)); + EdgeTable et (currentState->edgeTable->edgeTable.getMaximumBounds(), + path, transform.translated ((float) currentState->xOffset, + (float) currentState->yOffset)); - currentState->fillEdgeTable (image, et); + currentState->fillEdgeTable (image, et); } void LowLevelGraphicsSoftwareRenderer::drawImage (const Image& sourceImage, const Rectangle& srcClip, - const AffineTransform& transform, const bool fillEntireClipAsTiles) + const AffineTransform& transform, const bool fillEntireClipAsTiles) { - jassert (sourceImage.getBounds().contains (srcClip)); + jassert (sourceImage.getBounds().contains (srcClip)); - currentState->renderImage (image, sourceImage, srcClip, transform, - fillEntireClipAsTiles ? &(currentState->edgeTable->edgeTable) : 0); + currentState->renderImage (image, sourceImage, srcClip, transform, + fillEntireClipAsTiles ? &(currentState->edgeTable->edgeTable) : 0); } void LowLevelGraphicsSoftwareRenderer::drawLine (double x1, double y1, double x2, double y2) { - Path p; - p.addLineSegment ((float) x1, (float) y1, (float) x2, (float) y2, 1.0f); - fillPath (p, AffineTransform::identity); + Path p; + p.addLineSegment ((float) x1, (float) y1, (float) x2, (float) y2, 1.0f); + fillPath (p, AffineTransform::identity); } void LowLevelGraphicsSoftwareRenderer::drawVerticalLine (const int x, double top, double bottom) { - if (bottom > top) - { - EdgeTable et ((float) (x + currentState->xOffset), (float) (top + currentState->yOffset), 1.0f, (float) (bottom - top)); - currentState->fillEdgeTable (image, et); - } + if (bottom > top) + { + EdgeTable et ((float) (x + currentState->xOffset), (float) (top + currentState->yOffset), 1.0f, (float) (bottom - top)); + currentState->fillEdgeTable (image, et); + } } void LowLevelGraphicsSoftwareRenderer::drawHorizontalLine (const int y, double left, double right) { - if (right > left) - { - EdgeTable et ((float) (left + currentState->xOffset), (float) (y + currentState->yOffset), - (float) (right - left), 1.0f); - currentState->fillEdgeTable (image, et); - } + if (right > left) + { + EdgeTable et ((float) (left + currentState->xOffset), (float) (y + currentState->yOffset), + (float) (right - left), 1.0f); + currentState->fillEdgeTable (image, et); + } } class GlyphCache : private DeletedAtShutdown { public: - GlyphCache() throw() - : accessCounter (0), hits (0), misses (0) - { - for (int i = 120; --i >= 0;) - glyphs.add (new CachedGlyph()); - } + GlyphCache() throw() + : accessCounter (0), hits (0), misses (0) + { + for (int i = 120; --i >= 0;) + glyphs.add (new CachedGlyph()); + } - ~GlyphCache() throw() - { - clearSingletonInstance(); - } + ~GlyphCache() throw() + { + clearSingletonInstance(); + } - juce_DeclareSingleton_SingleThreaded_Minimal (GlyphCache); + juce_DeclareSingleton_SingleThreaded_Minimal (GlyphCache); - void drawGlyph (LLGCSavedState& state, Image& image, const Font& font, const int glyphNumber, float x, float y) throw() - { - ++accessCounter; - int oldestCounter = INT_MAX; - CachedGlyph* oldest = 0; + void drawGlyph (LLGCSavedState& state, Image& image, const Font& font, const int glyphNumber, float x, float y) throw() + { + ++accessCounter; + int oldestCounter = INT_MAX; + CachedGlyph* oldest = 0; - for (int i = glyphs.size(); --i >= 0;) - { - CachedGlyph* const glyph = glyphs.getUnchecked (i); + for (int i = glyphs.size(); --i >= 0;) + { + CachedGlyph* const glyph = glyphs.getUnchecked (i); - if (glyph->glyph == glyphNumber && glyph->font == font) - { - ++hits; - glyph->lastAccessCount = accessCounter; - glyph->draw (state, image, x, y); - return; - } + if (glyph->glyph == glyphNumber && glyph->font == font) + { + ++hits; + glyph->lastAccessCount = accessCounter; + glyph->draw (state, image, x, y); + return; + } - if (glyph->lastAccessCount <= oldestCounter) - { - oldestCounter = glyph->lastAccessCount; - oldest = glyph; - } - } + if (glyph->lastAccessCount <= oldestCounter) + { + oldestCounter = glyph->lastAccessCount; + oldest = glyph; + } + } - if (hits + ++misses > (glyphs.size() << 4)) - { - if (misses * 2 > hits) - { - for (int i = 32; --i >= 0;) - glyphs.add (new CachedGlyph()); - } + if (hits + ++misses > (glyphs.size() << 4)) + { + if (misses * 2 > hits) + { + for (int i = 32; --i >= 0;) + glyphs.add (new CachedGlyph()); + } - hits = misses = 0; - oldest = glyphs.getLast(); - } + hits = misses = 0; + oldest = glyphs.getLast(); + } - jassert (oldest != 0); - oldest->lastAccessCount = accessCounter; - oldest->generate (font, glyphNumber); - oldest->draw (state, image, x, y); - } + jassert (oldest != 0); + oldest->lastAccessCount = accessCounter; + oldest->generate (font, glyphNumber); + oldest->draw (state, image, x, y); + } - class CachedGlyph - { - public: - CachedGlyph() : glyph (0), lastAccessCount (0) {} - ~CachedGlyph() {} + class CachedGlyph + { + public: + CachedGlyph() : glyph (0), lastAccessCount (0) {} + ~CachedGlyph() {} - void draw (LLGCSavedState& state, Image& image, const float x, const float y) const throw() - { - if (edgeTable != 0) - { - EdgeTable et (*edgeTable); - et.translate (x, roundFloatToInt (y)); - state.fillEdgeTable (image, et, false); - } - } + void draw (LLGCSavedState& state, Image& image, const float x, const float y) const throw() + { + if (edgeTable != 0) + { + EdgeTable et (*edgeTable); + et.translate (x, roundToInt (y)); + state.fillEdgeTable (image, et, false); + } + } - void generate (const Font& newFont, const int glyphNumber) throw() - { - font = newFont; - glyph = glyphNumber; - edgeTable = 0; + void generate (const Font& newFont, const int glyphNumber) throw() + { + font = newFont; + glyph = glyphNumber; + edgeTable = 0; - Path glyphPath; - font.getTypeface()->getOutlineForGlyph (glyphNumber, glyphPath); + Path glyphPath; + font.getTypeface()->getOutlineForGlyph (glyphNumber, glyphPath); - if (! glyphPath.isEmpty()) - { - const float fontHeight = font.getHeight(); - const AffineTransform transform (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)); + if (! glyphPath.isEmpty()) + { + const float fontHeight = font.getHeight(); + const AffineTransform transform (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)); - float px, py, pw, ph; - glyphPath.getBoundsTransformed (transform.translated (0.0f, -0.5f), px, py, pw, ph); + float px, py, pw, ph; + glyphPath.getBoundsTransformed (transform.translated (0.0f, -0.5f), px, py, pw, ph); - Rectangle clip ((int) floorf (px), (int) floorf (py), - roundFloatToInt (pw) + 2, roundFloatToInt (ph) + 2); + Rectangle clip ((int) floorf (px), (int) floorf (py), + roundToInt (pw) + 2, roundToInt (ph) + 2); - edgeTable = new EdgeTable (clip, glyphPath, transform); - } - } + edgeTable = new EdgeTable (clip, glyphPath, transform); + } + } - int glyph, lastAccessCount; - Font font; + int glyph, lastAccessCount; + Font font; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - private: - ScopedPointer edgeTable; + private: + ScopedPointer edgeTable; - CachedGlyph (const CachedGlyph&); - const CachedGlyph& operator= (const CachedGlyph&); - }; + CachedGlyph (const CachedGlyph&); + const CachedGlyph& operator= (const CachedGlyph&); + }; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OwnedArray glyphs; - int accessCounter, hits, misses; + OwnedArray glyphs; + int accessCounter, hits, misses; - GlyphCache (const GlyphCache&); - const GlyphCache& operator= (const GlyphCache&); + GlyphCache (const GlyphCache&); + const GlyphCache& operator= (const GlyphCache&); }; juce_ImplementSingleton_SingleThreaded (GlyphCache); void LowLevelGraphicsSoftwareRenderer::setFont (const Font& newFont) { - currentState->font = newFont; + currentState->font = newFont; } const Font LowLevelGraphicsSoftwareRenderer::getFont() { - return currentState->font; + return currentState->font; } void LowLevelGraphicsSoftwareRenderer::drawGlyph (int glyphNumber, const AffineTransform& transform) { - Font& f = currentState->font; + Font& f = currentState->font; - if (transform.isOnlyTranslation()) - { - GlyphCache::getInstance()->drawGlyph (*currentState, image, f, glyphNumber, - transform.getTranslationX() + (float) currentState->xOffset, - transform.getTranslationY() + (float) currentState->yOffset); - } - else - { - Path p; - f.getTypeface()->getOutlineForGlyph (glyphNumber, p); - fillPath (p, AffineTransform::scale (f.getHeight() * f.getHorizontalScale(), f.getHeight()).followedBy (transform)); - } + if (transform.isOnlyTranslation()) + { + GlyphCache::getInstance()->drawGlyph (*currentState, image, f, glyphNumber, + transform.getTranslationX() + (float) currentState->xOffset, + transform.getTranslationY() + (float) currentState->yOffset); + } + else + { + Path p; + f.getTypeface()->getOutlineForGlyph (glyphNumber, p); + fillPath (p, AffineTransform::scale (f.getHeight() * f.getHorizontalScale(), f.getHeight()).followedBy (transform)); + } } #if JUCE_MSVC @@ -83370,106 +83161,106 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE RectanglePlacement::RectanglePlacement (const RectanglePlacement& other) throw() - : flags (other.flags) + : flags (other.flags) { } const RectanglePlacement& RectanglePlacement::operator= (const RectanglePlacement& other) throw() { - flags = other.flags; - return *this; + flags = other.flags; + return *this; } void RectanglePlacement::applyTo (double& x, double& y, - double& w, double& h, - const double dx, const double dy, - const double dw, const double dh) const throw() + double& w, double& h, + const double dx, const double dy, + const double dw, const double dh) const throw() { - if (w == 0 || h == 0) - return; + if (w == 0 || h == 0) + return; - if ((flags & stretchToFit) != 0) - { - x = dx; - y = dy; - w = dw; - h = dh; - } - else - { - double scale = (flags & fillDestination) != 0 ? jmax (dw / w, dh / h) - : jmin (dw / w, dh / h); + if ((flags & stretchToFit) != 0) + { + x = dx; + y = dy; + w = dw; + h = dh; + } + else + { + double scale = (flags & fillDestination) != 0 ? jmax (dw / w, dh / h) + : jmin (dw / w, dh / h); - if ((flags & onlyReduceInSize) != 0) - scale = jmin (scale, 1.0); + if ((flags & onlyReduceInSize) != 0) + scale = jmin (scale, 1.0); - if ((flags & onlyIncreaseInSize) != 0) - scale = jmax (scale, 1.0); + if ((flags & onlyIncreaseInSize) != 0) + scale = jmax (scale, 1.0); - w *= scale; - h *= scale; + w *= scale; + h *= scale; - if ((flags & xLeft) != 0) - x = dx; - else if ((flags & xRight) != 0) - x = dx + dw - w; - else - x = dx + (dw - w) * 0.5; + if ((flags & xLeft) != 0) + x = dx; + else if ((flags & xRight) != 0) + x = dx + dw - w; + else + x = dx + (dw - w) * 0.5; - if ((flags & yTop) != 0) - y = dy; - else if ((flags & yBottom) != 0) - y = dy + dh - h; - else - y = dy + (dh - h) * 0.5; - } + if ((flags & yTop) != 0) + y = dy; + else if ((flags & yBottom) != 0) + y = dy + dh - h; + else + y = dy + (dh - h) * 0.5; + } } const AffineTransform RectanglePlacement::getTransformToFit (float x, float y, - float w, float h, - const float dx, const float dy, - const float dw, const float dh) const throw() + float w, float h, + const float dx, const float dy, + const float dw, const float dh) const throw() { - if (w == 0 || h == 0) - return AffineTransform::identity; + if (w == 0 || h == 0) + return AffineTransform::identity; - const float scaleX = dw / w; - const float scaleY = dh / h; + const float scaleX = dw / w; + const float scaleY = dh / h; - if ((flags & stretchToFit) != 0) - return AffineTransform::translation (-x, -y) - .scaled (scaleX, scaleY) - .translated (dx, dy); + if ((flags & stretchToFit) != 0) + return AffineTransform::translation (-x, -y) + .scaled (scaleX, scaleY) + .translated (dx, dy); - float scale = (flags & fillDestination) != 0 ? jmax (scaleX, scaleY) - : jmin (scaleX, scaleY); + float scale = (flags & fillDestination) != 0 ? jmax (scaleX, scaleY) + : jmin (scaleX, scaleY); - if ((flags & onlyReduceInSize) != 0) - scale = jmin (scale, 1.0f); + if ((flags & onlyReduceInSize) != 0) + scale = jmin (scale, 1.0f); - if ((flags & onlyIncreaseInSize) != 0) - scale = jmax (scale, 1.0f); + if ((flags & onlyIncreaseInSize) != 0) + scale = jmax (scale, 1.0f); - w *= scale; - h *= scale; + w *= scale; + h *= scale; - float newX = dx; + float newX = dx; - if ((flags & xRight) != 0) - newX += dw - w; // right - else if ((flags & xLeft) == 0) - newX += (dw - w) / 2.0f; // centre + if ((flags & xRight) != 0) + newX += dw - w; // right + else if ((flags & xLeft) == 0) + newX += (dw - w) / 2.0f; // centre - float newY = dy; + float newY = dy; - if ((flags & yBottom) != 0) - newY += dh - h; // bottom - else if ((flags & yTop) == 0) - newY += (dh - h) / 2.0f; // centre + if ((flags & yBottom) != 0) + newY += dh - h; // bottom + else if ((flags & yTop) == 0) + newY += (dh - h) / 2.0f; // centre - return AffineTransform::translation (-x, -y) - .scaled (scale, scale) - .translated (newX, newY); + return AffineTransform::translation (-x, -y) + .scaled (scale, scale) + .translated (newX, newY); } END_JUCE_NAMESPACE @@ -83480,11 +83271,11 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE Drawable::RenderingContext::RenderingContext (Graphics& g_, - const AffineTransform& transform_, - const float opacity_) throw() - : g (g_), - transform (transform_), - opacity (opacity_) + const AffineTransform& transform_, + const float opacity_) throw() + : g (g_), + transform (transform_), + opacity (opacity_) { } @@ -83497,100 +83288,100 @@ Drawable::~Drawable() } void Drawable::draw (Graphics& g, const float opacity, - const AffineTransform& transform) const + const AffineTransform& transform) const { - render (RenderingContext (g, transform, opacity)); + render (RenderingContext (g, transform, opacity)); } void Drawable::drawAt (Graphics& g, const float x, const float y, const float opacity) const { - draw (g, opacity, AffineTransform::translation (x, y)); + draw (g, opacity, AffineTransform::translation (x, y)); } void Drawable::drawWithin (Graphics& g, - const int destX, - const int destY, - const int destW, - const int destH, - const RectanglePlacement& placement, - const float opacity) const + const int destX, + const int destY, + const int destW, + const int destH, + const RectanglePlacement& placement, + const float opacity) const { - if (destW > 0 && destH > 0) - { - float x, y, w, h; - getBounds (x, y, w, h); + if (destW > 0 && destH > 0) + { + float x, y, w, h; + getBounds (x, y, w, h); - draw (g, opacity, - placement.getTransformToFit (x, y, w, h, - (float) destX, (float) destY, - (float) destW, (float) destH)); - } + draw (g, opacity, + placement.getTransformToFit (x, y, w, h, + (float) destX, (float) destY, + (float) destW, (float) destH)); + } } -Drawable* Drawable::createFromImageData (const void* data, const int numBytes) +Drawable* Drawable::createFromImageData (const void* data, const size_t numBytes) { - Drawable* result = 0; + Drawable* result = 0; - Image* const image = ImageFileFormat::loadFrom (data, numBytes); + Image* const image = ImageFileFormat::loadFrom (data, (int) numBytes); - if (image != 0) - { - DrawableImage* const di = new DrawableImage(); - di->setImage (image, true); - result = di; - } - else - { - const String asString (String::createStringFromData (data, numBytes)); + if (image != 0) + { + DrawableImage* const di = new DrawableImage(); + di->setImage (image, true); + result = di; + } + else + { + const String asString (String::createStringFromData (data, (int) numBytes)); - XmlDocument doc (asString); - ScopedPointer outer (doc.getDocumentElement (true)); + XmlDocument doc (asString); + ScopedPointer outer (doc.getDocumentElement (true)); - if (outer != 0 && outer->hasTagName (T("svg"))) - { - ScopedPointer svg (doc.getDocumentElement()); + if (outer != 0 && outer->hasTagName (T("svg"))) + { + ScopedPointer svg (doc.getDocumentElement()); - if (svg != 0) - result = Drawable::createFromSVG (*svg); - } - } + if (svg != 0) + result = Drawable::createFromSVG (*svg); + } + } - return result; + return result; } Drawable* Drawable::createFromImageDataStream (InputStream& dataSource) { - MemoryBlock mb; - dataSource.readIntoMemoryBlock (mb); + MemoryBlock mb; + dataSource.readIntoMemoryBlock (mb); - return createFromImageData (mb.getData(), mb.getSize()); + return createFromImageData (mb.getData(), mb.getSize()); } Drawable* Drawable::createFromImageFile (const File& file) { - const ScopedPointer fin (file.createInputStream()); + const ScopedPointer fin (file.createInputStream()); - return fin != 0 ? createFromImageDataStream (*fin) : 0; + return fin != 0 ? createFromImageDataStream (*fin) : 0; } Drawable* Drawable::createFromValueTree (const ValueTree& tree) throw() { - Drawable* d = DrawablePath::createFromValueTree (tree); + Drawable* d = DrawablePath::createFromValueTree (tree); - if (d == 0) - { - d = DrawableComposite::createFromValueTree (tree); + if (d == 0) + { + d = DrawableComposite::createFromValueTree (tree); - if (d == 0) - { - d = DrawableImage::createFromValueTree (tree); + if (d == 0) + { + d = DrawableImage::createFromValueTree (tree); - if (d == 0) - d = DrawableText::createFromValueTree (tree); - } - } + if (d == 0) + d = DrawableText::createFromValueTree (tree); + } + } - return d; + return d; } END_JUCE_NAMESPACE @@ -83609,215 +83400,215 @@ DrawableComposite::~DrawableComposite() } void DrawableComposite::insertDrawable (Drawable* drawable, - const AffineTransform& transform, - const int index) + const AffineTransform& transform, + const int index) { - if (drawable != 0) - { - if (! drawables.contains (drawable)) - { - drawables.insert (index, drawable); + if (drawable != 0) + { + if (! drawables.contains (drawable)) + { + drawables.insert (index, drawable); - if (transform.isIdentity()) - transforms.insert (index, 0); - else - transforms.insert (index, new AffineTransform (transform)); - } - else - { - jassertfalse // trying to add a drawable that's already in here! - } - } + if (transform.isIdentity()) + transforms.insert (index, 0); + else + transforms.insert (index, new AffineTransform (transform)); + } + else + { + jassertfalse // trying to add a drawable that's already in here! + } + } } void DrawableComposite::insertDrawable (const Drawable& drawable, - const AffineTransform& transform, - const int index) + const AffineTransform& transform, + const int index) { - insertDrawable (drawable.createCopy(), transform, index); + insertDrawable (drawable.createCopy(), transform, index); } void DrawableComposite::removeDrawable (const int index, const bool deleteDrawable) { - drawables.remove (index, deleteDrawable); - transforms.remove (index); + drawables.remove (index, deleteDrawable); + transforms.remove (index); } void DrawableComposite::bringToFront (const int index) { - if (index >= 0 && index < drawables.size() - 1) - { - drawables.move (index, -1); - transforms.move (index, -1); - } + if (index >= 0 && index < drawables.size() - 1) + { + drawables.move (index, -1); + transforms.move (index, -1); + } } void DrawableComposite::render (const Drawable::RenderingContext& context) const { - if (drawables.size() > 0 && context.opacity > 0) - { - if (context.opacity >= 1.0f || drawables.size() == 1) - { - Drawable::RenderingContext contextCopy (context); + if (drawables.size() > 0 && context.opacity > 0) + { + if (context.opacity >= 1.0f || drawables.size() == 1) + { + Drawable::RenderingContext contextCopy (context); - for (int i = 0; i < drawables.size(); ++i) - { - const AffineTransform* const t = transforms.getUnchecked(i); - contextCopy.transform = (t == 0) ? context.transform - : t->followedBy (context.transform); + for (int i = 0; i < drawables.size(); ++i) + { + const AffineTransform* const t = transforms.getUnchecked(i); + contextCopy.transform = (t == 0) ? context.transform + : t->followedBy (context.transform); - drawables.getUnchecked(i)->render (contextCopy); - } - } - else - { - // To correctly render a whole composite layer with an overall transparency, - // we need to render everything opaquely into a temp buffer, then blend that - // with the target opacity... - const Rectangle clipBounds (context.g.getClipBounds()); - Image tempImage (Image::ARGB, clipBounds.getWidth(), clipBounds.getHeight(), true); + drawables.getUnchecked(i)->render (contextCopy); + } + } + else + { + // To correctly render a whole composite layer with an overall transparency, + // we need to render everything opaquely into a temp buffer, then blend that + // with the target opacity... + const Rectangle clipBounds (context.g.getClipBounds()); + Image tempImage (Image::ARGB, clipBounds.getWidth(), clipBounds.getHeight(), true); - { - Graphics tempG (tempImage); - tempG.setOrigin (-clipBounds.getX(), -clipBounds.getY()); - Drawable::RenderingContext tempContext (tempG, context.transform, 1.0f); - render (tempContext); - } + { + Graphics tempG (tempImage); + tempG.setOrigin (-clipBounds.getX(), -clipBounds.getY()); + Drawable::RenderingContext tempContext (tempG, context.transform, 1.0f); + render (tempContext); + } - context.g.setOpacity (context.opacity); - context.g.drawImageAt (&tempImage, clipBounds.getX(), clipBounds.getY()); - } - } + context.g.setOpacity (context.opacity); + context.g.drawImageAt (&tempImage, clipBounds.getX(), clipBounds.getY()); + } + } } void DrawableComposite::getBounds (float& x, float& y, float& width, float& height) const { - Path totalPath; + Path totalPath; - for (int i = 0; i < drawables.size(); ++i) - { - drawables.getUnchecked(i)->getBounds (x, y, width, height); + for (int i = 0; i < drawables.size(); ++i) + { + drawables.getUnchecked(i)->getBounds (x, y, width, height); - if (width > 0.0f && height > 0.0f) - { - Path outline; - outline.addRectangle (x, y, width, height); + if (width > 0.0f && height > 0.0f) + { + Path outline; + outline.addRectangle (x, y, width, height); - const AffineTransform* const t = transforms.getUnchecked(i); + const AffineTransform* const t = transforms.getUnchecked(i); - if (t == 0) - totalPath.addPath (outline); - else - totalPath.addPath (outline, *t); - } - } + if (t == 0) + totalPath.addPath (outline); + else + totalPath.addPath (outline, *t); + } + } - totalPath.getBounds (x, y, width, height); + totalPath.getBounds (x, y, width, height); } bool DrawableComposite::hitTest (float x, float y) const { - for (int i = 0; i < drawables.size(); ++i) - { - float tx = x; - float ty = y; + for (int i = 0; i < drawables.size(); ++i) + { + float tx = x; + float ty = y; - const AffineTransform* const t = transforms.getUnchecked(i); + const AffineTransform* const t = transforms.getUnchecked(i); - if (t != 0) - t->inverted().transformPoint (tx, ty); + if (t != 0) + t->inverted().transformPoint (tx, ty); - if (drawables.getUnchecked(i)->hitTest (tx, ty)) - return true; - } + if (drawables.getUnchecked(i)->hitTest (tx, ty)) + return true; + } - return false; + return false; } Drawable* DrawableComposite::createCopy() const { - DrawableComposite* const dc = new DrawableComposite(); + DrawableComposite* const dc = new DrawableComposite(); - for (int i = 0; i < drawables.size(); ++i) - { - dc->drawables.add (drawables.getUnchecked(i)->createCopy()); + for (int i = 0; i < drawables.size(); ++i) + { + dc->drawables.add (drawables.getUnchecked(i)->createCopy()); - const AffineTransform* const t = transforms.getUnchecked(i); - dc->transforms.add (t != 0 ? new AffineTransform (*t) : 0); - } + const AffineTransform* const t = transforms.getUnchecked(i); + dc->transforms.add (t != 0 ? new AffineTransform (*t) : 0); + } - return dc; + return dc; } ValueTree DrawableComposite::createValueTree() const throw() { - ValueTree v (T("Group")); + ValueTree v (T("Group")); - if (getName().isNotEmpty()) - v.setProperty ("id", getName(), 0); + if (getName().isNotEmpty()) + v.setProperty ("id", getName(), 0); - for (int i = 0; i < drawables.size(); ++i) - { - Drawable* const d = drawables.getUnchecked(i); + for (int i = 0; i < drawables.size(); ++i) + { + Drawable* const d = drawables.getUnchecked(i); - ValueTree child (d->createValueTree()); + ValueTree child (d->createValueTree()); - AffineTransform* transform = transforms.getUnchecked(i); + AffineTransform* transform = transforms.getUnchecked(i); - if (transform != 0) - { - String t; - t << transform->mat00 << " " << transform->mat01 << " " << transform->mat02 << " " - << transform->mat10 << " " << transform->mat11 << " " << transform->mat12; + if (transform != 0) + { + String t; + t << transform->mat00 << " " << transform->mat01 << " " << transform->mat02 << " " + << transform->mat10 << " " << transform->mat11 << " " << transform->mat12; - child.setProperty ("transform", t, 0); - } + child.setProperty ("transform", t, 0); + } - v.addChild (child, -1, 0); - } + v.addChild (child, -1, 0); + } - return v; + return v; } DrawableComposite* DrawableComposite::createFromValueTree (const ValueTree& tree) throw() { - if (! tree.hasType ("Group")) - return 0; + if (! tree.hasType ("Group")) + return 0; - DrawableComposite* dc = new DrawableComposite(); - dc->setName (tree ["id"]); + DrawableComposite* dc = new DrawableComposite(); + dc->setName (tree ["id"]); - for (int i = 0; i < tree.getNumChildren(); ++i) - { - ValueTree childTree (tree.getChild (i)); - Drawable* d = Drawable::createFromValueTree (childTree); + for (int i = 0; i < tree.getNumChildren(); ++i) + { + ValueTree childTree (tree.getChild (i)); + Drawable* d = Drawable::createFromValueTree (childTree); - if (d != 0) - { - AffineTransform transform; - const String transformAtt (childTree ["transform"].toString()); + if (d != 0) + { + AffineTransform transform; + const String transformAtt (childTree ["transform"].toString()); - if (transformAtt.isNotEmpty()) - { - StringArray tokens; - tokens.addTokens (transformAtt.trim(), false); - tokens.removeEmptyStrings (true); + if (transformAtt.isNotEmpty()) + { + StringArray tokens; + tokens.addTokens (transformAtt.trim(), false); + tokens.removeEmptyStrings (true); - if (tokens.size() == 6) - { - float f[6]; - for (int j = 0; j < 6; ++j) - f[j] = (float) tokens[j].getDoubleValue(); + if (tokens.size() == 6) + { + float f[6]; + for (int j = 0; j < 6; ++j) + f[j] = (float) tokens[j].getDoubleValue(); - transform = AffineTransform (f[0], f[1], f[2], f[3], f[4], f[5]); - } - } + transform = AffineTransform (f[0], f[1], f[2], f[3], f[4], f[5]); + } + } - dc->insertDrawable (d, transform); - } - } + dc->insertDrawable (d, transform); + } + } - return dc; + return dc; } END_JUCE_NAMESPACE @@ -83828,171 +83619,171 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE DrawableImage::DrawableImage() - : image (0), - canDeleteImage (false), - opacity (1.0f), - overlayColour (0x00000000) + : image (0), + canDeleteImage (false), + opacity (1.0f), + overlayColour (0x00000000) { } DrawableImage::~DrawableImage() { - clearImage(); + clearImage(); } void DrawableImage::clearImage() { - if (canDeleteImage && image != 0) - ImageCache::releaseOrDelete (image); + if (canDeleteImage && image != 0) + ImageCache::releaseOrDelete (image); - image = 0; + image = 0; } void DrawableImage::setImage (const Image& imageToCopy) { - clearImage(); - image = new Image (imageToCopy); - canDeleteImage = true; + clearImage(); + image = new Image (imageToCopy); + canDeleteImage = true; } void DrawableImage::setImage (Image* imageToUse, - const bool releaseWhenNotNeeded) + const bool releaseWhenNotNeeded) { - clearImage(); - image = imageToUse; - canDeleteImage = releaseWhenNotNeeded; + clearImage(); + image = imageToUse; + canDeleteImage = releaseWhenNotNeeded; } void DrawableImage::setOpacity (const float newOpacity) { - opacity = newOpacity; + opacity = newOpacity; } void DrawableImage::setOverlayColour (const Colour& newOverlayColour) { - overlayColour = newOverlayColour; + overlayColour = newOverlayColour; } void DrawableImage::render (const Drawable::RenderingContext& context) const { - if (image != 0) - { - if (opacity > 0.0f && ! overlayColour.isOpaque()) - { - context.g.setOpacity (context.opacity * opacity); - context.g.drawImageTransformed (image, image->getBounds(), - context.transform, false); - } + if (image != 0) + { + if (opacity > 0.0f && ! overlayColour.isOpaque()) + { + context.g.setOpacity (context.opacity * opacity); + context.g.drawImageTransformed (image, image->getBounds(), + context.transform, false); + } - if (! overlayColour.isTransparent()) - { - context.g.setColour (overlayColour.withMultipliedAlpha (context.opacity)); - context.g.drawImageTransformed (image, image->getBounds(), - context.transform, true); - } - } + if (! overlayColour.isTransparent()) + { + context.g.setColour (overlayColour.withMultipliedAlpha (context.opacity)); + context.g.drawImageTransformed (image, image->getBounds(), + context.transform, true); + } + } } void DrawableImage::getBounds (float& x, float& y, float& width, float& height) const { - x = 0.0f; - y = 0.0f; - width = 0.0f; - height = 0.0f; + x = 0.0f; + y = 0.0f; + width = 0.0f; + height = 0.0f; - if (image != 0) - { - width = (float) image->getWidth(); - height = (float) image->getHeight(); - } + if (image != 0) + { + width = (float) image->getWidth(); + height = (float) image->getHeight(); + } } bool DrawableImage::hitTest (float x, float y) const { - return image != 0 - && x >= 0.0f - && y >= 0.0f - && x < image->getWidth() - && y < image->getHeight() - && image->getPixelAt (roundFloatToInt (x), roundFloatToInt (y)).getAlpha() >= 127; + return image != 0 + && x >= 0.0f + && y >= 0.0f + && x < image->getWidth() + && y < image->getHeight() + && image->getPixelAt (roundToInt (x), roundToInt (y)).getAlpha() >= 127; } Drawable* DrawableImage::createCopy() const { - DrawableImage* const di = new DrawableImage(); + DrawableImage* const di = new DrawableImage(); - di->opacity = opacity; - di->overlayColour = overlayColour; + di->opacity = opacity; + di->overlayColour = overlayColour; - if (image != 0) - { - if ((! canDeleteImage) || ! ImageCache::isImageInCache (image)) - { - di->setImage (*image); - } - else - { - ImageCache::incReferenceCount (image); - di->setImage (image, true); - } - } + if (image != 0) + { + if ((! canDeleteImage) || ! ImageCache::isImageInCache (image)) + { + di->setImage (*image); + } + else + { + ImageCache::incReferenceCount (image); + di->setImage (image, true); + } + } - return di; + return di; } ValueTree DrawableImage::createValueTree() const throw() { - ValueTree v (T("Image")); + ValueTree v (T("Image")); - if (getName().isNotEmpty()) - v.setProperty ("id", getName(), 0); + if (getName().isNotEmpty()) + v.setProperty ("id", getName(), 0); - if (opacity < 1.0f) - v.setProperty ("opacity", (double) opacity, 0); + if (opacity < 1.0f) + v.setProperty ("opacity", (double) opacity, 0); - if (! overlayColour.isTransparent()) - v.setProperty ("overlay", String::toHexString ((int) overlayColour.getARGB()), 0); + if (! overlayColour.isTransparent()) + v.setProperty ("overlay", String::toHexString ((int) overlayColour.getARGB()), 0); - if (image != 0) - { - MemoryOutputStream imageData; - PNGImageFormat pngFormat; - if (pngFormat.writeImageToStream (*image, imageData)) - { - String base64 (MemoryBlock (imageData.getData(), imageData.getDataSize()).toBase64Encoding()); + if (image != 0) + { + MemoryOutputStream imageData; + PNGImageFormat pngFormat; + if (pngFormat.writeImageToStream (*image, imageData)) + { + String base64 (MemoryBlock (imageData.getData(), imageData.getDataSize()).toBase64Encoding()); - for (int i = (base64.length() & ~127); i >= 0; i -= 128) - base64 = base64.substring (0, i) + "\n" + base64.substring (i); + for (int i = (base64.length() & ~127); i >= 0; i -= 128) + base64 = base64.substring (0, i) + "\n" + base64.substring (i); - v.setProperty ("data", base64, 0); - } - } + v.setProperty ("data", base64, 0); + } + } - return v; + return v; } DrawableImage* DrawableImage::createFromValueTree (const ValueTree& tree) throw() { - if (! tree.hasType ("Image")) - return 0; + if (! tree.hasType ("Image")) + return 0; - DrawableImage* di = new DrawableImage(); + DrawableImage* di = new DrawableImage(); - di->setName (tree ["id"]); - di->opacity = tree.hasProperty ("opacity") ? (float) tree ["opacity"] : 1.0f; - di->overlayColour = Colour (tree ["overlay"].toString().getHexValue32()); + di->setName (tree ["id"]); + di->opacity = tree.hasProperty ("opacity") ? (float) tree ["opacity"] : 1.0f; + di->overlayColour = Colour (tree ["overlay"].toString().getHexValue32()); - MemoryBlock imageData; - if (imageData.fromBase64Encoding (tree ["data"])) - { - Image* const im = ImageFileFormat::loadFrom (imageData.getData(), imageData.getSize()); - if (im == 0) - return false; + MemoryBlock imageData; + if (imageData.fromBase64Encoding (tree ["data"])) + { + Image* const im = ImageFileFormat::loadFrom (imageData.getData(), (int) imageData.getSize()); + if (im == 0) + return false; - di->setImage (im, true); - } + di->setImage (im, true); + } - return di; + return di; } END_JUCE_NAMESPACE @@ -84003,9 +83794,9 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE DrawablePath::DrawablePath() - : mainFill (FillType (Colours::black)), - strokeFill (FillType (Colours::transparentBlack)), - strokeType (0.0f) + : mainFill (FillType (Colours::black)), + strokeFill (FillType (Colours::transparentBlack)), + strokeType (0.0f) { } @@ -84015,201 +83806,201 @@ DrawablePath::~DrawablePath() void DrawablePath::setPath (const Path& newPath) throw() { - path = newPath; - updateOutline(); + path = newPath; + updateOutline(); } void DrawablePath::setFill (const FillType& newFill) throw() { - mainFill = newFill; + mainFill = newFill; } void DrawablePath::setStrokeFill (const FillType& newFill) throw() { - strokeFill = newFill; + strokeFill = newFill; } void DrawablePath::setStrokeType (const PathStrokeType& newStrokeType) throw() { - strokeType = newStrokeType; - updateOutline(); + strokeType = newStrokeType; + updateOutline(); } void DrawablePath::setStrokeThickness (const float newThickness) throw() { - setStrokeType (PathStrokeType (newThickness, strokeType.getJointStyle(), strokeType.getEndStyle())); + setStrokeType (PathStrokeType (newThickness, strokeType.getJointStyle(), strokeType.getEndStyle())); } void DrawablePath::render (const Drawable::RenderingContext& context) const { - { - FillType f (mainFill); - if (f.isGradient()) - f.gradient->multiplyOpacity (context.opacity); + { + FillType f (mainFill); + if (f.isGradient()) + f.gradient->multiplyOpacity (context.opacity); - f.transform = f.transform.followedBy (context.transform); - context.g.setFillType (f); - context.g.fillPath (path, context.transform); - } + f.transform = f.transform.followedBy (context.transform); + context.g.setFillType (f); + context.g.fillPath (path, context.transform); + } - if (strokeType.getStrokeThickness() > 0.0f) - { - FillType f (strokeFill); - if (f.isGradient()) - f.gradient->multiplyOpacity (context.opacity); + if (strokeType.getStrokeThickness() > 0.0f) + { + FillType f (strokeFill); + if (f.isGradient()) + f.gradient->multiplyOpacity (context.opacity); - f.transform = f.transform.followedBy (context.transform); - context.g.setFillType (f); - context.g.fillPath (stroke, context.transform); - } + f.transform = f.transform.followedBy (context.transform); + context.g.setFillType (f); + context.g.fillPath (stroke, context.transform); + } } void DrawablePath::updateOutline() { - stroke.clear(); - strokeType.createStrokedPath (stroke, path, AffineTransform::identity, 4.0f); + stroke.clear(); + strokeType.createStrokedPath (stroke, path, AffineTransform::identity, 4.0f); } void DrawablePath::getBounds (float& x, float& y, float& width, float& height) const { - if (strokeType.getStrokeThickness() > 0.0f) - stroke.getBounds (x, y, width, height); - else - path.getBounds (x, y, width, height); + if (strokeType.getStrokeThickness() > 0.0f) + stroke.getBounds (x, y, width, height); + else + path.getBounds (x, y, width, height); } bool DrawablePath::hitTest (float x, float y) const { - return path.contains (x, y) - || stroke.contains (x, y); + return path.contains (x, y) + || stroke.contains (x, y); } Drawable* DrawablePath::createCopy() const { - DrawablePath* const dp = new DrawablePath(); + DrawablePath* const dp = new DrawablePath(); - dp->path = path; - dp->stroke = stroke; - dp->mainFill = mainFill; - dp->strokeFill = strokeFill; - dp->strokeType = strokeType; - return dp; + dp->path = path; + dp->stroke = stroke; + dp->mainFill = mainFill; + dp->strokeFill = strokeFill; + dp->strokeType = strokeType; + return dp; } static const FillType readFillTypeFromTree (const ValueTree& v) { - const String type (v["type"].toString()); + const String type (v["type"].toString()); - if (type.equalsIgnoreCase (T("solid"))) - { - const String colour (v ["colour"].toString()); - return FillType (Colour (colour.isEmpty() ? (uint32) 0xff000000 - : (uint32) colour.getHexValue32())); - } - else if (type.equalsIgnoreCase ("gradient")) - { - ColourGradient g; - g.x1 = v["x1"]; - g.y1 = v["y1"]; - g.x2 = v["x2"]; - g.y2 = v["y2"]; - g.isRadial = v["radial"]; + if (type.equalsIgnoreCase (T("solid"))) + { + const String colour (v ["colour"].toString()); + return FillType (Colour (colour.isEmpty() ? (uint32) 0xff000000 + : (uint32) colour.getHexValue32())); + } + else if (type.equalsIgnoreCase ("gradient")) + { + ColourGradient g; + g.x1 = v["x1"]; + g.y1 = v["y1"]; + g.x2 = v["x2"]; + g.y2 = v["y2"]; + g.isRadial = v["radial"]; - StringArray colours; - colours.addTokens (v["colours"].toString(), false); + StringArray colours; + colours.addTokens (v["colours"].toString(), false); - for (int i = 0; i < colours.size() / 2; ++i) - g.addColour (colours[i * 2].getDoubleValue(), - Colour ((uint32) colours[i * 2 + 1].getHexValue32())); + for (int i = 0; i < colours.size() / 2; ++i) + g.addColour (colours[i * 2].getDoubleValue(), + Colour ((uint32) colours[i * 2 + 1].getHexValue32())); - return FillType (g); - } + return FillType (g); + } - jassertfalse - return FillType(); + jassertfalse + return FillType(); } static ValueTree createTreeForFillType (const String& tagName, const FillType& fillType) { - ValueTree v (tagName); + ValueTree v (tagName); - if (fillType.isColour()) - { - v.setProperty ("type", T("solid"), 0); - v.setProperty ("colour", String::toHexString ((int) fillType.colour.getARGB()), 0); - } - else if (fillType.isGradient()) - { - v.setProperty ("type", T("gradient"), 0); - v.setProperty ("x1", fillType.gradient->x1, 0); - v.setProperty ("y1", fillType.gradient->y1, 0); - v.setProperty ("x2", fillType.gradient->x2, 0); - v.setProperty ("y2", fillType.gradient->y2, 0); - v.setProperty ("radial", fillType.gradient->isRadial, 0); + if (fillType.isColour()) + { + v.setProperty ("type", T("solid"), 0); + v.setProperty ("colour", String::toHexString ((int) fillType.colour.getARGB()), 0); + } + else if (fillType.isGradient()) + { + v.setProperty ("type", T("gradient"), 0); + v.setProperty ("x1", fillType.gradient->x1, 0); + v.setProperty ("y1", fillType.gradient->y1, 0); + v.setProperty ("x2", fillType.gradient->x2, 0); + v.setProperty ("y2", fillType.gradient->y2, 0); + v.setProperty ("radial", fillType.gradient->isRadial, 0); - String s; - for (int i = 0; i < fillType.gradient->getNumColours(); ++i) - s << " " << fillType.gradient->getColourPosition (i) - << " " << String::toHexString ((int) fillType.gradient->getColour(i).getARGB()); + String s; + for (int i = 0; i < fillType.gradient->getNumColours(); ++i) + s << " " << fillType.gradient->getColourPosition (i) + << " " << String::toHexString ((int) fillType.gradient->getColour(i).getARGB()); - v.setProperty ("colours", s.trimStart(), 0); - } - else - { - jassertfalse //xxx - } + v.setProperty ("colours", s.trimStart(), 0); + } + else + { + jassertfalse //xxx + } - return v; + return v; } ValueTree DrawablePath::createValueTree() const throw() { - ValueTree v (T("Path")); + ValueTree v (T("Path")); - v.addChild (createTreeForFillType (T("fill"), mainFill), -1, 0); - v.addChild (createTreeForFillType (T("stroke"), strokeFill), -1, 0); + v.addChild (createTreeForFillType (T("fill"), mainFill), -1, 0); + v.addChild (createTreeForFillType (T("stroke"), strokeFill), -1, 0); - if (getName().isNotEmpty()) - v.setProperty ("id", getName(), 0); + if (getName().isNotEmpty()) + v.setProperty ("id", getName(), 0); - v.setProperty ("strokeWidth", (double) strokeType.getStrokeThickness(), 0); - v.setProperty ("jointStyle", strokeType.getJointStyle() == PathStrokeType::mitered - ? T("miter") : (strokeType.getJointStyle() == PathStrokeType::curved ? T("curved") : T("bevel")), 0); - v.setProperty ("capStyle", strokeType.getEndStyle() == PathStrokeType::butt - ? T("butt") : (strokeType.getEndStyle() == PathStrokeType::square ? T("square") : T("round")), 0); - v.setProperty ("path", path.toString(), 0); + v.setProperty ("strokeWidth", (double) strokeType.getStrokeThickness(), 0); + v.setProperty ("jointStyle", strokeType.getJointStyle() == PathStrokeType::mitered + ? T("miter") : (strokeType.getJointStyle() == PathStrokeType::curved ? T("curved") : T("bevel")), 0); + v.setProperty ("capStyle", strokeType.getEndStyle() == PathStrokeType::butt + ? T("butt") : (strokeType.getEndStyle() == PathStrokeType::square ? T("square") : T("round")), 0); + v.setProperty ("path", path.toString(), 0); - return v; + return v; } DrawablePath* DrawablePath::createFromValueTree (const ValueTree& tree) throw() { - if (! tree.hasType ("Path")) - return 0; + if (! tree.hasType ("Path")) + return 0; - DrawablePath* p = new DrawablePath(); + DrawablePath* p = new DrawablePath(); - p->setName (tree ["id"]); - p->mainFill = readFillTypeFromTree (tree.getChildWithName (T("fill"))); - p->strokeFill = readFillTypeFromTree (tree.getChildWithName (T("stroke"))); + p->setName (tree ["id"]); + p->mainFill = readFillTypeFromTree (tree.getChildWithName (T("fill"))); + p->strokeFill = readFillTypeFromTree (tree.getChildWithName (T("stroke"))); - const String jointStyle (tree ["jointStyle"].toString()); - const String endStyle (tree ["capStyle"].toString()); + const String jointStyle (tree ["jointStyle"].toString()); + const String endStyle (tree ["capStyle"].toString()); - p->strokeType - = PathStrokeType (tree ["strokeWidth"], - jointStyle.equalsIgnoreCase (T("curved")) ? PathStrokeType::curved - : (jointStyle.equalsIgnoreCase (T("bevel")) ? PathStrokeType::beveled - : PathStrokeType::mitered), - endStyle.equalsIgnoreCase (T("square")) ? PathStrokeType::square - : (endStyle.equalsIgnoreCase (T("round")) ? PathStrokeType::rounded - : PathStrokeType::butt)); + p->strokeType + = PathStrokeType (tree ["strokeWidth"], + jointStyle.equalsIgnoreCase (T("curved")) ? PathStrokeType::curved + : (jointStyle.equalsIgnoreCase (T("bevel")) ? PathStrokeType::beveled + : PathStrokeType::mitered), + endStyle.equalsIgnoreCase (T("square")) ? PathStrokeType::square + : (endStyle.equalsIgnoreCase (T("round")) ? PathStrokeType::rounded + : PathStrokeType::butt)); - p->path.clear(); - p->path.restoreFromString (tree ["path"]); - p->updateOutline(); + p->path.clear(); + p->path.restoreFromString (tree ["path"]); + p->updateOutline(); - return p; + return p; } END_JUCE_NAMESPACE @@ -84220,7 +84011,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE DrawableText::DrawableText() - : colour (Colours::white) + : colour (Colours::white) { } @@ -84230,71 +84021,71 @@ DrawableText::~DrawableText() void DrawableText::setText (const GlyphArrangement& newText) { - text = newText; + text = newText; } void DrawableText::setText (const String& newText, const Font& fontToUse) { - text.clear(); - text.addLineOfText (fontToUse, newText, 0.0f, 0.0f); + text.clear(); + text.addLineOfText (fontToUse, newText, 0.0f, 0.0f); } void DrawableText::setColour (const Colour& newColour) { - colour = newColour; + colour = newColour; } void DrawableText::render (const Drawable::RenderingContext& context) const { - context.g.setColour (colour.withMultipliedAlpha (context.opacity)); - text.draw (context.g, context.transform); + context.g.setColour (colour.withMultipliedAlpha (context.opacity)); + text.draw (context.g, context.transform); } void DrawableText::getBounds (float& x, float& y, float& width, float& height) const { - text.getBoundingBox (0, -1, x, y, width, height, false); // (really returns top, left, bottom, right) - width -= x; - height -= y; + text.getBoundingBox (0, -1, x, y, width, height, false); // (really returns top, left, bottom, right) + width -= x; + height -= y; } bool DrawableText::hitTest (float x, float y) const { - return text.findGlyphIndexAt (x, y) >= 0; + return text.findGlyphIndexAt (x, y) >= 0; } Drawable* DrawableText::createCopy() const { - DrawableText* const dt = new DrawableText(); + DrawableText* const dt = new DrawableText(); - dt->text = text; - dt->colour = colour; + dt->text = text; + dt->colour = colour; - return dt; + return dt; } ValueTree DrawableText::createValueTree() const throw() { - ValueTree v (T("Text")); + ValueTree v (T("Text")); - if (getName().isNotEmpty()) - v.setProperty ("id", getName(), 0); + if (getName().isNotEmpty()) + v.setProperty ("id", getName(), 0); - jassertfalse // xxx not finished! - return v; + jassertfalse // xxx not finished! + return v; } DrawableText* DrawableText::createFromValueTree (const ValueTree& tree) throw() { - if (! tree.hasType ("Text")) - return 0; + if (! tree.hasType ("Text")) + return 0; - DrawableText* dt = new DrawableText(); + DrawableText* dt = new DrawableText(); - dt->setName (tree ["id"]); + dt->setName (tree ["id"]); - jassertfalse // xxx not finished! + jassertfalse // xxx not finished! - return dt; + return dt; } END_JUCE_NAMESPACE @@ -84308,1244 +84099,1244 @@ class SVGState { public: - SVGState (const XmlElement* const topLevel) - : topLevelXml (topLevel), - elementX (0), elementY (0), - width (512), height (512), - viewBoxW (0), viewBoxH (0) - { - } + SVGState (const XmlElement* const topLevel) + : topLevelXml (topLevel), + elementX (0), elementY (0), + width (512), height (512), + viewBoxW (0), viewBoxH (0) + { + } - ~SVGState() - { - } + ~SVGState() + { + } - Drawable* parseSVGElement (const XmlElement& xml) - { - if (! xml.hasTagName (T("svg"))) - return 0; + Drawable* parseSVGElement (const XmlElement& xml) + { + if (! xml.hasTagName (T("svg"))) + return 0; - DrawableComposite* const drawable = new DrawableComposite(); + DrawableComposite* const drawable = new DrawableComposite(); - drawable->setName (xml.getStringAttribute (T("id"))); + drawable->setName (xml.getStringAttribute (T("id"))); - SVGState newState (*this); + SVGState newState (*this); - if (xml.hasAttribute (T("transform"))) - newState.addTransform (xml); + if (xml.hasAttribute (T("transform"))) + newState.addTransform (xml); - newState.elementX = getCoordLength (xml.getStringAttribute (T("x"), String (newState.elementX)), viewBoxW); - newState.elementY = getCoordLength (xml.getStringAttribute (T("y"), String (newState.elementY)), viewBoxH); - newState.width = getCoordLength (xml.getStringAttribute (T("width"), String (newState.width)), viewBoxW); - newState.height = getCoordLength (xml.getStringAttribute (T("height"), String (newState.height)), viewBoxH); + newState.elementX = getCoordLength (xml.getStringAttribute (T("x"), String (newState.elementX)), viewBoxW); + newState.elementY = getCoordLength (xml.getStringAttribute (T("y"), String (newState.elementY)), viewBoxH); + newState.width = getCoordLength (xml.getStringAttribute (T("width"), String (newState.width)), viewBoxW); + newState.height = getCoordLength (xml.getStringAttribute (T("height"), String (newState.height)), viewBoxH); - if (xml.hasAttribute (T("viewBox"))) - { - const String viewParams (xml.getStringAttribute (T("viewBox"))); - int i = 0; - float vx, vy, vw, vh; + if (xml.hasAttribute (T("viewBox"))) + { + const String viewParams (xml.getStringAttribute (T("viewBox"))); + int i = 0; + float vx, vy, vw, vh; - if (parseCoords (viewParams, vx, vy, i, true) - && parseCoords (viewParams, vw, vh, i, true) - && vw > 0 - && vh > 0) - { - newState.viewBoxW = vw; - newState.viewBoxH = vh; + if (parseCoords (viewParams, vx, vy, i, true) + && parseCoords (viewParams, vw, vh, i, true) + && vw > 0 + && vh > 0) + { + newState.viewBoxW = vw; + newState.viewBoxH = vh; - int placementFlags = 0; + int placementFlags = 0; - const String aspect (xml.getStringAttribute (T("preserveAspectRatio"))); + const String aspect (xml.getStringAttribute (T("preserveAspectRatio"))); - if (aspect.containsIgnoreCase (T("none"))) - { - placementFlags = RectanglePlacement::stretchToFit; - } - else - { - if (aspect.containsIgnoreCase (T("slice"))) - placementFlags |= RectanglePlacement::fillDestination; + if (aspect.containsIgnoreCase (T("none"))) + { + placementFlags = RectanglePlacement::stretchToFit; + } + else + { + if (aspect.containsIgnoreCase (T("slice"))) + placementFlags |= RectanglePlacement::fillDestination; - if (aspect.containsIgnoreCase (T("xMin"))) - placementFlags |= RectanglePlacement::xLeft; - else if (aspect.containsIgnoreCase (T("xMax"))) - placementFlags |= RectanglePlacement::xRight; - else - placementFlags |= RectanglePlacement::xMid; + if (aspect.containsIgnoreCase (T("xMin"))) + placementFlags |= RectanglePlacement::xLeft; + else if (aspect.containsIgnoreCase (T("xMax"))) + placementFlags |= RectanglePlacement::xRight; + else + placementFlags |= RectanglePlacement::xMid; - if (aspect.containsIgnoreCase (T("yMin"))) - placementFlags |= RectanglePlacement::yTop; - else if (aspect.containsIgnoreCase (T("yMax"))) - placementFlags |= RectanglePlacement::yBottom; - else - placementFlags |= RectanglePlacement::yMid; - } + if (aspect.containsIgnoreCase (T("yMin"))) + placementFlags |= RectanglePlacement::yTop; + else if (aspect.containsIgnoreCase (T("yMax"))) + placementFlags |= RectanglePlacement::yBottom; + else + placementFlags |= RectanglePlacement::yMid; + } - const RectanglePlacement placement (placementFlags); + const RectanglePlacement placement (placementFlags); - newState.transform - = placement.getTransformToFit (vx, vy, vw, vh, - 0.0f, 0.0f, newState.width, newState.height) - .followedBy (newState.transform); - } - } - else - { - if (viewBoxW == 0) - newState.viewBoxW = newState.width; + newState.transform + = placement.getTransformToFit (vx, vy, vw, vh, + 0.0f, 0.0f, newState.width, newState.height) + .followedBy (newState.transform); + } + } + else + { + if (viewBoxW == 0) + newState.viewBoxW = newState.width; - if (viewBoxH == 0) - newState.viewBoxH = newState.height; - } + if (viewBoxH == 0) + newState.viewBoxH = newState.height; + } - newState.parseSubElements (xml, drawable); + newState.parseSubElements (xml, drawable); - return drawable; - } + return drawable; + } private: - const XmlElement* const topLevelXml; - float elementX, elementY, width, height, viewBoxW, viewBoxH; - AffineTransform transform; - String cssStyleText; - - void parseSubElements (const XmlElement& xml, DrawableComposite* const parentDrawable) - { - forEachXmlChildElement (xml, e) - { - Drawable* d = 0; - - if (e->hasTagName (T("g"))) - d = parseGroupElement (*e); - else if (e->hasTagName (T("svg"))) - d = parseSVGElement (*e); - else if (e->hasTagName (T("path"))) - d = parsePath (*e); - else if (e->hasTagName (T("rect"))) - d = parseRect (*e); - else if (e->hasTagName (T("circle"))) - d = parseCircle (*e); - else if (e->hasTagName (T("ellipse"))) - d = parseEllipse (*e); - else if (e->hasTagName (T("line"))) - d = parseLine (*e); - else if (e->hasTagName (T("polyline"))) - d = parsePolygon (*e, true); - else if (e->hasTagName (T("polygon"))) - d = parsePolygon (*e, false); - else if (e->hasTagName (T("text"))) - d = parseText (*e); - else if (e->hasTagName (T("switch"))) - d = parseSwitch (*e); - else if (e->hasTagName (T("style"))) - parseCSSStyle (*e); - - parentDrawable->insertDrawable (d); - } - } - - DrawableComposite* parseSwitch (const XmlElement& xml) - { - const XmlElement* const group = xml.getChildByName (T("g")); - - if (group != 0) - return parseGroupElement (*group); - - return 0; - } - - DrawableComposite* parseGroupElement (const XmlElement& xml) - { - DrawableComposite* const drawable = new DrawableComposite(); - - drawable->setName (xml.getStringAttribute (T("id"))); - - if (xml.hasAttribute (T("transform"))) - { - SVGState newState (*this); - newState.addTransform (xml); - - newState.parseSubElements (xml, drawable); - } - else - { - parseSubElements (xml, drawable); - } - - return drawable; - } - - Drawable* parsePath (const XmlElement& xml) const - { - const String d (xml.getStringAttribute (T("d")).trimStart()); - Path path; - - if (getStyleAttribute (&xml, T("fill-rule")).trim().equalsIgnoreCase (T("evenodd"))) - path.setUsingNonZeroWinding (false); - - int index = 0; - float lastX = 0, lastY = 0; - float lastX2 = 0, lastY2 = 0; - tchar lastCommandChar = 0; - bool carryOn = true; - - const String validCommandChars (T("MmLlHhVvCcSsQqTtAaZz")); - - for (;;) - { - float x, y, x2, y2, x3, y3; - const bool isRelative = (d[index] >= 'a' && d[index] <= 'z'); - - if (validCommandChars.containsChar (d[index])) - lastCommandChar = d [index++]; - - switch (lastCommandChar) - { - case T('M'): - case T('m'): - case T('L'): - case T('l'): - if (parseCoords (d, x, y, index, false)) - { - if (isRelative) - { - x += lastX; - y += lastY; - } - - if (lastCommandChar == T('M') || lastCommandChar == T('m')) - path.startNewSubPath (x, y); - else - path.lineTo (x, y); - - lastX2 = lastX; - lastY2 = lastY; - lastX = x; - lastY = y; - } - else - { - ++index; - } - - break; - - case T('H'): - case T('h'): - if (parseCoord (d, x, index, false, true)) - { - if (isRelative) - x += lastX; - - path.lineTo (x, lastY); - - lastX2 = lastX; - lastX = x; - } - else - { - ++index; - } - break; - - case T('V'): - case T('v'): - if (parseCoord (d, y, index, false, false)) - { - if (isRelative) - y += lastY; - - path.lineTo (lastX, y); - - lastY2 = lastY; - lastY = y; - } - else - { - ++index; - } - break; - - case T('C'): - case T('c'): - if (parseCoords (d, x, y, index, false) - && parseCoords (d, x2, y2, index, false) - && parseCoords (d, x3, y3, index, false)) - { - if (isRelative) - { - x += lastX; - y += lastY; - x2 += lastX; - y2 += lastY; - x3 += lastX; - y3 += lastY; - } - - path.cubicTo (x, y, x2, y2, x3, y3); - - lastX2 = x2; - lastY2 = y2; - lastX = x3; - lastY = y3; - } - else - { - ++index; - } - break; - - case T('S'): - case T('s'): - if (parseCoords (d, x, y, index, false) - && parseCoords (d, x3, y3, index, false)) - { - if (isRelative) - { - x += lastX; - y += lastY; - x3 += lastX; - y3 += lastY; - } - - x2 = lastX + (lastX - lastX2); - y2 = lastY + (lastY - lastY2); - path.cubicTo (x2, y2, x, y, x3, y3); - - lastX2 = x; - lastY2 = y; - lastX = x3; - lastY = y3; - } - else - { - ++index; - } - break; - - case T('Q'): - case T('q'): - if (parseCoords (d, x, y, index, false) - && parseCoords (d, x2, y2, index, false)) - { - if (isRelative) - { - x += lastX; - y += lastY; - x2 += lastX; - y2 += lastY; - } - - path.quadraticTo (x, y, x2, y2); - - lastX2 = x; - lastY2 = y; - lastX = x2; - lastY = y2; - } - else - { - ++index; - } - break; - - case T('T'): - case T('t'): - if (parseCoords (d, x, y, index, false)) - { - if (isRelative) - { - x += lastX; - y += lastY; - } - - x2 = lastX + (lastX - lastX2); - y2 = lastY + (lastY - lastY2); - path.quadraticTo (x2, y2, x, y); - - lastX2 = x2; - lastY2 = y2; - lastX = x; - lastY = y; - } - else - { - ++index; - } - break; - - case T('A'): - case T('a'): - if (parseCoords (d, x, y, index, false)) - { - String num; - - if (parseNextNumber (d, num, index, false)) - { - const float angle = num.getFloatValue() * (180.0f / float_Pi); - - if (parseNextNumber (d, num, index, false)) - { - const bool largeArc = num.getIntValue() != 0; - - if (parseNextNumber (d, num, index, false)) - { - const bool sweep = num.getIntValue() != 0; - - if (parseCoords (d, x2, y2, index, false)) - { - if (isRelative) - { - x2 += lastX; - y2 += lastY; - } - - if (lastX != x2 || lastY != y2) - { - double centreX, centreY, startAngle, deltaAngle; - double rx = x, ry = y; - - endpointToCentreParameters (lastX, lastY, x2, y2, - angle, largeArc, sweep, - rx, ry, centreX, centreY, - startAngle, deltaAngle); - - path.addCentredArc ((float) centreX, (float) centreY, - (float) rx, (float) ry, - angle, (float) startAngle, (float) (startAngle + deltaAngle), - false); - - path.lineTo (x2, y2); - } - - lastX2 = lastX; - lastY2 = lastY; - lastX = x2; - lastY = y2; - } - } - } - } - } - else - { - ++index; - } - - break; - - case T('Z'): - case T('z'): - path.closeSubPath(); - while (CharacterFunctions::isWhitespace (d [index])) - ++index; - - break; - - default: - carryOn = false; - break; - } - - if (! carryOn) - break; - } - - return parseShape (xml, path); - } - - Drawable* parseRect (const XmlElement& xml) const - { - Path rect; - - const bool hasRX = xml.hasAttribute (T("rx")); - const bool hasRY = xml.hasAttribute (T("ry")); - - if (hasRX || hasRY) - { - float rx = getCoordLength (xml.getStringAttribute (T("rx")), viewBoxW); - float ry = getCoordLength (xml.getStringAttribute (T("ry")), viewBoxH); - - if (! hasRX) - rx = ry; - else if (! hasRY) - ry = rx; - - rect.addRoundedRectangle (getCoordLength (xml.getStringAttribute (T("x")), viewBoxW), - getCoordLength (xml.getStringAttribute (T("y")), viewBoxH), - getCoordLength (xml.getStringAttribute (T("width")), viewBoxW), - getCoordLength (xml.getStringAttribute (T("height")), viewBoxH), - rx, ry); - } - else - { - rect.addRectangle (getCoordLength (xml.getStringAttribute (T("x")), viewBoxW), - getCoordLength (xml.getStringAttribute (T("y")), viewBoxH), - getCoordLength (xml.getStringAttribute (T("width")), viewBoxW), - getCoordLength (xml.getStringAttribute (T("height")), viewBoxH)); - } - - return parseShape (xml, rect); - } - - Drawable* parseCircle (const XmlElement& xml) const - { - Path circle; - - const float cx = getCoordLength (xml.getStringAttribute (T("cx")), viewBoxW); - const float cy = getCoordLength (xml.getStringAttribute (T("cy")), viewBoxH); - const float radius = getCoordLength (xml.getStringAttribute (T("r")), viewBoxW); - - circle.addEllipse (cx - radius, cy - radius, radius * 2.0f, radius * 2.0f); - - return parseShape (xml, circle); - } - - Drawable* parseEllipse (const XmlElement& xml) const - { - Path ellipse; - - const float cx = getCoordLength (xml.getStringAttribute (T("cx")), viewBoxW); - const float cy = getCoordLength (xml.getStringAttribute (T("cy")), viewBoxH); - const float radiusX = getCoordLength (xml.getStringAttribute (T("rx")), viewBoxW); - const float radiusY = getCoordLength (xml.getStringAttribute (T("ry")), viewBoxH); - - ellipse.addEllipse (cx - radiusX, cy - radiusY, radiusX * 2.0f, radiusY * 2.0f); - - return parseShape (xml, ellipse); - } - - Drawable* parseLine (const XmlElement& xml) const - { - Path line; - - const float x1 = getCoordLength (xml.getStringAttribute (T("x1")), viewBoxW); - const float y1 = getCoordLength (xml.getStringAttribute (T("y1")), viewBoxH); - const float x2 = getCoordLength (xml.getStringAttribute (T("x2")), viewBoxW); - const float y2 = getCoordLength (xml.getStringAttribute (T("y2")), viewBoxH); - - line.startNewSubPath (x1, y1); - line.lineTo (x2, y2); - - return parseShape (xml, line); - } - - Drawable* parsePolygon (const XmlElement& xml, const bool isPolyline) const - { - const String points (xml.getStringAttribute (T("points"))); - Path path; - - int index = 0; - float x, y; - - if (parseCoords (points, x, y, index, true)) - { - float firstX = x; - float firstY = y; - float lastX = 0, lastY = 0; - - path.startNewSubPath (x, y); - - while (parseCoords (points, x, y, index, true)) - { - lastX = x; - lastY = y; - path.lineTo (x, y); - } - - if ((! isPolyline) || (firstX == lastX && firstY == lastY)) - path.closeSubPath(); - } - - return parseShape (xml, path); - } - - Drawable* parseShape (const XmlElement& xml, Path& path, - const bool shouldParseTransform = true) const - { - if (shouldParseTransform && xml.hasAttribute (T("transform"))) - { - SVGState newState (*this); - newState.addTransform (xml); - - return newState.parseShape (xml, path, false); - } - - DrawablePath* dp = new DrawablePath(); - dp->setName (xml.getStringAttribute (T("id"))); - dp->setFill (FillType (Colours::transparentBlack)); - - path.applyTransform (transform); - dp->setPath (path); - - Path::Iterator iter (path); - - bool containsClosedSubPath = false; - while (iter.next()) - { - if (iter.elementType == Path::Iterator::closePath) - { - containsClosedSubPath = true; - break; - } - } - - dp->setFill (getPathFillType (path, - getStyleAttribute (&xml, T("fill")), - getStyleAttribute (&xml, T("fill-opacity")), - getStyleAttribute (&xml, T("opacity")), - containsClosedSubPath ? Colours::black - : Colours::transparentBlack)); - - const String strokeType (getStyleAttribute (&xml, T("stroke"))); - - if (strokeType.isNotEmpty() && ! strokeType.equalsIgnoreCase (T("none"))) - { - dp->setStrokeFill (getPathFillType (path, strokeType, - getStyleAttribute (&xml, T("stroke-opacity")), - getStyleAttribute (&xml, T("opacity")), - Colours::transparentBlack)); - - dp->setStrokeType (getStrokeFor (&xml)); - } + const XmlElement* const topLevelXml; + float elementX, elementY, width, height, viewBoxW, viewBoxH; + AffineTransform transform; + String cssStyleText; + + void parseSubElements (const XmlElement& xml, DrawableComposite* const parentDrawable) + { + forEachXmlChildElement (xml, e) + { + Drawable* d = 0; + + if (e->hasTagName (T("g"))) + d = parseGroupElement (*e); + else if (e->hasTagName (T("svg"))) + d = parseSVGElement (*e); + else if (e->hasTagName (T("path"))) + d = parsePath (*e); + else if (e->hasTagName (T("rect"))) + d = parseRect (*e); + else if (e->hasTagName (T("circle"))) + d = parseCircle (*e); + else if (e->hasTagName (T("ellipse"))) + d = parseEllipse (*e); + else if (e->hasTagName (T("line"))) + d = parseLine (*e); + else if (e->hasTagName (T("polyline"))) + d = parsePolygon (*e, true); + else if (e->hasTagName (T("polygon"))) + d = parsePolygon (*e, false); + else if (e->hasTagName (T("text"))) + d = parseText (*e); + else if (e->hasTagName (T("switch"))) + d = parseSwitch (*e); + else if (e->hasTagName (T("style"))) + parseCSSStyle (*e); + + parentDrawable->insertDrawable (d); + } + } + + DrawableComposite* parseSwitch (const XmlElement& xml) + { + const XmlElement* const group = xml.getChildByName (T("g")); + + if (group != 0) + return parseGroupElement (*group); + + return 0; + } + + DrawableComposite* parseGroupElement (const XmlElement& xml) + { + DrawableComposite* const drawable = new DrawableComposite(); + + drawable->setName (xml.getStringAttribute (T("id"))); + + if (xml.hasAttribute (T("transform"))) + { + SVGState newState (*this); + newState.addTransform (xml); + + newState.parseSubElements (xml, drawable); + } + else + { + parseSubElements (xml, drawable); + } + + return drawable; + } + + Drawable* parsePath (const XmlElement& xml) const + { + const String d (xml.getStringAttribute (T("d")).trimStart()); + Path path; + + if (getStyleAttribute (&xml, T("fill-rule")).trim().equalsIgnoreCase (T("evenodd"))) + path.setUsingNonZeroWinding (false); + + int index = 0; + float lastX = 0, lastY = 0; + float lastX2 = 0, lastY2 = 0; + tchar lastCommandChar = 0; + bool carryOn = true; + + const String validCommandChars (T("MmLlHhVvCcSsQqTtAaZz")); + + for (;;) + { + float x, y, x2, y2, x3, y3; + const bool isRelative = (d[index] >= 'a' && d[index] <= 'z'); + + if (validCommandChars.containsChar (d[index])) + lastCommandChar = d [index++]; + + switch (lastCommandChar) + { + case T('M'): + case T('m'): + case T('L'): + case T('l'): + if (parseCoords (d, x, y, index, false)) + { + if (isRelative) + { + x += lastX; + y += lastY; + } + + if (lastCommandChar == T('M') || lastCommandChar == T('m')) + path.startNewSubPath (x, y); + else + path.lineTo (x, y); + + lastX2 = lastX; + lastY2 = lastY; + lastX = x; + lastY = y; + } + else + { + ++index; + } + + break; + + case T('H'): + case T('h'): + if (parseCoord (d, x, index, false, true)) + { + if (isRelative) + x += lastX; + + path.lineTo (x, lastY); + + lastX2 = lastX; + lastX = x; + } + else + { + ++index; + } + break; + + case T('V'): + case T('v'): + if (parseCoord (d, y, index, false, false)) + { + if (isRelative) + y += lastY; + + path.lineTo (lastX, y); + + lastY2 = lastY; + lastY = y; + } + else + { + ++index; + } + break; + + case T('C'): + case T('c'): + if (parseCoords (d, x, y, index, false) + && parseCoords (d, x2, y2, index, false) + && parseCoords (d, x3, y3, index, false)) + { + if (isRelative) + { + x += lastX; + y += lastY; + x2 += lastX; + y2 += lastY; + x3 += lastX; + y3 += lastY; + } + + path.cubicTo (x, y, x2, y2, x3, y3); + + lastX2 = x2; + lastY2 = y2; + lastX = x3; + lastY = y3; + } + else + { + ++index; + } + break; + + case T('S'): + case T('s'): + if (parseCoords (d, x, y, index, false) + && parseCoords (d, x3, y3, index, false)) + { + if (isRelative) + { + x += lastX; + y += lastY; + x3 += lastX; + y3 += lastY; + } + + x2 = lastX + (lastX - lastX2); + y2 = lastY + (lastY - lastY2); + path.cubicTo (x2, y2, x, y, x3, y3); + + lastX2 = x; + lastY2 = y; + lastX = x3; + lastY = y3; + } + else + { + ++index; + } + break; + + case T('Q'): + case T('q'): + if (parseCoords (d, x, y, index, false) + && parseCoords (d, x2, y2, index, false)) + { + if (isRelative) + { + x += lastX; + y += lastY; + x2 += lastX; + y2 += lastY; + } + + path.quadraticTo (x, y, x2, y2); + + lastX2 = x; + lastY2 = y; + lastX = x2; + lastY = y2; + } + else + { + ++index; + } + break; + + case T('T'): + case T('t'): + if (parseCoords (d, x, y, index, false)) + { + if (isRelative) + { + x += lastX; + y += lastY; + } + + x2 = lastX + (lastX - lastX2); + y2 = lastY + (lastY - lastY2); + path.quadraticTo (x2, y2, x, y); + + lastX2 = x2; + lastY2 = y2; + lastX = x; + lastY = y; + } + else + { + ++index; + } + break; + + case T('A'): + case T('a'): + if (parseCoords (d, x, y, index, false)) + { + String num; + + if (parseNextNumber (d, num, index, false)) + { + const float angle = num.getFloatValue() * (180.0f / float_Pi); + + if (parseNextNumber (d, num, index, false)) + { + const bool largeArc = num.getIntValue() != 0; + + if (parseNextNumber (d, num, index, false)) + { + const bool sweep = num.getIntValue() != 0; + + if (parseCoords (d, x2, y2, index, false)) + { + if (isRelative) + { + x2 += lastX; + y2 += lastY; + } + + if (lastX != x2 || lastY != y2) + { + double centreX, centreY, startAngle, deltaAngle; + double rx = x, ry = y; + + endpointToCentreParameters (lastX, lastY, x2, y2, + angle, largeArc, sweep, + rx, ry, centreX, centreY, + startAngle, deltaAngle); + + path.addCentredArc ((float) centreX, (float) centreY, + (float) rx, (float) ry, + angle, (float) startAngle, (float) (startAngle + deltaAngle), + false); + + path.lineTo (x2, y2); + } + + lastX2 = lastX; + lastY2 = lastY; + lastX = x2; + lastY = y2; + } + } + } + } + } + else + { + ++index; + } + + break; + + case T('Z'): + case T('z'): + path.closeSubPath(); + while (CharacterFunctions::isWhitespace (d [index])) + ++index; + + break; + + default: + carryOn = false; + break; + } + + if (! carryOn) + break; + } + + return parseShape (xml, path); + } + + Drawable* parseRect (const XmlElement& xml) const + { + Path rect; + + const bool hasRX = xml.hasAttribute (T("rx")); + const bool hasRY = xml.hasAttribute (T("ry")); + + if (hasRX || hasRY) + { + float rx = getCoordLength (xml.getStringAttribute (T("rx")), viewBoxW); + float ry = getCoordLength (xml.getStringAttribute (T("ry")), viewBoxH); + + if (! hasRX) + rx = ry; + else if (! hasRY) + ry = rx; + + rect.addRoundedRectangle (getCoordLength (xml.getStringAttribute (T("x")), viewBoxW), + getCoordLength (xml.getStringAttribute (T("y")), viewBoxH), + getCoordLength (xml.getStringAttribute (T("width")), viewBoxW), + getCoordLength (xml.getStringAttribute (T("height")), viewBoxH), + rx, ry); + } + else + { + rect.addRectangle (getCoordLength (xml.getStringAttribute (T("x")), viewBoxW), + getCoordLength (xml.getStringAttribute (T("y")), viewBoxH), + getCoordLength (xml.getStringAttribute (T("width")), viewBoxW), + getCoordLength (xml.getStringAttribute (T("height")), viewBoxH)); + } + + return parseShape (xml, rect); + } + + Drawable* parseCircle (const XmlElement& xml) const + { + Path circle; + + const float cx = getCoordLength (xml.getStringAttribute (T("cx")), viewBoxW); + const float cy = getCoordLength (xml.getStringAttribute (T("cy")), viewBoxH); + const float radius = getCoordLength (xml.getStringAttribute (T("r")), viewBoxW); + + circle.addEllipse (cx - radius, cy - radius, radius * 2.0f, radius * 2.0f); + + return parseShape (xml, circle); + } + + Drawable* parseEllipse (const XmlElement& xml) const + { + Path ellipse; + + const float cx = getCoordLength (xml.getStringAttribute (T("cx")), viewBoxW); + const float cy = getCoordLength (xml.getStringAttribute (T("cy")), viewBoxH); + const float radiusX = getCoordLength (xml.getStringAttribute (T("rx")), viewBoxW); + const float radiusY = getCoordLength (xml.getStringAttribute (T("ry")), viewBoxH); + + ellipse.addEllipse (cx - radiusX, cy - radiusY, radiusX * 2.0f, radiusY * 2.0f); + + return parseShape (xml, ellipse); + } + + Drawable* parseLine (const XmlElement& xml) const + { + Path line; + + const float x1 = getCoordLength (xml.getStringAttribute (T("x1")), viewBoxW); + const float y1 = getCoordLength (xml.getStringAttribute (T("y1")), viewBoxH); + const float x2 = getCoordLength (xml.getStringAttribute (T("x2")), viewBoxW); + const float y2 = getCoordLength (xml.getStringAttribute (T("y2")), viewBoxH); + + line.startNewSubPath (x1, y1); + line.lineTo (x2, y2); + + return parseShape (xml, line); + } + + Drawable* parsePolygon (const XmlElement& xml, const bool isPolyline) const + { + const String points (xml.getStringAttribute (T("points"))); + Path path; + + int index = 0; + float x, y; + + if (parseCoords (points, x, y, index, true)) + { + float firstX = x; + float firstY = y; + float lastX = 0, lastY = 0; + + path.startNewSubPath (x, y); + + while (parseCoords (points, x, y, index, true)) + { + lastX = x; + lastY = y; + path.lineTo (x, y); + } + + if ((! isPolyline) || (firstX == lastX && firstY == lastY)) + path.closeSubPath(); + } + + return parseShape (xml, path); + } + + Drawable* parseShape (const XmlElement& xml, Path& path, + const bool shouldParseTransform = true) const + { + if (shouldParseTransform && xml.hasAttribute (T("transform"))) + { + SVGState newState (*this); + newState.addTransform (xml); + + return newState.parseShape (xml, path, false); + } + + DrawablePath* dp = new DrawablePath(); + dp->setName (xml.getStringAttribute (T("id"))); + dp->setFill (FillType (Colours::transparentBlack)); + + path.applyTransform (transform); + dp->setPath (path); + + Path::Iterator iter (path); + + bool containsClosedSubPath = false; + while (iter.next()) + { + if (iter.elementType == Path::Iterator::closePath) + { + containsClosedSubPath = true; + break; + } + } + + dp->setFill (getPathFillType (path, + getStyleAttribute (&xml, T("fill")), + getStyleAttribute (&xml, T("fill-opacity")), + getStyleAttribute (&xml, T("opacity")), + containsClosedSubPath ? Colours::black + : Colours::transparentBlack)); + + const String strokeType (getStyleAttribute (&xml, T("stroke"))); + + if (strokeType.isNotEmpty() && ! strokeType.equalsIgnoreCase (T("none"))) + { + dp->setStrokeFill (getPathFillType (path, strokeType, + getStyleAttribute (&xml, T("stroke-opacity")), + getStyleAttribute (&xml, T("opacity")), + Colours::transparentBlack)); + + dp->setStrokeType (getStrokeFor (&xml)); + } - return dp; - } + return dp; + } - const XmlElement* findLinkedElement (const XmlElement* e) const - { - const String id (e->getStringAttribute (T("xlink:href"))); - - if (! id.startsWithChar (T('#'))) - return 0; - - return findElementForId (topLevelXml, id.substring (1)); - } - - void addGradientStopsIn (ColourGradient& cg, const XmlElement* const fillXml) const - { - if (fillXml == 0) - return; - - forEachXmlChildElementWithTagName (*fillXml, e, T("stop")) - { - int index = 0; - Colour col (parseColour (getStyleAttribute (e, T("stop-color")), index, Colours::black)); - - const String opacity (getStyleAttribute (e, T("stop-opacity"), T("1"))); - col = col.withMultipliedAlpha (jlimit (0.0f, 1.0f, opacity.getFloatValue())); - - double offset = e->getDoubleAttribute (T("offset")); - - if (e->getStringAttribute (T("offset")).containsChar (T('%'))) - offset *= 0.01; - - cg.addColour (jlimit (0.0, 1.0, offset), col); - } - } - - const FillType getPathFillType (const Path& path, - const String& fill, - const String& fillOpacity, - const String& overallOpacity, - const Colour& defaultColour) const - { - float opacity = 1.0f; - - if (overallOpacity.isNotEmpty()) - opacity = jlimit (0.0f, 1.0f, overallOpacity.getFloatValue()); - - if (fillOpacity.isNotEmpty()) - opacity *= (jlimit (0.0f, 1.0f, fillOpacity.getFloatValue())); - - if (fill.startsWithIgnoreCase (T("url"))) - { - const String id (fill.fromFirstOccurrenceOf (T("#"), false, false) - .upToLastOccurrenceOf (T(")"), false, false).trim()); - - const XmlElement* const fillXml = findElementForId (topLevelXml, id); - - if (fillXml != 0 - && (fillXml->hasTagName (T("linearGradient")) - || fillXml->hasTagName (T("radialGradient")))) - { - const XmlElement* inheritedFrom = findLinkedElement (fillXml); - - ColourGradient gradient; - - addGradientStopsIn (gradient, inheritedFrom); - addGradientStopsIn (gradient, fillXml); - - if (gradient.getNumColours() > 0) - { - gradient.addColour (0.0, gradient.getColour (0)); - gradient.addColour (1.0, gradient.getColour (gradient.getNumColours() - 1)); - } - else - { - gradient.addColour (0.0, Colours::black); - gradient.addColour (1.0, Colours::black); - } - - if (overallOpacity.isNotEmpty()) - gradient.multiplyOpacity (overallOpacity.getFloatValue()); - - jassert (gradient.getNumColours() > 0); - - gradient.isRadial = fillXml->hasTagName (T("radialGradient")); - - float width = viewBoxW; - float height = viewBoxH; - float dx = 0.0f; - float dy = 0.0f; - - const bool userSpace = fillXml->getStringAttribute (T("gradientUnits")).equalsIgnoreCase (T("userSpaceOnUse")); - - if (! userSpace) - path.getBounds (dx, dy, width, height); - - if (gradient.isRadial) - { - gradient.x1 = dx + getCoordLength (fillXml->getStringAttribute (T("cx"), T("50%")), width); - gradient.y1 = dy + getCoordLength (fillXml->getStringAttribute (T("cy"), T("50%")), height); - - const float radius = getCoordLength (fillXml->getStringAttribute (T("r"), T("50%")), width); - - gradient.x2 = gradient.x1 + radius; - gradient.y2 = gradient.y1; - - //xxx (the fx, fy focal point isn't handled properly here..) - } - else - { - gradient.x1 = dx + getCoordLength (fillXml->getStringAttribute (T("x1"), T("0%")), width); - gradient.y1 = dy + getCoordLength (fillXml->getStringAttribute (T("y1"), T("0%")), height); - - gradient.x2 = dx + getCoordLength (fillXml->getStringAttribute (T("x2"), T("100%")), width); - gradient.y2 = dy + getCoordLength (fillXml->getStringAttribute (T("y2"), T("0%")), height); - - if (gradient.x1 == gradient.x2 && gradient.y1 == gradient.y2) - return Colour (gradient.getColour (gradient.getNumColours() - 1)); - } - - FillType type (gradient); - type.transform = parseTransform (fillXml->getStringAttribute (T("gradientTransform"))) - .followedBy (transform); - return type; - } - } - - if (fill.equalsIgnoreCase (T("none"))) - return Colours::transparentBlack; - - int i = 0; - const Colour colour (parseColour (fill, i, defaultColour)); - return colour.withMultipliedAlpha (opacity); - } - - const PathStrokeType getStrokeFor (const XmlElement* const xml) const - { - const String width (getStyleAttribute (xml, T("stroke-width"))); - const String cap (getStyleAttribute (xml, T("stroke-linecap"))); - const String join (getStyleAttribute (xml, T("stroke-linejoin"))); - - //const String mitreLimit (getStyleAttribute (xml, T("stroke-miterlimit"))); - //const String dashArray (getStyleAttribute (xml, T("stroke-dasharray"))); - //const String dashOffset (getStyleAttribute (xml, T("stroke-dashoffset"))); - - PathStrokeType::JointStyle joinStyle = PathStrokeType::mitered; - PathStrokeType::EndCapStyle capStyle = PathStrokeType::butt; - - if (join.equalsIgnoreCase (T("round"))) - joinStyle = PathStrokeType::curved; - else if (join.equalsIgnoreCase (T("bevel"))) - joinStyle = PathStrokeType::beveled; - - if (cap.equalsIgnoreCase (T("round"))) - capStyle = PathStrokeType::rounded; - else if (cap.equalsIgnoreCase (T("square"))) - capStyle = PathStrokeType::square; - - float ox = 0.0f, oy = 0.0f; - transform.transformPoint (ox, oy); - float x = getCoordLength (width, viewBoxW), y = 0.0f; - transform.transformPoint (x, y); - - return PathStrokeType (width.isNotEmpty() ? juce_hypotf (x - ox, y - oy) : 1.0f, - joinStyle, capStyle); - } - - Drawable* parseText (const XmlElement& xml) - { - Array xCoords, yCoords, dxCoords, dyCoords; - - getCoordList (xCoords, getInheritedAttribute (&xml, T("x")), true, true); - getCoordList (yCoords, getInheritedAttribute (&xml, T("y")), true, false); - getCoordList (dxCoords, getInheritedAttribute (&xml, T("dx")), true, true); - getCoordList (dyCoords, getInheritedAttribute (&xml, T("dy")), true, false); - - //xxx not done text yet! - - forEachXmlChildElement (xml, e) - { - if (e->isTextElement()) - { - const String text (e->getText()); - - Path path; - Drawable* s = parseShape (*e, path); - delete s; - } - else if (e->hasTagName (T("tspan"))) - { - Drawable* s = parseText (*e); - delete s; - } - } - - return 0; - } - - void addTransform (const XmlElement& xml) - { - transform = parseTransform (xml.getStringAttribute (T("transform"))) - .followedBy (transform); - } - - bool parseCoord (const String& s, float& value, int& index, - const bool allowUnits, const bool isX) const - { - String number; - - if (! parseNextNumber (s, number, index, allowUnits)) - { - value = 0; - return false; - } - - value = getCoordLength (number, isX ? viewBoxW : viewBoxH); - return true; - } - - bool parseCoords (const String& s, float& x, float& y, - int& index, const bool allowUnits) const - { - return parseCoord (s, x, index, allowUnits, true) - && parseCoord (s, y, index, allowUnits, false); - } - - float getCoordLength (const String& s, const float sizeForProportions) const - { - float n = s.getFloatValue(); - const int len = s.length(); - - if (len > 2) - { - const float dpi = 96.0f; - - const tchar n1 = s [len - 2]; - const tchar n2 = s [len - 1]; - - if (n1 == T('i') && n2 == T('n')) - n *= dpi; - else if (n1 == T('m') && n2 == T('m')) - n *= dpi / 25.4f; - else if (n1 == T('c') && n2 == T('m')) - n *= dpi / 2.54f; - else if (n1 == T('p') && n2 == T('c')) - n *= 15.0f; - else if (n2 == T('%')) - n *= 0.01f * sizeForProportions; - } - - return n; - } - - void getCoordList (Array & coords, const String& list, - const bool allowUnits, const bool isX) const - { - int index = 0; - float value; - - while (parseCoord (list, value, index, allowUnits, isX)) - coords.add (value); - } - - void parseCSSStyle (const XmlElement& xml) - { - cssStyleText = xml.getAllSubText() + T("\n") + cssStyleText; - } - - const String getStyleAttribute (const XmlElement* xml, const String& attributeName, - const String& defaultValue = String::empty) const - { - if (xml->hasAttribute (attributeName)) - return xml->getStringAttribute (attributeName, defaultValue); - - const String styleAtt (xml->getStringAttribute (T("style"))); - - if (styleAtt.isNotEmpty()) - { - const String value (getAttributeFromStyleList (styleAtt, attributeName, String::empty)); - - if (value.isNotEmpty()) - return value; - } - else if (xml->hasAttribute (T("class"))) - { - const String className (T(".") + xml->getStringAttribute (T("class"))); - - int index = cssStyleText.indexOfIgnoreCase (className + T(" ")); - - if (index < 0) - index = cssStyleText.indexOfIgnoreCase (className + T("{")); - - if (index >= 0) - { - const int openBracket = cssStyleText.indexOfChar (index, T('{')); - - if (openBracket > index) - { - const int closeBracket = cssStyleText.indexOfChar (openBracket, T('}')); - - if (closeBracket > openBracket) - { - const String value (getAttributeFromStyleList (cssStyleText.substring (openBracket + 1, closeBracket), attributeName, defaultValue)); - - if (value.isNotEmpty()) - return value; - } - } - } - } + const XmlElement* findLinkedElement (const XmlElement* e) const + { + const String id (e->getStringAttribute (T("xlink:href"))); + + if (! id.startsWithChar (T('#'))) + return 0; + + return findElementForId (topLevelXml, id.substring (1)); + } + + void addGradientStopsIn (ColourGradient& cg, const XmlElement* const fillXml) const + { + if (fillXml == 0) + return; + + forEachXmlChildElementWithTagName (*fillXml, e, T("stop")) + { + int index = 0; + Colour col (parseColour (getStyleAttribute (e, T("stop-color")), index, Colours::black)); + + const String opacity (getStyleAttribute (e, T("stop-opacity"), T("1"))); + col = col.withMultipliedAlpha (jlimit (0.0f, 1.0f, opacity.getFloatValue())); + + double offset = e->getDoubleAttribute (T("offset")); + + if (e->getStringAttribute (T("offset")).containsChar (T('%'))) + offset *= 0.01; + + cg.addColour (jlimit (0.0, 1.0, offset), col); + } + } + + const FillType getPathFillType (const Path& path, + const String& fill, + const String& fillOpacity, + const String& overallOpacity, + const Colour& defaultColour) const + { + float opacity = 1.0f; + + if (overallOpacity.isNotEmpty()) + opacity = jlimit (0.0f, 1.0f, overallOpacity.getFloatValue()); + + if (fillOpacity.isNotEmpty()) + opacity *= (jlimit (0.0f, 1.0f, fillOpacity.getFloatValue())); + + if (fill.startsWithIgnoreCase (T("url"))) + { + const String id (fill.fromFirstOccurrenceOf (T("#"), false, false) + .upToLastOccurrenceOf (T(")"), false, false).trim()); + + const XmlElement* const fillXml = findElementForId (topLevelXml, id); + + if (fillXml != 0 + && (fillXml->hasTagName (T("linearGradient")) + || fillXml->hasTagName (T("radialGradient")))) + { + const XmlElement* inheritedFrom = findLinkedElement (fillXml); + + ColourGradient gradient; + + addGradientStopsIn (gradient, inheritedFrom); + addGradientStopsIn (gradient, fillXml); + + if (gradient.getNumColours() > 0) + { + gradient.addColour (0.0, gradient.getColour (0)); + gradient.addColour (1.0, gradient.getColour (gradient.getNumColours() - 1)); + } + else + { + gradient.addColour (0.0, Colours::black); + gradient.addColour (1.0, Colours::black); + } + + if (overallOpacity.isNotEmpty()) + gradient.multiplyOpacity (overallOpacity.getFloatValue()); + + jassert (gradient.getNumColours() > 0); + + gradient.isRadial = fillXml->hasTagName (T("radialGradient")); + + float width = viewBoxW; + float height = viewBoxH; + float dx = 0.0f; + float dy = 0.0f; + + const bool userSpace = fillXml->getStringAttribute (T("gradientUnits")).equalsIgnoreCase (T("userSpaceOnUse")); + + if (! userSpace) + path.getBounds (dx, dy, width, height); + + if (gradient.isRadial) + { + gradient.x1 = dx + getCoordLength (fillXml->getStringAttribute (T("cx"), T("50%")), width); + gradient.y1 = dy + getCoordLength (fillXml->getStringAttribute (T("cy"), T("50%")), height); + + const float radius = getCoordLength (fillXml->getStringAttribute (T("r"), T("50%")), width); + + gradient.x2 = gradient.x1 + radius; + gradient.y2 = gradient.y1; + + //xxx (the fx, fy focal point isn't handled properly here..) + } + else + { + gradient.x1 = dx + getCoordLength (fillXml->getStringAttribute (T("x1"), T("0%")), width); + gradient.y1 = dy + getCoordLength (fillXml->getStringAttribute (T("y1"), T("0%")), height); + + gradient.x2 = dx + getCoordLength (fillXml->getStringAttribute (T("x2"), T("100%")), width); + gradient.y2 = dy + getCoordLength (fillXml->getStringAttribute (T("y2"), T("0%")), height); + + if (gradient.x1 == gradient.x2 && gradient.y1 == gradient.y2) + return Colour (gradient.getColour (gradient.getNumColours() - 1)); + } + + FillType type (gradient); + type.transform = parseTransform (fillXml->getStringAttribute (T("gradientTransform"))) + .followedBy (transform); + return type; + } + } + + if (fill.equalsIgnoreCase (T("none"))) + return Colours::transparentBlack; + + int i = 0; + const Colour colour (parseColour (fill, i, defaultColour)); + return colour.withMultipliedAlpha (opacity); + } + + const PathStrokeType getStrokeFor (const XmlElement* const xml) const + { + const String width (getStyleAttribute (xml, T("stroke-width"))); + const String cap (getStyleAttribute (xml, T("stroke-linecap"))); + const String join (getStyleAttribute (xml, T("stroke-linejoin"))); + + //const String mitreLimit (getStyleAttribute (xml, T("stroke-miterlimit"))); + //const String dashArray (getStyleAttribute (xml, T("stroke-dasharray"))); + //const String dashOffset (getStyleAttribute (xml, T("stroke-dashoffset"))); + + PathStrokeType::JointStyle joinStyle = PathStrokeType::mitered; + PathStrokeType::EndCapStyle capStyle = PathStrokeType::butt; + + if (join.equalsIgnoreCase (T("round"))) + joinStyle = PathStrokeType::curved; + else if (join.equalsIgnoreCase (T("bevel"))) + joinStyle = PathStrokeType::beveled; + + if (cap.equalsIgnoreCase (T("round"))) + capStyle = PathStrokeType::rounded; + else if (cap.equalsIgnoreCase (T("square"))) + capStyle = PathStrokeType::square; + + float ox = 0.0f, oy = 0.0f; + transform.transformPoint (ox, oy); + float x = getCoordLength (width, viewBoxW), y = 0.0f; + transform.transformPoint (x, y); + + return PathStrokeType (width.isNotEmpty() ? juce_hypotf (x - ox, y - oy) : 1.0f, + joinStyle, capStyle); + } + + Drawable* parseText (const XmlElement& xml) + { + Array xCoords, yCoords, dxCoords, dyCoords; + + getCoordList (xCoords, getInheritedAttribute (&xml, T("x")), true, true); + getCoordList (yCoords, getInheritedAttribute (&xml, T("y")), true, false); + getCoordList (dxCoords, getInheritedAttribute (&xml, T("dx")), true, true); + getCoordList (dyCoords, getInheritedAttribute (&xml, T("dy")), true, false); + + //xxx not done text yet! + + forEachXmlChildElement (xml, e) + { + if (e->isTextElement()) + { + const String text (e->getText()); + + Path path; + Drawable* s = parseShape (*e, path); + delete s; + } + else if (e->hasTagName (T("tspan"))) + { + Drawable* s = parseText (*e); + delete s; + } + } + + return 0; + } + + void addTransform (const XmlElement& xml) + { + transform = parseTransform (xml.getStringAttribute (T("transform"))) + .followedBy (transform); + } + + bool parseCoord (const String& s, float& value, int& index, + const bool allowUnits, const bool isX) const + { + String number; + + if (! parseNextNumber (s, number, index, allowUnits)) + { + value = 0; + return false; + } + + value = getCoordLength (number, isX ? viewBoxW : viewBoxH); + return true; + } + + bool parseCoords (const String& s, float& x, float& y, + int& index, const bool allowUnits) const + { + return parseCoord (s, x, index, allowUnits, true) + && parseCoord (s, y, index, allowUnits, false); + } + + float getCoordLength (const String& s, const float sizeForProportions) const + { + float n = s.getFloatValue(); + const int len = s.length(); + + if (len > 2) + { + const float dpi = 96.0f; + + const tchar n1 = s [len - 2]; + const tchar n2 = s [len - 1]; + + if (n1 == T('i') && n2 == T('n')) + n *= dpi; + else if (n1 == T('m') && n2 == T('m')) + n *= dpi / 25.4f; + else if (n1 == T('c') && n2 == T('m')) + n *= dpi / 2.54f; + else if (n1 == T('p') && n2 == T('c')) + n *= 15.0f; + else if (n2 == T('%')) + n *= 0.01f * sizeForProportions; + } + + return n; + } + + void getCoordList (Array & coords, const String& list, + const bool allowUnits, const bool isX) const + { + int index = 0; + float value; + + while (parseCoord (list, value, index, allowUnits, isX)) + coords.add (value); + } + + void parseCSSStyle (const XmlElement& xml) + { + cssStyleText = xml.getAllSubText() + T("\n") + cssStyleText; + } + + const String getStyleAttribute (const XmlElement* xml, const String& attributeName, + const String& defaultValue = String::empty) const + { + if (xml->hasAttribute (attributeName)) + return xml->getStringAttribute (attributeName, defaultValue); + + const String styleAtt (xml->getStringAttribute (T("style"))); + + if (styleAtt.isNotEmpty()) + { + const String value (getAttributeFromStyleList (styleAtt, attributeName, String::empty)); + + if (value.isNotEmpty()) + return value; + } + else if (xml->hasAttribute (T("class"))) + { + const String className (T(".") + xml->getStringAttribute (T("class"))); + + int index = cssStyleText.indexOfIgnoreCase (className + T(" ")); + + if (index < 0) + index = cssStyleText.indexOfIgnoreCase (className + T("{")); + + if (index >= 0) + { + const int openBracket = cssStyleText.indexOfChar (index, T('{')); + + if (openBracket > index) + { + const int closeBracket = cssStyleText.indexOfChar (openBracket, T('}')); + + if (closeBracket > openBracket) + { + const String value (getAttributeFromStyleList (cssStyleText.substring (openBracket + 1, closeBracket), attributeName, defaultValue)); + + if (value.isNotEmpty()) + return value; + } + } + } + } - xml = const_cast (topLevelXml)->findParentElementOf (xml); + xml = const_cast (topLevelXml)->findParentElementOf (xml); - if (xml != 0) - return getStyleAttribute (xml, attributeName, defaultValue); + if (xml != 0) + return getStyleAttribute (xml, attributeName, defaultValue); - return defaultValue; - } + return defaultValue; + } - const String getInheritedAttribute (const XmlElement* xml, const String& attributeName) const - { - if (xml->hasAttribute (attributeName)) - return xml->getStringAttribute (attributeName); + const String getInheritedAttribute (const XmlElement* xml, const String& attributeName) const + { + if (xml->hasAttribute (attributeName)) + return xml->getStringAttribute (attributeName); - xml = const_cast (topLevelXml)->findParentElementOf (xml); + xml = const_cast (topLevelXml)->findParentElementOf (xml); - if (xml != 0) - return getInheritedAttribute (xml, attributeName); + if (xml != 0) + return getInheritedAttribute (xml, attributeName); - return String::empty; - } + return String::empty; + } - static bool isIdentifierChar (const tchar c) - { - return CharacterFunctions::isLetter (c) || c == T('-'); - } - - static const String getAttributeFromStyleList (const String& list, const String& attributeName, const String& defaultValue) - { - int i = 0; - - for (;;) - { - i = list.indexOf (i, attributeName); - - if (i < 0) - break; - - if ((i == 0 || (i > 0 && ! isIdentifierChar (list [i - 1]))) - && ! isIdentifierChar (list [i + attributeName.length()])) - { - i = list.indexOfChar (i, T(':')); - - if (i < 0) - break; - - int end = list.indexOfChar (i, T(';')); - - if (end < 0) - end = 0x7ffff; - - return list.substring (i + 1, end).trim(); - } - - ++i; - } - - return defaultValue; - } - - static bool parseNextNumber (const String& source, String& value, int& index, const bool allowUnits) - { - const tchar* const s = (const tchar*) source; - - while (CharacterFunctions::isWhitespace (s[index]) || s[index] == T(',')) - ++index; - - int start = index; - - if (CharacterFunctions::isDigit (s[index]) || s[index] == T('.') || s[index] == T('-')) - ++index; - - while (CharacterFunctions::isDigit (s[index]) || s[index] == T('.')) - ++index; - - if ((s[index] == T('e') || s[index] == T('E')) - && (CharacterFunctions::isDigit (s[index + 1]) - || s[index + 1] == T('-') - || s[index + 1] == T('+'))) - { - index += 2; - - while (CharacterFunctions::isDigit (s[index])) - ++index; - } - - if (allowUnits) - { - while (CharacterFunctions::isLetter (s[index])) - ++index; - } - - if (index == start) - return false; - - value = String (s + start, index - start); - - while (CharacterFunctions::isWhitespace (s[index]) || s[index] == T(',')) - ++index; - - return true; - } - - static const Colour parseColour (const String& s, int& index, const Colour& defaultColour) - { - if (s [index] == T('#')) - { - uint32 hex [6]; - zeromem (hex, sizeof (hex)); - int numChars = 0; - - for (int i = 6; --i >= 0;) - { - const int hexValue = CharacterFunctions::getHexDigitValue (s [++index]); - - if (hexValue >= 0) - hex [numChars++] = hexValue; - else - break; - } - - if (numChars <= 3) - return Colour ((uint8) (hex [0] * 0x11), - (uint8) (hex [1] * 0x11), - (uint8) (hex [2] * 0x11)); - else - return Colour ((uint8) ((hex [0] << 4) + hex [1]), - (uint8) ((hex [2] << 4) + hex [3]), - (uint8) ((hex [4] << 4) + hex [5])); - } - else if (s [index] == T('r') - && s [index + 1] == T('g') - && s [index + 2] == T('b')) - { - const int openBracket = s.indexOfChar (index, T('(')); - const int closeBracket = s.indexOfChar (openBracket, T(')')); - - if (openBracket >= 3 && closeBracket > openBracket) - { - index = closeBracket; - - StringArray tokens; - tokens.addTokens (s.substring (openBracket + 1, closeBracket), T(","), T("")); - tokens.trim(); - tokens.removeEmptyStrings(); - - if (tokens[0].containsChar (T('%'))) - return Colour ((uint8) roundDoubleToInt (2.55 * tokens[0].getDoubleValue()), - (uint8) roundDoubleToInt (2.55 * tokens[1].getDoubleValue()), - (uint8) roundDoubleToInt (2.55 * tokens[2].getDoubleValue())); - else - return Colour ((uint8) tokens[0].getIntValue(), - (uint8) tokens[1].getIntValue(), - (uint8) tokens[2].getIntValue()); - } - } - - return Colours::findColourForName (s, defaultColour); - } - - static const AffineTransform parseTransform (String t) - { - AffineTransform result; - - while (t.isNotEmpty()) - { - StringArray tokens; - tokens.addTokens (t.fromFirstOccurrenceOf (T("("), false, false) - .upToFirstOccurrenceOf (T(")"), false, false), - T(", "), 0); - - tokens.removeEmptyStrings (true); - - float numbers [6]; - - for (int i = 0; i < 6; ++i) - numbers[i] = tokens[i].getFloatValue(); - - AffineTransform trans; - - if (t.startsWithIgnoreCase (T("matrix"))) - { - trans = AffineTransform (numbers[0], numbers[2], numbers[4], - numbers[1], numbers[3], numbers[5]); - } - else if (t.startsWithIgnoreCase (T("translate"))) - { - trans = trans.translated (numbers[0], numbers[1]); - } - else if (t.startsWithIgnoreCase (T("scale"))) - { - if (tokens.size() == 1) - trans = trans.scaled (numbers[0], numbers[0]); - else - trans = trans.scaled (numbers[0], numbers[1]); - } - else if (t.startsWithIgnoreCase (T("rotate"))) - { - if (tokens.size() != 3) - trans = trans.rotated (numbers[0] / (180.0f / float_Pi)); - else - trans = trans.rotated (numbers[0] / (180.0f / float_Pi), - numbers[1], numbers[2]); - } - else if (t.startsWithIgnoreCase (T("skewX"))) - { - trans = AffineTransform (1.0f, tanf (numbers[0] * (float_Pi / 180.0f)), 0.0f, - 0.0f, 1.0f, 0.0f); - } - else if (t.startsWithIgnoreCase (T("skewY"))) - { - trans = AffineTransform (1.0f, 0.0f, 0.0f, - tanf (numbers[0] * (float_Pi / 180.0f)), 1.0f, 0.0f); - } - - result = trans.followedBy (result); - t = t.fromFirstOccurrenceOf (T(")"), false, false).trimStart(); - } - - return result; - } - - static void endpointToCentreParameters (const double x1, const double y1, - const double x2, const double y2, - const double angle, - const bool largeArc, const bool sweep, - double& rx, double& ry, - double& centreX, double& centreY, - double& startAngle, double& deltaAngle) - { - const double midX = (x1 - x2) * 0.5; - const double midY = (y1 - y2) * 0.5; - - const double cosAngle = cos (angle); - const double sinAngle = sin (angle); - const double xp = cosAngle * midX + sinAngle * midY; - const double yp = cosAngle * midY - sinAngle * midX; - const double xp2 = xp * xp; - const double yp2 = yp * yp; - - double rx2 = rx * rx; - double ry2 = ry * ry; - - const double s = (xp2 / rx2) + (yp2 / ry2); - double c; - - if (s <= 1.0) - { - c = sqrt (jmax (0.0, ((rx2 * ry2) - (rx2 * yp2) - (ry2 * xp2)) - / (( rx2 * yp2) + (ry2 * xp2)))); - - if (largeArc == sweep) - c = -c; - } - else - { - const double s2 = sqrt (s); - rx *= s2; - ry *= s2; - rx2 = rx * rx; - ry2 = ry * ry; - c = 0; - } - - const double cpx = ((rx * yp) / ry) * c; - const double cpy = ((-ry * xp) / rx) * c; - - centreX = ((x1 + x2) * 0.5) + (cosAngle * cpx) - (sinAngle * cpy); - centreY = ((y1 + y2) * 0.5) + (sinAngle * cpx) + (cosAngle * cpy); - - const double ux = (xp - cpx) / rx; - const double uy = (yp - cpy) / ry; - const double vx = (-xp - cpx) / rx; - const double vy = (-yp - cpy) / ry; - - const double length = juce_hypot (ux, uy); - - startAngle = acos (jlimit (-1.0, 1.0, ux / length)); - - if (uy < 0) - startAngle = -startAngle; - - startAngle += double_Pi * 0.5; - - deltaAngle = acos (jlimit (-1.0, 1.0, ((ux * vx) + (uy * vy)) - / (length * juce_hypot (vx, vy)))); - - if ((ux * vy) - (uy * vx) < 0) - deltaAngle = -deltaAngle; - - if (sweep) - { - if (deltaAngle < 0) - deltaAngle += double_Pi * 2.0; - } - else - { - if (deltaAngle > 0) - deltaAngle -= double_Pi * 2.0; - } - - deltaAngle = fmod (deltaAngle, double_Pi * 2.0); - } - - static const XmlElement* findElementForId (const XmlElement* const parent, const String& id) - { - forEachXmlChildElement (*parent, e) - { - if (e->compareAttribute (T("id"), id)) - return e; - - const XmlElement* const found = findElementForId (e, id); - - if (found != 0) - return found; - } - - return 0; - } - - const SVGState& operator= (const SVGState&); + static bool isIdentifierChar (const tchar c) + { + return CharacterFunctions::isLetter (c) || c == T('-'); + } + + static const String getAttributeFromStyleList (const String& list, const String& attributeName, const String& defaultValue) + { + int i = 0; + + for (;;) + { + i = list.indexOf (i, attributeName); + + if (i < 0) + break; + + if ((i == 0 || (i > 0 && ! isIdentifierChar (list [i - 1]))) + && ! isIdentifierChar (list [i + attributeName.length()])) + { + i = list.indexOfChar (i, T(':')); + + if (i < 0) + break; + + int end = list.indexOfChar (i, T(';')); + + if (end < 0) + end = 0x7ffff; + + return list.substring (i + 1, end).trim(); + } + + ++i; + } + + return defaultValue; + } + + static bool parseNextNumber (const String& source, String& value, int& index, const bool allowUnits) + { + const tchar* const s = (const tchar*) source; + + while (CharacterFunctions::isWhitespace (s[index]) || s[index] == T(',')) + ++index; + + int start = index; + + if (CharacterFunctions::isDigit (s[index]) || s[index] == T('.') || s[index] == T('-')) + ++index; + + while (CharacterFunctions::isDigit (s[index]) || s[index] == T('.')) + ++index; + + if ((s[index] == T('e') || s[index] == T('E')) + && (CharacterFunctions::isDigit (s[index + 1]) + || s[index + 1] == T('-') + || s[index + 1] == T('+'))) + { + index += 2; + + while (CharacterFunctions::isDigit (s[index])) + ++index; + } + + if (allowUnits) + { + while (CharacterFunctions::isLetter (s[index])) + ++index; + } + + if (index == start) + return false; + + value = String (s + start, index - start); + + while (CharacterFunctions::isWhitespace (s[index]) || s[index] == T(',')) + ++index; + + return true; + } + + static const Colour parseColour (const String& s, int& index, const Colour& defaultColour) + { + if (s [index] == T('#')) + { + uint32 hex [6]; + zeromem (hex, sizeof (hex)); + int numChars = 0; + + for (int i = 6; --i >= 0;) + { + const int hexValue = CharacterFunctions::getHexDigitValue (s [++index]); + + if (hexValue >= 0) + hex [numChars++] = hexValue; + else + break; + } + + if (numChars <= 3) + return Colour ((uint8) (hex [0] * 0x11), + (uint8) (hex [1] * 0x11), + (uint8) (hex [2] * 0x11)); + else + return Colour ((uint8) ((hex [0] << 4) + hex [1]), + (uint8) ((hex [2] << 4) + hex [3]), + (uint8) ((hex [4] << 4) + hex [5])); + } + else if (s [index] == T('r') + && s [index + 1] == T('g') + && s [index + 2] == T('b')) + { + const int openBracket = s.indexOfChar (index, T('(')); + const int closeBracket = s.indexOfChar (openBracket, T(')')); + + if (openBracket >= 3 && closeBracket > openBracket) + { + index = closeBracket; + + StringArray tokens; + tokens.addTokens (s.substring (openBracket + 1, closeBracket), T(","), T("")); + tokens.trim(); + tokens.removeEmptyStrings(); + + if (tokens[0].containsChar (T('%'))) + return Colour ((uint8) roundToInt (2.55 * tokens[0].getDoubleValue()), + (uint8) roundToInt (2.55 * tokens[1].getDoubleValue()), + (uint8) roundToInt (2.55 * tokens[2].getDoubleValue())); + else + return Colour ((uint8) tokens[0].getIntValue(), + (uint8) tokens[1].getIntValue(), + (uint8) tokens[2].getIntValue()); + } + } + + return Colours::findColourForName (s, defaultColour); + } + + static const AffineTransform parseTransform (String t) + { + AffineTransform result; + + while (t.isNotEmpty()) + { + StringArray tokens; + tokens.addTokens (t.fromFirstOccurrenceOf (T("("), false, false) + .upToFirstOccurrenceOf (T(")"), false, false), + T(", "), 0); + + tokens.removeEmptyStrings (true); + + float numbers [6]; + + for (int i = 0; i < 6; ++i) + numbers[i] = tokens[i].getFloatValue(); + + AffineTransform trans; + + if (t.startsWithIgnoreCase (T("matrix"))) + { + trans = AffineTransform (numbers[0], numbers[2], numbers[4], + numbers[1], numbers[3], numbers[5]); + } + else if (t.startsWithIgnoreCase (T("translate"))) + { + trans = trans.translated (numbers[0], numbers[1]); + } + else if (t.startsWithIgnoreCase (T("scale"))) + { + if (tokens.size() == 1) + trans = trans.scaled (numbers[0], numbers[0]); + else + trans = trans.scaled (numbers[0], numbers[1]); + } + else if (t.startsWithIgnoreCase (T("rotate"))) + { + if (tokens.size() != 3) + trans = trans.rotated (numbers[0] / (180.0f / float_Pi)); + else + trans = trans.rotated (numbers[0] / (180.0f / float_Pi), + numbers[1], numbers[2]); + } + else if (t.startsWithIgnoreCase (T("skewX"))) + { + trans = AffineTransform (1.0f, tanf (numbers[0] * (float_Pi / 180.0f)), 0.0f, + 0.0f, 1.0f, 0.0f); + } + else if (t.startsWithIgnoreCase (T("skewY"))) + { + trans = AffineTransform (1.0f, 0.0f, 0.0f, + tanf (numbers[0] * (float_Pi / 180.0f)), 1.0f, 0.0f); + } + + result = trans.followedBy (result); + t = t.fromFirstOccurrenceOf (T(")"), false, false).trimStart(); + } + + return result; + } + + static void endpointToCentreParameters (const double x1, const double y1, + const double x2, const double y2, + const double angle, + const bool largeArc, const bool sweep, + double& rx, double& ry, + double& centreX, double& centreY, + double& startAngle, double& deltaAngle) + { + const double midX = (x1 - x2) * 0.5; + const double midY = (y1 - y2) * 0.5; + + const double cosAngle = cos (angle); + const double sinAngle = sin (angle); + const double xp = cosAngle * midX + sinAngle * midY; + const double yp = cosAngle * midY - sinAngle * midX; + const double xp2 = xp * xp; + const double yp2 = yp * yp; + + double rx2 = rx * rx; + double ry2 = ry * ry; + + const double s = (xp2 / rx2) + (yp2 / ry2); + double c; + + if (s <= 1.0) + { + c = sqrt (jmax (0.0, ((rx2 * ry2) - (rx2 * yp2) - (ry2 * xp2)) + / (( rx2 * yp2) + (ry2 * xp2)))); + + if (largeArc == sweep) + c = -c; + } + else + { + const double s2 = sqrt (s); + rx *= s2; + ry *= s2; + rx2 = rx * rx; + ry2 = ry * ry; + c = 0; + } + + const double cpx = ((rx * yp) / ry) * c; + const double cpy = ((-ry * xp) / rx) * c; + + centreX = ((x1 + x2) * 0.5) + (cosAngle * cpx) - (sinAngle * cpy); + centreY = ((y1 + y2) * 0.5) + (sinAngle * cpx) + (cosAngle * cpy); + + const double ux = (xp - cpx) / rx; + const double uy = (yp - cpy) / ry; + const double vx = (-xp - cpx) / rx; + const double vy = (-yp - cpy) / ry; + + const double length = juce_hypot (ux, uy); + + startAngle = acos (jlimit (-1.0, 1.0, ux / length)); + + if (uy < 0) + startAngle = -startAngle; + + startAngle += double_Pi * 0.5; + + deltaAngle = acos (jlimit (-1.0, 1.0, ((ux * vx) + (uy * vy)) + / (length * juce_hypot (vx, vy)))); + + if ((ux * vy) - (uy * vx) < 0) + deltaAngle = -deltaAngle; + + if (sweep) + { + if (deltaAngle < 0) + deltaAngle += double_Pi * 2.0; + } + else + { + if (deltaAngle > 0) + deltaAngle -= double_Pi * 2.0; + } + + deltaAngle = fmod (deltaAngle, double_Pi * 2.0); + } + + static const XmlElement* findElementForId (const XmlElement* const parent, const String& id) + { + forEachXmlChildElement (*parent, e) + { + if (e->compareAttribute (T("id"), id)) + return e; + + const XmlElement* const found = findElementForId (e, id); + + if (found != 0) + return found; + } + + return 0; + } + + const SVGState& operator= (const SVGState&); }; Drawable* Drawable::createFromSVG (const XmlElement& svgDocument) { - SVGState state (&svgDocument); - return state.parseSVGElement (svgDocument); + SVGState state (&svgDocument); + return state.parseSVGElement (svgDocument); } END_JUCE_NAMESPACE @@ -85561,9 +85352,9 @@ BEGIN_JUCE_NAMESPACE DropShadowEffect::DropShadowEffect() : offsetX (0), - offsetY (0), - radius (4), - opacity (0.6f) + offsetY (0), + radius (4), + opacity (0.6f) { } @@ -85572,63 +85363,63 @@ DropShadowEffect::~DropShadowEffect() } void DropShadowEffect::setShadowProperties (const float newRadius, - const float newOpacity, - const int newShadowOffsetX, - const int newShadowOffsetY) + const float newOpacity, + const int newShadowOffsetX, + const int newShadowOffsetY) { - radius = jmax (1.1f, newRadius); - offsetX = newShadowOffsetX; - offsetY = newShadowOffsetY; - opacity = newOpacity; + radius = jmax (1.1f, newRadius); + offsetX = newShadowOffsetX; + offsetY = newShadowOffsetY; + opacity = newOpacity; } void DropShadowEffect::applyEffect (Image& image, Graphics& g) { - const int w = image.getWidth(); - const int h = image.getHeight(); + const int w = image.getWidth(); + const int h = image.getHeight(); - Image shadowImage (Image::SingleChannel, w, h, false); + Image shadowImage (Image::SingleChannel, w, h, false); - const Image::BitmapData srcData (image, 0, 0, w, h); - const Image::BitmapData destData (shadowImage, 0, 0, w, h, true); + const Image::BitmapData srcData (image, 0, 0, w, h); + const Image::BitmapData destData (shadowImage, 0, 0, w, h, true); - const int filter = roundFloatToInt (63.0f / radius); - const int radiusMinus1 = roundFloatToInt ((radius - 1.0f) * 63.0f); + const int filter = roundToInt (63.0f / radius); + const int radiusMinus1 = roundToInt ((radius - 1.0f) * 63.0f); - for (int x = w; --x >= 0;) - { - int shadowAlpha = 0; + for (int x = w; --x >= 0;) + { + int shadowAlpha = 0; - const PixelARGB* src = ((const PixelARGB*) srcData.data) + x; - uint8* shadowPix = destData.data + x; + const PixelARGB* src = ((const PixelARGB*) srcData.data) + x; + uint8* shadowPix = destData.data + x; - for (int y = h; --y >= 0;) - { - shadowAlpha = ((shadowAlpha * radiusMinus1 + (src->getAlpha() << 6)) * filter) >> 12; + for (int y = h; --y >= 0;) + { + shadowAlpha = ((shadowAlpha * radiusMinus1 + (src->getAlpha() << 6)) * filter) >> 12; - *shadowPix = (uint8) shadowAlpha; - src = (const PixelARGB*) (((const uint8*) src) + srcData.lineStride); - shadowPix += destData.lineStride; - } - } + *shadowPix = (uint8) shadowAlpha; + src = (const PixelARGB*) (((const uint8*) src) + srcData.lineStride); + shadowPix += destData.lineStride; + } + } - for (int y = h; --y >= 0;) - { - int shadowAlpha = 0; - uint8* shadowPix = destData.getLinePointer (y); + for (int y = h; --y >= 0;) + { + int shadowAlpha = 0; + uint8* shadowPix = destData.getLinePointer (y); - for (int x = w; --x >= 0;) - { - shadowAlpha = ((shadowAlpha * radiusMinus1 + (*shadowPix << 6)) * filter) >> 12; - *shadowPix++ = (uint8) shadowAlpha; - } - } + for (int x = w; --x >= 0;) + { + shadowAlpha = ((shadowAlpha * radiusMinus1 + (*shadowPix << 6)) * filter) >> 12; + *shadowPix++ = (uint8) shadowAlpha; + } + } - g.setColour (Colours::black.withAlpha (opacity)); - g.drawImageAt (&shadowImage, offsetX, offsetY, true); + g.setColour (Colours::black.withAlpha (opacity)); + g.drawImageAt (&shadowImage, offsetX, offsetY, true); - g.setOpacity (1.0f); - g.drawImageAt (&image, 0, 0); + g.setOpacity (1.0f); + g.drawImageAt (&image, 0, 0); } END_JUCE_NAMESPACE @@ -85640,7 +85431,7 @@ BEGIN_JUCE_NAMESPACE GlowEffect::GlowEffect() : radius (2.0f), - colour (Colours::white) + colour (Colours::white) { } @@ -85649,31 +85440,31 @@ GlowEffect::~GlowEffect() } void GlowEffect::setGlowProperties (const float newRadius, - const Colour& newColour) + const Colour& newColour) { - radius = newRadius; - colour = newColour; + radius = newRadius; + colour = newColour; } void GlowEffect::applyEffect (Image& image, Graphics& g) { - const int w = image.getWidth(); - const int h = image.getHeight(); + const int w = image.getWidth(); + const int h = image.getHeight(); - Image temp (image.getFormat(), w, h, true); + Image temp (image.getFormat(), w, h, true); - ImageConvolutionKernel blurKernel (roundFloatToInt (radius * 2.0f)); + ImageConvolutionKernel blurKernel (roundToInt (radius * 2.0f)); - blurKernel.createGaussianBlur (radius); - blurKernel.rescaleAllValues (radius); + blurKernel.createGaussianBlur (radius); + blurKernel.rescaleAllValues (radius); - blurKernel.applyToImage (temp, &image, 0, 0, w, h); + blurKernel.applyToImage (temp, &image, 0, 0, w, h); - g.setColour (colour); - g.drawImageAt (&temp, 0, 0, true); + g.setColour (colour); + g.drawImageAt (&temp, 0, 0, true); - g.setOpacity (1.0f); - g.drawImageAt (&image, 0, 0, false); + g.setOpacity (1.0f); + g.drawImageAt (&image, 0, 0, false); } END_JUCE_NAMESPACE @@ -85684,7 +85475,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ReduceOpacityEffect::ReduceOpacityEffect (const float opacity_) - : opacity (opacity_) + : opacity (opacity_) { } @@ -85694,13 +85485,13 @@ ReduceOpacityEffect::~ReduceOpacityEffect() void ReduceOpacityEffect::setOpacity (const float newOpacity) { - opacity = jlimit (0.0f, 1.0f, newOpacity); + opacity = jlimit (0.0f, 1.0f, newOpacity); } void ReduceOpacityEffect::applyEffect (Image& image, Graphics& g) { - g.setOpacity (opacity); - g.drawImageAt (&image, 0, 0); + g.setOpacity (opacity); + g.drawImageAt (&image, 0, 0); } END_JUCE_NAMESPACE @@ -85721,58 +85512,58 @@ static const tchar* const juce_defaultFontNameMono = T(""); void clearUpDefaultFontNames() throw(); // in juce_LookAndFeel.cpp Font::SharedFontInternal::SharedFontInternal (const String& typefaceName_, const float height_, const float horizontalScale_, - const float kerning_, const float ascent_, const int styleFlags_, - Typeface* const typeface_) throw() - : typefaceName (typefaceName_), - height (height_), - horizontalScale (horizontalScale_), - kerning (kerning_), - ascent (ascent_), - styleFlags (styleFlags_), - typeface (typeface_) + const float kerning_, const float ascent_, const int styleFlags_, + Typeface* const typeface_) throw() + : typefaceName (typefaceName_), + height (height_), + horizontalScale (horizontalScale_), + kerning (kerning_), + ascent (ascent_), + styleFlags (styleFlags_), + typeface (typeface_) { } Font::SharedFontInternal::SharedFontInternal (const SharedFontInternal& other) throw() - : typefaceName (other.typefaceName), - height (other.height), - horizontalScale (other.horizontalScale), - kerning (other.kerning), - ascent (other.ascent), - styleFlags (other.styleFlags), - typeface (other.typeface) + : typefaceName (other.typefaceName), + height (other.height), + horizontalScale (other.horizontalScale), + kerning (other.kerning), + ascent (other.ascent), + styleFlags (other.styleFlags), + typeface (other.typeface) { } Font::Font() throw() - : font (new SharedFontInternal (juce_defaultFontNameSans, defaultFontHeight, - 1.0f, 0, 0, Font::plain, 0)) + : font (new SharedFontInternal (juce_defaultFontNameSans, defaultFontHeight, + 1.0f, 0, 0, Font::plain, 0)) { } Font::Font (const float fontHeight, const int styleFlags_) throw() - : font (new SharedFontInternal (juce_defaultFontNameSans, jlimit (minFontHeight, maxFontHeight, fontHeight), - 1.0f, 0, 0, styleFlags_, 0)) + : font (new SharedFontInternal (juce_defaultFontNameSans, jlimit (minFontHeight, maxFontHeight, fontHeight), + 1.0f, 0, 0, styleFlags_, 0)) { } Font::Font (const String& typefaceName_, - const float fontHeight, - const int styleFlags_) throw() - : font (new SharedFontInternal (typefaceName_, jlimit (minFontHeight, maxFontHeight, fontHeight), - 1.0f, 0, 0, styleFlags_, 0)) + const float fontHeight, + const int styleFlags_) throw() + : font (new SharedFontInternal (typefaceName_, jlimit (minFontHeight, maxFontHeight, fontHeight), + 1.0f, 0, 0, styleFlags_, 0)) { } Font::Font (const Font& other) throw() - : font (other.font) + : font (other.font) { } const Font& Font::operator= (const Font& other) throw() { - font = other.font; - return *this; + font = other.font; + return *this; } Font::~Font() throw() @@ -85780,321 +85571,320 @@ Font::~Font() throw() } Font::Font (const Typeface::Ptr& typeface) throw() - : font (new SharedFontInternal (typeface->getName(), defaultFontHeight, - 1.0f, 0, 0, Font::plain, typeface)) + : font (new SharedFontInternal (typeface->getName(), defaultFontHeight, + 1.0f, 0, 0, Font::plain, typeface)) { } bool Font::operator== (const Font& other) const throw() { - return font == other.font - || (font->height == other.font->height - && font->styleFlags == other.font->styleFlags - && font->horizontalScale == other.font->horizontalScale - && font->kerning == other.font->kerning - && font->typefaceName == other.font->typefaceName); + return font == other.font + || (font->height == other.font->height + && font->styleFlags == other.font->styleFlags + && font->horizontalScale == other.font->horizontalScale + && font->kerning == other.font->kerning + && font->typefaceName == other.font->typefaceName); } bool Font::operator!= (const Font& other) const throw() { - return ! operator== (other); + return ! operator== (other); } void Font::dupeInternalIfShared() throw() { - if (font->getReferenceCount() > 1) - font = new SharedFontInternal (*font); + if (font->getReferenceCount() > 1) + font = new SharedFontInternal (*font); } const String Font::getDefaultSansSerifFontName() throw() { - return juce_defaultFontNameSans; + return juce_defaultFontNameSans; } const String Font::getDefaultSerifFontName() throw() { - return juce_defaultFontNameSerif; + return juce_defaultFontNameSerif; } const String Font::getDefaultMonospacedFontName() throw() { - return juce_defaultFontNameMono; + return juce_defaultFontNameMono; } void Font::setTypefaceName (const String& faceName) throw() { - if (faceName != font->typefaceName) - { - dupeInternalIfShared(); - font->typefaceName = faceName; - font->typeface = 0; - font->ascent = 0; - } + if (faceName != font->typefaceName) + { + dupeInternalIfShared(); + font->typefaceName = faceName; + font->typeface = 0; + font->ascent = 0; + } } static String fallbackFont; const String Font::getFallbackFontName() throw() { - return fallbackFont; + return fallbackFont; } void Font::setFallbackFontName (const String& name) throw() { - fallbackFont = name; + fallbackFont = name; } void Font::setHeight (float newHeight) throw() { - newHeight = jlimit (minFontHeight, maxFontHeight, newHeight); + newHeight = jlimit (minFontHeight, maxFontHeight, newHeight); - if (font->height != newHeight) - { - dupeInternalIfShared(); - font->height = newHeight; - } + if (font->height != newHeight) + { + dupeInternalIfShared(); + font->height = newHeight; + } } void Font::setHeightWithoutChangingWidth (float newHeight) throw() { - newHeight = jlimit (minFontHeight, maxFontHeight, newHeight); + newHeight = jlimit (minFontHeight, maxFontHeight, newHeight); - if (font->height != newHeight) - { - dupeInternalIfShared(); - font->horizontalScale *= (font->height / newHeight); - font->height = newHeight; - } + if (font->height != newHeight) + { + dupeInternalIfShared(); + font->horizontalScale *= (font->height / newHeight); + font->height = newHeight; + } } void Font::setStyleFlags (const int newFlags) throw() { - if (font->styleFlags != newFlags) - { - dupeInternalIfShared(); - font->styleFlags = newFlags; - font->typeface = 0; - font->ascent = 0; - } + if (font->styleFlags != newFlags) + { + dupeInternalIfShared(); + font->styleFlags = newFlags; + font->typeface = 0; + font->ascent = 0; + } } void Font::setSizeAndStyle (float newHeight, - const int newStyleFlags, - const float newHorizontalScale, - const float newKerningAmount) throw() + const int newStyleFlags, + const float newHorizontalScale, + const float newKerningAmount) throw() { - newHeight = jlimit (minFontHeight, maxFontHeight, newHeight); + newHeight = jlimit (minFontHeight, maxFontHeight, newHeight); - if (font->height != newHeight - || font->horizontalScale != newHorizontalScale - || font->kerning != newKerningAmount) - { - dupeInternalIfShared(); - font->height = newHeight; - font->horizontalScale = newHorizontalScale; - font->kerning = newKerningAmount; - } + if (font->height != newHeight + || font->horizontalScale != newHorizontalScale + || font->kerning != newKerningAmount) + { + dupeInternalIfShared(); + font->height = newHeight; + font->horizontalScale = newHorizontalScale; + font->kerning = newKerningAmount; + } - setStyleFlags (newStyleFlags); + setStyleFlags (newStyleFlags); } void Font::setHorizontalScale (const float scaleFactor) throw() { - dupeInternalIfShared(); - font->horizontalScale = scaleFactor; + dupeInternalIfShared(); + font->horizontalScale = scaleFactor; } void Font::setExtraKerningFactor (const float extraKerning) throw() { - dupeInternalIfShared(); - font->kerning = extraKerning; + dupeInternalIfShared(); + font->kerning = extraKerning; } void Font::setBold (const bool shouldBeBold) throw() { - setStyleFlags (shouldBeBold ? (font->styleFlags | bold) - : (font->styleFlags & ~bold)); + setStyleFlags (shouldBeBold ? (font->styleFlags | bold) + : (font->styleFlags & ~bold)); } bool Font::isBold() const throw() { - return (font->styleFlags & bold) != 0; + return (font->styleFlags & bold) != 0; } void Font::setItalic (const bool shouldBeItalic) throw() { - setStyleFlags (shouldBeItalic ? (font->styleFlags | italic) - : (font->styleFlags & ~italic)); + setStyleFlags (shouldBeItalic ? (font->styleFlags | italic) + : (font->styleFlags & ~italic)); } bool Font::isItalic() const throw() { - return (font->styleFlags & italic) != 0; + return (font->styleFlags & italic) != 0; } void Font::setUnderline (const bool shouldBeUnderlined) throw() { - setStyleFlags (shouldBeUnderlined ? (font->styleFlags | underlined) - : (font->styleFlags & ~underlined)); + setStyleFlags (shouldBeUnderlined ? (font->styleFlags | underlined) + : (font->styleFlags & ~underlined)); } bool Font::isUnderlined() const throw() { - return (font->styleFlags & underlined) != 0; + return (font->styleFlags & underlined) != 0; } float Font::getAscent() const throw() { - if (font->ascent == 0) - font->ascent = getTypeface()->getAscent(); + if (font->ascent == 0) + font->ascent = getTypeface()->getAscent(); - return font->height * font->ascent; + return font->height * font->ascent; } float Font::getDescent() const throw() { - return font->height - getAscent(); + return font->height - getAscent(); } int Font::getStringWidth (const String& text) const throw() { - return roundFloatToInt (getStringWidthFloat (text)); + return roundToInt (getStringWidthFloat (text)); } float Font::getStringWidthFloat (const String& text) const throw() { - float w = getTypeface()->getStringWidth (text); + float w = getTypeface()->getStringWidth (text); - if (font->kerning != 0) - w += font->kerning * text.length(); + if (font->kerning != 0) + w += font->kerning * text.length(); - return w * font->height * font->horizontalScale; + return w * font->height * font->horizontalScale; } void Font::getGlyphPositions (const String& text, Array & glyphs, Array & xOffsets) const throw() { - getTypeface()->getGlyphPositions (text, glyphs, xOffsets); + getTypeface()->getGlyphPositions (text, glyphs, xOffsets); - const float scale = font->height * font->horizontalScale; - const int num = xOffsets.size(); + const float scale = font->height * font->horizontalScale; + const int num = xOffsets.size(); - if (num > 0) - { - float* const x = &(xOffsets.getReference(0)); + if (num > 0) + { + float* const x = &(xOffsets.getReference(0)); - if (font->kerning != 0) - { - for (int i = 0; i < num; ++i) - x[i] = (x[i] + i * font->kerning) * scale; - } - else - { - for (int i = 0; i < num; ++i) - x[i] *= scale; - } - } + if (font->kerning != 0) + { + for (int i = 0; i < num; ++i) + x[i] = (x[i] + i * font->kerning) * scale; + } + else + { + for (int i = 0; i < num; ++i) + x[i] *= scale; + } + } } void Font::findFonts (OwnedArray& destArray) throw() { - const StringArray names (findAllTypefaceNames()); + const StringArray names (findAllTypefaceNames()); - for (int i = 0; i < names.size(); ++i) - destArray.add (new Font (names[i], defaultFontHeight, Font::plain)); + for (int i = 0; i < names.size(); ++i) + destArray.add (new Font (names[i], defaultFontHeight, Font::plain)); } class TypefaceCache : public DeletedAtShutdown { public: - TypefaceCache (int numToCache = 10) throw() - : counter (1), - faces (2) - { - while (--numToCache >= 0) - faces.add (new CachedFace()); - } + TypefaceCache (int numToCache = 10) throw() + : counter (1) + { + while (--numToCache >= 0) + faces.add (new CachedFace()); + } - ~TypefaceCache() - { - clearUpDefaultFontNames(); - clearSingletonInstance(); - } + ~TypefaceCache() + { + clearUpDefaultFontNames(); + clearSingletonInstance(); + } - juce_DeclareSingleton_SingleThreaded_Minimal (TypefaceCache) + juce_DeclareSingleton_SingleThreaded_Minimal (TypefaceCache) - const Typeface::Ptr findTypefaceFor (const Font& font) throw() - { - const int flags = font.getStyleFlags() & (Font::bold | Font::italic); - const String faceName (font.getTypefaceName()); + const Typeface::Ptr findTypefaceFor (const Font& font) throw() + { + const int flags = font.getStyleFlags() & (Font::bold | Font::italic); + const String faceName (font.getTypefaceName()); - int i; - for (i = faces.size(); --i >= 0;) - { - CachedFace* const face = faces.getUnchecked(i); + int i; + for (i = faces.size(); --i >= 0;) + { + CachedFace* const face = faces.getUnchecked(i); - if (face->flags == flags - && face->typefaceName == faceName) - { - face->lastUsageCount = ++counter; - return face->typeFace; - } - } + if (face->flags == flags + && face->typefaceName == faceName) + { + face->lastUsageCount = ++counter; + return face->typeFace; + } + } - int replaceIndex = 0; - int bestLastUsageCount = INT_MAX; + int replaceIndex = 0; + int bestLastUsageCount = INT_MAX; - for (i = faces.size(); --i >= 0;) - { - const int lu = faces.getUnchecked(i)->lastUsageCount; + for (i = faces.size(); --i >= 0;) + { + const int lu = faces.getUnchecked(i)->lastUsageCount; - if (bestLastUsageCount > lu) - { - bestLastUsageCount = lu; - replaceIndex = i; - } - } + if (bestLastUsageCount > lu) + { + bestLastUsageCount = lu; + replaceIndex = i; + } + } - CachedFace* const face = faces.getUnchecked (replaceIndex); - face->typefaceName = faceName; - face->flags = flags; - face->lastUsageCount = ++counter; - face->typeFace = LookAndFeel::getDefaultLookAndFeel().getTypefaceForFont (font); - jassert (face->typeFace != 0); // the look and feel must return a typeface! + CachedFace* const face = faces.getUnchecked (replaceIndex); + face->typefaceName = faceName; + face->flags = flags; + face->lastUsageCount = ++counter; + face->typeFace = LookAndFeel::getDefaultLookAndFeel().getTypefaceForFont (font); + jassert (face->typeFace != 0); // the look and feel must return a typeface! - return face->typeFace; - } + return face->typeFace; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - struct CachedFace - { - CachedFace() throw() - : lastUsageCount (0), flags (-1) - { - } + struct CachedFace + { + CachedFace() throw() + : lastUsageCount (0), flags (-1) + { + } - String typefaceName; - int lastUsageCount; - int flags; - Typeface::Ptr typeFace; - }; + String typefaceName; + int lastUsageCount; + int flags; + Typeface::Ptr typeFace; + }; - int counter; - OwnedArray faces; + int counter; + OwnedArray faces; - TypefaceCache (const TypefaceCache&); - const TypefaceCache& operator= (const TypefaceCache&); + TypefaceCache (const TypefaceCache&); + const TypefaceCache& operator= (const TypefaceCache&); }; juce_ImplementSingleton_SingleThreaded (TypefaceCache) Typeface* Font::getTypeface() const throw() { - if (font->typeface == 0) - font->typeface = TypefaceCache::getInstance()->findTypefaceFor (*this); + if (font->typeface == 0) + font->typeface = TypefaceCache::getInstance()->findTypefaceFor (*this); - return font->typeface; + return font->typeface; } END_JUCE_NAMESPACE @@ -86110,91 +85900,91 @@ PositionedGlyph::PositionedGlyph() void PositionedGlyph::draw (const Graphics& g) const { - if (! isWhitespace()) - { - g.getInternalContext()->setFont (font); - g.getInternalContext()->drawGlyph (glyph, AffineTransform::translation (x, y)); - } + if (! isWhitespace()) + { + g.getInternalContext()->setFont (font); + g.getInternalContext()->drawGlyph (glyph, AffineTransform::translation (x, y)); + } } void PositionedGlyph::draw (const Graphics& g, - const AffineTransform& transform) const + const AffineTransform& transform) const { - if (! isWhitespace()) - { - g.getInternalContext()->setFont (font); - g.getInternalContext()->drawGlyph (glyph, AffineTransform::translation (x, y) - .followedBy (transform)); - } + if (! isWhitespace()) + { + g.getInternalContext()->setFont (font); + g.getInternalContext()->drawGlyph (glyph, AffineTransform::translation (x, y) + .followedBy (transform)); + } } void PositionedGlyph::createPath (Path& path) const { - if (! isWhitespace()) - { - Typeface* const t = font.getTypeface(); + if (! isWhitespace()) + { + Typeface* const t = font.getTypeface(); - if (t != 0) - { - Path p; - t->getOutlineForGlyph (glyph, p); + if (t != 0) + { + Path p; + t->getOutlineForGlyph (glyph, p); - path.addPath (p, AffineTransform::scale (font.getHeight() * font.getHorizontalScale(), font.getHeight()) - .translated (x, y)); - } - } + path.addPath (p, AffineTransform::scale (font.getHeight() * font.getHorizontalScale(), font.getHeight()) + .translated (x, y)); + } + } } bool PositionedGlyph::hitTest (float px, float py) const { - if (px >= getLeft() && px < getRight() - && py >= getTop() && py < getBottom() - && ! isWhitespace()) - { - Typeface* const t = font.getTypeface(); + if (px >= getLeft() && px < getRight() + && py >= getTop() && py < getBottom() + && ! isWhitespace()) + { + Typeface* const t = font.getTypeface(); - if (t != 0) - { - Path p; - t->getOutlineForGlyph (glyph, p); + if (t != 0) + { + Path p; + t->getOutlineForGlyph (glyph, p); - AffineTransform::translation (-x, -y) - .scaled (1.0f / (font.getHeight() * font.getHorizontalScale()), 1.0f / font.getHeight()) - .transformPoint (px, py); + AffineTransform::translation (-x, -y) + .scaled (1.0f / (font.getHeight() * font.getHorizontalScale()), 1.0f / font.getHeight()) + .transformPoint (px, py); - return p.contains (px, py); - } - } + return p.contains (px, py); + } + } - return false; + return false; } void PositionedGlyph::moveBy (const float deltaX, - const float deltaY) + const float deltaY) { - x += deltaX; - y += deltaY; + x += deltaX; + y += deltaY; } GlyphArrangement::GlyphArrangement() - : glyphs (128) { + glyphs.ensureStorageAllocated (128); } GlyphArrangement::GlyphArrangement (const GlyphArrangement& other) { - addGlyphArrangement (other); + addGlyphArrangement (other); } const GlyphArrangement& GlyphArrangement::operator= (const GlyphArrangement& other) { - if (this != &other) - { - clear(); - addGlyphArrangement (other); - } + if (this != &other) + { + clear(); + addGlyphArrangement (other); + } - return *this; + return *this; } GlyphArrangement::~GlyphArrangement() @@ -86203,689 +85993,689 @@ GlyphArrangement::~GlyphArrangement() void GlyphArrangement::clear() { - glyphs.clear(); + glyphs.clear(); } PositionedGlyph& GlyphArrangement::getGlyph (const int index) const { - jassert (((unsigned int) index) < (unsigned int) glyphs.size()); + jassert (((unsigned int) index) < (unsigned int) glyphs.size()); - return *glyphs [index]; + return *glyphs [index]; } void GlyphArrangement::addGlyphArrangement (const GlyphArrangement& other) { - glyphs.ensureStorageAllocated (glyphs.size() + other.glyphs.size()); + glyphs.ensureStorageAllocated (glyphs.size() + other.glyphs.size()); - for (int i = 0; i < other.glyphs.size(); ++i) - glyphs.add (new PositionedGlyph (*other.glyphs.getUnchecked (i))); + for (int i = 0; i < other.glyphs.size(); ++i) + glyphs.add (new PositionedGlyph (*other.glyphs.getUnchecked (i))); } void GlyphArrangement::removeRangeOfGlyphs (int startIndex, const int num) { - glyphs.removeRange (startIndex, num < 0 ? glyphs.size() : num); + glyphs.removeRange (startIndex, num < 0 ? glyphs.size() : num); } void GlyphArrangement::addLineOfText (const Font& font, - const String& text, - const float xOffset, - const float yOffset) + const String& text, + const float xOffset, + const float yOffset) { - addCurtailedLineOfText (font, text, - xOffset, yOffset, - 1.0e10f, false); + addCurtailedLineOfText (font, text, + xOffset, yOffset, + 1.0e10f, false); } void GlyphArrangement::addCurtailedLineOfText (const Font& font, - const String& text, - float xOffset, - const float yOffset, - const float maxWidthPixels, - const bool useEllipsis) + const String& text, + float xOffset, + const float yOffset, + const float maxWidthPixels, + const bool useEllipsis) { - int textLen = text.length(); + int textLen = text.length(); - if (textLen > 0) - { - Array newGlyphs; - Array xOffsets; - font.getGlyphPositions (text, newGlyphs, xOffsets); + if (textLen > 0) + { + Array newGlyphs; + Array xOffsets; + font.getGlyphPositions (text, newGlyphs, xOffsets); - const juce_wchar* const unicodeText = (const juce_wchar*) text; - textLen = jmin (textLen, newGlyphs.size()); + const juce_wchar* const unicodeText = (const juce_wchar*) text; + textLen = jmin (textLen, newGlyphs.size()); - for (int i = 0; i < textLen; ++i) - { - const float thisX = xOffsets.getUnchecked (i); - const float nextX = xOffsets.getUnchecked (i + 1); + for (int i = 0; i < textLen; ++i) + { + const float thisX = xOffsets.getUnchecked (i); + const float nextX = xOffsets.getUnchecked (i + 1); - if (nextX > maxWidthPixels + 1.0f) - { - // curtail the string if it's too wide.. - if (useEllipsis && textLen > 3 && glyphs.size() >= 3) - insertEllipsis (font, xOffset + maxWidthPixels, 0, glyphs.size()); + if (nextX > maxWidthPixels + 1.0f) + { + // curtail the string if it's too wide.. + if (useEllipsis && textLen > 3 && glyphs.size() >= 3) + insertEllipsis (font, xOffset + maxWidthPixels, 0, glyphs.size()); - break; - } - else - { - PositionedGlyph* const pg = new PositionedGlyph(); - pg->x = xOffset + thisX; - pg->y = yOffset; - pg->w = nextX - thisX; - pg->font = font; - pg->glyph = newGlyphs.getUnchecked(i); - pg->character = unicodeText[i]; + break; + } + else + { + PositionedGlyph* const pg = new PositionedGlyph(); + pg->x = xOffset + thisX; + pg->y = yOffset; + pg->w = nextX - thisX; + pg->font = font; + pg->glyph = newGlyphs.getUnchecked(i); + pg->character = unicodeText[i]; - glyphs.add (pg); - } - } - } + glyphs.add (pg); + } + } + } } int GlyphArrangement::insertEllipsis (const Font& font, const float maxXPos, - const int startIndex, int endIndex) + const int startIndex, int endIndex) { - int numDeleted = 0; + int numDeleted = 0; - if (glyphs.size() > 0) - { - Array dotGlyphs; - Array dotXs; - font.getGlyphPositions (T(".."), dotGlyphs, dotXs); + if (glyphs.size() > 0) + { + Array dotGlyphs; + Array dotXs; + font.getGlyphPositions (T(".."), dotGlyphs, dotXs); - const float dx = dotXs[1]; - float xOffset = 0.0f, yOffset = 0.0f; + const float dx = dotXs[1]; + float xOffset = 0.0f, yOffset = 0.0f; - while (endIndex > startIndex) - { - const PositionedGlyph* pg = glyphs.getUnchecked (--endIndex); - xOffset = pg->x; - yOffset = pg->y; + while (endIndex > startIndex) + { + const PositionedGlyph* pg = glyphs.getUnchecked (--endIndex); + xOffset = pg->x; + yOffset = pg->y; - glyphs.remove (endIndex); - ++numDeleted; + glyphs.remove (endIndex); + ++numDeleted; - if (xOffset + dx * 3 <= maxXPos) - break; - } + if (xOffset + dx * 3 <= maxXPos) + break; + } - for (int i = 3; --i >= 0;) - { - PositionedGlyph* const pg = new PositionedGlyph(); - pg->x = xOffset; - pg->y = yOffset; - pg->w = dx; - pg->font = font; - pg->character = '.'; - pg->glyph = dotGlyphs.getFirst(); - glyphs.insert (endIndex++, pg); - --numDeleted; + for (int i = 3; --i >= 0;) + { + PositionedGlyph* const pg = new PositionedGlyph(); + pg->x = xOffset; + pg->y = yOffset; + pg->w = dx; + pg->font = font; + pg->character = '.'; + pg->glyph = dotGlyphs.getFirst(); + glyphs.insert (endIndex++, pg); + --numDeleted; - xOffset += dx; + xOffset += dx; - if (xOffset > maxXPos) - break; - } - } + if (xOffset > maxXPos) + break; + } + } - return numDeleted; + return numDeleted; } void GlyphArrangement::addJustifiedText (const Font& font, - const String& text, - float x, float y, - const float maxLineWidth, - const Justification& horizontalLayout) + const String& text, + float x, float y, + const float maxLineWidth, + const Justification& horizontalLayout) { - int lineStartIndex = glyphs.size(); - addLineOfText (font, text, x, y); + int lineStartIndex = glyphs.size(); + addLineOfText (font, text, x, y); - const float originalY = y; + const float originalY = y; - while (lineStartIndex < glyphs.size()) - { - int i = lineStartIndex; + while (lineStartIndex < glyphs.size()) + { + int i = lineStartIndex; - if (glyphs.getUnchecked(i)->getCharacter() != T('\n') - && glyphs.getUnchecked(i)->getCharacter() != T('\r')) - ++i; + if (glyphs.getUnchecked(i)->getCharacter() != T('\n') + && glyphs.getUnchecked(i)->getCharacter() != T('\r')) + ++i; - const float lineMaxX = glyphs.getUnchecked (lineStartIndex)->getLeft() + maxLineWidth; - int lastWordBreakIndex = -1; + const float lineMaxX = glyphs.getUnchecked (lineStartIndex)->getLeft() + maxLineWidth; + int lastWordBreakIndex = -1; - while (i < glyphs.size()) - { - const PositionedGlyph* pg = glyphs.getUnchecked (i); - const juce_wchar c = pg->getCharacter(); + while (i < glyphs.size()) + { + const PositionedGlyph* pg = glyphs.getUnchecked (i); + const juce_wchar c = pg->getCharacter(); - if (c == T('\r') || c == T('\n')) - { - ++i; + if (c == T('\r') || c == T('\n')) + { + ++i; - if (c == T('\r') && i < glyphs.size() - && glyphs.getUnchecked(i)->getCharacter() == T('\n')) - ++i; + if (c == T('\r') && i < glyphs.size() + && glyphs.getUnchecked(i)->getCharacter() == T('\n')) + ++i; - break; - } - else if (pg->isWhitespace()) - { - lastWordBreakIndex = i + 1; - } - else if (pg->getRight() - 0.0001f >= lineMaxX) - { - if (lastWordBreakIndex >= 0) - i = lastWordBreakIndex; + break; + } + else if (pg->isWhitespace()) + { + lastWordBreakIndex = i + 1; + } + else if (pg->getRight() - 0.0001f >= lineMaxX) + { + if (lastWordBreakIndex >= 0) + i = lastWordBreakIndex; - break; - } + break; + } - ++i; - } + ++i; + } - const float currentLineStartX = glyphs.getUnchecked (lineStartIndex)->getLeft(); - float currentLineEndX = currentLineStartX; + const float currentLineStartX = glyphs.getUnchecked (lineStartIndex)->getLeft(); + float currentLineEndX = currentLineStartX; - for (int j = i; --j >= lineStartIndex;) - { - if (! glyphs.getUnchecked (j)->isWhitespace()) - { - currentLineEndX = glyphs.getUnchecked (j)->getRight(); - break; - } - } + for (int j = i; --j >= lineStartIndex;) + { + if (! glyphs.getUnchecked (j)->isWhitespace()) + { + currentLineEndX = glyphs.getUnchecked (j)->getRight(); + break; + } + } - float deltaX = 0.0f; + float deltaX = 0.0f; - if (horizontalLayout.testFlags (Justification::horizontallyJustified)) - spreadOutLine (lineStartIndex, i - lineStartIndex, maxLineWidth); - else if (horizontalLayout.testFlags (Justification::horizontallyCentred)) - deltaX = (maxLineWidth - (currentLineEndX - currentLineStartX)) * 0.5f; - else if (horizontalLayout.testFlags (Justification::right)) - deltaX = maxLineWidth - (currentLineEndX - currentLineStartX); + if (horizontalLayout.testFlags (Justification::horizontallyJustified)) + spreadOutLine (lineStartIndex, i - lineStartIndex, maxLineWidth); + else if (horizontalLayout.testFlags (Justification::horizontallyCentred)) + deltaX = (maxLineWidth - (currentLineEndX - currentLineStartX)) * 0.5f; + else if (horizontalLayout.testFlags (Justification::right)) + deltaX = maxLineWidth - (currentLineEndX - currentLineStartX); - moveRangeOfGlyphs (lineStartIndex, i - lineStartIndex, - x + deltaX - currentLineStartX, y - originalY); + moveRangeOfGlyphs (lineStartIndex, i - lineStartIndex, + x + deltaX - currentLineStartX, y - originalY); - lineStartIndex = i; + lineStartIndex = i; - y += font.getHeight(); - } + y += font.getHeight(); + } } void GlyphArrangement::addFittedText (const Font& f, - const String& text, - const float x, const float y, - const float width, const float height, - const Justification& layout, - int maximumLines, - const float minimumHorizontalScale) + const String& text, + const float x, const float y, + const float width, const float height, + const Justification& layout, + int maximumLines, + const float minimumHorizontalScale) { - // doesn't make much sense if this is outside a sensible range of 0.5 to 1.0 - jassert (minimumHorizontalScale > 0 && minimumHorizontalScale <= 1.0f); + // doesn't make much sense if this is outside a sensible range of 0.5 to 1.0 + jassert (minimumHorizontalScale > 0 && minimumHorizontalScale <= 1.0f); - if (text.containsAnyOf (T("\r\n"))) - { - GlyphArrangement ga; - ga.addJustifiedText (f, text, x, y, width, layout); + if (text.containsAnyOf (T("\r\n"))) + { + GlyphArrangement ga; + ga.addJustifiedText (f, text, x, y, width, layout); - float l, t, r, b; - ga.getBoundingBox (0, -1, l, t, r, b, false); + float l, t, r, b; + ga.getBoundingBox (0, -1, l, t, r, b, false); - float dy = y - t; + float dy = y - t; - if (layout.testFlags (Justification::verticallyCentred)) - dy += (height - (b - t)) * 0.5f; - else if (layout.testFlags (Justification::bottom)) - dy += height - (b - t); + if (layout.testFlags (Justification::verticallyCentred)) + dy += (height - (b - t)) * 0.5f; + else if (layout.testFlags (Justification::bottom)) + dy += height - (b - t); - ga.moveRangeOfGlyphs (0, -1, 0.0f, dy); + ga.moveRangeOfGlyphs (0, -1, 0.0f, dy); - glyphs.ensureStorageAllocated (glyphs.size() + ga.glyphs.size()); + glyphs.ensureStorageAllocated (glyphs.size() + ga.glyphs.size()); - for (int i = 0; i < ga.glyphs.size(); ++i) - glyphs.add (ga.glyphs.getUnchecked (i)); + for (int i = 0; i < ga.glyphs.size(); ++i) + glyphs.add (ga.glyphs.getUnchecked (i)); - ga.glyphs.clear (false); - return; - } + ga.glyphs.clear (false); + return; + } - int startIndex = glyphs.size(); - addLineOfText (f, text.trim(), x, y); + int startIndex = glyphs.size(); + addLineOfText (f, text.trim(), x, y); - if (glyphs.size() > startIndex) - { - float lineWidth = glyphs.getUnchecked (glyphs.size() - 1)->getRight() - - glyphs.getUnchecked (startIndex)->getLeft(); + if (glyphs.size() > startIndex) + { + float lineWidth = glyphs.getUnchecked (glyphs.size() - 1)->getRight() + - glyphs.getUnchecked (startIndex)->getLeft(); - if (lineWidth <= 0) - return; + if (lineWidth <= 0) + return; - if (lineWidth * minimumHorizontalScale < width) - { - if (lineWidth > width) - stretchRangeOfGlyphs (startIndex, glyphs.size() - startIndex, - width / lineWidth); + if (lineWidth * minimumHorizontalScale < width) + { + if (lineWidth > width) + stretchRangeOfGlyphs (startIndex, glyphs.size() - startIndex, + width / lineWidth); - justifyGlyphs (startIndex, glyphs.size() - startIndex, - x, y, width, height, layout); - } - else if (maximumLines <= 1) - { - fitLineIntoSpace (startIndex, glyphs.size() - startIndex, - x, y, width, height, f, layout, minimumHorizontalScale); - } - else - { - Font font (f); - String txt (text.trim()); - const int length = txt.length(); - const int originalStartIndex = startIndex; - int numLines = 1; + justifyGlyphs (startIndex, glyphs.size() - startIndex, + x, y, width, height, layout); + } + else if (maximumLines <= 1) + { + fitLineIntoSpace (startIndex, glyphs.size() - startIndex, + x, y, width, height, f, layout, minimumHorizontalScale); + } + else + { + Font font (f); + String txt (text.trim()); + const int length = txt.length(); + const int originalStartIndex = startIndex; + int numLines = 1; - if (length <= 12 && ! txt.containsAnyOf (T(" -\t\r\n"))) - maximumLines = 1; + if (length <= 12 && ! txt.containsAnyOf (T(" -\t\r\n"))) + maximumLines = 1; - maximumLines = jmin (maximumLines, length); + maximumLines = jmin (maximumLines, length); - while (numLines < maximumLines) - { - ++numLines; + while (numLines < maximumLines) + { + ++numLines; - const float newFontHeight = height / (float) numLines; + const float newFontHeight = height / (float) numLines; - if (newFontHeight < font.getHeight()) - { - font.setHeight (jmax (8.0f, newFontHeight)); + if (newFontHeight < font.getHeight()) + { + font.setHeight (jmax (8.0f, newFontHeight)); - removeRangeOfGlyphs (startIndex, -1); - addLineOfText (font, txt, x, y); + removeRangeOfGlyphs (startIndex, -1); + addLineOfText (font, txt, x, y); - lineWidth = glyphs.getUnchecked (glyphs.size() - 1)->getRight() - - glyphs.getUnchecked (startIndex)->getLeft(); - } + lineWidth = glyphs.getUnchecked (glyphs.size() - 1)->getRight() + - glyphs.getUnchecked (startIndex)->getLeft(); + } - if (numLines > lineWidth / width || newFontHeight < 8.0f) - break; - } + if (numLines > lineWidth / width || newFontHeight < 8.0f) + break; + } - if (numLines < 1) - numLines = 1; + if (numLines < 1) + numLines = 1; - float lineY = y; - float widthPerLine = lineWidth / numLines; - int lastLineStartIndex = 0; + float lineY = y; + float widthPerLine = lineWidth / numLines; + int lastLineStartIndex = 0; - for (int line = 0; line < numLines; ++line) - { - int i = startIndex; - lastLineStartIndex = i; - float lineStartX = glyphs.getUnchecked (startIndex)->getLeft(); + for (int line = 0; line < numLines; ++line) + { + int i = startIndex; + lastLineStartIndex = i; + float lineStartX = glyphs.getUnchecked (startIndex)->getLeft(); - if (line == numLines - 1) - { - widthPerLine = width; - i = glyphs.size(); - } - else - { - while (i < glyphs.size()) - { - lineWidth = (glyphs.getUnchecked (i)->getRight() - lineStartX); + if (line == numLines - 1) + { + widthPerLine = width; + i = glyphs.size(); + } + else + { + while (i < glyphs.size()) + { + lineWidth = (glyphs.getUnchecked (i)->getRight() - lineStartX); - if (lineWidth > widthPerLine) - { - // got to a point where the line's too long, so skip forward to find a - // good place to break it.. - const int searchStartIndex = i; + if (lineWidth > widthPerLine) + { + // got to a point where the line's too long, so skip forward to find a + // good place to break it.. + const int searchStartIndex = i; - while (i < glyphs.size()) - { - if ((glyphs.getUnchecked (i)->getRight() - lineStartX) * minimumHorizontalScale < width) - { - if (glyphs.getUnchecked (i)->isWhitespace() - || glyphs.getUnchecked (i)->getCharacter() == T('-')) - { - ++i; - break; - } - } - else - { - // can't find a suitable break, so try looking backwards.. - i = searchStartIndex; + while (i < glyphs.size()) + { + if ((glyphs.getUnchecked (i)->getRight() - lineStartX) * minimumHorizontalScale < width) + { + if (glyphs.getUnchecked (i)->isWhitespace() + || glyphs.getUnchecked (i)->getCharacter() == T('-')) + { + ++i; + break; + } + } + else + { + // can't find a suitable break, so try looking backwards.. + i = searchStartIndex; - for (int back = 1; back < jmin (5, i - startIndex - 1); ++back) - { - if (glyphs.getUnchecked (i - back)->isWhitespace() - || glyphs.getUnchecked (i - back)->getCharacter() == T('-')) - { - i -= back - 1; - break; - } - } + for (int back = 1; back < jmin (5, i - startIndex - 1); ++back) + { + if (glyphs.getUnchecked (i - back)->isWhitespace() + || glyphs.getUnchecked (i - back)->getCharacter() == T('-')) + { + i -= back - 1; + break; + } + } - break; - } + break; + } - ++i; - } + ++i; + } - break; - } + break; + } - ++i; - } + ++i; + } - int wsStart = i; - while (wsStart > 0 && glyphs.getUnchecked (wsStart - 1)->isWhitespace()) - --wsStart; + int wsStart = i; + while (wsStart > 0 && glyphs.getUnchecked (wsStart - 1)->isWhitespace()) + --wsStart; - int wsEnd = i; + int wsEnd = i; - while (wsEnd < glyphs.size() && glyphs.getUnchecked (wsEnd)->isWhitespace()) - ++wsEnd; + while (wsEnd < glyphs.size() && glyphs.getUnchecked (wsEnd)->isWhitespace()) + ++wsEnd; - removeRangeOfGlyphs (wsStart, wsEnd - wsStart); - i = jmax (wsStart, startIndex + 1); - } + removeRangeOfGlyphs (wsStart, wsEnd - wsStart); + i = jmax (wsStart, startIndex + 1); + } - i -= fitLineIntoSpace (startIndex, i - startIndex, - x, lineY, width, font.getHeight(), font, - layout.getOnlyHorizontalFlags() | Justification::verticallyCentred, - minimumHorizontalScale); + i -= fitLineIntoSpace (startIndex, i - startIndex, + x, lineY, width, font.getHeight(), font, + layout.getOnlyHorizontalFlags() | Justification::verticallyCentred, + minimumHorizontalScale); - startIndex = i; - lineY += font.getHeight(); + startIndex = i; + lineY += font.getHeight(); - if (startIndex >= glyphs.size()) - break; - } + if (startIndex >= glyphs.size()) + break; + } - justifyGlyphs (originalStartIndex, glyphs.size() - originalStartIndex, - x, y, width, height, layout.getFlags() & ~Justification::horizontallyJustified); - } - } + justifyGlyphs (originalStartIndex, glyphs.size() - originalStartIndex, + x, y, width, height, layout.getFlags() & ~Justification::horizontallyJustified); + } + } } void GlyphArrangement::moveRangeOfGlyphs (int startIndex, int num, - const float dx, const float dy) + const float dx, const float dy) { - jassert (startIndex >= 0); + jassert (startIndex >= 0); - if (dx != 0.0f || dy != 0.0f) - { - if (num < 0 || startIndex + num > glyphs.size()) - num = glyphs.size() - startIndex; + if (dx != 0.0f || dy != 0.0f) + { + if (num < 0 || startIndex + num > glyphs.size()) + num = glyphs.size() - startIndex; - while (--num >= 0) - glyphs.getUnchecked (startIndex++)->moveBy (dx, dy); - } + while (--num >= 0) + glyphs.getUnchecked (startIndex++)->moveBy (dx, dy); + } } int GlyphArrangement::fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, - const Justification& justification, float minimumHorizontalScale) + const Justification& justification, float minimumHorizontalScale) { - int numDeleted = 0; - const float lineStartX = glyphs.getUnchecked (start)->getLeft(); - float lineWidth = glyphs.getUnchecked (start + numGlyphs - 1)->getRight() - lineStartX; + int numDeleted = 0; + const float lineStartX = glyphs.getUnchecked (start)->getLeft(); + float lineWidth = glyphs.getUnchecked (start + numGlyphs - 1)->getRight() - lineStartX; - if (lineWidth > w) - { - if (minimumHorizontalScale < 1.0f) - { - stretchRangeOfGlyphs (start, numGlyphs, jmax (minimumHorizontalScale, w / lineWidth)); - lineWidth = glyphs.getUnchecked (start + numGlyphs - 1)->getRight() - lineStartX - 0.5f; - } + if (lineWidth > w) + { + if (minimumHorizontalScale < 1.0f) + { + stretchRangeOfGlyphs (start, numGlyphs, jmax (minimumHorizontalScale, w / lineWidth)); + lineWidth = glyphs.getUnchecked (start + numGlyphs - 1)->getRight() - lineStartX - 0.5f; + } - if (lineWidth > w) - { - numDeleted = insertEllipsis (font, lineStartX + w, start, start + numGlyphs); - numGlyphs -= numDeleted; - } - } + if (lineWidth > w) + { + numDeleted = insertEllipsis (font, lineStartX + w, start, start + numGlyphs); + numGlyphs -= numDeleted; + } + } - justifyGlyphs (start, numGlyphs, x, y, w, h, justification); - return numDeleted; + justifyGlyphs (start, numGlyphs, x, y, w, h, justification); + return numDeleted; } void GlyphArrangement::stretchRangeOfGlyphs (int startIndex, int num, - const float horizontalScaleFactor) + const float horizontalScaleFactor) { - jassert (startIndex >= 0); + jassert (startIndex >= 0); - if (num < 0 || startIndex + num > glyphs.size()) - num = glyphs.size() - startIndex; + if (num < 0 || startIndex + num > glyphs.size()) + num = glyphs.size() - startIndex; - if (num > 0) - { - const float xAnchor = glyphs.getUnchecked (startIndex)->getLeft(); + if (num > 0) + { + const float xAnchor = glyphs.getUnchecked (startIndex)->getLeft(); - while (--num >= 0) - { - PositionedGlyph* const pg = glyphs.getUnchecked (startIndex++); + while (--num >= 0) + { + PositionedGlyph* const pg = glyphs.getUnchecked (startIndex++); - pg->x = xAnchor + (pg->x - xAnchor) * horizontalScaleFactor; - pg->font.setHorizontalScale (pg->font.getHorizontalScale() * horizontalScaleFactor); - pg->w *= horizontalScaleFactor; - } - } + pg->x = xAnchor + (pg->x - xAnchor) * horizontalScaleFactor; + pg->font.setHorizontalScale (pg->font.getHorizontalScale() * horizontalScaleFactor); + pg->w *= horizontalScaleFactor; + } + } } void GlyphArrangement::getBoundingBox (int startIndex, int num, - float& left, - float& top, - float& right, - float& bottom, - const bool includeWhitespace) const + float& left, + float& top, + float& right, + float& bottom, + const bool includeWhitespace) const { - jassert (startIndex >= 0); + jassert (startIndex >= 0); - if (num < 0 || startIndex + num > glyphs.size()) - num = glyphs.size() - startIndex; + if (num < 0 || startIndex + num > glyphs.size()) + num = glyphs.size() - startIndex; - left = 0.0f; - top = 0.0f; - right = 0.0f; - bottom = 0.0f; - bool isFirst = true; + left = 0.0f; + top = 0.0f; + right = 0.0f; + bottom = 0.0f; + bool isFirst = true; - while (--num >= 0) - { - const PositionedGlyph* const pg = glyphs.getUnchecked (startIndex++); + while (--num >= 0) + { + const PositionedGlyph* const pg = glyphs.getUnchecked (startIndex++); - if (includeWhitespace || ! pg->isWhitespace()) - { - if (isFirst) - { - isFirst = false; - left = pg->getLeft(); - top = pg->getTop(); - right = pg->getRight(); - bottom = pg->getBottom(); - } - else - { - left = jmin (left, pg->getLeft()); - top = jmin (top, pg->getTop()); - right = jmax (right, pg->getRight()); - bottom = jmax (bottom, pg->getBottom()); - } - } - } + if (includeWhitespace || ! pg->isWhitespace()) + { + if (isFirst) + { + isFirst = false; + left = pg->getLeft(); + top = pg->getTop(); + right = pg->getRight(); + bottom = pg->getBottom(); + } + else + { + left = jmin (left, pg->getLeft()); + top = jmin (top, pg->getTop()); + right = jmax (right, pg->getRight()); + bottom = jmax (bottom, pg->getBottom()); + } + } + } } void GlyphArrangement::justifyGlyphs (const int startIndex, - const int num, - const float x, const float y, - const float width, const float height, - const Justification& justification) + const int num, + const float x, const float y, + const float width, const float height, + const Justification& justification) { - jassert (num >= 0 && startIndex >= 0); + jassert (num >= 0 && startIndex >= 0); - if (glyphs.size() > 0 && num > 0) - { - float left, top, right, bottom; - getBoundingBox (startIndex, num, left, top, right, bottom, - ! justification.testFlags (Justification::horizontallyJustified - | Justification::horizontallyCentred)); + if (glyphs.size() > 0 && num > 0) + { + float left, top, right, bottom; + getBoundingBox (startIndex, num, left, top, right, bottom, + ! justification.testFlags (Justification::horizontallyJustified + | Justification::horizontallyCentred)); - float deltaX = 0.0f; + float deltaX = 0.0f; - if (justification.testFlags (Justification::horizontallyJustified)) - deltaX = x - left; - else if (justification.testFlags (Justification::horizontallyCentred)) - deltaX = x + (width - (right - left)) * 0.5f - left; - else if (justification.testFlags (Justification::right)) - deltaX = (x + width) - right; - else - deltaX = x - left; + if (justification.testFlags (Justification::horizontallyJustified)) + deltaX = x - left; + else if (justification.testFlags (Justification::horizontallyCentred)) + deltaX = x + (width - (right - left)) * 0.5f - left; + else if (justification.testFlags (Justification::right)) + deltaX = (x + width) - right; + else + deltaX = x - left; - float deltaY = 0.0f; + float deltaY = 0.0f; - if (justification.testFlags (Justification::top)) - deltaY = y - top; - else if (justification.testFlags (Justification::bottom)) - deltaY = (y + height) - bottom; - else - deltaY = y + (height - (bottom - top)) * 0.5f - top; + if (justification.testFlags (Justification::top)) + deltaY = y - top; + else if (justification.testFlags (Justification::bottom)) + deltaY = (y + height) - bottom; + else + deltaY = y + (height - (bottom - top)) * 0.5f - top; - moveRangeOfGlyphs (startIndex, num, deltaX, deltaY); + moveRangeOfGlyphs (startIndex, num, deltaX, deltaY); - if (justification.testFlags (Justification::horizontallyJustified)) - { - int lineStart = 0; - float baseY = glyphs.getUnchecked (startIndex)->getBaselineY(); + if (justification.testFlags (Justification::horizontallyJustified)) + { + int lineStart = 0; + float baseY = glyphs.getUnchecked (startIndex)->getBaselineY(); - int i; - for (i = 0; i < num; ++i) - { - const float glyphY = glyphs.getUnchecked (startIndex + i)->getBaselineY(); + int i; + for (i = 0; i < num; ++i) + { + const float glyphY = glyphs.getUnchecked (startIndex + i)->getBaselineY(); - if (glyphY != baseY) - { - spreadOutLine (startIndex + lineStart, i - lineStart, width); + if (glyphY != baseY) + { + spreadOutLine (startIndex + lineStart, i - lineStart, width); - lineStart = i; - baseY = glyphY; - } - } + lineStart = i; + baseY = glyphY; + } + } - if (i > lineStart) - spreadOutLine (startIndex + lineStart, i - lineStart, width); - } - } + if (i > lineStart) + spreadOutLine (startIndex + lineStart, i - lineStart, width); + } + } } void GlyphArrangement::spreadOutLine (const int start, const int num, const float targetWidth) { - if (start + num < glyphs.size() - && glyphs.getUnchecked (start + num - 1)->getCharacter() != T('\r') - && glyphs.getUnchecked (start + num - 1)->getCharacter() != T('\n')) - { - int numSpaces = 0; - int spacesAtEnd = 0; + if (start + num < glyphs.size() + && glyphs.getUnchecked (start + num - 1)->getCharacter() != T('\r') + && glyphs.getUnchecked (start + num - 1)->getCharacter() != T('\n')) + { + int numSpaces = 0; + int spacesAtEnd = 0; - for (int i = 0; i < num; ++i) - { - if (glyphs.getUnchecked (start + i)->isWhitespace()) - { - ++spacesAtEnd; - ++numSpaces; - } - else - { - spacesAtEnd = 0; - } - } + for (int i = 0; i < num; ++i) + { + if (glyphs.getUnchecked (start + i)->isWhitespace()) + { + ++spacesAtEnd; + ++numSpaces; + } + else + { + spacesAtEnd = 0; + } + } - numSpaces -= spacesAtEnd; + numSpaces -= spacesAtEnd; - if (numSpaces > 0) - { - const float startX = glyphs.getUnchecked (start)->getLeft(); - const float endX = glyphs.getUnchecked (start + num - 1 - spacesAtEnd)->getRight(); + if (numSpaces > 0) + { + const float startX = glyphs.getUnchecked (start)->getLeft(); + const float endX = glyphs.getUnchecked (start + num - 1 - spacesAtEnd)->getRight(); - const float extraPaddingBetweenWords - = (targetWidth - (endX - startX)) / (float) numSpaces; + const float extraPaddingBetweenWords + = (targetWidth - (endX - startX)) / (float) numSpaces; - float deltaX = 0.0f; + float deltaX = 0.0f; - for (int i = 0; i < num; ++i) - { - glyphs.getUnchecked (start + i)->moveBy (deltaX, 0.0f); + for (int i = 0; i < num; ++i) + { + glyphs.getUnchecked (start + i)->moveBy (deltaX, 0.0f); - if (glyphs.getUnchecked (start + i)->isWhitespace()) - deltaX += extraPaddingBetweenWords; - } - } - } + if (glyphs.getUnchecked (start + i)->isWhitespace()) + deltaX += extraPaddingBetweenWords; + } + } + } } void GlyphArrangement::draw (const Graphics& g) const { - for (int i = 0; i < glyphs.size(); ++i) - { - const PositionedGlyph* const pg = glyphs.getUnchecked(i); + for (int i = 0; i < glyphs.size(); ++i) + { + const PositionedGlyph* const pg = glyphs.getUnchecked(i); - if (pg->font.isUnderlined()) - { - const float lineThickness = (pg->font.getDescent()) * 0.3f; + if (pg->font.isUnderlined()) + { + const float lineThickness = (pg->font.getDescent()) * 0.3f; - float nextX = pg->x + pg->w; + float nextX = pg->x + pg->w; - if (i < glyphs.size() - 1 && glyphs.getUnchecked (i + 1)->y == pg->y) - nextX = glyphs.getUnchecked (i + 1)->x; + if (i < glyphs.size() - 1 && glyphs.getUnchecked (i + 1)->y == pg->y) + nextX = glyphs.getUnchecked (i + 1)->x; - g.fillRect (pg->x, pg->y + lineThickness * 2.0f, - nextX - pg->x, lineThickness); - } + g.fillRect (pg->x, pg->y + lineThickness * 2.0f, + nextX - pg->x, lineThickness); + } - pg->draw (g); - } + pg->draw (g); + } } void GlyphArrangement::draw (const Graphics& g, const AffineTransform& transform) const { - for (int i = 0; i < glyphs.size(); ++i) - { - const PositionedGlyph* const pg = glyphs.getUnchecked(i); + for (int i = 0; i < glyphs.size(); ++i) + { + const PositionedGlyph* const pg = glyphs.getUnchecked(i); - if (pg->font.isUnderlined()) - { - const float lineThickness = (pg->font.getDescent()) * 0.3f; + if (pg->font.isUnderlined()) + { + const float lineThickness = (pg->font.getDescent()) * 0.3f; - float nextX = pg->x + pg->w; + float nextX = pg->x + pg->w; - if (i < glyphs.size() - 1 && glyphs.getUnchecked (i + 1)->y == pg->y) - nextX = glyphs.getUnchecked (i + 1)->x; + if (i < glyphs.size() - 1 && glyphs.getUnchecked (i + 1)->y == pg->y) + nextX = glyphs.getUnchecked (i + 1)->x; - Path p; - p.addLineSegment (pg->x, pg->y + lineThickness * 2.0f, - nextX, pg->y + lineThickness * 2.0f, - lineThickness); + Path p; + p.addLineSegment (pg->x, pg->y + lineThickness * 2.0f, + nextX, pg->y + lineThickness * 2.0f, + lineThickness); - g.fillPath (p, transform); - } + g.fillPath (p, transform); + } - pg->draw (g, transform); - } + pg->draw (g, transform); + } } void GlyphArrangement::createPath (Path& path) const { - for (int i = 0; i < glyphs.size(); ++i) - glyphs.getUnchecked (i)->createPath (path); + for (int i = 0; i < glyphs.size(); ++i) + glyphs.getUnchecked (i)->createPath (path); } int GlyphArrangement::findGlyphIndexAt (float x, float y) const { - for (int i = 0; i < glyphs.size(); ++i) - if (glyphs.getUnchecked (i)->hitTest (x, y)) - return i; + for (int i = 0; i < glyphs.size(); ++i) + if (glyphs.getUnchecked (i)->hitTest (x, y)) + return i; - return -1; + return -1; } END_JUCE_NAMESPACE @@ -86898,343 +86688,342 @@ BEGIN_JUCE_NAMESPACE class TextLayout::Token { public: - String text; - Font font; - int x, y, w, h; - int line, lineHeight; - bool isWhitespace, isNewLine; + String text; + Font font; + int x, y, w, h; + int line, lineHeight; + bool isWhitespace, isNewLine; - Token (const String& t, - const Font& f, - const bool isWhitespace_) throw() - : text (t), - font (f), - x(0), - y(0), - isWhitespace (isWhitespace_) - { - w = font.getStringWidth (t); - h = roundFloatToInt (f.getHeight()); - isNewLine = t.containsAnyOf (T("\r\n")); - } + Token (const String& t, + const Font& f, + const bool isWhitespace_) throw() + : text (t), + font (f), + x(0), + y(0), + isWhitespace (isWhitespace_) + { + w = font.getStringWidth (t); + h = roundToInt (f.getHeight()); + isNewLine = t.containsAnyOf (T("\r\n")); + } - Token (const Token& other) throw() - : text (other.text), - font (other.font), - x (other.x), - y (other.y), - w (other.w), - h (other.h), - line (other.line), - lineHeight (other.lineHeight), - isWhitespace (other.isWhitespace), - isNewLine (other.isNewLine) - { - } + Token (const Token& other) throw() + : text (other.text), + font (other.font), + x (other.x), + y (other.y), + w (other.w), + h (other.h), + line (other.line), + lineHeight (other.lineHeight), + isWhitespace (other.isWhitespace), + isNewLine (other.isNewLine) + { + } - ~Token() throw() - { - } + ~Token() throw() + { + } - void draw (Graphics& g, - const int xOffset, - const int yOffset) throw() - { - if (! isWhitespace) - { - g.setFont (font); - g.drawSingleLineText (text.trimEnd(), - xOffset + x, - yOffset + y + (lineHeight - h) - + roundFloatToInt (font.getAscent())); - } - } + void draw (Graphics& g, + const int xOffset, + const int yOffset) throw() + { + if (! isWhitespace) + { + g.setFont (font); + g.drawSingleLineText (text.trimEnd(), + xOffset + x, + yOffset + y + (lineHeight - h) + + roundToInt (font.getAscent())); + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; TextLayout::TextLayout() throw() - : tokens (64), - totalLines (0) + : totalLines (0) { + tokens.ensureStorageAllocated (64); } TextLayout::TextLayout (const String& text, - const Font& font) throw() - : tokens (64), - totalLines (0) + const Font& font) throw() + : totalLines (0) { - appendText (text, font); + tokens.ensureStorageAllocated (64); + appendText (text, font); } TextLayout::TextLayout (const TextLayout& other) throw() - : tokens (64), - totalLines (0) + : totalLines (0) { - *this = other; + *this = other; } const TextLayout& TextLayout::operator= (const TextLayout& other) throw() { - if (this != &other) - { - clear(); + if (this != &other) + { + clear(); - totalLines = other.totalLines; + totalLines = other.totalLines; - for (int i = 0; i < other.tokens.size(); ++i) - tokens.add (new Token (*other.tokens.getUnchecked(i))); - } + for (int i = 0; i < other.tokens.size(); ++i) + tokens.add (new Token (*other.tokens.getUnchecked(i))); + } - return *this; + return *this; } TextLayout::~TextLayout() throw() { - clear(); + clear(); } void TextLayout::clear() throw() { - tokens.clear(); - totalLines = 0; + tokens.clear(); + totalLines = 0; } void TextLayout::appendText (const String& text, - const Font& font) throw() + const Font& font) throw() { - const tchar* t = text; - String currentString; - int lastCharType = 0; + const tchar* t = text; + String currentString; + int lastCharType = 0; - for (;;) - { - const tchar c = *t++; - if (c == 0) - break; + for (;;) + { + const tchar c = *t++; + if (c == 0) + break; - int charType; - if (c == T('\r') || c == T('\n')) - { - charType = 0; - } - else if (CharacterFunctions::isWhitespace (c)) - { - charType = 2; - } - else - { - charType = 1; - } + int charType; + if (c == T('\r') || c == T('\n')) + { + charType = 0; + } + else if (CharacterFunctions::isWhitespace (c)) + { + charType = 2; + } + else + { + charType = 1; + } - if (charType == 0 || charType != lastCharType) - { - if (currentString.isNotEmpty()) - { - tokens.add (new Token (currentString, font, - lastCharType == 2 || lastCharType == 0)); - } + if (charType == 0 || charType != lastCharType) + { + if (currentString.isNotEmpty()) + { + tokens.add (new Token (currentString, font, + lastCharType == 2 || lastCharType == 0)); + } - currentString = String::charToString (c); + currentString = String::charToString (c); - if (c == T('\r') && *t == T('\n')) - currentString += *t++; - } - else - { - currentString += c; - } + if (c == T('\r') && *t == T('\n')) + currentString += *t++; + } + else + { + currentString += c; + } - lastCharType = charType; - } + lastCharType = charType; + } - if (currentString.isNotEmpty()) - tokens.add (new Token (currentString, font, lastCharType == 2)); + if (currentString.isNotEmpty()) + tokens.add (new Token (currentString, font, lastCharType == 2)); } void TextLayout::setText (const String& text, const Font& font) throw() { - clear(); - appendText (text, font); + clear(); + appendText (text, font); } void TextLayout::layout (int maxWidth, - const Justification& justification, - const bool attemptToBalanceLineLengths) throw() + const Justification& justification, + const bool attemptToBalanceLineLengths) throw() { - if (attemptToBalanceLineLengths) - { - const int originalW = maxWidth; - int bestWidth = maxWidth; - float bestLineProportion = 0.0f; + if (attemptToBalanceLineLengths) + { + const int originalW = maxWidth; + int bestWidth = maxWidth; + float bestLineProportion = 0.0f; - while (maxWidth > originalW / 2) - { - layout (maxWidth, justification, false); + while (maxWidth > originalW / 2) + { + layout (maxWidth, justification, false); - if (getNumLines() <= 1) - return; + if (getNumLines() <= 1) + return; - const int lastLineW = getLineWidth (getNumLines() - 1); - const int lastButOneLineW = getLineWidth (getNumLines() - 2); + const int lastLineW = getLineWidth (getNumLines() - 1); + const int lastButOneLineW = getLineWidth (getNumLines() - 2); - const float prop = lastLineW / (float) lastButOneLineW; + const float prop = lastLineW / (float) lastButOneLineW; - if (prop > 0.9f) - return; + if (prop > 0.9f) + return; - if (prop > bestLineProportion) - { - bestLineProportion = prop; - bestWidth = maxWidth; - } + if (prop > bestLineProportion) + { + bestLineProportion = prop; + bestWidth = maxWidth; + } - maxWidth -= 10; - } + maxWidth -= 10; + } - layout (bestWidth, justification, false); - } - else - { - int x = 0; - int y = 0; - int h = 0; - totalLines = 0; - int i; + layout (bestWidth, justification, false); + } + else + { + int x = 0; + int y = 0; + int h = 0; + totalLines = 0; + int i; - for (i = 0; i < tokens.size(); ++i) - { - Token* const t = tokens.getUnchecked(i); - t->x = x; - t->y = y; - t->line = totalLines; - x += t->w; - h = jmax (h, t->h); + for (i = 0; i < tokens.size(); ++i) + { + Token* const t = tokens.getUnchecked(i); + t->x = x; + t->y = y; + t->line = totalLines; + x += t->w; + h = jmax (h, t->h); - const Token* nextTok = tokens [i + 1]; + const Token* nextTok = tokens [i + 1]; - if (nextTok == 0) - break; + if (nextTok == 0) + break; - if (t->isNewLine || ((! nextTok->isWhitespace) && x + nextTok->w > maxWidth)) - { - // finished a line, so go back and update the heights of the things on it - for (int j = i; j >= 0; --j) - { - Token* const tok = tokens.getUnchecked(j); + if (t->isNewLine || ((! nextTok->isWhitespace) && x + nextTok->w > maxWidth)) + { + // finished a line, so go back and update the heights of the things on it + for (int j = i; j >= 0; --j) + { + Token* const tok = tokens.getUnchecked(j); - if (tok->line == totalLines) - tok->lineHeight = h; - else - break; - } + if (tok->line == totalLines) + tok->lineHeight = h; + else + break; + } - x = 0; - y += h; - h = 0; - ++totalLines; - } - } + x = 0; + y += h; + h = 0; + ++totalLines; + } + } - // finished a line, so go back and update the heights of the things on it - for (int j = jmin (i, tokens.size() - 1); j >= 0; --j) - { - Token* const t = tokens.getUnchecked(j); + // finished a line, so go back and update the heights of the things on it + for (int j = jmin (i, tokens.size() - 1); j >= 0; --j) + { + Token* const t = tokens.getUnchecked(j); - if (t->line == totalLines) - t->lineHeight = h; - else - break; - } + if (t->line == totalLines) + t->lineHeight = h; + else + break; + } - ++totalLines; + ++totalLines; - if (! justification.testFlags (Justification::left)) - { - int totalW = getWidth(); + if (! justification.testFlags (Justification::left)) + { + int totalW = getWidth(); - for (i = totalLines; --i >= 0;) - { - const int lineW = getLineWidth (i); + for (i = totalLines; --i >= 0;) + { + const int lineW = getLineWidth (i); - int dx = 0; - if (justification.testFlags (Justification::horizontallyCentred)) - dx = (totalW - lineW) / 2; - else if (justification.testFlags (Justification::right)) - dx = totalW - lineW; + int dx = 0; + if (justification.testFlags (Justification::horizontallyCentred)) + dx = (totalW - lineW) / 2; + else if (justification.testFlags (Justification::right)) + dx = totalW - lineW; - for (int j = tokens.size(); --j >= 0;) - { - Token* const t = tokens.getUnchecked(j); + for (int j = tokens.size(); --j >= 0;) + { + Token* const t = tokens.getUnchecked(j); - if (t->line == i) - t->x += dx; - } - } - } - } + if (t->line == i) + t->x += dx; + } + } + } + } } int TextLayout::getLineWidth (const int lineNumber) const throw() { - int maxW = 0; + int maxW = 0; - for (int i = tokens.size(); --i >= 0;) - { - const Token* const t = tokens.getUnchecked(i); + for (int i = tokens.size(); --i >= 0;) + { + const Token* const t = tokens.getUnchecked(i); - if (t->line == lineNumber && ! t->isWhitespace) - maxW = jmax (maxW, t->x + t->w); - } + if (t->line == lineNumber && ! t->isWhitespace) + maxW = jmax (maxW, t->x + t->w); + } - return maxW; + return maxW; } int TextLayout::getWidth() const throw() { - int maxW = 0; + int maxW = 0; - for (int i = tokens.size(); --i >= 0;) - { - const Token* const t = tokens.getUnchecked(i); - if (! t->isWhitespace) - maxW = jmax (maxW, t->x + t->w); - } + for (int i = tokens.size(); --i >= 0;) + { + const Token* const t = tokens.getUnchecked(i); + if (! t->isWhitespace) + maxW = jmax (maxW, t->x + t->w); + } - return maxW; + return maxW; } int TextLayout::getHeight() const throw() { - int maxH = 0; + int maxH = 0; - for (int i = tokens.size(); --i >= 0;) - { - const Token* const t = tokens.getUnchecked(i); + for (int i = tokens.size(); --i >= 0;) + { + const Token* const t = tokens.getUnchecked(i); - if (! t->isWhitespace) - maxH = jmax (maxH, t->y + t->h); - } + if (! t->isWhitespace) + maxH = jmax (maxH, t->y + t->h); + } - return maxH; + return maxH; } void TextLayout::draw (Graphics& g, - const int xOffset, - const int yOffset) const throw() + const int xOffset, + const int yOffset) const throw() { - for (int i = tokens.size(); --i >= 0;) - tokens.getUnchecked(i)->draw (g, xOffset, yOffset); + for (int i = tokens.size(); --i >= 0;) + tokens.getUnchecked(i)->draw (g, xOffset, yOffset); } void TextLayout::drawWithin (Graphics& g, - int x, int y, int w, int h, - const Justification& justification) const throw() + int x, int y, int w, int h, + const Justification& justification) const throw() { - justification.applyToRectangle (x, y, getWidth(), getHeight(), - x, y, w, h); + justification.applyToRectangle (x, y, getWidth(), getHeight(), + x, y, w, h); - draw (g, x, y); + draw (g, x, y); } END_JUCE_NAMESPACE @@ -87245,7 +87034,7 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE Typeface::Typeface (const String& name_) throw() - : name (name_) + : name (name_) { } @@ -87256,95 +87045,95 @@ Typeface::~Typeface() class CustomTypefaceGlyphInfo { public: - CustomTypefaceGlyphInfo (const juce_wchar character_, const Path& path_, const float width_) throw() - : character (character_), path (path_), width (width_) - { - } + CustomTypefaceGlyphInfo (const juce_wchar character_, const Path& path_, const float width_) throw() + : character (character_), path (path_), width (width_) + { + } - ~CustomTypefaceGlyphInfo() throw() - { - } + ~CustomTypefaceGlyphInfo() throw() + { + } - struct KerningPair - { - juce_wchar character2; - float kerningAmount; - }; + struct KerningPair + { + juce_wchar character2; + float kerningAmount; + }; - void addKerningPair (const juce_wchar subsequentCharacter, - const float extraKerningAmount) throw() - { - KerningPair kp; - kp.character2 = subsequentCharacter; - kp.kerningAmount = extraKerningAmount; - kerningPairs.add (kp); - } + void addKerningPair (const juce_wchar subsequentCharacter, + const float extraKerningAmount) throw() + { + KerningPair kp; + kp.character2 = subsequentCharacter; + kp.kerningAmount = extraKerningAmount; + kerningPairs.add (kp); + } - float getHorizontalSpacing (const juce_wchar subsequentCharacter) const throw() - { - if (subsequentCharacter != 0) - { - for (int i = kerningPairs.size(); --i >= 0;) - if (kerningPairs.getReference(i).character2 == subsequentCharacter) - return width + kerningPairs.getReference(i).kerningAmount; - } + float getHorizontalSpacing (const juce_wchar subsequentCharacter) const throw() + { + if (subsequentCharacter != 0) + { + for (int i = kerningPairs.size(); --i >= 0;) + if (kerningPairs.getReference(i).character2 == subsequentCharacter) + return width + kerningPairs.getReference(i).kerningAmount; + } - return width; - } + return width; + } - const juce_wchar character; - const Path path; - float width; - Array kerningPairs; + const juce_wchar character; + const Path path; + float width; + Array kerningPairs; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - CustomTypefaceGlyphInfo (const CustomTypefaceGlyphInfo&); - const CustomTypefaceGlyphInfo& operator= (const CustomTypefaceGlyphInfo&); + CustomTypefaceGlyphInfo (const CustomTypefaceGlyphInfo&); + const CustomTypefaceGlyphInfo& operator= (const CustomTypefaceGlyphInfo&); }; CustomTypeface::CustomTypeface() - : Typeface (String::empty) + : Typeface (String::empty) { - clear(); + clear(); } CustomTypeface::CustomTypeface (InputStream& serialisedTypefaceStream) - : Typeface (String::empty) + : Typeface (String::empty) { - clear(); + clear(); - GZIPDecompressorInputStream gzin (&serialisedTypefaceStream, false); - BufferedInputStream in (&gzin, 32768, false); + GZIPDecompressorInputStream gzin (&serialisedTypefaceStream, false); + BufferedInputStream in (&gzin, 32768, false); - name = in.readString(); - isBold = in.readBool(); - isItalic = in.readBool(); - ascent = in.readFloat(); - defaultCharacter = (juce_wchar) in.readShort(); + name = in.readString(); + isBold = in.readBool(); + isItalic = in.readBool(); + ascent = in.readFloat(); + defaultCharacter = (juce_wchar) in.readShort(); - int i, numChars = in.readInt(); + int i, numChars = in.readInt(); - for (i = 0; i < numChars; ++i) - { - const juce_wchar c = (juce_wchar) in.readShort(); - const float width = in.readFloat(); + for (i = 0; i < numChars; ++i) + { + const juce_wchar c = (juce_wchar) in.readShort(); + const float width = in.readFloat(); - Path p; - p.loadPathFromStream (in); - addGlyph (c, p, width); - } + Path p; + p.loadPathFromStream (in); + addGlyph (c, p, width); + } - const int numKerningPairs = in.readInt(); + const int numKerningPairs = in.readInt(); - for (i = 0; i < numKerningPairs; ++i) - { - const juce_wchar char1 = (juce_wchar) in.readShort(); - const juce_wchar char2 = (juce_wchar) in.readShort(); + for (i = 0; i < numKerningPairs; ++i) + { + const juce_wchar char1 = (juce_wchar) in.readShort(); + const juce_wchar char2 = (juce_wchar) in.readShort(); - addKerningPair (char1, char2, in.readFloat()); - } + addKerningPair (char1, char2, in.readFloat()); + } } CustomTypeface::~CustomTypeface() @@ -87353,227 +87142,227 @@ CustomTypeface::~CustomTypeface() void CustomTypeface::clear() { - defaultCharacter = 0; - ascent = 1.0f; - isBold = isItalic = false; - zeromem (lookupTable, sizeof (lookupTable)); - glyphs.clear(); + defaultCharacter = 0; + ascent = 1.0f; + isBold = isItalic = false; + zeromem (lookupTable, sizeof (lookupTable)); + glyphs.clear(); } void CustomTypeface::setCharacteristics (const String& name_, const float ascent_, const bool isBold_, - const bool isItalic_, const juce_wchar defaultCharacter_) throw() + const bool isItalic_, const juce_wchar defaultCharacter_) throw() { - name = name_; - defaultCharacter = defaultCharacter_; - ascent = ascent_; - isBold = isBold_; - isItalic = isItalic_; + name = name_; + defaultCharacter = defaultCharacter_; + ascent = ascent_; + isBold = isBold_; + isItalic = isItalic_; } void CustomTypeface::addGlyph (const juce_wchar character, const Path& path, const float width) throw() { - // Check that you're not trying to add the same character twice.. - jassert (findGlyph (character, false) == 0); + // Check that you're not trying to add the same character twice.. + jassert (findGlyph (character, false) == 0); - if (((unsigned int) character) < (unsigned int) numElementsInArray (lookupTable)) - lookupTable [character] = (short) glyphs.size(); + if (((unsigned int) character) < (unsigned int) numElementsInArray (lookupTable)) + lookupTable [character] = (short) glyphs.size(); - glyphs.add (new CustomTypefaceGlyphInfo (character, path, width)); + glyphs.add (new CustomTypefaceGlyphInfo (character, path, width)); } void CustomTypeface::addKerningPair (const juce_wchar char1, const juce_wchar char2, const float extraAmount) throw() { - if (extraAmount != 0) - { - CustomTypefaceGlyphInfo* const g = findGlyph (char1, true); - jassert (g != 0); // can only add kerning pairs for characters that exist! + if (extraAmount != 0) + { + CustomTypefaceGlyphInfo* const g = findGlyph (char1, true); + jassert (g != 0); // can only add kerning pairs for characters that exist! - if (g != 0) - g->addKerningPair (char2, extraAmount); - } + if (g != 0) + g->addKerningPair (char2, extraAmount); + } } CustomTypefaceGlyphInfo* CustomTypeface::findGlyph (const juce_wchar character, const bool loadIfNeeded) throw() { - if (((unsigned int) character) < (unsigned int) numElementsInArray (lookupTable) && lookupTable [character] > 0) - return glyphs [(int) lookupTable [(int) character]]; + if (((unsigned int) character) < (unsigned int) numElementsInArray (lookupTable) && lookupTable [character] > 0) + return glyphs [(int) lookupTable [(int) character]]; - for (int i = 0; i < glyphs.size(); ++i) - { - CustomTypefaceGlyphInfo* const g = glyphs.getUnchecked(i); - if (g->character == character) - return g; - } + for (int i = 0; i < glyphs.size(); ++i) + { + CustomTypefaceGlyphInfo* const g = glyphs.getUnchecked(i); + if (g->character == character) + return g; + } - if (loadIfNeeded && loadGlyphIfPossible (character)) - return findGlyph (character, false); + if (loadIfNeeded && loadGlyphIfPossible (character)) + return findGlyph (character, false); - return 0; + return 0; } CustomTypefaceGlyphInfo* CustomTypeface::findGlyphSubstituting (const juce_wchar character) throw() { - CustomTypefaceGlyphInfo* glyph = findGlyph (character, true); + CustomTypefaceGlyphInfo* glyph = findGlyph (character, true); - if (glyph == 0) - { - if (CharacterFunctions::isWhitespace (character) && character != L' ') - glyph = findGlyph (L' ', true); + if (glyph == 0) + { + if (CharacterFunctions::isWhitespace (character) && character != L' ') + glyph = findGlyph (L' ', true); - if (glyph == 0) - { - const Font fallbackFont (Font::getFallbackFontName(), 10, 0); - Typeface* const fallbackTypeface = fallbackFont.getTypeface(); - if (fallbackTypeface != 0 && fallbackTypeface != this) - { - //xxx - } + if (glyph == 0) + { + const Font fallbackFont (Font::getFallbackFontName(), 10, 0); + Typeface* const fallbackTypeface = fallbackFont.getTypeface(); + if (fallbackTypeface != 0 && fallbackTypeface != this) + { + //xxx + } - if (glyph == 0) - glyph = findGlyph (defaultCharacter, true); - } - } + if (glyph == 0) + glyph = findGlyph (defaultCharacter, true); + } + } - return glyph; + return glyph; } bool CustomTypeface::loadGlyphIfPossible (const juce_wchar characterNeeded) { - return false; + return false; } void CustomTypeface::addGlyphsFromOtherTypeface (Typeface& typefaceToCopy, juce_wchar characterStartIndex, int numCharacters) throw() { - for (int i = 0; i < numCharacters; ++i) - { - const juce_wchar c = (juce_wchar) (characterStartIndex + i); + for (int i = 0; i < numCharacters; ++i) + { + const juce_wchar c = (juce_wchar) (characterStartIndex + i); - Array glyphIndexes; - Array offsets; - typefaceToCopy.getGlyphPositions (String::charToString (c), glyphIndexes, offsets); + Array glyphIndexes; + Array offsets; + typefaceToCopy.getGlyphPositions (String::charToString (c), glyphIndexes, offsets); - const int glyphIndex = glyphIndexes.getFirst(); + const int glyphIndex = glyphIndexes.getFirst(); - if (glyphIndex >= 0 && glyphIndexes.size() > 0) - { - const float glyphWidth = offsets[1]; + if (glyphIndex >= 0 && glyphIndexes.size() > 0) + { + const float glyphWidth = offsets[1]; - Path p; - typefaceToCopy.getOutlineForGlyph (glyphIndex, p); + Path p; + typefaceToCopy.getOutlineForGlyph (glyphIndex, p); - addGlyph (c, p, glyphWidth); + addGlyph (c, p, glyphWidth); - for (int j = glyphs.size() - 1; --j >= 0;) - { - const juce_wchar char2 = glyphs.getUnchecked (j)->character; - glyphIndexes.clearQuick(); - offsets.clearQuick(); - typefaceToCopy.getGlyphPositions (String::charToString (c) + String::charToString (char2), glyphIndexes, offsets); + for (int j = glyphs.size() - 1; --j >= 0;) + { + const juce_wchar char2 = glyphs.getUnchecked (j)->character; + glyphIndexes.clearQuick(); + offsets.clearQuick(); + typefaceToCopy.getGlyphPositions (String::charToString (c) + String::charToString (char2), glyphIndexes, offsets); - if (offsets.size() > 1) - addKerningPair (c, char2, offsets[1] - glyphWidth); - } - } - } + if (offsets.size() > 1) + addKerningPair (c, char2, offsets[1] - glyphWidth); + } + } + } } bool CustomTypeface::writeToStream (OutputStream& outputStream) { - GZIPCompressorOutputStream out (&outputStream); + GZIPCompressorOutputStream out (&outputStream); - out.writeString (name); - out.writeBool (isBold); - out.writeBool (isItalic); - out.writeFloat (ascent); - out.writeShort ((short) (unsigned short) defaultCharacter); - out.writeInt (glyphs.size()); + out.writeString (name); + out.writeBool (isBold); + out.writeBool (isItalic); + out.writeFloat (ascent); + out.writeShort ((short) (unsigned short) defaultCharacter); + out.writeInt (glyphs.size()); - int i, numKerningPairs = 0; + int i, numKerningPairs = 0; - for (i = 0; i < glyphs.size(); ++i) - { - const CustomTypefaceGlyphInfo* const g = glyphs.getUnchecked (i); - out.writeShort ((short) (unsigned short) g->character); - out.writeFloat (g->width); - g->path.writePathToStream (out); + for (i = 0; i < glyphs.size(); ++i) + { + const CustomTypefaceGlyphInfo* const g = glyphs.getUnchecked (i); + out.writeShort ((short) (unsigned short) g->character); + out.writeFloat (g->width); + g->path.writePathToStream (out); - numKerningPairs += g->kerningPairs.size(); - } + numKerningPairs += g->kerningPairs.size(); + } - out.writeInt (numKerningPairs); + out.writeInt (numKerningPairs); - for (i = 0; i < glyphs.size(); ++i) - { - const CustomTypefaceGlyphInfo* const g = glyphs.getUnchecked (i); + for (i = 0; i < glyphs.size(); ++i) + { + const CustomTypefaceGlyphInfo* const g = glyphs.getUnchecked (i); - for (int j = 0; j < g->kerningPairs.size(); ++j) - { - const CustomTypefaceGlyphInfo::KerningPair& p = g->kerningPairs.getReference (j); - out.writeShort ((short) (unsigned short) g->character); - out.writeShort ((short) (unsigned short) p.character2); - out.writeFloat (p.kerningAmount); - } - } + for (int j = 0; j < g->kerningPairs.size(); ++j) + { + const CustomTypefaceGlyphInfo::KerningPair& p = g->kerningPairs.getReference (j); + out.writeShort ((short) (unsigned short) g->character); + out.writeShort ((short) (unsigned short) p.character2); + out.writeFloat (p.kerningAmount); + } + } - return true; + return true; } float CustomTypeface::getAscent() const { - return ascent; + return ascent; } float CustomTypeface::getDescent() const { - return 1.0f - ascent; + return 1.0f - ascent; } float CustomTypeface::getStringWidth (const String& text) { - float x = 0; - const juce_wchar* t = (const juce_wchar*) text; + float x = 0; + const juce_wchar* t = (const juce_wchar*) text; - while (*t != 0) - { - const CustomTypefaceGlyphInfo* const glyph = findGlyphSubstituting (*t++); + while (*t != 0) + { + const CustomTypefaceGlyphInfo* const glyph = findGlyphSubstituting (*t++); - if (glyph != 0) - x += glyph->getHorizontalSpacing (*t); - } + if (glyph != 0) + x += glyph->getHorizontalSpacing (*t); + } - return x; + return x; } void CustomTypeface::getGlyphPositions (const String& text, Array & resultGlyphs, Array& xOffsets) { - xOffsets.add (0); - float x = 0; - const juce_wchar* t = (const juce_wchar*) text; + xOffsets.add (0); + float x = 0; + const juce_wchar* t = (const juce_wchar*) text; - while (*t != 0) - { - const juce_wchar c = *t++; - const CustomTypefaceGlyphInfo* const glyph = findGlyphSubstituting (c); + while (*t != 0) + { + const juce_wchar c = *t++; + const CustomTypefaceGlyphInfo* const glyph = findGlyphSubstituting (c); - if (glyph != 0) - { - x += glyph->getHorizontalSpacing (*t); - resultGlyphs.add ((int) glyph->character); - xOffsets.add (x); - } - } + if (glyph != 0) + { + x += glyph->getHorizontalSpacing (*t); + resultGlyphs.add ((int) glyph->character); + xOffsets.add (x); + } + } } bool CustomTypeface::getOutlineForGlyph (int glyphNumber, Path& path) { - const CustomTypefaceGlyphInfo* const glyph = findGlyphSubstituting ((juce_wchar) glyphNumber); - if (glyph != 0) - { - path = glyph->path; - return true; - } + const CustomTypefaceGlyphInfo* const glyph = findGlyphSubstituting ((juce_wchar) glyphNumber); + if (glyph != 0) + { + path = glyph->path; + return true; + } - return false; + return false; } END_JUCE_NAMESPACE @@ -87584,225 +87373,225 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AffineTransform::AffineTransform() throw() - : mat00 (1.0f), - mat01 (0), - mat02 (0), - mat10 (0), - mat11 (1.0f), - mat12 (0) + : mat00 (1.0f), + mat01 (0), + mat02 (0), + mat10 (0), + mat11 (1.0f), + mat12 (0) { } AffineTransform::AffineTransform (const AffineTransform& other) throw() : mat00 (other.mat00), - mat01 (other.mat01), - mat02 (other.mat02), - mat10 (other.mat10), - mat11 (other.mat11), - mat12 (other.mat12) + mat01 (other.mat01), + mat02 (other.mat02), + mat10 (other.mat10), + mat11 (other.mat11), + mat12 (other.mat12) { } AffineTransform::AffineTransform (const float mat00_, - const float mat01_, - const float mat02_, - const float mat10_, - const float mat11_, - const float mat12_) throw() + const float mat01_, + const float mat02_, + const float mat10_, + const float mat11_, + const float mat12_) throw() : mat00 (mat00_), - mat01 (mat01_), - mat02 (mat02_), - mat10 (mat10_), - mat11 (mat11_), - mat12 (mat12_) + mat01 (mat01_), + mat02 (mat02_), + mat10 (mat10_), + mat11 (mat11_), + mat12 (mat12_) { } const AffineTransform& AffineTransform::operator= (const AffineTransform& other) throw() { - mat00 = other.mat00; - mat01 = other.mat01; - mat02 = other.mat02; - mat10 = other.mat10; - mat11 = other.mat11; - mat12 = other.mat12; + mat00 = other.mat00; + mat01 = other.mat01; + mat02 = other.mat02; + mat10 = other.mat10; + mat11 = other.mat11; + mat12 = other.mat12; - return *this; + return *this; } bool AffineTransform::operator== (const AffineTransform& other) const throw() { - return mat00 == other.mat00 - && mat01 == other.mat01 - && mat02 == other.mat02 - && mat10 == other.mat10 - && mat11 == other.mat11 - && mat12 == other.mat12; + return mat00 == other.mat00 + && mat01 == other.mat01 + && mat02 == other.mat02 + && mat10 == other.mat10 + && mat11 == other.mat11 + && mat12 == other.mat12; } bool AffineTransform::operator!= (const AffineTransform& other) const throw() { - return ! operator== (other); + return ! operator== (other); } bool AffineTransform::isIdentity() const throw() { - return (mat01 == 0) - && (mat02 == 0) - && (mat10 == 0) - && (mat12 == 0) - && (mat00 == 1.0f) - && (mat11 == 1.0f); + return (mat01 == 0) + && (mat02 == 0) + && (mat10 == 0) + && (mat12 == 0) + && (mat00 == 1.0f) + && (mat11 == 1.0f); } const AffineTransform AffineTransform::identity; const AffineTransform AffineTransform::followedBy (const AffineTransform& other) const throw() { - return AffineTransform (other.mat00 * mat00 + other.mat01 * mat10, - other.mat00 * mat01 + other.mat01 * mat11, - other.mat00 * mat02 + other.mat01 * mat12 + other.mat02, - other.mat10 * mat00 + other.mat11 * mat10, - other.mat10 * mat01 + other.mat11 * mat11, - other.mat10 * mat02 + other.mat11 * mat12 + other.mat12); + return AffineTransform (other.mat00 * mat00 + other.mat01 * mat10, + other.mat00 * mat01 + other.mat01 * mat11, + other.mat00 * mat02 + other.mat01 * mat12 + other.mat02, + other.mat10 * mat00 + other.mat11 * mat10, + other.mat10 * mat01 + other.mat11 * mat11, + other.mat10 * mat02 + other.mat11 * mat12 + other.mat12); } const AffineTransform AffineTransform::followedBy (const float omat00, - const float omat01, - const float omat02, - const float omat10, - const float omat11, - const float omat12) const throw() + const float omat01, + const float omat02, + const float omat10, + const float omat11, + const float omat12) const throw() { - return AffineTransform (omat00 * mat00 + omat01 * mat10, - omat00 * mat01 + omat01 * mat11, - omat00 * mat02 + omat01 * mat12 + omat02, - omat10 * mat00 + omat11 * mat10, - omat10 * mat01 + omat11 * mat11, - omat10 * mat02 + omat11 * mat12 + omat12); + return AffineTransform (omat00 * mat00 + omat01 * mat10, + omat00 * mat01 + omat01 * mat11, + omat00 * mat02 + omat01 * mat12 + omat02, + omat10 * mat00 + omat11 * mat10, + omat10 * mat01 + omat11 * mat11, + omat10 * mat02 + omat11 * mat12 + omat12); } const AffineTransform AffineTransform::translated (const float dx, - const float dy) const throw() + const float dy) const throw() { - return AffineTransform (mat00, mat01, mat02 + dx, - mat10, mat11, mat12 + dy); + return AffineTransform (mat00, mat01, mat02 + dx, + mat10, mat11, mat12 + dy); } const AffineTransform AffineTransform::translation (const float dx, - const float dy) throw() + const float dy) throw() { - return AffineTransform (1.0f, 0, dx, - 0, 1.0f, dy); + return AffineTransform (1.0f, 0, dx, + 0, 1.0f, dy); } const AffineTransform AffineTransform::rotated (const float rad) const throw() { - const float cosRad = cosf (rad); - const float sinRad = sinf (rad); + const float cosRad = cosf (rad); + const float sinRad = sinf (rad); - return followedBy (cosRad, -sinRad, 0, - sinRad, cosRad, 0); + return followedBy (cosRad, -sinRad, 0, + sinRad, cosRad, 0); } const AffineTransform AffineTransform::rotation (const float rad) throw() { - const float cosRad = cosf (rad); - const float sinRad = sinf (rad); + const float cosRad = cosf (rad); + const float sinRad = sinf (rad); - return AffineTransform (cosRad, -sinRad, 0, - sinRad, cosRad, 0); + return AffineTransform (cosRad, -sinRad, 0, + sinRad, cosRad, 0); } const AffineTransform AffineTransform::rotated (const float angle, - const float pivotX, - const float pivotY) const throw() + const float pivotX, + const float pivotY) const throw() { - return translated (-pivotX, -pivotY) - .rotated (angle) - .translated (pivotX, pivotY); + return translated (-pivotX, -pivotY) + .rotated (angle) + .translated (pivotX, pivotY); } const AffineTransform AffineTransform::rotation (const float angle, - const float pivotX, - const float pivotY) throw() + const float pivotX, + const float pivotY) throw() { - return translation (-pivotX, -pivotY) - .rotated (angle) - .translated (pivotX, pivotY); + return translation (-pivotX, -pivotY) + .rotated (angle) + .translated (pivotX, pivotY); } const AffineTransform AffineTransform::scaled (const float factorX, - const float factorY) const throw() + const float factorY) const throw() { - return AffineTransform (factorX * mat00, factorX * mat01, factorX * mat02, - factorY * mat10, factorY * mat11, factorY * mat12); + return AffineTransform (factorX * mat00, factorX * mat01, factorX * mat02, + factorY * mat10, factorY * mat11, factorY * mat12); } const AffineTransform AffineTransform::scale (const float factorX, - const float factorY) throw() + const float factorY) throw() { - return AffineTransform (factorX, 0, 0, - 0, factorY, 0); + return AffineTransform (factorX, 0, 0, + 0, factorY, 0); } const AffineTransform AffineTransform::sheared (const float shearX, - const float shearY) const throw() + const float shearY) const throw() { - return followedBy (1.0f, shearX, 0, - shearY, 1.0f, 0); + return followedBy (1.0f, shearX, 0, + shearY, 1.0f, 0); } const AffineTransform AffineTransform::inverted() const throw() { - double determinant = (mat00 * mat11 - mat10 * mat01); + double determinant = (mat00 * mat11 - mat10 * mat01); - if (determinant != 0.0) - { - determinant = 1.0 / determinant; + if (determinant != 0.0) + { + determinant = 1.0 / determinant; - const float dst00 = (float) (mat11 * determinant); - const float dst10 = (float) (-mat10 * determinant); - const float dst01 = (float) (-mat01 * determinant); - const float dst11 = (float) (mat00 * determinant); + const float dst00 = (float) (mat11 * determinant); + const float dst10 = (float) (-mat10 * determinant); + const float dst01 = (float) (-mat01 * determinant); + const float dst11 = (float) (mat00 * determinant); - return AffineTransform (dst00, dst01, -mat02 * dst00 - mat12 * dst01, - dst10, dst11, -mat02 * dst10 - mat12 * dst11); - } - else - { - // singularity.. - return *this; - } + return AffineTransform (dst00, dst01, -mat02 * dst00 - mat12 * dst01, + dst10, dst11, -mat02 * dst10 - mat12 * dst11); + } + else + { + // singularity.. + return *this; + } } bool AffineTransform::isSingularity() const throw() { - return (mat00 * mat11 - mat10 * mat01) == 0.0; + return (mat00 * mat11 - mat10 * mat01) == 0.0; } bool AffineTransform::isOnlyTranslation() const throw() { - return (mat01 == 0) - && (mat10 == 0) - && (mat00 == 1.0f) - && (mat11 == 1.0f); + return (mat01 == 0) + && (mat10 == 0) + && (mat00 == 1.0f) + && (mat11 == 1.0f); } void AffineTransform::transformPoint (float& x, - float& y) const throw() + float& y) const throw() { - const float oldX = x; - x = mat00 * oldX + mat01 * y + mat02; - y = mat10 * oldX + mat11 * y + mat12; + const float oldX = x; + x = mat00 * oldX + mat01 * y + mat02; + y = mat10 * oldX + mat11 * y + mat12; } void AffineTransform::transformPoint (double& x, - double& y) const throw() + double& y) const throw() { - const double oldX = x; - x = mat00 * oldX + mat01 * y + mat02; - y = mat10 * oldX + mat11 * y + mat12; + const double oldX = x; + x = mat00 * oldX + mat01 * y + mat02; + y = mat10 * oldX + mat11 * y + mat12; } END_JUCE_NAMESPACE @@ -87813,37 +87602,37 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE BorderSize::BorderSize() throw() - : top (0), - left (0), - bottom (0), - right (0) + : top (0), + left (0), + bottom (0), + right (0) { } BorderSize::BorderSize (const BorderSize& other) throw() - : top (other.top), - left (other.left), - bottom (other.bottom), - right (other.right) + : top (other.top), + left (other.left), + bottom (other.bottom), + right (other.right) { } BorderSize::BorderSize (const int topGap, - const int leftGap, - const int bottomGap, - const int rightGap) throw() - : top (topGap), - left (leftGap), - bottom (bottomGap), - right (rightGap) + const int leftGap, + const int bottomGap, + const int rightGap) throw() + : top (topGap), + left (leftGap), + bottom (bottomGap), + right (rightGap) { } BorderSize::BorderSize (const int allGaps) throw() - : top (allGaps), - left (allGaps), - bottom (allGaps), - right (allGaps) + : top (allGaps), + left (allGaps), + bottom (allGaps), + right (allGaps) { } @@ -87853,67 +87642,67 @@ BorderSize::~BorderSize() throw() void BorderSize::setTop (const int newTopGap) throw() { - top = newTopGap; + top = newTopGap; } void BorderSize::setLeft (const int newLeftGap) throw() { - left = newLeftGap; + left = newLeftGap; } void BorderSize::setBottom (const int newBottomGap) throw() { - bottom = newBottomGap; + bottom = newBottomGap; } void BorderSize::setRight (const int newRightGap) throw() { - right = newRightGap; + right = newRightGap; } const Rectangle BorderSize::subtractedFrom (const Rectangle& r) const throw() { - return Rectangle (r.getX() + left, - r.getY() + top, - r.getWidth() - (left + right), - r.getHeight() - (top + bottom)); + return Rectangle (r.getX() + left, + r.getY() + top, + r.getWidth() - (left + right), + r.getHeight() - (top + bottom)); } void BorderSize::subtractFrom (Rectangle& r) const throw() { - r.setBounds (r.getX() + left, - r.getY() + top, - r.getWidth() - (left + right), - r.getHeight() - (top + bottom)); + r.setBounds (r.getX() + left, + r.getY() + top, + r.getWidth() - (left + right), + r.getHeight() - (top + bottom)); } const Rectangle BorderSize::addedTo (const Rectangle& r) const throw() { - return Rectangle (r.getX() - left, - r.getY() - top, - r.getWidth() + (left + right), - r.getHeight() + (top + bottom)); + return Rectangle (r.getX() - left, + r.getY() - top, + r.getWidth() + (left + right), + r.getHeight() + (top + bottom)); } void BorderSize::addTo (Rectangle& r) const throw() { - r.setBounds (r.getX() - left, - r.getY() - top, - r.getWidth() + (left + right), - r.getHeight() + (top + bottom)); + r.setBounds (r.getX() - left, + r.getY() - top, + r.getWidth() + (left + right), + r.getHeight() + (top + bottom)); } bool BorderSize::operator== (const BorderSize& other) const throw() { - return top == other.top - && left == other.left - && bottom == other.bottom - && right == other.right; + return top == other.top + && left == other.left + && bottom == other.bottom + && right == other.right; } bool BorderSize::operator!= (const BorderSize& other) const throw() { - return ! operator== (other); + return ! operator== (other); } END_JUCE_NAMESPACE @@ -87924,124 +87713,124 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE static bool juce_lineIntersection (const float x1, const float y1, - const float x2, const float y2, - const float x3, const float y3, - const float x4, const float y4, - float& intersectionX, - float& intersectionY) throw() + const float x2, const float y2, + const float x3, const float y3, + const float x4, const float y4, + float& intersectionX, + float& intersectionY) throw() { - if (x2 != x3 || y2 != y3) - { - const float dx1 = x2 - x1; - const float dy1 = y2 - y1; - const float dx2 = x4 - x3; - const float dy2 = y4 - y3; - const float divisor = dx1 * dy2 - dx2 * dy1; + if (x2 != x3 || y2 != y3) + { + const float dx1 = x2 - x1; + const float dy1 = y2 - y1; + const float dx2 = x4 - x3; + const float dy2 = y4 - y3; + const float divisor = dx1 * dy2 - dx2 * dy1; - if (divisor == 0) - { - if (! ((dx1 == 0 && dy1 == 0) || (dx2 == 0 && dy2 == 0))) - { - if (dy1 == 0 && dy2 != 0) - { - const float along = (y1 - y3) / dy2; - intersectionX = x3 + along * dx2; - intersectionY = y1; + if (divisor == 0) + { + if (! ((dx1 == 0 && dy1 == 0) || (dx2 == 0 && dy2 == 0))) + { + if (dy1 == 0 && dy2 != 0) + { + const float along = (y1 - y3) / dy2; + intersectionX = x3 + along * dx2; + intersectionY = y1; - return along >= 0 && along <= 1.0f; - } - else if (dy2 == 0 && dy1 != 0) - { - const float along = (y3 - y1) / dy1; - intersectionX = x1 + along * dx1; - intersectionY = y3; + return along >= 0 && along <= 1.0f; + } + else if (dy2 == 0 && dy1 != 0) + { + const float along = (y3 - y1) / dy1; + intersectionX = x1 + along * dx1; + intersectionY = y3; - return along >= 0 && along <= 1.0f; - } - else if (dx1 == 0 && dx2 != 0) - { - const float along = (x1 - x3) / dx2; - intersectionX = x1; - intersectionY = y3 + along * dy2; + return along >= 0 && along <= 1.0f; + } + else if (dx1 == 0 && dx2 != 0) + { + const float along = (x1 - x3) / dx2; + intersectionX = x1; + intersectionY = y3 + along * dy2; - return along >= 0 && along <= 1.0f; - } - else if (dx2 == 0 && dx1 != 0) - { - const float along = (x3 - x1) / dx1; - intersectionX = x3; - intersectionY = y1 + along * dy1; + return along >= 0 && along <= 1.0f; + } + else if (dx2 == 0 && dx1 != 0) + { + const float along = (x3 - x1) / dx1; + intersectionX = x3; + intersectionY = y1 + along * dy1; - return along >= 0 && along <= 1.0f; - } - } + return along >= 0 && along <= 1.0f; + } + } - intersectionX = 0.5f * (x2 + x3); - intersectionY = 0.5f * (y2 + y3); + intersectionX = 0.5f * (x2 + x3); + intersectionY = 0.5f * (y2 + y3); - return false; - } + return false; + } - const float along1 = ((y1 - y3) * dx2 - (x1 - x3) * dy2) / divisor; + const float along1 = ((y1 - y3) * dx2 - (x1 - x3) * dy2) / divisor; - intersectionX = x1 + along1 * dx1; - intersectionY = y1 + along1 * dy1; + intersectionX = x1 + along1 * dx1; + intersectionY = y1 + along1 * dy1; - if (along1 < 0 || along1 > 1.0f) - return false; + if (along1 < 0 || along1 > 1.0f) + return false; - const float along2 = ((y1 - y3) * dx1 - (x1 - x3) * dy1) / divisor; + const float along2 = ((y1 - y3) * dx1 - (x1 - x3) * dy1) / divisor; - return along2 >= 0 && along2 <= 1.0f; - } + return along2 >= 0 && along2 <= 1.0f; + } - intersectionX = x2; - intersectionY = y2; - return true; + intersectionX = x2; + intersectionY = y2; + return true; } Line::Line() throw() - : startX (0.0f), - startY (0.0f), - endX (0.0f), - endY (0.0f) + : startX (0.0f), + startY (0.0f), + endX (0.0f), + endY (0.0f) { } Line::Line (const Line& other) throw() - : startX (other.startX), - startY (other.startY), - endX (other.endX), - endY (other.endY) + : startX (other.startX), + startY (other.startY), + endX (other.endX), + endY (other.endY) { } Line::Line (const float startX_, const float startY_, - const float endX_, const float endY_) throw() - : startX (startX_), - startY (startY_), - endX (endX_), - endY (endY_) + const float endX_, const float endY_) throw() + : startX (startX_), + startY (startY_), + endX (endX_), + endY (endY_) { } Line::Line (const Point& start, - const Point& end) throw() - : startX (start.getX()), - startY (start.getY()), - endX (end.getX()), - endY (end.getY()) + const Point& end) throw() + : startX (start.getX()), + startY (start.getY()), + endX (end.getX()), + endY (end.getY()) { } const Line& Line::operator= (const Line& other) throw() { - startX = other.startX; - startY = other.startY; - endX = other.endX; - endY = other.endY; + startX = other.startX; + startY = other.startY; + endX = other.endX; + endY = other.endY; - return *this; + return *this; } Line::~Line() throw() @@ -88050,235 +87839,235 @@ Line::~Line() throw() const Point Line::getStart() const throw() { - return Point (startX, startY); + return Point (startX, startY); } const Point Line::getEnd() const throw() { - return Point (endX, endY); + return Point (endX, endY); } void Line::setStart (const float newStartX, - const float newStartY) throw() + const float newStartY) throw() { - startX = newStartX; - startY = newStartY; + startX = newStartX; + startY = newStartY; } void Line::setStart (const Point& newStart) throw() { - startX = newStart.getX(); - startY = newStart.getY(); + startX = newStart.getX(); + startY = newStart.getY(); } void Line::setEnd (const float newEndX, - const float newEndY) throw() + const float newEndY) throw() { - endX = newEndX; - endY = newEndY; + endX = newEndX; + endY = newEndY; } void Line::setEnd (const Point& newEnd) throw() { - endX = newEnd.getX(); - endY = newEnd.getY(); + endX = newEnd.getX(); + endY = newEnd.getY(); } bool Line::operator== (const Line& other) const throw() { - return startX == other.startX - && startY == other.startY - && endX == other.endX - && endY == other.endY; + return startX == other.startX + && startY == other.startY + && endX == other.endX + && endY == other.endY; } bool Line::operator!= (const Line& other) const throw() { - return startX != other.startX - || startY != other.startY - || endX != other.endX - || endY != other.endY; + return startX != other.startX + || startY != other.startY + || endX != other.endX + || endY != other.endY; } void Line::applyTransform (const AffineTransform& transform) throw() { - transform.transformPoint (startX, startY); - transform.transformPoint (endX, endY); + transform.transformPoint (startX, startY); + transform.transformPoint (endX, endY); } float Line::getLength() const throw() { - return (float) juce_hypot (startX - endX, - startY - endY); + return (float) juce_hypot (startX - endX, + startY - endY); } float Line::getAngle() const throw() { - return atan2f (endX - startX, - endY - startY); + return atan2f (endX - startX, + endY - startY); } const Point Line::getPointAlongLine (const float distanceFromStart) const throw() { - const float alpha = distanceFromStart / getLength(); + const float alpha = distanceFromStart / getLength(); - return Point (startX + (endX - startX) * alpha, - startY + (endY - startY) * alpha); + return Point (startX + (endX - startX) * alpha, + startY + (endY - startY) * alpha); } const Point Line::getPointAlongLine (const float offsetX, - const float offsetY) const throw() + const float offsetY) const throw() { - const float dx = endX - startX; - const float dy = endY - startY; - const double length = juce_hypot (dx, dy); + const float dx = endX - startX; + const float dy = endY - startY; + const double length = juce_hypot (dx, dy); - if (length == 0) - return Point (startX, startY); - else - return Point (startX + (float) (((dx * offsetX) - (dy * offsetY)) / length), - startY + (float) (((dy * offsetX) + (dx * offsetY)) / length)); + if (length == 0) + return Point (startX, startY); + else + return Point (startX + (float) (((dx * offsetX) - (dy * offsetY)) / length), + startY + (float) (((dy * offsetX) + (dx * offsetY)) / length)); } const Point Line::getPointAlongLineProportionally (const float alpha) const throw() { - return Point (startX + (endX - startX) * alpha, - startY + (endY - startY) * alpha); + return Point (startX + (endX - startX) * alpha, + startY + (endY - startY) * alpha); } float Line::getDistanceFromLine (const float x, - const float y) const throw() + const float y) const throw() { - const double dx = endX - startX; - const double dy = endY - startY; - const double length = dx * dx + dy * dy; + const double dx = endX - startX; + const double dy = endY - startY; + const double length = dx * dx + dy * dy; - if (length > 0) - { - const double prop = ((x - startX) * dx + (y - startY) * dy) / length; + if (length > 0) + { + const double prop = ((x - startX) * dx + (y - startY) * dy) / length; - if (prop >= 0.0f && prop < 1.0f) - { - return (float) juce_hypot (x - (startX + prop * dx), - y - (startY + prop * dy)); - } - } + if (prop >= 0.0f && prop < 1.0f) + { + return (float) juce_hypot (x - (startX + prop * dx), + y - (startY + prop * dy)); + } + } - return (float) jmin (juce_hypot (x - startX, y - startY), - juce_hypot (x - endX, y - endY)); + return (float) jmin (juce_hypot (x - startX, y - startY), + juce_hypot (x - endX, y - endY)); } float Line::findNearestPointTo (const float x, - const float y) const throw() + const float y) const throw() { - const double dx = endX - startX; - const double dy = endY - startY; - const double length = dx * dx + dy * dy; + const double dx = endX - startX; + const double dy = endY - startY; + const double length = dx * dx + dy * dy; - if (length <= 0.0) - return 0.0f; + if (length <= 0.0) + return 0.0f; - return jlimit (0.0f, 1.0f, - (float) (((x - startX) * dx + (y - startY) * dy) / length)); + return jlimit (0.0f, 1.0f, + (float) (((x - startX) * dx + (y - startY) * dy) / length)); } const Line Line::withShortenedStart (const float distanceToShortenBy) const throw() { - const float length = getLength(); + const float length = getLength(); - return Line (getPointAlongLine (jmin (distanceToShortenBy, length)), - getEnd()); + return Line (getPointAlongLine (jmin (distanceToShortenBy, length)), + getEnd()); } const Line Line::withShortenedEnd (const float distanceToShortenBy) const throw() { - const float length = getLength(); + const float length = getLength(); - return Line (getStart(), - getPointAlongLine (length - jmin (distanceToShortenBy, length))); + return Line (getStart(), + getPointAlongLine (length - jmin (distanceToShortenBy, length))); } bool Line::clipToPath (const Path& path, - const bool keepSectionOutsidePath) throw() + const bool keepSectionOutsidePath) throw() { - const bool startInside = path.contains (startX, startY); - const bool endInside = path.contains (endX, endY); + const bool startInside = path.contains (startX, startY); + const bool endInside = path.contains (endX, endY); - if (startInside == endInside) - { - if (keepSectionOutsidePath != startInside) - { - // entirely outside the path - return false; - } - else - { - // entirely inside the path - startX = 0.0f; - startY = 0.0f; - endX = 0.0f; - endY = 0.0f; + if (startInside == endInside) + { + if (keepSectionOutsidePath != startInside) + { + // entirely outside the path + return false; + } + else + { + // entirely inside the path + startX = 0.0f; + startY = 0.0f; + endX = 0.0f; + endY = 0.0f; - return true; - } - } - else - { - bool changed = false; - PathFlatteningIterator iter (path, AffineTransform::identity); + return true; + } + } + else + { + bool changed = false; + PathFlatteningIterator iter (path, AffineTransform::identity); - while (iter.next()) - { - float ix, iy; + while (iter.next()) + { + float ix, iy; - if (intersects (Line (iter.x1, iter.y1, - iter.x2, iter.y2), - ix, iy)) - { - if ((startInside && keepSectionOutsidePath) - || (endInside && ! keepSectionOutsidePath)) - { - setStart (ix, iy); - } - else - { - setEnd (ix, iy); - } + if (intersects (Line (iter.x1, iter.y1, + iter.x2, iter.y2), + ix, iy)) + { + if ((startInside && keepSectionOutsidePath) + || (endInside && ! keepSectionOutsidePath)) + { + setStart (ix, iy); + } + else + { + setEnd (ix, iy); + } - changed = true; - } - } + changed = true; + } + } - return changed; - } + return changed; + } } bool Line::intersects (const Line& line, - float& intersectionX, - float& intersectionY) const throw() + float& intersectionX, + float& intersectionY) const throw() { - return juce_lineIntersection (startX, startY, - endX, endY, - line.startX, line.startY, - line.endX, line.endY, - intersectionX, - intersectionY); + return juce_lineIntersection (startX, startY, + endX, endY, + line.startX, line.startY, + line.endX, line.endY, + intersectionX, + intersectionY); } bool Line::isVertical() const throw() { - return startX == endX; + return startX == endX; } bool Line::isHorizontal() const throw() { - return startY == endY; + return startY == endY; } bool Line::isPointAbove (const float x, const float y) const throw() { - return startX != endX - && y < ((endY - startY) * (x - startX)) / (endX - startX) + startY; + return startX != endX + && y < ((endY - startY) * (x - startX)) / (endX - startX) + startY; } END_JUCE_NAMESPACE @@ -88290,24 +88079,23 @@ BEGIN_JUCE_NAMESPACE // tests that some co-ords aren't NaNs #define CHECK_COORDS_ARE_VALID(x, y) \ - jassert (x == x && y == y); + jassert (x == x && y == y); -const float Path::lineMarker = 100001.0f; -const float Path::moveMarker = 100002.0f; -const float Path::quadMarker = 100003.0f; -const float Path::cubicMarker = 100004.0f; +const float Path::lineMarker = 100001.0f; +const float Path::moveMarker = 100002.0f; +const float Path::quadMarker = 100003.0f; +const float Path::cubicMarker = 100004.0f; const float Path::closeSubPathMarker = 100005.0f; static const int defaultGranularity = 32; Path::Path() throw() - : data (defaultGranularity), - numElements (0), - pathXMin (0), - pathXMax (0), - pathYMin (0), - pathYMax (0), - useNonZeroWinding (true) + : numElements (0), + pathXMin (0), + pathXMax (0), + pathYMin (0), + pathYMax (0), + useNonZeroWinding (true) { } @@ -88316,1472 +88104,1471 @@ Path::~Path() throw() } Path::Path (const Path& other) throw() - : data (defaultGranularity), - numElements (other.numElements), - pathXMin (other.pathXMin), - pathXMax (other.pathXMax), - pathYMin (other.pathYMin), - pathYMax (other.pathYMax), - useNonZeroWinding (other.useNonZeroWinding) + : numElements (other.numElements), + pathXMin (other.pathXMin), + pathXMax (other.pathXMax), + pathYMin (other.pathYMin), + pathYMax (other.pathYMax), + useNonZeroWinding (other.useNonZeroWinding) { - if (numElements > 0) - { - data.setAllocatedSize (numElements); - memcpy (data.elements, other.data.elements, numElements * sizeof (float)); - } + if (numElements > 0) + { + data.setAllocatedSize (numElements); + memcpy (data.elements, other.data.elements, numElements * sizeof (float)); + } } const Path& Path::operator= (const Path& other) throw() { - if (this != &other) - { - data.ensureAllocatedSize (other.numElements); + if (this != &other) + { + data.ensureAllocatedSize (other.numElements); - numElements = other.numElements; - pathXMin = other.pathXMin; - pathXMax = other.pathXMax; - pathYMin = other.pathYMin; - pathYMax = other.pathYMax; - useNonZeroWinding = other.useNonZeroWinding; + numElements = other.numElements; + pathXMin = other.pathXMin; + pathXMax = other.pathXMax; + pathYMin = other.pathYMin; + pathYMax = other.pathYMax; + useNonZeroWinding = other.useNonZeroWinding; - if (numElements > 0) - memcpy (data.elements, other.data.elements, numElements * sizeof (float)); - } + if (numElements > 0) + memcpy (data.elements, other.data.elements, numElements * sizeof (float)); + } - return *this; + return *this; } void Path::clear() throw() { - numElements = 0; - pathXMin = 0; - pathYMin = 0; - pathYMax = 0; - pathXMax = 0; + numElements = 0; + pathXMin = 0; + pathYMin = 0; + pathYMax = 0; + pathXMax = 0; } void Path::swapWithPath (Path& other) { - swapVariables (data.numAllocated, other.data.numAllocated); - swapVariables (data.elements, other.data.elements); - swapVariables (numElements, other.numElements); - swapVariables (pathXMin, other.pathXMin); - swapVariables (pathXMax, other.pathXMax); - swapVariables (pathYMin, other.pathYMin); - swapVariables (pathYMax, other.pathYMax); - swapVariables (useNonZeroWinding, other.useNonZeroWinding); + swapVariables (data.numAllocated, other.data.numAllocated); + swapVariables (data.elements, other.data.elements); + swapVariables (numElements, other.numElements); + swapVariables (pathXMin, other.pathXMin); + swapVariables (pathXMax, other.pathXMax); + swapVariables (pathYMin, other.pathYMin); + swapVariables (pathYMax, other.pathYMax); + swapVariables (useNonZeroWinding, other.useNonZeroWinding); } void Path::setUsingNonZeroWinding (const bool isNonZero) throw() { - useNonZeroWinding = isNonZero; + useNonZeroWinding = isNonZero; } void Path::scaleToFit (const float x, const float y, const float w, const float h, - const bool preserveProportions) throw() + const bool preserveProportions) throw() { - applyTransform (getTransformToScaleToFit (x, y, w, h, preserveProportions)); + applyTransform (getTransformToScaleToFit (x, y, w, h, preserveProportions)); } bool Path::isEmpty() const throw() { - int i = 0; + int i = 0; - while (i < numElements) - { - const float type = data.elements [i++]; + while (i < numElements) + { + const float type = data.elements [i++]; - if (type == moveMarker) - { - i += 2; - } - else if (type == lineMarker - || type == quadMarker - || type == cubicMarker) - { - return false; - } - } + if (type == moveMarker) + { + i += 2; + } + else if (type == lineMarker + || type == quadMarker + || type == cubicMarker) + { + return false; + } + } - return true; + return true; } void Path::getBounds (float& x, float& y, - float& w, float& h) const throw() + float& w, float& h) const throw() { - x = pathXMin; - y = pathYMin; - w = pathXMax - pathXMin; - h = pathYMax - pathYMin; + x = pathXMin; + y = pathYMin; + w = pathXMax - pathXMin; + h = pathYMax - pathYMin; } void Path::getBoundsTransformed (const AffineTransform& transform, - float& x, float& y, - float& w, float& h) const throw() + float& x, float& y, + float& w, float& h) const throw() { - float x1 = pathXMin; - float y1 = pathYMin; - transform.transformPoint (x1, y1); + float x1 = pathXMin; + float y1 = pathYMin; + transform.transformPoint (x1, y1); - float x2 = pathXMax; - float y2 = pathYMin; - transform.transformPoint (x2, y2); + float x2 = pathXMax; + float y2 = pathYMin; + transform.transformPoint (x2, y2); - float x3 = pathXMin; - float y3 = pathYMax; - transform.transformPoint (x3, y3); + float x3 = pathXMin; + float y3 = pathYMax; + transform.transformPoint (x3, y3); - float x4 = pathXMax; - float y4 = pathYMax; - transform.transformPoint (x4, y4); + float x4 = pathXMax; + float y4 = pathYMax; + transform.transformPoint (x4, y4); - x = jmin (x1, x2, x3, x4); - y = jmin (y1, y2, y3, y4); - w = jmax (x1, x2, x3, x4) - x; - h = jmax (y1, y2, y3, y4) - y; + x = jmin (x1, x2, x3, x4); + y = jmin (y1, y2, y3, y4); + w = jmax (x1, x2, x3, x4) - x; + h = jmax (y1, y2, y3, y4) - y; } void Path::startNewSubPath (const float x, - const float y) throw() + const float y) throw() { - CHECK_COORDS_ARE_VALID (x, y); + CHECK_COORDS_ARE_VALID (x, y); - if (numElements == 0) - { - pathXMin = pathXMax = x; - pathYMin = pathYMax = y; - } - else - { - pathXMin = jmin (pathXMin, x); - pathXMax = jmax (pathXMax, x); - pathYMin = jmin (pathYMin, y); - pathYMax = jmax (pathYMax, y); - } + if (numElements == 0) + { + pathXMin = pathXMax = x; + pathYMin = pathYMax = y; + } + else + { + pathXMin = jmin (pathXMin, x); + pathXMax = jmax (pathXMax, x); + pathYMin = jmin (pathYMin, y); + pathYMax = jmax (pathYMax, y); + } - data.ensureAllocatedSize (numElements + 3); + data.ensureAllocatedSize (numElements + 3); - data.elements [numElements++] = moveMarker; - data.elements [numElements++] = x; - data.elements [numElements++] = y; + data.elements [numElements++] = moveMarker; + data.elements [numElements++] = x; + data.elements [numElements++] = y; } void Path::lineTo (const float x, const float y) throw() { - CHECK_COORDS_ARE_VALID (x, y); + CHECK_COORDS_ARE_VALID (x, y); - if (numElements == 0) - startNewSubPath (0, 0); + if (numElements == 0) + startNewSubPath (0, 0); - data.ensureAllocatedSize (numElements + 3); + data.ensureAllocatedSize (numElements + 3); - data.elements [numElements++] = lineMarker; - data.elements [numElements++] = x; - data.elements [numElements++] = y; + data.elements [numElements++] = lineMarker; + data.elements [numElements++] = x; + data.elements [numElements++] = y; - pathXMin = jmin (pathXMin, x); - pathXMax = jmax (pathXMax, x); - pathYMin = jmin (pathYMin, y); - pathYMax = jmax (pathYMax, y); + pathXMin = jmin (pathXMin, x); + pathXMax = jmax (pathXMax, x); + pathYMin = jmin (pathYMin, y); + pathYMax = jmax (pathYMax, y); } void Path::quadraticTo (const float x1, const float y1, - const float x2, const float y2) throw() + const float x2, const float y2) throw() { - CHECK_COORDS_ARE_VALID (x1, y1); - CHECK_COORDS_ARE_VALID (x2, y2); + CHECK_COORDS_ARE_VALID (x1, y1); + CHECK_COORDS_ARE_VALID (x2, y2); - if (numElements == 0) - startNewSubPath (0, 0); + if (numElements == 0) + startNewSubPath (0, 0); - data.ensureAllocatedSize (numElements + 5); + data.ensureAllocatedSize (numElements + 5); - data.elements [numElements++] = quadMarker; - data.elements [numElements++] = x1; - data.elements [numElements++] = y1; - data.elements [numElements++] = x2; - data.elements [numElements++] = y2; + data.elements [numElements++] = quadMarker; + data.elements [numElements++] = x1; + data.elements [numElements++] = y1; + data.elements [numElements++] = x2; + data.elements [numElements++] = y2; - pathXMin = jmin (pathXMin, x1, x2); - pathXMax = jmax (pathXMax, x1, x2); - pathYMin = jmin (pathYMin, y1, y2); - pathYMax = jmax (pathYMax, y1, y2); + pathXMin = jmin (pathXMin, x1, x2); + pathXMax = jmax (pathXMax, x1, x2); + pathYMin = jmin (pathYMin, y1, y2); + pathYMax = jmax (pathYMax, y1, y2); } void Path::cubicTo (const float x1, const float y1, - const float x2, const float y2, - const float x3, const float y3) throw() + const float x2, const float y2, + const float x3, const float y3) throw() { - CHECK_COORDS_ARE_VALID (x1, y1); - CHECK_COORDS_ARE_VALID (x2, y2); - CHECK_COORDS_ARE_VALID (x3, y3); + CHECK_COORDS_ARE_VALID (x1, y1); + CHECK_COORDS_ARE_VALID (x2, y2); + CHECK_COORDS_ARE_VALID (x3, y3); - if (numElements == 0) - startNewSubPath (0, 0); + if (numElements == 0) + startNewSubPath (0, 0); - data.ensureAllocatedSize (numElements + 7); + data.ensureAllocatedSize (numElements + 7); - data.elements [numElements++] = cubicMarker; - data.elements [numElements++] = x1; - data.elements [numElements++] = y1; - data.elements [numElements++] = x2; - data.elements [numElements++] = y2; - data.elements [numElements++] = x3; - data.elements [numElements++] = y3; + data.elements [numElements++] = cubicMarker; + data.elements [numElements++] = x1; + data.elements [numElements++] = y1; + data.elements [numElements++] = x2; + data.elements [numElements++] = y2; + data.elements [numElements++] = x3; + data.elements [numElements++] = y3; - pathXMin = jmin (pathXMin, x1, x2, x3); - pathXMax = jmax (pathXMax, x1, x2, x3); - pathYMin = jmin (pathYMin, y1, y2, y3); - pathYMax = jmax (pathYMax, y1, y2, y3); + pathXMin = jmin (pathXMin, x1, x2, x3); + pathXMax = jmax (pathXMax, x1, x2, x3); + pathYMin = jmin (pathYMin, y1, y2, y3); + pathYMax = jmax (pathYMax, y1, y2, y3); } void Path::closeSubPath() throw() { - if (numElements > 0 - && data.elements [numElements - 1] != closeSubPathMarker) - { - data.ensureAllocatedSize (numElements + 1); - data.elements [numElements++] = closeSubPathMarker; - } + if (numElements > 0 + && data.elements [numElements - 1] != closeSubPathMarker) + { + data.ensureAllocatedSize (numElements + 1); + data.elements [numElements++] = closeSubPathMarker; + } } const Point Path::getCurrentPosition() const { - int i = numElements - 1; + int i = numElements - 1; - if (i > 0 && data.elements[i] == closeSubPathMarker) - { - while (i >= 0) - { - if (data.elements[i] == moveMarker) - { - i += 2; - break; - } + if (i > 0 && data.elements[i] == closeSubPathMarker) + { + while (i >= 0) + { + if (data.elements[i] == moveMarker) + { + i += 2; + break; + } - --i; - } - } + --i; + } + } - if (i > 0) - return Point (data.elements [i - 1], data.elements [i]); + if (i > 0) + return Point (data.elements [i - 1], data.elements [i]); - return Point (0.0f, 0.0f); + return Point (0.0f, 0.0f); } void Path::addRectangle (const float x, const float y, - const float w, const float h) throw() + const float w, const float h) throw() { - float x1 = x, y1 = y, x2 = x + w, y2 = y + h; + float x1 = x, y1 = y, x2 = x + w, y2 = y + h; - if (w < 0) - swapVariables (x1, x2); + if (w < 0) + swapVariables (x1, x2); - if (h < 0) - swapVariables (y1, y2); + if (h < 0) + swapVariables (y1, y2); - data.ensureAllocatedSize (numElements + 13); + data.ensureAllocatedSize (numElements + 13); - if (numElements == 0) - { - pathXMin = x1; - pathXMax = x2; - pathYMin = y1; - pathYMax = y2; - } - else - { - pathXMin = jmin (pathXMin, x1); - pathXMax = jmax (pathXMax, x2); - pathYMin = jmin (pathYMin, y1); - pathYMax = jmax (pathYMax, y2); - } + if (numElements == 0) + { + pathXMin = x1; + pathXMax = x2; + pathYMin = y1; + pathYMax = y2; + } + else + { + pathXMin = jmin (pathXMin, x1); + pathXMax = jmax (pathXMax, x2); + pathYMin = jmin (pathYMin, y1); + pathYMax = jmax (pathYMax, y2); + } - data.elements [numElements++] = moveMarker; - data.elements [numElements++] = x1; - data.elements [numElements++] = y2; - data.elements [numElements++] = lineMarker; - data.elements [numElements++] = x1; - data.elements [numElements++] = y1; - data.elements [numElements++] = lineMarker; - data.elements [numElements++] = x2; - data.elements [numElements++] = y1; - data.elements [numElements++] = lineMarker; - data.elements [numElements++] = x2; - data.elements [numElements++] = y2; - data.elements [numElements++] = closeSubPathMarker; + data.elements [numElements++] = moveMarker; + data.elements [numElements++] = x1; + data.elements [numElements++] = y2; + data.elements [numElements++] = lineMarker; + data.elements [numElements++] = x1; + data.elements [numElements++] = y1; + data.elements [numElements++] = lineMarker; + data.elements [numElements++] = x2; + data.elements [numElements++] = y1; + data.elements [numElements++] = lineMarker; + data.elements [numElements++] = x2; + data.elements [numElements++] = y2; + data.elements [numElements++] = closeSubPathMarker; } void Path::addRectangle (const Rectangle& rectangle) throw() { - addRectangle ((float) rectangle.getX(), (float) rectangle.getY(), - (float) rectangle.getWidth(), (float) rectangle.getHeight()); + addRectangle ((float) rectangle.getX(), (float) rectangle.getY(), + (float) rectangle.getWidth(), (float) rectangle.getHeight()); } void Path::addRoundedRectangle (const float x, const float y, - const float w, const float h, - float csx, - float csy) throw() + const float w, const float h, + float csx, + float csy) throw() { - csx = jmin (csx, w * 0.5f); - csy = jmin (csy, h * 0.5f); - const float cs45x = csx * 0.45f; - const float cs45y = csy * 0.45f; - const float x2 = x + w; - const float y2 = y + h; + csx = jmin (csx, w * 0.5f); + csy = jmin (csy, h * 0.5f); + const float cs45x = csx * 0.45f; + const float cs45y = csy * 0.45f; + const float x2 = x + w; + const float y2 = y + h; - startNewSubPath (x + csx, y); - lineTo (x2 - csx, y); - cubicTo (x2 - cs45x, y, x2, y + cs45y, x2, y + csy); - lineTo (x2, y2 - csy); - cubicTo (x2, y2 - cs45y, x2 - cs45x, y2, x2 - csx, y2); - lineTo (x + csx, y2); - cubicTo (x + cs45x, y2, x, y2 - cs45y, x, y2 - csy); - lineTo (x, y + csy); - cubicTo (x, y + cs45y, x + cs45x, y, x + csx, y); - closeSubPath(); + startNewSubPath (x + csx, y); + lineTo (x2 - csx, y); + cubicTo (x2 - cs45x, y, x2, y + cs45y, x2, y + csy); + lineTo (x2, y2 - csy); + cubicTo (x2, y2 - cs45y, x2 - cs45x, y2, x2 - csx, y2); + lineTo (x + csx, y2); + cubicTo (x + cs45x, y2, x, y2 - cs45y, x, y2 - csy); + lineTo (x, y + csy); + cubicTo (x, y + cs45y, x + cs45x, y, x + csx, y); + closeSubPath(); } void Path::addRoundedRectangle (const float x, const float y, - const float w, const float h, - float cs) throw() + const float w, const float h, + float cs) throw() { - addRoundedRectangle (x, y, w, h, cs, cs); + addRoundedRectangle (x, y, w, h, cs, cs); } void Path::addTriangle (const float x1, const float y1, - const float x2, const float y2, - const float x3, const float y3) throw() + const float x2, const float y2, + const float x3, const float y3) throw() { - startNewSubPath (x1, y1); - lineTo (x2, y2); - lineTo (x3, y3); - closeSubPath(); + startNewSubPath (x1, y1); + lineTo (x2, y2); + lineTo (x3, y3); + closeSubPath(); } void Path::addQuadrilateral (const float x1, const float y1, - const float x2, const float y2, - const float x3, const float y3, - const float x4, const float y4) throw() + const float x2, const float y2, + const float x3, const float y3, + const float x4, const float y4) throw() { - startNewSubPath (x1, y1); - lineTo (x2, y2); - lineTo (x3, y3); - lineTo (x4, y4); - closeSubPath(); + startNewSubPath (x1, y1); + lineTo (x2, y2); + lineTo (x3, y3); + lineTo (x4, y4); + closeSubPath(); } void Path::addEllipse (const float x, const float y, - const float w, const float h) throw() + const float w, const float h) throw() { - const float hw = w * 0.5f; - const float hw55 = hw * 0.55f; - const float hh = h * 0.5f; - const float hh45 = hh * 0.55f; - const float cx = x + hw; - const float cy = y + hh; + const float hw = w * 0.5f; + const float hw55 = hw * 0.55f; + const float hh = h * 0.5f; + const float hh45 = hh * 0.55f; + const float cx = x + hw; + const float cy = y + hh; - startNewSubPath (cx, cy - hh); - cubicTo (cx + hw55, cy - hh, cx + hw, cy - hh45, cx + hw, cy); - cubicTo (cx + hw, cy + hh45, cx + hw55, cy + hh, cx, cy + hh); - cubicTo (cx - hw55, cy + hh, cx - hw, cy + hh45, cx - hw, cy); - cubicTo (cx - hw, cy - hh45, cx - hw55, cy - hh, cx, cy - hh); - closeSubPath(); + startNewSubPath (cx, cy - hh); + cubicTo (cx + hw55, cy - hh, cx + hw, cy - hh45, cx + hw, cy); + cubicTo (cx + hw, cy + hh45, cx + hw55, cy + hh, cx, cy + hh); + cubicTo (cx - hw55, cy + hh, cx - hw, cy + hh45, cx - hw, cy); + cubicTo (cx - hw, cy - hh45, cx - hw55, cy - hh, cx, cy - hh); + closeSubPath(); } void Path::addArc (const float x, const float y, - const float w, const float h, - const float fromRadians, - const float toRadians, - const bool startAsNewSubPath) throw() + const float w, const float h, + const float fromRadians, + const float toRadians, + const bool startAsNewSubPath) throw() { - const float radiusX = w / 2.0f; - const float radiusY = h / 2.0f; + const float radiusX = w / 2.0f; + const float radiusY = h / 2.0f; - addCentredArc (x + radiusX, - y + radiusY, - radiusX, radiusY, - 0.0f, - fromRadians, toRadians, - startAsNewSubPath); + addCentredArc (x + radiusX, + y + radiusY, + radiusX, radiusY, + 0.0f, + fromRadians, toRadians, + startAsNewSubPath); } static const float ellipseAngularIncrement = 0.05f; void Path::addCentredArc (const float centreX, const float centreY, - const float radiusX, const float radiusY, - const float rotationOfEllipse, - const float fromRadians, - const float toRadians, - const bool startAsNewSubPath) throw() + const float radiusX, const float radiusY, + const float rotationOfEllipse, + const float fromRadians, + const float toRadians, + const bool startAsNewSubPath) throw() { - if (radiusX > 0.0f && radiusY > 0.0f) - { - const AffineTransform rotation (AffineTransform::rotation (rotationOfEllipse, centreX, centreY)); - float angle = fromRadians; + if (radiusX > 0.0f && radiusY > 0.0f) + { + const AffineTransform rotation (AffineTransform::rotation (rotationOfEllipse, centreX, centreY)); + float angle = fromRadians; - if (startAsNewSubPath) - { - float x = centreX + radiusX * sinf (angle); - float y = centreY - radiusY * cosf (angle); + if (startAsNewSubPath) + { + float x = centreX + radiusX * sinf (angle); + float y = centreY - radiusY * cosf (angle); - if (rotationOfEllipse != 0) - rotation.transformPoint (x, y); + if (rotationOfEllipse != 0) + rotation.transformPoint (x, y); - startNewSubPath (x, y); - } + startNewSubPath (x, y); + } - if (fromRadians < toRadians) - { - if (startAsNewSubPath) - angle += ellipseAngularIncrement; + if (fromRadians < toRadians) + { + if (startAsNewSubPath) + angle += ellipseAngularIncrement; - while (angle < toRadians) - { - float x = centreX + radiusX * sinf (angle); - float y = centreY - radiusY * cosf (angle); + while (angle < toRadians) + { + float x = centreX + radiusX * sinf (angle); + float y = centreY - radiusY * cosf (angle); - if (rotationOfEllipse != 0) - rotation.transformPoint (x, y); + if (rotationOfEllipse != 0) + rotation.transformPoint (x, y); - lineTo (x, y); + lineTo (x, y); - angle += ellipseAngularIncrement; - } - } - else - { - if (startAsNewSubPath) - angle -= ellipseAngularIncrement; + angle += ellipseAngularIncrement; + } + } + else + { + if (startAsNewSubPath) + angle -= ellipseAngularIncrement; - while (angle > toRadians) - { - float x = centreX + radiusX * sinf (angle); - float y = centreY - radiusY * cosf (angle); + while (angle > toRadians) + { + float x = centreX + radiusX * sinf (angle); + float y = centreY - radiusY * cosf (angle); - if (rotationOfEllipse != 0) - rotation.transformPoint (x, y); + if (rotationOfEllipse != 0) + rotation.transformPoint (x, y); - lineTo (x, y); + lineTo (x, y); - angle -= ellipseAngularIncrement; - } - } + angle -= ellipseAngularIncrement; + } + } - float x = centreX + radiusX * sinf (toRadians); - float y = centreY - radiusY * cosf (toRadians); + float x = centreX + radiusX * sinf (toRadians); + float y = centreY - radiusY * cosf (toRadians); - if (rotationOfEllipse != 0) - rotation.transformPoint (x, y); + if (rotationOfEllipse != 0) + rotation.transformPoint (x, y); - lineTo (x, y); - } + lineTo (x, y); + } } void Path::addPieSegment (const float x, const float y, - const float width, const float height, - const float fromRadians, - const float toRadians, - const float innerCircleProportionalSize) + const float width, const float height, + const float fromRadians, + const float toRadians, + const float innerCircleProportionalSize) { - float hw = width * 0.5f; - float hh = height * 0.5f; - const float centreX = x + hw; - const float centreY = y + hh; + float hw = width * 0.5f; + float hh = height * 0.5f; + const float centreX = x + hw; + const float centreY = y + hh; - startNewSubPath (centreX + hw * sinf (fromRadians), - centreY - hh * cosf (fromRadians)); + startNewSubPath (centreX + hw * sinf (fromRadians), + centreY - hh * cosf (fromRadians)); - addArc (x, y, width, height, fromRadians, toRadians); + addArc (x, y, width, height, fromRadians, toRadians); - if (fabs (fromRadians - toRadians) > float_Pi * 1.999f) - { - closeSubPath(); + if (fabs (fromRadians - toRadians) > float_Pi * 1.999f) + { + closeSubPath(); - if (innerCircleProportionalSize > 0) - { - hw *= innerCircleProportionalSize; - hh *= innerCircleProportionalSize; + if (innerCircleProportionalSize > 0) + { + hw *= innerCircleProportionalSize; + hh *= innerCircleProportionalSize; - startNewSubPath (centreX + hw * sinf (toRadians), - centreY - hh * cosf (toRadians)); + startNewSubPath (centreX + hw * sinf (toRadians), + centreY - hh * cosf (toRadians)); - addArc (centreX - hw, centreY - hh, hw * 2.0f, hh * 2.0f, - toRadians, fromRadians); - } - } - else - { - if (innerCircleProportionalSize > 0) - { - hw *= innerCircleProportionalSize; - hh *= innerCircleProportionalSize; + addArc (centreX - hw, centreY - hh, hw * 2.0f, hh * 2.0f, + toRadians, fromRadians); + } + } + else + { + if (innerCircleProportionalSize > 0) + { + hw *= innerCircleProportionalSize; + hh *= innerCircleProportionalSize; - addArc (centreX - hw, centreY - hh, hw * 2.0f, hh * 2.0f, - toRadians, fromRadians); - } - else - { - lineTo (centreX, centreY); - } - } + addArc (centreX - hw, centreY - hh, hw * 2.0f, hh * 2.0f, + toRadians, fromRadians); + } + else + { + lineTo (centreX, centreY); + } + } - closeSubPath(); + closeSubPath(); } static void perpendicularOffset (const float x1, const float y1, - const float x2, const float y2, - const float offsetX, const float offsetY, - float& resultX, float& resultY) throw() + const float x2, const float y2, + const float offsetX, const float offsetY, + float& resultX, float& resultY) throw() { - const float dx = x2 - x1; - const float dy = y2 - y1; - const float len = juce_hypotf (dx, dy); + const float dx = x2 - x1; + const float dy = y2 - y1; + const float len = juce_hypotf (dx, dy); - if (len == 0) - { - resultX = x1; - resultY = y1; - } - else - { - resultX = x1 + ((dx * offsetX) - (dy * offsetY)) / len; - resultY = y1 + ((dy * offsetX) + (dx * offsetY)) / len; - } + if (len == 0) + { + resultX = x1; + resultY = y1; + } + else + { + resultX = x1 + ((dx * offsetX) - (dy * offsetY)) / len; + resultY = y1 + ((dy * offsetX) + (dx * offsetY)) / len; + } } void Path::addLineSegment (const float startX, const float startY, - const float endX, const float endY, - float lineThickness) throw() + const float endX, const float endY, + float lineThickness) throw() { - lineThickness *= 0.5f; + lineThickness *= 0.5f; - float x, y; + float x, y; - perpendicularOffset (startX, startY, endX, endY, - 0, lineThickness, x, y); - startNewSubPath (x, y); + perpendicularOffset (startX, startY, endX, endY, + 0, lineThickness, x, y); + startNewSubPath (x, y); - perpendicularOffset (startX, startY, endX, endY, - 0, -lineThickness, x, y); - lineTo (x, y); + perpendicularOffset (startX, startY, endX, endY, + 0, -lineThickness, x, y); + lineTo (x, y); - perpendicularOffset (endX, endY, startX, startY, - 0, lineThickness, x, y); - lineTo (x, y); + perpendicularOffset (endX, endY, startX, startY, + 0, lineThickness, x, y); + lineTo (x, y); - perpendicularOffset (endX, endY, startX, startY, - 0, -lineThickness, x, y); - lineTo (x, y); + perpendicularOffset (endX, endY, startX, startY, + 0, -lineThickness, x, y); + lineTo (x, y); - closeSubPath(); + closeSubPath(); } void Path::addArrow (const float startX, const float startY, - const float endX, const float endY, - float lineThickness, - float arrowheadWidth, - float arrowheadLength) throw() + const float endX, const float endY, + float lineThickness, + float arrowheadWidth, + float arrowheadLength) throw() { - lineThickness *= 0.5f; - arrowheadWidth *= 0.5f; - arrowheadLength = jmin (arrowheadLength, 0.8f * juce_hypotf (startX - endX, - startY - endY)); + lineThickness *= 0.5f; + arrowheadWidth *= 0.5f; + arrowheadLength = jmin (arrowheadLength, 0.8f * juce_hypotf (startX - endX, + startY - endY)); - float x, y; + float x, y; - perpendicularOffset (startX, startY, endX, endY, - 0, lineThickness, x, y); - startNewSubPath (x, y); + perpendicularOffset (startX, startY, endX, endY, + 0, lineThickness, x, y); + startNewSubPath (x, y); - perpendicularOffset (startX, startY, endX, endY, - 0, -lineThickness, x, y); - lineTo (x, y); + perpendicularOffset (startX, startY, endX, endY, + 0, -lineThickness, x, y); + lineTo (x, y); - perpendicularOffset (endX, endY, startX, startY, - arrowheadLength, lineThickness, x, y); - lineTo (x, y); + perpendicularOffset (endX, endY, startX, startY, + arrowheadLength, lineThickness, x, y); + lineTo (x, y); - perpendicularOffset (endX, endY, startX, startY, - arrowheadLength, arrowheadWidth, x, y); - lineTo (x, y); + perpendicularOffset (endX, endY, startX, startY, + arrowheadLength, arrowheadWidth, x, y); + lineTo (x, y); - perpendicularOffset (endX, endY, startX, startY, - 0, 0, x, y); - lineTo (x, y); + perpendicularOffset (endX, endY, startX, startY, + 0, 0, x, y); + lineTo (x, y); - perpendicularOffset (endX, endY, startX, startY, - arrowheadLength, -arrowheadWidth, x, y); - lineTo (x, y); + perpendicularOffset (endX, endY, startX, startY, + arrowheadLength, -arrowheadWidth, x, y); + lineTo (x, y); - perpendicularOffset (endX, endY, startX, startY, - arrowheadLength, -lineThickness, x, y); - lineTo (x, y); + perpendicularOffset (endX, endY, startX, startY, + arrowheadLength, -lineThickness, x, y); + lineTo (x, y); - closeSubPath(); + closeSubPath(); } void Path::addStar (const float centreX, - const float centreY, - const int numberOfPoints, - const float innerRadius, - const float outerRadius, - const float startAngle) + const float centreY, + const int numberOfPoints, + const float innerRadius, + const float outerRadius, + const float startAngle) { - jassert (numberOfPoints > 1); // this would be silly. + jassert (numberOfPoints > 1); // this would be silly. - if (numberOfPoints > 1) - { - const float angleBetweenPoints = float_Pi * 2.0f / numberOfPoints; + if (numberOfPoints > 1) + { + const float angleBetweenPoints = float_Pi * 2.0f / numberOfPoints; - for (int i = 0; i < numberOfPoints; ++i) - { - float angle = startAngle + i * angleBetweenPoints; + for (int i = 0; i < numberOfPoints; ++i) + { + float angle = startAngle + i * angleBetweenPoints; - const float x = centreX + outerRadius * sinf (angle); - const float y = centreY - outerRadius * cosf (angle); + const float x = centreX + outerRadius * sinf (angle); + const float y = centreY - outerRadius * cosf (angle); - if (i == 0) - startNewSubPath (x, y); - else - lineTo (x, y); + if (i == 0) + startNewSubPath (x, y); + else + lineTo (x, y); - angle += angleBetweenPoints * 0.5f; + angle += angleBetweenPoints * 0.5f; - lineTo (centreX + innerRadius * sinf (angle), - centreY - innerRadius * cosf (angle)); - } + lineTo (centreX + innerRadius * sinf (angle), + centreY - innerRadius * cosf (angle)); + } - closeSubPath(); - } + closeSubPath(); + } } void Path::addBubble (float x, float y, - float w, float h, - float cs, - float tipX, - float tipY, - int whichSide, - float arrowPos, - float arrowWidth) + float w, float h, + float cs, + float tipX, + float tipY, + int whichSide, + float arrowPos, + float arrowWidth) { - if (w > 1.0f && h > 1.0f) - { - cs = jmin (cs, w * 0.5f, h * 0.5f); - const float cs2 = 2.0f * cs; + if (w > 1.0f && h > 1.0f) + { + cs = jmin (cs, w * 0.5f, h * 0.5f); + const float cs2 = 2.0f * cs; - startNewSubPath (x + cs, y); + startNewSubPath (x + cs, y); - if (whichSide == 0) - { - const float halfArrowW = jmin (arrowWidth, w - cs2) * 0.5f; - const float arrowX1 = x + cs + jmax (0.0f, (w - cs2) * arrowPos - halfArrowW); - lineTo (arrowX1, y); - lineTo (tipX, tipY); - lineTo (arrowX1 + halfArrowW * 2.0f, y); - } + if (whichSide == 0) + { + const float halfArrowW = jmin (arrowWidth, w - cs2) * 0.5f; + const float arrowX1 = x + cs + jmax (0.0f, (w - cs2) * arrowPos - halfArrowW); + lineTo (arrowX1, y); + lineTo (tipX, tipY); + lineTo (arrowX1 + halfArrowW * 2.0f, y); + } - lineTo (x + w - cs, y); + lineTo (x + w - cs, y); - if (cs > 0.0f) - addArc (x + w - cs2, y, cs2, cs2, 0, float_Pi * 0.5f); + if (cs > 0.0f) + addArc (x + w - cs2, y, cs2, cs2, 0, float_Pi * 0.5f); - if (whichSide == 3) - { - const float halfArrowH = jmin (arrowWidth, h - cs2) * 0.5f; - const float arrowY1 = y + cs + jmax (0.0f, (h - cs2) * arrowPos - halfArrowH); - lineTo (x + w, arrowY1); - lineTo (tipX, tipY); - lineTo (x + w, arrowY1 + halfArrowH * 2.0f); - } + if (whichSide == 3) + { + const float halfArrowH = jmin (arrowWidth, h - cs2) * 0.5f; + const float arrowY1 = y + cs + jmax (0.0f, (h - cs2) * arrowPos - halfArrowH); + lineTo (x + w, arrowY1); + lineTo (tipX, tipY); + lineTo (x + w, arrowY1 + halfArrowH * 2.0f); + } - lineTo (x + w, y + h - cs); + lineTo (x + w, y + h - cs); - if (cs > 0.0f) - addArc (x + w - cs2, y + h - cs2, cs2, cs2, float_Pi * 0.5f, float_Pi); + if (cs > 0.0f) + addArc (x + w - cs2, y + h - cs2, cs2, cs2, float_Pi * 0.5f, float_Pi); - if (whichSide == 2) - { - const float halfArrowW = jmin (arrowWidth, w - cs2) * 0.5f; - const float arrowX1 = x + cs + jmax (0.0f, (w - cs2) * arrowPos - halfArrowW); - lineTo (arrowX1 + halfArrowW * 2.0f, y + h); - lineTo (tipX, tipY); - lineTo (arrowX1, y + h); - } + if (whichSide == 2) + { + const float halfArrowW = jmin (arrowWidth, w - cs2) * 0.5f; + const float arrowX1 = x + cs + jmax (0.0f, (w - cs2) * arrowPos - halfArrowW); + lineTo (arrowX1 + halfArrowW * 2.0f, y + h); + lineTo (tipX, tipY); + lineTo (arrowX1, y + h); + } - lineTo (x + cs, y + h); + lineTo (x + cs, y + h); - if (cs > 0.0f) - addArc (x, y + h - cs2, cs2, cs2, float_Pi, float_Pi * 1.5f); + if (cs > 0.0f) + addArc (x, y + h - cs2, cs2, cs2, float_Pi, float_Pi * 1.5f); - if (whichSide == 1) - { - const float halfArrowH = jmin (arrowWidth, h - cs2) * 0.5f; - const float arrowY1 = y + cs + jmax (0.0f, (h - cs2) * arrowPos - halfArrowH); - lineTo (x, arrowY1 + halfArrowH * 2.0f); - lineTo (tipX, tipY); - lineTo (x, arrowY1); - } + if (whichSide == 1) + { + const float halfArrowH = jmin (arrowWidth, h - cs2) * 0.5f; + const float arrowY1 = y + cs + jmax (0.0f, (h - cs2) * arrowPos - halfArrowH); + lineTo (x, arrowY1 + halfArrowH * 2.0f); + lineTo (tipX, tipY); + lineTo (x, arrowY1); + } - lineTo (x, y + cs); + lineTo (x, y + cs); - if (cs > 0.0f) - addArc (x, y, cs2, cs2, float_Pi * 1.5f, float_Pi * 2.0f - ellipseAngularIncrement); + if (cs > 0.0f) + addArc (x, y, cs2, cs2, float_Pi * 1.5f, float_Pi * 2.0f - ellipseAngularIncrement); - closeSubPath(); - } + closeSubPath(); + } } void Path::addPath (const Path& other) throw() { - int i = 0; + int i = 0; - while (i < other.numElements) - { - const float type = other.data.elements [i++]; + while (i < other.numElements) + { + const float type = other.data.elements [i++]; - if (type == moveMarker) - { - startNewSubPath (other.data.elements [i], - other.data.elements [i + 1]); + if (type == moveMarker) + { + startNewSubPath (other.data.elements [i], + other.data.elements [i + 1]); - i += 2; - } - else if (type == lineMarker) - { - lineTo (other.data.elements [i], - other.data.elements [i + 1]); + i += 2; + } + else if (type == lineMarker) + { + lineTo (other.data.elements [i], + other.data.elements [i + 1]); - i += 2; - } - else if (type == quadMarker) - { - quadraticTo (other.data.elements [i], - other.data.elements [i + 1], - other.data.elements [i + 2], - other.data.elements [i + 3]); - i += 4; - } - else if (type == cubicMarker) - { - cubicTo (other.data.elements [i], - other.data.elements [i + 1], - other.data.elements [i + 2], - other.data.elements [i + 3], - other.data.elements [i + 4], - other.data.elements [i + 5]); + i += 2; + } + else if (type == quadMarker) + { + quadraticTo (other.data.elements [i], + other.data.elements [i + 1], + other.data.elements [i + 2], + other.data.elements [i + 3]); + i += 4; + } + else if (type == cubicMarker) + { + cubicTo (other.data.elements [i], + other.data.elements [i + 1], + other.data.elements [i + 2], + other.data.elements [i + 3], + other.data.elements [i + 4], + other.data.elements [i + 5]); - i += 6; - } - else if (type == closeSubPathMarker) - { - closeSubPath(); - } - else - { - // something's gone wrong with the element list! - jassertfalse - } - } + i += 6; + } + else if (type == closeSubPathMarker) + { + closeSubPath(); + } + else + { + // something's gone wrong with the element list! + jassertfalse + } + } } void Path::addPath (const Path& other, - const AffineTransform& transformToApply) throw() + const AffineTransform& transformToApply) throw() { - int i = 0; + int i = 0; - while (i < other.numElements) - { - const float type = other.data.elements [i++]; + while (i < other.numElements) + { + const float type = other.data.elements [i++]; - if (type == closeSubPathMarker) - { - closeSubPath(); - } - else - { - float x = other.data.elements [i++]; - float y = other.data.elements [i++]; - transformToApply.transformPoint (x, y); + if (type == closeSubPathMarker) + { + closeSubPath(); + } + else + { + float x = other.data.elements [i++]; + float y = other.data.elements [i++]; + transformToApply.transformPoint (x, y); - if (type == moveMarker) - { - startNewSubPath (x, y); - } - else if (type == lineMarker) - { - lineTo (x, y); - } - else if (type == quadMarker) - { - float x2 = other.data.elements [i++]; - float y2 = other.data.elements [i++]; - transformToApply.transformPoint (x2, y2); + if (type == moveMarker) + { + startNewSubPath (x, y); + } + else if (type == lineMarker) + { + lineTo (x, y); + } + else if (type == quadMarker) + { + float x2 = other.data.elements [i++]; + float y2 = other.data.elements [i++]; + transformToApply.transformPoint (x2, y2); - quadraticTo (x, y, x2, y2); - } - else if (type == cubicMarker) - { - float x2 = other.data.elements [i++]; - float y2 = other.data.elements [i++]; - float x3 = other.data.elements [i++]; - float y3 = other.data.elements [i++]; - transformToApply.transformPoint (x2, y2); - transformToApply.transformPoint (x3, y3); + quadraticTo (x, y, x2, y2); + } + else if (type == cubicMarker) + { + float x2 = other.data.elements [i++]; + float y2 = other.data.elements [i++]; + float x3 = other.data.elements [i++]; + float y3 = other.data.elements [i++]; + transformToApply.transformPoint (x2, y2); + transformToApply.transformPoint (x3, y3); - cubicTo (x, y, x2, y2, x3, y3); - } - else - { - // something's gone wrong with the element list! - jassertfalse - } - } - } + cubicTo (x, y, x2, y2, x3, y3); + } + else + { + // something's gone wrong with the element list! + jassertfalse + } + } + } } void Path::applyTransform (const AffineTransform& transform) throw() { - int i = 0; - pathYMin = pathXMin = 0; - pathYMax = pathXMax = 0; - bool setMaxMin = false; + int i = 0; + pathYMin = pathXMin = 0; + pathYMax = pathXMax = 0; + bool setMaxMin = false; - while (i < numElements) - { - const float type = data.elements [i++]; + while (i < numElements) + { + const float type = data.elements [i++]; - if (type == moveMarker) - { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); + if (type == moveMarker) + { + transform.transformPoint (data.elements [i], + data.elements [i + 1]); - if (setMaxMin) - { - pathXMin = jmin (pathXMin, data.elements [i]); - pathXMax = jmax (pathXMax, data.elements [i]); - pathYMin = jmin (pathYMin, data.elements [i + 1]); - pathYMax = jmax (pathYMax, data.elements [i + 1]); - } - else - { - pathXMin = pathXMax = data.elements [i]; - pathYMin = pathYMax = data.elements [i + 1]; - setMaxMin = true; - } + if (setMaxMin) + { + pathXMin = jmin (pathXMin, data.elements [i]); + pathXMax = jmax (pathXMax, data.elements [i]); + pathYMin = jmin (pathYMin, data.elements [i + 1]); + pathYMax = jmax (pathYMax, data.elements [i + 1]); + } + else + { + pathXMin = pathXMax = data.elements [i]; + pathYMin = pathYMax = data.elements [i + 1]; + setMaxMin = true; + } - i += 2; - } - else if (type == lineMarker) - { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); + i += 2; + } + else if (type == lineMarker) + { + transform.transformPoint (data.elements [i], + data.elements [i + 1]); - pathXMin = jmin (pathXMin, data.elements [i]); - pathXMax = jmax (pathXMax, data.elements [i]); - pathYMin = jmin (pathYMin, data.elements [i + 1]); - pathYMax = jmax (pathYMax, data.elements [i + 1]); + pathXMin = jmin (pathXMin, data.elements [i]); + pathXMax = jmax (pathXMax, data.elements [i]); + pathYMin = jmin (pathYMin, data.elements [i + 1]); + pathYMax = jmax (pathYMax, data.elements [i + 1]); - i += 2; - } - else if (type == quadMarker) - { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); + i += 2; + } + else if (type == quadMarker) + { + transform.transformPoint (data.elements [i], + data.elements [i + 1]); - transform.transformPoint (data.elements [i + 2], - data.elements [i + 3]); + transform.transformPoint (data.elements [i + 2], + data.elements [i + 3]); - pathXMin = jmin (pathXMin, data.elements [i], data.elements [i + 2]); - pathXMax = jmax (pathXMax, data.elements [i], data.elements [i + 2]); - pathYMin = jmin (pathYMin, data.elements [i + 1], data.elements [i + 3]); - pathYMax = jmax (pathYMax, data.elements [i + 1], data.elements [i + 3]); + pathXMin = jmin (pathXMin, data.elements [i], data.elements [i + 2]); + pathXMax = jmax (pathXMax, data.elements [i], data.elements [i + 2]); + pathYMin = jmin (pathYMin, data.elements [i + 1], data.elements [i + 3]); + pathYMax = jmax (pathYMax, data.elements [i + 1], data.elements [i + 3]); - i += 4; - } - else if (type == cubicMarker) - { - transform.transformPoint (data.elements [i], - data.elements [i + 1]); + i += 4; + } + else if (type == cubicMarker) + { + transform.transformPoint (data.elements [i], + data.elements [i + 1]); - transform.transformPoint (data.elements [i + 2], - data.elements [i + 3]); + transform.transformPoint (data.elements [i + 2], + data.elements [i + 3]); - transform.transformPoint (data.elements [i + 4], - data.elements [i + 5]); + transform.transformPoint (data.elements [i + 4], + data.elements [i + 5]); - pathXMin = jmin (pathXMin, data.elements [i], data.elements [i + 2], data.elements [i + 4]); - pathXMax = jmax (pathXMax, data.elements [i], data.elements [i + 2], data.elements [i + 4]); - pathYMin = jmin (pathYMin, data.elements [i + 1], data.elements [i + 3], data.elements [i + 5]); - pathYMax = jmax (pathYMax, data.elements [i + 1], data.elements [i + 3], data.elements [i + 5]); + pathXMin = jmin (pathXMin, data.elements [i], data.elements [i + 2], data.elements [i + 4]); + pathXMax = jmax (pathXMax, data.elements [i], data.elements [i + 2], data.elements [i + 4]); + pathYMin = jmin (pathYMin, data.elements [i + 1], data.elements [i + 3], data.elements [i + 5]); + pathYMax = jmax (pathYMax, data.elements [i + 1], data.elements [i + 3], data.elements [i + 5]); - i += 6; - } - } + i += 6; + } + } } const AffineTransform Path::getTransformToScaleToFit (const float x, const float y, - const float w, const float h, - const bool preserveProportions, - const Justification& justification) const throw() + const float w, const float h, + const bool preserveProportions, + const Justification& justification) const throw() { - float sx, sy, sw, sh; - getBounds (sx, sy, sw, sh); + float sx, sy, sw, sh; + getBounds (sx, sy, sw, sh); - if (preserveProportions) - { - if (w <= 0 || h <= 0 || sw <= 0 || sh <= 0) - return AffineTransform::identity; + if (preserveProportions) + { + if (w <= 0 || h <= 0 || sw <= 0 || sh <= 0) + return AffineTransform::identity; - float newW, newH; - const float srcRatio = sh / sw; + float newW, newH; + const float srcRatio = sh / sw; - if (srcRatio > h / w) - { - newW = h / srcRatio; - newH = h; - } - else - { - newW = w; - newH = w * srcRatio; - } + if (srcRatio > h / w) + { + newW = h / srcRatio; + newH = h; + } + else + { + newW = w; + newH = w * srcRatio; + } - float newXCentre = x; - float newYCentre = y; + float newXCentre = x; + float newYCentre = y; - if (justification.testFlags (Justification::left)) - newXCentre += newW * 0.5f; - else if (justification.testFlags (Justification::right)) - newXCentre += w - newW * 0.5f; - else - newXCentre += w * 0.5f; + if (justification.testFlags (Justification::left)) + newXCentre += newW * 0.5f; + else if (justification.testFlags (Justification::right)) + newXCentre += w - newW * 0.5f; + else + newXCentre += w * 0.5f; - if (justification.testFlags (Justification::top)) - newYCentre += newH * 0.5f; - else if (justification.testFlags (Justification::bottom)) - newYCentre += h - newH * 0.5f; - else - newYCentre += h * 0.5f; + if (justification.testFlags (Justification::top)) + newYCentre += newH * 0.5f; + else if (justification.testFlags (Justification::bottom)) + newYCentre += h - newH * 0.5f; + else + newYCentre += h * 0.5f; - return AffineTransform::translation (sw * -0.5f - sx, sh * -0.5f - sy) - .scaled (newW / sw, newH / sh) - .translated (newXCentre, newYCentre); - } - else - { - return AffineTransform::translation (-sx, -sy) - .scaled (w / sw, h / sh) - .translated (x, y); - } + return AffineTransform::translation (sw * -0.5f - sx, sh * -0.5f - sy) + .scaled (newW / sw, newH / sh) + .translated (newXCentre, newYCentre); + } + else + { + return AffineTransform::translation (-sx, -sy) + .scaled (w / sw, h / sh) + .translated (x, y); + } } bool Path::contains (const float x, const float y, const float tolerence) const throw() { - if (x <= pathXMin || x >= pathXMax - || y <= pathYMin || y >= pathYMax) - return false; + if (x <= pathXMin || x >= pathXMax + || y <= pathYMin || y >= pathYMax) + return false; - PathFlatteningIterator i (*this, AffineTransform::identity, tolerence); + PathFlatteningIterator i (*this, AffineTransform::identity, tolerence); - int positiveCrossings = 0; - int negativeCrossings = 0; + int positiveCrossings = 0; + int negativeCrossings = 0; - while (i.next()) - { - if ((i.y1 <= y && i.y2 > y) - || (i.y2 <= y && i.y1 > y)) - { - const float intersectX = i.x1 + (i.x2 - i.x1) * (y - i.y1) / (i.y2 - i.y1); + while (i.next()) + { + if ((i.y1 <= y && i.y2 > y) + || (i.y2 <= y && i.y1 > y)) + { + const float intersectX = i.x1 + (i.x2 - i.x1) * (y - i.y1) / (i.y2 - i.y1); - if (intersectX <= x) - { - if (i.y1 < i.y2) - ++positiveCrossings; - else - ++negativeCrossings; - } - } - } + if (intersectX <= x) + { + if (i.y1 < i.y2) + ++positiveCrossings; + else + ++negativeCrossings; + } + } + } - return (useNonZeroWinding) ? (negativeCrossings != positiveCrossings) - : ((negativeCrossings + positiveCrossings) & 1) != 0; + return (useNonZeroWinding) ? (negativeCrossings != positiveCrossings) + : ((negativeCrossings + positiveCrossings) & 1) != 0; } bool Path::intersectsLine (const float x1, const float y1, - const float x2, const float y2, - const float tolerence) throw() + const float x2, const float y2, + const float tolerence) throw() { - PathFlatteningIterator i (*this, AffineTransform::identity, tolerence); + PathFlatteningIterator i (*this, AffineTransform::identity, tolerence); - const Line line1 (x1, y1, x2, y2); + const Line line1 (x1, y1, x2, y2); - while (i.next()) - { - const Line line2 (i.x1, i.y1, i.x2, i.y2); + while (i.next()) + { + const Line line2 (i.x1, i.y1, i.x2, i.y2); - float ix, iy; - if (line1.intersects (line2, ix, iy)) - return true; - } + float ix, iy; + if (line1.intersects (line2, ix, iy)) + return true; + } - return false; + return false; } const Path Path::createPathWithRoundedCorners (const float cornerRadius) const throw() { - if (cornerRadius <= 0.01f) - return *this; + if (cornerRadius <= 0.01f) + return *this; - int indexOfPathStart = 0, indexOfPathStartThis = 0; - int n = 0; - bool lastWasLine = false, firstWasLine = false; - Path p; + int indexOfPathStart = 0, indexOfPathStartThis = 0; + int n = 0; + bool lastWasLine = false, firstWasLine = false; + Path p; - while (n < numElements) - { - const float type = data.elements [n++]; + while (n < numElements) + { + const float type = data.elements [n++]; - if (type == moveMarker) - { - indexOfPathStart = p.numElements; - indexOfPathStartThis = n - 1; - const float x = data.elements [n++]; - const float y = data.elements [n++]; - p.startNewSubPath (x, y); - lastWasLine = false; - firstWasLine = (data.elements [n] == lineMarker); - } - else if (type == lineMarker || type == closeSubPathMarker) - { - float startX = 0, startY = 0, joinX = 0, joinY = 0, endX, endY; + if (type == moveMarker) + { + indexOfPathStart = p.numElements; + indexOfPathStartThis = n - 1; + const float x = data.elements [n++]; + const float y = data.elements [n++]; + p.startNewSubPath (x, y); + lastWasLine = false; + firstWasLine = (data.elements [n] == lineMarker); + } + else if (type == lineMarker || type == closeSubPathMarker) + { + float startX = 0, startY = 0, joinX = 0, joinY = 0, endX, endY; - if (type == lineMarker) - { - endX = data.elements [n++]; - endY = data.elements [n++]; + if (type == lineMarker) + { + endX = data.elements [n++]; + endY = data.elements [n++]; - if (n > 8) - { - startX = data.elements [n - 8]; - startY = data.elements [n - 7]; - joinX = data.elements [n - 5]; - joinY = data.elements [n - 4]; - } - } - else - { - endX = data.elements [indexOfPathStartThis + 1]; - endY = data.elements [indexOfPathStartThis + 2]; + if (n > 8) + { + startX = data.elements [n - 8]; + startY = data.elements [n - 7]; + joinX = data.elements [n - 5]; + joinY = data.elements [n - 4]; + } + } + else + { + endX = data.elements [indexOfPathStartThis + 1]; + endY = data.elements [indexOfPathStartThis + 2]; - if (n > 6) - { - startX = data.elements [n - 6]; - startY = data.elements [n - 5]; - joinX = data.elements [n - 3]; - joinY = data.elements [n - 2]; - } - } + if (n > 6) + { + startX = data.elements [n - 6]; + startY = data.elements [n - 5]; + joinX = data.elements [n - 3]; + joinY = data.elements [n - 2]; + } + } - if (lastWasLine) - { - const double len1 = juce_hypot (startX - joinX, - startY - joinY); + if (lastWasLine) + { + const double len1 = juce_hypot (startX - joinX, + startY - joinY); - if (len1 > 0) - { - const double propNeeded = jmin (0.5, cornerRadius / len1); + if (len1 > 0) + { + const double propNeeded = jmin (0.5, cornerRadius / len1); - p.data.elements [p.numElements - 2] = (float) (joinX - (joinX - startX) * propNeeded); - p.data.elements [p.numElements - 1] = (float) (joinY - (joinY - startY) * propNeeded); - } + p.data.elements [p.numElements - 2] = (float) (joinX - (joinX - startX) * propNeeded); + p.data.elements [p.numElements - 1] = (float) (joinY - (joinY - startY) * propNeeded); + } - const double len2 = juce_hypot (endX - joinX, - endY - joinY); + const double len2 = juce_hypot (endX - joinX, + endY - joinY); - if (len2 > 0) - { - const double propNeeded = jmin (0.5, cornerRadius / len2); + if (len2 > 0) + { + const double propNeeded = jmin (0.5, cornerRadius / len2); - p.quadraticTo (joinX, joinY, - (float) (joinX + (endX - joinX) * propNeeded), - (float) (joinY + (endY - joinY) * propNeeded)); - } + p.quadraticTo (joinX, joinY, + (float) (joinX + (endX - joinX) * propNeeded), + (float) (joinY + (endY - joinY) * propNeeded)); + } - p.lineTo (endX, endY); - } - else if (type == lineMarker) - { - p.lineTo (endX, endY); - lastWasLine = true; - } + p.lineTo (endX, endY); + } + else if (type == lineMarker) + { + p.lineTo (endX, endY); + lastWasLine = true; + } - if (type == closeSubPathMarker) - { - if (firstWasLine) - { - startX = data.elements [n - 3]; - startY = data.elements [n - 2]; - joinX = endX; - joinY = endY; - endX = data.elements [indexOfPathStartThis + 4]; - endY = data.elements [indexOfPathStartThis + 5]; + if (type == closeSubPathMarker) + { + if (firstWasLine) + { + startX = data.elements [n - 3]; + startY = data.elements [n - 2]; + joinX = endX; + joinY = endY; + endX = data.elements [indexOfPathStartThis + 4]; + endY = data.elements [indexOfPathStartThis + 5]; - const double len1 = juce_hypot (startX - joinX, - startY - joinY); + const double len1 = juce_hypot (startX - joinX, + startY - joinY); - if (len1 > 0) - { - const double propNeeded = jmin (0.5, cornerRadius / len1); + if (len1 > 0) + { + const double propNeeded = jmin (0.5, cornerRadius / len1); - p.data.elements [p.numElements - 2] = (float) (joinX - (joinX - startX) * propNeeded); - p.data.elements [p.numElements - 1] = (float) (joinY - (joinY - startY) * propNeeded); - } + p.data.elements [p.numElements - 2] = (float) (joinX - (joinX - startX) * propNeeded); + p.data.elements [p.numElements - 1] = (float) (joinY - (joinY - startY) * propNeeded); + } - const double len2 = juce_hypot (endX - joinX, - endY - joinY); + const double len2 = juce_hypot (endX - joinX, + endY - joinY); - if (len2 > 0) - { - const double propNeeded = jmin (0.5, cornerRadius / len2); + if (len2 > 0) + { + const double propNeeded = jmin (0.5, cornerRadius / len2); - endX = (float) (joinX + (endX - joinX) * propNeeded); - endY = (float) (joinY + (endY - joinY) * propNeeded); + endX = (float) (joinX + (endX - joinX) * propNeeded); + endY = (float) (joinY + (endY - joinY) * propNeeded); - p.quadraticTo (joinX, joinY, endX, endY); + p.quadraticTo (joinX, joinY, endX, endY); - p.data.elements [indexOfPathStart + 1] = endX; - p.data.elements [indexOfPathStart + 2] = endY; - } - } + p.data.elements [indexOfPathStart + 1] = endX; + p.data.elements [indexOfPathStart + 2] = endY; + } + } - p.closeSubPath(); - } - } - else if (type == quadMarker) - { - lastWasLine = false; - const float x1 = data.elements [n++]; - const float y1 = data.elements [n++]; - const float x2 = data.elements [n++]; - const float y2 = data.elements [n++]; - p.quadraticTo (x1, y1, x2, y2); - } - else if (type == cubicMarker) - { - lastWasLine = false; - const float x1 = data.elements [n++]; - const float y1 = data.elements [n++]; - const float x2 = data.elements [n++]; - const float y2 = data.elements [n++]; - const float x3 = data.elements [n++]; - const float y3 = data.elements [n++]; - p.cubicTo (x1, y1, x2, y2, x3, y3); - } - } + p.closeSubPath(); + } + } + else if (type == quadMarker) + { + lastWasLine = false; + const float x1 = data.elements [n++]; + const float y1 = data.elements [n++]; + const float x2 = data.elements [n++]; + const float y2 = data.elements [n++]; + p.quadraticTo (x1, y1, x2, y2); + } + else if (type == cubicMarker) + { + lastWasLine = false; + const float x1 = data.elements [n++]; + const float y1 = data.elements [n++]; + const float x2 = data.elements [n++]; + const float y2 = data.elements [n++]; + const float x3 = data.elements [n++]; + const float y3 = data.elements [n++]; + p.cubicTo (x1, y1, x2, y2, x3, y3); + } + } - return p; + return p; } void Path::loadPathFromStream (InputStream& source) { - while (! source.isExhausted()) - { - switch (source.readByte()) - { - case 'm': - { - const float x = source.readFloat(); - const float y = source.readFloat(); - startNewSubPath (x, y); - break; - } + while (! source.isExhausted()) + { + switch (source.readByte()) + { + case 'm': + { + const float x = source.readFloat(); + const float y = source.readFloat(); + startNewSubPath (x, y); + break; + } - case 'l': - { - const float x = source.readFloat(); - const float y = source.readFloat(); - lineTo (x, y); - break; - } + case 'l': + { + const float x = source.readFloat(); + const float y = source.readFloat(); + lineTo (x, y); + break; + } - case 'q': - { - const float x1 = source.readFloat(); - const float y1 = source.readFloat(); - const float x2 = source.readFloat(); - const float y2 = source.readFloat(); - quadraticTo (x1, y1, x2, y2); - break; - } + case 'q': + { + const float x1 = source.readFloat(); + const float y1 = source.readFloat(); + const float x2 = source.readFloat(); + const float y2 = source.readFloat(); + quadraticTo (x1, y1, x2, y2); + break; + } - case 'b': - { - const float x1 = source.readFloat(); - const float y1 = source.readFloat(); - const float x2 = source.readFloat(); - const float y2 = source.readFloat(); - const float x3 = source.readFloat(); - const float y3 = source.readFloat(); - cubicTo (x1, y1, x2, y2, x3, y3); - break; - } + case 'b': + { + const float x1 = source.readFloat(); + const float y1 = source.readFloat(); + const float x2 = source.readFloat(); + const float y2 = source.readFloat(); + const float x3 = source.readFloat(); + const float y3 = source.readFloat(); + cubicTo (x1, y1, x2, y2, x3, y3); + break; + } - case 'c': - closeSubPath(); - break; + case 'c': + closeSubPath(); + break; - case 'n': - useNonZeroWinding = true; - break; + case 'n': + useNonZeroWinding = true; + break; - case 'z': - useNonZeroWinding = false; - break; + case 'z': + useNonZeroWinding = false; + break; - case 'e': - return; // end of path marker + case 'e': + return; // end of path marker - default: - jassertfalse // illegal char in the stream - break; - } - } + default: + jassertfalse // illegal char in the stream + break; + } + } } void Path::loadPathFromData (const unsigned char* const data, - const int numberOfBytes) throw() + const int numberOfBytes) throw() { - MemoryInputStream in ((const char*) data, numberOfBytes, false); - loadPathFromStream (in); + MemoryInputStream in ((const char*) data, numberOfBytes, false); + loadPathFromStream (in); } void Path::writePathToStream (OutputStream& dest) const { - dest.writeByte ((useNonZeroWinding) ? 'n' : 'z'); + dest.writeByte ((useNonZeroWinding) ? 'n' : 'z'); - int i = 0; - while (i < numElements) - { - const float type = data.elements [i++]; + int i = 0; + while (i < numElements) + { + const float type = data.elements [i++]; - if (type == moveMarker) - { - dest.writeByte ('m'); - dest.writeFloat (data.elements [i++]); - dest.writeFloat (data.elements [i++]); - } - else if (type == lineMarker) - { - dest.writeByte ('l'); - dest.writeFloat (data.elements [i++]); - dest.writeFloat (data.elements [i++]); - } - else if (type == quadMarker) - { - dest.writeByte ('q'); - dest.writeFloat (data.elements [i++]); - dest.writeFloat (data.elements [i++]); - dest.writeFloat (data.elements [i++]); - dest.writeFloat (data.elements [i++]); - } - else if (type == cubicMarker) - { - dest.writeByte ('b'); - dest.writeFloat (data.elements [i++]); - dest.writeFloat (data.elements [i++]); - dest.writeFloat (data.elements [i++]); - dest.writeFloat (data.elements [i++]); - dest.writeFloat (data.elements [i++]); - dest.writeFloat (data.elements [i++]); - } - else if (type == closeSubPathMarker) - { - dest.writeByte ('c'); - } - } + if (type == moveMarker) + { + dest.writeByte ('m'); + dest.writeFloat (data.elements [i++]); + dest.writeFloat (data.elements [i++]); + } + else if (type == lineMarker) + { + dest.writeByte ('l'); + dest.writeFloat (data.elements [i++]); + dest.writeFloat (data.elements [i++]); + } + else if (type == quadMarker) + { + dest.writeByte ('q'); + dest.writeFloat (data.elements [i++]); + dest.writeFloat (data.elements [i++]); + dest.writeFloat (data.elements [i++]); + dest.writeFloat (data.elements [i++]); + } + else if (type == cubicMarker) + { + dest.writeByte ('b'); + dest.writeFloat (data.elements [i++]); + dest.writeFloat (data.elements [i++]); + dest.writeFloat (data.elements [i++]); + dest.writeFloat (data.elements [i++]); + dest.writeFloat (data.elements [i++]); + dest.writeFloat (data.elements [i++]); + } + else if (type == closeSubPathMarker) + { + dest.writeByte ('c'); + } + } - dest.writeByte ('e'); // marks the end-of-path + dest.writeByte ('e'); // marks the end-of-path } const String Path::toString() const { - MemoryOutputStream s (2048, 2048); - if (! useNonZeroWinding) - s << "a "; + MemoryOutputStream s (2048, 2048); + if (! useNonZeroWinding) + s << "a "; - int i = 0; - float lastMarker = 0.0f; + int i = 0; + float lastMarker = 0.0f; - while (i < numElements) - { - const float marker = data.elements [i++]; - char markerChar = 0; - int numCoords = 0; + while (i < numElements) + { + const float marker = data.elements [i++]; + char markerChar = 0; + int numCoords = 0; - if (marker == moveMarker) - { - markerChar = 'm'; - numCoords = 2; - } - else if (marker == lineMarker) - { - markerChar = 'l'; - numCoords = 2; - } - else if (marker == quadMarker) - { - markerChar = 'q'; - numCoords = 4; - } - else if (marker == cubicMarker) - { - markerChar = 'c'; - numCoords = 6; - } - else - { - jassert (marker == closeSubPathMarker); - markerChar = 'z'; - } + if (marker == moveMarker) + { + markerChar = 'm'; + numCoords = 2; + } + else if (marker == lineMarker) + { + markerChar = 'l'; + numCoords = 2; + } + else if (marker == quadMarker) + { + markerChar = 'q'; + numCoords = 4; + } + else if (marker == cubicMarker) + { + markerChar = 'c'; + numCoords = 6; + } + else + { + jassert (marker == closeSubPathMarker); + markerChar = 'z'; + } - if (marker != lastMarker) - { - s << markerChar << ' '; - lastMarker = marker; - } + if (marker != lastMarker) + { + s << markerChar << ' '; + lastMarker = marker; + } - while (--numCoords >= 0 && i < numElements) - { - String n (data.elements [i++], 3); + while (--numCoords >= 0 && i < numElements) + { + String n (data.elements [i++], 3); - if (n.endsWithChar (T('0'))) - { - do - { - n = n.dropLastCharacters (1); - } while (n.endsWithChar (T('0'))); + if (n.endsWithChar (T('0'))) + { + do + { + n = n.dropLastCharacters (1); + } while (n.endsWithChar (T('0'))); - if (n.endsWithChar (T('.'))) - n = n.dropLastCharacters (1); - } + if (n.endsWithChar (T('.'))) + n = n.dropLastCharacters (1); + } - s << n << ' '; - } - } + s << n << ' '; + } + } - const char* const result = (const char*) s.getData(); - int len = s.getDataSize(); + const char* const result = (const char*) s.getData(); + size_t len = s.getDataSize(); - while (len > 0 && CharacterFunctions::isWhitespace (result [len - 1])) - --len; + while (len > 0 && CharacterFunctions::isWhitespace (result [len - 1])) + --len; - return String (result, len); + return String (result, len); } static const String nextToken (const tchar*& t) { - while (CharacterFunctions::isWhitespace (*t)) - ++t; + while (CharacterFunctions::isWhitespace (*t)) + ++t; - const tchar* const start = t; + const tchar* const start = t; - while (*t != 0 && ! CharacterFunctions::isWhitespace (*t)) - ++t; + while (*t != 0 && ! CharacterFunctions::isWhitespace (*t)) + ++t; - const int length = (int) (t - start); + const int length = (int) (t - start); - while (CharacterFunctions::isWhitespace (*t)) - ++t; + while (CharacterFunctions::isWhitespace (*t)) + ++t; - return String (start, length); + return String (start, length); } void Path::restoreFromString (const String& stringVersion) { - clear(); - setUsingNonZeroWinding (true); + clear(); + setUsingNonZeroWinding (true); - const tchar* t = stringVersion; - tchar marker = T('m'); - int numValues = 2; - float values [6]; + const tchar* t = stringVersion; + tchar marker = T('m'); + int numValues = 2; + float values [6]; - while (*t != 0) - { - const String token (nextToken (t)); - const tchar firstChar = token[0]; - int startNum = 0; + while (*t != 0) + { + const String token (nextToken (t)); + const tchar firstChar = token[0]; + int startNum = 0; - if (firstChar == T('m') || firstChar == T('l')) - { - marker = firstChar; - numValues = 2; - } - else if (firstChar == T('q')) - { - marker = firstChar; - numValues = 4; - } - else if (firstChar == T('c')) - { - marker = firstChar; - numValues = 6; - } - else if (firstChar == T('z')) - { - marker = firstChar; - numValues = 0; - } - else if (firstChar == T('a')) - { - setUsingNonZeroWinding (false); - continue; - } - else - { - ++startNum; - values [0] = token.getFloatValue(); - } + if (firstChar == T('m') || firstChar == T('l')) + { + marker = firstChar; + numValues = 2; + } + else if (firstChar == T('q')) + { + marker = firstChar; + numValues = 4; + } + else if (firstChar == T('c')) + { + marker = firstChar; + numValues = 6; + } + else if (firstChar == T('z')) + { + marker = firstChar; + numValues = 0; + } + else if (firstChar == T('a')) + { + setUsingNonZeroWinding (false); + continue; + } + else + { + ++startNum; + values [0] = token.getFloatValue(); + } - for (int i = startNum; i < numValues; ++i) - values [i] = nextToken (t).getFloatValue(); + for (int i = startNum; i < numValues; ++i) + values [i] = nextToken (t).getFloatValue(); - switch (marker) - { - case T('m'): - startNewSubPath (values[0], values[1]); - break; + switch (marker) + { + case T('m'): + startNewSubPath (values[0], values[1]); + break; - case T('l'): - lineTo (values[0], values[1]); - break; + case T('l'): + lineTo (values[0], values[1]); + break; - case T('q'): - quadraticTo (values[0], values[1], - values[2], values[3]); - break; + case T('q'): + quadraticTo (values[0], values[1], + values[2], values[3]); + break; - case T('c'): - cubicTo (values[0], values[1], - values[2], values[3], - values[4], values[5]); - break; + case T('c'): + cubicTo (values[0], values[1], + values[2], values[3], + values[4], values[5]); + break; - case T('z'): - closeSubPath(); - break; + case T('z'): + closeSubPath(); + break; - default: - jassertfalse // illegal string format? - break; - } - } + default: + jassertfalse // illegal string format? + break; + } + } } Path::Iterator::Iterator (const Path& path_) - : path (path_), - index (0) + : path (path_), + index (0) { } @@ -89791,51 +89578,51 @@ Path::Iterator::~Iterator() bool Path::Iterator::next() { - const float* const elements = path.data.elements; + const float* const elements = path.data.elements; - if (index < path.numElements) - { - const float type = elements [index++]; + if (index < path.numElements) + { + const float type = elements [index++]; - if (type == moveMarker) - { - elementType = startNewSubPath; - x1 = elements [index++]; - y1 = elements [index++]; - } - else if (type == lineMarker) - { - elementType = lineTo; - x1 = elements [index++]; - y1 = elements [index++]; - } - else if (type == quadMarker) - { - elementType = quadraticTo; - x1 = elements [index++]; - y1 = elements [index++]; - x2 = elements [index++]; - y2 = elements [index++]; - } - else if (type == cubicMarker) - { - elementType = cubicTo; - x1 = elements [index++]; - y1 = elements [index++]; - x2 = elements [index++]; - y2 = elements [index++]; - x3 = elements [index++]; - y3 = elements [index++]; - } - else if (type == closeSubPathMarker) - { - elementType = closePath; - } + if (type == moveMarker) + { + elementType = startNewSubPath; + x1 = elements [index++]; + y1 = elements [index++]; + } + else if (type == lineMarker) + { + elementType = lineTo; + x1 = elements [index++]; + y1 = elements [index++]; + } + else if (type == quadMarker) + { + elementType = quadraticTo; + x1 = elements [index++]; + y1 = elements [index++]; + x2 = elements [index++]; + y2 = elements [index++]; + } + else if (type == cubicMarker) + { + elementType = cubicTo; + x1 = elements [index++]; + y1 = elements [index++]; + x2 = elements [index++]; + y2 = elements [index++]; + x3 = elements [index++]; + y3 = elements [index++]; + } + else if (type == closeSubPathMarker) + { + elementType = closePath; + } - return true; - } + return true; + } - return false; + return false; } END_JUCE_NAMESPACE @@ -89850,24 +89637,24 @@ BEGIN_JUCE_NAMESPACE #endif PathFlatteningIterator::PathFlatteningIterator (const Path& path_, - const AffineTransform& transform_, - float tolerence_) throw() - : x2 (0), - y2 (0), - closesSubPath (false), - subPathIndex (-1), - path (path_), - transform (transform_), - points (path_.data.elements), - tolerence (tolerence_ * tolerence_), - subPathCloseX (0), - subPathCloseY (0), - stackBase (32), - index (0), - stackSize (32) + const AffineTransform& transform_, + float tolerence_) throw() + : x2 (0), + y2 (0), + closesSubPath (false), + subPathIndex (-1), + path (path_), + transform (transform_), + points (path_.data.elements), + tolerence (tolerence_ * tolerence_), + subPathCloseX (0), + subPathCloseY (0), + stackBase (32), + index (0), + stackSize (32) { - isIdentityTransform = transform.isIdentity(); - stackPos = stackBase; + isIdentityTransform = transform.isIdentity(); + stackPos = stackBase; } PathFlatteningIterator::~PathFlatteningIterator() throw() @@ -89876,230 +89663,230 @@ PathFlatteningIterator::~PathFlatteningIterator() throw() bool PathFlatteningIterator::next() throw() { - x1 = x2; - y1 = y2; + x1 = x2; + y1 = y2; - float x3 = 0; - float y3 = 0; - float x4 = 0; - float y4 = 0; - float type; + float x3 = 0; + float y3 = 0; + float x4 = 0; + float y4 = 0; + float type; - for (;;) - { - if (stackPos == stackBase) - { - if (index >= path.numElements) - { - return false; - } - else - { - type = points [index++]; + for (;;) + { + if (stackPos == stackBase) + { + if (index >= path.numElements) + { + return false; + } + else + { + type = points [index++]; - if (type != Path::closeSubPathMarker) - { - x2 = points [index++]; - y2 = points [index++]; + if (type != Path::closeSubPathMarker) + { + x2 = points [index++]; + y2 = points [index++]; - if (! isIdentityTransform) - transform.transformPoint (x2, y2); + if (! isIdentityTransform) + transform.transformPoint (x2, y2); - if (type == Path::quadMarker) - { - x3 = points [index++]; - y3 = points [index++]; + if (type == Path::quadMarker) + { + x3 = points [index++]; + y3 = points [index++]; - if (! isIdentityTransform) - transform.transformPoint (x3, y3); - } - else if (type == Path::cubicMarker) - { - x3 = points [index++]; - y3 = points [index++]; - x4 = points [index++]; - y4 = points [index++]; + if (! isIdentityTransform) + transform.transformPoint (x3, y3); + } + else if (type == Path::cubicMarker) + { + x3 = points [index++]; + y3 = points [index++]; + x4 = points [index++]; + y4 = points [index++]; - if (! isIdentityTransform) - { - transform.transformPoint (x3, y3); - transform.transformPoint (x4, y4); - } - } - } - } - } - else - { - type = *--stackPos; + if (! isIdentityTransform) + { + transform.transformPoint (x3, y3); + transform.transformPoint (x4, y4); + } + } + } + } + } + else + { + type = *--stackPos; - if (type != Path::closeSubPathMarker) - { - x2 = *--stackPos; - y2 = *--stackPos; + if (type != Path::closeSubPathMarker) + { + x2 = *--stackPos; + y2 = *--stackPos; - if (type == Path::quadMarker) - { - x3 = *--stackPos; - y3 = *--stackPos; - } - else if (type == Path::cubicMarker) - { - x3 = *--stackPos; - y3 = *--stackPos; - x4 = *--stackPos; - y4 = *--stackPos; - } - } - } + if (type == Path::quadMarker) + { + x3 = *--stackPos; + y3 = *--stackPos; + } + else if (type == Path::cubicMarker) + { + x3 = *--stackPos; + y3 = *--stackPos; + x4 = *--stackPos; + y4 = *--stackPos; + } + } + } - if (type == Path::lineMarker) - { - ++subPathIndex; + if (type == Path::lineMarker) + { + ++subPathIndex; - closesSubPath = (stackPos == stackBase) - && (index < path.numElements) - && (points [index] == Path::closeSubPathMarker) - && x2 == subPathCloseX - && y2 == subPathCloseY; + closesSubPath = (stackPos == stackBase) + && (index < path.numElements) + && (points [index] == Path::closeSubPathMarker) + && x2 == subPathCloseX + && y2 == subPathCloseY; - return true; - } - else if (type == Path::quadMarker) - { - const int offset = (int) (stackPos - stackBase); + return true; + } + else if (type == Path::quadMarker) + { + const int offset = (int) (stackPos - stackBase); - if (offset >= stackSize - 10) - { - stackSize <<= 1; - stackBase.realloc (stackSize); - stackPos = stackBase + offset; - } + if (offset >= stackSize - 10) + { + stackSize <<= 1; + stackBase.realloc (stackSize); + stackPos = stackBase + offset; + } - const float dx1 = x1 - x2; - const float dy1 = y1 - y2; - const float dx2 = x2 - x3; - const float dy2 = y2 - y3; + const float dx1 = x1 - x2; + const float dy1 = y1 - y2; + const float dx2 = x2 - x3; + const float dy2 = y2 - y3; - const float m1x = (x1 + x2) * 0.5f; - const float m1y = (y1 + y2) * 0.5f; - const float m2x = (x2 + x3) * 0.5f; - const float m2y = (y2 + y3) * 0.5f; - const float m3x = (m1x + m2x) * 0.5f; - const float m3y = (m1y + m2y) * 0.5f; + const float m1x = (x1 + x2) * 0.5f; + const float m1y = (y1 + y2) * 0.5f; + const float m2x = (x2 + x3) * 0.5f; + const float m2y = (y2 + y3) * 0.5f; + const float m3x = (m1x + m2x) * 0.5f; + const float m3y = (m1y + m2y) * 0.5f; - if (dx1*dx1 + dy1*dy1 + dx2*dx2 + dy2*dy2 > tolerence) - { - *stackPos++ = y3; - *stackPos++ = x3; - *stackPos++ = m2y; - *stackPos++ = m2x; - *stackPos++ = Path::quadMarker; + if (dx1*dx1 + dy1*dy1 + dx2*dx2 + dy2*dy2 > tolerence) + { + *stackPos++ = y3; + *stackPos++ = x3; + *stackPos++ = m2y; + *stackPos++ = m2x; + *stackPos++ = Path::quadMarker; - *stackPos++ = m3y; - *stackPos++ = m3x; - *stackPos++ = m1y; - *stackPos++ = m1x; - *stackPos++ = Path::quadMarker; - } - else - { - *stackPos++ = y3; - *stackPos++ = x3; - *stackPos++ = Path::lineMarker; + *stackPos++ = m3y; + *stackPos++ = m3x; + *stackPos++ = m1y; + *stackPos++ = m1x; + *stackPos++ = Path::quadMarker; + } + else + { + *stackPos++ = y3; + *stackPos++ = x3; + *stackPos++ = Path::lineMarker; - *stackPos++ = m3y; - *stackPos++ = m3x; - *stackPos++ = Path::lineMarker; - } + *stackPos++ = m3y; + *stackPos++ = m3x; + *stackPos++ = Path::lineMarker; + } - jassert (stackPos < stackBase + stackSize); - } - else if (type == Path::cubicMarker) - { - const int offset = (int) (stackPos - stackBase); + jassert (stackPos < stackBase + stackSize); + } + else if (type == Path::cubicMarker) + { + const int offset = (int) (stackPos - stackBase); - if (offset >= stackSize - 16) - { - stackSize <<= 1; - stackBase.realloc (stackSize); - stackPos = stackBase + offset; - } + if (offset >= stackSize - 16) + { + stackSize <<= 1; + stackBase.realloc (stackSize); + stackPos = stackBase + offset; + } - const float dx1 = x1 - x2; - const float dy1 = y1 - y2; - const float dx2 = x2 - x3; - const float dy2 = y2 - y3; - const float dx3 = x3 - x4; - const float dy3 = y3 - y4; + const float dx1 = x1 - x2; + const float dy1 = y1 - y2; + const float dx2 = x2 - x3; + const float dy2 = y2 - y3; + const float dx3 = x3 - x4; + const float dy3 = y3 - y4; - const float m1x = (x1 + x2) * 0.5f; - const float m1y = (y1 + y2) * 0.5f; - const float m2x = (x3 + x2) * 0.5f; - const float m2y = (y3 + y2) * 0.5f; - const float m3x = (x3 + x4) * 0.5f; - const float m3y = (y3 + y4) * 0.5f; - const float m4x = (m1x + m2x) * 0.5f; - const float m4y = (m1y + m2y) * 0.5f; - const float m5x = (m3x + m2x) * 0.5f; - const float m5y = (m3y + m2y) * 0.5f; + const float m1x = (x1 + x2) * 0.5f; + const float m1y = (y1 + y2) * 0.5f; + const float m2x = (x3 + x2) * 0.5f; + const float m2y = (y3 + y2) * 0.5f; + const float m3x = (x3 + x4) * 0.5f; + const float m3y = (y3 + y4) * 0.5f; + const float m4x = (m1x + m2x) * 0.5f; + const float m4y = (m1y + m2y) * 0.5f; + const float m5x = (m3x + m2x) * 0.5f; + const float m5y = (m3y + m2y) * 0.5f; - if (dx1*dx1 + dy1*dy1 + dx2*dx2 - + dy2*dy2 + dx3*dx3 + dy3*dy3 > tolerence) - { - *stackPos++ = y4; - *stackPos++ = x4; - *stackPos++ = m3y; - *stackPos++ = m3x; - *stackPos++ = m5y; - *stackPos++ = m5x; - *stackPos++ = Path::cubicMarker; + if (dx1*dx1 + dy1*dy1 + dx2*dx2 + + dy2*dy2 + dx3*dx3 + dy3*dy3 > tolerence) + { + *stackPos++ = y4; + *stackPos++ = x4; + *stackPos++ = m3y; + *stackPos++ = m3x; + *stackPos++ = m5y; + *stackPos++ = m5x; + *stackPos++ = Path::cubicMarker; - *stackPos++ = (m4y + m5y) * 0.5f; - *stackPos++ = (m4x + m5x) * 0.5f; - *stackPos++ = m4y; - *stackPos++ = m4x; - *stackPos++ = m1y; - *stackPos++ = m1x; - *stackPos++ = Path::cubicMarker; - } - else - { - *stackPos++ = y4; - *stackPos++ = x4; - *stackPos++ = Path::lineMarker; + *stackPos++ = (m4y + m5y) * 0.5f; + *stackPos++ = (m4x + m5x) * 0.5f; + *stackPos++ = m4y; + *stackPos++ = m4x; + *stackPos++ = m1y; + *stackPos++ = m1x; + *stackPos++ = Path::cubicMarker; + } + else + { + *stackPos++ = y4; + *stackPos++ = x4; + *stackPos++ = Path::lineMarker; - *stackPos++ = m5y; - *stackPos++ = m5x; - *stackPos++ = Path::lineMarker; + *stackPos++ = m5y; + *stackPos++ = m5x; + *stackPos++ = Path::lineMarker; - *stackPos++ = m4y; - *stackPos++ = m4x; - *stackPos++ = Path::lineMarker; - } - } - else if (type == Path::closeSubPathMarker) - { - if (x2 != subPathCloseX || y2 != subPathCloseY) - { - x1 = x2; - y1 = y2; - x2 = subPathCloseX; - y2 = subPathCloseY; - closesSubPath = true; + *stackPos++ = m4y; + *stackPos++ = m4x; + *stackPos++ = Path::lineMarker; + } + } + else if (type == Path::closeSubPathMarker) + { + if (x2 != subPathCloseX || y2 != subPathCloseY) + { + x1 = x2; + y1 = y2; + x2 = subPathCloseX; + y2 = subPathCloseY; + closesSubPath = true; - return true; - } - } - else - { - jassert (type == Path::moveMarker); + return true; + } + } + else + { + jassert (type == Path::moveMarker); - subPathIndex = -1; - subPathCloseX = x1 = x2; - subPathCloseY = y1 = y2; - } - } + subPathIndex = -1; + subPathCloseX = x1 = x2; + subPathCloseY = y1 = y2; + } + } } END_JUCE_NAMESPACE @@ -90110,27 +89897,27 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE PathStrokeType::PathStrokeType (const float strokeThickness, - const JointStyle jointStyle_, - const EndCapStyle endStyle_) throw() - : thickness (strokeThickness), - jointStyle (jointStyle_), - endStyle (endStyle_) + const JointStyle jointStyle_, + const EndCapStyle endStyle_) throw() + : thickness (strokeThickness), + jointStyle (jointStyle_), + endStyle (endStyle_) { } PathStrokeType::PathStrokeType (const PathStrokeType& other) throw() - : thickness (other.thickness), - jointStyle (other.jointStyle), - endStyle (other.endStyle) + : thickness (other.thickness), + jointStyle (other.jointStyle), + endStyle (other.endStyle) { } const PathStrokeType& PathStrokeType::operator= (const PathStrokeType& other) throw() { - thickness = other.thickness; - jointStyle = other.jointStyle; - endStyle = other.endStyle; - return *this; + thickness = other.thickness; + jointStyle = other.jointStyle; + endStyle = other.endStyle; + return *this; } PathStrokeType::~PathStrokeType() throw() @@ -90139,577 +89926,577 @@ PathStrokeType::~PathStrokeType() throw() bool PathStrokeType::operator== (const PathStrokeType& other) const throw() { - return thickness == other.thickness - && jointStyle == other.jointStyle - && endStyle == other.endStyle; + return thickness == other.thickness + && jointStyle == other.jointStyle + && endStyle == other.endStyle; } bool PathStrokeType::operator!= (const PathStrokeType& other) const throw() { - return ! operator== (other); + return ! operator== (other); } static bool lineIntersection (const float x1, const float y1, - const float x2, const float y2, - const float x3, const float y3, - const float x4, const float y4, - float& intersectionX, - float& intersectionY, - float& distanceBeyondLine1EndSquared) throw() + const float x2, const float y2, + const float x3, const float y3, + const float x4, const float y4, + float& intersectionX, + float& intersectionY, + float& distanceBeyondLine1EndSquared) throw() { - if (x2 != x3 || y2 != y3) - { - const float dx1 = x2 - x1; - const float dy1 = y2 - y1; - const float dx2 = x4 - x3; - const float dy2 = y4 - y3; - const float divisor = dx1 * dy2 - dx2 * dy1; + if (x2 != x3 || y2 != y3) + { + const float dx1 = x2 - x1; + const float dy1 = y2 - y1; + const float dx2 = x4 - x3; + const float dy2 = y4 - y3; + const float divisor = dx1 * dy2 - dx2 * dy1; - if (divisor == 0) - { - if (! ((dx1 == 0 && dy1 == 0) || (dx2 == 0 && dy2 == 0))) - { - if (dy1 == 0 && dy2 != 0) - { - const float along = (y1 - y3) / dy2; - intersectionX = x3 + along * dx2; - intersectionY = y1; + if (divisor == 0) + { + if (! ((dx1 == 0 && dy1 == 0) || (dx2 == 0 && dy2 == 0))) + { + if (dy1 == 0 && dy2 != 0) + { + const float along = (y1 - y3) / dy2; + intersectionX = x3 + along * dx2; + intersectionY = y1; - distanceBeyondLine1EndSquared = intersectionX - x2; - distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; - if ((x2 > x1) == (intersectionX < x2)) - distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; + distanceBeyondLine1EndSquared = intersectionX - x2; + distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; + if ((x2 > x1) == (intersectionX < x2)) + distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; - return along >= 0 && along <= 1.0f; - } - else if (dy2 == 0 && dy1 != 0) - { - const float along = (y3 - y1) / dy1; - intersectionX = x1 + along * dx1; - intersectionY = y3; + return along >= 0 && along <= 1.0f; + } + else if (dy2 == 0 && dy1 != 0) + { + const float along = (y3 - y1) / dy1; + intersectionX = x1 + along * dx1; + intersectionY = y3; - distanceBeyondLine1EndSquared = (along - 1.0f) * dx1; - distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; - if (along < 1.0f) - distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; + distanceBeyondLine1EndSquared = (along - 1.0f) * dx1; + distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; + if (along < 1.0f) + distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; - return along >= 0 && along <= 1.0f; - } - else if (dx1 == 0 && dx2 != 0) - { - const float along = (x1 - x3) / dx2; - intersectionX = x1; - intersectionY = y3 + along * dy2; + return along >= 0 && along <= 1.0f; + } + else if (dx1 == 0 && dx2 != 0) + { + const float along = (x1 - x3) / dx2; + intersectionX = x1; + intersectionY = y3 + along * dy2; - distanceBeyondLine1EndSquared = intersectionY - y2; - distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; + distanceBeyondLine1EndSquared = intersectionY - y2; + distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; - if ((y2 > y1) == (intersectionY < y2)) - distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; + if ((y2 > y1) == (intersectionY < y2)) + distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; - return along >= 0 && along <= 1.0f; - } - else if (dx2 == 0 && dx1 != 0) - { - const float along = (x3 - x1) / dx1; - intersectionX = x3; - intersectionY = y1 + along * dy1; + return along >= 0 && along <= 1.0f; + } + else if (dx2 == 0 && dx1 != 0) + { + const float along = (x3 - x1) / dx1; + intersectionX = x3; + intersectionY = y1 + along * dy1; - distanceBeyondLine1EndSquared = (along - 1.0f) * dy1; - distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; - if (along < 1.0f) - distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; + distanceBeyondLine1EndSquared = (along - 1.0f) * dy1; + distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; + if (along < 1.0f) + distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; - return along >= 0 && along <= 1.0f; - } - } + return along >= 0 && along <= 1.0f; + } + } - intersectionX = 0.5f * (x2 + x3); - intersectionY = 0.5f * (y2 + y3); + intersectionX = 0.5f * (x2 + x3); + intersectionY = 0.5f * (y2 + y3); - distanceBeyondLine1EndSquared = 0.0f; - return false; - } - else - { - const float along1 = ((y1 - y3) * dx2 - (x1 - x3) * dy2) / divisor; + distanceBeyondLine1EndSquared = 0.0f; + return false; + } + else + { + const float along1 = ((y1 - y3) * dx2 - (x1 - x3) * dy2) / divisor; - intersectionX = x1 + along1 * dx1; - intersectionY = y1 + along1 * dy1; + intersectionX = x1 + along1 * dx1; + intersectionY = y1 + along1 * dy1; - if (along1 >= 0 && along1 <= 1.0f) - { - const float along2 = ((y1 - y3) * dx1 - (x1 - x3) * dy1); + if (along1 >= 0 && along1 <= 1.0f) + { + const float along2 = ((y1 - y3) * dx1 - (x1 - x3) * dy1); - if (along2 >= 0 && along2 <= divisor) - { - distanceBeyondLine1EndSquared = 0.0f; - return true; - } - } + if (along2 >= 0 && along2 <= divisor) + { + distanceBeyondLine1EndSquared = 0.0f; + return true; + } + } - distanceBeyondLine1EndSquared = along1 - 1.0f; - distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; - distanceBeyondLine1EndSquared *= (dx1 * dx1 + dy1 * dy1); + distanceBeyondLine1EndSquared = along1 - 1.0f; + distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; + distanceBeyondLine1EndSquared *= (dx1 * dx1 + dy1 * dy1); - if (along1 < 1.0f) - distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; + if (along1 < 1.0f) + distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; - return false; - } - } + return false; + } + } - intersectionX = x2; - intersectionY = y2; + intersectionX = x2; + intersectionY = y2; - distanceBeyondLine1EndSquared = 0.0f; - return true; + distanceBeyondLine1EndSquared = 0.0f; + return true; } // part of stroke drawing stuff static void addEdgeAndJoint (Path& destPath, - const PathStrokeType::JointStyle style, - const float maxMiterExtensionSquared, const float width, - const float x1, const float y1, - const float x2, const float y2, - const float x3, const float y3, - const float x4, const float y4, - const float midX, const float midY) throw() + const PathStrokeType::JointStyle style, + const float maxMiterExtensionSquared, const float width, + const float x1, const float y1, + const float x2, const float y2, + const float x3, const float y3, + const float x4, const float y4, + const float midX, const float midY) throw() { - if (style == PathStrokeType::beveled - || (x3 == x4 && y3 == y4) - || (x1 == x2 && y1 == y2)) - { - destPath.lineTo (x2, y2); - destPath.lineTo (x3, y3); - } - else - { - float jx, jy, distanceBeyondLine1EndSquared; + if (style == PathStrokeType::beveled + || (x3 == x4 && y3 == y4) + || (x1 == x2 && y1 == y2)) + { + destPath.lineTo (x2, y2); + destPath.lineTo (x3, y3); + } + else + { + float jx, jy, distanceBeyondLine1EndSquared; - // if they intersect, use this point.. - if (lineIntersection (x1, y1, x2, y2, - x3, y3, x4, y4, - jx, jy, distanceBeyondLine1EndSquared)) - { - destPath.lineTo (jx, jy); - } - else - { - if (style == PathStrokeType::mitered) - { - if (distanceBeyondLine1EndSquared < maxMiterExtensionSquared - && distanceBeyondLine1EndSquared > 0.0f) - { - destPath.lineTo (jx, jy); - } - else - { - // the end sticks out too far, so just use a blunt joint - destPath.lineTo (x2, y2); - destPath.lineTo (x3, y3); - } - } - else - { - // curved joints - float angle1 = atan2f (x2 - midX, y2 - midY); - float angle2 = atan2f (x3 - midX, y3 - midY); - const float angleIncrement = 0.1f; + // if they intersect, use this point.. + if (lineIntersection (x1, y1, x2, y2, + x3, y3, x4, y4, + jx, jy, distanceBeyondLine1EndSquared)) + { + destPath.lineTo (jx, jy); + } + else + { + if (style == PathStrokeType::mitered) + { + if (distanceBeyondLine1EndSquared < maxMiterExtensionSquared + && distanceBeyondLine1EndSquared > 0.0f) + { + destPath.lineTo (jx, jy); + } + else + { + // the end sticks out too far, so just use a blunt joint + destPath.lineTo (x2, y2); + destPath.lineTo (x3, y3); + } + } + else + { + // curved joints + float angle1 = atan2f (x2 - midX, y2 - midY); + float angle2 = atan2f (x3 - midX, y3 - midY); + const float angleIncrement = 0.1f; - destPath.lineTo (x2, y2); + destPath.lineTo (x2, y2); - if (fabs (angle1 - angle2) > angleIncrement) - { - if (angle2 > angle1 + float_Pi - || (angle2 < angle1 && angle2 >= angle1 - float_Pi)) - { - if (angle2 > angle1) - angle2 -= float_Pi * 2.0f; + if (fabs (angle1 - angle2) > angleIncrement) + { + if (angle2 > angle1 + float_Pi + || (angle2 < angle1 && angle2 >= angle1 - float_Pi)) + { + if (angle2 > angle1) + angle2 -= float_Pi * 2.0f; - jassert (angle1 <= angle2 + float_Pi); + jassert (angle1 <= angle2 + float_Pi); - angle1 -= angleIncrement; - while (angle1 > angle2) - { - destPath.lineTo (midX + width * sinf (angle1), - midY + width * cosf (angle1)); + angle1 -= angleIncrement; + while (angle1 > angle2) + { + destPath.lineTo (midX + width * sinf (angle1), + midY + width * cosf (angle1)); - angle1 -= angleIncrement; - } - } - else - { - if (angle1 > angle2) - angle1 -= float_Pi * 2.0f; + angle1 -= angleIncrement; + } + } + else + { + if (angle1 > angle2) + angle1 -= float_Pi * 2.0f; - jassert (angle1 >= angle2 - float_Pi); + jassert (angle1 >= angle2 - float_Pi); - angle1 += angleIncrement; - while (angle1 < angle2) - { - destPath.lineTo (midX + width * sinf (angle1), - midY + width * cosf (angle1)); + angle1 += angleIncrement; + while (angle1 < angle2) + { + destPath.lineTo (midX + width * sinf (angle1), + midY + width * cosf (angle1)); - angle1 += angleIncrement; - } - } - } + angle1 += angleIncrement; + } + } + } - destPath.lineTo (x3, y3); - } - } - } + destPath.lineTo (x3, y3); + } + } + } } static inline void addLineEnd (Path& destPath, - const PathStrokeType::EndCapStyle style, - const float x1, const float y1, - const float x2, const float y2, - const float width) throw() + const PathStrokeType::EndCapStyle style, + const float x1, const float y1, + const float x2, const float y2, + const float width) throw() { - if (style == PathStrokeType::butt) - { - destPath.lineTo (x2, y2); - } - else - { - float offx1, offy1, offx2, offy2; + if (style == PathStrokeType::butt) + { + destPath.lineTo (x2, y2); + } + else + { + float offx1, offy1, offx2, offy2; - float dx = x2 - x1; - float dy = y2 - y1; - const float len = juce_hypotf (dx, dy); + float dx = x2 - x1; + float dy = y2 - y1; + const float len = juce_hypotf (dx, dy); - if (len == 0) - { - offx1 = offx2 = x1; - offy1 = offy2 = y1; - } - else - { - const float offset = width / len; - dx *= offset; - dy *= offset; + if (len == 0) + { + offx1 = offx2 = x1; + offy1 = offy2 = y1; + } + else + { + const float offset = width / len; + dx *= offset; + dy *= offset; - offx1 = x1 + dy; - offy1 = y1 - dx; - offx2 = x2 + dy; - offy2 = y2 - dx; - } + offx1 = x1 + dy; + offy1 = y1 - dx; + offx2 = x2 + dy; + offy2 = y2 - dx; + } - if (style == PathStrokeType::square) - { - // sqaure ends - destPath.lineTo (offx1, offy1); - destPath.lineTo (offx2, offy2); - destPath.lineTo (x2, y2); - } - else - { - // rounded ends - const float midx = (offx1 + offx2) * 0.5f; - const float midy = (offy1 + offy2) * 0.5f; + if (style == PathStrokeType::square) + { + // sqaure ends + destPath.lineTo (offx1, offy1); + destPath.lineTo (offx2, offy2); + destPath.lineTo (x2, y2); + } + else + { + // rounded ends + const float midx = (offx1 + offx2) * 0.5f; + const float midy = (offy1 + offy2) * 0.5f; - destPath.cubicTo (x1 + (offx1 - x1) * 0.55f, y1 + (offy1 - y1) * 0.55f, - offx1 + (midx - offx1) * 0.45f, offy1 + (midy - offy1) * 0.45f, - midx, midy); + destPath.cubicTo (x1 + (offx1 - x1) * 0.55f, y1 + (offy1 - y1) * 0.55f, + offx1 + (midx - offx1) * 0.45f, offy1 + (midy - offy1) * 0.45f, + midx, midy); - destPath.cubicTo (midx + (offx2 - midx) * 0.55f, midy + (offy2 - midy) * 0.55f, - offx2 + (x2 - offx2) * 0.45f, offy2 + (y2 - offy2) * 0.45f, - x2, y2); - } - } + destPath.cubicTo (midx + (offx2 - midx) * 0.55f, midy + (offy2 - midy) * 0.55f, + offx2 + (x2 - offx2) * 0.45f, offy2 + (y2 - offy2) * 0.45f, + x2, y2); + } + } } struct LineSection { - LineSection() {} - LineSection (int) {} + LineSection() {} + LineSection (int) {} - float x1, y1, x2, y2; // original line - float lx1, ly1, lx2, ly2; // the left-hand stroke - float rx1, ry1, rx2, ry2; // the right-hand stroke + float x1, y1, x2, y2; // original line + float lx1, ly1, lx2, ly2; // the left-hand stroke + float rx1, ry1, rx2, ry2; // the right-hand stroke }; static void addSubPath (Path& destPath, const Array & subPath, - const bool isClosed, - const float width, const float maxMiterExtensionSquared, - const PathStrokeType::JointStyle jointStyle, const PathStrokeType::EndCapStyle endStyle) throw() + const bool isClosed, + const float width, const float maxMiterExtensionSquared, + const PathStrokeType::JointStyle jointStyle, const PathStrokeType::EndCapStyle endStyle) throw() { - jassert (subPath.size() > 0); + jassert (subPath.size() > 0); - const LineSection& firstLine = subPath.getReference (0); + const LineSection& firstLine = subPath.getReference (0); - float lastX1 = firstLine.lx1; - float lastY1 = firstLine.ly1; - float lastX2 = firstLine.lx2; - float lastY2 = firstLine.ly2; + float lastX1 = firstLine.lx1; + float lastY1 = firstLine.ly1; + float lastX2 = firstLine.lx2; + float lastY2 = firstLine.ly2; - if (isClosed) - { - destPath.startNewSubPath (lastX1, lastY1); - } - else - { - destPath.startNewSubPath (firstLine.rx2, firstLine.ry2); + if (isClosed) + { + destPath.startNewSubPath (lastX1, lastY1); + } + else + { + destPath.startNewSubPath (firstLine.rx2, firstLine.ry2); - addLineEnd (destPath, endStyle, - firstLine.rx2, firstLine.ry2, - lastX1, lastY1, - width); - } + addLineEnd (destPath, endStyle, + firstLine.rx2, firstLine.ry2, + lastX1, lastY1, + width); + } - int i; - for (i = 1; i < subPath.size(); ++i) - { - const LineSection& l = subPath.getReference (i); + int i; + for (i = 1; i < subPath.size(); ++i) + { + const LineSection& l = subPath.getReference (i); - addEdgeAndJoint (destPath, jointStyle, - maxMiterExtensionSquared, width, - lastX1, lastY1, lastX2, lastY2, - l.lx1, l.ly1, l.lx2, l.ly2, - l.x1, l.y1); + addEdgeAndJoint (destPath, jointStyle, + maxMiterExtensionSquared, width, + lastX1, lastY1, lastX2, lastY2, + l.lx1, l.ly1, l.lx2, l.ly2, + l.x1, l.y1); - lastX1 = l.lx1; - lastY1 = l.ly1; - lastX2 = l.lx2; - lastY2 = l.ly2; - } + lastX1 = l.lx1; + lastY1 = l.ly1; + lastX2 = l.lx2; + lastY2 = l.ly2; + } - const LineSection& lastLine = subPath.getReference (subPath.size() - 1); + const LineSection& lastLine = subPath.getReference (subPath.size() - 1); - if (isClosed) - { - const LineSection& l = subPath.getReference (0); + if (isClosed) + { + const LineSection& l = subPath.getReference (0); - addEdgeAndJoint (destPath, jointStyle, - maxMiterExtensionSquared, width, - lastX1, lastY1, lastX2, lastY2, - l.lx1, l.ly1, l.lx2, l.ly2, - l.x1, l.y1); + addEdgeAndJoint (destPath, jointStyle, + maxMiterExtensionSquared, width, + lastX1, lastY1, lastX2, lastY2, + l.lx1, l.ly1, l.lx2, l.ly2, + l.x1, l.y1); - destPath.closeSubPath(); - destPath.startNewSubPath (lastLine.rx1, lastLine.ry1); - } - else - { - destPath.lineTo (lastX2, lastY2); + destPath.closeSubPath(); + destPath.startNewSubPath (lastLine.rx1, lastLine.ry1); + } + else + { + destPath.lineTo (lastX2, lastY2); - addLineEnd (destPath, endStyle, - lastX2, lastY2, - lastLine.rx1, lastLine.ry1, - width); - } + addLineEnd (destPath, endStyle, + lastX2, lastY2, + lastLine.rx1, lastLine.ry1, + width); + } - lastX1 = lastLine.rx1; - lastY1 = lastLine.ry1; - lastX2 = lastLine.rx2; - lastY2 = lastLine.ry2; + lastX1 = lastLine.rx1; + lastY1 = lastLine.ry1; + lastX2 = lastLine.rx2; + lastY2 = lastLine.ry2; - for (i = subPath.size() - 1; --i >= 0;) - { - const LineSection& l = subPath.getReference (i); + for (i = subPath.size() - 1; --i >= 0;) + { + const LineSection& l = subPath.getReference (i); - addEdgeAndJoint (destPath, jointStyle, - maxMiterExtensionSquared, width, - lastX1, lastY1, lastX2, lastY2, - l.rx1, l.ry1, l.rx2, l.ry2, - l.x2, l.y2); + addEdgeAndJoint (destPath, jointStyle, + maxMiterExtensionSquared, width, + lastX1, lastY1, lastX2, lastY2, + l.rx1, l.ry1, l.rx2, l.ry2, + l.x2, l.y2); - lastX1 = l.rx1; - lastY1 = l.ry1; - lastX2 = l.rx2; - lastY2 = l.ry2; - } + lastX1 = l.rx1; + lastY1 = l.ry1; + lastX2 = l.rx2; + lastY2 = l.ry2; + } - if (isClosed) - { - addEdgeAndJoint (destPath, jointStyle, - maxMiterExtensionSquared, width, - lastX1, lastY1, lastX2, lastY2, - lastLine.rx1, lastLine.ry1, lastLine.rx2, lastLine.ry2, - lastLine.x2, lastLine.y2); - } - else - { - // do the last line - destPath.lineTo (lastX2, lastY2); - } + if (isClosed) + { + addEdgeAndJoint (destPath, jointStyle, + maxMiterExtensionSquared, width, + lastX1, lastY1, lastX2, lastY2, + lastLine.rx1, lastLine.ry1, lastLine.rx2, lastLine.ry2, + lastLine.x2, lastLine.y2); + } + else + { + // do the last line + destPath.lineTo (lastX2, lastY2); + } - destPath.closeSubPath(); + destPath.closeSubPath(); } void PathStrokeType::createStrokedPath (Path& destPath, - const Path& source, - const AffineTransform& transform, - const float extraAccuracy) const throw() + const Path& source, + const AffineTransform& transform, + const float extraAccuracy) const throw() { - if (thickness <= 0) - { - destPath.clear(); - return; - } + if (thickness <= 0) + { + destPath.clear(); + return; + } - const Path* sourcePath = &source; - Path temp; + const Path* sourcePath = &source; + Path temp; - if (sourcePath == &destPath) - { - destPath.swapWithPath (temp); - sourcePath = &temp; - } - else - { - destPath.clear(); - } + if (sourcePath == &destPath) + { + destPath.swapWithPath (temp); + sourcePath = &temp; + } + else + { + destPath.clear(); + } - destPath.setUsingNonZeroWinding (true); + destPath.setUsingNonZeroWinding (true); - const float maxMiterExtensionSquared = 9.0f * thickness * thickness; - const float width = 0.5f * thickness; + const float maxMiterExtensionSquared = 9.0f * thickness * thickness; + const float width = 0.5f * thickness; - // Iterate the path, creating a list of the - // left/right-hand lines along either side of it... - PathFlatteningIterator it (*sourcePath, transform, 9.0f / extraAccuracy); + // Iterate the path, creating a list of the + // left/right-hand lines along either side of it... + PathFlatteningIterator it (*sourcePath, transform, 9.0f / extraAccuracy); - Array subPath; - LineSection l; - l.x1 = 0; - l.y1 = 0; + Array subPath; + LineSection l; + l.x1 = 0; + l.y1 = 0; - const float minSegmentLength = 2.0f / (extraAccuracy * extraAccuracy); + const float minSegmentLength = 2.0f / (extraAccuracy * extraAccuracy); - while (it.next()) - { - if (it.subPathIndex == 0) - { - if (subPath.size() > 0) - { - addSubPath (destPath, subPath, false, width, maxMiterExtensionSquared, jointStyle, endStyle); - subPath.clearQuick(); - } + while (it.next()) + { + if (it.subPathIndex == 0) + { + if (subPath.size() > 0) + { + addSubPath (destPath, subPath, false, width, maxMiterExtensionSquared, jointStyle, endStyle); + subPath.clearQuick(); + } - l.x1 = it.x1; - l.y1 = it.y1; - } + l.x1 = it.x1; + l.y1 = it.y1; + } - l.x2 = it.x2; - l.y2 = it.y2; + l.x2 = it.x2; + l.y2 = it.y2; - float dx = l.x2 - l.x1; - float dy = l.y2 - l.y1; + float dx = l.x2 - l.x1; + float dy = l.y2 - l.y1; - const float hypotSquared = dx*dx + dy*dy; + const float hypotSquared = dx*dx + dy*dy; - if (it.closesSubPath || hypotSquared > minSegmentLength || it.isLastInSubpath()) - { - const float len = sqrtf (hypotSquared); + if (it.closesSubPath || hypotSquared > minSegmentLength || it.isLastInSubpath()) + { + const float len = sqrtf (hypotSquared); - if (len == 0) - { - l.rx1 = l.rx2 = l.lx1 = l.lx2 = l.x1; - l.ry1 = l.ry2 = l.ly1 = l.ly2 = l.y1; - } - else - { - const float offset = width / len; - dx *= offset; - dy *= offset; + if (len == 0) + { + l.rx1 = l.rx2 = l.lx1 = l.lx2 = l.x1; + l.ry1 = l.ry2 = l.ly1 = l.ly2 = l.y1; + } + else + { + const float offset = width / len; + dx *= offset; + dy *= offset; - l.rx2 = l.x1 - dy; - l.ry2 = l.y1 + dx; - l.lx1 = l.x1 + dy; - l.ly1 = l.y1 - dx; + l.rx2 = l.x1 - dy; + l.ry2 = l.y1 + dx; + l.lx1 = l.x1 + dy; + l.ly1 = l.y1 - dx; - l.lx2 = l.x2 + dy; - l.ly2 = l.y2 - dx; - l.rx1 = l.x2 - dy; - l.ry1 = l.y2 + dx; - } + l.lx2 = l.x2 + dy; + l.ly2 = l.y2 - dx; + l.rx1 = l.x2 - dy; + l.ry1 = l.y2 + dx; + } - subPath.add (l); + subPath.add (l); - if (it.closesSubPath) - { - addSubPath (destPath, subPath, true, width, maxMiterExtensionSquared, jointStyle, endStyle); - subPath.clearQuick(); - } - else - { - l.x1 = it.x2; - l.y1 = it.y2; - } - } - } + if (it.closesSubPath) + { + addSubPath (destPath, subPath, true, width, maxMiterExtensionSquared, jointStyle, endStyle); + subPath.clearQuick(); + } + else + { + l.x1 = it.x2; + l.y1 = it.y2; + } + } + } - if (subPath.size() > 0) - addSubPath (destPath, subPath, false, width, maxMiterExtensionSquared, jointStyle, endStyle); + if (subPath.size() > 0) + addSubPath (destPath, subPath, false, width, maxMiterExtensionSquared, jointStyle, endStyle); } void PathStrokeType::createDashedStroke (Path& destPath, - const Path& sourcePath, - const float* dashLengths, - int numDashLengths, - const AffineTransform& transform, - const float extraAccuracy) const throw() + const Path& sourcePath, + const float* dashLengths, + int numDashLengths, + const AffineTransform& transform, + const float extraAccuracy) const throw() { - if (thickness <= 0) - return; + if (thickness <= 0) + return; - // this should really be an even number.. - jassert ((numDashLengths & 1) == 0); + // this should really be an even number.. + jassert ((numDashLengths & 1) == 0); - Path newDestPath; - PathFlatteningIterator it (sourcePath, transform, 9.0f / extraAccuracy); + Path newDestPath; + PathFlatteningIterator it (sourcePath, transform, 9.0f / extraAccuracy); - bool first = true; - int dashNum = 0; - float pos = 0.0f, lineLen = 0.0f, lineEndPos = 0.0f; - float dx = 0.0f, dy = 0.0f; + bool first = true; + int dashNum = 0; + float pos = 0.0f, lineLen = 0.0f, lineEndPos = 0.0f; + float dx = 0.0f, dy = 0.0f; - for (;;) - { - const bool isSolid = ((dashNum & 1) == 0); - const float dashLen = dashLengths [dashNum++ % numDashLengths]; + for (;;) + { + const bool isSolid = ((dashNum & 1) == 0); + const float dashLen = dashLengths [dashNum++ % numDashLengths]; - jassert (dashLen > 0); // must be a positive increment! - if (dashLen <= 0) - break; + jassert (dashLen > 0); // must be a positive increment! + if (dashLen <= 0) + break; - pos += dashLen; + pos += dashLen; - while (pos > lineEndPos) - { - if (! it.next()) - { - if (isSolid && ! first) - newDestPath.lineTo (it.x2, it.y2); + while (pos > lineEndPos) + { + if (! it.next()) + { + if (isSolid && ! first) + newDestPath.lineTo (it.x2, it.y2); - createStrokedPath (destPath, newDestPath, AffineTransform::identity, extraAccuracy); - return; - } + createStrokedPath (destPath, newDestPath, AffineTransform::identity, extraAccuracy); + return; + } - if (isSolid && ! first) - newDestPath.lineTo (it.x1, it.y1); - else - newDestPath.startNewSubPath (it.x1, it.y1); + if (isSolid && ! first) + newDestPath.lineTo (it.x1, it.y1); + else + newDestPath.startNewSubPath (it.x1, it.y1); - dx = it.x2 - it.x1; - dy = it.y2 - it.y1; - lineLen = juce_hypotf (dx, dy); - lineEndPos += lineLen; - first = it.closesSubPath; - } + dx = it.x2 - it.x1; + dy = it.y2 - it.y1; + lineLen = juce_hypotf (dx, dy); + lineEndPos += lineLen; + first = it.closesSubPath; + } - const float alpha = (pos - (lineEndPos - lineLen)) / lineLen; + const float alpha = (pos - (lineEndPos - lineLen)) / lineLen; - if (isSolid) - newDestPath.lineTo (it.x1 + dx * alpha, - it.y1 + dy * alpha); - else - newDestPath.startNewSubPath (it.x1 + dx * alpha, - it.y1 + dy * alpha); - } + if (isSolid) + newDestPath.lineTo (it.x1 + dx * alpha, + it.y1 + dy * alpha); + else + newDestPath.startNewSubPath (it.x1 + dx * alpha, + it.y1 + dy * alpha); + } } END_JUCE_NAMESPACE @@ -90721,28 +90508,28 @@ BEGIN_JUCE_NAMESPACE Point::Point() throw() : x (0.0f), - y (0.0f) + y (0.0f) { } Point::Point (const Point& other) throw() : x (other.x), - y (other.y) + y (other.y) { } const Point& Point::operator= (const Point& other) throw() { - x = other.x; - y = other.y; + x = other.x; + y = other.y; - return *this; + return *this; } Point::Point (const float x_, - const float y_) throw() + const float y_) throw() : x (x_), - y (y_) + y (y_) { } @@ -90751,15 +90538,15 @@ Point::~Point() throw() } void Point::setXY (const float x_, - const float y_) throw() + const float y_) throw() { - x = x_; - y = y_; + x = x_; + y = y_; } void Point::applyTransform (const AffineTransform& transform) throw() { - transform.transformPoint (x, y); + transform.transformPoint (x, y); } END_JUCE_NAMESPACE @@ -90770,44 +90557,44 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE PositionedRectangle::PositionedRectangle() throw() - : x (0.0), - y (0.0), - w (0.0), - h (0.0), - xMode (anchorAtLeftOrTop | absoluteFromParentTopLeft), - yMode (anchorAtLeftOrTop | absoluteFromParentTopLeft), - wMode (absoluteSize), - hMode (absoluteSize) + : x (0.0), + y (0.0), + w (0.0), + h (0.0), + xMode (anchorAtLeftOrTop | absoluteFromParentTopLeft), + yMode (anchorAtLeftOrTop | absoluteFromParentTopLeft), + wMode (absoluteSize), + hMode (absoluteSize) { } PositionedRectangle::PositionedRectangle (const PositionedRectangle& other) throw() - : x (other.x), - y (other.y), - w (other.w), - h (other.h), - xMode (other.xMode), - yMode (other.yMode), - wMode (other.wMode), - hMode (other.hMode) + : x (other.x), + y (other.y), + w (other.w), + h (other.h), + xMode (other.xMode), + yMode (other.yMode), + wMode (other.wMode), + hMode (other.hMode) { } const PositionedRectangle& PositionedRectangle::operator= (const PositionedRectangle& other) throw() { - if (this != &other) - { - x = other.x; - y = other.y; - w = other.w; - h = other.h; - xMode = other.xMode; - yMode = other.yMode; - wMode = other.wMode; - hMode = other.hMode; - } + if (this != &other) + { + x = other.x; + y = other.y; + w = other.w; + h = other.h; + xMode = other.xMode; + yMode = other.yMode; + wMode = other.wMode; + hMode = other.hMode; + } - return *this; + return *this; } PositionedRectangle::~PositionedRectangle() throw() @@ -90816,311 +90603,311 @@ PositionedRectangle::~PositionedRectangle() throw() const bool PositionedRectangle::operator== (const PositionedRectangle& other) const throw() { - return x == other.x - && y == other.y - && w == other.w - && h == other.h - && xMode == other.xMode - && yMode == other.yMode - && wMode == other.wMode - && hMode == other.hMode; + return x == other.x + && y == other.y + && w == other.w + && h == other.h + && xMode == other.xMode + && yMode == other.yMode + && wMode == other.wMode + && hMode == other.hMode; } const bool PositionedRectangle::operator!= (const PositionedRectangle& other) const throw() { - return ! operator== (other); + return ! operator== (other); } PositionedRectangle::PositionedRectangle (const String& stringVersion) throw() { - StringArray tokens; - tokens.addTokens (stringVersion, false); + StringArray tokens; + tokens.addTokens (stringVersion, false); - decodePosString (tokens [0], xMode, x); - decodePosString (tokens [1], yMode, y); - decodeSizeString (tokens [2], wMode, w); - decodeSizeString (tokens [3], hMode, h); + decodePosString (tokens [0], xMode, x); + decodePosString (tokens [1], yMode, y); + decodeSizeString (tokens [2], wMode, w); + decodeSizeString (tokens [3], hMode, h); } const String PositionedRectangle::toString() const throw() { - String s; - s.preallocateStorage (12); + String s; + s.preallocateStorage (12); - addPosDescription (s, xMode, x); - s << T(' '); - addPosDescription (s, yMode, y); - s << T(' '); - addSizeDescription (s, wMode, w); - s << T(' '); - addSizeDescription (s, hMode, h); + addPosDescription (s, xMode, x); + s << T(' '); + addPosDescription (s, yMode, y); + s << T(' '); + addSizeDescription (s, wMode, w); + s << T(' '); + addSizeDescription (s, hMode, h); - return s; + return s; } const Rectangle PositionedRectangle::getRectangle (const Rectangle& target) const throw() { - jassert (! target.isEmpty()); + jassert (! target.isEmpty()); - double x_, y_, w_, h_; - applyPosAndSize (x_, w_, x, w, xMode, wMode, target.getX(), target.getWidth()); - applyPosAndSize (y_, h_, y, h, yMode, hMode, target.getY(), target.getHeight()); + double x_, y_, w_, h_; + applyPosAndSize (x_, w_, x, w, xMode, wMode, target.getX(), target.getWidth()); + applyPosAndSize (y_, h_, y, h, yMode, hMode, target.getY(), target.getHeight()); - return Rectangle (roundDoubleToInt (x_), roundDoubleToInt (y_), - roundDoubleToInt (w_), roundDoubleToInt (h_)); + return Rectangle (roundToInt (x_), roundToInt (y_), + roundToInt (w_), roundToInt (h_)); } void PositionedRectangle::getRectangleDouble (const Rectangle& target, - double& x_, double& y_, - double& w_, double& h_) const throw() + double& x_, double& y_, + double& w_, double& h_) const throw() { - jassert (! target.isEmpty()); + jassert (! target.isEmpty()); - applyPosAndSize (x_, w_, x, w, xMode, wMode, target.getX(), target.getWidth()); - applyPosAndSize (y_, h_, y, h, yMode, hMode, target.getY(), target.getHeight()); + applyPosAndSize (x_, w_, x, w, xMode, wMode, target.getX(), target.getWidth()); + applyPosAndSize (y_, h_, y, h, yMode, hMode, target.getY(), target.getHeight()); } void PositionedRectangle::applyToComponent (Component& comp) const throw() { - comp.setBounds (getRectangle (Rectangle (0, 0, comp.getParentWidth(), comp.getParentHeight()))); + comp.setBounds (getRectangle (Rectangle (0, 0, comp.getParentWidth(), comp.getParentHeight()))); } void PositionedRectangle::updateFrom (const Rectangle& rectangle, - const Rectangle& target) throw() + const Rectangle& target) throw() { - updatePosAndSize (x, w, rectangle.getX(), rectangle.getWidth(), xMode, wMode, target.getX(), target.getWidth()); - updatePosAndSize (y, h, rectangle.getY(), rectangle.getHeight(), yMode, hMode, target.getY(), target.getHeight()); + updatePosAndSize (x, w, rectangle.getX(), rectangle.getWidth(), xMode, wMode, target.getX(), target.getWidth()); + updatePosAndSize (y, h, rectangle.getY(), rectangle.getHeight(), yMode, hMode, target.getY(), target.getHeight()); } void PositionedRectangle::updateFromDouble (const double newX, const double newY, - const double newW, const double newH, - const Rectangle& target) throw() + const double newW, const double newH, + const Rectangle& target) throw() { - updatePosAndSize (x, w, newX, newW, xMode, wMode, target.getX(), target.getWidth()); - updatePosAndSize (y, h, newY, newH, yMode, hMode, target.getY(), target.getHeight()); + updatePosAndSize (x, w, newX, newW, xMode, wMode, target.getX(), target.getWidth()); + updatePosAndSize (y, h, newY, newH, yMode, hMode, target.getY(), target.getHeight()); } void PositionedRectangle::updateFromComponent (const Component& comp) throw() { - if (comp.getParentComponent() == 0 && ! comp.isOnDesktop()) - updateFrom (comp.getBounds(), Rectangle()); - else - updateFrom (comp.getBounds(), Rectangle (0, 0, comp.getParentWidth(), comp.getParentHeight())); + if (comp.getParentComponent() == 0 && ! comp.isOnDesktop()) + updateFrom (comp.getBounds(), Rectangle()); + else + updateFrom (comp.getBounds(), Rectangle (0, 0, comp.getParentWidth(), comp.getParentHeight())); } PositionedRectangle::AnchorPoint PositionedRectangle::getAnchorPointX() const throw() { - return (AnchorPoint) (xMode & (anchorAtLeftOrTop | anchorAtRightOrBottom | anchorAtCentre)); + return (AnchorPoint) (xMode & (anchorAtLeftOrTop | anchorAtRightOrBottom | anchorAtCentre)); } PositionedRectangle::PositionMode PositionedRectangle::getPositionModeX() const throw() { - return (PositionMode) (xMode & (absoluteFromParentTopLeft - | absoluteFromParentBottomRight - | absoluteFromParentCentre - | proportionOfParentSize)); + return (PositionMode) (xMode & (absoluteFromParentTopLeft + | absoluteFromParentBottomRight + | absoluteFromParentCentre + | proportionOfParentSize)); } PositionedRectangle::AnchorPoint PositionedRectangle::getAnchorPointY() const throw() { - return (AnchorPoint) (yMode & (anchorAtLeftOrTop | anchorAtRightOrBottom | anchorAtCentre)); + return (AnchorPoint) (yMode & (anchorAtLeftOrTop | anchorAtRightOrBottom | anchorAtCentre)); } PositionedRectangle::PositionMode PositionedRectangle::getPositionModeY() const throw() { - return (PositionMode) (yMode & (absoluteFromParentTopLeft - | absoluteFromParentBottomRight - | absoluteFromParentCentre - | proportionOfParentSize)); + return (PositionMode) (yMode & (absoluteFromParentTopLeft + | absoluteFromParentBottomRight + | absoluteFromParentCentre + | proportionOfParentSize)); } PositionedRectangle::SizeMode PositionedRectangle::getWidthMode() const throw() { - return (SizeMode) wMode; + return (SizeMode) wMode; } PositionedRectangle::SizeMode PositionedRectangle::getHeightMode() const throw() { - return (SizeMode) hMode; + return (SizeMode) hMode; } void PositionedRectangle::setModes (const AnchorPoint xAnchor, - const PositionMode xMode_, - const AnchorPoint yAnchor, - const PositionMode yMode_, - const SizeMode widthMode, - const SizeMode heightMode, - const Rectangle& target) throw() + const PositionMode xMode_, + const AnchorPoint yAnchor, + const PositionMode yMode_, + const SizeMode widthMode, + const SizeMode heightMode, + const Rectangle& target) throw() { - if (xMode != (xAnchor | xMode_) || wMode != widthMode) - { - double tx, tw; - applyPosAndSize (tx, tw, x, w, xMode, wMode, target.getX(), target.getWidth()); + if (xMode != (xAnchor | xMode_) || wMode != widthMode) + { + double tx, tw; + applyPosAndSize (tx, tw, x, w, xMode, wMode, target.getX(), target.getWidth()); - xMode = (uint8) (xAnchor | xMode_); - wMode = (uint8) widthMode; + xMode = (uint8) (xAnchor | xMode_); + wMode = (uint8) widthMode; - updatePosAndSize (x, w, tx, tw, xMode, wMode, target.getX(), target.getWidth()); - } + updatePosAndSize (x, w, tx, tw, xMode, wMode, target.getX(), target.getWidth()); + } - if (yMode != (yAnchor | yMode_) || hMode != heightMode) - { - double ty, th; - applyPosAndSize (ty, th, y, h, yMode, hMode, target.getY(), target.getHeight()); + if (yMode != (yAnchor | yMode_) || hMode != heightMode) + { + double ty, th; + applyPosAndSize (ty, th, y, h, yMode, hMode, target.getY(), target.getHeight()); - yMode = (uint8) (yAnchor | yMode_); - hMode = (uint8) heightMode; + yMode = (uint8) (yAnchor | yMode_); + hMode = (uint8) heightMode; - updatePosAndSize (y, h, ty, th, yMode, hMode, target.getY(), target.getHeight()); - } + updatePosAndSize (y, h, ty, th, yMode, hMode, target.getY(), target.getHeight()); + } } bool PositionedRectangle::isPositionAbsolute() const throw() { - return xMode == absoluteFromParentTopLeft - && yMode == absoluteFromParentTopLeft - && wMode == absoluteSize - && hMode == absoluteSize; + return xMode == absoluteFromParentTopLeft + && yMode == absoluteFromParentTopLeft + && wMode == absoluteSize + && hMode == absoluteSize; } void PositionedRectangle::addPosDescription (String& s, const uint8 mode, const double value) const throw() { - if ((mode & proportionOfParentSize) != 0) - { - s << (roundDoubleToInt (value * 100000.0) / 1000.0) << T('%'); - } - else - { - s << (roundDoubleToInt (value * 100.0) / 100.0); + if ((mode & proportionOfParentSize) != 0) + { + s << (roundToInt (value * 100000.0) / 1000.0) << T('%'); + } + else + { + s << (roundToInt (value * 100.0) / 100.0); - if ((mode & absoluteFromParentBottomRight) != 0) - s << T('R'); - else if ((mode & absoluteFromParentCentre) != 0) - s << T('C'); - } + if ((mode & absoluteFromParentBottomRight) != 0) + s << T('R'); + else if ((mode & absoluteFromParentCentre) != 0) + s << T('C'); + } - if ((mode & anchorAtRightOrBottom) != 0) - s << T('r'); - else if ((mode & anchorAtCentre) != 0) - s << T('c'); + if ((mode & anchorAtRightOrBottom) != 0) + s << T('r'); + else if ((mode & anchorAtCentre) != 0) + s << T('c'); } void PositionedRectangle::addSizeDescription (String& s, const uint8 mode, const double value) const throw() { - if (mode == proportionalSize) - s << (roundDoubleToInt (value * 100000.0) / 1000.0) << T('%'); - else if (mode == parentSizeMinusAbsolute) - s << (roundDoubleToInt (value * 100.0) / 100.0) << T('M'); - else - s << (roundDoubleToInt (value * 100.0) / 100.0); + if (mode == proportionalSize) + s << (roundToInt (value * 100000.0) / 1000.0) << T('%'); + else if (mode == parentSizeMinusAbsolute) + s << (roundToInt (value * 100.0) / 100.0) << T('M'); + else + s << (roundToInt (value * 100.0) / 100.0); } void PositionedRectangle::decodePosString (const String& s, uint8& mode, double& value) throw() { - if (s.containsChar (T('r'))) - mode = anchorAtRightOrBottom; - else if (s.containsChar (T('c'))) - mode = anchorAtCentre; - else - mode = anchorAtLeftOrTop; + if (s.containsChar (T('r'))) + mode = anchorAtRightOrBottom; + else if (s.containsChar (T('c'))) + mode = anchorAtCentre; + else + mode = anchorAtLeftOrTop; - if (s.containsChar (T('%'))) - { - mode |= proportionOfParentSize; - value = s.removeCharacters (T("%rcRC")).getDoubleValue() / 100.0; - } - else - { - if (s.containsChar (T('R'))) - mode |= absoluteFromParentBottomRight; - else if (s.containsChar (T('C'))) - mode |= absoluteFromParentCentre; - else - mode |= absoluteFromParentTopLeft; + if (s.containsChar (T('%'))) + { + mode |= proportionOfParentSize; + value = s.removeCharacters (T("%rcRC")).getDoubleValue() / 100.0; + } + else + { + if (s.containsChar (T('R'))) + mode |= absoluteFromParentBottomRight; + else if (s.containsChar (T('C'))) + mode |= absoluteFromParentCentre; + else + mode |= absoluteFromParentTopLeft; - value = s.removeCharacters (T("rcRC")).getDoubleValue(); - } + value = s.removeCharacters (T("rcRC")).getDoubleValue(); + } } void PositionedRectangle::decodeSizeString (const String& s, uint8& mode, double& value) throw() { - if (s.containsChar (T('%'))) - { - mode = proportionalSize; - value = s.upToFirstOccurrenceOf (T("%"), false, false).getDoubleValue() / 100.0; - } - else if (s.containsChar (T('M'))) - { - mode = parentSizeMinusAbsolute; - value = s.getDoubleValue(); - } - else - { - mode = absoluteSize; - value = s.getDoubleValue(); - } + if (s.containsChar (T('%'))) + { + mode = proportionalSize; + value = s.upToFirstOccurrenceOf (T("%"), false, false).getDoubleValue() / 100.0; + } + else if (s.containsChar (T('M'))) + { + mode = parentSizeMinusAbsolute; + value = s.getDoubleValue(); + } + else + { + mode = absoluteSize; + value = s.getDoubleValue(); + } } void PositionedRectangle::applyPosAndSize (double& xOut, double& wOut, - const double x_, const double w_, - const uint8 xMode_, const uint8 wMode_, - const int parentPos, - const int parentSize) const throw() + const double x_, const double w_, + const uint8 xMode_, const uint8 wMode_, + const int parentPos, + const int parentSize) const throw() { - if (wMode_ == proportionalSize) - wOut = roundDoubleToInt (w_ * parentSize); - else if (wMode_ == parentSizeMinusAbsolute) - wOut = jmax (0, parentSize - roundDoubleToInt (w_)); - else - wOut = roundDoubleToInt (w_); + if (wMode_ == proportionalSize) + wOut = roundToInt (w_ * parentSize); + else if (wMode_ == parentSizeMinusAbsolute) + wOut = jmax (0, parentSize - roundToInt (w_)); + else + wOut = roundToInt (w_); - if ((xMode_ & proportionOfParentSize) != 0) - xOut = parentPos + x_ * parentSize; - else if ((xMode_ & absoluteFromParentBottomRight) != 0) - xOut = (parentPos + parentSize) - x_; - else if ((xMode_ & absoluteFromParentCentre) != 0) - xOut = x_ + (parentPos + parentSize / 2); - else - xOut = x_ + parentPos; + if ((xMode_ & proportionOfParentSize) != 0) + xOut = parentPos + x_ * parentSize; + else if ((xMode_ & absoluteFromParentBottomRight) != 0) + xOut = (parentPos + parentSize) - x_; + else if ((xMode_ & absoluteFromParentCentre) != 0) + xOut = x_ + (parentPos + parentSize / 2); + else + xOut = x_ + parentPos; - if ((xMode_ & anchorAtRightOrBottom) != 0) - xOut -= wOut; - else if ((xMode_ & anchorAtCentre) != 0) - xOut -= wOut / 2; + if ((xMode_ & anchorAtRightOrBottom) != 0) + xOut -= wOut; + else if ((xMode_ & anchorAtCentre) != 0) + xOut -= wOut / 2; } void PositionedRectangle::updatePosAndSize (double& xOut, double& wOut, - double x_, const double w_, - const uint8 xMode_, const uint8 wMode_, - const int parentPos, - const int parentSize) const throw() + double x_, const double w_, + const uint8 xMode_, const uint8 wMode_, + const int parentPos, + const int parentSize) const throw() { - if (wMode_ == proportionalSize) - { - if (parentSize > 0) - wOut = w_ / parentSize; - } - else if (wMode_ == parentSizeMinusAbsolute) - wOut = parentSize - w_; - else - wOut = w_; + if (wMode_ == proportionalSize) + { + if (parentSize > 0) + wOut = w_ / parentSize; + } + else if (wMode_ == parentSizeMinusAbsolute) + wOut = parentSize - w_; + else + wOut = w_; - if ((xMode_ & anchorAtRightOrBottom) != 0) - x_ += w_; - else if ((xMode_ & anchorAtCentre) != 0) - x_ += w_ / 2; + if ((xMode_ & anchorAtRightOrBottom) != 0) + x_ += w_; + else if ((xMode_ & anchorAtCentre) != 0) + x_ += w_ / 2; - if ((xMode_ & proportionOfParentSize) != 0) - { - if (parentSize > 0) - xOut = (x_ - parentPos) / parentSize; - } - else if ((xMode_ & absoluteFromParentBottomRight) != 0) - xOut = (parentPos + parentSize) - x_; - else if ((xMode_ & absoluteFromParentCentre) != 0) - xOut = x_ - (parentPos + parentSize / 2); - else - xOut = x_ - parentPos; + if ((xMode_ & proportionOfParentSize) != 0) + { + if (parentSize > 0) + xOut = (x_ - parentPos) / parentSize; + } + else if ((xMode_ & absoluteFromParentBottomRight) != 0) + xOut = (parentPos + parentSize) - x_; + else if ((xMode_ & absoluteFromParentCentre) != 0) + xOut = x_ - (parentPos + parentSize / 2); + else + xOut = x_ - parentPos; } END_JUCE_NAMESPACE @@ -91132,34 +90919,34 @@ BEGIN_JUCE_NAMESPACE Rectangle::Rectangle() throw() : x (0), - y (0), - w (0), - h (0) + y (0), + w (0), + h (0) { } Rectangle::Rectangle (const int x_, const int y_, - const int w_, const int h_) throw() + const int w_, const int h_) throw() : x (x_), - y (y_), - w (w_), - h (h_) + y (y_), + w (w_), + h (h_) { } Rectangle::Rectangle (const int w_, const int h_) throw() : x (0), - y (0), - w (w_), - h (h_) + y (0), + w (w_), + h (h_) { } Rectangle::Rectangle (const Rectangle& other) throw() : x (other.x), - y (other.y), - w (other.w), - h (other.h) + y (other.y), + w (other.w), + h (other.h) { } @@ -91169,317 +90956,317 @@ Rectangle::~Rectangle() throw() bool Rectangle::isEmpty() const throw() { - return w <= 0 || h <= 0; + return w <= 0 || h <= 0; } void Rectangle::setBounds (const int x_, - const int y_, - const int w_, - const int h_) throw() + const int y_, + const int w_, + const int h_) throw() { - x = x_; - y = y_; - w = w_; - h = h_; + x = x_; + y = y_; + w = w_; + h = h_; } void Rectangle::setPosition (const int x_, - const int y_) throw() + const int y_) throw() { - x = x_; - y = y_; + x = x_; + y = y_; } void Rectangle::setSize (const int w_, - const int h_) throw() + const int h_) throw() { - w = w_; - h = h_; + w = w_; + h = h_; } void Rectangle::setWidth (const int newWidth) throw() { - w = newWidth; + w = newWidth; } void Rectangle::setHeight (const int newHeight) throw() { - h = newHeight; + h = newHeight; } void Rectangle::setLeft (const int newLeft) throw() { - w = jmax (0, x + w - newLeft); - x = newLeft; + w = jmax (0, x + w - newLeft); + x = newLeft; } void Rectangle::setTop (const int newTop) throw() { - h = jmax (0, y + h - newTop); - y = newTop; + h = jmax (0, y + h - newTop); + y = newTop; } void Rectangle::setRight (const int newRight) throw() { - x = jmin (x, newRight); - w = newRight - x; + x = jmin (x, newRight); + w = newRight - x; } void Rectangle::setBottom (const int newBottom) throw() { - y = jmin (y, newBottom); - h = newBottom - y; + y = jmin (y, newBottom); + h = newBottom - y; } void Rectangle::translate (const int dx, - const int dy) throw() + const int dy) throw() { - x += dx; - y += dy; + x += dx; + y += dy; } const Rectangle Rectangle::translated (const int dx, - const int dy) const throw() + const int dy) const throw() { - return Rectangle (x + dx, y + dy, w, h); + return Rectangle (x + dx, y + dy, w, h); } void Rectangle::expand (const int deltaX, - const int deltaY) throw() + const int deltaY) throw() { - const int nw = jmax (0, w + deltaX + deltaX); - const int nh = jmax (0, h + deltaY + deltaY); + const int nw = jmax (0, w + deltaX + deltaX); + const int nh = jmax (0, h + deltaY + deltaY); - setBounds (x - deltaX, - y - deltaY, - nw, nh); + setBounds (x - deltaX, + y - deltaY, + nw, nh); } const Rectangle Rectangle::expanded (const int deltaX, - const int deltaY) const throw() + const int deltaY) const throw() { - const int nw = jmax (0, w + deltaX + deltaX); - const int nh = jmax (0, h + deltaY + deltaY); + const int nw = jmax (0, w + deltaX + deltaX); + const int nh = jmax (0, h + deltaY + deltaY); - return Rectangle (x - deltaX, - y - deltaY, - nw, nh); + return Rectangle (x - deltaX, + y - deltaY, + nw, nh); } void Rectangle::reduce (const int deltaX, - const int deltaY) throw() + const int deltaY) throw() { - expand (-deltaX, -deltaY); + expand (-deltaX, -deltaY); } const Rectangle Rectangle::reduced (const int deltaX, - const int deltaY) const throw() + const int deltaY) const throw() { - return expanded (-deltaX, -deltaY); + return expanded (-deltaX, -deltaY); } bool Rectangle::operator== (const Rectangle& other) const throw() { - return x == other.x - && y == other.y - && w == other.w - && h == other.h; + return x == other.x + && y == other.y + && w == other.w + && h == other.h; } bool Rectangle::operator!= (const Rectangle& other) const throw() { - return x != other.x - || y != other.y - || w != other.w - || h != other.h; + return x != other.x + || y != other.y + || w != other.w + || h != other.h; } bool Rectangle::contains (const int px, - const int py) const throw() + const int py) const throw() { - return px >= x - && py >= y - && px < x + w - && py < y + h; + return px >= x + && py >= y + && px < x + w + && py < y + h; } bool Rectangle::contains (const Rectangle& other) const throw() { - return x <= other.x - && y <= other.y - && x + w >= other.x + other.w - && y + h >= other.y + other.h; + return x <= other.x + && y <= other.y + && x + w >= other.x + other.w + && y + h >= other.y + other.h; } bool Rectangle::intersects (const Rectangle& other) const throw() { - return x + w > other.x - && y + h > other.y - && x < other.x + other.w - && y < other.y + other.h - && w > 0 - && h > 0; + return x + w > other.x + && y + h > other.y + && x < other.x + other.w + && y < other.y + other.h + && w > 0 + && h > 0; } const Rectangle Rectangle::getIntersection (const Rectangle& other) const throw() { - const int nx = jmax (x, other.x); - const int ny = jmax (y, other.y); - const int nw = jmin (x + w, other.x + other.w) - nx; - const int nh = jmin (y + h, other.y + other.h) - ny; + const int nx = jmax (x, other.x); + const int ny = jmax (y, other.y); + const int nw = jmin (x + w, other.x + other.w) - nx; + const int nh = jmin (y + h, other.y + other.h) - ny; - if (nw >= 0 && nh >= 0) - return Rectangle (nx, ny, nw, nh); - else - return Rectangle(); + if (nw >= 0 && nh >= 0) + return Rectangle (nx, ny, nw, nh); + else + return Rectangle(); } bool Rectangle::intersectRectangle (int& x1, int& y1, int& w1, int& h1) const throw() { - const int maxX = jmax (x1, x); - w1 = jmin (x1 + w1, x + w) - maxX; + const int maxX = jmax (x1, x); + w1 = jmin (x1 + w1, x + w) - maxX; - if (w1 > 0) - { - const int maxY = jmax (y1, y); - h1 = jmin (y1 + h1, y + h) - maxY; + if (w1 > 0) + { + const int maxY = jmax (y1, y); + h1 = jmin (y1 + h1, y + h) - maxY; - if (h1 > 0) - { - x1 = maxX; - y1 = maxY; + if (h1 > 0) + { + x1 = maxX; + y1 = maxY; - return true; - } - } + return true; + } + } - return false; + return false; } bool Rectangle::intersectRectangles (int& x1, int& y1, int& w1, int& h1, - int x2, int y2, int w2, int h2) throw() + int x2, int y2, int w2, int h2) throw() { - const int x = jmax (x1, x2); - w1 = jmin (x1 + w1, x2 + w2) - x; + const int x = jmax (x1, x2); + w1 = jmin (x1 + w1, x2 + w2) - x; - if (w1 > 0) - { - const int y = jmax (y1, y2); - h1 = jmin (y1 + h1, y2 + h2) - y; + if (w1 > 0) + { + const int y = jmax (y1, y2); + h1 = jmin (y1 + h1, y2 + h2) - y; - if (h1 > 0) - { - x1 = x; - y1 = y; + if (h1 > 0) + { + x1 = x; + y1 = y; - return true; - } - } + return true; + } + } - return false; + return false; } const Rectangle Rectangle::getUnion (const Rectangle& other) const throw() { - const int newX = jmin (x, other.x); - const int newY = jmin (y, other.y); + const int newX = jmin (x, other.x); + const int newY = jmin (y, other.y); - return Rectangle (newX, newY, - jmax (x + w, other.x + other.w) - newX, - jmax (y + h, other.y + other.h) - newY); + return Rectangle (newX, newY, + jmax (x + w, other.x + other.w) - newX, + jmax (y + h, other.y + other.h) - newY); } bool Rectangle::enlargeIfAdjacent (const Rectangle& other) throw() { - if (x == other.x && getRight() == other.getRight() - && (other.getBottom() >= y && other.y <= getBottom())) - { - const int newY = jmin (y, other.y); - h = jmax (getBottom(), other.getBottom()) - newY; - y = newY; - return true; - } - else if (y == other.y && getBottom() == other.getBottom() - && (other.getRight() >= x && other.x <= getRight())) - { - const int newX = jmin (x, other.x); - w = jmax (getRight(), other.getRight()) - newX; - x = newX; - return true; - } + if (x == other.x && getRight() == other.getRight() + && (other.getBottom() >= y && other.y <= getBottom())) + { + const int newY = jmin (y, other.y); + h = jmax (getBottom(), other.getBottom()) - newY; + y = newY; + return true; + } + else if (y == other.y && getBottom() == other.getBottom() + && (other.getRight() >= x && other.x <= getRight())) + { + const int newX = jmin (x, other.x); + w = jmax (getRight(), other.getRight()) - newX; + x = newX; + return true; + } - return false; + return false; } bool Rectangle::reduceIfPartlyContainedIn (const Rectangle& other) throw() { - int inside = 0; - const int otherR = other.getRight(); + int inside = 0; + const int otherR = other.getRight(); - if (x >= other.x && x < otherR) - inside = 1; + if (x >= other.x && x < otherR) + inside = 1; - const int otherB = other.getBottom(); + const int otherB = other.getBottom(); - if (y >= other.y && y < otherB) - inside |= 2; + if (y >= other.y && y < otherB) + inside |= 2; - const int r = x + w; + const int r = x + w; - if (r >= other.x && r < otherR) - inside |= 4; + if (r >= other.x && r < otherR) + inside |= 4; - const int b = y + h; + const int b = y + h; - if (b >= other.y && b < otherB) - inside |= 8; + if (b >= other.y && b < otherB) + inside |= 8; - switch (inside) - { - case 1 + 2 + 8: - w = r - otherR; - x = otherR; - return true; + switch (inside) + { + case 1 + 2 + 8: + w = r - otherR; + x = otherR; + return true; - case 1 + 2 + 4: - h = b - otherB; - y = otherB; - return true; + case 1 + 2 + 4: + h = b - otherB; + y = otherB; + return true; - case 2 + 4 + 8: - w = other.x - x; - return true; + case 2 + 4 + 8: + w = other.x - x; + return true; - case 1 + 4 + 8: - h = other.y - y; - return true; - } + case 1 + 4 + 8: + h = other.y - y; + return true; + } - return false; + return false; } const String Rectangle::toString() const throw() { - String s; - s.preallocateStorage (16); + String s; + s.preallocateStorage (16); - s << x << T(' ') - << y << T(' ') - << w << T(' ') - << h; + s << x << T(' ') + << y << T(' ') + << w << T(' ') + << h; - return s; + return s; } const Rectangle Rectangle::fromString (const String& stringVersion) { - StringArray toks; - toks.addTokens (stringVersion.trim(), T(",; \t\r\n"), 0); + StringArray toks; + toks.addTokens (stringVersion.trim(), T(",; \t\r\n"), 0); - return Rectangle (toks[0].trim().getIntValue(), - toks[1].trim().getIntValue(), - toks[2].trim().getIntValue(), - toks[3].trim().getIntValue()); + return Rectangle (toks[0].trim().getIntValue(), + toks[1].trim().getIntValue(), + toks[2].trim().getIntValue(), + toks[3].trim().getIntValue()); } END_JUCE_NAMESPACE @@ -91495,21 +91282,21 @@ RectangleList::RectangleList() throw() RectangleList::RectangleList (const Rectangle& rect) throw() { - if (! rect.isEmpty()) - rects.add (rect); + if (! rect.isEmpty()) + rects.add (rect); } RectangleList::RectangleList (const RectangleList& other) throw() - : rects (other.rects) + : rects (other.rects) { } const RectangleList& RectangleList::operator= (const RectangleList& other) throw() { - if (this != &other) - rects = other.rects; + if (this != &other) + rects = other.rects; - return *this; + return *this; } RectangleList::~RectangleList() throw() @@ -91518,26 +91305,26 @@ RectangleList::~RectangleList() throw() void RectangleList::clear() throw() { - rects.clearQuick(); + rects.clearQuick(); } const Rectangle RectangleList::getRectangle (const int index) const throw() { - if (((unsigned int) index) < (unsigned int) rects.size()) - return rects.getReference (index); + if (((unsigned int) index) < (unsigned int) rects.size()) + return rects.getReference (index); - return Rectangle(); + return Rectangle(); } bool RectangleList::isEmpty() const throw() { - return rects.size() == 0; + return rects.size() == 0; } RectangleList::Iterator::Iterator (const RectangleList& list) throw() - : current (0), - owner (list), - index (list.rects.size()) + : current (0), + owner (list), + index (list.rects.size()) { } @@ -91547,436 +91334,436 @@ RectangleList::Iterator::~Iterator() throw() bool RectangleList::Iterator::next() throw() { - if (--index >= 0) - { - current = & (owner.rects.getReference (index)); - return true; - } + if (--index >= 0) + { + current = & (owner.rects.getReference (index)); + return true; + } - return false; + return false; } void RectangleList::add (const Rectangle& rect) throw() { - if (! rect.isEmpty()) - { - if (rects.size() == 0) - { - rects.add (rect); - } - else - { - bool anyOverlaps = false; + if (! rect.isEmpty()) + { + if (rects.size() == 0) + { + rects.add (rect); + } + else + { + bool anyOverlaps = false; - int i; - for (i = rects.size(); --i >= 0;) - { - Rectangle& ourRect = rects.getReference (i); + int i; + for (i = rects.size(); --i >= 0;) + { + Rectangle& ourRect = rects.getReference (i); - if (rect.intersects (ourRect)) - { - if (rect.contains (ourRect)) - rects.remove (i); - else if (! ourRect.reduceIfPartlyContainedIn (rect)) - anyOverlaps = true; - } - } + if (rect.intersects (ourRect)) + { + if (rect.contains (ourRect)) + rects.remove (i); + else if (! ourRect.reduceIfPartlyContainedIn (rect)) + anyOverlaps = true; + } + } - if (anyOverlaps && rects.size() > 0) - { - RectangleList r (rect); + if (anyOverlaps && rects.size() > 0) + { + RectangleList r (rect); - for (i = rects.size(); --i >= 0;) - { - const Rectangle& ourRect = rects.getReference (i); + for (i = rects.size(); --i >= 0;) + { + const Rectangle& ourRect = rects.getReference (i); - if (rect.intersects (ourRect)) - { - r.subtract (ourRect); + if (rect.intersects (ourRect)) + { + r.subtract (ourRect); - if (r.rects.size() == 0) - return; - } - } + if (r.rects.size() == 0) + return; + } + } - for (i = r.getNumRectangles(); --i >= 0;) - rects.add (r.rects.getReference (i)); - } - else - { - rects.add (rect); - } - } - } + for (i = r.getNumRectangles(); --i >= 0;) + rects.add (r.rects.getReference (i)); + } + else + { + rects.add (rect); + } + } + } } void RectangleList::addWithoutMerging (const Rectangle& rect) throw() { - rects.add (rect); + rects.add (rect); } void RectangleList::add (const int x, const int y, const int w, const int h) throw() { - if (rects.size() == 0) - { - if (w > 0 && h > 0) - rects.add (Rectangle (x, y, w, h)); - } - else - { - add (Rectangle (x, y, w, h)); - } + if (rects.size() == 0) + { + if (w > 0 && h > 0) + rects.add (Rectangle (x, y, w, h)); + } + else + { + add (Rectangle (x, y, w, h)); + } } void RectangleList::add (const RectangleList& other) throw() { - for (int i = 0; i < other.rects.size(); ++i) - add (other.rects.getReference (i)); + for (int i = 0; i < other.rects.size(); ++i) + add (other.rects.getReference (i)); } void RectangleList::subtract (const Rectangle& rect) throw() { - const int originalNumRects = rects.size(); + const int originalNumRects = rects.size(); - if (originalNumRects > 0) - { - const int x1 = rect.x; - const int y1 = rect.y; - const int x2 = x1 + rect.w; - const int y2 = y1 + rect.h; + if (originalNumRects > 0) + { + const int x1 = rect.x; + const int y1 = rect.y; + const int x2 = x1 + rect.w; + const int y2 = y1 + rect.h; - for (int i = getNumRectangles(); --i >= 0;) - { - Rectangle& r = rects.getReference (i); + for (int i = getNumRectangles(); --i >= 0;) + { + Rectangle& r = rects.getReference (i); - const int rx1 = r.x; - const int ry1 = r.y; - const int rx2 = rx1 + r.w; - const int ry2 = ry1 + r.h; + const int rx1 = r.x; + const int ry1 = r.y; + const int rx2 = rx1 + r.w; + const int ry2 = ry1 + r.h; - if (! (x2 <= rx1 || x1 >= rx2 || y2 <= ry1 || y1 >= ry2)) - { - if (x1 > rx1 && x1 < rx2) - { - if (y1 <= ry1 && y2 >= ry2 && x2 >= rx2) - { - r.w = x1 - rx1; - } - else - { - r.x = x1; - r.w = rx2 - x1; + if (! (x2 <= rx1 || x1 >= rx2 || y2 <= ry1 || y1 >= ry2)) + { + if (x1 > rx1 && x1 < rx2) + { + if (y1 <= ry1 && y2 >= ry2 && x2 >= rx2) + { + r.w = x1 - rx1; + } + else + { + r.x = x1; + r.w = rx2 - x1; - rects.insert (i + 1, Rectangle (rx1, ry1, x1 - rx1, ry2 - ry1)); - i += 2; - } - } - else if (x2 > rx1 && x2 < rx2) - { - r.x = x2; - r.w = rx2 - x2; + rects.insert (i + 1, Rectangle (rx1, ry1, x1 - rx1, ry2 - ry1)); + i += 2; + } + } + else if (x2 > rx1 && x2 < rx2) + { + r.x = x2; + r.w = rx2 - x2; - if (y1 > ry1 || y2 < ry2 || x1 > rx1) - { - rects.insert (i + 1, Rectangle (rx1, ry1, x2 - rx1, ry2 - ry1)); - i += 2; - } - } - else if (y1 > ry1 && y1 < ry2) - { - if (x1 <= rx1 && x2 >= rx2 && y2 >= ry2) - { - r.h = y1 - ry1; - } - else - { - r.y = y1; - r.h = ry2 - y1; + if (y1 > ry1 || y2 < ry2 || x1 > rx1) + { + rects.insert (i + 1, Rectangle (rx1, ry1, x2 - rx1, ry2 - ry1)); + i += 2; + } + } + else if (y1 > ry1 && y1 < ry2) + { + if (x1 <= rx1 && x2 >= rx2 && y2 >= ry2) + { + r.h = y1 - ry1; + } + else + { + r.y = y1; + r.h = ry2 - y1; - rects.insert (i + 1, Rectangle (rx1, ry1, rx2 - rx1, y1 - ry1)); - i += 2; - } - } - else if (y2 > ry1 && y2 < ry2) - { - r.y = y2; - r.h = ry2 - y2; + rects.insert (i + 1, Rectangle (rx1, ry1, rx2 - rx1, y1 - ry1)); + i += 2; + } + } + else if (y2 > ry1 && y2 < ry2) + { + r.y = y2; + r.h = ry2 - y2; - if (x1 > rx1 || x2 < rx2 || y1 > ry1) - { - rects.insert (i + 1, Rectangle (rx1, ry1, rx2 - rx1, y2 - ry1)); - i += 2; - } - } - else - { - rects.remove (i); - } - } - } + if (x1 > rx1 || x2 < rx2 || y1 > ry1) + { + rects.insert (i + 1, Rectangle (rx1, ry1, rx2 - rx1, y2 - ry1)); + i += 2; + } + } + else + { + rects.remove (i); + } + } + } - if (rects.size() > originalNumRects + 10) - consolidate(); - } + if (rects.size() > originalNumRects + 10) + consolidate(); + } } void RectangleList::subtract (const RectangleList& otherList) throw() { - for (int i = otherList.rects.size(); --i >= 0;) - subtract (otherList.rects.getReference (i)); + for (int i = otherList.rects.size(); --i >= 0;) + subtract (otherList.rects.getReference (i)); } bool RectangleList::clipTo (const Rectangle& rect) throw() { - bool notEmpty = false; + bool notEmpty = false; - if (rect.isEmpty()) - { - clear(); - } - else - { - for (int i = rects.size(); --i >= 0;) - { - Rectangle& r = rects.getReference (i); + if (rect.isEmpty()) + { + clear(); + } + else + { + for (int i = rects.size(); --i >= 0;) + { + Rectangle& r = rects.getReference (i); - if (! rect.intersectRectangle (r.x, r.y, r.w, r.h)) - rects.remove (i); - else - notEmpty = true; - } - } + if (! rect.intersectRectangle (r.x, r.y, r.w, r.h)) + rects.remove (i); + else + notEmpty = true; + } + } - return notEmpty; + return notEmpty; } bool RectangleList::clipTo (const RectangleList& other) throw() { - if (rects.size() == 0) - return false; + if (rects.size() == 0) + return false; - RectangleList result; + RectangleList result; - for (int j = 0; j < rects.size(); ++j) - { - const Rectangle& rect = rects.getReference (j); + for (int j = 0; j < rects.size(); ++j) + { + const Rectangle& rect = rects.getReference (j); - for (int i = other.rects.size(); --i >= 0;) - { - Rectangle r (other.rects.getReference (i)); + for (int i = other.rects.size(); --i >= 0;) + { + Rectangle r (other.rects.getReference (i)); - if (rect.intersectRectangle (r.x, r.y, r.w, r.h)) - result.rects.add (r); - } - } + if (rect.intersectRectangle (r.x, r.y, r.w, r.h)) + result.rects.add (r); + } + } - swapWith (result); + swapWith (result); - return ! isEmpty(); + return ! isEmpty(); } bool RectangleList::getIntersectionWith (const Rectangle& rect, RectangleList& destRegion) const throw() { - destRegion.clear(); + destRegion.clear(); - if (! rect.isEmpty()) - { - for (int i = rects.size(); --i >= 0;) - { - Rectangle r (rects.getReference (i)); + if (! rect.isEmpty()) + { + for (int i = rects.size(); --i >= 0;) + { + Rectangle r (rects.getReference (i)); - if (rect.intersectRectangle (r.x, r.y, r.w, r.h)) - destRegion.rects.add (r); - } - } + if (rect.intersectRectangle (r.x, r.y, r.w, r.h)) + destRegion.rects.add (r); + } + } - return destRegion.rects.size() > 0; + return destRegion.rects.size() > 0; } void RectangleList::swapWith (RectangleList& otherList) throw() { - rects.swapWithArray (otherList.rects); + rects.swapWithArray (otherList.rects); } void RectangleList::consolidate() throw() { - int i; - for (i = 0; i < getNumRectangles() - 1; ++i) - { - Rectangle& r = rects.getReference (i); - const int rx1 = r.x; - const int ry1 = r.y; - const int rx2 = rx1 + r.w; - const int ry2 = ry1 + r.h; + int i; + for (i = 0; i < getNumRectangles() - 1; ++i) + { + Rectangle& r = rects.getReference (i); + const int rx1 = r.x; + const int ry1 = r.y; + const int rx2 = rx1 + r.w; + const int ry2 = ry1 + r.h; - for (int j = rects.size(); --j > i;) - { - Rectangle& r2 = rects.getReference (j); - const int jrx1 = r2.x; - const int jry1 = r2.y; - const int jrx2 = jrx1 + r2.w; - const int jry2 = jry1 + r2.h; + for (int j = rects.size(); --j > i;) + { + Rectangle& r2 = rects.getReference (j); + const int jrx1 = r2.x; + const int jry1 = r2.y; + const int jrx2 = jrx1 + r2.w; + const int jry2 = jry1 + r2.h; - // if the vertical edges of any blocks are touching and their horizontals don't - // line up, split them horizontally.. - if (jrx1 == rx2 || jrx2 == rx1) - { - if (jry1 > ry1 && jry1 < ry2) - { - r.h = jry1 - ry1; - rects.add (Rectangle (rx1, jry1, rx2 - rx1, ry2 - jry1)); - i = -1; - break; - } + // if the vertical edges of any blocks are touching and their horizontals don't + // line up, split them horizontally.. + if (jrx1 == rx2 || jrx2 == rx1) + { + if (jry1 > ry1 && jry1 < ry2) + { + r.h = jry1 - ry1; + rects.add (Rectangle (rx1, jry1, rx2 - rx1, ry2 - jry1)); + i = -1; + break; + } - if (jry2 > ry1 && jry2 < ry2) - { - r.h = jry2 - ry1; - rects.add (Rectangle (rx1, jry2, rx2 - rx1, ry2 - jry2)); - i = -1; - break; - } - else if (ry1 > jry1 && ry1 < jry2) - { - r2.h = ry1 - jry1; - rects.add (Rectangle (jrx1, ry1, jrx2 - jrx1, jry2 - ry1)); - i = -1; - break; - } - else if (ry2 > jry1 && ry2 < jry2) - { - r2.h = ry2 - jry1; - rects.add (Rectangle (jrx1, ry2, jrx2 - jrx1, jry2 - ry2)); - i = -1; - break; - } - } - } - } + if (jry2 > ry1 && jry2 < ry2) + { + r.h = jry2 - ry1; + rects.add (Rectangle (rx1, jry2, rx2 - rx1, ry2 - jry2)); + i = -1; + break; + } + else if (ry1 > jry1 && ry1 < jry2) + { + r2.h = ry1 - jry1; + rects.add (Rectangle (jrx1, ry1, jrx2 - jrx1, jry2 - ry1)); + i = -1; + break; + } + else if (ry2 > jry1 && ry2 < jry2) + { + r2.h = ry2 - jry1; + rects.add (Rectangle (jrx1, ry2, jrx2 - jrx1, jry2 - ry2)); + i = -1; + break; + } + } + } + } - for (i = 0; i < rects.size() - 1; ++i) - { - Rectangle& r = rects.getReference (i); + for (i = 0; i < rects.size() - 1; ++i) + { + Rectangle& r = rects.getReference (i); - for (int j = rects.size(); --j > i;) - { - if (r.enlargeIfAdjacent (rects.getReference (j))) - { - rects.remove (j); - i = -1; - break; - } - } - } + for (int j = rects.size(); --j > i;) + { + if (r.enlargeIfAdjacent (rects.getReference (j))) + { + rects.remove (j); + i = -1; + break; + } + } + } } bool RectangleList::containsPoint (const int x, const int y) const throw() { - for (int i = getNumRectangles(); --i >= 0;) - if (rects.getReference (i).contains (x, y)) - return true; + for (int i = getNumRectangles(); --i >= 0;) + if (rects.getReference (i).contains (x, y)) + return true; - return false; + return false; } bool RectangleList::containsRectangle (const Rectangle& rectangleToCheck) const throw() { - if (rects.size() > 1) - { - RectangleList r (rectangleToCheck); + if (rects.size() > 1) + { + RectangleList r (rectangleToCheck); - for (int i = rects.size(); --i >= 0;) - { - r.subtract (rects.getReference (i)); + for (int i = rects.size(); --i >= 0;) + { + r.subtract (rects.getReference (i)); - if (r.rects.size() == 0) - return true; - } - } - else if (rects.size() > 0) - { - return rects.getReference (0).contains (rectangleToCheck); - } + if (r.rects.size() == 0) + return true; + } + } + else if (rects.size() > 0) + { + return rects.getReference (0).contains (rectangleToCheck); + } - return false; + return false; } bool RectangleList::intersectsRectangle (const Rectangle& rectangleToCheck) const throw() { - for (int i = rects.size(); --i >= 0;) - if (rects.getReference (i).intersects (rectangleToCheck)) - return true; + for (int i = rects.size(); --i >= 0;) + if (rects.getReference (i).intersects (rectangleToCheck)) + return true; - return false; + return false; } bool RectangleList::intersects (const RectangleList& other) const throw() { - for (int i = rects.size(); --i >= 0;) - if (other.intersectsRectangle (rects.getReference (i))) - return true; + for (int i = rects.size(); --i >= 0;) + if (other.intersectsRectangle (rects.getReference (i))) + return true; - return false; + return false; } const Rectangle RectangleList::getBounds() const throw() { - if (rects.size() <= 1) - { - if (rects.size() == 0) - return Rectangle(); - else - return rects.getReference (0); - } - else - { - const Rectangle& r = rects.getReference (0); + if (rects.size() <= 1) + { + if (rects.size() == 0) + return Rectangle(); + else + return rects.getReference (0); + } + else + { + const Rectangle& r = rects.getReference (0); - int minX = r.x; - int minY = r.y; - int maxX = minX + r.w; - int maxY = minY + r.h; + int minX = r.x; + int minY = r.y; + int maxX = minX + r.w; + int maxY = minY + r.h; - for (int i = rects.size(); --i > 0;) - { - const Rectangle& r2 = rects.getReference (i); + for (int i = rects.size(); --i > 0;) + { + const Rectangle& r2 = rects.getReference (i); - minX = jmin (minX, r2.x); - minY = jmin (minY, r2.y); - maxX = jmax (maxX, r2.getRight()); - maxY = jmax (maxY, r2.getBottom()); - } + minX = jmin (minX, r2.x); + minY = jmin (minY, r2.y); + maxX = jmax (maxX, r2.getRight()); + maxY = jmax (maxY, r2.getBottom()); + } - return Rectangle (minX, minY, maxX - minX, maxY - minY); - } + return Rectangle (minX, minY, maxX - minX, maxY - minY); + } } void RectangleList::offsetAll (const int dx, const int dy) throw() { - for (int i = rects.size(); --i >= 0;) - { - Rectangle& r = rects.getReference (i); + for (int i = rects.size(); --i >= 0;) + { + Rectangle& r = rects.getReference (i); - r.x += dx; - r.y += dy; - } + r.x += dx; + r.y += dy; + } } const Path RectangleList::toPath() const throw() { - Path p; + Path p; - for (int i = rects.size(); --i >= 0;) - { - const Rectangle& r = rects.getReference (i); + for (int i = rects.size(); --i >= 0;) + { + const Rectangle& r = rects.getReference (i); - p.addRectangle ((float) r.x, - (float) r.y, - (float) r.w, - (float) r.h); - } + p.addRectangle ((float) r.x, + (float) r.y, + (float) r.w, + (float) r.h); + } - return p; + return p; } END_JUCE_NAMESPACE @@ -91989,50 +91776,50 @@ BEGIN_JUCE_NAMESPACE static const int fullAlphaThreshold = 253; Image::Image (const PixelFormat format_, - const int imageWidth_, - const int imageHeight_) + const int imageWidth_, + const int imageHeight_) : format (format_), - imageWidth (imageWidth_), - imageHeight (imageHeight_), - imageData (0) + imageWidth (imageWidth_), + imageHeight (imageHeight_), + imageData (0) { - jassert (format_ == RGB || format_ == ARGB || format_ == SingleChannel); - jassert (imageWidth_ > 0 && imageHeight_ > 0); // it's illegal to create a zero-sized image - the - // actual image will be at least 1x1. + jassert (format_ == RGB || format_ == ARGB || format_ == SingleChannel); + jassert (imageWidth_ > 0 && imageHeight_ > 0); // it's illegal to create a zero-sized image - the + // actual image will be at least 1x1. } Image::Image (const PixelFormat format_, - const int imageWidth_, - const int imageHeight_, - const bool clearImage) + const int imageWidth_, + const int imageHeight_, + const bool clearImage) : format (format_), - imageWidth (imageWidth_), - imageHeight (imageHeight_) + imageWidth (imageWidth_), + imageHeight (imageHeight_) { - jassert (format_ == RGB || format_ == ARGB || format_ == SingleChannel); - jassert (imageWidth_ > 0 && imageHeight_ > 0); // it's illegal to create a zero-sized image - the - // actual image will be at least 1x1. + jassert (format_ == RGB || format_ == ARGB || format_ == SingleChannel); + jassert (imageWidth_ > 0 && imageHeight_ > 0); // it's illegal to create a zero-sized image - the + // actual image will be at least 1x1. - pixelStride = (format == RGB) ? 3 : ((format == ARGB) ? 4 : 1); - lineStride = (pixelStride * jmax (1, imageWidth_) + 3) & ~3; + pixelStride = (format == RGB) ? 3 : ((format == ARGB) ? 4 : 1); + lineStride = (pixelStride * jmax (1, imageWidth_) + 3) & ~3; - imageDataAllocated.allocate (lineStride * jmax (1, imageHeight_), clearImage); - imageData = imageDataAllocated; + imageDataAllocated.allocate (lineStride * jmax (1, imageHeight_), clearImage); + imageData = imageDataAllocated; } Image::Image (const Image& other) : format (other.format), - imageWidth (other.imageWidth), - imageHeight (other.imageHeight) + imageWidth (other.imageWidth), + imageHeight (other.imageHeight) { - pixelStride = (format == RGB) ? 3 : ((format == ARGB) ? 4 : 1); - lineStride = (pixelStride * jmax (1, imageWidth) + 3) & ~3; + pixelStride = (format == RGB) ? 3 : ((format == ARGB) ? 4 : 1); + lineStride = (pixelStride * jmax (1, imageWidth) + 3) & ~3; - imageDataAllocated.malloc (lineStride * jmax (1, imageHeight)); - imageData = imageDataAllocated; + imageDataAllocated.malloc (lineStride * jmax (1, imageHeight)); + imageData = imageDataAllocated; - BitmapData srcData (other, 0, 0, imageWidth, imageHeight); - setPixelData (0, 0, imageWidth, imageHeight, srcData.data, srcData.lineStride); + BitmapData srcData (other, 0, 0, imageWidth, imageHeight); + setPixelData (0, 0, imageWidth, imageHeight, srcData.data, srcData.lineStride); } Image::~Image() @@ -92041,27 +91828,27 @@ Image::~Image() LowLevelGraphicsContext* Image::createLowLevelContext() { - return new LowLevelGraphicsSoftwareRenderer (*this); + return new LowLevelGraphicsSoftwareRenderer (*this); } Image::BitmapData::BitmapData (Image& image, int x, int y, int w, int h, const bool /*makeWritable*/) - : data (image.imageData + image.lineStride * y + image.pixelStride * x), - lineStride (image.lineStride), - pixelStride (image.pixelStride), - width (w), - height (h) + : data (image.imageData + image.lineStride * y + image.pixelStride * x), + lineStride (image.lineStride), + pixelStride (image.pixelStride), + width (w), + height (h) { - jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= image.getWidth() && y + h <= image.getHeight()); + jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= image.getWidth() && y + h <= image.getHeight()); } Image::BitmapData::BitmapData (const Image& image, int x, int y, int w, int h) - : data (image.imageData + image.lineStride * y + image.pixelStride * x), - lineStride (image.lineStride), - pixelStride (image.pixelStride), - width (w), - height (h) + : data (image.imageData + image.lineStride * y + image.pixelStride * x), + lineStride (image.lineStride), + pixelStride (image.pixelStride), + width (w), + height (h) { - jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= image.getWidth() && y + h <= image.getHeight()); + jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= image.getWidth() && y + h <= image.getHeight()); } Image::BitmapData::~BitmapData() @@ -92069,368 +91856,368 @@ Image::BitmapData::~BitmapData() } void Image::setPixelData (int x, int y, int w, int h, - const uint8* sourcePixelData, int sourceLineStride) + const uint8* sourcePixelData, int sourceLineStride) { - jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= imageWidth && y + h <= imageHeight); + jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= imageWidth && y + h <= imageHeight); - if (Rectangle::intersectRectangles (x, y, w, h, 0, 0, imageWidth, imageHeight)) - { - const BitmapData dest (*this, x, y, w, h, true); + if (Rectangle::intersectRectangles (x, y, w, h, 0, 0, imageWidth, imageHeight)) + { + const BitmapData dest (*this, x, y, w, h, true); - for (int i = 0; i < h; ++i) - { - memcpy (dest.getLinePointer(i), - sourcePixelData + sourceLineStride * i, - w * dest.pixelStride); - } - } + for (int i = 0; i < h; ++i) + { + memcpy (dest.getLinePointer(i), + sourcePixelData + sourceLineStride * i, + w * dest.pixelStride); + } + } } void Image::clear (int dx, int dy, int dw, int dh, - const Colour& colourToClearTo) + const Colour& colourToClearTo) { - const PixelARGB col (colourToClearTo.getPixelARGB()); + const PixelARGB col (colourToClearTo.getPixelARGB()); - const BitmapData destData (*this, dx, dy, dw, dh, true); - uint8* dest = destData.data; + const BitmapData destData (*this, dx, dy, dw, dh, true); + uint8* dest = destData.data; - while (--dh >= 0) - { - uint8* line = dest; - dest += destData.lineStride; + while (--dh >= 0) + { + uint8* line = dest; + dest += destData.lineStride; - if (isARGB()) - { - for (int x = dw; --x >= 0;) - { - ((PixelARGB*) line)->set (col); - line += destData.pixelStride; - } - } - else if (isRGB()) - { - for (int x = dw; --x >= 0;) - { - ((PixelRGB*) line)->set (col); - line += destData.pixelStride; - } - } - else - { - for (int x = dw; --x >= 0;) - { - *line = col.getAlpha(); - line += destData.pixelStride; - } - } - } + if (isARGB()) + { + for (int x = dw; --x >= 0;) + { + ((PixelARGB*) line)->set (col); + line += destData.pixelStride; + } + } + else if (isRGB()) + { + for (int x = dw; --x >= 0;) + { + ((PixelRGB*) line)->set (col); + line += destData.pixelStride; + } + } + else + { + for (int x = dw; --x >= 0;) + { + *line = col.getAlpha(); + line += destData.pixelStride; + } + } + } } Image* Image::createCopy (int newWidth, int newHeight, - const Graphics::ResamplingQuality quality) const + const Graphics::ResamplingQuality quality) const { - if (newWidth < 0) - newWidth = imageWidth; + if (newWidth < 0) + newWidth = imageWidth; - if (newHeight < 0) - newHeight = imageHeight; + if (newHeight < 0) + newHeight = imageHeight; - Image* const newImage = Image::createNativeImage (format, newWidth, newHeight, true); + Image* const newImage = Image::createNativeImage (format, newWidth, newHeight, true); - Graphics g (*newImage); - g.setImageResamplingQuality (quality); + Graphics g (*newImage); + g.setImageResamplingQuality (quality); - g.drawImage (this, - 0, 0, newWidth, newHeight, - 0, 0, imageWidth, imageHeight, - false); + g.drawImage (this, + 0, 0, newWidth, newHeight, + 0, 0, imageWidth, imageHeight, + false); - return newImage; + return newImage; } Image* Image::createCopyOfAlphaChannel() const { - jassert (format != SingleChannel); + jassert (format != SingleChannel); - Image* const newImage = Image::createNativeImage (SingleChannel, imageWidth, imageHeight, false); + Image* const newImage = Image::createNativeImage (SingleChannel, imageWidth, imageHeight, false); - if (! hasAlphaChannel()) - { - newImage->clear (0, 0, imageWidth, imageHeight, Colours::black); - } - else - { - const BitmapData destData (*newImage, 0, 0, imageWidth, imageHeight, true); - const BitmapData srcData (*this, 0, 0, imageWidth, imageHeight); + if (! hasAlphaChannel()) + { + newImage->clear (0, 0, imageWidth, imageHeight, Colours::black); + } + else + { + const BitmapData destData (*newImage, 0, 0, imageWidth, imageHeight, true); + const BitmapData srcData (*this, 0, 0, imageWidth, imageHeight); - for (int y = 0; y < imageHeight; ++y) - { - const PixelARGB* src = (const PixelARGB*) srcData.getLinePointer(y); - uint8* dst = destData.getLinePointer (y); + for (int y = 0; y < imageHeight; ++y) + { + const PixelARGB* src = (const PixelARGB*) srcData.getLinePointer(y); + uint8* dst = destData.getLinePointer (y); - for (int x = imageWidth; --x >= 0;) - { - *dst++ = src->getAlpha(); - ++src; - } - } - } + for (int x = imageWidth; --x >= 0;) + { + *dst++ = src->getAlpha(); + ++src; + } + } + } - return newImage; + return newImage; } const Colour Image::getPixelAt (const int x, const int y) const { - Colour c; + Colour c; - if (((unsigned int) x) < (unsigned int) imageWidth - && ((unsigned int) y) < (unsigned int) imageHeight) - { - const BitmapData srcData (*this, x, y, 1, 1); + if (((unsigned int) x) < (unsigned int) imageWidth + && ((unsigned int) y) < (unsigned int) imageHeight) + { + const BitmapData srcData (*this, x, y, 1, 1); - if (isARGB()) - { - PixelARGB p (*(const PixelARGB*) srcData.data); - p.unpremultiply(); - c = Colour (p.getARGB()); - } - else if (isRGB()) - c = Colour (((const PixelRGB*) srcData.data)->getARGB()); - else - c = Colour ((uint8) 0, (uint8) 0, (uint8) 0, *(srcData.data)); - } + if (isARGB()) + { + PixelARGB p (*(const PixelARGB*) srcData.data); + p.unpremultiply(); + c = Colour (p.getARGB()); + } + else if (isRGB()) + c = Colour (((const PixelRGB*) srcData.data)->getARGB()); + else + c = Colour ((uint8) 0, (uint8) 0, (uint8) 0, *(srcData.data)); + } - return c; + return c; } void Image::setPixelAt (const int x, const int y, - const Colour& colour) + const Colour& colour) { - if (((unsigned int) x) < (unsigned int) imageWidth - && ((unsigned int) y) < (unsigned int) imageHeight) - { - const BitmapData destData (*this, x, y, 1, 1, true); - const PixelARGB col (colour.getPixelARGB()); + if (((unsigned int) x) < (unsigned int) imageWidth + && ((unsigned int) y) < (unsigned int) imageHeight) + { + const BitmapData destData (*this, x, y, 1, 1, true); + const PixelARGB col (colour.getPixelARGB()); - if (isARGB()) - ((PixelARGB*) destData.data)->set (col); - else if (isRGB()) - ((PixelRGB*) destData.data)->set (col); - else - *(destData.data) = col.getAlpha(); - } + if (isARGB()) + ((PixelARGB*) destData.data)->set (col); + else if (isRGB()) + ((PixelRGB*) destData.data)->set (col); + else + *(destData.data) = col.getAlpha(); + } } void Image::multiplyAlphaAt (const int x, const int y, - const float multiplier) + const float multiplier) { - if (((unsigned int) x) < (unsigned int) imageWidth - && ((unsigned int) y) < (unsigned int) imageHeight - && hasAlphaChannel()) - { - const BitmapData destData (*this, x, y, 1, 1, true); + if (((unsigned int) x) < (unsigned int) imageWidth + && ((unsigned int) y) < (unsigned int) imageHeight + && hasAlphaChannel()) + { + const BitmapData destData (*this, x, y, 1, 1, true); - if (isARGB()) - ((PixelARGB*) destData.data)->multiplyAlpha (multiplier); - else - *(destData.data) = (uint8) (*(destData.data) * multiplier); - } + if (isARGB()) + ((PixelARGB*) destData.data)->multiplyAlpha (multiplier); + else + *(destData.data) = (uint8) (*(destData.data) * multiplier); + } } void Image::multiplyAllAlphas (const float amountToMultiplyBy) { - if (hasAlphaChannel()) - { - const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), true); + if (hasAlphaChannel()) + { + const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), true); - if (isARGB()) - { - for (int y = 0; y < imageHeight; ++y) - { - uint8* p = destData.getLinePointer (y); + if (isARGB()) + { + for (int y = 0; y < imageHeight; ++y) + { + uint8* p = destData.getLinePointer (y); - for (int x = 0; x < imageWidth; ++x) - { - ((PixelARGB*) p)->multiplyAlpha (amountToMultiplyBy); - p += destData.pixelStride; - } - } - } - else - { - for (int y = 0; y < imageHeight; ++y) - { - uint8* p = destData.getLinePointer (y); + for (int x = 0; x < imageWidth; ++x) + { + ((PixelARGB*) p)->multiplyAlpha (amountToMultiplyBy); + p += destData.pixelStride; + } + } + } + else + { + for (int y = 0; y < imageHeight; ++y) + { + uint8* p = destData.getLinePointer (y); - for (int x = 0; x < imageWidth; ++x) - { - *p = (uint8) (*p * amountToMultiplyBy); - p += destData.pixelStride; - } - } - } - } - else - { - jassertfalse // can't do this without an alpha-channel! - } + for (int x = 0; x < imageWidth; ++x) + { + *p = (uint8) (*p * amountToMultiplyBy); + p += destData.pixelStride; + } + } + } + } + else + { + jassertfalse // can't do this without an alpha-channel! + } } void Image::desaturate() { - if (isARGB() || isRGB()) - { - const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), true); + if (isARGB() || isRGB()) + { + const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), true); - if (isARGB()) - { - for (int y = 0; y < imageHeight; ++y) - { - uint8* p = destData.getLinePointer (y); + if (isARGB()) + { + for (int y = 0; y < imageHeight; ++y) + { + uint8* p = destData.getLinePointer (y); - for (int x = 0; x < imageWidth; ++x) - { - ((PixelARGB*) p)->desaturate(); - p += destData.pixelStride; - } - } - } - else - { - for (int y = 0; y < imageHeight; ++y) - { - uint8* p = destData.getLinePointer (y); + for (int x = 0; x < imageWidth; ++x) + { + ((PixelARGB*) p)->desaturate(); + p += destData.pixelStride; + } + } + } + else + { + for (int y = 0; y < imageHeight; ++y) + { + uint8* p = destData.getLinePointer (y); - for (int x = 0; x < imageWidth; ++x) - { - ((PixelRGB*) p)->desaturate(); - p += destData.pixelStride; - } - } - } - } + for (int x = 0; x < imageWidth; ++x) + { + ((PixelRGB*) p)->desaturate(); + p += destData.pixelStride; + } + } + } + } } void Image::createSolidAreaMask (RectangleList& result, const float alphaThreshold) const { - if (hasAlphaChannel()) - { - const uint8 threshold = (uint8) jlimit (0, 255, roundFloatToInt (alphaThreshold * 255.0f)); - SparseSet pixelsOnRow; + if (hasAlphaChannel()) + { + const uint8 threshold = (uint8) jlimit (0, 255, roundToInt (alphaThreshold * 255.0f)); + SparseSet pixelsOnRow; - const BitmapData srcData (*this, 0, 0, getWidth(), getHeight()); + const BitmapData srcData (*this, 0, 0, getWidth(), getHeight()); - for (int y = 0; y < imageHeight; ++y) - { - pixelsOnRow.clear(); - const uint8* lineData = srcData.getLinePointer (y); + for (int y = 0; y < imageHeight; ++y) + { + pixelsOnRow.clear(); + const uint8* lineData = srcData.getLinePointer (y); - if (isARGB()) - { - for (int x = 0; x < imageWidth; ++x) - { - if (((const PixelARGB*) lineData)->getAlpha() >= threshold) - pixelsOnRow.addRange (x, 1); + if (isARGB()) + { + for (int x = 0; x < imageWidth; ++x) + { + if (((const PixelARGB*) lineData)->getAlpha() >= threshold) + pixelsOnRow.addRange (x, 1); - lineData += srcData.pixelStride; - } - } - else - { - for (int x = 0; x < imageWidth; ++x) - { - if (*lineData >= threshold) - pixelsOnRow.addRange (x, 1); + lineData += srcData.pixelStride; + } + } + else + { + for (int x = 0; x < imageWidth; ++x) + { + if (*lineData >= threshold) + pixelsOnRow.addRange (x, 1); - lineData += srcData.pixelStride; - } - } + lineData += srcData.pixelStride; + } + } - for (int i = 0; i < pixelsOnRow.getNumRanges(); ++i) - { - int x, w; + for (int i = 0; i < pixelsOnRow.getNumRanges(); ++i) + { + int x, w; - if (pixelsOnRow.getRange (i, x, w)) - result.add (Rectangle (x, y, w, 1)); - } + if (pixelsOnRow.getRange (i, x, w)) + result.add (Rectangle (x, y, w, 1)); + } - result.consolidate(); - } - } - else - { - result.add (0, 0, imageWidth, imageHeight); - } + result.consolidate(); + } + } + else + { + result.add (0, 0, imageWidth, imageHeight); + } } void Image::moveImageSection (int dx, int dy, - int sx, int sy, - int w, int h) + int sx, int sy, + int w, int h) { - if (dx < 0) - { - w += dx; - sx -= dx; - dx = 0; - } + if (dx < 0) + { + w += dx; + sx -= dx; + dx = 0; + } - if (dy < 0) - { - h += dy; - sy -= dy; - dy = 0; - } + if (dy < 0) + { + h += dy; + sy -= dy; + dy = 0; + } - if (sx < 0) - { - w += sx; - dx -= sx; - sx = 0; - } + if (sx < 0) + { + w += sx; + dx -= sx; + sx = 0; + } - if (sy < 0) - { - h += sy; - dy -= sy; - sy = 0; - } + if (sy < 0) + { + h += sy; + dy -= sy; + sy = 0; + } - const int minX = jmin (dx, sx); - const int minY = jmin (dy, sy); + const int minX = jmin (dx, sx); + const int minY = jmin (dy, sy); - w = jmin (w, getWidth() - jmax (sx, dx)); - h = jmin (h, getHeight() - jmax (sy, dy)); + w = jmin (w, getWidth() - jmax (sx, dx)); + h = jmin (h, getHeight() - jmax (sy, dy)); - if (w > 0 && h > 0) - { - const int maxX = jmax (dx, sx) + w; - const int maxY = jmax (dy, sy) + h; + if (w > 0 && h > 0) + { + const int maxX = jmax (dx, sx) + w; + const int maxY = jmax (dy, sy) + h; - const BitmapData destData (*this, minX, minY, maxX - minX, maxY - minY, true); + const BitmapData destData (*this, minX, minY, maxX - minX, maxY - minY, true); - uint8* dst = destData.getPixelPointer (dx - minX, dy - minY); - const uint8* src = destData.getPixelPointer (sx - minX, sy - minY); + uint8* dst = destData.getPixelPointer (dx - minX, dy - minY); + const uint8* src = destData.getPixelPointer (sx - minX, sy - minY); - const int lineSize = destData.pixelStride * w; + const int lineSize = destData.pixelStride * w; - if (dy > sy) - { - while (--h >= 0) - { - const int offset = h * destData.lineStride; - memmove (dst + offset, src + offset, lineSize); - } - } - else if (dst != src) - { - while (--h >= 0) - { - memmove (dst, src, lineSize); - dst += destData.lineStride; - src += destData.lineStride; - } - } - } + if (dy > sy) + { + while (--h >= 0) + { + const int offset = h * destData.lineStride; + memmove (dst + offset, src + offset, lineSize); + } + } + else if (dst != src) + { + while (--h >= 0) + { + memmove (dst, src, lineSize); + dst += destData.lineStride; + src += destData.lineStride; + } + } + } } END_JUCE_NAMESPACE @@ -92442,197 +92229,196 @@ BEGIN_JUCE_NAMESPACE struct ImageCacheItem { - ScopedPointer image; - int64 hashCode; - int refCount; - uint32 releaseTime; + ScopedPointer image; + int64 hashCode; + int refCount; + uint32 releaseTime; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; static ImageCache* instance = 0; static int cacheTimeout = 5000; ImageCache::ImageCache() - : images (4) { } ImageCache::~ImageCache() { - jassert (instance == this); - instance = 0; + jassert (instance == this); + instance = 0; } Image* ImageCache::getFromHashCode (const int64 hashCode) { - if (instance != 0) - { - const ScopedLock sl (instance->lock); + if (instance != 0) + { + const ScopedLock sl (instance->lock); - for (int i = instance->images.size(); --i >= 0;) - { - ImageCacheItem* const ci = instance->images.getUnchecked(i); + for (int i = instance->images.size(); --i >= 0;) + { + ImageCacheItem* const ci = instance->images.getUnchecked(i); - if (ci->hashCode == hashCode) - { - ci->refCount++; - return ci->image; - } - } - } + if (ci->hashCode == hashCode) + { + ci->refCount++; + return ci->image; + } + } + } - return 0; + return 0; } void ImageCache::addImageToCache (Image* const image, - const int64 hashCode) + const int64 hashCode) { - if (image != 0) - { - if (instance == 0) - instance = new ImageCache(); + if (image != 0) + { + if (instance == 0) + instance = new ImageCache(); - ImageCacheItem* const newC = new ImageCacheItem(); - newC->hashCode = hashCode; - newC->image = image; - newC->refCount = 1; - newC->releaseTime = 0; + ImageCacheItem* const newC = new ImageCacheItem(); + newC->hashCode = hashCode; + newC->image = image; + newC->refCount = 1; + newC->releaseTime = 0; - const ScopedLock sl (instance->lock); - instance->images.add (newC); - } + const ScopedLock sl (instance->lock); + instance->images.add (newC); + } } void ImageCache::release (Image* const imageToRelease) { - if (imageToRelease != 0 && instance != 0) - { - const ScopedLock sl (instance->lock); + if (imageToRelease != 0 && instance != 0) + { + const ScopedLock sl (instance->lock); - for (int i = instance->images.size(); --i >= 0;) - { - ImageCacheItem* const ci = instance->images.getUnchecked(i); + for (int i = instance->images.size(); --i >= 0;) + { + ImageCacheItem* const ci = instance->images.getUnchecked(i); - if ((Image*) ci->image == imageToRelease) - { - if (--(ci->refCount) == 0) - ci->releaseTime = Time::getApproximateMillisecondCounter(); + if ((Image*) ci->image == imageToRelease) + { + if (--(ci->refCount) == 0) + ci->releaseTime = Time::getApproximateMillisecondCounter(); - if (! instance->isTimerRunning()) - instance->startTimer (999); + if (! instance->isTimerRunning()) + instance->startTimer (999); - break; - } - } - } + break; + } + } + } } void ImageCache::releaseOrDelete (Image* const imageToRelease) { - if (isImageInCache (imageToRelease)) - release (imageToRelease); - else - delete imageToRelease; + if (isImageInCache (imageToRelease)) + release (imageToRelease); + else + delete imageToRelease; } bool ImageCache::isImageInCache (Image* const imageToLookFor) { - if (instance != 0) - { - const ScopedLock sl (instance->lock); + if (instance != 0) + { + const ScopedLock sl (instance->lock); - for (int i = instance->images.size(); --i >= 0;) - if ((Image*) instance->images.getUnchecked(i)->image == imageToLookFor) - return true; - } + for (int i = instance->images.size(); --i >= 0;) + if ((Image*) instance->images.getUnchecked(i)->image == imageToLookFor) + return true; + } - return false; + return false; } void ImageCache::incReferenceCount (Image* const image) { - if (instance != 0) - { - const ScopedLock sl (instance->lock); + if (instance != 0) + { + const ScopedLock sl (instance->lock); - for (int i = instance->images.size(); --i >= 0;) - { - ImageCacheItem* const ci = (ImageCacheItem*) instance->images.getUnchecked(i); + for (int i = instance->images.size(); --i >= 0;) + { + ImageCacheItem* const ci = (ImageCacheItem*) instance->images.getUnchecked(i); - if ((Image*) ci->image == image) - { - ci->refCount++; - return; - } - } - } + if ((Image*) ci->image == image) + { + ci->refCount++; + return; + } + } + } - jassertfalse // (trying to inc the ref count of an image that's not in the cache) + jassertfalse // (trying to inc the ref count of an image that's not in the cache) } void ImageCache::timerCallback() { - int numberStillNeedingReleasing = 0; - const unsigned int now = Time::getApproximateMillisecondCounter(); + int numberStillNeedingReleasing = 0; + const unsigned int now = Time::getApproximateMillisecondCounter(); - const ScopedLock sl (lock); + const ScopedLock sl (lock); - for (int i = images.size(); --i >= 0;) - { - ImageCacheItem* const ci = images.getUnchecked(i); + for (int i = images.size(); --i >= 0;) + { + ImageCacheItem* const ci = images.getUnchecked(i); - if (ci->refCount <= 0) - { - if (now > ci->releaseTime + cacheTimeout - || now < ci->releaseTime - 1000) - { - images.remove (i); - } - else - { - ++numberStillNeedingReleasing; - } - } - } + if (ci->refCount <= 0) + { + if (now > ci->releaseTime + cacheTimeout + || now < ci->releaseTime - 1000) + { + images.remove (i); + } + else + { + ++numberStillNeedingReleasing; + } + } + } - if (numberStillNeedingReleasing == 0) - stopTimer(); + if (numberStillNeedingReleasing == 0) + stopTimer(); } Image* ImageCache::getFromFile (const File& file) { - const int64 hashCode = file.hashCode64(); - Image* image = getFromHashCode (hashCode); + const int64 hashCode = file.hashCode64(); + Image* image = getFromHashCode (hashCode); - if (image == 0) - { - image = ImageFileFormat::loadFrom (file); - addImageToCache (image, hashCode); - } + if (image == 0) + { + image = ImageFileFormat::loadFrom (file); + addImageToCache (image, hashCode); + } - return image; + return image; } Image* ImageCache::getFromMemory (const void* imageData, - const int dataSize) + const int dataSize) { - const int64 hashCode = (int64) (pointer_sized_int) imageData; + const int64 hashCode = (int64) (pointer_sized_int) imageData; - Image* image = getFromHashCode (hashCode); + Image* image = getFromHashCode (hashCode); - if (image == 0) - { - image = ImageFileFormat::loadFrom (imageData, dataSize); - addImageToCache (image, hashCode); - } + if (image == 0) + { + image = ImageFileFormat::loadFrom (imageData, dataSize); + addImageToCache (image, hashCode); + } - return image; + return image; } void ImageCache::setCacheTimeout (const int millisecs) { - cacheTimeout = millisecs; + cacheTimeout = millisecs; } END_JUCE_NAMESPACE @@ -92643,10 +92429,10 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE ImageConvolutionKernel::ImageConvolutionKernel (const int size_) - : values (size_ * size_), - size (size_) + : values (size_ * size_), + size (size_) { - clear(); + clear(); } ImageConvolutionKernel::~ImageConvolutionKernel() @@ -92654,215 +92440,215 @@ ImageConvolutionKernel::~ImageConvolutionKernel() } void ImageConvolutionKernel::setKernelValue (const int x, - const int y, - const float value) + const int y, + const float value) { - if (((unsigned int) x) < (unsigned int) size - && ((unsigned int) y) < (unsigned int) size) - { - values [x + y * size] = value; - } - else - { - jassertfalse - } + if (((unsigned int) x) < (unsigned int) size + && ((unsigned int) y) < (unsigned int) size) + { + values [x + y * size] = value; + } + else + { + jassertfalse + } } void ImageConvolutionKernel::clear() { - for (int i = size * size; --i >= 0;) - values[i] = 0; + for (int i = size * size; --i >= 0;) + values[i] = 0; } void ImageConvolutionKernel::setOverallSum (const float desiredTotalSum) { - double currentTotal = 0.0; + double currentTotal = 0.0; - for (int i = size * size; --i >= 0;) - currentTotal += values[i]; + for (int i = size * size; --i >= 0;) + currentTotal += values[i]; - rescaleAllValues ((float) (desiredTotalSum / currentTotal)); + rescaleAllValues ((float) (desiredTotalSum / currentTotal)); } void ImageConvolutionKernel::rescaleAllValues (const float multiplier) { - for (int i = size * size; --i >= 0;) - values[i] *= multiplier; + for (int i = size * size; --i >= 0;) + values[i] *= multiplier; } void ImageConvolutionKernel::createGaussianBlur (const float radius) { - const double radiusFactor = -1.0 / (radius * radius * 2); - const int centre = size >> 1; + const double radiusFactor = -1.0 / (radius * radius * 2); + const int centre = size >> 1; - for (int y = size; --y >= 0;) - { - for (int x = size; --x >= 0;) - { - const int cx = x - centre; - const int cy = y - centre; + for (int y = size; --y >= 0;) + { + for (int x = size; --x >= 0;) + { + const int cx = x - centre; + const int cy = y - centre; - values [x + y * size] = (float) exp (radiusFactor * (cx * cx + cy * cy)); - } - } + values [x + y * size] = (float) exp (radiusFactor * (cx * cx + cy * cy)); + } + } - setOverallSum (1.0f); + setOverallSum (1.0f); } void ImageConvolutionKernel::applyToImage (Image& destImage, - const Image* sourceImage, - int dx, - int dy, - int dw, - int dh) const + const Image* sourceImage, + int dx, + int dy, + int dw, + int dh) const { - ScopedPointer imageCreated; + ScopedPointer imageCreated; - if (sourceImage == 0) - { - sourceImage = imageCreated = destImage.createCopy(); - } - else - { - jassert (sourceImage->getWidth() == destImage.getWidth() - && sourceImage->getHeight() == destImage.getHeight() - && sourceImage->getFormat() == destImage.getFormat()); + if (sourceImage == 0) + { + sourceImage = imageCreated = destImage.createCopy(); + } + else + { + jassert (sourceImage->getWidth() == destImage.getWidth() + && sourceImage->getHeight() == destImage.getHeight() + && sourceImage->getFormat() == destImage.getFormat()); - if (sourceImage->getWidth() != destImage.getWidth() - || sourceImage->getHeight() != destImage.getHeight() - || sourceImage->getFormat() != destImage.getFormat()) - return; - } + if (sourceImage->getWidth() != destImage.getWidth() + || sourceImage->getHeight() != destImage.getHeight() + || sourceImage->getFormat() != destImage.getFormat()) + return; + } - const int imageWidth = destImage.getWidth(); - const int imageHeight = destImage.getHeight(); + const int imageWidth = destImage.getWidth(); + const int imageHeight = destImage.getHeight(); - if (dx >= imageWidth || dy >= imageHeight) - return; + if (dx >= imageWidth || dy >= imageHeight) + return; - if (dx + dw > imageWidth) - dw = imageWidth - dx; + if (dx + dw > imageWidth) + dw = imageWidth - dx; - if (dy + dh > imageHeight) - dh = imageHeight - dy; + if (dy + dh > imageHeight) + dh = imageHeight - dy; - const int dx2 = dx + dw; - const int dy2 = dy + dh; + const int dx2 = dx + dw; + const int dy2 = dy + dh; - const Image::BitmapData destData (destImage, dx, dy, dw, dh, true); - uint8* line = destData.data; + const Image::BitmapData destData (destImage, dx, dy, dw, dh, true); + uint8* line = destData.data; - const Image::BitmapData srcData (*sourceImage, 0, 0, sourceImage->getWidth(), sourceImage->getHeight()); + const Image::BitmapData srcData (*sourceImage, 0, 0, sourceImage->getWidth(), sourceImage->getHeight()); - if (destData.pixelStride == 4) - { - for (int y = dy; y < dy2; ++y) - { - uint8* dest = line; - line += destData.lineStride; + if (destData.pixelStride == 4) + { + for (int y = dy; y < dy2; ++y) + { + uint8* dest = line; + line += destData.lineStride; - for (int x = dx; x < dx2; ++x) - { - float c1 = 0; - float c2 = 0; - float c3 = 0; - float c4 = 0; + for (int x = dx; x < dx2; ++x) + { + float c1 = 0; + float c2 = 0; + float c3 = 0; + float c4 = 0; - for (int yy = 0; yy < size; ++yy) - { - const int sy = y + yy - (size >> 1); + for (int yy = 0; yy < size; ++yy) + { + const int sy = y + yy - (size >> 1); - if (sy >= imageHeight) - break; + if (sy >= imageHeight) + break; - if (sy >= 0) - { - int sx = x - (size >> 1); - const uint8* src = srcData.getPixelPointer (sx, sy); + if (sy >= 0) + { + int sx = x - (size >> 1); + const uint8* src = srcData.getPixelPointer (sx, sy); - for (int xx = 0; xx < size; ++xx) - { - if (sx >= imageWidth) - break; + for (int xx = 0; xx < size; ++xx) + { + if (sx >= imageWidth) + break; - if (sx >= 0) - { - const float kernelMult = values [xx + yy * size]; - c1 += kernelMult * *src++; - c2 += kernelMult * *src++; - c3 += kernelMult * *src++; - c4 += kernelMult * *src++; - } - else - { - src += 4; - } + if (sx >= 0) + { + const float kernelMult = values [xx + yy * size]; + c1 += kernelMult * *src++; + c2 += kernelMult * *src++; + c3 += kernelMult * *src++; + c4 += kernelMult * *src++; + } + else + { + src += 4; + } - ++sx; - } - } - } + ++sx; + } + } + } - *dest++ = (uint8) jmin (0xff, roundFloatToInt (c1)); - *dest++ = (uint8) jmin (0xff, roundFloatToInt (c2)); - *dest++ = (uint8) jmin (0xff, roundFloatToInt (c3)); - *dest++ = (uint8) jmin (0xff, roundFloatToInt (c4)); - } - } - } - else if (destData.pixelStride == 3) - { - for (int y = dy; y < dy2; ++y) - { - uint8* dest = line; - line += destData.lineStride; + *dest++ = (uint8) jmin (0xff, roundToInt (c1)); + *dest++ = (uint8) jmin (0xff, roundToInt (c2)); + *dest++ = (uint8) jmin (0xff, roundToInt (c3)); + *dest++ = (uint8) jmin (0xff, roundToInt (c4)); + } + } + } + else if (destData.pixelStride == 3) + { + for (int y = dy; y < dy2; ++y) + { + uint8* dest = line; + line += destData.lineStride; - for (int x = dx; x < dx2; ++x) - { - float c1 = 0; - float c2 = 0; - float c3 = 0; + for (int x = dx; x < dx2; ++x) + { + float c1 = 0; + float c2 = 0; + float c3 = 0; - for (int yy = 0; yy < size; ++yy) - { - const int sy = y + yy - (size >> 1); + for (int yy = 0; yy < size; ++yy) + { + const int sy = y + yy - (size >> 1); - if (sy >= imageHeight) - break; + if (sy >= imageHeight) + break; - if (sy >= 0) - { - int sx = x - (size >> 1); - const uint8* src = srcData.getPixelPointer (sx, sy); + if (sy >= 0) + { + int sx = x - (size >> 1); + const uint8* src = srcData.getPixelPointer (sx, sy); - for (int xx = 0; xx < size; ++xx) - { - if (sx >= imageWidth) - break; + for (int xx = 0; xx < size; ++xx) + { + if (sx >= imageWidth) + break; - if (sx >= 0) - { - const float kernelMult = values [xx + yy * size]; - c1 += kernelMult * *src++; - c2 += kernelMult * *src++; - c3 += kernelMult * *src++; - } - else - { - src += 3; - } + if (sx >= 0) + { + const float kernelMult = values [xx + yy * size]; + c1 += kernelMult * *src++; + c2 += kernelMult * *src++; + c3 += kernelMult * *src++; + } + else + { + src += 3; + } - ++sx; - } - } - } + ++sx; + } + } + } - *dest++ = (uint8) roundFloatToInt (c1); - *dest++ = (uint8) roundFloatToInt (c2); - *dest++ = (uint8) roundFloatToInt (c3); - } - } - } + *dest++ = (uint8) roundToInt (c1); + *dest++ = (uint8) roundToInt (c2); + *dest++ = (uint8) roundToInt (c3); + } + } + } } END_JUCE_NAMESPACE @@ -92878,47 +92664,41 @@ BEGIN_JUCE_NAMESPACE #ifndef DOXYGEN -/** - Used internally by ImageFileFormat - don't use this class directly in your - application. - - @see ImageFileFormat -*/ class GIFLoader { public: - GIFLoader (InputStream& in); - ~GIFLoader(); + GIFLoader (InputStream& in); + ~GIFLoader(); - Image* getImage() const { return image; } + Image* getImage() const { return image; } private: - Image* image; - InputStream& input; - uint8 buffer [300]; - uint8 palette [256][4]; - bool dataBlockIsZero, fresh, finished; - int currentBit, lastBit, lastByteIndex; - int codeSize, setCodeSize; - int maxCode, maxCodeSize; - int firstcode, oldcode; - int clearCode, end_code; - enum { maxGifCode = 1 << 12 }; - int table [2] [maxGifCode]; - int stack [2 * maxGifCode]; - int *sp; + Image* image; + InputStream& input; + uint8 buffer [300]; + uint8 palette [256][4]; + bool dataBlockIsZero, fresh, finished; + int currentBit, lastBit, lastByteIndex; + int codeSize, setCodeSize; + int maxCode, maxCodeSize; + int firstcode, oldcode; + int clearCode, end_code; + enum { maxGifCode = 1 << 12 }; + int table [2] [maxGifCode]; + int stack [2 * maxGifCode]; + int *sp; - bool getSizeFromHeader (int& width, int& height); - bool readPalette (const int numCols); - int readDataBlock (unsigned char* dest); - int processExtension (int type, int& transparent); - int readLZWByte (bool initialise, int input_code_size); - int getCode (int code_size, bool initialise); - bool readImage (int width, int height, int interlace, int transparent); - static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } + bool getSizeFromHeader (int& width, int& height); + bool readPalette (const int numCols); + int readDataBlock (unsigned char* dest); + int processExtension (int type, int& transparent); + int readLZWByte (bool initialise, int input_code_size); + int getCode (int code_size, bool initialise); + bool readImage (int width, int height, int interlace, int transparent); + static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } - GIFLoader (const GIFLoader&); - const GIFLoader& operator= (const GIFLoader&); + GIFLoader (const GIFLoader&); + const GIFLoader& operator= (const GIFLoader&); }; #endif // DOXYGEN @@ -92929,176 +92709,176 @@ private: Image* juce_loadPNGImageFromStream (InputStream& inputStream); bool juce_writePNGImageToStream (const Image& image, OutputStream& out); -PNGImageFormat::PNGImageFormat() {} +PNGImageFormat::PNGImageFormat() {} PNGImageFormat::~PNGImageFormat() {} const String PNGImageFormat::getFormatName() { - return T("PNG"); + return T("PNG"); } bool PNGImageFormat::canUnderstand (InputStream& in) { - const int bytesNeeded = 4; - char header [bytesNeeded]; + const int bytesNeeded = 4; + char header [bytesNeeded]; - return in.read (header, bytesNeeded) == bytesNeeded - && header[1] == 'P' - && header[2] == 'N' - && header[3] == 'G'; + return in.read (header, bytesNeeded) == bytesNeeded + && header[1] == 'P' + && header[2] == 'N' + && header[3] == 'G'; } Image* PNGImageFormat::decodeImage (InputStream& in) { - return juce_loadPNGImageFromStream (in); + return juce_loadPNGImageFromStream (in); } bool PNGImageFormat::writeImageToStream (const Image& sourceImage, - OutputStream& destStream) + OutputStream& destStream) { - return juce_writePNGImageToStream (sourceImage, destStream); + return juce_writePNGImageToStream (sourceImage, destStream); } Image* juce_loadJPEGImageFromStream (InputStream& inputStream); bool juce_writeJPEGImageToStream (const Image& image, OutputStream& out, float quality); JPEGImageFormat::JPEGImageFormat() - : quality (-1.0f) + : quality (-1.0f) { } -JPEGImageFormat::~JPEGImageFormat() {} +JPEGImageFormat::~JPEGImageFormat() {} void JPEGImageFormat::setQuality (const float newQuality) { - quality = newQuality; + quality = newQuality; } const String JPEGImageFormat::getFormatName() { - return T("JPEG"); + return T("JPEG"); } bool JPEGImageFormat::canUnderstand (InputStream& in) { - const int bytesNeeded = 10; - uint8 header [bytesNeeded]; + const int bytesNeeded = 10; + uint8 header [bytesNeeded]; - if (in.read (header, bytesNeeded) == bytesNeeded) - { - return header[0] == 0xff - && header[1] == 0xd8 - && header[2] == 0xff - && (header[3] == 0xe0 || header[3] == 0xe1); - } + if (in.read (header, bytesNeeded) == bytesNeeded) + { + return header[0] == 0xff + && header[1] == 0xd8 + && header[2] == 0xff + && (header[3] == 0xe0 || header[3] == 0xe1); + } - return false; + return false; } Image* JPEGImageFormat::decodeImage (InputStream& in) { - return juce_loadJPEGImageFromStream (in); + return juce_loadJPEGImageFromStream (in); } bool JPEGImageFormat::writeImageToStream (const Image& sourceImage, - OutputStream& destStream) + OutputStream& destStream) { - return juce_writeJPEGImageToStream (sourceImage, destStream, quality); + return juce_writeJPEGImageToStream (sourceImage, destStream, quality); } class GIFImageFormat : public ImageFileFormat { public: - GIFImageFormat() {} - ~GIFImageFormat() {} + GIFImageFormat() {} + ~GIFImageFormat() {} - const String getFormatName() - { - return T("GIF"); - } + const String getFormatName() + { + return T("GIF"); + } - bool canUnderstand (InputStream& in) - { - const int bytesNeeded = 4; - char header [bytesNeeded]; + bool canUnderstand (InputStream& in) + { + const int bytesNeeded = 4; + char header [bytesNeeded]; - return (in.read (header, bytesNeeded) == bytesNeeded) - && header[0] == 'G' - && header[1] == 'I' - && header[2] == 'F'; - } + return (in.read (header, bytesNeeded) == bytesNeeded) + && header[0] == 'G' + && header[1] == 'I' + && header[2] == 'F'; + } - Image* decodeImage (InputStream& in) - { - const ScopedPointer loader (new GIFLoader (in)); - return loader->getImage(); - } + Image* decodeImage (InputStream& in) + { + const ScopedPointer loader (new GIFLoader (in)); + return loader->getImage(); + } - bool writeImageToStream (const Image& /*sourceImage*/, OutputStream& /*destStream*/) - { - return false; - } + bool writeImageToStream (const Image& /*sourceImage*/, OutputStream& /*destStream*/) + { + return false; + } }; ImageFileFormat* ImageFileFormat::findImageFormatForStream (InputStream& input) { - static PNGImageFormat png; - static JPEGImageFormat jpg; - static GIFImageFormat gif; + static PNGImageFormat png; + static JPEGImageFormat jpg; + static GIFImageFormat gif; - ImageFileFormat* formats[4]; - int numFormats = 0; + ImageFileFormat* formats[4]; + int numFormats = 0; - formats [numFormats++] = &png; - formats [numFormats++] = &jpg; - formats [numFormats++] = &gif; + formats [numFormats++] = &png; + formats [numFormats++] = &jpg; + formats [numFormats++] = &gif; - const int64 streamPos = input.getPosition(); + const int64 streamPos = input.getPosition(); - for (int i = 0; i < numFormats; ++i) - { - const bool found = formats[i]->canUnderstand (input); - input.setPosition (streamPos); + for (int i = 0; i < numFormats; ++i) + { + const bool found = formats[i]->canUnderstand (input); + input.setPosition (streamPos); - if (found) - return formats[i]; - } + if (found) + return formats[i]; + } - return 0; + return 0; } Image* ImageFileFormat::loadFrom (InputStream& input) { - ImageFileFormat* const format = findImageFormatForStream (input); + ImageFileFormat* const format = findImageFormatForStream (input); - if (format != 0) - return format->decodeImage (input); + if (format != 0) + return format->decodeImage (input); - return 0; + return 0; } Image* ImageFileFormat::loadFrom (const File& file) { - InputStream* const in = file.createInputStream(); + InputStream* const in = file.createInputStream(); - if (in != 0) - { - BufferedInputStream b (in, 8192, true); - return loadFrom (b); - } + if (in != 0) + { + BufferedInputStream b (in, 8192, true); + return loadFrom (b); + } - return 0; + return 0; } Image* ImageFileFormat::loadFrom (const void* rawData, const int numBytes) { - if (rawData != 0 && numBytes > 4) - { - MemoryInputStream stream (rawData, numBytes, false); - return loadFrom (stream); - } + if (rawData != 0 && numBytes > 4) + { + MemoryInputStream stream (rawData, numBytes, false); + return loadFrom (stream); + } - return 0; + return 0; } END_JUCE_NAMESPACE @@ -93109,78 +92889,78 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE GIFLoader::GIFLoader (InputStream& in) - : image (0), - input (in), - dataBlockIsZero (false), - fresh (false), - finished (false) + : image (0), + input (in), + dataBlockIsZero (false), + fresh (false), + finished (false) { - currentBit = lastBit = lastByteIndex = 0; - maxCode = maxCodeSize = codeSize = setCodeSize = 0; - firstcode = oldcode = 0; - clearCode = end_code = 0; + currentBit = lastBit = lastByteIndex = 0; + maxCode = maxCodeSize = codeSize = setCodeSize = 0; + firstcode = oldcode = 0; + clearCode = end_code = 0; - int imageWidth, imageHeight; - int transparent = -1; + int imageWidth, imageHeight; + int transparent = -1; - if (! getSizeFromHeader (imageWidth, imageHeight)) - return; + if (! getSizeFromHeader (imageWidth, imageHeight)) + return; - if ((imageWidth <= 0) || (imageHeight <= 0)) - return; + if ((imageWidth <= 0) || (imageHeight <= 0)) + return; - unsigned char buf [16]; - if (in.read (buf, 3) != 3) - return; + unsigned char buf [16]; + if (in.read (buf, 3) != 3) + return; - int numColours = 2 << (buf[0] & 7); + int numColours = 2 << (buf[0] & 7); - if ((buf[0] & 0x80) != 0) - readPalette (numColours); + if ((buf[0] & 0x80) != 0) + readPalette (numColours); - for (;;) - { - if (input.read (buf, 1) != 1) - break; + for (;;) + { + if (input.read (buf, 1) != 1) + break; - if (buf[0] == ';') - break; + if (buf[0] == ';') + break; - if (buf[0] == '!') - { - if (input.read (buf, 1) != 1) - break; + if (buf[0] == '!') + { + if (input.read (buf, 1) != 1) + break; - if (processExtension (buf[0], transparent) < 0) - break; + if (processExtension (buf[0], transparent) < 0) + break; - continue; - } + continue; + } - if (buf[0] != ',') - continue; + if (buf[0] != ',') + continue; - if (input.read (buf, 9) != 9) - break; + if (input.read (buf, 9) != 9) + break; - imageWidth = makeWord (buf[4], buf[5]); - imageHeight = makeWord (buf[6], buf[7]); + imageWidth = makeWord (buf[4], buf[5]); + imageHeight = makeWord (buf[6], buf[7]); - numColours = 2 << (buf[8] & 7); + numColours = 2 << (buf[8] & 7); - if ((buf[8] & 0x80) != 0) - if (! readPalette (numColours)) - break; + if ((buf[8] & 0x80) != 0) + if (! readPalette (numColours)) + break; - image = Image::createNativeImage ((transparent >= 0) ? Image::ARGB : Image::RGB, - imageWidth, imageHeight, (transparent >= 0)); + image = Image::createNativeImage ((transparent >= 0) ? Image::ARGB : Image::RGB, + imageWidth, imageHeight, (transparent >= 0)); - readImage (imageWidth, imageHeight, - (buf[8] & 0x40) != 0, - transparent); + readImage (imageWidth, imageHeight, + (buf[8] & 0x40) != 0, + transparent); - break; - } + break; + } } GIFLoader::~GIFLoader() @@ -93189,355 +92969,355 @@ GIFLoader::~GIFLoader() bool GIFLoader::getSizeFromHeader (int& w, int& h) { - unsigned char b [8]; + unsigned char b [8]; - if (input.read (b, 6) == 6) - { - if ((strncmp ("GIF87a", (char*) b, 6) == 0) - || (strncmp ("GIF89a", (char*) b, 6) == 0)) - { - if (input.read (b, 4) == 4) - { - w = makeWord (b[0], b[1]); - h = makeWord (b[2], b[3]); - return true; - } - } - } + if (input.read (b, 6) == 6) + { + if ((strncmp ("GIF87a", (char*) b, 6) == 0) + || (strncmp ("GIF89a", (char*) b, 6) == 0)) + { + if (input.read (b, 4) == 4) + { + w = makeWord (b[0], b[1]); + h = makeWord (b[2], b[3]); + return true; + } + } + } - return false; + return false; } bool GIFLoader::readPalette (const int numCols) { - unsigned char rgb[4]; + unsigned char rgb[4]; - for (int i = 0; i < numCols; ++i) - { - input.read (rgb, 3); + for (int i = 0; i < numCols; ++i) + { + input.read (rgb, 3); - palette [i][0] = rgb[0]; - palette [i][1] = rgb[1]; - palette [i][2] = rgb[2]; - palette [i][3] = 0xff; - } + palette [i][0] = rgb[0]; + palette [i][1] = rgb[1]; + palette [i][2] = rgb[2]; + palette [i][3] = 0xff; + } - return true; + return true; } int GIFLoader::readDataBlock (unsigned char* const dest) { - unsigned char n; + unsigned char n; - if (input.read (&n, 1) == 1) - { - dataBlockIsZero = (n == 0); + if (input.read (&n, 1) == 1) + { + dataBlockIsZero = (n == 0); - if (dataBlockIsZero || (input.read (dest, n) == n)) - return n; - } + if (dataBlockIsZero || (input.read (dest, n) == n)) + return n; + } - return -1; + return -1; } int GIFLoader::processExtension (const int type, int& transparent) { - unsigned char b [300]; - int n = 0; + unsigned char b [300]; + int n = 0; - if (type == 0xf9) - { - n = readDataBlock (b); - if (n < 0) - return 1; + if (type == 0xf9) + { + n = readDataBlock (b); + if (n < 0) + return 1; - if ((b[0] & 0x1) != 0) - transparent = b[3]; - } + if ((b[0] & 0x1) != 0) + transparent = b[3]; + } - do - { - n = readDataBlock (b); - } - while (n > 0); + do + { + n = readDataBlock (b); + } + while (n > 0); - return n; + return n; } int GIFLoader::getCode (const int codeSize_, const bool initialise) { - if (initialise) - { - currentBit = 0; - lastBit = 0; - finished = false; - return 0; - } + if (initialise) + { + currentBit = 0; + lastBit = 0; + finished = false; + return 0; + } - if ((currentBit + codeSize_) >= lastBit) - { - if (finished) - return -1; + if ((currentBit + codeSize_) >= lastBit) + { + if (finished) + return -1; - buffer[0] = buffer [lastByteIndex - 2]; - buffer[1] = buffer [lastByteIndex - 1]; + buffer[0] = buffer [lastByteIndex - 2]; + buffer[1] = buffer [lastByteIndex - 1]; - const int n = readDataBlock (&buffer[2]); + const int n = readDataBlock (&buffer[2]); - if (n == 0) - finished = true; + if (n == 0) + finished = true; - lastByteIndex = 2 + n; - currentBit = (currentBit - lastBit) + 16; - lastBit = (2 + n) * 8 ; - } + lastByteIndex = 2 + n; + currentBit = (currentBit - lastBit) + 16; + lastBit = (2 + n) * 8 ; + } - int result = 0; - int i = currentBit; + int result = 0; + int i = currentBit; - for (int j = 0; j < codeSize_; ++j) - { - result |= ((buffer[i >> 3] & (1 << (i & 7))) != 0) << j; - ++i; - } + for (int j = 0; j < codeSize_; ++j) + { + result |= ((buffer[i >> 3] & (1 << (i & 7))) != 0) << j; + ++i; + } - currentBit += codeSize_; + currentBit += codeSize_; - return result; + return result; } int GIFLoader::readLZWByte (const bool initialise, const int inputCodeSize) { - int code, incode, i; + int code, incode, i; - if (initialise) - { - setCodeSize = inputCodeSize; - codeSize = setCodeSize + 1; - clearCode = 1 << setCodeSize; - end_code = clearCode + 1; - maxCodeSize = 2 * clearCode; - maxCode = clearCode + 2; + if (initialise) + { + setCodeSize = inputCodeSize; + codeSize = setCodeSize + 1; + clearCode = 1 << setCodeSize; + end_code = clearCode + 1; + maxCodeSize = 2 * clearCode; + maxCode = clearCode + 2; - getCode (0, true); + getCode (0, true); - fresh = true; + fresh = true; - for (i = 0; i < clearCode; ++i) - { - table[0][i] = 0; - table[1][i] = i; - } + for (i = 0; i < clearCode; ++i) + { + table[0][i] = 0; + table[1][i] = i; + } - for (; i < maxGifCode; ++i) - { - table[0][i] = 0; - table[1][i] = 0; - } + for (; i < maxGifCode; ++i) + { + table[0][i] = 0; + table[1][i] = 0; + } - sp = stack; + sp = stack; - return 0; - } - else if (fresh) - { - fresh = false; + return 0; + } + else if (fresh) + { + fresh = false; - do - { - firstcode = oldcode - = getCode (codeSize, false); - } - while (firstcode == clearCode); + do + { + firstcode = oldcode + = getCode (codeSize, false); + } + while (firstcode == clearCode); - return firstcode; - } + return firstcode; + } - if (sp > stack) - return *--sp; + if (sp > stack) + return *--sp; - while ((code = getCode (codeSize, false)) >= 0) - { - if (code == clearCode) - { - for (i = 0; i < clearCode; ++i) - { - table[0][i] = 0; - table[1][i] = i; - } + while ((code = getCode (codeSize, false)) >= 0) + { + if (code == clearCode) + { + for (i = 0; i < clearCode; ++i) + { + table[0][i] = 0; + table[1][i] = i; + } - for (; i < maxGifCode; ++i) - { - table[0][i] = 0; - table[1][i] = 0; - } + for (; i < maxGifCode; ++i) + { + table[0][i] = 0; + table[1][i] = 0; + } - codeSize = setCodeSize + 1; - maxCodeSize = 2 * clearCode; - maxCode = clearCode + 2; - sp = stack; - firstcode = oldcode = getCode (codeSize, false); - return firstcode; + codeSize = setCodeSize + 1; + maxCodeSize = 2 * clearCode; + maxCode = clearCode + 2; + sp = stack; + firstcode = oldcode = getCode (codeSize, false); + return firstcode; - } - else if (code == end_code) - { - if (dataBlockIsZero) - return -2; + } + else if (code == end_code) + { + if (dataBlockIsZero) + return -2; - unsigned char buf [260]; + unsigned char buf [260]; - int n; - while ((n = readDataBlock (buf)) > 0) - {} + int n; + while ((n = readDataBlock (buf)) > 0) + {} - if (n != 0) - return -2; - } + if (n != 0) + return -2; + } - incode = code; + incode = code; - if (code >= maxCode) - { - *sp++ = firstcode; - code = oldcode; - } + if (code >= maxCode) + { + *sp++ = firstcode; + code = oldcode; + } - while (code >= clearCode) - { - *sp++ = table[1][code]; - if (code == table[0][code]) - return -2; + while (code >= clearCode) + { + *sp++ = table[1][code]; + if (code == table[0][code]) + return -2; - code = table[0][code]; - } + code = table[0][code]; + } - *sp++ = firstcode = table[1][code]; + *sp++ = firstcode = table[1][code]; - if ((code = maxCode) < maxGifCode) - { - table[0][code] = oldcode; - table[1][code] = firstcode; - ++maxCode; + if ((code = maxCode) < maxGifCode) + { + table[0][code] = oldcode; + table[1][code] = firstcode; + ++maxCode; - if ((maxCode >= maxCodeSize) - && (maxCodeSize < maxGifCode)) - { - maxCodeSize <<= 1; - ++codeSize; - } - } + if ((maxCode >= maxCodeSize) + && (maxCodeSize < maxGifCode)) + { + maxCodeSize <<= 1; + ++codeSize; + } + } - oldcode = incode; + oldcode = incode; - if (sp > stack) - return *--sp; - } + if (sp > stack) + return *--sp; + } - return code; + return code; } bool GIFLoader::readImage (const int width, const int height, - const int interlace, const int transparent) + const int interlace, const int transparent) { - unsigned char c; + unsigned char c; - if (input.read (&c, 1) != 1 - || readLZWByte (true, c) < 0) - return false; + if (input.read (&c, 1) != 1 + || readLZWByte (true, c) < 0) + return false; - if (transparent >= 0) - { - palette [transparent][0] = 0; - palette [transparent][1] = 0; - palette [transparent][2] = 0; - palette [transparent][3] = 0; - } + if (transparent >= 0) + { + palette [transparent][0] = 0; + palette [transparent][1] = 0; + palette [transparent][2] = 0; + palette [transparent][3] = 0; + } - int index; - int xpos = 0, ypos = 0, pass = 0; + int index; + int xpos = 0, ypos = 0, pass = 0; - const Image::BitmapData destData (*image, 0, 0, width, height, true); - uint8* p = destData.data; - const bool hasAlpha = image->hasAlphaChannel(); + const Image::BitmapData destData (*image, 0, 0, width, height, true); + uint8* p = destData.data; + const bool hasAlpha = image->hasAlphaChannel(); - while ((index = readLZWByte (false, c)) >= 0) - { - const uint8* const paletteEntry = palette [index]; + while ((index = readLZWByte (false, c)) >= 0) + { + const uint8* const paletteEntry = palette [index]; - if (hasAlpha) - { - ((PixelARGB*) p)->setARGB (paletteEntry[3], - paletteEntry[0], - paletteEntry[1], - paletteEntry[2]); + if (hasAlpha) + { + ((PixelARGB*) p)->setARGB (paletteEntry[3], + paletteEntry[0], + paletteEntry[1], + paletteEntry[2]); - ((PixelARGB*) p)->premultiply(); - } - else - { - ((PixelRGB*) p)->setARGB (0, - paletteEntry[0], - paletteEntry[1], - paletteEntry[2]); - } + ((PixelARGB*) p)->premultiply(); + } + else + { + ((PixelRGB*) p)->setARGB (0, + paletteEntry[0], + paletteEntry[1], + paletteEntry[2]); + } - p += destData.pixelStride; - ++xpos; + p += destData.pixelStride; + ++xpos; - if (xpos == width) - { - xpos = 0; + if (xpos == width) + { + xpos = 0; - if (interlace) - { - switch (pass) - { - case 0: - case 1: - ypos += 8; - break; - case 2: - ypos += 4; - break; - case 3: - ypos += 2; - break; - } + if (interlace) + { + switch (pass) + { + case 0: + case 1: + ypos += 8; + break; + case 2: + ypos += 4; + break; + case 3: + ypos += 2; + break; + } - while (ypos >= height) - { - ++pass; + while (ypos >= height) + { + ++pass; - switch (pass) - { - case 1: - ypos = 4; - break; - case 2: - ypos = 2; - break; - case 3: - ypos = 1; - break; - default: - return true; - } - } - } - else - { - ++ypos; - } + switch (pass) + { + case 1: + ypos = 4; + break; + case 2: + ypos = 2; + break; + case 3: + ypos = 1; + break; + default: + return true; + } + } + } + else + { + ++ypos; + } - p = destData.getPixelPointer (xpos, ypos); - } + p = destData.getPixelPointer (xpos, ypos); + } - if (ypos >= height) - break; - } + if (ypos >= height) + break; + } - return true; + return true; } END_JUCE_NAMESPACE @@ -93562,7 +93342,6 @@ namespace zlibNamespace #define ZLIB_H /********* Start of inlined file: zconf.h *********/ -/* @(#) $Id: zconf.h,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */ #ifndef ZCONF_H #define ZCONF_H @@ -93575,55 +93354,51 @@ namespace zlibNamespace #pragma warning (disable : 4131 4127 4244 4267) #endif -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - */ #ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ # define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define deflateBound z_deflateBound -# define deflatePrime z_deflatePrime -# define inflateInit2_ z_inflateInit2_ +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ # define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateCopy z_inflateCopy -# define inflateReset z_inflateReset -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table -# define zError z_zError +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError -# define alloc_func z_alloc_func -# define free_func z_free_func -# define in_func z_in_func -# define out_func z_out_func -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp #endif #if defined(__MSDOS__) && !defined(MSDOS) @@ -93637,21 +93412,17 @@ namespace zlibNamespace #endif #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) # ifndef WIN32 -# define WIN32 +# define WIN32 # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif +# ifndef SYS16BIT +# define SYS16BIT +# endif # endif #endif -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ #ifdef SYS16BIT # define MAXSEG_64K #endif @@ -93661,12 +93432,12 @@ namespace zlibNamespace #ifdef __STDC_VERSION__ # ifndef STDC -# define STDC +# define STDC # endif # if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif +# ifndef STDC99 +# define STDC99 +# endif # endif #endif #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) @@ -93682,131 +93453,92 @@ namespace zlibNamespace # define STDC #endif -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ +# define const /* note: need a more gentle solution here */ # endif #endif -/* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL #endif -/* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 +# define MAX_MEM_LEVEL 8 # else -# define MAX_MEM_LEVEL 9 +# define MAX_MEM_LEVEL 9 # endif #endif -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - #ifndef OF /* function prototypes */ # ifdef STDC -# define OF(args) args +# define OF(args) args # else -# define OF(args) () +# define OF(args) () # endif #endif -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ #ifdef SYS16BIT # if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif # endif # if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif # endif #endif #if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ # ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif # endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ # ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif +# ifdef FAR +# undef FAR +# endif +# include +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif # endif #endif #if defined (__BEOS__) # ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif # endif #endif @@ -93831,7 +93563,6 @@ typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; @@ -93844,24 +93575,24 @@ typedef uLong FAR uLongf; #ifdef STDC typedef void const *voidpc; typedef void FAR *voidpf; - typedef void *voidp; + typedef void *voidp; #else typedef Byte const *voidpc; typedef Byte FAR *voidpf; - typedef Byte *voidp; + typedef Byte *voidp; #endif -#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ # include /* for off_t */ -# include /* for SEEK_* and off_t */ +# include /* for SEEK_* and off_t */ # ifdef VMS -# include /* for off_t */ +# include /* for off_t */ # endif # define z_off_t off_t #endif #ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t @@ -93875,11 +93606,10 @@ typedef uLong FAR uLongf; #if defined(__MVS__) # define NO_vsnprintf # ifdef FAR -# undef FAR +# undef FAR # endif #endif -/* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) # pragma map(deflateInit_,"DEIN") # pragma map(deflateInit2_,"DEIN2") @@ -93906,1306 +93636,259 @@ extern "C" { #define ZLIB_VERSION "1.2.3" #define ZLIB_VERNUM 0x1230 -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. -*/ - typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ } gz_header; typedef gz_header FAR *gz_headerp; -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 +#define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -/* Allowed flush values; see deflate() and inflate() below for details */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. - */ -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 #define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ #define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - /* basic functions */ //ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). -*/ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumualte before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - the value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be - deallocated). -*/ - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) -*/ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, - Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() stop - if and when it gets to the next deflate block boundary. When decoding the - zlib or gzip format, this will cause inflate() to return immediately after - the header and before the first block. When doing a raw inflate, inflate() - will go ahead and process the first block, and will return when it gets to - the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 - if inflate() is currently decoding the last block in the deflate stream, - plus 128 if inflate() returned immediately after decoding an end-of-block - code or decoding the complete header up to just before the first byte of the - deflate stream. The end-of-block will not be indicated until all of the - uncompressed data from that block has been written to strm->next_out. The - number of unused bits may in general be greater than seven, except when - bit 7 of data_type is set, in which case the number of unused bits will be - less than eight. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster approach - may be used for the single inflate() call. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() will decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically. Any information - contained in the gzip header is not retained, so applications that need that - information should instead use raw inflate, see inflateInit2() below, or - inflateBack() and perform their own processing of the gzip header and - trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may then - call inflateSync() to look for a good compression block if a partial recovery - of the data is desired. -*/ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), - no header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as - Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy - parameter only affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately. Z_FIXED prevents the - use of dynamic Huffman codes, allowing for a simpler decoder for special - applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). -*/ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. In addition, the - current implementation of deflate will use at most the window size minus - 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ + const Bytef *dictionary, + uInt dictLength)); ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ + z_streamp source)); ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. -*/ + int level, + int strategy)); ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ + int good_length, + int max_lazy, + int nice_length, + int max_chain)); ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() - or deflateInit2(). This would be used to allocate an output buffer - for deflation in a single pass, and so would be called before deflate(). -*/ + uLong sourceLen)); ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the - bits leftover from a previous deflate stream when appending to it. As such, - this function can only be used for raw deflate, and must be used before the - first deflate() call after a deflateInit2() or deflateReset(). bits must be - less than or equal to 16, and that many of the least significant bits of - value will be inserted in the output. - - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ + int bits, + int value)); ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is - a crc32 instead of an adler32. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg - is set to null if there is no error message. inflateInit2 does not perform - any decompression apart from reading the zlib header if present: this will - be done by inflate(). (So next_in and avail_in may be modified, but next_out - and avail_out are unchanged.) -*/ + gz_headerp head)); ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ + const Bytef *dictionary, + uInt dictLength)); ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. -*/ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ + z_streamp source)); ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ + int bits, + int value)); ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK can be used to - force inflate() to return immediately after header processing is complete - and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When - any of extra, name, or comment are not Z_NULL and the respective field is - not present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not - be allocated, or Z_VERSION_ERROR if the version of the library does not - match the version of the header file. -*/ + gz_headerp head)); typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free - the allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects - only the raw deflate stream to decompress. This is different from the - normal behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format - error in the deflate stream (in which case strm->msg is set to indicate the - nature of the error), or Z_STREAM_ERROR if the stream was not properly - initialized. In the case of Z_BUF_ERROR, an input or output error can be - distinguished using strm->next_in which will be Z_NULL only if in() returned - an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to - out() returning non-zero. (in() will always be called before out(), so - strm->next_in is assured to be defined if out() returns non-zero.) Note - that inflateBack() cannot return Z_OK. -*/ + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ //ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - /* utility functions */ - -/* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. -*/ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least the value returned - by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ + const Bytef *source, uLong sourceLen)); ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ + const Bytef *source, uLong sourceLen, + int level)); ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before - a compress() or compress2() call to allocate the destination buffer. -*/ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. -*/ + const Bytef *source, uLong sourceLen)); typedef voidp gzFile; ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -/* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h", or 'R' for run-length encoding - as in "wb1R". (See the description of deflateInit2 for more information - about the strategy parameter.) - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. -*/ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). -*/ +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). The number of - uncompressed bytes written is limited to 4095. The caller should assure that - this limit is not exceeded. If it is exceeded, then gzprintf() will return - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() - because the secure snprintf() or vsnprintf() functions were not available. -*/ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. -*/ -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read again later. - Only one character of push-back is allowed. gzungetc() returns the - character pushed, or -1 on failure. gzungetc() will fail if a - character has been pushed but not read yet, or if c is -1. The pushed - character will be discarded if the stream is repositioned with gzseek() - or gzrewind(). -*/ +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. -*/ +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); -/* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -/* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns 1 if file is being read directly without decompression, otherwise - zero. -*/ -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). -*/ +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. -*/ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); -/* - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. -*/ + z_off_t len2)); ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is NULL, this function returns the required initial - value for the for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); -/* - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); + const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); + const char *version, int stream_size)); ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); + const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); + unsigned char FAR *window, + const char *version, + int stream_size)); #define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) #define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) #define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; /* hack for buggy compilers */ + struct internal_state {int dummy;}; /* hack for buggy compilers */ #endif -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); #ifdef __cplusplus } @@ -95229,152 +93912,152 @@ using namespace zlibNamespace; class GZIPCompressorHelper { public: - GZIPCompressorHelper (const int compressionLevel, const bool nowrap) - : data (0), - dataSize (0), - compLevel (compressionLevel), - strategy (0), - setParams (true), - streamIsValid (false), - finished (false), - shouldFinish (false) - { - zerostruct (stream); + GZIPCompressorHelper (const int compressionLevel, const bool nowrap) + : data (0), + dataSize (0), + compLevel (compressionLevel), + strategy (0), + setParams (true), + streamIsValid (false), + finished (false), + shouldFinish (false) + { + zerostruct (stream); - streamIsValid = (deflateInit2 (&stream, compLevel, Z_DEFLATED, - nowrap ? -MAX_WBITS : MAX_WBITS, - 8, strategy) == Z_OK); - } + streamIsValid = (deflateInit2 (&stream, compLevel, Z_DEFLATED, + nowrap ? -MAX_WBITS : MAX_WBITS, + 8, strategy) == Z_OK); + } - ~GZIPCompressorHelper() - { - if (streamIsValid) - deflateEnd (&stream); - } + ~GZIPCompressorHelper() + { + if (streamIsValid) + deflateEnd (&stream); + } - bool needsInput() const throw() - { - return dataSize <= 0; - } + bool needsInput() const throw() + { + return dataSize <= 0; + } - void setInput (uint8* const newData, const int size) throw() - { - data = newData; - dataSize = size; - } + void setInput (uint8* const newData, const int size) throw() + { + data = newData; + dataSize = size; + } - int doNextBlock (uint8* const dest, const int destSize) throw() - { - if (streamIsValid) - { - stream.next_in = data; - stream.next_out = dest; - stream.avail_in = dataSize; - stream.avail_out = destSize; + int doNextBlock (uint8* const dest, const int destSize) throw() + { + if (streamIsValid) + { + stream.next_in = data; + stream.next_out = dest; + stream.avail_in = dataSize; + stream.avail_out = destSize; - const int result = setParams ? deflateParams (&stream, compLevel, strategy) - : deflate (&stream, shouldFinish ? Z_FINISH : Z_NO_FLUSH); + const int result = setParams ? deflateParams (&stream, compLevel, strategy) + : deflate (&stream, shouldFinish ? Z_FINISH : Z_NO_FLUSH); - setParams = false; + setParams = false; - switch (result) - { - case Z_STREAM_END: - finished = true; - // Deliberate fall-through.. - case Z_OK: - data += dataSize - stream.avail_in; - dataSize = stream.avail_in; + switch (result) + { + case Z_STREAM_END: + finished = true; + // Deliberate fall-through.. + case Z_OK: + data += dataSize - stream.avail_in; + dataSize = stream.avail_in; - return destSize - stream.avail_out; + return destSize - stream.avail_out; - default: - break; - } - } + default: + break; + } + } - return 0; - } + return 0; + } private: - z_stream stream; - uint8* data; - int dataSize, compLevel, strategy; - bool setParams, streamIsValid; + z_stream stream; + uint8* data; + int dataSize, compLevel, strategy; + bool setParams, streamIsValid; public: - bool finished, shouldFinish; + bool finished, shouldFinish; }; const int gzipCompBufferSize = 32768; GZIPCompressorOutputStream::GZIPCompressorOutputStream (OutputStream* const destStream_, - int compressionLevel, - const bool deleteDestStream, - const bool noWrap) + int compressionLevel, + const bool deleteDestStream, + const bool noWrap) : destStream (destStream_), - streamToDelete (deleteDestStream ? destStream_ : 0), - buffer (gzipCompBufferSize) + streamToDelete (deleteDestStream ? destStream_ : 0), + buffer (gzipCompBufferSize) { - if (compressionLevel < 1 || compressionLevel > 9) - compressionLevel = -1; + if (compressionLevel < 1 || compressionLevel > 9) + compressionLevel = -1; - helper = new GZIPCompressorHelper (compressionLevel, noWrap); + helper = new GZIPCompressorHelper (compressionLevel, noWrap); } GZIPCompressorOutputStream::~GZIPCompressorOutputStream() { - flush(); + flush(); } void GZIPCompressorOutputStream::flush() { - if (! helper->finished) - { - helper->shouldFinish = true; + if (! helper->finished) + { + helper->shouldFinish = true; - while (! helper->finished) - doNextBlock(); - } + while (! helper->finished) + doNextBlock(); + } - destStream->flush(); + destStream->flush(); } bool GZIPCompressorOutputStream::write (const void* destBuffer, int howMany) { - if (! helper->finished) - { - helper->setInput ((uint8*) destBuffer, howMany); + if (! helper->finished) + { + helper->setInput ((uint8*) destBuffer, howMany); - while (! helper->needsInput()) - { - if (! doNextBlock()) - return false; - } - } + while (! helper->needsInput()) + { + if (! doNextBlock()) + return false; + } + } - return true; + return true; } bool GZIPCompressorOutputStream::doNextBlock() { - const int len = helper->doNextBlock (buffer, gzipCompBufferSize); + const int len = helper->doNextBlock (buffer, gzipCompBufferSize); - if (len > 0) - return destStream->write (buffer, len); - else - return true; + if (len > 0) + return destStream->write (buffer, len); + else + return true; } int64 GZIPCompressorOutputStream::getPosition() { - return destStream->getPosition(); + return destStream->getPosition(); } bool GZIPCompressorOutputStream::setPosition (int64 /*newPosition*/) { - jassertfalse // can't do it! - return false; + jassertfalse // can't do it! + return false; } END_JUCE_NAMESPACE @@ -95392,19 +94075,17 @@ namespace zlibNamespace #if JUCE_INCLUDE_ZLIB_CODE extern "C" { - #undef OS_CODE - #undef fdopen - #define ZLIB_INTERNAL - #define NO_DUMMY_DECL + #undef OS_CODE + #undef fdopen + #define ZLIB_INTERNAL + #define NO_DUMMY_DECL /********* Start of inlined file: adler32.c *********/ -/* @(#) $Id: adler32.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */ #define ZLIB_INTERNAL -#define BASE 65521UL /* largest prime smaller than 65536 */ +#define BASE 65521UL /* largest prime smaller than 65536 */ #define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); @@ -95412,226 +94093,181 @@ namespace zlibNamespace #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); -/* use NO_DIVIDE if your processor does not do division in hardware */ #ifdef NO_DIVIDE # define MOD(a) \ - do { \ - if (a >= (BASE << 16)) a -= (BASE << 16); \ - if (a >= (BASE << 15)) a -= (BASE << 15); \ - if (a >= (BASE << 14)) a -= (BASE << 14); \ - if (a >= (BASE << 13)) a -= (BASE << 13); \ - if (a >= (BASE << 12)) a -= (BASE << 12); \ - if (a >= (BASE << 11)) a -= (BASE << 11); \ - if (a >= (BASE << 10)) a -= (BASE << 10); \ - if (a >= (BASE << 9)) a -= (BASE << 9); \ - if (a >= (BASE << 8)) a -= (BASE << 8); \ - if (a >= (BASE << 7)) a -= (BASE << 7); \ - if (a >= (BASE << 6)) a -= (BASE << 6); \ - if (a >= (BASE << 5)) a -= (BASE << 5); \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ - if (a >= BASE) a -= BASE; \ - } while (0) + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) # define MOD4(a) \ - do { \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ - if (a >= BASE) a -= BASE; \ - } while (0) + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) #else # define MOD(a) a %= BASE # define MOD4(a) a %= BASE #endif -/* ========================================================================= */ uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) { - unsigned long sum2; - unsigned n; + unsigned long sum2; + unsigned n; - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; - /* in case user likes doing a byte at a time, keep it fast */ - if (len == 1) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == Z_NULL) - return 1L; + if (buf == Z_NULL) + return 1L; - /* in case short lengths are provided, keep it somewhat fast */ - if (len < 16) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD4(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } - /* do length NMAX blocks -- requires just one modulo operation */ - while (len >= NMAX) { - len -= NMAX; - n = NMAX / 16; /* NMAX is divisible by 16 */ - do { - DO16(buf); /* 16 sums unrolled */ - buf += 16; - } while (--n); - MOD(adler); - MOD(sum2); - } + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } - /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ - while (len >= 16) { - len -= 16; - DO16(buf); - buf += 16; - } - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - } + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } - /* return recombined sums */ - return adler | (sum2 << 16); + return adler | (sum2 << 16); } -/* ========================================================================= */ uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) { - unsigned long sum1; - unsigned long sum2; - unsigned rem; + unsigned long sum1; + unsigned long sum2; + unsigned rem; - /* the derivation of this formula is left as an exercise for the reader */ - rem = (unsigned)(len2 % BASE); - sum1 = adler1 & 0xffff; - sum2 = rem * sum1; - MOD(sum2); - sum1 += (adler2 & 0xffff) + BASE - 1; - sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; - if (sum1 > BASE) sum1 -= BASE; - if (sum1 > BASE) sum1 -= BASE; - if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); - if (sum2 > BASE) sum2 -= BASE; - return sum1 | (sum2 << 16); + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 > BASE) sum1 -= BASE; + if (sum1 > BASE) sum1 -= BASE; + if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 > BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); } /********* End of inlined file: adler32.c *********/ /********* Start of inlined file: compress.c *********/ -/* @(#) $Id: compress.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */ #define ZLIB_INTERNAL -/* =========================================================================== - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ int ZEXPORT compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, - uLong sourceLen, int level) + uLong sourceLen, int level) { - z_stream stream; - int err; + z_stream stream; + int err; - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; #ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; #endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; - err = deflateInit(&stream, level); - if (err != Z_OK) return err; + err = deflateInit(&stream, level); + if (err != Z_OK) return err; - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; - err = deflateEnd(&stream); - return err; + err = deflateEnd(&stream); + return err; } -/* =========================================================================== - */ int ZEXPORT compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { - return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } -/* =========================================================================== - If the default memLevel or windowBits for deflateInit() is changed, then - this function needs to be updated. - */ uLong ZEXPORT compressBound (uLong sourceLen) { - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; } /********* End of inlined file: compress.c *********/ - #undef DO1 - #undef DO8 + #undef DO1 + #undef DO8 /********* Start of inlined file: crc32.c *********/ -/* @(#) $Id: crc32.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */ - -/* - Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore - protection on the static variables used to control the first-use generation - of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should - first call get_crc_table() to initialize the tables before allowing more than - one thread to use crc32(). - */ #ifdef MAKECRCH # include # ifndef DYNAMIC_CRC_TABLE -# define DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE # endif /* !DYNAMIC_CRC_TABLE */ #endif /* MAKECRCH */ /********* Start of inlined file: zutil.h *********/ -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id: zutil.h,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */ #ifndef ZUTIL_H #define ZUTIL_H @@ -95640,31 +94276,25 @@ uLong ZEXPORT compressBound (uLong sourceLen) #ifdef STDC # ifndef _WIN32_WCE -# include +# include # endif # include # include #endif #ifdef NO_ERRNO_H # ifdef _WIN32_WCE - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. We rename it to - * avoid conflict with other libraries that use the same workaround. - */ -# define errno z_errno +# define errno z_errno # endif - extern int errno; + extern int errno; #else # ifndef _WIN32_WCE -# include +# include # endif #endif #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ typedef unsigned char uch; typedef uch FAR uchf; @@ -95673,53 +94303,42 @@ typedef ush FAR ushf; typedef unsigned long ulg; extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ return (strm->msg = (char*)ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif -/* default memLevel */ #define STORED_BLOCK 0 #define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ +#define DYN_TREES 2 #define MIN_MATCH 3 #define MAX_MATCH 258 -/* The minimum and maximum match lengths */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - /* target dependencies */ - #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 # if defined(__TURBOC__) || defined(__BORLANDC__) -# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include -# endif +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif # else /* MSC or DJGPP */ -# include +# include # endif #endif @@ -95730,7 +94349,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #if defined(VAXC) || defined(VMS) # define OS_CODE 0x02 # define F_OPEN(name, mode) \ - fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif #if defined(ATARI) || defined(atarist) @@ -95740,18 +94359,18 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #ifdef OS2 # define OS_CODE 0x06 # ifdef M_I86 - #include + #include # endif #endif #if defined(MACOS) || TARGET_OS_MAC # define OS_CODE 0x07 # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fdopen */ +# include /* for fdopen */ # else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif # endif #endif @@ -95761,7 +94380,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #ifdef WIN32 # ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ -# define OS_CODE 0x0b +# define OS_CODE 0x0b # endif #endif @@ -95775,18 +94394,16 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #if (defined(_MSC_VER) && (_MSC_VER > 600)) # if defined(_WIN32_WCE) -# define fdopen(fd,mode) NULL /* No fdopen() */ -# ifndef _PTRDIFF_T_DEFINED - typedef int ptrdiff_t; -# define _PTRDIFF_T_DEFINED -# endif +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif # else -# define fdopen(fd,type) _fdopen(fd,type) +# define fdopen(fd,type) _fdopen(fd,type) # endif #endif - /* common defaults */ - #ifndef OS_CODE # define OS_CODE 0x03 /* assume Unix */ #endif @@ -95795,35 +94412,30 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define F_OPEN(name, mode) fopen((name), (mode)) #endif - /* functions */ - #if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) # ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF +# define HAVE_VSNPRINTF # endif #endif #if defined(__CYGWIN__) # ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF +# define HAVE_VSNPRINTF # endif #endif #ifndef HAVE_VSNPRINTF # ifdef MSDOS - /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf +# define NO_vsnprintf # endif # ifdef __TURBOC__ -# define NO_vsnprintf +# define NO_vsnprintf # endif # ifdef WIN32 - /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# define vsnprintf _vsnprintf -# endif +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif # endif # ifdef __SASC -# define NO_vsnprintf +# define NO_vsnprintf # endif #endif #ifdef VMS @@ -95834,10 +94446,6 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) - /* Use our own functions for small and medium model with MSC <= 5.0. - * You may have to use the same strategy for Borland C (untested). - * The __SC__ check is for Symantec. - */ # define NO_MEMCPY #endif #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) @@ -95845,13 +94453,13 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif #ifdef HAVE_MEMCPY # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -# define zmemcpy _fmemcpy -# define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, len) +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) # else -# define zmemcpy memcpy -# define zmemcmp memcmp -# define zmemzero(dest, len) memset(dest, 0, len) +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) # endif #else extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); @@ -95859,11 +94467,10 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ extern void zmemzero OF((Bytef* dest, uInt len)); #endif -/* Diagnostic functions */ #ifdef DEBUG # include extern int z_verbose; - extern void z_error OF((const char *m)); + extern void z_error OF((const char *m)); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} @@ -95883,54 +94490,49 @@ voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); void zcfree OF((voidpf opaque, voidpf ptr)); #define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) + (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} #endif /* ZUTIL_H */ /********* End of inlined file: zutil.h *********/ - /* for STDC and FAR definitions */ - #define local static -/* Find a four-byte integer type for crc32_little() and crc32_big(). */ #ifndef NOBYFOUR -# ifdef STDC /* need ANSI C limits.h to determine sizes */ -# include -# define BYFOUR -# if (UINT_MAX == 0xffffffffUL) - typedef unsigned int u4; -# else -# if (ULONG_MAX == 0xffffffffUL) - typedef unsigned long u4; -# else -# if (USHRT_MAX == 0xffffffffUL) - typedef unsigned short u4; -# else -# undef BYFOUR /* can't find a four-byte integer type! */ -# endif -# endif -# endif +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif # endif /* STDC */ #endif /* !NOBYFOUR */ -/* Definitions for doing the crc four data bytes at a time. */ #ifdef BYFOUR # define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ - (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); + const unsigned char FAR *, unsigned)); local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); + const unsigned char FAR *, unsigned)); # define TBLS 8 #else # define TBLS 1 #endif /* BYFOUR */ -/* Local functions for crc concatenation */ local unsigned long gf2_matrix_times OF((unsigned long *mat, - unsigned long vec)); + unsigned long vec)); local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); #ifdef DYNAMIC_CRC_TABLE @@ -95941,561 +94543,522 @@ local void make_crc_table OF((void)); #ifdef MAKECRCH local void write_table OF((FILE *, const unsigned long FAR *)); #endif /* MAKECRCH */ -/* - Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The first table is simply the CRC of all possible eight bit values. This is - all the information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. -*/ local void make_crc_table() { - unsigned long c; - int n, k; - unsigned long poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static volatile int first = 1; /* flag to limit concurrent making */ - static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - /* See if another task is already doing this (not thread-safe, but better - than nothing -- significantly reduces duration of vulnerability in - case the advice about DYNAMIC_CRC_TABLE is ignored) */ - if (first) { - first = 0; + if (first) { + first = 0; - /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0UL; - for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) - poly |= 1UL << (31 - p[n]); + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (unsigned long)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; - } + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } #ifdef BYFOUR - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = REV(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = REV(c); - } - } + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } #endif /* BYFOUR */ - crc_table_empty = 0; - } - else { /* not first */ - /* wait for the other guy to finish (not efficient, but rare) */ - while (crc_table_empty) - ; - } + crc_table_empty = 0; + } + else { /* not first */ + while (crc_table_empty) + ; + } #ifdef MAKECRCH - /* write out CRC tables to crc32.h */ - { - FILE *out; + { + FILE *out; - out = fopen("crc32.h", "w"); - if (out == NULL) return; - fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); - fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const unsigned long FAR "); - fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); - write_table(out, crc_table[0]); + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); # ifdef BYFOUR - fprintf(out, "#ifdef BYFOUR\n"); - for (k = 1; k < 8; k++) { - fprintf(out, " },\n {\n"); - write_table(out, crc_table[k]); - } - fprintf(out, "#endif\n"); + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); # endif /* BYFOUR */ - fprintf(out, " }\n};\n"); - fclose(out); - } + fprintf(out, " }\n};\n"); + fclose(out); + } #endif /* MAKECRCH */ } #ifdef MAKECRCH local void write_table(out, table) - FILE *out; - const unsigned long FAR *table; + FILE *out; + const unsigned long FAR *table; { - int n; + int n; - for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], - n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); } #endif /* MAKECRCH */ #else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables of CRC-32s of all single-byte values, made by make_crc_table(). - */ /********* Start of inlined file: crc32.h *********/ local const unsigned long FAR crc_table[TBLS][256] = { { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL #ifdef BYFOUR }, { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL }, { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL }, { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL }, { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL }, { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL }, { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL }, { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL #endif } }; @@ -96503,326 +95066,235 @@ local const unsigned long FAR crc_table[TBLS][256] = #endif /* DYNAMIC_CRC_TABLE */ -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ const unsigned long FAR * ZEXPORT get_crc_table() { #ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); + if (crc_table_empty) + make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ - return (const unsigned long FAR *)crc_table; + return (const unsigned long FAR *)crc_table; } -/* ========================================================================= */ #define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 -/* ========================================================================= */ unsigned long ZEXPORT crc32 (unsigned long crc, const unsigned char FAR *buf, unsigned len) { - if (buf == Z_NULL) return 0UL; + if (buf == Z_NULL) return 0UL; #ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); + if (crc_table_empty) + make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ #ifdef BYFOUR - if (sizeof(void *) == sizeof(ptrdiff_t)) { - u4 endian; + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; - endian = 1; - if (*((unsigned char *)(&endian))) - return crc32_little(crc, buf, len); - else - return crc32_big(crc, buf, len); - } + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } #endif /* BYFOUR */ - crc = crc ^ 0xffffffffUL; - while (len >= 8) { - DO8; - len -= 8; - } - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffffUL; + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; } #ifdef BYFOUR -/* ========================================================================= */ #define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 -/* ========================================================================= */ local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf, unsigned len) { - register u4 c; - register const u4 FAR *buf4; + register u4 c; + register const u4 FAR *buf4; - c = (u4)crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } - buf4 = (const u4 FAR *)(const void FAR *)buf; - while (len >= 32) { - DOLIT32; - len -= 32; - } - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return (unsigned long)c; + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; } -/* ========================================================================= */ #define DOBIG4 c ^= *++buf4; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 -/* ========================================================================= */ local unsigned long crc32_big (unsigned long crc, const unsigned char FAR *buf, unsigned len) { - register u4 c; - register const u4 FAR *buf4; + register u4 c; + register const u4 FAR *buf4; - c = REV((u4)crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; - } + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } - buf4 = (const u4 FAR *)(const void FAR *)buf; - buf4--; - while (len >= 32) { - DOBIG32; - len -= 32; - } - while (len >= 4) { - DOBIG4; - len -= 4; - } - buf4++; - buf = (const unsigned char FAR *)buf4; + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return (unsigned long)(REV(c)); + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); } #endif /* BYFOUR */ -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ -/* ========================================================================= */ local unsigned long gf2_matrix_times (unsigned long *mat, unsigned long vec) { - unsigned long sum; + unsigned long sum; - sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; } -/* ========================================================================= */ local void gf2_matrix_square (unsigned long *square, unsigned long *mat) { - int n; + int n; - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); } -/* ========================================================================= */ uLong ZEXPORT crc32_combine (uLong crc1, uLong crc2, z_off_t len2) { - int n; - unsigned long row; - unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ - unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ - /* degenerate case */ - if (len2 == 0) - return crc1; + if (len2 == 0) + return crc1; - /* put operator for one zero bit in odd */ - odd[0] = 0xedb88320L; /* CRC-32 polynomial */ - row = 1; - for (n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } + odd[0] = 0xedb88320L; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } - /* put operator for two zero bits in even */ - gf2_matrix_square(even, odd); + gf2_matrix_square(even, odd); - /* put operator for four zero bits in odd */ - gf2_matrix_square(odd, even); + gf2_matrix_square(odd, even); - /* apply len2 zeros to crc1 (first square will put the operator for one - zero byte, eight zero bits, in even) */ - do { - /* apply zeros operator for this bit of len2 */ - gf2_matrix_square(even, odd); - if (len2 & 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; + do { + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; - /* if no more bits set, then done */ - if (len2 == 0) - break; + if (len2 == 0) + break; - /* another iteration of the loop with odd and even swapped */ - gf2_matrix_square(odd, even); - if (len2 & 1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; - /* if no more bits set, then done */ - } while (len2 != 0); + } while (len2 != 0); - /* return combined crc */ - crc1 ^= crc2; - return crc1; + crc1 ^= crc2; + return crc1; } /********* End of inlined file: crc32.c *********/ /********* Start of inlined file: deflate.c *********/ -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://www.ietf.org/rfc/rfc1951.txt - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -/* @(#) $Id: deflate.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */ /********* Start of inlined file: deflate.h *********/ -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id: deflate.h,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */ #ifndef DEFLATE_H #define DEFLATE_H -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer creation by deflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip encoding - should be left enabled. */ #ifndef NO_GZIP # define GZIP #endif #define NO_DUMMY_DECL -/* =========================================================================== - * Internal compression state. - */ - #define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ #define LITERALS 256 -/* number of literal bytes 0..255 */ #define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ #define D_CODES 30 -/* number of distance codes */ #define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ #define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ #define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ -#define INIT_STATE 42 +#define INIT_STATE 42 #define EXTRA_STATE 69 -#define NAME_STATE 73 +#define NAME_STATE 73 #define COMMENT_STATE 91 #define HCRC_STATE 103 #define BUSY_STATE 113 #define FINISH_STATE 666 -/* Stream status */ -/* Data structure describing a single value and its code string. */ typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; } FAR ct_data; #define Freq fc.freq @@ -96833,223 +95305,127 @@ typedef struct ct_data_s { typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; typedef Pos FAR Posf; typedef unsigned IPos; -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Bytef *pending_buf; /* output still pending */ - ulg pending_buf_size; /* size of pending_buf */ - Bytef *pending_out; /* next pending byte to output to the stream */ - uInt pending; /* nb of bytes in the pending buffer */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - gz_headerp gzhead; /* gzip header information to write */ - uInt gzindex; /* where in extra, name, or comment */ - Byte method; /* STORED (for zip only) or DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ - /* used by deflate.c: */ + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ + Bytef *window; - Bytef *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ + ulg window_size; - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ + Posf *prev; - Posf *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ + Posf *head; /* Heads of the hash chains or NIL. */ - Posf *head; /* Heads of the hash chains or NIL. */ + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ + uInt hash_shift; - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ + long block_start; - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ + uInt prev_length; - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ + uInt max_chain_length; - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ + uInt max_lazy_match; # define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ - uInt good_match; - /* Use a faster search when the previous match is longer than this */ + uInt good_match; - int nice_match; /* Stop searching when current match exceeds this */ + int nice_match; /* Stop searching when current match exceeds this */ - /* used by trees.c: */ - /* Didn't use ct_data typedef below to supress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ + ush bl_count[MAX_BITS+1]; - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ + uch depth[2*L_CODES+1]; - uchf *l_buf; /* buffer for literals or lengths */ + uchf *l_buf; /* buffer for literals or lengths */ - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ + uInt lit_bufsize; - uInt last_lit; /* running index in l_buf */ + uInt last_lit; /* running index in l_buf */ - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ + ushf *d_buf; - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - uInt matches; /* number of string matches in current block */ - int last_eob_len; /* bit length of EOB code for last block */ + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ #ifdef DEBUG - ulg compressed_len; /* total bit length of compressed file mod 2^32 */ - ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ + ush bi_buf; + int bi_valid; } FAR deflate_state; -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ #define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - /* in trees.c */ -void _tr_init OF((deflate_state *s)); -int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); -void _tr_align OF((deflate_state *s)); + int eof)); +void _tr_align OF((deflate_state *s)); void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); + int eof)); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. _dist_code[256] and _dist_code[257] are never - * used. - */ #ifndef DEBUG -/* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) extern uch _length_code[]; @@ -97061,25 +95437,25 @@ void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ - s->dyn_ltree[cc].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (length); \ - ush dist = (distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ - dist--; \ - s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ - s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ } #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ - flush = _tr_tally(s, distance, length) + flush = _tr_tally(s, distance, length) #endif #endif /* DEFLATE_H */ @@ -97087,40 +95463,30 @@ void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, const char deflate_copyright[] = " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ -/* =========================================================================== - * Function prototypes. - */ typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ } block_state; typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -/* Compression function. Returns the block state after the call. */ -local void fill_window OF((deflate_state *s)); +local void fill_window OF((deflate_state *s)); local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); #ifndef FASTEST local block_state deflate_slow OF((deflate_state *s, int flush)); #endif -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifndef FASTEST #ifdef ASMV - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); #else local uInt longest_match OF((deflate_state *s, IPos cur_match)); #endif @@ -97129,34 +95495,20 @@ local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); #ifdef DEBUG local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); + int length)); #endif -/* =========================================================================== - * Local data - */ - #define NIL 0 -/* Tail of hash chains */ #ifndef TOO_FAR # define TOO_FAR 4096 #endif -/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ typedef struct config_s { ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ ush nice_length; /* quit search above this match length */ ush max_chain; compress_func func; @@ -97164,1548 +95516,1192 @@ typedef struct config_s { #ifdef FASTEST local const config configuration_table[2] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ + {0, 0, 0, 0, deflate_stored}, /* store only */ + {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ #else local const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, + {0, 0, 0, 0, deflate_stored}, /* store only */ + {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ + {4, 5, 16, 8, deflate_fast}, + {4, 6, 32, 32, deflate_fast}, -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ + {4, 4, 16, 16, deflate_slow}, /* lazy matches */ + {8, 16, 32, 32, deflate_slow}, + {8, 16, 128, 128, deflate_slow}, + {8, 32, 128, 256, deflate_slow}, + {32, 128, 258, 1024, deflate_slow}, + {32, 258, 258, 4096, deflate_slow}}; /* max compression */ #endif -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - #define EQUAL 0 -/* result of memcmp for equal strings */ #ifndef NO_DUMMY_DECL struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ #endif -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * If this file is compiled with -DFASTEST, the compression level is forced - * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). - */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) #else #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) #endif -/* =========================================================================== - * Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ #define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); -/* ========================================================================= */ int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size) { - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); } -/* ========================================================================= */ int ZEXPORT deflateInit2_ (z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size) { - deflate_state *s; - int wrap = 1; - static const char my_version[] = ZLIB_VERSION; + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ + ushf *overlay; - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; - strm->msg = Z_NULL; - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; #ifdef FASTEST - if (level != 0) level = 1; + if (level != 0) level = 1; #else - if (level == Z_DEFAULT_COMPRESSION) level = 6; + if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } #ifdef GZIP - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } #endif - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state FAR *)s; - s->strm = strm; + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; - s->wrap = wrap; - s->gzhead = Z_NULL; - s->w_bits = windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; - s->hash_bits = memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - s->status = FINISH_STATE; - strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; - return deflateReset(strm); + return deflateReset(strm); } -/* ========================================================================= */ int ZEXPORT deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength) { - deflate_state *s; - uInt length = dictLength; - uInt n; - IPos hash_head = 0; + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || - strm->state->wrap == 2 || - (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) - return Z_STREAM_ERROR; + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; - s = strm->state; - if (s->wrap) - strm->adler = adler32(strm->adler, dictionary, dictLength); + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); - if (length < MIN_MATCH) return Z_OK; - if (length > MAX_DIST(s)) { - length = MAX_DIST(s); - dictionary += dictLength - length; /* use the tail of the dictionary */ - } - zmemcpy(s->window, dictionary, length); - s->strstart = length; - s->block_start = (long)length; + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; - /* Insert all strings in the hash table (except for the last two bytes). - * s->lookahead stays null, so s->ins_h will be recomputed at the next - * call of fill_window. - */ - s->ins_h = s->window[0]; - UPDATE_HASH(s, s->ins_h, s->window[1]); - for (n = 0; n <= length - MIN_MATCH; n++) { - INSERT_STRING(s, n, hash_head); - } - if (hash_head) hash_head = 0; /* to make compiler happy */ - return Z_OK; + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; } -/* ========================================================================= */ int ZEXPORT deflateReset (z_streamp strm) { - deflate_state *s; + deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { - return Z_STREAM_ERROR; - } + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; - if (s->wrap < 0) { - s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ - } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; - strm->adler = + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = #ifdef GZIP - s->wrap == 2 ? crc32(0L, Z_NULL, 0) : + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif - adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; - _tr_init(s); - lm_init(s); + _tr_init(s); + lm_init(s); - return Z_OK; + return Z_OK; } -/* ========================================================================= */ int ZEXPORT deflateSetHeader (z_streamp strm, gz_headerp head) { - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; - strm->state->gzhead = head; - return Z_OK; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; } -/* ========================================================================= */ int ZEXPORT deflatePrime (z_streamp strm, int bits, int value) { - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - strm->state->bi_valid = bits; - strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); - return Z_OK; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; } -/* ========================================================================= */ int ZEXPORT deflateParams (z_streamp strm, int level, int strategy) { - deflate_state *s; - compress_func func; - int err = Z_OK; + deflate_state *s; + compress_func func; + int err = Z_OK; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; #ifdef FASTEST - if (level != 0) level = 1; + if (level != 0) level = 1; #else - if (level == Z_DEFAULT_COMPRESSION) level = 6; + if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; - if (func != configuration_table[level].func && strm->total_in != 0) { - /* Flush the last buffer: */ - err = deflate(strm, Z_PARTIAL_FLUSH); - } - if (s->level != level) { - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return err; + if (func != configuration_table[level].func && strm->total_in != 0) { + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; } -/* ========================================================================= */ int ZEXPORT deflateTune (z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain) { - deflate_state *s; + deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; - s->nice_match = nice_length; - s->max_chain_length = max_chain; - return Z_OK; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; } -/* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. - * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. - * - * This function could be more sophisticated to provide closer upper bounds - * for every combination of windowBits and memLevel, as well as wrap. - * But even the conservative upper bound of about 14% expansion does not - * seem onerous for output buffer allocation. - */ uLong ZEXPORT deflateBound (z_streamp strm, uLong sourceLen) { - deflate_state *s; - uLong destLen; + deflate_state *s; + uLong destLen; - /* conservative upper bound */ - destLen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; + destLen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; - /* if can't get parameters, return conservative bound */ - if (strm == Z_NULL || strm->state == Z_NULL) - return destLen; + if (strm == Z_NULL || strm->state == Z_NULL) + return destLen; - /* if not default parameters, return conservative bound */ - s = strm->state; - if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return destLen; + s = strm->state; + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return destLen; - /* default settings: return tight bound for that case */ - return compressBound(sourceLen); + return compressBound(sourceLen); } -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ local void putShortMSB (deflate_state *s, uInt b) { - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); } -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). - */ local void flush_pending (z_streamp strm) { - unsigned len = strm->state->pending; + unsigned len = strm->state->pending; - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; - zmemcpy(strm->next_out, strm->state->pending_out, len); - strm->next_out += len; - strm->state->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - strm->state->pending -= len; - if (strm->state->pending == 0) { - strm->state->pending_out = strm->state->pending_buf; - } + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } } -/* ========================================================================= */ int ZEXPORT deflate (z_streamp strm, int flush) { - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_FINISH || flush < 0) { - return Z_STREAM_ERROR; - } - s = strm->state; + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; - if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - s->strm = strm; /* just in case */ - old_flush = s->last_flush; - s->last_flush = flush; + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; - /* Write the header */ - if (s->status == INIT_STATE) { + if (s->status == INIT_STATE) { #ifdef GZIP - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - else + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else #endif - { - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); - s->status = BUSY_STATE; - putShortMSB(s, header); + s->status = BUSY_STATE; + putShortMSB(s, header); - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - } - } + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } #ifdef GZIP - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; - } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; - } - } - else - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } - } - else - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; - } - else - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) - flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - } - } - else - s->status = BUSY_STATE; - } + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } #endif - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; + return Z_OK; + } - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm->avail_in == 0 && flush <= old_flush && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; - bstate = (*(configuration_table[s->level].func))(s, flush); + bstate = (*(configuration_table[s->level].func))(s, flush); - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - Assert(strm->avail_out > 0, "bug2"); + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); - if (flush != Z_FINISH) return Z_OK; - if (s->wrap <= 0) return Z_STREAM_END; + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; - /* Write the trailer */ #ifdef GZIP - if (s->wrap == 2) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); - put_byte(s, (Byte)(strm->total_in & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); - } - else + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else #endif - { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; } -/* ========================================================================= */ int ZEXPORT deflateEnd (z_streamp strm) { - int status; + int status; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); - ZFREE(strm, strm->state); - strm->state = Z_NULL; + ZFREE(strm, strm->state); + strm->state = Z_NULL; - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } -/* ========================================================================= - * Copy the source state to the destination state. - * To simplify the source, this is not supported for 16-bit MSDOS (which - * doesn't have enough memory anyway to duplicate compression states). - */ int ZEXPORT deflateCopy (z_streamp dest, z_streamp source) { #ifdef MAXSEG_64K - return Z_STREAM_ERROR; + return Z_STREAM_ERROR; #else - deflate_state *ds; - deflate_state *ss; - ushf *overlay; + deflate_state *ds; + deflate_state *ss; + ushf *overlay; - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { - return Z_STREAM_ERROR; - } + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } - ss = source->state; + ss = source->state; - zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(dest, source, sizeof(z_stream)); - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state FAR *) ds; - zmemcpy(ds, ss, sizeof(deflate_state)); - ds->strm = dest; + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; - ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); - ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; - return Z_OK; + return Z_OK; #endif /* MAXSEG_64K */ } -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ local int read_buf (z_streamp strm, Bytef *buf, unsigned size) { - unsigned len = strm->avail_in; + unsigned len = strm->avail_in; - if (len > size) len = size; - if (len == 0) return 0; + if (len > size) len = size; + if (len == 0) return 0; - strm->avail_in -= len; + strm->avail_in -= len; - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, strm->next_in, len); - } + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } #ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, strm->next_in, len); - } + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } #endif - zmemcpy(buf, strm->next_in, len); - strm->next_in += len; - strm->total_in += len; + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; - return (int)len; + return (int)len; } -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ local void lm_init (deflate_state *s) { - s->window_size = (ulg)2L*s->w_size; + s->window_size = (ulg)2L*s->w_size; - CLEAR_HASH(s); + CLEAR_HASH(s); - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; #ifndef FASTEST #ifdef ASMV - match_init(); /* initialize the asm code */ + match_init(); /* initialize the asm code */ #endif #endif } #ifndef FASTEST -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ #ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ local uInt longest_match(deflate_state *s, IPos cur_match) { - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Posf *prev = s->prev; - uInt wmask = s->w_mask; + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + Posf *prev = s->prev; + uInt wmask = s->w_mask; #ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); #else - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; - register Byte scan_end = scan[best_len]; + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; #endif - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ushf*)(match+best_len-1) != scan_end || - *(ushf*)match != scan_start) continue; + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - Assert(scan[2] == match[2], "scan[2]?"); - scan++, match++; - do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - if (*scan == *match) scan++; + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; #endif /* UNALIGNED_OK */ - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; #ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); + scan_end = *(ushf*)(scan+best_len-1); #else - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; #endif - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); - if ((uInt)best_len <= s->lookahead) return (uInt)best_len; - return s->lookahead; + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; } #endif /* ASMV */ #endif /* FASTEST */ -/* --------------------------------------------------------------------------- - * Optimized version for level == 1 or strategy == Z_RLE only - */ local uInt longest_match_fast (deflate_state *s, IPos cur_match) { - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - Assert(cur_match < s->strstart, "no future"); + Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; + match = s->window + cur_match; - /* Return failure if the match length is less than 2: - */ - if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match += 2; - Assert(*scan == *match, "match[2]?"); + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - len = MAX_MATCH - (int)(strend - scan); + len = MAX_MATCH - (int)(strend - scan); - if (len < MIN_MATCH) return MIN_MATCH - 1; + if (len < MIN_MATCH) return MIN_MATCH - 1; - s->match_start = cur_match; - return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; } #ifdef DEBUG -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ local void check_match(deflate_state *s, IPos start, IPos match, int length) { - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } } #else # define check_match(s, start, match, length) #endif /* DEBUG */ -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ local void fill_window (deflate_state *s) { - register unsigned n, m; - register Posf *p; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } + } else if (more == (unsigned)(-1)) { + more--; + } + } - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize+MAX_DIST(s)) { + if (s->strstart >= wsize+MAX_DIST(s)) { - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - /* %%% avoid this when Z_RLE */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); - n = wsize; + n = wsize; #ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); #endif - more += wsize; - } - if (s->strm->avail_in == 0) return; + more += wsize; + } + if (s->strm->avail_in == 0) return; - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); + Assert(more >= 2, "more < 2"); - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; - /* Initialize the hash value now that we have some input: */ - if (s->lookahead >= MIN_MATCH) { - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times + Call UPDATE_HASH() MIN_MATCH-3 more times #endif - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ + } - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); } -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ #define FLUSH_BLOCK_ONLY(s, eof) { \ _tr_flush_block(s, (s->block_start >= 0L ? \ - (charf *)&s->window[(unsigned)s->block_start] : \ - (charf *)Z_NULL), \ - (ulg)((long)s->strstart - s->block_start), \ - (eof)); \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ s->block_start = s->strstart; \ flush_pending(s->strm); \ Tracev((stderr,"[FLUSH]")); \ } -/* Same but force premature exit if necessary. */ #define FLUSH_BLOCK(s, eof) { \ FLUSH_BLOCK_ONLY(s, eof); \ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ } -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ local block_state deflate_stored(deflate_state *s, int flush) { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - ulg max_block_size = 0xffff; - ulg max_start; + ulg max_block_size = 0xffff; + ulg max_start; - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { + for (;;) { + if (s->lookahead <= 1) { - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); - s->strstart += s->lookahead; - s->lookahead = 0; + s->strstart += s->lookahead; + s->lookahead = 0; - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); - } - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; } -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ local block_state deflate_fast(deflate_state *s, int flush) { - IPos hash_head = NIL; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } + for (;;) { + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { #ifdef FASTEST - if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || - (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { - s->match_length = longest_match_fast (s, hash_head); - } + if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || + (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { + s->match_length = longest_match_fast (s, hash_head); + } #else - if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { - s->match_length = longest_match (s, hash_head); - } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { - s->match_length = longest_match_fast (s, hash_head); - } + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } #endif - /* longest_match() or longest_match_fast() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); - _tr_tally_dist(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH, bflush); + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); - s->lookahead -= s->match_length; + s->lookahead -= s->match_length; - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ #ifndef FASTEST - if (s->match_length <= s->max_insert_length && - s->lookahead >= MIN_MATCH) { - s->match_length--; /* string at strstart already in table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + } while (--s->match_length != 0); + s->strstart++; + } else #endif - { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times + Call UPDATE_HASH() MIN_MATCH-3 more times #endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + } + } else { + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; } #ifndef FASTEST -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ local block_state deflate_slow(deflate_state *s, int flush) { - IPos hash_head = NIL; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } + for (;;) { + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { - s->match_length = longest_match (s, hash_head); - } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { - s->match_length = longest_match_fast (s, hash_head); - } - /* longest_match() or longest_match_fast() sets match_start */ + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { + s->match_length = longest_match (s, hash_head); + } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { + s->match_length = longest_match_fast (s, hash_head); + } - if (s->match_length <= 5 && (s->strategy == Z_FILTERED + if (s->match_length <= 5 && (s->strategy == Z_FILTERED #if TOO_FAR <= 32767 - || (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR) + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) #endif - )) { + )) { - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ + s->match_length = MIN_MATCH-1; + } + } + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - check_match(s, s->strstart-1, s->prev_match, s->prev_length); + check_match(s, s->strstart-1, s->prev_match, s->prev_length); - _tr_tally_dist(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH, bflush); + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - s->prev_length -= 2; - do { - if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); - } - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; - if (bflush) FLUSH_BLOCK(s, 0); + if (bflush) FLUSH_BLOCK(s, 0); - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - if (bflush) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - s->match_available = 0; - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + } else if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; } #endif /* FASTEST */ #if 0 -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ local block_state deflate_rle(s, flush) - deflate_state *s; - int flush; + deflate_state *s; + int flush; { - int bflush; /* set if current block must be flushed */ - uInt run; /* length of run */ - uInt max; /* maximum length of run */ - uInt prev; /* byte at distance one to match */ - Bytef *scan; /* scan for end of run */ + int bflush; /* set if current block must be flushed */ + uInt run; /* length of run */ + uInt max; /* maximum length of run */ + uInt prev; /* byte at distance one to match */ + Bytef *scan; /* scan for end of run */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest encodable run. - */ - if (s->lookahead < MAX_MATCH) { - fill_window(s); - if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } + for (;;) { + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } - /* See how many times the previous byte repeats */ - run = 0; - if (s->strstart > 0) { /* if there is a previous byte, that is */ - max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; - scan = s->window + s->strstart - 1; - prev = *scan++; - do { - if (*scan++ != prev) - break; - } while (++run < max); - } + run = 0; + if (s->strstart > 0) { /* if there is a previous byte, that is */ + max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; + scan = s->window + s->strstart - 1; + prev = *scan++; + do { + if (*scan++ != prev) + break; + } while (++run < max); + } - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (run >= MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, run); - _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); - s->lookahead -= run; - s->strstart += run; - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + if (run >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, run); + _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); + s->lookahead -= run; + s->strstart += run; + } else { + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; } #endif /********* End of inlined file: deflate.c *********/ @@ -98713,203 +96709,118 @@ local block_state deflate_rle(s, flush) /********* Start of inlined file: inffast.c *********/ /********* Start of inlined file: inftrees.h *********/ -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ #ifndef _INFTREES_H_ #define _INFTREES_H_ -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - unsigned short val; /* offset in table or code value */ + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ } code; -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 0001eeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1444 code structures (852 for length/literals - and 592 for distances, the latter actually the result of an - exhaustive search). The true maximum is not known, but the value - below is more than safe. */ #define ENOUGH 2048 #define MAXD 592 -/* Type of code to build for inftable() */ typedef enum { - CODES, - LENS, - DISTS + CODES, + LENS, + DISTS } codetype; extern int inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); #endif /********* End of inlined file: inftrees.h *********/ /********* Start of inlined file: inflate.h *********/ -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ #ifndef _INFLATE_H_ #define _INFLATE_H_ -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer decoding by inflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip decoding - should be left enabled. */ #ifndef NO_GZIP # define GUNZIP #endif -/* Possible inflate modes between inflate() calls */ typedef enum { - HEAD, /* i: waiting for magic header */ - FLAGS, /* i: waiting for method and flags (gzip) */ - TIME, /* i: waiting for modification time (gzip) */ - OS, /* i: waiting for extra flags and operating system (gzip) */ - EXLEN, /* i: waiting for extra length (gzip) */ - EXTRA, /* i: waiting for extra bytes (gzip) */ - NAME, /* i: waiting for end of file name (gzip) */ - COMMENT, /* i: waiting for end of comment (gzip) */ - HCRC, /* i: waiting for header crc (gzip) */ - DICTID, /* i: waiting for dictionary check value */ - DICT, /* waiting for inflateSetDictionary() call */ - TYPE, /* i: waiting for type bits, including last-flag bit */ - TYPEDO, /* i: same, but skip check to exit inflate on new block */ - STORED, /* i: waiting for stored size (length and complement) */ - COPY, /* i/o: waiting for input or output to copy stored block */ - TABLE, /* i: waiting for dynamic block table lengths */ - LENLENS, /* i: waiting for code length code lengths */ - CODELENS, /* i: waiting for length/lit and distance code lengths */ - LEN, /* i: waiting for length/lit code */ - LENEXT, /* i: waiting for length extra bits */ - DIST, /* i: waiting for distance code */ - DISTEXT, /* i: waiting for distance extra bits */ - MATCH, /* o: waiting for output space to copy string */ - LIT, /* o: waiting for output space to write literal */ - CHECK, /* i: waiting for 32-bit check value */ - LENGTH, /* i: waiting for 32-bit length (gzip) */ - DONE, /* finished check, done -- remain here until reset */ - BAD, /* got a data error -- remain here until reset */ - MEM, /* got an inflate() memory error -- remain here until reset */ - SYNC /* looking for synchronization bytes to restart inflate() */ + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ } inflate_mode; -/* - State transitions between above modes - - - (most modes can go to the BAD or MEM mode -- not shown for clarity) - - Process header: - HEAD -> (gzip) or (zlib) - (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME - NAME -> COMMENT -> HCRC -> TYPE - (zlib) -> DICTID or TYPE - DICTID -> DICT -> TYPE - Read deflate blocks: - TYPE -> STORED or TABLE or LEN or CHECK - STORED -> COPY -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN - Read deflate codes: - LEN -> LENEXT or LIT or TYPE - LENEXT -> DIST -> DISTEXT -> MATCH -> LEN - LIT -> LEN - Process trailer: - CHECK -> LENGTH -> DONE - */ - -/* state maintained between inflate() calls. Approximately 7K bytes. */ struct inflate_state { - inflate_mode mode; /* current inflate mode */ - int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags (0 if zlib) */ - unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ - unsigned long check; /* protected copy of check value */ - unsigned long total; /* protected copy of output count */ - gz_headerp head; /* where to save gzip header information */ - /* sliding window */ - unsigned wbits; /* log base 2 of requested window size */ - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned write; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - /* bit accumulator */ - unsigned long hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ - /* for string and stored block copying */ - unsigned length; /* literal or length of data to copy */ - unsigned offset; /* distance back to copy string from */ - /* for table and code decoding */ - unsigned extra; /* extra bits needed */ - /* fixed and dynamic code tables */ - code const FAR *lencode; /* starting table for length/literal codes */ - code const FAR *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - unsigned have; /* number of code lengths in lens[] */ - code FAR *next; /* next available space in codes[] */ - unsigned short lens[320]; /* temporary storage for code lengths */ - unsigned short work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + unsigned extra; /* extra bits needed */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ }; #endif /********* End of inlined file: inflate.h *********/ /********* Start of inlined file: inffast.h *********/ -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ void inflate_fast OF((z_streamp strm, unsigned start)); /********* End of inlined file: inffast.h *********/ #ifndef ASMINF -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ #ifdef POSTINC # define OFF 0 # define PUP(a) *(a)++ @@ -98918,1736 +96829,1407 @@ void inflate_fast OF((z_streamp strm, unsigned start)); # define PUP(a) *++(a) #endif -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ void inflate_fast (z_streamp strm, unsigned start) { - struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ - unsigned char FAR *out; /* local strm->next_out */ - unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ - unsigned char FAR *end; /* while out < end, enough space available */ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ #ifdef INFLATE_STRICT - unsigned dmax; /* maximum distance from zlib header */ + unsigned dmax; /* maximum distance from zlib header */ #endif - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned write; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ - unsigned long hold; /* local strm->hold */ - unsigned bits; /* local strm->bits */ - code const FAR *lcode; /* local strm->lencode */ - code const FAR *dcode; /* local strm->distcode */ - unsigned lmask; /* mask for first level of length codes */ - unsigned dmask; /* mask for first level of distance codes */ - code thisx; /* retrieved table entry */ - unsigned op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - unsigned len; /* match length, unused bytes */ - unsigned dist; /* match distance */ - unsigned char FAR *from; /* where to copy match from */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code thisx; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; - last = in + (strm->avail_in - 5); - out = strm->next_out - OFF; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - 257); + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT - dmax = state->dmax; + dmax = state->dmax; #endif - wsize = state->wsize; - whave = state->whave; - write = state->write; - window = state->window; - hold = state->hold; - bits = state->bits; - lcode = state->lencode; - dcode = state->distcode; - lmask = (1U << state->lenbits) - 1; - dmask = (1U << state->distbits) - 1; + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - do { - if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - thisx = lcode[hold & lmask]; - dolen: - op = (unsigned)(thisx.bits); - hold >>= op; - bits -= op; - op = (unsigned)(thisx.op); - if (op == 0) { /* literal */ - Tracevv((stderr, thisx.val >= 0x20 && thisx.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", thisx.val)); - PUP(out) = (unsigned char)(thisx.val); - } - else if (op & 16) { /* length base */ - len = (unsigned)(thisx.val); - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - len += (unsigned)hold & ((1U << op) - 1); - hold >>= op; - bits -= op; - } - Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - thisx = dcode[hold & dmask]; - dodist: - op = (unsigned)(thisx.bits); - hold >>= op; - bits -= op; - op = (unsigned)(thisx.op); - if (op & 16) { /* distance base */ - dist = (unsigned)(thisx.val); - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - } - dist += (unsigned)hold & ((1U << op) - 1); + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + thisx = lcode[hold & lmask]; + dolen: + op = (unsigned)(thisx.bits); + hold >>= op; + bits -= op; + op = (unsigned)(thisx.op); + if (op == 0) { /* literal */ + Tracevv((stderr, thisx.val >= 0x20 && thisx.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", thisx.val)); + PUP(out) = (unsigned char)(thisx.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(thisx.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + thisx = dcode[hold & dmask]; + dodist: + op = (unsigned)(thisx.bits); + hold >>= op; + bits -= op; + op = (unsigned)(thisx.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(thisx.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT - if (dist > dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } #endif - hold >>= op; - bits -= op; - Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - from = window - OFF; - if (write == 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - else if (write < op) { /* wrap around window */ - from += wsize + write - op; - op -= write; - if (op < len) { /* some from end of window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = window - OFF; - if (write < len) { /* some from start of window */ - op = write; - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - } - else { /* contiguous in window */ - from += write - op; - if (op < len) { /* some from window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); - len -= 3; - } - if (len) { - PUP(out) = PUP(from); - if (len > 1) - PUP(out) = PUP(from); - } - } - else { - from = out - dist; /* copy direct from output */ - do { /* minimum length is three */ - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); - len -= 3; - } while (len > 2); - if (len) { - PUP(out) = PUP(from); - if (len > 1) - PUP(out) = PUP(from); - } - } - } - else if ((op & 64) == 0) { /* 2nd level distance code */ - thisx = dcode[thisx.val + (hold & ((1U << op) - 1))]; - goto dodist; - } - else { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - } - else if ((op & 64) == 0) { /* 2nd level length code */ - thisx = lcode[thisx.val + (hold & ((1U << op) - 1))]; - goto dolen; - } - else if (op & 32) { /* end-of-block */ - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - else { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - } while (in < last && out < end); + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + thisx = dcode[thisx.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + thisx = lcode[thisx.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - in -= len; - bits -= len << 3; - hold &= (1U << bits) - 1; + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; - /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; - strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); - strm->avail_out = (unsigned)(out < end ? - 257 + (end - out) : 257 - (out - end)); - state->hold = hold; - state->bits = bits; - return; + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; } -/* - inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - - Using bit fields for code structure - - Different op definition to avoid & for extra bits (do & for table bits) - - Three separate decoding do-loops for direct, window, and write == 0 - - Special case for distance > 1 copies to do overlapped load and store copy - - Explicit branch predictions (based on measured branch probabilities) - - Deferring match copy and interspersed it with decoding subsequent codes - - Swapping literal/length else - - Swapping window/direct else - - Larger unrolled copy loops (three is about right) - - Moving len -= 3 statement into middle of loop - */ - #endif /* !ASMINF */ /********* End of inlined file: inffast.c *********/ - #undef PULLBYTE - #undef LOAD - #undef RESTORE - #undef INITBITS - #undef NEEDBITS - #undef DROPBITS - #undef BYTEBITS + #undef PULLBYTE + #undef LOAD + #undef RESTORE + #undef INITBITS + #undef NEEDBITS + #undef DROPBITS + #undef BYTEBITS /********* Start of inlined file: inflate.c *********/ -/* - * Change history: - * - * 1.2.beta0 24 Nov 2002 - * - First version -- complete rewrite of inflate to simplify code, avoid - * creation of window when not needed, minimize use of window when it is - * needed, make inffast.c even faster, implement gzip decoding, and to - * improve code readability and style over the previous zlib inflate code - * - * 1.2.beta1 25 Nov 2002 - * - Use pointers for available input and output checking in inffast.c - * - Remove input and output counters in inffast.c - * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 - * - Remove unnecessary second byte pull from length extra in inffast.c - * - Unroll direct copy to three copies per loop in inffast.c - * - * 1.2.beta2 4 Dec 2002 - * - Change external routine names to reduce potential conflicts - * - Correct filename to inffixed.h for fixed tables in inflate.c - * - Make hbuf[] unsigned char to match parameter type in inflate.c - * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) - * to avoid negation problem on Alphas (64 bit) in inflate.c - * - * 1.2.beta3 22 Dec 2002 - * - Add comments on state->bits assertion in inffast.c - * - Add comments on op field in inftrees.h - * - Fix bug in reuse of allocated window after inflateReset() - * - Remove bit fields--back to byte structure for speed - * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths - * - Change post-increments to pre-increments in inflate_fast(), PPC biased? - * - Add compile time option, POSTINC, to use post-increments instead (Intel?) - * - Make MATCH copy in inflate() much faster for when inflate_fast() not used - * - Use local copies of stream next and avail values, as well as local bit - * buffer and bit count in inflate()--for speed when inflate_fast() not used - * - * 1.2.beta4 1 Jan 2003 - * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings - * - Move a comment on output buffer sizes from inffast.c to inflate.c - * - Add comments in inffast.c to introduce the inflate_fast() routine - * - Rearrange window copies in inflate_fast() for speed and simplification - * - Unroll last copy for window match in inflate_fast() - * - Use local copies of window variables in inflate_fast() for speed - * - Pull out common write == 0 case for speed in inflate_fast() - * - Make op and len in inflate_fast() unsigned for consistency - * - Add FAR to lcode and dcode declarations in inflate_fast() - * - Simplified bad distance check in inflate_fast() - * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new - * source file infback.c to provide a call-back interface to inflate for - * programs like gzip and unzip -- uses window as output buffer to avoid - * window copying - * - * 1.2.beta5 1 Jan 2003 - * - Improved inflateBack() interface to allow the caller to provide initial - * input in strm. - * - Fixed stored blocks bug in inflateBack() - * - * 1.2.beta6 4 Jan 2003 - * - Added comments in inffast.c on effectiveness of POSTINC - * - Typecasting all around to reduce compiler warnings - * - Changed loops from while (1) or do {} while (1) to for (;;), again to - * make compilers happy - * - Changed type of window in inflateBackInit() to unsigned char * - * - * 1.2.beta7 27 Jan 2003 - * - Changed many types to unsigned or unsigned short to avoid warnings - * - Added inflateCopy() function - * - * 1.2.0 9 Mar 2003 - * - Changed inflateBack() interface to provide separate opaque descriptors - * for the in() and out() functions - * - Changed inflateBack() argument and in_func typedef to swap the length - * and buffer address return values for the input function - * - Check next_in and next_out for Z_NULL on entry to inflate() - * - * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. - */ /********* Start of inlined file: inffast.h *********/ -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ void inflate_fast OF((z_streamp strm, unsigned start)); /********* End of inlined file: inffast.h *********/ #ifdef MAKEFIXED # ifndef BUILDFIXED -# define BUILDFIXED +# define BUILDFIXED # endif #endif -/* function prototypes */ local void fixedtables OF((struct inflate_state FAR *state)); local int updatewindow OF((z_streamp strm, unsigned out)); #ifdef BUILDFIXED void makefixed OF((void)); #endif local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, - unsigned len)); + unsigned len)); int ZEXPORT inflateReset (z_streamp strm) { - struct inflate_state FAR *state; + struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - strm->total_in = strm->total_out = state->total = 0; - strm->msg = Z_NULL; - strm->adler = 1; /* to support ill-conceived Java test suite */ - state->mode = HEAD; - state->last = 0; - state->havedict = 0; - state->dmax = 32768U; - state->head = Z_NULL; - state->wsize = 0; - state->whave = 0; - state->write = 0; - state->hold = 0; - state->bits = 0; - state->lencode = state->distcode = state->next = state->codes; - Tracev((stderr, "inflate: reset\n")); - return Z_OK; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->write = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; } int ZEXPORT inflatePrime (z_streamp strm, int bits, int value) { - struct inflate_state FAR *state; + struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; - value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; - return Z_OK; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; } int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) { - struct inflate_state FAR *state; + struct inflate_state FAR *state; - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL) return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; - state = (struct inflate_state FAR *) - ZALLOC(strm, 1, sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - if (windowBits < 0) { - state->wrap = 0; - windowBits = -windowBits; - } - else { - state->wrap = (windowBits >> 4) + 1; + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; #ifdef GUNZIP - if (windowBits < 48) windowBits &= 15; + if (windowBits < 48) windowBits &= 15; #endif - } - if (windowBits < 8 || windowBits > 15) { - ZFREE(strm, state); - strm->state = Z_NULL; - return Z_STREAM_ERROR; - } - state->wbits = (unsigned)windowBits; - state->window = Z_NULL; - return inflateReset(strm); + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); } int ZEXPORT inflateInit_ (z_streamp strm, const char *version, int stream_size) { - return inflateInit2_(strm, DEF_WBITS, version, stream_size); + return inflateInit2_(strm, DEF_WBITS, version, stream_size); } -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ local void fixedtables (struct inflate_state FAR *state) { #ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; + if (virgin) { + unsigned sym, bits; + static code *next; - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - /* do this just once */ - virgin = 0; - } + virgin = 0; + } #else /* !BUILDFIXED */ /********* Start of inlined file: inffixed.h *********/ - /* inffixed.h -- table for decoding fixed codes - * Generated automatically by makefixed(). - */ - /* WARNING: this file should *not* be used by applications. It - is part of the implementation of the compression library and - is subject to change. Applications should only use zlib.h. - */ + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, - {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, - {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, - {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, - {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, - {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, - {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, - {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, - {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, - {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, - {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, - {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, - {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, - {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, - {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, - {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, - {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, - {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, - {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, - {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, - {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, - {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, - {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, - {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, - {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, - {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, - {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, - {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, - {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, - {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, - {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, - {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, - {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, - {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, - {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, - {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, - {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, - {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, - {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, - {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, - {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, - {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, - {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, - {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, - {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, - {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, - {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, - {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, - {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, - {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, - {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, - {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, - {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, - {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, - {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, - {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, - {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, - {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, - {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, - {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, - {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, - {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, - {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, - {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, - {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, - {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, - {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, - {0,9,255} - }; - - static const code distfix[32] = { - {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, - {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, - {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, - {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, - {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, - {22,5,193},{64,5,0} - }; + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; /********* End of inlined file: inffixed.h *********/ #endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; } #ifdef MAKEFIXED #include -/* - Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also - defines BUILDFIXED, so the tables are built on the fly. makefixed() writes - those tables to stdout, which would be piped to inffixed.h. A small program - can simply call makefixed to do this: - - void makefixed(void); - - int main(void) - { - makefixed(); - return 0; - } - - Then that can be linked with zlib built with MAKEFIXED defined and run: - - a.out > inffixed.h - */ void makefixed() { - unsigned low, size; - struct inflate_state state; + unsigned low, size; + struct inflate_state state; - fixedtables(&state); - puts(" /* inffixed.h -- table for decoding fixed codes"); - puts(" * Generated automatically by makefixed()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, - state.lencode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, - state.distcode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); } #endif /* MAKEFIXED */ -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ local int updatewindow (z_streamp strm, unsigned out) { - struct inflate_state FAR *state; - unsigned copy, dist; + struct inflate_state FAR *state; + unsigned copy, dist; - state = (struct inflate_state FAR *)strm->state; + state = (struct inflate_state FAR *)strm->state; - /* if it hasn't been done already, allocate space for the window */ - if (state->window == Z_NULL) { - state->window = (unsigned char FAR *) - ZALLOC(strm, 1U << state->wbits, - sizeof(unsigned char)); - if (state->window == Z_NULL) return 1; - } + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } - /* if window not in use yet, initialize */ - if (state->wsize == 0) { - state->wsize = 1U << state->wbits; - state->write = 0; - state->whave = 0; - } + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } - /* copy state->wsize or less output bytes into the circular window */ - copy = out - strm->avail_out; - if (copy >= state->wsize) { - zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); - state->write = 0; - state->whave = state->wsize; - } - else { - dist = state->wsize - state->write; - if (dist > copy) dist = copy; - zmemcpy(state->window + state->write, strm->next_out - copy, dist); - copy -= dist; - if (copy) { - zmemcpy(state->window, strm->next_out - copy, copy); - state->write = copy; - state->whave = state->wsize; - } - else { - state->write += dist; - if (state->write == state->wsize) state->write = 0; - if (state->whave < state->wsize) state->whave += dist; - } - } - return 0; + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; } -/* Macros for inflate(): */ - -/* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP # define UPDATE(check, buf, len) \ - (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else # define UPDATE(check, buf, len) adler32(check, buf, len) #endif -/* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - check = crc32(check, hbuf, 2); \ - } while (0) + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) # define CRC4(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - hbuf[2] = (unsigned char)((word) >> 16); \ - hbuf[3] = (unsigned char)((word) >> 24); \ - check = crc32(check, hbuf, 4); \ - } while (0) + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) #endif -/* Load registers with state in inflate() for speed */ #define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) -/* Restore state from registers in inflate() */ #define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) -/* Clear the input bit accumulator */ #define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) + do { \ + hold = 0; \ + bits = 0; \ + } while (0) -/* Get a byte of input into the bit accumulator, or return from inflate() - if there is no input available. */ #define PULLBYTE() \ - do { \ - if (have == 0) goto inf_leave; \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflate(). */ #define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) -/* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) + ((unsigned)hold & ((1U << (n)) - 1)) -/* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) -/* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) -/* Reverse the bytes in a 32-bit value */ #define REVERSE(q) \ - ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - -/* - inflate() uses a state machine to process as much input data and generate as - much output data as possible before returning. The state machine is - structured roughly as follows: - - for (;;) switch (state) { - ... - case STATEn: - if (not enough input data or output space to make progress) - return; - ... make progress ... - state = STATEm; - break; - ... - } - - so when inflate() is called again, the same case is attempted again, and - if the appropriate resources are provided, the machine proceeds to the - next state. The NEEDBITS() macro is usually the way the state evaluates - whether it can proceed or should return. NEEDBITS() does the return if - the requested bits are not available. The typical use of the BITS macros - is: - - NEEDBITS(n); - ... do something with BITS(n) ... - DROPBITS(n); - - where NEEDBITS(n) either returns from inflate() if there isn't enough - input left to load n bits into the accumulator, or it continues. BITS(n) - gives the low n bits in the accumulator. When done, DROPBITS(n) drops - the low n bits off the accumulator. INITBITS() clears the accumulator - and sets the number of available bits to zero. BYTEBITS() discards just - enough bits to put the accumulator on a byte boundary. After BYTEBITS() - and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. - - NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return - if there is no input available. The decoding of variable length codes uses - PULLBYTE() directly in order to pull just enough bytes to decode the next - code, and no more. - - Some states loop until they get enough input, making sure that enough - state information is maintained to continue the loop where it left off - if NEEDBITS() returns in the loop. For example, want, need, and keep - would all have to actually be part of the saved state in case NEEDBITS() - returns: - - case STATEw: - while (want < need) { - NEEDBITS(n); - keep[want++] = BITS(n); - DROPBITS(n); - } - state = STATEx; - case STATEx: - - As shown above, if the next state is also the next case, then the break - is omitted. - - A state may also return if there is not enough output space available to - complete that state. Those states are copying stored data, writing a - literal byte, and copying a matching string. - - When returning, a "goto inf_leave" is used to update the total counters, - update the check value, and determine whether any progress has been made - during that inflate() call in order to return the proper return code. - Progress is defined as a change in either strm->avail_in or strm->avail_out. - When there is a window, goto inf_leave will update the window with the last - output written. If a goto inf_leave occurs in the middle of decompression - and there is no window currently, goto inf_leave will create one and copy - output to the window for the next call of inflate(). - - In this implementation, the flush parameter of inflate() only affects the - return code (per zlib.h). inflate() always writes as much as possible to - strm->next_out, given the space available and the provided input--the effect - documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers - the allocation of and copying into a sliding window until necessary, which - provides the effect documented in zlib.h for Z_FINISH when the entire input - stream available. So the only thing the flush parameter actually does is: - when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it - will return Z_BUF_ERROR if it has not reached the end of the stream. - */ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) int ZEXPORT inflate (z_streamp strm, int flush) { - struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned in, out; /* save starting available input and output */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code thisx; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code thisx; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ #ifdef GUNZIP - unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ #endif - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0)) - return Z_STREAM_ERROR; + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ - LOAD(); - in = have; - out = left; - ret = Z_OK; - for (;;) - switch (state->mode) { - case HEAD: - if (state->wrap == 0) { - state->mode = TYPEDO; - break; - } - NEEDBITS(16); + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); #ifdef GUNZIP - if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ - state->check = crc32(0L, Z_NULL, 0); - CRC2(state->check, hold); - INITBITS(); - state->mode = FLAGS; - break; - } - state->flags = 0; /* expect zlib header */ - if (state->head != Z_NULL) - state->head->done = -1; - if (!(state->wrap & 1) || /* check if zlib header allowed */ + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ #else - if ( + if ( #endif - ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = (char *)"incorrect header check"; - state->mode = BAD; - break; - } - if (BITS(4) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - DROPBITS(4); - len = BITS(4) + 8; - if (len > state->wbits) { - strm->msg = (char *)"invalid window size"; - state->mode = BAD; - break; - } - state->dmax = 1U << len; - Tracev((stderr, "inflate: zlib header ok\n")); - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = hold & 0x200 ? DICTID : TYPE; - INITBITS(); - break; + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; #ifdef GUNZIP - case FLAGS: - NEEDBITS(16); - state->flags = (int)(hold); - if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - if (state->flags & 0xe000) { - strm->msg = (char *)"unknown header flags set"; - state->mode = BAD; - break; - } - if (state->head != Z_NULL) - state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = TIME; - case TIME: - NEEDBITS(32); - if (state->head != Z_NULL) - state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); - INITBITS(); - state->mode = OS; - case OS: - NEEDBITS(16); - if (state->head != Z_NULL) { - state->head->xflags = (int)(hold & 0xff); - state->head->os = (int)(hold >> 8); - } - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = EXLEN; - case EXLEN: - if (state->flags & 0x0400) { - NEEDBITS(16); - state->length = (unsigned)(hold); - if (state->head != Z_NULL) - state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - } - else if (state->head != Z_NULL) - state->head->extra = Z_NULL; - state->mode = EXTRA; - case EXTRA: - if (state->flags & 0x0400) { - copy = state->length; - if (copy > have) copy = have; - if (copy) { - if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; - zmemcpy(state->head->extra + len, next, - len + copy > state->head->extra_max ? - state->head->extra_max - len : copy); - } - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - state->length -= copy; - } - if (state->length) goto inf_leave; - } - state->length = 0; - state->mode = NAME; - case NAME: - if (state->flags & 0x0800) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->name != Z_NULL && - state->length < state->head->name_max) - state->head->name[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->name = Z_NULL; - state->length = 0; - state->mode = COMMENT; - case COMMENT: - if (state->flags & 0x1000) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->comment != Z_NULL && - state->length < state->head->comm_max) - state->head->comment[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->comment = Z_NULL; - state->mode = HCRC; - case HCRC: - if (state->flags & 0x0200) { - NEEDBITS(16); - if (hold != (state->check & 0xffff)) { - strm->msg = (char *)"header crc mismatch"; - state->mode = BAD; - break; - } - INITBITS(); - } - if (state->head != Z_NULL) { - state->head->hcrc = (int)((state->flags >> 9) & 1); - state->head->done = 1; - } - strm->adler = state->check = crc32(0L, Z_NULL, 0); - state->mode = TYPE; - break; + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; #endif - case DICTID: - NEEDBITS(32); - strm->adler = state->check = REVERSE(hold); - INITBITS(); - state->mode = DICT; - case DICT: - if (state->havedict == 0) { - RESTORE(); - return Z_NEED_DICT; - } - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = TYPE; - case TYPE: - if (flush == Z_BLOCK) goto inf_leave; - case TYPEDO: - if (state->last) { - BYTEBITS(); - state->mode = CHECK; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - case STORED: - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - state->mode = COPY; - case COPY: - copy = state->length; - if (copy) { - if (copy > have) copy = have; - if (copy > left) copy = left; - if (copy == 0) goto inf_leave; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - break; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - case TABLE: - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } #endif - Tracev((stderr, "inflate: table sizes ok\n")); - state->have = 0; - state->mode = LENLENS; - case LENLENS: - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - state->have = 0; - state->mode = CODELENS; - case CODELENS: - while (state->have < state->nlen + state->ndist) { - for (;;) { - thisx = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(thisx.bits) <= bits) break; - PULLBYTE(); - } - if (thisx.val < 16) { - NEEDBITS(thisx.bits); - DROPBITS(thisx.bits); - state->lens[state->have++] = thisx.val; - } - else { - if (thisx.val == 16) { - NEEDBITS(thisx.bits + 2); - DROPBITS(thisx.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = state->lens[state->have - 1]; - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (thisx.val == 17) { - NEEDBITS(thisx.bits + 3); - DROPBITS(thisx.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(thisx.bits + 7); - DROPBITS(thisx.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + thisx = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(thisx.bits) <= bits) break; + PULLBYTE(); + } + if (thisx.val < 16) { + NEEDBITS(thisx.bits); + DROPBITS(thisx.bits); + state->lens[state->have++] = thisx.val; + } + else { + if (thisx.val == 16) { + NEEDBITS(thisx.bits + 2); + DROPBITS(thisx.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (thisx.val == 17) { + NEEDBITS(thisx.bits + 3); + DROPBITS(thisx.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(thisx.bits + 7); + DROPBITS(thisx.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } - /* handle error breaks in while */ - if (state->mode == BAD) break; + if (state->mode == BAD) break; - /* build code tables */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - case LEN: - if (have >= 6 && left >= 258) { - RESTORE(); - inflate_fast(strm, out); - LOAD(); - break; - } - for (;;) { - thisx = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(thisx.bits) <= bits) break; - PULLBYTE(); - } - if (thisx.op && (thisx.op & 0xf0) == 0) { - last = thisx; - for (;;) { - thisx = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + thisx.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(thisx.bits); - state->length = (unsigned)thisx.val; - if ((int)(thisx.op) == 0) { - Tracevv((stderr, thisx.val >= 0x20 && thisx.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", thisx.val)); - state->mode = LIT; - break; - } - if (thisx.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - if (thisx.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - state->extra = (unsigned)(thisx.op) & 15; - state->mode = LENEXT; - case LENEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - state->mode = DIST; - case DIST: - for (;;) { - thisx = state->distcode[BITS(state->distbits)]; - if ((unsigned)(thisx.bits) <= bits) break; - PULLBYTE(); - } - if ((thisx.op & 0xf0) == 0) { - last = thisx; - for (;;) { - thisx = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + thisx.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(thisx.bits); - if (thisx.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)thisx.val; - state->extra = (unsigned)(thisx.op) & 15; - state->mode = DISTEXT; - case DISTEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + thisx = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(thisx.bits) <= bits) break; + PULLBYTE(); + } + if (thisx.op && (thisx.op & 0xf0) == 0) { + last = thisx; + for (;;) { + thisx = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + thisx.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(thisx.bits); + state->length = (unsigned)thisx.val; + if ((int)(thisx.op) == 0) { + Tracevv((stderr, thisx.val >= 0x20 && thisx.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", thisx.val)); + state->mode = LIT; + break; + } + if (thisx.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (thisx.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(thisx.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + thisx = state->distcode[BITS(state->distbits)]; + if ((unsigned)(thisx.bits) <= bits) break; + PULLBYTE(); + } + if ((thisx.op & 0xf0) == 0) { + last = thisx; + for (;;) { + thisx = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + thisx.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(thisx.bits); + if (thisx.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)thisx.val; + state->extra = (unsigned)(thisx.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } #ifdef INFLATE_STRICT - if (state->offset > state->dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } #endif - if (state->offset > state->whave + out - left) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - state->mode = MATCH; - case MATCH: - if (left == 0) goto inf_leave; - copy = out - left; - if (state->offset > copy) { /* copy from window */ - copy = state->offset - copy; - if (copy > state->write) { - copy -= state->write; - from = state->window + (state->wsize - copy); - } - else - from = state->window + (state->write - copy); - if (copy > state->length) copy = state->length; - } - else { /* copy from output */ - from = put - state->offset; - copy = state->length; - } - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = *from++; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; - case LIT: - if (left == 0) goto inf_leave; - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - case CHECK: - if (state->wrap) { - NEEDBITS(32); - out -= left; - strm->total_out += out; - state->total += out; - if (out) - strm->adler = state->check = - UPDATE(state->check, put - out, out); - out = left; - if (( + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( #ifdef GUNZIP - state->flags ? hold : + state->flags ? hold : #endif - REVERSE(hold)) != state->check) { - strm->msg = (char *)"incorrect data check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: check matches trailer\n")); - } + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } #ifdef GUNZIP - state->mode = LENGTH; - case LENGTH: - if (state->wrap && state->flags) { - NEEDBITS(32); - if (hold != (state->total & 0xffffffffUL)) { - strm->msg = (char *)"incorrect length check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: length matches trailer\n")); - } + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } #endif - state->mode = DONE; - case DONE: - ret = Z_STREAM_END; - goto inf_leave; - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - default: - return Z_STREAM_ERROR; - } + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ inf_leave: - RESTORE(); - if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) - if (updatewindow(strm, out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - in -= strm->avail_in; - out -= strm->avail_out; - strm->total_in += in; - strm->total_out += out; - state->total += out; - if (state->wrap && out) - strm->adler = state->check = - UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + - (state->mode == TYPE ? 128 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) - ret = Z_BUF_ERROR; - return ret; + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; } int ZEXPORT inflateEnd (z_streamp strm) { - struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->window != Z_NULL) ZFREE(strm, state->window); - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; } int ZEXPORT inflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength) { - struct inflate_state FAR *state; - unsigned long id_; + struct inflate_state FAR *state; + unsigned long id_; - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->wrap != 0 && state->mode != DICT) - return Z_STREAM_ERROR; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; - /* check for correct dictionary id */ - if (state->mode == DICT) { - id_ = adler32(0L, Z_NULL, 0); - id_ = adler32(id_, dictionary, dictLength); - if (id_ != state->check) - return Z_DATA_ERROR; - } + if (state->mode == DICT) { + id_ = adler32(0L, Z_NULL, 0); + id_ = adler32(id_, dictionary, dictLength); + if (id_ != state->check) + return Z_DATA_ERROR; + } - /* copy dictionary to window */ - if (updatewindow(strm, strm->avail_out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - if (dictLength > state->wsize) { - zmemcpy(state->window, dictionary + dictLength - state->wsize, - state->wsize); - state->whave = state->wsize; - } - else { - zmemcpy(state->window + state->wsize - dictLength, dictionary, - dictLength); - state->whave = dictLength; - } - state->havedict = 1; - Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; } int ZEXPORT inflateGetHeader (z_streamp strm, gz_headerp head) { - struct inflate_state FAR *state; + struct inflate_state FAR *state; - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; - /* save header structure */ - state->head = head; - head->done = 0; - return Z_OK; + state->head = head; + head->done = 0; + return Z_OK; } -/* - Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found - or when out of input. When called, *have is the number of pattern bytes - found in order so far, in 0..3. On return *have is updated to the new - state. If on return *have equals four, then the pattern was found and the - return value is how many bytes were read including the last byte of the - pattern. If *have is less than four, then the pattern has not been found - yet and the return value is len. In the latter case, syncsearch() can be - called again with more data and the *have state. *have is initialized to - zero for the first call. - */ local unsigned syncsearch (unsigned FAR *have, unsigned char FAR *buf, unsigned len) { - unsigned got; - unsigned next; + unsigned got; + unsigned next; - got = *have; - next = 0; - while (next < len && got < 4) { - if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) - got++; - else if (buf[next]) - got = 0; - else - got = 4 - got; - next++; - } - *have = got; - return next; + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; } int ZEXPORT inflateSync (z_streamp strm) { - unsigned len; /* number of bytes to look at or looked at */ - unsigned long in, out; /* temporary to save total_in and total_out */ - unsigned char buf[4]; /* to restore bit buffer to byte string */ - struct inflate_state FAR *state; + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; - /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; - /* if first time, start search in bit buffer */ - if (state->mode != SYNC) { - state->mode = SYNC; - state->hold <<= state->bits & 7; - state->bits -= state->bits & 7; - len = 0; - while (state->bits >= 8) { - buf[len++] = (unsigned char)(state->hold); - state->hold >>= 8; - state->bits -= 8; - } - state->have = 0; - syncsearch(&(state->have), buf, len); - } + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } - /* search available input */ - len = syncsearch(&(state->have), strm->next_in, strm->avail_in); - strm->avail_in -= len; - strm->next_in += len; - strm->total_in += len; + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; - /* return no joy or set up to restart inflate() on a new block */ - if (state->have != 4) return Z_DATA_ERROR; - in = strm->total_in; out = strm->total_out; - inflateReset(strm); - strm->total_in = in; strm->total_out = out; - state->mode = TYPE; - return Z_OK; + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; } -/* - Returns true if inflate is currently at the end of a block generated by - Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - implementation to provide an additional safety check. PPP uses - Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored - block. When decompressing, PPP checks that at the end of input packet, - inflate is waiting for these length bytes. - */ int ZEXPORT inflateSyncPoint (z_streamp strm) { - struct inflate_state FAR *state; + struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - return state->mode == STORED && state->bits == 0; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; } int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) { - struct inflate_state FAR *state; - struct inflate_state FAR *copy; - unsigned char FAR *window; - unsigned wsize; + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; - /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)source->state; + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; - /* allocate space */ - copy = (struct inflate_state FAR *) - ZALLOC(source, 1, sizeof(struct inflate_state)); - if (copy == Z_NULL) return Z_MEM_ERROR; - window = Z_NULL; - if (state->window != Z_NULL) { - window = (unsigned char FAR *) - ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); - if (window == Z_NULL) { - ZFREE(source, copy); - return Z_MEM_ERROR; - } - } + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } - /* copy state */ - zmemcpy(dest, source, sizeof(z_stream)); - zmemcpy(copy, state, sizeof(struct inflate_state)); - if (state->lencode >= state->codes && - state->lencode <= state->codes + ENOUGH - 1) { - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); - } - copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) { - wsize = 1U << state->wbits; - zmemcpy(window, state->window, wsize); - } - copy->window = window; - dest->state = (struct internal_state FAR *)copy; - return Z_OK; + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; } /********* End of inlined file: inflate.c *********/ @@ -100657,377 +98239,228 @@ int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) const char inflate_copyright[] = " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ int inflate_table (codetype type, - unsigned short FAR *lens, - unsigned codes, - code FAR * FAR *table, - unsigned FAR *bits, - unsigned short FAR *work) + unsigned short FAR *lens, + unsigned codes, + code FAR * FAR *table, + unsigned FAR *bits, + unsigned short FAR *work) { - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code thisx; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 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 const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; - static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ - 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 const unsigned short dext[32] = { /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64}; + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code thisx; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 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 const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 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 const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + thisx.op = (unsigned char)64; /* invalid code marker */ + thisx.bits = (unsigned char)1; + thisx.val = (unsigned short)0; + *(*table)++ = thisx; /* make a table to force an error */ + *(*table)++ = thisx; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) { /* no symbols to code at all */ - thisx.op = (unsigned char)64; /* invalid code marker */ - thisx.bits = (unsigned char)1; - thisx.val = (unsigned short)0; - *(*table)++ = thisx; /* make a table to force an error */ - *(*table)++ = thisx; - *bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min <= MAXBITS; min++) - if (count[min] != 0) break; - if (root < min) root = min; + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + for (;;) { + thisx.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + thisx.op = (unsigned char)0; + thisx.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + thisx.op = (unsigned char)(extra[work[sym]]); + thisx.val = base[work[sym]]; + } + else { + thisx.op = (unsigned char)(32 + 64); /* end of block */ + thisx.val = 0; + } - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = thisx; + } while (fill != 0); - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked when a LENS table is being made - against the space in *table, ENOUGH, minus the maximum space needed by - the worst case distance code, MAXD. This should never happen, but the - sufficiency of ENOUGH has not been proven exhaustively, hence the check. - This assumes that when type == LENS, bits == 9. + if (len > root && (huff & mask) != low) { + if (drop == 0) + drop = root; - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ + next += min; /* here min is 1 << curr */ - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - end = 19; - break; - case LENS: - base = lbase; - base -= 257; - extra = lext; - extra -= 257; - end = 256; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; - /* check available table space */ - if (type == LENS && used >= ENOUGH - MAXD) - return 1; + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - thisx.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { - thisx.op = (unsigned char)0; - thisx.val = work[sym]; - } - else if ((int)(work[sym]) > end) { - thisx.op = (unsigned char)(extra[work[sym]]); - thisx.val = base[work[sym]]; - } - else { - thisx.op = (unsigned char)(32 + 64); /* end of block */ - thisx.val = 0; - } + thisx.op = (unsigned char)64; /* invalid code marker */ + thisx.bits = (unsigned char)(len - drop); + thisx.val = (unsigned short)0; + while (huff != 0) { + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + thisx.bits = (unsigned char)len; + } - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - next[(huff >> drop) + fill] = thisx; - } while (fill != 0); + next[huff >> drop] = thisx; - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if (type == LENS && used >= ENOUGH - MAXD) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - thisx.op = (unsigned char)64; /* invalid code marker */ - thisx.bits = (unsigned char)(len - drop); - thisx.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - thisx.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = thisx; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; + *table += used; + *bits = root; + return 0; } /********* End of inlined file: inftrees.c *********/ /********* Start of inlined file: trees.c *********/ -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* @(#) $Id: trees.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */ - -/* #define GEN_TREES_H */ #ifdef DEBUG # include #endif -/* =========================================================================== - * Constants - */ - #define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ #define END_BLOCK 256 -/* end of block literal code */ -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ +#define REP_3_6 16 -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ +#define REPZ_3_10 17 #define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {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}; @@ -101040,50 +98473,24 @@ local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ local const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ #define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ #define DIST_CODE_LEN 512 /* see definition of array dist_code below */ #if defined(GEN_TREES_H) || !defined(STDC) -/* non ANSI compilers may not accept trees.h */ local ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ local ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ uch _dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ uch _length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ local int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ local int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ #else @@ -101209,8 +98616,8 @@ local const int base_length[LENGTH_CODES] = { }; local const int base_dist[D_CODES] = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 }; /********* End of inlined file: trees.h *********/ @@ -101218,45 +98625,41 @@ local const int base_dist[D_CODES] = { #endif /* GEN_TREES_H */ struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const intf *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ }; local static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; local static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; local static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; -/* =========================================================================== - * Local (static) routines in this file. - */ - local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); local int build_bl_tree OF((deflate_state *s)); local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); + int blcodes)); local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); + ct_data *dtree)); local void set_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); #ifdef GEN_TREES_H local void gen_trees_header OF((void)); @@ -101264,1035 +98667,795 @@ local void gen_trees_header OF((void)); #ifndef DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ #else /* DEBUG */ # define send_code(s, c, tree) \ - { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } #endif -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ #define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ } -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ #ifdef DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); +local void send_bits OF((deflate_state *s, int value, int length)); local void send_bits (deflate_state *s, int value, int length) { - Tracevv((stderr," l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (value << s->bi_valid); - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= value << s->bi_valid; - s->bi_valid += length; - } + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } } #else /* !DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ - s->bi_buf |= (val << s->bi_valid);\ - put_short(s, s->bi_buf);\ - s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ - s->bi_valid += len - Buf_size;\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ } else {\ - s->bi_buf |= (value) << s->bi_valid;\ - s->bi_valid += len;\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ }\ } #endif /* DEBUG */ -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. - */ local void tr_static_init() { #if defined(GEN_TREES_H) || !defined(STDC) - static int static_init_done = 0; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; - if (static_init_done) return; + if (static_init_done) return; - /* For some embedded targets, global variables are not initialized: */ - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - _dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; # ifdef GEN_TREES_H - gen_trees_header(); + gen_trees_header(); # endif #endif /* defined(GEN_TREES_H) || !defined(STDC) */ } -/* =========================================================================== - * Genererate the file trees.h describing the static trees. - */ #ifdef GEN_TREES_H # ifndef DEBUG -# include +# include # endif # define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) void gen_trees_header() { - FILE *header = fopen("trees.h", "w"); - int i; + FILE *header = fopen("trees.h", "w"); + int i; - Assert (header != NULL, "Can't open trees.h"); - fprintf(header, - "/* header created automatically with -DGEN_TREES_H */\n\n"); + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); - fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, - static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } - fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, - static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } - fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - fprintf(header, "%2u%s", _dist_code[i], - SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } - fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - fprintf(header, "%2u%s", _length_code[i], - SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } - fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - fprintf(header, "%1u%s", base_length[i], - SEPARATOR(i, LENGTH_CODES-1, 20)); - } + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } - fprintf(header, "local const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "%5u%s", base_dist[i], - SEPARATOR(i, D_CODES-1, 10)); - } + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } - fclose(header); + fclose(header); } #endif /* GEN_TREES_H */ -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ void _tr_init(deflate_state *s) { - tr_static_init(); + tr_static_init(); - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; - s->bi_buf = 0; - s->bi_valid = 0; - s->last_eob_len = 8; /* enough lookahead for inflate */ + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ #ifdef DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; + s->compressed_len = 0L; + s->bits_sent = 0L; #endif - /* Initialize the first block of the first file: */ - init_block(s); + init_block(s); } -/* =========================================================================== - * Initialize a new block. - */ local void init_block (deflate_state *s) { - int n; /* iterates over tree elements */ + int n; /* iterates over tree elements */ - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; } #define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ #define pqremove(s, tree, top) \ {\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ } -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ #define smaller(tree, n, m, depth) \ (tree[n].Freq < tree[m].Freq || \ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ local void pqdownheap (deflate_state *s, - ct_data *tree, /* the tree to restore */ - int k) /* node to move down */ + ct_data *tree, /* the tree to restore */ + int k) /* node to move down */ { - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + if (smaller(tree, v, s->heap[j], s->depth)) break; - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; + s->heap[k] = s->heap[j]; k = j; - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; + j <<= 1; + } + s->heap[k] = v; } -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ local void gen_bitlen (deflate_state *s, tree_desc *desc) { - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; - if (n > max_code) continue; /* not a leaf node */ + if (n > max_code) continue; /* not a leaf node */ - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); - } - if (overflow == 0) return; + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; - Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ + Trace((stderr,"\nbit length overflow\n")); - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + overflow -= 2; + } while (overflow > 0); - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if ((unsigned) tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } } -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes (ct_data *tree, /* the tree to decorate */ - int max_code, /* largest code with non zero frequency */ - ushf *bl_count) /* number of codes at each bit length */ +local void gen_codes (ct_data *tree, /* the tree to decorate */ + int max_code, /* largest code with non zero frequency */ + ushf *bl_count) /* number of codes at each bit length */ { - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; + s->heap_len = 0, s->heap_max = HEAP_SIZE; - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + } + desc->max_code = max_code; - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? - s->depth[n] : s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; #ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } #endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); - } while (s->heap_len >= 2); + } while (s->heap_len >= 2); - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); + gen_bitlen(s, (tree_desc *)desc); - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); + gen_codes ((ct_data *)tree, max_code, s->bl_count); } -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ local void scan_tree (deflate_state *s, - ct_data *tree, /* the tree to be scanned */ - int max_code) /* and its largest code of non zero frequency */ + ct_data *tree, /* the tree to be scanned */ + int max_code) /* and its largest code of non zero frequency */ { - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } } -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ local void send_tree (deflate_state *s, - ct_data *tree, /* the tree to be scanned */ - int max_code) /* and its largest code of non zero frequency */ + ct_data *tree, /* the tree to be scanned */ + int max_code) /* and its largest code of non zero frequency */ { - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; + /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } } -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ local int build_bl_tree (deflate_state *s) { - int max_blindex; /* index of last bit length code of non zero freq */ + int max_blindex; /* index of last bit length code of non zero freq */ - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - s->opt_len, s->static_len)); + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); - return max_blindex; + return max_blindex; } -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ local void send_all_trees (deflate_state *s, - int lcodes, int dcodes, int blcodes) /* number of codes for each tree */ + int lcodes, int dcodes, int blcodes) /* number of codes for each tree */ { - int rank; /* index in bl_order */ + int rank; /* index in bl_order */ - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } -/* =========================================================================== - * Send a stored block - */ void _tr_stored_block (deflate_state *s, charf *buf, ulg stored_len, int eof) { - send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ #ifdef DEBUG - s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; - s->compressed_len += (stored_len + 4) << 3; + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; #endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - * The current inflate code requires 9 bits of lookahead. If the - * last two codes for the previous block (real code plus EOB) were coded - * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - * the last real code. In this case we send two empty static blocks instead - * of one. (There are no problems if the previous block is stored or fixed.) - * To simplify the code, we assume the worst case of last real code encoded - * on one bit only. - */ void _tr_align (deflate_state *s) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif - bi_flush(s); - /* Of the 10 bits for the empty block, we have already sent - * (10 - bi_valid) bits. The lookahead for the last real code (before - * the EOB of the previous block) was thus at least one plus the length - * of the EOB plus what we have just sent of the empty static block. - */ - if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); + bi_flush(s); + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG - s->compressed_len += 10L; + s->compressed_len += 10L; #endif - bi_flush(s); - } - s->last_eob_len = 7; + bi_flush(s); + } + s->last_eob_len = 7; } -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ void _tr_flush_block (deflate_state *s, - charf *buf, /* input block, or NULL if too old */ - ulg stored_len, /* length of input block */ - int eof) /* true if this is the last block for a file */ + charf *buf, /* input block, or NULL if too old */ + ulg stored_len, /* length of input block */ + int eof) /* true if this is the last block for a file */ { - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { + if (s->level > 0) { - /* Check if the file is binary or text */ - if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) - set_data_type(s); + if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) + set_data_type(s); - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); + max_blindex = build_bl_tree(s); - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - } else { - Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } #ifdef FORCE_STORED - if (buf != (char*)0) { /* force stored block */ + if (buf != (char*)0) { /* force stored block */ #else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { - /* 4: two words for the lengths */ + if (stored_len+4 <= opt_lenb && buf != (char*)0) { #endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, eof); + _tr_stored_block(s, buf, stored_len, eof); #ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ + } else if (static_lenb >= 0) { /* force static trees */ #else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { #endif - send_bits(s, (STATIC_TREES<<1)+eof, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); #ifdef DEBUG - s->compressed_len += 3 + s->static_len; + s->compressed_len += 3 + s->static_len; #endif - } else { - send_bits(s, (DYN_TREES<<1)+eof, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); #ifdef DEBUG - s->compressed_len += 3 + s->opt_len; + s->compressed_len += 3 + s->opt_len; #endif - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + init_block(s); - if (eof) { - bi_windup(s); + if (eof) { + bi_windup(s); #ifdef DEBUG - s->compressed_len += 7; /* align on byte boundary */ + s->compressed_len += 7; /* align on byte boundary */ #endif - } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*eof)); + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); } -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ int _tr_tally (deflate_state *s, - unsigned dist, /* distance of matched string */ - unsigned lc) /* match length-MIN_MATCH or unmatched char (if dist==0) */ + unsigned dist, /* distance of matched string */ + unsigned lc) /* match length-MIN_MATCH or unmatched char (if dist==0) */ { - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } #ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } #endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ + return (s->last_lit == s->lit_bufsize-1); } -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ local void compress_block (deflate_state *s, - ct_data *ltree, /* literal tree */ - ct_data *dtree) /* distance tree */ + ct_data *ltree, /* literal tree */ + ct_data *dtree) /* distance tree */ { - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - "pendingBuf overflow"); + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); - } while (lx < s->last_lit); + } while (lx < s->last_lit); - send_code(s, END_BLOCK, ltree); - s->last_eob_len = ltree[END_BLOCK].Len; + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; } -/* =========================================================================== - * Set the data type to BINARY or TEXT, using a crude approximation: - * set it to Z_TEXT if all symbols are either printable characters (33 to 255) - * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. - * IN assertion: the fields Freq of dyn_ltree are set. - */ local void set_data_type (deflate_state *s) { - int n; + int n; - for (n = 0; n < 9; n++) - if (s->dyn_ltree[n].Freq != 0) - break; - if (n == 9) - for (n = 14; n < 32; n++) - if (s->dyn_ltree[n].Freq != 0) - break; - s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; + for (n = 0; n < 9; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + if (n == 9) + for (n = 14; n < 32; n++) + if (s->dyn_ltree[n].Freq != 0) + break; + s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; } -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ local unsigned bi_reverse (unsigned code, int len) { - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; } -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ local void bi_flush (deflate_state *s) { - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } } -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ local void bi_windup (deflate_state *s) { - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; #ifdef DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; + s->bits_sent = (s->bits_sent+7) & ~7; #endif } -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ local void copy_block(deflate_state *s, - charf *buf, /* the input data */ - unsigned len, /* its length */ - int header) /* true if block header must be written */ + charf *buf, /* the input data */ + unsigned len, /* its length */ + int header) /* true if block header must be written */ { - bi_windup(s); /* align on byte boundary */ - s->last_eob_len = 8; /* enough lookahead for inflate */ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); #ifdef DEBUG - s->bits_sent += 2*16; + s->bits_sent += 2*16; #endif - } + } #ifdef DEBUG - s->bits_sent += (ulg)len<<3; + s->bits_sent += (ulg)len<<3; #endif - while (len--) { - put_byte(s, *buf++); - } + while (len--) { + put_byte(s, *buf++); + } } /********* End of inlined file: trees.c *********/ /********* Start of inlined file: zutil.c *********/ -/* @(#) $Id: zutil.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */ #ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ +struct internal_state {int dummy;}; /* for buggy compilers */ #endif const char * const z_errmsg[10] = { @@ -102307,242 +99470,127 @@ const char * const z_errmsg[10] = { "incompatible version",/* Z_VERSION_ERROR (-6) */ ""}; -/*const char * ZEXPORT zlibVersion() -{ - return ZLIB_VERSION; -} - -uLong ZEXPORT zlibCompileFlags() -{ - uLong flags; - - flags = 0; - switch (sizeof(uInt)) { - case 2: break; - case 4: flags += 1; break; - case 8: flags += 2; break; - default: flags += 3; - } - switch (sizeof(uLong)) { - case 2: break; - case 4: flags += 1 << 2; break; - case 8: flags += 2 << 2; break; - default: flags += 3 << 2; - } - switch (sizeof(voidpf)) { - case 2: break; - case 4: flags += 1 << 4; break; - case 8: flags += 2 << 4; break; - default: flags += 3 << 4; - } - switch (sizeof(z_off_t)) { - case 2: break; - case 4: flags += 1 << 6; break; - case 8: flags += 2 << 6; break; - default: flags += 3 << 6; - } -#ifdef DEBUG - flags += 1 << 8; -#endif -#if defined(ASMV) || defined(ASMINF) - flags += 1 << 9; -#endif -#ifdef ZLIB_WINAPI - flags += 1 << 10; -#endif -#ifdef BUILDFIXED - flags += 1 << 12; -#endif -#ifdef DYNAMIC_CRC_TABLE - flags += 1 << 13; -#endif -#ifdef NO_GZCOMPRESS - flags += 1L << 16; -#endif -#ifdef NO_GZIP - flags += 1L << 17; -#endif -#ifdef PKZIP_BUG_WORKAROUND - flags += 1L << 20; -#endif -#ifdef FASTEST - flags += 1L << 21; -#endif -#ifdef STDC -# ifdef NO_vsnprintf - flags += 1L << 25; -# ifdef HAS_vsprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_vsnprintf_void - flags += 1L << 26; -# endif -# endif -#else - flags += 1L << 24; -# ifdef NO_snprintf - flags += 1L << 25; -# ifdef HAS_sprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_snprintf_void - flags += 1L << 26; -# endif -# endif -#endif - return flags; -}*/ - #ifdef DEBUG # ifndef verbose -# define verbose 0 +# define verbose 0 # endif int z_verbose = verbose; void z_error (const char *m) { - fprintf(stderr, "%s\n", m); - exit(1); + fprintf(stderr, "%s\n", m); + exit(1); } #endif -/* exported to allow conversion of error code to string for compress() and - * uncompress() - */ const char * ZEXPORT zError(int err) { - return ERR_MSG(err); + return ERR_MSG(err); } #if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. - */ - int errno = 0; + int errno = 0; #endif #ifndef HAVE_MEMCPY void zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; + Bytef* dest; + const Bytef* source; + uInt len; { - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); } int zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; + const Bytef* s1; + const Bytef* s2; + uInt len; { - uInt j; + uInt j; - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; - } - return 0; + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; } void zmemzero(dest, len) - Bytef* dest; - uInt len; + Bytef* dest; + uInt len; { - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); } #endif #ifdef SYS16BIT #ifdef __TURBOC__ -/* Turbo C in 16-bit mode */ # define MY_ZCALLOC -/* Turbo C malloc() does not allow dynamic allocation of 64K bytes - * and farmalloc(64K) returns a pointer with an offset of 8, so we - * must fix the pointer. Warning: the pointer must be put back to its - * original form in order to free it, use zcfree(). - */ - #define MAX_PTR 10 -/* 10*64K = 640K */ local int next_ptr = 0; typedef struct ptr_table_s { - voidpf org_ptr; - voidpf new_ptr; + voidpf org_ptr; + voidpf new_ptr; } ptr_table; local ptr_table table[MAX_PTR]; -/* This table is used to remember the original form of pointers - * to large buffers (64K). Such pointers are normalized with a zero offset. - * Since MSDOS is not a preemptive multitasking OS, this table is not - * protected from concurrent access. This hack doesn't work anyway on - * a protected system like OS/2. Use Microsoft C instead. - */ voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) { - voidpf buf = opaque; /* just to make some compilers happy */ - ulg bsize = (ulg)items*size; + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; - /* If we allocate less than 65520 bytes, we assume that farmalloc - * will return a usable pointer which doesn't have to be normalized. - */ - if (bsize < 65520L) { - buf = farmalloc(bsize); - if (*(ush*)&buf != 0) return buf; - } else { - buf = farmalloc(bsize + 16L); - } - if (buf == NULL || next_ptr >= MAX_PTR) return NULL; - table[next_ptr].org_ptr = buf; + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; - /* Normalize the pointer to seg:0 */ - *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; - *(ush*)&buf = 0; - table[next_ptr++].new_ptr = buf; - return buf; + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; } void zcfree (voidpf opaque, voidpf ptr) { - int n; - if (*(ush*)&ptr != 0) { /* object < 64K */ - farfree(ptr); - return; - } - /* Find the original pointer */ - for (n = 0; n < next_ptr; n++) { - if (ptr != table[n].new_ptr) continue; + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; - farfree(table[n].org_ptr); - while (++n < next_ptr) { - table[n-1] = table[n]; - } - next_ptr--; - return; - } - ptr = opaque; /* just to make some compilers happy */ - Assert(0, "zcfree: ptr not found"); + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); } #endif /* __TURBOC__ */ #ifdef M_I86 -/* Microsoft C in 16-bit mode */ # define MY_ZCALLOC @@ -102553,14 +99601,14 @@ void zcfree (voidpf opaque, voidpf ptr) voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) { - if (opaque) opaque = 0; /* to make compiler happy */ - return _halloc((long)items, size); + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); } void zcfree (voidpf opaque, voidpf ptr) { - if (opaque) opaque = 0; /* to make compiler happy */ - _hfree(ptr); + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); } #endif /* M_I86 */ @@ -102577,21 +99625,21 @@ extern void free OF((voidpf ptr)); voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) { - if (opaque) items += size - size; /* make compiler happy */ - return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : - (voidpf)calloc(items, size); + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); } void zcfree (voidpf opaque, voidpf ptr) { - free(ptr); - if (opaque) return; /* make compiler happy */ + free(ptr); + if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ /********* End of inlined file: zutil.c *********/ - #undef Byte + #undef Byte } #else #include @@ -102611,95 +99659,95 @@ using namespace zlibNamespace; class GZIPDecompressHelper { public: - GZIPDecompressHelper (const bool noWrap) throw() - : data (0), - dataSize (0), - finished (true), - needsDictionary (false), - error (true), - streamIsValid (false) - { - zerostruct (stream); - streamIsValid = (inflateInit2 (&stream, noWrap ? -MAX_WBITS : MAX_WBITS) == Z_OK); - finished = error = ! streamIsValid; - } + GZIPDecompressHelper (const bool noWrap) throw() + : data (0), + dataSize (0), + finished (true), + needsDictionary (false), + error (true), + streamIsValid (false) + { + zerostruct (stream); + streamIsValid = (inflateInit2 (&stream, noWrap ? -MAX_WBITS : MAX_WBITS) == Z_OK); + finished = error = ! streamIsValid; + } - ~GZIPDecompressHelper() throw() - { - if (streamIsValid) - inflateEnd (&stream); - } + ~GZIPDecompressHelper() throw() + { + if (streamIsValid) + inflateEnd (&stream); + } - bool needsInput() const throw() { return dataSize <= 0; } + bool needsInput() const throw() { return dataSize <= 0; } - void setInput (uint8* const data_, const int size) throw() - { - data = data_; - dataSize = size; - } + void setInput (uint8* const data_, const int size) throw() + { + data = data_; + dataSize = size; + } - int doNextBlock (uint8* const dest, const int destSize) throw() - { - if (streamIsValid && data != 0 && ! finished) - { - stream.next_in = data; - stream.next_out = dest; - stream.avail_in = dataSize; - stream.avail_out = destSize; + int doNextBlock (uint8* const dest, const int destSize) throw() + { + if (streamIsValid && data != 0 && ! finished) + { + stream.next_in = data; + stream.next_out = dest; + stream.avail_in = dataSize; + stream.avail_out = destSize; - switch (inflate (&stream, Z_PARTIAL_FLUSH)) - { - case Z_STREAM_END: - finished = true; - // deliberate fall-through - case Z_OK: - data += dataSize - stream.avail_in; - dataSize = stream.avail_in; - return destSize - stream.avail_out; + switch (inflate (&stream, Z_PARTIAL_FLUSH)) + { + case Z_STREAM_END: + finished = true; + // deliberate fall-through + case Z_OK: + data += dataSize - stream.avail_in; + dataSize = stream.avail_in; + return destSize - stream.avail_out; - case Z_NEED_DICT: - needsDictionary = true; - data += dataSize - stream.avail_in; - dataSize = stream.avail_in; - break; + case Z_NEED_DICT: + needsDictionary = true; + data += dataSize - stream.avail_in; + dataSize = stream.avail_in; + break; - case Z_DATA_ERROR: - case Z_MEM_ERROR: - error = true; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + error = true; - default: - break; - } - } + default: + break; + } + } - return 0; - } + return 0; + } private: - z_stream stream; - uint8* data; - int dataSize; + z_stream stream; + uint8* data; + int dataSize; public: - bool finished, needsDictionary, error, streamIsValid; + bool finished, needsDictionary, error, streamIsValid; }; const int gzipDecompBufferSize = 32768; GZIPDecompressorInputStream::GZIPDecompressorInputStream (InputStream* const sourceStream_, - const bool deleteSourceWhenDestroyed, - const bool noWrap_, - const int64 uncompressedStreamLength_) + const bool deleteSourceWhenDestroyed, + const bool noWrap_, + const int64 uncompressedStreamLength_) : sourceStream (sourceStream_), - streamToDelete (deleteSourceWhenDestroyed ? sourceStream_ : 0), - uncompressedStreamLength (uncompressedStreamLength_), - noWrap (noWrap_), - isEof (false), - activeBufferSize (0), - originalSourcePos (sourceStream_->getPosition()), - currentPos (0), - buffer (gzipDecompBufferSize), - helper (new GZIPDecompressHelper (noWrap_)) + streamToDelete (deleteSourceWhenDestroyed ? sourceStream_ : 0), + uncompressedStreamLength (uncompressedStreamLength_), + noWrap (noWrap_), + isEof (false), + activeBufferSize (0), + originalSourcePos (sourceStream_->getPosition()), + currentPos (0), + buffer (gzipDecompBufferSize), + helper (new GZIPDecompressHelper (noWrap_)) { } @@ -102709,89 +99757,89 @@ GZIPDecompressorInputStream::~GZIPDecompressorInputStream() int64 GZIPDecompressorInputStream::getTotalLength() { - return uncompressedStreamLength; + return uncompressedStreamLength; } int GZIPDecompressorInputStream::read (void* destBuffer, int howMany) { - if ((howMany > 0) && ! isEof) - { - jassert (destBuffer != 0); + if ((howMany > 0) && ! isEof) + { + jassert (destBuffer != 0); - if (destBuffer != 0) - { - int numRead = 0; - uint8* d = (uint8*) destBuffer; + if (destBuffer != 0) + { + int numRead = 0; + uint8* d = (uint8*) destBuffer; - while (! helper->error) - { - const int n = helper->doNextBlock (d, howMany); - currentPos += n; + while (! helper->error) + { + const int n = helper->doNextBlock (d, howMany); + currentPos += n; - if (n == 0) - { - if (helper->finished || helper->needsDictionary) - { - isEof = true; - return numRead; - } + if (n == 0) + { + if (helper->finished || helper->needsDictionary) + { + isEof = true; + return numRead; + } - if (helper->needsInput()) - { - activeBufferSize = sourceStream->read (buffer, gzipDecompBufferSize); + if (helper->needsInput()) + { + activeBufferSize = sourceStream->read (buffer, gzipDecompBufferSize); - if (activeBufferSize > 0) - { - helper->setInput ((uint8*) buffer, activeBufferSize); - } - else - { - isEof = true; - return numRead; - } - } - } - else - { - numRead += n; - howMany -= n; - d += n; + if (activeBufferSize > 0) + { + helper->setInput ((uint8*) buffer, activeBufferSize); + } + else + { + isEof = true; + return numRead; + } + } + } + else + { + numRead += n; + howMany -= n; + d += n; - if (howMany <= 0) - return numRead; - } - } - } - } + if (howMany <= 0) + return numRead; + } + } + } + } - return 0; + return 0; } bool GZIPDecompressorInputStream::isExhausted() { - return helper->error || isEof; + return helper->error || isEof; } int64 GZIPDecompressorInputStream::getPosition() { - return currentPos; + return currentPos; } bool GZIPDecompressorInputStream::setPosition (int64 newPos) { - if (newPos < currentPos) - { - // to go backwards, reset the stream and start again.. - isEof = false; - activeBufferSize = 0; - currentPos = 0; - helper = new GZIPDecompressHelper (noWrap); + if (newPos < currentPos) + { + // to go backwards, reset the stream and start again.. + isEof = false; + activeBufferSize = 0; + currentPos = 0; + helper = new GZIPDecompressHelper (noWrap); - sourceStream->setPosition (originalSourcePos); - } + sourceStream->setPosition (originalSourcePos); + } - skipNextBytes (newPos - currentPos); - return true; + skipNextBytes (newPos - currentPos); + return true; } END_JUCE_NAMESPACE @@ -102831,29 +99879,6 @@ namespace FlacNamespace #ifndef FLAC__EXPORT_H #define FLAC__EXPORT_H -/** \file include/FLAC/export.h - * - * \brief - * This module contains #defines and symbols for exporting function - * calls, and providing version information and compiled-in features. - * - * See the \link flac_export export \endlink module. - */ - -/** \defgroup flac_export FLAC/export.h: export symbols - * \ingroup flac - * - * \brief - * This module contains #defines and symbols for exporting function - * calls, and providing version information and compiled-in features. - * - * If you are compiling with MSVC and will link to the static library - * (libFLAC.lib) you should define FLAC__NO_DLL in your project to - * make sure the symbols are exported properly. - * - * \{ - */ - #if defined(FLAC__NO_DLL) || !defined(_MSC_VER) #define FLAC_API @@ -102867,9 +99892,6 @@ namespace FlacNamespace #endif #endif -/** These #defines will mirror the libtool-based library version number, see - * http://www.gnu.org/software/libtool/manual.html#Libtool-versioning - */ #define FLAC_API_VERSION_CURRENT 10 #define FLAC_API_VERSION_REVISION 0 /**< see above */ #define FLAC_API_VERSION_AGE 2 /**< see above */ @@ -102878,15 +99900,12 @@ namespace FlacNamespace extern "C" { #endif -/** \c 1 if the library has been compiled with support for Ogg FLAC, else \c 0. */ extern FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC; #ifdef __cplusplus } #endif -/* \} */ - #endif /********* End of inlined file: export.h *********/ @@ -102965,137 +99984,24 @@ typedef FLAC__uint8 FLAC__byte; #include /* for size_t */ -/** \file include/FLAC/callback.h - * - * \brief - * This module defines the structures for describing I/O callbacks - * to the other FLAC interfaces. - * - * See the detailed documentation for callbacks in the - * \link flac_callbacks callbacks \endlink module. - */ - -/** \defgroup flac_callbacks FLAC/callback.h: I/O callback structures - * \ingroup flac - * - * \brief - * This module defines the structures for describing I/O callbacks - * to the other FLAC interfaces. - * - * The purpose of the I/O callback functions is to create a common way - * for the metadata interfaces to handle I/O. - * - * Originally the metadata interfaces required filenames as the way of - * specifying FLAC files to operate on. This is problematic in some - * environments so there is an additional option to specify a set of - * callbacks for doing I/O on the FLAC file, instead of the filename. - * - * In addition to the callbacks, a FLAC__IOHandle type is defined as an - * opaque structure for a data source. - * - * The callback function prototypes are similar (but not identical) to the - * stdio functions fread, fwrite, fseek, ftell, feof, and fclose. If you use - * stdio streams to implement the callbacks, you can pass fread, fwrite, and - * fclose anywhere a FLAC__IOCallback_Read, FLAC__IOCallback_Write, or - * FLAC__IOCallback_Close is required, and a FILE* anywhere a FLAC__IOHandle - * is required. \warning You generally CANNOT directly use fseek or ftell - * for FLAC__IOCallback_Seek or FLAC__IOCallback_Tell since on most systems - * these use 32-bit offsets and FLAC requires 64-bit offsets to deal with - * large files. You will have to find an equivalent function (e.g. ftello), - * or write a wrapper. The same is true for feof() since this is usually - * implemented as a macro, not as a function whose address can be taken. - * - * \{ - */ - #ifdef __cplusplus extern "C" { #endif -/** This is the opaque handle type used by the callbacks. Typically - * this is a \c FILE* or address of a file descriptor. - */ typedef void* FLAC__IOHandle; -/** Signature for the read callback. - * The signature and semantics match POSIX fread() implementations - * and can generally be used interchangeably. - * - * \param ptr The address of the read buffer. - * \param size The size of the records to be read. - * \param nmemb The number of records to be read. - * \param handle The handle to the data source. - * \retval size_t - * The number of records read. - */ typedef size_t (*FLAC__IOCallback_Read) (void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle); -/** Signature for the write callback. - * The signature and semantics match POSIX fwrite() implementations - * and can generally be used interchangeably. - * - * \param ptr The address of the write buffer. - * \param size The size of the records to be written. - * \param nmemb The number of records to be written. - * \param handle The handle to the data source. - * \retval size_t - * The number of records written. - */ typedef size_t (*FLAC__IOCallback_Write) (const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle); -/** Signature for the seek callback. - * The signature and semantics mostly match POSIX fseek() WITH ONE IMPORTANT - * EXCEPTION: the offset is a 64-bit type whereas fseek() is generally 'long' - * and 32-bits wide. - * - * \param handle The handle to the data source. - * \param offset The new position, relative to \a whence - * \param whence \c SEEK_SET, \c SEEK_CUR, or \c SEEK_END - * \retval int - * \c 0 on success, \c -1 on error. - */ typedef int (*FLAC__IOCallback_Seek) (FLAC__IOHandle handle, FLAC__int64 offset, int whence); -/** Signature for the tell callback. - * The signature and semantics mostly match POSIX ftell() WITH ONE IMPORTANT - * EXCEPTION: the offset is a 64-bit type whereas ftell() is generally 'long' - * and 32-bits wide. - * - * \param handle The handle to the data source. - * \retval FLAC__int64 - * The current position on success, \c -1 on error. - */ typedef FLAC__int64 (*FLAC__IOCallback_Tell) (FLAC__IOHandle handle); -/** Signature for the EOF callback. - * The signature and semantics mostly match POSIX feof() but WATCHOUT: - * on many systems, feof() is a macro, so in this case a wrapper function - * must be provided instead. - * - * \param handle The handle to the data source. - * \retval int - * \c 0 if not at end of file, nonzero if at end of file. - */ typedef int (*FLAC__IOCallback_Eof) (FLAC__IOHandle handle); -/** Signature for the close callback. - * The signature and semantics match POSIX fclose() implementations - * and can generally be used interchangeably. - * - * \param handle The handle to the data source. - * \retval int - * \c 0 on success, \c EOF on error. - */ typedef int (*FLAC__IOCallback_Close) (FLAC__IOHandle handle); -/** A structure for holding a set of callbacks. - * Each FLAC interface that requires a FLAC__IOCallbacks structure will - * describe which of the callbacks are required. The ones that are not - * required may be set to NULL. - * - * If the seek requirement for an interface is optional, you can signify that - * a data sorce is not seekable by setting the \a seek field to \c NULL. - */ typedef struct { FLAC__IOCallback_Read read; FLAC__IOCallback_Write write; @@ -103105,8 +100011,6 @@ typedef struct { FLAC__IOCallback_Close close; } FLAC__IOCallbacks; -/* \} */ - #ifdef __cplusplus } #endif @@ -103122,200 +100026,72 @@ typedef struct { extern "C" { #endif -/** \file include/FLAC/format.h - * - * \brief - * This module contains structure definitions for the representation - * of FLAC format components in memory. These are the basic - * structures used by the rest of the interfaces. - * - * See the detailed documentation in the - * \link flac_format format \endlink module. - */ - -/** \defgroup flac_format FLAC/format.h: format components - * \ingroup flac - * - * \brief - * This module contains structure definitions for the representation - * of FLAC format components in memory. These are the basic - * structures used by the rest of the interfaces. - * - * First, you should be familiar with the - * FLAC format. Many of the values here - * follow directly from the specification. As a user of libFLAC, the - * interesting parts really are the structures that describe the frame - * header and metadata blocks. - * - * The format structures here are very primitive, designed to store - * information in an efficient way. Reading information from the - * structures is easy but creating or modifying them directly is - * more complex. For the most part, as a user of a library, editing - * is not necessary; however, for metadata blocks it is, so there are - * convenience functions provided in the \link flac_metadata metadata - * module \endlink to simplify the manipulation of metadata blocks. - * - * \note - * It's not the best convention, but symbols ending in _LEN are in bits - * and _LENGTH are in bytes. _LENGTH symbols are \#defines instead of - * global variables because they are usually used when declaring byte - * arrays and some compilers require compile-time knowledge of array - * sizes when declared on the stack. - * - * \{ - */ - -/* - Most of the values described in this file are defined by the FLAC - format specification. There is nothing to tune here. -*/ - -/** The largest legal metadata type code. */ #define FLAC__MAX_METADATA_TYPE_CODE (126u) -/** The minimum block size, in samples, permitted by the format. */ #define FLAC__MIN_BLOCK_SIZE (16u) -/** The maximum block size, in samples, permitted by the format. */ #define FLAC__MAX_BLOCK_SIZE (65535u) -/** The maximum block size, in samples, permitted by the FLAC subset for - * sample rates up to 48kHz. */ #define FLAC__SUBSET_MAX_BLOCK_SIZE_48000HZ (4608u) -/** The maximum number of channels permitted by the format. */ #define FLAC__MAX_CHANNELS (8u) -/** The minimum sample resolution permitted by the format. */ #define FLAC__MIN_BITS_PER_SAMPLE (4u) -/** The maximum sample resolution permitted by the format. */ #define FLAC__MAX_BITS_PER_SAMPLE (32u) -/** The maximum sample resolution permitted by libFLAC. - * - * \warning - * FLAC__MAX_BITS_PER_SAMPLE is the limit of the FLAC format. However, - * the reference encoder/decoder is currently limited to 24 bits because - * of prevalent 32-bit math, so make sure and use this value when - * appropriate. - */ #define FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE (24u) -/** The maximum sample rate permitted by the format. The value is - * ((2 ^ 16) - 1) * 10; see FLAC format - * as to why. - */ #define FLAC__MAX_SAMPLE_RATE (655350u) -/** The maximum LPC order permitted by the format. */ #define FLAC__MAX_LPC_ORDER (32u) -/** The maximum LPC order permitted by the FLAC subset for sample rates - * up to 48kHz. */ #define FLAC__SUBSET_MAX_LPC_ORDER_48000HZ (12u) -/** The minimum quantized linear predictor coefficient precision - * permitted by the format. - */ #define FLAC__MIN_QLP_COEFF_PRECISION (5u) -/** The maximum quantized linear predictor coefficient precision - * permitted by the format. - */ #define FLAC__MAX_QLP_COEFF_PRECISION (15u) -/** The maximum order of the fixed predictors permitted by the format. */ #define FLAC__MAX_FIXED_ORDER (4u) -/** The maximum Rice partition order permitted by the format. */ #define FLAC__MAX_RICE_PARTITION_ORDER (15u) -/** The maximum Rice partition order permitted by the FLAC Subset. */ #define FLAC__SUBSET_MAX_RICE_PARTITION_ORDER (8u) -/** The version string of the release, stamped onto the libraries and binaries. - * - * \note - * This does not correspond to the shared library version number, which - * is used to determine binary compatibility. - */ extern FLAC_API const char *FLAC__VERSION_STRING; -/** The vendor string inserted by the encoder into the VORBIS_COMMENT block. - * This is a NUL-terminated ASCII string; when inserted into the - * VORBIS_COMMENT the trailing null is stripped. - */ extern FLAC_API const char *FLAC__VENDOR_STRING; -/** The byte string representation of the beginning of a FLAC stream. */ extern FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */ -/** The 32-bit integer big-endian representation of the beginning of - * a FLAC stream. - */ extern FLAC_API const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */ -/** The length of the FLAC signature in bits. */ extern FLAC_API const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */ -/** The length of the FLAC signature in bytes. */ #define FLAC__STREAM_SYNC_LENGTH (4u) -/***************************************************************************** - * - * Subframe structures - * - *****************************************************************************/ - -/*****************************************************************************/ - -/** An enumeration of the available entropy coding methods. */ typedef enum { FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE = 0, - /**< Residual is coded by partitioning into contexts, each with it's own - * 4-bit Rice parameter. */ FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 = 1 - /**< Residual is coded by partitioning into contexts, each with it's own - * 5-bit Rice parameter. */ } FLAC__EntropyCodingMethodType; -/** Maps a FLAC__EntropyCodingMethodType to a C string. - * - * Using a FLAC__EntropyCodingMethodType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[]; -/** Contents of a Rice partitioned residual - */ typedef struct { unsigned *parameters; - /**< The Rice parameters for each context. */ unsigned *raw_bits; - /**< Widths for escape-coded partitions. Will be non-zero for escaped - * partitions and zero for unescaped partitions. - */ unsigned capacity_by_order; - /**< The capacity of the \a parameters and \a raw_bits arrays - * specified as an order, i.e. the number of array elements - * allocated is 2 ^ \a capacity_by_order. - */ } FLAC__EntropyCodingMethod_PartitionedRiceContents; -/** Header for a Rice partitioned residual. (c.f. format specification) - */ typedef struct { unsigned order; - /**< The partition order, i.e. # of contexts = 2 ^ \a order. */ const FLAC__EntropyCodingMethod_PartitionedRiceContents *contents; - /**< The context's Rice parameters and/or raw bits. */ } FLAC__EntropyCodingMethod_PartitionedRice; @@ -103325,12 +100101,8 @@ extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PAR extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN; /**< == 5 (bits) */ extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; -/**< == (1<format specification) - */ typedef struct { FLAC__EntropyCodingMethodType type; union { @@ -103340,9 +100112,6 @@ typedef struct { extern FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN; /**< == 2 (bits) */ -/*****************************************************************************/ - -/** An enumeration of the available subframe types. */ typedef enum { FLAC__SUBFRAME_TYPE_CONSTANT = 0, /**< constant signal */ FLAC__SUBFRAME_TYPE_VERBATIM = 1, /**< uncompressed signal */ @@ -103350,71 +100119,45 @@ typedef enum { FLAC__SUBFRAME_TYPE_LPC = 3 /**< linear prediction */ } FLAC__SubframeType; -/** Maps a FLAC__SubframeType to a C string. - * - * Using a FLAC__SubframeType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__SubframeTypeString[]; -/** CONSTANT subframe. (c.f. format specification) - */ typedef struct { FLAC__int32 value; /**< The constant signal value. */ } FLAC__Subframe_Constant; -/** VERBATIM subframe. (c.f. format specification) - */ typedef struct { const FLAC__int32 *data; /**< A pointer to verbatim signal. */ } FLAC__Subframe_Verbatim; -/** FIXED subframe. (c.f. format specification) - */ typedef struct { FLAC__EntropyCodingMethod entropy_coding_method; - /**< The residual coding method. */ unsigned order; - /**< The polynomial order. */ FLAC__int32 warmup[FLAC__MAX_FIXED_ORDER]; - /**< Warmup samples to prime the predictor, length == order. */ const FLAC__int32 *residual; - /**< The residual signal, length == (blocksize minus order) samples. */ } FLAC__Subframe_Fixed; -/** LPC subframe. (c.f. format specification) - */ typedef struct { FLAC__EntropyCodingMethod entropy_coding_method; - /**< The residual coding method. */ unsigned order; - /**< The FIR order. */ unsigned qlp_coeff_precision; - /**< Quantized FIR filter coefficient precision in bits. */ int quantization_level; - /**< The qlp coeff shift needed. */ FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER]; - /**< FIR filter coefficients. */ FLAC__int32 warmup[FLAC__MAX_LPC_ORDER]; - /**< Warmup samples to prime the predictor, length == order. */ const FLAC__int32 *residual; - /**< The residual signal, length == (blocksize minus order) samples. */ } FLAC__Subframe_LPC; extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN; /**< == 4 (bits) */ extern FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN; /**< == 5 (bits) */ -/** FLAC subframe structure. (c.f. format specification) - */ typedef struct { FLAC__SubframeType type; union { @@ -103426,13 +100169,6 @@ typedef struct { unsigned wasted_bits; } FLAC__Subframe; -/** == 1 (bit) - * - * This used to be a zero-padding bit (hence the name - * FLAC__SUBFRAME_ZERO_PAD_LEN) but is now a reserved bit. It still has a - * mandatory value of \c 0 but in the future may take on the value \c 0 or \c 1 - * to mean something else. - */ extern FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN; extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN; /**< == 6 (bits) */ extern FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN; /**< == 1 (bit) */ @@ -103442,15 +100178,6 @@ extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK; / extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK; /**< = 0x10 */ extern FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK; /**< = 0x40 */ -/*****************************************************************************/ - -/***************************************************************************** - * - * Frame structures - * - *****************************************************************************/ - -/** An enumeration of the available channel assignments. */ typedef enum { FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT = 0, /**< independent channels */ FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE = 1, /**< left+side stereo */ @@ -103458,61 +100185,34 @@ typedef enum { FLAC__CHANNEL_ASSIGNMENT_MID_SIDE = 3 /**< mid+side stereo */ } FLAC__ChannelAssignment; -/** Maps a FLAC__ChannelAssignment to a C string. - * - * Using a FLAC__ChannelAssignment as the index to this array will - * give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__ChannelAssignmentString[]; -/** An enumeration of the possible frame numbering methods. */ typedef enum { FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER, /**< number contains the frame number */ FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER /**< number contains the sample number of first sample in frame */ } FLAC__FrameNumberType; -/** Maps a FLAC__FrameNumberType to a C string. - * - * Using a FLAC__FrameNumberType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__FrameNumberTypeString[]; -/** FLAC frame header structure. (c.f. format specification) - */ typedef struct { unsigned blocksize; - /**< The number of samples per subframe. */ unsigned sample_rate; - /**< The sample rate in Hz. */ unsigned channels; - /**< The number of channels (== number of subframes). */ FLAC__ChannelAssignment channel_assignment; - /**< The channel assignment for the frame. */ unsigned bits_per_sample; - /**< The sample resolution. */ FLAC__FrameNumberType number_type; - /**< The numbering scheme used for the frame. As a convenience, the - * decoder will always convert a frame number to a sample number because - * the rules are complex. */ union { FLAC__uint32 frame_number; FLAC__uint64 sample_number; } number; - /**< The frame number or sample number of first sample in frame; - * use the \a number_type value to determine which to use. */ FLAC__uint8 crc; - /**< CRC-8 (polynomial = x^8 + x^2 + x^1 + x^0, initialized with 0) - * of the raw frame header bytes, meaning everything before the CRC byte - * including the sync code. - */ } FLAC__FrameHeader; extern FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC; /**< == 0x3ffe; the frame header sync code */ @@ -103526,72 +100226,40 @@ extern FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN; /**< == 3 extern FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN; /**< == 1 (bit) */ extern FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN; /**< == 8 (bits) */ -/** FLAC frame footer structure. (c.f. format specification) - */ typedef struct { FLAC__uint16 crc; - /**< CRC-16 (polynomial = x^16 + x^15 + x^2 + x^0, initialized with - * 0) of the bytes before the crc, back to and including the frame header - * sync code. - */ } FLAC__FrameFooter; extern FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN; /**< == 16 (bits) */ -/** FLAC frame structure. (c.f. format specification) - */ typedef struct { FLAC__FrameHeader header; FLAC__Subframe subframes[FLAC__MAX_CHANNELS]; FLAC__FrameFooter footer; } FLAC__Frame; -/*****************************************************************************/ - -/***************************************************************************** - * - * Meta-data structures - * - *****************************************************************************/ - -/** An enumeration of the available metadata block types. */ typedef enum { FLAC__METADATA_TYPE_STREAMINFO = 0, - /**< STREAMINFO block */ FLAC__METADATA_TYPE_PADDING = 1, - /**< PADDING block */ FLAC__METADATA_TYPE_APPLICATION = 2, - /**< APPLICATION block */ FLAC__METADATA_TYPE_SEEKTABLE = 3, - /**< SEEKTABLE block */ FLAC__METADATA_TYPE_VORBIS_COMMENT = 4, - /**< VORBISCOMMENT block (a.k.a. FLAC tags) */ FLAC__METADATA_TYPE_CUESHEET = 5, - /**< CUESHEET block */ FLAC__METADATA_TYPE_PICTURE = 6, - /**< PICTURE block */ FLAC__METADATA_TYPE_UNDEFINED = 7 - /**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */ } FLAC__MetadataType; -/** Maps a FLAC__MetadataType to a C string. - * - * Using a FLAC__MetadataType as the index to this array will - * give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__MetadataTypeString[]; -/** FLAC STREAMINFO structure. (c.f. format specification) - */ typedef struct { unsigned min_blocksize, max_blocksize; unsigned min_framesize, max_framesize; @@ -103612,21 +100280,12 @@ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN; /**< == 36 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN; /**< == 128 (bits) */ -/** The total stream length of the STREAMINFO block in bytes. */ #define FLAC__STREAM_METADATA_STREAMINFO_LENGTH (34u) -/** FLAC PADDING structure. (c.f. format specification) - */ typedef struct { int dummy; - /**< Conceptually this is an empty struct since we don't store the - * padding bytes. Empty structs are not allowed by some C compilers, - * hence the dummy. - */ } FLAC__StreamMetadata_Padding; -/** FLAC APPLICATION structure. (c.f. format specification) - */ typedef struct { FLAC__byte id[4]; FLAC__byte *data; @@ -103634,56 +100293,27 @@ typedef struct { extern FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN; /**< == 32 (bits) */ -/** SeekPoint structure used in SEEKTABLE blocks. (c.f. format specification) - */ typedef struct { FLAC__uint64 sample_number; - /**< The sample number of the target frame. */ FLAC__uint64 stream_offset; - /**< The offset, in bytes, of the target frame with respect to - * beginning of the first frame. */ unsigned frame_samples; - /**< The number of samples in the target frame. */ } FLAC__StreamMetadata_SeekPoint; extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN; /**< == 64 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN; /**< == 64 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN; /**< == 16 (bits) */ -/** The total stream length of a seek point in bytes. */ #define FLAC__STREAM_METADATA_SEEKPOINT_LENGTH (18u) -/** The value used in the \a sample_number field of - * FLAC__StreamMetadataSeekPoint used to indicate a placeholder - * point (== 0xffffffffffffffff). - */ extern FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; -/** FLAC SEEKTABLE structure. (c.f. format specification) - * - * \note From the format specification: - * - The seek points must be sorted by ascending sample number. - * - Each seek point's sample number must be the first sample of the - * target frame. - * - Each seek point's sample number must be unique within the table. - * - Existence of a SEEKTABLE block implies a correct setting of - * total_samples in the stream_info block. - * - Behavior is undefined when more than one SEEKTABLE block is - * present in a stream. - */ typedef struct { unsigned num_points; FLAC__StreamMetadata_SeekPoint *points; } FLAC__StreamMetadata_SeekTable; -/** Vorbis comment entry structure used in VORBIS_COMMENT blocks. (c.f. format specification) - * - * For convenience, the APIs maintain a trailing NUL character at the end of - * \a entry which is not counted toward \a length, i.e. - * \code strlen(entry) == length \endcode - */ typedef struct { FLAC__uint32 length; FLAC__byte *entry; @@ -103691,8 +100321,6 @@ typedef struct { extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN; /**< == 32 (bits) */ -/** FLAC VORBIS_COMMENT structure. (c.f. format specification) - */ typedef struct { FLAC__StreamMetadata_VorbisComment_Entry vendor_string; FLAC__uint32 num_comments; @@ -103701,49 +100329,30 @@ typedef struct { extern FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN; /**< == 32 (bits) */ -/** FLAC CUESHEET track index structure. (See the - * format specification for - * the full description of each field.) - */ typedef struct { FLAC__uint64 offset; - /**< Offset in samples, relative to the track offset, of the index - * point. - */ FLAC__byte number; - /**< The index point number. */ } FLAC__StreamMetadata_CueSheet_Index; extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN; /**< == 64 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN; /**< == 8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN; /**< == 3*8 (bits) */ -/** FLAC CUESHEET track structure. (See the - * format specification for - * the full description of each field.) - */ typedef struct { FLAC__uint64 offset; - /**< Track offset in samples, relative to the beginning of the FLAC audio stream. */ FLAC__byte number; - /**< The track number. */ char isrc[13]; - /**< Track ISRC. This is a 12-digit alphanumeric code plus a trailing \c NUL byte */ unsigned type:1; - /**< The track type: 0 for audio, 1 for non-audio. */ unsigned pre_emphasis:1; - /**< The pre-emphasis flag: 0 for no pre-emphasis, 1 for pre-emphasis. */ FLAC__byte num_indices; - /**< The number of track index points. */ FLAC__StreamMetadata_CueSheet_Index *indices; - /**< NULL if num_indices == 0, else pointer to array of index points. */ } FLAC__StreamMetadata_CueSheet_Track; @@ -103755,28 +100364,16 @@ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN; /**< == 6+13*8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN; /**< == 8 (bits) */ -/** FLAC CUESHEET structure. (See the - * format specification - * for the full description of each field.) - */ typedef struct { char media_catalog_number[129]; - /**< Media catalog number, in ASCII printable characters 0x20-0x7e. In - * general, the media catalog number may be 0 to 128 bytes long; any - * unused characters should be right-padded with NUL characters. - */ FLAC__uint64 lead_in; - /**< The number of lead-in samples. */ FLAC__bool is_cd; - /**< \c true if CUESHEET corresponds to a Compact Disc, else \c false. */ unsigned num_tracks; - /**< The number of tracks. */ FLAC__StreamMetadata_CueSheet_Track *tracks; - /**< NULL if num_tracks == 0, else pointer to array of tracks. */ } FLAC__StreamMetadata_CueSheet; @@ -103786,7 +100383,6 @@ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN; /**< == extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN; /**< == 7+258*8 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN; /**< == 8 (bits) */ -/** An enumeration of the PICTURE types (see FLAC__StreamMetadataPicture and id3 v2.4 APIC tag). */ typedef enum { FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER = 0, /**< Other */ FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD = 1, /**< 32x32 pixels 'file icon' (PNG only) */ @@ -103812,59 +100408,26 @@ typedef enum { FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED } FLAC__StreamMetadata_Picture_Type; -/** Maps a FLAC__StreamMetadata_Picture_Type to a C string. - * - * Using a FLAC__StreamMetadata_Picture_Type as the index to this array - * will give the string equivalent. The contents should not be - * modified. - */ extern FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[]; -/** FLAC PICTURE structure. (See the - * format specification - * for the full description of each field.) - */ typedef struct { FLAC__StreamMetadata_Picture_Type type; - /**< The kind of picture stored. */ char *mime_type; - /**< Picture data's MIME type, in ASCII printable characters - * 0x20-0x7e, NUL terminated. For best compatibility with players, - * use picture data of MIME type \c image/jpeg or \c image/png. A - * MIME type of '-->' is also allowed, in which case the picture - * data should be a complete URL. In file storage, the MIME type is - * stored as a 32-bit length followed by the ASCII string with no NUL - * terminator, but is converted to a plain C string in this structure - * for convenience. - */ FLAC__byte *description; - /**< Picture's description in UTF-8, NUL terminated. In file storage, - * the description is stored as a 32-bit length followed by the UTF-8 - * string with no NUL terminator, but is converted to a plain C string - * in this structure for convenience. - */ FLAC__uint32 width; - /**< Picture's width in pixels. */ FLAC__uint32 height; - /**< Picture's height in pixels. */ FLAC__uint32 depth; - /**< Picture's color depth in bits-per-pixel. */ FLAC__uint32 colors; - /**< For indexed palettes (like GIF), picture's number of colors (the - * number of palette entries), or \c 0 for non-indexed (i.e. 2^depth). - */ FLAC__uint32 data_length; - /**< Length of binary picture data in bytes. */ FLAC__byte *data; - /**< Binary picture data. */ } FLAC__StreamMetadata_Picture; @@ -103877,27 +100440,16 @@ extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN; /**< == extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN; /**< == 32 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN; /**< == 32 (bits) */ -/** Structure that is used when a metadata block of unknown type is loaded. - * The contents are opaque. The structure is used only internally to - * correctly handle unknown metadata. - */ typedef struct { FLAC__byte *data; } FLAC__StreamMetadata_Unknown; -/** FLAC metadata block structure. (c.f. format specification) - */ typedef struct { FLAC__MetadataType type; - /**< The type of the metadata block; used determine which member of the - * \a data union to dereference. If type >= FLAC__METADATA_TYPE_UNDEFINED - * then \a data.unknown must be used. */ FLAC__bool is_last; - /**< \c true if this metadata block is the last, else \a false */ unsigned length; - /**< Length, in bytes, of the block data as it appears in the stream. */ union { FLAC__StreamMetadata_StreamInfo stream_info; @@ -103909,158 +100461,32 @@ typedef struct { FLAC__StreamMetadata_Picture picture; FLAC__StreamMetadata_Unknown unknown; } data; - /**< Polymorphic block data; use the \a type value to determine which - * to use. */ } FLAC__StreamMetadata; extern FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN; /**< == 1 (bit) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN; /**< == 7 (bits) */ extern FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN; /**< == 24 (bits) */ -/** The total stream length of a metadata block header in bytes. */ #define FLAC__STREAM_METADATA_HEADER_LENGTH (4u) -/*****************************************************************************/ - -/***************************************************************************** - * - * Utility functions - * - *****************************************************************************/ - -/** Tests that a sample rate is valid for FLAC. - * - * \param sample_rate The sample rate to test for compliance. - * \retval FLAC__bool - * \c true if the given sample rate conforms to the specification, else - * \c false. - */ FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate); -/** Tests that a sample rate is valid for the FLAC subset. The subset rules - * for valid sample rates are slightly more complex since the rate has to - * be expressible completely in the frame header. - * - * \param sample_rate The sample rate to test for compliance. - * \retval FLAC__bool - * \c true if the given sample rate conforms to the specification for the - * subset, else \c false. - */ FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate); -/** Check a Vorbis comment entry name to see if it conforms to the Vorbis - * comment specification. - * - * Vorbis comment names must be composed only of characters from - * [0x20-0x3C,0x3E-0x7D]. - * - * \param name A NUL-terminated string to be checked. - * \assert - * \code name != NULL \endcode - * \retval FLAC__bool - * \c false if entry name is illegal, else \c true. - */ FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *name); -/** Check a Vorbis comment entry value to see if it conforms to the Vorbis - * comment specification. - * - * Vorbis comment values must be valid UTF-8 sequences. - * - * \param value A string to be checked. - * \param length A the length of \a value in bytes. May be - * \c (unsigned)(-1) to indicate that \a value is a plain - * UTF-8 NUL-terminated string. - * \assert - * \code value != NULL \endcode - * \retval FLAC__bool - * \c false if entry name is illegal, else \c true. - */ FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length); -/** Check a Vorbis comment entry to see if it conforms to the Vorbis - * comment specification. - * - * Vorbis comment entries must be of the form 'name=value', and 'name' and - * 'value' must be legal according to - * FLAC__format_vorbiscomment_entry_name_is_legal() and - * FLAC__format_vorbiscomment_entry_value_is_legal() respectively. - * - * \param entry An entry to be checked. - * \param length The length of \a entry in bytes. - * \assert - * \code value != NULL \endcode - * \retval FLAC__bool - * \c false if entry name is illegal, else \c true. - */ FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length); -/** Check a seek table to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * seek table. - * - * \param seek_table A pointer to a seek table to be checked. - * \assert - * \code seek_table != NULL \endcode - * \retval FLAC__bool - * \c false if seek table is illegal, else \c true. - */ FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table); -/** Sort a seek table's seek points according to the format specification. - * This includes a "unique-ification" step to remove duplicates, i.e. - * seek points with identical \a sample_number values. Duplicate seek - * points are converted into placeholder points and sorted to the end of - * the table. - * - * \param seek_table A pointer to a seek table to be sorted. - * \assert - * \code seek_table != NULL \endcode - * \retval unsigned - * The number of duplicate seek points converted into placeholders. - */ FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table); -/** Check a cue sheet to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * cue sheet. - * - * \param cue_sheet A pointer to an existing cue sheet to be checked. - * \param check_cd_da_subset If \c true, check CUESHEET against more - * stringent requirements for a CD-DA (audio) disc. - * \param violation Address of a pointer to a string. If there is a - * violation, a pointer to a string explanation of the - * violation will be returned here. \a violation may be - * \c NULL if you don't need the returned string. Do not - * free the returned string; it will always point to static - * data. - * \assert - * \code cue_sheet != NULL \endcode - * \retval FLAC__bool - * \c false if cue sheet is illegal, else \c true. - */ FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation); -/** Check picture data to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * PICTURE block. - * - * \param picture A pointer to existing picture data to be checked. - * \param violation Address of a pointer to a string. If there is a - * violation, a pointer to a string explanation of the - * violation will be returned here. \a violation may be - * \c NULL if you don't need the returned string. Do not - * free the returned string; it will always point to static - * data. - * \assert - * \code picture != NULL \endcode - * \retval FLAC__bool - * \c false if picture data is illegal, else \c true. - */ FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation); -/* \} */ - #ifdef __cplusplus } #endif @@ -104074,2136 +100500,270 @@ FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Pic #include /* for off_t */ -/* -------------------------------------------------------------------- - (For an example of how all these routines are used, see the source - code for the unit tests in src/test_libFLAC/metadata_*.c, or - metaflac in src/metaflac/) - ------------------------------------------------------------------*/ - -/** \file include/FLAC/metadata.h - * - * \brief - * This module provides functions for creating and manipulating FLAC - * metadata blocks in memory, and three progressively more powerful - * interfaces for traversing and editing metadata in FLAC files. - * - * See the detailed documentation for each interface in the - * \link flac_metadata metadata \endlink module. - */ - -/** \defgroup flac_metadata FLAC/metadata.h: metadata interfaces - * \ingroup flac - * - * \brief - * This module provides functions for creating and manipulating FLAC - * metadata blocks in memory, and three progressively more powerful - * interfaces for traversing and editing metadata in native FLAC files. - * Note that currently only the Chain interface (level 2) supports Ogg - * FLAC files, and it is read-only i.e. no writing back changed - * metadata to file. - * - * There are three metadata interfaces of increasing complexity: - * - * Level 0: - * Read-only access to the STREAMINFO, VORBIS_COMMENT, CUESHEET, and - * PICTURE blocks. - * - * Level 1: - * Read-write access to all metadata blocks. This level is write- - * efficient in most cases (more on this below), and uses less memory - * than level 2. - * - * Level 2: - * Read-write access to all metadata blocks. This level is write- - * efficient in all cases, but uses more memory since all metadata for - * the whole file is read into memory and manipulated before writing - * out again. - * - * What do we mean by efficient? Since FLAC metadata appears at the - * beginning of the file, when writing metadata back to a FLAC file - * it is possible to grow or shrink the metadata such that the entire - * file must be rewritten. However, if the size remains the same during - * changes or PADDING blocks are utilized, only the metadata needs to be - * overwritten, which is much faster. - * - * Efficient means the whole file is rewritten at most one time, and only - * when necessary. Level 1 is not efficient only in the case that you - * cause more than one metadata block to grow or shrink beyond what can - * be accomodated by padding. In this case you should probably use level - * 2, which allows you to edit all the metadata for a file in memory and - * write it out all at once. - * - * All levels know how to skip over and not disturb an ID3v2 tag at the - * front of the file. - * - * All levels access files via their filenames. In addition, level 2 - * has additional alternative read and write functions that take an I/O - * handle and callbacks, for situations where access by filename is not - * possible. - * - * In addition to the three interfaces, this module defines functions for - * creating and manipulating various metadata objects in memory. As we see - * from the Format module, FLAC metadata blocks in memory are very primitive - * structures for storing information in an efficient way. Reading - * information from the structures is easy but creating or modifying them - * directly is more complex. The metadata object routines here facilitate - * this by taking care of the consistency and memory management drudgery. - * - * Unless you will be using the level 1 or 2 interfaces to modify existing - * metadata however, you will not probably not need these. - * - * From a dependency standpoint, none of the encoders or decoders require - * the metadata module. This is so that embedded users can strip out the - * metadata module from libFLAC to reduce the size and complexity. - */ - #ifdef __cplusplus extern "C" { #endif -/** \defgroup flac_metadata_level0 FLAC/metadata.h: metadata level 0 interface - * \ingroup flac_metadata - * - * \brief - * The level 0 interface consists of individual routines to read the - * STREAMINFO, VORBIS_COMMENT, CUESHEET, and PICTURE blocks, requiring - * only a filename. - * - * They try to skip any ID3v2 tag at the head of the file. - * - * \{ - */ - -/** Read the STREAMINFO metadata block of the given FLAC file. This function - * will try to skip any ID3v2 tag at the head of the file. - * - * \param filename The path to the FLAC file to read. - * \param streaminfo A pointer to space for the STREAMINFO block. Since - * FLAC__StreamMetadata is a simple structure with no - * memory allocation involved, you pass the address of - * an existing structure. It need not be initialized. - * \assert - * \code filename != NULL \endcode - * \code streaminfo != NULL \endcode - * \retval FLAC__bool - * \c true if a valid STREAMINFO block was read from \a filename. Returns - * \c false if there was a memory allocation error, a file decoder error, - * or the file contained no STREAMINFO block. (A memory allocation error - * is possible because this function must set up a file decoder.) - */ FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo); -/** Read the VORBIS_COMMENT metadata block of the given FLAC file. This - * function will try to skip any ID3v2 tag at the head of the file. - * - * \param filename The path to the FLAC file to read. - * \param tags The address where the returned pointer will be - * stored. The \a tags object must be deleted by - * the caller using FLAC__metadata_object_delete(). - * \assert - * \code filename != NULL \endcode - * \code tags != NULL \endcode - * \retval FLAC__bool - * \c true if a valid VORBIS_COMMENT block was read from \a filename, - * and \a *tags will be set to the address of the metadata structure. - * Returns \c false if there was a memory allocation error, a file - * decoder error, or the file contained no VORBIS_COMMENT block, and - * \a *tags will be set to \c NULL. - */ FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags); -/** Read the CUESHEET metadata block of the given FLAC file. This - * function will try to skip any ID3v2 tag at the head of the file. - * - * \param filename The path to the FLAC file to read. - * \param cuesheet The address where the returned pointer will be - * stored. The \a cuesheet object must be deleted by - * the caller using FLAC__metadata_object_delete(). - * \assert - * \code filename != NULL \endcode - * \code cuesheet != NULL \endcode - * \retval FLAC__bool - * \c true if a valid CUESHEET block was read from \a filename, - * and \a *cuesheet will be set to the address of the metadata - * structure. Returns \c false if there was a memory allocation - * error, a file decoder error, or the file contained no CUESHEET - * block, and \a *cuesheet will be set to \c NULL. - */ FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet); -/** Read a PICTURE metadata block of the given FLAC file. This - * function will try to skip any ID3v2 tag at the head of the file. - * Since there can be more than one PICTURE block in a file, this - * function takes a number of parameters that act as constraints to - * the search. The PICTURE block with the largest area matching all - * the constraints will be returned, or \a *picture will be set to - * \c NULL if there was no such block. - * - * \param filename The path to the FLAC file to read. - * \param picture The address where the returned pointer will be - * stored. The \a picture object must be deleted by - * the caller using FLAC__metadata_object_delete(). - * \param type The desired picture type. Use \c -1 to mean - * "any type". - * \param mime_type The desired MIME type, e.g. "image/jpeg". The - * string will be matched exactly. Use \c NULL to - * mean "any MIME type". - * \param description The desired description. The string will be - * matched exactly. Use \c NULL to mean "any - * description". - * \param max_width The maximum width in pixels desired. Use - * \c (unsigned)(-1) to mean "any width". - * \param max_height The maximum height in pixels desired. Use - * \c (unsigned)(-1) to mean "any height". - * \param max_depth The maximum color depth in bits-per-pixel desired. - * Use \c (unsigned)(-1) to mean "any depth". - * \param max_colors The maximum number of colors desired. Use - * \c (unsigned)(-1) to mean "any number of colors". - * \assert - * \code filename != NULL \endcode - * \code picture != NULL \endcode - * \retval FLAC__bool - * \c true if a valid PICTURE block was read from \a filename, - * and \a *picture will be set to the address of the metadata - * structure. Returns \c false if there was a memory allocation - * error, a file decoder error, or the file contained no PICTURE - * block, and \a *picture will be set to \c NULL. - */ FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors); -/* \} */ - -/** \defgroup flac_metadata_level1 FLAC/metadata.h: metadata level 1 interface - * \ingroup flac_metadata - * - * \brief - * The level 1 interface provides read-write access to FLAC file metadata and - * operates directly on the FLAC file. - * - * The general usage of this interface is: - * - * - Create an iterator using FLAC__metadata_simple_iterator_new() - * - Attach it to a file using FLAC__metadata_simple_iterator_init() and check - * the exit code. Call FLAC__metadata_simple_iterator_is_writable() to - * see if the file is writable, or only read access is allowed. - * - Use FLAC__metadata_simple_iterator_next() and - * FLAC__metadata_simple_iterator_prev() to traverse the blocks. - * This is does not read the actual blocks themselves. - * FLAC__metadata_simple_iterator_next() is relatively fast. - * FLAC__metadata_simple_iterator_prev() is slower since it needs to search - * forward from the front of the file. - * - Use FLAC__metadata_simple_iterator_get_block_type() or - * FLAC__metadata_simple_iterator_get_block() to access the actual data at - * the current iterator position. The returned object is yours to modify - * and free. - * - Use FLAC__metadata_simple_iterator_set_block() to write a modified block - * back. You must have write permission to the original file. Make sure to - * read the whole comment to FLAC__metadata_simple_iterator_set_block() - * below. - * - Use FLAC__metadata_simple_iterator_insert_block_after() to add new blocks. - * Use the object creation functions from - * \link flac_metadata_object here \endlink to generate new objects. - * - Use FLAC__metadata_simple_iterator_delete_block() to remove the block - * currently referred to by the iterator, or replace it with padding. - * - Destroy the iterator with FLAC__metadata_simple_iterator_delete() when - * finished. - * - * \note - * The FLAC file remains open the whole time between - * FLAC__metadata_simple_iterator_init() and - * FLAC__metadata_simple_iterator_delete(), so make sure you are not altering - * the file during this time. - * - * \note - * Do not modify the \a is_last, \a length, or \a type fields of returned - * FLAC__StreamMetadata objects. These are managed automatically. - * - * \note - * If any of the modification functions - * (FLAC__metadata_simple_iterator_set_block(), - * FLAC__metadata_simple_iterator_delete_block(), - * FLAC__metadata_simple_iterator_insert_block_after(), etc.) return \c false, - * you should delete the iterator as it may no longer be valid. - * - * \{ - */ - struct FLAC__Metadata_SimpleIterator; -/** The opaque structure definition for the level 1 iterator type. - * See the - * \link flac_metadata_level1 metadata level 1 module \endlink - * for a detailed description. - */ typedef struct FLAC__Metadata_SimpleIterator FLAC__Metadata_SimpleIterator; -/** Status type for FLAC__Metadata_SimpleIterator. - * - * The iterator's current status can be obtained by calling FLAC__metadata_simple_iterator_status(). - */ typedef enum { FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK = 0, - /**< The iterator is in the normal OK state */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT, - /**< The data passed into a function violated the function's usage criteria */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE, - /**< The iterator could not open the target file */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE, - /**< The iterator could not find the FLAC signature at the start of the file */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE, - /**< The iterator tried to write to a file that was not writable */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA, - /**< The iterator encountered input that does not conform to the FLAC metadata specification */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR, - /**< The iterator encountered an error while reading the FLAC file */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR, - /**< The iterator encountered an error while seeking in the FLAC file */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR, - /**< The iterator encountered an error while writing the FLAC file */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR, - /**< The iterator encountered an error renaming the FLAC file */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR, - /**< The iterator encountered an error removing the temporary file */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR, - /**< Memory allocation failed */ FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR - /**< The caller violated an assertion or an unexpected error occurred */ } FLAC__Metadata_SimpleIteratorStatus; -/** Maps a FLAC__Metadata_SimpleIteratorStatus to a C string. - * - * Using a FLAC__Metadata_SimpleIteratorStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[]; -/** Create a new iterator instance. - * - * \retval FLAC__Metadata_SimpleIterator* - * \c NULL if there was an error allocating memory, else the new instance. - */ FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void); -/** Free an iterator instance. Deletes the object pointed to by \a iterator. - * - * \param iterator A pointer to an existing iterator. - * \assert - * \code iterator != NULL \endcode - */ FLAC_API void FLAC__metadata_simple_iterator_delete(FLAC__Metadata_SimpleIterator *iterator); -/** Get the current status of the iterator. Call this after a function - * returns \c false to get the reason for the error. Also resets the status - * to FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK. - * - * \param iterator A pointer to an existing iterator. - * \assert - * \code iterator != NULL \endcode - * \retval FLAC__Metadata_SimpleIteratorStatus - * The current status of the iterator. - */ FLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__Metadata_SimpleIterator *iterator); -/** Initialize the iterator to point to the first metadata block in the - * given FLAC file. - * - * \param iterator A pointer to an existing iterator. - * \param filename The path to the FLAC file. - * \param read_only If \c true, the FLAC file will be opened - * in read-only mode; if \c false, the FLAC - * file will be opened for edit even if no - * edits are performed. - * \param preserve_file_stats If \c true, the owner and modification - * time will be preserved even if the FLAC - * file is written to. - * \assert - * \code iterator != NULL \endcode - * \code filename != NULL \endcode - * \retval FLAC__bool - * \c false if a memory allocation error occurs, the file can't be - * opened, or another error occurs, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool read_only, FLAC__bool preserve_file_stats); -/** Returns \c true if the FLAC file is writable. If \c false, calls to - * FLAC__metadata_simple_iterator_set_block() and - * FLAC__metadata_simple_iterator_insert_block_after() will fail. - * - * \param iterator A pointer to an existing iterator. - * \assert - * \code iterator != NULL \endcode - * \retval FLAC__bool - * See above. - */ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_writable(const FLAC__Metadata_SimpleIterator *iterator); -/** Moves the iterator forward one metadata block, returning \c false if - * already at the end. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__bool - * \c false if already at the last metadata block of the chain, else - * \c true. - */ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_next(FLAC__Metadata_SimpleIterator *iterator); -/** Moves the iterator backward one metadata block, returning \c false if - * already at the beginning. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__bool - * \c false if already at the first metadata block of the chain, else - * \c true. - */ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_prev(FLAC__Metadata_SimpleIterator *iterator); -/** Returns a flag telling if the current metadata block is the last. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__bool - * \c true if the current metadata block is the last in the file, - * else \c false. - */ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_is_last(const FLAC__Metadata_SimpleIterator *iterator); -/** Get the offset of the metadata block at the current position. This - * avoids reading the actual block data which can save time for large - * blocks. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval off_t - * The offset of the metadata block at the current iterator position. - * This is the byte offset relative to the beginning of the file of - * the current metadata block's header. - */ FLAC_API off_t FLAC__metadata_simple_iterator_get_block_offset(const FLAC__Metadata_SimpleIterator *iterator); -/** Get the type of the metadata block at the current position. This - * avoids reading the actual block data which can save time for large - * blocks. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__MetadataType - * The type of the metadata block at the current iterator position. - */ FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const FLAC__Metadata_SimpleIterator *iterator); -/** Get the length of the metadata block at the current position. This - * avoids reading the actual block data which can save time for large - * blocks. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval unsigned - * The length of the metadata block at the current iterator position. - * The is same length as that in the - * metadata block header, - * i.e. the length of the metadata body that follows the header. - */ FLAC_API unsigned FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator); -/** Get the application ID of the \c APPLICATION block at the current - * position. This avoids reading the actual block data which can save - * time for large blocks. - * - * \param iterator A pointer to an existing initialized iterator. - * \param id A pointer to a buffer of at least \c 4 bytes where - * the ID will be stored. - * \assert - * \code iterator != NULL \endcode - * \code id != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__bool - * \c true if the ID was successfully read, else \c false, in which - * case you should check FLAC__metadata_simple_iterator_status() to - * find out why. If the status is - * \c FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT, then the - * current metadata block is not an \c APPLICATION block. Otherwise - * if the status is - * \c FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR or - * \c FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR, an I/O error - * occurred and the iterator can no longer be used. - */ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_get_application_id(FLAC__Metadata_SimpleIterator *iterator, FLAC__byte *id); -/** Get the metadata block at the current position. You can modify the - * block but must use FLAC__metadata_simple_iterator_set_block() to - * write it back to the FLAC file. - * - * You must call FLAC__metadata_object_delete() on the returned object - * when you are finished with it. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__StreamMetadata* - * The current metadata block, or \c NULL if there was a memory - * allocation error. - */ FLAC_API FLAC__StreamMetadata *FLAC__metadata_simple_iterator_get_block(FLAC__Metadata_SimpleIterator *iterator); -/** Write a block back to the FLAC file. This function tries to be - * as efficient as possible; how the block is actually written is - * shown by the following: - * - * Existing block is a STREAMINFO block and the new block is a - * STREAMINFO block: the new block is written in place. Make sure - * you know what you're doing when changing the values of a - * STREAMINFO block. - * - * Existing block is a STREAMINFO block and the new block is a - * not a STREAMINFO block: this is an error since the first block - * must be a STREAMINFO block. Returns \c false without altering the - * file. - * - * Existing block is not a STREAMINFO block and the new block is a - * STREAMINFO block: this is an error since there may be only one - * STREAMINFO block. Returns \c false without altering the file. - * - * Existing block and new block are the same length: the existing - * block will be replaced by the new block, written in place. - * - * Existing block is longer than new block: if use_padding is \c true, - * the existing block will be overwritten in place with the new - * block followed by a PADDING block, if possible, to make the total - * size the same as the existing block. Remember that a padding - * block requires at least four bytes so if the difference in size - * between the new block and existing block is less than that, the - * entire file will have to be rewritten, using the new block's - * exact size. If use_padding is \c false, the entire file will be - * rewritten, replacing the existing block by the new block. - * - * Existing block is shorter than new block: if use_padding is \c true, - * the function will try and expand the new block into the following - * PADDING block, if it exists and doing so won't shrink the PADDING - * block to less than 4 bytes. If there is no following PADDING - * block, or it will shrink to less than 4 bytes, or use_padding is - * \c false, the entire file is rewritten, replacing the existing block - * with the new block. Note that in this case any following PADDING - * block is preserved as is. - * - * After writing the block, the iterator will remain in the same - * place, i.e. pointing to the new block. - * - * \param iterator A pointer to an existing initialized iterator. - * \param block The block to set. - * \param use_padding See above. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \code block != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false. - */ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_set_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding); -/** This is similar to FLAC__metadata_simple_iterator_set_block() - * except that instead of writing over an existing block, it appends - * a block after the existing block. \a use_padding is again used to - * tell the function to try an expand into following padding in an - * attempt to avoid rewriting the entire file. - * - * This function will fail and return \c false if given a STREAMINFO - * block. - * - * After writing the block, the iterator will be pointing to the - * new block. - * - * \param iterator A pointer to an existing initialized iterator. - * \param block The block to set. - * \param use_padding See above. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \code block != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false. - */ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_insert_block_after(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool use_padding); -/** Deletes the block at the current position. This will cause the - * entire FLAC file to be rewritten, unless \a use_padding is \c true, - * in which case the block will be replaced by an equal-sized PADDING - * block. The iterator will be left pointing to the block before the - * one just deleted. - * - * You may not delete the STREAMINFO block. - * - * \param iterator A pointer to an existing initialized iterator. - * \param use_padding See above. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_simple_iterator_init() - * \retval FLAC__bool - * \c true if successful, else \c false. - */ FLAC_API FLAC__bool FLAC__metadata_simple_iterator_delete_block(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool use_padding); -/* \} */ - -/** \defgroup flac_metadata_level2 FLAC/metadata.h: metadata level 2 interface - * \ingroup flac_metadata - * - * \brief - * The level 2 interface provides read-write access to FLAC file metadata; - * all metadata is read into memory, operated on in memory, and then written - * to file, which is more efficient than level 1 when editing multiple blocks. - * - * Currently Ogg FLAC is supported for read only, via - * FLAC__metadata_chain_read_ogg() but a subsequent - * FLAC__metadata_chain_write() will fail. - * - * The general usage of this interface is: - * - * - Create a new chain using FLAC__metadata_chain_new(). A chain is a - * linked list of FLAC metadata blocks. - * - Read all metadata into the the chain from a FLAC file using - * FLAC__metadata_chain_read() or FLAC__metadata_chain_read_ogg() and - * check the status. - * - Optionally, consolidate the padding using - * FLAC__metadata_chain_merge_padding() or - * FLAC__metadata_chain_sort_padding(). - * - Create a new iterator using FLAC__metadata_iterator_new() - * - Initialize the iterator to point to the first element in the chain - * using FLAC__metadata_iterator_init() - * - Traverse the chain using FLAC__metadata_iterator_next and - * FLAC__metadata_iterator_prev(). - * - Get a block for reading or modification using - * FLAC__metadata_iterator_get_block(). The pointer to the object - * inside the chain is returned, so the block is yours to modify. - * Changes will be reflected in the FLAC file when you write the - * chain. You can also add and delete blocks (see functions below). - * - When done, write out the chain using FLAC__metadata_chain_write(). - * Make sure to read the whole comment to the function below. - * - Delete the chain using FLAC__metadata_chain_delete(). - * - * \note - * Even though the FLAC file is not open while the chain is being - * manipulated, you must not alter the file externally during - * this time. The chain assumes the FLAC file will not change - * between the time of FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg() - * and FLAC__metadata_chain_write(). - * - * \note - * Do not modify the is_last, length, or type fields of returned - * FLAC__StreamMetadata objects. These are managed automatically. - * - * \note - * The metadata objects returned by FLAC__metadata_iterator_get_block() - * are owned by the chain; do not FLAC__metadata_object_delete() them. - * In the same way, blocks passed to FLAC__metadata_iterator_set_block() - * become owned by the chain and they will be deleted when the chain is - * deleted. - * - * \{ - */ - struct FLAC__Metadata_Chain; -/** The opaque structure definition for the level 2 chain type. - */ typedef struct FLAC__Metadata_Chain FLAC__Metadata_Chain; struct FLAC__Metadata_Iterator; -/** The opaque structure definition for the level 2 iterator type. - */ typedef struct FLAC__Metadata_Iterator FLAC__Metadata_Iterator; typedef enum { FLAC__METADATA_CHAIN_STATUS_OK = 0, - /**< The chain is in the normal OK state */ FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT, - /**< The data passed into a function violated the function's usage criteria */ FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE, - /**< The chain could not open the target file */ FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE, - /**< The chain could not find the FLAC signature at the start of the file */ FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE, - /**< The chain tried to write to a file that was not writable */ FLAC__METADATA_CHAIN_STATUS_BAD_METADATA, - /**< The chain encountered input that does not conform to the FLAC metadata specification */ FLAC__METADATA_CHAIN_STATUS_READ_ERROR, - /**< The chain encountered an error while reading the FLAC file */ FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR, - /**< The chain encountered an error while seeking in the FLAC file */ FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR, - /**< The chain encountered an error while writing the FLAC file */ FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR, - /**< The chain encountered an error renaming the FLAC file */ FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR, - /**< The chain encountered an error removing the temporary file */ FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR, - /**< Memory allocation failed */ FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR, - /**< The caller violated an assertion or an unexpected error occurred */ FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS, - /**< One or more of the required callbacks was NULL */ FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH, - /**< FLAC__metadata_chain_write() was called on a chain read by - * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(), - * or - * FLAC__metadata_chain_write_with_callbacks()/FLAC__metadata_chain_write_with_callbacks_and_tempfile() - * was called on a chain read by - * FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(). - * Matching read/write methods must always be used. */ FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL - /**< FLAC__metadata_chain_write_with_callbacks() was called when the - * chain write requires a tempfile; use - * FLAC__metadata_chain_write_with_callbacks_and_tempfile() instead. - * Or, FLAC__metadata_chain_write_with_callbacks_and_tempfile() was - * called when the chain write does not require a tempfile; use - * FLAC__metadata_chain_write_with_callbacks() instead. - * Always check FLAC__metadata_chain_check_if_tempfile_needed() - * before writing via callbacks. */ } FLAC__Metadata_ChainStatus; -/** Maps a FLAC__Metadata_ChainStatus to a C string. - * - * Using a FLAC__Metadata_ChainStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__Metadata_ChainStatusString[]; -/*********** FLAC__Metadata_Chain ***********/ - -/** Create a new chain instance. - * - * \retval FLAC__Metadata_Chain* - * \c NULL if there was an error allocating memory, else the new instance. - */ FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void); -/** Free a chain instance. Deletes the object pointed to by \a chain. - * - * \param chain A pointer to an existing chain. - * \assert - * \code chain != NULL \endcode - */ FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain); -/** Get the current status of the chain. Call this after a function - * returns \c false to get the reason for the error. Also resets the - * status to FLAC__METADATA_CHAIN_STATUS_OK. - * - * \param chain A pointer to an existing chain. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__Metadata_ChainStatus - * The current status of the chain. - */ FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain); -/** Read all metadata from a FLAC file into the chain. - * - * \param chain A pointer to an existing chain. - * \param filename The path to the FLAC file to read. - * \assert - * \code chain != NULL \endcode - * \code filename != NULL \endcode - * \retval FLAC__bool - * \c true if a valid list of metadata blocks was read from - * \a filename, else \c false. On failure, check the status with - * FLAC__metadata_chain_status(). - */ FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename); -/** Read all metadata from an Ogg FLAC file into the chain. - * - * \note Ogg FLAC metadata data writing is not supported yet and - * FLAC__metadata_chain_write() will fail. - * - * \param chain A pointer to an existing chain. - * \param filename The path to the Ogg FLAC file to read. - * \assert - * \code chain != NULL \endcode - * \code filename != NULL \endcode - * \retval FLAC__bool - * \c true if a valid list of metadata blocks was read from - * \a filename, else \c false. On failure, check the status with - * FLAC__metadata_chain_status(). - */ FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg(FLAC__Metadata_Chain *chain, const char *filename); -/** Read all metadata from a FLAC stream into the chain via I/O callbacks. - * - * The \a handle need only be open for reading, but must be seekable. - * The equivalent minimum stdio fopen() file mode is \c "r" (or \c "rb" - * for Windows). - * - * \param chain A pointer to an existing chain. - * \param handle The I/O handle of the FLAC stream to read. The - * handle will NOT be closed after the metadata is read; - * that is the duty of the caller. - * \param callbacks - * A set of callbacks to use for I/O. The mandatory - * callbacks are \a read, \a seek, and \a tell. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if a valid list of metadata blocks was read from - * \a handle, else \c false. On failure, check the status with - * FLAC__metadata_chain_status(). - */ FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks); -/** Read all metadata from an Ogg FLAC stream into the chain via I/O callbacks. - * - * The \a handle need only be open for reading, but must be seekable. - * The equivalent minimum stdio fopen() file mode is \c "r" (or \c "rb" - * for Windows). - * - * \note Ogg FLAC metadata data writing is not supported yet and - * FLAC__metadata_chain_write() will fail. - * - * \param chain A pointer to an existing chain. - * \param handle The I/O handle of the Ogg FLAC stream to read. The - * handle will NOT be closed after the metadata is read; - * that is the duty of the caller. - * \param callbacks - * A set of callbacks to use for I/O. The mandatory - * callbacks are \a read, \a seek, and \a tell. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if a valid list of metadata blocks was read from - * \a handle, else \c false. On failure, check the status with - * FLAC__metadata_chain_status(). - */ FLAC_API FLAC__bool FLAC__metadata_chain_read_ogg_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks); -/** Checks if writing the given chain would require the use of a - * temporary file, or if it could be written in place. - * - * Under certain conditions, padding can be utilized so that writing - * edited metadata back to the FLAC file does not require rewriting the - * entire file. If rewriting is required, then a temporary workfile is - * required. When writing metadata using callbacks, you must check - * this function to know whether to call - * FLAC__metadata_chain_write_with_callbacks() or - * FLAC__metadata_chain_write_with_callbacks_and_tempfile(). When - * writing with FLAC__metadata_chain_write(), the temporary file is - * handled internally. - * - * \param chain A pointer to an existing chain. - * \param use_padding - * Whether or not padding will be allowed to be used - * during the write. The value of \a use_padding given - * here must match the value later passed to - * FLAC__metadata_chain_write_with_callbacks() or - * FLAC__metadata_chain_write_with_callbacks_with_tempfile(). - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if writing the current chain would require a tempfile, or - * \c false if metadata can be written in place. - */ FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding); -/** Write all metadata out to the FLAC file. This function tries to be as - * efficient as possible; how the metadata is actually written is shown by - * the following: - * - * If the current chain is the same size as the existing metadata, the new - * data is written in place. - * - * If the current chain is longer than the existing metadata, and - * \a use_padding is \c true, and the last block is a PADDING block of - * sufficient length, the function will truncate the final padding block - * so that the overall size of the metadata is the same as the existing - * metadata, and then just rewrite the metadata. Otherwise, if not all of - * the above conditions are met, the entire FLAC file must be rewritten. - * If you want to use padding this way it is a good idea to call - * FLAC__metadata_chain_sort_padding() first so that you have the maximum - * amount of padding to work with, unless you need to preserve ordering - * of the PADDING blocks for some reason. - * - * If the current chain is shorter than the existing metadata, and - * \a use_padding is \c true, and the final block is a PADDING block, the padding - * is extended to make the overall size the same as the existing data. If - * \a use_padding is \c true and the last block is not a PADDING block, a new - * PADDING block is added to the end of the new data to make it the same - * size as the existing data (if possible, see the note to - * FLAC__metadata_simple_iterator_set_block() about the four byte limit) - * and the new data is written in place. If none of the above apply or - * \a use_padding is \c false, the entire FLAC file is rewritten. - * - * If \a preserve_file_stats is \c true, the owner and modification time will - * be preserved even if the FLAC file is written. - * - * For this write function to be used, the chain must have been read with - * FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(), not - * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(). - * - * \param chain A pointer to an existing chain. - * \param use_padding See above. - * \param preserve_file_stats See above. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if the write succeeded, else \c false. On failure, - * check the status with FLAC__metadata_chain_status(). - */ FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats); -/** Write all metadata out to a FLAC stream via callbacks. - * - * (See FLAC__metadata_chain_write() for the details on how padding is - * used to write metadata in place if possible.) - * - * The \a handle must be open for updating and be seekable. The - * equivalent minimum stdio fopen() file mode is \c "r+" (or \c "r+b" - * for Windows). - * - * For this write function to be used, the chain must have been read with - * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(), - * not FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(). - * Also, FLAC__metadata_chain_check_if_tempfile_needed() must have returned - * \c false. - * - * \param chain A pointer to an existing chain. - * \param use_padding See FLAC__metadata_chain_write() - * \param handle The I/O handle of the FLAC stream to write. The - * handle will NOT be closed after the metadata is - * written; that is the duty of the caller. - * \param callbacks A set of callbacks to use for I/O. The mandatory - * callbacks are \a write and \a seek. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if the write succeeded, else \c false. On failure, - * check the status with FLAC__metadata_chain_status(). - */ FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks); -/** Write all metadata out to a FLAC stream via callbacks. - * - * (See FLAC__metadata_chain_write() for the details on how padding is - * used to write metadata in place if possible.) - * - * This version of the write-with-callbacks function must be used when - * FLAC__metadata_chain_check_if_tempfile_needed() returns true. In - * this function, you must supply an I/O handle corresponding to the - * FLAC file to edit, and a temporary handle to which the new FLAC - * file will be written. It is the caller's job to move this temporary - * FLAC file on top of the original FLAC file to complete the metadata - * edit. - * - * The \a handle must be open for reading and be seekable. The - * equivalent minimum stdio fopen() file mode is \c "r" (or \c "rb" - * for Windows). - * - * The \a temp_handle must be open for writing. The - * equivalent minimum stdio fopen() file mode is \c "w" (or \c "wb" - * for Windows). It should be an empty stream, or at least positioned - * at the start-of-file (in which case it is the caller's duty to - * truncate it on return). - * - * For this write function to be used, the chain must have been read with - * FLAC__metadata_chain_read_with_callbacks()/FLAC__metadata_chain_read_ogg_with_callbacks(), - * not FLAC__metadata_chain_read()/FLAC__metadata_chain_read_ogg(). - * Also, FLAC__metadata_chain_check_if_tempfile_needed() must have returned - * \c true. - * - * \param chain A pointer to an existing chain. - * \param use_padding See FLAC__metadata_chain_write() - * \param handle The I/O handle of the original FLAC stream to read. - * The handle will NOT be closed after the metadata is - * written; that is the duty of the caller. - * \param callbacks A set of callbacks to use for I/O on \a handle. - * The mandatory callbacks are \a read, \a seek, and - * \a eof. - * \param temp_handle The I/O handle of the FLAC stream to write. The - * handle will NOT be closed after the metadata is - * written; that is the duty of the caller. - * \param temp_callbacks - * A set of callbacks to use for I/O on temp_handle. - * The only mandatory callback is \a write. - * \assert - * \code chain != NULL \endcode - * \retval FLAC__bool - * \c true if the write succeeded, else \c false. On failure, - * check the status with FLAC__metadata_chain_status(). - */ FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__IOHandle temp_handle, FLAC__IOCallbacks temp_callbacks); -/** Merge adjacent PADDING blocks into a single block. - * - * \note This function does not write to the FLAC file, it only - * modifies the chain. - * - * \warning Any iterator on the current chain will become invalid after this - * call. You should delete the iterator and get a new one. - * - * \param chain A pointer to an existing chain. - * \assert - * \code chain != NULL \endcode - */ FLAC_API void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain); -/** This function will move all PADDING blocks to the end on the metadata, - * then merge them into a single block. - * - * \note This function does not write to the FLAC file, it only - * modifies the chain. - * - * \warning Any iterator on the current chain will become invalid after this - * call. You should delete the iterator and get a new one. - * - * \param chain A pointer to an existing chain. - * \assert - * \code chain != NULL \endcode - */ FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain); -/*********** FLAC__Metadata_Iterator ***********/ - -/** Create a new iterator instance. - * - * \retval FLAC__Metadata_Iterator* - * \c NULL if there was an error allocating memory, else the new instance. - */ FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void); -/** Free an iterator instance. Deletes the object pointed to by \a iterator. - * - * \param iterator A pointer to an existing iterator. - * \assert - * \code iterator != NULL \endcode - */ FLAC_API void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator); -/** Initialize the iterator to point to the first metadata block in the - * given chain. - * - * \param iterator A pointer to an existing iterator. - * \param chain A pointer to an existing and initialized (read) chain. - * \assert - * \code iterator != NULL \endcode - * \code chain != NULL \endcode - */ FLAC_API void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain); -/** Moves the iterator forward one metadata block, returning \c false if - * already at the end. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__bool - * \c false if already at the last metadata block of the chain, else - * \c true. - */ FLAC_API FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator); -/** Moves the iterator backward one metadata block, returning \c false if - * already at the beginning. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__bool - * \c false if already at the first metadata block of the chain, else - * \c true. - */ FLAC_API FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator); -/** Get the type of the metadata block at the current position. - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__MetadataType - * The type of the metadata block at the current iterator position. - */ FLAC_API FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator); -/** Get the metadata block at the current position. You can modify - * the block in place but must write the chain before the changes - * are reflected to the FLAC file. You do not need to call - * FLAC__metadata_iterator_set_block() to reflect the changes; - * the pointer returned by FLAC__metadata_iterator_get_block() - * points directly into the chain. - * - * \warning - * Do not call FLAC__metadata_object_delete() on the returned object; - * to delete a block use FLAC__metadata_iterator_delete_block(). - * - * \param iterator A pointer to an existing initialized iterator. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__StreamMetadata* - * The current metadata block. - */ FLAC_API FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator); -/** Set the metadata block at the current position, replacing the existing - * block. The new block passed in becomes owned by the chain and it will be - * deleted when the chain is deleted. - * - * \param iterator A pointer to an existing initialized iterator. - * \param block A pointer to a metadata block. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \code block != NULL \endcode - * \retval FLAC__bool - * \c false if the conditions in the above description are not met, or - * a memory allocation error occurs, otherwise \c true. - */ FLAC_API FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block); -/** Removes the current block from the chain. If \a replace_with_padding is - * \c true, the block will instead be replaced with a padding block of equal - * size. You can not delete the STREAMINFO block. The iterator will be - * left pointing to the block before the one just "deleted", even if - * \a replace_with_padding is \c true. - * - * \param iterator A pointer to an existing initialized iterator. - * \param replace_with_padding See above. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__bool - * \c false if the conditions in the above description are not met, - * otherwise \c true. - */ FLAC_API FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding); -/** Insert a new block before the current block. You cannot insert a block - * before the first STREAMINFO block. You cannot insert a STREAMINFO block - * as there can be only one, the one that already exists at the head when you - * read in a chain. The chain takes ownership of the new block and it will be - * deleted when the chain is deleted. The iterator will be left pointing to - * the new block. - * - * \param iterator A pointer to an existing initialized iterator. - * \param block A pointer to a metadata block to insert. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__bool - * \c false if the conditions in the above description are not met, or - * a memory allocation error occurs, otherwise \c true. - */ FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block); -/** Insert a new block after the current block. You cannot insert a STREAMINFO - * block as there can be only one, the one that already exists at the head when - * you read in a chain. The chain takes ownership of the new block and it will - * be deleted when the chain is deleted. The iterator will be left pointing to - * the new block. - * - * \param iterator A pointer to an existing initialized iterator. - * \param block A pointer to a metadata block to insert. - * \assert - * \code iterator != NULL \endcode - * \a iterator has been successfully initialized with - * FLAC__metadata_iterator_init() - * \retval FLAC__bool - * \c false if the conditions in the above description are not met, or - * a memory allocation error occurs, otherwise \c true. - */ FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block); -/* \} */ - -/** \defgroup flac_metadata_object FLAC/metadata.h: metadata object methods - * \ingroup flac_metadata - * - * \brief - * This module contains methods for manipulating FLAC metadata objects. - * - * Since many are variable length we have to be careful about the memory - * management. We decree that all pointers to data in the object are - * owned by the object and memory-managed by the object. - * - * Use the FLAC__metadata_object_new() and FLAC__metadata_object_delete() - * functions to create all instances. When using the - * FLAC__metadata_object_set_*() functions to set pointers to data, set - * \a copy to \c true to have the function make it's own copy of the data, or - * to \c false to give the object ownership of your data. In the latter case - * your pointer must be freeable by free() and will be free()d when the object - * is FLAC__metadata_object_delete()d. It is legal to pass a null pointer as - * the data pointer to a FLAC__metadata_object_set_*() function as long as - * the length argument is 0 and the \a copy argument is \c false. - * - * The FLAC__metadata_object_new() and FLAC__metadata_object_clone() function - * will return \c NULL in the case of a memory allocation error, otherwise a new - * object. The FLAC__metadata_object_set_*() functions return \c false in the - * case of a memory allocation error. - * - * We don't have the convenience of C++ here, so note that the library relies - * on you to keep the types straight. In other words, if you pass, for - * example, a FLAC__StreamMetadata* that represents a STREAMINFO block to - * FLAC__metadata_object_application_set_data(), you will get an assertion - * failure. - * - * For convenience the FLAC__metadata_object_vorbiscomment_*() functions - * maintain a trailing NUL on each Vorbis comment entry. This is not counted - * toward the length or stored in the stream, but it can make working with plain - * comments (those that don't contain embedded-NULs in the value) easier. - * Entries passed into these functions have trailing NULs added if missing, and - * returned entries are guaranteed to have a trailing NUL. - * - * The FLAC__metadata_object_vorbiscomment_*() functions that take a Vorbis - * comment entry/name/value will first validate that it complies with the Vorbis - * comment specification and return false if it does not. - * - * There is no need to recalculate the length field on metadata blocks you - * have modified. They will be calculated automatically before they are - * written back to a file. - * - * \{ - */ - -/** Create a new metadata object instance of the given type. - * - * The object will be "empty"; i.e. values and data pointers will be \c 0, - * with the exception of FLAC__METADATA_TYPE_VORBIS_COMMENT, which will have - * the vendor string set (but zero comments). - * - * Do not pass in a value greater than or equal to - * \a FLAC__METADATA_TYPE_UNDEFINED unless you really know what you're - * doing. - * - * \param type Type of object to create - * \retval FLAC__StreamMetadata* - * \c NULL if there was an error allocating memory or the type code is - * greater than FLAC__MAX_METADATA_TYPE_CODE, else the new instance. - */ FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_new(FLAC__MetadataType type); -/** Create a copy of an existing metadata object. - * - * The copy is a "deep" copy, i.e. dynamically allocated data within the - * object is also copied. The caller takes ownership of the new block and - * is responsible for freeing it with FLAC__metadata_object_delete(). - * - * \param object Pointer to object to copy. - * \assert - * \code object != NULL \endcode - * \retval FLAC__StreamMetadata* - * \c NULL if there was an error allocating memory, else the new instance. - */ FLAC_API FLAC__StreamMetadata *FLAC__metadata_object_clone(const FLAC__StreamMetadata *object); -/** Free a metadata object. Deletes the object pointed to by \a object. - * - * The delete is a "deep" delete, i.e. dynamically allocated data within the - * object is also deleted. - * - * \param object A pointer to an existing object. - * \assert - * \code object != NULL \endcode - */ FLAC_API void FLAC__metadata_object_delete(FLAC__StreamMetadata *object); -/** Compares two metadata objects. - * - * The compare is "deep", i.e. dynamically allocated data within the - * object is also compared. - * - * \param block1 A pointer to an existing object. - * \param block2 A pointer to an existing object. - * \assert - * \code block1 != NULL \endcode - * \code block2 != NULL \endcode - * \retval FLAC__bool - * \c true if objects are identical, else \c false. - */ FLAC_API FLAC__bool FLAC__metadata_object_is_equal(const FLAC__StreamMetadata *block1, const FLAC__StreamMetadata *block2); -/** Sets the application data of an APPLICATION block. - * - * If \a copy is \c true, a copy of the data is stored; otherwise, the object - * takes ownership of the pointer. The existing data will be freed if this - * function is successful, otherwise the original data will remain if \a copy - * is \c true and malloc() fails. - * - * \note It is safe to pass a const pointer to \a data if \a copy is \c true. - * - * \param object A pointer to an existing APPLICATION object. - * \param data A pointer to the data to set. - * \param length The length of \a data in bytes. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_APPLICATION \endcode - * \code (data != NULL && length > 0) || - * (data == NULL && length == 0 && copy == false) \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, unsigned length, FLAC__bool copy); -/** Resize the seekpoint array. - * - * If the size shrinks, elements will truncated; if it grows, new placeholder - * points will be added to the end. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param new_num_points The desired length of the array; may be \c 0. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code (object->data.seek_table.points == NULL && object->data.seek_table.num_points == 0) || - * (object->data.seek_table.points != NULL && object->data.seek_table.num_points > 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation error, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMetadata *object, unsigned new_num_points); -/** Set a seekpoint in a seektable. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param point_num Index into seekpoint array to set. - * \param point The point to set. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code object->data.seek_table.num_points > point_num \endcode - */ FLAC_API void FLAC__metadata_object_seektable_set_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point); -/** Insert a seekpoint into a seektable. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param point_num Index into seekpoint array to set. - * \param point The point to set. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code object->data.seek_table.num_points >= point_num \endcode - * \retval FLAC__bool - * \c false if memory allocation error, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_seektable_insert_point(FLAC__StreamMetadata *object, unsigned point_num, FLAC__StreamMetadata_SeekPoint point); -/** Delete a seekpoint from a seektable. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param point_num Index into seekpoint array to set. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code object->data.seek_table.num_points > point_num \endcode - * \retval FLAC__bool - * \c false if memory allocation error, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_seektable_delete_point(FLAC__StreamMetadata *object, unsigned point_num); -/** Check a seektable to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * seektable. - * - * \param object A pointer to an existing SEEKTABLE object. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \retval FLAC__bool - * \c false if seek table is illegal, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_seektable_is_legal(const FLAC__StreamMetadata *object); -/** Append a number of placeholder points to the end of a seek table. - * - * \note - * As with the other ..._seektable_template_... functions, you should - * call FLAC__metadata_object_seektable_template_sort() when finished - * to make the seek table legal. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param num The number of placeholder points to append. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_placeholders(FLAC__StreamMetadata *object, unsigned num); -/** Append a specific seek point template to the end of a seek table. - * - * \note - * As with the other ..._seektable_template_... functions, you should - * call FLAC__metadata_object_seektable_template_sort() when finished - * to make the seek table legal. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param sample_number The sample number of the seek point template. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_point(FLAC__StreamMetadata *object, FLAC__uint64 sample_number); -/** Append specific seek point templates to the end of a seek table. - * - * \note - * As with the other ..._seektable_template_... functions, you should - * call FLAC__metadata_object_seektable_template_sort() when finished - * to make the seek table legal. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param sample_numbers An array of sample numbers for the seek points. - * \param num The number of seek point templates to append. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_points(FLAC__StreamMetadata *object, FLAC__uint64 sample_numbers[], unsigned num); -/** Append a set of evenly-spaced seek point templates to the end of a - * seek table. - * - * \note - * As with the other ..._seektable_template_... functions, you should - * call FLAC__metadata_object_seektable_template_sort() when finished - * to make the seek table legal. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param num The number of placeholder points to append. - * \param total_samples The total number of samples to be encoded; - * the seekpoints will be spaced approximately - * \a total_samples / \a num samples apart. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code total_samples > 0 \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points(FLAC__StreamMetadata *object, unsigned num, FLAC__uint64 total_samples); -/** Append a set of evenly-spaced seek point templates to the end of a - * seek table. - * - * \note - * As with the other ..._seektable_template_... functions, you should - * call FLAC__metadata_object_seektable_template_sort() when finished - * to make the seek table legal. - * - * \param object A pointer to an existing SEEKTABLE object. - * \param samples The number of samples apart to space the placeholder - * points. The first point will be at sample \c 0, the - * second at sample \a samples, then 2*\a samples, and - * so on. As long as \a samples and \a total_samples - * are greater than \c 0, there will always be at least - * one seekpoint at sample \c 0. - * \param total_samples The total number of samples to be encoded; - * the seekpoints will be spaced - * \a samples samples apart. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \code samples > 0 \endcode - * \code total_samples > 0 \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(FLAC__StreamMetadata *object, unsigned samples, FLAC__uint64 total_samples); -/** Sort a seek table's seek points according to the format specification, - * removing duplicates. - * - * \param object A pointer to a seek table to be sorted. - * \param compact If \c false, behaves like FLAC__format_seektable_sort(). - * If \c true, duplicates are deleted and the seek table is - * shrunk appropriately; the number of placeholder points - * present in the seek table will be the same after the call - * as before. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_SEEKTABLE \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_seektable_template_sort(FLAC__StreamMetadata *object, FLAC__bool compact); -/** Sets the vendor string in a VORBIS_COMMENT block. - * - * For convenience, a trailing NUL is added to the entry if it doesn't have - * one already. - * - * If \a copy is \c true, a copy of the entry is stored; otherwise, the object - * takes ownership of the \c entry.entry pointer. - * - * \note If this function returns \c false, the caller still owns the - * pointer. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param entry The entry to set the vendor string to. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code (entry.entry != NULL && entry.length > 0) || - * (entry.entry == NULL && entry.length == 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); -/** Resize the comment array. - * - * If the size shrinks, elements will truncated; if it grows, new empty - * fields will be added to the end. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param new_num_comments The desired length of the array; may be \c 0. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code (object->data.vorbis_comment.comments == NULL && object->data.vorbis_comment.num_comments == 0) || - * (object->data.vorbis_comment.comments != NULL && object->data.vorbis_comment.num_comments > 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__StreamMetadata *object, unsigned new_num_comments); -/** Sets a comment in a VORBIS_COMMENT block. - * - * For convenience, a trailing NUL is added to the entry if it doesn't have - * one already. - * - * If \a copy is \c true, a copy of the entry is stored; otherwise, the object - * takes ownership of the \c entry.entry pointer. - * - * \note If this function returns \c false, the caller still owns the - * pointer. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param comment_num Index into comment array to set. - * \param entry The entry to set the comment to. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code comment_num < object->data.vorbis_comment.num_comments \endcode - * \code (entry.entry != NULL && entry.length > 0) || - * (entry.entry == NULL && entry.length == 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); -/** Insert a comment in a VORBIS_COMMENT block at the given index. - * - * For convenience, a trailing NUL is added to the entry if it doesn't have - * one already. - * - * If \a copy is \c true, a copy of the entry is stored; otherwise, the object - * takes ownership of the \c entry.entry pointer. - * - * \note If this function returns \c false, the caller still owns the - * pointer. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param comment_num The index at which to insert the comment. The comments - * at and after \a comment_num move right one position. - * To append a comment to the end, set \a comment_num to - * \c object->data.vorbis_comment.num_comments . - * \param entry The comment to insert. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code object->data.vorbis_comment.num_comments >= comment_num \endcode - * \code (entry.entry != NULL && entry.length > 0) || - * (entry.entry == NULL && entry.length == 0 && copy == false) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_insert_comment(FLAC__StreamMetadata *object, unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); -/** Appends a comment to a VORBIS_COMMENT block. - * - * For convenience, a trailing NUL is added to the entry if it doesn't have - * one already. - * - * If \a copy is \c true, a copy of the entry is stored; otherwise, the object - * takes ownership of the \c entry.entry pointer. - * - * \note If this function returns \c false, the caller still owns the - * pointer. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param entry The comment to insert. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code (entry.entry != NULL && entry.length > 0) || - * (entry.entry == NULL && entry.length == 0 && copy == false) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_append_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy); -/** Replaces comments in a VORBIS_COMMENT block with a new one. - * - * For convenience, a trailing NUL is added to the entry if it doesn't have - * one already. - * - * Depending on the the value of \a all, either all or just the first comment - * whose field name(s) match the given entry's name will be replaced by the - * given entry. If no comments match, \a entry will simply be appended. - * - * If \a copy is \c true, a copy of the entry is stored; otherwise, the object - * takes ownership of the \c entry.entry pointer. - * - * \note If this function returns \c false, the caller still owns the - * pointer. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param entry The comment to insert. - * \param all If \c true, all comments whose field name matches - * \a entry's field name will be removed, and \a entry will - * be inserted at the position of the first matching - * comment. If \c false, only the first comment whose - * field name matches \a entry's field name will be - * replaced with \a entry. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code (entry.entry != NULL && entry.length > 0) || - * (entry.entry == NULL && entry.length == 0 && copy == false) \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_replace_comment(FLAC__StreamMetadata *object, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool all, FLAC__bool copy); -/** Delete a comment in a VORBIS_COMMENT block at the given index. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param comment_num The index of the comment to delete. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code object->data.vorbis_comment.num_comments > comment_num \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_delete_comment(FLAC__StreamMetadata *object, unsigned comment_num); -/** Creates a Vorbis comment entry from NUL-terminated name and value strings. - * - * On return, the filled-in \a entry->entry pointer will point to malloc()ed - * memory and shall be owned by the caller. For convenience the entry will - * have a terminating NUL. - * - * \param entry A pointer to a Vorbis comment entry. The entry's - * \c entry pointer should not point to allocated - * memory as it will be overwritten. - * \param field_name The field name in ASCII, \c NUL terminated. - * \param field_value The field value in UTF-8, \c NUL terminated. - * \assert - * \code entry != NULL \endcode - * \code field_name != NULL \endcode - * \code field_value != NULL \endcode - * \retval FLAC__bool - * \c false if malloc() fails, or if \a field_name or \a field_value does - * not comply with the Vorbis comment specification, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(FLAC__StreamMetadata_VorbisComment_Entry *entry, const char *field_name, const char *field_value); -/** Splits a Vorbis comment entry into NUL-terminated name and value strings. - * - * The returned pointers to name and value will be allocated by malloc() - * and shall be owned by the caller. - * - * \param entry An existing Vorbis comment entry. - * \param field_name The address of where the returned pointer to the - * field name will be stored. - * \param field_value The address of where the returned pointer to the - * field value will be stored. - * \assert - * \code (entry.entry != NULL && entry.length > 0) \endcode - * \code memchr(entry.entry, '=', entry.length) != NULL \endcode - * \code field_name != NULL \endcode - * \code field_value != NULL \endcode - * \retval FLAC__bool - * \c false if memory allocation fails or \a entry does not comply with the - * Vorbis comment specification, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_to_name_value_pair(const FLAC__StreamMetadata_VorbisComment_Entry entry, char **field_name, char **field_value); -/** Check if the given Vorbis comment entry's field name matches the given - * field name. - * - * \param entry An existing Vorbis comment entry. - * \param field_name The field name to check. - * \param field_name_length The length of \a field_name, not including the - * terminating \c NUL. - * \assert - * \code (entry.entry != NULL && entry.length > 0) \endcode - * \retval FLAC__bool - * \c true if the field names match, else \c false - */ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_entry_matches(const FLAC__StreamMetadata_VorbisComment_Entry entry, const char *field_name, unsigned field_name_length); -/** Find a Vorbis comment with the given field name. - * - * The search begins at entry number \a offset; use an offset of 0 to - * search from the beginning of the comment array. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param offset The offset into the comment array from where to start - * the search. - * \param field_name The field name of the comment to find. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \code field_name != NULL \endcode - * \retval int - * The offset in the comment array of the first comment whose field - * name matches \a field_name, or \c -1 if no match was found. - */ FLAC_API int FLAC__metadata_object_vorbiscomment_find_entry_from(const FLAC__StreamMetadata *object, unsigned offset, const char *field_name); -/** Remove first Vorbis comment matching the given field name. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param field_name The field name of comment to delete. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \retval int - * \c -1 for memory allocation error, \c 0 for no matching entries, - * \c 1 for one matching entry deleted. - */ FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entry_matching(FLAC__StreamMetadata *object, const char *field_name); -/** Remove all Vorbis comments matching the given field name. - * - * \param object A pointer to an existing VORBIS_COMMENT object. - * \param field_name The field name of comments to delete. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_VORBIS_COMMENT \endcode - * \retval int - * \c -1 for memory allocation error, \c 0 for no matching entries, - * else the number of matching entries deleted. - */ FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entries_matching(FLAC__StreamMetadata *object, const char *field_name); -/** Create a new CUESHEET track instance. - * - * The object will be "empty"; i.e. values and data pointers will be \c 0. - * - * \retval FLAC__StreamMetadata_CueSheet_Track* - * \c NULL if there was an error allocating memory, else the new instance. - */ FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(void); -/** Create a copy of an existing CUESHEET track object. - * - * The copy is a "deep" copy, i.e. dynamically allocated data within the - * object is also copied. The caller takes ownership of the new object and - * is responsible for freeing it with - * FLAC__metadata_object_cuesheet_track_delete(). - * - * \param object Pointer to object to copy. - * \assert - * \code object != NULL \endcode - * \retval FLAC__StreamMetadata_CueSheet_Track* - * \c NULL if there was an error allocating memory, else the new instance. - */ FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_clone(const FLAC__StreamMetadata_CueSheet_Track *object); -/** Delete a CUESHEET track object - * - * \param object A pointer to an existing CUESHEET track object. - * \assert - * \code object != NULL \endcode - */ FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_CueSheet_Track *object); -/** Resize a track's index point array. - * - * If the size shrinks, elements will truncated; if it grows, new blank - * indices will be added to the end. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index of the track to modify. NOTE: this is not - * necessarily the same as the track's \a number field. - * \param new_num_indices The desired length of the array; may be \c 0. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks > track_num \endcode - * \code (object->data.cue_sheet.tracks[track_num].indices == NULL && object->data.cue_sheet.tracks[track_num].num_indices == 0) || - * (object->data.cue_sheet.tracks[track_num].indices != NULL && object->data.cue_sheet.tracks[track_num].num_indices > 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation error, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__StreamMetadata *object, unsigned track_num, unsigned new_num_indices); -/** Insert an index point in a CUESHEET track at the given index. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index of the track to modify. NOTE: this is not - * necessarily the same as the track's \a number field. - * \param index_num The index into the track's index array at which to - * insert the index point. NOTE: this is not necessarily - * the same as the index point's \a number field. The - * indices at and after \a index_num move right one - * position. To append an index point to the end, set - * \a index_num to - * \c object->data.cue_sheet.tracks[track_num].num_indices . - * \param index The index point to insert. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks > track_num \endcode - * \code object->data.cue_sheet.tracks[track_num].num_indices >= index_num \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num, FLAC__StreamMetadata_CueSheet_Index index); -/** Insert a blank index point in a CUESHEET track at the given index. - * - * A blank index point is one in which all field values are zero. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index of the track to modify. NOTE: this is not - * necessarily the same as the track's \a number field. - * \param index_num The index into the track's index array at which to - * insert the index point. NOTE: this is not necessarily - * the same as the index point's \a number field. The - * indices at and after \a index_num move right one - * position. To append an index point to the end, set - * \a index_num to - * \c object->data.cue_sheet.tracks[track_num].num_indices . - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks > track_num \endcode - * \code object->data.cue_sheet.tracks[track_num].num_indices >= index_num \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_insert_blank_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num); -/** Delete an index point in a CUESHEET track at the given index. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index into the track array of the track to - * modify. NOTE: this is not necessarily the same - * as the track's \a number field. - * \param index_num The index into the track's index array of the index - * to delete. NOTE: this is not necessarily the same - * as the index's \a number field. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks > track_num \endcode - * \code object->data.cue_sheet.tracks[track_num].num_indices > index_num \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__StreamMetadata *object, unsigned track_num, unsigned index_num); -/** Resize the track array. - * - * If the size shrinks, elements will truncated; if it grows, new blank - * tracks will be added to the end. - * - * \param object A pointer to an existing CUESHEET object. - * \param new_num_tracks The desired length of the array; may be \c 0. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code (object->data.cue_sheet.tracks == NULL && object->data.cue_sheet.num_tracks == 0) || - * (object->data.cue_sheet.tracks != NULL && object->data.cue_sheet.num_tracks > 0) \endcode - * \retval FLAC__bool - * \c false if memory allocation error, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMetadata *object, unsigned new_num_tracks); -/** Sets a track in a CUESHEET block. - * - * If \a copy is \c true, a copy of the track is stored; otherwise, the object - * takes ownership of the \a track pointer. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num Index into track array to set. NOTE: this is not - * necessarily the same as the track's \a number field. - * \param track The track to set the track to. You may safely pass in - * a const pointer if \a copy is \c true. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code track_num < object->data.cue_sheet.num_tracks \endcode - * \code (track->indices != NULL && track->num_indices > 0) || - * (track->indices == NULL && track->num_indices == 0) - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_set_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy); -/** Insert a track in a CUESHEET block at the given index. - * - * If \a copy is \c true, a copy of the track is stored; otherwise, the object - * takes ownership of the \a track pointer. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index at which to insert the track. NOTE: this - * is not necessarily the same as the track's \a number - * field. The tracks at and after \a track_num move right - * one position. To append a track to the end, set - * \a track_num to \c object->data.cue_sheet.num_tracks . - * \param track The track to insert. You may safely pass in a const - * pointer if \a copy is \c true. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks >= track_num \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_track(FLAC__StreamMetadata *object, unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy); -/** Insert a blank track in a CUESHEET block at the given index. - * - * A blank track is one in which all field values are zero. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index at which to insert the track. NOTE: this - * is not necessarily the same as the track's \a number - * field. The tracks at and after \a track_num move right - * one position. To append a track to the end, set - * \a track_num to \c object->data.cue_sheet.num_tracks . - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks >= track_num \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_insert_blank_track(FLAC__StreamMetadata *object, unsigned track_num); -/** Delete a track in a CUESHEET block at the given index. - * - * \param object A pointer to an existing CUESHEET object. - * \param track_num The index into the track array of the track to - * delete. NOTE: this is not necessarily the same - * as the track's \a number field. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \code object->data.cue_sheet.num_tracks > track_num \endcode - * \retval FLAC__bool - * \c false if realloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_delete_track(FLAC__StreamMetadata *object, unsigned track_num); -/** Check a cue sheet to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * cue sheet. - * - * \param object A pointer to an existing CUESHEET object. - * \param check_cd_da_subset If \c true, check CUESHEET against more - * stringent requirements for a CD-DA (audio) disc. - * \param violation Address of a pointer to a string. If there is a - * violation, a pointer to a string explanation of the - * violation will be returned here. \a violation may be - * \c NULL if you don't need the returned string. Do not - * free the returned string; it will always point to static - * data. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \retval FLAC__bool - * \c false if cue sheet is illegal, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_is_legal(const FLAC__StreamMetadata *object, FLAC__bool check_cd_da_subset, const char **violation); -/** Calculate and return the CDDB/freedb ID for a cue sheet. The function - * assumes the cue sheet corresponds to a CD; the result is undefined - * if the cuesheet's is_cd bit is not set. - * - * \param object A pointer to an existing CUESHEET object. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_CUESHEET \endcode - * \retval FLAC__uint32 - * The unsigned integer representation of the CDDB/freedb ID - */ FLAC_API FLAC__uint32 FLAC__metadata_object_cuesheet_calculate_cddb_id(const FLAC__StreamMetadata *object); -/** Sets the MIME type of a PICTURE block. - * - * If \a copy is \c true, a copy of the string is stored; otherwise, the object - * takes ownership of the pointer. The existing string will be freed if this - * function is successful, otherwise the original string will remain if \a copy - * is \c true and malloc() fails. - * - * \note It is safe to pass a const pointer to \a mime_type if \a copy is \c true. - * - * \param object A pointer to an existing PICTURE object. - * \param mime_type A pointer to the MIME type string. The string must be - * ASCII characters 0x20-0x7e, NUL-terminated. No validation - * is done. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode - * \code (mime_type != NULL) \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_picture_set_mime_type(FLAC__StreamMetadata *object, char *mime_type, FLAC__bool copy); -/** Sets the description of a PICTURE block. - * - * If \a copy is \c true, a copy of the string is stored; otherwise, the object - * takes ownership of the pointer. The existing string will be freed if this - * function is successful, otherwise the original string will remain if \a copy - * is \c true and malloc() fails. - * - * \note It is safe to pass a const pointer to \a description if \a copy is \c true. - * - * \param object A pointer to an existing PICTURE object. - * \param description A pointer to the description string. The string must be - * valid UTF-8, NUL-terminated. No validation is done. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode - * \code (description != NULL) \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_picture_set_description(FLAC__StreamMetadata *object, FLAC__byte *description, FLAC__bool copy); -/** Sets the picture data of a PICTURE block. - * - * If \a copy is \c true, a copy of the data is stored; otherwise, the object - * takes ownership of the pointer. Also sets the \a data_length field of the - * metadata object to what is passed in as the \a length parameter. The - * existing data will be freed if this function is successful, otherwise the - * original data and data_length will remain if \a copy is \c true and - * malloc() fails. - * - * \note It is safe to pass a const pointer to \a data if \a copy is \c true. - * - * \param object A pointer to an existing PICTURE object. - * \param data A pointer to the data to set. - * \param length The length of \a data in bytes. - * \param copy See above. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode - * \code (data != NULL && length > 0) || - * (data == NULL && length == 0 && copy == false) \endcode - * \retval FLAC__bool - * \c false if \a copy is \c true and malloc() fails, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_picture_set_data(FLAC__StreamMetadata *object, FLAC__byte *data, FLAC__uint32 length, FLAC__bool copy); -/** Check a PICTURE block to see if it conforms to the FLAC specification. - * See the format specification for limits on the contents of the - * PICTURE block. - * - * \param object A pointer to existing PICTURE block to be checked. - * \param violation Address of a pointer to a string. If there is a - * violation, a pointer to a string explanation of the - * violation will be returned here. \a violation may be - * \c NULL if you don't need the returned string. Do not - * free the returned string; it will always point to static - * data. - * \assert - * \code object != NULL \endcode - * \code object->type == FLAC__METADATA_TYPE_PICTURE \endcode - * \retval FLAC__bool - * \c false if PICTURE block is illegal, else \c true. - */ FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMetadata *object, const char **violation); -/* \} */ - #ifdef __cplusplus } #endif @@ -106221,1023 +100781,185 @@ FLAC_API FLAC__bool FLAC__metadata_object_picture_is_legal(const FLAC__StreamMet extern "C" { #endif -/** \file include/FLAC/stream_decoder.h - * - * \brief - * This module contains the functions which implement the stream - * decoder. - * - * See the detailed documentation in the - * \link flac_stream_decoder stream decoder \endlink module. - */ - -/** \defgroup flac_decoder FLAC/ \*_decoder.h: decoder interfaces - * \ingroup flac - * - * \brief - * This module describes the decoder layers provided by libFLAC. - * - * The stream decoder can be used to decode complete streams either from - * the client via callbacks, or directly from a file, depending on how - * it is initialized. When decoding via callbacks, the client provides - * callbacks for reading FLAC data and writing decoded samples, and - * handling metadata and errors. If the client also supplies seek-related - * callback, the decoder function for sample-accurate seeking within the - * FLAC input is also available. When decoding from a file, the client - * needs only supply a filename or open \c FILE* and write/metadata/error - * callbacks; the rest of the callbacks are supplied internally. For more - * info see the \link flac_stream_decoder stream decoder \endlink module. - */ - -/** \defgroup flac_stream_decoder FLAC/stream_decoder.h: stream decoder interface - * \ingroup flac_decoder - * - * \brief - * This module contains the functions which implement the stream - * decoder. - * - * The stream decoder can decode native FLAC, and optionally Ogg FLAC - * (check FLAC_API_SUPPORTS_OGG_FLAC) streams and files. - * - * The basic usage of this decoder is as follows: - * - The program creates an instance of a decoder using - * FLAC__stream_decoder_new(). - * - The program overrides the default settings using - * FLAC__stream_decoder_set_*() functions. - * - The program initializes the instance to validate the settings and - * prepare for decoding using - * - FLAC__stream_decoder_init_stream() or FLAC__stream_decoder_init_FILE() - * or FLAC__stream_decoder_init_file() for native FLAC, - * - FLAC__stream_decoder_init_ogg_stream() or FLAC__stream_decoder_init_ogg_FILE() - * or FLAC__stream_decoder_init_ogg_file() for Ogg FLAC - * - The program calls the FLAC__stream_decoder_process_*() functions - * to decode data, which subsequently calls the callbacks. - * - The program finishes the decoding with FLAC__stream_decoder_finish(), - * which flushes the input and output and resets the decoder to the - * uninitialized state. - * - The instance may be used again or deleted with - * FLAC__stream_decoder_delete(). - * - * In more detail, the program will create a new instance by calling - * FLAC__stream_decoder_new(), then call FLAC__stream_decoder_set_*() - * functions to override the default decoder options, and call - * one of the FLAC__stream_decoder_init_*() functions. - * - * There are three initialization functions for native FLAC, one for - * setting up the decoder to decode FLAC data from the client via - * callbacks, and two for decoding directly from a FLAC file. - * - * For decoding via callbacks, use FLAC__stream_decoder_init_stream(). - * You must also supply several callbacks for handling I/O. Some (like - * seeking) are optional, depending on the capabilities of the input. - * - * For decoding directly from a file, use FLAC__stream_decoder_init_FILE() - * or FLAC__stream_decoder_init_file(). Then you must only supply an open - * \c FILE* or filename and fewer callbacks; the decoder will handle - * the other callbacks internally. - * - * There are three similarly-named init functions for decoding from Ogg - * FLAC streams. Check \c FLAC_API_SUPPORTS_OGG_FLAC to find out if the - * library has been built with Ogg support. - * - * Once the decoder is initialized, your program will call one of several - * functions to start the decoding process: - * - * - FLAC__stream_decoder_process_single() - Tells the decoder to process at - * most one metadata block or audio frame and return, calling either the - * metadata callback or write callback, respectively, once. If the decoder - * loses sync it will return with only the error callback being called. - * - FLAC__stream_decoder_process_until_end_of_metadata() - Tells the decoder - * to process the stream from the current location and stop upon reaching - * the first audio frame. The client will get one metadata, write, or error - * callback per metadata block, audio frame, or sync error, respectively. - * - FLAC__stream_decoder_process_until_end_of_stream() - Tells the decoder - * to process the stream from the current location until the read callback - * returns FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM or - * FLAC__STREAM_DECODER_READ_STATUS_ABORT. The client will get one metadata, - * write, or error callback per metadata block, audio frame, or sync error, - * respectively. - * - * When the decoder has finished decoding (normally or through an abort), - * the instance is finished by calling FLAC__stream_decoder_finish(), which - * ensures the decoder is in the correct state and frees memory. Then the - * instance may be deleted with FLAC__stream_decoder_delete() or initialized - * again to decode another stream. - * - * Seeking is exposed through the FLAC__stream_decoder_seek_absolute() method. - * At any point after the stream decoder has been initialized, the client can - * call this function to seek to an exact sample within the stream. - * Subsequently, the first time the write callback is called it will be - * passed a (possibly partial) block starting at that sample. - * - * If the client cannot seek via the callback interface provided, but still - * has another way of seeking, it can flush the decoder using - * FLAC__stream_decoder_flush() and start feeding data from the new position - * through the read callback. - * - * The stream decoder also provides MD5 signature checking. If this is - * turned on before initialization, FLAC__stream_decoder_finish() will - * report when the decoded MD5 signature does not match the one stored - * in the STREAMINFO block. MD5 checking is automatically turned off - * (until the next FLAC__stream_decoder_reset()) if there is no signature - * in the STREAMINFO block or when a seek is attempted. - * - * The FLAC__stream_decoder_set_metadata_*() functions deserve special - * attention. By default, the decoder only calls the metadata_callback for - * the STREAMINFO block. These functions allow you to tell the decoder - * explicitly which blocks to parse and return via the metadata_callback - * and/or which to skip. Use a FLAC__stream_decoder_set_metadata_respond_all(), - * FLAC__stream_decoder_set_metadata_ignore() ... or FLAC__stream_decoder_set_metadata_ignore_all(), - * FLAC__stream_decoder_set_metadata_respond() ... sequence to exactly specify - * which blocks to return. Remember that metadata blocks can potentially - * be big (for example, cover art) so filtering out the ones you don't - * use can reduce the memory requirements of the decoder. Also note the - * special forms FLAC__stream_decoder_set_metadata_respond_application(id) - * and FLAC__stream_decoder_set_metadata_ignore_application(id) for - * filtering APPLICATION blocks based on the application ID. - * - * STREAMINFO and SEEKTABLE blocks are always parsed and used internally, but - * they still can legally be filtered from the metadata_callback. - * - * \note - * The "set" functions may only be called when the decoder is in the - * state FLAC__STREAM_DECODER_UNINITIALIZED, i.e. after - * FLAC__stream_decoder_new() or FLAC__stream_decoder_finish(), but - * before FLAC__stream_decoder_init_*(). If this is the case they will - * return \c true, otherwise \c false. - * - * \note - * FLAC__stream_decoder_finish() resets all settings to the constructor - * defaults, including the callbacks. - * - * \{ - */ - -/** State values for a FLAC__StreamDecoder - * - * The decoder's state can be obtained by calling FLAC__stream_decoder_get_state(). - */ typedef enum { FLAC__STREAM_DECODER_SEARCH_FOR_METADATA = 0, - /**< The decoder is ready to search for metadata. */ FLAC__STREAM_DECODER_READ_METADATA, - /**< The decoder is ready to or is in the process of reading metadata. */ FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC, - /**< The decoder is ready to or is in the process of searching for the - * frame sync code. - */ FLAC__STREAM_DECODER_READ_FRAME, - /**< The decoder is ready to or is in the process of reading a frame. */ FLAC__STREAM_DECODER_END_OF_STREAM, - /**< The decoder has reached the end of the stream. */ FLAC__STREAM_DECODER_OGG_ERROR, - /**< An error occurred in the underlying Ogg layer. */ FLAC__STREAM_DECODER_SEEK_ERROR, - /**< An error occurred while seeking. The decoder must be flushed - * with FLAC__stream_decoder_flush() or reset with - * FLAC__stream_decoder_reset() before decoding can continue. - */ FLAC__STREAM_DECODER_ABORTED, - /**< The decoder was aborted by the read callback. */ FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR, - /**< An error occurred allocating memory. The decoder is in an invalid - * state and can no longer be used. - */ FLAC__STREAM_DECODER_UNINITIALIZED - /**< The decoder is in the uninitialized state; one of the - * FLAC__stream_decoder_init_*() functions must be called before samples - * can be processed. - */ } FLAC__StreamDecoderState; -/** Maps a FLAC__StreamDecoderState to a C string. - * - * Using a FLAC__StreamDecoderState as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamDecoderStateString[]; -/** Possible return values for the FLAC__stream_decoder_init_*() functions. - */ typedef enum { FLAC__STREAM_DECODER_INIT_STATUS_OK = 0, - /**< Initialization was successful. */ FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER, - /**< The library was not compiled with support for the given container - * format. - */ FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS, - /**< A required callback was not supplied. */ FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR, - /**< An error occurred allocating memory. */ FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE, - /**< fopen() failed in FLAC__stream_decoder_init_file() or - * FLAC__stream_decoder_init_ogg_file(). */ FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED - /**< FLAC__stream_decoder_init_*() was called when the decoder was - * already initialized, usually because - * FLAC__stream_decoder_finish() was not called. - */ } FLAC__StreamDecoderInitStatus; -/** Maps a FLAC__StreamDecoderInitStatus to a C string. - * - * Using a FLAC__StreamDecoderInitStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamDecoderInitStatusString[]; -/** Return values for the FLAC__StreamDecoder read callback. - */ typedef enum { FLAC__STREAM_DECODER_READ_STATUS_CONTINUE, - /**< The read was OK and decoding can continue. */ FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM, - /**< The read was attempted while at the end of the stream. Note that - * the client must only return this value when the read callback was - * called when already at the end of the stream. Otherwise, if the read - * itself moves to the end of the stream, the client should still return - * the data and \c FLAC__STREAM_DECODER_READ_STATUS_CONTINUE, and then on - * the next read callback it should return - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM with a byte count - * of \c 0. - */ FLAC__STREAM_DECODER_READ_STATUS_ABORT - /**< An unrecoverable error occurred. The decoder will return from the process call. */ } FLAC__StreamDecoderReadStatus; -/** Maps a FLAC__StreamDecoderReadStatus to a C string. - * - * Using a FLAC__StreamDecoderReadStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamDecoderReadStatusString[]; -/** Return values for the FLAC__StreamDecoder seek callback. - */ typedef enum { FLAC__STREAM_DECODER_SEEK_STATUS_OK, - /**< The seek was OK and decoding can continue. */ FLAC__STREAM_DECODER_SEEK_STATUS_ERROR, - /**< An unrecoverable error occurred. The decoder will return from the process call. */ FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED - /**< Client does not support seeking. */ } FLAC__StreamDecoderSeekStatus; -/** Maps a FLAC__StreamDecoderSeekStatus to a C string. - * - * Using a FLAC__StreamDecoderSeekStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamDecoderSeekStatusString[]; -/** Return values for the FLAC__StreamDecoder tell callback. - */ typedef enum { FLAC__STREAM_DECODER_TELL_STATUS_OK, - /**< The tell was OK and decoding can continue. */ FLAC__STREAM_DECODER_TELL_STATUS_ERROR, - /**< An unrecoverable error occurred. The decoder will return from the process call. */ FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED - /**< Client does not support telling the position. */ } FLAC__StreamDecoderTellStatus; -/** Maps a FLAC__StreamDecoderTellStatus to a C string. - * - * Using a FLAC__StreamDecoderTellStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamDecoderTellStatusString[]; -/** Return values for the FLAC__StreamDecoder length callback. - */ typedef enum { FLAC__STREAM_DECODER_LENGTH_STATUS_OK, - /**< The length call was OK and decoding can continue. */ FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR, - /**< An unrecoverable error occurred. The decoder will return from the process call. */ FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED - /**< Client does not support reporting the length. */ } FLAC__StreamDecoderLengthStatus; -/** Maps a FLAC__StreamDecoderLengthStatus to a C string. - * - * Using a FLAC__StreamDecoderLengthStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamDecoderLengthStatusString[]; -/** Return values for the FLAC__StreamDecoder write callback. - */ typedef enum { FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE, - /**< The write was OK and decoding can continue. */ FLAC__STREAM_DECODER_WRITE_STATUS_ABORT - /**< An unrecoverable error occurred. The decoder will return from the process call. */ } FLAC__StreamDecoderWriteStatus; -/** Maps a FLAC__StreamDecoderWriteStatus to a C string. - * - * Using a FLAC__StreamDecoderWriteStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[]; -/** Possible values passed back to the FLAC__StreamDecoder error callback. - * \c FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC is the generic catch- - * all. The rest could be caused by bad sync (false synchronization on - * data that is not the start of a frame) or corrupted data. The error - * itself is the decoder's best guess at what happened assuming a correct - * sync. For example \c FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER - * could be caused by a correct sync on the start of a frame, but some - * data in the frame header was corrupted. Or it could be the result of - * syncing on a point the stream that looked like the starting of a frame - * but was not. \c FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM - * could be because the decoder encountered a valid frame made by a future - * version of the encoder which it cannot parse, or because of a false - * sync making it appear as though an encountered frame was generated by - * a future encoder. - */ typedef enum { FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC, - /**< An error in the stream caused the decoder to lose synchronization. */ FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, - /**< The decoder encountered a corrupted frame header. */ FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH, - /**< The frame's data did not match the CRC in the footer. */ FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM - /**< The decoder encountered reserved fields in use in the stream. */ } FLAC__StreamDecoderErrorStatus; -/** Maps a FLAC__StreamDecoderErrorStatus to a C string. - * - * Using a FLAC__StreamDecoderErrorStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[]; -/*********************************************************************** - * - * class FLAC__StreamDecoder - * - ***********************************************************************/ - struct FLAC__StreamDecoderProtected; struct FLAC__StreamDecoderPrivate; -/** The opaque structure definition for the stream decoder type. - * See the \link flac_stream_decoder stream decoder module \endlink - * for a detailed description. - */ typedef struct { struct FLAC__StreamDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */ struct FLAC__StreamDecoderPrivate *private_; /* avoid the C++ keyword 'private' */ } FLAC__StreamDecoder; -/** Signature for the read callback. - * - * A function pointer matching this signature must be passed to - * FLAC__stream_decoder_init*_stream(). The supplied function will be - * called when the decoder needs more input data. The address of the - * buffer to be filled is supplied, along with the number of bytes the - * buffer can hold. The callback may choose to supply less data and - * modify the byte count but must be careful not to overflow the buffer. - * The callback then returns a status code chosen from - * FLAC__StreamDecoderReadStatus. - * - * Here is an example of a read callback for stdio streams: - * \code - * FLAC__StreamDecoderReadStatus read_cb(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * if(*bytes > 0) { - * *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, file); - * if(ferror(file)) - * return FLAC__STREAM_DECODER_READ_STATUS_ABORT; - * else if(*bytes == 0) - * return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - * else - * return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; - * } - * else - * return FLAC__STREAM_DECODER_READ_STATUS_ABORT; - * } - * \endcode - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param buffer A pointer to a location for the callee to store - * data to be decoded. - * \param bytes A pointer to the size of the buffer. On entry - * to the callback, it contains the maximum number - * of bytes that may be stored in \a buffer. The - * callee must set it to the actual number of bytes - * stored (0 in case of error or end-of-stream) before - * returning. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__StreamDecoderReadStatus - * The callee's return status. Note that the callback should return - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM if and only if - * zero bytes were read and there is no more data to be read. - */ typedef FLAC__StreamDecoderReadStatus (*FLAC__StreamDecoderReadCallback)(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); -/** Signature for the seek callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_decoder_init*_stream(). The supplied function will be - * called when the decoder needs to seek the input stream. The decoder - * will pass the absolute byte offset to seek to, 0 meaning the - * beginning of the stream. - * - * Here is an example of a seek callback for stdio streams: - * \code - * FLAC__StreamDecoderSeekStatus seek_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * if(file == stdin) - * return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED; - * else if(fseeko(file, (off_t)absolute_byte_offset, SEEK_SET) < 0) - * return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; - * else - * return FLAC__STREAM_DECODER_SEEK_STATUS_OK; - * } - * \endcode - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param absolute_byte_offset The offset from the beginning of the stream - * to seek to. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__StreamDecoderSeekStatus - * The callee's return status. - */ typedef FLAC__StreamDecoderSeekStatus (*FLAC__StreamDecoderSeekCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data); -/** Signature for the tell callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_decoder_init*_stream(). The supplied function will be - * called when the decoder wants to know the current position of the - * stream. The callback should return the byte offset from the - * beginning of the stream. - * - * Here is an example of a tell callback for stdio streams: - * \code - * FLAC__StreamDecoderTellStatus tell_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * off_t pos; - * if(file == stdin) - * return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED; - * else if((pos = ftello(file)) < 0) - * return FLAC__STREAM_DECODER_TELL_STATUS_ERROR; - * else { - * *absolute_byte_offset = (FLAC__uint64)pos; - * return FLAC__STREAM_DECODER_TELL_STATUS_OK; - * } - * } - * \endcode - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param absolute_byte_offset A pointer to storage for the current offset - * from the beginning of the stream. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__StreamDecoderTellStatus - * The callee's return status. - */ typedef FLAC__StreamDecoderTellStatus (*FLAC__StreamDecoderTellCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data); -/** Signature for the length callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_decoder_init*_stream(). The supplied function will be - * called when the decoder wants to know the total length of the stream - * in bytes. - * - * Here is an example of a length callback for stdio streams: - * \code - * FLAC__StreamDecoderLengthStatus length_cb(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * struct stat filestats; - * - * if(file == stdin) - * return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; - * else if(fstat(fileno(file), &filestats) != 0) - * return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; - * else { - * *stream_length = (FLAC__uint64)filestats.st_size; - * return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; - * } - * } - * \endcode - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param stream_length A pointer to storage for the length of the stream - * in bytes. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__StreamDecoderLengthStatus - * The callee's return status. - */ typedef FLAC__StreamDecoderLengthStatus (*FLAC__StreamDecoderLengthCallback)(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); -/** Signature for the EOF callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_decoder_init*_stream(). The supplied function will be - * called when the decoder needs to know if the end of the stream has - * been reached. - * - * Here is an example of a EOF callback for stdio streams: - * FLAC__bool eof_cb(const FLAC__StreamDecoder *decoder, void *client_data) - * \code - * { - * FILE *file = ((MyClientData*)client_data)->file; - * return feof(file)? true : false; - * } - * \endcode - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__bool - * \c true if the currently at the end of the stream, else \c false. - */ typedef FLAC__bool (*FLAC__StreamDecoderEofCallback)(const FLAC__StreamDecoder *decoder, void *client_data); -/** Signature for the write callback. - * - * A function pointer matching this signature must be passed to one of - * the FLAC__stream_decoder_init_*() functions. - * The supplied function will be called when the decoder has decoded a - * single audio frame. The decoder will pass the frame metadata as well - * as an array of pointers (one for each channel) pointing to the - * decoded audio. - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param frame The description of the decoded frame. See - * FLAC__Frame. - * \param buffer An array of pointers to decoded channels of data. - * Each pointer will point to an array of signed - * samples of length \a frame->header.blocksize. - * Channels will be ordered according to the FLAC - * specification; see the documentation for the - * frame header. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - * \retval FLAC__StreamDecoderWriteStatus - * The callee's return status. - */ typedef FLAC__StreamDecoderWriteStatus (*FLAC__StreamDecoderWriteCallback)(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); -/** Signature for the metadata callback. - * - * A function pointer matching this signature must be passed to one of - * the FLAC__stream_decoder_init_*() functions. - * The supplied function will be called when the decoder has decoded a - * metadata block. In a valid FLAC file there will always be one - * \c STREAMINFO block, followed by zero or more other metadata blocks. - * These will be supplied by the decoder in the same order as they - * appear in the stream and always before the first audio frame (i.e. - * write callback). The metadata block that is passed in must not be - * modified, and it doesn't live beyond the callback, so you should make - * a copy of it with FLAC__metadata_object_clone() if you will need it - * elsewhere. Since metadata blocks can potentially be large, by - * default the decoder only calls the metadata callback for the - * \c STREAMINFO block; you can instruct the decoder to pass or filter - * other blocks with FLAC__stream_decoder_set_metadata_*() calls. - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param metadata The decoded metadata block. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - */ typedef void (*FLAC__StreamDecoderMetadataCallback)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); -/** Signature for the error callback. - * - * A function pointer matching this signature must be passed to one of - * the FLAC__stream_decoder_init_*() functions. - * The supplied function will be called whenever an error occurs during - * decoding. - * - * \note In general, FLAC__StreamDecoder functions which change the - * state should not be called on the \a decoder while in the callback. - * - * \param decoder The decoder instance calling the callback. - * \param status The error encountered by the decoder. - * \param client_data The callee's client data set through - * FLAC__stream_decoder_init_*(). - */ typedef void (*FLAC__StreamDecoderErrorCallback)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - -/** Create a new stream decoder instance. The instance is created with - * default settings; see the individual FLAC__stream_decoder_set_*() - * functions for each setting's default. - * - * \retval FLAC__StreamDecoder* - * \c NULL if there was an error allocating memory, else the new instance. - */ FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(void); -/** Free a decoder instance. Deletes the object pointed to by \a decoder. - * - * \param decoder A pointer to an existing decoder. - * \assert - * \code decoder != NULL \endcode - */ FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder); -/*********************************************************************** - * - * Public class method prototypes - * - ***********************************************************************/ - -/** Set the serial number for the FLAC stream within the Ogg container. - * The default behavior is to use the serial number of the first Ogg - * page. Setting a serial number here will explicitly specify which - * stream is to be decoded. - * - * \note - * This does not need to be set for native FLAC decoding. - * - * \default \c use serial number of first page - * \param decoder A decoder instance to set. - * \param serial_number See above. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_decoder_set_ogg_serial_number(FLAC__StreamDecoder *decoder, long serial_number); -/** Set the "MD5 signature checking" flag. If \c true, the decoder will - * compute the MD5 signature of the unencoded audio data while decoding - * and compare it to the signature from the STREAMINFO block, if it - * exists, during FLAC__stream_decoder_finish(). - * - * MD5 signature checking will be turned off (until the next - * FLAC__stream_decoder_reset()) if there is no signature in the - * STREAMINFO block or when a seek is attempted. - * - * Clients that do not use the MD5 check should leave this off to speed - * up decoding. - * - * \default \c false - * \param decoder A decoder instance to set. - * \param value Flag value (see above). - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_decoder_set_md5_checking(FLAC__StreamDecoder *decoder, FLAC__bool value); -/** Direct the decoder to pass on all metadata blocks of type \a type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param type See above. - * \assert - * \code decoder != NULL \endcode - * \a type is valid - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond(FLAC__StreamDecoder *decoder, FLAC__MetadataType type); -/** Direct the decoder to pass on all APPLICATION metadata blocks of the - * given \a id. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param id See above. - * \assert - * \code decoder != NULL \endcode - * \code id != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]); -/** Direct the decoder to pass on all metadata blocks of any type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_all(FLAC__StreamDecoder *decoder); -/** Direct the decoder to filter out all metadata blocks of type \a type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param type See above. - * \assert - * \code decoder != NULL \endcode - * \a type is valid - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore(FLAC__StreamDecoder *decoder, FLAC__MetadataType type); -/** Direct the decoder to filter out all APPLICATION metadata blocks of - * the given \a id. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \param id See above. - * \assert - * \code decoder != NULL \endcode - * \code id != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4]); -/** Direct the decoder to filter out all metadata blocks of any type. - * - * \default By default, only the \c STREAMINFO block is returned via the - * metadata callback. - * \param decoder A decoder instance to set. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if the decoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_all(FLAC__StreamDecoder *decoder); -/** Get the current decoder state. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderState - * The current decoder state. - */ FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder); -/** Get the current decoder state as a C string. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval const char * - * The decoder state as a C string. Do not modify the contents. - */ FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder); -/** Get the "MD5 signature checking" flag. - * This is the value of the setting, not whether or not the decoder is - * currently checking the MD5 (remember, it can be turned off automatically - * by a seek). When the decoder is reset the flag will be restored to the - * value returned by this function. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * See above. - */ FLAC_API FLAC__bool FLAC__stream_decoder_get_md5_checking(const FLAC__StreamDecoder *decoder); -/** Get the total number of samples in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the \c STREAMINFO block. A value of \c 0 means "unknown". - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder); -/** Get the current number of channels in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ FLAC_API unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder); -/** Get the current channel assignment in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__ChannelAssignment - * See above. - */ FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder); -/** Get the current sample resolution in the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ FLAC_API unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder); -/** Get the current sample rate in Hz of the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ FLAC_API unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder); -/** Get the current blocksize of the stream being decoded. - * Will only be valid after decoding has started and will contain the - * value from the most recently decoded frame header. - * - * \param decoder A decoder instance to query. - * \assert - * \code decoder != NULL \endcode - * \retval unsigned - * See above. - */ FLAC_API unsigned FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder); -/** Returns the decoder's current read position within the stream. - * The position is the byte offset from the start of the stream. - * Bytes before this position have been fully decoded. Note that - * there may still be undecoded bytes in the decoder's read FIFO. - * The returned position is correct even after a seek. - * - * \warning This function currently only works for native FLAC, - * not Ogg FLAC streams. - * - * \param decoder A decoder instance to query. - * \param position Address at which to return the desired position. - * \assert - * \code decoder != NULL \endcode - * \code position != NULL \endcode - * \retval FLAC__bool - * \c true if successful, \c false if the stream is not native FLAC, - * or there was an error from the 'tell' callback or it returned - * \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED. - */ FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position); -/** Initialize the decoder instance to decode native FLAC streams. - * - * This flavor of initialization sets up the decoder to decode from a - * native FLAC stream. I/O is performed via callbacks to the client. - * For decoding from a plain file via filename or open FILE*, - * FLAC__stream_decoder_init_file() and FLAC__stream_decoder_init_FILE() - * provide a simpler interface. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \param decoder An uninitialized decoder instance. - * \param read_callback See FLAC__StreamDecoderReadCallback. This - * pointer must not be \c NULL. - * \param seek_callback See FLAC__StreamDecoderSeekCallback. This - * pointer may be \c NULL if seeking is not - * supported. If \a seek_callback is not \c NULL then a - * \a tell_callback, \a length_callback, and \a eof_callback must also be supplied. - * Alternatively, a dummy seek callback that just - * returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param tell_callback See FLAC__StreamDecoderTellCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a tell_callback must also be supplied. - * Alternatively, a dummy tell callback that just - * returns \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param length_callback See FLAC__StreamDecoderLengthCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a length_callback must also be supplied. - * Alternatively, a dummy length callback that just - * returns \c FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param eof_callback See FLAC__StreamDecoderEofCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a eof_callback must also be supplied. - * Alternatively, a dummy length callback that just - * returns \c false - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream( FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback read_callback, @@ -107251,74 +100973,6 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream( void *client_data ); -/** Initialize the decoder instance to decode Ogg FLAC streams. - * - * This flavor of initialization sets up the decoder to decode from a - * FLAC stream in an Ogg container. I/O is performed via callbacks to the - * client. For decoding from a plain file via filename or open FILE*, - * FLAC__stream_decoder_init_ogg_file() and FLAC__stream_decoder_init_ogg_FILE() - * provide a simpler interface. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \note Support for Ogg FLAC in the library is optional. If this - * library has been built without support for Ogg FLAC, this function - * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER. - * - * \param decoder An uninitialized decoder instance. - * \param read_callback See FLAC__StreamDecoderReadCallback. This - * pointer must not be \c NULL. - * \param seek_callback See FLAC__StreamDecoderSeekCallback. This - * pointer may be \c NULL if seeking is not - * supported. If \a seek_callback is not \c NULL then a - * \a tell_callback, \a length_callback, and \a eof_callback must also be supplied. - * Alternatively, a dummy seek callback that just - * returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param tell_callback See FLAC__StreamDecoderTellCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a tell_callback must also be supplied. - * Alternatively, a dummy tell callback that just - * returns \c FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param length_callback See FLAC__StreamDecoderLengthCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a length_callback must also be supplied. - * Alternatively, a dummy length callback that just - * returns \c FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param eof_callback See FLAC__StreamDecoderEofCallback. This - * pointer may be \c NULL if not supported by the client. If - * \a seek_callback is not \c NULL then a - * \a eof_callback must also be supplied. - * Alternatively, a dummy length callback that just - * returns \c false - * may also be supplied, all though this is slightly - * less efficient for the decoder. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream( FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback read_callback, @@ -107332,43 +100986,6 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream( void *client_data ); -/** Initialize the decoder instance to decode native FLAC files. - * - * This flavor of initialization sets up the decoder to decode from a - * plain native FLAC file. For non-stdio streams, you must use - * FLAC__stream_decoder_init_stream() and provide callbacks for the I/O. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \param decoder An uninitialized decoder instance. - * \param file An open FLAC file. The file should have been - * opened with mode \c "rb" and rewound. The file - * becomes owned by the decoder and should not be - * manipulated by the client while decoding. - * Unless \a file is \c stdin, it will be closed - * when FLAC__stream_decoder_finish() is called. - * Note however that seeking will not work when - * decoding from \c stdout since it is not seekable. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \code file != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE( FLAC__StreamDecoder *decoder, FILE *file, @@ -107378,47 +100995,6 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE( void *client_data ); -/** Initialize the decoder instance to decode Ogg FLAC files. - * - * This flavor of initialization sets up the decoder to decode from a - * plain Ogg FLAC file. For non-stdio streams, you must use - * FLAC__stream_decoder_init_ogg_stream() and provide callbacks for the I/O. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \note Support for Ogg FLAC in the library is optional. If this - * library has been built without support for Ogg FLAC, this function - * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER. - * - * \param decoder An uninitialized decoder instance. - * \param file An open FLAC file. The file should have been - * opened with mode \c "rb" and rewound. The file - * becomes owned by the decoder and should not be - * manipulated by the client while decoding. - * Unless \a file is \c stdin, it will be closed - * when FLAC__stream_decoder_finish() is called. - * Note however that seeking will not work when - * decoding from \c stdout since it is not seekable. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \code file != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE( FLAC__StreamDecoder *decoder, FILE *file, @@ -107428,39 +101004,6 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE( void *client_data ); -/** Initialize the decoder instance to decode native FLAC files. - * - * This flavor of initialization sets up the decoder to decode from a plain - * native FLAC file. If POSIX fopen() semantics are not sufficient, (for - * example, with Unicode filenames on Windows), you must use - * FLAC__stream_decoder_init_FILE(), or FLAC__stream_decoder_init_stream() - * and provide callbacks for the I/O. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \param decoder An uninitialized decoder instance. - * \param filename The name of the file to decode from. The file will - * be opened with fopen(). Use \c NULL to decode from - * \c stdin. Note that \c stdin is not seekable. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file( FLAC__StreamDecoder *decoder, const char *filename, @@ -107470,43 +101013,6 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file( void *client_data ); -/** Initialize the decoder instance to decode Ogg FLAC files. - * - * This flavor of initialization sets up the decoder to decode from a plain - * Ogg FLAC file. If POSIX fopen() semantics are not sufficient, (for - * example, with Unicode filenames on Windows), you must use - * FLAC__stream_decoder_init_ogg_FILE(), or FLAC__stream_decoder_init_ogg_stream() - * and provide callbacks for the I/O. - * - * This function should be called after FLAC__stream_decoder_new() and - * FLAC__stream_decoder_set_*() but before any of the - * FLAC__stream_decoder_process_*() functions. Will set and return the - * decoder state, which will be FLAC__STREAM_DECODER_SEARCH_FOR_METADATA - * if initialization succeeded. - * - * \note Support for Ogg FLAC in the library is optional. If this - * library has been built without support for Ogg FLAC, this function - * will return \c FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER. - * - * \param decoder An uninitialized decoder instance. - * \param filename The name of the file to decode from. The file will - * be opened with fopen(). Use \c NULL to decode from - * \c stdin. Note that \c stdin is not seekable. - * \param write_callback See FLAC__StreamDecoderWriteCallback. This - * pointer must not be \c NULL. - * \param metadata_callback See FLAC__StreamDecoderMetadataCallback. This - * pointer may be \c NULL if the callback is not - * desired. - * \param error_callback See FLAC__StreamDecoderErrorCallback. This - * pointer must not be \c NULL. - * \param client_data This value will be supplied to callbacks in their - * \a client_data argument. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__StreamDecoderInitStatus - * \c FLAC__STREAM_DECODER_INIT_STATUS_OK if initialization was successful; - * see FLAC__StreamDecoderInitStatus for the meanings of other return values. - */ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_file( FLAC__StreamDecoder *decoder, const char *filename, @@ -107516,211 +101022,22 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_file( void *client_data ); -/** Finish the decoding process. - * Flushes the decoding buffer, releases resources, resets the decoder - * settings to their defaults, and returns the decoder state to - * FLAC__STREAM_DECODER_UNINITIALIZED. - * - * In the event of a prematurely-terminated decode, it is not strictly - * necessary to call this immediately before FLAC__stream_decoder_delete() - * but it is good practice to match every FLAC__stream_decoder_init_*() - * with a FLAC__stream_decoder_finish(). - * - * \param decoder An uninitialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if MD5 checking is on AND a STREAMINFO block was available - * AND the MD5 signature in the STREAMINFO block was non-zero AND the - * signature does not match the one computed by the decoder; else - * \c true. - */ FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder); -/** Flush the stream input. - * The decoder's input buffer will be cleared and the state set to - * \c FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC. This will also turn - * off MD5 checking. - * - * \param decoder A decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false if a memory allocation - * error occurs (in which case the state will be set to - * \c FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR). - */ FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder); -/** Reset the decoding process. - * The decoder's input buffer will be cleared and the state set to - * \c FLAC__STREAM_DECODER_SEARCH_FOR_METADATA. This is similar to - * FLAC__stream_decoder_finish() except that the settings are - * preserved; there is no need to call FLAC__stream_decoder_init_*() - * before decoding again. MD5 checking will be restored to its original - * setting. - * - * If the decoder is seekable, or was initialized with - * FLAC__stream_decoder_init*_FILE() or FLAC__stream_decoder_init*_file(), - * the decoder will also attempt to seek to the beginning of the file. - * If this rewind fails, this function will return \c false. It follows - * that FLAC__stream_decoder_reset() cannot be used when decoding from - * \c stdin. - * - * If the decoder was initialized with FLAC__stream_encoder_init*_stream() - * and is not seekable (i.e. no seek callback was provided or the seek - * callback returns \c FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED), it - * is the duty of the client to start feeding data from the beginning of - * the stream on the next FLAC__stream_decoder_process() or - * FLAC__stream_decoder_process_interleaved() call. - * - * \param decoder A decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false if a memory allocation occurs - * (in which case the state will be set to - * \c FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR) or a seek error - * occurs (the state will be unchanged). - */ FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder); -/** Decode one metadata block or audio frame. - * This version instructs the decoder to decode a either a single metadata - * block or a single frame and stop, unless the callbacks return a fatal - * error or the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. - * - * As the decoder needs more input it will call the read callback. - * Depending on what was decoded, the metadata or write callback will be - * called with the decoded metadata block or audio frame. - * - * Unless there is a fatal read error or end of stream, this function - * will return once one whole frame is decoded. In other words, if the - * stream is not synchronized or points to a corrupt frame header, the - * decoder will continue to try and resync until it gets to a valid - * frame, then decode one frame, then return. If the decoder points to - * a frame whose frame CRC in the frame footer does not match the - * computed frame CRC, this function will issue a - * FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH error to the - * error callback, and return, having decoded one complete, although - * corrupt, frame. (Such corrupted frames are sent as silence of the - * correct length to the write callback.) - * - * \param decoder An initialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any fatal read, write, or memory allocation error - * occurred (meaning decoding must stop), else \c true; for more - * information about the decoder, check the decoder state with - * FLAC__stream_decoder_get_state(). - */ FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *decoder); -/** Decode until the end of the metadata. - * This version instructs the decoder to decode from the current position - * and continue until all the metadata has been read, or until the - * callbacks return a fatal error or the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. - * - * As the decoder needs more input it will call the read callback. - * As each metadata block is decoded, the metadata callback will be called - * with the decoded metadata. - * - * \param decoder An initialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any fatal read, write, or memory allocation error - * occurred (meaning decoding must stop), else \c true; for more - * information about the decoder, check the decoder state with - * FLAC__stream_decoder_get_state(). - */ FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__StreamDecoder *decoder); -/** Decode until the end of the stream. - * This version instructs the decoder to decode from the current position - * and continue until the end of stream (the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM), or until the - * callbacks return a fatal error. - * - * As the decoder needs more input it will call the read callback. - * As each metadata block and frame is decoded, the metadata or write - * callback will be called with the decoded metadata or frame. - * - * \param decoder An initialized decoder instance. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any fatal read, write, or memory allocation error - * occurred (meaning decoding must stop), else \c true; for more - * information about the decoder, check the decoder state with - * FLAC__stream_decoder_get_state(). - */ FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder); -/** Skip one audio frame. - * This version instructs the decoder to 'skip' a single frame and stop, - * unless the callbacks return a fatal error or the read callback returns - * \c FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM. - * - * The decoding flow is the same as what occurs when - * FLAC__stream_decoder_process_single() is called to process an audio - * frame, except that this function does not decode the parsed data into - * PCM or call the write callback. The integrity of the frame is still - * checked the same way as in the other process functions. - * - * This function will return once one whole frame is skipped, in the - * same way that FLAC__stream_decoder_process_single() will return once - * one whole frame is decoded. - * - * This function can be used in more quickly determining FLAC frame - * boundaries when decoding of the actual data is not needed, for - * example when an application is separating a FLAC stream into frames - * for editing or storing in a container. To do this, the application - * can use FLAC__stream_decoder_skip_single_frame() to quickly advance - * to the next frame, then use - * FLAC__stream_decoder_get_decode_position() to find the new frame - * boundary. - * - * This function should only be called when the stream has advanced - * past all the metadata, otherwise it will return \c false. - * - * \param decoder An initialized decoder instance not in a metadata - * state. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c false if any fatal read, write, or memory allocation error - * occurred (meaning decoding must stop), or if the decoder - * is in the FLAC__STREAM_DECODER_SEARCH_FOR_METADATA or - * FLAC__STREAM_DECODER_READ_METADATA state, else \c true; for more - * information about the decoder, check the decoder state with - * FLAC__stream_decoder_get_state(). - */ FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder); -/** Flush the input and seek to an absolute sample. - * Decoding will resume at the given sample. Note that because of - * this, the next write callback may contain a partial block. The - * client must support seeking the input or this function will fail - * and return \c false. Furthermore, if the decoder state is - * \c FLAC__STREAM_DECODER_SEEK_ERROR, then the decoder must be flushed - * with FLAC__stream_decoder_flush() or reset with - * FLAC__stream_decoder_reset() before decoding can continue. - * - * \param decoder A decoder instance. - * \param sample The target sample number to seek to. - * \assert - * \code decoder != NULL \endcode - * \retval FLAC__bool - * \c true if successful, else \c false. - */ FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *decoder, FLAC__uint64 sample); -/* \} */ - #ifdef __cplusplus } #endif @@ -107738,1716 +101055,237 @@ FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *deco extern "C" { #endif -/** \file include/FLAC/stream_encoder.h - * - * \brief - * This module contains the functions which implement the stream - * encoder. - * - * See the detailed documentation in the - * \link flac_stream_encoder stream encoder \endlink module. - */ - -/** \defgroup flac_encoder FLAC/ \*_encoder.h: encoder interfaces - * \ingroup flac - * - * \brief - * This module describes the encoder layers provided by libFLAC. - * - * The stream encoder can be used to encode complete streams either to the - * client via callbacks, or directly to a file, depending on how it is - * initialized. When encoding via callbacks, the client provides a write - * callback which will be called whenever FLAC data is ready to be written. - * If the client also supplies a seek callback, the encoder will also - * automatically handle the writing back of metadata discovered while - * encoding, like stream info, seek points offsets, etc. When encoding to - * a file, the client needs only supply a filename or open \c FILE* and an - * optional progress callback for periodic notification of progress; the - * write and seek callbacks are supplied internally. For more info see the - * \link flac_stream_encoder stream encoder \endlink module. - */ - -/** \defgroup flac_stream_encoder FLAC/stream_encoder.h: stream encoder interface - * \ingroup flac_encoder - * - * \brief - * This module contains the functions which implement the stream - * encoder. - * - * The stream encoder can encode to native FLAC, and optionally Ogg FLAC - * (check FLAC_API_SUPPORTS_OGG_FLAC) streams and files. - * - * The basic usage of this encoder is as follows: - * - The program creates an instance of an encoder using - * FLAC__stream_encoder_new(). - * - The program overrides the default settings using - * FLAC__stream_encoder_set_*() functions. At a minimum, the following - * functions should be called: - * - FLAC__stream_encoder_set_channels() - * - FLAC__stream_encoder_set_bits_per_sample() - * - FLAC__stream_encoder_set_sample_rate() - * - FLAC__stream_encoder_set_ogg_serial_number() (if encoding to Ogg FLAC) - * - FLAC__stream_encoder_set_total_samples_estimate() (if known) - * - If the application wants to control the compression level or set its own - * metadata, then the following should also be called: - * - FLAC__stream_encoder_set_compression_level() - * - FLAC__stream_encoder_set_verify() - * - FLAC__stream_encoder_set_metadata() - * - The rest of the set functions should only be called if the client needs - * exact control over how the audio is compressed; thorough understanding - * of the FLAC format is necessary to achieve good results. - * - The program initializes the instance to validate the settings and - * prepare for encoding using - * - FLAC__stream_encoder_init_stream() or FLAC__stream_encoder_init_FILE() - * or FLAC__stream_encoder_init_file() for native FLAC - * - FLAC__stream_encoder_init_ogg_stream() or FLAC__stream_encoder_init_ogg_FILE() - * or FLAC__stream_encoder_init_ogg_file() for Ogg FLAC - * - The program calls FLAC__stream_encoder_process() or - * FLAC__stream_encoder_process_interleaved() to encode data, which - * subsequently calls the callbacks when there is encoder data ready - * to be written. - * - The program finishes the encoding with FLAC__stream_encoder_finish(), - * which causes the encoder to encode any data still in its input pipe, - * update the metadata with the final encoding statistics if output - * seeking is possible, and finally reset the encoder to the - * uninitialized state. - * - The instance may be used again or deleted with - * FLAC__stream_encoder_delete(). - * - * In more detail, the stream encoder functions similarly to the - * \link flac_stream_decoder stream decoder \endlink, but has fewer - * callbacks and more options. Typically the client will create a new - * instance by calling FLAC__stream_encoder_new(), then set the necessary - * parameters with FLAC__stream_encoder_set_*(), and initialize it by - * calling one of the FLAC__stream_encoder_init_*() functions. - * - * Unlike the decoders, the stream encoder has many options that can - * affect the speed and compression ratio. When setting these parameters - * you should have some basic knowledge of the format (see the - * user-level documentation - * or the formal description). The - * FLAC__stream_encoder_set_*() functions themselves do not validate the - * values as many are interdependent. The FLAC__stream_encoder_init_*() - * functions will do this, so make sure to pay attention to the state - * returned by FLAC__stream_encoder_init_*() to make sure that it is - * FLAC__STREAM_ENCODER_INIT_STATUS_OK. Any parameters that are not set - * before FLAC__stream_encoder_init_*() will take on the defaults from - * the constructor. - * - * There are three initialization functions for native FLAC, one for - * setting up the encoder to encode FLAC data to the client via - * callbacks, and two for encoding directly to a file. - * - * For encoding via callbacks, use FLAC__stream_encoder_init_stream(). - * You must also supply a write callback which will be called anytime - * there is raw encoded data to write. If the client can seek the output - * it is best to also supply seek and tell callbacks, as this allows the - * encoder to go back after encoding is finished to write back - * information that was collected while encoding, like seek point offsets, - * frame sizes, etc. - * - * For encoding directly to a file, use FLAC__stream_encoder_init_FILE() - * or FLAC__stream_encoder_init_file(). Then you must only supply a - * filename or open \c FILE*; the encoder will handle all the callbacks - * internally. You may also supply a progress callback for periodic - * notification of the encoding progress. - * - * There are three similarly-named init functions for encoding to Ogg - * FLAC streams. Check \c FLAC_API_SUPPORTS_OGG_FLAC to find out if the - * library has been built with Ogg support. - * - * The call to FLAC__stream_encoder_init_*() currently will also immediately - * call the write callback several times, once with the \c fLaC signature, - * and once for each encoded metadata block. Note that for Ogg FLAC - * encoding you will usually get at least twice the number of callbacks than - * with native FLAC, one for the Ogg page header and one for the page body. - * - * After initializing the instance, the client may feed audio data to the - * encoder in one of two ways: - * - * - Channel separate, through FLAC__stream_encoder_process() - The client - * will pass an array of pointers to buffers, one for each channel, to - * the encoder, each of the same length. The samples need not be - * block-aligned, but each channel should have the same number of samples. - * - Channel interleaved, through - * FLAC__stream_encoder_process_interleaved() - The client will pass a single - * pointer to data that is channel-interleaved (i.e. channel0_sample0, - * channel1_sample0, ... , channelN_sample0, channel0_sample1, ...). - * Again, the samples need not be block-aligned but they must be - * sample-aligned, i.e. the first value should be channel0_sample0 and - * the last value channelN_sampleM. - * - * Note that for either process call, each sample in the buffers should be a - * signed integer, right-justified to the resolution set by - * FLAC__stream_encoder_set_bits_per_sample(). For example, if the resolution - * is 16 bits per sample, the samples should all be in the range [-32768,32767]. - * - * When the client is finished encoding data, it calls - * FLAC__stream_encoder_finish(), which causes the encoder to encode any - * data still in its input pipe, and call the metadata callback with the - * final encoding statistics. Then the instance may be deleted with - * FLAC__stream_encoder_delete() or initialized again to encode another - * stream. - * - * For programs that write their own metadata, but that do not know the - * actual metadata until after encoding, it is advantageous to instruct - * the encoder to write a PADDING block of the correct size, so that - * instead of rewriting the whole stream after encoding, the program can - * just overwrite the PADDING block. If only the maximum size of the - * metadata is known, the program can write a slightly larger padding - * block, then split it after encoding. - * - * Make sure you understand how lengths are calculated. All FLAC metadata - * blocks have a 4 byte header which contains the type and length. This - * length does not include the 4 bytes of the header. See the format page - * for the specification of metadata blocks and their lengths. - * - * \note - * If you are writing the FLAC data to a file via callbacks, make sure it - * is open for update (e.g. mode "w+" for stdio streams). This is because - * after the first encoding pass, the encoder will try to seek back to the - * beginning of the stream, to the STREAMINFO block, to write some data - * there. (If using FLAC__stream_encoder_init*_file() or - * FLAC__stream_encoder_init*_FILE(), the file is managed internally.) - * - * \note - * The "set" functions may only be called when the encoder is in the - * state FLAC__STREAM_ENCODER_UNINITIALIZED, i.e. after - * FLAC__stream_encoder_new() or FLAC__stream_encoder_finish(), but - * before FLAC__stream_encoder_init_*(). If this is the case they will - * return \c true, otherwise \c false. - * - * \note - * FLAC__stream_encoder_finish() resets all settings to the constructor - * defaults. - * - * \{ - */ - -/** State values for a FLAC__StreamEncoder. - * - * The encoder's state can be obtained by calling FLAC__stream_encoder_get_state(). - * - * If the encoder gets into any other state besides \c FLAC__STREAM_ENCODER_OK - * or \c FLAC__STREAM_ENCODER_UNINITIALIZED, it becomes invalid for encoding and - * must be deleted with FLAC__stream_encoder_delete(). - */ typedef enum { FLAC__STREAM_ENCODER_OK = 0, - /**< The encoder is in the normal OK state and samples can be processed. */ FLAC__STREAM_ENCODER_UNINITIALIZED, - /**< The encoder is in the uninitialized state; one of the - * FLAC__stream_encoder_init_*() functions must be called before samples - * can be processed. - */ FLAC__STREAM_ENCODER_OGG_ERROR, - /**< An error occurred in the underlying Ogg layer. */ FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR, - /**< An error occurred in the underlying verify stream decoder; - * check FLAC__stream_encoder_get_verify_decoder_state(). - */ FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA, - /**< The verify decoder detected a mismatch between the original - * audio signal and the decoded audio signal. - */ FLAC__STREAM_ENCODER_CLIENT_ERROR, - /**< One of the callbacks returned a fatal error. */ FLAC__STREAM_ENCODER_IO_ERROR, - /**< An I/O error occurred while opening/reading/writing a file. - * Check \c errno. - */ FLAC__STREAM_ENCODER_FRAMING_ERROR, - /**< An error occurred while writing the stream; usually, the - * write_callback returned an error. - */ FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR - /**< Memory allocation failed. */ } FLAC__StreamEncoderState; -/** Maps a FLAC__StreamEncoderState to a C string. - * - * Using a FLAC__StreamEncoderState as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamEncoderStateString[]; -/** Possible return values for the FLAC__stream_encoder_init_*() functions. - */ typedef enum { FLAC__STREAM_ENCODER_INIT_STATUS_OK = 0, - /**< Initialization was successful. */ FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR, - /**< General failure to set up encoder; call FLAC__stream_encoder_get_state() for cause. */ FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER, - /**< The library was not compiled with support for the given container - * format. - */ FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS, - /**< A required callback was not supplied. */ FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS, - /**< The encoder has an invalid setting for number of channels. */ FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE, - /**< The encoder has an invalid setting for bits-per-sample. - * FLAC supports 4-32 bps but the reference encoder currently supports - * only up to 24 bps. - */ FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE, - /**< The encoder has an invalid setting for the input sample rate. */ FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE, - /**< The encoder has an invalid setting for the block size. */ FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER, - /**< The encoder has an invalid setting for the maximum LPC order. */ FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION, - /**< The encoder has an invalid setting for the precision of the quantized linear predictor coefficients. */ FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER, - /**< The specified block size is less than the maximum LPC order. */ FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE, - /**< The encoder is bound to the Subset but other settings violate it. */ FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA, - /**< The metadata input to the encoder is invalid, in one of the following ways: - * - FLAC__stream_encoder_set_metadata() was called with a null pointer but a block count > 0 - * - One of the metadata blocks contains an undefined type - * - It contains an illegal CUESHEET as checked by FLAC__format_cuesheet_is_legal() - * - It contains an illegal SEEKTABLE as checked by FLAC__format_seektable_is_legal() - * - It contains more than one SEEKTABLE block or more than one VORBIS_COMMENT block - */ FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED - /**< FLAC__stream_encoder_init_*() was called when the encoder was - * already initialized, usually because - * FLAC__stream_encoder_finish() was not called. - */ } FLAC__StreamEncoderInitStatus; -/** Maps a FLAC__StreamEncoderInitStatus to a C string. - * - * Using a FLAC__StreamEncoderInitStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamEncoderInitStatusString[]; -/** Return values for the FLAC__StreamEncoder read callback. - */ typedef enum { FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE, - /**< The read was OK and decoding can continue. */ FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM, - /**< The read was attempted at the end of the stream. */ FLAC__STREAM_ENCODER_READ_STATUS_ABORT, - /**< An unrecoverable error occurred. */ FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED - /**< Client does not support reading back from the output. */ } FLAC__StreamEncoderReadStatus; -/** Maps a FLAC__StreamEncoderReadStatus to a C string. - * - * Using a FLAC__StreamEncoderReadStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamEncoderReadStatusString[]; -/** Return values for the FLAC__StreamEncoder write callback. - */ typedef enum { FLAC__STREAM_ENCODER_WRITE_STATUS_OK = 0, - /**< The write was OK and encoding can continue. */ FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR - /**< An unrecoverable error occurred. The encoder will return from the process call. */ } FLAC__StreamEncoderWriteStatus; -/** Maps a FLAC__StreamEncoderWriteStatus to a C string. - * - * Using a FLAC__StreamEncoderWriteStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[]; -/** Return values for the FLAC__StreamEncoder seek callback. - */ typedef enum { FLAC__STREAM_ENCODER_SEEK_STATUS_OK, - /**< The seek was OK and encoding can continue. */ FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR, - /**< An unrecoverable error occurred. */ FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED - /**< Client does not support seeking. */ } FLAC__StreamEncoderSeekStatus; -/** Maps a FLAC__StreamEncoderSeekStatus to a C string. - * - * Using a FLAC__StreamEncoderSeekStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[]; -/** Return values for the FLAC__StreamEncoder tell callback. - */ typedef enum { FLAC__STREAM_ENCODER_TELL_STATUS_OK, - /**< The tell was OK and encoding can continue. */ FLAC__STREAM_ENCODER_TELL_STATUS_ERROR, - /**< An unrecoverable error occurred. */ FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED - /**< Client does not support seeking. */ } FLAC__StreamEncoderTellStatus; -/** Maps a FLAC__StreamEncoderTellStatus to a C string. - * - * Using a FLAC__StreamEncoderTellStatus as the index to this array - * will give the string equivalent. The contents should not be modified. - */ extern FLAC_API const char * const FLAC__StreamEncoderTellStatusString[]; -/*********************************************************************** - * - * class FLAC__StreamEncoder - * - ***********************************************************************/ - struct FLAC__StreamEncoderProtected; struct FLAC__StreamEncoderPrivate; -/** The opaque structure definition for the stream encoder type. - * See the \link flac_stream_encoder stream encoder module \endlink - * for a detailed description. - */ typedef struct { struct FLAC__StreamEncoderProtected *protected_; /* avoid the C++ keyword 'protected' */ struct FLAC__StreamEncoderPrivate *private_; /* avoid the C++ keyword 'private' */ } FLAC__StreamEncoder; -/** Signature for the read callback. - * - * A function pointer matching this signature must be passed to - * FLAC__stream_encoder_init_ogg_stream() if seeking is supported. - * The supplied function will be called when the encoder needs to read back - * encoded data. This happens during the metadata callback, when the encoder - * has to read, modify, and rewrite the metadata (e.g. seekpoints) gathered - * while encoding. The address of the buffer to be filled is supplied, along - * with the number of bytes the buffer can hold. The callback may choose to - * supply less data and modify the byte count but must be careful not to - * overflow the buffer. The callback then returns a status code chosen from - * FLAC__StreamEncoderReadStatus. - * - * Here is an example of a read callback for stdio streams: - * \code - * FLAC__StreamEncoderReadStatus read_cb(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * if(*bytes > 0) { - * *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, file); - * if(ferror(file)) - * return FLAC__STREAM_ENCODER_READ_STATUS_ABORT; - * else if(*bytes == 0) - * return FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM; - * else - * return FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE; - * } - * else - * return FLAC__STREAM_ENCODER_READ_STATUS_ABORT; - * } - * \endcode - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param buffer A pointer to a location for the callee to store - * data to be encoded. - * \param bytes A pointer to the size of the buffer. On entry - * to the callback, it contains the maximum number - * of bytes that may be stored in \a buffer. The - * callee must set it to the actual number of bytes - * stored (0 in case of error or end-of-stream) before - * returning. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_set_client_data(). - * \retval FLAC__StreamEncoderReadStatus - * The callee's return status. - */ typedef FLAC__StreamEncoderReadStatus (*FLAC__StreamEncoderReadCallback)(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data); -/** Signature for the write callback. - * - * A function pointer matching this signature must be passed to - * FLAC__stream_encoder_init*_stream(). The supplied function will be called - * by the encoder anytime there is raw encoded data ready to write. It may - * include metadata mixed with encoded audio frames and the data is not - * guaranteed to be aligned on frame or metadata block boundaries. - * - * The only duty of the callback is to write out the \a bytes worth of data - * in \a buffer to the current position in the output stream. The arguments - * \a samples and \a current_frame are purely informational. If \a samples - * is greater than \c 0, then \a current_frame will hold the current frame - * number that is being written; otherwise it indicates that the write - * callback is being called to write metadata. - * - * \note - * Unlike when writing to native FLAC, when writing to Ogg FLAC the - * write callback will be called twice when writing each audio - * frame; once for the page header, and once for the page body. - * When writing the page header, the \a samples argument to the - * write callback will be \c 0. - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param buffer An array of encoded data of length \a bytes. - * \param bytes The byte length of \a buffer. - * \param samples The number of samples encoded by \a buffer. - * \c 0 has a special meaning; see above. - * \param current_frame The number of the current frame being encoded. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_init_*(). - * \retval FLAC__StreamEncoderWriteStatus - * The callee's return status. - */ typedef FLAC__StreamEncoderWriteStatus (*FLAC__StreamEncoderWriteCallback)(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data); -/** Signature for the seek callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_encoder_init*_stream(). The supplied function will be called - * when the encoder needs to seek the output stream. The encoder will pass - * the absolute byte offset to seek to, 0 meaning the beginning of the stream. - * - * Here is an example of a seek callback for stdio streams: - * \code - * FLAC__StreamEncoderSeekStatus seek_cb(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * if(file == stdin) - * return FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED; - * else if(fseeko(file, (off_t)absolute_byte_offset, SEEK_SET) < 0) - * return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR; - * else - * return FLAC__STREAM_ENCODER_SEEK_STATUS_OK; - * } - * \endcode - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param absolute_byte_offset The offset from the beginning of the stream - * to seek to. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_init_*(). - * \retval FLAC__StreamEncoderSeekStatus - * The callee's return status. - */ typedef FLAC__StreamEncoderSeekStatus (*FLAC__StreamEncoderSeekCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data); -/** Signature for the tell callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_encoder_init*_stream(). The supplied function will be called - * when the encoder needs to know the current position of the output stream. - * - * \warning - * The callback must return the true current byte offset of the output to - * which the encoder is writing. If you are buffering the output, make - * sure and take this into account. If you are writing directly to a - * FILE* from your write callback, ftell() is sufficient. If you are - * writing directly to a file descriptor from your write callback, you - * can use lseek(fd, SEEK_CUR, 0). The encoder may later seek back to - * these points to rewrite metadata after encoding. - * - * Here is an example of a tell callback for stdio streams: - * \code - * FLAC__StreamEncoderTellStatus tell_cb(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data) - * { - * FILE *file = ((MyClientData*)client_data)->file; - * off_t pos; - * if(file == stdin) - * return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED; - * else if((pos = ftello(file)) < 0) - * return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR; - * else { - * *absolute_byte_offset = (FLAC__uint64)pos; - * return FLAC__STREAM_ENCODER_TELL_STATUS_OK; - * } - * } - * \endcode - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param absolute_byte_offset The address at which to store the current - * position of the output. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_init_*(). - * \retval FLAC__StreamEncoderTellStatus - * The callee's return status. - */ typedef FLAC__StreamEncoderTellStatus (*FLAC__StreamEncoderTellCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data); -/** Signature for the metadata callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_encoder_init*_stream(). The supplied function will be called - * once at the end of encoding with the populated STREAMINFO structure. This - * is so the client can seek back to the beginning of the file and write the - * STREAMINFO block with the correct statistics after encoding (like - * minimum/maximum frame size and total samples). - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param metadata The final populated STREAMINFO block. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_init_*(). - */ typedef void (*FLAC__StreamEncoderMetadataCallback)(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data); -/** Signature for the progress callback. - * - * A function pointer matching this signature may be passed to - * FLAC__stream_encoder_init*_file() or FLAC__stream_encoder_init*_FILE(). - * The supplied function will be called when the encoder has finished - * writing a frame. The \c total_frames_estimate argument to the - * callback will be based on the value from - * FLAC__stream_encoder_set_total_samples_estimate(). - * - * \note In general, FLAC__StreamEncoder functions which change the - * state should not be called on the \a encoder while in the callback. - * - * \param encoder The encoder instance calling the callback. - * \param bytes_written Bytes written so far. - * \param samples_written Samples written so far. - * \param frames_written Frames written so far. - * \param total_frames_estimate The estimate of the total number of - * frames to be written. - * \param client_data The callee's client data set through - * FLAC__stream_encoder_init_*(). - */ typedef void (*FLAC__StreamEncoderProgressCallback)(const FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data); -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - -/** Create a new stream encoder instance. The instance is created with - * default settings; see the individual FLAC__stream_encoder_set_*() - * functions for each setting's default. - * - * \retval FLAC__StreamEncoder* - * \c NULL if there was an error allocating memory, else the new instance. - */ FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new(void); -/** Free an encoder instance. Deletes the object pointed to by \a encoder. - * - * \param encoder A pointer to an existing encoder. - * \assert - * \code encoder != NULL \endcode - */ FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder); -/*********************************************************************** - * - * Public class method prototypes - * - ***********************************************************************/ - -/** Set the serial number for the FLAC stream to use in the Ogg container. - * - * \note - * This does not need to be set for native FLAC encoding. - * - * \note - * It is recommended to set a serial number explicitly as the default of '0' - * may collide with other streams. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param serial_number See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_ogg_serial_number(FLAC__StreamEncoder *encoder, long serial_number); -/** Set the "verify" flag. If \c true, the encoder will verify it's own - * encoded output by feeding it through an internal decoder and comparing - * the original signal against the decoded signal. If a mismatch occurs, - * the process call will return \c false. Note that this will slow the - * encoding process by the extra time required for decoding and comparison. - * - * \default \c false - * \param encoder An encoder instance to set. - * \param value Flag value (see above). - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value); -/** Set the Subset flag. If \c true, - * the encoder will comply with the Subset and will check the - * settings during FLAC__stream_encoder_init_*() to see if all settings - * comply. If \c false, the settings may take advantage of the full - * range that the format allows. - * - * Make sure you know what it entails before setting this to \c false. - * - * \default \c true - * \param encoder An encoder instance to set. - * \param value Flag value (see above). - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value); -/** Set the number of channels to be encoded. - * - * \default \c 2 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_channels(FLAC__StreamEncoder *encoder, unsigned value); -/** Set the sample resolution of the input to be encoded. - * - * \warning - * Do not feed the encoder data that is wider than the value you - * set here or you will generate an invalid stream. - * - * \default \c 16 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_bits_per_sample(FLAC__StreamEncoder *encoder, unsigned value); -/** Set the sample rate (in Hz) of the input to be encoded. - * - * \default \c 44100 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *encoder, unsigned value); -/** Set the compression level - * - * The compression level is roughly proportional to the amount of effort - * the encoder expends to compress the file. A higher level usually - * means more computation but higher compression. The default level is - * suitable for most applications. - * - * Currently the levels range from \c 0 (fastest, least compression) to - * \c 8 (slowest, most compression). A value larger than \c 8 will be - * treated as \c 8. - * - * This function automatically calls the following other \c _set_ - * functions with appropriate values, so the client does not need to - * unless it specifically wants to override them: - * - FLAC__stream_encoder_set_do_mid_side_stereo() - * - FLAC__stream_encoder_set_loose_mid_side_stereo() - * - FLAC__stream_encoder_set_apodization() - * - FLAC__stream_encoder_set_max_lpc_order() - * - FLAC__stream_encoder_set_qlp_coeff_precision() - * - FLAC__stream_encoder_set_do_qlp_coeff_prec_search() - * - FLAC__stream_encoder_set_do_escape_coding() - * - FLAC__stream_encoder_set_do_exhaustive_model_search() - * - FLAC__stream_encoder_set_min_residual_partition_order() - * - FLAC__stream_encoder_set_max_residual_partition_order() - * - FLAC__stream_encoder_set_rice_parameter_search_dist() - * - * The actual values set for each level are: - * - * - * - * - * - * - * - * - * - * - * - * - *
level - * do mid-side stereo - * loose mid-side stereo - * apodization - * max lpc order - * qlp coeff precision - * qlp coeff prec search - * escape coding - * exhaustive model search - * min residual partition order - * max residual partition order - * rice parameter search dist - *
0 false false tukey(0.5) 0 0 false false false 0 3 0
1 true true tukey(0.5) 0 0 false false false 0 3 0
2 true false tukey(0.5) 0 0 false false false 0 3 0
3 false false tukey(0.5) 6 0 false false false 0 4 0
4 true true tukey(0.5) 8 0 false false false 0 4 0
5 true false tukey(0.5) 8 0 false false false 0 5 0
6 true false tukey(0.5) 8 0 false false false 0 6 0
7 true false tukey(0.5) 8 0 false false true 0 6 0
8 true false tukey(0.5) 12 0 false false true 0 6 0
- * - * \default \c 5 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncoder *encoder, unsigned value); -/** Set the blocksize to use while encoding. - * - * The number of samples to use per frame. Use \c 0 to let the encoder - * estimate a blocksize; this is usually best. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_blocksize(FLAC__StreamEncoder *encoder, unsigned value); -/** Set to \c true to enable mid-side encoding on stereo input. The - * number of channels must be 2 for this to have any effect. Set to - * \c false to use only independent channel coding. - * - * \default \c false - * \param encoder An encoder instance to set. - * \param value Flag value (see above). - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_do_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value); -/** Set to \c true to enable adaptive switching between mid-side and - * left-right encoding on stereo input. Set to \c false to use - * exhaustive searching. Setting this to \c true requires - * FLAC__stream_encoder_set_do_mid_side_stereo() to also be set to - * \c true in order to have any effect. - * - * \default \c false - * \param encoder An encoder instance to set. - * \param value Flag value (see above). - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamEncoder *encoder, FLAC__bool value); -/** Sets the apodization function(s) the encoder will use when windowing - * audio data for LPC analysis. - * - * The \a specification is a plain ASCII string which specifies exactly - * which functions to use. There may be more than one (up to 32), - * separated by \c ';' characters. Some functions take one or more - * comma-separated arguments in parentheses. - * - * The available functions are \c bartlett, \c bartlett_hann, - * \c blackman, \c blackman_harris_4term_92db, \c connes, \c flattop, - * \c gauss(STDDEV), \c hamming, \c hann, \c kaiser_bessel, \c nuttall, - * \c rectangle, \c triangle, \c tukey(P), \c welch. - * - * For \c gauss(STDDEV), STDDEV specifies the standard deviation - * (0blocksize / (2 ^ order). - * - * Set both min and max values to \c 0 to force a single context, - * whose Rice parameter is based on the residual signal variance. - * Otherwise, set a min and max order, and the encoder will search - * all orders, using the mean of each context for its Rice parameter, - * and use the best. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_min_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value); -/** Set the maximum partition order to search when coding the residual. - * This is used in tandem with - * FLAC__stream_encoder_set_min_residual_partition_order(). - * - * The partition order determines the context size in the residual. - * The context size will be approximately blocksize / (2 ^ order). - * - * Set both min and max values to \c 0 to force a single context, - * whose Rice parameter is based on the residual signal variance. - * Otherwise, set a min and max order, and the encoder will search - * all orders, using the mean of each context for its Rice parameter, - * and use the best. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_max_residual_partition_order(FLAC__StreamEncoder *encoder, unsigned value); -/** Deprecated. Setting this value has no effect. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__StreamEncoder *encoder, unsigned value); -/** Set an estimate of the total samples that will be encoded. - * This is merely an estimate and may be set to \c 0 if unknown. - * This value will be written to the STREAMINFO block before encoding, - * and can remove the need for the caller to rewrite the value later - * if the value is known before encoding. - * - * \default \c 0 - * \param encoder An encoder instance to set. - * \param value See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__StreamEncoder *encoder, FLAC__uint64 value); -/** Set the metadata blocks to be emitted to the stream before encoding. - * A value of \c NULL, \c 0 implies no metadata; otherwise, supply an - * array of pointers to metadata blocks. The array is non-const since - * the encoder may need to change the \a is_last flag inside them, and - * in some cases update seek point offsets. Otherwise, the encoder will - * not modify or free the blocks. It is up to the caller to free the - * metadata blocks after encoding finishes. - * - * \note - * The encoder stores only copies of the pointers in the \a metadata array; - * the metadata blocks themselves must survive at least until after - * FLAC__stream_encoder_finish() returns. Do not free the blocks until then. - * - * \note - * The STREAMINFO block is always written and no STREAMINFO block may - * occur in the supplied array. - * - * \note - * By default the encoder does not create a SEEKTABLE. If one is supplied - * in the \a metadata array, but the client has specified that it does not - * support seeking, then the SEEKTABLE will be written verbatim. However - * by itself this is not very useful as the client will not know the stream - * offsets for the seekpoints ahead of time. In order to get a proper - * seektable the client must support seeking. See next note. - * - * \note - * SEEKTABLE blocks are handled specially. Since you will not know - * the values for the seek point stream offsets, you should pass in - * a SEEKTABLE 'template', that is, a SEEKTABLE object with the - * required sample numbers (or placeholder points), with \c 0 for the - * \a frame_samples and \a stream_offset fields for each point. If the - * client has specified that it supports seeking by providing a seek - * callback to FLAC__stream_encoder_init_stream() or both seek AND read - * callback to FLAC__stream_encoder_init_ogg_stream() (or by using - * FLAC__stream_encoder_init*_file() or FLAC__stream_encoder_init*_FILE()), - * then while it is encoding the encoder will fill the stream offsets in - * for you and when encoding is finished, it will seek back and write the - * real values into the SEEKTABLE block in the stream. There are helper - * routines for manipulating seektable template blocks; see metadata.h: - * FLAC__metadata_object_seektable_template_*(). If the client does - * not support seeking, the SEEKTABLE will have inaccurate offsets which - * will slow down or remove the ability to seek in the FLAC stream. - * - * \note - * The encoder instance \b will modify the first \c SEEKTABLE block - * as it transforms the template to a valid seektable while encoding, - * but it is still up to the caller to free all metadata blocks after - * encoding. - * - * \note - * A VORBIS_COMMENT block may be supplied. The vendor string in it - * will be ignored. libFLAC will use it's own vendor string. libFLAC - * will not modify the passed-in VORBIS_COMMENT's vendor string, it - * will simply write it's own into the stream. If no VORBIS_COMMENT - * block is present in the \a metadata array, libFLAC will write an - * empty one, containing only the vendor string. - * - * \note The Ogg FLAC mapping requires that the VORBIS_COMMENT block be - * the second metadata block of the stream. The encoder already supplies - * the STREAMINFO block automatically. If \a metadata does not contain a - * VORBIS_COMMENT block, the encoder will supply that too. Otherwise, if - * \a metadata does contain a VORBIS_COMMENT block and it is not the - * first, the init function will reorder \a metadata by moving the - * VORBIS_COMMENT block to the front; the relative ordering of the other - * blocks will remain as they were. - * - * \note The Ogg FLAC mapping limits the number of metadata blocks per - * stream to \c 65535. If \a num_blocks exceeds this the function will - * return \c false. - * - * \default \c NULL, 0 - * \param encoder An encoder instance to set. - * \param metadata See above. - * \param num_blocks See above. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * \c false if the encoder is already initialized, else \c true. - * \c false if the encoder is already initialized, or if - * \a num_blocks > 65535 if encoding to Ogg FLAC, else \c true. - */ FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks); -/** Get the current encoder state. - * - * \param encoder An encoder instance to query. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__StreamEncoderState - * The current encoder state. - */ FLAC_API FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder); -/** Get the state of the verify stream decoder. - * Useful when the stream encoder state is - * \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR. - * - * \param encoder An encoder instance to query. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__StreamDecoderState - * The verify stream decoder state. - */ FLAC_API FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder); -/** Get the current encoder state as a C string. - * This version automatically resolves - * \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR by getting the - * verify decoder's state. - * - * \param encoder A encoder instance to query. - * \assert - * \code encoder != NULL \endcode - * \retval const char * - * The encoder state as a C string. Do not modify the contents. - */ FLAC_API const char *FLAC__stream_encoder_get_resolved_state_string(const FLAC__StreamEncoder *encoder); -/** Get relevant values about the nature of a verify decoder error. - * Useful when the stream encoder state is - * \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR. The arguments should - * be addresses in which the stats will be returned, or NULL if value - * is not desired. - * - * \param encoder An encoder instance to query. - * \param absolute_sample The absolute sample number of the mismatch. - * \param frame_number The number of the frame in which the mismatch occurred. - * \param channel The channel in which the mismatch occurred. - * \param sample The number of the sample (relative to the frame) in - * which the mismatch occurred. - * \param expected The expected value for the sample in question. - * \param got The actual value returned by the decoder. - * \assert - * \code encoder != NULL \endcode - */ FLAC_API void FLAC__stream_encoder_get_verify_decoder_error_stats(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got); -/** Get the "verify" flag. - * - * \param encoder An encoder instance to query. - * \assert - * \code encoder != NULL \endcode - * \retval FLAC__bool - * See FLAC__stream_encoder_set_verify(). - */ FLAC_API FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder); -/** Get the frame header. - * - * \param encoder An initialized encoder instance in the OK state. - * \param buffer An array of pointers to each channel's signal. - * \param samples The number of samples in one channel. - * \assert - * \code encoder != NULL \endcode - * \code FLAC__stream_encoder_get_state(encoder) == FLAC__STREAM_ENCODER_OK \endcode - * \retval FLAC__bool - * \c true if successful, else \c false; in this case, check the - * encoder state with FLAC__stream_encoder_get_state() to see what - * went wrong. - */ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples); -/** Submit data for encoding. - * This version allows you to supply the input data where the channels - * are interleaved into a single array (i.e. channel0_sample0, - * channel1_sample0, ... , channelN_sample0, channel0_sample1, ...). - * The samples need not be block-aligned but they must be - * sample-aligned, i.e. the first value should be channel0_sample0 - * and the last value channelN_sampleM. Each sample should be a signed - * integer, right-justified to the resolution set by - * FLAC__stream_encoder_set_bits_per_sample(). For example, if the - * resolution is 16 bits per sample, the samples should all be in the - * range [-32768,32767]. - * - * For applications where channel order is important, channels must - * follow the order as described in the - * frame header. - * - * \param encoder An initialized encoder instance in the OK state. - * \param buffer An array of channel-interleaved data (see above). - * \param samples The number of samples in one channel, the same as for - * FLAC__stream_encoder_process(). For example, if - * encoding two channels, \c 1000 \a samples corresponds - * to a \a buffer of 2000 values. - * \assert - * \code encoder != NULL \endcode - * \code FLAC__stream_encoder_get_state(encoder) == FLAC__STREAM_ENCODER_OK \endcode - * \retval FLAC__bool - * \c true if successful, else \c false; in this case, check the - * encoder state with FLAC__stream_encoder_get_state() to see what - * went wrong. - */ FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples); -/* \} */ - #ifdef __cplusplus } #endif @@ -109456,7 +101294,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder /********* End of inlined file: stream_encoder.h *********/ #ifdef _MSC_VER -/* OPT: an MSVC built-in would be better */ static _inline FLAC__uint32 local_swap32_(FLAC__uint32 x) { x = ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF); @@ -109465,7 +101302,6 @@ static _inline FLAC__uint32 local_swap32_(FLAC__uint32 x) #endif #if defined(_MSC_VER) && defined(_X86_) -/* OPT: an MSVC built-in would be better */ static void local_swap32_block_(FLAC__uint32 *start, FLAC__uint32 len) { __asm { @@ -109485,331 +101321,6 @@ done1: } #endif -/** \mainpage - * - * \section intro Introduction - * - * This is the documentation for the FLAC C and C++ APIs. It is - * highly interconnected; this introduction should give you a top - * level idea of the structure and how to find the information you - * need. As a prerequisite you should have at least a basic - * knowledge of the FLAC format, documented - * here. - * - * \section c_api FLAC C API - * - * The FLAC C API is the interface to libFLAC, a set of structures - * describing the components of FLAC streams, and functions for - * encoding and decoding streams, as well as manipulating FLAC - * metadata in files. The public include files will be installed - * in your include area (for example /usr/include/FLAC/...). - * - * By writing a little code and linking against libFLAC, it is - * relatively easy to add FLAC support to another program. The - * library is licensed under Xiph's BSD license. - * Complete source code of libFLAC as well as the command-line - * encoder and plugins is available and is a useful source of - * examples. - * - * Aside from encoders and decoders, libFLAC provides a powerful - * metadata interface for manipulating metadata in FLAC files. It - * allows the user to add, delete, and modify FLAC metadata blocks - * and it can automatically take advantage of PADDING blocks to avoid - * rewriting the entire FLAC file when changing the size of the - * metadata. - * - * libFLAC usually only requires the standard C library and C math - * library. In particular, threading is not used so there is no - * dependency on a thread library. However, libFLAC does not use - * global variables and should be thread-safe. - * - * libFLAC also supports encoding to and decoding from Ogg FLAC. - * However the metadata editing interfaces currently have limited - * read-only support for Ogg FLAC files. - * - * \section cpp_api FLAC C++ API - * - * The FLAC C++ API is a set of classes that encapsulate the - * structures and functions in libFLAC. They provide slightly more - * functionality with respect to metadata but are otherwise - * equivalent. For the most part, they share the same usage as - * their counterparts in libFLAC, and the FLAC C API documentation - * can be used as a supplement. The public include files - * for the C++ API will be installed in your include area (for - * example /usr/include/FLAC++/...). - * - * libFLAC++ is also licensed under - * Xiph's BSD license. - * - * \section getting_started Getting Started - * - * A good starting point for learning the API is to browse through - * the modules. Modules are logical - * groupings of related functions or classes, which correspond roughly - * to header files or sections of header files. Each module includes a - * detailed description of the general usage of its functions or - * classes. - * - * From there you can go on to look at the documentation of - * individual functions. You can see different views of the individual - * functions through the links in top bar across this page. - * - * If you prefer a more hands-on approach, you can jump right to some - * example code. - * - * \section porting_guide Porting Guide - * - * Starting with FLAC 1.1.3 a \link porting Porting Guide \endlink - * has been introduced which gives detailed instructions on how to - * port your code to newer versions of FLAC. - * - * \section embedded_developers Embedded Developers - * - * libFLAC has grown larger over time as more functionality has been - * included, but much of it may be unnecessary for a particular embedded - * implementation. Unused parts may be pruned by some simple editing of - * src/libFLAC/Makefile.am. In general, the decoders, encoders, and - * metadata interface are all independent from each other. - * - * It is easiest to just describe the dependencies: - * - * - All modules depend on the \link flac_format Format \endlink module. - * - The decoders and encoders depend on the bitbuffer. - * - The decoder is independent of the encoder. The encoder uses the - * decoder because of the verify feature, but this can be removed if - * not needed. - * - Parts of the metadata interface require the stream decoder (but not - * the encoder). - * - Ogg support is selectable through the compile time macro - * \c FLAC__HAS_OGG. - * - * For example, if your application only requires the stream decoder, no - * encoder, and no metadata interface, you can remove the stream encoder - * and the metadata interface, which will greatly reduce the size of the - * library. - * - * Also, there are several places in the libFLAC code with comments marked - * with "OPT:" where a #define can be changed to enable code that might be - * faster on a specific platform. Experimenting with these can yield faster - * binaries. - */ - -/** \defgroup porting Porting Guide for New Versions - * - * This module describes differences in the library interfaces from - * version to version. It assists in the porting of code that uses - * the libraries to newer versions of FLAC. - * - * One simple facility for making porting easier that has been added - * in FLAC 1.1.3 is a set of \c #defines in \c export.h of each - * library's includes (e.g. \c include/FLAC/export.h). The - * \c #defines mirror the libraries' - * libtool version numbers, - * e.g. in libFLAC there are \c FLAC_API_VERSION_CURRENT, - * \c FLAC_API_VERSION_REVISION, and \c FLAC_API_VERSION_AGE. - * These can be used to support multiple versions of an API during the - * transition phase, e.g. - * - * \code - * #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 - * legacy code - * #else - * new code - * #endif - * \endcode - * - * The the source will work for multiple versions and the legacy code can - * easily be removed when the transition is complete. - * - * Another available symbol is FLAC_API_SUPPORTS_OGG_FLAC (defined in - * include/FLAC/export.h), which can be used to determine whether or not - * the library has been compiled with support for Ogg FLAC. This is - * simpler than trying to call an Ogg init function and catching the - * error. - */ - -/** \defgroup porting_1_1_2_to_1_1_3 Porting from FLAC 1.1.2 to 1.1.3 - * \ingroup porting - * - * \brief - * This module describes porting from FLAC 1.1.2 to FLAC 1.1.3. - * - * The main change between the APIs in 1.1.2 and 1.1.3 is that they have - * been simplified. First, libOggFLAC has been merged into libFLAC and - * libOggFLAC++ has been merged into libFLAC++. Second, both the three - * decoding layers and three encoding layers have been merged into a - * single stream decoder and stream encoder. That is, the functionality - * of FLAC__SeekableStreamDecoder and FLAC__FileDecoder has been merged - * into FLAC__StreamDecoder, and FLAC__SeekableStreamEncoder and - * FLAC__FileEncoder into FLAC__StreamEncoder. Only the - * FLAC__StreamDecoder and FLAC__StreamEncoder remain. What this means - * is there is now a single API that can be used to encode or decode - * streams to/from native FLAC or Ogg FLAC and the single API can work - * on both seekable and non-seekable streams. - * - * Instead of creating an encoder or decoder of a certain layer, now the - * client will always create a FLAC__StreamEncoder or - * FLAC__StreamDecoder. The old layers are now differentiated by the - * initialization function. For example, for the decoder, - * FLAC__stream_decoder_init() has been replaced by - * FLAC__stream_decoder_init_stream(). This init function takes - * callbacks for the I/O, and the seeking callbacks are optional. This - * allows the client to use the same object for seekable and - * non-seekable streams. For decoding a FLAC file directly, the client - * can use FLAC__stream_decoder_init_file() and pass just a filename - * and fewer callbacks; most of the other callbacks are supplied - * internally. For situations where fopen()ing by filename is not - * possible (e.g. Unicode filenames on Windows) the client can instead - * open the file itself and supply the FILE* to - * FLAC__stream_decoder_init_FILE(). The init functions now returns a - * FLAC__StreamDecoderInitStatus instead of FLAC__StreamDecoderState. - * Since the callbacks and client data are now passed to the init - * function, the FLAC__stream_decoder_set_*_callback() functions and - * FLAC__stream_decoder_set_client_data() are no longer needed. The - * rest of the calls to the decoder are the same as before. - * - * There are counterpart init functions for Ogg FLAC, e.g. - * FLAC__stream_decoder_init_ogg_stream(). All the rest of the calls - * and callbacks are the same as for native FLAC. - * - * As an example, in FLAC 1.1.2 a seekable stream decoder would have - * been set up like so: - * - * \code - * FLAC__SeekableStreamDecoder *decoder = FLAC__seekable_stream_decoder_new(); - * if(decoder == NULL) do_something; - * FLAC__seekable_stream_decoder_set_md5_checking(decoder, true); - * [... other settings ...] - * FLAC__seekable_stream_decoder_set_read_callback(decoder, my_read_callback); - * FLAC__seekable_stream_decoder_set_seek_callback(decoder, my_seek_callback); - * FLAC__seekable_stream_decoder_set_tell_callback(decoder, my_tell_callback); - * FLAC__seekable_stream_decoder_set_length_callback(decoder, my_length_callback); - * FLAC__seekable_stream_decoder_set_eof_callback(decoder, my_eof_callback); - * FLAC__seekable_stream_decoder_set_write_callback(decoder, my_write_callback); - * FLAC__seekable_stream_decoder_set_metadata_callback(decoder, my_metadata_callback); - * FLAC__seekable_stream_decoder_set_error_callback(decoder, my_error_callback); - * FLAC__seekable_stream_decoder_set_client_data(decoder, my_client_data); - * if(FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) do_something; - * \endcode - * - * In FLAC 1.1.3 it is like this: - * - * \code - * FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new(); - * if(decoder == NULL) do_something; - * FLAC__stream_decoder_set_md5_checking(decoder, true); - * [... other settings ...] - * if(FLAC__stream_decoder_init_stream( - * decoder, - * my_read_callback, - * my_seek_callback, // or NULL - * my_tell_callback, // or NULL - * my_length_callback, // or NULL - * my_eof_callback, // or NULL - * my_write_callback, - * my_metadata_callback, // or NULL - * my_error_callback, - * my_client_data - * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something; - * \endcode - * - * or you could do; - * - * \code - * [...] - * FILE *file = fopen("somefile.flac","rb"); - * if(file == NULL) do_somthing; - * if(FLAC__stream_decoder_init_FILE( - * decoder, - * file, - * my_write_callback, - * my_metadata_callback, // or NULL - * my_error_callback, - * my_client_data - * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something; - * \endcode - * - * or just: - * - * \code - * [...] - * if(FLAC__stream_decoder_init_file( - * decoder, - * "somefile.flac", - * my_write_callback, - * my_metadata_callback, // or NULL - * my_error_callback, - * my_client_data - * ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something; - * \endcode - * - * Another small change to the decoder is in how it handles unparseable - * streams. Before, when the decoder found an unparseable stream - * (reserved for when the decoder encounters a stream from a future - * encoder that it can't parse), it changed the state to - * \c FLAC__STREAM_DECODER_UNPARSEABLE_STREAM. Now the decoder instead - * drops sync and calls the error callback with a new error code - * \c FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM. This is - * more robust. If your error callback does not discriminate on the the - * error state, your code does not need to be changed. - * - * The encoder now has a new setting: - * FLAC__stream_encoder_set_apodization(). This is for setting the - * method used to window the data before LPC analysis. You only need to - * add a call to this function if the default is not suitable. There - * are also two new convenience functions that may be useful: - * FLAC__metadata_object_cuesheet_calculate_cddb_id() and - * FLAC__metadata_get_cuesheet(). - * - * The \a bytes parameter to FLAC__StreamDecoderReadCallback, - * FLAC__StreamEncoderReadCallback, and FLAC__StreamEncoderWriteCallback - * is now \c size_t instead of \c unsigned. - */ - -/** \defgroup porting_1_1_3_to_1_1_4 Porting from FLAC 1.1.3 to 1.1.4 - * \ingroup porting - * - * \brief - * This module describes porting from FLAC 1.1.3 to FLAC 1.1.4. - * - * There were no changes to any of the interfaces from 1.1.3 to 1.1.4. - * There was a slight change in the implementation of - * FLAC__stream_encoder_set_metadata(); the function now makes a copy - * of the \a metadata array of pointers so the client no longer needs - * to maintain it after the call. The objects themselves that are - * pointed to by the array are still not copied though and must be - * maintained until the call to FLAC__stream_encoder_finish(). - */ - -/** \defgroup porting_1_1_4_to_1_2_0 Porting from FLAC 1.1.4 to 1.2.0 - * \ingroup porting - * - * \brief - * This module describes porting from FLAC 1.1.4 to FLAC 1.2.0. - * - * There were only very minor changes to the interfaces from 1.1.4 to 1.2.0. - * In libFLAC, \c FLAC__format_sample_rate_is_subset() was added. - * In libFLAC++, \c FLAC::Decoder::Stream::get_decode_position() was added. - * - * Finally, value of the constant \c FLAC__FRAME_HEADER_RESERVED_LEN - * has changed to reflect the conversion of one of the reserved bits - * into active use. It used to be \c 2 and now is \c 1. However the - * FLAC frame header length has not changed, so to skip the proper - * number of bits, use \c FLAC__FRAME_HEADER_RESERVED_LEN + - * \c FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN - */ - -/** \defgroup flac FLAC C API - * - * The FLAC C API is the interface to libFLAC, a set of structures - * describing the components of FLAC streams, and functions for - * encoding and decoding streams, as well as manipulating FLAC - * metadata in files. - * - * You should start with the format components as all other modules - * are dependent on it. - */ - #endif /********* End of inlined file: all.h *********/ @@ -109850,28 +101361,6 @@ unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v); #endif /********* End of inlined file: bitmath.h *********/ -/* An example of what FLAC__bitmath_ilog2() computes: - * - * ilog2( 0) = assertion failure - * ilog2( 1) = 0 - * ilog2( 2) = 1 - * ilog2( 3) = 1 - * ilog2( 4) = 2 - * ilog2( 5) = 2 - * ilog2( 6) = 2 - * ilog2( 7) = 2 - * ilog2( 8) = 3 - * ilog2( 9) = 3 - * ilog2(10) = 3 - * ilog2(11) = 3 - * ilog2(12) = 3 - * ilog2(13) = 3 - * ilog2(14) = 3 - * ilog2(15) = 3 - * ilog2(16) = 4 - * ilog2(17) = 4 - * ilog2(18) = 4 - */ unsigned FLAC__bitmath_ilog2(FLAC__uint32 v) { unsigned l = 0; @@ -109890,30 +101379,6 @@ unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v) return l; } -/* An example of what FLAC__bitmath_silog2() computes: - * - * silog2(-10) = 5 - * silog2(- 9) = 5 - * silog2(- 8) = 4 - * silog2(- 7) = 4 - * silog2(- 6) = 4 - * silog2(- 5) = 4 - * silog2(- 4) = 3 - * silog2(- 3) = 3 - * silog2(- 2) = 2 - * silog2(- 1) = 2 - * silog2( 0) = 0 - * silog2( 1) = 2 - * silog2( 2) = 3 - * silog2( 3) = 3 - * silog2( 4) = 4 - * silog2( 5) = 4 - * silog2( 6) = 4 - * silog2( 7) = 4 - * silog2( 8) = 5 - * silog2( 9) = 5 - * silog2( 10) = 5 - */ unsigned FLAC__bitmath_silog2(int v) { while(1) { @@ -110057,7 +101522,7 @@ void FLAC__cpu_info(FLAC__CPUInfo *info); #ifdef FLAC__CPU_IA32 #ifdef FLAC__HAS_NASM FLAC__uint32 FLAC__cpu_have_cpuid_asm_ia32(void); -void FLAC__cpu_info_asm_ia32(FLAC__uint32 *flags_edx, FLAC__uint32 *flags_ecx); +void FLAC__cpu_info_asm_ia32(FLAC__uint32 *flags_edx, FLAC__uint32 *flags_ecx); FLAC__uint32 FLAC__cpu_info_extended_amd_asm_ia32(void); #endif #endif @@ -110066,17 +101531,11 @@ FLAC__uint32 FLAC__cpu_info_extended_amd_asm_ia32(void); #endif /********* End of inlined file: cpu.h *********/ -/* - * opaque structure definition - */ struct FLAC__BitReader; typedef struct FLAC__BitReader FLAC__BitReader; typedef FLAC__bool (*FLAC__BitReaderReadCallback)(FLAC__byte buffer[], size_t *bytes, void *client_data); -/* - * construction, deletion, initialization, etc functions - */ FLAC__BitReader *FLAC__bitreader_new(void); void FLAC__bitreader_delete(FLAC__BitReader *br); FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__CPUInfo cpu, FLAC__BitReaderReadCallback rcb, void *cd); @@ -110084,23 +101543,13 @@ void FLAC__bitreader_free(FLAC__BitReader *br); /* does not 'free(br)' */ FLAC__bool FLAC__bitreader_clear(FLAC__BitReader *br); void FLAC__bitreader_dump(const FLAC__BitReader *br, FILE *out); -/* - * CRC functions - */ void FLAC__bitreader_reset_read_crc16(FLAC__BitReader *br, FLAC__uint16 seed); FLAC__uint16 FLAC__bitreader_get_read_crc16(FLAC__BitReader *br); -/* - * info functions - */ FLAC__bool FLAC__bitreader_is_consumed_byte_aligned(const FLAC__BitReader *br); unsigned FLAC__bitreader_bits_left_for_byte_alignment(const FLAC__BitReader *br); unsigned FLAC__bitreader_get_input_bits_unconsumed(const FLAC__BitReader *br); -/* - * read functions - */ - FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *val, unsigned bits); FLAC__bool FLAC__bitreader_read_raw_int32(FLAC__BitReader *br, FLAC__int32 *val, unsigned bits); FLAC__bool FLAC__bitreader_read_raw_uint64(FLAC__BitReader *br, FLAC__uint64 *val, unsigned bits); @@ -110113,9 +101562,9 @@ FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, unsig FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter); #ifndef FLAC__NO_ASM # ifdef FLAC__CPU_IA32 -# ifdef FLAC__HAS_NASM +# ifdef FLAC__HAS_NASM FLAC__bool FLAC__bitreader_read_rice_signed_block_asm_ia32_bswap(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter); -# endif +# endif # endif #endif #if 0 /* UNUSED */ @@ -110133,24 +101582,15 @@ FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br); #ifndef FLAC__PRIVATE__CRC_H #define FLAC__PRIVATE__CRC_H -/* 8 bit CRC generator, MSB shifted first -** polynomial = x^8 + x^2 + x^1 + x^0 -** init = 0 -*/ extern FLAC__byte const FLAC__crc8_table[256]; #define FLAC__CRC8_UPDATE(data, crc) (crc) = FLAC__crc8_table[(crc) ^ (data)]; void FLAC__crc8_update(const FLAC__byte data, FLAC__uint8 *crc); void FLAC__crc8_update_block(const FLAC__byte *data, unsigned len, FLAC__uint8 *crc); FLAC__uint8 FLAC__crc8(const FLAC__byte *data, unsigned len); -/* 16 bit CRC generator, MSB shifted first -** polynomial = x^16 + x^15 + x^2 + x^0 -** init = 0 -*/ extern unsigned FLAC__crc16_table[256]; #define FLAC__CRC16_UPDATE(data, crc) (((((crc)<<8) & 0xffff) ^ FLAC__crc16_table[((crc)>>8) ^ (data)])) -/* this alternate may be faster on some systems/compilers */ #if 0 #define FLAC__CRC16_UPDATE(data, crc) ((((crc)<<8) ^ FLAC__crc16_table[((crc)>>8) ^ (data)]) & 0xffff) #endif @@ -110160,15 +101600,10 @@ unsigned FLAC__crc16(const FLAC__byte *data, unsigned len); #endif /********* End of inlined file: crc.h *********/ -/* Things should be fastest when this matches the machine word size */ -/* WATCHOUT: if you change this you must also change the following #defines down to COUNT_ZERO_MSBS below to match */ -/* WATCHOUT: there are a few places where the code will not work unless brword is >= 32 bits wide */ -/* also, some sections currently only have fast versions for 4 or 8 bytes per word */ typedef FLAC__uint32 brword; #define FLAC__BYTES_PER_WORD 4 #define FLAC__BITS_PER_WORD 32 #define FLAC__WORD_ALL_ONES ((FLAC__uint32)0xffffffff) -/* SWAP_BE_WORD_TO_HOST swaps bytes in a brword (which is always big-endian) if necessary to match host byte order */ #if WORDS_BIGENDIAN #define SWAP_BE_WORD_TO_HOST(x) (x) #else @@ -110178,29 +101613,13 @@ typedef FLAC__uint32 brword; #define SWAP_BE_WORD_TO_HOST(x) ntohl(x) #endif #endif -/* counts the # of zero MSBs in a word */ #define COUNT_ZERO_MSBS(word) ( \ (word) <= 0xffff ? \ ( (word) <= 0xff? byte_to_unary_table[word] + 24 : byte_to_unary_table[(word) >> 8] + 16 ) : \ ( (word) <= 0xffffff? byte_to_unary_table[word >> 16] + 8 : byte_to_unary_table[(word) >> 24] ) \ ) -/* this alternate might be slightly faster on some systems/compilers: */ #define COUNT_ZERO_MSBS2(word) ( (word) <= 0xff ? byte_to_unary_table[word] + 24 : ((word) <= 0xffff ? byte_to_unary_table[(word) >> 8] + 16 : ((word) <= 0xffffff ? byte_to_unary_table[(word) >> 16] + 8 : byte_to_unary_table[(word) >> 24])) ) -/* - * This should be at least twice as large as the largest number of words - * required to represent any 'number' (in any encoding) you are going to - * read. With FLAC this is on the order of maybe a few hundred bits. - * If the buffer is smaller than that, the decoder won't be able to read - * in a whole number that is in a variable length encoding (e.g. Rice). - * But to be practical it should be at least 1K bytes. - * - * Increase this number to decrease the number of read callbacks, at the - * expense of using more memory. Or decrease for the reverse effect, - * keeping in mind the limit from the first paragraph. The optimal size - * also depends on the CPU cache size and other factors; some twiddling - * may be necessary to squeeze out the best performance. - */ static const unsigned FLAC__BITREADER_DEFAULT_CAPACITY = 65536u / FLAC__BITS_PER_WORD; /* in words */ static const unsigned char byte_to_unary_table[] = { @@ -110231,7 +101650,6 @@ static const unsigned char byte_to_unary_table[] = { #endif #define max(x,y) ((x)>(y)?(x):(y)) -/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ #ifdef _MSC_VER #define FLAC__U64L(x) x #else @@ -110242,10 +101660,7 @@ static const unsigned char byte_to_unary_table[] = { #define FLaC__INLINE #endif -/* WATCHOUT: assembly routines rely on the order in which these fields are declared */ struct FLAC__BitReader { - /* any partially-consumed word at the head will stay right-justified as bits are consumed from the left */ - /* any incomplete word at the tail will be left-justified, and bytes from the read callback are added on the right */ brword *buffer; unsigned capacity; /* in words */ unsigned words; /* # of completed words in buffer */ @@ -110288,14 +101703,12 @@ static FLaC__INLINE void crc16_update_word_(FLAC__BitReader *br, brword word) br->crc16_align = 0; } -/* would be static except it needs to be called by asm routines */ FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) { unsigned start, end; size_t bytes; FLAC__byte *target; - /* first shift the unconsumed buffer data toward the front as much as possible */ if(br->consumed_words > 0) { start = br->consumed_words; end = br->words + (br->bytes? 1:0); @@ -110305,45 +101718,20 @@ FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) br->consumed_words = 0; } - /* - * set the target for reading, taking into account word alignment and endianness - */ bytes = (br->capacity - br->words) * FLAC__BYTES_PER_WORD - br->bytes; if(bytes == 0) return false; /* no space left, buffer is too small; see note for FLAC__BITREADER_DEFAULT_CAPACITY */ target = ((FLAC__byte*)(br->buffer+br->words)) + br->bytes; - /* before reading, if the existing reader looks like this (say brword is 32 bits wide) - * bitstream : 11 22 33 44 55 br->words=1 br->bytes=1 (partial tail word is left-justified) - * buffer[BE]: 11 22 33 44 55 ?? ?? ?? (shown layed out as bytes sequentially in memory) - * buffer[LE]: 44 33 22 11 ?? ?? ?? 55 (?? being don't-care) - * ^^-------target, bytes=3 - * on LE machines, have to byteswap the odd tail word so nothing is - * overwritten: - */ #if WORDS_BIGENDIAN #else if(br->bytes) br->buffer[br->words] = SWAP_BE_WORD_TO_HOST(br->buffer[br->words]); #endif - /* now it looks like: - * bitstream : 11 22 33 44 55 br->words=1 br->bytes=1 - * buffer[BE]: 11 22 33 44 55 ?? ?? ?? - * buffer[LE]: 44 33 22 11 55 ?? ?? ?? - * ^^-------target, bytes=3 - */ - - /* read in the data; note that the callback may return a smaller number of bytes */ if(!br->read_callback(target, &bytes, br->client_data)) return false; - /* after reading bytes 66 77 88 99 AA BB CC DD EE FF from the client: - * bitstream : 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF - * buffer[BE]: 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF ?? - * buffer[LE]: 44 33 22 11 55 66 77 88 99 AA BB CC DD EE FF ?? - * now have to byteswap on LE machines: - */ #if WORDS_BIGENDIAN #else end = (br->words*FLAC__BYTES_PER_WORD + br->bytes + bytes + (FLAC__BYTES_PER_WORD-1)) / FLAC__BYTES_PER_WORD; @@ -110358,12 +101746,6 @@ FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) br->buffer[start] = SWAP_BE_WORD_TO_HOST(br->buffer[start]); #endif - /* now it looks like: - * bitstream : 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF - * buffer[BE]: 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF ?? - * buffer[LE]: 44 33 22 11 88 77 66 55 CC BB AA 99 ?? FF EE DD - * finally we'll update the reader values: - */ end = br->words*FLAC__BYTES_PER_WORD + br->bytes + bytes; br->words = end / FLAC__BYTES_PER_WORD; br->bytes = end % FLAC__BYTES_PER_WORD; @@ -110371,25 +101753,10 @@ FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) return true; } -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - FLAC__BitReader *FLAC__bitreader_new(void) { FLAC__BitReader *br = (FLAC__BitReader*)calloc(1, sizeof(FLAC__BitReader)); - /* calloc() implies: - memset(br, 0, sizeof(FLAC__BitReader)); - br->buffer = 0; - br->capacity = 0; - br->words = br->bytes = 0; - br->consumed_words = br->consumed_bits = 0; - br->read_callback = 0; - br->client_data = 0; - */ return br; } @@ -110401,12 +101768,6 @@ void FLAC__bitreader_delete(FLAC__BitReader *br) free(br); } -/*********************************************************************** - * - * Public class methods - * - ***********************************************************************/ - FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__CPUInfo cpu, FLAC__BitReaderReadCallback rcb, void *cd) { FLAC__ASSERT(0 != br); @@ -110492,7 +101853,6 @@ FLAC__uint16 FLAC__bitreader_get_read_crc16(FLAC__BitReader *br) FLAC__ASSERT((br->consumed_bits & 7) == 0); FLAC__ASSERT(br->crc16_align <= br->consumed_bits); - /* CRC any tail bytes in a partially-consumed word */ if(br->consumed_bits) { const brword tail = br->buffer[br->consumed_words]; for( ; br->crc16_align < br->consumed_bits; br->crc16_align += 8) @@ -110525,7 +101885,6 @@ FLaC__INLINE FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLA FLAC__ASSERT((br->capacity*FLAC__BITS_PER_WORD) * 2 >= bits); FLAC__ASSERT(br->consumed_words <= br->words); - /* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */ FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32); if(bits == 0) { /* OPT: investigate if this can ever happen, maybe change to assertion */ @@ -110538,9 +101897,7 @@ FLaC__INLINE FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLA return false; } if(br->consumed_words < br->words) { /* if we've not consumed up to a partial tail word... */ - /* OPT: taking out the consumed_bits==0 "else" case below might make things faster if less code allows the compiler to inline this function */ if(br->consumed_bits) { - /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */ const unsigned n = FLAC__BITS_PER_WORD - br->consumed_bits; const brword word = br->buffer[br->consumed_words]; if(bits < n) { @@ -110567,7 +101924,6 @@ FLaC__INLINE FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLA br->consumed_bits = bits; return true; } - /* at this point 'bits' must be == FLAC__BITS_PER_WORD; because of previous assertions, it can't be larger */ *val = word; crc16_update_word_(br, word); br->consumed_words++; @@ -110575,13 +101931,7 @@ FLaC__INLINE FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLA } } else { - /* in this case we're starting our read at a partial tail word; - * the reader has guaranteed that we have at least 'bits' bits - * available to read, which makes this case simpler. - */ - /* OPT: taking out the consumed_bits==0 "else" case below might make things faster if less code allows the compiler to inline this function */ if(br->consumed_bits) { - /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */ FLAC__ASSERT(br->consumed_bits + bits <= br->bytes*8); *val = (br->buffer[br->consumed_words] & (FLAC__WORD_ALL_ONES >> br->consumed_bits)) >> (FLAC__BITS_PER_WORD-br->consumed_bits-bits); br->consumed_bits += bits; @@ -110597,10 +101947,8 @@ FLaC__INLINE FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLA FLAC__bool FLAC__bitreader_read_raw_int32(FLAC__BitReader *br, FLAC__int32 *val, unsigned bits) { - /* OPT: inline raw uint32 code here, or make into a macro if possible in the .h file */ if(!FLAC__bitreader_read_raw_uint32(br, (FLAC__uint32*)val, bits)) return false; - /* sign-extend: */ *val <<= (32-bits); *val >>= (32-bits); return true; @@ -110631,8 +101979,6 @@ FLaC__INLINE FLAC__bool FLAC__bitreader_read_uint32_little_endian(FLAC__BitReade { FLAC__uint32 x8, x32 = 0; - /* this doesn't need to be that fast as currently it is only used for vorbis comments */ - if(!FLAC__bitreader_read_raw_uint32(br, &x32, 8)) return false; @@ -110654,10 +102000,6 @@ FLaC__INLINE FLAC__bool FLAC__bitreader_read_uint32_little_endian(FLAC__BitReade FLAC__bool FLAC__bitreader_skip_bits_no_crc(FLAC__BitReader *br, unsigned bits) { - /* - * OPT: a faster implementation is possible but probably not that useful - * since this is only called a couple of times in the metadata readers. - */ FLAC__ASSERT(0 != br); FLAC__ASSERT(0 != br->buffer); @@ -110695,7 +102037,6 @@ FLAC__bool FLAC__bitreader_skip_byte_block_aligned_no_crc(FLAC__BitReader *br, u FLAC__ASSERT(0 != br->buffer); FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(br)); - /* step 1: skip over partial head word to get word aligned */ while(nvals && br->consumed_bits) { /* i.e. run until we read 'nvals' bytes or we hit the end of the head word */ if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) return false; @@ -110703,7 +102044,6 @@ FLAC__bool FLAC__bitreader_skip_byte_block_aligned_no_crc(FLAC__BitReader *br, u } if(0 == nvals) return true; - /* step 2: skip whole words in chunks */ while(nvals >= FLAC__BYTES_PER_WORD) { if(br->consumed_words < br->words) { br->consumed_words++; @@ -110712,7 +102052,6 @@ FLAC__bool FLAC__bitreader_skip_byte_block_aligned_no_crc(FLAC__BitReader *br, u else if(!bitreader_read_from_client_(br)) return false; } - /* step 3: skip any remainder from partial tail bytes */ while(nvals) { if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) return false; @@ -110730,7 +102069,6 @@ FLAC__bool FLAC__bitreader_read_byte_block_aligned_no_crc(FLAC__BitReader *br, F FLAC__ASSERT(0 != br->buffer); FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(br)); - /* step 1: read from partial head word to get word aligned */ while(nvals && br->consumed_bits) { /* i.e. run until we read 'nvals' bytes or we hit the end of the head word */ if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) return false; @@ -110739,7 +102077,6 @@ FLAC__bool FLAC__bitreader_read_byte_block_aligned_no_crc(FLAC__BitReader *br, F } if(0 == nvals) return true; - /* step 2: read whole words in chunks */ while(nvals >= FLAC__BYTES_PER_WORD) { if(br->consumed_words < br->words) { const brword word = br->buffer[br->consumed_words++]; @@ -110767,7 +102104,6 @@ FLAC__bool FLAC__bitreader_read_byte_block_aligned_no_crc(FLAC__BitReader *br, F else if(!bitreader_read_from_client_(br)) return false; } - /* step 3: read any remainder from partial tail bytes */ while(nvals) { if(!FLAC__bitreader_read_raw_uint32(br, &x, 8)) return false; @@ -110825,16 +102161,8 @@ FLaC__INLINE FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, crc16_update_word_(br, br->buffer[br->consumed_words]); br->consumed_words++; br->consumed_bits = 0; - /* didn't find stop bit yet, have to keep going... */ } } - /* at this point we've eaten up all the whole words; have to try - * reading through any tail bytes before calling the read callback. - * this is a repeat of the above logic adjusted for the fact we - * don't have a whole word. note though if the client is feeding - * us data a byte at a time (unlikely), br->consumed_bits may not - * be zero. - */ if(br->bytes) { const unsigned end = br->bytes * 8; brword b = (br->buffer[br->consumed_words] & (FLAC__WORD_ALL_ONES << (FLAC__BITS_PER_WORD-end))) << br->consumed_bits; @@ -110850,7 +102178,6 @@ FLaC__INLINE FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, *val += end - br->consumed_bits; br->consumed_bits += end; FLAC__ASSERT(br->consumed_bits < FLAC__BITS_PER_WORD); - /* didn't find stop bit yet, have to keep going... */ } } if(!bitreader_read_from_client_(br)) @@ -110868,15 +102195,12 @@ FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, unsig FLAC__ASSERT(0 != br->buffer); FLAC__ASSERT(parameter <= 31); - /* read the unary MSBs and end bit */ if(!FLAC__bitreader_read_unary_unsigned(br, (unsigned int*) &msbs)) return false; - /* read the binary LSBs */ if(!FLAC__bitreader_read_raw_uint32(br, &lsbs, parameter)) return false; - /* compose the value */ uval = (msbs << parameter) | lsbs; if(uval & 1) *val = -((int)(uval >> 1)) - 1; @@ -110886,28 +102210,20 @@ FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, unsig return true; } -/* this is by far the most heavily used reader call. it ain't pretty but it's fast */ -/* a lot of the logic is copied, then adapted, from FLAC__bitreader_read_unary_unsigned() and FLAC__bitreader_read_raw_uint32() */ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter) -/* OPT: possibly faster version for use with MSVC */ #ifdef _MSC_VER { unsigned i; unsigned uval = 0; unsigned bits; /* the # of binary LSBs left to read to finish a rice codeword */ - /* try and get br->consumed_words and br->consumed_bits into register; - * must remember to flush them back to *br before calling other - * bitwriter functions that use them, and before returning */ register unsigned cwords; register unsigned cbits; FLAC__ASSERT(0 != br); FLAC__ASSERT(0 != br->buffer); - /* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */ FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32); FLAC__ASSERT(parameter < 32); - /* the above two asserts also guarantee that the binary part never straddles more that 2 words, so we don't have to loop to read it */ if(nvals == 0) return true; @@ -110917,7 +102233,6 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[ while(1) { - /* read unary part */ while(1) { while(cwords < br->words) { /* if we've not consumed up to a partial tail word... */ brword b = br->buffer[cwords] << cbits; @@ -110948,16 +102263,8 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[ crc16_update_word_(br, br->buffer[cwords]); cwords++; cbits = 0; - /* didn't find stop bit yet, have to keep going... */ } } - /* at this point we've eaten up all the whole words; have to try - * reading through any tail bytes before calling the read callback. - * this is a repeat of the above logic adjusted for the fact we - * don't have a whole word. note though if the client is feeding - * us data a byte at a time (unlikely), br->consumed_bits may not - * be zero. - */ if(br->bytes) { const unsigned end = br->bytes * 8; brword b = (br->buffer[cwords] & (FLAC__WORD_ALL_ONES << (FLAC__BITS_PER_WORD-end))) << cbits; @@ -110974,13 +102281,8 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[ uval += end - cbits; cbits += end; FLAC__ASSERT(cbits < FLAC__BITS_PER_WORD); - /* didn't find stop bit yet, have to keep going... */ } } - /* flush registers and read; bitreader_read_from_client_() does - * not touch br->consumed_bits at all but we still need to set - * it in case it fails and we have to return false. - */ br->consumed_bits = cbits; br->consumed_words = cwords; if(!bitreader_read_from_client_(br)) @@ -110988,15 +102290,10 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[ cwords = br->consumed_words; } break1: - /* read binary part */ FLAC__ASSERT(cwords <= br->words); if(bits) { while((br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits < bits) { - /* flush registers and read; bitreader_read_from_client_() does - * not touch br->consumed_bits at all but we still need to set - * it in case it fails and we have to return false. - */ br->consumed_bits = cbits; br->consumed_words = cwords; if(!bitreader_read_from_client_(br)) @@ -111005,7 +102302,6 @@ break1: } if(cwords < br->words) { /* if we've not consumed up to a partial tail word... */ if(cbits) { - /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */ const unsigned n = FLAC__BITS_PER_WORD - cbits; const brword word = br->buffer[cwords]; if(bits < n) { @@ -111036,13 +102332,8 @@ break1: } } else { - /* in this case we're starting our read at a partial tail word; - * the reader has guaranteed that we have at least 'bits' bits - * available to read, which makes this case simpler. - */ uval <<= bits; if(cbits) { - /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */ FLAC__ASSERT(cbits + bits <= br->bytes*8); uval |= (br->buffer[cwords] & (FLAC__WORD_ALL_ONES >> cbits)) >> (FLAC__BITS_PER_WORD-cbits-bits); cbits += bits; @@ -111056,10 +102347,8 @@ break1: } } break2: - /* compose the value */ *vals = (int)(uval >> 1 ^ -(int)(uval & 1)); - /* are we done? */ --nvals; if(nvals == 0) { br->consumed_bits = cbits; @@ -111077,19 +102366,14 @@ break2: unsigned i; unsigned uval = 0; - /* try and get br->consumed_words and br->consumed_bits into register; - * must remember to flush them back to *br before calling other - * bitwriter functions that use them, and before returning */ register unsigned cwords; register unsigned cbits; unsigned ucbits; /* keep track of the number of unconsumed bits in the buffer */ FLAC__ASSERT(0 != br); FLAC__ASSERT(0 != br->buffer); - /* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */ FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32); FLAC__ASSERT(parameter < 32); - /* the above two asserts also guarantee that the binary part never straddles more than 2 words, so we don't have to loop to read it */ if(nvals == 0) return true; @@ -111100,7 +102384,6 @@ break2: while(1) { - /* read unary part */ while(1) { while(cwords < br->words) { /* if we've not consumed up to a partial tail word... */ brword b = br->buffer[cwords] << cbits; @@ -111131,16 +102414,8 @@ break2: crc16_update_word_(br, br->buffer[cwords]); cwords++; cbits = 0; - /* didn't find stop bit yet, have to keep going... */ } } - /* at this point we've eaten up all the whole words; have to try - * reading through any tail bytes before calling the read callback. - * this is a repeat of the above logic adjusted for the fact we - * don't have a whole word. note though if the client is feeding - * us data a byte at a time (unlikely), br->consumed_bits may not - * be zero. - */ if(br->bytes) { const unsigned end = br->bytes * 8; brword b = (br->buffer[cwords] & ~(FLAC__WORD_ALL_ONES >> end)) << cbits; @@ -111156,37 +102431,23 @@ break2: uval += end - cbits; cbits += end; FLAC__ASSERT(cbits < FLAC__BITS_PER_WORD); - /* didn't find stop bit yet, have to keep going... */ } } - /* flush registers and read; bitreader_read_from_client_() does - * not touch br->consumed_bits at all but we still need to set - * it in case it fails and we have to return false. - */ br->consumed_bits = cbits; br->consumed_words = cwords; if(!bitreader_read_from_client_(br)) return false; cwords = br->consumed_words; ucbits = (br->words-cwords)*FLAC__BITS_PER_WORD + br->bytes*8 - cbits + uval; - /* + uval to offset our count by the # of unary bits already - * consumed before the read, because we will add these back - * in all at once at break1 - */ } break1: ucbits -= uval; ucbits--; /* account for stop bit */ - /* read binary part */ FLAC__ASSERT(cwords <= br->words); if(parameter) { while(ucbits < parameter) { - /* flush registers and read; bitreader_read_from_client_() does - * not touch br->consumed_bits at all but we still need to set - * it in case it fails and we have to return false. - */ br->consumed_bits = cbits; br->consumed_words = cwords; if(!bitreader_read_from_client_(br)) @@ -111196,7 +102457,6 @@ break1: } if(cwords < br->words) { /* if we've not consumed up to a partial tail word... */ if(cbits) { - /* this also works when consumed_bits==0, it's just slower than necessary for that case */ const unsigned n = FLAC__BITS_PER_WORD - cbits; const brword word = br->buffer[cwords]; if(parameter < n) { @@ -111223,13 +102483,8 @@ break1: } } else { - /* in this case we're starting our read at a partial tail word; - * the reader has guaranteed that we have at least 'parameter' - * bits available to read, which makes this case simpler. - */ uval <<= parameter; if(cbits) { - /* this also works when consumed_bits==0, it's just a little slower than necessary for that case */ FLAC__ASSERT(cbits + parameter <= br->bytes*8); uval |= (br->buffer[cwords] & (FLAC__WORD_ALL_ONES >> cbits)) >> (FLAC__BITS_PER_WORD-cbits-parameter); cbits += parameter; @@ -111243,10 +102498,8 @@ break1: ucbits -= parameter; - /* compose the value */ *vals = (int)(uval >> 1 ^ -(int)(uval & 1)); - /* are we done? */ --nvals; if(nvals == 0) { br->consumed_bits = cbits; @@ -111272,16 +102525,13 @@ FLAC__bool FLAC__bitreader_read_golomb_signed(FLAC__BitReader *br, int *val, uns k = FLAC__bitmath_ilog2(parameter); - /* read the unary MSBs and end bit */ if(!FLAC__bitreader_read_unary_unsigned(br, &msbs)) return false; - /* read the binary LSBs */ if(!FLAC__bitreader_read_raw_uint32(br, &lsbs, k)) return false; if(parameter == 1u<> 1)) - 1; else @@ -111316,16 +102564,13 @@ FLAC__bool FLAC__bitreader_read_golomb_unsigned(FLAC__BitReader *br, unsigned *v k = FLAC__bitmath_ilog2(parameter); - /* read the unary MSBs and end bit */ if(!FLAC__bitreader_read_unary_unsigned(br, &msbs)) return false; - /* read the binary LSBs */ if(!FLAC__bitreader_read_raw_uint32(br, &lsbs, k)) return false; if(parameter == 1u< /* for FILE */ -/* - * opaque structure definition - */ struct FLAC__BitWriter; typedef struct FLAC__BitWriter FLAC__BitWriter; -/* - * construction, deletion, initialization, etc functions - */ FLAC__BitWriter *FLAC__bitwriter_new(void); void FLAC__bitwriter_delete(FLAC__BitWriter *bw); FLAC__bool FLAC__bitwriter_init(FLAC__BitWriter *bw); @@ -111524,33 +102760,15 @@ void FLAC__bitwriter_free(FLAC__BitWriter *bw); /* does not 'free(buffer)' */ void FLAC__bitwriter_clear(FLAC__BitWriter *bw); void FLAC__bitwriter_dump(const FLAC__BitWriter *bw, FILE *out); -/* - * CRC functions - * - * non-const *bw because they have to cal FLAC__bitwriter_get_buffer() - */ FLAC__bool FLAC__bitwriter_get_write_crc16(FLAC__BitWriter *bw, FLAC__uint16 *crc); FLAC__bool FLAC__bitwriter_get_write_crc8(FLAC__BitWriter *bw, FLAC__byte *crc); -/* - * info functions - */ FLAC__bool FLAC__bitwriter_is_byte_aligned(const FLAC__BitWriter *bw); unsigned FLAC__bitwriter_get_input_bits_unconsumed(const FLAC__BitWriter *bw); /* can be called anytime, returns total # of bits unconsumed */ -/* - * direct buffer access - * - * there may be no calls on the bitwriter between get and release. - * the bitwriter continues to own the returned buffer. - * before get, bitwriter MUST be byte aligned: check with FLAC__bitwriter_is_byte_aligned() - */ FLAC__bool FLAC__bitwriter_get_buffer(FLAC__BitWriter *bw, const FLAC__byte **buffer, size_t *bytes); void FLAC__bitwriter_release_buffer(FLAC__BitWriter *bw); -/* - * write functions - */ FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, unsigned bits); FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, unsigned bits); FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, unsigned bits); @@ -111584,10 +102802,6 @@ FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw); # include #endif -/* WATCHOUT: for c++ you may have to #define __STDC_LIMIT_MACROS 1 real early - * before #including this file, otherwise SIZE_MAX might not be defined - */ - #include /* for SIZE_MAX */ #if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__ #include /* for SIZE_MAX in case limits.h didn't get it */ @@ -111609,12 +102823,8 @@ FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw); #define FLaC__INLINE #endif -/* avoid malloc()ing 0 bytes, see: - * https://www.securecoding.cert.org/confluence/display/seccode/MEM04-A.+Do+not+make+assumptions+about+the+result+of+allocating+0+bytes?focusedCommentId=5407003 -*/ static FLaC__INLINE void *safe_malloc_(size_t size) { - /* malloc(0) is undefined; FLAC src convention is to always allocate */ if(!size) size++; return malloc(size); @@ -111627,8 +102837,6 @@ static FLaC__INLINE void *safe_calloc_(size_t nmemb, size_t size) return calloc(nmemb, size); } -/*@@@@ there's probably a better way to prevent overflows when allocating untrusted sums but this works for now */ - static FLaC__INLINE void *safe_malloc_add_2op_(size_t size1, size_t size2) { size2 += size1; @@ -111666,7 +102874,6 @@ static FLaC__INLINE void *safe_malloc_mul_2op_(size_t size1, size_t size2) #if 0 needs support for cases where sizeof(size_t) != 4 { - /* could be faster #ifdef'ing off SIZEOF_SIZE_T */ if(sizeof(size_t) == 4) { if ((double)size1 * (double)size2 < 4294967296.0) return malloc(size1*size2); @@ -111674,7 +102881,6 @@ needs support for cases where sizeof(size_t) != 4 return 0; } #else -/* better? */ { if(!size1 || !size2) return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ @@ -111696,7 +102902,6 @@ static FLaC__INLINE void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_ return malloc(size1*size3); } -/* size1*size2 + size3 */ static FLaC__INLINE void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size3) { if(!size1 || !size2) @@ -111706,7 +102911,6 @@ static FLaC__INLINE void *safe_malloc_mul2add_(size_t size1, size_t size2, size_ return safe_malloc_add_2op_(size1*size2, size3); } -/* size1 * (size2 + size3) */ static FLaC__INLINE void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size3) { if(!size1 || (!size2 && !size3)) @@ -111759,7 +102963,6 @@ static FLaC__INLINE void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t return realloc(ptr, size1*size2); } -/* size1 * (size2 + size3) */ static FLaC__INLINE void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3) { if(!size1 || (!size2 && !size3)) @@ -111773,14 +102976,10 @@ static FLaC__INLINE void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t #endif /********* End of inlined file: alloc.h *********/ -/* Things should be fastest when this matches the machine word size */ -/* WATCHOUT: if you change this you must also change the following #defines down to SWAP_BE_WORD_TO_HOST below to match */ -/* WATCHOUT: there are a few places where the code will not work unless bwword is >= 32 bits wide */ typedef FLAC__uint32 bwword; #define FLAC__BYTES_PER_WORD 4 #define FLAC__BITS_PER_WORD 32 #define FLAC__WORD_ALL_ONES ((FLAC__uint32)0xffffffff) -/* SWAP_BE_WORD_TO_HOST swaps bytes in a bwword (which is always big-endian) if necessary to match host byte order */ #if WORDS_BIGENDIAN #define SWAP_BE_WORD_TO_HOST(x) (x) #else @@ -111791,14 +102990,7 @@ typedef FLAC__uint32 bwword; #endif #endif -/* - * The default capacity here doesn't matter too much. The buffer always grows - * to hold whatever is written to it. Usually the encoder will stop adding at - * a frame or metadata block, then write that out and clear the buffer for the - * next one. - */ static const unsigned FLAC__BITWRITER_DEFAULT_CAPACITY = 32768u / sizeof(bwword); /* size in words */ -/* When growing, increment 4K at a time */ static const unsigned FLAC__BITWRITER_DEFAULT_INCREMENT = 4096u / sizeof(bwword); /* size in words */ #define FLAC__WORDS_TO_BITS(words) ((words) * FLAC__BITS_PER_WORD) @@ -111809,7 +103001,6 @@ static const unsigned FLAC__BITWRITER_DEFAULT_INCREMENT = 4096u / sizeof(bwword) #endif #define min(x,y) ((x)<(y)?(x):(y)) -/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ #ifdef _MSC_VER #define FLAC__U64L(x) x #else @@ -111828,7 +103019,6 @@ struct FLAC__BitWriter { unsigned bits; /* # of used bits in accum */ }; -/* * WATCHOUT: The current implementation only grows the buffer. */ static FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, unsigned bits_to_add) { unsigned new_capacity; @@ -111837,19 +103027,13 @@ static FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, unsigned bits_to_add) FLAC__ASSERT(0 != bw); FLAC__ASSERT(0 != bw->buffer); - /* calculate total words needed to store 'bits_to_add' additional bits */ new_capacity = bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD); - /* it's possible (due to pessimism in the growth estimation that - * leads to this call) that we don't actually need to grow - */ if(bw->capacity >= new_capacity) return true; - /* round up capacity increase to the nearest FLAC__BITWRITER_DEFAULT_INCREMENT */ if((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT) new_capacity += FLAC__BITWRITER_DEFAULT_INCREMENT - ((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT); - /* make sure we got everything right */ FLAC__ASSERT(0 == (new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT); FLAC__ASSERT(new_capacity > bw->capacity); FLAC__ASSERT(new_capacity >= bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD)); @@ -111862,16 +103046,9 @@ static FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, unsigned bits_to_add) return true; } -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ - FLAC__BitWriter *FLAC__bitwriter_new(void) { FLAC__BitWriter *bw = (FLAC__BitWriter*)calloc(1, sizeof(FLAC__BitWriter)); - /* note that calloc() sets all members to 0 for us */ return bw; } @@ -111883,12 +103060,6 @@ void FLAC__bitwriter_delete(FLAC__BitWriter *bw) free(bw); } -/*********************************************************************** - * - * Public class methods - * - ***********************************************************************/ - FLAC__bool FLAC__bitwriter_init(FLAC__BitWriter *bw) { FLAC__ASSERT(0 != bw); @@ -111985,18 +103156,14 @@ unsigned FLAC__bitwriter_get_input_bits_unconsumed(const FLAC__BitWriter *bw) FLAC__bool FLAC__bitwriter_get_buffer(FLAC__BitWriter *bw, const FLAC__byte **buffer, size_t *bytes) { FLAC__ASSERT((bw->bits & 7) == 0); - /* double protection */ if(bw->bits & 7) return false; - /* if we have bits in the accumulator we have to flush those to the buffer first */ if(bw->bits) { FLAC__ASSERT(bw->words <= bw->capacity); if(bw->words == bw->capacity && !bitwriter_grow_(bw, FLAC__BITS_PER_WORD)) return false; - /* append bits as complete word to buffer, but don't change bw->accum or bw->bits */ bw->buffer[bw->words] = SWAP_BE_WORD_TO_HOST(bw->accum << (FLAC__BITS_PER_WORD-bw->bits)); } - /* now we can just return what we have */ *buffer = (FLAC__byte*)bw->buffer; *bytes = (FLAC__BYTES_PER_WORD * bw->words) + (bw->bits >> 3); return true; @@ -112004,9 +103171,6 @@ FLAC__bool FLAC__bitwriter_get_buffer(FLAC__BitWriter *bw, const FLAC__byte **bu void FLAC__bitwriter_release_buffer(FLAC__BitWriter *bw) { - /* nothing to do. in the future, strict checking of a 'writer-is-in- - * get-mode' flag could be added everywhere and then cleared here - */ (void)bw; } @@ -112019,10 +103183,8 @@ FLaC__INLINE FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, unsign if(bits == 0) return true; - /* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+bits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */ if(bw->capacity <= bw->words + bits && !bitwriter_grow_(bw, bits)) return false; - /* first part gets to word alignment */ if(bw->bits) { n = min(FLAC__BITS_PER_WORD - bw->bits, bits); bw->accum <<= n; @@ -112035,12 +103197,10 @@ FLaC__INLINE FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, unsign else return true; } - /* do whole words */ while(bits >= FLAC__BITS_PER_WORD) { bw->buffer[bw->words++] = 0; bits -= FLAC__BITS_PER_WORD; } - /* do any leftovers */ if(bits > 0) { bw->accum = 0; bw->bits = bits; @@ -112052,7 +103212,6 @@ FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FL { register unsigned left; - /* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */ FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32); FLAC__ASSERT(0 != bw); @@ -112062,7 +103221,6 @@ FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FL if(bits == 0) return true; - /* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+bits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */ if(bw->capacity <= bw->words + bits && !bitwriter_grow_(bw, bits)) return false; @@ -112089,7 +103247,6 @@ FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FL FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, unsigned bits) { - /* zero-out unused bits */ if(bits < 32) val &= (~(0xffffffff << bits)); @@ -112098,7 +103255,6 @@ FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLA FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, unsigned bits) { - /* this could be a little faster but it's not used for much */ if(bits > 32) { return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)(val>>32), bits-32) && @@ -112110,7 +103266,6 @@ FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FL FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val) { - /* this doesn't need to be that fast as currently it is only used for vorbis comments */ if(!FLAC__bitwriter_write_raw_uint32(bw, val & 0xff, 8)) return false; @@ -112128,7 +103283,6 @@ FLaC__INLINE FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, co { unsigned i; - /* this could be faster but currently we don't need it to be since it's only used for writing metadata */ for(i = 0; i < nvals; i++) { if(!FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)(vals[i]), 8)) return false; @@ -112153,7 +103307,6 @@ unsigned FLAC__bitwriter_rice_bits(FLAC__int32 val, unsigned parameter) FLAC__ASSERT(parameter < sizeof(unsigned)*8); - /* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */ uval = (val<<1) ^ (val>>31); return 1 + parameter + (uval >> parameter); @@ -112167,7 +103320,6 @@ unsigned FLAC__bitwriter_golomb_bits_signed(int val, unsigned parameter) FLAC__ASSERT(parameter > 0); - /* fold signed to unsigned */ if(val < 0) uval = (unsigned)(((-(++val)) << 1) + 1); else @@ -112232,7 +103384,6 @@ FLAC__bool FLAC__bitwriter_write_rice_signed(FLAC__BitWriter *bw, FLAC__int32 va FLAC__ASSERT(0 != bw->buffer); FLAC__ASSERT(parameter < 8*sizeof(uval)); - /* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */ uval = (val<<1) ^ (val>>31); msbs = uval >> parameter; @@ -112261,29 +103412,24 @@ FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FL FLAC__ASSERT(0 != bw); FLAC__ASSERT(0 != bw->buffer); FLAC__ASSERT(parameter < 8*sizeof(bwword)-1); - /* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */ FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32); while(nvals) { - /* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */ uval = (*vals<<1) ^ (*vals>>31); msbits = uval >> parameter; #if 0 /* OPT: can remove this special case if it doesn't make up for the extra compare (doesn't make a statistically significant difference with msvc or gcc/x86) */ if(bw->bits && bw->bits + msbits + lsbits <= FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current bwword */ - /* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free bwword to work in */ bw->bits = bw->bits + msbits + lsbits; uval |= mask1; /* set stop bit */ uval &= mask2; /* mask off unused top bits */ - /* NOT: bw->accum <<= msbits + lsbits because msbits+lsbits could be 32, then the shift would be a NOP */ bw->accum <<= msbits; bw->accum <<= lsbits; bw->accum |= uval; if(bw->bits == FLAC__BITS_PER_WORD) { bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum); bw->bits = 0; - /* burying the capacity check down here means we have to grow the buffer a little if there are more vals to do */ if(bw->capacity <= bw->words && nvals > 1 && !bitwriter_grow_(bw, 1)) { FLAC__ASSERT(bw->capacity == bw->words); return false; @@ -112293,7 +103439,6 @@ FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FL else { #elif 1 /*@@@@@@ OPT: try this version with MSVC6 to see if better, not much difference for gcc-4 */ if(bw->bits && bw->bits + msbits + lsbits < FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current bwword */ - /* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free bwword to work in */ bw->bits = bw->bits + msbits + lsbits; uval |= mask1; /* set stop bit */ uval &= mask2; /* mask off unused top bits */ @@ -112302,13 +103447,10 @@ FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FL } else { #endif - /* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+msbits+lsbits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */ - /* OPT: pessimism may cause flurry of false calls to grow_ which eat up all savings before it */ if(bw->capacity <= bw->words + bw->bits + msbits + 1/*lsbits always fit in 1 bwword*/ && !bitwriter_grow_(bw, msbits+lsbits)) return false; if(msbits) { - /* first part gets to word alignment */ if(bw->bits) { left = FLAC__BITS_PER_WORD - bw->bits; if(msbits < left) { @@ -112323,12 +103465,10 @@ FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FL bw->bits = 0; } } - /* do whole words */ while(msbits >= FLAC__BITS_PER_WORD) { bw->buffer[bw->words++] = 0; msbits -= FLAC__BITS_PER_WORD; } - /* do any leftovers */ if(msbits > 0) { bw->accum = 0; bw->bits = msbits; @@ -112345,10 +103485,6 @@ break1: bw->bits += lsbits; } else { - /* if bw->bits == 0, left==FLAC__BITS_PER_WORD which will always - * be > lsbits (because of previous assertions) so it would have - * triggered the (lsbitsbits); FLAC__ASSERT(left < FLAC__BITS_PER_WORD); bw->accum <<= left; @@ -112375,7 +103511,6 @@ FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, uns FLAC__ASSERT(0 != bw->buffer); FLAC__ASSERT(parameter > 0); - /* fold signed to unsigned */ if(val < 0) uval = (unsigned)(((-(++val)) << 1) + 1); else @@ -112397,10 +103532,8 @@ FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, uns return false; } else { - /* write the unary MSBs */ if(!FLAC__bitwriter_write_zeroes(bw, msbs)) return false; - /* write the unary end bit and binary LSBs */ if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, k+1)) return false; } @@ -112411,13 +103544,10 @@ FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, uns d = (1 << (k+1)) - parameter; q = uval / parameter; r = uval - (q * parameter); - /* write the unary MSBs */ if(!FLAC__bitwriter_write_zeroes(bw, q)) return false; - /* write the unary end bit */ if(!FLAC__bitwriter_write_raw_uint32(bw, 1, 1)) return false; - /* write the binary LSBs */ if(r >= d) { if(!FLAC__bitwriter_write_raw_uint32(bw, r+d, k+1)) return false; @@ -112455,10 +103585,8 @@ FLAC__bool FLAC__bitwriter_write_golomb_unsigned(FLAC__BitWriter *bw, unsigned u return false; } else { - /* write the unary MSBs */ if(!FLAC__bitwriter_write_zeroes(bw, msbs)) return false; - /* write the unary end bit and binary LSBs */ if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, k+1)) return false; } @@ -112469,13 +103597,10 @@ FLAC__bool FLAC__bitwriter_write_golomb_unsigned(FLAC__BitWriter *bw, unsigned u d = (1 << (k+1)) - parameter; q = uval / parameter; r = uval - (q * parameter); - /* write the unary MSBs */ if(!FLAC__bitwriter_write_zeroes(bw, q)) return false; - /* write the unary end bit */ if(!FLAC__bitwriter_write_raw_uint32(bw, 1, 1)) return false; - /* write the binary LSBs */ if(r >= d) { if(!FLAC__bitwriter_write_raw_uint32(bw, r+d, k+1)) return false; @@ -112592,7 +103717,6 @@ FLAC__bool FLAC__bitwriter_write_utf8_uint64(FLAC__BitWriter *bw, FLAC__uint64 v FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw) { - /* 0-pad to byte boundary */ if(bw->bits & 7u) return FLAC__bitwriter_write_zeroes(bw, 8 - (bw->bits & 7u)); else @@ -112641,7 +103765,7 @@ FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw) # include # include # ifndef CPU_SUBTYPE_POWERPC_970 -# define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) +# define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) # endif # else /* FLAC__SYS_DARWIN */ @@ -112676,41 +103800,21 @@ static void sigill_handler (int sig) #endif #if defined(__APPLE__) -/* how to get sysctlbyname()? */ #endif -/* these are flags in EDX of CPUID AX=00000001 */ static const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000; static const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000; static const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000; static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000; static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000; -/* these are flags in ECX of CPUID AX=00000001 */ static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE3 = 0x00000001; static const unsigned FLAC__CPUINFO_IA32_CPUID_SSSE3 = 0x00000200; -/* these are flags in EDX of CPUID AX=80000001 */ static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW = 0x80000000; static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW = 0x40000000; static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000; -/* - * Extra stuff needed for detection of OS support for SSE on IA-32 - */ #if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && defined FLAC__HAS_NASM && !defined FLAC__NO_SSE_OS && !defined FLAC__SSE_OS # if defined(__linux__) -/* - * If the OS doesn't support SSE, we will get here with a SIGILL. We - * modify the return address to jump over the offending SSE instruction - * and also the operation following it that indicates the instruction - * executed successfully. In this way we use no global variables and - * stay thread-safe. - * - * 3 + 3 + 6: - * 3 bytes for "xorps xmm0,xmm0" - * 3 bytes for estimate of how long the follwing "inc var" instruction is - * 6 bytes extra in case our estimate is wrong - * 12 bytes puts us in the NOP "landing zone" - */ # undef USE_OBSOLETE_SIGCONTEXT_FLAVOR /* #define this to use the older signal handler method */ # ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR static void sigill_handler_sse_os(int signal, struct sigcontext sc) @@ -112745,9 +103849,6 @@ static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000; void FLAC__cpu_info(FLAC__CPUInfo *info) { -/* - * IA32-specific - */ #ifdef FLAC__CPU_IA32 info->type = FLAC__CPUINFO_TYPE_IA32; #if !defined FLAC__NO_ASM && defined FLAC__HAS_NASM @@ -112765,7 +103866,6 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) info->data.ia32.ext3dnow = false; info->data.ia32.extmmx = false; if(info->data.ia32.cpuid) { - /* http://www.sandpile.org/ia32/cpuid.htm */ FLAC__uint32 flags_edx, flags_ecx; FLAC__cpu_info_asm_ia32(&flags_edx, &flags_ecx); info->data.ia32.cmov = (flags_edx & FLAC__CPUINFO_IA32_CPUID_CMOV )? true : false; @@ -112801,19 +103901,13 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) fprintf(stderr, " 3DNow!-MMX . %c\n", info->data.ia32.extmmx ? 'Y' : 'n'); #endif - /* - * now have to check for OS support of SSE/SSE2 - */ if(info->data.ia32.fxsr || info->data.ia32.sse || info->data.ia32.sse2) { #if defined FLAC__NO_SSE_OS - /* assume user knows better than us; turn it off */ info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; #elif defined FLAC__SSE_OS - /* assume user knows better than us; leave as detected above */ #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__APPLE__) int sse = 0; size_t len; - /* at least one of these must work: */ len = sizeof(sse); sse = sse || (sysctlbyname("hw.instruction_sse", &sse, &len, NULL, 0) == 0 && sse); len = sizeof(sse); sse = sse || (sysctlbyname("hw.optional.sse" , &sse, &len, NULL, 0) == 0 && sse); /* __APPLE__ ? */ if(!sse) @@ -112846,13 +103940,10 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) if(0 == sigaction(SIGILL, &sigill_sse, &sigill_save)) #endif { - /* http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html */ - /* see sigill_handler_sse_os() for an explanation of the following: */ asm volatile ( "xorl %0,%0\n\t" /* for some reason, still need to do this to clear 'sse' var */ "xorps %%xmm0,%%xmm0\n\t" /* will cause SIGILL if unsupported by OS */ "incl %0\n\t" /* SIGILL handler will jump over this */ - /* landing zone */ "nop\n\t" /* SIGILL jump lands here if "inc" is 9 bytes */ "nop\n\t" "nop\n\t" @@ -112876,7 +103967,6 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) _try { __asm { # if _MSC_VER <= 1200 - /* VC6 assembler doesn't know SSE, have to emit bytecode instead */ _emit 0x0F _emit 0x57 _emit 0xC0 @@ -112892,13 +103982,8 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) # else int sse = 0; LPTOP_LEVEL_EXCEPTION_FILTER save = SetUnhandledExceptionFilter(sigill_handler_sse_os); - /* see GCC version above for explanation */ - /* http://msdn2.microsoft.com/en-us/library/4ks26t93.aspx */ - /* http://www.codeproject.com/cpp/gccasm.asp */ - /* http://www.hick.org/~mmiller/msvc_inline_asm.html */ __asm { # if _MSC_VER <= 1200 - /* VC6 assembler doesn't know SSE, have to emit bytecode instead */ _emit 0x0F _emit 0x57 _emit 0xC0 @@ -112921,7 +104006,6 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; # endif #else - /* no way to test, disable to be safe */ info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; #endif #ifdef DEBUG @@ -112934,9 +104018,6 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) info->use_asm = false; #endif -/* - * PPC-specific - */ #elif defined FLAC__CPU_PPC info->type = FLAC__CPUINFO_TYPE_PPC; # if !defined FLAC__NO_ASM @@ -112959,8 +104040,6 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) } # else /* FLAC__USE_ALTIVEC && !FLAC__SYS_DARWIN */ { - /* no Darwin, do it the brute-force way */ - /* @@@@@@ this is not thread-safe; replace with SSE OS method above or remove */ info->data.ppc.altivec = 0; info->data.ppc.ppc64 = 0; @@ -112983,7 +104062,6 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) int x = 0; canjump = 1; - /* PPC64 hardware implements the cntlzd instruction */ asm volatile ("cntlzd %0, %1" : "=r" (x) : "r" (x) ); info->data.ppc.ppc64 = 1; @@ -112999,9 +104077,6 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) info->use_asm = false; # endif -/* - * unknown CPI - */ #else info->type = FLAC__CPUINFO_TYPE_UNKNOWN; info->use_asm = false; @@ -113036,8 +104111,6 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) # include #endif -/* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */ - FLAC__byte const FLAC__crc8_table[256] = { 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, @@ -113073,8 +104146,6 @@ FLAC__byte const FLAC__crc8_table[256] = { 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 }; -/* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */ - unsigned FLAC__crc16_table[256] = { 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, @@ -113188,28 +104259,11 @@ unsigned FLAC__crc16(const FLAC__byte *data, unsigned len) #include #endif -/* - * These typedefs make it easier to ensure that integer versions of - * the library really only contain integer operations. All the code - * in libFLAC should use FLAC__float and FLAC__double in place of - * float and double, and be protected by checks of the macro - * FLAC__INTEGER_ONLY_LIBRARY. - * - * FLAC__real is the basic floating point type used in LPC analysis. - */ #ifndef FLAC__INTEGER_ONLY_LIBRARY typedef double FLAC__double; typedef float FLAC__float; -/* - * WATCHOUT: changing FLAC__real will change the signatures of many - * functions that have assembly language equivalents and break them. - */ typedef float FLAC__real; #else -/* - * The convention for FLAC__fixedpoint is to use the upper 16 bits - * for the integer part and lower 16 bits for the fractional part. - */ typedef FLAC__int32 FLAC__fixedpoint; extern const FLAC__fixedpoint FLAC__FP_ZERO; extern const FLAC__fixedpoint FLAC__FP_ONE_HALF; @@ -113223,23 +104277,6 @@ extern const FLAC__fixedpoint FLAC__FP_E; #define FLAC__fixedpoint_div(x, y) ( (FLAC__fixedpoint) ( ( ((FLAC__int64)(x)<<32) / (FLAC__int64)(y) ) >> 16 ) ) -/* - * FLAC__fixedpoint_log2() - * -------------------------------------------------------------------- - * Returns the base-2 logarithm of the fixed-point number 'x' using an - * algorithm by Knuth for x >= 1.0 - * - * 'fracbits' is the number of fractional bits of 'x'. 'fracbits' must - * be < 32 and evenly divisible by 4 (0 is OK but not very precise). - * - * 'precision' roughly limits the number of iterations that are done; - * use (unsigned)(-1) for maximum precision. - * - * If 'x' is less than one -- that is, x < (1< 30 - * - * IN data[0,data_len-1] - * IN data_len - * OUT residual_bits_per_sample[0,FLAC__MAX_FIXED_ORDER] - */ #ifndef FLAC__INTEGER_ONLY_LIBRARY unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); # ifndef FLAC__NO_ASM @@ -113288,39 +104313,14 @@ unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned d unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); #endif -/* - * FLAC__fixed_compute_residual() - * -------------------------------------------------------------------- - * Compute the residual signal obtained from sutracting the predicted - * signal from the original. - * - * IN data[-order,data_len-1] original signal (NOTE THE INDICES!) - * IN data_len length of original signal - * IN order <= FLAC__MAX_FIXED_ORDER fixed-predictor order - * OUT residual[0,data_len-1] residual signal - */ void FLAC__fixed_compute_residual(const FLAC__int32 data[], unsigned data_len, unsigned order, FLAC__int32 residual[]); -/* - * FLAC__fixed_restore_signal() - * -------------------------------------------------------------------- - * Restore the original signal by summing the residual and the - * predictor. - * - * IN residual[0,data_len-1] residual signal - * IN data_len length of original signal - * IN order <= FLAC__MAX_FIXED_ORDER fixed-predictor order - * *** IMPORTANT: the caller must pass in the historical samples: - * IN data[-order,-1] previously-reconstructed historical samples - * OUT data[0,data_len-1] original signal - */ void FLAC__fixed_restore_signal(const FLAC__int32 residual[], unsigned data_len, unsigned order, FLAC__int32 data[]); #endif /********* End of inlined file: fixed.h *********/ #ifndef M_LN2 -/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ #define M_LN2 0.69314718055994530942 #endif @@ -113335,12 +104335,6 @@ void FLAC__fixed_restore_signal(const FLAC__int32 residual[], unsigned data_len, #define local_abs(x) ((unsigned)((x)<0? -(x) : (x))) #ifdef FLAC__INTEGER_ONLY_LIBRARY -/* rbps stands for residual bits per sample - * - * (ln(2) * err) - * rbps = log (-----------) - * 2 ( n ) - */ static FLAC__fixedpoint local__compute_rbps_integerized(FLAC__uint32 err, FLAC__uint32 n) { FLAC__uint32 rbps; @@ -113354,22 +104348,12 @@ static FLAC__fixedpoint local__compute_rbps_integerized(FLAC__uint32 err, FLAC__ FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE); if(err <= n) return 0; - /* - * The above two things tell us 1) n fits in 16 bits; 2) err/n > 1. - * These allow us later to know we won't lose too much precision in the - * fixed-point division (err< 0); bits = FLAC__bitmath_ilog2(err)+1; if(bits > 16) { @@ -113378,12 +104362,10 @@ static FLAC__fixedpoint local__compute_rbps_integerized(FLAC__uint32 err, FLAC__ } rbps = (FLAC__uint32)err; - /* Multiply by fixed-point version of ln(2), with 16 fractional bits */ rbps *= FLAC__FP_LN2; fracbits += 16; FLAC__ASSERT(fracbits >= 0); - /* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */ { const int f = fracbits & 3; if(f) { @@ -113397,21 +104379,9 @@ static FLAC__fixedpoint local__compute_rbps_integerized(FLAC__uint32 err, FLAC__ if(rbps == 0) return 0; - /* - * The return value must have 16 fractional bits. Since the whole part - * of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits - * must be >= -3, these assertion allows us to be able to shift rbps - * left if necessary to get 16 fracbits without losing any bits of the - * whole part of rbps. - * - * There is a slight chance due to accumulated error that the whole part - * will require 6 bits, so we use 6 in the assertion. Really though as - * long as it fits in 13 bits (32 - (16 - (-3))) we are fine. - */ FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6); FLAC__ASSERT(fracbits >= -3); - /* now shift the decimal point into place */ if(fracbits < 16) return rbps << (16-fracbits); else if(fracbits > 16) @@ -113433,22 +104403,12 @@ static FLAC__fixedpoint local__compute_rbps_wide_integerized(FLAC__uint64 err, F FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE); if(err <= n) return 0; - /* - * The above two things tell us 1) n fits in 16 bits; 2) err/n > 1. - * These allow us later to know we won't lose too much precision in the - * fixed-point division (err< 0); bits = FLAC__bitmath_ilog2_wide(err)+1; if(bits > 16) { @@ -113457,12 +104417,10 @@ static FLAC__fixedpoint local__compute_rbps_wide_integerized(FLAC__uint64 err, F } rbps = (FLAC__uint32)err; - /* Multiply by fixed-point version of ln(2), with 16 fractional bits */ rbps *= FLAC__FP_LN2; fracbits += 16; FLAC__ASSERT(fracbits >= 0); - /* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */ { const int f = fracbits & 3; if(f) { @@ -113476,21 +104434,9 @@ static FLAC__fixedpoint local__compute_rbps_wide_integerized(FLAC__uint64 err, F if(rbps == 0) return 0; - /* - * The return value must have 16 fractional bits. Since the whole part - * of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits - * must be >= -3, these assertion allows us to be able to shift rbps - * left if necessary to get 16 fracbits without losing any bits of the - * whole part of rbps. - * - * There is a slight chance due to accumulated error that the whole part - * will require 6 bits, so we use 6 in the assertion. Really though as - * long as it fits in 13 bits (32 - (16 - (-3))) we are fine. - */ FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6); FLAC__ASSERT(fracbits >= -3); - /* now shift the decimal point into place */ if(fracbits < 16) return rbps << (16-fracbits); else if(fracbits > 16) @@ -113515,7 +104461,7 @@ unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned d unsigned i, order; for(i = 0; i < data_len; i++) { - error = data[i] ; total_error_0 += local_abs(error); save = error; + error = data[i] ; total_error_0 += local_abs(error); save = error; error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error; error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error; error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error; @@ -113533,9 +104479,6 @@ unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned d else order = 4; - /* Estimate the expected number of bits per residual signal sample. */ - /* 'total_error*' is linearly related to the variance of the residual */ - /* signal, so we use it directly to compute E(|x|) */ FLAC__ASSERT(data_len > 0 || total_error_0 == 0); FLAC__ASSERT(data_len > 0 || total_error_1 == 0); FLAC__ASSERT(data_len > 0 || total_error_2 == 0); @@ -113569,15 +104512,11 @@ unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsig FLAC__int32 last_error_2 = last_error_1 - (data[-2] - data[-3]); FLAC__int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]); FLAC__int32 error, save; - /* total_error_* are 64-bits to avoid overflow when encoding - * erratic signals when the bits-per-sample and blocksize are - * large. - */ FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0; unsigned i, order; for(i = 0; i < data_len; i++) { - error = data[i] ; total_error_0 += local_abs(error); save = error; + error = data[i] ; total_error_0 += local_abs(error); save = error; error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error; error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error; error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error; @@ -113595,9 +104534,6 @@ unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsig else order = 4; - /* Estimate the expected number of bits per residual signal sample. */ - /* 'total_error*' is linearly related to the variance of the residual */ - /* signal, so we use it directly to compute E(|x|) */ FLAC__ASSERT(data_len > 0 || total_error_0 == 0); FLAC__ASSERT(data_len > 0 || total_error_1 == 0); FLAC__ASSERT(data_len > 0 || total_error_2 == 0); @@ -113605,7 +104541,6 @@ unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsig FLAC__ASSERT(data_len > 0 || total_error_4 == 0); #ifndef FLAC__INTEGER_ONLY_LIBRARY #if defined _MSC_VER || defined __MINGW32__ - /* with MSVC you have to spoon feed it the casting */ residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); @@ -113744,7 +104679,6 @@ void FLAC__fixed_restore_signal(const FLAC__int32 residual[], unsigned data_len, #ifdef FLAC__INTEGER_ONLY_LIBRARY -/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ #ifdef _MSC_VER #define FLAC__U64L(x) x #else @@ -113757,222 +104691,191 @@ const FLAC__fixedpoint FLAC__FP_ONE = 0x00010000; const FLAC__fixedpoint FLAC__FP_LN2 = 45426; const FLAC__fixedpoint FLAC__FP_E = 178145; -/* Lookup tables for Knuth's logarithm algorithm */ #define LOG2_LOOKUP_PRECISION 16 static const FLAC__uint32 log2_lookup[][LOG2_LOOKUP_PRECISION] = { { - /* - * 0 fraction bits - */ - /* undefined */ 0x00000000, - /* lg(2/1) = */ 0x00000001, - /* lg(4/3) = */ 0x00000000, - /* lg(8/7) = */ 0x00000000, - /* lg(16/15) = */ 0x00000000, - /* lg(32/31) = */ 0x00000000, - /* lg(64/63) = */ 0x00000000, - /* lg(128/127) = */ 0x00000000, - /* lg(256/255) = */ 0x00000000, - /* lg(512/511) = */ 0x00000000, - /* lg(1024/1023) = */ 0x00000000, - /* lg(2048/2047) = */ 0x00000000, - /* lg(4096/4095) = */ 0x00000000, - /* lg(8192/8191) = */ 0x00000000, - /* lg(16384/16383) = */ 0x00000000, - /* lg(32768/32767) = */ 0x00000000 + 0x00000000, + 0x00000001, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 }, { - /* - * 4 fraction bits - */ - /* undefined */ 0x00000000, - /* lg(2/1) = */ 0x00000010, - /* lg(4/3) = */ 0x00000007, - /* lg(8/7) = */ 0x00000003, - /* lg(16/15) = */ 0x00000001, - /* lg(32/31) = */ 0x00000001, - /* lg(64/63) = */ 0x00000000, - /* lg(128/127) = */ 0x00000000, - /* lg(256/255) = */ 0x00000000, - /* lg(512/511) = */ 0x00000000, - /* lg(1024/1023) = */ 0x00000000, - /* lg(2048/2047) = */ 0x00000000, - /* lg(4096/4095) = */ 0x00000000, - /* lg(8192/8191) = */ 0x00000000, - /* lg(16384/16383) = */ 0x00000000, - /* lg(32768/32767) = */ 0x00000000 + 0x00000000, + 0x00000010, + 0x00000007, + 0x00000003, + 0x00000001, + 0x00000001, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 }, { - /* - * 8 fraction bits - */ - /* undefined */ 0x00000000, - /* lg(2/1) = */ 0x00000100, - /* lg(4/3) = */ 0x0000006a, - /* lg(8/7) = */ 0x00000031, - /* lg(16/15) = */ 0x00000018, - /* lg(32/31) = */ 0x0000000c, - /* lg(64/63) = */ 0x00000006, - /* lg(128/127) = */ 0x00000003, - /* lg(256/255) = */ 0x00000001, - /* lg(512/511) = */ 0x00000001, - /* lg(1024/1023) = */ 0x00000000, - /* lg(2048/2047) = */ 0x00000000, - /* lg(4096/4095) = */ 0x00000000, - /* lg(8192/8191) = */ 0x00000000, - /* lg(16384/16383) = */ 0x00000000, - /* lg(32768/32767) = */ 0x00000000 + 0x00000000, + 0x00000100, + 0x0000006a, + 0x00000031, + 0x00000018, + 0x0000000c, + 0x00000006, + 0x00000003, + 0x00000001, + 0x00000001, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 }, { - /* - * 12 fraction bits - */ - /* undefined */ 0x00000000, - /* lg(2/1) = */ 0x00001000, - /* lg(4/3) = */ 0x000006a4, - /* lg(8/7) = */ 0x00000315, - /* lg(16/15) = */ 0x0000017d, - /* lg(32/31) = */ 0x000000bc, - /* lg(64/63) = */ 0x0000005d, - /* lg(128/127) = */ 0x0000002e, - /* lg(256/255) = */ 0x00000017, - /* lg(512/511) = */ 0x0000000c, - /* lg(1024/1023) = */ 0x00000006, - /* lg(2048/2047) = */ 0x00000003, - /* lg(4096/4095) = */ 0x00000001, - /* lg(8192/8191) = */ 0x00000001, - /* lg(16384/16383) = */ 0x00000000, - /* lg(32768/32767) = */ 0x00000000 + 0x00000000, + 0x00001000, + 0x000006a4, + 0x00000315, + 0x0000017d, + 0x000000bc, + 0x0000005d, + 0x0000002e, + 0x00000017, + 0x0000000c, + 0x00000006, + 0x00000003, + 0x00000001, + 0x00000001, + 0x00000000, + 0x00000000 }, { - /* - * 16 fraction bits - */ - /* undefined */ 0x00000000, - /* lg(2/1) = */ 0x00010000, - /* lg(4/3) = */ 0x00006a40, - /* lg(8/7) = */ 0x00003151, - /* lg(16/15) = */ 0x000017d6, - /* lg(32/31) = */ 0x00000bba, - /* lg(64/63) = */ 0x000005d1, - /* lg(128/127) = */ 0x000002e6, - /* lg(256/255) = */ 0x00000172, - /* lg(512/511) = */ 0x000000b9, - /* lg(1024/1023) = */ 0x0000005c, - /* lg(2048/2047) = */ 0x0000002e, - /* lg(4096/4095) = */ 0x00000017, - /* lg(8192/8191) = */ 0x0000000c, - /* lg(16384/16383) = */ 0x00000006, - /* lg(32768/32767) = */ 0x00000003 + 0x00000000, + 0x00010000, + 0x00006a40, + 0x00003151, + 0x000017d6, + 0x00000bba, + 0x000005d1, + 0x000002e6, + 0x00000172, + 0x000000b9, + 0x0000005c, + 0x0000002e, + 0x00000017, + 0x0000000c, + 0x00000006, + 0x00000003 }, { - /* - * 20 fraction bits - */ - /* undefined */ 0x00000000, - /* lg(2/1) = */ 0x00100000, - /* lg(4/3) = */ 0x0006a3fe, - /* lg(8/7) = */ 0x00031513, - /* lg(16/15) = */ 0x00017d60, - /* lg(32/31) = */ 0x0000bb9d, - /* lg(64/63) = */ 0x00005d10, - /* lg(128/127) = */ 0x00002e59, - /* lg(256/255) = */ 0x00001721, - /* lg(512/511) = */ 0x00000b8e, - /* lg(1024/1023) = */ 0x000005c6, - /* lg(2048/2047) = */ 0x000002e3, - /* lg(4096/4095) = */ 0x00000171, - /* lg(8192/8191) = */ 0x000000b9, - /* lg(16384/16383) = */ 0x0000005c, - /* lg(32768/32767) = */ 0x0000002e + 0x00000000, + 0x00100000, + 0x0006a3fe, + 0x00031513, + 0x00017d60, + 0x0000bb9d, + 0x00005d10, + 0x00002e59, + 0x00001721, + 0x00000b8e, + 0x000005c6, + 0x000002e3, + 0x00000171, + 0x000000b9, + 0x0000005c, + 0x0000002e }, { - /* - * 24 fraction bits - */ - /* undefined */ 0x00000000, - /* lg(2/1) = */ 0x01000000, - /* lg(4/3) = */ 0x006a3fe6, - /* lg(8/7) = */ 0x00315130, - /* lg(16/15) = */ 0x0017d605, - /* lg(32/31) = */ 0x000bb9ca, - /* lg(64/63) = */ 0x0005d0fc, - /* lg(128/127) = */ 0x0002e58f, - /* lg(256/255) = */ 0x0001720e, - /* lg(512/511) = */ 0x0000b8d8, - /* lg(1024/1023) = */ 0x00005c61, - /* lg(2048/2047) = */ 0x00002e2d, - /* lg(4096/4095) = */ 0x00001716, - /* lg(8192/8191) = */ 0x00000b8b, - /* lg(16384/16383) = */ 0x000005c5, - /* lg(32768/32767) = */ 0x000002e3 + 0x00000000, + 0x01000000, + 0x006a3fe6, + 0x00315130, + 0x0017d605, + 0x000bb9ca, + 0x0005d0fc, + 0x0002e58f, + 0x0001720e, + 0x0000b8d8, + 0x00005c61, + 0x00002e2d, + 0x00001716, + 0x00000b8b, + 0x000005c5, + 0x000002e3 }, { - /* - * 28 fraction bits - */ - /* undefined */ 0x00000000, - /* lg(2/1) = */ 0x10000000, - /* lg(4/3) = */ 0x06a3fe5c, - /* lg(8/7) = */ 0x03151301, - /* lg(16/15) = */ 0x017d6049, - /* lg(32/31) = */ 0x00bb9ca6, - /* lg(64/63) = */ 0x005d0fba, - /* lg(128/127) = */ 0x002e58f7, - /* lg(256/255) = */ 0x001720da, - /* lg(512/511) = */ 0x000b8d87, - /* lg(1024/1023) = */ 0x0005c60b, - /* lg(2048/2047) = */ 0x0002e2d7, - /* lg(4096/4095) = */ 0x00017160, - /* lg(8192/8191) = */ 0x0000b8ad, - /* lg(16384/16383) = */ 0x00005c56, - /* lg(32768/32767) = */ 0x00002e2b + 0x00000000, + 0x10000000, + 0x06a3fe5c, + 0x03151301, + 0x017d6049, + 0x00bb9ca6, + 0x005d0fba, + 0x002e58f7, + 0x001720da, + 0x000b8d87, + 0x0005c60b, + 0x0002e2d7, + 0x00017160, + 0x0000b8ad, + 0x00005c56, + 0x00002e2b } }; #if 0 static const FLAC__uint64 log2_lookup_wide[] = { { - /* - * 32 fraction bits - */ - /* undefined */ 0x00000000, - /* lg(2/1) = */ FLAC__U64L(0x100000000), - /* lg(4/3) = */ FLAC__U64L(0x6a3fe5c6), - /* lg(8/7) = */ FLAC__U64L(0x31513015), - /* lg(16/15) = */ FLAC__U64L(0x17d60497), - /* lg(32/31) = */ FLAC__U64L(0x0bb9ca65), - /* lg(64/63) = */ FLAC__U64L(0x05d0fba2), - /* lg(128/127) = */ FLAC__U64L(0x02e58f74), - /* lg(256/255) = */ FLAC__U64L(0x01720d9c), - /* lg(512/511) = */ FLAC__U64L(0x00b8d875), - /* lg(1024/1023) = */ FLAC__U64L(0x005c60aa), - /* lg(2048/2047) = */ FLAC__U64L(0x002e2d72), - /* lg(4096/4095) = */ FLAC__U64L(0x00171600), - /* lg(8192/8191) = */ FLAC__U64L(0x000b8ad2), - /* lg(16384/16383) = */ FLAC__U64L(0x0005c55d), - /* lg(32768/32767) = */ FLAC__U64L(0x0002e2ac) + 0x00000000, + FLAC__U64L(0x100000000), + FLAC__U64L(0x6a3fe5c6), + FLAC__U64L(0x31513015), + FLAC__U64L(0x17d60497), + FLAC__U64L(0x0bb9ca65), + FLAC__U64L(0x05d0fba2), + FLAC__U64L(0x02e58f74), + FLAC__U64L(0x01720d9c), + FLAC__U64L(0x00b8d875), + FLAC__U64L(0x005c60aa), + FLAC__U64L(0x002e2d72), + FLAC__U64L(0x00171600), + FLAC__U64L(0x000b8ad2), + FLAC__U64L(0x0005c55d), + FLAC__U64L(0x0002e2ac) }, { - /* - * 48 fraction bits - */ - /* undefined */ 0x00000000, - /* lg(2/1) = */ FLAC__U64L(0x1000000000000), - /* lg(4/3) = */ FLAC__U64L(0x6a3fe5c60429), - /* lg(8/7) = */ FLAC__U64L(0x315130157f7a), - /* lg(16/15) = */ FLAC__U64L(0x17d60496cfbb), - /* lg(32/31) = */ FLAC__U64L(0xbb9ca64ecac), - /* lg(64/63) = */ FLAC__U64L(0x5d0fba187cd), - /* lg(128/127) = */ FLAC__U64L(0x2e58f7441ee), - /* lg(256/255) = */ FLAC__U64L(0x1720d9c06a8), - /* lg(512/511) = */ FLAC__U64L(0xb8d8752173), - /* lg(1024/1023) = */ FLAC__U64L(0x5c60aa252e), - /* lg(2048/2047) = */ FLAC__U64L(0x2e2d71b0d8), - /* lg(4096/4095) = */ FLAC__U64L(0x1716001719), - /* lg(8192/8191) = */ FLAC__U64L(0xb8ad1de1b), - /* lg(16384/16383) = */ FLAC__U64L(0x5c55d640d), - /* lg(32768/32767) = */ FLAC__U64L(0x2e2abcf52) + 0x00000000, + FLAC__U64L(0x1000000000000), + FLAC__U64L(0x6a3fe5c60429), + FLAC__U64L(0x315130157f7a), + FLAC__U64L(0x17d60496cfbb), + FLAC__U64L(0xbb9ca64ecac), + FLAC__U64L(0x5d0fba187cd), + FLAC__U64L(0x2e58f7441ee), + FLAC__U64L(0x1720d9c06a8), + FLAC__U64L(0xb8d8752173), + FLAC__U64L(0x5c60aa252e), + FLAC__U64L(0x2e2d71b0d8), + FLAC__U64L(0x1716001719), + FLAC__U64L(0xb8ad1de1b), + FLAC__U64L(0x5c55d640d), + FLAC__U64L(0x2e2abcf52) } }; #endif @@ -113991,7 +104894,6 @@ FLAC__uint32 FLAC__fixedpoint_log2(FLAC__uint32 x, unsigned fracbits, unsigned p if(precision > LOG2_LOOKUP_PRECISION) precision = LOG2_LOOKUP_PRECISION; - /* Knuth's algorithm for computing logarithms, optimized for base-2 with lookup tables */ { FLAC__uint32 y = 0; FLAC__uint32 z = x >> 1, k = 1; @@ -114053,20 +104955,17 @@ FLAC__uint32 FLAC__fixedpoint_log2(FLAC__uint32 x, unsigned fracbits, unsigned p #endif #define min(a,b) ((a)<(b)?(a):(b)) -/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ #ifdef _MSC_VER #define FLAC__U64L(x) x #else #define FLAC__U64L(x) x##LLU #endif -/* VERSION should come from configure */ FLAC_API const char *FLAC__VERSION_STRING = VERSION ; #if defined _MSC_VER || defined __BORLANDC__ || defined __MINW32__ -/* yet one more hack because of MSVC6: */ FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.2.1 20070917"; #else FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20070917"; @@ -114244,7 +105143,6 @@ FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate) return true; } -/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table) { unsigned i; @@ -114268,10 +105166,8 @@ FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_S return true; } -/* used as the sort predicate for qsort() */ static int seekpoint_compare_(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r) { - /* we don't just 'return l->sample_number - r->sample_number' since the result (FLAC__int64) might overflow an 'int' */ if(l->sample_number == r->sample_number) return 0; else if(l->sample_number < r->sample_number) @@ -114280,7 +105176,6 @@ static int seekpoint_compare_(const FLAC__StreamMetadata_SeekPoint *l, const FLA return 1; } -/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table) { unsigned i, j; @@ -114288,10 +105183,8 @@ FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *se FLAC__ASSERT(0 != seek_table); - /* sort the seekpoints */ qsort(seek_table->points, seek_table->num_points, sizeof(FLAC__StreamMetadata_SeekPoint), (int (*)(const void *, const void *))seekpoint_compare_); - /* uniquify the seekpoints */ first = true; for(i = j = 0; i < seek_table->num_points; i++) { if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) { @@ -114313,12 +105206,6 @@ FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *se return j; } -/* - * also disallows non-shortest-form encodings, c.f. - * http://www.unicode.org/versions/corrigendum1.html - * and a more clear explanation at the end of this section: - * http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - */ static FLaC__INLINE unsigned utf8len_(const FLAC__byte *utf8) { FLAC__ASSERT(0 != utf8); @@ -114333,7 +105220,6 @@ static FLaC__INLINE unsigned utf8len_(const FLAC__byte *utf8) else if ((utf8[0] & 0xF0) == 0xE0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80) { if (utf8[0] == 0xE0 && (utf8[1] & 0xE0) == 0x80) /* overlong sequence check */ return 0; - /* illegal surrogates check (U+D800...U+DFFF and U+FFFE...U+FFFF) */ if (utf8[0] == 0xED && (utf8[1] & 0xE0) == 0xA0) /* D800-DFFF */ return 0; if (utf8[0] == 0xEF && utf8[1] == 0xBF && (utf8[2] & 0xFE) == 0xBE) /* FFFE-FFFF */ @@ -114418,7 +105304,6 @@ FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte * return true; } -/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation) { unsigned i, j; @@ -114497,7 +105382,6 @@ FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_Cu return true; } -/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */ FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation) { char *p; @@ -114522,9 +105406,6 @@ FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Pic return true; } -/* - * These routines are private to libFLAC - */ unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order) { return @@ -114638,138 +105519,46 @@ FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_s #ifndef FLAC__INTEGER_ONLY_LIBRARY -/* - * FLAC__lpc_window_data() - * -------------------------------------------------------------------- - * Applies the given window to the data. - * OPT: asm implementation - * - * IN in[0,data_len-1] - * IN window[0,data_len-1] - * OUT out[0,lag-1] - * IN data_len - */ void FLAC__lpc_window_data(const FLAC__int32 in[], const FLAC__real window[], FLAC__real out[], unsigned data_len); -/* - * FLAC__lpc_compute_autocorrelation() - * -------------------------------------------------------------------- - * Compute the autocorrelation for lags between 0 and lag-1. - * Assumes data[] outside of [0,data_len-1] == 0. - * Asserts that lag > 0. - * - * IN data[0,data_len-1] - * IN data_len - * IN 0 < lag <= data_len - * OUT autoc[0,lag-1] - */ void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); #ifndef FLAC__NO_ASM # ifdef FLAC__CPU_IA32 -# ifdef FLAC__HAS_NASM +# ifdef FLAC__HAS_NASM void FLAC__lpc_compute_autocorrelation_asm_ia32(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); void FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); -# endif +# endif # endif #endif -/* - * FLAC__lpc_compute_lp_coefficients() - * -------------------------------------------------------------------- - * Computes LP coefficients for orders 1..max_order. - * Do not call if autoc[0] == 0.0. This means the signal is zero - * and there is no point in calculating a predictor. - * - * IN autoc[0,max_order] autocorrelation values - * IN 0 < max_order <= FLAC__MAX_LPC_ORDER max LP order to compute - * OUT lp_coeff[0,max_order-1][0,max_order-1] LP coefficients for each order - * *** IMPORTANT: - * *** lp_coeff[0,max_order-1][max_order,FLAC__MAX_LPC_ORDER-1] are untouched - * OUT error[0,max_order-1] error for each order (more - * specifically, the variance of - * the error signal times # of - * samples in the signal) - * - * Example: if max_order is 9, the LP coefficients for order 9 will be - * in lp_coeff[8][0,8], the LP coefficients for order 8 will be - * in lp_coeff[7][0,7], etc. - */ void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned *max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], FLAC__double error[]); -/* - * FLAC__lpc_quantize_coefficients() - * -------------------------------------------------------------------- - * Quantizes the LP coefficients. NOTE: precision + bits_per_sample - * must be less than 32 (sizeof(FLAC__int32)*8). - * - * IN lp_coeff[0,order-1] LP coefficients - * IN order LP order - * IN FLAC__MIN_QLP_COEFF_PRECISION < precision - * desired precision (in bits, including sign - * bit) of largest coefficient - * OUT qlp_coeff[0,order-1] quantized coefficients - * OUT shift # of bits to shift right to get approximated - * LP coefficients. NOTE: could be negative. - * RETURN 0 => quantization OK - * 1 => coefficients require too much shifting for *shift to - * fit in the LPC subframe header. 'shift' is unset. - * 2 => coefficients are all zero, which is bad. 'shift' is - * unset. - */ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, unsigned precision, FLAC__int32 qlp_coeff[], int *shift); -/* - * FLAC__lpc_compute_residual_from_qlp_coefficients() - * -------------------------------------------------------------------- - * Compute the residual signal obtained from sutracting the predicted - * signal from the original. - * - * IN data[-order,data_len-1] original signal (NOTE THE INDICES!) - * IN data_len length of original signal - * IN qlp_coeff[0,order-1] quantized LP coefficients - * IN order > 0 LP order - * IN lp_quantization quantization of LP coefficients in bits - * OUT residual[0,data_len-1] residual signal - */ void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); #ifndef FLAC__NO_ASM # ifdef FLAC__CPU_IA32 -# ifdef FLAC__HAS_NASM +# ifdef FLAC__HAS_NASM void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); -# endif +# endif # endif #endif #endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ -/* - * FLAC__lpc_restore_signal() - * -------------------------------------------------------------------- - * Restore the original signal by summing the residual and the - * predictor. - * - * IN residual[0,data_len-1] residual signal - * IN data_len length of original signal - * IN qlp_coeff[0,order-1] quantized LP coefficients - * IN order > 0 LP order - * IN lp_quantization quantization of LP coefficients in bits - * *** IMPORTANT: the caller must pass in the historical samples: - * IN data[-order,-1] previously-reconstructed historical samples - * OUT data[0,data_len-1] original signal - */ void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); #ifndef FLAC__NO_ASM # ifdef FLAC__CPU_IA32 -# ifdef FLAC__HAS_NASM +# ifdef FLAC__HAS_NASM void FLAC__lpc_restore_signal_asm_ia32(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); void FLAC__lpc_restore_signal_asm_ia32_mmx(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); -# endif /* FLAC__HAS_NASM */ +# endif /* FLAC__HAS_NASM */ # elif defined FLAC__CPU_PPC void FLAC__lpc_restore_signal_asm_ppc_altivec_16(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); void FLAC__lpc_restore_signal_asm_ppc_altivec_16_order8(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); @@ -114778,32 +105567,9 @@ void FLAC__lpc_restore_signal_asm_ppc_altivec_16_order8(const FLAC__int32 residu #ifndef FLAC__INTEGER_ONLY_LIBRARY -/* - * FLAC__lpc_compute_expected_bits_per_residual_sample() - * -------------------------------------------------------------------- - * Compute the expected number of bits per residual signal sample - * based on the LP error (which is related to the residual variance). - * - * IN lpc_error >= 0.0 error returned from calculating LP coefficients - * IN total_samples > 0 # of samples in residual signal - * RETURN expected bits per sample - */ FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__double lpc_error, unsigned total_samples); FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(FLAC__double lpc_error, FLAC__double error_scale); -/* - * FLAC__lpc_compute_best_order() - * -------------------------------------------------------------------- - * Compute the best order from the array of signal errors returned - * during coefficient computation. - * - * IN lpc_error[0,max_order-1] >= 0.0 error returned from calculating LP coefficients - * IN max_order > 0 max LP order - * IN total_samples > 0 # of samples in residual signal - * IN overhead_bits_per_order # of bits overhead for each increased LP order - * (includes warmup sample size and quantized LP coefficient) - * RETURN [1,max_order] best order - */ unsigned FLAC__lpc_compute_best_order(const FLAC__double lpc_error[], unsigned max_order, unsigned total_samples, unsigned overhead_bits_per_order); #endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ @@ -114818,11 +105584,9 @@ unsigned FLAC__lpc_compute_best_order(const FLAC__double lpc_error[], unsigned m #ifndef FLAC__INTEGER_ONLY_LIBRARY #ifndef M_LN2 -/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ #define M_LN2 0.69314718055994530942 #endif -/* OPT: #undef'ing this may improve the speed on some architectures */ #define FLAC__LPC_UNROLLED_FILTER_LOOPS void FLAC__lpc_window_data(const FLAC__int32 in[], const FLAC__real window[], FLAC__real out[], unsigned data_len) @@ -114834,7 +105598,6 @@ void FLAC__lpc_window_data(const FLAC__int32 in[], const FLAC__real window[], FL void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]) { - /* a readable, but slower, version */ #if 0 FLAC__real d; unsigned i; @@ -114842,13 +105605,6 @@ void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_le FLAC__ASSERT(lag > 0); FLAC__ASSERT(lag <= data_len); - /* - * Technically we should subtract the mean first like so: - * for(i = 0; i < data_len; i++) - * data[i] -= mean; - * but it appears not to make enough of a difference to matter, and - * most signals are already closely centered around zero - */ while(lag--) { for(i = lag, d = 0.0; i < data_len; i++) d += data[i] * data[i - lag]; @@ -114856,10 +105612,6 @@ void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], unsigned data_le } #endif - /* - * this version tends to run faster because of better data locality - * ('data_len' is usually much larger than 'lag') - */ FLAC__real d; unsigned sample, coeff; const unsigned limit = data_len - lag; @@ -114894,13 +105646,11 @@ void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned *max_o err = autoc[0]; for(i = 0; i < *max_order; i++) { - /* Sum up this iteration's reflection coefficient. */ r = -autoc[i+1]; for(j = 0; j < i; j++) r -= lpc[j] * autoc[i-j]; ref[i] = (r/=err); - /* Update LPC coefficients and total error. */ lpc[i]=r; for(j = 0; j < (i>>1); j++) { FLAC__double tmp = lpc[j]; @@ -114912,12 +105662,10 @@ void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned *max_o err *= (1.0 - r * r); - /* save this order */ for(j = 0; j <= i; j++) lp_coeff[i][j] = (FLAC__real)(-lpc[j]); /* negate FIR filter coeff to get predictor coeff */ error[i] = err; - /* see SF bug #1601812 http://sourceforge.net/tracker/index.php?func=detail&aid=1601812&group_id=13478&atid=113478 */ if(err == 0.0) { *max_order = i+1; return; @@ -114934,13 +105682,11 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, FLAC__ASSERT(precision > 0); FLAC__ASSERT(precision >= FLAC__MIN_QLP_COEFF_PRECISION); - /* drop one bit for the sign; from here on out we consider only |lp_coeff[i]| */ precision--; qmax = 1 << precision; qmin = -qmax; qmax--; - /* calc cmax = max( |lp_coeff[i]| ) */ cmax = 0.0; for(i = 0; i < order; i++) { const FLAC__double d = fabs(lp_coeff[i]); @@ -114949,7 +105695,6 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, } if(cmax <= 0.0) { - /* => coefficients are all 0, which means our constant-detect didn't work */ return 2; } else { @@ -114994,10 +105739,6 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, qlp_coeff[i] = q; } } - /* negative shift is very rare but due to design flaw, negative shift is - * a NOP in the decoder, so it must be handled specially by scaling down - * coeffs - */ else { const int nshift = -(*shift); FLAC__double error = 0.0; @@ -115068,14 +105809,6 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, u *(residual++) = *(data++) - (sum >> lp_quantization); } - /* Here's a slower but clearer version: - for(i = 0; i < data_len; i++) { - sum = 0; - for(j = 0; j < order; j++) - sum += qlp_coeff[j] * data[i-j-1]; - residual[i] = data[i] - (sum >> lp_quantization); - } - */ } #else /* fully unrolled version for normal use */ { @@ -115085,11 +105818,6 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, u FLAC__ASSERT(order > 0); FLAC__ASSERT(order <= 32); - /* - * We do unique versions up to 12th order since that's the subset limit. - * Also they are roughly ordered to match frequency of occurrence to - * minimize branching. - */ if(order <= 12) { if(order > 8) { if(order > 10) { @@ -115281,18 +106009,18 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, u case 15: sum += qlp_coeff[14] * data[i-15]; case 14: sum += qlp_coeff[13] * data[i-14]; case 13: sum += qlp_coeff[12] * data[i-13]; - sum += qlp_coeff[11] * data[i-12]; - sum += qlp_coeff[10] * data[i-11]; - sum += qlp_coeff[ 9] * data[i-10]; - sum += qlp_coeff[ 8] * data[i- 9]; - sum += qlp_coeff[ 7] * data[i- 8]; - sum += qlp_coeff[ 6] * data[i- 7]; - sum += qlp_coeff[ 5] * data[i- 6]; - sum += qlp_coeff[ 4] * data[i- 5]; - sum += qlp_coeff[ 3] * data[i- 4]; - sum += qlp_coeff[ 2] * data[i- 3]; - sum += qlp_coeff[ 1] * data[i- 2]; - sum += qlp_coeff[ 0] * data[i- 1]; + sum += qlp_coeff[11] * data[i-12]; + sum += qlp_coeff[10] * data[i-11]; + sum += qlp_coeff[ 9] * data[i-10]; + sum += qlp_coeff[ 8] * data[i- 9]; + sum += qlp_coeff[ 7] * data[i- 8]; + sum += qlp_coeff[ 6] * data[i- 7]; + sum += qlp_coeff[ 5] * data[i- 6]; + sum += qlp_coeff[ 4] * data[i- 5]; + sum += qlp_coeff[ 3] * data[i- 4]; + sum += qlp_coeff[ 2] * data[i- 3]; + sum += qlp_coeff[ 1] * data[i- 2]; + sum += qlp_coeff[ 0] * data[i- 1]; } residual[i] = data[i] - (sum >> lp_quantization); } @@ -115347,11 +106075,6 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *da FLAC__ASSERT(order > 0); FLAC__ASSERT(order <= 32); - /* - * We do unique versions up to 12th order since that's the subset limit. - * Also they are roughly ordered to match frequency of occurrence to - * minimize branching. - */ if(order <= 12) { if(order > 8) { if(order > 10) { @@ -115543,18 +106266,18 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *da case 15: sum += qlp_coeff[14] * (FLAC__int64)data[i-15]; case 14: sum += qlp_coeff[13] * (FLAC__int64)data[i-14]; case 13: sum += qlp_coeff[12] * (FLAC__int64)data[i-13]; - sum += qlp_coeff[11] * (FLAC__int64)data[i-12]; - sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; - sum += qlp_coeff[ 9] * (FLAC__int64)data[i-10]; - sum += qlp_coeff[ 8] * (FLAC__int64)data[i- 9]; - sum += qlp_coeff[ 7] * (FLAC__int64)data[i- 8]; - sum += qlp_coeff[ 6] * (FLAC__int64)data[i- 7]; - sum += qlp_coeff[ 5] * (FLAC__int64)data[i- 6]; - sum += qlp_coeff[ 4] * (FLAC__int64)data[i- 5]; - sum += qlp_coeff[ 3] * (FLAC__int64)data[i- 4]; - sum += qlp_coeff[ 2] * (FLAC__int64)data[i- 3]; - sum += qlp_coeff[ 1] * (FLAC__int64)data[i- 2]; - sum += qlp_coeff[ 0] * (FLAC__int64)data[i- 1]; + sum += qlp_coeff[11] * (FLAC__int64)data[i-12]; + sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; + sum += qlp_coeff[ 9] * (FLAC__int64)data[i-10]; + sum += qlp_coeff[ 8] * (FLAC__int64)data[i- 9]; + sum += qlp_coeff[ 7] * (FLAC__int64)data[i- 8]; + sum += qlp_coeff[ 6] * (FLAC__int64)data[i- 7]; + sum += qlp_coeff[ 5] * (FLAC__int64)data[i- 6]; + sum += qlp_coeff[ 4] * (FLAC__int64)data[i- 5]; + sum += qlp_coeff[ 3] * (FLAC__int64)data[i- 4]; + sum += qlp_coeff[ 2] * (FLAC__int64)data[i- 3]; + sum += qlp_coeff[ 1] * (FLAC__int64)data[i- 2]; + sum += qlp_coeff[ 0] * (FLAC__int64)data[i- 1]; } residual[i] = data[i] - (FLAC__int32)(sum >> lp_quantization); } @@ -115598,14 +106321,6 @@ void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, c *(data++) = *(r++) + (sum >> lp_quantization); } - /* Here's a slower but clearer version: - for(i = 0; i < data_len; i++) { - sum = 0; - for(j = 0; j < order; j++) - sum += qlp_coeff[j] * data[i-j-1]; - data[i] = residual[i] + (sum >> lp_quantization); - } - */ } #else /* fully unrolled version for normal use */ { @@ -115615,11 +106330,6 @@ void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, c FLAC__ASSERT(order > 0); FLAC__ASSERT(order <= 32); - /* - * We do unique versions up to 12th order since that's the subset limit. - * Also they are roughly ordered to match frequency of occurrence to - * minimize branching. - */ if(order <= 12) { if(order > 8) { if(order > 10) { @@ -115811,18 +106521,18 @@ void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, c case 15: sum += qlp_coeff[14] * data[i-15]; case 14: sum += qlp_coeff[13] * data[i-14]; case 13: sum += qlp_coeff[12] * data[i-13]; - sum += qlp_coeff[11] * data[i-12]; - sum += qlp_coeff[10] * data[i-11]; - sum += qlp_coeff[ 9] * data[i-10]; - sum += qlp_coeff[ 8] * data[i- 9]; - sum += qlp_coeff[ 7] * data[i- 8]; - sum += qlp_coeff[ 6] * data[i- 7]; - sum += qlp_coeff[ 5] * data[i- 6]; - sum += qlp_coeff[ 4] * data[i- 5]; - sum += qlp_coeff[ 3] * data[i- 4]; - sum += qlp_coeff[ 2] * data[i- 3]; - sum += qlp_coeff[ 1] * data[i- 2]; - sum += qlp_coeff[ 0] * data[i- 1]; + sum += qlp_coeff[11] * data[i-12]; + sum += qlp_coeff[10] * data[i-11]; + sum += qlp_coeff[ 9] * data[i-10]; + sum += qlp_coeff[ 8] * data[i- 9]; + sum += qlp_coeff[ 7] * data[i- 8]; + sum += qlp_coeff[ 6] * data[i- 7]; + sum += qlp_coeff[ 5] * data[i- 6]; + sum += qlp_coeff[ 4] * data[i- 5]; + sum += qlp_coeff[ 3] * data[i- 4]; + sum += qlp_coeff[ 2] * data[i- 3]; + sum += qlp_coeff[ 1] * data[i- 2]; + sum += qlp_coeff[ 0] * data[i- 1]; } data[i] = residual[i] + (sum >> lp_quantization); } @@ -115877,11 +106587,6 @@ void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_l FLAC__ASSERT(order > 0); FLAC__ASSERT(order <= 32); - /* - * We do unique versions up to 12th order since that's the subset limit. - * Also they are roughly ordered to match frequency of occurrence to - * minimize branching. - */ if(order <= 12) { if(order > 8) { if(order > 10) { @@ -116073,18 +106778,18 @@ void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_l case 15: sum += qlp_coeff[14] * (FLAC__int64)data[i-15]; case 14: sum += qlp_coeff[13] * (FLAC__int64)data[i-14]; case 13: sum += qlp_coeff[12] * (FLAC__int64)data[i-13]; - sum += qlp_coeff[11] * (FLAC__int64)data[i-12]; - sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; - sum += qlp_coeff[ 9] * (FLAC__int64)data[i-10]; - sum += qlp_coeff[ 8] * (FLAC__int64)data[i- 9]; - sum += qlp_coeff[ 7] * (FLAC__int64)data[i- 8]; - sum += qlp_coeff[ 6] * (FLAC__int64)data[i- 7]; - sum += qlp_coeff[ 5] * (FLAC__int64)data[i- 6]; - sum += qlp_coeff[ 4] * (FLAC__int64)data[i- 5]; - sum += qlp_coeff[ 3] * (FLAC__int64)data[i- 4]; - sum += qlp_coeff[ 2] * (FLAC__int64)data[i- 3]; - sum += qlp_coeff[ 1] * (FLAC__int64)data[i- 2]; - sum += qlp_coeff[ 0] * (FLAC__int64)data[i- 1]; + sum += qlp_coeff[11] * (FLAC__int64)data[i-12]; + sum += qlp_coeff[10] * (FLAC__int64)data[i-11]; + sum += qlp_coeff[ 9] * (FLAC__int64)data[i-10]; + sum += qlp_coeff[ 8] * (FLAC__int64)data[i- 9]; + sum += qlp_coeff[ 7] * (FLAC__int64)data[i- 8]; + sum += qlp_coeff[ 6] * (FLAC__int64)data[i- 7]; + sum += qlp_coeff[ 5] * (FLAC__int64)data[i- 6]; + sum += qlp_coeff[ 4] * (FLAC__int64)data[i- 5]; + sum += qlp_coeff[ 3] * (FLAC__int64)data[i- 4]; + sum += qlp_coeff[ 2] * (FLAC__int64)data[i- 3]; + sum += qlp_coeff[ 1] * (FLAC__int64)data[i- 2]; + sum += qlp_coeff[ 0] * (FLAC__int64)data[i- 1]; } data[i] = residual[i] + (FLAC__int32)(sum >> lp_quantization); } @@ -116183,31 +106888,6 @@ unsigned FLAC__lpc_compute_best_order(const FLAC__double lpc_error[], unsigned m #ifndef FLAC__PRIVATE__MD5_H #define FLAC__PRIVATE__MD5_H -/* - * This is the header file for the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - * - * Changed so as no longer to depend on Colin Plumb's `usual.h' - * header definitions; now uses stuff from dpkg's config.h - * - Ian Jackson . - * Still in the public domain. - * - * Josh Coalson: made some changes to integrate with libFLAC. - * Still in the public domain, with no warranty. - */ - typedef struct { FLAC__uint32 in[16]; FLAC__uint32 buf[4]; @@ -116228,48 +106908,14 @@ FLAC__bool FLAC__MD5Accumulate(FLAC__MD5Context *ctx, const FLAC__int32 * const #define FLaC__INLINE #endif -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - * - * Changed so as no longer to depend on Colin Plumb's `usual.h' header - * definitions; now uses stuff from dpkg's config.h. - * - Ian Jackson . - * Still in the public domain. - * - * Josh Coalson: made some changes to integrate with libFLAC. - * Still in the public domain. - */ - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) -/* This is the central step in the MD5 algorithm. */ #define MD5STEP(f,w,x,y,z,in,s) \ (w += f(x,y,z) + in, w = (w<>(32-s)) + x) -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ static void FLAC__MD5Transform(FLAC__uint32 buf[4], FLAC__uint32 const in[16]) { register FLAC__uint32 a, b, c, d; @@ -116390,16 +107036,10 @@ static void byteSwapX16(FLAC__uint32 *buf) #define byteSwapX16(buf) #endif -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ static void FLAC__MD5Update(FLAC__MD5Context *ctx, FLAC__byte const *buf, unsigned len) { FLAC__uint32 t; - /* Update byte count */ - t = ctx->bytes[0]; if ((ctx->bytes[0] = t + len) < t) ctx->bytes[1]++; /* Carry from low to high */ @@ -116409,14 +107049,12 @@ static void FLAC__MD5Update(FLAC__MD5Context *ctx, FLAC__byte const *buf, unsign memcpy((FLAC__byte *)ctx->in + 64 - t, buf, len); return; } - /* First chunk is an odd size */ memcpy((FLAC__byte *)ctx->in + 64 - t, buf, t); byteSwapX16(ctx->in); FLAC__MD5Transform(ctx->buf, ctx->in); buf += t; len -= t; - /* Process data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->in, buf, 64); byteSwapX16(ctx->in); @@ -116425,14 +107063,9 @@ static void FLAC__MD5Update(FLAC__MD5Context *ctx, FLAC__byte const *buf, unsign len -= 64; } - /* Handle any remaining bytes of data. */ memcpy(ctx->in, buf, len); } -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ void FLAC__MD5Init(FLAC__MD5Context *ctx) { ctx->buf[0] = 0x67452301; @@ -116447,19 +107080,13 @@ void FLAC__MD5Init(FLAC__MD5Context *ctx) ctx->capacity = 0; } -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ void FLAC__MD5Final(FLAC__byte digest[16], FLAC__MD5Context *ctx) { int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ FLAC__byte *p = (FLAC__byte *)ctx->in + count; - /* Set the first char of padding to 0x80. There is always room. */ *p++ = 0x80; - /* Bytes of padding needed to make 56 bytes (-8..55) */ count = 56 - 1 - count; if (count < 0) { /* Padding forces an extra block */ @@ -116472,7 +107099,6 @@ void FLAC__MD5Final(FLAC__byte digest[16], FLAC__MD5Context *ctx) memset(p, 0, count); byteSwap(ctx->in, 14); - /* Append length in bits and transform */ ctx->in[14] = ctx->bytes[0] << 3; ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; FLAC__MD5Transform(ctx->buf, ctx->in); @@ -116487,9 +107113,6 @@ void FLAC__MD5Final(FLAC__byte digest[16], FLAC__MD5Context *ctx) } } -/* - * Convert the incoming audio signal to a byte stream - */ static void format_input_(FLAC__byte *buf, const FLAC__int32 * const signal[], unsigned channels, unsigned samples, unsigned bytes_per_sample) { unsigned channel, sample; @@ -116608,14 +107231,10 @@ static void format_input_(FLAC__byte *buf, const FLAC__int32 * const signal[], u } } -/* - * Convert the incoming audio signal to a byte stream and FLAC__MD5Update it. - */ FLAC__bool FLAC__MD5Accumulate(FLAC__MD5Context *ctx, const FLAC__int32 * const signal[], unsigned channels, unsigned samples, unsigned bytes_per_sample) { const size_t bytes_needed = (size_t)channels * (size_t)samples * (size_t)bytes_per_sample; - /* overflow check */ if((size_t)channels > SIZE_MAX / (size_t)bytes_per_sample) return false; if((size_t)channels * (size_t)bytes_per_sample > SIZE_MAX / (size_t)samples) @@ -116677,9 +107296,6 @@ FLAC__bool FLAC__MD5Accumulate(FLAC__MD5Context *ctx, const FLAC__int32 * const #include /* for size_t */ -/* Returns the unaligned address returned by malloc. - * Use free() on this address to deallocate. - */ void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address); FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer); FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer); @@ -116699,11 +107315,9 @@ void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address) FLAC__ASSERT(0 != aligned_address); #ifdef FLAC__ALIGN_MALLOC_DATA - /* align on 32-byte (256-bit) boundary */ x = safe_malloc_add_2op_(bytes, /*+*/31); #ifdef SIZEOF_VOIDP #if SIZEOF_VOIDP == 4 - /* could do *aligned_address = x + ((unsigned) (32 - (((unsigned)x) & 31))) & 31; */ *aligned_address = (void*)(((unsigned)x + 31) & -32); #elif SIZEOF_VOIDP == 8 *aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32))); @@ -116711,7 +107325,6 @@ void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address) # error Unsupported sizeof(void*) #endif #else - /* there's got to be a better way to do this right for all archs */ if(sizeof(void*) == sizeof(unsigned)) *aligned_address = (void*)(((unsigned)x + 31) & -32); else if(sizeof(void*) == sizeof(FLAC__uint64)) @@ -116731,7 +107344,7 @@ FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned elements, FLAC__int32 FLAC__int32 *pu; /* unaligned pointer */ union { /* union needed to comply with C99 pointer aliasing rules */ FLAC__int32 *pa; /* aligned pointer */ - void *pv; /* aligned pointer alias */ + void *pv; /* aligned pointer alias */ } u; FLAC__ASSERT(elements > 0); @@ -116739,9 +107352,6 @@ FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned elements, FLAC__int32 FLAC__ASSERT(0 != aligned_pointer); FLAC__ASSERT(unaligned_pointer != aligned_pointer); - if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ - return false; - pu = (FLAC__int32*)FLAC__memory_alloc_aligned(sizeof(*pu) * (size_t)elements, &u.pv); if(0 == pu) { return false; @@ -116760,7 +107370,7 @@ FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint FLAC__uint32 *pu; /* unaligned pointer */ union { /* union needed to comply with C99 pointer aliasing rules */ FLAC__uint32 *pa; /* aligned pointer */ - void *pv; /* aligned pointer alias */ + void *pv; /* aligned pointer alias */ } u; FLAC__ASSERT(elements > 0); @@ -116768,9 +107378,6 @@ FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint FLAC__ASSERT(0 != aligned_pointer); FLAC__ASSERT(unaligned_pointer != aligned_pointer); - if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ - return false; - pu = (FLAC__uint32*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); if(0 == pu) { return false; @@ -116789,7 +107396,7 @@ FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint FLAC__uint64 *pu; /* unaligned pointer */ union { /* union needed to comply with C99 pointer aliasing rules */ FLAC__uint64 *pa; /* aligned pointer */ - void *pv; /* aligned pointer alias */ + void *pv; /* aligned pointer alias */ } u; FLAC__ASSERT(elements > 0); @@ -116797,9 +107404,6 @@ FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint FLAC__ASSERT(0 != aligned_pointer); FLAC__ASSERT(unaligned_pointer != aligned_pointer); - if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ - return false; - pu = (FLAC__uint64*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); if(0 == pu) { return false; @@ -116818,7 +107422,7 @@ FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(unsigned elements, unsigned unsigned *pu; /* unaligned pointer */ union { /* union needed to comply with C99 pointer aliasing rules */ unsigned *pa; /* aligned pointer */ - void *pv; /* aligned pointer alias */ + void *pv; /* aligned pointer alias */ } u; FLAC__ASSERT(elements > 0); @@ -116826,9 +107430,6 @@ FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(unsigned elements, unsigned FLAC__ASSERT(0 != aligned_pointer); FLAC__ASSERT(unaligned_pointer != aligned_pointer); - if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ - return false; - pu = (unsigned*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); if(0 == pu) { return false; @@ -116849,7 +107450,7 @@ FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real * FLAC__real *pu; /* unaligned pointer */ union { /* union needed to comply with C99 pointer aliasing rules */ FLAC__real *pa; /* aligned pointer */ - void *pv; /* aligned pointer alias */ + void *pv; /* aligned pointer alias */ } u; FLAC__ASSERT(elements > 0); @@ -116857,9 +107458,6 @@ FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real * FLAC__ASSERT(0 != aligned_pointer); FLAC__ASSERT(unaligned_pointer != aligned_pointer); - if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ - return false; - pu = (FLAC__real*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); if(0 == pu) { return false; @@ -116944,9 +107542,6 @@ typedef struct FLAC__StreamDecoderProtected { #endif } FLAC__StreamDecoderProtected; -/* - * return the number of input bytes consumed - */ unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder); #endif @@ -116957,14 +107552,12 @@ unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecod #endif #define max(a,b) ((a)>(b)?(a):(b)) -/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ #ifdef _MSC_VER #define FLAC__U64L(x) x #else #define FLAC__U64L(x) x##LLU #endif -/* technically this should be in an "export.c" but this is convenient enough */ FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC = #if FLAC__HAS_OGG 1 @@ -116973,20 +107566,8 @@ FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC = #endif ; -/*********************************************************************** - * - * Private static data - * - ***********************************************************************/ - static FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; -/*********************************************************************** - * - * Private class method prototypes - * - ***********************************************************************/ - static void set_defaults_dec(FLAC__StreamDecoder *decoder); static FILE *get_binary_stdin_(void); static FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigned channels); @@ -117026,12 +107607,6 @@ static FLAC__StreamDecoderTellStatus file_tell_callback_dec (const FLAC__StreamD static FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data); static FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data); -/*********************************************************************** - * - * Private class data - * - ***********************************************************************/ - typedef struct FLAC__StreamDecoderPrivate { #if FLAC__HAS_OGG FLAC__bool is_ogg; @@ -117044,13 +107619,9 @@ typedef struct FLAC__StreamDecoderPrivate { FLAC__StreamDecoderWriteCallback write_callback; FLAC__StreamDecoderMetadataCallback metadata_callback; FLAC__StreamDecoderErrorCallback error_callback; - /* generic 32-bit datapath: */ void (*local_lpc_restore_signal)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); - /* generic 64-bit datapath: */ void (*local_lpc_restore_signal_64bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); - /* for use when the signal is <= 16 bits-per-sample, or <= 15 bits-per-sample on a side channel (which requires 1 extra bit): */ void (*local_lpc_restore_signal_16bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); - /* for use when the signal is <= 16 bits-per-sample, or <= 15 bits-per-sample on a side channel (which requires 1 extra bit), AND order <= 8: */ void (*local_lpc_restore_signal_16bit_order8)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); FLAC__bool (*local_bitreader_read_rice_signed_block)(FLAC__BitReader *br, int* vals, unsigned nvals, unsigned parameter); void *client_data; @@ -117073,14 +107644,12 @@ typedef struct FLAC__StreamDecoderPrivate { FLAC__CPUInfo cpuinfo; FLAC__byte header_warmup[2]; /* contains the sync code and reserved bits */ FLAC__byte lookahead; /* temp storage when we need to look ahead one byte in the stream */ - /* unaligned (original) pointers to allocated data */ FLAC__int32 *residual_unaligned[FLAC__MAX_CHANNELS]; FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek or if the metadata has a zero MD5 */ FLAC__bool internal_reset_hack; /* used only during init() so we can call reset to set up the decoder without rewinding the input */ FLAC__bool is_seeking; FLAC__MD5Context md5context; FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */ - /* (the rest of these are only used for seeking) */ FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */ FLAC__uint64 first_frame_offset; /* hint to the seek routine of where in the stream the first audio frame starts */ FLAC__uint64 target_sample; @@ -117090,12 +107659,6 @@ typedef struct FLAC__StreamDecoderPrivate { #endif } FLAC__StreamDecoderPrivate; -/*********************************************************************** - * - * Public static class data - * - ***********************************************************************/ - FLAC_API const char * const FLAC__StreamDecoderStateString[] = { "FLAC__STREAM_DECODER_SEARCH_FOR_METADATA", "FLAC__STREAM_DECODER_READ_METADATA", @@ -117154,11 +107717,6 @@ FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[] = { "FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM" }; -/*********************************************************************** - * - * Class constructor/destructor - * - ***********************************************************************/ FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(void) { FLAC__StreamDecoder *decoder; @@ -117246,12 +107804,6 @@ FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder) free(decoder); } -/*********************************************************************** - * - * Public class methods - * - ***********************************************************************/ - static FLAC__StreamDecoderInitStatus init_stream_internal_dec( FLAC__StreamDecoder *decoder, FLAC__StreamDecoderReadCallback read_callback, @@ -117290,17 +107842,12 @@ static FLAC__StreamDecoderInitStatus init_stream_internal_dec( return decoder->protected_->state = FLAC__STREAM_DECODER_OGG_ERROR; #endif - /* - * get the CPU info and set the function pointers - */ FLAC__cpu_info(&decoder->private_->cpuinfo); - /* first default to the non-asm routines */ decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal; decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide; decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal; decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal; decoder->private_->local_bitreader_read_rice_signed_block = FLAC__bitreader_read_rice_signed_block; - /* now override with asm where appropriate */ #ifndef FLAC__NO_ASM if(decoder->private_->cpuinfo.use_asm) { #ifdef FLAC__CPU_IA32 @@ -117331,8 +107878,6 @@ static FLAC__StreamDecoderInitStatus init_stream_internal_dec( } #endif - /* from here on, errors are fatal */ - if(!FLAC__bitreader_init(decoder->private_->input, decoder->private_->cpuinfo, read_callback_, decoder)) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR; @@ -117357,7 +107902,6 @@ static FLAC__StreamDecoderInitStatus init_stream_internal_dec( decoder->private_->internal_reset_hack = true; /* so the following reset does not try to rewind the input */ if(!FLAC__stream_decoder_reset(decoder)) { - /* above call sets the state for us */ return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR; } @@ -117388,7 +107932,7 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream( metadata_callback, error_callback, client_data, - /*is_ogg=*/false +false ); } @@ -117416,7 +107960,7 @@ FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream( metadata_callback, error_callback, client_data, - /*is_ogg=*/true +true ); } @@ -117439,11 +107983,6 @@ static FLAC__StreamDecoderInitStatus init_FILE_internal_( if(0 == write_callback || 0 == error_callback) return (FLAC__StreamDecoderInitStatus) (decoder->protected_->state = (FLAC__StreamDecoderState) FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS); - /* - * To make sure that our file does not go unclosed after an error, we - * must assign the FILE pointer before any further error can occur in - * this routine. - */ if(file == stdin) file = get_binary_stdin_(); /* just to be safe */ @@ -117502,11 +108041,6 @@ static FLAC__StreamDecoderInitStatus init_file_internal_( FLAC__ASSERT(0 != decoder); - /* - * To make sure that our file does not go unclosed after an error, we - * have to do the same entrance checks here that are later performed - * in FLAC__stream_decoder_init_FILE() before the FILE* is assigned. - */ if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) return (FLAC__StreamDecoderInitStatus) (decoder->protected_->state = (FLAC__StreamDecoderState) FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED); @@ -117557,9 +108091,6 @@ FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder) if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED) return true; - /* see the comment in FLAC__seekable_stream_decoder_reset() as to why we - * always call FLAC__MD5Final() - */ FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context); if(decoder->private_->has_seek_table && 0 != decoder->private_->seek_table.data.seek_table.points) { @@ -117569,12 +108100,6 @@ FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder) } FLAC__bitreader_free(decoder->private_->input); for(i = 0; i < FLAC__MAX_CHANNELS; i++) { - /* WATCHOUT: - * FLAC__lpc_restore_signal_asm_ia32_mmx() requires that the - * output arrays have a buffer of up to 3 zeroes in front - * (at negative indices) for alignment purposes; we use 4 - * to keep the data well-aligned. - */ if(0 != decoder->private_->output[i]) { free(decoder->private_->output[i]-4); decoder->private_->output[i] = 0; @@ -117619,7 +108144,6 @@ FLAC_API FLAC__bool FLAC__stream_decoder_set_ogg_serial_number(FLAC__StreamDecod if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) return false; #if FLAC__HAS_OGG - /* can't check decoder->private_->is_ogg since that's not set until init time */ FLAC__ogg_decoder_aspect_set_serial_number(&decoder->protected_->ogg_decoder_aspect, value); return true; #else @@ -117644,7 +108168,6 @@ FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond(FLAC__StreamDecode FLAC__ASSERT(0 != decoder->private_); FLAC__ASSERT(0 != decoder->protected_); FLAC__ASSERT((unsigned)type <= FLAC__MAX_METADATA_TYPE_CODE); - /* double protection */ if((unsigned)type > FLAC__MAX_METADATA_TYPE_CODE) return false; if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) @@ -117703,7 +108226,6 @@ FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore(FLAC__StreamDecoder FLAC__ASSERT(0 != decoder->private_); FLAC__ASSERT(0 != decoder->protected_); FLAC__ASSERT((unsigned)type <= FLAC__MAX_METADATA_TYPE_CODE); - /* double protection */ if((unsigned)type > FLAC__MAX_METADATA_TYPE_CODE) return false; if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) @@ -117829,7 +108351,6 @@ FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamD return false; if(decoder->private_->tell_callback(decoder, position, decoder->private_->client_data) != FLAC__STREAM_DECODER_TELL_STATUS_OK) return false; - /* should never happen since all FLAC frames and metadata blocks are byte aligned, but check just in case */ if(!FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)) return false; FLAC__ASSERT(*position >= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder)); @@ -117867,21 +108388,14 @@ FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder) FLAC__ASSERT(0 != decoder->protected_); if(!FLAC__stream_decoder_flush(decoder)) { - /* above call sets the state for us */ return false; } #if FLAC__HAS_OGG - /*@@@ could go in !internal_reset_hack block below */ if(decoder->private_->is_ogg) FLAC__ogg_decoder_aspect_reset(&decoder->protected_->ogg_decoder_aspect); #endif - /* Rewind if necessary. If FLAC__stream_decoder_init() is calling us, - * (internal_reset_hack) don't try to rewind since we are already at - * the beginning of the stream and don't want to fail if the input is - * not seekable. - */ if(!decoder->private_->internal_reset_hack) { if(decoder->private_->file == stdin) return false; /* can't rewind stdin, reset fails */ @@ -117900,18 +108414,8 @@ FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder) decoder->private_->has_seek_table = false; } decoder->private_->do_md5_checking = decoder->protected_->md5_checking; - /* - * This goes in reset() and not flush() because according to the spec, a - * fixed-blocksize stream must stay that way through the whole stream. - */ decoder->private_->fixed_block_size = decoder->private_->next_fixed_block_size = 0; - /* We initialize the FLAC__MD5Context even though we may never use it. This - * is because md5 checking may be turned on to start and then turned off if - * a seek occurs. So we init the context here and finalize it in - * FLAC__stream_decoder_finish() to make sure things are always cleaned up - * properly. - */ FLAC__MD5Init(&decoder->private_->md5context); decoder->private_->first_frame_offset = 0; @@ -118077,26 +108581,21 @@ FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *deco decoder->private_->is_seeking = true; - /* turn off md5 checking if a seek is attempted */ decoder->private_->do_md5_checking = false; - /* get the file length (currently our algorithm needs to know the length so it's also an error to get FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED) */ if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != FLAC__STREAM_DECODER_LENGTH_STATUS_OK) { decoder->private_->is_seeking = false; return false; } - /* if we haven't finished processing the metadata yet, do that so we have the STREAMINFO, SEEK_TABLE, and first_frame_offset */ if( decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA || decoder->protected_->state == FLAC__STREAM_DECODER_READ_METADATA ) { if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) { - /* above call sets the state for us */ decoder->private_->is_seeking = false; return false; } - /* check this again in case we didn't know total_samples the first time */ if(FLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= FLAC__stream_decoder_get_total_samples(decoder)) { decoder->private_->is_seeking = false; return false; @@ -118116,12 +108615,6 @@ FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *deco } } -/*********************************************************************** - * - * Protected class methods - * - ***********************************************************************/ - unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder) { FLAC__ASSERT(0 != decoder); @@ -118130,12 +108623,6 @@ unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecod return FLAC__bitreader_get_input_bits_unconsumed(decoder->private_->input) / 8; } -/*********************************************************************** - * - * Private class methods - * - ***********************************************************************/ - void set_defaults_dec(FLAC__StreamDecoder *decoder) { #if FLAC__HAS_OGG @@ -118162,19 +108649,11 @@ void set_defaults_dec(FLAC__StreamDecoder *decoder) #endif } -/* - * This will forcibly set stdin to binary mode (for OSes that require it) - */ FILE *get_binary_stdin_(void) { - /* if something breaks here it is probably due to the presence or - * absence of an underscore before the identifiers 'setmode', - * 'fileno', and/or 'O_BINARY'; check your system header files. - */ #if defined _MSC_VER || defined __MINGW32__ _setmode(_fileno(stdin), _O_BINARY); #elif defined __CYGWIN__ - /* almost certainly not needed for any modern Cygwin, but let's be safe... */ setmode(_fileno(stdin), _O_BINARY); #elif defined __EMX__ setmode(fileno(stdin), O_BINARY); @@ -118191,8 +108670,6 @@ FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigne if(size <= decoder->private_->output_capacity && channels <= decoder->private_->output_channels) return true; - /* simply using realloc() is not practical because the number of channels may change mid-stream */ - for(i = 0; i < FLAC__MAX_CHANNELS; i++) { if(0 != decoder->private_->output[i]) { free(decoder->private_->output[i]-4); @@ -118205,12 +108682,6 @@ FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigne } for(i = 0; i < channels; i++) { - /* WATCHOUT: - * FLAC__lpc_restore_signal_asm_ia32_mmx() requires that the - * output arrays have a buffer of up to 3 zeroes in front - * (at negative indices) for alignment purposes; we use 4 - * to keep the data well-aligned. - */ tmp = (FLAC__int32*)safe_malloc_muladd2_(sizeof(FLAC__int32), /*times (*/size, /*+*/4/*)*/); if(tmp == 0) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; @@ -118219,9 +108690,6 @@ FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigne memset(tmp, 0, sizeof(FLAC__int32)*4); decoder->private_->output[i] = tmp + 4; - /* WATCHOUT: - * minimum of quadword alignment for PPC vector optimizations is REQUIRED: - */ if(!FLAC__memory_alloc_aligned_int32_array(size, &decoder->private_->residual_unaligned[i], &decoder->private_->residual[i])) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; @@ -118286,8 +108754,6 @@ FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder) if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) return false; /* read_callback_ sets the state for us */ - /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */ - /* else we have to check if the second byte is the end of a sync code */ if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ decoder->private_->lookahead = (FLAC__byte)x; decoder->private_->cached = true; @@ -118375,12 +108841,10 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) else { switch(type) { case FLAC__METADATA_TYPE_PADDING: - /* skip the padding bytes */ if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, real_length)) return false; /* read_callback_ sets the state for us */ break; case FLAC__METADATA_TYPE_APPLICATION: - /* remember, we read the ID already */ if(real_length > 0) { if(0 == (block.data.application.data = (FLAC__byte*)malloc(real_length))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; @@ -118424,7 +108888,6 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) if(!decoder->private_->is_seeking && decoder->private_->metadata_callback) decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data); - /* now we have to free any malloc()ed data in the block */ switch(type) { case FLAC__METADATA_TYPE_PADDING: break; @@ -118470,7 +108933,6 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) } if(is_last) { - /* if this fails, it's OK, it's just a hint for the seek routine */ if(!FLAC__stream_decoder_get_decode_position(decoder, &decoder->private_->first_frame_offset)) decoder->private_->first_frame_offset = 0; decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; @@ -118541,7 +109003,6 @@ FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is return false; /* read_callback_ sets the state for us */ used_bits += 16*8; - /* skip the rest of the block */ FLAC__ASSERT(used_bits % 8 == 0); length -= (used_bits / 8); if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, length)) @@ -118563,7 +109024,6 @@ FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_ decoder->private_->seek_table.data.seek_table.num_points = length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; - /* use realloc since we may pass through here several times (e.g. after seeking) */ if(0 == (decoder->private_->seek_table.data.seek_table.points = (FLAC__StreamMetadata_SeekPoint*)safe_realloc_mul_2op_(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; @@ -118582,9 +109042,7 @@ FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_ decoder->private_->seek_table.data.seek_table.points[i].frame_samples = x; } length -= (decoder->private_->seek_table.data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH); - /* if there is a partial point left, skip over it */ if(length > 0) { - /*@@@ do a send_error_to_client_() here? there's an argument for either way */ if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, length)) return false; /* read_callback_ sets the state for us */ } @@ -118598,7 +109056,6 @@ FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__Stre FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); - /* read vendor string */ FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length)) return false; /* read_callback_ sets the state for us */ @@ -118614,12 +109071,10 @@ FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__Stre else obj->vendor_string.entry = 0; - /* read num comments */ FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32); if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->num_comments)) return false; /* read_callback_ sets the state for us */ - /* read comments */ if(obj->num_comments > 0) { if(0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)safe_malloc_mul_2op_(obj->num_comments, /*times*/sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; @@ -118738,12 +109193,10 @@ FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMeta FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); - /* read type */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN)) return false; /* read_callback_ sets the state for us */ obj->type = (FLAC__StreamMetadata_Picture_Type) x; - /* read MIME type */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN)) return false; /* read_callback_ sets the state for us */ if(0 == (obj->mime_type = (char*)safe_malloc_add_2op_(x, /*+*/1))) { @@ -118756,7 +109209,6 @@ FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMeta } obj->mime_type[x] = '\0'; - /* read description */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN)) return false; /* read_callback_ sets the state for us */ if(0 == (obj->description = (FLAC__byte*)safe_malloc_add_2op_(x, /*+*/1))) { @@ -118769,23 +109221,18 @@ FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMeta } obj->description[x] = '\0'; - /* read width */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN)) return false; /* read_callback_ sets the state for us */ - /* read height */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN)) return false; /* read_callback_ sets the state for us */ - /* read depth */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN)) return false; /* read_callback_ sets the state for us */ - /* read colors */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->colors, FLAC__STREAM_METADATA_PICTURE_COLORS_LEN)) return false; /* read_callback_ sets the state for us */ - /* read data */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &(obj->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN)) return false; /* read_callback_ sets the state for us */ if(0 == (obj->data = (FLAC__byte*)safe_malloc_(obj->data_length))) { @@ -118805,10 +109252,8 @@ FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder) FLAC__uint32 x; unsigned i, skip; - /* skip the version and flags bytes */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 24)) return false; /* read_callback_ sets the state for us */ - /* get the size (in bytes) to skip */ skip = 0; for(i = 0; i < 4; i++) { if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) @@ -118816,7 +109261,6 @@ FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder) skip <<= 7; skip |= (x & 0x7f); } - /* skip the rest of the tag */ if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, skip)) return false; /* read_callback_ sets the state for us */ return true; @@ -118827,8 +109271,6 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder) FLAC__uint32 x; FLAC__bool first = true; - /* If we know the total number of samples in the stream, stop if we've read that many. */ - /* This will stop us, for example, from wasting time trying to sync on an ID3V1 tag. */ if(FLAC__stream_decoder_get_total_samples(decoder) > 0) { if(decoder->private_->samples_decoded >= FLAC__stream_decoder_get_total_samples(decoder)) { decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM; @@ -118836,7 +109278,6 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder) } } - /* make sure we're byte aligned */ if(!FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)) { if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__bitreader_bits_left_for_byte_alignment(decoder->private_->input))) return false; /* read_callback_ sets the state for us */ @@ -118856,8 +109297,6 @@ FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder) if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) return false; /* read_callback_ sets the state for us */ - /* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */ - /* else we have to check if the second byte is the end of a sync code */ if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ decoder->private_->lookahead = (FLAC__byte)x; decoder->private_->cached = true; @@ -118887,7 +109326,6 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL *got_a_frame = false; - /* init the CRC */ frame_crc = 0; frame_crc = FLAC__CRC16_UPDATE(decoder->private_->header_warmup[0], frame_crc); frame_crc = FLAC__CRC16_UPDATE(decoder->private_->header_warmup[1], frame_crc); @@ -118900,13 +109338,9 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL if(!allocate_output_(decoder, decoder->private_->frame.header.blocksize, decoder->private_->frame.header.channels)) return false; for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) { - /* - * first figure the correct bits-per-sample of the subframe - */ unsigned bps = decoder->private_->frame.header.bits_per_sample; switch(decoder->private_->frame.header.channel_assignment) { case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: - /* no adjustment needed */ break; case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: FLAC__ASSERT(decoder->private_->frame.header.channels == 2); @@ -118926,9 +109360,6 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL default: FLAC__ASSERT(0); } - /* - * now read it - */ if(!read_subframe_(decoder, channel, bps, do_full_decode)) return false; if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption */ @@ -118939,18 +109370,13 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption (i.e. "zero bits" were not all zeroes) */ return true; - /* - * Read the frame CRC-16 from the footer and check - */ frame_crc = FLAC__bitreader_get_read_crc16(decoder->private_->input); if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN)) return false; /* read_callback_ sets the state for us */ if(frame_crc == x) { if(do_full_decode) { - /* Undo any special channel coding */ switch(decoder->private_->frame.header.channel_assignment) { case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: - /* do nothing */ break; case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: FLAC__ASSERT(decoder->private_->frame.header.channels == 2); @@ -118973,7 +109399,6 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL decoder->private_->output[0][i] = (mid + side) >> 1; decoder->private_->output[1][i] = (mid - side) >> 1; #else - /* OPT: without 'side' temp variable */ mid = (decoder->private_->output[0][i] << 1) | (decoder->private_->output[1][i] & 1); /* i.e. if 'side' is odd... */ decoder->private_->output[0][i] = (mid + decoder->private_->output[1][i]) >> 1; decoder->private_->output[1][i] = (mid - decoder->private_->output[1][i]) >> 1; @@ -118987,7 +109412,6 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL } } else { - /* Bad frame, emit error and zero the output signal */ send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH); if(do_full_decode) { for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) { @@ -118998,11 +109422,9 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL *got_a_frame = true; - /* we wait to update fixed_block_size until here, when we're sure we've got a proper frame and hence a correct blocksize */ if(decoder->private_->next_fixed_block_size) decoder->private_->fixed_block_size = decoder->private_->next_fixed_block_size; - /* put the latest values into the public section of the decoder instance */ decoder->protected_->channels = decoder->private_->frame.header.channels; decoder->protected_->channel_assignment = decoder->private_->frame.header.channel_assignment; decoder->protected_->bits_per_sample = decoder->private_->frame.header.bits_per_sample; @@ -119012,7 +109434,6 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL FLAC__ASSERT(decoder->private_->frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); decoder->private_->samples_decoded = decoder->private_->frame.header.number.sample_number + decoder->private_->frame.header.blocksize; - /* write it */ if(do_full_decode) { if(write_audio_frame_to_client_(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE) return false; @@ -119033,42 +109454,17 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); - /* init the raw header with the saved bits from synchronization */ raw_header[0] = decoder->private_->header_warmup[0]; raw_header[1] = decoder->private_->header_warmup[1]; raw_header_len = 2; - /* check to make sure that reserved bit is 0 */ if(raw_header[1] & 0x02) /* MAGIC NUMBER */ is_unparseable = true; - /* - * Note that along the way as we read the header, we look for a sync - * code inside. If we find one it would indicate that our original - * sync was bad since there cannot be a sync code in a valid header. - * - * Three kinds of things can go wrong when reading the frame header: - * 1) We may have sync'ed incorrectly and not landed on a frame header. - * If we don't find a sync code, it can end up looking like we read - * a valid but unparseable header, until getting to the frame header - * CRC. Even then we could get a false positive on the CRC. - * 2) We may have sync'ed correctly but on an unparseable frame (from a - * future encoder). - * 3) We may be on a damaged frame which appears valid but unparseable. - * - * For all these reasons, we try and read a complete frame header as - * long as it seems valid, even if unparseable, up until the frame - * header CRC. - */ - - /* - * read in the raw header as bytes so we can CRC it, and parse it on the way - */ for(i = 0; i < 2; i++) { if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) return false; /* read_callback_ sets the state for us */ if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */ - /* if we get here it means our original sync was erroneous since the sync code cannot appear in the header */ decoder->private_->lookahead = (FLAC__byte)x; decoder->private_->cached = true; send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER); @@ -119217,14 +109613,11 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) break; } - /* check to make sure that reserved bit is 0 */ if(raw_header[3] & 0x01) /* MAGIC NUMBER */ is_unparseable = true; - /* read the frame's starting sample number (or frame number as the case may be) */ if( raw_header[1] & 0x01 || - /*@@@ this clause is a concession to the old way of doing variable blocksize; the only known implementation is flake and can probably be removed without inconveniencing anyone */ (decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize != decoder->private_->stream_info.data.stream_info.max_blocksize) ) { /* variable blocksize */ if(!FLAC__bitreader_read_utf8_uint64(decoder->private_->input, &xx, raw_header, &raw_header_len)) @@ -119286,7 +109679,6 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) decoder->private_->frame.header.sample_rate = x*10; } - /* read the CRC-8 byte */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) return false; /* read_callback_ sets the state for us */ crc8 = (FLAC__byte)x; @@ -119297,7 +109689,6 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) return true; } - /* calculate the sample number from the frame number if needed */ decoder->private_->next_fixed_block_size = 0; if(decoder->private_->frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER) { x = decoder->private_->frame.header.number.frame_number; @@ -119317,7 +109708,6 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) decoder->private_->next_fixed_block_size = decoder->private_->frame.header.blocksize; } else { - /* can only get here if the stream has invalid frame numbering and no STREAMINFO, so assume it's not the last (possibly short) frame */ decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->frame.header.blocksize * (FLAC__uint64)x; } } @@ -119353,9 +109743,6 @@ FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, unsigned channel, unsign else decoder->private_->frame.subframes[channel].wasted_bits = 0; - /* - * Lots of magic numbers here - */ if(x & 0x80) { send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; @@ -119415,7 +109802,6 @@ FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, unsigned channe subframe->value = x; - /* decode the subframe */ if(do_full_decode) { for(i = 0; i < decoder->private_->frame.header.blocksize; i++) output[i] = x; @@ -119436,14 +109822,12 @@ FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, subframe->residual = decoder->private_->residual[channel]; subframe->order = order; - /* read warm-up samples */ for(u = 0; u < order; u++) { if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, bps)) return false; /* read_callback_ sets the state for us */ subframe->warmup[u] = i32; } - /* read entropy coding method info */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN)) return false; /* read_callback_ sets the state for us */ subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32; @@ -119461,7 +109845,6 @@ FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, return true; } - /* read residual */ switch(subframe->entropy_coding_method.type) { case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2: @@ -119472,7 +109855,6 @@ FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, unsigned channel, FLAC__ASSERT(0); } - /* decode the subframe */ if(do_full_decode) { memcpy(decoder->private_->output[channel], subframe->warmup, sizeof(FLAC__int32) * order); FLAC__fixed_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->output[channel]+order); @@ -119493,14 +109875,12 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, un subframe->residual = decoder->private_->residual[channel]; subframe->order = order; - /* read warm-up samples */ for(u = 0; u < order; u++) { if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, bps)) return false; /* read_callback_ sets the state for us */ subframe->warmup[u] = i32; } - /* read qlp coeff precision */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN)) return false; /* read_callback_ sets the state for us */ if(u32 == (1u << FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN) - 1) { @@ -119510,19 +109890,16 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, un } subframe->qlp_coeff_precision = u32+1; - /* read qlp shift */ if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN)) return false; /* read_callback_ sets the state for us */ subframe->quantization_level = i32; - /* read quantized lp coefficiencts */ for(u = 0; u < order; u++) { if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, subframe->qlp_coeff_precision)) return false; /* read_callback_ sets the state for us */ subframe->qlp_coeff[u] = i32; } - /* read entropy coding method info */ if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN)) return false; /* read_callback_ sets the state for us */ subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32; @@ -119540,7 +109917,6 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, un return true; } - /* read residual */ switch(subframe->entropy_coding_method.type) { case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE: case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2: @@ -119551,12 +109927,8 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, un FLAC__ASSERT(0); } - /* decode the subframe */ if(do_full_decode) { memcpy(decoder->private_->output[channel], subframe->warmup, sizeof(FLAC__int32) * order); - /*@@@@@@ technically not pessimistic enough, should be more like - if( (FLAC__uint64)order * ((((FLAC__uint64)1)<qlp_coeff_precision)-1) < (((FLAC__uint64)-1) << 32) ) - */ if(bps + subframe->qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32) if(bps <= 16 && subframe->qlp_coeff_precision <= 16) { if(order <= 8) @@ -119589,7 +109961,6 @@ FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, unsigned channe residual[i] = x; } - /* decode the subframe */ if(do_full_decode) memcpy(decoder->private_->output[channel], subframe->data, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize); @@ -119606,7 +109977,6 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigne const unsigned plen = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; const unsigned pesc = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; - /* sanity checks */ if(partition_order == 0) { if(decoder->private_->frame.header.blocksize < predictor_order) { send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); @@ -119674,7 +110044,6 @@ FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data) if( #if FLAC__HAS_OGG - /* see [1] HACK NOTE below for why we don't call the eof_callback when decoding Ogg FLAC */ !decoder->private_->is_ogg && #endif decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data) @@ -119684,16 +110053,6 @@ FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data) return false; } else if(*bytes > 0) { - /* While seeking, it is possible for our seek to land in the - * middle of audio data that looks exactly like a frame header - * from a future version of an encoder. When that happens, our - * error callback will get an - * FLAC__STREAM_DECODER_UNPARSEABLE_STREAM and increment its - * unparseable_frame_count. But there is a remote possibility - * that it is properly synced at such a "future-codec frame", - * so to make sure, we wait to see many "unparseable" errors in - * a row before bailing out. - */ if(decoder->private_->is_seeking && decoder->private_->unparseable_frame_count > 20) { decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; return false; @@ -119715,7 +110074,6 @@ FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data) status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM || ( #if FLAC__HAS_OGG - /* see [1] HACK NOTE below for why we don't call the eof_callback when decoding Ogg FLAC */ !decoder->private_->is_ogg && #endif decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data) @@ -119732,20 +110090,9 @@ FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data) } } else { - /* abort to avoid a deadlock */ decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED; return false; } - /* [1] @@@ HACK NOTE: The end-of-stream checking has to be hacked around - * for Ogg FLAC. This is because the ogg decoder aspect can lose sync - * and at the same time hit the end of the stream (for example, seeking - * to a point that is after the beginning of the last Ogg page). There - * is no way to report an Ogg sync loss through the callbacks (see note - * in read_callback_ogg_aspect_()) so it returns CONTINUE with *bytes==0. - * So to keep the decoder from stopping at this point we gate the call - * to the eof_callback and let the Ogg decoder aspect set the - * end-of-stream state when it is needed. - */ } #if FLAC__HAS_OGG @@ -119754,10 +110101,6 @@ FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecode switch(FLAC__ogg_decoder_aspect_read_callback_wrapper(&decoder->protected_->ogg_decoder_aspect, buffer, bytes, read_callback_proxy_, decoder, decoder->private_->client_data)) { case FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK: return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; - /* we don't really have a way to handle lost sync via read - * callback so we'll let it pass and let the underlying - * FLAC decoder catch the error - */ case FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC: return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; case FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM: @@ -119770,7 +110113,6 @@ FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecode return FLAC__STREAM_DECODER_READ_STATUS_ABORT; default: FLAC__ASSERT(0); - /* double protection */ return FLAC__STREAM_DECODER_READ_STATUS_ABORT; } } @@ -119787,7 +110129,6 @@ FLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, case FLAC__STREAM_DECODER_READ_STATUS_ABORT: return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT; default: - /* double protection: */ FLAC__ASSERT(0); return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT; } @@ -119809,9 +110150,7 @@ FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder decoder->private_->last_frame = *frame; /* save the frame */ if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */ unsigned delta = (unsigned)(target_sample - this_frame_sample); - /* kick out of seek mode */ decoder->private_->is_seeking = false; - /* shift out the samples before target_sample */ if(delta > 0) { unsigned channel; const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS]; @@ -119819,30 +110158,24 @@ FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder newbuffer[channel] = buffer[channel] + delta; decoder->private_->last_frame.header.blocksize -= delta; decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta; - /* write the relevant samples */ return decoder->private_->write_callback(decoder, &decoder->private_->last_frame, newbuffer, decoder->private_->client_data); } else { - /* write the relevant samples */ return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data); } } - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } - /* - * If we never got STREAMINFO, turn off MD5 checking to save - * cycles since we don't have a sum to compare to anyway - */ - if(!decoder->private_->has_stream_info) - decoder->private_->do_md5_checking = false; - if(decoder->private_->do_md5_checking) { - if(!FLAC__MD5Accumulate(&decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8)) - return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - } + if(!decoder->private_->has_stream_info) + decoder->private_->do_md5_checking = false; + if(decoder->private_->do_md5_checking) { + if(!FLAC__MD5Accumulate(&decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8)) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } - return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data); + return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data); } void send_error_to_client_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status) @@ -119865,59 +110198,34 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s const unsigned max_blocksize = decoder->private_->stream_info.data.stream_info.max_blocksize; const unsigned max_framesize = decoder->private_->stream_info.data.stream_info.max_framesize; const unsigned min_framesize = decoder->private_->stream_info.data.stream_info.min_framesize; - /* take these from the current frame in case they've changed mid-stream */ unsigned channels = FLAC__stream_decoder_get_channels(decoder); unsigned bps = FLAC__stream_decoder_get_bits_per_sample(decoder); const FLAC__StreamMetadata_SeekTable *seek_table = decoder->private_->has_seek_table? &decoder->private_->seek_table.data.seek_table : 0; - /* use values from stream info if we didn't decode a frame */ if(channels == 0) channels = decoder->private_->stream_info.data.stream_info.channels; if(bps == 0) bps = decoder->private_->stream_info.data.stream_info.bits_per_sample; - /* we are just guessing here */ if(max_framesize > 0) approx_bytes_per_frame = (max_framesize + min_framesize) / 2 + 1; - /* - * Check if it's a known fixed-blocksize stream. Note that though - * the spec doesn't allow zeroes in the STREAMINFO block, we may - * never get a STREAMINFO block when decoding so the value of - * min_blocksize might be zero. - */ else if(min_blocksize == max_blocksize && min_blocksize > 0) { - /* note there are no () around 'bps/8' to keep precision up since it's an integer calulation */ approx_bytes_per_frame = min_blocksize * channels * bps/8 + 64; } else approx_bytes_per_frame = 4096 * channels * bps/8 + 64; - /* - * First, we set an upper and lower bound on where in the - * stream we will search. For now we assume the worst case - * scenario, which is our best guess at the beginning of - * the first frame and end of the stream. - */ lower_bound = first_frame_offset; lower_bound_sample = 0; upper_bound = stream_length; upper_bound_sample = total_samples > 0 ? total_samples : target_sample /*estimate it*/; - /* - * Now we refine the bounds if we have a seektable with - * suitable points. Note that according to the spec they - * must be ordered by ascending sample number. - * - * Note: to protect against invalid seek tables we will ignore points - * that have frame_samples==0 or sample_number>=total_samples - */ if(seek_table) { FLAC__uint64 new_lower_bound = lower_bound; FLAC__uint64 new_upper_bound = upper_bound; FLAC__uint64 new_lower_bound_sample = lower_bound_sample; FLAC__uint64 new_upper_bound_sample = upper_bound_sample; - /* find the closest seek point <= target_sample, if it exists */ for(i = (int)seek_table->num_points - 1; i >= 0; i--) { if( seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && @@ -119932,7 +110240,6 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s new_lower_bound_sample = seek_table->points[i].sample_number; } - /* find the closest seek point > target_sample, if it exists */ for(i = 0; i < (int)seek_table->num_points; i++) { if( seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && @@ -119946,7 +110253,6 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s new_upper_bound = first_frame_offset + seek_table->points[i].stream_offset; new_upper_bound_sample = seek_table->points[i].sample_number; } - /* final protection against unsorted seek tables; keep original values if bogus */ if(new_upper_bound >= new_lower_bound) { lower_bound = new_lower_bound; upper_bound = new_upper_bound; @@ -119956,34 +110262,22 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s } FLAC__ASSERT(upper_bound_sample >= lower_bound_sample); - /* there are 2 insidious ways that the following equality occurs, which - * we need to fix: - * 1) total_samples is 0 (unknown) and target_sample is 0 - * 2) total_samples is 0 (unknown) and target_sample happens to be - * exactly equal to the last seek point in the seek table; this - * means there is no seek point above it, and upper_bound_samples - * remains equal to the estimate (of target_samples) we made above - * in either case it does not hurt to move upper_bound_sample up by 1 - */ if(upper_bound_sample == lower_bound_sample) upper_bound_sample++; decoder->private_->target_sample = target_sample; while(1) { - /* check if the bounds are still ok */ if (lower_bound_sample >= upper_bound_sample || lower_bound > upper_bound) { decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; return false; } #ifndef FLAC__INTEGER_ONLY_LIBRARY #if defined _MSC_VER || defined __MINGW32__ - /* with VC++ you have to spoon feed it the casting */ pos = (FLAC__int64)lower_bound + (FLAC__int64)((FLAC__double)(FLAC__int64)(target_sample - lower_bound_sample) / (FLAC__double)(FLAC__int64)(upper_bound_sample - lower_bound_sample) * (FLAC__double)(FLAC__int64)(upper_bound - lower_bound)) - approx_bytes_per_frame; #else pos = (FLAC__int64)lower_bound + (FLAC__int64)((FLAC__double)(target_sample - lower_bound_sample) / (FLAC__double)(upper_bound_sample - lower_bound_sample) * (FLAC__double)(upper_bound - lower_bound)) - approx_bytes_per_frame; #endif #else - /* a little less accurate: */ if(upper_bound - lower_bound < 0xffffffff) pos = (FLAC__int64)lower_bound + (FLAC__int64)(((target_sample - lower_bound_sample) * (upper_bound - lower_bound)) / (upper_bound_sample - lower_bound_sample)) - approx_bytes_per_frame; else /* @@@ WATCHOUT, ~2TB limit */ @@ -119998,24 +110292,14 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s return false; } if(!FLAC__stream_decoder_flush(decoder)) { - /* above call sets the state for us */ return false; } - /* Now we need to get a frame. First we need to reset our - * unparseable_frame_count; if we get too many unparseable - * frames in a row, the read callback will return - * FLAC__STREAM_DECODER_READ_STATUS_ABORT, causing - * FLAC__stream_decoder_process_single() to return false. - */ decoder->private_->unparseable_frame_count = 0; if(!FLAC__stream_decoder_process_single(decoder)) { decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; return false; } - /* our write callback will change the state when it gets to the target frame */ - /* actually, we could have got_a_frame if our decoder is at FLAC__STREAM_DECODER_END_OF_STREAM so we need to check for that also */ #if 0 - /*@@@@@@ used to be the following; not clear if the check for end of stream is needed anymore */ if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING && decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM) break; #endif @@ -120027,27 +110311,21 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s if (0 == decoder->private_->samples_decoded || (this_frame_sample + decoder->private_->last_frame.header.blocksize >= upper_bound_sample && !first_seek)) { if (pos == (FLAC__int64)lower_bound) { - /* can't move back any more than the first frame, something is fatally wrong */ decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; return false; } - /* our last move backwards wasn't big enough, try again */ approx_bytes_per_frame = approx_bytes_per_frame? approx_bytes_per_frame * 2 : 16; continue; } - /* allow one seek over upper bound, so we can get a correct upper_bound_sample for streams with unknown total_samples */ first_seek = false; - /* make sure we are not seeking in corrupted stream */ if (this_frame_sample < lower_bound_sample) { decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; return false; } - /* we need to narrow the search */ if(target_sample < this_frame_sample) { upper_bound_sample = this_frame_sample + decoder->private_->last_frame.header.blocksize; -/*@@@@@@ what will decode position be if at end of stream? */ if(!FLAC__stream_decoder_get_decode_position(decoder, &upper_bound)) { decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; return false; @@ -120077,21 +110355,10 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint FLAC__bool did_a_seek; unsigned iteration = 0; - /* In the first iterations, we will calculate the target byte position - * by the distance from the target sample to left_sample and - * right_sample (let's call it "proportional search"). After that, we - * will switch to binary search. - */ unsigned BINARY_SEARCH_AFTER_ITERATION = 2; - /* We will switch to a linear search once our current sample is less - * than this number of samples ahead of the target sample - */ static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2; - /* If the total number of samples is unknown, use a large value, and - * force binary search immediately. - */ if(right_sample == 0) { right_sample = (FLAC__uint64)(-1); BINARY_SEARCH_AFTER_ITERATION = 0; @@ -120106,32 +110373,23 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint else { #ifndef FLAC__INTEGER_ONLY_LIBRARY #if defined _MSC_VER || defined __MINGW32__ - /* with MSVC you have to spoon feed it the casting */ pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos)); #else pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos)); #endif #else - /* a little less accurate: */ if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff)) pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample)); else /* @@@ WATCHOUT, ~2TB limit */ pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16)); #endif - /* @@@ TODO: might want to limit pos to some distance - * before EOF, to make sure we land before the last frame, - * thereby getting a this_frame_sample and so having a better - * estimate. - */ } - /* physical seek */ if(decoder->private_->seek_callback((FLAC__StreamDecoder*)decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__STREAM_DECODER_SEEK_STATUS_OK) { decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; return false; } if(!FLAC__stream_decoder_flush(decoder)) { - /* above call sets the state for us */ return false; } did_a_seek = true; @@ -120146,22 +110404,14 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint } if(!decoder->private_->got_a_frame) { if(did_a_seek) { - /* this can happen if we seek to a point after the last frame; we drop - * to binary search right away in this case to avoid any wasted - * iterations of proportional search. - */ right_pos = pos; BINARY_SEARCH_AFTER_ITERATION = 0; } else { - /* this can probably only happen if total_samples is unknown and the - * target_sample is past the end of the stream - */ decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; return false; } } - /* our write callback will change the state when it gets to the target frame */ else if(!decoder->private_->is_seeking) { break; } @@ -120171,16 +110421,9 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint if (did_a_seek) { if (this_frame_sample <= target_sample) { - /* The 'equal' case should not happen, since - * FLAC__stream_decoder_process_single() - * should recognize that it has hit the - * target sample and we would exit through - * the 'break' above. - */ FLAC__ASSERT(this_frame_sample != target_sample); left_sample = this_frame_sample; - /* sanity check to avoid infinite loop */ if (left_pos == pos) { decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; return false; @@ -120189,7 +110432,6 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint } else if(this_frame_sample > target_sample) { right_sample = this_frame_sample; - /* sanity check to avoid infinite loop */ if (right_pos == pos) { decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; return false; @@ -120426,15 +110668,6 @@ FLAC__bool FLAC__subframe_add_verbatim(const FLAC__Subframe_Verbatim *subframe, #ifndef FLAC__INTEGER_ONLY_LIBRARY -/* - * FLAC__window_*() - * -------------------------------------------------------------------- - * Calculates window coefficients according to different apodization - * functions. - * - * OUT window[0,L-1] - * IN L (number of points in window) - */ void FLAC__window_bartlett(FLAC__real *window, const FLAC__int32 L); void FLAC__window_bartlett_hann(FLAC__real *window, const FLAC__int32 L); void FLAC__window_blackman(FLAC__real *window, const FLAC__int32 L); @@ -120470,16 +110703,7 @@ void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L); #endif #define max(x,y) ((x)>(y)?(x):(y)) -/* Exact Rice codeword length calculation is off by default. The simple - * (and fast) estimation (of how many bits a residual value will be - * encoded with) in this encoder is very good, almost always yielding - * compression within 0.1% of exact calculation. - */ #undef EXACT_RICE_BITS_CALCULATION -/* Rice parameter searching is off by default. The simple (and fast) - * parameter estimation in this encoder is very good, almost always - * yielding compression within 0.1% of the optimal parameters. - */ #undef ENABLE_RICE_PARAMETER_SEARCH typedef struct { @@ -120523,12 +110747,6 @@ static struct CompressionLevels { { true , false, 12, 0, false, false, true , 0, 6, 0 } }; -/*********************************************************************** - * - * Private class method prototypes - * - ***********************************************************************/ - static void set_defaults_enc(FLAC__StreamEncoder *encoder); static void free_(FLAC__StreamEncoder *encoder); static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize); @@ -120676,7 +110894,6 @@ static FLAC__bool set_partitioned_rice_( static unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples); -/* verify-related routines: */ static void append_to_verify_fifo_( verify_input_fifo *fifo, const FLAC__int32 * const input[], @@ -120704,24 +110921,18 @@ static FLAC__StreamEncoderTellStatus file_tell_callback_enc(const FLAC__StreamEn static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data); static FILE *get_binary_stdout_(void); -/*********************************************************************** - * - * Private class data - * - ***********************************************************************/ - typedef struct FLAC__StreamEncoderPrivate { - unsigned input_capacity; /* current size (in samples) of the signal and residual buffers */ + unsigned input_capacity; /* current size (in samples) of the signal and residual buffers */ FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */ - FLAC__int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */ + FLAC__int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */ #ifndef FLAC__INTEGER_ONLY_LIBRARY - FLAC__real *real_signal[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) the floating-point version of the input signal */ - FLAC__real *real_signal_mid_side[2]; /* (@@@ currently unused) the floating-point version of the mid-side input signal (stereo only) */ + FLAC__real *real_signal[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) the floating-point version of the input signal */ + FLAC__real *real_signal_mid_side[2]; /* (@@@ currently unused) the floating-point version of the mid-side input signal (stereo only) */ FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */ - FLAC__real *windowed_signal; /* the integer_signal[] * current window[] */ + FLAC__real *windowed_signal; /* the integer_signal[] * current window[] */ #endif - unsigned subframe_bps[FLAC__MAX_CHANNELS]; /* the effective bits per sample of the input signal (stream bps - wasted bits) */ - unsigned subframe_bps_mid_side[2]; /* the effective bits per sample of the mid-side input signal (stream bps - wasted bits + 0/1) */ + unsigned subframe_bps[FLAC__MAX_CHANNELS]; /* the effective bits per sample of the input signal (stream bps - wasted bits) */ + unsigned subframe_bps_mid_side[2]; /* the effective bits per sample of the mid-side input signal (stream bps - wasted bits + 0/1) */ FLAC__int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */ FLAC__int32 *residual_workspace_mid_side[2][2]; FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2]; @@ -120732,18 +110943,18 @@ typedef struct FLAC__StreamEncoderPrivate { FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace_mid_side[FLAC__MAX_CHANNELS][2]; FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr[FLAC__MAX_CHANNELS][2]; FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr_mid_side[FLAC__MAX_CHANNELS][2]; - unsigned best_subframe[FLAC__MAX_CHANNELS]; /* index (0 or 1) into 2nd dimension of the above workspaces */ + unsigned best_subframe[FLAC__MAX_CHANNELS]; /* index (0 or 1) into 2nd dimension of the above workspaces */ unsigned best_subframe_mid_side[2]; unsigned best_subframe_bits[FLAC__MAX_CHANNELS]; /* size in bits of the best subframe for each channel */ unsigned best_subframe_bits_mid_side[2]; - FLAC__uint64 *abs_residual_partition_sums; /* workspace where the sum of abs(candidate residual) for each partition is stored */ - unsigned *raw_bits_per_partition; /* workspace where the sum of silog2(candidate residual) for each partition is stored */ - FLAC__BitWriter *frame; /* the current frame being worked on */ - unsigned loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */ - unsigned loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */ + FLAC__uint64 *abs_residual_partition_sums; /* workspace where the sum of abs(candidate residual) for each partition is stored */ + unsigned *raw_bits_per_partition; /* workspace where the sum of silog2(candidate residual) for each partition is stored */ + FLAC__BitWriter *frame; /* the current frame being worked on */ + unsigned loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */ + unsigned loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */ FLAC__ChannelAssignment last_channel_assignment; - FLAC__StreamMetadata streaminfo; /* scratchpad for STREAMINFO as it is built */ - FLAC__StreamMetadata_SeekTable *seek_table; /* pointer into encoder->protected_->metadata_ where the seek table is */ + FLAC__StreamMetadata streaminfo; /* scratchpad for STREAMINFO as it is built */ + FLAC__StreamMetadata_SeekTable *seek_table; /* pointer into encoder->protected_->metadata_ where the seek table is */ unsigned current_sample_number; unsigned current_frame_number; FLAC__MD5Context md5context; @@ -120759,9 +110970,9 @@ typedef struct FLAC__StreamEncoderPrivate { void (*local_lpc_compute_residual_from_qlp_coefficients_64bit)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); void (*local_lpc_compute_residual_from_qlp_coefficients_16bit)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); #endif - FLAC__bool use_wide_by_block; /* use slow 64-bit versions of some functions because of the block size */ - FLAC__bool use_wide_by_partition; /* use slow 64-bit versions of some functions because of the min partition order and blocksize */ - FLAC__bool use_wide_by_order; /* use slow 64-bit versions of some functions because of the lpc order */ + FLAC__bool use_wide_by_block; /* use slow 64-bit versions of some functions because of the block size */ + FLAC__bool use_wide_by_partition; /* use slow 64-bit versions of some functions because of the min partition order and blocksize */ + FLAC__bool use_wide_by_order; /* use slow 64-bit versions of some functions because of the lpc order */ FLAC__bool disable_constant_subframes; FLAC__bool disable_fixed_subframes; FLAC__bool disable_verbatim_subframes; @@ -120776,12 +110987,11 @@ typedef struct FLAC__StreamEncoderPrivate { FLAC__StreamEncoderProgressCallback progress_callback; void *client_data; unsigned first_seekpoint_to_check; - FILE *file; /* only used when encoding to a file */ + FILE *file; /* only used when encoding to a file */ FLAC__uint64 bytes_written; FLAC__uint64 samples_written; unsigned frames_written; unsigned total_frames_estimate; - /* unaligned (original) pointers to allocated data */ FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS]; FLAC__int32 *integer_signal_mid_side_unaligned[2]; #ifndef FLAC__INTEGER_ONLY_LIBRARY @@ -120794,17 +111004,10 @@ typedef struct FLAC__StreamEncoderPrivate { FLAC__int32 *residual_workspace_mid_side_unaligned[2][2]; FLAC__uint64 *abs_residual_partition_sums_unaligned; unsigned *raw_bits_per_partition_unaligned; - /* - * These fields have been moved here from private function local - * declarations merely to save stack space during encoding. - */ #ifndef FLAC__INTEGER_ONLY_LIBRARY FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */ #endif FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */ - /* - * The data for the verify section - */ struct { FLAC__StreamDecoder *decoder; EncoderStateHint state_hint; @@ -120823,12 +111026,6 @@ typedef struct FLAC__StreamEncoderPrivate { FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */ } FLAC__StreamEncoderPrivate; -/*********************************************************************** - * - * Public static class data - * - ***********************************************************************/ - FLAC_API const char * const FLAC__StreamEncoderStateString[] = { "FLAC__STREAM_ENCODER_OK", "FLAC__STREAM_ENCODER_UNINITIALIZED", @@ -120882,24 +111079,8 @@ FLAC_API const char * const FLAC__StreamEncoderTellStatusString[] = { "FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED" }; -/* Number of samples that will be overread to watch for end of stream. By - * 'overread', we mean that the FLAC__stream_encoder_process*() calls will - * always try to read blocksize+1 samples before encoding a block, so that - * even if the stream has a total sample count that is an integral multiple - * of the blocksize, we will still notice when we are encoding the last - * block. This is needed, for example, to correctly set the end-of-stream - * marker in Ogg FLAC. - * - * WATCHOUT: some parts of the code assert that OVERREAD_ == 1 and there's - * not really any reason to change it. - */ static const unsigned OVERREAD_ = 1; -/*********************************************************************** - * - * Class constructor/destructor - * - */ FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new(void) { FLAC__StreamEncoder *encoder; @@ -121005,12 +111186,6 @@ FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder) free(encoder); } -/*********************************************************************** - * - * Public class methods - * - ***********************************************************************/ - static FLAC__StreamEncoderInitStatus init_stream_internal_enc( FLAC__StreamEncoder *encoder, FLAC__StreamEncoderReadCallback read_callback, @@ -121075,8 +111250,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( if(encoder->protected_->qlp_coeff_precision == 0) { if(encoder->protected_->bits_per_sample < 16) { - /* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */ - /* @@@ until then we'll make a guess */ encoder->protected_->qlp_coeff_precision = max(FLAC__MIN_QLP_COEFF_PRECISION, 2 + encoder->protected_->bits_per_sample / 2); } else if(encoder->protected_->bits_per_sample == 16) { @@ -121153,7 +111326,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order; #if FLAC__HAS_OGG - /* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */ if(is_ogg && 0 != encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 1) { unsigned i; for(i = 1; i < encoder->protected_->num_metadata_blocks; i++) { @@ -121167,7 +111339,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( } } #endif - /* keep track of any SEEKTABLE block */ if(0 != encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0) { unsigned i; for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) { @@ -121178,7 +111349,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( } } - /* validate metadata */ if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0) return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; metadata_has_seektable = false; @@ -121212,7 +111382,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( if(metadata_picture_has_type1) /* there should only be 1 per stream */ return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA; metadata_picture_has_type1 = true; - /* standard icon must be 32x32 pixel PNG */ if( m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD && ( @@ -121264,8 +111433,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( #ifndef FLAC__INTEGER_ONLY_LIBRARY encoder->private_->loose_mid_side_stereo_frames = (unsigned)((FLAC__double)encoder->protected_->sample_rate * 0.4 / (FLAC__double)encoder->protected_->blocksize + 0.5); #else - /* 26214 is the approximate fixed-point equivalent to 0.4 (0.4 * 2^16) */ - /* sample rate can be up to 655350 Hz, and thus use 20 bits, so we do the multiply÷ by hand */ FLAC__ASSERT(FLAC__MAX_SAMPLE_RATE <= 655350); FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535); FLAC__ASSERT(encoder->protected_->sample_rate <= 655350); @@ -121282,11 +111449,7 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( encoder->private_->use_wide_by_order = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(max(encoder->protected_->max_lpc_order, FLAC__MAX_FIXED_ORDER))+1 > 30); /*@@@ need to use this? */ encoder->private_->use_wide_by_partition = (false); /*@@@ need to set this */ - /* - * get the CPU info and set the function pointers - */ FLAC__cpu_info(&encoder->private_->cpuinfo); - /* first default to the non-asm routines */ #ifndef FLAC__INTEGER_ONLY_LIBRARY encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation; #endif @@ -121296,7 +111459,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide; encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients; #endif - /* now override with asm where appropriate */ #ifndef FLAC__INTEGER_ONLY_LIBRARY # ifndef FLAC__NO_ASM if(encoder->private_->cpuinfo.use_asm) { @@ -121332,12 +111494,10 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( } # endif /* !FLAC__NO_ASM */ #endif /* !FLAC__INTEGER_ONLY_LIBRARY */ - /* finally override based on wide-ness if necessary */ if(encoder->private_->use_wide_by_block) { encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide; } - /* set state to OK; from here on, errors are fatal and we'll override the state then */ encoder->protected_->state = FLAC__STREAM_ENCODER_OK; #if FLAC__HAS_OGG @@ -121356,7 +111516,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( encoder->private_->client_data = client_data; if(!resize_buffers_(encoder, encoder->protected_->blocksize)) { - /* the above function sets the state for us in case of an error */ return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } @@ -121365,14 +111524,7 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } - /* - * Set up the verify stuff if necessary - */ if(encoder->protected_->verify) { - /* - * First, set up the fifo which will hold the - * original signal to compare against - */ encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize+OVERREAD_; for(i = 0; i < encoder->protected_->channels; i++) { if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)safe_malloc_mul_2op_(sizeof(FLAC__int32), /*times*/encoder->private_->verify.input_fifo.size))) { @@ -121382,9 +111534,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( } encoder->private_->verify.input_fifo.tail = 0; - /* - * Now set up a stream decoder for verification - */ encoder->private_->verify.decoder = FLAC__stream_decoder_new(); if(0 == encoder->private_->verify.decoder) { encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR; @@ -121403,19 +111552,12 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( encoder->private_->verify.error_stats.expected = 0; encoder->private_->verify.error_stats.got = 0; - /* - * These must be done before we write any metadata, because that - * calls the write_callback, which uses these values. - */ encoder->private_->first_seekpoint_to_check = 0; encoder->private_->samples_written = 0; encoder->protected_->streaminfo_offset = 0; encoder->protected_->seektable_offset = 0; encoder->protected_->audio_offset = 0; - /* - * write the stream header - */ if(encoder->protected_->verify) encoder->private_->verify.state_hint = ENCODER_IN_MAGIC; if(!FLAC__bitwriter_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN)) { @@ -121423,13 +111565,9 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } if(!write_bitbuffer_(encoder, 0, /*is_last_block=*/false)) { - /* the above function sets the state for us in case of an error */ return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } - /* - * write the STREAMINFO metadata block - */ if(encoder->protected_->verify) encoder->private_->verify.state_hint = ENCODER_IN_METADATA; encoder->private_->streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO; @@ -121451,28 +111589,12 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } if(!write_bitbuffer_(encoder, 0, /*is_last_block=*/false)) { - /* the above function sets the state for us in case of an error */ return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } - /* - * Now that the STREAMINFO block is written, we can init this to an - * absurdly-high value... - */ encoder->private_->streaminfo.data.stream_info.min_framesize = (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN) - 1; - /* ... and clear this to 0 */ encoder->private_->streaminfo.data.stream_info.total_samples = 0; - /* - * Check to see if the supplied metadata contains a VORBIS_COMMENT; - * if not, we will write an empty one (FLAC__add_metadata_block() - * automatically supplies the vendor string). - * - * WATCHOUT: the Ogg FLAC mapping requires us to write this block after - * the STREAMINFO. (In the case that metadata_has_vorbis_comment is - * true it will have already insured that the metadata list is properly - * ordered.) - */ if(!metadata_has_vorbis_comment) { FLAC__StreamMetadata vorbis_comment; vorbis_comment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT; @@ -121487,14 +111609,10 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } if(!write_bitbuffer_(encoder, 0, /*is_last_block=*/false)) { - /* the above function sets the state for us in case of an error */ return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } } - /* - * write the user's metadata blocks - */ for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) { encoder->protected_->metadata[i]->is_last = (i == encoder->protected_->num_metadata_blocks - 1); if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame)) { @@ -121502,12 +111620,10 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_enc( return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } if(!write_bitbuffer_(encoder, 0, /*is_last_block=*/false)) { - /* the above function sets the state for us in case of an error */ return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } } - /* now that all the metadata is written, we save the stream offset */ if(encoder->private_->tell_callback && encoder->private_->tell_callback(encoder, &encoder->protected_->audio_offset, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) { /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */ encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; @@ -121530,13 +111646,13 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_stream( { return init_stream_internal_enc( encoder, - /*read_callback=*/0, +0, write_callback, seek_callback, tell_callback, metadata_callback, client_data, - /*is_ogg=*/false +false ); } @@ -121558,7 +111674,7 @@ FLAC_API FLAC__StreamEncoderInitStatus FLAC__stream_encoder_init_ogg_stream( tell_callback, metadata_callback, client_data, - /*is_ogg=*/true +true ); } @@ -121578,17 +111694,11 @@ static FLAC__StreamEncoderInitStatus init_FILE_internal_enc( if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED; - /* double protection */ if(file == 0) { encoder->protected_->state = FLAC__STREAM_ENCODER_IO_ERROR; return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } - /* - * To make sure that our file does not go unclosed after an error, we - * must assign the FILE pointer before any further error can occur in - * this routine. - */ if(file == stdout) file = get_binary_stdout_(); /* just to be safe */ @@ -121605,12 +111715,11 @@ static FLAC__StreamEncoderInitStatus init_FILE_internal_enc( file_write_callback_, encoder->private_->file == stdout? 0 : file_seek_callback_enc, encoder->private_->file == stdout? 0 : file_tell_callback_enc, - /*metadata_callback=*/0, +0, client_data, is_ogg ); if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) { - /* the above function sets the state for us in case of an error */ return init_status; } @@ -121656,11 +111765,6 @@ static FLAC__StreamEncoderInitStatus init_file_internal_enc( FLAC__ASSERT(0 != encoder); - /* - * To make sure that our file does not go unclosed after an error, we - * have to do the same entrance checks here that are later performed - * in FLAC__stream_encoder_init_FILE() before the FILE* is assigned. - */ if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED; @@ -121727,7 +111831,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder) #endif update_metadata_(encoder); - /* check if an error occurred while updating metadata */ if(encoder->protected_->state != FLAC__STREAM_ENCODER_OK) error = true; } @@ -121770,7 +111873,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_ogg_serial_number(FLAC__StreamEncod if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) return false; #if FLAC__HAS_OGG - /* can't check encoder->private_->is_ogg since that's not set until init time */ FLAC__ogg_encoder_aspect_set_serial_number(&encoder->protected_->ogg_encoder_aspect, value); return true; #else @@ -121857,23 +111959,21 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncod return false; if(value >= sizeof(compression_levels_)/sizeof(compression_levels_[0])) value = sizeof(compression_levels_)/sizeof(compression_levels_[0]) - 1; - ok &= FLAC__stream_encoder_set_do_mid_side_stereo (encoder, compression_levels_[value].do_mid_side_stereo); - ok &= FLAC__stream_encoder_set_loose_mid_side_stereo (encoder, compression_levels_[value].loose_mid_side_stereo); + ok &= FLAC__stream_encoder_set_do_mid_side_stereo (encoder, compression_levels_[value].do_mid_side_stereo); + ok &= FLAC__stream_encoder_set_loose_mid_side_stereo (encoder, compression_levels_[value].loose_mid_side_stereo); #ifndef FLAC__INTEGER_ONLY_LIBRARY #if 0 - /* was: */ - ok &= FLAC__stream_encoder_set_apodization (encoder, compression_levels_[value].apodization); - /* but it's too hard to specify the string in a locale-specific way */ + ok &= FLAC__stream_encoder_set_apodization (encoder, compression_levels_[value].apodization); #else encoder->protected_->num_apodizations = 1; encoder->protected_->apodizations[0].type = FLAC__APODIZATION_TUKEY; encoder->protected_->apodizations[0].parameters.tukey.p = 0.5; #endif #endif - ok &= FLAC__stream_encoder_set_max_lpc_order (encoder, compression_levels_[value].max_lpc_order); - ok &= FLAC__stream_encoder_set_qlp_coeff_precision (encoder, compression_levels_[value].qlp_coeff_precision); - ok &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search (encoder, compression_levels_[value].do_qlp_coeff_prec_search); - ok &= FLAC__stream_encoder_set_do_escape_coding (encoder, compression_levels_[value].do_escape_coding); + ok &= FLAC__stream_encoder_set_max_lpc_order (encoder, compression_levels_[value].max_lpc_order); + ok &= FLAC__stream_encoder_set_qlp_coeff_precision (encoder, compression_levels_[value].qlp_coeff_precision); + ok &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search (encoder, compression_levels_[value].do_qlp_coeff_prec_search); + ok &= FLAC__stream_encoder_set_do_escape_coding (encoder, compression_levels_[value].do_escape_coding); ok &= FLAC__stream_encoder_set_do_exhaustive_model_search (encoder, compression_levels_[value].do_exhaustive_model_search); ok &= FLAC__stream_encoder_set_min_residual_partition_order(encoder, compression_levels_[value].min_residual_partition_order); ok &= FLAC__stream_encoder_set_max_residual_partition_order(encoder, compression_levels_[value].max_residual_partition_order); @@ -121914,7 +112014,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamE return true; } -/*@@@@add to tests*/ FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *encoder, const char *specification) { FLAC__ASSERT(0 != encoder); @@ -122027,7 +112126,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_do_escape_coding(FLAC__StreamEncode if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) return false; #if 0 - /*@@@ deprecated: */ encoder->protected_->do_escape_coding = value; #else (void)value; @@ -122076,7 +112174,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_rice_parameter_search_dist(FLAC__St if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) return false; #if 0 - /*@@@ deprecated: */ encoder->protected_->rice_parameter_search_dist = value; #else (void)value; @@ -122106,7 +112203,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encod num_blocks = 0; if(0 == num_blocks) metadata = 0; - /* realloc() does not do exactly what we want so... */ if(encoder->protected_->metadata) { free(encoder->protected_->metadata); encoder->protected_->metadata = 0; @@ -122127,10 +112223,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encod return true; } -/* - * These three functions are not static, but not publically exposed in - * include/FLAC/ either. They are used by the test suite. - */ FLAC_API FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value) { FLAC__ASSERT(0 != encoder); @@ -122378,7 +112470,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c if(encoder->protected_->do_mid_side_stereo) { FLAC__ASSERT(channels == 2); - /* "i <= blocksize" to overread 1 sample; see comment in OVERREAD_ decl */ for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { encoder->private_->integer_signal_mid_side[1][i] = buffer[0][j] - buffer[1][j]; encoder->private_->integer_signal_mid_side[0][i] = (buffer[0][j] + buffer[1][j]) >> 1; /* NOTE: not the same as 'mid = (buffer[0][j] + buffer[1][j]) / 2' ! */ @@ -122389,13 +112480,11 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, c encoder->private_->current_sample_number += n; - /* we only process if we have a full block + 1 extra sample; final block is always handled by FLAC__stream_encoder_finish() */ if(encoder->private_->current_sample_number > blocksize) { FLAC__ASSERT(encoder->private_->current_sample_number == blocksize+OVERREAD_); FLAC__ASSERT(OVERREAD_ == 1); /* assert we only overread 1 sample which simplifies the rest of the code below */ if(!process_frame_(encoder, /*is_fractional_block=*/false, /*is_last_block=*/false)) return false; - /* move unprocessed overread samples to beginnings of arrays */ for(channel = 0; channel < channels; channel++) encoder->private_->integer_signal[channel][0] = encoder->private_->integer_signal[channel][blocksize]; if(encoder->protected_->do_mid_side_stereo) { @@ -122421,19 +112510,11 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); j = k = 0; - /* - * we have several flavors of the same basic loop, optimized for - * different conditions: - */ if(encoder->protected_->do_mid_side_stereo && channels == 2) { - /* - * stereo coding: unroll channel loop - */ do { if(encoder->protected_->verify) append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize+OVERREAD_-encoder->private_->current_sample_number, samples-j)); - /* "i <= blocksize" to overread 1 sample; see comment in OVERREAD_ decl */ for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { encoder->private_->integer_signal[0][i] = mid = side = buffer[k++]; x = buffer[k++]; @@ -122445,7 +112526,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder encoder->private_->integer_signal_mid_side[0][i] = mid; } encoder->private_->current_sample_number = i; - /* we only process if we have a full block + 1 extra sample; final block is always handled by FLAC__stream_encoder_finish() */ if(i > blocksize) { if(!process_frame_(encoder, /*is_fractional_block=*/false, /*is_last_block=*/false)) return false; @@ -122461,20 +112541,15 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder } while(j < samples); } else { - /* - * independent channel coding: buffer each channel in inner loop - */ do { if(encoder->protected_->verify) append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize+OVERREAD_-encoder->private_->current_sample_number, samples-j)); - /* "i <= blocksize" to overread 1 sample; see comment in OVERREAD_ decl */ for(i = encoder->private_->current_sample_number; i <= blocksize && j < samples; i++, j++) { for(channel = 0; channel < channels; channel++) encoder->private_->integer_signal[channel][i] = buffer[k++]; } encoder->private_->current_sample_number = i; - /* we only process if we have a full block + 1 extra sample; final block is always handled by FLAC__stream_encoder_finish() */ if(i > blocksize) { if(!process_frame_(encoder, /*is_fractional_block=*/false, /*is_last_block=*/false)) return false; @@ -122491,12 +112566,6 @@ FLAC_API FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder return true; } -/*********************************************************************** - * - * Private class methods - * - ***********************************************************************/ - void set_defaults_enc(FLAC__StreamEncoder *encoder) { FLAC__ASSERT(0 != encoder); @@ -122641,18 +112710,11 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize) FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); FLAC__ASSERT(encoder->private_->current_sample_number == 0); - /* To avoid excessive malloc'ing, we only grow the buffer; no shrinking. */ if(new_blocksize <= encoder->private_->input_capacity) return true; ok = true; - /* WATCHOUT: FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx() - * requires that the input arrays (in our case the integer signals) - * have a buffer of up to 3 zeroes in front (at negative indices) for - * alignment purposes; we use 4 in front to keep the data well-aligned. - */ - for(i = 0; ok && i < encoder->protected_->channels; i++) { ok = ok && FLAC__memory_alloc_aligned_int32_array(new_blocksize+4+OVERREAD_, &encoder->private_->integer_signal_unaligned[i], &encoder->private_->integer_signal[i]); memset(encoder->private_->integer_signal[i], 0, sizeof(FLAC__int32)*4); @@ -122692,13 +112754,10 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize) ok = ok && FLAC__memory_alloc_aligned_int32_array(new_blocksize, &encoder->private_->residual_workspace_mid_side_unaligned[channel][i], &encoder->private_->residual_workspace_mid_side[channel][i]); } } - /* the *2 is an approximation to the series 1 + 1/2 + 1/4 + ... that sums tree occupies in a flat array */ - /*@@@ new_blocksize*2 is too pessimistic, but to fix, we need smarter logic because a smaller new_blocksize can actually increase the # of partitions; would require moving this out into a separate function, then checking its capacity against the need of the current blocksize&min/max_partition_order (and maybe predictor order) */ ok = ok && FLAC__memory_alloc_aligned_uint64_array(new_blocksize * 2, &encoder->private_->abs_residual_partition_sums_unaligned, &encoder->private_->abs_residual_partition_sums); if(encoder->protected_->do_escape_coding) ok = ok && FLAC__memory_alloc_aligned_unsigned_array(new_blocksize * 2, &encoder->private_->raw_bits_per_partition_unaligned, &encoder->private_->raw_bits_per_partition); - /* now adjust the windows if the blocksize has changed */ #ifndef FLAC__INTEGER_ONLY_LIBRARY if(ok && new_blocksize != encoder->private_->input_capacity && encoder->protected_->max_lpc_order > 0) { for(i = 0; ok && i < encoder->protected_->num_apodizations; i++) { @@ -122750,7 +112809,6 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize) break; default: FLAC__ASSERT(0); - /* double protection */ FLAC__window_hann(encoder->private_->window[i], new_blocksize); break; } @@ -122818,15 +112876,11 @@ FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const FLAC__StreamEncoderWriteStatus status; FLAC__uint64 output_position = 0; - /* FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED just means we didn't get the offset; no error */ if(encoder->private_->tell_callback && encoder->private_->tell_callback(encoder, &output_position, encoder->private_->client_data) == FLAC__STREAM_ENCODER_TELL_STATUS_ERROR) { encoder->protected_->state = FLAC__STREAM_ENCODER_CLIENT_ERROR; return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; } - /* - * Watch for the STREAMINFO block and first SEEKTABLE block to go by and store their offsets. - */ if(samples == 0) { FLAC__MetadataType type = (FLAC__MetadataType) (buffer[0] & 0x7f); if(type == FLAC__METADATA_TYPE_STREAMINFO) @@ -122835,11 +112889,6 @@ FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const encoder->protected_->seektable_offset = output_position; } - /* - * Mark the current seek point if hit (if audio_offset == 0 that - * means we're still writing metadata and haven't hit the first - * frame yet) - */ if(0 != encoder->private_->seek_table && encoder->protected_->audio_offset > 0 && encoder->private_->seek_table->num_points > 0) { const unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder); const FLAC__uint64 frame_first_sample = encoder->private_->samples_written; @@ -122856,12 +112905,6 @@ FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const encoder->private_->seek_table->points[i].stream_offset = output_position - encoder->protected_->audio_offset; encoder->private_->seek_table->points[i].frame_samples = blocksize; encoder->private_->first_seekpoint_to_check++; - /* DO NOT: "break;" and here's why: - * The seektable template may contain more than one target - * sample for any given frame; we will keep looping, generating - * duplicate seekpoints for them, and we'll clean it up later, - * just before writing the seektable back to the metadata. - */ } else { encoder->private_->first_seekpoint_to_check++; @@ -122890,10 +112933,6 @@ FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { encoder->private_->bytes_written += bytes; encoder->private_->samples_written += samples; - /* we keep a high watermark on the number of frames written because - * when the encoder goes back to write metadata, 'current_frame' - * will drop back to 0. - */ encoder->private_->frames_written = max(encoder->private_->frames_written, encoder->private_->current_frame_number+1); } else @@ -122902,7 +112941,6 @@ FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const return status; } -/* Gets called when the encoding process has finished so that we can update the STREAMINFO and SEEKTABLE blocks. */ void update_metadata_(const FLAC__StreamEncoder *encoder) { FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)]; @@ -122915,14 +112953,6 @@ void update_metadata_(const FLAC__StreamEncoder *encoder) FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO); - /* All this is based on intimate knowledge of the stream header - * layout, but a change to the header format that would break this - * would also break all streams encoded in the previous format. - */ - - /* - * Write MD5 signature - */ { const unsigned md5_offset = FLAC__STREAM_METADATA_HEADER_LENGTH + @@ -122948,9 +112978,6 @@ void update_metadata_(const FLAC__StreamEncoder *encoder) } } - /* - * Write total samples - */ { const unsigned total_samples_byte_offset = FLAC__STREAM_METADATA_HEADER_LENGTH + @@ -122981,9 +113008,6 @@ void update_metadata_(const FLAC__StreamEncoder *encoder) } } - /* - * Write min/max framesize - */ { const unsigned min_framesize_offset = FLAC__STREAM_METADATA_HEADER_LENGTH + @@ -123009,9 +113033,6 @@ void update_metadata_(const FLAC__StreamEncoder *encoder) } } - /* - * Write seektable - */ if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) { unsigned i; @@ -123058,10 +113079,8 @@ void update_metadata_(const FLAC__StreamEncoder *encoder) } #if FLAC__HAS_OGG -/* Gets called when the encoding process has finished so that we can update the STREAMINFO and SEEKTABLE blocks. */ void update_ogg_metadata_(FLAC__StreamEncoder *encoder) { - /* the # of bytes in the 1st packet that precede the STREAMINFO */ static const unsigned FIRST_OGG_PACKET_STREAMINFO_PREFIX_LENGTH = FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH + FLAC__OGG_MAPPING_MAGIC_LENGTH + @@ -123080,29 +113099,15 @@ void update_ogg_metadata_(FLAC__StreamEncoder *encoder) FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO); FLAC__ASSERT(0 != encoder->private_->seek_callback); - /* Pre-check that client supports seeking, since we don't want the - * ogg_helper code to ever have to deal with this condition. - */ if(encoder->private_->seek_callback(encoder, 0, encoder->private_->client_data) == FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED) return; - /* All this is based on intimate knowledge of the stream header - * layout, but a change to the header format that would break this - * would also break all streams encoded in the previous format. - */ - - /** - ** Write STREAMINFO stats - **/ simple_ogg_page__init(&page); if(!simple_ogg_page__get_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data)) { simple_ogg_page__clear(&page); return; /* state already set */ } - /* - * Write MD5 signature - */ { const unsigned md5_offset = FIRST_OGG_PACKET_STREAMINFO_PREFIX_LENGTH + @@ -123126,9 +113131,6 @@ void update_ogg_metadata_(FLAC__StreamEncoder *encoder) memcpy(page.body + md5_offset, metadata->data.stream_info.md5sum, 16); } - /* - * Write total samples - */ { const unsigned total_samples_byte_offset = FIRST_OGG_PACKET_STREAMINFO_PREFIX_LENGTH + @@ -123158,9 +113160,6 @@ void update_ogg_metadata_(FLAC__StreamEncoder *encoder) memcpy(page.body + total_samples_byte_offset, b, 5); } - /* - * Write min/max framesize - */ { const unsigned min_framesize_offset = FIRST_OGG_PACKET_STREAMINFO_PREFIX_LENGTH + @@ -123189,9 +113188,6 @@ void update_ogg_metadata_(FLAC__StreamEncoder *encoder) } simple_ogg_page__clear(&page); - /* - * Write seektable - */ if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) { unsigned i; FLAC__byte *p; @@ -123253,33 +113249,20 @@ FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional FLAC__uint16 crc; FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); - /* - * Accumulate raw signal to the MD5 signature - */ if(encoder->protected_->do_md5 && !FLAC__MD5Accumulate(&encoder->private_->md5context, (const FLAC__int32 * const *)encoder->private_->integer_signal, encoder->protected_->channels, encoder->protected_->blocksize, (encoder->protected_->bits_per_sample+7) / 8)) { encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; return false; } - /* - * Process the frame header and subframes into the frame bitbuffer - */ if(!process_subframes_(encoder, is_fractional_block)) { - /* the above function sets the state for us in case of an error */ return false; } - /* - * Zero-pad the frame to a byte_boundary - */ if(!FLAC__bitwriter_zero_pad_to_byte_boundary(encoder->private_->frame)) { encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; return false; } - /* - * CRC-16 the whole thing - */ FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(encoder->private_->frame)); if( !FLAC__bitwriter_get_write_crc16(encoder->private_->frame, &crc) || @@ -123289,17 +113272,10 @@ FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional return false; } - /* - * Write it - */ if(!write_bitbuffer_(encoder, encoder->protected_->blocksize, is_last_block)) { - /* the above function sets the state for us in case of an error */ return false; } - /* - * Get ready for the next frame - */ encoder->private_->current_sample_number = 0; encoder->private_->current_frame_number++; encoder->private_->streaminfo.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize; @@ -123313,9 +113289,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti unsigned channel, min_partition_order = encoder->protected_->min_residual_partition_order, max_partition_order; FLAC__bool do_independent, do_mid_side; - /* - * Calculate the min,max Rice partition orders - */ if(is_fractional_block) { max_partition_order = 0; } @@ -123325,9 +113298,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti } min_partition_order = min(min_partition_order, max_partition_order); - /* - * Setup the frame - */ frame_header.blocksize = encoder->protected_->blocksize; frame_header.sample_rate = encoder->protected_->sample_rate; frame_header.channels = encoder->protected_->channels; @@ -123336,9 +113306,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti frame_header.number_type = FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER; frame_header.number.frame_number = encoder->private_->current_frame_number; - /* - * Figure out what channel assignments to try - */ if(encoder->protected_->do_mid_side_stereo) { if(encoder->protected_->loose_mid_side_stereo) { if(encoder->private_->loose_mid_side_stereo_frame_count == 0) { @@ -123362,9 +113329,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti FLAC__ASSERT(do_independent || do_mid_side); - /* - * Check for wasted bits; set effective bps for each subframe - */ if(do_independent) { for(channel = 0; channel < encoder->protected_->channels; channel++) { const unsigned w = get_wasted_bits_(encoder->private_->integer_signal[channel], encoder->protected_->blocksize); @@ -123381,9 +113345,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti } } - /* - * First do a normal encoding pass of each independent channel - */ if(do_independent) { for(channel = 0; channel < encoder->protected_->channels; channel++) { if(! @@ -123405,9 +113366,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti } } - /* - * Now do mid and side channels if requested - */ if(do_mid_side) { FLAC__ASSERT(encoder->protected_->channels == 2); @@ -123431,9 +113389,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti } } - /* - * Compose the frame bitbuffer - */ if(do_mid_side) { unsigned left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */ FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */ @@ -123452,13 +113407,12 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT == 0); FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE == 1); FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE == 2); - FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_MID_SIDE == 3); + FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_MID_SIDE == 3); FLAC__ASSERT(do_independent && do_mid_side); - /* We have to figure out which channel assignent results in the smallest frame */ - bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits [1]; - bits[FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE ] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits_mid_side[1]; - bits[FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE ] = encoder->private_->best_subframe_bits [1] + encoder->private_->best_subframe_bits_mid_side[1]; + bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits [1]; + bits[FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE ] = encoder->private_->best_subframe_bits [0] + encoder->private_->best_subframe_bits_mid_side[1]; + bits[FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE ] = encoder->private_->best_subframe_bits [1] + encoder->private_->best_subframe_bits_mid_side[1]; bits[FLAC__CHANNEL_ASSIGNMENT_MID_SIDE ] = encoder->private_->best_subframe_bits_mid_side[0] + encoder->private_->best_subframe_bits_mid_side[1]; channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; @@ -123480,16 +113434,16 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti switch(channel_assignment) { case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: - left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]]; - right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]]; + left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]]; + right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]]; break; case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: - left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]]; + left_subframe = &encoder->private_->subframe_workspace [0][encoder->private_->best_subframe [0]]; right_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]]; break; case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: left_subframe = &encoder->private_->subframe_workspace_mid_side[1][encoder->private_->best_subframe_mid_side[1]]; - right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]]; + right_subframe = &encoder->private_->subframe_workspace [1][encoder->private_->best_subframe [1]]; break; case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: left_subframe = &encoder->private_->subframe_workspace_mid_side[0][encoder->private_->best_subframe_mid_side[0]]; @@ -123501,16 +113455,16 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti switch(channel_assignment) { case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT: - left_bps = encoder->private_->subframe_bps [0]; - right_bps = encoder->private_->subframe_bps [1]; + left_bps = encoder->private_->subframe_bps [0]; + right_bps = encoder->private_->subframe_bps [1]; break; case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE: - left_bps = encoder->private_->subframe_bps [0]; + left_bps = encoder->private_->subframe_bps [0]; right_bps = encoder->private_->subframe_bps_mid_side[1]; break; case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE: left_bps = encoder->private_->subframe_bps_mid_side[1]; - right_bps = encoder->private_->subframe_bps [1]; + right_bps = encoder->private_->subframe_bps [1]; break; case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE: left_bps = encoder->private_->subframe_bps_mid_side[0]; @@ -123520,7 +113474,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti FLAC__ASSERT(0); } - /* note that encoder_add_subframe_ sets the state for us in case of an error */ if(!add_subframe_(encoder, frame_header.blocksize, left_bps , left_subframe , encoder->private_->frame)) return false; if(!add_subframe_(encoder, frame_header.blocksize, right_bps, right_subframe, encoder->private_->frame)) @@ -123534,7 +113487,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti for(channel = 0; channel < encoder->protected_->channels; channel++) { if(!add_subframe_(encoder, frame_header.blocksize, encoder->private_->subframe_bps[channel], &encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]], encoder->private_->frame)) { - /* the above function sets the state for us in case of an error */ return false; } } @@ -123581,12 +113533,10 @@ FLAC__bool process_subframe_( unsigned rice_parameter; unsigned _candidate_bits, _best_bits; unsigned _best_subframe; - /* only use RICE2 partitions if stream bps > 16 */ const unsigned rice_parameter_limit = FLAC__stream_encoder_get_bits_per_sample(encoder) > 16? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER; FLAC__ASSERT(frame_header->blocksize > 0); - /* verbatim subframe is the baseline against which we measure other compressed subframes */ _best_subframe = 0; if(encoder->private_->disable_verbatim_subframes && frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) _best_bits = UINT_MAX; @@ -123596,7 +113546,6 @@ FLAC__bool process_subframe_( if(frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) { unsigned signal_is_constant = false; guess_fixed_order = encoder->private_->local_fixed_compute_best_predictor(integer_signal+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample); - /* check for constant subframe */ if( !encoder->private_->disable_constant_subframes && #ifndef FLAC__INTEGER_ONLY_LIBRARY @@ -123605,7 +113554,6 @@ FLAC__bool process_subframe_( fixed_residual_bits_per_sample[1] == FLAC__FP_ZERO #endif ) { - /* the above means it's possible all samples are the same value; now double-check it: */ unsigned i; signal_is_constant = true; for(i = 1; i < frame_header->blocksize; i++) { @@ -123624,7 +113572,6 @@ FLAC__bool process_subframe_( } else { if(!encoder->private_->disable_fixed_subframes || (encoder->protected_->max_lpc_order == 0 && _best_bits == UINT_MAX)) { - /* encode fixed */ if(encoder->protected_->do_exhaustive_model_search) { min_fixed_order = 0; max_fixed_order = FLAC__MAX_FIXED_ORDER; @@ -123678,7 +113625,6 @@ FLAC__bool process_subframe_( } #ifndef FLAC__INTEGER_ONLY_LIBRARY - /* encode lpc */ if(encoder->protected_->max_lpc_order > 0) { if(encoder->protected_->max_lpc_order >= frame_header->blocksize) max_lpc_order = frame_header->blocksize-1; @@ -123689,7 +113635,6 @@ FLAC__bool process_subframe_( for (a = 0; a < encoder->protected_->num_apodizations; a++) { FLAC__lpc_window_data(integer_signal, encoder->private_->window[a], encoder->private_->windowed_signal, frame_header->blocksize); encoder->private_->local_lpc_compute_autocorrelation(encoder->private_->windowed_signal, frame_header->blocksize, max_lpc_order+1, autoc); - /* if autoc[0] == 0.0, the signal is constant and we usually won't get here, but it can happen */ if(autoc[0] != 0.0) { FLAC__lpc_compute_lp_coefficients(autoc, &max_lpc_order, encoder->private_->lp_coeff, lpc_error); if(encoder->protected_->do_exhaustive_model_search) { @@ -123725,7 +113670,6 @@ FLAC__bool process_subframe_( } if(encoder->protected_->do_qlp_coeff_prec_search) { min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION; - /* try to ensure a 32-bit datapath throughout for 16bps(+1bps for side channel) or less */ if(subframe_bps <= 17) { max_qlp_coeff_precision = min(32 - subframe_bps - lpc_order, FLAC__MAX_QLP_COEFF_PRECISION); max_qlp_coeff_precision = max(max_qlp_coeff_precision, min_qlp_coeff_precision); @@ -123774,7 +113718,6 @@ FLAC__bool process_subframe_( } } - /* under rare circumstances this can happen when all but lpc subframe types are disabled: */ if(_best_bits == UINT_MAX) { FLAC__ASSERT(_best_subframe == 0); _best_bits = evaluate_verbatim_subframe_(encoder, integer_signal, frame_header->blocksize, subframe_bps, subframe[_best_subframe]); @@ -123968,7 +113911,6 @@ unsigned evaluate_lpc_subframe_( int quantization, ret; const unsigned residual_samples = blocksize - order; - /* try to keep qlp coeff precision such that only 32-bit math is required for decode of <=16bps streams */ if(subframe_bps <= 16) { FLAC__ASSERT(order > 0); FLAC__ASSERT(order <= FLAC__MAX_LPC_ORDER); @@ -124122,23 +114064,13 @@ unsigned find_best_partition_order_( best_ecm->data.partitioned_rice.order = best_partition_order; { - /* - * We are allowed to de-const the pointer based on our special - * knowledge; it is const to the outside world. - */ FLAC__EntropyCodingMethod_PartitionedRiceContents* prc = (FLAC__EntropyCodingMethod_PartitionedRiceContents*)best_ecm->data.partitioned_rice.contents; unsigned partition; - /* save best parameters and raw_bits */ FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(prc, max(6, best_partition_order)); memcpy(prc->parameters, private_->partitioned_rice_contents_extra[best_parameters_index].parameters, sizeof(unsigned)*(1<<(best_partition_order))); if(do_escape_coding) memcpy(prc->raw_bits, private_->partitioned_rice_contents_extra[best_parameters_index].raw_bits, sizeof(unsigned)*(1<<(best_partition_order))); - /* - * Now need to check if the type should be changed to - * FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 based on the - * size of the rice parameters. - */ for(partition = 0; partition < (1u<parameters[partition] >= FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER) { best_ecm->type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2; @@ -124177,19 +114109,14 @@ void precompute_partition_info_sums_( FLAC__ASSERT(default_partition_samples > predictor_order); #if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && defined FLAC__HAS_NASM - /* slightly pessimistic but still catches all common cases */ - /* WATCHOUT: "+ bps" is an assumption that the average residual magnitude will not be more than "bps" bits */ if(FLAC__bitmath_ilog2(default_partition_samples) + bps < 32) { precompute_partition_info_sums_32bit_asm_ia32_(residual, abs_residual_partition_sums, residual_samples + predictor_order, predictor_order, min_partition_order, max_partition_order); return; } #endif - /* first do max_partition_order */ { unsigned partition, residual_sample, end = (unsigned)(-(int)predictor_order); - /* slightly pessimistic but still catches all common cases */ - /* WATCHOUT: "+ bps" is an assumption that the average residual magnitude will not be more than "bps" bits */ if(FLAC__bitmath_ilog2(default_partition_samples) + bps < 32) { FLAC__uint32 abs_residual_partition_sum; @@ -124214,7 +114141,6 @@ void precompute_partition_info_sums_( } } - /* now merge partitions for lower orders */ { unsigned from_partition = 0, to_partition = partitions; int partition_order; @@ -124244,7 +114170,6 @@ void precompute_partition_info_escapes_( unsigned from_partition, to_partition = 0; const unsigned blocksize = residual_samples + predictor_order; - /* first do max_partition_order */ for(partition_order = (int)max_partition_order; partition_order >= 0; partition_order--) { FLAC__int32 r; FLAC__uint32 rmax; @@ -124261,20 +114186,17 @@ void precompute_partition_info_escapes_( rmax = 0; for(partition_sample = 0; partition_sample < partition_samples; partition_sample++) { r = residual[residual_sample++]; - /* OPT: maybe faster: rmax |= r ^ (r>>31) */ if(r < 0) rmax |= ~r; else rmax |= r; } - /* now we know all residual values are in the range [-rmax-1,rmax] */ raw_bits_per_partition[partition] = rmax? FLAC__bitmath_ilog2(rmax) + 2 : 1; } to_partition = partitions; break; /*@@@ yuck, should remove the 'for' loop instead */ } - /* now merge partitions for lower orders */ for(from_partition = 0, --partition_order; partition_order >= (int)min_partition_order; partition_order--) { unsigned m; unsigned i; @@ -124320,12 +114242,6 @@ static FLaC__INLINE unsigned count_rice_bits_in_partition_( : (unsigned)(abs_residual_partition_sum << 1) /* can't shift by negative number, so reverse */ ) - (partition_samples >> 1) - /* -(partition_samples>>1) to subtract out extra contributions to the abs_residual_partition_sum. - * The actual number of bits used is closer to the sum(for all i in the partition) of abs(residual[i])>>(rice_parameter-1) - * By using the abs_residual_partition sum, we also add in bits in the LSBs that would normally be shifted out. - * So the subtraction term tries to guess how many extra bits were contributed. - * If the LSBs are randomly distributed, this should average to 0.5 extra bits per sample. - */ ; } #endif @@ -124426,14 +114342,6 @@ FLAC__bool set_partitioned_rice_( partition_samples -= predictor_order; } mean = abs_residual_partition_sums[partition]; - /* we are basically calculating the size in bits of the - * average residual magnitude in the partition: - * rice_parameter = floor(log2(mean/partition_samples)) - * 'mean' is not a good name for the variable, it is - * actually the sum of magnitudes of all residual values - * in the partition, so the actual mean is - * mean/partition_samples - */ for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1) ; if(rice_parameter >= rice_parameter_limit) { @@ -124562,10 +114470,6 @@ FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *d } else { if(encoded_bytes == 0) { - /* - * If we get here, a FIFO underflow has occurred, - * which means there is a bug somewhere. - */ FLAC__ASSERT(0); return FLAC__STREAM_DECODER_READ_STATUS_ABORT; } @@ -124614,7 +114518,6 @@ FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } } - /* dequeue the frame from the fifo */ encoder->private_->verify.input_fifo.tail -= blocksize; FLAC__ASSERT(encoder->private_->verify.input_fifo.tail <= OVERREAD_); for(channel = 0; channel < channels; channel++) @@ -124694,22 +114597,11 @@ FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *e if(local__fwrite(buffer, sizeof(FLAC__byte), bytes, encoder->private_->file) == bytes) { FLAC__bool call_it = 0 != encoder->private_->progress_callback && ( #if FLAC__HAS_OGG - /* We would like to be able to use 'samples > 0' in the - * clause here but currently because of the nature of our - * Ogg writing implementation, 'samples' is always 0 (see - * ogg_encoder_aspect.c). The downside is extra progress - * callbacks. - */ encoder->private_->is_ogg? true : #endif samples > 0 ); if(call_it) { - /* NOTE: We have to add +bytes, +samples, and +1 to the stats - * because at this point in the callback chain, the stats - * have not been updated. Only after we return and control - * gets back to write_frame_() are the stats updated - */ encoder->private_->progress_callback(encoder, encoder->private_->bytes_written+bytes, encoder->private_->samples_written+samples, encoder->private_->frames_written+(samples?1:0), encoder->private_->total_frames_estimate, encoder->private_->client_data); } return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; @@ -124718,19 +114610,11 @@ FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *e return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; } -/* - * This will forcibly set stdout to binary mode (for OSes that require it) - */ FILE *get_binary_stdout_(void) { - /* if something breaks here it is probably due to the presence or - * absence of an underscore before the identifiers 'setmode', - * 'fileno', and/or 'O_BINARY'; check your system header files. - */ #if defined _MSC_VER || defined __MINGW32__ _setmode(_fileno(stdout), _O_BINARY); #elif defined __CYGWIN__ - /* almost certainly not needed for any modern Cygwin, but let's be safe... */ setmode(_fileno(stdout), _O_BINARY); #elif defined __EMX__ setmode(fileno(stdout), O_BINARY); @@ -124789,9 +114673,6 @@ FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__ if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->type, FLAC__STREAM_METADATA_TYPE_LEN)) return false; - /* - * First, for VORBIS_COMMENTs, adjust the length to reflect our vendor string - */ i = metadata->length; if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { FLAC__ASSERT(metadata->data.vorbis_comment.vendor_string.length == 0 || 0 != metadata->data.vorbis_comment.vendor_string.entry); @@ -124964,7 +114845,6 @@ FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWrit return false; FLAC__ASSERT(header->blocksize > 0 && header->blocksize <= FLAC__MAX_BLOCK_SIZE); - /* when this assertion holds true, any legal blocksize can be expressed in the frame header */ FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535u); blocksize_hint = 0; switch(header->blocksize) { @@ -125085,7 +114965,6 @@ FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWrit break; } - /* write the CRC */ if(!FLAC__bitwriter_get_write_crc8(bw, &crc)) return false; if(!FLAC__bitwriter_write_raw_uint32(bw, crc, FLAC__FRAME_HEADER_CRC_LEN)) @@ -125134,7 +115013,7 @@ FLAC__bool FLAC__subframe_add_fixed(const FLAC__Subframe_Fixed *subframe, unsign subframe->entropy_coding_method.data.partitioned_rice.contents->parameters, subframe->entropy_coding_method.data.partitioned_rice.contents->raw_bits, subframe->entropy_coding_method.data.partitioned_rice.order, - /*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 +subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 )) return false; break; @@ -125180,7 +115059,7 @@ FLAC__bool FLAC__subframe_add_lpc(const FLAC__Subframe_LPC *subframe, unsigned r subframe->entropy_coding_method.data.partitioned_rice.contents->parameters, subframe->entropy_coding_method.data.partitioned_rice.contents->raw_bits, subframe->entropy_coding_method.data.partitioned_rice.order, - /*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 +subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2 )) return false; break; @@ -125316,7 +115195,6 @@ FLAC__bool add_residual_partitioned_rice_(FLAC__BitWriter *bw, const FLAC__int32 #ifndef FLAC__INTEGER_ONLY_LIBRARY #ifndef M_PI -/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ #define M_PI 3.14159265358979323846 #endif @@ -125357,7 +115235,6 @@ void FLAC__window_blackman(FLAC__real *window, const FLAC__int32 L) window[n] = (FLAC__real)(0.42f - 0.5f * cos(2.0f * M_PI * n / N) + 0.08f * cos(4.0f * M_PI * n / N)); } -/* 4-term -92dB side-lobe */ void FLAC__window_blackman_harris_4term_92db_sidelobe(FLAC__real *window, const FLAC__int32 L) { const FLAC__int32 N = L - 1; @@ -125472,9 +115349,7 @@ void FLAC__window_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__rea else { const FLAC__int32 Np = (FLAC__int32)(p / 2.0f * L) - 1; FLAC__int32 n; - /* start with rectangle... */ FLAC__window_rectangle(window, L); - /* ...replace ends with hann */ if (Np > 0) { for (n = 0; n <= Np; n++) { window[n] = (FLAC__real)(0.5f - 0.5f * cos(M_PI * n / Np)); @@ -125519,388 +115394,388 @@ static const tchar* const flacExtensions[] = { T(".flac"), 0 }; class FlacReader : public AudioFormatReader { - FLAC__StreamDecoder* decoder; - AudioSampleBuffer reservoir; - int reservoirStart, samplesInReservoir; - bool ok, scanningForLength; + FLAC__StreamDecoder* decoder; + AudioSampleBuffer reservoir; + int reservoirStart, samplesInReservoir; + bool ok, scanningForLength; public: - FlacReader (InputStream* const in) - : AudioFormatReader (in, TRANS (flacFormatName)), - reservoir (2, 0), - reservoirStart (0), - samplesInReservoir (0), - scanningForLength (false) - { - using namespace FlacNamespace; - lengthInSamples = 0; + FlacReader (InputStream* const in) + : AudioFormatReader (in, TRANS (flacFormatName)), + reservoir (2, 0), + reservoirStart (0), + samplesInReservoir (0), + scanningForLength (false) + { + using namespace FlacNamespace; + lengthInSamples = 0; - decoder = FLAC__stream_decoder_new(); + decoder = FLAC__stream_decoder_new(); - ok = FLAC__stream_decoder_init_stream (decoder, - readCallback_, seekCallback_, tellCallback_, lengthCallback_, - eofCallback_, writeCallback_, metadataCallback_, errorCallback_, - (void*) this) == FLAC__STREAM_DECODER_INIT_STATUS_OK; + ok = FLAC__stream_decoder_init_stream (decoder, + readCallback_, seekCallback_, tellCallback_, lengthCallback_, + eofCallback_, writeCallback_, metadataCallback_, errorCallback_, + (void*) this) == FLAC__STREAM_DECODER_INIT_STATUS_OK; - if (ok) - { - FLAC__stream_decoder_process_until_end_of_metadata (decoder); + if (ok) + { + FLAC__stream_decoder_process_until_end_of_metadata (decoder); - if (lengthInSamples == 0 && sampleRate > 0) - { - // the length hasn't been stored in the metadata, so we'll need to - // work it out the length the hard way, by scanning the whole file.. - scanningForLength = true; - FLAC__stream_decoder_process_until_end_of_stream (decoder); - scanningForLength = false; - const int64 tempLength = lengthInSamples; + if (lengthInSamples == 0 && sampleRate > 0) + { + // the length hasn't been stored in the metadata, so we'll need to + // work it out the length the hard way, by scanning the whole file.. + scanningForLength = true; + FLAC__stream_decoder_process_until_end_of_stream (decoder); + scanningForLength = false; + const int64 tempLength = lengthInSamples; - FLAC__stream_decoder_reset (decoder); - FLAC__stream_decoder_process_until_end_of_metadata (decoder); - lengthInSamples = tempLength; - } - } - } + FLAC__stream_decoder_reset (decoder); + FLAC__stream_decoder_process_until_end_of_metadata (decoder); + lengthInSamples = tempLength; + } + } + } - ~FlacReader() - { - FLAC__stream_decoder_delete (decoder); - } + ~FlacReader() + { + FLAC__stream_decoder_delete (decoder); + } - void useMetadata (const FLAC__StreamMetadata_StreamInfo& info) - { - sampleRate = info.sample_rate; - bitsPerSample = info.bits_per_sample; - lengthInSamples = (unsigned int) info.total_samples; - numChannels = info.channels; + void useMetadata (const FLAC__StreamMetadata_StreamInfo& info) + { + sampleRate = info.sample_rate; + bitsPerSample = info.bits_per_sample; + lengthInSamples = (unsigned int) info.total_samples; + numChannels = info.channels; - reservoir.setSize (numChannels, 2 * info.max_blocksize, false, false, true); - } + reservoir.setSize (numChannels, 2 * info.max_blocksize, false, false, true); + } - // returns the number of samples read - bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples) - { - using namespace FlacNamespace; + // returns the number of samples read + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) + { + using namespace FlacNamespace; - if (! ok) - return false; + if (! ok) + return false; - while (numSamples > 0) - { - if (startSampleInFile >= reservoirStart - && startSampleInFile < reservoirStart + samplesInReservoir) - { - const int num = (int) jmin ((int64) numSamples, - reservoirStart + samplesInReservoir - startSampleInFile); + while (numSamples > 0) + { + if (startSampleInFile >= reservoirStart + && startSampleInFile < reservoirStart + samplesInReservoir) + { + const int num = (int) jmin ((int64) numSamples, + reservoirStart + samplesInReservoir - startSampleInFile); - jassert (num > 0); + jassert (num > 0); - for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;) - if (destSamples[i] != 0) - memcpy (destSamples[i] + startOffsetInDestBuffer, - reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)), - sizeof (int) * num); + for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;) + if (destSamples[i] != 0) + memcpy (destSamples[i] + startOffsetInDestBuffer, + reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)), + sizeof (int) * num); - startOffsetInDestBuffer += num; - startSampleInFile += num; - numSamples -= num; - } - else - { - if (startSampleInFile >= (int) lengthInSamples) - { - samplesInReservoir = 0; - } - else if (startSampleInFile < reservoirStart - || startSampleInFile > reservoirStart + jmax (samplesInReservoir, 511)) - { - // had some problems with flac crashing if the read pos is aligned more - // accurately than this. Probably fixed in newer versions of the library, though. - reservoirStart = (int) (startSampleInFile & ~511); - samplesInReservoir = 0; - FLAC__stream_decoder_seek_absolute (decoder, (FLAC__uint64) reservoirStart); - } - else - { - reservoirStart += samplesInReservoir; - samplesInReservoir = 0; - FLAC__stream_decoder_process_single (decoder); - } + startOffsetInDestBuffer += num; + startSampleInFile += num; + numSamples -= num; + } + else + { + if (startSampleInFile >= (int) lengthInSamples) + { + samplesInReservoir = 0; + } + else if (startSampleInFile < reservoirStart + || startSampleInFile > reservoirStart + jmax (samplesInReservoir, 511)) + { + // had some problems with flac crashing if the read pos is aligned more + // accurately than this. Probably fixed in newer versions of the library, though. + reservoirStart = (int) (startSampleInFile & ~511); + samplesInReservoir = 0; + FLAC__stream_decoder_seek_absolute (decoder, (FLAC__uint64) reservoirStart); + } + else + { + reservoirStart += samplesInReservoir; + samplesInReservoir = 0; + FLAC__stream_decoder_process_single (decoder); + } - if (samplesInReservoir == 0) - break; - } - } + if (samplesInReservoir == 0) + break; + } + } - if (numSamples > 0) - { - for (int i = numDestChannels; --i >= 0;) - if (destSamples[i] != 0) - zeromem (destSamples[i] + startOffsetInDestBuffer, - sizeof (int) * numSamples); - } + if (numSamples > 0) + { + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); + } - return true; - } + return true; + } - void useSamples (const FLAC__int32* const buffer[], int numSamples) - { - if (scanningForLength) - { - lengthInSamples += numSamples; - } - else - { - if (numSamples > reservoir.getNumSamples()) - reservoir.setSize (numChannels, numSamples, false, false, true); + void useSamples (const FLAC__int32* const buffer[], int numSamples) + { + if (scanningForLength) + { + lengthInSamples += numSamples; + } + else + { + if (numSamples > reservoir.getNumSamples()) + reservoir.setSize (numChannels, numSamples, false, false, true); - const int bitsToShift = 32 - bitsPerSample; + const int bitsToShift = 32 - bitsPerSample; - for (int i = 0; i < (int) numChannels; ++i) - { - const FLAC__int32* src = buffer[i]; + for (int i = 0; i < (int) numChannels; ++i) + { + const FLAC__int32* src = buffer[i]; - int n = i; - while (src == 0 && n > 0) - src = buffer [--n]; + int n = i; + while (src == 0 && n > 0) + src = buffer [--n]; - if (src != 0) - { - int* dest = (int*) reservoir.getSampleData(i); + if (src != 0) + { + int* dest = (int*) reservoir.getSampleData(i); - for (int j = 0; j < numSamples; ++j) - dest[j] = src[j] << bitsToShift; - } - } + for (int j = 0; j < numSamples; ++j) + dest[j] = src[j] << bitsToShift; + } + } - samplesInReservoir = numSamples; - } - } + samplesInReservoir = numSamples; + } + } - static FLAC__StreamDecoderReadStatus readCallback_ (const FLAC__StreamDecoder*, FLAC__byte buffer[], size_t* bytes, void* client_data) - { - *bytes = (unsigned int) ((const FlacReader*) client_data)->input->read (buffer, (int) *bytes); - return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; - } + static FLAC__StreamDecoderReadStatus readCallback_ (const FLAC__StreamDecoder*, FLAC__byte buffer[], size_t* bytes, void* client_data) + { + *bytes = (unsigned int) ((const FlacReader*) client_data)->input->read (buffer, (int) *bytes); + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } - static FLAC__StreamDecoderSeekStatus seekCallback_ (const FLAC__StreamDecoder*, FLAC__uint64 absolute_byte_offset, void* client_data) - { - ((const FlacReader*) client_data)->input->setPosition ((int) absolute_byte_offset); - return FLAC__STREAM_DECODER_SEEK_STATUS_OK; - } + static FLAC__StreamDecoderSeekStatus seekCallback_ (const FLAC__StreamDecoder*, FLAC__uint64 absolute_byte_offset, void* client_data) + { + ((const FlacReader*) client_data)->input->setPosition ((int) absolute_byte_offset); + return FLAC__STREAM_DECODER_SEEK_STATUS_OK; + } - static FLAC__StreamDecoderTellStatus tellCallback_ (const FLAC__StreamDecoder*, FLAC__uint64* absolute_byte_offset, void* client_data) - { - *absolute_byte_offset = ((const FlacReader*) client_data)->input->getPosition(); - return FLAC__STREAM_DECODER_TELL_STATUS_OK; - } + static FLAC__StreamDecoderTellStatus tellCallback_ (const FLAC__StreamDecoder*, FLAC__uint64* absolute_byte_offset, void* client_data) + { + *absolute_byte_offset = ((const FlacReader*) client_data)->input->getPosition(); + return FLAC__STREAM_DECODER_TELL_STATUS_OK; + } - static FLAC__StreamDecoderLengthStatus lengthCallback_ (const FLAC__StreamDecoder*, FLAC__uint64* stream_length, void* client_data) - { - *stream_length = ((const FlacReader*) client_data)->input->getTotalLength(); - return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; - } + static FLAC__StreamDecoderLengthStatus lengthCallback_ (const FLAC__StreamDecoder*, FLAC__uint64* stream_length, void* client_data) + { + *stream_length = ((const FlacReader*) client_data)->input->getTotalLength(); + return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; + } - static FLAC__bool eofCallback_ (const FLAC__StreamDecoder*, void* client_data) - { - return ((const FlacReader*) client_data)->input->isExhausted(); - } + static FLAC__bool eofCallback_ (const FLAC__StreamDecoder*, void* client_data) + { + return ((const FlacReader*) client_data)->input->isExhausted(); + } - static FLAC__StreamDecoderWriteStatus writeCallback_ (const FLAC__StreamDecoder*, - const FLAC__Frame* frame, - const FLAC__int32* const buffer[], - void* client_data) - { - ((FlacReader*) client_data)->useSamples (buffer, frame->header.blocksize); - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; - } + static FLAC__StreamDecoderWriteStatus writeCallback_ (const FLAC__StreamDecoder*, + const FLAC__Frame* frame, + const FLAC__int32* const buffer[], + void* client_data) + { + ((FlacReader*) client_data)->useSamples (buffer, frame->header.blocksize); + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + } - static void metadataCallback_ (const FLAC__StreamDecoder*, - const FLAC__StreamMetadata* metadata, - void* client_data) - { - ((FlacReader*) client_data)->useMetadata (metadata->data.stream_info); - } + static void metadataCallback_ (const FLAC__StreamDecoder*, + const FLAC__StreamMetadata* metadata, + void* client_data) + { + ((FlacReader*) client_data)->useMetadata (metadata->data.stream_info); + } - static void errorCallback_ (const FLAC__StreamDecoder*, FLAC__StreamDecoderErrorStatus, void*) - { - } + static void errorCallback_ (const FLAC__StreamDecoder*, FLAC__StreamDecoderErrorStatus, void*) + { + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; class FlacWriter : public AudioFormatWriter { - FLAC__StreamEncoder* encoder; - MemoryBlock temp; + FLAC__StreamEncoder* encoder; + MemoryBlock temp; public: - bool ok; + bool ok; - FlacWriter (OutputStream* const out, - const double sampleRate_, - const int numChannels_, - const int bitsPerSample_) - : AudioFormatWriter (out, TRANS (flacFormatName), - sampleRate_, - numChannels_, - bitsPerSample_) - { - using namespace FlacNamespace; - encoder = FLAC__stream_encoder_new(); + FlacWriter (OutputStream* const out, + const double sampleRate_, + const int numChannels_, + const int bitsPerSample_) + : AudioFormatWriter (out, TRANS (flacFormatName), + sampleRate_, + numChannels_, + bitsPerSample_) + { + using namespace FlacNamespace; + encoder = FLAC__stream_encoder_new(); - FLAC__stream_encoder_set_do_mid_side_stereo (encoder, numChannels == 2); - FLAC__stream_encoder_set_loose_mid_side_stereo (encoder, numChannels == 2); - FLAC__stream_encoder_set_channels (encoder, numChannels); - FLAC__stream_encoder_set_bits_per_sample (encoder, jmin (24, bitsPerSample)); - FLAC__stream_encoder_set_sample_rate (encoder, (unsigned int) sampleRate); - FLAC__stream_encoder_set_blocksize (encoder, 2048); - FLAC__stream_encoder_set_do_escape_coding (encoder, true); + FLAC__stream_encoder_set_do_mid_side_stereo (encoder, numChannels == 2); + FLAC__stream_encoder_set_loose_mid_side_stereo (encoder, numChannels == 2); + FLAC__stream_encoder_set_channels (encoder, numChannels); + FLAC__stream_encoder_set_bits_per_sample (encoder, jmin ((unsigned int) 24, bitsPerSample)); + FLAC__stream_encoder_set_sample_rate (encoder, (unsigned int) sampleRate); + FLAC__stream_encoder_set_blocksize (encoder, 2048); + FLAC__stream_encoder_set_do_escape_coding (encoder, true); - ok = FLAC__stream_encoder_init_stream (encoder, - encodeWriteCallback, encodeSeekCallback, - encodeTellCallback, encodeMetadataCallback, - (void*) this) == FLAC__STREAM_ENCODER_INIT_STATUS_OK; - } + ok = FLAC__stream_encoder_init_stream (encoder, + encodeWriteCallback, encodeSeekCallback, + encodeTellCallback, encodeMetadataCallback, + (void*) this) == FLAC__STREAM_ENCODER_INIT_STATUS_OK; + } - ~FlacWriter() - { - if (ok) - { - FLAC__stream_encoder_finish (encoder); - output->flush(); - } - else - { - output = 0; // to stop the base class deleting this, as it needs to be returned - // to the caller of createWriter() - } + ~FlacWriter() + { + if (ok) + { + FLAC__stream_encoder_finish (encoder); + output->flush(); + } + else + { + output = 0; // to stop the base class deleting this, as it needs to be returned + // to the caller of createWriter() + } - FLAC__stream_encoder_delete (encoder); - } + FLAC__stream_encoder_delete (encoder); + } - bool write (const int** samplesToWrite, int numSamples) - { - if (! ok) - return false; + bool write (const int** samplesToWrite, int numSamples) + { + if (! ok) + return false; - int* buf[3]; - const int bitsToShift = 32 - bitsPerSample; + int* buf[3]; + const int bitsToShift = 32 - bitsPerSample; - if (bitsToShift > 0) - { - const int numChannelsToWrite = (samplesToWrite[1] == 0) ? 1 : 2; - temp.setSize (sizeof (int) * numSamples * numChannelsToWrite); + if (bitsToShift > 0) + { + const int numChannelsToWrite = (samplesToWrite[1] == 0) ? 1 : 2; + temp.setSize (sizeof (int) * numSamples * numChannelsToWrite); - buf[0] = (int*) temp.getData(); - buf[1] = buf[0] + numSamples; - buf[2] = 0; + buf[0] = (int*) temp.getData(); + buf[1] = buf[0] + numSamples; + buf[2] = 0; - for (int i = numChannelsToWrite; --i >= 0;) - { - if (samplesToWrite[i] != 0) - { - for (int j = 0; j < numSamples; ++j) - buf [i][j] = (samplesToWrite [i][j] >> bitsToShift); - } - } + for (int i = numChannelsToWrite; --i >= 0;) + { + if (samplesToWrite[i] != 0) + { + for (int j = 0; j < numSamples; ++j) + buf [i][j] = (samplesToWrite [i][j] >> bitsToShift); + } + } - samplesToWrite = (const int**) buf; - } + samplesToWrite = (const int**) buf; + } - return FLAC__stream_encoder_process (encoder, - (const FLAC__int32**) samplesToWrite, - numSamples) != 0; - } + return FLAC__stream_encoder_process (encoder, + (const FLAC__int32**) samplesToWrite, + numSamples) != 0; + } - bool writeData (const void* const data, const int size) const - { - return output->write (data, size); - } + bool writeData (const void* const data, const int size) const + { + return output->write (data, size); + } - static void packUint32 (FLAC__uint32 val, FLAC__byte* b, const int bytes) - { - b += bytes; + static void packUint32 (FLAC__uint32 val, FLAC__byte* b, const int bytes) + { + b += bytes; - for (int i = 0; i < bytes; ++i) - { - *(--b) = (FLAC__byte) (val & 0xff); - val >>= 8; - } - } + for (int i = 0; i < bytes; ++i) + { + *(--b) = (FLAC__byte) (val & 0xff); + val >>= 8; + } + } - void writeMetaData (const FLAC__StreamMetadata* metadata) - { - using namespace FlacNamespace; - const FLAC__StreamMetadata_StreamInfo& info = metadata->data.stream_info; + void writeMetaData (const FLAC__StreamMetadata* metadata) + { + using namespace FlacNamespace; + const FLAC__StreamMetadata_StreamInfo& info = metadata->data.stream_info; - unsigned char buffer [FLAC__STREAM_METADATA_STREAMINFO_LENGTH]; - const unsigned int channelsMinus1 = info.channels - 1; - const unsigned int bitsMinus1 = info.bits_per_sample - 1; + unsigned char buffer [FLAC__STREAM_METADATA_STREAMINFO_LENGTH]; + const unsigned int channelsMinus1 = info.channels - 1; + const unsigned int bitsMinus1 = info.bits_per_sample - 1; - packUint32 (info.min_blocksize, buffer, 2); - packUint32 (info.max_blocksize, buffer + 2, 2); - packUint32 (info.min_framesize, buffer + 4, 3); - packUint32 (info.max_framesize, buffer + 7, 3); - buffer[10] = (uint8) ((info.sample_rate >> 12) & 0xff); - buffer[11] = (uint8) ((info.sample_rate >> 4) & 0xff); - buffer[12] = (uint8) (((info.sample_rate & 0x0f) << 4) | (channelsMinus1 << 1) | (bitsMinus1 >> 4)); - buffer[13] = (FLAC__byte) (((bitsMinus1 & 0x0f) << 4) | (unsigned int) ((info.total_samples >> 32) & 0x0f)); - packUint32 ((FLAC__uint32) info.total_samples, buffer + 14, 4); - memcpy (buffer + 18, info.md5sum, 16); + packUint32 (info.min_blocksize, buffer, 2); + packUint32 (info.max_blocksize, buffer + 2, 2); + packUint32 (info.min_framesize, buffer + 4, 3); + packUint32 (info.max_framesize, buffer + 7, 3); + buffer[10] = (uint8) ((info.sample_rate >> 12) & 0xff); + buffer[11] = (uint8) ((info.sample_rate >> 4) & 0xff); + buffer[12] = (uint8) (((info.sample_rate & 0x0f) << 4) | (channelsMinus1 << 1) | (bitsMinus1 >> 4)); + buffer[13] = (FLAC__byte) (((bitsMinus1 & 0x0f) << 4) | (unsigned int) ((info.total_samples >> 32) & 0x0f)); + packUint32 ((FLAC__uint32) info.total_samples, buffer + 14, 4); + memcpy (buffer + 18, info.md5sum, 16); - const bool seekOk = output->setPosition (4); - (void) seekOk; + const bool seekOk = output->setPosition (4); + (void) seekOk; - // if this fails, you've given it an output stream that can't seek! It needs - // to be able to seek back to write the header - jassert (seekOk); + // if this fails, you've given it an output stream that can't seek! It needs + // to be able to seek back to write the header + jassert (seekOk); - output->writeIntBigEndian (FLAC__STREAM_METADATA_STREAMINFO_LENGTH); - output->write (buffer, FLAC__STREAM_METADATA_STREAMINFO_LENGTH); - } + output->writeIntBigEndian (FLAC__STREAM_METADATA_STREAMINFO_LENGTH); + output->write (buffer, FLAC__STREAM_METADATA_STREAMINFO_LENGTH); + } - static FLAC__StreamEncoderWriteStatus encodeWriteCallback (const FLAC__StreamEncoder*, - const FLAC__byte buffer[], - size_t bytes, - unsigned int /*samples*/, - unsigned int /*current_frame*/, - void* client_data) - { - using namespace FlacNamespace; - return ((FlacWriter*) client_data)->writeData (buffer, (int) bytes) - ? FLAC__STREAM_ENCODER_WRITE_STATUS_OK - : FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; - } + static FLAC__StreamEncoderWriteStatus encodeWriteCallback (const FLAC__StreamEncoder*, + const FLAC__byte buffer[], + size_t bytes, + unsigned int /*samples*/, + unsigned int /*current_frame*/, + void* client_data) + { + using namespace FlacNamespace; + return ((FlacWriter*) client_data)->writeData (buffer, (int) bytes) + ? FLAC__STREAM_ENCODER_WRITE_STATUS_OK + : FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; + } - static FLAC__StreamEncoderSeekStatus encodeSeekCallback (const FLAC__StreamEncoder*, FLAC__uint64, void*) - { - return FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED; - } + static FLAC__StreamEncoderSeekStatus encodeSeekCallback (const FLAC__StreamEncoder*, FLAC__uint64, void*) + { + return FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED; + } - static FLAC__StreamEncoderTellStatus encodeTellCallback (const FLAC__StreamEncoder*, FLAC__uint64* absolute_byte_offset, void* client_data) - { - if (client_data == 0) - return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED; + static FLAC__StreamEncoderTellStatus encodeTellCallback (const FLAC__StreamEncoder*, FLAC__uint64* absolute_byte_offset, void* client_data) + { + if (client_data == 0) + return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED; - *absolute_byte_offset = (FLAC__uint64) ((FlacWriter*) client_data)->output->getPosition(); - return FLAC__STREAM_ENCODER_TELL_STATUS_OK; - } + *absolute_byte_offset = (FLAC__uint64) ((FlacWriter*) client_data)->output->getPosition(); + return FLAC__STREAM_ENCODER_TELL_STATUS_OK; + } - static void encodeMetadataCallback (const FLAC__StreamEncoder*, - const FLAC__StreamMetadata* metadata, - void* client_data) - { - ((FlacWriter*) client_data)->writeMetaData (metadata); - } + static void encodeMetadataCallback (const FLAC__StreamEncoder*, + const FLAC__StreamMetadata* metadata, + void* client_data) + { + ((FlacWriter*) client_data)->writeMetaData (metadata); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; FlacAudioFormat::FlacAudioFormat() - : AudioFormat (TRANS (flacFormatName), (const tchar**) flacExtensions) + : AudioFormat (TRANS (flacFormatName), (const tchar**) flacExtensions) { } @@ -125910,64 +115785,64 @@ FlacAudioFormat::~FlacAudioFormat() const Array FlacAudioFormat::getPossibleSampleRates() { - const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 0 }; - return Array (rates); + const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 0 }; + return Array (rates); } const Array FlacAudioFormat::getPossibleBitDepths() { - const int depths[] = { 16, 24, 0 }; - return Array (depths); + const int depths[] = { 16, 24, 0 }; + return Array (depths); } bool FlacAudioFormat::canDoStereo() { - return true; + return true; } bool FlacAudioFormat::canDoMono() { - return true; + return true; } bool FlacAudioFormat::isCompressed() { - return true; + return true; } AudioFormatReader* FlacAudioFormat::createReaderFor (InputStream* in, - const bool deleteStreamIfOpeningFails) + const bool deleteStreamIfOpeningFails) { - ScopedPointer r (new FlacReader (in)); + ScopedPointer r (new FlacReader (in)); - if (r->sampleRate != 0) - return r.release(); + if (r->sampleRate != 0) + return r.release(); - if (! deleteStreamIfOpeningFails) - r->input = 0; + if (! deleteStreamIfOpeningFails) + r->input = 0; - return 0; + return 0; } AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out, - double sampleRate, - unsigned int numberOfChannels, - int bitsPerSample, - const StringPairArray& /*metadataValues*/, - int /*qualityOptionIndex*/) + double sampleRate, + unsigned int numberOfChannels, + int bitsPerSample, + const StringPairArray& /*metadataValues*/, + int /*qualityOptionIndex*/) { - if (getPossibleBitDepths().contains (bitsPerSample)) - { - ScopedPointer w (new FlacWriter (out, - sampleRate, - numberOfChannels, - bitsPerSample)); + if (getPossibleBitDepths().contains (bitsPerSample)) + { + ScopedPointer w (new FlacWriter (out, + sampleRate, + numberOfChannels, + bitsPerSample)); - if (w->ok) - return w.release(); - } + if (w->ok) + return w.release(); + } - return 0; + return 0; } END_JUCE_NAMESPACE @@ -126017,42 +115892,39 @@ extern "C" { #ifndef _OS_TYPES_H #define _OS_TYPES_H -/* make it easy on the folks that want to compile the libs with a - different malloc than stdlib */ #define _ogg_malloc malloc #define _ogg_calloc calloc #define _ogg_realloc realloc -#define _ogg_free free +#define _ogg_free free #if defined(_WIN32) # if defined(__CYGWIN__) -# include <_G_config.h> - typedef _G_int64_t ogg_int64_t; - typedef _G_int32_t ogg_int32_t; - typedef _G_uint32_t ogg_uint32_t; - typedef _G_int16_t ogg_int16_t; - typedef _G_uint16_t ogg_uint16_t; +# include <_G_config.h> + typedef _G_int64_t ogg_int64_t; + typedef _G_int32_t ogg_int32_t; + typedef _G_uint32_t ogg_uint32_t; + typedef _G_int16_t ogg_int16_t; + typedef _G_uint16_t ogg_uint16_t; # elif defined(__MINGW32__) - typedef short ogg_int16_t; - typedef unsigned short ogg_uint16_t; - typedef int ogg_int32_t; - typedef unsigned int ogg_uint32_t; - typedef long long ogg_int64_t; - typedef unsigned long long ogg_uint64_t; + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + typedef unsigned long long ogg_uint64_t; # elif defined(__MWERKS__) - typedef long long ogg_int64_t; - typedef int ogg_int32_t; - typedef unsigned int ogg_uint32_t; - typedef short ogg_int16_t; - typedef unsigned short ogg_uint16_t; + typedef long long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; # else - /* MSVC/Borland */ - typedef __int64 ogg_int64_t; - typedef __int32 ogg_int32_t; - typedef unsigned __int32 ogg_uint32_t; - typedef __int16 ogg_int16_t; - typedef unsigned __int16 ogg_uint16_t; + typedef __int64 ogg_int64_t; + typedef __int32 ogg_int32_t; + typedef unsigned __int32 ogg_uint32_t; + typedef __int16 ogg_int16_t; + typedef unsigned __int16 ogg_uint16_t; # endif #elif defined(__MACOS__) @@ -126075,7 +115947,6 @@ extern "C" { #elif defined(__BEOS__) - /* Be */ # include typedef int16_t ogg_int16_t; typedef u_int16_t ogg_uint16_t; @@ -126085,7 +115956,6 @@ extern "C" { #elif defined (__EMX__) - /* OS/2 GCC */ typedef short ogg_int16_t; typedef unsigned short ogg_uint16_t; typedef int ogg_int32_t; @@ -126094,7 +115964,6 @@ extern "C" { #elif defined (DJGPP) - /* DJGPP */ typedef short ogg_int16_t; typedef int ogg_int32_t; typedef unsigned int ogg_uint32_t; @@ -126102,7 +115971,6 @@ extern "C" { #elif defined(R5900) - /* PS2 EE */ typedef long ogg_int64_t; typedef int ogg_int32_t; typedef unsigned ogg_uint32_t; @@ -126110,7 +115978,6 @@ extern "C" { #elif defined(__SYMBIAN32__) - /* Symbian GCC */ typedef signed short ogg_int16_t; typedef unsigned short ogg_uint16_t; typedef signed int ogg_int32_t; @@ -126148,8 +116015,6 @@ typedef struct { long storage; } oggpack_buffer; -/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/ - typedef struct { unsigned char *header; long header_len; @@ -126158,52 +116023,46 @@ typedef struct { } ogg_page; ogg_uint32_t ogg_bitreverse(ogg_uint32_t x){ - x= ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL); - x= ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL); - x= ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL); - x= ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL); + x= ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL); + x= ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL); + x= ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL); + x= ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL); return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL); } -/* ogg_stream_state contains the current encode/decode state of a logical - Ogg bitstream **********************************************************/ - typedef struct { - unsigned char *body_data; /* bytes from packet bodies */ - long body_storage; /* storage elements allocated */ - long body_fill; /* elements stored; fill mark */ - long body_returned; /* elements of fill returned */ + unsigned char *body_data; /* bytes from packet bodies */ + long body_storage; /* storage elements allocated */ + long body_fill; /* elements stored; fill mark */ + long body_returned; /* elements of fill returned */ - int *lacing_vals; /* The values that will go to the segment table */ + int *lacing_vals; /* The values that will go to the segment table */ ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact this way, but it is simple coupled to the lacing fifo */ - long lacing_storage; - long lacing_fill; - long lacing_packet; - long lacing_returned; + long lacing_storage; + long lacing_fill; + long lacing_packet; + long lacing_returned; - unsigned char header[282]; /* working space for header encode */ - int header_fill; + unsigned char header[282]; /* working space for header encode */ + int header_fill; - int e_o_s; /* set when we have buffered the last packet in the - logical bitstream */ - int b_o_s; /* set after we've written the initial page - of a logical bitstream */ - long serialno; - long pageno; - ogg_int64_t packetno; /* sequence number for decode; the framing - knows where there's a hole in the data, - but we need coupling so that the codec - (which is in a seperate abstraction - layer) also knows about the gap */ + int e_o_s; /* set when we have buffered the last packet in the + logical bitstream */ + int b_o_s; /* set after we've written the initial page + of a logical bitstream */ + long serialno; + long pageno; + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a seperate abstraction + layer) also knows about the gap */ ogg_int64_t granulepos; } ogg_stream_state; -/* ogg_packet is used to encapsulate the data and metadata belonging - to a single raw Ogg/Vorbis packet *************************************/ - typedef struct { unsigned char *packet; long bytes; @@ -126212,7 +116071,7 @@ typedef struct { ogg_int64_t granulepos; - ogg_int64_t packetno; /* sequence number for decode; the framing + ogg_int64_t packetno; /* sequence number for decode; the framing knows where there's a hole in the data, but we need coupling so that the codec (which is in a seperate abstraction @@ -126230,8 +116089,6 @@ typedef struct { int bodybytes; } ogg_sync_state; -/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ - extern void oggpack_writeinit(oggpack_buffer *b); extern void oggpack_writetrunc(oggpack_buffer *b,long bits); extern void oggpack_writealign(oggpack_buffer *b); @@ -126268,48 +116125,42 @@ extern long oggpackB_bytes(oggpack_buffer *b); extern long oggpackB_bits(oggpack_buffer *b); extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b); -/* Ogg BITSTREAM PRIMITIVES: encoding **************************/ +extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op); +extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og); -extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op); -extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og); -extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og); - -/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ - -extern int ogg_sync_init(ogg_sync_state *oy); -extern int ogg_sync_clear(ogg_sync_state *oy); -extern int ogg_sync_reset(ogg_sync_state *oy); +extern int ogg_sync_init(ogg_sync_state *oy); +extern int ogg_sync_clear(ogg_sync_state *oy); +extern int ogg_sync_reset(ogg_sync_state *oy); extern int ogg_sync_destroy(ogg_sync_state *oy); -extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); -extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); -extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); -extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); -extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); -extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); -extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); +extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); +extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); +extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); +extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); +extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); +extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); -/* Ogg BITSTREAM PRIMITIVES: general ***************************/ +extern int ogg_stream_init(ogg_stream_state *os,int serialno); +extern int ogg_stream_clear(ogg_stream_state *os); +extern int ogg_stream_reset(ogg_stream_state *os); +extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); +extern int ogg_stream_destroy(ogg_stream_state *os); +extern int ogg_stream_eos(ogg_stream_state *os); -extern int ogg_stream_init(ogg_stream_state *os,int serialno); -extern int ogg_stream_clear(ogg_stream_state *os); -extern int ogg_stream_reset(ogg_stream_state *os); -extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); -extern int ogg_stream_destroy(ogg_stream_state *os); -extern int ogg_stream_eos(ogg_stream_state *os); +extern void ogg_page_checksum_set(ogg_page *og); -extern void ogg_page_checksum_set(ogg_page *og); - -extern int ogg_page_version(ogg_page *og); -extern int ogg_page_continued(ogg_page *og); -extern int ogg_page_bos(ogg_page *og); -extern int ogg_page_eos(ogg_page *og); +extern int ogg_page_version(ogg_page *og); +extern int ogg_page_continued(ogg_page *og); +extern int ogg_page_bos(ogg_page *og); +extern int ogg_page_eos(ogg_page *og); extern ogg_int64_t ogg_page_granulepos(ogg_page *og); -extern int ogg_page_serialno(ogg_page *og); -extern long ogg_page_pageno(ogg_page *og); -extern int ogg_page_packets(ogg_page *og); +extern int ogg_page_serialno(ogg_page *og); +extern long ogg_page_pageno(ogg_page *og); +extern int ogg_page_packets(ogg_page *og); -extern void ogg_packet_clear(ogg_packet *op); +extern void ogg_packet_clear(ogg_packet *op); #ifdef __cplusplus } @@ -126323,21 +116174,6 @@ typedef struct vorbis_info{ int channels; long rate; - /* The below bitrate declarations are *hints*. - Combinations of the three values carry the following implications: - - all three set to the same value: - implies a fixed rate bitstream - only nominal set: - implies a VBR stream that averages the nominal bitrate. No hard - upper/lower limit - upper and or lower set: - implies a VBR bitstream that obeys the bitrate limits. nominal - may also be set to give a nominal rate. - none set: - the coder does not care to speculate. - */ - long bitrate_upper; long bitrate_nominal; long bitrate_lower; @@ -126346,18 +116182,15 @@ typedef struct vorbis_info{ void *codec_setup; } vorbis_info; -/* vorbis_dsp_state buffers the current vorbis audio - analysis/synthesis state. The DSP state belongs to a specific - logical bitstream ****************************************************/ typedef struct vorbis_dsp_state{ int analysisp; vorbis_info *vi; float **pcm; float **pcmret; - int pcm_storage; - int pcm_current; - int pcm_returned; + int pcm_storage; + int pcm_current; + int pcm_returned; int preextrapolate; int eofflag; @@ -126375,12 +116208,11 @@ typedef struct vorbis_dsp_state{ ogg_int64_t floor_bits; ogg_int64_t res_bits; - void *backend_state; + void *backend_state; } vorbis_dsp_state; typedef struct vorbis_block{ - /* necessary stream state for linking to the framing abstraction */ - float **pcm; /* this is a pointer into local storage */ + float **pcm; /* this is a pointer into local storage */ oggpack_buffer opb; long lW; @@ -126389,20 +116221,17 @@ typedef struct vorbis_block{ int pcmend; int mode; - int eofflag; + int eofflag; ogg_int64_t granulepos; ogg_int64_t sequence; vorbis_dsp_state *vd; /* For read-only access of configuration */ - /* local storage to avoid remallocing; it's up to the mapping to - structure it */ - void *localstore; - long localtop; - long localalloc; - long totaluse; + void *localstore; + long localtop; + long localalloc; + long totaluse; struct alloc_chain *reap; - /* bitmetrics for the frame */ long glue_bits; long time_bits; long floor_bits; @@ -126412,117 +116241,83 @@ typedef struct vorbis_block{ } vorbis_block; -/* vorbis_block is a single block of data to be processed as part of -the analysis/synthesis stream; it belongs to a specific logical -bitstream, but is independant from other vorbis_blocks belonging to -that logical bitstream. *************************************************/ - struct alloc_chain{ void *ptr; struct alloc_chain *next; }; -/* vorbis_info contains all the setup information specific to the - specific compression/decompression mode in progress (eg, - psychoacoustic settings, channel setup, options, codebook - etc). vorbis_info and substructures are in backends.h. -*********************************************************************/ - -/* the comments are not part of vorbis_info so that vorbis_info can be - static storage */ typedef struct vorbis_comment{ - /* unlimited user comment fields. libvorbis writes 'libvorbis' - whatever vendor is set to in encode */ char **user_comments; int *comment_lengths; - int comments; + int comments; char *vendor; } vorbis_comment; -/* libvorbis encodes in two abstraction layers; first we perform DSP - and produce a packet (see docs/analysis.txt). The packet is then - coded into a framed OggSquish bitstream by the second layer (see - docs/framing.txt). Decode is the reverse process; we sync/frame - the bitstream and extract individual packets, then decode the - packet back into PCM audio. +extern void vorbis_info_init(vorbis_info *vi); +extern void vorbis_info_clear(vorbis_info *vi); +extern int vorbis_info_blocksize(vorbis_info *vi,int zo); +extern void vorbis_comment_init(vorbis_comment *vc); +extern void vorbis_comment_add(vorbis_comment *vc, char *comment); +extern void vorbis_comment_add_tag(vorbis_comment *vc, + const char *tag, char *contents); +extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count); +extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag); +extern void vorbis_comment_clear(vorbis_comment *vc); - The extra framing/packetizing is used in streaming formats, such as - files. Over the net (such as with UDP), the framing and - packetization aren't necessary as they're provided by the transport - and the streaming layer is not used */ - -/* Vorbis PRIMITIVES: general ***************************************/ - -extern void vorbis_info_init(vorbis_info *vi); -extern void vorbis_info_clear(vorbis_info *vi); -extern int vorbis_info_blocksize(vorbis_info *vi,int zo); -extern void vorbis_comment_init(vorbis_comment *vc); -extern void vorbis_comment_add(vorbis_comment *vc, char *comment); -extern void vorbis_comment_add_tag(vorbis_comment *vc, - const char *tag, char *contents); -extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count); -extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag); -extern void vorbis_comment_clear(vorbis_comment *vc); - -extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb); -extern int vorbis_block_clear(vorbis_block *vb); -extern void vorbis_dsp_clear(vorbis_dsp_state *v); +extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb); +extern int vorbis_block_clear(vorbis_block *vb); +extern void vorbis_dsp_clear(vorbis_dsp_state *v); extern double vorbis_granule_time(vorbis_dsp_state *v, - ogg_int64_t granulepos); + ogg_int64_t granulepos); -/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/ - -extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi); -extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op); -extern int vorbis_analysis_headerout(vorbis_dsp_state *v, +extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op); +extern int vorbis_analysis_headerout(vorbis_dsp_state *v, vorbis_comment *vc, ogg_packet *op, ogg_packet *op_comm, ogg_packet *op_code); extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals); -extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals); -extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb); -extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op); +extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op); -extern int vorbis_bitrate_addblock(vorbis_block *vb); -extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, +extern int vorbis_bitrate_addblock(vorbis_block *vb); +extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, ogg_packet *op); -/* Vorbis PRIMITIVES: synthesis layer *******************************/ -extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc, +extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc, ogg_packet *op); -extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi); -extern int vorbis_synthesis_restart(vorbis_dsp_state *v); -extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op); -extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op); -extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb); -extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm); -extern int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm); -extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples); -extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); +extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_synthesis_restart(vorbis_dsp_state *v); +extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples); +extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); -extern int vorbis_synthesis_halfrate(vorbis_info *v,int flag); -extern int vorbis_synthesis_halfrate_p(vorbis_info *v); +extern int vorbis_synthesis_halfrate(vorbis_info *v,int flag); +extern int vorbis_synthesis_halfrate_p(vorbis_info *v); -/* Vorbis ERRORS and return codes ***********************************/ +#define OV_FALSE -1 +#define OV_EOF -2 +#define OV_HOLE -3 -#define OV_FALSE -1 -#define OV_EOF -2 -#define OV_HOLE -3 - -#define OV_EREAD -128 -#define OV_EFAULT -129 -#define OV_EIMPL -130 -#define OV_EINVAL -131 +#define OV_EREAD -128 +#define OV_EFAULT -129 +#define OV_EIMPL -130 +#define OV_EINVAL -131 #define OV_ENOTVORBIS -132 #define OV_EBADHEADER -133 #define OV_EVERSION -134 #define OV_ENOTAUDIO -135 #define OV_EBADPACKET -136 #define OV_EBADLINK -137 -#define OV_ENOSEEK -138 +#define OV_ENOSEEK -138 #ifdef __cplusplus } @@ -126532,20 +116327,20 @@ extern int vorbis_synthesis_halfrate_p(vorbis_info *v); /********* End of inlined file: codec.h *********/ extern int vorbis_encode_init(vorbis_info *vi, - long channels, - long rate, + long channels, + long rate, - long max_bitrate, - long nominal_bitrate, - long min_bitrate); + long max_bitrate, + long nominal_bitrate, + long min_bitrate); extern int vorbis_encode_setup_managed(vorbis_info *vi, - long channels, - long rate, + long channels, + long rate, - long max_bitrate, - long nominal_bitrate, - long min_bitrate); + long max_bitrate, + long nominal_bitrate, + long min_bitrate); extern int vorbis_encode_setup_vbr(vorbis_info *vi, long channels, @@ -126565,14 +116360,13 @@ extern int vorbis_encode_setup_init(vorbis_info *vi); extern int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg); - /* deprecated rate management supported only for compatability */ -#define OV_ECTL_RATEMANAGE_GET 0x10 -#define OV_ECTL_RATEMANAGE_SET 0x11 -#define OV_ECTL_RATEMANAGE_AVG 0x12 -#define OV_ECTL_RATEMANAGE_HARD 0x13 +#define OV_ECTL_RATEMANAGE_GET 0x10 +#define OV_ECTL_RATEMANAGE_SET 0x11 +#define OV_ECTL_RATEMANAGE_AVG 0x12 +#define OV_ECTL_RATEMANAGE_HARD 0x13 struct ovectl_ratemanage_arg { - int management_active; + int management_active; long bitrate_hard_min; long bitrate_hard_max; @@ -126584,12 +116378,11 @@ struct ovectl_ratemanage_arg { double bitrate_av_window_center; }; - /* new rate setup */ -#define OV_ECTL_RATEMANAGE2_GET 0x14 -#define OV_ECTL_RATEMANAGE2_SET 0x15 +#define OV_ECTL_RATEMANAGE2_GET 0x14 +#define OV_ECTL_RATEMANAGE2_SET 0x15 struct ovectl_ratemanage2_arg { - int management_active; + int management_active; long bitrate_limit_min_kbps; long bitrate_limit_max_kbps; @@ -126600,11 +116393,11 @@ struct ovectl_ratemanage2_arg { double bitrate_average_damping; }; -#define OV_ECTL_LOWPASS_GET 0x20 -#define OV_ECTL_LOWPASS_SET 0x21 +#define OV_ECTL_LOWPASS_GET 0x20 +#define OV_ECTL_LOWPASS_SET 0x21 -#define OV_ECTL_IBLOCK_GET 0x30 -#define OV_ECTL_IBLOCK_SET 0x31 +#define OV_ECTL_IBLOCK_GET 0x30 +#define OV_ECTL_IBLOCK_SET 0x31 #ifdef __cplusplus } @@ -126624,61 +116417,48 @@ extern "C" #include -/* The function prototypes for the callbacks are basically the same as for - * the stdio functions fread, fseek, fclose, ftell. - * The one difference is that the FILE * arguments have been replaced with - * a void * - this is to be used as a pointer to whatever internal data these - * functions might need. In the stdio case, it's just a FILE * cast to a void * - * - * If you use other functions, check the docs for these functions and return - * the right values. For seek_func(), you *MUST* return -1 if the stream is - * unseekable - */ typedef struct { size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); - int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); - int (*close_func) (void *datasource); + int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); + int (*close_func) (void *datasource); long (*tell_func) (void *datasource); } ov_callbacks; #define NOTOPEN 0 #define PARTOPEN 1 -#define OPENED 2 +#define OPENED 2 #define STREAMSET 3 #define INITSET 4 typedef struct OggVorbis_File { - void *datasource; /* Pointer to a FILE *, etc. */ - int seekable; - ogg_int64_t offset; - ogg_int64_t end; + void *datasource; /* Pointer to a FILE *, etc. */ + int seekable; + ogg_int64_t offset; + ogg_int64_t end; ogg_sync_state oy; - /* If the FILE handle isn't seekable (eg, a pipe), only the current - stream appears */ - int links; - ogg_int64_t *offsets; - ogg_int64_t *dataoffsets; - long *serialnos; - ogg_int64_t *pcmlengths; /* overloaded to maintain binary + int links; + ogg_int64_t *offsets; + ogg_int64_t *dataoffsets; + long *serialnos; + ogg_int64_t *pcmlengths; /* overloaded to maintain binary compatability; x2 size, stores both beginning and end values */ - vorbis_info *vi; + vorbis_info *vi; vorbis_comment *vc; - /* Decoding working state local storage */ - ogg_int64_t pcm_offset; - int ready_state; - long current_serialno; - int current_link; + ogg_int64_t pcm_offset; + int ready_state; + long current_serialno; + int current_link; - double bittrack; - double samptrack; + double bittrack; + double samptrack; ogg_stream_state os; /* take physical pages, weld into a logical - stream of packets */ + stream of packets */ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ - vorbis_block vb; /* local working space for packet->PCM decode */ + vorbis_block vb; /* local working space for packet->PCM decode */ ov_callbacks callbacks; @@ -126726,7 +116506,7 @@ extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link); extern long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int samples, int *bitstream); extern long ov_read(OggVorbis_File *vf,char *buffer,int length, - int bigendianp,int word,int sgned,int *bitstream); + int bigendianp,int word,int sgned,int *bitstream); extern int ov_crosslap(OggVorbis_File *vf1,OggVorbis_File *vf2); extern int ov_halfrate(OggVorbis_File *vf,int flag); @@ -126740,8 +116520,6 @@ extern int ov_halfrate_p(OggVorbis_File *vf); /********* End of inlined file: vorbisfile.h *********/ /********* Start of inlined file: bitwise.c *********/ -/* We're 'LSb' endian; if we write a word but read individual bits, - then we'll read the lsb first */ /********* Start of inlined file: juce_OggVorbisHeader.h *********/ // This file is included at the start of each Ogg-Vorbis .c file, just to do a few housekeeping @@ -126800,12 +116578,11 @@ void oggpackB_writetrunc(oggpack_buffer *b,long bits){ *b->ptr&=mask8B[bits]; } -/* Takes only up to 32 bits. */ void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){ if(b->endbyte+4>=b->storage){ - b->buffer=(unsigned char*) _ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); - b->storage+=BUFFER_INCREMENT; - b->ptr=b->buffer+b->endbyte; + b->buffer=(unsigned char*) _ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); + b->storage+=BUFFER_INCREMENT; + b->ptr=b->buffer+b->endbyte; } value&=mask[bits]; @@ -126814,19 +116591,19 @@ void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){ b->ptr[0]|=value<endbit; if(bits>=8){ - b->ptr[1]=(unsigned char)(value>>(8-b->endbit)); - if(bits>=16){ - b->ptr[2]=(unsigned char)(value>>(16-b->endbit)); - if(bits>=24){ + b->ptr[1]=(unsigned char)(value>>(8-b->endbit)); + if(bits>=16){ + b->ptr[2]=(unsigned char)(value>>(16-b->endbit)); + if(bits>=24){ b->ptr[3]=(unsigned char)(value>>(24-b->endbit)); if(bits>=32){ if(b->endbit) - b->ptr[4]=(unsigned char)(value>>(32-b->endbit)); + b->ptr[4]=(unsigned char)(value>>(32-b->endbit)); else - b->ptr[4]=0; + b->ptr[4]=0; + } + } } - } - } } b->endbyte+=bits/8; @@ -126834,12 +116611,11 @@ void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){ b->endbit=bits&7; } -/* Takes only up to 32 bits. */ void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){ if(b->endbyte+4>=b->storage){ - b->buffer=(unsigned char*) _ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); - b->storage+=BUFFER_INCREMENT; - b->ptr=b->buffer+b->endbyte; + b->buffer=(unsigned char*) _ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); + b->storage+=BUFFER_INCREMENT; + b->ptr=b->buffer+b->endbyte; } value=(value&mask[bits])<<(32-bits); @@ -126848,19 +116624,19 @@ void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){ b->ptr[0]|=value>>(24+b->endbit); if(bits>=8){ - b->ptr[1]=(unsigned char)(value>>(16+b->endbit)); - if(bits>=16){ - b->ptr[2]=(unsigned char)(value>>(8+b->endbit)); - if(bits>=24){ + b->ptr[1]=(unsigned char)(value>>(16+b->endbit)); + if(bits>=16){ + b->ptr[2]=(unsigned char)(value>>(8+b->endbit)); + if(bits>=24){ b->ptr[3]=(unsigned char)(value>>(b->endbit)); if(bits>=32){ if(b->endbit) - b->ptr[4]=(unsigned char)(value<<(8-b->endbit)); + b->ptr[4]=(unsigned char)(value<<(8-b->endbit)); else - b->ptr[4]=0; + b->ptr[4]=0; + } + } } - } - } } b->endbyte+=bits/8; @@ -126871,51 +116647,49 @@ void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){ void oggpack_writealign(oggpack_buffer *b){ int bits=8-b->endbit; if(bits<8) - oggpack_write(b,0,bits); + oggpack_write(b,0,bits); } void oggpackB_writealign(oggpack_buffer *b){ int bits=8-b->endbit; if(bits<8) - oggpackB_write(b,0,bits); + oggpackB_write(b,0,bits); } static void oggpack_writecopy_helper(oggpack_buffer *b, - void *source, - long bits, - void (*w)(oggpack_buffer *, - unsigned long, - int), - int msb){ + void *source, + long bits, + void (*w)(oggpack_buffer *, + unsigned long, + int), + int msb){ unsigned char *ptr=(unsigned char *)source; long bytes=bits/8; bits-=bytes*8; if(b->endbit){ - int i; - /* unaligned copy. Do it the hard way. */ - for(i=0;iendbyte+bytes+1>=b->storage){ - b->storage=b->endbyte+bytes+BUFFER_INCREMENT; - b->buffer=(unsigned char*) _ogg_realloc(b->buffer,b->storage); - b->ptr=b->buffer+b->endbyte; - } + if(b->endbyte+bytes+1>=b->storage){ + b->storage=b->endbyte+bytes+BUFFER_INCREMENT; + b->buffer=(unsigned char*) _ogg_realloc(b->buffer,b->storage); + b->ptr=b->buffer+b->endbyte; + } - memmove(b->ptr,source,bytes); - b->ptr+=bytes; - b->endbyte+=bytes; - *b->ptr=0; + memmove(b->ptr,source,bytes); + b->ptr+=bytes; + b->endbyte+=bytes; + *b->ptr=0; } if(bits){ - if(msb) - w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits); - else - w(b,(unsigned long)(ptr[bytes]),bits); + if(msb) + w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits); + else + w(b,(unsigned long)(ptr[bytes]),bits); } } @@ -126956,7 +116730,6 @@ void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){ oggpack_readinit(b,buf,bytes); } -/* Read in bits without advancing the bitptr; bits <= 32 */ long oggpack_look(oggpack_buffer *b,int bits){ unsigned long ret; unsigned long m=mask[bits]; @@ -126964,26 +116737,24 @@ long oggpack_look(oggpack_buffer *b,int bits){ bits+=b->endbit; if(b->endbyte+4>=b->storage){ - /* not the main path */ - if(b->endbyte*8+bits>b->storage*8)return(-1); + if(b->endbyte*8+bits>b->storage*8)return(-1); } ret=b->ptr[0]>>b->endbit; if(bits>8){ - ret|=b->ptr[1]<<(8-b->endbit); - if(bits>16){ - ret|=b->ptr[2]<<(16-b->endbit); - if(bits>24){ + ret|=b->ptr[1]<<(8-b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(16-b->endbit); + if(bits>24){ ret|=b->ptr[3]<<(24-b->endbit); if(bits>32 && b->endbit) ret|=b->ptr[4]<<(32-b->endbit); - } - } + } + } } return(m&ret); } -/* Read in bits without advancing the bitptr; bits <= 32 */ long oggpackB_look(oggpack_buffer *b,int bits){ unsigned long ret; int m=32-bits; @@ -126991,21 +116762,20 @@ long oggpackB_look(oggpack_buffer *b,int bits){ bits+=b->endbit; if(b->endbyte+4>=b->storage){ - /* not the main path */ - if(b->endbyte*8+bits>b->storage*8)return(-1); + if(b->endbyte*8+bits>b->storage*8)return(-1); } ret=b->ptr[0]<<(24+b->endbit); if(bits>8){ - ret|=b->ptr[1]<<(16+b->endbit); - if(bits>16){ - ret|=b->ptr[2]<<(8+b->endbit); - if(bits>24){ + ret|=b->ptr[1]<<(16+b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(8+b->endbit); + if(bits>24){ ret|=b->ptr[3]<<(b->endbit); if(bits>32 && b->endbit) ret|=b->ptr[4]>>(8-b->endbit); - } - } + } + } } return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1); } @@ -127033,9 +116803,9 @@ void oggpackB_adv(oggpack_buffer *b,int bits){ void oggpack_adv1(oggpack_buffer *b){ if(++(b->endbit)>7){ - b->endbit=0; - b->ptr++; - b->endbyte++; + b->endbit=0; + b->ptr++; + b->endbyte++; } } @@ -127043,7 +116813,6 @@ void oggpackB_adv1(oggpack_buffer *b){ oggpack_adv1(b); } -/* bits <= 32 */ long oggpack_read(oggpack_buffer *b,int bits){ long ret; unsigned long m=mask[bits]; @@ -127051,23 +116820,22 @@ long oggpack_read(oggpack_buffer *b,int bits){ bits+=b->endbit; if(b->endbyte+4>=b->storage){ - /* not the main path */ - ret=-1L; - if(b->endbyte*8+bits>b->storage*8)goto overflow; + ret=-1L; + if(b->endbyte*8+bits>b->storage*8)goto overflow; } ret=b->ptr[0]>>b->endbit; if(bits>8){ - ret|=b->ptr[1]<<(8-b->endbit); - if(bits>16){ - ret|=b->ptr[2]<<(16-b->endbit); - if(bits>24){ + ret|=b->ptr[1]<<(8-b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(16-b->endbit); + if(bits>24){ ret|=b->ptr[3]<<(24-b->endbit); if(bits>32 && b->endbit){ ret|=b->ptr[4]<<(32-b->endbit); } - } - } + } + } } ret&=m; @@ -127079,7 +116847,6 @@ long oggpack_read(oggpack_buffer *b,int bits){ return(ret); } -/* bits <= 32 */ long oggpackB_read(oggpack_buffer *b,int bits){ long ret; long m=32-bits; @@ -127087,22 +116854,21 @@ long oggpackB_read(oggpack_buffer *b,int bits){ bits+=b->endbit; if(b->endbyte+4>=b->storage){ - /* not the main path */ - ret=-1L; - if(b->endbyte*8+bits>b->storage*8)goto overflow; + ret=-1L; + if(b->endbyte*8+bits>b->storage*8)goto overflow; } ret=b->ptr[0]<<(24+b->endbit); if(bits>8){ - ret|=b->ptr[1]<<(16+b->endbit); - if(bits>16){ - ret|=b->ptr[2]<<(8+b->endbit); - if(bits>24){ + ret|=b->ptr[1]<<(16+b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(8+b->endbit); + if(bits>24){ ret|=b->ptr[3]<<(b->endbit); if(bits>32 && b->endbit) ret|=b->ptr[4]>>(8-b->endbit); - } - } + } + } } ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1); @@ -127118,9 +116884,8 @@ long oggpack_read1(oggpack_buffer *b){ long ret; if(b->endbyte>=b->storage){ - /* not the main path */ - ret=-1L; - goto overflow; + ret=-1L; + goto overflow; } ret=(b->ptr[0]>>b->endbit)&1; @@ -127129,9 +116894,9 @@ long oggpack_read1(oggpack_buffer *b){ b->endbit++; if(b->endbit>7){ - b->endbit=0; - b->ptr++; - b->endbyte++; + b->endbit=0; + b->ptr++; + b->endbyte++; } return(ret); } @@ -127140,9 +116905,8 @@ long oggpackB_read1(oggpack_buffer *b){ long ret; if(b->endbyte>=b->storage){ - /* not the main path */ - ret=-1L; - goto overflow; + ret=-1L; + goto overflow; } ret=(b->ptr[0]>>(7-b->endbit))&1; @@ -127151,9 +116915,9 @@ long oggpackB_read1(oggpack_buffer *b){ b->endbit++; if(b->endbit>7){ - b->endbit=0; - b->ptr++; - b->endbyte++; + b->endbit=0; + b->ptr++; + b->endbyte++; } return(ret); } @@ -127182,17 +116946,14 @@ unsigned char *oggpackB_get_buffer(oggpack_buffer *b){ return oggpack_get_buffer(b); } -/* Self test of the bitwise routines; everything else is based on - them, so they damned well better be solid. */ - #ifdef _V_SELFTEST #include static int ilog(unsigned int v){ int ret=0; while(v){ - ret++; - v>>=1; + ret++; + v>>=1; } return(ret); } @@ -127211,31 +116972,31 @@ void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){ oggpack_reset(&o); for(i=0;i #include -/* A complete description of Ogg framing exists in docs/framing.html */ - int ogg_page_version(ogg_page *og){ return((int)(og->header[4])); } @@ -127581,47 +117334,28 @@ long ogg_page_pageno(ogg_page *og){ (og->header[21]<<24)); } -/* returns the number of packets that are completed on this page (if - the leading packet is begun on a previous page, but ends on this - page, it's counted */ - -/* NOTE: -If a page consists of a packet begun on a previous page, and a new -packet begun (but not completed) on this page, the return will be: - ogg_page_packets(page) ==1, - ogg_page_continued(page) !=0 - -If a page happens to be a single packet that was begun on a -previous page, and spans to the next page (in the case of a three or -more page packet), the return will be: - ogg_page_packets(page) ==0, - ogg_page_continued(page) !=0 -*/ - int ogg_page_packets(ogg_page *og){ int i,n=og->header[26],count=0; for(i=0;iheader[27+i]<255)count++; + if(og->header[27+i]<255)count++; return(count); } #if 0 -/* helper to initialize lookup for direct-table CRC (illustrative; we - use the static init below) */ static ogg_uint32_t _ogg_crc_entry(unsigned long index){ - int i; + int i; unsigned long r; r = index << 24; for (i=0; i<8; i++) - if (r & 0x80000000UL) - r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator - polynomial, although we use an - unreflected alg and an init/final - of 0, not 0xffffffff */ - else - r<<=1; + if (r & 0x80000000UL) + r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator + polynomial, although we use an + unreflected alg and an init/final + of 0, not 0xffffffff */ + else + r<<=1; return (r & 0xffffffffUL); } #endif @@ -127692,132 +117426,108 @@ static const ogg_uint32_t crc_lookup[256]={ 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668, 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4}; -/* init the encode/decode logical stream state */ - int ogg_stream_init(ogg_stream_state *os,int serialno){ if(os){ - memset(os,0,sizeof(*os)); - os->body_storage=16*1024; - os->body_data=(unsigned char*) _ogg_malloc(os->body_storage*sizeof(*os->body_data)); + memset(os,0,sizeof(*os)); + os->body_storage=16*1024; + os->body_data=(unsigned char*) _ogg_malloc(os->body_storage*sizeof(*os->body_data)); - os->lacing_storage=1024; - os->lacing_vals=(int*) _ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals)); - os->granule_vals=(ogg_int64_t*) _ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals)); + os->lacing_storage=1024; + os->lacing_vals=(int*) _ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals)); + os->granule_vals=(ogg_int64_t*) _ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals)); - os->serialno=serialno; + os->serialno=serialno; - return(0); + return(0); } return(-1); } -/* _clear does not free os, only the non-flat storage within */ int ogg_stream_clear(ogg_stream_state *os){ if(os){ - if(os->body_data)_ogg_free(os->body_data); - if(os->lacing_vals)_ogg_free(os->lacing_vals); - if(os->granule_vals)_ogg_free(os->granule_vals); + if(os->body_data)_ogg_free(os->body_data); + if(os->lacing_vals)_ogg_free(os->lacing_vals); + if(os->granule_vals)_ogg_free(os->granule_vals); - memset(os,0,sizeof(*os)); + memset(os,0,sizeof(*os)); } return(0); } int ogg_stream_destroy(ogg_stream_state *os){ if(os){ - ogg_stream_clear(os); - _ogg_free(os); + ogg_stream_clear(os); + _ogg_free(os); } return(0); } -/* Helpers for ogg_stream_encode; this keeps the structure and - what's happening fairly clear */ - static void _os_body_expand(ogg_stream_state *os,int needed){ if(os->body_storage<=os->body_fill+needed){ - os->body_storage+=(needed+1024); - os->body_data=(unsigned char*) _ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data)); + os->body_storage+=(needed+1024); + os->body_data=(unsigned char*) _ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data)); } } static void _os_lacing_expand(ogg_stream_state *os,int needed){ if(os->lacing_storage<=os->lacing_fill+needed){ - os->lacing_storage+=(needed+32); - os->lacing_vals=(int*)_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals)); - os->granule_vals=(ogg_int64_t*)_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals)); + os->lacing_storage+=(needed+32); + os->lacing_vals=(int*)_ogg_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals)); + os->granule_vals=(ogg_int64_t*)_ogg_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals)); } } -/* checksum the page */ -/* Direct table CRC; note that this will be faster in the future if we - perform the checksum silmultaneously with other copies */ - void ogg_page_checksum_set(ogg_page *og){ if(og){ - ogg_uint32_t crc_reg=0; - int i; + ogg_uint32_t crc_reg=0; + int i; - /* safety; needed for API behavior, but not framing code */ - og->header[22]=0; - og->header[23]=0; - og->header[24]=0; - og->header[25]=0; + og->header[22]=0; + og->header[23]=0; + og->header[24]=0; + og->header[25]=0; - for(i=0;iheader_len;i++) - crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]]; - for(i=0;ibody_len;i++) - crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]]; + for(i=0;iheader_len;i++) + crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]]; + for(i=0;ibody_len;i++) + crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]]; - og->header[22]=(unsigned char)(crc_reg&0xff); - og->header[23]=(unsigned char)((crc_reg>>8)&0xff); - og->header[24]=(unsigned char)((crc_reg>>16)&0xff); - og->header[25]=(unsigned char)((crc_reg>>24)&0xff); + og->header[22]=(unsigned char)(crc_reg&0xff); + og->header[23]=(unsigned char)((crc_reg>>8)&0xff); + og->header[24]=(unsigned char)((crc_reg>>16)&0xff); + og->header[25]=(unsigned char)((crc_reg>>24)&0xff); } } -/* submit data to the internal buffer of the framing engine */ int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){ int lacing_vals=op->bytes/255+1,i; if(os->body_returned){ - /* advance packet data according to the body_returned pointer. We - had to keep it around to return a pointer into the buffer last - call */ - os->body_fill-=os->body_returned; - if(os->body_fill) - memmove(os->body_data,os->body_data+os->body_returned, - os->body_fill); - os->body_returned=0; + os->body_fill-=os->body_returned; + if(os->body_fill) + memmove(os->body_data,os->body_data+os->body_returned, + os->body_fill); + os->body_returned=0; } - /* make sure we have the buffer storage */ _os_body_expand(os,op->bytes); _os_lacing_expand(os,lacing_vals); - /* Copy in the submitted packet. Yes, the copy is a waste; this is - the liability of overly clean abstraction for the time being. It - will actually be fairly easy to eliminate the extra copy in the - future */ - memcpy(os->body_data+os->body_fill,op->packet,op->bytes); os->body_fill+=op->bytes; - /* Store lacing vals for this packet */ for(i=0;ilacing_vals[os->lacing_fill+i]=255; - os->granule_vals[os->lacing_fill+i]=os->granulepos; + os->lacing_vals[os->lacing_fill+i]=255; + os->granule_vals[os->lacing_fill+i]=os->granulepos; } os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255; os->granulepos=os->granule_vals[os->lacing_fill+i]=op->granulepos; - /* flag the first segment as the beginning of the packet */ os->lacing_vals[os->lacing_fill]|= 0x100; os->lacing_fill+=lacing_vals; - /* for the sake of completeness */ os->packetno++; if(op->e_o_s)os->e_o_s=1; @@ -127825,20 +117535,6 @@ int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){ return(0); } -/* This will flush remaining packets into a page (returning nonzero), - even if there is not enough data to trigger a flush normally - (undersized page). If there are no packets or partial packets to - flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will - try to flush a normal sized page like ogg_stream_pageout; a call to - ogg_stream_flush does not guarantee that all packets have flushed. - Only a return value of 0 from ogg_stream_flush indicates all packet - data is flushed into pages. - - since ogg_stream_flush will flush the last page in a stream even if - it's undersized, you almost certainly want to use ogg_stream_pageout - (and *not* ogg_stream_flush) unless you specifically need to flush - an page regardless of size in the middle of a stream. */ - int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){ int i; int vals=0; @@ -127849,120 +117545,93 @@ int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){ if(maxvals==0)return(0); - /* construct a page */ - /* decide how many segments to include */ - - /* If this is the initial header case, the first page must only include - the initial header packet */ if(os->b_o_s==0){ /* 'initial header page' case */ - granule_pos=0; - for(vals=0;valslacing_vals[vals]&0x0ff)<255){ + granule_pos=0; + for(vals=0;valslacing_vals[vals]&0x0ff)<255){ vals++; break; - } - } + } + } }else{ - for(vals=0;vals4096)break; - acc+=os->lacing_vals[vals]&0x0ff; - if((os->lacing_vals[vals]&0xff)<255) - granule_pos=os->granule_vals[vals]; - } + for(vals=0;vals4096)break; + acc+=os->lacing_vals[vals]&0x0ff; + if((os->lacing_vals[vals]&0xff)<255) + granule_pos=os->granule_vals[vals]; + } } - /* construct the header in temp storage */ memcpy(os->header,"OggS",4); - /* stream structure version */ os->header[4]=0x00; - /* continued packet flag? */ os->header[5]=0x00; if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01; - /* first page flag? */ if(os->b_o_s==0)os->header[5]|=0x02; - /* last page flag? */ if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04; os->b_o_s=1; - /* 64 bits of PCM position */ for(i=6;i<14;i++){ - os->header[i]=(unsigned char)(granule_pos&0xff); - granule_pos>>=8; + os->header[i]=(unsigned char)(granule_pos&0xff); + granule_pos>>=8; } - /* 32 bits of stream serial number */ { - long serialno=os->serialno; - for(i=14;i<18;i++){ - os->header[i]=(unsigned char)(serialno&0xff); - serialno>>=8; - } + long serialno=os->serialno; + for(i=14;i<18;i++){ + os->header[i]=(unsigned char)(serialno&0xff); + serialno>>=8; + } } - /* 32 bits of page counter (we have both counter and page header - because this val can roll over) */ if(os->pageno==-1)os->pageno=0; /* because someone called - stream_reset; this would be a - strange thing to do in an - encode stream, but it has - plausible uses */ + stream_reset; this would be a + strange thing to do in an + encode stream, but it has + plausible uses */ { - long pageno=os->pageno++; - for(i=18;i<22;i++){ - os->header[i]=(unsigned char)(pageno&0xff); - pageno>>=8; - } + long pageno=os->pageno++; + for(i=18;i<22;i++){ + os->header[i]=(unsigned char)(pageno&0xff); + pageno>>=8; + } } - /* zero for computation; filled in later */ os->header[22]=0; os->header[23]=0; os->header[24]=0; os->header[25]=0; - /* segment table */ os->header[26]=(unsigned char)(vals&0xff); for(i=0;iheader[i+27]=(unsigned char)(os->lacing_vals[i]&0xff); + bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff); - /* set pointers in the ogg_page struct */ og->header=os->header; og->header_len=os->header_fill=vals+27; og->body=os->body_data+os->body_returned; og->body_len=bytes; - /* advance the lacing data and set the body_returned pointer */ - os->lacing_fill-=vals; memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals)); memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals)); os->body_returned+=bytes; - /* calculate the checksum */ - ogg_page_checksum_set(og); - /* done */ return(1); } -/* This constructs pages from buffered packet segments. The pointers -returned are to static buffers; do not free. The returned buffers are -good only until the next call (using the same ogg_stream_state) */ - int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){ - if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */ - os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */ - os->lacing_fill>=255 || /* 'segment table full' case */ - (os->lacing_fill&&!os->b_o_s)){ /* 'initial header page' case */ + if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */ + os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */ + os->lacing_fill>=255 || /* 'segment table full' case */ + (os->lacing_fill&&!os->b_o_s)){ /* 'initial header page' case */ - return(ogg_stream_flush(os,og)); + return(ogg_stream_flush(os,og)); } - /* not enough data to construct a page and not end of stream */ return(0); } @@ -127970,68 +117639,48 @@ int ogg_stream_eos(ogg_stream_state *os){ return os->e_o_s; } -/* DECODING PRIMITIVES: packet streaming layer **********************/ - -/* This has two layers to place more of the multi-serialno and paging - control in the application's hands. First, we expose a data buffer - using ogg_sync_buffer(). The app either copies into the - buffer, or passes it directly to read(), etc. We then call - ogg_sync_wrote() to tell how many bytes we just added. - - Pages are returned (pointers into the buffer in ogg_sync_state) - by ogg_sync_pageout(). The page is then submitted to - ogg_stream_pagein() along with the appropriate - ogg_stream_state* (ie, matching serialno). We then get raw - packets out calling ogg_stream_packetout() with a - ogg_stream_state. */ - -/* initialize the struct to a known state */ int ogg_sync_init(ogg_sync_state *oy){ if(oy){ - memset(oy,0,sizeof(*oy)); + memset(oy,0,sizeof(*oy)); } return(0); } -/* clear non-flat storage within */ int ogg_sync_clear(ogg_sync_state *oy){ if(oy){ - if(oy->data)_ogg_free(oy->data); - ogg_sync_init(oy); + if(oy->data)_ogg_free(oy->data); + ogg_sync_init(oy); } return(0); } int ogg_sync_destroy(ogg_sync_state *oy){ if(oy){ - ogg_sync_clear(oy); - _ogg_free(oy); + ogg_sync_clear(oy); + _ogg_free(oy); } return(0); } char *ogg_sync_buffer(ogg_sync_state *oy, long size){ - /* first, clear out any space that has been previously returned */ if(oy->returned){ - oy->fill-=oy->returned; - if(oy->fill>0) - memmove(oy->data,oy->data+oy->returned,oy->fill); - oy->returned=0; + oy->fill-=oy->returned; + if(oy->fill>0) + memmove(oy->data,oy->data+oy->returned,oy->fill); + oy->returned=0; } if(size>oy->storage-oy->fill){ - /* We need to extend the internal buffer */ - long newsize=size+oy->fill+4096; /* an extra page to be nice */ + long newsize=size+oy->fill+4096; /* an extra page to be nice */ - if(oy->data) - oy->data=(unsigned char*) _ogg_realloc(oy->data,newsize); - else - oy->data=(unsigned char*) _ogg_malloc(newsize); - oy->storage=newsize; + if(oy->data) + oy->data=(unsigned char*) _ogg_realloc(oy->data,newsize); + else + oy->data=(unsigned char*) _ogg_malloc(newsize); + oy->storage=newsize; } - /* expose a segment at least as large as requested at the fill mark */ return((char *)oy->data+oy->fill); } @@ -128041,85 +117690,63 @@ int ogg_sync_wrote(ogg_sync_state *oy, long bytes){ return(0); } -/* sync the stream. This is meant to be useful for finding page - boundaries. - - return values for this: - -n) skipped n bytes - 0) page not ready; more data (no bytes skipped) - n) page synced at current location; page length n bytes - -*/ - long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ unsigned char *page=oy->data+oy->returned; unsigned char *next; long bytes=oy->fill-oy->returned; if(oy->headerbytes==0){ - int headerbytes,i; - if(bytes<27)return(0); /* not enough for a header */ + int headerbytes,i; + if(bytes<27)return(0); /* not enough for a header */ - /* verify capture pattern */ - if(memcmp(page,"OggS",4))goto sync_fail; + if(memcmp(page,"OggS",4))goto sync_fail; - headerbytes=page[26]+27; - if(bytesbodybytes+=page[27+i]; - oy->headerbytes=headerbytes; + for(i=0;ibodybytes+=page[27+i]; + oy->headerbytes=headerbytes; } if(oy->bodybytes+oy->headerbytes>bytes)return(0); - /* The whole test page is buffered. Verify the checksum */ { - /* Grab the checksum bytes, set the header field to zero */ - char chksum[4]; - ogg_page log; + char chksum[4]; + ogg_page log; - memcpy(chksum,page+22,4); - memset(page+22,0,4); + memcpy(chksum,page+22,4); + memset(page+22,0,4); - /* set up a temp page struct and recompute the checksum */ - log.header=page; - log.header_len=oy->headerbytes; - log.body=page+oy->headerbytes; - log.body_len=oy->bodybytes; - ogg_page_checksum_set(&log); + log.header=page; + log.header_len=oy->headerbytes; + log.body=page+oy->headerbytes; + log.body_len=oy->bodybytes; + ogg_page_checksum_set(&log); - /* Compare */ - if(memcmp(chksum,page+22,4)){ - /* D'oh. Mismatch! Corrupt page (or miscapture and not a page - at all) */ - /* replace the computed checksum with the one actually read in */ - memcpy(page+22,chksum,4); + if(memcmp(chksum,page+22,4)){ + memcpy(page+22,chksum,4); - /* Bad checksum. Lose sync */ - goto sync_fail; - } + goto sync_fail; + } } - /* yes, have a whole page all ready to go */ { - unsigned char *page=oy->data+oy->returned; - long bytes; + unsigned char *page=oy->data+oy->returned; + long bytes; - if(og){ - og->header=page; - og->header_len=oy->headerbytes; - og->body=page+oy->headerbytes; - og->body_len=oy->bodybytes; - } + if(og){ + og->header=page; + og->header_len=oy->headerbytes; + og->body=page+oy->headerbytes; + og->body_len=oy->bodybytes; + } - oy->unsynced=0; - oy->returned+=(bytes=oy->headerbytes+oy->bodybytes); - oy->headerbytes=0; - oy->bodybytes=0; - return(bytes); + oy->unsynced=0; + oy->returned+=(bytes=oy->headerbytes+oy->bodybytes); + oy->headerbytes=0; + oy->bodybytes=0; + return(bytes); } sync_fail: @@ -128127,62 +117754,38 @@ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ oy->headerbytes=0; oy->bodybytes=0; - /* search for possible capture */ next=(unsigned char*)memchr(page+1,'O',bytes-1); if(!next) - next=oy->data+oy->fill; + next=oy->data+oy->fill; oy->returned=next-oy->data; return(-(next-page)); } -/* sync the stream and get a page. Keep trying until we find a page. - Supress 'sync errors' after reporting the first. - - return values: - -1) recapture (hole in data) - 0) need more data - 1) page returned - - Returns pointers into buffered data; invalidated by next call to - _stream, _clear, _init, or _buffer */ - int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){ - /* all we need to do is verify a page at the head of the stream - buffer. If it doesn't verify, we look for the next potential - frame */ - for(;;){ - long ret=ogg_sync_pageseek(oy,og); - if(ret>0){ - /* have a page */ - return(1); - } - if(ret==0){ - /* need more data */ - return(0); - } + long ret=ogg_sync_pageseek(oy,og); + if(ret>0){ + return(1); + } + if(ret==0){ + return(0); + } - /* head did not start a synced page... skipped some bytes */ - if(!oy->unsynced){ - oy->unsynced=1; - return(-1); - } - - /* loop. keep looking */ + if(!oy->unsynced){ + oy->unsynced=1; + return(-1); + } } } -/* add the incoming page to the stream state; we decompose the page - into packet segments here as well. */ - int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){ unsigned char *header=og->header; unsigned char *body=og->body; - long bodysize=og->body_len; - int segptr=0; + long bodysize=og->body_len; + int segptr=0; int version=ogg_page_version(og); int continued=ogg_page_continued(og); @@ -128193,62 +117796,53 @@ int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){ long pageno=ogg_page_pageno(og); int segments=header[26]; - /* clean up 'returned data' */ { - long lr=os->lacing_returned; - long br=os->body_returned; + long lr=os->lacing_returned; + long br=os->body_returned; - /* body data */ - if(br){ - os->body_fill-=br; - if(os->body_fill) + if(br){ + os->body_fill-=br; + if(os->body_fill) memmove(os->body_data,os->body_data+br,os->body_fill); - os->body_returned=0; - } + os->body_returned=0; + } - if(lr){ - /* segment table */ - if(os->lacing_fill-lr){ + if(lr){ + if(os->lacing_fill-lr){ memmove(os->lacing_vals,os->lacing_vals+lr, (os->lacing_fill-lr)*sizeof(*os->lacing_vals)); memmove(os->granule_vals,os->granule_vals+lr, (os->lacing_fill-lr)*sizeof(*os->granule_vals)); - } - os->lacing_fill-=lr; - os->lacing_packet-=lr; - os->lacing_returned=0; - } + } + os->lacing_fill-=lr; + os->lacing_packet-=lr; + os->lacing_returned=0; + } } - /* check the serial number */ if(serialno!=os->serialno)return(-1); if(version>0)return(-1); _os_lacing_expand(os,segments+1); - /* are we in sequence? */ if(pageno!=os->pageno){ - int i; + int i; - /* unroll previous partial packet (if any) */ - for(i=os->lacing_packet;ilacing_fill;i++) - os->body_fill-=os->lacing_vals[i]&0xff; - os->lacing_fill=os->lacing_packet; + for(i=os->lacing_packet;ilacing_fill;i++) + os->body_fill-=os->lacing_vals[i]&0xff; + os->lacing_fill=os->lacing_packet; - /* make a note of dropped data in segment table */ - if(os->pageno!=-1){ - os->lacing_vals[os->lacing_fill++]=0x400; - os->lacing_packet++; - } + if(os->pageno!=-1){ + os->lacing_vals[os->lacing_fill++]=0x400; + os->lacing_packet++; + } } - /* are we a 'continued packet' page? If so, we may need to skip - some segments */ if(continued){ - if(os->lacing_fill<1 || - os->lacing_vals[os->lacing_fill-1]==0x400){ - bos=0; - for(;segptrlacing_fill<1 || + os->lacing_vals[os->lacing_fill-1]==0x400){ + bos=0; + for(;segptrbody_data+os->body_fill,body,bodysize); - os->body_fill+=bodysize; + _os_body_expand(os,bodysize); + memcpy(os->body_data+os->body_fill,body,bodysize); + os->body_fill+=bodysize; } { - int saved=-1; - while(segptrlacing_vals[os->lacing_fill]=val; - os->granule_vals[os->lacing_fill]=-1; + int saved=-1; + while(segptrlacing_vals[os->lacing_fill]=val; + os->granule_vals[os->lacing_fill]=-1; - if(bos){ + if(bos){ os->lacing_vals[os->lacing_fill]|=0x100; bos=0; - } + } - if(val<255)saved=os->lacing_fill; + if(val<255)saved=os->lacing_fill; - os->lacing_fill++; - segptr++; + os->lacing_fill++; + segptr++; - if(val<255)os->lacing_packet=os->lacing_fill; - } + if(val<255)os->lacing_packet=os->lacing_fill; + } - /* set the granulepos on the last granuleval of the last full packet */ - if(saved!=-1){ - os->granule_vals[saved]=granulepos; - } + if(saved!=-1){ + os->granule_vals[saved]=granulepos; + } } if(eos){ - os->e_o_s=1; - if(os->lacing_fill>0) - os->lacing_vals[os->lacing_fill-1]|=0x200; + os->e_o_s=1; + if(os->lacing_fill>0) + os->lacing_vals[os->lacing_fill-1]|=0x200; } os->pageno=pageno+1; @@ -128304,7 +117897,6 @@ int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){ return(0); } -/* clear things to an initial state. Good to call, eg, before seeking */ int ogg_sync_reset(ogg_sync_state *oy){ oy->fill=0; oy->returned=0; @@ -128341,54 +117933,47 @@ int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){ static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){ - /* The last part of decode. We have the stream broken into packet - segments. Now we need to group them into packets (or return the - out of sync markers) */ - int ptr=os->lacing_returned; if(os->lacing_packet<=ptr)return(0); if(os->lacing_vals[ptr]&0x400){ - /* we need to tell the codec there's a gap; it might need to - handle previous packet dependencies. */ - os->lacing_returned++; - os->packetno++; - return(-1); + os->lacing_returned++; + os->packetno++; + return(-1); } if(!op && !adv)return(1); /* just using peek as an inexpensive way - to ask if there's a whole packet - waiting */ + to ask if there's a whole packet + waiting */ - /* Gather the whole packet. We'll have no holes or a partial packet */ { - int size=os->lacing_vals[ptr]&0xff; - int bytes=size; - int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */ - int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */ + int size=os->lacing_vals[ptr]&0xff; + int bytes=size; + int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */ + int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */ - while(size==255){ - int val=os->lacing_vals[++ptr]; - size=val&0xff; - if(val&0x200)eos=0x200; - bytes+=size; - } + while(size==255){ + int val=os->lacing_vals[++ptr]; + size=val&0xff; + if(val&0x200)eos=0x200; + bytes+=size; + } - if(op){ - op->e_o_s=eos; - op->b_o_s=bos; - op->packet=os->body_data+os->body_returned; - op->packetno=os->packetno; - op->granulepos=os->granule_vals[ptr]; - op->bytes=bytes; - } + if(op){ + op->e_o_s=eos; + op->b_o_s=bos; + op->packet=os->body_data+os->body_returned; + op->packetno=os->packetno; + op->granulepos=os->granule_vals[ptr]; + op->bytes=bytes; + } - if(adv){ - os->body_returned+=bytes; - os->lacing_returned=ptr+1; - os->packetno++; - } + if(adv){ + os->body_returned+=bytes; + os->lacing_returned=ptr+1; + os->packetno++; + } } return(1); } @@ -128418,63 +118003,58 @@ void checkpacket(ogg_packet *op,int len, int no, int pos){ static int lastno=0; if(op->bytes!=len){ - fprintf(stderr,"incorrect packet length!\n"); - exit(1); + fprintf(stderr,"incorrect packet length!\n"); + exit(1); } if(op->granulepos!=pos){ - fprintf(stderr,"incorrect packet position!\n"); - exit(1); + fprintf(stderr,"incorrect packet position!\n"); + exit(1); } - /* packet number just follows sequence/gap; adjust the input number - for that */ if(no==0){ - sequence=0; + sequence=0; }else{ - sequence++; - if(no>lastno+1) - sequence++; + sequence++; + if(no>lastno+1) + sequence++; } lastno=no; if(op->packetno!=sequence){ - fprintf(stderr,"incorrect packet sequence %ld != %d\n", - (long)(op->packetno),sequence); - exit(1); + fprintf(stderr,"incorrect packet sequence %ld != %d\n", + (long)(op->packetno),sequence); + exit(1); } - /* Test data */ for(j=0;jbytes;j++) - if(op->packet[j]!=((j+no)&0xff)){ - fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n", - j,op->packet[j],(j+no)&0xff); - exit(1); - } + if(op->packet[j]!=((j+no)&0xff)){ + fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n", + j,op->packet[j],(j+no)&0xff); + exit(1); + } } void check_page(unsigned char *data,const int *header,ogg_page *og){ long j; - /* Test data */ for(j=0;jbody_len;j++) - if(og->body[j]!=data[j]){ - fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n", - j,data[j],og->body[j]); - exit(1); - } + if(og->body[j]!=data[j]){ + fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n", + j,data[j],og->body[j]); + exit(1); + } - /* Test header */ for(j=0;jheader_len;j++){ - if(og->header[j]!=header[j]){ - fprintf(stderr,"header content mismatch at pos %ld:\n",j); - for(j=0;jheader[j]!=header[j]){ + fprintf(stderr,"header content mismatch at pos %ld:\n",j); + for(j=0;jheader[j]); - fprintf(stderr,"\n"); - exit(1); - } + fprintf(stderr,"\n"); + exit(1); + } } if(og->header_len!=header[26]+27){ - fprintf(stderr,"header length incorrect! (%ld!=%d)\n", - og->header_len,header[26]+27); - exit(1); + fprintf(stderr,"header length incorrect! (%ld!=%d)\n", + og->header_len,header[26]+27); + exit(1); } } @@ -128499,7 +118079,7 @@ void print_header(ogg_page *og){ (int)og->header[26]); for(j=27;jheader_len;j++) - fprintf(stderr,"%d ",(int)og->header[j]); + fprintf(stderr,"%d ",(int)og->header[j]); fprintf(stderr,")\n\n"); } @@ -128523,191 +118103,183 @@ void error(void){ exit(1); } -/* 17 only */ const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,0,0,0,0, - 0x15,0xed,0xec,0x91, - 1, - 17}; + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0x15,0xed,0xec,0x91, + 1, + 17}; -/* 17, 254, 255, 256, 500, 510, 600 byte, pad */ const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,0,0,0,0, - 0x59,0x10,0x6c,0x2c, - 1, - 17}; + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0x59,0x10,0x6c,0x2c, + 1, + 17}; const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04, - 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,1,0,0,0, - 0x89,0x33,0x85,0xce, - 13, - 254,255,0,255,1,255,245,255,255,0, - 255,255,90}; + 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x89,0x33,0x85,0xce, + 13, + 254,255,0,255,1,255,245,255,255,0, + 255,255,90}; -/* nil packets; beginning,middle,end */ const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,0,0,0,0, - 0xff,0x7b,0x23,0x17, - 1, - 0}; + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04, - 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,1,0,0,0, - 0x5c,0x3f,0x66,0xcb, - 17, - 17,254,255,0,0,255,1,0,255,245,255,255,0, - 255,255,90,0}; + 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x5c,0x3f,0x66,0xcb, + 17, + 17,254,255,0,0,255,1,0,255,245,255,255,0, + 255,255,90,0}; -/* large initial packet */ const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,0,0,0,0, - 0x01,0x27,0x31,0xaa, - 18, - 255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255,255,10}; + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0x01,0x27,0x31,0xaa, + 18, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,10}; const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04, - 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,1,0,0,0, - 0x7f,0x4e,0x8a,0xd2, - 4, - 255,4,255,0}; + 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x7f,0x4e,0x8a,0xd2, + 4, + 255,4,255,0}; -/* continuing packet test */ const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,0,0,0,0, - 0xff,0x7b,0x23,0x17, - 1, - 0}; + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x01,0x02,0x03,0x04,1,0,0,0, - 0x54,0x05,0x51,0xc8, - 17, - 255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255,255}; + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x54,0x05,0x51,0xc8, + 17, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255}; const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05, - 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,2,0,0,0, - 0xc8,0xc3,0xcb,0xed, - 5, - 10,255,4,255,0}; + 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0xc8,0xc3,0xcb,0xed, + 5, + 10,255,4,255,0}; -/* page with the 255 segment limit */ const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,0,0,0,0, - 0xff,0x7b,0x23,0x17, - 1, - 0}; + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00, - 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,1,0,0,0, - 0xed,0x2a,0x2e,0xa7, - 255, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10,10, - 10,10,10,10,10,10,10}; + 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0xed,0x2a,0x2e,0xa7, + 255, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10}; const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04, - 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,2,0,0,0, - 0x6c,0x3b,0x82,0x3d, - 1, - 50}; + 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0x6c,0x3b,0x82,0x3d, + 1, + 50}; -/* packet that overspans over an entire page */ const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,0,0,0,0, - 0xff,0x7b,0x23,0x17, - 1, - 0}; + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00, - 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,1,0,0,0, - 0x3c,0xd9,0x4d,0x3f, - 17, - 100,255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255}; + 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x3c,0xd9,0x4d,0x3f, + 17, + 100,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255}; const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x01,0x02,0x03,0x04,2,0,0,0, - 0x01,0xd2,0xe5,0xe5, - 17, - 255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255,255}; + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0x01,0xd2,0xe5,0xe5, + 17, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255}; const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05, - 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,3,0,0,0, - 0xef,0xdd,0x88,0xde, - 7, - 255,255,75,255,4,255,0}; + 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,3,0,0,0, + 0xef,0xdd,0x88,0xde, + 7, + 255,255,75,255,4,255,0}; -/* packet that overspans over an entire page */ const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,0,0,0,0, - 0xff,0x7b,0x23,0x17, - 1, - 0}; + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00, - 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,1,0,0,0, - 0x3c,0xd9,0x4d,0x3f, - 17, - 100,255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255}; + 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x3c,0xd9,0x4d,0x3f, + 17, + 100,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255}; const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05, - 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,2,0,0,0, - 0xd4,0xe0,0x60,0xe5, - 1,0}; + 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0xd4,0xe0,0x60,0xe5, + 1,0}; void test_pack(const int *pl, const int **headers, int byteskip, - int pageskip, int packetskip){ + int pageskip, int packetskip){ unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */ long inptr=0; long outptr=0; @@ -128725,33 +118297,29 @@ void test_pack(const int *pl, const int **headers, int byteskip, ogg_sync_reset(&oy); for(packets=0;packetsbyteskip){ - memcpy(next,og.header,byteskipcount-byteskip); - next+=byteskipcount-byteskip; - byteskipcount=byteskip; + memcpy(next,og.header,byteskipcount-byteskip); + next+=byteskipcount-byteskip; + byteskipcount=byteskip; } byteskipcount+=og.body_len; if(byteskipcount>byteskip){ - memcpy(next,og.body,byteskipcount-byteskip); - next+=byteskipcount-byteskip; - byteskipcount=byteskip; + memcpy(next,og.body,byteskipcount-byteskip); + next+=byteskipcount-byteskip; + byteskipcount=byteskip; } ogg_sync_wrote(&oy,next-buf); while(1){ - int ret=ogg_sync_pageout(&oy,&og_de); - if(ret==0)break; - if(ret<0)continue; - /* got a page. Happy happy. Verify that it's good. */ + int ret=ogg_sync_pageout(&oy,&og_de); + if(ret==0)break; + if(ret<0)continue; fprintf(stderr,"(%ld), ",pageout); - check_page(data+deptr,headers[pageout],&og_de); - deptr+=og_de.body_len; - pageout++; + check_page(data+deptr,headers[pageout],&og_de); + deptr+=og_de.body_len; + pageout++; - /* submit it to deconstitution */ - ogg_stream_pagein(&os_de,&og_de); + ogg_stream_pagein(&os_de,&og_de); - /* packets out? */ - while(ogg_stream_packetpeek(&os_de,&op_de2)>0){ - ogg_stream_packetpeek(&os_de,NULL); - ogg_stream_packetout(&os_de,&op_de); /* just catching them all */ + while(ogg_stream_packetpeek(&os_de,&op_de2)>0){ + ogg_stream_packetpeek(&os_de,NULL); + ogg_stream_packetout(&os_de,&op_de); /* just catching them all */ - /* verify peek and out match */ - if(memcmp(&op_de,&op_de2,sizeof(op_de))){ + if(memcmp(&op_de,&op_de2,sizeof(op_de))){ fprintf(stderr,"packetout != packetpeek! pos=%ld\n", depacket); exit(1); - } + } - /* verify the packet! */ - /* check data */ - if(memcmp(data+depacket,op_de.packet,op_de.bytes)){ + if(memcmp(data+depacket,op_de.packet,op_de.bytes)){ fprintf(stderr,"packet data mismatch in decode! pos=%ld\n", depacket); exit(1); - } - /* check bos flag */ - if(bosflag==0 && op_de.b_o_s==0){ + } + if(bosflag==0 && op_de.b_o_s==0){ fprintf(stderr,"b_o_s flag not set on packet!\n"); exit(1); - } - if(bosflag && op_de.b_o_s){ + } + if(bosflag && op_de.b_o_s){ fprintf(stderr,"b_o_s flag incorrectly set on packet!\n"); exit(1); - } - bosflag=1; - depacket+=op_de.bytes; + } + bosflag=1; + depacket+=op_de.bytes; - /* check eos flag */ - if(eosflag){ + if(eosflag){ fprintf(stderr,"Multiple decoded packets with eos flag!\n"); exit(1); - } + } - if(op_de.e_o_s)eosflag=1; + if(op_de.e_o_s)eosflag=1; - /* check granulepos flag */ - if(op_de.granulepos!=-1){ + if(op_de.granulepos!=-1){ fprintf(stderr," granule:%ld ",(long)op_de.granulepos); - } - } + } + } + } + } } } - } - } } _ogg_free(data); if(headers[pageno]!=NULL){ - fprintf(stderr,"did not write last page!\n"); - exit(1); + fprintf(stderr,"did not write last page!\n"); + exit(1); } if(headers[pageout]!=NULL){ - fprintf(stderr,"did not decode last page!\n"); - exit(1); + fprintf(stderr,"did not decode last page!\n"); + exit(1); } if(inptr!=outptr){ - fprintf(stderr,"encoded page data incomplete!\n"); - exit(1); + fprintf(stderr,"encoded page data incomplete!\n"); + exit(1); } if(inptr!=deptr){ - fprintf(stderr,"decoded page data incomplete!\n"); - exit(1); + fprintf(stderr,"decoded page data incomplete!\n"); + exit(1); } if(inptr!=depacket){ - fprintf(stderr,"decoded packet data incomplete!\n"); - exit(1); + fprintf(stderr,"decoded packet data incomplete!\n"); + exit(1); } if(!eosflag){ - fprintf(stderr,"Never got a packet with EOS set!\n"); - exit(1); + fprintf(stderr,"Never got a packet with EOS set!\n"); + exit(1); } fprintf(stderr,"ok.\n"); } @@ -128891,58 +118448,49 @@ int main(void){ ogg_stream_init(&os_de,0x04030201); ogg_sync_init(&oy); - /* Exercise each code path in the framing code. Also verify that - the checksums are working. */ - { - /* 17 only */ - const int packets[]={17, -1}; - const int *headret[]={head1_0,NULL}; + const int packets[]={17, -1}; + const int *headret[]={head1_0,NULL}; - fprintf(stderr,"testing single page encoding... "); - test_pack(packets,headret,0,0,0); + fprintf(stderr,"testing single page encoding... "); + test_pack(packets,headret,0,0,0); } { - /* 17, 254, 255, 256, 500, 510, 600 byte, pad */ - const int packets[]={17, 254, 255, 256, 500, 510, 600, -1}; - const int *headret[]={head1_1,head2_1,NULL}; + const int packets[]={17, 254, 255, 256, 500, 510, 600, -1}; + const int *headret[]={head1_1,head2_1,NULL}; - fprintf(stderr,"testing basic page encoding... "); - test_pack(packets,headret,0,0,0); + fprintf(stderr,"testing basic page encoding... "); + test_pack(packets,headret,0,0,0); } { - /* nil packets; beginning,middle,end */ - const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1}; - const int *headret[]={head1_2,head2_2,NULL}; + const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1}; + const int *headret[]={head1_2,head2_2,NULL}; - fprintf(stderr,"testing basic nil packets... "); - test_pack(packets,headret,0,0,0); + fprintf(stderr,"testing basic nil packets... "); + test_pack(packets,headret,0,0,0); } { - /* large initial packet */ - const int packets[]={4345,259,255,-1}; - const int *headret[]={head1_3,head2_3,NULL}; + const int packets[]={4345,259,255,-1}; + const int *headret[]={head1_3,head2_3,NULL}; - fprintf(stderr,"testing initial-packet lacing > 4k... "); - test_pack(packets,headret,0,0,0); + fprintf(stderr,"testing initial-packet lacing > 4k... "); + test_pack(packets,headret,0,0,0); } { - /* continuing packet test */ - const int packets[]={0,4345,259,255,-1}; - const int *headret[]={head1_4,head2_4,head3_4,NULL}; + const int packets[]={0,4345,259,255,-1}; + const int *headret[]={head1_4,head2_4,head3_4,NULL}; - fprintf(stderr,"testing single packet page span... "); - test_pack(packets,headret,0,0,0); + fprintf(stderr,"testing single packet page span... "); + test_pack(packets,headret,0,0,0); } - /* page with the 255 segment limit */ { - const int packets[]={0,10,10,10,10,10,10,10,10, + const int packets[]={0,10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, @@ -128974,323 +118522,298 @@ int main(void){ 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,10, 10,10,10,10,10,10,10,50,-1}; - const int *headret[]={head1_5,head2_5,head3_5,NULL}; + const int *headret[]={head1_5,head2_5,head3_5,NULL}; - fprintf(stderr,"testing max packet segments... "); - test_pack(packets,headret,0,0,0); + fprintf(stderr,"testing max packet segments... "); + test_pack(packets,headret,0,0,0); } { - /* packet that overspans over an entire page */ - const int packets[]={0,100,9000,259,255,-1}; - const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; + const int packets[]={0,100,9000,259,255,-1}; + const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; - fprintf(stderr,"testing very large packets... "); - test_pack(packets,headret,0,0,0); + fprintf(stderr,"testing very large packets... "); + test_pack(packets,headret,0,0,0); } { - /* test for the libogg 1.1.1 resync in large continuation bug - found by Josh Coalson) */ - const int packets[]={0,100,9000,259,255,-1}; - const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; + const int packets[]={0,100,9000,259,255,-1}; + const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; - fprintf(stderr,"testing continuation resync in very large packets... "); - test_pack(packets,headret,100,2,3); + fprintf(stderr,"testing continuation resync in very large packets... "); + test_pack(packets,headret,100,2,3); } { - /* term only page. why not? */ - const int packets[]={0,100,4080,-1}; - const int *headret[]={head1_7,head2_7,head3_7,NULL}; + const int packets[]={0,100,4080,-1}; + const int *headret[]={head1_7,head2_7,head3_7,NULL}; - fprintf(stderr,"testing zero data page (1 nil packet)... "); - test_pack(packets,headret,0,0,0); + fprintf(stderr,"testing zero data page (1 nil packet)... "); + test_pack(packets,headret,0,0,0); } { - /* build a bunch of pages for testing */ - unsigned char *data=_ogg_malloc(1024*1024); - int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1}; - int inptr=0,i,j; - ogg_page og[5]; + unsigned char *data=_ogg_malloc(1024*1024); + int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1}; + int inptr=0,i,j; + ogg_page og[5]; - ogg_stream_reset(&os_en); + ogg_stream_reset(&os_en); - for(i=0;pl[i]!=-1;i++){ - ogg_packet op; - int len=pl[i]; + for(i=0;pl[i]!=-1;i++){ + ogg_packet op; + int len=pl[i]; - op.packet=data+inptr; - op.bytes=len; - op.e_o_s=(pl[i+1]<0?1:0); - op.granulepos=(i+1)*1000; + op.packet=data+inptr; + op.bytes=len; + op.e_o_s=(pl[i+1]<0?1:0); + op.granulepos=(i+1)*1000; - for(j=0;j0)error(); + { + ogg_page og_de; + fprintf(stderr,"Testing sync on partial inputs... "); + ogg_sync_reset(&oy); + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + 3); + ogg_sync_wrote(&oy,3); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); - /* Test fractional page inputs: incomplete fixed header */ - memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3, - 20); - ogg_sync_wrote(&oy,20); - if(ogg_sync_pageout(&oy,&og_de)>0)error(); + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3, + 20); + ogg_sync_wrote(&oy,20); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); - /* Test fractional page inputs: incomplete header */ - memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23, - 5); - ogg_sync_wrote(&oy,5); - if(ogg_sync_pageout(&oy,&og_de)>0)error(); + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23, + 5); + ogg_sync_wrote(&oy,5); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); - /* Test fractional page inputs: incomplete body */ + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28, + og[1].header_len-28); + ogg_sync_wrote(&oy,og[1].header_len-28); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); - memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28, - og[1].header_len-28); - ogg_sync_wrote(&oy,og[1].header_len-28); - if(ogg_sync_pageout(&oy,&og_de)>0)error(); + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000); + ogg_sync_wrote(&oy,1000); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); - memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000); - ogg_sync_wrote(&oy,1000); - if(ogg_sync_pageout(&oy,&og_de)>0)error(); + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000, + og[1].body_len-1000); + ogg_sync_wrote(&oy,og[1].body_len-1000); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); - memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000, - og[1].body_len-1000); - ogg_sync_wrote(&oy,og[1].body_len-1000); - if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + fprintf(stderr,"ok.\n"); + } - fprintf(stderr,"ok.\n"); - } + { + ogg_page og_de; + fprintf(stderr,"Testing sync on 1+partial inputs... "); + ogg_sync_reset(&oy); - /* Test fractional page inputs: page + incomplete capture */ - { - ogg_page og_de; - fprintf(stderr,"Testing sync on 1+partial inputs... "); - ogg_sync_reset(&oy); + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + og[1].header_len); + ogg_sync_wrote(&oy,og[1].header_len); - memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, - og[1].header_len); - ogg_sync_wrote(&oy,og[1].header_len); + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); - memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, - og[1].body_len); - ogg_sync_wrote(&oy,og[1].body_len); + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + 20); + ogg_sync_wrote(&oy,20); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); - memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, - 20); - ogg_sync_wrote(&oy,20); - if(ogg_sync_pageout(&oy,&og_de)<=0)error(); - if(ogg_sync_pageout(&oy,&og_de)>0)error(); + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20, + og[1].header_len-20); + ogg_sync_wrote(&oy,og[1].header_len-20); + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); - memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20, - og[1].header_len-20); - ogg_sync_wrote(&oy,og[1].header_len-20); - memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, - og[1].body_len); - ogg_sync_wrote(&oy,og[1].body_len); - if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + fprintf(stderr,"ok.\n"); + } - fprintf(stderr,"ok.\n"); - } + { + ogg_page og_de; + fprintf(stderr,"Testing search for capture... "); + ogg_sync_reset(&oy); - /* Test recapture: garbage + page */ - { - ogg_page og_de; - fprintf(stderr,"Testing search for capture... "); - ogg_sync_reset(&oy); + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); - /* 'garbage' */ - memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, - og[1].body_len); - ogg_sync_wrote(&oy,og[1].body_len); + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + og[1].header_len); + ogg_sync_wrote(&oy,og[1].header_len); - memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, - og[1].header_len); - ogg_sync_wrote(&oy,og[1].header_len); + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); - memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, - og[1].body_len); - ogg_sync_wrote(&oy,og[1].body_len); + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, + 20); + ogg_sync_wrote(&oy,20); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); - memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, - 20); - ogg_sync_wrote(&oy,20); - if(ogg_sync_pageout(&oy,&og_de)>0)error(); - if(ogg_sync_pageout(&oy,&og_de)<=0)error(); - if(ogg_sync_pageout(&oy,&og_de)>0)error(); + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20, + og[2].header_len-20); + ogg_sync_wrote(&oy,og[2].header_len-20); + memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body, + og[2].body_len); + ogg_sync_wrote(&oy,og[2].body_len); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); - memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20, - og[2].header_len-20); - ogg_sync_wrote(&oy,og[2].header_len-20); - memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body, - og[2].body_len); - ogg_sync_wrote(&oy,og[2].body_len); - if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + fprintf(stderr,"ok.\n"); + } - fprintf(stderr,"ok.\n"); - } + { + ogg_page og_de; + fprintf(stderr,"Testing recapture... "); + ogg_sync_reset(&oy); - /* Test recapture: page + garbage + page */ - { - ogg_page og_de; - fprintf(stderr,"Testing recapture... "); - ogg_sync_reset(&oy); + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + og[1].header_len); + ogg_sync_wrote(&oy,og[1].header_len); - memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, - og[1].header_len); - ogg_sync_wrote(&oy,og[1].header_len); + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); - memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, - og[1].body_len); - ogg_sync_wrote(&oy,og[1].body_len); + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, + og[2].header_len); + ogg_sync_wrote(&oy,og[2].header_len); - memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, - og[2].header_len); - ogg_sync_wrote(&oy,og[2].header_len); + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, + og[2].header_len); + ogg_sync_wrote(&oy,og[2].header_len); - memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, - og[2].header_len); - ogg_sync_wrote(&oy,og[2].header_len); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); - if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body, + og[2].body_len-5); + ogg_sync_wrote(&oy,og[2].body_len-5); - memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body, - og[2].body_len-5); - ogg_sync_wrote(&oy,og[2].body_len-5); + memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header, + og[3].header_len); + ogg_sync_wrote(&oy,og[3].header_len); - memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header, - og[3].header_len); - ogg_sync_wrote(&oy,og[3].header_len); + memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body, + og[3].body_len); + ogg_sync_wrote(&oy,og[3].body_len); - memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body, - og[3].body_len); - ogg_sync_wrote(&oy,og[3].body_len); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); - if(ogg_sync_pageout(&oy,&og_de)>0)error(); - if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + fprintf(stderr,"ok.\n"); + } - fprintf(stderr,"ok.\n"); - } - - /* Free page data that was previously copied */ - { - for(i=0;i<5;i++){ + { + for(i=0;i<5;i++){ free_page(&og[i]); - } - } + } + } } return(0); @@ -129330,7 +118853,6 @@ int main(void){ #ifndef _OGG_mdct_H_ #define _OGG_mdct_H_ -/*#define MDCT_INTEGERIZED <- be warned there could be some hurt left here*/ #ifdef MDCT_INTEGERIZED #define DATA_TYPE int @@ -129363,7 +118885,7 @@ typedef struct { int log2n; DATA_TYPE *trig; - int *bitrev; + int *bitrev; DATA_TYPE scale; } mdct_lookup; @@ -129376,10 +118898,10 @@ extern void mdct_backward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out); #endif /********* End of inlined file: mdct.h *********/ -#define VE_PRE 16 -#define VE_WIN 4 +#define VE_PRE 16 +#define VE_WIN 4 #define VE_POST 2 -#define VE_AMP (VE_PRE+VE_POST-1) +#define VE_AMP (VE_PRE+VE_POST-1) #define VE_BANDS 7 #define VE_NEARDC 15 @@ -129412,13 +118934,13 @@ typedef struct { float minenergy; mdct_lookup mdct; - float *mdct_win; + float *mdct_win; - envelope_band band[VE_BANDS]; + envelope_band band[VE_BANDS]; envelope_filter_state *filter; int stretch; - int *mark; + int *mark; long storage; long current; @@ -129439,40 +118961,24 @@ extern int _ve_envelope_mark(vorbis_dsp_state *v); #ifndef _V_CODEBOOK_H_ #define _V_CODEBOOK_H_ -/* This structure encapsulates huffman and VQ style encoding books; it - doesn't do anything specific to either. - - valuelist/quantlist are nonNULL (and q_* significant) only if - there's entry->value mapping to be done. - - If encode-side mapping must be done (and thus the entry needs to be - hunted), the auxiliary encode pointer will point to a decision - tree. This is true of both VQ and huffman, but is mostly useful - with VQ. - -*/ - typedef struct static_codebook{ - long dim; /* codebook dimensions (elements per vector) */ - long entries; /* codebook entries */ - long *lengthlist; /* codeword lengths in bits */ + long dim; /* codebook dimensions (elements per vector) */ + long entries; /* codebook entries */ + long *lengthlist; /* codeword lengths in bits */ - /* mapping ***************************************************************/ - int maptype; /* 0=none - 1=implicitly populated values from map column - 2=listed arbitrary values */ + int maptype; /* 0=none + 1=implicitly populated values from map column + 2=listed arbitrary values */ - /* The below does a linear, single monotonic sequence mapping. */ - long q_min; /* packed 32 bit float; quant value 0 maps to minval */ - long q_delta; /* packed 32 bit float; val 1 - val 0 == delta */ - int q_quant; /* bits: 0 < quant <= 16 */ - int q_sequencep; /* bitflag */ + long q_min; /* packed 32 bit float; quant value 0 maps to minval */ + long q_delta; /* packed 32 bit float; val 1 - val 0 == delta */ + int q_quant; /* bits: 0 < quant <= 16 */ + int q_sequencep; /* bitflag */ - long *quantlist; /* map == 1: (int)(entries^(1/dim)) element column map + long *quantlist; /* map == 1: (int)(entries^(1/dim)) element column map map == 2: list of dim*entries quantized entry vals */ - /* encode helpers ********************************************************/ struct encode_aux_nearestmatch *nearest_tree; struct encode_aux_threshmatch *thresh_tree; struct encode_aux_pigeonhole *pigeon_tree; @@ -129480,25 +118986,21 @@ typedef struct static_codebook{ int allocedp; } static_codebook; -/* this structures an arbitrary trained book to quickly find the - nearest cell match */ typedef struct encode_aux_nearestmatch{ - /* pre-calculated partitioning tree */ long *ptr0; long *ptr1; - long *p; /* decision points (each is an entry) */ - long *q; /* decision points (each is an entry) */ - long aux; /* number of tree entries */ + long *p; /* decision points (each is an entry) */ + long *q; /* decision points (each is an entry) */ + long aux; /* number of tree entries */ long alloc; } encode_aux_nearestmatch; -/* assumes a maptype of 1; encode side only, so that's OK */ typedef struct encode_aux_threshmatch{ float *quantthresh; long *quantmap; - int quantvals; - int threshvals; + int quantvals; + int threshvals; } encode_aux_threshmatch; typedef struct encode_aux_pigeonhole{ @@ -129516,22 +119018,19 @@ typedef struct encode_aux_pigeonhole{ } encode_aux_pigeonhole; typedef struct codebook{ - long dim; /* codebook dimensions (elements per vector) */ - long entries; /* codebook entries */ + long dim; /* codebook dimensions (elements per vector) */ + long entries; /* codebook entries */ long used_entries; /* populated codebook entries */ const static_codebook *c; - /* for encode, the below are entry-ordered, fully populated */ - /* for decode, the below are ordered by bitreversed codeword and only - used entries are populated */ - float *valuelist; /* list of dim*entries actual entry values */ + float *valuelist; /* list of dim*entries actual entry values */ ogg_uint32_t *codelist; /* list of bitstream codewords for each entry */ - int *dec_index; /* only used if sparseness collapsed */ - char *dec_codelengths; + int *dec_index; /* only used if sparseness collapsed */ + char *dec_codelengths; ogg_uint32_t *dec_firsttable; - int dec_firsttablen; - int dec_maxlength; + int dec_firsttablen; + int dec_maxlength; } codebook; @@ -129559,45 +119058,44 @@ extern int vorbis_staticbook_unpack(oggpack_buffer *b,static_codebook *c); extern int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b); extern int vorbis_book_errorv(codebook *book, float *a); extern int vorbis_book_encodev(codebook *book, int best,float *a, - oggpack_buffer *b); + oggpack_buffer *b); extern long vorbis_book_decode(codebook *book, oggpack_buffer *b); extern long vorbis_book_decodevs_add(codebook *book, float *a, - oggpack_buffer *b,int n); + oggpack_buffer *b,int n); extern long vorbis_book_decodev_set(codebook *book, float *a, - oggpack_buffer *b,int n); + oggpack_buffer *b,int n); extern long vorbis_book_decodev_add(codebook *book, float *a, - oggpack_buffer *b,int n); + oggpack_buffer *b,int n); extern long vorbis_book_decodevv_add(codebook *book, float **a, - long off,int ch, - oggpack_buffer *b,int n); + long off,int ch, + oggpack_buffer *b,int n); #endif /********* End of inlined file: codebook.h *********/ -#define BLOCKTYPE_IMPULSE 0 -#define BLOCKTYPE_PADDING 1 +#define BLOCKTYPE_IMPULSE 0 +#define BLOCKTYPE_PADDING 1 #define BLOCKTYPE_TRANSITION 0 -#define BLOCKTYPE_LONG 1 +#define BLOCKTYPE_LONG 1 #define PACKETBLOBS 15 typedef struct vorbis_block_internal{ float **pcmdelay; /* this is a pointer into local storage */ float ampmax; - int blocktype; + int blocktype; oggpack_buffer *packetblob[PACKETBLOBS]; /* initialized, must be freed; - blob [PACKETBLOBS/2] points to - the oggpack_buffer in the - main vorbis_block */ + blob [PACKETBLOBS/2] points to + the oggpack_buffer in the + main vorbis_block */ } vorbis_block_internal; typedef void vorbis_look_floor; typedef void vorbis_look_residue; typedef void vorbis_look_transform; -/* mode ************************************************************/ typedef struct { int blockflag; int windowtype; @@ -129632,24 +119130,19 @@ extern void drft_clear(drft_lookup *l); /********* End of inlined file: smallft.h *********/ /********* Start of inlined file: backends.h *********/ -/* this is exposed up here because we need it for static modes. - Lookups for each backend aren't exposed because there's no reason - to do so */ #ifndef _vorbis_backend_h_ #define _vorbis_backend_h_ -/* this would all be simpler/shorter with templates, but.... */ -/* Floor backend generic *****************************************/ typedef struct{ - void (*pack) (vorbis_info_floor *,oggpack_buffer *); - vorbis_info_floor *(*unpack)(vorbis_info *,oggpack_buffer *); - vorbis_look_floor *(*look) (vorbis_dsp_state *,vorbis_info_floor *); + void (*pack) (vorbis_info_floor *,oggpack_buffer *); + vorbis_info_floor *(*unpack)(vorbis_info *,oggpack_buffer *); + vorbis_look_floor *(*look) (vorbis_dsp_state *,vorbis_info_floor *); void (*free_info) (vorbis_info_floor *); void (*free_look) (vorbis_look_floor *); void *(*inverse1) (struct vorbis_block *,vorbis_look_floor *); int (*inverse2) (struct vorbis_block *,vorbis_look_floor *, - void *buffer,float *); + void *buffer,float *); } vorbis_func_floor; typedef struct{ @@ -129663,7 +119156,7 @@ typedef struct{ int numbooks; /* <= 16 */ int books[16]; - float lessthan; /* encode-only config setting hacks for libvorbis */ + float lessthan; /* encode-only config setting hacks for libvorbis */ float greaterthan; /* encode-only config setting hacks for libvorbis */ } vorbis_info_floor0; @@ -129672,18 +119165,17 @@ typedef struct{ #define VIF_CLASS 16 #define VIF_PARTS 31 typedef struct{ - int partitions; /* 0 to 31 */ + int partitions; /* 0 to 31 */ int partitionclass[VIF_PARTS]; /* 0 to 15 */ - int class_dim[VIF_CLASS]; /* 1 to 8 */ - int class_subs[VIF_CLASS]; /* 0,1,2,3 (bits: 1<>=1; + ret++; + v>>=1; } return(ret); } @@ -130157,29 +119617,24 @@ static int ilog2(unsigned int v){ int ret=0; if(v)--v; while(v){ - ret++; - v>>=1; + ret++; + v>>=1; } return(ret); } typedef struct private_state { - /* local lookup storage */ - envelope_lookup *ve; /* envelope lookup */ - int window[2]; - vorbis_look_transform **transform[2]; /* block, type */ - drft_lookup fft_look[2]; + envelope_lookup *ve; /* envelope lookup */ + int window[2]; + vorbis_look_transform **transform[2]; /* block, type */ + drft_lookup fft_look[2]; - int modebits; - vorbis_look_floor **flr; + int modebits; + vorbis_look_floor **flr; vorbis_look_residue **residue; - vorbis_look_psy *psy; + vorbis_look_psy *psy; vorbis_look_psy_global *psy_g_look; - /* local storage, only used on the encoding side. This way the - application does not need to worry about freeing some packets' - memory and not others'; packet storage is always tracked. - Cleared next call to a _dsp_ function */ unsigned char *header; unsigned char *header1; unsigned char *header2; @@ -130189,12 +119644,6 @@ typedef struct private_state { ogg_int64_t sample_count; } private_state; -/* codec_setup_info contains all the setup information specific to the - specific compression/decompression mode in progress (eg, - psychoacoustic settings, channel setup, options, codebook - etc). -*********************************************************************/ - /********* Start of inlined file: highlevel.h *********/ typedef struct highlevel_byblocktype { double tone_mask_setting; @@ -130212,7 +119661,7 @@ typedef struct highlevel_encode_setup { double short_setting; double impulse_noisetune; - int managed; + int managed; long bitrate_min; long bitrate_av; double bitrate_av_damp; @@ -130239,41 +119688,33 @@ typedef struct highlevel_encode_setup { typedef struct codec_setup_info { - /* Vorbis supports only short and long blocks, but allows the - encoder to choose the sizes */ - long blocksizes[2]; - /* modes are the primary means of supporting on-the-fly different - blocksizes, different channel mappings (LR or M/A), - different residue backends, etc. Each mode consists of a - blocksize flag and a mapping (along with the mapping setup */ + int modes; + int maps; + int floors; + int residues; + int books; + int psys; /* encode only */ - int modes; - int maps; - int floors; - int residues; - int books; - int psys; /* encode only */ + vorbis_info_mode *mode_param[64]; + int map_type[64]; + vorbis_info_mapping *map_param[64]; + int floor_type[64]; + vorbis_info_floor *floor_param[64]; + int residue_type[64]; + vorbis_info_residue *residue_param[64]; + static_codebook *book_param[256]; + codebook *fullbooks; - vorbis_info_mode *mode_param[64]; - int map_type[64]; - vorbis_info_mapping *map_param[64]; - int floor_type[64]; - vorbis_info_floor *floor_param[64]; - int residue_type[64]; - vorbis_info_residue *residue_param[64]; - static_codebook *book_param[256]; - codebook *fullbooks; - - vorbis_info_psy *psy_param[4]; /* encode only */ + vorbis_info_psy *psy_param[4]; /* encode only */ vorbis_info_psy_global psy_g_param; bitrate_manager_info bi; highlevel_encode_setup hi; /* used only by vorbisenc.c. It's a - highly redundant structure, but - improves clarity of program flow. */ - int halfrate_flag; /* painless downsample for decode */ + highly redundant structure, but + improves clarity of program flow. */ + int halfrate_flag; /* painless downsample for decode */ } codec_setup_info; extern vorbis_look_psy_global *_vp_global_look(vorbis_info *vi); @@ -130293,7 +119734,7 @@ extern void _vp_global_free(vorbis_look_psy_global *look); #define VI_RESB 3 #define VI_MAPB 1 -extern vorbis_func_floor *_floor_P[]; +extern vorbis_func_floor *_floor_P[]; extern vorbis_func_residue *_residue_P[]; extern vorbis_func_mapping *_mapping_P[]; @@ -130306,25 +119747,23 @@ extern vorbis_func_mapping *_mapping_P[]; #include -/* 20log10(x) */ #define VORBIS_IEEE_FLOAT32 1 #ifdef VORBIS_IEEE_FLOAT32 static float unitnorm(float x){ union { - ogg_uint32_t i; - float f; + ogg_uint32_t i; + float f; } ix; ix.f = x; ix.i = (ix.i & 0x80000000U) | (0x3f800000U); return ix.f; } -/* Segher was off (too high) by ~ .3 decibel. Center the conversion correctly. */ static float todB(const float *x){ union { - ogg_uint32_t i; - float f; + ogg_uint32_t i; + float f; } ix; ix.f = *x; ix.i = ix.i&0x7fffffff; @@ -130347,24 +119786,12 @@ static float unitnorm(float x){ #define fromdB(x) (exp((x)*.11512925f)) -/* The bark scale equations are approximations, since the original - table was somewhat hand rolled. The below are chosen to have the - best possible fit to the rolled tables, thus their somewhat odd - appearance (these are more accurate and over a longer range than - the oft-quoted bark equations found in the texts I have). The - approximations are valid from 0 - 30kHz (nyquist) or so. - - all f in Hz, z in Bark */ - #define toBARK(n) (13.1f*atan(.00074f*(n))+2.24f*atan((n)*(n)*1.85e-8f)+1e-4f*(n)) #define fromBARK(z) (102.f*(z)-2.f*pow(z,2.f)+.4f*pow(z,3.f)+pow(1.46f,z)-1.f) -#define toMEL(n) (log(1.f+(n)*.001f)*1442.695f) +#define toMEL(n) (log(1.f+(n)*.001f)*1442.695f) #define fromMEL(m) (1000.f*exp((m)/1442.695f)-1000.f) -/* Frequency to octave. We arbitrarily declare 63.5 Hz to be octave - 0.0 */ - -#define toOC(n) (log(n)*1.442695f-5.965784f) +#define toOC(n) (log(n)*1.442695f-5.965784f) #define fromOC(o) (exp(((o)+5.965784f)*.693147f)) #endif @@ -130372,7 +119799,6 @@ static float unitnorm(float x){ int analysis_noisy=1; -/* decides between modes, dispatches to the appropriate mapping. */ int vorbis_analysis(vorbis_block *vb, ogg_packet *op){ int ret,i; vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; @@ -130382,72 +119808,62 @@ int vorbis_analysis(vorbis_block *vb, ogg_packet *op){ vb->floor_bits=0; vb->res_bits=0; - /* first things first. Make sure encode is ready */ for(i=0;ipacketblob[i]); - - /* we only have one mapping type (0), and we let the mapping code - itself figure out what soft mode to use. This allows easier - bitrate management */ + oggpack_reset(vbi->packetblob[i]); if((ret=_mapping_P[0]->forward(vb))) - return(ret); + return(ret); if(op){ - if(vorbis_bitrate_managed(vb)) - /* The app is using a bitmanaged mode... but not using the - bitrate management interface. */ - return(OV_EINVAL); + if(vorbis_bitrate_managed(vb)) + return(OV_EINVAL); - op->packet=oggpack_get_buffer(&vb->opb); - op->bytes=oggpack_bytes(&vb->opb); - op->b_o_s=0; - op->e_o_s=vb->eofflag; - op->granulepos=vb->granulepos; - op->packetno=vb->sequence; /* for sake of completeness */ + op->packet=oggpack_get_buffer(&vb->opb); + op->bytes=oggpack_bytes(&vb->opb); + op->b_o_s=0; + op->e_o_s=vb->eofflag; + op->granulepos=vb->granulepos; + op->packetno=vb->sequence; /* for sake of completeness */ } return(0); } -/* there was no great place to put this.... */ void _analysis_output_always(const char *base,int i,float *v,int n,int bark,int dB,ogg_int64_t off){ int j; FILE *of; char buffer[80]; - /* if(i==5870){*/ - sprintf(buffer,"%s_%d.m",base,i); - of=fopen(buffer,"w"); + sprintf(buffer,"%s_%d.m",base,i); + of=fopen(buffer,"w"); - if(!of)perror("failed to open data dump file"); + if(!of)perror("failed to open data dump file"); - for(j=0;j #include -/* compute bitrate tracking setup */ void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; bitrate_manager_info *bi=&ci->bi; @@ -130479,25 +119894,23 @@ void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){ memset(bm,0,sizeof(*bm)); if(bi && (bi->reservoir_bits>0)){ - long ratesamples=vi->rate; - int halfsamples=ci->blocksizes[0]>>1; + long ratesamples=vi->rate; + int halfsamples=ci->blocksizes[0]>>1; - bm->short_per_long=ci->blocksizes[1]/ci->blocksizes[0]; - bm->managed=1; + bm->short_per_long=ci->blocksizes[1]/ci->blocksizes[0]; + bm->managed=1; - bm->avg_bitsper= rint(1.*bi->avg_rate*halfsamples/ratesamples); - bm->min_bitsper= rint(1.*bi->min_rate*halfsamples/ratesamples); - bm->max_bitsper= rint(1.*bi->max_rate*halfsamples/ratesamples); + bm->avg_bitsper= rint(1.*bi->avg_rate*halfsamples/ratesamples); + bm->min_bitsper= rint(1.*bi->min_rate*halfsamples/ratesamples); + bm->max_bitsper= rint(1.*bi->max_rate*halfsamples/ratesamples); - bm->avgfloat=PACKETBLOBS/2; + bm->avgfloat=PACKETBLOBS/2; - /* not a necessary fix, but one that leads to a more balanced - typical initialization */ - { - long desired_fill=bi->reservoir_bits*bi->reservoir_bias; - bm->minmax_reservoir=desired_fill; - bm->avg_reservoir=desired_fill; - } + { + long desired_fill=bi->reservoir_bits*bi->reservoir_bias; + bm->minmax_reservoir=desired_fill; + bm->avg_reservoir=desired_fill; + } } } @@ -130508,22 +119921,21 @@ void vorbis_bitrate_clear(bitrate_manager_state *bm){ } int vorbis_bitrate_managed(vorbis_block *vb){ - vorbis_dsp_state *vd=vb->vd; - private_state *b=(private_state*)vd->backend_state; + vorbis_dsp_state *vd=vb->vd; + private_state *b=(private_state*)vd->backend_state; bitrate_manager_state *bm=&b->bms; if(bm && bm->managed)return(1); return(0); } -/* finish taking in the block we just processed */ int vorbis_bitrate_addblock(vorbis_block *vb){ vorbis_block_internal *vbi=(vorbis_block_internal*)vb->internal; - vorbis_dsp_state *vd=vb->vd; - private_state *b=(private_state*)vd->backend_state; + vorbis_dsp_state *vd=vb->vd; + private_state *b=(private_state*)vd->backend_state; bitrate_manager_state *bm=&b->bms; - vorbis_info *vi=vd->vi; - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; bitrate_manager_info *bi=&ci->bi; int choice=rint(bm->avgfloat); @@ -130533,163 +119945,135 @@ int vorbis_bitrate_addblock(vorbis_block *vb){ int samples=ci->blocksizes[vb->W]>>1; long desired_fill=bi->reservoir_bits*bi->reservoir_bias; if(!bm->managed){ - /* not a bitrate managed stream, but for API simplicity, we'll - buffer the packet to keep the code path clean */ - if(bm->vb)return(-1); /* one has been submitted without - being claimed */ - bm->vb=vb; - return(0); + if(bm->vb)return(-1); /* one has been submitted without + being claimed */ + bm->vb=vb; + return(0); } bm->vb=vb; - /* look ahead for avg floater */ if(bm->avg_bitsper>0){ - double slew=0.; - long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper); - double slewlimit= 15./bi->slew_damp; + double slew=0.; + long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper); + double slewlimit= 15./bi->slew_damp; - /* choosing a new floater: - if we're over target, we slew down - if we're under target, we slew up - - choose slew as follows: look through packetblobs of this frame - and set slew as the first in the appropriate direction that - gives us the slew we want. This may mean no slew if delta is - already favorable. - - Then limit slew to slew max */ - - if(bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){ - while(choice>0 && this_bits>avg_target_bits && - bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){ + if(bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){ + while(choice>0 && this_bits>avg_target_bits && + bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){ choice--; this_bits=oggpack_bytes(vbi->packetblob[choice])*8; - } - }else if(bm->avg_reservoir+(this_bits-avg_target_bits)avg_reservoir+(this_bits-avg_target_bits)avg_reservoir+(this_bits-avg_target_bits)avg_reservoir+(this_bits-avg_target_bits)packetblob[choice])*8; - } - } + } + } - slew=rint(choice-bm->avgfloat)/samples*vi->rate; - if(slew<-slewlimit)slew=-slewlimit; - if(slew>slewlimit)slew=slewlimit; - choice=rint(bm->avgfloat+= slew/vi->rate*samples); - this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + slew=rint(choice-bm->avgfloat)/samples*vi->rate; + if(slew<-slewlimit)slew=-slewlimit; + if(slew>slewlimit)slew=slewlimit; + choice=rint(bm->avgfloat+= slew/vi->rate*samples); + this_bits=oggpack_bytes(vbi->packetblob[choice])*8; } - /* enforce min(if used) on the current floater (if used) */ if(bm->min_bitsper>0){ - /* do we need to force the bitrate up? */ - if(this_bitsminmax_reservoir-(min_target_bits-this_bits)<0){ + if(this_bitsminmax_reservoir-(min_target_bits-this_bits)<0){ choice++; if(choice>=PACKETBLOBS)break; this_bits=oggpack_bytes(vbi->packetblob[choice])*8; - } - } + } + } } - /* enforce max (if used) on the current floater (if used) */ if(bm->max_bitsper>0){ - /* do we need to force the bitrate down? */ - if(this_bits>max_target_bits){ - while(bm->minmax_reservoir+(this_bits-max_target_bits)>bi->reservoir_bits){ + if(this_bits>max_target_bits){ + while(bm->minmax_reservoir+(this_bits-max_target_bits)>bi->reservoir_bits){ choice--; if(choice<0)break; this_bits=oggpack_bytes(vbi->packetblob[choice])*8; - } - } + } + } } - /* Choice of packetblobs now made based on floater, and min/max - requirements. Now boundary check extreme choices */ - if(choice<0){ - /* choosing a smaller packetblob is insufficient to trim bitrate. - frame will need to be truncated */ - long maxsize=(max_target_bits+(bi->reservoir_bits-bm->minmax_reservoir))/8; - bm->choice=choice=0; + long maxsize=(max_target_bits+(bi->reservoir_bits-bm->minmax_reservoir))/8; + bm->choice=choice=0; - if(oggpack_bytes(vbi->packetblob[choice])>maxsize){ + if(oggpack_bytes(vbi->packetblob[choice])>maxsize){ - oggpack_writetrunc(vbi->packetblob[choice],maxsize*8); - this_bits=oggpack_bytes(vbi->packetblob[choice])*8; - } + oggpack_writetrunc(vbi->packetblob[choice],maxsize*8); + this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + } }else{ - long minsize=(min_target_bits-bm->minmax_reservoir+7)/8; - if(choice>=PACKETBLOBS) - choice=PACKETBLOBS-1; + long minsize=(min_target_bits-bm->minmax_reservoir+7)/8; + if(choice>=PACKETBLOBS) + choice=PACKETBLOBS-1; - bm->choice=choice; + bm->choice=choice; - /* prop up bitrate according to demand. pad this frame out with zeroes */ - minsize-=oggpack_bytes(vbi->packetblob[choice]); - while(minsize-->0)oggpack_write(vbi->packetblob[choice],0,8); - this_bits=oggpack_bytes(vbi->packetblob[choice])*8; + minsize-=oggpack_bytes(vbi->packetblob[choice]); + while(minsize-->0)oggpack_write(vbi->packetblob[choice],0,8); + this_bits=oggpack_bytes(vbi->packetblob[choice])*8; } - /* now we have the final packet and the final packet size. Update statistics */ - /* min and max reservoir */ if(bm->min_bitsper>0 || bm->max_bitsper>0){ - if(max_target_bits>0 && this_bits>max_target_bits){ - bm->minmax_reservoir+=(this_bits-max_target_bits); - }else if(min_target_bits>0 && this_bitsminmax_reservoir+=(this_bits-min_target_bits); - }else{ - /* inbetween; we want to take reservoir toward but not past desired_fill */ - if(bm->minmax_reservoir>desired_fill){ + if(max_target_bits>0 && this_bits>max_target_bits){ + bm->minmax_reservoir+=(this_bits-max_target_bits); + }else if(min_target_bits>0 && this_bitsminmax_reservoir+=(this_bits-min_target_bits); + }else{ + if(bm->minmax_reservoir>desired_fill){ if(max_target_bits>0){ /* logical bulletproofing against initialization state */ bm->minmax_reservoir+=(this_bits-max_target_bits); if(bm->minmax_reservoirminmax_reservoir=desired_fill; }else{ bm->minmax_reservoir=desired_fill; } - }else{ + }else{ if(min_target_bits>0){ /* logical bulletproofing against initialization state */ bm->minmax_reservoir+=(this_bits-min_target_bits); if(bm->minmax_reservoir>desired_fill)bm->minmax_reservoir=desired_fill; }else{ bm->minmax_reservoir=desired_fill; } - } - } + } + } } - /* avg reservoir */ if(bm->avg_bitsper>0){ - long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper); - bm->avg_reservoir+=this_bits-avg_target_bits; + long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper); + bm->avg_reservoir+=this_bits-avg_target_bits; } return(0); } int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){ - private_state *b=(private_state*)vd->backend_state; + private_state *b=(private_state*)vd->backend_state; bitrate_manager_state *bm=&b->bms; - vorbis_block *vb=bm->vb; - int choice=PACKETBLOBS/2; + vorbis_block *vb=bm->vb; + int choice=PACKETBLOBS/2; if(!vb)return 0; if(op){ - vorbis_block_internal *vbi=(vorbis_block_internal*)vb->internal; + vorbis_block_internal *vbi=(vorbis_block_internal*)vb->internal; - if(vorbis_bitrate_managed(vb)) - choice=bm->choice; + if(vorbis_bitrate_managed(vb)) + choice=bm->choice; - op->packet=oggpack_get_buffer(vbi->packetblob[choice]); - op->bytes=oggpack_bytes(vbi->packetblob[choice]); - op->b_o_s=0; - op->e_o_s=vb->eofflag; - op->granulepos=vb->granulepos; - op->packetno=vb->sequence; /* for sake of completeness */ + op->packet=oggpack_get_buffer(vbi->packetblob[choice]); + op->bytes=oggpack_bytes(vbi->packetblob[choice]); + op->b_o_s=0; + op->e_o_s=vb->eofflag; + op->granulepos=vb->granulepos; + op->packetno=vb->sequence; /* for sake of completeness */ } bm->vb=0; @@ -130722,7 +120106,7 @@ int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){ extern float *_vorbis_window_get(int n); extern void _vorbis_apply_window(float *d,int *winno,long *blocksizes, - int lW,int W,int nW); + int lW,int W,int nW); #endif /********* End of inlined file: window.h *********/ @@ -130731,54 +120115,14 @@ extern void _vorbis_apply_window(float *d,int *winno,long *blocksizes, #ifndef _V_LPC_H_ #define _V_LPC_H_ -/* simple linear scale LPC code */ extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m); extern void vorbis_lpc_predict(float *coeff,float *prime,int m, - float *data,long n); + float *data,long n); #endif /********* End of inlined file: lpc.h *********/ -/* pcm accumulator examples (not exhaustive): - - <-------------- lW ----------------> - <--------------- W ----------------> -: .....|..... _______________ | -: .''' | '''_--- | |\ | -:.....''' |_____--- '''......| | \_______| -:.................|__________________|_______|__|______| - |<------ Sl ------>| > Sr < |endW - |beginSl |endSl | |endSr - |beginW |endlW |beginSr - - |< lW >| - <--------------- W ----------------> - | | .. ______________ | - | | ' `/ | ---_ | - |___.'___/`. | ---_____| - |_______|__|_______|_________________| - | >|Sl|< |<------ Sr ----->|endW - | | |endSl |beginSr |endSr - |beginW | |endlW - mult[0] |beginSl mult[n] - - <-------------- lW -----------------> - |<--W-->| -: .............. ___ | | -: .''' |`/ \ | | -:.....''' |/`....\|...| -:.........................|___|___|___| - |Sl |Sr |endW - | | |endSr - | |beginSr - | |endSl - |beginSl - |beginW -*/ - -/* block abstraction setup *********************************************/ - #ifndef WORD_ALIGN #define WORD_ALIGN 8 #endif @@ -130790,19 +120134,19 @@ int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ vb->localalloc=0; vb->localstore=NULL; if(v->analysisp){ - vorbis_block_internal *vbi=(vorbis_block_internal*) - (vb->internal=(vorbis_block_internal*)_ogg_calloc(1,sizeof(vorbis_block_internal))); - vbi->ampmax=-9999; + vorbis_block_internal *vbi=(vorbis_block_internal*) + (vb->internal=(vorbis_block_internal*)_ogg_calloc(1,sizeof(vorbis_block_internal))); + vbi->ampmax=-9999; - for(i=0;ipacketblob[i]=&vb->opb; - }else{ + }else{ vbi->packetblob[i]= (oggpack_buffer*) _ogg_calloc(1,sizeof(oggpack_buffer)); - } - oggpack_writeinit(vbi->packetblob[i]); - } + } + oggpack_writeinit(vbi->packetblob[i]); + } } return(0); @@ -130811,45 +120155,39 @@ int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ void *_vorbis_block_alloc(vorbis_block *vb,long bytes){ bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1); if(bytes+vb->localtop>vb->localalloc){ - /* can't just _ogg_realloc... there are outstanding pointers */ - if(vb->localstore){ - struct alloc_chain *link=(struct alloc_chain*)_ogg_malloc(sizeof(*link)); - vb->totaluse+=vb->localtop; - link->next=vb->reap; - link->ptr=vb->localstore; - vb->reap=link; - } - /* highly conservative */ - vb->localalloc=bytes; - vb->localstore=_ogg_malloc(vb->localalloc); - vb->localtop=0; + if(vb->localstore){ + struct alloc_chain *link=(struct alloc_chain*)_ogg_malloc(sizeof(*link)); + vb->totaluse+=vb->localtop; + link->next=vb->reap; + link->ptr=vb->localstore; + vb->reap=link; + } + vb->localalloc=bytes; + vb->localstore=_ogg_malloc(vb->localalloc); + vb->localtop=0; } { - void *ret=(void *)(((char *)vb->localstore)+vb->localtop); - vb->localtop+=bytes; - return ret; + void *ret=(void *)(((char *)vb->localstore)+vb->localtop); + vb->localtop+=bytes; + return ret; } } -/* reap the chain, pull the ripcord */ void _vorbis_block_ripcord(vorbis_block *vb){ - /* reap the chain */ struct alloc_chain *reap=vb->reap; while(reap){ - struct alloc_chain *next=reap->next; - _ogg_free(reap->ptr); - memset(reap,0,sizeof(*reap)); - _ogg_free(reap); - reap=next; + struct alloc_chain *next=reap->next; + _ogg_free(reap->ptr); + memset(reap,0,sizeof(*reap)); + _ogg_free(reap); + reap=next; } - /* consolidate storage */ if(vb->totaluse){ - vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); - vb->localalloc+=vb->totaluse; - vb->totaluse=0; + vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); + vb->localalloc+=vb->totaluse; + vb->totaluse=0; } - /* pull the ripcord */ vb->localtop=0; vb->reap=NULL; } @@ -130862,20 +120200,16 @@ int vorbis_block_clear(vorbis_block *vb){ if(vb->localstore)_ogg_free(vb->localstore); if(vbi){ - for(i=0;ipacketblob[i]); - if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]); - } - _ogg_free(vbi); + for(i=0;ipacketblob[i]); + if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]); + } + _ogg_free(vbi); } memset(vb,0,sizeof(*vb)); return(0); } -/* Analysis side code, but directly related to blocking. Thus it's - here and not in analysis.c (which is for analysis transforms only). - The init is here because some of it is shared */ - static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ int i; codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; @@ -130894,90 +120228,76 @@ static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ b->transform[0]=(vorbis_look_transform**)_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0])); b->transform[1]=(vorbis_look_transform**)_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1])); - /* MDCT is tranform 0 */ - b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup)); b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup)); mdct_init((mdct_lookup*)b->transform[0][0],ci->blocksizes[0]>>hs); mdct_init((mdct_lookup*)b->transform[1][0],ci->blocksizes[1]>>hs); - /* Vorbis I uses only window type 0 */ b->window[0]=ilog2(ci->blocksizes[0])-6; b->window[1]=ilog2(ci->blocksizes[1])-6; if(encp){ /* encode/decode differ here */ - /* analysis always needs an fft */ - drft_init(&b->fft_look[0],ci->blocksizes[0]); - drft_init(&b->fft_look[1],ci->blocksizes[1]); + drft_init(&b->fft_look[0],ci->blocksizes[0]); + drft_init(&b->fft_look[1],ci->blocksizes[1]); - /* finish the codebooks */ - if(!ci->fullbooks){ - ci->fullbooks=(codebook*) _ogg_calloc(ci->books,sizeof(*ci->fullbooks)); - for(i=0;ibooks;i++) + if(!ci->fullbooks){ + ci->fullbooks=(codebook*) _ogg_calloc(ci->books,sizeof(*ci->fullbooks)); + for(i=0;ibooks;i++) vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]); - } + } - b->psy=(vorbis_look_psy*)_ogg_calloc(ci->psys,sizeof(*b->psy)); - for(i=0;ipsys;i++){ - _vp_psy_init(b->psy+i, + b->psy=(vorbis_look_psy*)_ogg_calloc(ci->psys,sizeof(*b->psy)); + for(i=0;ipsys;i++){ + _vp_psy_init(b->psy+i, ci->psy_param[i], &ci->psy_g_param, ci->blocksizes[ci->psy_param[i]->blockflag]/2, vi->rate); - } + } - v->analysisp=1; + v->analysisp=1; }else{ - /* finish the codebooks */ - if(!ci->fullbooks){ - ci->fullbooks=(codebook*) _ogg_calloc(ci->books,sizeof(*ci->fullbooks)); - for(i=0;ibooks;i++){ + if(!ci->fullbooks){ + ci->fullbooks=(codebook*) _ogg_calloc(ci->books,sizeof(*ci->fullbooks)); + for(i=0;ibooks;i++){ vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]); - /* decode codebooks are now standalone after init */ vorbis_staticbook_destroy(ci->book_param[i]); ci->book_param[i]=NULL; - } - } + } + } } - /* initialize the storage vectors. blocksize[1] is small for encode, - but the correct size for decode */ v->pcm_storage=ci->blocksizes[1]; v->pcm=(float**)_ogg_malloc(vi->channels*sizeof(*v->pcm)); v->pcmret=(float**)_ogg_malloc(vi->channels*sizeof(*v->pcmret)); { - int i; - for(i=0;ichannels;i++) - v->pcm[i]=(float*)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); + int i; + for(i=0;ichannels;i++) + v->pcm[i]=(float*)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); } - /* all 1 (large block) or 0 (small block) */ - /* explicitly set for the sake of clarity */ v->lW=0; /* previous window size */ v->W=0; /* current window size */ - /* all vector indexes */ v->centerW=ci->blocksizes[1]/2; v->pcm_current=v->centerW; - /* initialize all the backend lookups */ b->flr=(vorbis_look_floor**)_ogg_calloc(ci->floors,sizeof(*b->flr)); b->residue=(vorbis_look_residue**)_ogg_calloc(ci->residues,sizeof(*b->residue)); for(i=0;ifloors;i++) - b->flr[i]=_floor_P[ci->floor_type[i]]-> - look(v,ci->floor_param[i]); + b->flr[i]=_floor_P[ci->floor_type[i]]-> + look(v,ci->floor_param[i]); for(i=0;iresidues;i++) - b->residue[i]=_residue_P[ci->residue_type[i]]-> - look(v,ci->residue_param[i]); + b->residue[i]=_residue_P[ci->residue_type[i]]-> + look(v,ci->residue_param[i]); return 0; } -/* arbitrary settings and spec-mandated numbers get filled in here */ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ private_state *b=NULL; @@ -130985,14 +120305,11 @@ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ b=(private_state*)v->backend_state; b->psy_g_look=_vp_global_look(vi); - /* Initialize the envelope state storage */ b->ve=(envelope_lookup*)_ogg_calloc(1,sizeof(*b->ve)); _ve_envelope_init(b->ve,vi); vorbis_bitrate_init(vi,&b->bms); - /* compressed audio packets start after the headers - with sequence number 3 */ v->sequence=3; return(0); @@ -131001,70 +120318,69 @@ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ void vorbis_dsp_clear(vorbis_dsp_state *v){ int i; if(v){ - vorbis_info *vi=v->vi; - codec_setup_info *ci=(codec_setup_info*)(vi?vi->codec_setup:NULL); - private_state *b=(private_state*)v->backend_state; + vorbis_info *vi=v->vi; + codec_setup_info *ci=(codec_setup_info*)(vi?vi->codec_setup:NULL); + private_state *b=(private_state*)v->backend_state; - if(b){ + if(b){ - if(b->ve){ + if(b->ve){ _ve_envelope_clear(b->ve); _ogg_free(b->ve); - } + } - if(b->transform[0]){ + if(b->transform[0]){ mdct_clear((mdct_lookup*) b->transform[0][0]); _ogg_free(b->transform[0][0]); _ogg_free(b->transform[0]); - } - if(b->transform[1]){ + } + if(b->transform[1]){ mdct_clear((mdct_lookup*) b->transform[1][0]); _ogg_free(b->transform[1][0]); _ogg_free(b->transform[1]); - } + } - if(b->flr){ + if(b->flr){ for(i=0;ifloors;i++) _floor_P[ci->floor_type[i]]-> - free_look(b->flr[i]); + free_look(b->flr[i]); _ogg_free(b->flr); - } - if(b->residue){ + } + if(b->residue){ for(i=0;iresidues;i++) _residue_P[ci->residue_type[i]]-> - free_look(b->residue[i]); + free_look(b->residue[i]); _ogg_free(b->residue); - } - if(b->psy){ + } + if(b->psy){ for(i=0;ipsys;i++) _vp_psy_clear(b->psy+i); _ogg_free(b->psy); - } + } - if(b->psy_g_look)_vp_global_free(b->psy_g_look); - vorbis_bitrate_clear(&b->bms); + if(b->psy_g_look)_vp_global_free(b->psy_g_look); + vorbis_bitrate_clear(&b->bms); - drft_clear(&b->fft_look[0]); - drft_clear(&b->fft_look[1]); + drft_clear(&b->fft_look[0]); + drft_clear(&b->fft_look[1]); - } + } - if(v->pcm){ - for(i=0;ichannels;i++) + if(v->pcm){ + for(i=0;ichannels;i++) if(v->pcm[i])_ogg_free(v->pcm[i]); - _ogg_free(v->pcm); - if(v->pcmret)_ogg_free(v->pcmret); - } + _ogg_free(v->pcm); + if(v->pcmret)_ogg_free(v->pcmret); + } - if(b){ - /* free header, header1, header2 */ - if(b->header)_ogg_free(b->header); - if(b->header1)_ogg_free(b->header1); - if(b->header2)_ogg_free(b->header2); - _ogg_free(b); - } + if(b){ + if(b->header)_ogg_free(b->header); + if(b->header1)_ogg_free(b->header1); + if(b->header2)_ogg_free(b->header2); + _ogg_free(b); + } - memset(v,0,sizeof(*v)); + memset(v,0,sizeof(*v)); } } @@ -131073,24 +120389,20 @@ float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){ vorbis_info *vi=v->vi; private_state *b=(private_state*)v->backend_state; - /* free header, header1, header2 */ if(b->header)_ogg_free(b->header);b->header=NULL; if(b->header1)_ogg_free(b->header1);b->header1=NULL; if(b->header2)_ogg_free(b->header2);b->header2=NULL; - /* Do we have enough storage space for the requested buffer? If not, - expand the PCM (and envelope) storage */ - if(v->pcm_current+vals>=v->pcm_storage){ - v->pcm_storage=v->pcm_current+vals*2; + v->pcm_storage=v->pcm_current+vals*2; - for(i=0;ichannels;i++){ - v->pcm[i]=(float*)_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i])); - } + for(i=0;ichannels;i++){ + v->pcm[i]=(float*)_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i])); + } } for(i=0;ichannels;i++) - v->pcmret[i]=v->pcm[i]+v->pcm_current; + v->pcmret[i]=v->pcm[i]+v->pcm_current; return(v->pcmret); } @@ -131104,93 +120416,70 @@ static void _preextrapolate_helper(vorbis_dsp_state *v){ v->preextrapolate=1; if(v->pcm_current-v->centerW>order*2){ /* safety */ - for(i=0;ivi->channels;i++){ - /* need to run the extrapolation in reverse! */ - for(j=0;jpcm_current;j++) + for(i=0;ivi->channels;i++){ + for(j=0;jpcm_current;j++) work[j]=v->pcm[i][v->pcm_current-j-1]; - /* prime as above */ - vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order); + vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order); - /* run the predictor filter */ - vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order, + vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order, order, work+v->pcm_current-v->centerW, v->centerW); - for(j=0;jpcm_current;j++) + for(j=0;jpcm_current;j++) v->pcm[i][v->pcm_current-j-1]=work[j]; - } + } } } -/* call with val<=0 to set eof */ - int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){ vorbis_info *vi=v->vi; codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; if(vals<=0){ - int order=32; - int i; - float *lpc=(float*) alloca(order*sizeof(*lpc)); + int order=32; + int i; + float *lpc=(float*) alloca(order*sizeof(*lpc)); - /* if it wasn't done earlier (very short sample) */ - if(!v->preextrapolate) - _preextrapolate_helper(v); + if(!v->preextrapolate) + _preextrapolate_helper(v); - /* We're encoding the end of the stream. Just make sure we have - [at least] a few full blocks of zeroes at the end. */ - /* actually, we don't want zeroes; that could drop a large - amplitude off a cliff, creating spread spectrum noise that will - suck to encode. Extrapolate for the sake of cleanliness. */ + vorbis_analysis_buffer(v,ci->blocksizes[1]*3); + v->eofflag=v->pcm_current; + v->pcm_current+=ci->blocksizes[1]*3; - vorbis_analysis_buffer(v,ci->blocksizes[1]*3); - v->eofflag=v->pcm_current; - v->pcm_current+=ci->blocksizes[1]*3; - - for(i=0;ichannels;i++){ - if(v->eofflag>order*2){ - /* extrapolate with LPC to fill in */ + for(i=0;ichannels;i++){ + if(v->eofflag>order*2){ long n; - /* make a predictor filter */ n=v->eofflag; if(n>ci->blocksizes[1])n=ci->blocksizes[1]; vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order); - /* run the predictor filter */ vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order, v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag); - }else{ - /* not enough data to extrapolate (unlikely to happen due to - guarding the overlap, but bulletproof in case that - assumtion goes away). zeroes will do. */ + }else{ memset(v->pcm[i]+v->eofflag,0, - (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i])); + (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i])); - } - } + } + } }else{ - if(v->pcm_current+vals>v->pcm_storage) - return(OV_EINVAL); + if(v->pcm_current+vals>v->pcm_storage) + return(OV_EINVAL); - v->pcm_current+=vals; + v->pcm_current+=vals; - /* we may want to reverse extrapolate the beginning of a stream - too... in case we're beginning on a cliff! */ - /* clumsy, but simple. It only runs once, so simple is good. */ - if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1]) - _preextrapolate_helper(v); + if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1]) + _preextrapolate_helper(v); } return(0); } -/* do the deltas, envelope shaping, pre-echo and determine the size of - the next block on which to continue analysis */ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ int i; vorbis_info *vi=v->vi; @@ -131200,77 +120489,60 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext; vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; - /* check to see if we're started... */ if(!v->preextrapolate)return(0); - /* check to see if we're done... */ if(v->eofflag==-1)return(0); - /* By our invariant, we have lW, W and centerW set. Search for - the next boundary so we can determine nW (the next window size) - which lets us compute the shape of the current block's window */ - - /* we do an envelope search even on a single blocksize; we may still - be throwing more bits at impulses, and envelope search handles - marking impulses too. */ { - long bp=_ve_envelope_search(v); - if(bp==-1){ + long bp=_ve_envelope_search(v); + if(bp==-1){ - if(v->eofflag==0)return(0); /* not enough data currently to search for a - full long block */ - v->nW=0; - }else{ + if(v->eofflag==0)return(0); /* not enough data currently to search for a + full long block */ + v->nW=0; + }else{ - if(ci->blocksizes[0]==ci->blocksizes[1]) + if(ci->blocksizes[0]==ci->blocksizes[1]) v->nW=0; - else + else v->nW=bp; - } + } } centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4; { - /* center of next block + next block maximum right side. */ - long blockbound=centerNext+ci->blocksizes[v->nW]/2; - if(v->pcm_currentblocksizes[v->nW]/2; + if(v->pcm_currentlW=v->lW; vb->W=v->W; vb->nW=v->nW; if(v->W){ - if(!v->lW || !v->nW){ - vbi->blocktype=BLOCKTYPE_TRANSITION; - /*fprintf(stderr,"-");*/ - }else{ - vbi->blocktype=BLOCKTYPE_LONG; - /*fprintf(stderr,"_");*/ - } + if(!v->lW || !v->nW){ + vbi->blocktype=BLOCKTYPE_TRANSITION; + }else{ + vbi->blocktype=BLOCKTYPE_LONG; + } }else{ - if(_ve_envelope_mark(v)){ - vbi->blocktype=BLOCKTYPE_IMPULSE; - /*fprintf(stderr,"|");*/ + if(_ve_envelope_mark(v)){ + vbi->blocktype=BLOCKTYPE_IMPULSE; - }else{ - vbi->blocktype=BLOCKTYPE_PADDING; - /*fprintf(stderr,".");*/ + }else{ + vbi->blocktype=BLOCKTYPE_PADDING; - } + } } vb->vd=v; @@ -131278,10 +120550,6 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ vb->granulepos=v->granulepos; vb->pcmend=ci->blocksizes[v->W]; - /* copy the vectors; this uses the local storage in vb */ - - /* this tracks 'strongest peak' for later psychoacoustics */ - /* moved to the global psy state; clean this mess up */ if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax; g->ampmax=_vp_ampmax_decay(g->ampmax,v); vbi->ampmax=g->ampmax; @@ -131289,64 +120557,52 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ vb->pcm=(float**)_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); vbi->pcmdelay=(float**)_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels); for(i=0;ichannels;i++){ - vbi->pcmdelay[i]= - (float*) _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); - memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); - vb->pcm[i]=vbi->pcmdelay[i]+beginW; - - /* before we added the delay - vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); - memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i])); - */ + vbi->pcmdelay[i]= + (float*) _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); + memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); + vb->pcm[i]=vbi->pcmdelay[i]+beginW; } - /* handle eof detection: eof==0 means that we've not yet received EOF - eof>0 marks the last 'real' sample in pcm[] - eof<0 'no more to do'; doesn't get here */ - if(v->eofflag){ - if(v->centerW>=v->eofflag){ - v->eofflag=-1; - vb->eofflag=1; - return(1); - } + if(v->centerW>=v->eofflag){ + v->eofflag=-1; + vb->eofflag=1; + return(1); + } } - /* advance storage vectors and clean up */ { - int new_centerNext=ci->blocksizes[1]/2; - int movementW=centerNext-new_centerNext; + int new_centerNext=ci->blocksizes[1]/2; + int movementW=centerNext-new_centerNext; - if(movementW>0){ + if(movementW>0){ - _ve_envelope_shift(b->ve,movementW); - v->pcm_current-=movementW; + _ve_envelope_shift(b->ve,movementW); + v->pcm_current-=movementW; - for(i=0;ichannels;i++) + for(i=0;ichannels;i++) memmove(v->pcm[i],v->pcm[i]+movementW, v->pcm_current*sizeof(*v->pcm[i])); - v->lW=v->W; - v->W=v->nW; - v->centerW=new_centerNext; + v->lW=v->W; + v->W=v->nW; + v->centerW=new_centerNext; - if(v->eofflag){ + if(v->eofflag){ v->eofflag-=movementW; if(v->eofflag<=0)v->eofflag=-1; - /* do not add padding to end of stream! */ if(v->centerW>=v->eofflag){ v->granulepos+=movementW-(v->centerW-v->eofflag); }else{ v->granulepos+=movementW; } - }else{ + }else{ v->granulepos+=movementW; - } - } + } + } } - /* done */ return(1); } @@ -131380,10 +120636,6 @@ int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ return 0; } -/* Unlike in analysis, the window is only partially applied for each - block. The time domain envelope is not yet handled at the point of - calling (as it relies on the previous block). */ - int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ vorbis_info *vi=v->vi; codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; @@ -131399,189 +120651,151 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ v->nW=-1; if((v->sequence==-1)|| - (v->sequence+1 != vb->sequence)){ - v->granulepos=-1; /* out of sequence; lose count */ - b->sample_count=-1; + (v->sequence+1 != vb->sequence)){ + v->granulepos=-1; /* out of sequence; lose count */ + b->sample_count=-1; } v->sequence=vb->sequence; if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly was called on block */ - int n=ci->blocksizes[v->W]>>(hs+1); - int n0=ci->blocksizes[0]>>(hs+1); - int n1=ci->blocksizes[1]>>(hs+1); + int n=ci->blocksizes[v->W]>>(hs+1); + int n0=ci->blocksizes[0]>>(hs+1); + int n1=ci->blocksizes[1]>>(hs+1); - int thisCenter; - int prevCenter; + int thisCenter; + int prevCenter; - v->glue_bits+=vb->glue_bits; - v->time_bits+=vb->time_bits; - v->floor_bits+=vb->floor_bits; - v->res_bits+=vb->res_bits; + v->glue_bits+=vb->glue_bits; + v->time_bits+=vb->time_bits; + v->floor_bits+=vb->floor_bits; + v->res_bits+=vb->res_bits; - if(v->centerW){ - thisCenter=n1; - prevCenter=0; - }else{ - thisCenter=0; - prevCenter=n1; - } + if(v->centerW){ + thisCenter=n1; + prevCenter=0; + }else{ + thisCenter=0; + prevCenter=n1; + } - /* v->pcm is now used like a two-stage double buffer. We don't want - to have to constantly shift *or* adjust memory usage. Don't - accept a new block until the old is shifted out */ - - for(j=0;jchannels;j++){ - /* the overlap/add section */ - if(v->lW){ + for(j=0;jchannels;j++){ + if(v->lW){ if(v->W){ - /* large/large */ float *w=_vorbis_window_get(b->window[1]-hs); float *pcm=v->pcm[j]+prevCenter; float *p=vb->pcm[j]; for(i=0;iwindow[0]-hs); float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2; float *p=vb->pcm[j]; for(i=0;iW){ - /* small/large */ float *w=_vorbis_window_get(b->window[0]-hs); float *pcm=v->pcm[j]+prevCenter; float *p=vb->pcm[j]+n1/2-n0/2; for(i=0;iwindow[0]-hs); float *pcm=v->pcm[j]+prevCenter; float *p=vb->pcm[j]; for(i=0;ipcm[j]+thisCenter; float *p=vb->pcm[j]+n; for(i=0;icenterW) - v->centerW=0; - else - v->centerW=n1; + if(v->centerW) + v->centerW=0; + else + v->centerW=n1; - /* deal with initial packet state; we do this using the explicit - pcm_returned==-1 flag otherwise we're sensitive to first block - being short or long */ - - if(v->pcm_returned==-1){ - v->pcm_returned=thisCenter; - v->pcm_current=thisCenter; - }else{ - v->pcm_returned=prevCenter; - v->pcm_current=prevCenter+ + if(v->pcm_returned==-1){ + v->pcm_returned=thisCenter; + v->pcm_current=thisCenter; + }else{ + v->pcm_returned=prevCenter; + v->pcm_current=prevCenter+ ((ci->blocksizes[v->lW]/4+ ci->blocksizes[v->W]/4)>>hs); - } + } } - /* track the frame number... This is for convenience, but also - making sure our last packet doesn't end with added padding. If - the last packet is partial, the number of samples we'll have to - return will be past the vb->granulepos. - - This is not foolproof! It will be confused if we begin - decoding at the last page after a seek or hole. In that case, - we don't have a starting point to judge where the last frame - is. For this reason, vorbisfile will always try to make sure - it reads the last two marked pages in proper sequence */ - if(b->sample_count==-1){ - b->sample_count=0; + b->sample_count=0; }else{ - b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; + b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; } if(v->granulepos==-1){ - if(vb->granulepos!=-1){ /* only set if we have a position to set to */ + if(vb->granulepos!=-1){ /* only set if we have a position to set to */ - v->granulepos=vb->granulepos; + v->granulepos=vb->granulepos; - /* is this a short page? */ - if(b->sample_count>v->granulepos){ - /* corner case; if this is both the first and last audio page, - then spec says the end is cut, not beginning */ + if(b->sample_count>v->granulepos){ if(vb->eofflag){ - /* trim the end */ - /* no preceeding granulepos; assume we started at zero (we'd - have to in a short single-page stream) */ - /* granulepos could be -1 due to a seek, but that would result - in a long count, not short count */ v->pcm_current-=(b->sample_count-v->granulepos)>>hs; }else{ - /* trim the beginning */ v->pcm_returned+=(b->sample_count-v->granulepos)>>hs; if(v->pcm_returned>v->pcm_current) - v->pcm_returned=v->pcm_current; + v->pcm_returned=v->pcm_current; } - } + } - } + } }else{ - v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; - if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ + v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; + if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ - if(v->granulepos>vb->granulepos){ + if(v->granulepos>vb->granulepos){ long extra=v->granulepos-vb->granulepos; if(extra) if(vb->eofflag){ - /* partial last frame. Strip the extra samples off */ - v->pcm_current-=extra>>hs; + v->pcm_current-=extra>>hs; + } /* else {Shouldn't happen *unless* the bitstream is out of + spec. Either way, believe the bitstream } */ } /* else {Shouldn't happen *unless* the bitstream is out of - spec. Either way, believe the bitstream } */ - } /* else {Shouldn't happen *unless* the bitstream is out of spec. Either way, believe the bitstream } */ - v->granulepos=vb->granulepos; - } + v->granulepos=vb->granulepos; + } } - /* Update, cleanup */ - if(vb->eofflag)v->eofflag=1; return(0); } -/* pcm==NULL indicates we just want the pending samples, no more */ int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){ vorbis_info *vi=v->vi; if(v->pcm_returned>-1 && v->pcm_returnedpcm_current){ - if(pcm){ - int i; - for(i=0;ichannels;i++) + if(pcm){ + int i; + for(i=0;ichannels;i++) v->pcmret[i]=v->pcm[i]+v->pcm_returned; - *pcm=v->pcmret; - } - return(v->pcm_current-v->pcm_returned); + *pcm=v->pcmret; + } + return(v->pcm_current-v->pcm_returned); } return(0); } @@ -131592,11 +120806,6 @@ int vorbis_synthesis_read(vorbis_dsp_state *v,int n){ return(0); } -/* intended for use with a specific vorbisfile feature; we want access - to the [usually synthetic/postextrapolated] buffer and lapping at - the end of a decode cycle, specifically, a half-short-block worth. - This funtion works like pcmout above, except it will also expose - this implicit buffer data not normally decoded. */ int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){ vorbis_info *vi=v->vi; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; @@ -131609,63 +120818,48 @@ int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){ if(v->pcm_returned<0)return 0; - /* our returned data ends at pcm_returned; because the synthesis pcm - buffer is a two-fragment ring, that means our data block may be - fragmented by buffering, wrapping or a short block not filling - out a buffer. To simplify things, we unfragment if it's at all - possibly needed. Otherwise, we'd need to call lapout more than - once as well as hold additional dsp state. Opt for - simplicity. */ - - /* centerW was advanced by blockin; it would be the center of the - *next* block */ if(v->centerW==n1){ - /* the data buffer wraps; swap the halves */ - /* slow, sure, small */ - for(j=0;jchannels;j++){ - float *p=v->pcm[j]; - for(i=0;ichannels;j++){ + float *p=v->pcm[j]; + for(i=0;ipcm_current-=n1; - v->pcm_returned-=n1; - v->centerW=0; + v->pcm_current-=n1; + v->pcm_returned-=n1; + v->centerW=0; } - /* solidify buffer into contiguous space */ if((v->lW^v->W)==1){ - /* long/short or short/long */ - for(j=0;jchannels;j++){ - float *s=v->pcm[j]; - float *d=v->pcm[j]+(n1-n0)/2; - for(i=(n1+n0)/2-1;i>=0;--i) + for(j=0;jchannels;j++){ + float *s=v->pcm[j]; + float *d=v->pcm[j]+(n1-n0)/2; + for(i=(n1+n0)/2-1;i>=0;--i) d[i]=s[i]; - } - v->pcm_returned+=(n1-n0)/2; - v->pcm_current+=(n1-n0)/2; + } + v->pcm_returned+=(n1-n0)/2; + v->pcm_current+=(n1-n0)/2; }else{ - if(v->lW==0){ - /* short/short */ - for(j=0;jchannels;j++){ + if(v->lW==0){ + for(j=0;jchannels;j++){ float *s=v->pcm[j]; float *d=v->pcm[j]+n1-n0; for(i=n0-1;i>=0;--i) d[i]=s[i]; - } - v->pcm_returned+=n1-n0; - v->pcm_current+=n1-n0; - } + } + v->pcm_returned+=n1-n0; + v->pcm_current+=n1-n0; + } } if(pcm){ - int i; - for(i=0;ichannels;i++) - v->pcmret[i]=v->pcm[i]+v->pcm_returned; - *pcm=v->pcmret; + int i; + for(i=0;ichannels;i++) + v->pcmret[i]=v->pcm[i]+v->pcm_returned; + *pcm=v->pcmret; } return(n1+n-v->pcm_returned); @@ -131702,226 +120896,183 @@ float *vorbis_window(vorbis_dsp_state *v,int W){ #include #include -/* packs the given codebook into the bitstream **************************/ - int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){ long i,j; int ordered=0; - /* first the basic parameters */ oggpack_write(opb,0x564342,24); oggpack_write(opb,c->dim,16); oggpack_write(opb,c->entries,24); - /* pack the codewords. There are two packings; length ordered and - length random. Decide between the two now. */ - for(i=1;ientries;i++) - if(c->lengthlist[i-1]==0 || c->lengthlist[i]lengthlist[i-1])break; + if(c->lengthlist[i-1]==0 || c->lengthlist[i]lengthlist[i-1])break; if(i==c->entries)ordered=1; if(ordered){ - /* length ordered. We only need to say how many codewords of - each length. The actual codewords are generated - deterministically */ - long count=0; - oggpack_write(opb,1,1); /* ordered */ - oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */ + long count=0; + oggpack_write(opb,1,1); /* ordered */ + oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */ - for(i=1;ientries;i++){ - long thisx=c->lengthlist[i]; - long last=c->lengthlist[i-1]; - if(thisx>last){ + for(i=1;ientries;i++){ + long thisx=c->lengthlist[i]; + long last=c->lengthlist[i-1]; + if(thisx>last){ for(j=last;jentries-count)); count=i; } - } - } - oggpack_write(opb,i-count,_ilog(c->entries-count)); + } + } + oggpack_write(opb,i-count,_ilog(c->entries-count)); }else{ - /* length random. Again, we don't code the codeword itself, just - the length. This time, though, we have to encode each length */ - oggpack_write(opb,0,1); /* unordered */ + oggpack_write(opb,0,1); /* unordered */ - /* algortihmic mapping has use for 'unused entries', which we tag - here. The algorithmic mapping happens as usual, but the unused - entry has no codeword. */ - for(i=0;ientries;i++) - if(c->lengthlist[i]==0)break; + for(i=0;ientries;i++) + if(c->lengthlist[i]==0)break; - if(i==c->entries){ - oggpack_write(opb,0,1); /* no unused entries */ - for(i=0;ientries;i++) + if(i==c->entries){ + oggpack_write(opb,0,1); /* no unused entries */ + for(i=0;ientries;i++) oggpack_write(opb,c->lengthlist[i]-1,5); - }else{ - oggpack_write(opb,1,1); /* we have unused entries; thus we tag */ - for(i=0;ientries;i++){ + }else{ + oggpack_write(opb,1,1); /* we have unused entries; thus we tag */ + for(i=0;ientries;i++){ if(c->lengthlist[i]==0){ oggpack_write(opb,0,1); }else{ oggpack_write(opb,1,1); oggpack_write(opb,c->lengthlist[i]-1,5); } - } - } + } + } } - /* is the entry number the desired return value, or do we have a - mapping? If we have a mapping, what type? */ oggpack_write(opb,c->maptype,4); switch(c->maptype){ case 0: - /* no mapping */ - break; + break; case 1:case 2: - /* implicitly populated value mapping */ - /* explicitly populated value mapping */ - if(!c->quantlist){ - /* no quantlist? error */ - return(-1); - } + if(!c->quantlist){ + return(-1); + } - /* values that define the dequantization */ - oggpack_write(opb,c->q_min,32); - oggpack_write(opb,c->q_delta,32); - oggpack_write(opb,c->q_quant-1,4); - oggpack_write(opb,c->q_sequencep,1); + oggpack_write(opb,c->q_min,32); + oggpack_write(opb,c->q_delta,32); + oggpack_write(opb,c->q_quant-1,4); + oggpack_write(opb,c->q_sequencep,1); - { - int quantvals; - switch(c->maptype){ - case 1: - /* a single column of (c->entries/c->dim) quantized values for - building a full value list algorithmically (square lattice) */ + { + int quantvals; + switch(c->maptype){ + case 1: quantvals=_book_maptype1_quantvals(c); break; - case 2: - /* every value (c->entries*c->dim total) specified explicitly */ + case 2: quantvals=c->entries*c->dim; break; - default: /* NOT_REACHABLE */ + default: /* NOT_REACHABLE */ quantvals=-1; - } + } - /* quantized values */ - for(i=0;iquantlist[i]),c->q_quant); - } - break; + } + break; default: - /* error case; we don't have any other map types now */ - return(-1); + return(-1); } return(0); } -/* unpacks a codebook from the packet buffer into the codebook struct, - readies the codebook auxiliary structures for decode *************/ int vorbis_staticbook_unpack(oggpack_buffer *opb,static_codebook *s){ long i,j; memset(s,0,sizeof(*s)); s->allocedp=1; - /* make sure alignment is correct */ if(oggpack_read(opb,24)!=0x564342)goto _eofout; - /* first the basic parameters */ s->dim=oggpack_read(opb,16); s->entries=oggpack_read(opb,24); if(s->entries==-1)goto _eofout; - /* codeword ordering.... length ordered or unordered? */ switch((int)oggpack_read(opb,1)){ case 0: - /* unordered */ - s->lengthlist=(long*)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); + s->lengthlist=(long*)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); - /* allocated but unused entries? */ - if(oggpack_read(opb,1)){ - /* yes, unused entries */ + if(oggpack_read(opb,1)){ - for(i=0;ientries;i++){ + for(i=0;ientries;i++){ if(oggpack_read(opb,1)){ long num=oggpack_read(opb,5); if(num==-1)goto _eofout; s->lengthlist[i]=num+1; }else s->lengthlist[i]=0; - } - }else{ - /* all entries used; no tagging */ - for(i=0;ientries;i++){ + } + }else{ + for(i=0;ientries;i++){ long num=oggpack_read(opb,5); if(num==-1)goto _eofout; s->lengthlist[i]=num+1; - } - } + } + } - break; + break; case 1: - /* ordered */ - { - long length=oggpack_read(opb,5)+1; - s->lengthlist=(long*)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); + { + long length=oggpack_read(opb,5)+1; + s->lengthlist=(long*)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); - for(i=0;ientries;){ + for(i=0;ientries;){ long num=oggpack_read(opb,_ilog(s->entries-i)); if(num==-1)goto _eofout; for(j=0;jentries;j++,i++) s->lengthlist[i]=length; length++; - } - } - break; + } + } + break; default: - /* EOF */ - return(-1); + return(-1); } - /* Do we have a mapping to unpack? */ switch((s->maptype=oggpack_read(opb,4))){ case 0: - /* no mapping */ - break; + break; case 1: case 2: - /* implicitly populated value mapping */ - /* explicitly populated value mapping */ - s->q_min=oggpack_read(opb,32); - s->q_delta=oggpack_read(opb,32); - s->q_quant=oggpack_read(opb,4)+1; - s->q_sequencep=oggpack_read(opb,1); + s->q_min=oggpack_read(opb,32); + s->q_delta=oggpack_read(opb,32); + s->q_quant=oggpack_read(opb,4)+1; + s->q_sequencep=oggpack_read(opb,1); - { - int quantvals=0; - switch(s->maptype){ - case 1: + { + int quantvals=0; + switch(s->maptype){ + case 1: quantvals=_book_maptype1_quantvals(s); break; - case 2: + case 2: quantvals=s->entries*s->dim; break; - } + } - /* quantized values */ - s->quantlist=(long*)_ogg_malloc(sizeof(*s->quantlist)*quantvals); - for(i=0;iquantlist=(long*)_ogg_malloc(sizeof(*s->quantlist)*quantvals); + for(i=0;iquantlist[i]=oggpack_read(opb,s->q_quant); - if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout; - } - break; + if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout; + } + break; default: - goto _errout; + goto _errout; } - /* all set */ return(0); _errout: @@ -131930,122 +121081,79 @@ int vorbis_staticbook_unpack(oggpack_buffer *opb,static_codebook *s){ return(-1); } -/* returns the number of bits ************************************************/ int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){ oggpack_write(b,book->codelist[a],book->c->lengthlist[a]); return(book->c->lengthlist[a]); } -/* One the encode side, our vector writers are each designed for a -specific purpose, and the encoder is not flexible without modification: - -The LSP vector coder uses a single stage nearest-match with no -interleave, so no step and no error return. This is specced by floor0 -and doesn't change. - -Residue0 encoding interleaves, uses multiple stages, and each stage -peels of a specific amount of resolution from a lattice (thus we want -to match by threshold, not nearest match). Residue doesn't *have* to -be encoded that way, but to change it, one will need to add more -infrastructure on the encode side (decode side is specced and simpler) */ - -/* floor0 LSP (single stage, non interleaved, nearest match) */ -/* returns entry number and *modifies a* to the quantization value *****/ int vorbis_book_errorv(codebook *book,float *a){ int dim=book->dim,k; int best=_best(book,a,1); for(k=0;kvaluelist+best*dim)[k]; + a[k]=(book->valuelist+best*dim)[k]; return(best); } -/* returns the number of bits and *modifies a* to the quantization value *****/ int vorbis_book_encodev(codebook *book,int best,float *a,oggpack_buffer *b){ int k,dim=book->dim; for(k=0;kvaluelist+best*dim)[k]; + a[k]=(book->valuelist+best*dim)[k]; return(vorbis_book_encode(book,best,b)); } -/* the 'eliminate the decode tree' optimization actually requires the - codewords to be MSb first, not LSb. This is an annoying inelegancy - (and one of the first places where carefully thought out design - turned out to be wrong; Vorbis II and future Ogg codecs should go - to an MSb bitpacker), but not actually the huge hit it appears to - be. The first-stage decode table catches most words so that - bitreverse is not in the main execution path. */ - STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){ int read=book->dec_maxlength; long lo,hi; long lok = oggpack_look(b,book->dec_firsttablen); if (lok >= 0) { - long entry = book->dec_firsttable[lok]; - if(entry&0x80000000UL){ - lo=(entry>>15)&0x7fff; - hi=book->used_entries-(entry&0x7fff); - }else{ - oggpack_adv(b, book->dec_codelengths[entry-1]); - return(entry-1); - } + long entry = book->dec_firsttable[lok]; + if(entry&0x80000000UL){ + lo=(entry>>15)&0x7fff; + hi=book->used_entries-(entry&0x7fff); + }else{ + oggpack_adv(b, book->dec_codelengths[entry-1]); + return(entry-1); + } }else{ - lo=0; - hi=book->used_entries; + lo=0; + hi=book->used_entries; } lok = oggpack_look(b, read); while(lok<0 && read>1) - lok = oggpack_look(b, --read); + lok = oggpack_look(b, --read); if(lok<0)return -1; - /* bisect search for the codeword in the ordered list */ { - ogg_uint32_t testword=ogg_bitreverse((ogg_uint32_t)lok); + ogg_uint32_t testword=ogg_bitreverse((ogg_uint32_t)lok); - while(hi-lo>1){ - long p=(hi-lo)>>1; - long test=book->codelist[lo+p]>testword; - lo+=p&(test-1); - hi-=p&(-test); - } + while(hi-lo>1){ + long p=(hi-lo)>>1; + long test=book->codelist[lo+p]>testword; + lo+=p&(test-1); + hi-=p&(-test); + } - if(book->dec_codelengths[lo]<=read){ - oggpack_adv(b, book->dec_codelengths[lo]); - return(lo); - } + if(book->dec_codelengths[lo]<=read){ + oggpack_adv(b, book->dec_codelengths[lo]); + return(lo); + } } oggpack_adv(b, read); return(-1); } -/* Decode side is specced and easier, because we don't need to find - matches using different criteria; we simply read and map. There are - two things we need to do 'depending': - - We may need to support interleave. We don't really, but it's - convenient to do it here rather than rebuild the vector later. - - Cascades may be additive or multiplicitive; this is not inherent in - the codebook, but set in the code using the codebook. Like - interleaving, it's easiest to do it here. - addmul==0 -> declarative (set the value) - addmul==1 -> additive - addmul==2 -> multiplicitive */ - -/* returns the [original, not compacted] entry number or -1 on eof *********/ long vorbis_book_decode(codebook *book, oggpack_buffer *b){ long packed_entry=decode_packed_entry_number(book,b); if(packed_entry>=0) - return(book->dec_index[packed_entry]); + return(book->dec_index[packed_entry]); - /* if there's no dec_index, the codebook unpacking isn't collapsed */ return(packed_entry); } -/* returns 0 on OK or -1 on eof *************************************/ long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){ int step=n/book->dim; long *entry = (long*)alloca(sizeof(*entry)*step); @@ -132053,13 +121161,13 @@ long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){ int i,j,o; for (i = 0; i < step; i++) { - entry[i]=decode_packed_entry_number(book,b); - if(entry[i]==-1)return(-1); - t[i] = book->valuelist+entry[i]*book->dim; + entry[i]=decode_packed_entry_number(book,b); + if(entry[i]==-1)return(-1); + t[i] = book->valuelist+entry[i]*book->dim; } for(i=0,o=0;idim;i++,o+=step) - for (j=0;jdim>8){ - for(i=0;ivaluelist+entry*book->dim; - for (j=0;jdim;) + for(i=0;ivaluelist+entry*book->dim; + for (j=0;jdim;) a[i++]+=t[j++]; - } + } }else{ - for(i=0;ivaluelist+entry*book->dim; - j=0; - switch((int)book->dim){ - case 8: + for(i=0;ivaluelist+entry*book->dim; + j=0; + switch((int)book->dim){ + case 8: a[i++]+=t[j++]; - case 7: + case 7: a[i++]+=t[j++]; - case 6: + case 6: a[i++]+=t[j++]; - case 5: + case 5: a[i++]+=t[j++]; - case 4: + case 4: a[i++]+=t[j++]; - case 3: + case 3: a[i++]+=t[j++]; - case 2: + case 2: a[i++]+=t[j++]; - case 1: + case 1: a[i++]+=t[j++]; - case 0: + case 0: break; - } - } + } + } } return(0); } @@ -132111,42 +121219,38 @@ long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){ float *t; for(i=0;ivaluelist+entry*book->dim; - for (j=0;jdim;) - a[i++]=t[j++]; + entry = decode_packed_entry_number(book,b); + if(entry==-1)return(-1); + t = book->valuelist+entry*book->dim; + for (j=0;jdim;) + a[i++]=t[j++]; } return(0); } long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch, - oggpack_buffer *b,int n){ + oggpack_buffer *b,int n){ long i,j,entry; int chptr=0; for(i=offset/ch;i<(offset+n)/ch;){ - entry = decode_packed_entry_number(book,b); - if(entry==-1)return(-1); - { - const float *t = book->valuelist+entry*book->dim; - for (j=0;jdim;j++){ + entry = decode_packed_entry_number(book,b); + if(entry==-1)return(-1); + { + const float *t = book->valuelist+entry*book->dim; + for (j=0;jdim;j++){ a[chptr++][i]+=t[j]; if(chptr==ch){ chptr=0; i++; } - } - } + } + } } return(0); } #ifdef _V_SELFTEST -/* Simple enough; pack a few candidate codebooks, unpack them. Code a - number of vectors through (keeping track of the quantized values), - and decode using the unpacked book. quantized version of in should - exactly equal out */ #include @@ -132213,7 +121317,7 @@ float test3[TESTSIZE]={ 30,-25,-30,-1,-5,-32,4,3,-2,0}; static_codebook *testlist[]={&_vq_book_lsp20_0, - &_vq_book_res0a_13,NULL}; + &_vq_book_res0a_13,NULL}; float *testvec[]={test1,test3}; int main(){ @@ -132225,59 +121329,55 @@ int main(){ fprintf(stderr,"Testing codebook abstraction...:\n"); while(testlist[ptr]){ - codebook c; - static_codebook s; - float *qv=alloca(sizeof(*qv)*TESTSIZE); - float *iv=alloca(sizeof(*iv)*TESTSIZE); - memcpy(qv,testvec[ptr],sizeof(*qv)*TESTSIZE); - memset(iv,0,sizeof(*iv)*TESTSIZE); + codebook c; + static_codebook s; + float *qv=alloca(sizeof(*qv)*TESTSIZE); + float *iv=alloca(sizeof(*iv)*TESTSIZE); + memcpy(qv,testvec[ptr],sizeof(*qv)*TESTSIZE); + memset(iv,0,sizeof(*iv)*TESTSIZE); - fprintf(stderr,"\tpacking/coding %ld... ",ptr); + fprintf(stderr,"\tpacking/coding %ld... ",ptr); - /* pack the codebook, write the testvector */ - oggpack_reset(&write); - vorbis_book_init_encode(&c,testlist[ptr]); /* get it into memory - we can write */ - vorbis_staticbook_pack(testlist[ptr],&write); - fprintf(stderr,"Codebook size %ld bytes... ",oggpack_bytes(&write)); - for(i=0;i.000001){ + } + for(i=0;i.000001){ fprintf(stderr,"read (%g) != written (%g) at position (%ld)\n", iv[i],qv[i],i); exit(1); - } + } - fprintf(stderr,"OK\n"); - ptr++; + fprintf(stderr,"OK\n"); + ptr++; } - /* The above is the trivial stuff; now try unquantizing a log scale codebook */ - exit(0); } @@ -132320,11 +121420,10 @@ void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){ mdct_init(&e->mdct,n); for(i=0;imdct_win[i]=sin(i/(n-1.)*M_PI); - e->mdct_win[i]*=e->mdct_win[i]; + e->mdct_win[i]=sin(i/(n-1.)*M_PI); + e->mdct_win[i]*=e->mdct_win[i]; } - /* magic follows */ e->band[0].begin=2; e->band[0].end=4; e->band[1].begin=4; e->band[1].end=5; e->band[2].begin=6; e->band[2].end=6; @@ -132334,13 +121433,13 @@ void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){ e->band[6].begin=22; e->band[6].end=8; for(j=0;jband[j].end; - e->band[j].window=(float*)_ogg_malloc(n*sizeof(*e->band[0].window)); - for(i=0;iband[j].window[i]=sin((i+.5)/n*M_PI); - e->band[j].total+=e->band[j].window[i]; - } - e->band[j].total=1./e->band[j].total; + n=e->band[j].end; + e->band[j].window=(float*)_ogg_malloc(n*sizeof(*e->band[0].window)); + for(i=0;iband[j].window[i]=sin((i+.5)/n*M_PI); + e->band[j].total+=e->band[j].window[i]; + } + e->band[j].total=1./e->band[j].total; } e->filter=(envelope_filter_state*)_ogg_calloc(VE_BANDS*ch,sizeof(*e->filter)); @@ -132352,16 +121451,13 @@ void _ve_envelope_clear(envelope_lookup *e){ int i; mdct_clear(&e->mdct); for(i=0;iband[i].window); + _ogg_free(e->band[i].window); _ogg_free(e->mdct_win); _ogg_free(e->filter); _ogg_free(e->mark); memset(e,0,sizeof(*e)); } -/* fairly straight threshhold-by-band based until we find something - that works better and isn't patented. */ - static int _ve_amp(envelope_lookup *ve, vorbis_info_psy_global *gi, float *data, @@ -132373,112 +121469,86 @@ static int _ve_amp(envelope_lookup *ve, long i,j; float decay; - /* we want to have a 'minimum bar' for energy, else we're just - basing blocks on quantization noise that outweighs the signal - itself (for low power signals) */ - float minV=ve->minenergy; float *vec=(float*) alloca(n*sizeof(*vec)); - /* stretch is used to gradually lengthen the number of windows - considered prevoius-to-potential-trigger */ int stretch=max(VE_MINSTRETCH,ve->stretch/2); float penalty=gi->stretch_penalty-(ve->stretch/2-VE_MINSTRETCH); if(penalty<0.f)penalty=0.f; if(penalty>gi->stretch_penalty)penalty=gi->stretch_penalty; - /*_analysis_output_always("lpcm",seq2,data,n,0,0, - totalshift+pos*ve->searchstep);*/ - - /* window and transform */ for(i=0;imdct_win[i]; + vec[i]=data[i]*ve->mdct_win[i]; mdct_forward(&ve->mdct,vec,vec); - /*_analysis_output_always("mdct",seq2,vec,n/2,0,1,0); */ - - /* near-DC spreading function; this has nothing to do with - psychoacoustics, just sidelobe leakage and window size */ { - float temp=vec[0]*vec[0]+.7*vec[1]*vec[1]+.2*vec[2]*vec[2]; - int ptr=filters->nearptr; + float temp=vec[0]*vec[0]+.7*vec[1]*vec[1]+.2*vec[2]*vec[2]; + int ptr=filters->nearptr; - /* the accumulation is regularly refreshed from scratch to avoid - floating point creep */ - if(ptr==0){ - decay=filters->nearDC_acc=filters->nearDC_partialacc+temp; - filters->nearDC_partialacc=temp; - }else{ - decay=filters->nearDC_acc+=temp; - filters->nearDC_partialacc+=temp; - } - filters->nearDC_acc-=filters->nearDC[ptr]; - filters->nearDC[ptr]=temp; + if(ptr==0){ + decay=filters->nearDC_acc=filters->nearDC_partialacc+temp; + filters->nearDC_partialacc=temp; + }else{ + decay=filters->nearDC_acc+=temp; + filters->nearDC_partialacc+=temp; + } + filters->nearDC_acc-=filters->nearDC[ptr]; + filters->nearDC[ptr]=temp; - decay*=(1./(VE_NEARDC+1)); - filters->nearptr++; - if(filters->nearptr>=VE_NEARDC)filters->nearptr=0; - decay=todB(&decay)*.5-15.f; + decay*=(1./(VE_NEARDC+1)); + filters->nearptr++; + if(filters->nearptr>=VE_NEARDC)filters->nearptr=0; + decay=todB(&decay)*.5-15.f; } - /* perform spreading and limiting, also smooth the spectrum. yes, - the MDCT results in all real coefficients, but it still *behaves* - like real/imaginary pairs */ for(i=0;i>1]=val; - decay-=8.; + float val=vec[i]*vec[i]+vec[i+1]*vec[i+1]; + val=todB(&val)*.5f; + if(val>1]=val; + decay-=8.; } - /*_analysis_output_always("spread",seq2++,vec,n/4,0,0,0);*/ - - /* perform preecho/postecho triggering by band */ for(j=0;j=VE_AMP)filters[j].ampptr=0; - } + filters[j].ampbuf[thisx]=acc; + filters[j].ampptr++; + if(filters[j].ampptr>=VE_AMP)filters[j].ampptr=0; + } - /* look at min/max, decide trigger */ - if(valmax>gi->preecho_thresh[j]+penalty){ - ret|=1; - ret|=4; - } - if(valminpostecho_thresh[j]-penalty)ret|=2; + if(valmax>gi->preecho_thresh[j]+penalty){ + ret|=1; + ret|=4; + } + if(valminpostecho_thresh[j]-penalty)ret|=2; } return(ret); @@ -132500,92 +121570,91 @@ long _ve_envelope_search(vorbis_dsp_state *v){ int last=v->pcm_current/ve->searchstep-VE_WIN; if(first<0)first=0; - /* make sure we have enough storage to match the PCM */ if(last+VE_WIN+VE_POST>ve->storage){ - ve->storage=last+VE_WIN+VE_POST; /* be sure */ - ve->mark=(int*)_ogg_realloc(ve->mark,ve->storage*sizeof(*ve->mark)); + ve->storage=last+VE_WIN+VE_POST; /* be sure */ + ve->mark=(int*)_ogg_realloc(ve->mark,ve->storage*sizeof(*ve->mark)); } for(j=first;jstretch++; - if(ve->stretch>VE_MAXSTRETCH*2) - ve->stretch=VE_MAXSTRETCH*2; + ve->stretch++; + if(ve->stretch>VE_MAXSTRETCH*2) + ve->stretch=VE_MAXSTRETCH*2; - for(i=0;ich;i++){ - float *pcm=v->pcm[i]+ve->searchstep*(j); - ret|=_ve_amp(ve,gi,pcm,ve->band,ve->filter+i*VE_BANDS,j); - } + for(i=0;ich;i++){ + float *pcm=v->pcm[i]+ve->searchstep*(j); + ret|=_ve_amp(ve,gi,pcm,ve->band,ve->filter+i*VE_BANDS,j); + } - ve->mark[j+VE_POST]=0; - if(ret&1){ - ve->mark[j]=1; - ve->mark[j+1]=1; - } + ve->mark[j+VE_POST]=0; + if(ret&1){ + ve->mark[j]=1; + ve->mark[j+1]=1; + } - if(ret&2){ - ve->mark[j]=1; - if(j>0)ve->mark[j-1]=1; - } + if(ret&2){ + ve->mark[j]=1; + if(j>0)ve->mark[j-1]=1; + } - if(ret&4)ve->stretch=-1; + if(ret&4)ve->stretch=-1; } ve->current=last*ve->searchstep; { - long centerW=v->centerW; - long testW= - centerW+ - ci->blocksizes[v->W]/4+ - ci->blocksizes[1]/2+ - ci->blocksizes[0]/4; + long centerW=v->centerW; + long testW= + centerW+ + ci->blocksizes[v->W]/4+ + ci->blocksizes[1]/2+ + ci->blocksizes[0]/4; - j=ve->cursor; + j=ve->cursor; - while(jcurrent-(ve->searchstep)){/* account for postecho - working back one window */ - if(j>=testW)return(1); + while(jcurrent-(ve->searchstep)){/* account for postecho + working back one window */ + if(j>=testW)return(1); - ve->cursor=j; + ve->cursor=j; - if(ve->mark[j/ve->searchstep]){ + if(ve->mark[j/ve->searchstep]){ if(j>centerW){ #if 0 if(j>ve->curmark){ - float *marker=alloca(v->pcm_current*sizeof(*marker)); - int l,m; - memset(marker,0,sizeof(*marker)*v->pcm_current); + float *marker=alloca(v->pcm_current*sizeof(*marker)); + int l,m; + memset(marker,0,sizeof(*marker)*v->pcm_current); fprintf(stderr,"mark! seq=%d, cursor:%fs time:%fs\n", - seq, - (totalshift+ve->cursor)/44100., - (totalshift+j)/44100.); + seq, + (totalshift+ve->cursor)/44100., + (totalshift+j)/44100.); _analysis_output_always("pcmL",seq,v->pcm[0],v->pcm_current,0,0,totalshift); _analysis_output_always("pcmR",seq,v->pcm[1],v->pcm_current,0,0,totalshift); _analysis_output_always("markL",seq,v->pcm[0],j,0,0,totalshift); _analysis_output_always("markR",seq,v->pcm[1],j,0,0,totalshift); - for(m=0;msearchstep]=ve->filter[m].markers[l]*.1; - _analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift); - } + for(l=0;lsearchstep]=ve->filter[m].markers[l]*.1; + _analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift); + } - for(m=0;msearchstep]=ve->filter[m+VE_BANDS].markers[l]*.1; - _analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift); - } + for(l=0;lsearchstep]=ve->filter[m+VE_BANDS].markers[l]*.1; + _analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift); + } - for(l=0;lsearchstep]=ve->mark[l]*.4; + for(l=0;lsearchstep]=ve->mark[l]*.4; _analysis_output_always("mark",seq,marker,v->pcm_current,0,0,totalshift); - seq++; + seq++; } #endif @@ -132594,9 +121663,9 @@ long _ve_envelope_search(vorbis_dsp_state *v){ if(j>=testW)return(1); return(0); } - } - j+=ve->searchstep; - } + } + j+=ve->searchstep; + } } return(-1); @@ -132610,42 +121679,42 @@ int _ve_envelope_mark(vorbis_dsp_state *v){ long beginW=centerW-ci->blocksizes[v->W]/4; long endW=centerW+ci->blocksizes[v->W]/4; if(v->W){ - beginW-=ci->blocksizes[v->lW]/4; - endW+=ci->blocksizes[v->nW]/4; + beginW-=ci->blocksizes[v->lW]/4; + endW+=ci->blocksizes[v->nW]/4; }else{ - beginW-=ci->blocksizes[0]/4; - endW+=ci->blocksizes[0]/4; + beginW-=ci->blocksizes[0]/4; + endW+=ci->blocksizes[0]/4; } if(ve->curmark>=beginW && ve->curmarksearchstep; - long last=endW/ve->searchstep; - long i; - for(i=first;imark[i])return(1); + long first=beginW/ve->searchstep; + long last=endW/ve->searchstep; + long i; + for(i=first;imark[i])return(1); } return(0); } void _ve_envelope_shift(envelope_lookup *e,long shift){ int smallsize=e->current/e->searchstep+VE_POST; /* adjust for placing marks - ahead of ve->current */ + ahead of ve->current */ int smallshift=shift/e->searchstep; memmove(e->mark,e->mark+smallshift,(smallsize-smallshift)*sizeof(*e->mark)); #if 0 for(i=0;ich;i++) - memmove(e->filter[i].markers, - e->filter[i].markers+smallshift, - (1024-smallshift)*sizeof(*(*e->filter).markers)); + memmove(e->filter[i].markers, + e->filter[i].markers+smallshift, + (1024-smallshift)*sizeof(*(*e->filter).markers)); totalshift+=shift; #endif e->current-=shift; if(e->curmark>=0) - e->curmark-=shift; + e->curmark-=shift; e->cursor-=shift; } @@ -132696,13 +121765,11 @@ typedef struct { long frames; } vorbis_look_floor0; -/***********************************************/ - static void floor0_free_info(vorbis_info_floor *i){ vorbis_info_floor0 *info=(vorbis_info_floor0 *)i; if(info){ - memset(info,0,sizeof(*info)); - _ogg_free(info); + memset(info,0,sizeof(*info)); + _ogg_free(info); } } @@ -132710,20 +121777,20 @@ static void floor0_free_look(vorbis_look_floor *i){ vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; if(look){ - if(look->linearmap){ + if(look->linearmap){ - if(look->linearmap[0])_ogg_free(look->linearmap[0]); - if(look->linearmap[1])_ogg_free(look->linearmap[1]); + if(look->linearmap[0])_ogg_free(look->linearmap[0]); + if(look->linearmap[1])_ogg_free(look->linearmap[1]); - _ogg_free(look->linearmap); - } - memset(look,0,sizeof(*look)); - _ogg_free(look); + _ogg_free(look->linearmap); + } + memset(look,0,sizeof(*look)); + _ogg_free(look); } } static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; int j; vorbis_info_floor0 *info=(vorbis_info_floor0*)_ogg_malloc(sizeof(*info)); @@ -132740,8 +121807,8 @@ static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ if(info->numbooks<1)goto err_out; for(j=0;jnumbooks;j++){ - info->books[j]=oggpack_read(opb,8); - if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out; + info->books[j]=oggpack_read(opb,8); + if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out; } return(info); @@ -132750,50 +121817,33 @@ static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ return(NULL); } -/* initialize Bark scale and normalization lookups. We could do this - with static tables, but Vorbis allows a number of possible - combinations, so it's best to do it computationally. - - The below is authoritative in terms of defining scale mapping. - Note that the scale depends on the sampling rate as well as the - linear block and mapping sizes */ - -static void floor0_map_lazy_init(vorbis_block *vb, +static void floor0_map_lazy_init(vorbis_block *vb, vorbis_info_floor *infoX, vorbis_look_floor0 *look){ if(!look->linearmap[vb->W]){ - vorbis_dsp_state *vd=vb->vd; - vorbis_info *vi=vd->vi; - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; - vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX; - int W=vb->W; - int n=ci->blocksizes[W]/2,j; + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX; + int W=vb->W; + int n=ci->blocksizes[W]/2,j; - /* we choose a scaling constant so that: - floor(bark(rate/2-1)*C)=mapped-1 - floor(bark(rate/2)*C)=mapped */ - float scale=look->ln/toBARK(info->rate/2.f); + float scale=look->ln/toBARK(info->rate/2.f); - /* the mapping from a linear scale to a smaller bark scale is - straightforward. We do *not* make sure that the linear mapping - does not skip bark-scale bins; the decoder simply skips them and - the encoder may do what it wishes in filling them. They're - necessary in some mapping combinations to keep the scale spacing - accurate */ - look->linearmap[W]=(int*)_ogg_malloc((n+1)*sizeof(**look->linearmap)); - for(j=0;jrate/2.f)/n*j) - *scale); /* bark numbers represent band edges */ - if(val>=look->ln)val=look->ln-1; /* guard against the approximation */ - look->linearmap[W][j]=val; - } - look->linearmap[W][j]=-1; - look->n[W]=n; + look->linearmap[W]=(int*)_ogg_malloc((n+1)*sizeof(**look->linearmap)); + for(j=0;jrate/2.f)/n*j) + *scale); /* bark numbers represent band edges */ + if(val>=look->ln)val=look->ln-1; /* guard against the approximation */ + look->linearmap[W][j]=val; + } + look->linearmap[W][j]=-1; + look->n[W]=n; } } static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd, - vorbis_info_floor *i){ + vorbis_info_floor *i){ vorbis_info_floor0 *info=(vorbis_info_floor0*)i; vorbis_look_floor0 *look=(vorbis_look_floor0*)_ogg_calloc(1,sizeof(*look)); look->m=info->order; @@ -132812,30 +121862,27 @@ static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){ int ampraw=oggpack_read(&vb->opb,info->ampbits); if(ampraw>0){ /* also handles the -1 out of data case */ - long maxval=(1<ampbits)-1; - float amp=(float)ampraw/maxval*info->ampdB; - int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); + long maxval=(1<ampbits)-1; + float amp=(float)ampraw/maxval*info->ampdB; + int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); - if(booknum!=-1 && booknumnumbooks){ /* be paranoid */ - codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; - codebook *b=ci->fullbooks+info->books[booknum]; - float last=0.f; + if(booknum!=-1 && booknumnumbooks){ /* be paranoid */ + codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; + codebook *b=ci->fullbooks+info->books[booknum]; + float last=0.f; - /* the additional b->dim is a guard against any possible stack - smash; b->dim is provably more than we can overflow the - vector */ - float *lsp=(float*)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1)); + float *lsp=(float*)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1)); - for(j=0;jm;j+=b->dim) + for(j=0;jm;j+=b->dim) if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop; - for(j=0;jm;){ + for(j=0;jm;){ for(k=0;kdim;k++,j++)lsp[j]+=last; last=lsp[j-1]; - } + } - lsp[look->m]=amp; - return(lsp); - } + lsp[look->m]=amp; + return(lsp); + } } eop: return(NULL); @@ -132849,22 +121896,20 @@ static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i, floor0_map_lazy_init(vb,info,look); if(memo){ - float *lsp=(float *)memo; - float amp=lsp[look->m]; + float *lsp=(float *)memo; + float amp=lsp[look->m]; - /* take the coefficients back to a spectral envelope curve */ - vorbis_lsp_to_curve(out, + vorbis_lsp_to_curve(out, look->linearmap[vb->W], look->n[vb->W], look->ln, lsp,look->m,amp,(float)info->ampdB); - return(1); + return(1); } memset(out,0,sizeof(*out)*look->n[vb->W]); return(0); } -/* export hooks */ vorbis_func_floor floor0_exportbundle={ NULL,&floor0_unpack,&floor0_look,&floor0_free_info, &floor0_free_look,&floor0_inverse1,&floor0_inverse2 @@ -132924,26 +121969,20 @@ typedef struct lsfit_acc{ long an; } lsfit_acc; -/***********************************************/ - static void floor1_free_info(vorbis_info_floor *i){ vorbis_info_floor1 *info=(vorbis_info_floor1 *)i; if(info){ - memset(info,0,sizeof(*info)); - _ogg_free(info); + memset(info,0,sizeof(*info)); + _ogg_free(info); } } static void floor1_free_look(vorbis_look_floor *i){ vorbis_look_floor1 *look=(vorbis_look_floor1 *)i; if(look){ - /*fprintf(stderr,"floor 1 bit usage %f:%f (%f total)\n", - (float)look->phrasebits/look->frames, - (float)look->postbits/look->frames, - (float)(look->postbits+look->phrasebits)/look->frames);*/ - memset(look,0,sizeof(*look)); - _ogg_free(look); + memset(look,0,sizeof(*look)); + _ogg_free(look); } } @@ -132955,73 +121994,67 @@ static void floor1_pack (vorbis_info_floor *i,oggpack_buffer *opb){ int maxposit=info->postlist[1]; int maxclass=-1; - /* save out partitions */ oggpack_write(opb,info->partitions,5); /* only 0 to 31 legal */ for(j=0;jpartitions;j++){ - oggpack_write(opb,info->partitionclass[j],4); /* only 0 to 15 legal */ - if(maxclasspartitionclass[j])maxclass=info->partitionclass[j]; + oggpack_write(opb,info->partitionclass[j],4); /* only 0 to 15 legal */ + if(maxclasspartitionclass[j])maxclass=info->partitionclass[j]; } - /* save out partition classes */ for(j=0;jclass_dim[j]-1,3); /* 1 to 8 */ - oggpack_write(opb,info->class_subs[j],2); /* 0 to 3 */ - if(info->class_subs[j])oggpack_write(opb,info->class_book[j],8); - for(k=0;k<(1<class_subs[j]);k++) - oggpack_write(opb,info->class_subbook[j][k]+1,8); + oggpack_write(opb,info->class_dim[j]-1,3); /* 1 to 8 */ + oggpack_write(opb,info->class_subs[j],2); /* 0 to 3 */ + if(info->class_subs[j])oggpack_write(opb,info->class_book[j],8); + for(k=0;k<(1<class_subs[j]);k++) + oggpack_write(opb,info->class_subbook[j][k]+1,8); } - /* save out the post list */ - oggpack_write(opb,info->mult-1,2); /* only 1,2,3,4 legal now */ + oggpack_write(opb,info->mult-1,2); /* only 1,2,3,4 legal now */ oggpack_write(opb,ilog2(maxposit),4); rangebits=ilog2(maxposit); for(j=0,k=0;jpartitions;j++){ - count+=info->class_dim[info->partitionclass[j]]; - for(;kpostlist[k+2],rangebits); + count+=info->class_dim[info->partitionclass[j]]; + for(;kpostlist[k+2],rangebits); } } static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; int j,k,count=0,maxclass=-1,rangebits; vorbis_info_floor1 *info=(vorbis_info_floor1*)_ogg_calloc(1,sizeof(*info)); - /* read partitions */ info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */ for(j=0;jpartitions;j++){ - info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */ - if(maxclasspartitionclass[j])maxclass=info->partitionclass[j]; + info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */ + if(maxclasspartitionclass[j])maxclass=info->partitionclass[j]; } - /* read partition classes */ for(j=0;jclass_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */ - info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */ - if(info->class_subs[j]<0) - goto err_out; - if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8); - if(info->class_book[j]<0 || info->class_book[j]>=ci->books) - goto err_out; - for(k=0;k<(1<class_subs[j]);k++){ - info->class_subbook[j][k]=oggpack_read(opb,8)-1; - if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books) + info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */ + info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */ + if(info->class_subs[j]<0) + goto err_out; + if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8); + if(info->class_book[j]<0 || info->class_book[j]>=ci->books) + goto err_out; + for(k=0;k<(1<class_subs[j]);k++){ + info->class_subbook[j][k]=oggpack_read(opb,8)-1; + if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books) goto err_out; - } + } } - /* read the post list */ - info->mult=oggpack_read(opb,2)+1; /* only 1,2,3,4 legal now */ + info->mult=oggpack_read(opb,2)+1; /* only 1,2,3,4 legal now */ rangebits=oggpack_read(opb,4); for(j=0,k=0;jpartitions;j++){ - count+=info->class_dim[info->partitionclass[j]]; - for(;kpostlist[k+2]=oggpack_read(opb,rangebits); - if(t<0 || t>=(1<class_dim[info->partitionclass[j]]; + for(;kpostlist[k+2]=oggpack_read(opb,rangebits); + if(t<0 || t>=(1<postlist[0]=0; info->postlist[1]=1<vi=info; look->n=info->postlist[1]; - /* we drop each position value in-between already decoded values, - and use linear interpolation to predict each new value past the - edges. The positions are read in the order of the position - list... we precompute the bounding positions in the lookup. Of - course, the neighbors can change (if a position is declined), but - this is an initial mapping */ - for(i=0;ipartitions;i++)n+=info->class_dim[info->partitionclass[i]]; n+=2; look->posts=n; - /* also store a sorted position index */ for(i=0;ipostlist+i; qsort(sortpointer,n,sizeof(*sortpointer),icomp); - /* points from sort order back to range number */ for(i=0;iforward_index[i]=sortpointer[i]-info->postlist; - /* points from range order to sorted position */ for(i=0;ireverse_index[look->forward_index[i]]=i; - /* we actually need the post values too */ for(i=0;isorted_index[i]=info->postlist[look->forward_index[i]]; - /* quantize values to multiplier spec */ switch(info->mult){ case 1: /* 1024 -> 256 */ - look->quant_q=256; - break; + look->quant_q=256; + break; case 2: /* 1024 -> 128 */ - look->quant_q=128; - break; + look->quant_q=128; + break; case 3: /* 1024 -> 86 */ - look->quant_q=86; - break; + look->quant_q=86; + break; case 4: /* 1024 -> 64 */ - look->quant_q=64; - break; + look->quant_q=64; + break; } - /* discover our neighbors for decode where we don't use fit flags - (that would push the neighbors outward) */ for(i=0;in; - int currentx=info->postlist[i+2]; - for(j=0;jpostlist[j]; - if(x>lx && xn; + int currentx=info->postlist[i+2]; + for(j=0;jpostlist[j]; + if(x>lx && xcurrentx){ + } + if(xcurrentx){ hi=j; hx=x; - } - } - look->loneighbor[i]=lo; - look->hineighbor[i]=hi; + } + } + look->loneighbor[i]=lo; + look->hineighbor[i]=hi; } return(look); @@ -133117,14 +122136,14 @@ static int render_point(int x0,int x1,int y0,int y1,int x){ y1&=0x7fff; { - int dy=y1-y0; - int adx=x1-x0; - int ady=abs(dy); - int err=ady*(x-x0); + int dy=y1-y0; + int adx=x1-x0; + int ady=abs(dy); + int err=ady*(x-x0); - int off=err/adx; - if(dy<0)return(y0-off); - return(y0+off); + int off=err/adx; + if(dy<0)return(y0-off); + return(y0+off); } } @@ -133216,14 +122235,14 @@ static void render_line(int x0,int x1,int y0,int y1,float *d){ d[x]*=FLOOR1_fromdB_LOOKUP[y]; while(++x=adx){ - err-=adx; - y+=sy; - }else{ - y+=base; - } - d[x]*=FLOOR1_fromdB_LOOKUP[y]; + err=err+ady; + if(err>=adx){ + err-=adx; + y+=sy; + }else{ + y+=base; + } + d[x]*=FLOOR1_fromdB_LOOKUP[y]; } } @@ -133241,18 +122260,17 @@ static void render_line0(int x0,int x1,int y0,int y1,int *d){ d[x]=y; while(++x=adx){ - err-=adx; - y+=sy; - }else{ - y+=base; - } - d[x]=y; + err=err+ady; + if(err>=adx){ + err-=adx; + y+=sy; + }else{ + y+=base; + } + d[x]=y; } } -/* the floor has already been filtered to only include relevant sections */ static int accumulate_fit(const float *flr,const float *mdct, int x0, int x1,lsfit_acc *a, int n,vorbis_info_floor1 *info){ @@ -133265,24 +122283,24 @@ static int accumulate_fit(const float *flr,const float *mdct, if(x1>=n)x1=n-1; for(i=x0;i<=x1;i++){ - int quantized=vorbis_dBquant(flr+i); - if(quantized){ - if(mdct[i]+info->twofitatten>=flr[i]){ + int quantized=vorbis_dBquant(flr+i); + if(quantized){ + if(mdct[i]+info->twofitatten>=flr[i]){ xa += i; ya += quantized; x2a += i*i; y2a += quantized*quantized; xya += i*quantized; na++; - }else{ + }else{ xb += i; yb += quantized; x2b += i*i; y2b += quantized*quantized; xyb += i*quantized; nb++; - } - } + } + } } xb+=xa; @@ -133292,16 +122310,15 @@ static int accumulate_fit(const float *flr,const float *mdct, xyb+=xya; nb+=na; - /* weight toward the actually used frequencies if we meet the threshhold */ { - int weight=nb*info->twofitweight/(na+1); + int weight=nb*info->twofitweight/(na+1); - a->xa=xa*weight+xb; - a->ya=ya*weight+yb; - a->x2a=x2a*weight+x2b; - a->y2a=y2a*weight+y2b; - a->xya=xya*weight+xyb; - a->an=na*weight+nb; + a->xa=xa*weight+xb; + a->ya=ya*weight+yb; + a->x2a=x2a*weight+x2b; + a->y2a=y2a*weight+y2b; + a->xya=xya*weight+xyb; + a->an=na*weight+nb; } return(na); @@ -133313,66 +122330,54 @@ static void fit_line(lsfit_acc *a,int fits,int *y0,int *y1){ long x1=a[fits-1].x1; for(i=0;i=0){ - x+= x0; - y+= *y0; - x2+= x0 * x0; - y2+= *y0 * *y0; - xy+= *y0 * x0; - an++; + x+= x0; + y+= *y0; + x2+= x0 * x0; + y2+= *y0 * *y0; + xy+= *y0 * x0; + an++; } if(*y1>=0){ - x+= x1; - y+= *y1; - x2+= x1 * x1; - y2+= *y1 * *y1; - xy+= *y1 * x1; - an++; + x+= x1; + y+= *y1; + x2+= x1 * x1; + y2+= *y1 * *y1; + xy+= *y1 * x1; + an++; } if(an){ - /* need 64 bit multiplies, which C doesn't give portably as int */ - double fx=x; - double fy=y; - double fx2=x2; - double fxy=xy; - double denom=1./(an*fx2-fx*fx); - double a=(fy*fx2-fxy*fx)*denom; - double b=(an*fxy-fx*fy)*denom; - *y0=rint(a+b*x0); - *y1=rint(a+b*x1); + double fx=x; + double fy=y; + double fx2=x2; + double fxy=xy; + double denom=1./(an*fx2-fx*fx); + double a=(fy*fx2-fxy*fx)*denom; + double b=(an*fxy-fx*fy)*denom; + *y0=rint(a+b*x0); + *y1=rint(a+b*x1); - /* limit to our range! */ - if(*y0>1023)*y0=1023; - if(*y1>1023)*y1=1023; - if(*y0<0)*y0=0; - if(*y1<0)*y1=0; + if(*y0>1023)*y0=1023; + if(*y1>1023)*y1=1023; + if(*y0<0)*y0=0; + if(*y1<0)*y1=0; }else{ - *y0=0; - *y1=0; + *y0=0; + *y1=0; } } -/*static void fit_line_point(lsfit_acc *a,int fits,int *y0,int *y1){ - long y=0; - int i; - - for(i=0;itwofitatten>=mask[x]){ - if(y+info->maxovermaxunder>val)return(1); + if(y+info->maxovermaxunder>val)return(1); } while(++x=adx){ - err-=adx; - y+=sy; - }else{ - y+=base; - } + err=err+ady; + if(err>=adx){ + err-=adx; + y+=sy; + }else{ + y+=base; + } - val=vorbis_dBquant(mask+x); - mse+=((y-val)*(y-val)); - n++; - if(mdct[x]+info->twofitatten>=mask[x]){ - if(val){ + val=vorbis_dBquant(mask+x); + mse+=((y-val)*(y-val)); + n++; + if(mdct[x]+info->twofitatten>=mask[x]){ + if(val){ if(y+info->maxovermaxunder>val)return(1); - } - } + } + } } if(info->maxover*info->maxover/n>info->maxerr)return(0); @@ -133426,9 +122431,9 @@ static int inspect_error(int x0,int x1,int y0,int y1,const float *mask, static int post_Y(int *A,int *B,int pos){ if(A[pos]<0) - return B[pos]; + return B[pos]; if(B[pos]<0) - return A[pos]; + return A[pos]; return (A[pos]+B[pos])>>1; } @@ -133455,122 +122460,106 @@ int *floor1_fit(vorbis_block *vb,void *look_, for(i=0;isorted_index[i], - look->sorted_index[i+1],fits+i, - n,info); + for(i=0;isorted_index[i], + look->sorted_index[i+1],fits+i, + n,info); } if(nonzero){ - /* start by fitting the implicit base case.... */ - int y0=-200; - int y1=-200; - fit_line(fits,posts-1,&y0,&y1); + int y0=-200; + int y1=-200; + fit_line(fits,posts-1,&y0,&y1); - fit_valueA[0]=y0; - fit_valueB[0]=y0; - fit_valueB[1]=y1; - fit_valueA[1]=y1; + fit_valueA[0]=y0; + fit_valueB[0]=y0; + fit_valueB[1]=y1; + fit_valueA[1]=y1; - /* Non degenerate case */ - /* start progressive splitting. This is a greedy, non-optimal - algorithm, but simple and close enough to the best - answer. */ - for(i=2;ireverse_index[i]; - int ln=loneighbor[sortpos]; - int hn=hineighbor[sortpos]; + for(i=2;ireverse_index[i]; + int ln=loneighbor[sortpos]; + int hn=hineighbor[sortpos]; - /* eliminate repeat searches of a particular range with a memo */ - if(memo[ln]!=hn){ - /* haven't performed this error search yet */ + if(memo[ln]!=hn){ int lsortpos=look->reverse_index[ln]; int hsortpos=look->reverse_index[hn]; memo[ln]=hn; { - /* A note: we want to bound/minimize *local*, not global, error */ int lx=info->postlist[ln]; int hx=info->postlist[hn]; int ly=post_Y(fit_valueA,fit_valueB,ln); int hy=post_Y(fit_valueA,fit_valueB,hn); if(ly==-1 || hy==-1){ - exit(1); + exit(1); } if(inspect_error(lx,hx,ly,hy,logmask,logmdct,info)){ - /* outside error bounds/begin search area. Split it. */ - int ly0=-200; - int ly1=-200; - int hy0=-200; - int hy1=-200; - fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1); - fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1); + int ly0=-200; + int ly1=-200; + int hy0=-200; + int hy1=-200; + fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1); + fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1); - /* store new edge values */ - fit_valueB[ln]=ly0; - if(ln==0)fit_valueA[ln]=ly0; - fit_valueA[i]=ly1; - fit_valueB[i]=hy0; - fit_valueA[hn]=hy1; - if(hn==1)fit_valueB[hn]=hy1; + fit_valueB[ln]=ly0; + if(ln==0)fit_valueA[ln]=ly0; + fit_valueA[i]=ly1; + fit_valueB[i]=hy0; + fit_valueA[hn]=hy1; + if(hn==1)fit_valueB[hn]=hy1; - if(ly1>=0 || hy0>=0){ - /* store new neighbor values */ - for(j=sortpos-1;j>=0;j--) + if(ly1>=0 || hy0>=0){ + for(j=sortpos-1;j>=0;j--) if(hineighbor[j]==hn) hineighbor[j]=i; else break; - for(j=sortpos+1;jloneighbor[i-2]; - int hn=look->hineighbor[i-2]; - int x0=info->postlist[ln]; - int x1=info->postlist[hn]; - int y0=output[ln]; - int y1=output[hn]; + for(i=2;iloneighbor[i-2]; + int hn=look->hineighbor[i-2]; + int x0=info->postlist[ln]; + int x1=info->postlist[hn]; + int y0=output[ln]; + int y1=output[hn]; - int predicted=render_point(x0,x1,y0,y1,info->postlist[i]); - int vx=post_Y(fit_valueA,fit_valueB,i); + int predicted=render_point(x0,x1,y0,y1,info->postlist[i]); + int vx=post_Y(fit_valueA,fit_valueB,i); - if(vx>=0 && predicted!=vx){ + if(vx>=0 && predicted!=vx){ output[i]=vx; - }else{ + }else{ output[i]= predicted|0x8000; - } - } + } + } } return(output); @@ -133587,12 +122576,12 @@ int *floor1_interpolate_fit(vorbis_block *vb,void *look_, int *output=NULL; if(A && B){ - output=(int*)_vorbis_block_alloc(vb,sizeof(*output)*posts); + output=(int*)_vorbis_block_alloc(vb,sizeof(*output)*posts); - for(i=0;i>16; - if(A[i]&0x8000 && B[i]&0x8000)output[i]|=0x8000; - } + for(i=0;i>16; + if(A[i]&0x8000 && B[i]&0x8000)output[i]|=0x8000; + } } return(output); @@ -133612,118 +122601,104 @@ int floor1_encode(oggpack_buffer *opb,vorbis_block *vb, codebook *books=ci->fullbooks; static long seq=0; - /* quantize values to multiplier spec */ if(post){ - for(i=0;imult){ - case 1: /* 1024 -> 256 */ + for(i=0;imult){ + case 1: /* 1024 -> 256 */ val>>=2; break; - case 2: /* 1024 -> 128 */ + case 2: /* 1024 -> 128 */ val>>=3; break; - case 3: /* 1024 -> 86 */ + case 3: /* 1024 -> 86 */ val/=12; break; - case 4: /* 1024 -> 64 */ + case 4: /* 1024 -> 64 */ val>>=4; break; - } - post[i]=val | (post[i]&0x8000); - } + } + post[i]=val | (post[i]&0x8000); + } - out[0]=post[0]; - out[1]=post[1]; + out[0]=post[0]; + out[1]=post[1]; - /* find prediction values for each post and subtract them */ - for(i=2;iloneighbor[i-2]; - int hn=look->hineighbor[i-2]; - int x0=info->postlist[ln]; - int x1=info->postlist[hn]; - int y0=post[ln]; - int y1=post[hn]; + for(i=2;iloneighbor[i-2]; + int hn=look->hineighbor[i-2]; + int x0=info->postlist[ln]; + int x1=info->postlist[hn]; + int y0=post[ln]; + int y1=post[hn]; - int predicted=render_point(x0,x1,y0,y1,info->postlist[i]); + int predicted=render_point(x0,x1,y0,y1,info->postlist[i]); - if((post[i]&0x8000) || (predicted==post[i])){ + if((post[i]&0x8000) || (predicted==post[i])){ post[i]=predicted|0x8000; /* in case there was roundoff jitter - in interpolation */ + in interpolation */ out[i]=0; - }else{ + }else{ int headroom=(look->quant_q-predictedquant_q-predicted:predicted); + look->quant_q-predicted:predicted); int val=post[i]-predicted; - /* at this point the 'deviation' value is in the range +/- max - range, but the real, unique range can always be mapped to - only [0-maxrange). So we want to wrap the deviation into - this limited range, but do it in the way that least screws - an essentially gaussian probability distribution. */ - if(val<0) if(val<-headroom) - val=headroom-val-1; + val=headroom-val-1; else - val=-1-(val<<1); + val=-1-(val<<1); else if(val>=headroom) - val= val+headroom; + val= val+headroom; else - val<<=1; + val<<=1; out[i]=val; post[ln]&=0x7fff; post[hn]&=0x7fff; - } - } + } + } - /* we have everything we need. pack it out */ - /* mark nontrivial floor */ - oggpack_write(opb,1,1); + oggpack_write(opb,1,1); - /* beginning/end post */ - look->frames++; - look->postbits+=ilog(look->quant_q-1)*2; - oggpack_write(opb,out[0],ilog(look->quant_q-1)); - oggpack_write(opb,out[1],ilog(look->quant_q-1)); + look->frames++; + look->postbits+=ilog(look->quant_q-1)*2; + oggpack_write(opb,out[0],ilog(look->quant_q-1)); + oggpack_write(opb,out[1],ilog(look->quant_q-1)); - /* partition by partition */ - for(i=0,j=2;ipartitions;i++){ - int classx=info->partitionclass[i]; - int cdim=info->class_dim[classx]; - int csubbits=info->class_subs[classx]; - int csub=1<partitions;i++){ + int classx=info->partitionclass[i]; + int cdim=info->class_dim[classx]; + int csubbits=info->class_subs[classx]; + int csub=1<class_subbook[classx][k]; if(booknum<0){ - maxval[k]=1; + maxval[k]=1; }else{ - maxval[k]=sbooks[info->class_subbook[classx][k]]->entries; + maxval[k]=sbooks[info->class_subbook[classx][k]]->entries; } } for(k=0;kphrasebits+= vorbis_book_encode(books+info->class_book[classx],cval,opb); @@ -133738,42 +122713,36 @@ int floor1_encode(oggpack_buffer *opb,vorbis_block *vb, fclose(of); } #endif - } + } - /* write post values */ - for(k=0;kclass_subbook[classx][bookas[k]]; if(book>=0){ - /* hack to allow training with 'bad' books */ if(out[j+k]<(books+book)->entries) - look->postbits+=vorbis_book_encode(books+book, - out[j+k],opb); - /*else - fprintf(stderr,"+!");*/ + look->postbits+=vorbis_book_encode(books+book, + out[j+k],opb); #ifdef TRAIN_FLOOR1 { - FILE *of; - char buffer[80]; + FILE *of; + char buffer[80]; sprintf(buffer,"line_%dx%ld_%dsub%d.vqd", - vb->pcmend/2,posts-2,class,bookas[k]); + vb->pcmend/2,posts-2,class,bookas[k]); of=fopen(buffer,"a"); fprintf(of,"%d\n",out[j+k]); - fclose(of); + fclose(of); } #endif } - } - j+=cdim; - } + } + j+=cdim; + } - { - /* generate quantized floor equivalent to what we'd unpack in decode */ - /* render the lines */ - int hx=0; - int lx=0; - int ly=post[0]*info->mult; - for(j=1;jposts;j++){ + { + int hx=0; + int lx=0; + int ly=post[0]*info->mult; + for(j=1;jposts;j++){ int current=look->forward_index[j]; int hy=post[current]&0x7fff; if(hy==post[current]){ @@ -133786,16 +122755,16 @@ int floor1_encode(oggpack_buffer *opb,vorbis_block *vb, lx=hx; ly=hy; } - } - for(j=hx;jpcmend/2;j++)ilogmask[j]=ly; /* be certain */ - seq++; - return(1); - } + } + for(j=hx;jpcmend/2;j++)ilogmask[j]=ly; /* be certain */ + seq++; + return(1); + } }else{ - oggpack_write(opb,0,1); - memset(ilogmask,0,vb->pcmend/2*sizeof(*ilogmask)); - seq++; - return(0); + oggpack_write(opb,0,1); + memset(ilogmask,0,vb->pcmend/2*sizeof(*ilogmask)); + seq++; + return(0); } } @@ -133807,65 +122776,61 @@ static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ int i,j,k; codebook *books=ci->fullbooks; - /* unpack wrapped/predicted values from stream */ if(oggpack_read(&vb->opb,1)==1){ - int *fit_value=(int*)_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value)); + int *fit_value=(int*)_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value)); - fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); - fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); + fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); + fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); - /* partition by partition */ - for(i=0,j=2;ipartitions;i++){ - int classx=info->partitionclass[i]; - int cdim=info->class_dim[classx]; - int csubbits=info->class_subs[classx]; - int csub=1<partitions;i++){ + int classx=info->partitionclass[i]; + int cdim=info->class_dim[classx]; + int csubbits=info->class_subs[classx]; + int csub=1<class_book[classx],&vb->opb); if(cval==-1)goto eop; - } + } - for(k=0;kclass_subbook[classx][cval&(csub-1)]; cval>>=csubbits; if(book>=0){ if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1) - goto eop; + goto eop; }else{ fit_value[j+k]=0; } - } - j+=cdim; - } + } + j+=cdim; + } - /* unwrap positive values and reconsitute via linear interpolation */ - for(i=2;iposts;i++){ - int predicted=render_point(info->postlist[look->loneighbor[i-2]], + for(i=2;iposts;i++){ + int predicted=render_point(info->postlist[look->loneighbor[i-2]], info->postlist[look->hineighbor[i-2]], fit_value[look->loneighbor[i-2]], fit_value[look->hineighbor[i-2]], info->postlist[i]); - int hiroom=look->quant_q-predicted; - int loroom=predicted; - int room=(hiroomquant_q-predicted; + int loroom=predicted; + int room=(hiroom=room){ if(hiroom>loroom){ - val = val-loroom; + val = val-loroom; }else{ - val = -1-(val-hiroom); + val = -1-(val-hiroom); } }else{ if(val&1){ - val= -((val+1)>>1); + val= -((val+1)>>1); }else{ - val>>=1; + val>>=1; } } @@ -133873,13 +122838,13 @@ static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ fit_value[look->loneighbor[i-2]]&=0x7fff; fit_value[look->hineighbor[i-2]]&=0x7fff; - }else{ + }else{ fit_value[i]=predicted|0x8000; - } + } - } + } - return(fit_value); + return(fit_value); } eop: return(NULL); @@ -133891,19 +122856,18 @@ static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo, vorbis_info_floor1 *info=look->vi; codec_setup_info *ci=(codec_setup_info*)vb->vd->vi->codec_setup; - int n=ci->blocksizes[vb->W]/2; + int n=ci->blocksizes[vb->W]/2; int j; if(memo){ - /* render the lines */ - int *fit_value=(int *)memo; - int hx=0; - int lx=0; - int ly=fit_value[0]*info->mult; - for(j=1;jposts;j++){ - int current=look->forward_index[j]; - int hy=fit_value[current]&0x7fff; - if(hy==fit_value[current]){ + int *fit_value=(int *)memo; + int hx=0; + int lx=0; + int ly=fit_value[0]*info->mult; + for(j=1;jposts;j++){ + int current=look->forward_index[j]; + int hy=fit_value[current]&0x7fff; + if(hy==fit_value[current]){ hy*=info->mult; hx=info->postlist[current]; @@ -133912,16 +122876,15 @@ static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo, lx=hx; ly=hy; - } - } - for(j=hx;j #include #include @@ -133953,13 +122913,13 @@ vorbis_func_floor floor1_exportbundle={ static void _v_writestring(oggpack_buffer *o, const char *s, int bytes){ while(bytes--){ - oggpack_write(o,*s++,8); + oggpack_write(o,*s++,8); } } static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ while(bytes--){ - *buf++=oggpack_read(o,8); + *buf++=oggpack_read(o,8); } } @@ -133969,9 +122929,9 @@ void vorbis_comment_init(vorbis_comment *vc){ void vorbis_comment_add(vorbis_comment *vc,char *comment){ vc->user_comments=(char**)_ogg_realloc(vc->user_comments, - (vc->comments+2)*sizeof(*vc->user_comments)); + (vc->comments+2)*sizeof(*vc->user_comments)); vc->comment_lengths=(int*)_ogg_realloc(vc->comment_lengths, - (vc->comments+2)*sizeof(*vc->comment_lengths)); + (vc->comments+2)*sizeof(*vc->comment_lengths)); vc->comment_lengths[vc->comments]=strlen(comment); vc->user_comments[vc->comments]=(char*)_ogg_malloc(vc->comment_lengths[vc->comments]+1); strcpy(vc->user_comments[vc->comments], comment); @@ -133987,14 +122947,12 @@ void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, char *contents) vorbis_comment_add(vc, comment); } -/* This is more or less the same as strncasecmp - but that doesn't exist - * everywhere, and this is a fairly trivial function, so we include it */ static int tagcompare(const char *s1, const char *s2, int n){ int c=0; while(c < n){ - if(toupper(s1[c]) != toupper(s2[c])) - return !0; - c++; + if(toupper(s1[c]) != toupper(s2[c])) + return !0; + c++; } return 0; } @@ -134009,13 +122967,12 @@ char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){ strcat(fulltag, "="); for(i=0;icomments;i++){ - if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ - if(count == found) - /* We return a pointer to the data, not a copy */ - return vc->user_comments[i] + taglen; - else + if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ + if(count == found) + return vc->user_comments[i] + taglen; + else found++; - } + } } return NULL; /* didn't find anything */ } @@ -134028,8 +122985,8 @@ int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ strcat(fulltag, "="); for(i=0;icomments;i++){ - if(!tagcompare(vc->user_comments[i], fulltag, taglen)) - count++; + if(!tagcompare(vc->user_comments[i], fulltag, taglen)) + count++; } return count; @@ -134037,71 +122994,65 @@ int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ void vorbis_comment_clear(vorbis_comment *vc){ if(vc){ - long i; - for(i=0;icomments;i++) - if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); - if(vc->user_comments)_ogg_free(vc->user_comments); + long i; + for(i=0;icomments;i++) + if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); + if(vc->user_comments)_ogg_free(vc->user_comments); if(vc->comment_lengths)_ogg_free(vc->comment_lengths); - if(vc->vendor)_ogg_free(vc->vendor); + if(vc->vendor)_ogg_free(vc->vendor); } memset(vc,0,sizeof(*vc)); } -/* blocksize 0 is guaranteed to be short, 1 is guarantted to be long. - They may be equal, but short will never ge greater than long */ int vorbis_info_blocksize(vorbis_info *vi,int zo){ codec_setup_info *ci = (codec_setup_info*)vi->codec_setup; return ci ? ci->blocksizes[zo] : -1; } -/* used by synthesis, which has a full, alloced vi */ void vorbis_info_init(vorbis_info *vi){ memset(vi,0,sizeof(*vi)); vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info)); } void vorbis_info_clear(vorbis_info *vi){ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; int i; if(ci){ - for(i=0;imodes;i++) - if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); + for(i=0;imodes;i++) + if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); - for(i=0;imaps;i++) /* unpack does the range checking */ - _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); + for(i=0;imaps;i++) /* unpack does the range checking */ + _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); - for(i=0;ifloors;i++) /* unpack does the range checking */ - _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); + for(i=0;ifloors;i++) /* unpack does the range checking */ + _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); - for(i=0;iresidues;i++) /* unpack does the range checking */ - _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); + for(i=0;iresidues;i++) /* unpack does the range checking */ + _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); - for(i=0;ibooks;i++){ - if(ci->book_param[i]){ - /* knows if the book was not alloced */ + for(i=0;ibooks;i++){ + if(ci->book_param[i]){ vorbis_staticbook_destroy(ci->book_param[i]); - } - if(ci->fullbooks) + } + if(ci->fullbooks) vorbis_book_clear(ci->fullbooks+i); - } - if(ci->fullbooks) + } + if(ci->fullbooks) _ogg_free(ci->fullbooks); - for(i=0;ipsys;i++) - _vi_psy_free(ci->psy_param[i]); + for(i=0;ipsys;i++) + _vi_psy_free(ci->psy_param[i]); - _ogg_free(ci); + _ogg_free(ci); } memset(vi,0,sizeof(*vi)); } -/* Header packing/unpacking ********************************************/ - static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; if(!ci)return(OV_EFAULT); vi->version=oggpack_read(opb,32); @@ -134142,11 +123093,11 @@ static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ vc->comment_lengths=(int*)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths)); for(i=0;icomments;i++){ - int len=oggpack_read(opb,32); - if(len<0)goto err_out; + int len=oggpack_read(opb,32); + if(len<0)goto err_out; vc->comment_lengths[i]=len; - vc->user_comments[i]=(char*)_ogg_calloc(len+1,1); - _v_readstring(opb,vc->user_comments[i],len); + vc->user_comments[i]=(char*)_ogg_calloc(len+1,1); + _v_readstring(opb,vc->user_comments[i],len); } if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ @@ -134156,76 +123107,60 @@ static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ return(OV_EBADHEADER); } -/* all of the real encoding details are here. The modes, books, - everything */ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; int i; if(!ci)return(OV_EFAULT); - /* codebooks */ ci->books=oggpack_read(opb,8)+1; - /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/ for(i=0;ibooks;i++){ - ci->book_param[i]=(static_codebook*)_ogg_calloc(1,sizeof(*ci->book_param[i])); - if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out; + ci->book_param[i]=(static_codebook*)_ogg_calloc(1,sizeof(*ci->book_param[i])); + if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out; } - /* time backend settings; hooks are unused */ { - int times=oggpack_read(opb,6)+1; - for(i=0;i=VI_TIMEB)goto err_out; - } + int times=oggpack_read(opb,6)+1; + for(i=0;i=VI_TIMEB)goto err_out; + } } - /* floor backend settings */ ci->floors=oggpack_read(opb,6)+1; - /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/ - /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/ for(i=0;ifloors;i++){ - ci->floor_type[i]=oggpack_read(opb,16); - if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; - ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); - if(!ci->floor_param[i])goto err_out; + ci->floor_type[i]=oggpack_read(opb,16); + if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; + ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); + if(!ci->floor_param[i])goto err_out; } - /* residue backend settings */ ci->residues=oggpack_read(opb,6)+1; - /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/ - /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/ for(i=0;iresidues;i++){ - ci->residue_type[i]=oggpack_read(opb,16); - if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; - ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); - if(!ci->residue_param[i])goto err_out; + ci->residue_type[i]=oggpack_read(opb,16); + if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; + ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); + if(!ci->residue_param[i])goto err_out; } - /* map backend settings */ ci->maps=oggpack_read(opb,6)+1; - /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/ - /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/ for(i=0;imaps;i++){ - ci->map_type[i]=oggpack_read(opb,16); - if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; - ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); - if(!ci->map_param[i])goto err_out; + ci->map_type[i]=oggpack_read(opb,16); + if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; + ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); + if(!ci->map_param[i])goto err_out; } - /* mode settings */ ci->modes=oggpack_read(opb,6)+1; - /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/ for(i=0;imodes;i++){ - ci->mode_param[i]=(vorbis_info_mode*)_ogg_calloc(1,sizeof(*ci->mode_param[i])); - ci->mode_param[i]->blockflag=oggpack_read(opb,1); - ci->mode_param[i]->windowtype=oggpack_read(opb,16); - ci->mode_param[i]->transformtype=oggpack_read(opb,16); - ci->mode_param[i]->mapping=oggpack_read(opb,8); + ci->mode_param[i]=(vorbis_info_mode*)_ogg_calloc(1,sizeof(*ci->mode_param[i])); + ci->mode_param[i]->blockflag=oggpack_read(opb,1); + ci->mode_param[i]->windowtype=oggpack_read(opb,16); + ci->mode_param[i]->transformtype=oggpack_read(opb,16); + ci->mode_param[i]->mapping=oggpack_read(opb,8); - if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; - if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; - if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; + if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; + if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; + if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; } if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ @@ -134236,78 +123171,61 @@ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ return(OV_EBADHEADER); } -/* The Vorbis header is in three packets; the initial small packet in - the first page that identifies basic parameters, a second packet - with bitstream comments and a third packet that holds the - codebook. */ - int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ oggpack_buffer opb; if(op){ - oggpack_readinit(&opb,op->packet,op->bytes); + oggpack_readinit(&opb,op->packet,op->bytes); - /* Which of the three types of header is this? */ - /* Also verify header-ness, vorbis */ - { - char buffer[6]; - int packtype=oggpack_read(&opb,8); - memset(buffer,0,6); - _v_readstring(&opb,buffer,6); - if(memcmp(buffer,"vorbis",6)){ - /* not a vorbis header */ + { + char buffer[6]; + int packtype=oggpack_read(&opb,8); + memset(buffer,0,6); + _v_readstring(&opb,buffer,6); + if(memcmp(buffer,"vorbis",6)){ return(OV_ENOTVORBIS); - } - switch(packtype){ - case 0x01: /* least significant *bit* is read first */ + } + switch(packtype){ + case 0x01: /* least significant *bit* is read first */ if(!op->b_o_s){ - /* Not the initial packet */ return(OV_EBADHEADER); } if(vi->rate!=0){ - /* previously initialized info header */ return(OV_EBADHEADER); } return(_vorbis_unpack_info(vi,&opb)); - case 0x03: /* least significant *bit* is read first */ + case 0x03: /* least significant *bit* is read first */ if(vi->rate==0){ - /* um... we didn't get the initial header */ return(OV_EBADHEADER); } return(_vorbis_unpack_comment(vc,&opb)); - case 0x05: /* least significant *bit* is read first */ + case 0x05: /* least significant *bit* is read first */ if(vi->rate==0 || vc->vendor==NULL){ - /* um... we didn;t get the initial header or comments yet */ return(OV_EBADHEADER); } return(_vorbis_unpack_books(vi,&opb)); - default: - /* Not a valid vorbis header type */ + default: return(OV_EBADHEADER); break; - } - } + } + } } return(OV_EBADHEADER); } -/* pack side **********************************************************/ - static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; if(!ci)return(OV_EFAULT); - /* preamble */ oggpack_write(opb,0x01,8); _v_writestring(opb,"vorbis", 6); - /* basic information about the stream */ oggpack_write(opb,0x00,32); oggpack_write(opb,vi->channels,8); oggpack_write(opb,vi->rate,32); @@ -134327,27 +123245,23 @@ static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){ char temp[]="Xiph.Org libVorbis I 20050304"; int bytes = strlen(temp); - /* preamble */ oggpack_write(opb,0x03,8); _v_writestring(opb,"vorbis", 6); - /* vendor */ oggpack_write(opb,bytes,32); _v_writestring(opb,temp, bytes); - /* comments */ - oggpack_write(opb,vc->comments,32); if(vc->comments){ - int i; - for(i=0;icomments;i++){ - if(vc->user_comments[i]){ + int i; + for(i=0;icomments;i++){ + if(vc->user_comments[i]){ oggpack_write(opb,vc->comment_lengths[i],32); _v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]); - }else{ + }else{ oggpack_write(opb,0,32); - } - } + } + } } oggpack_write(opb,1,1); @@ -134355,53 +123269,47 @@ static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){ } static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; int i; if(!ci)return(OV_EFAULT); oggpack_write(opb,0x05,8); _v_writestring(opb,"vorbis", 6); - /* books */ oggpack_write(opb,ci->books-1,8); for(i=0;ibooks;i++) - if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out; + if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out; - /* times; hook placeholders */ oggpack_write(opb,0,6); oggpack_write(opb,0,16); - /* floors */ oggpack_write(opb,ci->floors-1,6); for(i=0;ifloors;i++){ - oggpack_write(opb,ci->floor_type[i],16); - if(_floor_P[ci->floor_type[i]]->pack) - _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb); - else - goto err_out; + oggpack_write(opb,ci->floor_type[i],16); + if(_floor_P[ci->floor_type[i]]->pack) + _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb); + else + goto err_out; } - /* residues */ oggpack_write(opb,ci->residues-1,6); for(i=0;iresidues;i++){ - oggpack_write(opb,ci->residue_type[i],16); - _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb); + oggpack_write(opb,ci->residue_type[i],16); + _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb); } - /* maps */ oggpack_write(opb,ci->maps-1,6); for(i=0;imaps;i++){ - oggpack_write(opb,ci->map_type[i],16); - _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb); + oggpack_write(opb,ci->map_type[i],16); + _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb); } - /* modes */ oggpack_write(opb,ci->modes-1,6); for(i=0;imodes;i++){ - oggpack_write(opb,ci->mode_param[i]->blockflag,1); - oggpack_write(opb,ci->mode_param[i]->windowtype,16); - oggpack_write(opb,ci->mode_param[i]->transformtype,16); - oggpack_write(opb,ci->mode_param[i]->mapping,8); + oggpack_write(opb,ci->mode_param[i]->blockflag,1); + oggpack_write(opb,ci->mode_param[i]->windowtype,16); + oggpack_write(opb,ci->mode_param[i]->transformtype,16); + oggpack_write(opb,ci->mode_param[i]->mapping,8); } oggpack_write(opb,1,1); @@ -134411,7 +123319,7 @@ err_out: } int vorbis_commentheader_out(vorbis_comment *vc, - ogg_packet *op){ + ogg_packet *op){ oggpack_buffer opb; @@ -134431,26 +123339,23 @@ int vorbis_commentheader_out(vorbis_comment *vc, } int vorbis_analysis_headerout(vorbis_dsp_state *v, - vorbis_comment *vc, - ogg_packet *op, - ogg_packet *op_comm, - ogg_packet *op_code){ + vorbis_comment *vc, + ogg_packet *op, + ogg_packet *op_comm, + ogg_packet *op_code){ int ret=OV_EIMPL; vorbis_info *vi=v->vi; oggpack_buffer opb; private_state *b=(private_state*)v->backend_state; if(!b){ - ret=OV_EFAULT; - goto err_out; + ret=OV_EFAULT; + goto err_out; } - /* first header packet **********************************************/ - oggpack_writeinit(&opb); if(_vorbis_pack_info(&opb,vi))goto err_out; - /* build the packet */ if(b->header)_ogg_free(b->header); b->header=(unsigned char*) _ogg_malloc(oggpack_bytes(&opb)); memcpy(b->header,opb.buffer,oggpack_bytes(&opb)); @@ -134461,8 +123366,6 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v, op->granulepos=0; op->packetno=0; - /* second header packet (comments) **********************************/ - oggpack_reset(&opb); if(_vorbis_pack_comment(&opb,vc))goto err_out; @@ -134476,8 +123379,6 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v, op_comm->granulepos=0; op_comm->packetno=1; - /* third header packet (modes/codebooks) ****************************/ - oggpack_reset(&opb); if(_vorbis_pack_books(&opb,vi))goto err_out; @@ -134510,7 +123411,7 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v, double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){ if(granulepos>=0) - return((double)granulepos/v->vi->rate); + return((double)granulepos/v->vi->rate); return(-1); } @@ -134518,33 +123419,6 @@ double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){ /********* End of inlined file: info.c *********/ /********* Start of inlined file: lpc.c *********/ -/* Some of these routines (autocorrelator, LPC coefficient estimator) - are derived from code written by Jutta Degener and Carsten Bormann; - thus we include their copyright below. The entirety of this file - is freely redistributable on the condition that both of these - copyright notices are preserved without modification. */ - -/* Preserved Copyright: *********************************************/ - -/* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann, -Technische Universita"t Berlin - -Any use of this software is permitted provided that this notice is not -removed and that neither the authors nor the Technische Universita"t -Berlin are deemed to have made any representations as to the -suitability of this software for any purpose nor are held responsible -for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR -THIS SOFTWARE. - -As a matter of courtesy, the authors request to be informed about uses -this software has found, about bugs in this software, and about any -improvements that may be of general interest. - -Berlin, 28.11.1994 -Jutta Degener -Carsten Bormann - -*********************************************************************/ /********* Start of inlined file: juce_OggVorbisHeader.h *********/ // This file is included at the start of each Ogg-Vorbis .c file, just to do a few housekeeping @@ -134561,94 +123435,71 @@ Carsten Bormann #include #include -/* Autocorrelation LPC coeff generation algorithm invented by - N. Levinson in 1947, modified by J. Durbin in 1959. */ - -/* Input : n elements of time doamin data - Output: m lpc coefficients, excitation energy */ - float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){ double *aut=(double*)alloca(sizeof(*aut)*(m+1)); double *lpc=(double*)alloca(sizeof(*lpc)*(m)); double error; int i,j; - /* autocorrelation, p+1 lag coefficients */ j=m+1; while(j--){ - double d=0; /* double needed for accumulator depth */ - for(i=j;i -/* interpolated lookup based fromdB function, domain -140dB to 0dB only */ float vorbis_fromdBlook(float a){ int i=vorbis_ftoi(a*((float)(-(1<=(FROMdB_LOOKUP_SZ<>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); + ((i>=(FROMdB_LOOKUP_SZ<>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); } #endif #ifdef INT_LOOKUP -/* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in - 16.16 format - - returns in m.8 format */ long vorbis_invsqlook_i(long a,long e){ long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1); long d=(a&INVSQ_LOOKUP_I_MASK)<<(16-INVSQ_LOOKUP_I_SHIFT); /* 0.16 */ - long val=INVSQ_LOOKUP_I[i]- /* 1.16 */ - (((INVSQ_LOOKUP_I[i]-INVSQ_LOOKUP_I[i+1])* /* 0.16 */ - d)>>16); /* result 1.16 */ + long val=INVSQ_LOOKUP_I[i]- /* 1.16 */ + (((INVSQ_LOOKUP_I[i]-INVSQ_LOOKUP_I[i+1])* /* 0.16 */ + d)>>16); /* result 1.16 */ e+=32; if(e&1)val=(val*5792)>>13; /* multiply val by 1/sqrt(2) */ @@ -134975,17 +123798,13 @@ long vorbis_invsqlook_i(long a,long e){ return(val>>e); } -/* interpolated lookup based fromdB function, domain -140dB to 0dB only */ -/* a is in n.12 format */ float vorbis_fromdBlook_i(long a){ int i=(-a)>>(12-FROMdB2_SHIFT); return (i<0)?1.f: - ((i>=(FROMdB_LOOKUP_SZ<>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); + ((i>=(FROMdB_LOOKUP_SZ<>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); } -/* interpolated lookup based cos function, domain 0 to PI only */ -/* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */ long vorbis_coslook_i(long a){ int i=a>>COS_LOOKUP_I_SHIFT; int d=a&COS_LOOKUP_I_MASK; @@ -134998,13 +123817,8 @@ long vorbis_coslook_i(long a){ #endif /********* End of inlined file: lookup.c *********/ - /* catch this in the build system; we #include for - compilers (like gcc) that can't inline across - modules */ - -/* side effect: changes *lsp to cosines of lsp */ void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m, - float amp,float ampoffset){ + float amp,float ampoffset){ int i; float wdel=M_PI/ln; vorbis_fpu_control fpu; @@ -135015,41 +123829,38 @@ void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m, i=0; while(i>1; + int k=map[i]; + int qexp; + float p=.7071067812f; + float q=.7071067812f; + float w=vorbis_coslook(wdel*k); + float *ftmp=lsp; + int c=m>>1; - do{ - q*=ftmp[0]-w; - p*=ftmp[1]-w; - ftmp+=2; - }while(--c); + do{ + q*=ftmp[0]-w; + p*=ftmp[1]-w; + ftmp+=2; + }while(--c); - if(m&1){ - /* odd order filter; slightly assymetric */ - /* the last coefficient */ - q*=ftmp[0]-w; - q*=q; - p*=p*(1.f-w*w); - }else{ - /* even order filter; still symmetric */ - q*=q*(1.f+w); - p*=p*(1.f-w); - } + if(m&1){ + q*=ftmp[0]-w; + q*=q; + p*=p*(1.f-w*w); + }else{ + q*=q*(1.f+w); + p*=p*(1.f-w); + } - q=frexp(p+q,&qexp); - q=vorbis_fromdBlook(amp* + q=frexp(p+q,&qexp); + q=vorbis_fromdBlook(amp* vorbis_invsqlook(q)* vorbis_invsq2explook(qexp+m)- ampoffset); - do{ - curve[i++]*=q; - }while(map[i]==k); + do{ + curve[i++]*=q; + }while(map[i]==k); } vorbis_fpu_restore(fpu); } @@ -135148,20 +123959,20 @@ static float INVSQ_LOOKUP[INVSQ_LOOKUP_SZ+1]={ #define INVSQ2EXP_LOOKUP_MIN (-32) #define INVSQ2EXP_LOOKUP_MAX 32 static float INVSQ2EXP_LOOKUP[INVSQ2EXP_LOOKUP_MAX-\ - INVSQ2EXP_LOOKUP_MIN+1]={ - 65536.f, 46340.95001f, 32768.f, 23170.47501f, - 16384.f, 11585.2375f, 8192.f, 5792.618751f, - 4096.f, 2896.309376f, 2048.f, 1448.154688f, - 1024.f, 724.0773439f, 512.f, 362.038672f, - 256.f, 181.019336f, 128.f, 90.50966799f, - 64.f, 45.254834f, 32.f, 22.627417f, - 16.f, 11.3137085f, 8.f, 5.656854249f, - 4.f, 2.828427125f, 2.f, 1.414213562f, - 1.f, 0.7071067812f, 0.5f, 0.3535533906f, - 0.25f, 0.1767766953f, 0.125f, 0.08838834765f, - 0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f, - 0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f, - 0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f, + INVSQ2EXP_LOOKUP_MIN+1]={ + 65536.f, 46340.95001f, 32768.f, 23170.47501f, + 16384.f, 11585.2375f, 8192.f, 5792.618751f, + 4096.f, 2896.309376f, 2048.f, 1448.154688f, + 1024.f, 724.0773439f, 512.f, 362.038672f, + 256.f, 181.019336f, 128.f, 90.50966799f, + 64.f, 45.254834f, 32.f, 22.627417f, + 16.f, 11.3137085f, 8.f, 5.656854249f, + 4.f, 2.828427125f, 2.f, 1.414213562f, + 1.f, 0.7071067812f, 0.5f, 0.3535533906f, + 0.25f, 0.1767766953f, 0.125f, 0.08838834765f, + 0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f, + 0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f, + 0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f, 0.0009765625f, 0.000690533966f, 0.00048828125f, 0.000345266983f, 0.000244140625f,0.0001726334915f,0.0001220703125f,8.631674575e-05f, 6.103515625e-05f,4.315837288e-05f,3.051757812e-05f,2.157918644e-05f, @@ -135176,23 +123987,23 @@ static float INVSQ2EXP_LOOKUP[INVSQ2EXP_LOOKUP_MAX-\ #define FROMdB2_SHIFT 3 #define FROMdB2_MASK 31 static float FROMdB_LOOKUP[FROMdB_LOOKUP_SZ]={ - 1.f, 0.6309573445f, 0.3981071706f, 0.2511886432f, - 0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f, - 0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f, - 0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f, + 1.f, 0.6309573445f, 0.3981071706f, 0.2511886432f, + 0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f, + 0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f, + 0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f, 0.0006309573445f,0.0003981071706f,0.0002511886432f,0.0001584893192f, - 0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f, - 1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f, - 2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f, + 0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f, + 1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f, + 2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f, 3.981071706e-07f,2.511886432e-07f,1.584893192e-07f, }; static float FROMdB2_LOOKUP[FROMdB2_LOOKUP_SZ]={ 0.9928302478f, 0.9786445908f, 0.9646616199f, 0.9508784391f, - 0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f, + 0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f, 0.8848608897f, 0.8722179097f, 0.8597555737f, 0.8474713009f, - 0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f, - 0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f, + 0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f, + 0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f, 0.7445176537f, 0.7338799116f, 0.7233941627f, 0.7130582353f, 0.7028699885f, 0.6928273125f, 0.6829281272f, 0.6731703824f, 0.6635520573f, 0.6540711597f, 0.6447257262f, 0.6355138211f, @@ -135235,14 +124046,14 @@ static long COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={ 13623l, 13395l, 13160l, 12916l, 12665l, 12406l, 12140l, 11866l, 11585l, 11297l, 11003l, 10702l, - 10394l, 10080l, 9760l, 9434l, - 9102l, 8765l, 8423l, 8076l, - 7723l, 7366l, 7005l, 6639l, - 6270l, 5897l, 5520l, 5139l, - 4756l, 4370l, 3981l, 3590l, - 3196l, 2801l, 2404l, 2006l, - 1606l, 1205l, 804l, 402l, - 0l, -401l, -803l, -1204l, + 10394l, 10080l, 9760l, 9434l, + 9102l, 8765l, 8423l, 8076l, + 7723l, 7366l, 7005l, 6639l, + 6270l, 5897l, 5520l, 5139l, + 4756l, 4370l, 3981l, 3590l, + 3196l, 2801l, 2404l, 2006l, + 1606l, 1205l, 804l, 402l, + 0l, -401l, -803l, -1204l, -1605l, -2005l, -2403l, -2800l, -3195l, -3589l, -3980l, -4369l, -4755l, -5138l, -5519l, -5896l, @@ -135268,7 +124079,6 @@ static long COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={ #ifdef FLOAT_LOOKUP -/* interpolated lookup based cos function, domain 0 to PI only */ float vorbis_coslook(float a){ double d=a*(.31830989*(float)COS_LOOKUP_SZ); int i=vorbis_ftoi(d-.5); @@ -135276,40 +124086,33 @@ float vorbis_coslook(float a){ return COS_LOOKUP[i]+ (d-i)*(COS_LOOKUP[i+1]-COS_LOOKUP[i]); } -/* interpolated 1./sqrt(p) where .5 <= p < 1. */ float vorbis_invsqlook(float a){ double d=a*(2.f*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ; int i=vorbis_ftoi(d-.5f); return INVSQ_LOOKUP[i]+ (d-i)*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]); } -/* interpolated 1./sqrt(p) where .5 <= p < 1. */ float vorbis_invsq2explook(int a){ return INVSQ2EXP_LOOKUP[a-INVSQ2EXP_LOOKUP_MIN]; } #include -/* interpolated lookup based fromdB function, domain -140dB to 0dB only */ float vorbis_fromdBlook(float a){ int i=vorbis_ftoi(a*((float)(-(1<=(FROMdB_LOOKUP_SZ<>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); + ((i>=(FROMdB_LOOKUP_SZ<>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); } #endif #ifdef INT_LOOKUP -/* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in - 16.16 format - - returns in m.8 format */ long vorbis_invsqlook_i(long a,long e){ long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1); long d=(a&INVSQ_LOOKUP_I_MASK)<<(16-INVSQ_LOOKUP_I_SHIFT); /* 0.16 */ - long val=INVSQ_LOOKUP_I[i]- /* 1.16 */ - (((INVSQ_LOOKUP_I[i]-INVSQ_LOOKUP_I[i+1])* /* 0.16 */ - d)>>16); /* result 1.16 */ + long val=INVSQ_LOOKUP_I[i]- /* 1.16 */ + (((INVSQ_LOOKUP_I[i]-INVSQ_LOOKUP_I[i+1])* /* 0.16 */ + d)>>16); /* result 1.16 */ e+=32; if(e&1)val=(val*5792)>>13; /* multiply val by 1/sqrt(2) */ @@ -135318,17 +124121,13 @@ long vorbis_invsqlook_i(long a,long e){ return(val>>e); } -/* interpolated lookup based fromdB function, domain -140dB to 0dB only */ -/* a is in n.12 format */ float vorbis_fromdBlook_i(long a){ int i=(-a)>>(12-FROMdB2_SHIFT); return (i<0)?1.f: - ((i>=(FROMdB_LOOKUP_SZ<>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); + ((i>=(FROMdB_LOOKUP_SZ<>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); } -/* interpolated lookup based cos function, domain 0 to PI only */ -/* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */ long vorbis_coslook_i(long a){ int i=a>>COS_LOOKUP_I_SHIFT; int d=a&COS_LOOKUP_I_MASK; @@ -135341,10 +124140,6 @@ long vorbis_coslook_i(long a){ #endif /********* End of inlined file: lookup.c *********/ - /* catch this in the build system; we #include for - compilers (like gcc) that can't inline across - modules */ - static int MLOOP_1[64]={ 0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13, 14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14, @@ -135361,13 +124156,9 @@ static int MLOOP_2[64]={ static int MLOOP_3[8]={0,1,2,2,3,3,3,3}; -/* side effect: changes *lsp to cosines of lsp */ void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m, - float amp,float ampoffset){ + float amp,float ampoffset){ - /* 0 <= m < 256 */ - - /* set up for using all int later */ int i; int ampoffseti=rint(ampoffset*4096.f); int ampi=rint(amp*16.f); @@ -135376,131 +124167,110 @@ void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m, i=0; while(i>25])) + for(j=3;j>25])) if(!(shift=MLOOP_2[(pi|qi)>>19])) shift=MLOOP_3[(pi|qi)>>16]; - qi=(qi>>shift)*labs(ilsp[j-1]-wi); - pi=(pi>>shift)*labs(ilsp[j]-wi); - qexp+=shift; - } - if(!(shift=MLOOP_1[(pi|qi)>>25])) - if(!(shift=MLOOP_2[(pi|qi)>>19])) + qi=(qi>>shift)*labs(ilsp[j-1]-wi); + pi=(pi>>shift)*labs(ilsp[j]-wi); + qexp+=shift; + } + if(!(shift=MLOOP_1[(pi|qi)>>25])) + if(!(shift=MLOOP_2[(pi|qi)>>19])) shift=MLOOP_3[(pi|qi)>>16]; - /* pi,qi normalized collectively, both tracked using qexp */ + if(m&1){ + qi=(qi>>shift)*labs(ilsp[j-1]-wi); + pi=(pi>>shift)<<14; + qexp+=shift; - if(m&1){ - /* odd order filter; slightly assymetric */ - /* the last coefficient */ - qi=(qi>>shift)*labs(ilsp[j-1]-wi); - pi=(pi>>shift)<<14; - qexp+=shift; - - if(!(shift=MLOOP_1[(pi|qi)>>25])) + if(!(shift=MLOOP_1[(pi|qi)>>25])) if(!(shift=MLOOP_2[(pi|qi)>>19])) shift=MLOOP_3[(pi|qi)>>16]; - pi>>=shift; - qi>>=shift; - qexp+=shift-14*((m+1)>>1); + pi>>=shift; + qi>>=shift; + qexp+=shift-14*((m+1)>>1); - pi=((pi*pi)>>16); - qi=((qi*qi)>>16); - qexp=qexp*2+m; + pi=((pi*pi)>>16); + qi=((qi*qi)>>16); + qexp=qexp*2+m; - pi*=(1<<14)-((wi*wi)>>14); - qi+=pi>>14; + pi*=(1<<14)-((wi*wi)>>14); + qi+=pi>>14; - }else{ - /* even order filter; still symmetric */ + }else{ - /* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't - worth tracking step by step */ + pi>>=shift; + qi>>=shift; + qexp+=shift-7*m; - pi>>=shift; - qi>>=shift; - qexp+=shift-7*m; + pi=((pi*pi)>>16); + qi=((qi*qi)>>16); + qexp=qexp*2+m; - pi=((pi*pi)>>16); - qi=((qi*qi)>>16); - qexp=qexp*2+m; + pi*=(1<<14)-wi; + qi*=(1<<14)+wi; + qi=(qi+pi)>>14; - pi*=(1<<14)-wi; - qi*=(1<<14)+wi; - qi=(qi+pi)>>14; + } - } - - /* we've let the normalization drift because it wasn't important; - however, for the lookup, things must be normalized again. We - need at most one right shift or a number of left shifts */ - - if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */ - qi>>=1; qexp++; - }else - while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/ + if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */ + qi>>=1; qexp++; + }else + while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/ qi<<=1; qexp--; - } + } - amp=vorbis_fromdBlook_i(ampi* /* n.4 */ - vorbis_invsqlook_i(qi,qexp)- - /* m.8, m+n<=8 */ - ampoffseti); /* 8.12[0] */ + amp=vorbis_fromdBlook_i(ampi* /* n.4 */ + vorbis_invsqlook_i(qi,qexp)- + ampoffseti); /* 8.12[0] */ - curve[i]*=amp; - while(map[++i]==k)curve[i]*=amp; + curve[i]*=amp; + while(map[++i]==k)curve[i]*=amp; } } #else -/* old, nonoptimized but simple version for any poor sap who needs to - figure out what the hell this code does, or wants the other - fraction of a dB precision */ - -/* side effect: changes *lsp to cosines of lsp */ void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m, - float amp,float ampoffset){ + float amp,float ampoffset){ int i; float wdel=M_PI/ln; for(i=0;i= i; j--) { - g[j-2] -= g[j]; - g[j] += g[j]; - } + for(j=ord; j >= i; j--) { + g[j-2] -= g[j]; + g[j] += g[j]; + } } } @@ -135523,13 +124293,6 @@ static int comp(const void *a,const void *b){ return (*(float *)a<*(float *)b)-(*(float *)a>*(float *)b); } -/* Newton-Raphson-Maehly actually functioned as a decent root finder, - but there are root sets for which it gets into limit cycles - (exacerbated by zero suppression) and fails. We can't afford to - fail, even if the failure is 1 in 100,000,000, so we now use - Laguerre and later polish with Newton-Raphson (which can then - afford to fail) */ - #define EPSILON 10e-7 static int Laguerre_With_Deflation(float *a,int ord,float *r){ int i,m; @@ -135538,54 +124301,48 @@ static int Laguerre_With_Deflation(float *a,int ord,float *r){ for(i=0;i<=ord;i++)defl[i]=a[i]; for(m=ord;m>0;m--){ - double newx=0.f,delta; + double newx=0.f,delta; - /* iterate a root */ - while(1){ - double p=defl[m],pp=0.f,ppp=0.f,denom; + while(1){ + double p=defl[m],pp=0.f,ppp=0.f,denom; - /* eval the polynomial and its first two derivatives */ - for(i=m;i>0;i--){ + for(i=m;i>0;i--){ ppp = newx*ppp + pp; pp = newx*pp + p; p = newx*p + defl[i-1]; - } + } - /* Laguerre's method */ - denom=(m-1) * ((m-1)*pp*pp - m*p*ppp); - if(denom<0) + denom=(m-1) * ((m-1)*pp*pp - m*p*ppp); + if(denom<0) return(-1); /* complex root! The LPC generator handed us a bad filter */ - if(pp>0){ + if(pp>0){ denom = pp + sqrt(denom); if(denom-(EPSILON))denom=-(EPSILON); - } + } - delta = m*p/denom; - newx -= delta; + delta = m*p/denom; + newx -= delta; - if(delta<0.f)delta*=-1; + if(delta<0.f)delta*=-1; - if(fabs(delta/newx)<10e-12)break; - lastdelta=delta; - } + if(fabs(delta/newx)<10e-12)break; + lastdelta=delta; + } - r[m-1]=newx; + r[m-1]=newx; - /* forward deflation */ - - for(i=m;i>0;i--) - defl[i-1]+=newx*defl[i]; - defl++; + for(i=m;i>0;i--) + defl[i-1]+=newx*defl[i]; + defl++; } return(0); } -/* for spit-and-polish only */ static int Newton_Raphson(float *a,int ord,float *r){ int i, k, count=0; double error=1.f; @@ -135594,36 +124351,32 @@ static int Newton_Raphson(float *a,int ord,float *r){ for(i=0; i1e-20){ - error=0; + error=0; - for(i=0; i= 0; k--) { + for(i=0; i= 0; k--) { pp= pp* rooti + p; p = p * rooti + a[k]; - } + } - delta = p/pp; - root[i] -= delta; - error+= delta*delta; - } + delta = p/pp; + root[i] -= delta; + error+= delta*delta; + } - if(count>40)return(-1); + if(count>40)return(-1); - count++; + count++; } - /* Replaced the original bubble sort with a real sort. With your - help, we can eliminate the bubble sort in our lifetime. --Monty */ - for(i=0; i>1; int g1_order,g2_order; @@ -135633,35 +124386,27 @@ int vorbis_lpc_to_lsp(float *lpc,float *lsp,int m){ float *g2r=(float*)alloca(sizeof(*g2r)*(order2+1)); int i; - /* even and odd are slightly different base cases */ g1_order=(m+1)>>1; g2_order=(m) >>1; - /* Compute the lengths of the x polynomials. */ - /* Compute the first half of K & R F1 & F2 polynomials. */ - /* Compute half of the symmetric and antisymmetric polynomials. */ - /* Remove the roots at +1 and -1. */ - g1[g1_order] = 1.f; for(i=1;i<=g1_order;i++) g1[g1_order-i] = lpc[i-1]+lpc[m-i]; g2[g2_order] = 1.f; for(i=1;i<=g2_order;i++) g2[g2_order-i] = lpc[i-1]-lpc[m-i]; if(g1_order>g2_order){ - for(i=2; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+2]; + for(i=2; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+2]; }else{ - for(i=1; i<=g1_order;i++) g1[g1_order-i] -= g1[g1_order-i+1]; - for(i=1; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+1]; + for(i=1; i<=g1_order;i++) g1[g1_order-i] -= g1[g1_order-i+1]; + for(i=1; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+1]; } - /* Convert into polynomials in cos(alpha) */ cheby(g1,g1_order); cheby(g2,g2_order); - /* Find the roots of the 2 even polynomials.*/ if(Laguerre_With_Deflation(g1,g1_order,g1r) || - Laguerre_With_Deflation(g2,g2_order,g2r)) - return(-1); + Laguerre_With_Deflation(g2,g2_order,g2r)) + return(-1); Newton_Raphson(g1,g1_order,g1r); /* if it fails, it leaves g1r alone */ Newton_Raphson(g2,g2_order,g2r); /* if it fails, it leaves g2r alone */ @@ -135670,10 +124415,10 @@ int vorbis_lpc_to_lsp(float *lpc,float *lsp,int m){ qsort(g2r,g2_order,sizeof(*g2r),comp); for(i=0;i #include -/* simplistic, wasteful way of doing this (unique lookup for each - mode/submapping); there should be a central repository for - identical lookups. That will require minor work, so I'm putting it - off as low priority. - - Why a lookup for each backend in a given mode? Because the - blocksize is set by the mode, and low backend lookups may require - parameters from other areas of the mode/mapping */ - static void mapping0_free_info(vorbis_info_mapping *i){ vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)i; if(info){ - memset(info,0,sizeof(*info)); - _ogg_free(info); + memset(info,0,sizeof(*info)); + _ogg_free(info); } } @@ -135719,8 +124455,8 @@ static int ilog3(unsigned int v){ int ret=0; if(v)--v; while(v){ - ret++; - v>>=1; + ret++; + v>>=1; } return(ret); } @@ -135730,86 +124466,77 @@ static void mapping0_pack(vorbis_info *vi,vorbis_info_mapping *vm, int i; vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm; - /* another 'we meant to do it this way' hack... up to beta 4, we - packed 4 binary zeros here to signify one submapping in use. We - now redefine that to mean four bitflags that indicate use of - deeper features; bit0:submappings, bit1:coupling, - bit2,3:reserved. This is backward compatable with all actual uses - of the beta code. */ - if(info->submaps>1){ - oggpack_write(opb,1,1); - oggpack_write(opb,info->submaps-1,4); + oggpack_write(opb,1,1); + oggpack_write(opb,info->submaps-1,4); }else - oggpack_write(opb,0,1); + oggpack_write(opb,0,1); if(info->coupling_steps>0){ - oggpack_write(opb,1,1); - oggpack_write(opb,info->coupling_steps-1,8); + oggpack_write(opb,1,1); + oggpack_write(opb,info->coupling_steps-1,8); - for(i=0;icoupling_steps;i++){ - oggpack_write(opb,info->coupling_mag[i],ilog3(vi->channels)); - oggpack_write(opb,info->coupling_ang[i],ilog3(vi->channels)); - } + for(i=0;icoupling_steps;i++){ + oggpack_write(opb,info->coupling_mag[i],ilog3(vi->channels)); + oggpack_write(opb,info->coupling_ang[i],ilog3(vi->channels)); + } }else - oggpack_write(opb,0,1); + oggpack_write(opb,0,1); oggpack_write(opb,0,2); /* 2,3:reserved */ - /* we don't write the channel submappings if we only have one... */ if(info->submaps>1){ - for(i=0;ichannels;i++) - oggpack_write(opb,info->chmuxlist[i],4); + for(i=0;ichannels;i++) + oggpack_write(opb,info->chmuxlist[i],4); } for(i=0;isubmaps;i++){ - oggpack_write(opb,0,8); /* time submap unused */ - oggpack_write(opb,info->floorsubmap[i],8); - oggpack_write(opb,info->residuesubmap[i],8); + oggpack_write(opb,0,8); /* time submap unused */ + oggpack_write(opb,info->floorsubmap[i],8); + oggpack_write(opb,info->residuesubmap[i],8); } } -/* also responsible for range checking */ static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){ int i; vorbis_info_mapping0 *info=(vorbis_info_mapping0*)_ogg_calloc(1,sizeof(*info)); - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; memset(info,0,sizeof(*info)); if(oggpack_read(opb,1)) - info->submaps=oggpack_read(opb,4)+1; + info->submaps=oggpack_read(opb,4)+1; else - info->submaps=1; + info->submaps=1; if(oggpack_read(opb,1)){ - info->coupling_steps=oggpack_read(opb,8)+1; + info->coupling_steps=oggpack_read(opb,8)+1; - for(i=0;icoupling_steps;i++){ - int testM=info->coupling_mag[i]=oggpack_read(opb,ilog3(vi->channels)); - int testA=info->coupling_ang[i]=oggpack_read(opb,ilog3(vi->channels)); + for(i=0;icoupling_steps;i++){ + int testM=info->coupling_mag[i]=oggpack_read(opb,ilog3(vi->channels)); + int testA=info->coupling_ang[i]=oggpack_read(opb,ilog3(vi->channels)); - if(testM<0 || + if(testM<0 || testA<0 || testM==testA || testM>=vi->channels || testA>=vi->channels) goto err_out; - } + } } if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */ if(info->submaps>1){ - for(i=0;ichannels;i++){ - info->chmuxlist[i]=oggpack_read(opb,4); - if(info->chmuxlist[i]>=info->submaps)goto err_out; - } + for(i=0;ichannels;i++){ + info->chmuxlist[i]=oggpack_read(opb,4); + if(info->chmuxlist[i]>=info->submaps)goto err_out; + } } for(i=0;isubmaps;i++){ - oggpack_read(opb,8); /* time submap unused */ - info->floorsubmap[i]=oggpack_read(opb,8); - if(info->floorsubmap[i]>=ci->floors)goto err_out; - info->residuesubmap[i]=oggpack_read(opb,8); - if(info->residuesubmap[i]>=ci->residues)goto err_out; + oggpack_read(opb,8); /* time submap unused */ + info->floorsubmap[i]=oggpack_read(opb,8); + if(info->floorsubmap[i]>=ci->floors)goto err_out; + info->residuesubmap[i]=oggpack_read(opb,8); + if(info->residuesubmap[i]>=ci->residues)goto err_out; } return info; @@ -135892,8 +124619,8 @@ static float FLOOR1_fromdB_LOOKUP[256]={ #endif extern int *floor1_fit(vorbis_block *vb,void *look, - const float *logmdct, /* in */ - const float *logmask); + const float *logmdct, /* in */ + const float *logmask); extern int *floor1_interpolate_fit(vorbis_block *vb,void *look, int *A,int *B, int del); @@ -135902,17 +124629,17 @@ extern int floor1_encode(oggpack_buffer *opb,vorbis_block *vb, int *post,int *ilogmask); static int mapping0_forward(vorbis_block *vb){ - vorbis_dsp_state *vd=vb->vd; - vorbis_info *vi=vd->vi; - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; - private_state *b=(private_state*)vb->vd->backend_state; + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + private_state *b=(private_state*)vb->vd->backend_state; vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; - int n=vb->pcmend; + int n=vb->pcmend; int i,j,k; - int *nonzero = (int*) alloca(sizeof(*nonzero)*vi->channels); - float **gmdct = (float**) _vorbis_block_alloc(vb,vi->channels*sizeof(*gmdct)); - int **ilogmaskch= (int**) _vorbis_block_alloc(vb,vi->channels*sizeof(*ilogmaskch)); + int *nonzero = (int*) alloca(sizeof(*nonzero)*vi->channels); + float **gmdct = (float**) _vorbis_block_alloc(vb,vi->channels*sizeof(*gmdct)); + int **ilogmaskch= (int**) _vorbis_block_alloc(vb,vi->channels*sizeof(*ilogmaskch)); int ***floor_posts = (int***) _vorbis_block_alloc(vb,vi->channels*sizeof(*floor_posts)); float global_ampmax=vbi->ampmax; @@ -135922,204 +124649,182 @@ static int mapping0_forward(vorbis_block *vb){ int modenumber=vb->W; vorbis_info_mapping0 *info=(vorbis_info_mapping0*)ci->map_param[modenumber]; vorbis_look_psy *psy_look= - b->psy+blocktype+(vb->W?2:0); + b->psy+blocktype+(vb->W?2:0); vb->mode=modenumber; for(i=0;ichannels;i++){ - float scale=4.f/n; - float scale_dB; + float scale=4.f/n; + float scale_dB; - float *pcm =vb->pcm[i]; - float *logfft =pcm; + float *pcm =vb->pcm[i]; + float *logfft =pcm; - gmdct[i]=(float*)_vorbis_block_alloc(vb,n/2*sizeof(**gmdct)); + gmdct[i]=(float*)_vorbis_block_alloc(vb,n/2*sizeof(**gmdct)); - scale_dB=todB(&scale) + .345; /* + .345 is a hack; the original - todB estimation used on IEEE 754 - compliant machines had a bug that - returned dB values about a third - of a decibel too high. The bug - was harmless because tunings - implicitly took that into - account. However, fixing the bug - in the estimator requires - changing all the tunings as well. - For now, it's easier to sync - things back up here, and - recalibrate the tunings in the - next major model upgrade. */ + scale_dB=todB(&scale) + .345; /* + .345 is a hack; the original + todB estimation used on IEEE 754 + compliant machines had a bug that + returned dB values about a third + of a decibel too high. The bug + was harmless because tunings + implicitly took that into + account. However, fixing the bug + in the estimator requires + changing all the tunings as well. + For now, it's easier to sync + things back up here, and + recalibrate the tunings in the + next major model upgrade. */ #if 0 - if(vi->channels==2) - if(i==0) + if(vi->channels==2) + if(i==0) _analysis_output("pcmL",seq,pcm,n,0,0,total-n/2); - else + else _analysis_output("pcmR",seq,pcm,n,0,0,total-n/2); #endif - /* window the PCM data */ - _vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW); + _vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW); #if 0 - if(vi->channels==2) - if(i==0) + if(vi->channels==2) + if(i==0) _analysis_output("windowedL",seq,pcm,n,0,0,total-n/2); - else + else _analysis_output("windowedR",seq,pcm,n,0,0,total-n/2); #endif - /* transform the PCM data */ - /* only MDCT right now.... */ - mdct_forward((mdct_lookup*) b->transform[vb->W][0],pcm,gmdct[i]); + mdct_forward((mdct_lookup*) b->transform[vb->W][0],pcm,gmdct[i]); - /* FFT yields more accurate tonal estimation (not phase sensitive) */ - drft_forward(&b->fft_look[vb->W],pcm); - logfft[0]=scale_dB+todB(pcm) + .345; /* + .345 is a hack; the - original todB estimation used on - IEEE 754 compliant machines had a - bug that returned dB values about - a third of a decibel too high. - The bug was harmless because - tunings implicitly took that into - account. However, fixing the bug - in the estimator requires - changing all the tunings as well. - For now, it's easier to sync - things back up here, and - recalibrate the tunings in the - next major model upgrade. */ - local_ampmax[i]=logfft[0]; - for(j=1;j>1]=scale_dB+.5f*todB(&temp) + .345; /* + - .345 is a hack; the original todB - estimation used on IEEE 754 - compliant machines had a bug that - returned dB values about a third - of a decibel too high. The bug - was harmless because tunings - implicitly took that into - account. However, fixing the bug - in the estimator requires - changing all the tunings as well. - For now, it's easier to sync - things back up here, and - recalibrate the tunings in the - next major model upgrade. */ - if(temp>local_ampmax[i])local_ampmax[i]=temp; - } + drft_forward(&b->fft_look[vb->W],pcm); + logfft[0]=scale_dB+todB(pcm) + .345; /* + .345 is a hack; the + original todB estimation used on + IEEE 754 compliant machines had a + bug that returned dB values about + a third of a decibel too high. + The bug was harmless because + tunings implicitly took that into + account. However, fixing the bug + in the estimator requires + changing all the tunings as well. + For now, it's easier to sync + things back up here, and + recalibrate the tunings in the + next major model upgrade. */ + local_ampmax[i]=logfft[0]; + for(j=1;j>1]=scale_dB+.5f*todB(&temp) + .345; /* + + .345 is a hack; the original todB + estimation used on IEEE 754 + compliant machines had a bug that + returned dB values about a third + of a decibel too high. The bug + was harmless because tunings + implicitly took that into + account. However, fixing the bug + in the estimator requires + changing all the tunings as well. + For now, it's easier to sync + things back up here, and + recalibrate the tunings in the + next major model upgrade. */ + if(temp>local_ampmax[i])local_ampmax[i]=temp; + } - if(local_ampmax[i]>0.f)local_ampmax[i]=0.f; - if(local_ampmax[i]>global_ampmax)global_ampmax=local_ampmax[i]; + if(local_ampmax[i]>0.f)local_ampmax[i]=0.f; + if(local_ampmax[i]>global_ampmax)global_ampmax=local_ampmax[i]; #if 0 - if(vi->channels==2){ - if(i==0){ + if(vi->channels==2){ + if(i==0){ _analysis_output("fftL",seq,logfft,n/2,1,0,0); - }else{ + }else{ _analysis_output("fftR",seq,logfft,n/2,1,0,0); - } - } + } + } #endif } { - float *noise = (float*) _vorbis_block_alloc(vb,n/2*sizeof(*noise)); - float *tone = (float*) _vorbis_block_alloc(vb,n/2*sizeof(*tone)); + float *noise = (float*) _vorbis_block_alloc(vb,n/2*sizeof(*noise)); + float *tone = (float*) _vorbis_block_alloc(vb,n/2*sizeof(*tone)); - for(i=0;ichannels;i++){ - /* the encoder setup assumes that all the modes used by any - specific bitrate tweaking use the same floor */ + for(i=0;ichannels;i++){ - int submap=info->chmuxlist[i]; + int submap=info->chmuxlist[i]; - /* the following makes things clearer to *me* anyway */ - float *mdct =gmdct[i]; - float *logfft =vb->pcm[i]; + float *mdct =gmdct[i]; + float *logfft =vb->pcm[i]; - float *logmdct =logfft+n/2; - float *logmask =logfft; + float *logmdct =logfft+n/2; + float *logmask =logfft; - vb->mode=modenumber; + vb->mode=modenumber; - floor_posts[i]=(int**) _vorbis_block_alloc(vb,PACKETBLOBS*sizeof(**floor_posts)); - memset(floor_posts[i],0,sizeof(**floor_posts)*PACKETBLOBS); + floor_posts[i]=(int**) _vorbis_block_alloc(vb,PACKETBLOBS*sizeof(**floor_posts)); + memset(floor_posts[i],0,sizeof(**floor_posts)*PACKETBLOBS); - for(j=0;jchannels==2){ + if(vi->channels==2){ if(i==0) _analysis_output("mdctL",seq,logmdct,n/2,1,0,0); else _analysis_output("mdctR",seq,logmdct,n/2,1,0,0); - }else{ + }else{ _analysis_output("mdct",seq,logmdct,n/2,1,0,0); - } + } #endif - /* first step; noise masking. Not only does 'noise masking' - give us curves from which we can decide how much resolution - to give noise parts of the spectrum, it also implicitly hands - us a tonality estimate (the larger the value in the - 'noise_depth' vector, the more tonal that area is) */ - - _vp_noisemask(psy_look, - logmdct, - noise); /* noise does not have by-frequency offset - bias applied yet */ + _vp_noisemask(psy_look, + logmdct, + noise); /* noise does not have by-frequency offset + bias applied yet */ #if 0 - if(vi->channels==2){ + if(vi->channels==2){ if(i==0) _analysis_output("noiseL",seq,noise,n/2,1,0,0); else _analysis_output("noiseR",seq,noise,n/2,1,0,0); - } + } #endif - /* second step: 'all the other crap'; all the stuff that isn't - computed/fit for bitrate management goes in the second psy - vector. This includes tone masking, peak limiting and ATH */ - - _vp_tonemask(psy_look, + _vp_tonemask(psy_look, logfft, tone, global_ampmax, local_ampmax[i]); #if 0 - if(vi->channels==2){ + if(vi->channels==2){ if(i==0) _analysis_output("toneL",seq,tone,n/2,1,0,0); else _analysis_output("toneR",seq,tone,n/2,1,0,0); - } + } #endif - /* third step; we offset the noise vectors, overlay tone - masking. We then do a floor1-specific line fit. If we're - performing bitrate management, the line fit is performed - multiple times for up/down tweakage on demand. */ - #if 0 - { - float aotuv[psy_look->n]; + { + float aotuv[psy_look->n]; #endif _vp_offset_and_mix(psy_look, @@ -136137,32 +124842,26 @@ static int mapping0_forward(vorbis_block *vb){ else _analysis_output("aotuvM1_R",seq,aotuv,psy_look->n,1,1,0); } - } + } #endif #if 0 - if(vi->channels==2){ + if(vi->channels==2){ if(i==0) _analysis_output("mask1L",seq,logmask,n/2,1,0,0); else _analysis_output("mask1R",seq,logmask,n/2,1,0,0); - } + } #endif - /* this algorithm is hardwired to floor 1 for now; abort out if - we're *not* floor1. This won't happen unless someone has - broken the encode setup lib. Guard it anyway. */ - if(ci->floor_type[info->floorsubmap[submap]]!=1)return(-1); + if(ci->floor_type[info->floorsubmap[submap]]!=1)return(-1); - floor_posts[i][PACKETBLOBS/2]= + floor_posts[i][PACKETBLOBS/2]= floor1_fit(vb,b->flr[info->floorsubmap[submap]], logmdct, logmask); - /* are we managing bitrate? If so, perform two more fits for - later rate tweaking (fits represent hi/lo) */ - if(vorbis_bitrate_managed(vb) && floor_posts[i][PACKETBLOBS/2]){ - /* higher rate by way of lower noise curve */ + if(vorbis_bitrate_managed(vb) && floor_posts[i][PACKETBLOBS/2]){ _vp_offset_and_mix(psy_look, noise, @@ -136183,10 +124882,9 @@ static int mapping0_forward(vorbis_block *vb){ floor_posts[i][PACKETBLOBS-1]= floor1_fit(vb,b->flr[info->floorsubmap[submap]], - logmdct, - logmask); + logmdct, + logmask); - /* lower rate by way of higher noise curve */ _vp_offset_and_mix(psy_look, noise, tone, @@ -136205,98 +124903,77 @@ static int mapping0_forward(vorbis_block *vb){ floor_posts[i][0]= floor1_fit(vb,b->flr[info->floorsubmap[submap]], - logmdct, - logmask); + logmdct, + logmask); - /* we also interpolate a range of intermediate curves for - intermediate rates */ for(k=1;kflr[info->floorsubmap[submap]], + floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]], floor_posts[i][0], floor_posts[i][PACKETBLOBS/2], k*65536/(PACKETBLOBS/2)); for(k=PACKETBLOBS/2+1;kflr[info->floorsubmap[submap]], + floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]], floor_posts[i][PACKETBLOBS/2], floor_posts[i][PACKETBLOBS-1], (k-PACKETBLOBS/2)*65536/(PACKETBLOBS/2)); - } - } + } + } } vbi->ampmax=global_ampmax; - /* - the next phases are performed once for vbr-only and PACKETBLOB - times for bitrate managed modes. - - 1) encode actual mode being used - 2) encode the floor for each channel, compute coded mask curve/res - 3) normalize and couple. - 4) encode residue - 5) save packet bytes to the packetblob vector - - */ - - /* iterate over the many masking curve fits we've created */ - { - float **res_bundle=(float**) alloca(sizeof(*res_bundle)*vi->channels); - float **couple_bundle=(float**) alloca(sizeof(*couple_bundle)*vi->channels); - int *zerobundle=(int*) alloca(sizeof(*zerobundle)*vi->channels); - int **sortindex=(int**) alloca(sizeof(*sortindex)*vi->channels); - float **mag_memo; - int **mag_sort; + float **res_bundle=(float**) alloca(sizeof(*res_bundle)*vi->channels); + float **couple_bundle=(float**) alloca(sizeof(*couple_bundle)*vi->channels); + int *zerobundle=(int*) alloca(sizeof(*zerobundle)*vi->channels); + int **sortindex=(int**) alloca(sizeof(*sortindex)*vi->channels); + float **mag_memo; + int **mag_sort; - if(info->coupling_steps){ - mag_memo=_vp_quantize_couple_memo(vb, + if(info->coupling_steps){ + mag_memo=_vp_quantize_couple_memo(vb, &ci->psy_g_param, psy_look, info, gmdct); - mag_sort=_vp_quantize_couple_sort(vb, + mag_sort=_vp_quantize_couple_sort(vb, psy_look, info, mag_memo); - hf_reduction(&ci->psy_g_param, + hf_reduction(&ci->psy_g_param, psy_look, info, mag_memo); - } + } - memset(sortindex,0,sizeof(*sortindex)*vi->channels); - if(psy_look->vi->normal_channel_p){ - for(i=0;ichannels;i++){ - float *mdct =gmdct[i]; + memset(sortindex,0,sizeof(*sortindex)*vi->channels); + if(psy_look->vi->normal_channel_p){ + for(i=0;ichannels;i++){ + float *mdct =gmdct[i]; sortindex[i]=(int*) alloca(sizeof(**sortindex)*n/2); _vp_noise_normalize_sort(psy_look,mdct,sortindex[i]); - } - } + } + } - for(k=(vorbis_bitrate_managed(vb)?0:PACKETBLOBS/2); + for(k=(vorbis_bitrate_managed(vb)?0:PACKETBLOBS/2); k<=(vorbis_bitrate_managed(vb)?PACKETBLOBS-1:PACKETBLOBS/2); k++){ - oggpack_buffer *opb=vbi->packetblob[k]; + oggpack_buffer *opb=vbi->packetblob[k]; - /* start out our new packet blob with packet type and mode */ - /* Encode the packet type */ - oggpack_write(opb,0,1); - /* Encode the modenumber */ - /* Encode frame mode, pre,post windowsize, then dispatch */ - oggpack_write(opb,modenumber,b->modebits); - if(vb->W){ + oggpack_write(opb,0,1); + oggpack_write(opb,modenumber,b->modebits); + if(vb->W){ oggpack_write(opb,vb->lW,1); oggpack_write(opb,vb->nW,1); - } + } - /* encode floor, compute masking curve, sep out residue */ - for(i=0;ichannels;i++){ + for(i=0;ichannels;i++){ int submap=info->chmuxlist[i]; - float *mdct =gmdct[i]; - float *res =vb->pcm[i]; + float *mdct =gmdct[i]; + float *res =vb->pcm[i]; int *ilogmask=ilogmaskch[i]= (int*) _vorbis_block_alloc(vb,n/2*sizeof(**gmdct)); @@ -136309,7 +124986,7 @@ static int mapping0_forward(vorbis_block *vb){ sprintf(buf,"maskI%c%d",i?'R':'L',k); float work[n/2]; for(j=0;jcoupling_steps){ + if(info->coupling_steps){ _vp_couple(k, &ci->psy_g_param, psy_look, @@ -136351,20 +125022,19 @@ static int mapping0_forward(vorbis_block *vb){ ilogmaskch, nonzero, ci->psy_g_param.sliding_lowpass[vb->W][k]); - } + } - /* classify and encode by submap */ - for(i=0;isubmaps;i++){ + for(i=0;isubmaps;i++){ int ch_in_bundle=0; long **classifications; int resnum=info->residuesubmap[i]; for(j=0;jchannels;j++){ if(info->chmuxlist[j]==i){ - zerobundle[ch_in_bundle]=0; - if(nonzero[j])zerobundle[ch_in_bundle]=1; - res_bundle[ch_in_bundle]=vb->pcm[j]; - couple_bundle[ch_in_bundle++]=vb->pcm[j]+n/2; + zerobundle[ch_in_bundle]=0; + if(nonzero[j])zerobundle[ch_in_bundle]=1; + res_bundle[ch_in_bundle]=vb->pcm[j]; + couple_bundle[ch_in_bundle++]=vb->pcm[j]+n/2; } } @@ -136374,10 +125044,9 @@ static int mapping0_forward(vorbis_block *vb){ _residue_P[ci->residue_type[resnum]]-> forward(opb,vb,b->residue[resnum], couple_bundle,NULL,zerobundle,ch_in_bundle,classifications); - } + } - /* ok, done encoding. Next protopacket. */ - } + } } @@ -136389,70 +125058,66 @@ static int mapping0_forward(vorbis_block *vb){ } static int mapping0_inverse(vorbis_block *vb,vorbis_info_mapping *l){ - vorbis_dsp_state *vd=vb->vd; - vorbis_info *vi=vd->vi; - codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; - private_state *b=(private_state*)vd->backend_state; + vorbis_dsp_state *vd=vb->vd; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; + private_state *b=(private_state*)vd->backend_state; vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)l; - int i,j; - long n=vb->pcmend=ci->blocksizes[vb->W]; + int i,j; + long n=vb->pcmend=ci->blocksizes[vb->W]; float **pcmbundle=(float**) alloca(sizeof(*pcmbundle)*vi->channels); - int *zerobundle=(int*) alloca(sizeof(*zerobundle)*vi->channels); + int *zerobundle=(int*) alloca(sizeof(*zerobundle)*vi->channels); int *nonzero =(int*) alloca(sizeof(*nonzero)*vi->channels); void **floormemo=(void**) alloca(sizeof(*floormemo)*vi->channels); - /* recover the spectral envelope; store it in the PCM vector for now */ for(i=0;ichannels;i++){ - int submap=info->chmuxlist[i]; - floormemo[i]=_floor_P[ci->floor_type[info->floorsubmap[submap]]]-> - inverse1(vb,b->flr[info->floorsubmap[submap]]); - if(floormemo[i]) - nonzero[i]=1; - else - nonzero[i]=0; - memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2); + int submap=info->chmuxlist[i]; + floormemo[i]=_floor_P[ci->floor_type[info->floorsubmap[submap]]]-> + inverse1(vb,b->flr[info->floorsubmap[submap]]); + if(floormemo[i]) + nonzero[i]=1; + else + nonzero[i]=0; + memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2); } - /* channel coupling can 'dirty' the nonzero listing */ for(i=0;icoupling_steps;i++){ - if(nonzero[info->coupling_mag[i]] || - nonzero[info->coupling_ang[i]]){ - nonzero[info->coupling_mag[i]]=1; - nonzero[info->coupling_ang[i]]=1; - } + if(nonzero[info->coupling_mag[i]] || + nonzero[info->coupling_ang[i]]){ + nonzero[info->coupling_mag[i]]=1; + nonzero[info->coupling_ang[i]]=1; + } } - /* recover the residue into our working vectors */ for(i=0;isubmaps;i++){ - int ch_in_bundle=0; - for(j=0;jchannels;j++){ - if(info->chmuxlist[j]==i){ + int ch_in_bundle=0; + for(j=0;jchannels;j++){ + if(info->chmuxlist[j]==i){ if(nonzero[j]) zerobundle[ch_in_bundle]=1; else zerobundle[ch_in_bundle]=0; pcmbundle[ch_in_bundle++]=vb->pcm[j]; - } - } + } + } - _residue_P[ci->residue_type[info->residuesubmap[i]]]-> - inverse(vb,b->residue[info->residuesubmap[i]], - pcmbundle,zerobundle,ch_in_bundle); + _residue_P[ci->residue_type[info->residuesubmap[i]]]-> + inverse(vb,b->residue[info->residuesubmap[i]], + pcmbundle,zerobundle,ch_in_bundle); } - /* channel coupling */ for(i=info->coupling_steps-1;i>=0;i--){ - float *pcmM=vb->pcm[info->coupling_mag[i]]; - float *pcmA=vb->pcm[info->coupling_ang[i]]; + float *pcmM=vb->pcm[info->coupling_mag[i]]; + float *pcmA=vb->pcm[info->coupling_ang[i]]; - for(j=0;j0) + if(mag>0) if(ang>0){ pcmM[j]=mag; pcmA[j]=mag-ang; @@ -136460,7 +125125,7 @@ static int mapping0_inverse(vorbis_block *vb,vorbis_info_mapping *l){ pcmA[j]=mag; pcmM[j]=mag+ang; } - else + else if(ang>0){ pcmM[j]=mag; pcmA[j]=mag+ang; @@ -136468,30 +125133,25 @@ static int mapping0_inverse(vorbis_block *vb,vorbis_info_mapping *l){ pcmA[j]=mag; pcmM[j]=mag-ang; } - } + } } - /* compute and apply spectral envelope */ for(i=0;ichannels;i++){ - float *pcm=vb->pcm[i]; - int submap=info->chmuxlist[i]; - _floor_P[ci->floor_type[info->floorsubmap[submap]]]-> - inverse2(vb,b->flr[info->floorsubmap[submap]], - floormemo[i],pcm); + float *pcm=vb->pcm[i]; + int submap=info->chmuxlist[i]; + _floor_P[ci->floor_type[info->floorsubmap[submap]]]-> + inverse2(vb,b->flr[info->floorsubmap[submap]], + floormemo[i],pcm); } - /* transform the PCM data; takes PCM vector, vb; modifies PCM vector */ - /* only MDCT right now.... */ for(i=0;ichannels;i++){ - float *pcm=vb->pcm[i]; - mdct_backward((mdct_lookup*) b->transform[vb->W][0],pcm,pcm); + float *pcm=vb->pcm[i]; + mdct_backward((mdct_lookup*) b->transform[vb->W][0],pcm,pcm); } - /* all done! */ return(0); } -/* export hooks */ vorbis_func_mapping mapping0_exportbundle={ &mapping0_pack, &mapping0_unpack, @@ -136504,11 +125164,6 @@ vorbis_func_mapping mapping0_exportbundle={ /********* End of inlined file: mapping0.c *********/ /********* Start of inlined file: mdct.c *********/ -/* this can also be run as an integer transform by uncommenting a - define in mdct.h; the integerization is a first pass and although - it's likely stable for Vorbis, the dynamic range is constrained and - roundoff isn't done (so it's noisy). Consider it functional, but - only a starting point. There's no point on a machine with an FPU */ /********* Start of inlined file: juce_OggVorbisHeader.h *********/ // This file is included at the start of each Ogg-Vorbis .c file, just to do a few housekeeping @@ -136526,9 +125181,6 @@ vorbis_func_mapping mapping0_exportbundle={ #include #include -/* build lookups for trig functions; also pre-figure scaling and - some window function algebra. */ - void mdct_init(mdct_lookup *lookup,int n){ int *bitrev=(int*) _ogg_malloc(sizeof(*bitrev)*(n/4)); DATA_TYPE *T=(DATA_TYPE*) _ogg_malloc(sizeof(*T)*(n+n/4)); @@ -136540,37 +125192,32 @@ void mdct_init(mdct_lookup *lookup,int n){ lookup->trig=T; lookup->bitrev=bitrev; -/* trig lookups... */ - for(i=0;i>j;j++) + int mask=(1<<(log2n-1))-1,i,j; + int msb=1<<(log2n-2); + for(i=0;i>j;j++) if((msb>>j)&i)acc|=1<scale=FLOAT_CONV(4.f/n); } -/* 8 point butterfly (in place, 4 register) */ STIN void mdct_butterfly_8(DATA_TYPE *x){ REG_TYPE r0 = x[6] + x[2]; REG_TYPE r1 = x[6] - x[2]; @@ -136594,95 +125241,93 @@ STIN void mdct_butterfly_8(DATA_TYPE *x){ } -/* 16 point butterfly (in place, 4 register) */ STIN void mdct_butterfly_16(DATA_TYPE *x){ - REG_TYPE r0 = x[1] - x[9]; - REG_TYPE r1 = x[0] - x[8]; + REG_TYPE r0 = x[1] - x[9]; + REG_TYPE r1 = x[0] - x[8]; - x[8] += x[0]; - x[9] += x[1]; - x[0] = MULT_NORM((r0 + r1) * cPI2_8); - x[1] = MULT_NORM((r0 - r1) * cPI2_8); + x[8] += x[0]; + x[9] += x[1]; + x[0] = MULT_NORM((r0 + r1) * cPI2_8); + x[1] = MULT_NORM((r0 - r1) * cPI2_8); - r0 = x[3] - x[11]; - r1 = x[10] - x[2]; - x[10] += x[2]; - x[11] += x[3]; - x[2] = r0; - x[3] = r1; + r0 = x[3] - x[11]; + r1 = x[10] - x[2]; + x[10] += x[2]; + x[11] += x[3]; + x[2] = r0; + x[3] = r1; - r0 = x[12] - x[4]; - r1 = x[13] - x[5]; - x[12] += x[4]; - x[13] += x[5]; - x[4] = MULT_NORM((r0 - r1) * cPI2_8); - x[5] = MULT_NORM((r0 + r1) * cPI2_8); + r0 = x[12] - x[4]; + r1 = x[13] - x[5]; + x[12] += x[4]; + x[13] += x[5]; + x[4] = MULT_NORM((r0 - r1) * cPI2_8); + x[5] = MULT_NORM((r0 + r1) * cPI2_8); - r0 = x[14] - x[6]; - r1 = x[15] - x[7]; - x[14] += x[6]; - x[15] += x[7]; - x[6] = r0; - x[7] = r1; + r0 = x[14] - x[6]; + r1 = x[15] - x[7]; + x[14] += x[6]; + x[15] += x[7]; + x[6] = r0; + x[7] = r1; mdct_butterfly_8(x); mdct_butterfly_8(x+8); } -/* 32 point butterfly (in place, 4 register) */ STIN void mdct_butterfly_32(DATA_TYPE *x){ - REG_TYPE r0 = x[30] - x[14]; - REG_TYPE r1 = x[31] - x[15]; + REG_TYPE r0 = x[30] - x[14]; + REG_TYPE r1 = x[31] - x[15]; - x[30] += x[14]; - x[31] += x[15]; - x[14] = r0; - x[15] = r1; + x[30] += x[14]; + x[31] += x[15]; + x[14] = r0; + x[15] = r1; - r0 = x[28] - x[12]; - r1 = x[29] - x[13]; - x[28] += x[12]; - x[29] += x[13]; - x[12] = MULT_NORM( r0 * cPI1_8 - r1 * cPI3_8 ); + r0 = x[28] - x[12]; + r1 = x[29] - x[13]; + x[28] += x[12]; + x[29] += x[13]; + x[12] = MULT_NORM( r0 * cPI1_8 - r1 * cPI3_8 ); x[13] = MULT_NORM( r0 * cPI3_8 + r1 * cPI1_8 ); - r0 = x[26] - x[10]; - r1 = x[27] - x[11]; - x[26] += x[10]; - x[27] += x[11]; + r0 = x[26] - x[10]; + r1 = x[27] - x[11]; + x[26] += x[10]; + x[27] += x[11]; x[10] = MULT_NORM(( r0 - r1 ) * cPI2_8); x[11] = MULT_NORM(( r0 + r1 ) * cPI2_8); - r0 = x[24] - x[8]; - r1 = x[25] - x[9]; + r0 = x[24] - x[8]; + r1 = x[25] - x[9]; x[24] += x[8]; x[25] += x[9]; x[8] = MULT_NORM( r0 * cPI3_8 - r1 * cPI1_8 ); x[9] = MULT_NORM( r1 * cPI3_8 + r0 * cPI1_8 ); - r0 = x[22] - x[6]; - r1 = x[7] - x[23]; + r0 = x[22] - x[6]; + r1 = x[7] - x[23]; x[22] += x[6]; x[23] += x[7]; x[6] = r1; x[7] = r0; - r0 = x[4] - x[20]; - r1 = x[5] - x[21]; + r0 = x[4] - x[20]; + r1 = x[5] - x[21]; x[20] += x[4]; x[21] += x[5]; x[4] = MULT_NORM( r1 * cPI1_8 + r0 * cPI3_8 ); x[5] = MULT_NORM( r1 * cPI3_8 - r0 * cPI1_8 ); - r0 = x[2] - x[18]; - r1 = x[3] - x[19]; + r0 = x[2] - x[18]; + r1 = x[3] - x[19]; x[18] += x[2]; x[19] += x[3]; x[2] = MULT_NORM(( r1 + r0 ) * cPI2_8); x[3] = MULT_NORM(( r1 - r0 ) * cPI2_8); - r0 = x[0] - x[16]; - r1 = x[1] - x[17]; + r0 = x[0] - x[16]; + r1 = x[1] - x[17]; x[16] += x[0]; x[17] += x[1]; x[0] = MULT_NORM( r1 * cPI3_8 + r0 * cPI1_8 ); @@ -136693,183 +125338,181 @@ STIN void mdct_butterfly_32(DATA_TYPE *x){ } -/* N point first stage butterfly (in place, 2 register) */ STIN void mdct_butterfly_first(DATA_TYPE *T, DATA_TYPE *x, int points){ - DATA_TYPE *x1 = x + points - 8; - DATA_TYPE *x2 = x + (points>>1) - 8; + DATA_TYPE *x1 = x + points - 8; + DATA_TYPE *x2 = x + (points>>1) - 8; REG_TYPE r0; REG_TYPE r1; do{ - r0 = x1[6] - x2[6]; - r1 = x1[7] - x2[7]; - x1[6] += x2[6]; - x1[7] += x2[7]; - x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]); - x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]); + r0 = x1[6] - x2[6]; + r1 = x1[7] - x2[7]; + x1[6] += x2[6]; + x1[7] += x2[7]; + x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]); + x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]); - r0 = x1[4] - x2[4]; - r1 = x1[5] - x2[5]; - x1[4] += x2[4]; - x1[5] += x2[5]; - x2[4] = MULT_NORM(r1 * T[5] + r0 * T[4]); - x2[5] = MULT_NORM(r1 * T[4] - r0 * T[5]); + r0 = x1[4] - x2[4]; + r1 = x1[5] - x2[5]; + x1[4] += x2[4]; + x1[5] += x2[5]; + x2[4] = MULT_NORM(r1 * T[5] + r0 * T[4]); + x2[5] = MULT_NORM(r1 * T[4] - r0 * T[5]); - r0 = x1[2] - x2[2]; - r1 = x1[3] - x2[3]; - x1[2] += x2[2]; - x1[3] += x2[3]; - x2[2] = MULT_NORM(r1 * T[9] + r0 * T[8]); - x2[3] = MULT_NORM(r1 * T[8] - r0 * T[9]); + r0 = x1[2] - x2[2]; + r1 = x1[3] - x2[3]; + x1[2] += x2[2]; + x1[3] += x2[3]; + x2[2] = MULT_NORM(r1 * T[9] + r0 * T[8]); + x2[3] = MULT_NORM(r1 * T[8] - r0 * T[9]); - r0 = x1[0] - x2[0]; - r1 = x1[1] - x2[1]; - x1[0] += x2[0]; - x1[1] += x2[1]; - x2[0] = MULT_NORM(r1 * T[13] + r0 * T[12]); - x2[1] = MULT_NORM(r1 * T[12] - r0 * T[13]); + r0 = x1[0] - x2[0]; + r1 = x1[1] - x2[1]; + x1[0] += x2[0]; + x1[1] += x2[1]; + x2[0] = MULT_NORM(r1 * T[13] + r0 * T[12]); + x2[1] = MULT_NORM(r1 * T[12] - r0 * T[13]); - x1-=8; - x2-=8; - T+=16; + x1-=8; + x2-=8; + T+=16; }while(x2>=x); } -/* N/stage point generic N stage butterfly (in place, 2 register) */ STIN void mdct_butterfly_generic(DATA_TYPE *T, DATA_TYPE *x, int points, int trigint){ - DATA_TYPE *x1 = x + points - 8; - DATA_TYPE *x2 = x + (points>>1) - 8; + DATA_TYPE *x1 = x + points - 8; + DATA_TYPE *x2 = x + (points>>1) - 8; REG_TYPE r0; REG_TYPE r1; do{ - r0 = x1[6] - x2[6]; - r1 = x1[7] - x2[7]; - x1[6] += x2[6]; - x1[7] += x2[7]; - x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]); - x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]); + r0 = x1[6] - x2[6]; + r1 = x1[7] - x2[7]; + x1[6] += x2[6]; + x1[7] += x2[7]; + x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]); + x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]); - T+=trigint; + T+=trigint; - r0 = x1[4] - x2[4]; - r1 = x1[5] - x2[5]; - x1[4] += x2[4]; - x1[5] += x2[5]; - x2[4] = MULT_NORM(r1 * T[1] + r0 * T[0]); - x2[5] = MULT_NORM(r1 * T[0] - r0 * T[1]); + r0 = x1[4] - x2[4]; + r1 = x1[5] - x2[5]; + x1[4] += x2[4]; + x1[5] += x2[5]; + x2[4] = MULT_NORM(r1 * T[1] + r0 * T[0]); + x2[5] = MULT_NORM(r1 * T[0] - r0 * T[1]); - T+=trigint; + T+=trigint; - r0 = x1[2] - x2[2]; - r1 = x1[3] - x2[3]; - x1[2] += x2[2]; - x1[3] += x2[3]; - x2[2] = MULT_NORM(r1 * T[1] + r0 * T[0]); - x2[3] = MULT_NORM(r1 * T[0] - r0 * T[1]); + r0 = x1[2] - x2[2]; + r1 = x1[3] - x2[3]; + x1[2] += x2[2]; + x1[3] += x2[3]; + x2[2] = MULT_NORM(r1 * T[1] + r0 * T[0]); + x2[3] = MULT_NORM(r1 * T[0] - r0 * T[1]); - T+=trigint; + T+=trigint; - r0 = x1[0] - x2[0]; - r1 = x1[1] - x2[1]; - x1[0] += x2[0]; - x1[1] += x2[1]; - x2[0] = MULT_NORM(r1 * T[1] + r0 * T[0]); - x2[1] = MULT_NORM(r1 * T[0] - r0 * T[1]); + r0 = x1[0] - x2[0]; + r1 = x1[1] - x2[1]; + x1[0] += x2[0]; + x1[1] += x2[1]; + x2[0] = MULT_NORM(r1 * T[1] + r0 * T[0]); + x2[1] = MULT_NORM(r1 * T[0] - r0 * T[1]); - T+=trigint; - x1-=8; - x2-=8; + T+=trigint; + x1-=8; + x2-=8; }while(x2>=x); } STIN void mdct_butterflies(mdct_lookup *init, - DATA_TYPE *x, - int points){ + DATA_TYPE *x, + int points){ DATA_TYPE *T=init->trig; int stages=init->log2n-5; int i,j; if(--stages>0){ - mdct_butterfly_first(T,x,points); + mdct_butterfly_first(T,x,points); } for(i=1;--stages>0;i++){ - for(j=0;j<(1<>i)*j,points>>i,4<>i)*j,points>>i,4<trig)_ogg_free(l->trig); - if(l->bitrev)_ogg_free(l->bitrev); - memset(l,0,sizeof(*l)); + if(l->trig)_ogg_free(l->trig); + if(l->bitrev)_ogg_free(l->bitrev); + memset(l,0,sizeof(*l)); } } STIN void mdct_bitreverse(mdct_lookup *init, - DATA_TYPE *x){ - int n = init->n; - int *bit = init->bitrev; - DATA_TYPE *w0 = x; - DATA_TYPE *w1 = x = w0+(n>>1); - DATA_TYPE *T = init->trig+n; + DATA_TYPE *x){ + int n = init->n; + int *bit = init->bitrev; + DATA_TYPE *w0 = x; + DATA_TYPE *w1 = x = w0+(n>>1); + DATA_TYPE *T = init->trig+n; do{ - DATA_TYPE *x0 = x+bit[0]; - DATA_TYPE *x1 = x+bit[1]; + DATA_TYPE *x0 = x+bit[0]; + DATA_TYPE *x1 = x+bit[1]; - REG_TYPE r0 = x0[1] - x1[1]; - REG_TYPE r1 = x0[0] + x1[0]; - REG_TYPE r2 = MULT_NORM(r1 * T[0] + r0 * T[1]); - REG_TYPE r3 = MULT_NORM(r1 * T[1] - r0 * T[0]); + REG_TYPE r0 = x0[1] - x1[1]; + REG_TYPE r1 = x0[0] + x1[0]; + REG_TYPE r2 = MULT_NORM(r1 * T[0] + r0 * T[1]); + REG_TYPE r3 = MULT_NORM(r1 * T[1] - r0 * T[0]); - w1 -= 4; + w1 -= 4; - r0 = HALVE(x0[1] + x1[1]); - r1 = HALVE(x0[0] - x1[0]); + r0 = HALVE(x0[1] + x1[1]); + r1 = HALVE(x0[0] - x1[0]); - w0[0] = r0 + r2; - w1[2] = r0 - r2; - w0[1] = r1 + r3; - w1[3] = r3 - r1; + w0[0] = r0 + r2; + w1[2] = r0 - r2; + w0[1] = r1 + r3; + w1[3] = r3 - r1; - x0 = x+bit[2]; - x1 = x+bit[3]; + x0 = x+bit[2]; + x1 = x+bit[3]; - r0 = x0[1] - x1[1]; - r1 = x0[0] + x1[0]; - r2 = MULT_NORM(r1 * T[2] + r0 * T[3]); - r3 = MULT_NORM(r1 * T[3] - r0 * T[2]); + r0 = x0[1] - x1[1]; + r1 = x0[0] + x1[0]; + r2 = MULT_NORM(r1 * T[2] + r0 * T[3]); + r3 = MULT_NORM(r1 * T[3] - r0 * T[2]); - r0 = HALVE(x0[1] + x1[1]); - r1 = HALVE(x0[0] - x1[0]); + r0 = HALVE(x0[1] + x1[1]); + r1 = HALVE(x0[0] - x1[0]); - w0[2] = r0 + r2; - w1[0] = r0 - r2; - w0[3] = r1 + r3; - w1[1] = r3 - r1; + w0[2] = r0 + r2; + w1[0] = r0 - r2; + w0[3] = r1 + r3; + w1[1] = r3 - r1; - T += 4; - bit += 4; - w0 += 4; + T += 4; + bit += 4; + w0 += 4; }while(w0>1; int n4=n>>2; - /* rotate */ - DATA_TYPE *iX = in+n2-7; DATA_TYPE *oX = out+n2+n4; DATA_TYPE *T = init->trig+n4; do{ - oX -= 4; - oX[0] = MULT_NORM(-iX[2] * T[3] - iX[0] * T[2]); - oX[1] = MULT_NORM (iX[0] * T[3] - iX[2] * T[2]); - oX[2] = MULT_NORM(-iX[6] * T[1] - iX[4] * T[0]); - oX[3] = MULT_NORM (iX[4] * T[1] - iX[6] * T[0]); - iX -= 8; - T += 4; + oX -= 4; + oX[0] = MULT_NORM(-iX[2] * T[3] - iX[0] * T[2]); + oX[1] = MULT_NORM (iX[0] * T[3] - iX[2] * T[2]); + oX[2] = MULT_NORM(-iX[6] * T[1] - iX[4] * T[0]); + oX[3] = MULT_NORM (iX[4] * T[1] - iX[6] * T[0]); + iX -= 8; + T += 4; }while(iX>=in); - iX = in+n2-8; - oX = out+n2+n4; - T = init->trig+n4; + iX = in+n2-8; + oX = out+n2+n4; + T = init->trig+n4; do{ - T -= 4; - oX[0] = MULT_NORM (iX[4] * T[3] + iX[6] * T[2]); - oX[1] = MULT_NORM (iX[4] * T[2] - iX[6] * T[3]); - oX[2] = MULT_NORM (iX[0] * T[1] + iX[2] * T[0]); - oX[3] = MULT_NORM (iX[0] * T[0] - iX[2] * T[1]); - iX -= 8; - oX += 4; + T -= 4; + oX[0] = MULT_NORM (iX[4] * T[3] + iX[6] * T[2]); + oX[1] = MULT_NORM (iX[4] * T[2] - iX[6] * T[3]); + oX[2] = MULT_NORM (iX[0] * T[1] + iX[2] * T[0]); + oX[3] = MULT_NORM (iX[0] * T[0] - iX[2] * T[1]); + iX -= 8; + oX += 4; }while(iX>=in); mdct_butterflies(init,out+n2,n2); mdct_bitreverse(init,out); - /* roatate + window */ - { - DATA_TYPE *oX1=out+n2+n4; - DATA_TYPE *oX2=out+n2+n4; - DATA_TYPE *iX =out; - T =init->trig+n2; + DATA_TYPE *oX1=out+n2+n4; + DATA_TYPE *oX2=out+n2+n4; + DATA_TYPE *iX =out; + T =init->trig+n2; - do{ - oX1-=4; + do{ + oX1-=4; - oX1[3] = MULT_NORM (iX[0] * T[1] - iX[1] * T[0]); - oX2[0] = -MULT_NORM (iX[0] * T[0] + iX[1] * T[1]); + oX1[3] = MULT_NORM (iX[0] * T[1] - iX[1] * T[0]); + oX2[0] = -MULT_NORM (iX[0] * T[0] + iX[1] * T[1]); - oX1[2] = MULT_NORM (iX[2] * T[3] - iX[3] * T[2]); - oX2[1] = -MULT_NORM (iX[2] * T[2] + iX[3] * T[3]); + oX1[2] = MULT_NORM (iX[2] * T[3] - iX[3] * T[2]); + oX2[1] = -MULT_NORM (iX[2] * T[2] + iX[3] * T[3]); - oX1[1] = MULT_NORM (iX[4] * T[5] - iX[5] * T[4]); - oX2[2] = -MULT_NORM (iX[4] * T[4] + iX[5] * T[5]); + oX1[1] = MULT_NORM (iX[4] * T[5] - iX[5] * T[4]); + oX2[2] = -MULT_NORM (iX[4] * T[4] + iX[5] * T[5]); - oX1[0] = MULT_NORM (iX[6] * T[7] - iX[7] * T[6]); - oX2[3] = -MULT_NORM (iX[6] * T[6] + iX[7] * T[7]); + oX1[0] = MULT_NORM (iX[6] * T[7] - iX[7] * T[6]); + oX2[3] = -MULT_NORM (iX[6] * T[6] + iX[7] * T[7]); - oX2+=4; - iX += 8; - T += 8; - }while(iXoX2); + iX=out+n2+n4; + oX1=out+n2+n4; + oX2=out+n2; + do{ + oX1-=4; + oX1[0]= iX[3]; + oX1[1]= iX[2]; + oX1[2]= iX[1]; + oX1[3]= iX[0]; + iX+=4; + }while(oX1>oX2); } } @@ -136978,10 +125617,6 @@ void mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){ DATA_TYPE *w=(DATA_TYPE*) alloca(n*sizeof(*w)); /* forward needs working space */ DATA_TYPE *w2=w+n2; - /* rotate */ - - /* window + rotate + step 1 */ - REG_TYPE r0; REG_TYPE r1; DATA_TYPE *x0=in+n2+n4; @@ -136991,53 +125626,51 @@ void mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){ int i=0; for(i=0;itrig+n2; x0=out+n2; for(i=0;iscale); - x0[0] =MULT_NORM((w[0]*T[1]-w[1]*T[0])*init->scale); - w+=2; - T+=2; + x0--; + out[i] =MULT_NORM((w[0]*T[0]+w[1]*T[1])*init->scale); + x0[0] =MULT_NORM((w[0]*T[1]-w[1]*T[0])*init->scale); + w+=2; + T+=2; } } @@ -137065,768 +125698,739 @@ void mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){ #ifndef _V_MASKING_H_ #define _V_MASKING_H_ -/* more detailed ATH; the bass if flat to save stressing the floor - overly for only a bin or two of savings. */ - #define MAX_ATH 88 static float ATH[]={ - /*15*/ -51, -52, -53, -54, -55, -56, -57, -58, - /*31*/ -59, -60, -61, -62, -63, -64, -65, -66, - /*63*/ -67, -68, -69, -70, -71, -72, -73, -74, - /*125*/ -75, -76, -77, -78, -80, -81, -82, -83, - /*250*/ -84, -85, -86, -87, -88, -88, -89, -89, - /*500*/ -90, -91, -91, -92, -93, -94, -95, -96, - /*1k*/ -96, -97, -98, -98, -99, -99,-100,-100, - /*2k*/ -101,-102,-103,-104,-106,-107,-107,-107, - /*4k*/ -107,-105,-103,-102,-101, -99, -98, -96, - /*8k*/ -95, -95, -96, -97, -96, -95, -93, -90, - /*16k*/ -80, -70, -50, -40, -30, -30, -30, -30 + -51, -52, -53, -54, -55, -56, -57, -58, + -59, -60, -61, -62, -63, -64, -65, -66, + -67, -68, -69, -70, -71, -72, -73, -74, + -75, -76, -77, -78, -80, -81, -82, -83, + -84, -85, -86, -87, -88, -88, -89, -89, + -90, -91, -91, -92, -93, -94, -95, -96, + -96, -97, -98, -98, -99, -99,-100,-100, + -101,-102,-103,-104,-106,-107,-107,-107, + -107,-105,-103,-102,-101, -99, -98, -96, + -95, -95, -96, -97, -96, -95, -93, -90, + -80, -70, -50, -40, -30, -30, -30, -30 }; -/* The tone masking curves from Ehmer's and Fielder's papers have been - replaced by an empirically collected data set. The previously - published values were, far too often, simply on crack. */ - #define EHMER_OFFSET 16 #define EHMER_MAX 56 -/* masking tones from -50 to 0dB, 62.5 through 16kHz at half octaves - test tones from -2 octaves to +5 octaves sampled at eighth octaves */ -/* (Vorbis 0dB, the loudest possible tone, is assumed to be ~100dB SPL - for collection of these curves) */ - static float tonemasks[P_BANDS][6][EHMER_MAX]={ - /* 62.5 Hz */ {{ -60, -60, -60, -60, -60, -60, -60, -60, - -60, -60, -60, -60, -62, -62, -65, -73, - -69, -68, -68, -67, -70, -70, -72, -74, - -75, -79, -79, -80, -83, -88, -93, -100, - -110, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -60, -60, -60, -60, -62, -62, -65, -73, + -69, -68, -68, -67, -70, -70, -72, -74, + -75, -79, -79, -80, -83, -88, -93, -100, + -110, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -48, -48, -48, -48, -48, -48, -48, -48, - -48, -48, -48, -48, -48, -53, -61, -66, - -66, -68, -67, -70, -76, -76, -72, -73, - -75, -76, -78, -79, -83, -88, -93, -100, - -110, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -48, -48, -48, -48, -48, -53, -61, -66, + -66, -68, -67, -70, -76, -76, -72, -73, + -75, -76, -78, -79, -83, -88, -93, -100, + -110, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -37, -37, -37, -37, -37, -37, -37, -37, - -38, -40, -42, -46, -48, -53, -55, -62, - -65, -58, -56, -56, -61, -60, -65, -67, - -69, -71, -77, -77, -78, -80, -82, -84, - -88, -93, -98, -106, -112, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -38, -40, -42, -46, -48, -53, -55, -62, + -65, -58, -56, -56, -61, -60, -65, -67, + -69, -71, -77, -77, -78, -80, -82, -84, + -88, -93, -98, -106, -112, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -25, -25, -25, -25, -25, -25, -25, -25, - -25, -26, -27, -29, -32, -38, -48, -52, - -52, -50, -48, -48, -51, -52, -54, -60, - -67, -67, -66, -68, -69, -73, -73, -76, - -80, -81, -81, -85, -85, -86, -88, -93, - -100, -110, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -25, -26, -27, -29, -32, -38, -48, -52, + -52, -50, -48, -48, -51, -52, -54, -60, + -67, -67, -66, -68, -69, -73, -73, -76, + -80, -81, -81, -85, -85, -86, -88, -93, + -100, -110, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -16, -16, -16, -16, -16, -16, -16, -16, - -17, -19, -20, -22, -26, -28, -31, -40, - -47, -39, -39, -40, -42, -43, -47, -51, - -57, -52, -55, -55, -60, -58, -62, -63, - -70, -67, -69, -72, -73, -77, -80, -82, - -83, -87, -90, -94, -98, -104, -115, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -17, -19, -20, -22, -26, -28, -31, -40, + -47, -39, -39, -40, -42, -43, -47, -51, + -57, -52, -55, -55, -60, -58, -62, -63, + -70, -67, -69, -72, -73, -77, -80, -82, + -83, -87, -90, -94, -98, -104, -115, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -8, -8, -8, -8, -8, -8, -8, -8, - -8, -8, -10, -11, -15, -19, -25, -30, - -34, -31, -30, -31, -29, -32, -35, -42, - -48, -42, -44, -46, -50, -50, -51, -52, - -59, -54, -55, -55, -58, -62, -63, -66, - -72, -73, -76, -75, -78, -80, -80, -81, - -84, -88, -90, -94, -98, -101, -106, -110}}, - /* 88Hz */ + -8, -8, -10, -11, -15, -19, -25, -30, + -34, -31, -30, -31, -29, -32, -35, -42, + -48, -42, -44, -46, -50, -50, -51, -52, + -59, -54, -55, -55, -58, -62, -63, -66, + -72, -73, -76, -75, -78, -80, -80, -81, + -84, -88, -90, -94, -98, -101, -106, -110}}, {{ -66, -66, -66, -66, -66, -66, -66, -66, - -66, -66, -66, -66, -66, -67, -67, -67, - -76, -72, -71, -74, -76, -76, -75, -78, - -79, -79, -81, -83, -86, -89, -93, -97, - -100, -105, -110, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -66, -66, -66, -66, -66, -67, -67, -67, + -76, -72, -71, -74, -76, -76, -75, -78, + -79, -79, -81, -83, -86, -89, -93, -97, + -100, -105, -110, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -47, -47, -47, -47, -47, -47, -47, -47, - -47, -47, -47, -48, -51, -55, -59, -66, - -66, -66, -67, -66, -68, -69, -70, -74, - -79, -77, -77, -78, -80, -81, -82, -84, - -86, -88, -91, -95, -100, -108, -116, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -47, -47, -47, -48, -51, -55, -59, -66, + -66, -66, -67, -66, -68, -69, -70, -74, + -79, -77, -77, -78, -80, -81, -82, -84, + -86, -88, -91, -95, -100, -108, -116, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -36, -36, -36, -36, -36, -36, -36, -36, - -36, -37, -37, -41, -44, -48, -51, -58, - -62, -60, -57, -59, -59, -60, -63, -65, - -72, -71, -70, -72, -74, -77, -76, -78, - -81, -81, -80, -83, -86, -91, -96, -100, - -105, -110, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -36, -37, -37, -41, -44, -48, -51, -58, + -62, -60, -57, -59, -59, -60, -63, -65, + -72, -71, -70, -72, -74, -77, -76, -78, + -81, -81, -80, -83, -86, -91, -96, -100, + -105, -110, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -28, -28, -28, -28, -28, -28, -28, -28, - -28, -30, -32, -32, -33, -35, -41, -49, - -50, -49, -47, -48, -48, -52, -51, -57, - -65, -61, -59, -61, -64, -69, -70, -74, - -77, -77, -78, -81, -84, -85, -87, -90, - -92, -96, -100, -107, -112, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -28, -30, -32, -32, -33, -35, -41, -49, + -50, -49, -47, -48, -48, -52, -51, -57, + -65, -61, -59, -61, -64, -69, -70, -74, + -77, -77, -78, -81, -84, -85, -87, -90, + -92, -96, -100, -107, -112, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -19, -19, -19, -19, -19, -19, -19, -19, - -20, -21, -23, -27, -30, -35, -36, -41, - -46, -44, -42, -40, -41, -41, -43, -48, - -55, -53, -52, -53, -56, -59, -58, -60, - -67, -66, -69, -71, -72, -75, -79, -81, - -84, -87, -90, -93, -97, -101, -107, -114, - -999, -999, -999, -999, -999, -999, -999, -999}, + -20, -21, -23, -27, -30, -35, -36, -41, + -46, -44, -42, -40, -41, -41, -43, -48, + -55, -53, -52, -53, -56, -59, -58, -60, + -67, -66, -69, -71, -72, -75, -79, -81, + -84, -87, -90, -93, -97, -101, -107, -114, + -999, -999, -999, -999, -999, -999, -999, -999}, { -9, -9, -9, -9, -9, -9, -9, -9, - -11, -12, -12, -15, -16, -20, -23, -30, - -37, -34, -33, -34, -31, -32, -32, -38, - -47, -44, -41, -40, -47, -49, -46, -46, - -58, -50, -50, -54, -58, -62, -64, -67, - -67, -70, -72, -76, -79, -83, -87, -91, - -96, -100, -104, -110, -999, -999, -999, -999}}, - /* 125 Hz */ + -11, -12, -12, -15, -16, -20, -23, -30, + -37, -34, -33, -34, -31, -32, -32, -38, + -47, -44, -41, -40, -47, -49, -46, -46, + -58, -50, -50, -54, -58, -62, -64, -67, + -67, -70, -72, -76, -79, -83, -87, -91, + -96, -100, -104, -110, -999, -999, -999, -999}}, {{ -62, -62, -62, -62, -62, -62, -62, -62, - -62, -62, -63, -64, -66, -67, -66, -68, - -75, -72, -76, -75, -76, -78, -79, -82, - -84, -85, -90, -94, -101, -110, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -62, -62, -63, -64, -66, -67, -66, -68, + -75, -72, -76, -75, -76, -78, -79, -82, + -84, -85, -90, -94, -101, -110, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -59, -59, -59, -59, -59, -59, -59, -59, - -59, -59, -59, -60, -60, -61, -63, -66, - -71, -68, -70, -70, -71, -72, -72, -75, - -81, -78, -79, -82, -83, -86, -90, -97, - -103, -113, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -59, -59, -59, -60, -60, -61, -63, -66, + -71, -68, -70, -70, -71, -72, -72, -75, + -81, -78, -79, -82, -83, -86, -90, -97, + -103, -113, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -53, -53, -53, -53, -53, -53, -53, -53, - -53, -54, -55, -57, -56, -57, -55, -61, - -65, -60, -60, -62, -63, -63, -66, -68, - -74, -73, -75, -75, -78, -80, -80, -82, - -85, -90, -96, -101, -108, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -53, -54, -55, -57, -56, -57, -55, -61, + -65, -60, -60, -62, -63, -63, -66, -68, + -74, -73, -75, -75, -78, -80, -80, -82, + -85, -90, -96, -101, -108, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -46, -46, -46, -46, -46, -46, -46, -46, - -46, -46, -47, -47, -47, -47, -48, -51, - -57, -51, -49, -50, -51, -53, -54, -59, - -66, -60, -62, -67, -67, -70, -72, -75, - -76, -78, -81, -85, -88, -94, -97, -104, - -112, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -46, -46, -47, -47, -47, -47, -48, -51, + -57, -51, -49, -50, -51, -53, -54, -59, + -66, -60, -62, -67, -67, -70, -72, -75, + -76, -78, -81, -85, -88, -94, -97, -104, + -112, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -36, -36, -36, -36, -36, -36, -36, -36, - -39, -41, -42, -42, -39, -38, -41, -43, - -52, -44, -40, -39, -37, -37, -40, -47, - -54, -50, -48, -50, -55, -61, -59, -62, - -66, -66, -66, -69, -69, -73, -74, -74, - -75, -77, -79, -82, -87, -91, -95, -100, - -108, -115, -999, -999, -999, -999, -999, -999}, + -39, -41, -42, -42, -39, -38, -41, -43, + -52, -44, -40, -39, -37, -37, -40, -47, + -54, -50, -48, -50, -55, -61, -59, -62, + -66, -66, -66, -69, -69, -73, -74, -74, + -75, -77, -79, -82, -87, -91, -95, -100, + -108, -115, -999, -999, -999, -999, -999, -999}, { -28, -26, -24, -22, -20, -20, -23, -29, - -30, -31, -28, -27, -28, -28, -28, -35, - -40, -33, -32, -29, -30, -30, -30, -37, - -45, -41, -37, -38, -45, -47, -47, -48, - -53, -49, -48, -50, -49, -49, -51, -52, - -58, -56, -57, -56, -60, -61, -62, -70, - -72, -74, -78, -83, -88, -93, -100, -106}}, - /* 177 Hz */ + -30, -31, -28, -27, -28, -28, -28, -35, + -40, -33, -32, -29, -30, -30, -30, -37, + -45, -41, -37, -38, -45, -47, -47, -48, + -53, -49, -48, -50, -49, -49, -51, -52, + -58, -56, -57, -56, -60, -61, -62, -70, + -72, -74, -78, -83, -88, -93, -100, -106}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -110, -105, -100, -95, -91, -87, -83, - -80, -78, -76, -78, -78, -81, -83, -85, - -86, -85, -86, -87, -90, -97, -107, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -110, -105, -100, -95, -91, -87, -83, + -80, -78, -76, -78, -78, -81, -83, -85, + -86, -85, -86, -87, -90, -97, -107, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -110, -105, -100, -95, -90, - -85, -81, -77, -73, -70, -67, -67, -68, - -75, -73, -70, -69, -70, -72, -75, -79, - -84, -83, -84, -86, -88, -89, -89, -93, - -98, -105, -112, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -85, -81, -77, -73, -70, -67, -67, -68, + -75, -73, -70, -69, -70, -72, -75, -79, + -84, -83, -84, -86, -88, -89, -89, -93, + -98, -105, -112, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-105, -100, -95, -90, -85, -80, -76, -71, - -68, -68, -65, -63, -63, -62, -62, -64, - -65, -64, -61, -62, -63, -64, -66, -68, - -73, -73, -74, -75, -76, -81, -83, -85, - -88, -89, -92, -95, -100, -108, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -68, -68, -65, -63, -63, -62, -62, -64, + -65, -64, -61, -62, -63, -64, -66, -68, + -73, -73, -74, -75, -76, -81, -83, -85, + -88, -89, -92, -95, -100, -108, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -80, -75, -71, -68, -65, -63, -62, -61, - -61, -61, -61, -59, -56, -57, -53, -50, - -58, -52, -50, -50, -52, -53, -54, -58, - -67, -63, -67, -68, -72, -75, -78, -80, - -81, -81, -82, -85, -89, -90, -93, -97, - -101, -107, -114, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -61, -61, -61, -59, -56, -57, -53, -50, + -58, -52, -50, -50, -52, -53, -54, -58, + -67, -63, -67, -68, -72, -75, -78, -80, + -81, -81, -82, -85, -89, -90, -93, -97, + -101, -107, -114, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, { -65, -61, -59, -57, -56, -55, -55, -56, - -56, -57, -55, -53, -52, -47, -44, -44, - -50, -44, -41, -39, -39, -42, -40, -46, - -51, -49, -50, -53, -54, -63, -60, -61, - -62, -66, -66, -66, -70, -73, -74, -75, - -76, -75, -79, -85, -89, -91, -96, -102, - -110, -999, -999, -999, -999, -999, -999, -999}, + -56, -57, -55, -53, -52, -47, -44, -44, + -50, -44, -41, -39, -39, -42, -40, -46, + -51, -49, -50, -53, -54, -63, -60, -61, + -62, -66, -66, -66, -70, -73, -74, -75, + -76, -75, -79, -85, -89, -91, -96, -102, + -110, -999, -999, -999, -999, -999, -999, -999}, { -52, -50, -49, -49, -48, -48, -48, -49, - -50, -50, -49, -46, -43, -39, -35, -33, - -38, -36, -32, -29, -32, -32, -32, -35, - -44, -39, -38, -38, -46, -50, -45, -46, - -53, -50, -50, -50, -54, -54, -53, -53, - -56, -57, -59, -66, -70, -72, -74, -79, - -83, -85, -90, -97, -114, -999, -999, -999}}, - /* 250 Hz */ + -50, -50, -49, -46, -43, -39, -35, -33, + -38, -36, -32, -29, -32, -32, -32, -35, + -44, -39, -38, -38, -46, -50, -45, -46, + -53, -50, -50, -50, -54, -54, -53, -53, + -56, -57, -59, -66, -70, -72, -74, -79, + -83, -85, -90, -97, -114, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -110, -105, - -100, -95, -90, -86, -80, -75, -75, -79, - -80, -79, -80, -81, -82, -88, -95, -103, - -110, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -100, -95, -90, -86, -80, -75, -75, -79, + -80, -79, -80, -81, -82, -88, -95, -103, + -110, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -108, -103, -98, -93, - -88, -83, -79, -78, -75, -71, -67, -68, - -73, -73, -72, -73, -75, -77, -80, -82, - -88, -93, -100, -107, -114, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -88, -83, -79, -78, -75, -71, -67, -68, + -73, -73, -72, -73, -75, -77, -80, -82, + -88, -93, -100, -107, -114, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -110, -105, -101, -96, -90, - -86, -81, -77, -73, -69, -66, -61, -62, - -66, -64, -62, -65, -66, -70, -72, -76, - -81, -80, -84, -90, -95, -102, -110, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -86, -81, -77, -73, -69, -66, -61, -62, + -66, -64, -62, -65, -66, -70, -72, -76, + -81, -80, -84, -90, -95, -102, -110, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -107, -103, -97, -92, -88, - -83, -79, -74, -70, -66, -59, -53, -58, - -62, -55, -54, -54, -54, -58, -61, -62, - -72, -70, -72, -75, -78, -80, -81, -80, - -83, -83, -88, -93, -100, -107, -115, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -83, -79, -74, -70, -66, -59, -53, -58, + -62, -55, -54, -54, -54, -58, -61, -62, + -72, -70, -72, -75, -78, -80, -81, -80, + -83, -83, -88, -93, -100, -107, -115, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -105, -100, -95, -90, -85, - -80, -75, -70, -66, -62, -56, -48, -44, - -48, -46, -46, -43, -46, -48, -48, -51, - -58, -58, -59, -60, -62, -62, -61, -61, - -65, -64, -65, -68, -70, -74, -75, -78, - -81, -86, -95, -110, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -80, -75, -70, -66, -62, -56, -48, -44, + -48, -46, -46, -43, -46, -48, -48, -51, + -58, -58, -59, -60, -62, -62, -61, -61, + -65, -64, -65, -68, -70, -74, -75, -78, + -81, -86, -95, -110, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -105, -100, -95, -90, -85, -80, - -75, -70, -65, -61, -55, -49, -39, -33, - -40, -35, -32, -38, -40, -33, -35, -37, - -46, -41, -45, -44, -46, -42, -45, -46, - -52, -50, -50, -50, -54, -54, -55, -57, - -62, -64, -66, -68, -70, -76, -81, -90, - -100, -110, -999, -999, -999, -999, -999, -999}}, - /* 354 hz */ + -75, -70, -65, -61, -55, -49, -39, -33, + -40, -35, -32, -38, -40, -33, -35, -37, + -46, -41, -45, -44, -46, -42, -45, -46, + -52, -50, -50, -50, -54, -54, -55, -57, + -62, -64, -66, -68, -70, -76, -81, -90, + -100, -110, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -105, -98, -90, -85, -82, -83, -80, -78, - -84, -79, -80, -83, -87, -89, -91, -93, - -99, -106, -117, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -105, -98, -90, -85, -82, -83, -80, -78, + -84, -79, -80, -83, -87, -89, -91, -93, + -99, -106, -117, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -105, -98, -90, -85, -80, -75, -70, -68, - -74, -72, -74, -77, -80, -82, -85, -87, - -92, -89, -91, -95, -100, -106, -112, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -105, -98, -90, -85, -80, -75, -70, -68, + -74, -72, -74, -77, -80, -82, -85, -87, + -92, -89, -91, -95, -100, -106, -112, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -105, -98, -90, -83, -75, -71, -63, -64, - -67, -62, -64, -67, -70, -73, -77, -81, - -84, -83, -85, -89, -90, -93, -98, -104, - -109, -114, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -105, -98, -90, -83, -75, -71, -63, -64, + -67, -62, -64, -67, -70, -73, -77, -81, + -84, -83, -85, -89, -90, -93, -98, -104, + -109, -114, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -103, -96, -88, -81, -75, -68, -58, -54, - -56, -54, -56, -56, -58, -60, -63, -66, - -74, -69, -72, -72, -75, -74, -77, -81, - -81, -82, -84, -87, -93, -96, -99, -104, - -110, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -103, -96, -88, -81, -75, -68, -58, -54, + -56, -54, -56, -56, -58, -60, -63, -66, + -74, -69, -72, -72, -75, -74, -77, -81, + -81, -82, -84, -87, -93, -96, -99, -104, + -110, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -108, -102, -96, - -91, -85, -80, -74, -68, -60, -51, -46, - -48, -46, -43, -45, -47, -47, -49, -48, - -56, -53, -55, -58, -57, -63, -58, -60, - -66, -64, -67, -70, -70, -74, -77, -84, - -86, -89, -91, -93, -94, -101, -109, -118, - -999, -999, -999, -999, -999, -999, -999, -999}, + -91, -85, -80, -74, -68, -60, -51, -46, + -48, -46, -43, -45, -47, -47, -49, -48, + -56, -53, -55, -58, -57, -63, -58, -60, + -66, -64, -67, -70, -70, -74, -77, -84, + -86, -89, -91, -93, -94, -101, -109, -118, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -108, -103, -98, -93, -88, - -83, -78, -73, -68, -60, -53, -44, -35, - -38, -38, -34, -34, -36, -40, -41, -44, - -51, -45, -46, -47, -46, -54, -50, -49, - -50, -50, -50, -51, -54, -57, -58, -60, - -66, -66, -66, -64, -65, -68, -77, -82, - -87, -95, -110, -999, -999, -999, -999, -999}}, - /* 500 Hz */ + -83, -78, -73, -68, -60, -53, -44, -35, + -38, -38, -34, -34, -36, -40, -41, -44, + -51, -45, -46, -47, -46, -54, -50, -49, + -50, -50, -50, -51, -54, -57, -58, -60, + -66, -66, -66, -64, -65, -68, -77, -82, + -87, -95, -110, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -107, -102, -97, -92, -87, -83, -78, -75, - -82, -79, -83, -85, -89, -92, -95, -98, - -101, -105, -109, -113, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -107, -102, -97, -92, -87, -83, -78, -75, + -82, -79, -83, -85, -89, -92, -95, -98, + -101, -105, -109, -113, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -106, - -100, -95, -90, -86, -81, -78, -74, -69, - -74, -74, -76, -79, -83, -84, -86, -89, - -92, -97, -93, -100, -103, -107, -110, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -100, -95, -90, -86, -81, -78, -74, -69, + -74, -74, -76, -79, -83, -84, -86, -89, + -92, -97, -93, -100, -103, -107, -110, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -106, -100, - -95, -90, -87, -83, -80, -75, -69, -60, - -66, -66, -68, -70, -74, -78, -79, -81, - -81, -83, -84, -87, -93, -96, -99, -103, - -107, -110, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -95, -90, -87, -83, -80, -75, -69, -60, + -66, -66, -68, -70, -74, -78, -79, -81, + -81, -83, -84, -87, -93, -96, -99, -103, + -107, -110, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -108, -103, -98, - -93, -89, -85, -82, -78, -71, -62, -55, - -58, -58, -54, -54, -55, -59, -61, -62, - -70, -66, -66, -67, -70, -72, -75, -78, - -84, -84, -84, -88, -91, -90, -95, -98, - -102, -103, -106, -110, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -93, -89, -85, -82, -78, -71, -62, -55, + -58, -58, -54, -54, -55, -59, -61, -62, + -70, -66, -66, -67, -70, -72, -75, -78, + -84, -84, -84, -88, -91, -90, -95, -98, + -102, -103, -106, -110, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -108, -103, -98, -94, - -90, -87, -82, -79, -73, -67, -58, -47, - -50, -45, -41, -45, -48, -44, -44, -49, - -54, -51, -48, -47, -49, -50, -51, -57, - -58, -60, -63, -69, -70, -69, -71, -74, - -78, -82, -90, -95, -101, -105, -110, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -90, -87, -82, -79, -73, -67, -58, -47, + -50, -45, -41, -45, -48, -44, -44, -49, + -54, -51, -48, -47, -49, -50, -51, -57, + -58, -60, -63, -69, -70, -69, -71, -74, + -78, -82, -90, -95, -101, -105, -110, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -105, -101, -97, -93, -90, - -85, -80, -77, -72, -65, -56, -48, -37, - -40, -36, -34, -40, -50, -47, -38, -41, - -47, -38, -35, -39, -38, -43, -40, -45, - -50, -45, -44, -47, -50, -55, -48, -48, - -52, -66, -70, -76, -82, -90, -97, -105, - -110, -999, -999, -999, -999, -999, -999, -999}}, - /* 707 Hz */ + -85, -80, -77, -72, -65, -56, -48, -37, + -40, -36, -34, -40, -50, -47, -38, -41, + -47, -38, -35, -39, -38, -43, -40, -45, + -50, -45, -44, -47, -50, -55, -48, -48, + -52, -66, -70, -76, -82, -90, -97, -105, + -110, -999, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -108, -103, -98, -93, -86, -79, -76, - -83, -81, -85, -87, -89, -93, -98, -102, - -107, -112, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -108, -103, -98, -93, -86, -79, -76, + -83, -81, -85, -87, -89, -93, -98, -102, + -107, -112, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -108, -103, -98, -93, -86, -79, -71, - -77, -74, -77, -79, -81, -84, -85, -90, - -92, -93, -92, -98, -101, -108, -112, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -108, -103, -98, -93, -86, -79, -71, + -77, -74, -77, -79, -81, -84, -85, -90, + -92, -93, -92, -98, -101, -108, -112, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -108, -103, -98, -93, -87, -78, -68, -65, - -66, -62, -65, -67, -70, -73, -75, -78, - -82, -82, -83, -84, -91, -93, -98, -102, - -106, -110, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -108, -103, -98, -93, -87, -78, -68, -65, + -66, -62, -65, -67, -70, -73, -75, -78, + -82, -82, -83, -84, -91, -93, -98, -102, + -106, -110, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -105, -100, -95, -90, -82, -74, -62, -57, - -58, -56, -51, -52, -52, -54, -54, -58, - -66, -59, -60, -63, -66, -69, -73, -79, - -83, -84, -80, -81, -81, -82, -88, -92, - -98, -105, -113, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -105, -100, -95, -90, -82, -74, -62, -57, + -58, -56, -51, -52, -52, -54, -54, -58, + -66, -59, -60, -63, -66, -69, -73, -79, + -83, -84, -80, -81, -81, -82, -88, -92, + -98, -105, -113, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -107, - -102, -97, -92, -84, -79, -69, -57, -47, - -52, -47, -44, -45, -50, -52, -42, -42, - -53, -43, -43, -48, -51, -56, -55, -52, - -57, -59, -61, -62, -67, -71, -78, -83, - -86, -94, -98, -103, -110, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -102, -97, -92, -84, -79, -69, -57, -47, + -52, -47, -44, -45, -50, -52, -42, -42, + -53, -43, -43, -48, -51, -56, -55, -52, + -57, -59, -61, -62, -67, -71, -78, -83, + -86, -94, -98, -103, -110, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -105, -100, - -95, -90, -84, -78, -70, -61, -51, -41, - -40, -38, -40, -46, -52, -51, -41, -40, - -46, -40, -38, -38, -41, -46, -41, -46, - -47, -43, -43, -45, -41, -45, -56, -67, - -68, -83, -87, -90, -95, -102, -107, -113, - -999, -999, -999, -999, -999, -999, -999, -999}}, - /* 1000 Hz */ + -95, -90, -84, -78, -70, -61, -51, -41, + -40, -38, -40, -46, -52, -51, -41, -40, + -46, -40, -38, -38, -41, -46, -41, -46, + -47, -43, -43, -45, -41, -45, -56, -67, + -68, -83, -87, -90, -95, -102, -107, -113, + -999, -999, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -109, -105, -101, -96, -91, -84, -77, - -82, -82, -85, -89, -94, -100, -106, -110, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -109, -105, -101, -96, -91, -84, -77, + -82, -82, -85, -89, -94, -100, -106, -110, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -106, -103, -98, -92, -85, -80, -71, - -75, -72, -76, -80, -84, -86, -89, -93, - -100, -107, -113, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -106, -103, -98, -92, -85, -80, -71, + -75, -72, -76, -80, -84, -86, -89, -93, + -100, -107, -113, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -107, - -104, -101, -97, -92, -88, -84, -80, -64, - -66, -63, -64, -66, -69, -73, -77, -83, - -83, -86, -91, -98, -104, -111, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -104, -101, -97, -92, -88, -84, -80, -64, + -66, -63, -64, -66, -69, -73, -77, -83, + -83, -86, -91, -98, -104, -111, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -107, - -104, -101, -97, -92, -90, -84, -74, -57, - -58, -52, -55, -54, -50, -52, -50, -52, - -63, -62, -69, -76, -77, -78, -78, -79, - -82, -88, -94, -100, -106, -111, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -104, -101, -97, -92, -90, -84, -74, -57, + -58, -52, -55, -54, -50, -52, -50, -52, + -63, -62, -69, -76, -77, -78, -78, -79, + -82, -88, -94, -100, -106, -111, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -106, -102, - -98, -95, -90, -85, -83, -78, -70, -50, - -50, -41, -44, -49, -47, -50, -50, -44, - -55, -46, -47, -48, -48, -54, -49, -49, - -58, -62, -71, -81, -87, -92, -97, -102, - -108, -114, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -98, -95, -90, -85, -83, -78, -70, -50, + -50, -41, -44, -49, -47, -50, -50, -44, + -55, -46, -47, -48, -48, -54, -49, -49, + -58, -62, -71, -81, -87, -92, -97, -102, + -108, -114, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -106, -102, - -98, -95, -90, -85, -83, -78, -70, -45, - -43, -41, -47, -50, -51, -50, -49, -45, - -47, -41, -44, -41, -39, -43, -38, -37, - -40, -41, -44, -50, -58, -65, -73, -79, - -85, -92, -97, -101, -105, -109, -113, -999, - -999, -999, -999, -999, -999, -999, -999, -999}}, - /* 1414 Hz */ + -98, -95, -90, -85, -83, -78, -70, -45, + -43, -41, -47, -50, -51, -50, -49, -45, + -47, -41, -44, -41, -39, -43, -38, -37, + -40, -41, -44, -50, -58, -65, -73, -79, + -85, -92, -97, -101, -105, -109, -113, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -107, -100, -95, -87, -81, - -85, -83, -88, -93, -100, -107, -114, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -107, -100, -95, -87, -81, + -85, -83, -88, -93, -100, -107, -114, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -107, -101, -95, -88, -83, -76, - -73, -72, -79, -84, -90, -95, -100, -105, - -110, -115, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -107, -101, -95, -88, -83, -76, + -73, -72, -79, -84, -90, -95, -100, -105, + -110, -115, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -104, -98, -92, -87, -81, -70, - -65, -62, -67, -71, -74, -80, -85, -91, - -95, -99, -103, -108, -111, -114, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -104, -98, -92, -87, -81, -70, + -65, -62, -67, -71, -74, -80, -85, -91, + -95, -99, -103, -108, -111, -114, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -103, -97, -90, -85, -76, -60, - -56, -54, -60, -62, -61, -56, -63, -65, - -73, -74, -77, -75, -78, -81, -86, -87, - -88, -91, -94, -98, -103, -110, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -103, -97, -90, -85, -76, -60, + -56, -54, -60, -62, -61, -56, -63, -65, + -73, -74, -77, -75, -78, -81, -86, -87, + -88, -91, -94, -98, -103, -110, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -105, - -100, -97, -92, -86, -81, -79, -70, -57, - -51, -47, -51, -58, -60, -56, -53, -50, - -58, -52, -50, -50, -53, -55, -64, -69, - -71, -85, -82, -78, -81, -85, -95, -102, - -112, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -100, -97, -92, -86, -81, -79, -70, -57, + -51, -47, -51, -58, -60, -56, -53, -50, + -58, -52, -50, -50, -53, -55, -64, -69, + -71, -85, -82, -78, -81, -85, -95, -102, + -112, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -105, - -100, -97, -92, -85, -83, -79, -72, -49, - -40, -43, -43, -54, -56, -51, -50, -40, - -43, -38, -36, -35, -37, -38, -37, -44, - -54, -60, -57, -60, -70, -75, -84, -92, - -103, -112, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}}, - /* 2000 Hz */ + -100, -97, -92, -85, -83, -79, -72, -49, + -40, -43, -43, -54, -56, -51, -50, -40, + -43, -38, -36, -35, -37, -38, -37, -44, + -54, -60, -57, -60, -70, -75, -84, -92, + -103, -112, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -110, -102, -95, -89, -82, - -83, -84, -90, -92, -99, -107, -113, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -110, -102, -95, -89, -82, + -83, -84, -90, -92, -99, -107, -113, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -107, -101, -95, -89, -83, -72, - -74, -78, -85, -88, -88, -90, -92, -98, - -105, -111, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -107, -101, -95, -89, -83, -72, + -74, -78, -85, -88, -88, -90, -92, -98, + -105, -111, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -109, -103, -97, -93, -87, -81, -70, - -70, -67, -75, -73, -76, -79, -81, -83, - -88, -89, -97, -103, -110, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -109, -103, -97, -93, -87, -81, -70, + -70, -67, -75, -73, -76, -79, -81, -83, + -88, -89, -97, -103, -110, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -107, -100, -94, -88, -83, -75, -63, - -59, -59, -63, -66, -60, -62, -67, -67, - -77, -76, -81, -88, -86, -92, -96, -102, - -109, -116, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -107, -100, -94, -88, -83, -75, -63, + -59, -59, -63, -66, -60, -62, -67, -67, + -77, -76, -81, -88, -86, -92, -96, -102, + -109, -116, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -105, -98, -92, -86, -81, -73, -56, - -52, -47, -55, -60, -58, -52, -51, -45, - -49, -50, -53, -54, -61, -71, -70, -69, - -78, -79, -87, -90, -96, -104, -112, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -105, -98, -92, -86, -81, -73, -56, + -52, -47, -55, -60, -58, -52, -51, -45, + -49, -50, -53, -54, -61, -71, -70, -69, + -78, -79, -87, -90, -96, -104, -112, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -103, -96, -90, -86, -78, -70, -51, - -42, -47, -48, -55, -54, -54, -53, -42, - -35, -28, -33, -38, -37, -44, -47, -49, - -54, -63, -68, -78, -82, -89, -94, -99, - -104, -109, -114, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}}, - /* 2828 Hz */ + -999, -103, -96, -90, -86, -78, -70, -51, + -42, -47, -48, -55, -54, -54, -53, -42, + -35, -28, -33, -38, -37, -44, -47, -49, + -54, -63, -68, -78, -82, -89, -94, -99, + -104, -109, -114, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -110, -100, -90, -79, - -85, -81, -82, -82, -89, -94, -99, -103, - -109, -115, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -110, -100, -90, -79, + -85, -81, -82, -82, -89, -94, -99, -103, + -109, -115, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -105, -97, -85, -72, - -74, -70, -70, -70, -76, -85, -91, -93, - -97, -103, -109, -115, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -105, -97, -85, -72, + -74, -70, -70, -70, -76, -85, -91, -93, + -97, -103, -109, -115, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -112, -93, -81, -68, - -62, -60, -60, -57, -63, -70, -77, -82, - -90, -93, -98, -104, -109, -113, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -112, -93, -81, -68, + -62, -60, -60, -57, -63, -70, -77, -82, + -90, -93, -98, -104, -109, -113, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -113, -100, -93, -84, -63, - -58, -48, -53, -54, -52, -52, -57, -64, - -66, -76, -83, -81, -85, -85, -90, -95, - -98, -101, -103, -106, -108, -111, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -113, -100, -93, -84, -63, + -58, -48, -53, -54, -52, -52, -57, -64, + -66, -76, -83, -81, -85, -85, -90, -95, + -98, -101, -103, -106, -108, -111, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -105, -95, -86, -74, -53, - -50, -38, -43, -49, -43, -42, -39, -39, - -46, -52, -57, -56, -72, -69, -74, -81, - -87, -92, -94, -97, -99, -102, -105, -108, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -105, -95, -86, -74, -53, + -50, -38, -43, -49, -43, -42, -39, -39, + -46, -52, -57, -56, -72, -69, -74, -81, + -87, -92, -94, -97, -99, -102, -105, -108, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -108, -99, -90, -76, -66, -45, - -43, -41, -44, -47, -43, -47, -40, -30, - -31, -31, -39, -33, -40, -41, -43, -53, - -59, -70, -73, -77, -79, -82, -84, -87, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}}, - /* 4000 Hz */ + -999, -999, -108, -99, -90, -76, -66, -45, + -43, -41, -44, -47, -43, -47, -40, -30, + -31, -31, -39, -33, -40, -41, -43, -53, + -59, -70, -73, -77, -79, -82, -84, -87, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -110, -91, -76, - -75, -85, -93, -98, -104, -110, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -999, -110, -91, -76, + -75, -85, -93, -98, -104, -110, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -110, -91, -70, - -70, -75, -86, -89, -94, -98, -101, -106, - -110, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -999, -110, -91, -70, + -70, -75, -86, -89, -94, -98, -101, -106, + -110, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -110, -95, -80, -60, - -65, -64, -74, -83, -88, -91, -95, -99, - -103, -107, -110, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -110, -95, -80, -60, + -65, -64, -74, -83, -88, -91, -95, -99, + -103, -107, -110, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -110, -95, -80, -58, - -55, -49, -66, -68, -71, -78, -78, -80, - -88, -85, -89, -97, -100, -105, -110, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -110, -95, -80, -58, + -55, -49, -66, -68, -71, -78, -78, -80, + -88, -85, -89, -97, -100, -105, -110, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -110, -95, -80, -53, - -52, -41, -59, -59, -49, -58, -56, -63, - -86, -79, -90, -93, -98, -103, -107, -112, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -110, -95, -80, -53, + -52, -41, -59, -59, -49, -58, -56, -63, + -86, -79, -90, -93, -98, -103, -107, -112, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -110, -97, -91, -73, -45, - -40, -33, -53, -61, -49, -54, -50, -50, - -60, -52, -67, -74, -81, -92, -96, -100, - -105, -110, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}}, - /* 5657 Hz */ + -999, -999, -999, -110, -97, -91, -73, -45, + -40, -33, -53, -61, -49, -54, -50, -50, + -60, -52, -67, -74, -81, -92, -96, -100, + -105, -110, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -113, -106, -99, -92, -77, - -80, -88, -97, -106, -115, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -113, -106, -99, -92, -77, + -80, -88, -97, -106, -115, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -116, -109, -102, -95, -89, -74, - -72, -88, -87, -95, -102, -109, -116, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -116, -109, -102, -95, -89, -74, + -72, -88, -87, -95, -102, -109, -116, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -116, -109, -102, -95, -89, -75, - -66, -74, -77, -78, -86, -87, -90, -96, - -105, -115, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -116, -109, -102, -95, -89, -75, + -66, -74, -77, -78, -86, -87, -90, -96, + -105, -115, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -115, -108, -101, -94, -88, -66, - -56, -61, -70, -65, -78, -72, -83, -84, - -93, -98, -105, -110, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -115, -108, -101, -94, -88, -66, + -56, -61, -70, -65, -78, -72, -83, -84, + -93, -98, -105, -110, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -110, -105, -95, -89, -82, -57, - -52, -52, -59, -56, -59, -58, -69, -67, - -88, -82, -82, -89, -94, -100, -108, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -110, -105, -95, -89, -82, -57, + -52, -52, -59, -56, -59, -58, -69, -67, + -88, -82, -82, -89, -94, -100, -108, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -110, -101, -96, -90, -83, -77, -54, - -43, -38, -50, -48, -52, -48, -42, -42, - -51, -52, -53, -59, -65, -71, -78, -85, - -95, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}}, - /* 8000 Hz */ + -999, -110, -101, -96, -90, -83, -77, -54, + -43, -38, -50, -48, -52, -48, -42, -42, + -51, -52, -53, -59, -65, -71, -78, -85, + -95, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -120, -105, -86, -68, - -78, -79, -90, -100, -110, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -120, -105, -86, -68, + -78, -79, -90, -100, -110, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -120, -105, -86, -66, - -73, -77, -88, -96, -105, -115, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -120, -105, -86, -66, + -73, -77, -88, -96, -105, -115, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -120, -105, -92, -80, -61, - -64, -68, -80, -87, -92, -100, -110, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -120, -105, -92, -80, -61, + -64, -68, -80, -87, -92, -100, -110, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -120, -104, -91, -79, -52, - -60, -54, -64, -69, -77, -80, -82, -84, - -85, -87, -88, -90, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -120, -104, -91, -79, -52, + -60, -54, -64, -69, -77, -80, -82, -84, + -85, -87, -88, -90, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -118, -100, -87, -77, -49, - -50, -44, -58, -61, -61, -67, -65, -62, - -62, -62, -65, -68, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -118, -100, -87, -77, -49, + -50, -44, -58, -61, -61, -67, -65, -62, + -62, -62, -65, -68, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -115, -98, -84, -62, -49, - -44, -38, -46, -49, -49, -46, -39, -37, - -39, -40, -42, -43, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}}, - /* 11314 Hz */ + -999, -999, -999, -115, -98, -84, -62, -49, + -44, -38, -46, -49, -49, -46, -39, -37, + -39, -40, -42, -43, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -110, -88, -74, - -77, -82, -82, -85, -90, -94, -99, -104, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -999, -110, -88, -74, + -77, -82, -82, -85, -90, -94, -99, -104, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -110, -88, -66, - -70, -81, -80, -81, -84, -88, -91, -93, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -999, -110, -88, -66, + -70, -81, -80, -81, -84, -88, -91, -93, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -110, -88, -61, - -63, -70, -71, -74, -77, -80, -83, -85, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -999, -110, -88, -61, + -63, -70, -71, -74, -77, -80, -83, -85, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -110, -86, -62, - -63, -62, -62, -58, -52, -50, -50, -52, - -54, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -999, -110, -86, -62, + -63, -62, -62, -58, -52, -50, -50, -52, + -54, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -118, -108, -84, -53, - -50, -50, -50, -55, -47, -45, -40, -40, - -40, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -999, -118, -108, -84, -53, + -50, -50, -50, -55, -47, -45, -40, -40, + -40, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -118, -100, -73, -43, - -37, -42, -43, -53, -38, -37, -35, -35, - -38, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}}, - /* 16000 Hz */ + -999, -999, -999, -999, -118, -100, -73, -43, + -37, -42, -43, -53, -38, -37, -35, -35, + -38, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}}, {{-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -110, -100, -91, -84, -74, - -80, -80, -80, -80, -80, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -110, -100, -91, -84, -74, + -80, -80, -80, -80, -80, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -110, -100, -91, -84, -74, - -68, -68, -68, -68, -68, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -110, -100, -91, -84, -74, + -68, -68, -68, -68, -68, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -110, -100, -86, -78, -70, - -60, -45, -30, -21, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -110, -100, -86, -78, -70, + -60, -45, -30, -21, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -110, -100, -87, -78, -67, - -48, -38, -29, -21, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -110, -100, -87, -78, -67, + -48, -38, -29, -21, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -110, -100, -86, -69, -56, - -45, -35, -33, -29, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}, + -999, -999, -999, -110, -100, -86, -69, -56, + -45, -35, -33, -29, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}, {-999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -110, -100, -83, -71, -48, - -27, -38, -37, -34, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999}} + -999, -999, -999, -110, -100, -83, -71, -48, + -27, -38, -37, -34, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999}} }; #endif @@ -137850,32 +126454,32 @@ vorbis_look_psy_global *_vp_global_look(vorbis_info *vi){ void _vp_global_free(vorbis_look_psy_global *look){ if(look){ - memset(look,0,sizeof(*look)); - _ogg_free(look); + memset(look,0,sizeof(*look)); + _ogg_free(look); } } void _vi_gpsy_free(vorbis_info_psy_global *i){ if(i){ - memset(i,0,sizeof(*i)); - _ogg_free(i); + memset(i,0,sizeof(*i)); + _ogg_free(i); } } void _vi_psy_free(vorbis_info_psy *i){ if(i){ - memset(i,0,sizeof(*i)); - _ogg_free(i); + memset(i,0,sizeof(*i)); + _ogg_free(i); } } static void min_curve(float *c, - float *c2){ + float *c2){ int i; for(i=0;ic[i])c[i]=c2[i]; } @@ -137883,7 +126487,7 @@ static void max_curve(float *c, static void attenuate_curve(float *c,float att){ int i; for(i=0;iATH[j+k+ath_offset])min=ATH[j+k+ath_offset]; }else{ if(min>ATH[MAX_ATH-1])min=ATH[MAX_ATH-1]; } - ath[j]=min; - } + ath[j]=min; + } - /* copy curves into working space, replicate the 50dB curve to 30 - and 40, replicate the 100dB curve to 110 */ - for(j=0;j<6;j++) - memcpy(workc[i][j+2],tonemasks[i][j],EHMER_MAX*sizeof(*tonemasks[i][j])); - memcpy(workc[i][0],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0])); - memcpy(workc[i][1],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0])); + for(j=0;j<6;j++) + memcpy(workc[i][j+2],tonemasks[i][j],EHMER_MAX*sizeof(*tonemasks[i][j])); + memcpy(workc[i][0],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0])); + memcpy(workc[i][1],tonemasks[i][0],EHMER_MAX*sizeof(*tonemasks[i][0])); - /* apply centered curve boost/decay */ - for(j=0;j0)adj=0.; if(adj>0. && center_boost<0)adj=0.; workc[i][j][k]+=adj; - } - } + } + } - /* normalize curves so the driving amplitude is 0dB */ - /* make temp curves with the ATH overlayed */ - for(j=0;j an eighth of an octave and that the eighth - octave values may also be composited. */ + bin=floor(fromOC(i*.5)/binHz); + lo_curve= ceil(toOC(bin*binHz+1)*2); + hi_curve= floor(toOC((bin+1)*binHz)*2); + if(lo_curve>i)lo_curve=i; + if(lo_curve<0)lo_curve=0; + if(hi_curve>=P_BANDS)hi_curve=P_BANDS-1; - /* which octave curves will we be compositing? */ - bin=floor(fromOC(i*.5)/binHz); - lo_curve= ceil(toOC(bin*binHz+1)*2); - hi_curve= floor(toOC((bin+1)*binHz)*2); - if(lo_curve>i)lo_curve=i; - if(lo_curve<0)lo_curve=0; - if(hi_curve>=P_BANDS)hi_curve=P_BANDS-1; + for(m=0;mn)hi_bin=n; for(;lworkc[k][m][j]) - brute_buffer[l]=workc[k][m][j]; + if(brute_buffer[l]>workc[k][m][j]) + brute_buffer[l]=workc[k][m][j]; } for(;lworkc[k][m][EHMER_MAX-1]) - brute_buffer[l]=workc[k][m][EHMER_MAX-1]; + brute_buffer[l]=workc[k][m][EHMER_MAX-1]; - } + } - /* be equally paranoid about being valid up to next half ocatve */ - if(i+1n)hi_bin=n; for(;lworkc[k][m][j]) - brute_buffer[l]=workc[k][m][j]; + if(brute_buffer[l]>workc[k][m][j]) + brute_buffer[l]=workc[k][m][j]; } for(;lworkc[k][m][EHMER_MAX-1]) - brute_buffer[l]=workc[k][m][EHMER_MAX-1]; + brute_buffer[l]=workc[k][m][EHMER_MAX-1]; - } + } - for(j=0;j=n){ - ret[i][m][j+2]=-999.; + ret[i][m][j+2]=-999.; }else{ - ret[i][m][j+2]=brute_buffer[bin]; + ret[i][m][j+2]=brute_buffer[bin]; } } - } + } - /* add fenceposts */ - for(j=0;j-200.f)break; - ret[i][m][0]=j; + ret[i][m][0]=j; - for(j=EHMER_MAX-1;j>EHMER_OFFSET+1;j--) + for(j=EHMER_MAX-1;j>EHMER_OFFSET+1;j--) if(ret[i][m][j+2]>-200.f) break; - ret[i][m][1]=j; + ret[i][m][1]=j; - } + } } return(ret); @@ -138086,72 +126655,68 @@ void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi, p->n=n; p->rate=rate; - /* AoTuV HF weighting */ p->m_val = 1.; if(rate < 26000) p->m_val = 0; else if(rate < 38000) p->m_val = .94; /* 32kHz */ else if(rate > 46000) p->m_val = 1.275; /* 48kHz */ - /* set up the lookups for a given blocksize and sample rate */ - for(i=0,j=0;iath[j]=base+100.; - base+=delta; - } - } + int endpos=rint(fromOC((i+1)*.125-2.)*2*n/rate); + float base=ATH[i]; + if(jath[j]=base+100.; + base+=delta; + } + } } for(i=0;inoisewindowlominnoisewindowlominnoisewindowlo);lo++); - for(;hi<=n && (hinoisewindowhimin || + for(;hi<=n && (hinoisewindowhimin || toBARK(rate/(2*n)*hi)<(bark+vi->noisewindowhi));hi++); - p->bark[i]=((lo-1)<<16)+(hi-1); + p->bark[i]=((lo-1)<<16)+(hi-1); } for(i=0;ioctave[i]=toOC((i+.25f)*.5*rate/n)*(1<<(p->shiftoc+1))+.5f; + p->octave[i]=toOC((i+.25f)*.5*rate/n)*(1<<(p->shiftoc+1))+.5f; p->tonecurves=setup_tone_curves(vi->toneatt,rate*.5/n,n, vi->tone_centerboost,vi->tone_decay); - /* set up rolling noise median */ p->noiseoffset=(float**)_ogg_malloc(P_NOISECURVES*sizeof(*p->noiseoffset)); for(i=0;inoiseoffset[i]=(float*)_ogg_malloc(n*sizeof(**p->noiseoffset)); + p->noiseoffset[i]=(float*)_ogg_malloc(n*sizeof(**p->noiseoffset)); for(i=0;i=P_BANDS-1)halfoc=P_BANDS-1; - inthalfoc=(int)halfoc; - del=halfoc-inthalfoc; + if(halfoc<0)halfoc=0; + if(halfoc>=P_BANDS-1)halfoc=P_BANDS-1; + inthalfoc=(int)halfoc; + del=halfoc-inthalfoc; - for(j=0;jnoiseoffset[j][i]= + for(j=0;jnoiseoffset[j][i]= p->vi->noiseoff[j][inthalfoc]*(1.-del) + p->vi->noiseoff[j][inthalfoc+1]*del; } #if 0 { - static int ls=0; - _analysis_output_always("noiseoff0",ls,p->noiseoffset[0],n,1,0,0); - _analysis_output_always("noiseoff1",ls,p->noiseoffset[1],n,1,0,0); - _analysis_output_always("noiseoff2",ls++,p->noiseoffset[2],n,1,0,0); + static int ls=0; + _analysis_output_always("noiseoff0",ls,p->noiseoffset[0],n,1,0,0); + _analysis_output_always("noiseoff1",ls,p->noiseoffset[1],n,1,0,0); + _analysis_output_always("noiseoff2",ls++,p->noiseoffset[2],n,1,0,0); } #endif } @@ -138159,34 +126724,33 @@ void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi, void _vp_psy_clear(vorbis_look_psy *p){ int i,j; if(p){ - if(p->ath)_ogg_free(p->ath); - if(p->octave)_ogg_free(p->octave); - if(p->bark)_ogg_free(p->bark); - if(p->tonecurves){ - for(i=0;iath)_ogg_free(p->ath); + if(p->octave)_ogg_free(p->octave); + if(p->bark)_ogg_free(p->bark); + if(p->tonecurves){ + for(i=0;itonecurves[i][j]); } _ogg_free(p->tonecurves[i]); - } - _ogg_free(p->tonecurves); - } - if(p->noiseoffset){ - for(i=0;inoiseoffset[i]); - } - _ogg_free(p->noiseoffset); - } - memset(p,0,sizeof(*p)); + } + _ogg_free(p->tonecurves); + } + if(p->noiseoffset){ + for(i=0;inoiseoffset[i]); + } + _ogg_free(p->noiseoffset); + } + memset(p,0,sizeof(*p)); } } -/* octave/(8*eighth_octave_lines) x scale and dB y scale */ static void seed_curve(float *seed, - const float **curves, - float amp, - int oc, int n, - int linesper,float dBoffset){ + const float **curves, + float amp, + int oc, int n, + int linesper,float dBoffset){ int i,post1; int seedptr; const float *posts,*curve; @@ -138200,49 +126764,47 @@ static void seed_curve(float *seed, seedptr=oc+(posts[0]-EHMER_OFFSET)*linesper-(linesper>>1); for(i=posts[0];i0){ - float lin=amp+curve[i]; - if(seed[seedptr]=n)break; + if(seedptr>0){ + float lin=amp+curve[i]; + if(seed[seedptr]=n)break; } } static void seed_loop(vorbis_look_psy *p, - const float ***curves, - const float *f, - const float *flr, - float *seed, - float specmax){ + const float ***curves, + const float *f, + const float *flr, + float *seed, + float specmax){ vorbis_info_psy *vi=p->vi; long n=p->n,i; float dBoffset=vi->max_curve_dB-specmax; - /* prime the working vector with peak values */ - for(i=0;ioctave[i]; - while(i+1octave[i+1]==oc){ - i++; - if(f[i]>max)max=f[i]; - } + float max=f[i]; + long oc=p->octave[i]; + while(i+1octave[i+1]==oc){ + i++; + if(f[i]>max)max=f[i]; + } - if(max+6.f>flr[i]){ - oc=oc>>p->shiftoc; + if(max+6.f>flr[i]){ + oc=oc>>p->shiftoc; - if(oc>=P_BANDS)oc=P_BANDS-1; - if(oc<0)oc=0; + if(oc>=P_BANDS)oc=P_BANDS-1; + if(oc<0)oc=0; - seed_curve(seed, + seed_curve(seed, curves[oc], max, p->octave[i]-p->firstoc, p->total_octave_lines, p->eighth_octave_lines, dBoffset); - } + } } } @@ -138254,61 +126816,53 @@ static void seed_chase(float *seeds, int linesper, long n){ long i; for(i=0;i1 && ampstack[stack-1]<=ampstack[stack-2] && - i1 && ampstack[stack-1]<=ampstack[stack-2] && + iampstack[i]){ - endpos=posstack[i+1]; - }else{ - endpos=posstack[i]+linesper+1; /* +1 is important, else bin 0 is + long endpos; + if(iampstack[i]){ + endpos=posstack[i+1]; + }else{ + endpos=posstack[i]+linesper+1; /* +1 is important, else bin 0 is discarded in short frames */ - } - if(endpos>n)endpos=n; - for(;posn)endpos=n; + for(;pos static void max_seeds(vorbis_look_psy *p, - float *seed, - float *flr){ + float *seed, + float *flr){ long n=p->total_octave_lines; - int linesper=p->eighth_octave_lines; + int linesper=p->eighth_octave_lines; long linpos=0; long pos; @@ -138317,33 +126871,33 @@ static void max_seeds(vorbis_look_psy *p, pos=p->octave[0]-p->firstoc-(linesper>>1); while(linpos+1n){ - float minV=seed[pos]; - long end=((p->octave[linpos]+p->octave[linpos+1])>>1)-p->firstoc; - if(minV>p->vi->tone_abs_limit)minV=p->vi->tone_abs_limit; - while(pos+1<=end){ - pos++; - if((seed[pos]>NEGINF && seed[pos]octave[linpos]+p->octave[linpos+1])>>1)-p->firstoc; + if(minV>p->vi->tone_abs_limit)minV=p->vi->tone_abs_limit; + while(pos+1<=end){ + pos++; + if((seed[pos]>NEGINF && seed[pos]firstoc; - for(;linposn && p->octave[linpos]<=end;linpos++) - if(flr[linpos]firstoc; + for(;linposn && p->octave[linpos]<=end;linpos++) + if(flr[linpos]total_octave_lines-1]; - for(;linposn;linpos++) - if(flr[linpos]total_octave_lines-1]; + for(;linposn;linpos++) + if(flr[linpos]> 16; - if( lo>=0 ) break; - hi = b[i] & 0xffff; + lo = b[i] >> 16; + if( lo>=0 ) break; + hi = b[i] & 0xffff; - tN = N[hi] + N[-lo]; - tX = X[hi] - X[-lo]; - tXX = XX[hi] + XX[-lo]; - tY = Y[hi] + Y[-lo]; - tXY = XY[hi] - XY[-lo]; + tN = N[hi] + N[-lo]; + tX = X[hi] - X[-lo]; + tXX = XX[hi] + XX[-lo]; + tY = Y[hi] + Y[-lo]; + tXY = XY[hi] - XY[-lo]; - A = tY * tXX - tX * tXY; - B = tN * tXY - tX * tY; - D = tN * tXX - tX * tX; - R = (A + x * B) / D; - if (R < 0.f) - R = 0.f; + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; + if (R < 0.f) + R = 0.f; - noise[i] = R - offset; + noise[i] = R - offset; } for ( ;; i++, x += 1.f) { - lo = b[i] >> 16; - hi = b[i] & 0xffff; - if(hi>=n)break; + lo = b[i] >> 16; + hi = b[i] & 0xffff; + if(hi>=n)break; - tN = N[hi] - N[lo]; - tX = X[hi] - X[lo]; - tXX = XX[hi] - XX[lo]; - tY = Y[hi] - Y[lo]; - tXY = XY[hi] - XY[lo]; + tN = N[hi] - N[lo]; + tX = X[hi] - X[lo]; + tXX = XX[hi] - XX[lo]; + tY = Y[hi] - Y[lo]; + tXY = XY[hi] - XY[lo]; - A = tY * tXX - tX * tXY; - B = tN * tXY - tX * tY; - D = tN * tXX - tX * tX; - R = (A + x * B) / D; - if (R < 0.f) R = 0.f; + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; + if (R < 0.f) R = 0.f; - noise[i] = R - offset; + noise[i] = R - offset; } for ( ; i < n; i++, x += 1.f) { - R = (A + x * B) / D; - if (R < 0.f) R = 0.f; + R = (A + x * B) / D; + if (R < 0.f) R = 0.f; - noise[i] = R - offset; + noise[i] = R - offset; } if (fixed <= 0) return; for (i = 0, x = 0.f;; i++, x += 1.f) { - hi = i + fixed / 2; - lo = hi - fixed; - if(lo>=0)break; + hi = i + fixed / 2; + lo = hi - fixed; + if(lo>=0)break; - tN = N[hi] + N[-lo]; - tX = X[hi] - X[-lo]; - tXX = XX[hi] + XX[-lo]; - tY = Y[hi] + Y[-lo]; - tXY = XY[hi] - XY[-lo]; + tN = N[hi] + N[-lo]; + tX = X[hi] - X[-lo]; + tXX = XX[hi] + XX[-lo]; + tY = Y[hi] + Y[-lo]; + tXY = XY[hi] - XY[-lo]; - A = tY * tXX - tX * tXY; - B = tN * tXY - tX * tY; - D = tN * tXX - tX * tX; - R = (A + x * B) / D; + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; - if (R - offset < noise[i]) noise[i] = R - offset; + if (R - offset < noise[i]) noise[i] = R - offset; } for ( ;; i++, x += 1.f) { - hi = i + fixed / 2; - lo = hi - fixed; - if(hi>=n)break; + hi = i + fixed / 2; + lo = hi - fixed; + if(hi>=n)break; - tN = N[hi] - N[lo]; - tX = X[hi] - X[lo]; - tXX = XX[hi] - XX[lo]; - tY = Y[hi] - Y[lo]; - tXY = XY[hi] - XY[lo]; + tN = N[hi] - N[lo]; + tX = X[hi] - X[lo]; + tXX = XX[hi] - XX[lo]; + tY = Y[hi] - Y[lo]; + tXY = XY[hi] - XY[lo]; - A = tY * tXX - tX * tXY; - B = tN * tXY - tX * tY; - D = tN * tXX - tX * tX; - R = (A + x * B) / D; + A = tY * tXX - tX * tXY; + B = tN * tXY - tX * tY; + D = tN * tXX - tX * tX; + R = (A + x * B) / D; - if (R - offset < noise[i]) noise[i] = R - offset; + if (R - offset < noise[i]) noise[i] = R - offset; } for ( ; i < n; i++, x += 1.f) { - R = (A + x * B) / D; - if (R - offset < noise[i]) noise[i] = R - offset; + R = (A + x * B) / D; + if (R - offset < noise[i]) noise[i] = R - offset; } } @@ -138558,22 +127112,22 @@ static float FLOOR1_fromdB_INV_LOOKUP[256]={ }; void _vp_remove_floor(vorbis_look_psy *p, - float *mdct, - int *codedflr, - float *residue, - int sliding_lowpass){ + float *mdct, + int *codedflr, + float *residue, + int sliding_lowpass){ int i,n=p->n; if(sliding_lowpass>n)sliding_lowpass=n; for(i=0;ibark,logmdct,logmask, - 140.,-1); + 140.,-1); for(i=0;ibark,work,logmask,0., - p->vi->noisewindowfixed); + p->vi->noisewindowfixed); for(i=0;i=NOISE_COMPAND_LEVELS)dB=NOISE_COMPAND_LEVELS-1; - if(dB<0)dB=0; - logmask[i]= work[i]+p->vi->noisecompand[dB]; + int dB=logmask[i]+.5; + if(dB>=NOISE_COMPAND_LEVELS)dB=NOISE_COMPAND_LEVELS-1; + if(dB<0)dB=0; + logmask[i]= work[i]+p->vi->noisecompand[dB]; } } @@ -138636,14 +127190,11 @@ void _vp_tonemask(vorbis_look_psy *p, float att=local_specmax+p->vi->ath_adjatt; for(i=0;itotal_octave_lines;i++)seed[i]=NEGINF; - /* set the ATH (floating below localmax, not global max by a - specified att) */ if(attvi->ath_maxatt)att=p->vi->ath_maxatt; for(i=0;iath[i]+att; + logmask[i]=p->ath[i]+att; - /* tone masking */ seed_loop(p,(const float ***)p->tonecurves,logfft,logmask,seed,global_specmax); max_seeds(p,seed,logmask); @@ -138663,46 +127214,26 @@ void _vp_offset_and_mix(vorbis_look_psy *p, cx = p->m_val; for(i=0;inoiseoffset[offset_select][i]; - if(val>p->vi->noisemaxsupp)val=p->vi->noisemaxsupp; - logmask[i]=max(val,tone[i]+toneatt); + float val= noise[i]+p->noiseoffset[offset_select][i]; + if(val>p->vi->noisemaxsupp)val=p->vi->noisemaxsupp; + logmask[i]=max(val,tone[i]+toneatt); - /* AoTuV */ - /** @ M1 ** - The following codes improve a noise problem. - A fundamental idea uses the value of masking and carries out - the relative compensation of the MDCT. - However, this code is not perfect and all noise problems cannot be solved. - by Aoyumi @ 2004/04/18 - */ + if(offset_select == 1) { + coeffi = -17.2; /* coeffi is a -17.2dB threshold */ + val = val - logmdct[i]; /* val == mdct line value relative to floor in dB */ - if(offset_select == 1) { - coeffi = -17.2; /* coeffi is a -17.2dB threshold */ - val = val - logmdct[i]; /* val == mdct line value relative to floor in dB */ - - if(val > coeffi){ - /* mdct value is > -17.2 dB below floor */ + if(val > coeffi){ de = 1.0-((val-coeffi)*0.005*cx); - /* pro-rated attenuation: - -0.00 dB boost if mdct value is -17.2dB (relative to floor) - -0.77 dB boost if mdct value is 0dB (relative to floor) - -1.64 dB boost if mdct value is +17.2dB (relative to floor) - etc... */ if(de < 0) de = 0.0001; - }else - /* mdct value is <= -17.2 dB below floor */ + }else de = 1.0-((val-coeffi)*0.0003*cx); - /* pro-rated attenuation: - +0.00 dB atten if mdct value is -17.2dB (relative to floor) - +0.45 dB atten if mdct value is -34.4dB (relative to floor) - etc... */ - mdct[i] *= de; + mdct[i] *= de; - } + } } } @@ -138720,22 +127251,22 @@ float _vp_ampmax_decay(float amp,vorbis_dsp_state *vd){ } static void couple_lossless(float A, float B, - float *qA, float *qB){ + float *qA, float *qB){ int test1=fabs(*qA)>fabs(*qB); test1-= fabs(*qA)fabs(B))<<1)-1; if(test1==1){ - *qB=(*qA>0.f?*qA-*qB:*qB-*qA); + *qB=(*qA>0.f?*qA-*qB:*qB-*qA); }else{ - float temp=*qB; - *qB=(*qB>0.f?*qA-*qB:*qB-*qA); - *qA=temp; + float temp=*qB; + *qB=(*qB>0.f?*qA-*qB:*qB-*qA); + *qA=temp; } if(*qB>fabs(*qA)*1.9999f){ - *qB= -fabs(*qA)*2.f; - *qA= -*qA; + *qB= -fabs(*qA)*2.f; + *qA= -*qA; } } @@ -138750,8 +127281,8 @@ static float hypot_lookup[32]={ -0.229718, -0.249913, -0.271001, -0.292893}; static void precomputed_couple_point(float premag, - int floorA,int floorB, - float *mag, float *ang){ + int floorA,int floorB, + float *mag, float *ang){ int test=(floorA>floorB)-1; int offset=31-abs(floorA-floorB); @@ -138763,17 +127294,11 @@ static void precomputed_couple_point(float premag, *ang=0.f; } -/* just like below, this is currently set up to only do - single-step-depth coupling. Otherwise, we'd have to do more - copying (which will be inevitable later) */ - -/* doing the real circular magnitude calculation is audibly superior - to (A+B)/sqrt(2) */ static float dipole_hypot(float a, float b){ if(a>0.){ - if(b>0.)return sqrt(a*a+b*b); - if(a>-b)return sqrt(a*a-b*b); - return -sqrt(b*b-a*a); + if(b>0.)return sqrt(a*a+b*b); + if(a>-b)return sqrt(a*a-b*b); + return -sqrt(b*b-a*a); } if(b<0.)return -sqrt(a*a+b*b); if(-a>b)return -sqrt(a*a-b*b); @@ -138781,16 +127306,15 @@ static float dipole_hypot(float a, float b){ } static float round_hypot(float a, float b){ if(a>0.){ - if(b>0.)return sqrt(a*a+b*b); - if(a>-b)return sqrt(a*a+b*b); - return -sqrt(b*b+a*a); + if(b>0.)return sqrt(a*a+b*b); + if(a>-b)return sqrt(a*a+b*b); + return -sqrt(b*b+a*a); } if(b<0.)return -sqrt(a*a+b*b); if(-a>b)return -sqrt(a*a+b*b); return sqrt(b*b+a*a); } -/* revert to round hypot for now */ float **_vp_quantize_couple_memo(vorbis_block *vb, vorbis_info_psy_global *g, vorbis_look_psy *p, @@ -138802,19 +127326,18 @@ float **_vp_quantize_couple_memo(vorbis_block *vb, int limit=g->coupling_pointlimit[p->vi->blockflag][PACKETBLOBS/2]; for(i=0;icoupling_steps;i++){ - float *mdctM=mdct[vi->coupling_mag[i]]; - float *mdctA=mdct[vi->coupling_ang[i]]; - ret[i]=(float*) _vorbis_block_alloc(vb,n*sizeof(**ret)); - for(j=0;jcoupling_mag[i]]; + float *mdctA=mdct[vi->coupling_ang[i]]; + ret[i]=(float*) _vorbis_block_alloc(vb,n*sizeof(**ret)); + for(j=0;jvi->normal_point_p){ - int i,j,k,n=p->n; - int **ret=(int**) _vorbis_block_alloc(vb,vi->coupling_steps*sizeof(*ret)); - int partition=p->vi->normal_partition; - float **work=(float**) alloca(sizeof(*work)*partition); + int i,j,k,n=p->n; + int **ret=(int**) _vorbis_block_alloc(vb,vi->coupling_steps*sizeof(*ret)); + int partition=p->vi->normal_partition; + float **work=(float**) alloca(sizeof(*work)*partition); - for(i=0;icoupling_steps;i++){ - ret[i]=(int*) _vorbis_block_alloc(vb,n*sizeof(**ret)); + for(i=0;icoupling_steps;i++){ + ret[i]=(int*) _vorbis_block_alloc(vb,n*sizeof(**ret)); - for(j=0;jn; vorbis_info_psy *vi=p->vi; int partition=vi->normal_partition; @@ -138855,12 +127378,12 @@ void _vp_noise_normalize_sort(vorbis_look_psy *p, int start=vi->normal_start; for(j=start;jn)partition=n-j; - for(i=0;in)partition=n-j; + for(i=0;in)start=n; if(vi->normal_channel_p){ - for(;j=.25f){ @@ -138896,17 +127419,17 @@ void _vp_noise_normalize(vorbis_look_psy *p, out[k]=unitnorm(in[k]); acc-=1.; } - } + } - for(;in; - /* perform any requested channel coupling */ - /* point stereo can only be used in a first stage (in this encoder) - because of the dependency on floor lookups */ for(i=0;icoupling_steps;i++){ - /* once we're doing multistage coupling in which a channel goes - through more than one coupling step, the floor vector - magnitudes will also have to be recalculated an propogated - along with PCM. Right now, we're not (that will wait until 5.1 - most likely), so the code isn't here yet. The memory management - here is all assuming single depth couplings anyway. */ + if(nonzero[vi->coupling_mag[i]] || + nonzero[vi->coupling_ang[i]]){ - /* make sure coupling a zero and a nonzero channel results in two - nonzero channels. */ - if(nonzero[vi->coupling_mag[i]] || - nonzero[vi->coupling_ang[i]]){ + float *rM=res[vi->coupling_mag[i]]; + float *rA=res[vi->coupling_ang[i]]; + float *qM=rM+n; + float *qA=rA+n; + int *floorM=ifloor[vi->coupling_mag[i]]; + int *floorA=ifloor[vi->coupling_ang[i]]; + float prepoint=stereo_threshholds[g->coupling_prepointamp[blobno]]; + float postpoint=stereo_threshholds[g->coupling_postpointamp[blobno]]; + int partition=(p->vi->normal_point_p?p->vi->normal_partition:p->n); + int limit=g->coupling_pointlimit[p->vi->blockflag][blobno]; + int pointlimit=limit; - float *rM=res[vi->coupling_mag[i]]; - float *rA=res[vi->coupling_ang[i]]; - float *qM=rM+n; - float *qA=rA+n; - int *floorM=ifloor[vi->coupling_mag[i]]; - int *floorA=ifloor[vi->coupling_ang[i]]; - float prepoint=stereo_threshholds[g->coupling_prepointamp[blobno]]; - float postpoint=stereo_threshholds[g->coupling_postpointamp[blobno]]; - int partition=(p->vi->normal_point_p?p->vi->normal_partition:p->n); - int limit=g->coupling_pointlimit[p->vi->blockflag][blobno]; - int pointlimit=limit; + nonzero[vi->coupling_mag[i]]=1; + nonzero[vi->coupling_ang[i]]=1; - nonzero[vi->coupling_mag[i]]=1; - nonzero[vi->coupling_ang[i]]=1; + if(n > 1000) + postpoint=stereo_threshholds_limited[g->coupling_postpointamp[blobno]]; - /* The threshold of a stereo is changed with the size of n */ - if(n > 1000) - postpoint=stereo_threshholds_limited[g->coupling_postpointamp[blobno]]; - - for(j=0;jn;j+=partition){ + for(j=0;jn;j+=partition){ float acc=0.f; for(k=0;k=limit && fabs(rM[l])=limit && fabs(rM[l])vi->normal_point_p){ for(k=0;k=p->vi->normal_thresh;k++){ - int l=mag_sort[i][j+k]; - if(l=pointlimit && rint(qM[l])==0.f){ - qM[l]=unitnorm(qM[l]); - acc-=1.f; - } + int l=mag_sort[i][j+k]; + if(l=pointlimit && rint(qM[l])==0.f){ + qM[l]=unitnorm(qM[l]); + acc-=1.f; + } + } + } } } - } - } } } -/* AoTuV */ -/** @ M2 ** - The boost problem by the combination of noise normalization and point stereo is eased. - However, this is a temporary patch. - by Aoyumi @ 2004/04/18 -*/ - void hf_reduction(vorbis_info_psy_global *g, - vorbis_look_psy *p, - vorbis_info_mapping0 *vi, - float **mdct){ + vorbis_look_psy *p, + vorbis_info_mapping0 *vi, + float **mdct){ int i,j,n=p->n, de=0.3*p->m_val; int limit=g->coupling_pointlimit[p->vi->blockflag][PACKETBLOBS/2]; for(i=0; icoupling_steps; i++){ - /* for(j=start; jparts;j++){ - /*fprintf(stderr,"partition %d: ",j);*/ + { + int j,k,l; + for(j=0;jparts;j++){ for(k=0;k<8;k++) if(look->training_data[k][j]){ - char buffer[80]; - FILE *of; - codebook *statebook=look->partbooks[j][k]; + char buffer[80]; + FILE *of; + codebook *statebook=look->partbooks[j][k]; - /* long and short into the same bucket by current convention */ sprintf(buffer,"res_part%d_pass%d.vqd",j,k); of=fopen(buffer,"a"); - for(l=0;lentries;l++) + for(l=0;lentries;l++) fprintf(of,"%d:%ld\n",l,look->training_data[k][j][l]); - fclose(of); + fclose(of); - /*fprintf(stderr,"%d(%.2f|%.2f) ",k, - look->training_min[k][j],look->training_max[k][j]);*/ - - _ogg_free(look->training_data[k][j]); - look->training_data[k][j]=NULL; + _ogg_free(look->training_data[k][j]); + look->training_data[k][j]=NULL; } - /*fprintf(stderr,"\n");*/ - } - } - fprintf(stderr,"min/max residue: %g::%g\n",look->tmin,look->tmax); + } + } + fprintf(stderr,"min/max residue: %g::%g\n",look->tmin,look->tmax); - /*fprintf(stderr,"residue bit usage %f:%f (%f total)\n", - (float)look->phrasebits/look->frames, - (float)look->postbits/look->frames, - (float)(look->postbits+look->phrasebits)/look->frames);*/ #endif - /*vorbis_info_residue0 *info=look->info; + for(j=0;jparts;j++) + if(look->partbooks[j])_ogg_free(look->partbooks[j]); + _ogg_free(look->partbooks); + for(j=0;jpartvals;j++) + _ogg_free(look->decodemap[j]); + _ogg_free(look->decodemap); - fprintf(stderr, - "%ld frames encoded in %ld phrasebits and %ld residue bits " - "(%g/frame) \n",look->frames,look->phrasebits, - look->resbitsflat, - (look->phrasebits+look->resbitsflat)/(float)look->frames); - - for(j=0;jparts;j++){ - long acc=0; - fprintf(stderr,"\t[%d] == ",j); - for(k=0;kstages;k++) - if((info->secondstages[j]>>k)&1){ - fprintf(stderr,"%ld,",look->resbits[j][k]); - acc+=look->resbits[j][k]; - } - - fprintf(stderr,":: (%ld vals) %1.2fbits/sample\n",look->resvals[j], - acc?(float)acc/(look->resvals[j]*info->grouping):0); - } - fprintf(stderr,"\n");*/ - - for(j=0;jparts;j++) - if(look->partbooks[j])_ogg_free(look->partbooks[j]); - _ogg_free(look->partbooks); - for(j=0;jpartvals;j++) - _ogg_free(look->decodemap[j]); - _ogg_free(look->decodemap); - - memset(look,0,sizeof(*look)); - _ogg_free(look); + memset(look,0,sizeof(*look)); + _ogg_free(look); } } static int icount(unsigned int v){ int ret=0; while(v){ - ret+=v&1; - v>>=1; + ret+=v&1; + v>>=1; } return(ret); } @@ -139216,33 +127679,28 @@ void res0_pack(vorbis_info_residue *vr,oggpack_buffer *opb){ oggpack_write(opb,info->end,24); oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and - code with a partitioned book */ + code with a partitioned book */ oggpack_write(opb,info->partitions-1,6); /* possible partition choices */ oggpack_write(opb,info->groupbook,8); /* group huffman book */ - /* secondstages is a bitmask; as encoding progresses pass by pass, a - bitmask of one indicates this partition class has bits to write - this pass */ for(j=0;jpartitions;j++){ - if(ilog(info->secondstages[j])>3){ - /* yes, this is a minor hack due to not thinking ahead */ - oggpack_write(opb,info->secondstages[j],3); - oggpack_write(opb,1,1); - oggpack_write(opb,info->secondstages[j]>>3,5); - }else - oggpack_write(opb,info->secondstages[j],4); /* trailing zero */ - acc+=icount(info->secondstages[j]); + if(ilog(info->secondstages[j])>3){ + oggpack_write(opb,info->secondstages[j],3); + oggpack_write(opb,1,1); + oggpack_write(opb,info->secondstages[j]>>3,5); + }else + oggpack_write(opb,info->secondstages[j],4); /* trailing zero */ + acc+=icount(info->secondstages[j]); } for(j=0;jbooklist[j],8); + oggpack_write(opb,info->booklist[j],8); } -/* vorbis_info is for range checking */ vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ int j,acc=0; vorbis_info_residue0 *info=(vorbis_info_residue0*) _ogg_calloc(1,sizeof(*info)); - codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; info->begin=oggpack_read(opb,24); info->end=oggpack_read(opb,24); @@ -139251,19 +127709,19 @@ vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ info->groupbook=oggpack_read(opb,8); for(j=0;jpartitions;j++){ - int cascade=oggpack_read(opb,3); - if(oggpack_read(opb,1)) - cascade|=(oggpack_read(opb,5)<<3); - info->secondstages[j]=cascade; + int cascade=oggpack_read(opb,3); + if(oggpack_read(opb,1)) + cascade|=(oggpack_read(opb,5)<<3); + info->secondstages[j]=cascade; - acc+=icount(cascade); + acc+=icount(cascade); } for(j=0;jbooklist[j]=oggpack_read(opb,8); + info->booklist[j]=oggpack_read(opb,8); if(info->groupbook>=ci->books)goto errout; for(j=0;jbooklist[j]>=ci->books)goto errout; + if(info->booklist[j]>=ci->books)goto errout; return(info); errout: @@ -139272,10 +127730,10 @@ vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ } vorbis_look_residue *res0_look(vorbis_dsp_state *vd, - vorbis_info_residue *vr){ + vorbis_info_residue *vr){ vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; vorbis_look_residue0 *look=(vorbis_look_residue0 *)_ogg_calloc(1,sizeof(*look)); - codec_setup_info *ci=(codec_setup_info*)vd->vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vd->vi->codec_setup; int j,k,acc=0; int dim; @@ -139290,11 +127748,11 @@ vorbis_look_residue *res0_look(vorbis_dsp_state *vd, look->partbooks=(codebook***)_ogg_calloc(look->parts,sizeof(*look->partbooks)); for(j=0;jparts;j++){ - int stages=ilog(info->secondstages[j]); - if(stages){ - if(stages>maxstage)maxstage=stages; - look->partbooks[j]=(codebook**) _ogg_calloc(stages,sizeof(*look->partbooks[j])); - for(k=0;ksecondstages[j]); + if(stages){ + if(stages>maxstage)maxstage=stages; + look->partbooks[j]=(codebook**) _ogg_calloc(stages,sizeof(*look->partbooks[j])); + for(k=0;ksecondstages[j]&(1<partbooks[j][k]=ci->fullbooks+info->booklist[acc++]; #ifdef TRAIN_RES @@ -139302,68 +127760,65 @@ vorbis_look_residue *res0_look(vorbis_dsp_state *vd, sizeof(***look->training_data)); #endif } - } + } } look->partvals=rint(pow((float)look->parts,(float)dim)); look->stages=maxstage; look->decodemap=(int**)_ogg_malloc(look->partvals*sizeof(*look->decodemap)); for(j=0;jpartvals;j++){ - long val=j; - long mult=look->partvals/look->parts; - look->decodemap[j]=(int*)_ogg_malloc(dim*sizeof(*look->decodemap[j])); - for(k=0;kparts; - look->decodemap[j][k]=deco; - } + long val=j; + long mult=look->partvals/look->parts; + look->decodemap[j]=(int*)_ogg_malloc(dim*sizeof(*look->decodemap[j])); + for(k=0;kparts; + look->decodemap[j][k]=deco; + } } #if defined(TRAIN_RES) || defined (TRAIN_RESAUX) { - static int train_seq=0; - look->train_seq=train_seq++; + static int train_seq=0; + look->train_seq=train_seq++; } #endif return(look); } -/* break an abstraction and copy some code for performance purposes */ static int local_book_besterror(codebook *book,float *a){ int dim=book->dim,i,k,o; int best=0; encode_aux_threshmatch *tt=book->c->thresh_tree; - /* find the quant val of each scalar */ for(k=0,o=dim;kthreshvals>>1; + float val=a[--o]; + i=tt->threshvals>>1; - if(valquantthresh[i]){ - if(valquantthresh[i-1]){ + if(valquantthresh[i]){ + if(valquantthresh[i-1]){ for(--i;i>0;--i) if(val>=tt->quantthresh[i-1]) - break; - } - }else{ + break; + } + }else{ - for(++i;ithreshvals-1;++i) + for(++i;ithreshvals-1;++i) if(valquantthresh[i])break; - } + } - best=(best*tt->quantvals)+tt->quantmap[i]; + best=(best*tt->quantvals)+tt->quantmap[i]; } - /* regular lattices are easy :-) */ if(book->c->lengthlist[best]<=0){ - const static_codebook *c=book->c; - int i,j; - float bestf=0.f; - float *e=book->valuelist; - best=-1; - for(i=0;ientries;i++){ - if(c->lengthlist[i]>0){ + const static_codebook *c=book->c; + int i,j; + float bestf=0.f; + float *e=book->valuelist; + best=-1; + for(i=0;ientries;i++){ + if(c->lengthlist[i]>0){ float thisx=0.f; for(j=0;jvaluelist+best*dim; - for(i=0;ivaluelist+best*dim; + for(i=0;idim; int step=n/dim; for(i=0;iinfo; - /* move all this setup out later */ int samples_per_partition=info->grouping; int possible_partitions=info->partitions; int n=info->end-info->begin; @@ -139421,48 +127875,44 @@ static long **_01class(vorbis_block *vb,vorbis_look_residue *vl, long **partword=(long**)_vorbis_block_alloc(vb,ch*sizeof(*partword)); float scale=100./samples_per_partition; - /* we find the partition type for each partition of each - channel. We'll go back and do the interleaved encoding in a - bit. For now, clarity */ - for(i=0;ibegin; - for(j=0;jbegin; + for(j=0;jmax)max=fabs(in[j][offset+k]); ent+=fabs(rint(in[j][offset+k])); - } - ent*=scale; + } + ent*=scale; - for(k=0;kclassmetric1[k] && (info->classmetric2[k]<0 || (int)entclassmetric2[k])) break; - partword[j][i]=k; - } + partword[j][i]=k; + } } #ifdef TRAIN_RESAUX { - FILE *of; - char buffer[80]; + FILE *of; + char buffer[80]; - for(i=0;itrain_seq); - of=fopen(buffer,"a"); - for(j=0;jtrain_seq); + of=fopen(buffer,"a"); + for(j=0;jframes++; @@ -139470,16 +127920,12 @@ static long **_01class(vorbis_block *vb,vorbis_look_residue *vl, return(partword); } -/* designed for stereo or other modes where the partition size is an - integer multiple of the number of channels encoded in the current - submap */ static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,float **in, - int ch){ + int ch){ long i,j,k,l; vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; vorbis_info_residue0 *info=look->info; - /* move all this setup out later */ int samples_per_partition=info->grouping; int possible_partitions=info->partitions; int n=info->end-info->begin; @@ -139496,21 +127942,21 @@ static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,float **in, memset(partword[0],0,n*ch/samples_per_partition*sizeof(*partword[0])); for(i=0,l=info->begin/ch;imagmax)magmax=fabs(in[0][l]); - for(k=1;kmagmax)magmax=fabs(in[0][l]); + for(k=1;kangmax)angmax=fabs(in[k][l]); - l++; - } + l++; + } - for(j=0;jclassmetric1[j] && + for(j=0;jclassmetric1[j] && angmax<=info->classmetric2[j]) break; - partword[0][i]=j; + partword[0][i]=j; } @@ -139518,7 +127964,7 @@ static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,float **in, sprintf(buffer,"resaux_%d.vqd",look->train_seq); of=fopen(buffer,"a"); for(i=0;iinfo; - /* move all this setup out later */ int samples_per_partition=info->grouping; int possible_partitions=info->partitions; int partitions_per_word=look->phrasebook->dim; @@ -139550,109 +127995,87 @@ static int _01forward(oggpack_buffer *opb, #ifdef TRAIN_RES for(i=0;ibegin;jend;j++){ - if(in[i][j]>look->tmax)look->tmax=in[i][j]; - if(in[i][j]tmin)look->tmin=in[i][j]; - } + for(j=info->begin;jend;j++){ + if(in[i][j]>look->tmax)look->tmax=in[i][j]; + if(in[i][j]tmin)look->tmin=in[i][j]; + } #endif memset(resbits,0,sizeof(resbits)); memset(resvals,0,sizeof(resvals)); - /* we code the partition words for each channel, then the residual - words for a partition per channel until we've written all the - residual words for that partition word. Then write the next - partition channel words... */ - for(s=0;sstages;s++){ - for(i=0;iphrasebook->entries) - look->phrasebits+=vorbis_book_encode(look->phrasebook,val,opb); + look->phrasebits+=vorbis_book_encode(look->phrasebook,val,opb); #if 0 /*def TRAIN_RES*/ else fprintf(stderr,"!"); #endif } - } + } - /* now we encode interleaved residual values for the partitions */ - for(k=0;kbegin; for(j=0;jsecondstages[partword[j][i]]&(1<partbooks[partword[j][i]][s]; - if(statebook){ - int ret; - long *accumulator=NULL; + codebook *statebook=look->partbooks[partword[j][i]][s]; + if(statebook){ + int ret; + long *accumulator=NULL; #ifdef TRAIN_RES - accumulator=look->training_data[s][partword[j][i]]; - { + accumulator=look->training_data[s][partword[j][i]]; + { int l; float *samples=in[j]+offset; for(l=0;ltraining_min[s][partword[j][i]]) - look->training_min[s][partword[j][i]]=samples[l]; + look->training_min[s][partword[j][i]]=samples[l]; if(samples[l]>look->training_max[s][partword[j][i]]) - look->training_max[s][partword[j][i]]=samples[l]; + look->training_max[s][partword[j][i]]=samples[l]; } - } + } #endif - ret=encode(opb,in[j]+offset,samples_per_partition, + ret=encode(opb,in[j]+offset,samples_per_partition, statebook,accumulator); - look->postbits+=ret; - resbits[partword[j][i]]+=ret; - } + look->postbits+=ret; + resbits[partword[j][i]]+=ret; + } + } + } } } - } - } } - /*{ - long total=0; - long totalbits=0; - fprintf(stderr,"%d :: ",vb->mode); - for(k=0;kinfo; - /* move all this setup out later */ int samples_per_partition=info->grouping; int partitions_per_word=look->phrasebook->dim; int n=info->end-info->begin; @@ -139662,36 +128085,32 @@ static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl, int ***partword=(int***)alloca(ch*sizeof(*partword)); for(j=0;jstages;s++){ - /* each loop decodes on partition codeword containing - partitions_pre_word partitions */ - for(i=0,l=0;iphrasebook,&vb->opb); if(temp==-1)goto eopbreak; partword[j][l]=look->decodemap[temp]; if(partword[j][l]==NULL)goto errout; } - } + } - /* now we decode residual values for the partitions */ - for(k=0;kbegin+i*samples_per_partition; if(info->secondstages[partword[j][l][k]]&(1<partbooks[partword[j][l][k]][s]; - if(stagebook){ - if(decodepart(stagebook,in[j]+offset,&vb->opb, - samples_per_partition)==-1)goto eopbreak; - } + codebook *stagebook=look->partbooks[partword[j][l][k]][s]; + if(stagebook){ + if(decodepart(stagebook,in[j]+offset,&vb->opb, + samples_per_partition)==-1)goto eopbreak; + } } } - } + } } errout: @@ -139700,49 +128119,44 @@ static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl, } #if 0 -/* residue 0 and 1 are just slight variants of one another. 0 is - interleaved, 1 is not */ long **res0_class(vorbis_block *vb,vorbis_look_residue *vl, float **in,int *nonzero,int ch){ - /* we encode only the nonzero parts of a bundle */ int i,used=0; for(i=0;ipcmend/2; for(i=0;ipcmend/2; for(i=0;ipcmend/2,used=0; - /* don't duplicate the code; use a working vector hack for now and - reshape ourselves into a single channel res1 */ - /* ugly; reallocs for each coupling pass :-( */ float *work=(float*)_vorbis_block_alloc(vb,ch*n*sizeof(*work)); for(i=0;iinfo; - /* move all this setup out later */ int samples_per_partition=info->grouping; int partitions_per_word=look->phrasebook->dim; int n=info->end-info->begin; @@ -139881,29 +128286,27 @@ int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, if(i==ch)return(0); /* no nonzero vectors */ for(s=0;sstages;s++){ - for(i=0,l=0;iphrasebook,&vb->opb); if(temp==-1)goto eopbreak; partword[l]=look->decodemap[temp]; if(partword[l]==NULL)goto errout; - } + } - /* now we decode residual values for the partitions */ - for(k=0;ksecondstages[partword[l][k]]&(1<partbooks[partword[l][k]][s]; if(stagebook){ - if(vorbis_book_decodevv_add(stagebook,in, + if(vorbis_book_decodevv_add(stagebook,in, i*samples_per_partition+info->begin,ch, &vb->opb,samples_per_partition)==-1) - goto eopbreak; + goto eopbreak; } } - } + } } errout: @@ -139964,32 +128367,26 @@ vorbis_func_residue residue2_exportbundle={ #include #include -/**** pack/unpack helpers ******************************************/ int _ilog(unsigned int v){ int ret=0; while(v){ - ret++; - v>>=1; + ret++; + v>>=1; } return(ret); } -/* 32 bit float (not IEEE; nonnormalized mantissa + - biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm - Why not IEEE? It's just not that important here. */ - #define VQ_FEXP 10 #define VQ_FMAN 21 #define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */ -/* doesn't currently guard under/overflow */ long _float32_pack(float val){ int sign=0; long exp; long mant; if(val<0){ - sign=0x80000000; - val= -val; + sign=0x80000000; + val= -val; } exp= floor(log(val)/log(2.f)); mant=rint(ldexp(val,(VQ_FMAN-1)-exp)); @@ -140000,15 +128397,12 @@ long _float32_pack(float val){ float _float32_unpack(long val){ double mant=val&0x1fffff; - int sign=val&0x80000000; + int sign=val&0x80000000; long exp =(val&0x7fe00000L)>>VQ_FMAN; if(sign)mant= -mant; return(ldexp(mant,exp-(VQ_FMAN-1)-VQ_FEXP_BIAS)); } -/* given a list of word lengths, generate a list of codewords. Works - for length ordered or unordered, always assigns the lowest valued - codewords first. Extended to handle unused entries (length 0) */ ogg_uint32_t *_make_words(long *l,long n,long sparsecount){ long i,j,count=0; ogg_uint32_t marker[33]; @@ -140016,207 +128410,168 @@ ogg_uint32_t *_make_words(long *l,long n,long sparsecount){ memset(marker,0,sizeof(marker)); for(i=0;i0){ - ogg_uint32_t entry=marker[length]; + long length=l[i]; + if(length>0){ + ogg_uint32_t entry=marker[length]; - /* when we claim a node for an entry, we also claim the nodes - below it (pruning off the imagined tree that may have dangled - from it) as well as blocking the use of any nodes directly - above for leaves */ - - /* update ourself */ - if(length<32 && (entry>>length)){ - /* error condition; the lengths must specify an overpopulated tree */ + if(length<32 && (entry>>length)){ _ogg_free(r); return(NULL); - } - r[count++]=entry; + } + r[count++]=entry; - /* Look to see if the next shorter marker points to the node - above. if so, update it and repeat. */ - { + { for(j=length;j>0;j--){ if(marker[j]&1){ - /* have to jump branches */ - if(j==1) - marker[1]++; - else - marker[j]=marker[j-1]<<1; - break; /* invariant says next upper marker would already - have been moved if it was on the same path */ + if(j==1) + marker[1]++; + else + marker[j]=marker[j-1]<<1; + break; /* invariant says next upper marker would already + have been moved if it was on the same path */ } marker[j]++; } - } + } - /* prune the tree; the implicit invariant says all the longer - markers were dangling from our just-taken node. Dangle them - from our *new* node. */ - for(j=length+1;j<33;j++) + for(j=length+1;j<33;j++) if((marker[j]>>1) == entry){ entry=marker[j]; marker[j]=marker[j-1]<<1; }else break; - }else - if(sparsecount==0)count++; + }else + if(sparsecount==0)count++; } - /* bitreverse the words because our bitwise packer/unpacker is LSb - endian */ for(i=0,count=0;i>j)&1; - } + ogg_uint32_t temp=0; + for(j=0;j>j)&1; + } - if(sparsecount){ - if(l[i]) + if(sparsecount){ + if(l[i]) r[count++]=temp; - }else - r[count++]=temp; + }else + r[count++]=temp; } return(r); } -/* there might be a straightforward one-line way to do the below - that's portable and totally safe against roundoff, but I haven't - thought of it. Therefore, we opt on the side of caution */ long _book_maptype1_quantvals(const static_codebook *b){ long vals=floor(pow((float)b->entries,1.f/b->dim)); - /* the above *should* be reliable, but we'll not assume that FP is - ever reliable when bitstream sync is at stake; verify via integer - means that vals really is the greatest value of dim for which - vals^b->bim <= b->entries */ - /* treat the above as an initial guess */ while(1){ - long acc=1; - long acc1=1; - int i; - for(i=0;idim;i++){ - acc*=vals; - acc1*=vals+1; - } - if(acc<=b->entries && acc1>b->entries){ - return(vals); - }else{ - if(acc>b->entries){ + long acc=1; + long acc1=1; + int i; + for(i=0;idim;i++){ + acc*=vals; + acc1*=vals+1; + } + if(acc<=b->entries && acc1>b->entries){ + return(vals); + }else{ + if(acc>b->entries){ vals--; - }else{ + }else{ vals++; - } - } + } + } } } -/* unpack the quantized list of values for encode/decode ***********/ -/* we need to deal with two map types: in map type 1, the values are - generated algorithmically (each column of the vector counts through - the values in the quant vector). in map type 2, all the values came - in in an explicit list. Both value lists must be unpacked */ float *_book_unquantize(const static_codebook *b,int n,int *sparsemap){ long j,k,count=0; if(b->maptype==1 || b->maptype==2){ - int quantvals; - float mindel=_float32_unpack(b->q_min); - float delta=_float32_unpack(b->q_delta); - float *r=(float*)_ogg_calloc(n*b->dim,sizeof(*r)); + int quantvals; + float mindel=_float32_unpack(b->q_min); + float delta=_float32_unpack(b->q_delta); + float *r=(float*)_ogg_calloc(n*b->dim,sizeof(*r)); - /* maptype 1 and 2 both use a quantized value vector, but - different sizes */ - switch(b->maptype){ - case 1: - /* most of the time, entries%dimensions == 0, but we need to be - well defined. We define that the possible vales at each - scalar is values == entries/dim. If entries%dim != 0, we'll - have 'too few' values (values*dimentries;j++){ + switch(b->maptype){ + case 1: + quantvals=_book_maptype1_quantvals(b); + for(j=0;jentries;j++){ if((sparsemap && b->lengthlist[j]) || !sparsemap){ float last=0.f; int indexdiv=1; for(k=0;kdim;k++){ - int index= (j/indexdiv)%quantvals; - float val=b->quantlist[index]; - val=fabs(val)*delta+mindel+last; - if(b->q_sequencep)last=val; - if(sparsemap) - r[sparsemap[count]*b->dim+k]=val; - else - r[count*b->dim+k]=val; - indexdiv*=quantvals; + int index= (j/indexdiv)%quantvals; + float val=b->quantlist[index]; + val=fabs(val)*delta+mindel+last; + if(b->q_sequencep)last=val; + if(sparsemap) + r[sparsemap[count]*b->dim+k]=val; + else + r[count*b->dim+k]=val; + indexdiv*=quantvals; } count++; } - } - break; - case 2: - for(j=0;jentries;j++){ + } + break; + case 2: + for(j=0;jentries;j++){ if((sparsemap && b->lengthlist[j]) || !sparsemap){ float last=0.f; for(k=0;kdim;k++){ - float val=b->quantlist[j*b->dim+k]; - val=fabs(val)*delta+mindel+last; - if(b->q_sequencep)last=val; - if(sparsemap) - r[sparsemap[count]*b->dim+k]=val; - else - r[count*b->dim+k]=val; + float val=b->quantlist[j*b->dim+k]; + val=fabs(val)*delta+mindel+last; + if(b->q_sequencep)last=val; + if(sparsemap) + r[sparsemap[count]*b->dim+k]=val; + else + r[count*b->dim+k]=val; } count++; } - } - break; - } + } + break; + } - return(r); + return(r); } return(NULL); } void vorbis_staticbook_clear(static_codebook *b){ if(b->allocedp){ - if(b->quantlist)_ogg_free(b->quantlist); - if(b->lengthlist)_ogg_free(b->lengthlist); - if(b->nearest_tree){ - _ogg_free(b->nearest_tree->ptr0); - _ogg_free(b->nearest_tree->ptr1); - _ogg_free(b->nearest_tree->p); - _ogg_free(b->nearest_tree->q); - memset(b->nearest_tree,0,sizeof(*b->nearest_tree)); - _ogg_free(b->nearest_tree); - } - if(b->thresh_tree){ - _ogg_free(b->thresh_tree->quantthresh); - _ogg_free(b->thresh_tree->quantmap); - memset(b->thresh_tree,0,sizeof(*b->thresh_tree)); - _ogg_free(b->thresh_tree); - } + if(b->quantlist)_ogg_free(b->quantlist); + if(b->lengthlist)_ogg_free(b->lengthlist); + if(b->nearest_tree){ + _ogg_free(b->nearest_tree->ptr0); + _ogg_free(b->nearest_tree->ptr1); + _ogg_free(b->nearest_tree->p); + _ogg_free(b->nearest_tree->q); + memset(b->nearest_tree,0,sizeof(*b->nearest_tree)); + _ogg_free(b->nearest_tree); + } + if(b->thresh_tree){ + _ogg_free(b->thresh_tree->quantthresh); + _ogg_free(b->thresh_tree->quantmap); + memset(b->thresh_tree,0,sizeof(*b->thresh_tree)); + _ogg_free(b->thresh_tree); + } - memset(b,0,sizeof(*b)); + memset(b,0,sizeof(*b)); } } void vorbis_staticbook_destroy(static_codebook *b){ if(b->allocedp){ - vorbis_staticbook_clear(b); - _ogg_free(b); + vorbis_staticbook_clear(b); + _ogg_free(b); } } void vorbis_book_clear(codebook *b){ - /* static book is not cleared; we're likely called on the lookup and - the static codebook belongs to the info struct */ if(b->valuelist)_ogg_free(b->valuelist); if(b->codelist)_ogg_free(b->codelist); @@ -140242,72 +128597,58 @@ int vorbis_book_init_encode(codebook *c,const static_codebook *s){ static int sort32a(const void *a,const void *b){ return ( **(ogg_uint32_t **)a>**(ogg_uint32_t **)b)- - ( **(ogg_uint32_t **)a<**(ogg_uint32_t **)b); + ( **(ogg_uint32_t **)a<**(ogg_uint32_t **)b); } -/* decode codebook arrangement is more heavily optimized than encode */ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ int i,j,n=0,tabn; int *sortindex; memset(c,0,sizeof(*c)); - /* count actually used entries */ for(i=0;ientries;i++) - if(s->lengthlist[i]>0) - n++; + if(s->lengthlist[i]>0) + n++; c->entries=s->entries; c->used_entries=n; c->dim=s->dim; - /* two different remappings go on here. - - First, we collapse the likely sparse codebook down only to - actually represented values/words. This collapsing needs to be - indexed as map-valueless books are used to encode original entry - positions as integers. - - Second, we reorder all vectors, including the entry index above, - by sorted bitreversed codeword to allow treeless decode. */ - { - /* perform sort */ - ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries); - ogg_uint32_t **codep=(ogg_uint32_t**)alloca(sizeof(*codep)*n); + ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries); + ogg_uint32_t **codep=(ogg_uint32_t**)alloca(sizeof(*codep)*n); - if(codes==NULL)goto err_out; + if(codes==NULL)goto err_out; - for(i=0;icodelist=(ogg_uint32_t*)_ogg_malloc(n*sizeof(*c->codelist)); - /* the index is a reverse index */ - for(i=0;icodelist=(ogg_uint32_t*)_ogg_malloc(n*sizeof(*c->codelist)); + for(i=0;icodelist[sortindex[i]]=codes[i]; - _ogg_free(codes); + for(i=0;icodelist[sortindex[i]]=codes[i]; + _ogg_free(codes); } c->valuelist=_book_unquantize(s,n,sortindex); c->dec_index=(int*)_ogg_malloc(n*sizeof(*c->dec_index)); for(n=0,i=0;ientries;i++) - if(s->lengthlist[i]>0) - c->dec_index[sortindex[n++]]=i; + if(s->lengthlist[i]>0) + c->dec_index[sortindex[n++]]=i; c->dec_codelengths=(char*)_ogg_malloc(n*sizeof(*c->dec_codelengths)); for(n=0,i=0;ientries;i++) - if(s->lengthlist[i]>0) - c->dec_codelengths[sortindex[n++]]=s->lengthlist[i]; + if(s->lengthlist[i]>0) + c->dec_codelengths[sortindex[n++]]=s->lengthlist[i]; c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */ if(c->dec_firsttablen<5)c->dec_firsttablen=5; @@ -140318,30 +128659,25 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ c->dec_maxlength=0; for(i=0;idec_maxlengthdec_codelengths[i]) - c->dec_maxlength=c->dec_codelengths[i]; - if(c->dec_codelengths[i]<=c->dec_firsttablen){ - ogg_uint32_t orig=ogg_bitreverse(c->codelist[i]); - for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++) + if(c->dec_maxlengthdec_codelengths[i]) + c->dec_maxlength=c->dec_codelengths[i]; + if(c->dec_codelengths[i]<=c->dec_firsttablen){ + ogg_uint32_t orig=ogg_bitreverse(c->codelist[i]); + for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++) c->dec_firsttable[orig|(j<dec_codelengths[i])]=i+1; - } + } } - /* now fill in 'unused' entries in the firsttable with hi/lo search - hints for the non-direct-hits */ { - ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen); - long lo=0,hi=0; + ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen); + long lo=0,hi=0; - for(i=0;idec_firsttablen); - if(c->dec_firsttable[ogg_bitreverse(word)]==0){ + for(i=0;idec_firsttablen); + if(c->dec_firsttable[ogg_bitreverse(word)]==0){ while((lo+1)codelist[lo+1]<=word)lo++; - while( hi=(c->codelist[hi]&mask))hi++; + while( hi=(c->codelist[hi]&mask))hi++; - /* we only actually have 15 bits per hint to play with here. - In order to overflow gracefully (nothing breaks, efficiency - just drops), encode as the difference from the extremes. */ { unsigned long loval=lo; unsigned long hival=n-hi; @@ -140349,10 +128685,10 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ if(loval>0x7fff)loval=0x7fff; if(hival>0x7fff)hival=0x7fff; c->dec_firsttable[ogg_bitreverse(word)]= - 0x80000000UL | (loval<<15) | hival; + 0x80000000UL | (loval<<15) | hival; + } + } } - } - } } return(0); @@ -140365,8 +128701,8 @@ static float _dist(int el,float *ref, float *b,int step){ int i; float acc=0.f; for(i=0;idim; int k,o; - /*int savebest=-1; - float saverr;*/ - /* do we have a threshhold encode hint? */ if(tt){ - int index=0,i; - /* find the quant val of each scalar */ - for(k=0,o=step*(dim-1);kthreshvals>>1; - if(a[o]quantthresh[i]){ + i=tt->threshvals>>1; + if(a[o]quantthresh[i]){ for(;i>0;i--) if(a[o]>=tt->quantthresh[i-1]) - break; + break; - }else{ + }else{ for(i++;ithreshvals-1;i++) if(a[o]quantthresh[i])break; - } + } - index=(index*tt->quantvals)+tt->quantmap[i]; - } - /* regular lattices are easy :-) */ - if(book->c->lengthlist[index]>0) /* is this unused? If so, we'll + index=(index*tt->quantvals)+tt->quantmap[i]; + } + if(book->c->lengthlist[index]>0) /* is this unused? If so, we'll use a decision tree after all and fall through*/ - return(index); + return(index); } #if 0 - /* do we have a pigeonhole encode hint? */ if(pt){ - const static_codebook *c=book->c; - int i,besti=-1; - float best=0.f; - int entry=0; + const static_codebook *c=book->c; + int i,besti=-1; + float best=0.f; + int entry=0; - /* dealing with sequentialness is a pain in the ass */ - if(c->q_sequencep){ - int pv; - long mul=1; - float qlast=0; - for(k=0,o=0;kq_sequencep){ + int pv; + long mul=1; + float qlast=0; + for(k=0,o=0;kmin)/pt->del); if(pv<0 || pv>=pt->mapentries)break; entry+=pt->pigeonmap[pv]*mul; mul*=pt->quantvals; qlast+=pv*pt->del+pt->min; - } - }else{ - for(k=0,o=step*(dim-1);kmin)/pt->del); if(pv<0 || pv>=pt->mapentries)break; entry=entry*pt->quantvals+pt->pigeonmap[pv]; - } - } + } + } - /* must be within the pigeonholable range; if we quant outside (or - in an entry that we define no list for), brute force it */ - if(k==dim && pt->fitlength[entry]){ - /* search the abbreviated list */ - long *list=pt->fitlist+pt->fitmap[entry]; - for(i=0;ifitlength[entry];i++){ + if(k==dim && pt->fitlength[entry]){ + long *list=pt->fitlist+pt->fitmap[entry]; + for(i=0;ifitlength[entry];i++){ float this=_dist(dim,book->valuelist+list[i]*dim,a,step); if(besti==-1 || thisvaluelist+nt->p[ptr]; - float *q=book->valuelist+nt->q[ptr]; + while(1){ + float c=0.f; + float *p=book->valuelist+nt->p[ptr]; + float *q=book->valuelist+nt->q[ptr]; - for(k=0,o=0;k0.f) /* in A */ + if(c>0.f) /* in A */ ptr= -nt->ptr0[ptr]; - else /* in B */ + else /* in B */ ptr= -nt->ptr1[ptr]; - if(ptr<=0)break; - } - return(-ptr); + if(ptr<=0)break; + } + return(-ptr); } #endif - /* brute force it! */ { - const static_codebook *c=book->c; - int i,besti=-1; - float best=0.f; - float *e=book->valuelist; - for(i=0;ientries;i++){ - if(c->lengthlist[i]>0){ + const static_codebook *c=book->c; + int i,besti=-1; + float best=0.f; + float *e=book->valuelist; + for(i=0;ientries;i++){ + if(c->lengthlist[i]>0){ float thisx=_dist(dim,e,a,step); if(besti==-1 || thisxvaluelist+savebest*dim)[i]); - fprintf(stderr,"\n" - "bruteforce (entry %d, err %g):",besti,best); - for(i=0;ivaluelist+besti*dim)[i]); - fprintf(stderr,"\n"); - }*/ - return(besti); + return(besti); } } long vorbis_book_codeword(codebook *book,int entry){ if(book->c) /* only use with encode; decode optimizations are - allowed to break this */ - return book->codelist[entry]; + allowed to break this */ + return book->codelist[entry]; return -1; } long vorbis_book_codelen(codebook *book,int entry){ if(book->c) /* only use with encode; decode optimizations are - allowed to break this */ - return book->c->lengthlist[entry]; + allowed to break this */ + return book->c->lengthlist[entry]; return -1; } #ifdef _V_SELFTEST -/* Unit tests of the dequantizer; this stuff will be OK - cross-platform, I simply want to be sure that special mapping cases - actually work properly; a bug could go unnoticed for a while */ - #include -/* cases: - - no mapping - full, explicit mapping - algorithmic mapping - - nonsequential - sequential -*/ - -static long full_quantlist1[]={0,1,2,3, 4,5,6,7, 8,3,6,1}; +static long full_quantlist1[]={0,1,2,3, 4,5,6,7, 8,3,6,1}; static long partial_quantlist1[]={0,7,2}; -/* no mapping */ static_codebook test1={ 4,16, NULL, @@ -140558,7 +128853,6 @@ static_codebook test1={ }; static float *test1_result=NULL; -/* linear, full mapping, nonsequential */ static_codebook test2={ 4,3, NULL, @@ -140569,7 +128863,6 @@ static_codebook test2={ }; static float test2_result[]={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2}; -/* linear, full mapping, sequential */ static_codebook test3={ 4,3, NULL, @@ -140580,7 +128873,6 @@ static_codebook test3={ }; static float test3_result[]={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6}; -/* linear, algorithmic mapping, nonsequential */ static_codebook test4={ 3,27, NULL, @@ -140590,16 +128882,15 @@ static_codebook test4={ NULL,NULL }; static float test4_result[]={-3,-3,-3, 4,-3,-3, -1,-3,-3, - -3, 4,-3, 4, 4,-3, -1, 4,-3, - -3,-1,-3, 4,-1,-3, -1,-1,-3, - -3,-3, 4, 4,-3, 4, -1,-3, 4, - -3, 4, 4, 4, 4, 4, -1, 4, 4, - -3,-1, 4, 4,-1, 4, -1,-1, 4, - -3,-3,-1, 4,-3,-1, -1,-3,-1, - -3, 4,-1, 4, 4,-1, -1, 4,-1, - -3,-1,-1, 4,-1,-1, -1,-1,-1}; + -3, 4,-3, 4, 4,-3, -1, 4,-3, + -3,-1,-3, 4,-1,-3, -1,-1,-3, + -3,-3, 4, 4,-3, 4, -1,-3, 4, + -3, 4, 4, 4, 4, 4, -1, 4, 4, + -3,-1, 4, 4,-1, 4, -1,-1, 4, + -3,-3,-1, 4,-3,-1, -1,-3,-1, + -3, 4,-1, 4, 4,-1, -1, 4,-1, + -3,-1,-1, 4,-1,-1, -1,-1,-1}; -/* linear, algorithmic mapping, sequential */ static_codebook test5={ 3,27, NULL, @@ -140609,43 +128900,42 @@ static_codebook test5={ NULL,NULL }; static float test5_result[]={-3,-6,-9, 4, 1,-2, -1,-4,-7, - -3, 1,-2, 4, 8, 5, -1, 3, 0, - -3,-4,-7, 4, 3, 0, -1,-2,-5, - -3,-6,-2, 4, 1, 5, -1,-4, 0, - -3, 1, 5, 4, 8,12, -1, 3, 7, - -3,-4, 0, 4, 3, 7, -1,-2, 2, - -3,-6,-7, 4, 1, 0, -1,-4,-5, - -3, 1, 0, 4, 8, 7, -1, 3, 2, - -3,-4,-5, 4, 3, 2, -1,-2,-3}; + -3, 1,-2, 4, 8, 5, -1, 3, 0, + -3,-4,-7, 4, 3, 0, -1,-2,-5, + -3,-6,-2, 4, 1, 5, -1,-4, 0, + -3, 1, 5, 4, 8,12, -1, 3, 7, + -3,-4, 0, 4, 3, 7, -1,-2, 2, + -3,-6,-7, 4, 1, 0, -1,-4,-5, + -3, 1, 0, 4, 8, 7, -1, 3, 2, + -3,-4,-5, 4, 3, 2, -1,-2,-3}; void run_test(static_codebook *b,float *comp){ float *out=_book_unquantize(b,b->entries,NULL); int i; if(comp){ - if(!out){ - fprintf(stderr,"_book_unquantize incorrectly returned NULL\n"); - exit(1); - } + if(!out){ + fprintf(stderr,"_book_unquantize incorrectly returned NULL\n"); + exit(1); + } - for(i=0;ientries*b->dim;i++) - if(fabs(out[i]-comp[i])>.0001){ + for(i=0;ientries*b->dim;i++) + if(fabs(out[i]-comp[i])>.0001){ fprintf(stderr,"disagreement in unquantized and reference data:\n" "position %d, %g != %g\n",i,out[i],comp[i]); exit(1); - } + } }else{ - if(out){ - fprintf(stderr,"_book_unquantize returned a value array: \n" + if(out){ + fprintf(stderr,"_book_unquantize returned a value array: \n" " correct result should have been NULL\n"); - exit(1); - } + exit(1); + } } } int main(){ - /* run the nine dequant tests, and compare to the hand-rolled results */ fprintf(stderr,"Dequant test 1... "); run_test(&test1,test1_result); fprintf(stderr,"OK\nDequant test 2... "); @@ -140667,18 +128957,6 @@ int main(){ /********* End of inlined file: sharedbook.c *********/ /********* Start of inlined file: smallft.c *********/ -/* FFT implementation from OggSquish, minus cosine transforms, - * minus all but radix 2/4 case. In Vorbis we only need this - * cut-down version. - * - * To do more than just power-of-two sized vectors, see the full - * version I wrote for NetLib. - * - * Note that the packing is a little strange; rather than the FFT r/i - * packing following R_0, I_n, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, - * it follows R_0, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, I_n like the - * FORTRAN version - */ /********* Start of inlined file: juce_OggVorbisHeader.h *********/ // This file is included at the start of each Ogg-Vorbis .c file, just to do a few housekeeping @@ -140709,9 +128987,9 @@ static void drfti1(int n, float *wa, int *ifac){ L101: j++; if (j < 4) - ntry=ntryh[j]; + ntry=ntryh[j]; else - ntry+=2; + ntry+=2; L104: nq=nl/ntry; @@ -140725,8 +129003,8 @@ static void drfti1(int n, float *wa, int *ifac){ if(nf==1)goto L107; for (i=1;il1){ - for(j=1;jl1)goto L139; @@ -141772,20 +130050,20 @@ L132: is= -ido-1; t1=0; for(j=1;jtrigcache)_ogg_free(l->trigcache); - if(l->splitcache)_ogg_free(l->splitcache); - memset(l,0,sizeof(*l)); + if(l->trigcache)_ogg_free(l->trigcache); + if(l->splitcache)_ogg_free(l->splitcache); + memset(l,0,sizeof(*l)); } } @@ -141932,24 +130196,20 @@ void drft_clear(drft_lookup *l){ #include int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){ - vorbis_dsp_state *vd=vb->vd; - private_state *b=(private_state*)vd->backend_state; - vorbis_info *vi=vd->vi; - codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; - oggpack_buffer *opb=&vb->opb; - int type,mode,i; + vorbis_dsp_state *vd=vb->vd; + private_state *b=(private_state*)vd->backend_state; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; + oggpack_buffer *opb=&vb->opb; + int type,mode,i; - /* first things first. Make sure decode is ready */ _vorbis_block_ripcord(vb); oggpack_readinit(opb,op->packet,op->bytes); - /* Check the packet type */ if(oggpack_read(opb,1)!=0){ - /* Oops. This is not an audio data packet */ - return(OV_ENOTAUDIO); + return(OV_ENOTAUDIO); } - /* read our mode and pre/post windowsize */ mode=oggpack_read(opb,b->modebits); if(mode==-1)return(OV_EBADPACKET); @@ -141957,75 +130217,62 @@ int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){ vb->W=ci->mode_param[mode]->blockflag; if(vb->W){ - /* this doesn;t get mapped through mode selection as it's used - only for window selection */ - vb->lW=oggpack_read(opb,1); - vb->nW=oggpack_read(opb,1); - if(vb->nW==-1) return(OV_EBADPACKET); + vb->lW=oggpack_read(opb,1); + vb->nW=oggpack_read(opb,1); + if(vb->nW==-1) return(OV_EBADPACKET); }else{ - vb->lW=0; - vb->nW=0; + vb->lW=0; + vb->nW=0; } - /* more setup */ vb->granulepos=op->granulepos; vb->sequence=op->packetno; vb->eofflag=op->e_o_s; - /* alloc pcm passback storage */ vb->pcmend=ci->blocksizes[vb->W]; vb->pcm=(float**)_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); for(i=0;ichannels;i++) - vb->pcm[i]=(float*)_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); + vb->pcm[i]=(float*)_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); - /* unpack_header enforces range checking */ type=ci->map_type[ci->mode_param[mode]->mapping]; return(_mapping_P[type]->inverse(vb,ci->map_param[ci->mode_param[mode]-> mapping])); } -/* used to track pcm position without actually performing decode. - Useful for sequential 'fast forward' */ int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){ - vorbis_dsp_state *vd=vb->vd; - private_state *b=(private_state*)vd->backend_state; - vorbis_info *vi=vd->vi; - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; - oggpack_buffer *opb=&vb->opb; - int mode; + vorbis_dsp_state *vd=vb->vd; + private_state *b=(private_state*)vd->backend_state; + vorbis_info *vi=vd->vi; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + oggpack_buffer *opb=&vb->opb; + int mode; - /* first things first. Make sure decode is ready */ _vorbis_block_ripcord(vb); oggpack_readinit(opb,op->packet,op->bytes); - /* Check the packet type */ if(oggpack_read(opb,1)!=0){ - /* Oops. This is not an audio data packet */ - return(OV_ENOTAUDIO); + return(OV_ENOTAUDIO); } - /* read our mode and pre/post windowsize */ mode=oggpack_read(opb,b->modebits); if(mode==-1)return(OV_EBADPACKET); vb->mode=mode; vb->W=ci->mode_param[mode]->blockflag; if(vb->W){ - vb->lW=oggpack_read(opb,1); - vb->nW=oggpack_read(opb,1); - if(vb->nW==-1) return(OV_EBADPACKET); + vb->lW=oggpack_read(opb,1); + vb->nW=oggpack_read(opb,1); + if(vb->nW==-1) return(OV_EBADPACKET); }else{ - vb->lW=0; - vb->nW=0; + vb->lW=0; + vb->nW=0; } - /* more setup */ vb->granulepos=op->granulepos; vb->sequence=op->packetno; vb->eofflag=op->e_o_s; - /* no pcm */ vb->pcmend=0; vb->pcm=NULL; @@ -142033,45 +130280,40 @@ int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){ } long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; - oggpack_buffer opb; - int mode; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + oggpack_buffer opb; + int mode; oggpack_readinit(&opb,op->packet,op->bytes); - /* Check the packet type */ if(oggpack_read(&opb,1)!=0){ - /* Oops. This is not an audio data packet */ - return(OV_ENOTAUDIO); + return(OV_ENOTAUDIO); } { - int modebits=0; - int v=ci->modes; - while(v>1){ - modebits++; - v>>=1; - } + int modebits=0; + int v=ci->modes; + while(v>1){ + modebits++; + v>>=1; + } - /* read our mode and pre/post windowsize */ - mode=oggpack_read(&opb,modebits); + mode=oggpack_read(&opb,modebits); } if(mode==-1)return(OV_EBADPACKET); return(ci->blocksizes[ci->mode_param[mode]->blockflag]); } int vorbis_synthesis_halfrate(vorbis_info *vi,int flag){ - /* set / clear half-sample-rate mode */ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; - /* right now, our MDCT can't handle < 64 sample windows. */ if(ci->blocksizes[0]<=64 && flag)return -1; ci->halfrate_flag=(flag?1:0); return 0; } int vorbis_synthesis_halfrate_p(vorbis_info *vi){ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; return ci->halfrate_flag; } @@ -142095,10 +130337,6 @@ int vorbis_synthesis_halfrate_p(vorbis_info *vi){ #include #include -/* careful with this; it's using static array sizing to make managing - all the modes a little less annoying. If we use a residue backend - with > 12 partition types, or a different division of iteration, - this needs to be updated. */ typedef struct { static_codebook *books[12][3]; } static_bookblock; @@ -142114,7 +130352,7 @@ typedef struct { } vorbis_residue_template; typedef struct { - vorbis_info_mapping0 *map; + vorbis_info_mapping0 *map; vorbis_residue_template *res; } vorbis_mapping_template; @@ -142126,13 +130364,6 @@ typedef struct { int data[NOISE_COMPAND_LEVELS]; } compandblock; -/* high level configuration information for setting things up - step-by-step with the detailed vorbis_encode_ctl interface. - There's a fair amount of redundancy such that interactive setup - does not directly deal with any vorbis_info or codec_setup_info - initialization; it's all stored (until full init) in this highlevel - setup, then flushed out to the real codec setup structs later. */ - typedef struct { int att[P_NOISECURVES]; float boost; @@ -142157,46 +130388,46 @@ typedef struct { } noise3; typedef struct { - int mappings; + int mappings; double *rate_mapping; double *quality_mapping; - int coupling_restriction; - long samplerate_min_restriction; - long samplerate_max_restriction; + int coupling_restriction; + long samplerate_min_restriction; + long samplerate_max_restriction; - int *blocksize_short; - int *blocksize_long; + int *blocksize_short; + int *blocksize_long; - att3 *psy_tone_masteratt; - int *psy_tone_0dB; - int *psy_tone_dBsuppress; + att3 *psy_tone_masteratt; + int *psy_tone_0dB; + int *psy_tone_dBsuppress; vp_adjblock *psy_tone_adj_impulse; vp_adjblock *psy_tone_adj_long; vp_adjblock *psy_tone_adj_other; noiseguard *psy_noiseguards; - noise3 *psy_noise_bias_impulse; - noise3 *psy_noise_bias_padding; - noise3 *psy_noise_bias_trans; - noise3 *psy_noise_bias_long; - int *psy_noise_dBsuppress; + noise3 *psy_noise_bias_impulse; + noise3 *psy_noise_bias_padding; + noise3 *psy_noise_bias_trans; + noise3 *psy_noise_bias_long; + int *psy_noise_dBsuppress; compandblock *psy_noise_compand; - double *psy_noise_compand_short_mapping; - double *psy_noise_compand_long_mapping; + double *psy_noise_compand_short_mapping; + double *psy_noise_compand_long_mapping; - int *psy_noise_normal_start[2]; - int *psy_noise_normal_partition[2]; + int *psy_noise_normal_start[2]; + int *psy_noise_normal_partition[2]; double *psy_noise_normal_thresh; - int *psy_ath_float; - int *psy_ath_abs; + int *psy_ath_float; + int *psy_ath_abs; double *psy_lowpass; vorbis_info_psy_global *global_params; - double *global_mapping; + double *global_mapping; adj_stereo *stereo_modes; static_codebook ***floor_books; @@ -142207,7 +130438,6 @@ typedef struct { vorbis_mapping_template *maps; } ve_setup_data_template; -/* a few static coder conventions */ static vorbis_info_mode _mode_template[2]={ {0,0,0,0}, {1,0,0,1} @@ -144184,89 +132414,79 @@ static static_codebook **_floor_books[10]={ }; static vorbis_info_floor1 _floor[10]={ - /* 128 x 4 */ { - 1,{0},{4},{2},{0}, - {{1,2,3,4}}, - 4,{0,128, 33,8,16,70}, + 1,{0},{4},{2},{0}, + {{1,2,3,4}}, + 4,{0,128, 33,8,16,70}, - 60,30,500, 1.,18., -1 + 60,30,500, 1.,18., -1 }, - /* 256 x 4 */ { - 1,{0},{4},{2},{0}, - {{1,2,3,4}}, - 4,{0,256, 66,16,32,140}, + 1,{0},{4},{2},{0}, + {{1,2,3,4}}, + 4,{0,256, 66,16,32,140}, - 60,30,500, 1.,18., -1 + 60,30,500, 1.,18., -1 }, - /* 128 x 7 */ { - 2,{0,1},{3,4},{2,2},{0,1}, - {{-1,2,3,4},{-1,5,6,7}}, - 4,{0,128, 14,4,58, 2,8,28,90}, + 2,{0,1},{3,4},{2,2},{0,1}, + {{-1,2,3,4},{-1,5,6,7}}, + 4,{0,128, 14,4,58, 2,8,28,90}, - 60,30,500, 1.,18., -1 + 60,30,500, 1.,18., -1 }, - /* 256 x 7 */ { - 2,{0,1},{3,4},{2,2},{0,1}, - {{-1,2,3,4},{-1,5,6,7}}, - 4,{0,256, 28,8,116, 4,16,56,180}, + 2,{0,1},{3,4},{2,2},{0,1}, + {{-1,2,3,4},{-1,5,6,7}}, + 4,{0,256, 28,8,116, 4,16,56,180}, - 60,30,500, 1.,18., -1 + 60,30,500, 1.,18., -1 }, - /* 128 x 11 */ { - 4,{0,1,2,3},{2,3,3,3},{0,1,2,2},{-1,0,1,2}, - {{3},{4,5},{-1,6,7,8},{-1,9,10,11}}, + 4,{0,1,2,3},{2,3,3,3},{0,1,2,2},{-1,0,1,2}, + {{3},{4,5},{-1,6,7,8},{-1,9,10,11}}, - 2,{0,128, 8,33, 4,16,70, 2,6,12, 23,46,90}, + 2,{0,128, 8,33, 4,16,70, 2,6,12, 23,46,90}, - 60,30,500, 1,18., -1 + 60,30,500, 1,18., -1 }, - /* 128 x 17 */ { - 6,{0,1,1,2,3,3},{2,3,3,3},{0,1,2,2},{-1,0,1,2}, - {{3},{4,5},{-1,6,7,8},{-1,9,10,11}}, - 2,{0,128, 12,46, 4,8,16, 23,33,70, 2,6,10, 14,19,28, 39,58,90}, + 6,{0,1,1,2,3,3},{2,3,3,3},{0,1,2,2},{-1,0,1,2}, + {{3},{4,5},{-1,6,7,8},{-1,9,10,11}}, + 2,{0,128, 12,46, 4,8,16, 23,33,70, 2,6,10, 14,19,28, 39,58,90}, - 60,30,500, 1,18., -1 + 60,30,500, 1,18., -1 }, - /* 256 x 4 (low bitrate version) */ { - 1,{0},{4},{2},{0}, - {{1,2,3,4}}, - 4,{0,256, 66,16,32,140}, + 1,{0},{4},{2},{0}, + {{1,2,3,4}}, + 4,{0,256, 66,16,32,140}, - 60,30,500, 1.,18., -1 + 60,30,500, 1.,18., -1 }, - /* 1024 x 27 */ { - 8,{0,1,2,2,3,3,4,4},{3,4,3,4,3},{0,1,1,2,2},{-1,0,1,2,3}, - {{4},{5,6},{7,8},{-1,9,10,11},{-1,12,13,14}}, - 2,{0,1024, 93,23,372, 6,46,186,750, 14,33,65, 130,260,556, - 3,10,18,28, 39,55,79,111, 158,220,312, 464,650,850}, + 8,{0,1,2,2,3,3,4,4},{3,4,3,4,3},{0,1,1,2,2},{-1,0,1,2,3}, + {{4},{5,6},{7,8},{-1,9,10,11},{-1,12,13,14}}, + 2,{0,1024, 93,23,372, 6,46,186,750, 14,33,65, 130,260,556, + 3,10,18,28, 39,55,79,111, 158,220,312, 464,650,850}, - 60,30,500, 3,18., -1 /* lowpass */ + 60,30,500, 3,18., -1 /* lowpass */ }, - /* 2048 x 27 */ { - 8,{0,1,2,2,3,3,4,4},{3,4,3,4,3},{0,1,1,2,2},{-1,0,1,2,3}, - {{4},{5,6},{7,8},{-1,9,10,11},{-1,12,13,14}}, - 2,{0,2048, 186,46,744, 12,92,372,1500, 28,66,130, 260,520,1112, - 6,20,36,56, 78,110,158,222, 316,440,624, 928,1300,1700}, + 8,{0,1,2,2,3,3,4,4},{3,4,3,4,3},{0,1,1,2,2},{-1,0,1,2,3}, + {{4},{5,6},{7,8},{-1,9,10,11},{-1,12,13,14}}, + 2,{0,2048, 186,46,744, 12,92,372,1500, 28,66,130, 260,520,1112, + 6,20,36,56, 78,110,158,222, 316,440,624, 928,1300,1700}, - 60,30,500, 3,18., -1 /* lowpass */ + 60,30,500, 3,18., -1 /* lowpass */ }, - /* 512 x 17 */ { - 6,{0,1,1,2,3,3},{2,3,3,3},{0,1,2,2},{-1,0,1,2}, - {{3},{4,5},{-1,6,7,8},{-1,9,10,11}}, - 2,{0,512, 46,186, 16,33,65, 93,130,278, - 7,23,39, 55,79,110, 156,232,360}, + 6,{0,1,1,2,3,3},{2,3,3,3},{0,1,2,2},{-1,0,1,2}, + {{3},{4,5},{-1,6,7,8},{-1,9,10,11}}, + 2,{0,512, 46,186, 16,33,65, 93,130,278, + 7,23,39, 55,79,110, 156,232,360}, - 60,30,500, 1,18., -1 /* lowpass! */ + 60,30,500, 1,18., -1 /* lowpass! */ }, }; @@ -144701,7 +132921,7 @@ static float _vq_quantthresh__16c0_s_p1_0[] = { }; static long _vq_quantmap__16c0_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p1_0 = { @@ -144778,7 +132998,7 @@ static float _vq_quantthresh__16c0_s_p2_0[] = { }; static long _vq_quantmap__16c0_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p2_0 = { @@ -144855,7 +133075,7 @@ static float _vq_quantthresh__16c0_s_p3_0[] = { }; static long _vq_quantmap__16c0_s_p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p3_0 = { @@ -144902,8 +133122,8 @@ static float _vq_quantthresh__16c0_s_p4_0[] = { }; static long _vq_quantmap__16c0_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p4_0 = { @@ -144950,8 +133170,8 @@ static float _vq_quantthresh__16c0_s_p5_0[] = { }; static long _vq_quantmap__16c0_s_p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p5_0 = { @@ -145020,8 +133240,8 @@ static float _vq_quantthresh__16c0_s_p6_0[] = { }; static long _vq_quantmap__16c0_s_p6_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -145063,7 +133283,7 @@ static float _vq_quantthresh__16c0_s_p7_0[] = { }; static long _vq_quantmap__16c0_s_p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p7_0 = { @@ -145115,8 +133335,8 @@ static float _vq_quantthresh__16c0_s_p7_1[] = { }; static long _vq_quantmap__16c0_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p7_1 = { @@ -145173,8 +133393,8 @@ static float _vq_quantthresh__16c0_s_p8_0[] = { }; static long _vq_quantmap__16c0_s_p8_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p8_0 = { @@ -145213,7 +133433,7 @@ static float _vq_quantthresh__16c0_s_p8_1[] = { }; static long _vq_quantmap__16c0_s_p8_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p8_1 = { @@ -145254,7 +133474,7 @@ static float _vq_quantthresh__16c0_s_p9_0[] = { }; static long _vq_quantmap__16c0_s_p9_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p9_0 = { @@ -145317,8 +133537,8 @@ static float _vq_quantthresh__16c0_s_p9_1[] = { }; static long _vq_quantmap__16c0_s_p9_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__16c0_s_p9_1 = { @@ -145401,8 +133621,8 @@ static float _vq_quantthresh__16c0_s_p9_2[] = { }; static long _vq_quantmap__16c0_s_p9_2[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -145891,7 +134111,7 @@ static float _vq_quantthresh__16c1_s_p1_0[] = { }; static long _vq_quantmap__16c1_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p1_0 = { @@ -145968,7 +134188,7 @@ static float _vq_quantthresh__16c1_s_p2_0[] = { }; static long _vq_quantmap__16c1_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p2_0 = { @@ -146045,7 +134265,7 @@ static float _vq_quantthresh__16c1_s_p3_0[] = { }; static long _vq_quantmap__16c1_s_p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p3_0 = { @@ -146092,8 +134312,8 @@ static float _vq_quantthresh__16c1_s_p4_0[] = { }; static long _vq_quantmap__16c1_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p4_0 = { @@ -146140,8 +134360,8 @@ static float _vq_quantthresh__16c1_s_p5_0[] = { }; static long _vq_quantmap__16c1_s_p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p5_0 = { @@ -146210,8 +134430,8 @@ static float _vq_quantthresh__16c1_s_p6_0[] = { }; static long _vq_quantmap__16c1_s_p6_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -146253,7 +134473,7 @@ static float _vq_quantthresh__16c1_s_p7_0[] = { }; static long _vq_quantmap__16c1_s_p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p7_0 = { @@ -146305,8 +134525,8 @@ static float _vq_quantthresh__16c1_s_p7_1[] = { }; static long _vq_quantmap__16c1_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p7_1 = { @@ -146363,8 +134583,8 @@ static float _vq_quantthresh__16c1_s_p8_0[] = { }; static long _vq_quantmap__16c1_s_p8_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p8_0 = { @@ -146403,7 +134623,7 @@ static float _vq_quantthresh__16c1_s_p8_1[] = { }; static long _vq_quantmap__16c1_s_p8_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p8_1 = { @@ -146460,8 +134680,8 @@ static float _vq_quantthresh__16c1_s_p9_0[] = { }; static long _vq_quantmap__16c1_s_p9_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p9_0 = { @@ -146524,8 +134744,8 @@ static float _vq_quantthresh__16c1_s_p9_1[] = { }; static long _vq_quantmap__16c1_s_p9_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__16c1_s_p9_1 = { @@ -146608,8 +134828,8 @@ static float _vq_quantthresh__16c1_s_p9_2[] = { }; static long _vq_quantmap__16c1_s_p9_2[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -146693,7 +134913,7 @@ static float _vq_quantthresh__16c2_s_p1_0[] = { }; static long _vq_quantmap__16c2_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p1_0 = { @@ -146770,7 +134990,7 @@ static float _vq_quantthresh__16c2_s_p2_0[] = { }; static long _vq_quantmap__16c2_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p2_0 = { @@ -146817,8 +135037,8 @@ static float _vq_quantthresh__16c2_s_p3_0[] = { }; static long _vq_quantmap__16c2_s_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p3_0 = { @@ -146887,8 +135107,8 @@ static float _vq_quantthresh__16c2_s_p4_0[] = { }; static long _vq_quantmap__16c2_s_p4_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -146930,7 +135150,7 @@ static float _vq_quantthresh__16c2_s_p5_0[] = { }; static long _vq_quantmap__16c2_s_p5_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p5_0 = { @@ -146982,8 +135202,8 @@ static float _vq_quantthresh__16c2_s_p5_1[] = { }; static long _vq_quantmap__16c2_s_p5_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p5_1 = { @@ -147040,8 +135260,8 @@ static float _vq_quantthresh__16c2_s_p6_0[] = { }; static long _vq_quantmap__16c2_s_p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p6_0 = { @@ -147080,7 +135300,7 @@ static float _vq_quantthresh__16c2_s_p6_1[] = { }; static long _vq_quantmap__16c2_s_p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p6_1 = { @@ -147137,8 +135357,8 @@ static float _vq_quantthresh__16c2_s_p7_0[] = { }; static long _vq_quantmap__16c2_s_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p7_0 = { @@ -147190,8 +135410,8 @@ static float _vq_quantthresh__16c2_s_p7_1[] = { }; static long _vq_quantmap__16c2_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p7_1 = { @@ -147254,8 +135474,8 @@ static float _vq_quantthresh__16c2_s_p8_0[] = { }; static long _vq_quantmap__16c2_s_p8_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p8_0 = { @@ -147338,8 +135558,8 @@ static float _vq_quantthresh__16c2_s_p8_1[] = { }; static long _vq_quantmap__16c2_s_p8_1[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -147397,8 +135617,8 @@ static float _vq_quantthresh__16c2_s_p9_0[] = { }; static long _vq_quantmap__16c2_s_p9_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__16c2_s_p9_0 = { @@ -147467,8 +135687,8 @@ static float _vq_quantthresh__16c2_s_p9_1[] = { }; static long _vq_quantmap__16c2_s_p9_1[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -147534,8 +135754,8 @@ static float _vq_quantthresh__16c2_s_p9_2[] = { static long _vq_quantmap__16c2_s_p9_2[] = { 25, 23, 21, 19, 17, 15, 13, 11, - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, 12, 14, 16, 18, 20, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, }; @@ -148003,7 +136223,7 @@ static float _vq_quantthresh__8c0_s_p1_0[] = { }; static long _vq_quantmap__8c0_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p1_0 = { @@ -148080,7 +136300,7 @@ static float _vq_quantthresh__8c0_s_p2_0[] = { }; static long _vq_quantmap__8c0_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p2_0 = { @@ -148157,7 +136377,7 @@ static float _vq_quantthresh__8c0_s_p3_0[] = { }; static long _vq_quantmap__8c0_s_p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p3_0 = { @@ -148204,8 +136424,8 @@ static float _vq_quantthresh__8c0_s_p4_0[] = { }; static long _vq_quantmap__8c0_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p4_0 = { @@ -148252,8 +136472,8 @@ static float _vq_quantthresh__8c0_s_p5_0[] = { }; static long _vq_quantmap__8c0_s_p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p5_0 = { @@ -148322,8 +136542,8 @@ static float _vq_quantthresh__8c0_s_p6_0[] = { }; static long _vq_quantmap__8c0_s_p6_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -148365,7 +136585,7 @@ static float _vq_quantthresh__8c0_s_p7_0[] = { }; static long _vq_quantmap__8c0_s_p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p7_0 = { @@ -148417,8 +136637,8 @@ static float _vq_quantthresh__8c0_s_p7_1[] = { }; static long _vq_quantmap__8c0_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p7_1 = { @@ -148475,8 +136695,8 @@ static float _vq_quantthresh__8c0_s_p8_0[] = { }; static long _vq_quantmap__8c0_s_p8_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p8_0 = { @@ -148515,7 +136735,7 @@ static float _vq_quantthresh__8c0_s_p8_1[] = { }; static long _vq_quantmap__8c0_s_p8_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p8_1 = { @@ -148556,7 +136776,7 @@ static float _vq_quantthresh__8c0_s_p9_0[] = { }; static long _vq_quantmap__8c0_s_p9_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p9_0 = { @@ -148619,8 +136839,8 @@ static float _vq_quantthresh__8c0_s_p9_1[] = { }; static long _vq_quantmap__8c0_s_p9_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__8c0_s_p9_1 = { @@ -148703,8 +136923,8 @@ static float _vq_quantthresh__8c0_s_p9_2[] = { }; static long _vq_quantmap__8c0_s_p9_2[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -149172,7 +137392,7 @@ static float _vq_quantthresh__8c1_s_p1_0[] = { }; static long _vq_quantmap__8c1_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p1_0 = { @@ -149249,7 +137469,7 @@ static float _vq_quantthresh__8c1_s_p2_0[] = { }; static long _vq_quantmap__8c1_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p2_0 = { @@ -149326,7 +137546,7 @@ static float _vq_quantthresh__8c1_s_p3_0[] = { }; static long _vq_quantmap__8c1_s_p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p3_0 = { @@ -149373,8 +137593,8 @@ static float _vq_quantthresh__8c1_s_p4_0[] = { }; static long _vq_quantmap__8c1_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p4_0 = { @@ -149421,8 +137641,8 @@ static float _vq_quantthresh__8c1_s_p5_0[] = { }; static long _vq_quantmap__8c1_s_p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p5_0 = { @@ -149491,8 +137711,8 @@ static float _vq_quantthresh__8c1_s_p6_0[] = { }; static long _vq_quantmap__8c1_s_p6_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -149534,7 +137754,7 @@ static float _vq_quantthresh__8c1_s_p7_0[] = { }; static long _vq_quantmap__8c1_s_p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p7_0 = { @@ -149586,8 +137806,8 @@ static float _vq_quantthresh__8c1_s_p7_1[] = { }; static long _vq_quantmap__8c1_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p7_1 = { @@ -149644,8 +137864,8 @@ static float _vq_quantthresh__8c1_s_p8_0[] = { }; static long _vq_quantmap__8c1_s_p8_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p8_0 = { @@ -149684,7 +137904,7 @@ static float _vq_quantthresh__8c1_s_p8_1[] = { }; static long _vq_quantmap__8c1_s_p8_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p8_1 = { @@ -149741,8 +137961,8 @@ static float _vq_quantthresh__8c1_s_p9_0[] = { }; static long _vq_quantmap__8c1_s_p9_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p9_0 = { @@ -149805,8 +138025,8 @@ static float _vq_quantthresh__8c1_s_p9_1[] = { }; static long _vq_quantmap__8c1_s_p9_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__8c1_s_p9_1 = { @@ -149889,8 +138109,8 @@ static float _vq_quantthresh__8c1_s_p9_2[] = { }; static long _vq_quantmap__8c1_s_p9_2[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -150379,7 +138599,7 @@ static float _vq_quantthresh__44c2_s_p1_0[] = { }; static long _vq_quantmap__44c2_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p1_0 = { @@ -150456,7 +138676,7 @@ static float _vq_quantthresh__44c2_s_p2_0[] = { }; static long _vq_quantmap__44c2_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p2_0 = { @@ -150533,7 +138753,7 @@ static float _vq_quantthresh__44c2_s_p3_0[] = { }; static long _vq_quantmap__44c2_s_p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p3_0 = { @@ -150580,8 +138800,8 @@ static float _vq_quantthresh__44c2_s_p4_0[] = { }; static long _vq_quantmap__44c2_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p4_0 = { @@ -150628,8 +138848,8 @@ static float _vq_quantthresh__44c2_s_p5_0[] = { }; static long _vq_quantmap__44c2_s_p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p5_0 = { @@ -150698,8 +138918,8 @@ static float _vq_quantthresh__44c2_s_p6_0[] = { }; static long _vq_quantmap__44c2_s_p6_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -150741,7 +138961,7 @@ static float _vq_quantthresh__44c2_s_p7_0[] = { }; static long _vq_quantmap__44c2_s_p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p7_0 = { @@ -150793,8 +139013,8 @@ static float _vq_quantthresh__44c2_s_p7_1[] = { }; static long _vq_quantmap__44c2_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p7_1 = { @@ -150851,8 +139071,8 @@ static float _vq_quantthresh__44c2_s_p8_0[] = { }; static long _vq_quantmap__44c2_s_p8_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p8_0 = { @@ -150891,7 +139111,7 @@ static float _vq_quantthresh__44c2_s_p8_1[] = { }; static long _vq_quantmap__44c2_s_p8_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p8_1 = { @@ -150948,8 +139168,8 @@ static float _vq_quantthresh__44c2_s_p9_0[] = { }; static long _vq_quantmap__44c2_s_p9_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p9_0 = { @@ -151006,8 +139226,8 @@ static float _vq_quantthresh__44c2_s_p9_1[] = { }; static long _vq_quantmap__44c2_s_p9_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c2_s_p9_1 = { @@ -151076,8 +139296,8 @@ static float _vq_quantthresh__44c2_s_p9_2[] = { }; static long _vq_quantmap__44c2_s_p9_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -151566,7 +139786,7 @@ static float _vq_quantthresh__44c3_s_p1_0[] = { }; static long _vq_quantmap__44c3_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p1_0 = { @@ -151643,7 +139863,7 @@ static float _vq_quantthresh__44c3_s_p2_0[] = { }; static long _vq_quantmap__44c3_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p2_0 = { @@ -151720,7 +139940,7 @@ static float _vq_quantthresh__44c3_s_p3_0[] = { }; static long _vq_quantmap__44c3_s_p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p3_0 = { @@ -151767,8 +139987,8 @@ static float _vq_quantthresh__44c3_s_p4_0[] = { }; static long _vq_quantmap__44c3_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p4_0 = { @@ -151815,8 +140035,8 @@ static float _vq_quantthresh__44c3_s_p5_0[] = { }; static long _vq_quantmap__44c3_s_p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p5_0 = { @@ -151885,8 +140105,8 @@ static float _vq_quantthresh__44c3_s_p6_0[] = { }; static long _vq_quantmap__44c3_s_p6_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -151928,7 +140148,7 @@ static float _vq_quantthresh__44c3_s_p7_0[] = { }; static long _vq_quantmap__44c3_s_p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p7_0 = { @@ -151980,8 +140200,8 @@ static float _vq_quantthresh__44c3_s_p7_1[] = { }; static long _vq_quantmap__44c3_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p7_1 = { @@ -152038,8 +140258,8 @@ static float _vq_quantthresh__44c3_s_p8_0[] = { }; static long _vq_quantmap__44c3_s_p8_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p8_0 = { @@ -152078,7 +140298,7 @@ static float _vq_quantthresh__44c3_s_p8_1[] = { }; static long _vq_quantmap__44c3_s_p8_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p8_1 = { @@ -152135,8 +140355,8 @@ static float _vq_quantthresh__44c3_s_p9_0[] = { }; static long _vq_quantmap__44c3_s_p9_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p9_0 = { @@ -152199,8 +140419,8 @@ static float _vq_quantthresh__44c3_s_p9_1[] = { }; static long _vq_quantmap__44c3_s_p9_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44c3_s_p9_1 = { @@ -152269,8 +140489,8 @@ static float _vq_quantthresh__44c3_s_p9_2[] = { }; static long _vq_quantmap__44c3_s_p9_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -152759,7 +140979,7 @@ static float _vq_quantthresh__44c4_s_p1_0[] = { }; static long _vq_quantmap__44c4_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p1_0 = { @@ -152836,7 +141056,7 @@ static float _vq_quantthresh__44c4_s_p2_0[] = { }; static long _vq_quantmap__44c4_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p2_0 = { @@ -152913,7 +141133,7 @@ static float _vq_quantthresh__44c4_s_p3_0[] = { }; static long _vq_quantmap__44c4_s_p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p3_0 = { @@ -152960,8 +141180,8 @@ static float _vq_quantthresh__44c4_s_p4_0[] = { }; static long _vq_quantmap__44c4_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p4_0 = { @@ -153008,8 +141228,8 @@ static float _vq_quantthresh__44c4_s_p5_0[] = { }; static long _vq_quantmap__44c4_s_p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p5_0 = { @@ -153078,8 +141298,8 @@ static float _vq_quantthresh__44c4_s_p6_0[] = { }; static long _vq_quantmap__44c4_s_p6_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -153121,7 +141341,7 @@ static float _vq_quantthresh__44c4_s_p7_0[] = { }; static long _vq_quantmap__44c4_s_p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p7_0 = { @@ -153173,8 +141393,8 @@ static float _vq_quantthresh__44c4_s_p7_1[] = { }; static long _vq_quantmap__44c4_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p7_1 = { @@ -153231,8 +141451,8 @@ static float _vq_quantthresh__44c4_s_p8_0[] = { }; static long _vq_quantmap__44c4_s_p8_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p8_0 = { @@ -153271,7 +141491,7 @@ static float _vq_quantthresh__44c4_s_p8_1[] = { }; static long _vq_quantmap__44c4_s_p8_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p8_1 = { @@ -153328,8 +141548,8 @@ static float _vq_quantthresh__44c4_s_p9_0[] = { }; static long _vq_quantmap__44c4_s_p9_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p9_0 = { @@ -153392,8 +141612,8 @@ static float _vq_quantthresh__44c4_s_p9_1[] = { }; static long _vq_quantmap__44c4_s_p9_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44c4_s_p9_1 = { @@ -153476,8 +141696,8 @@ static float _vq_quantthresh__44c4_s_p9_2[] = { }; static long _vq_quantmap__44c4_s_p9_2[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -153966,7 +142186,7 @@ static float _vq_quantthresh__44c5_s_p1_0[] = { }; static long _vq_quantmap__44c5_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c5_s_p1_0 = { @@ -154043,7 +142263,7 @@ static float _vq_quantthresh__44c5_s_p2_0[] = { }; static long _vq_quantmap__44c5_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c5_s_p2_0 = { @@ -154120,7 +142340,7 @@ static float _vq_quantthresh__44c5_s_p3_0[] = { }; static long _vq_quantmap__44c5_s_p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c5_s_p3_0 = { @@ -154167,8 +142387,8 @@ static float _vq_quantthresh__44c5_s_p4_0[] = { }; static long _vq_quantmap__44c5_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c5_s_p4_0 = { @@ -154215,8 +142435,8 @@ static float _vq_quantthresh__44c5_s_p5_0[] = { }; static long _vq_quantmap__44c5_s_p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c5_s_p5_0 = { @@ -154285,8 +142505,8 @@ static float _vq_quantthresh__44c5_s_p6_0[] = { }; static long _vq_quantmap__44c5_s_p6_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -154328,7 +142548,7 @@ static float _vq_quantthresh__44c5_s_p7_0[] = { }; static long _vq_quantmap__44c5_s_p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c5_s_p7_0 = { @@ -154380,8 +142600,8 @@ static float _vq_quantthresh__44c5_s_p7_1[] = { }; static long _vq_quantmap__44c5_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c5_s_p7_1 = { @@ -154438,8 +142658,8 @@ static float _vq_quantthresh__44c5_s_p8_0[] = { }; static long _vq_quantmap__44c5_s_p8_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c5_s_p8_0 = { @@ -154478,7 +142698,7 @@ static float _vq_quantthresh__44c5_s_p8_1[] = { }; static long _vq_quantmap__44c5_s_p8_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c5_s_p8_1 = { @@ -154541,8 +142761,8 @@ static float _vq_quantthresh__44c5_s_p9_0[] = { }; static long _vq_quantmap__44c5_s_p9_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44c5_s_p9_0 = { @@ -154611,8 +142831,8 @@ static float _vq_quantthresh__44c5_s_p9_1[] = { }; static long _vq_quantmap__44c5_s_p9_1[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -154696,8 +142916,8 @@ static float _vq_quantthresh__44c5_s_p9_2[] = { }; static long _vq_quantmap__44c5_s_p9_2[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -154781,7 +143001,7 @@ static float _vq_quantthresh__44c6_s_p1_0[] = { }; static long _vq_quantmap__44c6_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p1_0 = { @@ -154858,7 +143078,7 @@ static float _vq_quantthresh__44c6_s_p2_0[] = { }; static long _vq_quantmap__44c6_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p2_0 = { @@ -154905,8 +143125,8 @@ static float _vq_quantthresh__44c6_s_p3_0[] = { }; static long _vq_quantmap__44c6_s_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p3_0 = { @@ -154975,8 +143195,8 @@ static float _vq_quantthresh__44c6_s_p4_0[] = { }; static long _vq_quantmap__44c6_s_p4_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -155018,7 +143238,7 @@ static float _vq_quantthresh__44c6_s_p5_0[] = { }; static long _vq_quantmap__44c6_s_p5_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p5_0 = { @@ -155070,8 +143290,8 @@ static float _vq_quantthresh__44c6_s_p5_1[] = { }; static long _vq_quantmap__44c6_s_p5_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p5_1 = { @@ -155128,8 +143348,8 @@ static float _vq_quantthresh__44c6_s_p6_0[] = { }; static long _vq_quantmap__44c6_s_p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p6_0 = { @@ -155168,7 +143388,7 @@ static float _vq_quantthresh__44c6_s_p6_1[] = { }; static long _vq_quantmap__44c6_s_p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p6_1 = { @@ -155225,8 +143445,8 @@ static float _vq_quantthresh__44c6_s_p7_0[] = { }; static long _vq_quantmap__44c6_s_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p7_0 = { @@ -155278,8 +143498,8 @@ static float _vq_quantthresh__44c6_s_p7_1[] = { }; static long _vq_quantmap__44c6_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p7_1 = { @@ -155342,8 +143562,8 @@ static float _vq_quantthresh__44c6_s_p8_0[] = { }; static long _vq_quantmap__44c6_s_p8_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p8_0 = { @@ -155426,8 +143646,8 @@ static float _vq_quantthresh__44c6_s_p8_1[] = { }; static long _vq_quantmap__44c6_s_p8_1[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -155485,8 +143705,8 @@ static float _vq_quantthresh__44c6_s_p9_0[] = { }; static long _vq_quantmap__44c6_s_p9_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p9_0 = { @@ -155543,8 +143763,8 @@ static float _vq_quantthresh__44c6_s_p9_1[] = { }; static long _vq_quantmap__44c6_s_p9_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c6_s_p9_1 = { @@ -155636,8 +143856,8 @@ static float _vq_quantthresh__44c6_s_p9_2[] = { static long _vq_quantmap__44c6_s_p9_2[] = { 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, @@ -155723,7 +143943,7 @@ static float _vq_quantthresh__44c7_s_p1_0[] = { }; static long _vq_quantmap__44c7_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p1_0 = { @@ -155800,7 +144020,7 @@ static float _vq_quantthresh__44c7_s_p2_0[] = { }; static long _vq_quantmap__44c7_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p2_0 = { @@ -155847,8 +144067,8 @@ static float _vq_quantthresh__44c7_s_p3_0[] = { }; static long _vq_quantmap__44c7_s_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p3_0 = { @@ -155917,8 +144137,8 @@ static float _vq_quantthresh__44c7_s_p4_0[] = { }; static long _vq_quantmap__44c7_s_p4_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -155960,7 +144180,7 @@ static float _vq_quantthresh__44c7_s_p5_0[] = { }; static long _vq_quantmap__44c7_s_p5_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p5_0 = { @@ -156012,8 +144232,8 @@ static float _vq_quantthresh__44c7_s_p5_1[] = { }; static long _vq_quantmap__44c7_s_p5_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p5_1 = { @@ -156070,8 +144290,8 @@ static float _vq_quantthresh__44c7_s_p6_0[] = { }; static long _vq_quantmap__44c7_s_p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p6_0 = { @@ -156110,7 +144330,7 @@ static float _vq_quantthresh__44c7_s_p6_1[] = { }; static long _vq_quantmap__44c7_s_p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p6_1 = { @@ -156167,8 +144387,8 @@ static float _vq_quantthresh__44c7_s_p7_0[] = { }; static long _vq_quantmap__44c7_s_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p7_0 = { @@ -156220,8 +144440,8 @@ static float _vq_quantthresh__44c7_s_p7_1[] = { }; static long _vq_quantmap__44c7_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p7_1 = { @@ -156284,8 +144504,8 @@ static float _vq_quantthresh__44c7_s_p8_0[] = { }; static long _vq_quantmap__44c7_s_p8_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p8_0 = { @@ -156368,8 +144588,8 @@ static float _vq_quantthresh__44c7_s_p8_1[] = { }; static long _vq_quantmap__44c7_s_p8_1[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -156427,8 +144647,8 @@ static float _vq_quantthresh__44c7_s_p9_0[] = { }; static long _vq_quantmap__44c7_s_p9_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p9_0 = { @@ -156485,8 +144705,8 @@ static float _vq_quantthresh__44c7_s_p9_1[] = { }; static long _vq_quantmap__44c7_s_p9_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c7_s_p9_1 = { @@ -156578,8 +144798,8 @@ static float _vq_quantthresh__44c7_s_p9_2[] = { static long _vq_quantmap__44c7_s_p9_2[] = { 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, @@ -156665,7 +144885,7 @@ static float _vq_quantthresh__44c8_s_p1_0[] = { }; static long _vq_quantmap__44c8_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c8_s_p1_0 = { @@ -156742,7 +144962,7 @@ static float _vq_quantthresh__44c8_s_p2_0[] = { }; static long _vq_quantmap__44c8_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c8_s_p2_0 = { @@ -156789,8 +145009,8 @@ static float _vq_quantthresh__44c8_s_p3_0[] = { }; static long _vq_quantmap__44c8_s_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c8_s_p3_0 = { @@ -156859,8 +145079,8 @@ static float _vq_quantthresh__44c8_s_p4_0[] = { }; static long _vq_quantmap__44c8_s_p4_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -156902,7 +145122,7 @@ static float _vq_quantthresh__44c8_s_p5_0[] = { }; static long _vq_quantmap__44c8_s_p5_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c8_s_p5_0 = { @@ -156954,8 +145174,8 @@ static float _vq_quantthresh__44c8_s_p5_1[] = { }; static long _vq_quantmap__44c8_s_p5_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c8_s_p5_1 = { @@ -157012,8 +145232,8 @@ static float _vq_quantthresh__44c8_s_p6_0[] = { }; static long _vq_quantmap__44c8_s_p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c8_s_p6_0 = { @@ -157052,7 +145272,7 @@ static float _vq_quantthresh__44c8_s_p6_1[] = { }; static long _vq_quantmap__44c8_s_p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c8_s_p6_1 = { @@ -157109,8 +145329,8 @@ static float _vq_quantthresh__44c8_s_p7_0[] = { }; static long _vq_quantmap__44c8_s_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c8_s_p7_0 = { @@ -157162,8 +145382,8 @@ static float _vq_quantthresh__44c8_s_p7_1[] = { }; static long _vq_quantmap__44c8_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c8_s_p7_1 = { @@ -157226,8 +145446,8 @@ static float _vq_quantthresh__44c8_s_p8_0[] = { }; static long _vq_quantmap__44c8_s_p8_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44c8_s_p8_0 = { @@ -157310,8 +145530,8 @@ static float _vq_quantthresh__44c8_s_p8_1[] = { }; static long _vq_quantmap__44c8_s_p8_1[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -157381,8 +145601,8 @@ static float _vq_quantthresh__44c8_s_p9_0[] = { }; static long _vq_quantmap__44c8_s_p9_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -157459,8 +145679,8 @@ static float _vq_quantthresh__44c8_s_p9_1[] = { }; static long _vq_quantmap__44c8_s_p9_1[] = { - 17, 15, 13, 11, 9, 7, 5, 3, - 1, 0, 2, 4, 6, 8, 10, 12, + 17, 15, 13, 11, 9, 7, 5, 3, + 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, }; @@ -157553,8 +145773,8 @@ static float _vq_quantthresh__44c8_s_p9_2[] = { static long _vq_quantmap__44c8_s_p9_2[] = { 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, @@ -157640,7 +145860,7 @@ static float _vq_quantthresh__44c9_s_p1_0[] = { }; static long _vq_quantmap__44c9_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c9_s_p1_0 = { @@ -157717,7 +145937,7 @@ static float _vq_quantthresh__44c9_s_p2_0[] = { }; static long _vq_quantmap__44c9_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c9_s_p2_0 = { @@ -157764,8 +145984,8 @@ static float _vq_quantthresh__44c9_s_p3_0[] = { }; static long _vq_quantmap__44c9_s_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c9_s_p3_0 = { @@ -157834,8 +146054,8 @@ static float _vq_quantthresh__44c9_s_p4_0[] = { }; static long _vq_quantmap__44c9_s_p4_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -157877,7 +146097,7 @@ static float _vq_quantthresh__44c9_s_p5_0[] = { }; static long _vq_quantmap__44c9_s_p5_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c9_s_p5_0 = { @@ -157929,8 +146149,8 @@ static float _vq_quantthresh__44c9_s_p5_1[] = { }; static long _vq_quantmap__44c9_s_p5_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c9_s_p5_1 = { @@ -157987,8 +146207,8 @@ static float _vq_quantthresh__44c9_s_p6_0[] = { }; static long _vq_quantmap__44c9_s_p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c9_s_p6_0 = { @@ -158027,7 +146247,7 @@ static float _vq_quantthresh__44c9_s_p6_1[] = { }; static long _vq_quantmap__44c9_s_p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c9_s_p6_1 = { @@ -158084,8 +146304,8 @@ static float _vq_quantthresh__44c9_s_p7_0[] = { }; static long _vq_quantmap__44c9_s_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c9_s_p7_0 = { @@ -158137,8 +146357,8 @@ static float _vq_quantthresh__44c9_s_p7_1[] = { }; static long _vq_quantmap__44c9_s_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c9_s_p7_1 = { @@ -158201,8 +146421,8 @@ static float _vq_quantthresh__44c9_s_p8_0[] = { }; static long _vq_quantmap__44c9_s_p8_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44c9_s_p8_0 = { @@ -158285,8 +146505,8 @@ static float _vq_quantthresh__44c9_s_p8_1[] = { }; static long _vq_quantmap__44c9_s_p8_1[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -158363,8 +146583,8 @@ static float _vq_quantthresh__44c9_s_p9_0[] = { }; static long _vq_quantmap__44c9_s_p9_0[] = { - 17, 15, 13, 11, 9, 7, 5, 3, - 1, 0, 2, 4, 6, 8, 10, 12, + 17, 15, 13, 11, 9, 7, 5, 3, + 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, }; @@ -158441,8 +146661,8 @@ static float _vq_quantthresh__44c9_s_p9_1[] = { }; static long _vq_quantmap__44c9_s_p9_1[] = { - 17, 15, 13, 11, 9, 7, 5, 3, - 1, 0, 2, 4, 6, 8, 10, 12, + 17, 15, 13, 11, 9, 7, 5, 3, + 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, }; @@ -158535,8 +146755,8 @@ static float _vq_quantthresh__44c9_s_p9_2[] = { static long _vq_quantmap__44c9_s_p9_2[] = { 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, @@ -159026,7 +147246,7 @@ static float _vq_quantthresh__44c0_s_p1_0[] = { }; static long _vq_quantmap__44c0_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c0_s_p1_0 = { @@ -159103,7 +147323,7 @@ static float _vq_quantthresh__44c0_s_p2_0[] = { }; static long _vq_quantmap__44c0_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c0_s_p2_0 = { @@ -159150,8 +147370,8 @@ static float _vq_quantthresh__44c0_s_p3_0[] = { }; static long _vq_quantmap__44c0_s_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c0_s_p3_0 = { @@ -159198,8 +147418,8 @@ static float _vq_quantthresh__44c0_s_p4_0[] = { }; static long _vq_quantmap__44c0_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c0_s_p4_0 = { @@ -159268,8 +147488,8 @@ static float _vq_quantthresh__44c0_s_p5_0[] = { }; static long _vq_quantmap__44c0_s_p5_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -159311,7 +147531,7 @@ static float _vq_quantthresh__44c0_s_p6_0[] = { }; static long _vq_quantmap__44c0_s_p6_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c0_s_p6_0 = { @@ -159363,8 +147583,8 @@ static float _vq_quantthresh__44c0_s_p6_1[] = { }; static long _vq_quantmap__44c0_s_p6_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c0_s_p6_1 = { @@ -159421,8 +147641,8 @@ static float _vq_quantthresh__44c0_s_p7_0[] = { }; static long _vq_quantmap__44c0_s_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c0_s_p7_0 = { @@ -159461,7 +147681,7 @@ static float _vq_quantthresh__44c0_s_p7_1[] = { }; static long _vq_quantmap__44c0_s_p7_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c0_s_p7_1 = { @@ -159538,7 +147758,7 @@ static float _vq_quantthresh__44c0_s_p8_0[] = { }; static long _vq_quantmap__44c0_s_p8_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c0_s_p8_0 = { @@ -159595,8 +147815,8 @@ static float _vq_quantthresh__44c0_s_p8_1[] = { }; static long _vq_quantmap__44c0_s_p8_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c0_s_p8_1 = { @@ -159665,8 +147885,8 @@ static float _vq_quantthresh__44c0_s_p8_2[] = { }; static long _vq_quantmap__44c0_s_p8_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -160153,7 +148373,7 @@ static float _vq_quantthresh__44c0_sm_p1_0[] = { }; static long _vq_quantmap__44c0_sm_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c0_sm_p1_0 = { @@ -160230,7 +148450,7 @@ static float _vq_quantthresh__44c0_sm_p2_0[] = { }; static long _vq_quantmap__44c0_sm_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c0_sm_p2_0 = { @@ -160277,8 +148497,8 @@ static float _vq_quantthresh__44c0_sm_p3_0[] = { }; static long _vq_quantmap__44c0_sm_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c0_sm_p3_0 = { @@ -160325,8 +148545,8 @@ static float _vq_quantthresh__44c0_sm_p4_0[] = { }; static long _vq_quantmap__44c0_sm_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c0_sm_p4_0 = { @@ -160395,8 +148615,8 @@ static float _vq_quantthresh__44c0_sm_p5_0[] = { }; static long _vq_quantmap__44c0_sm_p5_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -160438,7 +148658,7 @@ static float _vq_quantthresh__44c0_sm_p6_0[] = { }; static long _vq_quantmap__44c0_sm_p6_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c0_sm_p6_0 = { @@ -160490,8 +148710,8 @@ static float _vq_quantthresh__44c0_sm_p6_1[] = { }; static long _vq_quantmap__44c0_sm_p6_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c0_sm_p6_1 = { @@ -160548,8 +148768,8 @@ static float _vq_quantthresh__44c0_sm_p7_0[] = { }; static long _vq_quantmap__44c0_sm_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c0_sm_p7_0 = { @@ -160588,7 +148808,7 @@ static float _vq_quantthresh__44c0_sm_p7_1[] = { }; static long _vq_quantmap__44c0_sm_p7_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c0_sm_p7_1 = { @@ -160635,8 +148855,8 @@ static float _vq_quantthresh__44c0_sm_p8_0[] = { }; static long _vq_quantmap__44c0_sm_p8_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c0_sm_p8_0 = { @@ -160693,8 +148913,8 @@ static float _vq_quantthresh__44c0_sm_p8_1[] = { }; static long _vq_quantmap__44c0_sm_p8_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c0_sm_p8_1 = { @@ -160763,8 +148983,8 @@ static float _vq_quantthresh__44c0_sm_p8_2[] = { }; static long _vq_quantmap__44c0_sm_p8_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -161251,7 +149471,7 @@ static float _vq_quantthresh__44c1_s_p1_0[] = { }; static long _vq_quantmap__44c1_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c1_s_p1_0 = { @@ -161328,7 +149548,7 @@ static float _vq_quantthresh__44c1_s_p2_0[] = { }; static long _vq_quantmap__44c1_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c1_s_p2_0 = { @@ -161375,8 +149595,8 @@ static float _vq_quantthresh__44c1_s_p3_0[] = { }; static long _vq_quantmap__44c1_s_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c1_s_p3_0 = { @@ -161423,8 +149643,8 @@ static float _vq_quantthresh__44c1_s_p4_0[] = { }; static long _vq_quantmap__44c1_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c1_s_p4_0 = { @@ -161493,8 +149713,8 @@ static float _vq_quantthresh__44c1_s_p5_0[] = { }; static long _vq_quantmap__44c1_s_p5_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -161536,7 +149756,7 @@ static float _vq_quantthresh__44c1_s_p6_0[] = { }; static long _vq_quantmap__44c1_s_p6_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c1_s_p6_0 = { @@ -161588,8 +149808,8 @@ static float _vq_quantthresh__44c1_s_p6_1[] = { }; static long _vq_quantmap__44c1_s_p6_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c1_s_p6_1 = { @@ -161646,8 +149866,8 @@ static float _vq_quantthresh__44c1_s_p7_0[] = { }; static long _vq_quantmap__44c1_s_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c1_s_p7_0 = { @@ -161686,7 +149906,7 @@ static float _vq_quantthresh__44c1_s_p7_1[] = { }; static long _vq_quantmap__44c1_s_p7_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c1_s_p7_1 = { @@ -161743,8 +149963,8 @@ static float _vq_quantthresh__44c1_s_p8_0[] = { }; static long _vq_quantmap__44c1_s_p8_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c1_s_p8_0 = { @@ -161801,8 +150021,8 @@ static float _vq_quantthresh__44c1_s_p8_1[] = { }; static long _vq_quantmap__44c1_s_p8_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c1_s_p8_1 = { @@ -161871,8 +150091,8 @@ static float _vq_quantthresh__44c1_s_p8_2[] = { }; static long _vq_quantmap__44c1_s_p8_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -162359,7 +150579,7 @@ static float _vq_quantthresh__44c1_sm_p1_0[] = { }; static long _vq_quantmap__44c1_sm_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c1_sm_p1_0 = { @@ -162436,7 +150656,7 @@ static float _vq_quantthresh__44c1_sm_p2_0[] = { }; static long _vq_quantmap__44c1_sm_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c1_sm_p2_0 = { @@ -162483,8 +150703,8 @@ static float _vq_quantthresh__44c1_sm_p3_0[] = { }; static long _vq_quantmap__44c1_sm_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c1_sm_p3_0 = { @@ -162531,8 +150751,8 @@ static float _vq_quantthresh__44c1_sm_p4_0[] = { }; static long _vq_quantmap__44c1_sm_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44c1_sm_p4_0 = { @@ -162601,8 +150821,8 @@ static float _vq_quantthresh__44c1_sm_p5_0[] = { }; static long _vq_quantmap__44c1_sm_p5_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -162644,7 +150864,7 @@ static float _vq_quantthresh__44c1_sm_p6_0[] = { }; static long _vq_quantmap__44c1_sm_p6_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44c1_sm_p6_0 = { @@ -162696,8 +150916,8 @@ static float _vq_quantthresh__44c1_sm_p6_1[] = { }; static long _vq_quantmap__44c1_sm_p6_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44c1_sm_p6_1 = { @@ -162754,8 +150974,8 @@ static float _vq_quantthresh__44c1_sm_p7_0[] = { }; static long _vq_quantmap__44c1_sm_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c1_sm_p7_0 = { @@ -162794,7 +151014,7 @@ static float _vq_quantthresh__44c1_sm_p7_1[] = { }; static long _vq_quantmap__44c1_sm_p7_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44c1_sm_p7_1 = { @@ -162851,8 +151071,8 @@ static float _vq_quantthresh__44c1_sm_p8_0[] = { }; static long _vq_quantmap__44c1_sm_p8_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c1_sm_p8_0 = { @@ -162909,8 +151129,8 @@ static float _vq_quantthresh__44c1_sm_p8_1[] = { }; static long _vq_quantmap__44c1_sm_p8_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44c1_sm_p8_1 = { @@ -162979,8 +151199,8 @@ static float _vq_quantthresh__44c1_sm_p8_2[] = { }; static long _vq_quantmap__44c1_sm_p8_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -163467,7 +151687,7 @@ static float _vq_quantthresh__44cn1_s_p1_0[] = { }; static long _vq_quantmap__44cn1_s_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44cn1_s_p1_0 = { @@ -163544,7 +151764,7 @@ static float _vq_quantthresh__44cn1_s_p2_0[] = { }; static long _vq_quantmap__44cn1_s_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44cn1_s_p2_0 = { @@ -163591,8 +151811,8 @@ static float _vq_quantthresh__44cn1_s_p3_0[] = { }; static long _vq_quantmap__44cn1_s_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44cn1_s_p3_0 = { @@ -163639,8 +151859,8 @@ static float _vq_quantthresh__44cn1_s_p4_0[] = { }; static long _vq_quantmap__44cn1_s_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44cn1_s_p4_0 = { @@ -163709,8 +151929,8 @@ static float _vq_quantthresh__44cn1_s_p5_0[] = { }; static long _vq_quantmap__44cn1_s_p5_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -163752,7 +151972,7 @@ static float _vq_quantthresh__44cn1_s_p6_0[] = { }; static long _vq_quantmap__44cn1_s_p6_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44cn1_s_p6_0 = { @@ -163804,8 +152024,8 @@ static float _vq_quantthresh__44cn1_s_p6_1[] = { }; static long _vq_quantmap__44cn1_s_p6_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44cn1_s_p6_1 = { @@ -163862,8 +152082,8 @@ static float _vq_quantthresh__44cn1_s_p7_0[] = { }; static long _vq_quantmap__44cn1_s_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44cn1_s_p7_0 = { @@ -163902,7 +152122,7 @@ static float _vq_quantthresh__44cn1_s_p7_1[] = { }; static long _vq_quantmap__44cn1_s_p7_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44cn1_s_p7_1 = { @@ -163979,7 +152199,7 @@ static float _vq_quantthresh__44cn1_s_p8_0[] = { }; static long _vq_quantmap__44cn1_s_p8_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44cn1_s_p8_0 = { @@ -164036,8 +152256,8 @@ static float _vq_quantthresh__44cn1_s_p8_1[] = { }; static long _vq_quantmap__44cn1_s_p8_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44cn1_s_p8_1 = { @@ -164106,8 +152326,8 @@ static float _vq_quantthresh__44cn1_s_p8_2[] = { }; static long _vq_quantmap__44cn1_s_p8_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -164594,7 +152814,7 @@ static float _vq_quantthresh__44cn1_sm_p1_0[] = { }; static long _vq_quantmap__44cn1_sm_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44cn1_sm_p1_0 = { @@ -164671,7 +152891,7 @@ static float _vq_quantthresh__44cn1_sm_p2_0[] = { }; static long _vq_quantmap__44cn1_sm_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44cn1_sm_p2_0 = { @@ -164718,8 +152938,8 @@ static float _vq_quantthresh__44cn1_sm_p3_0[] = { }; static long _vq_quantmap__44cn1_sm_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44cn1_sm_p3_0 = { @@ -164766,8 +152986,8 @@ static float _vq_quantthresh__44cn1_sm_p4_0[] = { }; static long _vq_quantmap__44cn1_sm_p4_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44cn1_sm_p4_0 = { @@ -164836,8 +153056,8 @@ static float _vq_quantthresh__44cn1_sm_p5_0[] = { }; static long _vq_quantmap__44cn1_sm_p5_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -164879,7 +153099,7 @@ static float _vq_quantthresh__44cn1_sm_p6_0[] = { }; static long _vq_quantmap__44cn1_sm_p6_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44cn1_sm_p6_0 = { @@ -164931,8 +153151,8 @@ static float _vq_quantthresh__44cn1_sm_p6_1[] = { }; static long _vq_quantmap__44cn1_sm_p6_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44cn1_sm_p6_1 = { @@ -164989,8 +153209,8 @@ static float _vq_quantthresh__44cn1_sm_p7_0[] = { }; static long _vq_quantmap__44cn1_sm_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44cn1_sm_p7_0 = { @@ -165029,7 +153249,7 @@ static float _vq_quantthresh__44cn1_sm_p7_1[] = { }; static long _vq_quantmap__44cn1_sm_p7_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44cn1_sm_p7_1 = { @@ -165076,8 +153296,8 @@ static float _vq_quantthresh__44cn1_sm_p8_0[] = { }; static long _vq_quantmap__44cn1_sm_p8_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44cn1_sm_p8_0 = { @@ -165134,8 +153354,8 @@ static float _vq_quantthresh__44cn1_sm_p8_1[] = { }; static long _vq_quantmap__44cn1_sm_p8_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44cn1_sm_p8_1 = { @@ -165204,8 +153424,8 @@ static float _vq_quantthresh__44cn1_sm_p8_2[] = { }; static long _vq_quantmap__44cn1_sm_p8_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -165248,11 +153468,8 @@ static static_codebook _huff_book__44cn1_sm_short = { }; /********* End of inlined file: res_books_stereo.h *********/ -/***** residue backends *********************************************/ - static vorbis_info_residue0 _residue_44_low={ 0,-1, -1, 9,-1, - /* 0 1 2 3 4 5 6 7 */ {0}, {-1}, { .5, 1.5, 2.5, 2.5, 4.5, 8.5, 16.5, 32.5}, @@ -165261,7 +153478,6 @@ static vorbis_info_residue0 _residue_44_low={ static vorbis_info_residue0 _residue_44_mid={ 0,-1, -1, 10,-1, - /* 0 1 2 3 4 5 6 7 8 */ {0}, {-1}, { .5, 1.5, 1.5, 2.5, 2.5, 4.5, 8.5, 16.5, 32.5}, @@ -165270,7 +153486,6 @@ static vorbis_info_residue0 _residue_44_mid={ static vorbis_info_residue0 _residue_44_high={ 0,-1, -1, 10,-1, - /* 0 1 2 3 4 5 6 7 8 */ {0}, {-1}, { .5, 1.5, 2.5, 4.5, 8.5, 16.5, 32.5, 71.5,157.5}, @@ -165279,129 +153494,129 @@ static vorbis_info_residue0 _residue_44_high={ static static_bookblock _resbook_44s_n1={ { - {0},{0,0,&_44cn1_s_p1_0},{0,0,&_44cn1_s_p2_0}, - {0,0,&_44cn1_s_p3_0},{0,0,&_44cn1_s_p4_0},{0,0,&_44cn1_s_p5_0}, - {&_44cn1_s_p6_0,&_44cn1_s_p6_1},{&_44cn1_s_p7_0,&_44cn1_s_p7_1}, - {&_44cn1_s_p8_0,&_44cn1_s_p8_1,&_44cn1_s_p8_2} + {0},{0,0,&_44cn1_s_p1_0},{0,0,&_44cn1_s_p2_0}, + {0,0,&_44cn1_s_p3_0},{0,0,&_44cn1_s_p4_0},{0,0,&_44cn1_s_p5_0}, + {&_44cn1_s_p6_0,&_44cn1_s_p6_1},{&_44cn1_s_p7_0,&_44cn1_s_p7_1}, + {&_44cn1_s_p8_0,&_44cn1_s_p8_1,&_44cn1_s_p8_2} } }; static static_bookblock _resbook_44sm_n1={ { - {0},{0,0,&_44cn1_sm_p1_0},{0,0,&_44cn1_sm_p2_0}, - {0,0,&_44cn1_sm_p3_0},{0,0,&_44cn1_sm_p4_0},{0,0,&_44cn1_sm_p5_0}, - {&_44cn1_sm_p6_0,&_44cn1_sm_p6_1},{&_44cn1_sm_p7_0,&_44cn1_sm_p7_1}, - {&_44cn1_sm_p8_0,&_44cn1_sm_p8_1,&_44cn1_sm_p8_2} + {0},{0,0,&_44cn1_sm_p1_0},{0,0,&_44cn1_sm_p2_0}, + {0,0,&_44cn1_sm_p3_0},{0,0,&_44cn1_sm_p4_0},{0,0,&_44cn1_sm_p5_0}, + {&_44cn1_sm_p6_0,&_44cn1_sm_p6_1},{&_44cn1_sm_p7_0,&_44cn1_sm_p7_1}, + {&_44cn1_sm_p8_0,&_44cn1_sm_p8_1,&_44cn1_sm_p8_2} } }; static static_bookblock _resbook_44s_0={ { - {0},{0,0,&_44c0_s_p1_0},{0,0,&_44c0_s_p2_0}, - {0,0,&_44c0_s_p3_0},{0,0,&_44c0_s_p4_0},{0,0,&_44c0_s_p5_0}, - {&_44c0_s_p6_0,&_44c0_s_p6_1},{&_44c0_s_p7_0,&_44c0_s_p7_1}, - {&_44c0_s_p8_0,&_44c0_s_p8_1,&_44c0_s_p8_2} + {0},{0,0,&_44c0_s_p1_0},{0,0,&_44c0_s_p2_0}, + {0,0,&_44c0_s_p3_0},{0,0,&_44c0_s_p4_0},{0,0,&_44c0_s_p5_0}, + {&_44c0_s_p6_0,&_44c0_s_p6_1},{&_44c0_s_p7_0,&_44c0_s_p7_1}, + {&_44c0_s_p8_0,&_44c0_s_p8_1,&_44c0_s_p8_2} } }; static static_bookblock _resbook_44sm_0={ { - {0},{0,0,&_44c0_sm_p1_0},{0,0,&_44c0_sm_p2_0}, - {0,0,&_44c0_sm_p3_0},{0,0,&_44c0_sm_p4_0},{0,0,&_44c0_sm_p5_0}, - {&_44c0_sm_p6_0,&_44c0_sm_p6_1},{&_44c0_sm_p7_0,&_44c0_sm_p7_1}, - {&_44c0_sm_p8_0,&_44c0_sm_p8_1,&_44c0_sm_p8_2} + {0},{0,0,&_44c0_sm_p1_0},{0,0,&_44c0_sm_p2_0}, + {0,0,&_44c0_sm_p3_0},{0,0,&_44c0_sm_p4_0},{0,0,&_44c0_sm_p5_0}, + {&_44c0_sm_p6_0,&_44c0_sm_p6_1},{&_44c0_sm_p7_0,&_44c0_sm_p7_1}, + {&_44c0_sm_p8_0,&_44c0_sm_p8_1,&_44c0_sm_p8_2} } }; static static_bookblock _resbook_44s_1={ { - {0},{0,0,&_44c1_s_p1_0},{0,0,&_44c1_s_p2_0}, - {0,0,&_44c1_s_p3_0},{0,0,&_44c1_s_p4_0},{0,0,&_44c1_s_p5_0}, - {&_44c1_s_p6_0,&_44c1_s_p6_1},{&_44c1_s_p7_0,&_44c1_s_p7_1}, - {&_44c1_s_p8_0,&_44c1_s_p8_1,&_44c1_s_p8_2} + {0},{0,0,&_44c1_s_p1_0},{0,0,&_44c1_s_p2_0}, + {0,0,&_44c1_s_p3_0},{0,0,&_44c1_s_p4_0},{0,0,&_44c1_s_p5_0}, + {&_44c1_s_p6_0,&_44c1_s_p6_1},{&_44c1_s_p7_0,&_44c1_s_p7_1}, + {&_44c1_s_p8_0,&_44c1_s_p8_1,&_44c1_s_p8_2} } }; static static_bookblock _resbook_44sm_1={ { - {0},{0,0,&_44c1_sm_p1_0},{0,0,&_44c1_sm_p2_0}, - {0,0,&_44c1_sm_p3_0},{0,0,&_44c1_sm_p4_0},{0,0,&_44c1_sm_p5_0}, - {&_44c1_sm_p6_0,&_44c1_sm_p6_1},{&_44c1_sm_p7_0,&_44c1_sm_p7_1}, - {&_44c1_sm_p8_0,&_44c1_sm_p8_1,&_44c1_sm_p8_2} + {0},{0,0,&_44c1_sm_p1_0},{0,0,&_44c1_sm_p2_0}, + {0,0,&_44c1_sm_p3_0},{0,0,&_44c1_sm_p4_0},{0,0,&_44c1_sm_p5_0}, + {&_44c1_sm_p6_0,&_44c1_sm_p6_1},{&_44c1_sm_p7_0,&_44c1_sm_p7_1}, + {&_44c1_sm_p8_0,&_44c1_sm_p8_1,&_44c1_sm_p8_2} } }; static static_bookblock _resbook_44s_2={ { - {0},{0,0,&_44c2_s_p1_0},{0,0,&_44c2_s_p2_0},{0,0,&_44c2_s_p3_0}, - {0,0,&_44c2_s_p4_0},{0,0,&_44c2_s_p5_0},{0,0,&_44c2_s_p6_0}, - {&_44c2_s_p7_0,&_44c2_s_p7_1},{&_44c2_s_p8_0,&_44c2_s_p8_1}, - {&_44c2_s_p9_0,&_44c2_s_p9_1,&_44c2_s_p9_2} + {0},{0,0,&_44c2_s_p1_0},{0,0,&_44c2_s_p2_0},{0,0,&_44c2_s_p3_0}, + {0,0,&_44c2_s_p4_0},{0,0,&_44c2_s_p5_0},{0,0,&_44c2_s_p6_0}, + {&_44c2_s_p7_0,&_44c2_s_p7_1},{&_44c2_s_p8_0,&_44c2_s_p8_1}, + {&_44c2_s_p9_0,&_44c2_s_p9_1,&_44c2_s_p9_2} } }; static static_bookblock _resbook_44s_3={ { - {0},{0,0,&_44c3_s_p1_0},{0,0,&_44c3_s_p2_0},{0,0,&_44c3_s_p3_0}, - {0,0,&_44c3_s_p4_0},{0,0,&_44c3_s_p5_0},{0,0,&_44c3_s_p6_0}, - {&_44c3_s_p7_0,&_44c3_s_p7_1},{&_44c3_s_p8_0,&_44c3_s_p8_1}, - {&_44c3_s_p9_0,&_44c3_s_p9_1,&_44c3_s_p9_2} + {0},{0,0,&_44c3_s_p1_0},{0,0,&_44c3_s_p2_0},{0,0,&_44c3_s_p3_0}, + {0,0,&_44c3_s_p4_0},{0,0,&_44c3_s_p5_0},{0,0,&_44c3_s_p6_0}, + {&_44c3_s_p7_0,&_44c3_s_p7_1},{&_44c3_s_p8_0,&_44c3_s_p8_1}, + {&_44c3_s_p9_0,&_44c3_s_p9_1,&_44c3_s_p9_2} } }; static static_bookblock _resbook_44s_4={ { - {0},{0,0,&_44c4_s_p1_0},{0,0,&_44c4_s_p2_0},{0,0,&_44c4_s_p3_0}, - {0,0,&_44c4_s_p4_0},{0,0,&_44c4_s_p5_0},{0,0,&_44c4_s_p6_0}, - {&_44c4_s_p7_0,&_44c4_s_p7_1},{&_44c4_s_p8_0,&_44c4_s_p8_1}, - {&_44c4_s_p9_0,&_44c4_s_p9_1,&_44c4_s_p9_2} + {0},{0,0,&_44c4_s_p1_0},{0,0,&_44c4_s_p2_0},{0,0,&_44c4_s_p3_0}, + {0,0,&_44c4_s_p4_0},{0,0,&_44c4_s_p5_0},{0,0,&_44c4_s_p6_0}, + {&_44c4_s_p7_0,&_44c4_s_p7_1},{&_44c4_s_p8_0,&_44c4_s_p8_1}, + {&_44c4_s_p9_0,&_44c4_s_p9_1,&_44c4_s_p9_2} } }; static static_bookblock _resbook_44s_5={ { - {0},{0,0,&_44c5_s_p1_0},{0,0,&_44c5_s_p2_0},{0,0,&_44c5_s_p3_0}, - {0,0,&_44c5_s_p4_0},{0,0,&_44c5_s_p5_0},{0,0,&_44c5_s_p6_0}, - {&_44c5_s_p7_0,&_44c5_s_p7_1},{&_44c5_s_p8_0,&_44c5_s_p8_1}, - {&_44c5_s_p9_0,&_44c5_s_p9_1,&_44c5_s_p9_2} + {0},{0,0,&_44c5_s_p1_0},{0,0,&_44c5_s_p2_0},{0,0,&_44c5_s_p3_0}, + {0,0,&_44c5_s_p4_0},{0,0,&_44c5_s_p5_0},{0,0,&_44c5_s_p6_0}, + {&_44c5_s_p7_0,&_44c5_s_p7_1},{&_44c5_s_p8_0,&_44c5_s_p8_1}, + {&_44c5_s_p9_0,&_44c5_s_p9_1,&_44c5_s_p9_2} } }; static static_bookblock _resbook_44s_6={ { - {0},{0,0,&_44c6_s_p1_0},{0,0,&_44c6_s_p2_0},{0,0,&_44c6_s_p3_0}, - {0,0,&_44c6_s_p4_0}, - {&_44c6_s_p5_0,&_44c6_s_p5_1}, - {&_44c6_s_p6_0,&_44c6_s_p6_1}, - {&_44c6_s_p7_0,&_44c6_s_p7_1}, - {&_44c6_s_p8_0,&_44c6_s_p8_1}, - {&_44c6_s_p9_0,&_44c6_s_p9_1,&_44c6_s_p9_2} + {0},{0,0,&_44c6_s_p1_0},{0,0,&_44c6_s_p2_0},{0,0,&_44c6_s_p3_0}, + {0,0,&_44c6_s_p4_0}, + {&_44c6_s_p5_0,&_44c6_s_p5_1}, + {&_44c6_s_p6_0,&_44c6_s_p6_1}, + {&_44c6_s_p7_0,&_44c6_s_p7_1}, + {&_44c6_s_p8_0,&_44c6_s_p8_1}, + {&_44c6_s_p9_0,&_44c6_s_p9_1,&_44c6_s_p9_2} } }; static static_bookblock _resbook_44s_7={ { - {0},{0,0,&_44c7_s_p1_0},{0,0,&_44c7_s_p2_0},{0,0,&_44c7_s_p3_0}, - {0,0,&_44c7_s_p4_0}, - {&_44c7_s_p5_0,&_44c7_s_p5_1}, - {&_44c7_s_p6_0,&_44c7_s_p6_1}, - {&_44c7_s_p7_0,&_44c7_s_p7_1}, - {&_44c7_s_p8_0,&_44c7_s_p8_1}, - {&_44c7_s_p9_0,&_44c7_s_p9_1,&_44c7_s_p9_2} + {0},{0,0,&_44c7_s_p1_0},{0,0,&_44c7_s_p2_0},{0,0,&_44c7_s_p3_0}, + {0,0,&_44c7_s_p4_0}, + {&_44c7_s_p5_0,&_44c7_s_p5_1}, + {&_44c7_s_p6_0,&_44c7_s_p6_1}, + {&_44c7_s_p7_0,&_44c7_s_p7_1}, + {&_44c7_s_p8_0,&_44c7_s_p8_1}, + {&_44c7_s_p9_0,&_44c7_s_p9_1,&_44c7_s_p9_2} } }; static static_bookblock _resbook_44s_8={ { - {0},{0,0,&_44c8_s_p1_0},{0,0,&_44c8_s_p2_0},{0,0,&_44c8_s_p3_0}, - {0,0,&_44c8_s_p4_0}, - {&_44c8_s_p5_0,&_44c8_s_p5_1}, - {&_44c8_s_p6_0,&_44c8_s_p6_1}, - {&_44c8_s_p7_0,&_44c8_s_p7_1}, - {&_44c8_s_p8_0,&_44c8_s_p8_1}, - {&_44c8_s_p9_0,&_44c8_s_p9_1,&_44c8_s_p9_2} + {0},{0,0,&_44c8_s_p1_0},{0,0,&_44c8_s_p2_0},{0,0,&_44c8_s_p3_0}, + {0,0,&_44c8_s_p4_0}, + {&_44c8_s_p5_0,&_44c8_s_p5_1}, + {&_44c8_s_p6_0,&_44c8_s_p6_1}, + {&_44c8_s_p7_0,&_44c8_s_p7_1}, + {&_44c8_s_p8_0,&_44c8_s_p8_1}, + {&_44c8_s_p9_0,&_44c8_s_p9_1,&_44c8_s_p9_2} } }; static static_bookblock _resbook_44s_9={ { - {0},{0,0,&_44c9_s_p1_0},{0,0,&_44c9_s_p2_0},{0,0,&_44c9_s_p3_0}, - {0,0,&_44c9_s_p4_0}, - {&_44c9_s_p5_0,&_44c9_s_p5_1}, - {&_44c9_s_p6_0,&_44c9_s_p6_1}, - {&_44c9_s_p7_0,&_44c9_s_p7_1}, - {&_44c9_s_p8_0,&_44c9_s_p8_1}, - {&_44c9_s_p9_0,&_44c9_s_p9_1,&_44c9_s_p9_2} + {0},{0,0,&_44c9_s_p1_0},{0,0,&_44c9_s_p2_0},{0,0,&_44c9_s_p3_0}, + {0,0,&_44c9_s_p4_0}, + {&_44c9_s_p5_0,&_44c9_s_p5_1}, + {&_44c9_s_p6_0,&_44c9_s_p6_1}, + {&_44c9_s_p7_0,&_44c9_s_p7_1}, + {&_44c9_s_p8_0,&_44c9_s_p8_1}, + {&_44c9_s_p9_0,&_44c9_s_p9_1,&_44c9_s_p9_2} } }; @@ -165522,7 +153737,6 @@ static vorbis_mapping_template _mapres_template_44_stereo[]={ /********* End of inlined file: residue_44.h *********/ /********* Start of inlined file: psych_44.h *********/ -/* preecho trigger settings *****************************************/ static vorbis_info_psy_global _psy_global_44[5]={ @@ -165558,422 +153772,264 @@ static vorbis_info_psy_global _psy_global_44[5]={ }, }; -/* noise compander lookups * low, mid, high quality ****************/ static compandblock _psy_compand_44[6]={ - /* sub-mode Z short */ {{ - 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ - 8, 9,10,11,12,13,14, 15, /* 15dB */ - 16,17,18,19,20,21,22, 23, /* 23dB */ - 24,25,26,27,28,29,30, 31, /* 31dB */ - 32,33,34,35,36,37,38, 39, /* 39dB */ + 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ + 8, 9,10,11,12,13,14, 15, /* 15dB */ + 16,17,18,19,20,21,22, 23, /* 23dB */ + 24,25,26,27,28,29,30, 31, /* 31dB */ + 32,33,34,35,36,37,38, 39, /* 39dB */ }}, - /* mode_Z nominal short */ {{ - 0, 1, 2, 3, 4, 5, 6, 6, /* 7dB */ - 7, 7, 7, 7, 6, 6, 6, 7, /* 15dB */ - 7, 8, 9,10,11,12,13, 14, /* 23dB */ - 15,16,17,17,17,18,18, 19, /* 31dB */ - 19,19,20,21,22,23,24, 25, /* 39dB */ + 0, 1, 2, 3, 4, 5, 6, 6, /* 7dB */ + 7, 7, 7, 7, 6, 6, 6, 7, /* 15dB */ + 7, 8, 9,10,11,12,13, 14, /* 23dB */ + 15,16,17,17,17,18,18, 19, /* 31dB */ + 19,19,20,21,22,23,24, 25, /* 39dB */ }}, - /* mode A short */ {{ - 0, 1, 2, 3, 4, 5, 5, 5, /* 7dB */ - 6, 6, 6, 5, 4, 4, 4, 4, /* 15dB */ - 4, 4, 5, 5, 5, 6, 6, 6, /* 23dB */ - 7, 7, 7, 8, 8, 8, 9, 10, /* 31dB */ - 11,12,13,14,15,16,17, 18, /* 39dB */ + 0, 1, 2, 3, 4, 5, 5, 5, /* 7dB */ + 6, 6, 6, 5, 4, 4, 4, 4, /* 15dB */ + 4, 4, 5, 5, 5, 6, 6, 6, /* 23dB */ + 7, 7, 7, 8, 8, 8, 9, 10, /* 31dB */ + 11,12,13,14,15,16,17, 18, /* 39dB */ }}, - /* sub-mode Z long */ {{ - 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ - 8, 9,10,11,12,13,14, 15, /* 15dB */ - 16,17,18,19,20,21,22, 23, /* 23dB */ - 24,25,26,27,28,29,30, 31, /* 31dB */ - 32,33,34,35,36,37,38, 39, /* 39dB */ + 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ + 8, 9,10,11,12,13,14, 15, /* 15dB */ + 16,17,18,19,20,21,22, 23, /* 23dB */ + 24,25,26,27,28,29,30, 31, /* 31dB */ + 32,33,34,35,36,37,38, 39, /* 39dB */ }}, - /* mode_Z nominal long */ {{ - 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ - 8, 9,10,11,12,12,13, 13, /* 15dB */ - 13,14,14,14,15,15,15, 15, /* 23dB */ - 16,16,17,17,17,18,18, 19, /* 31dB */ - 19,19,20,21,22,23,24, 25, /* 39dB */ + 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ + 8, 9,10,11,12,12,13, 13, /* 15dB */ + 13,14,14,14,15,15,15, 15, /* 23dB */ + 16,16,17,17,17,18,18, 19, /* 31dB */ + 19,19,20,21,22,23,24, 25, /* 39dB */ }}, - /* mode A long */ {{ - 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ - 8, 8, 7, 6, 5, 4, 4, 4, /* 15dB */ - 4, 4, 5, 5, 5, 6, 6, 6, /* 23dB */ - 7, 7, 7, 8, 8, 8, 9, 10, /* 31dB */ - 11,12,13,14,15,16,17, 18, /* 39dB */ + 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ + 8, 8, 7, 6, 5, 4, 4, 4, /* 15dB */ + 4, 4, 5, 5, 5, 6, 6, 6, /* 23dB */ + 7, 7, 7, 8, 8, 8, 9, 10, /* 31dB */ + 11,12,13,14,15,16,17, 18, /* 39dB */ }} }; -/* tonal masking curve level adjustments *************************/ - static vp_adjblock _vp_tonemask_adj_longblock[12]={ - /* 63 125 250 500 1 2 4 8 16 */ - {{ -3, -8,-13,-15,-10,-10,-10,-10,-10,-10,-10, 0, 0, 0, 0, 0, 0}}, /* -1 */ -/* {{-15,-15,-15,-15,-10, -8, -4, -2, 0, 0, 0, 10, 0, 0, 0, 0, 0}}, 0 */ {{ -4,-10,-14,-16,-15,-14,-13,-12,-12,-12,-11, -1, -1, -1, -1, -1, 0}}, /* 0 */ -/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 5, 0, 0, 0, 0, 0}}, 1 */ {{ -6,-12,-14,-16,-15,-15,-14,-13,-13,-12,-12, -2, -2, -1, -1, -1, 0}}, /* 1 */ -/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 2 */ {{-12,-13,-14,-16,-16,-16,-15,-14,-13,-12,-12, -6, -3, -1, -1, -1, 0}}, /* 2 */ -/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 3 */ {{-15,-15,-15,-16,-16,-16,-16,-14,-13,-13,-13,-10, -4, -2, -1, -1, 0}}, /* 3 */ -/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, *//* 4 */ +/* 4 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-13,-11, -7 -3, -1, -1 , 0}}, /* 4 */ -/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 5 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-13,-11, -7 -3, -1, -1 , 0}}, /* 5 */ -/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 6 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -8, -4, -2, -2, 0}}, /* 6 */ -/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 7 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 7 */ -/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 8 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 8 */ -/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 9 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 9 */ -/* {{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 10 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 10 */ }; static vp_adjblock _vp_tonemask_adj_otherblock[12]={ - /* 63 125 250 500 1 2 4 8 16 */ {{ -3, -8,-13,-15,-10,-10, -9, -9, -9, -9, -9, 1, 1, 1, 1, 1, 1}}, /* -1 */ -/* {{-20,-20,-20,-20,-14,-12,-10, -8, -4, 0, 0, 10, 0, 0, 0, 0, 0}}, 0 */ {{ -4,-10,-14,-16,-14,-13,-12,-12,-11,-11,-10, 0, 0, 0, 0, 0, 0}}, /* 0 */ -/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 5, 0, 0, 0, 0, 0}}, 1 */ {{ -6,-12,-14,-16,-15,-15,-14,-13,-13,-12,-12, -2, -2, -1, 0, 0, 0}}, /* 1 */ -/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 2 */ {{-12,-13,-14,-16,-16,-16,-15,-14,-13,-12,-12, -5, -2, -1, 0, 0, 0}}, /* 2 */ -/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 3 */ {{-15,-15,-15,-16,-16,-16,-16,-14,-13,-13,-13,-10, -4, -2, 0, 0, 0}}, /* 3 */ -/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 4 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-13,-11, -7 -3, -1, -1 , 0}}, /* 4 */ -/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 5 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-13,-11, -7 -3, -1, -1 , 0}}, /* 5 */ -/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 6 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -8, -4, -2, -2, 0}}, /* 6 */ -/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 7 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 7 */ -/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 8 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 8 */ -/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 9 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 9 */ -/* {{-20,-20,-20,-20,-20,-18,-16,-14,-10, 0, 0, 0, 0, 0, 0, 0, 0}}, 10 */ {{-16,-16,-16,-16,-16,-16,-16,-15,-14,-14,-14,-12, -9, -4, -2, -2, 0}}, /* 10 */ }; -/* noise bias (transition block) */ static noise3 _psy_noisebias_trans[12]={ - /* 63 125 250 500 1k 2k 4k 8k 16k*/ - /* -1 */ {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 8, 8, 8, 8, 10, 12, 14, 20}, - {-30,-30,-30,-30,-26,-20,-16, -8, -6, -6, -2, 2, 2, 3, 6, 6, 15}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, - /* 0 - {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 5, 8, 10}, - {-30,-30,-30,-30,-26,-22,-20,-14, -8, -4, 0, 0, 0, 0, 2, 4, 10}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -6, -4, -4, -4, -2}}},*/ + {-30,-30,-30,-30,-26,-20,-16, -8, -6, -6, -2, 2, 2, 3, 6, 6, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, {{{-15,-15,-15,-15,-15,-12, -6, -4, 0, 2, 4, 4, 5, 5, 5, 8, 10}, - {-30,-30,-30,-30,-26,-22,-20,-14, -8, -4, 0, 0, 0, 0, 2, 3, 6}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -6, -4, -4, -4, -2}}}, - /* 1 + {-30,-30,-30,-30,-26,-22,-20,-14, -8, -4, 0, 0, 0, 0, 2, 3, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -6, -4, -4, -4, -2}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 5, 8, 10}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -2, -2, -2, -2, 0, 2, 8}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -6, -6, -6, -4}}},*/ - {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 5, 8, 10}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -2, -2, -2, -2, 0, 1, 4}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -6, -6, -6, -4}}}, - /* 2 + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -2, -2, -2, -2, 0, 1, 4}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -6, -6, -6, -4}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 2, 2, 4, 4, 5, 6, 10}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -2, -2, -2, -2, 0, 2, 6}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, */ - {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 2, 2, 4, 4, 5, 6, 10}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -2, -1, 0, 3}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -7, -4}}}, - /* 3 + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -2, -1, 0, 3}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -7, -4}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 2, 2, 4, 4, 4, 5, 8}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -3, -1, 1, 6}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}},*/ - {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 2, 2, 4, 4, 4, 5, 8}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -3, -2, 0, 2}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, - /* 4 + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -3, -2, 0, 2}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, {{{-20,-20,-20,-20,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -3, -1, 1, 5}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}},*/ - {{{-20,-20,-20,-20,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -3, -2, -1, 1}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, - /* 5 + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -3, -3, -3, -3, -2, -1, 1}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, - {-32,-32,-32,-32,-28,-24,-22,-16,-12, -6, -4, -4, -4, -4, -2, -1, 2}, - {-34,-34,-34,-34,-30,-24,-24,-18,-14,-12,-12,-12,-12,-10,-10, -9, -5}}}, */ + {-32,-32,-32,-32,-28,-24,-22,-16,-12, -6, -4, -4, -4, -4, -3, -1, 0}, + {-34,-34,-34,-34,-30,-24,-24,-18,-14,-12,-12,-12,-12,-10,-10, -9, -5}}}, {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, - {-32,-32,-32,-32,-28,-24,-22,-16,-12, -6, -4, -4, -4, -4, -3, -1, 0}, - {-34,-34,-34,-34,-30,-24,-24,-18,-14,-12,-12,-12,-12,-10,-10, -9, -5}}}, - /* 6 + {-32,-32,-32,-32,-28,-24,-24,-18,-14, -8, -6, -6, -6, -6, -5, -2, 0}, + {-34,-34,-34,-34,-30,-26,-26,-24,-22,-19,-19,-19,-19,-18,-17,-16,-12}}}, {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, - {-32,-32,-32,-32,-28,-24,-24,-18,-14, -8, -6, -6, -6, -6, -4, -2, 1}, - {-34,-34,-34,-34,-30,-26,-24,-18,-17,-15,-15,-15,-15,-13,-13,-12, -8}}},*/ - {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, - {-32,-32,-32,-32,-28,-24,-24,-18,-14, -8, -6, -6, -6, -6, -5, -2, 0}, - {-34,-34,-34,-34,-30,-26,-26,-24,-22,-19,-19,-19,-19,-18,-17,-16,-12}}}, - /* 7 - {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, - {-32,-32,-32,-32,-28,-24,-24,-18,-14,-12,-10, -8, -8, -8, -6, -4, 0}, - {-34,-34,-34,-34,-30,-26,-26,-24,-22,-19,-19,-19,-19,-18,-17,-16,-12}}},*/ - {{{-24,-24,-24,-24,-20,-18,-14, -8, -1, 1, 1, 1, 2, 3, 3, 4, 7}, - {-32,-32,-32,-32,-28,-24,-24,-24,-18,-14,-12,-10,-10,-10, -8, -6, -2}, - {-34,-34,-34,-34,-30,-26,-26,-26,-24,-24,-24,-24,-24,-24,-24,-20,-16}}}, - /* 8 + {-32,-32,-32,-32,-28,-24,-24,-24,-18,-14,-12,-10,-10,-10, -8, -6, -2}, + {-34,-34,-34,-34,-30,-26,-26,-26,-24,-24,-24,-24,-24,-24,-24,-20,-16}}}, {{{-24,-24,-24,-24,-22,-20,-15,-10, -8, -2, 0, 0, 0, 1, 2, 3, 7}, - {-36,-36,-36,-36,-30,-30,-30,-24,-18,-14,-12,-10,-10,-10, -8, -6, -2}, - {-36,-36,-36,-36,-34,-30,-28,-26,-24,-24,-24,-24,-24,-24,-24,-20,-16}}},*/ - {{{-24,-24,-24,-24,-22,-20,-15,-10, -8, -2, 0, 0, 0, 1, 2, 3, 7}, - {-36,-36,-36,-36,-30,-30,-30,-24,-20,-16,-16,-16,-16,-14,-12,-10, -7}, - {-36,-36,-36,-36,-34,-30,-28,-26,-24,-30,-30,-30,-30,-30,-30,-24,-20}}}, - /* 9 + {-36,-36,-36,-36,-30,-30,-30,-24,-20,-16,-16,-16,-16,-14,-12,-10, -7}, + {-36,-36,-36,-36,-34,-30,-28,-26,-24,-30,-30,-30,-30,-30,-30,-24,-20}}}, {{{-28,-28,-28,-28,-28,-28,-28,-20,-14, -8, -4, -4, -4, -4, -4, -2, 2}, - {-36,-36,-36,-36,-34,-32,-32,-28,-20,-16,-16,-16,-16,-14,-12,-10, -7}, - {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-24,-20}}},*/ - {{{-28,-28,-28,-28,-28,-28,-28,-20,-14, -8, -4, -4, -4, -4, -4, -2, 2}, - {-38,-38,-38,-38,-36,-34,-34,-30,-24,-20,-20,-20,-20,-18,-16,-12,-10}, - {-40,-40,-40,-40,-40,-40,-40,-38,-35,-35,-35,-35,-35,-35,-35,-35,-30}}}, - /* 10 */ + {-38,-38,-38,-38,-36,-34,-34,-30,-24,-20,-20,-20,-20,-18,-16,-12,-10}, + {-40,-40,-40,-40,-40,-40,-40,-38,-35,-35,-35,-35,-35,-35,-35,-35,-30}}}, {{{-30,-30,-30,-30,-30,-30,-30,-28,-20,-14,-14,-14,-14,-14,-14,-12,-10}, - {-40,-40,-40,-40,-40,-40,-40,-40,-35,-30,-30,-30,-30,-30,-30,-30,-20}, - {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, + {-40,-40,-40,-40,-40,-40,-40,-40,-35,-30,-30,-30,-30,-30,-30,-30,-20}, + {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, }; -/* noise bias (long block) */ static noise3 _psy_noisebias_long[12]={ - /*63 125 250 500 1k 2k 4k 8k 16k*/ - /* -1 */ {{{-10,-10,-10,-10,-10, -4, 0, 0, 0, 6, 6, 6, 6, 10, 10, 12, 20}, - {-20,-20,-20,-20,-20,-20,-10, -2, 0, 0, 0, 0, 0, 2, 4, 6, 15}, - {-20,-20,-20,-20,-20,-20,-20,-10, -6, -6, -6, -6, -6, -4, -4, -4, -2}}}, + {-20,-20,-20,-20,-20,-20,-10, -2, 0, 0, 0, 0, 0, 2, 4, 6, 15}, + {-20,-20,-20,-20,-20,-20,-20,-10, -6, -6, -6, -6, -6, -4, -4, -4, -2}}}, - /* 0 */ - /* {{{-10,-10,-10,-10,-10,-10, -8, 2, 2, 2, 4, 4, 5, 5, 5, 8, 10}, - {-20,-20,-20,-20,-20,-20,-20,-14, -6, 0, 0, 0, 0, 0, 2, 4, 10}, - {-20,-20,-20,-20,-20,-20,-20,-14, -8, -6, -6, -6, -6, -4, -4, -4, -2}}},*/ {{{-10,-10,-10,-10,-10,-10, -8, 2, 2, 2, 4, 4, 5, 5, 5, 8, 10}, - {-20,-20,-20,-20,-20,-20,-20,-14, -6, 0, 0, 0, 0, 0, 2, 3, 6}, - {-20,-20,-20,-20,-20,-20,-20,-14, -8, -6, -6, -6, -6, -4, -4, -4, -2}}}, - /* 1 */ - /* {{{-10,-10,-10,-10,-10,-10, -8, -4, 0, 2, 4, 4, 5, 5, 5, 8, 10}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -2, -2, -2, -2, 0, 2, 8}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10, -8, -8, -8, -8, -6, -6, -6, -4}}},*/ + {-20,-20,-20,-20,-20,-20,-20,-14, -6, 0, 0, 0, 0, 0, 2, 3, 6}, + {-20,-20,-20,-20,-20,-20,-20,-14, -8, -6, -6, -6, -6, -4, -4, -4, -2}}}, {{{-10,-10,-10,-10,-10,-10, -8, -4, 0, 2, 4, 4, 5, 5, 5, 8, 10}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -2, -2, -2, -2, 0, 1, 4}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10, -8, -8, -8, -8, -6, -6, -6, -4}}}, - /* 2 */ - /* {{{-10,-10,-10,-10,-10,-10,-10, -8, 0, 2, 2, 2, 4, 4, 5, 6, 10}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -2, -2, -2, -2, 0, 2, 6}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}},*/ + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -2, -2, -2, -2, 0, 1, 4}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -8, -8, -8, -8, -6, -6, -6, -4}}}, {{{-10,-10,-10,-10,-10,-10,-10, -8, 0, 2, 2, 2, 4, 4, 5, 6, 10}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -2, -1, 0, 3}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, - /* 3 */ - /* {{{-10,-10,-10,-10,-10,-10,-10, -8, 0, 2, 2, 2, 4, 4, 4, 5, 8}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -3, -1, 1, 6}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}},*/ + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -2, -1, 0, 3}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}}, {{{-10,-10,-10,-10,-10,-10,-10, -8, 0, 2, 2, 2, 4, 4, 4, 5, 8}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -3, -2, 0, 2}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -5}}}, - /* 4 */ - /* {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -3, -1, 1, 5}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -4}}},*/ + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -3, -2, 0, 2}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -5}}}, {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -3, -2, -1, 1}, - {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -7}}}, - /* 5 */ - /* {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, - {-22,-22,-22,-22,-22,-22,-22,-16,-12, -6, -4, -4, -4, -4, -2, -1, 2}, - {-24,-24,-24,-24,-24,-24,-24,-18,-14,-12,-12,-12,-12,-10,-10, -9, -5}}},*/ + {-20,-20,-20,-20,-20,-20,-20,-14,-10, -4, -3, -3, -3, -3, -2, -1, 1}, + {-20,-20,-20,-20,-20,-20,-20,-14,-10,-10,-10,-10,-10, -8, -8, -8, -7}}}, {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, - {-22,-22,-22,-22,-22,-22,-22,-16,-12, -6, -4, -4, -4, -4, -3, -1, 0}, - {-24,-24,-24,-24,-24,-24,-24,-18,-14,-12,-12,-12,-12,-10,-10, -9, -8}}}, - /* 6 */ - /* {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, - {-24,-24,-24,-24,-24,-24,-24,-18,-14, -8, -6, -6, -6, -6, -4, -2, 1}, - {-26,-26,-26,-26,-26,-26,-26,-18,-16,-15,-15,-15,-15,-13,-13,-12, -8}}},*/ + {-22,-22,-22,-22,-22,-22,-22,-16,-12, -6, -4, -4, -4, -4, -3, -1, 0}, + {-24,-24,-24,-24,-24,-24,-24,-18,-14,-12,-12,-12,-12,-10,-10, -9, -8}}}, {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, - {-24,-24,-24,-24,-24,-24,-24,-18,-14, -8, -6, -6, -6, -6, -5, -2, 0}, - {-26,-26,-26,-26,-26,-26,-26,-18,-16,-15,-15,-15,-15,-13,-13,-12,-10}}}, - /* 7 */ + {-24,-24,-24,-24,-24,-24,-24,-18,-14, -8, -6, -6, -6, -6, -5, -2, 0}, + {-26,-26,-26,-26,-26,-26,-26,-18,-16,-15,-15,-15,-15,-13,-13,-12,-10}}}, {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 1, 1, 1, 2, 3, 3, 4, 7}, - {-24,-24,-24,-24,-24,-24,-24,-18,-14,-10, -8, -8, -8, -8, -6, -4, 0}, - {-26,-26,-26,-26,-26,-26,-26,-22,-20,-19,-19,-19,-19,-18,-17,-16,-12}}}, - /* 8 */ + {-24,-24,-24,-24,-24,-24,-24,-18,-14,-10, -8, -8, -8, -8, -6, -4, 0}, + {-26,-26,-26,-26,-26,-26,-26,-22,-20,-19,-19,-19,-19,-18,-17,-16,-12}}}, {{{-15,-15,-15,-15,-15,-15,-15,-10, -4, 0, 0, 0, 0, 1, 2, 3, 7}, - {-26,-26,-26,-26,-26,-26,-26,-20,-16,-12,-10,-10,-10,-10, -8, -6, -2}, - {-28,-28,-28,-28,-28,-28,-28,-26,-24,-24,-24,-24,-24,-24,-24,-20,-16}}}, - /* 9 */ + {-26,-26,-26,-26,-26,-26,-26,-20,-16,-12,-10,-10,-10,-10, -8, -6, -2}, + {-28,-28,-28,-28,-28,-28,-28,-26,-24,-24,-24,-24,-24,-24,-24,-20,-16}}}, {{{-22,-22,-22,-22,-22,-22,-22,-18,-14, -8, -4, -4, -4, -4, -4, -2, 2}, - {-26,-26,-26,-26,-26,-26,-26,-22,-18,-16,-16,-16,-16,-14,-12,-10, -7}, - {-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-24,-20}}}, - /* 10 */ + {-26,-26,-26,-26,-26,-26,-26,-22,-18,-16,-16,-16,-16,-14,-12,-10, -7}, + {-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-24,-20}}}, {{{-24,-24,-24,-24,-24,-24,-24,-24,-24,-18,-14,-14,-14,-14,-14,-12,-10}, - {-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-20}, - {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, + {-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-30,-20}, + {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, }; -/* noise bias (impulse block) */ static noise3 _psy_noisebias_impulse[12]={ - /* 63 125 250 500 1k 2k 4k 8k 16k*/ - /* -1 */ {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 8, 8, 8, 8, 10, 12, 14, 20}, - {-30,-30,-30,-30,-26,-20,-16, -8, -6, -6, -2, 2, 2, 3, 6, 6, 15}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, + {-30,-30,-30,-30,-26,-20,-16, -8, -6, -6, -2, 2, 2, 3, 6, 6, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, - /* 0 */ - /* {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 4, 8, 8, 8, 10, 12, 14, 20}, - {-30,-30,-30,-30,-26,-22,-20,-14, -6, -2, 0, 0, 0, 0, 2, 4, 10}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}},*/ {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 4, 8, 8, 8, 10, 12, 14, 20}, - {-30,-30,-30,-30,-26,-22,-20,-14, -6, -2, 0, 0, 0, 0, 2, 3, 6}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, - /* 1 */ + {-30,-30,-30,-30,-26,-22,-20,-14, -6, -2, 0, 0, 0, 0, 2, 3, 6}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, {{{-12,-12,-12,-12,-12, -8, -6, -4, 0, 4, 4, 4, 4, 10, 12, 14, 20}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -4, -4, -2, -2, -2, -2, 2}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8,-10,-10, -8, -8, -8, -6, -4}}}, - /* 2 */ + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -4, -4, -2, -2, -2, -2, 2}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8,-10,-10, -8, -8, -8, -6, -4}}}, {{{-14,-14,-14,-14,-14,-10, -8, -6, -2, 2, 2, 2, 2, 8, 10, 10, 16}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -4, -4, -4, -2, 0}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10,-10,-10, -8, -4}}}, - /* 3 */ + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -4, -4, -4, -2, 0}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10,-10,-10, -8, -4}}}, {{{-14,-14,-14,-14,-14,-10, -8, -6, -2, 2, 2, 2, 2, 6, 8, 8, 14}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -4, -4, -4, -2, 0}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10,-10,-10, -8, -4}}}, - /* 4 */ + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -4, -4, -4, -2, 0}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10,-10,-10, -8, -4}}}, {{{-16,-16,-16,-16,-16,-12,-10, -6, -2, 0, 0, 0, 0, 4, 6, 6, 12}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -4, -4, -4, -2, 0}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10,-10,-10, -8, -4}}}, - /* 5 */ + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -4, -4, -4, -2, 0}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10,-10,-10,-10,-10,-10,-10, -8, -4}}}, {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 4, 6, 11}, - {-32,-32,-32,-32,-28,-24,-22,-16,-10, -6, -8, -8, -6, -6, -6, -4, -2}, - {-34,-34,-34,-34,-30,-26,-24,-18,-14,-12,-12,-12,-12,-12,-10, -9, -5}}}, - /* 6 + {-32,-32,-32,-32,-28,-24,-22,-16,-10, -6, -8, -8, -6, -6, -6, -4, -2}, + {-34,-34,-34,-34,-30,-26,-24,-18,-14,-12,-12,-12,-12,-12,-10, -9, -5}}}, {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 4, 6, 11}, - {-34,-34,-34,-34,-30,-30,-24,-20,-12,-12,-14,-14,-10, -9, -8, -6, -4}, - {-34,-34,-34,-34,-34,-30,-26,-20,-16,-15,-15,-15,-15,-15,-13,-12, -8}}},*/ - {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 4, 6, 11}, - {-34,-34,-34,-34,-30,-30,-30,-24,-16,-16,-16,-16,-16,-16,-14,-14,-12}, - {-36,-36,-36,-36,-36,-34,-28,-24,-20,-20,-20,-20,-20,-20,-20,-18,-16}}}, - /* 7 */ - /* {{{-22,-22,-22,-22,-22,-20,-14,-10, -6, 0, 0, 0, 0, 4, 4, 6, 11}, - {-34,-34,-34,-34,-30,-30,-24,-20,-14,-14,-16,-16,-14,-12,-10,-10,-10}, - {-34,-34,-34,-34,-32,-32,-30,-24,-20,-19,-19,-19,-19,-19,-17,-16,-12}}},*/ + {-34,-34,-34,-34,-30,-30,-30,-24,-16,-16,-16,-16,-16,-16,-14,-14,-12}, + {-36,-36,-36,-36,-36,-34,-28,-24,-20,-20,-20,-20,-20,-20,-20,-18,-16}}}, {{{-22,-22,-22,-22,-22,-20,-14,-10, -6, 0, 0, 0, 0, 4, 4, 6, 11}, - {-34,-34,-34,-34,-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-24,-22}, - {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-30,-24}}}, - /* 8 */ - /* {{{-24,-24,-24,-24,-24,-22,-14,-10, -6, -1, -1, -1, -1, 3, 3, 5, 10}, - {-34,-34,-34,-34,-30,-30,-30,-24,-20,-20,-20,-20,-20,-18,-16,-16,-14}, - {-36,-36,-36,-36,-36,-34,-28,-24,-24,-24,-24,-24,-24,-24,-24,-20,-16}}},*/ + {-34,-34,-34,-34,-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-24,-22}, + {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-30,-24}}}, {{{-24,-24,-24,-24,-24,-22,-14,-10, -6, -1, -1, -1, -1, 3, 3, 5, 10}, - {-34,-34,-34,-34,-34,-32,-32,-30,-26,-26,-26,-26,-26,-26,-26,-26,-24}, - {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-30,-24}}}, - /* 9 */ - /* {{{-28,-28,-28,-28,-28,-28,-28,-20,-14, -8, -4, -4, -4, -4, -4, -2, 2}, - {-36,-36,-36,-36,-34,-32,-32,-30,-26,-26,-26,-26,-26,-22,-20,-20,-18}, - {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-24,-20}}},*/ + {-34,-34,-34,-34,-34,-32,-32,-30,-26,-26,-26,-26,-26,-26,-26,-26,-24}, + {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-30,-24}}}, {{{-28,-28,-28,-28,-28,-28,-28,-20,-14, -8, -4, -4, -4, -4, -4, -2, 2}, - {-36,-36,-36,-36,-34,-32,-32,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26}, - {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-24,-20}}}, - /* 10 */ + {-36,-36,-36,-36,-34,-32,-32,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26}, + {-40,-40,-40,-40,-40,-40,-40,-32,-30,-30,-30,-30,-30,-30,-30,-24,-20}}}, {{{-30,-30,-30,-30,-30,-26,-24,-24,-24,-20,-16,-16,-16,-16,-16,-14,-12}, - {-40,-40,-40,-40,-40,-40,-40,-40,-35,-30,-30,-30,-30,-30,-30,-30,-26}, - {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, + {-40,-40,-40,-40,-40,-40,-40,-40,-35,-30,-30,-30,-30,-30,-30,-30,-26}, + {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, }; -/* noise bias (padding block) */ static noise3 _psy_noisebias_padding[12]={ - /* 63 125 250 500 1k 2k 4k 8k 16k*/ - /* -1 */ {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 8, 8, 8, 8, 10, 12, 14, 20}, - {-30,-30,-30,-30,-26,-20,-16, -8, -6, -6, -2, 2, 2, 3, 6, 6, 15}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, + {-30,-30,-30,-30,-26,-20,-16, -8, -6, -6, -2, 2, 2, 3, 6, 6, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -4, -2}}}, - /* 0 */ {{{-10,-10,-10,-10,-10, -4, 0, 0, 4, 8, 8, 8, 8, 10, 12, 14, 20}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -2, 2, 3, 6, 6, 8, 10}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -4, -4, -4, -4, -2, 0, 2}}}, - /* 1 */ + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -2, 2, 3, 6, 6, 8, 10}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, -4, -4, -4, -4, -2, 0, 2}}}, {{{-12,-12,-12,-12,-12, -8, -6, -4, 0, 4, 4, 4, 4, 10, 12, 14, 20}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, 0, 0, 0, 2, 2, 4, 8}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -6, -6, -4, -2, 0}}}, - /* 2 */ - /* {{{-14,-14,-14,-14,-14,-10, -8, -6, -2, 2, 2, 2, 2, 8, 10, 10, 16}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, 0, 0, 0, 2, 2, 4, 8}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}},*/ + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -4, 0, 0, 0, 2, 2, 4, 8}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -6, -6, -6, -6, -4, -2, 0}}}, {{{-14,-14,-14,-14,-14,-10, -8, -6, -2, 2, 2, 2, 2, 8, 10, 10, 16}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -1, -1, -1, 0, 0, 2, 6}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}}, - /* 3 */ + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -1, -1, -1, 0, 0, 2, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}}, {{{-14,-14,-14,-14,-14,-10, -8, -6, -2, 2, 2, 2, 2, 6, 8, 8, 14}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -1, -1, -1, 0, 0, 2, 6}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}}, - /* 4 */ + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -1, -1, -1, 0, 0, 2, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}}, {{{-16,-16,-16,-16,-16,-12,-10, -6, -2, 0, 0, 0, 0, 4, 6, 6, 12}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -1, -1, -1, -1, 0, 2, 6}, - {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}}, - /* 5 */ + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -6, -1, -1, -1, -1, 0, 2, 6}, + {-30,-30,-30,-30,-26,-22,-20,-14,-10, -8, -8, -8, -8, -8, -6, -4, -2}}}, {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 6, 6, 12}, - {-32,-32,-32,-32,-28,-24,-22,-16,-12, -6, -3, -3, -3, -3, -2, 0, 4}, - {-34,-34,-34,-34,-30,-26,-24,-18,-14,-10,-10,-10,-10,-10, -8, -5, -3}}}, - /* 6 */ + {-32,-32,-32,-32,-28,-24,-22,-16,-12, -6, -3, -3, -3, -3, -2, 0, 4}, + {-34,-34,-34,-34,-30,-26,-24,-18,-14,-10,-10,-10,-10,-10, -8, -5, -3}}}, {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 6, 6, 12}, - {-34,-34,-34,-34,-30,-30,-24,-20,-14, -8, -4, -4, -4, -4, -3, -1, 4}, - {-34,-34,-34,-34,-34,-30,-26,-20,-16,-13,-13,-13,-13,-13,-11, -8, -6}}}, - /* 7 */ + {-34,-34,-34,-34,-30,-30,-24,-20,-14, -8, -4, -4, -4, -4, -3, -1, 4}, + {-34,-34,-34,-34,-34,-30,-26,-20,-16,-13,-13,-13,-13,-13,-11, -8, -6}}}, {{{-20,-20,-20,-20,-20,-18,-14,-10, -4, 0, 0, 0, 0, 4, 6, 6, 12}, - {-34,-34,-34,-34,-30,-30,-30,-24,-16,-10, -8, -6, -6, -6, -5, -3, 1}, - {-34,-34,-34,-34,-32,-32,-28,-22,-18,-16,-16,-16,-16,-16,-14,-12,-10}}}, - /* 8 */ + {-34,-34,-34,-34,-30,-30,-30,-24,-16,-10, -8, -6, -6, -6, -5, -3, 1}, + {-34,-34,-34,-34,-32,-32,-28,-22,-18,-16,-16,-16,-16,-16,-14,-12,-10}}}, {{{-22,-22,-22,-22,-22,-20,-14,-10, -4, 0, 0, 0, 0, 3, 5, 5, 11}, - {-34,-34,-34,-34,-30,-30,-30,-24,-16,-12,-10, -8, -8, -8, -7, -5, -2}, - {-36,-36,-36,-36,-36,-34,-28,-22,-20,-20,-20,-20,-20,-20,-20,-16,-14}}}, - /* 9 */ + {-34,-34,-34,-34,-30,-30,-30,-24,-16,-12,-10, -8, -8, -8, -7, -5, -2}, + {-36,-36,-36,-36,-36,-34,-28,-22,-20,-20,-20,-20,-20,-20,-20,-16,-14}}}, {{{-28,-28,-28,-28,-28,-28,-28,-20,-14, -8, -2, -2, -2, -2, 0, 2, 6}, - {-36,-36,-36,-36,-34,-32,-32,-24,-16,-12,-12,-12,-12,-12,-10, -8, -5}, - {-40,-40,-40,-40,-40,-40,-40,-32,-26,-24,-24,-24,-24,-24,-24,-20,-18}}}, - /* 10 */ + {-36,-36,-36,-36,-34,-32,-32,-24,-16,-12,-12,-12,-12,-12,-10, -8, -5}, + {-40,-40,-40,-40,-40,-40,-40,-32,-26,-24,-24,-24,-24,-24,-24,-20,-18}}}, {{{-30,-30,-30,-30,-30,-26,-24,-24,-24,-20,-12,-12,-12,-12,-12,-10, -8}, - {-40,-40,-40,-40,-40,-40,-40,-40,-35,-30,-25,-25,-25,-25,-25,-25,-15}, - {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, + {-40,-40,-40,-40,-40,-40,-40,-40,-35,-30,-25,-25,-25,-25,-25,-25,-15}, + {-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40}}}, }; static noiseguard _psy_noiseguards_44[4]={ @@ -165994,23 +154050,15 @@ static int _psy_noise_suppress[12]={ }; static vorbis_info_psy _psy_info_template={ - /* blockflag */ -1, - /* ath_adjatt, ath_maxatt */ -140.,-140., - /* tonemask att boost/decay,suppr,curves */ - {0.f,0.f,0.f}, 0.,0., -40.f, {0.}, + {0.f,0.f,0.f}, 0.,0., -40.f, {0.}, - /*noisemaskp,supp, low/high window, low/hi guard, minimum */ - 1, -0.f, .5f, .5f, 0,0,0, - /* noiseoffset*3, noisecompand, max_curve_dB */ + 1, -0.f, .5f, .5f, 0,0,0, {{-1},{-1},{-1}},{-1},105.f, - /* noise normalization - channel_p, point_p, start, partition, thresh. */ 0,0,-1,-1,0., }; -/* ath ****************/ - static int _psy_ath_floater[12]={ -100,-100,-100,-100,-100,-100,-105,-105,-105,-105,-110,-120, }; @@ -166018,149 +154066,96 @@ static int _psy_ath_abs[12]={ -130,-130,-130,-130,-140,-140,-140,-140,-140,-140,-140,-150, }; -/* stereo setup. These don't map directly to quality level, there's - an additional indirection as several of the below may be used in a - single bitmanaged stream - -****************/ - -/* various stereo possibilities */ - -/* stereo mode by base quality level */ static adj_stereo _psy_stereo_modes_44[12]={ - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 -1 */ {{ 4, 4, 4, 4, 4, 4, 4, 3, 2, 2, 1, 0, 0, 0, 0}, { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 4, 3}, { 1, 2, 3, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 8, 8}, { 12,12.5, 13,13.5, 14,14.5, 15, 99, 99, 99, 99, 99, 99, 99, 99}}, -/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 */ -/*{{ 4, 4, 4, 4, 4, 4, 4, 3, 2, 2, 1, 0, 0, 0, 0}, - { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 4, 3}, - { 1, 2, 3, 4, 5, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8}, - { 12,12.5, 13,13.5, 14,14.5, 15, 99, 99, 99, 99, 99, 99, 99, 99}},*/ {{ 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0}, { 8, 8, 8, 8, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, 3}, { 1, 2, 3, 4, 4, 5, 6, 6, 6, 6, 6, 8, 8, 8, 8}, { 12,12.5, 13,13.5, 14,14.5, 15, 99, 99, 99, 99, 99, 99, 99, 99}}, - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 */ {{ 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0}, { 8, 8, 8, 8, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, 3}, { 1, 2, 3, 4, 4, 5, 6, 6, 6, 6, 6, 8, 8, 8, 8}, { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2 */ - /* {{ 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 0, 0, 0, 0, 0}, - { 8, 8, 8, 6, 5, 5, 5, 5, 5, 5, 5, 4, 3, 2, 1}, - { 3, 4, 4, 4, 5, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8}, - { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, */ {{ 3, 3, 3, 3, 3, 3, 3, 2, 1, 1, 0, 0, 0, 0, 0}, { 8, 8, 6, 6, 5, 5, 4, 4, 4, 4, 4, 4, 3, 2, 1}, { 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8}, { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 3 */ {{ 2, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, { 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1}, { 4, 4, 5, 6, 6, 6, 6, 6, 8, 8, 10, 10, 10, 10, 10}, { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 4 */ {{ 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 2, 1, 0}, { 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10}, { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 5 */ - /* {{ 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - { 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0}, - { 6, 6, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10}, - { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}},*/ {{ 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0}, { 6, 7, 8, 8, 8, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12}, { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 6 */ - /* {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - { 3, 3, 3, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - { 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, - { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, */ {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 3, 3, 3, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 8, 8, 8, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 7 */ - /* {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - { 3, 3, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - { 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, - { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}},*/ {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 3, 3, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 8, 8, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 8 */ - /* {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - { 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - { 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, - { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}},*/ {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 8, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 9 */ {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 10 */ {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99}}, }; -/* tone master attenuation by base quality mode and bitrate tweak */ static att3 _psy_tone_masteratt_44[12]={ - {{ 35, 21, 9}, 0, 0}, /* -1 */ + {{ 35, 21, 9}, 0, 0}, /* -1 */ {{ 30, 20, 8}, -2, 1.25}, /* 0 */ - /* {{ 25, 14, 4}, 0, 0}, *//* 1 */ - {{ 25, 12, 2}, 0, 0}, /* 1 */ - /* {{ 20, 10, -2}, 0, 0}, *//* 2 */ - {{ 20, 9, -3}, 0, 0}, /* 2 */ - {{ 20, 9, -4}, 0, 0}, /* 3 */ - {{ 20, 9, -4}, 0, 0}, /* 4 */ - {{ 20, 6, -6}, 0, 0}, /* 5 */ - {{ 20, 3, -10}, 0, 0}, /* 6 */ - {{ 18, 1, -14}, 0, 0}, /* 7 */ - {{ 18, 0, -16}, 0, 0}, /* 8 */ - {{ 18, -2, -16}, 0, 0}, /* 9 */ - {{ 12, -2, -20}, 0, 0}, /* 10 */ +/* 1 */ + {{ 25, 12, 2}, 0, 0}, /* 1 */ +/* 2 */ + {{ 20, 9, -3}, 0, 0}, /* 2 */ + {{ 20, 9, -4}, 0, 0}, /* 3 */ + {{ 20, 9, -4}, 0, 0}, /* 4 */ + {{ 20, 6, -6}, 0, 0}, /* 5 */ + {{ 20, 3, -10}, 0, 0}, /* 6 */ + {{ 18, 1, -14}, 0, 0}, /* 7 */ + {{ 18, 0, -16}, 0, 0}, /* 8 */ + {{ 18, -2, -16}, 0, 0}, /* 9 */ + {{ 12, -2, -20}, 0, 0}, /* 10 */ }; -/* lowpass by mode **************/ static double _psy_lowpass_44[12]={ - /* 15.1,15.8,16.5,17.9,20.5,48.,999.,999.,999.,999.,999. */ 13.9,15.1,15.8,16.5,17.2,18.9,20.1,48.,999.,999.,999.,999. }; -/* noise normalization **********/ - static int _noise_start_short_44[11]={ - /* 16,16,16,16,32,32,9999,9999,9999,9999 */ 32,16,16,16,32,9999,9999,9999,9999,9999,9999 }; static int _noise_start_long_44[11]={ - /* 128,128,128,256,512,512,9999,9999,9999,9999 */ 256,128,128,256,512,9999,9999,9999,9999,9999,9999 }; static int _noise_part_short_44[11]={ - 8,8,8,8,8,8,8,8,8,8,8 + 8,8,8,8,8,8,8,8,8,8,8 }; static int _noise_part_long_44[11]={ - 32,32,32,32,32,32,32,32,32,32,32 + 32,32,32,32,32,32,32,32,32,32,32 }; static double _noise_thresh_44[11]={ - /* .2,.2,.3,.4,.5,.5,9999.,9999.,9999.,9999., */ .2,.2,.2,.4,.6,9999.,9999.,9999.,9999.,9999.,9999., }; @@ -166193,7 +154188,6 @@ static double _psy_compand_long_mapping[12]={ }; static double _global_mapping_44[12]={ - /* 1., 1., 1.5, 2., 2., 2.5, 2.7, 3.0, 3.5, 4., 4. */ 0., 1., 1., 1.5, 2., 2., 2.5, 2.7, 3.0, 3.7, 4., 4. }; @@ -166282,7 +154276,7 @@ static float _vq_quantthresh__16u0__p1_0[] = { }; static long _vq_quantmap__16u0__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16u0__p1_0 = { @@ -166323,7 +154317,7 @@ static float _vq_quantthresh__16u0__p2_0[] = { }; static long _vq_quantmap__16u0__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16u0__p2_0 = { @@ -166400,7 +154394,7 @@ static float _vq_quantthresh__16u0__p3_0[] = { }; static long _vq_quantmap__16u0__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16u0__p3_0 = { @@ -166477,7 +154471,7 @@ static float _vq_quantthresh__16u0__p4_0[] = { }; static long _vq_quantmap__16u0__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16u0__p4_0 = { @@ -166524,8 +154518,8 @@ static float _vq_quantthresh__16u0__p5_0[] = { }; static long _vq_quantmap__16u0__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__16u0__p5_0 = { @@ -166582,8 +154576,8 @@ static float _vq_quantthresh__16u0__p6_0[] = { }; static long _vq_quantmap__16u0__p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__16u0__p6_0 = { @@ -166622,7 +154616,7 @@ static float _vq_quantthresh__16u0__p6_1[] = { }; static long _vq_quantmap__16u0__p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16u0__p6_1 = { @@ -166663,7 +154657,7 @@ static float _vq_quantthresh__16u0__p7_0[] = { }; static long _vq_quantmap__16u0__p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16u0__p7_0 = { @@ -166726,8 +154720,8 @@ static float _vq_quantthresh__16u0__p7_1[] = { }; static long _vq_quantmap__16u0__p7_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__16u0__p7_1 = { @@ -166810,8 +154804,8 @@ static float _vq_quantthresh__16u0__p7_2[] = { }; static long _vq_quantmap__16u0__p7_2[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -166892,7 +154886,7 @@ static float _vq_quantthresh__16u1__p1_0[] = { }; static long _vq_quantmap__16u1__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16u1__p1_0 = { @@ -166933,7 +154927,7 @@ static float _vq_quantthresh__16u1__p2_0[] = { }; static long _vq_quantmap__16u1__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16u1__p2_0 = { @@ -167010,7 +155004,7 @@ static float _vq_quantthresh__16u1__p3_0[] = { }; static long _vq_quantmap__16u1__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16u1__p3_0 = { @@ -167087,7 +155081,7 @@ static float _vq_quantthresh__16u1__p4_0[] = { }; static long _vq_quantmap__16u1__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16u1__p4_0 = { @@ -167134,8 +155128,8 @@ static float _vq_quantthresh__16u1__p5_0[] = { }; static long _vq_quantmap__16u1__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__16u1__p5_0 = { @@ -167182,8 +155176,8 @@ static float _vq_quantthresh__16u1__p6_0[] = { }; static long _vq_quantmap__16u1__p6_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__16u1__p6_0 = { @@ -167224,7 +155218,7 @@ static float _vq_quantthresh__16u1__p7_0[] = { }; static long _vq_quantmap__16u1__p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16u1__p7_0 = { @@ -167276,8 +155270,8 @@ static float _vq_quantthresh__16u1__p7_1[] = { }; static long _vq_quantmap__16u1__p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__16u1__p7_1 = { @@ -167329,8 +155323,8 @@ static float _vq_quantthresh__16u1__p8_0[] = { }; static long _vq_quantmap__16u1__p8_0[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__16u1__p8_0 = { @@ -167382,8 +155376,8 @@ static float _vq_quantthresh__16u1__p8_1[] = { }; static long _vq_quantmap__16u1__p8_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__16u1__p8_1 = { @@ -167446,8 +155440,8 @@ static float _vq_quantthresh__16u1__p9_0[] = { }; static long _vq_quantmap__16u1__p9_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__16u1__p9_0 = { @@ -167510,8 +155504,8 @@ static float _vq_quantthresh__16u1__p9_1[] = { }; static long _vq_quantmap__16u1__p9_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__16u1__p9_1 = { @@ -167580,8 +155574,8 @@ static float _vq_quantthresh__16u1__p9_2[] = { }; static long _vq_quantmap__16u1__p9_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -167686,7 +155680,7 @@ static float _vq_quantthresh__16u2_p1_0[] = { }; static long _vq_quantmap__16u2_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16u2_p1_0 = { @@ -167763,7 +155757,7 @@ static float _vq_quantthresh__16u2_p2_0[] = { }; static long _vq_quantmap__16u2_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16u2_p2_0 = { @@ -167810,8 +155804,8 @@ static float _vq_quantthresh__16u2_p3_0[] = { }; static long _vq_quantmap__16u2_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__16u2_p3_0 = { @@ -167880,8 +155874,8 @@ static float _vq_quantthresh__16u2_p4_0[] = { }; static long _vq_quantmap__16u2_p4_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -167923,7 +155917,7 @@ static float _vq_quantthresh__16u2_p5_0[] = { }; static long _vq_quantmap__16u2_p5_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__16u2_p5_0 = { @@ -167975,8 +155969,8 @@ static float _vq_quantthresh__16u2_p5_1[] = { }; static long _vq_quantmap__16u2_p5_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__16u2_p5_1 = { @@ -168033,8 +156027,8 @@ static float _vq_quantthresh__16u2_p6_0[] = { }; static long _vq_quantmap__16u2_p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__16u2_p6_0 = { @@ -168073,7 +156067,7 @@ static float _vq_quantthresh__16u2_p6_1[] = { }; static long _vq_quantmap__16u2_p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__16u2_p6_1 = { @@ -168130,8 +156124,8 @@ static float _vq_quantthresh__16u2_p7_0[] = { }; static long _vq_quantmap__16u2_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__16u2_p7_0 = { @@ -168183,8 +156177,8 @@ static float _vq_quantthresh__16u2_p7_1[] = { }; static long _vq_quantmap__16u2_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__16u2_p7_1 = { @@ -168247,8 +156241,8 @@ static float _vq_quantthresh__16u2_p8_0[] = { }; static long _vq_quantmap__16u2_p8_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__16u2_p8_0 = { @@ -168331,8 +156325,8 @@ static float _vq_quantthresh__16u2_p8_1[] = { }; static long _vq_quantmap__16u2_p8_1[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -168396,8 +156390,8 @@ static float _vq_quantthresh__16u2_p9_0[] = { }; static long _vq_quantmap__16u2_p9_0[] = { - 11, 9, 7, 5, 3, 1, 13, 0, - 14, 2, 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 13, 0, + 14, 2, 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__16u2_p9_0 = { @@ -168473,8 +156467,8 @@ static float _vq_quantthresh__16u2_p9_1[] = { }; static long _vq_quantmap__16u2_p9_1[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 17, 0, 18, 2, 4, 6, 8, 10, + 15, 13, 11, 9, 7, 5, 3, 1, + 17, 0, 18, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -168567,8 +156561,8 @@ static float _vq_quantthresh__16u2_p9_2[] = { static long _vq_quantmap__16u2_p9_2[] = { 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, @@ -168612,7 +156606,7 @@ static float _vq_quantthresh__8u0__p1_0[] = { }; static long _vq_quantmap__8u0__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8u0__p1_0 = { @@ -168653,7 +156647,7 @@ static float _vq_quantthresh__8u0__p2_0[] = { }; static long _vq_quantmap__8u0__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8u0__p2_0 = { @@ -168730,7 +156724,7 @@ static float _vq_quantthresh__8u0__p3_0[] = { }; static long _vq_quantmap__8u0__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8u0__p3_0 = { @@ -168807,7 +156801,7 @@ static float _vq_quantthresh__8u0__p4_0[] = { }; static long _vq_quantmap__8u0__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8u0__p4_0 = { @@ -168854,8 +156848,8 @@ static float _vq_quantthresh__8u0__p5_0[] = { }; static long _vq_quantmap__8u0__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__8u0__p5_0 = { @@ -168912,8 +156906,8 @@ static float _vq_quantthresh__8u0__p6_0[] = { }; static long _vq_quantmap__8u0__p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__8u0__p6_0 = { @@ -168952,7 +156946,7 @@ static float _vq_quantthresh__8u0__p6_1[] = { }; static long _vq_quantmap__8u0__p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8u0__p6_1 = { @@ -168993,7 +156987,7 @@ static float _vq_quantthresh__8u0__p7_0[] = { }; static long _vq_quantmap__8u0__p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8u0__p7_0 = { @@ -169056,8 +157050,8 @@ static float _vq_quantthresh__8u0__p7_1[] = { }; static long _vq_quantmap__8u0__p7_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__8u0__p7_1 = { @@ -169140,8 +157134,8 @@ static float _vq_quantthresh__8u0__p7_2[] = { }; static long _vq_quantmap__8u0__p7_2[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -169201,7 +157195,7 @@ static float _vq_quantthresh__8u1__p1_0[] = { }; static long _vq_quantmap__8u1__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8u1__p1_0 = { @@ -169242,7 +157236,7 @@ static float _vq_quantthresh__8u1__p2_0[] = { }; static long _vq_quantmap__8u1__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8u1__p2_0 = { @@ -169319,7 +157313,7 @@ static float _vq_quantthresh__8u1__p3_0[] = { }; static long _vq_quantmap__8u1__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8u1__p3_0 = { @@ -169396,7 +157390,7 @@ static float _vq_quantthresh__8u1__p4_0[] = { }; static long _vq_quantmap__8u1__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__8u1__p4_0 = { @@ -169443,8 +157437,8 @@ static float _vq_quantthresh__8u1__p5_0[] = { }; static long _vq_quantmap__8u1__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__8u1__p5_0 = { @@ -169491,8 +157485,8 @@ static float _vq_quantthresh__8u1__p6_0[] = { }; static long _vq_quantmap__8u1__p6_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__8u1__p6_0 = { @@ -169533,7 +157527,7 @@ static float _vq_quantthresh__8u1__p7_0[] = { }; static long _vq_quantmap__8u1__p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__8u1__p7_0 = { @@ -169585,8 +157579,8 @@ static float _vq_quantthresh__8u1__p7_1[] = { }; static long _vq_quantmap__8u1__p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__8u1__p7_1 = { @@ -169638,8 +157632,8 @@ static float _vq_quantthresh__8u1__p8_0[] = { }; static long _vq_quantmap__8u1__p8_0[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__8u1__p8_0 = { @@ -169691,8 +157685,8 @@ static float _vq_quantthresh__8u1__p8_1[] = { }; static long _vq_quantmap__8u1__p8_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__8u1__p8_1 = { @@ -169755,8 +157749,8 @@ static float _vq_quantthresh__8u1__p9_0[] = { }; static long _vq_quantmap__8u1__p9_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__8u1__p9_0 = { @@ -169819,8 +157813,8 @@ static float _vq_quantthresh__8u1__p9_1[] = { }; static long _vq_quantmap__8u1__p9_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__8u1__p9_1 = { @@ -169889,8 +157883,8 @@ static float _vq_quantthresh__8u1__p9_2[] = { }; static long _vq_quantmap__8u1__p9_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -169971,7 +157965,7 @@ static float _vq_quantthresh__44u0__p1_0[] = { }; static long _vq_quantmap__44u0__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u0__p1_0 = { @@ -170012,7 +158006,7 @@ static float _vq_quantthresh__44u0__p2_0[] = { }; static long _vq_quantmap__44u0__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u0__p2_0 = { @@ -170089,7 +158083,7 @@ static float _vq_quantthresh__44u0__p3_0[] = { }; static long _vq_quantmap__44u0__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u0__p3_0 = { @@ -170166,7 +158160,7 @@ static float _vq_quantthresh__44u0__p4_0[] = { }; static long _vq_quantmap__44u0__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u0__p4_0 = { @@ -170213,8 +158207,8 @@ static float _vq_quantthresh__44u0__p5_0[] = { }; static long _vq_quantmap__44u0__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u0__p5_0 = { @@ -170271,8 +158265,8 @@ static float _vq_quantthresh__44u0__p6_0[] = { }; static long _vq_quantmap__44u0__p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u0__p6_0 = { @@ -170311,7 +158305,7 @@ static float _vq_quantthresh__44u0__p6_1[] = { }; static long _vq_quantmap__44u0__p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u0__p6_1 = { @@ -170388,7 +158382,7 @@ static float _vq_quantthresh__44u0__p7_0[] = { }; static long _vq_quantmap__44u0__p7_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u0__p7_0 = { @@ -170445,8 +158439,8 @@ static float _vq_quantthresh__44u0__p7_1[] = { }; static long _vq_quantmap__44u0__p7_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u0__p7_1 = { @@ -170503,8 +158497,8 @@ static float _vq_quantthresh__44u0__p7_2[] = { }; static long _vq_quantmap__44u0__p7_2[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u0__p7_2 = { @@ -170581,7 +158575,7 @@ static float _vq_quantthresh__44u1__p1_0[] = { }; static long _vq_quantmap__44u1__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u1__p1_0 = { @@ -170622,7 +158616,7 @@ static float _vq_quantthresh__44u1__p2_0[] = { }; static long _vq_quantmap__44u1__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u1__p2_0 = { @@ -170699,7 +158693,7 @@ static float _vq_quantthresh__44u1__p3_0[] = { }; static long _vq_quantmap__44u1__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u1__p3_0 = { @@ -170776,7 +158770,7 @@ static float _vq_quantthresh__44u1__p4_0[] = { }; static long _vq_quantmap__44u1__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u1__p4_0 = { @@ -170823,8 +158817,8 @@ static float _vq_quantthresh__44u1__p5_0[] = { }; static long _vq_quantmap__44u1__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u1__p5_0 = { @@ -170881,8 +158875,8 @@ static float _vq_quantthresh__44u1__p6_0[] = { }; static long _vq_quantmap__44u1__p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u1__p6_0 = { @@ -170921,7 +158915,7 @@ static float _vq_quantthresh__44u1__p6_1[] = { }; static long _vq_quantmap__44u1__p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u1__p6_1 = { @@ -170964,7 +158958,7 @@ static float _vq_quantthresh__44u1__p7_0[] = { }; static long _vq_quantmap__44u1__p7_0[] = { - 5, 3, 1, 0, 2, 4, 6, + 5, 3, 1, 0, 2, 4, 6, }; static encode_aux_threshmatch _vq_auxt__44u1__p7_0 = { @@ -171021,8 +159015,8 @@ static float _vq_quantthresh__44u1__p7_1[] = { }; static long _vq_quantmap__44u1__p7_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u1__p7_1 = { @@ -171079,8 +159073,8 @@ static float _vq_quantthresh__44u1__p7_2[] = { }; static long _vq_quantmap__44u1__p7_2[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u1__p7_2 = { @@ -171157,7 +159151,7 @@ static float _vq_quantthresh__44u2__p1_0[] = { }; static long _vq_quantmap__44u2__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u2__p1_0 = { @@ -171198,7 +159192,7 @@ static float _vq_quantthresh__44u2__p2_0[] = { }; static long _vq_quantmap__44u2__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u2__p2_0 = { @@ -171275,7 +159269,7 @@ static float _vq_quantthresh__44u2__p3_0[] = { }; static long _vq_quantmap__44u2__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u2__p3_0 = { @@ -171352,7 +159346,7 @@ static float _vq_quantthresh__44u2__p4_0[] = { }; static long _vq_quantmap__44u2__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u2__p4_0 = { @@ -171399,8 +159393,8 @@ static float _vq_quantthresh__44u2__p5_0[] = { }; static long _vq_quantmap__44u2__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u2__p5_0 = { @@ -171457,8 +159451,8 @@ static float _vq_quantthresh__44u2__p6_0[] = { }; static long _vq_quantmap__44u2__p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u2__p6_0 = { @@ -171497,7 +159491,7 @@ static float _vq_quantthresh__44u2__p6_1[] = { }; static long _vq_quantmap__44u2__p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u2__p6_1 = { @@ -171544,8 +159538,8 @@ static float _vq_quantthresh__44u2__p7_0[] = { }; static long _vq_quantmap__44u2__p7_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u2__p7_0 = { @@ -171602,8 +159596,8 @@ static float _vq_quantthresh__44u2__p7_1[] = { }; static long _vq_quantmap__44u2__p7_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u2__p7_1 = { @@ -171660,8 +159654,8 @@ static float _vq_quantthresh__44u2__p7_2[] = { }; static long _vq_quantmap__44u2__p7_2[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u2__p7_2 = { @@ -171738,7 +159732,7 @@ static float _vq_quantthresh__44u3__p1_0[] = { }; static long _vq_quantmap__44u3__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u3__p1_0 = { @@ -171779,7 +159773,7 @@ static float _vq_quantthresh__44u3__p2_0[] = { }; static long _vq_quantmap__44u3__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u3__p2_0 = { @@ -171856,7 +159850,7 @@ static float _vq_quantthresh__44u3__p3_0[] = { }; static long _vq_quantmap__44u3__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u3__p3_0 = { @@ -171933,7 +159927,7 @@ static float _vq_quantthresh__44u3__p4_0[] = { }; static long _vq_quantmap__44u3__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u3__p4_0 = { @@ -171980,8 +159974,8 @@ static float _vq_quantthresh__44u3__p5_0[] = { }; static long _vq_quantmap__44u3__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u3__p5_0 = { @@ -172038,8 +160032,8 @@ static float _vq_quantthresh__44u3__p6_0[] = { }; static long _vq_quantmap__44u3__p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u3__p6_0 = { @@ -172078,7 +160072,7 @@ static float _vq_quantthresh__44u3__p6_1[] = { }; static long _vq_quantmap__44u3__p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u3__p6_1 = { @@ -172125,8 +160119,8 @@ static float _vq_quantthresh__44u3__p7_0[] = { }; static long _vq_quantmap__44u3__p7_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u3__p7_0 = { @@ -172189,8 +160183,8 @@ static float _vq_quantthresh__44u3__p7_1[] = { }; static long _vq_quantmap__44u3__p7_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44u3__p7_1 = { @@ -172259,8 +160253,8 @@ static float _vq_quantthresh__44u3__p7_2[] = { }; static long _vq_quantmap__44u3__p7_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -172338,7 +160332,7 @@ static float _vq_quantthresh__44u4__p1_0[] = { }; static long _vq_quantmap__44u4__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u4__p1_0 = { @@ -172379,7 +160373,7 @@ static float _vq_quantthresh__44u4__p2_0[] = { }; static long _vq_quantmap__44u4__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u4__p2_0 = { @@ -172456,7 +160450,7 @@ static float _vq_quantthresh__44u4__p3_0[] = { }; static long _vq_quantmap__44u4__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u4__p3_0 = { @@ -172533,7 +160527,7 @@ static float _vq_quantthresh__44u4__p4_0[] = { }; static long _vq_quantmap__44u4__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u4__p4_0 = { @@ -172580,8 +160574,8 @@ static float _vq_quantthresh__44u4__p5_0[] = { }; static long _vq_quantmap__44u4__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u4__p5_0 = { @@ -172638,8 +160632,8 @@ static float _vq_quantthresh__44u4__p6_0[] = { }; static long _vq_quantmap__44u4__p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u4__p6_0 = { @@ -172678,7 +160672,7 @@ static float _vq_quantthresh__44u4__p6_1[] = { }; static long _vq_quantmap__44u4__p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u4__p6_1 = { @@ -172735,8 +160729,8 @@ static float _vq_quantthresh__44u4__p7_0[] = { }; static long _vq_quantmap__44u4__p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u4__p7_0 = { @@ -172799,8 +160793,8 @@ static float _vq_quantthresh__44u4__p7_1[] = { }; static long _vq_quantmap__44u4__p7_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44u4__p7_1 = { @@ -172869,8 +160863,8 @@ static float _vq_quantthresh__44u4__p7_2[] = { }; static long _vq_quantmap__44u4__p7_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -172951,7 +160945,7 @@ static float _vq_quantthresh__44u5__p1_0[] = { }; static long _vq_quantmap__44u5__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u5__p1_0 = { @@ -172992,7 +160986,7 @@ static float _vq_quantthresh__44u5__p2_0[] = { }; static long _vq_quantmap__44u5__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u5__p2_0 = { @@ -173069,7 +161063,7 @@ static float _vq_quantthresh__44u5__p3_0[] = { }; static long _vq_quantmap__44u5__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u5__p3_0 = { @@ -173146,7 +161140,7 @@ static float _vq_quantthresh__44u5__p4_0[] = { }; static long _vq_quantmap__44u5__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u5__p4_0 = { @@ -173193,8 +161187,8 @@ static float _vq_quantthresh__44u5__p5_0[] = { }; static long _vq_quantmap__44u5__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u5__p5_0 = { @@ -173241,8 +161235,8 @@ static float _vq_quantthresh__44u5__p6_0[] = { }; static long _vq_quantmap__44u5__p6_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u5__p6_0 = { @@ -173283,7 +161277,7 @@ static float _vq_quantthresh__44u5__p7_0[] = { }; static long _vq_quantmap__44u5__p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u5__p7_0 = { @@ -173335,8 +161329,8 @@ static float _vq_quantthresh__44u5__p7_1[] = { }; static long _vq_quantmap__44u5__p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u5__p7_1 = { @@ -173388,8 +161382,8 @@ static float _vq_quantthresh__44u5__p8_0[] = { }; static long _vq_quantmap__44u5__p8_0[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u5__p8_0 = { @@ -173441,8 +161435,8 @@ static float _vq_quantthresh__44u5__p8_1[] = { }; static long _vq_quantmap__44u5__p8_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u5__p8_1 = { @@ -173499,8 +161493,8 @@ static float _vq_quantthresh__44u5__p9_0[] = { }; static long _vq_quantmap__44u5__p9_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u5__p9_0 = { @@ -173563,8 +161557,8 @@ static float _vq_quantthresh__44u5__p9_1[] = { }; static long _vq_quantmap__44u5__p9_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44u5__p9_1 = { @@ -173633,8 +161627,8 @@ static float _vq_quantthresh__44u5__p9_2[] = { }; static long _vq_quantmap__44u5__p9_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -173718,7 +161712,7 @@ static float _vq_quantthresh__44u6__p1_0[] = { }; static long _vq_quantmap__44u6__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u6__p1_0 = { @@ -173759,7 +161753,7 @@ static float _vq_quantthresh__44u6__p2_0[] = { }; static long _vq_quantmap__44u6__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u6__p2_0 = { @@ -173836,7 +161830,7 @@ static float _vq_quantthresh__44u6__p3_0[] = { }; static long _vq_quantmap__44u6__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u6__p3_0 = { @@ -173913,7 +161907,7 @@ static float _vq_quantthresh__44u6__p4_0[] = { }; static long _vq_quantmap__44u6__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u6__p4_0 = { @@ -173960,8 +161954,8 @@ static float _vq_quantthresh__44u6__p5_0[] = { }; static long _vq_quantmap__44u6__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u6__p5_0 = { @@ -174008,8 +162002,8 @@ static float _vq_quantthresh__44u6__p6_0[] = { }; static long _vq_quantmap__44u6__p6_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u6__p6_0 = { @@ -174050,7 +162044,7 @@ static float _vq_quantthresh__44u6__p7_0[] = { }; static long _vq_quantmap__44u6__p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u6__p7_0 = { @@ -174102,8 +162096,8 @@ static float _vq_quantthresh__44u6__p7_1[] = { }; static long _vq_quantmap__44u6__p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u6__p7_1 = { @@ -174155,8 +162149,8 @@ static float _vq_quantthresh__44u6__p8_0[] = { }; static long _vq_quantmap__44u6__p8_0[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u6__p8_0 = { @@ -174208,8 +162202,8 @@ static float _vq_quantthresh__44u6__p8_1[] = { }; static long _vq_quantmap__44u6__p8_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u6__p8_1 = { @@ -174272,8 +162266,8 @@ static float _vq_quantthresh__44u6__p9_0[] = { }; static long _vq_quantmap__44u6__p9_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44u6__p9_0 = { @@ -174336,8 +162330,8 @@ static float _vq_quantthresh__44u6__p9_1[] = { }; static long _vq_quantmap__44u6__p9_1[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44u6__p9_1 = { @@ -174406,8 +162400,8 @@ static float _vq_quantthresh__44u6__p9_2[] = { }; static long _vq_quantmap__44u6__p9_2[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -174491,7 +162485,7 @@ static float _vq_quantthresh__44u7__p1_0[] = { }; static long _vq_quantmap__44u7__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u7__p1_0 = { @@ -174532,7 +162526,7 @@ static float _vq_quantthresh__44u7__p2_0[] = { }; static long _vq_quantmap__44u7__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u7__p2_0 = { @@ -174609,7 +162603,7 @@ static float _vq_quantthresh__44u7__p3_0[] = { }; static long _vq_quantmap__44u7__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u7__p3_0 = { @@ -174686,7 +162680,7 @@ static float _vq_quantthresh__44u7__p4_0[] = { }; static long _vq_quantmap__44u7__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u7__p4_0 = { @@ -174733,8 +162727,8 @@ static float _vq_quantthresh__44u7__p5_0[] = { }; static long _vq_quantmap__44u7__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u7__p5_0 = { @@ -174781,8 +162775,8 @@ static float _vq_quantthresh__44u7__p6_0[] = { }; static long _vq_quantmap__44u7__p6_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u7__p6_0 = { @@ -174823,7 +162817,7 @@ static float _vq_quantthresh__44u7__p7_0[] = { }; static long _vq_quantmap__44u7__p7_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u7__p7_0 = { @@ -174875,8 +162869,8 @@ static float _vq_quantthresh__44u7__p7_1[] = { }; static long _vq_quantmap__44u7__p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u7__p7_1 = { @@ -174928,8 +162922,8 @@ static float _vq_quantthresh__44u7__p8_0[] = { }; static long _vq_quantmap__44u7__p8_0[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u7__p8_0 = { @@ -174981,8 +162975,8 @@ static float _vq_quantthresh__44u7__p8_1[] = { }; static long _vq_quantmap__44u7__p8_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u7__p8_1 = { @@ -175034,8 +163028,8 @@ static float _vq_quantthresh__44u7__p9_0[] = { }; static long _vq_quantmap__44u7__p9_0[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u7__p9_0 = { @@ -175092,8 +163086,8 @@ static float _vq_quantthresh__44u7__p9_1[] = { }; static long _vq_quantmap__44u7__p9_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u7__p9_1 = { @@ -175185,8 +163179,8 @@ static float _vq_quantthresh__44u7__p9_2[] = { static long _vq_quantmap__44u7__p9_2[] = { 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, @@ -175293,7 +163287,7 @@ static float _vq_quantthresh__44u8_p1_0[] = { }; static long _vq_quantmap__44u8_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u8_p1_0 = { @@ -175370,7 +163364,7 @@ static float _vq_quantthresh__44u8_p2_0[] = { }; static long _vq_quantmap__44u8_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u8_p2_0 = { @@ -175417,8 +163411,8 @@ static float _vq_quantthresh__44u8_p3_0[] = { }; static long _vq_quantmap__44u8_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u8_p3_0 = { @@ -175487,8 +163481,8 @@ static float _vq_quantthresh__44u8_p4_0[] = { }; static long _vq_quantmap__44u8_p4_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -175530,7 +163524,7 @@ static float _vq_quantthresh__44u8_p5_0[] = { }; static long _vq_quantmap__44u8_p5_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u8_p5_0 = { @@ -175582,8 +163576,8 @@ static float _vq_quantthresh__44u8_p5_1[] = { }; static long _vq_quantmap__44u8_p5_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u8_p5_1 = { @@ -175640,8 +163634,8 @@ static float _vq_quantthresh__44u8_p6_0[] = { }; static long _vq_quantmap__44u8_p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u8_p6_0 = { @@ -175680,7 +163674,7 @@ static float _vq_quantthresh__44u8_p6_1[] = { }; static long _vq_quantmap__44u8_p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u8_p6_1 = { @@ -175737,8 +163731,8 @@ static float _vq_quantthresh__44u8_p7_0[] = { }; static long _vq_quantmap__44u8_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u8_p7_0 = { @@ -175790,8 +163784,8 @@ static float _vq_quantthresh__44u8_p7_1[] = { }; static long _vq_quantmap__44u8_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u8_p7_1 = { @@ -175854,8 +163848,8 @@ static float _vq_quantthresh__44u8_p8_0[] = { }; static long _vq_quantmap__44u8_p8_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44u8_p8_0 = { @@ -175938,8 +163932,8 @@ static float _vq_quantthresh__44u8_p8_1[] = { }; static long _vq_quantmap__44u8_p8_1[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -175987,8 +163981,8 @@ static float _vq_quantthresh__44u8_p9_0[] = { }; static long _vq_quantmap__44u8_p9_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u8_p9_0 = { @@ -176064,8 +164058,8 @@ static float _vq_quantthresh__44u8_p9_1[] = { }; static long _vq_quantmap__44u8_p9_1[] = { - 17, 15, 13, 11, 9, 7, 5, 3, - 1, 0, 2, 4, 6, 8, 10, 12, + 17, 15, 13, 11, 9, 7, 5, 3, + 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, }; @@ -176158,8 +164152,8 @@ static float _vq_quantthresh__44u8_p9_2[] = { static long _vq_quantmap__44u8_p9_2[] = { 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, @@ -176245,7 +164239,7 @@ static float _vq_quantthresh__44u9_p1_0[] = { }; static long _vq_quantmap__44u9_p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u9_p1_0 = { @@ -176322,7 +164316,7 @@ static float _vq_quantthresh__44u9_p2_0[] = { }; static long _vq_quantmap__44u9_p2_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u9_p2_0 = { @@ -176369,8 +164363,8 @@ static float _vq_quantthresh__44u9_p3_0[] = { }; static long _vq_quantmap__44u9_p3_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44u9_p3_0 = { @@ -176439,8 +164433,8 @@ static float _vq_quantthresh__44u9_p4_0[] = { }; static long _vq_quantmap__44u9_p4_0[] = { - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, }; @@ -176482,7 +164476,7 @@ static float _vq_quantthresh__44u9_p5_0[] = { }; static long _vq_quantmap__44u9_p5_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44u9_p5_0 = { @@ -176534,8 +164528,8 @@ static float _vq_quantthresh__44u9_p5_1[] = { }; static long _vq_quantmap__44u9_p5_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u9_p5_1 = { @@ -176592,8 +164586,8 @@ static float _vq_quantthresh__44u9_p6_0[] = { }; static long _vq_quantmap__44u9_p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u9_p6_0 = { @@ -176632,7 +164626,7 @@ static float _vq_quantthresh__44u9_p6_1[] = { }; static long _vq_quantmap__44u9_p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44u9_p6_1 = { @@ -176689,8 +164683,8 @@ static float _vq_quantthresh__44u9_p7_0[] = { }; static long _vq_quantmap__44u9_p7_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44u9_p7_0 = { @@ -176742,8 +164736,8 @@ static float _vq_quantthresh__44u9_p7_1[] = { }; static long _vq_quantmap__44u9_p7_1[] = { - 9, 7, 5, 3, 1, 0, 2, 4, - 6, 8, 10, + 9, 7, 5, 3, 1, 0, 2, 4, + 6, 8, 10, }; static encode_aux_threshmatch _vq_auxt__44u9_p7_1 = { @@ -176806,8 +164800,8 @@ static float _vq_quantthresh__44u9_p8_0[] = { }; static long _vq_quantmap__44u9_p8_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44u9_p8_0 = { @@ -176890,8 +164884,8 @@ static float _vq_quantthresh__44u9_p8_1[] = { }; static long _vq_quantmap__44u9_p8_1[] = { - 19, 17, 15, 13, 11, 9, 7, 5, - 3, 1, 0, 2, 4, 6, 8, 10, + 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, }; @@ -176955,8 +164949,8 @@ static float _vq_quantthresh__44u9_p9_0[] = { }; static long _vq_quantmap__44u9_p9_0[] = { - 13, 11, 9, 7, 5, 3, 1, 0, - 2, 4, 6, 8, 10, 12, 14, + 13, 11, 9, 7, 5, 3, 1, 0, + 2, 4, 6, 8, 10, 12, 14, }; static encode_aux_threshmatch _vq_auxt__44u9_p9_0 = { @@ -177032,8 +165026,8 @@ static float _vq_quantthresh__44u9_p9_1[] = { }; static long _vq_quantmap__44u9_p9_1[] = { - 17, 15, 13, 11, 9, 7, 5, 3, - 1, 0, 2, 4, 6, 8, 10, 12, + 17, 15, 13, 11, 9, 7, 5, 3, + 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, }; @@ -177126,8 +165120,8 @@ static float _vq_quantthresh__44u9_p9_2[] = { static long _vq_quantmap__44u9_p9_2[] = { 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, - 15, 13, 11, 9, 7, 5, 3, 1, - 0, 2, 4, 6, 8, 10, 12, 14, + 15, 13, 11, 9, 7, 5, 3, 1, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, @@ -177189,7 +165183,7 @@ static float _vq_quantthresh__44un1__p1_0[] = { }; static long _vq_quantmap__44un1__p1_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44un1__p1_0 = { @@ -177230,7 +165224,7 @@ static float _vq_quantthresh__44un1__p2_0[] = { }; static long _vq_quantmap__44un1__p2_0[] = { - 1, 0, 2, + 1, 0, 2, }; static encode_aux_threshmatch _vq_auxt__44un1__p2_0 = { @@ -177307,7 +165301,7 @@ static float _vq_quantthresh__44un1__p3_0[] = { }; static long _vq_quantmap__44un1__p3_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44un1__p3_0 = { @@ -177384,7 +165378,7 @@ static float _vq_quantthresh__44un1__p4_0[] = { }; static long _vq_quantmap__44un1__p4_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44un1__p4_0 = { @@ -177431,8 +165425,8 @@ static float _vq_quantthresh__44un1__p5_0[] = { }; static long _vq_quantmap__44un1__p5_0[] = { - 7, 5, 3, 1, 0, 2, 4, 6, - 8, + 7, 5, 3, 1, 0, 2, 4, 6, + 8, }; static encode_aux_threshmatch _vq_auxt__44un1__p5_0 = { @@ -177489,8 +165483,8 @@ static float _vq_quantthresh__44un1__p6_0[] = { }; static long _vq_quantmap__44un1__p6_0[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44un1__p6_0 = { @@ -177529,7 +165523,7 @@ static float _vq_quantthresh__44un1__p6_1[] = { }; static long _vq_quantmap__44un1__p6_1[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44un1__p6_1 = { @@ -177606,7 +165600,7 @@ static float _vq_quantthresh__44un1__p7_0[] = { }; static long _vq_quantmap__44un1__p7_0[] = { - 3, 1, 0, 2, 4, + 3, 1, 0, 2, 4, }; static encode_aux_threshmatch _vq_auxt__44un1__p7_0 = { @@ -177663,8 +165657,8 @@ static float _vq_quantthresh__44un1__p7_1[] = { }; static long _vq_quantmap__44un1__p7_1[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44un1__p7_1 = { @@ -177721,8 +165715,8 @@ static float _vq_quantthresh__44un1__p7_2[] = { }; static long _vq_quantmap__44un1__p7_2[] = { - 11, 9, 7, 5, 3, 1, 0, 2, - 4, 6, 8, 10, 12, + 11, 9, 7, 5, 3, 1, 0, 2, + 4, 6, 8, 10, 12, }; static encode_aux_threshmatch _vq_auxt__44un1__p7_2 = { @@ -177762,8 +165756,6 @@ static static_codebook _huff_book__44un1__short = { }; /********* End of inlined file: res_books_uncoupled.h *********/ -/***** residue backends *********************************************/ - static vorbis_info_residue0 _residue_44_low_un={ 0,-1, -1, 8,-1, {0}, @@ -177774,7 +165766,6 @@ static vorbis_info_residue0 _residue_44_low_un={ static vorbis_info_residue0 _residue_44_mid_un={ 0,-1, -1, 10,-1, - /* 0 1 2 3 4 5 6 7 8 9 */ {0}, {-1}, { .5, 1.5, 1.5, 2.5, 2.5, 4.5, 4.5, 16.5, 60.5}, @@ -177783,16 +165774,12 @@ static vorbis_info_residue0 _residue_44_mid_un={ static vorbis_info_residue0 _residue_44_hi_un={ 0,-1, -1, 10,-1, - /* 0 1 2 3 4 5 6 7 8 9 */ {0}, {-1}, { .5, 1.5, 2.5, 4.5, 8.5, 16.5, 32.5, 71.5,157.5}, { -1, -1, -1, -1, -1, -1, -1, -1, -1} }; -/* mapping conventions: - only one submap (this would change for efficient 5.1 support for example)*/ -/* Four psychoacoustic profiles are used, one for each blocktype */ static vorbis_info_mapping0 _map_nominal_u[2]={ {1, {0,0}, {0}, {0}, 0,{0},{0}}, {1, {0,0}, {1}, {1}, 0,{0},{0}} @@ -177800,144 +165787,144 @@ static vorbis_info_mapping0 _map_nominal_u[2]={ static static_bookblock _resbook_44u_n1={ { - {0}, - {0,0,&_44un1__p1_0}, - {0,0,&_44un1__p2_0}, - {0,0,&_44un1__p3_0}, - {0,0,&_44un1__p4_0}, - {0,0,&_44un1__p5_0}, - {&_44un1__p6_0,&_44un1__p6_1}, - {&_44un1__p7_0,&_44un1__p7_1,&_44un1__p7_2} + {0}, + {0,0,&_44un1__p1_0}, + {0,0,&_44un1__p2_0}, + {0,0,&_44un1__p3_0}, + {0,0,&_44un1__p4_0}, + {0,0,&_44un1__p5_0}, + {&_44un1__p6_0,&_44un1__p6_1}, + {&_44un1__p7_0,&_44un1__p7_1,&_44un1__p7_2} } }; static static_bookblock _resbook_44u_0={ { - {0}, - {0,0,&_44u0__p1_0}, - {0,0,&_44u0__p2_0}, - {0,0,&_44u0__p3_0}, - {0,0,&_44u0__p4_0}, - {0,0,&_44u0__p5_0}, - {&_44u0__p6_0,&_44u0__p6_1}, - {&_44u0__p7_0,&_44u0__p7_1,&_44u0__p7_2} + {0}, + {0,0,&_44u0__p1_0}, + {0,0,&_44u0__p2_0}, + {0,0,&_44u0__p3_0}, + {0,0,&_44u0__p4_0}, + {0,0,&_44u0__p5_0}, + {&_44u0__p6_0,&_44u0__p6_1}, + {&_44u0__p7_0,&_44u0__p7_1,&_44u0__p7_2} } }; static static_bookblock _resbook_44u_1={ { - {0}, - {0,0,&_44u1__p1_0}, - {0,0,&_44u1__p2_0}, - {0,0,&_44u1__p3_0}, - {0,0,&_44u1__p4_0}, - {0,0,&_44u1__p5_0}, - {&_44u1__p6_0,&_44u1__p6_1}, - {&_44u1__p7_0,&_44u1__p7_1,&_44u1__p7_2} + {0}, + {0,0,&_44u1__p1_0}, + {0,0,&_44u1__p2_0}, + {0,0,&_44u1__p3_0}, + {0,0,&_44u1__p4_0}, + {0,0,&_44u1__p5_0}, + {&_44u1__p6_0,&_44u1__p6_1}, + {&_44u1__p7_0,&_44u1__p7_1,&_44u1__p7_2} } }; static static_bookblock _resbook_44u_2={ { - {0}, - {0,0,&_44u2__p1_0}, - {0,0,&_44u2__p2_0}, - {0,0,&_44u2__p3_0}, - {0,0,&_44u2__p4_0}, - {0,0,&_44u2__p5_0}, - {&_44u2__p6_0,&_44u2__p6_1}, - {&_44u2__p7_0,&_44u2__p7_1,&_44u2__p7_2} + {0}, + {0,0,&_44u2__p1_0}, + {0,0,&_44u2__p2_0}, + {0,0,&_44u2__p3_0}, + {0,0,&_44u2__p4_0}, + {0,0,&_44u2__p5_0}, + {&_44u2__p6_0,&_44u2__p6_1}, + {&_44u2__p7_0,&_44u2__p7_1,&_44u2__p7_2} } }; static static_bookblock _resbook_44u_3={ { - {0}, - {0,0,&_44u3__p1_0}, - {0,0,&_44u3__p2_0}, - {0,0,&_44u3__p3_0}, - {0,0,&_44u3__p4_0}, - {0,0,&_44u3__p5_0}, - {&_44u3__p6_0,&_44u3__p6_1}, - {&_44u3__p7_0,&_44u3__p7_1,&_44u3__p7_2} + {0}, + {0,0,&_44u3__p1_0}, + {0,0,&_44u3__p2_0}, + {0,0,&_44u3__p3_0}, + {0,0,&_44u3__p4_0}, + {0,0,&_44u3__p5_0}, + {&_44u3__p6_0,&_44u3__p6_1}, + {&_44u3__p7_0,&_44u3__p7_1,&_44u3__p7_2} } }; static static_bookblock _resbook_44u_4={ { - {0}, - {0,0,&_44u4__p1_0}, - {0,0,&_44u4__p2_0}, - {0,0,&_44u4__p3_0}, - {0,0,&_44u4__p4_0}, - {0,0,&_44u4__p5_0}, - {&_44u4__p6_0,&_44u4__p6_1}, - {&_44u4__p7_0,&_44u4__p7_1,&_44u4__p7_2} + {0}, + {0,0,&_44u4__p1_0}, + {0,0,&_44u4__p2_0}, + {0,0,&_44u4__p3_0}, + {0,0,&_44u4__p4_0}, + {0,0,&_44u4__p5_0}, + {&_44u4__p6_0,&_44u4__p6_1}, + {&_44u4__p7_0,&_44u4__p7_1,&_44u4__p7_2} } }; static static_bookblock _resbook_44u_5={ { - {0}, - {0,0,&_44u5__p1_0}, - {0,0,&_44u5__p2_0}, - {0,0,&_44u5__p3_0}, - {0,0,&_44u5__p4_0}, - {0,0,&_44u5__p5_0}, - {0,0,&_44u5__p6_0}, - {&_44u5__p7_0,&_44u5__p7_1}, - {&_44u5__p8_0,&_44u5__p8_1}, - {&_44u5__p9_0,&_44u5__p9_1,&_44u5__p9_2} + {0}, + {0,0,&_44u5__p1_0}, + {0,0,&_44u5__p2_0}, + {0,0,&_44u5__p3_0}, + {0,0,&_44u5__p4_0}, + {0,0,&_44u5__p5_0}, + {0,0,&_44u5__p6_0}, + {&_44u5__p7_0,&_44u5__p7_1}, + {&_44u5__p8_0,&_44u5__p8_1}, + {&_44u5__p9_0,&_44u5__p9_1,&_44u5__p9_2} } }; static static_bookblock _resbook_44u_6={ { - {0}, - {0,0,&_44u6__p1_0}, - {0,0,&_44u6__p2_0}, - {0,0,&_44u6__p3_0}, - {0,0,&_44u6__p4_0}, - {0,0,&_44u6__p5_0}, - {0,0,&_44u6__p6_0}, - {&_44u6__p7_0,&_44u6__p7_1}, - {&_44u6__p8_0,&_44u6__p8_1}, - {&_44u6__p9_0,&_44u6__p9_1,&_44u6__p9_2} + {0}, + {0,0,&_44u6__p1_0}, + {0,0,&_44u6__p2_0}, + {0,0,&_44u6__p3_0}, + {0,0,&_44u6__p4_0}, + {0,0,&_44u6__p5_0}, + {0,0,&_44u6__p6_0}, + {&_44u6__p7_0,&_44u6__p7_1}, + {&_44u6__p8_0,&_44u6__p8_1}, + {&_44u6__p9_0,&_44u6__p9_1,&_44u6__p9_2} } }; static static_bookblock _resbook_44u_7={ { - {0}, - {0,0,&_44u7__p1_0}, - {0,0,&_44u7__p2_0}, - {0,0,&_44u7__p3_0}, - {0,0,&_44u7__p4_0}, - {0,0,&_44u7__p5_0}, - {0,0,&_44u7__p6_0}, - {&_44u7__p7_0,&_44u7__p7_1}, - {&_44u7__p8_0,&_44u7__p8_1}, - {&_44u7__p9_0,&_44u7__p9_1,&_44u7__p9_2} + {0}, + {0,0,&_44u7__p1_0}, + {0,0,&_44u7__p2_0}, + {0,0,&_44u7__p3_0}, + {0,0,&_44u7__p4_0}, + {0,0,&_44u7__p5_0}, + {0,0,&_44u7__p6_0}, + {&_44u7__p7_0,&_44u7__p7_1}, + {&_44u7__p8_0,&_44u7__p8_1}, + {&_44u7__p9_0,&_44u7__p9_1,&_44u7__p9_2} } }; static static_bookblock _resbook_44u_8={ { - {0}, - {0,0,&_44u8_p1_0}, - {0,0,&_44u8_p2_0}, - {0,0,&_44u8_p3_0}, - {0,0,&_44u8_p4_0}, - {&_44u8_p5_0,&_44u8_p5_1}, - {&_44u8_p6_0,&_44u8_p6_1}, - {&_44u8_p7_0,&_44u8_p7_1}, - {&_44u8_p8_0,&_44u8_p8_1}, - {&_44u8_p9_0,&_44u8_p9_1,&_44u8_p9_2} + {0}, + {0,0,&_44u8_p1_0}, + {0,0,&_44u8_p2_0}, + {0,0,&_44u8_p3_0}, + {0,0,&_44u8_p4_0}, + {&_44u8_p5_0,&_44u8_p5_1}, + {&_44u8_p6_0,&_44u8_p6_1}, + {&_44u8_p7_0,&_44u8_p7_1}, + {&_44u8_p8_0,&_44u8_p8_1}, + {&_44u8_p9_0,&_44u8_p9_1,&_44u8_p9_2} } }; static static_bookblock _resbook_44u_9={ { - {0}, - {0,0,&_44u9_p1_0}, - {0,0,&_44u9_p2_0}, - {0,0,&_44u9_p3_0}, - {0,0,&_44u9_p4_0}, - {&_44u9_p5_0,&_44u9_p5_1}, - {&_44u9_p6_0,&_44u9_p6_1}, - {&_44u9_p7_0,&_44u9_p7_1}, - {&_44u9_p8_0,&_44u9_p8_1}, - {&_44u9_p9_0,&_44u9_p9_1,&_44u9_p9_2} + {0}, + {0,0,&_44u9_p1_0}, + {0,0,&_44u9_p2_0}, + {0,0,&_44u9_p3_0}, + {0,0,&_44u9_p4_0}, + {&_44u9_p5_0,&_44u9_p5_1}, + {&_44u9_p6_0,&_44u9_p6_1}, + {&_44u9_p7_0,&_44u9_p7_1}, + {&_44u9_p8_0,&_44u9_p8_1}, + {&_44u9_p9_0,&_44u9_p9_1,&_44u9_p9_2} } }; @@ -178245,31 +166232,26 @@ static att3 _psy_tone_masteratt_8[3]={ }; static vp_adjblock _vp_tonemask_adj_8[3]={ - /* adjust for mode zero */ - /* 63 125 250 500 1 2 4 8 16 */ {{-15,-15,-15,-15,-10,-10, -6, 0, 0, 0, 0,10, 0, 0,99,99,99}}, /* 1 */ {{-15,-15,-15,-15,-10,-10, -6, 0, 0, 0, 0,10, 0, 0,99,99,99}}, /* 1 */ {{-15,-15,-15,-15,-10,-10, -6, 0, 0, 0, 0, 0, 0, 0,99,99,99}}, /* 1 */ }; static noise3 _psy_noisebias_8[3]={ - /* 63 125 250 500 1k 2k 4k 8k 16k*/ {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 8, 8, 8, 10, 10, 99, 99, 99}, - {-10,-10,-10,-10, -5, -5, -5, 0, 0, 4, 4, 4, 4, 4, 99, 99, 99}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, + {-10,-10,-10,-10, -5, -5, -5, 0, 0, 4, 4, 4, 4, 4, 99, 99, 99}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 8, 8, 8, 10, 10, 99, 99, 99}, - {-10,-10,-10,-10,-10,-10, -5, -5, -5, 0, 0, 0, 0, 0, 99, 99, 99}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, + {-10,-10,-10,-10,-10,-10, -5, -5, -5, 0, 0, 0, 0, 0, 99, 99, 99}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 99, 99, 99}, - {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10, 99, 99, 99}, - {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24, 99, 99, 99}}}, + {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10, 99, 99, 99}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24, 99, 99, 99}}}, }; -/* stereo mode by base quality level */ static adj_stereo _psy_stereo_modes_8[3]={ - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 */ {{ 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, { 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, @@ -178291,18 +166273,18 @@ static noiseguard _psy_noiseguards_8[2]={ static compandblock _psy_compand_8[2]={ {{ - 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ - 8, 8, 9, 9,10,10,11, 11, /* 15dB */ - 12,12,13,13,14,14,15, 15, /* 23dB */ - 16,16,17,17,17,18,18, 19, /* 31dB */ - 19,19,20,21,22,23,24, 25, /* 39dB */ + 0, 1, 2, 3, 4, 5, 6, 7, /* 7dB */ + 8, 8, 9, 9,10,10,11, 11, /* 15dB */ + 12,12,13,13,14,14,15, 15, /* 23dB */ + 16,16,17,17,17,18,18, 19, /* 31dB */ + 19,19,20,21,22,23,24, 25, /* 39dB */ }}, {{ - 0, 1, 2, 3, 4, 5, 6, 6, /* 7dB */ - 7, 7, 6, 6, 5, 5, 4, 4, /* 15dB */ - 3, 3, 3, 4, 5, 6, 7, 8, /* 23dB */ - 9,10,11,12,13,14,15, 16, /* 31dB */ - 17,18,19,20,21,22,23, 24, /* 39dB */ + 0, 1, 2, 3, 4, 5, 6, 6, /* 7dB */ + 7, 7, 6, 6, 5, 5, 4, 4, /* 15dB */ + 3, 3, 3, 4, 5, 6, 7, 8, /* 23dB */ + 9,10,11,12,13,14,15, 16, /* 31dB */ + 17,18,19,20,21,22,23, 24, /* 39dB */ }}, }; @@ -178325,22 +166307,20 @@ static int _psy_ath_abs_8[3]={ /********* Start of inlined file: residue_8.h *********/ -/***** residue backends *********************************************/ - static static_bookblock _resbook_8s_0={ { - {0},{0,0,&_8c0_s_p1_0},{0,0,&_8c0_s_p2_0},{0,0,&_8c0_s_p3_0}, - {0,0,&_8c0_s_p4_0},{0,0,&_8c0_s_p5_0},{0,0,&_8c0_s_p6_0}, - {&_8c0_s_p7_0,&_8c0_s_p7_1},{&_8c0_s_p8_0,&_8c0_s_p8_1}, - {&_8c0_s_p9_0,&_8c0_s_p9_1,&_8c0_s_p9_2} + {0},{0,0,&_8c0_s_p1_0},{0,0,&_8c0_s_p2_0},{0,0,&_8c0_s_p3_0}, + {0,0,&_8c0_s_p4_0},{0,0,&_8c0_s_p5_0},{0,0,&_8c0_s_p6_0}, + {&_8c0_s_p7_0,&_8c0_s_p7_1},{&_8c0_s_p8_0,&_8c0_s_p8_1}, + {&_8c0_s_p9_0,&_8c0_s_p9_1,&_8c0_s_p9_2} } }; static static_bookblock _resbook_8s_1={ { - {0},{0,0,&_8c1_s_p1_0},{0,0,&_8c1_s_p2_0},{0,0,&_8c1_s_p3_0}, - {0,0,&_8c1_s_p4_0},{0,0,&_8c1_s_p5_0},{0,0,&_8c1_s_p6_0}, - {&_8c1_s_p7_0,&_8c1_s_p7_1},{&_8c1_s_p8_0,&_8c1_s_p8_1}, - {&_8c1_s_p9_0,&_8c1_s_p9_1,&_8c1_s_p9_2} + {0},{0,0,&_8c1_s_p1_0},{0,0,&_8c1_s_p2_0},{0,0,&_8c1_s_p3_0}, + {0,0,&_8c1_s_p4_0},{0,0,&_8c1_s_p5_0},{0,0,&_8c1_s_p6_0}, + {&_8c1_s_p7_0,&_8c1_s_p7_1},{&_8c1_s_p8_0,&_8c1_s_p8_1}, + {&_8c1_s_p9_0,&_8c1_s_p9_1,&_8c1_s_p9_2} } }; @@ -178362,28 +166342,28 @@ static vorbis_mapping_template _mapres_template_8_stereo[2]={ static static_bookblock _resbook_8u_0={ { - {0}, - {0,0,&_8u0__p1_0}, - {0,0,&_8u0__p2_0}, - {0,0,&_8u0__p3_0}, - {0,0,&_8u0__p4_0}, - {0,0,&_8u0__p5_0}, - {&_8u0__p6_0,&_8u0__p6_1}, - {&_8u0__p7_0,&_8u0__p7_1,&_8u0__p7_2} + {0}, + {0,0,&_8u0__p1_0}, + {0,0,&_8u0__p2_0}, + {0,0,&_8u0__p3_0}, + {0,0,&_8u0__p4_0}, + {0,0,&_8u0__p5_0}, + {&_8u0__p6_0,&_8u0__p6_1}, + {&_8u0__p7_0,&_8u0__p7_1,&_8u0__p7_2} } }; static static_bookblock _resbook_8u_1={ { - {0}, - {0,0,&_8u1__p1_0}, - {0,0,&_8u1__p2_0}, - {0,0,&_8u1__p3_0}, - {0,0,&_8u1__p4_0}, - {0,0,&_8u1__p5_0}, - {0,0,&_8u1__p6_0}, - {&_8u1__p7_0,&_8u1__p7_1}, - {&_8u1__p8_0,&_8u1__p8_1}, - {&_8u1__p9_0,&_8u1__p9_1,&_8u1__p9_2} + {0}, + {0,0,&_8u1__p1_0}, + {0,0,&_8u1__p2_0}, + {0,0,&_8u1__p3_0}, + {0,0,&_8u1__p4_0}, + {0,0,&_8u1__p5_0}, + {0,0,&_8u1__p6_0}, + {&_8u1__p7_0,&_8u1__p7_1}, + {&_8u1__p8_0,&_8u1__p8_1}, + {&_8u1__p9_0,&_8u1__p9_1,&_8u1__p9_2} } }; @@ -178543,26 +166523,23 @@ static att3 _psy_tone_masteratt_11[3]={ }; static vp_adjblock _vp_tonemask_adj_11[3]={ - /* adjust for mode zero */ - /* 63 125 250 500 1 2 4 8 16 */ {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0,10, 2, 0,99,99,99}}, /* 0 */ {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0, 5, 0, 0,99,99,99}}, /* 1 */ {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0, 0, 0, 0,99,99,99}}, /* 2 */ }; static noise3 _psy_noisebias_11[3]={ - /* 63 125 250 500 1k 2k 4k 8k 16k*/ {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 10, 10, 12, 12, 12, 99, 99, 99}, - {-15,-15,-15,-15,-10,-10, -5, 0, 0, 4, 4, 5, 5, 10, 99, 99, 99}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, + {-15,-15,-15,-15,-10,-10, -5, 0, 0, 4, 4, 5, 5, 10, 99, 99, 99}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 10, 10, 12, 12, 12, 99, 99, 99}, - {-15,-15,-15,-15,-10,-10, -5, -5, -5, 0, 0, 0, 0, 0, 99, 99, 99}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, + {-15,-15,-15,-15,-10,-10, -5, -5, -5, 0, 0, 0, 0, 0, 99, 99, 99}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, 99, 99, 99}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 99, 99, 99}, - {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10, 99, 99, 99}, - {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24, 99, 99, 99}}}, + {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10, 99, 99, 99}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24, 99, 99, 99}}}, }; static double _noise_thresh_11[3]={ .3,.5,.5 }; @@ -178694,9 +166671,7 @@ ve_setup_data_template ve_setup_11_uncoupled={ /********* Start of inlined file: setup_16.h *********/ /********* Start of inlined file: psych_16.h *********/ -/* stereo mode by base quality level */ static adj_stereo _psy_stereo_modes_16[4]={ - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 */ {{ 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, { 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4}, @@ -178725,8 +166700,6 @@ static att3 _psy_tone_masteratt_16[4]={ }; static vp_adjblock _vp_tonemask_adj_16[4]={ - /* adjust for mode zero */ - /* 63 125 250 500 1 2 4 8 16 */ {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0,10, 0, 0, 0, 0, 0}}, /* 0 */ {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0,10, 0, 0, 0, 0, 0}}, /* 1 */ {{-20,-20,-20,-20,-20,-16,-10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 2 */ @@ -178734,60 +166707,57 @@ static vp_adjblock _vp_tonemask_adj_16[4]={ }; static noise3 _psy_noisebias_16_short[4]={ - /* 63 125 250 500 1k 2k 4k 8k 16k*/ {{{-15,-15,-15,-15,-15,-10,-10,-5, 4, 10, 10, 10, 10, 12, 12, 14, 20}, - {-15,-15,-15,-15,-15,-10,-10, -5, 0, 0, 4, 5, 5, 6, 8, 8, 15}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, + {-15,-15,-15,-15,-15,-10,-10, -5, 0, 0, 4, 5, 5, 6, 8, 8, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, {{{-15,-15,-15,-15,-15,-10,-10,-5, 4, 6, 6, 6, 6, 8, 10, 12, 20}, - {-15,-15,-15,-15,-15,-15,-15,-10, -5, -5, -5, 4, 5, 6, 8, 8, 15}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10,-10,-10,-10,-10,-10,-10,-10,-10}}}, + {-15,-15,-15,-15,-15,-15,-15,-10, -5, -5, -5, 4, 5, 6, 8, 8, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10,-10,-10,-10,-10,-10,-10,-10,-10}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 5, 8, 12}, - {-20,-20,-20,-20,-16,-12,-20,-14,-10,-10, -8, 0, 0, 0, 0, 2, 5}, - {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, + {-20,-20,-20,-20,-16,-12,-20,-14,-10,-10, -8, 0, 0, 0, 0, 2, 5}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, -5, -5, -5, -5, -5, 0, 0, 0, 6}, - {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10,-10,-10, -6}, - {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, + {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10,-10,-10, -6}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, }; static noise3 _psy_noisebias_16_impulse[4]={ - /* 63 125 250 500 1k 2k 4k 8k 16k*/ {{{-15,-15,-15,-15,-15,-10,-10,-5, 4, 10, 10, 10, 10, 12, 12, 14, 20}, - {-15,-15,-15,-15,-15,-10,-10, -5, 0, 0, 4, 5, 5, 6, 8, 8, 15}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, + {-15,-15,-15,-15,-15,-10,-10, -5, 0, 0, 4, 5, 5, 6, 8, 8, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, {{{-15,-15,-15,-15,-15,-10,-10,-5, 4, 4, 4, 4, 5, 5, 6, 8, 15}, - {-15,-15,-15,-15,-15,-15,-15,-10, -5, -5, -5, 0, 0, 0, 0, 4, 10}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10,-10,-10,-10,-10,-10,-10,-10,-10}}}, + {-15,-15,-15,-15,-15,-15,-15,-10, -5, -5, -5, 0, 0, 0, 0, 4, 10}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10,-10,-10,-10,-10,-10,-10,-10,-10}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 0, 0, 0, 0, 0, 0, 4, 10}, - {-20,-20,-20,-20,-16,-12,-20,-14,-10,-10,-10,-10,-10,-10,-10, -7, -5}, - {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, + {-20,-20,-20,-20,-16,-12,-20,-14,-10,-10,-10,-10,-10,-10,-10, -7, -5}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, -5, -5, -5, -5, -5, 0, 0, 0, 6}, - {-30,-30,-30,-30,-26,-22,-20,-18,-18,-18,-20,-20,-20,-20,-20,-20,-16}, - {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, + {-30,-30,-30,-30,-26,-22,-20,-18,-18,-18,-20,-20,-20,-20,-20,-20,-16}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, }; static noise3 _psy_noisebias_16[4]={ - /* 63 125 250 500 1k 2k 4k 8k 16k*/ {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 6, 8, 8, 10, 10, 10, 14, 20}, - {-10,-10,-10,-10,-10, -5, -2, -2, 0, 0, 0, 4, 5, 6, 8, 8, 15}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, + {-10,-10,-10,-10,-10, -5, -2, -2, 0, 0, 0, 4, 5, 6, 8, 8, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, {{{-10,-10,-10,-10, -5, -5, -5, 0, 4, 6, 6, 6, 6, 8, 10, 12, 20}, - {-15,-15,-15,-15,-15,-10, -5, -5, 0, 0, 0, 4, 5, 6, 8, 8, 15}, - {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, + {-15,-15,-15,-15,-15,-10, -5, -5, 0, 0, 0, 4, 5, 6, 8, 8, 15}, + {-30,-30,-30,-30,-30,-24,-20,-14,-10, -6, -8, -8, -6, -6, -6, -6, -6}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, 0, 2, 4, 4, 5, 5, 5, 8, 12}, - {-20,-20,-20,-20,-16,-12,-20,-10, -5, -5, 0, 0, 0, 0, 0, 2, 5}, - {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, + {-20,-20,-20,-20,-16,-12,-20,-10, -5, -5, 0, 0, 0, 0, 0, 2, 5}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, {{{-15,-15,-15,-15,-15,-12,-10, -8, -5, -5, -5, -5, -5, 0, 0, 0, 6}, - {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10,-10,-10, -6}, - {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, + {-30,-30,-30,-30,-26,-22,-20,-14,-12,-12,-10,-10,-10,-10,-10,-10, -6}, + {-30,-30,-30,-30,-26,-26,-26,-26,-26,-26,-26,-26,-26,-24,-20,-20,-20}}}, }; static double _noise_thresh_16[4]={ .3,.5,.5,.5 }; @@ -178805,48 +166775,47 @@ static int _psy_ath_abs_16[4]={ /********* End of inlined file: psych_16.h *********/ /********* Start of inlined file: residue_16.h *********/ -/***** residue backends *********************************************/ static static_bookblock _resbook_16s_0={ { - {0}, - {0,0,&_16c0_s_p1_0}, - {0,0,&_16c0_s_p2_0}, - {0,0,&_16c0_s_p3_0}, - {0,0,&_16c0_s_p4_0}, - {0,0,&_16c0_s_p5_0}, - {0,0,&_16c0_s_p6_0}, - {&_16c0_s_p7_0,&_16c0_s_p7_1}, - {&_16c0_s_p8_0,&_16c0_s_p8_1}, - {&_16c0_s_p9_0,&_16c0_s_p9_1,&_16c0_s_p9_2} + {0}, + {0,0,&_16c0_s_p1_0}, + {0,0,&_16c0_s_p2_0}, + {0,0,&_16c0_s_p3_0}, + {0,0,&_16c0_s_p4_0}, + {0,0,&_16c0_s_p5_0}, + {0,0,&_16c0_s_p6_0}, + {&_16c0_s_p7_0,&_16c0_s_p7_1}, + {&_16c0_s_p8_0,&_16c0_s_p8_1}, + {&_16c0_s_p9_0,&_16c0_s_p9_1,&_16c0_s_p9_2} } }; static static_bookblock _resbook_16s_1={ { - {0}, - {0,0,&_16c1_s_p1_0}, - {0,0,&_16c1_s_p2_0}, - {0,0,&_16c1_s_p3_0}, - {0,0,&_16c1_s_p4_0}, - {0,0,&_16c1_s_p5_0}, - {0,0,&_16c1_s_p6_0}, - {&_16c1_s_p7_0,&_16c1_s_p7_1}, - {&_16c1_s_p8_0,&_16c1_s_p8_1}, - {&_16c1_s_p9_0,&_16c1_s_p9_1,&_16c1_s_p9_2} + {0}, + {0,0,&_16c1_s_p1_0}, + {0,0,&_16c1_s_p2_0}, + {0,0,&_16c1_s_p3_0}, + {0,0,&_16c1_s_p4_0}, + {0,0,&_16c1_s_p5_0}, + {0,0,&_16c1_s_p6_0}, + {&_16c1_s_p7_0,&_16c1_s_p7_1}, + {&_16c1_s_p8_0,&_16c1_s_p8_1}, + {&_16c1_s_p9_0,&_16c1_s_p9_1,&_16c1_s_p9_2} } }; static static_bookblock _resbook_16s_2={ { - {0}, - {0,0,&_16c2_s_p1_0}, - {0,0,&_16c2_s_p2_0}, - {0,0,&_16c2_s_p3_0}, - {0,0,&_16c2_s_p4_0}, - {&_16c2_s_p5_0,&_16c2_s_p5_1}, - {&_16c2_s_p6_0,&_16c2_s_p6_1}, - {&_16c2_s_p7_0,&_16c2_s_p7_1}, - {&_16c2_s_p8_0,&_16c2_s_p8_1}, - {&_16c2_s_p9_0,&_16c2_s_p9_1,&_16c2_s_p9_2} + {0}, + {0,0,&_16c2_s_p1_0}, + {0,0,&_16c2_s_p2_0}, + {0,0,&_16c2_s_p3_0}, + {0,0,&_16c2_s_p4_0}, + {&_16c2_s_p5_0,&_16c2_s_p5_1}, + {&_16c2_s_p6_0,&_16c2_s_p6_1}, + {&_16c2_s_p7_0,&_16c2_s_p7_1}, + {&_16c2_s_p8_0,&_16c2_s_p8_1}, + {&_16c2_s_p9_0,&_16c2_s_p9_1,&_16c2_s_p9_2} } }; @@ -178882,42 +166851,42 @@ static vorbis_mapping_template _mapres_template_16_stereo[3]={ static static_bookblock _resbook_16u_0={ { - {0}, - {0,0,&_16u0__p1_0}, - {0,0,&_16u0__p2_0}, - {0,0,&_16u0__p3_0}, - {0,0,&_16u0__p4_0}, - {0,0,&_16u0__p5_0}, - {&_16u0__p6_0,&_16u0__p6_1}, - {&_16u0__p7_0,&_16u0__p7_1,&_16u0__p7_2} + {0}, + {0,0,&_16u0__p1_0}, + {0,0,&_16u0__p2_0}, + {0,0,&_16u0__p3_0}, + {0,0,&_16u0__p4_0}, + {0,0,&_16u0__p5_0}, + {&_16u0__p6_0,&_16u0__p6_1}, + {&_16u0__p7_0,&_16u0__p7_1,&_16u0__p7_2} } }; static static_bookblock _resbook_16u_1={ { - {0}, - {0,0,&_16u1__p1_0}, - {0,0,&_16u1__p2_0}, - {0,0,&_16u1__p3_0}, - {0,0,&_16u1__p4_0}, - {0,0,&_16u1__p5_0}, - {0,0,&_16u1__p6_0}, - {&_16u1__p7_0,&_16u1__p7_1}, - {&_16u1__p8_0,&_16u1__p8_1}, - {&_16u1__p9_0,&_16u1__p9_1,&_16u1__p9_2} + {0}, + {0,0,&_16u1__p1_0}, + {0,0,&_16u1__p2_0}, + {0,0,&_16u1__p3_0}, + {0,0,&_16u1__p4_0}, + {0,0,&_16u1__p5_0}, + {0,0,&_16u1__p6_0}, + {&_16u1__p7_0,&_16u1__p7_1}, + {&_16u1__p8_0,&_16u1__p8_1}, + {&_16u1__p9_0,&_16u1__p9_1,&_16u1__p9_2} } }; static static_bookblock _resbook_16u_2={ { - {0}, - {0,0,&_16u2_p1_0}, - {0,0,&_16u2_p2_0}, - {0,0,&_16u2_p3_0}, - {0,0,&_16u2_p4_0}, - {&_16u2_p5_0,&_16u2_p5_1}, - {&_16u2_p6_0,&_16u2_p6_1}, - {&_16u2_p7_0,&_16u2_p7_1}, - {&_16u2_p8_0,&_16u2_p8_1}, - {&_16u2_p9_0,&_16u2_p9_1,&_16u2_p9_2} + {0}, + {0,0,&_16u2_p1_0}, + {0,0,&_16u2_p2_0}, + {0,0,&_16u2_p3_0}, + {0,0,&_16u2_p4_0}, + {&_16u2_p5_0,&_16u2_p5_1}, + {&_16u2_p6_0,&_16u2_p6_1}, + {&_16u2_p7_0,&_16u2_p7_1}, + {&_16u2_p8_0,&_16u2_p8_1}, + {&_16u2_p9_0,&_16u2_p9_1,&_16u2_p9_2} } }; @@ -179435,48 +167404,45 @@ static ve_setup_data_template *setup_list[]={ static int vorbis_encode_toplevel_setup(vorbis_info *vi,int ch,long rate){ if(vi && vi->codec_setup){ - vi->version=0; - vi->channels=ch; - vi->rate=rate; + vi->version=0; + vi->channels=ch; + vi->rate=rate; - return(0); + return(0); } return(OV_EINVAL); } static void vorbis_encode_floor_setup(vorbis_info *vi,double s,int block, - static_codebook ***books, - vorbis_info_floor1 *in, - int *x){ + static_codebook ***books, + vorbis_info_floor1 *in, + int *x){ int i,k,is=s; vorbis_info_floor1 *f=(vorbis_info_floor1*) _ogg_calloc(1,sizeof(*f)); codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; memcpy(f,in+x[is],sizeof(*f)); - /* fill in the lowpass field, even if it's temporary */ f->n=ci->blocksizes[block]>>1; - /* books */ { - int partitions=f->partitions; - int maxclass=-1; - int maxbook=-1; - for(i=0;ipartitionclass[i]>maxclass)maxclass=f->partitionclass[i]; - for(i=0;i<=maxclass;i++){ - if(f->class_book[i]>maxbook)maxbook=f->class_book[i]; - f->class_book[i]+=ci->books; - for(k=0;k<(1<class_subs[i]);k++){ + int partitions=f->partitions; + int maxclass=-1; + int maxbook=-1; + for(i=0;ipartitionclass[i]>maxclass)maxclass=f->partitionclass[i]; + for(i=0;i<=maxclass;i++){ + if(f->class_book[i]>maxbook)maxbook=f->class_book[i]; + f->class_book[i]+=ci->books; + for(k=0;k<(1<class_subs[i]);k++){ if(f->class_subbook[i][k]>maxbook)maxbook=f->class_subbook[i][k]; if(f->class_subbook[i][k]>=0)f->class_subbook[i][k]+=ci->books; - } - } + } + } - for(i=0;i<=maxbook;i++) - ci->book_param[ci->books++]=books[x[is]][i]; + for(i=0;i<=maxbook;i++) + ci->book_param[ci->books++]=books[x[is]][i]; } - /* for now, we're only using floor 1 */ ci->floor_type[ci->floors]=1; ci->floor_param[ci->floors]=f; ci->floors++; @@ -179485,8 +167451,8 @@ static void vorbis_encode_floor_setup(vorbis_info *vi,double s,int block, } static void vorbis_encode_global_psych_setup(vorbis_info *vi,double s, - vorbis_info_psy_global *in, - double *x){ + vorbis_info_psy_global *in, + double *x){ int i,is=s; double ds=s-is; codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; @@ -179498,22 +167464,21 @@ static void vorbis_encode_global_psych_setup(vorbis_info *vi,double s, is=(int)ds; ds-=is; if(ds==0 && is>0){ - is--; - ds=1.; + is--; + ds=1.; } - /* interpolate the trigger threshholds */ for(i=0;i<4;i++){ - g->preecho_thresh[i]=in[is].preecho_thresh[i]*(1.-ds)+in[is+1].preecho_thresh[i]*ds; - g->postecho_thresh[i]=in[is].postecho_thresh[i]*(1.-ds)+in[is+1].postecho_thresh[i]*ds; + g->preecho_thresh[i]=in[is].preecho_thresh[i]*(1.-ds)+in[is+1].preecho_thresh[i]*ds; + g->postecho_thresh[i]=in[is].postecho_thresh[i]*(1.-ds)+in[is+1].postecho_thresh[i]*ds; } g->ampmax_att_per_sec=ci->hi.amplitude_track_dBpersec; return; } static void vorbis_encode_global_stereo(vorbis_info *vi, - highlevel_encode_setup *hi, - adj_stereo *p){ + highlevel_encode_setup *hi, + adj_stereo *p){ float s=hi->stereo_point_setting; int i,is=s; double ds=s-is; @@ -179521,12 +167486,11 @@ static void vorbis_encode_global_stereo(vorbis_info *vi, vorbis_info_psy_global *g=&ci->psy_g_param; if(p){ - memcpy(g->coupling_prepointamp,p[is].pre,sizeof(*p[is].pre)*PACKETBLOBS); - memcpy(g->coupling_postpointamp,p[is].post,sizeof(*p[is].post)*PACKETBLOBS); + memcpy(g->coupling_prepointamp,p[is].pre,sizeof(*p[is].pre)*PACKETBLOBS); + memcpy(g->coupling_postpointamp,p[is].post,sizeof(*p[is].post)*PACKETBLOBS); - if(hi->managed){ - /* interpolate the kHz threshholds */ - for(i=0;imanaged){ + for(i=0;icoupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; @@ -179536,56 +167500,56 @@ static void vorbis_encode_global_stereo(vorbis_info *vi, g->sliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; - } - }else{ - float kHz=p[is].kHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].kHz[PACKETBLOBS/2]*ds; - for(i=0;icoupling_pointlimit[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; g->coupling_pointlimit[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; g->coupling_pkHz[i]=kHz; - } + } - kHz=p[is].lowpasskHz[PACKETBLOBS/2]*(1.-ds)+p[is+1].lowpasskHz[PACKETBLOBS/2]*ds; - for(i=0;isliding_lowpass[0][i]=kHz*1000./vi->rate*ci->blocksizes[0]; g->sliding_lowpass[1][i]=kHz*1000./vi->rate*ci->blocksizes[1]; - } - } + } + } }else{ - for(i=0;isliding_lowpass[0][i]=ci->blocksizes[0]; - g->sliding_lowpass[1][i]=ci->blocksizes[1]; - } + for(i=0;isliding_lowpass[0][i]=ci->blocksizes[0]; + g->sliding_lowpass[1][i]=ci->blocksizes[1]; + } } return; } static void vorbis_encode_psyset_setup(vorbis_info *vi,double s, - int *nn_start, - int *nn_partition, - double *nn_thresh, - int block){ + int *nn_start, + int *nn_partition, + double *nn_thresh, + int block){ codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; vorbis_info_psy *p=ci->psy_param[block]; highlevel_encode_setup *hi=&ci->hi; int is=s; if(block>=ci->psys) - ci->psys=block+1; + ci->psys=block+1; if(!p){ - p=(vorbis_info_psy*)_ogg_calloc(1,sizeof(*p)); - ci->psy_param[block]=p; + p=(vorbis_info_psy*)_ogg_calloc(1,sizeof(*p)); + ci->psy_param[block]=p; } memcpy(p,&_psy_info_template,sizeof(*p)); p->blockflag=block>>1; if(hi->noise_normalize_p){ - p->normal_channel_p=1; - p->normal_point_p=1; - p->normal_start=nn_start[is]; - p->normal_partition=nn_partition[is]; - p->normal_thresh=nn_thresh[is]; + p->normal_channel_p=1; + p->normal_point_p=1; + p->normal_start=nn_start[is]; + p->normal_partition=nn_partition[is]; + p->normal_thresh=nn_thresh[is]; } return; @@ -179600,8 +167564,6 @@ static void vorbis_encode_tonemask_setup(vorbis_info *vi,double s,int block, codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; vorbis_info_psy *p=ci->psy_param[block]; - /* 0 and 2 are only used by bitmanagement, but there's no harm to always - filling the values in here */ p->tone_masteratt[0]=att[is].att[0]*(1.-ds)+att[is+1].att[0]*ds; p->tone_masteratt[1]=att[is].att[1]*(1.-ds)+att[is+1].att[1]*ds; p->tone_masteratt[2]=att[is].att[2]*(1.-ds)+att[is+1].att[2]*ds; @@ -179611,12 +167573,12 @@ static void vorbis_encode_tonemask_setup(vorbis_info *vi,double s,int block, p->max_curve_dB=max[is]*(1.-ds)+max[is+1]*ds; for(i=0;itoneatt[i]=in[is].block[i]*(1.-ds)+in[is+1].block[i]*ds; + p->toneatt[i]=in[is].block[i]*(1.-ds)+in[is+1].block[i]*ds; return; } static void vorbis_encode_compand_setup(vorbis_info *vi,double s,int block, - compandblock *in, double *x){ + compandblock *in, double *x){ int i,is=s; double ds=s-is; codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; @@ -179626,18 +167588,17 @@ static void vorbis_encode_compand_setup(vorbis_info *vi,double s,int block, is=(int)ds; ds-=is; if(ds==0 && is>0){ - is--; - ds=1.; + is--; + ds=1.; } - /* interpolate the compander settings */ for(i=0;inoisecompand[i]=in[is].data[i]*(1.-ds)+in[is+1].data[i]*ds; + p->noisecompand[i]=in[is].data[i]*(1.-ds)+in[is+1].data[i]*ds; return; } static void vorbis_encode_peak_setup(vorbis_info *vi,double s,int block, - int *suppress){ + int *suppress){ int is=s; double ds=s-is; codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; @@ -179664,17 +167625,15 @@ static void vorbis_encode_noisebias_setup(vorbis_info *vi,double s,int block, p->noisewindowfixed=guard[block].fixed; for(j=0;jnoiseoff[j][i]=in[is].data[j][i]*(1.-ds)+in[is+1].data[j][i]*ds; + for(i=0;inoiseoff[j][i]=in[is].data[j][i]*(1.-ds)+in[is+1].data[j][i]*ds; - /* impulse blocks may take a user specified bias to boost the - nominal/high noise encoding depth */ for(j=0;jnoiseoff[j][0]+6; /* the lowest it can go */ - for(i=0;inoiseoff[j][i]+=userbias; - if(p->noiseoff[j][i]noiseoff[j][i]=min; - } + float min=p->noiseoff[j][0]+6; /* the lowest it can go */ + for(i=0;inoiseoff[j][i]+=userbias; + if(p->noiseoff[j][i]noiseoff[j][i]=min; + } } return; @@ -179692,7 +167651,7 @@ static void vorbis_encode_ath_setup(vorbis_info *vi,int block){ static int book_dup_or_new(codec_setup_info *ci,static_codebook *book){ int i; for(i=0;ibooks;i++) - if(ci->book_param[i]==book)return(i); + if(ci->book_param[i]==book)return(i); return(ci->books++); } @@ -179711,116 +167670,102 @@ static void vorbis_encode_blocksize_setup(vorbis_info *vi,double s, } static void vorbis_encode_residue_setup(vorbis_info *vi, - int number, int block, - vorbis_residue_template *res){ + int number, int block, + vorbis_residue_template *res){ codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; int i,n; vorbis_info_residue0 *r=(vorbis_info_residue0*)(ci->residue_param[number]= - (vorbis_info_residue0*)_ogg_malloc(sizeof(*r))); + (vorbis_info_residue0*)_ogg_malloc(sizeof(*r))); memcpy(r,res->res,sizeof(*r)); if(ci->residues<=number)ci->residues=number+1; switch(ci->blocksizes[block]){ case 64:case 128:case 256: - r->grouping=16; - break; + r->grouping=16; + break; default: - r->grouping=32; - break; + r->grouping=32; + break; } ci->residue_type[number]=res->res_type; - /* to be adjusted by lowpass/pointlimit later */ n=r->end=ci->blocksizes[block]>>1; if(res->res_type==2) - n=r->end*=vi->channels; + n=r->end*=vi->channels; - /* fill in all the books */ { - int booklist=0,k; + int booklist=0,k; - if(ci->hi.managed){ - for(i=0;ipartitions;i++) + if(ci->hi.managed){ + for(i=0;ipartitions;i++) for(k=0;k<3;k++) if(res->books_base_managed->books[i][k]) - r->secondstages[i]|=(1<secondstages[i]|=(1<groupbook=book_dup_or_new(ci,res->book_aux_managed); - ci->book_param[r->groupbook]=res->book_aux_managed; + r->groupbook=book_dup_or_new(ci,res->book_aux_managed); + ci->book_param[r->groupbook]=res->book_aux_managed; - for(i=0;ipartitions;i++){ + for(i=0;ipartitions;i++){ for(k=0;k<3;k++){ if(res->books_base_managed->books[i][k]){ - int bookid=book_dup_or_new(ci,res->books_base_managed->books[i][k]); - r->booklist[booklist++]=bookid; - ci->book_param[bookid]=res->books_base_managed->books[i][k]; + int bookid=book_dup_or_new(ci,res->books_base_managed->books[i][k]); + r->booklist[booklist++]=bookid; + ci->book_param[bookid]=res->books_base_managed->books[i][k]; } } - } + } - }else{ + }else{ - for(i=0;ipartitions;i++) + for(i=0;ipartitions;i++) for(k=0;k<3;k++) if(res->books_base->books[i][k]) - r->secondstages[i]|=(1<secondstages[i]|=(1<groupbook=book_dup_or_new(ci,res->book_aux); - ci->book_param[r->groupbook]=res->book_aux; + r->groupbook=book_dup_or_new(ci,res->book_aux); + ci->book_param[r->groupbook]=res->book_aux; - for(i=0;ipartitions;i++){ + for(i=0;ipartitions;i++){ for(k=0;k<3;k++){ if(res->books_base->books[i][k]){ - int bookid=book_dup_or_new(ci,res->books_base->books[i][k]); - r->booklist[booklist++]=bookid; - ci->book_param[bookid]=res->books_base->books[i][k]; + int bookid=book_dup_or_new(ci,res->books_base->books[i][k]); + r->booklist[booklist++]=bookid; + ci->book_param[bookid]=res->books_base->books[i][k]; + } + } } } - } - } } - /* lowpass setup/pointlimit */ { - double freq=ci->hi.lowpass_kHz*1000.; - vorbis_info_floor1 *f=(vorbis_info_floor1*)ci->floor_param[block]; /* by convention */ - double nyq=vi->rate/2.; - long blocksize=ci->blocksizes[block]>>1; + double freq=ci->hi.lowpass_kHz*1000.; + vorbis_info_floor1 *f=(vorbis_info_floor1*)ci->floor_param[block]; /* by convention */ + double nyq=vi->rate/2.; + long blocksize=ci->blocksizes[block]>>1; - /* lowpass needs to be set in the floor and the residue. */ - if(freq>nyq)freq=nyq; - /* in the floor, the granularity can be very fine; it doesn't alter - the encoding structure, only the samples used to fit the floor - approximation */ - f->n=freq/nyq*blocksize; + if(freq>nyq)freq=nyq; + f->n=freq/nyq*blocksize; - /* this res may by limited by the maximum pointlimit of the mode, - not the lowpass. the floor is always lowpass limited. */ - if(res->limit_type){ - if(ci->hi.managed) + if(res->limit_type){ + if(ci->hi.managed) freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS-1]*1000.; - else + else freq=ci->psy_g_param.coupling_pkHz[PACKETBLOBS/2]*1000.; - if(freq>nyq)freq=nyq; - } + if(freq>nyq)freq=nyq; + } - /* in the residue, we're constrained, physically, by partition - boundaries. We still lowpass 'wherever', but we have to round up - here to next boundary, or the vorbis spec will round it *down* to - previous boundary in encode/decode */ - if(ci->residue_type[block]==2) - r->end=(int)((freq/nyq*blocksize*2)/r->grouping+.9)* /* round up only if we're well past */ + if(ci->residue_type[block]==2) + r->end=(int)((freq/nyq*blocksize*2)/r->grouping+.9)* /* round up only if we're well past */ r->grouping; - else - r->end=(int)((freq/nyq*blocksize)/r->grouping+.9)* /* round up only if we're well past */ + else + r->end=(int)((freq/nyq*blocksize)/r->grouping+.9)* /* round up only if we're well past */ r->grouping; } } -/* we assume two maps in this encoder */ static void vorbis_encode_map_n_res_setup(vorbis_info *vi,double s, vorbis_mapping_template *maps){ @@ -179834,18 +167779,18 @@ static void vorbis_encode_map_n_res_setup(vorbis_info *vi,double s, for(i=0;imap_param[i]=_ogg_calloc(1,sizeof(*map)); - ci->mode_param[i]=(vorbis_info_mode*)_ogg_calloc(1,sizeof(*mode)); + ci->map_param[i]=_ogg_calloc(1,sizeof(*map)); + ci->mode_param[i]=(vorbis_info_mode*)_ogg_calloc(1,sizeof(*mode)); - memcpy(ci->mode_param[i],mode+i,sizeof(*_mode_template)); - if(i>=ci->modes)ci->modes=i+1; + memcpy(ci->mode_param[i],mode+i,sizeof(*_mode_template)); + if(i>=ci->modes)ci->modes=i+1; - ci->map_type[i]=0; - memcpy(ci->map_param[i],map+i,sizeof(*map)); - if(i>=ci->maps)ci->maps=i+1; + ci->map_type[i]=0; + memcpy(ci->map_param[i],map+i,sizeof(*map)); + if(i>=ci->maps)ci->maps=i+1; - for(j=0;jrate_mapping; if(r==NULL) - return(-1); + return(-1); return((r[is]*(1.-ds)+r[is+1]*ds)*ch); } static void get_setup_template(vorbis_info *vi, - long ch,long srate, - double req,int q_or_bitrate){ + long ch,long srate, + double req,int q_or_bitrate){ int i=0,j; codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; highlevel_encode_setup *hi=&ci->hi; if(q_or_bitrate)req/=ch; while(setup_list[i]){ - if(setup_list[i]->coupling_restriction==-1 || - setup_list[i]->coupling_restriction==ch){ - if(srate>=setup_list[i]->samplerate_min_restriction && + if(setup_list[i]->coupling_restriction==-1 || + setup_list[i]->coupling_restriction==ch){ + if(srate>=setup_list[i]->samplerate_min_restriction && srate<=setup_list[i]->samplerate_max_restriction){ int mappings=setup_list[i]->mappings; double *map=(q_or_bitrate? - setup_list[i]->rate_mapping: - setup_list[i]->quality_mapping); + setup_list[i]->rate_mapping: + setup_list[i]->quality_mapping); - /* the template matches. Does the requested quality mode - fall within this template's modes? */ if(reqmap[setup_list[i]->mappings]){++i;continue;} for(j=0;j=map[j] && reqsetup=setup_list[i]; if(j==mappings) hi->base_setting=j-.001; @@ -179901,21 +167843,14 @@ static void get_setup_template(vorbis_info *vi, } return; - } - } - i++; + } + } + i++; } hi->setup=NULL; } -/* encoders will need to use vorbis_info_init beforehand and call - vorbis_info clear when all done */ - -/* two interfaces; this, more detailed one, and later a convenience - layer on top */ - -/* the final setup call */ int vorbis_encode_setup_init(vorbis_info *vi){ int i0=0,singleblock=0; codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; @@ -179925,121 +167860,104 @@ int vorbis_encode_setup_init(vorbis_info *vi){ if(ci==NULL)return(OV_EINVAL); if(!hi->impulse_block_p)i0=1; - /* too low/high an ATH floater is nonsensical, but doesn't break anything */ if(hi->ath_floating_dB>-80)hi->ath_floating_dB=-80; if(hi->ath_floating_dB<-200)hi->ath_floating_dB=-200; - /* again, bound this to avoid the app shooting itself int he foot - too badly */ if(hi->amplitude_track_dBpersec>0.)hi->amplitude_track_dBpersec=0.; if(hi->amplitude_track_dBpersec<-99999.)hi->amplitude_track_dBpersec=-99999.; - /* get the appropriate setup template; matches the fetch in previous - stages */ setup=(ve_setup_data_template *)hi->setup; if(setup==NULL)return(OV_EINVAL); hi->set_in_stone=1; - /* choose block sizes from configured sizes as well as paying - attention to long_block_p and short_block_p. If the configured - short and long blocks are the same length, we set long_block_p - and unset short_block_p */ vorbis_encode_blocksize_setup(vi,hi->base_setting, setup->blocksize_short, setup->blocksize_long); if(ci->blocksizes[0]==ci->blocksizes[1])singleblock=1; - /* floor setup; choose proper floor params. Allocated on the floor - stack in order; if we alloc only long floor, it's 0 */ vorbis_encode_floor_setup(vi,hi->short_setting,0, - setup->floor_books, - setup->floor_params, - setup->floor_short_mapping); + setup->floor_books, + setup->floor_params, + setup->floor_short_mapping); if(!singleblock) - vorbis_encode_floor_setup(vi,hi->long_setting,1, - setup->floor_books, - setup->floor_params, - setup->floor_long_mapping); + vorbis_encode_floor_setup(vi,hi->long_setting,1, + setup->floor_books, + setup->floor_params, + setup->floor_long_mapping); - /* setup of [mostly] short block detection and stereo*/ vorbis_encode_global_psych_setup(vi,hi->trigger_setting, setup->global_params, setup->global_mapping); vorbis_encode_global_stereo(vi,hi,setup->stereo_modes); - /* basic psych setup and noise normalization */ vorbis_encode_psyset_setup(vi,hi->short_setting, - setup->psy_noise_normal_start[0], - setup->psy_noise_normal_partition[0], - setup->psy_noise_normal_thresh, - 0); + setup->psy_noise_normal_start[0], + setup->psy_noise_normal_partition[0], + setup->psy_noise_normal_thresh, + 0); vorbis_encode_psyset_setup(vi,hi->short_setting, - setup->psy_noise_normal_start[0], - setup->psy_noise_normal_partition[0], - setup->psy_noise_normal_thresh, - 1); + setup->psy_noise_normal_start[0], + setup->psy_noise_normal_partition[0], + setup->psy_noise_normal_thresh, + 1); if(!singleblock){ - vorbis_encode_psyset_setup(vi,hi->long_setting, - setup->psy_noise_normal_start[1], - setup->psy_noise_normal_partition[1], - setup->psy_noise_normal_thresh, - 2); - vorbis_encode_psyset_setup(vi,hi->long_setting, - setup->psy_noise_normal_start[1], - setup->psy_noise_normal_partition[1], - setup->psy_noise_normal_thresh, - 3); + vorbis_encode_psyset_setup(vi,hi->long_setting, + setup->psy_noise_normal_start[1], + setup->psy_noise_normal_partition[1], + setup->psy_noise_normal_thresh, + 2); + vorbis_encode_psyset_setup(vi,hi->long_setting, + setup->psy_noise_normal_start[1], + setup->psy_noise_normal_partition[1], + setup->psy_noise_normal_thresh, + 3); } - /* tone masking setup */ vorbis_encode_tonemask_setup(vi,hi->block[i0].tone_mask_setting,0, - setup->psy_tone_masteratt, - setup->psy_tone_0dB, - setup->psy_tone_adj_impulse); + setup->psy_tone_masteratt, + setup->psy_tone_0dB, + setup->psy_tone_adj_impulse); vorbis_encode_tonemask_setup(vi,hi->block[1].tone_mask_setting,1, - setup->psy_tone_masteratt, - setup->psy_tone_0dB, - setup->psy_tone_adj_other); + setup->psy_tone_masteratt, + setup->psy_tone_0dB, + setup->psy_tone_adj_other); if(!singleblock){ - vorbis_encode_tonemask_setup(vi,hi->block[2].tone_mask_setting,2, + vorbis_encode_tonemask_setup(vi,hi->block[2].tone_mask_setting,2, setup->psy_tone_masteratt, setup->psy_tone_0dB, setup->psy_tone_adj_other); - vorbis_encode_tonemask_setup(vi,hi->block[3].tone_mask_setting,3, + vorbis_encode_tonemask_setup(vi,hi->block[3].tone_mask_setting,3, setup->psy_tone_masteratt, setup->psy_tone_0dB, setup->psy_tone_adj_long); } - /* noise companding setup */ vorbis_encode_compand_setup(vi,hi->block[i0].noise_compand_setting,0, - setup->psy_noise_compand, - setup->psy_noise_compand_short_mapping); + setup->psy_noise_compand, + setup->psy_noise_compand_short_mapping); vorbis_encode_compand_setup(vi,hi->block[1].noise_compand_setting,1, - setup->psy_noise_compand, - setup->psy_noise_compand_short_mapping); + setup->psy_noise_compand, + setup->psy_noise_compand_short_mapping); if(!singleblock){ - vorbis_encode_compand_setup(vi,hi->block[2].noise_compand_setting,2, + vorbis_encode_compand_setup(vi,hi->block[2].noise_compand_setting,2, setup->psy_noise_compand, setup->psy_noise_compand_long_mapping); - vorbis_encode_compand_setup(vi,hi->block[3].noise_compand_setting,3, + vorbis_encode_compand_setup(vi,hi->block[3].noise_compand_setting,3, setup->psy_noise_compand, setup->psy_noise_compand_long_mapping); } - /* peak guarding setup */ vorbis_encode_peak_setup(vi,hi->block[i0].tone_peaklimit_setting,0, setup->psy_tone_dBsuppress); vorbis_encode_peak_setup(vi,hi->block[1].tone_peaklimit_setting,1, setup->psy_tone_dBsuppress); if(!singleblock){ - vorbis_encode_peak_setup(vi,hi->block[2].tone_peaklimit_setting,2, - setup->psy_tone_dBsuppress); - vorbis_encode_peak_setup(vi,hi->block[3].tone_peaklimit_setting,3, - setup->psy_tone_dBsuppress); + vorbis_encode_peak_setup(vi,hi->block[2].tone_peaklimit_setting,2, + setup->psy_tone_dBsuppress); + vorbis_encode_peak_setup(vi,hi->block[3].tone_peaklimit_setting,3, + setup->psy_tone_dBsuppress); } - /* noise bias setup */ vorbis_encode_noisebias_setup(vi,hi->block[i0].noise_bias_setting,0, setup->psy_noise_dBsuppress, setup->psy_noise_bias_impulse, @@ -180050,11 +167968,11 @@ int vorbis_encode_setup_init(vorbis_info *vi){ setup->psy_noise_bias_padding, setup->psy_noiseguards,0.); if(!singleblock){ - vorbis_encode_noisebias_setup(vi,hi->block[2].noise_bias_setting,2, + vorbis_encode_noisebias_setup(vi,hi->block[2].noise_bias_setting,2, setup->psy_noise_dBsuppress, setup->psy_noise_bias_trans, setup->psy_noiseguards,0.); - vorbis_encode_noisebias_setup(vi,hi->block[3].noise_bias_setting,3, + vorbis_encode_noisebias_setup(vi,hi->block[3].noise_bias_setting,3, setup->psy_noise_dBsuppress, setup->psy_noise_bias_long, setup->psy_noiseguards,0.); @@ -180063,36 +167981,35 @@ int vorbis_encode_setup_init(vorbis_info *vi){ vorbis_encode_ath_setup(vi,0); vorbis_encode_ath_setup(vi,1); if(!singleblock){ - vorbis_encode_ath_setup(vi,2); - vorbis_encode_ath_setup(vi,3); + vorbis_encode_ath_setup(vi,2); + vorbis_encode_ath_setup(vi,3); } vorbis_encode_map_n_res_setup(vi,hi->base_setting,setup->maps); - /* set bitrate readonlies and management */ if(hi->bitrate_av>0) - vi->bitrate_nominal=hi->bitrate_av; + vi->bitrate_nominal=hi->bitrate_av; else{ - vi->bitrate_nominal=setting_to_approx_bitrate(vi); + vi->bitrate_nominal=setting_to_approx_bitrate(vi); } vi->bitrate_lower=hi->bitrate_min; vi->bitrate_upper=hi->bitrate_max; if(hi->bitrate_av) - vi->bitrate_window=(double)hi->bitrate_reservoir/hi->bitrate_av; + vi->bitrate_window=(double)hi->bitrate_reservoir/hi->bitrate_av; else - vi->bitrate_window=0.; + vi->bitrate_window=0.; if(hi->managed){ - ci->bi.avg_rate=hi->bitrate_av; - ci->bi.min_rate=hi->bitrate_min; - ci->bi.max_rate=hi->bitrate_max; + ci->bi.avg_rate=hi->bitrate_av; + ci->bi.min_rate=hi->bitrate_min; + ci->bi.max_rate=hi->bitrate_max; - ci->bi.reservoir_bits=hi->bitrate_reservoir; - ci->bi.reservoir_bias= - hi->bitrate_reservoir_bias; + ci->bi.reservoir_bits=hi->bitrate_reservoir; + ci->bi.reservoir_bias= + hi->bitrate_reservoir_bias; - ci->bi.slew_damp=hi->bitrate_av_damp; + ci->bi.slew_damp=hi->bitrate_av_damp; } @@ -180101,8 +168018,8 @@ int vorbis_encode_setup_init(vorbis_info *vi){ } static int vorbis_encode_setup_setting(vorbis_info *vi, - long channels, - long rate){ + long channels, + long rate){ int ret=0,i,is; codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; highlevel_encode_setup *hi=&ci->hi; @@ -180125,30 +168042,30 @@ static int vorbis_encode_setup_setting(vorbis_info *vi, hi->stereo_point_setting=hi->base_setting; hi->lowpass_kHz= - setup->psy_lowpass[is]*(1.-ds)+setup->psy_lowpass[is+1]*ds; + setup->psy_lowpass[is]*(1.-ds)+setup->psy_lowpass[is+1]*ds; hi->ath_floating_dB=setup->psy_ath_float[is]*(1.-ds)+ - setup->psy_ath_float[is+1]*ds; + setup->psy_ath_float[is+1]*ds; hi->ath_absolute_dB=setup->psy_ath_abs[is]*(1.-ds)+ - setup->psy_ath_abs[is+1]*ds; + setup->psy_ath_abs[is+1]*ds; hi->amplitude_track_dBpersec=-6.; hi->trigger_setting=hi->base_setting; for(i=0;i<4;i++){ - hi->block[i].tone_mask_setting=hi->base_setting; - hi->block[i].tone_peaklimit_setting=hi->base_setting; - hi->block[i].noise_bias_setting=hi->base_setting; - hi->block[i].noise_compand_setting=hi->base_setting; + hi->block[i].tone_mask_setting=hi->base_setting; + hi->block[i].tone_peaklimit_setting=hi->base_setting; + hi->block[i].noise_bias_setting=hi->base_setting; + hi->block[i].noise_compand_setting=hi->base_setting; } return(ret); } int vorbis_encode_setup_vbr(vorbis_info *vi, - long channels, - long rate, - float quality){ + long channels, + long rate, + float quality){ codec_setup_info *ci=(codec_setup_info*) vi->codec_setup; highlevel_encode_setup *hi=&ci->hi; @@ -180172,12 +168089,12 @@ int vorbis_encode_init_vbr(vorbis_info *vi, ret=vorbis_encode_setup_vbr(vi,channels,rate,base_quality); if(ret){ - vorbis_info_clear(vi); - return ret; + vorbis_info_clear(vi); + return ret; } ret=vorbis_encode_setup_init(vi); if(ret) - vorbis_info_clear(vi); + vorbis_info_clear(vi); return(ret); } @@ -180195,18 +168112,18 @@ int vorbis_encode_setup_managed(vorbis_info *vi, int ret=0; if(nominal_bitrate<=0.){ - if(max_bitrate>0.){ - if(min_bitrate>0.) + if(max_bitrate>0.){ + if(min_bitrate>0.) nominal_bitrate=(max_bitrate+min_bitrate)*.5; - else + else nominal_bitrate=max_bitrate*.875; - }else{ - if(min_bitrate>0.){ + }else{ + if(min_bitrate>0.){ nominal_bitrate=min_bitrate; - }else{ + }else{ return(OV_EINVAL); - } - } + } + } } get_setup_template(vi,channels,rate,nominal_bitrate,1); @@ -180214,11 +168131,10 @@ int vorbis_encode_setup_managed(vorbis_info *vi, ret=vorbis_encode_setup_setting(vi,channels,rate); if(ret){ - vorbis_info_clear(vi); - return ret; + vorbis_info_clear(vi); + return ret; } - /* initialize management with sane defaults */ hi->managed=1; hi->bitrate_min=min_bitrate; hi->bitrate_max=max_bitrate; @@ -180232,41 +168148,40 @@ int vorbis_encode_setup_managed(vorbis_info *vi, } int vorbis_encode_init(vorbis_info *vi, - long channels, - long rate, + long channels, + long rate, - long max_bitrate, - long nominal_bitrate, - long min_bitrate){ + long max_bitrate, + long nominal_bitrate, + long min_bitrate){ int ret=vorbis_encode_setup_managed(vi,channels,rate, - max_bitrate, - nominal_bitrate, - min_bitrate); + max_bitrate, + nominal_bitrate, + min_bitrate); if(ret){ - vorbis_info_clear(vi); - return(ret); + vorbis_info_clear(vi); + return(ret); } ret=vorbis_encode_setup_init(vi); if(ret) - vorbis_info_clear(vi); + vorbis_info_clear(vi); return(ret); } int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ if(vi){ - codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; - highlevel_encode_setup *hi=&ci->hi; - int setp=(number&0xf); /* a read request has a low nibble of 0 */ + codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; + highlevel_encode_setup *hi=&ci->hi; + int setp=(number&0xf); /* a read request has a low nibble of 0 */ - if(setp && hi->set_in_stone)return(OV_EINVAL); + if(setp && hi->set_in_stone)return(OV_EINVAL); - switch(number){ + switch(number){ - /* now deprecated *****************/ - case OV_ECTL_RATEMANAGE_GET: - { + case OV_ECTL_RATEMANAGE_GET: + { struct ovectl_ratemanage_arg *ai= (struct ovectl_ratemanage_arg *)arg; @@ -180280,12 +168195,11 @@ int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ ai->bitrate_av_lo=hi->bitrate_av; ai->bitrate_av_hi=hi->bitrate_av; - } - return(0); + } + return(0); - /* now deprecated *****************/ - case OV_ECTL_RATEMANAGE_SET: - { + case OV_ECTL_RATEMANAGE_SET: + { struct ovectl_ratemanage_arg *ai= (struct ovectl_ratemanage_arg *)arg; if(ai==NULL){ @@ -180295,12 +168209,11 @@ int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_AVG,arg); vorbis_encode_ctl(vi,OV_ECTL_RATEMANAGE_HARD,arg); } - } - return 0; + } + return 0; - /* now deprecated *****************/ - case OV_ECTL_RATEMANAGE_AVG: - { + case OV_ECTL_RATEMANAGE_AVG: + { struct ovectl_ratemanage_arg *ai= (struct ovectl_ratemanage_arg *)arg; if(ai==NULL){ @@ -180308,11 +168221,10 @@ int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ }else{ hi->bitrate_av=(ai->bitrate_av_lo+ai->bitrate_av_hi)*.5; } - } - return(0); - /* now deprecated *****************/ - case OV_ECTL_RATEMANAGE_HARD: - { + } + return(0); + case OV_ECTL_RATEMANAGE_HARD: + { struct ovectl_ratemanage_arg *ai= (struct ovectl_ratemanage_arg *)arg; if(ai==NULL){ @@ -180322,16 +168234,15 @@ int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ hi->bitrate_min=ai->bitrate_hard_min; hi->bitrate_max=ai->bitrate_hard_max; hi->bitrate_reservoir=ai->bitrate_hard_window* - (hi->bitrate_max+hi->bitrate_min)*.5; + (hi->bitrate_max+hi->bitrate_min)*.5; } if(hi->bitrate_reservoir<128.) hi->bitrate_reservoir=128.; - } - return(0); + } + return(0); - /* replacement ratemanage interface */ - case OV_ECTL_RATEMANAGE2_GET: - { + case OV_ECTL_RATEMANAGE2_GET: + { struct ovectl_ratemanage2_arg *ai= (struct ovectl_ratemanage2_arg *)arg; if(ai==NULL)return OV_EINVAL; @@ -180343,42 +168254,41 @@ int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ ai->bitrate_average_damping=hi->bitrate_av_damp; ai->bitrate_limit_reservoir_bits=hi->bitrate_reservoir; ai->bitrate_limit_reservoir_bias=hi->bitrate_reservoir_bias; - } - return (0); - case OV_ECTL_RATEMANAGE2_SET: - { + } + return (0); + case OV_ECTL_RATEMANAGE2_SET: + { struct ovectl_ratemanage2_arg *ai= (struct ovectl_ratemanage2_arg *)arg; if(ai==NULL){ hi->managed=0; }else{ - /* sanity check; only catch invariant violations */ if(ai->bitrate_limit_min_kbps>0 && - ai->bitrate_average_kbps>0 && - ai->bitrate_limit_min_kbps>ai->bitrate_average_kbps) - return OV_EINVAL; + ai->bitrate_average_kbps>0 && + ai->bitrate_limit_min_kbps>ai->bitrate_average_kbps) + return OV_EINVAL; if(ai->bitrate_limit_max_kbps>0 && - ai->bitrate_average_kbps>0 && - ai->bitrate_limit_max_kbpsbitrate_average_kbps) - return OV_EINVAL; + ai->bitrate_average_kbps>0 && + ai->bitrate_limit_max_kbpsbitrate_average_kbps) + return OV_EINVAL; if(ai->bitrate_limit_min_kbps>0 && - ai->bitrate_limit_max_kbps>0 && - ai->bitrate_limit_min_kbps>ai->bitrate_limit_max_kbps) - return OV_EINVAL; + ai->bitrate_limit_max_kbps>0 && + ai->bitrate_limit_min_kbps>ai->bitrate_limit_max_kbps) + return OV_EINVAL; if(ai->bitrate_average_damping <= 0.) - return OV_EINVAL; + return OV_EINVAL; if(ai->bitrate_limit_reservoir_bits < 0) - return OV_EINVAL; + return OV_EINVAL; if(ai->bitrate_limit_reservoir_bias < 0.) - return OV_EINVAL; + return OV_EINVAL; if(ai->bitrate_limit_reservoir_bias > 1.) - return OV_EINVAL; + return OV_EINVAL; hi->managed=ai->management_active; hi->bitrate_min=ai->bitrate_limit_min_kbps * 1000; @@ -180388,42 +168298,42 @@ int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ hi->bitrate_reservoir=ai->bitrate_limit_reservoir_bits; hi->bitrate_reservoir_bias=ai->bitrate_limit_reservoir_bias; } - } - return 0; + } + return 0; - case OV_ECTL_LOWPASS_GET: - { + case OV_ECTL_LOWPASS_GET: + { double *farg=(double *)arg; *farg=hi->lowpass_kHz; - } - return(0); - case OV_ECTL_LOWPASS_SET: - { + } + return(0); + case OV_ECTL_LOWPASS_SET: + { double *farg=(double *)arg; hi->lowpass_kHz=*farg; if(hi->lowpass_kHz<2.)hi->lowpass_kHz=2.; if(hi->lowpass_kHz>99.)hi->lowpass_kHz=99.; - } - return(0); - case OV_ECTL_IBLOCK_GET: - { + } + return(0); + case OV_ECTL_IBLOCK_GET: + { double *farg=(double *)arg; *farg=hi->impulse_noisetune; - } - return(0); - case OV_ECTL_IBLOCK_SET: - { + } + return(0); + case OV_ECTL_IBLOCK_SET: + { double *farg=(double *)arg; hi->impulse_noisetune=*farg; if(hi->impulse_noisetune>0.)hi->impulse_noisetune=0.; if(hi->impulse_noisetune<-15.)hi->impulse_noisetune=-15.; - } - return(0); - } + } + return(0); + } - return(OV_EIMPL); + return(OV_EIMPL); } return(OV_EINVAL); } @@ -180450,114 +168360,59 @@ int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg){ #include #include -/* A 'chained bitstream' is a Vorbis bitstream that contains more than - one logical bitstream arranged end to end (the only form of Ogg - multiplexing allowed in a Vorbis bitstream; grouping [parallel - multiplexing] is not allowed in Vorbis) */ - -/* A Vorbis file can be played beginning to end (streamed) without - worrying ahead of time about chaining (see decoder_example.c). If - we have the whole file, however, and want random access - (seeking/scrubbing) or desire to know the total length/time of a - file, we need to account for the possibility of chaining. */ - -/* We can handle things a number of ways; we can determine the entire - bitstream structure right off the bat, or find pieces on demand. - This example determines and caches structure for the entire - bitstream, but builds a virtual decoder on the fly when moving - between links in the chain. */ - -/* There are also different ways to implement seeking. Enough - information exists in an Ogg bitstream to seek to - sample-granularity positions in the output. Or, one can seek by - picking some portion of the stream roughly in the desired area if - we only want coarse navigation through the stream. */ - -/************************************************************************* - * Many, many internal helpers. The intention is not to be confusing; - * rampant duplication and monolithic function implementation would be - * harder to understand anyway. The high level functions are last. Begin - * grokking near the end of the file */ - -/* read a little more data from the file/pipe into the ogg_sync framer -*/ #define CHUNKSIZE 8500 /* a shade over 8k; anyone using pages well - over 8k gets what they deserve */ + over 8k gets what they deserve */ static long _get_data(OggVorbis_File *vf){ errno=0; if(vf->datasource){ - char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE); - long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource); - if(bytes>0)ogg_sync_wrote(&vf->oy,bytes); - if(bytes==0 && errno)return(-1); - return(bytes); + char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE); + long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource); + if(bytes>0)ogg_sync_wrote(&vf->oy,bytes); + if(bytes==0 && errno)return(-1); + return(bytes); }else - return(0); + return(0); } -/* save a tiny smidge of verbosity to make the code more readable */ static void _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){ if(vf->datasource){ - (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET); - vf->offset=offset; - ogg_sync_reset(&vf->oy); + (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET); + vf->offset=offset; + ogg_sync_reset(&vf->oy); }else{ - /* shouldn't happen unless someone writes a broken callback */ - return; + return; } } -/* The read/seek functions track absolute position within the stream */ - -/* from the head of the stream, get the next page. boundary specifies - if the function is allowed to fetch more data from the stream (and - how much) or only use internally buffered data. - - boundary: -1) unbounded search - 0) read no additional data; use cached only - n) search for a new page beginning for n bytes - - return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD) - n) found a page at absolute offset n */ - static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og, ogg_int64_t boundary){ if(boundary>0)boundary+=vf->offset; while(1){ - long more; + long more; - if(boundary>0 && vf->offset>=boundary)return(OV_FALSE); - more=ogg_sync_pageseek(&vf->oy,og); + if(boundary>0 && vf->offset>=boundary)return(OV_FALSE); + more=ogg_sync_pageseek(&vf->oy,og); - if(more<0){ - /* skipped n bytes */ - vf->offset-=more; - }else{ - if(more==0){ - /* send more paramedics */ + if(more<0){ + vf->offset-=more; + }else{ + if(more==0){ if(!boundary)return(OV_FALSE); { long ret=_get_data(vf); if(ret==0)return(OV_EOF); if(ret<0)return(OV_EREAD); } - }else{ - /* got a page. Return the offset at the page beginning, - advance the internal offset past the page end */ + }else{ ogg_int64_t ret=vf->offset; vf->offset+=more; return(ret); - } - } + } + } } } -/* find the latest page beginning before the current stream cursor - position. Much dirtier than the above as Ogg doesn't have any - backward search linkage. no 'readp' as it will certainly have to - read. */ -/* returns offset or OV_EREAD, OV_FAULT */ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){ ogg_int64_t begin=vf->offset; ogg_int64_t end=begin; @@ -180565,66 +168420,58 @@ static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){ ogg_int64_t offset=-1; while(offset==-1){ - begin-=CHUNKSIZE; - if(begin<0) - begin=0; - _seek_helper(vf,begin); - while(vf->offsetoffset); - if(ret==OV_EREAD)return(OV_EREAD); - if(ret<0){ + begin-=CHUNKSIZE; + if(begin<0) + begin=0; + _seek_helper(vf,begin); + while(vf->offsetoffset); + if(ret==OV_EREAD)return(OV_EREAD); + if(ret<0){ break; - }else{ + }else{ offset=ret; - } - } + } + } } - /* we have the offset. Actually snork and hold the page now */ _seek_helper(vf,offset); ret=_get_next_page(vf,og,CHUNKSIZE); if(ret<0) - /* this shouldn't be possible */ - return(OV_EFAULT); + return(OV_EFAULT); return(offset); } -/* finds each bitstream link one at a time using a bisection search - (has to begin by knowing the offset of the lb's initial page). - Recurses for each link so it can alloc the link storage after - finding them all, then unroll and fill the cache at the same time */ static int _bisect_forward_serialno(OggVorbis_File *vf, - ogg_int64_t begin, - ogg_int64_t searched, - ogg_int64_t end, - long currentno, - long m){ + ogg_int64_t begin, + ogg_int64_t searched, + ogg_int64_t end, + long currentno, + long m){ ogg_int64_t endsearched=end; ogg_int64_t next=end; ogg_page og; ogg_int64_t ret; - /* the below guards against garbage seperating the last and - first pages of two links. */ while(searched=0)next=ret; - }else{ - searched=ret+og.header_len+og.body_len; - } + _seek_helper(vf,bisect); + ret=_get_next_page(vf,&og,-1); + if(ret==OV_EREAD)return(OV_EREAD); + if(ret<0 || ogg_page_serialno(&og)!=currentno){ + endsearched=bisect; + if(ret>=0)next=ret; + }else{ + searched=ret+og.header_len+og.body_len; + } } _seek_helper(vf,next); @@ -180632,14 +168479,14 @@ static int _bisect_forward_serialno(OggVorbis_File *vf, if(ret==OV_EREAD)return(OV_EREAD); if(searched>=end || ret<0){ - vf->links=m+1; - vf->offsets=(ogg_int64_t*)_ogg_malloc((vf->links+1)*sizeof(*vf->offsets)); - vf->serialnos=(long*)_ogg_malloc(vf->links*sizeof(*vf->serialnos)); - vf->offsets[m+1]=searched; + vf->links=m+1; + vf->offsets=(ogg_int64_t*)_ogg_malloc((vf->links+1)*sizeof(*vf->offsets)); + vf->serialnos=(long*)_ogg_malloc(vf->links*sizeof(*vf->serialnos)); + vf->offsets[m+1]=searched; }else{ - ret=_bisect_forward_serialno(vf,next,vf->offset, + ret=_bisect_forward_serialno(vf,next,vf->offset, end,ogg_page_serialno(&og),m+1); - if(ret==OV_EREAD)return(OV_EREAD); + if(ret==OV_EREAD)return(OV_EREAD); } vf->offsets[m]=begin; @@ -180647,8 +168494,6 @@ static int _bisect_forward_serialno(OggVorbis_File *vf, return(0); } -/* uses the local ogg_stream storage in vf; this is important for - non-streaming input sources */ static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc, long *serialno,ogg_page *og_ptr){ ogg_page og; @@ -180656,42 +168501,39 @@ static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc, int i,ret; if(!og_ptr){ - ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE); - if(llret==OV_EREAD)return(OV_EREAD); - if(llret<0)return OV_ENOTVORBIS; - og_ptr=&og; + ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE); + if(llret==OV_EREAD)return(OV_EREAD); + if(llret<0)return OV_ENOTVORBIS; + og_ptr=&og; } ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr)); if(serialno)*serialno=vf->os.serialno; vf->ready_state=STREAMSET; - /* extract the initial header from the first page and verify that the - Ogg bitstream is in fact Vorbis data */ - vorbis_info_init(vi); vorbis_comment_init(vc); i=0; while(i<3){ - ogg_stream_pagein(&vf->os,og_ptr); - while(i<3){ - int result=ogg_stream_packetout(&vf->os,&op); - if(result==0)break; - if(result==-1){ + ogg_stream_pagein(&vf->os,og_ptr); + while(i<3){ + int result=ogg_stream_packetout(&vf->os,&op); + if(result==0)break; + if(result==-1){ ret=OV_EBADHEADER; goto bail_header; - } - if((ret=vorbis_synthesis_headerin(vi,vc,&op))){ + } + if((ret=vorbis_synthesis_headerin(vi,vc,&op))){ goto bail_header; - } - i++; - } - if(i<3) - if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){ + } + i++; + } + if(i<3) + if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){ ret=OV_EBADHEADER; goto bail_header; - } + } } return 0; @@ -180703,15 +168545,6 @@ static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc, return ret; } -/* last step of the OggVorbis_File initialization; get all the - vorbis_info structs and PCM positions. Only called by the seekable - initialization (local stream storage is hacked slightly; pay - attention to how that's done) */ - -/* this is void and does not propogate errors up because we want to be - able to open and use damaged bitstreams as well as we can. Just - watch out for missing information for links in the OggVorbis_File - struct */ static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){ ogg_page og; int i; @@ -180723,79 +168556,65 @@ static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){ vf->pcmlengths=(ogg_int64_t*) _ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths)); for(i=0;ilinks;i++){ - if(i==0){ - /* we already grabbed the initial header earlier. Just set the offset */ - vf->dataoffsets[i]=dataoffset; - _seek_helper(vf,dataoffset); + if(i==0){ + vf->dataoffsets[i]=dataoffset; + _seek_helper(vf,dataoffset); - }else{ + }else{ - /* seek to the location of the initial header */ - - _seek_helper(vf,vf->offsets[i]); - if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){ - vf->dataoffsets[i]=-1; - }else{ + _seek_helper(vf,vf->offsets[i]); + if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){ + vf->dataoffsets[i]=-1; + }else{ vf->dataoffsets[i]=vf->offset; - } - } + } + } - /* fetch beginning PCM offset */ + if(vf->dataoffsets[i]!=-1){ + ogg_int64_t accumulated=0; + long lastblock=-1; + int result; - if(vf->dataoffsets[i]!=-1){ - ogg_int64_t accumulated=0; - long lastblock=-1; - int result; + ogg_stream_reset_serialno(&vf->os,vf->serialnos[i]); - ogg_stream_reset_serialno(&vf->os,vf->serialnos[i]); - - while(1){ + while(1){ ogg_packet op; ret=_get_next_page(vf,&og,-1); if(ret<0) - /* this should not be possible unless the file is - truncated/mangled */ break; if(ogg_page_serialno(&og)!=vf->serialnos[i]) break; - /* count blocksizes of all frames in the page */ ogg_stream_pagein(&vf->os,&og); while((result=ogg_stream_packetout(&vf->os,&op))){ if(result>0){ /* ignore holes */ - long thisblock=vorbis_packet_blocksize(vf->vi+i,&op); - if(lastblock!=-1) - accumulated+=(lastblock+thisblock)>>2; - lastblock=thisblock; + long thisblock=vorbis_packet_blocksize(vf->vi+i,&op); + if(lastblock!=-1) + accumulated+=(lastblock+thisblock)>>2; + lastblock=thisblock; } } if(ogg_page_granulepos(&og)!=-1){ - /* pcm offset of last packet on the first audio page */ accumulated= ogg_page_granulepos(&og)-accumulated; break; } - } + } - /* less than zero? This is a stream with samples trimmed off - the beginning, a normal occurrence; set the offset to zero */ - if(accumulated<0)accumulated=0; + if(accumulated<0)accumulated=0; - vf->pcmlengths[i*2]=accumulated; - } + vf->pcmlengths[i*2]=accumulated; + } - /* get the PCM length of this link. To do this, - get the last page of the stream */ - { - ogg_int64_t end=vf->offsets[i+1]; - _seek_helper(vf,end); + { + ogg_int64_t end=vf->offsets[i+1]; + _seek_helper(vf,end); - while(1){ + while(1){ ret=_get_prev_page(vf,&og); if(ret<0){ - /* this should not be possible */ vorbis_info_clear(vf->vi+i); vorbis_comment_clear(vf->vc+i); break; @@ -180805,8 +168624,8 @@ static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){ break; } vf->offset=ret; - } - } + } + } } } @@ -180814,11 +168633,11 @@ static int _make_decode_ready(OggVorbis_File *vf){ if(vf->ready_state>STREAMSET)return 0; if(vf->ready_stateseekable){ - if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link)) - return OV_EBADLINK; + if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link)) + return OV_EBADLINK; }else{ - if(vorbis_synthesis_init(&vf->vd,vf->vi)) - return OV_EBADLINK; + if(vorbis_synthesis_init(&vf->vd,vf->vi)) + return OV_EBADLINK; } vorbis_block_init(&vf->vd,&vf->vb); vf->ready_state=INITSET; @@ -180832,194 +168651,132 @@ static int _open_seekable2(OggVorbis_File *vf){ ogg_int64_t dataoffset=vf->offset, end; ogg_page og; - /* we're partially open and have a first link header state in - storage in vf */ - /* we can seek, so set out learning all about this file */ (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END); vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource); - /* We get the offset for the last page of the physical bitstream. - Most OggVorbis files will contain a single logical bitstream */ end=_get_prev_page(vf,&og); if(end<0)return(end); - /* more than one logical bitstream? */ if(ogg_page_serialno(&og)!=serialno){ - /* Chained bitstream. Bisect-search each logical bitstream - section. Do so based on serial number only */ - if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return(OV_EREAD); + if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return(OV_EREAD); }else{ - /* Only one logical bitstream */ - if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return(OV_EREAD); + if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return(OV_EREAD); } - /* the initial header memory is referenced by vf after; don't free it */ _prefetch_all_headers(vf,dataoffset); return(ov_raw_seek(vf,0)); } -/* clear out the current logical bitstream decoder */ static void _decode_clear(OggVorbis_File *vf){ vorbis_dsp_clear(&vf->vd); vorbis_block_clear(&vf->vb); vf->ready_state=OPENED; } -/* fetch and process a packet. Handles the case where we're at a - bitstream boundary and dumps the decoding machine. If the decoding - machine is unloaded, it loads it. It also keeps pcm_offset up to - date (seek and read both use this. seek uses a special hack with - readp). - - return: <0) error, OV_HOLE (lost packet) or OV_EOF - 0) need more data (only if readp==0) - 1) got a packet -*/ - static int _fetch_and_process_packet(OggVorbis_File *vf, - ogg_packet *op_in, - int readp, - int spanp){ + ogg_packet *op_in, + int readp, + int spanp){ ogg_page og; - /* handle one packet. Try to fetch it from current stream state */ - /* extract packets from page */ while(1){ - /* process a packet if we can. If the machine isn't loaded, - neither is a page */ - if(vf->ready_state==INITSET){ - while(1) { - ogg_packet op; - ogg_packet *op_ptr=(op_in?op_in:&op); + if(vf->ready_state==INITSET){ + while(1) { + ogg_packet op; + ogg_packet *op_ptr=(op_in?op_in:&op); int result=ogg_stream_packetout(&vf->os,op_ptr); ogg_int64_t granulepos; op_in=NULL; if(result==-1)return(OV_HOLE); /* hole in the data. */ if(result>0){ - /* got a packet. process it */ granulepos=op_ptr->granulepos; if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy - header handling. The - header packets aren't - audio, so if/when we - submit them, - vorbis_synthesis will - reject them */ + header handling. The + header packets aren't + audio, so if/when we + submit them, + vorbis_synthesis will + reject them */ - /* suck in the synthesis data and track bitrate */ - { - int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL); - /* for proper use of libvorbis within libvorbisfile, - oldsamples will always be zero. */ - if(oldsamples)return(OV_EFAULT); + { + int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL); + if(oldsamples)return(OV_EFAULT); - vorbis_synthesis_blockin(&vf->vd,&vf->vb); - vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples; - vf->bittrack+=op_ptr->bytes*8; - } + vorbis_synthesis_blockin(&vf->vd,&vf->vb); + vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples; + vf->bittrack+=op_ptr->bytes*8; + } - /* update the pcm offset. */ - if(granulepos!=-1 && !op_ptr->e_o_s){ - int link=(vf->seekable?vf->current_link:0); - int i,samples; + if(granulepos!=-1 && !op_ptr->e_o_s){ + int link=(vf->seekable?vf->current_link:0); + int i,samples; - /* this packet has a pcm_offset on it (the last packet - completed on a page carries the offset) After processing - (above), we know the pcm position of the *last* sample - ready to be returned. Find the offset of the *first* - - As an aside, this trick is inaccurate if we begin - reading anew right at the last page; the end-of-stream - granulepos declares the last frame in the stream, and the - last packet of the last page may be a partial frame. - So, we need a previous granulepos from an in-sequence page - to have a reference point. Thus the !op_ptr->e_o_s clause - above */ - - if(vf->seekable && link>0) + if(vf->seekable && link>0) granulepos-=vf->pcmlengths[link*2]; - if(granulepos<0)granulepos=0; /* actually, this - shouldn't be possible - here unless the stream - is very broken */ + if(granulepos<0)granulepos=0; /* actually, this + shouldn't be possible + here unless the stream + is very broken */ - samples=vorbis_synthesis_pcmout(&vf->vd,NULL); + samples=vorbis_synthesis_pcmout(&vf->vd,NULL); - granulepos-=samples; - for(i=0;ipcmlengths[i*2+1]; - vf->pcm_offset=granulepos; - } - return(1); + granulepos-=samples; + for(i=0;ipcmlengths[i*2+1]; + vf->pcm_offset=granulepos; + } + return(1); } } else break; - } - } + } + } - if(vf->ready_state>=OPENED){ - ogg_int64_t ret; - if(!readp)return(0); - if((ret=_get_next_page(vf,&og,-1))<0){ + if(vf->ready_state>=OPENED){ + ogg_int64_t ret; + if(!readp)return(0); + if((ret=_get_next_page(vf,&og,-1))<0){ return(OV_EOF); /* eof. leave unitialized */ - } + } - /* bitrate tracking; add the header's bytes here, the body bytes - are done by packet above */ - vf->bittrack+=og.header_len*8; + vf->bittrack+=og.header_len*8; - /* has our decoding just traversed a bitstream boundary? */ - if(vf->ready_state==INITSET){ + if(vf->ready_state==INITSET){ if(vf->current_serialno!=ogg_page_serialno(&og)){ if(!spanp) - return(OV_EOF); + return(OV_EOF); _decode_clear(vf); if(!vf->seekable){ - vorbis_info_clear(vf->vi); - vorbis_comment_clear(vf->vc); + vorbis_info_clear(vf->vi); + vorbis_comment_clear(vf->vc); + } + } } } - } - } - /* Do we need to load a new machine before submitting the page? */ - /* This is different in the seekable and non-seekable cases. + if(vf->ready_state!=INITSET){ + int link; - In the seekable case, we already have all the header - information loaded and cached; we just initialize the machine - with it and continue on our merry way. - - In the non-seekable (streaming) case, we'll only be at a - boundary if we just left the previous logical bitstream and - we're now nominally at the header of the next bitstream - */ - - if(vf->ready_state!=INITSET){ - int link; - - if(vf->ready_stateready_stateseekable){ vf->current_serialno=ogg_page_serialno(&og); - /* match the serialno to bitstream section. We use this rather than - offset positions to avoid problems near logical bitstream - boundaries */ for(link=0;linklinks;link++) - if(vf->serialnos[link]==vf->current_serialno)break; + if(vf->serialnos[link]==vf->current_serialno)break; if(link==vf->links)return(OV_EBADLINK); /* sign of a bogus - stream. error out, - leave machine - uninitialized */ + stream. error out, + leave machine + uninitialized */ vf->current_link=link; @@ -181027,34 +168784,30 @@ static int _fetch_and_process_packet(OggVorbis_File *vf, vf->ready_state=STREAMSET; }else{ - /* we're streaming */ - /* fetch the three header packets, build the info struct */ int ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og); if(ret)return(ret); vf->current_link++; link=0; } - } + } - { + { int ret=_make_decode_ready(vf); if(ret<0)return ret; - } - } - ogg_stream_pagein(&vf->os,&og); + } + } + ogg_stream_pagein(&vf->os,&og); } } -/* if, eg, 64 bit stdio is configured by default, this will build with - fseek64 */ static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){ if(f==NULL)return(-1); return fseek(f,off,whence); } static int _ov_open1(void *f,OggVorbis_File *vf,char *initial, - long ibytes, ov_callbacks callbacks){ + long ibytes, ov_callbacks callbacks){ int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1); int ret; @@ -181062,35 +168815,26 @@ static int _ov_open1(void *f,OggVorbis_File *vf,char *initial, vf->datasource=f; vf->callbacks = callbacks; - /* init the framing state */ ogg_sync_init(&vf->oy); - /* perhaps some data was previously read into a buffer for testing - against other stream types. Allow initialization from this - previously read data (as we may be reading from a non-seekable - stream) */ if(initial){ - char *buffer=ogg_sync_buffer(&vf->oy,ibytes); - memcpy(buffer,initial,ibytes); - ogg_sync_wrote(&vf->oy,ibytes); + char *buffer=ogg_sync_buffer(&vf->oy,ibytes); + memcpy(buffer,initial,ibytes); + ogg_sync_wrote(&vf->oy,ibytes); } - /* can we seek? Stevens suggests the seek test was portable */ if(offsettest!=-1)vf->seekable=1; - /* No seeking yet; Set up a 'single' (current) logical bitstream - entry for partial open */ vf->links=1; vf->vi=(vorbis_info*) _ogg_calloc(vf->links,sizeof(*vf->vi)); vf->vc=(vorbis_comment*) _ogg_calloc(vf->links,sizeof(*vf->vc)); ogg_stream_init(&vf->os,-1); /* fill in the serialno later */ - /* Try to fetch the headers, maintaining all the storage */ if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){ - vf->datasource=NULL; - ov_clear(vf); + vf->datasource=NULL; + ov_clear(vf); }else - vf->ready_state=PARTOPEN; + vf->ready_state=PARTOPEN; return(ret); } @@ -181098,41 +168842,40 @@ static int _ov_open2(OggVorbis_File *vf){ if(vf->ready_state != PARTOPEN) return OV_EINVAL; vf->ready_state=OPENED; if(vf->seekable){ - int ret=_open_seekable2(vf); - if(ret){ - vf->datasource=NULL; - ov_clear(vf); - } - return(ret); + int ret=_open_seekable2(vf); + if(ret){ + vf->datasource=NULL; + ov_clear(vf); + } + return(ret); }else - vf->ready_state=STREAMSET; + vf->ready_state=STREAMSET; return 0; } -/* clear out the OggVorbis_File struct */ int ov_clear(OggVorbis_File *vf){ if(vf){ - vorbis_block_clear(&vf->vb); - vorbis_dsp_clear(&vf->vd); - ogg_stream_clear(&vf->os); + vorbis_block_clear(&vf->vb); + vorbis_dsp_clear(&vf->vd); + ogg_stream_clear(&vf->os); - if(vf->vi && vf->links){ - int i; - for(i=0;ilinks;i++){ + if(vf->vi && vf->links){ + int i; + for(i=0;ilinks;i++){ vorbis_info_clear(vf->vi+i); vorbis_comment_clear(vf->vc+i); - } - _ogg_free(vf->vi); - _ogg_free(vf->vc); - } - if(vf->dataoffsets)_ogg_free(vf->dataoffsets); - if(vf->pcmlengths)_ogg_free(vf->pcmlengths); - if(vf->serialnos)_ogg_free(vf->serialnos); - if(vf->offsets)_ogg_free(vf->offsets); - ogg_sync_clear(&vf->oy); - if(vf->datasource)(vf->callbacks.close_func)(vf->datasource); - memset(vf,0,sizeof(*vf)); + } + _ogg_free(vf->vi); + _ogg_free(vf->vc); + } + if(vf->dataoffsets)_ogg_free(vf->dataoffsets); + if(vf->pcmlengths)_ogg_free(vf->pcmlengths); + if(vf->serialnos)_ogg_free(vf->serialnos); + if(vf->offsets)_ogg_free(vf->offsets); + ogg_sync_clear(&vf->oy); + if(vf->datasource)(vf->callbacks.close_func)(vf->datasource); + memset(vf,0,sizeof(*vf)); } #ifdef DEBUG_LEAKS _VDBG_dump(); @@ -181140,16 +168883,8 @@ int ov_clear(OggVorbis_File *vf){ return(0); } -/* inspects the OggVorbis file and finds/documents all the logical - bitstreams contained in it. Tries to be tolerant of logical - bitstream sections that are truncated/woogie. - - return: -1) error - 0) OK -*/ - int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes, - ov_callbacks callbacks){ + ov_callbacks callbacks){ int ret=_ov_open1(f,vf,initial,ibytes,callbacks); if(ret)return ret; return _ov_open2(vf); @@ -181157,34 +168892,31 @@ int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes, int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){ ov_callbacks callbacks = { - (size_t (*)(void *, size_t, size_t, void *)) fread, - (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, - (int (*)(void *)) fclose, - (long (*)(void *)) ftell + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, + (int (*)(void *)) fclose, + (long (*)(void *)) ftell }; return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks); } -/* cheap hack for game usage where downsampling is desirable; there's - no need for SRC as we can just do it cheaply in libvorbis. */ - int ov_halfrate(OggVorbis_File *vf,int flag){ int i; if(vf->vi==NULL)return OV_EINVAL; if(!vf->seekable)return OV_EINVAL; if(vf->ready_state>=STREAMSET) - _decode_clear(vf); /* clear out stream state; later on libvorbis - will be able to swap this on the fly, but - for now dumping the decode machine is needed - to reinit the MDCT lookups. 1.1 libvorbis - is planned to be able to switch on the fly */ + _decode_clear(vf); /* clear out stream state; later on libvorbis + will be able to swap this on the fly, but + for now dumping the decode machine is needed + to reinit the MDCT lookups. 1.1 libvorbis + is planned to be able to switch on the fly */ for(i=0;ilinks;i++){ - if(vorbis_synthesis_halfrate(vf->vi+i,flag)){ - ov_halfrate(vf,0); - return OV_EINVAL; - } + if(vorbis_synthesis_halfrate(vf->vi+i,flag)){ + ov_halfrate(vf,0); + return OV_EINVAL; + } } return 0; } @@ -181194,23 +168926,18 @@ int ov_halfrate_p(OggVorbis_File *vf){ return vorbis_synthesis_halfrate_p(vf->vi); } -/* Only partially open the vorbis file; test for Vorbisness, and load - the headers for the first chain. Do not seek (although test for - seekability). Use ov_test_open to finish opening the file, else - ov_clear to close/free it. Same return codes as open. */ - int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes, - ov_callbacks callbacks) + ov_callbacks callbacks) { return _ov_open1(f,vf,initial,ibytes,callbacks); } int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){ ov_callbacks callbacks = { - (size_t (*)(void *, size_t, size_t, void *)) fread, - (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, - (int (*)(void *)) fclose, - (long (*)(void *)) ftell + (size_t (*)(void *, size_t, size_t, void *)) fread, + (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, + (int (*)(void *)) fclose, + (long (*)(void *)) ftell }; return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks); @@ -181221,67 +168948,46 @@ int ov_test_open(OggVorbis_File *vf){ return _ov_open2(vf); } -/* How many logical bitstreams in this physical bitstream? */ long ov_streams(OggVorbis_File *vf){ return vf->links; } -/* Is the FILE * associated with vf seekable? */ long ov_seekable(OggVorbis_File *vf){ return vf->seekable; } -/* returns the bitrate for a given logical bitstream or the entire - physical bitstream. If the file is open for random access, it will - find the *actual* average bitrate. If the file is streaming, it - returns the nominal bitrate (if set) else the average of the - upper/lower bounds (if set) else -1 (unset). - - If you want the actual bitrate field settings, get them from the - vorbis_info structs */ - long ov_bitrate(OggVorbis_File *vf,int i){ if(vf->ready_state=vf->links)return(OV_EINVAL); if(!vf->seekable && i!=0)return(ov_bitrate(vf,0)); if(i<0){ - ogg_int64_t bits=0; - int i; - float br; - for(i=0;ilinks;i++) - bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8; - /* This once read: return(rint(bits/ov_time_total(vf,-1))); - * gcc 3.x on x86 miscompiled this at optimisation level 2 and above, - * so this is slightly transformed to make it work. - */ - br = bits/ov_time_total(vf,-1); - return(rint(br)); + ogg_int64_t bits=0; + int i; + float br; + for(i=0;ilinks;i++) + bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8; + br = bits/ov_time_total(vf,-1); + return(rint(br)); }else{ - if(vf->seekable){ - /* return the actual bitrate */ - return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i))); - }else{ - /* return nominal if set */ - if(vf->vi[i].bitrate_nominal>0){ + if(vf->seekable){ + return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i))); + }else{ + if(vf->vi[i].bitrate_nominal>0){ return vf->vi[i].bitrate_nominal; - }else{ + }else{ if(vf->vi[i].bitrate_upper>0){ if(vf->vi[i].bitrate_lower>0){ - return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2; + return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2; }else{ - return vf->vi[i].bitrate_upper; + return vf->vi[i].bitrate_upper; } } return(OV_FALSE); - } - } + } + } } } -/* returns the actual bitrate since last call. returns -1 if no - additional data to offer since last call (or at beginning of stream), - EINVAL if stream is only partially open -*/ long ov_bitrate_instant(OggVorbis_File *vf){ int link=(vf->seekable?vf->current_link:0); long ret; @@ -181293,205 +168999,160 @@ long ov_bitrate_instant(OggVorbis_File *vf){ return(ret); } -/* Guess */ long ov_serialnumber(OggVorbis_File *vf,int i){ if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1)); if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1)); if(i<0){ - return(vf->current_serialno); + return(vf->current_serialno); }else{ - return(vf->serialnos[i]); + return(vf->serialnos[i]); } } -/* returns: total raw (compressed) length of content if i==-1 - raw (compressed) length of that logical bitstream for i==0 to n - OV_EINVAL if the stream is not seekable (we can't know the length) - or if stream is only partially open -*/ ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){ if(vf->ready_stateseekable || i>=vf->links)return(OV_EINVAL); if(i<0){ - ogg_int64_t acc=0; - int i; - for(i=0;ilinks;i++) - acc+=ov_raw_total(vf,i); - return(acc); + ogg_int64_t acc=0; + int i; + for(i=0;ilinks;i++) + acc+=ov_raw_total(vf,i); + return(acc); }else{ - return(vf->offsets[i+1]-vf->offsets[i]); + return(vf->offsets[i+1]-vf->offsets[i]); } } -/* returns: total PCM length (samples) of content if i==-1 PCM length - (samples) of that logical bitstream for i==0 to n - OV_EINVAL if the stream is not seekable (we can't know the - length) or only partially open -*/ ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){ if(vf->ready_stateseekable || i>=vf->links)return(OV_EINVAL); if(i<0){ - ogg_int64_t acc=0; - int i; - for(i=0;ilinks;i++) - acc+=ov_pcm_total(vf,i); - return(acc); + ogg_int64_t acc=0; + int i; + for(i=0;ilinks;i++) + acc+=ov_pcm_total(vf,i); + return(acc); }else{ - return(vf->pcmlengths[i*2+1]); + return(vf->pcmlengths[i*2+1]); } } -/* returns: total seconds of content if i==-1 - seconds in that logical bitstream for i==0 to n - OV_EINVAL if the stream is not seekable (we can't know the - length) or only partially open -*/ double ov_time_total(OggVorbis_File *vf,int i){ if(vf->ready_stateseekable || i>=vf->links)return(OV_EINVAL); if(i<0){ - double acc=0; - int i; - for(i=0;ilinks;i++) - acc+=ov_time_total(vf,i); - return(acc); + double acc=0; + int i; + for(i=0;ilinks;i++) + acc+=ov_time_total(vf,i); + return(acc); }else{ - return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate); + return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate); } } -/* seek to an offset relative to the *compressed* data. This also - scans packets to update the PCM cursor. It will cross a logical - bitstream boundary, but only if it can't get any packets out of the - tail of the bitstream we seek to (so no surprises). - - returns zero on success, nonzero on failure */ - int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ ogg_stream_state work_os; if(vf->ready_stateseekable) - return(OV_ENOSEEK); /* don't dump machine if we can't seek */ + return(OV_ENOSEEK); /* don't dump machine if we can't seek */ if(pos<0 || pos>vf->end)return(OV_EINVAL); - /* don't yet clear out decoding machine (if it's initialized), in - the case we're in the same link. Restart the decode lapping, and - let _fetch_and_process_packet deal with a potential bitstream - boundary */ vf->pcm_offset=-1; ogg_stream_reset_serialno(&vf->os, - vf->current_serialno); /* must set serialno */ + vf->current_serialno); /* must set serialno */ vorbis_synthesis_restart(&vf->vd); _seek_helper(vf,pos); - /* we need to make sure the pcm_offset is set, but we don't want to - advance the raw cursor past good packets just to get to the first - with a granulepos. That's not equivalent behavior to beginning - decoding as immediately after the seek position as possible. - - So, a hack. We use two stream states; a local scratch state and - the shared vf->os stream state. We use the local state to - scan, and the shared state as a buffer for later decode. - - Unfortuantely, on the last page we still advance to last packet - because the granulepos on the last page is not necessarily on a - packet boundary, and we need to make sure the granpos is - correct. - */ - { - ogg_page og; - ogg_packet op; - int lastblock=0; - int accblock=0; - int thisblock; - int eosflag; + ogg_page og; + ogg_packet op; + int lastblock=0; + int accblock=0; + int thisblock; + int eosflag; - ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */ - ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE - return from not necessarily - starting from the beginning */ + ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */ + ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE + return from not necessarily + starting from the beginning */ - while(1){ - if(vf->ready_state>=STREAMSET){ - /* snarf/scan a packet if we can */ + while(1){ + if(vf->ready_state>=STREAMSET){ int result=ogg_stream_packetout(&work_os,&op); if(result>0){ if(vf->vi[vf->current_link].codec_setup){ - thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); - if(thisblock<0){ - ogg_stream_packetout(&vf->os,NULL); - thisblock=0; - }else{ + thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); + if(thisblock<0){ + ogg_stream_packetout(&vf->os,NULL); + thisblock=0; + }else{ - if(eosflag) - ogg_stream_packetout(&vf->os,NULL); - else + if(eosflag) + ogg_stream_packetout(&vf->os,NULL); + else if(lastblock)accblock+=(lastblock+thisblock)>>2; - } + } - if(op.granulepos!=-1){ - int i,link=vf->current_link; - ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2]; - if(granulepos<0)granulepos=0; + if(op.granulepos!=-1){ + int i,link=vf->current_link; + ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2]; + if(granulepos<0)granulepos=0; - for(i=0;ipcmlengths[i*2+1]; - vf->pcm_offset=granulepos-accblock; - break; - } - lastblock=thisblock; - continue; + vf->pcm_offset=granulepos-accblock; + break; + } + lastblock=thisblock; + continue; }else - ogg_stream_packetout(&vf->os,NULL); + ogg_stream_packetout(&vf->os,NULL); } - } + } - if(!lastblock){ + if(!lastblock){ if(_get_next_page(vf,&og,-1)<0){ vf->pcm_offset=ov_pcm_total(vf,-1); break; } - }else{ - /* huh? Bogus stream with packets but no granulepos */ + }else{ vf->pcm_offset=-1; break; - } + } - /* has our decoding just traversed a bitstream boundary? */ - if(vf->ready_state>=STREAMSET) + if(vf->ready_state>=STREAMSET) if(vf->current_serialno!=ogg_page_serialno(&og)){ _decode_clear(vf); /* clear out stream state */ ogg_stream_clear(&work_os); } - if(vf->ready_stateready_statecurrent_serialno=ogg_page_serialno(&og); for(link=0;linklinks;link++) if(vf->serialnos[link]==vf->current_serialno)break; if(link==vf->links)goto seek_error; /* sign of a bogus stream. - error out, leave - machine uninitialized */ + error out, leave + machine uninitialized */ vf->current_link=link; ogg_stream_reset_serialno(&vf->os,vf->current_serialno); ogg_stream_reset_serialno(&work_os,vf->current_serialno); vf->ready_state=STREAMSET; - } + } - ogg_stream_pagein(&vf->os,&og); - ogg_stream_pagein(&work_os,&og); - eosflag=ogg_page_eos(&og); - } + ogg_stream_pagein(&vf->os,&og); + ogg_stream_pagein(&work_os,&og); + eosflag=ogg_page_eos(&og); + } } ogg_stream_clear(&work_os); @@ -181500,19 +169161,12 @@ int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ return(0); seek_error: - /* dump the machine so we're in a known state */ vf->pcm_offset=-1; ogg_stream_clear(&work_os); _decode_clear(vf); return OV_EBADLINK; } -/* Page granularity seek (faster than sample granularity because we - don't do the last bit of decode to find a specific sample). - - Seek to the last [granule marked] page preceeding the specified pos - location, such that decoding past the returned point will quickly - arrive at the requested position. */ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){ int link=-1; ogg_int64_t result=0; @@ -181523,131 +169177,113 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){ if(pos<0 || pos>total)return(OV_EINVAL); - /* which bitstream section does this pcm offset occur in? */ for(link=vf->links-1;link>=0;link--){ - total-=vf->pcmlengths[link*2+1]; - if(pos>=total)break; + total-=vf->pcmlengths[link*2+1]; + if(pos>=total)break; } - /* search within the logical bitstream for the page with the highest - pcm_pos preceeding (or equal to) pos. There is a danger here; - missing pages or incorrect frame number information in the - bitstream could make our task impossible. Account for that (it - would be an error condition) */ - - /* new search algorithm by HB (Nicholas Vinen) */ { - ogg_int64_t end=vf->offsets[link+1]; - ogg_int64_t begin=vf->offsets[link]; - ogg_int64_t begintime = vf->pcmlengths[link*2]; - ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime; - ogg_int64_t target=pos-total+begintime; - ogg_int64_t best=begin; + ogg_int64_t end=vf->offsets[link+1]; + ogg_int64_t begin=vf->offsets[link]; + ogg_int64_t begintime = vf->pcmlengths[link*2]; + ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime; + ogg_int64_t target=pos-total+begintime; + ogg_int64_t best=begin; - ogg_page og; - while(beginoffset); if(result==OV_EREAD) goto seek_error; if(result<0){ if(bisect<=begin+1) - end=begin; /* found it */ + end=begin; /* found it */ else{ - if(bisect==0) goto seek_error; - bisect-=CHUNKSIZE; - if(bisect<=begin)bisect=begin+1; - _seek_helper(vf,bisect); + if(bisect==0) goto seek_error; + bisect-=CHUNKSIZE; + if(bisect<=begin)bisect=begin+1; + _seek_helper(vf,bisect); } }else{ ogg_int64_t granulepos=ogg_page_granulepos(&og); if(granulepos==-1)continue; if(granuleposoffset; /* raw offset of next page */ - begintime=granulepos; + best=result; /* raw offset of packet with granulepos */ + begin=vf->offset; /* raw offset of next page */ + begintime=granulepos; - if(target-begintime>44100)break; - bisect=begin; /* *not* begin + 1 */ + if(target-begintime>44100)break; + bisect=begin; /* *not* begin + 1 */ }else{ - if(bisect<=begin+1) - end=begin; /* found it */ - else{ - if(end==vf->offset){ /* we're pretty close - we'd be stuck in */ + if(bisect<=begin+1) + end=begin; /* found it */ + else{ + if(end==vf->offset){ /* we're pretty close - we'd be stuck in */ end=result; bisect-=CHUNKSIZE; /* an endless loop otherwise. */ if(bisect<=begin)bisect=begin+1; _seek_helper(vf,bisect); - }else{ + }else{ end=result; endtime=granulepos; break; - } - } + } + } + } + } } } - } - } - /* found our page. seek to it, update pcm offset. Easier case than - raw_seek, don't keep packets preceeding granulepos. */ - { - ogg_page og; - ogg_packet op; + { + ogg_page og; + ogg_packet op; - /* seek */ - _seek_helper(vf,best); - vf->pcm_offset=-1; + _seek_helper(vf,best); + vf->pcm_offset=-1; - if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* shouldn't happen */ + if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* shouldn't happen */ - if(link!=vf->current_link){ - /* Different link; dump entire decode machine */ + if(link!=vf->current_link){ _decode_clear(vf); vf->current_link=link; vf->current_serialno=ogg_page_serialno(&og); vf->ready_state=STREAMSET; - }else{ + }else{ vorbis_synthesis_restart(&vf->vd); - } + } - ogg_stream_reset_serialno(&vf->os,vf->current_serialno); - ogg_stream_pagein(&vf->os,&og); + ogg_stream_reset_serialno(&vf->os,vf->current_serialno); + ogg_stream_pagein(&vf->os,&og); - /* pull out all but last packet; the one with granulepos */ - while(1){ + while(1){ result=ogg_stream_packetpeek(&vf->os,&op); if(result==0){ - /* !!! the packet finishing this page originated on a - preceeding page. Keep fetching previous pages until we - get one with a granulepos or without the 'continued' flag - set. Then just use raw_seek for simplicity. */ _seek_helper(vf,best); while(1){ - result=_get_prev_page(vf,&og); - if(result<0) goto seek_error; - if(ogg_page_granulepos(&og)>-1 || - !ogg_page_continued(&og)){ - return ov_raw_seek(vf,result); - } - vf->offset=result; + result=_get_prev_page(vf,&og); + if(result<0) goto seek_error; + if(ogg_page_granulepos(&og)>-1 || + !ogg_page_continued(&og)){ + return ov_raw_seek(vf,result); + } + vf->offset=result; } } if(result<0){ @@ -181661,83 +169297,69 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){ break; }else result=ogg_stream_packetout(&vf->os,NULL); - } - } + } + } } - /* verify result */ if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){ - result=OV_EFAULT; - goto seek_error; + result=OV_EFAULT; + goto seek_error; } vf->bittrack=0.f; vf->samptrack=0.f; return(0); seek_error: - /* dump machine so we're in a known state */ vf->pcm_offset=-1; _decode_clear(vf); return (int)result; } -/* seek to a sample offset relative to the decompressed pcm stream - returns zero on success, nonzero on failure */ - int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){ int thisblock,lastblock=0; int ret=ov_pcm_seek_page(vf,pos); if(ret<0)return(ret); if((ret=_make_decode_ready(vf)))return ret; - /* discard leading packets we don't need for the lapping of the - position we want; don't decode them */ - while(1){ - ogg_packet op; - ogg_page og; + ogg_packet op; + ogg_page og; - int ret=ogg_stream_packetpeek(&vf->os,&op); - if(ret>0){ - thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); - if(thisblock<0){ + int ret=ogg_stream_packetpeek(&vf->os,&op); + if(ret>0){ + thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); + if(thisblock<0){ ogg_stream_packetout(&vf->os,NULL); continue; /* non audio packet */ - } - if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2; + } + if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2; - if(vf->pcm_offset+((thisblock+ + if(vf->pcm_offset+((thisblock+ vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break; - /* remove the packet from packet queue and track its granulepos */ - ogg_stream_packetout(&vf->os,NULL); - vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with - only tracking, no - pcm_decode */ - vorbis_synthesis_blockin(&vf->vd,&vf->vb); + ogg_stream_packetout(&vf->os,NULL); + vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with + only tracking, no + pcm_decode */ + vorbis_synthesis_blockin(&vf->vd,&vf->vb); - /* end of logical stream case is hard, especially with exact - length positioning. */ - - if(op.granulepos>-1){ + if(op.granulepos>-1){ int i; - /* always believe the stream markers */ vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2]; if(vf->pcm_offset<0)vf->pcm_offset=0; for(i=0;icurrent_link;i++) vf->pcm_offset+=vf->pcmlengths[i*2+1]; - } + } - lastblock=thisblock; + lastblock=thisblock; - }else{ - if(ret<0 && ret!=OV_HOLE)break; + }else{ + if(ret<0 && ret!=OV_HOLE)break; - /* suck in a new page */ - if(_get_next_page(vf,&og,-1)<0)break; - if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf); + if(_get_next_page(vf,&og,-1)<0)break; + if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf); - if(vf->ready_stateready_statecurrent_serialno=ogg_page_serialno(&og); @@ -181751,35 +169373,30 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){ ret=_make_decode_ready(vf); if(ret)return ret; lastblock=0; - } + } - ogg_stream_pagein(&vf->os,&og); - } + ogg_stream_pagein(&vf->os,&og); + } } vf->bittrack=0.f; vf->samptrack=0.f; - /* discard samples until we reach the desired position. Crossing a - logical bitstream boundary with abandon is OK. */ while(vf->pcm_offsetpcm_offset; - long samples=vorbis_synthesis_pcmout(&vf->vd,NULL); + ogg_int64_t target=pos-vf->pcm_offset; + long samples=vorbis_synthesis_pcmout(&vf->vd,NULL); - if(samples>target)samples=target; - vorbis_synthesis_read(&vf->vd,samples); - vf->pcm_offset+=samples; + if(samples>target)samples=target; + vorbis_synthesis_read(&vf->vd,samples); + vf->pcm_offset+=samples; - if(samplespcm_offset=ov_pcm_total(vf,-1); /* eof */ } return 0; } -/* seek to a playback time relative to the decompressed pcm stream - returns zero on success, nonzero on failure */ int ov_time_seek(OggVorbis_File *vf,double seconds){ - /* translate time to PCM position and call ov_pcm_seek */ int link=-1; ogg_int64_t pcm_total=ov_pcm_total(vf,-1); @@ -181789,24 +169406,19 @@ int ov_time_seek(OggVorbis_File *vf,double seconds){ if(!vf->seekable)return(OV_ENOSEEK); if(seconds<0 || seconds>time_total)return(OV_EINVAL); - /* which bitstream section does this time offset occur in? */ for(link=vf->links-1;link>=0;link--){ - pcm_total-=vf->pcmlengths[link*2+1]; - time_total-=ov_time_total(vf,link); - if(seconds>=time_total)break; + pcm_total-=vf->pcmlengths[link*2+1]; + time_total-=ov_time_total(vf,link); + if(seconds>=time_total)break; } - /* enough information to convert time offset to pcm offset */ { - ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate; - return(ov_pcm_seek(vf,target)); + ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate; + return(ov_pcm_seek(vf,target)); } } -/* page-granularity version of ov_time_seek - returns zero on success, nonzero on failure */ int ov_time_seek_page(OggVorbis_File *vf,double seconds){ - /* translate time to PCM position and call ov_pcm_seek */ int link=-1; ogg_int64_t pcm_total=ov_pcm_total(vf,-1); @@ -181816,34 +169428,28 @@ int ov_time_seek_page(OggVorbis_File *vf,double seconds){ if(!vf->seekable)return(OV_ENOSEEK); if(seconds<0 || seconds>time_total)return(OV_EINVAL); - /* which bitstream section does this time offset occur in? */ for(link=vf->links-1;link>=0;link--){ - pcm_total-=vf->pcmlengths[link*2+1]; - time_total-=ov_time_total(vf,link); - if(seconds>=time_total)break; + pcm_total-=vf->pcmlengths[link*2+1]; + time_total-=ov_time_total(vf,link); + if(seconds>=time_total)break; } - /* enough information to convert time offset to pcm offset */ { - ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate; - return(ov_pcm_seek_page(vf,target)); + ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate; + return(ov_pcm_seek_page(vf,target)); } } -/* tell the current stream offset cursor. Note that seek followed by - tell will likely not give the set offset due to caching */ ogg_int64_t ov_raw_tell(OggVorbis_File *vf){ if(vf->ready_stateoffset); } -/* return PCM offset (sample) of next PCM sample to be read */ ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){ if(vf->ready_statepcm_offset); } -/* return time offset (seconds) of next PCM sample to be read */ double ov_time_tell(OggVorbis_File *vf){ int link=0; ogg_int64_t pcm_total=0; @@ -181851,60 +169457,50 @@ double ov_time_tell(OggVorbis_File *vf){ if(vf->ready_stateseekable){ - pcm_total=ov_pcm_total(vf,-1); - time_total=ov_time_total(vf,-1); + pcm_total=ov_pcm_total(vf,-1); + time_total=ov_time_total(vf,-1); - /* which bitstream section does this time offset occur in? */ - for(link=vf->links-1;link>=0;link--){ - pcm_total-=vf->pcmlengths[link*2+1]; - time_total-=ov_time_total(vf,link); - if(vf->pcm_offset>=pcm_total)break; - } + for(link=vf->links-1;link>=0;link--){ + pcm_total-=vf->pcmlengths[link*2+1]; + time_total-=ov_time_total(vf,link); + if(vf->pcm_offset>=pcm_total)break; + } } return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate); } -/* link: -1) return the vorbis_info struct for the bitstream section - currently being decoded - 0-n) to request information for a specific bitstream section - - In the case of a non-seekable bitstream, any call returns the - current bitstream. NULL in the case that the machine is not - initialized */ - vorbis_info *ov_info(OggVorbis_File *vf,int link){ if(vf->seekable){ - if(link<0) - if(vf->ready_state>=STREAMSET) + if(link<0) + if(vf->ready_state>=STREAMSET) return vf->vi+vf->current_link; - else - return vf->vi; - else - if(link>=vf->links) + else + return vf->vi; + else + if(link>=vf->links) return NULL; - else + else return vf->vi+link; }else{ - return vf->vi; + return vf->vi; } } -/* grr, strong typing, grr, no templates/inheritence, grr */ vorbis_comment *ov_comment(OggVorbis_File *vf,int link){ if(vf->seekable){ - if(link<0) - if(vf->ready_state>=STREAMSET) + if(link<0) + if(vf->ready_state>=STREAMSET) return vf->vc+vf->current_link; - else + else return vf->vc; - else - if(link>=vf->links) + else + if(link>=vf->links) return NULL; - else + else return vf->vc+link; }else{ - return vf->vc; + return vf->vc; } } @@ -181915,39 +169511,8 @@ static int host_is_big_endian() { return 0; } -/* up to this point, everything could more or less hide the multiple - logical bitstream nature of chaining from the toplevel application - if the toplevel application didn't particularly care. However, at - the point that we actually read audio back, the multiple-section - nature must surface: Multiple bitstream sections do not necessarily - have to have the same number of channels or sampling rate. - - ov_read returns the sequential logical bitstream number currently - being decoded along with the PCM data in order that the toplevel - application can take action on channel/sample rate changes. This - number will be incremented even for streamed (non-seekable) streams - (for seekable streams, it represents the actual logical bitstream - index within the physical bitstream. Note that the accessor - functions above are aware of this dichotomy). - - input values: buffer) a buffer to hold packed PCM data for return - length) the byte length requested to be placed into buffer - bigendianp) should the data be packed LSB first (0) or - MSB first (1) - word) word size for output. currently 1 (byte) or - 2 (16 bit short) - - return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL) - 0) EOF - n) number of bytes of PCM actually returned. The - below works on a packet-by-packet basis, so the - return length is not related to the 'length' passed - in, just guaranteed to fit. - - *section) set to the logical bitstream number */ - long ov_read(OggVorbis_File *vf,char *buffer,int length, - int bigendianp,int word,int sgned,int *bitstream){ + int bigendianp,int word,int sgned,int *bitstream){ int i,j; int host_endian = host_is_big_endian(); @@ -181957,149 +169522,133 @@ long ov_read(OggVorbis_File *vf,char *buffer,int length, if(vf->ready_stateready_state==INITSET){ - samples=vorbis_synthesis_pcmout(&vf->vd,&pcm); - if(samples)break; - } + if(vf->ready_state==INITSET){ + samples=vorbis_synthesis_pcmout(&vf->vd,&pcm); + if(samples)break; + } - /* suck in another packet */ - { - int ret=_fetch_and_process_packet(vf,NULL,1,1); - if(ret==OV_EOF) + { + int ret=_fetch_and_process_packet(vf,NULL,1,1); + if(ret==OV_EOF) return(0); - if(ret<=0) + if(ret<=0) return(ret); - } + } } if(samples>0){ - /* yay! proceed to pack data into the byte buffer */ + long channels=ov_info(vf,-1)->channels; + long bytespersample=word * channels; + vorbis_fpu_control fpu; + (void) fpu; // (to avoid a warning about it being unused) + if(samples>length/bytespersample)samples=length/bytespersample; - long channels=ov_info(vf,-1)->channels; - long bytespersample=word * channels; - vorbis_fpu_control fpu; - (void) fpu; // (to avoid a warning about it being unused) - if(samples>length/bytespersample)samples=length/bytespersample; + if(samples <= 0) + return OV_EINVAL; - if(samples <= 0) - return OV_EINVAL; - - /* a tight loop to pack each size */ - { - int val; - if(word==1){ + { + int val; + if(word==1){ int off=(sgned?0:128); vorbis_fpu_setround(&fpu); for(j=0;j127)val=127; - else if(val<-128)val=-128; - *buffer++=val+off; + val=vorbis_ftoi(pcm[i][j]*128.f); + if(val>127)val=127; + else if(val<-128)val=-128; + *buffer++=val+off; } vorbis_fpu_restore(fpu); - }else{ + }else{ int off=(sgned?0:32768); if(host_endian==bigendianp){ if(sgned){ - vorbis_fpu_setround(&fpu); - for(i=0;i32767)val=32767; else if(val<-32768)val=-32768; *dest=val; dest+=channels; - } - } - vorbis_fpu_restore(fpu); + } + } + vorbis_fpu_restore(fpu); }else{ - vorbis_fpu_setround(&fpu); - for(i=0;i32767)val=32767; else if(val<-32768)val=-32768; *dest=val+off; dest+=channels; - } - } - vorbis_fpu_restore(fpu); + } + } + vorbis_fpu_restore(fpu); } }else if(bigendianp){ vorbis_fpu_setround(&fpu); for(j=0;j32767)val=32767; - else if(val<-32768)val=-32768; - val+=off; - *buffer++=(val>>8); - *buffer++=(val&0xff); - } + for(i=0;i32767)val=32767; + else if(val<-32768)val=-32768; + val+=off; + *buffer++=(val>>8); + *buffer++=(val&0xff); + } vorbis_fpu_restore(fpu); }else{ int val; vorbis_fpu_setround(&fpu); for(j=0;j32767)val=32767; - else if(val<-32768)val=-32768; - val+=off; - *buffer++=(val&0xff); - *buffer++=(val>>8); + for(i=0;i32767)val=32767; + else if(val<-32768)val=-32768; + val+=off; + *buffer++=(val&0xff); + *buffer++=(val>>8); } vorbis_fpu_restore(fpu); } - } - } + } + } - vorbis_synthesis_read(&vf->vd,samples); - vf->pcm_offset+=samples; - if(bitstream)*bitstream=vf->current_link; - return(samples*bytespersample); + vorbis_synthesis_read(&vf->vd,samples); + vf->pcm_offset+=samples; + if(bitstream)*bitstream=vf->current_link; + return(samples*bytespersample); }else{ - return(samples); + return(samples); } } -/* input values: pcm_channels) a float vector per channel of output - length) the sample length being read by the app - - return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL) - 0) EOF - n) number of samples of PCM actually returned. The - below works on a packet-by-packet basis, so the - return length is not related to the 'length' passed - in, just guaranteed to fit. - - *section) set to the logical bitstream number */ - long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length, int *bitstream){ if(vf->ready_stateready_state==INITSET){ - float **pcm; - long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm); - if(samples){ + if(vf->ready_state==INITSET){ + float **pcm; + long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm); + if(samples){ if(pcm_channels)*pcm_channels=pcm; if(samples>length)samples=length; vorbis_synthesis_read(&vf->vd,samples); @@ -182107,132 +169656,113 @@ long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length, if(bitstream)*bitstream=vf->current_link; return samples; - } - } + } + } - /* suck in another packet */ - { - int ret=_fetch_and_process_packet(vf,NULL,1,1); - if(ret==OV_EOF)return(0); - if(ret<=0)return(ret); - } + { + int ret=_fetch_and_process_packet(vf,NULL,1,1); + if(ret==OV_EOF)return(0); + if(ret<=0)return(ret); + } } } extern float *vorbis_window(vorbis_dsp_state *v,int W); extern void _analysis_output_always(const char *base,int i,float *v,int n,int bark,int dB, - ogg_int64_t off); + ogg_int64_t off); static void _ov_splice(float **pcm,float **lappcm, - int n1, int n2, - int ch1, int ch2, - float *w1, float *w2){ + int n1, int n2, + int ch1, int ch2, + float *w1, float *w2){ int i,j; float *w=w1; int n=n1; if(n1>n2){ - n=n2; - w=w2; + n=n2; + w=w2; } - /* splice */ for(j=0;jready_state==INITSET)break; - /* suck in another packet */ - { - int ret=_fetch_and_process_packet(vf,NULL,1,0); - if(ret<0 && ret!=OV_HOLE)return(ret); - } + if(vf->ready_state==INITSET)break; + { + int ret=_fetch_and_process_packet(vf,NULL,1,0); + if(ret<0 && ret!=OV_HOLE)return(ret); + } } return 0; } -/* make sure vf is INITSET and that we have a primed buffer; if - we're crosslapping at a stream section boundary, this also makes - sure we're sanity checking against the right stream information */ static int _ov_initprime(OggVorbis_File *vf){ vorbis_dsp_state *vd=&vf->vd; while(1){ - if(vf->ready_state==INITSET) - if(vorbis_synthesis_pcmout(vd,NULL))break; + if(vf->ready_state==INITSET) + if(vorbis_synthesis_pcmout(vd,NULL))break; - /* suck in another packet */ - { - int ret=_fetch_and_process_packet(vf,NULL,1,0); - if(ret<0 && ret!=OV_HOLE)return(ret); - } + { + int ret=_fetch_and_process_packet(vf,NULL,1,0); + if(ret<0 && ret!=OV_HOLE)return(ret); + } } return 0; } -/* grab enough data for lapping from vf; this may be in the form of - unreturned, already-decoded pcm, remaining PCM we will need to - decode, or synthetic postextrapolation from last packets. */ static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd, - float **lappcm,int lapsize){ + float **lappcm,int lapsize){ int lapcount=0,i; float **pcm; - /* try first to decode the lapping data */ while(lapcountlapsize-lapcount)samples=lapsize-lapcount; - for(i=0;ichannels;i++) + int samples=vorbis_synthesis_pcmout(vd,&pcm); + if(samples){ + if(samples>lapsize-lapcount)samples=lapsize-lapcount; + for(i=0;ichannels;i++) memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples); - lapcount+=samples; - vorbis_synthesis_read(vd,samples); - }else{ - /* suck in another packet */ - int ret=_fetch_and_process_packet(vf,NULL,1,0); /* do *not* span */ - if(ret==OV_EOF)break; - } + lapcount+=samples; + vorbis_synthesis_read(vd,samples); + }else{ + int ret=_fetch_and_process_packet(vf,NULL,1,0); /* do *not* span */ + if(ret==OV_EOF)break; + } } if(lapcountvd,&pcm); - if(samples==0){ - for(i=0;ichannels;i++) + int samples=vorbis_synthesis_lapout(&vf->vd,&pcm); + if(samples==0){ + for(i=0;ichannels;i++) memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount); - lapcount=lapsize; - }else{ - if(samples>lapsize-lapcount)samples=lapsize-lapcount; - for(i=0;ichannels;i++) + lapcount=lapsize; + }else{ + if(samples>lapsize-lapcount)samples=lapsize-lapcount; + for(i=0;ichannels;i++) memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples); - lapcount+=samples; - } + lapcount+=samples; + } } } -/* this sets up crosslapping of a sample by using trailing data from - sample 1 and lapping it into the windowing buffer of sample 2 */ int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){ vorbis_info *vi1,*vi2; float **lappcm; @@ -182244,10 +169774,6 @@ int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){ if(vf1->ready_stateready_statevd,0); for(i=0;ichannels;i++) - lappcm[i]=(float*) alloca(sizeof(**lappcm)*n1); + lappcm[i]=(float*) alloca(sizeof(**lappcm)*n1); _ov_getlap(vf1,vi1,&vf1->vd,lappcm,n1); - /* have a lapping buffer from vf1; now to splice it into the lapping - buffer of vf2 */ - /* consolidate and expose the buffer. */ vorbis_synthesis_lapout(&vf2->vd,&pcm); _analysis_output_always("pcmL",0,pcm[0],n1*2,0,0,0); _analysis_output_always("pcmR",0,pcm[1],n1*2,0,0,0); - /* splice */ _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2); - /* done */ return(0); } @@ -182307,28 +169828,23 @@ static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos, lappcm=(float**) alloca(sizeof(*lappcm)*ch1); for(i=0;ivd,lappcm,n1); - /* have lapping data; seek and prime the buffer */ ret=localseek(vf,pos); if(ret)return ret; ret=_ov_initprime(vf); if(ret)return(ret); - /* Guard against cross-link changes; they're perfectly legal */ vi=ov_info(vf,-1); ch2=vi->channels; n2=vorbis_info_blocksize(vi,0)>>(1+hs); w2=vorbis_window(&vf->vd,0); - /* consolidate and expose the buffer. */ vorbis_synthesis_lapout(&vf->vd,&pcm); - /* splice */ _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2); - /* done */ return(0); } @@ -182368,28 +169884,23 @@ static int _ov_d_seek_lap(OggVorbis_File *vf,double pos, lappcm=(float**) alloca(sizeof(*lappcm)*ch1); for(i=0;ivd,lappcm,n1); - /* have lapping data; seek and prime the buffer */ ret=localseek(vf,pos); if(ret)return ret; ret=_ov_initprime(vf); if(ret)return(ret); - /* Guard against cross-link changes; they're perfectly legal */ vi=ov_info(vf,-1); ch2=vi->channels; n2=vorbis_info_blocksize(vi,0)>>(1+hs); w2=vorbis_window(&vf->vd,0); - /* consolidate and expose the buffer. */ vorbis_synthesis_lapout(&vf->vd,&pcm); - /* splice */ _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2); - /* done */ return(0); } @@ -184505,32 +172016,32 @@ void _vorbis_apply_window(float *d,int *winno,long *blocksizes, nW=(W?nW:0); { - float *windowLW=vwin[winno[lW]]; - float *windowNW=vwin[winno[nW]]; + float *windowLW=vwin[winno[lW]]; + float *windowNW=vwin[winno[nW]]; - long n=blocksizes[W]; - long ln=blocksizes[lW]; - long rn=blocksizes[nW]; + long n=blocksizes[W]; + long ln=blocksizes[lW]; + long rn=blocksizes[nW]; - long leftbegin=n/4-ln/4; - long leftend=leftbegin+ln/2; + long leftbegin=n/4-ln/4; + long leftend=leftbegin+ln/2; - long rightbegin=n/2+n/4-rn/4; - long rightend=rightbegin+rn/2; + long rightbegin=n/2+n/4-rn/4; + long rightend=rightbegin+rn/2; - int i,p; + int i,p; - for(i=0;ichannels; - bitsPerSample = 16; - sampleRate = info->rate; + if (err == 0) + { + vorbis_info* info = ov_info (&ovFile, -1); + lengthInSamples = (uint32) ov_pcm_total (&ovFile, -1); + numChannels = info->channels; + bitsPerSample = 16; + sampleRate = info->rate; - reservoir.setSize (numChannels, - (int) jmin (lengthInSamples, (int64) reservoir.getNumSamples())); - } - } + reservoir.setSize (numChannels, + (int) jmin (lengthInSamples, (int64) reservoir.getNumSamples())); + } + } - ~OggReader() - { - ov_clear (&ovFile); - } + ~OggReader() + { + ov_clear (&ovFile); + } - bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples) - { - while (numSamples > 0) - { - const int numAvailable = reservoirStart + samplesInReservoir - startSampleInFile; + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples) + { + while (numSamples > 0) + { + const int numAvailable = reservoirStart + samplesInReservoir - startSampleInFile; - if (startSampleInFile >= reservoirStart && numAvailable > 0) - { - // got a few samples overlapping, so use them before seeking.. + if (startSampleInFile >= reservoirStart && numAvailable > 0) + { + // got a few samples overlapping, so use them before seeking.. - const int numToUse = jmin (numSamples, numAvailable); + const int numToUse = jmin (numSamples, numAvailable); - for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;) - if (destSamples[i] != 0) - memcpy (destSamples[i] + startOffsetInDestBuffer, - reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)), - sizeof (float) * numToUse); + for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;) + if (destSamples[i] != 0) + memcpy (destSamples[i] + startOffsetInDestBuffer, + reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)), + sizeof (float) * numToUse); - startSampleInFile += numToUse; - numSamples -= numToUse; - startOffsetInDestBuffer += numToUse; + startSampleInFile += numToUse; + numSamples -= numToUse; + startOffsetInDestBuffer += numToUse; - if (numSamples == 0) - break; - } + if (numSamples == 0) + break; + } - if (startSampleInFile < reservoirStart - || startSampleInFile + numSamples > reservoirStart + samplesInReservoir) - { - // buffer miss, so refill the reservoir - int bitStream = 0; + if (startSampleInFile < reservoirStart + || startSampleInFile + numSamples > reservoirStart + samplesInReservoir) + { + // buffer miss, so refill the reservoir + int bitStream = 0; - reservoirStart = jmax (0, (int) startSampleInFile); - samplesInReservoir = reservoir.getNumSamples(); + reservoirStart = jmax (0, (int) startSampleInFile); + samplesInReservoir = reservoir.getNumSamples(); - if (reservoirStart != (int) ov_pcm_tell (&ovFile)) - ov_pcm_seek (&ovFile, reservoirStart); + if (reservoirStart != (int) ov_pcm_tell (&ovFile)) + ov_pcm_seek (&ovFile, reservoirStart); - int offset = 0; - int numToRead = samplesInReservoir; + int offset = 0; + int numToRead = samplesInReservoir; - while (numToRead > 0) - { - float** dataIn = 0; + while (numToRead > 0) + { + float** dataIn = 0; - const int samps = ov_read_float (&ovFile, &dataIn, numToRead, &bitStream); - if (samps <= 0) - break; + const int samps = ov_read_float (&ovFile, &dataIn, numToRead, &bitStream); + if (samps <= 0) + break; - jassert (samps <= numToRead); + jassert (samps <= numToRead); - for (int i = jmin (numChannels, reservoir.getNumChannels()); --i >= 0;) - { - memcpy (reservoir.getSampleData (i, offset), - dataIn[i], - sizeof (float) * samps); - } + for (int i = jmin ((int) numChannels, reservoir.getNumChannels()); --i >= 0;) + { + memcpy (reservoir.getSampleData (i, offset), + dataIn[i], + sizeof (float) * samps); + } - numToRead -= samps; - offset += samps; - } + numToRead -= samps; + offset += samps; + } - if (numToRead > 0) - reservoir.clear (offset, numToRead); - } - } + if (numToRead > 0) + reservoir.clear (offset, numToRead); + } + } - if (numSamples > 0) - { - for (int i = numDestChannels; --i >= 0;) - if (destSamples[i] != 0) - zeromem (destSamples[i] + startOffsetInDestBuffer, - sizeof (int) * numSamples); - } + if (numSamples > 0) + { + for (int i = numDestChannels; --i >= 0;) + if (destSamples[i] != 0) + zeromem (destSamples[i] + startOffsetInDestBuffer, + sizeof (int) * numSamples); + } - return true; - } + return true; + } - static size_t oggReadCallback (void* ptr, size_t size, size_t nmemb, void* datasource) - { - return (size_t) (((InputStream*) datasource)->read (ptr, (int) (size * nmemb)) / size); - } + static size_t oggReadCallback (void* ptr, size_t size, size_t nmemb, void* datasource) + { + return (size_t) (((InputStream*) datasource)->read (ptr, (int) (size * nmemb)) / size); + } - static int oggSeekCallback (void* datasource, ogg_int64_t offset, int whence) - { - InputStream* const in = (InputStream*) datasource; + static int oggSeekCallback (void* datasource, ogg_int64_t offset, int whence) + { + InputStream* const in = (InputStream*) datasource; - if (whence == SEEK_CUR) - offset += in->getPosition(); - else if (whence == SEEK_END) - offset += in->getTotalLength(); + if (whence == SEEK_CUR) + offset += in->getPosition(); + else if (whence == SEEK_END) + offset += in->getTotalLength(); - in->setPosition (offset); - return 0; - } + in->setPosition (offset); + return 0; + } - static int oggCloseCallback (void*) - { - return 0; - } + static int oggCloseCallback (void*) + { + return 0; + } - static long oggTellCallback (void* datasource) - { - return (long) ((InputStream*) datasource)->getPosition(); - } + static long oggTellCallback (void* datasource) + { + return (long) ((InputStream*) datasource)->getPosition(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; class OggWriter : public AudioFormatWriter { - ogg_stream_state os; - ogg_page og; - ogg_packet op; - vorbis_info vi; - vorbis_comment vc; - vorbis_dsp_state vd; - vorbis_block vb; + ogg_stream_state os; + ogg_page og; + ogg_packet op; + vorbis_info vi; + vorbis_comment vc; + vorbis_dsp_state vd; + vorbis_block vb; public: - bool ok; + bool ok; - OggWriter (OutputStream* const out, - const double sampleRate, - const int numChannels, - const int bitsPerSample, - const int qualityIndex) - : AudioFormatWriter (out, TRANS (oggFormatName), - sampleRate, - numChannels, - bitsPerSample) - { - ok = false; + OggWriter (OutputStream* const out, + const double sampleRate, + const int numChannels, + const int bitsPerSample, + const int qualityIndex) + : AudioFormatWriter (out, TRANS (oggFormatName), + sampleRate, + numChannels, + bitsPerSample) + { + ok = false; - vorbis_info_init (&vi); + vorbis_info_init (&vi); - if (vorbis_encode_init_vbr (&vi, - numChannels, - (int) sampleRate, - jlimit (0.0f, 1.0f, qualityIndex * 0.5f)) == 0) - { - vorbis_comment_init (&vc); + if (vorbis_encode_init_vbr (&vi, + numChannels, + (int) sampleRate, + jlimit (0.0f, 1.0f, qualityIndex * 0.5f)) == 0) + { + vorbis_comment_init (&vc); - if (JUCEApplication::getInstance() != 0) - vorbis_comment_add_tag (&vc, "ENCODER", - (char*) (const char*) JUCEApplication::getInstance()->getApplicationName()); + if (JUCEApplication::getInstance() != 0) + vorbis_comment_add_tag (&vc, "ENCODER", + (char*) (const char*) JUCEApplication::getInstance()->getApplicationName()); - vorbis_analysis_init (&vd, &vi); - vorbis_block_init (&vd, &vb); + vorbis_analysis_init (&vd, &vi); + vorbis_block_init (&vd, &vb); - ogg_stream_init (&os, Random::getSystemRandom().nextInt()); + ogg_stream_init (&os, Random::getSystemRandom().nextInt()); - ogg_packet header; - ogg_packet header_comm; - ogg_packet header_code; + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; - vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code); + vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code); - ogg_stream_packetin (&os, &header); - ogg_stream_packetin (&os, &header_comm); - ogg_stream_packetin (&os, &header_code); + ogg_stream_packetin (&os, &header); + ogg_stream_packetin (&os, &header_comm); + ogg_stream_packetin (&os, &header_code); - for (;;) - { - if (ogg_stream_flush (&os, &og) == 0) - break; + for (;;) + { + if (ogg_stream_flush (&os, &og) == 0) + break; - output->write (og.header, og.header_len); - output->write (og.body, og.body_len); - } + output->write (og.header, og.header_len); + output->write (og.body, og.body_len); + } - ok = true; - } - } + ok = true; + } + } - ~OggWriter() - { - if (ok) - { - // write a zero-length packet to show ogg that we're finished.. - write (0, 0); + ~OggWriter() + { + if (ok) + { + // write a zero-length packet to show ogg that we're finished.. + write (0, 0); - ogg_stream_clear (&os); - vorbis_block_clear (&vb); - vorbis_dsp_clear (&vd); - vorbis_comment_clear (&vc); + ogg_stream_clear (&os); + vorbis_block_clear (&vb); + vorbis_dsp_clear (&vd); + vorbis_comment_clear (&vc); - vorbis_info_clear (&vi); - output->flush(); - } - else - { - vorbis_info_clear (&vi); - output = 0; // to stop the base class deleting this, as it needs to be returned - // to the caller of createWriter() - } - } + vorbis_info_clear (&vi); + output->flush(); + } + else + { + vorbis_info_clear (&vi); + output = 0; // to stop the base class deleting this, as it needs to be returned + // to the caller of createWriter() + } + } - bool write (const int** samplesToWrite, int numSamples) - { - if (! ok) - return false; + bool write (const int** samplesToWrite, int numSamples) + { + if (! ok) + return false; - if (numSamples > 0) - { - const double gain = 1.0 / 0x80000000u; - float** const vorbisBuffer = vorbis_analysis_buffer (&vd, numSamples); + if (numSamples > 0) + { + const double gain = 1.0 / 0x80000000u; + float** const vorbisBuffer = vorbis_analysis_buffer (&vd, numSamples); - for (int i = numChannels; --i >= 0;) - { - float* const dst = vorbisBuffer[i]; - const int* const src = samplesToWrite [i]; + for (int i = numChannels; --i >= 0;) + { + float* const dst = vorbisBuffer[i]; + const int* const src = samplesToWrite [i]; - if (src != 0 && dst != 0) - { - for (int j = 0; j < numSamples; ++j) - dst[j] = (float) (src[j] * gain); - } - } - } + if (src != 0 && dst != 0) + { + for (int j = 0; j < numSamples; ++j) + dst[j] = (float) (src[j] * gain); + } + } + } - vorbis_analysis_wrote (&vd, numSamples); + vorbis_analysis_wrote (&vd, numSamples); - while (vorbis_analysis_blockout (&vd, &vb) == 1) - { - vorbis_analysis (&vb, 0); - vorbis_bitrate_addblock (&vb); + while (vorbis_analysis_blockout (&vd, &vb) == 1) + { + vorbis_analysis (&vb, 0); + vorbis_bitrate_addblock (&vb); - while (vorbis_bitrate_flushpacket (&vd, &op)) - { - ogg_stream_packetin (&os, &op); + while (vorbis_bitrate_flushpacket (&vd, &op)) + { + ogg_stream_packetin (&os, &op); - for (;;) - { - if (ogg_stream_pageout (&os, &og) == 0) - break; + for (;;) + { + if (ogg_stream_pageout (&os, &og) == 0) + break; - output->write (og.header, og.header_len); - output->write (og.body, og.body_len); + output->write (og.header, og.header_len); + output->write (og.body, og.body_len); - if (ogg_page_eos (&og)) - break; - } - } - } + if (ogg_page_eos (&og)) + break; + } + } + } - return true; - } + return true; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; OggVorbisAudioFormat::OggVorbisAudioFormat() - : AudioFormat (TRANS (oggFormatName), (const tchar**) oggExtensions) + : AudioFormat (TRANS (oggFormatName), (const tchar**) oggExtensions) { } @@ -184858,97 +172369,97 @@ OggVorbisAudioFormat::~OggVorbisAudioFormat() const Array OggVorbisAudioFormat::getPossibleSampleRates() { - const int rates[] = { 22050, 32000, 44100, 48000, 0 }; - return Array (rates); + const int rates[] = { 22050, 32000, 44100, 48000, 0 }; + return Array (rates); } const Array OggVorbisAudioFormat::getPossibleBitDepths() { - Array depths; - depths.add (32); - return depths; + Array depths; + depths.add (32); + return depths; } bool OggVorbisAudioFormat::canDoStereo() { - return true; + return true; } bool OggVorbisAudioFormat::canDoMono() { - return true; + return true; } AudioFormatReader* OggVorbisAudioFormat::createReaderFor (InputStream* in, - const bool deleteStreamIfOpeningFails) + const bool deleteStreamIfOpeningFails) { - ScopedPointer r (new OggReader (in)); + ScopedPointer r (new OggReader (in)); - if (r->sampleRate != 0) - return r.release(); + if (r->sampleRate != 0) + return r.release(); - if (! deleteStreamIfOpeningFails) - r->input = 0; + if (! deleteStreamIfOpeningFails) + r->input = 0; - return 0; + return 0; } AudioFormatWriter* OggVorbisAudioFormat::createWriterFor (OutputStream* out, - double sampleRate, - unsigned int numChannels, - int bitsPerSample, - const StringPairArray& /*metadataValues*/, - int qualityOptionIndex) + double sampleRate, + unsigned int numChannels, + int bitsPerSample, + const StringPairArray& /*metadataValues*/, + int qualityOptionIndex) { - ScopedPointer w (new OggWriter (out, - sampleRate, - numChannels, - bitsPerSample, - qualityOptionIndex)); + ScopedPointer w (new OggWriter (out, + sampleRate, + numChannels, + bitsPerSample, + qualityOptionIndex)); - return w->ok ? w.release() : 0; + return w->ok ? w.release() : 0; } bool OggVorbisAudioFormat::isCompressed() { - return true; + return true; } const StringArray OggVorbisAudioFormat::getQualityOptions() { - StringArray s; - s.add ("Low Quality"); - s.add ("Medium Quality"); - s.add ("High Quality"); - return s; + StringArray s; + s.add ("Low Quality"); + s.add ("Medium Quality"); + s.add ("High Quality"); + return s; } int OggVorbisAudioFormat::estimateOggFileQuality (const File& source) { - FileInputStream* const in = source.createInputStream(); + FileInputStream* const in = source.createInputStream(); - if (in != 0) - { - ScopedPointer r (createReaderFor (in, true)); + if (in != 0) + { + ScopedPointer r (createReaderFor (in, true)); - if (r != 0) - { - const int64 numSamps = r->lengthInSamples; - r = 0; + if (r != 0) + { + const int64 numSamps = r->lengthInSamples; + r = 0; - const int64 fileNumSamps = source.getSize() / 4; - const double ratio = numSamps / (double) fileNumSamps; + const int64 fileNumSamps = source.getSize() / 4; + const double ratio = numSamps / (double) fileNumSamps; - if (ratio > 12.0) - return 0; - else if (ratio > 6.0) - return 1; - else - return 2; - } - } + if (ratio > 12.0) + return 0; + else if (ratio > 6.0) + return 1; + else + return 2; + } + } - return 1; + return 1; } END_JUCE_NAMESPACE @@ -184965,26 +172476,21 @@ END_JUCE_NAMESPACE namespace jpeglibNamespace { #if JUCE_INCLUDE_JPEGLIB_CODE + #if JUCE_MINGW + typedef unsigned char boolean; + #endif extern "C" { - #define JPEG_INTERNALS - #undef FAR + #define JPEG_INTERNALS + #undef FAR /********* Start of inlined file: jpeglib.h *********/ #ifndef JPEGLIB_H #define JPEGLIB_H -/* - * First we include the configuration files that record how this - * installation of the JPEG library is set up. jconfig.h can be - * generated automatically for many systems. jmorecfg.h contains - * manual configuration options that most people need not worry about. - */ - #ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ /********* Start of inlined file: jconfig.h *********/ -/* see jconfig.doc for explanations */ // disable all the warnings under MSVC #ifdef _MSC_VER @@ -185001,8 +172507,6 @@ namespace jpeglibNamespace #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT -/* #define void char */ -/* #define const */ #undef CHAR_IS_UNSIGNED #define HAVE_STDDEF_H #define HAVE_STDLIB_H @@ -185012,7 +172516,6 @@ namespace jpeglibNamespace #undef NEED_SHORT_EXTERNAL_NAMES #undef INCOMPLETE_TYPES_BROKEN -/* Define "boolean" as unsigned char, not int, per Windows custom */ #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ typedef unsigned char boolean; #endif @@ -185041,50 +172544,15 @@ typedef unsigned char boolean; #endif /* JPEG_CJPEG_DJPEG */ /********* End of inlined file: jconfig.h *********/ - /* widely used configuration options */ #endif /********* Start of inlined file: jmorecfg.h *********/ -/* - * Define BITS_IN_JSAMPLE as either - * 8 for 8-bit sample values (the usual setting) - * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. - */ #define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ -/* - * Maximum number of components (color channels) allowed in JPEG image. - * To meet the letter of the JPEG spec, set this to 255. However, darn - * few applications need more than 4 channels (maybe 5 for CMYK + alpha - * mask). We recommend 10 as a reasonable compromise; use 4 if you are - * really short on memory. (Each allowed component costs a hundred or so - * bytes of storage, whether actually used in an image or not.) - */ - #define MAX_COMPONENTS 10 /* maximum number of image components */ -/* - * Basic data types. - * You may need to change these if you have a machine with unusual data - * type sizes; for example, "char" not 8 bits, "short" not 16 bits, - * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, - * but it had better be at least 16. - */ - -/* Representation of a single sample (pixel element value). - * We frequently allocate large arrays of these, so it's important to keep - * them small. But if you have memory to burn and access to char or short - * arrays is very slow on your hardware, you might want to change these. - */ - #if BITS_IN_JSAMPLE == 8 -/* JSAMPLE should be the smallest type that will hold the values 0..255. - * You can use a signed char by having GETJSAMPLE mask it with 0xFF. - */ #ifdef HAVE_UNSIGNED_CHAR @@ -185108,9 +172576,6 @@ typedef char JSAMPLE; #endif /* BITS_IN_JSAMPLE == 8 */ #if BITS_IN_JSAMPLE == 12 -/* JSAMPLE should be the smallest type that will hold the values 0..4095. - * On nearly all machines "short" will do nicely. - */ typedef short JSAMPLE; #define GETJSAMPLE(value) ((int) (value)) @@ -185120,20 +172585,8 @@ typedef short JSAMPLE; #endif /* BITS_IN_JSAMPLE == 12 */ -/* Representation of a DCT frequency coefficient. - * This should be a signed value of at least 16 bits; "short" is usually OK. - * Again, we allocate large arrays of these, but you can change to int - * if you have memory to burn and "short" is really slow. - */ - typedef short JCOEF; -/* Compressed datastreams are represented as arrays of JOCTET. - * These must be EXACTLY 8 bits wide, at least once they are written to - * external storage. Note that when using the stdio data source/destination - * managers, this is also the data type passed to fread/fwrite. - */ - #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JOCTET; @@ -185150,15 +172603,6 @@ typedef char JOCTET; #endif /* HAVE_UNSIGNED_CHAR */ -/* These typedefs are used for various table entries and so forth. - * They must be at least as wide as specified; but making them too big - * won't cost a huge amount of memory, so we don't provide special - * extraction code like we did for JSAMPLE. (In other words, these - * typedefs live at a different point on the speed/space tradeoff curve.) - */ - -/* UINT8 must hold at least the values 0..255. */ - #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char UINT8; #else /* not HAVE_UNSIGNED_CHAR */ @@ -185169,84 +172613,41 @@ typedef short UINT8; #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ -/* UINT16 must hold at least the values 0..65535. */ - #ifdef HAVE_UNSIGNED_SHORT typedef unsigned short UINT16; #else /* not HAVE_UNSIGNED_SHORT */ typedef unsigned int UINT16; #endif /* HAVE_UNSIGNED_SHORT */ -/* INT16 must hold at least the values -32768..32767. */ - #ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ typedef short INT16; #endif -/* INT32 must hold at least signed 32-bit values. */ - #ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ typedef long INT32; #endif -/* Datatype used for image dimensions. The JPEG standard only supports - * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore - * "unsigned int" is sufficient on all machines. However, if you need to - * handle larger images and you don't mind deviating from the spec, you - * can change this datatype. - */ - typedef unsigned int JDIMENSION; #define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ -/* These macros are used in all function definitions and extern declarations. - * You could modify them if you need to change function linkage conventions; - * in particular, you'll need to do that to make the library a Windows DLL. - * Another application is to make all functions global for use with debuggers - * or code profilers that require it. - */ - -/* a function called through method pointers: */ #define METHODDEF(type) static type -/* a function used only in its module: */ #define LOCAL(type) static type -/* a function referenced thru EXTERNs: */ #define GLOBAL(type) type -/* a reference to a GLOBAL function: */ #define EXTERN(type) extern type -/* This macro is used to declare a "method", that is, a function pointer. - * We want to supply prototype parameters if the compiler can cope. - * Note that the arglist parameter must be parenthesized! - * Again, you can customize this if you need special linkage keywords. - */ - #ifdef HAVE_PROTOTYPES #define JMETHOD(type,methodname,arglist) type (*methodname) arglist #else #define JMETHOD(type,methodname,arglist) type (*methodname) () #endif -/* Here is the pseudo-keyword for declaring pointers that must be "far" - * on 80x86 machines. Most of the specialized coding for 80x86 is handled - * by just saying "FAR *" where such a pointer is needed. In a few places - * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. - */ - #ifdef NEED_FAR_POINTERS #define FAR far #else #define FAR #endif -/* - * On a few systems, type boolean and/or its values FALSE, TRUE may appear - * in standard header files. Or you may have conflicts with application- - * specific header files that you want to include together with these files. - * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. - */ - #ifndef HAVE_BOOLEAN typedef int boolean; #endif @@ -185257,92 +172658,38 @@ typedef int boolean; #define TRUE 1 #endif -/* - * The remaining options affect code selection within the JPEG library, - * but they don't need to be visible to most applications using the library. - * To minimize application namespace pollution, the symbols won't be - * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. - */ - #ifdef JPEG_INTERNALS #define JPEG_INTERNAL_OPTIONS #endif #ifdef JPEG_INTERNAL_OPTIONS -/* - * These defines indicate whether to include various optional functions. - * Undefining some of these symbols will produce a smaller but less capable - * library. Note that you can leave certain source files out of the - * compilation/linking process if you've #undef'd the corresponding symbols. - * (You may HAVE to do that if your compiler doesn't like null source files.) - */ - -/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ - -/* Capability options common to encoder and decoder: */ - #define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ #define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ #define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ -/* Encoder capability options: */ - -#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ -/* Note: if you selected 12-bit data precision, it is dangerous to turn off - * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit - * precision, so jchuff.c normally uses entropy optimization to compute - * usable tables for higher precision. If you don't want to do optimization, - * you'll have to supply different default Huffman tables. - * The exact same statements apply for progressive JPEG: the default tables - * don't work for progressive mode. (This may get fixed, however.) - */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ #define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ -/* Decoder capability options: */ - -#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ #define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ -#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ #undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ #define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ -#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ -#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ - -/* more capability options later, no doubt */ - -/* - * Ordering of RGB data in scanlines passed to or from the application. - * If your application wants to deal with data in the order B,G,R, just - * change these macros. You can also deal with formats such as R,G,B,X - * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing - * the offsets will also change the order in which colormap data is organized. - * RESTRICTIONS: - * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. - * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not - * useful if you are using JPEG color spaces other than YCbCr or grayscale. - * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE - * is not 3 (they don't understand about dummy color components!). So you - * can't use color quantization if you change that value. - */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ #define RGB_RED 0 /* Offset of Red in an RGB scanline element */ #define RGB_GREEN 1 /* Offset of Green */ #define RGB_BLUE 2 /* Offset of Blue */ #define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ -/* Definitions for speed-related optimizations. */ - -/* If your compiler supports inline functions, define INLINE - * as the inline keyword; otherwise define it as empty. - */ - #ifndef INLINE #ifdef __GNUC__ /* for instance, GNU C knows about inline */ #define INLINE __inline__ @@ -185352,23 +172699,10 @@ typedef int boolean; #endif #endif -/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying - * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER - * as short on such a machine. MULTIPLIER must be at least 16 bits wide. - */ - #ifndef MULTIPLIER #define MULTIPLIER int /* type for fastest integer multiply */ #endif -/* FAST_FLOAT should be either float or double, whichever is done faster - * by your compiler. (Note that this type is only used in the floating point - * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) - * Typically, float is faster in ANSI C compilers, while double is faster in - * pre-ANSI compilers (because they insist on converting to double anyway). - * The code below therefore chooses float if we have ANSI-style prototypes. - */ - #ifndef FAST_FLOAT #ifdef HAVE_PROTOTYPES #define FAST_FLOAT float @@ -185380,43 +172714,20 @@ typedef int boolean; #endif /* JPEG_INTERNAL_OPTIONS */ /********* End of inlined file: jmorecfg.h *********/ - /* seldom changed options */ - -/* Version ID for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". - */ - #define JPEG_LIB_VERSION 62 /* Version 6b */ -/* Various constants determining the sizes of things. - * All of these are specified by the JPEG standard, so don't change them - * if you want to be compatible. - */ - -#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ -#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ -#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ -#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ -#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ #define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ -#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ -/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; - * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. - * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU - * to handle it. We even let you do this from the jconfig.h file. However, - * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe - * sometimes emits noncompliant files doesn't mean you should too. - */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ #define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ #ifndef D_MAX_BLOCKS_IN_MCU #define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ #endif -/* Data structures for images (arrays of samples and of DCT coefficients). - * On 80x86 machines, the image arrays are too big for near pointers, - * but the pointer arrays can fit in near memory. - */ - typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ @@ -185428,89 +172739,33 @@ typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ -/* Types for JPEG compression parameters and working tables. */ - -/* DCT coefficient quantization tables. */ - typedef struct { - /* This array gives the coefficient quantizers in natural array order - * (not the zigzag order in which they are stored in a JPEG DQT marker). - * CAUTION: IJG versions prior to v6a kept this array in zigzag order. - */ UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ boolean sent_table; /* TRUE when table has been output */ } JQUANT_TBL; -/* Huffman coding tables. */ - typedef struct { - /* These two fields directly represent the contents of a JPEG DHT marker */ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ - /* length k bits; bits[0] is unused */ UINT8 huffval[256]; /* The symbols, in order of incr code length */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ boolean sent_table; /* TRUE when table has been output */ } JHUFF_TBL; -/* Basic info about one component (color channel). */ - typedef struct { - /* These values are fixed over the whole image. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOF marker. */ int component_id; /* identifier for this component (0..255) */ int component_index; /* its index in SOF or cinfo->comp_info[] */ int h_samp_factor; /* horizontal sampling factor (1..4) */ int v_samp_factor; /* vertical sampling factor (1..4) */ int quant_tbl_no; /* quantization table selector (0..3) */ - /* These values may vary between scans. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOS marker. */ - /* The decompressor output side may not use these variables. */ int dc_tbl_no; /* DC entropy table selector (0..3) */ int ac_tbl_no; /* AC entropy table selector (0..3) */ - /* Remaining fields should be treated as private by applications. */ - - /* These values are computed during compression or decompression startup: */ - /* Component's size in DCT blocks. - * Any dummy blocks added to complete an MCU are not counted; therefore - * these values do not depend on whether a scan is interleaved or not. - */ JDIMENSION width_in_blocks; JDIMENSION height_in_blocks; - /* Size of a DCT block in samples. Always DCTSIZE for compression. - * For decompression this is the size of the output from one DCT block, - * reflecting any scaling we choose to apply during the IDCT step. - * Values of 1,2,4,8 are likely to be supported. Note that different - * components may receive different IDCT scalings. - */ int DCT_scaled_size; - /* The downsampled dimensions are the component's actual, unpadded number - * of samples at the main buffer (preprocessing/compression interface), thus - * downsampled_width = ceil(image_width * Hi/Hmax) - * and similarly for height. For decompression, IDCT scaling is included, so - * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) - */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ - /* This flag is used only for decompression. In cases where some of the - * components will be ignored (eg grayscale output from YCbCr image), - * we can skip most computations for the unused components. - */ boolean component_needed; /* do we need the value of this component? */ - /* These values are computed before starting a scan of the component. */ - /* The decompressor output side may not use these variables. */ int MCU_width; /* number of blocks per MCU, horizontally */ int MCU_height; /* number of blocks per MCU, vertically */ int MCU_blocks; /* MCU_width * MCU_height */ @@ -185518,18 +172773,11 @@ typedef struct { int last_col_width; /* # of non-dummy blocks across in last MCU */ int last_row_height; /* # of non-dummy blocks down in last MCU */ - /* Saved quantization table for component; NULL if none yet saved. - * See jdinput.c comments about the need for this information. - * This field is currently used only for decompression. - */ JQUANT_TBL * quant_table; - /* Private per-component storage for DCT or IDCT subsystem. */ void * dct_table; } jpeg_component_info; -/* The script for encoding a multiple-scan file is an array of these: */ - typedef struct { int comps_in_scan; /* number of components encoded in this scan */ int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ @@ -185537,8 +172785,6 @@ typedef struct { int Ah, Al; /* progressive JPEG successive approx. parms */ } jpeg_scan_info; -/* The decompressor can save APPn and COM markers in a list of these: */ - typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; struct jpeg_marker_struct { @@ -185547,11 +172793,8 @@ struct jpeg_marker_struct { unsigned int original_length; /* # bytes of data in the file */ unsigned int data_length; /* # bytes of data saved at data[] */ JOCTET FAR * data; /* the data contained in the marker */ - /* the marker length word is not counted in data_length or original_length */ }; -/* Known color spaces. */ - typedef enum { JCS_UNKNOWN, /* error/unspecified */ JCS_GRAYSCALE, /* monochrome */ @@ -185561,8 +172804,6 @@ typedef enum { JCS_YCCK /* Y/Cb/Cr/K */ } J_COLOR_SPACE; -/* DCT/IDCT algorithm options. */ - typedef enum { JDCT_ISLOW, /* slow but accurate integer algorithm */ JDCT_IFAST, /* faster, less accurate integer method */ @@ -185576,16 +172817,12 @@ typedef enum { #define JDCT_FASTEST JDCT_IFAST #endif -/* Dithering options for decompression. */ - typedef enum { JDITHER_NONE, /* no dithering */ JDITHER_ORDERED, /* simple ordered dither */ JDITHER_FS /* Floyd-Steinberg error diffusion dither */ } J_DITHER_MODE; -/* Common fields between JPEG compression and decompression master structs. */ - #define jpeg_common_fields \ struct jpeg_error_mgr * err; /* Error handler module */\ struct jpeg_memory_mgr * mem; /* Memory manager module */\ @@ -185594,35 +172831,19 @@ typedef enum { boolean is_decompressor; /* So common code can tell which is which */\ int global_state /* For checking call sequence validity */ -/* Routines that are to be used by both halves of the library are declared - * to receive a pointer to this structure. There are no actual instances of - * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. - */ struct jpeg_common_struct { jpeg_common_fields; /* Fields common to both master struct types */ - /* Additional fields follow in an actual jpeg_compress_struct or - * jpeg_decompress_struct. All three structs must agree on these - * initial fields! (This would be a lot cleaner in C++.) - */ }; typedef struct jpeg_common_struct * j_common_ptr; typedef struct jpeg_compress_struct * j_compress_ptr; typedef struct jpeg_decompress_struct * j_decompress_ptr; -/* Master record for a compression instance */ - struct jpeg_compress_struct { jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ - /* Destination for compressed data */ struct jpeg_destination_mgr * dest; - /* Description of source image --- these fields must be filled in by - * outer application before starting compression. in_color_space must - * be correct before you can even call jpeg_set_defaults(). - */ - JDIMENSION image_width; /* input image width */ JDIMENSION image_height; /* input image height */ int input_components; /* # of color components in input image */ @@ -185630,28 +172851,17 @@ struct jpeg_compress_struct { double input_gamma; /* image gamma of input image */ - /* Compression parameters --- these fields must be set before calling - * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to - * initialize everything to reasonable defaults, then changing anything - * the application specifically wants to change. That way you won't get - * burnt when new parameters are added. Also note that there are several - * helper routines to simplify changing parameters. - */ - int data_precision; /* bits of precision in image data */ int num_components; /* # of color components in JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ @@ -185659,10 +172869,6 @@ struct jpeg_compress_struct { int num_scans; /* # of entries in scan_info array */ const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ - /* The default value of scan_info is NULL, which causes a single-scan - * sequential JPEG file to be emitted. To create a multi-scan file, - * set num_scans and scan_info to point to an array of scan definitions. - */ boolean raw_data_in; /* TRUE=caller supplies downsampled data */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ @@ -185671,74 +172877,36 @@ struct jpeg_compress_struct { int smoothing_factor; /* 1..100, or 0 for no input smoothing */ J_DCT_METHOD dct_method; /* DCT algorithm selector */ - /* The restart interval can be specified in absolute MCUs by setting - * restart_interval, or in MCU rows by setting restart_in_rows - * (in which case the correct restart_interval will be figured - * for each scan). - */ unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ int restart_in_rows; /* if > 0, MCU rows per restart interval */ - /* Parameters controlling emission of special markers. */ - boolean write_JFIF_header; /* should a JFIF marker be written? */ UINT8 JFIF_major_version; /* What to write for the JFIF version number */ UINT8 JFIF_minor_version; - /* These three values are not used by the JPEG code, merely copied */ - /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ - /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ - /* ratio is defined by X_density/Y_density even when density_unit=0. */ UINT8 density_unit; /* JFIF code for pixel size units */ UINT16 X_density; /* Horizontal pixel density */ UINT16 Y_density; /* Vertical pixel density */ boolean write_Adobe_marker; /* should an Adobe marker be written? */ - /* State variable: index of next scanline to be written to - * jpeg_write_scanlines(). Application may use this to control its - * processing loop, e.g., "while (next_scanline < image_height)". - */ - JDIMENSION next_scanline; /* 0 .. image_height-1 */ - /* Remaining fields are known throughout compressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during compression startup - */ boolean progressive_mode; /* TRUE if scan script uses progressive mode */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ - /* The coefficient controller receives data in units of MCU rows as defined - * for fully interleaved scans (whether the JPEG file is interleaved or not). - * There are v_samp_factor * DCTSIZE sample rows of each component in an - * "iMCU" (interleaved MCU) row. - */ - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - */ int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[C_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - /* - * Links to compression subobjects (methods and private variables of modules) - */ struct jpeg_comp_master * master; struct jpeg_c_main_controller * main; struct jpeg_c_prep_controller * prep; @@ -185752,27 +172920,16 @@ struct jpeg_compress_struct { int script_space_size; }; -/* Master record for a decompression instance */ - struct jpeg_decompress_struct { jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ - /* Source of compressed data */ struct jpeg_source_mgr * src; - /* Basic description of image --- filled in by jpeg_read_header(). */ - /* Application may inspect these values to decide how to process image. */ - JDIMENSION image_width; /* nominal image width (from SOF marker) */ JDIMENSION image_height; /* nominal image height */ int num_components; /* # of color components in JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - /* Decompression processing parameters --- these fields must be set before - * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes - * them to default values. - */ - J_COLOR_SPACE out_color_space; /* colorspace for output */ unsigned int scale_num, scale_denom; /* fraction by which to scale image */ @@ -185787,99 +172944,40 @@ struct jpeg_decompress_struct { boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ boolean quantize_colors; /* TRUE=colormapped output wanted */ - /* the following are ignored if not quantize_colors: */ J_DITHER_MODE dither_mode; /* type of color dithering to use */ boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ int desired_number_of_colors; /* max # colors to use in created colormap */ - /* these are significant only in buffered-image mode: */ boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ boolean enable_external_quant;/* enable future use of external colormap */ boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ - /* Description of actual output image that will be returned to application. - * These fields are computed by jpeg_start_decompress(). - * You can also use jpeg_calc_output_dimensions() to determine these values - * in advance of calling jpeg_start_decompress(). - */ - JDIMENSION output_width; /* scaled image width */ JDIMENSION output_height; /* scaled image height */ int out_color_components; /* # of color components in out_color_space */ int output_components; /* # of color components returned */ - /* output_components is 1 (a colormap index) when quantizing colors; - * otherwise it equals out_color_components. - */ int rec_outbuf_height; /* min recommended height of scanline buffer */ - /* If the buffer passed to jpeg_read_scanlines() is less than this many rows - * high, space and time will be wasted due to unnecessary data copying. - * Usually rec_outbuf_height will be 1 or 2, at most 4. - */ - /* When quantizing colors, the output colormap is described by these fields. - * The application can supply a colormap by setting colormap non-NULL before - * calling jpeg_start_decompress; otherwise a colormap is created during - * jpeg_start_decompress or jpeg_start_output. - * The map has out_color_components rows and actual_number_of_colors columns. - */ int actual_number_of_colors; /* number of entries in use */ JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ - /* State variables: these variables indicate the progress of decompression. - * The application may examine these but must not modify them. - */ - - /* Row index of next scanline to be read from jpeg_read_scanlines(). - * Application may use this to control its processing loop, e.g., - * "while (output_scanline < output_height)". - */ JDIMENSION output_scanline; /* 0 .. output_height-1 */ - /* Current input scan number and number of iMCU rows completed in scan. - * These indicate the progress of the decompressor input side. - */ int input_scan_number; /* Number of SOS markers seen so far */ JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ - /* The "output scan number" is the notional scan being displayed by the - * output side. The decompressor will not allow output scan/row number - * to get ahead of input scan/row, but it can fall arbitrarily far behind. - */ int output_scan_number; /* Nominal scan number being displayed */ JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ - /* Current progression status. coef_bits[c][i] indicates the precision - * with which component c's DCT coefficient i (in zigzag order) is known. - * It is -1 when no data has yet been received, otherwise it is the point - * transform (shift) value for the most recent scan of the coefficient - * (thus, 0 at completion of the progression). - * This pointer is NULL when reading a non-progressive file. - */ int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ - /* Internal JPEG parameters --- the application usually need not look at - * these fields. Note that the decompressor output side may not use - * any parameters that can change between scans. - */ - - /* Quantization and Huffman tables are carried forward across input - * datastreams when processing abbreviated JPEG datastreams. - */ - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - /* These parameters are never carried across datastreams, since they - * are given in SOF/SOS markers or defined to be reset by SOI. - */ int data_precision; /* bits of precision in image data */ jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ @@ -185890,11 +172988,7 @@ struct jpeg_decompress_struct { unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ - /* These fields record data obtained from optional markers recognized by - * the JPEG library. - */ boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ - /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ UINT8 JFIF_major_version; /* JFIF version number */ UINT8 JFIF_minor_version; UINT8 density_unit; /* JFIF code for pixel size units */ @@ -185905,63 +172999,30 @@ struct jpeg_decompress_struct { boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - /* Aside from the specific data retained from APPn markers known to the - * library, the uninterpreted contents of any or all APPn and COM markers - * can be saved in a list for examination by the application. - */ jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ - /* Remaining fields are known throughout decompressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during decompression startup - */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ - /* The coefficient controller's input and output progress is measured in - * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows - * in fully interleaved JPEG scans, but are used whether the scan is - * interleaved or not. We define an iMCU row as v_samp_factor DCT block - * rows of each component. Therefore, the IDCT output contains - * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. - */ JSAMPLE * sample_range_limit; /* table for fast range-limiting */ - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - * Note that the decompressor output side must not use these fields. - */ int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[D_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - /* This field is shared between entropy decoder and marker parser. - * It is either zero or the code of a JPEG marker that has been - * read from the data source, but has not yet been processed. - */ int unread_marker; - /* - * Links to decompression subobjects (methods, private variables of modules) - */ struct jpeg_decomp_master * master; struct jpeg_d_main_controller * main; struct jpeg_d_coef_controller * coef; @@ -185975,72 +173036,32 @@ struct jpeg_decompress_struct { struct jpeg_color_quantizer * cquantize; }; -/* "Object" declarations for JPEG modules that may be supplied or called - * directly by the surrounding application. - * As with all objects in the JPEG library, these structs only define the - * publicly visible methods and state variables of a module. Additional - * private fields may exist after the public ones. - */ - -/* Error handler object */ - struct jpeg_error_mgr { - /* Error exit handler: does not return to caller */ JMETHOD(void, error_exit, (j_common_ptr cinfo)); - /* Conditionally emit a trace or warning message */ JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); - /* Routine that actually outputs a trace or error message */ JMETHOD(void, output_message, (j_common_ptr cinfo)); - /* Format a message string for the most recent JPEG error or message */ JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); #define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ - /* Reset error state variables at start of a new image */ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); - /* The message ID code and any parameters are saved here. - * A message can have one string parameter or up to 8 int parameters. - */ int msg_code; #define JMSG_STR_PARM_MAX 80 union { - int i[8]; - char s[JMSG_STR_PARM_MAX]; + int i[8]; + char s[JMSG_STR_PARM_MAX]; } msg_parm; - /* Standard state variables for error facility */ - int trace_level; /* max msg_level that will be displayed */ - /* For recoverable corrupt-data errors, we emit a warning message, - * but keep going unless emit_message chooses to abort. emit_message - * should count warnings in num_warnings. The surrounding application - * can check for bad data by seeing if num_warnings is nonzero at the - * end of processing. - */ long num_warnings; /* number of corrupt-data warnings */ - /* These fields point to the table(s) of error message strings. - * An application can change the table pointer to switch to a different - * message list (typically, to change the language in which errors are - * reported). Some applications may wish to add additional error codes - * that will be handled by the JPEG library error mechanism; the second - * table pointer is used for this purpose. - * - * First table includes all errors generated by JPEG library itself. - * Error code 0 is reserved for a "no such error string" message. - */ const char * const * jpeg_message_table; /* Library errors */ - int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ - /* Second table can be added by application (see cjpeg/djpeg for example). - * It contains strings numbered first_addon_message..last_addon_message. - */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ const char * const * addon_message_table; /* Non-library errors */ int first_addon_message; /* code for first string in addon table */ int last_addon_message; /* code for last string in addon table */ }; -/* Progress monitor object */ - struct jpeg_progress_mgr { JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); @@ -186050,8 +173071,6 @@ struct jpeg_progress_mgr { int total_passes; /* total number of passes expected */ }; -/* Data destination object for compression */ - struct jpeg_destination_mgr { JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ @@ -186061,8 +173080,6 @@ struct jpeg_destination_mgr { JMETHOD(void, term_destination, (j_compress_ptr cinfo)); }; -/* Data source object for decompression */ - struct jpeg_source_mgr { const JOCTET * next_input_byte; /* => next byte to read from buffer */ size_t bytes_in_buffer; /* # of bytes remaining in buffer */ @@ -186074,17 +173091,6 @@ struct jpeg_source_mgr { JMETHOD(void, term_source, (j_decompress_ptr cinfo)); }; -/* Memory manager object. - * Allocates "small" objects (a few K total), "large" objects (tens of K), - * and "really big" objects (virtual arrays with backing store if needed). - * The memory manager does not allow individual objects to be freed; rather, - * each created object is assigned to a pool, and whole pools can be freed - * at once. This is faster and more convenient than remembering exactly what - * to free, especially where malloc()/free() are not too speedy. - * NB: alloc routines never return NULL. They exit to error_exit if not - * successful. - */ - #define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ #define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ #define JPOOL_NUMPOOLS 2 @@ -186093,17 +173099,16 @@ typedef struct jvirt_sarray_control * jvirt_sarray_ptr; typedef struct jvirt_barray_control * jvirt_barray_ptr; struct jpeg_memory_mgr { - /* Method pointers */ JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, size_t sizeofobject)); JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); + size_t sizeofobject)); JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, - JDIMENSION numrows)); + JDIMENSION samplesperrow, + JDIMENSION numrows)); JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, - JDIMENSION numrows)); + JDIMENSION blocksperrow, + JDIMENSION numrows)); JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, int pool_id, boolean pre_zero, @@ -186123,47 +173128,26 @@ struct jpeg_memory_mgr { JDIMENSION num_rows, boolean writable)); JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, - jvirt_barray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); JMETHOD(void, self_destruct, (j_common_ptr cinfo)); - /* Limit on memory allocation for this JPEG object. (Note that this is - * merely advisory, not a guaranteed maximum; it only affects the space - * used for virtual-array buffers.) May be changed by outer application - * after creating the JPEG object. - */ long max_memory_to_use; - /* Maximum allocation request accepted by alloc_large. */ long max_alloc_chunk; }; -/* Routine signature for application-supplied marker processing methods. - * Need not pass marker code since it is stored in cinfo->unread_marker. - */ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); -/* Declarations for routines called by application. - * The JPP macro hides prototype parameters from compilers that can't cope. - * Note JPP requires double parentheses. - */ - #ifdef HAVE_PROTOTYPES #define JPP(arglist) arglist #else #define JPP(arglist) () #endif -/* Short forms of external names for systems with brain-damaged linkers. - * We shorten external names to be unique in the first six letters, which - * is good enough for all known systems. - * (If your compiler itself needs names to be unique in less than 15 - * characters, you are out of luck. Get a better compiler.) - */ - #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_std_error jStdError #define jpeg_CreateCompress jCreaCompress @@ -186215,41 +173199,28 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); #define jpeg_resync_to_restart jResyncRestart #endif /* NEED_SHORT_EXTERNAL_NAMES */ -/* Default error-management setup */ EXTERN(struct jpeg_error_mgr *) jpeg_std_error JPP((struct jpeg_error_mgr * err)); -/* Initialization of JPEG compression objects. - * jpeg_create_compress() and jpeg_create_decompress() are the exported - * names that applications should call. These expand to calls on - * jpeg_CreateCompress and jpeg_CreateDecompress with additional information - * passed for version mismatch checking. - * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. - */ #define jpeg_create_compress(cinfo) \ - jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ (size_t) sizeof(struct jpeg_compress_struct)) #define jpeg_create_decompress(cinfo) \ - jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ (size_t) sizeof(struct jpeg_decompress_struct)) EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, - int version, size_t structsize)); + int version, size_t structsize)); EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, int version, size_t structsize)); -/* Destruction of JPEG compression objects */ EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); -/* Standard data source and destination managers: stdio streams. */ -/* Caller is responsible for opening the file before and closing after. */ EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); -/* Default parameter setup for compression */ EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); -/* Compression parameter setup aids */ EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, - J_COLOR_SPACE colorspace)); + J_COLOR_SPACE colorspace)); EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, boolean force_baseline)); @@ -186257,135 +173228,95 @@ EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, int scale_factor, boolean force_baseline)); EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, - boolean force_baseline)); + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); EXTERN(int) jpeg_quality_scaling JPP((int quality)); EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, - boolean suppress)); + boolean suppress)); EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); -/* Main entry points for compression */ EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, - boolean write_all_tables)); + boolean write_all_tables)); EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION num_lines)); + JSAMPARRAY scanlines, + JDIMENSION num_lines)); EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); -/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION num_lines)); + JSAMPIMAGE data, + JDIMENSION num_lines)); -/* Write a special marker. See libjpeg.doc concerning safe usage. */ EXTERN(void) jpeg_write_marker JPP((j_compress_ptr cinfo, int marker, - const JOCTET * dataptr, unsigned int datalen)); -/* Same, but piecemeal. */ + const JOCTET * dataptr, unsigned int datalen)); EXTERN(void) jpeg_write_m_header JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); EXTERN(void) jpeg_write_m_byte JPP((j_compress_ptr cinfo, int val)); -/* Alternate compression function: just write an abbreviated table file */ EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); -/* Decompression startup: read start of JPEG datastream to see what's there */ EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, boolean require_image)); -/* Return value is one of: */ #define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ #define JPEG_HEADER_OK 1 /* Found valid image datastream */ #define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ -/* If you pass require_image = TRUE (normal case), you need not check for - * a TABLES_ONLY return code; an abbreviated file will cause an error exit. - * JPEG_SUSPENDED is only possible if you use a data source module that can - * give a suspension return (the stdio source module doesn't). - */ -/* Main entry points for decompression */ EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION max_lines)); + JSAMPARRAY scanlines, + JDIMENSION max_lines)); EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); -/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, JSAMPIMAGE data, JDIMENSION max_lines)); -/* Additional entry points for buffered-image mode. */ EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, - int scan_number)); + int scan_number)); EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); -/* Return value is one of: */ -/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ #define JPEG_REACHED_SOS 1 /* Reached start of new scan */ #define JPEG_REACHED_EOI 2 /* Reached end of image */ #define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ #define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ -/* Precalculate output dimensions for current decompression parameters. */ EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); -/* Control saving of COM and APPn markers into marker_list. */ EXTERN(void) jpeg_save_markers JPP((j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit)); + unsigned int length_limit)); -/* Install a special processing method for COM or APPn markers. */ EXTERN(void) jpeg_set_marker_processor JPP((j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine)); + jpeg_marker_parser_method routine)); -/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo)); -/* If you choose to abort compression or decompression before completing - * jpeg_finish_(de)compress, then you need to clean up to release memory, - * temporary files, etc. You can just call jpeg_destroy_(de)compress - * if you're done with the JPEG object, but if you want to clean it up and - * reuse it, call this: - */ EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); -/* Generic versions of jpeg_abort and jpeg_destroy that work on either - * flavor of JPEG object. These may be more convenient in some places. - */ EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); -/* Default restart-marker-resync procedure for use by data source modules */ EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, - int desired)); - -/* These marker codes are exported since applications and data source modules - * are likely to want to use them. - */ + int desired)); #define JPEG_RST0 0xD0 /* RST0 marker code */ #define JPEG_EOI 0xD9 /* EOI marker code */ #define JPEG_APP0 0xE0 /* APP0 marker code */ #define JPEG_COM 0xFE /* COM marker code */ -/* If we have a brain-damaged compiler that emits warnings (or worse, errors) - * for structure definitions that are never filled in, keep it quiet by - * supplying dummy definitions for the various substructures. - */ - #ifdef INCOMPLETE_TYPES_BROKEN #ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ struct jvirt_sarray_control { long dummy; }; @@ -186413,27 +173344,17 @@ struct jpeg_color_quantizer { long dummy; }; #endif /* JPEG_INTERNALS */ #endif /* INCOMPLETE_TYPES_BROKEN */ -/* - * The JPEG library modules define JPEG_INTERNALS before including this file. - * The internal structure declarations are read only when that is true. - * Applications using the library should not include jpegint.h, but may wish - * to include jerror.h. - */ - #ifdef JPEG_INTERNALS /********* Start of inlined file: jpegint.h *********/ -/* Declarations for both compression & decompression */ typedef enum { /* Operating modes for buffer controllers */ JBUF_PASS_THRU, /* Plain stripwise operation */ - /* Remaining modes require a full-image buffer to have been created */ JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ } J_BUF_MODE; -/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ #define CSTATE_START 100 /* after create_compress */ #define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ #define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ @@ -186450,28 +173371,22 @@ typedef enum { /* Operating modes for buffer controllers */ #define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ #define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ -/* Declarations for compression modules */ - -/* Master control module */ struct jpeg_comp_master { JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); - /* State variables made visible to other modules */ boolean call_pass_startup; /* True if pass_startup must be called */ boolean is_last_pass; /* True during last pass */ }; -/* Main buffer control (downsampled-data buffer) */ struct jpeg_c_main_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail)); + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); }; -/* Compression preprocessing (downsampling input buffer control) */ struct jpeg_c_prep_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, @@ -186483,14 +173398,12 @@ struct jpeg_c_prep_controller { JDIMENSION out_row_groups_avail)); }; -/* Coefficient buffer control */ struct jpeg_c_coef_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, JSAMPIMAGE input_buf)); }; -/* Colorspace conversion */ struct jpeg_color_converter { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); JMETHOD(void, color_convert, (j_compress_ptr cinfo, @@ -186498,135 +173411,105 @@ struct jpeg_color_converter { JDIMENSION output_row, int num_rows)); }; -/* Downsampling */ struct jpeg_downsampler { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); JMETHOD(void, downsample, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_index, - JSAMPIMAGE output_buf, - JDIMENSION out_row_group_index)); + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); boolean need_context_rows; /* TRUE if need rows above & below */ }; -/* Forward DCT (also controls coefficient quantization) */ struct jpeg_forward_dct { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - /* perhaps this should be an array??? */ JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, - jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks)); + jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); }; -/* Entropy encoding */ struct jpeg_entropy_encoder { JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); }; -/* Marker writing */ struct jpeg_marker_writer { JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); - /* These routines are exported to allow insertion of extra markers */ - /* Probably only COM and APPn markers should be written this way */ JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, - unsigned int datalen)); + unsigned int datalen)); JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); }; -/* Declarations for decompression modules */ - -/* Master control module */ struct jpeg_decomp_master { JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); - /* State variables made visible to other modules */ boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ }; -/* Input control module */ struct jpeg_input_controller { JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); - /* State variables made visible to other modules */ boolean has_multiple_scans; /* True if file has multiple scans */ boolean eoi_reached; /* True when EOI has been consumed */ }; -/* Main buffer control (downsampled-data buffer) */ struct jpeg_d_main_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, process_data, (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); }; -/* Coefficient buffer control */ struct jpeg_d_coef_controller { JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); - /* Pointer to array of coefficient virtual arrays, or NULL if none */ jvirt_barray_ptr *coef_arrays; }; -/* Decompression postprocessing (color quantization buffer control) */ struct jpeg_d_post_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); }; -/* Marker reading & parsing */ struct jpeg_marker_reader { JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); - /* Read markers until SOS or EOI. - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - */ JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); - /* Read a restart marker --- exported for use by entropy decoder only */ jpeg_marker_parser_method read_restart_marker; - /* State of marker reader --- nominally internal, but applications - * supplying COM or APPn handlers might like to know the state. - */ boolean saw_SOI; /* found SOI? */ boolean saw_SOF; /* found SOF? */ int next_restart_num; /* next restart number expected (0-7) */ unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ }; -/* Entropy decoding */ struct jpeg_entropy_decoder { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); - /* This is here to share code between baseline and progressive decoders; */ - /* other modules probably should not use it */ boolean insufficient_data; /* set TRUE after emitting warning */ }; -/* Inverse DCT (also performs dequantization) */ typedef JMETHOD(void, inverse_DCT_method_ptr, (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, @@ -186634,11 +173517,9 @@ typedef JMETHOD(void, inverse_DCT_method_ptr, struct jpeg_inverse_dct { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - /* It is useful to allow each component to have a separate IDCT method. */ inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; }; -/* Upsampling (note that upsampler must also call color converter) */ struct jpeg_upsampler { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(void, upsample, (j_decompress_ptr cinfo, @@ -186652,7 +173533,6 @@ struct jpeg_upsampler { boolean need_context_rows; /* TRUE if need rows above & below */ }; -/* Colorspace conversion */ struct jpeg_color_deconverter { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(void, color_convert, (j_decompress_ptr cinfo, @@ -186660,7 +173540,6 @@ struct jpeg_color_deconverter { JSAMPARRAY output_buf, int num_rows)); }; -/* Color quantization or color precision reduction */ struct jpeg_color_quantizer { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, @@ -186670,23 +173549,11 @@ struct jpeg_color_quantizer { JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); }; -/* Miscellaneous useful macros */ - #undef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #undef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) -/* We assume that right shift corresponds to signed division by 2 with - * rounding towards minus infinity. This is correct for typical "arithmetic - * shift" instructions that shift in copies of the sign bit. But some - * C compilers implement >> with an unsigned shift. For these machines you - * must define RIGHT_SHIFT_IS_UNSIGNED. - * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. - * It is only applied with constant shift counts. SHIFT_TEMPS must be - * included in the variables of any routine using RIGHT_SHIFT. - */ - #ifdef RIGHT_SHIFT_IS_UNSIGNED #define SHIFT_TEMPS INT32 shift_temp; #define RIGHT_SHIFT(x,shft) \ @@ -186698,8 +173565,6 @@ struct jpeg_color_quantizer { #define RIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif -/* Short forms of external names for systems with brain-damaged linkers. */ - #ifdef NEED_SHORT_EXTERNAL_NAMES #define jinit_compress_master jICompress #define jinit_c_master_control jICMaster @@ -186736,7 +173601,6 @@ struct jpeg_color_quantizer { #define jpeg_natural_order jZAGTable #endif /* NEED_SHORT_EXTERNAL_NAMES */ -/* Compression module initialization routines */ EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, boolean transcode_only)); @@ -186752,7 +173616,6 @@ EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); -/* Decompression module initialization routines */ EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); @@ -186770,26 +173633,21 @@ EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); -/* Memory manager initialization */ EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); -/* Utility routines in jutils.c */ EXTERN(long) jdiv_round_up JPP((long a, long b)); EXTERN(long) jround_up JPP((long a, long b)); EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols)); + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks)); EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); -/* Constant tables in jutils.c */ #if 0 /* This table is not actually needed in v6a */ extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ #endif extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ -/* Suppress undefined-structure complaints if necessary. */ - #ifdef INCOMPLETE_TYPES_BROKEN #ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ struct jvirt_sarray_control { long dummy; }; @@ -186798,20 +173656,11 @@ struct jvirt_barray_control { long dummy; }; #endif /* INCOMPLETE_TYPES_BROKEN */ /********* End of inlined file: jpegint.h *********/ - /* fetch private declarations */ - /********* Start of inlined file: jerror.h *********/ -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ #ifndef JMESSAGE #ifndef JERROR_H -/* First time through, define the enum list */ #define JMAKE_ENUM_LIST #else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ #define JMESSAGE(code,string) #endif /* JERROR_H */ #endif /* JMESSAGE */ @@ -186826,7 +173675,6 @@ typedef enum { JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ -/* For maintenance convenience, list is alphabetical by message code name */ JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, there are legal restrictions on arithmetic coding") JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") @@ -186979,16 +173827,11 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #undef JMAKE_ENUM_LIST #endif /* JMAKE_ENUM_LIST */ -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ #undef JMESSAGE #ifndef JERROR_H #define JERROR_H -/* Macros to simplify using the error and trace message stuff */ -/* The first parameter is either type of cinfo pointer */ - -/* Fatal errors (print message and exit) */ #define ERREXIT(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) @@ -187021,7 +173864,6 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #define MAKESTMT(stuff) do { stuff } while (0) -/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ #define WARNMS(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) @@ -187035,7 +173877,6 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -/* Informational/debugging messages */ #define TRACEMS(cinfo,lvl,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) @@ -187078,7 +173919,6 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #endif /* JERROR_H */ /********* End of inlined file: jerror.h *********/ - /* fetch error codes too */ #endif #endif /* JPEGLIB_H */ @@ -187088,13 +173928,11 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #define JPEG_INTERNALS /********* Start of inlined file: jinclude.h *********/ -/* Include auto-config file to find out which system include files we need. */ #ifndef __jinclude_h__ #define __jinclude_h__ /********* Start of inlined file: jconfig.h *********/ -/* see jconfig.doc for explanations */ // disable all the warnings under MSVC #ifdef _MSC_VER @@ -187111,8 +173949,6 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT -/* #define void char */ -/* #define const */ #undef CHAR_IS_UNSIGNED #define HAVE_STDDEF_H #define HAVE_STDLIB_H @@ -187122,7 +173958,6 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #undef NEED_SHORT_EXTERNAL_NAMES #undef INCOMPLETE_TYPES_BROKEN -/* Define "boolean" as unsigned char, not int, per Windows custom */ #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ typedef unsigned char boolean; #endif @@ -187151,20 +173986,8 @@ typedef unsigned char boolean; #endif /* JPEG_CJPEG_DJPEG */ /********* End of inlined file: jconfig.h *********/ - /* auto configuration options */ #define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ -/* - * We need the NULL macro and size_t typedef. - * On an ANSI-conforming system it is sufficient to include . - * Otherwise, we get them from or ; we may have to - * pull in as well. - * Note that the core JPEG library does not require ; - * only the default error handler and data source/destination modules do. - * But we must pull it in because of the references to FILE in jpeglib.h. - * You can remove those references if you want to compile without . - */ - #ifdef HAVE_STDDEF_H #include #endif @@ -187179,16 +174002,6 @@ typedef unsigned char boolean; #include -/* - * We need memory copying and zeroing functions, plus strncpy(). - * ANSI and System V implementations declare these in . - * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). - * Some systems may declare memset and memcpy in . - * - * NOTE: we assume the size parameters to these functions are of type size_t. - * Change the casts in these macros if not! - */ - #ifdef NEED_BSD_STRINGS #include @@ -187203,22 +174016,8 @@ typedef unsigned char boolean; #endif -/* - * In ANSI C, and indeed any rational implementation, size_t is also the - * type returned by sizeof(). However, it seems there are some irrational - * implementations out there, in which sizeof() returns an int even though - * size_t is defined as long or unsigned long. To ensure consistent results - * we always use this SIZEOF() macro in place of using sizeof() directly. - */ - #define SIZEOF(object) ((size_t) sizeof(object)) -/* - * The modules that use fread() and fwrite() always invoke them through - * these macros. On some systems you may need to twiddle the argument casts. - * CAUTION: argument order is different from underlying functions! - */ - #define JFREAD(file,buf,sizeofbuf) \ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) #define JFWRITE(file,buf,sizeofbuf) \ @@ -187291,11 +174090,6 @@ typedef enum { /* JPEG marker codes */ M_ERROR = 0x100 } JPEG_MARKER; -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - #ifdef AVOID_TABLES #define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) @@ -187306,110 +174100,74 @@ typedef enum { /* JPEG marker codes */ static const int extend_test[16] = /* entry n is 2**(n-1) */ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; #endif /* AVOID_TABLES */ #endif /********* End of inlined file: jinclude.h *********/ -/* - * Initialization of a JPEG compression object. - * The error manager must already be set up (in case memory manager fails). - */ - GLOBAL(void) jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) { int i; - /* Guard against version mismatches between library and caller. */ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ if (version != JPEG_LIB_VERSION) - ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); if (structsize != SIZEOF(struct jpeg_compress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, - (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); - /* For debugging purposes, we zero the whole master structure. - * But the application has already set the err pointer, and may have set - * client_data, so we have to save and restore those fields. - * Note: if application hasn't set client_data, tools like Purify may - * complain here. - */ { - struct jpeg_error_mgr * err = cinfo->err; - void * client_data = cinfo->client_data; /* ignore Purify complaint here */ - MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); - cinfo->err = err; - cinfo->client_data = client_data; + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; } cinfo->is_decompressor = FALSE; - /* Initialize a memory manager instance for this object */ jinit_memory_mgr((j_common_ptr) cinfo); - /* Zero out pointers to permanent structures. */ cinfo->progress = NULL; cinfo->dest = NULL; cinfo->comp_info = NULL; for (i = 0; i < NUM_QUANT_TBLS; i++) - cinfo->quant_tbl_ptrs[i] = NULL; + cinfo->quant_tbl_ptrs[i] = NULL; for (i = 0; i < NUM_HUFF_TBLS; i++) { - cinfo->dc_huff_tbl_ptrs[i] = NULL; - cinfo->ac_huff_tbl_ptrs[i] = NULL; + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; } cinfo->script_space = NULL; cinfo->input_gamma = 1.0; /* in case application forgets */ - /* OK, I'm ready */ cinfo->global_state = CSTATE_START; } -/* - * Destruction of a JPEG compression object - */ - GLOBAL(void) jpeg_destroy_compress (j_compress_ptr cinfo) { jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ } -/* - * Abort processing of a JPEG compression operation, - * but don't destroy the object itself. - */ - GLOBAL(void) jpeg_abort_compress (j_compress_ptr cinfo) { jpeg_abort((j_common_ptr) cinfo); /* use common routine */ } -/* - * Forcibly suppress or un-suppress all quantization and Huffman tables. - * Marks all currently defined tables as already written (if suppress) - * or not written (if !suppress). This will control whether they get emitted - * by a subsequent jpeg_start_compress call. - * - * This routine is exported for use by applications that want to produce - * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but - * since it is called by jpeg_start_compress, we put it here --- otherwise - * jcparam.o would be linked whether the application used it or not. - */ - GLOBAL(void) jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) { @@ -187418,69 +174176,48 @@ jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) JHUFF_TBL * htbl; for (i = 0; i < NUM_QUANT_TBLS; i++) { - if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) - qtbl->sent_table = suppress; + if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) + qtbl->sent_table = suppress; } for (i = 0; i < NUM_HUFF_TBLS; i++) { - if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) - htbl->sent_table = suppress; - if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) - htbl->sent_table = suppress; + if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; } } -/* - * Finish JPEG compression. - * - * If a multipass operating mode was selected, this may do a great deal of - * work including most of the actual output. - */ - GLOBAL(void) jpeg_finish_compress (j_compress_ptr cinfo) { JDIMENSION iMCU_row; if (cinfo->global_state == CSTATE_SCANNING || - cinfo->global_state == CSTATE_RAW_OK) { - /* Terminate first pass */ - if (cinfo->next_scanline < cinfo->image_height) - ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); - (*cinfo->master->finish_pass) (cinfo); + cinfo->global_state == CSTATE_RAW_OK) { + if (cinfo->next_scanline < cinfo->image_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_pass) (cinfo); } else if (cinfo->global_state != CSTATE_WRCOEFS) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Perform any remaining passes */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); while (! cinfo->master->is_last_pass) { - (*cinfo->master->prepare_for_pass) (cinfo); - for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { - if (cinfo->progress != NULL) { + (*cinfo->master->prepare_for_pass) (cinfo); + for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { + if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) iMCU_row; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - /* We bypass the main controller and invoke coef controller directly; - * all work is being done from the coefficient buffer. - */ - if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) + } + if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) ERREXIT(cinfo, JERR_CANT_SUSPEND); - } - (*cinfo->master->finish_pass) (cinfo); + } + (*cinfo->master->finish_pass) (cinfo); } - /* Write EOI, do final cleanup */ (*cinfo->marker->write_file_trailer) (cinfo); (*cinfo->dest->term_destination) (cinfo); - /* We can use jpeg_abort to release memory and reset global_state */ jpeg_abort((j_common_ptr) cinfo); } -/* - * Write a special marker. - * This is only recommended for writing COM or APPn markers. - * Must be called after jpeg_start_compress() and before - * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). - */ - GLOBAL(void) jpeg_write_marker (j_compress_ptr cinfo, int marker, const JOCTET *dataptr, unsigned int datalen) @@ -187488,29 +174225,27 @@ jpeg_write_marker (j_compress_ptr cinfo, int marker, JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); if (cinfo->next_scanline != 0 || - (cinfo->global_state != CSTATE_SCANNING && - cinfo->global_state != CSTATE_RAW_OK && - cinfo->global_state != CSTATE_WRCOEFS)) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ while (datalen--) { - (*write_marker_byte) (cinfo, *dataptr); - dataptr++; + (*write_marker_byte) (cinfo, *dataptr); + dataptr++; } } -/* Same, but piecemeal. */ - GLOBAL(void) jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) { if (cinfo->next_scanline != 0 || - (cinfo->global_state != CSTATE_SCANNING && - cinfo->global_state != CSTATE_RAW_OK && - cinfo->global_state != CSTATE_WRCOEFS)) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); } @@ -187521,143 +174256,63 @@ jpeg_write_m_byte (j_compress_ptr cinfo, int val) (*cinfo->marker->write_marker_byte) (cinfo, val); } -/* - * Alternate compression function: just write an abbreviated table file. - * Before calling this, all parameters and a data destination must be set up. - * - * To produce a pair of files containing abbreviated tables and abbreviated - * image data, one would proceed as follows: - * - * initialize JPEG object - * set JPEG parameters - * set destination to table file - * jpeg_write_tables(cinfo); - * set destination to image file - * jpeg_start_compress(cinfo, FALSE); - * write data... - * jpeg_finish_compress(cinfo); - * - * jpeg_write_tables has the side effect of marking all tables written - * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress - * will not re-emit the tables unless it is passed write_all_tables=TRUE. - */ - GLOBAL(void) jpeg_write_tables (j_compress_ptr cinfo) { if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); - /* Initialize the marker writer ... bit of a crock to do it here. */ jinit_marker_writer(cinfo); - /* Write them tables! */ (*cinfo->marker->write_tables_only) (cinfo); - /* And clean up. */ (*cinfo->dest->term_destination) (cinfo); - /* - * In library releases up through v6a, we called jpeg_abort() here to free - * any working memory allocated by the destination manager and marker - * writer. Some applications had a problem with that: they allocated space - * of their own from the library memory manager, and didn't want it to go - * away during write_tables. So now we do nothing. This will cause a - * memory leak if an app calls write_tables repeatedly without doing a full - * compression cycle or otherwise resetting the JPEG object. However, that - * seems less bad than unexpectedly freeing memory in the normal case. - * An app that prefers the old behavior can call jpeg_abort for itself after - * each call to jpeg_write_tables(). - */ } /********* End of inlined file: jcapimin.c *********/ /********* Start of inlined file: jcapistd.c *********/ #define JPEG_INTERNALS -/* - * Compression initialization. - * Before calling this, all parameters and a data destination must be set up. - * - * We require a write_all_tables parameter as a failsafe check when writing - * multiple datastreams from the same compression object. Since prior runs - * will have left all the tables marked sent_table=TRUE, a subsequent run - * would emit an abbreviated stream (no tables) by default. This may be what - * is wanted, but for safety's sake it should not be the default behavior: - * programmers should have to make a deliberate choice to emit abbreviated - * images. Therefore the documentation and examples should encourage people - * to pass write_all_tables=TRUE; then it will take active thought to do the - * wrong thing. - */ - GLOBAL(void) jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) { if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (write_all_tables) - jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ + jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ - /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); - /* Perform master selection of active modules */ jinit_compress_master(cinfo); - /* Set up for the first pass */ (*cinfo->master->prepare_for_pass) (cinfo); - /* Ready for application to drive first pass through jpeg_write_scanlines - * or jpeg_write_raw_data. - */ cinfo->next_scanline = 0; cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); } -/* - * Write some scanlines of data to the JPEG compressor. - * - * The return value will be the number of lines actually written. - * This should be less than the supplied num_lines only in case that - * the data destination module has requested suspension of the compressor, - * or if more than image_height scanlines are passed in. - * - * Note: we warn about excess calls to jpeg_write_scanlines() since - * this likely signals an application programmer error. However, - * excess scanlines passed in the last valid call are *silently* ignored, - * so that the application need not adjust num_lines for end-of-image - * when using a multiple-scanline buffer. - */ - GLOBAL(JDIMENSION) jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION num_lines) + JDIMENSION num_lines) { JDIMENSION row_ctr, rows_left; if (cinfo->global_state != CSTATE_SCANNING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->next_scanline >= cinfo->image_height) - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->next_scanline; - cinfo->progress->pass_limit = (long) cinfo->image_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } - /* Give master control module another chance if this is first call to - * jpeg_write_scanlines. This lets output of the frame/scan headers be - * delayed so that application can write COM, etc, markers between - * jpeg_start_compress and jpeg_write_scanlines. - */ if (cinfo->master->call_pass_startup) - (*cinfo->master->pass_startup) (cinfo); + (*cinfo->master->pass_startup) (cinfo); - /* Ignore any extra scanlines at bottom of image. */ rows_left = cinfo->image_height - cinfo->next_scanline; if (num_lines > rows_left) - num_lines = rows_left; + num_lines = rows_left; row_ctr = 0; (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); @@ -187665,51 +174320,36 @@ jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, return row_ctr; } -/* - * Alternate entry point to write raw data. - * Processes exactly one iMCU row per call, unless suspended. - */ - GLOBAL(JDIMENSION) jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION num_lines) + JDIMENSION num_lines) { JDIMENSION lines_per_iMCU_row; if (cinfo->global_state != CSTATE_RAW_OK) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->next_scanline >= cinfo->image_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; } - /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->next_scanline; - cinfo->progress->pass_limit = (long) cinfo->image_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } - /* Give master control module another chance if this is first call to - * jpeg_write_raw_data. This lets output of the frame/scan headers be - * delayed so that application can write COM, etc, markers between - * jpeg_start_compress and jpeg_write_raw_data. - */ if (cinfo->master->call_pass_startup) - (*cinfo->master->pass_startup) (cinfo); + (*cinfo->master->pass_startup) (cinfo); - /* Verify that at least one iMCU row has been passed. */ lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; if (num_lines < lines_per_iMCU_row) - ERREXIT(cinfo, JERR_BUFFER_SIZE); + ERREXIT(cinfo, JERR_BUFFER_SIZE); - /* Directly compress the row. */ if (! (*cinfo->coef->compress_data) (cinfo, data)) { - /* If compressor did not consume the whole row, suspend processing. */ - return 0; + return 0; } - /* OK, we processed one iMCU row. */ cinfo->next_scanline += lines_per_iMCU_row; return lines_per_iMCU_row; } @@ -187718,11 +174358,6 @@ jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, /********* Start of inlined file: jccoefct.c *********/ #define JPEG_INTERNALS -/* We use a full-image coefficient buffer when doing Huffman optimization, - * and also for writing multiple-scan JPEG files. In all cases, the DCT - * step is run during the first pass, and subsequent passes need only read - * the buffered coefficients. - */ #ifdef ENTROPY_OPT_SUPPORTED #define FULL_COEF_BUFFER_SUPPORTED #else @@ -187731,8 +174366,6 @@ jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, #endif #endif -/* Private buffer controller object */ - typedef struct { struct jpeg_c_coef_controller pub; /* public fields */ @@ -187741,60 +174374,40 @@ typedef struct { int MCU_vert_offset; /* counts MCU rows within iMCU row */ int MCU_rows_per_iMCU_row; /* number of such rows needed */ - /* For single-pass compression, it's sufficient to buffer just one MCU - * (although this may prove a bit slow in practice). We allocate a - * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each - * MCU constructed and sent. (On 80x86, the workspace is FAR even though - * it's not really very big; this is to keep the module interfaces unchanged - * when a large coefficient buffer is necessary.) - * In multi-pass modes, this array points to the current MCU's blocks - * within the virtual arrays. - */ JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; - /* In multi-pass modes, we need a virtual block array for each component. */ jvirt_barray_ptr whole_image[MAX_COMPONENTS]; } my_coef_controller; typedef my_coef_controller * my_coef_ptr; -/* Forward declarations */ METHODDEF(boolean) compress_data - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); #ifdef FULL_COEF_BUFFER_SUPPORTED METHODDEF(boolean) compress_first_pass - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); METHODDEF(boolean) compress_output - JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); #endif LOCAL(void) start_iMCU_row (j_compress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row */ { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; + coef->MCU_rows_per_iMCU_row = 1; } else { - if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; } coef->mcu_ctr = 0; coef->MCU_vert_offset = 0; } -/* - * Initialize for a processing pass. - */ - METHODDEF(void) start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { @@ -187805,38 +174418,28 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) switch (pass_mode) { case JBUF_PASS_THRU: - if (coef->whole_image[0] != NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_data; - break; + if (coef->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_data; + break; #ifdef FULL_COEF_BUFFER_SUPPORTED case JBUF_SAVE_AND_PASS: - if (coef->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_first_pass; - break; + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_first_pass; + break; case JBUF_CRANK_DEST: - if (coef->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - coef->pub.compress_data = compress_output; - break; + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_output; + break; #endif default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; } } -/* - * Process some data in the single-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the image. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf contains a plane for each component in image, - * which we index according to the component's SOF position. - */ - METHODDEF(boolean) compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { @@ -187848,22 +174451,12 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) JDIMENSION ypos, xpos; jpeg_component_info *compptr; - /* Loop to write as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { - /* Determine where data comes from in input_buf and do the DCT thing. - * Each call on forward_DCT processes a horizontal row of DCT blocks - * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks - * sequentially. Dummy blocks at the right or bottom edge are filled in - * specially. The data in them does not matter for image reconstruction, - * so we fill them with values that will encode to the smallest amount of - * data, viz: all zeroes in the AC entries, DC entries equal to previous - * block's DC value. (Thanks to Thomas Kinsman for this idea.) - */ - blkn = 0; - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + blkn = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; @@ -187871,45 +174464,37 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || - yoffset+yindex < compptr->last_row_height) { - (*cinfo->fdct->forward_DCT) (cinfo, compptr, + yoffset+yindex < compptr->last_row_height) { + (*cinfo->fdct->forward_DCT) (cinfo, compptr, input_buf[compptr->component_index], coef->MCU_buffer[blkn], ypos, xpos, (JDIMENSION) blockcnt); - if (blockcnt < compptr->MCU_width) { - /* Create some dummy blocks at the right edge of the image. */ - jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], + if (blockcnt < compptr->MCU_width) { + jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); - for (bi = blockcnt; bi < compptr->MCU_width; bi++) { + for (bi = blockcnt; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; - } - } + } + } } else { - /* Create a row of dummy blocks at the bottom of the image. */ - jzero_far((void FAR *) coef->MCU_buffer[blkn], - compptr->MCU_width * SIZEOF(JBLOCK)); - for (bi = 0; bi < compptr->MCU_width; bi++) { - coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; - } + jzero_far((void FAR *) coef->MCU_buffer[blkn], + compptr->MCU_width * SIZEOF(JBLOCK)); + for (bi = 0; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; + } } blkn += compptr->MCU_width; ypos += DCTSIZE; } - } - /* Try to write the MCU. In event of a suspension failure, we will - * re-DCT the MCU on restart (a bit inefficient, could be fixed...) - */ - if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ + } + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; return FALSE; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->mcu_ctr = 0; + } + } + coef->mcu_ctr = 0; } - /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; @@ -187917,27 +174502,6 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) #ifdef FULL_COEF_BUFFER_SUPPORTED -/* - * Process some data in the first pass of a multi-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the image. - * This amount of data is read from the source buffer, DCT'd and quantized, - * and saved into the virtual arrays. We also generate suitable dummy blocks - * as needed at the right and lower edges. (The dummy blocks are constructed - * in the virtual arrays, which have been padded appropriately.) This makes - * it possible for subsequent passes not to worry about real vs. dummy blocks. - * - * We must also emit the data to the entropy encoder. This is conveniently - * done by calling compress_output() after we've loaded the current strip - * of the virtual arrays. - * - * NB: input_buf contains a plane for each component in image. All - * components are DCT'd and loaded into the virtual arrays in this pass. - * However, it may be that only a subset of the components are emitted to - * the entropy encoder during this first pass; be careful about looking - * at the scan-dependent variables (MCU dimensions, etc). - */ - METHODDEF(boolean) compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { @@ -187951,54 +174515,41 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) JBLOCKROW thisblockrow, lastblockrow; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Align the virtual buffer for this component. */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - coef->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, TRUE); - /* Count non-dummy DCT block rows in this iMCU row. */ - if (coef->iMCU_row_num < last_iMCU_row) - block_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here, since may not be set! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - } - blocks_across = compptr->width_in_blocks; - h_samp_factor = compptr->h_samp_factor; - /* Count number of dummy blocks to be added at the right margin. */ - ndummy = (int) (blocks_across % h_samp_factor); - if (ndummy > 0) - ndummy = h_samp_factor - ndummy; - /* Perform DCT for all non-dummy blocks in this iMCU row. Each call - * on forward_DCT processes a complete horizontal row of DCT blocks. - */ - for (block_row = 0; block_row < block_rows; block_row++) { - thisblockrow = buffer[block_row]; - (*cinfo->fdct->forward_DCT) (cinfo, compptr, + ci++, compptr++) { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + if (coef->iMCU_row_num < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + blocks_across = compptr->width_in_blocks; + h_samp_factor = compptr->h_samp_factor; + ndummy = (int) (blocks_across % h_samp_factor); + if (ndummy > 0) + ndummy = h_samp_factor - ndummy; + for (block_row = 0; block_row < block_rows; block_row++) { + thisblockrow = buffer[block_row]; + (*cinfo->fdct->forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow, (JDIMENSION) (block_row * DCTSIZE), (JDIMENSION) 0, blocks_across); - if (ndummy > 0) { - /* Create dummy blocks at the right edge of the image. */ + if (ndummy > 0) { thisblockrow += blocks_across; /* => first dummy block */ jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); lastDC = thisblockrow[-1][0]; for (bi = 0; bi < ndummy; bi++) { thisblockrow[bi][0] = lastDC; } - } - } - /* If at end of image, create dummy block rows as needed. - * The tricky part here is that within each MCU, we want the DC values - * of the dummy blocks to match the last real block's DC value. - * This squeezes a few more bytes out of the resulting file... - */ - if (coef->iMCU_row_num == last_iMCU_row) { - blocks_across += ndummy; /* include lower right corner */ - MCUs_across = blocks_across / h_samp_factor; - for (block_row = block_rows; block_row < compptr->v_samp_factor; + } + } + if (coef->iMCU_row_num == last_iMCU_row) { + blocks_across += ndummy; /* include lower right corner */ + MCUs_across = blocks_across / h_samp_factor; + for (block_row = block_rows; block_row < compptr->v_samp_factor; block_row++) { thisblockrow = buffer[block_row]; lastblockrow = buffer[block_row-1]; @@ -188007,32 +174558,18 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { lastDC = lastblockrow[h_samp_factor-1][0]; for (bi = 0; bi < h_samp_factor; bi++) { - thisblockrow[bi][0] = lastDC; + thisblockrow[bi][0] = lastDC; } thisblockrow += h_samp_factor; /* advance to next MCU in row */ lastblockrow += h_samp_factor; } - } - } + } + } } - /* NB: compress_output will increment iMCU_row_num if successful. - * A suspension return will result in redoing all the work above next time. - */ - /* Emit data to the entropy encoder, sharing code with subsequent passes */ return compress_output(cinfo, input_buf); } -/* - * Process some data in subsequent passes of a multi-pass case. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the scan. - * The data is obtained from the virtual arrays and fed to the entropy coder. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf is ignored; it is likely to be a NULL pointer. - */ - METHODDEF(boolean) compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { @@ -188044,47 +174581,37 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) JBLOCKROW buffer_ptr; jpeg_component_info *compptr; - /* Align the virtual buffers for the components used in this scan. - * NB: during first pass, this is safe only because the buffers will - * already be aligned properly, so jmemmgr.c won't need to do any I/O. - */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - coef->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); } - /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { buffer_ptr = buffer[ci][yindex+yoffset] + start_col; for (xindex = 0; xindex < compptr->MCU_width; xindex++) { - coef->MCU_buffer[blkn++] = buffer_ptr++; + coef->MCU_buffer[blkn++] = buffer_ptr++; } } - } - /* Try to write the MCU. */ - if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ + } + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; return FALSE; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->mcu_ctr = 0; + } + } + coef->mcu_ctr = 0; } - /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; @@ -188092,54 +174619,46 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) #endif /* FULL_COEF_BUFFER_SUPPORTED */ -/* - * Initialize coefficient buffer controller. - */ - GLOBAL(void) jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; coef = (my_coef_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_c_coef_controller *) coef; coef->pub.start_pass = start_pass_coef; - /* Create the coefficient buffer. */ if (need_full_buffer) { #ifdef FULL_COEF_BUFFER_SUPPORTED - /* Allocate a full-image virtual array for each component, */ - /* padded to a multiple of samp_factor DCT blocks in each direction. */ - int ci; - jpeg_component_info *compptr; + int ci; + jpeg_component_info *compptr; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); - } + } #else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { - /* We only need a single-MCU buffer. */ - JBLOCKROW buffer; - int i; + JBLOCKROW buffer; + int i; - buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { - coef->MCU_buffer[i] = buffer + i; - } - coef->whole_image[0] = NULL; /* flag for no virtual arrays */ + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->whole_image[0] = NULL; /* flag for no virtual arrays */ } } /********* End of inlined file: jccoefct.c *********/ @@ -188147,58 +174666,19 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) /********* Start of inlined file: jccolor.c *********/ #define JPEG_INTERNALS -/* Private subobject */ - typedef struct { struct jpeg_color_converter pub; /* public fields */ - /* Private state for RGB->YCC conversion */ INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ } my_color_converter; typedef my_color_converter * my_cconvert_ptr; -/**************** RGB -> YCbCr conversion: most common case **************/ - -/* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B - * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE - * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) - * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, - * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and - * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) - * were not represented exactly. Now we sacrifice exact representation of - * maximum red and maximum blue in order to get exact grayscales. - * - * To avoid floating-point arithmetic, we represent the fractional constants - * as integers scaled up by 2^16 (about 4 digits precision); we have to divide - * the products by 2^16, with appropriate rounding, to get the correct answer. - * - * For even more speed, we avoid doing any multiplications in the inner loop - * by precalculating the constants times R,G,B for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. - * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included - * in the tables to save adding them separately in the inner loop. - */ - #define SCALEBITS 16 /* speediest right-shift on some machines */ #define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L< Y section */ #define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ #define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ @@ -188210,10 +174690,6 @@ typedef my_color_converter * my_cconvert_ptr; #define B_CR_OFF (7*(MAXJSAMPLE+1)) #define TABLE_SIZE (8*(MAXJSAMPLE+1)) -/* - * Initialize for RGB->YCC colorspace conversion. - */ - METHODDEF(void) rgb_ycc_start (j_compress_ptr cinfo) { @@ -188221,42 +174697,22 @@ rgb_ycc_start (j_compress_ptr cinfo) INT32 * rgb_ycc_tab; INT32 i; - /* Allocate and fill in the conversion tables. */ cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (TABLE_SIZE * SIZEOF(INT32))); for (i = 0; i <= MAXJSAMPLE; i++) { - rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; - rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; - rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; - rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; - rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; - /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. - * This ensures that the maximum output will round to MAXJSAMPLE - * not MAXJSAMPLE+1, and thus that we don't have to range-limit. - */ - rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; -/* B=>Cb and R=>Cr tables are the same - rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; -*/ - rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; - rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; } } -/* - * Convert some rows of samples to the JPEG colorspace. - * - * Note that we change from the application's interleaved-pixel format - * to our internal noninterleaved, one-plane-per-component format. - * The input buffer is therefore three times as wide as the output buffer. - * - * A starting row offset is provided only for the output buffer. The caller - * can easily adjust the passed input_buf value to accommodate any row - * offset required on that side. - */ - METHODDEF(void) rgb_ycc_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, @@ -188271,46 +174727,29 @@ rgb_ycc_convert (j_compress_ptr cinfo, JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { - inptr = *input_buf++; - outptr0 = output_buf[0][output_row]; - outptr1 = output_buf[1][output_row]; - outptr2 = output_buf[2][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - r = GETJSAMPLE(inptr[RGB_RED]); - g = GETJSAMPLE(inptr[RGB_GREEN]); - b = GETJSAMPLE(inptr[RGB_BLUE]); - inptr += RGB_PIXELSIZE; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations - * must be too; we do not need an explicit range-limiting operation. - * Hence the value being shifted is never negative, and we don't - * need the general RIGHT_SHIFT macro. - */ - /* Y */ - outptr0[col] = (JSAMPLE) + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + outptr0[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); - /* Cb */ - outptr1[col] = (JSAMPLE) + outptr1[col] = (JSAMPLE) ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) >> SCALEBITS); - /* Cr */ - outptr2[col] = (JSAMPLE) + outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); - } + } } } -/**************** Cases other than RGB -> YCbCr **************/ - -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles RGB->grayscale conversion, which is the same - * as the RGB->Y portion of RGB->YCbCr. - * We assume rgb_ycc_start has been called (we only use the Y tables). - */ - METHODDEF(void) rgb_gray_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, @@ -188325,30 +174764,21 @@ rgb_gray_convert (j_compress_ptr cinfo, JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { - inptr = *input_buf++; - outptr = output_buf[0][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - r = GETJSAMPLE(inptr[RGB_RED]); - g = GETJSAMPLE(inptr[RGB_GREEN]); - b = GETJSAMPLE(inptr[RGB_BLUE]); - inptr += RGB_PIXELSIZE; - /* Y */ - outptr[col] = (JSAMPLE) + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + outptr[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); - } + } } } -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles Adobe-style CMYK->YCCK conversion, - * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same - * conversion as above, while passing K (black) unchanged. - * We assume rgb_ycc_start has been called. - */ - METHODDEF(void) cmyk_ycck_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, @@ -188363,46 +174793,31 @@ cmyk_ycck_convert (j_compress_ptr cinfo, JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { - inptr = *input_buf++; - outptr0 = output_buf[0][output_row]; - outptr1 = output_buf[1][output_row]; - outptr2 = output_buf[2][output_row]; - outptr3 = output_buf[3][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); - g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); - b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); - /* K passes through as-is */ - outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ - inptr += 4; - /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations - * must be too; we do not need an explicit range-limiting operation. - * Hence the value being shifted is never negative, and we don't - * need the general RIGHT_SHIFT macro. - */ - /* Y */ - outptr0[col] = (JSAMPLE) + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + outptr3 = output_buf[3][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); + g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); + b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); + outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ + inptr += 4; + outptr0[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); - /* Cb */ - outptr1[col] = (JSAMPLE) + outptr1[col] = (JSAMPLE) ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) >> SCALEBITS); - /* Cr */ - outptr2[col] = (JSAMPLE) + outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); - } + } } } -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles grayscale output with no conversion. - * The source can be either plain grayscale or YCbCr (since Y == gray). - */ - METHODDEF(void) grayscale_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, @@ -188415,26 +174830,20 @@ grayscale_convert (j_compress_ptr cinfo, int instride = cinfo->input_components; while (--num_rows >= 0) { - inptr = *input_buf++; - outptr = output_buf[0][output_row]; - output_row++; - for (col = 0; col < num_cols; col++) { - outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ - inptr += instride; - } + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ + inptr += instride; + } } } -/* - * Convert some rows of samples to the JPEG colorspace. - * This version handles multi-component colorspaces without conversion. - * We assume input_components == num_components. - */ - METHODDEF(void) null_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) { register JSAMPROW inptr; register JSAMPROW outptr; @@ -188444,163 +174853,138 @@ null_convert (j_compress_ptr cinfo, JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { - /* It seems fastest to make a separate pass for each component. */ - for (ci = 0; ci < nc; ci++) { - inptr = *input_buf; - outptr = output_buf[ci][output_row]; - for (col = 0; col < num_cols; col++) { + for (ci = 0; ci < nc; ci++) { + inptr = *input_buf; + outptr = output_buf[ci][output_row]; + for (col = 0; col < num_cols; col++) { outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ inptr += nc; - } - } - input_buf++; - output_row++; + } + } + input_buf++; + output_row++; } } -/* - * Empty method for start_pass. - */ - METHODDEF(void) null_method (j_compress_ptr cinfo) { - /* no work needed */ } -/* - * Module initialization routine for input colorspace conversion. - */ - GLOBAL(void) jinit_color_converter (j_compress_ptr cinfo) { my_cconvert_ptr cconvert; cconvert = (my_cconvert_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_converter)); cinfo->cconvert = (struct jpeg_color_converter *) cconvert; - /* set start_pass to null method until we find out differently */ cconvert->pub.start_pass = null_method; - /* Make sure input_components agrees with in_color_space */ switch (cinfo->in_color_space) { case JCS_GRAYSCALE: - if (cinfo->input_components != 1) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; + if (cinfo->input_components != 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; case JCS_RGB: #if RGB_PIXELSIZE != 3 - if (cinfo->input_components != RGB_PIXELSIZE) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; + if (cinfo->input_components != RGB_PIXELSIZE) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; #endif /* else share code with YCbCr */ case JCS_YCbCr: - if (cinfo->input_components != 3) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; + if (cinfo->input_components != 3) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; case JCS_CMYK: case JCS_YCCK: - if (cinfo->input_components != 4) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; + if (cinfo->input_components != 4) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; default: /* JCS_UNKNOWN can be anything */ - if (cinfo->input_components < 1) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; + if (cinfo->input_components < 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; } - /* Check num_components, set conversion method based on requested space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: - if (cinfo->num_components != 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_GRAYSCALE) - cconvert->pub.color_convert = grayscale_convert; - else if (cinfo->in_color_space == JCS_RGB) { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_gray_convert; - } else if (cinfo->in_color_space == JCS_YCbCr) - cconvert->pub.color_convert = grayscale_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_GRAYSCALE) + cconvert->pub.color_convert = grayscale_convert; + else if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_gray_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = grayscale_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; case JCS_RGB: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; case JCS_YCbCr: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB) { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = rgb_ycc_convert; - } else if (cinfo->in_color_space == JCS_YCbCr) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; case JCS_CMYK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_CMYK) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; case JCS_YCCK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_CMYK) { - cconvert->pub.start_pass = rgb_ycc_start; - cconvert->pub.color_convert = cmyk_ycck_convert; - } else if (cinfo->in_color_space == JCS_YCCK) - cconvert->pub.color_convert = null_convert; - else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = cmyk_ycck_convert; + } else if (cinfo->in_color_space == JCS_YCCK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; default: /* allow null conversion of JCS_UNKNOWN */ - if (cinfo->jpeg_color_space != cinfo->in_color_space || + if (cinfo->jpeg_color_space != cinfo->in_color_space || cinfo->num_components != cinfo->input_components) - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - cconvert->pub.color_convert = null_convert; - break; + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + cconvert->pub.color_convert = null_convert; + break; } } /********* End of inlined file: jccolor.c *********/ - #undef FIX + #undef FIX /********* Start of inlined file: jcdctmgr.c *********/ #define JPEG_INTERNALS /********* Start of inlined file: jdct.h *********/ -/* - * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; - * the DCT is to be performed in-place in that buffer. Type DCTELEM is int - * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT - * implementations use an array of type FAST_FLOAT, instead.) - * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). - * The DCT outputs are returned scaled up by a factor of 8; they therefore - * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This - * convention improves accuracy in integer implementations and saves some - * work in floating-point ones. - * Quantization of the output coefficients is done by jcdctmgr.c. - */ #ifndef __jdct_h__ #define __jdct_h__ @@ -188614,23 +174998,6 @@ typedef INT32 DCTELEM; /* must have 32 bits */ typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); -/* - * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer - * to an output sample array. The routine must dequantize the input data as - * well as perform the IDCT; for dequantization, it uses the multiplier table - * pointed to by compptr->dct_table. The output data is to be placed into the - * sample array starting at a specified column. (Any row offset needed will - * be applied to the array pointer before it is passed to the IDCT code.) - * Note that the number of samples emitted by the IDCT routine is - * DCT_scaled_size * DCT_scaled_size. - */ - -/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ - -/* - * Each IDCT routine has its own ideas about the best dct_table element type. - */ - typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ #if BITS_IN_JSAMPLE == 8 typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ @@ -188641,21 +175008,10 @@ typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ #endif typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ -/* - * Each IDCT routine is responsible for range-limiting its results and - * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could - * be quite far out of range if the input data is corrupt, so a bulletproof - * range-limiting step is required. We use a mask-and-table-lookup method - * to do the combined operations quickly. See the comments with - * prepare_range_limit_table (in jdmaster.c) for more info. - */ - #define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) #define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ -/* Short forms of external names for systems with brain-damaged linkers. */ - #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_fdct_islow jFDislow #define jpeg_fdct_ifast jFDifast @@ -188668,67 +175024,36 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ #define jpeg_idct_1x1 jRD1x1 #endif /* NEED_SHORT_EXTERNAL_NAMES */ -/* Extern declarations for the forward and inverse DCT routines. */ - EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); EXTERN(void) jpeg_idct_islow - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_ifast - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_float - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x4 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x2 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_1x1 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -/* - * Macros for handling fixed-point arithmetic; these are used by many - * but not all of the DCT/IDCT modules. - * - * All values are expected to be of type INT32. - * Fractional constants are scaled left by CONST_BITS bits. - * CONST_BITS is defined within each module using these macros, - * and may differ from one module to the next. - */ - #define ONE ((INT32) 1) #define CONST_SCALE (ONE << CONST_BITS) -/* Convert a positive real constant to an integer scaled by CONST_SCALE. - * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, - * thus causing a lot of useless floating-point operations at run time. - */ - #define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) -/* Descale and correctly round an INT32 value that's scaled by N bits. - * We assume RIGHT_SHIFT rounds towards minus infinity, so adding - * the fudge factor is correct for either sign of X. - */ - #define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * This macro is used only when the two inputs will actually be no more than - * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a - * full 32x32 multiply. This provides a useful speedup on many machines. - * Unfortunately there is no way to specify a 16x16->32 multiply portably - * in C, but some C compilers will do the right thing if you provide the - * correct combination of casts. - */ - #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) #endif @@ -188740,8 +175065,6 @@ EXTERN(void) jpeg_idct_1x1 #define MULTIPLY16C16(var,const) ((var) * (const)) #endif -/* Same except both inputs are variables. */ - #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) #endif @@ -188753,24 +175076,14 @@ EXTERN(void) jpeg_idct_1x1 #endif /********* End of inlined file: jdct.h *********/ - /* Private declarations for DCT subsystem */ - -/* Private subobject for this module */ - typedef struct { struct jpeg_forward_dct pub; /* public fields */ - /* Pointer to the DCT routine actually in use */ forward_DCT_method_ptr do_dct; - /* The actual post-DCT divisors --- not identical to the quant table - * entries, because of scaling (especially for an unnormalized DCT). - * Each table is given in normal array order. - */ DCTELEM * divisors[NUM_QUANT_TBLS]; #ifdef DCT_FLOAT_SUPPORTED - /* Same as above for the floating-point case. */ float_DCT_method_ptr do_float_dct; FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; #endif @@ -188778,15 +175091,6 @@ typedef struct { typedef my_fdct_controller * my_fdct_ptr; -/* - * Initialize for a processing pass. - * Verify that all referenced Q-tables are present, and set up - * the divisor table for each one. - * In the current implementation, DCT of all components is done during - * the first pass, even if only some components will be output in the - * first scan. Hence all components should be examined here. - */ - METHODDEF(void) start_pass_fdctmgr (j_compress_ptr cinfo) { @@ -188797,44 +175101,31 @@ start_pass_fdctmgr (j_compress_ptr cinfo) DCTELEM * dtbl; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - qtblno = compptr->quant_tbl_no; - /* Make sure specified quantization table is present */ - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + ci++, compptr++) { + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - qtbl = cinfo->quant_tbl_ptrs[qtblno]; - /* Compute divisors for this quant table */ - /* We may do this more than once for same table, but it's not a big deal */ - switch (cinfo->dct_method) { + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - /* For LL&M IDCT method, divisors are equal to raw quantization - * coefficients multiplied by 8 (to counteract scaling). - */ - if (fdct->divisors[qtblno] == NULL) { + case JDCT_ISLOW: + if (fdct->divisors[qtblno] == NULL) { fdct->divisors[qtblno] = (DCTELEM *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; - } - break; + } + break; #endif #ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - { - /* For AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - */ + case JDCT_IFAST: + { #define CONST_BITS 14 static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, @@ -188848,30 +175139,22 @@ start_pass_fdctmgr (j_compress_ptr cinfo) if (fdct->divisors[qtblno] == NULL) { fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DCTSIZE2 * SIZEOF(DCTELEM)); } dtbl = fdct->divisors[qtblno]; for (i = 0; i < DCTSIZE2; i++) { dtbl[i] = (DCTELEM) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], (INT32) aanscales[i]), - CONST_BITS-3); + CONST_BITS-3); } - } - break; + } + break; #endif #ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - { - /* For float AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - * What's actually stored is 1/divisor so that the inner loop can - * use a multiplication rather than a division. - */ + case JDCT_FLOAT: + { FAST_FLOAT * fdtbl; int row, col; static const double aanscalefactor[DCTSIZE] = { @@ -188881,45 +175164,35 @@ start_pass_fdctmgr (j_compress_ptr cinfo) if (fdct->float_divisors[qtblno] == NULL) { fdct->float_divisors[qtblno] = (FAST_FLOAT *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DCTSIZE2 * SIZEOF(FAST_FLOAT)); } fdtbl = fdct->float_divisors[qtblno]; i = 0; for (row = 0; row < DCTSIZE; row++) { for (col = 0; col < DCTSIZE; col++) { - fdtbl[i] = (FAST_FLOAT) - (1.0 / (((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col] * 8.0))); - i++; + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; } } - } - break; + } + break; #endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } } } -/* - * Perform forward DCT on one or more blocks of a component. - * - * The input samples are taken from the sample_data[] array starting at - * position start_row/start_col, and moving to the right for any additional - * blocks. The quantized coefficients are returned in coef_blocks[]. - */ - METHODDEF(void) forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks) -/* This version is used for integer DCT implementations. */ + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) { - /* This routine is heavily used, so it's worth coding it tightly. */ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; forward_DCT_method_ptr do_dct = fdct->do_dct; DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; @@ -188929,13 +175202,12 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, sample_data += start_row; /* fold in the vertical offset once */ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { - /* Load data into workspace, applying unsigned->signed conversion */ - { register DCTELEM *workspaceptr; - register JSAMPROW elemptr; - register int elemr; + { register DCTELEM *workspaceptr; + register JSAMPROW elemptr; + register int elemr; - workspaceptr = workspace; - for (elemr = 0; elemr < DCTSIZE; elemr++) { + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = sample_data[elemr] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; @@ -188949,36 +175221,22 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) { - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; } } #endif - } - } + } + } - /* Perform the DCT */ - (*do_dct) (workspace); + (*do_dct) (workspace); - /* Quantize/descale the coefficients, and store into coef_blocks[] */ - { register DCTELEM temp, qval; - register int i; - register JCOEFPTR output_ptr = coef_blocks[bi]; + { register DCTELEM temp, qval; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; - for (i = 0; i < DCTSIZE2; i++) { + for (i = 0; i < DCTSIZE2; i++) { qval = divisors[i]; temp = workspace[i]; - /* Divide the coefficient value by qval, ensuring proper rounding. - * Since C does not specify the direction of rounding for negative - * quotients, we have to force the dividend positive for portability. - * - * In most files, at least half of the output values will be zero - * (at default quantization settings, more like three-quarters...) - * so we should ensure that this case is fast. On many machines, - * a comparison is enough cheaper than a divide to make a special test - * a win. Since both inputs will be nonnegative, we need only test - * for a < b to discover whether a/b is 0. - * If your machine's division is fast enough, define FAST_DIVIDE. - */ #ifdef FAST_DIVIDE #define DIVIDE_BY(a,b) a /= b #else @@ -188994,8 +175252,8 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, DIVIDE_BY(temp, qval); } output_ptr[i] = (JCOEF) temp; - } - } + } + } } } @@ -189006,9 +175264,7 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks) -/* This version is used for floating-point DCT implementations. */ { - /* This routine is heavily used, so it's worth coding it tightly. */ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; float_DCT_method_ptr do_dct = fdct->do_float_dct; FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; @@ -189018,13 +175274,12 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, sample_data += start_row; /* fold in the vertical offset once */ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { - /* Load data into workspace, applying unsigned->signed conversion */ - { register FAST_FLOAT *workspaceptr; - register JSAMPROW elemptr; - register int elemr; + { register FAST_FLOAT *workspaceptr; + register JSAMPROW elemptr; + register int elemr; - workspaceptr = workspace; - for (elemr = 0; elemr < DCTSIZE; elemr++) { + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = sample_data[elemr] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); @@ -189038,43 +175293,30 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) { - *workspaceptr++ = (FAST_FLOAT) - (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT) + (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); } } #endif - } - } + } + } - /* Perform the DCT */ - (*do_dct) (workspace); + (*do_dct) (workspace); - /* Quantize/descale the coefficients, and store into coef_blocks[] */ - { register FAST_FLOAT temp; - register int i; - register JCOEFPTR output_ptr = coef_blocks[bi]; + { register FAST_FLOAT temp; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; - for (i = 0; i < DCTSIZE2; i++) { - /* Apply the quantization and scaling factor */ + for (i = 0; i < DCTSIZE2; i++) { temp = workspace[i] * divisors[i]; - /* Round to nearest integer. - * Since C does not specify the direction of rounding for negative - * quotients, we have to force the dividend positive for portability. - * The maximum coefficient size is +-16K (for 12-bit data), so this - * code should work for either 16-bit or 32-bit ints. - */ output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); - } - } + } + } } } #endif /* DCT_FLOAT_SUPPORTED */ -/* - * Initialize FDCT manager. - */ - GLOBAL(void) jinit_forward_dct (j_compress_ptr cinfo) { @@ -189082,7 +175324,7 @@ jinit_forward_dct (j_compress_ptr cinfo) int i; fdct = (my_fdct_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_fdct_controller)); cinfo->fdct = (struct jpeg_forward_dct *) fdct; fdct->pub.start_pass = start_pass_fdctmgr; @@ -189090,48 +175332,42 @@ jinit_forward_dct (j_compress_ptr cinfo) switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: - fdct->pub.forward_DCT = forward_DCT; - fdct->do_dct = jpeg_fdct_islow; - break; + fdct->pub.forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_islow; + break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: - fdct->pub.forward_DCT = forward_DCT; - fdct->do_dct = jpeg_fdct_ifast; - break; + fdct->pub.forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_ifast; + break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: - fdct->pub.forward_DCT = forward_DCT_float; - fdct->do_float_dct = jpeg_fdct_float; - break; + fdct->pub.forward_DCT = forward_DCT_float; + fdct->do_float_dct = jpeg_fdct_float; + break; #endif default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; } - /* Mark divisor tables unallocated */ for (i = 0; i < NUM_QUANT_TBLS; i++) { - fdct->divisors[i] = NULL; + fdct->divisors[i] = NULL; #ifdef DCT_FLOAT_SUPPORTED - fdct->float_divisors[i] = NULL; + fdct->float_divisors[i] = NULL; #endif } } /********* End of inlined file: jcdctmgr.c *********/ - #undef CONST_BITS + #undef CONST_BITS /********* Start of inlined file: jchuff.c *********/ #define JPEG_INTERNALS /********* Start of inlined file: jchuff.h *********/ -/* The legal range of a DCT coefficient is - * -1024 .. +1023 for 8-bit data; - * -16384 .. +16383 for 12-bit data. - * Hence the magnitude should always fit in 10 or 14 bits respectively. - */ #ifndef _jchuff_h_ #define _jchuff_h_ @@ -189142,52 +175378,32 @@ jinit_forward_dct (j_compress_ptr cinfo) #define MAX_COEF_BITS 14 #endif -/* Derived data constructed for each Huffman table */ - typedef struct { unsigned int ehufco[256]; /* code for each symbol */ char ehufsi[256]; /* length of code for each symbol */ - /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ } c_derived_tbl; -/* Short forms of external names for systems with brain-damaged linkers. */ - #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_make_c_derived_tbl jMkCDerived #define jpeg_gen_optimal_table jGenOptTbl #endif /* NEED_SHORT_EXTERNAL_NAMES */ -/* Expand a Huffman table definition into the derived format */ EXTERN(void) jpeg_make_c_derived_tbl JPP((j_compress_ptr cinfo, boolean isDC, int tblno, - c_derived_tbl ** pdtbl)); + c_derived_tbl ** pdtbl)); -/* Generate an optimal table definition given the specified counts */ EXTERN(void) jpeg_gen_optimal_table JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); #endif /********* End of inlined file: jchuff.h *********/ - /* Declarations shared with jcphuff.c */ - -/* Expanded entropy encoder object for Huffman encoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - typedef struct { INT32 put_buffer; /* current bit-accumulation buffer */ int put_bits; /* # of bits now in it */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - #ifndef NO_STRUCT_ASSIGN #define ASSIGN_STATE(dest,src) ((dest) = (src)) #else @@ -189207,11 +175423,9 @@ typedef struct { savable_state saved; /* Bit buffer & DC state at start of MCU */ - /* These fields are NOT loaded into local working state. */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ int next_restart_num; /* next restart number to write (0-7) */ - /* Pointers to derived tables (these workspaces have image lifespan) */ c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; @@ -189223,10 +175437,6 @@ typedef struct { typedef huff_entropy_encoder * huff_entropy_ptr; -/* Working state while writing an MCU. - * This struct contains all the fields that are needed by subroutines. - */ - typedef struct { JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ @@ -189234,7 +175444,6 @@ typedef struct { j_compress_ptr cinfo; /* dump_buffer needs access to this */ } working_state; -/* Forward declarations */ METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); @@ -189244,12 +175453,6 @@ METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); #endif -/* - * Initialize for a Huffman-compressed scan. - * If gather_statistics is TRUE, we do not output anything during the scan, - * just count the Huffman symbols used and generate Huffman code tables. - */ - METHODDEF(void) start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) { @@ -189259,69 +175462,53 @@ start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) if (gather_statistics) { #ifdef ENTROPY_OPT_SUPPORTED - entropy->pub.encode_mcu = encode_mcu_gather; - entropy->pub.finish_pass = finish_pass_gather; + entropy->pub.encode_mcu = encode_mcu_gather; + entropy->pub.finish_pass = finish_pass_gather; #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - entropy->pub.encode_mcu = encode_mcu_huff; - entropy->pub.finish_pass = finish_pass_huff; + entropy->pub.encode_mcu = encode_mcu_huff; + entropy->pub.finish_pass = finish_pass_huff; } for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - if (gather_statistics) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (gather_statistics) { #ifdef ENTROPY_OPT_SUPPORTED - /* Check for invalid table indexes */ - /* (make_c_derived_tbl does this in the other path) */ - if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); - if (actbl < 0 || actbl >= NUM_HUFF_TBLS) + if (actbl < 0 || actbl >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->dc_count_ptrs[dctbl] == NULL) + if (entropy->dc_count_ptrs[dctbl] == NULL) entropy->dc_count_ptrs[dctbl] = (long *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); - if (entropy->ac_count_ptrs[actbl] == NULL) + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); + if (entropy->ac_count_ptrs[actbl] == NULL) entropy->ac_count_ptrs[actbl] = (long *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); #endif - } else { - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, - & entropy->ac_derived_tbls[actbl]); - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; + } else { + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + } + entropy->saved.last_dc_val[ci] = 0; } - /* Initialize bit buffer to empty */ entropy->saved.put_buffer = 0; entropy->saved.put_bits = 0; - /* Initialize restart stuff */ entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num = 0; } -/* - * Compute the derived values for a Huffman table. - * This routine also performs some validation checks on the table. - * - * Note this is also used by jcphuff.c. - */ - GLOBAL(void) jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, c_derived_tbl ** pdtbl) @@ -189333,126 +175520,84 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, unsigned int huffcode[257]; unsigned int code; - /* Note that huffsize[] and huffcode[] are filled in code-length order, - * paralleling the order of the symbols themselves in htbl->huffval[]. - */ - - /* Find the input Huffman table */ if (tblno < 0 || tblno >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); htbl = - isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; if (htbl == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - /* Allocate a workspace if we haven't already done so. */ if (*pdtbl == NULL) - *pdtbl = (c_derived_tbl *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + *pdtbl = (c_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(c_derived_tbl)); dtbl = *pdtbl; - /* Figure C.1: make table of Huffman code length for each symbol */ - p = 0; for (l = 1; l <= 16; l++) { - i = (int) htbl->bits[l]; - if (i < 0 || p + i > 256) /* protect against table overrun */ - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - while (i--) - huffsize[p++] = (char) l; + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; } huffsize[p] = 0; lastp = p; - /* Figure C.2: generate the codes themselves */ - /* We also validate that the counts represent a legal Huffman code tree. */ - code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { - while (((int) huffsize[p]) == si) { - huffcode[p++] = code; - code++; - } - /* code is now 1 more than the last code used for codelength si; but - * it must still fit in si bits, since no code is allowed to be all ones. - */ - if (((INT32) code) >= (((INT32) 1) << si)) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - code <<= 1; - si++; + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; } - /* Figure C.3: generate encoding tables */ - /* These are code and size indexed by symbol value */ - - /* Set all codeless symbols to have code length 0; - * this lets us detect duplicate VAL entries here, and later - * allows emit_bits to detect any attempt to emit such symbols. - */ MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); - /* This is also a convenient place to check for out-of-range - * and duplicated VAL entries. We allow 0..255 for AC symbols - * but only 0..15 for DC. (We could constrain them further - * based on data depth and mode, but this seems enough.) - */ maxsymbol = isDC ? 15 : 255; for (p = 0; p < lastp; p++) { - i = htbl->huffval[p]; - if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - dtbl->ehufco[i] = huffcode[p]; - dtbl->ehufsi[i] = huffsize[p]; + i = htbl->huffval[p]; + if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + dtbl->ehufco[i] = huffcode[p]; + dtbl->ehufsi[i] = huffsize[p]; } } -/* Outputting bytes to the file */ - -/* Emit a byte, taking 'action' if must suspend. */ #define emit_byte(state,val,action) \ { *(state)->next_output_byte++ = (JOCTET) (val); \ if (--(state)->free_in_buffer == 0) \ - if (! dump_buffer(state)) \ - { action; } } + if (! dump_buffer(state)) \ + { action; } } LOCAL(boolean) dump_buffer (working_state * state) -/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ { struct jpeg_destination_mgr * dest = state->cinfo->dest; if (! (*dest->empty_output_buffer) (state->cinfo)) - return FALSE; - /* After a successful buffer dump, must reset buffer pointers */ + return FALSE; state->next_output_byte = dest->next_output_byte; state->free_in_buffer = dest->free_in_buffer; return TRUE; } -/* Outputting bits to the file */ - -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. - */ - INLINE LOCAL(boolean) emit_bits (working_state * state, unsigned int code, int size) -/* Emit some bits; return TRUE if successful, FALSE if must suspend */ { - /* This routine is heavily used, so it's worth coding tightly. */ register INT32 put_buffer = (INT32) code; register int put_bits = state->cur.put_bits; - /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) - ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); + int c = (int) ((put_buffer >> 16) & 0xFF); - emit_byte(state, c, return FALSE); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(state, 0, return FALSE); - } - put_buffer <<= 8; - put_bits -= 8; + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; } state->cur.put_buffer = put_buffer; /* update state variables */ @@ -189483,14 +175628,12 @@ LOCAL(boolean) flush_bits (working_state * state) { if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ - return FALSE; + return FALSE; state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ state->cur.put_bits = 0; return TRUE; } -/* Encode a single block's worth of coefficients */ - LOCAL(boolean) encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, c_derived_tbl *dctbl, c_derived_tbl *actbl) @@ -189499,119 +175642,87 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, register int nbits; register int k, r, i; - /* Encode the DC coefficient difference per section F.1.2.1 */ - temp = temp2 = block[0] - last_dc_val; if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* For a negative input, want temp2 = bitwise complement of abs(input) */ - /* This code assumes we are on a two's complement machine */ - temp2--; + temp = -temp; /* temp is abs value of input */ + temp2--; } - /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { - nbits++; - temp >>= 1; + nbits++; + temp >>= 1; } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ if (nbits > MAX_COEF_BITS+1) - ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - /* Emit the Huffman-coded symbol for the number of bits */ if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) - return FALSE; + return FALSE; - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ if (nbits) /* emit_bits rejects calls with size 0 */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) - return FALSE; - - /* Encode the AC coefficients per section F.1.2.2 */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; r = 0; /* r = run length of zeros */ for (k = 1; k < DCTSIZE2; k++) { - if ((temp = block[jpeg_natural_order[k]]) == 0) { - r++; - } else { - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + while (r > 15) { if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) return FALSE; r -= 16; - } + } - temp2 = temp; - if (temp < 0) { + temp2 = temp; + if (temp < 0) { temp = -temp; /* temp is abs value of input */ - /* This code assumes we are on a two's complement machine */ temp2--; - } + } - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) + if (nbits > MAX_COEF_BITS) ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - /* Emit Huffman symbol for run length / number of bits */ - i = (r << 4) + nbits; - if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) + i = (r << 4) + nbits; + if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) return FALSE; - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) + if (! emit_bits(state, (unsigned int) temp2, nbits)) return FALSE; - r = 0; - } + r = 0; + } } - /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) - if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) - return FALSE; + if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) + return FALSE; return TRUE; } -/* - * Emit a restart marker & resynchronize predictions. - */ - LOCAL(boolean) emit_restart (working_state * state, int restart_num) { int ci; if (! flush_bits(state)) - return FALSE; + return FALSE; emit_byte(state, 0xFF, return FALSE); emit_byte(state, JPEG_RST0 + restart_num, return FALSE); - /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) - state->cur.last_dc_val[ci] = 0; - - /* The restart counter is not updated until we successfully write the MCU. */ + state->cur.last_dc_val[ci] = 0; return TRUE; } -/* - * Encode and output one MCU's worth of Huffman-compressed coefficients. - */ - METHODDEF(boolean) encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -189620,91 +175731,65 @@ encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) int blkn, ci; jpeg_component_info * compptr; - /* Load up working state */ state.next_output_byte = cinfo->dest->next_output_byte; state.free_in_buffer = cinfo->dest->free_in_buffer; ASSIGN_STATE(state.cur, entropy->saved); state.cinfo = cinfo; - /* Emit restart marker if needed */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! emit_restart(&state, entropy->next_restart_num)) + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) return FALSE; } - /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - if (! encode_one_block(&state, + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + if (! encode_one_block(&state, MCU_data[blkn][0], state.cur.last_dc_val[ci], entropy->dc_derived_tbls[compptr->dc_tbl_no], entropy->ac_derived_tbls[compptr->ac_tbl_no])) - return FALSE; - /* Update last_dc_val */ - state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; + return FALSE; + state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; } - /* Completed MCU, so update state */ cinfo->dest->next_output_byte = state.next_output_byte; cinfo->dest->free_in_buffer = state.free_in_buffer; ASSIGN_STATE(entropy->saved, state.cur); - /* Update restart-interval state too */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; } return TRUE; } -/* - * Finish up at the end of a Huffman-compressed scan. - */ - METHODDEF(void) finish_pass_huff (j_compress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; working_state state; - /* Load up working state ... flush_bits needs it */ state.next_output_byte = cinfo->dest->next_output_byte; state.free_in_buffer = cinfo->dest->free_in_buffer; ASSIGN_STATE(state.cur, entropy->saved); state.cinfo = cinfo; - /* Flush out the last data */ if (! flush_bits(&state)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); + ERREXIT(cinfo, JERR_CANT_SUSPEND); - /* Update state */ cinfo->dest->next_output_byte = state.next_output_byte; cinfo->dest->free_in_buffer = state.free_in_buffer; ASSIGN_STATE(entropy->saved, state.cur); } -/* - * Huffman coding optimization. - * - * We first scan the supplied data and count the number of uses of each symbol - * that is to be Huffman-coded. (This process MUST agree with the code above.) - * Then we build a Huffman coding tree for the observed counts. - * Symbols which are not needed at all for the particular image are not - * assigned any code, which saves space in the DHT marker as well as in - * the compressed data. - */ - #ifdef ENTROPY_OPT_SUPPORTED -/* Process a single block's worth of coefficients */ - LOCAL(void) htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, long dc_counts[], long ac_counts[]) @@ -189713,70 +175798,50 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, register int nbits; register int k, r; - /* Encode the DC coefficient difference per section F.1.2.1 */ - temp = block[0] - last_dc_val; if (temp < 0) - temp = -temp; + temp = -temp; - /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { - nbits++; - temp >>= 1; + nbits++; + temp >>= 1; } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ if (nbits > MAX_COEF_BITS+1) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); + ERREXIT(cinfo, JERR_BAD_DCT_COEF); - /* Count the Huffman symbol for the number of bits */ dc_counts[nbits]++; - /* Encode the AC coefficients per section F.1.2.2 */ - r = 0; /* r = run length of zeros */ for (k = 1; k < DCTSIZE2; k++) { - if ((temp = block[jpeg_natural_order[k]]) == 0) { - r++; - } else { - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + while (r > 15) { ac_counts[0xF0]++; r -= 16; - } + } - /* Find the number of bits needed for the magnitude of the coefficient */ - if (temp < 0) + if (temp < 0) temp = -temp; - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) + if (nbits > MAX_COEF_BITS) ERREXIT(cinfo, JERR_BAD_DCT_COEF); - /* Count Huffman symbol for run length / number of bits */ - ac_counts[(r << 4) + nbits]++; + ac_counts[(r << 4) + nbits]++; - r = 0; - } + r = 0; + } } - /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) - ac_counts[0]++; + ac_counts[0]++; } -/* - * Trial-encode one MCU's worth of Huffman-compressed coefficients. - * No data is actually output, so no suspension return is possible. - */ - METHODDEF(boolean) encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -189784,58 +175849,27 @@ encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) int blkn, ci; jpeg_component_info * compptr; - /* Take care of restart intervals if needed */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) + if (entropy->restarts_to_go == 0) { + for (ci = 0; ci < cinfo->comps_in_scan; ci++) entropy->saved.last_dc_val[ci] = 0; - /* Update restart state */ - entropy->restarts_to_go = cinfo->restart_interval; - } - entropy->restarts_to_go--; + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; } for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], - entropy->dc_count_ptrs[compptr->dc_tbl_no], - entropy->ac_count_ptrs[compptr->ac_tbl_no]); - entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; } return TRUE; } -/* - * Generate the best Huffman code table for the given counts, fill htbl. - * Note this is also used by jcphuff.c. - * - * The JPEG standard requires that no symbol be assigned a codeword of all - * one bits (so that padding bits added at the end of a compressed segment - * can't look like a valid code). Because of the canonical ordering of - * codewords, this just means that there must be an unused slot in the - * longest codeword length category. Section K.2 of the JPEG spec suggests - * reserving such a slot by pretending that symbol 256 is a valid symbol - * with count 1. In theory that's not optimal; giving it count zero but - * including it in the symbol set anyway should give a better Huffman code. - * But the theoretically better code actually seems to come out worse in - * practice, because it produces more all-ones bytes (which incur stuffed - * zero bytes in the final file). In any case the difference is tiny. - * - * The JPEG standard requires Huffman codes to be no more than 16 bits long. - * If some symbols have a very small but nonzero probability, the Huffman tree - * must be adjusted to meet the code length restriction. We currently use - * the adjustment method suggested in JPEG section K.2. This method is *not* - * optimal; it may not choose the best possible limited-length code. But - * typically only very-low-frequency symbols will be given less-than-optimal - * lengths, so the code is almost optimal. Experimental comparisons against - * an optimal limited-length-code algorithm indicate that the difference is - * microscopic --- usually less than a hundredth of a percent of total size. - * So the extra complexity of an optimal algorithm doesn't seem worthwhile. - */ - GLOBAL(void) jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) { @@ -189847,135 +175881,94 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) int p, i, j; long v; - /* This algorithm is explained in section K.2 of the JPEG standard */ - MEMZERO(bits, SIZEOF(bits)); MEMZERO(codesize, SIZEOF(codesize)); for (i = 0; i < 257; i++) - others[i] = -1; /* init links to empty */ + others[i] = -1; /* init links to empty */ freq[256] = 1; /* make sure 256 has a nonzero count */ - /* Including the pseudo-symbol 256 in the Huffman procedure guarantees - * that no real symbol is given code-value of all ones, because 256 - * will be placed last in the largest codeword category. - */ - - /* Huffman's basic algorithm to assign optimal code lengths to symbols */ for (;;) { - /* Find the smallest nonzero frequency, set c1 = its symbol */ - /* In case of ties, take the larger symbol number */ - c1 = -1; - v = 1000000000L; - for (i = 0; i <= 256; i++) { - if (freq[i] && freq[i] <= v) { + c1 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v) { v = freq[i]; c1 = i; - } - } + } + } - /* Find the next smallest nonzero frequency, set c2 = its symbol */ - /* In case of ties, take the larger symbol number */ - c2 = -1; - v = 1000000000L; - for (i = 0; i <= 256; i++) { - if (freq[i] && freq[i] <= v && i != c1) { + c2 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v && i != c1) { v = freq[i]; c2 = i; - } - } + } + } - /* Done if we've merged everything into one frequency */ - if (c2 < 0) - break; + if (c2 < 0) + break; - /* Else merge the two counts/trees */ - freq[c1] += freq[c2]; - freq[c2] = 0; + freq[c1] += freq[c2]; + freq[c2] = 0; - /* Increment the codesize of everything in c1's tree branch */ - codesize[c1]++; - while (others[c1] >= 0) { - c1 = others[c1]; - codesize[c1]++; - } + codesize[c1]++; + while (others[c1] >= 0) { + c1 = others[c1]; + codesize[c1]++; + } - others[c1] = c2; /* chain c2 onto c1's tree branch */ + others[c1] = c2; /* chain c2 onto c1's tree branch */ - /* Increment the codesize of everything in c2's tree branch */ - codesize[c2]++; - while (others[c2] >= 0) { - c2 = others[c2]; - codesize[c2]++; - } + codesize[c2]++; + while (others[c2] >= 0) { + c2 = others[c2]; + codesize[c2]++; + } } - /* Now count the number of symbols of each code length */ for (i = 0; i <= 256; i++) { - if (codesize[i]) { - /* The JPEG standard seems to think that this can't happen, */ - /* but I'm paranoid... */ - if (codesize[i] > MAX_CLEN) + if (codesize[i]) { + if (codesize[i] > MAX_CLEN) ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); - bits[codesize[i]]++; - } + bits[codesize[i]]++; + } } - /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure - * Huffman procedure assigned any such lengths, we must adjust the coding. - * Here is what the JPEG spec says about how this next bit works: - * Since symbols are paired for the longest Huffman code, the symbols are - * removed from this length category two at a time. The prefix for the pair - * (which is one bit shorter) is allocated to one of the pair; then, - * skipping the BITS entry for that prefix length, a code word from the next - * shortest nonzero BITS entry is converted into a prefix for two code words - * one bit longer. - */ - for (i = MAX_CLEN; i > 16; i--) { - while (bits[i] > 0) { - j = i - 2; /* find length of new prefix to be used */ - while (bits[j] == 0) + while (bits[i] > 0) { + j = i - 2; /* find length of new prefix to be used */ + while (bits[j] == 0) j--; - bits[i] -= 2; /* remove two symbols */ - bits[i-1]++; /* one goes in this length */ - bits[j+1] += 2; /* two new symbols in this length */ - bits[j]--; /* symbol of this length is now a prefix */ - } + bits[i] -= 2; /* remove two symbols */ + bits[i-1]++; /* one goes in this length */ + bits[j+1] += 2; /* two new symbols in this length */ + bits[j]--; /* symbol of this length is now a prefix */ + } } - /* Remove the count for the pseudo-symbol 256 from the largest codelength */ while (bits[i] == 0) /* find largest codelength still in use */ - i--; + i--; bits[i]--; - /* Return final symbol counts (only for lengths 0..16) */ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); - /* Return a list of the symbols sorted by code length */ - /* It's not real clear to me why we don't need to consider the codelength - * changes made above, but the JPEG spec seems to think this works. - */ p = 0; for (i = 1; i <= MAX_CLEN; i++) { - for (j = 0; j <= 255; j++) { - if (codesize[j] == i) { + for (j = 0; j <= 255; j++) { + if (codesize[j] == i) { htbl->huffval[p] = (UINT8) j; p++; - } - } + } + } } - /* Set sent_table FALSE so updated table will be written to JPEG file. */ htbl->sent_table = FALSE; } -/* - * Finish up a statistics-gathering pass and create the new Huffman tables. - */ - METHODDEF(void) finish_pass_gather (j_compress_ptr cinfo) { @@ -189986,39 +175979,32 @@ finish_pass_gather (j_compress_ptr cinfo) boolean did_dc[NUM_HUFF_TBLS]; boolean did_ac[NUM_HUFF_TBLS]; - /* It's important not to apply jpeg_gen_optimal_table more than once - * per table, because it clobbers the input frequency counts! - */ MEMZERO(did_dc, SIZEOF(did_dc)); MEMZERO(did_ac, SIZEOF(did_ac)); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - if (! did_dc[dctbl]) { - htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; - if (*htblptr == NULL) + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); - did_dc[dctbl] = TRUE; - } - if (! did_ac[actbl]) { - htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; - if (*htblptr == NULL) + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + if (! did_ac[actbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; + if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); - did_ac[actbl] = TRUE; - } + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); + did_ac[actbl] = TRUE; + } } } #endif /* ENTROPY_OPT_SUPPORTED */ -/* - * Module initialization routine for Huffman entropy encoding. - */ - GLOBAL(void) jinit_huff_encoder (j_compress_ptr cinfo) { @@ -190026,74 +176012,57 @@ jinit_huff_encoder (j_compress_ptr cinfo) int i; entropy = (huff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(huff_entropy_encoder)); cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; entropy->pub.start_pass = start_pass_huff; - /* Mark tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; #ifdef ENTROPY_OPT_SUPPORTED - entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; + entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; #endif } } /********* End of inlined file: jchuff.c *********/ - #undef emit_byte + #undef emit_byte /********* Start of inlined file: jcinit.c *********/ #define JPEG_INTERNALS -/* - * Master selection of compression modules. - * This is done once at the start of processing an image. We determine - * which modules will be used and give them appropriate initialization calls. - */ - GLOBAL(void) jinit_compress_master (j_compress_ptr cinfo) { - /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, FALSE /* full compression */); - /* Preprocessing */ if (! cinfo->raw_data_in) { - jinit_color_converter(cinfo); - jinit_downsampler(cinfo); - jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); } - /* Forward DCT */ jinit_forward_dct(cinfo); - /* Entropy encoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); } else { - if (cinfo->progressive_mode) { + if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); + jinit_phuff_encoder(cinfo); #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif - } else - jinit_huff_encoder(cinfo); + } else + jinit_huff_encoder(cinfo); } - /* Need a full-image coefficient buffer in any multi-pass mode. */ jinit_c_coef_controller(cinfo, (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); jinit_marker_writer(cinfo); - /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - /* Write the datastream header (SOI) immediately. - * Frame and scan headers are postponed till later. - * This lets application insert special markers after the SOI. - */ (*cinfo->marker->write_file_header) (cinfo); } /********* End of inlined file: jcinit.c *********/ @@ -190101,15 +176070,8 @@ jinit_compress_master (j_compress_ptr cinfo) /********* Start of inlined file: jcmainct.c *********/ #define JPEG_INTERNALS -/* Note: currently, there is no operating mode in which a full-image buffer - * is needed at this step. If there were, that mode could not be used with - * "raw data" input, since this module is bypassed in that case. However, - * we've left the code here for possible use in special applications. - */ #undef FULL_MAIN_BUFFER_SUPPORTED -/* Private buffer controller object */ - typedef struct { struct jpeg_c_main_controller pub; /* public fields */ @@ -190118,44 +176080,31 @@ typedef struct { boolean suspended; /* remember if we suspended output */ J_BUF_MODE pass_mode; /* current operating mode */ - /* If using just a strip buffer, this points to the entire set of buffers - * (we allocate one for each component). In the full-image case, this - * points to the currently accessible strips of the virtual arrays. - */ JSAMPARRAY buffer[MAX_COMPONENTS]; #ifdef FULL_MAIN_BUFFER_SUPPORTED - /* If using full-image storage, this array holds pointers to virtual-array - * control blocks for each component. Unused if not full-image storage. - */ jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; #endif } my_main_controller; typedef my_main_controller * my_main_ptr; -/* Forward declarations */ METHODDEF(void) process_data_simple_main JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); #ifdef FULL_MAIN_BUFFER_SUPPORTED METHODDEF(void) process_data_buffer_main JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); #endif -/* - * Initialize for a processing pass. - */ - METHODDEF(void) start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_main_ptr main_ = (my_main_ptr) cinfo->main; - /* Do nothing in raw-data mode. */ if (cinfo->raw_data_in) - return; + return; main_->cur_iMCU_row = 0; /* initialize counters */ main_->rowgroup_ctr = 0; @@ -190165,32 +176114,26 @@ start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) switch (pass_mode) { case JBUF_PASS_THRU: #ifdef FULL_MAIN_BUFFER_SUPPORTED - if (main_->whole_image[0] != NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + if (main_->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif - main_->pub.process_data = process_data_simple_main; - break; + main_->pub.process_data = process_data_simple_main; + break; #ifdef FULL_MAIN_BUFFER_SUPPORTED case JBUF_SAVE_SOURCE: case JBUF_CRANK_DEST: case JBUF_SAVE_AND_PASS: - if (main_->whole_image[0] == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - main_->pub.process_data = process_data_buffer_main; - break; + if (main_->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + main_->pub.process_data = process_data_buffer_main; + break; #endif default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; } } -/* - * Process some data. - * This routine handles the simple pass-through mode, - * where we have only a strip buffer. - */ - METHODDEF(void) process_data_simple_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, @@ -190199,53 +176142,33 @@ process_data_simple_main (j_compress_ptr cinfo, my_main_ptr main_ = (my_main_ptr) cinfo->main; while (main_->cur_iMCU_row < cinfo->total_iMCU_rows) { - /* Read input data if we haven't filled the main buffer yet */ - if (main_->rowgroup_ctr < DCTSIZE) - (*cinfo->prep->pre_process_data) (cinfo, + if (main_->rowgroup_ctr < DCTSIZE) + (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, main_->buffer, &main_->rowgroup_ctr, (JDIMENSION) DCTSIZE); - /* If we don't have a full iMCU row buffered, return to application for - * more data. Note that preprocessor will always pad to fill the iMCU row - * at the bottom of the image. - */ - if (main_->rowgroup_ctr != DCTSIZE) - return; + if (main_->rowgroup_ctr != DCTSIZE) + return; - /* Send the completed row to the compressor */ - if (! (*cinfo->coef->compress_data) (cinfo, main_->buffer)) { - /* If compressor did not consume the whole row, then we must need to - * suspend processing and return to the application. In this situation - * we pretend we didn't yet consume the last input row; otherwise, if - * it happened to be the last row of the image, the application would - * think we were done. - */ - if (! main_->suspended) { + if (! (*cinfo->coef->compress_data) (cinfo, main_->buffer)) { + if (! main_->suspended) { (*in_row_ctr)--; main_->suspended = TRUE; - } - return; - } - /* We did finish the row. Undo our little suspension hack if a previous - * call suspended; then mark the main buffer empty. - */ - if (main_->suspended) { - (*in_row_ctr)++; - main_->suspended = FALSE; - } - main_->rowgroup_ctr = 0; - main_->cur_iMCU_row++; + } + return; + } + if (main_->suspended) { + (*in_row_ctr)++; + main_->suspended = FALSE; + } + main_->rowgroup_ctr = 0; + main_->cur_iMCU_row++; } } #ifdef FULL_MAIN_BUFFER_SUPPORTED -/* - * Process some data. - * This routine handles all of the modes that use a full-size buffer. - */ - METHODDEF(void) process_data_buffer_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, @@ -190257,70 +176180,50 @@ process_data_buffer_main (j_compress_ptr cinfo, boolean writing = (main->pass_mode != JBUF_CRANK_DEST); while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { - /* Realign the virtual buffers if at the start of an iMCU row. */ - if (main->rowgroup_ctr == 0) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + if (main->rowgroup_ctr == 0) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { main->buffer[ci] = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, main->whole_image[ci], main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); - } - /* In a read pass, pretend we just read some source data. */ - if (! writing) { + } + if (! writing) { *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; main->rowgroup_ctr = DCTSIZE; - } - } + } + } - /* If a write pass, read input data until the current iMCU row is full. */ - /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ - if (writing) { - (*cinfo->prep->pre_process_data) (cinfo, + if (writing) { + (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, main->buffer, &main->rowgroup_ctr, (JDIMENSION) DCTSIZE); - /* Return to application if we need more data to fill the iMCU row. */ - if (main->rowgroup_ctr < DCTSIZE) + if (main->rowgroup_ctr < DCTSIZE) return; - } + } - /* Emit data, unless this is a sink-only pass. */ - if (main->pass_mode != JBUF_SAVE_SOURCE) { - if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { - /* If compressor did not consume the whole row, then we must need to - * suspend processing and return to the application. In this situation - * we pretend we didn't yet consume the last input row; otherwise, if - * it happened to be the last row of the image, the application would - * think we were done. - */ + if (main->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { if (! main->suspended) { (*in_row_ctr)--; main->suspended = TRUE; } return; - } - /* We did finish the row. Undo our little suspension hack if a previous - * call suspended; then mark the main buffer empty. - */ - if (main->suspended) { + } + if (main->suspended) { (*in_row_ctr)++; main->suspended = FALSE; - } - } + } + } - /* If get here, we are done with this iMCU row. Mark buffer empty. */ - main->rowgroup_ctr = 0; - main->cur_iMCU_row++; + main->rowgroup_ctr = 0; + main->cur_iMCU_row++; } } #endif /* FULL_MAIN_BUFFER_SUPPORTED */ -/* - * Initialize main buffer controller. - */ - GLOBAL(void) jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) { @@ -190329,46 +176232,39 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) jpeg_component_info *compptr; main_ = (my_main_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); cinfo->main = (struct jpeg_c_main_controller *) main_; main_->pub.start_pass = start_pass_main; - /* We don't need to create a buffer in raw-data mode. */ if (cinfo->raw_data_in) - return; + return; - /* Create the buffer. It holds downsampled data, so each component - * may be of a different size. - */ if (need_full_buffer) { #ifdef FULL_MAIN_BUFFER_SUPPORTED - /* Allocate a full-image virtual array for each component */ - /* Note we pad the bottom to a multiple of the iMCU height */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, compptr->width_in_blocks * DCTSIZE, (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor) * DCTSIZE, (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); - } + } #else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { #ifdef FULL_MAIN_BUFFER_SUPPORTED - main_->whole_image[0] = NULL; /* flag for no virtual arrays */ + main_->whole_image[0] = NULL; /* flag for no virtual arrays */ #endif - /* Allocate a strip buffer for each component */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - main_->buffer[ci] = (*cinfo->mem->alloc_sarray) + main_->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * DCTSIZE, (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); - } + } } } /********* End of inlined file: jcmainct.c *********/ @@ -190376,8 +176272,6 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) /********* Start of inlined file: jcmarker.c *********/ #define JPEG_INTERNALS -/* Private state */ - typedef struct { struct jpeg_marker_writer pub; /* public fields */ @@ -190386,34 +176280,20 @@ typedef struct { typedef my_marker_writer * my_marker_ptr; -/* - * Basic output routines. - * - * Note that we do not support suspension while writing a marker. - * Therefore, an application using suspension must ensure that there is - * enough buffer space for the initial markers (typ. 600-700 bytes) before - * calling jpeg_start_compress, and enough space to write the trailing EOI - * (a few bytes) before calling jpeg_finish_compress. Multipass compression - * modes are not supported at all with suspension, so those two are the only - * points where markers will be written. - */ - LOCAL(void) emit_byte (j_compress_ptr cinfo, int val) -/* Emit a byte */ { struct jpeg_destination_mgr * dest = cinfo->dest; *(dest->next_output_byte)++ = (JOCTET) val; if (--dest->free_in_buffer == 0) { - if (! (*dest->empty_output_buffer) (cinfo)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); } } LOCAL(void) emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) -/* Emit a marker code */ { emit_byte(cinfo, 0xFF); emit_byte(cinfo, (int) mark); @@ -190421,50 +176301,42 @@ emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) LOCAL(void) emit_2bytes (j_compress_ptr cinfo, int value) -/* Emit a 2-byte integer; these are always MSB first in JPEG files */ { emit_byte(cinfo, (value >> 8) & 0xFF); emit_byte(cinfo, value & 0xFF); } -/* - * Routines to write specific marker types. - */ - LOCAL(int) emit_dqt (j_compress_ptr cinfo, int index) -/* Emit a DQT marker */ -/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ { JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; int prec; int i; if (qtbl == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); prec = 0; for (i = 0; i < DCTSIZE2; i++) { - if (qtbl->quantval[i] > 255) - prec = 1; + if (qtbl->quantval[i] > 255) + prec = 1; } if (! qtbl->sent_table) { - emit_marker(cinfo, M_DQT); + emit_marker(cinfo, M_DQT); - emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); + emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); - emit_byte(cinfo, index + (prec<<4)); + emit_byte(cinfo, index + (prec<<4)); - for (i = 0; i < DCTSIZE2; i++) { - /* The table entries must be emitted in zigzag order. */ - unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; - if (prec) + for (i = 0; i < DCTSIZE2; i++) { + unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; + if (prec) emit_byte(cinfo, (int) (qval >> 8)); - emit_byte(cinfo, (int) (qval & 0xFF)); - } + emit_byte(cinfo, (int) (qval & 0xFF)); + } - qtbl->sent_table = TRUE; + qtbl->sent_table = TRUE; } return prec; @@ -190472,46 +176344,42 @@ emit_dqt (j_compress_ptr cinfo, int index) LOCAL(void) emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) -/* Emit a DHT marker */ { JHUFF_TBL * htbl; int length, i; if (is_ac) { - htbl = cinfo->ac_huff_tbl_ptrs[index]; - index += 0x10; /* output index has AC bit set */ + htbl = cinfo->ac_huff_tbl_ptrs[index]; + index += 0x10; /* output index has AC bit set */ } else { - htbl = cinfo->dc_huff_tbl_ptrs[index]; + htbl = cinfo->dc_huff_tbl_ptrs[index]; } if (htbl == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); if (! htbl->sent_table) { - emit_marker(cinfo, M_DHT); + emit_marker(cinfo, M_DHT); - length = 0; - for (i = 1; i <= 16; i++) - length += htbl->bits[i]; + length = 0; + for (i = 1; i <= 16; i++) + length += htbl->bits[i]; - emit_2bytes(cinfo, length + 2 + 1 + 16); - emit_byte(cinfo, index); + emit_2bytes(cinfo, length + 2 + 1 + 16); + emit_byte(cinfo, index); - for (i = 1; i <= 16; i++) - emit_byte(cinfo, htbl->bits[i]); + for (i = 1; i <= 16; i++) + emit_byte(cinfo, htbl->bits[i]); - for (i = 0; i < length; i++) - emit_byte(cinfo, htbl->huffval[i]); + for (i = 0; i < length; i++) + emit_byte(cinfo, htbl->huffval[i]); - htbl->sent_table = TRUE; + htbl->sent_table = TRUE; } } LOCAL(void) emit_dac (j_compress_ptr cinfo) -/* Emit a DAC marker */ -/* Since the useful info is so small, we want to emit all the tables in */ -/* one DAC marker. Therefore this routine does its own scan of the table. */ { #ifdef C_ARITH_CODING_SUPPORTED char dc_in_use[NUM_ARITH_TBLS]; @@ -190520,38 +176388,37 @@ emit_dac (j_compress_ptr cinfo) jpeg_component_info *compptr; for (i = 0; i < NUM_ARITH_TBLS; i++) - dc_in_use[i] = ac_in_use[i] = 0; + dc_in_use[i] = ac_in_use[i] = 0; for (i = 0; i < cinfo->comps_in_scan; i++) { - compptr = cinfo->cur_comp_info[i]; - dc_in_use[compptr->dc_tbl_no] = 1; - ac_in_use[compptr->ac_tbl_no] = 1; + compptr = cinfo->cur_comp_info[i]; + dc_in_use[compptr->dc_tbl_no] = 1; + ac_in_use[compptr->ac_tbl_no] = 1; } length = 0; for (i = 0; i < NUM_ARITH_TBLS; i++) - length += dc_in_use[i] + ac_in_use[i]; + length += dc_in_use[i] + ac_in_use[i]; emit_marker(cinfo, M_DAC); emit_2bytes(cinfo, length*2 + 2); for (i = 0; i < NUM_ARITH_TBLS; i++) { - if (dc_in_use[i]) { - emit_byte(cinfo, i); - emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); - } - if (ac_in_use[i]) { - emit_byte(cinfo, i + 0x10); - emit_byte(cinfo, cinfo->arith_ac_K[i]); - } + if (dc_in_use[i]) { + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + } + if (ac_in_use[i]) { + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); + } } #endif /* C_ARITH_CODING_SUPPORTED */ } LOCAL(void) emit_dri (j_compress_ptr cinfo) -/* Emit a DRI marker */ { emit_marker(cinfo, M_DRI); @@ -190562,7 +176429,6 @@ emit_dri (j_compress_ptr cinfo) LOCAL(void) emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) -/* Emit a SOF marker */ { int ci; jpeg_component_info *compptr; @@ -190571,10 +176437,9 @@ emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ - /* Make sure image isn't bigger than SOF field can handle */ if ((long) cinfo->image_height > 65535L || - (long) cinfo->image_width > 65535L) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); + (long) cinfo->image_width > 65535L) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); emit_byte(cinfo, cinfo->data_precision); emit_2bytes(cinfo, (int) cinfo->image_height); @@ -190583,16 +176448,15 @@ emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) emit_byte(cinfo, cinfo->num_components); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - emit_byte(cinfo, compptr->component_id); - emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); - emit_byte(cinfo, compptr->quant_tbl_no); + ci++, compptr++) { + emit_byte(cinfo, compptr->component_id); + emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); + emit_byte(cinfo, compptr->quant_tbl_no); } } LOCAL(void) emit_sos (j_compress_ptr cinfo) -/* Emit a SOS marker */ { int i, td, ta; jpeg_component_info *compptr; @@ -190604,25 +176468,20 @@ emit_sos (j_compress_ptr cinfo) emit_byte(cinfo, cinfo->comps_in_scan); for (i = 0; i < cinfo->comps_in_scan; i++) { - compptr = cinfo->cur_comp_info[i]; - emit_byte(cinfo, compptr->component_id); - td = compptr->dc_tbl_no; - ta = compptr->ac_tbl_no; - if (cinfo->progressive_mode) { - /* Progressive mode: only DC or only AC tables are used in one scan; - * furthermore, Huffman coding of DC refinement uses no table at all. - * We emit 0 for unused field(s); this is recommended by the P&M text - * but does not seem to be specified in the standard. - */ - if (cinfo->Ss == 0) { + compptr = cinfo->cur_comp_info[i]; + emit_byte(cinfo, compptr->component_id); + td = compptr->dc_tbl_no; + ta = compptr->ac_tbl_no; + if (cinfo->progressive_mode) { + if (cinfo->Ss == 0) { ta = 0; /* DC scan */ if (cinfo->Ah != 0 && !cinfo->arith_code) td = 0; /* no DC table either */ - } else { + } else { td = 0; /* AC scan */ - } - } - emit_byte(cinfo, (td << 4) + ta); + } + } + emit_byte(cinfo, (td << 4) + ta); } emit_byte(cinfo, cinfo->Ss); @@ -190632,19 +176491,7 @@ emit_sos (j_compress_ptr cinfo) LOCAL(void) emit_jfif_app0 (j_compress_ptr cinfo) -/* Emit a JFIF-compliant APP0 marker */ { - /* - * Length of APP0 block (2 bytes) - * Block ID (4 bytes - ASCII "JFIF") - * Zero byte (1 byte to terminate the ID string) - * Version Major, Minor (2 bytes - major first) - * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) - * Xdpu (2 bytes - dots per unit horizontal) - * Ydpu (2 bytes - dots per unit vertical) - * Thumbnail X size (1 byte) - * Thumbnail Y size (1 byte) - */ emit_marker(cinfo, M_APP0); @@ -190666,23 +176513,7 @@ emit_jfif_app0 (j_compress_ptr cinfo) LOCAL(void) emit_adobe_app14 (j_compress_ptr cinfo) -/* Emit an Adobe APP14 marker */ { - /* - * Length of APP14 block (2 bytes) - * Block ID (5 bytes - ASCII "Adobe") - * Version Number (2 bytes - currently 100) - * Flags0 (2 bytes - currently 0) - * Flags1 (2 bytes - currently 0) - * Color transform (1 byte) - * - * Although Adobe TN 5116 mentions Version = 101, all the Adobe files - * now in circulation seem to use Version = 100, so that's what we write. - * - * We write the color transform byte as 1 if the JPEG color space is - * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with - * whether the encoder performed a transformation, which is pretty useless. - */ emit_marker(cinfo, M_APP14); @@ -190698,31 +176529,22 @@ emit_adobe_app14 (j_compress_ptr cinfo) emit_2bytes(cinfo, 0); /* Flags1 */ switch (cinfo->jpeg_color_space) { case JCS_YCbCr: - emit_byte(cinfo, 1); /* Color transform = 1 */ - break; + emit_byte(cinfo, 1); /* Color transform = 1 */ + break; case JCS_YCCK: - emit_byte(cinfo, 2); /* Color transform = 2 */ - break; + emit_byte(cinfo, 2); /* Color transform = 2 */ + break; default: - emit_byte(cinfo, 0); /* Color transform = 0 */ - break; + emit_byte(cinfo, 0); /* Color transform = 0 */ + break; } } -/* - * These routines allow writing an arbitrary marker with parameters. - * The only intended use is to emit COM or APPn markers after calling - * write_file_header and before calling write_frame_header. - * Other uses are not guaranteed to produce desirable results. - * Counting the parameter bytes properly is the caller's responsibility. - */ - METHODDEF(void) write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) -/* Emit an arbitrary marker header */ { if (datalen > (unsigned int) 65533) /* safety check */ - ERREXIT(cinfo, JERR_BAD_LENGTH); + ERREXIT(cinfo, JERR_BAD_LENGTH); emit_marker(cinfo, (JPEG_MARKER) marker); @@ -190731,22 +176553,10 @@ write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) METHODDEF(void) write_marker_byte (j_compress_ptr cinfo, int val) -/* Emit one byte of marker parameters following write_marker_header */ { emit_byte(cinfo, val); } -/* - * Write datastream header. - * This consists of an SOI and optional APPn markers. - * We recommend use of the JFIF marker, but not the Adobe marker, - * when using YCbCr or grayscale data. The JFIF marker should NOT - * be used for any other JPEG colorspace. The Adobe marker is helpful - * to distinguish RGB, CMYK, and YCCK colorspaces. - * Note that an application can write additional header markers after - * jpeg_start_compress returns. - */ - METHODDEF(void) write_file_header (j_compress_ptr cinfo) { @@ -190754,23 +176564,14 @@ write_file_header (j_compress_ptr cinfo) emit_marker(cinfo, M_SOI); /* first the SOI */ - /* SOI is defined to reset restart interval to 0 */ marker->last_restart_interval = 0; if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ - emit_jfif_app0(cinfo); + emit_jfif_app0(cinfo); if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ - emit_adobe_app14(cinfo); + emit_adobe_app14(cinfo); } -/* - * Write frame header. - * This consists of DQT and SOFn markers. - * Note that we do not emit the SOF until we have emitted the DQT(s). - * This avoids compatibility problems with incorrect implementations that - * try to error-check the quant table numbers as soon as they see the SOF. - */ - METHODDEF(void) write_frame_header (j_compress_ptr cinfo) { @@ -190778,55 +176579,40 @@ write_frame_header (j_compress_ptr cinfo) boolean is_baseline; jpeg_component_info *compptr; - /* Emit DQT for each quantization table. - * Note that emit_dqt() suppresses any duplicate tables. - */ prec = 0; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - prec += emit_dqt(cinfo, compptr->quant_tbl_no); + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); } - /* now prec is nonzero iff there are any 16-bit quant tables. */ - /* Check for a non-baseline specification. - * Note we assume that Huffman table numbers won't be changed later. - */ if (cinfo->arith_code || cinfo->progressive_mode || - cinfo->data_precision != 8) { - is_baseline = FALSE; - } else { - is_baseline = TRUE; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + cinfo->data_precision != 8) { is_baseline = FALSE; - } - if (prec && is_baseline) { - is_baseline = FALSE; - /* If it's baseline except for quantizer size, warn the user */ - TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); - } + } else { + is_baseline = TRUE; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + is_baseline = FALSE; + } + if (prec && is_baseline) { + is_baseline = FALSE; + TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + } } - /* Emit the proper SOF marker */ if (cinfo->arith_code) { - emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ + emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ } else { - if (cinfo->progressive_mode) - emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ - else if (is_baseline) - emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ - else - emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + if (cinfo->progressive_mode) + emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (is_baseline) + emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ + else + emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ } } -/* - * Write scan header. - * This consists of DHT or DAC markers, optional DRI, and SOS. - * Compressed data will be written following the SOS. - */ - METHODDEF(void) write_scan_header (j_compress_ptr cinfo) { @@ -190835,61 +176621,38 @@ write_scan_header (j_compress_ptr cinfo) jpeg_component_info *compptr; if (cinfo->arith_code) { - /* Emit arith conditioning info. We may have some duplication - * if the file has multiple scans, but it's so small it's hardly - * worth worrying about. - */ - emit_dac(cinfo); + emit_dac(cinfo); } else { - /* Emit Huffman tables. - * Note that emit_dht() suppresses any duplicate tables. - */ - for (i = 0; i < cinfo->comps_in_scan; i++) { - compptr = cinfo->cur_comp_info[i]; - if (cinfo->progressive_mode) { - /* Progressive mode: only DC or only AC tables are used in one scan */ + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + if (cinfo->progressive_mode) { if (cinfo->Ss == 0) { if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); } else { emit_dht(cinfo, compptr->ac_tbl_no, TRUE); } - } else { - /* Sequential mode: need both DC and AC tables */ + } else { emit_dht(cinfo, compptr->dc_tbl_no, FALSE); emit_dht(cinfo, compptr->ac_tbl_no, TRUE); - } - } + } + } } - /* Emit DRI if required --- note that DRI value could change for each scan. - * We avoid wasting space with unnecessary DRIs, however. - */ if (cinfo->restart_interval != marker->last_restart_interval) { - emit_dri(cinfo); - marker->last_restart_interval = cinfo->restart_interval; + emit_dri(cinfo); + marker->last_restart_interval = cinfo->restart_interval; } emit_sos(cinfo); } -/* - * Write datastream trailer. - */ - METHODDEF(void) write_file_trailer (j_compress_ptr cinfo) { emit_marker(cinfo, M_EOI); } -/* - * Write an abbreviated table-specification datastream. - * This consists of SOI, DQT and DHT tables, and EOI. - * Any table that is defined and not marked sent_table = TRUE will be - * emitted. Note that all tables will be marked sent_table = TRUE at exit. - */ - METHODDEF(void) write_tables_only (j_compress_ptr cinfo) { @@ -190898,37 +176661,31 @@ write_tables_only (j_compress_ptr cinfo) emit_marker(cinfo, M_SOI); for (i = 0; i < NUM_QUANT_TBLS; i++) { - if (cinfo->quant_tbl_ptrs[i] != NULL) - (void) emit_dqt(cinfo, i); + if (cinfo->quant_tbl_ptrs[i] != NULL) + (void) emit_dqt(cinfo, i); } if (! cinfo->arith_code) { - for (i = 0; i < NUM_HUFF_TBLS; i++) { - if (cinfo->dc_huff_tbl_ptrs[i] != NULL) + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL) emit_dht(cinfo, i, FALSE); - if (cinfo->ac_huff_tbl_ptrs[i] != NULL) + if (cinfo->ac_huff_tbl_ptrs[i] != NULL) emit_dht(cinfo, i, TRUE); - } + } } emit_marker(cinfo, M_EOI); } -/* - * Initialize the marker writer module. - */ - GLOBAL(void) jinit_marker_writer (j_compress_ptr cinfo) { my_marker_ptr marker; - /* Create the subobject */ marker = (my_marker_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_marker_writer)); cinfo->marker = (struct jpeg_marker_writer *) marker; - /* Initialize method pointers */ marker->pub.write_file_header = write_file_header; marker->pub.write_frame_header = write_frame_header; marker->pub.write_scan_header = write_scan_header; @@ -190936,7 +176693,6 @@ jinit_marker_writer (j_compress_ptr cinfo) marker->pub.write_tables_only = write_tables_only; marker->pub.write_marker_header = write_marker_header; marker->pub.write_marker_byte = write_marker_byte; - /* Initialize private state */ marker->last_restart_interval = 0; } /********* End of inlined file: jcmarker.c *********/ @@ -190944,8 +176700,6 @@ jinit_marker_writer (j_compress_ptr cinfo) /********* Start of inlined file: jcmaster.c *********/ #define JPEG_INTERNALS -/* Private state */ - typedef enum { main_pass, /* input data, also do first output step */ huff_opt_pass, /* Huffman code optimization pass */ @@ -190965,88 +176719,68 @@ typedef struct { typedef my_comp_master * my_master_ptr; -/* - * Support routines that do various essential calculations. - */ - LOCAL(void) initial_setup (j_compress_ptr cinfo) -/* Do computations that are needed before master selection phase */ { int ci; jpeg_component_info *compptr; long samplesperrow; JDIMENSION jd_samplesperrow; - /* Sanity check on image dimensions */ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0 || cinfo->input_components <= 0) - ERREXIT(cinfo, JERR_EMPTY_IMAGE); + || cinfo->num_components <= 0 || cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); - /* Make sure image isn't bigger than I can handle */ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || - (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - /* Width of an input scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; jd_samplesperrow = (JDIMENSION) samplesperrow; if ((long) jd_samplesperrow != samplesperrow) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - /* For now, precision must match compiled-in value... */ if (cinfo->data_precision != BITS_IN_JSAMPLE) - ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); - /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) - ERREXIT(cinfo, JERR_BAD_SAMPLING); - cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); - cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } - /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Fill in the correct component_index value; don't rely on application */ - compptr->component_index = ci; - /* For compression, we never do DCT scaling. */ - compptr->DCT_scaled_size = DCTSIZE; - /* Size in DCT blocks */ - compptr->width_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - /* Size in samples */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); - /* Mark component needed (this flag isn't actually used for compression) */ - compptr->component_needed = TRUE; + ci++, compptr++) { + compptr->component_index = ci; + compptr->DCT_scaled_size = DCTSIZE; + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + compptr->component_needed = TRUE; } - /* Compute number of fully interleaved MCU rows (number of times that - * main controller will call coefficient controller). - */ cinfo->total_iMCU_rows = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, + jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); } @@ -191054,9 +176788,6 @@ initial_setup (j_compress_ptr cinfo) LOCAL(void) validate_script (j_compress_ptr cinfo) -/* Verify that the scan script in cinfo->scan_info[] is valid; also - * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. - */ { const jpeg_scan_info * scanptr; int scanno, ncomps, ci, coefi, thisi; @@ -191065,124 +176796,100 @@ validate_script (j_compress_ptr cinfo) #ifdef C_PROGRESSIVE_SUPPORTED int * last_bitpos_ptr; int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; - /* -1 until that coefficient has been seen; then last Al for it */ #endif if (cinfo->num_scans <= 0) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); - /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; - * for progressive JPEG, no scan can have this. - */ scanptr = cinfo->scan_info; if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { #ifdef C_PROGRESSIVE_SUPPORTED - cinfo->progressive_mode = TRUE; - last_bitpos_ptr = & last_bitpos[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) - for (coefi = 0; coefi < DCTSIZE2; coefi++) + cinfo->progressive_mode = TRUE; + last_bitpos_ptr = & last_bitpos[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (coefi = 0; coefi < DCTSIZE2; coefi++) *last_bitpos_ptr++ = -1; #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - cinfo->progressive_mode = FALSE; - for (ci = 0; ci < cinfo->num_components; ci++) - component_sent[ci] = FALSE; + cinfo->progressive_mode = FALSE; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; } for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { - /* Validate component indexes */ - ncomps = scanptr->comps_in_scan; - if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); - for (ci = 0; ci < ncomps; ci++) { - thisi = scanptr->component_index[ci]; - if (thisi < 0 || thisi >= cinfo->num_components) + ncomps = scanptr->comps_in_scan; + if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (thisi < 0 || thisi >= cinfo->num_components) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); - /* Components must appear in SOF order within each scan */ - if (ci > 0 && thisi <= scanptr->component_index[ci-1]) + if (ci > 0 && thisi <= scanptr->component_index[ci-1]) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); - } - /* Validate progression parameters */ - Ss = scanptr->Ss; - Se = scanptr->Se; - Ah = scanptr->Ah; - Al = scanptr->Al; - if (cinfo->progressive_mode) { + } + Ss = scanptr->Ss; + Se = scanptr->Se; + Ah = scanptr->Ah; + Al = scanptr->Al; + if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED - /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that - * seems wrong: the upper bound ought to depend on data precision. - * Perhaps they really meant 0..N+1 for N-bit precision. - * Here we allow 0..10 for 8-bit data; Al larger than 10 results in - * out-of-range reconstructed DC values during the first DC scan, - * which might cause problems for some decoders. - */ #if BITS_IN_JSAMPLE == 8 #define MAX_AH_AL 10 #else #define MAX_AH_AL 13 #endif - if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - if (Ss == 0) { + if (Ss == 0) { if (Se != 0) /* DC and AC together not OK */ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } else { + } else { if (ncomps != 1) /* AC scans must be for only one component */ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } - for (ci = 0; ci < ncomps; ci++) { + } + for (ci = 0; ci < ncomps; ci++) { last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); for (coefi = Ss; coefi <= Se; coefi++) { if (last_bitpos_ptr[coefi] < 0) { - /* first scan of this coefficient */ - if (Ah != 0) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Ah != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } else { - /* not first scan */ - if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } last_bitpos_ptr[coefi] = Al; } - } + } #endif - } else { - /* For sequential JPEG, all progression parameters must be these: */ - if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) + } else { + if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - /* Make sure components are not sent twice */ - for (ci = 0; ci < ncomps; ci++) { + for (ci = 0; ci < ncomps; ci++) { thisi = scanptr->component_index[ci]; if (component_sent[thisi]) ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); component_sent[thisi] = TRUE; - } - } + } + } } - /* Now verify that everything got sent. */ if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED - /* For progressive mode, we only check that at least some DC data - * got sent for each component; the spec does not require that all bits - * of all coefficients be transmitted. Would it be wiser to enforce - * transmission of all coefficient bits?? - */ - for (ci = 0; ci < cinfo->num_components; ci++) { - if (last_bitpos[ci][0] < 0) + for (ci = 0; ci < cinfo->num_components; ci++) { + if (last_bitpos[ci][0] < 0) ERREXIT(cinfo, JERR_MISSING_DATA); - } + } #endif } else { - for (ci = 0; ci < cinfo->num_components; ci++) { - if (! component_sent[ci]) + for (ci = 0; ci < cinfo->num_components; ci++) { + if (! component_sent[ci]) ERREXIT(cinfo, JERR_MISSING_DATA); - } + } } } @@ -191190,136 +176897,109 @@ validate_script (j_compress_ptr cinfo) LOCAL(void) select_scan_parameters (j_compress_ptr cinfo) -/* Set up the scan parameters for the current scan */ { int ci; #ifdef C_MULTISCAN_FILES_SUPPORTED if (cinfo->scan_info != NULL) { - /* Prepare for current scan --- the script is already validated */ - my_master_ptr master = (my_master_ptr) cinfo->master; - const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; + my_master_ptr master = (my_master_ptr) cinfo->master; + const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; - cinfo->comps_in_scan = scanptr->comps_in_scan; - for (ci = 0; ci < scanptr->comps_in_scan; ci++) { - cinfo->cur_comp_info[ci] = + cinfo->comps_in_scan = scanptr->comps_in_scan; + for (ci = 0; ci < scanptr->comps_in_scan; ci++) { + cinfo->cur_comp_info[ci] = &cinfo->comp_info[scanptr->component_index[ci]]; - } - cinfo->Ss = scanptr->Ss; - cinfo->Se = scanptr->Se; - cinfo->Ah = scanptr->Ah; - cinfo->Al = scanptr->Al; + } + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; } else #endif { - /* Prepare for single sequential-JPEG scan containing all components */ - if (cinfo->num_components > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPS_IN_SCAN); - cinfo->comps_in_scan = cinfo->num_components; - for (ci = 0; ci < cinfo->num_components; ci++) { - cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; - } - cinfo->Ss = 0; - cinfo->Se = DCTSIZE2-1; - cinfo->Ah = 0; - cinfo->Al = 0; + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + cinfo->comps_in_scan = cinfo->num_components; + for (ci = 0; ci < cinfo->num_components; ci++) { + cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; + } + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2-1; + cinfo->Ah = 0; + cinfo->Al = 0; } } LOCAL(void) per_scan_setup (j_compress_ptr cinfo) -/* Do computations that are needed before processing a JPEG scan */ -/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ { int ci, mcublks, tmp; jpeg_component_info *compptr; if (cinfo->comps_in_scan == 1) { - /* Noninterleaved (single-component) scan */ - compptr = cinfo->cur_comp_info[0]; + compptr = cinfo->cur_comp_info[0]; - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = compptr->width_in_blocks; - cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - /* For noninterleaved scan, always one block per MCU */ - compptr->MCU_width = 1; - compptr->MCU_height = 1; - compptr->MCU_blocks = 1; - compptr->MCU_sample_width = DCTSIZE; - compptr->last_col_width = 1; - /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of block rows present in the last iMCU row. - */ - tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (tmp == 0) tmp = compptr->v_samp_factor; - compptr->last_row_height = tmp; + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = DCTSIZE; + compptr->last_col_width = 1; + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; - /* Prepare array describing MCU composition */ - cinfo->blocks_in_MCU = 1; - cinfo->MCU_membership[0] = 0; + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; } else { - /* Interleaved (multi-component) scan */ - if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, - MAX_COMPS_IN_SCAN); + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*DCTSIZE)); - cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*DCTSIZE)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); - cinfo->blocks_in_MCU = 0; + cinfo->blocks_in_MCU = 0; - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of blocks of component in each MCU */ - compptr->MCU_width = compptr->h_samp_factor; - compptr->MCU_height = compptr->v_samp_factor; - compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; - /* Figure number of non-dummy blocks in last MCU column & row */ - tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); - if (tmp == 0) tmp = compptr->MCU_width; - compptr->last_col_width = tmp; - tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); - if (tmp == 0) tmp = compptr->MCU_height; - compptr->last_row_height = tmp; - /* Prepare array describing MCU composition */ - mcublks = compptr->MCU_blocks; - if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); - while (mcublks-- > 0) { + while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; - } - } + } + } } - /* Convert restart specified in rows to actual MCU count. */ - /* Note that count must fit in 16 bits, so we provide limiting. */ if (cinfo->restart_in_rows > 0) { - long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; - cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); + long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; + cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); } } -/* - * Per-pass setup. - * This is called at the beginning of each pass. We determine which modules - * will be active during this pass and give them appropriate start_pass calls. - * We also set is_last_pass to indicate whether any more passes will be - * required. - */ - METHODDEF(void) prepare_for_pass (j_compress_ptr cinfo) { @@ -191327,86 +177007,62 @@ prepare_for_pass (j_compress_ptr cinfo) switch (master->pass_type) { case main_pass: - /* Initial pass: will collect input data, and do either Huffman - * optimization or data output for the first scan. - */ - select_scan_parameters(cinfo); - per_scan_setup(cinfo); - if (! cinfo->raw_data_in) { - (*cinfo->cconvert->start_pass) (cinfo); - (*cinfo->downsample->start_pass) (cinfo); - (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); - } - (*cinfo->fdct->start_pass) (cinfo); - (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); - (*cinfo->coef->start_pass) (cinfo, + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (! cinfo->raw_data_in) { + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->downsample->start_pass) (cinfo); + (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); + } + (*cinfo->fdct->start_pass) (cinfo); + (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); + (*cinfo->coef->start_pass) (cinfo, (master->total_passes > 1 ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); - (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); - if (cinfo->optimize_coding) { - /* No immediate data output; postpone writing frame/scan headers */ - master->pub.call_pass_startup = FALSE; - } else { - /* Will write frame/scan headers at first jpeg_write_scanlines call */ - master->pub.call_pass_startup = TRUE; - } - break; + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + if (cinfo->optimize_coding) { + master->pub.call_pass_startup = FALSE; + } else { + master->pub.call_pass_startup = TRUE; + } + break; #ifdef ENTROPY_OPT_SUPPORTED case huff_opt_pass: - /* Do Huffman optimization for a scan after the first one. */ - select_scan_parameters(cinfo); - per_scan_setup(cinfo); - if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { - (*cinfo->entropy->start_pass) (cinfo, TRUE); - (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); - master->pub.call_pass_startup = FALSE; - break; - } - /* Special case: Huffman DC refinement scans need no Huffman table - * and therefore we can skip the optimization pass for them. - */ - master->pass_type = output_pass; - master->pass_number++; - /*FALLTHROUGH*/ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { + (*cinfo->entropy->start_pass) (cinfo, TRUE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + master->pub.call_pass_startup = FALSE; + break; + } + master->pass_type = output_pass; + master->pass_number++; #endif case output_pass: - /* Do a data-output pass. */ - /* We need not repeat per-scan setup if prior optimization pass did it. */ - if (! cinfo->optimize_coding) { - select_scan_parameters(cinfo); - per_scan_setup(cinfo); - } - (*cinfo->entropy->start_pass) (cinfo, FALSE); - (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); - /* We emit frame/scan headers now */ - if (master->scan_number == 0) - (*cinfo->marker->write_frame_header) (cinfo); - (*cinfo->marker->write_scan_header) (cinfo); - master->pub.call_pass_startup = FALSE; - break; + if (! cinfo->optimize_coding) { + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + } + (*cinfo->entropy->start_pass) (cinfo, FALSE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + if (master->scan_number == 0) + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); + master->pub.call_pass_startup = FALSE; + break; default: - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); } master->pub.is_last_pass = (master->pass_number == master->total_passes-1); - /* Set up progress monitor's pass info if present */ if (cinfo->progress != NULL) { - cinfo->progress->completed_passes = master->pass_number; - cinfo->progress->total_passes = master->total_passes; + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->total_passes; } } -/* - * Special start-of-pass hook. - * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. - * In single-pass processing, we need this hook because we don't want to - * write frame/scan headers during jpeg_start_compress; we want to let the - * application write COM markers etc. between jpeg_start_compress and the - * jpeg_write_scanlines loop. - * In multi-pass processing, this routine is not used. - */ - METHODDEF(void) pass_startup (j_compress_ptr cinfo) { @@ -191416,56 +177072,39 @@ pass_startup (j_compress_ptr cinfo) (*cinfo->marker->write_scan_header) (cinfo); } -/* - * Finish up at end of pass. - */ - METHODDEF(void) finish_pass_master (j_compress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; - /* The entropy coder always needs an end-of-pass call, - * either to analyze statistics or to flush its output buffer. - */ (*cinfo->entropy->finish_pass) (cinfo); - /* Update state for next pass */ switch (master->pass_type) { case main_pass: - /* next pass is either output of scan 0 (after optimization) - * or output of scan 1 (if no optimization). - */ - master->pass_type = output_pass; - if (! cinfo->optimize_coding) - master->scan_number++; - break; + master->pass_type = output_pass; + if (! cinfo->optimize_coding) + master->scan_number++; + break; case huff_opt_pass: - /* next pass is always output of current scan */ - master->pass_type = output_pass; - break; + master->pass_type = output_pass; + break; case output_pass: - /* next pass is either optimization or output of next scan */ - if (cinfo->optimize_coding) - master->pass_type = huff_opt_pass; - master->scan_number++; - break; + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + master->scan_number++; + break; } master->pass_number++; } -/* - * Initialize master compression control. - */ - GLOBAL(void) jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) { my_master_ptr master; master = (my_master_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_comp_master)); cinfo->master = (struct jpeg_comp_master *) master; master->pub.prepare_for_pass = prepare_for_pass; @@ -191473,119 +177112,78 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) master->pub.finish_pass = finish_pass_master; master->pub.is_last_pass = FALSE; - /* Validate parameters, determine derived values */ initial_setup(cinfo); if (cinfo->scan_info != NULL) { #ifdef C_MULTISCAN_FILES_SUPPORTED - validate_script(cinfo); + validate_script(cinfo); #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - cinfo->progressive_mode = FALSE; - cinfo->num_scans = 1; + cinfo->progressive_mode = FALSE; + cinfo->num_scans = 1; } if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */ - cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ + cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ - /* Initialize my private state */ if (transcode_only) { - /* no main pass in transcoding */ - if (cinfo->optimize_coding) - master->pass_type = huff_opt_pass; - else - master->pass_type = output_pass; + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + else + master->pass_type = output_pass; } else { - /* for normal compression, first pass is always this type: */ - master->pass_type = main_pass; + master->pass_type = main_pass; } master->scan_number = 0; master->pass_number = 0; if (cinfo->optimize_coding) - master->total_passes = cinfo->num_scans * 2; + master->total_passes = cinfo->num_scans * 2; else - master->total_passes = cinfo->num_scans; + master->total_passes = cinfo->num_scans; } /********* End of inlined file: jcmaster.c *********/ /********* Start of inlined file: jcomapi.c *********/ #define JPEG_INTERNALS -/* - * Abort processing of a JPEG compression or decompression operation, - * but don't destroy the object itself. - * - * For this, we merely clean up all the nonpermanent memory pools. - * Note that temp files (virtual arrays) are not allowed to belong to - * the permanent pool, so we will be able to close all temp files here. - * Closing a data source or destination, if necessary, is the application's - * responsibility. - */ - GLOBAL(void) jpeg_abort (j_common_ptr cinfo) { int pool; - /* Do nothing if called on a not-initialized or destroyed JPEG object. */ if (cinfo->mem == NULL) - return; + return; - /* Releasing pools in reverse order might help avoid fragmentation - * with some (brain-damaged) malloc libraries. - */ for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { - (*cinfo->mem->free_pool) (cinfo, pool); + (*cinfo->mem->free_pool) (cinfo, pool); } - /* Reset overall state for possible reuse of object */ if (cinfo->is_decompressor) { - cinfo->global_state = DSTATE_START; - /* Try to keep application from accessing now-deleted marker list. - * A bit kludgy to do it here, but this is the most central place. - */ - ((j_decompress_ptr) cinfo)->marker_list = NULL; + cinfo->global_state = DSTATE_START; + ((j_decompress_ptr) cinfo)->marker_list = NULL; } else { - cinfo->global_state = CSTATE_START; + cinfo->global_state = CSTATE_START; } } -/* - * Destruction of a JPEG object. - * - * Everything gets deallocated except the master jpeg_compress_struct itself - * and the error manager struct. Both of these are supplied by the application - * and must be freed, if necessary, by the application. (Often they are on - * the stack and so don't need to be freed anyway.) - * Closing a data source or destination, if necessary, is the application's - * responsibility. - */ - GLOBAL(void) jpeg_destroy (j_common_ptr cinfo) { - /* We need only tell the memory manager to release everything. */ - /* NB: mem pointer is NULL if memory mgr failed to initialize. */ if (cinfo->mem != NULL) - (*cinfo->mem->self_destruct) (cinfo); + (*cinfo->mem->self_destruct) (cinfo); cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ cinfo->global_state = 0; /* mark it destroyed */ } -/* - * Convenience routines for allocating quantization and Huffman tables. - * (Would jutils.c be a more reasonable place to put these?) - */ - GLOBAL(JQUANT_TBL *) jpeg_alloc_quant_table (j_common_ptr cinfo) { JQUANT_TBL *tbl; tbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); tbl->sent_table = FALSE; /* make sure this is false in any new table */ return tbl; } @@ -191596,7 +177194,7 @@ jpeg_alloc_huff_table (j_common_ptr cinfo) JHUFF_TBL *tbl; tbl = (JHUFF_TBL *) - (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); tbl->sent_table = FALSE; /* make sure this is false in any new table */ return tbl; } @@ -191605,228 +177203,175 @@ jpeg_alloc_huff_table (j_common_ptr cinfo) /********* Start of inlined file: jcparam.c *********/ #define JPEG_INTERNALS -/* - * Quantization table setup routines - */ - GLOBAL(void) jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, boolean force_baseline) -/* Define a quantization table equal to the basic_table times - * a scale factor (given as a percentage). - * If force_baseline is TRUE, the computed quantization table entries - * are limited to 1..255 for JPEG baseline compatibility. - */ + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) { JQUANT_TBL ** qtblptr; int i; long temp; - /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) - ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); + ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; if (*qtblptr == NULL) - *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); for (i = 0; i < DCTSIZE2; i++) { - temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; - /* limit the values to the valid range */ - if (temp <= 0L) temp = 1L; - if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ - if (force_baseline && temp > 255L) - temp = 255L; /* limit to baseline range if requested */ - (*qtblptr)->quantval[i] = (UINT16) temp; + temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; + if (temp <= 0L) temp = 1L; + if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ + if (force_baseline && temp > 255L) + temp = 255L; /* limit to baseline range if requested */ + (*qtblptr)->quantval[i] = (UINT16) temp; } - /* Initialize sent_table FALSE so table will be written to JPEG file. */ (*qtblptr)->sent_table = FALSE; } GLOBAL(void) jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, boolean force_baseline) -/* Set or change the 'quality' (quantization) setting, using default tables - * and a straight percentage-scaling quality scale. In most cases it's better - * to use jpeg_set_quality (below); this entry point is provided for - * applications that insist on a linear percentage scaling. - */ { - /* These are the sample quantization tables given in JPEG spec section K.1. - * The spec says that the values given produce "good" quality, and - * when divided by 2, "very good" quality. - */ static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 }; static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 }; - /* Set up two quantization tables using the specified scaling */ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, - scale_factor, force_baseline); + scale_factor, force_baseline); jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, - scale_factor, force_baseline); + scale_factor, force_baseline); } GLOBAL(int) jpeg_quality_scaling (int quality) -/* Convert a user-specified quality rating to a percentage scaling factor - * for an underlying quantization table, using our recommended scaling curve. - * The input 'quality' factor should be 0 (terrible) to 100 (very good). - */ { - /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ if (quality <= 0) quality = 1; if (quality > 100) quality = 100; - /* The basic table is used as-is (scaling 100) for a quality of 50. - * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; - * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table - * to make all the table entries 1 (hence, minimum quantization loss). - * Qualities 1..50 are converted to scaling percentage 5000/Q. - */ if (quality < 50) - quality = 5000 / quality; + quality = 5000 / quality; else - quality = 200 - quality*2; + quality = 200 - quality*2; return quality; } GLOBAL(void) jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) -/* Set or change the 'quality' (quantization) setting, using default tables. - * This is the standard quality-adjusting entry point for typical user - * interfaces; only those who want detailed control over quantization tables - * would use the preceding three routines directly. - */ { - /* Convert user 0-100 rating to percentage scaling */ quality = jpeg_quality_scaling(quality); - /* Set up standard quality tables */ jpeg_set_linear_quality(cinfo, quality, force_baseline); } -/* - * Huffman table setup routines - */ - LOCAL(void) add_huff_table (j_compress_ptr cinfo, JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) -/* Define a Huffman table */ { int nsymbols, len; if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - /* Copy the number-of-symbols-of-each-code-length counts */ MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); - /* Validate the counts. We do this here mainly so we can copy the right - * number of symbols from the val[] array, without risking marching off - * the end of memory. jchuff.c will do a more thorough test later. - */ nsymbols = 0; for (len = 1; len <= 16; len++) - nsymbols += bits[len]; + nsymbols += bits[len]; if (nsymbols < 1 || nsymbols > 256) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); - /* Initialize sent_table FALSE so table will be written to JPEG file. */ (*htblptr)->sent_table = FALSE; } LOCAL(void) std_huff_tables (j_compress_ptr cinfo) -/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ -/* IMPORTANT: these are only valid for 8-bit data precision! */ { static const UINT8 bits_dc_luminance[17] = - { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_luminance[] = - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 bits_dc_chrominance[17] = - { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_chrominance[] = - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 bits_ac_luminance[17] = - { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static const UINT8 val_ac_luminance[] = - { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa }; + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; static const UINT8 bits_ac_chrominance[17] = - { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static const UINT8 val_ac_chrominance[] = - { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, - 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, - 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa }; + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], bits_dc_luminance, val_dc_luminance); @@ -191838,137 +177383,85 @@ std_huff_tables (j_compress_ptr cinfo) bits_ac_chrominance, val_ac_chrominance); } -/* - * Default parameter setup for compression. - * - * Applications that don't choose to use this routine must do their - * own setup of all these parameters. Alternately, you can call this - * to establish defaults and then alter parameters selectively. This - * is the recommended approach since, if we add any new parameters, - * your code will still work (they'll be set to reasonable defaults). - */ - GLOBAL(void) jpeg_set_defaults (j_compress_ptr cinfo) { int i; - /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Allocate comp_info array large enough for maximum component count. - * Array is made permanent in case application wants to compress - * multiple images at same param settings. - */ if (cinfo->comp_info == NULL) - cinfo->comp_info = (jpeg_component_info *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + cinfo->comp_info = (jpeg_component_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, MAX_COMPONENTS * SIZEOF(jpeg_component_info)); - /* Initialize everything not dependent on the color space */ - cinfo->data_precision = BITS_IN_JSAMPLE; - /* Set up two quantization tables using default quality of 75 */ jpeg_set_quality(cinfo, 75, TRUE); - /* Set up two Huffman tables */ std_huff_tables(cinfo); - /* Initialize default arithmetic coding conditioning */ for (i = 0; i < NUM_ARITH_TBLS; i++) { - cinfo->arith_dc_L[i] = 0; - cinfo->arith_dc_U[i] = 1; - cinfo->arith_ac_K[i] = 5; + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; } - /* Default is no multiple-scan output */ cinfo->scan_info = NULL; cinfo->num_scans = 0; - /* Expect normal source image, not raw downsampled data */ cinfo->raw_data_in = FALSE; - /* Use Huffman coding, not arithmetic coding, by default */ cinfo->arith_code = FALSE; - /* By default, don't do extra passes to optimize entropy coding */ cinfo->optimize_coding = FALSE; - /* The standard Huffman tables are only valid for 8-bit data precision. - * If the precision is higher, force optimization on so that usable - * tables will be computed. This test can be removed if default tables - * are supplied that are valid for the desired precision. - */ if (cinfo->data_precision > 8) - cinfo->optimize_coding = TRUE; + cinfo->optimize_coding = TRUE; - /* By default, use the simpler non-cosited sampling alignment */ cinfo->CCIR601_sampling = FALSE; - /* No input smoothing */ cinfo->smoothing_factor = 0; - /* DCT algorithm preference */ cinfo->dct_method = JDCT_DEFAULT; - /* No restart markers */ cinfo->restart_interval = 0; cinfo->restart_in_rows = 0; - /* Fill in default JFIF marker parameters. Note that whether the marker - * will actually be written is determined by jpeg_set_colorspace. - * - * By default, the library emits JFIF version code 1.01. - * An application that wants to emit JFIF 1.02 extension markers should set - * JFIF_minor_version to 2. We could probably get away with just defaulting - * to 1.02, but there may still be some decoders in use that will complain - * about that; saying 1.01 should minimize compatibility problems. - */ cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ cinfo->JFIF_minor_version = 1; cinfo->density_unit = 0; /* Pixel size is unknown by default */ cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ cinfo->Y_density = 1; - /* Choose JPEG colorspace based on input space, set defaults accordingly */ - jpeg_default_colorspace(cinfo); } -/* - * Select an appropriate JPEG colorspace for in_color_space. - */ - GLOBAL(void) jpeg_default_colorspace (j_compress_ptr cinfo) { switch (cinfo->in_color_space) { case JCS_GRAYSCALE: - jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); - break; + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + break; case JCS_RGB: - jpeg_set_colorspace(cinfo, JCS_YCbCr); - break; + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; case JCS_YCbCr: - jpeg_set_colorspace(cinfo, JCS_YCbCr); - break; + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; case JCS_CMYK: - jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ - break; + jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ + break; case JCS_YCCK: - jpeg_set_colorspace(cinfo, JCS_YCCK); - break; + jpeg_set_colorspace(cinfo, JCS_YCCK); + break; case JCS_UNKNOWN: - jpeg_set_colorspace(cinfo, JCS_UNKNOWN); - break; + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; default: - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); } } -/* - * Set the JPEG colorspace, and choose colorspace-dependent default values. - */ - GLOBAL(void) jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) { @@ -191984,13 +177477,8 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) compptr->dc_tbl_no = (dctbl), \ compptr->ac_tbl_no = (actbl) ) - /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - - /* For all colorspaces, we use Q and Huff tables 0 for luminance components, - * tables 1 for chrominance components. - */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); cinfo->jpeg_color_space = colorspace; @@ -191999,54 +177487,51 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) switch (colorspace) { case JCS_GRAYSCALE: - cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ - cinfo->num_components = 1; - /* JFIF specifies component ID 1 */ - SET_COMP(0, 1, 1,1, 0, 0,0); - break; + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 1; + SET_COMP(0, 1, 1,1, 0, 0,0); + break; case JCS_RGB: - cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ - cinfo->num_components = 3; - SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); - SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); - SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); - break; + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ + cinfo->num_components = 3; + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); + SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + break; case JCS_YCbCr: - cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ - cinfo->num_components = 3; - /* JFIF specifies component IDs 1,2,3 */ - /* We default to 2x2 subsamples of chrominance */ - SET_COMP(0, 1, 2,2, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - break; + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 3; + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + break; case JCS_CMYK: - cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ - cinfo->num_components = 4; - SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); - SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); - SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); - SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); - break; + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ + cinfo->num_components = 4; + SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); + SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); + SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); + SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); + break; case JCS_YCCK: - cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ - cinfo->num_components = 4; - SET_COMP(0, 1, 2,2, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - SET_COMP(3, 4, 2,2, 0, 0,0); - break; + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ + cinfo->num_components = 4; + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 2,2, 0, 0,0); + break; case JCS_UNKNOWN: - cinfo->num_components = cinfo->input_components; - if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - for (ci = 0; ci < cinfo->num_components; ci++) { - SET_COMP(ci, ci, 1,1, 0, 0,0); - } - break; + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; default: - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); } } @@ -192054,8 +177539,7 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) LOCAL(jpeg_scan_info *) fill_a_scan (jpeg_scan_info * scanptr, int ci, - int Ss, int Se, int Ah, int Al) -/* Support routine: generate one scan for specified component */ + int Ss, int Se, int Ah, int Al) { scanptr->comps_in_scan = 1; scanptr->component_index[0] = ci; @@ -192069,50 +177553,41 @@ fill_a_scan (jpeg_scan_info * scanptr, int ci, LOCAL(jpeg_scan_info *) fill_scans (jpeg_scan_info * scanptr, int ncomps, - int Ss, int Se, int Ah, int Al) -/* Support routine: generate one scan for each component */ + int Ss, int Se, int Ah, int Al) { int ci; for (ci = 0; ci < ncomps; ci++) { - scanptr->comps_in_scan = 1; - scanptr->component_index[0] = ci; - scanptr->Ss = Ss; - scanptr->Se = Se; - scanptr->Ah = Ah; - scanptr->Al = Al; - scanptr++; + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; } return scanptr; } LOCAL(jpeg_scan_info *) fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) -/* Support routine: generate interleaved DC scan if possible, else N scans */ { int ci; if (ncomps <= MAX_COMPS_IN_SCAN) { - /* Single interleaved DC scan */ - scanptr->comps_in_scan = ncomps; - for (ci = 0; ci < ncomps; ci++) - scanptr->component_index[ci] = ci; - scanptr->Ss = scanptr->Se = 0; - scanptr->Ah = Ah; - scanptr->Al = Al; - scanptr++; + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = scanptr->Se = 0; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; } else { - /* Noninterleaved DC scan for each component */ - scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); + scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); } return scanptr; } -/* - * Create a recommended progressive-JPEG script. - * cinfo->num_components and cinfo->jpeg_color_space must be correct. - */ - GLOBAL(void) jpeg_simple_progression (j_compress_ptr cinfo) { @@ -192120,33 +177595,22 @@ jpeg_simple_progression (j_compress_ptr cinfo) int nscans; jpeg_scan_info * scanptr; - /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Figure space needed for script. Calculation must match code below! */ if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { - /* Custom script for YCbCr color images. */ - nscans = 10; + nscans = 10; } else { - /* All-purpose script for other color spaces. */ - if (ncomps > MAX_COMPS_IN_SCAN) - nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ - else - nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ + if (ncomps > MAX_COMPS_IN_SCAN) + nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ + else + nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ } - /* Allocate space for script. - * We need to put it in the permanent pool in case the application performs - * multiple compressions without changing the settings. To avoid a memory - * leak if jpeg_simple_progression is called repeatedly for the same JPEG - * object, we try to re-use previously allocated space, and we allocate - * enough space to handle YCbCr even if initially asked for grayscale. - */ if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { - cinfo->script_space_size = MAX(nscans, 10); - cinfo->script_space = (jpeg_scan_info *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + cinfo->script_space_size = MAX(nscans, 10); + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, cinfo->script_space_size * SIZEOF(jpeg_scan_info)); } scanptr = cinfo->script_space; @@ -192154,36 +177618,23 @@ jpeg_simple_progression (j_compress_ptr cinfo) cinfo->num_scans = nscans; if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { - /* Custom script for YCbCr color images. */ - /* Initial DC scan */ - scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); - /* Initial AC scan: get some luma data out in a hurry */ - scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); - /* Chroma data is too small to be worth expending many scans on */ - scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); - scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); - /* Complete spectral selection for luma AC */ - scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); - /* Refine next bit of luma AC */ - scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); - /* Finish DC successive approximation */ - scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); - /* Finish AC successive approximation */ - scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); - scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); - /* Luma bottom bit comes last since it's usually largest scan */ - scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); + scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); + scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); + scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); + scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); } else { - /* All-purpose script for other color spaces. */ - /* Successive approximation first pass */ - scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); - scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); - scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); - /* Successive approximation second pass */ - scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); - /* Successive approximation final pass */ - scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); - scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); + scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); + scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); } } @@ -192195,61 +177646,36 @@ jpeg_simple_progression (j_compress_ptr cinfo) #ifdef C_PROGRESSIVE_SUPPORTED -/* Expanded entropy encoder object for progressive Huffman encoding. */ - typedef struct { struct jpeg_entropy_encoder pub; /* public fields */ - /* Mode flag: TRUE for optimization, FALSE for actual data output */ boolean gather_statistics; - /* Bit-level coding status. - * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. - */ JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ INT32 put_buffer; /* current bit-accumulation buffer */ int put_bits; /* # of bits now in it */ j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ - /* Coding status for DC components */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ - /* Coding status for AC components */ int ac_tbl_no; /* the table number of the single component */ unsigned int EOBRUN; /* run length of EOBs */ unsigned int BE; /* # of buffered correction bits before MCU */ char * bit_buffer; /* buffer for correction bits (1 per char) */ - /* packing correction bits tightly would save some space but cost time... */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ int next_restart_num; /* next restart number to write (0-7) */ - /* Pointers to derived tables (these workspaces have image lifespan). - * Since any one scan codes only DC or only AC, we only need one set - * of tables, not one for DC and one for AC. - */ c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - /* Statistics tables for optimization; again, one set is enough */ long * count_ptrs[NUM_HUFF_TBLS]; } phuff_entropy_encoder; typedef phuff_entropy_encoder * phuff_entropy_ptr; -/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit - * buffer can hold. Larger sizes may slightly improve compression, but - * 1000 is already well into the realm of overkill. - * The minimum safe size is 64 bits. - */ - #define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ -/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. - * We assume that int right shift is unsigned if INT32 right shift is, - * which should be safe. - */ - #ifdef RIGHT_SHIFT_IS_UNSIGNED #define ISHIFT_TEMPS int ishift_temp; #define IRIGHT_SHIFT(x,shft) \ @@ -192261,22 +177687,17 @@ typedef phuff_entropy_encoder * phuff_entropy_ptr; #define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif -/* Forward declarations */ METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); + JBLOCKROW *MCU_data)); METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); + JBLOCKROW *MCU_data)); METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); + JBLOCKROW *MCU_data)); METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); + JBLOCKROW *MCU_data)); METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); -/* - * Initialize for a Huffman-compressed scan using progressive JPEG. - */ - METHODDEF(void) start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) { @@ -192290,126 +177711,89 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) is_DC_band = (cinfo->Ss == 0); - /* We assume jcmaster.c already validated the scan parameters. */ - - /* Select execution routines */ if (cinfo->Ah == 0) { - if (is_DC_band) - entropy->pub.encode_mcu = encode_mcu_DC_first; - else - entropy->pub.encode_mcu = encode_mcu_AC_first; + if (is_DC_band) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; } else { - if (is_DC_band) - entropy->pub.encode_mcu = encode_mcu_DC_refine; - else { - entropy->pub.encode_mcu = encode_mcu_AC_refine; - /* AC refinement needs a correction bit buffer */ - if (entropy->bit_buffer == NULL) + if (is_DC_band) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else { + entropy->pub.encode_mcu = encode_mcu_AC_refine; + if (entropy->bit_buffer == NULL) entropy->bit_buffer = (char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - MAX_CORR_BITS * SIZEOF(char)); - } + MAX_CORR_BITS * SIZEOF(char)); + } } if (gather_statistics) - entropy->pub.finish_pass = finish_pass_gather_phuff; + entropy->pub.finish_pass = finish_pass_gather_phuff; else - entropy->pub.finish_pass = finish_pass_phuff; + entropy->pub.finish_pass = finish_pass_phuff; - /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 - * for AC coefficients. - */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Initialize DC predictions to 0 */ - entropy->last_dc_val[ci] = 0; - /* Get table index */ - if (is_DC_band) { - if (cinfo->Ah != 0) /* DC refinement needs no table */ + compptr = cinfo->cur_comp_info[ci]; + entropy->last_dc_val[ci] = 0; + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ continue; - tbl = compptr->dc_tbl_no; - } else { - entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; - } - if (gather_statistics) { - /* Check for invalid table index */ - /* (make_c_derived_tbl does this in the other path) */ - if (tbl < 0 || tbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->count_ptrs[tbl] == NULL) + tbl = compptr->dc_tbl_no; + } else { + entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; + } + if (gather_statistics) { + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + if (entropy->count_ptrs[tbl] == NULL) entropy->count_ptrs[tbl] = (long *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); - } else { - /* Compute derived values for Huffman table */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, - & entropy->derived_tbls[tbl]); - } + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, + & entropy->derived_tbls[tbl]); + } } - /* Initialize AC stuff */ entropy->EOBRUN = 0; entropy->BE = 0; - /* Initialize bit buffer to empty */ entropy->put_buffer = 0; entropy->put_bits = 0; - /* Initialize restart stuff */ entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num = 0; } -/* Outputting bytes to the file. - * NB: these must be called only when actually outputting, - * that is, entropy->gather_statistics == FALSE. - */ - -/* Emit a byte */ #define emit_byte(entropy,val) \ { *(entropy)->next_output_byte++ = (JOCTET) (val); \ if (--(entropy)->free_in_buffer == 0) \ - dump_buffer_p(entropy); } + dump_buffer_p(entropy); } LOCAL(void) dump_buffer_p (phuff_entropy_ptr entropy) -/* Empty the output buffer; we do not support suspension in this module. */ { struct jpeg_destination_mgr * dest = entropy->cinfo->dest; if (! (*dest->empty_output_buffer) (entropy->cinfo)) - ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); - /* After a successful buffer dump, must reset buffer pointers */ + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); entropy->next_output_byte = dest->next_output_byte; entropy->free_in_buffer = dest->free_in_buffer; } -/* Outputting bits to the file */ - -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. - */ - INLINE LOCAL(void) emit_bits_p (phuff_entropy_ptr entropy, unsigned int code, int size) -/* Emit some bits, unless we are in gather mode */ { - /* This routine is heavily used, so it's worth coding tightly. */ register INT32 put_buffer = (INT32) code; register int put_bits = entropy->put_bits; - /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) - ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); if (entropy->gather_statistics) - return; /* do nothing if we're only getting stats */ + return; /* do nothing if we're only getting stats */ put_buffer &= (((INT32) 1)<put_buffer; /* and merge with old buffer contents */ while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); + int c = (int) ((put_buffer >> 16) & 0xFF); - emit_byte(entropy, c); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(entropy, 0); - } - put_buffer <<= 8; - put_bits -= 8; + emit_byte(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; } entropy->put_buffer = put_buffer; /* update variables */ @@ -192438,78 +177822,60 @@ LOCAL(void) flush_bits_p (phuff_entropy_ptr entropy) { emit_bits_p(entropy, 0x7F, 7); /* fill any partial byte with ones */ - entropy->put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->put_buffer = 0; /* and reset bit-buffer to empty */ entropy->put_bits = 0; } -/* - * Emit (or just count) a Huffman symbol. - */ - INLINE LOCAL(void) emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) { if (entropy->gather_statistics) - entropy->count_ptrs[tbl_no][symbol]++; + entropy->count_ptrs[tbl_no][symbol]++; else { - c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; - emit_bits_p(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; + emit_bits_p(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); } } -/* - * Emit bits from a correction bit buffer. - */ - LOCAL(void) emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, - unsigned int nbits) + unsigned int nbits) { if (entropy->gather_statistics) - return; /* no real work */ + return; /* no real work */ while (nbits > 0) { - emit_bits_p(entropy, (unsigned int) (*bufstart), 1); - bufstart++; - nbits--; + emit_bits_p(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; } } -/* - * Emit any pending EOBRUN symbol. - */ - LOCAL(void) emit_eobrun (phuff_entropy_ptr entropy) { register int temp, nbits; if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ - temp = entropy->EOBRUN; - nbits = 0; - while ((temp >>= 1)) - nbits++; - /* safety check: shouldn't happen given limited correction-bit buffer */ - if (nbits > 14) - ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + temp = entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); - emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); - if (nbits) - emit_bits_p(entropy, entropy->EOBRUN, nbits); + emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits_p(entropy, entropy->EOBRUN, nbits); - entropy->EOBRUN = 0; + entropy->EOBRUN = 0; - /* Emit any buffered correction bits */ - emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); - entropy->BE = 0; + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; } } -/* - * Emit a restart marker & resynchronize predictions. - */ - LOCAL(void) emit_restart_p (phuff_entropy_ptr entropy, int restart_num) { @@ -192518,27 +177884,20 @@ emit_restart_p (phuff_entropy_ptr entropy, int restart_num) emit_eobrun(entropy); if (! entropy->gather_statistics) { - flush_bits_p(entropy); - emit_byte(entropy, 0xFF); - emit_byte(entropy, JPEG_RST0 + restart_num); + flush_bits_p(entropy); + emit_byte(entropy, 0xFF); + emit_byte(entropy, JPEG_RST0 + restart_num); } if (entropy->cinfo->Ss == 0) { - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) - entropy->last_dc_val[ci] = 0; + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->last_dc_val[ci] = 0; } else { - /* Re-initialize all AC-related fields to 0 */ - entropy->EOBRUN = 0; - entropy->BE = 0; + entropy->EOBRUN = 0; + entropy->BE = 0; } } -/* - * MCU encoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - METHODDEF(boolean) encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -192554,77 +177913,55 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; - /* Emit restart marker if needed */ if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart_p(entropy, entropy->next_restart_num); + if (entropy->restarts_to_go == 0) + emit_restart_p(entropy, entropy->next_restart_num); - /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; - /* Compute the DC value after the required point transform by Al. - * This is simply an arithmetic right shift. - */ - temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); - /* DC differences are figured on the point-transformed values. */ - temp = temp2 - entropy->last_dc_val[ci]; - entropy->last_dc_val[ci] = temp2; + temp = temp2 - entropy->last_dc_val[ci]; + entropy->last_dc_val[ci] = temp2; - /* Encode the DC coefficient difference per section G.1.2.1 */ - temp2 = temp; - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* For a negative input, want temp2 = bitwise complement of abs(input) */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp2--; + } - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); - /* Count/emit the Huffman-coded symbol for the number of bits */ - emit_symbol(entropy, compptr->dc_tbl_no, nbits); + emit_symbol(entropy, compptr->dc_tbl_no, nbits); - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (nbits) /* emit_bits rejects calls with size 0 */ - emit_bits_p(entropy, (unsigned int) temp2, nbits); + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits_p(entropy, (unsigned int) temp2, nbits); } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; - /* Update restart-interval state too */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; } return TRUE; } -/* - * MCU encoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -192639,98 +177976,73 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; - /* Emit restart marker if needed */ if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart_p(entropy, entropy->next_restart_num); + if (entropy->restarts_to_go == 0) + emit_restart_p(entropy, entropy->next_restart_num); - /* Encode the MCU data block */ block = MCU_data[0]; - /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ - r = 0; /* r = run length of zeros */ for (k = cinfo->Ss; k <= Se; k++) { - if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { - r++; - continue; - } - /* We must apply the point transform by Al. For AC coefficients this - * is an integer division with rounding towards 0. To do this portably - * in C, we shift after obtaining the absolute value; so the code is - * interwoven with finding the abs value (temp) and output bits (temp2). - */ - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - temp >>= Al; /* apply the point transform */ - /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ - temp2 = ~temp; - } else { - temp >>= Al; /* apply the point transform */ - temp2 = temp; - } - /* Watch out for case that nonzero coef is zero after point transform */ - if (temp == 0) { - r++; - continue; - } + if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { + r++; + continue; + } + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + if (temp == 0) { + r++; + continue; + } - /* Emit any pending EOBRUN */ - if (entropy->EOBRUN > 0) - emit_eobrun(entropy); - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); - r -= 16; - } + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + while (r > 15) { + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); - /* Count/emit Huffman symbol for run length / number of bits */ - emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - emit_bits_p(entropy, (unsigned int) temp2, nbits); + emit_bits_p(entropy, (unsigned int) temp2, nbits); - r = 0; /* reset zero run length */ + r = 0; /* reset zero run length */ } if (r > 0) { /* If there are trailing zeroes, */ - entropy->EOBRUN++; /* count an EOB */ - if (entropy->EOBRUN == 0x7FFF) - emit_eobrun(entropy); /* force it out to avoid overflow */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; - /* Update restart-interval state too */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; } return TRUE; } -/* - * MCU encoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. - */ - METHODDEF(boolean) encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -192743,40 +178055,32 @@ encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; - /* Emit restart marker if needed */ if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart_p(entropy, entropy->next_restart_num); + if (entropy->restarts_to_go == 0) + emit_restart_p(entropy, entropy->next_restart_num); - /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; + block = MCU_data[blkn]; - /* We simply emit the Al'th bit of the DC coefficient value. */ - temp = (*block)[0]; - emit_bits_p(entropy, (unsigned int) (temp >> Al), 1); + temp = (*block)[0]; + emit_bits_p(entropy, (unsigned int) (temp >> Al), 1); } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; - /* Update restart-interval state too */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; } return TRUE; } -/* - * MCU encoding for AC successive approximation refinement scan. - */ - METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -192794,116 +178098,82 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; - /* Emit restart marker if needed */ if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart_p(entropy, entropy->next_restart_num); + if (entropy->restarts_to_go == 0) + emit_restart_p(entropy, entropy->next_restart_num); - /* Encode the MCU data block */ block = MCU_data[0]; - /* It is convenient to make a pre-pass to determine the transformed - * coefficients' absolute values and the EOB position. - */ EOB = 0; for (k = cinfo->Ss; k <= Se; k++) { - temp = (*block)[jpeg_natural_order[k]]; - /* We must apply the point transform by Al. For AC coefficients this - * is an integer division with rounding towards 0. To do this portably - * in C, we shift after obtaining the absolute value. - */ - if (temp < 0) - temp = -temp; /* temp is abs value of input */ - temp >>= Al; /* apply the point transform */ - absvalues[k] = temp; /* save abs value for main pass */ - if (temp == 1) - EOB = k; /* EOB = index of last newly-nonzero coef */ + temp = (*block)[jpeg_natural_order[k]]; + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ } - /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ - r = 0; /* r = run length of zeros */ BR = 0; /* BR = count of buffered bits added now */ BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ for (k = cinfo->Ss; k <= Se; k++) { - if ((temp = absvalues[k]) == 0) { - r++; - continue; - } + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } - /* Emit any required ZRLs, but not if they can be folded into EOB */ - while (r > 15 && k <= EOB) { - /* emit any pending EOBRUN and the BE correction bits */ - emit_eobrun(entropy); - /* Emit ZRL */ - emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); - r -= 16; - /* Emit buffered correction bits that must be associated with ZRL */ - emit_buffered_bits(entropy, BR_buffer, BR); - BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ - BR = 0; - } + while (r > 15 && k <= EOB) { + emit_eobrun(entropy); + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } - /* If the coef was previously nonzero, it only needs a correction bit. - * NOTE: a straight translation of the spec's figure G.7 would suggest - * that we also need to test r > 15. But if r > 15, we can only get here - * if k > EOB, which implies that this coefficient is not 1. - */ - if (temp > 1) { - /* The correction bit is the next bit of the absolute value. */ - BR_buffer[BR++] = (char) (temp & 1); - continue; - } + if (temp > 1) { + BR_buffer[BR++] = (char) (temp & 1); + continue; + } - /* Emit any pending EOBRUN and the BE correction bits */ - emit_eobrun(entropy); + emit_eobrun(entropy); - /* Count/emit Huffman symbol for run length / number of bits */ - emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); - /* Emit output bit for newly-nonzero coef */ - temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; - emit_bits_p(entropy, (unsigned int) temp, 1); + temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; + emit_bits_p(entropy, (unsigned int) temp, 1); - /* Emit buffered correction bits that must be associated with this code */ - emit_buffered_bits(entropy, BR_buffer, BR); - BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ - BR = 0; - r = 0; /* reset zero run length */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ } if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ - entropy->EOBRUN++; /* count an EOB */ - entropy->BE += BR; /* concat my correction bits to older ones */ - /* We force out the EOB if we risk either: - * 1. overflow of the EOB counter; - * 2. overflow of the correction bit buffer during the next MCU. - */ - if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) - emit_eobrun(entropy); + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); } cinfo->dest->next_output_byte = entropy->next_output_byte; cinfo->dest->free_in_buffer = entropy->free_in_buffer; - /* Update restart-interval state too */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; } return TRUE; } -/* - * Finish up at the end of a Huffman-compressed progressive scan. - */ - METHODDEF(void) finish_pass_phuff (j_compress_ptr cinfo) { @@ -192912,7 +178182,6 @@ finish_pass_phuff (j_compress_ptr cinfo) entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; - /* Flush out any buffered data */ emit_eobrun(entropy); flush_bits_p(entropy); @@ -192920,10 +178189,6 @@ finish_pass_phuff (j_compress_ptr cinfo) cinfo->dest->free_in_buffer = entropy->free_in_buffer; } -/* - * Finish up a statistics-gathering pass and create the new Huffman tables. - */ - METHODDEF(void) finish_pass_gather_phuff (j_compress_ptr cinfo) { @@ -192934,42 +178199,34 @@ finish_pass_gather_phuff (j_compress_ptr cinfo) JHUFF_TBL **htblptr; boolean did[NUM_HUFF_TBLS]; - /* Flush out buffered data (all we care about is counting the EOB symbol) */ emit_eobrun(entropy); is_DC_band = (cinfo->Ss == 0); - /* It's important not to apply jpeg_gen_optimal_table more than once - * per table, because it clobbers the input frequency counts! - */ MEMZERO(did, SIZEOF(did)); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (is_DC_band) { - if (cinfo->Ah != 0) /* DC refinement needs no table */ + compptr = cinfo->cur_comp_info[ci]; + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ continue; - tbl = compptr->dc_tbl_no; - } else { - tbl = compptr->ac_tbl_no; - } - if (! did[tbl]) { - if (is_DC_band) - htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; - else - htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); - did[tbl] = TRUE; - } + tbl = compptr->dc_tbl_no; + } else { + tbl = compptr->ac_tbl_no; + } + if (! did[tbl]) { + if (is_DC_band) + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + else + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); + did[tbl] = TRUE; + } } } -/* - * Module initialization routine for progressive Huffman entropy encoding. - */ - GLOBAL(void) jinit_phuff_encoder (j_compress_ptr cinfo) { @@ -192977,15 +178234,14 @@ jinit_phuff_encoder (j_compress_ptr cinfo) int i; entropy = (phuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(phuff_entropy_encoder)); cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; entropy->pub.start_pass = start_pass_phuff; - /* Mark tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - entropy->count_ptrs[i] = NULL; + entropy->derived_tbls[i] = NULL; + entropy->count_ptrs[i] = NULL; } entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ } @@ -192996,41 +178252,13 @@ jinit_phuff_encoder (j_compress_ptr cinfo) /********* Start of inlined file: jcprepct.c *********/ #define JPEG_INTERNALS -/* At present, jcsample.c can request context rows only for smoothing. - * In the future, we might also need context rows for CCIR601 sampling - * or other more-complex downsampling procedures. The code to support - * context rows should be compiled only if needed. - */ #ifdef INPUT_SMOOTHING_SUPPORTED #define CONTEXT_ROWS_SUPPORTED #endif -/* - * For the simple (no-context-row) case, we just need to buffer one - * row group's worth of pixels for the downsampling step. At the bottom of - * the image, we pad to a full row group by replicating the last pixel row. - * The downsampler's last output row is then replicated if needed to pad - * out to a full iMCU row. - * - * When providing context rows, we must buffer three row groups' worth of - * pixels. Three row groups are physically allocated, but the row pointer - * arrays are made five row groups high, with the extra pointers above and - * below "wrapping around" to point to the last and first real row groups. - * This allows the downsampler to access the proper context rows. - * At the top and bottom of the image, we create dummy context rows by - * copying the first or last real pixel row. This copying could be avoided - * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the - * trouble on the compression side. - */ - -/* Private buffer controller object */ - typedef struct { struct jpeg_c_prep_controller pub; /* public fields */ - /* Downsampling input buffer. This buffer holds color-converted data - * until we have enough to do a downsample step. - */ JSAMPARRAY color_buf[MAX_COMPONENTS]; JDIMENSION rows_to_go; /* counts rows remaining in source image */ @@ -193044,58 +178272,34 @@ typedef struct { typedef my_prep_controller * my_prep_ptr; -/* - * Initialize for a processing pass. - */ - METHODDEF(void) start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; if (pass_mode != JBUF_PASS_THRU) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - /* Initialize total-height counter for detecting bottom of image */ prep->rows_to_go = cinfo->image_height; - /* Mark the conversion buffer empty */ prep->next_buf_row = 0; #ifdef CONTEXT_ROWS_SUPPORTED - /* Preset additional state variables for context mode. - * These aren't used in non-context mode, so we needn't test which mode. - */ prep->this_row_group = 0; - /* Set next_buf_stop to stop after two row groups have been read in. */ prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; #endif } -/* - * Expand an image vertically from height input_rows to height output_rows, - * by duplicating the bottom row. - */ - LOCAL(void) expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, - int input_rows, int output_rows) + int input_rows, int output_rows) { register int row; for (row = input_rows; row < output_rows; row++) { - jcopy_sample_rows(image_data, input_rows-1, image_data, row, - 1, num_cols); + jcopy_sample_rows(image_data, input_rows-1, image_data, row, + 1, num_cols); } } -/* - * Process some data in the simple no-context case. - * - * Preprocessor output data is counted in "row groups". A row group - * is defined to be v_samp_factor sample rows of each component. - * Downsampling will produce this much data from each max_v_samp_factor - * input rows. - */ - METHODDEF(void) pre_process_data (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, @@ -193110,64 +178314,54 @@ pre_process_data (j_compress_ptr cinfo, while (*in_row_ctr < in_rows_avail && *out_row_group_ctr < out_row_groups_avail) { - /* Do color conversion to fill the conversion buffer. */ - inrows = in_rows_avail - *in_row_ctr; - numrows = cinfo->max_v_samp_factor - prep->next_buf_row; - numrows = (int) MIN((JDIMENSION) numrows, inrows); - (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION) prep->next_buf_row, - numrows); - *in_row_ctr += numrows; - prep->next_buf_row += numrows; - prep->rows_to_go -= numrows; - /* If at bottom of image, pad to fill the conversion buffer. */ - if (prep->rows_to_go == 0 && + inrows = in_rows_avail - *in_row_ctr; + numrows = cinfo->max_v_samp_factor - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + if (prep->rows_to_go == 0 && prep->next_buf_row < cinfo->max_v_samp_factor) { - for (ci = 0; ci < cinfo->num_components; ci++) { + for (ci = 0; ci < cinfo->num_components; ci++) { expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, prep->next_buf_row, cinfo->max_v_samp_factor); - } - prep->next_buf_row = cinfo->max_v_samp_factor; - } - /* If we've filled the conversion buffer, empty it. */ - if (prep->next_buf_row == cinfo->max_v_samp_factor) { - (*cinfo->downsample->downsample) (cinfo, + } + prep->next_buf_row = cinfo->max_v_samp_factor; + } + if (prep->next_buf_row == cinfo->max_v_samp_factor) { + (*cinfo->downsample->downsample) (cinfo, prep->color_buf, (JDIMENSION) 0, output_buf, *out_row_group_ctr); - prep->next_buf_row = 0; - (*out_row_group_ctr)++; - } - /* If at bottom of image, pad the output to a full iMCU height. - * Note we assume the caller is providing a one-iMCU-height output buffer! - */ - if (prep->rows_to_go == 0 && + prep->next_buf_row = 0; + (*out_row_group_ctr)++; + } + if (prep->rows_to_go == 0 && *out_row_group_ctr < out_row_groups_avail) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { expand_bottom_edge(output_buf[ci], compptr->width_in_blocks * DCTSIZE, (int) (*out_row_group_ctr * compptr->v_samp_factor), (int) (out_row_groups_avail * compptr->v_samp_factor)); - } - *out_row_group_ctr = out_row_groups_avail; - break; /* can exit outer loop without test */ - } + } + *out_row_group_ctr = out_row_groups_avail; + break; /* can exit outer loop without test */ + } } } #ifdef CONTEXT_ROWS_SUPPORTED -/* - * Process some data in the context case. - */ - METHODDEF(void) pre_process_context (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail) + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; int numrows, ci; @@ -193175,64 +178369,54 @@ pre_process_context (j_compress_ptr cinfo, JDIMENSION inrows; while (*out_row_group_ctr < out_row_groups_avail) { - if (*in_row_ctr < in_rows_avail) { - /* Do color conversion to fill the conversion buffer. */ - inrows = in_rows_avail - *in_row_ctr; - numrows = prep->next_buf_stop - prep->next_buf_row; - numrows = (int) MIN((JDIMENSION) numrows, inrows); - (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + if (*in_row_ctr < in_rows_avail) { + inrows = in_rows_avail - *in_row_ctr; + numrows = prep->next_buf_stop - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, prep->color_buf, (JDIMENSION) prep->next_buf_row, numrows); - /* Pad at top of image, if first time through */ - if (prep->rows_to_go == cinfo->image_height) { + if (prep->rows_to_go == cinfo->image_height) { for (ci = 0; ci < cinfo->num_components; ci++) { int row; for (row = 1; row <= cinfo->max_v_samp_factor; row++) { - jcopy_sample_rows(prep->color_buf[ci], 0, - prep->color_buf[ci], -row, - 1, cinfo->image_width); + jcopy_sample_rows(prep->color_buf[ci], 0, + prep->color_buf[ci], -row, + 1, cinfo->image_width); } } - } - *in_row_ctr += numrows; - prep->next_buf_row += numrows; - prep->rows_to_go -= numrows; - } else { - /* Return for more data, unless we are at the bottom of the image. */ - if (prep->rows_to_go != 0) + } + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + } else { + if (prep->rows_to_go != 0) break; - /* When at bottom of image, pad to fill the conversion buffer. */ - if (prep->next_buf_row < prep->next_buf_stop) { + if (prep->next_buf_row < prep->next_buf_stop) { for (ci = 0; ci < cinfo->num_components; ci++) { expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, - prep->next_buf_row, prep->next_buf_stop); + prep->next_buf_row, prep->next_buf_stop); } prep->next_buf_row = prep->next_buf_stop; - } - } - /* If we've gotten enough data, downsample a row group. */ - if (prep->next_buf_row == prep->next_buf_stop) { - (*cinfo->downsample->downsample) (cinfo, + } + } + if (prep->next_buf_row == prep->next_buf_stop) { + (*cinfo->downsample->downsample) (cinfo, prep->color_buf, (JDIMENSION) prep->this_row_group, output_buf, *out_row_group_ctr); - (*out_row_group_ctr)++; - /* Advance pointers with wraparound as necessary. */ - prep->this_row_group += cinfo->max_v_samp_factor; - if (prep->this_row_group >= buf_height) + (*out_row_group_ctr)++; + prep->this_row_group += cinfo->max_v_samp_factor; + if (prep->this_row_group >= buf_height) prep->this_row_group = 0; - if (prep->next_buf_row >= buf_height) + if (prep->next_buf_row >= buf_height) prep->next_buf_row = 0; - prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; - } + prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; + } } } -/* - * Create the wrapped-around downsampling input buffer needed for context mode. - */ - LOCAL(void) create_context_buffer (j_compress_ptr cinfo) { @@ -193242,44 +178426,31 @@ create_context_buffer (j_compress_ptr cinfo) jpeg_component_info * compptr; JSAMPARRAY true_buffer, fake_buffer; - /* Grab enough space for fake row pointers for all the components; - * we need five row groups' worth of pointers for each component. - */ fake_buffer = (JSAMPARRAY) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (cinfo->num_components * 5 * rgroup_height) * SIZEOF(JSAMPROW)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Allocate the actual buffer space (3 row groups) for this component. - * We make the buffer wide enough to allow the downsampler to edge-expand - * horizontally within the buffer, if it so chooses. - */ - true_buffer = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * - cinfo->max_h_samp_factor) / compptr->h_samp_factor), - (JDIMENSION) (3 * rgroup_height)); - /* Copy true buffer row pointers into the middle of the fake row array */ - MEMCOPY(fake_buffer + rgroup_height, true_buffer, - 3 * rgroup_height * SIZEOF(JSAMPROW)); - /* Fill in the above and below wraparound pointers */ - for (i = 0; i < rgroup_height; i++) { - fake_buffer[i] = true_buffer[2 * rgroup_height + i]; - fake_buffer[4 * rgroup_height + i] = true_buffer[i]; - } - prep->color_buf[ci] = fake_buffer + rgroup_height; - fake_buffer += 5 * rgroup_height; /* point to space for next component */ + ci++, compptr++) { + true_buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) (3 * rgroup_height)); + MEMCOPY(fake_buffer + rgroup_height, true_buffer, + 3 * rgroup_height * SIZEOF(JSAMPROW)); + for (i = 0; i < rgroup_height; i++) { + fake_buffer[i] = true_buffer[2 * rgroup_height + i]; + fake_buffer[4 * rgroup_height + i] = true_buffer[i]; + } + prep->color_buf[ci] = fake_buffer + rgroup_height; + fake_buffer += 5 * rgroup_height; /* point to space for next component */ } } #endif /* CONTEXT_ROWS_SUPPORTED */ -/* - * Initialize preprocessing controller. - */ - GLOBAL(void) jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) { @@ -193288,37 +178459,31 @@ jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) jpeg_component_info * compptr; if (need_full_buffer) /* safety check */ - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); prep = (my_prep_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_prep_controller)); cinfo->prep = (struct jpeg_c_prep_controller *) prep; prep->pub.start_pass = start_pass_prep; - /* Allocate the color conversion buffer. - * We make the buffer wide enough to allow the downsampler to edge-expand - * horizontally within the buffer, if it so chooses. - */ if (cinfo->downsample->need_context_rows) { - /* Set up to provide context rows */ #ifdef CONTEXT_ROWS_SUPPORTED - prep->pub.pre_process_data = pre_process_context; - create_context_buffer(cinfo); + prep->pub.pre_process_data = pre_process_context; + create_context_buffer(cinfo); #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - /* No context, just make it tall enough for one row group */ - prep->pub.pre_process_data = pre_process_data; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + prep->pub.pre_process_data = pre_process_data; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) cinfo->max_v_samp_factor); - } + } } } /********* End of inlined file: jcprepct.c *********/ @@ -193326,37 +178491,23 @@ jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) /********* Start of inlined file: jcsample.c *********/ #define JPEG_INTERNALS -/* Pointer to routine to downsample a single component */ typedef JMETHOD(void, downsample1_ptr, (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data)); -/* Private subobject */ - typedef struct { struct jpeg_downsampler pub; /* public fields */ - /* Downsampling method pointers, one per component */ downsample1_ptr methods[MAX_COMPONENTS]; } my_downsampler; typedef my_downsampler * my_downsample_ptr; -/* - * Initialize for a downsampling pass. - */ - METHODDEF(void) start_pass_downsample (j_compress_ptr cinfo) { - /* no work for now */ } -/* - * Expand a component horizontally from width input_cols to width output_cols, - * by duplicating the rightmost samples. - */ - LOCAL(void) expand_right_edge (JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols, JDIMENSION output_cols) @@ -193368,21 +178519,15 @@ expand_right_edge (JSAMPARRAY image_data, int num_rows, int numcols = (int) (output_cols - input_cols); if (numcols > 0) { - for (row = 0; row < num_rows; row++) { - ptr = image_data[row] + input_cols; - pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ - for (count = numcols; count > 0; count--) + for (row = 0; row < num_rows; row++) { + ptr = image_data[row] + input_cols; + pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ + for (count = numcols; count > 0; count--) *ptr++ = pixval; - } + } } } -/* - * Do downsampling for a whole row group (all components). - * - * In this version we simply downsample each component independently. - */ - METHODDEF(void) sep_downsample (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_index, @@ -193394,20 +178539,13 @@ sep_downsample (j_compress_ptr cinfo, JSAMPARRAY in_ptr, out_ptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - in_ptr = input_buf[ci] + in_row_index; - out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); - (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); + ci++, compptr++) { + in_ptr = input_buf[ci] + in_row_index; + out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); + (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); } } -/* - * Downsample pixel values of a single component. - * One row group is processed per call. - * This version handles arbitrary integral sampling ratios, without smoothing. - * Note that this version is not actually used for customary sampling ratios. - */ - METHODDEF(void) int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) @@ -193423,61 +178561,37 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, numpix = h_expand * v_expand; numpix2 = numpix/2; - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * h_expand); + cinfo->image_width, output_cols * h_expand); inrow = 0; for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - for (outcol = 0, outcol_h = 0; outcol < output_cols; + outptr = output_data[outrow]; + for (outcol = 0, outcol_h = 0; outcol < output_cols; outcol++, outcol_h += h_expand) { - outvalue = 0; - for (v = 0; v < v_expand; v++) { + outvalue = 0; + for (v = 0; v < v_expand; v++) { inptr = input_data[inrow+v] + outcol_h; for (h = 0; h < h_expand; h++) { outvalue += (INT32) GETJSAMPLE(*inptr++); } - } - *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); - } - inrow += v_expand; + } + *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); + } + inrow += v_expand; } } -/* - * Downsample pixel values of a single component. - * This version handles the special case of a full-size component, - * without smoothing. - */ - METHODDEF(void) fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + JSAMPARRAY input_data, JSAMPARRAY output_data) { - /* Copy the data */ jcopy_sample_rows(input_data, 0, output_data, 0, - cinfo->max_v_samp_factor, cinfo->image_width); - /* Edge-expand */ + cinfo->max_v_samp_factor, cinfo->image_width); expand_right_edge(output_data, cinfo->max_v_samp_factor, - cinfo->image_width, compptr->width_in_blocks * DCTSIZE); + cinfo->image_width, compptr->width_in_blocks * DCTSIZE); } -/* - * Downsample pixel values of a single component. - * This version handles the common case of 2:1 horizontal and 1:1 vertical, - * without smoothing. - * - * A note about the "bias" calculations: when rounding fractional values to - * integer, we do not want to always round 0.5 up to the next integer. - * If we did that, we'd introduce a noticeable bias towards larger values. - * Instead, this code is arranged so that 0.5 will be rounded up or down at - * alternate pixel locations (a simple ordered dither pattern). - */ - METHODDEF(void) h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) @@ -193488,32 +178602,22 @@ h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, register JSAMPROW inptr, outptr; register int bias; - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * 2); + cinfo->image_width, output_cols * 2); for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr = input_data[outrow]; - bias = 0; /* bias = 0,1,0,1,... for successive samples */ - for (outcol = 0; outcol < output_cols; outcol++) { - *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) - + bias) >> 1); - bias ^= 1; /* 0=>1, 1=>0 */ - inptr += 2; - } + outptr = output_data[outrow]; + inptr = input_data[outrow]; + bias = 0; /* bias = 0,1,0,1,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + + bias) >> 1); + bias ^= 1; /* 0=>1, 1=>0 */ + inptr += 2; + } } } -/* - * Downsample pixel values of a single component. - * This version handles the standard case of 2:1 horizontal and 2:1 vertical, - * without smoothing. - */ - METHODDEF(void) h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) @@ -193524,38 +178628,28 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, register JSAMPROW inptr0, inptr1, outptr; register int bias; - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * 2); + cinfo->image_width, output_cols * 2); inrow = 0; for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr0 = input_data[inrow]; - inptr1 = input_data[inrow+1]; - bias = 1; /* bias = 1,2,1,2,... for successive samples */ - for (outcol = 0; outcol < output_cols; outcol++) { - *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) - + bias) >> 2); - bias ^= 3; /* 1=>2, 2=>1 */ - inptr0 += 2; inptr1 += 2; - } - inrow += 2; + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + bias = 1; /* bias = 1,2,1,2,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + + bias) >> 2); + bias ^= 3; /* 1=>2, 2=>1 */ + inptr0 += 2; inptr1 += 2; + } + inrow += 2; } } #ifdef INPUT_SMOOTHING_SUPPORTED -/* - * Downsample pixel values of a single component. - * This version handles the standard case of 2:1 horizontal and 2:1 vertical, - * with smoothing. One row of context is required. - */ - METHODDEF(void) h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) @@ -193566,98 +178660,67 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, - cinfo->image_width, output_cols * 2); - - /* We don't bother to form the individual "smoothed" input pixel values; - * we can directly compute the output which is the average of the four - * smoothed values. Each of the four member pixels contributes a fraction - * (1-8*SF) to its own smoothed image and a fraction SF to each of the three - * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final - * output. The four corner-adjacent neighbor pixels contribute a fraction - * SF to just one smoothed pixel, or SF/4 to the final output; while the - * eight edge-adjacent neighbors contribute SF to each of two smoothed - * pixels, or SF/2 overall. In order to use integer arithmetic, these - * factors are scaled by 2^16 = 65536. - * Also recall that SF = smoothing_factor / 1024. - */ + cinfo->image_width, output_cols * 2); memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ inrow = 0; for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr0 = input_data[inrow]; - inptr1 = input_data[inrow+1]; - above_ptr = input_data[inrow-1]; - below_ptr = input_data[inrow+2]; + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+2]; - /* Special case for first column: pretend column -1 is same as column 0 */ - membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); - neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); - neighsum += neighsum; - neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); + neighsum += neighsum; + neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); - membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; - for (colctr = output_cols - 2; colctr > 0; colctr--) { - /* sum of pixels directly mapped to this output element */ - membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); - /* sum of edge-neighbor pixels */ - neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); - /* The edge-neighbors count twice as much as corner-neighbors */ - neighsum += neighsum; - /* Add in the corner-neighbors */ - neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + + neighsum += neighsum; + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); - /* form final output scaled up by 2^16 */ - membersum = membersum * memberscale + neighsum * neighscale; - /* round, descale and output it */ - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; - } + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + } - /* Special case for last column */ - membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); - neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); - neighsum += neighsum; - neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); + neighsum += neighsum; + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); - membersum = membersum * memberscale + neighsum * neighscale; - *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); - inrow += 2; + inrow += 2; } } -/* - * Downsample pixel values of a single component. - * This version handles the special case of a full-size component, - * with smoothing. One row of context is required. - */ - METHODDEF(void) fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + JSAMPARRAY input_data, JSAMPARRAY output_data) { int outrow; JDIMENSION colctr; @@ -193666,66 +178729,49 @@ fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, INT32 membersum, neighsum, memberscale, neighscale; int colsum, lastcolsum, nextcolsum; - /* Expand input data enough to let all the output samples be generated - * by the standard loop. Special-casing padded output would be more - * efficient. - */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, - cinfo->image_width, output_cols); - - /* Each of the eight neighbor pixels contributes a fraction SF to the - * smoothed pixel, while the main pixel contributes (1-8*SF). In order - * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. - * Also recall that SF = smoothing_factor / 1024. - */ + cinfo->image_width, output_cols); memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr = input_data[outrow]; - above_ptr = input_data[outrow-1]; - below_ptr = input_data[outrow+1]; + outptr = output_data[outrow]; + inptr = input_data[outrow]; + above_ptr = input_data[outrow-1]; + below_ptr = input_data[outrow+1]; - /* Special case for first column */ - colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + - GETJSAMPLE(*inptr); - membersum = GETJSAMPLE(*inptr++); - nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + GETJSAMPLE(*inptr); - neighsum = colsum + (colsum - membersum) + nextcolsum; - membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - lastcolsum = colsum; colsum = nextcolsum; + membersum = GETJSAMPLE(*inptr++); + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = colsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; - for (colctr = output_cols - 2; colctr > 0; colctr--) { - membersum = GETJSAMPLE(*inptr++); - above_ptr++; below_ptr++; - nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + membersum = GETJSAMPLE(*inptr++); + above_ptr++; below_ptr++; + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); - neighsum = lastcolsum + (colsum - membersum) + nextcolsum; - membersum = membersum * memberscale + neighsum * neighscale; - *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); - lastcolsum = colsum; colsum = nextcolsum; - } + neighsum = lastcolsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + } - /* Special case for last column */ - membersum = GETJSAMPLE(*inptr); - neighsum = lastcolsum + (colsum - membersum) + colsum; - membersum = membersum * memberscale + neighsum * neighscale; - *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + membersum = GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + colsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); } } #endif /* INPUT_SMOOTHING_SUPPORTED */ -/* - * Module initialization routine for downsampling. - * Note that we must select a routine for each component. - */ - GLOBAL(void) jinit_downsampler (j_compress_ptr cinfo) { @@ -193735,7 +178781,7 @@ jinit_downsampler (j_compress_ptr cinfo) boolean smoothok = TRUE; downsample = (my_downsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_downsampler)); cinfo->downsample = (struct jpeg_downsampler *) downsample; downsample->pub.start_pass = start_pass_downsample; @@ -193743,44 +178789,43 @@ jinit_downsampler (j_compress_ptr cinfo) downsample->pub.need_context_rows = FALSE; if (cinfo->CCIR601_sampling) - ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); - /* Verify we can handle the sampling factors, and set up method pointers */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor == cinfo->max_h_samp_factor && + ci++, compptr++) { + if (compptr->h_samp_factor == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) { #ifdef INPUT_SMOOTHING_SUPPORTED - if (cinfo->smoothing_factor) { + if (cinfo->smoothing_factor) { downsample->methods[ci] = fullsize_smooth_downsample; downsample->pub.need_context_rows = TRUE; - } else + } else #endif downsample->methods[ci] = fullsize_downsample; - } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && - compptr->v_samp_factor == cinfo->max_v_samp_factor) { - smoothok = FALSE; - downsample->methods[ci] = h2v1_downsample; - } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && - compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { + smoothok = FALSE; + downsample->methods[ci] = h2v1_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { #ifdef INPUT_SMOOTHING_SUPPORTED - if (cinfo->smoothing_factor) { + if (cinfo->smoothing_factor) { downsample->methods[ci] = h2v2_smooth_downsample; downsample->pub.need_context_rows = TRUE; - } else + } else #endif downsample->methods[ci] = h2v2_downsample; - } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && - (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { - smoothok = FALSE; - downsample->methods[ci] = int_downsample; - } else - ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && + (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { + smoothok = FALSE; + downsample->methods[ci] = int_downsample; + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); } #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor && !smoothok) - TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); + TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); #endif } /********* End of inlined file: jcsample.c *********/ @@ -193788,192 +178833,117 @@ jinit_downsampler (j_compress_ptr cinfo) /********* Start of inlined file: jctrans.c *********/ #define JPEG_INTERNALS -/* Forward declarations */ LOCAL(void) transencode_master_selection JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); LOCAL(void) transencode_coef_controller JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); -/* - * Compression initialization for writing raw-coefficient data. - * Before calling this, all parameters and a data destination must be set up. - * Call jpeg_finish_compress() to actually write the data. - * - * The number of passed virtual arrays must match cinfo->num_components. - * Note that the virtual arrays need not be filled or even realized at - * the time write_coefficients is called; indeed, if the virtual arrays - * were requested from this compression object's memory manager, they - * typically will be realized during this routine and filled afterwards. - */ - GLOBAL(void) jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { if (cinfo->global_state != CSTATE_START) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Mark all tables to be written */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); jpeg_suppress_tables(cinfo, FALSE); - /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); - /* Perform master selection of active modules */ transencode_master_selection(cinfo, coef_arrays); - /* Wait for jpeg_finish_compress() call */ cinfo->next_scanline = 0; /* so jpeg_write_marker works */ cinfo->global_state = CSTATE_WRCOEFS; } -/* - * Initialize the compression object with default parameters, - * then copy from the source object all parameters needed for lossless - * transcoding. Parameters that can be varied without loss (such as - * scan script and Huffman optimization) are left in their default states. - */ - GLOBAL(void) jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, - j_compress_ptr dstinfo) + j_compress_ptr dstinfo) { JQUANT_TBL ** qtblptr; jpeg_component_info *incomp, *outcomp; JQUANT_TBL *c_quant, *slot_quant; int tblno, ci, coefi; - /* Safety check to ensure start_compress not called yet. */ if (dstinfo->global_state != CSTATE_START) - ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); - /* Copy fundamental image dimensions */ + ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); dstinfo->image_width = srcinfo->image_width; dstinfo->image_height = srcinfo->image_height; dstinfo->input_components = srcinfo->num_components; dstinfo->in_color_space = srcinfo->jpeg_color_space; - /* Initialize all parameters to default values */ jpeg_set_defaults(dstinfo); - /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. - * Fix it to get the right header markers for the image colorspace. - */ jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); dstinfo->data_precision = srcinfo->data_precision; dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; - /* Copy the source's quantization tables. */ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { - if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { - qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; - if (*qtblptr == NULL) + if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { + qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; + if (*qtblptr == NULL) *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); - MEMCOPY((*qtblptr)->quantval, - srcinfo->quant_tbl_ptrs[tblno]->quantval, - SIZEOF((*qtblptr)->quantval)); - (*qtblptr)->sent_table = FALSE; - } + MEMCOPY((*qtblptr)->quantval, + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); + (*qtblptr)->sent_table = FALSE; + } } - /* Copy the source's per-component info. - * Note we assume jpeg_set_defaults has allocated the dest comp_info array. - */ dstinfo->num_components = srcinfo->num_components; if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) - ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, - MAX_COMPONENTS); + ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, + MAX_COMPONENTS); for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; - ci < dstinfo->num_components; ci++, incomp++, outcomp++) { - outcomp->component_id = incomp->component_id; - outcomp->h_samp_factor = incomp->h_samp_factor; - outcomp->v_samp_factor = incomp->v_samp_factor; - outcomp->quant_tbl_no = incomp->quant_tbl_no; - /* Make sure saved quantization table for component matches the qtable - * slot. If not, the input file re-used this qtable slot. - * IJG encoder currently cannot duplicate this. - */ - tblno = outcomp->quant_tbl_no; - if (tblno < 0 || tblno >= NUM_QUANT_TBLS || + ci < dstinfo->num_components; ci++, incomp++, outcomp++) { + outcomp->component_id = incomp->component_id; + outcomp->h_samp_factor = incomp->h_samp_factor; + outcomp->v_samp_factor = incomp->v_samp_factor; + outcomp->quant_tbl_no = incomp->quant_tbl_no; + tblno = outcomp->quant_tbl_no; + if (tblno < 0 || tblno >= NUM_QUANT_TBLS || srcinfo->quant_tbl_ptrs[tblno] == NULL) - ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); - slot_quant = srcinfo->quant_tbl_ptrs[tblno]; - c_quant = incomp->quant_table; - if (c_quant != NULL) { - for (coefi = 0; coefi < DCTSIZE2; coefi++) { + ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); + slot_quant = srcinfo->quant_tbl_ptrs[tblno]; + c_quant = incomp->quant_table; + if (c_quant != NULL) { + for (coefi = 0; coefi < DCTSIZE2; coefi++) { if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); - } - } - /* Note: we do not copy the source's Huffman table assignments; - * instead we rely on jpeg_set_colorspace to have made a suitable choice. - */ + } + } } - /* Also copy JFIF version and resolution information, if available. - * Strictly speaking this isn't "critical" info, but it's nearly - * always appropriate to copy it if available. In particular, - * if the application chooses to copy JFIF 1.02 extension markers from - * the source file, we need to copy the version to make sure we don't - * emit a file that has 1.02 extensions but a claimed version of 1.01. - * We will *not*, however, copy version info from mislabeled "2.01" files. - */ if (srcinfo->saw_JFIF_marker) { - if (srcinfo->JFIF_major_version == 1) { - dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; - dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; - } - dstinfo->density_unit = srcinfo->density_unit; - dstinfo->X_density = srcinfo->X_density; - dstinfo->Y_density = srcinfo->Y_density; + if (srcinfo->JFIF_major_version == 1) { + dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; + dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; + } + dstinfo->density_unit = srcinfo->density_unit; + dstinfo->X_density = srcinfo->X_density; + dstinfo->Y_density = srcinfo->Y_density; } } -/* - * Master selection of compression modules for transcoding. - * This substitutes for jcinit.c's initialization of the full compressor. - */ - LOCAL(void) transencode_master_selection (j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays) + jvirt_barray_ptr * coef_arrays) { - /* Although we don't actually use input_components for transcoding, - * jcmaster.c's initial_setup will complain if input_components is 0. - */ cinfo->input_components = 1; - /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, TRUE /* transcode only */); - /* Entropy encoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); } else { - if (cinfo->progressive_mode) { + if (cinfo->progressive_mode) { #ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); + jinit_phuff_encoder(cinfo); #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif - } else - jinit_huff_encoder(cinfo); + } else + jinit_huff_encoder(cinfo); } - /* We need a special coefficient buffer controller. */ transencode_coef_controller(cinfo, coef_arrays); jinit_marker_writer(cinfo); - /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - /* Write the datastream header (SOI, JFIF) immediately. - * Frame and scan headers are postponed till later. - * This lets application insert special markers after the SOI. - */ (*cinfo->marker->write_file_header) (cinfo); } -/* - * The rest of this file is a special implementation of the coefficient - * buffer controller. This is similar to jccoefct.c, but it handles only - * output from presupplied virtual arrays. Furthermore, we generate any - * dummy padding blocks on-the-fly rather than expecting them to be present - * in the arrays. - */ - -/* Private buffer controller object */ - typedef struct { struct jpeg_c_coef_controller pub; /* public fields */ @@ -193982,10 +178952,8 @@ typedef struct { int MCU_vert_offset; /* counts MCU rows within iMCU row */ int MCU_rows_per_iMCU_row; /* number of such rows needed */ - /* Virtual block array for each component. */ jvirt_barray_ptr * whole_image; - /* Workspace for constructing dummy blocks at right/bottom edges. */ JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; } my_coef_controller2; @@ -193993,53 +178961,34 @@ typedef my_coef_controller2 * my_coef_ptr2; LOCAL(void) start_iMCU_row2 (j_compress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row */ { my_coef_ptr2 coef = (my_coef_ptr2) cinfo->coef; - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; + coef->MCU_rows_per_iMCU_row = 1; } else { - if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; } coef->mcu_ctr = 0; coef->MCU_vert_offset = 0; } -/* - * Initialize for a processing pass. - */ - METHODDEF(void) start_pass_coef2 (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_coef_ptr2 coef = (my_coef_ptr2) cinfo->coef; if (pass_mode != JBUF_CRANK_DEST) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->iMCU_row_num = 0; start_iMCU_row2(cinfo); } -/* - * Process some data. - * We process the equivalent of one fully interleaved MCU row ("iMCU" row) - * per call, ie, v_samp_factor block rows for each component in the scan. - * The data is obtained from the virtual arrays and fed to the entropy coder. - * Returns TRUE if the iMCU row is completed, FALSE if suspended. - * - * NB: input_buf is ignored; it is likely to be a NULL pointer. - */ - METHODDEF(boolean) compress_output2 (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { @@ -194054,101 +179003,76 @@ compress_output2 (j_compress_ptr cinfo, JSAMPIMAGE input_buf) JBLOCKROW buffer_ptr; jpeg_component_info *compptr; - /* Align the virtual buffers for the components used in this scan. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - coef->iMCU_row_num * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); } - /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || - yindex+yoffset < compptr->last_row_height) { - /* Fill in pointers to real blocks in this row */ - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < blockcnt; xindex++) - MCU_buffer[blkn++] = buffer_ptr++; + yindex+yoffset < compptr->last_row_height) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; } else { - /* At bottom of image, need a whole row of dummy blocks */ - xindex = 0; + xindex = 0; } - /* Fill in any dummy blocks needed in this row. - * Dummy blocks are filled in the same way as in jccoefct.c: - * all zeroes in the AC entries, DC entries equal to previous - * block's DC value. The init routine has already zeroed the - * AC entries, so we need only set the DC entries correctly. - */ for (; xindex < compptr->MCU_width; xindex++) { - MCU_buffer[blkn] = coef->dummy_buffer[blkn]; - MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; - blkn++; + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; } } - } - /* Try to write the MCU. */ - if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { - /* Suspension forced; update state counters and exit */ + } + if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; return FALSE; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->mcu_ctr = 0; + } + } + coef->mcu_ctr = 0; } - /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row2(cinfo); return TRUE; } -/* - * Initialize coefficient buffer controller. - * - * Each passed coefficient array must be the right size for that - * coefficient: width_in_blocks wide and height_in_blocks high, - * with unitheight at least v_samp_factor. - */ - LOCAL(void) transencode_coef_controller (j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays) + jvirt_barray_ptr * coef_arrays) { my_coef_ptr2 coef; JBLOCKROW buffer; int i; coef = (my_coef_ptr2) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller2)); cinfo->coef = (struct jpeg_c_coef_controller *) coef; coef->pub.start_pass = start_pass_coef2; coef->pub.compress_data = compress_output2; - /* Save pointer to virtual arrays */ coef->whole_image = coef_arrays; - /* Allocate and pre-zero space for dummy DCT blocks. */ buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { - coef->dummy_buffer[i] = buffer + i; + coef->dummy_buffer[i] = buffer + i; } } /********* End of inlined file: jctrans.c *********/ @@ -194156,248 +179080,168 @@ transencode_coef_controller (j_compress_ptr cinfo, /********* Start of inlined file: jdapistd.c *********/ #define JPEG_INTERNALS -/* Forward declarations */ LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); -/* - * Decompression initialization. - * jpeg_read_header must be completed before calling this. - * - * If a multipass operating mode was selected, this will do all but the - * last pass, and thus may take a great deal of time. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - GLOBAL(boolean) jpeg_start_decompress (j_decompress_ptr cinfo) { if (cinfo->global_state == DSTATE_READY) { - /* First call: initialize master control, select active modules */ - jinit_master_decompress(cinfo); - if (cinfo->buffered_image) { - /* No more work here; expecting jpeg_start_output next */ - cinfo->global_state = DSTATE_BUFIMAGE; - return TRUE; - } - cinfo->global_state = DSTATE_PRELOAD; + jinit_master_decompress(cinfo); + if (cinfo->buffered_image) { + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; + } + cinfo->global_state = DSTATE_PRELOAD; } if (cinfo->global_state == DSTATE_PRELOAD) { - /* If file has multiple scans, absorb them all into the coef buffer */ - if (cinfo->inputctl->has_multiple_scans) { + if (cinfo->inputctl->has_multiple_scans) { #ifdef D_MULTISCAN_FILES_SUPPORTED - for (;;) { + for (;;) { int retcode; - /* Call progress monitor hook if present */ if (cinfo->progress != NULL) (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - /* Absorb some more input */ retcode = (*cinfo->inputctl->consume_input) (cinfo); if (retcode == JPEG_SUSPENDED) return FALSE; if (retcode == JPEG_REACHED_EOI) break; - /* Advance progress counter if appropriate */ if (cinfo->progress != NULL && - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* jdmaster underestimated number of scans; ratchet up one scan */ - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; } } - } + } #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif /* D_MULTISCAN_FILES_SUPPORTED */ - } - cinfo->output_scan_number = cinfo->input_scan_number; + } + cinfo->output_scan_number = cinfo->input_scan_number; } else if (cinfo->global_state != DSTATE_PRESCAN) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Perform any dummy output passes, and set up for the final pass */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); return output_pass_setup(cinfo); } -/* - * Set up for an output pass, and perform any dummy pass(es) needed. - * Common subroutine for jpeg_start_decompress and jpeg_start_output. - * Entry: global_state = DSTATE_PRESCAN only if previously suspended. - * Exit: If done, returns TRUE and sets global_state for proper output mode. - * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. - */ - LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo) { if (cinfo->global_state != DSTATE_PRESCAN) { - /* First call: do pass setup */ - (*cinfo->master->prepare_for_output_pass) (cinfo); - cinfo->output_scanline = 0; - cinfo->global_state = DSTATE_PRESCAN; + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; + cinfo->global_state = DSTATE_PRESCAN; } - /* Loop over any required dummy passes */ while (cinfo->master->is_dummy_pass) { #ifdef QUANT_2PASS_SUPPORTED - /* Crank through the dummy pass */ - while (cinfo->output_scanline < cinfo->output_height) { - JDIMENSION last_scanline; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) { + while (cinfo->output_scanline < cinfo->output_height) { + JDIMENSION last_scanline; + if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->output_scanline; cinfo->progress->pass_limit = (long) cinfo->output_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - } - /* Process some data */ - last_scanline = cinfo->output_scanline; - (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, - &cinfo->output_scanline, (JDIMENSION) 0); - if (cinfo->output_scanline == last_scanline) + } + last_scanline = cinfo->output_scanline; + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, + &cinfo->output_scanline, (JDIMENSION) 0); + if (cinfo->output_scanline == last_scanline) return FALSE; /* No progress made, must suspend */ - } - /* Finish up dummy pass, and set up for another one */ - (*cinfo->master->finish_output_pass) (cinfo); - (*cinfo->master->prepare_for_output_pass) (cinfo); - cinfo->output_scanline = 0; + } + (*cinfo->master->finish_output_pass) (cinfo); + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif /* QUANT_2PASS_SUPPORTED */ } - /* Ready for application to drive output pass through - * jpeg_read_scanlines or jpeg_read_raw_data. - */ cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; return TRUE; } -/* - * Read some scanlines of data from the JPEG decompressor. - * - * The return value will be the number of lines actually read. - * This may be less than the number requested in several cases, - * including bottom of image, data source suspension, and operating - * modes that emit multiple scanlines at a time. - * - * Note: we warn about excess calls to jpeg_read_scanlines() since - * this likely signals an application programmer error. However, - * an oversize buffer (max_lines > scanlines remaining) is not an error. - */ - GLOBAL(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION max_lines) + JDIMENSION max_lines) { JDIMENSION row_ctr; if (cinfo->global_state != DSTATE_SCANNING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; } - /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } - /* Process some data */ row_ctr = 0; (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); cinfo->output_scanline += row_ctr; return row_ctr; } -/* - * Alternate entry point to read raw data. - * Processes exactly one iMCU row per call, unless suspended. - */ - GLOBAL(JDIMENSION) jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION max_lines) + JDIMENSION max_lines) { JDIMENSION lines_per_iMCU_row; if (cinfo->global_state != DSTATE_RAW_OK) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { - WARNMS(cinfo, JWRN_TOO_MUCH_DATA); - return 0; + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; } - /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } - /* Verify that at least one iMCU row can be returned. */ lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; if (max_lines < lines_per_iMCU_row) - ERREXIT(cinfo, JERR_BUFFER_SIZE); + ERREXIT(cinfo, JERR_BUFFER_SIZE); - /* Decompress directly into user's buffer. */ if (! (*cinfo->coef->decompress_data) (cinfo, data)) - return 0; /* suspension forced, can do nothing more */ + return 0; /* suspension forced, can do nothing more */ - /* OK, we processed one iMCU row. */ cinfo->output_scanline += lines_per_iMCU_row; return lines_per_iMCU_row; } -/* Additional entry points for buffered-image mode. */ - #ifdef D_MULTISCAN_FILES_SUPPORTED -/* - * Initialize for an output pass in buffered-image mode. - */ - GLOBAL(boolean) jpeg_start_output (j_decompress_ptr cinfo, int scan_number) { if (cinfo->global_state != DSTATE_BUFIMAGE && - cinfo->global_state != DSTATE_PRESCAN) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); - /* Limit scan number to valid range */ + cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (scan_number <= 0) - scan_number = 1; + scan_number = 1; if (cinfo->inputctl->eoi_reached && - scan_number > cinfo->input_scan_number) - scan_number = cinfo->input_scan_number; + scan_number > cinfo->input_scan_number) + scan_number = cinfo->input_scan_number; cinfo->output_scan_number = scan_number; - /* Perform any dummy output passes, and set up for the real pass */ return output_pass_setup(cinfo); } -/* - * Finish up after an output pass in buffered-image mode. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - GLOBAL(boolean) jpeg_finish_output (j_decompress_ptr cinfo) { if ((cinfo->global_state == DSTATE_SCANNING || - cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { - /* Terminate this pass. */ - /* We do not require the whole pass to have been completed. */ - (*cinfo->master->finish_output_pass) (cinfo); - cinfo->global_state = DSTATE_BUFPOST; + cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_BUFPOST; } else if (cinfo->global_state != DSTATE_BUFPOST) { - /* BUFPOST = repeat call after a suspension, anything else is error */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } - /* Read markers looking for SOS or EOI */ while (cinfo->input_scan_number <= cinfo->output_scan_number && ! cinfo->inputctl->eoi_reached) { - if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) - return FALSE; /* Suspend, come back later */ + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ } cinfo->global_state = DSTATE_BUFIMAGE; return TRUE; @@ -194409,167 +179253,128 @@ jpeg_finish_output (j_decompress_ptr cinfo) /********* Start of inlined file: jdapimin.c *********/ #define JPEG_INTERNALS -/* - * Initialization of a JPEG decompression object. - * The error manager must already be set up (in case memory manager fails). - */ - GLOBAL(void) jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) { int i; - /* Guard against version mismatches between library and caller. */ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ if (version != JPEG_LIB_VERSION) - ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); if (structsize != SIZEOF(struct jpeg_decompress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, - (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); - /* For debugging purposes, we zero the whole master structure. - * But the application has already set the err pointer, and may have set - * client_data, so we have to save and restore those fields. - * Note: if application hasn't set client_data, tools like Purify may - * complain here. - */ { - struct jpeg_error_mgr * err = cinfo->err; - void * client_data = cinfo->client_data; /* ignore Purify complaint here */ - MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); - cinfo->err = err; - cinfo->client_data = client_data; + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; } cinfo->is_decompressor = TRUE; - /* Initialize a memory manager instance for this object */ jinit_memory_mgr((j_common_ptr) cinfo); - /* Zero out pointers to permanent structures. */ cinfo->progress = NULL; cinfo->src = NULL; for (i = 0; i < NUM_QUANT_TBLS; i++) - cinfo->quant_tbl_ptrs[i] = NULL; + cinfo->quant_tbl_ptrs[i] = NULL; for (i = 0; i < NUM_HUFF_TBLS; i++) { - cinfo->dc_huff_tbl_ptrs[i] = NULL; - cinfo->ac_huff_tbl_ptrs[i] = NULL; + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; } - /* Initialize marker processor so application can override methods - * for COM, APPn markers before calling jpeg_read_header. - */ cinfo->marker_list = NULL; jinit_marker_reader(cinfo); - /* And initialize the overall input controller. */ jinit_input_controller(cinfo); - /* OK, I'm ready */ cinfo->global_state = DSTATE_START; } -/* - * Destruction of a JPEG decompression object - */ - GLOBAL(void) jpeg_destroy_decompress (j_decompress_ptr cinfo) { jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ } -/* - * Abort processing of a JPEG decompression operation, - * but don't destroy the object itself. - */ - GLOBAL(void) jpeg_abort_decompress (j_decompress_ptr cinfo) { jpeg_abort((j_common_ptr) cinfo); /* use common routine */ } -/* - * Set default decompression parameters. - */ - LOCAL(void) default_decompress_parms (j_decompress_ptr cinfo) { - /* Guess the input colorspace, and set output colorspace accordingly. */ - /* (Wish JPEG committee had provided a real way to specify this...) */ - /* Note application may override our guesses. */ switch (cinfo->num_components) { case 1: - cinfo->jpeg_color_space = JCS_GRAYSCALE; - cinfo->out_color_space = JCS_GRAYSCALE; - break; + cinfo->jpeg_color_space = JCS_GRAYSCALE; + cinfo->out_color_space = JCS_GRAYSCALE; + break; case 3: - if (cinfo->saw_JFIF_marker) { - cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ - } else if (cinfo->saw_Adobe_marker) { - switch (cinfo->Adobe_transform) { - case 0: + if (cinfo->saw_JFIF_marker) { + cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ + } else if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: cinfo->jpeg_color_space = JCS_RGB; break; - case 1: + case 1: cinfo->jpeg_color_space = JCS_YCbCr; break; - default: + default: WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ break; - } - } else { - /* Saw no special markers, try to guess from the component IDs */ - int cid0 = cinfo->comp_info[0].component_id; - int cid1 = cinfo->comp_info[1].component_id; - int cid2 = cinfo->comp_info[2].component_id; + } + } else { + int cid0 = cinfo->comp_info[0].component_id; + int cid1 = cinfo->comp_info[1].component_id; + int cid2 = cinfo->comp_info[2].component_id; - if (cid0 == 1 && cid1 == 2 && cid2 == 3) + if (cid0 == 1 && cid1 == 2 && cid2 == 3) cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ - else if (cid0 == 82 && cid1 == 71 && cid2 == 66) + else if (cid0 == 82 && cid1 == 71 && cid2 == 66) cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ - else { + else { TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - } - } - /* Always guess RGB is proper output colorspace. */ - cinfo->out_color_space = JCS_RGB; - break; + } + } + cinfo->out_color_space = JCS_RGB; + break; case 4: - if (cinfo->saw_Adobe_marker) { - switch (cinfo->Adobe_transform) { - case 0: + if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: cinfo->jpeg_color_space = JCS_CMYK; break; - case 2: + case 2: cinfo->jpeg_color_space = JCS_YCCK; break; - default: + default: WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ break; - } - } else { - /* No special markers, assume straight CMYK. */ - cinfo->jpeg_color_space = JCS_CMYK; - } - cinfo->out_color_space = JCS_CMYK; - break; + } + } else { + cinfo->jpeg_color_space = JCS_CMYK; + } + cinfo->out_color_space = JCS_CMYK; + break; default: - cinfo->jpeg_color_space = JCS_UNKNOWN; - cinfo->out_color_space = JCS_UNKNOWN; - break; + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + break; } - /* Set defaults for other decompression parameters. */ cinfo->scale_num = 1; /* 1:1 scaling */ cinfo->scale_denom = 1; cinfo->output_gamma = 1.0; @@ -194579,7 +179384,6 @@ default_decompress_parms (j_decompress_ptr cinfo) cinfo->do_fancy_upsampling = TRUE; cinfo->do_block_smoothing = TRUE; cinfo->quantize_colors = FALSE; - /* We set these in case application only sets quantize_colors. */ cinfo->dither_mode = JDITHER_FS; #ifdef QUANT_2PASS_SUPPORTED cinfo->two_pass_quantize = TRUE; @@ -194588,111 +179392,59 @@ default_decompress_parms (j_decompress_ptr cinfo) #endif cinfo->desired_number_of_colors = 256; cinfo->colormap = NULL; - /* Initialize for no mode change in buffered-image mode. */ cinfo->enable_1pass_quant = FALSE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; } -/* - * Decompression startup: read start of JPEG datastream to see what's there. - * Need only initialize JPEG object and supply a data source before calling. - * - * This routine will read as far as the first SOS marker (ie, actual start of - * compressed data), and will save all tables and parameters in the JPEG - * object. It will also initialize the decompression parameters to default - * values, and finally return JPEG_HEADER_OK. On return, the application may - * adjust the decompression parameters and then call jpeg_start_decompress. - * (Or, if the application only wanted to determine the image parameters, - * the data need not be decompressed. In that case, call jpeg_abort or - * jpeg_destroy to release any temporary space.) - * If an abbreviated (tables only) datastream is presented, the routine will - * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then - * re-use the JPEG object to read the abbreviated image datastream(s). - * It is unnecessary (but OK) to call jpeg_abort in this case. - * The JPEG_SUSPENDED return code only occurs if the data source module - * requests suspension of the decompressor. In this case the application - * should load more source data and then re-call jpeg_read_header to resume - * processing. - * If a non-suspending data source is used and require_image is TRUE, then the - * return code need not be inspected since only JPEG_HEADER_OK is possible. - * - * This routine is now just a front end to jpeg_consume_input, with some - * extra error checking. - */ - GLOBAL(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) { int retcode; if (cinfo->global_state != DSTATE_START && - cinfo->global_state != DSTATE_INHEADER) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + cinfo->global_state != DSTATE_INHEADER) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); retcode = jpeg_consume_input(cinfo); switch (retcode) { case JPEG_REACHED_SOS: - retcode = JPEG_HEADER_OK; - break; + retcode = JPEG_HEADER_OK; + break; case JPEG_REACHED_EOI: - if (require_image) /* Complain if application wanted an image */ - ERREXIT(cinfo, JERR_NO_IMAGE); - /* Reset to start state; it would be safer to require the application to - * call jpeg_abort, but we can't change it now for compatibility reasons. - * A side effect is to free any temporary memory (there shouldn't be any). - */ - jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ - retcode = JPEG_HEADER_TABLES_ONLY; - break; + if (require_image) /* Complain if application wanted an image */ + ERREXIT(cinfo, JERR_NO_IMAGE); + jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ + retcode = JPEG_HEADER_TABLES_ONLY; + break; case JPEG_SUSPENDED: - /* no work */ - break; + break; } return retcode; } -/* - * Consume data in advance of what the decompressor requires. - * This can be called at any time once the decompressor object has - * been created and a data source has been set up. - * - * This routine is essentially a state machine that handles a couple - * of critical state-transition actions, namely initial setup and - * transition from header scanning to ready-for-start_decompress. - * All the actual input is done via the input controller's consume_input - * method. - */ - GLOBAL(int) jpeg_consume_input (j_decompress_ptr cinfo) { int retcode = JPEG_SUSPENDED; - /* NB: every possible DSTATE value should be listed in this switch */ switch (cinfo->global_state) { case DSTATE_START: - /* Start-of-datastream actions: reset appropriate modules */ - (*cinfo->inputctl->reset_input_controller) (cinfo); - /* Initialize application's data source module */ - (*cinfo->src->init_source) (cinfo); - cinfo->global_state = DSTATE_INHEADER; - /*FALLTHROUGH*/ + (*cinfo->inputctl->reset_input_controller) (cinfo); + (*cinfo->src->init_source) (cinfo); + cinfo->global_state = DSTATE_INHEADER; case DSTATE_INHEADER: - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ - /* Set up default parameters based on header data */ - default_decompress_parms(cinfo); - /* Set global state: ready for start_decompress */ - cinfo->global_state = DSTATE_READY; - } - break; + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ + default_decompress_parms(cinfo); + cinfo->global_state = DSTATE_READY; + } + break; case DSTATE_READY: - /* Can't advance past first SOS until start_decompress is called */ - retcode = JPEG_REACHED_SOS; - break; + retcode = JPEG_REACHED_SOS; + break; case DSTATE_PRELOAD: case DSTATE_PRESCAN: case DSTATE_SCANNING: @@ -194700,96 +179452,63 @@ jpeg_consume_input (j_decompress_ptr cinfo) case DSTATE_BUFIMAGE: case DSTATE_BUFPOST: case DSTATE_STOPPING: - retcode = (*cinfo->inputctl->consume_input) (cinfo); - break; + retcode = (*cinfo->inputctl->consume_input) (cinfo); + break; default: - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } return retcode; } -/* - * Have we finished reading the input file? - */ - GLOBAL(boolean) jpeg_input_complete (j_decompress_ptr cinfo) { - /* Check for valid jpeg object */ if (cinfo->global_state < DSTATE_START || - cinfo->global_state > DSTATE_STOPPING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); return cinfo->inputctl->eoi_reached; } -/* - * Is there more than one scan? - */ - GLOBAL(boolean) jpeg_has_multiple_scans (j_decompress_ptr cinfo) { - /* Only valid after jpeg_read_header completes */ if (cinfo->global_state < DSTATE_READY || - cinfo->global_state > DSTATE_STOPPING) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); return cinfo->inputctl->has_multiple_scans; } -/* - * Finish JPEG decompression. - * - * This will normally just verify the file trailer and release temp storage. - * - * Returns FALSE if suspended. The return value need be inspected only if - * a suspending data source is used. - */ - GLOBAL(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo) { if ((cinfo->global_state == DSTATE_SCANNING || - cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { - /* Terminate final pass of non-buffered mode */ - if (cinfo->output_scanline < cinfo->output_height) - ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); - (*cinfo->master->finish_output_pass) (cinfo); - cinfo->global_state = DSTATE_STOPPING; + cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { + if (cinfo->output_scanline < cinfo->output_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_STOPPING; } else if (cinfo->global_state == DSTATE_BUFIMAGE) { - /* Finishing after a buffered-image operation */ - cinfo->global_state = DSTATE_STOPPING; + cinfo->global_state = DSTATE_STOPPING; } else if (cinfo->global_state != DSTATE_STOPPING) { - /* STOPPING = repeat call after a suspension, anything else is error */ - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } - /* Read until EOI */ while (! cinfo->inputctl->eoi_reached) { - if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) - return FALSE; /* Suspend, come back later */ + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ } - /* Do final cleanup */ (*cinfo->src->term_source) (cinfo); - /* We can use jpeg_abort to release memory and reset global_state */ jpeg_abort((j_common_ptr) cinfo); return TRUE; } /********* End of inlined file: jdapimin.c *********/ /********* Start of inlined file: jdatasrc.c *********/ -/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ /********* Start of inlined file: jerror.h *********/ -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ #ifndef JMESSAGE #ifndef JERROR_H -/* First time through, define the enum list */ #define JMAKE_ENUM_LIST #else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ #define JMESSAGE(code,string) #endif /* JERROR_H */ #endif /* JMESSAGE */ @@ -194804,7 +179523,6 @@ typedef enum { JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ -/* For maintenance convenience, list is alphabetical by message code name */ JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, there are legal restrictions on arithmetic coding") JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") @@ -194957,16 +179675,11 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #undef JMAKE_ENUM_LIST #endif /* JMAKE_ENUM_LIST */ -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ #undef JMESSAGE #ifndef JERROR_H #define JERROR_H -/* Macros to simplify using the error and trace message stuff */ -/* The first parameter is either type of cinfo pointer */ - -/* Fatal errors (print message and exit) */ #define ERREXIT(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) @@ -194999,7 +179712,6 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #define MAKESTMT(stuff) do { stuff } while (0) -/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ #define WARNMS(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) @@ -195013,7 +179725,6 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -/* Informational/debugging messages */ #define TRACEMS(cinfo,lvl,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) @@ -195056,8 +179767,6 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") #endif /* JERROR_H */ /********* End of inlined file: jerror.h *********/ -/* Expanded data source object for stdio input */ - typedef struct { struct jpeg_source_mgr pub; /* public fields */ @@ -195070,56 +179779,14 @@ typedef my_source_mgr * my_src_ptr; #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ -/* - * Initialize source --- called by jpeg_read_header - * before any data is actually read. - */ - METHODDEF(void) init_source (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; - /* We reset the empty-input-file flag for each image, - * but we don't clear the input buffer. - * This is correct behavior for reading a series of images from one source. - */ src->start_of_file = TRUE; } -/* - * Fill the input buffer --- called whenever buffer is emptied. - * - * In typical applications, this should read fresh data into the buffer - * (ignoring the current state of next_input_byte & bytes_in_buffer), - * reset the pointer & count to the start of the buffer, and return TRUE - * indicating that the buffer has been reloaded. It is not necessary to - * fill the buffer entirely, only to obtain at least one more byte. - * - * There is no such thing as an EOF return. If the end of the file has been - * reached, the routine has a choice of ERREXIT() or inserting fake data into - * the buffer. In most cases, generating a warning message and inserting a - * fake EOI marker is the best course of action --- this will allow the - * decompressor to output however much of the image is there. However, - * the resulting error message is misleading if the real problem is an empty - * input file, so we handle that case specially. - * - * In applications that need to be able to suspend compression due to input - * not being available yet, a FALSE return indicates that no more data can be - * obtained right now, but more may be forthcoming later. In this situation, - * the decompressor will return to its caller (with an indication of the - * number of scanlines it has read, if any). The application should resume - * decompression after it has loaded more data into the input buffer. Note - * that there are substantial restrictions on the use of suspension --- see - * the documentation. - * - * When suspending, the decompressor will back up to a convenient restart point - * (typically the start of the current MCU). next_input_byte & bytes_in_buffer - * indicate where the restart point will be if the current call returns FALSE. - * Data beyond this point must be rescanned after resumption, so move it to - * the front of the buffer rather than discarding it. - */ - METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo) { @@ -195129,13 +179796,12 @@ fill_input_buffer (j_decompress_ptr cinfo) nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); if (nbytes <= 0) { - if (src->start_of_file) /* Treat empty input file as fatal error */ - ERREXIT(cinfo, JERR_INPUT_EMPTY); - WARNMS(cinfo, JWRN_JPEG_EOF); - /* Insert a fake EOI marker */ - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; - nbytes = 2; + if (src->start_of_file) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; } src->pub.next_input_byte = src->buffer; @@ -195145,88 +179811,38 @@ fill_input_buffer (j_decompress_ptr cinfo) return TRUE; } -/* - * Skip data --- used to skip over a potentially large amount of - * uninteresting data (such as an APPn marker). - * - * Writers of suspendable-input applications must note that skip_input_data - * is not granted the right to give a suspension return. If the skip extends - * beyond the data currently in the buffer, the buffer can be marked empty so - * that the next read will cause a fill_input_buffer call that can suspend. - * Arranging for additional bytes to be discarded before reloading the input - * buffer is the application writer's problem. - */ - METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes) { my_src_ptr src = (my_src_ptr) cinfo->src; - /* Just a dumb implementation for now. Could use fseek() except - * it doesn't work on pipes. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) fill_input_buffer(cinfo); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; } } -/* - * An additional method that can be provided by data source modules is the - * resync_to_restart method for error recovery in the presence of RST markers. - * For the moment, this source module just uses the default resync method - * provided by the JPEG library. That method assumes that no backtracking - * is possible. - */ - -/* - * Terminate source --- called by jpeg_finish_decompress - * after all data has been read. Often a no-op. - * - * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding - * application must deal with any cleanup that should happen even - * for error exit. - */ - METHODDEF(void) term_source (j_decompress_ptr cinfo) { - /* no work necessary here */ } -/* - * Prepare for input from a stdio stream. - * The caller must have already opened the stream, and is responsible - * for closing it after finishing decompression. - */ - GLOBAL(void) jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) { my_src_ptr src; - /* The source object and input buffer are made permanent so that a series - * of JPEG images can be read from the same file by calling jpeg_stdio_src - * only before the first one. (If we discarded the buffer at the end of - * one image, we'd likely lose the start of the next one.) - * This makes it unsafe to use this manager and a different source - * manager serially with the same JPEG object. Caveat programmer. - */ if (cinfo->src == NULL) { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_source_mgr)); - src = (my_src_ptr) cinfo->src; - src->buffer = (JOCTET *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * SIZEOF(JOCTET)); } @@ -195245,42 +179861,24 @@ jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) /********* Start of inlined file: jdcoefct.c *********/ #define JPEG_INTERNALS -/* Block smoothing is only applicable for progressive JPEG, so: */ #ifndef D_PROGRESSIVE_SUPPORTED #undef BLOCK_SMOOTHING_SUPPORTED #endif -/* Private buffer controller object */ - typedef struct { struct jpeg_d_coef_controller pub; /* public fields */ - /* These variables keep track of the current location of the input side. */ - /* cinfo->input_iMCU_row is also used for this. */ JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ int MCU_vert_offset; /* counts MCU rows within iMCU row */ int MCU_rows_per_iMCU_row; /* number of such rows needed */ - /* The output side's location is represented by cinfo->output_iMCU_row. */ - - /* In single-pass modes, it's sufficient to buffer just one MCU. - * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, - * and let the entropy decoder write into that workspace each time. - * (On 80x86, the workspace is FAR even though it's not really very big; - * this is to keep the module interfaces unchanged when a large coefficient - * buffer is necessary.) - * In multi-pass modes, this array points to the current MCU's blocks - * within the virtual arrays; it is used only by the input side. - */ JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; #ifdef D_MULTISCAN_FILES_SUPPORTED - /* In multi-pass modes, we need a virtual block array for each component. */ jvirt_barray_ptr whole_image[MAX_COMPONENTS]; #endif #ifdef BLOCK_SMOOTHING_SUPPORTED - /* When doing block smoothing, we latch coefficient Al values here */ int * coef_bits_latch; #define SAVED_COEFS 6 /* we save coef_bits[0..5] */ #endif @@ -195288,7 +179886,6 @@ typedef struct { typedef my_coef_controller3 * my_coef_ptr3; -/* Forward declarations */ METHODDEF(int) decompress_onepass JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); #ifdef D_MULTISCAN_FILES_SUPPORTED @@ -195303,31 +179900,22 @@ METHODDEF(int) decompress_smooth_data LOCAL(void) start_iMCU_row3 (j_decompress_ptr cinfo) -/* Reset within-iMCU-row counters for a new row (input side) */ { my_coef_ptr3 coef = (my_coef_ptr3) cinfo->coef; - /* In an interleaved scan, an MCU row is the same as an iMCU row. - * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. - * But at the bottom of the image, process only what's left. - */ if (cinfo->comps_in_scan > 1) { - coef->MCU_rows_per_iMCU_row = 1; + coef->MCU_rows_per_iMCU_row = 1; } else { - if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; - else - coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; } coef->MCU_ctr = 0; coef->MCU_vert_offset = 0; } -/* - * Initialize for an input processing pass. - */ - METHODDEF(void) start_input_pass (j_decompress_ptr cinfo) { @@ -195335,37 +179923,22 @@ start_input_pass (j_decompress_ptr cinfo) start_iMCU_row3(cinfo); } -/* - * Initialize for an output processing pass. - */ - METHODDEF(void) start_output_pass (j_decompress_ptr cinfo) { #ifdef BLOCK_SMOOTHING_SUPPORTED my_coef_ptr3 coef = (my_coef_ptr3) cinfo->coef; - /* If multipass, check to see whether to use block smoothing on this pass */ if (coef->pub.coef_arrays != NULL) { - if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) - coef->pub.decompress_data = decompress_smooth_data; - else - coef->pub.decompress_data = decompress_data; + if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) + coef->pub.decompress_data = decompress_smooth_data; + else + coef->pub.decompress_data = decompress_data; } #endif cinfo->output_iMCU_row = 0; } -/* - * Decompress and return some data in the single-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Input and output must run in lockstep since we have only a one-MCU buffer. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image, - * which we index according to the component's SOF position. - */ - METHODDEF(int) decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { @@ -195379,73 +179952,57 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) jpeg_component_info *compptr; inverse_DCT_method_ptr inverse_DCT; - /* Loop to process as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { - /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ - jzero_far((void FAR *) coef->MCU_buffer[0], + jzero_far((void FAR *) coef->MCU_buffer[0], (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); - if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return JPEG_SUSPENDED; - } - /* Determine where data should go in output_buf and do the IDCT thing. - * We skip dummy blocks at the right and bottom edges (but blkn gets - * incremented past them!). Note the inner loop relies on having - * allocated the MCU_buffer[] blocks sequentially. - */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + } + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; - /* Don't bother to IDCT an uninteresting component. */ if (! compptr->component_needed) { blkn += compptr->MCU_blocks; continue; } inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; + : compptr->last_col_width; output_ptr = output_buf[compptr->component_index] + yoffset * compptr->DCT_scaled_size; start_col = MCU_col_num * compptr->MCU_sample_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (cinfo->input_iMCU_row < last_iMCU_row || - yoffset+yindex < compptr->last_row_height) { - output_col = start_col; - for (xindex = 0; xindex < useful_width; xindex++) { - (*inverse_DCT) (cinfo, compptr, - (JCOEFPTR) coef->MCU_buffer[blkn+xindex], - output_ptr, output_col); - output_col += compptr->DCT_scaled_size; - } + yoffset+yindex < compptr->last_row_height) { + output_col = start_col; + for (xindex = 0; xindex < useful_width; xindex++) { + (*inverse_DCT) (cinfo, compptr, + (JCOEFPTR) coef->MCU_buffer[blkn+xindex], + output_ptr, output_col); + output_col += compptr->DCT_scaled_size; + } } blkn += compptr->MCU_width; output_ptr += compptr->DCT_scaled_size; } - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->MCU_ctr = 0; + } + } + coef->MCU_ctr = 0; } - /* Completed the iMCU row, advance counters for next one */ cinfo->output_iMCU_row++; if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row3(cinfo); - return JPEG_ROW_COMPLETED; + start_iMCU_row3(cinfo); + return JPEG_ROW_COMPLETED; } - /* Completed the scan */ (*cinfo->inputctl->finish_input_pass) (cinfo); return JPEG_SCAN_COMPLETED; } -/* - * Dummy consume-input routine for single-pass operation. - */ - METHODDEF(int) dummy_consume_data (j_decompress_ptr cinfo) { @@ -195454,13 +180011,6 @@ dummy_consume_data (j_decompress_ptr cinfo) #ifdef D_MULTISCAN_FILES_SUPPORTED -/* - * Consume input data and store it in the full-image coefficient buffer. - * We read as much as one fully interleaved MCU row ("iMCU" row) per call, - * ie, v_samp_factor block rows for each component in the scan. - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - */ - METHODDEF(int) consume_data (j_decompress_ptr cinfo) { @@ -195472,65 +180022,45 @@ consume_data (j_decompress_ptr cinfo) JBLOCKROW buffer_ptr; jpeg_component_info *compptr; - /* Align the virtual buffers for the components used in this scan. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - buffer[ci] = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], - cinfo->input_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, TRUE); - /* Note: entropy decoder expects buffer to be zeroed, - * but this is handled automatically by the memory manager - * because we requested a pre-zeroed array. - */ + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + cinfo->input_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); } - /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; - yoffset++) { - for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) { - /* Construct list of pointers to DCT blocks belonging to this MCU */ - blkn = 0; /* index of current DCT block within MCU */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { buffer_ptr = buffer[ci][yindex+yoffset] + start_col; for (xindex = 0; xindex < compptr->MCU_width; xindex++) { - coef->MCU_buffer[blkn++] = buffer_ptr++; + coef->MCU_buffer[blkn++] = buffer_ptr++; } } - } - /* Try to fetch the MCU. */ - if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ + } + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return JPEG_SUSPENDED; - } - } - /* Completed an MCU row, but perhaps not an iMCU row */ - coef->MCU_ctr = 0; + } + } + coef->MCU_ctr = 0; } - /* Completed the iMCU row, advance counters for next one */ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { - start_iMCU_row3(cinfo); - return JPEG_ROW_COMPLETED; + start_iMCU_row3(cinfo); + return JPEG_ROW_COMPLETED; } - /* Completed the scan */ (*cinfo->inputctl->finish_input_pass) (cinfo); return JPEG_SCAN_COMPLETED; } -/* - * Decompress and return some data in the multi-pass case. - * Always attempts to emit one fully interleaved MCU row ("iMCU" row). - * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. - * - * NB: output_buf contains a plane for each component in image. - */ - METHODDEF(int) decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { @@ -195545,51 +180075,44 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) jpeg_component_info *compptr; inverse_DCT_method_ptr inverse_DCT; - /* Force some input to be done if we are getting ahead of the input. */ while (cinfo->input_scan_number < cinfo->output_scan_number || (cinfo->input_scan_number == cinfo->output_scan_number && cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; } - /* OK, output from the virtual arrays. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) - continue; - /* Align the virtual buffer for this component. */ - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - cinfo->output_iMCU_row * compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row) - block_rows = compptr->v_samp_factor; - else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - } - inverse_DCT = cinfo->idct->inverse_DCT[ci]; - output_ptr = output_buf[ci]; - /* Loop over all DCT blocks to be processed. */ - for (block_row = 0; block_row < block_rows; block_row++) { - buffer_ptr = buffer[block_row]; - output_col = 0; - for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { + ci++, compptr++) { + if (! compptr->component_needed) + continue; + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + cinfo->output_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + if (cinfo->output_iMCU_row < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + output_col = 0; + for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, output_ptr, output_col); buffer_ptr++; output_col += compptr->DCT_scaled_size; - } - output_ptr += compptr->DCT_scaled_size; - } + } + output_ptr += compptr->DCT_scaled_size; + } } if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; + return JPEG_ROW_COMPLETED; return JPEG_SCAN_COMPLETED; } @@ -195597,29 +180120,12 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) #ifdef BLOCK_SMOOTHING_SUPPORTED -/* - * This code applies interblock smoothing as described by section K.8 - * of the JPEG standard: the first 5 AC coefficients are estimated from - * the DC values of a DCT block and its 8 neighboring blocks. - * We apply smoothing only for progressive JPEG decoding, and only if - * the coefficients it can estimate are not yet known to full precision. - */ - -/* Natural-order array positions of the first 5 zigzag-order coefficients */ #define Q01_POS 1 #define Q10_POS 8 #define Q20_POS 16 #define Q11_POS 9 #define Q02_POS 2 -/* - * Determine whether block smoothing is applicable and safe. - * We also latch the current states of the coef_bits[] entries for the - * AC coefficients; otherwise, if the input side of the decompressor - * advances into a new scan, we might think the coefficients are known - * more accurately than they really are. - */ - LOCAL(boolean) smoothing_ok (j_decompress_ptr cinfo) { @@ -195632,49 +180138,40 @@ smoothing_ok (j_decompress_ptr cinfo) int * coef_bits_latch; if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) - return FALSE; + return FALSE; - /* Allocate latch area if not already done */ if (coef->coef_bits_latch == NULL) - coef->coef_bits_latch = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + coef->coef_bits_latch = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * (SAVED_COEFS * SIZEOF(int))); coef_bits_latch = coef->coef_bits_latch; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* All components' quantization values must already be latched. */ - if ((qtable = compptr->quant_table) == NULL) - return FALSE; - /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ - if (qtable->quantval[0] == 0 || + ci++, compptr++) { + if ((qtable = compptr->quant_table) == NULL) + return FALSE; + if (qtable->quantval[0] == 0 || qtable->quantval[Q01_POS] == 0 || qtable->quantval[Q10_POS] == 0 || qtable->quantval[Q20_POS] == 0 || qtable->quantval[Q11_POS] == 0 || qtable->quantval[Q02_POS] == 0) - return FALSE; - /* DC values must be at least partly known for all components. */ - coef_bits = cinfo->coef_bits[ci]; - if (coef_bits[0] < 0) - return FALSE; - /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ - for (coefi = 1; coefi <= 5; coefi++) { - coef_bits_latch[coefi] = coef_bits[coefi]; - if (coef_bits[coefi] != 0) + return FALSE; + coef_bits = cinfo->coef_bits[ci]; + if (coef_bits[0] < 0) + return FALSE; + for (coefi = 1; coefi <= 5; coefi++) { + coef_bits_latch[coefi] = coef_bits[coefi]; + if (coef_bits[coefi] != 0) smoothing_useful = TRUE; - } - coef_bits_latch += SAVED_COEFS; + } + coef_bits_latch += SAVED_COEFS; } return smoothing_useful; } -/* - * Variant of decompress_data for use when doing block smoothing. - */ - METHODDEF(int) decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { @@ -195696,206 +180193,173 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; int Al, pred; - /* Force some input to be done if we are getting ahead of the input. */ while (cinfo->input_scan_number <= cinfo->output_scan_number && ! cinfo->inputctl->eoi_reached) { - if (cinfo->input_scan_number == cinfo->output_scan_number) { - /* If input is working on current scan, we ordinarily want it to - * have completed the current row. But if input scan is DC, - * we want it to keep one row ahead so that next block row's DC - * values are up to date. - */ - JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; - if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) + if (cinfo->input_scan_number == cinfo->output_scan_number) { + JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; + if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) break; - } - if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) - return JPEG_SUSPENDED; + } + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; } - /* OK, output from the virtual arrays. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) - continue; - /* Count non-dummy DCT block rows in this iMCU row. */ - if (cinfo->output_iMCU_row < last_iMCU_row) { - block_rows = compptr->v_samp_factor; - access_rows = block_rows * 2; /* this and next iMCU row */ - last_row = FALSE; - } else { - /* NB: can't use last_row_height here; it is input-side-dependent! */ - block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (block_rows == 0) block_rows = compptr->v_samp_factor; - access_rows = block_rows; /* this iMCU row only */ - last_row = TRUE; - } - /* Align the virtual buffer for this component. */ - if (cinfo->output_iMCU_row > 0) { - access_rows += compptr->v_samp_factor; /* prior iMCU row too */ - buffer = (*cinfo->mem->access_virt_barray) + ci++, compptr++) { + if (! compptr->component_needed) + continue; + if (cinfo->output_iMCU_row < last_iMCU_row) { + block_rows = compptr->v_samp_factor; + access_rows = block_rows * 2; /* this and next iMCU row */ + last_row = FALSE; + } else { + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + access_rows = block_rows; /* this iMCU row only */ + last_row = TRUE; + } + if (cinfo->output_iMCU_row > 0) { + access_rows += compptr->v_samp_factor; /* prior iMCU row too */ + buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, (JDIMENSION) access_rows, FALSE); - buffer += compptr->v_samp_factor; /* point to current iMCU row */ - first_row = FALSE; - } else { - buffer = (*cinfo->mem->access_virt_barray) + buffer += compptr->v_samp_factor; /* point to current iMCU row */ + first_row = FALSE; + } else { + buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); - first_row = TRUE; - } - /* Fetch component-dependent info */ - coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); - quanttbl = compptr->quant_table; - Q00 = quanttbl->quantval[0]; - Q01 = quanttbl->quantval[Q01_POS]; - Q10 = quanttbl->quantval[Q10_POS]; - Q20 = quanttbl->quantval[Q20_POS]; - Q11 = quanttbl->quantval[Q11_POS]; - Q02 = quanttbl->quantval[Q02_POS]; - inverse_DCT = cinfo->idct->inverse_DCT[ci]; - output_ptr = output_buf[ci]; - /* Loop over all DCT blocks to be processed. */ - for (block_row = 0; block_row < block_rows; block_row++) { - buffer_ptr = buffer[block_row]; - if (first_row && block_row == 0) + first_row = TRUE; + } + coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); + quanttbl = compptr->quant_table; + Q00 = quanttbl->quantval[0]; + Q01 = quanttbl->quantval[Q01_POS]; + Q10 = quanttbl->quantval[Q10_POS]; + Q20 = quanttbl->quantval[Q20_POS]; + Q11 = quanttbl->quantval[Q11_POS]; + Q02 = quanttbl->quantval[Q02_POS]; + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + if (first_row && block_row == 0) prev_block_row = buffer_ptr; - else + else prev_block_row = buffer[block_row-1]; - if (last_row && block_row == block_rows-1) + if (last_row && block_row == block_rows-1) next_block_row = buffer_ptr; - else + else next_block_row = buffer[block_row+1]; - /* We fetch the surrounding DC values using a sliding-register approach. - * Initialize all nine here so as to do the right thing on narrow pics. - */ - DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; - DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; - DC7 = DC8 = DC9 = (int) next_block_row[0][0]; - output_col = 0; - last_block_column = compptr->width_in_blocks - 1; - for (block_num = 0; block_num <= last_block_column; block_num++) { - /* Fetch current DCT block into workspace so we can modify it. */ + DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; + DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; + DC7 = DC8 = DC9 = (int) next_block_row[0][0]; + output_col = 0; + last_block_column = compptr->width_in_blocks - 1; + for (block_num = 0; block_num <= last_block_column; block_num++) { jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); - /* Update DC values */ if (block_num < last_block_column) { DC3 = (int) prev_block_row[1][0]; DC6 = (int) buffer_ptr[1][0]; DC9 = (int) next_block_row[1][0]; } - /* Compute coefficient estimates per K.8. - * An estimate is applied only if coefficient is still zero, - * and is not known to be fully accurate. - */ - /* AC01 */ if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { num = 36 * Q00 * (DC4 - DC6); if (num >= 0) { - pred = (int) (((Q01<<7) + num) / (Q01<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1< 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q10<<7) + num) / (Q10<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1< 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q20<<7) + num) / (Q20<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1< 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q11<<7) + num) / (Q11<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1< 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q02<<7) + num) / (Q02<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1< 0 && pred >= (1< 0 && pred >= (1<DCT_scaled_size; - } - output_ptr += compptr->DCT_scaled_size; - } + } + output_ptr += compptr->DCT_scaled_size; + } } if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) - return JPEG_ROW_COMPLETED; + return JPEG_ROW_COMPLETED; return JPEG_SCAN_COMPLETED; } #endif /* BLOCK_SMOOTHING_SUPPORTED */ -/* - * Initialize coefficient buffer controller. - */ - GLOBAL(void) jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr3 coef; coef = (my_coef_ptr3) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller3)); cinfo->coef = (struct jpeg_d_coef_controller *) coef; coef->pub.start_input_pass = start_input_pass; @@ -195904,66 +180368,57 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) coef->coef_bits_latch = NULL; #endif - /* Create the coefficient buffer. */ if (need_full_buffer) { #ifdef D_MULTISCAN_FILES_SUPPORTED - /* Allocate a full-image virtual array for each component, */ - /* padded to a multiple of samp_factor DCT blocks in each direction. */ - /* Note we ask for a pre-zeroed array. */ - int ci, access_rows; - jpeg_component_info *compptr; + int ci, access_rows; + jpeg_component_info *compptr; - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - access_rows = compptr->v_samp_factor; + access_rows = compptr->v_samp_factor; #ifdef BLOCK_SMOOTHING_SUPPORTED - /* If block smoothing could be used, need a bigger window */ - if (cinfo->progressive_mode) + if (cinfo->progressive_mode) access_rows *= 3; #endif - coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) access_rows); - } - coef->pub.consume_data = consume_data; - coef->pub.decompress_data = decompress_data; - coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ + } + coef->pub.consume_data = consume_data; + coef->pub.decompress_data = decompress_data; + coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { - /* We only need a single-MCU buffer. */ - JBLOCKROW buffer; - int i; + JBLOCKROW buffer; + int i; - buffer = (JBLOCKROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); - for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { - coef->MCU_buffer[i] = buffer + i; - } - coef->pub.consume_data = dummy_consume_data; - coef->pub.decompress_data = decompress_onepass; - coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ + for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->pub.consume_data = dummy_consume_data; + coef->pub.decompress_data = decompress_onepass; + coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ } } /********* End of inlined file: jdcoefct.c *********/ - #undef FIX + #undef FIX /********* Start of inlined file: jdcolor.c *********/ #define JPEG_INTERNALS -/* Private subobject */ - typedef struct { struct jpeg_color_deconverter pub; /* public fields */ - /* Private state for YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ @@ -195972,43 +180427,10 @@ typedef struct { typedef my_color_deconverter2 * my_cconvert_ptr2; -/**************** YCbCr -> RGB conversion: most common case **************/ - -/* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * R = Y + 1.40200 * Cr - * G = Y - 0.34414 * Cb - 0.71414 * Cr - * B = Y + 1.77200 * Cb - * where Cb and Cr represent the incoming values less CENTERJSAMPLE. - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) - * - * To avoid floating-point arithmetic, we represent the fractional constants - * as integers scaled up by 2^16 (about 4 digits precision); we have to divide - * the products by 2^16, with appropriate rounding, to get the correct answer. - * Notice that Y, being an integral input, does not contribute any fraction - * so it need not participate in the rounding. - * - * For even more speed, we avoid doing any multiplications in the inner loop - * by precalculating the constants times Cb and Cr for all possible values. - * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. - * The Cr=>R and Cb=>B values can be rounded to integers in advance; the - * values for the G calculation are left scaled up, since we must add them - * together before rounding. - */ - #define SCALEBITS 16 /* speediest right-shift on some machines */ #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. - */ - LOCAL(void) build_ycc_rgb_table (j_decompress_ptr cinfo) { @@ -196018,46 +180440,28 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) SHIFT_TEMPS cconvert->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); cconvert->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ - cconvert->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ - cconvert->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; + cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; } } -/* - * Convert some rows of samples to the output colorspace. - * - * Note that we change from noninterleaved, one-plane-per-component format - * to interleaved-pixel format. The output buffer is therefore three times - * as wide as the input buffer. - * A starting row offset is provided only for the input buffer. The caller - * can easily adjust the passed output_buf value to accommodate any row - * offset required on that side. - */ - METHODDEF(void) ycc_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, @@ -196069,7 +180473,6 @@ ycc_rgb_convert (j_decompress_ptr cinfo, register JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = cconvert->Cr_r_tab; register int * Cbbtab = cconvert->Cb_b_tab; @@ -196078,37 +180481,29 @@ ycc_rgb_convert (j_decompress_ptr cinfo, SHIFT_TEMPS while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; - outptr[RGB_GREEN] = range_limit[y + - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + outptr[RGB_GREEN] = range_limit[y + + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))]; - outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; - outptr += RGB_PIXELSIZE; - } + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr += RGB_PIXELSIZE; + } } } -/**************** Cases other than YCbCr -> RGB **************/ - -/* - * Color conversion for no colorspace change: just copy the data, - * converting from separate-planes to interleaved representation. - */ - METHODDEF(void) null_convert2 (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) { register JSAMPROW inptr, outptr; register JDIMENSION count; @@ -196117,40 +180512,28 @@ null_convert2 (j_decompress_ptr cinfo, int ci; while (--num_rows >= 0) { - for (ci = 0; ci < num_components; ci++) { - inptr = input_buf[ci][input_row]; - outptr = output_buf[0] + ci; - for (count = num_cols; count > 0; count--) { + for (ci = 0; ci < num_components; ci++) { + inptr = input_buf[ci][input_row]; + outptr = output_buf[0] + ci; + for (count = num_cols; count > 0; count--) { *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ outptr += num_components; - } - } - input_row++; - output_buf++; + } + } + input_row++; + output_buf++; } } -/* - * Color conversion for grayscale: just copy the data. - * This also works for YCbCr -> grayscale conversion, in which - * we just copy the Y (luminance) component and ignore chrominance. - */ - METHODDEF(void) grayscale_convert2 (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, - num_rows, cinfo->output_width); + num_rows, cinfo->output_width); } -/* - * Convert grayscale to RGB: just duplicate the graylevel three times. - * This is provided to support applications that don't want to cope - * with grayscale as a separate case. - */ - METHODDEF(void) gray_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, @@ -196161,23 +180544,15 @@ gray_rgb_convert (j_decompress_ptr cinfo, JDIMENSION num_cols = cinfo->output_width; while (--num_rows >= 0) { - inptr = input_buf[0][input_row++]; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - /* We can dispense with GETJSAMPLE() here */ - outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; - outptr += RGB_PIXELSIZE; - } + inptr = input_buf[0][input_row++]; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; + outptr += RGB_PIXELSIZE; + } } } -/* - * Adobe-style YCCK->CMYK conversion. - * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same - * conversion as above, while passing K (black) unchanged. - * We assume build_ycc_rgb_table has been called. - */ - METHODDEF(void) ycck_cmyk_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, @@ -196189,7 +180564,6 @@ ycck_cmyk_convert (j_decompress_ptr cinfo, register JSAMPROW inptr0, inptr1, inptr2, inptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; - /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = cconvert->Cr_r_tab; register int * Cbbtab = cconvert->Cb_b_tab; @@ -196198,43 +180572,32 @@ ycck_cmyk_convert (j_decompress_ptr cinfo, SHIFT_TEMPS while (--num_rows >= 0) { - inptr0 = input_buf[0][input_row]; - inptr1 = input_buf[1][input_row]; - inptr2 = input_buf[2][input_row]; - inptr3 = input_buf[3][input_row]; - input_row++; - outptr = *output_buf++; - for (col = 0; col < num_cols; col++) { - y = GETJSAMPLE(inptr0[col]); - cb = GETJSAMPLE(inptr1[col]); - cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ - outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS)))]; - outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ - /* K passes through unchanged */ - outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ - outptr += 4; - } + outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ + outptr += 4; + } } } -/* - * Empty method for start_pass. - */ - METHODDEF(void) start_pass_dcolor (j_decompress_ptr cinfo) { - /* no work needed */ } -/* - * Module initialization routine for output colorspace conversion. - */ - GLOBAL(void) jinit_color_deconverter (j_decompress_ptr cinfo) { @@ -196242,133 +180605,100 @@ jinit_color_deconverter (j_decompress_ptr cinfo) int ci; cconvert = (my_cconvert_ptr2) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_deconverter2)); cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; cconvert->pub.start_pass = start_pass_dcolor; - /* Make sure num_components agrees with jpeg_color_space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: - if (cinfo->num_components != 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; case JCS_RGB: case JCS_YCbCr: - if (cinfo->num_components != 3) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; case JCS_CMYK: case JCS_YCCK: - if (cinfo->num_components != 4) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; default: /* JCS_UNKNOWN can be anything */ - if (cinfo->num_components < 1) - ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - break; + if (cinfo->num_components < 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; } - /* Set out_color_components and conversion method based on requested space. - * Also clear the component_needed flags for any unused components, - * so that earlier pipeline stages can avoid useless computation. - */ - switch (cinfo->out_color_space) { case JCS_GRAYSCALE: - cinfo->out_color_components = 1; - if (cinfo->jpeg_color_space == JCS_GRAYSCALE || + cinfo->out_color_components = 1; + if (cinfo->jpeg_color_space == JCS_GRAYSCALE || cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = grayscale_convert2; - /* For color->grayscale conversion, only the Y (0) component is needed */ - for (ci = 1; ci < cinfo->num_components; ci++) + cconvert->pub.color_convert = grayscale_convert2; + for (ci = 1; ci < cinfo->num_components; ci++) cinfo->comp_info[ci].component_needed = FALSE; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; case JCS_RGB: - cinfo->out_color_components = RGB_PIXELSIZE; - if (cinfo->jpeg_color_space == JCS_YCbCr) { - cconvert->pub.color_convert = ycc_rgb_convert; - build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb_convert; - } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { - cconvert->pub.color_convert = null_convert2; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = ycc_rgb_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { + cconvert->pub.color_convert = gray_rgb_convert; + } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { + cconvert->pub.color_convert = null_convert2; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; case JCS_CMYK: - cinfo->out_color_components = 4; - if (cinfo->jpeg_color_space == JCS_YCCK) { - cconvert->pub.color_convert = ycck_cmyk_convert; - build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_CMYK) { - cconvert->pub.color_convert = null_convert2; - } else - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + cinfo->out_color_components = 4; + if (cinfo->jpeg_color_space == JCS_YCCK) { + cconvert->pub.color_convert = ycck_cmyk_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + cconvert->pub.color_convert = null_convert2; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; default: - /* Permit null conversion to same output space */ - if (cinfo->out_color_space == cinfo->jpeg_color_space) { - cinfo->out_color_components = cinfo->num_components; - cconvert->pub.color_convert = null_convert2; - } else /* unsupported non-null conversion */ - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + if (cinfo->out_color_space == cinfo->jpeg_color_space) { + cinfo->out_color_components = cinfo->num_components; + cconvert->pub.color_convert = null_convert2; + } else /* unsupported non-null conversion */ + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; } if (cinfo->quantize_colors) - cinfo->output_components = 1; /* single colormapped output component */ + cinfo->output_components = 1; /* single colormapped output component */ else - cinfo->output_components = cinfo->out_color_components; + cinfo->output_components = cinfo->out_color_components; } /********* End of inlined file: jdcolor.c *********/ - #undef FIX + #undef FIX /********* Start of inlined file: jddctmgr.c *********/ #define JPEG_INTERNALS -/* - * The decompressor input side (jdinput.c) saves away the appropriate - * quantization table for each component at the start of the first scan - * involving that component. (This is necessary in order to correctly - * decode files that reuse Q-table slots.) - * When we are ready to make an output pass, the saved Q-table is converted - * to a multiplier table that will actually be used by the IDCT routine. - * The multiplier table contents are IDCT-method-dependent. To support - * application changes in IDCT method between scans, we can remake the - * multiplier tables if necessary. - * In buffered-image mode, the first output pass may occur before any data - * has been seen for some components, and thus before their Q-tables have - * been saved away. To handle this case, multiplier tables are preset - * to zeroes; the result of the IDCT will be a neutral gray level. - */ - -/* Private subobject for this module */ - typedef struct { struct jpeg_inverse_dct pub; /* public fields */ - /* This array contains the IDCT method code that each multiplier table - * is currently set up for, or -1 if it's not yet set up. - * The actual multiplier tables are pointed to by dct_table in the - * per-component comp_info structures. - */ int cur_method[MAX_COMPONENTS]; } my_idct_controller; typedef my_idct_controller * my_idct_ptr; -/* Allocated multiplier tables: big enough for any supported variant */ - typedef union { ISLOW_MULT_TYPE islow_array[DCTSIZE2]; #ifdef DCT_IFAST_SUPPORTED @@ -196379,9 +180709,6 @@ typedef union { #endif } multiplier_table; -/* The current scaled-IDCT routines require ISLOW-style multiplier tables, - * so be sure to compile that code if either ISLOW or SCALING is requested. - */ #ifdef DCT_ISLOW_SUPPORTED #define PROVIDE_ISLOW_TABLES #else @@ -196390,12 +180717,6 @@ typedef union { #endif #endif -/* - * Prepare for an output pass. - * Here we select the proper IDCT routine for each component and build - * a matching multiplier table. - */ - METHODDEF(void) start_pass (j_decompress_ptr cinfo) { @@ -196407,94 +180728,75 @@ start_pass (j_decompress_ptr cinfo) JQUANT_TBL * qtbl; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Select the proper IDCT routine for this component's scaling */ - switch (compptr->DCT_scaled_size) { + ci++, compptr++) { + switch (compptr->DCT_scaled_size) { #ifdef IDCT_SCALING_SUPPORTED - case 1: - method_ptr = jpeg_idct_1x1; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; - case 2: - method_ptr = jpeg_idct_2x2; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; - case 4: - method_ptr = jpeg_idct_4x4; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ - break; + case 1: + method_ptr = jpeg_idct_1x1; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 2: + method_ptr = jpeg_idct_2x2; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 4: + method_ptr = jpeg_idct_4x4; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; #endif - case DCTSIZE: - switch (cinfo->dct_method) { + case DCTSIZE: + switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: + case JDCT_ISLOW: method_ptr = jpeg_idct_islow; method = JDCT_ISLOW; break; #endif #ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: + case JDCT_IFAST: method_ptr = jpeg_idct_ifast; method = JDCT_IFAST; break; #endif #ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: + case JDCT_FLOAT: method_ptr = jpeg_idct_float; method = JDCT_FLOAT; break; #endif - default: + default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; - } - break; - default: - ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); - break; - } - idct->pub.inverse_DCT[ci] = method_ptr; - /* Create multiplier table from quant table. - * However, we can skip this if the component is uninteresting - * or if we already built the table. Also, if no quant table - * has yet been saved for the component, we leave the - * multiplier table all-zero; we'll be reading zeroes from the - * coefficient controller's buffer anyway. - */ - if (! compptr->component_needed || idct->cur_method[ci] == method) - continue; - qtbl = compptr->quant_table; - if (qtbl == NULL) /* happens if no data yet for component */ - continue; - idct->cur_method[ci] = method; - switch (method) { + } + break; + default: + ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); + break; + } + idct->pub.inverse_DCT[ci] = method_ptr; + if (! compptr->component_needed || idct->cur_method[ci] == method) + continue; + qtbl = compptr->quant_table; + if (qtbl == NULL) /* happens if no data yet for component */ + continue; + idct->cur_method[ci] = method; + switch (method) { #ifdef PROVIDE_ISLOW_TABLES - case JDCT_ISLOW: - { - /* For LL&M IDCT method, multipliers are equal to raw quantization - * coefficients, but are stored as ints to ensure access efficiency. - */ + case JDCT_ISLOW: + { ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; for (i = 0; i < DCTSIZE2; i++) { ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; } - } - break; + } + break; #endif #ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - { - /* For AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * For integer operation, the multiplier table is to be scaled by - * IFAST_SCALE_BITS. - */ + case JDCT_IFAST: + { IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; #define CONST_BITS 14 static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, @@ -196508,21 +180810,16 @@ start_pass (j_decompress_ptr cinfo) for (i = 0; i < DCTSIZE2; i++) { ifmtbl[i] = (IFAST_MULT_TYPE) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], (INT32) aanscales[i]), - CONST_BITS-IFAST_SCALE_BITS); + CONST_BITS-IFAST_SCALE_BITS); } - } - break; + } + break; #endif #ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - { - /* For float AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - */ + case JDCT_FLOAT: + { FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; int row, col; static const double aanscalefactor[DCTSIZE] = { @@ -196533,26 +180830,22 @@ start_pass (j_decompress_ptr cinfo) i = 0; for (row = 0; row < DCTSIZE; row++) { for (col = 0; col < DCTSIZE; col++) { - fmtbl[i] = (FLOAT_MULT_TYPE) - ((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col]); - i++; + fmtbl[i] = (FLOAT_MULT_TYPE) + ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col]); + i++; } } - } - break; + } + break; #endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } } } -/* - * Initialize IDCT manager. - */ - GLOBAL(void) jinit_inverse_dct (j_decompress_ptr cinfo) { @@ -196561,32 +180854,29 @@ jinit_inverse_dct (j_decompress_ptr cinfo) jpeg_component_info *compptr; idct = (my_idct_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_idct_controller)); cinfo->idct = (struct jpeg_inverse_dct *) idct; idct->pub.start_pass = start_pass; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Allocate and pre-zero a multiplier table for each component */ - compptr->dct_table = - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + ci++, compptr++) { + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(multiplier_table)); - MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); - /* Mark multiplier table not yet set up for any method */ - idct->cur_method[ci] = -1; + MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); + idct->cur_method[ci] = -1; } } /********* End of inlined file: jddctmgr.c *********/ - #undef CONST_BITS - #undef ASSIGN_STATE + #undef CONST_BITS + #undef ASSIGN_STATE /********* Start of inlined file: jdhuff.c *********/ #define JPEG_INTERNALS /********* Start of inlined file: jdhuff.h *********/ -/* Short forms of external names for systems with brain-damaged linkers. */ #ifndef __jdhuff_h__ #define __jdhuff_h__ @@ -196597,85 +180887,38 @@ jinit_inverse_dct (j_decompress_ptr cinfo) #define jpeg_huff_decode jHufDecode #endif /* NEED_SHORT_EXTERNAL_NAMES */ -/* Derived data constructed for each Huffman table */ - #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ typedef struct { - /* Basic tables: (element [0] of each array is unused) */ INT32 maxcode[18]; /* largest code of length k (-1 if none) */ - /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ INT32 valoffset[17]; /* huffval[] offset for codes of length k */ - /* valoffset[k] = huffval[] index of 1st symbol of code length k, less - * the smallest code of length k; so given a code of length k, the - * corresponding symbol is huffval[code + valoffset[k]] - */ - /* Link to public Huffman table (needed only in jpeg_huff_decode) */ JHUFF_TBL *pub; - /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of - * the input data stream. If the next Huffman code is no more - * than HUFF_LOOKAHEAD bits long, we can obtain its length and - * the corresponding symbol directly from these tables. - */ int look_nbits[1< 32 bits on your machine, and shifting/masking longs is - * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE - * appropriately should be a win. Unfortunately we can't define the size - * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) - * because not all machines measure sizeof in 8-bit bytes. - */ - typedef struct { /* Bitreading state saved across MCUs */ bit_buf_type get_buffer; /* current bit-extraction buffer */ int bits_left; /* # of unused bits in it */ } bitread_perm_state; typedef struct { /* Bitreading working state within an MCU */ - /* Current data source location */ - /* We need a copy, rather than munging the original, in case of suspension */ const JOCTET * next_input_byte; /* => next byte to read from source */ size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ - /* Bit input buffer --- note these values are kept in register variables, - * not in this struct, inside the inner loops. - */ bit_buf_type get_buffer; /* current bit-extraction buffer */ int bits_left; /* # of unused bits in it */ - /* Pointer needed by jpeg_fill_bit_buffer. */ j_decompress_ptr cinfo; /* back link to decompress master record */ } bitread_working_state; -/* Macros to declare and load/save bitread local variables. */ #define BITREAD_STATE_VARS \ register bit_buf_type get_buffer; \ register int bits_left; \ @@ -196694,29 +180937,11 @@ typedef struct { /* Bitreading working state within an MCU */ permstate.get_buffer = get_buffer; \ permstate.bits_left = bits_left -/* - * These macros provide the in-line portion of bit fetching. - * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer - * before using GET_BITS, PEEK_BITS, or DROP_BITS. - * The variables get_buffer and bits_left are assumed to be locals, - * but the state struct might not be (jpeg_huff_decode needs this). - * CHECK_BIT_BUFFER(state,n,action); - * Ensure there are N bits in get_buffer; if suspend, take action. - * val = GET_BITS(n); - * Fetch next N bits. - * val = PEEK_BITS(n); - * Fetch next N bits without removing them from the buffer. - * DROP_BITS(n); - * Discard next N bits. - * The value N should be a simple variable, not an expression, because it - * is evaluated multiple times. - */ - #define CHECK_BIT_BUFFER(state,nbits,action) \ { if (bits_left < (nbits)) { \ - if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ - { action; } \ - get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } #define GET_BITS(nbits) \ (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) @@ -196727,76 +180952,43 @@ typedef struct { /* Bitreading working state within an MCU */ #define DROP_BITS(nbits) \ (bits_left -= (nbits)) -/* Load up the bit buffer to a depth of at least nbits */ EXTERN(boolean) jpeg_fill_bit_buffer JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, int nbits)); - -/* - * Code for extracting next Huffman-coded symbol from input bit stream. - * Again, this is time-critical and we make the main paths be macros. - * - * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits - * without looping. Usually, more than 95% of the Huffman codes will be 8 - * or fewer bits long. The few overlength codes are handled with a loop, - * which need not be inline code. - * - * Notes about the HUFF_DECODE macro: - * 1. Near the end of the data segment, we may fail to get enough bits - * for a lookahead. In that case, we do it the hard way. - * 2. If the lookahead table contains no entry, the next code must be - * more than HUFF_LOOKAHEAD bits long. - * 3. jpeg_huff_decode returns -1 if forced to suspend. - */ + register int bits_left, int nbits)); #define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ { register int nb, look; \ if (bits_left < HUFF_LOOKAHEAD) { \ - if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - nb = 1; goto slowlabel; \ - } \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ } \ look = PEEK_BITS(HUFF_LOOKAHEAD); \ if ((nb = htbl->look_nbits[look]) != 0) { \ - DROP_BITS(nb); \ - result = htbl->look_sym[look]; \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ } else { \ - nb = HUFF_LOOKAHEAD+1; \ + nb = HUFF_LOOKAHEAD+1; \ slowlabel: \ - if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ { failaction; } \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ } \ } -/* Out-of-line case for Huffman code fetching */ EXTERN(int) jpeg_huff_decode JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, d_derived_tbl * htbl, int min_bits)); + register int bits_left, d_derived_tbl * htbl, int min_bits)); #endif /********* End of inlined file: jdhuff.h *********/ - /* Declarations shared with jdphuff.c */ - -/* - * Expanded entropy decoder object for Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - typedef struct { int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state2; -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - #ifndef NO_STRUCT_ASSIGN #define ASSIGN_STATE(dest,src) ((dest) = (src)) #else @@ -196812,35 +181004,22 @@ typedef struct { typedef struct { struct jpeg_entropy_decoder pub; /* public fields */ - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ bitread_perm_state bitstate; /* Bit buffer at start of MCU */ savable_state2 saved; /* Other state at start of MCU */ - /* These fields are NOT loaded into local working state. */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ - /* Pointers to derived tables (these workspaces have image lifespan) */ d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; - /* Precalculated info set up by start_pass for use in decode_mcu: */ - - /* Pointers to derived tables to be used for each block within an MCU */ d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; - /* Whether we care about the DC and AC coefficient values for each block */ boolean dc_needed[D_MAX_BLOCKS_IN_MCU]; boolean ac_needed[D_MAX_BLOCKS_IN_MCU]; } huff_entropy_decoder2; typedef huff_entropy_decoder2 * huff_entropy_ptr2; -/* - * Initialize for a Huffman-compressed scan. - */ - METHODDEF(void) start_pass_huff_decoder (j_decompress_ptr cinfo) { @@ -196848,61 +181027,41 @@ start_pass_huff_decoder (j_decompress_ptr cinfo) int ci, blkn, dctbl, actbl; jpeg_component_info * compptr; - /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. - * This ought to be an error condition, but we make it a warning because - * there are some baseline files out there with all zeroes in these bytes. - */ if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || - cinfo->Ah != 0 || cinfo->Al != 0) - WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + cinfo->Ah != 0 || cinfo->Al != 0) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, - & entropy->ac_derived_tbls[actbl]); - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + entropy->saved.last_dc_val[ci] = 0; } - /* Precalculate decoding info for each block in an MCU of this scan */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - /* Precalculate which table to use for each block */ - entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; - entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; - /* Decide whether we really care about the coefficient values */ - if (compptr->component_needed) { - entropy->dc_needed[blkn] = TRUE; - /* we don't need the ACs if producing a 1/8th-size image */ - entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); - } else { - entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; - } + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + if (compptr->component_needed) { + entropy->dc_needed[blkn] = TRUE; + entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); + } else { + entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; + } } - /* Initialize bitread state variables */ entropy->bitstate.bits_left = 0; entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ entropy->pub.insufficient_data = FALSE; - /* Initialize restart counter */ entropy->restarts_to_go = cinfo->restart_interval; } -/* - * Compute the derived values for a Huffman table. - * This routine also performs some validation checks on the table. - * - * Note this is also used by jdphuff.c. - */ - GLOBAL(void) jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, d_derived_tbl ** pdtbl) @@ -196915,129 +181074,80 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, unsigned int huffcode[257]; unsigned int code; - /* Note that huffsize[] and huffcode[] are filled in code-length order, - * paralleling the order of the symbols themselves in htbl->huffval[]. - */ - - /* Find the input Huffman table */ if (tblno < 0 || tblno >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); htbl = - isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; if (htbl == NULL) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); - /* Allocate a workspace if we haven't already done so. */ if (*pdtbl == NULL) - *pdtbl = (d_derived_tbl *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + *pdtbl = (d_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(d_derived_tbl)); dtbl = *pdtbl; dtbl->pub = htbl; /* fill in back link */ - /* Figure C.1: make table of Huffman code length for each symbol */ - p = 0; for (l = 1; l <= 16; l++) { - i = (int) htbl->bits[l]; - if (i < 0 || p + i > 256) /* protect against table overrun */ - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - while (i--) - huffsize[p++] = (char) l; + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; } huffsize[p] = 0; numsymbols = p; - /* Figure C.2: generate the codes themselves */ - /* We also validate that the counts represent a legal Huffman code tree. */ - code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { - while (((int) huffsize[p]) == si) { - huffcode[p++] = code; - code++; - } - /* code is now 1 more than the last code used for codelength si; but - * it must still fit in si bits, since no code is allowed to be all ones. - */ - if (((INT32) code) >= (((INT32) 1) << si)) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - code <<= 1; - si++; + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; } - /* Figure F.15: generate decoding tables for bit-sequential decoding */ - p = 0; for (l = 1; l <= 16; l++) { - if (htbl->bits[l]) { - /* valoffset[l] = huffval[] index of 1st symbol of code length l, - * minus the minimum code of length l - */ - dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; - p += htbl->bits[l]; - dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ - } else { - dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ - } + if (htbl->bits[l]) { + dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; + p += htbl->bits[l]; + dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ + } else { + dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ + } } dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ - /* Compute lookahead tables to speed up decoding. - * First we set all the table entries to 0, indicating "too long"; - * then we iterate through the Huffman codes that are short enough and - * fill in all the entries that correspond to bit sequences starting - * with that code. - */ - MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); p = 0; for (l = 1; l <= HUFF_LOOKAHEAD; l++) { - for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { - /* l = current code's length, p = its index in huffcode[] & huffval[]. */ - /* Generate left-justified code followed by all possible bit sequences */ - lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); - for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { + for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { + lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); + for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { dtbl->look_nbits[lookbits] = l; dtbl->look_sym[lookbits] = htbl->huffval[p]; lookbits++; - } - } + } + } } - /* Validate symbols as being reasonable. - * For AC tables, we make no check, but accept all byte values 0..255. - * For DC tables, we require the symbols to be in range 0..15. - * (Tighter bounds could be applied depending on the data depth and mode, - * but this is sufficient to ensure safe decoding.) - */ if (isDC) { - for (i = 0; i < numsymbols; i++) { - int sym = htbl->huffval[i]; - if (sym < 0 || sym > 15) + for (i = 0; i < numsymbols; i++) { + int sym = htbl->huffval[i]; + if (sym < 0 || sym > 15) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - } + } } } -/* - * Out-of-line code for bit fetching (shared with jdphuff.c). - * See jdhuff.h for info about usage. - * Note: current values of get_buffer and bits_left are passed as parameters, - * but are returned in the corresponding fields of the state struct. - * - * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width - * of get_buffer to be used. (On machines with wider words, an even larger - * buffer could be used.) However, on some machines 32-bit shifts are - * quite slow and take time proportional to the number of places shifted. - * (This is true with most PC compilers, for instance.) In this case it may - * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the - * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. - */ - #ifdef SLOW_SHIFT_32 #define MIN_GET_BITS 15 /* minimum allowable value */ #else @@ -197046,96 +181156,61 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, GLOBAL(boolean) jpeg_fill_bit_buffer (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - int nbits) -/* Load up the bit buffer to a depth of at least nbits */ + register bit_buf_type get_buffer, register int bits_left, + int nbits) { - /* Copy heavily used state fields into locals (hopefully registers) */ register const JOCTET * next_input_byte = state->next_input_byte; register size_t bytes_in_buffer = state->bytes_in_buffer; j_decompress_ptr cinfo = state->cinfo; - /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ - /* (It is assumed that no request will be for more than that many bits.) */ - /* We fail to do so only if we hit a marker or are forced to suspend. */ - if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ - while (bits_left < MIN_GET_BITS) { - register int c; + while (bits_left < MIN_GET_BITS) { + register int c; - /* Attempt to read a byte */ - if (bytes_in_buffer == 0) { + if (bytes_in_buffer == 0) { if (! (*cinfo->src->fill_input_buffer) (cinfo)) return FALSE; next_input_byte = cinfo->src->next_input_byte; bytes_in_buffer = cinfo->src->bytes_in_buffer; - } - bytes_in_buffer--; - c = GETJOCTET(*next_input_byte++); + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); - /* If it's 0xFF, check and discard stuffed zero byte */ - if (c == 0xFF) { - /* Loop here to discard any padding FF's on terminating marker, - * so that we can save a valid unread_marker value. NOTE: we will - * accept multiple FF's followed by a 0 as meaning a single FF data - * byte. This data pattern is not valid according to the standard. - */ + if (c == 0xFF) { do { if (bytes_in_buffer == 0) { - if (! (*cinfo->src->fill_input_buffer) (cinfo)) - return FALSE; - next_input_byte = cinfo->src->next_input_byte; - bytes_in_buffer = cinfo->src->bytes_in_buffer; + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; } bytes_in_buffer--; c = GETJOCTET(*next_input_byte++); } while (c == 0xFF); if (c == 0) { - /* Found FF/00, which represents an FF data byte */ c = 0xFF; } else { - /* Oops, it's actually a marker indicating end of compressed data. - * Save the marker code for later use. - * Fine point: it might appear that we should save the marker into - * bitread working state, not straight into permanent state. But - * once we have hit a marker, we cannot need to suspend within the - * current MCU, because we will read no more bytes from the data - * source. So it is OK to update permanent state right away. - */ cinfo->unread_marker = c; - /* See if we need to insert some fake zero bits. */ goto no_more_bytes; } - } + } - /* OK, load c into get_buffer */ - get_buffer = (get_buffer << 8) | c; - bits_left += 8; - } /* end while */ + get_buffer = (get_buffer << 8) | c; + bits_left += 8; + } /* end while */ } else { no_more_bytes: - /* We get here if we've read the marker that terminates the compressed - * data segment. There should be enough bits in the buffer register - * to satisfy the request; if so, no problem. - */ - if (nbits > bits_left) { - /* Uh-oh. Report corrupted data to user and stuff zeroes into - * the data stream, so that we can produce some kind of image. - * We use a nonvolatile flag to ensure that only one warning message - * appears per data segment. - */ - if (! cinfo->entropy->insufficient_data) { + if (nbits > bits_left) { + if (! cinfo->entropy->insufficient_data) { WARNMS(cinfo, JWRN_HIT_MARKER); cinfo->entropy->insufficient_data = TRUE; - } - /* Fill the buffer with zero bits */ - get_buffer <<= MIN_GET_BITS - bits_left; - bits_left = MIN_GET_BITS; - } + } + get_buffer <<= MIN_GET_BITS - bits_left; + bits_left = MIN_GET_BITS; + } } - /* Unload the local registers */ state->next_input_byte = next_input_byte; state->bytes_in_buffer = bytes_in_buffer; state->get_buffer = get_buffer; @@ -197144,11 +181219,6 @@ jpeg_fill_bit_buffer (bitread_working_state * state, return TRUE; } -/* - * Out-of-line code for Huffman code decoding. - * See jdhuff.h for info about usage. - */ - GLOBAL(int) jpeg_huff_decode (bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, @@ -197157,89 +181227,50 @@ jpeg_huff_decode (bitread_working_state * state, register int l = min_bits; register INT32 code; - /* HUFF_DECODE has determined that the code is at least min_bits */ - /* bits long, so fetch that many bits in one swoop. */ - CHECK_BIT_BUFFER(*state, l, return -1); code = GET_BITS(l); - /* Collect the rest of the Huffman code one bit at a time. */ - /* This is per Figure F.16 in the JPEG spec. */ - while (code > htbl->maxcode[l]) { - code <<= 1; - CHECK_BIT_BUFFER(*state, 1, return -1); - code |= GET_BITS(1); - l++; + code <<= 1; + CHECK_BIT_BUFFER(*state, 1, return -1); + code |= GET_BITS(1); + l++; } - /* Unload the local registers */ state->get_buffer = get_buffer; state->bits_left = bits_left; - /* With garbage input we may reach the sentinel value l = 17. */ - if (l > 16) { - WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); - return 0; /* fake a zero as the safest result */ + WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); + return 0; /* fake a zero as the safest result */ } return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; } -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - LOCAL(boolean) process_restart (j_decompress_ptr cinfo) { huff_entropy_ptr2 entropy = (huff_entropy_ptr2) cinfo->entropy; int ci; - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; entropy->bitstate.bits_left = 0; - /* Advance past the RSTn marker */ if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; + return FALSE; - /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; + entropy->saved.last_dc_val[ci] = 0; - /* Reset restart counter */ entropy->restarts_to_go = cinfo->restart_interval; - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ if (cinfo->unread_marker == 0) - entropy->pub.insufficient_data = FALSE; + entropy->pub.insufficient_data = FALSE; return TRUE; } -/* - * Decode and return one MCU's worth of Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. - * (Wholesale zeroing is usually a little faster than retail...) - * - * Returns FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * this module, since we'll just re-assign them on the next call.) - */ - METHODDEF(boolean) decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -197248,53 +181279,39 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) BITREAD_STATE_VARS; savable_state2 state; - /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) return FALSE; } - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ if (! entropy->pub.insufficient_data) { - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); - /* Outer loop handles each block in the MCU */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; + d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + register int s, k, r; - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - JBLOCKROW block = MCU_data[blkn]; - d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; - d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; - register int s, k, r; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); - if (s) { + HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); + if (s) { CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); - } + } - if (entropy->dc_needed[blkn]) { - /* Convert DC difference to actual value, update last_dc_val */ + if (entropy->dc_needed[blkn]) { int ci = cinfo->MCU_membership[blkn]; s += state.last_dc_val[ci]; state.last_dc_val[ci] = s; - /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ (*block)[0] = (JCOEF) s; - } + } - if (entropy->ac_needed[blkn]) { + if (entropy->ac_needed[blkn]) { - /* Section F.2.2.2: decode the AC coefficients */ - /* Since zeroes are skipped, output area must be cleared beforehand */ for (k = 1; k < DCTSIZE2; k++) { HUFF_DECODE(s, br_state, actbl, return FALSE, label2); @@ -197302,26 +181319,20 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) s &= 15; if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Output coefficient in natural (dezigzagged) order. - * Note: the extra entries in jpeg_natural_order[] will save us - * if k >= DCTSIZE2, which could happen if the data is corrupted. - */ - (*block)[jpeg_natural_order[k]] = (JCOEF) s; + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + (*block)[jpeg_natural_order[k]] = (JCOEF) s; } else { - if (r != 15) - break; - k += 15; + if (r != 15) + break; + k += 15; } } - } else { + } else { - /* Section F.2.2.2: decode the AC coefficients */ - /* In this path we just discard the values */ for (k = 1; k < DCTSIZE2; k++) { HUFF_DECODE(s, br_state, actbl, return FALSE, label3); @@ -197329,34 +181340,28 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) s &= 15; if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); } else { - if (r != 15) - break; - k += 15; + if (r != 15) + break; + k += 15; } } - } - } + } + } - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); } - /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; } -/* - * Module initialization routine for Huffman entropy decoding. - */ - GLOBAL(void) jinit_huff_decoder (j_decompress_ptr cinfo) { @@ -197364,15 +181369,14 @@ jinit_huff_decoder (j_decompress_ptr cinfo) int i; entropy = (huff_entropy_ptr2) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(huff_entropy_decoder2)); cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; entropy->pub.start_pass = start_pass_huff_decoder; entropy->pub.decode_mcu = decode_mcu; - /* Mark tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; } } /********* End of inlined file: jdhuff.c *********/ @@ -197380,8 +181384,6 @@ jinit_huff_decoder (j_decompress_ptr cinfo) /********* Start of inlined file: jdinput.c *********/ #define JPEG_INTERNALS -/* Private state */ - typedef struct { struct jpeg_input_controller pub; /* public fields */ @@ -197390,192 +181392,132 @@ typedef struct { typedef my_input_controller * my_inputctl_ptr; -/* Forward declarations */ METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); -/* - * Routines to calculate various quantities related to the size of the image. - */ - LOCAL(void) initial_setup2 (j_decompress_ptr cinfo) -/* Called once, when first SOS marker is reached */ { int ci; jpeg_component_info *compptr; - /* Make sure image isn't bigger than I can handle */ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || - (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - /* For now, precision must match compiled-in value... */ if (cinfo->data_precision != BITS_IN_JSAMPLE) - ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); - /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); - /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) - ERREXIT(cinfo, JERR_BAD_SAMPLING); - cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); - cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } - /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. - * In the full decompressor, this will be overridden by jdmaster.c; - * but in the transcoder, jdmaster.c is not used, so we must do it here. - */ cinfo->min_DCT_scaled_size = DCTSIZE; - /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->DCT_scaled_size = DCTSIZE; - /* Size in DCT blocks */ - compptr->width_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * DCTSIZE)); - /* downsampled_width and downsampled_height will also be overridden by - * jdmaster.c if we are doing full decompression. The transcoder library - * doesn't use these values, but the calling application might. - */ - /* Size in samples */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); - /* Mark component needed, until color conversion says otherwise */ - compptr->component_needed = TRUE; - /* Mark no quantization table yet saved for component */ - compptr->quant_table = NULL; + ci++, compptr++) { + compptr->DCT_scaled_size = DCTSIZE; + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + compptr->component_needed = TRUE; + compptr->quant_table = NULL; } - /* Compute number of fully interleaved MCU rows. */ cinfo->total_iMCU_rows = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, + jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); - /* Decide whether file contains multiple scans */ if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) - cinfo->inputctl->has_multiple_scans = TRUE; + cinfo->inputctl->has_multiple_scans = TRUE; else - cinfo->inputctl->has_multiple_scans = FALSE; + cinfo->inputctl->has_multiple_scans = FALSE; } LOCAL(void) per_scan_setup2 (j_decompress_ptr cinfo) -/* Do computations that are needed before processing a JPEG scan */ -/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ { int ci, mcublks, tmp; jpeg_component_info *compptr; if (cinfo->comps_in_scan == 1) { - /* Noninterleaved (single-component) scan */ - compptr = cinfo->cur_comp_info[0]; + compptr = cinfo->cur_comp_info[0]; - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = compptr->width_in_blocks; - cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - /* For noninterleaved scan, always one block per MCU */ - compptr->MCU_width = 1; - compptr->MCU_height = 1; - compptr->MCU_blocks = 1; - compptr->MCU_sample_width = compptr->DCT_scaled_size; - compptr->last_col_width = 1; - /* For noninterleaved scans, it is convenient to define last_row_height - * as the number of block rows present in the last iMCU row. - */ - tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); - if (tmp == 0) tmp = compptr->v_samp_factor; - compptr->last_row_height = tmp; + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = compptr->DCT_scaled_size; + compptr->last_col_width = 1; + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; - /* Prepare array describing MCU composition */ - cinfo->blocks_in_MCU = 1; - cinfo->MCU_membership[0] = 0; + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; } else { - /* Interleaved (multi-component) scan */ - if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, - MAX_COMPS_IN_SCAN); + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); - /* Overall image size in MCUs */ - cinfo->MCUs_per_row = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*DCTSIZE)); - cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*DCTSIZE)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); - cinfo->blocks_in_MCU = 0; + cinfo->blocks_in_MCU = 0; - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Sampling factors give # of blocks of component in each MCU */ - compptr->MCU_width = compptr->h_samp_factor; - compptr->MCU_height = compptr->v_samp_factor; - compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; - /* Figure number of non-dummy blocks in last MCU column & row */ - tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); - if (tmp == 0) tmp = compptr->MCU_width; - compptr->last_col_width = tmp; - tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); - if (tmp == 0) tmp = compptr->MCU_height; - compptr->last_row_height = tmp; - /* Prepare array describing MCU composition */ - mcublks = compptr->MCU_blocks; - if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); - while (mcublks-- > 0) { + while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; - } - } + } + } } } -/* - * Save away a copy of the Q-table referenced by each component present - * in the current scan, unless already saved during a prior scan. - * - * In a multiple-scan JPEG file, the encoder could assign different components - * the same Q-table slot number, but change table definitions between scans - * so that each component uses a different Q-table. (The IJG encoder is not - * currently capable of doing this, but other encoders might.) Since we want - * to be able to dequantize all the components at the end of the file, this - * means that we have to save away the table actually used for each component. - * We do this by copying the table at the start of the first scan containing - * the component. - * The JPEG spec prohibits the encoder from changing the contents of a Q-table - * slot between scans of a component using that slot. If the encoder does so - * anyway, this decoder will simply use the Q-table values that were current - * at the start of the first scan for the component. - * - * The decompressor output side looks only at the saved quant tables, - * not at the current Q-table slots. - */ - LOCAL(void) latch_quant_tables (j_decompress_ptr cinfo) { @@ -197584,31 +181526,21 @@ latch_quant_tables (j_decompress_ptr cinfo) JQUANT_TBL * qtbl; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* No work if we already saved Q-table for this component */ - if (compptr->quant_table != NULL) - continue; - /* Make sure specified quantization table is present */ - qtblno = compptr->quant_tbl_no; - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + compptr = cinfo->cur_comp_info[ci]; + if (compptr->quant_table != NULL) + continue; + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - /* OK, save away the quantization table */ - qtbl = (JQUANT_TBL *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(JQUANT_TBL)); - MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); - compptr->quant_table = qtbl; + MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr->quant_table = qtbl; } } -/* - * Initialize the input modules to read a scan of compressed data. - * The first call to this is done by jdmaster.c after initializing - * the entire decompressor (during jpeg_start_decompress). - * Subsequent calls come from consume_markers, below. - */ - METHODDEF(void) start_input_pass2 (j_decompress_ptr cinfo) { @@ -197619,28 +181551,12 @@ start_input_pass2 (j_decompress_ptr cinfo) cinfo->inputctl->consume_input = cinfo->coef->consume_data; } -/* - * Finish up after inputting a compressed-data scan. - * This is called by the coefficient controller after it's read all - * the expected data of the scan. - */ - METHODDEF(void) finish_input_pass (j_decompress_ptr cinfo) { cinfo->inputctl->consume_input = consume_markers; } -/* - * Read JPEG markers before, between, or after compressed-data scans. - * Change state as necessary when a new scan is reached. - * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - * - * The consume_input method pointer points either here or to the - * coefficient controller's consume_data routine, depending on whether - * we are reading a compressed data segment or inter-segment markers. - */ - METHODDEF(int) consume_markers (j_decompress_ptr cinfo) { @@ -197648,49 +181564,38 @@ consume_markers (j_decompress_ptr cinfo) int val; if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ - return JPEG_REACHED_EOI; + return JPEG_REACHED_EOI; val = (*cinfo->marker->read_markers) (cinfo); switch (val) { case JPEG_REACHED_SOS: /* Found SOS */ - if (inputctl->inheaders) { /* 1st SOS */ - initial_setup2(cinfo); - inputctl->inheaders = FALSE; - /* Note: start_input_pass must be called by jdmaster.c - * before any more input can be consumed. jdapimin.c is - * responsible for enforcing this sequencing. - */ - } else { /* 2nd or later SOS marker */ - if (! inputctl->pub.has_multiple_scans) + if (inputctl->inheaders) { /* 1st SOS */ + initial_setup2(cinfo); + inputctl->inheaders = FALSE; + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ - start_input_pass2(cinfo); - } - break; + start_input_pass2(cinfo); + } + break; case JPEG_REACHED_EOI: /* Found EOI */ - inputctl->pub.eoi_reached = TRUE; - if (inputctl->inheaders) { /* Tables-only datastream, apparently */ - if (cinfo->marker->saw_SOF) + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) ERREXIT(cinfo, JERR_SOF_NO_SOS); - } else { - /* Prevent infinite loop in coef ctlr's decompress_data routine - * if user set output_scan_number larger than number of scans. - */ - if (cinfo->output_scan_number > cinfo->input_scan_number) + } else { + if (cinfo->output_scan_number > cinfo->input_scan_number) cinfo->output_scan_number = cinfo->input_scan_number; - } - break; + } + break; case JPEG_SUSPENDED: - break; + break; } return val; } -/* - * Reset state to begin a fresh datastream. - */ - METHODDEF(void) reset_input_controller (j_decompress_ptr cinfo) { @@ -197700,36 +181605,24 @@ reset_input_controller (j_decompress_ptr cinfo) inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ inputctl->pub.eoi_reached = FALSE; inputctl->inheaders = TRUE; - /* Reset other modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->marker->reset_marker_reader) (cinfo); - /* Reset progression state -- would be cleaner if entropy decoder did this */ cinfo->coef_bits = NULL; } -/* - * Initialize the input controller module. - * This is called only once, when the decompression object is created. - */ - GLOBAL(void) jinit_input_controller (j_decompress_ptr cinfo) { my_inputctl_ptr inputctl; - /* Create subobject in permanent pool */ inputctl = (my_inputctl_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_input_controller)); cinfo->inputctl = (struct jpeg_input_controller *) inputctl; - /* Initialize method pointers */ inputctl->pub.consume_input = consume_markers; inputctl->pub.reset_input_controller = reset_input_controller; inputctl->pub.start_input_pass = start_input_pass2; inputctl->pub.finish_input_pass = finish_input_pass; - /* Initialize state: can't use reset_input_controller since we don't - * want to try to reset other modules yet. - */ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ inputctl->pub.eoi_reached = FALSE; inputctl->inheaders = TRUE; @@ -197739,110 +181632,14 @@ jinit_input_controller (j_decompress_ptr cinfo) /********* Start of inlined file: jdmainct.c *********/ #define JPEG_INTERNALS -/* - * In the current system design, the main buffer need never be a full-image - * buffer; any full-height buffers will be found inside the coefficient or - * postprocessing controllers. Nonetheless, the main controller is not - * trivial. Its responsibility is to provide context rows for upsampling/ - * rescaling, and doing this in an efficient fashion is a bit tricky. - * - * Postprocessor input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) - * sample rows of each component. (We require DCT_scaled_size values to be - * chosen such that these numbers are integers. In practice DCT_scaled_size - * values will likely be powers of two, so we actually have the stronger - * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) - * Upsampling will typically produce max_v_samp_factor pixel rows from each - * row group (times any additional scale factor that the upsampler is - * applying). - * - * The coefficient controller will deliver data to us one iMCU row at a time; - * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or - * exactly min_DCT_scaled_size row groups. (This amount of data corresponds - * to one row of MCUs when the image is fully interleaved.) Note that the - * number of sample rows varies across components, but the number of row - * groups does not. Some garbage sample rows may be included in the last iMCU - * row at the bottom of the image. - * - * Depending on the vertical scaling algorithm used, the upsampler may need - * access to the sample row(s) above and below its current input row group. - * The upsampler is required to set need_context_rows TRUE at global selection - * time if so. When need_context_rows is FALSE, this controller can simply - * obtain one iMCU row at a time from the coefficient controller and dole it - * out as row groups to the postprocessor. - * - * When need_context_rows is TRUE, this controller guarantees that the buffer - * passed to postprocessing contains at least one row group's worth of samples - * above and below the row group(s) being processed. Note that the context - * rows "above" the first passed row group appear at negative row offsets in - * the passed buffer. At the top and bottom of the image, the required - * context rows are manufactured by duplicating the first or last real sample - * row; this avoids having special cases in the upsampling inner loops. - * - * The amount of context is fixed at one row group just because that's a - * convenient number for this controller to work with. The existing - * upsamplers really only need one sample row of context. An upsampler - * supporting arbitrary output rescaling might wish for more than one row - * group of context when shrinking the image; tough, we don't handle that. - * (This is justified by the assumption that downsizing will be handled mostly - * by adjusting the DCT_scaled_size values, so that the actual scale factor at - * the upsample step needn't be much less than one.) - * - * To provide the desired context, we have to retain the last two row groups - * of one iMCU row while reading in the next iMCU row. (The last row group - * can't be processed until we have another row group for its below-context, - * and so we have to save the next-to-last group too for its above-context.) - * We could do this most simply by copying data around in our buffer, but - * that'd be very slow. We can avoid copying any data by creating a rather - * strange pointer structure. Here's how it works. We allocate a workspace - * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number - * of row groups per iMCU row). We create two sets of redundant pointers to - * the workspace. Labeling the physical row groups 0 to M+1, the synthesized - * pointer lists look like this: - * M+1 M-1 - * master pointer --> 0 master pointer --> 0 - * 1 1 - * ... ... - * M-3 M-3 - * M-2 M - * M-1 M+1 - * M M-2 - * M+1 M-1 - * 0 0 - * We read alternate iMCU rows using each master pointer; thus the last two - * row groups of the previous iMCU row remain un-overwritten in the workspace. - * The pointer lists are set up so that the required context rows appear to - * be adjacent to the proper places when we pass the pointer lists to the - * upsampler. - * - * The above pictures describe the normal state of the pointer lists. - * At top and bottom of the image, we diddle the pointer lists to duplicate - * the first or last sample row as necessary (this is cheaper than copying - * sample rows around). - * - * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that - * situation each iMCU row provides only one row group so the buffering logic - * must be different (eg, we must read two iMCU rows before we can emit the - * first row group). For now, we simply do not support providing context - * rows when min_DCT_scaled_size is 1. That combination seems unlikely to - * be worth providing --- if someone wants a 1/8th-size preview, they probably - * want it quick and dirty, so a context-free upsampler is sufficient. - */ - -/* Private buffer controller object */ - typedef struct { struct jpeg_d_main_controller pub; /* public fields */ - /* Pointer to allocated workspace (M or M+2 row groups). */ JSAMPARRAY buffer[MAX_COMPONENTS]; boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ - /* Remaining fields are only used in the context case. */ - - /* These are the master pointers to the funny-order pointer lists. */ JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ int whichptr; /* indicates which pointer set is now in use */ @@ -197853,29 +181650,24 @@ typedef struct { typedef my_main_controller4 * my_main_ptr4; -/* context_state values: */ #define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ #define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ #define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ -/* Forward declarations */ METHODDEF(void) process_data_simple_main2 JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); METHODDEF(void) process_data_context_main JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) process_data_crank_post JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #endif LOCAL(void) alloc_funny_pointers (j_decompress_ptr cinfo) -/* Allocate space for the funny pointer lists. - * This is done only once, not once per pass. - */ { my_main_ptr4 main_ = (my_main_ptr4) cinfo->main; int ci, rgroup; @@ -197883,39 +181675,27 @@ alloc_funny_pointers (j_decompress_ptr cinfo) jpeg_component_info *compptr; JSAMPARRAY xbuf; - /* Get top-level space for component array pointers. - * We alloc both arrays with one call to save a few cycles. - */ main_->xbuffer[0] = (JSAMPIMAGE) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); main_->xbuffer[1] = main_->xbuffer[0] + cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - /* Get space for pointer lists --- M+4 row groups in each list. - * We alloc both pointer lists with one call to save a few cycles. - */ - xbuf = (JSAMPARRAY) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); - xbuf += rgroup; /* want one row group at negative offsets */ - main_->xbuffer[0][ci] = xbuf; - xbuf += rgroup * (M + 4); - main_->xbuffer[1][ci] = xbuf; + xbuf += rgroup; /* want one row group at negative offsets */ + main_->xbuffer[0][ci] = xbuf; + xbuf += rgroup * (M + 4); + main_->xbuffer[1][ci] = xbuf; } } LOCAL(void) make_funny_pointers (j_decompress_ptr cinfo) -/* Create the funny pointer lists discussed in the comments above. - * The actual workspace is already allocated (in main->buffer), - * and the space for the pointer lists is allocated too. - * This routine just fills in the curiously ordered lists. - * This will be repeated at the beginning of each pass. - */ { my_main_ptr4 main_ = (my_main_ptr4) cinfo->main; int ci, i, rgroup; @@ -197924,37 +181704,27 @@ make_funny_pointers (j_decompress_ptr cinfo) JSAMPARRAY buf, xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - xbuf0 = main_->xbuffer[0][ci]; - xbuf1 = main_->xbuffer[1][ci]; - /* First copy the workspace pointers as-is */ - buf = main_->buffer[ci]; - for (i = 0; i < rgroup * (M + 2); i++) { - xbuf0[i] = xbuf1[i] = buf[i]; - } - /* In the second list, put the last four row groups in swapped order */ - for (i = 0; i < rgroup * 2; i++) { - xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; - xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; - } - /* The wraparound pointers at top and bottom will be filled later - * (see set_wraparound_pointers, below). Initially we want the "above" - * pointers to duplicate the first actual data line. This only needs - * to happen in xbuffer[0]. - */ - for (i = 0; i < rgroup; i++) { - xbuf0[i - rgroup] = xbuf0[0]; - } + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf0 = main_->xbuffer[0][ci]; + xbuf1 = main_->xbuffer[1][ci]; + buf = main_->buffer[ci]; + for (i = 0; i < rgroup * (M + 2); i++) { + xbuf0[i] = xbuf1[i] = buf[i]; + } + for (i = 0; i < rgroup * 2; i++) { + xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; + xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; + } + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[0]; + } } } LOCAL(void) set_wraparound_pointers (j_decompress_ptr cinfo) -/* Set up the "wraparound" pointers at top and bottom of the pointer lists. - * This changes the pointer list state from top-of-image to the normal state. - */ { my_main_ptr4 main_ = (my_main_ptr4) cinfo->main; int ci, i, rgroup; @@ -197963,26 +181733,22 @@ set_wraparound_pointers (j_decompress_ptr cinfo) JSAMPARRAY xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - xbuf0 = main_->xbuffer[0][ci]; - xbuf1 = main_->xbuffer[1][ci]; - for (i = 0; i < rgroup; i++) { - xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; - xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; - xbuf0[rgroup*(M+2) + i] = xbuf0[i]; - xbuf1[rgroup*(M+2) + i] = xbuf1[i]; - } + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf0 = main_->xbuffer[0][ci]; + xbuf1 = main_->xbuffer[1][ci]; + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; + xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; + xbuf0[rgroup*(M+2) + i] = xbuf0[i]; + xbuf1[rgroup*(M+2) + i] = xbuf1[i]; + } } } LOCAL(void) set_bottom_pointers (j_decompress_ptr cinfo) -/* Change the pointer lists to duplicate the last sample row at the bottom - * of the image. whichptr indicates which xbuffer holds the final iMCU row. - * Also sets rowgroups_avail to indicate number of nondummy row groups in row. - */ { my_main_ptr4 main_ = (my_main_ptr4) cinfo->main; int ci, i, rgroup, iMCUheight, rows_left; @@ -197990,33 +181756,21 @@ set_bottom_pointers (j_decompress_ptr cinfo) JSAMPARRAY xbuf; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Count sample rows in one iMCU row and in one row group */ - iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; - rgroup = iMCUheight / cinfo->min_DCT_scaled_size; - /* Count nondummy sample rows remaining for this component */ - rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); - if (rows_left == 0) rows_left = iMCUheight; - /* Count nondummy row groups. Should get same answer for each component, - * so we need only do it once. - */ - if (ci == 0) { - main_->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); - } - /* Duplicate the last real sample row rgroup*2 times; this pads out the - * last partial rowgroup and ensures at least one full rowgroup of context. - */ - xbuf = main_->xbuffer[main_->whichptr][ci]; - for (i = 0; i < rgroup * 2; i++) { - xbuf[rows_left + i] = xbuf[rows_left-1]; - } + ci++, compptr++) { + iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; + rgroup = iMCUheight / cinfo->min_DCT_scaled_size; + rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); + if (rows_left == 0) rows_left = iMCUheight; + if (ci == 0) { + main_->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + } + xbuf = main_->xbuffer[main_->whichptr][ci]; + for (i = 0; i < rgroup * 2; i++) { + xbuf[rows_left + i] = xbuf[rows_left-1]; + } } } -/* - * Initialize for a processing pass. - */ - METHODDEF(void) start_pass_main2 (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { @@ -198024,36 +181778,29 @@ start_pass_main2 (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) switch (pass_mode) { case JBUF_PASS_THRU: - if (cinfo->upsample->need_context_rows) { - main_->pub.process_data = process_data_context_main; - make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ - main_->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ - main_->context_state = CTX_PREPARE_FOR_IMCU; - main_->iMCU_row_ctr = 0; - } else { - /* Simple case with no context needed */ - main_->pub.process_data = process_data_simple_main2; - } - main_->buffer_full = FALSE; /* Mark buffer empty */ - main_->rowgroup_ctr = 0; - break; + if (cinfo->upsample->need_context_rows) { + main_->pub.process_data = process_data_context_main; + make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ + main_->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + main_->context_state = CTX_PREPARE_FOR_IMCU; + main_->iMCU_row_ctr = 0; + } else { + main_->pub.process_data = process_data_simple_main2; + } + main_->buffer_full = FALSE; /* Mark buffer empty */ + main_->rowgroup_ctr = 0; + break; #ifdef QUANT_2PASS_SUPPORTED case JBUF_CRANK_DEST: - /* For last pass of 2-pass quantization, just crank the postprocessor */ - main_->pub.process_data = process_data_crank_post; - break; + main_->pub.process_data = process_data_crank_post; + break; #endif default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; } } -/* - * Process some data. - * This handles the simple case where no context is required. - */ - METHODDEF(void) process_data_simple_main2 (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, @@ -198062,37 +181809,24 @@ process_data_simple_main2 (j_decompress_ptr cinfo, my_main_ptr4 main_ = (my_main_ptr4) cinfo->main; JDIMENSION rowgroups_avail; - /* Read input data if we haven't filled the main buffer yet */ if (! main_->buffer_full) { - if (! (*cinfo->coef->decompress_data) (cinfo, main_->buffer)) - return; /* suspension forced, can do nothing more */ - main_->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + if (! (*cinfo->coef->decompress_data) (cinfo, main_->buffer)) + return; /* suspension forced, can do nothing more */ + main_->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ } - /* There are always min_DCT_scaled_size row groups in an iMCU row. */ rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; - /* Note: at the bottom of the image, we may pass extra garbage row groups - * to the postprocessor. The postprocessor has to check for bottom - * of image anyway (at row resolution), so no point in us doing it too. - */ - /* Feed the postprocessor */ (*cinfo->post->post_process_data) (cinfo, main_->buffer, - &main_->rowgroup_ctr, rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); + &main_->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); - /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ if (main_->rowgroup_ctr >= rowgroups_avail) { - main_->buffer_full = FALSE; - main_->rowgroup_ctr = 0; + main_->buffer_full = FALSE; + main_->rowgroup_ctr = 0; } } -/* - * Process some data. - * This handles the case where context rows must be provided. - */ - METHODDEF(void) process_data_context_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, @@ -198100,70 +181834,46 @@ process_data_context_main (j_decompress_ptr cinfo, { my_main_ptr4 main_ = (my_main_ptr4) cinfo->main; - /* Read input data if we haven't filled the main buffer yet */ if (! main_->buffer_full) { - if (! (*cinfo->coef->decompress_data) (cinfo, + if (! (*cinfo->coef->decompress_data) (cinfo, main_->xbuffer[main_->whichptr])) - return; /* suspension forced, can do nothing more */ - main_->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ - main_->iMCU_row_ctr++; /* count rows received */ + return; /* suspension forced, can do nothing more */ + main_->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + main_->iMCU_row_ctr++; /* count rows received */ } - /* Postprocessor typically will not swallow all the input data it is handed - * in one call (due to filling the output buffer first). Must be prepared - * to exit and restart. This switch lets us keep track of how far we got. - * Note that each case falls through to the next on successful completion. - */ switch (main_->context_state) { case CTX_POSTPONED_ROW: - /* Call postprocessor using previously set pointers for postponed row */ - (*cinfo->post->post_process_data) (cinfo, main_->xbuffer[main_->whichptr], + (*cinfo->post->post_process_data) (cinfo, main_->xbuffer[main_->whichptr], &main_->rowgroup_ctr, main_->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); - if (main_->rowgroup_ctr < main_->rowgroups_avail) - return; /* Need to suspend */ - main_->context_state = CTX_PREPARE_FOR_IMCU; - if (*out_row_ctr >= out_rows_avail) - return; /* Postprocessor exactly filled output buf */ - /*FALLTHROUGH*/ + if (main_->rowgroup_ctr < main_->rowgroups_avail) + return; /* Need to suspend */ + main_->context_state = CTX_PREPARE_FOR_IMCU; + if (*out_row_ctr >= out_rows_avail) + return; /* Postprocessor exactly filled output buf */ case CTX_PREPARE_FOR_IMCU: - /* Prepare to process first M-1 row groups of this iMCU row */ - main_->rowgroup_ctr = 0; - main_->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); - /* Check for bottom of image: if so, tweak pointers to "duplicate" - * the last sample row, and adjust rowgroups_avail to ignore padding rows. - */ - if (main_->iMCU_row_ctr == cinfo->total_iMCU_rows) - set_bottom_pointers(cinfo); - main_->context_state = CTX_PROCESS_IMCU; - /*FALLTHROUGH*/ + main_->rowgroup_ctr = 0; + main_->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); + if (main_->iMCU_row_ctr == cinfo->total_iMCU_rows) + set_bottom_pointers(cinfo); + main_->context_state = CTX_PROCESS_IMCU; case CTX_PROCESS_IMCU: - /* Call postprocessor using previously set pointers */ - (*cinfo->post->post_process_data) (cinfo, main_->xbuffer[main_->whichptr], + (*cinfo->post->post_process_data) (cinfo, main_->xbuffer[main_->whichptr], &main_->rowgroup_ctr, main_->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); - if (main_->rowgroup_ctr < main_->rowgroups_avail) - return; /* Need to suspend */ - /* After the first iMCU, change wraparound pointers to normal state */ - if (main_->iMCU_row_ctr == 1) - set_wraparound_pointers(cinfo); - /* Prepare to load new iMCU row using other xbuffer list */ - main_->whichptr ^= 1; /* 0=>1 or 1=>0 */ - main_->buffer_full = FALSE; - /* Still need to process last row group of this iMCU row, */ - /* which is saved at index M+1 of the other xbuffer */ - main_->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); - main_->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); - main_->context_state = CTX_POSTPONED_ROW; + if (main_->rowgroup_ctr < main_->rowgroups_avail) + return; /* Need to suspend */ + if (main_->iMCU_row_ctr == 1) + set_wraparound_pointers(cinfo); + main_->whichptr ^= 1; /* 0=>1 or 1=>0 */ + main_->buffer_full = FALSE; + main_->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); + main_->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); + main_->context_state = CTX_POSTPONED_ROW; } } -/* - * Process some data. - * Final pass of two-pass quantization: just call the postprocessor. - * Source data will be the postprocessor controller's internal buffer. - */ - #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) @@ -198172,16 +181882,12 @@ process_data_crank_post (j_decompress_ptr cinfo, JDIMENSION out_rows_avail) { (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, - (JDIMENSION *) NULL, (JDIMENSION) 0, - output_buf, out_row_ctr, out_rows_avail); + (JDIMENSION *) NULL, (JDIMENSION) 0, + output_buf, out_row_ctr, out_rows_avail); } #endif /* QUANT_2PASS_SUPPORTED */ -/* - * Initialize main buffer controller. - */ - GLOBAL(void) jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { @@ -198190,31 +181896,28 @@ jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) jpeg_component_info *compptr; main_ = (my_main_ptr4) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller4)); cinfo->main = (struct jpeg_d_main_controller *) main_; main_->pub.start_pass = start_pass_main2; if (need_full_buffer) /* shouldn't happen */ - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - /* Allocate the workspace. - * ngroups is the number of row groups we need. - */ if (cinfo->upsample->need_context_rows) { - if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ - ERREXIT(cinfo, JERR_NOTIMPL); - alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ - ngroups = cinfo->min_DCT_scaled_size + 2; + if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ + ERREXIT(cinfo, JERR_NOTIMPL); + alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ + ngroups = cinfo->min_DCT_scaled_size + 2; } else { - ngroups = cinfo->min_DCT_scaled_size; + ngroups = cinfo->min_DCT_scaled_size; } for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ - main_->buffer[ci] = (*cinfo->mem->alloc_sarray) + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + main_->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * compptr->DCT_scaled_size, (JDIMENSION) (rgroup * ngroups)); @@ -198225,73 +181928,46 @@ jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) /********* Start of inlined file: jdmarker.c *********/ #define JPEG_INTERNALS -/* Private state */ - typedef struct { struct jpeg_marker_reader pub; /* public fields */ - /* Application-overridable marker processing methods */ jpeg_marker_parser_method process_COM; jpeg_marker_parser_method process_APPn[16]; - /* Limit on marker data length to save for each marker type */ unsigned int length_limit_COM; unsigned int length_limit_APPn[16]; - /* Status of COM/APPn marker saving */ jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ unsigned int bytes_read; /* data bytes read so far in marker */ - /* Note: cur_marker is not linked into marker_list until it's all read. */ } my_marker_reader; typedef my_marker_reader * my_marker_ptr2; -/* - * Macros for fetching data from the data source module. - * - * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect - * the current restart point; we update them only when we have reached a - * suitable place to restart if a suspension occurs. - */ - -/* Declare and initialize local copies of input pointer/count */ #define INPUT_VARS(cinfo) \ struct jpeg_source_mgr * datasrc = (cinfo)->src; \ const JOCTET * next_input_byte = datasrc->next_input_byte; \ size_t bytes_in_buffer = datasrc->bytes_in_buffer -/* Unload the local copies --- do this only at a restart boundary */ #define INPUT_SYNC(cinfo) \ ( datasrc->next_input_byte = next_input_byte, \ datasrc->bytes_in_buffer = bytes_in_buffer ) -/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ #define INPUT_RELOAD(cinfo) \ ( next_input_byte = datasrc->next_input_byte, \ bytes_in_buffer = datasrc->bytes_in_buffer ) -/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. - * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, - * but we must reload the local copies after a successful fill. - */ #define MAKE_BYTE_AVAIL(cinfo,action) \ if (bytes_in_buffer == 0) { \ if (! (*datasrc->fill_input_buffer) (cinfo)) \ - { action; } \ + { action; } \ INPUT_RELOAD(cinfo); \ } -/* Read a byte into variable V. - * If must suspend, take the specified action (typically "return FALSE"). - */ #define INPUT_BYTE(cinfo,V,action) \ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ bytes_in_buffer--; \ V = GETJOCTET(*next_input_byte++); ) -/* As above, but read two bytes interpreted as an unsigned 16-bit integer. - * V should be declared unsigned int or perhaps INT32. - */ #define INPUT_2BYTES(cinfo,V,action) \ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ bytes_in_buffer--; \ @@ -198300,58 +181976,23 @@ typedef my_marker_reader * my_marker_ptr2; bytes_in_buffer--; \ V += GETJOCTET(*next_input_byte++); ) -/* - * Routines to process JPEG markers. - * - * Entry condition: JPEG marker itself has been read and its code saved - * in cinfo->unread_marker; input restart point is just after the marker. - * - * Exit: if return TRUE, have read and processed any parameters, and have - * updated the restart point to point after the parameters. - * If return FALSE, was forced to suspend before reaching end of - * marker parameters; restart point has not been moved. Same routine - * will be called again after application supplies more input data. - * - * This approach to suspension assumes that all of a marker's parameters - * can fit into a single input bufferload. This should hold for "normal" - * markers. Some COM/APPn markers might have large parameter segments - * that might not fit. If we are simply dropping such a marker, we use - * skip_input_data to get past it, and thereby put the problem on the - * source manager's shoulders. If we are saving the marker's contents - * into memory, we use a slightly different convention: when forced to - * suspend, the marker processor updates the restart point to the end of - * what it's consumed (ie, the end of the buffer) before returning FALSE. - * On resumption, cinfo->unread_marker still contains the marker code, - * but the data source will point to the next chunk of marker data. - * The marker processor must retain internal state to deal with this. - * - * Note that we don't bother to avoid duplicate trace messages if a - * suspension occurs within marker parameters. Other side effects - * require more care. - */ - LOCAL(boolean) get_soi (j_decompress_ptr cinfo) -/* Process an SOI marker */ { int i; TRACEMS(cinfo, 1, JTRC_SOI); if (cinfo->marker->saw_SOI) - ERREXIT(cinfo, JERR_SOI_DUPLICATE); - - /* Reset all parameters that are defined to be reset by SOI */ + ERREXIT(cinfo, JERR_SOI_DUPLICATE); for (i = 0; i < NUM_ARITH_TBLS; i++) { - cinfo->arith_dc_L[i] = 0; - cinfo->arith_dc_U[i] = 1; - cinfo->arith_ac_K[i] = 5; + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; } cinfo->restart_interval = 0; - /* Set initial assumptions for colorspace etc */ - cinfo->jpeg_color_space = JCS_UNKNOWN; cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ @@ -198371,7 +182012,6 @@ get_soi (j_decompress_ptr cinfo) LOCAL(boolean) get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) -/* Process a SOFn marker */ { INT32 length; int c, ci; @@ -198395,35 +182035,32 @@ get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) cinfo->num_components); if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_DUPLICATE); + ERREXIT(cinfo, JERR_SOF_DUPLICATE); - /* We don't support files in which the image height is initially specified */ - /* as 0 and is later redefined by DNL. As long as we have to check that, */ - /* might as well have a general sanity check. */ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0) - ERREXIT(cinfo, JERR_EMPTY_IMAGE); + || cinfo->num_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); if (length != (cinfo->num_components * 3)) - ERREXIT(cinfo, JERR_BAD_LENGTH); + ERREXIT(cinfo, JERR_BAD_LENGTH); if (cinfo->comp_info == NULL) /* do only once, even if suspend */ - cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) + cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * SIZEOF(jpeg_component_info)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->component_index = ci; - INPUT_BYTE(cinfo, compptr->component_id, return FALSE); - INPUT_BYTE(cinfo, c, return FALSE); - compptr->h_samp_factor = (c >> 4) & 15; - compptr->v_samp_factor = (c ) & 15; - INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); + ci++, compptr++) { + compptr->component_index = ci; + INPUT_BYTE(cinfo, compptr->component_id, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + compptr->h_samp_factor = (c >> 4) & 15; + compptr->v_samp_factor = (c ) & 15; + INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); - TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, - compptr->component_id, compptr->h_samp_factor, - compptr->v_samp_factor, compptr->quant_tbl_no); + TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, + compptr->component_id, compptr->h_samp_factor, + compptr->v_samp_factor, compptr->quant_tbl_no); } cinfo->marker->saw_SOF = TRUE; @@ -198434,7 +182071,6 @@ get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) LOCAL(boolean) get_sos (j_decompress_ptr cinfo) -/* Process a SOS marker */ { INT32 length; int i, ci, n, c, cc; @@ -198442,7 +182078,7 @@ get_sos (j_decompress_ptr cinfo) INPUT_VARS(cinfo); if (! cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOS_NO_SOF); + ERREXIT(cinfo, JERR_SOS_NO_SOF); INPUT_2BYTES(cinfo, length, return FALSE); @@ -198451,50 +182087,45 @@ get_sos (j_decompress_ptr cinfo) TRACEMS1(cinfo, 1, JTRC_SOS, n); if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) - ERREXIT(cinfo, JERR_BAD_LENGTH); + ERREXIT(cinfo, JERR_BAD_LENGTH); cinfo->comps_in_scan = n; - /* Collect the component-spec parameters */ - for (i = 0; i < n; i++) { - INPUT_BYTE(cinfo, cc, return FALSE); - INPUT_BYTE(cinfo, c, return FALSE); + INPUT_BYTE(cinfo, cc, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - if (cc == compptr->component_id) + if (cc == compptr->component_id) goto id_found; - } + } - ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); id_found: - cinfo->cur_comp_info[i] = compptr; - compptr->dc_tbl_no = (c >> 4) & 15; - compptr->ac_tbl_no = (c ) & 15; + cinfo->cur_comp_info[i] = compptr; + compptr->dc_tbl_no = (c >> 4) & 15; + compptr->ac_tbl_no = (c ) & 15; - TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, - compptr->dc_tbl_no, compptr->ac_tbl_no); + TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, + compptr->dc_tbl_no, compptr->ac_tbl_no); } - /* Collect the additional scan parameters Ss, Se, Ah/Al. */ INPUT_BYTE(cinfo, c, return FALSE); cinfo->Ss = c; INPUT_BYTE(cinfo, c, return FALSE); cinfo->Se = c; INPUT_BYTE(cinfo, c, return FALSE); cinfo->Ah = (c >> 4) & 15; - cinfo->Al = (c ) & 15; + cinfo->Al = (c ) & 15; TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - /* Prepare to scan data & restart markers */ cinfo->marker->next_restart_num = 0; - /* Count another SOS marker */ cinfo->input_scan_number++; INPUT_SYNC(cinfo); @@ -198505,7 +182136,6 @@ get_sos (j_decompress_ptr cinfo) LOCAL(boolean) get_dac (j_decompress_ptr cinfo) -/* Process a DAC marker */ { INT32 length; int index, val; @@ -198515,28 +182145,28 @@ get_dac (j_decompress_ptr cinfo) length -= 2; while (length > 0) { - INPUT_BYTE(cinfo, index, return FALSE); - INPUT_BYTE(cinfo, val, return FALSE); + INPUT_BYTE(cinfo, index, return FALSE); + INPUT_BYTE(cinfo, val, return FALSE); - length -= 2; + length -= 2; - TRACEMS2(cinfo, 1, JTRC_DAC, index, val); + TRACEMS2(cinfo, 1, JTRC_DAC, index, val); - if (index < 0 || index >= (2*NUM_ARITH_TBLS)) - ERREXIT1(cinfo, JERR_DAC_INDEX, index); + if (index < 0 || index >= (2*NUM_ARITH_TBLS)) + ERREXIT1(cinfo, JERR_DAC_INDEX, index); - if (index >= NUM_ARITH_TBLS) { /* define AC table */ - cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; - } else { /* define DC table */ - cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); - cinfo->arith_dc_U[index] = (UINT8) (val >> 4); - if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) + if (index >= NUM_ARITH_TBLS) { /* define AC table */ + cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; + } else { /* define DC table */ + cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); + cinfo->arith_dc_U[index] = (UINT8) (val >> 4); + if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) ERREXIT1(cinfo, JERR_DAC_VALUE, val); - } + } } if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); + ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_SYNC(cinfo); return TRUE; @@ -198550,7 +182180,6 @@ get_dac (j_decompress_ptr cinfo) LOCAL(boolean) get_dht (j_decompress_ptr cinfo) -/* Process a DHT marker */ { INT32 length; UINT8 bits[17]; @@ -198563,56 +182192,53 @@ get_dht (j_decompress_ptr cinfo) length -= 2; while (length > 16) { - INPUT_BYTE(cinfo, index, return FALSE); + INPUT_BYTE(cinfo, index, return FALSE); - TRACEMS1(cinfo, 1, JTRC_DHT, index); + TRACEMS1(cinfo, 1, JTRC_DHT, index); - bits[0] = 0; - count = 0; - for (i = 1; i <= 16; i++) { - INPUT_BYTE(cinfo, bits[i], return FALSE); - count += bits[i]; - } + bits[0] = 0; + count = 0; + for (i = 1; i <= 16; i++) { + INPUT_BYTE(cinfo, bits[i], return FALSE); + count += bits[i]; + } - length -= 1 + 16; + length -= 1 + 16; - TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[1], bits[2], bits[3], bits[4], - bits[5], bits[6], bits[7], bits[8]); - TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[9], bits[10], bits[11], bits[12], - bits[13], bits[14], bits[15], bits[16]); + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); - /* Here we just do minimal validation of the counts to avoid walking - * off the end of our table space. jdhuff.c will check more carefully. - */ - if (count > 256 || ((INT32) count) > length) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + if (count > 256 || ((INT32) count) > length) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); - for (i = 0; i < count; i++) - INPUT_BYTE(cinfo, huffval[i], return FALSE); + for (i = 0; i < count; i++) + INPUT_BYTE(cinfo, huffval[i], return FALSE); - length -= count; + length -= count; - if (index & 0x10) { /* AC table definition */ - index -= 0x10; - htblptr = &cinfo->ac_huff_tbl_ptrs[index]; - } else { /* DC table definition */ - htblptr = &cinfo->dc_huff_tbl_ptrs[index]; - } + if (index & 0x10) { /* AC table definition */ + index -= 0x10; + htblptr = &cinfo->ac_huff_tbl_ptrs[index]; + } else { /* DC table definition */ + htblptr = &cinfo->dc_huff_tbl_ptrs[index]; + } - if (index < 0 || index >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_DHT_INDEX, index); + if (index < 0 || index >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_DHT_INDEX, index); - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); - MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); } if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); + ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_SYNC(cinfo); return TRUE; @@ -198620,7 +182246,6 @@ get_dht (j_decompress_ptr cinfo) LOCAL(boolean) get_dqt (j_decompress_ptr cinfo) -/* Process a DQT marker */ { INT32 length; int n, i, prec; @@ -198632,44 +182257,43 @@ get_dqt (j_decompress_ptr cinfo) length -= 2; while (length > 0) { - INPUT_BYTE(cinfo, n, return FALSE); - prec = n >> 4; - n &= 0x0F; + INPUT_BYTE(cinfo, n, return FALSE); + prec = n >> 4; + n &= 0x0F; - TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); + TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); - if (n >= NUM_QUANT_TBLS) - ERREXIT1(cinfo, JERR_DQT_INDEX, n); + if (n >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, n); - if (cinfo->quant_tbl_ptrs[n] == NULL) - cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); - quant_ptr = cinfo->quant_tbl_ptrs[n]; + if (cinfo->quant_tbl_ptrs[n] == NULL) + cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); + quant_ptr = cinfo->quant_tbl_ptrs[n]; - for (i = 0; i < DCTSIZE2; i++) { - if (prec) + for (i = 0; i < DCTSIZE2; i++) { + if (prec) INPUT_2BYTES(cinfo, tmp, return FALSE); - else + else INPUT_BYTE(cinfo, tmp, return FALSE); - /* We convert the zigzag-order table to natural array order. */ - quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; - } + quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; + } - if (cinfo->err->trace_level >= 2) { - for (i = 0; i < DCTSIZE2; i += 8) { + if (cinfo->err->trace_level >= 2) { + for (i = 0; i < DCTSIZE2; i += 8) { TRACEMS8(cinfo, 2, JTRC_QUANTVALS, quant_ptr->quantval[i], quant_ptr->quantval[i+1], quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); - } - } + } + } - length -= DCTSIZE2+1; - if (prec) length -= DCTSIZE2; + length -= DCTSIZE2+1; + if (prec) length -= DCTSIZE2; } if (length != 0) - ERREXIT(cinfo, JERR_BAD_LENGTH); + ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_SYNC(cinfo); return TRUE; @@ -198677,7 +182301,6 @@ get_dqt (j_decompress_ptr cinfo) LOCAL(boolean) get_dri (j_decompress_ptr cinfo) -/* Process a DRI marker */ { INT32 length; unsigned int tmp; @@ -198686,7 +182309,7 @@ get_dri (j_decompress_ptr cinfo) INPUT_2BYTES(cinfo, length, return FALSE); if (length != 4) - ERREXIT(cinfo, JERR_BAD_LENGTH); + ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_2BYTES(cinfo, tmp, return FALSE); @@ -198698,125 +182321,93 @@ get_dri (j_decompress_ptr cinfo) return TRUE; } -/* - * Routines for processing APPn and COM markers. - * These are either saved in memory or discarded, per application request. - * APP0 and APP14 are specially checked to see if they are - * JFIF and Adobe markers, respectively. - */ - #define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ #define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ #define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ LOCAL(void) examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, - unsigned int datalen, INT32 remaining) -/* Examine first few bytes from an APP0. - * Take appropriate action if it is a JFIF marker. - * datalen is # of bytes at data[], remaining is length of rest of marker data. - */ + unsigned int datalen, INT32 remaining) { INT32 totallen = (INT32) datalen + remaining; if (datalen >= APP0_DATA_LEN && - GETJOCTET(data[0]) == 0x4A && - GETJOCTET(data[1]) == 0x46 && - GETJOCTET(data[2]) == 0x49 && - GETJOCTET(data[3]) == 0x46 && - GETJOCTET(data[4]) == 0) { - /* Found JFIF APP0 marker: save info */ - cinfo->saw_JFIF_marker = TRUE; - cinfo->JFIF_major_version = GETJOCTET(data[5]); - cinfo->JFIF_minor_version = GETJOCTET(data[6]); - cinfo->density_unit = GETJOCTET(data[7]); - cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); - cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); - /* Check version. - * Major version must be 1, anything else signals an incompatible change. - * (We used to treat this as an error, but now it's a nonfatal warning, - * because some bozo at Hijaak couldn't read the spec.) - * Minor version should be 0..2, but process anyway if newer. - */ - if (cinfo->JFIF_major_version != 1) - WARNMS2(cinfo, JWRN_JFIF_MAJOR, - cinfo->JFIF_major_version, cinfo->JFIF_minor_version); - /* Generate trace messages */ - TRACEMS5(cinfo, 1, JTRC_JFIF, - cinfo->JFIF_major_version, cinfo->JFIF_minor_version, - cinfo->X_density, cinfo->Y_density, cinfo->density_unit); - /* Validate thumbnail dimensions and issue appropriate messages */ - if (GETJOCTET(data[12]) | GETJOCTET(data[13])) - TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, - GETJOCTET(data[12]), GETJOCTET(data[13])); - totallen -= APP0_DATA_LEN; - if (totallen != + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x49 && + GETJOCTET(data[3]) == 0x46 && + GETJOCTET(data[4]) == 0) { + cinfo->saw_JFIF_marker = TRUE; + cinfo->JFIF_major_version = GETJOCTET(data[5]); + cinfo->JFIF_minor_version = GETJOCTET(data[6]); + cinfo->density_unit = GETJOCTET(data[7]); + cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); + cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); + if (cinfo->JFIF_major_version != 1) + WARNMS2(cinfo, JWRN_JFIF_MAJOR, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version); + TRACEMS5(cinfo, 1, JTRC_JFIF, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version, + cinfo->X_density, cinfo->Y_density, cinfo->density_unit); + if (GETJOCTET(data[12]) | GETJOCTET(data[13])) + TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, + GETJOCTET(data[12]), GETJOCTET(data[13])); + totallen -= APP0_DATA_LEN; + if (totallen != ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) - TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); + TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); } else if (datalen >= 6 && - GETJOCTET(data[0]) == 0x4A && - GETJOCTET(data[1]) == 0x46 && - GETJOCTET(data[2]) == 0x58 && - GETJOCTET(data[3]) == 0x58 && - GETJOCTET(data[4]) == 0) { - /* Found JFIF "JFXX" extension APP0 marker */ - /* The library doesn't actually do anything with these, - * but we try to produce a helpful trace message. - */ - switch (GETJOCTET(data[5])) { - case 0x10: - TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); - break; - case 0x11: - TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); - break; - case 0x13: - TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); - break; - default: - TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, - GETJOCTET(data[5]), (int) totallen); - break; - } + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x58 && + GETJOCTET(data[3]) == 0x58 && + GETJOCTET(data[4]) == 0) { + switch (GETJOCTET(data[5])) { + case 0x10: + TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); + break; + case 0x11: + TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); + break; + case 0x13: + TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); + break; + default: + TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, + GETJOCTET(data[5]), (int) totallen); + break; + } } else { - /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ - TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); + TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); } } LOCAL(void) examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, - unsigned int datalen, INT32 remaining) -/* Examine first few bytes from an APP14. - * Take appropriate action if it is an Adobe marker. - * datalen is # of bytes at data[], remaining is length of rest of marker data. - */ + unsigned int datalen, INT32 remaining) { unsigned int version, flags0, flags1, transform; if (datalen >= APP14_DATA_LEN && - GETJOCTET(data[0]) == 0x41 && - GETJOCTET(data[1]) == 0x64 && - GETJOCTET(data[2]) == 0x6F && - GETJOCTET(data[3]) == 0x62 && - GETJOCTET(data[4]) == 0x65) { - /* Found Adobe APP14 marker */ - version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); - flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); - flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); - transform = GETJOCTET(data[11]); - TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); - cinfo->saw_Adobe_marker = TRUE; - cinfo->Adobe_transform = (UINT8) transform; + GETJOCTET(data[0]) == 0x41 && + GETJOCTET(data[1]) == 0x64 && + GETJOCTET(data[2]) == 0x6F && + GETJOCTET(data[3]) == 0x62 && + GETJOCTET(data[4]) == 0x65) { + version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); + flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); + flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); + transform = GETJOCTET(data[11]); + TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); + cinfo->saw_Adobe_marker = TRUE; + cinfo->Adobe_transform = (UINT8) transform; } else { - /* Start of APP14 does not match "Adobe", or too short */ - TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); + TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); } } METHODDEF(boolean) get_interesting_appn (j_decompress_ptr cinfo) -/* Process an APP0 or APP14 marker without saving it */ { INT32 length; JOCTET b[APPN_DATA_LEN]; @@ -198826,35 +182417,31 @@ get_interesting_appn (j_decompress_ptr cinfo) INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; - /* get the interesting part of the marker data */ if (length >= APPN_DATA_LEN) - numtoread = APPN_DATA_LEN; + numtoread = APPN_DATA_LEN; else if (length > 0) - numtoread = (unsigned int) length; + numtoread = (unsigned int) length; else - numtoread = 0; + numtoread = 0; for (i = 0; i < numtoread; i++) - INPUT_BYTE(cinfo, b[i], return FALSE); + INPUT_BYTE(cinfo, b[i], return FALSE); length -= numtoread; - /* process it */ switch (cinfo->unread_marker) { case M_APP0: - examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); - break; + examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); + break; case M_APP14: - examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); - break; + examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); + break; default: - /* can't get here unless jpeg_save_markers chooses wrong processor */ - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); - break; + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; } - /* skip any remaining data -- could be lots */ INPUT_SYNC(cinfo); if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); + (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } @@ -198863,7 +182450,6 @@ get_interesting_appn (j_decompress_ptr cinfo) METHODDEF(boolean) save_marker (j_decompress_ptr cinfo) -/* Save an APPn or COM marker into the marker list */ { my_marker_ptr2 marker = (my_marker_ptr2) cinfo->marker; jpeg_saved_marker_ptr cur_marker = marker->cur_marker; @@ -198873,93 +182459,79 @@ save_marker (j_decompress_ptr cinfo) INPUT_VARS(cinfo); if (cur_marker == NULL) { - /* begin reading a marker */ - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - if (length >= 0) { /* watch out for bogus length word */ - /* figure out how much we want to save */ - unsigned int limit; - if (cinfo->unread_marker == (int) M_COM) + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + if (length >= 0) { /* watch out for bogus length word */ + unsigned int limit; + if (cinfo->unread_marker == (int) M_COM) limit = marker->length_limit_COM; - else + else limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; - if ((unsigned int) length < limit) + if ((unsigned int) length < limit) limit = (unsigned int) length; - /* allocate and initialize the marker item */ - cur_marker = (jpeg_saved_marker_ptr) + cur_marker = (jpeg_saved_marker_ptr) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(struct jpeg_marker_struct) + limit); - cur_marker->next = NULL; - cur_marker->marker = (UINT8) cinfo->unread_marker; - cur_marker->original_length = (unsigned int) length; - cur_marker->data_length = limit; - /* data area is just beyond the jpeg_marker_struct */ - data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); - marker->cur_marker = cur_marker; - marker->bytes_read = 0; - bytes_read = 0; - data_length = limit; - } else { - /* deal with bogus length word */ - bytes_read = data_length = 0; - data = NULL; - } + SIZEOF(struct jpeg_marker_struct) + limit); + cur_marker->next = NULL; + cur_marker->marker = (UINT8) cinfo->unread_marker; + cur_marker->original_length = (unsigned int) length; + cur_marker->data_length = limit; + data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); + marker->cur_marker = cur_marker; + marker->bytes_read = 0; + bytes_read = 0; + data_length = limit; + } else { + bytes_read = data_length = 0; + data = NULL; + } } else { - /* resume reading a marker */ - bytes_read = marker->bytes_read; - data_length = cur_marker->data_length; - data = cur_marker->data + bytes_read; + bytes_read = marker->bytes_read; + data_length = cur_marker->data_length; + data = cur_marker->data + bytes_read; } while (bytes_read < data_length) { - INPUT_SYNC(cinfo); /* move the restart point to here */ - marker->bytes_read = bytes_read; - /* If there's not at least one byte in buffer, suspend */ - MAKE_BYTE_AVAIL(cinfo, return FALSE); - /* Copy bytes with reasonable rapidity */ - while (bytes_read < data_length && bytes_in_buffer > 0) { - *data++ = *next_input_byte++; - bytes_in_buffer--; - bytes_read++; - } + INPUT_SYNC(cinfo); /* move the restart point to here */ + marker->bytes_read = bytes_read; + MAKE_BYTE_AVAIL(cinfo, return FALSE); + while (bytes_read < data_length && bytes_in_buffer > 0) { + *data++ = *next_input_byte++; + bytes_in_buffer--; + bytes_read++; + } } - /* Done reading what we want to read */ if (cur_marker != NULL) { /* will be NULL if bogus length word */ - /* Add new marker to end of list */ - if (cinfo->marker_list == NULL) { - cinfo->marker_list = cur_marker; - } else { - jpeg_saved_marker_ptr prev = cinfo->marker_list; - while (prev->next != NULL) + if (cinfo->marker_list == NULL) { + cinfo->marker_list = cur_marker; + } else { + jpeg_saved_marker_ptr prev = cinfo->marker_list; + while (prev->next != NULL) prev = prev->next; - prev->next = cur_marker; - } - /* Reset pointer & calc remaining data length */ - data = cur_marker->data; - length = cur_marker->original_length - data_length; + prev->next = cur_marker; + } + data = cur_marker->data; + length = cur_marker->original_length - data_length; } - /* Reset to initial state for next marker */ marker->cur_marker = NULL; - /* Process the marker if interesting; else just make a generic trace msg */ switch (cinfo->unread_marker) { case M_APP0: - examine_app0(cinfo, data, data_length, length); - break; + examine_app0(cinfo, data, data_length, length); + break; case M_APP14: - examine_app14(cinfo, data, data_length, length); - break; + examine_app14(cinfo, data, data_length, length); + break; default: - TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, - (int) (data_length + length)); - break; + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, + (int) (data_length + length)); + break; } - /* skip any remaining data -- could be lots */ INPUT_SYNC(cinfo); /* do before skip_input_data */ if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); + (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } @@ -198968,7 +182540,6 @@ save_marker (j_decompress_ptr cinfo) METHODDEF(boolean) skip_variable (j_decompress_ptr cinfo) -/* Skip over an unknown or uninteresting variable-length marker */ { INT32 length; INPUT_VARS(cinfo); @@ -198980,20 +182551,11 @@ skip_variable (j_decompress_ptr cinfo) INPUT_SYNC(cinfo); /* do before skip_input_data */ if (length > 0) - (*cinfo->src->skip_input_data) (cinfo, (long) length); + (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } -/* - * Find the next JPEG marker, save it in cinfo->unread_marker. - * Returns FALSE if had to suspend before reaching a marker; - * in that case cinfo->unread_marker is unchanged. - * - * Note that the result might not be a valid marker code, - * but it will never be 0 or FF. - */ - LOCAL(boolean) next_marker (j_decompress_ptr cinfo) { @@ -199001,37 +182563,24 @@ next_marker (j_decompress_ptr cinfo) INPUT_VARS(cinfo); for (;;) { - INPUT_BYTE(cinfo, c, return FALSE); - /* Skip any non-FF bytes. - * This may look a bit inefficient, but it will not occur in a valid file. - * We sync after each discarded byte so that a suspending data source - * can discard the byte from its buffer. - */ - while (c != 0xFF) { - cinfo->marker->discarded_bytes++; - INPUT_SYNC(cinfo); - INPUT_BYTE(cinfo, c, return FALSE); - } - /* This loop swallows any duplicate FF bytes. Extra FFs are legal as - * pad bytes, so don't count them in discarded_bytes. We assume there - * will not be so many consecutive FF bytes as to overflow a suspending - * data source's input buffer. - */ - do { - INPUT_BYTE(cinfo, c, return FALSE); - } while (c == 0xFF); - if (c != 0) - break; /* found a valid marker, exit loop */ - /* Reach here if we found a stuffed-zero data sequence (FF/00). - * Discard it and loop back to try again. - */ - cinfo->marker->discarded_bytes += 2; - INPUT_SYNC(cinfo); + INPUT_BYTE(cinfo, c, return FALSE); + while (c != 0xFF) { + cinfo->marker->discarded_bytes++; + INPUT_SYNC(cinfo); + INPUT_BYTE(cinfo, c, return FALSE); + } + do { + INPUT_BYTE(cinfo, c, return FALSE); + } while (c == 0xFF); + if (c != 0) + break; /* found a valid marker, exit loop */ + cinfo->marker->discarded_bytes += 2; + INPUT_SYNC(cinfo); } if (cinfo->marker->discarded_bytes != 0) { - WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); - cinfo->marker->discarded_bytes = 0; + WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); + cinfo->marker->discarded_bytes = 0; } cinfo->unread_marker = c; @@ -199042,12 +182591,6 @@ next_marker (j_decompress_ptr cinfo) LOCAL(boolean) first_marker (j_decompress_ptr cinfo) -/* Like next_marker, but used to obtain the initial SOI marker. */ -/* For this marker, we do not allow preceding garbage or fill; otherwise, - * we might well scan an entire input file before realizing it ain't JPEG. - * If an application wants to process non-JFIF files, it must seek to the - * SOI before calling the JPEG library. - */ { int c, c2; INPUT_VARS(cinfo); @@ -199055,7 +182598,7 @@ first_marker (j_decompress_ptr cinfo) INPUT_BYTE(cinfo, c, return FALSE); INPUT_BYTE(cinfo, c2, return FALSE); if (c != 0xFF || c2 != (int) M_SOI) - ERREXIT2(cinfo, JERR_NO_SOI, c, c2); + ERREXIT2(cinfo, JERR_NO_SOI, c, c2); cinfo->unread_marker = c2; @@ -199063,300 +182606,202 @@ first_marker (j_decompress_ptr cinfo) return TRUE; } -/* - * Read markers until SOS or EOI. - * - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - */ - METHODDEF(int) read_markers (j_decompress_ptr cinfo) { - /* Outer loop repeats once for each marker. */ for (;;) { - /* Collect the marker proper, unless we already did. */ - /* NB: first_marker() enforces the requirement that SOI appear first. */ - if (cinfo->unread_marker == 0) { - if (! cinfo->marker->saw_SOI) { + if (cinfo->unread_marker == 0) { + if (! cinfo->marker->saw_SOI) { if (! first_marker(cinfo)) return JPEG_SUSPENDED; - } else { + } else { if (! next_marker(cinfo)) return JPEG_SUSPENDED; - } - } - /* At this point cinfo->unread_marker contains the marker code and the - * input point is just past the marker proper, but before any parameters. - * A suspension will cause us to return with this state still true. - */ - switch (cinfo->unread_marker) { - case M_SOI: - if (! get_soi(cinfo)) + } + } + switch (cinfo->unread_marker) { + case M_SOI: + if (! get_soi(cinfo)) return JPEG_SUSPENDED; - break; + break; - case M_SOF0: /* Baseline */ - case M_SOF1: /* Extended sequential, Huffman */ - if (! get_sof(cinfo, FALSE, FALSE)) + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + if (! get_sof(cinfo, FALSE, FALSE)) return JPEG_SUSPENDED; - break; + break; - case M_SOF2: /* Progressive, Huffman */ - if (! get_sof(cinfo, TRUE, FALSE)) + case M_SOF2: /* Progressive, Huffman */ + if (! get_sof(cinfo, TRUE, FALSE)) return JPEG_SUSPENDED; - break; + break; - case M_SOF9: /* Extended sequential, arithmetic */ - if (! get_sof(cinfo, FALSE, TRUE)) + case M_SOF9: /* Extended sequential, arithmetic */ + if (! get_sof(cinfo, FALSE, TRUE)) return JPEG_SUSPENDED; - break; + break; - case M_SOF10: /* Progressive, arithmetic */ - if (! get_sof(cinfo, TRUE, TRUE)) + case M_SOF10: /* Progressive, arithmetic */ + if (! get_sof(cinfo, TRUE, TRUE)) return JPEG_SUSPENDED; - break; + break; - /* Currently unsupported SOFn types */ - case M_SOF3: /* Lossless, Huffman */ - case M_SOF5: /* Differential sequential, Huffman */ - case M_SOF6: /* Differential progressive, Huffman */ - case M_SOF7: /* Differential lossless, Huffman */ - case M_JPG: /* Reserved for JPEG extensions */ - case M_SOF11: /* Lossless, arithmetic */ - case M_SOF13: /* Differential sequential, arithmetic */ - case M_SOF14: /* Differential progressive, arithmetic */ - case M_SOF15: /* Differential lossless, arithmetic */ - ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); - break; + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_JPG: /* Reserved for JPEG extensions */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); + break; - case M_SOS: - if (! get_sos(cinfo)) + case M_SOS: + if (! get_sos(cinfo)) return JPEG_SUSPENDED; - cinfo->unread_marker = 0; /* processed the marker */ - return JPEG_REACHED_SOS; + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_SOS; - case M_EOI: - TRACEMS(cinfo, 1, JTRC_EOI); - cinfo->unread_marker = 0; /* processed the marker */ - return JPEG_REACHED_EOI; + case M_EOI: + TRACEMS(cinfo, 1, JTRC_EOI); + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_EOI; - case M_DAC: - if (! get_dac(cinfo)) + case M_DAC: + if (! get_dac(cinfo)) return JPEG_SUSPENDED; - break; + break; - case M_DHT: - if (! get_dht(cinfo)) + case M_DHT: + if (! get_dht(cinfo)) return JPEG_SUSPENDED; - break; + break; - case M_DQT: - if (! get_dqt(cinfo)) + case M_DQT: + if (! get_dqt(cinfo)) return JPEG_SUSPENDED; - break; + break; - case M_DRI: - if (! get_dri(cinfo)) + case M_DRI: + if (! get_dri(cinfo)) return JPEG_SUSPENDED; - break; + break; - case M_APP0: - case M_APP1: - case M_APP2: - case M_APP3: - case M_APP4: - case M_APP5: - case M_APP6: - case M_APP7: - case M_APP8: - case M_APP9: - case M_APP10: - case M_APP11: - case M_APP12: - case M_APP13: - case M_APP14: - case M_APP15: - if (! (*((my_marker_ptr2) cinfo->marker)->process_APPn[ + case M_APP0: + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP14: + case M_APP15: + if (! (*((my_marker_ptr2) cinfo->marker)->process_APPn[ cinfo->unread_marker - (int) M_APP0]) (cinfo)) return JPEG_SUSPENDED; - break; + break; - case M_COM: - if (! (*((my_marker_ptr2) cinfo->marker)->process_COM) (cinfo)) + case M_COM: + if (! (*((my_marker_ptr2) cinfo->marker)->process_COM) (cinfo)) return JPEG_SUSPENDED; - break; + break; - case M_RST0: /* these are all parameterless */ - case M_RST1: - case M_RST2: - case M_RST3: - case M_RST4: - case M_RST5: - case M_RST6: - case M_RST7: - case M_TEM: - TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); - break; + case M_RST0: /* these are all parameterless */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); + break; - case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ - if (! skip_variable(cinfo)) + case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ + if (! skip_variable(cinfo)) return JPEG_SUSPENDED; - break; + break; - default: /* must be DHP, EXP, JPGn, or RESn */ - /* For now, we treat the reserved markers as fatal errors since they are - * likely to be used to signal incompatible JPEG Part 3 extensions. - * Once the JPEG 3 version-number marker is well defined, this code - * ought to change! - */ - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); - break; - } - /* Successfully processed marker, so reset state variable */ - cinfo->unread_marker = 0; + default: /* must be DHP, EXP, JPGn, or RESn */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + cinfo->unread_marker = 0; } /* end loop */ } -/* - * Read a restart marker, which is expected to appear next in the datastream; - * if the marker is not there, take appropriate recovery action. - * Returns FALSE if suspension is required. - * - * This is called by the entropy decoder after it has read an appropriate - * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder - * has already read a marker from the data source. Under normal conditions - * cinfo->unread_marker will be reset to 0 before returning; if not reset, - * it holds a marker which the decoder will be unable to read past. - */ - METHODDEF(boolean) read_restart_marker (j_decompress_ptr cinfo) { - /* Obtain a marker unless we already did. */ - /* Note that next_marker will complain if it skips any data. */ if (cinfo->unread_marker == 0) { - if (! next_marker(cinfo)) - return FALSE; + if (! next_marker(cinfo)) + return FALSE; } if (cinfo->unread_marker == - ((int) M_RST0 + cinfo->marker->next_restart_num)) { - /* Normal case --- swallow the marker and let entropy decoder continue */ - TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); - cinfo->unread_marker = 0; + ((int) M_RST0 + cinfo->marker->next_restart_num)) { + TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); + cinfo->unread_marker = 0; } else { - /* Uh-oh, the restart markers have been messed up. */ - /* Let the data source manager determine how to resync. */ - if (! (*cinfo->src->resync_to_restart) (cinfo, - cinfo->marker->next_restart_num)) - return FALSE; + if (! (*cinfo->src->resync_to_restart) (cinfo, + cinfo->marker->next_restart_num)) + return FALSE; } - /* Update next-restart state */ cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; return TRUE; } -/* - * This is the default resync_to_restart method for data source managers - * to use if they don't have any better approach. Some data source managers - * may be able to back up, or may have additional knowledge about the data - * which permits a more intelligent recovery strategy; such managers would - * presumably supply their own resync method. - * - * read_restart_marker calls resync_to_restart if it finds a marker other than - * the restart marker it was expecting. (This code is *not* used unless - * a nonzero restart interval has been declared.) cinfo->unread_marker is - * the marker code actually found (might be anything, except 0 or FF). - * The desired restart marker number (0..7) is passed as a parameter. - * This routine is supposed to apply whatever error recovery strategy seems - * appropriate in order to position the input stream to the next data segment. - * Note that cinfo->unread_marker is treated as a marker appearing before - * the current data-source input point; usually it should be reset to zero - * before returning. - * Returns FALSE if suspension is required. - * - * This implementation is substantially constrained by wanting to treat the - * input as a data stream; this means we can't back up. Therefore, we have - * only the following actions to work with: - * 1. Simply discard the marker and let the entropy decoder resume at next - * byte of file. - * 2. Read forward until we find another marker, discarding intervening - * data. (In theory we could look ahead within the current bufferload, - * without having to discard data if we don't find the desired marker. - * This idea is not implemented here, in part because it makes behavior - * dependent on buffer size and chance buffer-boundary positions.) - * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). - * This will cause the entropy decoder to process an empty data segment, - * inserting dummy zeroes, and then we will reprocess the marker. - * - * #2 is appropriate if we think the desired marker lies ahead, while #3 is - * appropriate if the found marker is a future restart marker (indicating - * that we have missed the desired restart marker, probably because it got - * corrupted). - * We apply #2 or #3 if the found marker is a restart marker no more than - * two counts behind or ahead of the expected one. We also apply #2 if the - * found marker is not a legal JPEG marker code (it's certainly bogus data). - * If the found marker is a restart marker more than 2 counts away, we do #1 - * (too much risk that the marker is erroneous; with luck we will be able to - * resync at some future point). - * For any valid non-restart JPEG marker, we apply #3. This keeps us from - * overrunning the end of a scan. An implementation limited to single-scan - * files might find it better to apply #2 for markers other than EOI, since - * any other marker would have to be bogus data in that case. - */ - GLOBAL(boolean) jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) { int marker = cinfo->unread_marker; int action = 1; - /* Always put up a warning. */ WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); - /* Outer loop handles repeated decision after scanning forward. */ for (;;) { - if (marker < (int) M_SOF0) - action = 2; /* invalid marker */ - else if (marker < (int) M_RST0 || marker > (int) M_RST7) - action = 3; /* valid non-restart marker */ - else { - if (marker == ((int) M_RST0 + ((desired+1) & 7)) || + if (marker < (int) M_SOF0) + action = 2; /* invalid marker */ + else if (marker < (int) M_RST0 || marker > (int) M_RST7) + action = 3; /* valid non-restart marker */ + else { + if (marker == ((int) M_RST0 + ((desired+1) & 7)) || marker == ((int) M_RST0 + ((desired+2) & 7))) action = 3; /* one of the next two expected restarts */ - else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || - marker == ((int) M_RST0 + ((desired-2) & 7))) + else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || + marker == ((int) M_RST0 + ((desired-2) & 7))) action = 2; /* a prior restart, so advance */ - else + else action = 1; /* desired restart or too far away */ - } - TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); - switch (action) { - case 1: - /* Discard marker and let entropy decoder resume processing. */ - cinfo->unread_marker = 0; - return TRUE; - case 2: - /* Scan to the next marker, and repeat the decision loop. */ - if (! next_marker(cinfo)) + } + TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); + switch (action) { + case 1: + cinfo->unread_marker = 0; + return TRUE; + case 2: + if (! next_marker(cinfo)) return FALSE; - marker = cinfo->unread_marker; - break; - case 3: - /* Return without advancing past this marker. */ - /* Entropy decoder will be forced to process an empty segment. */ - return TRUE; - } + marker = cinfo->unread_marker; + break; + case 3: + return TRUE; + } } /* end loop */ } -/* - * Reset marker processing state to begin a fresh datastream. - */ - METHODDEF(void) reset_marker_reader (j_decompress_ptr cinfo) { @@ -199371,46 +182816,30 @@ reset_marker_reader (j_decompress_ptr cinfo) marker->cur_marker = NULL; } -/* - * Initialize the marker reader module. - * This is called only once, when the decompression object is created. - */ - GLOBAL(void) jinit_marker_reader (j_decompress_ptr cinfo) { my_marker_ptr2 marker; int i; - /* Create subobject in permanent pool */ marker = (my_marker_ptr2) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_marker_reader)); cinfo->marker = (struct jpeg_marker_reader *) marker; - /* Initialize public method pointers */ marker->pub.reset_marker_reader = reset_marker_reader; marker->pub.read_markers = read_markers; marker->pub.read_restart_marker = read_restart_marker; - /* Initialize COM/APPn processing. - * By default, we examine and then discard APP0 and APP14, - * but simply discard COM and all other APPn. - */ marker->process_COM = skip_variable; marker->length_limit_COM = 0; for (i = 0; i < 16; i++) { - marker->process_APPn[i] = skip_variable; - marker->length_limit_APPn[i] = 0; + marker->process_APPn[i] = skip_variable; + marker->length_limit_APPn[i] = 0; } marker->process_APPn[0] = get_interesting_appn; marker->process_APPn[14] = get_interesting_appn; - /* Reset marker processing state */ reset_marker_reader(cinfo); } -/* - * Control saving of COM and APPn markers into marker_list. - */ - #ifdef SAVE_MARKERS_SUPPORTED GLOBAL(void) @@ -199421,46 +182850,34 @@ jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, long maxlength; jpeg_marker_parser_method processor; - /* Length limit mustn't be larger than what we can allocate - * (should only be a concern in a 16-bit environment). - */ maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); if (((long) length_limit) > maxlength) - length_limit = (unsigned int) maxlength; + length_limit = (unsigned int) maxlength; - /* Choose processor routine to use. - * APP0/APP14 have special requirements. - */ if (length_limit) { - processor = save_marker; - /* If saving APP0/APP14, save at least enough for our internal use. */ - if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) - length_limit = APP0_DATA_LEN; - else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) - length_limit = APP14_DATA_LEN; + processor = save_marker; + if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) + length_limit = APP0_DATA_LEN; + else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) + length_limit = APP14_DATA_LEN; } else { - processor = skip_variable; - /* If discarding APP0/APP14, use our regular on-the-fly processor. */ - if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) - processor = get_interesting_appn; + processor = skip_variable; + if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) + processor = get_interesting_appn; } if (marker_code == (int) M_COM) { - marker->process_COM = processor; - marker->length_limit_COM = length_limit; + marker->process_COM = processor; + marker->length_limit_COM = length_limit; } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { - marker->process_APPn[marker_code - (int) M_APP0] = processor; - marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; + marker->process_APPn[marker_code - (int) M_APP0] = processor; + marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; } else - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); } #endif /* SAVE_MARKERS_SUPPORTED */ -/* - * Install a special processing method for COM or APPn markers. - */ - GLOBAL(void) jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, jpeg_marker_parser_method routine) @@ -199468,19 +182885,17 @@ jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, my_marker_ptr2 marker = (my_marker_ptr2) cinfo->marker; if (marker_code == (int) M_COM) - marker->process_COM = routine; + marker->process_COM = routine; else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) - marker->process_APPn[marker_code - (int) M_APP0] = routine; + marker->process_APPn[marker_code - (int) M_APP0] = routine; else - ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); } /********* End of inlined file: jdmarker.c *********/ /********* Start of inlined file: jdmaster.c *********/ #define JPEG_INTERNALS -/* Private state */ - typedef struct { struct jpeg_decomp_master pub; /* public fields */ @@ -199488,261 +182903,159 @@ typedef struct { boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ - /* Saved references to initialized quantizer modules, - * in case we need to switch modes. - */ struct jpeg_color_quantizer * quantizer_1pass; struct jpeg_color_quantizer * quantizer_2pass; } my_decomp_master; typedef my_decomp_master * my_master_ptr6; -/* - * Determine whether merged upsample/color conversion should be used. - * CRUCIAL: this must match the actual capabilities of jdmerge.c! - */ - LOCAL(boolean) use_merged_upsample (j_decompress_ptr cinfo) { #ifdef UPSAMPLE_MERGING_SUPPORTED - /* Merging is the equivalent of plain box-filter upsampling */ if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) - return FALSE; - /* jdmerge.c only supports YCC=>RGB color conversion */ + return FALSE; if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || - cinfo->out_color_space != JCS_RGB || - cinfo->out_color_components != RGB_PIXELSIZE) - return FALSE; - /* and it only handles 2h1v or 2h2v sampling ratios */ + cinfo->out_color_space != JCS_RGB || + cinfo->out_color_components != RGB_PIXELSIZE) + return FALSE; if (cinfo->comp_info[0].h_samp_factor != 2 || - cinfo->comp_info[1].h_samp_factor != 1 || - cinfo->comp_info[2].h_samp_factor != 1 || - cinfo->comp_info[0].v_samp_factor > 2 || - cinfo->comp_info[1].v_samp_factor != 1 || - cinfo->comp_info[2].v_samp_factor != 1) - return FALSE; - /* furthermore, it doesn't work if we've scaled the IDCTs differently */ + cinfo->comp_info[1].h_samp_factor != 1 || + cinfo->comp_info[2].h_samp_factor != 1 || + cinfo->comp_info[0].v_samp_factor > 2 || + cinfo->comp_info[1].v_samp_factor != 1 || + cinfo->comp_info[2].v_samp_factor != 1) + return FALSE; if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size || - cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || - cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) - return FALSE; - /* ??? also need to test for upsample-time rescaling, when & if supported */ + cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || + cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) + return FALSE; return TRUE; /* by golly, it'll work... */ #else return FALSE; #endif } -/* - * Compute output image dimensions and related values. - * NOTE: this is exported for possible use by application. - * Hence it mustn't do anything that can't be done twice. - * Also note that it may be called before the master module is initialized! - */ - GLOBAL(void) jpeg_calc_output_dimensions (j_decompress_ptr cinfo) -/* Do computations that are needed before master selection phase */ { #ifdef IDCT_SCALING_SUPPORTED int ci; jpeg_component_info *compptr; #endif - /* Prevent application from calling me at wrong times */ if (cinfo->global_state != DSTATE_READY) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); #ifdef IDCT_SCALING_SUPPORTED - /* Compute actual output image dimensions and DCT scaling choices. */ if (cinfo->scale_num * 8 <= cinfo->scale_denom) { - /* Provide 1/8 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 8L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 8L); - cinfo->min_DCT_scaled_size = 1; + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 8L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 8L); + cinfo->min_DCT_scaled_size = 1; } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { - /* Provide 1/4 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 4L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 4L); - cinfo->min_DCT_scaled_size = 2; + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 4L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 4L); + cinfo->min_DCT_scaled_size = 2; } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { - /* Provide 1/2 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 2L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 2L); - cinfo->min_DCT_scaled_size = 4; + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 2L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 2L); + cinfo->min_DCT_scaled_size = 4; } else { - /* Provide 1/1 scaling */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - cinfo->min_DCT_scaled_size = DCTSIZE; + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + cinfo->min_DCT_scaled_size = DCTSIZE; } - /* In selecting the actual DCT scaling for each component, we try to - * scale up the chroma components via IDCT scaling rather than upsampling. - * This saves time if the upsampler gets to use 1:1 scaling. - * Note this code assumes that the supported DCT scalings are powers of 2. - */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - int ssize = cinfo->min_DCT_scaled_size; - while (ssize < DCTSIZE && + ci++, compptr++) { + int ssize = cinfo->min_DCT_scaled_size; + while (ssize < DCTSIZE && (compptr->h_samp_factor * ssize * 2 <= - cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && + cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && (compptr->v_samp_factor * ssize * 2 <= - cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { - ssize = ssize * 2; - } - compptr->DCT_scaled_size = ssize; + cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { + ssize = ssize * 2; + } + compptr->DCT_scaled_size = ssize; } - /* Recompute downsampled dimensions of components; - * application needs to know these if using raw downsampled data. - */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Size in samples, after IDCT scaling */ - compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * - (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), - (long) (cinfo->max_h_samp_factor * DCTSIZE)); - compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * - (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), - (long) (cinfo->max_v_samp_factor * DCTSIZE)); + ci++, compptr++) { + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * + (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * + (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), + (long) (cinfo->max_v_samp_factor * DCTSIZE)); } #else /* !IDCT_SCALING_SUPPORTED */ - /* Hardwire it to "no scaling" */ cinfo->output_width = cinfo->image_width; cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, - * and has computed unscaled downsampled_width and downsampled_height. - */ #endif /* IDCT_SCALING_SUPPORTED */ - /* Report number of components in selected colorspace. */ - /* Probably this should be in the color conversion module... */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: - cinfo->out_color_components = 1; - break; + cinfo->out_color_components = 1; + break; case JCS_RGB: #if RGB_PIXELSIZE != 3 - cinfo->out_color_components = RGB_PIXELSIZE; - break; + cinfo->out_color_components = RGB_PIXELSIZE; + break; #endif /* else share code with YCbCr */ case JCS_YCbCr: - cinfo->out_color_components = 3; - break; + cinfo->out_color_components = 3; + break; case JCS_CMYK: case JCS_YCCK: - cinfo->out_color_components = 4; - break; + cinfo->out_color_components = 4; + break; default: /* else must be same colorspace as in file */ - cinfo->out_color_components = cinfo->num_components; - break; + cinfo->out_color_components = cinfo->num_components; + break; } cinfo->output_components = (cinfo->quantize_colors ? 1 : - cinfo->out_color_components); + cinfo->out_color_components); - /* See if upsampler will want to emit more than one row at a time */ if (use_merged_upsample(cinfo)) - cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; + cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; else - cinfo->rec_outbuf_height = 1; + cinfo->rec_outbuf_height = 1; } -/* - * Several decompression processes need to range-limit values to the range - * 0..MAXJSAMPLE; the input value may fall somewhat outside this range - * due to noise introduced by quantization, roundoff error, etc. These - * processes are inner loops and need to be as fast as possible. On most - * machines, particularly CPUs with pipelines or instruction prefetch, - * a (subscript-check-less) C table lookup - * x = sample_range_limit[x]; - * is faster than explicit tests - * if (x < 0) x = 0; - * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; - * These processes all use a common table prepared by the routine below. - * - * For most steps we can mathematically guarantee that the initial value - * of x is within MAXJSAMPLE+1 of the legal range, so a table running from - * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial - * limiting step (just after the IDCT), a wildly out-of-range value is - * possible if the input data is corrupt. To avoid any chance of indexing - * off the end of memory and getting a bad-pointer trap, we perform the - * post-IDCT limiting thus: - * x = range_limit[x & MASK]; - * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit - * samples. Under normal circumstances this is more than enough range and - * a correct output will be generated; with bogus input data the mask will - * cause wraparound, and we will safely generate a bogus-but-in-range output. - * For the post-IDCT step, we want to convert the data from signed to unsigned - * representation by adding CENTERJSAMPLE at the same time that we limit it. - * So the post-IDCT limiting table ends up looking like this: - * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, - * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0,1,...,CENTERJSAMPLE-1 - * Negative inputs select values from the upper half of the table after - * masking. - * - * We can save some space by overlapping the start of the post-IDCT table - * with the simpler range limiting table. The post-IDCT table begins at - * sample_range_limit + CENTERJSAMPLE. - * - * Note that the table is allocated in near data space on PCs; it's small - * enough and used often enough to justify this. - */ - LOCAL(void) prepare_range_limit_table (j_decompress_ptr cinfo) -/* Allocate and fill in the sample_range_limit table */ { JSAMPLE * table; int i; table = (JSAMPLE *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ cinfo->sample_range_limit = table; - /* First segment of "simple" table: limit[x] = 0 for x < 0 */ MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); - /* Main part of "simple" table: limit[x] = x */ for (i = 0; i <= MAXJSAMPLE; i++) - table[i] = (JSAMPLE) i; + table[i] = (JSAMPLE) i; table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ - /* End of simple table, rest of first half of post-IDCT table */ for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) - table[i] = MAXJSAMPLE; - /* Second half of post-IDCT table */ + table[i] = MAXJSAMPLE; MEMZERO(table + (2 * (MAXJSAMPLE+1)), (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); } -/* - * Master selection of decompression modules. - * This is done once at jpeg_start_decompress time. We determine - * which modules will be used and give them appropriate initialization calls. - * We also initialize the decompressor input side to begin consuming data. - * - * Since jpeg_read_header has finished, we know what is in the SOF - * and (first) SOS markers. We also have all the application parameter - * settings. - */ - LOCAL(void) master_selection (j_decompress_ptr cinfo) { @@ -199751,147 +183064,114 @@ master_selection (j_decompress_ptr cinfo) long samplesperrow; JDIMENSION jd_samplesperrow; - /* Initialize dimensions and other stuff */ jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); - /* Width of an output scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; jd_samplesperrow = (JDIMENSION) samplesperrow; if ((long) jd_samplesperrow != samplesperrow) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - /* Initialize my private state */ master->pass_number = 0; master->using_merged_upsample = use_merged_upsample(cinfo); - /* Color quantizer selection */ master->quantizer_1pass = NULL; master->quantizer_2pass = NULL; - /* No mode changes if not using buffered-image mode. */ if (! cinfo->quantize_colors || ! cinfo->buffered_image) { - cinfo->enable_1pass_quant = FALSE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; } if (cinfo->quantize_colors) { - if (cinfo->raw_data_out) - ERREXIT(cinfo, JERR_NOTIMPL); - /* 2-pass quantizer only works in 3-component color space. */ - if (cinfo->out_color_components != 3) { - cinfo->enable_1pass_quant = TRUE; - cinfo->enable_external_quant = FALSE; - cinfo->enable_2pass_quant = FALSE; - cinfo->colormap = NULL; - } else if (cinfo->colormap != NULL) { - cinfo->enable_external_quant = TRUE; - } else if (cinfo->two_pass_quantize) { - cinfo->enable_2pass_quant = TRUE; - } else { - cinfo->enable_1pass_quant = TRUE; - } + if (cinfo->raw_data_out) + ERREXIT(cinfo, JERR_NOTIMPL); + if (cinfo->out_color_components != 3) { + cinfo->enable_1pass_quant = TRUE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + cinfo->colormap = NULL; + } else if (cinfo->colormap != NULL) { + cinfo->enable_external_quant = TRUE; + } else if (cinfo->two_pass_quantize) { + cinfo->enable_2pass_quant = TRUE; + } else { + cinfo->enable_1pass_quant = TRUE; + } - if (cinfo->enable_1pass_quant) { + if (cinfo->enable_1pass_quant) { #ifdef QUANT_1PASS_SUPPORTED - jinit_1pass_quantizer(cinfo); - master->quantizer_1pass = cinfo->cquantize; + jinit_1pass_quantizer(cinfo); + master->quantizer_1pass = cinfo->cquantize; #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif - } + } - /* We use the 2-pass code to map to external colormaps. */ - if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { + if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { #ifdef QUANT_2PASS_SUPPORTED - jinit_2pass_quantizer(cinfo); - master->quantizer_2pass = cinfo->cquantize; + jinit_2pass_quantizer(cinfo); + master->quantizer_2pass = cinfo->cquantize; #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif - } - /* If both quantizers are initialized, the 2-pass one is left active; - * this is necessary for starting with quantization to an external map. - */ + } } - /* Post-processing: in particular, color conversion first */ if (! cinfo->raw_data_out) { - if (master->using_merged_upsample) { + if (master->using_merged_upsample) { #ifdef UPSAMPLE_MERGING_SUPPORTED - jinit_merged_upsampler(cinfo); /* does color conversion too */ + jinit_merged_upsampler(cinfo); /* does color conversion too */ #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif - } else { - jinit_color_deconverter(cinfo); - jinit_upsampler(cinfo); - } - jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); } - /* Inverse DCT */ jinit_inverse_dct(cinfo); - /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); } else { - if (cinfo->progressive_mode) { + if (cinfo->progressive_mode) { #ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); + jinit_phuff_decoder(cinfo); #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif - } else - jinit_huff_decoder(cinfo); + } else + jinit_huff_decoder(cinfo); } - /* Initialize principal buffer controllers. */ use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; jinit_d_coef_controller(cinfo, use_c_buffer); if (! cinfo->raw_data_out) - jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); - /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - /* Initialize input side of decompressor to consume first scan. */ (*cinfo->inputctl->start_input_pass) (cinfo); #ifdef D_MULTISCAN_FILES_SUPPORTED - /* If jpeg_start_decompress will read the whole file, initialize - * progress monitoring appropriately. The input step is counted - * as one pass. - */ if (cinfo->progress != NULL && ! cinfo->buffered_image && - cinfo->inputctl->has_multiple_scans) { - int nscans; - /* Estimate number of scans to set pass_limit. */ - if (cinfo->progressive_mode) { - /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ - nscans = 2 + 3 * cinfo->num_components; - } else { - /* For a nonprogressive multiscan file, estimate 1 scan per component. */ - nscans = cinfo->num_components; - } - cinfo->progress->pass_counter = 0L; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; - cinfo->progress->completed_passes = 0; - cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); - /* Count the input pass as done */ - master->pass_number++; + cinfo->inputctl->has_multiple_scans) { + int nscans; + if (cinfo->progressive_mode) { + nscans = 2 + 3 * cinfo->num_components; + } else { + nscans = cinfo->num_components; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); + master->pass_number++; } #endif /* D_MULTISCAN_FILES_SUPPORTED */ } -/* - * Per-pass setup. - * This is called at the beginning of each output pass. We determine which - * modules will be active during this pass and give them appropriate - * start_pass calls. We also set is_dummy_pass to indicate whether this - * is a "real" output pass or a dummy pass for color quantization. - * (In the latter case, jdapistd.c will crank the pass to completion.) - */ - METHODDEF(void) prepare_for_output_pass (j_decompress_ptr cinfo) { @@ -199899,108 +183179,86 @@ prepare_for_output_pass (j_decompress_ptr cinfo) if (master->pub.is_dummy_pass) { #ifdef QUANT_2PASS_SUPPORTED - /* Final pass of 2-pass quantization */ - master->pub.is_dummy_pass = FALSE; - (*cinfo->cquantize->start_pass) (cinfo, FALSE); - (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); - (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); + master->pub.is_dummy_pass = FALSE; + (*cinfo->cquantize->start_pass) (cinfo, FALSE); + (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); + (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif /* QUANT_2PASS_SUPPORTED */ } else { - if (cinfo->quantize_colors && cinfo->colormap == NULL) { - /* Select new quantization method */ - if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { + if (cinfo->quantize_colors && cinfo->colormap == NULL) { + if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { cinfo->cquantize = master->quantizer_2pass; master->pub.is_dummy_pass = TRUE; - } else if (cinfo->enable_1pass_quant) { + } else if (cinfo->enable_1pass_quant) { cinfo->cquantize = master->quantizer_1pass; - } else { + } else { ERREXIT(cinfo, JERR_MODE_CHANGE); - } - } - (*cinfo->idct->start_pass) (cinfo); - (*cinfo->coef->start_output_pass) (cinfo); - if (! cinfo->raw_data_out) { - if (! master->using_merged_upsample) + } + } + (*cinfo->idct->start_pass) (cinfo); + (*cinfo->coef->start_output_pass) (cinfo); + if (! cinfo->raw_data_out) { + if (! master->using_merged_upsample) (*cinfo->cconvert->start_pass) (cinfo); - (*cinfo->upsample->start_pass) (cinfo); - if (cinfo->quantize_colors) + (*cinfo->upsample->start_pass) (cinfo); + if (cinfo->quantize_colors) (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); - (*cinfo->post->start_pass) (cinfo, - (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); - (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); - } + (*cinfo->post->start_pass) (cinfo, + (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + } } - /* Set up progress monitor's pass info if present */ if (cinfo->progress != NULL) { - cinfo->progress->completed_passes = master->pass_number; - cinfo->progress->total_passes = master->pass_number + - (master->pub.is_dummy_pass ? 2 : 1); - /* In buffered-image mode, we assume one more output pass if EOI not - * yet reached, but no more passes if EOI has been reached. - */ - if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { - cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); - } + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->pass_number + + (master->pub.is_dummy_pass ? 2 : 1); + if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { + cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); + } } } -/* - * Finish up at end of an output pass. - */ - METHODDEF(void) finish_output_pass (j_decompress_ptr cinfo) { my_master_ptr6 master = (my_master_ptr6) cinfo->master; if (cinfo->quantize_colors) - (*cinfo->cquantize->finish_pass) (cinfo); + (*cinfo->cquantize->finish_pass) (cinfo); master->pass_number++; } #ifdef D_MULTISCAN_FILES_SUPPORTED -/* - * Switch to a new external colormap between output passes. - */ - GLOBAL(void) jpeg_new_colormap (j_decompress_ptr cinfo) { my_master_ptr6 master = (my_master_ptr6) cinfo->master; - /* Prevent application from calling me at wrong times */ if (cinfo->global_state != DSTATE_BUFIMAGE) - ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->quantize_colors && cinfo->enable_external_quant && - cinfo->colormap != NULL) { - /* Select 2-pass quantizer for external colormap use */ - cinfo->cquantize = master->quantizer_2pass; - /* Notify quantizer of colormap change */ - (*cinfo->cquantize->new_color_map) (cinfo); - master->pub.is_dummy_pass = FALSE; /* just in case */ + cinfo->colormap != NULL) { + cinfo->cquantize = master->quantizer_2pass; + (*cinfo->cquantize->new_color_map) (cinfo); + master->pub.is_dummy_pass = FALSE; /* just in case */ } else - ERREXIT(cinfo, JERR_MODE_CHANGE); + ERREXIT(cinfo, JERR_MODE_CHANGE); } #endif /* D_MULTISCAN_FILES_SUPPORTED */ -/* - * Initialize master decompression control and select active modules. - * This is performed at the start of jpeg_start_decompress. - */ - GLOBAL(void) jinit_master_decompress (j_decompress_ptr cinfo) { my_master_ptr6 master; master = (my_master_ptr6) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_decomp_master)); cinfo->master = (struct jpeg_decomp_master *) master; master->pub.prepare_for_output_pass = prepare_for_output_pass; @@ -200012,34 +183270,25 @@ jinit_master_decompress (j_decompress_ptr cinfo) } /********* End of inlined file: jdmaster.c *********/ - #undef FIX + #undef FIX /********* Start of inlined file: jdmerge.c *********/ #define JPEG_INTERNALS #ifdef UPSAMPLE_MERGING_SUPPORTED -/* Private subobject */ - typedef struct { struct jpeg_upsampler pub; /* public fields */ - /* Pointer to routine to do actual upsampling/conversion of one row group */ JMETHOD(void, upmethod, (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)); - /* Private state for YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ INT32 * Cb_g_tab; /* => table for Cb to G conversion */ - /* For 2:1 vertical sampling, we produce two output rows at a time. - * We need a "spare" row buffer to hold the second output row if the - * application provides just a one-row buffer; we also use the spare - * to discard the dummy last row if the image height is odd. - */ JSAMPROW spare_row; boolean spare_full; /* T if spare buffer is occupied */ @@ -200053,11 +183302,6 @@ typedef my_upsampler * my_upsample_ptr; #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. - * This is taken directly from jdcolor.c; see that file for more info. - */ - LOCAL(void) build_ycc_rgb_table2 (j_decompress_ptr cinfo) { @@ -200067,139 +183311,95 @@ build_ycc_rgb_table2 (j_decompress_ptr cinfo) SHIFT_TEMPS upsample->Cr_r_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); upsample->Cb_b_tab = (int *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); upsample->Cr_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); upsample->Cb_g_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ - upsample->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ - upsample->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ - /* We also add in ONE_HALF so that need not do it in inner loop */ - upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; + upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; } } -/* - * Initialize for an upsampling pass. - */ - METHODDEF(void) start_pass_merged_upsample (j_decompress_ptr cinfo) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - /* Mark the spare buffer empty */ upsample->spare_full = FALSE; - /* Initialize total-height counter for detecting bottom of image */ upsample->rows_to_go = cinfo->output_height; } -/* - * Control routine to do upsampling (and color conversion). - * - * The control routine just handles the row buffering considerations. - */ - METHODDEF(void) merged_2v_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -/* 2:1 vertical sampling case: may need a spare row. */ + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; JSAMPROW work_ptrs[2]; JDIMENSION num_rows; /* number of rows returned to caller */ if (upsample->spare_full) { - /* If we have a spare row saved from a previous cycle, just return it. */ - jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, - 1, upsample->out_row_width); - num_rows = 1; - upsample->spare_full = FALSE; + jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, upsample->out_row_width); + num_rows = 1; + upsample->spare_full = FALSE; } else { - /* Figure number of rows to return to caller. */ - num_rows = 2; - /* Not more than the distance to the end of the image. */ - if (num_rows > upsample->rows_to_go) - num_rows = upsample->rows_to_go; - /* And not more than what the client can accept: */ - out_rows_avail -= *out_row_ctr; - if (num_rows > out_rows_avail) - num_rows = out_rows_avail; - /* Create output pointer array for upsampler. */ - work_ptrs[0] = output_buf[*out_row_ctr]; - if (num_rows > 1) { - work_ptrs[1] = output_buf[*out_row_ctr + 1]; - } else { - work_ptrs[1] = upsample->spare_row; - upsample->spare_full = TRUE; - } - /* Now do the upsampling. */ - (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); + num_rows = 2; + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + work_ptrs[0] = output_buf[*out_row_ctr]; + if (num_rows > 1) { + work_ptrs[1] = output_buf[*out_row_ctr + 1]; + } else { + work_ptrs[1] = upsample->spare_row; + upsample->spare_full = TRUE; + } + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); } - /* Adjust counts */ *out_row_ctr += num_rows; upsample->rows_to_go -= num_rows; - /* When the buffer is emptied, declare this input row group consumed */ if (! upsample->spare_full) - (*in_row_group_ctr)++; + (*in_row_group_ctr)++; } METHODDEF(void) merged_1v_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) -/* 1:1 vertical sampling case: much easier, never need a spare row. */ + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; - /* Just do the upsampling. */ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, output_buf + *out_row_ctr); - /* Adjust counts */ (*out_row_ctr)++; (*in_row_group_ctr)++; } -/* - * These are the routines invoked by the control routines to do - * the actual upsampling/conversion. One row group is processed per call. - * - * Note: since we may be writing directly into application-supplied buffers, - * we have to be honest about the output width; we can't assume the buffer - * has been rounded up to an even width. - */ - -/* - * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. - */ - METHODDEF(void) h2v1_merged_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; @@ -200207,7 +183407,6 @@ h2v1_merged_upsample (j_decompress_ptr cinfo, register JSAMPROW outptr; JSAMPROW inptr0, inptr1, inptr2; JDIMENSION col; - /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; int * Crrtab = upsample->Cr_r_tab; int * Cbbtab = upsample->Cb_b_tab; @@ -200219,48 +183418,40 @@ h2v1_merged_upsample (j_decompress_ptr cinfo, inptr1 = input_buf[1][in_row_group_ctr]; inptr2 = input_buf[2][in_row_group_ctr]; outptr = output_buf[0]; - /* Loop for each pair of output pixels */ for (col = cinfo->output_width >> 1; col > 0; col--) { - /* Do the chroma part of the calculation */ - cb = GETJSAMPLE(*inptr1++); - cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - /* Fetch 2 Y values and emit 2 pixels */ - y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - outptr += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; - outptr += RGB_PIXELSIZE; + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; } - /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { - cb = GETJSAMPLE(*inptr1); - cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - y = GETJSAMPLE(*inptr0); - outptr[RGB_RED] = range_limit[y + cred]; - outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; } } -/* - * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. - */ - METHODDEF(void) h2v2_merged_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; @@ -200268,7 +183459,6 @@ h2v2_merged_upsample (j_decompress_ptr cinfo, register JSAMPROW outptr0, outptr1; JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; - /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; int * Crrtab = upsample->Cr_r_tab; int * Cbbtab = upsample->Cb_b_tab; @@ -200282,69 +183472,57 @@ h2v2_merged_upsample (j_decompress_ptr cinfo, inptr2 = input_buf[2][in_row_group_ctr]; outptr0 = output_buf[0]; outptr1 = output_buf[1]; - /* Loop for each group of output pixels */ for (col = cinfo->output_width >> 1; col > 0; col--) { - /* Do the chroma part of the calculation */ - cb = GETJSAMPLE(*inptr1++); - cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - /* Fetch 4 Y values and emit 4 pixels */ - y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - outptr0 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - outptr0 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - outptr1 += RGB_PIXELSIZE; - y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; - outptr1 += RGB_PIXELSIZE; + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; } - /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { - cb = GETJSAMPLE(*inptr1); - cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; - cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; - y = GETJSAMPLE(*inptr00); - outptr0[RGB_RED] = range_limit[y + cred]; - outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; - y = GETJSAMPLE(*inptr01); - outptr1[RGB_RED] = range_limit[y + cred]; - outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + y = GETJSAMPLE(*inptr01); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; } } -/* - * Module initialization routine for merged upsampling/color conversion. - * - * NB: this is called under the conditions determined by use_merged_upsample() - * in jdmaster.c. That routine MUST correspond to the actual capabilities - * of this module; no safety checks are made here. - */ - GLOBAL(void) jinit_merged_upsampler (j_decompress_ptr cinfo) { my_upsample_ptr upsample; upsample = (my_upsample_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_upsampler)); cinfo->upsample = (struct jpeg_upsampler *) upsample; upsample->pub.start_pass = start_pass_merged_upsample; @@ -200353,17 +183531,15 @@ jinit_merged_upsampler (j_decompress_ptr cinfo) upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; if (cinfo->max_v_samp_factor == 2) { - upsample->pub.upsample = merged_2v_upsample; - upsample->upmethod = h2v2_merged_upsample; - /* Allocate a spare row buffer */ - upsample->spare_row = (JSAMPROW) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + upsample->pub.upsample = merged_2v_upsample; + upsample->upmethod = h2v2_merged_upsample; + upsample->spare_row = (JSAMPROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); } else { - upsample->pub.upsample = merged_1v_upsample; - upsample->upmethod = h2v1_merged_upsample; - /* No spare row needed */ - upsample->spare_row = NULL; + upsample->pub.upsample = merged_1v_upsample; + upsample->upmethod = h2v1_merged_upsample; + upsample->spare_row = NULL; } build_ycc_rgb_table2(cinfo); @@ -200372,30 +183548,18 @@ jinit_merged_upsampler (j_decompress_ptr cinfo) #endif /* UPSAMPLE_MERGING_SUPPORTED */ /********* End of inlined file: jdmerge.c *********/ - #undef ASSIGN_STATE + #undef ASSIGN_STATE /********* Start of inlined file: jdphuff.c *********/ #define JPEG_INTERNALS #ifdef D_PROGRESSIVE_SUPPORTED -/* - * Expanded entropy decoder object for progressive Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - typedef struct { unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state3; -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - #ifndef NO_STRUCT_ASSIGN #define ASSIGN_STATE(dest,src) ((dest) = (src)) #else @@ -200412,16 +183576,11 @@ typedef struct { typedef struct { struct jpeg_entropy_decoder pub; /* public fields */ - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ bitread_perm_state bitstate; /* Bit buffer at start of MCU */ savable_state3 saved; /* Other state at start of MCU */ - /* These fields are NOT loaded into local working state. */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ - /* Pointers to derived tables (these workspaces have image lifespan) */ d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ @@ -200429,19 +183588,14 @@ typedef struct { typedef phuff_entropy_decoder * phuff_entropy_ptr2; -/* Forward declarations */ METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); + JBLOCKROW *MCU_data)); METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); + JBLOCKROW *MCU_data)); METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); + JBLOCKROW *MCU_data)); METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); - -/* - * Initialize for a Huffman-compressed scan. - */ + JBLOCKROW *MCU_data)); METHODDEF(void) start_pass_phuff_decoder (j_decompress_ptr cinfo) @@ -200454,161 +183608,100 @@ start_pass_phuff_decoder (j_decompress_ptr cinfo) is_DC_band = (cinfo->Ss == 0); - /* Validate scan parameters */ bad = FALSE; if (is_DC_band) { - if (cinfo->Se != 0) - bad = TRUE; + if (cinfo->Se != 0) + bad = TRUE; } else { - /* need not check Ss/Se < 0 since they came from unsigned bytes */ - if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) - bad = TRUE; - /* AC scans may have only one component */ - if (cinfo->comps_in_scan != 1) - bad = TRUE; + if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) + bad = TRUE; + if (cinfo->comps_in_scan != 1) + bad = TRUE; } if (cinfo->Ah != 0) { - /* Successive approximation refinement scan: must have Al = Ah-1. */ - if (cinfo->Al != cinfo->Ah-1) - bad = TRUE; + if (cinfo->Al != cinfo->Ah-1) + bad = TRUE; } if (cinfo->Al > 13) /* need not check for < 0 */ - bad = TRUE; - /* Arguably the maximum Al value should be less than 13 for 8-bit precision, - * but the spec doesn't say so, and we try to be liberal about what we - * accept. Note: large Al values could result in out-of-range DC - * coefficients during early scans, leading to bizarre displays due to - * overflows in the IDCT math. But we won't crash. - */ + bad = TRUE; if (bad) - ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - /* Update progression status, and verify that scan order is legal. - * Note that inter-scan inconsistencies are treated as warnings - * not fatal errors ... not clear if this is right way to behave. - */ + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - int cindex = cinfo->cur_comp_info[ci]->component_index; - coef_bit_ptr = & cinfo->coef_bits[cindex][0]; - if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); - for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { - int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; - if (cinfo->Ah != expected) + int cindex = cinfo->cur_comp_info[ci]->component_index; + coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); - coef_bit_ptr[coefi] = cinfo->Al; - } + coef_bit_ptr[coefi] = cinfo->Al; + } } - /* Select MCU decoding routine */ if (cinfo->Ah == 0) { - if (is_DC_band) - entropy->pub.decode_mcu = decode_mcu_DC_first; - else - entropy->pub.decode_mcu = decode_mcu_AC_first; + if (is_DC_band) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; } else { - if (is_DC_band) - entropy->pub.decode_mcu = decode_mcu_DC_refine; - else - entropy->pub.decode_mcu = decode_mcu_AC_refine; + if (is_DC_band) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; } for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Make sure requested tables are present, and compute derived tables. - * We may build same derived table more than once, but it's not expensive. - */ - if (is_DC_band) { - if (cinfo->Ah == 0) { /* DC refinement needs no table */ + compptr = cinfo->cur_comp_info[ci]; + if (is_DC_band) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ tbl = compptr->dc_tbl_no; jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, & entropy->derived_tbls[tbl]); - } - } else { - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->derived_tbls[tbl]); - /* remember the single active table */ - entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + entropy->saved.last_dc_val[ci] = 0; } - /* Initialize bitread state variables */ entropy->bitstate.bits_left = 0; entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ entropy->pub.insufficient_data = FALSE; - /* Initialize private state variables */ entropy->saved.EOBRUN = 0; - /* Initialize restart counter */ entropy->restarts_to_go = cinfo->restart_interval; } -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - LOCAL(boolean) process_restartp (j_decompress_ptr cinfo) { phuff_entropy_ptr2 entropy = (phuff_entropy_ptr2) cinfo->entropy; int ci; - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; entropy->bitstate.bits_left = 0; - /* Advance past the RSTn marker */ if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; + return FALSE; - /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - /* Re-init EOB run count, too */ + entropy->saved.last_dc_val[ci] = 0; entropy->saved.EOBRUN = 0; - /* Reset restart counter */ entropy->restarts_to_go = cinfo->restart_interval; - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ if (cinfo->unread_marker == 0) - entropy->pub.insufficient_data = FALSE; + entropy->pub.insufficient_data = FALSE; return TRUE; } -/* - * Huffman MCU decoding. - * Each of these routines decodes and returns one MCU's worth of - * Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. - * - * We return FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * spectral selection, since we'll just re-assign them on the next call. - * Successive approximation AC refinement has to be more careful, however.) - */ - -/* - * MCU decoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - METHODDEF(boolean) decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -200622,63 +183715,44 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) d_derived_tbl * tbl; jpeg_component_info * compptr; - /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restartp(cinfo)) + if (entropy->restarts_to_go == 0) + if (! process_restartp(cinfo)) return FALSE; } - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ if (! entropy->pub.insufficient_data) { - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); - /* Outer loop handles each block in the MCU */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - tbl = entropy->derived_tbls[compptr->dc_tbl_no]; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, tbl, return FALSE, label1); - if (s) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); - } + } - /* Convert DC difference to actual value, update last_dc_val */ - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ - (*block)[0] = (JCOEF) (s << Al); - } + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + (*block)[0] = (JCOEF) (s << Al); + } - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); } - /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; } -/* - * MCU decoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - METHODDEF(boolean) decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -200691,33 +183765,24 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) BITREAD_STATE_VARS; d_derived_tbl * tbl; - /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restartp(cinfo)) + if (entropy->restarts_to_go == 0) + if (! process_restartp(cinfo)) return FALSE; } - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ if (! entropy->pub.insufficient_data) { - /* Load up working state. - * We can avoid loading/saving bitread state if in an EOB run. - */ - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - /* There is always only one block per MCU */ + if (EOBRUN > 0) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; - if (EOBRUN > 0) /* if it's a band of zeroes... */ - EOBRUN--; /* ...process it now (we do nothing) */ - else { - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - for (k = cinfo->Ss; k <= Se; k++) { + for (k = cinfo->Ss; k <= Se; k++) { HUFF_DECODE(s, br_state, tbl, return FALSE, label2); r = s >> 4; s &= 15; @@ -200726,43 +183791,34 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) CHECK_BIT_BUFFER(br_state, s, return FALSE); r = GET_BITS(s); s = HUFF_EXTEND(r, s); - /* Scale and output coefficient in natural (dezigzagged) order */ (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); } else { if (r == 15) { /* ZRL */ - k += 15; /* skip 15 zeroes in band */ + k += 15; /* skip 15 zeroes in band */ } else { /* EOBr, run length is 2^r + appended bits */ - EOBRUN = 1 << r; - if (r) { /* EOBr, r > 0 */ - CHECK_BIT_BUFFER(br_state, r, return FALSE); - r = GET_BITS(r); - EOBRUN += r; - } - EOBRUN--; /* this band is processed at this moment */ - break; /* force end-of-band */ + EOBRUN = 1 << r; + if (r) { /* EOBr, r > 0 */ + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += r; + } + EOBRUN--; /* this band is processed at this moment */ + break; /* force end-of-band */ } } - } + } - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - } + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } - /* Completed MCU, so update state */ - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ } - /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; } -/* - * MCU decoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. - */ - METHODDEF(boolean) decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -200772,45 +183828,29 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) JBLOCKROW block; BITREAD_STATE_VARS; - /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restartp(cinfo)) + if (entropy->restarts_to_go == 0) + if (! process_restartp(cinfo)) return FALSE; } - /* Not worth the cycles to check insufficient_data here, - * since we will not change the data anyway if we read zeroes. - */ - - /* Load up working state */ BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - /* Outer loop handles each block in the MCU */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; + block = MCU_data[blkn]; - /* Encoded data is simply the next bit of the two's-complement DC value */ - CHECK_BIT_BUFFER(br_state, 1, return FALSE); - if (GET_BITS(1)) - (*block)[0] |= p1; - /* Note: since we use |=, repeating the assignment later is safe */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + (*block)[0] |= p1; } - /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; } -/* - * MCU decoding for AC successive approximation refinement scan. - */ - METHODDEF(boolean) decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { @@ -200827,139 +183867,107 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) int num_newnz; int newnz_pos[DCTSIZE2]; - /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restartp(cinfo)) + if (entropy->restarts_to_go == 0) + if (! process_restartp(cinfo)) return FALSE; } - /* If we've run out of data, don't modify the MCU. - */ if (! entropy->pub.insufficient_data) { - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - /* There is always only one block per MCU */ - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; - /* If we are forced to suspend, we must undo the assignments to any newly - * nonzero coefficients in the block, because otherwise we'd get confused - * next time about which coefficients were already nonzero. - * But we need not undo addition of bits to already-nonzero coefficients; - * instead, we can test the current bit to see if we already did it. - */ - num_newnz = 0; + num_newnz = 0; - /* initialize coefficient loop counter to start of band */ - k = cinfo->Ss; + k = cinfo->Ss; - if (EOBRUN == 0) { - for (; k <= Se; k++) { + if (EOBRUN == 0) { + for (; k <= Se; k++) { HUFF_DECODE(s, br_state, tbl, goto undoit, label3); r = s >> 4; s &= 15; if (s) { if (s != 1) /* size of new coef should always be 1 */ - WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (GET_BITS(1)) - s = p1; /* newly nonzero coef is positive */ + s = p1; /* newly nonzero coef is positive */ else - s = m1; /* newly nonzero coef is negative */ + s = m1; /* newly nonzero coef is negative */ } else { if (r != 15) { - EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ - if (r) { - CHECK_BIT_BUFFER(br_state, r, goto undoit); - r = GET_BITS(r); - EOBRUN += r; - } - break; /* rest of block is handled by EOB logic */ + EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += r; + } + break; /* rest of block is handled by EOB logic */ } - /* note s = 0 for processing ZRL */ } - /* Advance over already-nonzero coefs and r still-zero coefs, - * appending correction bits to the nonzeroes. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ do { thiscoef = *block + jpeg_natural_order[k]; if (*thiscoef != 0) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ if (*thiscoef >= 0) *thiscoef += p1; else *thiscoef += m1; - } - } + } + } } else { - if (--r < 0) - break; /* reached target zero coefficient */ + if (--r < 0) + break; /* reached target zero coefficient */ } k++; } while (k <= Se); if (s) { int pos = jpeg_natural_order[k]; - /* Output newly nonzero coefficient */ (*block)[pos] = (JCOEF) s; - /* Remember its position in case we have to suspend */ newnz_pos[num_newnz++] = pos; } - } - } + } + } - if (EOBRUN > 0) { - /* Scan any remaining coefficient positions after the end-of-band - * (the last newly nonzero coefficient, if any). Append a correction - * bit to each already-nonzero coefficient. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - for (; k <= Se; k++) { + if (EOBRUN > 0) { + for (; k <= Se; k++) { thiscoef = *block + jpeg_natural_order[k]; if (*thiscoef != 0) { CHECK_BIT_BUFFER(br_state, 1, goto undoit); if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ - if (*thiscoef >= 0) + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) *thiscoef += p1; - else + else *thiscoef += m1; - } + } } } - } - /* Count one block completed in EOB run */ - EOBRUN--; - } + } + EOBRUN--; + } - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ } - /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; undoit: - /* Re-zero any output coefficients that we made newly nonzero */ while (num_newnz > 0) - (*block)[newnz_pos[--num_newnz]] = 0; + (*block)[newnz_pos[--num_newnz]] = 0; return FALSE; } -/* - * Module initialization routine for progressive Huffman entropy decoding. - */ - GLOBAL(void) jinit_phuff_decoder (j_decompress_ptr cinfo) { @@ -200968,24 +183976,22 @@ jinit_phuff_decoder (j_decompress_ptr cinfo) int ci, i; entropy = (phuff_entropy_ptr2) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(phuff_entropy_decoder)); cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; entropy->pub.start_pass = start_pass_phuff_decoder; - /* Mark derived tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; + entropy->derived_tbls[i] = NULL; } - /* Create progression status table */ cinfo->coef_bits = (int (*)[DCTSIZE2]) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components*DCTSIZE2*SIZEOF(int)); coef_bit_ptr = & cinfo->coef_bits[0][0]; for (ci = 0; ci < cinfo->num_components; ci++) - for (i = 0; i < DCTSIZE2; i++) - *coef_bit_ptr++ = -1; + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; } #endif /* D_PROGRESSIVE_SUPPORTED */ @@ -200994,52 +184000,39 @@ jinit_phuff_decoder (j_decompress_ptr cinfo) /********* Start of inlined file: jdpostct.c *********/ #define JPEG_INTERNALS -/* Private buffer controller object */ - typedef struct { struct jpeg_d_post_controller pub; /* public fields */ - /* Color quantization source buffer: this holds output data from - * the upsample/color conversion step to be passed to the quantizer. - * For two-pass color quantization, we need a full-image buffer; - * for one-pass operation, a strip buffer is sufficient. - */ jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ JDIMENSION strip_height; /* buffer size in rows */ - /* for two-pass mode only: */ JDIMENSION starting_row; /* row # of first row in current strip */ JDIMENSION next_row; /* index of next row to fill/empty in strip */ } my_post_controller; typedef my_post_controller * my_post_ptr; -/* Forward declarations */ METHODDEF(void) post_process_1pass JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) post_process_prepass JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); METHODDEF(void) post_process_2pass JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); #endif -/* - * Initialize for a processing pass. - */ - METHODDEF(void) start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { @@ -201047,71 +184040,53 @@ start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) switch (pass_mode) { case JBUF_PASS_THRU: - if (cinfo->quantize_colors) { - /* Single-pass processing with color quantization. */ - post->pub.post_process_data = post_process_1pass; - /* We could be doing buffered-image output before starting a 2-pass - * color quantization; in that case, jinit_d_post_controller did not - * allocate a strip buffer. Use the virtual-array buffer as workspace. - */ - if (post->buffer == NULL) { + if (cinfo->quantize_colors) { + post->pub.post_process_data = post_process_1pass; + if (post->buffer == NULL) { post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->whole_image, (JDIMENSION) 0, post->strip_height, TRUE); - } - } else { - /* For single-pass processing without color quantization, - * I have no work to do; just call the upsampler directly. - */ - post->pub.post_process_data = cinfo->upsample->upsample; - } - break; + } + } else { + post->pub.post_process_data = cinfo->upsample->upsample; + } + break; #ifdef QUANT_2PASS_SUPPORTED case JBUF_SAVE_AND_PASS: - /* First pass of 2-pass quantization */ - if (post->whole_image == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_prepass; - break; + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_prepass; + break; case JBUF_CRANK_DEST: - /* Second pass of 2-pass quantization */ - if (post->whole_image == NULL) - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - post->pub.post_process_data = post_process_2pass; - break; + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_2pass; + break; #endif /* QUANT_2PASS_SUPPORTED */ default: - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); - break; + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; } post->starting_row = post->next_row = 0; } -/* - * Process some data in the one-pass (strip buffer) case. - * This is used for color precision reduction as well as one-pass quantization. - */ - METHODDEF(void) post_process_1pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION num_rows, max_rows; - /* Fill the buffer, but not more than what we can dump out in one go. */ - /* Note we rely on the upsampler to detect bottom of image. */ max_rows = out_rows_avail - *out_row_ctr; if (max_rows > post->strip_height) - max_rows = post->strip_height; + max_rows = post->strip_height; num_rows = 0; (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, in_row_groups_avail, post->buffer, &num_rows, max_rows); - /* Quantize and emit data. */ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer, output_buf + *out_row_ctr, (int) num_rows); *out_row_ctr += num_rows; @@ -201119,275 +184094,191 @@ post_process_1pass (j_decompress_ptr cinfo, #ifdef QUANT_2PASS_SUPPORTED -/* - * Process some data in the first pass of 2-pass quantization. - */ - METHODDEF(void) post_process_prepass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION old_next_row, num_rows; - /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) + post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->whole_image, post->starting_row, post->strip_height, TRUE); } - /* Upsample some data (up to a strip height's worth). */ old_next_row = post->next_row; (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, in_row_groups_avail, post->buffer, &post->next_row, post->strip_height); - /* Allow quantizer to scan new data. No data is emitted, */ - /* but we advance out_row_ctr so outer loop can tell when we're done. */ if (post->next_row > old_next_row) { - num_rows = post->next_row - old_next_row; - (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, + num_rows = post->next_row - old_next_row; + (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, (JSAMPARRAY) NULL, (int) num_rows); - *out_row_ctr += num_rows; + *out_row_ctr += num_rows; } - /* Advance if we filled the strip. */ if (post->next_row >= post->strip_height) { - post->starting_row += post->strip_height; - post->next_row = 0; + post->starting_row += post->strip_height; + post->next_row = 0; } } -/* - * Process some data in the second pass of 2-pass quantization. - */ - METHODDEF(void) post_process_2pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION num_rows, max_rows; - /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { - post->buffer = (*cinfo->mem->access_virt_sarray) + post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->whole_image, post->starting_row, post->strip_height, FALSE); } - /* Determine number of rows to emit. */ num_rows = post->strip_height - post->next_row; /* available in strip */ max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ if (num_rows > max_rows) - num_rows = max_rows; - /* We have to check bottom of image here, can't depend on upsampler. */ + num_rows = max_rows; max_rows = cinfo->output_height - post->starting_row; if (num_rows > max_rows) - num_rows = max_rows; + num_rows = max_rows; - /* Quantize and emit data. */ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + post->next_row, output_buf + *out_row_ctr, (int) num_rows); *out_row_ctr += num_rows; - /* Advance if we filled the strip. */ post->next_row += num_rows; if (post->next_row >= post->strip_height) { - post->starting_row += post->strip_height; - post->next_row = 0; + post->starting_row += post->strip_height; + post->next_row = 0; } } #endif /* QUANT_2PASS_SUPPORTED */ -/* - * Initialize postprocessing controller. - */ - GLOBAL(void) jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_post_ptr post; post = (my_post_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_post_controller)); cinfo->post = (struct jpeg_d_post_controller *) post; post->pub.start_pass = start_pass_dpost; post->whole_image = NULL; /* flag for no virtual arrays */ post->buffer = NULL; /* flag for no strip buffer */ - /* Create the quantization buffer, if needed */ if (cinfo->quantize_colors) { - /* The buffer strip height is max_v_samp_factor, which is typically - * an efficient number of rows for upsampling to return. - * (In the presence of output rescaling, we might want to be smarter?) - */ - post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; - if (need_full_buffer) { - /* Two-pass color quantization: need full-image storage. */ - /* We round up the number of rows to a multiple of the strip height. */ + post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; + if (need_full_buffer) { #ifdef QUANT_2PASS_SUPPORTED - post->whole_image = (*cinfo->mem->request_virt_sarray) + post->whole_image = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, cinfo->output_width * cinfo->out_color_components, (JDIMENSION) jround_up((long) cinfo->output_height, (long) post->strip_height), post->strip_height); #else - ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif /* QUANT_2PASS_SUPPORTED */ - } else { - /* One-pass color quantization: just make a strip buffer. */ - post->buffer = (*cinfo->mem->alloc_sarray) + } else { + post->buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width * cinfo->out_color_components, post->strip_height); - } + } } } /********* End of inlined file: jdpostct.c *********/ - #undef FIX + #undef FIX /********* Start of inlined file: jdsample.c *********/ #define JPEG_INTERNALS -/* Pointer to routine to upsample a single component */ typedef JMETHOD(void, upsample1_ptr, (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); -/* Private subobject */ - typedef struct { struct jpeg_upsampler pub; /* public fields */ - /* Color conversion buffer. When using separate upsampling and color - * conversion steps, this buffer holds one upsampled row group until it - * has been color converted and output. - * Note: we do not allocate any storage for component(s) which are full-size, - * ie do not need rescaling. The corresponding entry of color_buf[] is - * simply set to point to the input data array, thereby avoiding copying. - */ JSAMPARRAY color_buf[MAX_COMPONENTS]; - /* Per-component upsampling method pointers */ upsample1_ptr methods[MAX_COMPONENTS]; int next_row_out; /* counts rows emitted from color_buf */ JDIMENSION rows_to_go; /* counts rows remaining in image */ - /* Height of an input row group for each component. */ int rowgroup_height[MAX_COMPONENTS]; - /* These arrays save pixel expansion factors so that int_expand need not - * recompute them each time. They are unused for other upsampling methods. - */ UINT8 h_expand[MAX_COMPONENTS]; UINT8 v_expand[MAX_COMPONENTS]; } my_upsampler2; typedef my_upsampler2 * my_upsample_ptr2; -/* - * Initialize for an upsampling pass. - */ - METHODDEF(void) start_pass_upsample (j_decompress_ptr cinfo) { my_upsample_ptr2 upsample = (my_upsample_ptr2) cinfo->upsample; - /* Mark the conversion buffer empty */ upsample->next_row_out = cinfo->max_v_samp_factor; - /* Initialize total-height counter for detecting bottom of image */ upsample->rows_to_go = cinfo->output_height; } -/* - * Control routine to do upsampling (and color conversion). - * - * In this version we upsample each component independently. - * We upsample one row group into the conversion buffer, then apply - * color conversion a row at a time. - */ - METHODDEF(void) sep_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_upsample_ptr2 upsample = (my_upsample_ptr2) cinfo->upsample; int ci; jpeg_component_info * compptr; JDIMENSION num_rows; - /* Fill the conversion buffer, if it's empty */ if (upsample->next_row_out >= cinfo->max_v_samp_factor) { - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - /* Invoke per-component upsample method. Notice we pass a POINTER - * to color_buf[ci], so that fullsize_upsample can change it. - */ - (*upsample->methods[ci]) (cinfo, compptr, + (*upsample->methods[ci]) (cinfo, compptr, input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), upsample->color_buf + ci); - } - upsample->next_row_out = 0; + } + upsample->next_row_out = 0; } - /* Color-convert and emit rows */ - - /* How many we have in the buffer: */ num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); - /* Not more than the distance to the end of the image. Need this test - * in case the image height is not a multiple of max_v_samp_factor: - */ if (num_rows > upsample->rows_to_go) - num_rows = upsample->rows_to_go; - /* And not more than what the client can accept: */ + num_rows = upsample->rows_to_go; out_rows_avail -= *out_row_ctr; if (num_rows > out_rows_avail) - num_rows = out_rows_avail; + num_rows = out_rows_avail; (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, - (JDIMENSION) upsample->next_row_out, - output_buf + *out_row_ctr, - (int) num_rows); + (JDIMENSION) upsample->next_row_out, + output_buf + *out_row_ctr, + (int) num_rows); - /* Adjust counts */ *out_row_ctr += num_rows; upsample->rows_to_go -= num_rows; upsample->next_row_out += num_rows; - /* When the buffer is emptied, declare this input row group consumed */ if (upsample->next_row_out >= cinfo->max_v_samp_factor) - (*in_row_group_ctr)++; + (*in_row_group_ctr)++; } -/* - * These are the routines invoked by sep_upsample to upsample pixel values - * of a single component. One row group is processed per call. - */ - -/* - * For full-size components, we just make color_buf[ci] point at the - * input buffer, and thus avoid copying any data. Note that this is - * safe only because sep_upsample doesn't declare the input row group - * "consumed" until we are done color converting and emitting it. - */ - METHODDEF(void) fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) @@ -201395,32 +184286,16 @@ fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, *output_data_ptr = input_data; } -/* - * This is a no-op version used for "uninteresting" components. - * These components will not be referenced by color conversion. - */ - METHODDEF(void) noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { *output_data_ptr = NULL; /* safety check */ } -/* - * This version handles any integral sampling ratios. - * This is not used for typical JPEG files, so it need not be fast. - * Nor, for that matter, is it particularly accurate: the algorithm is - * simple replication of the input pixel onto the corresponding output - * pixels. The hi-falutin sampling literature refers to this as a - * "box filter". A box filter tends to introduce visible artifacts, - * so if you are actually going to use 3:1 or 4:1 sampling ratios - * you would be well advised to improve this code. - */ - METHODDEF(void) int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { my_upsample_ptr2 upsample = (my_upsample_ptr2) cinfo->upsample; JSAMPARRAY output_data = *output_data_ptr; @@ -201436,34 +184311,27 @@ int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, inrow = outrow = 0; while (outrow < cinfo->max_v_samp_factor) { - /* Generate one output row with proper horizontal expansion */ - inptr = input_data[inrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - for (h = h_expand; h > 0; h--) { + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + for (h = h_expand; h > 0; h--) { *outptr++ = invalue; - } - } - /* Generate any additional output rows by duplicating the first one */ - if (v_expand > 1) { - jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + } + } + if (v_expand > 1) { + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, v_expand-1, cinfo->output_width); - } - inrow++; - outrow += v_expand; + } + inrow++; + outrow += v_expand; } } -/* - * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. - * It's still a box filter. - */ - METHODDEF(void) h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; @@ -201472,25 +184340,20 @@ h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, int inrow; for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - *outptr++ = invalue; - *outptr++ = invalue; - } + inptr = input_data[inrow]; + outptr = output_data[inrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } } } -/* - * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. - * It's still a box filter. - */ - METHODDEF(void) h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; @@ -201500,39 +184363,24 @@ h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, inrow = outrow = 0; while (outrow < cinfo->max_v_samp_factor) { - inptr = input_data[inrow]; - outptr = output_data[outrow]; - outend = outptr + cinfo->output_width; - while (outptr < outend) { - invalue = *inptr++; /* don't need GETJSAMPLE() here */ - *outptr++ = invalue; - *outptr++ = invalue; - } - jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - 1, cinfo->output_width); - inrow++; - outrow += 2; + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + 1, cinfo->output_width); + inrow++; + outrow += 2; } } -/* - * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. - * - * The upsampling algorithm is linear interpolation between pixel centers, - * also known as a "triangle filter". This is a good compromise between - * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 - * of the way between input pixel centers. - * - * A note about the "bias" calculations: when rounding fractional values to - * integer, we do not want to always round 0.5 up to the next integer. - * If we did that, we'd introduce a noticeable bias towards larger values. - * Instead, this code is arranged so that 0.5 will be rounded up or down at - * alternate pixel locations (a simple ordered dither pattern). - */ - METHODDEF(void) h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; @@ -201541,38 +184389,27 @@ h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, int inrow; for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; - /* Special case for first column */ - invalue = GETJSAMPLE(*inptr++); - *outptr++ = (JSAMPLE) invalue; - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); + inptr = input_data[inrow]; + outptr = output_data[inrow]; + invalue = GETJSAMPLE(*inptr++); + *outptr++ = (JSAMPLE) invalue; + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ - invalue = GETJSAMPLE(*inptr++) * 3; - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); - } + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + invalue = GETJSAMPLE(*inptr++) * 3; + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); + } - /* Special case for last column */ - invalue = GETJSAMPLE(*inptr); - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); - *outptr++ = (JSAMPLE) invalue; + invalue = GETJSAMPLE(*inptr); + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); + *outptr++ = (JSAMPLE) invalue; } } -/* - * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. - * Again a triangle filter; see comments for h2v1 case, above. - * - * It is OK for us to reference the adjacent input rows because we demanded - * context from the main buffer controller (see initialization code). - */ - METHODDEF(void) h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr0, inptr1, outptr; @@ -201586,43 +184423,34 @@ h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, inrow = outrow = 0; while (outrow < cinfo->max_v_samp_factor) { - for (v = 0; v < 2; v++) { - /* inptr0 points to nearest input row, inptr1 points to next nearest */ - inptr0 = input_data[inrow]; - if (v == 0) /* next nearest is row above */ + for (v = 0; v < 2; v++) { + inptr0 = input_data[inrow]; + if (v == 0) /* next nearest is row above */ inptr1 = input_data[inrow-1]; - else /* next nearest is row below */ + else /* next nearest is row below */ inptr1 = input_data[inrow+1]; - outptr = output_data[outrow++]; + outptr = output_data[outrow++]; - /* Special case for first column */ - thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; + thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ - /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; - } + } - /* Special case for last column */ - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); - } - inrow++; + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); + } + inrow++; } } -/* - * Module initialization routine for upsampling. - */ - GLOBAL(void) jinit_upsampler (j_decompress_ptr cinfo) { @@ -201633,7 +184461,7 @@ jinit_upsampler (j_decompress_ptr cinfo) int h_in_group, v_in_group, h_out_group, v_out_group; upsample = (my_upsample_ptr2) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_upsampler2)); cinfo->upsample = (struct jpeg_upsampler *) upsample; upsample->pub.start_pass = start_pass_upsample; @@ -201641,67 +184469,53 @@ jinit_upsampler (j_decompress_ptr cinfo) upsample->pub.need_context_rows = FALSE; /* until we find out differently */ if (cinfo->CCIR601_sampling) /* this isn't supported */ - ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); - /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, - * so don't ask for it. - */ do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; - /* Verify we can handle the sampling factors, select per-component methods, - * and create storage as needed. - */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - /* Compute size of an "input group" after IDCT scaling. This many samples - * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. - */ - h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / + ci++, compptr++) { + h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; - v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; - h_out_group = cinfo->max_h_samp_factor; - v_out_group = cinfo->max_v_samp_factor; - upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ - need_buffer = TRUE; - if (! compptr->component_needed) { - /* Don't bother to upsample an uninteresting component. */ - upsample->methods[ci] = noop_upsample; - need_buffer = FALSE; - } else if (h_in_group == h_out_group && v_in_group == v_out_group) { - /* Fullsize components can be processed without any work. */ - upsample->methods[ci] = fullsize_upsample; - need_buffer = FALSE; - } else if (h_in_group * 2 == h_out_group && - v_in_group == v_out_group) { - /* Special cases for 2h1v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) + h_out_group = cinfo->max_h_samp_factor; + v_out_group = cinfo->max_v_samp_factor; + upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ + need_buffer = TRUE; + if (! compptr->component_needed) { + upsample->methods[ci] = noop_upsample; + need_buffer = FALSE; + } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + upsample->methods[ci] = fullsize_upsample; + need_buffer = FALSE; + } else if (h_in_group * 2 == h_out_group && + v_in_group == v_out_group) { + if (do_fancy && compptr->downsampled_width > 2) upsample->methods[ci] = h2v1_fancy_upsample; - else + else upsample->methods[ci] = h2v1_upsample; - } else if (h_in_group * 2 == h_out_group && - v_in_group * 2 == v_out_group) { - /* Special cases for 2h2v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) { + } else if (h_in_group * 2 == h_out_group && + v_in_group * 2 == v_out_group) { + if (do_fancy && compptr->downsampled_width > 2) { upsample->methods[ci] = h2v2_fancy_upsample; upsample->pub.need_context_rows = TRUE; - } else + } else upsample->methods[ci] = h2v2_upsample; - } else if ((h_out_group % h_in_group) == 0 && - (v_out_group % v_in_group) == 0) { - /* Generic integral-factors upsampling method */ - upsample->methods[ci] = int_upsample; - upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); - upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); - } else - ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); - if (need_buffer) { - upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + } else if ((h_out_group % h_in_group) == 0 && + (v_out_group % v_in_group) == 0) { + upsample->methods[ci] = int_upsample; + upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); + upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + if (need_buffer) { + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) jround_up((long) cinfo->output_width, (long) cinfo->max_h_samp_factor), (JDIMENSION) cinfo->max_v_samp_factor); - } + } } } /********* End of inlined file: jdsample.c *********/ @@ -201709,128 +184523,79 @@ jinit_upsampler (j_decompress_ptr cinfo) /********* Start of inlined file: jdtrans.c *********/ #define JPEG_INTERNALS -/* Forward declarations */ LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); -/* - * Read the coefficient arrays from a JPEG file. - * jpeg_read_header must be completed before calling this. - * - * The entire image is read into a set of virtual coefficient-block arrays, - * one per component. The return value is a pointer to the array of - * virtual-array descriptors. These can be manipulated directly via the - * JPEG memory manager, or handed off to jpeg_write_coefficients(). - * To release the memory occupied by the virtual arrays, call - * jpeg_finish_decompress() when done with the data. - * - * An alternative usage is to simply obtain access to the coefficient arrays - * during a buffered-image-mode decompression operation. This is allowed - * after any jpeg_finish_output() call. The arrays can be accessed until - * jpeg_finish_decompress() is called. (Note that any call to the library - * may reposition the arrays, so don't rely on access_virt_barray() results - * to stay valid across library calls.) - * - * Returns NULL if suspended. This case need be checked only if - * a suspending data source is used. - */ - GLOBAL(jvirt_barray_ptr *) jpeg_read_coefficients (j_decompress_ptr cinfo) { if (cinfo->global_state == DSTATE_READY) { - /* First call: initialize active modules */ - transdecode_master_selection(cinfo); - cinfo->global_state = DSTATE_RDCOEFS; + transdecode_master_selection(cinfo); + cinfo->global_state = DSTATE_RDCOEFS; } if (cinfo->global_state == DSTATE_RDCOEFS) { - /* Absorb whole file into the coef buffer */ - for (;;) { - int retcode; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) + for (;;) { + int retcode; + if (cinfo->progress != NULL) (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - /* Absorb some more input */ - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_SUSPENDED) + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) return NULL; - if (retcode == JPEG_REACHED_EOI) + if (retcode == JPEG_REACHED_EOI) break; - /* Advance progress counter if appropriate */ - if (cinfo->progress != NULL && + if (cinfo->progress != NULL && (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* startup underestimated number of scans; ratchet up one scan */ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; } - } - } - /* Set state so that jpeg_finish_decompress does the right thing */ - cinfo->global_state = DSTATE_STOPPING; + } + } + cinfo->global_state = DSTATE_STOPPING; } - /* At this point we should be in state DSTATE_STOPPING if being used - * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access - * to the coefficients during a full buffered-image-mode decompression. - */ if ((cinfo->global_state == DSTATE_STOPPING || - cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { - return cinfo->coef->coef_arrays; + cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { + return cinfo->coef->coef_arrays; } - /* Oops, improper usage */ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); return NULL; /* keep compiler happy */ } -/* - * Master selection of decompression modules for transcoding. - * This substitutes for jdmaster.c's initialization of the full decompressor. - */ - LOCAL(void) transdecode_master_selection (j_decompress_ptr cinfo) { - /* This is effectively a buffered-image operation. */ cinfo->buffered_image = TRUE; - /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); } else { - if (cinfo->progressive_mode) { + if (cinfo->progressive_mode) { #ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); + jinit_phuff_decoder(cinfo); #else - ERREXIT(cinfo, JERR_NOT_COMPILED); + ERREXIT(cinfo, JERR_NOT_COMPILED); #endif - } else - jinit_huff_decoder(cinfo); + } else + jinit_huff_decoder(cinfo); } - /* Always get a full-image coefficient buffer. */ jinit_d_coef_controller(cinfo, TRUE); - /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); - /* Initialize input side of decompressor to consume first scan. */ (*cinfo->inputctl->start_input_pass) (cinfo); - /* Initialize progress monitoring. */ if (cinfo->progress != NULL) { - int nscans; - /* Estimate number of scans to set pass_limit. */ - if (cinfo->progressive_mode) { - /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ - nscans = 2 + 3 * cinfo->num_components; - } else if (cinfo->inputctl->has_multiple_scans) { - /* For a nonprogressive multiscan file, estimate 1 scan per component. */ - nscans = cinfo->num_components; - } else { - nscans = 1; - } - cinfo->progress->pass_counter = 0L; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; - cinfo->progress->completed_passes = 0; - cinfo->progress->total_passes = 1; + int nscans; + if (cinfo->progressive_mode) { + nscans = 2 + 3 * cinfo->num_components; + } else if (cinfo->inputctl->has_multiple_scans) { + nscans = cinfo->num_components; + } else { + nscans = 1; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = 1; } } /********* End of inlined file: jdtrans.c *********/ @@ -201840,18 +184605,10 @@ transdecode_master_selection (j_decompress_ptr cinfo) #ifdef DCT_FLOAT_SUPPORTED -/* - * This module is specialized to the case DCTSIZE = 8. - */ - #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif -/* - * Perform the forward DCT on one block of samples. - */ - GLOBAL(void) jpeg_fdct_float (FAST_FLOAT * data) { @@ -201861,104 +184618,90 @@ jpeg_fdct_float (FAST_FLOAT * data) FAST_FLOAT *dataptr; int ctr; - /* Pass 1: process rows. */ - dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; - /* Even part */ + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; - dataptr[0] = tmp10 + tmp11; /* phase 3 */ - dataptr[4] = tmp10 - tmp11; + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; - z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ - dataptr[2] = tmp13 + z1; /* phase 5 */ - dataptr[6] = tmp13 - z1; + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; - /* Odd part */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ - z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ - z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ - z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[5] = z13 + z2; /* phase 6 */ - dataptr[3] = z13 - z2; - dataptr[1] = z11 + z4; - dataptr[7] = z11 - z4; - - dataptr += DCTSIZE; /* advance pointer to next row */ + dataptr += DCTSIZE; /* advance pointer to next row */ } - /* Pass 2: process columns. */ - dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - /* Even part */ + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; - dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ - dataptr[DCTSIZE*4] = tmp10 - tmp11; + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; - z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ - dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ - dataptr[DCTSIZE*6] = tmp13 - z1; + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; - /* Odd part */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ - z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ - z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ - z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ - dataptr[DCTSIZE*3] = z13 - z2; - dataptr[DCTSIZE*1] = z11 + z4; - dataptr[DCTSIZE*7] = z11 - z4; - - dataptr++; /* advance pointer to next column */ + dataptr++; /* advance pointer to next column */ } } @@ -201970,48 +184713,10 @@ jpeg_fdct_float (FAST_FLOAT * data) #ifdef DCT_ISLOW_SUPPORTED -/* - * This module is specialized to the case DCTSIZE = 8. - */ - #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif -/* - * The poop on this scaling stuff is as follows: - * - * Each 1-D DCT step produces outputs which are a factor of sqrt(N) - * larger than the true DCT outputs. The final outputs are therefore - * a factor of N larger than desired; since N=8 this can be cured by - * a simple right shift at the end of the algorithm. The advantage of - * this arrangement is that we save two multiplications per 1-D DCT, - * because the y0 and y4 outputs need not be divided by sqrt(N). - * In the IJG code, this factor of 8 is removed by the quantization step - * (in jcdctmgr.c), NOT in this module. - * - * We have to do addition and subtraction of the integer inputs, which - * is no problem, and multiplication by fractional constants, which is - * a problem to do in integer arithmetic. We multiply all the constants - * by CONST_SCALE and convert them to integer constants (thus retaining - * CONST_BITS bits of precision in the constants). After doing a - * multiplication we have to divide the product by CONST_SCALE, with proper - * rounding, to produce the correct output. This division can be done - * cheaply as a right shift of CONST_BITS bits. We postpone shifting - * as long as possible so that partial sums can be added together with - * full fractional precision. - * - * The outputs of the first pass are scaled up by PASS1_BITS bits so that - * they are represented to better-than-integral precision. These outputs - * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word - * with the recommended scaling. (For 12-bit sample data, the intermediate - * array is INT32 anyway.) - * - * To avoid overflow of the 32-bit intermediate results in pass 2, we must - * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis - * shows that the values given below are the most effective. - */ - #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 @@ -202020,13 +184725,6 @@ jpeg_fdct_float (FAST_FLOAT * data) #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - #if CONST_BITS == 13 #define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ #define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ @@ -202055,23 +184753,12 @@ jpeg_fdct_float (FAST_FLOAT * data) #define FIX_3_072711026 FIX(3.072711026) #endif -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - #if BITS_IN_JSAMPLE == 8 #define MULTIPLY(var,const) MULTIPLY16C16(var,const) #else #define MULTIPLY(var,const) ((var) * (const)) #endif -/* - * Perform the forward DCT on one block of samples. - */ - GLOBAL(void) jpeg_fdct_islow (DCTELEM * data) { @@ -202082,187 +184769,131 @@ jpeg_fdct_islow (DCTELEM * data) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; - /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". - */ + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); - dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); - dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), CONST_BITS-PASS1_BITS); - dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), CONST_BITS-PASS1_BITS); - /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents cos(K*pi/16). - * i0..i3 in the paper are tmp4..tmp7 here. - */ + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - z1 = tmp4 + tmp7; - z2 = tmp5 + tmp6; - z3 = tmp4 + tmp6; - z4 = tmp5 + tmp7; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z3 += z5; + z4 += z5; - z3 += z5; - z4 += z5; + dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); - dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); - dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); - dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); - dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); - - dataptr += DCTSIZE; /* advance pointer to next row */ + dataptr += DCTSIZE; /* advance pointer to next row */ } - /* Pass 2: process columns. - * We remove the PASS1_BITS scaling, but leave the results scaled up - * by an overall factor of 8. - */ - dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". - */ + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); - dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); - dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); - - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), CONST_BITS+PASS1_BITS); - /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents cos(K*pi/16). - * i0..i3 in the paper are tmp4..tmp7 here. - */ + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - z1 = tmp4 + tmp7; - z2 = tmp5 + tmp6; - z3 = tmp4 + tmp6; - z4 = tmp5 + tmp7; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z3 += z5; + z4 += z5; - z3 += z5; - z4 += z5; - - dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS+PASS1_BITS); - dataptr++; /* advance pointer to next column */ + dataptr++; /* advance pointer to next column */ } } #endif /* DCT_ISLOW_SUPPORTED */ /********* End of inlined file: jfdctint.c *********/ - #undef CONST_BITS - #undef MULTIPLY - #undef FIX_0_541196100 + #undef CONST_BITS + #undef MULTIPLY + #undef FIX_0_541196100 /********* Start of inlined file: jfdctfst.c *********/ #define JPEG_INTERNALS #ifdef DCT_IFAST_SUPPORTED -/* - * This module is specialized to the case DCTSIZE = 8. - */ - #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif -/* Scaling decisions are generally the same as in the LL&M algorithm; - * see jfdctint.c for more details. However, we choose to descale - * (right shift) multiplication products as soon as they are formed, - * rather than carrying additional fractional bits into subsequent additions. - * This compromises accuracy slightly, but it lets us save a few shifts. - * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) - * everywhere except in the multiplications proper; this saves a good deal - * of work on 16-bit-int machines. - * - * Again to save a few shifts, the intermediate results between pass 1 and - * pass 2 are not upscaled, but are represented only to integral precision. - * - * A final compromise is to represent the multiplicative constants to only - * 8 fractional bits, rather than 13. This saves some shifting work on some - * machines, and may also reduce the cost of multiplication (since there - * are fewer one-bits in the constants). - */ - #define CONST_BITS 8 -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - #if CONST_BITS == 8 #define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ #define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ @@ -202275,26 +184906,13 @@ jpeg_fdct_islow (DCTELEM * data) #define FIX_1_306562965 FIX(1.306562965) #endif -/* We can gain a little more speed, with a further compromise in accuracy, - * by omitting the addition in a descaling shift. This yields an incorrectly - * rounded result half the time... - */ - #ifndef USE_ACCURATE_ROUNDING #undef DESCALE #define DESCALE(x,n) RIGHT_SHIFT(x, n) #endif -/* Multiply a DCTELEM variable by an INT32 constant, and immediately - * descale to yield a DCTELEM result. - */ - #define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) -/* - * Perform the forward DCT on one block of samples. - */ - GLOBAL(void) jpeg_fdct_ifast (DCTELEM * data) { @@ -202305,135 +184923,109 @@ jpeg_fdct_ifast (DCTELEM * data) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; - /* Even part */ + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; - dataptr[0] = tmp10 + tmp11; /* phase 3 */ - dataptr[4] = tmp10 - tmp11; + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ - dataptr[2] = tmp13 + z1; /* phase 5 */ - dataptr[6] = tmp13 - z1; + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; - /* Odd part */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ - z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ - z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ - z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[5] = z13 + z2; /* phase 6 */ - dataptr[3] = z13 - z2; - dataptr[1] = z11 + z4; - dataptr[7] = z11 - z4; - - dataptr += DCTSIZE; /* advance pointer to next row */ + dataptr += DCTSIZE; /* advance pointer to next row */ } - /* Pass 2: process columns. */ - dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - /* Even part */ + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; - tmp10 = tmp0 + tmp3; /* phase 2 */ - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; - dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ - dataptr[DCTSIZE*4] = tmp10 - tmp11; + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ - dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ - dataptr[DCTSIZE*6] = tmp13 - z1; + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; - /* Odd part */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ - tmp10 = tmp4 + tmp5; /* phase 2 */ - tmp11 = tmp5 + tmp6; - tmp12 = tmp6 + tmp7; + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; - /* The rotator is modified from fig 4-8 to avoid extra negations. */ - z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ - z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ - z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ - z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; - z11 = tmp7 + z3; /* phase 5 */ - z13 = tmp7 - z3; - - dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ - dataptr[DCTSIZE*3] = z13 - z2; - dataptr[DCTSIZE*1] = z11 + z4; - dataptr[DCTSIZE*7] = z11 - z4; - - dataptr++; /* advance pointer to next column */ + dataptr++; /* advance pointer to next column */ } } #endif /* DCT_IFAST_SUPPORTED */ /********* End of inlined file: jfdctfst.c *********/ - #undef FIX_0_541196100 + #undef FIX_0_541196100 /********* Start of inlined file: jidctflt.c *********/ #define JPEG_INTERNALS #ifdef DCT_FLOAT_SUPPORTED -/* - * This module is specialized to the case DCTSIZE = 8. - */ - #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce a float result. - */ - #define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) -/* - * Perform dequantization and inverse DCT on one block of coefficients. - */ - GLOBAL(void) jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, @@ -202451,210 +185043,153 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS - /* Pass 1: process columns from input, store into work array. */ - inptr = coef_block; quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } - /* Even part */ + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - /* Odd part */ + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; - tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; - z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*4] = tmp3 + tmp4; + wsptr[DCTSIZE*3] = tmp3 - tmp4; - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - wsptr[DCTSIZE*0] = tmp0 + tmp7; - wsptr[DCTSIZE*7] = tmp0 - tmp7; - wsptr[DCTSIZE*1] = tmp1 + tmp6; - wsptr[DCTSIZE*6] = tmp1 - tmp6; - wsptr[DCTSIZE*2] = tmp2 + tmp5; - wsptr[DCTSIZE*5] = tmp2 - tmp5; - wsptr[DCTSIZE*4] = tmp3 + tmp4; - wsptr[DCTSIZE*3] = tmp3 - tmp4; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; } - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3. */ - wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * And testing floats for zero is relatively expensive, so we don't bother. - */ + outptr = output_buf[ctr] + output_col; - /* Even part */ + tmp10 = wsptr[0] + wsptr[4]; + tmp11 = wsptr[0] - wsptr[4]; - tmp10 = wsptr[0] + wsptr[4]; - tmp11 = wsptr[0] - wsptr[4]; + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; - tmp13 = wsptr[2] + wsptr[6]; - tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; - /* Odd part */ + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); - z13 = wsptr[5] + wsptr[3]; - z10 = wsptr[5] - wsptr[3]; - z11 = wsptr[1] + wsptr[7]; - z12 = wsptr[1] - wsptr[7]; + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ - tmp7 = z11 + z13; - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; - z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) + & RANGE_MASK]; - tmp6 = tmp12 - tmp7; - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - /* Final output stage: scale down by a factor of 8 and range-limit */ - - outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ + wsptr += DCTSIZE; /* advance pointer to next row */ } } #endif /* DCT_FLOAT_SUPPORTED */ /********* End of inlined file: jidctflt.c *********/ - #undef CONST_BITS - #undef FIX_1_847759065 - #undef MULTIPLY - #undef DEQUANTIZE - #undef DESCALE + #undef CONST_BITS + #undef FIX_1_847759065 + #undef MULTIPLY + #undef DEQUANTIZE + #undef DESCALE /********* Start of inlined file: jidctfst.c *********/ #define JPEG_INTERNALS #ifdef DCT_IFAST_SUPPORTED -/* - * This module is specialized to the case DCTSIZE = 8. - */ - #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif -/* Scaling decisions are generally the same as in the LL&M algorithm; - * see jidctint.c for more details. However, we choose to descale - * (right shift) multiplication products as soon as they are formed, - * rather than carrying additional fractional bits into subsequent additions. - * This compromises accuracy slightly, but it lets us save a few shifts. - * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) - * everywhere except in the multiplications proper; this saves a good deal - * of work on 16-bit-int machines. - * - * The dequantized coefficients are not integers because the AA&N scaling - * factors have been incorporated. We represent them scaled up by PASS1_BITS, - * so that the first and second IDCT rounds have the same input scaling. - * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to - * avoid a descaling shift; this compromises accuracy rather drastically - * for small quantization table entries, but it saves a lot of shifts. - * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, - * so we use a much larger scaling factor to preserve accuracy. - * - * A final compromise is to represent the multiplicative constants to only - * 8 fractional bits, rather than 13. This saves some shifting work on some - * machines, and may also reduce the cost of multiplication (since there - * are fewer one-bits in the constants). - */ - #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 8 #define PASS1_BITS 2 @@ -202663,13 +185198,6 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - #if CONST_BITS == 8 #define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ #define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ @@ -202682,28 +185210,13 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, #define FIX_2_613125930 FIX(2.613125930) #endif -/* We can gain a little more speed, with a further compromise in accuracy, - * by omitting the addition in a descaling shift. This yields an incorrectly - * rounded result half the time... - */ - #ifndef USE_ACCURATE_ROUNDING #undef DESCALE #define DESCALE(x,n) RIGHT_SHIFT(x, n) #endif -/* Multiply a DCTELEM variable by an INT32 constant, and immediately - * descale to yield a DCTELEM result. - */ - #define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 - * multiplication will do. For 12-bit data, the multiplier table is - * declared INT32, so a 32-bit multiply will be used. - */ - #if BITS_IN_JSAMPLE == 8 #define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) #else @@ -202711,10 +185224,6 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) #endif -/* Like DESCALE, but applies to a DCTELEM and produces an int. - * We assume that int right shift is unsigned if INT32 right shift is. - */ - #ifdef RIGHT_SHIFT_IS_UNSIGNED #define ISHIFT_TEMPS DCTELEM ishift_temp; #if BITS_IN_JSAMPLE == 8 @@ -202723,9 +185232,9 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, #define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ #endif #define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ - (ishift_temp >> (shft))) + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) #else #define ISHIFT_TEMPS #define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) @@ -202737,10 +185246,6 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, #define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) #endif -/* - * Perform dequantization and inverse DCT on one block of coefficients. - */ - GLOBAL(void) jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, @@ -202759,242 +185264,173 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, SHIFT_TEMPS /* for DESCALE */ ISHIFT_TEMPS /* for IDESCALE */ - /* Pass 1: process columns from input, store into work array. */ - inptr = coef_block; quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } - /* Even part */ + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - /* Odd part */ + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; - tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); + wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); + wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); + wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); + wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); + wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); + wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); - wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); - wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); - wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); - wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); - wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); - wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); - wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; } - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ - wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ + outptr = output_buf[ctr] + output_col; #ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) + JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) & RANGE_MASK]; - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - outptr[4] = dcval; - outptr[5] = dcval; - outptr[6] = dcval; - outptr[7] = dcval; + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } #endif - /* Even part */ + tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); + tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); - tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); - tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) + - tmp13; - tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); - tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) - - tmp13; + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; + z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; + z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; + z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; + z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; - /* Odd part */ + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; - z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; - z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; - z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + & RANGE_MASK]; - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - /* Final output stage: scale down by a factor of 8 and range-limit */ - - outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ + wsptr += DCTSIZE; /* advance pointer to next row */ } } #endif /* DCT_IFAST_SUPPORTED */ /********* End of inlined file: jidctfst.c *********/ - #undef CONST_BITS - #undef FIX_1_847759065 - #undef MULTIPLY - #undef DEQUANTIZE + #undef CONST_BITS + #undef FIX_1_847759065 + #undef MULTIPLY + #undef DEQUANTIZE /********* Start of inlined file: jidctint.c *********/ #define JPEG_INTERNALS #ifdef DCT_ISLOW_SUPPORTED -/* - * This module is specialized to the case DCTSIZE = 8. - */ - #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif -/* - * The poop on this scaling stuff is as follows: - * - * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) - * larger than the true IDCT outputs. The final outputs are therefore - * a factor of N larger than desired; since N=8 this can be cured by - * a simple right shift at the end of the algorithm. The advantage of - * this arrangement is that we save two multiplications per 1-D IDCT, - * because the y0 and y4 inputs need not be divided by sqrt(N). - * - * We have to do addition and subtraction of the integer inputs, which - * is no problem, and multiplication by fractional constants, which is - * a problem to do in integer arithmetic. We multiply all the constants - * by CONST_SCALE and convert them to integer constants (thus retaining - * CONST_BITS bits of precision in the constants). After doing a - * multiplication we have to divide the product by CONST_SCALE, with proper - * rounding, to produce the correct output. This division can be done - * cheaply as a right shift of CONST_BITS bits. We postpone shifting - * as long as possible so that partial sums can be added together with - * full fractional precision. - * - * The outputs of the first pass are scaled up by PASS1_BITS bits so that - * they are represented to better-than-integral precision. These outputs - * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word - * with the recommended scaling. (To scale up 12-bit sample data further, an - * intermediate INT32 array would be needed.) - * - * To avoid overflow of the 32-bit intermediate results in pass 2, we must - * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis - * shows that the values given below are the most effective. - */ - #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 @@ -203003,13 +185439,6 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - #if CONST_BITS == 13 #define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ #define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ @@ -203038,30 +185467,14 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, #define FIX_3_072711026 FIX(3.072711026) #endif -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - #if BITS_IN_JSAMPLE == 8 #define MULTIPLY(var,const) MULTIPLY16C16(var,const) #else #define MULTIPLY(var,const) ((var) * (const)) #endif -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce an int result. In this module, both inputs and result - * are 16 bits or less, so either int or short multiply will work. - */ - #define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) -/* - * Perform dequantization and inverse DCT on one block of coefficients. - */ - GLOBAL(void) jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, @@ -203079,228 +185492,185 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS - /* Pass 1: process columns from input, store into work array. */ - /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); - tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; - tmp0 = (z2 + z3) << CONST_BITS; - tmp1 = (z2 - z3) << CONST_BITS; + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - z1 = tmp0 + tmp3; - z2 = tmp1 + tmp2; - z3 = tmp0 + tmp2; - z4 = tmp1 + tmp3; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + z3 += z5; + z4 += z5; - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; - z3 += z5; - z4 += z5; + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; } - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ - wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { - outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ + outptr = output_buf[ctr] + output_col; #ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) & RANGE_MASK]; - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - outptr[4] = dcval; - outptr[5] = dcval; - outptr[6] = dcval; - outptr[7] = dcval; + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } #endif - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); - tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; + tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; - tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; - tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; - /* Odd part per figure 8; the matrix is unitary and hence its - * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. - */ + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - tmp0 = (INT32) wsptr[7]; - tmp1 = (INT32) wsptr[5]; - tmp2 = (INT32) wsptr[3]; - tmp3 = (INT32) wsptr[1]; + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - z1 = tmp0 + tmp3; - z2 = tmp1 + tmp2; - z3 = tmp0 + tmp2; - z4 = tmp1 + tmp3; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + z3 += z5; + z4 += z5; - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; - - /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + & RANGE_MASK]; - wsptr += DCTSIZE; /* advance pointer to next row */ + wsptr += DCTSIZE; /* advance pointer to next row */ } } @@ -203312,16 +185682,10 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, #ifdef IDCT_SCALING_SUPPORTED -/* - * This module is specialized to the case DCTSIZE = 8. - */ - #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif -/* Scaling is the same as in jidctint.c. */ - #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 @@ -203330,13 +185694,6 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - #if CONST_BITS == 13 #define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ #define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ @@ -203369,35 +185726,18 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, #define FIX_3_624509785 FIX(3.624509785) #endif -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - #if BITS_IN_JSAMPLE == 8 #define MULTIPLY(var,const) MULTIPLY16C16(var,const) #else #define MULTIPLY(var,const) ((var) * (const)) #endif -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce an int result. In this module, both inputs and result - * are 16 bits or less, so either int or short multiply will work. - */ - #define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 4x4 output block. - */ - GLOBAL(void) jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; INT32 z1, z2, z3, z4; @@ -203410,146 +185750,121 @@ jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, int workspace[DCTSIZE*4]; /* buffers data between passes */ SHIFT_TEMPS - /* Pass 1: process columns from input, store into work array. */ - inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { - /* Don't bother to process column 4, because second pass won't use it */ - if (ctr == DCTSIZE-4) - continue; - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + if (ctr == DCTSIZE-4) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero; we need not examine term 4 for 4x4 output */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; - continue; - } + continue; + } - /* Even part */ + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= (CONST_BITS+1); - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= (CONST_BITS+1); + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); - tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; - tmp10 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ - tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ - /* Final output stage */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); } - /* Pass 2: process 4 rows from work array, store into output array. */ - wsptr = workspace; for (ctr = 0; ctr < 4; ctr++) { - outptr = output_buf[ctr] + output_col; - /* It's not clear whether a zero row test is worthwhile here ... */ + outptr = output_buf[ctr] + output_col; #ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) & RANGE_MASK]; - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } #endif - /* Even part */ + tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); - tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); - - tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) + tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); - tmp10 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; - /* Odd part */ + z1 = (INT32) wsptr[7]; + z2 = (INT32) wsptr[5]; + z3 = (INT32) wsptr[3]; + z4 = (INT32) wsptr[1]; - z1 = (INT32) wsptr[7]; - z2 = (INT32) wsptr[5]; - z3 = (INT32) wsptr[3]; - z4 = (INT32) wsptr[1]; - - tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ - tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ - /* Final output stage */ + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ + wsptr += DCTSIZE; /* advance pointer to next row */ } } -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 2x2 output block. - */ - GLOBAL(void) jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp10, z1; JCOEFPTR inptr; @@ -203561,111 +185876,83 @@ jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, int workspace[DCTSIZE*2]; /* buffers data between passes */ SHIFT_TEMPS - /* Pass 1: process columns from input, store into work array. */ - inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { - /* Don't bother to process columns 2,4,6 */ - if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) - continue; - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && + if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; - continue; - } + continue; + } - /* Even part */ + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 = z1 << (CONST_BITS+2); - z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp10 = z1 << (CONST_BITS+2); + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - - /* Final output stage */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); } - /* Pass 2: process 2 rows from work array, store into output array. */ - wsptr = workspace; for (ctr = 0; ctr < 2; ctr++) { - outptr = output_buf[ctr] + output_col; - /* It's not clear whether a zero row test is worthwhile here ... */ + outptr = output_buf[ctr] + output_col; #ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) & RANGE_MASK]; - outptr[0] = dcval; - outptr[1] = dcval; + outptr[0] = dcval; + outptr[1] = dcval; - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } #endif - /* Even part */ + tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); - tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); - - /* Odd part */ - - tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - /* Final output stage */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3+2) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3+2) - & RANGE_MASK]; + & RANGE_MASK]; - wsptr += DCTSIZE; /* advance pointer to next row */ + wsptr += DCTSIZE; /* advance pointer to next row */ } } -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 1x1 output block. - */ - GLOBAL(void) jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { int dcval; ISLOW_MULT_TYPE * quantptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); SHIFT_TEMPS - /* We hardly need an inverse DCT routine for this: just take the - * average pixel value, which is one-eighth of the DC coefficient. - */ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; dcval = DEQUANTIZE(coef_block[0], quantptr[0]); dcval = (int) DESCALE((INT32) dcval, 3); @@ -203684,8 +185971,6 @@ jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, #ifndef __jmemsys_h__ #define __jmemsys_h__ -/* Short forms of external names for systems with brain-damaged linkers. */ - #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_get_small jGetSmall #define jpeg_free_small jFreeSmall @@ -203697,84 +185982,23 @@ jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, #define jpeg_mem_term jMemTerm #endif /* NEED_SHORT_EXTERNAL_NAMES */ -/* - * These two functions are used to allocate and release small chunks of - * memory. (Typically the total amount requested through jpeg_get_small is - * no more than 20K or so; this will be requested in chunks of a few K each.) - * Behavior should be the same as for the standard library functions malloc - * and free; in particular, jpeg_get_small must return NULL on failure. - * On most systems, these ARE malloc and free. jpeg_free_small is passed the - * size of the object being freed, just in case it's needed. - * On an 80x86 machine using small-data memory model, these manage near heap. - */ - EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, size_t sizeofobject)); -/* - * These two functions are used to allocate and release large chunks of - * memory (up to the total free space designated by jpeg_mem_available). - * The interface is the same as above, except that on an 80x86 machine, - * far pointers are used. On most other machines these are identical to - * the jpeg_get/free_small routines; but we keep them separate anyway, - * in case a different allocation strategy is desirable for large chunks. - */ - EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, - size_t sizeofobject)); + size_t sizeofobject)); EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, size_t sizeofobject)); -/* - * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may - * be requested in a single call to jpeg_get_large (and jpeg_get_small for that - * matter, but that case should never come into play). This macro is needed - * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. - * On those machines, we expect that jconfig.h will provide a proper value. - * On machines with 32-bit flat address spaces, any large constant may be used. - * - * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type - * size_t and will be a multiple of sizeof(align_type). - */ - #ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ #define MAX_ALLOC_CHUNK 1000000000L #endif -/* - * This routine computes the total space still available for allocation by - * jpeg_get_large. If more space than this is needed, backing store will be - * used. NOTE: any memory already allocated must not be counted. - * - * There is a minimum space requirement, corresponding to the minimum - * feasible buffer sizes; jmemmgr.c will request that much space even if - * jpeg_mem_available returns zero. The maximum space needed, enough to hold - * all working storage in memory, is also passed in case it is useful. - * Finally, the total space already allocated is passed. If no better - * method is available, cinfo->mem->max_memory_to_use - already_allocated - * is often a suitable calculation. - * - * It is OK for jpeg_mem_available to underestimate the space available - * (that'll just lead to more backing-store access than is really necessary). - * However, an overestimate will lead to failure. Hence it's wise to subtract - * a slop factor from the true available space. 5% should be enough. - * - * On machines with lots of virtual memory, any large constant may be returned. - * Conversely, zero may be returned to always use the minimum amount of memory. - */ - EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, - long min_bytes_needed, - long max_bytes_needed, - long already_allocated)); - -/* - * This structure holds whatever state is needed to access a single - * backing-store object. The read/write/close method pointers are called - * by jmemmgr.c to manipulate the backing-store object; all other fields - * are private to the system-dependent backing store routines. - */ + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); #define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ @@ -203798,129 +186022,59 @@ typedef union { //typedef struct backing_store_struct * backing_store_ptr; typedef struct backing_store_struct { - /* Methods for reading/writing/closing this backing-store object */ JMETHOD(void, read_backing_store, (j_common_ptr cinfo, - struct backing_store_struct *info, - void FAR * buffer_address, - long file_offset, long byte_count)); + struct backing_store_struct *info, + void FAR * buffer_address, + long file_offset, long byte_count)); JMETHOD(void, write_backing_store, (j_common_ptr cinfo, - struct backing_store_struct *info, - void FAR * buffer_address, - long file_offset, long byte_count)); + struct backing_store_struct *info, + void FAR * buffer_address, + long file_offset, long byte_count)); JMETHOD(void, close_backing_store, (j_common_ptr cinfo, - struct backing_store_struct *info)); + struct backing_store_struct *info)); - /* Private fields for system-dependent backing-store management */ #ifdef USE_MSDOS_MEMMGR - /* For the MS-DOS manager (jmemdos.c), we need: */ handle_union handle; /* reference to backing-store storage object */ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ #else #ifdef USE_MAC_MEMMGR - /* For the Mac manager (jmemmac.c), we need: */ short temp_file; /* file reference number to temp file */ FSSpec tempSpec; /* the FSSpec for the temp file */ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ #else - /* For a typical implementation with temp files, we need: */ FILE * temp_file; /* stdio reference to temp file */ char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ #endif #endif } backing_store_info; -/* - * Initial opening of a backing-store object. This must fill in the - * read/write/close pointers in the object. The read/write routines - * may take an error exit if the specified maximum file size is exceeded. - * (If jpeg_mem_available always returns a large value, this routine can - * just take an error exit.) - */ - EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, struct backing_store_struct *info, long total_bytes_needed)); -/* - * These routines take care of any system-dependent initialization and - * cleanup required. jpeg_mem_init will be called before anything is - * allocated (and, therefore, nothing in cinfo is of use except the error - * manager pointer). It should return a suitable default value for - * max_memory_to_use; this may subsequently be overridden by the surrounding - * application. (Note that max_memory_to_use is only important if - * jpeg_mem_available chooses to consult it ... no one else will.) - * jpeg_mem_term may assume that all requested memory has been freed and that - * all opened backing-store objects have been closed. - */ - EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); #endif /********* End of inlined file: jmemsys.h *********/ - /* import the system-dependent declarations */ - #ifndef NO_GETENV #ifndef HAVE_STDLIB_H /* should declare getenv() */ extern char * getenv JPP((const char * name)); #endif #endif -/* - * Some important notes: - * The allocation routines provided here must never return NULL. - * They should exit to error_exit if unsuccessful. - * - * It's not a good idea to try to merge the sarray and barray routines, - * even though they are textually almost the same, because samples are - * usually stored as bytes while coefficients are shorts or ints. Thus, - * in machines where byte pointers have a different representation from - * word pointers, the resulting machine code could not be the same. - */ - -/* - * Many machines require storage alignment: longs must start on 4-byte - * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() - * always returns pointers that are multiples of the worst-case alignment - * requirement, and we had better do so too. - * There isn't any really portable way to determine the worst-case alignment - * requirement. This module assumes that the alignment requirement is - * multiples of sizeof(ALIGN_TYPE). - * By default, we define ALIGN_TYPE as double. This is necessary on some - * workstations (where doubles really do need 8-byte alignment) and will work - * fine on nearly everything. If your machine has lesser alignment needs, - * you can save a few bytes by making ALIGN_TYPE smaller. - * The only place I know of where this will NOT work is certain Macintosh - * 680x0 compilers that define double as a 10-byte IEEE extended float. - * Doing 10-byte alignment is counterproductive because longwords won't be - * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have - * such a compiler. - */ - #ifndef ALIGN_TYPE /* so can override from jconfig.h */ #define ALIGN_TYPE double #endif -/* - * We allocate objects from "pools", where each pool is gotten with a single - * request to jpeg_get_small() or jpeg_get_large(). There is no per-object - * overhead within a pool, except for alignment padding. Each pool has a - * header with a link to the next pool of the same class. - * Small and large pool headers are identical except that the latter's - * link pointer must be FAR on 80x86 machines. - * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE - * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple - * of the alignment requirement of ALIGN_TYPE. - */ - typedef union small_pool_struct * small_pool_ptr; typedef union small_pool_struct { struct { - small_pool_ptr next; /* next in list of pools */ - size_t bytes_used; /* how many bytes already used within pool */ - size_t bytes_left; /* bytes still available in this pool */ + small_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ } hdr; ALIGN_TYPE dummy; /* included in union to ensure alignment */ } small_pool_hdr; @@ -203929,50 +186083,29 @@ typedef union large_pool_struct FAR * large_pool_ptr; typedef union large_pool_struct { struct { - large_pool_ptr next; /* next in list of pools */ - size_t bytes_used; /* how many bytes already used within pool */ - size_t bytes_left; /* bytes still available in this pool */ + large_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ } hdr; ALIGN_TYPE dummy; /* included in union to ensure alignment */ } large_pool_hdr; -/* - * Here is the full definition of a memory manager object. - */ - typedef struct { struct jpeg_memory_mgr pub; /* public fields */ - /* Each pool identifier (lifetime class) names a linked list of pools. */ small_pool_ptr small_list[JPOOL_NUMPOOLS]; large_pool_ptr large_list[JPOOL_NUMPOOLS]; - /* Since we only have one lifetime class of virtual arrays, only one - * linked list is necessary (for each datatype). Note that the virtual - * array control blocks being linked together are actually stored somewhere - * in the small-pool list. - */ jvirt_sarray_ptr virt_sarray_list; jvirt_barray_ptr virt_barray_list; - /* This counts total space obtained from jpeg_get_small/large */ long total_space_allocated; - /* alloc_sarray and alloc_barray set this value for use by virtual - * array routines. - */ JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ } my_memory_mgr; typedef my_memory_mgr * my_mem_ptr; -/* - * The control blocks for virtual arrays. - * Note that these blocks are allocated in the "small" pool area. - * System-dependent info for the associated backing store (if any) is hidden - * inside the backing_store_info struct. - */ - struct jvirt_sarray_control { JSAMPARRAY mem_buffer; /* => the in-memory buffer */ JDIMENSION rows_in_array; /* total virtual array height */ @@ -204014,24 +186147,20 @@ print_mem_stats (j_common_ptr cinfo, int pool_id) small_pool_ptr shdr_ptr; large_pool_ptr lhdr_ptr; - /* Since this is only a debugging stub, we can cheat a little by using - * fprintf directly rather than going through the trace message code. - * This is helpful because message parm array can't handle longs. - */ fprintf(stderr, "Freeing pool %d, total space = %ld\n", pool_id, mem->total_space_allocated); for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; - lhdr_ptr = lhdr_ptr->hdr.next) { - fprintf(stderr, " Large chunk used %ld\n", - (long) lhdr_ptr->hdr.bytes_used); + lhdr_ptr = lhdr_ptr->hdr.next) { + fprintf(stderr, " Large chunk used %ld\n", + (long) lhdr_ptr->hdr.bytes_used); } for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; - shdr_ptr = shdr_ptr->hdr.next) { - fprintf(stderr, " Small chunk used %ld free %ld\n", - (long) shdr_ptr->hdr.bytes_used, - (long) shdr_ptr->hdr.bytes_left); + shdr_ptr = shdr_ptr->hdr.next) { + fprintf(stderr, " Small chunk used %ld free %ld\n", + (long) shdr_ptr->hdr.bytes_used, + (long) shdr_ptr->hdr.bytes_left); } } @@ -204039,8 +186168,6 @@ print_mem_stats (j_common_ptr cinfo, int pool_id) LOCAL(void) out_of_memory (j_common_ptr cinfo, int which) -/* Report an out-of-memory error and stop execution */ -/* If we compiled MEM_STATS support, report alloc requests before dying */ { #ifdef MEM_STATS cinfo->err->trace_level = 2; /* force self_destruct to report stats */ @@ -204048,19 +186175,6 @@ out_of_memory (j_common_ptr cinfo, int which) ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); } -/* - * Allocation of "small" objects. - * - * For these, we use pooled storage. When a new pool must be created, - * we try to get enough space for the current request plus a "slop" factor, - * where the slop will be the amount of leftover space in the new pool. - * The speed vs. space tradeoff is largely determined by the slop values. - * A different slop value is provided for each pool class (lifetime), - * and we also distinguish the first pool of a class from later ones. - * NOTE: the values given work fairly well on both 16- and 32-bit-int - * machines, but may be too small if longs are 64 bits or more. - */ - static const size_t first_pool_slop[JPOOL_NUMPOOLS] = { 1600, /* first PERMANENT pool */ @@ -204077,66 +186191,56 @@ static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = METHODDEF(void *) alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) -/* Allocate a "small" object */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; small_pool_ptr hdr_ptr, prev_hdr_ptr; char * data_ptr; size_t odd_bytes, min_request, slop; - /* Check for unsatisfiable request (do now to ensure no overflow below) */ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) - out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ + out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ - /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); if (odd_bytes > 0) - sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; - /* See if space is available in any existing pool */ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ prev_hdr_ptr = NULL; hdr_ptr = mem->small_list[pool_id]; while (hdr_ptr != NULL) { - if (hdr_ptr->hdr.bytes_left >= sizeofobject) - break; /* found pool with enough space */ - prev_hdr_ptr = hdr_ptr; - hdr_ptr = hdr_ptr->hdr.next; + if (hdr_ptr->hdr.bytes_left >= sizeofobject) + break; /* found pool with enough space */ + prev_hdr_ptr = hdr_ptr; + hdr_ptr = hdr_ptr->hdr.next; } - /* Time to make a new pool? */ if (hdr_ptr == NULL) { - /* min_request is what we need now, slop is what will be leftover */ - min_request = sizeofobject + SIZEOF(small_pool_hdr); - if (prev_hdr_ptr == NULL) /* first pool in class? */ - slop = first_pool_slop[pool_id]; - else - slop = extra_pool_slop[pool_id]; - /* Don't ask for more than MAX_ALLOC_CHUNK */ - if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) - slop = (size_t) (MAX_ALLOC_CHUNK-min_request); - /* Try to get space, if fail reduce slop and try again */ - for (;;) { - hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); - if (hdr_ptr != NULL) + min_request = sizeofobject + SIZEOF(small_pool_hdr); + if (prev_hdr_ptr == NULL) /* first pool in class? */ + slop = first_pool_slop[pool_id]; + else + slop = extra_pool_slop[pool_id]; + if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) + slop = (size_t) (MAX_ALLOC_CHUNK-min_request); + for (;;) { + hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); + if (hdr_ptr != NULL) break; - slop /= 2; - if (slop < MIN_SLOP) /* give up when it gets real small */ + slop /= 2; + if (slop < MIN_SLOP) /* give up when it gets real small */ out_of_memory(cinfo, 2); /* jpeg_get_small failed */ - } - mem->total_space_allocated += min_request + slop; - /* Success, initialize the new pool header and add to end of list */ - hdr_ptr->hdr.next = NULL; - hdr_ptr->hdr.bytes_used = 0; - hdr_ptr->hdr.bytes_left = sizeofobject + slop; - if (prev_hdr_ptr == NULL) /* first pool in class? */ - mem->small_list[pool_id] = hdr_ptr; - else - prev_hdr_ptr->hdr.next = hdr_ptr; + } + mem->total_space_allocated += min_request + slop; + hdr_ptr->hdr.next = NULL; + hdr_ptr->hdr.bytes_used = 0; + hdr_ptr->hdr.bytes_left = sizeofobject + slop; + if (prev_hdr_ptr == NULL) /* first pool in class? */ + mem->small_list[pool_id] = hdr_ptr; + else + prev_hdr_ptr->hdr.next = hdr_ptr; } - /* OK, allocate the object from the current pool */ data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ hdr_ptr->hdr.bytes_used += sizeofobject; @@ -204145,52 +186249,30 @@ alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) return (void *) data_ptr; } -/* - * Allocation of "large" objects. - * - * The external semantics of these are the same as "small" objects, - * except that FAR pointers are used on 80x86. However the pool - * management heuristics are quite different. We assume that each - * request is large enough that it may as well be passed directly to - * jpeg_get_large; the pool management just links everything together - * so that we can free it all on demand. - * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY - * structures. The routines that create these structures (see below) - * deliberately bunch rows together to ensure a large request size. - */ - METHODDEF(void FAR *) alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) -/* Allocate a "large" object */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; large_pool_ptr hdr_ptr; size_t odd_bytes; - /* Check for unsatisfiable request (do now to ensure no overflow below) */ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) - out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ + out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ - /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); if (odd_bytes > 0) - sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; - /* Always make a new pool */ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + - SIZEOF(large_pool_hdr)); + SIZEOF(large_pool_hdr)); if (hdr_ptr == NULL) - out_of_memory(cinfo, 4); /* jpeg_get_large failed */ + out_of_memory(cinfo, 4); /* jpeg_get_large failed */ mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); - /* Success, initialize the new pool header and add to list */ hdr_ptr->hdr.next = mem->large_list[pool_id]; - /* We maintain space counts in each pool header for statistical purposes, - * even though they are not needed for allocation. - */ hdr_ptr->hdr.bytes_used = sizeofobject; hdr_ptr->hdr.bytes_left = 0; mem->large_list[pool_id] = hdr_ptr; @@ -204198,23 +186280,9 @@ alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ } -/* - * Creation of 2-D sample arrays. - * The pointers are in near heap, the samples themselves in FAR heap. - * - * To minimize allocation overhead and to allow I/O of large contiguous - * blocks, we allocate the sample rows in groups of as many rows as possible - * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. - * NB: the virtual array control routines, later in this file, know about - * this chunking of rows. The rowsperchunk value is left in the mem manager - * object so that it can be saved away if this sarray is the workspace for - * a virtual array. - */ - METHODDEF(JSAMPARRAY) alloc_sarray (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, JDIMENSION numrows) -/* Allocate a 2-D sample array */ + JDIMENSION samplesperrow, JDIMENSION numrows) { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; JSAMPARRAY result; @@ -204222,46 +186290,37 @@ alloc_sarray (j_common_ptr cinfo, int pool_id, JDIMENSION rowsperchunk, currow, i; long ltemp; - /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / ((long) samplesperrow * SIZEOF(JSAMPLE)); if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; + rowsperchunk = (JDIMENSION) ltemp; else - rowsperchunk = numrows; + rowsperchunk = numrows; mem->last_rowsperchunk = rowsperchunk; - /* Get space for row pointers (small object) */ result = (JSAMPARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JSAMPROW))); + (size_t) (numrows * SIZEOF(JSAMPROW))); - /* Get the rows themselves (large objects) */ currow = 0; while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JSAMPROW) alloc_large(cinfo, pool_id, + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW) alloc_large(cinfo, pool_id, (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow * SIZEOF(JSAMPLE))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += samplesperrow; - } + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } } return result; } -/* - * Creation of 2-D coefficient-block arrays. - * This is essentially the same as the code for sample arrays, above. - */ - METHODDEF(JBLOCKARRAY) alloc_barray (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, JDIMENSION numrows) -/* Allocate a 2-D coefficient-block array */ + JDIMENSION blocksperrow, JDIMENSION numrows) { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; JBLOCKARRAY result; @@ -204269,87 +186328,45 @@ alloc_barray (j_common_ptr cinfo, int pool_id, JDIMENSION rowsperchunk, currow, i; long ltemp; - /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / ((long) blocksperrow * SIZEOF(JBLOCK)); if (ltemp <= 0) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long) numrows) - rowsperchunk = (JDIMENSION) ltemp; + rowsperchunk = (JDIMENSION) ltemp; else - rowsperchunk = numrows; + rowsperchunk = numrows; mem->last_rowsperchunk = rowsperchunk; - /* Get space for row pointers (small object) */ result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JBLOCKROW))); + (size_t) (numrows * SIZEOF(JBLOCKROW))); - /* Get the rows themselves (large objects) */ currow = 0; while (currow < numrows) { - rowsperchunk = MIN(rowsperchunk, numrows - currow); - workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow * SIZEOF(JBLOCK))); - for (i = rowsperchunk; i > 0; i--) { - result[currow++] = workspace; - workspace += blocksperrow; - } + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += blocksperrow; + } } return result; } -/* - * About virtual array management: - * - * The above "normal" array routines are only used to allocate strip buffers - * (as wide as the image, but just a few rows high). Full-image-sized buffers - * are handled as "virtual" arrays. The array is still accessed a strip at a - * time, but the memory manager must save the whole array for repeated - * accesses. The intended implementation is that there is a strip buffer in - * memory (as high as is possible given the desired memory limit), plus a - * backing file that holds the rest of the array. - * - * The request_virt_array routines are told the total size of the image and - * the maximum number of rows that will be accessed at once. The in-memory - * buffer must be at least as large as the maxaccess value. - * - * The request routines create control blocks but not the in-memory buffers. - * That is postponed until realize_virt_arrays is called. At that time the - * total amount of space needed is known (approximately, anyway), so free - * memory can be divided up fairly. - * - * The access_virt_array routines are responsible for making a specific strip - * area accessible (after reading or writing the backing file, if necessary). - * Note that the access routines are told whether the caller intends to modify - * the accessed strip; during a read-only pass this saves having to rewrite - * data to disk. The access routines are also responsible for pre-zeroing - * any newly accessed rows, if pre-zeroing was requested. - * - * In current usage, the access requests are usually for nonoverlapping - * strips; that is, successive access start_row numbers differ by exactly - * num_rows = maxaccess. This means we can get good performance with simple - * buffer dump/reload logic, by making the in-memory buffer be a multiple - * of the access height; then there will never be accesses across bufferload - * boundaries. The code will still work with overlapping access requests, - * but it doesn't handle bufferload overlaps very efficiently. - */ - METHODDEF(jvirt_sarray_ptr) request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION samplesperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -/* Request a virtual 2-D sample array */ + JDIMENSION samplesperrow, JDIMENSION numrows, + JDIMENSION maxaccess) { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; jvirt_sarray_ptr result; - /* Only IMAGE-lifetime virtual arrays are currently supported */ if (pool_id != JPOOL_IMAGE) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - /* get control block */ result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, SIZEOF(struct jvirt_sarray_control)); @@ -204367,18 +186384,15 @@ request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, METHODDEF(jvirt_barray_ptr) request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION blocksperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -/* Request a virtual 2-D coefficient-block array */ + JDIMENSION blocksperrow, JDIMENSION numrows, + JDIMENSION maxaccess) { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; jvirt_barray_ptr result; - /* Only IMAGE-lifetime virtual arrays are currently supported */ if (pool_id != JPOOL_IMAGE) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ - /* get control block */ result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, SIZEOF(struct jvirt_barray_control)); @@ -204396,7 +186410,6 @@ request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, METHODDEF(void) realize_virt_arrays (j_common_ptr cinfo) -/* Allocate the in-memory buffers for any unrealized virtual arrays */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; long space_per_minheight, maximum_space, avail_mem; @@ -204404,338 +186417,258 @@ realize_virt_arrays (j_common_ptr cinfo) jvirt_sarray_ptr sptr; jvirt_barray_ptr bptr; - /* Compute the minimum space needed (maxaccess rows in each buffer) - * and the maximum space needed (full image height in each buffer). - * These may be of use to the system-dependent jpeg_mem_available routine. - */ space_per_minheight = 0; maximum_space = 0; for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->mem_buffer == NULL) { /* if not realized yet */ - space_per_minheight += (long) sptr->maxaccess * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); - maximum_space += (long) sptr->rows_in_array * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); - } + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) sptr->maxaccess * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + maximum_space += (long) sptr->rows_in_array * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + } } for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->mem_buffer == NULL) { /* if not realized yet */ - space_per_minheight += (long) bptr->maxaccess * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); - maximum_space += (long) bptr->rows_in_array * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); - } + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) bptr->maxaccess * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + maximum_space += (long) bptr->rows_in_array * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + } } if (space_per_minheight <= 0) - return; /* no unrealized arrays, no work */ + return; /* no unrealized arrays, no work */ - /* Determine amount of memory to actually use; this is system-dependent. */ avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, mem->total_space_allocated); - /* If the maximum space needed is available, make all the buffers full - * height; otherwise parcel it out with the same number of minheights - * in each buffer. - */ if (avail_mem >= maximum_space) - max_minheights = 1000000000L; + max_minheights = 1000000000L; else { - max_minheights = avail_mem / space_per_minheight; - /* If there doesn't seem to be enough space, try to get the minimum - * anyway. This allows a "stub" implementation of jpeg_mem_available(). - */ - if (max_minheights <= 0) - max_minheights = 1; + max_minheights = avail_mem / space_per_minheight; + if (max_minheights <= 0) + max_minheights = 1; } - /* Allocate the in-memory buffers and initialize backing store as needed. */ - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->mem_buffer == NULL) { /* if not realized yet */ - minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; - if (minheights <= max_minheights) { - /* This buffer fits in memory */ + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; + if (minheights <= max_minheights) { sptr->rows_in_mem = sptr->rows_in_array; - } else { - /* It doesn't fit in memory, create backing store. */ + } else { sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); jpeg_open_backing_store(cinfo, & sptr->b_s_info, (long) sptr->rows_in_array * (long) sptr->samplesperrow * (long) SIZEOF(JSAMPLE)); sptr->b_s_open = TRUE; - } - sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, - sptr->samplesperrow, sptr->rows_in_mem); - sptr->rowsperchunk = mem->last_rowsperchunk; - sptr->cur_start_row = 0; - sptr->first_undef_row = 0; - sptr->dirty = FALSE; - } + } + sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, + sptr->samplesperrow, sptr->rows_in_mem); + sptr->rowsperchunk = mem->last_rowsperchunk; + sptr->cur_start_row = 0; + sptr->first_undef_row = 0; + sptr->dirty = FALSE; + } } for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->mem_buffer == NULL) { /* if not realized yet */ - minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; - if (minheights <= max_minheights) { - /* This buffer fits in memory */ + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; + if (minheights <= max_minheights) { bptr->rows_in_mem = bptr->rows_in_array; - } else { - /* It doesn't fit in memory, create backing store. */ + } else { bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); jpeg_open_backing_store(cinfo, & bptr->b_s_info, (long) bptr->rows_in_array * (long) bptr->blocksperrow * (long) SIZEOF(JBLOCK)); bptr->b_s_open = TRUE; - } - bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, - bptr->blocksperrow, bptr->rows_in_mem); - bptr->rowsperchunk = mem->last_rowsperchunk; - bptr->cur_start_row = 0; - bptr->first_undef_row = 0; - bptr->dirty = FALSE; - } + } + bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, + bptr->blocksperrow, bptr->rows_in_mem); + bptr->rowsperchunk = mem->last_rowsperchunk; + bptr->cur_start_row = 0; + bptr->first_undef_row = 0; + bptr->dirty = FALSE; + } } } LOCAL(void) do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) -/* Do backing store read or write of a virtual sample array */ { long bytesperrow, file_offset, byte_count, rows, thisrow, i; bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); file_offset = ptr->cur_start_row * bytesperrow; - /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { - /* One chunk, but check for short chunk at end of buffer */ - rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); - /* Transfer no more than is currently defined */ - thisrow = (long) ptr->cur_start_row + i; - rows = MIN(rows, (long) ptr->first_undef_row - thisrow); - /* Transfer no more than fits in file */ - rows = MIN(rows, (long) ptr->rows_in_array - thisrow); - if (rows <= 0) /* this chunk might be past end of file! */ - break; - byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); - file_offset += byte_count; + file_offset += byte_count; } } LOCAL(void) do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) -/* Do backing store read or write of a virtual coefficient-block array */ { long bytesperrow, file_offset, byte_count, rows, thisrow, i; bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); file_offset = ptr->cur_start_row * bytesperrow; - /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { - /* One chunk, but check for short chunk at end of buffer */ - rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); - /* Transfer no more than is currently defined */ - thisrow = (long) ptr->cur_start_row + i; - rows = MIN(rows, (long) ptr->first_undef_row - thisrow); - /* Transfer no more than fits in file */ - rows = MIN(rows, (long) ptr->rows_in_array - thisrow); - if (rows <= 0) /* this chunk might be past end of file! */ - break; - byte_count = rows * bytesperrow; - if (writing) - (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); - else - (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); - file_offset += byte_count; + file_offset += byte_count; } } METHODDEF(JSAMPARRAY) access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) -/* Access the part of a virtual sample array starting at start_row */ -/* and extending for num_rows rows. writable is true if */ -/* caller intends to modify the accessed area. */ + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) { JDIMENSION end_row = start_row + num_rows; JDIMENSION undef_row; - /* debugging check */ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || - ptr->mem_buffer == NULL) - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - - /* Make the desired part of the virtual array accessible */ - if (start_row < ptr->cur_start_row || - end_row > ptr->cur_start_row+ptr->rows_in_mem) { - if (! ptr->b_s_open) - ERREXIT(cinfo, JERR_VIRTUAL_BUG); - /* Flush old buffer contents if necessary */ - if (ptr->dirty) { - do_sarray_io(cinfo, ptr, TRUE); - ptr->dirty = FALSE; - } - /* Decide what part of virtual array to access. - * Algorithm: if target address > current window, assume forward scan, - * load starting at target address. If target address < current window, - * assume backward scan, load so that target area is top of window. - * Note that when switching from forward write to forward read, will have - * start_row = 0, so the limiting case applies and we load from 0 anyway. - */ - if (start_row > ptr->cur_start_row) { - ptr->cur_start_row = start_row; - } else { - /* use long arithmetic here to avoid overflow & unsigned problems */ - long ltemp; - - ltemp = (long) end_row - (long) ptr->rows_in_mem; - if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ - ptr->cur_start_row = (JDIMENSION) ltemp; - } - /* Read in the selected part of the array. - * During the initial write pass, we will do no actual read - * because the selected part is all undefined. - */ - do_sarray_io(cinfo, ptr, FALSE); - } - /* Ensure the accessed part of the array is defined; prezero if needed. - * To improve locality of access, we only prezero the part of the array - * that the caller is about to access, not the entire in-memory array. - */ - if (ptr->first_undef_row < end_row) { - if (ptr->first_undef_row < start_row) { - if (writable) /* writer skipped over a section of array */ + ptr->mem_buffer == NULL) ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - undef_row = start_row; /* but reader is allowed to read ahead */ - } else { - undef_row = ptr->first_undef_row; - } - if (writable) - ptr->first_undef_row = end_row; - if (ptr->pre_zero) { - size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); - undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ - end_row -= ptr->cur_start_row; - while (undef_row < end_row) { + + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + if (ptr->dirty) { + do_sarray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + do_sarray_io(cinfo, ptr, FALSE); + } + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); undef_row++; - } - } else { - if (! writable) /* reader looking at undefined data */ + } + } else { + if (! writable) /* reader looking at undefined data */ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - } + } } - /* Flag the buffer dirty if caller will write in it */ if (writable) - ptr->dirty = TRUE; - /* Return address of proper part of the buffer */ + ptr->dirty = TRUE; return ptr->mem_buffer + (start_row - ptr->cur_start_row); } METHODDEF(JBLOCKARRAY) access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) -/* Access the part of a virtual block array starting at start_row */ -/* and extending for num_rows rows. writable is true if */ -/* caller intends to modify the accessed area. */ + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) { JDIMENSION end_row = start_row + num_rows; JDIMENSION undef_row; - /* debugging check */ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || - ptr->mem_buffer == NULL) - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - - /* Make the desired part of the virtual array accessible */ - if (start_row < ptr->cur_start_row || - end_row > ptr->cur_start_row+ptr->rows_in_mem) { - if (! ptr->b_s_open) - ERREXIT(cinfo, JERR_VIRTUAL_BUG); - /* Flush old buffer contents if necessary */ - if (ptr->dirty) { - do_barray_io(cinfo, ptr, TRUE); - ptr->dirty = FALSE; - } - /* Decide what part of virtual array to access. - * Algorithm: if target address > current window, assume forward scan, - * load starting at target address. If target address < current window, - * assume backward scan, load so that target area is top of window. - * Note that when switching from forward write to forward read, will have - * start_row = 0, so the limiting case applies and we load from 0 anyway. - */ - if (start_row > ptr->cur_start_row) { - ptr->cur_start_row = start_row; - } else { - /* use long arithmetic here to avoid overflow & unsigned problems */ - long ltemp; - - ltemp = (long) end_row - (long) ptr->rows_in_mem; - if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ - ptr->cur_start_row = (JDIMENSION) ltemp; - } - /* Read in the selected part of the array. - * During the initial write pass, we will do no actual read - * because the selected part is all undefined. - */ - do_barray_io(cinfo, ptr, FALSE); - } - /* Ensure the accessed part of the array is defined; prezero if needed. - * To improve locality of access, we only prezero the part of the array - * that the caller is about to access, not the entire in-memory array. - */ - if (ptr->first_undef_row < end_row) { - if (ptr->first_undef_row < start_row) { - if (writable) /* writer skipped over a section of array */ + ptr->mem_buffer == NULL) ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - undef_row = start_row; /* but reader is allowed to read ahead */ - } else { - undef_row = ptr->first_undef_row; - } - if (writable) - ptr->first_undef_row = end_row; - if (ptr->pre_zero) { - size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); - undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ - end_row -= ptr->cur_start_row; - while (undef_row < end_row) { + + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + if (ptr->dirty) { + do_barray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + do_barray_io(cinfo, ptr, FALSE); + } + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); undef_row++; - } - } else { - if (! writable) /* reader looking at undefined data */ + } + } else { + if (! writable) /* reader looking at undefined data */ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); - } + } } - /* Flag the buffer dirty if caller will write in it */ if (writable) - ptr->dirty = TRUE; - /* Return address of proper part of the buffer */ + ptr->dirty = TRUE; return ptr->mem_buffer + (start_row - ptr->cur_start_row); } -/* - * Release all objects belonging to a specified pool. - */ - METHODDEF(void) free_pool (j_common_ptr cinfo, int pool_id) { @@ -204745,93 +186678,75 @@ free_pool (j_common_ptr cinfo, int pool_id) size_t space_freed; if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) - ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ #ifdef MEM_STATS if (cinfo->err->trace_level > 1) - print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ + print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ #endif - /* If freeing IMAGE pool, close any virtual arrays first */ if (pool_id == JPOOL_IMAGE) { - jvirt_sarray_ptr sptr; - jvirt_barray_ptr bptr; + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; - for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { - if (sptr->b_s_open) { /* there may be no backing store */ + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->b_s_open) { /* there may be no backing store */ sptr->b_s_open = FALSE; /* prevent recursive close if error */ (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); - } - } - mem->virt_sarray_list = NULL; - for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { - if (bptr->b_s_open) { /* there may be no backing store */ + } + } + mem->virt_sarray_list = NULL; + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->b_s_open) { /* there may be no backing store */ bptr->b_s_open = FALSE; /* prevent recursive close if error */ (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); - } - } - mem->virt_barray_list = NULL; + } + } + mem->virt_barray_list = NULL; } - /* Release large objects */ lhdr_ptr = mem->large_list[pool_id]; mem->large_list[pool_id] = NULL; while (lhdr_ptr != NULL) { - large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; - space_freed = lhdr_ptr->hdr.bytes_used + + large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; + space_freed = lhdr_ptr->hdr.bytes_used + lhdr_ptr->hdr.bytes_left + SIZEOF(large_pool_hdr); - jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); - mem->total_space_allocated -= space_freed; - lhdr_ptr = next_lhdr_ptr; + jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + lhdr_ptr = next_lhdr_ptr; } - /* Release small objects */ shdr_ptr = mem->small_list[pool_id]; mem->small_list[pool_id] = NULL; while (shdr_ptr != NULL) { - small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; - space_freed = shdr_ptr->hdr.bytes_used + + small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; + space_freed = shdr_ptr->hdr.bytes_used + shdr_ptr->hdr.bytes_left + SIZEOF(small_pool_hdr); - jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); - mem->total_space_allocated -= space_freed; - shdr_ptr = next_shdr_ptr; + jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + shdr_ptr = next_shdr_ptr; } } -/* - * Close up shop entirely. - * Note that this cannot be called unless cinfo->mem is non-NULL. - */ - METHODDEF(void) self_destruct (j_common_ptr cinfo) { int pool; - /* Close all backing store, release all memory. - * Releasing pools in reverse order might help avoid fragmentation - * with some (brain-damaged) malloc libraries. - */ for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { - free_pool(cinfo, pool); + free_pool(cinfo, pool); } - /* Release the memory manager control block too. */ jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); cinfo->mem = NULL; /* ensures I will be called only once */ jpeg_mem_term(cinfo); /* system-dependent cleanup */ } -/* - * Memory manager initialization. - * When this is called, only the error manager pointer is valid in cinfo! - */ - GLOBAL(void) jinit_memory_mgr (j_common_ptr cinfo) { @@ -204842,36 +186757,22 @@ jinit_memory_mgr (j_common_ptr cinfo) cinfo->mem = NULL; /* for safety if init fails */ - /* Check for configuration errors. - * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably - * doesn't reflect any real hardware alignment requirement. - * The test is a little tricky: for X>0, X and X-1 have no one-bits - * in common if and only if X is a power of 2, ie has only one one-bit. - * Some compilers may give an "unreachable code" warning here; ignore it. - */ if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) - ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); - /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be - * a multiple of SIZEOF(ALIGN_TYPE). - * Again, an "unreachable code" warning may be ignored here. - * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. - */ + ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); test_mac = (size_t) MAX_ALLOC_CHUNK; if ((long) test_mac != MAX_ALLOC_CHUNK || - (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) - ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ - /* Attempt to allocate memory manager's control block */ mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); if (mem == NULL) { - jpeg_mem_term(cinfo); /* system-dependent cleanup */ - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); + jpeg_mem_term(cinfo); /* system-dependent cleanup */ + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); } - /* OK, fill in the method pointers */ mem->pub.alloc_small = alloc_small; mem->pub.alloc_large = alloc_large; mem->pub.alloc_sarray = alloc_sarray; @@ -204884,42 +186785,33 @@ jinit_memory_mgr (j_common_ptr cinfo) mem->pub.free_pool = free_pool; mem->pub.self_destruct = self_destruct; - /* Make MAX_ALLOC_CHUNK accessible to other modules */ mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; - /* Initialize working state */ mem->pub.max_memory_to_use = max_to_use; for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { - mem->small_list[pool] = NULL; - mem->large_list[pool] = NULL; + mem->small_list[pool] = NULL; + mem->large_list[pool] = NULL; } mem->virt_sarray_list = NULL; mem->virt_barray_list = NULL; mem->total_space_allocated = SIZEOF(my_memory_mgr); - /* Declare ourselves open for business */ cinfo->mem = & mem->pub; - /* Check for an environment variable JPEGMEM; if found, override the - * default max_memory setting from jpeg_mem_init. Note that the - * surrounding application may again override this value. - * If your system doesn't support getenv(), define NO_GETENV to disable - * this feature. - */ #ifndef NO_GETENV { char * memenv; - if ((memenv = getenv("JPEGMEM")) != NULL) { - char ch = 'x'; + if ((memenv = getenv("JPEGMEM")) != NULL) { + char ch = 'x'; - if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { + if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { if (ch == 'm' || ch == 'M') max_to_use *= 1000L; mem->pub.max_memory_to_use = max_to_use * 1000L; - } - } + } + } } #endif @@ -204934,11 +186826,6 @@ extern void * malloc JPP((size_t size)); extern void free JPP((void *ptr)); #endif -/* - * Memory allocation and freeing are controlled by the regular library - * routines malloc() and free(). - */ - GLOBAL(void *) jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) { @@ -204951,13 +186838,6 @@ jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) free(object); } -/* - * "Large" objects are treated the same as "small" ones. - * NB: although we include FAR keywords in the routine declarations, - * this file won't actually work in 80x86 small/medium model; at least, - * you probably won't be able to process useful-size images in only 64KB. - */ - GLOBAL(void FAR *) jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) { @@ -204970,24 +186850,13 @@ jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) free(object); } -/* - * This routine computes the total memory space available for allocation. - * Here we always say, "we got all you want bud!" - */ - GLOBAL(long) jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, - long max_bytes_needed, long already_allocated) + long max_bytes_needed, long already_allocated) { return max_bytes_needed; } -/* - * Backing store (temporary file) management. - * Since jpeg_mem_available always promised the moon, - * this should never be called and we can just error out. - */ - GLOBAL(void) jpeg_open_backing_store (j_common_ptr cinfo, struct backing_store_struct *info, long total_bytes_needed) @@ -204995,11 +186864,6 @@ jpeg_open_backing_store (j_common_ptr cinfo, struct backing_store_struct *info, ERREXIT(cinfo, JERR_NO_BACKING_STORE); } -/* - * These routines take care of any system-dependent initialization and - * cleanup required. Here, there isn't any. - */ - GLOBAL(long) jpeg_mem_init (j_common_ptr cinfo) { @@ -205009,7 +186873,6 @@ jpeg_mem_init (j_common_ptr cinfo) GLOBAL(void) jpeg_mem_term (j_common_ptr cinfo) { - /* no work */ } /********* End of inlined file: jmemnobs.c *********/ @@ -205018,58 +186881,7 @@ jpeg_mem_term (j_common_ptr cinfo) #ifdef QUANT_1PASS_SUPPORTED -/* - * The main purpose of 1-pass quantization is to provide a fast, if not very - * high quality, colormapped output capability. A 2-pass quantizer usually - * gives better visual quality; however, for quantized grayscale output this - * quantizer is perfectly adequate. Dithering is highly recommended with this - * quantizer, though you can turn it off if you really want to. - * - * In 1-pass quantization the colormap must be chosen in advance of seeing the - * image. We use a map consisting of all combinations of Ncolors[i] color - * values for the i'th component. The Ncolors[] values are chosen so that - * their product, the total number of colors, is no more than that requested. - * (In most cases, the product will be somewhat less.) - * - * Since the colormap is orthogonal, the representative value for each color - * component can be determined without considering the other components; - * then these indexes can be combined into a colormap index by a standard - * N-dimensional-array-subscript calculation. Most of the arithmetic involved - * can be precalculated and stored in the lookup table colorindex[]. - * colorindex[i][j] maps pixel value j in component i to the nearest - * representative value (grid plane) for that component; this index is - * multiplied by the array stride for component i, so that the - * index of the colormap entry closest to a given pixel value is just - * sum( colorindex[component-number][pixel-component-value] ) - * Aside from being fast, this scheme allows for variable spacing between - * representative values with no additional lookup cost. - * - * If gamma correction has been applied in color conversion, it might be wise - * to adjust the color grid spacing so that the representative colors are - * equidistant in linear space. At this writing, gamma correction is not - * implemented by jdcolor, so nothing is done here. - */ - -/* Declarations for ordered dithering. - * - * We use a standard 16x16 ordered dither array. The basic concept of ordered - * dithering is described in many references, for instance Dale Schumacher's - * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). - * In place of Schumacher's comparisons against a "threshold" value, we add a - * "dither" value to the input pixel and then round the result to the nearest - * output value. The dither value is equivalent to (0.5 - threshold) times - * the distance between output values. For ordered dithering, we assume that - * the output colors are equally spaced; if not, results will probably be - * worse, since the dither may be too much or too little at a given point. - * - * The normal calculation would be to form pixel value + dither, range-limit - * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. - * We can skip the separate range-limiting step by extending the colorindex - * table in both directions. - */ - #define ODITHER_SIZE 16 /* dimension of dither matrix */ -/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ #define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ #define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ @@ -205077,10 +186889,6 @@ typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { - /* Bayer's order-4 dither array. Generated by the code given in - * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. - * The values in this array must range from 0 to ODITHER_CELLS-1. - */ { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, @@ -205099,30 +186907,6 @@ static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } }; -/* Declarations for Floyd-Steinberg dithering. - * - * Errors are accumulated into the array fserrors[], at a resolution of - * 1/16th of a pixel count. The error at a given pixel is propagated - * to its not-yet-processed neighbors using the standard F-S fractions, - * ... (here) 7/16 - * 3/16 5/16 1/16 - * We work left-to-right on even rows, right-to-left on odd rows. - * - * We can get away with a single array (holding one row's worth of errors) - * by using it to store the current row's errors at pixel columns not yet - * processed, but the next row's errors at columns already processed. We - * need only a few extra variables to hold the errors immediately around the - * current column. (If we are lucky, those variables are in registers, but - * even if not, they're probably cheaper to access than array elements are.) - * - * The fserrors[] array is indexed [component#][position]. - * We provide (#columns + 2) entries per component; the extra entry at each - * end saves us from special-casing the first and last pixels. - * - * Note: on a wide image, we might not have enough room in a PC's near data - * segment to hold the error array; so it is allocated with alloc_large. - */ - #if BITS_IN_JSAMPLE == 8 typedef INT16 FSERROR; /* 16 bits should be enough */ typedef int LOCFSERROR; /* use 'int' for calculation temps */ @@ -205133,56 +186917,30 @@ typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ -/* Private subobject */ - #define MAX_Q_COMPS 4 /* max components I can handle */ typedef struct { struct jpeg_color_quantizer pub; /* public fields */ - /* Initially allocated colormap is saved here */ JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ int sv_actual; /* number of entries in use */ JSAMPARRAY colorindex; /* Precomputed mapping for speed */ - /* colorindex[i][j] = index of color closest to pixel value j in component i, - * premultiplied as described above. Since colormap indexes must fit into - * JSAMPLEs, the entries of this array will too. - */ boolean is_padded; /* is the colorindex padded for odither? */ int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ - /* Variables for ordered dithering */ int row_index; /* cur row's vertical index in dither matrix */ ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ - /* Variables for Floyd-Steinberg dithering */ FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ boolean on_odd_row; /* flag to remember which row we are on */ } my_cquantizer; typedef my_cquantizer * my_cquantize_ptr; -/* - * Policy-making subroutines for create_colormap and create_colorindex. - * These routines determine the colormap to be used. The rest of the module - * only assumes that the colormap is orthogonal. - * - * * select_ncolors decides how to divvy up the available colors - * among the components. - * * output_value defines the set of representative values for a component. - * * largest_input_value defines the mapping from input values to - * representative values for a component. - * Note that the latter two routines may impose different policies for - * different components, though this is not currently done. - */ - LOCAL(int) select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) -/* Determine allocation of desired colors to components, */ -/* and fill in Ncolors[] array to indicate choice. */ -/* Return value is total number of colors (product of Ncolors[] values). */ { int nc = cinfo->out_color_components; /* number of color components */ int max_colors = cinfo->desired_number_of_colors; @@ -205191,46 +186949,35 @@ select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) long temp; static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; - /* We can allocate at least the nc'th root of max_colors per component. */ - /* Compute floor(nc'th root of max_colors). */ iroot = 1; do { - iroot++; - temp = iroot; /* set temp = iroot ** nc */ - for (i = 1; i < nc; i++) - temp *= iroot; + iroot++; + temp = iroot; /* set temp = iroot ** nc */ + for (i = 1; i < nc; i++) + temp *= iroot; } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ iroot--; /* now iroot = floor(root) */ - /* Must have at least 2 color values per component */ if (iroot < 2) - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); - /* Initialize to iroot color values for each component */ total_colors = 1; for (i = 0; i < nc; i++) { - Ncolors[i] = iroot; - total_colors *= iroot; + Ncolors[i] = iroot; + total_colors *= iroot; } - /* We may be able to increment the count for one or more components without - * exceeding max_colors, though we know not all can be incremented. - * Sometimes, the first component can be incremented more than once! - * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) - * In RGB colorspace, try to increment G first, then R, then B. - */ do { - changed = FALSE; - for (i = 0; i < nc; i++) { - j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); - /* calculate new total_colors if Ncolors[j] is incremented */ - temp = total_colors / Ncolors[j]; - temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ - if (temp > (long) max_colors) + changed = FALSE; + for (i = 0; i < nc; i++) { + j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); + temp = total_colors / Ncolors[j]; + temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ + if (temp > (long) max_colors) break; /* won't fit, done with this pass */ - Ncolors[j]++; /* OK, apply the increment */ - total_colors = (int) temp; - changed = TRUE; - } + Ncolors[j]++; /* OK, apply the increment */ + total_colors = (int) temp; + changed = TRUE; + } } while (changed); return total_colors; @@ -205238,30 +186985,16 @@ select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) LOCAL(int) output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) -/* Return j'th output value, where j will range from 0 to maxj */ -/* The output values must fall in 0..MAXJSAMPLE in increasing order */ { - /* We always provide values 0 and MAXJSAMPLE for each component; - * any additional values are equally spaced between these limits. - * (Forcing the upper and lower values to the limits ensures that - * dithering can't produce a color outside the selected gamut.) - */ return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); } LOCAL(int) largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) -/* Return largest input value that should map to j'th output value */ -/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ { - /* Breakpoints are halfway between values returned by output_value */ return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); } -/* - * Create the colormap. - */ - LOCAL(void) create_colormap (j_decompress_ptr cinfo) { @@ -205270,57 +187003,38 @@ create_colormap (j_decompress_ptr cinfo) int total_colors; /* Number of distinct output colors */ int i,j,k, nci, blksize, blkdist, ptr, val; - /* Select number of colors for each component */ total_colors = select_ncolors(cinfo, cquantize->Ncolors); - /* Report selected color counts */ if (cinfo->out_color_components == 3) - TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, - total_colors, cquantize->Ncolors[0], - cquantize->Ncolors[1], cquantize->Ncolors[2]); + TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, + total_colors, cquantize->Ncolors[0], + cquantize->Ncolors[1], cquantize->Ncolors[2]); else - TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); - - /* Allocate and fill in the colormap. */ - /* The colors are ordered in the map in standard row-major order, */ - /* i.e. rightmost (highest-indexed) color changes most rapidly. */ + TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); colormap = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); - /* blksize is number of adjacent repeated entries for a component */ - /* blkdist is distance between groups of identical entries for a component */ blkdist = total_colors; for (i = 0; i < cinfo->out_color_components; i++) { - /* fill in colormap entries for i'th color component */ - nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ - blksize = blkdist / nci; - for (j = 0; j < nci; j++) { - /* Compute j'th output value (out of nci) for component */ - val = output_value(cinfo, i, j, nci-1); - /* Fill in all colormap entries that have this value of this component */ - for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { - /* fill in blksize entries beginning at ptr */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blkdist / nci; + for (j = 0; j < nci; j++) { + val = output_value(cinfo, i, j, nci-1); + for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { for (k = 0; k < blksize; k++) colormap[i][ptr+k] = (JSAMPLE) val; - } - } - blkdist = blksize; /* blksize of this color is blkdist of next */ + } + } + blkdist = blksize; /* blksize of this color is blkdist of next */ } - /* Save the colormap in private storage, - * where it will survive color quantization mode changes. - */ cquantize->sv_colormap = colormap; cquantize->sv_actual = total_colors; } -/* - * Create the color index table. - */ - LOCAL(void) create_colorindex (j_decompress_ptr cinfo) { @@ -205328,61 +187042,44 @@ create_colorindex (j_decompress_ptr cinfo) JSAMPROW indexptr; int i,j,k, nci, blksize, val, pad; - /* For ordered dither, we pad the color index tables by MAXJSAMPLE in - * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). - * This is not necessary in the other dithering modes. However, we - * flag whether it was done in case user changes dithering mode. - */ if (cinfo->dither_mode == JDITHER_ORDERED) { - pad = MAXJSAMPLE*2; - cquantize->is_padded = TRUE; + pad = MAXJSAMPLE*2; + cquantize->is_padded = TRUE; } else { - pad = 0; - cquantize->is_padded = FALSE; + pad = 0; + cquantize->is_padded = FALSE; } cquantize->colorindex = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (MAXJSAMPLE+1 + pad), - (JDIMENSION) cinfo->out_color_components); + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1 + pad), + (JDIMENSION) cinfo->out_color_components); - /* blksize is number of adjacent repeated entries for a component */ blksize = cquantize->sv_actual; for (i = 0; i < cinfo->out_color_components; i++) { - /* fill in colorindex entries for i'th color component */ - nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ - blksize = blksize / nci; + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blksize / nci; - /* adjust colorindex pointers to provide padding at negative indexes. */ - if (pad) - cquantize->colorindex[i] += MAXJSAMPLE; + if (pad) + cquantize->colorindex[i] += MAXJSAMPLE; - /* in loop, val = index of current output value, */ - /* and k = largest j that maps to current val */ - indexptr = cquantize->colorindex[i]; - val = 0; - k = largest_input_value(cinfo, i, 0, nci-1); - for (j = 0; j <= MAXJSAMPLE; j++) { - while (j > k) /* advance val if past boundary */ + indexptr = cquantize->colorindex[i]; + val = 0; + k = largest_input_value(cinfo, i, 0, nci-1); + for (j = 0; j <= MAXJSAMPLE; j++) { + while (j > k) /* advance val if past boundary */ k = largest_input_value(cinfo, i, ++val, nci-1); - /* premultiply so that no multiplication needed in main processing */ - indexptr[j] = (JSAMPLE) (val * blksize); - } - /* Pad at both ends if necessary */ - if (pad) - for (j = 1; j <= MAXJSAMPLE; j++) { + indexptr[j] = (JSAMPLE) (val * blksize); + } + if (pad) + for (j = 1; j <= MAXJSAMPLE; j++) { indexptr[-j] = indexptr[0]; indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; - } + } } } -/* - * Create an ordered-dither array for a component having ncolors - * distinct output values. - */ - LOCAL(ODITHER_MATRIX_PTR) make_odither_array (j_decompress_ptr cinfo, int ncolors) { @@ -205391,33 +187088,19 @@ make_odither_array (j_decompress_ptr cinfo, int ncolors) INT32 num,den; odither = (ODITHER_MATRIX_PTR) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(ODITHER_MATRIX)); - /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). - * Hence the dither value for the matrix cell with fill order f - * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). - * On 16-bit-int machine, be careful to avoid overflow. - */ den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1)); for (j = 0; j < ODITHER_SIZE; j++) { - for (k = 0; k < ODITHER_SIZE; k++) { - num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) - * MAXJSAMPLE; - /* Ensure round towards zero despite C's lack of consistency - * about rounding negative values in integer division... - */ - odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); - } + for (k = 0; k < ODITHER_SIZE; k++) { + num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) + * MAXJSAMPLE; + odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); + } } return odither; } -/* - * Create the ordered-dither tables. - * Components having the same number of representative colors may - * share a dither table. - */ - LOCAL(void) create_odither_tables (j_decompress_ptr cinfo) { @@ -205426,28 +187109,23 @@ create_odither_tables (j_decompress_ptr cinfo) int i, j, nci; for (i = 0; i < cinfo->out_color_components; i++) { - nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ - odither = NULL; /* search for matching prior component */ - for (j = 0; j < i; j++) { - if (nci == cquantize->Ncolors[j]) { + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + odither = NULL; /* search for matching prior component */ + for (j = 0; j < i; j++) { + if (nci == cquantize->Ncolors[j]) { odither = cquantize->odither[j]; break; - } - } - if (odither == NULL) /* need a new table? */ - odither = make_odither_array(cinfo, nci); - cquantize->odither[i] = odither; + } + } + if (odither == NULL) /* need a new table? */ + odither = make_odither_array(cinfo, nci); + cquantize->odither[i] = odither; } } -/* - * Map some rows of pixels to the output colormapped representation. - */ - METHODDEF(void) color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) -/* General case, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; JSAMPARRAY colorindex = cquantize->colorindex; @@ -205459,22 +187137,21 @@ color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, register int nc = cinfo->out_color_components; for (row = 0; row < num_rows; row++) { - ptrin = input_buf[row]; - ptrout = output_buf[row]; - for (col = width; col > 0; col--) { - pixcode = 0; - for (ci = 0; ci < nc; ci++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = 0; + for (ci = 0; ci < nc; ci++) { pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); - } - *ptrout++ = (JSAMPLE) pixcode; - } + } + *ptrout++ = (JSAMPLE) pixcode; + } } } METHODDEF(void) color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) -/* Fast path for out_color_components==3, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register int pixcode; @@ -205487,21 +187164,20 @@ color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { - ptrin = input_buf[row]; - ptrout = output_buf[row]; - for (col = width; col > 0; col--) { - pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); - pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); - pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); - *ptrout++ = (JSAMPLE) pixcode; - } + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); + *ptrout++ = (JSAMPLE) pixcode; + } } } METHODDEF(void) quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* General case, with ordered dithering */ + JSAMPARRAY output_buf, int num_rows) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register JSAMPROW input_ptr; @@ -205516,41 +187192,31 @@ quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { - /* Initialize output values to 0 so can process components separately */ - jzero_far((void FAR *) output_buf[row], - (size_t) (width * SIZEOF(JSAMPLE))); - row_index = cquantize->row_index; - for (ci = 0; ci < nc; ci++) { - input_ptr = input_buf[row] + ci; - output_ptr = output_buf[row]; - colorindex_ci = cquantize->colorindex[ci]; - dither = cquantize->odither[ci][row_index]; - col_index = 0; + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + row_index = cquantize->row_index; + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + colorindex_ci = cquantize->colorindex[ci]; + dither = cquantize->odither[ci][row_index]; + col_index = 0; - for (col = width; col > 0; col--) { - /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, - * select output value, accumulate into output code for this pixel. - * Range-limiting need not be done explicitly, as we have extended - * the colorindex table to produce the right answers for out-of-range - * inputs. The maximum dither is +- MAXJSAMPLE; this sets the - * required amount of padding. - */ + for (col = width; col > 0; col--) { *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; input_ptr += nc; output_ptr++; col_index = (col_index + 1) & ODITHER_MASK; - } - } - /* Advance row index for next row */ - row_index = (row_index + 1) & ODITHER_MASK; - cquantize->row_index = row_index; + } + } + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; } } METHODDEF(void) quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* Fast path for out_color_components==3, with ordered dithering */ + JSAMPARRAY output_buf, int num_rows) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register int pixcode; @@ -205568,33 +187234,32 @@ quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { - row_index = cquantize->row_index; - input_ptr = input_buf[row]; - output_ptr = output_buf[row]; - dither0 = cquantize->odither[0][row_index]; - dither1 = cquantize->odither[1][row_index]; - dither2 = cquantize->odither[2][row_index]; - col_index = 0; + row_index = cquantize->row_index; + input_ptr = input_buf[row]; + output_ptr = output_buf[row]; + dither0 = cquantize->odither[0][row_index]; + dither1 = cquantize->odither[1][row_index]; + dither2 = cquantize->odither[2][row_index]; + col_index = 0; - for (col = width; col > 0; col--) { - pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + dither0[col_index]]); - pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + dither1[col_index]]); - pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + dither2[col_index]]); - *output_ptr++ = (JSAMPLE) pixcode; - col_index = (col_index + 1) & ODITHER_MASK; - } - row_index = (row_index + 1) & ODITHER_MASK; - cquantize->row_index = row_index; + *output_ptr++ = (JSAMPLE) pixcode; + col_index = (col_index + 1) & ODITHER_MASK; + } + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; } } METHODDEF(void) quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) -/* General case, with Floyd-Steinberg dithering */ + JSAMPARRAY output_buf, int num_rows) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register LOCFSERROR cur; /* current error or pixel value */ @@ -205619,59 +187284,34 @@ quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, SHIFT_TEMPS for (row = 0; row < num_rows; row++) { - /* Initialize output values to 0 so can process components separately */ - jzero_far((void FAR *) output_buf[row], - (size_t) (width * SIZEOF(JSAMPLE))); - for (ci = 0; ci < nc; ci++) { - input_ptr = input_buf[row] + ci; - output_ptr = output_buf[row]; - if (cquantize->on_odd_row) { - /* work right to left in this row */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + if (cquantize->on_odd_row) { input_ptr += (width-1) * nc; /* so point to rightmost pixel */ output_ptr += width-1; dir = -1; dirnc = -nc; errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ - } else { - /* work left to right in this row */ + } else { dir = 1; dirnc = nc; errorptr = cquantize->fserrors[ci]; /* => entry before first column */ - } - colorindex_ci = cquantize->colorindex[ci]; - colormap_ci = cquantize->sv_colormap[ci]; - /* Preset error values: no error propagated to first pixel from left */ - cur = 0; - /* and no error propagated to row below yet */ - belowerr = bpreverr = 0; + } + colorindex_ci = cquantize->colorindex[ci]; + colormap_ci = cquantize->sv_colormap[ci]; + cur = 0; + belowerr = bpreverr = 0; - for (col = width; col > 0; col--) { - /* cur holds the error propagated from the previous pixel on the - * current line. Add the error propagated from the previous line - * to form the complete error correction term for this pixel, and - * round the error term (which is expressed * 16) to an integer. - * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct - * for either sign of the error value. - * Note: errorptr points to *previous* column's array entry. - */ + for (col = width; col > 0; col--) { cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE; this sets the required size - * of the range_limit array. - */ cur += GETJSAMPLE(*input_ptr); cur = GETJSAMPLE(range_limit[cur]); - /* Select output value, accumulate into output code for this pixel */ pixcode = GETJSAMPLE(colorindex_ci[cur]); *output_ptr += (JSAMPLE) pixcode; - /* Compute actual representation error at this pixel */ - /* Note: we can do this even though we don't have the final */ - /* pixel code, because the colormap is orthogonal. */ cur -= GETJSAMPLE(colormap_ci[pixcode]); - /* Compute error fractions to be propagated to adjacent pixels. - * Add these into the running sums, and simultaneously shift the - * next-line error sums left by 1 column. - */ bnexterr = cur; delta = cur * 2; cur += delta; /* form error * 3 */ @@ -205680,28 +187320,16 @@ quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, bpreverr = belowerr + cur; belowerr = bnexterr; cur += delta; /* form error * 7 */ - /* At this point cur contains the 7/16 error value to be propagated - * to the next pixel on the current line, and all the errors for the - * next line have been shifted over. We are therefore ready to move on. - */ input_ptr += dirnc; /* advance input ptr to next column */ output_ptr += dir; /* advance output ptr to next column */ errorptr += dir; /* advance errorptr to current column */ - } - /* Post-loop cleanup: we must unload the final error value into the - * final fserrors[] entry. Note we need not unload belowerr because - * it is for the dummy column before or after the actual array. - */ - errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ - } - cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); + } + errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ + } + cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); } } -/* - * Allocate workspace for Floyd-Steinberg errors. - */ - LOCAL(void) alloc_fs_workspace (j_decompress_ptr cinfo) { @@ -205711,15 +187339,11 @@ alloc_fs_workspace (j_decompress_ptr cinfo) arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); for (i = 0; i < cinfo->out_color_components; i++) { - cquantize->fserrors[i] = (FSERRPTR) - (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + cquantize->fserrors[i] = (FSERRPTR) + (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); } } -/* - * Initialize for one-pass color quantization. - */ - METHODDEF(void) start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) { @@ -205727,83 +187351,60 @@ start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) size_t arraysize; int i; - /* Install my colormap. */ cinfo->colormap = cquantize->sv_colormap; cinfo->actual_number_of_colors = cquantize->sv_actual; - /* Initialize for desired dithering mode. */ switch (cinfo->dither_mode) { case JDITHER_NONE: - if (cinfo->out_color_components == 3) - cquantize->pub.color_quantize = color_quantize3; - else - cquantize->pub.color_quantize = color_quantize; - break; + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = color_quantize3; + else + cquantize->pub.color_quantize = color_quantize; + break; case JDITHER_ORDERED: - if (cinfo->out_color_components == 3) - cquantize->pub.color_quantize = quantize3_ord_dither; - else - cquantize->pub.color_quantize = quantize_ord_dither; - cquantize->row_index = 0; /* initialize state for ordered dither */ - /* If user changed to ordered dither from another mode, - * we must recreate the color index table with padding. - * This will cost extra space, but probably isn't very likely. - */ - if (! cquantize->is_padded) - create_colorindex(cinfo); - /* Create ordered-dither tables if we didn't already. */ - if (cquantize->odither[0] == NULL) - create_odither_tables(cinfo); - break; + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = quantize3_ord_dither; + else + cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->row_index = 0; /* initialize state for ordered dither */ + if (! cquantize->is_padded) + create_colorindex(cinfo); + if (cquantize->odither[0] == NULL) + create_odither_tables(cinfo); + break; case JDITHER_FS: - cquantize->pub.color_quantize = quantize_fs_dither; - cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ - /* Allocate Floyd-Steinberg workspace if didn't already. */ - if (cquantize->fserrors[0] == NULL) - alloc_fs_workspace(cinfo); - /* Initialize the propagated errors to zero. */ - arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); - for (i = 0; i < cinfo->out_color_components; i++) - jzero_far((void FAR *) cquantize->fserrors[i], arraysize); - break; + cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ + if (cquantize->fserrors[0] == NULL) + alloc_fs_workspace(cinfo); + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) + jzero_far((void FAR *) cquantize->fserrors[i], arraysize); + break; default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; } } -/* - * Finish up at the end of the pass. - */ - METHODDEF(void) finish_pass_1_quant (j_decompress_ptr cinfo) { - /* no work in 1-pass case */ } -/* - * Switch to a new external colormap between output passes. - * Shouldn't get to this module! - */ - METHODDEF(void) new_color_map_1_quant (j_decompress_ptr cinfo) { ERREXIT(cinfo, JERR_MODE_CHANGE); } -/* - * Module initialization routine for 1-pass color quantization. - */ - GLOBAL(void) jinit_1pass_quantizer (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; cquantize = (my_cquantize_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_cquantizer)); cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; cquantize->pub.start_pass = start_pass_1_quant; @@ -205812,25 +187413,16 @@ jinit_1pass_quantizer (j_decompress_ptr cinfo) cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ - /* Make sure my internal arrays won't overflow */ if (cinfo->out_color_components > MAX_Q_COMPS) - ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); - /* Make sure colormap indexes can be represented by JSAMPLEs */ + ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); - /* Create the colormap and color index table. */ create_colormap(cinfo); create_colorindex(cinfo); - /* Allocate Floyd-Steinberg workspace now if requested. - * We do this now since it is FAR storage and may affect the memory - * manager's space calculations. If the user changes to FS dither - * mode in a later pass, we will allocate the space then, and will - * possibly overrun the max_memory_to_use setting. - */ if (cinfo->dither_mode == JDITHER_FS) - alloc_fs_workspace(cinfo); + alloc_fs_workspace(cinfo); } #endif /* QUANT_1PASS_SUPPORTED */ @@ -205841,63 +187433,10 @@ jinit_1pass_quantizer (j_decompress_ptr cinfo) #ifdef QUANT_2PASS_SUPPORTED -/* - * This module implements the well-known Heckbert paradigm for color - * quantization. Most of the ideas used here can be traced back to - * Heckbert's seminal paper - * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", - * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. - * - * In the first pass over the image, we accumulate a histogram showing the - * usage count of each possible color. To keep the histogram to a reasonable - * size, we reduce the precision of the input; typical practice is to retain - * 5 or 6 bits per color, so that 8 or 4 different input values are counted - * in the same histogram cell. - * - * Next, the color-selection step begins with a box representing the whole - * color space, and repeatedly splits the "largest" remaining box until we - * have as many boxes as desired colors. Then the mean color in each - * remaining box becomes one of the possible output colors. - * - * The second pass over the image maps each input pixel to the closest output - * color (optionally after applying a Floyd-Steinberg dithering correction). - * This mapping is logically trivial, but making it go fast enough requires - * considerable care. - * - * Heckbert-style quantizers vary a good deal in their policies for choosing - * the "largest" box and deciding where to cut it. The particular policies - * used here have proved out well in experimental comparisons, but better ones - * may yet be found. - * - * In earlier versions of the IJG code, this module quantized in YCbCr color - * space, processing the raw upsampled data without a color conversion step. - * This allowed the color conversion math to be done only once per colormap - * entry, not once per pixel. However, that optimization precluded other - * useful optimizations (such as merging color conversion with upsampling) - * and it also interfered with desired capabilities such as quantizing to an - * externally-supplied colormap. We have therefore abandoned that approach. - * The present code works in the post-conversion color space, typically RGB. - * - * To improve the visual quality of the results, we actually work in scaled - * RGB space, giving G distances more weight than R, and R in turn more than - * B. To do everything in integer math, we must use integer scale factors. - * The 2/3/1 scale factors used here correspond loosely to the relative - * weights of the colors in the NTSC grayscale equation. - * If you want to use this code to quantize a non-RGB color space, you'll - * probably need to change these scale factors. - */ - #define R_SCALE 2 /* scale R distances by this much */ #define G_SCALE 3 /* scale G distances by this much */ #define B_SCALE 1 /* and B by this much */ -/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined - * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B - * and B,G,R orders. If you define some other weird order in jmorecfg.h, - * you'll get compile errors until you extend this logic. In that case - * you'll probably want to tweak the histogram sizes too. - */ - #if RGB_RED == 0 #define C0_SCALE R_SCALE #endif @@ -205914,47 +187453,16 @@ jinit_1pass_quantizer (j_decompress_ptr cinfo) #define C2_SCALE B_SCALE #endif -/* - * First we have the histogram data structure and routines for creating it. - * - * The number of bits of precision can be adjusted by changing these symbols. - * We recommend keeping 6 bits for G and 5 each for R and B. - * If you have plenty of memory and cycles, 6 bits all around gives marginally - * better results; if you are short of memory, 5 bits all around will save - * some space but degrade the results. - * To maintain a fully accurate histogram, we'd need to allocate a "long" - * (preferably unsigned long) for each cell. In practice this is overkill; - * we can get by with 16 bits per cell. Few of the cell counts will overflow, - * and clamping those that do overflow to the maximum value will give close- - * enough results. This reduces the recommended histogram size from 256Kb - * to 128Kb, which is a useful savings on PC-class machines. - * (In the second pass the histogram space is re-used for pixel mapping data; - * in that capacity, each cell must be able to store zero to the number of - * desired colors. 16 bits/cell is plenty for that too.) - * Since the JPEG code is intended to run in small memory model on 80x86 - * machines, we can't just allocate the histogram in one chunk. Instead - * of a true 3-D array, we use a row of pointers to 2-D arrays. Each - * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and - * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that - * on 80x86 machines, the pointer row is in near memory but the actual - * arrays are in far memory (same arrangement as we use for image arrays). - */ - #define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ -/* These will do the right thing for either R,G,B or B,G,R color order, - * but you may not like the results for other color orders. - */ #define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ #define HIST_C1_BITS 6 /* bits of precision in G histogram */ #define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ -/* Number of elements along histogram axes. */ #define HIST_C0_ELEMS (1<output_width; for (row = 0; row < num_rows; row++) { - ptr = input_buf[row]; - for (col = width; col > 0; col--) { - /* get pixel value and index into the histogram */ - histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] + ptr = input_buf[row]; + for (col = width; col > 0; col--) { + histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] [GETJSAMPLE(ptr[1]) >> C1_SHIFT] [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; - /* increment, check for overflow and undo increment if so. */ - if (++(*histp) <= 0) + if (++(*histp) <= 0) (*histp)--; - ptr += 3; - } + ptr += 3; + } } } -/* - * Next we have the really interesting routines: selection of a colormap - * given the completed histogram. - * These routines work with a list of "boxes", each representing a rectangular - * subset of the input color space (to histogram precision). - */ - typedef struct { - /* The bounds of the box (inclusive); expressed as histogram indexes */ int c0min, c0max; int c1min, c1max; int c2min, c2max; - /* The volume (actually 2-norm) of the box */ INT32 volume; - /* The number of nonzero histogram cells within this box */ long colorcount; } box; @@ -206081,8 +187539,6 @@ typedef box * boxptr; LOCAL(boxptr) find_biggest_color_pop (boxptr boxlist, int numboxes) -/* Find the splittable box with the largest color population */ -/* Returns NULL if no splittable boxes remain */ { register boxptr boxp; register int i; @@ -206090,18 +187546,16 @@ find_biggest_color_pop (boxptr boxlist, int numboxes) boxptr which = NULL; for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { - if (boxp->colorcount > maxc && boxp->volume > 0) { - which = boxp; - maxc = boxp->colorcount; - } + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } } return which; } LOCAL(boxptr) find_biggest_volume (boxptr boxlist, int numboxes) -/* Find the splittable box with the largest (scaled) volume */ -/* Returns NULL if no splittable boxes remain */ { register boxptr boxp; register int i; @@ -206109,18 +187563,16 @@ find_biggest_volume (boxptr boxlist, int numboxes) boxptr which = NULL; for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { - if (boxp->volume > maxv) { - which = boxp; - maxv = boxp->volume; - } + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } } return which; } LOCAL(void) update_box (j_decompress_ptr cinfo, boxptr boxp) -/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ -/* and recompute its volume and population */ { my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize; hist3d histogram = cquantize->histogram; @@ -206135,178 +187587,147 @@ update_box (j_decompress_ptr cinfo, boxptr boxp) c2min = boxp->c2min; c2max = boxp->c2max; if (c0max > c0min) - for (c0 = c0min; c0 <= c0max; c0++) - for (c1 = c1min; c1 <= c1max; c1++) { + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { - boxp->c0min = c0min = c0; - goto have_c0min; + boxp->c0min = c0min = c0; + goto have_c0min; + } } - } have_c0min: if (c0max > c0min) - for (c0 = c0max; c0 >= c0min; c0--) - for (c1 = c1min; c1 <= c1max; c1++) { + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { - boxp->c0max = c0max = c0; - goto have_c0max; + boxp->c0max = c0max = c0; + goto have_c0max; + } } - } have_c0max: if (c1max > c1min) - for (c1 = c1min; c1 <= c1max; c1++) - for (c0 = c0min; c0 <= c0max; c0++) { + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { - boxp->c1min = c1min = c1; - goto have_c1min; + boxp->c1min = c1min = c1; + goto have_c1min; + } } - } have_c1min: if (c1max > c1min) - for (c1 = c1max; c1 >= c1min; c1--) - for (c0 = c0min; c0 <= c0max; c0++) { + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { - boxp->c1max = c1max = c1; - goto have_c1max; + boxp->c1max = c1max = c1; + goto have_c1max; + } } - } have_c1max: if (c2max > c2min) - for (c2 = c2min; c2 <= c2max; c2++) - for (c0 = c0min; c0 <= c0max; c0++) { + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1min][c2]; for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) if (*histp != 0) { - boxp->c2min = c2min = c2; - goto have_c2min; + boxp->c2min = c2min = c2; + goto have_c2min; + } } - } have_c2min: if (c2max > c2min) - for (c2 = c2max; c2 >= c2min; c2--) - for (c0 = c0min; c0 <= c0max; c0++) { + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1min][c2]; for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) if (*histp != 0) { - boxp->c2max = c2max = c2; - goto have_c2max; + boxp->c2max = c2max = c2; + goto have_c2max; + } } - } have_c2max: - /* Update box volume. - * We use 2-norm rather than real volume here; this biases the method - * against making long narrow boxes, and it has the side benefit that - * a box is splittable iff norm > 0. - * Since the differences are expressed in histogram-cell units, - * we have to shift back to JSAMPLE units to get consistent distances; - * after which, we scale according to the selected distance scale factors. - */ dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; - /* Now scan remaining volume of box and compute population */ ccount = 0; for (c0 = c0min; c0 <= c0max; c0++) - for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++, histp++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) if (*histp != 0) { ccount++; } - } + } boxp->colorcount = ccount; } LOCAL(int) median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, - int desired_colors) -/* Repeatedly select and split the largest box until we have enough boxes */ + int desired_colors) { int n,lb; int c0,c1,c2,cmax; register boxptr b1,b2; while (numboxes < desired_colors) { - /* Select box to split. - * Current algorithm: by population for first half, then by volume. - */ - if (numboxes*2 <= desired_colors) { - b1 = find_biggest_color_pop(boxlist, numboxes); - } else { - b1 = find_biggest_volume(boxlist, numboxes); - } - if (b1 == NULL) /* no splittable boxes left! */ - break; - b2 = &boxlist[numboxes]; /* where new box will go */ - /* Copy the color bounds to the new box. */ - b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; - b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; - /* Choose which axis to split the box on. - * Current algorithm: longest scaled axis. - * See notes in update_box about scaling distances. - */ - c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; - c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; - c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; - /* We want to break any ties in favor of green, then red, blue last. - * This code does the right thing for R,G,B or B,G,R color orders only. - */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; #if RGB_RED == 0 - cmax = c1; n = 1; - if (c0 > cmax) { cmax = c0; n = 0; } - if (c2 > cmax) { n = 2; } + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } #else - cmax = c1; n = 1; - if (c2 > cmax) { cmax = c2; n = 2; } - if (c0 > cmax) { n = 0; } + cmax = c1; n = 1; + if (c2 > cmax) { cmax = c2; n = 2; } + if (c0 > cmax) { n = 0; } #endif - /* Choose split point along selected axis, and update box bounds. - * Current algorithm: split at halfway point. - * (Since the box has been shrunk to minimum volume, - * any split will produce two nonempty subboxes.) - * Note that lb value is max for lower box, so must be < old max. - */ - switch (n) { - case 0: - lb = (b1->c0max + b1->c0min) / 2; - b1->c0max = lb; - b2->c0min = lb+1; - break; - case 1: - lb = (b1->c1max + b1->c1min) / 2; - b1->c1max = lb; - b2->c1min = lb+1; - break; - case 2: - lb = (b1->c2max + b1->c2min) / 2; - b1->c2max = lb; - b2->c2min = lb+1; - break; - } - /* Update stats for boxes */ - update_box(cinfo, b1); - update_box(cinfo, b2); - numboxes++; + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + update_box(cinfo, b1); + update_box(cinfo, b2); + numboxes++; } return numboxes; } LOCAL(void) compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) -/* Compute representative color for a box, put it in colormap[icolor] */ { - /* Current algorithm: mean weighted by pixels (not colors) */ - /* Note it is important to get the rounding correct! */ my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize; hist3d histogram = cquantize->histogram; histptr histp; @@ -206323,17 +187744,17 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) c2min = boxp->c2min; c2max = boxp->c2max; for (c0 = c0min; c0 <= c0max; c0++) - for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) { + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { if ((count = *histp++) != 0) { total += count; c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; } - } - } + } + } cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); @@ -206342,16 +187763,13 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) LOCAL(void) select_colors (j_decompress_ptr cinfo, int desired_colors) -/* Master routine for color selection */ { boxptr boxlist; int numboxes; int i; - /* Allocate workspace for box list */ boxlist = (boxptr) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); - /* Initialize one box containing whole space */ + ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); numboxes = 1; boxlist[0].c0min = 0; boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; @@ -206359,71 +187777,14 @@ select_colors (j_decompress_ptr cinfo, int desired_colors) boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; boxlist[0].c2min = 0; boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; - /* Shrink it to actually-used volume and set its statistics */ update_box(cinfo, & boxlist[0]); - /* Perform median-cut to produce final box list */ numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); - /* Compute the representative color for each box, fill colormap */ for (i = 0; i < numboxes; i++) - compute_color(cinfo, & boxlist[i], i); + compute_color(cinfo, & boxlist[i], i); cinfo->actual_number_of_colors = numboxes; TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); } -/* - * These routines are concerned with the time-critical task of mapping input - * colors to the nearest color in the selected colormap. - * - * We re-use the histogram space as an "inverse color map", essentially a - * cache for the results of nearest-color searches. All colors within a - * histogram cell will be mapped to the same colormap entry, namely the one - * closest to the cell's center. This may not be quite the closest entry to - * the actual input color, but it's almost as good. A zero in the cache - * indicates we haven't found the nearest color for that cell yet; the array - * is cleared to zeroes before starting the mapping pass. When we find the - * nearest color for a cell, its colormap index plus one is recorded in the - * cache for future use. The pass2 scanning routines call fill_inverse_cmap - * when they need to use an unfilled entry in the cache. - * - * Our method of efficiently finding nearest colors is based on the "locally - * sorted search" idea described by Heckbert and on the incremental distance - * calculation described by Spencer W. Thomas in chapter III.1 of Graphics - * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that - * the distances from a given colormap entry to each cell of the histogram can - * be computed quickly using an incremental method: the differences between - * distances to adjacent cells themselves differ by a constant. This allows a - * fairly fast implementation of the "brute force" approach of computing the - * distance from every colormap entry to every histogram cell. Unfortunately, - * it needs a work array to hold the best-distance-so-far for each histogram - * cell (because the inner loop has to be over cells, not colormap entries). - * The work array elements have to be INT32s, so the work array would need - * 256Kb at our recommended precision. This is not feasible in DOS machines. - * - * To get around these problems, we apply Thomas' method to compute the - * nearest colors for only the cells within a small subbox of the histogram. - * The work array need be only as big as the subbox, so the memory usage - * problem is solved. Furthermore, we need not fill subboxes that are never - * referenced in pass2; many images use only part of the color gamut, so a - * fair amount of work is saved. An additional advantage of this - * approach is that we can apply Heckbert's locality criterion to quickly - * eliminate colormap entries that are far away from the subbox; typically - * three-fourths of the colormap entries are rejected by Heckbert's criterion, - * and we need not compute their distances to individual cells in the subbox. - * The speed of this approach is heavily influenced by the subbox size: too - * small means too much overhead, too big loses because Heckbert's criterion - * can't eliminate as many colormap entries. Empirically the best subbox - * size seems to be about 1/512th of the histogram (1/8th in each direction). - * - * Thomas' article also describes a refined method which is asymptotically - * faster than the brute-force method, but it is also far more complex and - * cannot efficiently be applied to small subboxes. It is therefore not - * useful for programs intended to be portable to DOS machines. On machines - * with plenty of memory, filling the whole histogram in one shot with Thomas' - * refined method might be faster than the present code --- but then again, - * it might not be any faster, and it's certainly more complicated. - */ - -/* log2(histogram cells in update box) for each axis; this can be adjusted */ #define BOX_C0_LOG (HIST_C0_BITS-3) #define BOX_C1_LOG (HIST_C1_BITS-3) #define BOX_C2_LOG (HIST_C2_BITS-3) @@ -206436,25 +187797,9 @@ select_colors (j_decompress_ptr cinfo, int desired_colors) #define BOX_C1_SHIFT (C1_SHIFT + BOX_C1_LOG) #define BOX_C2_SHIFT (C2_SHIFT + BOX_C2_LOG) -/* - * The next three routines implement inverse colormap filling. They could - * all be folded into one big routine, but splitting them up this way saves - * some stack space (the mindist[] and bestdist[] arrays need not coexist) - * and may allow some compilers to produce better code by registerizing more - * inner-loop variables. - */ - LOCAL(int) find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - JSAMPLE colorlist[]) -/* Locate the colormap entries close enough to an update box to be candidates - * for the nearest entry to some cell(s) in the update box. The update box - * is specified by the center coordinates of its first cell. The number of - * candidate colormap entries is returned, and their colormap indexes are - * placed in colorlist[]. - * This routine uses Heckbert's "locally sorted search" criterion to select - * the colors that need further consideration. - */ + JSAMPLE colorlist[]) { int numcolors = cinfo->actual_number_of_colors; int maxc0, maxc1, maxc2; @@ -206463,12 +187808,6 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, INT32 minmaxdist, min_dist, max_dist, tdist; INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ - /* Compute true coordinates of update box's upper corner and center. - * Actually we compute the coordinates of the center of the upper-corner - * histogram cell, which are the upper bounds of the volume we care about. - * Note that since ">>" rounds down, the "center" values may be closer to - * min than to max; hence comparisons to them must be "<=", not "<". - */ maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); centerc0 = (minc0 + maxc0) >> 1; maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); @@ -206476,98 +187815,82 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); centerc2 = (minc2 + maxc2) >> 1; - /* For each color in colormap, find: - * 1. its minimum squared-distance to any point in the update box - * (zero if color is within update box); - * 2. its maximum squared-distance to any point in the update box. - * Both of these can be found by considering only the corners of the box. - * We save the minimum distance for each color in mindist[]; - * only the smallest maximum distance is of interest. - */ minmaxdist = 0x7FFFFFFFL; for (i = 0; i < numcolors; i++) { - /* We compute the squared-c0-distance term, then add in the other two. */ - x = GETJSAMPLE(cinfo->colormap[0][i]); - if (x < minc0) { - tdist = (x - minc0) * C0_SCALE; - min_dist = tdist*tdist; - tdist = (x - maxc0) * C0_SCALE; - max_dist = tdist*tdist; - } else if (x > maxc0) { - tdist = (x - maxc0) * C0_SCALE; - min_dist = tdist*tdist; - tdist = (x - minc0) * C0_SCALE; - max_dist = tdist*tdist; - } else { - /* within cell range so no contribution to min_dist */ - min_dist = 0; - if (x <= centerc0) { + x = GETJSAMPLE(cinfo->colormap[0][i]); + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + min_dist = 0; + if (x <= centerc0) { tdist = (x - maxc0) * C0_SCALE; max_dist = tdist*tdist; - } else { + } else { tdist = (x - minc0) * C0_SCALE; max_dist = tdist*tdist; - } - } + } + } - x = GETJSAMPLE(cinfo->colormap[1][i]); - if (x < minc1) { - tdist = (x - minc1) * C1_SCALE; - min_dist += tdist*tdist; - tdist = (x - maxc1) * C1_SCALE; - max_dist += tdist*tdist; - } else if (x > maxc1) { - tdist = (x - maxc1) * C1_SCALE; - min_dist += tdist*tdist; - tdist = (x - minc1) * C1_SCALE; - max_dist += tdist*tdist; - } else { - /* within cell range so no contribution to min_dist */ - if (x <= centerc1) { + x = GETJSAMPLE(cinfo->colormap[1][i]); + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + if (x <= centerc1) { tdist = (x - maxc1) * C1_SCALE; max_dist += tdist*tdist; - } else { + } else { tdist = (x - minc1) * C1_SCALE; max_dist += tdist*tdist; - } - } + } + } - x = GETJSAMPLE(cinfo->colormap[2][i]); - if (x < minc2) { - tdist = (x - minc2) * C2_SCALE; - min_dist += tdist*tdist; - tdist = (x - maxc2) * C2_SCALE; - max_dist += tdist*tdist; - } else if (x > maxc2) { - tdist = (x - maxc2) * C2_SCALE; - min_dist += tdist*tdist; - tdist = (x - minc2) * C2_SCALE; - max_dist += tdist*tdist; - } else { - /* within cell range so no contribution to min_dist */ - if (x <= centerc2) { + x = GETJSAMPLE(cinfo->colormap[2][i]); + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + if (x <= centerc2) { tdist = (x - maxc2) * C2_SCALE; max_dist += tdist*tdist; - } else { + } else { tdist = (x - minc2) * C2_SCALE; max_dist += tdist*tdist; - } - } + } + } - mindist[i] = min_dist; /* save away the results */ - if (max_dist < minmaxdist) - minmaxdist = max_dist; + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; } - /* Now we know that no cell in the update box is more than minmaxdist - * away from some colormap entry. Therefore, only colors that are - * within minmaxdist of some part of the box need be considered. - */ ncolors = 0; for (i = 0; i < numcolors; i++) { - if (mindist[i] <= minmaxdist) - colorlist[ncolors++] = (JSAMPLE) i; + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; } return ncolors; } @@ -206575,12 +187898,6 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, LOCAL(void) find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) -/* Find the closest colormap entry for each cell in the update box, - * given the list of candidate colors prepared by find_nearby_colors. - * Return the indexes of the closest entries in the bestcolor[] array. - * This routine uses Thomas' incremental distance calculation method to - * find the distance from a colormap entry to successive cells in the box. - */ { int ic0, ic1, ic2; int i, icolor; @@ -206591,51 +187908,40 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, INT32 xx0, xx1; /* distance increments */ register INT32 xx2; INT32 inc0, inc1, inc2; /* initial values for increments */ - /* This array holds the distance to the nearest-so-far color for each cell */ INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; - /* Initialize best-distance for each cell of the update box */ bptr = bestdist; for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) - *bptr++ = 0x7FFFFFFFL; + *bptr++ = 0x7FFFFFFFL; - /* For each color selected by find_nearby_colors, - * compute its distance to the center of each cell in the box. - * If that's less than best-so-far, update best distance and color number. - */ - - /* Nominal steps between cell centers ("x" in Thomas article) */ #define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) #define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) #define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) for (i = 0; i < numcolors; i++) { - icolor = GETJSAMPLE(colorlist[i]); - /* Compute (square of) distance from minc0/c1/c2 to this color */ - inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; - dist0 = inc0*inc0; - inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; - dist0 += inc1*inc1; - inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; - dist0 += inc2*inc2; - /* Form the initial difference increments */ - inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; - inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; - inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; - /* Now loop over all cells in box, updating distance per Thomas method */ - bptr = bestdist; - cptr = bestcolor; - xx0 = inc0; - for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { - dist1 = dist0; - xx1 = inc1; - for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + icolor = GETJSAMPLE(colorlist[i]); + inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; + dist0 += inc2*inc2; + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { dist2 = dist1; xx2 = inc2; for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { if (dist2 < *bptr) { - *bptr = dist2; - *cptr = (JSAMPLE) icolor; + *bptr = dist2; + *cptr = (JSAMPLE) icolor; } dist2 += xx2; xx2 += 2 * STEP_C2 * STEP_C2; @@ -206644,18 +187950,15 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, } dist1 += xx1; xx1 += 2 * STEP_C1 * STEP_C1; - } - dist0 += xx0; - xx0 += 2 * STEP_C0 * STEP_C0; - } + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } } } LOCAL(void) fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) -/* Fill the inverse-colormap entries in the update box that contains */ -/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ -/* we can fill as many others as we wish.) */ { my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize; hist3d histogram = cquantize->histogram; @@ -206663,57 +187966,40 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) int ic0, ic1, ic2; register JSAMPLE * cptr; /* pointer into bestcolor[] array */ register histptr cachep; /* pointer into main cache array */ - /* This array lists the candidate colormap indexes. */ JSAMPLE colorlist[MAXNUMCOLORS]; int numcolors; /* number of candidate colors */ - /* This array holds the actually closest colormap index for each cell. */ JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; - /* Convert cell coordinates to update box ID */ c0 >>= BOX_C0_LOG; c1 >>= BOX_C1_LOG; c2 >>= BOX_C2_LOG; - /* Compute true coordinates of update box's origin corner. - * Actually we compute the coordinates of the center of the corner - * histogram cell, which are the lower bounds of the volume we care about. - */ minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); - /* Determine which colormap entries are close enough to be candidates - * for the nearest entry to some cell in the update box. - */ numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); - /* Determine the actually nearest colors. */ find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, bestcolor); - /* Save the best color numbers (plus 1) in the main cache array */ c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ c1 <<= BOX_C1_LOG; c2 <<= BOX_C2_LOG; cptr = bestcolor; for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { - for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { - cachep = & histogram[c0+ic0][c1+ic1][c2]; - for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); - } - } + } + } } } -/* - * Map some rows of pixels to the output colormapped representation. - */ - METHODDEF(void) pass2_no_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) -/* This version performs no dithering */ { my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize; hist3d histogram = cquantize->histogram; @@ -206725,28 +188011,23 @@ pass2_no_dither (j_decompress_ptr cinfo, JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { - inptr = input_buf[row]; - outptr = output_buf[row]; - for (col = width; col > 0; col--) { - /* get pixel value and index into the cache */ - c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; - c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; - c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; - cachep = & histogram[c0][c1][c2]; - /* If we have not seen this color before, find nearest colormap entry */ - /* and update the cache */ - if (*cachep == 0) + inptr = input_buf[row]; + outptr = output_buf[row]; + for (col = width; col > 0; col--) { + c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; + c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; + c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; + cachep = & histogram[c0][c1][c2]; + if (*cachep == 0) fill_inverse_cmap(cinfo, c0,c1,c2); - /* Now emit the colormap index for this cell */ - *outptr++ = (JSAMPLE) (*cachep - 1); - } + *outptr++ = (JSAMPLE) (*cachep - 1); + } } } METHODDEF(void) pass2_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) -/* This version performs Floyd-Steinberg dithering */ { my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize; hist3d histogram = cquantize->histogram; @@ -206770,76 +188051,48 @@ pass2_fs_dither (j_decompress_ptr cinfo, SHIFT_TEMPS for (row = 0; row < num_rows; row++) { - inptr = input_buf[row]; - outptr = output_buf[row]; - if (cquantize->on_odd_row) { - /* work right to left in this row */ - inptr += (width-1) * 3; /* so point to rightmost pixel */ - outptr += width-1; - dir = -1; - dir3 = -3; - errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ - cquantize->on_odd_row = FALSE; /* flip for next time */ - } else { - /* work left to right in this row */ - dir = 1; - dir3 = 3; - errorptr = cquantize->fserrors; /* => entry before first real column */ - cquantize->on_odd_row = TRUE; /* flip for next time */ - } - /* Preset error values: no error propagated to first pixel from left */ - cur0 = cur1 = cur2 = 0; - /* and no error propagated to row below yet */ - belowerr0 = belowerr1 = belowerr2 = 0; - bpreverr0 = bpreverr1 = bpreverr2 = 0; + inptr = input_buf[row]; + outptr = output_buf[row]; + if (cquantize->on_odd_row) { + inptr += (width-1) * 3; /* so point to rightmost pixel */ + outptr += width-1; + dir = -1; + dir3 = -3; + errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ + cquantize->on_odd_row = FALSE; /* flip for next time */ + } else { + dir = 1; + dir3 = 3; + errorptr = cquantize->fserrors; /* => entry before first real column */ + cquantize->on_odd_row = TRUE; /* flip for next time */ + } + cur0 = cur1 = cur2 = 0; + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; - for (col = width; col > 0; col--) { - /* curN holds the error propagated from the previous pixel on the - * current line. Add the error propagated from the previous line - * to form the complete error correction term for this pixel, and - * round the error term (which is expressed * 16) to an integer. - * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct - * for either sign of the error value. - * Note: errorptr points to *previous* column's array entry. - */ - cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); - cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); - cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); - /* Limit the error using transfer function set by init_error_limit. - * See comments with init_error_limit for rationale. - */ - cur0 = error_limit[cur0]; - cur1 = error_limit[cur1]; - cur2 = error_limit[cur2]; - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE (or less with error limiting); - * this sets the required size of the range_limit array. - */ - cur0 += GETJSAMPLE(inptr[0]); - cur1 += GETJSAMPLE(inptr[1]); - cur2 += GETJSAMPLE(inptr[2]); - cur0 = GETJSAMPLE(range_limit[cur0]); - cur1 = GETJSAMPLE(range_limit[cur1]); - cur2 = GETJSAMPLE(range_limit[cur2]); - /* Index into the cache with adjusted pixel value */ - cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; - /* If we have not seen this color before, find nearest colormap */ - /* entry and update the cache */ - if (*cachep == 0) + for (col = width; col > 0; col--) { + cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); + cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); + cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + cur0 += GETJSAMPLE(inptr[0]); + cur1 += GETJSAMPLE(inptr[1]); + cur2 += GETJSAMPLE(inptr[2]); + cur0 = GETJSAMPLE(range_limit[cur0]); + cur1 = GETJSAMPLE(range_limit[cur1]); + cur2 = GETJSAMPLE(range_limit[cur2]); + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + if (*cachep == 0) fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); - /* Now emit the colormap index for this cell */ - { register int pixcode = *cachep - 1; + { register int pixcode = *cachep - 1; *outptr = (JSAMPLE) pixcode; - /* Compute representation error for this pixel */ cur0 -= GETJSAMPLE(colormap0[pixcode]); cur1 -= GETJSAMPLE(colormap1[pixcode]); cur2 -= GETJSAMPLE(colormap2[pixcode]); - } - /* Compute error fractions to be propagated to adjacent pixels. - * Add these into the running sums, and simultaneously shift the - * next-line error sums left by 1 column. - */ - { register LOCFSERROR bnexterr, delta; + } + { register LOCFSERROR bnexterr, delta; bnexterr = cur0; /* Process component 0 */ delta = cur0 * 2; @@ -206865,98 +188118,58 @@ pass2_fs_dither (j_decompress_ptr cinfo, bpreverr2 = belowerr2 + cur2; belowerr2 = bnexterr; cur2 += delta; /* form error * 7 */ - } - /* At this point curN contains the 7/16 error value to be propagated - * to the next pixel on the current line, and all the errors for the - * next line have been shifted over. We are therefore ready to move on. - */ - inptr += dir3; /* Advance pixel pointers to next column */ - outptr += dir; - errorptr += dir3; /* advance errorptr to current column */ - } - /* Post-loop cleanup: we must unload the final error values into the - * final fserrors[] entry. Note we need not unload belowerrN because - * it is for the dummy column before or after the actual array. - */ - errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ - errorptr[1] = (FSERROR) bpreverr1; - errorptr[2] = (FSERROR) bpreverr2; + } + inptr += dir3; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; } } -/* - * Initialize the error-limiting transfer function (lookup table). - * The raw F-S error computation can potentially compute error values of up to - * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be - * much less, otherwise obviously wrong pixels will be created. (Typical - * effects include weird fringes at color-area boundaries, isolated bright - * pixels in a dark area, etc.) The standard advice for avoiding this problem - * is to ensure that the "corners" of the color cube are allocated as output - * colors; then repeated errors in the same direction cannot cause cascading - * error buildup. However, that only prevents the error from getting - * completely out of hand; Aaron Giles reports that error limiting improves - * the results even with corner colors allocated. - * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty - * well, but the smoother transfer function used below is even better. Thanks - * to Aaron Giles for this idea. - */ - LOCAL(void) init_error_limit (j_decompress_ptr cinfo) -/* Allocate and fill in the error_limiter table */ { my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize; int * table; int in, out; table = (int *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); + ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ cquantize->error_limiter = table; #define STEPSIZE ((MAXJSAMPLE+1)/16) - /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ out = 0; for (in = 0; in < STEPSIZE; in++, out++) { - table[in] = out; table[-in] = -out; + table[in] = out; table[-in] = -out; } - /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { - table[in] = out; table[-in] = -out; + table[in] = out; table[-in] = -out; } - /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ for (; in <= MAXJSAMPLE; in++) { - table[in] = out; table[-in] = -out; + table[in] = out; table[-in] = -out; } #undef STEPSIZE } -/* - * Finish up at the end of each pass. - */ - METHODDEF(void) finish_pass1 (j_decompress_ptr cinfo) { my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize; - /* Select the representative colors and fill in cinfo->colormap */ cinfo->colormap = cquantize->sv_colormap; select_colors(cinfo, cquantize->desired); - /* Force next pass to zero the color index table */ cquantize->needs_zeroed = TRUE; } METHODDEF(void) finish_pass2 (j_decompress_ptr cinfo) { - /* no work */ } -/* - * Initialize for each processing pass. - */ - METHODDEF(void) start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) { @@ -206964,74 +188177,56 @@ start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) hist3d histogram = cquantize->histogram; int i; - /* Only F-S dithering or no dithering is supported. */ - /* If user asks for ordered dither, give him F-S. */ if (cinfo->dither_mode != JDITHER_NONE) - cinfo->dither_mode = JDITHER_FS; + cinfo->dither_mode = JDITHER_FS; if (is_pre_scan) { - /* Set up method pointers */ - cquantize->pub.color_quantize = prescan_quantize; - cquantize->pub.finish_pass = finish_pass1; - cquantize->needs_zeroed = TRUE; /* Always zero histogram */ + cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub.finish_pass = finish_pass1; + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ } else { - /* Set up method pointers */ - if (cinfo->dither_mode == JDITHER_FS) - cquantize->pub.color_quantize = pass2_fs_dither; - else - cquantize->pub.color_quantize = pass2_no_dither; - cquantize->pub.finish_pass = finish_pass2; + if (cinfo->dither_mode == JDITHER_FS) + cquantize->pub.color_quantize = pass2_fs_dither; + else + cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub.finish_pass = finish_pass2; - /* Make sure color count is acceptable */ - i = cinfo->actual_number_of_colors; - if (i < 1) - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); - if (i > MAXNUMCOLORS) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + i = cinfo->actual_number_of_colors; + if (i < 1) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); - if (cinfo->dither_mode == JDITHER_FS) { - size_t arraysize = (size_t) ((cinfo->output_width + 2) * + if (cinfo->dither_mode == JDITHER_FS) { + size_t arraysize = (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))); - /* Allocate Floyd-Steinberg workspace if we didn't already. */ - if (cquantize->fserrors == NULL) + if (cquantize->fserrors == NULL) cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); - /* Initialize the propagated errors to zero. */ - jzero_far((void FAR *) cquantize->fserrors, arraysize); - /* Make the error-limit table if we didn't already. */ - if (cquantize->error_limiter == NULL) + jzero_far((void FAR *) cquantize->fserrors, arraysize); + if (cquantize->error_limiter == NULL) init_error_limit(cinfo); - cquantize->on_odd_row = FALSE; - } + cquantize->on_odd_row = FALSE; + } } - /* Zero the histogram or inverse color map, if necessary */ if (cquantize->needs_zeroed) { - for (i = 0; i < HIST_C0_ELEMS; i++) { - jzero_far((void FAR *) histogram[i], + for (i = 0; i < HIST_C0_ELEMS; i++) { + jzero_far((void FAR *) histogram[i], HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); - } - cquantize->needs_zeroed = FALSE; + } + cquantize->needs_zeroed = FALSE; } } -/* - * Switch to a new external colormap between output passes. - */ - METHODDEF(void) new_color_map_2_quant (j_decompress_ptr cinfo) { my_cquantize_ptr2 cquantize = (my_cquantize_ptr2) cinfo->cquantize; - /* Reset the inverse color map */ cquantize->needs_zeroed = TRUE; } -/* - * Module initialization routine for 2-pass color quantization. - */ - GLOBAL(void) jinit_2pass_quantizer (j_decompress_ptr cinfo) { @@ -207039,7 +188234,7 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo) int i; cquantize = (my_cquantize_ptr2) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_cquantizer2)); cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; cquantize->pub.start_pass = start_pass_2_quant; @@ -207047,55 +188242,38 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo) cquantize->fserrors = NULL; /* flag optional arrays not allocated */ cquantize->error_limiter = NULL; - /* Make sure jdmaster didn't give me a case I can't handle */ if (cinfo->out_color_components != 3) - ERREXIT(cinfo, JERR_NOTIMPL); + ERREXIT(cinfo, JERR_NOTIMPL); - /* Allocate the histogram/inverse colormap storage */ cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); + ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); for (i = 0; i < HIST_C0_ELEMS; i++) { - cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); } cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ - /* Allocate storage for the completed colormap, if required. - * We do this now since it is FAR storage and may affect - * the memory manager's space calculations. - */ if (cinfo->enable_2pass_quant) { - /* Make sure color count is acceptable */ - int desired = cinfo->desired_number_of_colors; - /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ - if (desired < 8) - ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); - /* Make sure colormap indexes can be represented by JSAMPLEs */ - if (desired > MAXNUMCOLORS) - ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); - cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); - cquantize->desired = desired; + int desired = cinfo->desired_number_of_colors; + if (desired < 8) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); + if (desired > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); + cquantize->desired = desired; } else - cquantize->sv_colormap = NULL; + cquantize->sv_colormap = NULL; - /* Only F-S dithering or no dithering is supported. */ - /* If user asks for ordered dither, give him F-S. */ if (cinfo->dither_mode != JDITHER_NONE) - cinfo->dither_mode = JDITHER_FS; + cinfo->dither_mode = JDITHER_FS; - /* Allocate Floyd-Steinberg workspace if necessary. - * This isn't really needed until pass 2, but again it is FAR storage. - * Although we will cope with a later change in dither_mode, - * we do not promise to honor max_memory_to_use if dither_mode changes. - */ if (cinfo->dither_mode == JDITHER_FS) { - cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); - /* Might as well create the error-limiting table too. */ - init_error_limit(cinfo); + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); + init_error_limit(cinfo); } } @@ -207105,11 +188283,6 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo) /********* Start of inlined file: jutils.c *********/ #define JPEG_INTERNALS -/* - * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element - * of a DCT block read in natural order (left to right, top to bottom). - */ - #if 0 /* This table is not actually needed in v6a */ const int jpeg_zigzag_order[DCTSIZE2] = { @@ -207125,20 +188298,6 @@ const int jpeg_zigzag_order[DCTSIZE2] = { #endif -/* - * jpeg_natural_order[i] is the natural-order position of the i'th element - * of zigzag order. - * - * When reading corrupted data, the Huffman decoders could attempt - * to reference an entry beyond the end of this array (if the decoded - * zero run length reaches past the end of the block). To prevent - * wild stores without adding an inner-loop test, we put some extra - * "63"s after the real entries. This will cause the extra coefficient - * to be stored in location 63 of the block, not somewhere random. - * The worst case would be a run-length of 15, which means we need 16 - * fake entries. - */ - const int jpeg_natural_order[DCTSIZE2+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, @@ -207152,36 +188311,19 @@ const int jpeg_natural_order[DCTSIZE2+16] = { 63, 63, 63, 63, 63, 63, 63, 63 }; -/* - * Arithmetic utilities - */ - GLOBAL(long) jdiv_round_up (long a, long b) -/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ -/* Assumes a >= 0, b > 0 */ { return (a + b - 1L) / b; } GLOBAL(long) jround_up (long a, long b) -/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ -/* Assumes a >= 0, b > 0 */ { a += b - 1L; return a - (a % b); } -/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays - * and coefficient-block arrays. This won't work on 80x86 because the arrays - * are FAR and we're assuming a small-pointer memory model. However, some - * DOS compilers provide far-pointer versions of memcpy() and memset() even - * in the small-model libraries. These will be used if USE_FMEM is defined. - * Otherwise, the routines below do it the hard way. (The performance cost - * is not all that great, because these routines aren't very heavily used.) - */ - #ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ #define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) #define FMEMZERO(target,size) MEMZERO(target,size) @@ -207196,11 +188338,6 @@ GLOBAL(void) jcopy_sample_rows (JSAMPARRAY input_array, int source_row, JSAMPARRAY output_array, int dest_row, int num_rows, JDIMENSION num_cols) -/* Copy some rows of samples from one place to another. - * num_rows rows are copied from input_array[source_row++] - * to output_array[dest_row++]; these areas may overlap for duplication. - * The source and destination arrays must be at least as wide as num_cols. - */ { register JSAMPROW inptr, outptr; #ifdef FMEMCOPY @@ -207214,13 +188351,13 @@ jcopy_sample_rows (JSAMPARRAY input_array, int source_row, output_array += dest_row; for (row = num_rows; row > 0; row--) { - inptr = *input_array++; - outptr = *output_array++; + inptr = *input_array++; + outptr = *output_array++; #ifdef FMEMCOPY - FMEMCOPY(outptr, inptr, count); + FMEMCOPY(outptr, inptr, count); #else - for (count = num_cols; count > 0; count--) - *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ + for (count = num_cols; count > 0; count--) + *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ #endif } } @@ -207228,7 +188365,6 @@ jcopy_sample_rows (JSAMPARRAY input_array, int source_row, GLOBAL(void) jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks) -/* Copy a row of coefficient blocks from one place to another. */ { #ifdef FMEMCOPY FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); @@ -207239,15 +188375,13 @@ jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, inptr = (JCOEFPTR) input_row; outptr = (JCOEFPTR) output_row; for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { - *outptr++ = *inptr++; + *outptr++ = *inptr++; } #endif } GLOBAL(void) jzero_far (void FAR * target, size_t bytestozero) -/* Zero out a chunk of FAR memory. */ -/* This might be sample-array data, block-array data, or alloc_large data. */ { #ifdef FMEMZERO FMEMZERO(target, bytestozero); @@ -207256,26 +188390,20 @@ jzero_far (void FAR * target, size_t bytestozero) register size_t count; for (count = bytestozero; count > 0; count--) { - *ptr++ = 0; + *ptr++ = 0; } #endif } /********* End of inlined file: jutils.c *********/ /********* Start of inlined file: transupp.c *********/ -/* Although this file really shouldn't have access to the library internals, - * it's helpful to let it call jround_up() and jcopy_block_row(). - */ #define JPEG_INTERNALS /********* Start of inlined file: transupp.h *********/ -/* If you happen not to want the image transform support, disable it here */ #ifndef TRANSFORMS_SUPPORTED #define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ #endif -/* Short forms of external names for systems with brain-damaged linkers. */ - #ifdef NEED_SHORT_EXTERNAL_NAMES #define jtransform_request_workspace jTrRequest #define jtransform_adjust_parameters jTrAdjust @@ -207284,10 +188412,6 @@ jzero_far (void FAR * target, size_t bytestozero) #define jcopy_markers_execute jCMrkExec #endif /* NEED_SHORT_EXTERNAL_NAMES */ -/* - * Codes for supported types of image transformations. - */ - typedef enum { JXFORM_NONE, /* no transformation */ JXFORM_FLIP_H, /* horizontal flip */ @@ -207299,74 +188423,30 @@ typedef enum { JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ } JXFORM_CODE; -/* - * Although rotating and flipping data expressed as DCT coefficients is not - * hard, there is an asymmetry in the JPEG format specification for images - * whose dimensions aren't multiples of the iMCU size. The right and bottom - * image edges are padded out to the next iMCU boundary with junk data; but - * no padding is possible at the top and left edges. If we were to flip - * the whole image including the pad data, then pad garbage would become - * visible at the top and/or left, and real pixels would disappear into the - * pad margins --- perhaps permanently, since encoders & decoders may not - * bother to preserve DCT blocks that appear to be completely outside the - * nominal image area. So, we have to exclude any partial iMCUs from the - * basic transformation. - * - * Transpose is the only transformation that can handle partial iMCUs at the - * right and bottom edges completely cleanly. flip_h can flip partial iMCUs - * at the bottom, but leaves any partial iMCUs at the right edge untouched. - * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched. - * The other transforms are defined as combinations of these basic transforms - * and process edge blocks in a way that preserves the equivalence. - * - * The "trim" option causes untransformable partial iMCUs to be dropped; - * this is not strictly lossless, but it usually gives the best-looking - * result for odd-size images. Note that when this option is active, - * the expected mathematical equivalences between the transforms may not hold. - * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim - * followed by -rot 180 -trim trims both edges.) - * - * We also offer a "force to grayscale" option, which simply discards the - * chrominance channels of a YCbCr image. This is lossless in the sense that - * the luminance channel is preserved exactly. It's not the same kind of - * thing as the rotate/flip transformations, but it's convenient to handle it - * as part of this package, mainly because the transformation routines have to - * be aware of the option to know how many components to work on. - */ - typedef struct { - /* Options: set by caller */ JXFORM_CODE transform; /* image transform operator */ boolean trim; /* if TRUE, trim partial MCUs as needed */ boolean force_grayscale; /* if TRUE, convert color image to grayscale */ - /* Internal workspace: caller should not touch these */ int num_components; /* # of components in workspace */ jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ } jpeg_transform_info; #if TRANSFORMS_SUPPORTED -/* Request any required workspace */ EXTERN(void) jtransform_request_workspace JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); -/* Adjust output image parameters */ EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info)); -/* Execute the actual transformation, if any */ + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info)); EXTERN(void) jtransform_execute_transformation JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info)); + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info)); #endif /* TRANSFORMS_SUPPORTED */ -/* - * Support for copying optional markers from source to destination file. - */ - typedef enum { JCOPYOPT_NONE, /* copy no optional markers */ JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ @@ -207375,60 +188455,18 @@ typedef enum { #define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ -/* Setup decompression object to save desired markers in memory */ EXTERN(void) jcopy_markers_setup JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); -/* Copy markers saved in the given source object to the destination object */ EXTERN(void) jcopy_markers_execute JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - JCOPY_OPTION option)); + JCOPY_OPTION option)); /********* End of inlined file: transupp.h *********/ - /* My own external interface */ - #if TRANSFORMS_SUPPORTED -/* - * Lossless image transformation routines. These routines work on DCT - * coefficient arrays and thus do not require any lossy decompression - * or recompression of the image. - * Thanks to Guido Vollbeding for the initial design and code of this feature. - * - * Horizontal flipping is done in-place, using a single top-to-bottom - * pass through the virtual source array. It will thus be much the - * fastest option for images larger than main memory. - * - * The other routines require a set of destination virtual arrays, so they - * need twice as much memory as jpegtran normally does. The destination - * arrays are always written in normal scan order (top to bottom) because - * the virtual array manager expects this. The source arrays will be scanned - * in the corresponding order, which means multiple passes through the source - * arrays for most of the transforms. That could result in much thrashing - * if the image is larger than main memory. - * - * Some notes about the operating environment of the individual transform - * routines: - * 1. Both the source and destination virtual arrays are allocated from the - * source JPEG object, and therefore should be manipulated by calling the - * source's memory manager. - * 2. The destination's component count should be used. It may be smaller - * than the source's when forcing to grayscale. - * 3. Likewise the destination's sampling factors should be used. When - * forcing to grayscale the destination's sampling factors will be all 1, - * and we may as well take that as the effective iMCU size. - * 4. When "trim" is in effect, the destination's dimensions will be the - * trimmed values but the source's will be untrimmed. - * 5. All the routines assume that the source and destination buffers are - * padded out to a full iMCU boundary. This is true, although for the - * source buffer it is an undocumented property of jdcoefct.c. - * Notes 2,3,4 boil down to this: generally we should use the destination's - * dimensions and ignore the source's. - */ - LOCAL(void) do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays) -/* Horizontal flip; done in-place, so no separate dest array is required */ { JDIMENSION MCU_cols, comp_width, blk_x, blk_y; int ci, k, offset_y; @@ -207437,39 +188475,33 @@ do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOEF temp1, temp2; jpeg_component_info *compptr; - /* Horizontal mirroring of DCT blocks is accomplished by swapping - * pairs of blocks in-place. Within a DCT block, we perform horizontal - * mirroring by changing the signs of odd-numbered columns. - * Partial iMCUs at the right edge are left untouched. - */ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_width = MCU_cols * compptr->h_samp_factor; - for (blk_y = 0; blk_y < compptr->height_in_blocks; + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + for (blk_y = 0; blk_y < compptr->height_in_blocks; blk_y += compptr->v_samp_factor) { - buffer = (*srcinfo->mem->access_virt_barray) + buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { ptr1 = buffer[offset_y][blk_x]; ptr2 = buffer[offset_y][comp_width - blk_x - 1]; - /* this unrolled loop doesn't need to know which row it's on... */ for (k = 0; k < DCTSIZE2; k += 2) { - temp1 = *ptr1; /* swap even column */ - temp2 = *ptr2; - *ptr1++ = temp2; - *ptr2++ = temp1; - temp1 = *ptr1; /* swap odd column with sign change */ - temp2 = *ptr2; - *ptr1++ = -temp2; - *ptr2++ = -temp1; + temp1 = *ptr1; /* swap even column */ + temp2 = *ptr2; + *ptr1++ = temp2; + *ptr2++ = temp1; + temp1 = *ptr1; /* swap odd column with sign change */ + temp2 = *ptr2; + *ptr1++ = -temp2; + *ptr2++ = -temp1; + } + } } } - } - } } } @@ -207477,7 +188509,6 @@ LOCAL(void) do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays) -/* Vertical flip */ { JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; int ci, i, j, offset_y; @@ -207486,68 +188517,54 @@ do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; - /* We output into a separate array because we can't touch different - * rows of the source virtual array simultaneously. Otherwise, this - * is a pretty straightforward analog of horizontal flip. - * Within a DCT block, vertical mirroring is done by changing the signs - * of odd-numbered rows. - * Partial iMCUs at the bottom edge are copied verbatim. - */ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_height = MCU_rows * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + compptr = dstinfo->comp_info + ci; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) + dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); - if (dst_blk_y < comp_height) { - /* Row is within the mirrorable area. */ + if (dst_blk_y < comp_height) { src_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); - } else { - /* Bottom-edge blocks will be copied verbatim. */ + } else { src_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, FALSE); - } - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { if (dst_blk_y < comp_height) { - /* Row is within the mirrorable area. */ dst_row_ptr = dst_buffer[offset_y]; src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; - dst_blk_x++) { - dst_ptr = dst_row_ptr[dst_blk_x]; - src_ptr = src_row_ptr[dst_blk_x]; - for (i = 0; i < DCTSIZE; i += 2) { - /* copy even row */ - for (j = 0; j < DCTSIZE; j++) + dst_blk_x++) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + for (j = 0; j < DCTSIZE; j++) *dst_ptr++ = *src_ptr++; - /* copy odd row with sign change */ - for (j = 0; j < DCTSIZE; j++) + for (j = 0; j < DCTSIZE; j++) *dst_ptr++ = - *src_ptr++; - } + } } } else { - /* Just copy row verbatim. */ jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y], compptr->width_in_blocks); } - } - } + } + } } } LOCAL(void) do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jvirt_barray_ptr *dst_coef_arrays) -/* Transpose source into destination */ + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) { JDIMENSION dst_blk_x, dst_blk_y; int ci, i, j, offset_x, offset_y; @@ -207555,34 +188572,29 @@ do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; - /* Transposing pixels within a block just requires transposing the - * DCT coefficients. - * Partial iMCUs at the edges require no special treatment; we simply - * process all the available DCT blocks for every component. - */ for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + compptr = dstinfo->comp_info + ci; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) + dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; - dst_blk_x += compptr->h_samp_factor) { + dst_blk_x += compptr->h_samp_factor) { src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, - (JDIMENSION) compptr->h_samp_factor, FALSE); + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; - for (i = 0; i < DCTSIZE; i++) - for (j = 0; j < DCTSIZE; j++) + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + for (i = 0; i < DCTSIZE; i++) + for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; } } - } - } + } + } } } @@ -207590,11 +188602,6 @@ LOCAL(void) do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays) -/* 90 degree rotation is equivalent to - * 1. Transposing the image; - * 2. Horizontal mirroring. - * These two steps are merged into a single processing routine. - */ { JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; int ci, i, j, offset_x, offset_y; @@ -207602,62 +188609,51 @@ do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; - /* Because of the horizontal mirror step, we can't process partial iMCUs - * at the (output) right edge properly. They just get transposed and - * not mirrored. - */ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_width = MCU_cols * compptr->h_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) + dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; - dst_blk_x += compptr->h_samp_factor) { + dst_blk_x += compptr->h_samp_factor) { src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, - (JDIMENSION) compptr->h_samp_factor, FALSE); + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; - if (dst_blk_x < comp_width) { - /* Block is within the mirrorable area. */ - dst_ptr = dst_buffer[offset_y] + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + if (dst_blk_x < comp_width) { + dst_ptr = dst_buffer[offset_y] [comp_width - dst_blk_x - offset_x - 1]; - for (i = 0; i < DCTSIZE; i++) { + for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; i++; for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; - } - } else { - /* Edge blocks are transposed but not mirrored. */ - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; - for (i = 0; i < DCTSIZE; i++) + } + } else { + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + for (i = 0; i < DCTSIZE; i++) for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; - } + } + } + } } } - } - } } } LOCAL(void) do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jvirt_barray_ptr *dst_coef_arrays) -/* 270 degree rotation is equivalent to - * 1. Horizontal mirroring; - * 2. Transposing the image. - * These two steps are merged into a single processing routine. - */ + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) { JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; int ci, i, j, offset_x, offset_y; @@ -207665,62 +188661,51 @@ do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; - /* Because of the horizontal mirror step, we can't process partial iMCUs - * at the (output) bottom edge properly. They just get transposed and - * not mirrored. - */ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_height = MCU_rows * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + compptr = dstinfo->comp_info + ci; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) + dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; - dst_blk_x += compptr->h_samp_factor) { + dst_blk_x += compptr->h_samp_factor) { src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, - (JDIMENSION) compptr->h_samp_factor, FALSE); + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; - if (dst_blk_y < comp_height) { - /* Block is within the mirrorable area. */ - src_ptr = src_buffer[offset_x] + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; + if (dst_blk_y < comp_height) { + src_ptr = src_buffer[offset_x] [comp_height - dst_blk_y - offset_y - 1]; - for (i = 0; i < DCTSIZE; i++) { + for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) { dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; j++; dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; } - } - } else { - /* Edge blocks are transposed but not mirrored. */ - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; - for (i = 0; i < DCTSIZE; i++) + } + } else { + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + for (i = 0; i < DCTSIZE; i++) for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; - } + } + } + } } } - } - } } } LOCAL(void) do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jvirt_barray_ptr *dst_coef_arrays) -/* 180 degree rotation is equivalent to - * 1. Vertical mirroring; - * 2. Horizontal mirroring. - * These two steps are merged into a single processing routine. - */ + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) { JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; int ci, i, j, offset_y; @@ -207733,98 +188718,79 @@ do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_width = MCU_cols * compptr->h_samp_factor; - comp_height = MCU_rows * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) + dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); - if (dst_blk_y < comp_height) { - /* Row is within the vertically mirrorable area. */ + if (dst_blk_y < comp_height) { src_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); - } else { - /* Bottom-edge rows are only mirrored horizontally. */ + } else { src_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, FALSE); - } - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + } + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { if (dst_blk_y < comp_height) { - /* Row is within the mirrorable area. */ dst_row_ptr = dst_buffer[offset_y]; src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; - /* Process the blocks that can be mirrored both ways. */ for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { - dst_ptr = dst_row_ptr[dst_blk_x]; - src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; - for (i = 0; i < DCTSIZE; i += 2) { - /* For even row, negate every odd column. */ - for (j = 0; j < DCTSIZE; j += 2) { + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE; i += 2) { + for (j = 0; j < DCTSIZE; j += 2) { *dst_ptr++ = *src_ptr++; *dst_ptr++ = - *src_ptr++; - } - /* For odd row, negate every even column. */ - for (j = 0; j < DCTSIZE; j += 2) { + } + for (j = 0; j < DCTSIZE; j += 2) { *dst_ptr++ = - *src_ptr++; *dst_ptr++ = *src_ptr++; - } - } + } + } } - /* Any remaining right-edge blocks are only mirrored vertically. */ for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { - dst_ptr = dst_row_ptr[dst_blk_x]; - src_ptr = src_row_ptr[dst_blk_x]; - for (i = 0; i < DCTSIZE; i += 2) { - for (j = 0; j < DCTSIZE; j++) + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE; i += 2) { + for (j = 0; j < DCTSIZE; j++) *dst_ptr++ = *src_ptr++; - for (j = 0; j < DCTSIZE; j++) + for (j = 0; j < DCTSIZE; j++) *dst_ptr++ = - *src_ptr++; - } + } } } else { - /* Remaining rows are just mirrored horizontally. */ dst_row_ptr = dst_buffer[offset_y]; src_row_ptr = src_buffer[offset_y]; - /* Process the blocks that can be mirrored. */ for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { - dst_ptr = dst_row_ptr[dst_blk_x]; - src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; - for (i = 0; i < DCTSIZE2; i += 2) { - *dst_ptr++ = *src_ptr++; - *dst_ptr++ = - *src_ptr++; - } + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; + for (i = 0; i < DCTSIZE2; i += 2) { + *dst_ptr++ = *src_ptr++; + *dst_ptr++ = - *src_ptr++; + } } - /* Any remaining right-edge blocks are only copied. */ for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { - dst_ptr = dst_row_ptr[dst_blk_x]; - src_ptr = src_row_ptr[dst_blk_x]; - for (i = 0; i < DCTSIZE2; i++) - *dst_ptr++ = *src_ptr++; + dst_ptr = dst_row_ptr[dst_blk_x]; + src_ptr = src_row_ptr[dst_blk_x]; + for (i = 0; i < DCTSIZE2; i++) + *dst_ptr++ = *src_ptr++; + } + } } } - } - } } } LOCAL(void) do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jvirt_barray_ptr *dst_coef_arrays) -/* Transverse transpose is equivalent to - * 1. 180 degree rotation; - * 2. Transposition; - * or - * 1. Horizontal mirroring; - * 2. Transposition; - * 3. Horizontal mirroring. - * These steps are merged into a single processing routine. - */ + jvirt_barray_ptr *src_coef_arrays, + jvirt_barray_ptr *dst_coef_arrays) { JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; int ci, i, j, offset_x, offset_y; @@ -207836,161 +188802,134 @@ do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_width = MCU_cols * compptr->h_samp_factor; - comp_height = MCU_rows * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; + compptr = dstinfo->comp_info + ci; + comp_width = MCU_cols * compptr->h_samp_factor; + comp_height = MCU_rows * compptr->v_samp_factor; + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) + dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; - dst_blk_x += compptr->h_samp_factor) { + dst_blk_x += compptr->h_samp_factor) { src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, - (JDIMENSION) compptr->h_samp_factor, FALSE); + ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, + (JDIMENSION) compptr->h_samp_factor, FALSE); for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { - if (dst_blk_y < comp_height) { - src_ptr = src_buffer[offset_x] + if (dst_blk_y < comp_height) { + src_ptr = src_buffer[offset_x] [comp_height - dst_blk_y - offset_y - 1]; - if (dst_blk_x < comp_width) { - /* Block is within the mirrorable area. */ + if (dst_blk_x < comp_width) { dst_ptr = dst_buffer[offset_y] [comp_width - dst_blk_x - offset_x - 1]; for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) { - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; - j++; - dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; } i++; for (j = 0; j < DCTSIZE; j++) { - dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; - j++; - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; } } - } else { - /* Right-edge blocks are mirrored in y only */ + } else { dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) { - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; - j++; - dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + j++; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; } } - } - } else { - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; - if (dst_blk_x < comp_width) { - /* Bottom-edge blocks are mirrored in x only */ + } + } else { + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; + if (dst_blk_x < comp_width) { dst_ptr = dst_buffer[offset_y] [comp_width - dst_blk_x - offset_x - 1]; for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; i++; for (j = 0; j < DCTSIZE; j++) - dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; + dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; } - } else { - /* At lower right corner, just transpose, no mirroring */ + } else { dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; for (i = 0; i < DCTSIZE; i++) for (j = 0; j < DCTSIZE; j++) - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; - } - } + dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; + } + } + } + } } } - } - } } } -/* Request any required workspace. - * - * We allocate the workspace virtual arrays from the source decompression - * object, so that all the arrays (both the original data and the workspace) - * will be taken into account while making memory management decisions. - * Hence, this routine must be called after jpeg_read_header (which reads - * the image dimensions) and before jpeg_read_coefficients (which realizes - * the source's virtual arrays). - */ - GLOBAL(void) jtransform_request_workspace (j_decompress_ptr srcinfo, - jpeg_transform_info *info) + jpeg_transform_info *info) { jvirt_barray_ptr *coef_arrays = NULL; jpeg_component_info *compptr; int ci; if (info->force_grayscale && - srcinfo->jpeg_color_space == JCS_YCbCr && - srcinfo->num_components == 3) { - /* We'll only process the first component */ - info->num_components = 1; + srcinfo->jpeg_color_space == JCS_YCbCr && + srcinfo->num_components == 3) { + info->num_components = 1; } else { - /* Process all the components */ - info->num_components = srcinfo->num_components; + info->num_components = srcinfo->num_components; } switch (info->transform) { case JXFORM_NONE: case JXFORM_FLIP_H: - /* Don't need a workspace array */ - break; + break; case JXFORM_FLIP_V: case JXFORM_ROT_180: - /* Need workspace arrays having same dimensions as source image. - * Note that we allocate arrays padded out to the next iMCU boundary, - * so that transform routines need not worry about missing edge blocks. - */ - coef_arrays = (jvirt_barray_ptr *) - (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, + coef_arrays = (jvirt_barray_ptr *) + (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, SIZEOF(jvirt_barray_ptr) * info->num_components); - for (ci = 0; ci < info->num_components; ci++) { - compptr = srcinfo->comp_info + ci; - coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) + for (ci = 0; ci < info->num_components; ci++) { + compptr = srcinfo->comp_info + ci; + coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); - } - break; + } + break; case JXFORM_TRANSPOSE: case JXFORM_TRANSVERSE: case JXFORM_ROT_90: case JXFORM_ROT_270: - /* Need workspace arrays having transposed dimensions. - * Note that we allocate arrays padded out to the next iMCU boundary, - * so that transform routines need not worry about missing edge blocks. - */ - coef_arrays = (jvirt_barray_ptr *) - (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, + coef_arrays = (jvirt_barray_ptr *) + (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, SIZEOF(jvirt_barray_ptr) * info->num_components); - for (ci = 0; ci < info->num_components; ci++) { - compptr = srcinfo->comp_info + ci; - coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) + for (ci = 0; ci < info->num_components; ci++) { + compptr = srcinfo->comp_info + ci; + coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) compptr->h_samp_factor); - } - break; + } + break; } info->workspace_coef_arrays = coef_arrays; } -/* Transpose destination image parameters */ - LOCAL(void) transpose_critical_parameters (j_compress_ptr dstinfo) { @@ -208000,54 +188939,45 @@ transpose_critical_parameters (j_compress_ptr dstinfo) JDIMENSION dtemp; UINT16 qtemp; - /* Transpose basic image dimensions */ dtemp = dstinfo->image_width; dstinfo->image_width = dstinfo->image_height; dstinfo->image_height = dtemp; - /* Transpose sampling factors */ for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - itemp = compptr->h_samp_factor; - compptr->h_samp_factor = compptr->v_samp_factor; - compptr->v_samp_factor = itemp; + compptr = dstinfo->comp_info + ci; + itemp = compptr->h_samp_factor; + compptr->h_samp_factor = compptr->v_samp_factor; + compptr->v_samp_factor = itemp; } - /* Transpose quantization tables */ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { - qtblptr = dstinfo->quant_tbl_ptrs[tblno]; - if (qtblptr != NULL) { - for (i = 0; i < DCTSIZE; i++) { + qtblptr = dstinfo->quant_tbl_ptrs[tblno]; + if (qtblptr != NULL) { + for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < i; j++) { qtemp = qtblptr->quantval[i*DCTSIZE+j]; qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i]; qtblptr->quantval[j*DCTSIZE+i] = qtemp; } - } - } + } + } } } -/* Trim off any partial iMCUs on the indicated destination edge */ - LOCAL(void) trim_right_edge (j_compress_ptr dstinfo) { int ci, max_h_samp_factor; JDIMENSION MCU_cols; - /* We have to compute max_h_samp_factor ourselves, - * because it hasn't been set yet in the destination - * (and we don't want to use the source's value). - */ max_h_samp_factor = 1; for (ci = 0; ci < dstinfo->num_components; ci++) { - int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor; - max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor); + int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor; + max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor); } MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE); if (MCU_cols > 0) /* can't trim to 0 pixels */ - dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE); + dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE); } LOCAL(void) @@ -208056,117 +188986,79 @@ trim_bottom_edge (j_compress_ptr dstinfo) int ci, max_v_samp_factor; JDIMENSION MCU_rows; - /* We have to compute max_v_samp_factor ourselves, - * because it hasn't been set yet in the destination - * (and we don't want to use the source's value). - */ max_v_samp_factor = 1; for (ci = 0; ci < dstinfo->num_components; ci++) { - int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor; - max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor); + int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor; + max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor); } MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE); if (MCU_rows > 0) /* can't trim to 0 pixels */ - dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE); + dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE); } -/* Adjust output image parameters as needed. - * - * This must be called after jpeg_copy_critical_parameters() - * and before jpeg_write_coefficients(). - * - * The return value is the set of virtual coefficient arrays to be written - * (either the ones allocated by jtransform_request_workspace, or the - * original source data arrays). The caller will need to pass this value - * to jpeg_write_coefficients(). - */ - GLOBAL(jvirt_barray_ptr *) jtransform_adjust_parameters (j_decompress_ptr srcinfo, - j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info) + j_compress_ptr dstinfo, + jvirt_barray_ptr *src_coef_arrays, + jpeg_transform_info *info) { - /* If force-to-grayscale is requested, adjust destination parameters */ if (info->force_grayscale) { - /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed - * properly. Among other things, the target h_samp_factor & v_samp_factor - * will get set to 1, which typically won't match the source. - * In fact we do this even if the source is already grayscale; that - * provides an easy way of coercing a grayscale JPEG with funny sampling - * factors to the customary 1,1. (Some decoders fail on other factors.) - */ - if ((dstinfo->jpeg_color_space == JCS_YCbCr && + if ((dstinfo->jpeg_color_space == JCS_YCbCr && dstinfo->num_components == 3) || (dstinfo->jpeg_color_space == JCS_GRAYSCALE && dstinfo->num_components == 1)) { - /* We have to preserve the source's quantization table number. */ - int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; - jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); - dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; - } else { - /* Sorry, can't do it */ - ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); - } + int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; + jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); + dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; + } else { + ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); + } } - /* Correct the destination's image dimensions etc if necessary */ switch (info->transform) { case JXFORM_NONE: - /* Nothing to do */ - break; + break; case JXFORM_FLIP_H: - if (info->trim) - trim_right_edge(dstinfo); - break; + if (info->trim) + trim_right_edge(dstinfo); + break; case JXFORM_FLIP_V: - if (info->trim) - trim_bottom_edge(dstinfo); - break; + if (info->trim) + trim_bottom_edge(dstinfo); + break; case JXFORM_TRANSPOSE: - transpose_critical_parameters(dstinfo); - /* transpose does NOT have to trim anything */ - break; + transpose_critical_parameters(dstinfo); + break; case JXFORM_TRANSVERSE: - transpose_critical_parameters(dstinfo); - if (info->trim) { - trim_right_edge(dstinfo); - trim_bottom_edge(dstinfo); - } - break; + transpose_critical_parameters(dstinfo); + if (info->trim) { + trim_right_edge(dstinfo); + trim_bottom_edge(dstinfo); + } + break; case JXFORM_ROT_90: - transpose_critical_parameters(dstinfo); - if (info->trim) - trim_right_edge(dstinfo); - break; + transpose_critical_parameters(dstinfo); + if (info->trim) + trim_right_edge(dstinfo); + break; case JXFORM_ROT_180: - if (info->trim) { - trim_right_edge(dstinfo); - trim_bottom_edge(dstinfo); - } - break; + if (info->trim) { + trim_right_edge(dstinfo); + trim_bottom_edge(dstinfo); + } + break; case JXFORM_ROT_270: - transpose_critical_parameters(dstinfo); - if (info->trim) - trim_bottom_edge(dstinfo); - break; + transpose_critical_parameters(dstinfo); + if (info->trim) + trim_bottom_edge(dstinfo); + break; } - /* Return the appropriate output data set */ if (info->workspace_coef_arrays != NULL) - return info->workspace_coef_arrays; + return info->workspace_coef_arrays; return src_coef_arrays; } -/* Execute the actual transformation, if any. - * - * This must be called *after* jpeg_write_coefficients, because it depends - * on jpeg_write_coefficients to have computed subsidiary values such as - * the per-component width and height fields in the destination object. - * - * Note that some transformations will modify the source data arrays! - */ - GLOBAL(void) jtransform_execute_transformation (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, @@ -208177,75 +189069,57 @@ jtransform_execute_transformation (j_decompress_ptr srcinfo, switch (info->transform) { case JXFORM_NONE: - break; + break; case JXFORM_FLIP_H: - do_flip_h(srcinfo, dstinfo, src_coef_arrays); - break; + do_flip_h(srcinfo, dstinfo, src_coef_arrays); + break; case JXFORM_FLIP_V: - do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); - break; + do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; case JXFORM_TRANSPOSE: - do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); - break; + do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; case JXFORM_TRANSVERSE: - do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); - break; + do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; case JXFORM_ROT_90: - do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); - break; + do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; case JXFORM_ROT_180: - do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); - break; + do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; case JXFORM_ROT_270: - do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); - break; + do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); + break; } } #endif /* TRANSFORMS_SUPPORTED */ -/* Setup decompression object to save desired markers in memory. - * This must be called before jpeg_read_header() to have the desired effect. - */ - GLOBAL(void) jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option) { #ifdef SAVE_MARKERS_SUPPORTED int m; - /* Save comments except under NONE option */ if (option != JCOPYOPT_NONE) { - jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); + jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF); } - /* Save all types of APPn markers iff ALL option */ if (option == JCOPYOPT_ALL) { - for (m = 0; m < 16; m++) - jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); + for (m = 0; m < 16; m++) + jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF); } #endif /* SAVE_MARKERS_SUPPORTED */ } -/* Copy markers saved in the given source object to the destination object. - * This should be called just after jpeg_start_compress() or - * jpeg_write_coefficients(). - * Note that those routines will have written the SOI, and also the - * JFIF APP0 or Adobe APP14 markers if selected. - */ - GLOBAL(void) jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - JCOPY_OPTION option) + JCOPY_OPTION option) { jpeg_saved_marker_ptr marker; - /* In the current implementation, we don't actually need to examine the - * option flag here; we just copy everything that got saved. - * But to avoid confusion, we do not output JFIF and Adobe APP14 markers - * if the encoder library already wrote one. - */ for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) { - if (dstinfo->write_JFIF_header && + if (dstinfo->write_JFIF_header && marker->marker == JPEG_APP0 && marker->data_length >= 5 && GETJOCTET(marker->data[0]) == 0x4A && @@ -208253,8 +189127,8 @@ jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, GETJOCTET(marker->data[2]) == 0x49 && GETJOCTET(marker->data[3]) == 0x46 && GETJOCTET(marker->data[4]) == 0) - continue; /* reject duplicate JFIF */ - if (dstinfo->write_Adobe_marker && + continue; /* reject duplicate JFIF */ + if (dstinfo->write_Adobe_marker && marker->marker == JPEG_APP0+14 && marker->data_length >= 5 && GETJOCTET(marker->data[0]) == 0x41 && @@ -208262,18 +189136,17 @@ jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, GETJOCTET(marker->data[2]) == 0x6F && GETJOCTET(marker->data[3]) == 0x62 && GETJOCTET(marker->data[4]) == 0x65) - continue; /* reject duplicate Adobe */ + continue; /* reject duplicate Adobe */ #ifdef NEED_FAR_POINTERS - /* We could use jpeg_write_marker if the data weren't FAR... */ - { - unsigned int i; - jpeg_write_m_header(dstinfo, marker->marker, marker->data_length); - for (i = 0; i < marker->data_length; i++) + { + unsigned int i; + jpeg_write_m_header(dstinfo, marker->marker, marker->data_length); + for (i = 0; i < marker->data_length; i++) jpeg_write_m_byte(dstinfo, marker->data[i]); - } + } #else - jpeg_write_marker(dstinfo, marker->marker, - marker->data, marker->data_length); + jpeg_write_marker(dstinfo, marker->marker, + marker->data, marker->data_length); #endif } } @@ -208303,22 +189176,22 @@ struct JPEGDecodingFailure {}; static void fatalErrorHandler (j_common_ptr) { - throw JPEGDecodingFailure(); + throw JPEGDecodingFailure(); } -static void silentErrorCallback1 (j_common_ptr) {} -static void silentErrorCallback2 (j_common_ptr, int) {} +static void silentErrorCallback1 (j_common_ptr) {} +static void silentErrorCallback2 (j_common_ptr, int) {} static void silentErrorCallback3 (j_common_ptr, char*) {} static void setupSilentErrorHandler (struct jpeg_error_mgr& err) { - zerostruct (err); + zerostruct (err); - err.error_exit = fatalErrorHandler; - err.emit_message = silentErrorCallback2; - err.output_message = silentErrorCallback1; - err.format_message = silentErrorCallback3; - err.reset_error_mgr = silentErrorCallback1; + err.error_exit = fatalErrorHandler; + err.emit_message = silentErrorCallback2; + err.output_message = silentErrorCallback1; + err.format_message = silentErrorCallback3; + err.reset_error_mgr = silentErrorCallback1; } static void dummyCallback1 (j_decompress_ptr) @@ -208327,117 +189200,117 @@ static void dummyCallback1 (j_decompress_ptr) static void jpegSkip (j_decompress_ptr decompStruct, long num) { - decompStruct->src->next_input_byte += num; + decompStruct->src->next_input_byte += num; - num = jmin (num, (int) decompStruct->src->bytes_in_buffer); - decompStruct->src->bytes_in_buffer -= num; + num = jmin (num, (long) decompStruct->src->bytes_in_buffer); + decompStruct->src->bytes_in_buffer -= num; } static boolean jpegFill (j_decompress_ptr) { - return 0; + return 0; } Image* juce_loadJPEGImageFromStream (InputStream& in) { - MemoryBlock mb; - in.readIntoMemoryBlock (mb); + MemoryBlock mb; + in.readIntoMemoryBlock (mb); - Image* image = 0; + Image* image = 0; - if (mb.getSize() > 16) - { - struct jpeg_decompress_struct jpegDecompStruct; + if (mb.getSize() > 16) + { + struct jpeg_decompress_struct jpegDecompStruct; - struct jpeg_error_mgr jerr; - setupSilentErrorHandler (jerr); - jpegDecompStruct.err = &jerr; + struct jpeg_error_mgr jerr; + setupSilentErrorHandler (jerr); + jpegDecompStruct.err = &jerr; - jpeg_create_decompress (&jpegDecompStruct); + jpeg_create_decompress (&jpegDecompStruct); - jpegDecompStruct.src = (jpeg_source_mgr*)(jpegDecompStruct.mem->alloc_small) - ((j_common_ptr)(&jpegDecompStruct), JPOOL_PERMANENT, sizeof (jpeg_source_mgr)); + jpegDecompStruct.src = (jpeg_source_mgr*)(jpegDecompStruct.mem->alloc_small) + ((j_common_ptr)(&jpegDecompStruct), JPOOL_PERMANENT, sizeof (jpeg_source_mgr)); - jpegDecompStruct.src->init_source = dummyCallback1; - jpegDecompStruct.src->fill_input_buffer = jpegFill; - jpegDecompStruct.src->skip_input_data = jpegSkip; - jpegDecompStruct.src->resync_to_restart = jpeg_resync_to_restart; - jpegDecompStruct.src->term_source = dummyCallback1; + jpegDecompStruct.src->init_source = dummyCallback1; + jpegDecompStruct.src->fill_input_buffer = jpegFill; + jpegDecompStruct.src->skip_input_data = jpegSkip; + jpegDecompStruct.src->resync_to_restart = jpeg_resync_to_restart; + jpegDecompStruct.src->term_source = dummyCallback1; - jpegDecompStruct.src->next_input_byte = (const unsigned char*) mb.getData(); - jpegDecompStruct.src->bytes_in_buffer = mb.getSize(); + jpegDecompStruct.src->next_input_byte = (const unsigned char*) mb.getData(); + jpegDecompStruct.src->bytes_in_buffer = mb.getSize(); - try - { - jpeg_read_header (&jpegDecompStruct, TRUE); + try + { + jpeg_read_header (&jpegDecompStruct, TRUE); - jpeg_calc_output_dimensions (&jpegDecompStruct); + jpeg_calc_output_dimensions (&jpegDecompStruct); - const int width = jpegDecompStruct.output_width; - const int height = jpegDecompStruct.output_height; + const int width = jpegDecompStruct.output_width; + const int height = jpegDecompStruct.output_height; - jpegDecompStruct.out_color_space = JCS_RGB; + jpegDecompStruct.out_color_space = JCS_RGB; - JSAMPARRAY buffer - = (*jpegDecompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegDecompStruct, - JPOOL_IMAGE, - width * 3, 1); + JSAMPARRAY buffer + = (*jpegDecompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegDecompStruct, + JPOOL_IMAGE, + width * 3, 1); - if (jpeg_start_decompress (&jpegDecompStruct)) - { - image = Image::createNativeImage (Image::RGB, width, height, false); - const bool hasAlphaChan = image->hasAlphaChannel(); + if (jpeg_start_decompress (&jpegDecompStruct)) + { + image = Image::createNativeImage (Image::RGB, width, height, false); + const bool hasAlphaChan = image->hasAlphaChannel(); - const Image::BitmapData destData (*image, 0, 0, width, height, true); + const Image::BitmapData destData (*image, 0, 0, width, height, true); - for (int y = 0; y < height; ++y) - { - jpeg_read_scanlines (&jpegDecompStruct, buffer, 1); + for (int y = 0; y < height; ++y) + { + jpeg_read_scanlines (&jpegDecompStruct, buffer, 1); - const uint8* src = *buffer; - uint8* dest = destData.getLinePointer (y); + const uint8* src = *buffer; + uint8* dest = destData.getLinePointer (y); - if (hasAlphaChan) - { - for (int i = width; --i >= 0;) - { - ((PixelARGB*) dest)->setARGB (0xff, src[0], src[1], src[2]); - ((PixelARGB*) dest)->premultiply(); - dest += destData.pixelStride; - src += 3; - } - } - else - { - for (int i = width; --i >= 0;) - { - ((PixelRGB*) dest)->setARGB (0xff, src[0], src[1], src[2]); - dest += destData.pixelStride; - src += 3; - } - } - } + if (hasAlphaChan) + { + for (int i = width; --i >= 0;) + { + ((PixelARGB*) dest)->setARGB (0xff, src[0], src[1], src[2]); + ((PixelARGB*) dest)->premultiply(); + dest += destData.pixelStride; + src += 3; + } + } + else + { + for (int i = width; --i >= 0;) + { + ((PixelRGB*) dest)->setARGB (0xff, src[0], src[1], src[2]); + dest += destData.pixelStride; + src += 3; + } + } + } - jpeg_finish_decompress (&jpegDecompStruct); + jpeg_finish_decompress (&jpegDecompStruct); - in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); - } + in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData()); + } - jpeg_destroy_decompress (&jpegDecompStruct); - } - catch (...) - {} - } + jpeg_destroy_decompress (&jpegDecompStruct); + } + catch (...) + {} + } - return image; + return image; } static const int jpegBufferSize = 512; struct JuceJpegDest : public jpeg_destination_mgr { - OutputStream* output; - char* buffer; + OutputStream* output; + char* buffer; }; static void jpegWriteInit (j_compress_ptr) @@ -208446,107 +189319,107 @@ static void jpegWriteInit (j_compress_ptr) static void jpegWriteTerminate (j_compress_ptr cinfo) { - JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest; + JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest; - const int numToWrite = jpegBufferSize - dest->free_in_buffer; - dest->output->write (dest->buffer, numToWrite); + const size_t numToWrite = jpegBufferSize - dest->free_in_buffer; + dest->output->write (dest->buffer, (int) numToWrite); } static boolean jpegWriteFlush (j_compress_ptr cinfo) { - JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest; + JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest; - const int numToWrite = jpegBufferSize; + const int numToWrite = jpegBufferSize; - dest->next_output_byte = (JOCTET*) dest->buffer; - dest->free_in_buffer = jpegBufferSize; + dest->next_output_byte = (JOCTET*) dest->buffer; + dest->free_in_buffer = jpegBufferSize; - return dest->output->write (dest->buffer, numToWrite); + return dest->output->write (dest->buffer, numToWrite); } bool juce_writeJPEGImageToStream (const Image& image, - OutputStream& out, - float quality) + OutputStream& out, + float quality) { - if (image.hasAlphaChannel()) - { - // this method could fill the background in white and still save the image.. - jassertfalse - return true; - } + if (image.hasAlphaChannel()) + { + // this method could fill the background in white and still save the image.. + jassertfalse + return true; + } - struct jpeg_compress_struct jpegCompStruct; + struct jpeg_compress_struct jpegCompStruct; - struct jpeg_error_mgr jerr; - setupSilentErrorHandler (jerr); - jpegCompStruct.err = &jerr; + struct jpeg_error_mgr jerr; + setupSilentErrorHandler (jerr); + jpegCompStruct.err = &jerr; - jpeg_create_compress (&jpegCompStruct); + jpeg_create_compress (&jpegCompStruct); - JuceJpegDest dest; - jpegCompStruct.dest = &dest; + JuceJpegDest dest; + jpegCompStruct.dest = &dest; - dest.output = &out; - HeapBlock tempBuffer (jpegBufferSize); - dest.buffer = (char*) tempBuffer; - dest.next_output_byte = (JOCTET*) dest.buffer; - dest.free_in_buffer = jpegBufferSize; - dest.init_destination = jpegWriteInit; - dest.empty_output_buffer = jpegWriteFlush; - dest.term_destination = jpegWriteTerminate; + dest.output = &out; + HeapBlock tempBuffer (jpegBufferSize); + dest.buffer = (char*) tempBuffer; + dest.next_output_byte = (JOCTET*) dest.buffer; + dest.free_in_buffer = jpegBufferSize; + dest.init_destination = jpegWriteInit; + dest.empty_output_buffer = jpegWriteFlush; + dest.term_destination = jpegWriteTerminate; - jpegCompStruct.image_width = image.getWidth(); - jpegCompStruct.image_height = image.getHeight(); - jpegCompStruct.input_components = 3; - jpegCompStruct.in_color_space = JCS_RGB; - jpegCompStruct.write_JFIF_header = 1; + jpegCompStruct.image_width = image.getWidth(); + jpegCompStruct.image_height = image.getHeight(); + jpegCompStruct.input_components = 3; + jpegCompStruct.in_color_space = JCS_RGB; + jpegCompStruct.write_JFIF_header = 1; - jpegCompStruct.X_density = 72; - jpegCompStruct.Y_density = 72; + jpegCompStruct.X_density = 72; + jpegCompStruct.Y_density = 72; - jpeg_set_defaults (&jpegCompStruct); + jpeg_set_defaults (&jpegCompStruct); - jpegCompStruct.dct_method = JDCT_FLOAT; - jpegCompStruct.optimize_coding = 1; -// jpegCompStruct.smoothing_factor = 10; + jpegCompStruct.dct_method = JDCT_FLOAT; + jpegCompStruct.optimize_coding = 1; +// jpegCompStruct.smoothing_factor = 10; - if (quality < 0.0f) - quality = 0.85f; + if (quality < 0.0f) + quality = 0.85f; - jpeg_set_quality (&jpegCompStruct, jlimit (0, 100, roundFloatToInt (quality * 100.0f)), TRUE); + jpeg_set_quality (&jpegCompStruct, jlimit (0, 100, roundToInt (quality * 100.0f)), TRUE); - jpeg_start_compress (&jpegCompStruct, TRUE); + jpeg_start_compress (&jpegCompStruct, TRUE); - const int strideBytes = jpegCompStruct.image_width * jpegCompStruct.input_components; + const int strideBytes = jpegCompStruct.image_width * jpegCompStruct.input_components; - JSAMPARRAY buffer = (*jpegCompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegCompStruct, - JPOOL_IMAGE, - strideBytes, 1); + JSAMPARRAY buffer = (*jpegCompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegCompStruct, + JPOOL_IMAGE, + strideBytes, 1); - const Image::BitmapData srcData (image, 0, 0, jpegCompStruct.image_width, jpegCompStruct.image_height); + const Image::BitmapData srcData (image, 0, 0, jpegCompStruct.image_width, jpegCompStruct.image_height); - while (jpegCompStruct.next_scanline < jpegCompStruct.image_height) - { - const uint8* src = srcData.getLinePointer (jpegCompStruct.next_scanline); - uint8* dst = *buffer; + while (jpegCompStruct.next_scanline < jpegCompStruct.image_height) + { + const uint8* src = srcData.getLinePointer (jpegCompStruct.next_scanline); + uint8* dst = *buffer; - for (int i = jpegCompStruct.image_width; --i >= 0;) - { - *dst++ = ((const PixelRGB*) src)->getRed(); - *dst++ = ((const PixelRGB*) src)->getGreen(); - *dst++ = ((const PixelRGB*) src)->getBlue(); - src += srcData.pixelStride; - } + for (int i = jpegCompStruct.image_width; --i >= 0;) + { + *dst++ = ((const PixelRGB*) src)->getRed(); + *dst++ = ((const PixelRGB*) src)->getGreen(); + *dst++ = ((const PixelRGB*) src)->getBlue(); + src += srcData.pixelStride; + } - jpeg_write_scanlines (&jpegCompStruct, buffer, 1); - } + jpeg_write_scanlines (&jpegCompStruct, buffer, 1); + } - jpeg_finish_compress (&jpegCompStruct); - jpeg_destroy_compress (&jpegCompStruct); + jpeg_finish_compress (&jpegCompStruct); + jpeg_destroy_compress (&jpegCompStruct); - out.flush(); + out.flush(); - return true; + return true; } END_JUCE_NAMESPACE @@ -208585,380 +189458,16 @@ namespace pnglibNamespace extern "C" { - using ::abs; - #define PNG_INTERNAL - #define NO_DUMMY_DECL - #define PNG_SETJMP_NOT_SUPPORTED + using ::abs; + #define PNG_INTERNAL + #define NO_DUMMY_DECL + #define PNG_SETJMP_NOT_SUPPORTED /********* Start of inlined file: png.h *********/ -/* png.h - header file for PNG reference library - * - * libpng version 1.2.21 - October 4, 2007 - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * Authors and maintainers: - * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat - * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.2.21 - October 4, 2007: Glenn - * See also "Contributing Authors", below. - * - * Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - * 1.0.8rc1 1 10008 2.1.0.8rc1 - * 1.0.8 1 10008 2.1.0.8 - * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - * 1.0.9rc1 1 10009 2.1.0.9rc1 - * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - * 1.0.9rc2 1 10009 2.1.0.9rc2 - * 1.0.9 1 10009 2.1.0.9 - * 1.0.10beta1 1 10010 2.1.0.10beta1 - * 1.0.10rc1 1 10010 2.1.0.10rc1 - * 1.0.10 1 10010 2.1.0.10 - * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - * 1.0.11rc1 1 10011 2.1.0.11rc1 - * 1.0.11 1 10011 2.1.0.11 - * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - * 1.0.12rc1 2 10012 2.1.0.12rc1 - * 1.0.12 2 10012 2.1.0.12 - * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) - * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - * 1.2.0rc1 3 10200 3.1.2.0rc1 - * 1.2.0 3 10200 3.1.2.0 - * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 - * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - * 1.2.1 3 10201 3.1.2.1 - * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - * 1.0.13 10 10013 10.so.0.1.0.13 - * 1.2.2 12 10202 12.so.0.1.2.2 - * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - * 1.2.3 12 10203 12.so.0.1.2.3 - * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 - * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - * 1.0.14 10 10014 10.so.0.1.0.14 - * 1.2.4 13 10204 12.so.0.1.2.4 - * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 - * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 - * 1.0.15 10 10015 10.so.0.1.0.15 - * 1.2.5 13 10205 12.so.0.1.2.5 - * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - * 1.0.16 10 10016 10.so.0.1.0.16 - * 1.2.6 13 10206 12.so.0.1.2.6 - * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - * 1.0.17rc1 10 10017 10.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 10.so.0.1.0.17 - * 1.2.7 13 10207 12.so.0.1.2.7 - * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 - * 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5 - * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - * 1.0.18 10 10018 10.so.0.1.0.18 - * 1.2.8 13 10208 12.so.0.1.2.8 - * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 - * 1.2.9beta4-11 13 10209 12.so.0.9[.0] - * 1.2.9rc1 13 10209 12.so.0.9[.0] - * 1.2.9 13 10209 12.so.0.9[.0] - * 1.2.10beta1-8 13 10210 12.so.0.10[.0] - * 1.2.10rc1-3 13 10210 12.so.0.10[.0] - * 1.2.10 13 10210 12.so.0.10[.0] - * 1.2.11beta1-4 13 10211 12.so.0.11[.0] - * 1.0.19rc1-5 10 10019 10.so.0.19[.0] - * 1.2.11rc1-5 13 10211 12.so.0.11[.0] - * 1.0.19 10 10019 10.so.0.19[.0] - * 1.2.11 13 10211 12.so.0.11[.0] - * 1.0.20 10 10020 10.so.0.20[.0] - * 1.2.12 13 10212 12.so.0.12[.0] - * 1.2.13beta1 13 10213 12.so.0.13[.0] - * 1.0.21 10 10021 10.so.0.21[.0] - * 1.2.13 13 10213 12.so.0.13[.0] - * 1.2.14beta1-2 13 10214 12.so.0.14[.0] - * 1.0.22rc1 10 10022 10.so.0.22[.0] - * 1.2.14rc1 13 10214 12.so.0.14[.0] - * 1.0.22 10 10022 10.so.0.22[.0] - * 1.2.14 13 10214 12.so.0.14[.0] - * 1.2.15beta1-6 13 10215 12.so.0.15[.0] - * 1.0.23rc1-5 10 10023 10.so.0.23[.0] - * 1.2.15rc1-5 13 10215 12.so.0.15[.0] - * 1.0.23 10 10023 10.so.0.23[.0] - * 1.2.15 13 10215 12.so.0.15[.0] - * 1.2.16beta1-2 13 10216 12.so.0.16[.0] - * 1.2.16rc1 13 10216 12.so.0.16[.0] - * 1.0.24 10 10024 10.so.0.24[.0] - * 1.2.16 13 10216 12.so.0.16[.0] - * 1.2.17beta1-2 13 10217 12.so.0.17[.0] - * 1.0.25rc1 10 10025 10.so.0.25[.0] - * 1.2.17rc1-3 13 10217 12.so.0.17[.0] - * 1.0.25 10 10025 10.so.0.25[.0] - * 1.2.17 13 10217 12.so.0.17[.0] - * 1.0.26 10 10026 10.so.0.26[.0] - * 1.2.18 13 10218 12.so.0.18[.0] - * 1.2.19beta1-31 13 10219 12.so.0.19[.0] - * 1.0.27rc1-6 10 10027 10.so.0.27[.0] - * 1.2.19rc1-6 13 10219 12.so.0.19[.0] - * 1.0.27 10 10027 10.so.0.27[.0] - * 1.2.19 13 10219 12.so.0.19[.0] - * 1.2.20beta01-04 13 10220 12.so.0.20[.0] - * 1.0.28rc1-6 10 10028 10.so.0.28[.0] - * 1.2.20rc1-6 13 10220 12.so.0.20[.0] - * 1.0.28 10 10028 10.so.0.28[.0] - * 1.2.20 13 10220 12.so.0.20[.0] - * 1.2.21beta1-2 13 10221 12.so.0.21[.0] - * 1.2.21rc1-3 13 10221 12.so.0.21[.0] - * 1.0.29 10 10029 10.so.0.29[.0] - * 1.2.21 13 10221 12.so.0.21[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng.txt or libpng.3 for more information. The PNG specification - * is available as a W3C Recommendation and as an ISO Specification, - * - * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." - * #define PNG_USER_DLLFNAME_POSTFIX - * e.g. // private DLL "libpng13gx.dll" - * #define PNG_USER_DLLFNAME_POSTFIX "gx" - * - * The following macros are also at your disposal if you want to complete the - * DLL VERSIONINFO structure. - * - PNG_USER_VERSIONINFO_COMMENTS - * - PNG_USER_VERSIONINFO_COMPANYNAME - * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS - */ - #ifdef __STDC__ #ifdef SPECIALBUILD # pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ @@ -209101,199 +189557,112 @@ namespace pnglibNamespace #ifndef PNG_VERSION_INFO_ONLY -/* End of material added to libpng-1.2.8 */ - -/* Added at libpng-1.2.19, removed at libpng-1.2.20 because it caused trouble - Restored at libpng-1.2.21 */ -# define PNG_WARN_UNINITIALIZED_ROW 1 -/* End of material added at libpng-1.2.19/1.2.21 */ - -/* This is the size of the compression buffer, and thus the size of - * an IDAT chunk. Make this whatever size you feel is best for your - * machine. One of these will be allocated per png_struct. When this - * is full, it writes the data to the disk, and does some other - * calculations. Making this an extremely small size will slow - * the library down, but you may want to experiment to determine - * where it becomes significant, if you are concerned with memory - * usage. Note that zlib allocates at least 32Kb also. For readers, - * this describes the size of the buffer available to read the data in. - * Unless this gets smaller than the size of a row (compressed), - * it should not make much difference how big this is. - */ +# define PNG_WARN_UNINITIALIZED_ROW 1 #ifndef PNG_ZBUF_SIZE # define PNG_ZBUF_SIZE 8192 #endif -/* Enable if you want a write-only libpng */ - #ifndef PNG_NO_READ_SUPPORTED # define PNG_READ_SUPPORTED #endif -/* Enable if you want a read-only libpng */ - #ifndef PNG_NO_WRITE_SUPPORTED # define PNG_WRITE_SUPPORTED #endif -/* Enabled by default in 1.2.0. You can disable this if you don't need to - support PNGs that are embedded in MNG datastreams */ #if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES) # ifndef PNG_MNG_FEATURES_SUPPORTED -# define PNG_MNG_FEATURES_SUPPORTED +# define PNG_MNG_FEATURES_SUPPORTED # endif #endif #ifndef PNG_NO_FLOATING_POINT_SUPPORTED # ifndef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FLOATING_POINT_SUPPORTED +# define PNG_FLOATING_POINT_SUPPORTED # endif #endif -/* If you are running on a machine where you cannot allocate more - * than 64K of memory at once, uncomment this. While libpng will not - * normally need that much memory in a chunk (unless you load up a very - * large file), zlib needs to know how big of a chunk it can use, and - * libpng thus makes sure to check any memory allocation to verify it - * will fit into memory. -#define PNG_MAX_MALLOC_64K - */ #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) # define PNG_MAX_MALLOC_64K #endif -/* Special munging to support doing things the 'cygwin' way: - * 'Normal' png-on-win32 defines/defaults: - * PNG_BUILD_DLL -- building dll - * PNG_USE_DLL -- building an application, linking to dll - * (no define) -- building static library, or building an - * application and linking to the static lib - * 'Cygwin' defines/defaults: - * PNG_BUILD_DLL -- (ignored) building the dll - * (no define) -- (ignored) building an application, linking to the dll - * PNG_STATIC -- (ignored) building the static lib, or building an - * application that links to the static lib. - * ALL_STATIC -- (ignored) building various static libs, or building an - * application that links to the static libs. - * Thus, - * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and - * this bit of #ifdefs will define the 'correct' config variables based on - * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but - * unnecessary. - * - * Also, the precedence order is: - * ALL_STATIC (since we can't #undef something outside our namespace) - * PNG_BUILD_DLL - * PNG_STATIC - * (nothing) == PNG_USE_DLL - * - * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent - * of auto-import in binutils, we no longer need to worry about - * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, - * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes - * to __declspec() stuff. However, we DO need to worry about - * PNG_BUILD_DLL and PNG_STATIC because those change some defaults - * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. - */ #if defined(__CYGWIN__) # if defined(ALL_STATIC) -# if defined(PNG_BUILD_DLL) -# undef PNG_BUILD_DLL -# endif -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if defined(PNG_DLL) -# undef PNG_DLL -# endif -# if !defined(PNG_STATIC) -# define PNG_STATIC -# endif +# if defined(PNG_BUILD_DLL) +# undef PNG_BUILD_DLL +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# if !defined(PNG_STATIC) +# define PNG_STATIC +# endif # else -# if defined (PNG_BUILD_DLL) -# if defined(PNG_STATIC) -# undef PNG_STATIC -# endif -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if !defined(PNG_DLL) -# define PNG_DLL -# endif -# else -# if defined(PNG_STATIC) -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if defined(PNG_DLL) -# undef PNG_DLL -# endif -# else -# if !defined(PNG_USE_DLL) -# define PNG_USE_DLL -# endif -# if !defined(PNG_DLL) -# define PNG_DLL -# endif -# endif -# endif +# if defined (PNG_BUILD_DLL) +# if defined(PNG_STATIC) +# undef PNG_STATIC +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# else +# if defined(PNG_STATIC) +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# else +# if !defined(PNG_USE_DLL) +# define PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# endif +# endif # endif #endif -/* This protects us against compilers that run on a windowing system - * and thus don't have or would rather us not use the stdio types: - * stdin, stdout, and stderr. The only one currently used is stderr - * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will - * prevent these from being compiled and used. #defining PNG_NO_STDIO - * will also prevent these, plus will prevent the entire set of stdio - * macros and functions (FILE *, printf, etc.) from being compiled and used, - * unless (PNG_DEBUG > 0) has been #defined. - * - * #define PNG_NO_CONSOLE_IO - * #define PNG_NO_STDIO - */ - #if defined(_WIN32_WCE) # include - /* Console I/O functions are not supported on WindowsCE */ # define PNG_NO_CONSOLE_IO # ifdef PNG_DEBUG -# undef PNG_DEBUG +# undef PNG_DEBUG # endif #endif #ifdef PNG_BUILD_DLL # ifndef PNG_CONSOLE_IO_SUPPORTED -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif # endif #endif # ifdef PNG_NO_STDIO -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif -# ifdef PNG_DEBUG -# if (PNG_DEBUG > 0) -# include -# endif -# endif +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# include +# endif +# endif # else -# if !defined(_WIN32_WCE) -/* "stdio.h" functions are not supported on WindowsCE */ -# include -# endif +# if !defined(_WIN32_WCE) +# include +# endif # endif -/* This macro protects us against machines that don't have function - * prototypes (ie K&R style headers). If your compiler does not handle - * function prototypes, define this macro and use the included ansi2knr. - * I've always been able to use _NO_PROTO as the indicator, but you may - * need to drag the empty declaration out in front of here, or change the - * ifdef to suit your own needs. - */ #ifndef PNGARG #ifdef OF /* zlib prototype munger */ @@ -209303,7 +189672,7 @@ namespace pnglibNamespace #ifdef _NO_PROTO # define PNGARG(arglist) () # ifndef PNG_TYPECAST_NULL -# define PNG_TYPECAST_NULL +# define PNG_TYPECAST_NULL # endif #else # define PNGARG(arglist) arglist @@ -209313,18 +189682,13 @@ namespace pnglibNamespace #endif /* PNGARG */ -/* Try to determine if we are compiling on a Mac. Note that testing for - * just __MWERKS__ is not good enough, because the Codewarrior is now used - * on non-Mac platforms. - */ #ifndef MACOS # if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ - defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) -# define MACOS + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) +# define MACOS # endif #endif -/* enough people need this for various reasons to include it here */ #if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE) # include #endif @@ -209334,32 +189698,25 @@ namespace pnglibNamespace #endif #ifdef PNG_SETJMP_SUPPORTED -/* This is an attempt to force a single setjmp behaviour on Linux. If - * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. - */ # ifdef __linux__ -# ifdef _BSD_SOURCE -# define PNG_SAVE_BSD_SOURCE -# undef _BSD_SOURCE -# endif -# ifdef _SETJMP_H - /* If you encounter a compiler error here, see the explanation - * near the end of INSTALL. - */ - __png.h__ already includes setjmp.h; - __dont__ include it again.; -# endif +# ifdef _BSD_SOURCE +# define PNG_SAVE_BSD_SOURCE +# undef _BSD_SOURCE +# endif +# ifdef _SETJMP_H + __png.h__ already includes setjmp.h; + __dont__ include it again.; +# endif # endif /* __linux__ */ - /* include setjmp.h for error handling */ # include # ifdef __linux__ -# ifdef PNG_SAVE_BSD_SOURCE -# define _BSD_SOURCE -# undef PNG_SAVE_BSD_SOURCE -# endif +# ifdef PNG_SAVE_BSD_SOURCE +# define _BSD_SOURCE +# undef PNG_SAVE_BSD_SOURCE +# endif # endif /* __linux__ */ #endif /* PNG_SETJMP_SUPPORTED */ @@ -209371,65 +189728,39 @@ namespace pnglibNamespace # include #endif -/* Other defines for things like memory and the like can go here. */ #ifdef PNG_INTERNAL #include -/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which - * aren't usually used outside the library (as far as I know), so it is - * debatable if they should be exported at all. In the future, when it is - * possible to have run-time registry of chunk-handling functions, some of - * these will be made available again. -#define PNG_EXTERN extern - */ #define PNG_EXTERN -/* Other defines specific to compilers can go here. Try to keep - * them inside an appropriate ifdef/endif pair for portability. - */ - #if defined(PNG_FLOATING_POINT_SUPPORTED) # if defined(MACOS) - /* We need to check that hasn't already been included earlier - * as it seems it doesn't agree with , yet we should really use - * if possible. - */ -# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) -# include -# endif +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif # else -# include +# include # endif # if defined(_AMIGA) && defined(__SASC) && defined(_M68881) - /* Amiga SAS/C: We must include builtin FPU functions when compiling using - * MATH=68881 - */ -# include +# include # endif #endif -/* Codewarrior on NT has linking problems without this. */ #if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) # define PNG_ALWAYS_EXTERN #endif -/* This provides the non-ANSI (far) memory allocation routines. */ #if defined(__TURBOC__) && defined(__MSDOS__) # include # include #endif -/* I have no idea why is this necessary... */ #if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \ - defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) + defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) # include #endif -/* This controls how fine the dithering gets. As this allocates - * a largish chunk of memory (32K), those who are not as concerned - * with dithering quality can decrease some or all of these. - */ #ifndef PNG_DITHER_RED_BITS # define PNG_DITHER_RED_BITS 5 #endif @@ -209440,97 +189771,43 @@ namespace pnglibNamespace # define PNG_DITHER_BLUE_BITS 5 #endif -/* This controls how fine the gamma correction becomes when you - * are only interested in 8 bits anyway. Increasing this value - * results in more memory being used, and more pow() functions - * being called to fill in the gamma tables. Don't set this value - * less then 8, and even that may not work (I haven't tested it). - */ - #ifndef PNG_MAX_GAMMA_8 # define PNG_MAX_GAMMA_8 11 #endif -/* This controls how much a difference in gamma we can tolerate before - * we actually start doing gamma conversion. - */ #ifndef PNG_GAMMA_THRESHOLD # define PNG_GAMMA_THRESHOLD 0.05 #endif #endif /* PNG_INTERNAL */ -/* The following uses const char * instead of char * for error - * and warning message functions, so some compilers won't complain. - * If you do not want to use const, define PNG_NO_CONST here. - */ - #ifndef PNG_NO_CONST # define PNG_CONST const #else # define PNG_CONST #endif -/* The following defines give you the ability to remove code from the - * library that you will not be using. I wish I could figure out how to - * automate this, but I can't do that without making it seriously hard - * on the users. So if you are not using an ability, change the #define - * to and #undef, and that part of the library will not be compiled. If - * your linker can't find a function, you may want to make sure the - * ability is defined here. Some of these depend upon some others being - * defined. I haven't figured out all the interactions here, so you may - * have to experiment awhile to get everything to compile. If you are - * creating or using a shared library, you probably shouldn't touch this, - * as it will affect the size of the structures, and this will cause bad - * things to happen if the library and/or application ever change. - */ - -/* Any features you will not be using can be undef'ed here */ - -/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user - * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS - * on the compile line, then pick and choose which ones to define without - * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED - * if you only want to have a png-compliant reader/writer but don't need - * any of the extra transformations. This saves about 80 kbytes in a - * typical installation of the library. (PNG_NO_* form added in version - * 1.0.1c, for consistency) - */ - -/* The size of the png_text structure changed in libpng-1.0.6 when - * iTXt support was added. iTXt support was turned off by default through - * libpng-1.2.x, to support old apps that malloc the png_text structure - * instead of calling png_set_text() and letting libpng malloc it. It - * was turned on by default in libpng-1.3.0. - */ - #if defined(PNG_1_0_X) || defined (PNG_1_2_X) # ifndef PNG_NO_iTXt_SUPPORTED -# define PNG_NO_iTXt_SUPPORTED +# define PNG_NO_iTXt_SUPPORTED # endif # ifndef PNG_NO_READ_iTXt -# define PNG_NO_READ_iTXt +# define PNG_NO_READ_iTXt # endif # ifndef PNG_NO_WRITE_iTXt -# define PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_iTXt # endif #endif #if !defined(PNG_NO_iTXt_SUPPORTED) # if !defined(PNG_READ_iTXt_SUPPORTED) && !defined(PNG_NO_READ_iTXt) -# define PNG_READ_iTXt +# define PNG_READ_iTXt # endif # if !defined(PNG_WRITE_iTXt_SUPPORTED) && !defined(PNG_NO_WRITE_iTXt) -# define PNG_WRITE_iTXt +# define PNG_WRITE_iTXt # endif #endif -/* The following support, added after version 1.0.0, can be turned off here en - * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility - * with old applications that require the length of png_struct and png_info - * to remain unchanged. - */ - #ifdef PNG_LEGACY_SUPPORTED # define PNG_NO_FREE_ME # define PNG_NO_READ_UNKNOWN_CHUNKS @@ -209554,9 +189831,8 @@ namespace pnglibNamespace # define PNG_NO_FIXED_POINT_SUPPORTED #endif -/* Ignore attempt to turn off both floating and fixed point support */ #if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ - !defined(PNG_NO_FIXED_POINT_SUPPORTED) + !defined(PNG_NO_FIXED_POINT_SUPPORTED) # define PNG_FIXED_POINT_SUPPORTED #endif @@ -209567,84 +189843,81 @@ namespace pnglibNamespace #if defined(PNG_READ_SUPPORTED) #if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_TRANSFORMS) + !defined(PNG_NO_READ_TRANSFORMS) # define PNG_READ_TRANSFORMS_SUPPORTED #endif #ifdef PNG_READ_TRANSFORMS_SUPPORTED # ifndef PNG_NO_READ_EXPAND -# define PNG_READ_EXPAND_SUPPORTED +# define PNG_READ_EXPAND_SUPPORTED # endif # ifndef PNG_NO_READ_SHIFT -# define PNG_READ_SHIFT_SUPPORTED +# define PNG_READ_SHIFT_SUPPORTED # endif # ifndef PNG_NO_READ_PACK -# define PNG_READ_PACK_SUPPORTED +# define PNG_READ_PACK_SUPPORTED # endif # ifndef PNG_NO_READ_BGR -# define PNG_READ_BGR_SUPPORTED +# define PNG_READ_BGR_SUPPORTED # endif # ifndef PNG_NO_READ_SWAP -# define PNG_READ_SWAP_SUPPORTED +# define PNG_READ_SWAP_SUPPORTED # endif # ifndef PNG_NO_READ_PACKSWAP -# define PNG_READ_PACKSWAP_SUPPORTED +# define PNG_READ_PACKSWAP_SUPPORTED # endif # ifndef PNG_NO_READ_INVERT -# define PNG_READ_INVERT_SUPPORTED +# define PNG_READ_INVERT_SUPPORTED # endif # ifndef PNG_NO_READ_DITHER -# define PNG_READ_DITHER_SUPPORTED +# define PNG_READ_DITHER_SUPPORTED # endif # ifndef PNG_NO_READ_BACKGROUND -# define PNG_READ_BACKGROUND_SUPPORTED +# define PNG_READ_BACKGROUND_SUPPORTED # endif # ifndef PNG_NO_READ_16_TO_8 -# define PNG_READ_16_TO_8_SUPPORTED +# define PNG_READ_16_TO_8_SUPPORTED # endif # ifndef PNG_NO_READ_FILLER -# define PNG_READ_FILLER_SUPPORTED +# define PNG_READ_FILLER_SUPPORTED # endif # ifndef PNG_NO_READ_GAMMA -# define PNG_READ_GAMMA_SUPPORTED +# define PNG_READ_GAMMA_SUPPORTED # endif # ifndef PNG_NO_READ_GRAY_TO_RGB -# define PNG_READ_GRAY_TO_RGB_SUPPORTED +# define PNG_READ_GRAY_TO_RGB_SUPPORTED # endif # ifndef PNG_NO_READ_SWAP_ALPHA -# define PNG_READ_SWAP_ALPHA_SUPPORTED +# define PNG_READ_SWAP_ALPHA_SUPPORTED # endif # ifndef PNG_NO_READ_INVERT_ALPHA -# define PNG_READ_INVERT_ALPHA_SUPPORTED +# define PNG_READ_INVERT_ALPHA_SUPPORTED # endif # ifndef PNG_NO_READ_STRIP_ALPHA -# define PNG_READ_STRIP_ALPHA_SUPPORTED +# define PNG_READ_STRIP_ALPHA_SUPPORTED # endif # ifndef PNG_NO_READ_USER_TRANSFORM -# define PNG_READ_USER_TRANSFORM_SUPPORTED +# define PNG_READ_USER_TRANSFORM_SUPPORTED # endif # ifndef PNG_NO_READ_RGB_TO_GRAY -# define PNG_READ_RGB_TO_GRAY_SUPPORTED +# define PNG_READ_RGB_TO_GRAY_SUPPORTED # endif #endif /* PNG_READ_TRANSFORMS_SUPPORTED */ #if !defined(PNG_NO_PROGRESSIVE_READ) && \ !defined(PNG_PROGRESSIVE_READ_SUPPORTED) /* if you don't do progressive */ # define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ -#endif /* about interlacing capability! You'll */ - /* still have interlacing unless you change the following line: */ +#endif /* about interlacing capability! You'll */ #define PNG_READ_INTERLACING_SUPPORTED /* required in PNG-compliant decoders */ #ifndef PNG_NO_READ_COMPOSITE_NODIV # ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ -# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ # endif #endif #if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Deprecated, will be removed from version 2.0.0. - Use PNG_MNG_FEATURES_SUPPORTED instead. */ #ifndef PNG_NO_READ_EMPTY_PLTE # define PNG_READ_EMPTY_PLTE_SUPPORTED #endif @@ -209655,53 +189928,53 @@ namespace pnglibNamespace #if defined(PNG_WRITE_SUPPORTED) # if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_TRANSFORMS) + !defined(PNG_NO_WRITE_TRANSFORMS) # define PNG_WRITE_TRANSFORMS_SUPPORTED #endif #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED # ifndef PNG_NO_WRITE_SHIFT -# define PNG_WRITE_SHIFT_SUPPORTED +# define PNG_WRITE_SHIFT_SUPPORTED # endif # ifndef PNG_NO_WRITE_PACK -# define PNG_WRITE_PACK_SUPPORTED +# define PNG_WRITE_PACK_SUPPORTED # endif # ifndef PNG_NO_WRITE_BGR -# define PNG_WRITE_BGR_SUPPORTED +# define PNG_WRITE_BGR_SUPPORTED # endif # ifndef PNG_NO_WRITE_SWAP -# define PNG_WRITE_SWAP_SUPPORTED +# define PNG_WRITE_SWAP_SUPPORTED # endif # ifndef PNG_NO_WRITE_PACKSWAP -# define PNG_WRITE_PACKSWAP_SUPPORTED +# define PNG_WRITE_PACKSWAP_SUPPORTED # endif # ifndef PNG_NO_WRITE_INVERT -# define PNG_WRITE_INVERT_SUPPORTED +# define PNG_WRITE_INVERT_SUPPORTED # endif # ifndef PNG_NO_WRITE_FILLER -# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ # endif # ifndef PNG_NO_WRITE_SWAP_ALPHA -# define PNG_WRITE_SWAP_ALPHA_SUPPORTED +# define PNG_WRITE_SWAP_ALPHA_SUPPORTED # endif # ifndef PNG_NO_WRITE_INVERT_ALPHA -# define PNG_WRITE_INVERT_ALPHA_SUPPORTED +# define PNG_WRITE_INVERT_ALPHA_SUPPORTED # endif # ifndef PNG_NO_WRITE_USER_TRANSFORM -# define PNG_WRITE_USER_TRANSFORM_SUPPORTED +# define PNG_WRITE_USER_TRANSFORM_SUPPORTED # endif #endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ #if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ - !defined(PNG_WRITE_INTERLACING_SUPPORTED) + !defined(PNG_WRITE_INTERLACING_SUPPORTED) #define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant - encoders, but can cause trouble - if left undefined */ + encoders, but can cause trouble + if left undefined */ #endif #if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ - !defined(PNG_WRITE_WEIGHTED_FILTER) && \ - defined(PNG_FLOATING_POINT_SUPPORTED) + !defined(PNG_WRITE_WEIGHTED_FILTER) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) # define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED #endif @@ -209710,7 +189983,6 @@ namespace pnglibNamespace #endif #if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */ #ifndef PNG_NO_WRITE_EMPTY_PLTE # define PNG_WRITE_EMPTY_PLTE_SUPPORTED #endif @@ -209720,14 +189992,14 @@ namespace pnglibNamespace #ifndef PNG_1_0_X # ifndef PNG_NO_ERROR_NUMBERS -# define PNG_ERROR_NUMBERS_SUPPORTED +# define PNG_ERROR_NUMBERS_SUPPORTED # endif #endif /* PNG_1_0_X */ #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) # ifndef PNG_NO_USER_TRANSFORM_PTR -# define PNG_USER_TRANSFORM_PTR_SUPPORTED +# define PNG_USER_TRANSFORM_PTR_SUPPORTED # endif #endif @@ -209735,67 +190007,44 @@ namespace pnglibNamespace # define PNG_TIME_RFC1123_SUPPORTED #endif -/* This adds extra functions in pngget.c for accessing data from the - * info pointer (added in version 0.99) - * png_get_image_width() - * png_get_image_height() - * png_get_bit_depth() - * png_get_color_type() - * png_get_compression_type() - * png_get_filter_type() - * png_get_interlace_type() - * png_get_pixel_aspect_ratio() - * png_get_pixels_per_meter() - * png_get_x_offset_pixels() - * png_get_y_offset_pixels() - * png_get_x_offset_microns() - * png_get_y_offset_microns() - */ #if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) # define PNG_EASY_ACCESS_SUPPORTED #endif -/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 - * and removed from version 1.2.20. The following will be removed - * from libpng-1.4.0 -*/ - #if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_OPTIMIZED_CODE) # ifndef PNG_OPTIMIZED_CODE_SUPPORTED -# define PNG_OPTIMIZED_CODE_SUPPORTED +# define PNG_OPTIMIZED_CODE_SUPPORTED # endif #endif #if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) # ifndef PNG_ASSEMBLER_CODE_SUPPORTED -# define PNG_ASSEMBLER_CODE_SUPPORTED +# define PNG_ASSEMBLER_CODE_SUPPORTED # endif # if defined(__GNUC__) && defined(__x86_64__) && (__GNUC__ < 4) - /* work around 64-bit gcc compiler bugs in gcc-3.x */ -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_NO_MMX_CODE -# endif +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif # endif # if defined(__APPLE__) -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_NO_MMX_CODE -# endif +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif # endif # if (defined(__MWERKS__) && ((__MWERKS__ < 0x0900) || macintosh)) -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_NO_MMX_CODE -# endif +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_NO_MMX_CODE +# endif # endif # if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_MMX_CODE_SUPPORTED +# define PNG_MMX_CODE_SUPPORTED # endif #endif -/* end of obsolete code to be removed from libpng-1.4.0 */ #if !defined(PNG_1_0_X) #if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) @@ -209803,7 +190052,6 @@ namespace pnglibNamespace #endif #endif /* PNG_1_0_X */ -/* Added at libpng-1.2.6 */ #if !defined(PNG_1_0_X) #ifndef PNG_SET_USER_LIMITS_SUPPORTED #if !defined(PNG_NO_SET_USER_LIMITS) && !defined(PNG_SET_USER_LIMITS_SUPPORTED) @@ -209812,9 +190060,6 @@ namespace pnglibNamespace #endif #endif /* PNG_1_0_X */ -/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGS no matter - * how large, set these limits to 0x7fffffffL - */ #ifndef PNG_USER_WIDTH_MAX # define PNG_USER_WIDTH_MAX 1000000L #endif @@ -209822,51 +190067,15 @@ namespace pnglibNamespace # define PNG_USER_HEIGHT_MAX 1000000L #endif -/* These are currently experimental features, define them if you want */ - -/* very little testing */ -/* -#ifdef PNG_READ_SUPPORTED -# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# endif -#endif -*/ - -/* This is only for PowerPC big-endian and 680x0 systems */ -/* some testing */ -/* -#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -# define PNG_READ_BIG_ENDIAN_SUPPORTED -#endif -*/ - -/* Buggy compilers (e.g., gcc 2.7.2.2) need this */ -/* -#define PNG_NO_POINTER_INDEXING -*/ - -/* These functions are turned off by default, as they will be phased out. */ -/* -#define PNG_USELESS_TESTS_SUPPORTED -#define PNG_CORRECT_PALETTE_SUPPORTED -*/ - -/* Any chunks you are not interested in, you can undef here. The - * ones that allocate memory may be expecially important (hIST, - * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info - * a bit smaller. - */ - #if defined(PNG_READ_SUPPORTED) && \ - !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_ANCILLARY_CHUNKS) + !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_ANCILLARY_CHUNKS) # define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED #endif #if defined(PNG_WRITE_SUPPORTED) && \ - !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) + !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) # define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED #endif @@ -209899,10 +190108,10 @@ namespace pnglibNamespace #endif #ifndef PNG_NO_READ_iTXt # ifndef PNG_READ_iTXt_SUPPORTED -# define PNG_READ_iTXt_SUPPORTED +# define PNG_READ_iTXt_SUPPORTED # endif # ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED # endif #endif #ifndef PNG_NO_READ_oFFs @@ -209952,28 +190161,28 @@ namespace pnglibNamespace #ifndef PNG_NO_READ_UNKNOWN_CHUNKS # define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED # ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED # endif # ifndef PNG_NO_HANDLE_AS_UNKNOWN -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED # endif #endif #if !defined(PNG_NO_READ_USER_CHUNKS) && \ - defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) # define PNG_READ_USER_CHUNKS_SUPPORTED # define PNG_USER_CHUNKS_SUPPORTED # ifdef PNG_NO_READ_UNKNOWN_CHUNKS -# undef PNG_NO_READ_UNKNOWN_CHUNKS +# undef PNG_NO_READ_UNKNOWN_CHUNKS # endif # ifdef PNG_NO_HANDLE_AS_UNKNOWN -# undef PNG_NO_HANDLE_AS_UNKNOWN +# undef PNG_NO_HANDLE_AS_UNKNOWN # endif #endif #ifndef PNG_NO_READ_OPT_PLTE # define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ -#endif /* optional PLTE chunk in RGB and RGBA images */ +#endif /* optional PLTE chunk in RGB and RGBA images */ #if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ - defined(PNG_READ_zTXt_SUPPORTED) + defined(PNG_READ_zTXt_SUPPORTED) # define PNG_READ_TEXT_SUPPORTED # define PNG_TEXT_SUPPORTED #endif @@ -209990,161 +190199,144 @@ namespace pnglibNamespace #ifndef PNG_NO_WRITE_bKGD # define PNG_WRITE_bKGD_SUPPORTED # ifndef PNG_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_cHRM # define PNG_WRITE_cHRM_SUPPORTED # ifndef PNG_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_gAMA # define PNG_WRITE_gAMA_SUPPORTED # ifndef PNG_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_hIST # define PNG_WRITE_hIST_SUPPORTED # ifndef PNG_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_iCCP # define PNG_WRITE_iCCP_SUPPORTED # ifndef PNG_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_iTXt # ifndef PNG_WRITE_iTXt_SUPPORTED -# define PNG_WRITE_iTXt_SUPPORTED +# define PNG_WRITE_iTXt_SUPPORTED # endif # ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_oFFs # define PNG_WRITE_oFFs_SUPPORTED # ifndef PNG_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_pCAL # define PNG_WRITE_pCAL_SUPPORTED # ifndef PNG_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_sCAL # define PNG_WRITE_sCAL_SUPPORTED # ifndef PNG_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_pHYs # define PNG_WRITE_pHYs_SUPPORTED # ifndef PNG_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_sBIT # define PNG_WRITE_sBIT_SUPPORTED # ifndef PNG_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_sPLT # define PNG_WRITE_sPLT_SUPPORTED # ifndef PNG_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_sRGB # define PNG_WRITE_sRGB_SUPPORTED # ifndef PNG_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_tEXt # define PNG_WRITE_tEXt_SUPPORTED # ifndef PNG_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_tIME # define PNG_WRITE_tIME_SUPPORTED # ifndef PNG_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_tRNS # define PNG_WRITE_tRNS_SUPPORTED # ifndef PNG_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_zTXt # define PNG_WRITE_zTXt_SUPPORTED # ifndef PNG_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED # endif #endif #ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS # define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED # ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED # endif # ifndef PNG_NO_HANDLE_AS_UNKNOWN -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif # endif #endif #if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ - defined(PNG_WRITE_zTXt_SUPPORTED) + defined(PNG_WRITE_zTXt_SUPPORTED) # define PNG_WRITE_TEXT_SUPPORTED # ifndef PNG_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED # endif #endif #endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ -/* Turn this off to disable png_read_png() and - * png_write_png() and leave the row_pointers member - * out of the info structure. - */ #ifndef PNG_NO_INFO_IMAGE # define PNG_INFO_IMAGE_SUPPORTED #endif -/* need the time information for reading tIME chunks */ #if defined(PNG_tIME_SUPPORTED) # if !defined(_WIN32_WCE) - /* "time.h" functions are not supported on WindowsCE */ -# include +# include # endif #endif -/* Some typedefs to get us started. These should be safe on most of the - * common platforms. The typedefs should be at least as large as the - * numbers suggest (a png_uint_32 must be at least 32 bits long), but they - * don't have to be exactly that size. Some compilers dislike passing - * unsigned shorts as function parameters, so you may be better off using - * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may - * want to have unsigned int for png_uint_32 instead of unsigned long. - */ - typedef unsigned long png_uint_32; typedef long png_int_32; typedef unsigned short png_uint_16; typedef short png_int_16; typedef unsigned char png_byte; -/* This is usually size_t. It is typedef'ed just in case you need it to - change (I'm not sure if you will or not, so I thought I'd be safe) */ #ifdef PNG_SIZE_T typedef PNG_SIZE_T png_size_t; # define png_sizeof(x) png_convert_size(sizeof (x)) @@ -210153,174 +190345,112 @@ typedef unsigned char png_byte; # define png_sizeof(x) sizeof (x) #endif -/* The following is needed for medium model support. It cannot be in the - * PNG_INTERNAL section. Needs modification for other compilers besides - * MSC. Model independent support declares all arrays and pointers to be - * large using the far keyword. The zlib version used must also support - * model independent data. As of version zlib 1.0.4, the necessary changes - * have been made in zlib. The USE_FAR_KEYWORD define triggers other - * changes that are needed. (Tim Wegner) - */ - -/* Separate compiler dependencies (problem here is that zlib.h always - defines FAR. (SJT) */ #ifdef __BORLANDC__ # if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) -# define LDATA 1 +# define LDATA 1 # else -# define LDATA 0 +# define LDATA 0 # endif - /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ # if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) -# define PNG_MAX_MALLOC_64K -# if (LDATA != 1) -# ifndef FAR -# define FAR __far -# endif -# define USE_FAR_KEYWORD -# endif /* LDATA != 1 */ - /* Possibly useful for moving data out of default segment. - * Uncomment it if you want. Could also define FARDATA as - * const if your compiler supports it. (SJT) -# define FARDATA FAR - */ +# define PNG_MAX_MALLOC_64K +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ # endif /* __WIN32__, __FLAT__, __CYGWIN__ */ #endif /* __BORLANDC__ */ -/* Suggest testing for specific compiler first before testing for - * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, - * making reliance oncertain keywords suspect. (SJT) - */ - -/* MSC Medium model */ #if defined(FAR) # if defined(M_I86MM) -# define USE_FAR_KEYWORD -# define FARDATA FAR -# include +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include # endif #endif -/* SJT: default case */ #ifndef FAR # define FAR #endif -/* At this point FAR is always defined */ #ifndef FARDATA # define FARDATA #endif -/* Typedef for floating-point numbers that are converted - to fixed-point with a multiple of 100,000, e.g., int_gamma */ typedef png_int_32 png_fixed_point; -/* Add typedefs for pointers */ -typedef void FAR * png_voidp; -typedef png_byte FAR * png_bytep; -typedef png_uint_32 FAR * png_uint_32p; -typedef png_int_32 FAR * png_int_32p; -typedef png_uint_16 FAR * png_uint_16p; -typedef png_int_16 FAR * png_int_16p; +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; typedef PNG_CONST char FAR * png_const_charp; -typedef char FAR * png_charp; +typedef char FAR * png_charp; typedef png_fixed_point FAR * png_fixed_point_p; #ifndef PNG_NO_STDIO #if defined(_WIN32_WCE) -typedef HANDLE png_FILE_p; +typedef HANDLE png_FILE_p; #else -typedef FILE * png_FILE_p; +typedef FILE * png_FILE_p; #endif #endif #ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * png_doublep; +typedef double FAR * png_doublep; #endif -/* Pointers to pointers; i.e. arrays */ -typedef png_byte FAR * FAR * png_bytepp; -typedef png_uint_32 FAR * FAR * png_uint_32pp; -typedef png_int_32 FAR * FAR * png_int_32pp; -typedef png_uint_16 FAR * FAR * png_uint_16pp; -typedef png_int_16 FAR * FAR * png_int_16pp; +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; typedef PNG_CONST char FAR * FAR * png_const_charpp; -typedef char FAR * FAR * png_charpp; +typedef char FAR * FAR * png_charpp; typedef png_fixed_point FAR * FAR * png_fixed_point_pp; #ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * FAR * png_doublepp; +typedef double FAR * FAR * png_doublepp; #endif -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char FAR * FAR * FAR * png_charppp; +typedef char FAR * FAR * FAR * png_charppp; #if 0 -/* SPC - Is this stuff deprecated? */ -/* It'll be removed as of libpng-1.3.0 - GR-P */ -/* libpng typedefs for types in zlib. If zlib changes - * or another compression library is used, then change these. - * Eliminates need to change all the source files. - */ -typedef charf * png_zcharp; +typedef charf * png_zcharp; typedef charf * FAR * png_zcharpp; typedef z_stream FAR * png_zstreamp; #endif /* (PNG_1_0_X) || defined(PNG_1_2_X) */ -/* - * Define PNG_BUILD_DLL if the module being built is a Windows - * LIBPNG DLL. - * - * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. - * It is equivalent to Microsoft predefined macro _DLL that is - * automatically defined when you compile using the share - * version of the CRT (C Run-Time library) - * - * The cygwin mods make this behavior a little different: - * Define PNG_BUILD_DLL if you are building a dll for use with cygwin - * Define PNG_STATIC if you are building a static library for use with cygwin, - * -or- if you are building an application that you want to link to the - * static library. - * PNG_USE_DLL is defined by default (no user action needed) unless one of - * the other flags is defined. - */ - #if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) # define PNG_DLL #endif -/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib. - * When building a static lib, default to no GLOBAL ARRAYS, but allow - * command-line override - */ #if defined(__CYGWIN__) # if !defined(PNG_STATIC) -# if defined(PNG_USE_GLOBAL_ARRAYS) -# undef PNG_USE_GLOBAL_ARRAYS -# endif -# if !defined(PNG_USE_LOCAL_ARRAYS) -# define PNG_USE_LOCAL_ARRAYS -# endif +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif # else -# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) -# if defined(PNG_USE_GLOBAL_ARRAYS) -# undef PNG_USE_GLOBAL_ARRAYS -# endif -# endif +# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# endif # endif # if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) -# define PNG_USE_LOCAL_ARRAYS +# define PNG_USE_LOCAL_ARRAYS # endif #endif -/* Do not use global arrays (helps with building DLL's) - * They are no longer used in libpng itself, since version 1.0.5c, - * but might be required for some pre-1.0.5c applications. - */ #if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) # if defined(PNG_NO_GLOBAL_ARRAYS) || \ - (defined(__GNUC__) && defined(PNG_DLL)) || defined(_MSC_VER) -# define PNG_USE_LOCAL_ARRAYS + (defined(__GNUC__) && defined(PNG_DLL)) || defined(_MSC_VER) +# define PNG_USE_LOCAL_ARRAYS # else -# define PNG_USE_GLOBAL_ARRAYS +# define PNG_USE_GLOBAL_ARRAYS # endif #endif @@ -210331,16 +190461,9 @@ typedef z_stream FAR * png_zstreamp; # define PNG_IMPEXP #endif -/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", - * you may get warnings regarding the linkage of png_zalloc and png_zfree. - * Don't ignore those warnings; you must also reset the default calling - * convention in your compiler to match your PNGAPI, and you must build - * zlib and your applications the same way you build libpng. - */ - #if defined(__MINGW32__) && !defined(PNG_MODULEDEF) # ifndef PNG_NO_MODULEDEF -# define PNG_NO_MODULEDEF +# define PNG_NO_MODULEDEF # endif #endif @@ -210349,59 +190472,58 @@ typedef z_stream FAR * png_zstreamp; #endif #if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ - (( defined(_Windows) || defined(_WINDOWS) || \ - defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) + (( defined(_Windows) || defined(_WINDOWS) || \ + defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) # ifndef PNGAPI -# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) -# define PNGAPI __cdecl -# else -# define PNGAPI _cdecl -# endif +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGAPI __cdecl +# else +# define PNGAPI _cdecl +# endif # endif # if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ - 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) -# define PNG_IMPEXP + 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) +# define PNG_IMPEXP # endif # if !defined(PNG_IMPEXP) -# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol -# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol +# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol +# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol - /* Borland/Microsoft */ -# if defined(_MSC_VER) || defined(__BORLANDC__) -# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) -# define PNG_EXPORT PNG_EXPORT_TYPE1 -# else -# define PNG_EXPORT PNG_EXPORT_TYPE2 -# if defined(PNG_BUILD_DLL) -# define PNG_IMPEXP __export -# else -# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in - VC++ */ -# endif /* Exists in Borland C++ for - C++ classes (== huge) */ -# endif -# endif +# if defined(_MSC_VER) || defined(__BORLANDC__) +# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) +# define PNG_EXPORT PNG_EXPORT_TYPE1 +# else +# define PNG_EXPORT PNG_EXPORT_TYPE2 +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __export +# else +# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in + VC++ */ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ +# endif +# endif -# if !defined(PNG_IMPEXP) -# if defined(PNG_BUILD_DLL) -# define PNG_IMPEXP __declspec(dllexport) -# else -# define PNG_IMPEXP __declspec(dllimport) -# endif -# endif +# if !defined(PNG_IMPEXP) +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __declspec(dllexport) +# else +# define PNG_IMPEXP __declspec(dllimport) +# endif +# endif # endif /* PNG_IMPEXP */ #else /* !(DLL || non-cygwin WINDOWS) */ # if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# ifndef PNGAPI -# define PNGAPI _System -# endif +# ifndef PNGAPI +# define PNGAPI _System +# endif # else -# if 0 /* ... other platforms, with other meanings */ -# endif +# if 0 /* ... other platforms, with other meanings */ +# endif # endif #endif @@ -210414,12 +190536,12 @@ typedef z_stream FAR * png_zstreamp; #ifdef PNG_BUILDSYMS # ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END +# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END # endif # ifdef PNG_USE_GLOBAL_ARRAYS -# ifndef PNG_EXPORT_VAR -# define PNG_EXPORT_VAR(type) PNG_DATA_EXPORT -# endif +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) PNG_DATA_EXPORT +# endif # endif #endif @@ -210429,14 +190551,10 @@ typedef z_stream FAR * png_zstreamp; #ifdef PNG_USE_GLOBAL_ARRAYS # ifndef PNG_EXPORT_VAR -# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type +# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type # endif #endif -/* User may want to use these so they are not in PNG_INTERNAL. Any library - * functions that are passed far data must be model independent. - */ - #ifndef PNG_ABORT # define PNG_ABORT() abort() #endif @@ -210449,7 +190567,6 @@ typedef z_stream FAR * png_zstreamp; #endif #if defined(USE_FAR_KEYWORD) /* memory model independent fns */ -/* use this to make far-to-near assignments */ # define CHECK 1 # define NOCHECK 0 # define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) @@ -210458,51 +190575,41 @@ typedef z_stream FAR * png_zstreamp; # define png_strcpy _fstrcpy # define png_strncpy _fstrncpy /* Added to v 1.2.6 */ # define png_strlen _fstrlen -# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcmp _fmemcmp /* SJT: added */ # define png_memcpy _fmemcpy # define png_memset _fmemset #else /* use the usual functions */ -# define CVT_PTR(ptr) (ptr) +# define CVT_PTR(ptr) (ptr) # define CVT_PTR_NOCHECK(ptr) (ptr) # ifndef PNG_NO_SNPRINTF -# ifdef _MSC_VER -# define png_snprintf _snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 _snprintf -# define png_snprintf6 _snprintf -# else -# define png_snprintf snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 snprintf -# define png_snprintf6 snprintf -# endif +# ifdef _MSC_VER +# define png_snprintf _snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 _snprintf +# define png_snprintf6 _snprintf +# else +# define png_snprintf snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 snprintf +# define png_snprintf6 snprintf +# endif # else - /* You don't have or don't want to use snprintf(). Caution: Using - * sprintf instead of snprintf exposes your application to accidental - * or malevolent buffer overflows. If you don't have snprintf() - * as a general rule you should provide one (you can get one from - * Portable OpenSSH). */ -# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) -# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) -# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ - sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) +# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) +# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) +# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ + sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) # endif # define png_strcpy strcpy -# define png_strncpy strncpy /* Added to v 1.2.6 */ +# define png_strncpy strncpy /* Added to v 1.2.6 */ # define png_strlen strlen -# define png_memcmp memcmp /* SJT: added */ +# define png_memcmp memcmp /* SJT: added */ # define png_memcpy memcpy # define png_memset memset #endif -/* End of memory model independent support */ -/* Just a little check that someone hasn't tried to define something - * contradictory. - */ #if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) # undef PNG_ZBUF_SIZE # define PNG_ZBUF_SIZE 65536L #endif -/* Added at libpng-1.2.8 */ #endif /* PNG_VERSION_INFO_ONLY */ #endif /* PNGCONF_H */ @@ -210512,110 +190619,76 @@ typedef z_stream FAR * png_zstreamp; #pragma warning (disable: 4996 4100) #endif -/* - * Added at libpng-1.2.8 */ -/* Ref MSDN: Private as priority over Special - * VS_FF_PRIVATEBUILD File *was not* built using standard release - * procedures. If this value is given, the StringFileInfo block must - * contain a PrivateBuild string. - * - * VS_FF_SPECIALBUILD File *was* built by the original company using - * standard release procedures but is a variation of the standard - * file of the same version number. If this value is given, the - * StringFileInfo block must contain a SpecialBuild string. - */ - #if defined(PNG_USER_PRIVATEBUILD) # define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) #else # if defined(PNG_LIBPNG_SPECIALBUILD) -# define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) # else -# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) # endif #endif #ifndef PNG_VERSION_INFO_ONLY -/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -/* This file is arranged in several sections. The first section contains - * structure and type definitions. The second section contains the external - * library functions, while the third has the internal library functions, - * which applications aren't expected to use directly. - */ - #ifndef PNG_NO_TYPECAST_NULL -#define int_p_NULL (int *)NULL -#define png_bytep_NULL (png_bytep)NULL -#define png_bytepp_NULL (png_bytepp)NULL -#define png_doublep_NULL (png_doublep)NULL -#define png_error_ptr_NULL (png_error_ptr)NULL -#define png_flush_ptr_NULL (png_flush_ptr)NULL -#define png_free_ptr_NULL (png_free_ptr)NULL -#define png_infopp_NULL (png_infopp)NULL -#define png_malloc_ptr_NULL (png_malloc_ptr)NULL +#define int_p_NULL (int *)NULL +#define png_bytep_NULL (png_bytep)NULL +#define png_bytepp_NULL (png_bytepp)NULL +#define png_doublep_NULL (png_doublep)NULL +#define png_error_ptr_NULL (png_error_ptr)NULL +#define png_flush_ptr_NULL (png_flush_ptr)NULL +#define png_free_ptr_NULL (png_free_ptr)NULL +#define png_infopp_NULL (png_infopp)NULL +#define png_malloc_ptr_NULL (png_malloc_ptr)NULL #define png_read_status_ptr_NULL (png_read_status_ptr)NULL -#define png_rw_ptr_NULL (png_rw_ptr)NULL -#define png_structp_NULL (png_structp)NULL -#define png_uint_16p_NULL (png_uint_16p)NULL -#define png_voidp_NULL (png_voidp)NULL +#define png_rw_ptr_NULL (png_rw_ptr)NULL +#define png_structp_NULL (png_structp)NULL +#define png_uint_16p_NULL (png_uint_16p)NULL +#define png_voidp_NULL (png_voidp)NULL #define png_write_status_ptr_NULL (png_write_status_ptr)NULL #else -#define int_p_NULL NULL -#define png_bytep_NULL NULL -#define png_bytepp_NULL NULL -#define png_doublep_NULL NULL -#define png_error_ptr_NULL NULL -#define png_flush_ptr_NULL NULL -#define png_free_ptr_NULL NULL -#define png_infopp_NULL NULL -#define png_malloc_ptr_NULL NULL +#define int_p_NULL NULL +#define png_bytep_NULL NULL +#define png_bytepp_NULL NULL +#define png_doublep_NULL NULL +#define png_error_ptr_NULL NULL +#define png_flush_ptr_NULL NULL +#define png_free_ptr_NULL NULL +#define png_infopp_NULL NULL +#define png_malloc_ptr_NULL NULL #define png_read_status_ptr_NULL NULL -#define png_rw_ptr_NULL NULL -#define png_structp_NULL NULL -#define png_uint_16p_NULL NULL -#define png_voidp_NULL NULL +#define png_rw_ptr_NULL NULL +#define png_structp_NULL NULL +#define png_uint_16p_NULL NULL +#define png_voidp_NULL NULL #define png_write_status_ptr_NULL NULL #endif -/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ #if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) -/* Version information for C files, stored in png.c. This had better match - * the version above. - */ #ifdef PNG_USE_GLOBAL_ARRAYS PNG_EXPORT_VAR (PNG_CONST char) png_libpng_ver[18]; - /* need room for 99.99.99beta99z */ #else #define png_libpng_ver png_get_header_ver(NULL) #endif #ifdef PNG_USE_GLOBAL_ARRAYS -/* This was removed in version 1.0.5c */ -/* Structures to facilitate easy interlacing. See png.c for more details */ PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_start[7]; PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_inc[7]; PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_ystart[7]; PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_yinc[7]; PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_mask[7]; PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_dsp_mask[7]; -/* This isn't currently used. If you need it, see png.c for more details. -PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_height[7]; -*/ #endif #endif /* PNG_NO_EXTERN */ -/* Three color definitions. The order of the red, green, and blue, (and the - * exact size) is not important, although the size of the fields need to - * be png_byte or png_uint_16 (as defined below). - */ typedef struct png_color_struct { png_byte red; @@ -210627,7 +190700,7 @@ typedef png_color FAR * FAR * png_colorpp; typedef struct png_color_16_struct { - png_byte index; /* used for palette files */ + png_byte index; /* used for palette files */ png_uint_16 red; /* for use in red green blue files */ png_uint_16 green; png_uint_16 blue; @@ -210647,10 +190720,6 @@ typedef struct png_color_8_struct typedef png_color_8 FAR * png_color_8p; typedef png_color_8 FAR * FAR * png_color_8pp; -/* - * The following two structures are used for the in-core representation - * of sPLT chunks. - */ typedef struct png_sPLT_entry_struct { png_uint_16 red; @@ -210662,75 +190731,54 @@ typedef struct png_sPLT_entry_struct typedef png_sPLT_entry FAR * png_sPLT_entryp; typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; -/* When the depth of the sPLT palette is 8 bits, the color and alpha samples - * occupy the LSB of their respective members, and the MSB of each member - * is zero-filled. The frequency member always occupies the full 16 bits. - */ - typedef struct png_sPLT_struct { - png_charp name; /* palette name */ - png_byte depth; /* depth of palette samples */ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ png_sPLT_entryp entries; /* palette entries */ - png_int_32 nentries; /* number of palette entries */ + png_int_32 nentries; /* number of palette entries */ } png_sPLT_t; typedef png_sPLT_t FAR * png_sPLT_tp; typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; #ifdef PNG_TEXT_SUPPORTED -/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, - * and whether that contents is compressed or not. The "key" field - * points to a regular zero-terminated C string. The "text", "lang", and - * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. - * However, the * structure returned by png_get_text() will always contain - * regular zero-terminated C strings (possibly empty), never NULL pointers, - * so they can be safely used in printf() and other string-handling functions. - */ typedef struct png_text_struct { - int compression; /* compression value: - -1: tEXt, none - 0: zTXt, deflate - 1: iTXt, none - 2: iTXt, deflate */ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ png_charp key; /* keyword, 1-79 character description of "text" */ png_charp text; /* comment, may be an empty string (ie "") - or a NULL pointer */ + or a NULL pointer */ png_size_t text_length; /* length of the text string */ #ifdef PNG_iTXt_SUPPORTED png_size_t itxt_length; /* length of the itxt string */ - png_charp lang; /* language code, 0-79 characters - or a NULL pointer */ - png_charp lang_key; /* keyword translated UTF-8 string, 0 or more - chars or a NULL pointer */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ #endif } png_text; typedef png_text FAR * png_textp; typedef png_text FAR * FAR * png_textpp; #endif -/* Supported compression types for text in PNG files (tEXt, and zTXt). - * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ #define PNG_TEXT_COMPRESSION_NONE_WR -3 #define PNG_TEXT_COMPRESSION_zTXt_WR -2 -#define PNG_TEXT_COMPRESSION_NONE -1 -#define PNG_TEXT_COMPRESSION_zTXt 0 -#define PNG_ITXT_COMPRESSION_NONE 1 -#define PNG_ITXT_COMPRESSION_zTXt 2 -#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ -/* png_time is a way to hold the time in an machine independent way. - * Two conversions are provided, both from time_t and struct tm. There - * is no portable way to convert to either of these structures, as far - * as I know. If you know of a portable way, send it to me. As a side - * note - PNG has always been Year 2000 compliant! - */ typedef struct png_time_struct { png_uint_16 year; /* full year, as in, 1995 */ png_byte month; /* month of year, 1 - 12 */ - png_byte day; /* day of month, 1 - 31 */ - png_byte hour; /* hour of day, 0 - 23 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ png_byte minute; /* minute of hour, 0 - 59 */ png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ } png_time; @@ -210738,201 +190786,88 @@ typedef png_time FAR * png_timep; typedef png_time FAR * FAR * png_timepp; #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -/* png_unknown_chunk is a structure to hold queued chunks for which there is - * no specific support. The idea is that we can use this to queue - * up private chunks for output even though the library doesn't actually - * know about their semantics. - */ typedef struct png_unknown_chunk_t { - png_byte name[5]; - png_byte *data; - png_size_t size; + png_byte name[5]; + png_byte *data; + png_size_t size; - /* libpng-using applications should NOT directly modify this byte. */ - png_byte location; /* mode of operation at read time */ + png_byte location; /* mode of operation at read time */ } png_unknown_chunk; typedef png_unknown_chunk FAR * png_unknown_chunkp; typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; #endif -/* png_info is a structure that holds the information in a PNG file so - * that the application can find out the characteristics of the image. - * If you are reading the file, this structure will tell you what is - * in the PNG file. If you are writing the file, fill in the information - * you want to put into the PNG file, then call png_write_info(). - * The names chosen should be very close to the PNG specification, so - * consult that document for information about the meaning of each field. - * - * With libpng < 0.95, it was only possible to directly set and read the - * the values in the png_info_struct, which meant that the contents and - * order of the values had to remain fixed. With libpng 0.95 and later, - * however, there are now functions that abstract the contents of - * png_info_struct from the application, so this makes it easier to use - * libpng with dynamic libraries, and even makes it possible to use - * libraries that don't have all of the libpng ancillary chunk-handing - * functionality. - * - * In any case, the order of the parameters in png_info_struct should NOT - * be changed for as long as possible to keep compatibility with applications - * that use the old direct-access method with png_info_struct. - * - * The following members may have allocated storage attached that should be - * cleaned up before the structure is discarded: palette, trans, text, - * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, - * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these - * are automatically freed when the info structure is deallocated, if they were - * allocated internally by libpng. This behavior can be changed by means - * of the png_data_freer() function. - * - * More allocation details: all the chunk-reading functions that - * change these members go through the corresponding png_set_* - * functions. A function to clear these members is available: see - * png_free_data(). The png_set_* functions do not depend on being - * able to point info structure members to any of the storage they are - * passed (they make their own copies), EXCEPT that the png_set_text - * functions use the same storage passed to them in the text_ptr or - * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns - * functions do not make their own copies. - */ typedef struct png_info_struct { - /* the following are necessary for every PNG file */ - png_uint_32 width; /* width of image in pixels (from IHDR) */ - png_uint_32 height; /* height of image in pixels (from IHDR) */ - png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ - png_uint_32 rowbytes; /* bytes needed to hold an untransformed row */ - png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + png_uint_32 rowbytes; /* bytes needed to hold an untransformed row */ + png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ - png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ - png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ - /* The following three should have been named *_method not *_type */ + png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ - png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - /* The following is informational only on read, and not used on writes. */ - png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte spare_byte; /* to align the data, and for future use */ + png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte spare_byte; /* to align the data, and for future use */ png_byte signature[8]; /* magic bytes read by libpng from start of file */ - /* The rest of the data is optional. If you are reading, check the - * valid field to see if the information in these are valid. If you - * are writing, set the valid field to those chunks you want written, - * and initialize the appropriate fields below. - */ - #if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) - /* The gAMA chunk describes the gamma characteristics of the system - * on which the image was created, normally in the range [1.0, 2.5]. - * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. - */ float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */ #endif #if defined(PNG_sRGB_SUPPORTED) - /* GR-P, 0.96a */ - /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */ #endif #if defined(PNG_TEXT_SUPPORTED) - /* The tEXt, and zTXt chunks contain human-readable textual data in - * uncompressed, compressed, and optionally compressed forms, respectively. - * The data in "text" is an array of pointers to uncompressed, - * null-terminated C strings. Each chunk has a keyword that describes the - * textual data contained in that chunk. Keywords are not required to be - * unique, and the text string may be empty. Any number of text chunks may - * be in an image. - */ int num_text; /* number of comments read/to write */ int max_text; /* current size of text array */ png_textp text; /* array of comments read/to write */ #endif /* PNG_TEXT_SUPPORTED */ #if defined(PNG_tIME_SUPPORTED) - /* The tIME chunk holds the last time the displayed image data was - * modified. See the png_time struct for the contents of this struct. - */ png_time mod_time; #endif #if defined(PNG_sBIT_SUPPORTED) - /* The sBIT chunk specifies the number of significant high-order bits - * in the pixel data. Values are in the range [1, bit_depth], and are - * only specified for the channels in the pixel data. The contents of - * the low-order bits is not specified. Data is valid if - * (valid & PNG_INFO_sBIT) is non-zero. - */ png_color_8 sig_bit; /* significant bits in color channels */ #endif #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ defined(PNG_READ_BACKGROUND_SUPPORTED) - /* The tRNS chunk supplies transparency data for paletted images and - * other image types that don't need a full alpha channel. There are - * "num_trans" transparency values for a paletted image, stored in the - * same order as the palette colors, starting from index 0. Values - * for the data are in the range [0, 255], ranging from fully transparent - * to fully opaque, respectively. For non-paletted images, there is a - * single color specified that should be treated as fully transparent. - * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. - */ png_bytep trans; /* transparent values for paletted image */ png_color_16 trans_values; /* transparent color for non-palette image */ #endif #if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - /* The bKGD chunk gives the suggested image background color if the - * display program does not have its own background color and the image - * is needs to composited onto a background before display. The colors - * in "background" are normally in the same color space/depth as the - * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. - */ png_color_16 background; #endif #if defined(PNG_oFFs_SUPPORTED) - /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards - * and downwards from the top-left corner of the display, page, or other - * application-specific co-ordinate space. See the PNG_OFFSET_ defines - * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. - */ png_int_32 x_offset; /* x offset on page */ png_int_32 y_offset; /* y offset on page */ png_byte offset_unit_type; /* offset units type */ #endif #if defined(PNG_pHYs_SUPPORTED) - /* The pHYs chunk gives the physical pixel density of the image for - * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ - * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. - */ png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ png_uint_32 y_pixels_per_unit; /* vertical pixel density */ png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ #endif #if defined(PNG_hIST_SUPPORTED) - /* The hIST chunk contains the relative frequency or importance of the - * various palette entries, so that a viewer can intelligently select a - * reduced-color palette, if required. Data is an array of "num_palette" - * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) - * is non-zero. - */ png_uint_16p hist; #endif #ifdef PNG_cHRM_SUPPORTED - /* The cHRM chunk describes the CIE color characteristics of the monitor - * on which the PNG was created. This data allows the viewer to do gamut - * mapping of the input image to ensure that the viewer sees the same - * colors in the image as the creator. Values are in the range - * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. - */ #ifdef PNG_FLOATING_POINT_SUPPORTED float x_white; float y_white; @@ -210946,75 +190881,50 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) #endif #if defined(PNG_pCAL_SUPPORTED) - /* The pCAL chunk describes a transformation between the stored pixel - * values and original physical data values used to create the image. - * The integer range [0, 2^bit_depth - 1] maps to the floating-point - * range given by [pcal_X0, pcal_X1], and are further transformed by a - * (possibly non-linear) transformation function given by "pcal_type" - * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ - * defines below, and the PNG-Group's PNG extensions document for a - * complete description of the transformations and how they should be - * implemented, and for a description of the ASCII parameter strings. - * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. - */ png_charp pcal_purpose; /* pCAL chunk description string */ - png_int_32 pcal_X0; /* minimum value */ - png_int_32 pcal_X1; /* maximum value */ - png_charp pcal_units; /* Latin-1 string giving physical units */ + png_int_32 pcal_X0; /* minimum value */ + png_int_32 pcal_X1; /* maximum value */ + png_charp pcal_units; /* Latin-1 string giving physical units */ png_charpp pcal_params; /* ASCII strings containing parameter values */ - png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ png_byte pcal_nparams; /* number of parameters given in pcal_params */ #endif -/* New members added in libpng-1.0.6 */ #ifdef PNG_FREE_ME_SUPPORTED - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ #endif #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - /* storage for unknown chunks that the library doesn't recognize. */ png_unknown_chunkp unknown_chunks; png_size_t unknown_chunks_num; #endif #if defined(PNG_iCCP_SUPPORTED) - /* iCCP chunk data. */ - png_charp iccp_name; /* profile name */ + png_charp iccp_name; /* profile name */ png_charp iccp_profile; /* International Color Consortium profile data */ - /* Note to maintainer: should be png_bytep */ png_uint_32 iccp_proflen; /* ICC profile data length */ png_byte iccp_compression; /* Always zero */ #endif #if defined(PNG_sPLT_SUPPORTED) - /* data on sPLT chunks (there may be more than one). */ png_sPLT_tp splt_palettes; png_uint_32 splt_palettes_num; #endif #if defined(PNG_sCAL_SUPPORTED) - /* The sCAL chunk describes the actual physical dimensions of the - * subject matter of the graphic. The chunk contains a unit specification - * a byte value, and two ASCII strings representing floating-point - * values. The values are width and height corresponsing to one pixel - * in the image. This external representation is converted to double - * here. Data values are valid if (valid & PNG_INFO_sCAL) is non-zero. - */ - png_byte scal_unit; /* unit of physical scale */ + png_byte scal_unit; /* unit of physical scale */ #ifdef PNG_FLOATING_POINT_SUPPORTED - double scal_pixel_width; /* width of one pixel */ + double scal_pixel_width; /* width of one pixel */ double scal_pixel_height; /* height of one pixel */ #endif #ifdef PNG_FIXED_POINT_SUPPORTED - png_charp scal_s_width; /* string containing height */ - png_charp scal_s_height; /* string containing width */ + png_charp scal_s_width; /* string containing height */ + png_charp scal_s_height; /* string containing width */ #endif #endif #if defined(PNG_INFO_IMAGE_SUPPORTED) - /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */ - /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ - png_bytepp row_pointers; /* the image bits */ + png_bytepp row_pointers; /* the image bits */ #endif #if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED) @@ -211037,86 +190947,65 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) typedef png_info FAR * png_infop; typedef png_info FAR * FAR * png_infopp; -/* Maximum positive integer used in PNG is (2^31)-1 */ #define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) #define PNG_UINT_32_MAX ((png_uint_32)(-1)) #define PNG_SIZE_MAX ((png_size_t)(-1)) #if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* PNG_MAX_UINT is deprecated; use PNG_UINT_31_MAX instead. */ #define PNG_MAX_UINT PNG_UINT_31_MAX #endif -/* These describe the color_type field in png_info. */ -/* color type masks */ -#define PNG_COLOR_MASK_PALETTE 1 -#define PNG_COLOR_MASK_COLOR 2 -#define PNG_COLOR_MASK_ALPHA 4 +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 -/* color types. Note that not all combinations are legal */ #define PNG_COLOR_TYPE_GRAY 0 #define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) -#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) #define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) #define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) -/* aliases */ #define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA #define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA -/* This is for compression type. PNG 1.0-1.2 only define the single type. */ #define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ #define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE -/* This is for filter type. PNG 1.0-1.2 only define the single type. */ -#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ #define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ #define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE -/* These are for the interlacing type. These values should NOT be changed. */ -#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ -#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ -#define PNG_INTERLACE_LAST 2 /* Not a valid value */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ -/* These are for the oFFs chunk. These values should NOT be changed. */ -#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ -#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ -#define PNG_OFFSET_LAST 2 /* Not a valid value */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ -/* These are for the pCAL chunk. These values should NOT be changed. */ -#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ -#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ -#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ #define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ -#define PNG_EQUATION_LAST 4 /* Not a valid value */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ -/* These are for the sCAL chunk. These values should NOT be changed. */ -#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ -#define PNG_SCALE_METER 1 /* meters per pixel */ -#define PNG_SCALE_RADIAN 2 /* radians per pixel */ -#define PNG_SCALE_LAST 3 /* Not a valid value */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ -/* These are for the pHYs chunk. These values should NOT be changed. */ -#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ -#define PNG_RESOLUTION_METER 1 /* pixels/meter */ -#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ -/* These are for the sRGB chunk. These values should NOT be changed. */ #define PNG_sRGB_INTENT_PERCEPTUAL 0 #define PNG_sRGB_INTENT_RELATIVE 1 #define PNG_sRGB_INTENT_SATURATION 2 #define PNG_sRGB_INTENT_ABSOLUTE 3 -#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ -/* This is for text chunks */ -#define PNG_KEYWORD_MAX_LENGTH 79 +#define PNG_KEYWORD_MAX_LENGTH 79 -/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ -#define PNG_MAX_PALETTE_LENGTH 256 +#define PNG_MAX_PALETTE_LENGTH 256 -/* These determine if an ancillary chunk's data has been successfully read - * from the PNG header, or if the application has filled in the corresponding - * data in the info_struct to be written into the output file. The values - * of the PNG_INFO_ defines should NOT be changed. - */ #define PNG_INFO_gAMA 0x0001 #define PNG_INFO_sBIT 0x0002 #define PNG_INFO_cHRM 0x0004 @@ -211134,10 +191023,6 @@ typedef png_info FAR * FAR * png_infopp; #define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ #define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ -/* This is used for the transformation routines, as some of them - * change these values for the row. It also should enable using - * the routines for other purposes. - */ typedef struct png_row_info_struct { png_uint_32 width; /* width of row */ @@ -211151,12 +191036,6 @@ typedef struct png_row_info_struct typedef png_row_info FAR * png_row_infop; typedef png_row_info FAR * FAR * png_row_infopp; -/* These are the function types for the I/O functions and for the functions - * that allow the user to override the default I/O functions with his or her - * own. The png_error_ptr type should match that of user-supplied warning - * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. - */ typedef struct png_struct_def png_struct; typedef png_struct FAR * png_structp; @@ -211176,10 +191055,10 @@ typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, - png_row_infop, png_bytep)); + png_row_infop, png_bytep)); #endif #if defined(PNG_USER_CHUNKS_SUPPORTED) @@ -211189,47 +191068,38 @@ typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); #endif -/* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only */ -/* Flags for MNG supported features */ -#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 -#define PNG_FLAG_MNG_FILTER_64 0x04 -#define PNG_ALL_MNG_FEATURES 0x05 +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); -/* The structure that holds the information to read and write PNG files. - * The only people who need to care about what is inside of this are the - * people who will be modifying the library for their own special needs. - * It should NOT be accessed directly by an application, except to store - * the jmp_buf. - */ - struct png_struct_def { #ifdef PNG_SETJMP_SUPPORTED - jmp_buf jmpbuf; /* used in png_error */ + jmp_buf jmpbuf; /* used in png_error */ #endif - png_error_ptr error_fn; /* function for printing errors and aborting */ + png_error_ptr error_fn; /* function for printing errors and aborting */ png_error_ptr warning_fn; /* function for printing warnings */ - png_voidp error_ptr; /* user supplied struct for error functions */ + png_voidp error_ptr; /* user supplied struct for error functions */ png_rw_ptr write_data_fn; /* function for writing output data */ png_rw_ptr read_data_fn; /* function for reading input data */ - png_voidp io_ptr; /* ptr to application struct for I/O functions */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) png_user_transform_ptr read_user_transform_fn; /* user read transform */ @@ -211239,69 +191109,68 @@ struct png_struct_def png_user_transform_ptr write_user_transform_fn; /* user write transform */ #endif -/* These were added in libpng-1.0.2 */ #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) png_voidp user_transform_ptr; /* user supplied struct for user transform */ - png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ png_byte user_transform_channels; /* channels in user transformed pixels */ #endif #endif - png_uint_32 mode; /* tells us where we are in the PNG file */ - png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ png_uint_32 transformations; /* which transformations to perform */ - z_stream zstream; /* pointer to decompression structure (below) */ - png_bytep zbuf; /* buffer for zlib */ - png_size_t zbuf_size; /* size of zbuf */ - int zlib_level; /* holds zlib compression level */ - int zlib_method; /* holds zlib compression method */ - int zlib_window_bits; /* holds zlib compression window bits */ - int zlib_mem_level; /* holds zlib compression memory level */ - int zlib_strategy; /* holds zlib compression strategy */ + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + png_size_t zbuf_size; /* size of zbuf */ + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ - png_uint_32 width; /* width of image in pixels */ - png_uint_32 height; /* height of image in pixels */ - png_uint_32 num_rows; /* number of rows in current pass */ - png_uint_32 usr_width; /* width of row at start of write */ - png_uint_32 rowbytes; /* size of row in bytes */ - png_uint_32 irowbytes; /* size of current interlaced row in bytes */ - png_uint_32 iwidth; /* width of current interlaced row in pixels */ - png_uint_32 row_number; /* current row in interlace pass */ - png_bytep prev_row; /* buffer to save previous (unfiltered) row */ - png_bytep row_buf; /* buffer to save current (unfiltered) row */ + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_uint_32 rowbytes; /* size of row in bytes */ + png_uint_32 irowbytes; /* size of current interlaced row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ png_bytep sub_row; /* buffer to save "sub" row when filtering */ png_bytep up_row; /* buffer to save "up" row when filtering */ png_bytep avg_row; /* buffer to save "avg" row when filtering */ png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ - png_row_info row_info; /* used for transformation routines */ + png_row_info row_info; /* used for transformation routines */ - png_uint_32 idat_size; /* current IDAT size for read */ - png_uint_32 crc; /* current chunk CRC value */ - png_colorp palette; /* palette from the input file */ + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ png_uint_16 num_palette; /* number of color entries in palette */ - png_uint_16 num_trans; /* number of transparency values */ - png_byte chunk_name[5]; /* null-terminated name of current chunk */ - png_byte compression; /* file compression type (always 0) */ - png_byte filter; /* file filter type (always 0) */ - png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - png_byte pass; /* current interlace pass (0 - 6) */ - png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ - png_byte color_type; /* color type of file */ - png_byte bit_depth; /* bit depth of file */ - png_byte usr_bit_depth; /* bit depth of users row */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte channels; /* number of channels in file */ - png_byte usr_channels; /* channels at start of write */ - png_byte sig_bytes; /* magic bytes read/written from start of file */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) #ifdef PNG_LEGACY_SUPPORTED - png_byte filler; /* filler byte for pixel expansion */ + png_byte filler; /* filler byte for pixel expansion */ #else - png_uint_16 filler; /* filler bytes for pixel expansion */ + png_uint_16 filler; /* filler bytes for pixel expansion */ #endif #endif @@ -211318,38 +191187,38 @@ struct png_struct_def #if defined(PNG_WRITE_FLUSH_SUPPORTED) png_flush_ptr output_flush_fn;/* Function for flushing output */ - png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ - png_uint_32 flush_rows; /* number of rows written since last flush */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ #endif #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ #ifdef PNG_FLOATING_POINT_SUPPORTED - float gamma; /* file gamma value */ + float gamma; /* file gamma value */ float screen_gamma; /* screen gamma value (display_exponent) */ #endif #endif #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep gamma_table; /* gamma table for 8-bit depth files */ - png_bytep gamma_from_1; /* converts from 1.0 to screen */ - png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ #endif #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit; /* significant bits in each available channel */ + png_color_8 sig_bit; /* significant bits in each available channel */ #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ + png_color_8 shift; /* shift for significant bit tranformation */ #endif #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans; /* transparency values for paletted files */ + png_bytep trans; /* transparency values for paletted files */ png_color_16 trans_values; /* transparency values for non-paletted files */ #endif @@ -211359,29 +191228,28 @@ struct png_struct_def png_progressive_info_ptr info_fn; /* called after header data fully read */ png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ png_progressive_end_ptr end_fn; /* called after image is complete */ - png_bytep save_buffer_ptr; /* current location in save_buffer */ - png_bytep save_buffer; /* buffer for previously read data */ - png_bytep current_buffer_ptr; /* current location in current_buffer */ - png_bytep current_buffer; /* buffer for recently used data */ - png_uint_32 push_length; /* size of current input chunk */ - png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ png_size_t current_buffer_size; /* amount of data now in current_buffer */ - int process_mode; /* what push library is currently doing */ - int cur_palette; /* current push library palette index */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ # if defined(PNG_TEXT_SUPPORTED) - png_size_t current_text_size; /* current size of text input data */ - png_size_t current_text_left; /* how much text left to read in input */ - png_charp current_text; /* current text chunk buffer */ - png_charp current_text_ptr; /* current location in current_text */ + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ # endif /* PNG_TEXT_SUPPORTED */ #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* for the Borland special 64K segment handler */ png_bytepp offset_table_ptr; png_bytep offset_table; png_uint_16 offset_table_number; @@ -211390,32 +191258,30 @@ struct png_struct_def #endif #if defined(PNG_READ_DITHER_SUPPORTED) - png_bytep palette_lookup; /* lookup table for dithering */ - png_bytep dither_index; /* index translation for palette files */ + png_bytep palette_lookup; /* lookup table for dithering */ + png_bytep dither_index; /* index translation for palette files */ #endif #if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) - png_uint_16p hist; /* histogram */ + png_uint_16p hist; /* histogram */ #endif #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_byte heuristic_method; /* heuristic for row filter selection */ - png_byte num_prev_filters; /* number of weights for previous rows */ - png_bytep prev_filters; /* filter type(s) of previous row(s) */ - png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ - png_uint_16p filter_costs; /* relative filter calculation cost */ - png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ #endif #if defined(PNG_TIME_RFC1123_SUPPORTED) - png_charp time_buffer; /* String to hold RFC 1123 time text */ + png_charp time_buffer; /* String to hold RFC 1123 time text */ #endif -/* New members added in libpng-1.0.6 */ - #ifdef PNG_FREE_ME_SUPPORTED - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ #endif #if defined(PNG_USER_CHUNKS_SUPPORTED) @@ -211428,20 +191294,16 @@ struct png_struct_def png_bytep chunk_list; #endif -/* New members added in libpng-1.0.3 */ #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) png_byte rgb_to_gray_status; - /* These were changed from png_byte in libpng-1.0.6 */ png_uint_16 rgb_to_gray_red_coeff; png_uint_16 rgb_to_gray_green_coeff; png_uint_16 rgb_to_gray_blue_coeff; #endif -/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ #if defined(PNG_MNG_FEATURES_SUPPORTED) || \ - defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* changed from png_byte to png_uint_32 at version 1.2.0 */ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) #ifdef PNG_1_0_X png_byte mng_features_permitted; #else @@ -211449,52 +191311,42 @@ struct png_struct_def #endif /* PNG_1_0_X */ #endif -/* New member added in libpng-1.0.7 */ #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) png_fixed_point int_gamma; #endif -/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ #if defined(PNG_MNG_FEATURES_SUPPORTED) png_byte filter_type; #endif #if defined(PNG_1_0_X) -/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ png_uint_32 row_buf_size; #endif -/* New members added in libpng-1.2.0 */ #if defined(PNG_ASSEMBLER_CODE_SUPPORTED) # if !defined(PNG_1_0_X) -# if defined(PNG_MMX_CODE_SUPPORTED) - png_byte mmx_bitdepth_threshold; +# if defined(PNG_MMX_CODE_SUPPORTED) + png_byte mmx_bitdepth_threshold; png_uint_32 mmx_rowbytes_threshold; -# endif +# endif png_uint_32 asm_flags; # endif #endif -/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ #ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr; /* user supplied struct for mem functions */ - png_malloc_ptr malloc_fn; /* function for allocating memory */ - png_free_ptr free_fn; /* function for freeing memory */ + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ #endif -/* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ #if defined(PNG_READ_DITHER_SUPPORTED) -/* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep dither_sort; /* working sort array */ - png_bytep index_to_palette; /* where the original index currently is */ - /* in the palette */ - png_bytep palette_to_index; /* which original index points to this */ - /* palette color */ + png_bytep dither_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is */ + png_bytep palette_to_index; /* which original index points to this */ #endif -/* New members added in libpng-1.0.16 and 1.2.6 */ png_byte compression_type; #ifdef PNG_SET_USER_LIMITS_SUPPORTED @@ -211502,54 +191354,29 @@ struct png_struct_def png_uint_32 user_height_max; #endif -/* New member added in libpng-1.0.25 and 1.2.17 */ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - /* storage for unknown chunk that the library doesn't recognize. */ png_unknown_chunk unknown_chunk; #endif }; -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ typedef png_structp version_1_2_21; typedef png_struct FAR * FAR * png_structpp; -/* Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng.txt for the - * full explanation, see example.c for the summary. This just provides - * a simple one line description of the use of each function. - */ - -/* Returns the version number of the library */ extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, int num_bytes)); -/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a - * PNG file. Returns zero if the supplied bytes match the 8-byte PNG - * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). - */ extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, png_size_t num_to_check)); -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)); -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ extern PNG_EXPORT(png_structp,png_create_read_struct) PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn)); -/* Allocate and initialize png_ptr struct for writing, and any other memory */ extern PNG_EXPORT(png_structp,png_create_write_struct) PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn)); @@ -211564,10 +191391,8 @@ extern PNG_EXPORT(void,png_set_compression_buffer_size) PNGARG((png_structp png_ptr, png_uint_32 size)); #endif -/* Reset the compression stream */ extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ #ifdef PNG_USER_MEM_SUPPORTED extern PNG_EXPORT(png_structp,png_create_read_struct_2) PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, @@ -211579,44 +191404,36 @@ extern PNG_EXPORT(png_structp,png_create_write_struct_2) png_malloc_ptr malloc_fn, png_free_ptr free_fn)); #endif -/* Write a PNG chunk - size, type, (optional) data, CRC. */ extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, png_bytep chunk_name, png_bytep data, png_size_t length)); -/* Write the start of a PNG chunk - length and chunk name. */ extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, png_bytep chunk_name, png_uint_32 length)); -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, png_bytep data, png_size_t length)); -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); -/* Allocate and initialize the info structure */ extern PNG_EXPORT(png_infop,png_create_info_struct) PNGARG((png_structp png_ptr)); #if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Initialize the info structure (old interface - DEPRECATED) */ extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr)); #undef png_info_init #define png_info_init(info_ptr) png_info_init_3(&info_ptr,\ - png_sizeof(png_info)); + png_sizeof(png_info)); #endif extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, - png_size_t png_info_struct_size)); + png_size_t png_info_struct_size)); -/* Writes all the PNG information before the image. */ extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, png_infop info_ptr)); extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, png_infop info_ptr)); #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the information before the actual image data. */ extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, png_infop info_ptr)); #endif @@ -211627,20 +191444,16 @@ extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) #endif #if !defined(_WIN32_WCE) -/* "time.h" functions are not supported on WindowsCE */ #if defined(PNG_WRITE_tIME_SUPPORTED) -/* convert from a struct tm to png_time */ extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, struct tm FAR * ttime)); -/* convert from time_t to png_time. Uses gmtime() */ extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, time_t ttime)); #endif /* PNG_WRITE_tIME_SUPPORTED */ #endif /* _WIN32_WCE */ #if defined(PNG_READ_EXPAND_SUPPORTED) -/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); #if !defined(PNG_1_0_X) extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp @@ -211649,23 +191462,19 @@ extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); #if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Deprecated */ extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); #endif #endif #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -/* Expand the grayscale to 24-bit RGB if necessary. */ extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -/* Reduce RGB to grayscale. */ #ifdef PNG_FLOATING_POINT_SUPPORTED extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, int error_action, double red, double green )); @@ -211684,23 +191493,20 @@ extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, png_uint_32 filler, int flags)); -/* The values of the PNG_FILLER_ defines should NOT be changed */ #define PNG_FILLER_BEFORE 0 #define PNG_FILLER_AFTER 1 -/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ #if !defined(PNG_1_0_X) extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, png_uint_32 filler, int flags)); @@ -211708,39 +191514,32 @@ extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, #endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swap bytes in 16-bit depth files. */ extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, png_color_8p true_bits)); #endif #if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. */ + defined(PNG_WRITE_INTERLACING_SUPPORTED) extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_BACKGROUND_SUPPORTED) -/* Handle alpha and tRNS by replacing with a background color. */ #ifdef PNG_FLOATING_POINT_SUPPORTED extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, png_color_16p background_color, int background_gamma_code, @@ -211748,24 +191547,21 @@ extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, #endif #define PNG_BACKGROUND_GAMMA_UNKNOWN 0 #define PNG_BACKGROUND_GAMMA_SCREEN 1 -#define PNG_BACKGROUND_GAMMA_FILE 2 +#define PNG_BACKGROUND_GAMMA_FILE 2 #define PNG_BACKGROUND_GAMMA_UNIQUE 3 #endif #if defined(PNG_READ_16_TO_8_SUPPORTED) -/* strip the second byte of information from a 16-bit depth file. */ extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_DITHER_SUPPORTED) -/* Turn on dithering, and reduce the palette to the number of colors available. */ extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, png_colorp palette, int num_palette, int maximum_colors, png_uint_16p histogram, int full_dither)); #endif #if defined(PNG_READ_GAMMA_SUPPORTED) -/* Handle gamma correction. Screen_gamma=(display_exponent) */ #ifdef PNG_FLOATING_POINT_SUPPORTED extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, double screen_gamma, double default_file_gamma)); @@ -211774,175 +191570,99 @@ extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, #if defined(PNG_1_0_X) || defined (PNG_1_2_X) #if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ -/* Deprecated and will be removed. Use png_permit_mng_features() instead. */ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, int empty_plte_permitted)); #endif #endif #if defined(PNG_WRITE_FLUSH_SUPPORTED) -/* Set how many lines between output flushes - 0 for no flushing */ extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); #endif -/* optional update palette with requested transformations */ extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); -/* optional call to update the users info structure */ extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, png_infop info_ptr)); #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read one or more rows of image data. */ extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); #endif #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read a row of data. */ extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, png_bytep row, png_bytep display_row)); #endif #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the whole image into memory at once. */ extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, png_bytepp image)); #endif -/* write a row of image data */ extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, png_bytep row)); -/* write a few rows of image data */ extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, png_bytepp row, png_uint_32 num_rows)); -/* write the image data */ extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, png_bytepp image)); -/* writes the end of the PNG file. */ extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, png_infop info_ptr)); #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the end of the PNG file. */ extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, png_infop info_ptr)); #endif -/* free any memory associated with the png_info_struct */ extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, png_infopp info_ptr_ptr)); -/* free any memory associated with the png_struct and the png_info_structs */ extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); -/* free all memory used by the read (old method - NOT DLL EXPORTED) */ extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)); -/* free any memory associated with the png_struct and the png_info_structs */ extern PNG_EXPORT(void,png_destroy_write_struct) PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); -/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ extern void png_write_destroy PNGARG((png_structp png_ptr)); -/* set the libpng method of handling chunk CRC errors */ extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, int crit_action, int ancil_action)); -/* Values for png_set_crc_action() to say how to handle CRC errors in - * ancillary and critical chunks, and whether to use the data contained - * therein. Note that it is impossible to "discard" data in a critical - * chunk. For versions prior to 0.90, the action was always error/quit, - * whereas in version 0.90 and later, the action for CRC errors in ancillary - * chunks is warn/discard. These values should NOT be changed. - * - * value action:critical action:ancillary - */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ -/* These functions give the user control over the scan-line filtering in - * libpng and the compression methods used by zlib. These functions are - * mainly useful for testing, as the defaults should work with most users. - * Those users who are tight on memory or want faster performance at the - * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. - */ - -/* set the filtering method(s) used by libpng. Currently, the only valid - * value for "method" is 0. - */ extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, int filters)); -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 #define PNG_FILTER_PAETH 0x80 #define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) + PNG_FILTER_AVG | PNG_FILTER_PAETH) -/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. - */ #define PNG_FILTER_VALUE_NONE 0 #define PNG_FILTER_VALUE_SUB 1 -#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_UP 2 #define PNG_FILTER_VALUE_AVG 3 #define PNG_FILTER_VALUE_PAETH 4 #define PNG_FILTER_VALUE_LAST 5 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ -/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ - * defines, either the default (minimum-sum-of-absolute-differences), or - * the experimental method (weighted-minimum-sum-of-absolute-differences). - * - * Weights are factors >= 1.0, indicating how important it is to keep the - * filter type consistent between rows. Larger numbers mean the current - * filter is that many times as likely to be the same as the "num_weights" - * previous filters. This is cumulative for each previous row with a weight. - * There needs to be "num_weights" values in "filter_weights", or it can be - * NULL if the weights aren't being specified. Weights have no influence on - * the selection of the first row filter. Well chosen weights can (in theory) - * improve the compression for a given image. - * - * Costs are factors >= 1.0 indicating the relative decoding costs of a - * filter type. Higher costs indicate more decoding expense, and are - * therefore less likely to be selected over a filter with lower computational - * costs. There needs to be a value in "filter_costs" for each valid filter - * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't - * setting the costs. Costs try to improve the speed of decompression without - * unduly increasing the compressed image size. - * - * A negative weight or cost indicates the default value is to be used, and - * values in the range [0.0, 1.0) indicate the value is to remain unchanged. - * The default values for both weights and costs are currently 1.0, but may - * change if good general weighting/cost heuristics can be found. If both - * the weights and costs are set to 1.0, this degenerates the WEIGHTED method - * to the UNWEIGHTED method, but with added encoding time/computation. - */ #ifdef PNG_FLOATING_POINT_SUPPORTED extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, int heuristic_method, int num_weights, png_doublep filter_weights, @@ -211950,21 +191670,11 @@ extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, #endif #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ -/* Heuristic used for row filter selection. These defines should NOT be - * changed. - */ #define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ #define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ #define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ -/* Set the library compression level. Currently, valid values range from - * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 - * (0 - no compression, 9 - "maximal" compression). Note that tests have - * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, - * these values may not correspond directly to the zlib compression levels. - */ extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, int level)); @@ -211980,47 +191690,21 @@ extern PNG_EXPORT(void,png_set_compression_window_bits) extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, int method)); -/* These next functions are called for input/output, memory, and error - * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, - * and call standard C I/O routines such as fread(), fwrite(), and - * fprintf(). These functions can be made to use other I/O routines - * at run time for those applications that need to handle I/O in a - * different manner by calling png_set_???_fn(). See libpng.txt for - * more information. - */ - #if !defined(PNG_NO_STDIO) -/* Initialize the input/output for the PNG file to the default functions. */ extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); #endif -/* Replace the (error and abort), and warning functions with user - * supplied functions. If no messages are to be printed you must still - * write and use replacement functions. The replacement error_fn should - * still do a longjmp to the last setjmp location if you are using this - * method of error handling. If error_fn or warning_fn is NULL, the - * default function will be used. - */ - extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); -/* Return the user pointer associated with the error functions */ extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); -/* Replace the default data output functions with a user supplied one(s). - * If buffered output is not used, then output_flush_fn can be set to NULL. - * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time - * output_flush_fn will be ignored (and thus can be NULL). - */ extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); -/* Replace the default data input function with a user supplied one. */ extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, png_voidp io_ptr, png_rw_ptr read_data_fn)); -/* Return the user pointer associated with the I/O functions */ extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, @@ -212030,32 +191714,29 @@ extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, png_write_status_ptr write_row_fn)); #ifdef PNG_USER_MEM_SUPPORTED -/* Replace the default memory allocation functions with user supplied one(s). */ extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -/* Return the user pointer associated with the memory functions */ extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) + defined(PNG_LEGACY_SUPPORTED) extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp png_ptr, png_user_transform_ptr read_user_transform_fn)); #endif #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) + defined(PNG_LEGACY_SUPPORTED) extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp png_ptr, png_user_transform_ptr write_user_transform_fn)); #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp png_ptr, png_voidp user_transform_ptr, int user_transform_depth, int user_transform_channels)); -/* Return the user pointer associated with the user transform functions */ extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) PNGARG((png_structp png_ptr)); #endif @@ -212068,25 +191749,17 @@ extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp #endif #ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* Sets the function callbacks for the push reader, and a pointer to a - * user-defined structure available to the callback functions. - */ extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, png_voidp progressive_ptr, png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); -/* returns the user pointer associated with the push read functions */ extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) PNGARG((png_structp png_ptr)); -/* function to be called when data becomes available */ extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); -/* function that combines rows. Not very much different than the - * png_combine_row() call. Is this even used????? - */ extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, png_bytep old_row, png_bytep new_row)); #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ @@ -212097,37 +191770,28 @@ extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, #if defined(PNG_1_0_X) # define png_malloc_warn png_malloc #else -/* Added at libpng version 1.2.4 */ extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, png_uint_32 size)); #endif -/* frees a pointer allocated by png_malloc() */ extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); #if defined(PNG_1_0_X) -/* Function to allocate memory for zlib. */ extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items, uInt size)); -/* Function to free memory for zlib */ extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); #endif -/* Free data that was allocated internally */ extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num)); #ifdef PNG_FREE_ME_SUPPORTED -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application */ extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask)); #endif -/* assignments for png_data_freer */ #define PNG_DESTROY_WILL_FREE_DATA 1 #define PNG_SET_WILL_FREE_DATA 1 #define PNG_USER_WILL_FREE_DATA 2 -/* Flags for png_ptr->free_me and info_ptr->free_me */ #define PNG_FREE_HIST 0x0008 #define PNG_FREE_ICCP 0x0010 #define PNG_FREE_SPLT 0x0020 @@ -212161,95 +191825,63 @@ extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, #endif /* USE_FAR_KEYWORD */ #ifndef PNG_NO_ERROR_TEXT -/* Fatal error in PNG image of libpng - can't continue */ extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, png_const_charp error_message)); -/* The same, but the chunk name is prepended to the error string. */ extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, png_const_charp error_message)); #else -/* Fatal error in PNG image of libpng - can't continue */ extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)); #endif #ifndef PNG_NO_WARNINGS -/* Non-fatal error in libpng. Can continue, but may have a problem. */ extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, png_const_charp warning_message)); #ifdef PNG_READ_SUPPORTED -/* Non-fatal error in libpng, chunk name is prepended to message. */ extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, png_const_charp warning_message)); #endif /* PNG_READ_SUPPORTED */ #endif /* PNG_NO_WARNINGS */ -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ calls are used to read values from the - * png_info_struct, either storing the parameters in the passed variables, or - * setting pointers into the png_info_struct where the data is stored. The - * png_get_ functions return a non-zero value if the data was available - * in info_ptr, or return zero and do not change any of the parameters if the - * data was not available. - * - * These functions should be used instead of directly accessing png_info - * to avoid problems with future changes in the size and internal layout of - * png_info_struct. - */ -/* Returns "flag" if chunk data is valid in info_ptr. */ extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 flag)); -/* Returns number of bytes needed to hold a transformed row. */ extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, png_infop info_ptr)); #if defined(PNG_INFO_IMAGE_SUPPORTED) -/* Returns row_pointers, which is an array of pointers to scanlines that was -returned from png_read_png(). */ extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, png_infop info_ptr)); -/* Set row_pointers, which is an array of pointers to scanlines for use -by png_write_png(). */ extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)); #endif -/* Returns number of color channels in image. */ extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, png_infop info_ptr)); #ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp png_ptr, png_infop info_ptr)); -/* Returns image height in pixels. */ extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp png_ptr, png_infop info_ptr)); -/* Returns image bit_depth. */ extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp png_ptr, png_infop info_ptr)); -/* Returns image color_type. */ extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp png_ptr, png_infop info_ptr)); -/* Returns image filter_type. */ extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp png_ptr, png_infop info_ptr)); -/* Returns image interlace_type. */ extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp png_ptr, png_infop info_ptr)); -/* Returns image compression_type. */ extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp png_ptr, png_infop info_ptr)); -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp png_ptr, png_infop info_ptr)); extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp @@ -212257,13 +191889,11 @@ png_ptr, png_infop info_ptr)); extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp png_ptr, png_infop info_ptr)); -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ #ifdef PNG_FLOATING_POINT_SUPPORTED extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp png_ptr, png_infop info_ptr)); #endif -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp png_ptr, png_infop info_ptr)); extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp @@ -212275,7 +191905,6 @@ png_ptr, png_infop info_ptr)); #endif /* PNG_EASY_ACCESS_SUPPORTED */ -/* Returns pointer to signature string read from PNG header */ extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, png_infop info_ptr)); @@ -212424,14 +192053,12 @@ extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, png_infop info_ptr, png_charpp name, int *compression_type, png_charpp profile, png_uint_32 *proflen)); - /* Note to maintainer: profile should be png_bytepp */ #endif #if defined(PNG_iCCP_SUPPORTED) extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, png_infop info_ptr, png_charp name, int compression_type, png_charp profile, png_uint_32 proflen)); - /* Note to maintainer: profile should be png_bytep */ #endif #if defined(PNG_sPLT_SUPPORTED) @@ -212445,19 +192072,10 @@ extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, #endif #if defined(PNG_TEXT_SUPPORTED) -/* png_get_text also returns the number of text chunks in *num_text */ extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, int *num_text)); #endif -/* - * Note while png_set_text() will accept a structure whose text, - * language, and translated keywords are NULL pointers, the structure - * returned by png_get_text will always contain regular - * zero-terminated C strings. They might be empty strings but - * they will never be NULL pointers. - */ - #if defined(PNG_TEXT_SUPPORTED) extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, int num_text)); @@ -212513,15 +192131,6 @@ extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, #endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -/* provide a list of chunks and how they are to be handled, if the built-in - handling or default unknown chunk handling is not desired. Any chunks not - listed will be handled in the default manner. The IHDR and IEND chunks - must not be listed. - keep = 0: follow default behaviour - = 1: do not keep - = 2: keep only if safe-to-copy - = 3: keep even if unsafe-to-copy -*/ extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp png_ptr, int keep, png_bytep chunk_list, int num_chunks)); extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, @@ -212536,29 +192145,20 @@ PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep chunk_name)); #endif -/* Png_free_data() will turn off the "valid" flag for anything it frees. - If you need to turn it off for a chunk that your application has freed, - you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, png_infop info_ptr, int mask)); #if defined(PNG_INFO_IMAGE_SUPPORTED) -/* The "params" pointer is currently not used and is for future expansion. */ extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); + png_infop info_ptr, + int transforms, + png_voidp params)); extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); + png_infop info_ptr, + int transforms, + png_voidp params)); #endif -/* Define PNG_DEBUG at compile time for debugging information. Higher - * numbers for PNG_DEBUG mean more debugging information. This has - * only been added since version 0.95 so it is not implemented throughout - * libpng yet, but more support will be added as needed. - */ #ifdef PNG_DEBUG #if (PNG_DEBUG > 0) #if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) @@ -212575,21 +192175,21 @@ extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, #if (PNG_DEBUG > 1) #define png_debug(l,m) \ { \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ } #define png_debug1(l,m,p1) \ { \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ } #define png_debug2(l,m,p1,p2) \ { \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ } #endif /* (PNG_DEBUG > 1) */ #endif /* _MSC_VER */ @@ -212615,68 +192215,59 @@ extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp png_ptr, png_uint_32 mng_features_permitted)); #endif -/* For use in png_set_keep_unknown, added to version 1.2.6 */ #define PNG_HANDLE_CHUNK_AS_DEFAULT 0 -#define PNG_HANDLE_CHUNK_NEVER 1 -#define PNG_HANDLE_CHUNK_IF_SAFE 2 -#define PNG_HANDLE_CHUNK_ALWAYS 3 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 -/* Added to version 1.2.0 */ #if defined(PNG_ASSEMBLER_CODE_SUPPORTED) #if defined(PNG_MMX_CODE_SUPPORTED) #define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ -#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ #define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04 -#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 +#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 #define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10 -#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 +#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 #define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40 #define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80 -#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ +#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ #define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ - | PNG_ASM_FLAG_MMX_READ_INTERLACE \ - | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ - | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ - | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ - | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ) + | PNG_ASM_FLAG_MMX_READ_INTERLACE \ + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ + | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ) #define PNG_MMX_WRITE_FLAGS ( 0 ) #define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \ - | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \ - | PNG_MMX_READ_FLAGS \ - | PNG_MMX_WRITE_FLAGS ) + | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \ + | PNG_MMX_READ_FLAGS \ + | PNG_MMX_WRITE_FLAGS ) #define PNG_SELECT_READ 1 #define PNG_SELECT_WRITE 2 #endif /* PNG_MMX_CODE_SUPPORTED */ #if !defined(PNG_1_0_X) -/* pngget.c */ extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask) PNGARG((int flag_select, int *compilerID)); -/* pngget.c */ extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask) PNGARG((int flag_select)); -/* pngget.c */ extern PNG_EXPORT(png_uint_32,png_get_asm_flags) PNGARG((png_structp png_ptr)); -/* pngget.c */ extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold) PNGARG((png_structp png_ptr)); -/* pngget.c */ extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold) PNGARG((png_structp png_ptr)); -/* pngset.c */ extern PNG_EXPORT(void,png_set_asm_flags) PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); -/* pngset.c */ extern PNG_EXPORT(void,png_set_mmx_thresholds) PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, png_uint_32 mmx_rowbytes_threshold)); @@ -212684,12 +192275,9 @@ extern PNG_EXPORT(void,png_set_mmx_thresholds) #endif /* PNG_1_0_X */ #if !defined(PNG_1_0_X) -/* png.c, pnggccrd.c, or pngvcrd.c */ extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); #endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. */ #ifdef PNG_ERROR_NUMBERS_SUPPORTED extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp png_ptr, png_uint_32 strip_mode)); @@ -212697,7 +192285,6 @@ extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp #endif /* PNG_1_0_X */ -/* Added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); @@ -212707,57 +192294,34 @@ extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp png_ptr)); #endif -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */ - #ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines we avoid an integer divide, which will be slower on - * most machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on a few RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 - \ + (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 - \ - (png_uint_16)(alpha)) + (png_uint_16)128); \ - (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } - -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(png_uint_32)(65535L - \ - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ - (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L - \ + (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } #else /* standard method using integer division */ -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - (png_uint_16)127) / 255) +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ - (png_uint_32)32767) / (png_uint_32)65535L) +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) #endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ -/* Inline macros to do direct reads of bytes from the input buffer. These - * require that you are using an architecture that uses PNG byte ordering - * (MSB first) and supports unaligned data storage. I think that PowerPC - * in big-endian mode and 680x0 are the only ones that will support this. - * The x86 line of processors definitely do not. The png_get_int_32() - * routine also assumes we are using two's complement format for negative - * values, which is almost certainly true. - */ #if defined(PNG_READ_BIG_ENDIAN_SUPPORTED) # define png_get_uint_32(buf) ( *((png_uint_32p) (buf))) # define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) @@ -212769,173 +192333,119 @@ extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); #endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ extern PNG_EXPORT(png_uint_32,png_get_uint_31) PNGARG((png_structp png_ptr, png_bytep buf)); -/* No png_get_int_16 -- may be added if there's a real need for it. */ -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). - */ extern PNG_EXPORT(void,png_save_uint_32) PNGARG((png_bytep buf, png_uint_32 i)); extern PNG_EXPORT(void,png_save_int_32) PNGARG((png_bytep buf, png_int_32 i)); -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ extern PNG_EXPORT(void,png_save_uint_16) PNGARG((png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ -/* ************************************************************************* */ - -/* These next functions are used internally in the code. They generally - * shouldn't be used unless you are writing code to add or replace some - * functionality in libpng. More information about most functions can - * be found in the files where the functions are located. - */ - -/* Various modes of operation, that are visible to applications because - * they are used for unknown chunk location. - */ -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 -#define PNG_HAVE_IDAT 0x04 -#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ -#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 #if defined(PNG_INTERNAL) -/* More modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. - */ -#define PNG_HAVE_gAMA 0x20 -#define PNG_HAVE_cHRM 0x40 -#define PNG_HAVE_sRGB 0x80 -#define PNG_HAVE_CHUNK_HEADER 0x100 -#define PNG_WROTE_tIME 0x200 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 #define PNG_WROTE_INFO_BEFORE_PLTE 0x400 -#define PNG_BACKGROUND_IS_GRAY 0x800 -#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ -/* flags for the transformations the PNG library does on the image data */ -#define PNG_BGR 0x0001 -#define PNG_INTERLACE 0x0002 -#define PNG_PACK 0x0004 -#define PNG_SHIFT 0x0008 -#define PNG_SWAP_BYTES 0x0010 -#define PNG_INVERT_MONO 0x0020 -#define PNG_DITHER 0x0040 -#define PNG_BACKGROUND 0x0080 +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_DITHER 0x0040 +#define PNG_BACKGROUND 0x0080 #define PNG_BACKGROUND_EXPAND 0x0100 - /* 0x0200 unused */ -#define PNG_16_TO_8 0x0400 -#define PNG_RGBA 0x0800 -#define PNG_EXPAND 0x1000 -#define PNG_GAMMA 0x2000 -#define PNG_GRAY_TO_RGB 0x4000 -#define PNG_FILLER 0x8000L -#define PNG_PACKSWAP 0x10000L -#define PNG_SWAP_ALPHA 0x20000L -#define PNG_STRIP_ALPHA 0x40000L -#define PNG_INVERT_ALPHA 0x80000L +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L #define PNG_USER_TRANSFORM 0x100000L #define PNG_RGB_TO_GRAY_ERR 0x200000L #define PNG_RGB_TO_GRAY_WARN 0x400000L -#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ - /* 0x800000L Unused */ -#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ -#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ -/* flags for png_create_struct */ #define PNG_STRUCT_PNG 0x0001 #define PNG_STRUCT_INFO 0x0002 -/* Scaling factor for filter heuristic weighting calculations */ #define PNG_WEIGHT_SHIFT 8 #define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) #define PNG_COST_SHIFT 3 #define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) -/* flags for the png_ptr->flags rather than declaring a byte for each one */ -#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 -#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 -#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 #define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 -#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 -#define PNG_FLAG_ZLIB_FINISHED 0x0020 -#define PNG_FLAG_ROW_INIT 0x0040 -#define PNG_FLAG_FILLER_AFTER 0x0080 -#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 -#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 -#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 -#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 -#define PNG_FLAG_FREE_PLTE 0x1000 -#define PNG_FLAG_FREE_TRNS 0x2000 -#define PNG_FLAG_FREE_HIST 0x4000 -#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L -#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L -#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L -#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L -#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L -#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L -#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ -#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ - /* 0x800000L unused */ - /* 0x1000000L unused */ - /* 0x2000000L unused */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 +#define PNG_FLAG_FREE_PLTE 0x1000 +#define PNG_FLAG_FREE_TRNS 0x2000 +#define PNG_FLAG_FREE_HIST 0x4000 +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L +#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ #define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ - PNG_FLAG_CRC_ANCILLARY_NOWARN) + PNG_FLAG_CRC_ANCILLARY_NOWARN) #define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ - PNG_FLAG_CRC_CRITICAL_IGNORE) + PNG_FLAG_CRC_CRITICAL_IGNORE) -#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ - PNG_FLAG_CRC_CRITICAL_MASK) - -/* save typing and make code easier to understand */ +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) #define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ abs((int)((c1).green) - (int)((c2).green)) + \ abs((int)((c1).blue) - (int)((c2).blue))) -/* Added to libpng-1.2.6 JB */ #define PNG_ROWBYTES(pixel_bits, width) \ - ((pixel_bits) >= 8 ? \ - ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \ - (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) ) + ((pixel_bits) >= 8 ? \ + ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \ + (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) ) -/* PNG_OUT_OF_RANGE returns true if value is outside the range - ideal-delta..ideal+delta. Each argument is evaluated twice. - "ideal" and "delta" should be constants, normally simple - integers, "value" a variable. Added to libpng-1.2.6 JB */ #define PNG_OUT_OF_RANGE(value, ideal, delta) \ - ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) -/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ #if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) -/* place to hold the signature string for a PNG file. */ #ifdef PNG_USE_GLOBAL_ARRAYS PNG_EXPORT_VAR (PNG_CONST png_byte FARDATA) png_sig[8]; #else #endif #endif /* PNG_NO_EXTERN */ -/* Constant strings for known chunk types. If you need to add a chunk, - * define the name here, and add an invocation of the macro in png.c and - * wherever it's needed. - */ #define PNG_IHDR png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} #define PNG_IDAT png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} #define PNG_IEND png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} @@ -212983,43 +192493,35 @@ PNG_EXPORT_VAR (png_byte FARDATA) png_zTXt[5]; #endif /* PNG_USE_GLOBAL_ARRAYS */ #if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Initialize png_ptr struct for reading, and allocate any other memory. - * (old interface - DEPRECATED - use png_create_read_struct instead). - */ extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr)); #undef png_read_init #define png_read_init(png_ptr) png_read_init_3(&png_ptr, \ - PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); + PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); #endif extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size)); + png_const_charp user_png_ver, png_size_t png_struct_size)); #if defined(PNG_1_0_X) || defined (PNG_1_2_X) extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t - png_info_size)); + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); #endif #if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Initialize png_ptr struct for writing, and allocate any other memory. - * (old interface - DEPRECATED - use png_create_write_struct instead). - */ extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr)); #undef png_write_init #define png_write_init(png_ptr) png_write_init_3(&png_ptr, \ - PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); + PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); #endif extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size)); + png_const_charp user_png_ver, png_size_t png_struct_size)); extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t - png_info_size)); + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); -/* Allocate memory for an internal libpng struct */ PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); -/* Free memory from internal libpng struct */ PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr @@ -213027,25 +192529,18 @@ PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, png_free_ptr free_fn, png_voidp mem_ptr)); -/* Free any memory that info_ptr points to and reset struct. */ PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, png_infop info_ptr)); #ifndef PNG_1_0_X -/* Function to allocate memory for zlib. */ PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); -/* Function to free memory for zlib */ PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); #ifdef PNG_SIZE_T -/* Function to convert a sizeof an item to png_sizeof item */ PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); #endif -/* Next four functions are used internally as callbacks. PNGAPI is required - * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ - PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, png_bytep data, png_size_t length)); @@ -213069,39 +192564,28 @@ PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, #endif #endif /* PNG_1_0_X */ -/* Reset the CRC variable */ PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); -/* Write the "data" buffer to whatever output you are using. */ PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, png_size_t length)); -/* Read data from whatever input you are using into the "data" buffer */ PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, png_size_t length)); -/* Read bytes into buf, and update png_ptr->crc */ PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, png_size_t length)); -/* Decompress data in a chunk that uses compression */ #if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ - defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr, int comp_type, png_charp chunkdata, png_size_t chunklength, png_size_t prefix_length, png_size_t *data_length)); #endif -/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); -/* Read the CRC from the file and compare it to the libpng calculated CRC */ PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); -/* Calculate the CRC over a section of data. Note that we are only - * passing a maximum of 64K on systems that have this as a memory limit, - * since this is the maximum buffer size we can specify. - */ PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, png_size_t length)); @@ -213109,14 +192593,8 @@ PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); #endif -/* simple function to write the signature */ PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); -/* write various chunks */ - -/* Write the IHDR chunk, and update the png_struct with the necessary - * information. - */ PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, int compression_method, int filter_method, @@ -213136,7 +192614,7 @@ PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); #endif #ifdef PNG_FIXED_POINT_SUPPORTED PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point - file_gamma)); + file_gamma)); #endif #endif @@ -213170,7 +192648,6 @@ PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, png_charp name, int compression_type, png_charp profile, int proflen)); - /* Note to maintainer: profile should be png_bytep */ #endif #if defined(PNG_WRITE_sPLT_SUPPORTED) @@ -213194,7 +192671,7 @@ PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, #endif #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ - defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, png_charp key, png_charpp new_key)); #endif @@ -213254,58 +192731,40 @@ PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, #endif #endif -/* Called when finished processing a row of data */ PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); -/* Internal use only. Called before first row of data */ PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); #if defined(PNG_READ_GAMMA_SUPPORTED) PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); #endif -/* combine a row of data, dealing with alpha, etc. if requested */ PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, int mask)); #if defined(PNG_READ_INTERLACING_SUPPORTED) -/* expand an interlaced row */ -/* OLD pre-1.0.9 interface: -PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass, png_uint_32 transformations)); - */ PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); #endif -/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ - #if defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* grab pixels out of a row for an interlaced pass */ PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, png_bytep row, int pass)); #endif -/* unfilter a row */ PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); -/* Choose the best filter to use and filter the row data */ PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, png_row_infop row_info)); -/* Write out the filtered row. */ PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, png_bytep filtered_row)); -/* finish a row while reading, dealing with interlacing passes, etc. */ PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); -/* initialize the row buffers, etc. */ PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); -/* optional call to update the users info structure */ PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, png_infop info_ptr)); -/* these are the functions that do the transformations */ #if defined(PNG_READ_FILLER_SUPPORTED) PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, png_bytep row, png_uint_32 filler, png_uint_32 flags)); @@ -213332,7 +192791,7 @@ PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, #endif #if defined(PNG_WRITE_FILLER_SUPPORTED) || \ - defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, png_bytep row, png_uint_32 flags)); #endif @@ -213423,11 +192882,6 @@ PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, png_bytep row, png_color_16p trans_value)); #endif -/* The following decodes the appropriate chunks, and does error correction, - * then calls the appropriate callback for the chunk if it is valid. - */ - -/* decode the IHDR chunk */ PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 length)); PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, @@ -213526,7 +192980,6 @@ PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, png_bytep chunk_name)); -/* handle the transformations for reading and writing */ PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); @@ -213590,7 +193043,7 @@ PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, #if defined(PNG_ASSEMBLER_CODE_SUPPORTED) #if defined(PNG_MMX_CODE_SUPPORTED) -/* png.c */ /* PRIVATE */ + /* PRIVATE */ PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)); #endif #endif @@ -213617,8 +193070,6 @@ png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); #endif /* PNG_pHYs_SUPPORTED */ #endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ -/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ - #endif /* PNG_INTERNAL */ #ifdef __cplusplus @@ -213626,43 +193077,26 @@ png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); #endif #endif /* PNG_VERSION_INFO_ONLY */ -/* do not put anything past this line */ #endif /* PNG_H */ /********* End of inlined file: png.h *********/ - #define PNG_NO_EXTERN + #define PNG_NO_EXTERN /********* Start of inlined file: png.c *********/ -/* png.c - location for general purpose libpng functions - * - * Last changed in libpng 1.2.21 [October 4, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ #define PNG_INTERNAL #define PNG_NO_EXTERN -/* Generate a compiler error if there is an old png.h in the search path. */ typedef version_1_2_21 Your_png_h_is_not_version_1_2_21; -/* Version information for C files. This had better match the version - * string defined in png.h. */ - #ifdef PNG_USE_GLOBAL_ARRAYS -/* png_libpng_ver was changed to a function in version 1.0.5c */ PNG_CONST char png_libpng_ver[18] = PNG_LIBPNG_VER_STRING; #ifdef PNG_READ_SUPPORTED -/* png_sig was changed to a function in version 1.0.5c */ -/* Place to hold the signature string for a PNG file. */ PNG_CONST png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; #endif /* PNG_READ_SUPPORTED */ -/* Invoke global declarations for constant strings for known chunk types */ PNG_IHDR; PNG_IDAT; PNG_IEND; @@ -213686,41 +193120,23 @@ PNG_tRNS; PNG_zTXt; #ifdef PNG_READ_SUPPORTED -/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ -/* start of interlace block */ PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; -/* offset to next interlace block */ PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; -/* start of interlace block in the y direction */ PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; -/* offset to next interlace block in the y direction */ PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; -/* Height of interlace block. This is not currently used - if you need - * it, uncomment it here and in png.h -PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; -*/ - -/* Mask to determine which pixels are valid in a pass */ PNG_CONST int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; -/* Mask to determine which pixels to overwrite while displaying */ PNG_CONST int FARDATA png_pass_dsp_mask[] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; #endif /* PNG_READ_SUPPORTED */ #endif /* PNG_USE_GLOBAL_ARRAYS */ -/* Tells libpng that we have already handled the first "num_bytes" bytes - * of the PNG file signature. If the PNG data is embedded into another - * stream we can set num_bytes = 8 so that libpng will not attempt to read - * or write any of the magic bytes before it starts on the IHDR. - */ - #ifdef PNG_READ_SUPPORTED void PNGAPI png_set_sig_bytes(png_structp png_ptr, int num_bytes) @@ -213728,42 +193144,30 @@ png_set_sig_bytes(png_structp png_ptr, int num_bytes) if(png_ptr == NULL) return; png_debug(1, "in png_set_sig_bytes\n"); if (num_bytes > 8) - png_error(png_ptr, "Too many bytes for PNG signature."); + png_error(png_ptr, "Too many bytes for PNG signature."); png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); } -/* Checks whether the supplied bytes match the PNG signature. We allow - * checking less than the full 8-byte signature so that those apps that - * already read the first few bytes of a file to determine the file type - * can simply check the remaining bytes for extra assurance. Returns - * an integer less than, equal to, or greater than zero if sig is found, - * respectively, to be less than, to match, or be greater than the correct - * PNG signature (this is the same behaviour as strcmp, memcmp, etc). - */ int PNGAPI png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check) { png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; if (num_to_check > 8) - num_to_check = 8; + num_to_check = 8; else if (num_to_check < 1) - return (-1); + return (-1); if (start > 7) - return (-1); + return (-1); if (start + num_to_check > 8) - num_to_check = 8 - start; + num_to_check = 8 - start; return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); } #if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* (Obsolete) function to check signature bytes. It does not allow one - * to check a partial signature. This function might be removed in the - * future - use png_sig_cmp(). Returns true (nonzero) if the file is PNG. - */ int PNGAPI png_check_sig(png_bytep sig, int num) { @@ -213773,7 +193177,6 @@ png_check_sig(png_bytep sig, int num) #endif /* PNG_READ_SUPPORTED */ #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -/* Function to allocate memory for zlib and clear it to 0. */ #ifdef PNG_1_0_X voidpf PNGAPI #else @@ -213789,8 +193192,8 @@ png_zalloc(voidpf png_ptr, uInt items, uInt size) if(png_ptr == NULL) return (NULL); if (items > PNG_UINT_32_MAX/size) { - png_warning (p, "Potential overflow in png_zalloc()"); - return (NULL); + png_warning (p, "Potential overflow in png_zalloc()"); + return (NULL); } num_bytes = (png_uint_32)items * size; @@ -213800,23 +193203,22 @@ png_zalloc(voidpf png_ptr, uInt items, uInt size) #if defined(PNG_1_0_X) && !defined(PNG_NO_ZALLOC_ZERO) if (ptr == NULL) - return ((voidpf)ptr); + return ((voidpf)ptr); if (num_bytes > (png_uint_32)0x8000L) { - png_memset(ptr, 0, (png_size_t)0x8000L); - png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0, - (png_size_t)(num_bytes - (png_uint_32)0x8000L)); + png_memset(ptr, 0, (png_size_t)0x8000L); + png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0, + (png_size_t)(num_bytes - (png_uint_32)0x8000L)); } else { - png_memset(ptr, 0, (png_size_t)num_bytes); + png_memset(ptr, 0, (png_size_t)num_bytes); } #endif return ((voidpf)ptr); } -/* function to free memory for zlib */ #ifdef PNG_1_0_X void PNGAPI #else @@ -213827,47 +193229,33 @@ png_zfree(voidpf png_ptr, voidpf ptr) png_free((png_structp)png_ptr, (png_voidp)ptr); } -/* Reset the CRC variable to 32 bits of 1's. Care must be taken - * in case CRC is > 32 bits to leave the top bits 0. - */ void /* PRIVATE */ png_reset_crc(png_structp png_ptr) { png_ptr->crc = crc32(0, Z_NULL, 0); } -/* Calculate the CRC over a section of data. We can only pass as - * much data to this routine as the largest single buffer size. We - * also check that this data will actually be used before going to the - * trouble of calculating it. - */ void /* PRIVATE */ png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length) { int need_crc = 1; - if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ { - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == - (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) - need_crc = 0; + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; } - else /* critical */ + else /* critical */ { - if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) - need_crc = 0; + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; } if (need_crc) - png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); } -/* Allocate the memory for an info_struct for the application. We don't - * really need the png_ptr, but it could potentially be useful in the - * future. This should be used in favour of malloc(png_sizeof(png_info)) - * and png_info_init() so that applications that want to use a shared - * libpng don't have to be recompiled if png_info changes size. - */ png_infop PNGAPI png_create_info_struct(png_structp png_ptr) { @@ -213877,21 +193265,16 @@ png_create_info_struct(png_structp png_ptr) if(png_ptr == NULL) return (NULL); #ifdef PNG_USER_MEM_SUPPORTED info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, - png_ptr->malloc_fn, png_ptr->mem_ptr); + png_ptr->malloc_fn, png_ptr->mem_ptr); #else info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); #endif if (info_ptr != NULL) - png_info_init_3(&info_ptr, png_sizeof(png_info)); + png_info_init_3(&info_ptr, png_sizeof(png_info)); return (info_ptr); } -/* This function frees the memory associated with a single info struct. - * Normally, one would use either png_destroy_read_struct() or - * png_destroy_write_struct() to free an info struct, but this may be - * useful for some applications. - */ void PNGAPI png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) { @@ -213900,32 +193283,27 @@ png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) png_debug(1, "in png_destroy_info_struct\n"); if (info_ptr_ptr != NULL) - info_ptr = *info_ptr_ptr; + info_ptr = *info_ptr_ptr; if (info_ptr != NULL) { - png_info_destroy(png_ptr, info_ptr); + png_info_destroy(png_ptr, info_ptr); #ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, - png_ptr->mem_ptr); + png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, + png_ptr->mem_ptr); #else - png_destroy_struct((png_voidp)info_ptr); + png_destroy_struct((png_voidp)info_ptr); #endif - *info_ptr_ptr = NULL; + *info_ptr_ptr = NULL; } } -/* Initialize the info structure. This is now an internal function (0.89) - * and applications using it are urged to use png_create_info_struct() - * instead. - */ #if defined(PNG_1_0_X) || defined(PNG_1_2_X) #undef png_info_init void PNGAPI png_info_init(png_infop info_ptr) { - /* We only come here via pre-1.0.12-compiled applications */ png_info_init_3(&info_ptr, 0); } #endif @@ -213940,13 +193318,12 @@ png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) png_debug(1, "in png_info_init_3\n"); if(png_sizeof(png_info) > png_info_struct_size) - { - png_destroy_struct(info_ptr); - info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); - *ptr_ptr = info_ptr; - } + { + png_destroy_struct(info_ptr); + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); + *ptr_ptr = info_ptr; + } - /* set everything to 0 */ png_memset(info_ptr, 0, png_sizeof (png_info)); } @@ -213957,14 +193334,14 @@ png_data_freer(png_structp png_ptr, png_infop info_ptr, { png_debug(1, "in png_data_freer\n"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; if(freer == PNG_DESTROY_WILL_FREE_DATA) - info_ptr->free_me |= mask; + info_ptr->free_me |= mask; else if(freer == PNG_USER_WILL_FREE_DATA) - info_ptr->free_me &= ~mask; + info_ptr->free_me &= ~mask; else - png_warning(png_ptr, - "Unknown freer parameter in png_data_freer."); + png_warning(png_ptr, + "Unknown freer parameter in png_data_freer."); } #endif @@ -213974,10 +193351,9 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, { png_debug(1, "in png_free_data\n"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; #if defined(PNG_TEXT_SUPPORTED) -/* free text item num or (if num == -1) all text items */ #ifdef PNG_FREE_ME_SUPPORTED if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) #else @@ -213986,43 +193362,41 @@ if (mask & PNG_FREE_TEXT) { if (num != -1) { - if (info_ptr->text && info_ptr->text[num].key) - { - png_free(png_ptr, info_ptr->text[num].key); - info_ptr->text[num].key = NULL; - } + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } } else { - int i; - for (i = 0; i < info_ptr->num_text; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); - png_free(png_ptr, info_ptr->text); - info_ptr->text = NULL; - info_ptr->num_text=0; + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; } } #endif #if defined(PNG_tRNS_SUPPORTED) -/* free any tRNS entry */ #ifdef PNG_FREE_ME_SUPPORTED if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) #else if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS)) #endif { - png_free(png_ptr, info_ptr->trans); - info_ptr->valid &= ~PNG_INFO_tRNS; + png_free(png_ptr, info_ptr->trans); + info_ptr->valid &= ~PNG_INFO_tRNS; #ifndef PNG_FREE_ME_SUPPORTED - png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; + png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; #endif - info_ptr->trans = NULL; + info_ptr->trans = NULL; } #endif #if defined(PNG_sCAL_SUPPORTED) -/* free any sCAL entry */ #ifdef PNG_FREE_ME_SUPPORTED if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) #else @@ -214030,60 +193404,57 @@ if (mask & PNG_FREE_SCAL) #endif { #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, info_ptr->scal_s_width); - png_free(png_ptr, info_ptr->scal_s_height); - info_ptr->scal_s_width = NULL; - info_ptr->scal_s_height = NULL; + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; #endif - info_ptr->valid &= ~PNG_INFO_sCAL; + info_ptr->valid &= ~PNG_INFO_sCAL; } #endif #if defined(PNG_pCAL_SUPPORTED) -/* free any pCAL entry */ #ifdef PNG_FREE_ME_SUPPORTED if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) #else if (mask & PNG_FREE_PCAL) #endif { - png_free(png_ptr, info_ptr->pcal_purpose); - png_free(png_ptr, info_ptr->pcal_units); - info_ptr->pcal_purpose = NULL; - info_ptr->pcal_units = NULL; - if (info_ptr->pcal_params != NULL) - { - int i; - for (i = 0; i < (int)info_ptr->pcal_nparams; i++) - { - png_free(png_ptr, info_ptr->pcal_params[i]); - info_ptr->pcal_params[i]=NULL; - } - png_free(png_ptr, info_ptr->pcal_params); - info_ptr->pcal_params = NULL; - } - info_ptr->valid &= ~PNG_INFO_pCAL; + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + int i; + for (i = 0; i < (int)info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i]=NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; } #endif #if defined(PNG_iCCP_SUPPORTED) -/* free any iCCP entry */ #ifdef PNG_FREE_ME_SUPPORTED if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) #else if (mask & PNG_FREE_ICCP) #endif { - png_free(png_ptr, info_ptr->iccp_name); - png_free(png_ptr, info_ptr->iccp_profile); - info_ptr->iccp_name = NULL; - info_ptr->iccp_profile = NULL; - info_ptr->valid &= ~PNG_INFO_iCCP; + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; } #endif #if defined(PNG_sPLT_SUPPORTED) -/* free a given sPLT entry, or (if num == -1) all sPLT entries */ #ifdef PNG_FREE_ME_SUPPORTED if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) #else @@ -214092,27 +193463,27 @@ if (mask & PNG_FREE_SPLT) { if (num != -1) { - if(info_ptr->splt_palettes) - { - png_free(png_ptr, info_ptr->splt_palettes[num].name); - png_free(png_ptr, info_ptr->splt_palettes[num].entries); - info_ptr->splt_palettes[num].name = NULL; - info_ptr->splt_palettes[num].entries = NULL; - } + if(info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } } else { - if(info_ptr->splt_palettes_num) - { - int i; - for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); + if(info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); - png_free(png_ptr, info_ptr->splt_palettes); - info_ptr->splt_palettes = NULL; - info_ptr->splt_palettes_num = 0; - } - info_ptr->valid &= ~PNG_INFO_sPLT; + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; } } #endif @@ -214120,8 +193491,8 @@ if (mask & PNG_FREE_SPLT) #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) if(png_ptr->unknown_chunk.data) { - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; } #ifdef PNG_FREE_ME_SUPPORTED if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) @@ -214131,97 +193502,90 @@ if (mask & PNG_FREE_UNKN) { if (num != -1) { - if(info_ptr->unknown_chunks) - { - png_free(png_ptr, info_ptr->unknown_chunks[num].data); - info_ptr->unknown_chunks[num].data = NULL; - } + if(info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } } else { - int i; + int i; - if(info_ptr->unknown_chunks_num) - { - for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); + if(info_ptr->unknown_chunks_num) + { + for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); - png_free(png_ptr, info_ptr->unknown_chunks); - info_ptr->unknown_chunks = NULL; - info_ptr->unknown_chunks_num = 0; - } + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } } } #endif #if defined(PNG_hIST_SUPPORTED) -/* free any hIST entry */ #ifdef PNG_FREE_ME_SUPPORTED if ((mask & PNG_FREE_HIST) & info_ptr->free_me) #else if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST)) #endif { - png_free(png_ptr, info_ptr->hist); - info_ptr->hist = NULL; - info_ptr->valid &= ~PNG_INFO_hIST; + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; #ifndef PNG_FREE_ME_SUPPORTED - png_ptr->flags &= ~PNG_FLAG_FREE_HIST; + png_ptr->flags &= ~PNG_FLAG_FREE_HIST; #endif } #endif -/* free any PLTE entry that was internally allocated */ #ifdef PNG_FREE_ME_SUPPORTED if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) #else if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE)) #endif { - png_zfree(png_ptr, info_ptr->palette); - info_ptr->palette = NULL; - info_ptr->valid &= ~PNG_INFO_PLTE; + png_zfree(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; #ifndef PNG_FREE_ME_SUPPORTED - png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; + png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; #endif - info_ptr->num_palette = 0; + info_ptr->num_palette = 0; } #if defined(PNG_INFO_IMAGE_SUPPORTED) -/* free any image bits attached to the info structure */ #ifdef PNG_FREE_ME_SUPPORTED if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) #else if (mask & PNG_FREE_ROWS) #endif { - if(info_ptr->row_pointers) - { - int row; - for (row = 0; row < (int)info_ptr->height; row++) - { - png_free(png_ptr, info_ptr->row_pointers[row]); - info_ptr->row_pointers[row]=NULL; - } - png_free(png_ptr, info_ptr->row_pointers); - info_ptr->row_pointers=NULL; - } - info_ptr->valid &= ~PNG_INFO_IDAT; + if(info_ptr->row_pointers) + { + int row; + for (row = 0; row < (int)info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row]=NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers=NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; } #endif #ifdef PNG_FREE_ME_SUPPORTED if(num == -1) - info_ptr->free_me &= ~mask; + info_ptr->free_me &= ~mask; else - info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); + info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); #endif } -/* This is an internal routine to free any memory that the info struct is - * pointing to before re-using it or freeing the struct itself. Recall - * that png_free() checks for NULL pointers for us. - */ void /* PRIVATE */ png_info_destroy(png_structp png_ptr, png_infop info_ptr) { @@ -214232,9 +193596,9 @@ png_info_destroy(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) if (png_ptr->num_chunk_list) { - png_free(png_ptr, png_ptr->chunk_list); - png_ptr->chunk_list=NULL; - png_ptr->num_chunk_list=0; + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + png_ptr->num_chunk_list=0; } #endif @@ -214242,10 +193606,6 @@ png_info_destroy(png_structp png_ptr, png_infop info_ptr) } #endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ -/* This function returns a pointer to the io_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy() or png_read_destroy() are called. - */ png_voidp PNGAPI png_get_io_ptr(png_structp png_ptr) { @@ -214255,12 +193615,6 @@ png_get_io_ptr(png_structp png_ptr) #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) #if !defined(PNG_NO_STDIO) -/* Initialize the default input/output functions for the PNG file. If you - * use your own read or write routines, you can call either png_set_read_fn() - * or png_set_write_fn() instead of png_init_io(). If you have defined - * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't - * necessarily available. - */ void PNGAPI png_init_io(png_structp png_ptr, png_FILE_p fp) { @@ -214271,49 +193625,46 @@ png_init_io(png_structp png_ptr, png_FILE_p fp) #endif #if defined(PNG_TIME_RFC1123_SUPPORTED) -/* Convert the supplied time into an RFC 1123 string suitable for use in - * a "Creation Time" or other text-based time string. - */ png_charp PNGAPI png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime) { static PNG_CONST char short_months[12][4] = - {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; if(png_ptr == NULL) return (NULL); if (png_ptr->time_buffer == NULL) { - png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* - png_sizeof(char))); + png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* + png_sizeof(char))); } #if defined(_WIN32_WCE) { - wchar_t time_buf[29]; - wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"), - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); - WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29, - NULL, NULL); + wchar_t time_buf[29]; + wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"), + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29, + NULL, NULL); } #else #ifdef USE_FAR_KEYWORD { - char near_time_buf[29]; - png_snprintf6(near_time_buf,29,"%d %s %d %02d:%02d:%02d +0000", - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); - png_memcpy(png_ptr->time_buffer, near_time_buf, - 29*png_sizeof(char)); + char near_time_buf[29]; + png_snprintf6(near_time_buf,29,"%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + png_memcpy(png_ptr->time_buffer, near_time_buf, + 29*png_sizeof(char)); } #else png_snprintf6(png_ptr->time_buffer,29,"%d %s %d %02d:%02d:%02d +0000", - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); #endif #endif /* _WIN32_WCE */ return ((png_charp)png_ptr->time_buffer); @@ -214332,18 +193683,9 @@ png_get_copyright(png_structp png_ptr) Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\n"); } -/* The following return the library version as a short string in the - * format 1.0.0 through 99.99.99zz. To get the version of *.h files - * used with your application, print out PNG_LIBPNG_VER_STRING, which - * is defined in png.h. - * Note: now there is no difference between png_get_libpng_ver() and - * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, - * it is guaranteed that png.c uses the correct version of png.h. - */ png_charp PNGAPI png_get_libpng_ver(png_structp png_ptr) { - /* Version of *.c files used when building libpng */ png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ return ((png_charp) PNG_LIBPNG_VER_STRING); } @@ -214351,7 +193693,6 @@ png_get_libpng_ver(png_structp png_ptr) png_charp PNGAPI png_get_header_ver(png_structp png_ptr) { - /* Version of *.h files used when building libpng */ png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ return ((png_charp) PNG_LIBPNG_VER_STRING); } @@ -214359,7 +193700,6 @@ png_get_header_ver(png_structp png_ptr) png_charp PNGAPI png_get_header_version(png_structp png_ptr) { - /* Returns longer string containing both version and date */ png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ return ((png_charp) PNG_HEADER_VERSION_STRING #ifndef PNG_READ_SUPPORTED @@ -214373,20 +193713,18 @@ png_get_header_version(png_structp png_ptr) int PNGAPI png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name) { - /* check chunk_name and return "keep" value if it's on the list, else 0 */ int i; png_bytep p; if(png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) - return 0; + return 0; p=png_ptr->chunk_list+png_ptr->num_chunk_list*5-5; for (i = png_ptr->num_chunk_list; i; i--, p-=5) - if (!png_memcmp(chunk_name, p, 4)) - return ((int)*(p+4)); + if (!png_memcmp(chunk_name, p, 4)) + return ((int)*(p+4)); return 0; } #endif -/* This function, added to libpng-1.0.6g, is untested. */ int PNGAPI png_reset_zstream(png_structp png_ptr) { @@ -214395,35 +193733,30 @@ png_reset_zstream(png_structp png_ptr) } #endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ -/* This function was added to libpng-1.0.7 */ png_uint_32 PNGAPI png_access_version_number(void) { - /* Version of *.c files used when building libpng */ return((png_uint_32) PNG_LIBPNG_VER); } #if defined(PNG_READ_SUPPORTED) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) #if !defined(PNG_1_0_X) -/* this function was added to libpng 1.2.0 */ int PNGAPI png_mmx_support(void) { - /* obsolete, to be removed from libpng-1.4.0 */ - return -1; + return -1; } #endif /* PNG_1_0_X */ #endif /* PNG_READ_SUPPORTED && PNG_ASSEMBLER_CODE_SUPPORTED */ #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) #ifdef PNG_SIZE_T -/* Added at libpng version 1.2.6 */ PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); png_size_t PNGAPI png_convert_size(size_t size) { if (size > (png_size_t)-1) - PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ + PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ return ((png_size_t)size); } #endif /* PNG_SIZE_T */ @@ -214431,19 +193764,6 @@ png_convert_size(size_t size) /********* End of inlined file: png.c *********/ /********* Start of inlined file: pngerror.c *********/ -/* pngerror.c - stub functions for i/o and memory allocation - * - * Last changed in libpng 1.2.20 October 4, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all error handling. Users who - * need special error handling are expected to write replacement functions - * and use png_set_error_fn() to use those functions. See the instructions - * at each function. - */ #define PNG_INTERNAL @@ -214457,11 +193777,6 @@ png_default_warning PNGARG((png_structp png_ptr, png_const_charp warning_message)); #endif /* PNG_NO_WARNINGS */ -/* This function is called whenever there is a fatal error. This function - * should not be changed. If there is a need to handle errors differently, - * you should supply a replacement error function and use png_set_error_fn() - * to replace the error function at run-time. - */ #ifndef PNG_NO_ERROR_TEXT void PNGAPI png_error(png_structp png_ptr, png_const_charp error_message) @@ -214470,43 +193785,41 @@ png_error(png_structp png_ptr, png_const_charp error_message) char msg[16]; if (png_ptr != NULL) { - if (png_ptr->flags& - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) - { - if (*error_message == '#') - { - int offset; - for (offset=1; offset<15; offset++) - if (*(error_message+offset) == ' ') - break; - if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) - { - int i; - for (i=0; iflags&PNG_FLAG_STRIP_ERROR_TEXT) - { - msg[0]='0'; - msg[1]='\0'; - error_message=msg; - } - } - } + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == '#') + { + int offset; + for (offset=1; offset<15; offset++) + if (*(error_message+offset) == ' ') + break; + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i=0; iflags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0]='0'; + msg[1]='\0'; + error_message=msg; + } + } + } } #endif if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_ptr, error_message); + (*(png_ptr->error_fn))(png_ptr, error_message); - /* If the custom handler doesn't exist, or if it returns, - use the default handler, which will not return. */ png_default_error(png_ptr, error_message); } #else @@ -214514,20 +193827,13 @@ void PNGAPI png_err(png_structp png_ptr) { if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_ptr, '\0'); + (*(png_ptr->error_fn))(png_ptr, '\0'); - /* If the custom handler doesn't exist, or if it returns, - use the default handler, which will not return. */ png_default_error(png_ptr, '\0'); } #endif /* PNG_NO_ERROR_TEXT */ #ifndef PNG_NO_WARNINGS -/* This function is called whenever there is a non-fatal error. This function - * should not be changed. If there is a need to handle warnings differently, - * you should supply a replacement warning function and use - * png_set_error_fn() to replace the warning function at run-time. - */ void PNGAPI png_warning(png_structp png_ptr, png_const_charp warning_message) { @@ -214536,35 +193842,25 @@ png_warning(png_structp png_ptr, png_const_charp warning_message) { #ifdef PNG_ERROR_NUMBERS_SUPPORTED if (png_ptr->flags& - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) #endif - { - if (*warning_message == '#') - { - for (offset=1; offset<15; offset++) - if (*(warning_message+offset) == ' ') - break; - } - } - if (png_ptr != NULL && png_ptr->warning_fn != NULL) - (*(png_ptr->warning_fn))(png_ptr, warning_message+offset); + { + if (*warning_message == '#') + { + for (offset=1; offset<15; offset++) + if (*(warning_message+offset) == ' ') + break; + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_ptr, warning_message+offset); } else - png_default_warning(png_ptr, warning_message+offset); + png_default_warning(png_ptr, warning_message+offset); } #endif /* PNG_NO_WARNINGS */ -/* These utilities are used internally to build an error message that relates - * to the current chunk. The chunk name comes from png_ptr->chunk_name, - * this is used to prefix the message. The message is limited in length - * to 63 bytes, the name characters are output as hex digits wrapped in [] - * if the character is invalid. - */ #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) -/*static PNG_CONST char png_digit[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F' -};*/ #if !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) static void /* PRIVATE */ @@ -214575,28 +193871,28 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp while (iin < 4) { - int c = png_ptr->chunk_name[iin++]; - if (isnonalpha(c)) - { - buffer[iout++] = '['; - buffer[iout++] = png_digit[(c & 0xf0) >> 4]; - buffer[iout++] = png_digit[c & 0x0f]; - buffer[iout++] = ']'; - } - else - { - buffer[iout++] = (png_byte)c; - } + int c = png_ptr->chunk_name[iin++]; + if (isnonalpha(c)) + { + buffer[iout++] = '['; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = ']'; + } + else + { + buffer[iout++] = (png_byte)c; + } } if (error_message == NULL) - buffer[iout] = 0; + buffer[iout] = 0; else { - buffer[iout++] = ':'; - buffer[iout++] = ' '; - png_strncpy(buffer+iout, error_message, 63); - buffer[iout+63] = 0; + buffer[iout++] = ':'; + buffer[iout++] = ' '; + png_strncpy(buffer+iout, error_message, 63); + buffer[iout+63] = 0; } } @@ -214606,11 +193902,11 @@ png_chunk_error(png_structp png_ptr, png_const_charp error_message) { char msg[18+64]; if (png_ptr == NULL) - png_error(png_ptr, error_message); + png_error(png_ptr, error_message); else { - png_format_buffer(png_ptr, msg, error_message); - png_error(png_ptr, msg); + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); } } #endif /* PNG_READ_SUPPORTED */ @@ -214622,20 +193918,15 @@ png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) { char msg[18+64]; if (png_ptr == NULL) - png_warning(png_ptr, warning_message); + png_warning(png_ptr, warning_message); else { - png_format_buffer(png_ptr, msg, warning_message); - png_warning(png_ptr, msg); + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); } } #endif /* PNG_NO_WARNINGS */ -/* This is the default error handling function. Note that replacements for - * this function MUST NOT RETURN, or the program will likely crash. This - * function is used by default, or if the program supplies NULL for the - * error function pointer in png_set_error_fn(). - */ static void /* PRIVATE */ png_default_error(png_structp png_ptr, png_const_charp error_message) { @@ -214643,22 +193934,22 @@ png_default_error(png_structp png_ptr, png_const_charp error_message) #ifdef PNG_ERROR_NUMBERS_SUPPORTED if (*error_message == '#') { - int offset; - char error_number[16]; - for (offset=0; offset<15; offset++) - { - error_number[offset] = *(error_message+offset+1); - if (*(error_message+offset) == ' ') - break; - } - if((offset > 1) && (offset < 15)) - { - error_number[offset-1]='\0'; - fprintf(stderr, "libpng error no. %s: %s\n", error_number, - error_message+offset); - } - else - fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset); + int offset; + char error_number[16]; + for (offset=0; offset<15; offset++) + { + error_number[offset] = *(error_message+offset+1); + if (*(error_message+offset) == ' ') + break; + } + if((offset > 1) && (offset < 15)) + { + error_number[offset-1]='\0'; + fprintf(stderr, "libpng error no. %s: %s\n", error_number, + error_message+offset); + } + else + fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset); } else #endif @@ -214670,9 +193961,9 @@ png_default_error(png_structp png_ptr, png_const_charp error_message) { # ifdef USE_FAR_KEYWORD { - jmp_buf jmpbuf; - png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); - longjmp(jmpbuf, 1); + jmp_buf jmpbuf; + png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); + longjmp(jmpbuf, 1); } # else longjmp(png_ptr->jmpbuf, 1); @@ -214687,11 +193978,6 @@ png_default_error(png_structp png_ptr, png_const_charp error_message) } #ifndef PNG_NO_WARNINGS -/* This function is called when there is a warning, but the library thinks - * it can continue anyway. Replacement functions don't have to do anything - * here if you don't want them to. In the default configuration, png_ptr is - * not used, but it is passed in case it may be useful. - */ static void /* PRIVATE */ png_default_warning(png_structp png_ptr, png_const_charp warning_message) { @@ -214699,26 +193985,26 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message) # ifdef PNG_ERROR_NUMBERS_SUPPORTED if (*warning_message == '#') { - int offset; - char warning_number[16]; - for (offset=0; offset<15; offset++) - { - warning_number[offset]=*(warning_message+offset+1); - if (*(warning_message+offset) == ' ') - break; - } - if((offset > 1) && (offset < 15)) - { - warning_number[offset-1]='\0'; - fprintf(stderr, "libpng warning no. %s: %s\n", warning_number, - warning_message+offset); - } - else - fprintf(stderr, "libpng warning: %s\n", warning_message); + int offset; + char warning_number[16]; + for (offset=0; offset<15; offset++) + { + warning_number[offset]=*(warning_message+offset+1); + if (*(warning_message+offset) == ' ') + break; + } + if((offset > 1) && (offset < 15)) + { + warning_number[offset-1]='\0'; + fprintf(stderr, "libpng warning no. %s: %s\n", warning_number, + warning_message+offset); + } + else + fprintf(stderr, "libpng warning: %s\n", warning_message); } else # endif - fprintf(stderr, "libpng warning: %s\n", warning_message); + fprintf(stderr, "libpng warning: %s\n", warning_message); #else warning_message = warning_message; /* make compiler happy */ #endif @@ -214726,31 +194012,22 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message) } #endif /* PNG_NO_WARNINGS */ -/* This function is called when the application wants to use another method - * of handling errors and warnings. Note that the error function MUST NOT - * return to the calling routine or serious problems will occur. The return - * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) - */ void PNGAPI png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn) { if (png_ptr == NULL) - return; + return; png_ptr->error_ptr = error_ptr; png_ptr->error_fn = error_fn; png_ptr->warning_fn = warning_fn; } -/* This function returns a pointer to the error_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy and png_read_destroy are called. - */ png_voidp PNGAPI png_get_error_ptr(png_structp png_ptr) { if (png_ptr == NULL) - return NULL; + return NULL; return ((png_voidp)png_ptr->error_ptr); } @@ -214760,8 +194037,8 @@ png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) { if(png_ptr != NULL) { - png_ptr->flags &= - ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); } } #endif @@ -214769,14 +194046,6 @@ png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) /********* End of inlined file: pngerror.c *********/ /********* Start of inlined file: pngget.c *********/ -/* pngget.c - retrieval of values from info struct - * - * Last changed in libpng 1.2.15 January 5, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ #define PNG_INTERNAL @@ -214786,18 +194055,18 @@ png_uint_32 PNGAPI png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->valid & flag); + return(info_ptr->valid & flag); else - return(0); + return(0); } png_uint_32 PNGAPI png_get_rowbytes(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->rowbytes); + return(info_ptr->rowbytes); else - return(0); + return(0); } #if defined(PNG_INFO_IMAGE_SUPPORTED) @@ -214805,20 +194074,19 @@ png_bytepp PNGAPI png_get_rows(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->row_pointers); + return(info_ptr->row_pointers); else - return(0); + return(0); } #endif #ifdef PNG_EASY_ACCESS_SUPPORTED -/* easy access to info, added in libpng-0.99 */ png_uint_32 PNGAPI png_get_image_width(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) { - return info_ptr->width; + return info_ptr->width; } return (0); } @@ -214828,7 +194096,7 @@ png_get_image_height(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) { - return info_ptr->height; + return info_ptr->height; } return (0); } @@ -214838,7 +194106,7 @@ png_get_bit_depth(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) { - return info_ptr->bit_depth; + return info_ptr->bit_depth; } return (0); } @@ -214848,7 +194116,7 @@ png_get_color_type(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) { - return info_ptr->color_type; + return info_ptr->color_type; } return (0); } @@ -214858,7 +194126,7 @@ png_get_filter_type(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) { - return info_ptr->filter_type; + return info_ptr->filter_type; } return (0); } @@ -214868,7 +194136,7 @@ png_get_interlace_type(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) { - return info_ptr->interlace_type; + return info_ptr->interlace_type; } return (0); } @@ -214878,7 +194146,7 @@ png_get_compression_type(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) { - return info_ptr->compression_type; + return info_ptr->compression_type; } return (0); } @@ -214890,10 +194158,10 @@ png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_pHYs_SUPPORTED) if (info_ptr->valid & PNG_INFO_pHYs) { - png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter"); - if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) - return (0); - else return (info_ptr->x_pixels_per_unit); + png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + else return (info_ptr->x_pixels_per_unit); } #else return (0); @@ -214908,10 +194176,10 @@ png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_pHYs_SUPPORTED) if (info_ptr->valid & PNG_INFO_pHYs) { - png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter"); - if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) - return (0); - else return (info_ptr->y_pixels_per_unit); + png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + else return (info_ptr->y_pixels_per_unit); } #else return (0); @@ -214926,11 +194194,11 @@ png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_pHYs_SUPPORTED) if (info_ptr->valid & PNG_INFO_pHYs) { - png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter"); - if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER || - info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit) - return (0); - else return (info_ptr->x_pixels_per_unit); + png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER || + info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit) + return (0); + else return (info_ptr->x_pixels_per_unit); } #else return (0); @@ -214946,12 +194214,12 @@ png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_pHYs_SUPPORTED) if (info_ptr->valid & PNG_INFO_pHYs) { - png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio"); - if (info_ptr->x_pixels_per_unit == 0) - return ((float)0.0); - else - return ((float)((float)info_ptr->y_pixels_per_unit - /(float)info_ptr->x_pixels_per_unit)); + png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio"); + if (info_ptr->x_pixels_per_unit == 0) + return ((float)0.0); + else + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); } #else return (0.0); @@ -214967,10 +194235,10 @@ png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_oFFs_SUPPORTED) if (info_ptr->valid & PNG_INFO_oFFs) { - png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) - return (0); - else return (info_ptr->x_offset); + png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + else return (info_ptr->x_offset); } #else return (0); @@ -214985,10 +194253,10 @@ png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_oFFs_SUPPORTED) if (info_ptr->valid & PNG_INFO_oFFs) { - png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) - return (0); - else return (info_ptr->y_offset); + png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + else return (info_ptr->y_offset); } #else return (0); @@ -215003,10 +194271,10 @@ png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_oFFs_SUPPORTED) if (info_ptr->valid & PNG_INFO_oFFs) { - png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) - return (0); - else return (info_ptr->x_offset); + png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + else return (info_ptr->x_offset); } #else return (0); @@ -215021,10 +194289,10 @@ png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_oFFs_SUPPORTED) if (info_ptr->valid & PNG_INFO_oFFs) { - png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) - return (0); - else return (info_ptr->y_offset); + png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + else return (info_ptr->y_offset); } #else return (0); @@ -215037,35 +194305,35 @@ png_uint_32 PNGAPI png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) { return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr) - *.0254 +.5)); + *.0254 +.5)); } png_uint_32 PNGAPI png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) { return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr) - *.0254 +.5)); + *.0254 +.5)); } png_uint_32 PNGAPI png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) { return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr) - *.0254 +.5)); + *.0254 +.5)); } float PNGAPI png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr) { return ((float)png_get_x_offset_microns(png_ptr, info_ptr) - *.00003937); + *.00003937); } float PNGAPI png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr) { return ((float)png_get_y_offset_microns(png_ptr, info_ptr) - *.00003937); + *.00003937); } #if defined(PNG_pHYs_SUPPORTED) @@ -215077,53 +194345,51 @@ png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr, if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) { - png_debug1(1, "in %s retrieval function\n", "pHYs"); - if (res_x != NULL) - { - *res_x = info_ptr->x_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (res_y != NULL) - { - *res_y = info_ptr->y_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (unit_type != NULL) - { - *unit_type = (int)info_ptr->phys_unit_type; - retval |= PNG_INFO_pHYs; - if(*unit_type == 1) - { - if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); - if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); - } - } + png_debug1(1, "in %s retrieval function\n", "pHYs"); + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + if(*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } } return (retval); } #endif /* PNG_pHYs_SUPPORTED */ #endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ -/* png_get_channels really belongs in here, too, but it's been around longer */ - #endif /* PNG_EASY_ACCESS_SUPPORTED */ png_byte PNGAPI png_get_channels(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->channels); + return(info_ptr->channels); else - return (0); + return (0); } png_bytep PNGAPI png_get_signature(png_structp png_ptr, png_infop info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->signature); + return(info_ptr->signature); else - return (NULL); + return (NULL); } #if defined(PNG_bKGD_SUPPORTED) @@ -215132,11 +194398,11 @@ png_get_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p *background) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) - && background != NULL) + && background != NULL) { - png_debug1(1, "in %s retrieval function\n", "bKGD"); - *background = &(info_ptr->background); - return (PNG_INFO_bKGD); + png_debug1(1, "in %s retrieval function\n", "bKGD"); + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); } return (0); } @@ -215151,24 +194417,24 @@ png_get_cHRM(png_structp png_ptr, png_infop info_ptr, { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) { - png_debug1(1, "in %s retrieval function\n", "cHRM"); - if (white_x != NULL) - *white_x = (double)info_ptr->x_white; - if (white_y != NULL) - *white_y = (double)info_ptr->y_white; - if (red_x != NULL) - *red_x = (double)info_ptr->x_red; - if (red_y != NULL) - *red_y = (double)info_ptr->y_red; - if (green_x != NULL) - *green_x = (double)info_ptr->x_green; - if (green_y != NULL) - *green_y = (double)info_ptr->y_green; - if (blue_x != NULL) - *blue_x = (double)info_ptr->x_blue; - if (blue_y != NULL) - *blue_y = (double)info_ptr->y_blue; - return (PNG_INFO_cHRM); + png_debug1(1, "in %s retrieval function\n", "cHRM"); + if (white_x != NULL) + *white_x = (double)info_ptr->x_white; + if (white_y != NULL) + *white_y = (double)info_ptr->y_white; + if (red_x != NULL) + *red_x = (double)info_ptr->x_red; + if (red_y != NULL) + *red_y = (double)info_ptr->y_red; + if (green_x != NULL) + *green_x = (double)info_ptr->x_green; + if (green_y != NULL) + *green_y = (double)info_ptr->y_green; + if (blue_x != NULL) + *blue_x = (double)info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = (double)info_ptr->y_blue; + return (PNG_INFO_cHRM); } return (0); } @@ -215182,24 +194448,24 @@ png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) { - png_debug1(1, "in %s retrieval function\n", "cHRM"); - if (white_x != NULL) - *white_x = info_ptr->int_x_white; - if (white_y != NULL) - *white_y = info_ptr->int_y_white; - if (red_x != NULL) - *red_x = info_ptr->int_x_red; - if (red_y != NULL) - *red_y = info_ptr->int_y_red; - if (green_x != NULL) - *green_x = info_ptr->int_x_green; - if (green_y != NULL) - *green_y = info_ptr->int_y_green; - if (blue_x != NULL) - *blue_x = info_ptr->int_x_blue; - if (blue_y != NULL) - *blue_y = info_ptr->int_y_blue; - return (PNG_INFO_cHRM); + png_debug1(1, "in %s retrieval function\n", "cHRM"); + if (white_x != NULL) + *white_x = info_ptr->int_x_white; + if (white_y != NULL) + *white_y = info_ptr->int_y_white; + if (red_x != NULL) + *red_x = info_ptr->int_x_red; + if (red_y != NULL) + *red_y = info_ptr->int_y_red; + if (green_x != NULL) + *green_x = info_ptr->int_x_green; + if (green_y != NULL) + *green_y = info_ptr->int_y_green; + if (blue_x != NULL) + *blue_x = info_ptr->int_x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->int_y_blue; + return (PNG_INFO_cHRM); } return (0); } @@ -215212,11 +194478,11 @@ png_uint_32 PNGAPI png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) - && file_gamma != NULL) + && file_gamma != NULL) { - png_debug1(1, "in %s retrieval function\n", "gAMA"); - *file_gamma = (double)info_ptr->gamma; - return (PNG_INFO_gAMA); + png_debug1(1, "in %s retrieval function\n", "gAMA"); + *file_gamma = (double)info_ptr->gamma; + return (PNG_INFO_gAMA); } return (0); } @@ -215224,14 +194490,14 @@ png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma) #ifdef PNG_FIXED_POINT_SUPPORTED png_uint_32 PNGAPI png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, - png_fixed_point *int_file_gamma) + png_fixed_point *int_file_gamma) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) - && int_file_gamma != NULL) + && int_file_gamma != NULL) { - png_debug1(1, "in %s retrieval function\n", "gAMA"); - *int_file_gamma = info_ptr->int_gamma; - return (PNG_INFO_gAMA); + png_debug1(1, "in %s retrieval function\n", "gAMA"); + *int_file_gamma = info_ptr->int_gamma; + return (PNG_INFO_gAMA); } return (0); } @@ -215243,11 +194509,11 @@ png_uint_32 PNGAPI png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) - && file_srgb_intent != NULL) + && file_srgb_intent != NULL) { - png_debug1(1, "in %s retrieval function\n", "sRGB"); - *file_srgb_intent = (int)info_ptr->srgb_intent; - return (PNG_INFO_sRGB); + png_debug1(1, "in %s retrieval function\n", "sRGB"); + *file_srgb_intent = (int)info_ptr->srgb_intent; + return (PNG_INFO_sRGB); } return (0); } @@ -215256,20 +194522,18 @@ png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) #if defined(PNG_iCCP_SUPPORTED) png_uint_32 PNGAPI png_get_iCCP(png_structp png_ptr, png_infop info_ptr, - png_charpp name, int *compression_type, - png_charpp profile, png_uint_32 *proflen) + png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) - && name != NULL && profile != NULL && proflen != NULL) + && name != NULL && profile != NULL && proflen != NULL) { - png_debug1(1, "in %s retrieval function\n", "iCCP"); - *name = info_ptr->iccp_name; - *profile = info_ptr->iccp_profile; - /* compression_type is a dummy so the API won't have to change - if we introduce multiple compression types later. */ - *proflen = (int)info_ptr->iccp_proflen; - *compression_type = (int)info_ptr->iccp_compression; - return (PNG_INFO_iCCP); + png_debug1(1, "in %s retrieval function\n", "iCCP"); + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + *proflen = (int)info_ptr->iccp_proflen; + *compression_type = (int)info_ptr->iccp_compression; + return (PNG_INFO_iCCP); } return (0); } @@ -215278,12 +194542,12 @@ png_get_iCCP(png_structp png_ptr, png_infop info_ptr, #if defined(PNG_sPLT_SUPPORTED) png_uint_32 PNGAPI png_get_sPLT(png_structp png_ptr, png_infop info_ptr, - png_sPLT_tpp spalettes) + png_sPLT_tpp spalettes) { if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) { - *spalettes = info_ptr->splt_palettes; - return ((png_uint_32)info_ptr->splt_palettes_num); + *spalettes = info_ptr->splt_palettes; + return ((png_uint_32)info_ptr->splt_palettes_num); } return (0); } @@ -215294,11 +194558,11 @@ png_uint_32 PNGAPI png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) - && hist != NULL) + && hist != NULL) { - png_debug1(1, "in %s retrieval function\n", "hIST"); - *hist = info_ptr->hist; - return (PNG_INFO_hIST); + png_debug1(1, "in %s retrieval function\n", "hIST"); + *hist = info_ptr->hist; + return (PNG_INFO_hIST); } return (0); } @@ -215312,40 +194576,39 @@ png_get_IHDR(png_structp png_ptr, png_infop info_ptr, { if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL && - bit_depth != NULL && color_type != NULL) + bit_depth != NULL && color_type != NULL) { - png_debug1(1, "in %s retrieval function\n", "IHDR"); - *width = info_ptr->width; - *height = info_ptr->height; - *bit_depth = info_ptr->bit_depth; - if (info_ptr->bit_depth < 1 || info_ptr->bit_depth > 16) - png_error(png_ptr, "Invalid bit depth"); - *color_type = info_ptr->color_type; - if (info_ptr->color_type > 6) - png_error(png_ptr, "Invalid color type"); - if (compression_type != NULL) - *compression_type = info_ptr->compression_type; - if (filter_type != NULL) - *filter_type = info_ptr->filter_type; - if (interlace_type != NULL) - *interlace_type = info_ptr->interlace_type; + png_debug1(1, "in %s retrieval function\n", "IHDR"); + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + if (info_ptr->bit_depth < 1 || info_ptr->bit_depth > 16) + png_error(png_ptr, "Invalid bit depth"); + *color_type = info_ptr->color_type; + if (info_ptr->color_type > 6) + png_error(png_ptr, "Invalid color type"); + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; - /* check for potential overflow of rowbytes */ - if (*width == 0 || *width > PNG_UINT_31_MAX) - png_error(png_ptr, "Invalid image width"); - if (*height == 0 || *height > PNG_UINT_31_MAX) - png_error(png_ptr, "Invalid image height"); - if (info_ptr->width > (PNG_UINT_32_MAX - >> 3) /* 8-byte RGBA pixels */ - - 64 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - { - png_warning(png_ptr, - "Width too large for libpng to process image data."); - } - return (1); + if (*width == 0 || *width > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image width"); + if (*height == 0 || *height > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid image height"); + if (info_ptr->width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + { + png_warning(png_ptr, + "Width too large for libpng to process image data."); + } + return (1); } return (0); } @@ -215356,13 +194619,13 @@ png_get_oFFs(png_structp png_ptr, png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) - && offset_x != NULL && offset_y != NULL && unit_type != NULL) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) { - png_debug1(1, "in %s retrieval function\n", "oFFs"); - *offset_x = info_ptr->x_offset; - *offset_y = info_ptr->y_offset; - *unit_type = (int)info_ptr->offset_unit_type; - return (PNG_INFO_oFFs); + png_debug1(1, "in %s retrieval function\n", "oFFs"); + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); } return (0); } @@ -215375,18 +194638,18 @@ png_get_pCAL(png_structp png_ptr, png_infop info_ptr, png_charp *units, png_charpp *params) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) - && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && - nparams != NULL && units != NULL && params != NULL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) { - png_debug1(1, "in %s retrieval function\n", "pCAL"); - *purpose = info_ptr->pcal_purpose; - *X0 = info_ptr->pcal_X0; - *X1 = info_ptr->pcal_X1; - *type = (int)info_ptr->pcal_type; - *nparams = (int)info_ptr->pcal_nparams; - *units = info_ptr->pcal_units; - *params = info_ptr->pcal_params; - return (PNG_INFO_pCAL); + png_debug1(1, "in %s retrieval function\n", "pCAL"); + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); } return (0); } @@ -215396,33 +194659,33 @@ png_get_pCAL(png_structp png_ptr, png_infop info_ptr, #ifdef PNG_FLOATING_POINT_SUPPORTED png_uint_32 PNGAPI png_get_sCAL(png_structp png_ptr, png_infop info_ptr, - int *unit, double *width, double *height) + int *unit, double *width, double *height) { - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sCAL)) - { - *unit = info_ptr->scal_unit; - *width = info_ptr->scal_pixel_width; - *height = info_ptr->scal_pixel_height; - return (PNG_INFO_sCAL); - } - return(0); + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_pixel_width; + *height = info_ptr->scal_pixel_height; + return (PNG_INFO_sCAL); + } + return(0); } #else #ifdef PNG_FIXED_POINT_SUPPORTED png_uint_32 PNGAPI png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr, - int *unit, png_charpp width, png_charpp height) + int *unit, png_charpp width, png_charpp height) { - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sCAL)) - { - *unit = info_ptr->scal_unit; - *width = info_ptr->scal_s_width; - *height = info_ptr->scal_s_height; - return (PNG_INFO_sCAL); - } - return(0); + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + return(0); } #endif #endif @@ -215436,24 +194699,24 @@ png_get_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 retval = 0; if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_pHYs)) + (info_ptr->valid & PNG_INFO_pHYs)) { - png_debug1(1, "in %s retrieval function\n", "pHYs"); - if (res_x != NULL) - { - *res_x = info_ptr->x_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (res_y != NULL) - { - *res_y = info_ptr->y_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (unit_type != NULL) - { - *unit_type = (int)info_ptr->phys_unit_type; - retval |= PNG_INFO_pHYs; - } + png_debug1(1, "in %s retrieval function\n", "pHYs"); + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } } return (retval); } @@ -215464,13 +194727,13 @@ png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette, int *num_palette) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) - && palette != NULL) + && palette != NULL) { - png_debug1(1, "in %s retrieval function\n", "PLTE"); - *palette = info_ptr->palette; - *num_palette = info_ptr->num_palette; - png_debug1(3, "num_palette = %d\n", *num_palette); - return (PNG_INFO_PLTE); + png_debug1(1, "in %s retrieval function\n", "PLTE"); + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d\n", *num_palette); + return (PNG_INFO_PLTE); } return (0); } @@ -215480,11 +194743,11 @@ png_uint_32 PNGAPI png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) - && sig_bit != NULL) + && sig_bit != NULL) { - png_debug1(1, "in %s retrieval function\n", "sBIT"); - *sig_bit = &(info_ptr->sig_bit); - return (PNG_INFO_sBIT); + png_debug1(1, "in %s retrieval function\n", "sBIT"); + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); } return (0); } @@ -215497,17 +194760,17 @@ png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, { if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) { - png_debug1(1, "in %s retrieval function\n", - (png_ptr->chunk_name[0] == '\0' ? "text" - : (png_const_charp)png_ptr->chunk_name)); - if (text_ptr != NULL) - *text_ptr = info_ptr->text; - if (num_text != NULL) - *num_text = info_ptr->num_text; - return ((png_uint_32)info_ptr->num_text); + png_debug1(1, "in %s retrieval function\n", + (png_ptr->chunk_name[0] == '\0' ? "text" + : (png_const_charp)png_ptr->chunk_name)); + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + if (num_text != NULL) + *num_text = info_ptr->num_text; + return ((png_uint_32)info_ptr->num_text); } if (num_text != NULL) - *num_text = 0; + *num_text = 0; return(0); } #endif @@ -215517,11 +194780,11 @@ png_uint_32 PNGAPI png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time) { if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) - && mod_time != NULL) + && mod_time != NULL) { - png_debug1(1, "in %s retrieval function\n", "tIME"); - *mod_time = &(info_ptr->mod_time); - return (PNG_INFO_tIME); + png_debug1(1, "in %s retrieval function\n", "tIME"); + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); } return (0); } @@ -215535,32 +194798,32 @@ png_get_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 retval = 0; if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) { - png_debug1(1, "in %s retrieval function\n", "tRNS"); - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (trans != NULL) - { - *trans = info_ptr->trans; - retval |= PNG_INFO_tRNS; - } - if (trans_values != NULL) - *trans_values = &(info_ptr->trans_values); - } - else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ - { - if (trans_values != NULL) - { - *trans_values = &(info_ptr->trans_values); - retval |= PNG_INFO_tRNS; - } - if(trans != NULL) - *trans = NULL; - } - if(num_trans != NULL) - { - *num_trans = info_ptr->num_trans; - retval |= PNG_INFO_tRNS; - } + png_debug1(1, "in %s retrieval function\n", "tRNS"); + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans != NULL) + { + *trans = info_ptr->trans; + retval |= PNG_INFO_tRNS; + } + if (trans_values != NULL) + *trans_values = &(info_ptr->trans_values); + } + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_values != NULL) + { + *trans_values = &(info_ptr->trans_values); + retval |= PNG_INFO_tRNS; + } + if(trans != NULL) + *trans = NULL; + } + if(num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } } return (retval); } @@ -215569,12 +194832,12 @@ png_get_tRNS(png_structp png_ptr, png_infop info_ptr, #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) png_uint_32 PNGAPI png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr, - png_unknown_chunkpp unknowns) + png_unknown_chunkpp unknowns) { if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) { - *unknowns = info_ptr->unknown_chunks; - return ((png_uint_32)info_ptr->unknown_chunks_num); + *unknowns = info_ptr->unknown_chunks; + return ((png_uint_32)info_ptr->unknown_chunks_num); } return (0); } @@ -215606,63 +194869,51 @@ png_get_compression_buffer_size(png_structp png_ptr) #ifdef PNG_ASSEMBLER_CODE_SUPPORTED #ifndef PNG_1_0_X -/* this function was added to libpng 1.2.0 and should exist by default */ png_uint_32 PNGAPI png_get_asm_flags (png_structp png_ptr) { - /* obsolete, to be removed from libpng-1.4.0 */ - return (png_ptr? 0L: 0L); + return (png_ptr? 0L: 0L); } -/* this function was added to libpng 1.2.0 and should exist by default */ png_uint_32 PNGAPI png_get_asm_flagmask (int flag_select) { - /* obsolete, to be removed from libpng-1.4.0 */ - flag_select=flag_select; - return 0L; + flag_select=flag_select; + return 0L; } - /* GRR: could add this: && defined(PNG_MMX_CODE_SUPPORTED) */ -/* this function was added to libpng 1.2.0 */ png_uint_32 PNGAPI png_get_mmx_flagmask (int flag_select, int *compilerID) { - /* obsolete, to be removed from libpng-1.4.0 */ - flag_select=flag_select; - *compilerID = -1; /* unknown (i.e., no asm/MMX code compiled) */ - return 0L; + flag_select=flag_select; + *compilerID = -1; /* unknown (i.e., no asm/MMX code compiled) */ + return 0L; } -/* this function was added to libpng 1.2.0 */ png_byte PNGAPI png_get_mmx_bitdepth_threshold (png_structp png_ptr) { - /* obsolete, to be removed from libpng-1.4.0 */ - return (png_ptr? 0: 0); + return (png_ptr? 0: 0); } -/* this function was added to libpng 1.2.0 */ png_uint_32 PNGAPI png_get_mmx_rowbytes_threshold (png_structp png_ptr) { - /* obsolete, to be removed from libpng-1.4.0 */ - return (png_ptr? 0L: 0L); + return (png_ptr? 0L: 0L); } #endif /* ?PNG_1_0_X */ #endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED -/* these functions were added to libpng 1.2.6 */ png_uint_32 PNGAPI png_get_user_width_max (png_structp png_ptr) { - return (png_ptr? png_ptr->user_width_max : 0); + return (png_ptr? png_ptr->user_width_max : 0); } png_uint_32 PNGAPI png_get_user_height_max (png_structp png_ptr) { - return (png_ptr? png_ptr->user_height_max : 0); + return (png_ptr? png_ptr->user_height_max : 0); } #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ @@ -215670,31 +194921,13 @@ png_get_user_height_max (png_structp png_ptr) /********* End of inlined file: pngget.c *********/ /********* Start of inlined file: pngmem.c *********/ -/* pngmem.c - stub functions for memory allocation - * - * Last changed in libpng 1.2.13 November 13, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all memory allocation. Users who - * need special memory handling are expected to supply replacement - * functions for png_malloc() and png_free(), and to use - * png_create_read_struct_2() and png_create_write_struct_2() to - * identify the replacement functions. - */ #define PNG_INTERNAL #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -/* Borland DOS special memory handler */ #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* if you change this, be sure to change the one in png.h also */ -/* Allocate memory for a png_struct. The malloc and memset can be replaced - by a single call to calloc() if this is thought to improve performance. */ png_voidp /* PRIVATE */ png_create_struct(int type) { @@ -215702,7 +194935,6 @@ png_create_struct(int type) return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); } -/* Alternate version of png_create_struct, for use with user-defined malloc. */ png_voidp /* PRIVATE */ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) { @@ -215711,29 +194943,28 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) png_voidp struct_ptr; if (type == PNG_STRUCT_INFO) - size = png_sizeof(png_info); + size = png_sizeof(png_info); else if (type == PNG_STRUCT_PNG) - size = png_sizeof(png_struct); + size = png_sizeof(png_struct); else - return (png_get_copyright(NULL)); + return (png_get_copyright(NULL)); #ifdef PNG_USER_MEM_SUPPORTED if(malloc_fn != NULL) { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); } else #endif /* PNG_USER_MEM_SUPPORTED */ - struct_ptr = (png_voidp)farmalloc(size); + struct_ptr = (png_voidp)farmalloc(size); if (struct_ptr != NULL) - png_memset(struct_ptr, 0, size); + png_memset(struct_ptr, 0, size); return (struct_ptr); } -/* Free memory allocated by a png_create_struct() call */ void /* PRIVATE */ png_destroy_struct(png_voidp struct_ptr) { @@ -215741,63 +194972,42 @@ png_destroy_struct(png_voidp struct_ptr) png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); } -/* Free memory allocated by a png_create_struct() call */ void /* PRIVATE */ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, - png_voidp mem_ptr) + png_voidp mem_ptr) { #endif if (struct_ptr != NULL) { #ifdef PNG_USER_MEM_SUPPORTED - if(free_fn != NULL) - { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - (*(free_fn))(png_ptr, struct_ptr); - return; - } + if(free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } #endif /* PNG_USER_MEM_SUPPORTED */ - farfree (struct_ptr); + farfree (struct_ptr); } } -/* Allocate memory. For reasonable files, size should never exceed - * 64K. However, zlib may allocate more then 64K if you don't tell - * it not to. See zconf.h and png.h for more information. zlib does - * need to allocate exactly 64K, so whatever you call here must - * have the ability to do that. - * - * Borland seems to have a problem in DOS mode for exactly 64K. - * It gives you a segment with an offset of 8 (perhaps to store its - * memory stuff). zlib doesn't like this at all, so we have to - * detect and deal with it. This code should not be needed in - * Windows or OS/2 modes, and only in 16 bit mode. This code has - * been updated by Alexander Lehmann for version 0.89 to waste less - * memory. - * - * Note that we can't use png_size_t for the "size" declaration, - * since on some systems a png_size_t is a 16-bit quantity, and as a - * result, we would be truncating potentially larger memory requests - * (which should cause a fatal error) and introducing major problems. - */ - png_voidp PNGAPI png_malloc(png_structp png_ptr, png_uint_32 size) { png_voidp ret; if (png_ptr == NULL || size == 0) - return (NULL); + return (NULL); #ifdef PNG_USER_MEM_SUPPORTED if(png_ptr->malloc_fn != NULL) - ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); else - ret = (png_malloc_default(png_ptr, size)); + ret = (png_malloc_default(png_ptr, size)); if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of memory!"); + png_error(png_ptr, "Out of memory!"); return (ret); } @@ -215808,152 +195018,148 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size) #endif /* PNG_USER_MEM_SUPPORTED */ if (png_ptr == NULL || size == 0) - return (NULL); + return (NULL); #ifdef PNG_MAX_MALLOC_64K if (size > (png_uint_32)65536L) { - png_warning(png_ptr, "Cannot Allocate > 64K"); - ret = NULL; + png_warning(png_ptr, "Cannot Allocate > 64K"); + ret = NULL; } else #endif if (size != (size_t)size) - ret = NULL; + ret = NULL; else if (size == (png_uint_32)65536L) { - if (png_ptr->offset_table == NULL) - { - /* try to see if we need to do any of this fancy stuff */ - ret = farmalloc(size); - if (ret == NULL || ((png_size_t)ret & 0xffff)) - { - int num_blocks; - png_uint_32 total_size; - png_bytep table; - int i; - png_byte huge * hptr; + if (png_ptr->offset_table == NULL) + { + ret = farmalloc(size); + if (ret == NULL || ((png_size_t)ret & 0xffff)) + { + int num_blocks; + png_uint_32 total_size; + png_bytep table; + int i; + png_byte huge * hptr; - if (ret != NULL) - { - farfree(ret); - ret = NULL; - } + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } - if(png_ptr->zlib_window_bits > 14) - num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); - else - num_blocks = 1; - if (png_ptr->zlib_mem_level >= 7) - num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); - else - num_blocks++; + if(png_ptr->zlib_window_bits > 14) + num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + else + num_blocks = 1; + if (png_ptr->zlib_mem_level >= 7) + num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + else + num_blocks++; - total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; + total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; - table = farmalloc(total_size); + table = farmalloc(total_size); - if (table == NULL) - { + if (table == NULL) + { #ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */ - else - png_warning(png_ptr, "Out Of Memory."); + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */ + else + png_warning(png_ptr, "Out Of Memory."); #endif - return (NULL); - } + return (NULL); + } - if ((png_size_t)table & 0xfff0) - { + if ((png_size_t)table & 0xfff0) + { #ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, - "Farmalloc didn't return normalized pointer"); - else - png_warning(png_ptr, - "Farmalloc didn't return normalized pointer"); + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, + "Farmalloc didn't return normalized pointer"); + else + png_warning(png_ptr, + "Farmalloc didn't return normalized pointer"); #endif - return (NULL); - } + return (NULL); + } - png_ptr->offset_table = table; - png_ptr->offset_table_ptr = farmalloc(num_blocks * - png_sizeof (png_bytep)); + png_ptr->offset_table = table; + png_ptr->offset_table_ptr = farmalloc(num_blocks * + png_sizeof (png_bytep)); - if (png_ptr->offset_table_ptr == NULL) - { + if (png_ptr->offset_table_ptr == NULL) + { #ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */ - else - png_warning(png_ptr, "Out Of memory."); + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */ + else + png_warning(png_ptr, "Out Of memory."); #endif - return (NULL); - } + return (NULL); + } - hptr = (png_byte huge *)table; - if ((png_size_t)hptr & 0xf) - { - hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); - hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ - } - for (i = 0; i < num_blocks; i++) - { - png_ptr->offset_table_ptr[i] = (png_bytep)hptr; - hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ - } + hptr = (png_byte huge *)table; + if ((png_size_t)hptr & 0xf) + { + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ + } + for (i = 0; i < num_blocks; i++) + { + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ + } - png_ptr->offset_table_number = num_blocks; - png_ptr->offset_table_count = 0; - png_ptr->offset_table_count_free = 0; - } - } + png_ptr->offset_table_number = num_blocks; + png_ptr->offset_table_count = 0; + png_ptr->offset_table_count_free = 0; + } + } - if (png_ptr->offset_table_count >= png_ptr->offset_table_number) - { + if (png_ptr->offset_table_count >= png_ptr->offset_table_number) + { #ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */ - else - png_warning(png_ptr, "Out of Memory."); + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */ + else + png_warning(png_ptr, "Out of Memory."); #endif - return (NULL); - } + return (NULL); + } - ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; + ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; } else - ret = farmalloc(size); + ret = farmalloc(size); #ifndef PNG_USER_MEM_SUPPORTED if (ret == NULL) { - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */ - else - png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */ + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */ + else + png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */ } #endif return (ret); } -/* free a pointer allocated by png_malloc(). In the default - configuration, png_ptr is not used, but is passed in case it - is needed. If ptr is NULL, return without taking any action. */ void PNGAPI png_free(png_structp png_ptr, png_voidp ptr) { if (png_ptr == NULL || ptr == NULL) - return; + return; #ifdef PNG_USER_MEM_SUPPORTED if (png_ptr->free_fn != NULL) { - (*(png_ptr->free_fn))(png_ptr, ptr); - return; + (*(png_ptr->free_fn))(png_ptr, ptr); + return; } else png_free_default(png_ptr, ptr); } @@ -215967,37 +195173,34 @@ png_free_default(png_structp png_ptr, png_voidp ptr) if (png_ptr->offset_table != NULL) { - int i; + int i; - for (i = 0; i < png_ptr->offset_table_count; i++) - { - if (ptr == png_ptr->offset_table_ptr[i]) - { - ptr = NULL; - png_ptr->offset_table_count_free++; - break; - } - } - if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) - { - farfree(png_ptr->offset_table); - farfree(png_ptr->offset_table_ptr); - png_ptr->offset_table = NULL; - png_ptr->offset_table_ptr = NULL; - } + for (i = 0; i < png_ptr->offset_table_count; i++) + { + if (ptr == png_ptr->offset_table_ptr[i]) + { + ptr = NULL; + png_ptr->offset_table_count_free++; + break; + } + } + if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) + { + farfree(png_ptr->offset_table); + farfree(png_ptr->offset_table_ptr); + png_ptr->offset_table = NULL; + png_ptr->offset_table_ptr = NULL; + } } if (ptr != NULL) { - farfree(ptr); + farfree(ptr); } } #else /* Not the Borland DOS special memory handler */ -/* Allocate memory for a png_struct or a png_info. The malloc and - memset can be replaced by a single call to calloc() if this is thought - to improve performance noticably. */ png_voidp /* PRIVATE */ png_create_struct(int type) { @@ -216005,9 +195208,6 @@ png_create_struct(int type) return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); } -/* Allocate memory for a png_struct or a png_info. The malloc and - memset can be replaced by a single call to calloc() if this is thought - to improve performance noticably. */ png_voidp /* PRIVATE */ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) { @@ -216016,22 +195216,22 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) png_voidp struct_ptr; if (type == PNG_STRUCT_INFO) - size = png_sizeof(png_info); + size = png_sizeof(png_info); else if (type == PNG_STRUCT_PNG) - size = png_sizeof(png_struct); + size = png_sizeof(png_struct); else - return (NULL); + return (NULL); #ifdef PNG_USER_MEM_SUPPORTED if(malloc_fn != NULL) { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - struct_ptr = (*(malloc_fn))(png_ptr, size); - if (struct_ptr != NULL) - png_memset(struct_ptr, 0, size); - return (struct_ptr); + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); } #endif /* PNG_USER_MEM_SUPPORTED */ @@ -216045,12 +195245,11 @@ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) # endif #endif if (struct_ptr != NULL) - png_memset(struct_ptr, 0, size); + png_memset(struct_ptr, 0, size); return (struct_ptr); } -/* Free memory allocated by a png_create_struct() call */ void /* PRIVATE */ png_destroy_struct(png_voidp struct_ptr) { @@ -216058,42 +195257,35 @@ png_destroy_struct(png_voidp struct_ptr) png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); } -/* Free memory allocated by a png_create_struct() call */ void /* PRIVATE */ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, - png_voidp mem_ptr) + png_voidp mem_ptr) { #endif /* PNG_USER_MEM_SUPPORTED */ if (struct_ptr != NULL) { #ifdef PNG_USER_MEM_SUPPORTED - if(free_fn != NULL) - { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - (*(free_fn))(png_ptr, struct_ptr); - return; - } + if(free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } #endif /* PNG_USER_MEM_SUPPORTED */ #if defined(__TURBOC__) && !defined(__FLAT__) - farfree(struct_ptr); + farfree(struct_ptr); #else # if defined(_MSC_VER) && defined(MAXSEG_64K) - hfree(struct_ptr); + hfree(struct_ptr); # else - free(struct_ptr); + free(struct_ptr); # endif #endif } } -/* Allocate memory. For reasonable files, size should never exceed - 64K. However, zlib may allocate more then 64K if you don't tell - it not to. See zconf.h and png.h for more information. zlib does - need to allocate exactly 64K, so whatever you call here must - have the ability to do that. */ - png_voidp PNGAPI png_malloc(png_structp png_ptr, png_uint_32 size) { @@ -216101,14 +195293,14 @@ png_malloc(png_structp png_ptr, png_uint_32 size) #ifdef PNG_USER_MEM_SUPPORTED if (png_ptr == NULL || size == 0) - return (NULL); + return (NULL); if(png_ptr->malloc_fn != NULL) - ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); else - ret = (png_malloc_default(png_ptr, size)); + ret = (png_malloc_default(png_ptr, size)); if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory!"); + png_error(png_ptr, "Out of Memory!"); return (ret); } @@ -216119,21 +195311,20 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size) #endif /* PNG_USER_MEM_SUPPORTED */ if (png_ptr == NULL || size == 0) - return (NULL); + return (NULL); #ifdef PNG_MAX_MALLOC_64K if (size > (png_uint_32)65536L) { #ifndef PNG_USER_MEM_SUPPORTED - if(png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Cannot Allocate > 64K"); - else + if(png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Cannot Allocate > 64K"); + else #endif - return NULL; + return NULL; } #endif - /* Check for overflow */ #if defined(__TURBOC__) && !defined(__FLAT__) if (size != (unsigned long)size) ret = NULL; @@ -216155,25 +195346,23 @@ png_malloc_default(png_structp png_ptr, png_uint_32 size) #ifndef PNG_USER_MEM_SUPPORTED if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory"); + png_error(png_ptr, "Out of Memory"); #endif return (ret); } -/* Free a pointer allocated by png_malloc(). If ptr is NULL, return - without taking any action. */ void PNGAPI png_free(png_structp png_ptr, png_voidp ptr) { if (png_ptr == NULL || ptr == NULL) - return; + return; #ifdef PNG_USER_MEM_SUPPORTED if (png_ptr->free_fn != NULL) { - (*(png_ptr->free_fn))(png_ptr, ptr); - return; + (*(png_ptr->free_fn))(png_ptr, ptr); + return; } else png_free_default(png_ptr, ptr); } @@ -216181,7 +195370,7 @@ void PNGAPI png_free_default(png_structp png_ptr, png_voidp ptr) { if (png_ptr == NULL || ptr == NULL) - return; + return; #endif /* PNG_USER_MEM_SUPPORTED */ @@ -216201,11 +195390,6 @@ png_free_default(png_structp png_ptr, png_voidp ptr) #if defined(PNG_1_0_X) # define png_malloc_warn png_malloc #else -/* This function was added at libpng version 1.2.3. The png_malloc_warn() - * function will set up png_malloc() to issue a png_warning and return NULL - * instead of issuing a png_error, if it fails to allocate the requested - * memory. - */ png_voidp PNGAPI png_malloc_warn(png_structp png_ptr, png_uint_32 size) { @@ -216229,7 +195413,7 @@ png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2, size = (png_size_t)length; if ((png_uint_32)size != length) - png_error(png_ptr,"Overflow in png_memcpy_check."); + png_error(png_ptr,"Overflow in png_memcpy_check."); return(png_memcpy (s1, s2, size)); } @@ -216242,16 +195426,13 @@ png_memset_check (png_structp png_ptr, png_voidp s1, int value, size = (png_size_t)length; if ((png_uint_32)size != length) - png_error(png_ptr,"Overflow in png_memset_check."); + png_error(png_ptr,"Overflow in png_memset_check."); return (png_memset (s1, value, size)); } #ifdef PNG_USER_MEM_SUPPORTED -/* This function is called when the application wants to use another method - * of allocating and freeing memory. - */ void PNGAPI png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn) @@ -216263,10 +195444,6 @@ png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr } } -/* This function returns a pointer to the mem_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy and png_read_destroy are called. - */ png_voidp PNGAPI png_get_mem_ptr(png_structp png_ptr) { @@ -216278,23 +195455,11 @@ png_get_mem_ptr(png_structp png_ptr) /********* End of inlined file: pngmem.c *********/ /********* Start of inlined file: pngread.c *********/ -/* pngread.c - read a PNG file - * - * Last changed in libpng 1.2.20 September 7, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file contains routines that an application calls directly to - * read a PNG file or stream. - */ #define PNG_INTERNAL #if defined(PNG_READ_SUPPORTED) -/* Create a PNG structure for reading, and allocate any memory needed. */ png_structp PNGAPI png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn) @@ -216302,10 +195467,9 @@ png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, #ifdef PNG_USER_MEM_SUPPORTED return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); } -/* Alternate create PNG structure for reading, and allocate any memory needed. */ png_structp PNGAPI png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, @@ -216326,14 +195490,13 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_debug(1, "in png_create_read_struct\n"); #ifdef PNG_USER_MEM_SUPPORTED png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, - (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); #else png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); #endif if (png_ptr == NULL) - return (NULL); + return (NULL); - /* added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_ptr->user_width_max=PNG_USER_WIDTH_MAX; png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; @@ -216346,15 +195509,15 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, if (setjmp(png_ptr->jmpbuf)) #endif { - png_free(png_ptr, png_ptr->zbuf); - png_ptr->zbuf=NULL; + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf=NULL; #ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)png_ptr, - (png_free_ptr)free_fn, (png_voidp)mem_ptr); + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); #else - png_destroy_struct((png_voidp)png_ptr); + png_destroy_struct((png_voidp)png_ptr); #endif - return (NULL); + return (NULL); } #ifdef USE_FAR_KEYWORD png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); @@ -216370,58 +195533,52 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, i=0; do { - if(user_png_ver[i] != png_libpng_ver[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + if(user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; } while (png_libpng_ver[i++]); if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) { - /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so - * we must recompile any applications that use any older library version. - * For versions after libpng 1.0, we will be compatible, so we need - * only check the first digit. - */ - if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || - (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || - (user_png_ver[0] == '0' && user_png_ver[2] < '9')) - { + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[80]; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); + char msg[80]; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); #endif #ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; + png_ptr->flags=0; #endif - png_error(png_ptr, - "Incompatible libpng version in application and library"); - } + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } } - /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); + (png_uint_32)png_ptr->zbuf_size); png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; switch (inflateInit(&png_ptr->zstream)) { - case Z_OK: /* Do nothing */ break; - case Z_MEM_ERROR: - case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; - case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; - default: png_error(png_ptr, "Unknown zlib error"); + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; + default: png_error(png_ptr, "Unknown zlib error"); } png_ptr->zstream.next_out = png_ptr->zbuf; @@ -216430,30 +195587,23 @@ png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); #ifdef PNG_SETJMP_SUPPORTED -/* Applications that neglect to set up their own setjmp() and then encounter - a png_error() will longjmp here. Since the jmpbuf is then meaningless we - abort instead of returning. */ #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) - PNG_ABORT(); + PNG_ABORT(); png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); #else if (setjmp(png_ptr->jmpbuf)) - PNG_ABORT(); + PNG_ABORT(); #endif #endif return (png_ptr); } #if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* Initialize PNG structure for reading, and allocate any memory needed. - This interface is deprecated in favour of the png_create_read_struct(), - and it will disappear as of libpng-1.3.0. */ #undef png_read_init void PNGAPI png_read_init(png_structp png_ptr) { - /* We only come here via pre-1.0.7-compiled applications */ png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0); } @@ -216461,45 +195611,44 @@ void PNGAPI png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t png_info_size) { - /* We only come here via pre-1.0.12-compiled applications */ if(png_ptr == NULL) return; #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) if(png_sizeof(png_struct) > png_struct_size || - png_sizeof(png_info) > png_info_size) + png_sizeof(png_info) > png_info_size) { - char msg[80]; - png_ptr->warning_fn=NULL; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); + char msg[80]; + png_ptr->warning_fn=NULL; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); } #endif if(png_sizeof(png_struct) > png_struct_size) - { - png_ptr->error_fn=NULL; + { + png_ptr->error_fn=NULL; #ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; + png_ptr->flags=0; #endif - png_error(png_ptr, - "The png struct allocated by the application for reading is too small."); - } + png_error(png_ptr, + "The png struct allocated by the application for reading is too small."); + } if(png_sizeof(png_info) > png_info_size) - { - png_ptr->error_fn=NULL; + { + png_ptr->error_fn=NULL; #ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; + png_ptr->flags=0; #endif - png_error(png_ptr, - "The info struct allocated by application for reading is too small."); - } + png_error(png_ptr, + "The info struct allocated by application for reading is too small."); + } png_read_init_3(&png_ptr, user_png_ver, png_struct_size); } #endif /* PNG_1_0_X || PNG_1_2_X */ @@ -216520,62 +195669,57 @@ png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, do { - if(user_png_ver[i] != png_libpng_ver[i]) - { + if(user_png_ver[i] != png_libpng_ver[i]) + { #ifdef PNG_LEGACY_SUPPORTED - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; #else - png_ptr->warning_fn=NULL; - png_warning(png_ptr, - "Application uses deprecated png_read_init() and should be recompiled."); - break; + png_ptr->warning_fn=NULL; + png_warning(png_ptr, + "Application uses deprecated png_read_init() and should be recompiled."); + break; #endif - } + } } while (png_libpng_ver[i++]); png_debug(1, "in png_read_init_3\n"); #ifdef PNG_SETJMP_SUPPORTED - /* save jump buffer and error functions */ png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); #endif if(png_sizeof(png_struct) > png_struct_size) - { - png_destroy_struct(png_ptr); - *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); - png_ptr = *ptr_ptr; - } + { + png_destroy_struct(png_ptr); + *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + png_ptr = *ptr_ptr; + } - /* reset all variables to 0 */ png_memset(png_ptr, 0, png_sizeof (png_struct)); #ifdef PNG_SETJMP_SUPPORTED - /* restore jump buffer */ png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); #endif - /* added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_ptr->user_width_max=PNG_USER_WIDTH_MAX; png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; #endif - /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); + (png_uint_32)png_ptr->zbuf_size); png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; switch (inflateInit(&png_ptr->zstream)) { - case Z_OK: /* Do nothing */ break; - case Z_MEM_ERROR: - case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break; - case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break; - default: png_error(png_ptr, "Unknown zlib error"); + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break; + default: png_error(png_ptr, "Unknown zlib error"); } png_ptr->zstream.next_out = png_ptr->zbuf; @@ -216585,256 +195729,238 @@ png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, } #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. This has been - * changed in v0.90 to allow reading a file that already has the magic - * bytes read from the stream. You can tell libpng how many bytes have - * been read from the beginning of the stream (up to the maximum of 8) - * via png_set_sig_bytes(), and we will only check the remaining bytes - * here. The application can then have access to the signature bytes we - * read if it is determined that this isn't a valid PNG file. - */ void PNGAPI png_read_info(png_structp png_ptr, png_infop info_ptr) { if(png_ptr == NULL) return; png_debug(1, "in png_read_info\n"); - /* If we haven't checked all of the PNG signature bytes, do so now. */ if (png_ptr->sig_bytes < 8) { - png_size_t num_checked = png_ptr->sig_bytes, - num_to_check = 8 - num_checked; + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; - png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); - png_ptr->sig_bytes = 8; + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) - { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); - } - if (num_checked < 3) - png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; } for(;;) { #ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IHDR; - PNG_CONST PNG_IDAT; - PNG_CONST PNG_IEND; - PNG_CONST PNG_PLTE; + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; #if defined(PNG_READ_bKGD_SUPPORTED) - PNG_CONST PNG_bKGD; + PNG_CONST PNG_bKGD; #endif #if defined(PNG_READ_cHRM_SUPPORTED) - PNG_CONST PNG_cHRM; + PNG_CONST PNG_cHRM; #endif #if defined(PNG_READ_gAMA_SUPPORTED) - PNG_CONST PNG_gAMA; + PNG_CONST PNG_gAMA; #endif #if defined(PNG_READ_hIST_SUPPORTED) - PNG_CONST PNG_hIST; + PNG_CONST PNG_hIST; #endif #if defined(PNG_READ_iCCP_SUPPORTED) - PNG_CONST PNG_iCCP; + PNG_CONST PNG_iCCP; #endif #if defined(PNG_READ_iTXt_SUPPORTED) - PNG_CONST PNG_iTXt; + PNG_CONST PNG_iTXt; #endif #if defined(PNG_READ_oFFs_SUPPORTED) - PNG_CONST PNG_oFFs; + PNG_CONST PNG_oFFs; #endif #if defined(PNG_READ_pCAL_SUPPORTED) - PNG_CONST PNG_pCAL; + PNG_CONST PNG_pCAL; #endif #if defined(PNG_READ_pHYs_SUPPORTED) - PNG_CONST PNG_pHYs; + PNG_CONST PNG_pHYs; #endif #if defined(PNG_READ_sBIT_SUPPORTED) - PNG_CONST PNG_sBIT; + PNG_CONST PNG_sBIT; #endif #if defined(PNG_READ_sCAL_SUPPORTED) - PNG_CONST PNG_sCAL; + PNG_CONST PNG_sCAL; #endif #if defined(PNG_READ_sPLT_SUPPORTED) - PNG_CONST PNG_sPLT; + PNG_CONST PNG_sPLT; #endif #if defined(PNG_READ_sRGB_SUPPORTED) - PNG_CONST PNG_sRGB; + PNG_CONST PNG_sRGB; #endif #if defined(PNG_READ_tEXt_SUPPORTED) - PNG_CONST PNG_tEXt; + PNG_CONST PNG_tEXt; #endif #if defined(PNG_READ_tIME_SUPPORTED) - PNG_CONST PNG_tIME; + PNG_CONST PNG_tIME; #endif #if defined(PNG_READ_tRNS_SUPPORTED) - PNG_CONST PNG_tRNS; + PNG_CONST PNG_tRNS; #endif #if defined(PNG_READ_zTXt_SUPPORTED) - PNG_CONST PNG_zTXt; + PNG_CONST PNG_zTXt; #endif #endif /* PNG_USE_LOCAL_ARRAYS */ - png_byte chunk_length[4]; - png_uint_32 length; + png_byte chunk_length[4]; + png_uint_32 length; - png_read_data(png_ptr, chunk_length, 4); - length = png_get_uint_31(png_ptr,chunk_length); + png_read_data(png_ptr, chunk_length, 4); + length = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); - png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name, - length); + png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name, + length); - /* This should be a binary subdivision search or a hash for - * matching the chunk name rather than a linear search. - */ - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - if(png_ptr->mode & PNG_AFTER_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + if(png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; - if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) - png_handle_IHDR(png_ptr, info_ptr, length); - else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) - png_handle_IEND(png_ptr, info_ptr, length); + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) - { - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_ptr->mode |= PNG_HAVE_IDAT; - png_handle_unknown(png_ptr, info_ptr, length); - if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_ptr->mode |= PNG_HAVE_PLTE; - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - break; - } - } + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + break; + } + } #endif - else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_handle_PLTE(png_ptr, info_ptr, length); - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); - png_ptr->idat_size = length; - png_ptr->mode |= PNG_HAVE_IDAT; - break; - } + png_ptr->idat_size = length; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } #if defined(PNG_READ_bKGD_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) - png_handle_bKGD(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_cHRM_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) - png_handle_cHRM(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_gAMA_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) - png_handle_gAMA(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_hIST_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) - png_handle_hIST(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_oFFs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) - png_handle_oFFs(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_pCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) - png_handle_pCAL(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) - png_handle_sCAL(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_pHYs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) - png_handle_pHYs(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sBIT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) - png_handle_sBIT(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sRGB_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) - png_handle_sRGB(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_iCCP_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) - png_handle_iCCP(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sPLT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) - png_handle_sPLT(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_tEXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) - png_handle_tEXt(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_tIME_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) - png_handle_tIME(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_tRNS_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) - png_handle_tRNS(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_zTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) - png_handle_zTXt(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_iTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) - png_handle_iTXt(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); #endif - else - png_handle_unknown(png_ptr, info_ptr, length); + else + png_handle_unknown(png_ptr, info_ptr, length); } } #endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ -/* optional call to update the users info_ptr structure */ void PNGAPI png_read_update_info(png_structp png_ptr, png_infop info_ptr) { png_debug(1, "in png_read_update_info\n"); if(png_ptr == NULL) return; if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); + png_read_start_row(png_ptr); else - png_warning(png_ptr, - "Ignoring extra png_read_update_info() call; row buffer not reallocated"); + png_warning(png_ptr, + "Ignoring extra png_read_update_info() call; row buffer not reallocated"); png_read_transform_info(png_ptr, info_ptr); } #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Initialize palette, background, etc, after transformations - * are set, but before any reading takes place. This allows - * the user to obtain a gamma-corrected palette, for example. - * If the user doesn't call this, we will do it ourselves. - */ void PNGAPI png_start_read_image(png_structp png_ptr) { png_debug(1, "in png_start_read_image\n"); if(png_ptr == NULL) return; if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); + png_read_start_row(png_ptr); } #endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ @@ -216845,169 +195971,167 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) #ifdef PNG_USE_LOCAL_ARRAYS PNG_CONST PNG_IDAT; PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, - 0xff}; + 0xff}; PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; #endif int ret; if(png_ptr == NULL) return; png_debug2(1, "in png_read_row (row %lu, pass %d)\n", - png_ptr->row_number, png_ptr->pass); + png_ptr->row_number, png_ptr->pass); if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); + png_read_start_row(png_ptr); if (png_ptr->row_number == 0 && png_ptr->pass == 0) { - /* check for transforms that have been set but were defined out */ #if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) if (png_ptr->transformations & PNG_INVERT_MONO) - png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined."); #endif #if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) if (png_ptr->transformations & PNG_FILLER) - png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined."); #endif #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED) if (png_ptr->transformations & PNG_PACKSWAP) - png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined."); #endif #if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) if (png_ptr->transformations & PNG_PACK) - png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined."); #endif #if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) if (png_ptr->transformations & PNG_SHIFT) - png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined."); #endif #if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) if (png_ptr->transformations & PNG_BGR) - png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined."); #endif #if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) if (png_ptr->transformations & PNG_SWAP_BYTES) - png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined."); #endif } #if defined(PNG_READ_INTERLACING_SUPPORTED) - /* if interlaced and we do not need a new row, combine row and return */ if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) { - switch (png_ptr->pass) - { - case 0: - if (png_ptr->row_number & 0x07) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 1: - if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 2: - if ((png_ptr->row_number & 0x07) != 4) - { - if (dsp_row != NULL && (png_ptr->row_number & 4)) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 3: - if ((png_ptr->row_number & 3) || png_ptr->width < 3) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 4: - if ((png_ptr->row_number & 3) != 2) - { - if (dsp_row != NULL && (png_ptr->row_number & 2)) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 5: - if ((png_ptr->row_number & 1) || png_ptr->width < 2) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 6: - if (!(png_ptr->row_number & 1)) - { - png_read_finish_row(png_ptr); - return; - } - break; - } + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } } #endif if (!(png_ptr->mode & PNG_HAVE_IDAT)) - png_error(png_ptr, "Invalid attempt to read row data"); + png_error(png_ptr, "Invalid attempt to read row data"); png_ptr->zstream.next_out = png_ptr->row_buf; png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; do { - if (!(png_ptr->zstream.avail_in)) - { - while (!png_ptr->idat_size) - { - png_byte chunk_length[4]; + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_byte chunk_length[4]; - png_crc_finish(png_ptr, 0); + png_crc_finish(png_ptr, 0); - png_read_data(png_ptr, chunk_length, 4); - png_ptr->idat_size = png_get_uint_31(png_ptr,chunk_length); + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_error(png_ptr, "Not enough image data"); - } - png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_in = png_ptr->zbuf; - if (png_ptr->zbuf_size > png_ptr->idat_size) - png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; - png_crc_read(png_ptr, png_ptr->zbuf, - (png_size_t)png_ptr->zstream.avail_in); - png_ptr->idat_size -= png_ptr->zstream.avail_in; - } - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret == Z_STREAM_END) - { - if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || - png_ptr->idat_size) - png_error(png_ptr, "Extra compressed data"); - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - if (ret != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : - "Decompression error"); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, + (png_size_t)png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression error"); } while (png_ptr->zstream.avail_out); @@ -217017,86 +196141,57 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) png_ptr->row_info.bit_depth = png_ptr->bit_depth; png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); + png_ptr->row_info.width); if(png_ptr->row_buf[0]) png_read_filter_row(png_ptr, &(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->prev_row + 1, - (int)(png_ptr->row_buf[0])); + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, - png_ptr->rowbytes + 1); + png_ptr->rowbytes + 1); #if defined(PNG_MNG_FEATURES_SUPPORTED) if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) { - /* Intrapixel differencing */ - png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); } #endif if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) - png_do_read_transformations(png_ptr); + png_do_read_transformations(png_ptr); #if defined(PNG_READ_INTERLACING_SUPPORTED) - /* blow up interlaced rows to full size */ if (png_ptr->interlaced && - (png_ptr->transformations & PNG_INTERLACE)) + (png_ptr->transformations & PNG_INTERLACE)) { - if (png_ptr->pass < 6) -/* old interface (pre-1.0.9): - png_do_read_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); - */ - png_do_read_interlace(png_ptr); + if (png_ptr->pass < 6) + png_do_read_interlace(png_ptr); - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - if (row != NULL) - png_combine_row(png_ptr, row, - png_pass_mask[png_ptr->pass]); + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + if (row != NULL) + png_combine_row(png_ptr, row, + png_pass_mask[png_ptr->pass]); } else #endif { - if (row != NULL) - png_combine_row(png_ptr, row, 0xff); - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, 0xff); + if (row != NULL) + png_combine_row(png_ptr, row, 0xff); + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 0xff); } png_read_finish_row(png_ptr); if (png_ptr->read_row_fn != NULL) - (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); } #endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. If the image is interlaced, - * and png_set_interlace_handling() has been called, the rows need to - * contain the contents of the rows from the previous pass. If the - * image has alpha or transparency, and png_handle_alpha()[*] has been - * called, the rows contents must be initialized to the contents of the - * screen. - * - * "row" holds the actual image, and pixels are placed in it - * as they arrive. If the image is displayed after each pass, it will - * appear to "sparkle" in. "display_row" can be used to display a - * "chunky" progressive image, with finer detail added as it becomes - * available. If you do not want this "chunky" display, you may pass - * NULL for display_row. If you do not want the sparkle display, and - * you have not called png_handle_alpha(), you may pass NULL for rows. - * If you have called png_handle_alpha(), and the image has either an - * alpha channel or a transparency chunk, you must provide a buffer for - * rows. In this case, you do not have to provide a display_row buffer - * also, but you may. If the image is not interlaced, or if you have - * not called png_set_interlace_handling(), the display_row buffer will - * be ignored, so pass NULL to it. - * - * [*] png_handle_alpha() does not exist yet, as of this version of libpng - */ void PNGAPI png_read_rows(png_structp png_ptr, png_bytepp row, @@ -217111,43 +196206,31 @@ png_read_rows(png_structp png_ptr, png_bytepp row, rp = row; dp = display_row; if (rp != NULL && dp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep rptr = *rp++; - png_bytep dptr = *dp++; + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; - png_read_row(png_ptr, rptr, dptr); - } + png_read_row(png_ptr, rptr, dptr); + } else if(rp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep rptr = *rp; - png_read_row(png_ptr, rptr, png_bytep_NULL); - rp++; - } + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, png_bytep_NULL); + rp++; + } else if(dp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep dptr = *dp; - png_read_row(png_ptr, png_bytep_NULL, dptr); - dp++; - } + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, png_bytep_NULL, dptr); + dp++; + } } #endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read the entire image. If the image has an alpha channel or a tRNS - * chunk, and you have called png_handle_alpha()[*], you will need to - * initialize the image to the current image that PNG will be overlaying. - * We set the num_rows again here, in case it was incorrectly set in - * png_read_start_row() by a call to png_read_update_info() or - * png_start_read_image() if png_set_interlace_handling() wasn't called - * prior to either of these functions like it should have been. You can - * only call this function once. If you desire to have an image for - * each pass of a interlaced image, use png_read_rows() instead. - * - * [*] png_handle_alpha() does not exist yet, as of this version of libpng - */ void PNGAPI png_read_image(png_structp png_ptr, png_bytepp image) { @@ -217162,8 +196245,8 @@ png_read_image(png_structp png_ptr, png_bytepp image) pass = png_set_interlace_handling(png_ptr); #else if (png_ptr->interlaced) - png_error(png_ptr, - "Cannot read interlaced image -- interlace handler disabled."); + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled."); pass = 1; #endif @@ -217172,21 +196255,17 @@ png_read_image(png_structp png_ptr, png_bytepp image) for (j = 0; j < pass; j++) { - rp = image; - for (i = 0; i < image_height; i++) - { - png_read_row(png_ptr, *rp, png_bytep_NULL); - rp++; - } + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, png_bytep_NULL); + rp++; + } } } #endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. Will not read past the end of the - * file, will verify the end is accurate, and will read any comments - * or time information at the end of the file, if info is not NULL. - */ void PNGAPI png_read_end(png_structp png_ptr, png_infop info_ptr) { @@ -217200,174 +196279,170 @@ png_read_end(png_structp png_ptr, png_infop info_ptr) do { #ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IHDR; - PNG_CONST PNG_IDAT; - PNG_CONST PNG_IEND; - PNG_CONST PNG_PLTE; + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; #if defined(PNG_READ_bKGD_SUPPORTED) - PNG_CONST PNG_bKGD; + PNG_CONST PNG_bKGD; #endif #if defined(PNG_READ_cHRM_SUPPORTED) - PNG_CONST PNG_cHRM; + PNG_CONST PNG_cHRM; #endif #if defined(PNG_READ_gAMA_SUPPORTED) - PNG_CONST PNG_gAMA; + PNG_CONST PNG_gAMA; #endif #if defined(PNG_READ_hIST_SUPPORTED) - PNG_CONST PNG_hIST; + PNG_CONST PNG_hIST; #endif #if defined(PNG_READ_iCCP_SUPPORTED) - PNG_CONST PNG_iCCP; + PNG_CONST PNG_iCCP; #endif #if defined(PNG_READ_iTXt_SUPPORTED) - PNG_CONST PNG_iTXt; + PNG_CONST PNG_iTXt; #endif #if defined(PNG_READ_oFFs_SUPPORTED) - PNG_CONST PNG_oFFs; + PNG_CONST PNG_oFFs; #endif #if defined(PNG_READ_pCAL_SUPPORTED) - PNG_CONST PNG_pCAL; + PNG_CONST PNG_pCAL; #endif #if defined(PNG_READ_pHYs_SUPPORTED) - PNG_CONST PNG_pHYs; + PNG_CONST PNG_pHYs; #endif #if defined(PNG_READ_sBIT_SUPPORTED) - PNG_CONST PNG_sBIT; + PNG_CONST PNG_sBIT; #endif #if defined(PNG_READ_sCAL_SUPPORTED) - PNG_CONST PNG_sCAL; + PNG_CONST PNG_sCAL; #endif #if defined(PNG_READ_sPLT_SUPPORTED) - PNG_CONST PNG_sPLT; + PNG_CONST PNG_sPLT; #endif #if defined(PNG_READ_sRGB_SUPPORTED) - PNG_CONST PNG_sRGB; + PNG_CONST PNG_sRGB; #endif #if defined(PNG_READ_tEXt_SUPPORTED) - PNG_CONST PNG_tEXt; + PNG_CONST PNG_tEXt; #endif #if defined(PNG_READ_tIME_SUPPORTED) - PNG_CONST PNG_tIME; + PNG_CONST PNG_tIME; #endif #if defined(PNG_READ_tRNS_SUPPORTED) - PNG_CONST PNG_tRNS; + PNG_CONST PNG_tRNS; #endif #if defined(PNG_READ_zTXt_SUPPORTED) - PNG_CONST PNG_zTXt; + PNG_CONST PNG_zTXt; #endif #endif /* PNG_USE_LOCAL_ARRAYS */ - png_read_data(png_ptr, chunk_length, 4); - length = png_get_uint_31(png_ptr,chunk_length); + png_read_data(png_ptr, chunk_length, 4); + length = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); - png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name); + png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name); - if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) - png_handle_IHDR(png_ptr, info_ptr, length); - else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) - png_handle_IEND(png_ptr, info_ptr, length); + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) - { - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - png_error(png_ptr, "Too many IDAT's found"); - } - png_handle_unknown(png_ptr, info_ptr, length); - if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_ptr->mode |= PNG_HAVE_PLTE; - } + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_error(png_ptr, "Too many IDAT's found"); + } + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + } #endif - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - /* Zero length IDATs are legal after the last IDAT has been - * read, but not after other chunks have been read. - */ - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - png_error(png_ptr, "Too many IDAT's found"); - png_crc_finish(png_ptr, length); - } - else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_handle_PLTE(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_error(png_ptr, "Too many IDAT's found"); + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); #if defined(PNG_READ_bKGD_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) - png_handle_bKGD(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_cHRM_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) - png_handle_cHRM(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_gAMA_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) - png_handle_gAMA(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_hIST_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) - png_handle_hIST(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_oFFs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) - png_handle_oFFs(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_pCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) - png_handle_pCAL(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) - png_handle_sCAL(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_pHYs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) - png_handle_pHYs(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sBIT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) - png_handle_sBIT(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sRGB_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) - png_handle_sRGB(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_iCCP_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) - png_handle_iCCP(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_sPLT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) - png_handle_sPLT(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_tEXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) - png_handle_tEXt(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_tIME_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) - png_handle_tIME(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_tRNS_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) - png_handle_tRNS(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_zTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) - png_handle_zTXt(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); #endif #if defined(PNG_READ_iTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) - png_handle_iTXt(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); #endif - else - png_handle_unknown(png_ptr, info_ptr, length); + else + png_handle_unknown(png_ptr, info_ptr, length); } while (!(png_ptr->mode & PNG_HAVE_IEND)); } #endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ -/* free all memory used by the read */ void PNGAPI png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr) @@ -217381,13 +196456,13 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_debug(1, "in png_destroy_read_struct\n"); if (png_ptr_ptr != NULL) - png_ptr = *png_ptr_ptr; + png_ptr = *png_ptr_ptr; if (info_ptr_ptr != NULL) - info_ptr = *info_ptr_ptr; + info_ptr = *info_ptr_ptr; if (end_info_ptr_ptr != NULL) - end_info_ptr = *end_info_ptr_ptr; + end_info_ptr = *end_info_ptr_ptr; #ifdef PNG_USER_MEM_SUPPORTED free_fn = png_ptr->free_fn; @@ -217399,45 +196474,44 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, if (info_ptr != NULL) { #if defined(PNG_TEXT_SUPPORTED) - png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); #endif #ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); #else - png_destroy_struct((png_voidp)info_ptr); + png_destroy_struct((png_voidp)info_ptr); #endif - *info_ptr_ptr = NULL; + *info_ptr_ptr = NULL; } if (end_info_ptr != NULL) { #if defined(PNG_READ_TEXT_SUPPORTED) - png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); + png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); #endif #ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); + png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); #else - png_destroy_struct((png_voidp)end_info_ptr); + png_destroy_struct((png_voidp)end_info_ptr); #endif - *end_info_ptr_ptr = NULL; + *end_info_ptr_ptr = NULL; } if (png_ptr != NULL) { #ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); #else - png_destroy_struct((png_voidp)png_ptr); + png_destroy_struct((png_voidp)png_ptr); #endif - *png_ptr_ptr = NULL; + *png_ptr_ptr = NULL; } } -/* free all memory used by the read (old method) */ void /* PRIVATE */ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr) { @@ -217453,10 +196527,10 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr png_debug(1, "in png_read_destroy\n"); if (info_ptr != NULL) - png_info_destroy(png_ptr, info_ptr); + png_info_destroy(png_ptr, info_ptr); if (end_info_ptr != NULL) - png_info_destroy(png_ptr, end_info_ptr); + png_info_destroy(png_ptr, end_info_ptr); png_free(png_ptr, png_ptr->zbuf); png_free(png_ptr, png_ptr->big_row_buf); @@ -217474,66 +196548,66 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr #endif #ifdef PNG_FREE_ME_SUPPORTED if (png_ptr->free_me & PNG_FREE_PLTE) - png_zfree(png_ptr, png_ptr->palette); + png_zfree(png_ptr, png_ptr->palette); png_ptr->free_me &= ~PNG_FREE_PLTE; #else if (png_ptr->flags & PNG_FLAG_FREE_PLTE) - png_zfree(png_ptr, png_ptr->palette); + png_zfree(png_ptr, png_ptr->palette); png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; #endif #if defined(PNG_tRNS_SUPPORTED) || \ - defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) #ifdef PNG_FREE_ME_SUPPORTED if (png_ptr->free_me & PNG_FREE_TRNS) - png_free(png_ptr, png_ptr->trans); + png_free(png_ptr, png_ptr->trans); png_ptr->free_me &= ~PNG_FREE_TRNS; #else if (png_ptr->flags & PNG_FLAG_FREE_TRNS) - png_free(png_ptr, png_ptr->trans); + png_free(png_ptr, png_ptr->trans); png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; #endif #endif #if defined(PNG_READ_hIST_SUPPORTED) #ifdef PNG_FREE_ME_SUPPORTED if (png_ptr->free_me & PNG_FREE_HIST) - png_free(png_ptr, png_ptr->hist); + png_free(png_ptr, png_ptr->hist); png_ptr->free_me &= ~PNG_FREE_HIST; #else if (png_ptr->flags & PNG_FLAG_FREE_HIST) - png_free(png_ptr, png_ptr->hist); + png_free(png_ptr, png_ptr->hist); png_ptr->flags &= ~PNG_FLAG_FREE_HIST; #endif #endif #if defined(PNG_READ_GAMMA_SUPPORTED) if (png_ptr->gamma_16_table != NULL) { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_table[i]); - } + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } png_free(png_ptr, png_ptr->gamma_16_table); } #if defined(PNG_READ_BACKGROUND_SUPPORTED) if (png_ptr->gamma_16_from_1 != NULL) { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_from_1[i]); - } + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } png_free(png_ptr, png_ptr->gamma_16_from_1); } if (png_ptr->gamma_16_to_1 != NULL) { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_to_1[i]); - } + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } png_free(png_ptr, png_ptr->gamma_16_to_1); } #endif @@ -217553,9 +196627,6 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr #endif /* PNG_TEXT_SUPPORTED */ #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - /* Save the important info out of the png_struct, in case it is - * being used again. - */ #ifdef PNG_SETJMP_SUPPORTED png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); #endif @@ -217593,149 +196664,102 @@ png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) #if defined(PNG_INFO_IMAGE_SUPPORTED) void PNGAPI png_read_png(png_structp png_ptr, png_infop info_ptr, - int transforms, - voidp params) + int transforms, + voidp params) { int row; if(png_ptr == NULL) return; #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel from opacity to transparency - */ if (transforms & PNG_TRANSFORM_INVERT_ALPHA) - png_set_invert_alpha(png_ptr); + png_set_invert_alpha(png_ptr); #endif - /* png_read_info() gives us all of the information from the - * PNG file before the first IDAT (image data chunk). - */ png_read_info(png_ptr, info_ptr); if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) - png_error(png_ptr,"Image is too high to process with png_read_png()"); - - /* -------------- image transformations start here ------------------- */ + png_error(png_ptr,"Image is too high to process with png_read_png()"); #if defined(PNG_READ_16_TO_8_SUPPORTED) - /* tell libpng to strip 16 bit/color files down to 8 bits per color - */ if (transforms & PNG_TRANSFORM_STRIP_16) - png_set_strip_16(png_ptr); + png_set_strip_16(png_ptr); #endif #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) - /* Strip alpha bytes from the input data without combining with - * the background (not recommended). - */ if (transforms & PNG_TRANSFORM_STRIP_ALPHA) - png_set_strip_alpha(png_ptr); + png_set_strip_alpha(png_ptr); #endif #if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) - /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single - * byte into separate bytes (useful for paletted and grayscale images). - */ if (transforms & PNG_TRANSFORM_PACKING) - png_set_packing(png_ptr); + png_set_packing(png_ptr); #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) - /* Change the order of packed pixels to least significant bit first - * (not useful if you are using png_set_packing). - */ if (transforms & PNG_TRANSFORM_PACKSWAP) - png_set_packswap(png_ptr); + png_set_packswap(png_ptr); #endif #if defined(PNG_READ_EXPAND_SUPPORTED) - /* Expand paletted colors into true RGB triplets - * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel - * Expand paletted or RGB images with transparency to full alpha - * channels so the data will be available as RGBA quartets. - */ if (transforms & PNG_TRANSFORM_EXPAND) - if ((png_ptr->bit_depth < 8) || - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || - (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) - png_set_expand(png_ptr); + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); #endif - /* We don't handle background color or gamma transformation or dithering. - */ - #if defined(PNG_READ_INVERT_SUPPORTED) - /* invert monochrome files to have 0 as white and 1 as black - */ if (transforms & PNG_TRANSFORM_INVERT_MONO) - png_set_invert_mono(png_ptr); + png_set_invert_mono(png_ptr); #endif #if defined(PNG_READ_SHIFT_SUPPORTED) - /* If you want to shift the pixel values from the range [0,255] or - * [0,65535] to the original [0,7] or [0,31], or whatever range the - * colors were originally in: - */ if ((transforms & PNG_TRANSFORM_SHIFT) - && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) { - png_color_8p sig_bit; + png_color_8p sig_bit; - png_get_sBIT(png_ptr, info_ptr, &sig_bit); - png_set_shift(png_ptr, sig_bit); + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); } #endif #if defined(PNG_READ_BGR_SUPPORTED) - /* flip the RGB pixels to BGR (or RGBA to BGRA) - */ if (transforms & PNG_TRANSFORM_BGR) - png_set_bgr(png_ptr); + png_set_bgr(png_ptr); #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) - /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) - */ if (transforms & PNG_TRANSFORM_SWAP_ALPHA) - png_set_swap_alpha(png_ptr); + png_set_swap_alpha(png_ptr); #endif #if defined(PNG_READ_SWAP_SUPPORTED) - /* swap bytes of 16 bit files to least significant byte first - */ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) - png_set_swap(png_ptr); + png_set_swap(png_ptr); #endif - /* We don't handle adding filler bytes */ - - /* Optional call to gamma correct and add the background to the palette - * and update info structure. REQUIRED if you are expecting libpng to - * update the palette for you (i.e., you selected such a transform above). - */ png_read_update_info(png_ptr, info_ptr); - /* -------------- image transformations end here ------------------- */ - #ifdef PNG_FREE_ME_SUPPORTED png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); #endif if(info_ptr->row_pointers == NULL) { - info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, - info_ptr->height * png_sizeof(png_bytep)); + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * png_sizeof(png_bytep)); #ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_ROWS; + info_ptr->free_me |= PNG_FREE_ROWS; #endif - for (row = 0; row < (int)info_ptr->height; row++) - { - info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, - png_get_rowbytes(png_ptr, info_ptr)); - } + for (row = 0; row < (int)info_ptr->height; row++) + { + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } } png_read_image(png_ptr, info_ptr->row_pointers); info_ptr->valid |= PNG_INFO_IDAT; - /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); transforms = transforms; /* quiet compiler warnings */ @@ -217748,29 +196772,20 @@ png_read_png(png_structp png_ptr, png_infop info_ptr, /********* End of inlined file: pngread.c *********/ /********* Start of inlined file: pngpread.c *********/ -/* pngpread.c - read a png file in push mode - * - * Last changed in libpng 1.2.21 October 4, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ #define PNG_INTERNAL #ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* push model modes */ #define PNG_READ_SIG_MODE 0 #define PNG_READ_CHUNK_MODE 1 #define PNG_READ_IDAT_MODE 2 -#define PNG_SKIP_MODE 3 +#define PNG_SKIP_MODE 3 #define PNG_READ_tEXt_MODE 4 #define PNG_READ_zTXt_MODE 5 #define PNG_READ_DONE_MODE 6 #define PNG_READ_iTXt_MODE 7 -#define PNG_ERROR_MODE 8 +#define PNG_ERROR_MODE 8 void PNGAPI png_process_data(png_structp png_ptr, png_infop info_ptr, @@ -217781,103 +196796,94 @@ png_process_data(png_structp png_ptr, png_infop info_ptr, while (png_ptr->buffer_size) { - png_process_some_data(png_ptr, info_ptr); + png_process_some_data(png_ptr, info_ptr); } } -/* What we do with the incoming data depends on what we were previously - * doing before we ran out of data... - */ void /* PRIVATE */ png_process_some_data(png_structp png_ptr, png_infop info_ptr) { if(png_ptr == NULL) return; switch (png_ptr->process_mode) { - case PNG_READ_SIG_MODE: - { - png_push_read_sig(png_ptr, info_ptr); - break; - } - case PNG_READ_CHUNK_MODE: - { - png_push_read_chunk(png_ptr, info_ptr); - break; - } - case PNG_READ_IDAT_MODE: - { - png_push_read_IDAT(png_ptr); - break; - } + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } #if defined(PNG_READ_tEXt_SUPPORTED) - case PNG_READ_tEXt_MODE: - { - png_push_read_tEXt(png_ptr, info_ptr); - break; - } + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } #endif #if defined(PNG_READ_zTXt_SUPPORTED) - case PNG_READ_zTXt_MODE: - { - png_push_read_zTXt(png_ptr, info_ptr); - break; - } + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } #endif #if defined(PNG_READ_iTXt_SUPPORTED) - case PNG_READ_iTXt_MODE: - { - png_push_read_iTXt(png_ptr, info_ptr); - break; - } + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } #endif - case PNG_SKIP_MODE: - { - png_push_crc_finish(png_ptr); - break; - } - default: - { - png_ptr->buffer_size = 0; - break; - } + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + default: + { + png_ptr->buffer_size = 0; + break; + } } } -/* Read any remaining signature bytes from the stream and compare them with - * the correct PNG signature. It is possible that this routine is called - * with bytes already read from the signature, either because they have been - * checked by the calling application, or because of multiple calls to this - * routine. - */ void /* PRIVATE */ png_push_read_sig(png_structp png_ptr, png_infop info_ptr) { png_size_t num_checked = png_ptr->sig_bytes, - num_to_check = 8 - num_checked; + num_to_check = 8 - num_checked; if (png_ptr->buffer_size < num_to_check) { - num_to_check = png_ptr->buffer_size; + num_to_check = png_ptr->buffer_size; } png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), - num_to_check); + num_to_check); png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check); if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); } else { - if (png_ptr->sig_bytes >= 8) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } } } @@ -217885,367 +196891,357 @@ void /* PRIVATE */ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) { #ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IHDR; - PNG_CONST PNG_IDAT; - PNG_CONST PNG_IEND; - PNG_CONST PNG_PLTE; + PNG_CONST PNG_IHDR; + PNG_CONST PNG_IDAT; + PNG_CONST PNG_IEND; + PNG_CONST PNG_PLTE; #if defined(PNG_READ_bKGD_SUPPORTED) - PNG_CONST PNG_bKGD; + PNG_CONST PNG_bKGD; #endif #if defined(PNG_READ_cHRM_SUPPORTED) - PNG_CONST PNG_cHRM; + PNG_CONST PNG_cHRM; #endif #if defined(PNG_READ_gAMA_SUPPORTED) - PNG_CONST PNG_gAMA; + PNG_CONST PNG_gAMA; #endif #if defined(PNG_READ_hIST_SUPPORTED) - PNG_CONST PNG_hIST; + PNG_CONST PNG_hIST; #endif #if defined(PNG_READ_iCCP_SUPPORTED) - PNG_CONST PNG_iCCP; + PNG_CONST PNG_iCCP; #endif #if defined(PNG_READ_iTXt_SUPPORTED) - PNG_CONST PNG_iTXt; + PNG_CONST PNG_iTXt; #endif #if defined(PNG_READ_oFFs_SUPPORTED) - PNG_CONST PNG_oFFs; + PNG_CONST PNG_oFFs; #endif #if defined(PNG_READ_pCAL_SUPPORTED) - PNG_CONST PNG_pCAL; + PNG_CONST PNG_pCAL; #endif #if defined(PNG_READ_pHYs_SUPPORTED) - PNG_CONST PNG_pHYs; + PNG_CONST PNG_pHYs; #endif #if defined(PNG_READ_sBIT_SUPPORTED) - PNG_CONST PNG_sBIT; + PNG_CONST PNG_sBIT; #endif #if defined(PNG_READ_sCAL_SUPPORTED) - PNG_CONST PNG_sCAL; + PNG_CONST PNG_sCAL; #endif #if defined(PNG_READ_sRGB_SUPPORTED) - PNG_CONST PNG_sRGB; + PNG_CONST PNG_sRGB; #endif #if defined(PNG_READ_sPLT_SUPPORTED) - PNG_CONST PNG_sPLT; + PNG_CONST PNG_sPLT; #endif #if defined(PNG_READ_tEXt_SUPPORTED) - PNG_CONST PNG_tEXt; + PNG_CONST PNG_tEXt; #endif #if defined(PNG_READ_tIME_SUPPORTED) - PNG_CONST PNG_tIME; + PNG_CONST PNG_tIME; #endif #if defined(PNG_READ_tRNS_SUPPORTED) - PNG_CONST PNG_tRNS; + PNG_CONST PNG_tRNS; #endif #if defined(PNG_READ_zTXt_SUPPORTED) - PNG_CONST PNG_zTXt; + PNG_CONST PNG_zTXt; #endif #endif /* PNG_USE_LOCAL_ARRAYS */ - /* First we make sure we have enough data for the 4 byte chunk name - * and the 4 byte chunk length before proceeding with decoding the - * chunk data. To fully decode each of these chunks, we also make - * sure we have enough data in the buffer for the 4 byte CRC at the - * end of every chunk (except IDAT, which is handled separately). - */ if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) { - png_byte chunk_length[4]; + png_byte chunk_length[4]; - if (png_ptr->buffer_size < 8) - { - png_push_save_buffer(png_ptr); - return; - } + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; } if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - if(png_ptr->mode & PNG_AFTER_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + if(png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); } else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); - png_ptr->process_mode = PNG_READ_DONE_MODE; - png_push_have_end(png_ptr, info_ptr); + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); } #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_ptr->mode |= PNG_HAVE_IDAT; - png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); - if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_ptr->mode |= PNG_HAVE_PLTE; - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - } + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + } } #endif else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); } else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) { - /* If we reach an IDAT chunk, this means we have read all of the - * header chunks, and we can start reading the image (or if this - * is called after the image has been read - we have an error). - */ - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); - if (png_ptr->mode & PNG_HAVE_IDAT) - { - if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - if (png_ptr->push_length == 0) - return; + if (png_ptr->mode & PNG_HAVE_IDAT) + { + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; - if (png_ptr->mode & PNG_AFTER_IDAT) - png_error(png_ptr, "Too many IDAT's found"); - } + if (png_ptr->mode & PNG_AFTER_IDAT) + png_error(png_ptr, "Too many IDAT's found"); + } - png_ptr->idat_size = png_ptr->push_length; - png_ptr->mode |= PNG_HAVE_IDAT; - png_ptr->process_mode = PNG_READ_IDAT_MODE; - png_push_have_info(png_ptr, info_ptr); - png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; - png_ptr->zstream.next_out = png_ptr->row_buf; - return; + png_ptr->idat_size = png_ptr->push_length; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; } #if defined(PNG_READ_gAMA_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_sBIT_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_cHRM_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_sRGB_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_iCCP_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_sPLT_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_tRNS_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_bKGD_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_hIST_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_pHYs_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_oFFs_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_pCAL_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_sCAL_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_tIME_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_tEXt_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_zTXt_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); } #endif #if defined(PNG_READ_iTXt_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); } #endif else { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); } png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; @@ -218263,46 +197259,46 @@ png_push_crc_finish(png_structp png_ptr) { if (png_ptr->skip_length && png_ptr->save_buffer_size) { - png_size_t save_size; + png_size_t save_size; - if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) - save_size = (png_size_t)png_ptr->skip_length; - else - save_size = png_ptr->save_buffer_size; + if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->save_buffer_size; - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - png_ptr->skip_length -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; } if (png_ptr->skip_length && png_ptr->current_buffer_size) { - png_size_t save_size; + png_size_t save_size; - if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) - save_size = (png_size_t)png_ptr->skip_length; - else - save_size = png_ptr->current_buffer_size; + if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->current_buffer_size; - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - png_ptr->skip_length -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; } if (!png_ptr->skip_length) { - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } - png_crc_finish(png_ptr, 0); - png_ptr->process_mode = PNG_READ_CHUNK_MODE; + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; } } @@ -218315,33 +197311,33 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) ptr = buffer; if (png_ptr->save_buffer_size) { - png_size_t save_size; + png_size_t save_size; - if (length < png_ptr->save_buffer_size) - save_size = length; - else - save_size = png_ptr->save_buffer_size; + if (length < png_ptr->save_buffer_size) + save_size = length; + else + save_size = png_ptr->save_buffer_size; - png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); - length -= save_size; - ptr += save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; + png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; } if (length && png_ptr->current_buffer_size) { - png_size_t save_size; + png_size_t save_size; - if (length < png_ptr->current_buffer_size) - save_size = length; - else - save_size = png_ptr->current_buffer_size; + if (length < png_ptr->current_buffer_size) + save_size = length; + else + save_size = png_ptr->current_buffer_size; - png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; + png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; } } @@ -218350,45 +197346,45 @@ png_push_save_buffer(png_structp png_ptr) { if (png_ptr->save_buffer_size) { - if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) - { - png_size_t i,istop; - png_bytep sp; - png_bytep dp; + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i,istop; + png_bytep sp; + png_bytep dp; - istop = png_ptr->save_buffer_size; - for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; - i < istop; i++, sp++, dp++) - { - *dp = *sp; - } - } + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } } if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > - png_ptr->save_buffer_max) + png_ptr->save_buffer_max) { - png_size_t new_max; - png_bytep old_buffer; + png_size_t new_max; + png_bytep old_buffer; - if (png_ptr->save_buffer_size > PNG_SIZE_MAX - - (png_ptr->current_buffer_size + 256)) - { - png_error(png_ptr, "Potential overflow of save_buffer"); - } - new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; - old_buffer = png_ptr->save_buffer; - png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, - (png_uint_32)new_max); - png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); - png_free(png_ptr, old_buffer); - png_ptr->save_buffer_max = new_max; + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, + (png_uint_32)new_max); + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; } if (png_ptr->current_buffer_size) { - png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, - png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); - png_ptr->save_buffer_size += png_ptr->current_buffer_size; - png_ptr->current_buffer_size = 0; + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; } png_ptr->save_buffer_ptr = png_ptr->save_buffer; png_ptr->buffer_size = 0; @@ -218412,86 +197408,84 @@ png_push_read_IDAT(png_structp png_ptr) #endif if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) { - png_byte chunk_length[4]; + png_byte chunk_length[4]; - if (png_ptr->buffer_size < 8) - { - png_push_save_buffer(png_ptr); - return; - } + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_error(png_ptr, "Not enough compressed data"); - return; - } + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_error(png_ptr, "Not enough compressed data"); + return; + } - png_ptr->idat_size = png_ptr->push_length; + png_ptr->idat_size = png_ptr->push_length; } if (png_ptr->idat_size && png_ptr->save_buffer_size) { - png_size_t save_size; + png_size_t save_size; - if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) - { - save_size = (png_size_t)png_ptr->idat_size; - /* check for overflow */ - if((png_uint_32)save_size != png_ptr->idat_size) - png_error(png_ptr, "save_size overflowed in pngpread"); - } - else - save_size = png_ptr->save_buffer_size; + if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + if((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->save_buffer_size; - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); - png_ptr->idat_size -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; } if (png_ptr->idat_size && png_ptr->current_buffer_size) { - png_size_t save_size; + png_size_t save_size; - if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) - { - save_size = (png_size_t)png_ptr->idat_size; - /* check for overflow */ - if((png_uint_32)save_size != png_ptr->idat_size) - png_error(png_ptr, "save_size overflowed in pngpread"); - } - else - save_size = png_ptr->current_buffer_size; + if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + if((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->current_buffer_size; - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); - png_ptr->idat_size -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; } if (!png_ptr->idat_size) { - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } - png_crc_finish(png_ptr, 0); - png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; - png_ptr->mode |= PNG_AFTER_IDAT; + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; } } @@ -218502,56 +197496,56 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, int ret; if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length) - png_error(png_ptr, "Extra compression data"); + png_error(png_ptr, "Extra compression data"); png_ptr->zstream.next_in = buffer; png_ptr->zstream.avail_in = (uInt)buffer_length; for(;;) { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK) - { - if (ret == Z_STREAM_END) - { - if (png_ptr->zstream.avail_in) - png_error(png_ptr, "Extra compressed data"); - if (!(png_ptr->zstream.avail_out)) - { - png_push_process_row(png_ptr); - } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK) + { + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_in) + png_error(png_ptr, "Extra compressed data"); + if (!(png_ptr->zstream.avail_out)) + { + png_push_process_row(png_ptr); + } - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - else if (ret == Z_BUF_ERROR) - break; - else - png_error(png_ptr, "Decompression Error"); - } - if (!(png_ptr->zstream.avail_out)) - { - if (( + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + else if (ret == Z_BUF_ERROR) + break; + else + png_error(png_ptr, "Decompression Error"); + } + if (!(png_ptr->zstream.avail_out)) + { + if (( #if defined(PNG_READ_INTERLACING_SUPPORTED) - png_ptr->interlaced && png_ptr->pass > 6) || - (!png_ptr->interlaced && + png_ptr->interlaced && png_ptr->pass > 6) || + (!png_ptr->interlaced && #endif - png_ptr->row_number == png_ptr->num_rows)) - { - if (png_ptr->zstream.avail_in) - { - png_warning(png_ptr, "Too much data in IDAT chunks"); - } + png_ptr->row_number == png_ptr->num_rows)) + { + if (png_ptr->zstream.avail_in) + { + png_warning(png_ptr, "Too much data in IDAT chunks"); + } - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - png_push_process_row(png_ptr); - png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; - png_ptr->zstream.next_out = png_ptr->row_buf; - } - else - break; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + png_push_process_row(png_ptr); + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + png_ptr->zstream.next_out = png_ptr->row_buf; + } + else + break; } } @@ -218565,172 +197559,167 @@ png_push_process_row(png_structp png_ptr) png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); + png_ptr->row_info.width); png_read_filter_row(png_ptr, &(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->prev_row + 1, - (int)(png_ptr->row_buf[0])); + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, - png_ptr->rowbytes + 1); + png_ptr->rowbytes + 1); if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) - png_do_read_transformations(png_ptr); + png_do_read_transformations(png_ptr); #if defined(PNG_READ_INTERLACING_SUPPORTED) - /* blow up interlaced rows to full size */ if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) { - if (png_ptr->pass < 6) -/* old interface (pre-1.0.9): - png_do_read_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); - */ - png_do_read_interlace(png_ptr); + if (png_ptr->pass < 6) + png_do_read_interlace(png_ptr); - switch (png_ptr->pass) - { - case 0: - { - int i; - for (i = 0; i < 8 && png_ptr->pass == 0; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */ - } - if (png_ptr->pass == 2) /* pass 1 might be empty */ - { - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - if (png_ptr->pass == 4 && png_ptr->height <= 4) - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - if (png_ptr->pass == 6 && png_ptr->height <= 4) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 1: - { - int i; - for (i = 0; i < 8 && png_ptr->pass == 1; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 2) /* skip top 4 generated rows */ - { - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 2: - { - int i; - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 4) /* pass 3 might be empty */ - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 3: - { - int i; - for (i = 0; i < 4 && png_ptr->pass == 3; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 4) /* skip top two generated rows */ - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 4: - { - int i; - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 6) /* pass 5 might be empty */ - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 5: - { - int i; - for (i = 0; i < 2 && png_ptr->pass == 5; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 6) /* skip top generated row */ - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 6: - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - if (png_ptr->pass != 6) - break; - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */ + } + if (png_ptr->pass == 2) /* pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 2) /* skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 2: + { + int i; + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 4) /* pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 3: + { + int i; + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 4) /* skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 4: + { + int i; + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 6) /* pass 5 might be empty */ + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 5: + { + int i; + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 6) /* skip top generated row */ + { + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + if (png_ptr->pass != 6) + break; + png_push_have_row(png_ptr, png_bytep_NULL); + png_read_push_finish_row(png_ptr); + } + } } else #endif { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); } } @@ -218738,65 +197727,56 @@ void /* PRIVATE */ png_read_push_finish_row(png_structp png_ptr) { #ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* start of interlace block */ PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; - /* offset to next interlace block */ PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; - /* start of interlace block in the y direction */ PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; - /* offset to next interlace block in the y direction */ PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; - /* Height of interlace block. This is not currently used - if you need - * it, uncomment it here and in png.h - PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; - */ #endif png_ptr->row_number++; if (png_ptr->row_number < png_ptr->num_rows) - return; + return; if (png_ptr->interlaced) { - png_ptr->row_number = 0; - png_memset_check(png_ptr, png_ptr->prev_row, 0, - png_ptr->rowbytes + 1); - do - { - png_ptr->pass++; - if ((png_ptr->pass == 1 && png_ptr->width < 5) || - (png_ptr->pass == 3 && png_ptr->width < 3) || - (png_ptr->pass == 5 && png_ptr->width < 2)) - png_ptr->pass++; + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; - if (png_ptr->pass > 7) - png_ptr->pass--; - if (png_ptr->pass >= 7) - break; + if (png_ptr->pass > 7) + png_ptr->pass--; + if (png_ptr->pass >= 7) + break; - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; - png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, - png_ptr->iwidth) + 1; + png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; - if (png_ptr->transformations & PNG_INTERLACE) - break; + if (png_ptr->transformations & PNG_INTERLACE) + break; - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; - } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); } } @@ -218806,24 +197786,24 @@ png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place tEXt"); - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } + { + png_error(png_ptr, "Out of place tEXt"); + info_ptr = info_ptr; /* to quiet some compiler warnings */ + } #ifdef PNG_MAX_MALLOC_64K png_ptr->skip_length = 0; /* This may not be necessary */ if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ { - png_warning(png_ptr, "tEXt chunk too large to fit in memory"); - png_ptr->skip_length = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; } #endif png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); + (png_uint_32)(length+1)); png_ptr->current_text[length] = '\0'; png_ptr->current_text_ptr = png_ptr->current_text; png_ptr->current_text_size = (png_size_t)length; @@ -218836,62 +197816,62 @@ png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) { if (png_ptr->buffer_size && png_ptr->current_text_left) { - png_size_t text_size; + png_size_t text_size; - if (png_ptr->buffer_size < png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; } if (!(png_ptr->current_text_left)) { - png_textp text_ptr; - png_charp text; - png_charp key; - int ret; + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } - png_push_crc_finish(png_ptr); + png_push_crc_finish(png_ptr); #if defined(PNG_MAX_MALLOC_64K) - if (png_ptr->skip_length) - return; + if (png_ptr->skip_length) + return; #endif - key = png_ptr->current_text; + key = png_ptr->current_text; - for (text = key; *text; text++) - /* empty loop */ ; + for (text = key; *text; text++) + ; - if (text < key + png_ptr->current_text_size) - text++; + if (text < key + png_ptr->current_text_size) + text++; - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr->key = key; + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; #ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; #endif - text_ptr->text = text; + text_ptr->text = text; - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + png_ptr->current_text = NULL; - if (ret) - png_warning(png_ptr, "Insufficient memory to store text chunk."); + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk."); } } #endif @@ -218902,26 +197882,22 @@ png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place zTXt"); - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } + { + png_error(png_ptr, "Out of place zTXt"); + info_ptr = info_ptr; /* to quiet some compiler warnings */ + } #ifdef PNG_MAX_MALLOC_64K - /* We can't handle zTXt chunks > 64K, since we don't have enough space - * to be able to store the uncompressed data. Actually, the threshold - * is probably around 32K, but it isn't as definite as 64K is. - */ if (length > (png_uint_32)65535L) { - png_warning(png_ptr, "zTXt chunk too large to fit in memory"); - png_push_crc_skip(png_ptr, length); - return; + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; } #endif png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); + (png_uint_32)(length+1)); png_ptr->current_text[length] = '\0'; png_ptr->current_text_ptr = png_ptr->current_text; png_ptr->current_text_size = (png_size_t)length; @@ -218934,156 +197910,155 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) { if (png_ptr->buffer_size && png_ptr->current_text_left) { - png_size_t text_size; + png_size_t text_size; - if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; } if (!(png_ptr->current_text_left)) { - png_textp text_ptr; - png_charp text; - png_charp key; - int ret; - png_size_t text_size, key_size; + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } - png_push_crc_finish(png_ptr); + png_push_crc_finish(png_ptr); - key = png_ptr->current_text; + key = png_ptr->current_text; - for (text = key; *text; text++) - /* empty loop */ ; + for (text = key; *text; text++) + ; - /* zTXt can't have zero text */ - if (text >= key + png_ptr->current_text_size) - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - return; - } + if (text >= key + png_ptr->current_text_size) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } - text++; + text++; - if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */ - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - return; - } + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */ + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } - text++; + text++; - png_ptr->zstream.next_in = (png_bytep )text; - png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - - (text - key)); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = (png_bytep )text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - key_size = text - key; - text_size = 0; - text = NULL; - ret = Z_STREAM_END; + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; - while (png_ptr->zstream.avail_in) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - png_ptr->current_text = NULL; - png_free(png_ptr, key); - png_free(png_ptr, text); - return; - } - if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) - { - if (text == NULL) - { - text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out - + key_size + 1)); - png_memcpy(text + key_size, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - png_memcpy(text, key, key_size); - text_size = key_size + png_ptr->zbuf_size - - png_ptr->zstream.avail_out; - *(text + text_size) = '\0'; - } - else - { - png_charp tmp; + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + + key_size + 1)); + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_memcpy(text, key, key_size); + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + else + { + png_charp tmp; - tmp = text; - text = (png_charp)png_malloc(png_ptr, text_size + - (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out - + 1)); - png_memcpy(text, tmp, text_size); - png_free(png_ptr, tmp); - png_memcpy(text + text_size, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; - *(text + text_size) = '\0'; - } - if (ret != Z_STREAM_END) - { - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - else - { - break; - } + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + + 1)); + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } - if (ret == Z_STREAM_END) - break; - } + if (ret == Z_STREAM_END) + break; + } - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; - if (ret != Z_STREAM_END) - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - png_free(png_ptr, text); - return; - } + if (ret != Z_STREAM_END) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } - png_ptr->current_text = NULL; - png_free(png_ptr, key); - key = text; - text += key_size; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + key = text; + text += key_size; - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; - text_ptr->key = key; + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; #ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; #endif - text_ptr->text = text; + text_ptr->text = text; - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); - if (ret) - png_warning(png_ptr, "Insufficient memory to store text chunk."); + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk."); } } #endif @@ -219094,24 +198069,24 @@ png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place iTXt"); - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } + { + png_error(png_ptr, "Out of place iTXt"); + info_ptr = info_ptr; /* to quiet some compiler warnings */ + } #ifdef PNG_MAX_MALLOC_64K png_ptr->skip_length = 0; /* This may not be necessary */ if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ { - png_warning(png_ptr, "iTXt chunk too large to fit in memory"); - png_ptr->skip_length = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; } #endif png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); + (png_uint_32)(length+1)); png_ptr->current_text[length] = '\0'; png_ptr->current_text_ptr = png_ptr->current_text; png_ptr->current_text_size = (png_size_t)length; @@ -219125,89 +198100,85 @@ png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) if (png_ptr->buffer_size && png_ptr->current_text_left) { - png_size_t text_size; + png_size_t text_size; - if (png_ptr->buffer_size < png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; } if (!(png_ptr->current_text_left)) { - png_textp text_ptr; - png_charp key; - int comp_flag; - png_charp lang; - png_charp lang_key; - png_charp text; - int ret; + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + int ret; - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } - png_push_crc_finish(png_ptr); + png_push_crc_finish(png_ptr); #if defined(PNG_MAX_MALLOC_64K) - if (png_ptr->skip_length) - return; + if (png_ptr->skip_length) + return; #endif - key = png_ptr->current_text; + key = png_ptr->current_text; - for (lang = key; *lang; lang++) - /* empty loop */ ; + for (lang = key; *lang; lang++) + ; - if (lang < key + png_ptr->current_text_size - 3) - lang++; + if (lang < key + png_ptr->current_text_size - 3) + lang++; - comp_flag = *lang++; - lang++; /* skip comp_type, always zero */ + comp_flag = *lang++; + lang++; /* skip comp_type, always zero */ - for (lang_key = lang; *lang_key; lang_key++) - /* empty loop */ ; - lang_key++; /* skip NUL separator */ + for (lang_key = lang; *lang_key; lang_key++) + ; + lang_key++; /* skip NUL separator */ - text=lang_key; - if (lang_key < key + png_ptr->current_text_size - 1) - { - for (; *text; text++) - /* empty loop */ ; - } + text=lang_key; + if (lang_key < key + png_ptr->current_text_size - 1) + { + for (; *text; text++) + ; + } - if (text < key + png_ptr->current_text_size) - text++; + if (text < key + png_ptr->current_text_size) + text++; - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = comp_flag + 2; - text_ptr->key = key; - text_ptr->lang = lang; - text_ptr->lang_key = lang_key; - text_ptr->text = text; - text_ptr->text_length = 0; - text_ptr->itxt_length = png_strlen(text); + text_ptr = (png_textp)png_malloc(png_ptr, + (png_uint_32)png_sizeof(png_text)); + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - png_ptr->current_text = NULL; + png_ptr->current_text = NULL; - png_free(png_ptr, text_ptr); - if (ret) - png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); } } #endif -/* This function is called when we haven't found a handler for this - * chunk. If there isn't a problem with the chunk itself (ie a bad chunk - * name or a critical chunk), the chunk is (currently) silently ignored. - */ void /* PRIVATE */ png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) @@ -219218,62 +198189,61 @@ png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 if (!(png_ptr->chunk_name[0] & 0x20)) { #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - && png_ptr->read_user_chunk_fn == NULL + && png_ptr->read_user_chunk_fn == NULL #endif - ) + ) #endif - png_chunk_error(png_ptr, "unknown critical chunk"); + png_chunk_error(png_ptr, "unknown critical chunk"); - info_ptr = info_ptr; /* to quiet some compiler warnings */ + info_ptr = info_ptr; /* to quiet some compiler warnings */ } #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) { #ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } #endif - png_strncpy((png_charp)png_ptr->unknown_chunk.name, + png_strncpy((png_charp)png_ptr->unknown_chunk.name, (png_charp)png_ptr->chunk_name, 5); - png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); - png_ptr->unknown_chunk.size = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_ptr->unknown_chunk.size = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - if(png_ptr->read_user_chunk_fn != NULL) - { - /* callback to user unknown chunk handler */ - int ret; - ret = (*(png_ptr->read_user_chunk_fn)) - (png_ptr, &png_ptr->unknown_chunk); - if (ret < 0) - png_chunk_error(png_ptr, "error in user chunk"); - if (ret == 0) - { - if (!(png_ptr->chunk_name[0] & 0x20)) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS) - png_chunk_error(png_ptr, "unknown critical chunk"); - png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); - } - } + if(png_ptr->read_user_chunk_fn != NULL) + { + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } #else - png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); #endif - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; } else #endif - skip=length; + skip=length; png_push_crc_skip(png_ptr, skip); } @@ -219281,22 +198251,22 @@ void /* PRIVATE */ png_push_have_info(png_structp png_ptr, png_infop info_ptr) { if (png_ptr->info_fn != NULL) - (*(png_ptr->info_fn))(png_ptr, info_ptr); + (*(png_ptr->info_fn))(png_ptr, info_ptr); } void /* PRIVATE */ png_push_have_end(png_structp png_ptr, png_infop info_ptr) { if (png_ptr->end_fn != NULL) - (*(png_ptr->end_fn))(png_ptr, info_ptr); + (*(png_ptr->end_fn))(png_ptr, info_ptr); } void /* PRIVATE */ png_push_have_row(png_structp png_ptr, png_bytep row) { if (png_ptr->row_fn != NULL) - (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, - (int)png_ptr->pass); + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); } void PNGAPI @@ -219305,11 +198275,11 @@ png_progressive_combine_row (png_structp png_ptr, { #ifdef PNG_USE_LOCAL_ARRAYS PNG_CONST int FARDATA png_pass_dsp_mask[7] = - {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; #endif if(png_ptr == NULL) return; - if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ - png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); + if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ + png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); } void PNGAPI @@ -219335,46 +198305,22 @@ png_get_progressive_ptr(png_structp png_ptr) /********* End of inlined file: pngpread.c *********/ /********* Start of inlined file: pngrio.c *********/ -/* pngrio.c - functions for data input - * - * Last changed in libpng 1.2.13 November 13, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all input. Users who need - * special handling are expected to write a function that has the same - * arguments as this and performs a similar function, but that possibly - * has a different input method. Note that you shouldn't change this - * function, but rather write a replacement function and then make - * libpng use it at run time with png_set_read_fn(...). - */ #define PNG_INTERNAL #if defined(PNG_READ_SUPPORTED) -/* Read the data from whatever input you are using. The default routine - reads from a file pointer. Note that this routine sometimes gets called - with very small lengths, so you should implement some kind of simple - buffering if you are using unbuffered reads. This should never be asked - to read more then 64K on a 16 bit machine. */ void /* PRIVATE */ png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { png_debug1(4,"reading %d bytes\n", (int)length); if (png_ptr->read_data_fn != NULL) - (*(png_ptr->read_data_fn))(png_ptr, data, length); + (*(png_ptr->read_data_fn))(png_ptr, data, length); else - png_error(png_ptr, "Call to NULL read function"); + png_error(png_ptr, "Call to NULL read function"); } #if !defined(PNG_NO_STDIO) -/* This is the function that does the actual reading of data. If you are - not reading from a standard C stream, you should create a replacement - read_data function and use it at run time with png_set_read_fn(), rather - than changing the library. */ #ifndef USE_FAR_KEYWORD void PNGAPI png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) @@ -219382,25 +198328,18 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) png_size_t check; if(png_ptr == NULL) return; - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ #if defined(_WIN32_WCE) if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; + check = 0; #else check = (png_size_t)fread(data, (png_size_t)1, length, - (png_FILE_p)png_ptr->io_ptr); + (png_FILE_p)png_ptr->io_ptr); #endif if (check != length) - png_error(png_ptr, "Read Error"); + png_error(png_ptr, "Read Error"); } #else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ #define NEAR_BUF_SIZE 1024 #define MIN(a,b) (a <= b ? a : b) @@ -219413,62 +198352,48 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) png_FILE_p io_ptr; if(png_ptr == NULL) return; - /* Check if data really is near. If so, use usual code. */ n_data = (png_byte *)CVT_PTR_NOCHECK(data); io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); if ((png_bytep)n_data == data) { #if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; #else - check = fread(n_data, 1, length, io_ptr); + check = fread(n_data, 1, length, io_ptr); #endif } else { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t read, remaining, err; - check = 0; - remaining = length; - do - { - read = MIN(NEAR_BUF_SIZE, remaining); + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); #if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) - err = 0; + if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) + err = 0; #else - err = fread(buf, (png_size_t)1, read, io_ptr); + err = fread(buf, (png_size_t)1, read, io_ptr); #endif - png_memcpy(data, buf, read); /* copy far buffer to near buffer */ - if(err != read) - break; - else - check += err; - data += read; - remaining -= read; - } - while (remaining != 0); + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + if(err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); } if ((png_uint_32)check != (png_uint_32)length) - png_error(png_ptr, "read Error"); + png_error(png_ptr, "read Error"); } #endif #endif -/* This function allows the application to supply a new input function - for libpng if standard C streams aren't being used. - - This function takes as its arguments: - png_ptr - pointer to a png input data structure - io_ptr - pointer to user supplied structure containing info about - the input functions. May be NULL. - read_data_fn - pointer to a new input function that takes as its - arguments a pointer to a png_struct, a pointer to - a location where input data can be stored, and a 32-bit - unsigned int that is the number of bytes to be read. - To exit and output any fatal error messages the new write - function should call png_error(png_ptr, "Error msg"). */ void PNGAPI png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, png_rw_ptr read_data_fn) @@ -219478,21 +198403,20 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, #if !defined(PNG_NO_STDIO) if (read_data_fn != NULL) - png_ptr->read_data_fn = read_data_fn; + png_ptr->read_data_fn = read_data_fn; else - png_ptr->read_data_fn = png_default_read_data; + png_ptr->read_data_fn = png_default_read_data; #else png_ptr->read_data_fn = read_data_fn; #endif - /* It is an error to write to a read device */ if (png_ptr->write_data_fn != NULL) { - png_ptr->write_data_fn = NULL; - png_warning(png_ptr, - "It's an error to set both read_data_fn and write_data_fn in the "); - png_warning(png_ptr, - "same structure. Resetting write_data_fn to NULL."); + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "It's an error to set both read_data_fn and write_data_fn in the "); + png_warning(png_ptr, + "same structure. Resetting write_data_fn to NULL."); } #if defined(PNG_WRITE_FLUSH_SUPPORTED) @@ -219503,81 +198427,65 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, /********* End of inlined file: pngrio.c *********/ /********* Start of inlined file: pngrtran.c *********/ -/* pngrtran.c - transforms the data in a row for PNG readers - * - * Last changed in libpng 1.2.21 [October 4, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file contains functions optionally called by an application - * in order to tell libpng how to handle data when reading a PNG. - * Transformations that are used in both reading and writing are - * in pngtrans.c. - */ #define PNG_INTERNAL #if defined(PNG_READ_SUPPORTED) -/* Set the action on getting a CRC error for an ancillary or critical chunk. */ void PNGAPI png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) { png_debug(1, "in png_set_crc_action\n"); - /* Tell libpng how we react to CRC errors in critical chunks */ if(png_ptr == NULL) return; switch (crit_action) { - case PNG_CRC_NO_CHANGE: /* leave setting as is */ - break; - case PNG_CRC_WARN_USE: /* warn/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; - break; - case PNG_CRC_QUIET_USE: /* quiet/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | - PNG_FLAG_CRC_CRITICAL_IGNORE; - break; - case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */ - png_warning(png_ptr, "Can't discard critical data on CRC error."); - case PNG_CRC_ERROR_QUIT: /* error/quit */ - case PNG_CRC_DEFAULT: - default: - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - break; + case PNG_CRC_NO_CHANGE: /* leave setting as is */ + break; + case PNG_CRC_WARN_USE: /* warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + case PNG_CRC_QUIET_USE: /* quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */ + png_warning(png_ptr, "Can't discard critical data on CRC error."); + case PNG_CRC_ERROR_QUIT: /* error/quit */ + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; } switch (ancil_action) { - case PNG_CRC_NO_CHANGE: /* leave setting as is */ - break; - case PNG_CRC_WARN_USE: /* warn/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; - break; - case PNG_CRC_QUIET_USE: /* quiet/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | - PNG_FLAG_CRC_ANCILLARY_NOWARN; - break; - case PNG_CRC_ERROR_QUIT: /* error/quit */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; - break; - case PNG_CRC_WARN_DISCARD: /* warn/discard data */ - case PNG_CRC_DEFAULT: - default: - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - break; + case PNG_CRC_NO_CHANGE: /* leave setting as is */ + break; + case PNG_CRC_WARN_USE: /* warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + case PNG_CRC_QUIET_USE: /* quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + case PNG_CRC_ERROR_QUIT: /* error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + case PNG_CRC_WARN_DISCARD: /* warn/discard data */ + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; } } #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - defined(PNG_FLOATING_POINT_SUPPORTED) -/* handle alpha and tRNS via a background color */ + defined(PNG_FLOATING_POINT_SUPPORTED) void PNGAPI png_set_background(png_structp png_ptr, png_color_16p background_color, int background_gamma_code, @@ -219587,13 +198495,13 @@ png_set_background(png_structp png_ptr, if(png_ptr == NULL) return; if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) { - png_warning(png_ptr, "Application must supply a known background gamma"); - return; + png_warning(png_ptr, "Application must supply a known background gamma"); + return; } png_ptr->transformations |= PNG_BACKGROUND; png_memcpy(&(png_ptr->background), background_color, - png_sizeof(png_color_16)); + png_sizeof(png_color_16)); png_ptr->background_gamma = (float)background_gamma; png_ptr->background_gamma_type = (png_byte)(background_gamma_code); png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); @@ -219601,7 +198509,6 @@ png_set_background(png_structp png_ptr, #endif #if defined(PNG_READ_16_TO_8_SUPPORTED) -/* strip 16 bit depth files to 8 bit depth */ void PNGAPI png_set_strip_16(png_structp png_ptr) { @@ -219622,14 +198529,6 @@ png_set_strip_alpha(png_structp png_ptr) #endif #if defined(PNG_READ_DITHER_SUPPORTED) -/* Dither file to 8 bit. Supply a palette, the current number - * of elements in the palette, the maximum number of elements - * allowed, and a histogram if possible. If the current number - * of colors is greater then the maximum number, the palette will be - * modified to fit in the maximum number. "full_dither" indicates - * whether we need a dithering cube set up for RGB images, or if we - * simply are reducing the number of colors in a paletted image. - */ typedef struct png_dsort_struct { @@ -219637,7 +198536,7 @@ typedef struct png_dsort_struct png_byte left; png_byte right; } png_dsort; -typedef png_dsort FAR * png_dsortp; +typedef png_dsort FAR * png_dsortp; typedef png_dsort FAR * FAR * png_dsortpp; void PNGAPI @@ -219651,400 +198550,345 @@ png_set_dither(png_structp png_ptr, png_colorp palette, if (!full_dither) { - int i; + int i; - png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); - for (i = 0; i < num_palette; i++) - png_ptr->dither_index[i] = (png_byte)i; + png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); + for (i = 0; i < num_palette; i++) + png_ptr->dither_index[i] = (png_byte)i; } if (num_palette > maximum_colors) { - if (histogram != NULL) - { - /* This is easy enough, just throw out the least used colors. - Perhaps not the best solution, but good enough. */ + if (histogram != NULL) + { - int i; + int i; - /* initialize an array to sort colors */ - png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); + png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); - /* initialize the dither_sort array */ - for (i = 0; i < num_palette; i++) - png_ptr->dither_sort[i] = (png_byte)i; + for (i = 0; i < num_palette; i++) + png_ptr->dither_sort[i] = (png_byte)i; - /* Find the least used palette entries by starting a - bubble sort, and running it until we have sorted - out enough colors. Note that we don't care about - sorting all the colors, just finding which are - least used. */ + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* to stop early if the list is pre-sorted */ + int j; - for (i = num_palette - 1; i >= maximum_colors; i--) - { - int done; /* to stop early if the list is pre-sorted */ - int j; + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->dither_sort[j]] + < histogram[png_ptr->dither_sort[j + 1]]) + { + png_byte t; - done = 1; - for (j = 0; j < i; j++) - { - if (histogram[png_ptr->dither_sort[j]] - < histogram[png_ptr->dither_sort[j + 1]]) - { - png_byte t; + t = png_ptr->dither_sort[j]; + png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; + png_ptr->dither_sort[j + 1] = t; + done = 0; + } + } + if (done) + break; + } - t = png_ptr->dither_sort[j]; - png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; - png_ptr->dither_sort[j + 1] = t; - done = 0; - } - } - if (done) - break; - } + if (full_dither) + { + int j = num_palette; - /* swap the palette around, and set up a table, if necessary */ - if (full_dither) - { - int j = num_palette; + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->dither_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->dither_sort[j] >= maximum_colors); + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; - /* put all the useful colors within the max, but don't - move the others */ - for (i = 0; i < maximum_colors; i++) - { - if ((int)png_ptr->dither_sort[i] >= maximum_colors) - { - do - j--; - while ((int)png_ptr->dither_sort[j] >= maximum_colors); - palette[i] = palette[j]; - } - } - } - else - { - int j = num_palette; + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->dither_sort[i] >= maximum_colors) + { + png_color tmp_color; - /* move all the used colors inside the max limit, and - develop a translation table */ - for (i = 0; i < maximum_colors; i++) - { - /* only move the colors we need to */ - if ((int)png_ptr->dither_sort[i] >= maximum_colors) - { - png_color tmp_color; + do + j--; + while ((int)png_ptr->dither_sort[j] >= maximum_colors); - do - j--; - while ((int)png_ptr->dither_sort[j] >= maximum_colors); + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + png_ptr->dither_index[j] = (png_byte)i; + png_ptr->dither_index[i] = (png_byte)j; + } + } - tmp_color = palette[j]; - palette[j] = palette[i]; - palette[i] = tmp_color; - /* indicate where the color went */ - png_ptr->dither_index[j] = (png_byte)i; - png_ptr->dither_index[i] = (png_byte)j; - } - } + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->dither_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; - /* find closest color for those colors we are not using */ - for (i = 0; i < num_palette; i++) - { - if ((int)png_ptr->dither_index[i] >= maximum_colors) - { - int min_d, k, min_k, d_index; + d_index = png_ptr->dither_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; - /* find the closest color to one we threw out */ - d_index = png_ptr->dither_index[i]; - min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); - for (k = 1, min_k = 0; k < maximum_colors; k++) - { - int d; + d = PNG_COLOR_DIST(palette[d_index], palette[k]); - d = PNG_COLOR_DIST(palette[d_index], palette[k]); + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + png_ptr->dither_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->dither_sort); + png_ptr->dither_sort=NULL; + } + else + { + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; - if (d < min_d) - { - min_d = d; - min_k = k; - } - } - /* point to closest color */ - png_ptr->dither_index[i] = (png_byte)min_k; - } - } - } - png_free(png_ptr, png_ptr->dither_sort); - png_ptr->dither_sort=NULL; - } - else - { - /* This is much harder to do simply (and quickly). Perhaps - we need to go through a median cut routine, but those - don't always behave themselves with only a few colors - as input. So we will just find the closest two colors, - and throw out one of them (chosen somewhat randomly). - [We don't understand this at all, so if someone wants to - work on improving it, be our guest - AED, GRP] - */ - int i; - int max_d; - int num_new_palette; - png_dsortp t; - png_dsortpp hash; + t=NULL; - t=NULL; + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof (png_byte))); - /* initialize palette index arrays */ - png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); - png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } - /* initialize the sort array */ - for (i = 0; i < num_palette; i++) - { - png_ptr->index_to_palette[i] = (png_byte)i; - png_ptr->palette_to_index[i] = (png_byte)i; - } + hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * + png_sizeof (png_dsortp))); + for (i = 0; i < 769; i++) + hash[i] = NULL; - hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * - png_sizeof (png_dsortp))); - for (i = 0; i < 769; i++) - hash[i] = NULL; -/* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */ + num_new_palette = num_palette; - num_new_palette = num_palette; + max_d = 96; - /* initial wild guess at how far apart the farthest pixel - pair we will be eliminating will be. Larger - numbers mean more areas will be allocated, Smaller - numbers run the risk of not saving enough data, and - having to do this all over again. + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; - I have not done extensive checking on this number. - */ - max_d = 96; + for (j = i + 1; j < num_new_palette; j++) + { + int d; - while (num_new_palette > maximum_colors) - { - for (i = 0; i < num_new_palette - 1; i++) - { - int j; + d = PNG_COLOR_DIST(palette[i], palette[j]); - for (j = i + 1; j < num_new_palette; j++) - { - int d; + if (d <= max_d) + { - d = PNG_COLOR_DIST(palette[i], palette[j]); + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(png_sizeof(png_dsort))); + if (t == NULL) + break; + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } - if (d <= max_d) - { + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; - t = (png_dsortp)png_malloc_warn(png_ptr, - (png_uint_32)(png_sizeof(png_dsort))); - if (t == NULL) - break; - t->next = hash[d]; - t->left = (png_byte)i; - t->right = (png_byte)j; - hash[d] = t; - } - } - if (t == NULL) - break; - } + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; - if (t != NULL) - for (i = 0; i <= max_d; i++) - { - if (hash[i] != NULL) - { - png_dsortp p; + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } - for (p = hash[i]; p; p = p->next) - { - if ((int)png_ptr->index_to_palette[p->left] - < num_new_palette && - (int)png_ptr->index_to_palette[p->right] - < num_new_palette) - { - int j, next_j; + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (!full_dither) + { + int k; - if (num_new_palette & 0x01) - { - j = p->left; - next_j = p->right; - } - else - { - j = p->right; - next_j = p->left; - } + for (k = 0; k < num_palette; k++) + { + if (png_ptr->dither_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->dither_index[k] = + png_ptr->index_to_palette[next_j]; + if ((int)png_ptr->dither_index[k] == + num_new_palette) + png_ptr->dither_index[k] = + png_ptr->index_to_palette[j]; + } + } - num_new_palette--; - palette[png_ptr->index_to_palette[j]] - = palette[num_new_palette]; - if (!full_dither) - { - int k; + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; - for (k = 0; k < num_palette; k++) - { - if (png_ptr->dither_index[k] == - png_ptr->index_to_palette[j]) - png_ptr->dither_index[k] = - png_ptr->index_to_palette[next_j]; - if ((int)png_ptr->dither_index[k] == - num_new_palette) - png_ptr->dither_index[k] = - png_ptr->index_to_palette[j]; - } - } + png_ptr->index_to_palette[j] = (png_byte)num_new_palette; + png_ptr->palette_to_index[num_new_palette] = (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } - png_ptr->index_to_palette[png_ptr->palette_to_index - [num_new_palette]] = png_ptr->index_to_palette[j]; - png_ptr->palette_to_index[png_ptr->index_to_palette[j]] - = png_ptr->palette_to_index[num_new_palette]; - - png_ptr->index_to_palette[j] = (png_byte)num_new_palette; - png_ptr->palette_to_index[num_new_palette] = (png_byte)j; - } - if (num_new_palette <= maximum_colors) - break; - } - if (num_new_palette <= maximum_colors) - break; - } - } - - for (i = 0; i < 769; i++) - { - if (hash[i] != NULL) - { - png_dsortp p = hash[i]; - while (p) - { - t = p->next; - png_free(png_ptr, p); - p = t; - } - } - hash[i] = 0; - } - max_d += 96; - } - png_free(png_ptr, hash); - png_free(png_ptr, png_ptr->palette_to_index); - png_free(png_ptr, png_ptr->index_to_palette); - png_ptr->palette_to_index=NULL; - png_ptr->index_to_palette=NULL; - } - num_palette = maximum_colors; + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index=NULL; + png_ptr->index_to_palette=NULL; + } + num_palette = maximum_colors; } if (png_ptr->palette == NULL) { - png_ptr->palette = palette; + png_ptr->palette = palette; } png_ptr->num_palette = (png_uint_16)num_palette; if (full_dither) { - int i; - png_bytep distance; - int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + - PNG_DITHER_BLUE_BITS; - int num_red = (1 << PNG_DITHER_RED_BITS); - int num_green = (1 << PNG_DITHER_GREEN_BITS); - int num_blue = (1 << PNG_DITHER_BLUE_BITS); - png_size_t num_entries = ((png_size_t)1 << total_bits); + int i; + png_bytep distance; + int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + + PNG_DITHER_BLUE_BITS; + int num_red = (1 << PNG_DITHER_RED_BITS); + int num_green = (1 << PNG_DITHER_GREEN_BITS); + int num_blue = (1 << PNG_DITHER_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); - png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, - (png_uint_32)(num_entries * png_sizeof (png_byte))); + png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, + (png_uint_32)(num_entries * png_sizeof (png_byte))); - png_memset(png_ptr->palette_lookup, 0, num_entries * - png_sizeof (png_byte)); + png_memset(png_ptr->palette_lookup, 0, num_entries * + png_sizeof (png_byte)); - distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * - png_sizeof(png_byte))); + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + png_sizeof(png_byte))); - png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); - for (i = 0; i < num_palette; i++) - { - int ir, ig, ib; - int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); - int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); - int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); - for (ir = 0; ir < num_red; ir++) - { - /* int dr = abs(ir - r); */ - int dr = ((ir > r) ? ir - r : r - ir); - int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); + for (ir = 0; ir < num_red; ir++) + { + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); - for (ig = 0; ig < num_green; ig++) - { - /* int dg = abs(ig - g); */ - int dg = ((ig > g) ? ig - g : g - ig); - int dt = dr + dg; - int dm = ((dr > dg) ? dr : dg); - int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); + for (ig = 0; ig < num_green; ig++) + { + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); - for (ib = 0; ib < num_blue; ib++) - { - int d_index = index_g | ib; - /* int db = abs(ib - b); */ - int db = ((ib > b) ? ib - b : b - ib); - int dmax = ((dm > db) ? dm : db); - int d = dmax + dt + db; + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; - if (d < (int)distance[d_index]) - { - distance[d_index] = (png_byte)d; - png_ptr->palette_lookup[d_index] = (png_byte)i; - } - } - } - } - } + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } - png_free(png_ptr, distance); + png_free(png_ptr, distance); } } #endif #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) -/* Transform the image from the file_gamma to the screen_gamma. We - * only do transformations on images where the file_gamma and screen_gamma - * are not close reciprocals, otherwise it slows things down slightly, and - * also needlessly introduces small errors. - * - * We will turn off gamma transformation later if no semitransparent entries - * are present in the tRNS array for palette images. We can't do it here - * because we don't necessarily have the tRNS chunk yet. - */ void PNGAPI png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) { png_debug(1, "in png_set_gamma\n"); if(png_ptr == NULL) return; if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) - png_ptr->transformations |= PNG_GAMMA; + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + png_ptr->transformations |= PNG_GAMMA; png_ptr->gamma = (float)file_gamma; png_ptr->screen_gamma = (float)scrn_gamma; } #endif #if defined(PNG_READ_EXPAND_SUPPORTED) -/* Expand paletted images to RGB, expand grayscale images of - * less than 8-bit depth to 8-bit depth, and expand tRNS chunks - * to alpha channels. - */ void PNGAPI png_set_expand(png_structp png_ptr) { @@ -220056,24 +198900,6 @@ png_set_expand(png_structp png_ptr) #endif } -/* GRR 19990627: the following three functions currently are identical - * to png_set_expand(). However, it is entirely reasonable that someone - * might wish to expand an indexed image to RGB but *not* expand a single, - * fully transparent palette entry to a full alpha channel--perhaps instead - * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace - * the transparent color with a particular RGB value, or drop tRNS entirely. - * IOW, a future version of the library may make the transformations flag - * a bit more fine-grained, with separate bits for each of these three - * functions. - * - * More to the point, these functions make it obvious what libpng will be - * doing, whereas "expand" can (and does) mean any number of things. - * - * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified - * to expand only the sample depth but not to expand the tRNS to alpha. - */ - -/* Expand paletted images to RGB. */ void PNGAPI png_set_palette_to_rgb(png_structp png_ptr) { @@ -220087,7 +198913,6 @@ png_set_palette_to_rgb(png_structp png_ptr) } #if !defined(PNG_1_0_X) -/* Expand grayscale images of less than 8-bit depth to 8 bits. */ void PNGAPI png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) { @@ -220101,8 +198926,6 @@ png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) #endif #if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* Expand grayscale images of less than 8-bit depth to 8 bits. */ -/* Deprecated as of libpng-1.2.9 */ void PNGAPI png_set_gray_1_2_4_to_8(png_structp png_ptr) { @@ -220112,7 +198935,6 @@ png_set_gray_1_2_4_to_8(png_structp png_ptr) } #endif -/* Expand tRNS chunks to alpha channels. */ void PNGAPI png_set_tRNS_to_alpha(png_structp png_ptr) { @@ -220138,18 +198960,15 @@ png_set_gray_to_rgb(png_structp png_ptr) #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) #if defined(PNG_FLOATING_POINT_SUPPORTED) -/* Convert a RGB image to a grayscale of the same width. This allows us, - * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. - */ void PNGAPI png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, double green) { - int red_fixed = (int)((float)red*100000.0 + 0.5); - int green_fixed = (int)((float)green*100000.0 + 0.5); - if(png_ptr == NULL) return; - png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); + int red_fixed = (int)((float)red*100000.0 + 0.5); + int green_fixed = (int)((float)green*100000.0 + 0.5); + if(png_ptr == NULL) return; + png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); } #endif @@ -220161,49 +198980,49 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, if(png_ptr == NULL) return; switch(error_action) { - case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; - break; - case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; - break; - case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; } if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) #if defined(PNG_READ_EXPAND_SUPPORTED) - png_ptr->transformations |= PNG_EXPAND; + png_ptr->transformations |= PNG_EXPAND; #else { - png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); - png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; } #endif { - png_uint_16 red_int, green_int; - if(red < 0 || green < 0) - { - red_int = 6968; /* .212671 * 32768 + .5 */ - green_int = 23434; /* .715160 * 32768 + .5 */ - } - else if(red + green < 100000L) - { - red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); - green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); - } - else - { - png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); - red_int = 6968; - green_int = 23434; - } - png_ptr->rgb_to_gray_red_coeff = red_int; - png_ptr->rgb_to_gray_green_coeff = green_int; - png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int); + png_uint_16 red_int, green_int; + if(red < 0 || green < 0) + { + red_int = 6968; /* .212671 * 32768 + .5 */ + green_int = 23434; /* .715160 * 32768 + .5 */ + } + else if(red + green < 100000L) + { + red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); + green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); + } + else + { + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); + red_int = 6968; + green_int = 23434; + } + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int); } } #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) void PNGAPI png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr read_user_transform_fn) @@ -220216,15 +199035,12 @@ png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr #endif #ifdef PNG_LEGACY_SUPPORTED if(read_user_transform_fn) - png_warning(png_ptr, - "This version of libpng does not support user transforms"); + png_warning(png_ptr, + "This version of libpng does not support user transforms"); #endif } #endif -/* Initialize everything needed for the read. This includes modifying - * the palette. - */ void /* PRIVATE */ png_init_read_transformations(png_structp png_ptr) { @@ -220241,105 +199057,93 @@ png_init_read_transformations(png_structp png_ptr) #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - /* Detect gray background and attempt to enable optimization - * for gray --> RGB case */ - /* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or - * RGB_ALPHA (in which case need_expand is superfluous anyway), the - * background color might actually be gray yet not be flagged as such. - * This is not a problem for the current code, which uses - * PNG_BACKGROUND_IS_GRAY only to decide when to do the - * png_do_gray_to_rgb() transformation. - */ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - !(color_type & PNG_COLOR_MASK_COLOR)) + !(color_type & PNG_COLOR_MASK_COLOR)) { - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; } else if ((png_ptr->transformations & PNG_BACKGROUND) && - !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_GRAY_TO_RGB) && - png_ptr->background.red == png_ptr->background.green && - png_ptr->background.red == png_ptr->background.blue) + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_GRAY_TO_RGB) && + png_ptr->background.red == png_ptr->background.green && + png_ptr->background.red == png_ptr->background.blue) { - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - png_ptr->background.gray = png_ptr->background.red; + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; } #endif if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_EXPAND)) + (png_ptr->transformations & PNG_EXPAND)) { - if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ - { - /* expand background and tRNS chunks */ - switch (png_ptr->bit_depth) - { - case 1: - png_ptr->background.gray *= (png_uint_16)0xff; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_values.gray *= (png_uint_16)0xff; - png_ptr->trans_values.red = png_ptr->trans_values.green - = png_ptr->trans_values.blue = png_ptr->trans_values.gray; - } - break; - case 2: - png_ptr->background.gray *= (png_uint_16)0x55; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_values.gray *= (png_uint_16)0x55; - png_ptr->trans_values.red = png_ptr->trans_values.green - = png_ptr->trans_values.blue = png_ptr->trans_values.gray; - } - break; - case 4: - png_ptr->background.gray *= (png_uint_16)0x11; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_values.gray *= (png_uint_16)0x11; - png_ptr->trans_values.red = png_ptr->trans_values.green - = png_ptr->trans_values.blue = png_ptr->trans_values.gray; - } - break; - case 8: - case 16: - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - break; - } - } - else if (color_type == PNG_COLOR_TYPE_PALETTE) - { - png_ptr->background.red = - png_ptr->palette[png_ptr->background.index].red; - png_ptr->background.green = - png_ptr->palette[png_ptr->background.index].green; - png_ptr->background.blue = - png_ptr->palette[png_ptr->background.index].blue; + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ + { + switch (png_ptr->bit_depth) + { + case 1: + png_ptr->background.gray *= (png_uint_16)0xff; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0xff; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + case 2: + png_ptr->background.gray *= (png_uint_16)0x55; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0x55; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + case 4: + png_ptr->background.gray *= (png_uint_16)0x11; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_values.gray *= (png_uint_16)0x11; + png_ptr->trans_values.red = png_ptr->trans_values.green + = png_ptr->trans_values.blue = png_ptr->trans_values.gray; + } + break; + case 8: + case 16: + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + } + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_ALPHA) - { + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { #if defined(PNG_READ_EXPAND_SUPPORTED) - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) #endif - { - /* invert the alpha channel (in tRNS) unless the pixels are - going to be expanded, in which case leave it for later */ - int i,istop; - istop=(int)png_ptr->num_trans; - for (i=0; itrans[i] = (png_byte)(255 - png_ptr->trans[i]); - } - } + { + int i,istop; + istop=(int)png_ptr->num_trans; + for (i=0; itrans[i] = (png_byte)(255 - png_ptr->trans[i]); + } + } #endif - } + } } #endif @@ -220349,274 +199153,261 @@ png_init_read_transformations(png_structp png_ptr) #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) - && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) - < PNG_GAMMA_THRESHOLD)) + && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) + < PNG_GAMMA_THRESHOLD)) { - int i,k; - k=0; - for (i=0; inum_trans; i++) - { - if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) - k=1; /* partial transparency is present */ - } - if (k == 0) - png_ptr->transformations &= (~PNG_GAMMA); + int i,k; + k=0; + for (i=0; inum_trans; i++) + { + if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) + k=1; /* partial transparency is present */ + } + if (k == 0) + png_ptr->transformations &= (~PNG_GAMMA); } if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && - png_ptr->gamma != 0.0) + png_ptr->gamma != 0.0) { - png_build_gamma_table(png_ptr); + png_build_gamma_table(png_ptr); #if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->transformations & PNG_BACKGROUND) - { - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - /* could skip if no transparency and - */ - png_color back, back_1; - png_colorp palette = png_ptr->palette; - int num_palette = png_ptr->num_palette; - int i; - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) - { - back.red = png_ptr->gamma_table[png_ptr->background.red]; - back.green = png_ptr->gamma_table[png_ptr->background.green]; - back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; - back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; - back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; - back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; - } - else - { - double g, gs; + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g, gs; - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = (png_ptr->screen_gamma); - gs = 1.0; - break; - case PNG_BACKGROUND_GAMMA_FILE: - g = 1.0 / (png_ptr->gamma); - gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - break; - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = 1.0 / (png_ptr->background_gamma); - gs = 1.0 / (png_ptr->background_gamma * - png_ptr->screen_gamma); - break; - default: - g = 1.0; /* back_1 */ - gs = 1.0; /* back */ - } + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + default: + g = 1.0; /* back_1 */ + gs = 1.0; /* back */ + } - if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) - { - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; - } - else - { - back.red = (png_byte)(pow( - (double)png_ptr->background.red/255, gs) * 255.0 + .5); - back.green = (png_byte)(pow( - (double)png_ptr->background.green/255, gs) * 255.0 + .5); - back.blue = (png_byte)(pow( - (double)png_ptr->background.blue/255, gs) * 255.0 + .5); - } + if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + else + { + back.red = (png_byte)(pow( + (double)png_ptr->background.red/255, gs) * 255.0 + .5); + back.green = (png_byte)(pow( + (double)png_ptr->background.green/255, gs) * 255.0 + .5); + back.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, gs) * 255.0 + .5); + } - back_1.red = (png_byte)(pow( - (double)png_ptr->background.red/255, g) * 255.0 + .5); - back_1.green = (png_byte)(pow( - (double)png_ptr->background.green/255, g) * 255.0 + .5); - back_1.blue = (png_byte)(pow( - (double)png_ptr->background.blue/255, g) * 255.0 + .5); - } - for (i = 0; i < num_palette; i++) - { - if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) - { - if (png_ptr->trans[i] == 0) - { - palette[i] = back; - } - else /* if (png_ptr->trans[i] != 0xff) */ - { - png_byte v, w; + back_1.red = (png_byte)(pow( + (double)png_ptr->background.red/255, g) * 255.0 + .5); + back_1.green = (png_byte)(pow( + (double)png_ptr->background.green/255, g) * 255.0 + .5); + back_1.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, g) * 255.0 + .5); + } + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans[i] != 0xff) */ + { + png_byte v, w; - v = png_ptr->gamma_to_1[palette[i].red]; - png_composite(w, v, png_ptr->trans[i], back_1.red); - palette[i].red = png_ptr->gamma_from_1[w]; + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; - v = png_ptr->gamma_to_1[palette[i].green]; - png_composite(w, v, png_ptr->trans[i], back_1.green); - palette[i].green = png_ptr->gamma_from_1[w]; + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; - v = png_ptr->gamma_to_1[palette[i].blue]; - png_composite(w, v, png_ptr->trans[i], back_1.blue); - palette[i].blue = png_ptr->gamma_from_1[w]; - } - } - else - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } - /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ - else - /* color_type != PNG_COLOR_TYPE_PALETTE */ - { - double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); - double g = 1.0; - double gs = 1.0; + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + else + { + double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); + double g = 1.0; + double gs = 1.0; - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = (png_ptr->screen_gamma); - gs = 1.0; - break; - case PNG_BACKGROUND_GAMMA_FILE: - g = 1.0 / (png_ptr->gamma); - gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - break; - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = 1.0 / (png_ptr->background_gamma); - gs = 1.0 / (png_ptr->background_gamma * - png_ptr->screen_gamma); - break; - } + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + } - png_ptr->background_1.gray = (png_uint_16)(pow( - (double)png_ptr->background.gray / m, g) * m + .5); - png_ptr->background.gray = (png_uint_16)(pow( - (double)png_ptr->background.gray / m, gs) * m + .5); + png_ptr->background_1.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, g) * m + .5); + png_ptr->background.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, gs) * m + .5); - if ((png_ptr->background.red != png_ptr->background.green) || - (png_ptr->background.red != png_ptr->background.blue) || - (png_ptr->background.red != png_ptr->background.gray)) - { - /* RGB or RGBA with color background */ - png_ptr->background_1.red = (png_uint_16)(pow( - (double)png_ptr->background.red / m, g) * m + .5); - png_ptr->background_1.green = (png_uint_16)(pow( - (double)png_ptr->background.green / m, g) * m + .5); - png_ptr->background_1.blue = (png_uint_16)(pow( - (double)png_ptr->background.blue / m, g) * m + .5); - png_ptr->background.red = (png_uint_16)(pow( - (double)png_ptr->background.red / m, gs) * m + .5); - png_ptr->background.green = (png_uint_16)(pow( - (double)png_ptr->background.green / m, gs) * m + .5); - png_ptr->background.blue = (png_uint_16)(pow( - (double)png_ptr->background.blue / m, gs) * m + .5); - } - else - { - /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ - png_ptr->background_1.red = png_ptr->background_1.green - = png_ptr->background_1.blue = png_ptr->background_1.gray; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - } - } - } - else - /* transformation does not include PNG_BACKGROUND */ + if ((png_ptr->background.red != png_ptr->background.green) || + (png_ptr->background.red != png_ptr->background.blue) || + (png_ptr->background.red != png_ptr->background.gray)) + { + png_ptr->background_1.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, g) * m + .5); + png_ptr->background_1.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, g) * m + .5); + png_ptr->background_1.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, g) * m + .5); + png_ptr->background.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, gs) * m + .5); + png_ptr->background.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, gs) * m + .5); + png_ptr->background.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, gs) * m + .5); + } + else + { + png_ptr->background_1.red = png_ptr->background_1.green + = png_ptr->background_1.blue = png_ptr->background_1.gray; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + } + } + } + else #endif /* PNG_READ_BACKGROUND_SUPPORTED */ - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - png_colorp palette = png_ptr->palette; - int num_palette = png_ptr->num_palette; - int i; + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; - for (i = 0; i < num_palette; i++) - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } } #if defined(PNG_READ_BACKGROUND_SUPPORTED) else #endif #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ #if defined(PNG_READ_BACKGROUND_SUPPORTED) - /* No GAMMA transformation */ if ((png_ptr->transformations & PNG_BACKGROUND) && - (color_type == PNG_COLOR_TYPE_PALETTE)) + (color_type == PNG_COLOR_TYPE_PALETTE)) { - int i; - int istop = (int)png_ptr->num_trans; - png_color back; - png_colorp palette = png_ptr->palette; + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; - for (i = 0; i < istop; i++) - { - if (png_ptr->trans[i] == 0) - { - palette[i] = back; - } - else if (png_ptr->trans[i] != 0xff) - { - /* The png_composite() macro is defined in png.h */ - png_composite(palette[i].red, palette[i].red, - png_ptr->trans[i], back.red); - png_composite(palette[i].green, palette[i].green, - png_ptr->trans[i], back.green); - png_composite(palette[i].blue, palette[i].blue, - png_ptr->trans[i], back.blue); - } - } + for (i = 0; i < istop; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (png_ptr->trans[i] != 0xff) + { + png_composite(palette[i].red, palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans[i], back.blue); + } + } } #endif /* PNG_READ_BACKGROUND_SUPPORTED */ #if defined(PNG_READ_SHIFT_SUPPORTED) if ((png_ptr->transformations & PNG_SHIFT) && - (color_type == PNG_COLOR_TYPE_PALETTE)) + (color_type == PNG_COLOR_TYPE_PALETTE)) { - png_uint_16 i; - png_uint_16 istop = png_ptr->num_palette; - int sr = 8 - png_ptr->sig_bit.red; - int sg = 8 - png_ptr->sig_bit.green; - int sb = 8 - png_ptr->sig_bit.blue; + png_uint_16 i; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; - if (sr < 0 || sr > 8) - sr = 0; - if (sg < 0 || sg > 8) - sg = 0; - if (sb < 0 || sb > 8) - sb = 0; - for (i = 0; i < istop; i++) - { - png_ptr->palette[i].red >>= sr; - png_ptr->palette[i].green >>= sg; - png_ptr->palette[i].blue >>= sb; - } + if (sr < 0 || sr > 8) + sr = 0; + if (sg < 0 || sg > 8) + sg = 0; + if (sb < 0 || sb > 8) + sb = 0; + for (i = 0; i < istop; i++) + { + png_ptr->palette[i].red >>= sr; + png_ptr->palette[i].green >>= sg; + png_ptr->palette[i].blue >>= sb; + } } #endif /* PNG_READ_SHIFT_SUPPORTED */ } #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ && !defined(PNG_READ_BACKGROUND_SUPPORTED) if(png_ptr) - return; + return; #endif } -/* Modify the info structure to reflect the transformations. The - * info should be updated so a PNG file could be written with it, - * assuming the transformations result in valid PNG data. - */ void /* PRIVATE */ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) { @@ -220624,37 +199415,37 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_READ_EXPAND_SUPPORTED) if (png_ptr->transformations & PNG_EXPAND) { - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND_tRNS)) - info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - else - info_ptr->color_type = PNG_COLOR_TYPE_RGB; - info_ptr->bit_depth = 8; - info_ptr->num_trans = 0; - } - else - { - if (png_ptr->num_trans) - { - if (png_ptr->transformations & PNG_EXPAND_tRNS) - info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; - else - info_ptr->color_type |= PNG_COLOR_MASK_COLOR; - } - if (info_ptr->bit_depth < 8) - info_ptr->bit_depth = 8; - info_ptr->num_trans = 0; - } + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND_tRNS)) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + { + if (png_ptr->transformations & PNG_EXPAND_tRNS) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + else + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; + } + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } } #endif #if defined(PNG_READ_BACKGROUND_SUPPORTED) if (png_ptr->transformations & PNG_BACKGROUND) { - info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; - info_ptr->num_trans = 0; - info_ptr->background = png_ptr->background; + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; + info_ptr->num_trans = 0; + info_ptr->background = png_ptr->background; } #endif @@ -220662,72 +199453,70 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) if (png_ptr->transformations & PNG_GAMMA) { #ifdef PNG_FLOATING_POINT_SUPPORTED - info_ptr->gamma = png_ptr->gamma; + info_ptr->gamma = png_ptr->gamma; #endif #ifdef PNG_FIXED_POINT_SUPPORTED - info_ptr->int_gamma = png_ptr->int_gamma; + info_ptr->int_gamma = png_ptr->int_gamma; #endif } #endif #if defined(PNG_READ_16_TO_8_SUPPORTED) if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) - info_ptr->bit_depth = 8; + info_ptr->bit_depth = 8; #endif #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) if (png_ptr->transformations & PNG_GRAY_TO_RGB) - info_ptr->color_type |= PNG_COLOR_MASK_COLOR; + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; #endif #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) if (png_ptr->transformations & PNG_RGB_TO_GRAY) - info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; #endif #if defined(PNG_READ_DITHER_SUPPORTED) if (png_ptr->transformations & PNG_DITHER) { - if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || - (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && - png_ptr->palette_lookup && info_ptr->bit_depth == 8) - { - info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; - } + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } } #endif #if defined(PNG_READ_PACK_SUPPORTED) if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) - info_ptr->bit_depth = 8; + info_ptr->bit_depth = 8; #endif if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - info_ptr->channels = 1; + info_ptr->channels = 1; else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) - info_ptr->channels = 3; + info_ptr->channels = 3; else - info_ptr->channels = 1; + info_ptr->channels = 1; #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) - info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; #endif if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - info_ptr->channels++; + info_ptr->channels++; #if defined(PNG_READ_FILLER_SUPPORTED) - /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ if ((png_ptr->transformations & PNG_FILLER) && - ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || - (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) { - info_ptr->channels++; - /* if adding a true alpha channel not just filler */ + info_ptr->channels++; #if !defined(PNG_1_0_X) - if (png_ptr->transformations & PNG_ADD_ALPHA) - info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; #endif } #endif @@ -220735,29 +199524,25 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ defined(PNG_READ_USER_TRANSFORM_SUPPORTED) if(png_ptr->transformations & PNG_USER_TRANSFORM) - { - if(info_ptr->bit_depth < png_ptr->user_transform_depth) - info_ptr->bit_depth = png_ptr->user_transform_depth; - if(info_ptr->channels < png_ptr->user_transform_channels) - info_ptr->channels = png_ptr->user_transform_channels; - } + { + if(info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + if(info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } #endif info_ptr->pixel_depth = (png_byte)(info_ptr->channels * - info_ptr->bit_depth); + info_ptr->bit_depth); info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width); #if !defined(PNG_READ_EXPAND_SUPPORTED) if(png_ptr) - return; + return; #endif } -/* Transform the row. The order of transformations is significant, - * and is very touchy. If you add a transformation, take care to - * decide how it fits in with the other transformations here. - */ void /* PRIVATE */ png_do_read_transformations(png_structp png_ptr) { @@ -220765,123 +199550,88 @@ png_do_read_transformations(png_structp png_ptr) if (png_ptr->row_buf == NULL) { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[50]; + char msg[50]; - png_snprintf2(msg, 50, - "NULL row buffer for row %ld, pass %d", png_ptr->row_number, - png_ptr->pass); - png_error(png_ptr, msg); + png_snprintf2(msg, 50, + "NULL row buffer for row %ld, pass %d", png_ptr->row_number, + png_ptr->pass); + png_error(png_ptr, msg); #else - png_error(png_ptr, "NULL row buffer"); + png_error(png_ptr, "NULL row buffer"); #endif } #ifdef PNG_WARN_UNINITIALIZED_ROW if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - /* Application has failed to call either png_read_start_image() - * or png_read_update_info() after setting transforms that expand - * pixels. This check added to libpng-1.2.19 */ #if (PNG_WARN_UNINITIALIZED_ROW==1) - png_error(png_ptr, "Uninitialized row"); + png_error(png_ptr, "Uninitialized row"); #else - png_warning(png_ptr, "Uninitialized row"); + png_warning(png_ptr, "Uninitialized row"); #endif #endif #if defined(PNG_READ_EXPAND_SUPPORTED) if (png_ptr->transformations & PNG_EXPAND) { - if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) - { - png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->palette, png_ptr->trans, png_ptr->num_trans); - } - else - { - if (png_ptr->num_trans && - (png_ptr->transformations & PNG_EXPAND_tRNS)) - png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->trans_values)); - else - png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, - NULL); - } + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans, png_ptr->num_trans); + } + else + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values)); + else + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + NULL); + } } #endif #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) - png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); #endif #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) if (png_ptr->transformations & PNG_RGB_TO_GRAY) { - int rgb_error = - png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); - if(rgb_error) - { - png_ptr->rgb_to_gray_status=1; - if((png_ptr->transformations & PNG_RGB_TO_GRAY) == - PNG_RGB_TO_GRAY_WARN) - png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); - if((png_ptr->transformations & PNG_RGB_TO_GRAY) == - PNG_RGB_TO_GRAY_ERR) - png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); - } + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); + if(rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + if((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } } #endif -/* -From Andreas Dilger e-mail to png-implement, 26 March 1998: - - In most cases, the "simple transparency" should be done prior to doing - gray-to-RGB, or you will have to test 3x as many bytes to check if a - pixel is transparent. You would also need to make sure that the - transparency information is upgraded to RGB. - - To summarize, the current flow is: - - Gray + simple transparency -> compare 1 or 2 gray bytes and composite - with background "in place" if transparent, - convert to RGB if necessary - - Gray + alpha -> composite with gray background and remove alpha bytes, - convert to RGB if necessary - - To support RGB backgrounds for gray images we need: - - Gray + simple transparency -> convert to RGB + simple transparency, compare - 3 or 6 bytes and composite with background - "in place" if transparent (3x compare/pixel - compared to doing composite with gray bkgrnd) - - Gray + alpha -> convert to RGB + alpha, composite with background and - remove alpha bytes (3x float operations/pixel - compared with composite on gray background) - - Greg's change will do this. The reason it wasn't done before is for - performance, as this increases the per-pixel operations. If we would check - in advance if the background was gray or RGB, and position the gray-to-RGB - transform appropriately, then it would save a lot of work/time. - */ - #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - /* if gray -> RGB, do so now only if background is non-gray; else do later - * for performance reasons */ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) - png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_READ_BACKGROUND_SUPPORTED) if ((png_ptr->transformations & PNG_BACKGROUND) && - ((png_ptr->num_trans != 0 ) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) - png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->trans_values), &(png_ptr->background) + ((png_ptr->num_trans != 0 ) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) + png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values), &(png_ptr->background) #if defined(PNG_READ_GAMMA_SUPPORTED) - , &(png_ptr->background_1), - png_ptr->gamma_table, png_ptr->gamma_from_1, - png_ptr->gamma_to_1, png_ptr->gamma_16_table, - png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, - png_ptr->gamma_shift + , &(png_ptr->background_1), + png_ptr->gamma_table, png_ptr->gamma_from_1, + png_ptr->gamma_to_1, png_ptr->gamma_16_table, + png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, + png_ptr->gamma_shift #endif ); #endif @@ -220889,121 +199639,108 @@ From Andreas Dilger e-mail to png-implement, 26 March 1998: #if defined(PNG_READ_GAMMA_SUPPORTED) if ((png_ptr->transformations & PNG_GAMMA) && #if defined(PNG_READ_BACKGROUND_SUPPORTED) - !((png_ptr->transformations & PNG_BACKGROUND) && - ((png_ptr->num_trans != 0) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && + !((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && #endif - (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) - png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->gamma_table, png_ptr->gamma_16_table, - png_ptr->gamma_shift); + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->gamma_table, png_ptr->gamma_16_table, + png_ptr->gamma_shift); #endif #if defined(PNG_READ_16_TO_8_SUPPORTED) if (png_ptr->transformations & PNG_16_TO_8) - png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_READ_DITHER_SUPPORTED) if (png_ptr->transformations & PNG_DITHER) { - png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->palette_lookup, png_ptr->dither_index); - if(png_ptr->row_info.rowbytes == (png_uint_32)0) - png_error(png_ptr, "png_do_dither returned rowbytes=0"); + png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->dither_index); + if(png_ptr->row_info.rowbytes == (png_uint_32)0) + png_error(png_ptr, "png_do_dither returned rowbytes=0"); } #endif #if defined(PNG_READ_INVERT_SUPPORTED) if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_READ_SHIFT_SUPPORTED) if (png_ptr->transformations & PNG_SHIFT) - png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->shift)); + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); #endif #if defined(PNG_READ_PACK_SUPPORTED) if (png_ptr->transformations & PNG_PACK) - png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_READ_BGR_SUPPORTED) if (png_ptr->transformations & PNG_BGR) - png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - /* if gray -> RGB, do so now only if we did not do so above */ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) - png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_READ_FILLER_SUPPORTED) if (png_ptr->transformations & PNG_FILLER) - png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - (png_uint_32)png_ptr->filler, png_ptr->flags); + png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); #endif #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) if (png_ptr->transformations & PNG_INVERT_ALPHA) - png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) if (png_ptr->transformations & PNG_SWAP_ALPHA) - png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_READ_SWAP_SUPPORTED) if (png_ptr->transformations & PNG_SWAP_BYTES) - png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) if (png_ptr->transformations & PNG_USER_TRANSFORM) - { - if(png_ptr->read_user_transform_fn != NULL) - (*(png_ptr->read_user_transform_fn)) /* user read transform function */ - (png_ptr, /* png_ptr */ - &(png_ptr->row_info), /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_uint_32 rowbytes; number of bytes in row */ - /* png_byte color_type; color type of pixels */ - /* png_byte bit_depth; bit depth of samples */ - /* png_byte channels; number of channels (1-4) */ - /* png_byte pixel_depth; bits per pixel (depth*channels) */ - png_ptr->row_buf + 1); /* start of pixel data for row */ + { + if(png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* user read transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + png_ptr->row_buf + 1); /* start of pixel data for row */ #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) - if(png_ptr->user_transform_depth) - png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; - if(png_ptr->user_transform_channels) - png_ptr->row_info.channels = png_ptr->user_transform_channels; + if(png_ptr->user_transform_depth) + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + if(png_ptr->user_transform_channels) + png_ptr->row_info.channels = png_ptr->user_transform_channels; #endif - png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * - png_ptr->row_info.channels); - png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); } #endif } #if defined(PNG_READ_PACK_SUPPORTED) -/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, - * without changing the actual values. Thus, if you had a row with - * a bit depth of 1, you would end up with bytes that only contained - * the numbers 0 or 1. If you would rather they contain 0 and 255, use - * png_do_shift() after this. - */ void /* PRIVATE */ png_do_unpack(png_row_infop row_info, png_bytep row) { @@ -221014,192 +199751,186 @@ png_do_unpack(png_row_infop row_info, png_bytep row) if (row_info->bit_depth < 8) #endif { - png_uint_32 i; - png_uint_32 row_width=row_info->width; + png_uint_32 i; + png_uint_32 row_width=row_info->width; - switch (row_info->bit_depth) - { - case 1: - { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x01); - if (shift == 7) - { - shift = 0; - sp--; - } - else - shift++; + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; - dp--; - } - break; - } - case 2: - { + dp--; + } + break; + } + case 2: + { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x03); - if (shift == 6) - { - shift = 0; - sp--; - } - else - shift += 2; + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; - dp--; - } - break; - } - case 4: - { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x0f); - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift = 4; + dp--; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; - dp--; - } - break; - } - } - row_info->bit_depth = 8; - row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_width * row_info->channels; + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; } } #endif #if defined(PNG_READ_SHIFT_SUPPORTED) -/* Reverse the effects of png_do_shift. This routine merely shifts the - * pixels back to their significant bits values. Thus, if you have - * a row of bit depth 8, but only 5 are significant, this will shift - * the values back to 0 through 31. - */ void /* PRIVATE */ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) { png_debug(1, "in png_do_unshift\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && sig_bits != NULL && + row != NULL && row_info != NULL && sig_bits != NULL && #endif - row_info->color_type != PNG_COLOR_TYPE_PALETTE) + row_info->color_type != PNG_COLOR_TYPE_PALETTE) { - int shift[4]; - int channels = 0; - int c; - png_uint_16 value = 0; - png_uint_32 row_width = row_info->width; + int shift[4]; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; - if (row_info->color_type & PNG_COLOR_MASK_COLOR) - { - shift[channels++] = row_info->bit_depth - sig_bits->red; - shift[channels++] = row_info->bit_depth - sig_bits->green; - shift[channels++] = row_info->bit_depth - sig_bits->blue; - } - else - { - shift[channels++] = row_info->bit_depth - sig_bits->gray; - } - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - shift[channels++] = row_info->bit_depth - sig_bits->alpha; - } + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = row_info->bit_depth - sig_bits->red; + shift[channels++] = row_info->bit_depth - sig_bits->green; + shift[channels++] = row_info->bit_depth - sig_bits->blue; + } + else + { + shift[channels++] = row_info->bit_depth - sig_bits->gray; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = row_info->bit_depth - sig_bits->alpha; + } - for (c = 0; c < channels; c++) - { - if (shift[c] <= 0) - shift[c] = 0; - else - value = 1; - } + for (c = 0; c < channels; c++) + { + if (shift[c] <= 0) + shift[c] = 0; + else + value = 1; + } - if (!value) - return; + if (!value) + return; - switch (row_info->bit_depth) - { - case 2: - { - png_bytep bp; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; + switch (row_info->bit_depth) + { + case 2: + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; - for (bp = row, i = 0; i < istop; i++) - { - *bp >>= 1; - *bp++ &= 0x55; - } - break; - } - case 4: - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | - (png_byte)((int)0xf >> shift[0])); + for (bp = row, i = 0; i < istop; i++) + { + *bp >>= 1; + *bp++ &= 0x55; + } + break; + } + case 4: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | + (png_byte)((int)0xf >> shift[0])); - for (i = 0; i < istop; i++) - { - *bp >>= shift[0]; - *bp++ &= mask; - } - break; - } - case 8: - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = row_width * channels; + for (i = 0; i < istop; i++) + { + *bp >>= shift[0]; + *bp++ &= mask; + } + break; + } + case 8: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_width * channels; - for (i = 0; i < istop; i++) - { - *bp++ >>= shift[i%channels]; - } - break; - } - case 16: - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = channels * row_width; + for (i = 0; i < istop; i++) + { + *bp++ >>= shift[i%channels]; + } + break; + } + case 16: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; - for (i = 0; i < istop; i++) - { - value = (png_uint_16)((*bp << 8) + *(bp + 1)); - value >>= shift[i%channels]; - *bp++ = (png_byte)(value >> 8); - *bp++ = (png_byte)(value & 0xff); - } - break; - } - } + for (i = 0; i < istop; i++) + { + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } + } } } #endif #if defined(PNG_READ_16_TO_8_SUPPORTED) -/* chop rows of bit depth 16 down to 8 */ void /* PRIVATE */ png_do_chop(png_row_infop row_info, png_bytep row) { @@ -221210,45 +199941,23 @@ png_do_chop(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 16) #endif { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - png_uint_32 istop = row_info->width * row_info->channels; + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + png_uint_32 istop = row_info->width * row_info->channels; - for (i = 0; i> 8)) >> 8; - * - * Approximate calculation with shift/add instead of multiply/divide: - * *dp = ((((png_uint_32)(*sp) << 8) | - * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; - * - * What we actually do to avoid extra shifting and conversion: - */ - *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); + *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); #else - /* Simply discard the low order byte */ - *dp = *sp; + *dp = *sp; #endif - } - row_info->bit_depth = 8; - row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_info->width * row_info->channels; + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; } } #endif @@ -221262,85 +199971,81 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) if (row != NULL && row_info != NULL) #endif { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This converts from RGBA to ARGB */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } - } - /* This converts from RRGGBBAA to AARRGGBB */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This converts from GA to AG */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } - } - /* This converts from GGAA to AAGG */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } - } - } + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } } } #endif @@ -221354,97 +200059,73 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) if (row != NULL && row_info != NULL) #endif { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This inverts the alpha channel in RGBA */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); -/* This does nothing: - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - We can replace it with: -*/ - sp-=3; - dp=sp; - } - } - /* This inverts the alpha channel in RRGGBBAA */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; + sp-=3; + dp=sp; + } + } + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = (png_byte)(255 - *(--sp)); + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); -/* This does nothing: - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - We can replace it with: -*/ - sp-=6; - dp=sp; - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This inverts the alpha channel in GA */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; + sp-=6; + dp=sp; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = *(--sp); - } - } - /* This inverts the alpha channel in GGAA */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = (png_byte)(255 - *(--sp)); -/* - *(--dp) = *(--sp); - *(--dp) = *(--sp); -*/ - sp-=2; - dp=sp; - } - } - } + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + sp-=2; + dp=sp; + } + } + } } } #endif #if defined(PNG_READ_FILLER_SUPPORTED) -/* Add filler channel if we have RGB color */ void /* PRIVATE */ png_do_read_filler(png_row_infop row_info, png_bytep row, png_uint_32 filler, png_uint_32 flags) @@ -221458,169 +200139,160 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, png_debug(1, "in png_do_read_filler\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - row_info->color_type == PNG_COLOR_TYPE_GRAY) + row_info->color_type == PNG_COLOR_TYPE_GRAY) { - if(row_info->bit_depth == 8) - { - /* This changes the data from G to GX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 1; i < row_width; i++) - { - *(--dp) = lo_filler; - *(--dp) = *(--sp); - } - *(--dp) = lo_filler; - row_info->channels = 2; - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - /* This changes the data from G to XG */ - else - { - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = lo_filler; - } - row_info->channels = 2; - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - } - else if(row_info->bit_depth == 16) - { - /* This changes the data from GG to GGXX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 1; i < row_width; i++) - { - *(--dp) = hi_filler; - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = hi_filler; - *(--dp) = lo_filler; - row_info->channels = 2; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - /* This changes the data from GG to XXGG */ - else - { - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = hi_filler; - *(--dp) = lo_filler; - } - row_info->channels = 2; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - } + if(row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + else + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + else if(row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + else + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } } /* COLOR_TYPE == GRAY */ else if (row_info->color_type == PNG_COLOR_TYPE_RGB) { - if(row_info->bit_depth == 8) - { - /* This changes the data from RGB to RGBX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 1; i < row_width; i++) - { - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = lo_filler; - row_info->channels = 4; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - /* This changes the data from RGB to XRGB */ - else - { - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = lo_filler; - } - row_info->channels = 4; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - } - else if(row_info->bit_depth == 16) - { - /* This changes the data from RRGGBB to RRGGBBXX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 1; i < row_width; i++) - { - *(--dp) = hi_filler; - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = hi_filler; - *(--dp) = lo_filler; - row_info->channels = 4; - row_info->pixel_depth = 64; - row_info->rowbytes = row_width * 8; - } - /* This changes the data from RRGGBB to XXRRGGBB */ - else - { - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = hi_filler; - *(--dp) = lo_filler; - } - row_info->channels = 4; - row_info->pixel_depth = 64; - row_info->rowbytes = row_width * 8; - } - } + if(row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + else + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + else if(row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + else + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } } /* COLOR_TYPE == RGB */ } #endif #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -/* expand grayscale files to RGB, with or without alpha */ void /* PRIVATE */ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) { @@ -221630,98 +200302,79 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) png_debug(1, "in png_do_gray_to_rgb\n"); if (row_info->bit_depth >= 8 && #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - if (row_info->bit_depth == 8) - { - png_bytep sp = row + (png_size_t)row_width - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(dp--) = *sp; - *(dp--) = *sp; - *(dp--) = *(sp--); - } - } - else - { - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; - for (i = 0; i < row_width; i++) - { - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *(sp--); - *(dp--) = *(sp--); - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (row_info->bit_depth == 8) - { - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(dp--) = *(sp--); - *(dp--) = *sp; - *(dp--) = *sp; - *(dp--) = *(sp--); - } - } - else - { - png_bytep sp = row + (png_size_t)row_width * 4 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; - for (i = 0; i < row_width; i++) - { - *(dp--) = *(sp--); - *(dp--) = *(sp--); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *(sp--); - *(dp--) = *(sp--); - } - } - } - row_info->channels += (png_byte)2; - row_info->color_type |= PNG_COLOR_MASK_COLOR; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels += (png_byte)2; + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); } } #endif #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -/* reduce RGB files to grayscale, with or without alpha - * using the equation given in Poynton's ColorFAQ at - * - * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net - * - * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B - * - * We approximate this with - * - * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B - * - * which can be expressed with integers as - * - * Y = (6969 * R + 23434 * G + 2365 * B)/32768 - * - * The calculation is to be done in a linear colorspace. - * - * Other integer coefficents can be used via png_set_rgb_to_gray(). - */ int /* PRIVATE */ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) @@ -221734,233 +200387,228 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) png_debug(1, "in png_do_rgb_to_gray\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) + (row_info->color_type & PNG_COLOR_MASK_COLOR)) { - png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; - png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; - png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - if (row_info->bit_depth == 8) - { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_byte red = png_ptr->gamma_to_1[*(sp++)]; - png_byte green = png_ptr->gamma_to_1[*(sp++)]; - png_byte blue = png_ptr->gamma_to_1[*(sp++)]; - if(red != green || red != blue) - { - rgb_error |= 1; - *(dp++) = png_ptr->gamma_from_1[ - (rc*red+gc*green+bc*blue)>>15]; - } - else - *(dp++) = *(sp-1); - } - } - else + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if(red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red+gc*green+bc*blue)>>15]; + } + else + *(dp++) = *(sp-1); + } + } + else #endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_byte red = *(sp++); - png_byte green = *(sp++); - png_byte blue = *(sp++); - if(red != green || red != blue) - { - rgb_error |= 1; - *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15); - } - else - *(dp++) = *(sp-1); - } - } - } + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if(red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15); + } + else + *(dp++) = *(sp-1); + } + } + } - else /* RGB bit_depth == 16 */ - { + else /* RGB bit_depth == 16 */ + { #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_16_to_1 != NULL && - png_ptr->gamma_16_from_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, w; + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; - red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - if(red == green && red == blue) - w = red; - else - { - png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> - png_ptr->gamma_shift][red>>8]; - png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> - png_ptr->gamma_shift][green>>8]; - png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> - png_ptr->gamma_shift][blue>>8]; - png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 - + bc*blue_1)>>15); - w = png_ptr->gamma_16_from_1[(gray16&0xff) >> - png_ptr->gamma_shift][gray16 >> 8]; - rgb_error |= 1; - } + if(red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } - *(dp++) = (png_byte)((w>>8) & 0xff); - *(dp++) = (png_byte)(w & 0xff); - } - } - else + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + } + } + else #endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, gray16; + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; - red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - if(red != green || red != blue) - rgb_error |= 1; - gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); - *(dp++) = (png_byte)((gray16>>8) & 0xff); - *(dp++) = (png_byte)(gray16 & 0xff); - } - } - } - } - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - if (row_info->bit_depth == 8) - { + if(red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_byte red = png_ptr->gamma_to_1[*(sp++)]; - png_byte green = png_ptr->gamma_to_1[*(sp++)]; - png_byte blue = png_ptr->gamma_to_1[*(sp++)]; - if(red != green || red != blue) - rgb_error |= 1; - *(dp++) = png_ptr->gamma_from_1 - [(rc*red + gc*green + bc*blue)>>15]; - *(dp++) = *(sp++); /* alpha */ - } - } - else + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if(red != green || red != blue) + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>15]; + *(dp++) = *(sp++); /* alpha */ + } + } + else #endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_byte red = *(sp++); - png_byte green = *(sp++); - png_byte blue = *(sp++); - if(red != green || red != blue) - rgb_error |= 1; - *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); - *(dp++) = *(sp++); /* alpha */ - } - } - } - else /* RGBA bit_depth == 16 */ - { + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if(red != green || red != blue) + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_16_to_1 != NULL && - png_ptr->gamma_16_from_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, w; + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; - red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - if(red == green && red == blue) - w = red; - else - { - png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> - png_ptr->gamma_shift][red>>8]; - png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> - png_ptr->gamma_shift][green>>8]; - png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> - png_ptr->gamma_shift][blue>>8]; - png_uint_16 gray16 = (png_uint_16)((rc * red_1 - + gc * green_1 + bc * blue_1)>>15); - w = png_ptr->gamma_16_from_1[(gray16&0xff) >> - png_ptr->gamma_shift][gray16 >> 8]; - rgb_error |= 1; - } + if(red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + + gc * green_1 + bc * blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } - *(dp++) = (png_byte)((w>>8) & 0xff); - *(dp++) = (png_byte)(w & 0xff); - *(dp++) = *(sp++); /* alpha */ - *(dp++) = *(sp++); - } - } - else + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else #endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, gray16; - red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; - if(red != green || red != blue) - rgb_error |= 1; - gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); - *(dp++) = (png_byte)((gray16>>8) & 0xff); - *(dp++) = (png_byte)(gray16 & 0xff); - *(dp++) = *(sp++); /* alpha */ - *(dp++) = *(sp++); - } - } - } - } + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + if(red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } row_info->channels -= (png_byte)2; - row_info->color_type &= ~PNG_COLOR_MASK_COLOR; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + row_info->color_type &= ~PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); } return rgb_error; } #endif -/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth - * large of png_color. This lets grayscale images be treated as - * paletted. Most useful for gamma correction and simplification - * of code. - */ void PNGAPI png_build_grayscale_palette(int bit_depth, png_colorp palette) { @@ -221971,41 +200619,40 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette) png_debug(1, "in png_do_build_grayscale_palette\n"); if (palette == NULL) - return; + return; switch (bit_depth) { - case 1: - num_palette = 2; - color_inc = 0xff; - break; - case 2: - num_palette = 4; - color_inc = 0x55; - break; - case 4: - num_palette = 16; - color_inc = 0x11; - break; - case 8: - num_palette = 256; - color_inc = 1; - break; - default: - num_palette = 0; - color_inc = 0; - break; + case 1: + num_palette = 2; + color_inc = 0xff; + break; + case 2: + num_palette = 4; + color_inc = 0x55; + break; + case 4: + num_palette = 16; + color_inc = 0x11; + break; + case 8: + num_palette = 256; + color_inc = 1; + break; + default: + num_palette = 0; + color_inc = 0; + break; } for (i = 0, v = 0; i < num_palette; i++, v += color_inc) { - palette[i].red = (png_byte)v; - palette[i].green = (png_byte)v; - palette[i].blue = (png_byte)v; + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; } } -/* This function is currently unused. Do we really need it? */ #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED) void /* PRIVATE */ png_correct_palette(png_structp png_ptr, png_colorp palette, @@ -222013,126 +200660,126 @@ png_correct_palette(png_structp png_ptr, png_colorp palette, { png_debug(1, "in png_correct_palette\n"); #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) { - png_color back, back_1; + png_color back, back_1; - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) - { - back.red = png_ptr->gamma_table[png_ptr->background.red]; - back.green = png_ptr->gamma_table[png_ptr->background.green]; - back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; - back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; - back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; - back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; - } - else - { - double g; + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g; - g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); + g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || - fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) - { - back.red = png_ptr->background.red; - back.green = png_ptr->background.green; - back.blue = png_ptr->background.blue; - } - else - { - back.red = - (png_byte)(pow((double)png_ptr->background.red/255, g) * - 255.0 + 0.5); - back.green = - (png_byte)(pow((double)png_ptr->background.green/255, g) * - 255.0 + 0.5); - back.blue = - (png_byte)(pow((double)png_ptr->background.blue/255, g) * - 255.0 + 0.5); - } + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || + fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = png_ptr->background.red; + back.green = png_ptr->background.green; + back.blue = png_ptr->background.blue; + } + else + { + back.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } - g = 1.0 / png_ptr->background_gamma; + g = 1.0 / png_ptr->background_gamma; - back_1.red = - (png_byte)(pow((double)png_ptr->background.red/255, g) * - 255.0 + 0.5); - back_1.green = - (png_byte)(pow((double)png_ptr->background.green/255, g) * - 255.0 + 0.5); - back_1.blue = - (png_byte)(pow((double)png_ptr->background.blue/255, g) * - 255.0 + 0.5); - } + back_1.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back_1.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back_1.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_uint_32 i; + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_uint_32 i; - for (i = 0; i < (png_uint_32)num_palette; i++) - { - if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) - { - palette[i] = back; - } - else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) - { - png_byte v, w; + for (i = 0; i < (png_uint_32)num_palette; i++) + { + if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + png_byte v, w; - v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; - png_composite(w, v, png_ptr->trans[i], back_1.red); - palette[i].red = png_ptr->gamma_from_1[w]; + v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; - v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; - png_composite(w, v, png_ptr->trans[i], back_1.green); - palette[i].green = png_ptr->gamma_from_1[w]; + v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; - v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; - png_composite(w, v, png_ptr->trans[i], back_1.blue); - palette[i].blue = png_ptr->gamma_from_1[w]; - } - else - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } - else - { - int i; + v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + else + { + int i; - for (i = 0; i < num_palette; i++) - { - if (palette[i].red == (png_byte)png_ptr->trans_values.gray) - { - palette[i] = back; - } - else - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } + for (i = 0; i < num_palette; i++) + { + if (palette[i].red == (png_byte)png_ptr->trans_values.gray) + { + palette[i] = back; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } } else #endif #if defined(PNG_READ_GAMMA_SUPPORTED) if (png_ptr->transformations & PNG_GAMMA) { - int i; + int i; - for (i = 0; i < num_palette; i++) - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } } #if defined(PNG_READ_BACKGROUND_SUPPORTED) else @@ -222141,57 +200788,53 @@ png_correct_palette(png_structp png_ptr, png_colorp palette, #if defined(PNG_READ_BACKGROUND_SUPPORTED) if (png_ptr->transformations & PNG_BACKGROUND) { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_color back; + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_color back; - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; - for (i = 0; i < (int)png_ptr->num_trans; i++) - { - if (png_ptr->trans[i] == 0) - { - palette[i].red = back.red; - palette[i].green = back.green; - palette[i].blue = back.blue; - } - else if (png_ptr->trans[i] != 0xff) - { - png_composite(palette[i].red, png_ptr->palette[i].red, - png_ptr->trans[i], back.red); - png_composite(palette[i].green, png_ptr->palette[i].green, - png_ptr->trans[i], back.green); - png_composite(palette[i].blue, png_ptr->palette[i].blue, - png_ptr->trans[i], back.blue); - } - } - } - else /* assume grayscale palette (what else could it be?) */ - { - int i; + for (i = 0; i < (int)png_ptr->num_trans; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i].red = back.red; + palette[i].green = back.green; + palette[i].blue = back.blue; + } + else if (png_ptr->trans[i] != 0xff) + { + png_composite(palette[i].red, png_ptr->palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, png_ptr->palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, png_ptr->palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + } + else /* assume grayscale palette (what else could it be?) */ + { + int i; - for (i = 0; i < num_palette; i++) - { - if (i == (png_byte)png_ptr->trans_values.gray) - { - palette[i].red = (png_byte)png_ptr->background.red; - palette[i].green = (png_byte)png_ptr->background.green; - palette[i].blue = (png_byte)png_ptr->background.blue; - } - } - } + for (i = 0; i < num_palette; i++) + { + if (i == (png_byte)png_ptr->trans_values.gray) + { + palette[i].red = (png_byte)png_ptr->background.red; + palette[i].green = (png_byte)png_ptr->background.green; + palette[i].blue = (png_byte)png_ptr->background.blue; + } + } + } } #endif } #endif #if defined(PNG_READ_BACKGROUND_SUPPORTED) -/* Replace any alpha or transparency with the supplied background color. - * "background" is already in the screen gamma, while "background_1" is - * at a gamma of 1.0. Paletted files have already been taken care of. - */ void /* PRIVATE */ png_do_background(png_row_infop row_info, png_bytep row, png_color_16p trans_values, png_color_16p background @@ -222211,676 +200854,664 @@ png_do_background(png_row_infop row_info, png_bytep row, png_debug(1, "in png_do_background\n"); if (background != NULL && #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || - (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) + (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || + (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) { - switch (row_info->color_type) - { - case PNG_COLOR_TYPE_GRAY: - { - switch (row_info->bit_depth) - { - case 1: - { - sp = row; - shift = 7; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x01) - == trans_values->gray) - { - *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - if (!shift) - { - shift = 7; - sp++; - } - else - shift--; - } - break; - } - case 2: - { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == trans_values->gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 7; + sp++; + } + else + shift--; + } + break; + } + case 2: + { #if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == trans_values->gray) - { - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - else - { - png_byte p = (png_byte)((*sp >> shift) & 0x03); - png_byte g = (png_byte)((gamma_table [p | (p << 2) | - (p << 4) | (p << 6)] >> 6) & 0x03); - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(g << shift); - } - if (!shift) - { - shift = 6; - sp++; - } - else - shift -= 2; - } - } - else + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x03); + png_byte g = (png_byte)((gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03); + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + else #endif - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == trans_values->gray) - { - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - if (!shift) - { - shift = 6; - sp++; - } - else - shift -= 2; - } - } - break; - } - case 4: - { + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + break; + } + case 4: + { #if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == trans_values->gray) - { - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - else - { - png_byte p = (png_byte)((*sp >> shift) & 0x0f); - png_byte g = (png_byte)((gamma_table[p | - (p << 4)] >> 4) & 0x0f); - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(g << shift); - } - if (!shift) - { - shift = 4; - sp++; - } - else - shift -= 4; - } - } - else + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x0f); + png_byte g = (png_byte)((gamma_table[p | + (p << 4)] >> 4) & 0x0f); + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + else #endif - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == trans_values->gray) - { - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - if (!shift) - { - shift = 4; - sp++; - } - else - shift -= 4; - } - } - break; - } - case 8: - { + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + break; + } + case 8: + { #if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == trans_values->gray) - { - *sp = (png_byte)background->gray; - } - else - { - *sp = gamma_table[*sp]; - } - } - } - else + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + else + { + *sp = gamma_table[*sp]; + } + } + } + else #endif - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == trans_values->gray) - { - *sp = (png_byte)background->gray; - } - } - } - break; - } - case 16: - { + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + } + } + break; + } + case 16: + { #if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == trans_values->gray) - { - /* background is already in screen gamma */ - *sp = (png_byte)((background->gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->gray & 0xff); - } - else - { - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - } - } - else + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else #endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == trans_values->gray) - { - *sp = (png_byte)((background->gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->gray & 0xff); - } - } - } - break; - } - } - break; - } - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) - { + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + } + } + break; + } + } + break; + } + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { #if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 3) - { - if (*sp == trans_values->red && - *(sp + 1) == trans_values->green && - *(sp + 2) == trans_values->blue) - { - *sp = (png_byte)background->red; - *(sp + 1) = (png_byte)background->green; - *(sp + 2) = (png_byte)background->blue; - } - else - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } - } - } - else + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else #endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 3) - { - if (*sp == trans_values->red && - *(sp + 1) == trans_values->green && - *(sp + 2) == trans_values->blue) - { - *sp = (png_byte)background->red; - *(sp + 1) = (png_byte)background->green; - *(sp + 2) = (png_byte)background->blue; - } - } - } - } - else /* if (row_info->bit_depth == 16) */ - { + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { #if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); - if (r == trans_values->red && g == trans_values->green && - b == trans_values->blue) - { - /* background is already in screen gamma */ - *sp = (png_byte)((background->red >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->red & 0xff); - *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(sp + 3) = (png_byte)(background->green & 0xff); - *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(background->blue & 0xff); - } - else - { - png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - } - } - else + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + else #endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); - png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); - if (r == trans_values->red && g == trans_values->green && - b == trans_values->blue) - { - *sp = (png_byte)((background->red >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->red & 0xff); - *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(sp + 3) = (png_byte)(background->green & 0xff); - *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(background->blue & 0xff); - } - } - } - } - break; - } - case PNG_COLOR_TYPE_GRAY_ALPHA: - { - if (row_info->bit_depth == 8) - { + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + } + } + } + break; + } + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { #if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 2, dp++) - { - png_uint_16 a = *(sp + 1); + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_uint_16 a = *(sp + 1); - if (a == 0xff) - { - *dp = gamma_table[*sp]; - } - else if (a == 0) - { - /* background is already in screen gamma */ - *dp = (png_byte)background->gray; - } - else - { - png_byte v, w; + if (a == 0xff) + { + *dp = gamma_table[*sp]; + } + else if (a == 0) + { + *dp = (png_byte)background->gray; + } + else + { + png_byte v, w; - v = gamma_to_1[*sp]; - png_composite(w, v, a, background_1->gray); - *dp = gamma_from_1[w]; - } - } - } - else + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->gray); + *dp = gamma_from_1[w]; + } + } + } + else #endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 2, dp++) - { - png_byte a = *(sp + 1); + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_byte a = *(sp + 1); - if (a == 0xff) - { - *dp = *sp; - } + if (a == 0xff) + { + *dp = *sp; + } #if defined(PNG_READ_GAMMA_SUPPORTED) - else if (a == 0) - { - *dp = (png_byte)background->gray; - } - else - { - png_composite(*dp, *sp, a, background_1->gray); - } + else if (a == 0) + { + *dp = (png_byte)background->gray; + } + else + { + png_composite(*dp, *sp, a, background_1->gray); + } #else - *dp = (png_byte)background->gray; + *dp = (png_byte)background->gray; #endif - } - } - } - else /* if (png_ptr->bit_depth == 16) */ - { + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { #if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 2) - { - png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - } + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } #if defined(PNG_READ_GAMMA_SUPPORTED) - else if (a == 0) + else if (a == 0) #else - else + else #endif - { - /* background is already in screen gamma */ - *dp = (png_byte)((background->gray >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->gray & 0xff); - } + { + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } #if defined(PNG_READ_GAMMA_SUPPORTED) - else - { - png_uint_16 g, v, w; + else + { + png_uint_16 g, v, w; - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, background_1->gray); - w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; - *dp = (png_byte)((w >> 8) & 0xff); - *(dp + 1) = (png_byte)(w & 0xff); - } + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, background_1->gray); + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *dp = (png_byte)((w >> 8) & 0xff); + *(dp + 1) = (png_byte)(w & 0xff); + } #endif - } - } - else + } + } + else #endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 2) - { - png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - if (a == (png_uint_16)0xffff) - { - png_memcpy(dp, sp, 2); - } + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 2); + } #if defined(PNG_READ_GAMMA_SUPPORTED) - else if (a == 0) + else if (a == 0) #else - else + else #endif - { - *dp = (png_byte)((background->gray >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->gray & 0xff); - } + { + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } #if defined(PNG_READ_GAMMA_SUPPORTED) - else - { - png_uint_16 g, v; + else + { + png_uint_16 g, v; - g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, background_1->gray); - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - } + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, background_1->gray); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } #endif - } - } - } - break; - } - case PNG_COLOR_TYPE_RGB_ALPHA: - { - if (row_info->bit_depth == 8) - { + } + } + } + break; + } + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { #if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 3) - { - png_byte a = *(sp + 3); + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); - if (a == 0xff) - { - *dp = gamma_table[*sp]; - *(dp + 1) = gamma_table[*(sp + 1)]; - *(dp + 2) = gamma_table[*(sp + 2)]; - } - else if (a == 0) - { - /* background is already in screen gamma */ - *dp = (png_byte)background->red; - *(dp + 1) = (png_byte)background->green; - *(dp + 2) = (png_byte)background->blue; - } - else - { - png_byte v, w; + if (a == 0xff) + { + *dp = gamma_table[*sp]; + *(dp + 1) = gamma_table[*(sp + 1)]; + *(dp + 2) = gamma_table[*(sp + 2)]; + } + else if (a == 0) + { + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_byte v, w; - v = gamma_to_1[*sp]; - png_composite(w, v, a, background_1->red); - *dp = gamma_from_1[w]; - v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, background_1->green); - *(dp + 1) = gamma_from_1[w]; - v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, background_1->blue); - *(dp + 2) = gamma_from_1[w]; - } - } - } - else + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->red); + *dp = gamma_from_1[w]; + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, background_1->green); + *(dp + 1) = gamma_from_1[w]; + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, background_1->blue); + *(dp + 2) = gamma_from_1[w]; + } + } + } + else #endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 3) - { - png_byte a = *(sp + 3); + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); - if (a == 0xff) - { - *dp = *sp; - *(dp + 1) = *(sp + 1); - *(dp + 2) = *(sp + 2); - } - else if (a == 0) - { - *dp = (png_byte)background->red; - *(dp + 1) = (png_byte)background->green; - *(dp + 2) = (png_byte)background->blue; - } - else - { - png_composite(*dp, *sp, a, background->red); - png_composite(*(dp + 1), *(sp + 1), a, - background->green); - png_composite(*(dp + 2), *(sp + 2), a, - background->blue); - } - } - } - } - else /* if (row_info->bit_depth == 16) */ - { + if (a == 0xff) + { + *dp = *sp; + *(dp + 1) = *(sp + 1); + *(dp + 2) = *(sp + 2); + } + else if (a == 0) + { + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_composite(*dp, *sp, a, background->red); + png_composite(*(dp + 1), *(sp + 1), a, + background->green); + png_composite(*(dp + 2), *(sp + 2), a, + background->blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { #if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 8, dp += 6) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(dp + 2) = (png_byte)((v >> 8) & 0xff); - *(dp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(dp + 4) = (png_byte)((v >> 8) & 0xff); - *(dp + 5) = (png_byte)(v & 0xff); - } - else if (a == 0) - { - /* background is already in screen gamma */ - *dp = (png_byte)((background->red >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->red & 0xff); - *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(dp + 3) = (png_byte)(background->green & 0xff); - *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(dp + 5) = (png_byte)(background->blue & 0xff); - } - else - { - png_uint_16 v, w, x; + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + else if (a == 0) + { + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v, w, x; - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, background_1->red); - x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - *dp = (png_byte)((x >> 8) & 0xff); - *(dp + 1) = (png_byte)(x & 0xff); - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, background_1->green); - x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - *(dp + 2) = (png_byte)((x >> 8) & 0xff); - *(dp + 3) = (png_byte)(x & 0xff); - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, background_1->blue); - x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; - *(dp + 4) = (png_byte)((x >> 8) & 0xff); - *(dp + 5) = (png_byte)(x & 0xff); - } - } - } - else + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, background_1->red); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *dp = (png_byte)((x >> 8) & 0xff); + *(dp + 1) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, background_1->green); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *(dp + 2) = (png_byte)((x >> 8) & 0xff); + *(dp + 3) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, background_1->blue); + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; + *(dp + 4) = (png_byte)((x >> 8) & 0xff); + *(dp + 5) = (png_byte)(x & 0xff); + } + } + } + else #endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 8, dp += 6) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - if (a == (png_uint_16)0xffff) - { - png_memcpy(dp, sp, 6); - } - else if (a == 0) - { - *dp = (png_byte)((background->red >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->red & 0xff); - *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(dp + 3) = (png_byte)(background->green & 0xff); - *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(dp + 5) = (png_byte)(background->blue & 0xff); - } - else - { - png_uint_16 v; + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 6); + } + else if (a == 0) + { + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v; - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); - png_composite_16(v, r, a, background->red); - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - png_composite_16(v, g, a, background->green); - *(dp + 2) = (png_byte)((v >> 8) & 0xff); - *(dp + 3) = (png_byte)(v & 0xff); - png_composite_16(v, b, a, background->blue); - *(dp + 4) = (png_byte)((v >> 8) & 0xff); - *(dp + 5) = (png_byte)(v & 0xff); - } - } - } - } - break; - } - } + png_composite_16(v, r, a, background->red); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, background->green); + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, b, a, background->blue); + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + } - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; - row_info->channels--; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + row_info->channels--; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } } } #endif #if defined(PNG_READ_GAMMA_SUPPORTED) -/* Gamma correct the image, avoiding the alpha channel. Make sure - * you do this after you deal with the transparency issue on grayscale - * or RGB images. If your bit depth is 8, use gamma_table, if it - * is 16, use gamma_16_table and gamma_shift. Build these with - * build_gamma_table(). - */ void /* PRIVATE */ png_do_gamma(png_row_infop row_info, png_bytep row, png_bytep gamma_table, png_uint_16pp gamma_16_table, @@ -222893,176 +201524,173 @@ png_do_gamma(png_row_infop row_info, png_bytep row, png_debug(1, "in png_do_gamma\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - ((row_info->bit_depth <= 8 && gamma_table != NULL) || - (row_info->bit_depth == 16 && gamma_16_table != NULL))) + ((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) { - switch (row_info->color_type) - { - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - } - } - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v; + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - } - } - break; - } - case PNG_COLOR_TYPE_RGB_ALPHA: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - sp++; - } - } - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 4; - } - } - break; - } - case PNG_COLOR_TYPE_GRAY_ALPHA: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp += 2; - } - } - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 4; - } - } - break; - } - case PNG_COLOR_TYPE_GRAY: - { - if (row_info->bit_depth == 2) - { - sp = row; - for (i = 0; i < row_width; i += 4) - { - int a = *sp & 0xc0; - int b = *sp & 0x30; - int c = *sp & 0x0c; - int d = *sp & 0x03; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; - *sp = (png_byte)( - ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| - ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| - ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| - ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); - sp++; - } - } - if (row_info->bit_depth == 4) - { - sp = row; - for (i = 0; i < row_width; i += 2) - { - int msb = *sp & 0xf0; - int lsb = *sp & 0x0f; + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; - *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) - | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); - sp++; - } - } - else if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - } - } - else if (row_info->bit_depth == 16) - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - } - } - break; - } - } + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + } } } #endif #if defined(PNG_READ_EXPAND_SUPPORTED) -/* Expands a palette row to an RGB or RGBA row depending - * upon whether you supply trans and num_trans. - */ void /* PRIVATE */ png_do_expand_palette(png_row_infop row_info, png_bytep row, png_colorp palette, png_bytep trans, int num_trans) @@ -223075,137 +201703,134 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, png_debug(1, "in png_do_expand_palette\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - row_info->color_type == PNG_COLOR_TYPE_PALETTE) + row_info->color_type == PNG_COLOR_TYPE_PALETTE) { - if (row_info->bit_depth < 8) - { - switch (row_info->bit_depth) - { - case 1: - { - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 1; - else - *dp = 0; - if (shift == 7) - { - shift = 0; - sp--; - } - else - shift++; + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; - dp--; - } - break; - } - case 2: - { - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)value; - if (shift == 6) - { - shift = 0; - sp--; - } - else - shift += 2; + dp--; + } + break; + } + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; - dp--; - } - break; - } - case 4: - { - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((row_width & 0x01) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)value; - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift += 4; + dp--; + } + break; + } + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift += 4; - dp--; - } - break; - } - } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - switch (row_info->bit_depth) - { - case 8: - { - if (trans != NULL) - { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 2) - 1; + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + switch (row_info->bit_depth) + { + case 8: + { + if (trans != NULL) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; - for (i = 0; i < row_width; i++) - { - if ((int)(*sp) >= num_trans) - *dp-- = 0xff; - else - *dp-- = trans[*sp]; - *dp-- = palette[*sp].blue; - *dp-- = palette[*sp].green; - *dp-- = palette[*sp].red; - sp--; - } - row_info->bit_depth = 8; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - row_info->color_type = 6; - row_info->channels = 4; - } - else - { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width * 3) - 1; + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + else + *dp-- = trans[*sp]; + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; - for (i = 0; i < row_width; i++) - { - *dp-- = palette[*sp].blue; - *dp-- = palette[*sp].green; - *dp-- = palette[*sp].red; - sp--; - } - row_info->bit_depth = 8; - row_info->pixel_depth = 24; - row_info->rowbytes = row_width * 3; - row_info->color_type = 2; - row_info->channels = 3; - } - break; - } - } + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + break; + } + } } } -/* If the bit depth < 8, it is expanded to 8. Also, if the already - * expanded transparency value is supplied, an alpha channel is built. - */ void /* PRIVATE */ png_do_expand(png_row_infop row_info, png_bytep row, png_color_16p trans_value) @@ -223220,194 +201845,194 @@ png_do_expand(png_row_infop row_info, png_bytep row, if (row != NULL && row_info != NULL) #endif { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); - if (row_info->bit_depth < 8) - { - switch (row_info->bit_depth) - { - case 1: - { - gray = (png_uint_16)((gray&0x01)*0xff); - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 0xff; - else - *dp = 0; - if (shift == 7) - { - shift = 0; - sp--; - } - else - shift++; + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (png_uint_16)((gray&0x01)*0xff); + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; - dp--; - } - break; - } - case 2: - { - gray = (png_uint_16)((gray&0x03)*0x55); - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)(value | (value << 2) | (value << 4) | - (value << 6)); - if (shift == 6) - { - shift = 0; - sp--; - } - else - shift += 2; + dp--; + } + break; + } + case 2: + { + gray = (png_uint_16)((gray&0x03)*0x55); + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; - dp--; - } - break; - } - case 4: - { - gray = (png_uint_16)((gray&0x0f)*0x11); - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)(value | (value << 4)); - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift = 4; + dp--; + } + break; + } + case 4: + { + gray = (png_uint_16)((gray&0x0f)*0x11); + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; - dp--; - } - break; - } - } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } - if (trans_value != NULL) - { - if (row_info->bit_depth == 8) - { - gray = gray & 0xff; - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 1) - 1; - for (i = 0; i < row_width; i++) - { - if (*sp == gray) - *dp-- = 0; - else - *dp-- = 0xff; - *dp-- = *sp--; - } - } - else if (row_info->bit_depth == 16) - { - png_byte gray_high = (gray >> 8) & 0xff; - png_byte gray_low = gray & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (row_info->rowbytes << 1) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp-1) == gray_high && *(sp) == gray_low) - { - *dp-- = 0; - *dp-- = 0; - } - else - { - *dp-- = 0xff; - *dp-- = 0xff; - } - *dp-- = *sp--; - *dp-- = *sp--; - } - } - row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; - row_info->channels = 2; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_width); - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) - { - if (row_info->bit_depth == 8) - { - png_byte red = trans_value->red & 0xff; - png_byte green = trans_value->green & 0xff; - png_byte blue = trans_value->blue & 0xff; - sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 2) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) - *dp-- = 0; - else - *dp-- = 0xff; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - } - } - else if (row_info->bit_depth == 16) - { - png_byte red_high = (trans_value->red >> 8) & 0xff; - png_byte green_high = (trans_value->green >> 8) & 0xff; - png_byte blue_high = (trans_value->blue >> 8) & 0xff; - png_byte red_low = trans_value->red & 0xff; - png_byte green_low = trans_value->green & 0xff; - png_byte blue_low = trans_value->blue & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 3) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp - 5) == red_high && - *(sp - 4) == red_low && - *(sp - 3) == green_high && - *(sp - 2) == green_low && - *(sp - 1) == blue_high && - *(sp ) == blue_low) - { - *dp-- = 0; - *dp-- = 0; - } - else - { - *dp-- = 0xff; - *dp-- = 0xff; - } - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - } - } - row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - row_info->channels = 4; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } + if (trans_value != NULL) + { + if (row_info->bit_depth == 8) + { + gray = gray & 0xff; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte gray_high = (gray >> 8) & 0xff; + png_byte gray_low = gray & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp-1) == gray_high && *(sp) == gray_low) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) + { + if (row_info->bit_depth == 8) + { + png_byte red = trans_value->red & 0xff; + png_byte green = trans_value->green & 0xff; + png_byte blue = trans_value->blue & 0xff; + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (trans_value->red >> 8) & 0xff; + png_byte green_high = (trans_value->green >> 8) & 0xff; + png_byte blue_high = (trans_value->blue >> 8) & 0xff; + png_byte red_low = trans_value->red & 0xff; + png_byte green_low = trans_value->green & 0xff; + png_byte blue_low = trans_value->blue & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } } } #endif @@ -223415,7 +202040,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, #if defined(PNG_READ_DITHER_SUPPORTED) void /* PRIVATE */ png_do_dither(png_row_infop row_info, png_bytep row, - png_bytep palette_lookup, png_bytep dither_lookup) + png_bytep palette_lookup, png_bytep dither_lookup) { png_bytep sp, dp; png_uint_32 i; @@ -223426,79 +202051,72 @@ png_do_dither(png_row_infop row_info, png_bytep row, if (row != NULL && row_info != NULL) #endif { - if (row_info->color_type == PNG_COLOR_TYPE_RGB && - palette_lookup && row_info->bit_depth == 8) - { - int r, g, b, p; - sp = row; - dp = row; - for (i = 0; i < row_width; i++) - { - r = *sp++; - g = *sp++; - b = *sp++; + if (row_info->color_type == PNG_COLOR_TYPE_RGB && + palette_lookup && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; - /* this looks real messy, but the compiler will reduce - it down to a reasonable formula. For example, with - 5 bits per color, we get: - p = (((r >> 3) & 0x1f) << 10) | - (((g >> 3) & 0x1f) << 5) | - ((b >> 3) & 0x1f); - */ - p = (((r >> (8 - PNG_DITHER_RED_BITS)) & - ((1 << PNG_DITHER_RED_BITS) - 1)) << - (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | - (((g >> (8 - PNG_DITHER_GREEN_BITS)) & - ((1 << PNG_DITHER_GREEN_BITS) - 1)) << - (PNG_DITHER_BLUE_BITS)) | - ((b >> (8 - PNG_DITHER_BLUE_BITS)) & - ((1 << PNG_DITHER_BLUE_BITS) - 1)); + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); - *dp++ = palette_lookup[p]; - } - row_info->color_type = PNG_COLOR_TYPE_PALETTE; - row_info->channels = 1; - row_info->pixel_depth = row_info->bit_depth; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && - palette_lookup != NULL && row_info->bit_depth == 8) - { - int r, g, b, p; - sp = row; - dp = row; - for (i = 0; i < row_width; i++) - { - r = *sp++; - g = *sp++; - b = *sp++; - sp++; + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; - p = (((r >> (8 - PNG_DITHER_RED_BITS)) & - ((1 << PNG_DITHER_RED_BITS) - 1)) << - (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | - (((g >> (8 - PNG_DITHER_GREEN_BITS)) & - ((1 << PNG_DITHER_GREEN_BITS) - 1)) << - (PNG_DITHER_BLUE_BITS)) | - ((b >> (8 - PNG_DITHER_BLUE_BITS)) & - ((1 << PNG_DITHER_BLUE_BITS) - 1)); + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); - *dp++ = palette_lookup[p]; - } - row_info->color_type = PNG_COLOR_TYPE_PALETTE; - row_info->channels = 1; - row_info->pixel_depth = row_info->bit_depth; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && - dither_lookup && row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - *sp = dither_lookup[*sp]; - } - } + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + dither_lookup && row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + *sp = dither_lookup[*sp]; + } + } } } #endif @@ -223508,11 +202126,6 @@ png_do_dither(png_row_infop row_info, png_bytep row, static PNG_CONST int png_gamma_shift[] = {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; -/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit - * tables, we don't make a full table if we are reducing to 8-bit in - * the future. Note also how the gamma_16 tables are segmented so that - * we don't need to allocate > 64K chunks for a full 16-bit table. - */ void /* PRIVATE */ png_build_gamma_table(png_structp png_ptr) { @@ -223520,266 +202133,264 @@ png_build_gamma_table(png_structp png_ptr) if (png_ptr->bit_depth <= 8) { - int i; - double g; + int i; + double g; - if (png_ptr->screen_gamma > .000001) - g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - else - g = 1.0; + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; - png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, - (png_uint_32)256); + png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); - for (i = 0; i < 256; i++) - { - png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, - g) * 255.0 + .5); - } + for (i = 0; i < 256; i++) + { + png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) - { + if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) + { - g = 1.0 / (png_ptr->gamma); + g = 1.0 / (png_ptr->gamma); - png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, - (png_uint_32)256); + png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); - for (i = 0; i < 256; i++) - { - png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, - g) * 255.0 + .5); - } + for (i = 0; i < 256; i++) + { + png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } - png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, - (png_uint_32)256); + png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); - if(png_ptr->screen_gamma > 0.000001) - g = 1.0 / png_ptr->screen_gamma; - else - g = png_ptr->gamma; /* probably doing rgb_to_gray */ + if(png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + else + g = png_ptr->gamma; /* probably doing rgb_to_gray */ - for (i = 0; i < 256; i++) - { - png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, - g) * 255.0 + .5); + for (i = 0; i < 256; i++) + { + png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); - } - } + } + } #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ } else { - double g; - int i, j, shift, num; - int sig_bit; - png_uint_32 ig; + double g; + int i, j, shift, num; + int sig_bit; + png_uint_32 ig; - if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - { - sig_bit = (int)png_ptr->sig_bit.red; - if ((int)png_ptr->sig_bit.green > sig_bit) - sig_bit = png_ptr->sig_bit.green; - if ((int)png_ptr->sig_bit.blue > sig_bit) - sig_bit = png_ptr->sig_bit.blue; - } - else - { - sig_bit = (int)png_ptr->sig_bit.gray; - } + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = (int)png_ptr->sig_bit.red; + if ((int)png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + if ((int)png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + { + sig_bit = (int)png_ptr->sig_bit.gray; + } - if (sig_bit > 0) - shift = 16 - sig_bit; - else - shift = 0; + if (sig_bit > 0) + shift = 16 - sig_bit; + else + shift = 0; - if (png_ptr->transformations & PNG_16_TO_8) - { - if (shift < (16 - PNG_MAX_GAMMA_8)) - shift = (16 - PNG_MAX_GAMMA_8); - } + if (png_ptr->transformations & PNG_16_TO_8) + { + if (shift < (16 - PNG_MAX_GAMMA_8)) + shift = (16 - PNG_MAX_GAMMA_8); + } - if (shift > 8) - shift = 8; - if (shift < 0) - shift = 0; + if (shift > 8) + shift = 8; + if (shift < 0) + shift = 0; - png_ptr->gamma_shift = (png_byte)shift; + png_ptr->gamma_shift = (png_byte)shift; - num = (1 << (8 - shift)); + num = (1 << (8 - shift)); - if (png_ptr->screen_gamma > .000001) - g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - else - g = 1.0; + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; - png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, - (png_uint_32)(num * png_sizeof (png_uint_16p))); + png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof (png_uint_16p))); - if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) - { - double fin, fout; - png_uint_32 last, max; + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) + { + double fin, fout; + png_uint_32 last, max; - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); - } + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); + } - g = 1.0 / g; - last = 0; - for (i = 0; i < 256; i++) - { - fout = ((double)i + 0.5) / 256.0; - fin = pow(fout, g); - max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); - while (last <= max) - { - png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] - [(int)(last >> (8 - shift))] = (png_uint_16)( - (png_uint_16)i | ((png_uint_16)i << 8)); - last++; - } - } - while (last < ((png_uint_32)num << 8)) - { - png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] - [(int)(last >> (8 - shift))] = (png_uint_16)65535L; - last++; - } - } - else - { - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); + g = 1.0 / g; + last = 0; + for (i = 0; i < 256; i++) + { + fout = ((double)i + 0.5) / 256.0; + fin = pow(fout, g); + max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); + while (last <= max) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)( + (png_uint_16)i | ((png_uint_16)i << 8)); + last++; + } + } + while (last < ((png_uint_32)num << 8)) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)65535L; + last++; + } + } + else + { + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); - ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); - for (j = 0; j < 256; j++) - { - png_ptr->gamma_16_table[i][j] = - (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / - 65535.0, g) * 65535.0 + .5); - } - } - } + ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_table[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) - { + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) + { - g = 1.0 / (png_ptr->gamma); + g = 1.0 / (png_ptr->gamma); - png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, - (png_uint_32)(num * png_sizeof (png_uint_16p ))); + png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof (png_uint_16p ))); - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); - ig = (((png_uint_32)i * - (png_uint_32)png_gamma_shift[shift]) >> 4); - for (j = 0; j < 256; j++) - { - png_ptr->gamma_16_to_1[i][j] = - (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / - 65535.0, g) * 65535.0 + .5); - } - } + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_to_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } - if(png_ptr->screen_gamma > 0.000001) - g = 1.0 / png_ptr->screen_gamma; - else - g = png_ptr->gamma; /* probably doing rgb_to_gray */ + if(png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + else + g = png_ptr->gamma; /* probably doing rgb_to_gray */ - png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, - (png_uint_32)(num * png_sizeof (png_uint_16p))); + png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * png_sizeof (png_uint_16p))); - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof (png_uint_16))); - ig = (((png_uint_32)i * - (png_uint_32)png_gamma_shift[shift]) >> 4); - for (j = 0; j < 256; j++) - { - png_ptr->gamma_16_from_1[i][j] = - (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / - 65535.0, g) * 65535.0 + .5); - } - } - } + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_from_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ } } #endif -/* To do: install integer version of png_build_gamma_table here */ #endif #if defined(PNG_MNG_FEATURES_SUPPORTED) -/* undoes intrapixel differencing */ void /* PRIVATE */ png_do_read_intrapixel(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_read_intrapixel\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) + (row_info->color_type & PNG_COLOR_MASK_COLOR)) { - int bytes_per_pixel; - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - png_bytep rp; - png_uint_32 i; + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 3; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 4; - else - return; + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); - *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); - } - } - else if (row_info->bit_depth == 16) - { - png_bytep rp; - png_uint_32 i; + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); + *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 6; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 8; - else - return; + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); - png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); - png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); - png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL); - png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL); - *(rp ) = (png_byte)((red >> 8) & 0xff); - *(rp+1) = (png_byte)(red & 0xff); - *(rp+4) = (png_byte)((blue >> 8) & 0xff); - *(rp+5) = (png_byte)(blue & 0xff); - } - } + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); + png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); + png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); + png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } } } #endif /* PNG_MNG_FEATURES_SUPPORTED */ @@ -223787,17 +202398,6 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row) /********* End of inlined file: pngrtran.c *********/ /********* Start of inlined file: pngrutil.c *********/ -/* pngrutil.c - utilities to read a PNG file - * - * Last changed in libpng 1.2.21 [October 4, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file contains routines that are only called from within - * libpng itself during the course of reading an image. - */ #define PNG_INTERNAL @@ -223809,7 +202409,6 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row) #ifdef PNG_FLOATING_POINT_SUPPORTED # if defined(WIN32_WCE_OLD) -/* strtod() function is not supported on WindowsCE */ __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr) { double result = 0; @@ -223820,16 +202419,16 @@ __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **end str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t)); if ( NULL != str ) { - MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); - result = wcstod(str, &end); - len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); - *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); - png_free(png_ptr, str); + MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); + result = wcstod(str, &end); + len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); + *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); + png_free(png_ptr, str); } return result; } # else -# define png_strtod(p,a,b) strtod(a,b) +# define png_strtod(p,a,b) strtod(a,b) # endif #endif @@ -223838,48 +202437,42 @@ png_get_uint_31(png_structp png_ptr, png_bytep buf) { png_uint_32 i = png_get_uint_32(buf); if (i > PNG_UINT_31_MAX) - png_error(png_ptr, "PNG unsigned integer out of range."); + png_error(png_ptr, "PNG unsigned integer out of range."); return (i); } #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ png_uint_32 PNGAPI png_get_uint_32(png_bytep buf) { png_uint_32 i = ((png_uint_32)(*buf) << 24) + - ((png_uint_32)(*(buf + 1)) << 16) + - ((png_uint_32)(*(buf + 2)) << 8) + - (png_uint_32)(*(buf + 3)); + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + (png_uint_32)(*(buf + 3)); return (i); } -/* Grab a signed 32-bit integer from a buffer in big-endian format. The - * data is stored in the PNG file in two's complement format, and it is - * assumed that the machine format for signed integers is the same. */ png_int_32 PNGAPI png_get_int_32(png_bytep buf) { png_int_32 i = ((png_int_32)(*buf) << 24) + - ((png_int_32)(*(buf + 1)) << 16) + - ((png_int_32)(*(buf + 2)) << 8) + - (png_int_32)(*(buf + 3)); + ((png_int_32)(*(buf + 1)) << 16) + + ((png_int_32)(*(buf + 2)) << 8) + + (png_int_32)(*(buf + 3)); return (i); } -/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ png_uint_16 PNGAPI png_get_uint_16(png_bytep buf) { png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + - (png_uint_16)(*(buf + 1))); + (png_uint_16)(*(buf + 1))); return (i); } #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */ -/* Read data, and (optionally) run it through the CRC. */ void /* PRIVATE */ png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) { @@ -223888,10 +202481,6 @@ png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) png_calculate_crc(png_ptr, buf, length); } -/* Optionally skip data and then check the CRC. Depending on whether we - are reading a ancillary or critical chunk, and how the program has set - things up, we may calculate the CRC on the data and print a message. - Returns '1' if there was a CRC error, '0' otherwise. */ int /* PRIVATE */ png_crc_finish(png_structp png_ptr, png_uint_32 skip) { @@ -223900,34 +202489,32 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip) for (i = (png_size_t)skip; i > istop; i -= istop) { - png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); } if (i) { - png_crc_read(png_ptr, png_ptr->zbuf, i); + png_crc_read(png_ptr, png_ptr->zbuf, i); } if (png_crc_error(png_ptr)) { - if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ - !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || - (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ - (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) - { - png_chunk_warning(png_ptr, "CRC error"); - } - else - { - png_chunk_error(png_ptr, "CRC error"); - } - return (1); + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) + { + png_chunk_warning(png_ptr, "CRC error"); + } + else + { + png_chunk_error(png_ptr, "CRC error"); + } + return (1); } return (0); } -/* Compare the CRC stored in the PNG file with that calculated by libpng from - the data it has read thus far. */ int /* PRIVATE */ png_crc_error(png_structp png_ptr) { @@ -223935,42 +202522,35 @@ png_crc_error(png_structp png_ptr) png_uint_32 crc; int need_crc = 1; - if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ { - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == - (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) - need_crc = 0; + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; } - else /* critical */ + else /* critical */ { - if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) - need_crc = 0; + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; } png_read_data(png_ptr, crc_bytes, 4); if (need_crc) { - crc = png_get_uint_32(crc_bytes); - return ((int)(crc != png_ptr->crc)); + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); } else - return (0); + return (0); } #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ - defined(PNG_READ_iCCP_SUPPORTED) -/* - * Decompress trailing data in a chunk. The assumption is that chunkdata - * points at an allocated area holding the contents of a chunk with a - * trailing compressed part. What we get back is an allocated area - * holding the original prefix part and an uncompressed version of the - * trailing part (the malloc area passed in is freed). - */ + defined(PNG_READ_iCCP_SUPPORTED) png_charp /* PRIVATE */ png_decompress_chunk(png_structp png_ptr, int comp_type, - png_charp chunkdata, png_size_t chunklength, - png_size_t prefix_size, png_size_t *newlength) + png_charp chunkdata, png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) { static PNG_CONST char msg[] = "Error decoding compressed text"; png_charp text; @@ -223978,159 +202558,157 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, if (comp_type == PNG_COMPRESSION_TYPE_BASE) { - int ret = Z_OK; - png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size); - png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + int ret = Z_OK; + png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size); + png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - text_size = 0; - text = NULL; + text_size = 0; + text = NULL; - while (png_ptr->zstream.avail_in) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - if (png_ptr->zstream.msg != NULL) - png_warning(png_ptr, png_ptr->zstream.msg); - else - png_warning(png_ptr, msg); - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_warning(png_ptr, png_ptr->zstream.msg); + else + png_warning(png_ptr, msg); + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; - if (text == NULL) - { - text_size = prefix_size + png_sizeof(msg) + 1; - text = (png_charp)png_malloc_warn(png_ptr, text_size); - if (text == NULL) - { - png_free(png_ptr,chunkdata); - png_error(png_ptr,"Not enough memory to decompress chunk"); - } - png_memcpy(text, chunkdata, prefix_size); - } + if (text == NULL) + { + text_size = prefix_size + png_sizeof(msg) + 1; + text = (png_charp)png_malloc_warn(png_ptr, text_size); + if (text == NULL) + { + png_free(png_ptr,chunkdata); + png_error(png_ptr,"Not enough memory to decompress chunk"); + } + png_memcpy(text, chunkdata, prefix_size); + } - text[text_size - 1] = 0x00; + text[text_size - 1] = 0x00; - /* Copy what we can of the error message into the text chunk */ - text_size = (png_size_t)(chunklength - (text - chunkdata) - 1); - text_size = png_sizeof(msg) > text_size ? text_size : - png_sizeof(msg); - png_memcpy(text + prefix_size, msg, text_size + 1); - break; - } - if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) - { - if (text == NULL) - { - text_size = prefix_size + - png_ptr->zbuf_size - png_ptr->zstream.avail_out; - text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); - if (text == NULL) - { - png_free(png_ptr,chunkdata); - png_error(png_ptr,"Not enough memory to decompress chunk."); - } - png_memcpy(text + prefix_size, png_ptr->zbuf, - text_size - prefix_size); - png_memcpy(text, chunkdata, prefix_size); - *(text + text_size) = 0x00; - } - else - { - png_charp tmp; + text_size = (png_size_t)(chunklength - (text - chunkdata) - 1); + text_size = png_sizeof(msg) > text_size ? text_size : + png_sizeof(msg); + png_memcpy(text + prefix_size, msg, text_size + 1); + break; + } + if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) + { + if (text == NULL) + { + text_size = prefix_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out; + text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); + if (text == NULL) + { + png_free(png_ptr,chunkdata); + png_error(png_ptr,"Not enough memory to decompress chunk."); + } + png_memcpy(text + prefix_size, png_ptr->zbuf, + text_size - prefix_size); + png_memcpy(text, chunkdata, prefix_size); + *(text + text_size) = 0x00; + } + else + { + png_charp tmp; - tmp = text; - text = (png_charp)png_malloc_warn(png_ptr, - (png_uint_32)(text_size + - png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); - if (text == NULL) - { - png_free(png_ptr, tmp); - png_free(png_ptr, chunkdata); - png_error(png_ptr,"Not enough memory to decompress chunk.."); - } - png_memcpy(text, tmp, text_size); - png_free(png_ptr, tmp); - png_memcpy(text + text_size, png_ptr->zbuf, - (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); - text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; - *(text + text_size) = 0x00; - } - if (ret == Z_STREAM_END) - break; - else - { - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - } - if (ret != Z_STREAM_END) - { + tmp = text; + text = (png_charp)png_malloc_warn(png_ptr, + (png_uint_32)(text_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); + if (text == NULL) + { + png_free(png_ptr, tmp); + png_free(png_ptr, chunkdata); + png_error(png_ptr,"Not enough memory to decompress chunk.."); + } + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + png_memcpy(text + text_size, png_ptr->zbuf, + (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = 0x00; + } + if (ret == Z_STREAM_END) + break; + else + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + } + if (ret != Z_STREAM_END) + { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char umsg[52]; + char umsg[52]; - if (ret == Z_BUF_ERROR) - png_snprintf(umsg, 52, - "Buffer error in compressed datastream in %s chunk", - png_ptr->chunk_name); - else if (ret == Z_DATA_ERROR) - png_snprintf(umsg, 52, - "Data error in compressed datastream in %s chunk", - png_ptr->chunk_name); - else - png_snprintf(umsg, 52, - "Incomplete compressed datastream in %s chunk", - png_ptr->chunk_name); - png_warning(png_ptr, umsg); + if (ret == Z_BUF_ERROR) + png_snprintf(umsg, 52, + "Buffer error in compressed datastream in %s chunk", + png_ptr->chunk_name); + else if (ret == Z_DATA_ERROR) + png_snprintf(umsg, 52, + "Data error in compressed datastream in %s chunk", + png_ptr->chunk_name); + else + png_snprintf(umsg, 52, + "Incomplete compressed datastream in %s chunk", + png_ptr->chunk_name); + png_warning(png_ptr, umsg); #else - png_warning(png_ptr, - "Incomplete compressed datastream in chunk other than IDAT"); + png_warning(png_ptr, + "Incomplete compressed datastream in chunk other than IDAT"); #endif - text_size=prefix_size; - if (text == NULL) - { - text = (png_charp)png_malloc_warn(png_ptr, text_size+1); - if (text == NULL) - { - png_free(png_ptr, chunkdata); - png_error(png_ptr,"Not enough memory for text."); - } - png_memcpy(text, chunkdata, prefix_size); - } - *(text + text_size) = 0x00; - } + text_size=prefix_size; + if (text == NULL) + { + text = (png_charp)png_malloc_warn(png_ptr, text_size+1); + if (text == NULL) + { + png_free(png_ptr, chunkdata); + png_error(png_ptr,"Not enough memory for text."); + } + png_memcpy(text, chunkdata, prefix_size); + } + *(text + text_size) = 0x00; + } - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; - png_free(png_ptr, chunkdata); - chunkdata = text; - *newlength=text_size; + png_free(png_ptr, chunkdata); + chunkdata = text; + *newlength=text_size; } else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char umsg[50]; + char umsg[50]; - png_snprintf(umsg, 50, - "Unknown zTXt compression type %d", comp_type); - png_warning(png_ptr, umsg); + png_snprintf(umsg, 50, + "Unknown zTXt compression type %d", comp_type); + png_warning(png_ptr, umsg); #else - png_warning(png_ptr, "Unknown zTXt compression type"); + png_warning(png_ptr, "Unknown zTXt compression type"); #endif - *(chunkdata + prefix_size) = 0x00; - *newlength=prefix_size; + *(chunkdata + prefix_size) = 0x00; + *newlength=prefix_size; } return chunkdata; } #endif -/* read and check the IDHR chunk */ void /* PRIVATE */ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { @@ -224142,11 +202720,10 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_IHDR\n"); if (png_ptr->mode & PNG_HAVE_IHDR) - png_error(png_ptr, "Out of place IHDR"); + png_error(png_ptr, "Out of place IHDR"); - /* check the length */ if (length != 13) - png_error(png_ptr, "Invalid IHDR chunk"); + png_error(png_ptr, "Invalid IHDR chunk"); png_ptr->mode |= PNG_HAVE_IHDR; @@ -224161,7 +202738,6 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) filter_type = buf[11]; interlace_type = buf[12]; - /* set internal variables */ png_ptr->width = width; png_ptr->height = height; png_ptr->bit_depth = (png_byte)bit_depth; @@ -224172,25 +202748,23 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #endif png_ptr->compression_type = (png_byte)compression_type; - /* find number of channels */ switch (png_ptr->color_type) { - case PNG_COLOR_TYPE_GRAY: - case PNG_COLOR_TYPE_PALETTE: - png_ptr->channels = 1; - break; - case PNG_COLOR_TYPE_RGB: - png_ptr->channels = 3; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - png_ptr->channels = 2; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - png_ptr->channels = 4; - break; + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; } - /* set up other useful info */ png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * png_ptr->channels); png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); @@ -224198,10 +202772,9 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug1(3,"channels = %d\n", png_ptr->channels); png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes); png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, - color_type, interlace_type, compression_type, filter_type); + color_type, interlace_type, compression_type, filter_type); } -/* read and check the palette */ void /* PRIVATE */ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { @@ -224214,45 +202787,45 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_PLTE\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before PLTE"); + png_error(png_ptr, "Missing IHDR before PLTE"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid PLTE after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid PLTE after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (png_ptr->mode & PNG_HAVE_PLTE) - png_error(png_ptr, "Duplicate PLTE chunk"); + png_error(png_ptr, "Duplicate PLTE chunk"); png_ptr->mode |= PNG_HAVE_PLTE; if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) { - png_warning(png_ptr, - "Ignoring PLTE chunk in grayscale PNG"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, + "Ignoring PLTE chunk in grayscale PNG"); + png_crc_finish(png_ptr, length); + return; } #if !defined(PNG_READ_OPT_PLTE_SUPPORTED) if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) { - png_crc_finish(png_ptr, length); - return; + png_crc_finish(png_ptr, length); + return; } #endif if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) { - if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - { - png_warning(png_ptr, "Invalid palette chunk"); - png_crc_finish(png_ptr, length); - return; - } - else - { - png_error(png_ptr, "Invalid palette chunk"); - } + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_warning(png_ptr, "Invalid palette chunk"); + png_crc_finish(png_ptr, length); + return; + } + else + { + png_error(png_ptr, "Invalid palette chunk"); + } } num = (int)length / 3; @@ -224260,60 +202833,50 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #ifndef PNG_NO_POINTER_INDEXING for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) { - png_byte buf[3]; + png_byte buf[3]; - png_crc_read(png_ptr, buf, 3); - pal_ptr->red = buf[0]; - pal_ptr->green = buf[1]; - pal_ptr->blue = buf[2]; + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; } #else for (i = 0; i < num; i++) { - png_byte buf[3]; + png_byte buf[3]; - png_crc_read(png_ptr, buf, 3); - /* don't depend upon png_color being any order */ - palette[i].red = buf[0]; - palette[i].green = buf[1]; - palette[i].blue = buf[2]; + png_crc_read(png_ptr, buf, 3); + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; } #endif - /* If we actually NEED the PLTE chunk (ie for a paletted image), we do - whatever the normal CRC configuration tells us. However, if we - have an RGB image, the PLTE can be considered ancillary, so - we will act as though it is. */ #if !defined(PNG_READ_OPT_PLTE_SUPPORTED) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) #endif { - png_crc_finish(png_ptr, 0); + png_crc_finish(png_ptr, 0); } #if !defined(PNG_READ_OPT_PLTE_SUPPORTED) else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ { - /* If we don't want to use the data from an ancillary chunk, - we have two options: an error abort, or a warning and we - ignore the data in this chunk (which should be OK, since - it's considered ancillary for a RGB or RGBA image). */ - if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) - { - if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) - { - png_chunk_error(png_ptr, "CRC error"); - } - else - { - png_chunk_warning(png_ptr, "CRC error"); - return; - } - } - /* Otherwise, we (optionally) emit a warning and use the chunk. */ - else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) - { - png_chunk_warning(png_ptr, "CRC error"); - } + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_error(png_ptr, "CRC error"); + } + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } } #endif @@ -224322,19 +202885,19 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #if defined(PNG_READ_tRNS_SUPPORTED) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) - { - if (png_ptr->num_trans > (png_uint_16)num) - { - png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); - png_ptr->num_trans = (png_uint_16)num; - } - if (info_ptr->num_trans > (png_uint_16)num) - { - png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); - info_ptr->num_trans = (png_uint_16)num; - } - } + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + if (png_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); + png_ptr->num_trans = (png_uint_16)num; + } + if (info_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); + info_ptr->num_trans = (png_uint_16)num; + } + } } #endif @@ -224347,14 +202910,14 @@ png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) { - png_error(png_ptr, "No image in file"); + png_error(png_ptr, "No image in file"); } png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); if (length != 0) { - png_warning(png_ptr, "Incorrect IEND chunk length"); + png_warning(png_ptr, "Incorrect IEND chunk length"); } png_crc_finish(png_ptr, length); @@ -224374,67 +202937,65 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_gAMA\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before gAMA"); + png_error(png_ptr, "Missing IHDR before gAMA"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid gAMA after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid gAMA after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place gAMA chunk"); + png_warning(png_ptr, "Out of place gAMA chunk"); if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) #if defined(PNG_READ_sRGB_SUPPORTED) - && !(info_ptr->valid & PNG_INFO_sRGB) + && !(info_ptr->valid & PNG_INFO_sRGB) #endif - ) + ) { - png_warning(png_ptr, "Duplicate gAMA chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate gAMA chunk"); + png_crc_finish(png_ptr, length); + return; } if (length != 4) { - png_warning(png_ptr, "Incorrect gAMA chunk length"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Incorrect gAMA chunk length"); + png_crc_finish(png_ptr, length); + return; } png_crc_read(png_ptr, buf, 4); if (png_crc_finish(png_ptr, 0)) - return; + return; igamma = (png_fixed_point)png_get_uint_32(buf); - /* check for zero gamma */ if (igamma == 0) - { - png_warning(png_ptr, - "Ignoring gAMA chunk with gamma=0"); - return; - } + { + png_warning(png_ptr, + "Ignoring gAMA chunk with gamma=0"); + return; + } #if defined(PNG_READ_sRGB_SUPPORTED) if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) - if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) - { - png_warning(png_ptr, - "Ignoring incorrect gAMA value when sRGB is also present"); + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); #ifndef PNG_NO_CONSOLE_IO - fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma); + fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma); #endif - return; - } + return; + } #endif /* PNG_READ_sRGB_SUPPORTED */ #ifdef PNG_FLOATING_POINT_SUPPORTED file_gamma = (float)igamma / (float)100000.0; # ifdef PNG_READ_GAMMA_SUPPORTED - png_ptr->gamma = file_gamma; + png_ptr->gamma = file_gamma; # endif - png_set_gAMA(png_ptr, info_ptr, file_gamma); + png_set_gAMA(png_ptr, info_ptr, file_gamma); #endif #ifdef PNG_FIXED_POINT_SUPPORTED png_set_gAMA_fixed(png_ptr, info_ptr, igamma); @@ -224454,55 +203015,54 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) buf[0] = buf[1] = buf[2] = buf[3] = 0; if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sBIT"); + png_error(png_ptr, "Missing IHDR before sBIT"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid sBIT after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid sBIT after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (png_ptr->mode & PNG_HAVE_PLTE) { - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place sBIT chunk"); + png_warning(png_ptr, "Out of place sBIT chunk"); } if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) { - png_warning(png_ptr, "Duplicate sBIT chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate sBIT chunk"); + png_crc_finish(png_ptr, length); + return; } if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - truelen = 3; + truelen = 3; else - truelen = (png_size_t)png_ptr->channels; + truelen = (png_size_t)png_ptr->channels; if (length != truelen || length > 4) { - png_warning(png_ptr, "Incorrect sBIT chunk length"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Incorrect sBIT chunk length"); + png_crc_finish(png_ptr, length); + return; } png_crc_read(png_ptr, buf, truelen); if (png_crc_finish(png_ptr, 0)) - return; + return; if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) { - png_ptr->sig_bit.red = buf[0]; - png_ptr->sig_bit.green = buf[1]; - png_ptr->sig_bit.blue = buf[2]; - png_ptr->sig_bit.alpha = buf[3]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; } else { - png_ptr->sig_bit.gray = buf[0]; - png_ptr->sig_bit.red = buf[0]; - png_ptr->sig_bit.green = buf[0]; - png_ptr->sig_bit.blue = buf[0]; - png_ptr->sig_bit.alpha = buf[1]; + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; } png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); } @@ -224517,40 +203077,39 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; #endif png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, - int_y_green, int_x_blue, int_y_blue; + int_y_green, int_x_blue, int_y_blue; png_uint_32 uint_x, uint_y; png_debug(1, "in png_handle_cHRM\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before cHRM"); + png_error(png_ptr, "Missing IHDR before cHRM"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid cHRM after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid cHRM after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Missing PLTE before cHRM"); + png_warning(png_ptr, "Missing PLTE before cHRM"); if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) #if defined(PNG_READ_sRGB_SUPPORTED) - && !(info_ptr->valid & PNG_INFO_sRGB) + && !(info_ptr->valid & PNG_INFO_sRGB) #endif - ) + ) { - png_warning(png_ptr, "Duplicate cHRM chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate cHRM chunk"); + png_crc_finish(png_ptr, length); + return; } if (length != 32) { - png_warning(png_ptr, "Incorrect cHRM chunk length"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Incorrect cHRM chunk length"); + png_crc_finish(png_ptr, length); + return; } png_crc_read(png_ptr, buf, 4); @@ -224560,11 +203119,11 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) uint_y = png_get_uint_32(buf); if (uint_x > 80000L || uint_y > 80000L || - uint_x + uint_y > 100000L) + uint_x + uint_y > 100000L) { - png_warning(png_ptr, "Invalid cHRM white point"); - png_crc_finish(png_ptr, 24); - return; + png_warning(png_ptr, "Invalid cHRM white point"); + png_crc_finish(png_ptr, 24); + return; } int_x_white = (png_fixed_point)uint_x; int_y_white = (png_fixed_point)uint_y; @@ -224577,9 +203136,9 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (uint_x + uint_y > 100000L) { - png_warning(png_ptr, "Invalid cHRM red point"); - png_crc_finish(png_ptr, 16); - return; + png_warning(png_ptr, "Invalid cHRM red point"); + png_crc_finish(png_ptr, 16); + return; } int_x_red = (png_fixed_point)uint_x; int_y_red = (png_fixed_point)uint_y; @@ -224592,9 +203151,9 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (uint_x + uint_y > 100000L) { - png_warning(png_ptr, "Invalid cHRM green point"); - png_crc_finish(png_ptr, 8); - return; + png_warning(png_ptr, "Invalid cHRM green point"); + png_crc_finish(png_ptr, 8); + return; } int_x_green = (png_fixed_point)uint_x; int_y_green = (png_fixed_point)uint_y; @@ -224607,9 +203166,9 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (uint_x + uint_y > 100000L) { - png_warning(png_ptr, "Invalid cHRM blue point"); - png_crc_finish(png_ptr, 0); - return; + png_warning(png_ptr, "Invalid cHRM blue point"); + png_crc_finish(png_ptr, 0); + return; } int_x_blue = (png_fixed_point)uint_x; int_y_blue = (png_fixed_point)uint_y; @@ -224627,48 +203186,48 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #if defined(PNG_READ_sRGB_SUPPORTED) if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) - { - if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || - PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || - PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || - PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || - PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || - PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || - PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || - PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) - { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); + { + if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); #ifndef PNG_NO_CONSOLE_IO #ifdef PNG_FLOATING_POINT_SUPPORTED - fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n", - white_x, white_y, red_x, red_y); - fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n", - green_x, green_y, blue_x, blue_y); + fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n", + white_x, white_y, red_x, red_y); + fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n", + green_x, green_y, blue_x, blue_y); #else - fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", - int_x_white, int_y_white, int_x_red, int_y_red); - fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n", - int_x_green, int_y_green, int_x_blue, int_y_blue); + fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", + int_x_white, int_y_white, int_x_red, int_y_red); + fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n", + int_x_green, int_y_green, int_x_blue, int_y_blue); #endif #endif /* PNG_NO_CONSOLE_IO */ - } - png_crc_finish(png_ptr, 0); - return; - } + } + png_crc_finish(png_ptr, 0); + return; + } #endif /* PNG_READ_sRGB_SUPPORTED */ #ifdef PNG_FLOATING_POINT_SUPPORTED png_set_cHRM(png_ptr, info_ptr, - white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); #endif #ifdef PNG_FIXED_POINT_SUPPORTED png_set_cHRM_fixed(png_ptr, info_ptr, - int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, - int_y_green, int_x_blue, int_y_blue); + int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue); #endif if (png_crc_finish(png_ptr, 0)) - return; + return; } #endif @@ -224682,41 +203241,39 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_sRGB\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sRGB"); + png_error(png_ptr, "Missing IHDR before sRGB"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid sRGB after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid sRGB after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place sRGB chunk"); + png_warning(png_ptr, "Out of place sRGB chunk"); if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) { - png_warning(png_ptr, "Duplicate sRGB chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate sRGB chunk"); + png_crc_finish(png_ptr, length); + return; } if (length != 1) { - png_warning(png_ptr, "Incorrect sRGB chunk length"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Incorrect sRGB chunk length"); + png_crc_finish(png_ptr, length); + return; } png_crc_read(png_ptr, buf, 1); if (png_crc_finish(png_ptr, 0)) - return; + return; intent = buf[0]; - /* check for bad intent */ if (intent >= PNG_sRGB_INTENT_LAST) { - png_warning(png_ptr, "Unknown sRGB intent"); - return; + png_warning(png_ptr, "Unknown sRGB intent"); + return; } #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) @@ -224724,44 +203281,44 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_fixed_point igamma; #ifdef PNG_FIXED_POINT_SUPPORTED - igamma=info_ptr->int_gamma; + igamma=info_ptr->int_gamma; #else # ifdef PNG_FLOATING_POINT_SUPPORTED - igamma=(png_fixed_point)(info_ptr->gamma * 100000.); + igamma=(png_fixed_point)(info_ptr->gamma * 100000.); # endif #endif - if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) - { - png_warning(png_ptr, - "Ignoring incorrect gAMA value when sRGB is also present"); + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); #ifndef PNG_NO_CONSOLE_IO # ifdef PNG_FIXED_POINT_SUPPORTED - fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma); + fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma); # else -# ifdef PNG_FLOATING_POINT_SUPPORTED - fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma); -# endif +# ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma); +# endif # endif #endif - } + } } #endif /* PNG_READ_gAMA_SUPPORTED */ #ifdef PNG_READ_cHRM_SUPPORTED #ifdef PNG_FIXED_POINT_SUPPORTED if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) - if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) - { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); - } + if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } #endif /* PNG_FIXED_POINT_SUPPORTED */ #endif /* PNG_READ_cHRM_SUPPORTED */ @@ -224772,7 +203329,6 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #if defined(PNG_READ_iCCP_SUPPORTED) void /* PRIVATE */ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -/* Note: this does not properly handle chunks that are > 64K under DOS */ { png_charp chunkdata; png_byte compression_type; @@ -224785,30 +203341,29 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_iCCP\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before iCCP"); + png_error(png_ptr, "Missing IHDR before iCCP"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid iCCP after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid iCCP after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place iCCP chunk"); + png_warning(png_ptr, "Out of place iCCP chunk"); if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) { - png_warning(png_ptr, "Duplicate iCCP chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate iCCP chunk"); + png_crc_finish(png_ptr, length); + return; } #ifdef PNG_MAX_MALLOC_64K if (length > (png_uint_32)65535L) { - png_warning(png_ptr, "iCCP chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; + png_warning(png_ptr, "iCCP chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; } #endif @@ -224818,67 +203373,63 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (png_crc_finish(png_ptr, skip)) { - png_free(png_ptr, chunkdata); - return; + png_free(png_ptr, chunkdata); + return; } chunkdata[slength] = 0x00; for (profile = chunkdata; *profile; profile++) - /* empty loop to find end of name */ ; + ; ++profile; - /* there should be at least one zero (the compression type byte) - following the separator, and we should be on it */ if ( profile >= chunkdata + slength - 1) { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "Malformed iCCP chunk"); - return; + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Malformed iCCP chunk"); + return; } - /* compression_type should always be zero */ compression_type = *profile++; if (compression_type) { - png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); - compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 - wrote nonzero) */ + png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); + compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 + wrote nonzero) */ } prefix_length = profile - chunkdata; chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata, - slength, prefix_length, &data_length); + slength, prefix_length, &data_length); profile_length = data_length - prefix_length; if ( prefix_length > data_length || profile_length < 4) { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "Profile size field missing from iCCP chunk"); - return; + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Profile size field missing from iCCP chunk"); + return; } - /* Check the profile_size recorded in the first 32 bits of the ICC profile */ pC = (png_bytep)(chunkdata+prefix_length); profile_size = ((*(pC ))<<24) | - ((*(pC+1))<<16) | - ((*(pC+2))<< 8) | - ((*(pC+3)) ); + ((*(pC+1))<<16) | + ((*(pC+2))<< 8) | + ((*(pC+3)) ); if(profile_size < profile_length) - profile_length = profile_size; + profile_length = profile_size; if(profile_size > profile_length) { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "Ignoring truncated iCCP profile."); - return; + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Ignoring truncated iCCP profile."); + return; } png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type, - chunkdata + prefix_length, profile_length); + chunkdata + prefix_length, profile_length); png_free(png_ptr, chunkdata); } #endif /* PNG_READ_iCCP_SUPPORTED */ @@ -224886,7 +203437,6 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #if defined(PNG_READ_sPLT_SUPPORTED) void /* PRIVATE */ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -/* Note: this does not properly handle chunks that are > 64K under DOS */ { png_bytep chunkdata; png_bytep entry_start; @@ -224901,20 +203451,20 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_sPLT\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sPLT"); + png_error(png_ptr, "Missing IHDR before sPLT"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid sPLT after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid sPLT after IDAT"); + png_crc_finish(png_ptr, length); + return; } #ifdef PNG_MAX_MALLOC_64K if (length > (png_uint_32)65535L) { - png_warning(png_ptr, "sPLT chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; + png_warning(png_ptr, "sPLT chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; } #endif @@ -224924,96 +203474,93 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (png_crc_finish(png_ptr, skip)) { - png_free(png_ptr, chunkdata); - return; + png_free(png_ptr, chunkdata); + return; } chunkdata[slength] = 0x00; for (entry_start = chunkdata; *entry_start; entry_start++) - /* empty loop to find end of name */ ; + ; ++entry_start; - /* a sample depth should follow the separator, and we should be on it */ if (entry_start > chunkdata + slength - 2) { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "malformed sPLT chunk"); - return; + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "malformed sPLT chunk"); + return; } new_palette.depth = *entry_start++; entry_size = (new_palette.depth == 8 ? 6 : 10); data_length = (slength - (entry_start - chunkdata)); - /* integrity-check the data length */ if (data_length % entry_size) { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "sPLT chunk has bad length"); - return; + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "sPLT chunk has bad length"); + return; } new_palette.nentries = (png_int_32) ( data_length / entry_size); if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX / - png_sizeof(png_sPLT_entry))) + png_sizeof(png_sPLT_entry))) { - png_warning(png_ptr, "sPLT chunk too long"); - return; + png_warning(png_ptr, "sPLT chunk too long"); + return; } new_palette.entries = (png_sPLT_entryp)png_malloc_warn( - png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); + png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); if (new_palette.entries == NULL) { - png_warning(png_ptr, "sPLT chunk requires too much memory"); - return; + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; } #ifndef PNG_NO_POINTER_INDEXING for (i = 0; i < new_palette.nentries; i++) { - png_sPLT_entryp pp = new_palette.entries + i; + png_sPLT_entryp pp = new_palette.entries + i; - if (new_palette.depth == 8) - { - pp->red = *entry_start++; - pp->green = *entry_start++; - pp->blue = *entry_start++; - pp->alpha = *entry_start++; - } - else - { - pp->red = png_get_uint_16(entry_start); entry_start += 2; - pp->green = png_get_uint_16(entry_start); entry_start += 2; - pp->blue = png_get_uint_16(entry_start); entry_start += 2; - pp->alpha = png_get_uint_16(entry_start); entry_start += 2; - } - pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; } #else pp = new_palette.entries; for (i = 0; i < new_palette.nentries; i++) { - if (new_palette.depth == 8) - { - pp[i].red = *entry_start++; - pp[i].green = *entry_start++; - pp[i].blue = *entry_start++; - pp[i].alpha = *entry_start++; - } - else - { - pp[i].red = png_get_uint_16(entry_start); entry_start += 2; - pp[i].green = png_get_uint_16(entry_start); entry_start += 2; - pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; - pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; - } - pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; } #endif - /* discard all chunk data except the name and stash that */ new_palette.name = (png_charp)chunkdata; png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); @@ -225032,95 +203579,91 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_tRNS\n"); - /* For non-indexed color, mask off any bits in the tRNS value that - * exceed the bit depth. Some creators were writing extra bits there. - * This is not needed for indexed color. */ bit_mask = (1 << png_ptr->bit_depth) - 1; if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before tRNS"); + png_error(png_ptr, "Missing IHDR before tRNS"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid tRNS after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid tRNS after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) { - png_warning(png_ptr, "Duplicate tRNS chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate tRNS chunk"); + png_crc_finish(png_ptr, length); + return; } if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) { - png_byte buf[2]; + png_byte buf[2]; - if (length != 2) - { - png_warning(png_ptr, "Incorrect tRNS chunk length"); - png_crc_finish(png_ptr, length); - return; - } + if (length != 2) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } - png_crc_read(png_ptr, buf, 2); - png_ptr->num_trans = 1; - png_ptr->trans_values.gray = png_get_uint_16(buf) & bit_mask; + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_values.gray = png_get_uint_16(buf) & bit_mask; } else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) { - png_byte buf[6]; + png_byte buf[6]; - if (length != 6) - { - png_warning(png_ptr, "Incorrect tRNS chunk length"); - png_crc_finish(png_ptr, length); - return; - } - png_crc_read(png_ptr, buf, (png_size_t)length); - png_ptr->num_trans = 1; - png_ptr->trans_values.red = png_get_uint_16(buf) & bit_mask; - png_ptr->trans_values.green = png_get_uint_16(buf + 2) & bit_mask; - png_ptr->trans_values.blue = png_get_uint_16(buf + 4) & bit_mask; + if (length != 6) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, buf, (png_size_t)length); + png_ptr->num_trans = 1; + png_ptr->trans_values.red = png_get_uint_16(buf) & bit_mask; + png_ptr->trans_values.green = png_get_uint_16(buf + 2) & bit_mask; + png_ptr->trans_values.blue = png_get_uint_16(buf + 4) & bit_mask; } else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - if (!(png_ptr->mode & PNG_HAVE_PLTE)) - { - /* Should be an error, but we can cope with it. */ - png_warning(png_ptr, "Missing PLTE before tRNS"); - } - if (length > (png_uint_32)png_ptr->num_palette || - length > PNG_MAX_PALETTE_LENGTH) - { - png_warning(png_ptr, "Incorrect tRNS chunk length"); - png_crc_finish(png_ptr, length); - return; - } - if (length == 0) - { - png_warning(png_ptr, "Zero length tRNS chunk"); - png_crc_finish(png_ptr, length); - return; - } - png_crc_read(png_ptr, readbuf, (png_size_t)length); - png_ptr->num_trans = (png_uint_16)length; + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before tRNS"); + } + if (length > (png_uint_32)png_ptr->num_palette || + length > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + if (length == 0) + { + png_warning(png_ptr, "Zero length tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, readbuf, (png_size_t)length); + png_ptr->num_trans = (png_uint_16)length; } else { - png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); + png_crc_finish(png_ptr, length); + return; } if (png_crc_finish(png_ptr, 0)) { - png_ptr->num_trans = 0; - return; + png_ptr->num_trans = 0; + return; } png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, - &(png_ptr->trans_values)); + &(png_ptr->trans_values)); } #endif @@ -225134,79 +203677,75 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_bKGD\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before bKGD"); + png_error(png_ptr, "Missing IHDR before bKGD"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid bKGD after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid bKGD after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) + !(png_ptr->mode & PNG_HAVE_PLTE)) { - png_warning(png_ptr, "Missing PLTE before bKGD"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Missing PLTE before bKGD"); + png_crc_finish(png_ptr, length); + return; } else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) { - png_warning(png_ptr, "Duplicate bKGD chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate bKGD chunk"); + png_crc_finish(png_ptr, length); + return; } if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - truelen = 1; + truelen = 1; else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - truelen = 6; + truelen = 6; else - truelen = 2; + truelen = 2; if (length != truelen) { - png_warning(png_ptr, "Incorrect bKGD chunk length"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Incorrect bKGD chunk length"); + png_crc_finish(png_ptr, length); + return; } png_crc_read(png_ptr, buf, truelen); if (png_crc_finish(png_ptr, 0)) - return; + return; - /* We convert the index value into RGB components so that we can allow - * arbitrary RGB values for background when we have transparency, and - * so it is easy to determine the RGB values of the background color - * from the info_ptr struct. */ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - png_ptr->background.index = buf[0]; - if(info_ptr->num_palette) - { - if(buf[0] > info_ptr->num_palette) - { - png_warning(png_ptr, "Incorrect bKGD chunk index value"); - return; - } - png_ptr->background.red = - (png_uint_16)png_ptr->palette[buf[0]].red; - png_ptr->background.green = - (png_uint_16)png_ptr->palette[buf[0]].green; - png_ptr->background.blue = - (png_uint_16)png_ptr->palette[buf[0]].blue; - } + png_ptr->background.index = buf[0]; + if(info_ptr->num_palette) + { + if(buf[0] > info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + png_ptr->background.red = + (png_uint_16)png_ptr->palette[buf[0]].red; + png_ptr->background.green = + (png_uint_16)png_ptr->palette[buf[0]].green; + png_ptr->background.blue = + (png_uint_16)png_ptr->palette[buf[0]].blue; + } } else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ { - png_ptr->background.red = - png_ptr->background.green = - png_ptr->background.blue = - png_ptr->background.gray = png_get_uint_16(buf); + png_ptr->background.red = + png_ptr->background.green = + png_ptr->background.blue = + png_ptr->background.gray = png_get_uint_16(buf); } else { - png_ptr->background.red = png_get_uint_16(buf); - png_ptr->background.green = png_get_uint_16(buf + 2); - png_ptr->background.blue = png_get_uint_16(buf + 4); + png_ptr->background.red = png_get_uint_16(buf); + png_ptr->background.green = png_get_uint_16(buf + 2); + png_ptr->background.blue = png_get_uint_16(buf + 4); } png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); @@ -225223,45 +203762,45 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_hIST\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before hIST"); + png_error(png_ptr, "Missing IHDR before hIST"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid hIST after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid hIST after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (!(png_ptr->mode & PNG_HAVE_PLTE)) { - png_warning(png_ptr, "Missing PLTE before hIST"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Missing PLTE before hIST"); + png_crc_finish(png_ptr, length); + return; } else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) { - png_warning(png_ptr, "Duplicate hIST chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate hIST chunk"); + png_crc_finish(png_ptr, length); + return; } num = length / 2 ; if (num != (unsigned int) png_ptr->num_palette || num > - (unsigned int) PNG_MAX_PALETTE_LENGTH) + (unsigned int) PNG_MAX_PALETTE_LENGTH) { - png_warning(png_ptr, "Incorrect hIST chunk length"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; } for (i = 0; i < num; i++) { - png_byte buf[2]; + png_byte buf[2]; - png_crc_read(png_ptr, buf, 2); - readbuf[i] = png_get_uint_16(buf); + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); } if (png_crc_finish(png_ptr, 0)) - return; + return; png_set_hIST(png_ptr, info_ptr, readbuf); } @@ -225278,30 +203817,30 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_pHYs\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before pHYs"); + png_error(png_ptr, "Missing IHDR before pHYs"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid pHYs after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid pHYs after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) { - png_warning(png_ptr, "Duplicate pHYs chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate pHYs chunk"); + png_crc_finish(png_ptr, length); + return; } if (length != 9) { - png_warning(png_ptr, "Incorrect pHYs chunk length"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Incorrect pHYs chunk length"); + png_crc_finish(png_ptr, length); + return; } png_crc_read(png_ptr, buf, 9); if (png_crc_finish(png_ptr, 0)) - return; + return; res_x = png_get_uint_32(buf); res_y = png_get_uint_32(buf + 4); @@ -225321,30 +203860,30 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_oFFs\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before oFFs"); + png_error(png_ptr, "Missing IHDR before oFFs"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid oFFs after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid oFFs after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) { - png_warning(png_ptr, "Duplicate oFFs chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate oFFs chunk"); + png_crc_finish(png_ptr, length); + return; } if (length != 9) { - png_warning(png_ptr, "Incorrect oFFs chunk length"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Incorrect oFFs chunk length"); + png_crc_finish(png_ptr, length); + return; } png_crc_read(png_ptr, buf, 9); if (png_crc_finish(png_ptr, 0)) - return; + return; offset_x = png_get_int_32(buf); offset_y = png_get_int_32(buf + 4); @@ -225354,7 +203893,6 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #endif #if defined(PNG_READ_pCAL_SUPPORTED) -/* read the pCAL chunk (described in the PNG Extensions document) */ void /* PRIVATE */ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { @@ -225369,52 +203907,50 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_pCAL\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before pCAL"); + png_error(png_ptr, "Missing IHDR before pCAL"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid pCAL after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid pCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) { - png_warning(png_ptr, "Duplicate pCAL chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate pCAL chunk"); + png_crc_finish(png_ptr, length); + return; } png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n", - length + 1); + length + 1); purpose = (png_charp)png_malloc_warn(png_ptr, length + 1); if (purpose == NULL) - { - png_warning(png_ptr, "No memory for pCAL purpose."); - return; - } + { + png_warning(png_ptr, "No memory for pCAL purpose."); + return; + } slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)purpose, slength); if (png_crc_finish(png_ptr, 0)) { - png_free(png_ptr, purpose); - return; + png_free(png_ptr, purpose); + return; } purpose[slength] = 0x00; /* null terminate the last string */ png_debug(3, "Finding end of pCAL purpose string\n"); for (buf = purpose; *buf; buf++) - /* empty loop */ ; + ; endptr = purpose + slength; - /* We need to have at least 12 bytes after the purpose string - in order to get the parameter information. */ if (endptr <= buf + 12) { - png_warning(png_ptr, "Invalid pCAL data"); - png_free(png_ptr, purpose); - return; + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, purpose); + return; } png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n"); @@ -225425,56 +203961,52 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) units = buf + 11; png_debug(3, "Checking pCAL equation type and number of parameters\n"); - /* Check that we have the right number of parameters for known - equation types. */ if ((type == PNG_EQUATION_LINEAR && nparams != 2) || - (type == PNG_EQUATION_BASE_E && nparams != 3) || - (type == PNG_EQUATION_ARBITRARY && nparams != 3) || - (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) { - png_warning(png_ptr, "Invalid pCAL parameters for equation type"); - png_free(png_ptr, purpose); - return; + png_warning(png_ptr, "Invalid pCAL parameters for equation type"); + png_free(png_ptr, purpose); + return; } else if (type >= PNG_EQUATION_LAST) { - png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); } for (buf = units; *buf; buf++) - /* Empty loop to move past the units string. */ ; + ; png_debug(3, "Allocating pCAL parameters array\n"); params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams - *png_sizeof(png_charp))) ; + *png_sizeof(png_charp))) ; if (params == NULL) - { - png_free(png_ptr, purpose); - png_warning(png_ptr, "No memory for pCAL params."); - return; - } + { + png_free(png_ptr, purpose); + png_warning(png_ptr, "No memory for pCAL params."); + return; + } - /* Get pointers to the start of each parameter string. */ for (i = 0; i < (int)nparams; i++) { - buf++; /* Skip the null string terminator from previous parameter. */ + buf++; /* Skip the null string terminator from previous parameter. */ - png_debug1(3, "Reading pCAL parameter %d\n", i); - for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) - /* Empty loop to move past each parameter string */ ; + png_debug1(3, "Reading pCAL parameter %d\n", i); + for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) + ; - /* Make sure we haven't run out of data yet */ - if (buf > endptr) - { - png_warning(png_ptr, "Invalid pCAL data"); - png_free(png_ptr, purpose); - png_free(png_ptr, params); - return; - } + if (buf > endptr) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, purpose); + png_free(png_ptr, params); + return; + } } png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams, - units, params); + units, params); png_free(png_ptr, purpose); png_free(png_ptr, params); @@ -225482,7 +204014,6 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #endif #if defined(PNG_READ_sCAL_SUPPORTED) -/* read the sCAL chunk */ void /* PRIVATE */ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { @@ -225500,107 +204031,107 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_sCAL\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sCAL"); + png_error(png_ptr, "Missing IHDR before sCAL"); else if (png_ptr->mode & PNG_HAVE_IDAT) { - png_warning(png_ptr, "Invalid sCAL after IDAT"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Invalid sCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; } else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) { - png_warning(png_ptr, "Duplicate sCAL chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate sCAL chunk"); + png_crc_finish(png_ptr, length); + return; } png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n", - length + 1); + length + 1); buffer = (png_charp)png_malloc_warn(png_ptr, length + 1); if (buffer == NULL) - { - png_warning(png_ptr, "Out of memory while processing sCAL chunk"); - return; - } + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk"); + return; + } slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)buffer, slength); if (png_crc_finish(png_ptr, 0)) { - png_free(png_ptr, buffer); - return; + png_free(png_ptr, buffer); + return; } buffer[slength] = 0x00; /* null terminate the last string */ - ep = buffer + 1; /* skip unit byte */ + ep = buffer + 1; /* skip unit byte */ #ifdef PNG_FLOATING_POINT_SUPPORTED width = png_strtod(png_ptr, ep, &vp); if (*vp) { - png_warning(png_ptr, "malformed width string in sCAL chunk"); - return; + png_warning(png_ptr, "malformed width string in sCAL chunk"); + return; } #else #ifdef PNG_FIXED_POINT_SUPPORTED swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); if (swidth == NULL) - { - png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); - return; - } + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); + return; + } png_memcpy(swidth, ep, (png_size_t)png_strlen(ep)); #endif #endif for (ep = buffer; *ep; ep++) - /* empty loop */ ; + ; ep++; if (buffer + slength < ep) { - png_warning(png_ptr, "Truncated sCAL chunk"); + png_warning(png_ptr, "Truncated sCAL chunk"); #if defined(PNG_FIXED_POINT_SUPPORTED) && \ - !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, swidth); + !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); #endif - png_free(png_ptr, buffer); - return; + png_free(png_ptr, buffer); + return; } #ifdef PNG_FLOATING_POINT_SUPPORTED height = png_strtod(png_ptr, ep, &vp); if (*vp) { - png_warning(png_ptr, "malformed height string in sCAL chunk"); - return; + png_warning(png_ptr, "malformed height string in sCAL chunk"); + return; } #else #ifdef PNG_FIXED_POINT_SUPPORTED sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); if (swidth == NULL) - { - png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); - return; - } + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); + return; + } png_memcpy(sheight, ep, (png_size_t)png_strlen(ep)); #endif #endif if (buffer + slength < ep #ifdef PNG_FLOATING_POINT_SUPPORTED - || width <= 0. || height <= 0. + || width <= 0. || height <= 0. #endif - ) + ) { - png_warning(png_ptr, "Invalid sCAL data"); - png_free(png_ptr, buffer); + png_warning(png_ptr, "Invalid sCAL data"); + png_free(png_ptr, buffer); #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, swidth); - png_free(png_ptr, sheight); + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); #endif - return; + return; } #ifdef PNG_FLOATING_POINT_SUPPORTED @@ -225629,27 +204160,27 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_tIME\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Out of place tIME chunk"); + png_error(png_ptr, "Out of place tIME chunk"); else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) { - png_warning(png_ptr, "Duplicate tIME chunk"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Duplicate tIME chunk"); + png_crc_finish(png_ptr, length); + return; } if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->mode |= PNG_AFTER_IDAT; if (length != 7) { - png_warning(png_ptr, "Incorrect tIME chunk length"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr, "Incorrect tIME chunk length"); + png_crc_finish(png_ptr, length); + return; } png_crc_read(png_ptr, buf, 7); if (png_crc_finish(png_ptr, 0)) - return; + return; mod_time.second = buf[6]; mod_time.minute = buf[5]; @@ -225663,7 +204194,6 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #endif #if defined(PNG_READ_tEXt_SUPPORTED) -/* Note: this does not properly handle chunks that are > 64K under DOS */ void /* PRIVATE */ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { @@ -225677,50 +204207,50 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_tEXt\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before tEXt"); + png_error(png_ptr, "Missing IHDR before tEXt"); if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->mode |= PNG_AFTER_IDAT; #ifdef PNG_MAX_MALLOC_64K if (length > (png_uint_32)65535L) { - png_warning(png_ptr, "tEXt chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; } #endif key = (png_charp)png_malloc_warn(png_ptr, length + 1); if (key == NULL) { - png_warning(png_ptr, "No memory to process text chunk."); - return; + png_warning(png_ptr, "No memory to process text chunk."); + return; } slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)key, slength); if (png_crc_finish(png_ptr, skip)) { - png_free(png_ptr, key); - return; + png_free(png_ptr, key); + return; } key[slength] = 0x00; for (text = key; *text; text++) - /* empty loop to find end of key */ ; + ; if (text != key + slength) - text++; + text++; text_ptr = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)png_sizeof(png_text)); + (png_uint_32)png_sizeof(png_text)); if (text_ptr == NULL) { - png_warning(png_ptr, "Not enough memory to process text chunk."); - png_free(png_ptr, key); - return; + png_warning(png_ptr, "Not enough memory to process text chunk."); + png_free(png_ptr, key); + return; } text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; text_ptr->key = key; @@ -225737,12 +204267,11 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, key); png_free(png_ptr, text_ptr); if (ret) - png_warning(png_ptr, "Insufficient memory to process text chunk."); + png_warning(png_ptr, "Insufficient memory to process text chunk."); } #endif #if defined(PNG_READ_zTXt_SUPPORTED) -/* note: this does not correctly handle chunks that are > 64K under DOS */ void /* PRIVATE */ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { @@ -225755,70 +204284,67 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_zTXt\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before zTXt"); + png_error(png_ptr, "Missing IHDR before zTXt"); if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->mode |= PNG_AFTER_IDAT; #ifdef PNG_MAX_MALLOC_64K - /* We will no doubt have problems with chunks even half this size, but - there is no hard and fast rule to tell us where to stop. */ if (length > (png_uint_32)65535L) { - png_warning(png_ptr,"zTXt chunk too large to fit in memory"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr,"zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; } #endif chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); if (chunkdata == NULL) { - png_warning(png_ptr,"Out of memory processing zTXt chunk."); - return; + png_warning(png_ptr,"Out of memory processing zTXt chunk."); + return; } slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)chunkdata, slength); if (png_crc_finish(png_ptr, 0)) { - png_free(png_ptr, chunkdata); - return; + png_free(png_ptr, chunkdata); + return; } chunkdata[slength] = 0x00; for (text = chunkdata; *text; text++) - /* empty loop */ ; + ; - /* zTXt must have some text after the chunkdataword */ if (text >= chunkdata + slength - 2) { - png_warning(png_ptr, "Truncated zTXt chunk"); - png_free(png_ptr, chunkdata); - return; + png_warning(png_ptr, "Truncated zTXt chunk"); + png_free(png_ptr, chunkdata); + return; } else { - comp_type = *(++text); - if (comp_type != PNG_TEXT_COMPRESSION_zTXt) - { - png_warning(png_ptr, "Unknown compression type in zTXt chunk"); - comp_type = PNG_TEXT_COMPRESSION_zTXt; - } - text++; /* skip the compression_method byte */ + comp_type = *(++text); + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) + { + png_warning(png_ptr, "Unknown compression type in zTXt chunk"); + comp_type = PNG_TEXT_COMPRESSION_zTXt; + } + text++; /* skip the compression_method byte */ } prefix_len = text - chunkdata; chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata, - (png_size_t)length, prefix_len, &data_len); + (png_size_t)length, prefix_len, &data_len); text_ptr = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)png_sizeof(png_text)); + (png_uint_32)png_sizeof(png_text)); if (text_ptr == NULL) { - png_warning(png_ptr,"Not enough memory to process zTXt chunk."); - png_free(png_ptr, chunkdata); - return; + png_warning(png_ptr,"Not enough memory to process zTXt chunk."); + png_free(png_ptr, chunkdata); + return; } text_ptr->compression = comp_type; text_ptr->key = chunkdata; @@ -225835,12 +204361,11 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, text_ptr); png_free(png_ptr, chunkdata); if (ret) - png_error(png_ptr, "Insufficient memory to store zTXt chunk."); + png_error(png_ptr, "Insufficient memory to store zTXt chunk."); } #endif #if defined(PNG_READ_iTXt_SUPPORTED) -/* note: this does not correctly handle chunks that are > 64K under DOS */ void /* PRIVATE */ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { @@ -225855,94 +204380,88 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_debug(1, "in png_handle_iTXt\n"); if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before iTXt"); + png_error(png_ptr, "Missing IHDR before iTXt"); if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->mode |= PNG_AFTER_IDAT; #ifdef PNG_MAX_MALLOC_64K - /* We will no doubt have problems with chunks even half this size, but - there is no hard and fast rule to tell us where to stop. */ if (length > (png_uint_32)65535L) { - png_warning(png_ptr,"iTXt chunk too large to fit in memory"); - png_crc_finish(png_ptr, length); - return; + png_warning(png_ptr,"iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; } #endif chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); if (chunkdata == NULL) { - png_warning(png_ptr, "No memory to process iTXt chunk."); - return; + png_warning(png_ptr, "No memory to process iTXt chunk."); + return; } slength = (png_size_t)length; png_crc_read(png_ptr, (png_bytep)chunkdata, slength); if (png_crc_finish(png_ptr, 0)) { - png_free(png_ptr, chunkdata); - return; + png_free(png_ptr, chunkdata); + return; } chunkdata[slength] = 0x00; for (lang = chunkdata; *lang; lang++) - /* empty loop */ ; - lang++; /* skip NUL separator */ - - /* iTXt must have a language tag (possibly empty), two compression bytes, - translated keyword (possibly empty), and possibly some text after the - keyword */ + ; + lang++; /* skip NUL separator */ if (lang >= chunkdata + slength - 3) { - png_warning(png_ptr, "Truncated iTXt chunk"); - png_free(png_ptr, chunkdata); - return; + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, chunkdata); + return; } else { - comp_flag = *lang++; - comp_type = *lang++; + comp_flag = *lang++; + comp_type = *lang++; } for (lang_key = lang; *lang_key; lang_key++) - /* empty loop */ ; - lang_key++; /* skip NUL separator */ + ; + lang_key++; /* skip NUL separator */ if (lang_key >= chunkdata + slength) { - png_warning(png_ptr, "Truncated iTXt chunk"); - png_free(png_ptr, chunkdata); - return; + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, chunkdata); + return; } for (text = lang_key; *text; text++) - /* empty loop */ ; - text++; /* skip NUL separator */ + ; + text++; /* skip NUL separator */ if (text >= chunkdata + slength) { - png_warning(png_ptr, "Malformed iTXt chunk"); - png_free(png_ptr, chunkdata); - return; + png_warning(png_ptr, "Malformed iTXt chunk"); + png_free(png_ptr, chunkdata); + return; } prefix_len = text - chunkdata; key=chunkdata; if (comp_flag) - chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata, - (size_t)length, prefix_len, &data_len); + chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata, + (size_t)length, prefix_len, &data_len); else - data_len=png_strlen(chunkdata + prefix_len); + data_len=png_strlen(chunkdata + prefix_len); text_ptr = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)png_sizeof(png_text)); + (png_uint_32)png_sizeof(png_text)); if (text_ptr == NULL) { - png_warning(png_ptr,"Not enough memory to process iTXt chunk."); - png_free(png_ptr, chunkdata); - return; + png_warning(png_ptr,"Not enough memory to process iTXt chunk."); + png_free(png_ptr, chunkdata); + return; } text_ptr->compression = (int)comp_flag + 1; text_ptr->lang_key = chunkdata+(lang_key-key); @@ -225957,15 +204476,10 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_free(png_ptr, text_ptr); png_free(png_ptr, chunkdata); if (ret) - png_error(png_ptr, "Insufficient memory to store iTXt chunk."); + png_error(png_ptr, "Insufficient memory to store iTXt chunk."); } #endif -/* This function is called when we haven't found a handler for a - chunk. If there isn't a problem with the chunk itself (ie bad - chunk name, CRC, or a critical chunk), the chunk is silently ignored - -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which - case it will be saved away to be written out later. */ void /* PRIVATE */ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { @@ -225976,10 +204490,10 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (png_ptr->mode & PNG_HAVE_IDAT) { #ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IDAT; + PNG_CONST PNG_IDAT; #endif - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */ - png_ptr->mode |= PNG_AFTER_IDAT; + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */ + png_ptr->mode |= PNG_AFTER_IDAT; } png_check_chunk_name(png_ptr, png_ptr->chunk_name); @@ -225987,61 +204501,60 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) if (!(png_ptr->chunk_name[0] & 0x20)) { #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - && png_ptr->read_user_chunk_fn == NULL + && png_ptr->read_user_chunk_fn == NULL #endif - ) + ) #endif - png_chunk_error(png_ptr, "unknown critical chunk"); + png_chunk_error(png_ptr, "unknown critical chunk"); } #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) || - (png_ptr->read_user_chunk_fn != NULL)) + (png_ptr->read_user_chunk_fn != NULL)) { #ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } #endif - png_strncpy((png_charp)png_ptr->unknown_chunk.name, + png_strncpy((png_charp)png_ptr->unknown_chunk.name, (png_charp)png_ptr->chunk_name, 5); - png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); - png_ptr->unknown_chunk.size = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_ptr->unknown_chunk.size = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - if(png_ptr->read_user_chunk_fn != NULL) - { - /* callback to user unknown chunk handler */ - int ret; - ret = (*(png_ptr->read_user_chunk_fn)) - (png_ptr, &png_ptr->unknown_chunk); - if (ret < 0) - png_chunk_error(png_ptr, "error in user chunk"); - if (ret == 0) - { - if (!(png_ptr->chunk_name[0] & 0x20)) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS) - png_chunk_error(png_ptr, "unknown critical chunk"); - png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); - } - } + if(png_ptr->read_user_chunk_fn != NULL) + { + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } #else - png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); #endif - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; } else #endif - skip = length; + skip = length; png_crc_finish(png_ptr, skip); @@ -226050,12 +204563,6 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) #endif } -/* This function is called to verify that a chunk name is valid. - This function can't have the "critical chunk check" incorporated - into it, since in the future we will need to be able to call user - functions to handle unknown critical chunks after we check that - the chunk name itself is valid. */ - #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) void /* PRIVATE */ @@ -226063,228 +204570,213 @@ png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) { png_debug(1, "in png_check_chunk_name\n"); if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || - isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) + isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) { - png_chunk_error(png_ptr, "invalid chunk type"); + png_chunk_error(png_ptr, "invalid chunk type"); } } -/* Combines the row recently read in with the existing pixels in the - row. This routine takes care of alpha and transparency if requested. - This routine also handles the two methods of progressive display - of interlaced images, depending on the mask value. - The mask value describes which pixels are to be combined with - the row. The pattern always repeats every 8 pixels, so just 8 - bits are needed. A one indicates the pixel is to be combined, - a zero indicates the pixel is to be skipped. This is in addition - to any alpha or transparency value associated with the pixel. If - you want all pixels to be combined, pass 0xff (255) in mask. */ - void /* PRIVATE */ png_combine_row(png_structp png_ptr, png_bytep row, int mask) { png_debug(1,"in png_combine_row\n"); if (mask == 0xff) { - png_memcpy(row, png_ptr->row_buf + 1, - PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); + png_memcpy(row, png_ptr->row_buf + 1, + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); } else { - switch (png_ptr->row_info.pixel_depth) - { - case 1: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - int s_inc, s_start, s_end; - int m = 0x80; - int shift; - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_inc, s_start, s_end; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; #if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 7; - s_inc = 1; - } - else + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + else #endif - { - s_start = 7; - s_end = 0; - s_inc = -1; - } + { + s_start = 7; + s_end = 0; + s_inc = -1; + } - shift = s_start; + shift = s_start; - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - int value; + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + int value; - value = (*sp >> shift) & 0x01; - *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } + value = (*sp >> shift) & 0x01; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - case 2: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - int s_start, s_end, s_inc; - int m = 0x80; - int shift; - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - int value; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 2: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; #if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 6; - s_inc = 2; - } - else + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + else #endif - { - s_start = 6; - s_end = 0; - s_inc = -2; - } + { + s_start = 6; + s_end = 0; + s_inc = -2; + } - shift = s_start; + shift = s_start; - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - value = (*sp >> shift) & 0x03; - *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x03; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - case 4: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - int s_start, s_end, s_inc; - int m = 0x80; - int shift; - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - int value; + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 4: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; #if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 4; - s_inc = 4; - } - else + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + else #endif - { - s_start = 4; - s_end = 0; - s_inc = -4; - } - shift = s_start; + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - value = (*sp >> shift) & 0xf; - *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - default: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - png_byte m = 0x80; + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + default: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + png_byte m = 0x80; - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - png_memcpy(dp, sp, pixel_bytes); - } + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + png_memcpy(dp, sp, pixel_bytes); + } - sp += pixel_bytes; - dp += pixel_bytes; + sp += pixel_bytes; + dp += pixel_bytes; - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - } + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + } } } #ifdef PNG_READ_INTERLACING_SUPPORTED -/* OLD pre-1.0.9 interface: -void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, - png_uint_32 transformations) - */ void /* PRIVATE */ png_do_read_interlace(png_structp png_ptr) { @@ -226293,213 +204785,211 @@ png_do_read_interlace(png_structp png_ptr) int pass = png_ptr->pass; png_uint_32 transformations = png_ptr->transformations; #ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* offset to next interlace block */ PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; #endif png_debug(1,"in png_do_read_interlace\n"); if (row != NULL && row_info != NULL) { - png_uint_32 final_width; + png_uint_32 final_width; - final_width = row_info->width * png_pass_inc[pass]; + final_width = row_info->width * png_pass_inc[pass]; - switch (row_info->pixel_depth) - { - case 1: - { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; - png_byte v; - png_uint_32 i; - int j; + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; #if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (int)((row_info->width + 7) & 0x07); - dshift = (int)((final_width + 7) & 0x07); - s_start = 7; - s_end = 0; - s_inc = -1; - } - else + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + else #endif - { - sshift = 7 - (int)((row_info->width + 7) & 0x07); - dshift = 7 - (int)((final_width + 7) & 0x07); - s_start = 0; - s_end = 7; - s_inc = 1; - } + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } - for (i = 0; i < row_info->width; i++) - { - v = (png_byte)((*sp >> sshift) & 0x01); - for (j = 0; j < jstop; j++) - { - *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - case 2: - { - png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); - png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; - png_uint_32 i; + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; #if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (int)(((row_info->width + 3) & 0x03) << 1); - dshift = (int)(((final_width + 3) & 0x03) << 1); - s_start = 6; - s_end = 0; - s_inc = -2; - } - else + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + else #endif - { - sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); - dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); - s_start = 0; - s_end = 6; - s_inc = 2; - } + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } - for (i = 0; i < row_info->width; i++) - { - png_byte v; - int j; + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; - v = (png_byte)((*sp >> sshift) & 0x03); - for (j = 0; j < jstop; j++) - { - *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - case 4: - { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); - int sshift, dshift; - int s_start, s_end, s_inc; - png_uint_32 i; - int jstop = png_pass_inc[pass]; + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; #if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (int)(((row_info->width + 1) & 0x01) << 2); - dshift = (int)(((final_width + 1) & 0x01) << 2); - s_start = 4; - s_end = 0; - s_inc = -4; - } - else + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + else #endif - { - sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); - dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); - s_start = 0; - s_end = 4; - s_inc = 4; - } + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } - for (i = 0; i < row_info->width; i++) - { - png_byte v = (png_byte)((*sp >> sshift) & 0xf); - int j; + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0xf); + int j; - for (j = 0; j < jstop; j++) - { - *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - default: - { - png_size_t pixel_bytes = (row_info->pixel_depth >> 3); - png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; - png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; - int jstop = png_pass_inc[pass]; - png_uint_32 i; + int jstop = png_pass_inc[pass]; + png_uint_32 i; - for (i = 0; i < row_info->width; i++) - { - png_byte v[8]; - int j; + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; + int j; - png_memcpy(v, sp, pixel_bytes); - for (j = 0; j < jstop; j++) - { - png_memcpy(dp, v, pixel_bytes); - dp -= pixel_bytes; - } - sp -= pixel_bytes; - } - break; - } - } - row_info->width = final_width; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width); + png_memcpy(v, sp, pixel_bytes); + for (j = 0; j < jstop; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sp -= pixel_bytes; + } + break; + } + } + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width); } #if !defined(PNG_READ_PACKSWAP_SUPPORTED) transformations = transformations; /* silence compiler warning */ @@ -226515,118 +205005,109 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter); switch (filter) { - case PNG_FILTER_VALUE_NONE: - break; - case PNG_FILTER_VALUE_SUB: - { - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp = row + bpp; - png_bytep lp = row; + case PNG_FILTER_VALUE_NONE: + break; + case PNG_FILTER_VALUE_SUB: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; - for (i = bpp; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_UP: - { - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_bytep rp = row; - png_bytep pp = prev_row; + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_UP: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_bytep pp = prev_row; - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_AVG: - { - png_uint_32 i; - png_bytep rp = row; - png_bytep pp = prev_row; - png_bytep lp = row; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_uint_32 istop = row_info->rowbytes - bpp; + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_AVG: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + - ((int)(*pp++) / 2 )) & 0xff); - rp++; - } + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + rp++; + } - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + - (int)(*pp++ + *lp++) / 2 ) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_PAETH: - { - png_uint_32 i; - png_bytep rp = row; - png_bytep pp = prev_row; - png_bytep lp = row; - png_bytep cp = prev_row; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_uint_32 istop=row_info->rowbytes - bpp; + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *lp++) / 2 ) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_PAETH: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_bytep cp = prev_row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop=row_info->rowbytes - bpp; - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } - for (i = 0; i < istop; i++) /* use leftover rp,pp */ - { - int a, b, c, pa, pb, pc, p; + for (i = 0; i < istop; i++) /* use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; - a = *lp++; - b = *pp++; - c = *cp++; + a = *lp++; + b = *pp++; + c = *cp++; - p = b - c; - pc = a - c; + p = b - c; + pc = a - c; #ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); #else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; #endif - /* - if (pa <= pb && pa <= pc) - p = a; - else if (pb <= pc) - p = b; - else - p = c; - */ + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; - - *rp = (png_byte)(((int)(*rp) + p) & 0xff); - rp++; - } - break; - } - default: - png_warning(png_ptr, "Ignoring bad adaptive filter type"); - *row=0; - break; + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + break; + } + default: + png_warning(png_ptr, "Ignoring bad adaptive filter type"); + *row=0; + break; } } @@ -226634,124 +205115,119 @@ void /* PRIVATE */ png_read_finish_row(png_structp png_ptr) { #ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* start of interlace block */ PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - /* offset to next interlace block */ PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - /* start of interlace block in the y direction */ PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - /* offset to next interlace block in the y direction */ PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif png_debug(1, "in png_read_finish_row\n"); png_ptr->row_number++; if (png_ptr->row_number < png_ptr->num_rows) - return; + return; if (png_ptr->interlaced) { - png_ptr->row_number = 0; - png_memset_check(png_ptr, png_ptr->prev_row, 0, - png_ptr->rowbytes + 1); - do - { - png_ptr->pass++; - if (png_ptr->pass >= 7) - break; - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; - png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, - png_ptr->iwidth) + 1; + png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; - if (!(png_ptr->transformations & PNG_INTERLACE)) - { - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - if (!(png_ptr->num_rows)) - continue; - } - else /* if (png_ptr->transformations & PNG_INTERLACE) */ - break; - } while (png_ptr->iwidth == 0); + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (!(png_ptr->num_rows)) + continue; + } + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; + } while (png_ptr->iwidth == 0); - if (png_ptr->pass < 7) - return; + if (png_ptr->pass < 7) + return; } if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) { #ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IDAT; + PNG_CONST PNG_IDAT; #endif - char extra; - int ret; + char extra; + int ret; - png_ptr->zstream.next_out = (Bytef *)&extra; - png_ptr->zstream.avail_out = (uInt)1; - for(;;) - { - if (!(png_ptr->zstream.avail_in)) - { - while (!png_ptr->idat_size) - { - png_byte chunk_length[4]; + png_ptr->zstream.next_out = (Bytef *)&extra; + png_ptr->zstream.avail_out = (uInt)1; + for(;;) + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_byte chunk_length[4]; - png_crc_finish(png_ptr, 0); + png_crc_finish(png_ptr, 0); - png_read_data(png_ptr, chunk_length, 4); - png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_error(png_ptr, "Not enough image data"); + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); - } - png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_in = png_ptr->zbuf; - if (png_ptr->zbuf_size > png_ptr->idat_size) - png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; - png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); - png_ptr->idat_size -= png_ptr->zstream.avail_in; - } - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret == Z_STREAM_END) - { - if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || - png_ptr->idat_size) - png_warning(png_ptr, "Extra compressed data"); - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - if (ret != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : - "Decompression Error"); + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_warning(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression Error"); - if (!(png_ptr->zstream.avail_out)) - { - png_warning(png_ptr, "Extra compressed data."); - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } + if (!(png_ptr->zstream.avail_out)) + { + png_warning(png_ptr, "Extra compressed data."); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } - } - png_ptr->zstream.avail_out = 0; + } + png_ptr->zstream.avail_out = 0; } if (png_ptr->idat_size || png_ptr->zstream.avail_in) - png_warning(png_ptr, "Extra compression data"); + png_warning(png_ptr, "Extra compression data"); inflateReset(&png_ptr->zstream); @@ -226762,18 +205238,13 @@ void /* PRIVATE */ png_read_start_row(png_structp png_ptr) { #ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* start of interlace block */ PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - /* offset to next interlace block */ PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - /* start of interlace block in the y direction */ PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - /* offset to next interlace block in the y direction */ PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif @@ -226785,153 +205256,149 @@ png_read_start_row(png_structp png_ptr) png_init_read_transformations(png_ptr); if (png_ptr->interlaced) { - if (!(png_ptr->transformations & PNG_INTERLACE)) - png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - - png_pass_ystart[0]) / png_pass_yinc[0]; - else - png_ptr->num_rows = png_ptr->height; + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + else + png_ptr->num_rows = png_ptr->height; - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; - row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1; + row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1; - png_ptr->irowbytes = (png_size_t)row_bytes; - if((png_uint_32)png_ptr->irowbytes != row_bytes) - png_error(png_ptr, "Rowbytes overflow in png_read_start_row"); + png_ptr->irowbytes = (png_size_t)row_bytes; + if((png_uint_32)png_ptr->irowbytes != row_bytes) + png_error(png_ptr, "Rowbytes overflow in png_read_start_row"); } else { - png_ptr->num_rows = png_ptr->height; - png_ptr->iwidth = png_ptr->width; - png_ptr->irowbytes = png_ptr->rowbytes + 1; + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + png_ptr->irowbytes = png_ptr->rowbytes + 1; } max_pixel_depth = png_ptr->pixel_depth; #if defined(PNG_READ_PACK_SUPPORTED) if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) - max_pixel_depth = 8; + max_pixel_depth = 8; #endif #if defined(PNG_READ_EXPAND_SUPPORTED) if (png_ptr->transformations & PNG_EXPAND) { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (png_ptr->num_trans) - max_pixel_depth = 32; - else - max_pixel_depth = 24; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - if (max_pixel_depth < 8) - max_pixel_depth = 8; - if (png_ptr->num_trans) - max_pixel_depth *= 2; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - if (png_ptr->num_trans) - { - max_pixel_depth *= 4; - max_pixel_depth /= 3; - } - } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } } #endif #if defined(PNG_READ_FILLER_SUPPORTED) if (png_ptr->transformations & (PNG_FILLER)) { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - max_pixel_depth = 32; - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - if (max_pixel_depth <= 8) - max_pixel_depth = 16; - else - max_pixel_depth = 32; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - if (max_pixel_depth <= 32) - max_pixel_depth = 32; - else - max_pixel_depth = 64; - } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_pixel_depth = 32; + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + else + max_pixel_depth = 32; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } } #endif #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) if (png_ptr->transformations & PNG_GRAY_TO_RGB) { - if ( + if ( #if defined(PNG_READ_EXPAND_SUPPORTED) - (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || #endif #if defined(PNG_READ_FILLER_SUPPORTED) - (png_ptr->transformations & (PNG_FILLER)) || + (png_ptr->transformations & (PNG_FILLER)) || #endif - png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (max_pixel_depth <= 16) - max_pixel_depth = 32; - else - max_pixel_depth = 64; - } - else - { - if (max_pixel_depth <= 8) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - max_pixel_depth = 32; - else - max_pixel_depth = 24; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - max_pixel_depth = 64; - else - max_pixel_depth = 48; - } + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + else + max_pixel_depth = 48; + } } #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) if(png_ptr->transformations & PNG_USER_TRANSFORM) - { - int user_pixel_depth=png_ptr->user_transform_depth* - png_ptr->user_transform_channels; - if(user_pixel_depth > max_pixel_depth) - max_pixel_depth=user_pixel_depth; - } + { + int user_pixel_depth=png_ptr->user_transform_depth* + png_ptr->user_transform_channels; + if(user_pixel_depth > max_pixel_depth) + max_pixel_depth=user_pixel_depth; + } #endif - /* align the width on the next larger 8 pixels. Mainly used - for interlacing */ row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); - /* calculate the maximum bytes needed, adding a byte and a pixel - for safety's sake */ row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) + - 1 + ((max_pixel_depth + 7) >> 3); + 1 + ((max_pixel_depth + 7) >> 3); #ifdef PNG_MAX_MALLOC_64K if (row_bytes > (png_uint_32)65536L) - png_error(png_ptr, "This image requires a row greater than 64KB"); + png_error(png_ptr, "This image requires a row greater than 64KB"); #endif png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64); png_ptr->row_buf = png_ptr->big_row_buf+32; #ifdef PNG_MAX_MALLOC_64K if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L) - png_error(png_ptr, "This image requires a row greater than 64KB"); + png_error(png_ptr, "This image requires a row greater than 64KB"); #endif if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1)) - png_error(png_ptr, "Row has too many bytes to allocate in memory."); + png_error(png_ptr, "Row has too many bytes to allocate in memory."); png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( - png_ptr->rowbytes + 1)); + png_ptr->rowbytes + 1)); png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1); @@ -226948,19 +205415,6 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) /********* End of inlined file: pngrutil.c *********/ /********* Start of inlined file: pngset.c *********/ -/* pngset.c - storage of image information into info struct - * - * Last changed in libpng 1.2.21 [October 4, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * The functions here are used during reads to store data from the file - * into the info struct, and during writes to store application data - * into the info struct for writing into the file. This abstracts the - * info struct and allows us to change the structure in the future. - */ #define PNG_INTERNAL @@ -226972,7 +205426,7 @@ png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) { png_debug1(1, "in %s storage function\n", "bKGD"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); info_ptr->valid |= PNG_INFO_bKGD; @@ -226988,25 +205442,25 @@ png_set_cHRM(png_structp png_ptr, png_infop info_ptr, { png_debug1(1, "in %s storage function\n", "cHRM"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; if (white_x < 0.0 || white_y < 0.0 || - red_x < 0.0 || red_y < 0.0 || - green_x < 0.0 || green_y < 0.0 || - blue_x < 0.0 || blue_y < 0.0) + red_x < 0.0 || red_y < 0.0 || + green_x < 0.0 || green_y < 0.0 || + blue_x < 0.0 || blue_y < 0.0) { - png_warning(png_ptr, - "Ignoring attempt to set negative chromaticity value"); - return; + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + return; } if (white_x > 21474.83 || white_y > 21474.83 || - red_x > 21474.83 || red_y > 21474.83 || - green_x > 21474.83 || green_y > 21474.83 || - blue_x > 21474.83 || blue_y > 21474.83) + red_x > 21474.83 || red_y > 21474.83 || + green_x > 21474.83 || green_y > 21474.83 || + blue_x > 21474.83 || blue_y > 21474.83) { - png_warning(png_ptr, - "Ignoring attempt to set chromaticity value exceeding 21474.83"); - return; + png_warning(png_ptr, + "Ignoring attempt to set chromaticity value exceeding 21474.83"); + return; } info_ptr->x_white = (float)white_x; @@ -227039,40 +205493,40 @@ png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, { png_debug1(1, "in %s storage function\n", "cHRM"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; if (white_x < 0 || white_y < 0 || - red_x < 0 || red_y < 0 || - green_x < 0 || green_y < 0 || - blue_x < 0 || blue_y < 0) + red_x < 0 || red_y < 0 || + green_x < 0 || green_y < 0 || + blue_x < 0 || blue_y < 0) { - png_warning(png_ptr, - "Ignoring attempt to set negative chromaticity value"); - return; + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + return; } #ifdef PNG_FLOATING_POINT_SUPPORTED if (white_x > (double) PNG_UINT_31_MAX || - white_y > (double) PNG_UINT_31_MAX || - red_x > (double) PNG_UINT_31_MAX || - red_y > (double) PNG_UINT_31_MAX || - green_x > (double) PNG_UINT_31_MAX || - green_y > (double) PNG_UINT_31_MAX || - blue_x > (double) PNG_UINT_31_MAX || - blue_y > (double) PNG_UINT_31_MAX) + white_y > (double) PNG_UINT_31_MAX || + red_x > (double) PNG_UINT_31_MAX || + red_y > (double) PNG_UINT_31_MAX || + green_x > (double) PNG_UINT_31_MAX || + green_y > (double) PNG_UINT_31_MAX || + blue_x > (double) PNG_UINT_31_MAX || + blue_y > (double) PNG_UINT_31_MAX) #else if (white_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - white_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || - red_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - red_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || - green_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - green_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || - blue_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || - blue_y > (png_fixed_point) PNG_UINT_31_MAX/100000L) + white_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || + red_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || + red_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || + green_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || + green_y > (png_fixed_point) PNG_UINT_31_MAX/100000L || + blue_x > (png_fixed_point) PNG_UINT_31_MAX/100000L || + blue_y > (png_fixed_point) PNG_UINT_31_MAX/100000L) #endif { - png_warning(png_ptr, - "Ignoring attempt to set chromaticity value exceeding 21474.83"); - return; + png_warning(png_ptr, + "Ignoring attempt to set chromaticity value exceeding 21474.83"); + return; } info_ptr->int_x_white = white_x; info_ptr->int_y_white = white_y; @@ -227105,23 +205559,22 @@ png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) double gamma; png_debug1(1, "in %s storage function\n", "gAMA"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; - /* Check for overflow */ if (file_gamma > 21474.83) { - png_warning(png_ptr, "Limiting gamma to 21474.83"); - gamma=21474.83; + png_warning(png_ptr, "Limiting gamma to 21474.83"); + gamma=21474.83; } else - gamma=file_gamma; + gamma=file_gamma; info_ptr->gamma = (float)gamma; #ifdef PNG_FIXED_POINT_SUPPORTED info_ptr->int_gamma = (int)(gamma*100000.+.5); #endif info_ptr->valid |= PNG_INFO_gAMA; if(gamma == 0.0) - png_warning(png_ptr, "Setting gamma=0"); + png_warning(png_ptr, "Setting gamma=0"); } #endif void PNGAPI @@ -227132,22 +205585,22 @@ png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point png_debug1(1, "in %s storage function\n", "gAMA"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; if (int_gamma > (png_fixed_point) PNG_UINT_31_MAX) { - png_warning(png_ptr, "Limiting gamma to 21474.83"); - gamma=PNG_UINT_31_MAX; + png_warning(png_ptr, "Limiting gamma to 21474.83"); + gamma=PNG_UINT_31_MAX; } else { - if (int_gamma < 0) - { - png_warning(png_ptr, "Setting negative gamma to zero"); - gamma=0; - } - else - gamma=int_gamma; + if (int_gamma < 0) + { + png_warning(png_ptr, "Setting negative gamma to zero"); + gamma=0; + } + else + gamma=int_gamma; } #ifdef PNG_FLOATING_POINT_SUPPORTED info_ptr->gamma = (float)(gamma/100000.); @@ -227157,7 +205610,7 @@ png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point #endif info_ptr->valid |= PNG_INFO_gAMA; if(gamma == 0) - png_warning(png_ptr, "Setting gamma=0"); + png_warning(png_ptr, "Setting gamma=0"); } #endif @@ -227169,30 +205622,28 @@ png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) png_debug1(1, "in %s storage function\n", "hIST"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; if (info_ptr->num_palette == 0 || info_ptr->num_palette - > PNG_MAX_PALETTE_LENGTH) + > PNG_MAX_PALETTE_LENGTH) { - png_warning(png_ptr, - "Invalid palette size, hIST allocation skipped."); - return; + png_warning(png_ptr, + "Invalid palette size, hIST allocation skipped."); + return; } #ifdef PNG_FREE_ME_SUPPORTED png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); #endif - /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in version - 1.2.1 */ png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, - (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof (png_uint_16))); + (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof (png_uint_16))); if (png_ptr->hist == NULL) - { - png_warning(png_ptr, "Insufficient memory for hIST chunk data."); - return; - } + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data."); + return; + } for (i = 0; i < info_ptr->num_palette; i++) - png_ptr->hist[i] = hist[i]; + png_ptr->hist[i] = hist[i]; info_ptr->hist = png_ptr->hist; info_ptr->valid |= PNG_INFO_hIST; @@ -227212,75 +205663,64 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr, { png_debug1(1, "in %s storage function\n", "IHDR"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; - /* check for width and height valid values */ if (width == 0 || height == 0) - png_error(png_ptr, "Image width or height is zero in IHDR"); + png_error(png_ptr, "Image width or height is zero in IHDR"); #ifdef PNG_SET_USER_LIMITS_SUPPORTED if (width > png_ptr->user_width_max || height > png_ptr->user_height_max) - png_error(png_ptr, "image size exceeds user limits in IHDR"); + png_error(png_ptr, "image size exceeds user limits in IHDR"); #else if (width > PNG_USER_WIDTH_MAX || height > PNG_USER_HEIGHT_MAX) - png_error(png_ptr, "image size exceeds user limits in IHDR"); + png_error(png_ptr, "image size exceeds user limits in IHDR"); #endif if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX) - png_error(png_ptr, "Invalid image size in IHDR"); + png_error(png_ptr, "Invalid image size in IHDR"); if ( width > (PNG_UINT_32_MAX - >> 3) /* 8-byte RGBA pixels */ - - 64 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - png_warning(png_ptr, "Width is too large for libpng to process pixels"); + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + png_warning(png_ptr, "Width is too large for libpng to process pixels"); - /* check other values */ if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && - bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth in IHDR"); + bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth in IHDR"); if (color_type < 0 || color_type == 1 || - color_type == 5 || color_type > 6) - png_error(png_ptr, "Invalid color type in IHDR"); + color_type == 5 || color_type > 6) + png_error(png_ptr, "Invalid color type in IHDR"); if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || - ((color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) - png_error(png_ptr, "Invalid color type/bit depth combination in IHDR"); + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + png_error(png_ptr, "Invalid color type/bit depth combination in IHDR"); if (interlace_type >= PNG_INTERLACE_LAST) - png_error(png_ptr, "Unknown interlace method in IHDR"); + png_error(png_ptr, "Unknown interlace method in IHDR"); if (compression_type != PNG_COMPRESSION_TYPE_BASE) - png_error(png_ptr, "Unknown compression method in IHDR"); + png_error(png_ptr, "Unknown compression method in IHDR"); #if defined(PNG_MNG_FEATURES_SUPPORTED) - /* Accept filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not read a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted) - png_warning(png_ptr,"MNG features are not allowed in a PNG datastream"); + png_warning(png_ptr,"MNG features are not allowed in a PNG datastream"); if(filter_type != PNG_FILTER_TYPE_BASE) { - if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && - ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && - (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA))) - png_error(png_ptr, "Unknown filter method in IHDR"); - if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) - png_warning(png_ptr, "Invalid filter method in IHDR"); + if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + png_error(png_ptr, "Unknown filter method in IHDR"); + if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) + png_warning(png_ptr, "Invalid filter method in IHDR"); } #else if(filter_type != PNG_FILTER_TYPE_BASE) - png_error(png_ptr, "Unknown filter method in IHDR"); + png_error(png_ptr, "Unknown filter method in IHDR"); #endif info_ptr->width = width; @@ -227291,25 +205731,24 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr, info_ptr->filter_type = (png_byte)filter_type; info_ptr->interlace_type = (png_byte)interlace_type; if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - info_ptr->channels = 1; + info_ptr->channels = 1; else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) - info_ptr->channels = 3; + info_ptr->channels = 3; else - info_ptr->channels = 1; + info_ptr->channels = 1; if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - info_ptr->channels++; + info_ptr->channels++; info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); - /* check for potential overflow */ if (width > (PNG_UINT_32_MAX - >> 3) /* 8-byte RGBA pixels */ - - 64 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - info_ptr->rowbytes = (png_size_t)0; + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + info_ptr->rowbytes = (png_size_t)0; else - info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,width); + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,width); } #if defined(PNG_oFFs_SUPPORTED) @@ -227319,7 +205758,7 @@ png_set_oFFs(png_structp png_ptr, png_infop info_ptr, { png_debug1(1, "in %s storage function\n", "oFFs"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; info_ptr->x_offset = offset_x; info_ptr->y_offset = offset_y; @@ -227339,16 +205778,16 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr, png_debug1(1, "in %s storage function\n", "pCAL"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; length = png_strlen(purpose) + 1; png_debug1(3, "allocating purpose for info (%lu bytes)\n", length); info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); if (info_ptr->pcal_purpose == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL purpose."); - return; - } + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose."); + return; + } png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length); png_debug(3, "storing X0, X1, type, and nparams in info\n"); @@ -227361,33 +205800,33 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr, png_debug1(3, "allocating units for info (%lu bytes)\n", length); info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); if (info_ptr->pcal_units == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL units."); - return; - } + { + png_warning(png_ptr, "Insufficient memory for pCAL units."); + return; + } png_memcpy(info_ptr->pcal_units, units, (png_size_t)length); info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, - (png_uint_32)((nparams + 1) * png_sizeof(png_charp))); + (png_uint_32)((nparams + 1) * png_sizeof(png_charp))); if (info_ptr->pcal_params == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL params."); - return; - } + { + png_warning(png_ptr, "Insufficient memory for pCAL params."); + return; + } info_ptr->pcal_params[nparams] = NULL; for (i = 0; i < nparams; i++) { - length = png_strlen(params[i]) + 1; - png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length); - info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->pcal_params[i] == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL parameter."); - return; - } - png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); + length = png_strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length); + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter."); + return; + } + png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); } info_ptr->valid |= PNG_INFO_pCAL; @@ -227401,11 +205840,11 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr, #ifdef PNG_FLOATING_POINT_SUPPORTED void PNGAPI png_set_sCAL(png_structp png_ptr, png_infop info_ptr, - int unit, double width, double height) + int unit, double width, double height) { png_debug1(1, "in %s storage function\n", "sCAL"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; info_ptr->scal_unit = (png_byte)unit; info_ptr->scal_pixel_width = width; @@ -227417,13 +205856,13 @@ png_set_sCAL(png_structp png_ptr, png_infop info_ptr, #ifdef PNG_FIXED_POINT_SUPPORTED void PNGAPI png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, - int unit, png_charp swidth, png_charp sheight) + int unit, png_charp swidth, png_charp sheight) { png_uint_32 length; png_debug1(1, "in %s storage function\n", "sCAL"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; info_ptr->scal_unit = (png_byte)unit; @@ -227432,8 +205871,8 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length); if (info_ptr->scal_s_width == NULL) { - png_warning(png_ptr, - "Memory allocation failed while processing sCAL."); + png_warning(png_ptr, + "Memory allocation failed while processing sCAL."); } png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length); @@ -227442,9 +205881,9 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length); if (info_ptr->scal_s_height == NULL) { - png_free (png_ptr, info_ptr->scal_s_width); - png_warning(png_ptr, - "Memory allocation failed while processing sCAL."); + png_free (png_ptr, info_ptr->scal_s_width); + png_warning(png_ptr, + "Memory allocation failed while processing sCAL."); } png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length); @@ -227464,7 +205903,7 @@ png_set_pHYs(png_structp png_ptr, png_infop info_ptr, { png_debug1(1, "in %s storage function\n", "pHYs"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; info_ptr->x_pixels_per_unit = res_x; info_ptr->y_pixels_per_unit = res_y; @@ -227480,35 +205919,27 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr, png_debug1(1, "in %s storage function\n", "PLTE"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) - { - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_error(png_ptr, "Invalid palette length"); - else - { - png_warning(png_ptr, "Invalid palette length"); - return; - } - } + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Invalid palette length"); + else + { + png_warning(png_ptr, "Invalid palette length"); + return; + } + } - /* - * It may not actually be necessary to set png_ptr->palette here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - */ #ifdef PNG_FREE_ME_SUPPORTED png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); #endif - /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead - of num_palette entries, - in case of an invalid PNG file that has too-large sample values. */ png_ptr->palette = (png_colorp)png_malloc(png_ptr, - PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); png_memset(png_ptr->palette, 0, PNG_MAX_PALETTE_LENGTH * - png_sizeof(png_color)); + png_sizeof(png_color)); png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof (png_color)); info_ptr->palette = png_ptr->palette; info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; @@ -227529,7 +205960,7 @@ png_set_sBIT(png_structp png_ptr, png_infop info_ptr, { png_debug1(1, "in %s storage function\n", "sBIT"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof (png_color_8)); info_ptr->valid |= PNG_INFO_sBIT; @@ -227542,7 +205973,7 @@ png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) { png_debug1(1, "in %s storage function\n", "sRGB"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; info_ptr->srgb_intent = (png_byte)intent; info_ptr->valid |= PNG_INFO_sRGB; @@ -227566,12 +205997,12 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, #endif #ifdef PNG_FIXED_POINT_SUPPORTED png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, - int_green_y, int_blue_x, int_blue_y; + int_green_y, int_blue_x, int_blue_y; #endif #endif png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; png_set_sRGB(png_ptr, info_ptr, intent); @@ -227598,8 +206029,8 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, int_blue_y = 6000L; png_set_cHRM_fixed(png_ptr, info_ptr, - int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y, - int_blue_x, int_blue_y); + int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y, + int_blue_x, int_blue_y); #endif #ifdef PNG_FLOATING_POINT_SUPPORTED white_x = (float).3127; @@ -227612,7 +206043,7 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, blue_y = (float).06; png_set_cHRM(png_ptr, info_ptr, - white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); #endif #endif } @@ -227621,29 +206052,29 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, #if defined(PNG_iCCP_SUPPORTED) void PNGAPI png_set_iCCP(png_structp png_ptr, png_infop info_ptr, - png_charp name, int compression_type, - png_charp profile, png_uint_32 proflen) + png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen) { png_charp new_iccp_name; png_charp new_iccp_profile; png_debug1(1, "in %s storage function\n", "iCCP"); if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) - return; + return; new_iccp_name = (png_charp)png_malloc_warn(png_ptr, png_strlen(name)+1); if (new_iccp_name == NULL) { - png_warning(png_ptr, "Insufficient memory to process iCCP chunk."); - return; + png_warning(png_ptr, "Insufficient memory to process iCCP chunk."); + return; } png_strncpy(new_iccp_name, name, png_strlen(name)+1); new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen); if (new_iccp_profile == NULL) { - png_free (png_ptr, new_iccp_name); - png_warning(png_ptr, "Insufficient memory to process iCCP profile."); - return; + png_free (png_ptr, new_iccp_name); + png_warning(png_ptr, "Insufficient memory to process iCCP profile."); + return; } png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); @@ -227652,8 +206083,6 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr, info_ptr->iccp_proflen = proflen; info_ptr->iccp_name = new_iccp_name; info_ptr->iccp_profile = new_iccp_profile; - /* Compression is always zero but is here so the API and info structure - * does not have to change if we introduce multiple compression types */ info_ptr->iccp_compression = (png_byte)compression_type; #ifdef PNG_FREE_ME_SUPPORTED info_ptr->free_me |= PNG_FREE_ICCP; @@ -227670,7 +206099,7 @@ png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, int ret; ret=png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); if (ret) - png_error(png_ptr, "Insufficient memory to store text"); + png_error(png_ptr, "Insufficient memory to store text"); } int /* PRIVATE */ @@ -227680,154 +206109,150 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, int i; png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ? - "text" : (png_const_charp)png_ptr->chunk_name)); + "text" : (png_const_charp)png_ptr->chunk_name)); if (png_ptr == NULL || info_ptr == NULL || num_text == 0) - return(0); + return(0); - /* Make sure we have enough space in the "text" array in info_struct - * to hold all of the incoming text_ptr objects. - */ if (info_ptr->num_text + num_text > info_ptr->max_text) { - if (info_ptr->text != NULL) - { - png_textp old_text; - int old_max; + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; - old_max = info_ptr->max_text; - info_ptr->max_text = info_ptr->num_text + num_text + 8; - old_text = info_ptr->text; - info_ptr->text = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); - if (info_ptr->text == NULL) - { - png_free(png_ptr, old_text); - return(1); - } - png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * - png_sizeof(png_text))); - png_free(png_ptr, old_text); - } - else - { - info_ptr->max_text = num_text + 8; - info_ptr->num_text = 0; - info_ptr->text = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); - if (info_ptr->text == NULL) - return(1); + old_max = info_ptr->max_text; + info_ptr->max_text = info_ptr->num_text + num_text + 8; + old_text = info_ptr->text; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); + if (info_ptr->text == NULL) + { + png_free(png_ptr, old_text); + return(1); + } + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + png_sizeof(png_text))); + png_free(png_ptr, old_text); + } + else + { + info_ptr->max_text = num_text + 8; + info_ptr->num_text = 0; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); + if (info_ptr->text == NULL) + return(1); #ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_TEXT; + info_ptr->free_me |= PNG_FREE_TEXT; #endif - } - png_debug1(3, "allocated %d entries for info_ptr->text\n", - info_ptr->max_text); + } + png_debug1(3, "allocated %d entries for info_ptr->text\n", + info_ptr->max_text); } for (i = 0; i < num_text; i++) { - png_size_t text_length,key_len; - png_size_t lang_len,lang_key_len; - png_textp textp = &(info_ptr->text[info_ptr->num_text]); + png_size_t text_length,key_len; + png_size_t lang_len,lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); - if (text_ptr[i].key == NULL) - continue; + if (text_ptr[i].key == NULL) + continue; - key_len = png_strlen(text_ptr[i].key); + key_len = png_strlen(text_ptr[i].key); - if(text_ptr[i].compression <= 0) - { - lang_len = 0; - lang_key_len = 0; - } - else + if(text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + else #ifdef PNG_iTXt_SUPPORTED - { - /* set iTXt data */ - if (text_ptr[i].lang != NULL) - lang_len = png_strlen(text_ptr[i].lang); - else - lang_len = 0; - if (text_ptr[i].lang_key != NULL) - lang_key_len = png_strlen(text_ptr[i].lang_key); - else - lang_key_len = 0; - } + { + if (text_ptr[i].lang != NULL) + lang_len = png_strlen(text_ptr[i].lang); + else + lang_len = 0; + if (text_ptr[i].lang_key != NULL) + lang_key_len = png_strlen(text_ptr[i].lang_key); + else + lang_key_len = 0; + } #else - { - png_warning(png_ptr, "iTXt chunk not supported."); - continue; - } + { + png_warning(png_ptr, "iTXt chunk not supported."); + continue; + } #endif - if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') - { - text_length = 0; + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; #ifdef PNG_iTXt_SUPPORTED - if(text_ptr[i].compression > 0) - textp->compression = PNG_ITXT_COMPRESSION_NONE; - else + if(text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + else #endif - textp->compression = PNG_TEXT_COMPRESSION_NONE; - } - else - { - text_length = png_strlen(text_ptr[i].text); - textp->compression = text_ptr[i].compression; - } + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + else + { + text_length = png_strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } - textp->key = (png_charp)png_malloc_warn(png_ptr, - (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4)); - if (textp->key == NULL) - return(1); - png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n", - (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4), - (int)textp->key); + textp->key = (png_charp)png_malloc_warn(png_ptr, + (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4)); + if (textp->key == NULL) + return(1); + png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n", + (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4), + (int)textp->key); - png_memcpy(textp->key, text_ptr[i].key, - (png_size_t)(key_len)); - *(textp->key+key_len) = '\0'; + png_memcpy(textp->key, text_ptr[i].key, + (png_size_t)(key_len)); + *(textp->key+key_len) = '\0'; #ifdef PNG_iTXt_SUPPORTED - if (text_ptr[i].compression > 0) - { - textp->lang=textp->key + key_len + 1; - png_memcpy(textp->lang, text_ptr[i].lang, lang_len); - *(textp->lang+lang_len) = '\0'; - textp->lang_key=textp->lang + lang_len + 1; - png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); - *(textp->lang_key+lang_key_len) = '\0'; - textp->text=textp->lang_key + lang_key_len + 1; - } - else + if (text_ptr[i].compression > 0) + { + textp->lang=textp->key + key_len + 1; + png_memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang+lang_len) = '\0'; + textp->lang_key=textp->lang + lang_len + 1; + png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key+lang_key_len) = '\0'; + textp->text=textp->lang_key + lang_key_len + 1; + } + else #endif - { + { #ifdef PNG_iTXt_SUPPORTED - textp->lang=NULL; - textp->lang_key=NULL; + textp->lang=NULL; + textp->lang_key=NULL; #endif - textp->text=textp->key + key_len + 1; - } - if(text_length) - png_memcpy(textp->text, text_ptr[i].text, - (png_size_t)(text_length)); - *(textp->text+text_length) = '\0'; + textp->text=textp->key + key_len + 1; + } + if(text_length) + png_memcpy(textp->text, text_ptr[i].text, + (png_size_t)(text_length)); + *(textp->text+text_length) = '\0'; #ifdef PNG_iTXt_SUPPORTED - if(textp->compression > 0) - { - textp->text_length = 0; - textp->itxt_length = text_length; - } - else + if(textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + else #endif - { - textp->text_length = text_length; + { + textp->text_length = text_length; #ifdef PNG_iTXt_SUPPORTED - textp->itxt_length = 0; + textp->itxt_length = 0; #endif - } - info_ptr->num_text++; - png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text); + } + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text); } return(0); } @@ -227839,8 +206264,8 @@ png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) { png_debug1(1, "in %s storage function\n", "tIME"); if (png_ptr == NULL || info_ptr == NULL || - (png_ptr->mode & PNG_WROTE_tIME)) - return; + (png_ptr->mode & PNG_WROTE_tIME)) + return; png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof (png_time)); info_ptr->valid |= PNG_INFO_tIME; @@ -227854,36 +206279,30 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr, { png_debug1(1, "in %s storage function\n", "tRNS"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; if (trans != NULL) { - /* - * It may not actually be necessary to set png_ptr->trans here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - */ #ifdef PNG_FREE_ME_SUPPORTED - png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); #endif - /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ - png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, - (png_uint_32)PNG_MAX_PALETTE_LENGTH); - if (num_trans <= PNG_MAX_PALETTE_LENGTH) - png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans); + png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, + (png_uint_32)PNG_MAX_PALETTE_LENGTH); + if (num_trans <= PNG_MAX_PALETTE_LENGTH) + png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans); #ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_TRNS; + info_ptr->free_me |= PNG_FREE_TRNS; #else - png_ptr->flags |= PNG_FLAG_FREE_TRNS; + png_ptr->flags |= PNG_FLAG_FREE_TRNS; #endif } if (trans_values != NULL) { - png_memcpy(&(info_ptr->trans_values), trans_values, - png_sizeof(png_color_16)); - if (num_trans == 0) - num_trans = 1; + png_memcpy(&(info_ptr->trans_values), trans_values, + png_sizeof(png_color_16)); + if (num_trans == 0) + num_trans = 1; } info_ptr->num_trans = (png_uint_16)num_trans; info_ptr->valid |= PNG_INFO_tRNS; @@ -227893,62 +206312,60 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr, #if defined(PNG_sPLT_SUPPORTED) void PNGAPI png_set_sPLT(png_structp png_ptr, - png_infop info_ptr, png_sPLT_tp entries, int nentries) + png_infop info_ptr, png_sPLT_tp entries, int nentries) { - png_sPLT_tp np; - int i; + png_sPLT_tp np; + int i; - if (png_ptr == NULL || info_ptr == NULL) - return; + if (png_ptr == NULL || info_ptr == NULL) + return; - np = (png_sPLT_tp)png_malloc_warn(png_ptr, - (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t)); - if (np == NULL) - { - png_warning(png_ptr, "No memory for sPLT palettes."); - return; - } + np = (png_sPLT_tp)png_malloc_warn(png_ptr, + (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t)); + if (np == NULL) + { + png_warning(png_ptr, "No memory for sPLT palettes."); + return; + } - png_memcpy(np, info_ptr->splt_palettes, - info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); - png_free(png_ptr, info_ptr->splt_palettes); - info_ptr->splt_palettes=NULL; + png_memcpy(np, info_ptr->splt_palettes, + info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes=NULL; - for (i = 0; i < nentries; i++) - { - png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; - png_sPLT_tp from = entries + i; + for (i = 0; i < nentries; i++) + { + png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; + png_sPLT_tp from = entries + i; - to->name = (png_charp)png_malloc_warn(png_ptr, - png_strlen(from->name) + 1); - if (to->name == NULL) - { - png_warning(png_ptr, - "Out of memory while processing sPLT chunk"); - } - /* TODO: use png_malloc_warn */ - png_strncpy(to->name, from->name, png_strlen(from->name)+1); - to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, - from->nentries * png_sizeof(png_sPLT_entry)); - /* TODO: use png_malloc_warn */ - png_memcpy(to->entries, from->entries, - from->nentries * png_sizeof(png_sPLT_entry)); - if (to->entries == NULL) - { - png_warning(png_ptr, - "Out of memory while processing sPLT chunk"); - png_free(png_ptr,to->name); - to->name = NULL; - } - to->nentries = from->nentries; - to->depth = from->depth; - } + to->name = (png_charp)png_malloc_warn(png_ptr, + png_strlen(from->name) + 1); + if (to->name == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + } + png_strncpy(to->name, from->name, png_strlen(from->name)+1); + to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + from->nentries * png_sizeof(png_sPLT_entry)); + png_memcpy(to->entries, from->entries, + from->nentries * png_sizeof(png_sPLT_entry)); + if (to->entries == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + png_free(png_ptr,to->name); + to->name = NULL; + } + to->nentries = from->nentries; + to->depth = from->depth; + } - info_ptr->splt_palettes = np; - info_ptr->splt_palettes_num += nentries; - info_ptr->valid |= PNG_INFO_sPLT; + info_ptr->splt_palettes = np; + info_ptr->splt_palettes_num += nentries; + info_ptr->valid |= PNG_INFO_sPLT; #ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_SPLT; + info_ptr->free_me |= PNG_FREE_SPLT; #endif } #endif /* PNG_sPLT_SUPPORTED */ @@ -227958,53 +206375,52 @@ void PNGAPI png_set_unknown_chunks(png_structp png_ptr, png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) { - png_unknown_chunkp np; - int i; + png_unknown_chunkp np; + int i; - if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) - return; + if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) + return; - np = (png_unknown_chunkp)png_malloc_warn(png_ptr, - (info_ptr->unknown_chunks_num + num_unknowns) * - png_sizeof(png_unknown_chunk)); - if (np == NULL) - { - png_warning(png_ptr, - "Out of memory while processing unknown chunk."); - return; - } + np = (png_unknown_chunkp)png_malloc_warn(png_ptr, + (info_ptr->unknown_chunks_num + num_unknowns) * + png_sizeof(png_unknown_chunk)); + if (np == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk."); + return; + } - png_memcpy(np, info_ptr->unknown_chunks, - info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); - png_free(png_ptr, info_ptr->unknown_chunks); - info_ptr->unknown_chunks=NULL; + png_memcpy(np, info_ptr->unknown_chunks, + info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks=NULL; - for (i = 0; i < num_unknowns; i++) - { - png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; - png_unknown_chunkp from = unknowns + i; + for (i = 0; i < num_unknowns; i++) + { + png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; + png_unknown_chunkp from = unknowns + i; - png_strncpy((png_charp)to->name, (png_charp)from->name, 5); - to->data = (png_bytep)png_malloc_warn(png_ptr, from->size); - if (to->data == NULL) - { - png_warning(png_ptr, - "Out of memory while processing unknown chunk."); - } - else - { - png_memcpy(to->data, from->data, from->size); - to->size = from->size; + png_strncpy((png_charp)to->name, (png_charp)from->name, 5); + to->data = (png_bytep)png_malloc_warn(png_ptr, from->size); + if (to->data == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk."); + } + else + { + png_memcpy(to->data, from->data, from->size); + to->size = from->size; - /* note our location in the read or write sequence */ - to->location = (png_byte)(png_ptr->mode & 0xff); - } - } + to->location = (png_byte)(png_ptr->mode & 0xff); + } + } - info_ptr->unknown_chunks = np; - info_ptr->unknown_chunks_num += num_unknowns; + info_ptr->unknown_chunks = np; + info_ptr->unknown_chunks_num += num_unknowns; #ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_UNKN; + info_ptr->free_me |= PNG_FREE_UNKN; #endif } void PNGAPI @@ -228012,25 +206428,23 @@ png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, int chunk, int location) { if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < - (int)info_ptr->unknown_chunks_num) - info_ptr->unknown_chunks[chunk].location = (png_byte)location; + (int)info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; } #endif #if defined(PNG_1_0_X) || defined(PNG_1_2_X) #if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) void PNGAPI png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted) { - /* This function is deprecated in favor of png_permit_mng_features() - and will be removed from libpng-1.3.0 */ png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n"); if (png_ptr == NULL) - return; + return; png_ptr->mng_features_permitted = (png_byte) - ((png_ptr->mng_features_permitted & (~(PNG_FLAG_MNG_EMPTY_PLTE))) | - ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); + ((png_ptr->mng_features_permitted & (~(PNG_FLAG_MNG_EMPTY_PLTE))) | + ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); } #endif #endif @@ -228041,9 +206455,9 @@ png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) { png_debug(1, "in png_permit_mng_features\n"); if (png_ptr == NULL) - return (png_uint_32)0; + return (png_uint_32)0; png_ptr->mng_features_permitted = - (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); return (png_uint_32)png_ptr->mng_features_permitted; } #endif @@ -228053,43 +206467,43 @@ void PNGAPI png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep chunk_list, int num_chunks) { - png_bytep new_list, p; - int i, old_num_chunks; - if (png_ptr == NULL) - return; - if (num_chunks == 0) - { - if(keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) - png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; - else - png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + png_bytep new_list, p; + int i, old_num_chunks; + if (png_ptr == NULL) + return; + if (num_chunks == 0) + { + if(keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) + png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; - if(keep == PNG_HANDLE_CHUNK_ALWAYS) - png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; - else - png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; - return; - } - if (chunk_list == NULL) - return; - old_num_chunks=png_ptr->num_chunk_list; - new_list=(png_bytep)png_malloc(png_ptr, - (png_uint_32)(5*(num_chunks+old_num_chunks))); - if(png_ptr->chunk_list != NULL) - { - png_memcpy(new_list, png_ptr->chunk_list, - (png_size_t)(5*old_num_chunks)); - png_free(png_ptr, png_ptr->chunk_list); - png_ptr->chunk_list=NULL; - } - png_memcpy(new_list+5*old_num_chunks, chunk_list, - (png_size_t)(5*num_chunks)); - for (p=new_list+5*old_num_chunks+4, i=0; inum_chunk_list=old_num_chunks+num_chunks; - png_ptr->chunk_list=new_list; + if(keep == PNG_HANDLE_CHUNK_ALWAYS) + png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + return; + } + if (chunk_list == NULL) + return; + old_num_chunks=png_ptr->num_chunk_list; + new_list=(png_bytep)png_malloc(png_ptr, + (png_uint_32)(5*(num_chunks+old_num_chunks))); + if(png_ptr->chunk_list != NULL) + { + png_memcpy(new_list, png_ptr->chunk_list, + (png_size_t)(5*old_num_chunks)); + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + } + png_memcpy(new_list+5*old_num_chunks, chunk_list, + (png_size_t)(5*num_chunks)); + for (p=new_list+5*old_num_chunks+4, i=0; inum_chunk_list=old_num_chunks+num_chunks; + png_ptr->chunk_list=new_list; #ifdef PNG_FREE_ME_SUPPORTED - png_ptr->free_me |= PNG_FREE_LIST; + png_ptr->free_me |= PNG_FREE_LIST; #endif } #endif @@ -228101,7 +206515,7 @@ png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, { png_debug(1, "in png_set_read_user_chunk_fn\n"); if (png_ptr == NULL) - return; + return; png_ptr->read_user_chunk_fn = read_user_chunk_fn; png_ptr->user_chunk_ptr = user_chunk_ptr; } @@ -228114,13 +206528,13 @@ png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) png_debug1(1, "in %s storage function\n", "rows"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) - png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); info_ptr->row_pointers = row_pointers; if(row_pointers) - info_ptr->valid |= PNG_INFO_IDAT; + info_ptr->valid |= PNG_INFO_IDAT; } #endif @@ -228128,14 +206542,14 @@ png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) void PNGAPI png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size) { - if (png_ptr == NULL) - return; - if(png_ptr->zbuf) - png_free(png_ptr, png_ptr->zbuf); - png_ptr->zbuf_size = (png_size_t)size; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + if (png_ptr == NULL) + return; + if(png_ptr->zbuf) + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf_size = (png_size_t)size; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; } #endif @@ -228143,45 +206557,36 @@ void PNGAPI png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) { if (png_ptr && info_ptr) - info_ptr->valid &= ~(mask); + info_ptr->valid &= ~(mask); } #ifndef PNG_1_0_X #ifdef PNG_ASSEMBLER_CODE_SUPPORTED -/* function was added to libpng 1.2.0 and should always exist by default */ void PNGAPI png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags) { -/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ - if (png_ptr != NULL) - png_ptr->asm_flags = 0; + if (png_ptr != NULL) + png_ptr->asm_flags = 0; } -/* this function was added to libpng 1.2.0 */ void PNGAPI png_set_mmx_thresholds (png_structp png_ptr, - png_byte mmx_bitdepth_threshold, - png_uint_32 mmx_rowbytes_threshold) + png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold) { -/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ - if (png_ptr == NULL) - return; + if (png_ptr == NULL) + return; } #endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED -/* this function was added to libpng 1.2.6 */ void PNGAPI png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, - png_uint_32 user_height_max) + png_uint_32 user_height_max) { - /* Images with dimensions larger than these limits will be - * rejected by png_set_IHDR(). To accept any PNG datastream - * regardless of dimensions, set both limits to 0x7ffffffL. - */ - if(png_ptr == NULL) return; - png_ptr->user_width_max = user_width_max; - png_ptr->user_height_max = user_height_max; + if(png_ptr == NULL) return; + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; } #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ @@ -228190,20 +206595,11 @@ png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, /********* End of inlined file: pngset.c *********/ /********* Start of inlined file: pngtrans.c *********/ -/* pngtrans.c - transforms the data in a row (used by both readers and writers) - * - * Last changed in libpng 1.2.17 May 15, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ #define PNG_INTERNAL #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* turn on BGR-to-RGB mapping */ void PNGAPI png_set_bgr(png_structp png_ptr) { @@ -228214,19 +206610,17 @@ png_set_bgr(png_structp png_ptr) #endif #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* turn on 16 bit byte swapping */ void PNGAPI png_set_swap(png_structp png_ptr) { png_debug(1, "in png_set_swap\n"); if(png_ptr == NULL) return; if (png_ptr->bit_depth == 16) - png_ptr->transformations |= PNG_SWAP_BYTES; + png_ptr->transformations |= PNG_SWAP_BYTES; } #endif #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* turn on pixel packing */ void PNGAPI png_set_packing(png_structp png_ptr) { @@ -228234,21 +206628,20 @@ png_set_packing(png_structp png_ptr) if(png_ptr == NULL) return; if (png_ptr->bit_depth < 8) { - png_ptr->transformations |= PNG_PACK; - png_ptr->usr_bit_depth = 8; + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; } } #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* turn on packed pixel swapping */ void PNGAPI png_set_packswap(png_structp png_ptr) { png_debug(1, "in png_set_packswap\n"); if(png_ptr == NULL) return; if (png_ptr->bit_depth < 8) - png_ptr->transformations |= PNG_PACKSWAP; + png_ptr->transformations |= PNG_PACKSWAP; } #endif @@ -228264,15 +206657,15 @@ png_set_shift(png_structp png_ptr, png_color_8p true_bits) #endif #if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) + defined(PNG_WRITE_INTERLACING_SUPPORTED) int PNGAPI png_set_interlace_handling(png_structp png_ptr) { png_debug(1, "in png_set_interlace handling\n"); if (png_ptr && png_ptr->interlaced) { - png_ptr->transformations |= PNG_INTERLACE; - return (7); + png_ptr->transformations |= PNG_INTERLACE; + return (7); } return (1); @@ -228280,11 +206673,6 @@ png_set_interlace_handling(png_structp png_ptr) #endif #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte on read, or remove a filler or alpha byte on write. - * The filler type has changed in v0.95 to allow future 2-byte fillers - * for 48-bit input data, as well as to avoid problems with some compilers - * that don't like bytes as parameters. - */ void PNGAPI png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) { @@ -228293,31 +206681,22 @@ png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) png_ptr->transformations |= PNG_FILLER; png_ptr->filler = (png_byte)filler; if (filler_loc == PNG_FILLER_AFTER) - png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; else - png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; - - /* This should probably go in the "do_read_filler" routine. - * I attempted to do that in libpng-1.0.1a but that caused problems - * so I restored it in libpng-1.0.2a - */ + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) { - png_ptr->usr_channels = 4; + png_ptr->usr_channels = 4; } - /* Also I added this in libpng-1.0.2a (what happens when we expand - * a less-than-8-bit grayscale to GA? */ - if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) { - png_ptr->usr_channels = 2; + png_ptr->usr_channels = 2; } } #if !defined(PNG_1_0_X) -/* Added to libpng-1.2.7 */ void PNGAPI png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) { @@ -228331,7 +206710,7 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) void PNGAPI png_set_swap_alpha(png_structp png_ptr) { @@ -228342,7 +206721,7 @@ png_set_swap_alpha(png_structp png_ptr) #endif #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) void PNGAPI png_set_invert_alpha(png_structp png_ptr) { @@ -228361,82 +206740,77 @@ png_set_invert_mono(png_structp png_ptr) png_ptr->transformations |= PNG_INVERT_MONO; } -/* invert monochrome grayscale data */ void /* PRIVATE */ png_do_invert(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_invert\n"); - /* This test removed from libpng version 1.0.13 and 1.2.0: - * if (row_info->bit_depth == 1 && - */ #if defined(PNG_USELESS_TESTS_SUPPORTED) if (row == NULL || row_info == NULL) - return; + return; #endif if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(~(*rp)); - rp++; - } + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } } else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - row_info->bit_depth == 8) + row_info->bit_depth == 8) { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; - for (i = 0; i < istop; i+=2) - { - *rp = (png_byte)(~(*rp)); - rp+=2; - } + for (i = 0; i < istop; i+=2) + { + *rp = (png_byte)(~(*rp)); + rp+=2; + } } else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - row_info->bit_depth == 16) + row_info->bit_depth == 16) { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; - for (i = 0; i < istop; i+=4) - { - *rp = (png_byte)(~(*rp)); - *(rp+1) = (png_byte)(~(*(rp+1))); - rp+=4; - } + for (i = 0; i < istop; i+=4) + { + *rp = (png_byte)(~(*rp)); + *(rp+1) = (png_byte)(~(*(rp+1))); + rp+=4; + } } } #endif #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* swaps byte order on 16 bit depth images */ void /* PRIVATE */ png_do_swap(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_swap\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - row_info->bit_depth == 16) + row_info->bit_depth == 16) { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop= row_info->width * row_info->channels; + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; - for (i = 0; i < istop; i++, rp += 2) - { - png_byte t = *rp; - *rp = *(rp + 1); - *(rp + 1) = t; - } + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } } } #endif @@ -228547,39 +206921,37 @@ static PNG_CONST png_byte fourbppswaptable[256] = { 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF }; -/* swaps pixel packing order within bytes */ void /* PRIVATE */ png_do_packswap(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_packswap\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - row_info->bit_depth < 8) + row_info->bit_depth < 8) { - png_bytep rp, end, table; + png_bytep rp, end, table; - end = row + row_info->rowbytes; + end = row + row_info->rowbytes; - if (row_info->bit_depth == 1) - table = (png_bytep)onebppswaptable; - else if (row_info->bit_depth == 2) - table = (png_bytep)twobppswaptable; - else if (row_info->bit_depth == 4) - table = (png_bytep)fourbppswaptable; - else - return; + if (row_info->bit_depth == 1) + table = (png_bytep)onebppswaptable; + else if (row_info->bit_depth == 2) + table = (png_bytep)twobppswaptable; + else if (row_info->bit_depth == 4) + table = (png_bytep)fourbppswaptable; + else + return; - for (rp = row; rp < end; rp++) - *rp = table[*rp]; + for (rp = row; rp < end; rp++) + *rp = table[*rp]; } } #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ #if defined(PNG_WRITE_FILLER_SUPPORTED) || \ - defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -/* remove filler or alpha byte(s) */ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) void /* PRIVATE */ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) { @@ -228588,234 +206960,215 @@ png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) if (row != NULL && row_info != NULL) #endif { - png_bytep sp=row; - png_bytep dp=row; - png_uint_32 row_width=row_info->width; - png_uint_32 i; + png_bytep sp=row; + png_bytep dp=row; + png_uint_32 row_width=row_info->width; + png_uint_32 i; - if ((row_info->color_type == PNG_COLOR_TYPE_RGB || - (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && - (flags & PNG_FLAG_STRIP_ALPHA))) && - row_info->channels == 4) - { - if (row_info->bit_depth == 8) - { - /* This converts from RGBX or RGBA to RGB */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - dp+=3; sp+=4; - for (i = 1; i < row_width; i++) - { - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - sp++; - } - } - /* This converts from XRGB or ARGB to RGB */ - else - { - for (i = 0; i < row_width; i++) - { - sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 24; - row_info->rowbytes = row_width * 3; - } - else /* if (row_info->bit_depth == 16) */ - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ - sp += 8; dp += 6; - for (i = 1; i < row_width; i++) - { - /* This could be (although png_memcpy is probably slower): - png_memcpy(dp, sp, 6); - sp += 8; - dp += 6; - */ + if ((row_info->color_type == PNG_COLOR_TYPE_RGB || + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + dp+=3; sp+=4; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp++; + } + } + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + sp += 8; dp += 6; + for (i = 1; i < row_width; i++) + { - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - sp += 2; - } - } - else - { - /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ - for (i = 0; i < row_width; i++) - { - /* This could be (although png_memcpy is probably slower): - png_memcpy(dp, sp, 6); - sp += 8; - dp += 6; - */ + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + for (i = 0; i < row_width; i++) + { - sp+=2; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 48; - row_info->rowbytes = row_width * 6; - } - row_info->channels = 3; - } - else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || - (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - (flags & PNG_FLAG_STRIP_ALPHA))) && - row_info->channels == 2) - { - if (row_info->bit_depth == 8) - { - /* This converts from GX or GA to G */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - for (i = 0; i < row_width; i++) - { - *dp++ = *sp++; - sp++; - } - } - /* This converts from XG or AG to G */ - else - { - for (i = 0; i < row_width; i++) - { - sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - else /* if (row_info->bit_depth == 16) */ - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This converts from GGXX or GGAA to GG */ - sp += 4; dp += 2; - for (i = 1; i < row_width; i++) - { - *dp++ = *sp++; - *dp++ = *sp++; - sp += 2; - } - } - else - { - /* This converts from XXGG or AAGG to GG */ - for (i = 0; i < row_width; i++) - { - sp += 2; - *dp++ = *sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - row_info->channels = 1; - } - if (flags & PNG_FLAG_STRIP_ALPHA) - row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + sp+=2; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 48; + row_info->rowbytes = row_width * 6; + } + row_info->channels = 3; + } + else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || + (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + for (i = 0; i < row_width; i++) + { + *dp++ = *sp++; + sp++; + } + } + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + sp += 4; dp += 2; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + for (i = 0; i < row_width; i++) + { + sp += 2; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + row_info->channels = 1; + } + if (flags & PNG_FLAG_STRIP_ALPHA) + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; } } #endif #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* swaps red and blue bytes within a pixel */ void /* PRIVATE */ png_do_bgr(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_bgr\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) + (row_info->color_type & PNG_COLOR_MASK_COLOR)) { - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - png_bytep rp; - png_uint_32 i; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; - for (i = 0, rp = row; i < row_width; i++, rp += 3) - { - png_byte save = *rp; - *rp = *(rp + 2); - *(rp + 2) = save; - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - png_bytep rp; - png_uint_32 i; + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; - for (i = 0, rp = row; i < row_width; i++, rp += 4) - { - png_byte save = *rp; - *rp = *(rp + 2); - *(rp + 2) = save; - } - } - } - else if (row_info->bit_depth == 16) - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - png_bytep rp; - png_uint_32 i; + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; - for (i = 0, rp = row; i < row_width; i++, rp += 6) - { - png_byte save = *rp; - *rp = *(rp + 4); - *(rp + 4) = save; - save = *(rp + 1); - *(rp + 1) = *(rp + 5); - *(rp + 5) = save; - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - png_bytep rp; - png_uint_32 i; + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; - for (i = 0, rp = row; i < row_width; i++, rp += 8) - { - png_byte save = *rp; - *rp = *(rp + 4); - *(rp + 4) = save; - save = *(rp + 1); - *(rp + 1) = *(rp + 5); - *(rp + 5) = save; - } - } - } + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } } } #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) void PNGAPI png_set_user_transform_info(png_structp png_ptr, png_voidp user_transform_ptr, int user_transform_depth, int user_transform_channels) @@ -228828,17 +207181,12 @@ png_set_user_transform_info(png_structp png_ptr, png_voidp png_ptr->user_transform_channels = (png_byte)user_transform_channels; #else if(user_transform_ptr || user_transform_depth || user_transform_channels) - png_warning(png_ptr, - "This version of libpng does not support user transform info"); + png_warning(png_ptr, + "This version of libpng does not support user transform info"); #endif } #endif -/* This function returns a pointer to the user_transform_ptr associated with - * the user transform functions. The application should free any memory - * associated with this pointer before png_write_destroy and png_read_destroy - * are called. - */ png_voidp PNGAPI png_get_user_transform_ptr(png_structp png_ptr) { @@ -228853,46 +207201,21 @@ png_get_user_transform_ptr(png_structp png_ptr) /********* End of inlined file: pngtrans.c *********/ /********* Start of inlined file: pngwio.c *********/ -/* pngwio.c - functions for data output - * - * Last changed in libpng 1.2.13 November 13, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all output. Users who need - * special handling are expected to write functions that have the same - * arguments as these and perform similar functions, but that possibly - * use different output methods. Note that you shouldn't change these - * functions, but rather write replacement functions and then change - * them at run time with png_set_write_fn(...). - */ #define PNG_INTERNAL #ifdef PNG_WRITE_SUPPORTED -/* Write the data to whatever output you are using. The default routine - writes to a file pointer. Note that this routine sometimes gets called - with very small lengths, so you should implement some kind of simple - buffering if you are using unbuffered writes. This should never be asked - to write more than 64K on a 16 bit machine. */ - void /* PRIVATE */ png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { if (png_ptr->write_data_fn != NULL ) - (*(png_ptr->write_data_fn))(png_ptr, data, length); + (*(png_ptr->write_data_fn))(png_ptr, data, length); else - png_error(png_ptr, "Call to NULL write function"); + png_error(png_ptr, "Call to NULL write function"); } #if !defined(PNG_NO_STDIO) -/* This is the function that does the actual writing of data. If you are - not writing to a standard C stream, you should create a replacement - write_data function and use it at run time with png_set_write_fn(), rather - than changing the library. */ #ifndef USE_FAR_KEYWORD void PNGAPI png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) @@ -228902,18 +207225,14 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) if(png_ptr == NULL) return; #if defined(_WIN32_WCE) if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; + check = 0; #else check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); #endif if (check != length) - png_error(png_ptr, "Write Error"); + png_error(png_ptr, "Write Error"); } #else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ #define NEAR_BUF_SIZE 1024 #define MIN(a,b) (a <= b ? a : b) @@ -228926,59 +207245,55 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) png_FILE_p io_ptr; if(png_ptr == NULL) return; - /* Check if data really is near. If so, use usual code. */ near_data = (png_byte *)CVT_PTR_NOCHECK(data); io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); if ((png_bytep)near_data == data) { #if defined(_WIN32_WCE) - if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) - check = 0; + if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) + check = 0; #else - check = fwrite(near_data, 1, length, io_ptr); + check = fwrite(near_data, 1, length, io_ptr); #endif } else { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t written, remaining, err; - check = 0; - remaining = length; - do - { - written = MIN(NEAR_BUF_SIZE, remaining); - png_memcpy(buf, data, written); /* copy far buffer to near buffer */ + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* copy far buffer to near buffer */ #if defined(_WIN32_WCE) - if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) - err = 0; + if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) + err = 0; #else - err = fwrite(buf, 1, written, io_ptr); + err = fwrite(buf, 1, written, io_ptr); #endif - if (err != written) - break; - else - check += err; - data += written; - remaining -= written; - } - while (remaining != 0); + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); } if (check != length) - png_error(png_ptr, "Write Error"); + png_error(png_ptr, "Write Error"); } #endif #endif -/* This function is called to output any data pending writing (normally - to disk). After png_flush is called, there should be no data pending - writing in any buffers. */ #if defined(PNG_WRITE_FLUSH_SUPPORTED) void /* PRIVATE */ png_flush(png_structp png_ptr) { if (png_ptr->output_flush_fn != NULL) - (*(png_ptr->output_flush_fn))(png_ptr); + (*(png_ptr->output_flush_fn))(png_ptr); } #if !defined(PNG_NO_STDIO) @@ -228992,34 +207307,12 @@ png_default_flush(png_structp png_ptr) #if !defined(_WIN32_WCE) io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); if (io_ptr != NULL) - fflush(io_ptr); + fflush(io_ptr); #endif } #endif #endif -/* This function allows the application to supply new output functions for - libpng if standard C streams aren't being used. - - This function takes as its arguments: - png_ptr - pointer to a png output data structure - io_ptr - pointer to user supplied structure containing info about - the output functions. May be NULL. - write_data_fn - pointer to a new output function that takes as its - arguments a pointer to a png_struct, a pointer to - data to be written, and a 32-bit unsigned int that is - the number of bytes to be written. The new write - function should call png_error(png_ptr, "Error msg") - to exit and output any fatal error messages. - flush_data_fn - pointer to a new flush function that takes as its - arguments a pointer to a png_struct. After a call to - the flush function, there should be no data in any buffers - or pending transmission. If the output method doesn't do - any buffering of ouput, a function prototype must still be - supplied although it doesn't have to do anything. If - PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile - time, output_flush_fn will be ignored, although it must be - supplied for compatibility. */ void PNGAPI png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) @@ -229029,9 +207322,9 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, #if !defined(PNG_NO_STDIO) if (write_data_fn != NULL) - png_ptr->write_data_fn = write_data_fn; + png_ptr->write_data_fn = write_data_fn; else - png_ptr->write_data_fn = png_default_write_data; + png_ptr->write_data_fn = png_default_write_data; #else png_ptr->write_data_fn = write_data_fn; #endif @@ -229039,22 +207332,21 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, #if defined(PNG_WRITE_FLUSH_SUPPORTED) #if !defined(PNG_NO_STDIO) if (output_flush_fn != NULL) - png_ptr->output_flush_fn = output_flush_fn; + png_ptr->output_flush_fn = output_flush_fn; else - png_ptr->output_flush_fn = png_default_flush; + png_ptr->output_flush_fn = png_default_flush; #else png_ptr->output_flush_fn = output_flush_fn; #endif #endif /* PNG_WRITE_FLUSH_SUPPORTED */ - /* It is an error to read while writing a png file */ if (png_ptr->read_data_fn != NULL) { - png_ptr->read_data_fn = NULL; - png_warning(png_ptr, - "Attempted to set both read_data_fn and write_data_fn in"); - png_warning(png_ptr, - "the same structure. Resetting read_data_fn to NULL."); + png_ptr->read_data_fn = NULL; + png_warning(png_ptr, + "Attempted to set both read_data_fn and write_data_fn in"); + png_warning(png_ptr, + "the same structure. Resetting read_data_fn to NULL."); } } @@ -229067,8 +207359,8 @@ void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) FP_OFF(near_ptr) = FP_OFF(ptr); far_ptr = (void FAR *)near_ptr; if(check != 0) - if(FP_SEG(ptr) != FP_SEG(far_ptr)) - png_error(png_ptr,"segment lost in conversion"); + if(FP_SEG(ptr) != FP_SEG(far_ptr)) + png_error(png_ptr,"segment lost in conversion"); return(near_ptr); } # else @@ -229079,8 +207371,8 @@ void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) near_ptr = (void FAR *)ptr; far_ptr = (void FAR *)near_ptr; if(check != 0) - if(far_ptr != ptr) - png_error(png_ptr,"segment lost in conversion"); + if(far_ptr != ptr) + png_error(png_ptr,"segment lost in conversion"); return(near_ptr); } # endif @@ -229089,97 +207381,76 @@ void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) /********* End of inlined file: pngwio.c *********/ /********* Start of inlined file: pngwrite.c *********/ -/* pngwrite.c - general routines to write a PNG file - * - * Last changed in libpng 1.2.15 January 5, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ -/* get internal access to png.h */ #define PNG_INTERNAL #ifdef PNG_WRITE_SUPPORTED -/* Writes all the PNG information. This is the suggested way to use the - * library. If you have a new chunk to add, make a function to write it, - * and put it in the correct location here. If you want the chunk written - * after the image data, put it in png_write_end(). I strongly encourage - * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing - * the chunk, as that will keep the code from breaking if you want to just - * write a plain PNG file. If you have long comments, I suggest writing - * them in png_write_end(), and compressing them. - */ void PNGAPI png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) { png_debug(1, "in png_write_info_before_PLTE\n"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) { png_write_sig(png_ptr); /* write PNG signature */ #if defined(PNG_MNG_FEATURES_SUPPORTED) if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) { - png_warning(png_ptr,"MNG features are not allowed in a PNG datastream"); - png_ptr->mng_features_permitted=0; + png_warning(png_ptr,"MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted=0; } #endif - /* write IHDR information. */ png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, - info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, - info_ptr->filter_type, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, #if defined(PNG_WRITE_INTERLACING_SUPPORTED) - info_ptr->interlace_type); + info_ptr->interlace_type); #else - 0); + 0); #endif - /* the rest of these check to see if the valid field has the appropriate - flag set, and if it does, writes the chunk. */ #if defined(PNG_WRITE_gAMA_SUPPORTED) if (info_ptr->valid & PNG_INFO_gAMA) { # ifdef PNG_FLOATING_POINT_SUPPORTED - png_write_gAMA(png_ptr, info_ptr->gamma); + png_write_gAMA(png_ptr, info_ptr->gamma); #else #ifdef PNG_FIXED_POINT_SUPPORTED - png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); + png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); # endif #endif } #endif #if defined(PNG_WRITE_sRGB_SUPPORTED) if (info_ptr->valid & PNG_INFO_sRGB) - png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); #endif #if defined(PNG_WRITE_iCCP_SUPPORTED) if (info_ptr->valid & PNG_INFO_iCCP) - png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, - info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, + info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); #endif #if defined(PNG_WRITE_sBIT_SUPPORTED) if (info_ptr->valid & PNG_INFO_sBIT) - png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); #endif #if defined(PNG_WRITE_cHRM_SUPPORTED) if (info_ptr->valid & PNG_INFO_cHRM) { #ifdef PNG_FLOATING_POINT_SUPPORTED - png_write_cHRM(png_ptr, - info_ptr->x_white, info_ptr->y_white, - info_ptr->x_red, info_ptr->y_red, - info_ptr->x_green, info_ptr->y_green, - info_ptr->x_blue, info_ptr->y_blue); + png_write_cHRM(png_ptr, + info_ptr->x_white, info_ptr->y_white, + info_ptr->x_red, info_ptr->y_red, + info_ptr->x_green, info_ptr->y_green, + info_ptr->x_blue, info_ptr->y_blue); #else # ifdef PNG_FIXED_POINT_SUPPORTED - png_write_cHRM_fixed(png_ptr, - info_ptr->int_x_white, info_ptr->int_y_white, - info_ptr->int_x_red, info_ptr->int_y_red, - info_ptr->int_x_green, info_ptr->int_y_green, - info_ptr->int_x_blue, info_ptr->int_y_blue); + png_write_cHRM_fixed(png_ptr, + info_ptr->int_x_white, info_ptr->int_y_white, + info_ptr->int_x_red, info_ptr->int_y_red, + info_ptr->int_x_green, info_ptr->int_y_green, + info_ptr->int_x_blue, info_ptr->int_y_blue); # endif #endif } @@ -229187,27 +207458,27 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) if (info_ptr->unknown_chunks_num) { - png_unknown_chunk *up; + png_unknown_chunk *up; - png_debug(5, "writing extra chunks\n"); + png_debug(5, "writing extra chunks\n"); - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && !(up->location & PNG_HAVE_PLTE) && - !(up->location & PNG_HAVE_IDAT) && - ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || - (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) - { - png_write_chunk(png_ptr, up->name, up->data, up->size); - } - } + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && !(up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } } #endif - png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; } } @@ -229221,271 +207492,244 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) png_debug(1, "in png_write_info\n"); if (png_ptr == NULL || info_ptr == NULL) - return; + return; png_write_info_before_PLTE(png_ptr, info_ptr); if (info_ptr->valid & PNG_INFO_PLTE) - png_write_PLTE(png_ptr, info_ptr->palette, - (png_uint_32)info_ptr->num_palette); + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_error(png_ptr, "Valid palette required for paletted images"); + png_error(png_ptr, "Valid palette required for paletted images"); #if defined(PNG_WRITE_tRNS_SUPPORTED) if (info_ptr->valid & PNG_INFO_tRNS) - { + { #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel (in tRNS) */ - if ((png_ptr->transformations & PNG_INVERT_ALPHA) && - info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - int j; - for (j=0; j<(int)info_ptr->num_trans; j++) - info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); - } + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j=0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); + } #endif - png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), - info_ptr->num_trans, info_ptr->color_type); - } + png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), + info_ptr->num_trans, info_ptr->color_type); + } #endif #if defined(PNG_WRITE_bKGD_SUPPORTED) if (info_ptr->valid & PNG_INFO_bKGD) - png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); #endif #if defined(PNG_WRITE_hIST_SUPPORTED) if (info_ptr->valid & PNG_INFO_hIST) - png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); #endif #if defined(PNG_WRITE_oFFs_SUPPORTED) if (info_ptr->valid & PNG_INFO_oFFs) - png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, - info_ptr->offset_unit_type); + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); #endif #if defined(PNG_WRITE_pCAL_SUPPORTED) if (info_ptr->valid & PNG_INFO_pCAL) - png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, - info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, - info_ptr->pcal_units, info_ptr->pcal_params); + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); #endif #if defined(PNG_WRITE_sCAL_SUPPORTED) if (info_ptr->valid & PNG_INFO_sCAL) #if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) - png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, - info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); + png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); #else #ifdef PNG_FIXED_POINT_SUPPORTED - png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, - info_ptr->scal_s_width, info_ptr->scal_s_height); + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); #else - png_warning(png_ptr, - "png_write_sCAL not supported; sCAL chunk not written."); + png_warning(png_ptr, + "png_write_sCAL not supported; sCAL chunk not written."); #endif #endif #endif #if defined(PNG_WRITE_pHYs_SUPPORTED) if (info_ptr->valid & PNG_INFO_pHYs) - png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, - info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); #endif #if defined(PNG_WRITE_tIME_SUPPORTED) if (info_ptr->valid & PNG_INFO_tIME) { - png_write_tIME(png_ptr, &(info_ptr->mod_time)); - png_ptr->mode |= PNG_WROTE_tIME; + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; } #endif #if defined(PNG_WRITE_sPLT_SUPPORTED) if (info_ptr->valid & PNG_INFO_sPLT) - for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) - png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); #endif #if defined(PNG_WRITE_TEXT_SUPPORTED) - /* Check to see if we need to write text chunks */ for (i = 0; i < info_ptr->num_text; i++) { - png_debug2(2, "Writing header text chunk %d, type %d\n", i, - info_ptr->text[i].compression); - /* an internationalized chunk? */ - if (info_ptr->text[i].compression > 0) - { + png_debug2(2, "Writing header text chunk %d, type %d\n", i, + info_ptr->text[i].compression); + if (info_ptr->text[i].compression > 0) + { #if defined(PNG_WRITE_iTXt_SUPPORTED) - /* write international chunk */ - png_write_iTXt(png_ptr, - info_ptr->text[i].compression, - info_ptr->text[i].key, - info_ptr->text[i].lang, - info_ptr->text[i].lang_key, - info_ptr->text[i].text); + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); #else - png_warning(png_ptr, "Unable to write international text"); + png_warning(png_ptr, "Unable to write international text"); #endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - /* If we want a compressed text chunk */ - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) - { + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { #if defined(PNG_WRITE_zTXt_SUPPORTED) - /* write compressed chunk */ - png_write_zTXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0, - info_ptr->text[i].compression); + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); #else - png_warning(png_ptr, "Unable to write compressed text"); + png_warning(png_ptr, "Unable to write compressed text"); #endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; - } - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) - { + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { #if defined(PNG_WRITE_tEXt_SUPPORTED) - /* write uncompressed chunk */ - png_write_tEXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, - 0); + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); #else - png_warning(png_ptr, "Unable to write uncompressed text"); + png_warning(png_ptr, "Unable to write uncompressed text"); #endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } } #endif #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) if (info_ptr->unknown_chunks_num) { - png_unknown_chunk *up; + png_unknown_chunk *up; - png_debug(5, "writing extra chunks\n"); + png_debug(5, "writing extra chunks\n"); - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && (up->location & PNG_HAVE_PLTE) && - !(up->location & PNG_HAVE_IDAT) && - ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || - (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) - { - png_write_chunk(png_ptr, up->name, up->data, up->size); - } - } + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } } #endif } -/* Writes the end of the PNG file. If you don't want to write comments or - * time information, you can pass NULL for info. If you already wrote these - * in png_write_info(), do not write them again here. If you have long - * comments, I suggest writing them here, and compressing them. - */ void PNGAPI png_write_end(png_structp png_ptr, png_infop info_ptr) { png_debug(1, "in png_write_end\n"); if (png_ptr == NULL) - return; + return; if (!(png_ptr->mode & PNG_HAVE_IDAT)) - png_error(png_ptr, "No IDATs written into file"); + png_error(png_ptr, "No IDATs written into file"); - /* see if user wants us to write information chunks */ if (info_ptr != NULL) { #if defined(PNG_WRITE_TEXT_SUPPORTED) - int i; /* local index variable */ + int i; /* local index variable */ #endif #if defined(PNG_WRITE_tIME_SUPPORTED) - /* check to see if user has supplied a time chunk */ - if ((info_ptr->valid & PNG_INFO_tIME) && - !(png_ptr->mode & PNG_WROTE_tIME)) - png_write_tIME(png_ptr, &(info_ptr->mod_time)); + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); #endif #if defined(PNG_WRITE_TEXT_SUPPORTED) - /* loop through comment chunks */ - for (i = 0; i < info_ptr->num_text; i++) - { - png_debug2(2, "Writing trailer text chunk %d, type %d\n", i, - info_ptr->text[i].compression); - /* an internationalized chunk? */ - if (info_ptr->text[i].compression > 0) - { + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d\n", i, + info_ptr->text[i].compression); + if (info_ptr->text[i].compression > 0) + { #if defined(PNG_WRITE_iTXt_SUPPORTED) - /* write international chunk */ - png_write_iTXt(png_ptr, - info_ptr->text[i].compression, - info_ptr->text[i].key, - info_ptr->text[i].lang, - info_ptr->text[i].lang_key, - info_ptr->text[i].text); + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); #else - png_warning(png_ptr, "Unable to write international text"); + png_warning(png_ptr, "Unable to write international text"); #endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) - { + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { #if defined(PNG_WRITE_zTXt_SUPPORTED) - /* write compressed chunk */ - png_write_zTXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0, - info_ptr->text[i].compression); + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); #else - png_warning(png_ptr, "Unable to write compressed text"); + png_warning(png_ptr, "Unable to write compressed text"); #endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; - } - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) - { + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { #if defined(PNG_WRITE_tEXt_SUPPORTED) - /* write uncompressed chunk */ - png_write_tEXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0); + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); #else - png_warning(png_ptr, "Unable to write uncompressed text"); + png_warning(png_ptr, "Unable to write uncompressed text"); #endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - } + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } #endif #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) if (info_ptr->unknown_chunks_num) { - png_unknown_chunk *up; + png_unknown_chunk *up; - png_debug(5, "writing extra chunks\n"); + png_debug(5, "writing extra chunks\n"); - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && (up->location & PNG_AFTER_IDAT) && - ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || - (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) - { - png_write_chunk(png_ptr, up->name, up->data, up->size); - } - } + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } } #endif } png_ptr->mode |= PNG_AFTER_IDAT; - /* write end of PNG file */ png_write_IEND(png_ptr); } #if defined(PNG_WRITE_tIME_SUPPORTED) #if !defined(_WIN32_WCE) -/* "time.h" functions are not supported on WindowsCE */ void PNGAPI png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) { @@ -229510,17 +207754,15 @@ png_convert_from_time_t(png_timep ptime, time_t ttime) #endif #endif -/* Initialize png_ptr structure, and allocate any memory needed */ png_structp PNGAPI png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn) { #ifdef PNG_USER_MEM_SUPPORTED return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); } -/* Alternate initialize png_ptr structure, and allocate any memory needed */ png_structp PNGAPI png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, @@ -229537,14 +207779,13 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_debug(1, "in png_create_write_struct\n"); #ifdef PNG_USER_MEM_SUPPORTED png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, - (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); #else png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); #endif /* PNG_USER_MEM_SUPPORTED */ if (png_ptr == NULL) - return (NULL); + return (NULL); - /* added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_ptr->user_width_max=PNG_USER_WIDTH_MAX; png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; @@ -229557,10 +207798,10 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, if (setjmp(png_ptr->jmpbuf)) #endif { - png_free(png_ptr, png_ptr->zbuf); - png_ptr->zbuf=NULL; - png_destroy_struct(png_ptr); - return (NULL); + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf=NULL; + png_destroy_struct(png_ptr); + return (NULL); } #ifdef USE_FAR_KEYWORD png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); @@ -229575,80 +207816,68 @@ png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, i=0; do { - if(user_png_ver[i] != png_libpng_ver[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + if(user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; } while (png_libpng_ver[i++]); if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) { - /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so - * we must recompile any applications that use any older library version. - * For versions after libpng 1.0, we will be compatible, so we need - * only check the first digit. - */ - if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || - (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || - (user_png_ver[0] == '0' && user_png_ver[2] < '9')) - { + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[80]; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); + char msg[80]; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); #endif #ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; + png_ptr->flags=0; #endif - png_error(png_ptr, - "Incompatible libpng version in application and library"); - } + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } } - /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); + (png_uint_32)png_ptr->zbuf_size); png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, - png_flush_ptr_NULL); + png_flush_ptr_NULL); #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, - 1, png_doublep_NULL, png_doublep_NULL); + 1, png_doublep_NULL, png_doublep_NULL); #endif #ifdef PNG_SETJMP_SUPPORTED -/* Applications that neglect to set up their own setjmp() and then encounter - a png_error() will longjmp here. Since the jmpbuf is then meaningless we - abort instead of returning. */ #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) - PNG_ABORT(); + PNG_ABORT(); png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); #else if (setjmp(png_ptr->jmpbuf)) - PNG_ABORT(); + PNG_ABORT(); #endif #endif return (png_ptr); } -/* Initialize png_ptr structure, and allocate any memory needed */ #if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* Deprecated. */ #undef png_write_init void PNGAPI png_write_init(png_structp png_ptr) { - /* We only come here via pre-1.0.7-compiled applications */ png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0); } @@ -229656,45 +207885,44 @@ void PNGAPI png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t png_info_size) { - /* We only come here via pre-1.0.12-compiled applications */ if(png_ptr == NULL) return; #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) if(png_sizeof(png_struct) > png_struct_size || - png_sizeof(png_info) > png_info_size) + png_sizeof(png_info) > png_info_size) { - char msg[80]; - png_ptr->warning_fn=NULL; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); + char msg[80]; + png_ptr->warning_fn=NULL; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); } #endif if(png_sizeof(png_struct) > png_struct_size) - { - png_ptr->error_fn=NULL; + { + png_ptr->error_fn=NULL; #ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; + png_ptr->flags=0; #endif - png_error(png_ptr, - "The png struct allocated by the application for writing is too small."); - } + png_error(png_ptr, + "The png struct allocated by the application for writing is too small."); + } if(png_sizeof(png_info) > png_info_size) - { - png_ptr->error_fn=NULL; + { + png_ptr->error_fn=NULL; #ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; + png_ptr->flags=0; #endif - png_error(png_ptr, - "The info struct allocated by the application for writing is too small."); - } + png_error(png_ptr, + "The info struct allocated by the application for writing is too small."); + } png_write_init_3(&png_ptr, user_png_ver, png_struct_size); } #endif /* PNG_1_0_X || PNG_1_2_X */ @@ -229711,70 +207939,60 @@ png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, int i = 0; if (png_ptr == NULL) - return; + return; do { - if (user_png_ver[i] != png_libpng_ver[i]) - { + if (user_png_ver[i] != png_libpng_ver[i]) + { #ifdef PNG_LEGACY_SUPPORTED - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; #else - png_ptr->warning_fn=NULL; - png_warning(png_ptr, - "Application uses deprecated png_write_init() and should be recompiled."); - break; + png_ptr->warning_fn=NULL; + png_warning(png_ptr, + "Application uses deprecated png_write_init() and should be recompiled."); + break; #endif - } + } } while (png_libpng_ver[i++]); png_debug(1, "in png_write_init_3\n"); #ifdef PNG_SETJMP_SUPPORTED - /* save jump buffer and error functions */ png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); #endif if (png_sizeof(png_struct) > png_struct_size) - { - png_destroy_struct(png_ptr); - png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); - *ptr_ptr = png_ptr; - } + { + png_destroy_struct(png_ptr); + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + *ptr_ptr = png_ptr; + } - /* reset all variables to 0 */ png_memset(png_ptr, 0, png_sizeof (png_struct)); - /* added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_ptr->user_width_max=PNG_USER_WIDTH_MAX; png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; #endif #ifdef PNG_SETJMP_SUPPORTED - /* restore jump buffer */ png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); #endif png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, - png_flush_ptr_NULL); + png_flush_ptr_NULL); - /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); + (png_uint_32)png_ptr->zbuf_size); #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, - 1, png_doublep_NULL, png_doublep_NULL); + 1, png_doublep_NULL, png_doublep_NULL); #endif } -/* Write a few rows of image data. If the image is interlaced, - * either you will have to write the 7 sub images, or, if you - * have called png_set_interlace_handling(), you will have to - * "write" the image seven times. - */ void PNGAPI png_write_rows(png_structp png_ptr, png_bytepp row, png_uint_32 num_rows) @@ -229785,18 +208003,14 @@ png_write_rows(png_structp png_ptr, png_bytepp row, png_debug(1, "in png_write_rows\n"); if (png_ptr == NULL) - return; + return; - /* loop through the rows */ for (i = 0, rp = row; i < num_rows; i++, rp++) { - png_write_row(png_ptr, *rp); + png_write_row(png_ptr, *rp); } } -/* Write the image. You only need to call this function once, even - * if you are writing an interlaced image. - */ void PNGAPI png_write_image(png_structp png_ptr, png_bytepp image) { @@ -229805,146 +208019,136 @@ png_write_image(png_structp png_ptr, png_bytepp image) png_bytepp rp; /* points to current row */ if (png_ptr == NULL) - return; + return; png_debug(1, "in png_write_image\n"); #if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* intialize interlace handling. If image is not interlaced, - this will set pass to 1 */ num_pass = png_set_interlace_handling(png_ptr); #else num_pass = 1; #endif - /* loop through passes */ for (pass = 0; pass < num_pass; pass++) { - /* loop through image */ - for (i = 0, rp = image; i < png_ptr->height; i++, rp++) - { - png_write_row(png_ptr, *rp); - } + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } } } -/* called by user to write a row of image data */ void PNGAPI png_write_row(png_structp png_ptr, png_bytep row) { if (png_ptr == NULL) - return; + return; png_debug2(1, "in png_write_row (row %ld, pass %d)\n", - png_ptr->row_number, png_ptr->pass); + png_ptr->row_number, png_ptr->pass); - /* initialize transformations and other stuff if first time */ if (png_ptr->row_number == 0 && png_ptr->pass == 0) { - /* make sure we wrote the header info */ if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) - png_error(png_ptr, - "png_write_info was never called before png_write_row."); + png_error(png_ptr, + "png_write_info was never called before png_write_row."); - /* check for transforms that have been set but were defined out */ #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) if (png_ptr->transformations & PNG_INVERT_MONO) - png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); #endif #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) if (png_ptr->transformations & PNG_FILLER) - png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); #endif #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) if (png_ptr->transformations & PNG_PACKSWAP) - png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); #endif #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) if (png_ptr->transformations & PNG_PACK) - png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); #endif #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) if (png_ptr->transformations & PNG_SHIFT) - png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); #endif #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) if (png_ptr->transformations & PNG_BGR) - png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); #endif #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) if (png_ptr->transformations & PNG_SWAP_BYTES) - png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); #endif - png_write_start_row(png_ptr); + png_write_start_row(png_ptr); } #if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* if interlaced and not interested in row, return */ if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) { - switch (png_ptr->pass) - { - case 0: - if (png_ptr->row_number & 0x07) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 1: - if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 2: - if ((png_ptr->row_number & 0x07) != 4) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 3: - if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 4: - if ((png_ptr->row_number & 0x03) != 2) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 5: - if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 6: - if (!(png_ptr->row_number & 0x01)) - { - png_write_finish_row(png_ptr); - return; - } - break; - } + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + } } #endif - /* set up row info for transformations */ png_ptr->row_info.color_type = png_ptr->color_type; png_ptr->row_info.width = png_ptr->usr_width; png_ptr->row_info.channels = png_ptr->usr_channels; png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * - png_ptr->row_info.channels); + png_ptr->row_info.channels); png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); + png_ptr->row_info.width); png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type); png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width); @@ -229953,67 +208157,50 @@ png_write_row(png_structp png_ptr, png_bytep row) png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth); png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes); - /* Copy user's row into buffer, leaving room for filter byte. */ png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row, - png_ptr->row_info.rowbytes); + png_ptr->row_info.rowbytes); #if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* handle interlacing */ if (png_ptr->interlaced && png_ptr->pass < 6 && - (png_ptr->transformations & PNG_INTERLACE)) + (png_ptr->transformations & PNG_INTERLACE)) { - png_do_write_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass); - /* this should always get caught above, but still ... */ - if (!(png_ptr->row_info.width)) - { - png_write_finish_row(png_ptr); - return; - } + png_do_write_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass); + if (!(png_ptr->row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } } #endif - /* handle other transformations */ if (png_ptr->transformations) - png_do_write_transformations(png_ptr); + png_do_write_transformations(png_ptr); #if defined(PNG_MNG_FEATURES_SUPPORTED) - /* Write filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not write a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) { - /* Intrapixel differencing */ - png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); } #endif - /* Find a filter if necessary, filter the row and write it out. */ png_write_find_filter(png_ptr, &(png_ptr->row_info)); if (png_ptr->write_row_fn != NULL) - (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); } #if defined(PNG_WRITE_FLUSH_SUPPORTED) -/* Set the automatic flush interval or 0 to turn flushing off */ void PNGAPI png_set_flush(png_structp png_ptr, int nrows) { png_debug(1, "in png_set_flush\n"); if (png_ptr == NULL) - return; + return; png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); } -/* flush the current output buffers now */ void PNGAPI png_write_flush(png_structp png_ptr) { @@ -230021,54 +208208,47 @@ png_write_flush(png_structp png_ptr) png_debug(1, "in png_write_flush\n"); if (png_ptr == NULL) - return; - /* We have already written out all of the data */ + return; if (png_ptr->row_number >= png_ptr->num_rows) - return; + return; do { - int ret; + int ret; - /* compress the data */ - ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); - wrote_IDAT = 0; + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); + wrote_IDAT = 0; - /* check for compression errors */ - if (ret != Z_OK) - { - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } - if (!(png_ptr->zstream.avail_out)) - { - /* write the IDAT and reset the zlib output buffer */ - png_write_IDAT(png_ptr, png_ptr->zbuf, - png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - wrote_IDAT = 1; - } + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + wrote_IDAT = 1; + } } while(wrote_IDAT == 1); - /* If there is any data left to be output, write it into a new IDAT */ if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) { - /* write the IDAT and reset the zlib output buffer */ - png_write_IDAT(png_ptr, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; } png_ptr->flush_rows = 0; png_flush(png_ptr); } #endif /* PNG_WRITE_FLUSH_SUPPORTED */ -/* free all memory used by the write */ void PNGAPI png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) { @@ -230082,52 +208262,51 @@ png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) png_debug(1, "in png_destroy_write_struct\n"); if (png_ptr_ptr != NULL) { - png_ptr = *png_ptr_ptr; + png_ptr = *png_ptr_ptr; #ifdef PNG_USER_MEM_SUPPORTED - free_fn = png_ptr->free_fn; - mem_ptr = png_ptr->mem_ptr; + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; #endif } if (info_ptr_ptr != NULL) - info_ptr = *info_ptr_ptr; + info_ptr = *info_ptr_ptr; if (info_ptr != NULL) { - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - if (png_ptr->num_chunk_list) - { - png_free(png_ptr, png_ptr->chunk_list); - png_ptr->chunk_list=NULL; - png_ptr->num_chunk_list=0; - } + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + png_ptr->num_chunk_list=0; + } #endif #ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); #else - png_destroy_struct((png_voidp)info_ptr); + png_destroy_struct((png_voidp)info_ptr); #endif - *info_ptr_ptr = NULL; + *info_ptr_ptr = NULL; } if (png_ptr != NULL) { - png_write_destroy(png_ptr); + png_write_destroy(png_ptr); #ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); #else - png_destroy_struct((png_voidp)png_ptr); + png_destroy_struct((png_voidp)png_ptr); #endif - *png_ptr_ptr = NULL; + *png_ptr_ptr = NULL; } } -/* Free any memory used in png_ptr struct (old method) */ void /* PRIVATE */ png_write_destroy(png_structp png_ptr) { @@ -230142,10 +208321,8 @@ png_write_destroy(png_structp png_ptr) #endif png_debug(1, "in png_write_destroy\n"); - /* free any memory zlib uses */ deflateEnd(&png_ptr->zstream); - /* free our memory. png_free checks NULL for us. */ png_free(png_ptr, png_ptr->zbuf); png_free(png_ptr, png_ptr->row_buf); png_free(png_ptr, png_ptr->prev_row); @@ -230167,7 +208344,6 @@ png_write_destroy(png_structp png_ptr) #endif #ifdef PNG_SETJMP_SUPPORTED - /* reset structure */ png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); #endif @@ -230192,126 +208368,109 @@ png_write_destroy(png_structp png_ptr) #endif } -/* Allow the application to select one or more row filters to use. */ void PNGAPI png_set_filter(png_structp png_ptr, int method, int filters) { png_debug(1, "in png_set_filter\n"); if (png_ptr == NULL) - return; + return; #if defined(PNG_MNG_FEATURES_SUPPORTED) if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (method == PNG_INTRAPIXEL_DIFFERENCING)) - method = PNG_FILTER_TYPE_BASE; + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; #endif if (method == PNG_FILTER_TYPE_BASE) { - switch (filters & (PNG_ALL_FILTERS | 0x07)) - { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { #ifndef PNG_NO_WRITE_FILTER - case 5: - case 6: - case 7: png_warning(png_ptr, "Unknown row filter for method 0"); + case 5: + case 6: + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); #endif /* PNG_NO_WRITE_FILTER */ - case PNG_FILTER_VALUE_NONE: - png_ptr->do_filter=PNG_FILTER_NONE; break; + case PNG_FILTER_VALUE_NONE: + png_ptr->do_filter=PNG_FILTER_NONE; break; #ifndef PNG_NO_WRITE_FILTER - case PNG_FILTER_VALUE_SUB: - png_ptr->do_filter=PNG_FILTER_SUB; break; - case PNG_FILTER_VALUE_UP: - png_ptr->do_filter=PNG_FILTER_UP; break; - case PNG_FILTER_VALUE_AVG: - png_ptr->do_filter=PNG_FILTER_AVG; break; - case PNG_FILTER_VALUE_PAETH: - png_ptr->do_filter=PNG_FILTER_PAETH; break; - default: png_ptr->do_filter = (png_byte)filters; break; + case PNG_FILTER_VALUE_SUB: + png_ptr->do_filter=PNG_FILTER_SUB; break; + case PNG_FILTER_VALUE_UP: + png_ptr->do_filter=PNG_FILTER_UP; break; + case PNG_FILTER_VALUE_AVG: + png_ptr->do_filter=PNG_FILTER_AVG; break; + case PNG_FILTER_VALUE_PAETH: + png_ptr->do_filter=PNG_FILTER_PAETH; break; + default: png_ptr->do_filter = (png_byte)filters; break; #else - default: png_warning(png_ptr, "Unknown row filter for method 0"); + default: png_warning(png_ptr, "Unknown row filter for method 0"); #endif /* PNG_NO_WRITE_FILTER */ - } + } - /* If we have allocated the row_buf, this means we have already started - * with the image and we should have allocated all of the filter buffers - * that have been selected. If prev_row isn't already allocated, then - * it is too late to start using the filters that need it, since we - * will be missing the data in the previous row. If an application - * wants to start and stop using particular filters during compression, - * it should start out with all of the filters, and then add and - * remove them after the start of compression. - */ - if (png_ptr->row_buf != NULL) - { + if (png_ptr->row_buf != NULL) + { #ifndef PNG_NO_WRITE_FILTER - if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } - if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Up filter after starting"); - png_ptr->do_filter &= ~PNG_FILTER_UP; - } - else - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } - } + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_UP; + } + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } - if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Average filter after starting"); - png_ptr->do_filter &= ~PNG_FILTER_AVG; - } - else - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } - } + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_AVG; + } + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } - if ((png_ptr->do_filter & PNG_FILTER_PAETH) && - png_ptr->paeth_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Paeth filter after starting"); - png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); - } - else - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } - } + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } - if (png_ptr->do_filter == PNG_NO_FILTERS) + if (png_ptr->do_filter == PNG_NO_FILTERS) #endif /* PNG_NO_WRITE_FILTER */ - png_ptr->do_filter = PNG_FILTER_NONE; - } + png_ptr->do_filter = PNG_FILTER_NONE; + } } else - png_error(png_ptr, "Unknown custom filter method"); + png_error(png_ptr, "Unknown custom filter method"); } -/* This allows us to influence the way in which libpng chooses the "best" - * filter for the current scanline. While the "minimum-sum-of-absolute- - * differences metric is relatively fast and effective, there is some - * question as to whether it can be improved upon by trying to keep the - * filtered data going to zlib more consistent, hopefully resulting in - * better compression. - */ -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */ +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */ void PNGAPI png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, int num_weights, png_doublep filter_weights, @@ -230321,22 +208480,22 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, png_debug(1, "in png_set_filter_heuristics\n"); if (png_ptr == NULL) - return; + return; if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) { - png_warning(png_ptr, "Unknown filter heuristic method"); - return; + png_warning(png_ptr, "Unknown filter heuristic method"); + return; } if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) { - heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; } if (num_weights < 0 || filter_weights == NULL || - heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) { - num_weights = 0; + num_weights = 0; } png_ptr->num_prev_filters = (png_byte)num_weights; @@ -230344,88 +208503,77 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, if (num_weights > 0) { - if (png_ptr->prev_filters == NULL) - { - png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_byte) * num_weights)); + if (png_ptr->prev_filters == NULL) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_byte) * num_weights)); - /* To make sure that the weighting starts out fairly */ - for (i = 0; i < num_weights; i++) - { - png_ptr->prev_filters[i] = 255; - } - } + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + } - if (png_ptr->filter_weights == NULL) - { - png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + if (png_ptr->filter_weights == NULL) + { + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); - png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); - for (i = 0; i < num_weights; i++) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - } + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + } - for (i = 0; i < num_weights; i++) - { - if (filter_weights[i] < 0.0) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - else - { - png_ptr->inv_filter_weights[i] = - (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); - png_ptr->filter_weights[i] = - (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); - } - } + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] < 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); + png_ptr->filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); + } + } } - /* If, in the future, there are other filter methods, this would - * need to be based on png_ptr->filter. - */ if (png_ptr->filter_costs == NULL) { - png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); - png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) - { - png_ptr->inv_filter_costs[i] = - png_ptr->filter_costs[i] = PNG_COST_FACTOR; - } + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } } - /* Here is where we set the relative costs of the different filters. We - * should take the desired compression level into account when setting - * the costs, so that Paeth, for instance, has a high relative cost at low - * compression levels, while it has a lower relative cost at higher - * compression settings. The filter types are in order of increasing - * relative cost, so it would be possible to do this with an algorithm. - */ for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) { - if (filter_costs == NULL || filter_costs[i] < 0.0) - { - png_ptr->inv_filter_costs[i] = - png_ptr->filter_costs[i] = PNG_COST_FACTOR; - } - else if (filter_costs[i] >= 1.0) - { - png_ptr->inv_filter_costs[i] = - (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); - png_ptr->filter_costs[i] = - (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); - } + if (filter_costs == NULL || filter_costs[i] < 0.0) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + else if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); + png_ptr->filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); + } } } #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ @@ -230435,7 +208583,7 @@ png_set_compression_level(png_structp png_ptr, int level) { png_debug(1, "in png_set_compression_level\n"); if (png_ptr == NULL) - return; + return; png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; png_ptr->zlib_level = level; } @@ -230445,7 +208593,7 @@ png_set_compression_mem_level(png_structp png_ptr, int mem_level) { png_debug(1, "in png_set_compression_mem_level\n"); if (png_ptr == NULL) - return; + return; png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; png_ptr->zlib_mem_level = mem_level; } @@ -230455,7 +208603,7 @@ png_set_compression_strategy(png_structp png_ptr, int strategy) { png_debug(1, "in png_set_compression_strategy\n"); if (png_ptr == NULL) - return; + return; png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; png_ptr->zlib_strategy = strategy; } @@ -230464,18 +208612,17 @@ void PNGAPI png_set_compression_window_bits(png_structp png_ptr, int window_bits) { if (png_ptr == NULL) - return; + return; if (window_bits > 15) - png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); else if (window_bits < 8) - png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); #ifndef WBITS_8_OK - /* avoid libpng bug with 256-byte windows */ if (window_bits == 8) - { - png_warning(png_ptr, "Compression window is being reset to 512"); - window_bits=9; - } + { + png_warning(png_ptr, "Compression window is being reset to 512"); + window_bits=9; + } #endif png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; png_ptr->zlib_window_bits = window_bits; @@ -230486,9 +208633,9 @@ png_set_compression_method(png_structp png_ptr, int method) { png_debug(1, "in png_set_compression_method\n"); if (png_ptr == NULL) - return; + return; if (method != 8) - png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; png_ptr->zlib_method = method; } @@ -230497,7 +208644,7 @@ void PNGAPI png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) { if (png_ptr == NULL) - return; + return; png_ptr->write_row_fn = write_row_fn; } @@ -230508,7 +208655,7 @@ png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr { png_debug(1, "in png_set_write_user_transform_fn\n"); if (png_ptr == NULL) - return; + return; png_ptr->transformations |= PNG_USER_TRANSFORM; png_ptr->write_user_transform_fn = write_user_transform_fn; } @@ -230517,81 +208664,61 @@ png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr #if defined(PNG_INFO_IMAGE_SUPPORTED) void PNGAPI png_write_png(png_structp png_ptr, png_infop info_ptr, - int transforms, voidp params) + int transforms, voidp params) { if (png_ptr == NULL || info_ptr == NULL) - return; + return; #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel from opacity to transparency */ if (transforms & PNG_TRANSFORM_INVERT_ALPHA) - png_set_invert_alpha(png_ptr); + png_set_invert_alpha(png_ptr); #endif - /* Write the file header information. */ png_write_info(png_ptr, info_ptr); - /* ------ these transformations don't touch the info structure ------- */ - #if defined(PNG_WRITE_INVERT_SUPPORTED) - /* invert monochrome pixels */ if (transforms & PNG_TRANSFORM_INVERT_MONO) - png_set_invert_mono(png_ptr); + png_set_invert_mono(png_ptr); #endif #if defined(PNG_WRITE_SHIFT_SUPPORTED) - /* Shift the pixels up to a legal bit depth and fill in - * as appropriate to correctly scale the image. - */ if ((transforms & PNG_TRANSFORM_SHIFT) - && (info_ptr->valid & PNG_INFO_sBIT)) - png_set_shift(png_ptr, &info_ptr->sig_bit); + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); #endif #if defined(PNG_WRITE_PACK_SUPPORTED) - /* pack pixels into bytes */ if (transforms & PNG_TRANSFORM_PACKING) - png_set_packing(png_ptr); + png_set_packing(png_ptr); #endif #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) - /* swap location of alpha bytes from ARGB to RGBA */ if (transforms & PNG_TRANSFORM_SWAP_ALPHA) - png_set_swap_alpha(png_ptr); + png_set_swap_alpha(png_ptr); #endif #if defined(PNG_WRITE_FILLER_SUPPORTED) - /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into - * RGB (4 channels -> 3 channels). The second parameter is not used. - */ if (transforms & PNG_TRANSFORM_STRIP_FILLER) - png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); #endif #if defined(PNG_WRITE_BGR_SUPPORTED) - /* flip BGR pixels to RGB */ if (transforms & PNG_TRANSFORM_BGR) - png_set_bgr(png_ptr); + png_set_bgr(png_ptr); #endif #if defined(PNG_WRITE_SWAP_SUPPORTED) - /* swap bytes of 16-bit files to most significant byte first */ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) - png_set_swap(png_ptr); + png_set_swap(png_ptr); #endif #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) - /* swap bits of 1, 2, 4 bit packed pixel formats */ if (transforms & PNG_TRANSFORM_PACKSWAP) - png_set_packswap(png_ptr); + png_set_packswap(png_ptr); #endif - /* ----------------------- end of transformations ------------------- */ - - /* write the bits */ if (info_ptr->valid & PNG_INFO_IDAT) - png_write_image(png_ptr, info_ptr->row_pointers); + png_write_image(png_ptr, info_ptr->row_pointers); - /* It is REQUIRED to call this to finish writing the rest of the file */ png_write_end(png_ptr, info_ptr); transforms = transforms; /* quiet compiler warnings */ @@ -230602,216 +208729,188 @@ png_write_png(png_structp png_ptr, png_infop info_ptr, /********* End of inlined file: pngwrite.c *********/ /********* Start of inlined file: pngwtran.c *********/ -/* pngwtran.c - transforms the data in a row for PNG writers - * - * Last changed in libpng 1.2.9 April 14, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ #define PNG_INTERNAL #ifdef PNG_WRITE_SUPPORTED -/* Transform the data according to the user's wishes. The order of - * transformations is significant. - */ void /* PRIVATE */ png_do_write_transformations(png_structp png_ptr) { png_debug(1, "in png_do_write_transformations\n"); if (png_ptr == NULL) - return; + return; #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) if (png_ptr->transformations & PNG_USER_TRANSFORM) - if(png_ptr->write_user_transform_fn != NULL) - (*(png_ptr->write_user_transform_fn)) /* user write transform function */ - (png_ptr, /* png_ptr */ - &(png_ptr->row_info), /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_uint_32 rowbytes; number of bytes in row */ - /* png_byte color_type; color type of pixels */ - /* png_byte bit_depth; bit depth of samples */ - /* png_byte channels; number of channels (1-4) */ - /* png_byte pixel_depth; bits per pixel (depth*channels) */ - png_ptr->row_buf + 1); /* start of pixel data for row */ + if(png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* user write transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + png_ptr->row_buf + 1); /* start of pixel data for row */ #endif #if defined(PNG_WRITE_FILLER_SUPPORTED) if (png_ptr->transformations & PNG_FILLER) - png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->flags); + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->flags); #endif #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_WRITE_PACK_SUPPORTED) if (png_ptr->transformations & PNG_PACK) - png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, - (png_uint_32)png_ptr->bit_depth); + png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); #endif #if defined(PNG_WRITE_SWAP_SUPPORTED) if (png_ptr->transformations & PNG_SWAP_BYTES) - png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_WRITE_SHIFT_SUPPORTED) if (png_ptr->transformations & PNG_SHIFT) - png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->shift)); + png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); #endif #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) if (png_ptr->transformations & PNG_SWAP_ALPHA) - png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) if (png_ptr->transformations & PNG_INVERT_ALPHA) - png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_WRITE_BGR_SUPPORTED) if (png_ptr->transformations & PNG_BGR) - png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif #if defined(PNG_WRITE_INVERT_SUPPORTED) if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif } #if defined(PNG_WRITE_PACK_SUPPORTED) -/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The - * row_info bit depth should be 8 (one pixel per byte). The channels - * should be 1 (this only happens on grayscale and paletted images). - */ void /* PRIVATE */ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) { png_debug(1, "in png_do_pack\n"); if (row_info->bit_depth == 8 && #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - row_info->channels == 1) + row_info->channels == 1) { - switch ((int)bit_depth) - { - case 1: - { - png_bytep sp, dp; - int mask, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - sp = row; - dp = row; - mask = 0x80; - v = 0; + sp = row; + dp = row; + mask = 0x80; + v = 0; - for (i = 0; i < row_width; i++) - { - if (*sp != 0) - v |= mask; - sp++; - if (mask > 1) - mask >>= 1; - else - { - mask = 0x80; - *dp = (png_byte)v; - dp++; - v = 0; - } - } - if (mask != 0x80) - *dp = (png_byte)v; - break; - } - case 2: - { - png_bytep sp, dp; - int shift, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + sp++; + if (mask > 1) + mask >>= 1; + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + if (mask != 0x80) + *dp = (png_byte)v; + break; + } + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - sp = row; - dp = row; - shift = 6; - v = 0; - for (i = 0; i < row_width; i++) - { - png_byte value; + sp = row; + dp = row; + shift = 6; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; - value = (png_byte)(*sp & 0x03); - v |= (value << shift); - if (shift == 0) - { - shift = 6; - *dp = (png_byte)v; - dp++; - v = 0; - } - else - shift -= 2; - sp++; - } - if (shift != 6) - *dp = (png_byte)v; - break; - } - case 4: - { - png_bytep sp, dp; - int shift, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 2; + sp++; + } + if (shift != 6) + *dp = (png_byte)v; + break; + } + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - sp = row; - dp = row; - shift = 4; - v = 0; - for (i = 0; i < row_width; i++) - { - png_byte value; + sp = row; + dp = row; + shift = 4; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; - value = (png_byte)(*sp & 0x0f); - v |= (value << shift); + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); - if (shift == 0) - { - shift = 4; - *dp = (png_byte)v; - dp++; - v = 0; - } - else - shift -= 4; + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 4; - sp++; - } - if (shift != 4) - *dp = (png_byte)v; - break; - } - } - row_info->bit_depth = (png_byte)bit_depth; - row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_info->width); + sp++; + } + if (shift != 4) + *dp = (png_byte)v; + break; + } + } + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); } } #endif #if defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Shift pixel values to take advantage of whole range. Pass the - * true number of bits in bit_depth. The row should be packed - * according to row_info->bit_depth. Thus, if you had a row of - * bit depth 4, but the pixels only had values from 0 to 7, you - * would pass 3 as bit_depth, and this routine would translate the - * data to 0 to 15. - */ void /* PRIVATE */ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) { @@ -230821,116 +208920,115 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) #else if ( #endif - row_info->color_type != PNG_COLOR_TYPE_PALETTE) + row_info->color_type != PNG_COLOR_TYPE_PALETTE) { - int shift_start[4], shift_dec[4]; - int channels = 0; + int shift_start[4], shift_dec[4]; + int channels = 0; - if (row_info->color_type & PNG_COLOR_MASK_COLOR) - { - shift_start[channels] = row_info->bit_depth - bit_depth->red; - shift_dec[channels] = bit_depth->red; - channels++; - shift_start[channels] = row_info->bit_depth - bit_depth->green; - shift_dec[channels] = bit_depth->green; - channels++; - shift_start[channels] = row_info->bit_depth - bit_depth->blue; - shift_dec[channels] = bit_depth->blue; - channels++; - } - else - { - shift_start[channels] = row_info->bit_depth - bit_depth->gray; - shift_dec[channels] = bit_depth->gray; - channels++; - } - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - shift_start[channels] = row_info->bit_depth - bit_depth->alpha; - shift_dec[channels] = bit_depth->alpha; - channels++; - } + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } - /* with low row depths, could only be grayscale, so one channel */ - if (row_info->bit_depth < 8) - { - png_bytep bp = row; - png_uint_32 i; - png_byte mask; - png_uint_32 row_bytes = row_info->rowbytes; + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_uint_32 i; + png_byte mask; + png_uint_32 row_bytes = row_info->rowbytes; - if (bit_depth->gray == 1 && row_info->bit_depth == 2) - mask = 0x55; - else if (row_info->bit_depth == 4 && bit_depth->gray == 3) - mask = 0x11; - else - mask = 0xff; + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + else + mask = 0xff; - for (i = 0; i < row_bytes; i++, bp++) - { - png_uint_16 v; - int j; + for (i = 0; i < row_bytes; i++, bp++) + { + png_uint_16 v; + int j; - v = *bp; - *bp = 0; - for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) - { - if (j > 0) - *bp |= (png_byte)((v << j) & 0xff); - else - *bp |= (png_byte)((v >> (-j)) & mask); - } - } - } - else if (row_info->bit_depth == 8) - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = channels * row_info->width; + v = *bp; + *bp = 0; + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & mask); + } + } + } + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; - for (i = 0; i < istop; i++, bp++) - { + for (i = 0; i < istop; i++, bp++) + { - png_uint_16 v; - int j; - int c = (int)(i%channels); + png_uint_16 v; + int j; + int c = (int)(i%channels); - v = *bp; - *bp = 0; - for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) - { - if (j > 0) - *bp |= (png_byte)((v << j) & 0xff); - else - *bp |= (png_byte)((v >> (-j)) & 0xff); - } - } - } - else - { - png_bytep bp; - png_uint_32 i; - png_uint_32 istop = channels * row_info->width; + v = *bp; + *bp = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & 0xff); + } + } + } + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; - for (bp = row, i = 0; i < istop; i++) - { - int c = (int)(i%channels); - png_uint_16 value, v; - int j; + for (bp = row, i = 0; i < istop; i++) + { + int c = (int)(i%channels); + png_uint_16 value, v; + int j; - v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); - value = 0; - for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) - { - if (j > 0) - value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); - else - value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); - } - *bp++ = (png_byte)(value >> 8); - *bp++ = (png_byte)(value & 0xff); - } - } + v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); + value = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + else + value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); + } + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + } } } #endif @@ -230944,81 +209042,77 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) if (row != NULL && row_info != NULL) #endif { - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This converts from ARGB to RGBA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save; - } - } - /* This converts from AARRGGBB to RRGGBBAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save[2]; - save[0] = *(sp++); - save[1] = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save[0]; - *(dp++) = save[1]; - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This converts from AG to GA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save; - } - } - /* This converts from AAGG to GGAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save[2]; - save[0] = *(sp++); - save[1] = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save[0]; - *(dp++) = save[1]; - } - } - } + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } } } #endif @@ -231032,143 +209126,121 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) if (row != NULL && row_info != NULL) #endif { - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This inverts the alpha channel in RGBA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=3; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - /* This inverts the alpha channel in RRGGBBAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + sp+=3; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=6; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This inverts the alpha channel in GA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + sp+=6; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - *(dp++) = *(sp++); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - /* This inverts the alpha channel in GGAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=2; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - } + for (i = 0, sp = dp = row; i < row_width; i++) + { + sp+=2; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } } } #endif #if defined(PNG_MNG_FEATURES_SUPPORTED) -/* undoes intrapixel differencing */ void /* PRIVATE */ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) { png_debug(1, "in png_do_write_intrapixel\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && + row != NULL && row_info != NULL && #endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) + (row_info->color_type & PNG_COLOR_MASK_COLOR)) { - int bytes_per_pixel; - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - png_bytep rp; - png_uint_32 i; + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 3; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 4; - else - return; + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - *(rp) = (png_byte)((*rp - *(rp+1))&0xff); - *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); - } - } - else if (row_info->bit_depth == 16) - { - png_bytep rp; - png_uint_32 i; + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp+1))&0xff); + *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 6; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 8; - else - return; + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); - png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); - png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); - png_uint_32 red = (png_uint_32)((s0-s1) & 0xffffL); - png_uint_32 blue = (png_uint_32)((s2-s1) & 0xffffL); - *(rp ) = (png_byte)((red >> 8) & 0xff); - *(rp+1) = (png_byte)(red & 0xff); - *(rp+4) = (png_byte)((blue >> 8) & 0xff); - *(rp+5) = (png_byte)(blue & 0xff); - } - } + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); + png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); + png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); + png_uint_32 red = (png_uint_32)((s0-s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2-s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } } } #endif /* PNG_MNG_FEATURES_SUPPORTED */ @@ -231176,23 +209248,11 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) /********* End of inlined file: pngwtran.c *********/ /********* Start of inlined file: pngwutil.c *********/ -/* pngwutil.c - utilities to write a PNG file - * - * Last changed in libpng 1.2.20 Septhember 3, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ #define PNG_INTERNAL #ifdef PNG_WRITE_SUPPORTED -/* Place a 32-bit number into a buffer in PNG byte order. We work - * with unsigned numbers for convenience, although one supported - * ancillary chunk uses signed (two's complement) numbers. - */ void PNGAPI png_save_uint_32(png_bytep buf, png_uint_32 i) { @@ -231202,10 +209262,6 @@ png_save_uint_32(png_bytep buf, png_uint_32 i) buf[3] = (png_byte)(i & 0xff); } -/* The png_save_int_32 function assumes integers are stored in two's - * complement format. If this isn't the case, then this routine needs to - * be modified to write data in two's complement format. - */ void PNGAPI png_save_int_32(png_bytep buf, png_int_32 i) { @@ -231215,10 +209271,6 @@ png_save_int_32(png_bytep buf, png_int_32 i) buf[3] = (png_byte)(i & 0xff); } -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ void PNGAPI png_save_uint_16(png_bytep buf, unsigned int i) { @@ -231226,15 +209278,6 @@ png_save_uint_16(png_bytep buf, unsigned int i) buf[1] = (png_byte)(i & 0xff); } -/* Write a PNG chunk all at once. The type is an array of ASCII characters - * representing the chunk name. The array must be at least 4 bytes in - * length, and does not need to be null terminated. To be safe, pass the - * pre-defined chunk names here, and if you need a new one, define it - * where the others are defined. The length is the length of the data. - * All the data must be present. If that is not possible, use the - * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() - * functions instead. - */ void PNGAPI png_write_chunk(png_structp png_ptr, png_bytep chunk_name, png_bytep data, png_size_t length) @@ -231245,10 +209288,6 @@ png_write_chunk(png_structp png_ptr, png_bytep chunk_name, png_write_chunk_end(png_ptr); } -/* Write the start of a PNG chunk. The type is the chunk type. - * The total_length is the sum of the lengths of all the data you will be - * passing in png_write_chunk_data(). - */ void PNGAPI png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, png_uint_32 length) @@ -231257,35 +209296,25 @@ png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length); if(png_ptr == NULL) return; - /* write the length */ png_save_uint_32(buf, length); png_write_data(png_ptr, buf, (png_size_t)4); - /* write the chunk name */ png_write_data(png_ptr, chunk_name, (png_size_t)4); - /* reset the crc and run it over the chunk name */ png_reset_crc(png_ptr); png_calculate_crc(png_ptr, chunk_name, (png_size_t)4); } -/* Write the data of a PNG chunk started with png_write_chunk_start(). - * Note that multiple calls to this function are allowed, and that the - * sum of the lengths from these calls *must* add up to the total_length - * given to png_write_chunk_start(). - */ void PNGAPI png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) { - /* write the data, and run the CRC over it */ if(png_ptr == NULL) return; if (data != NULL && length > 0) { - png_calculate_crc(png_ptr, data, length); - png_write_data(png_ptr, data, length); + png_calculate_crc(png_ptr, data, length); + png_write_data(png_ptr, data, length); } } -/* Finish a chunk started with png_write_chunk_start(). */ void PNGAPI png_write_chunk_end(png_structp png_ptr) { @@ -231293,51 +209322,36 @@ png_write_chunk_end(png_structp png_ptr) if(png_ptr == NULL) return; - /* write the crc */ png_save_uint_32(buf, png_ptr->crc); png_write_data(png_ptr, buf, (png_size_t)4); } -/* Simple function to write the signature. If we have already written - * the magic bytes of the signature, or more likely, the PNG stream is - * being embedded into another stream and doesn't need its own signature, - * we should call png_set_sig_bytes() to tell libpng how many of the - * bytes have already been written. - */ void /* PRIVATE */ png_write_sig(png_structp png_ptr) { png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; - /* write the rest of the 8 byte signature */ png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], - (png_size_t)8 - png_ptr->sig_bytes); + (png_size_t)8 - png_ptr->sig_bytes); if(png_ptr->sig_bytes < 3) - png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; } #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) -/* - * This pair of functions encapsulates the operation of (a) compressing a - * text string, and (b) issuing it later as a series of chunk data writes. - * The compression_state structure is shared context for these functions - * set up by the caller in order to make the whole mess thread-safe. - */ typedef struct { - char *input; /* the uncompressed input data */ - int input_len; /* its length */ - int num_output_ptr; /* number of output pointers used */ - int max_output_ptr; /* size of output_ptr */ - png_charpp output_ptr; /* array of pointers to output */ + char *input; /* the uncompressed input data */ + int input_len; /* its length */ + int num_output_ptr; /* number of output pointers used */ + int max_output_ptr; /* size of output_ptr */ + png_charpp output_ptr; /* array of pointers to output */ } compression_state; -/* compress given text into storage in the png_ptr structure */ static int /* PRIVATE */ png_text_compress(png_structp png_ptr, - png_charp text, png_size_t text_len, int compression, - compression_state *comp) + png_charp text, png_size_t text_len, int compression, + compression_state *comp) { int ret; @@ -231347,208 +209361,165 @@ png_text_compress(png_structp png_ptr, comp->input = NULL; comp->input_len = 0; - /* we may just want to pass the text right through */ if (compression == PNG_TEXT_COMPRESSION_NONE) { - comp->input = text; - comp->input_len = text_len; - return((int)text_len); + comp->input = text; + comp->input_len = text_len; + return((int)text_len); } if (compression >= PNG_TEXT_COMPRESSION_LAST) { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[50]; - png_snprintf(msg, 50, "Unknown compression type %d", compression); - png_warning(png_ptr, msg); + char msg[50]; + png_snprintf(msg, 50, "Unknown compression type %d", compression); + png_warning(png_ptr, msg); #else - png_warning(png_ptr, "Unknown compression type"); + png_warning(png_ptr, "Unknown compression type"); #endif } - /* We can't write the chunk until we find out how much data we have, - * which means we need to run the compressor first and save the - * output. This shouldn't be a problem, as the vast majority of - * comments should be reasonable, but we will set up an array of - * malloc'd pointers to be sure. - * - * If we knew the application was well behaved, we could simplify this - * greatly by assuming we can always malloc an output buffer large - * enough to hold the compressed text ((1001 * text_len / 1000) + 12) - * and malloc this directly. The only time this would be a bad idea is - * if we can't malloc more than 64K and we have 64K of random input - * data, or if the input string is incredibly large (although this - * wouldn't cause a failure, just a slowdown due to swapping). - */ - - /* set up the compression buffers */ png_ptr->zstream.avail_in = (uInt)text_len; png_ptr->zstream.next_in = (Bytef *)text; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; - /* this is the same compression loop as in png_write_row() */ do { - /* compress the data */ - ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); - if (ret != Z_OK) - { - /* error */ - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - /* check to see if we need more room */ - if (!(png_ptr->zstream.avail_out)) - { - /* make sure the output array has room */ - if (comp->num_output_ptr >= comp->max_output_ptr) - { - int old_max; + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + if (!(png_ptr->zstream.avail_out)) + { + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; - old_max = comp->max_output_ptr; - comp->max_output_ptr = comp->num_output_ptr + 4; - if (comp->output_ptr != NULL) - { - png_charpp old_ptr; + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; - old_ptr = comp->output_ptr; - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charpp))); - png_memcpy(comp->output_ptr, old_ptr, old_max - * png_sizeof (png_charp)); - png_free(png_ptr, old_ptr); - } - else - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charp))); - } + old_ptr = comp->output_ptr; + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, old_max + * png_sizeof (png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charp))); + } - /* save the data */ - comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, - png_ptr->zbuf_size); - comp->num_output_ptr++; + comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; - /* and reset the buffer */ - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = png_ptr->zbuf; - } - /* continue until we don't have any more to compress */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } } while (png_ptr->zstream.avail_in); - /* finish the compression */ do { - /* tell zlib we are finished */ - ret = deflate(&png_ptr->zstream, Z_FINISH); + ret = deflate(&png_ptr->zstream, Z_FINISH); - if (ret == Z_OK) - { - /* check to see if we need more room */ - if (!(png_ptr->zstream.avail_out)) - { - /* check to make sure our output array has room */ - if (comp->num_output_ptr >= comp->max_output_ptr) - { - int old_max; + if (ret == Z_OK) + { + if (!(png_ptr->zstream.avail_out)) + { + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; - old_max = comp->max_output_ptr; - comp->max_output_ptr = comp->num_output_ptr + 4; - if (comp->output_ptr != NULL) - { - png_charpp old_ptr; + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; - old_ptr = comp->output_ptr; - /* This could be optimized to realloc() */ - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charpp))); - png_memcpy(comp->output_ptr, old_ptr, - old_max * png_sizeof (png_charp)); - png_free(png_ptr, old_ptr); - } - else - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charp))); - } + old_ptr = comp->output_ptr; + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, + old_max * png_sizeof (png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * + png_sizeof (png_charp))); + } - /* save off the data */ - comp->output_ptr[comp->num_output_ptr] = - (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); - png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, - png_ptr->zbuf_size); - comp->num_output_ptr++; + comp->output_ptr[comp->num_output_ptr] = + (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; - /* and reset the buffer pointers */ - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = png_ptr->zbuf; - } - } - else if (ret != Z_STREAM_END) - { - /* we got an error */ - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } } while (ret != Z_STREAM_END); - /* text length is number of buffers plus last buffer */ text_len = png_ptr->zbuf_size * comp->num_output_ptr; if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) - text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; return((int)text_len); } -/* ship the compressed text out via chunk writes */ static void /* PRIVATE */ png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) { int i; - /* handle the no-compression case */ if (comp->input) { - png_write_chunk_data(png_ptr, (png_bytep)comp->input, - (png_size_t)comp->input_len); - return; + png_write_chunk_data(png_ptr, (png_bytep)comp->input, + (png_size_t)comp->input_len); + return; } - /* write saved output buffers, if any */ for (i = 0; i < comp->num_output_ptr; i++) { - png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i], - png_ptr->zbuf_size); - png_free(png_ptr, comp->output_ptr[i]); - comp->output_ptr[i]=NULL; + png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i], + png_ptr->zbuf_size); + png_free(png_ptr, comp->output_ptr[i]); + comp->output_ptr[i]=NULL; } if (comp->max_output_ptr != 0) - png_free(png_ptr, comp->output_ptr); - comp->output_ptr=NULL; - /* write anything left in zbuf */ + png_free(png_ptr, comp->output_ptr); + comp->output_ptr=NULL; if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) - png_write_chunk_data(png_ptr, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_write_chunk_data(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); - /* reset zlib for another zTXt/iTXt or image data */ deflateReset(&png_ptr->zstream); png_ptr->zstream.data_type = Z_BINARY; } #endif -/* Write the IHDR chunk, and update the png_struct with the necessary - * information. Note that the rest of this code depends upon this - * information being correct. - */ void /* PRIVATE */ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, int compression_type, int filter_type, @@ -231560,90 +209531,79 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_byte buf[13]; /* buffer to store the IHDR info */ png_debug(1, "in png_write_IHDR\n"); - /* Check that we have valid input data from the application info */ switch (color_type) { - case PNG_COLOR_TYPE_GRAY: - switch (bit_depth) - { - case 1: - case 2: - case 4: - case 8: - case 16: png_ptr->channels = 1; break; - default: png_error(png_ptr,"Invalid bit depth for grayscale image"); - } - break; - case PNG_COLOR_TYPE_RGB: - if (bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth for RGB image"); - png_ptr->channels = 3; - break; - case PNG_COLOR_TYPE_PALETTE: - switch (bit_depth) - { - case 1: - case 2: - case 4: - case 8: png_ptr->channels = 1; break; - default: png_error(png_ptr, "Invalid bit depth for paletted image"); - } - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - if (bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); - png_ptr->channels = 2; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - if (bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth for RGBA image"); - png_ptr->channels = 4; - break; - default: - png_error(png_ptr, "Invalid image color type specified"); + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + case 16: png_ptr->channels = 1; break; + default: png_error(png_ptr,"Invalid bit depth for grayscale image"); + } + break; + case PNG_COLOR_TYPE_RGB: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGB image"); + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: png_ptr->channels = 1; break; + default: png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGBA image"); + png_ptr->channels = 4; + break; + default: + png_error(png_ptr, "Invalid image color type specified"); } if (compression_type != PNG_COMPRESSION_TYPE_BASE) { - png_warning(png_ptr, "Invalid compression type specified"); - compression_type = PNG_COMPRESSION_TYPE_BASE; + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; } - /* Write filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not write a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ if ( #if defined(PNG_MNG_FEATURES_SUPPORTED) - !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && - (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) && - (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && #endif - filter_type != PNG_FILTER_TYPE_BASE) + filter_type != PNG_FILTER_TYPE_BASE) { - png_warning(png_ptr, "Invalid filter type specified"); - filter_type = PNG_FILTER_TYPE_BASE; + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; } #ifdef PNG_WRITE_INTERLACING_SUPPORTED if (interlace_type != PNG_INTERLACE_NONE && - interlace_type != PNG_INTERLACE_ADAM7) + interlace_type != PNG_INTERLACE_ADAM7) { - png_warning(png_ptr, "Invalid interlace type specified"); - interlace_type = PNG_INTERLACE_ADAM7; + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; } #else interlace_type=PNG_INTERLACE_NONE; #endif - /* save off the relevent information */ png_ptr->bit_depth = (png_byte)bit_depth; png_ptr->color_type = (png_byte)color_type; png_ptr->interlaced = (png_byte)interlace_type; @@ -231656,12 +209616,10 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); - /* set the usr info, so any transformations can modify it */ png_ptr->usr_width = png_ptr->width; png_ptr->usr_bit_depth = png_ptr->bit_depth; png_ptr->usr_channels = png_ptr->channels; - /* pack the header information into the buffer */ png_save_uint_32(buf, width); png_save_uint_32(buf + 4, height); buf[8] = (png_byte)bit_depth; @@ -231670,53 +209628,45 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, buf[11] = (png_byte)filter_type; buf[12] = (png_byte)interlace_type; - /* write the chunk */ png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); - /* initialize zlib with PNG info */ png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; if (!(png_ptr->do_filter)) { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || - png_ptr->bit_depth < 8) - png_ptr->do_filter = PNG_FILTER_NONE; - else - png_ptr->do_filter = PNG_ALL_FILTERS; + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + else + png_ptr->do_filter = PNG_ALL_FILTERS; } if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) { - if (png_ptr->do_filter != PNG_FILTER_NONE) - png_ptr->zlib_strategy = Z_FILTERED; - else - png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; + if (png_ptr->do_filter != PNG_FILTER_NONE) + png_ptr->zlib_strategy = Z_FILTERED; + else + png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; } if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) - png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) - png_ptr->zlib_mem_level = 8; + png_ptr->zlib_mem_level = 8; if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) - png_ptr->zlib_window_bits = 15; + png_ptr->zlib_window_bits = 15; if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) - png_ptr->zlib_method = 8; + png_ptr->zlib_method = 8; if (deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, - png_ptr->zlib_method, png_ptr->zlib_window_bits, - png_ptr->zlib_mem_level, png_ptr->zlib_strategy) != Z_OK) - png_error(png_ptr, "zlib failed to initialize compressor"); + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy) != Z_OK) + png_error(png_ptr, "zlib failed to initialize compressor"); png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - /* libpng is not interested in zstream.data_type */ - /* set it to a predefined value, to avoid its evaluation inside zlib */ png_ptr->zstream.data_type = Z_BINARY; png_ptr->mode = PNG_HAVE_IHDR; } -/* write the palette. We are careful not to trust png_color to be in the - * correct order for PNG, so people can redefine it to any convenient - * structure. - */ void /* PRIVATE */ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) { @@ -231730,26 +209680,26 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) png_debug(1, "in png_write_PLTE\n"); if (( #if defined(PNG_MNG_FEATURES_SUPPORTED) - !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && #endif - num_pal == 0) || num_pal > 256) + num_pal == 0) || num_pal > 256) { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_error(png_ptr, "Invalid number of colors in palette"); - } - else - { - png_warning(png_ptr, "Invalid number of colors in palette"); - return; - } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } } if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) { - png_warning(png_ptr, - "Ignoring request to write a PLTE chunk in grayscale PNG"); - return; + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + return; } png_ptr->num_palette = (png_uint_16)num_pal; @@ -231759,27 +209709,25 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) #ifndef PNG_NO_POINTER_INDEXING for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) { - buf[0] = pal_ptr->red; - buf[1] = pal_ptr->green; - buf[2] = pal_ptr->blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); } #else - /* This is a little slower but some buggy compilers need to do this instead */ pal_ptr=palette; for (i = 0; i < num_pal; i++) { - buf[0] = pal_ptr[i].red; - buf[1] = pal_ptr[i].green; - buf[2] = pal_ptr[i].blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); } #endif png_write_chunk_end(png_ptr); png_ptr->mode |= PNG_HAVE_PLTE; } -/* write an IDAT chunk */ void /* PRIVATE */ png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) { @@ -231788,50 +209736,44 @@ png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) #endif png_debug(1, "in png_write_IDAT\n"); - /* Optimize the CMF field in the zlib stream. */ - /* This hack of the zlib stream is compliant to the stream specification. */ if (!(png_ptr->mode & PNG_HAVE_IDAT) && - png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) { - unsigned int z_cmf = data[0]; /* zlib compression method and flags */ - if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) - { - /* Avoid memory underflows and multiplication overflows. */ - /* The conditions below are practically always satisfied; - however, they still must be checked. */ - if (length >= 2 && - png_ptr->height < 16384 && png_ptr->width < 16384) - { - png_uint_32 uncompressed_idat_size = png_ptr->height * - ((png_ptr->width * - png_ptr->channels * png_ptr->bit_depth + 15) >> 3); - unsigned int z_cinfo = z_cmf >> 4; - unsigned int half_z_window_size = 1 << (z_cinfo + 7); - while (uncompressed_idat_size <= half_z_window_size && - half_z_window_size >= 256) - { - z_cinfo--; - half_z_window_size >>= 1; - } - z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); - if (data[0] != (png_byte)z_cmf) - { - data[0] = (png_byte)z_cmf; - data[1] &= 0xe0; - data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); - } - } - } - else - png_error(png_ptr, - "Invalid zlib compression method or flags in IDAT"); + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + if (length >= 2 && + png_ptr->height < 16384 && png_ptr->width < 16384) + { + png_uint_32 uncompressed_idat_size = png_ptr->height * + ((png_ptr->width * + png_ptr->channels * png_ptr->bit_depth + 15) >> 3); + unsigned int z_cinfo = z_cmf >> 4; + unsigned int half_z_window_size = 1 << (z_cinfo + 7); + while (uncompressed_idat_size <= half_z_window_size && + half_z_window_size >= 256) + { + z_cinfo--; + half_z_window_size >>= 1; + } + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + if (data[0] != (png_byte)z_cmf) + { + data[0] = (png_byte)z_cmf; + data[1] &= 0xe0; + data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); + } + } + } + else + png_error(png_ptr, + "Invalid zlib compression method or flags in IDAT"); } png_write_chunk(png_ptr, png_IDAT, data, length); png_ptr->mode |= PNG_HAVE_IDAT; } -/* write an IEND chunk */ void /* PRIVATE */ png_write_IEND(png_structp png_ptr) { @@ -231840,12 +209782,11 @@ png_write_IEND(png_structp png_ptr) #endif png_debug(1, "in png_write_IEND\n"); png_write_chunk(png_ptr, png_IEND, png_bytep_NULL, - (png_size_t)0); + (png_size_t)0); png_ptr->mode |= PNG_HAVE_IEND; } #if defined(PNG_WRITE_gAMA_SUPPORTED) -/* write a gAMA chunk */ #ifdef PNG_FLOATING_POINT_SUPPORTED void /* PRIVATE */ png_write_gAMA(png_structp png_ptr, double file_gamma) @@ -231857,7 +209798,6 @@ png_write_gAMA(png_structp png_ptr, double file_gamma) png_byte buf[4]; png_debug(1, "in png_write_gAMA\n"); - /* file_gamma is saved in 1/100,000ths */ igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); png_save_uint_32(buf, igamma); png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); @@ -231873,7 +209813,6 @@ png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) png_byte buf[4]; png_debug(1, "in png_write_gAMA\n"); - /* file_gamma is saved in 1/100,000ths */ png_save_uint_32(buf, (png_uint_32)file_gamma); png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); } @@ -231881,7 +209820,6 @@ png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) #endif #if defined(PNG_WRITE_sRGB_SUPPORTED) -/* write a sRGB chunk */ void /* PRIVATE */ png_write_sRGB(png_structp png_ptr, int srgb_intent) { @@ -231892,15 +209830,14 @@ png_write_sRGB(png_structp png_ptr, int srgb_intent) png_debug(1, "in png_write_sRGB\n"); if(srgb_intent >= PNG_sRGB_INTENT_LAST) - png_warning(png_ptr, - "Invalid sRGB rendering intent specified"); + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); buf[0]=(png_byte)srgb_intent; png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); } #endif #if defined(PNG_WRITE_iCCP_SUPPORTED) -/* write an iCCP chunk */ void /* PRIVATE */ png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, png_charp profile, int profile_len) @@ -231922,51 +209859,50 @@ png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, comp.input_len = 0; if (name == NULL || (name_len = png_check_keyword(png_ptr, name, - &new_name)) == 0) + &new_name)) == 0) { - png_warning(png_ptr, "Empty keyword in iCCP chunk"); - return; + png_warning(png_ptr, "Empty keyword in iCCP chunk"); + return; } if (compression_type != PNG_COMPRESSION_TYPE_BASE) - png_warning(png_ptr, "Unknown compression type in iCCP chunk"); + png_warning(png_ptr, "Unknown compression type in iCCP chunk"); if (profile == NULL) - profile_len = 0; + profile_len = 0; if (profile_len > 3) - embedded_profile_len = - ((*( (png_bytep)profile ))<<24) | - ((*( (png_bytep)profile+1))<<16) | - ((*( (png_bytep)profile+2))<< 8) | - ((*( (png_bytep)profile+3)) ); + embedded_profile_len = + ((*( (png_bytep)profile ))<<24) | + ((*( (png_bytep)profile+1))<<16) | + ((*( (png_bytep)profile+2))<< 8) | + ((*( (png_bytep)profile+3)) ); if (profile_len < embedded_profile_len) - { - png_warning(png_ptr, - "Embedded profile length too large in iCCP chunk"); - return; - } + { + png_warning(png_ptr, + "Embedded profile length too large in iCCP chunk"); + return; + } if (profile_len > embedded_profile_len) - { - png_warning(png_ptr, - "Truncating profile to actual length in iCCP chunk"); - profile_len = embedded_profile_len; - } + { + png_warning(png_ptr, + "Truncating profile to actual length in iCCP chunk"); + profile_len = embedded_profile_len; + } if (profile_len) - profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len, - PNG_COMPRESSION_TYPE_BASE, &comp); + profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len, + PNG_COMPRESSION_TYPE_BASE, &comp); - /* make sure we include the NULL after the name and the compression type */ png_write_chunk_start(png_ptr, png_iCCP, - (png_uint_32)name_len+profile_len+2); + (png_uint_32)name_len+profile_len+2); new_name[name_len+1]=0x00; png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2); if (profile_len) - png_write_compressed_data_out(png_ptr, &comp); + png_write_compressed_data_out(png_ptr, &comp); png_write_chunk_end(png_ptr); png_free(png_ptr, new_name); @@ -231974,7 +209910,6 @@ png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, #endif #if defined(PNG_WRITE_sPLT_SUPPORTED) -/* write a sPLT chunk */ void /* PRIVATE */ png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) { @@ -231993,61 +209928,59 @@ png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) png_debug(1, "in png_write_sPLT\n"); if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr, - spalette->name, &new_name))==0) + spalette->name, &new_name))==0) { - png_warning(png_ptr, "Empty keyword in sPLT chunk"); - return; + png_warning(png_ptr, "Empty keyword in sPLT chunk"); + return; } - /* make sure we include the NULL after the name */ png_write_chunk_start(png_ptr, png_sPLT, - (png_uint_32)(name_len + 2 + palette_size)); + (png_uint_32)(name_len + 2 + palette_size)); png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1); png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1); - /* loop through each palette entry, writing appropriately */ #ifndef PNG_NO_POINTER_INDEXING for (ep = spalette->entries; epentries+spalette->nentries; ep++) { - if (spalette->depth == 8) - { - entrybuf[0] = (png_byte)ep->red; - entrybuf[1] = (png_byte)ep->green; - entrybuf[2] = (png_byte)ep->blue; - entrybuf[3] = (png_byte)ep->alpha; - png_save_uint_16(entrybuf + 4, ep->frequency); - } - else - { - png_save_uint_16(entrybuf + 0, ep->red); - png_save_uint_16(entrybuf + 2, ep->green); - png_save_uint_16(entrybuf + 4, ep->blue); - png_save_uint_16(entrybuf + 6, ep->alpha); - png_save_uint_16(entrybuf + 8, ep->frequency); - } - png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); } #else ep=spalette->entries; for (i=0; i>spalette->nentries; i++) { - if (spalette->depth == 8) - { - entrybuf[0] = (png_byte)ep[i].red; - entrybuf[1] = (png_byte)ep[i].green; - entrybuf[2] = (png_byte)ep[i].blue; - entrybuf[3] = (png_byte)ep[i].alpha; - png_save_uint_16(entrybuf + 4, ep[i].frequency); - } - else - { - png_save_uint_16(entrybuf + 0, ep[i].red); - png_save_uint_16(entrybuf + 2, ep[i].green); - png_save_uint_16(entrybuf + 4, ep[i].blue); - png_save_uint_16(entrybuf + 6, ep[i].alpha); - png_save_uint_16(entrybuf + 8, ep[i].frequency); - } - png_write_chunk_data(png_ptr, entrybuf, entry_size); + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + png_write_chunk_data(png_ptr, entrybuf, entry_size); } #endif @@ -232057,7 +209990,6 @@ png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) #endif #if defined(PNG_WRITE_sBIT_SUPPORTED) -/* write the sBIT chunk */ void /* PRIVATE */ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) { @@ -232068,44 +210000,43 @@ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) png_size_t size; png_debug(1, "in png_write_sBIT\n"); - /* make sure we don't depend upon the order of PNG_COLOR_8 */ if (color_type & PNG_COLOR_MASK_COLOR) { - png_byte maxbits; + png_byte maxbits; - maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : - png_ptr->usr_bit_depth); - if (sbit->red == 0 || sbit->red > maxbits || - sbit->green == 0 || sbit->green > maxbits || - sbit->blue == 0 || sbit->blue > maxbits) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - buf[0] = sbit->red; - buf[1] = sbit->green; - buf[2] = sbit->blue; - size = 3; + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; } else { - if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - buf[0] = sbit->gray; - size = 1; + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->gray; + size = 1; } if (color_type & PNG_COLOR_MASK_ALPHA) { - if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - buf[size++] = sbit->alpha; + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[size++] = sbit->alpha; } png_write_chunk(png_ptr, png_sBIT, buf, size); @@ -232113,7 +210044,6 @@ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) #endif #if defined(PNG_WRITE_cHRM_SUPPORTED) -/* write the cHRM chunk */ #ifdef PNG_FLOATING_POINT_SUPPORTED void /* PRIVATE */ png_write_cHRM(png_structp png_ptr, double white_x, double white_y, @@ -232127,15 +210057,14 @@ png_write_cHRM(png_structp png_ptr, double white_x, double white_y, png_uint_32 itemp; png_debug(1, "in png_write_cHRM\n"); - /* each value is saved in 1/100,000ths */ if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 || - white_x + white_y > 1.0) + white_x + white_y > 1.0) { - png_warning(png_ptr, "Invalid cHRM white point specified"); + png_warning(png_ptr, "Invalid cHRM white point specified"); #if !defined(PNG_NO_CONSOLE_IO) - fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y); + fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y); #endif - return; + return; } itemp = (png_uint_32)(white_x * 100000.0 + 0.5); png_save_uint_32(buf, itemp); @@ -232144,8 +210073,8 @@ png_write_cHRM(png_structp png_ptr, double white_x, double white_y, if (red_x < 0 || red_y < 0 || red_x + red_y > 1.0) { - png_warning(png_ptr, "Invalid cHRM red point specified"); - return; + png_warning(png_ptr, "Invalid cHRM red point specified"); + return; } itemp = (png_uint_32)(red_x * 100000.0 + 0.5); png_save_uint_32(buf + 8, itemp); @@ -232154,8 +210083,8 @@ png_write_cHRM(png_structp png_ptr, double white_x, double white_y, if (green_x < 0 || green_y < 0 || green_x + green_y > 1.0) { - png_warning(png_ptr, "Invalid cHRM green point specified"); - return; + png_warning(png_ptr, "Invalid cHRM green point specified"); + return; } itemp = (png_uint_32)(green_x * 100000.0 + 0.5); png_save_uint_32(buf + 16, itemp); @@ -232164,8 +210093,8 @@ png_write_cHRM(png_structp png_ptr, double white_x, double white_y, if (blue_x < 0 || blue_y < 0 || blue_x + blue_y > 1.0) { - png_warning(png_ptr, "Invalid cHRM blue point specified"); - return; + png_warning(png_ptr, "Invalid cHRM blue point specified"); + return; } itemp = (png_uint_32)(blue_x * 100000.0 + 0.5); png_save_uint_32(buf + 24, itemp); @@ -232188,38 +210117,37 @@ png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, png_byte buf[32]; png_debug(1, "in png_write_cHRM\n"); - /* each value is saved in 1/100,000ths */ if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L) { - png_warning(png_ptr, "Invalid fixed cHRM white point specified"); + png_warning(png_ptr, "Invalid fixed cHRM white point specified"); #if !defined(PNG_NO_CONSOLE_IO) - fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y); + fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y); #endif - return; + return; } png_save_uint_32(buf, (png_uint_32)white_x); png_save_uint_32(buf + 4, (png_uint_32)white_y); if (red_x + red_y > 100000L) { - png_warning(png_ptr, "Invalid cHRM fixed red point specified"); - return; + png_warning(png_ptr, "Invalid cHRM fixed red point specified"); + return; } png_save_uint_32(buf + 8, (png_uint_32)red_x); png_save_uint_32(buf + 12, (png_uint_32)red_y); if (green_x + green_y > 100000L) { - png_warning(png_ptr, "Invalid fixed cHRM green point specified"); - return; + png_warning(png_ptr, "Invalid fixed cHRM green point specified"); + return; } png_save_uint_32(buf + 16, (png_uint_32)green_x); png_save_uint_32(buf + 20, (png_uint_32)green_y); if (blue_x + blue_y > 100000L) { - png_warning(png_ptr, "Invalid fixed cHRM blue point specified"); - return; + png_warning(png_ptr, "Invalid fixed cHRM blue point specified"); + return; } png_save_uint_32(buf + 24, (png_uint_32)blue_x); png_save_uint_32(buf + 28, (png_uint_32)blue_y); @@ -232230,7 +210158,6 @@ png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, #endif #if defined(PNG_WRITE_tRNS_SUPPORTED) -/* write the tRNS chunk */ void /* PRIVATE */ png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, int num_trans, int color_type) @@ -232243,49 +210170,45 @@ png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, png_debug(1, "in png_write_tRNS\n"); if (color_type == PNG_COLOR_TYPE_PALETTE) { - if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) - { - png_warning(png_ptr,"Invalid number of transparent colors specified"); - return; - } - /* write the chunk out as it is */ - png_write_chunk(png_ptr, png_tRNS, trans, (png_size_t)num_trans); + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_warning(png_ptr,"Invalid number of transparent colors specified"); + return; + } + png_write_chunk(png_ptr, png_tRNS, trans, (png_size_t)num_trans); } else if (color_type == PNG_COLOR_TYPE_GRAY) { - /* one 16 bit value */ - if(tran->gray >= (1 << png_ptr->bit_depth)) - { - png_warning(png_ptr, - "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); - return; - } - png_save_uint_16(buf, tran->gray); - png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); + if(tran->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, tran->gray); + png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); } else if (color_type == PNG_COLOR_TYPE_RGB) { - /* three 16 bit values */ - png_save_uint_16(buf, tran->red); - png_save_uint_16(buf + 2, tran->green); - png_save_uint_16(buf + 4, tran->blue); - if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) - { - png_warning(png_ptr, - "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); - return; - } - png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); + if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); } else { - png_warning(png_ptr, "Can't write tRNS with an alpha channel"); + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); } } #endif #if defined(PNG_WRITE_bKGD_SUPPORTED) -/* write the background chunk */ void /* PRIVATE */ png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) { @@ -232297,48 +210220,47 @@ png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) png_debug(1, "in png_write_bKGD\n"); if (color_type == PNG_COLOR_TYPE_PALETTE) { - if ( + if ( #if defined(PNG_MNG_FEATURES_SUPPORTED) - (png_ptr->num_palette || - (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && #endif - back->index > png_ptr->num_palette) - { - png_warning(png_ptr, "Invalid background palette index"); - return; - } - buf[0] = back->index; - png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); + back->index > png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + buf[0] = back->index; + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); } else if (color_type & PNG_COLOR_MASK_COLOR) { - png_save_uint_16(buf, back->red); - png_save_uint_16(buf + 2, back->green); - png_save_uint_16(buf + 4, back->blue); - if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) - { - png_warning(png_ptr, - "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); - return; - } - png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); + if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); } else { - if(back->gray >= (1 << png_ptr->bit_depth)) - { - png_warning(png_ptr, - "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); - return; - } - png_save_uint_16(buf, back->gray); - png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); + if(back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, back->gray); + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); } } #endif #if defined(PNG_WRITE_hIST_SUPPORTED) -/* write the histogram */ void /* PRIVATE */ png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) { @@ -232351,34 +210273,24 @@ png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) png_debug(1, "in png_write_hIST\n"); if (num_hist > (int)png_ptr->num_palette) { - png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist, - png_ptr->num_palette); - png_warning(png_ptr, "Invalid number of histogram entries specified"); - return; + png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist, + png_ptr->num_palette); + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; } png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); for (i = 0; i < num_hist; i++) { - png_save_uint_16(buf, hist[i]); - png_write_chunk_data(png_ptr, buf, (png_size_t)2); + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); } png_write_chunk_end(png_ptr); } #endif #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ - defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) -/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, - * and if invalid, correct the keyword rather than discarding the entire - * chunk. The PNG 1.0 specification requires keywords 1-79 characters in - * length, forbids leading or trailing whitespace, multiple internal spaces, - * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. - * - * The new_key is allocated to hold the corrected keyword and must be freed - * by the calling routine. This avoids problems with trying to write to - * static keywords without having to have duplicate copies of the strings. - */ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) png_size_t /* PRIVATE */ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) { @@ -232392,8 +210304,8 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) if (key == NULL || (key_len = png_strlen(key)) == 0) { - png_warning(png_ptr, "zero length keyword"); - return ((png_size_t)0); + png_warning(png_ptr, "zero length keyword"); + return ((png_size_t)0); } png_debug1(2, "Keyword to be checked is '%s'\n", key); @@ -232401,97 +210313,93 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); if (*new_key == NULL) { - png_warning(png_ptr, "Out of memory while procesing keyword"); - return ((png_size_t)0); + png_warning(png_ptr, "Out of memory while procesing keyword"); + return ((png_size_t)0); } - /* Replace non-printing characters with a blank and print a warning */ for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) { - if ((png_byte)*kp < 0x20 || - ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1)) - { + if ((png_byte)*kp < 0x20 || + ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1)) + { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[40]; + char msg[40]; - png_snprintf(msg, 40, - "invalid keyword character 0x%02X", (png_byte)*kp); - png_warning(png_ptr, msg); + png_snprintf(msg, 40, + "invalid keyword character 0x%02X", (png_byte)*kp); + png_warning(png_ptr, msg); #else - png_warning(png_ptr, "invalid character in keyword"); + png_warning(png_ptr, "invalid character in keyword"); #endif - *dp = ' '; - } - else - { - *dp = *kp; - } + *dp = ' '; + } + else + { + *dp = *kp; + } } *dp = '\0'; - /* Remove any trailing white space. */ kp = *new_key + key_len - 1; if (*kp == ' ') { - png_warning(png_ptr, "trailing spaces removed from keyword"); + png_warning(png_ptr, "trailing spaces removed from keyword"); - while (*kp == ' ') - { - *(kp--) = '\0'; - key_len--; - } + while (*kp == ' ') + { + *(kp--) = '\0'; + key_len--; + } } - /* Remove any leading white space. */ kp = *new_key; if (*kp == ' ') { - png_warning(png_ptr, "leading spaces removed from keyword"); + png_warning(png_ptr, "leading spaces removed from keyword"); - while (*kp == ' ') - { - kp++; - key_len--; - } + while (*kp == ' ') + { + kp++; + key_len--; + } } png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp); - /* Remove multiple internal spaces. */ for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) { - if (*kp == ' ' && kflag == 0) - { - *(dp++) = *kp; - kflag = 1; - } - else if (*kp == ' ') - { - key_len--; - kwarn=1; - } - else - { - *(dp++) = *kp; - kflag = 0; - } + if (*kp == ' ' && kflag == 0) + { + *(dp++) = *kp; + kflag = 1; + } + else if (*kp == ' ') + { + key_len--; + kwarn=1; + } + else + { + *(dp++) = *kp; + kflag = 0; + } } *dp = '\0'; if(kwarn) - png_warning(png_ptr, "extra interior spaces removed from keyword"); + png_warning(png_ptr, "extra interior spaces removed from keyword"); if (key_len == 0) { - png_free(png_ptr, *new_key); - *new_key=NULL; - png_warning(png_ptr, "Zero length keyword"); + png_free(png_ptr, *new_key); + *new_key=NULL; + png_warning(png_ptr, "Zero length keyword"); } if (key_len > 79) { - png_warning(png_ptr, "keyword length must be 1 - 79 characters"); - new_key[79] = '\0'; - key_len = 79; + png_warning(png_ptr, "keyword length must be 1 - 79 characters"); + new_key[79] = '\0'; + key_len = 79; } return (key_len); @@ -232499,7 +210407,6 @@ png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) #endif #if defined(PNG_WRITE_tEXt_SUPPORTED) -/* write a tEXt chunk */ void /* PRIVATE */ png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, png_size_t text_len) @@ -232513,26 +210420,19 @@ png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, png_debug(1, "in png_write_tEXt\n"); if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) { - png_warning(png_ptr, "Empty keyword in tEXt chunk"); - return; + png_warning(png_ptr, "Empty keyword in tEXt chunk"); + return; } if (text == NULL || *text == '\0') - text_len = 0; + text_len = 0; else - text_len = png_strlen(text); + text_len = png_strlen(text); - /* make sure we include the 0 after the key */ png_write_chunk_start(png_ptr, png_tEXt, (png_uint_32)key_len+text_len+1); - /* - * We leave it to the application to meet PNG-1.0 requirements on the - * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of - * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. - * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. - */ png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); if (text_len) - png_write_chunk_data(png_ptr, (png_bytep)text, text_len); + png_write_chunk_data(png_ptr, (png_bytep)text, text_len); png_write_chunk_end(png_ptr); png_free(png_ptr, new_key); @@ -232540,7 +210440,6 @@ png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, #endif #if defined(PNG_WRITE_zTXt_SUPPORTED) -/* write a compressed text chunk */ void /* PRIVATE */ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, png_size_t text_len, int compression) @@ -232563,46 +210462,39 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) { - png_warning(png_ptr, "Empty keyword in zTXt chunk"); - return; + png_warning(png_ptr, "Empty keyword in zTXt chunk"); + return; } if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) { - png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); - png_free(png_ptr, new_key); - return; + png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); + png_free(png_ptr, new_key); + return; } text_len = png_strlen(text); - /* compute the compressed data; do it now for the length */ text_len = png_text_compress(png_ptr, text, text_len, compression, - &comp); + &comp); - /* write start of chunk */ png_write_chunk_start(png_ptr, png_zTXt, (png_uint_32) - (key_len+text_len+2)); - /* write key */ + (key_len+text_len+2)); png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); png_free(png_ptr, new_key); buf[0] = (png_byte)compression; - /* write compression */ png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); - /* write the compressed data */ png_write_compressed_data_out(png_ptr, &comp); - /* close the chunk */ png_write_chunk_end(png_ptr); } #endif #if defined(PNG_WRITE_iTXt_SUPPORTED) -/* write an iTXt chunk */ void /* PRIVATE */ png_write_iTXt(png_structp png_ptr, int compression, png_charp key, - png_charp lang, png_charp lang_key, png_charp text) + png_charp lang, png_charp lang_key, png_charp text) { #ifdef PNG_USE_LOCAL_ARRAYS PNG_iTXt; @@ -232621,56 +210513,44 @@ png_write_iTXt(png_structp png_ptr, int compression, png_charp key, if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) { - png_warning(png_ptr, "Empty keyword in iTXt chunk"); - return; + png_warning(png_ptr, "Empty keyword in iTXt chunk"); + return; } if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) { - png_warning(png_ptr, "Empty language field in iTXt chunk"); - new_lang = NULL; - lang_len = 0; + png_warning(png_ptr, "Empty language field in iTXt chunk"); + new_lang = NULL; + lang_len = 0; } if (lang_key == NULL) - lang_key_len = 0; + lang_key_len = 0; else - lang_key_len = png_strlen(lang_key); + lang_key_len = png_strlen(lang_key); if (text == NULL) - text_len = 0; + text_len = 0; else - text_len = png_strlen(text); + text_len = png_strlen(text); - /* compute the compressed data; do it now for the length */ text_len = png_text_compress(png_ptr, text, text_len, compression-2, - &comp); - - /* make sure we include the compression flag, the compression byte, - * and the NULs after the key, lang, and lang_key parts */ + &comp); png_write_chunk_start(png_ptr, png_iTXt, - (png_uint_32)( - 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ - + key_len - + lang_len - + lang_key_len - + text_len)); + (png_uint_32)( + 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ + + key_len + + lang_len + + lang_key_len + + text_len)); - /* - * We leave it to the application to meet PNG-1.0 requirements on the - * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of - * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. - * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. - */ png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); - /* set the compression flag */ if (compression == PNG_ITXT_COMPRESSION_NONE || \ - compression == PNG_TEXT_COMPRESSION_NONE) - cbuf[0] = 0; + compression == PNG_TEXT_COMPRESSION_NONE) + cbuf[0] = 0; else /* compression == PNG_ITXT_COMPRESSION_zTXt */ - cbuf[0] = 1; - /* set the compression method */ + cbuf[0] = 1; cbuf[1] = 0; png_write_chunk_data(png_ptr, cbuf, 2); @@ -232682,12 +210562,11 @@ png_write_iTXt(png_structp png_ptr, int compression, png_charp key, png_write_chunk_end(png_ptr); png_free(png_ptr, new_key); if (new_lang) - png_free(png_ptr, new_lang); + png_free(png_ptr, new_lang); } #endif #if defined(PNG_WRITE_oFFs_SUPPORTED) -/* write the oFFs chunk */ void /* PRIVATE */ png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, int unit_type) @@ -232699,7 +210578,7 @@ png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, png_debug(1, "in png_write_oFFs\n"); if (unit_type >= PNG_OFFSET_LAST) - png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); png_save_int_32(buf, x_offset); png_save_int_32(buf + 4, y_offset); @@ -232709,7 +210588,6 @@ png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, } #endif #if defined(PNG_WRITE_pCAL_SUPPORTED) -/* write the pCAL chunk (described in the PNG extensions document) */ void /* PRIVATE */ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) @@ -232725,7 +210603,7 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams); if (type >= PNG_EQUATION_LAST) - png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len); @@ -232734,15 +210612,13 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, total_len = purpose_len + units_len + 10; params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams - *png_sizeof(png_uint_32))); + *png_sizeof(png_uint_32))); - /* Find the length of each parameter, making sure we don't count the - null terminator for the last parameter. */ for (i = 0; i < nparams; i++) { - params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); - png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]); - total_len += (png_size_t)params_len[i]; + params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]); + total_len += (png_size_t)params_len[i]; } png_debug1(3, "pCAL total length = %d\n", (int)total_len); @@ -232759,8 +210635,8 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, for (i = 0; i < nparams; i++) { - png_write_chunk_data(png_ptr, (png_bytep)params[i], - (png_size_t)params_len[i]); + png_write_chunk_data(png_ptr, (png_bytep)params[i], + (png_size_t)params_len[i]); } png_free(png_ptr, params_len); @@ -232769,7 +210645,6 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, #endif #if defined(PNG_WRITE_sCAL_SUPPORTED) -/* write the sCAL chunk */ #if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) void /* PRIVATE */ png_write_sCAL(png_structp png_ptr, int unit, double width, double height) @@ -232784,19 +210659,18 @@ png_write_sCAL(png_structp png_ptr, int unit, double width, double height) buf[0] = (char)unit; #if defined(_WIN32_WCE) -/* sprintf() function is not supported on WindowsCE */ { - wchar_t wc_buf[32]; - size_t wc_len; - swprintf(wc_buf, TEXT("%12.12e"), width); - wc_len = wcslen(wc_buf); - WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, NULL); - total_len = wc_len + 2; - swprintf(wc_buf, TEXT("%12.12e"), height); - wc_len = wcslen(wc_buf); - WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len, - NULL, NULL); - total_len += wc_len; + wchar_t wc_buf[32]; + size_t wc_len; + swprintf(wc_buf, TEXT("%12.12e"), width); + wc_len = wcslen(wc_buf); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, NULL); + total_len = wc_len + 2; + swprintf(wc_buf, TEXT("%12.12e"), height); + wc_len = wcslen(wc_buf); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len, + NULL, NULL); + total_len += wc_len; } #else png_snprintf(buf + 1, 63, "%12.12e", width); @@ -232827,12 +210701,12 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, total_len = wlen + hlen + 2; if (total_len > 64) { - png_warning(png_ptr, "Can't write sCAL (buffer too small)"); - return; + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); + return; } buf[0] = (png_byte)unit; - png_memcpy(buf + 1, width, wlen + 1); /* append the '\0' here */ + png_memcpy(buf + 1, width, wlen + 1); /* append the '\0' here */ png_memcpy(buf + wlen + 2, height, hlen); /* do NOT append the '\0' here */ png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len); @@ -232843,7 +210717,6 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, #endif #if defined(PNG_WRITE_pHYs_SUPPORTED) -/* write the pHYs chunk */ void /* PRIVATE */ png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, @@ -232856,7 +210729,7 @@ png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, png_debug(1, "in png_write_pHYs\n"); if (unit_type >= PNG_RESOLUTION_LAST) - png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); png_save_uint_32(buf, x_pixels_per_unit); png_save_uint_32(buf + 4, y_pixels_per_unit); @@ -232867,9 +210740,6 @@ png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, #endif #if defined(PNG_WRITE_tIME_SUPPORTED) -/* Write the tIME chunk. Use either png_convert_from_struct_tm() - * or png_convert_from_time_t(), or fill in the structure yourself. - */ void /* PRIVATE */ png_write_tIME(png_structp png_ptr, png_timep mod_time) { @@ -232880,11 +210750,11 @@ png_write_tIME(png_structp png_ptr, png_timep mod_time) png_debug(1, "in png_write_tIME\n"); if (mod_time->month > 12 || mod_time->month < 1 || - mod_time->day > 31 || mod_time->day < 1 || - mod_time->hour > 23 || mod_time->second > 60) + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) { - png_warning(png_ptr, "Invalid time specified for tIME chunk"); - return; + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; } png_save_uint_16(buf, mod_time->year); @@ -232898,24 +210768,18 @@ png_write_tIME(png_structp png_ptr, png_timep mod_time) } #endif -/* initializes the row writing capability of libpng */ void /* PRIVATE */ png_write_start_row(png_structp png_ptr) { #ifdef PNG_WRITE_INTERLACING_SUPPORTED #ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* start of interlace block */ int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - /* offset to next interlace block */ int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - /* start of interlace block in the y direction */ int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - /* offset to next interlace block in the y direction */ int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif #endif @@ -232924,96 +210788,85 @@ png_write_start_row(png_structp png_ptr) png_debug(1, "in png_write_start_row\n"); buf_size = (png_size_t)(PNG_ROWBYTES( - png_ptr->usr_channels*png_ptr->usr_bit_depth,png_ptr->width)+1); + png_ptr->usr_channels*png_ptr->usr_bit_depth,png_ptr->width)+1); - /* set up row buffer */ png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; #ifndef PNG_NO_WRITE_FILTERING - /* set up filtering buffer, if using this filter */ if (png_ptr->do_filter & PNG_FILTER_SUB) { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; } - /* We only need to keep the previous row if we are using one of these. */ if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) { - /* set up previous row buffer */ - png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); - png_memset(png_ptr->prev_row, 0, buf_size); + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); + png_memset(png_ptr->prev_row, 0, buf_size); - if (png_ptr->do_filter & PNG_FILTER_UP) - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } - if (png_ptr->do_filter & PNG_FILTER_AVG) - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } - if (png_ptr->do_filter & PNG_FILTER_PAETH) - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } #endif /* PNG_NO_WRITE_FILTERING */ } #ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* if interlaced, we need to set up width and height of pass */ if (png_ptr->interlaced) { - if (!(png_ptr->transformations & PNG_INTERLACE)) - { - png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - - png_pass_ystart[0]) / png_pass_yinc[0]; - png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - - png_pass_start[0]) / png_pass_inc[0]; - } - else - { - png_ptr->num_rows = png_ptr->height; - png_ptr->usr_width = png_ptr->width; - } + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } } else #endif { - png_ptr->num_rows = png_ptr->height; - png_ptr->usr_width = png_ptr->width; + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; } png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_ptr->zstream.next_out = png_ptr->zbuf; } -/* Internal use only. Called when finished processing a row of data. */ void /* PRIVATE */ png_write_finish_row(png_structp png_ptr) { #ifdef PNG_WRITE_INTERLACING_SUPPORTED #ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* start of interlace block */ int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - /* offset to next interlace block */ int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - /* start of interlace block in the y direction */ int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - /* offset to next interlace block in the y direction */ int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif #endif @@ -233021,87 +210874,76 @@ png_write_finish_row(png_structp png_ptr) int ret; png_debug(1, "in png_write_finish_row\n"); - /* next row */ png_ptr->row_number++; - /* see if we are done */ if (png_ptr->row_number < png_ptr->num_rows) - return; + return; #ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* if interlaced, go to next pass */ if (png_ptr->interlaced) { - png_ptr->row_number = 0; - if (png_ptr->transformations & PNG_INTERLACE) - { - png_ptr->pass++; - } - else - { - /* loop until we find a non-zero width or height pass */ - do - { - png_ptr->pass++; - if (png_ptr->pass >= 7) - break; - png_ptr->usr_width = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - if (png_ptr->transformations & PNG_INTERLACE) - break; - } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + else + { + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (png_ptr->transformations & PNG_INTERLACE) + break; + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); - } + } - /* reset the row above the image for the next pass */ - if (png_ptr->pass < 7) - { - if (png_ptr->prev_row != NULL) - png_memset(png_ptr->prev_row, 0, - (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* - png_ptr->usr_bit_depth,png_ptr->width))+1); - return; - } + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + png_memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth,png_ptr->width))+1); + return; + } } #endif - /* if we get here, we've just written the last row, so we need - to flush the compressor */ do { - /* tell the compressor we are done */ - ret = deflate(&png_ptr->zstream, Z_FINISH); - /* check for an error */ - if (ret == Z_OK) - { - /* check to see if we need more room */ - if (!(png_ptr->zstream.avail_out)) - { - png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - else if (ret != Z_STREAM_END) - { - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } + ret = deflate(&png_ptr->zstream, Z_FINISH); + if (ret == Z_OK) + { + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } } while (ret != Z_STREAM_END); - /* write any extra space */ if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) { - png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - - png_ptr->zstream.avail_out); + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - + png_ptr->zstream.avail_out); } deflateReset(&png_ptr->zstream); @@ -233109,180 +210951,156 @@ png_write_finish_row(png_structp png_ptr) } #if defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Pick out the correct pixels for the interlace pass. - * The basic idea here is to go through the row with a source - * pointer and a destination pointer (sp and dp), and copy the - * correct pixels for the pass. As the row gets compacted, - * sp will always be >= dp, so we should never overwrite anything. - * See the default: case for the easiest code to understand. - */ void /* PRIVATE */ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) { #ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* start of interlace block */ int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - /* offset to next interlace block */ int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; #endif png_debug(1, "in png_do_write_interlace\n"); - /* we don't have to do anything on the last pass (6) */ #if defined(PNG_USELESS_TESTS_SUPPORTED) if (row != NULL && row_info != NULL && pass < 6) #else if (pass < 6) #endif { - /* each pixel depth is handled separately */ - switch (row_info->pixel_depth) - { - case 1: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - dp = row; - d = 0; - shift = 7; - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 3); - value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; - d |= (value << shift); + dp = row; + d = 0; + shift = 7; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); - if (shift == 0) - { - shift = 7; - *dp++ = (png_byte)d; - d = 0; - } - else - shift--; + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + else + shift--; - } - if (shift != 7) - *dp = (png_byte)d; - break; - } - case 2: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + } + if (shift != 7) + *dp = (png_byte)d; + break; + } + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - dp = row; - shift = 6; - d = 0; - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 2); - value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; - d |= (value << shift); + dp = row; + shift = 6; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); - if (shift == 0) - { - shift = 6; - *dp++ = (png_byte)d; - d = 0; - } - else - shift -= 2; - } - if (shift != 6) - *dp = (png_byte)d; - break; - } - case 4: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + break; + } + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; - dp = row; - shift = 4; - d = 0; - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 1); - value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; - d |= (value << shift); + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); - if (shift == 0) - { - shift = 4; - *dp++ = (png_byte)d; - d = 0; - } - else - shift -= 4; - } - if (shift != 4) - *dp = (png_byte)d; - break; - } - default: - { - png_bytep sp; - png_bytep dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - png_size_t pixel_bytes; + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + break; + } + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; - /* start at the beginning */ - dp = row; - /* find out how many bytes each pixel takes up */ - pixel_bytes = (row_info->pixel_depth >> 3); - /* loop through the row, only looking at the pixels that - matter */ - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - /* find out where the original pixel is */ - sp = row + (png_size_t)i * pixel_bytes; - /* move the pixel */ - if (dp != sp) - png_memcpy(dp, sp, pixel_bytes); - /* next pixel */ - dp += pixel_bytes; - } - break; - } - } - /* set new row width */ - row_info->width = (row_info->width + - png_pass_inc[pass] - 1 - - png_pass_start[pass]) / - png_pass_inc[pass]; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_info->width); + dp = row; + pixel_bytes = (row_info->pixel_depth >> 3); + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)i * pixel_bytes; + if (dp != sp) + png_memcpy(dp, sp, pixel_bytes); + dp += pixel_bytes; + } + break; + } + } + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); } } #endif -/* This filters the row, chooses which filter to use, if it has not already - * been specified by the application, and then writes the row out with the - * chosen filter. - */ #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) #define PNG_HISHIFT 10 #define PNG_LOMASK ((png_uint_32)0xffffL) @@ -233301,7 +211119,6 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) #endif png_debug(1, "in png_write_find_filter\n"); - /* find out how many bytes offset each pixel is */ bpp = (row_info->pixel_depth + 7) >> 3; prev_row = png_ptr->prev_row; @@ -233311,654 +211128,604 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) row_buf = best_row; mins = PNG_MAXSUM; - /* The prediction method we use is to find which method provides the - * smallest value when summing the absolute values of the distances - * from zero, using anything >= 128 as negative numbers. This is known - * as the "minimum sum of absolute differences" heuristic. Other - * heuristics are the "weighted minimum sum of absolute differences" - * (experimental and can in theory improve compression), and the "zlib - * predictive" method (not implemented yet), which does test compressions - * of lines using different filter methods, and then chooses the - * (series of) filter(s) that give minimum compressed data size (VERY - * computationally expensive). - * - * GRR 980525: consider also - * (1) minimum sum of absolute differences from running average (i.e., - * keep running sum of non-absolute differences & count of bytes) - * [track dispersion, too? restart average if dispersion too large?] - * (1b) minimum sum of absolute differences from sliding average, probably - * with window size <= deflate window (usually 32K) - * (2) minimum sum of squared differences from zero or running average - * (i.e., ~ root-mean-square approach) - */ - - /* We don't need to test the 'no filter' case if this is the only filter - * that has been chosen, as it doesn't actually do anything to the data. - */ if ((filter_to_do & PNG_FILTER_NONE) && - filter_to_do != PNG_FILTER_NONE) + filter_to_do != PNG_FILTER_NONE) { - png_bytep rp; - png_uint_32 sum = 0; - png_uint_32 i; - int v; + png_bytep rp; + png_uint_32 sum = 0; + png_uint_32 i; + int v; - for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) - { - v = *rp; - sum += (v < 128) ? v : 256 - v; - } + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - png_uint_32 sumhi, sumlo; - int j; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ - /* Reduce the sum if we match any of the previous rows */ - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } - /* Factor in the cost of this filter (this is here for completeness, - * but it makes no sense to have a "cost" for the NONE filter, as - * it has the minimum possible computational cost - none). - */ - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> - PNG_COST_SHIFT; + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } #endif - mins = sum; + mins = sum; } - /* sub filter */ if (filter_to_do == PNG_FILTER_SUB) - /* it's the only filter so no testing is needed */ { - png_bytep rp, lp, dp; - png_uint_32 i; - for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; - i++, rp++, dp++) - { - *dp = *rp; - } - for (lp = row_buf + 1; i < row_bytes; - i++, rp++, lp++, dp++) - { - *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); - } - best_row = png_ptr->sub_row; + png_bytep rp, lp, dp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + best_row = png_ptr->sub_row; } else if (filter_to_do & PNG_FILTER_SUB) { - png_bytep rp, dp, lp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - /* We temporarily increase the "minimum sum" by the factor we - * would reduce the sum of this filter, so that we can do the - * early exit comparison without scaling the sum each time. - */ - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } #endif - for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; - i++, rp++, dp++) - { - v = *dp = *rp; + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; - sum += (v < 128) ? v : 256 - v; - } - for (lp = row_buf + 1; i < row_bytes; - i++, rp++, lp++, dp++) - { - v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); - sum += (v < 128) ? v : 256 - v; + sum += (v < 128) ? v : 256 - v; - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) - { - sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } - sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } #endif - if (sum < mins) - { - mins = sum; - best_row = png_ptr->sub_row; - } + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } } - /* up filter */ if (filter_to_do == PNG_FILTER_UP) { - png_bytep rp, dp, pp; - png_uint_32 i; + png_bytep rp, dp, pp; + png_uint_32 i; - for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, - pp = prev_row + 1; i < row_bytes; - i++, rp++, pp++, dp++) - { - *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); - } - best_row = png_ptr->up_row; + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + best_row = png_ptr->up_row; } else if (filter_to_do & PNG_FILTER_UP) { - png_bytep rp, dp, pp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } #endif - for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, - pp = prev_row + 1; i < row_bytes; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - sum += (v < 128) ? v : 256 - v; + sum += (v < 128) ? v : 256 - v; - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } #endif - if (sum < mins) - { - mins = sum; - best_row = png_ptr->up_row; - } + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } } - /* avg filter */ if (filter_to_do == PNG_FILTER_AVG) { - png_bytep rp, dp, pp, lp; - png_uint_32 i; - for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); - } - for (lp = row_buf + 1; i < row_bytes; i++) - { - *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) - & 0xff); - } - best_row = png_ptr->avg_row; + png_bytep rp, dp, pp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; } else if (filter_to_do & PNG_FILTER_AVG) { - png_bytep rp, dp, pp, lp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } #endif - for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); - sum += (v < 128) ? v : 256 - v; - } - for (lp = row_buf + 1; i < row_bytes; i++) - { - v = *dp++ = - (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); - sum += (v < 128) ? v : 256 - v; + sum += (v < 128) ? v : 256 - v; - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } #endif - if (sum < mins) - { - mins = sum; - best_row = png_ptr->avg_row; - } + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } } - /* Paeth filter */ if (filter_to_do == PNG_FILTER_PAETH) { - png_bytep rp, dp, pp, cp, lp; - png_uint_32 i; - for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - } + png_bytep rp, dp, pp, cp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } - for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) - { - int a, b, c, pa, pb, pc, p; + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; - b = *pp++; - c = *cp++; - a = *lp++; + b = *pp++; + c = *cp++; + a = *lp++; - p = b - c; - pc = a - c; + p = b - c; + pc = a - c; #ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); #else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; #endif - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; - *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); - } - best_row = png_ptr->paeth_row; + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; } else if (filter_to_do & PNG_FILTER_PAETH) { - png_bytep rp, dp, pp, cp, lp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } #endif - for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - sum += (v < 128) ? v : 256 - v; - } + sum += (v < 128) ? v : 256 - v; + } - for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) - { - int a, b, c, pa, pb, pc, p; + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; - b = *pp++; - c = *cp++; - a = *lp++; + b = *pp++; + c = *cp++; + a = *lp++; #ifndef PNG_SLOW_PAETH - p = b - c; - pc = a - c; + p = b - c; + pc = a - c; #ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); #else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; #endif - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; #else /* PNG_SLOW_PAETH */ - p = a + b - c; - pa = abs(p - a); - pb = abs(p - b); - pc = abs(p - c); - if (pa <= pb && pa <= pc) - p = a; - else if (pb <= pc) - p = b; - else - p = c; + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; #endif /* PNG_SLOW_PAETH */ - v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); - sum += (v < 128) ? v : 256 - v; + sum += (v < 128) ? v : 256 - v; - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } #endif - if (sum < mins) - { - best_row = png_ptr->paeth_row; - } + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } } #endif /* PNG_NO_WRITE_FILTER */ - /* Do the actual writing of the filtered row data from the chosen filter. */ png_write_filtered_row(png_ptr, best_row); #ifndef PNG_NO_WRITE_FILTER #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - /* Save the type of filter we picked this time for future calculations */ if (png_ptr->num_prev_filters > 0) { - int j; - for (j = 1; j < num_p_filters; j++) - { - png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; - } - png_ptr->prev_filters[j] = best_row[0]; + int j; + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + png_ptr->prev_filters[j] = best_row[0]; } #endif #endif /* PNG_NO_WRITE_FILTER */ } -/* Do the actual writing of a previously filtered row. */ void /* PRIVATE */ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) { png_debug(1, "in png_write_filtered_row\n"); png_debug1(2, "filter = %d\n", filtered_row[0]); - /* set up the zlib input buffer */ png_ptr->zstream.next_in = filtered_row; png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; - /* repeat until we have compressed all the data */ do { - int ret; /* return of zlib */ + int ret; /* return of zlib */ - /* compress the data */ - ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); - /* check for compression errors */ - if (ret != Z_OK) - { - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } - /* see if it is time to write another IDAT */ - if (!(png_ptr->zstream.avail_out)) - { - /* write the IDAT and reset the zlib output buffer */ - png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - /* repeat until all data has been compressed */ + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } } while (png_ptr->zstream.avail_in); - /* swap the current and previous rows */ if (png_ptr->prev_row != NULL) { - png_bytep tptr; + png_bytep tptr; - tptr = png_ptr->prev_row; - png_ptr->prev_row = png_ptr->row_buf; - png_ptr->row_buf = tptr; + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; } - /* finish row - updates counters and flushes zlib if last row */ png_write_finish_row(png_ptr); #if defined(PNG_WRITE_FLUSH_SUPPORTED) png_ptr->flush_rows++; if (png_ptr->flush_dist > 0 && - png_ptr->flush_rows >= png_ptr->flush_dist) + png_ptr->flush_rows >= png_ptr->flush_dist) { - png_write_flush(png_ptr); + png_write_flush(png_ptr); } #endif } @@ -233989,219 +211756,219 @@ using ::free; static void pngReadCallback (png_structp pngReadStruct, png_bytep data, png_size_t length) { - InputStream* const in = (InputStream*) png_get_io_ptr (pngReadStruct); - in->read (data, (int) length); + InputStream* const in = (InputStream*) png_get_io_ptr (pngReadStruct); + in->read (data, (int) length); } struct PNGErrorStruct {}; static void pngErrorCallback (png_structp, png_const_charp) { - throw PNGErrorStruct(); + throw PNGErrorStruct(); } Image* juce_loadPNGImageFromStream (InputStream& in) { - Image* image = 0; + Image* image = 0; - png_structp pngReadStruct; - png_infop pngInfoStruct; + png_structp pngReadStruct; + png_infop pngInfoStruct; - pngReadStruct = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); + pngReadStruct = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); - if (pngReadStruct != 0) - { - pngInfoStruct = png_create_info_struct (pngReadStruct); + if (pngReadStruct != 0) + { + pngInfoStruct = png_create_info_struct (pngReadStruct); - if (pngInfoStruct == 0) - { - png_destroy_read_struct (&pngReadStruct, 0, 0); - return 0; - } + if (pngInfoStruct == 0) + { + png_destroy_read_struct (&pngReadStruct, 0, 0); + return 0; + } - png_set_error_fn (pngReadStruct, 0, pngErrorCallback, pngErrorCallback); + png_set_error_fn (pngReadStruct, 0, pngErrorCallback, pngErrorCallback); - // read the header.. - png_set_read_fn (pngReadStruct, &in, pngReadCallback); + // read the header.. + png_set_read_fn (pngReadStruct, &in, pngReadCallback); - png_uint_32 width, height; - int bitDepth, colorType, interlaceType; + png_uint_32 width, height; + int bitDepth, colorType, interlaceType; - png_read_info (pngReadStruct, pngInfoStruct); + png_read_info (pngReadStruct, pngInfoStruct); - png_get_IHDR (pngReadStruct, pngInfoStruct, - &width, &height, - &bitDepth, &colorType, - &interlaceType, 0, 0); + png_get_IHDR (pngReadStruct, pngInfoStruct, + &width, &height, + &bitDepth, &colorType, + &interlaceType, 0, 0); - if (bitDepth == 16) - png_set_strip_16 (pngReadStruct); + if (bitDepth == 16) + png_set_strip_16 (pngReadStruct); - if (colorType == PNG_COLOR_TYPE_PALETTE) - png_set_expand (pngReadStruct); + if (colorType == PNG_COLOR_TYPE_PALETTE) + png_set_expand (pngReadStruct); - if (bitDepth < 8) - png_set_expand (pngReadStruct); + if (bitDepth < 8) + png_set_expand (pngReadStruct); - if (png_get_valid (pngReadStruct, pngInfoStruct, PNG_INFO_tRNS)) - png_set_expand (pngReadStruct); + if (png_get_valid (pngReadStruct, pngInfoStruct, PNG_INFO_tRNS)) + png_set_expand (pngReadStruct); - if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb (pngReadStruct); + if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb (pngReadStruct); - png_set_add_alpha (pngReadStruct, 0xff, PNG_FILLER_AFTER); + png_set_add_alpha (pngReadStruct, 0xff, PNG_FILLER_AFTER); - bool hasAlphaChan = (colorType & PNG_COLOR_MASK_ALPHA) != 0 - || pngInfoStruct->num_trans > 0; + bool hasAlphaChan = (colorType & PNG_COLOR_MASK_ALPHA) != 0 + || pngInfoStruct->num_trans > 0; - // Load the image into a temp buffer in the pnglib format.. - HeapBlock tempBuffer (height * (width << 2)); + // Load the image into a temp buffer in the pnglib format.. + HeapBlock tempBuffer (height * (width << 2)); - { - HeapBlock rows (height); - for (int y = (int) height; --y >= 0;) - rows[y] = (png_bytep) (tempBuffer + (width << 2) * y); + { + HeapBlock rows (height); + for (int y = (int) height; --y >= 0;) + rows[y] = (png_bytep) (tempBuffer + (width << 2) * y); - png_read_image (pngReadStruct, rows); - png_read_end (pngReadStruct, pngInfoStruct); - } + png_read_image (pngReadStruct, rows); + png_read_end (pngReadStruct, pngInfoStruct); + } - png_destroy_read_struct (&pngReadStruct, &pngInfoStruct, 0); + png_destroy_read_struct (&pngReadStruct, &pngInfoStruct, 0); - // now convert the data to a juce image format.. - image = Image::createNativeImage (hasAlphaChan ? Image::ARGB : Image::RGB, - width, height, hasAlphaChan); + // now convert the data to a juce image format.. + image = Image::createNativeImage (hasAlphaChan ? Image::ARGB : Image::RGB, + (int) width, (int) height, hasAlphaChan); - hasAlphaChan = image->hasAlphaChannel(); // (the native image creator may not give back what we expect) + hasAlphaChan = image->hasAlphaChannel(); // (the native image creator may not give back what we expect) - const Image::BitmapData destData (*image, 0, 0, width, height, true); - uint8* srcRow = tempBuffer; - uint8* destRow = destData.data; + const Image::BitmapData destData (*image, 0, 0, (int) width, (int) height, true); + uint8* srcRow = tempBuffer; + uint8* destRow = destData.data; - for (int y = 0; y < (int) height; ++y) - { - const uint8* src = srcRow; - srcRow += (width << 2); - uint8* dest = destRow; - destRow += destData.lineStride; + for (int y = 0; y < (int) height; ++y) + { + const uint8* src = srcRow; + srcRow += (width << 2); + uint8* dest = destRow; + destRow += destData.lineStride; - if (hasAlphaChan) - { - for (int i = width; --i >= 0;) - { - ((PixelARGB*) dest)->setARGB (src[3], src[0], src[1], src[2]); - ((PixelARGB*) dest)->premultiply(); - dest += destData.pixelStride; - src += 4; - } - } - else - { - for (int i = width; --i >= 0;) - { - ((PixelRGB*) dest)->setARGB (0, src[0], src[1], src[2]); - dest += destData.pixelStride; - src += 4; - } - } - } - } + if (hasAlphaChan) + { + for (int i = (int) width; --i >= 0;) + { + ((PixelARGB*) dest)->setARGB (src[3], src[0], src[1], src[2]); + ((PixelARGB*) dest)->premultiply(); + dest += destData.pixelStride; + src += 4; + } + } + else + { + for (int i = (int) width; --i >= 0;) + { + ((PixelRGB*) dest)->setARGB (0, src[0], src[1], src[2]); + dest += destData.pixelStride; + src += 4; + } + } + } + } - return image; + return image; } static void pngWriteDataCallback (png_structp png_ptr, png_bytep data, png_size_t length) { - OutputStream* const out = (OutputStream*) png_ptr->io_ptr; + OutputStream* const out = (OutputStream*) png_ptr->io_ptr; - const bool ok = out->write (data, length); + const bool ok = out->write (data, (int) length); - (void) ok; - jassert (ok); + (void) ok; + jassert (ok); } bool juce_writePNGImageToStream (const Image& image, OutputStream& out) { - const int width = image.getWidth(); - const int height = image.getHeight(); + const int width = image.getWidth(); + const int height = image.getHeight(); - png_structp pngWriteStruct = png_create_write_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); + png_structp pngWriteStruct = png_create_write_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); - if (pngWriteStruct == 0) - return false; + if (pngWriteStruct == 0) + return false; - png_infop pngInfoStruct = png_create_info_struct (pngWriteStruct); + png_infop pngInfoStruct = png_create_info_struct (pngWriteStruct); - if (pngInfoStruct == 0) - { - png_destroy_write_struct (&pngWriteStruct, (png_infopp) 0); - return false; - } + if (pngInfoStruct == 0) + { + png_destroy_write_struct (&pngWriteStruct, (png_infopp) 0); + return false; + } - png_set_write_fn (pngWriteStruct, &out, pngWriteDataCallback, 0); + png_set_write_fn (pngWriteStruct, &out, pngWriteDataCallback, 0); - png_set_IHDR (pngWriteStruct, pngInfoStruct, width, height, 8, - image.hasAlphaChannel() ? PNG_COLOR_TYPE_RGB_ALPHA - : PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, - PNG_FILTER_TYPE_BASE); + png_set_IHDR (pngWriteStruct, pngInfoStruct, width, height, 8, + image.hasAlphaChannel() ? PNG_COLOR_TYPE_RGB_ALPHA + : PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); - HeapBlock rowData (width * 4); + HeapBlock rowData (width * 4); - png_color_8 sig_bit; - sig_bit.red = 8; - sig_bit.green = 8; - sig_bit.blue = 8; - sig_bit.alpha = 8; - png_set_sBIT (pngWriteStruct, pngInfoStruct, &sig_bit); + png_color_8 sig_bit; + sig_bit.red = 8; + sig_bit.green = 8; + sig_bit.blue = 8; + sig_bit.alpha = 8; + png_set_sBIT (pngWriteStruct, pngInfoStruct, &sig_bit); - png_write_info (pngWriteStruct, pngInfoStruct); + png_write_info (pngWriteStruct, pngInfoStruct); - png_set_shift (pngWriteStruct, &sig_bit); - png_set_packing (pngWriteStruct); + png_set_shift (pngWriteStruct, &sig_bit); + png_set_packing (pngWriteStruct); - const Image::BitmapData srcData (image, 0, 0, width, height); + const Image::BitmapData srcData (image, 0, 0, width, height); - for (int y = 0; y < height; ++y) - { - uint8* dst = (uint8*) rowData; - const uint8* src = srcData.getLinePointer (y); + for (int y = 0; y < height; ++y) + { + uint8* dst = (uint8*) rowData; + const uint8* src = srcData.getLinePointer (y); - if (image.hasAlphaChannel()) - { - for (int i = width; --i >= 0;) - { - PixelARGB p (*(const PixelARGB*) src); - p.unpremultiply(); + if (image.hasAlphaChannel()) + { + for (int i = width; --i >= 0;) + { + PixelARGB p (*(const PixelARGB*) src); + p.unpremultiply(); - *dst++ = p.getRed(); - *dst++ = p.getGreen(); - *dst++ = p.getBlue(); - *dst++ = p.getAlpha(); - src += srcData.pixelStride; - } - } - else - { - for (int i = width; --i >= 0;) - { - *dst++ = ((const PixelRGB*) src)->getRed(); - *dst++ = ((const PixelRGB*) src)->getGreen(); - *dst++ = ((const PixelRGB*) src)->getBlue(); - src += srcData.pixelStride; - } - } + *dst++ = p.getRed(); + *dst++ = p.getGreen(); + *dst++ = p.getBlue(); + *dst++ = p.getAlpha(); + src += srcData.pixelStride; + } + } + else + { + for (int i = width; --i >= 0;) + { + *dst++ = ((const PixelRGB*) src)->getRed(); + *dst++ = ((const PixelRGB*) src)->getGreen(); + *dst++ = ((const PixelRGB*) src)->getBlue(); + src += srcData.pixelStride; + } + } - png_write_rows (pngWriteStruct, &rowData, 1); - } + png_write_rows (pngWriteStruct, &rowData, 1); + } - png_write_end (pngWriteStruct, pngInfoStruct); - png_destroy_write_struct (&pngWriteStruct, &pngInfoStruct); + png_write_end (pngWriteStruct, pngInfoStruct); + png_destroy_write_struct (&pngWriteStruct, &pngInfoStruct); - out.flush(); + out.flush(); - return true; + return true; } END_JUCE_NAMESPACE @@ -234214,13 +211981,6 @@ END_JUCE_NAMESPACE /********* Start of inlined file: juce_win32_NativeCode.cpp *********/ -/* - This file wraps together all the win32-specific code, so that - we can include all the native headers just once, and compile all our - platform-specific stuff in one big lump, keeping it out of the way of - the rest of the codebase. -*/ - BEGIN_JUCE_NAMESPACE #define JUCE_INCLUDED_FILE 1 @@ -234247,21 +212007,21 @@ BEGIN_JUCE_NAMESPACE // params: list of params (bracketed) // #define DynamicLibraryImport(functionName, localFunctionName, returnType, object, params) \ - typedef returnType (WINAPI *type##localFunctionName) params; \ - type##localFunctionName localFunctionName \ - = (type##localFunctionName)object.findProcAddress (#functionName); + typedef returnType (WINAPI *type##localFunctionName) params; \ + type##localFunctionName localFunctionName \ + = (type##localFunctionName)object.findProcAddress (#functionName); // loads and unloads a DLL automatically class JUCE_API DynamicLibraryLoader { public: - DynamicLibraryLoader (const String& name); - ~DynamicLibraryLoader(); + DynamicLibraryLoader (const String& name); + ~DynamicLibraryLoader(); - void* findProcAddress (const String& functionName); + void* findProcAddress (const String& functionName); private: - void* libHandle; + void* libHandle; }; #endif @@ -234270,17 +212030,17 @@ private: DynamicLibraryLoader::DynamicLibraryLoader (const String& name) { - libHandle = LoadLibrary (name); + libHandle = LoadLibrary (name); } DynamicLibraryLoader::~DynamicLibraryLoader() { - FreeLibrary ((HMODULE) libHandle); + FreeLibrary ((HMODULE) libHandle); } void* DynamicLibraryLoader::findProcAddress (const String& functionName) { - return (void*) GetProcAddress ((HMODULE) libHandle, functionName); + return (void*) GetProcAddress ((HMODULE) libHandle, functionName); } #endif @@ -234291,21 +212051,20 @@ void* DynamicLibraryLoader::findProcAddress (const String& functionName) // compiled on its own). #if JUCE_INCLUDED_FILE -extern void juce_updateMultiMonitorInfo() throw(); -extern void juce_initialiseThreadEvents() throw(); +extern void juce_initialiseThreadEvents(); void Logger::outputDebugString (const String& text) throw() { - OutputDebugString (text + T("\n")); + OutputDebugString (text + T("\n")); } void Logger::outputDebugPrintf (const tchar* format, ...) throw() { - String text; - va_list args; - va_start (args, format); - text.vprintf(format, args); - outputDebugString (text); + String text; + va_list args; + va_start (args, format); + text.vprintf(format, args); + outputDebugString (text); } static int64 hiResTicksPerSecond; @@ -234320,15 +212079,15 @@ static double hiResTicksScaleFactor; const String SystemStats::getCpuVendor() throw() { - int info [4]; - __cpuid (info, 0); + int info [4]; + __cpuid (info, 0); - char v [12]; - memcpy (v, info + 1, 4); - memcpy (v + 4, info + 3, 4); - memcpy (v + 8, info + 2, 4); + char v [12]; + memcpy (v, info + 1, 4); + memcpy (v + 4, info + 3, 4); + memcpy (v + 8, info + 2, 4); - return String (v, 12); + return String (v, 12); } #else @@ -234337,308 +212096,308 @@ const String SystemStats::getCpuVendor() throw() static void juce_getCpuVendor (char* const v) { - int vendor[4]; - zeromem (vendor, 16); + int vendor[4]; + zeromem (vendor, 16); #ifdef JUCE_64BIT #else #ifndef __MINGW32__ - __try + __try #endif - { + { #if JUCE_GCC - unsigned int dummy = 0; - __asm__ ("cpuid" : "=a" (dummy), "=b" (vendor[0]), "=c" (vendor[2]),"=d" (vendor[1]) : "a" (0)); + unsigned int dummy = 0; + __asm__ ("cpuid" : "=a" (dummy), "=b" (vendor[0]), "=c" (vendor[2]),"=d" (vendor[1]) : "a" (0)); #else - __asm - { - mov eax, 0 - cpuid - mov [vendor], ebx - mov [vendor + 4], edx - mov [vendor + 8], ecx - } + __asm + { + mov eax, 0 + cpuid + mov [vendor], ebx + mov [vendor + 4], edx + mov [vendor + 8], ecx + } #endif - } + } #ifndef __MINGW32__ - __except (EXCEPTION_EXECUTE_HANDLER) - { - *v = 0; - } + __except (EXCEPTION_EXECUTE_HANDLER) + { + *v = 0; + } #endif #endif - memcpy (v, vendor, 16); + memcpy (v, vendor, 16); } const String SystemStats::getCpuVendor() throw() { - char v [16]; - juce_getCpuVendor (v); - return String (v, 16); + char v [16]; + juce_getCpuVendor (v); + return String (v, 16); } #endif struct CPUFlags { - bool hasMMX : 1; - bool hasSSE : 1; - bool hasSSE2 : 1; - bool has3DNow : 1; + bool hasMMX : 1; + bool hasSSE : 1; + bool hasSSE2 : 1; + bool has3DNow : 1; }; static CPUFlags cpuFlags; bool SystemStats::hasMMX() throw() { - return cpuFlags.hasMMX; + return cpuFlags.hasMMX; } bool SystemStats::hasSSE() throw() { - return cpuFlags.hasSSE; + return cpuFlags.hasSSE; } bool SystemStats::hasSSE2() throw() { - return cpuFlags.hasSSE2; + return cpuFlags.hasSSE2; } bool SystemStats::has3DNow() throw() { - return cpuFlags.has3DNow; + return cpuFlags.has3DNow; } void SystemStats::initialiseStats() throw() { - juce_initialiseThreadEvents(); + juce_initialiseThreadEvents(); - cpuFlags.hasMMX = IsProcessorFeaturePresent (PF_MMX_INSTRUCTIONS_AVAILABLE) != 0; - cpuFlags.hasSSE = IsProcessorFeaturePresent (PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0; - cpuFlags.hasSSE2 = IsProcessorFeaturePresent (PF_XMMI64_INSTRUCTIONS_AVAILABLE) != 0; + cpuFlags.hasMMX = IsProcessorFeaturePresent (PF_MMX_INSTRUCTIONS_AVAILABLE) != 0; + cpuFlags.hasSSE = IsProcessorFeaturePresent (PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0; + cpuFlags.hasSSE2 = IsProcessorFeaturePresent (PF_XMMI64_INSTRUCTIONS_AVAILABLE) != 0; #ifdef PF_AMD3D_INSTRUCTIONS_AVAILABLE - cpuFlags.has3DNow = IsProcessorFeaturePresent (PF_AMD3D_INSTRUCTIONS_AVAILABLE) != 0; + cpuFlags.has3DNow = IsProcessorFeaturePresent (PF_AMD3D_INSTRUCTIONS_AVAILABLE) != 0; #else - cpuFlags.has3DNow = IsProcessorFeaturePresent (PF_3DNOW_INSTRUCTIONS_AVAILABLE) != 0; + cpuFlags.has3DNow = IsProcessorFeaturePresent (PF_3DNOW_INSTRUCTIONS_AVAILABLE) != 0; #endif - LARGE_INTEGER f; - QueryPerformanceFrequency (&f); - hiResTicksPerSecond = f.QuadPart; - hiResTicksScaleFactor = 1000.0 / hiResTicksPerSecond; + LARGE_INTEGER f; + QueryPerformanceFrequency (&f); + hiResTicksPerSecond = f.QuadPart; + hiResTicksScaleFactor = 1000.0 / hiResTicksPerSecond; - String s (SystemStats::getJUCEVersion()); + String s (SystemStats::getJUCEVersion()); #ifdef JUCE_DEBUG - const MMRESULT res = timeBeginPeriod (1); - jassert (res == TIMERR_NOERROR); + const MMRESULT res = timeBeginPeriod (1); + jassert (res == TIMERR_NOERROR); #else - timeBeginPeriod (1); + timeBeginPeriod (1); #endif #if defined (JUCE_DEBUG) && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS - _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif } SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() throw() { - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof (info); - GetVersionEx (&info); + OSVERSIONINFO info; + info.dwOSVersionInfoSize = sizeof (info); + GetVersionEx (&info); - if (info.dwPlatformId == VER_PLATFORM_WIN32_NT) - { - switch (info.dwMajorVersion) - { - case 5: return (info.dwMinorVersion == 0) ? Win2000 : WinXP; - case 6: return (info.dwMinorVersion == 0) ? WinVista : Windows7; - default: jassertfalse; break; // !! not a supported OS! - } - } - else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) - { - jassert (info.dwMinorVersion != 0); // !! still running on Windows 95?? - return Win98; - } + if (info.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + switch (info.dwMajorVersion) + { + case 5: return (info.dwMinorVersion == 0) ? Win2000 : WinXP; + case 6: return (info.dwMinorVersion == 0) ? WinVista : Windows7; + default: jassertfalse; break; // !! not a supported OS! + } + } + else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + { + jassert (info.dwMinorVersion != 0); // !! still running on Windows 95?? + return Win98; + } - return UnknownOS; + return UnknownOS; } const String SystemStats::getOperatingSystemName() throw() { - const char* name = "Unknown OS"; + const char* name = "Unknown OS"; - switch (getOperatingSystemType()) - { - case Windows7: name = "Windows 7"; break; - case WinVista: name = "Windows Vista"; break; - case WinXP: name = "Windows XP"; break; - case Win2000: name = "Windows 2000"; break; - case Win98: name = "Windows 98"; break; - default: jassertfalse; break; // !! new type of OS? - } + switch (getOperatingSystemType()) + { + case Windows7: name = "Windows 7"; break; + case WinVista: name = "Windows Vista"; break; + case WinXP: name = "Windows XP"; break; + case Win2000: name = "Windows 2000"; break; + case Win98: name = "Windows 98"; break; + default: jassertfalse; break; // !! new type of OS? + } - return name; + return name; } bool SystemStats::isOperatingSystem64Bit() throw() { #ifdef _WIN64 - return true; + return true; #else - typedef BOOL (WINAPI* LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + typedef BOOL (WINAPI* LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); - LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle (L"kernel32"), "IsWow64Process"); + LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle (L"kernel32"), "IsWow64Process"); - BOOL isWow64 = FALSE; + BOOL isWow64 = FALSE; - return (fnIsWow64Process != 0) - && fnIsWow64Process (GetCurrentProcess(), &isWow64) - && (isWow64 != FALSE); + return (fnIsWow64Process != 0) + && fnIsWow64Process (GetCurrentProcess(), &isWow64) + && (isWow64 != FALSE); #endif } int SystemStats::getMemorySizeInMegabytes() throw() { - MEMORYSTATUSEX mem; - mem.dwLength = sizeof (mem); - GlobalMemoryStatusEx (&mem); - return (int) (mem.ullTotalPhys / (1024 * 1024)) + 1; + MEMORYSTATUSEX mem; + mem.dwLength = sizeof (mem); + GlobalMemoryStatusEx (&mem); + return (int) (mem.ullTotalPhys / (1024 * 1024)) + 1; } int SystemStats::getNumCpus() throw() { - SYSTEM_INFO systemInfo; - GetSystemInfo (&systemInfo); + SYSTEM_INFO systemInfo; + GetSystemInfo (&systemInfo); - return systemInfo.dwNumberOfProcessors; + return systemInfo.dwNumberOfProcessors; } uint32 juce_millisecondsSinceStartup() throw() { - return (uint32) GetTickCount(); + return (uint32) GetTickCount(); } int64 Time::getHighResolutionTicks() throw() { - LARGE_INTEGER ticks; - QueryPerformanceCounter (&ticks); + LARGE_INTEGER ticks; + QueryPerformanceCounter (&ticks); - const int64 mainCounterAsHiResTicks = (GetTickCount() * hiResTicksPerSecond) / 1000; - const int64 newOffset = mainCounterAsHiResTicks - ticks.QuadPart; + const int64 mainCounterAsHiResTicks = (GetTickCount() * hiResTicksPerSecond) / 1000; + const int64 newOffset = mainCounterAsHiResTicks - ticks.QuadPart; - // fix for a very obscure PCI hardware bug that can make the counter - // sometimes jump forwards by a few seconds.. - static int64 hiResTicksOffset = 0; - const int64 offsetDrift = abs64 (newOffset - hiResTicksOffset); + // fix for a very obscure PCI hardware bug that can make the counter + // sometimes jump forwards by a few seconds.. + static int64 hiResTicksOffset = 0; + const int64 offsetDrift = abs64 (newOffset - hiResTicksOffset); - if (offsetDrift > (hiResTicksPerSecond >> 1)) - hiResTicksOffset = newOffset; + if (offsetDrift > (hiResTicksPerSecond >> 1)) + hiResTicksOffset = newOffset; - return ticks.QuadPart + hiResTicksOffset; + return ticks.QuadPart + hiResTicksOffset; } double Time::getMillisecondCounterHiRes() throw() { - return getHighResolutionTicks() * hiResTicksScaleFactor; + return getHighResolutionTicks() * hiResTicksScaleFactor; } int64 Time::getHighResolutionTicksPerSecond() throw() { - return hiResTicksPerSecond; + return hiResTicksPerSecond; } int64 SystemStats::getClockCycleCounter() throw() { #if JUCE_USE_INTRINSICS - // MS intrinsics version... - return __rdtsc(); + // MS intrinsics version... + return __rdtsc(); #elif JUCE_GCC - // GNU inline asm version... - unsigned int hi = 0, lo = 0; + // GNU inline asm version... + unsigned int hi = 0, lo = 0; - __asm__ __volatile__ ( - "xor %%eax, %%eax \n\ - xor %%edx, %%edx \n\ - rdtsc \n\ - movl %%eax, %[lo] \n\ - movl %%edx, %[hi]" - : - : [hi] "m" (hi), - [lo] "m" (lo) - : "cc", "eax", "ebx", "ecx", "edx", "memory"); + __asm__ __volatile__ ( + "xor %%eax, %%eax \n\ + xor %%edx, %%edx \n\ + rdtsc \n\ + movl %%eax, %[lo] \n\ + movl %%edx, %[hi]" + : + : [hi] "m" (hi), + [lo] "m" (lo) + : "cc", "eax", "ebx", "ecx", "edx", "memory"); - return (int64) ((((uint64) hi) << 32) | lo); + return (int64) ((((uint64) hi) << 32) | lo); #else - // MSVC inline asm version... - unsigned int hi = 0, lo = 0; + // MSVC inline asm version... + unsigned int hi = 0, lo = 0; - __asm - { - xor eax, eax - xor edx, edx - rdtsc - mov lo, eax - mov hi, edx - } + __asm + { + xor eax, eax + xor edx, edx + rdtsc + mov lo, eax + mov hi, edx + } - return (int64) ((((uint64) hi) << 32) | lo); + return (int64) ((((uint64) hi) << 32) | lo); #endif } int SystemStats::getCpuSpeedInMegaherz() throw() { - const int64 cycles = SystemStats::getClockCycleCounter(); - const uint32 millis = Time::getMillisecondCounter(); - int lastResult = 0; + const int64 cycles = SystemStats::getClockCycleCounter(); + const uint32 millis = Time::getMillisecondCounter(); + int lastResult = 0; - for (;;) - { - int n = 1000000; - while (--n > 0) {} + for (;;) + { + int n = 1000000; + while (--n > 0) {} - const uint32 millisElapsed = Time::getMillisecondCounter() - millis; - const int64 cyclesNow = SystemStats::getClockCycleCounter(); + const uint32 millisElapsed = Time::getMillisecondCounter() - millis; + const int64 cyclesNow = SystemStats::getClockCycleCounter(); - if (millisElapsed > 80) - { - const int newResult = (int) (((cyclesNow - cycles) / millisElapsed) / 1000); + if (millisElapsed > 80) + { + const int newResult = (int) (((cyclesNow - cycles) / millisElapsed) / 1000); - if (millisElapsed > 500 || (lastResult == newResult && newResult > 100)) - return newResult; + if (millisElapsed > 500 || (lastResult == newResult && newResult > 100)) + return newResult; - lastResult = newResult; - } - } + lastResult = newResult; + } + } } bool Time::setSystemTimeToThisTime() const throw() { - SYSTEMTIME st; + SYSTEMTIME st; - st.wDayOfWeek = 0; - st.wYear = (WORD) getYear(); - st.wMonth = (WORD) (getMonth() + 1); - st.wDay = (WORD) getDayOfMonth(); - st.wHour = (WORD) getHours(); - st.wMinute = (WORD) getMinutes(); - st.wSecond = (WORD) getSeconds(); - st.wMilliseconds = (WORD) (millisSinceEpoch % 1000); + st.wDayOfWeek = 0; + st.wYear = (WORD) getYear(); + st.wMonth = (WORD) (getMonth() + 1); + st.wDay = (WORD) getDayOfMonth(); + st.wHour = (WORD) getHours(); + st.wMinute = (WORD) getMinutes(); + st.wSecond = (WORD) getSeconds(); + st.wMilliseconds = (WORD) (millisSinceEpoch % 1000); - // do this twice because of daylight saving conversion problems - the - // first one sets it up, the second one kicks it in. - return SetLocalTime (&st) != 0 - && SetLocalTime (&st) != 0; + // do this twice because of daylight saving conversion problems - the + // first one sets it up, the second one kicks it in. + return SetLocalTime (&st) != 0 + && SetLocalTime (&st) != 0; } int SystemStats::getPageSize() throw() { - SYSTEM_INFO systemInfo; - GetSystemInfo (&systemInfo); + SYSTEM_INFO systemInfo; + GetSystemInfo (&systemInfo); - return systemInfo.dwPageSize; + return systemInfo.dwPageSize; } #endif @@ -234655,59 +212414,59 @@ int SystemStats::getPageSize() throw() CriticalSection::CriticalSection() throw() { - // (just to check the MS haven't changed this structure and broken things...) + // (just to check the MS haven't changed this structure and broken things...) #if _MSC_VER >= 1400 - static_jassert (sizeof (CRITICAL_SECTION) <= sizeof (internal)); + static_jassert (sizeof (CRITICAL_SECTION) <= sizeof (internal)); #else - static_jassert (sizeof (CRITICAL_SECTION) <= 24); + static_jassert (sizeof (CRITICAL_SECTION) <= 24); #endif - InitializeCriticalSection ((CRITICAL_SECTION*) internal); + InitializeCriticalSection ((CRITICAL_SECTION*) internal); } CriticalSection::~CriticalSection() throw() { - DeleteCriticalSection ((CRITICAL_SECTION*) internal); + DeleteCriticalSection ((CRITICAL_SECTION*) internal); } void CriticalSection::enter() const throw() { - EnterCriticalSection ((CRITICAL_SECTION*) internal); + EnterCriticalSection ((CRITICAL_SECTION*) internal); } bool CriticalSection::tryEnter() const throw() { - return TryEnterCriticalSection ((CRITICAL_SECTION*) internal) != FALSE; + return TryEnterCriticalSection ((CRITICAL_SECTION*) internal) != FALSE; } void CriticalSection::exit() const throw() { - LeaveCriticalSection ((CRITICAL_SECTION*) internal); + LeaveCriticalSection ((CRITICAL_SECTION*) internal); } WaitableEvent::WaitableEvent() throw() - : internal (CreateEvent (0, FALSE, FALSE, 0)) + : internal (CreateEvent (0, FALSE, FALSE, 0)) { } WaitableEvent::~WaitableEvent() throw() { - CloseHandle (internal); + CloseHandle (internal); } bool WaitableEvent::wait (const int timeOutMillisecs) const throw() { - return WaitForSingleObject (internal, timeOutMillisecs) == WAIT_OBJECT_0; + return WaitForSingleObject (internal, timeOutMillisecs) == WAIT_OBJECT_0; } void WaitableEvent::signal() const throw() { - SetEvent (internal); + SetEvent (internal); } void WaitableEvent::reset() const throw() { - ResetEvent (internal); + ResetEvent (internal); } void JUCE_API juce_threadEntryPoint (void*); @@ -234715,137 +212474,137 @@ void JUCE_API juce_threadEntryPoint (void*); static unsigned int __stdcall threadEntryProc (void* userData) { #if ! JUCE_ONLY_BUILD_CORE_LIBRARY - AttachThreadInput (GetWindowThreadProcessId (juce_messageWindowHandle, 0), - GetCurrentThreadId(), TRUE); + AttachThreadInput (GetWindowThreadProcessId (juce_messageWindowHandle, 0), + GetCurrentThreadId(), TRUE); #endif - juce_threadEntryPoint (userData); + juce_threadEntryPoint (userData); - _endthreadex (0); - return 0; + _endthreadex (0); + return 0; } void juce_CloseThreadHandle (void* handle) { - CloseHandle ((HANDLE) handle); + CloseHandle ((HANDLE) handle); } void* juce_createThread (void* userData) { - unsigned int threadId; + unsigned int threadId; - return (void*) _beginthreadex (0, 0, - &threadEntryProc, - userData, - 0, &threadId); + return (void*) _beginthreadex (0, 0, + &threadEntryProc, + userData, + 0, &threadId); } void juce_killThread (void* handle) { - if (handle != 0) - { + if (handle != 0) + { #ifdef JUCE_DEBUG - OutputDebugString (_T("** Warning - Forced thread termination **\n")); + OutputDebugString (_T("** Warning - Forced thread termination **\n")); #endif - TerminateThread (handle, 0); - } + TerminateThread (handle, 0); + } } void juce_setCurrentThreadName (const String& name) { #if defined (JUCE_DEBUG) && JUCE_MSVC - struct - { - DWORD dwType; - LPCSTR szName; - DWORD dwThreadID; - DWORD dwFlags; - } info; + struct + { + DWORD dwType; + LPCSTR szName; + DWORD dwThreadID; + DWORD dwFlags; + } info; - info.dwType = 0x1000; - info.szName = name; - info.dwThreadID = GetCurrentThreadId(); - info.dwFlags = 0; + info.dwType = 0x1000; + info.szName = name; + info.dwThreadID = GetCurrentThreadId(); + info.dwFlags = 0; - #define MS_VC_EXCEPTION 0x406d1388 + #define MS_VC_EXCEPTION 0x406d1388 - __try - { - RaiseException (MS_VC_EXCEPTION, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info); - } - __except (EXCEPTION_CONTINUE_EXECUTION) - {} + __try + { + RaiseException (MS_VC_EXCEPTION, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info); + } + __except (EXCEPTION_CONTINUE_EXECUTION) + {} #else - (void) name; + (void) name; #endif } Thread::ThreadID Thread::getCurrentThreadId() { - return (ThreadID) (pointer_sized_int) GetCurrentThreadId(); + return (ThreadID) (pointer_sized_int) GetCurrentThreadId(); } // priority 1 to 10 where 5=normal, 1=low bool juce_setThreadPriority (void* threadHandle, int priority) { - int pri = THREAD_PRIORITY_TIME_CRITICAL; + int pri = THREAD_PRIORITY_TIME_CRITICAL; - if (priority < 1) - pri = THREAD_PRIORITY_IDLE; - else if (priority < 2) - pri = THREAD_PRIORITY_LOWEST; - else if (priority < 5) - pri = THREAD_PRIORITY_BELOW_NORMAL; - else if (priority < 7) - pri = THREAD_PRIORITY_NORMAL; - else if (priority < 9) - pri = THREAD_PRIORITY_ABOVE_NORMAL; - else if (priority < 10) - pri = THREAD_PRIORITY_HIGHEST; + if (priority < 1) + pri = THREAD_PRIORITY_IDLE; + else if (priority < 2) + pri = THREAD_PRIORITY_LOWEST; + else if (priority < 5) + pri = THREAD_PRIORITY_BELOW_NORMAL; + else if (priority < 7) + pri = THREAD_PRIORITY_NORMAL; + else if (priority < 9) + pri = THREAD_PRIORITY_ABOVE_NORMAL; + else if (priority < 10) + pri = THREAD_PRIORITY_HIGHEST; - if (threadHandle == 0) - threadHandle = GetCurrentThread(); + if (threadHandle == 0) + threadHandle = GetCurrentThread(); - return SetThreadPriority (threadHandle, pri) != FALSE; + return SetThreadPriority (threadHandle, pri) != FALSE; } void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) { - SetThreadAffinityMask (GetCurrentThread(), affinityMask); + SetThreadAffinityMask (GetCurrentThread(), affinityMask); } static HANDLE sleepEvent = 0; void juce_initialiseThreadEvents() { - if (sleepEvent == 0) + if (sleepEvent == 0) #ifdef JUCE_DEBUG - sleepEvent = CreateEvent (0, 0, 0, _T("Juce Sleep Event")); + sleepEvent = CreateEvent (0, 0, 0, _T("Juce Sleep Event")); #else - sleepEvent = CreateEvent (0, 0, 0, 0); + sleepEvent = CreateEvent (0, 0, 0, 0); #endif } void Thread::yield() { - Sleep (0); + Sleep (0); } void JUCE_CALLTYPE Thread::sleep (const int millisecs) { - if (millisecs >= 10) - { - Sleep (millisecs); - } - else - { - jassert (sleepEvent != 0); + if (millisecs >= 10) + { + Sleep (millisecs); + } + else + { + jassert (sleepEvent != 0); - // unlike Sleep() this is guaranteed to return to the current thread after - // the time expires, so we'll use this for short waits, which are more likely - // to need to be accurate - WaitForSingleObject (sleepEvent, millisecs); - } + // unlike Sleep() this is guaranteed to return to the current thread after + // the time expires, so we'll use this for short waits, which are more likely + // to need to be accurate + WaitForSingleObject (sleepEvent, millisecs); + } } static int lastProcessPriority = -1; @@ -234854,147 +212613,147 @@ static int lastProcessPriority = -1; // when you swap apps, and this forces an update when the app is brought to the front. void juce_repeatLastProcessPriority() { - if (lastProcessPriority >= 0) // (avoid changing this if it's not been explicitly set by the app..) - { - DWORD p; + if (lastProcessPriority >= 0) // (avoid changing this if it's not been explicitly set by the app..) + { + DWORD p; - switch (lastProcessPriority) - { - case Process::LowPriority: - p = IDLE_PRIORITY_CLASS; - break; + switch (lastProcessPriority) + { + case Process::LowPriority: + p = IDLE_PRIORITY_CLASS; + break; - case Process::NormalPriority: - p = NORMAL_PRIORITY_CLASS; - break; + case Process::NormalPriority: + p = NORMAL_PRIORITY_CLASS; + break; - case Process::HighPriority: - p = HIGH_PRIORITY_CLASS; - break; + case Process::HighPriority: + p = HIGH_PRIORITY_CLASS; + break; - case Process::RealtimePriority: - p = REALTIME_PRIORITY_CLASS; - break; + case Process::RealtimePriority: + p = REALTIME_PRIORITY_CLASS; + break; - default: - jassertfalse // bad priority value - return; - } + default: + jassertfalse // bad priority value + return; + } - SetPriorityClass (GetCurrentProcess(), p); - } + SetPriorityClass (GetCurrentProcess(), p); + } } void Process::setPriority (ProcessPriority prior) { - if (lastProcessPriority != (int) prior) - { - lastProcessPriority = (int) prior; - juce_repeatLastProcessPriority(); - } + if (lastProcessPriority != (int) prior) + { + lastProcessPriority = (int) prior; + juce_repeatLastProcessPriority(); + } } bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger() { - return IsDebuggerPresent() != FALSE; + return IsDebuggerPresent() != FALSE; } bool JUCE_CALLTYPE Process::isRunningUnderDebugger() { - return juce_isRunningUnderDebugger(); + return juce_isRunningUnderDebugger(); } void Process::raisePrivilege() { - jassertfalse // xxx not implemented + jassertfalse // xxx not implemented } void Process::lowerPrivilege() { - jassertfalse // xxx not implemented + jassertfalse // xxx not implemented } void Process::terminate() { #if defined (JUCE_DEBUG) && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS - _CrtDumpMemoryLeaks(); + _CrtDumpMemoryLeaks(); #endif - // bullet in the head in case there's a problem shutting down.. - ExitProcess (0); + // bullet in the head in case there's a problem shutting down.. + ExitProcess (0); } void* PlatformUtilities::loadDynamicLibrary (const String& name) { - void* result = 0; + void* result = 0; - JUCE_TRY - { - result = (void*) LoadLibrary (name); - } - JUCE_CATCH_ALL + JUCE_TRY + { + result = (void*) LoadLibrary (name); + } + JUCE_CATCH_ALL - return result; + return result; } void PlatformUtilities::freeDynamicLibrary (void* h) { - JUCE_TRY - { - if (h != 0) - FreeLibrary ((HMODULE) h); - } - JUCE_CATCH_ALL + JUCE_TRY + { + if (h != 0) + FreeLibrary ((HMODULE) h); + } + JUCE_CATCH_ALL } void* PlatformUtilities::getProcedureEntryPoint (void* h, const String& name) { - return (h != 0) ? (void*) GetProcAddress ((HMODULE) h, name) - : 0; + return (h != 0) ? (void*) GetProcAddress ((HMODULE) h, name) + : 0; } InterProcessLock::InterProcessLock (const String& name_) - : internal (0), - name (name_), - reentrancyLevel (0) + : internal (0), + name (name_), + reentrancyLevel (0) { } InterProcessLock::~InterProcessLock() { - exit(); + exit(); } bool InterProcessLock::enter (const int timeOutMillisecs) { - if (reentrancyLevel++ == 0) - { - internal = CreateMutex (0, TRUE, "Global\\" + name); + if (reentrancyLevel++ == 0) + { + internal = CreateMutex (0, TRUE, "Global\\" + name); - if (internal != 0 && GetLastError() == ERROR_ALREADY_EXISTS) - { - if (timeOutMillisecs == 0 - || WaitForSingleObject (internal, (timeOutMillisecs < 0) ? INFINITE : timeOutMillisecs) - == WAIT_TIMEOUT) - { - ReleaseMutex (internal); - CloseHandle (internal); - internal = 0; - } - } - } + if (internal != 0 && GetLastError() == ERROR_ALREADY_EXISTS) + { + if (timeOutMillisecs == 0 + || WaitForSingleObject (internal, (timeOutMillisecs < 0) ? INFINITE : timeOutMillisecs) + == WAIT_TIMEOUT) + { + ReleaseMutex (internal); + CloseHandle (internal); + internal = 0; + } + } + } - return (internal != 0); + return (internal != 0); } void InterProcessLock::exit() { - if (--reentrancyLevel == 0 && internal != 0) - { - ReleaseMutex (internal); - CloseHandle (internal); - internal = 0; - } + if (--reentrancyLevel == 0 && internal != 0) + { + ReleaseMutex (internal); + CloseHandle (internal); + internal = 0; + } } #endif @@ -235013,867 +212772,867 @@ void InterProcessLock::exit() #define CSIDL_MYVIDEO 0x000e #endif -const tchar File::separator = T('\\'); +const tchar File::separator = T('\\'); const tchar* File::separatorString = T("\\"); bool juce_fileExists (const String& fileName, const bool dontCountDirectories) { - if (fileName.isEmpty()) - return false; + if (fileName.isEmpty()) + return false; - const DWORD attr = GetFileAttributes (fileName); + const DWORD attr = GetFileAttributes (fileName); - return dontCountDirectories ? ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) - : (attr != 0xffffffff); + return dontCountDirectories ? ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) + : (attr != 0xffffffff); } bool juce_isDirectory (const String& fileName) { - const DWORD attr = GetFileAttributes (fileName); + const DWORD attr = GetFileAttributes (fileName); - return (attr != 0xffffffff) - && ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); + return (attr != 0xffffffff) + && ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); } bool juce_canWriteToFile (const String& fileName) { - const DWORD attr = GetFileAttributes (fileName); + const DWORD attr = GetFileAttributes (fileName); - return ((attr & FILE_ATTRIBUTE_READONLY) == 0); + return ((attr & FILE_ATTRIBUTE_READONLY) == 0); } bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) { - DWORD attr = GetFileAttributes (fileName); + DWORD attr = GetFileAttributes (fileName); - if (attr == 0xffffffff) - return false; + if (attr == 0xffffffff) + return false; - if (isReadOnly != juce_canWriteToFile (fileName)) - return true; + if (isReadOnly != juce_canWriteToFile (fileName)) + return true; - if (isReadOnly) - attr |= FILE_ATTRIBUTE_READONLY; - else - attr &= ~FILE_ATTRIBUTE_READONLY; + if (isReadOnly) + attr |= FILE_ATTRIBUTE_READONLY; + else + attr &= ~FILE_ATTRIBUTE_READONLY; - return SetFileAttributes (fileName, attr) != FALSE; + return SetFileAttributes (fileName, attr) != FALSE; } bool File::isHidden() const { - return (GetFileAttributes (getFullPathName()) & FILE_ATTRIBUTE_HIDDEN) != 0; + return (GetFileAttributes (getFullPathName()) & FILE_ATTRIBUTE_HIDDEN) != 0; } bool juce_deleteFile (const String& fileName) { - if (juce_isDirectory (fileName)) - return RemoveDirectory (fileName) != 0; + if (juce_isDirectory (fileName)) + return RemoveDirectory (fileName) != 0; - return DeleteFile (fileName) != 0; + return DeleteFile (fileName) != 0; } bool File::moveToTrash() const { - if (! exists()) - return true; + if (! exists()) + return true; - SHFILEOPSTRUCT fos; - zerostruct (fos); + SHFILEOPSTRUCT fos; + zerostruct (fos); - // The string we pass in must be double null terminated.. - String doubleNullTermPath (getFullPathName() + " "); - TCHAR* p = (TCHAR*) (const TCHAR*) doubleNullTermPath; - p [getFullPathName().length()] = 0; + // The string we pass in must be double null terminated.. + String doubleNullTermPath (getFullPathName() + " "); + TCHAR* p = (TCHAR*) (const TCHAR*) doubleNullTermPath; + p [getFullPathName().length()] = 0; - fos.wFunc = FO_DELETE; - fos.hwnd = (HWND) 0; - fos.pFrom = p; - fos.pTo = NULL; - fos.fFlags = FOF_ALLOWUNDO | FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION - | FOF_NOCONFIRMMKDIR | FOF_RENAMEONCOLLISION; + fos.wFunc = FO_DELETE; + fos.hwnd = (HWND) 0; + fos.pFrom = p; + fos.pTo = NULL; + fos.fFlags = FOF_ALLOWUNDO | FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION + | FOF_NOCONFIRMMKDIR | FOF_RENAMEONCOLLISION; - return SHFileOperation (&fos) == 0; + return SHFileOperation (&fos) == 0; } bool juce_moveFile (const String& source, const String& dest) { - return MoveFile (source, dest) != 0; + return MoveFile (source, dest) != 0; } bool juce_copyFile (const String& source, const String& dest) { - return CopyFile (source, dest, false) != 0; + return CopyFile (source, dest, false) != 0; } void juce_createDirectory (const String& fileName) { - if (! juce_fileExists (fileName, true)) - { - CreateDirectory (fileName, 0); - } + if (! juce_fileExists (fileName, true)) + { + CreateDirectory (fileName, 0); + } } // return 0 if not possible void* juce_fileOpen (const String& fileName, bool forWriting) { - HANDLE h; + HANDLE h; - if (forWriting) - { - h = CreateFile (fileName, GENERIC_WRITE, FILE_SHARE_READ, 0, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (forWriting) + { + h = CreateFile (fileName, GENERIC_WRITE, FILE_SHARE_READ, 0, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); - if (h != INVALID_HANDLE_VALUE) - SetFilePointer (h, 0, 0, FILE_END); - else - h = 0; - } - else - { - h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); + if (h != INVALID_HANDLE_VALUE) + SetFilePointer (h, 0, 0, FILE_END); + else + h = 0; + } + else + { + h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); - if (h == INVALID_HANDLE_VALUE) - h = 0; - } + if (h == INVALID_HANDLE_VALUE) + h = 0; + } - return (void*) h; + return (void*) h; } void juce_fileClose (void* handle) { - CloseHandle (handle); + CloseHandle (handle); } int juce_fileRead (void* handle, void* buffer, int size) { - DWORD num = 0; - ReadFile ((HANDLE) handle, buffer, size, &num, 0); - return num; + DWORD num = 0; + ReadFile ((HANDLE) handle, buffer, size, &num, 0); + return num; } int juce_fileWrite (void* handle, const void* buffer, int size) { - DWORD num; + DWORD num; - WriteFile ((HANDLE) handle, - buffer, size, - &num, 0); + WriteFile ((HANDLE) handle, + buffer, size, + &num, 0); - return num; + return num; } int64 juce_fileSetPosition (void* handle, int64 pos) { - LARGE_INTEGER li; - li.QuadPart = pos; - li.LowPart = SetFilePointer ((HANDLE) handle, - li.LowPart, - &li.HighPart, - FILE_BEGIN); // (returns -1 if it fails) + LARGE_INTEGER li; + li.QuadPart = pos; + li.LowPart = SetFilePointer ((HANDLE) handle, + li.LowPart, + &li.HighPart, + FILE_BEGIN); // (returns -1 if it fails) - return li.QuadPart; + return li.QuadPart; } int64 juce_fileGetPosition (void* handle) { - LARGE_INTEGER li; - li.QuadPart = 0; - li.LowPart = SetFilePointer ((HANDLE) handle, - 0, &li.HighPart, - FILE_CURRENT); // (returns -1 if it fails) + LARGE_INTEGER li; + li.QuadPart = 0; + li.LowPart = SetFilePointer ((HANDLE) handle, + 0, &li.HighPart, + FILE_CURRENT); // (returns -1 if it fails) - return jmax ((int64) 0, li.QuadPart); + return jmax ((int64) 0, li.QuadPart); } void juce_fileFlush (void* handle) { - FlushFileBuffers ((HANDLE) handle); + FlushFileBuffers ((HANDLE) handle); } int64 juce_getFileSize (const String& fileName) { - WIN32_FILE_ATTRIBUTE_DATA attributes; + WIN32_FILE_ATTRIBUTE_DATA attributes; - if (GetFileAttributesEx (fileName, GetFileExInfoStandard, &attributes)) - { - return (((int64) attributes.nFileSizeHigh) << 32) - | attributes.nFileSizeLow; - } + if (GetFileAttributesEx (fileName, GetFileExInfoStandard, &attributes)) + { + return (((int64) attributes.nFileSizeHigh) << 32) + | attributes.nFileSizeLow; + } - return 0; + return 0; } static int64 fileTimeToTime (const FILETIME* const ft) { - // tell me if this fails! - static_jassert (sizeof (ULARGE_INTEGER) == sizeof (FILETIME)); + // tell me if this fails! + static_jassert (sizeof (ULARGE_INTEGER) == sizeof (FILETIME)); #if JUCE_GCC - return (((const ULARGE_INTEGER*) ft)->QuadPart - 116444736000000000LL) / 10000; + return (((const ULARGE_INTEGER*) ft)->QuadPart - 116444736000000000LL) / 10000; #else - return (((const ULARGE_INTEGER*) ft)->QuadPart - 116444736000000000) / 10000; + return (((const ULARGE_INTEGER*) ft)->QuadPart - 116444736000000000) / 10000; #endif } static void timeToFileTime (const int64 time, FILETIME* const ft) { #if JUCE_GCC - ((ULARGE_INTEGER*) ft)->QuadPart = time * 10000 + 116444736000000000LL; + ((ULARGE_INTEGER*) ft)->QuadPart = time * 10000 + 116444736000000000LL; #else - ((ULARGE_INTEGER*) ft)->QuadPart = time * 10000 + 116444736000000000; + ((ULARGE_INTEGER*) ft)->QuadPart = time * 10000 + 116444736000000000; #endif } void juce_getFileTimes (const String& fileName, - int64& modificationTime, - int64& accessTime, - int64& creationTime) + int64& modificationTime, + int64& accessTime, + int64& creationTime) { - WIN32_FILE_ATTRIBUTE_DATA attributes; + WIN32_FILE_ATTRIBUTE_DATA attributes; - if (GetFileAttributesEx (fileName, GetFileExInfoStandard, &attributes)) - { - modificationTime = fileTimeToTime (&attributes.ftLastWriteTime); - creationTime = fileTimeToTime (&attributes.ftCreationTime); - accessTime = fileTimeToTime (&attributes.ftLastAccessTime); - } - else - { - creationTime = accessTime = modificationTime = 0; - } + if (GetFileAttributesEx (fileName, GetFileExInfoStandard, &attributes)) + { + modificationTime = fileTimeToTime (&attributes.ftLastWriteTime); + creationTime = fileTimeToTime (&attributes.ftCreationTime); + accessTime = fileTimeToTime (&attributes.ftLastAccessTime); + } + else + { + creationTime = accessTime = modificationTime = 0; + } } bool juce_setFileTimes (const String& fileName, - int64 modificationTime, - int64 accessTime, - int64 creationTime) + int64 modificationTime, + int64 accessTime, + int64 creationTime) { - FILETIME m, a, c; + FILETIME m, a, c; - if (modificationTime > 0) - timeToFileTime (modificationTime, &m); + if (modificationTime > 0) + timeToFileTime (modificationTime, &m); - if (accessTime > 0) - timeToFileTime (accessTime, &a); + if (accessTime > 0) + timeToFileTime (accessTime, &a); - if (creationTime > 0) - timeToFileTime (creationTime, &c); + if (creationTime > 0) + timeToFileTime (creationTime, &c); - void* const h = juce_fileOpen (fileName, true); - bool ok = false; + void* const h = juce_fileOpen (fileName, true); + bool ok = false; - if (h != 0) - { - ok = SetFileTime ((HANDLE) h, - (creationTime > 0) ? &c : 0, - (accessTime > 0) ? &a : 0, - (modificationTime > 0) ? &m : 0) != 0; - juce_fileClose (h); - } + if (h != 0) + { + ok = SetFileTime ((HANDLE) h, + (creationTime > 0) ? &c : 0, + (accessTime > 0) ? &a : 0, + (modificationTime > 0) ? &m : 0) != 0; + juce_fileClose (h); + } - return ok; + return ok; } // return '\0' separated list of strings const StringArray juce_getFileSystemRoots() { - TCHAR buffer [2048]; - buffer[0] = 0; - buffer[1] = 0; - GetLogicalDriveStrings (2048, buffer); + TCHAR buffer [2048]; + buffer[0] = 0; + buffer[1] = 0; + GetLogicalDriveStrings (2048, buffer); - TCHAR* n = buffer; - StringArray roots; + TCHAR* n = buffer; + StringArray roots; - while (*n != 0) - { - roots.add (String (n)); + while (*n != 0) + { + roots.add (String (n)); - while (*n++ != 0) - { - } - } + while (*n++ != 0) + { + } + } - roots.sort (true); - return roots; + roots.sort (true); + return roots; } const String juce_getVolumeLabel (const String& filenameOnVolume, - int& volumeSerialNumber) + int& volumeSerialNumber) { - TCHAR n [4]; - n[0] = *(const TCHAR*) filenameOnVolume; - n[1] = L':'; - n[2] = L'\\'; - n[3] = 0; + TCHAR n [4]; + n[0] = *(const TCHAR*) filenameOnVolume; + n[1] = L':'; + n[2] = L'\\'; + n[3] = 0; - TCHAR dest [64]; - DWORD serialNum; + TCHAR dest [64]; + DWORD serialNum; - if (! GetVolumeInformation (n, dest, 64, (DWORD*) &serialNum, 0, 0, 0, 0)) - { - dest[0] = 0; - serialNum = 0; - } + if (! GetVolumeInformation (n, dest, 64, (DWORD*) &serialNum, 0, 0, 0, 0)) + { + dest[0] = 0; + serialNum = 0; + } - volumeSerialNumber = serialNum; - return String (dest); + volumeSerialNumber = serialNum; + return String (dest); } static int64 getDiskSpaceInfo (String fn, const bool total) { - if (fn[1] == T(':')) - fn = fn.substring (0, 2) + T("\\"); + if (fn[1] == T(':')) + fn = fn.substring (0, 2) + T("\\"); - ULARGE_INTEGER spc, tot, totFree; + ULARGE_INTEGER spc, tot, totFree; - if (GetDiskFreeSpaceEx (fn, &spc, &tot, &totFree)) - return (int64) (total ? tot.QuadPart - : spc.QuadPart); + if (GetDiskFreeSpaceEx (fn, &spc, &tot, &totFree)) + return (int64) (total ? tot.QuadPart + : spc.QuadPart); - return 0; + return 0; } int64 File::getBytesFreeOnVolume() const { - return getDiskSpaceInfo (getFullPathName(), false); + return getDiskSpaceInfo (getFullPathName(), false); } int64 File::getVolumeTotalSize() const { - return getDiskSpaceInfo (getFullPathName(), true); + return getDiskSpaceInfo (getFullPathName(), true); } static unsigned int getWindowsDriveType (const String& fileName) { - TCHAR n[4]; - n[0] = *(const TCHAR*) fileName; - n[1] = L':'; - n[2] = L'\\'; - n[3] = 0; + TCHAR n[4]; + n[0] = *(const TCHAR*) fileName; + n[1] = L':'; + n[2] = L'\\'; + n[3] = 0; - return GetDriveType (n); + return GetDriveType (n); } bool File::isOnCDRomDrive() const { - return getWindowsDriveType (getFullPathName()) == DRIVE_CDROM; + return getWindowsDriveType (getFullPathName()) == DRIVE_CDROM; } bool File::isOnHardDisk() const { - if (fullPath.isEmpty()) - return false; + if (fullPath.isEmpty()) + return false; - const unsigned int n = getWindowsDriveType (getFullPathName()); + const unsigned int n = getWindowsDriveType (getFullPathName()); - if (fullPath.toLowerCase()[0] <= 'b' - && fullPath[1] == T(':')) - { - return n != DRIVE_REMOVABLE; - } - else - { - return n != DRIVE_CDROM && n != DRIVE_REMOTE; - } + if (fullPath.toLowerCase()[0] <= 'b' + && fullPath[1] == T(':')) + { + return n != DRIVE_REMOVABLE; + } + else + { + return n != DRIVE_CDROM && n != DRIVE_REMOTE; + } } bool File::isOnRemovableDrive() const { - if (fullPath.isEmpty()) - return false; + if (fullPath.isEmpty()) + return false; - const unsigned int n = getWindowsDriveType (getFullPathName()); + const unsigned int n = getWindowsDriveType (getFullPathName()); - return n == DRIVE_CDROM - || n == DRIVE_REMOTE - || n == DRIVE_REMOVABLE - || n == DRIVE_RAMDISK; + return n == DRIVE_CDROM + || n == DRIVE_REMOTE + || n == DRIVE_REMOVABLE + || n == DRIVE_RAMDISK; } #define MAX_PATH_CHARS (MAX_PATH + 256) static const File juce_getSpecialFolderPath (int type) { - WCHAR path [MAX_PATH_CHARS]; + WCHAR path [MAX_PATH_CHARS]; - if (SHGetSpecialFolderPath (0, path, type, 0)) - return File (String (path)); + if (SHGetSpecialFolderPath (0, path, type, 0)) + return File (String (path)); - return File::nonexistent; + return File::nonexistent; } const File JUCE_CALLTYPE File::getSpecialLocation (const SpecialLocationType type) { - int csidlType = 0; + int csidlType = 0; - switch (type) - { - case userHomeDirectory: - csidlType = CSIDL_PROFILE; - break; + switch (type) + { + case userHomeDirectory: + csidlType = CSIDL_PROFILE; + break; - case userDocumentsDirectory: - csidlType = CSIDL_PERSONAL; - break; + case userDocumentsDirectory: + csidlType = CSIDL_PERSONAL; + break; - case userDesktopDirectory: - csidlType = CSIDL_DESKTOP; - break; + case userDesktopDirectory: + csidlType = CSIDL_DESKTOP; + break; - case userApplicationDataDirectory: - csidlType = CSIDL_APPDATA; - break; + case userApplicationDataDirectory: + csidlType = CSIDL_APPDATA; + break; - case commonApplicationDataDirectory: - csidlType = CSIDL_COMMON_APPDATA; - break; + case commonApplicationDataDirectory: + csidlType = CSIDL_COMMON_APPDATA; + break; - case globalApplicationsDirectory: - csidlType = CSIDL_PROGRAM_FILES; - break; + case globalApplicationsDirectory: + csidlType = CSIDL_PROGRAM_FILES; + break; - case userMusicDirectory: - csidlType = CSIDL_MYMUSIC; - break; + case userMusicDirectory: + csidlType = CSIDL_MYMUSIC; + break; - case userMoviesDirectory: - csidlType = CSIDL_MYVIDEO; - break; + case userMoviesDirectory: + csidlType = CSIDL_MYVIDEO; + break; - case tempDirectory: - { - WCHAR dest [2048]; - dest[0] = 0; - GetTempPath (2048, dest); - return File (String (dest)); - } + case tempDirectory: + { + WCHAR dest [2048]; + dest[0] = 0; + GetTempPath (2048, dest); + return File (String (dest)); + } - case invokedExecutableFile: - case currentExecutableFile: - case currentApplicationFile: - { - HINSTANCE moduleHandle = (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(); + case invokedExecutableFile: + case currentExecutableFile: + case currentApplicationFile: + { + HINSTANCE moduleHandle = (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(); - WCHAR dest [MAX_PATH_CHARS]; - dest[0] = 0; - GetModuleFileName (moduleHandle, dest, MAX_PATH_CHARS); - return File (String (dest)); - } - break; + WCHAR dest [MAX_PATH_CHARS]; + dest[0] = 0; + GetModuleFileName (moduleHandle, dest, MAX_PATH_CHARS); + return File (String (dest)); + } + break; - default: - jassertfalse // unknown type? - return File::nonexistent; - } + default: + jassertfalse // unknown type? + return File::nonexistent; + } - return juce_getSpecialFolderPath (csidlType); + return juce_getSpecialFolderPath (csidlType); } const File File::getCurrentWorkingDirectory() { - WCHAR dest [MAX_PATH_CHARS]; - dest[0] = 0; - GetCurrentDirectory (MAX_PATH_CHARS, dest); - return File (String (dest)); + WCHAR dest [MAX_PATH_CHARS]; + dest[0] = 0; + GetCurrentDirectory (MAX_PATH_CHARS, dest); + return File (String (dest)); } bool File::setAsCurrentWorkingDirectory() const { - return SetCurrentDirectory (getFullPathName()) != FALSE; + return SetCurrentDirectory (getFullPathName()) != FALSE; } const String File::getVersion() const { - String result; + String result; - DWORD handle = 0; - DWORD bufferSize = GetFileVersionInfoSize (getFullPathName(), &handle); - HeapBlock buffer; - buffer.calloc (bufferSize); + DWORD handle = 0; + DWORD bufferSize = GetFileVersionInfoSize (getFullPathName(), &handle); + HeapBlock buffer; + buffer.calloc (bufferSize); - if (GetFileVersionInfo (getFullPathName(), 0, bufferSize, buffer)) - { - VS_FIXEDFILEINFO* vffi; - UINT len = 0; + if (GetFileVersionInfo (getFullPathName(), 0, bufferSize, buffer)) + { + VS_FIXEDFILEINFO* vffi; + UINT len = 0; - if (VerQueryValue (buffer, _T("\\"), (LPVOID*) &vffi, &len)) - { - result.printf (T("%d.%d.%d.%d"), - HIWORD (vffi->dwFileVersionMS), - LOWORD (vffi->dwFileVersionMS), - HIWORD (vffi->dwFileVersionLS), - LOWORD (vffi->dwFileVersionLS)); - } - } + if (VerQueryValue (buffer, _T("\\"), (LPVOID*) &vffi, &len)) + { + result.printf (T("%d.%d.%d.%d"), + HIWORD (vffi->dwFileVersionMS), + LOWORD (vffi->dwFileVersionMS), + HIWORD (vffi->dwFileVersionLS), + LOWORD (vffi->dwFileVersionLS)); + } + } - return result; + return result; } const File File::getLinkedTarget() const { - File result (*this); - String p (getFullPathName()); + File result (*this); + String p (getFullPathName()); - if (! exists()) - p += T(".lnk"); - else if (getFileExtension() != T(".lnk")) - return result; + if (! exists()) + p += T(".lnk"); + else if (getFileExtension() != T(".lnk")) + return result; - ComSmartPtr shellLink; - if (SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink, CLSCTX_INPROC_SERVER))) - { - ComSmartPtr persistFile; - if (SUCCEEDED (shellLink->QueryInterface (IID_IPersistFile, (LPVOID*) &persistFile))) - { - if (SUCCEEDED (persistFile->Load ((const WCHAR*) p, STGM_READ)) - && SUCCEEDED (shellLink->Resolve (0, SLR_ANY_MATCH | SLR_NO_UI))) - { - WIN32_FIND_DATA winFindData; - WCHAR resolvedPath [MAX_PATH]; + ComSmartPtr shellLink; + if (SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink, CLSCTX_INPROC_SERVER))) + { + ComSmartPtr persistFile; + if (SUCCEEDED (shellLink->QueryInterface (IID_IPersistFile, (LPVOID*) &persistFile))) + { + if (SUCCEEDED (persistFile->Load ((const WCHAR*) p, STGM_READ)) + && SUCCEEDED (shellLink->Resolve (0, SLR_ANY_MATCH | SLR_NO_UI))) + { + WIN32_FIND_DATA winFindData; + WCHAR resolvedPath [MAX_PATH]; - if (SUCCEEDED (shellLink->GetPath (resolvedPath, MAX_PATH, &winFindData, SLGP_UNCPRIORITY))) - result = File (resolvedPath); - } - } - } + if (SUCCEEDED (shellLink->GetPath (resolvedPath, MAX_PATH, &winFindData, SLGP_UNCPRIORITY))) + result = File (resolvedPath); + } + } + } - return result; + return result; } template static void getFindFileInfo (FindDataType& findData, - String& filename, bool* const isDir, bool* const isHidden, - int64* const fileSize, Time* const modTime, Time* const creationTime, - bool* const isReadOnly) + String& filename, bool* const isDir, bool* const isHidden, + int64* const fileSize, Time* const modTime, Time* const creationTime, + bool* const isReadOnly) { - filename = findData.cFileName; + filename = findData.cFileName; - if (isDir != 0) - *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); + if (isDir != 0) + *isDir = ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); - if (isHidden != 0) - *isHidden = ((findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0); + if (isHidden != 0) + *isHidden = ((findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0); - if (fileSize != 0) - *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32); + if (fileSize != 0) + *fileSize = findData.nFileSizeLow + (((int64) findData.nFileSizeHigh) << 32); - if (modTime != 0) - *modTime = fileTimeToTime (&findData.ftLastWriteTime); + if (modTime != 0) + *modTime = fileTimeToTime (&findData.ftLastWriteTime); - if (creationTime != 0) - *creationTime = fileTimeToTime (&findData.ftCreationTime); + if (creationTime != 0) + *creationTime = fileTimeToTime (&findData.ftCreationTime); - if (isReadOnly != 0) - *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0); + if (isReadOnly != 0) + *isReadOnly = ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0); } void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResult, - bool* isDir, bool* isHidden, int64* fileSize, - Time* modTime, Time* creationTime, bool* isReadOnly) + bool* isDir, bool* isHidden, int64* fileSize, + Time* modTime, Time* creationTime, bool* isReadOnly) { - String wc (directory); + String wc (directory); - if (! wc.endsWithChar (File::separator)) - wc += File::separator; + if (! wc.endsWithChar (File::separator)) + wc += File::separator; - wc += wildCard; + wc += wildCard; - WIN32_FIND_DATA findData; - HANDLE h = FindFirstFile (wc, &findData); + WIN32_FIND_DATA findData; + HANDLE h = FindFirstFile (wc, &findData); - if (h != INVALID_HANDLE_VALUE) - { - getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize, - modTime, creationTime, isReadOnly); - return h; - } + if (h != INVALID_HANDLE_VALUE) + { + getFindFileInfo (findData, firstResult, isDir, isHidden, fileSize, + modTime, creationTime, isReadOnly); + return h; + } - firstResult = String::empty; - return 0; + firstResult = String::empty; + return 0; } bool juce_findFileNext (void* handle, String& resultFile, - bool* isDir, bool* isHidden, int64* fileSize, - Time* modTime, Time* creationTime, bool* isReadOnly) + bool* isDir, bool* isHidden, int64* fileSize, + Time* modTime, Time* creationTime, bool* isReadOnly) { - WIN32_FIND_DATA findData; + WIN32_FIND_DATA findData; - if (handle != 0 && FindNextFile ((HANDLE) handle, &findData) != 0) - { - getFindFileInfo (findData, resultFile, isDir, isHidden, fileSize, - modTime, creationTime, isReadOnly); - return true; - } + if (handle != 0 && FindNextFile ((HANDLE) handle, &findData) != 0) + { + getFindFileInfo (findData, resultFile, isDir, isHidden, fileSize, + modTime, creationTime, isReadOnly); + return true; + } - resultFile = String::empty; - return false; + resultFile = String::empty; + return false; } void juce_findFileClose (void* handle) { - FindClose (handle); + FindClose (handle); } bool juce_launchFile (const String& fileName, - const String& parameters) + const String& parameters) { - HINSTANCE hInstance = 0; + HINSTANCE hInstance = 0; - JUCE_TRY - { - hInstance = ShellExecute (0, 0, fileName, parameters, 0, SW_SHOWDEFAULT); - } - JUCE_CATCH_ALL + JUCE_TRY + { + hInstance = ShellExecute (0, 0, fileName, parameters, 0, SW_SHOWDEFAULT); + } + JUCE_CATCH_ALL - return hInstance > (HINSTANCE) 32; + return hInstance > (HINSTANCE) 32; } void File::revealToUser() const { - if (isDirectory()) - startAsProcess(); - else if (getParentDirectory().exists()) - getParentDirectory().startAsProcess(); + if (isDirectory()) + startAsProcess(); + else if (getParentDirectory().exists()) + getParentDirectory().startAsProcess(); } struct NamedPipeInternal { - HANDLE pipeH; - HANDLE cancelEvent; - bool connected, createdPipe; + HANDLE pipeH; + HANDLE cancelEvent; + bool connected, createdPipe; - NamedPipeInternal() - : pipeH (0), - cancelEvent (0), - connected (false), - createdPipe (false) - { - cancelEvent = CreateEvent (0, FALSE, FALSE, 0); - } + NamedPipeInternal() + : pipeH (0), + cancelEvent (0), + connected (false), + createdPipe (false) + { + cancelEvent = CreateEvent (0, FALSE, FALSE, 0); + } - ~NamedPipeInternal() - { - disconnect(); + ~NamedPipeInternal() + { + disconnect(); - if (pipeH != 0) - CloseHandle (pipeH); + if (pipeH != 0) + CloseHandle (pipeH); - CloseHandle (cancelEvent); - } + CloseHandle (cancelEvent); + } - bool connect (const int timeOutMs) - { - if (! createdPipe) - return true; + bool connect (const int timeOutMs) + { + if (! createdPipe) + return true; - if (! connected) - { - OVERLAPPED over; - zerostruct (over); + if (! connected) + { + OVERLAPPED over; + zerostruct (over); - over.hEvent = CreateEvent (0, TRUE, FALSE, 0); + over.hEvent = CreateEvent (0, TRUE, FALSE, 0); - if (ConnectNamedPipe (pipeH, &over)) - { - connected = false; // yes, you read that right. In overlapped mode it should always return 0. - } - else - { - const int err = GetLastError(); + if (ConnectNamedPipe (pipeH, &over)) + { + connected = false; // yes, you read that right. In overlapped mode it should always return 0. + } + else + { + const int err = GetLastError(); - if (err == ERROR_IO_PENDING || err == ERROR_PIPE_LISTENING) - { - HANDLE handles[] = { over.hEvent, cancelEvent }; + if (err == ERROR_IO_PENDING || err == ERROR_PIPE_LISTENING) + { + HANDLE handles[] = { over.hEvent, cancelEvent }; - if (WaitForMultipleObjects (2, handles, FALSE, - timeOutMs >= 0 ? timeOutMs : INFINITE) == WAIT_OBJECT_0) - connected = true; - } - else if (err == ERROR_PIPE_CONNECTED) - { - connected = true; - } - } + if (WaitForMultipleObjects (2, handles, FALSE, + timeOutMs >= 0 ? timeOutMs : INFINITE) == WAIT_OBJECT_0) + connected = true; + } + else if (err == ERROR_PIPE_CONNECTED) + { + connected = true; + } + } - CloseHandle (over.hEvent); - } + CloseHandle (over.hEvent); + } - return connected; - } + return connected; + } - void disconnect() - { - if (connected) - { - DisconnectNamedPipe (pipeH); - connected = false; - } - } + void disconnect() + { + if (connected) + { + DisconnectNamedPipe (pipeH); + connected = false; + } + } }; void NamedPipe::close() { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - delete intern; - internal = 0; + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + delete intern; + internal = 0; } bool NamedPipe::openInternal (const String& pipeName, const bool createPipe) { - close(); + close(); - NamedPipeInternal* const intern = new NamedPipeInternal(); + NamedPipeInternal* const intern = new NamedPipeInternal(); - String file ("\\\\.\\pipe\\"); - file += pipeName; + String file ("\\\\.\\pipe\\"); + file += pipeName; - intern->createdPipe = createPipe; + intern->createdPipe = createPipe; - if (createPipe) - { - intern->pipeH = CreateNamedPipe (file, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0, - PIPE_UNLIMITED_INSTANCES, - 4096, 4096, 0, NULL); - } - else - { - intern->pipeH = CreateFile (file, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, 0); - } + if (createPipe) + { + intern->pipeH = CreateNamedPipe (file, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0, + PIPE_UNLIMITED_INSTANCES, + 4096, 4096, 0, NULL); + } + else + { + intern->pipeH = CreateFile (file, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, 0); + } - if (intern->pipeH != INVALID_HANDLE_VALUE) - { - internal = intern; - return true; - } + if (intern->pipeH != INVALID_HANDLE_VALUE) + { + internal = intern; + return true; + } - delete intern; - return false; + delete intern; + return false; } int NamedPipe::read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds) { - int bytesRead = -1; - bool waitAgain = true; + int bytesRead = -1; + bool waitAgain = true; - while (waitAgain && internal != 0) - { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - waitAgain = false; + while (waitAgain && internal != 0) + { + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + waitAgain = false; - if (! intern->connect (timeOutMilliseconds)) - break; + if (! intern->connect (timeOutMilliseconds)) + break; - if (maxBytesToRead <= 0) - return 0; + if (maxBytesToRead <= 0) + return 0; - OVERLAPPED over; - zerostruct (over); - over.hEvent = CreateEvent (0, TRUE, FALSE, 0); + OVERLAPPED over; + zerostruct (over); + over.hEvent = CreateEvent (0, TRUE, FALSE, 0); - unsigned long numRead; + unsigned long numRead; - if (ReadFile (intern->pipeH, destBuffer, maxBytesToRead, &numRead, &over)) - { - bytesRead = (int) numRead; - } - else if (GetLastError() == ERROR_IO_PENDING) - { - HANDLE handles[] = { over.hEvent, intern->cancelEvent }; - DWORD waitResult = WaitForMultipleObjects (2, handles, FALSE, - timeOutMilliseconds >= 0 ? timeOutMilliseconds - : INFINITE); - if (waitResult != WAIT_OBJECT_0) - { - // if the operation timed out, let's cancel it... - CancelIo (intern->pipeH); - WaitForSingleObject (over.hEvent, INFINITE); // makes sure cancel is complete - } + if (ReadFile (intern->pipeH, destBuffer, maxBytesToRead, &numRead, &over)) + { + bytesRead = (int) numRead; + } + else if (GetLastError() == ERROR_IO_PENDING) + { + HANDLE handles[] = { over.hEvent, intern->cancelEvent }; + DWORD waitResult = WaitForMultipleObjects (2, handles, FALSE, + timeOutMilliseconds >= 0 ? timeOutMilliseconds + : INFINITE); + if (waitResult != WAIT_OBJECT_0) + { + // if the operation timed out, let's cancel it... + CancelIo (intern->pipeH); + WaitForSingleObject (over.hEvent, INFINITE); // makes sure cancel is complete + } - if (GetOverlappedResult (intern->pipeH, &over, &numRead, FALSE)) - { - bytesRead = (int) numRead; - } - else if (GetLastError() == ERROR_BROKEN_PIPE && intern->createdPipe) - { - intern->disconnect(); - waitAgain = true; - } - } - else - { - waitAgain = internal != 0; - Sleep (5); - } + if (GetOverlappedResult (intern->pipeH, &over, &numRead, FALSE)) + { + bytesRead = (int) numRead; + } + else if (GetLastError() == ERROR_BROKEN_PIPE && intern->createdPipe) + { + intern->disconnect(); + waitAgain = true; + } + } + else + { + waitAgain = internal != 0; + Sleep (5); + } - CloseHandle (over.hEvent); - } + CloseHandle (over.hEvent); + } - return bytesRead; + return bytesRead; } int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds) { - int bytesWritten = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + int bytesWritten = -1; + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - if (intern != 0 && intern->connect (timeOutMilliseconds)) - { - if (numBytesToWrite <= 0) - return 0; + if (intern != 0 && intern->connect (timeOutMilliseconds)) + { + if (numBytesToWrite <= 0) + return 0; - OVERLAPPED over; - zerostruct (over); + OVERLAPPED over; + zerostruct (over); - over.hEvent = CreateEvent (0, TRUE, FALSE, 0); + over.hEvent = CreateEvent (0, TRUE, FALSE, 0); - unsigned long numWritten; + unsigned long numWritten; - if (WriteFile (intern->pipeH, sourceBuffer, numBytesToWrite, &numWritten, &over)) - { - bytesWritten = (int) numWritten; - } - else if (GetLastError() == ERROR_IO_PENDING) - { - HANDLE handles[] = { over.hEvent, intern->cancelEvent }; - DWORD waitResult; + if (WriteFile (intern->pipeH, sourceBuffer, numBytesToWrite, &numWritten, &over)) + { + bytesWritten = (int) numWritten; + } + else if (GetLastError() == ERROR_IO_PENDING) + { + HANDLE handles[] = { over.hEvent, intern->cancelEvent }; + DWORD waitResult; - waitResult = WaitForMultipleObjects (2, handles, FALSE, - timeOutMilliseconds >= 0 ? timeOutMilliseconds - : INFINITE); + waitResult = WaitForMultipleObjects (2, handles, FALSE, + timeOutMilliseconds >= 0 ? timeOutMilliseconds + : INFINITE); - if (waitResult != WAIT_OBJECT_0) - { - CancelIo (intern->pipeH); - WaitForSingleObject (over.hEvent, INFINITE); - } + if (waitResult != WAIT_OBJECT_0) + { + CancelIo (intern->pipeH); + WaitForSingleObject (over.hEvent, INFINITE); + } - if (GetOverlappedResult (intern->pipeH, &over, &numWritten, FALSE)) - { - bytesWritten = (int) numWritten; - } - else if (GetLastError() == ERROR_BROKEN_PIPE && intern->createdPipe) - { - intern->disconnect(); - } - } + if (GetOverlappedResult (intern->pipeH, &over, &numWritten, FALSE)) + { + bytesWritten = (int) numWritten; + } + else if (GetLastError() == ERROR_BROKEN_PIPE && intern->createdPipe) + { + intern->disconnect(); + } + } - CloseHandle (over.hEvent); - } + CloseHandle (over.hEvent); + } - return bytesWritten; + return bytesWritten; } void NamedPipe::cancelPendingReads() { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - if (intern != 0) - SetEvent (intern->cancelEvent); + if (intern != 0) + SetEvent (intern->cancelEvent); } #endif @@ -235890,380 +213649,380 @@ void NamedPipe::cancelPendingReads() bool juce_isOnLine() { - DWORD connectionType; + DWORD connectionType; - return InternetGetConnectedState (&connectionType, 0) != 0 - || (connectionType & (INTERNET_CONNECTION_LAN | INTERNET_CONNECTION_PROXY)) != 0; + return InternetGetConnectedState (&connectionType, 0) != 0 + || (connectionType & (INTERNET_CONNECTION_LAN | INTERNET_CONNECTION_PROXY)) != 0; } struct ConnectionAndRequestStruct { - HINTERNET connection, request; + HINTERNET connection, request; }; static HINTERNET sessionHandle = 0; void* juce_openInternetFile (const String& url, - const String& headers, - const MemoryBlock& postData, - const bool isPost, - URL::OpenStreamProgressCallback* callback, - void* callbackContext, - int timeOutMs) + const String& headers, + const MemoryBlock& postData, + const bool isPost, + URL::OpenStreamProgressCallback* callback, + void* callbackContext, + int timeOutMs) { - if (sessionHandle == 0) - sessionHandle = InternetOpen (_T("juce"), - INTERNET_OPEN_TYPE_PRECONFIG, - 0, 0, 0); + if (sessionHandle == 0) + sessionHandle = InternetOpen (_T("juce"), + INTERNET_OPEN_TYPE_PRECONFIG, + 0, 0, 0); - if (sessionHandle != 0) - { - // break up the url.. - TCHAR file[1024], server[1024]; + if (sessionHandle != 0) + { + // break up the url.. + TCHAR file[1024], server[1024]; - URL_COMPONENTS uc; - zerostruct (uc); + URL_COMPONENTS uc; + zerostruct (uc); - uc.dwStructSize = sizeof (uc); - uc.dwUrlPathLength = sizeof (file); - uc.dwHostNameLength = sizeof (server); - uc.lpszUrlPath = file; - uc.lpszHostName = server; + uc.dwStructSize = sizeof (uc); + uc.dwUrlPathLength = sizeof (file); + uc.dwHostNameLength = sizeof (server); + uc.lpszUrlPath = file; + uc.lpszHostName = server; - if (InternetCrackUrl (url, 0, 0, &uc)) - { - if (timeOutMs == 0) - timeOutMs = 30000; - else if (timeOutMs < 0) - timeOutMs = -1; + if (InternetCrackUrl (url, 0, 0, &uc)) + { + if (timeOutMs == 0) + timeOutMs = 30000; + else if (timeOutMs < 0) + timeOutMs = -1; - InternetSetOption (sessionHandle, INTERNET_OPTION_CONNECT_TIMEOUT, &timeOutMs, sizeof (timeOutMs)); + InternetSetOption (sessionHandle, INTERNET_OPTION_CONNECT_TIMEOUT, &timeOutMs, sizeof (timeOutMs)); - const bool isFtp = url.startsWithIgnoreCase (T("ftp:")); + const bool isFtp = url.startsWithIgnoreCase (T("ftp:")); - HINTERNET connection = InternetConnect (sessionHandle, - uc.lpszHostName, - uc.nPort, - _T(""), _T(""), - isFtp ? INTERNET_SERVICE_FTP - : INTERNET_SERVICE_HTTP, - 0, 0); + HINTERNET connection = InternetConnect (sessionHandle, + uc.lpszHostName, + uc.nPort, + _T(""), _T(""), + isFtp ? INTERNET_SERVICE_FTP + : INTERNET_SERVICE_HTTP, + 0, 0); - if (connection != 0) - { - if (isFtp) - { - HINTERNET request = FtpOpenFile (connection, - uc.lpszUrlPath, - GENERIC_READ, - FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_NEED_FILE, - 0); + if (connection != 0) + { + if (isFtp) + { + HINTERNET request = FtpOpenFile (connection, + uc.lpszUrlPath, + GENERIC_READ, + FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_NEED_FILE, + 0); - ConnectionAndRequestStruct* const result = new ConnectionAndRequestStruct(); - result->connection = connection; - result->request = request; - return result; - } - else - { - const TCHAR* mimeTypes[] = { _T("*/*"), 0 }; + ConnectionAndRequestStruct* const result = new ConnectionAndRequestStruct(); + result->connection = connection; + result->request = request; + return result; + } + else + { + const TCHAR* mimeTypes[] = { _T("*/*"), 0 }; - DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE; + DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE; - if (url.startsWithIgnoreCase (T("https:"))) - flags |= INTERNET_FLAG_SECURE; // (this flag only seems necessary if the OS is running IE6 - - // IE7 seems to automatically work out when it's https) + if (url.startsWithIgnoreCase (T("https:"))) + flags |= INTERNET_FLAG_SECURE; // (this flag only seems necessary if the OS is running IE6 - + // IE7 seems to automatically work out when it's https) - HINTERNET request = HttpOpenRequest (connection, - isPost ? _T("POST") - : _T("GET"), - uc.lpszUrlPath, - 0, 0, mimeTypes, flags, 0); + HINTERNET request = HttpOpenRequest (connection, + isPost ? _T("POST") + : _T("GET"), + uc.lpszUrlPath, + 0, 0, mimeTypes, flags, 0); - if (request != 0) - { - INTERNET_BUFFERS buffers; - zerostruct (buffers); - buffers.dwStructSize = sizeof (INTERNET_BUFFERS); - buffers.lpcszHeader = (LPCTSTR) headers; - buffers.dwHeadersLength = headers.length(); - buffers.dwBufferTotal = (DWORD) postData.getSize(); - ConnectionAndRequestStruct* result = 0; + if (request != 0) + { + INTERNET_BUFFERS buffers; + zerostruct (buffers); + buffers.dwStructSize = sizeof (INTERNET_BUFFERS); + buffers.lpcszHeader = (LPCTSTR) headers; + buffers.dwHeadersLength = headers.length(); + buffers.dwBufferTotal = (DWORD) postData.getSize(); + ConnectionAndRequestStruct* result = 0; - if (HttpSendRequestEx (request, &buffers, 0, HSR_INITIATE, 0)) - { - int bytesSent = 0; + if (HttpSendRequestEx (request, &buffers, 0, HSR_INITIATE, 0)) + { + int bytesSent = 0; - for (;;) - { - const int bytesToDo = jmin (1024, postData.getSize() - bytesSent); - DWORD bytesDone = 0; + for (;;) + { + const int bytesToDo = jmin (1024, (int) postData.getSize() - bytesSent); + DWORD bytesDone = 0; - if (bytesToDo > 0 - && ! InternetWriteFile (request, - ((const char*) postData.getData()) + bytesSent, - bytesToDo, &bytesDone)) - { - break; - } + if (bytesToDo > 0 + && ! InternetWriteFile (request, + ((const char*) postData.getData()) + bytesSent, + bytesToDo, &bytesDone)) + { + break; + } - if (bytesToDo == 0 || (int) bytesDone < bytesToDo) - { - result = new ConnectionAndRequestStruct(); - result->connection = connection; - result->request = request; + if (bytesToDo == 0 || (int) bytesDone < bytesToDo) + { + result = new ConnectionAndRequestStruct(); + result->connection = connection; + result->request = request; - HttpEndRequest (request, 0, 0, 0); - return result; - } + HttpEndRequest (request, 0, 0, 0); + return result; + } - bytesSent += bytesDone; + bytesSent += bytesDone; - if (callback != 0 && ! callback (callbackContext, bytesSent, postData.getSize())) - break; - } - } + if (callback != 0 && ! callback (callbackContext, bytesSent, postData.getSize())) + break; + } + } - InternetCloseHandle (request); - } + InternetCloseHandle (request); + } - InternetCloseHandle (connection); - } - } - } - } + InternetCloseHandle (connection); + } + } + } + } - return 0; + return 0; } int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) { - DWORD bytesRead = 0; + DWORD bytesRead = 0; - const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; + const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; - if (crs != 0) - InternetReadFile (crs->request, - buffer, bytesToRead, - &bytesRead); + if (crs != 0) + InternetReadFile (crs->request, + buffer, bytesToRead, + &bytesRead); - return bytesRead; + return bytesRead; } int juce_seekInInternetFile (void* handle, int newPosition) { - if (handle != 0) - { - const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; + if (handle != 0) + { + const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; - return InternetSetFilePointer (crs->request, - newPosition, 0, - FILE_BEGIN, 0); - } - else - { - return -1; - } + return InternetSetFilePointer (crs->request, + newPosition, 0, + FILE_BEGIN, 0); + } + else + { + return -1; + } } int64 juce_getInternetFileContentLength (void* handle) { - const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; + const ConnectionAndRequestStruct* const crs = (const ConnectionAndRequestStruct*) handle; - if (crs != 0) - { - DWORD index = 0; - DWORD result = 0; - DWORD size = sizeof (result); + if (crs != 0) + { + DWORD index = 0; + DWORD result = 0; + DWORD size = sizeof (result); - if (HttpQueryInfo (crs->request, - HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, - &result, - &size, - &index)) - { - return (int64) result; - } - } + if (HttpQueryInfo (crs->request, + HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, + &result, + &size, + &index)) + { + return (int64) result; + } + } - return -1; + return -1; } void juce_closeInternetFile (void* handle) { - if (handle != 0) - { - ConnectionAndRequestStruct* const crs = (ConnectionAndRequestStruct*) handle; - InternetCloseHandle (crs->request); - InternetCloseHandle (crs->connection); - delete crs; - } + if (handle != 0) + { + ConnectionAndRequestStruct* const crs = (ConnectionAndRequestStruct*) handle; + InternetCloseHandle (crs->request); + InternetCloseHandle (crs->connection); + delete crs; + } } static int getMACAddressViaGetAdaptersInfo (int64* addresses, int maxNum, const bool littleEndian) throw() { - int numFound = 0; + int numFound = 0; - DynamicLibraryLoader dll ("iphlpapi.dll"); - DynamicLibraryImport (GetAdaptersInfo, getAdaptersInfo, DWORD, dll, (PIP_ADAPTER_INFO, PULONG)) + DynamicLibraryLoader dll ("iphlpapi.dll"); + DynamicLibraryImport (GetAdaptersInfo, getAdaptersInfo, DWORD, dll, (PIP_ADAPTER_INFO, PULONG)) - if (getAdaptersInfo != 0) - { - ULONG len = sizeof (IP_ADAPTER_INFO); - MemoryBlock mb; - PIP_ADAPTER_INFO adapterInfo = (PIP_ADAPTER_INFO) mb.getData(); + if (getAdaptersInfo != 0) + { + ULONG len = sizeof (IP_ADAPTER_INFO); + MemoryBlock mb; + PIP_ADAPTER_INFO adapterInfo = (PIP_ADAPTER_INFO) mb.getData(); - if (getAdaptersInfo (adapterInfo, &len) == ERROR_BUFFER_OVERFLOW) - { - mb.setSize (len); - adapterInfo = (PIP_ADAPTER_INFO) mb.getData(); - } + if (getAdaptersInfo (adapterInfo, &len) == ERROR_BUFFER_OVERFLOW) + { + mb.setSize (len); + adapterInfo = (PIP_ADAPTER_INFO) mb.getData(); + } - if (getAdaptersInfo (adapterInfo, &len) == NO_ERROR) - { - PIP_ADAPTER_INFO adapter = adapterInfo; + if (getAdaptersInfo (adapterInfo, &len) == NO_ERROR) + { + PIP_ADAPTER_INFO adapter = adapterInfo; - while (adapter != 0) - { - int64 mac = 0; - for (unsigned int i = 0; i < adapter->AddressLength; ++i) - mac = (mac << 8) | adapter->Address[i]; + while (adapter != 0) + { + int64 mac = 0; + for (unsigned int i = 0; i < adapter->AddressLength; ++i) + mac = (mac << 8) | adapter->Address[i]; - if (littleEndian) - mac = (int64) ByteOrder::swap ((uint64) mac); + if (littleEndian) + mac = (int64) ByteOrder::swap ((uint64) mac); - if (numFound < maxNum && mac != 0) - addresses [numFound++] = mac; + if (numFound < maxNum && mac != 0) + addresses [numFound++] = mac; - adapter = adapter->Next; - } - } - } + adapter = adapter->Next; + } + } + } - return numFound; + return numFound; } static int getMACAddressesViaNetBios (int64* addresses, int maxNum, const bool littleEndian) throw() { - int numFound = 0; + int numFound = 0; - DynamicLibraryLoader dll ("netapi32.dll"); - DynamicLibraryImport (Netbios, NetbiosCall, UCHAR, dll, (PNCB)) + DynamicLibraryLoader dll ("netapi32.dll"); + DynamicLibraryImport (Netbios, NetbiosCall, UCHAR, dll, (PNCB)) - if (NetbiosCall != 0) - { - NCB ncb; - zerostruct (ncb); + if (NetbiosCall != 0) + { + NCB ncb; + zerostruct (ncb); - typedef struct _ASTAT_ - { - ADAPTER_STATUS adapt; - NAME_BUFFER NameBuff [30]; - } ASTAT; + typedef struct _ASTAT_ + { + ADAPTER_STATUS adapt; + NAME_BUFFER NameBuff [30]; + } ASTAT; - ASTAT astat; - zerostruct (astat); + ASTAT astat; + zerostruct (astat); - LANA_ENUM enums; - zerostruct (enums); + LANA_ENUM enums; + zerostruct (enums); - ncb.ncb_command = NCBENUM; - ncb.ncb_buffer = (unsigned char*) &enums; - ncb.ncb_length = sizeof (LANA_ENUM); - NetbiosCall (&ncb); + ncb.ncb_command = NCBENUM; + ncb.ncb_buffer = (unsigned char*) &enums; + ncb.ncb_length = sizeof (LANA_ENUM); + NetbiosCall (&ncb); - for (int i = 0; i < enums.length; ++i) - { - zerostruct (ncb); - ncb.ncb_command = NCBRESET; - ncb.ncb_lana_num = enums.lana[i]; + for (int i = 0; i < enums.length; ++i) + { + zerostruct (ncb); + ncb.ncb_command = NCBRESET; + ncb.ncb_lana_num = enums.lana[i]; - if (NetbiosCall (&ncb) == 0) - { - zerostruct (ncb); - memcpy (ncb.ncb_callname, "* ", NCBNAMSZ); - ncb.ncb_command = NCBASTAT; - ncb.ncb_lana_num = enums.lana[i]; + if (NetbiosCall (&ncb) == 0) + { + zerostruct (ncb); + memcpy (ncb.ncb_callname, "* ", NCBNAMSZ); + ncb.ncb_command = NCBASTAT; + ncb.ncb_lana_num = enums.lana[i]; - ncb.ncb_buffer = (unsigned char*) &astat; - ncb.ncb_length = sizeof (ASTAT); + ncb.ncb_buffer = (unsigned char*) &astat; + ncb.ncb_length = sizeof (ASTAT); - if (NetbiosCall (&ncb) == 0) - { - if (astat.adapt.adapter_type == 0xfe) - { - uint64 mac = 0; - for (int i = 6; --i >= 0;) - mac = (mac << 8) | astat.adapt.adapter_address [littleEndian ? i : (5 - i)]; + if (NetbiosCall (&ncb) == 0) + { + if (astat.adapt.adapter_type == 0xfe) + { + uint64 mac = 0; + for (int i = 6; --i >= 0;) + mac = (mac << 8) | astat.adapt.adapter_address [littleEndian ? i : (5 - i)]; - if (numFound < maxNum && mac != 0) - addresses [numFound++] = mac; - } - } - } - } - } + if (numFound < maxNum && mac != 0) + addresses [numFound++] = mac; + } + } + } + } + } - return numFound; + return numFound; } int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw() { - int numFound = getMACAddressViaGetAdaptersInfo (addresses, maxNum, littleEndian); + int numFound = getMACAddressViaGetAdaptersInfo (addresses, maxNum, littleEndian); - if (numFound == 0) - numFound = getMACAddressesViaNetBios (addresses, maxNum, littleEndian); + if (numFound == 0) + numFound = getMACAddressesViaNetBios (addresses, maxNum, littleEndian); - return numFound; + return numFound; } typedef ULONG (WINAPI *MAPISendMailType) (LHANDLE, ULONG, lpMapiMessage, ::FLAGS, ULONG); bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress, - const String& emailSubject, - const String& bodyText, - const StringArray& filesToAttach) + const String& emailSubject, + const String& bodyText, + const StringArray& filesToAttach) { - HMODULE h = LoadLibraryA ("MAPI32.dll"); + HMODULE h = LoadLibraryA ("MAPI32.dll"); - MAPISendMailType mapiSendMail = (MAPISendMailType) GetProcAddress (h, "MAPISendMail"); - bool ok = false; + MAPISendMailType mapiSendMail = (MAPISendMailType) GetProcAddress (h, "MAPISendMail"); + bool ok = false; - if (mapiSendMail != 0) - { - MapiMessage message; - zerostruct (message); - message.lpszSubject = (LPSTR) (LPCSTR) emailSubject; - message.lpszNoteText = (LPSTR) (LPCSTR) bodyText; + if (mapiSendMail != 0) + { + MapiMessage message; + zerostruct (message); + message.lpszSubject = (LPSTR) (LPCSTR) emailSubject; + message.lpszNoteText = (LPSTR) (LPCSTR) bodyText; - MapiRecipDesc recip; - zerostruct (recip); - recip.ulRecipClass = MAPI_TO; - String targetEmailAddress_ (targetEmailAddress); - if (targetEmailAddress_.isEmpty()) - targetEmailAddress_ = " "; // (Windows Mail can't deal with a blank address) - recip.lpszName = (LPSTR) (LPCSTR) targetEmailAddress_; - message.nRecipCount = 1; - message.lpRecips = &recip; + MapiRecipDesc recip; + zerostruct (recip); + recip.ulRecipClass = MAPI_TO; + String targetEmailAddress_ (targetEmailAddress); + if (targetEmailAddress_.isEmpty()) + targetEmailAddress_ = " "; // (Windows Mail can't deal with a blank address) + recip.lpszName = (LPSTR) (LPCSTR) targetEmailAddress_; + message.nRecipCount = 1; + message.lpRecips = &recip; - MemoryBlock mb (sizeof (MapiFileDesc) * filesToAttach.size()); - mb.fillWith (0); - MapiFileDesc* files = (MapiFileDesc*) mb.getData(); + MemoryBlock mb (sizeof (MapiFileDesc) * filesToAttach.size()); + mb.fillWith (0); + MapiFileDesc* files = (MapiFileDesc*) mb.getData(); - message.nFileCount = filesToAttach.size(); - message.lpFiles = files; + message.nFileCount = filesToAttach.size(); + message.lpFiles = files; - for (int i = 0; i < filesToAttach.size(); ++i) - { - files[i].nPosition = (ULONG) -1; - files[i].lpszPathName = (LPSTR) (LPCSTR) filesToAttach [i]; - } + for (int i = 0; i < filesToAttach.size(); ++i) + { + files[i].nPosition = (ULONG) -1; + files[i].lpszPathName = (LPSTR) (LPCSTR) filesToAttach [i]; + } - ok = (mapiSendMail (0, 0, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0) == SUCCESS_SUCCESS); - } + ok = (mapiSendMail (0, 0, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0) == SUCCESS_SUCCESS); + } - FreeLibrary (h); - return ok; + FreeLibrary (h); + return ok; } #endif @@ -236275,196 +214034,199 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd #if JUCE_INCLUDED_FILE static HKEY findKeyForPath (String name, - const bool createForWriting, - String& valueName) + const bool createForWriting, + String& valueName) { - HKEY rootKey = 0; + HKEY rootKey = 0; - if (name.startsWithIgnoreCase (T("HKEY_CURRENT_USER\\"))) - rootKey = HKEY_CURRENT_USER; - else if (name.startsWithIgnoreCase (T("HKEY_LOCAL_MACHINE\\"))) - rootKey = HKEY_LOCAL_MACHINE; - else if (name.startsWithIgnoreCase (T("HKEY_CLASSES_ROOT\\"))) - rootKey = HKEY_CLASSES_ROOT; + if (name.startsWithIgnoreCase (T("HKEY_CURRENT_USER\\"))) + rootKey = HKEY_CURRENT_USER; + else if (name.startsWithIgnoreCase (T("HKEY_LOCAL_MACHINE\\"))) + rootKey = HKEY_LOCAL_MACHINE; + else if (name.startsWithIgnoreCase (T("HKEY_CLASSES_ROOT\\"))) + rootKey = HKEY_CLASSES_ROOT; - if (rootKey != 0) - { - name = name.substring (name.indexOfChar (T('\\')) + 1); + if (rootKey != 0) + { + name = name.substring (name.indexOfChar (T('\\')) + 1); - const int lastSlash = name.lastIndexOfChar (T('\\')); - valueName = name.substring (lastSlash + 1); - name = name.substring (0, lastSlash); + const int lastSlash = name.lastIndexOfChar (T('\\')); + valueName = name.substring (lastSlash + 1); + name = name.substring (0, lastSlash); - HKEY key; - DWORD result; + HKEY key; + DWORD result; - if (createForWriting) - { - if (RegCreateKeyEx (rootKey, name, 0, L"", REG_OPTION_NON_VOLATILE, - (KEY_WRITE | KEY_QUERY_VALUE), 0, &key, &result) == ERROR_SUCCESS) - return key; - } - else - { - if (RegOpenKeyEx (rootKey, name, 0, KEY_READ, &key) == ERROR_SUCCESS) - return key; - } - } + if (createForWriting) + { + if (RegCreateKeyEx (rootKey, name, 0, L"", REG_OPTION_NON_VOLATILE, + (KEY_WRITE | KEY_QUERY_VALUE), 0, &key, &result) == ERROR_SUCCESS) + return key; + } + else + { + if (RegOpenKeyEx (rootKey, name, 0, KEY_READ, &key) == ERROR_SUCCESS) + return key; + } + } - return 0; + return 0; } const String PlatformUtilities::getRegistryValue (const String& regValuePath, - const String& defaultValue) + const String& defaultValue) { - String valueName, s; - HKEY k = findKeyForPath (regValuePath, false, valueName); + String valueName, result (defaultValue); + HKEY k = findKeyForPath (regValuePath, false, valueName); - if (k != 0) - { - WCHAR buffer [2048]; - unsigned long bufferSize = sizeof (buffer); - DWORD type = REG_SZ; + if (k != 0) + { + WCHAR buffer [2048]; + unsigned long bufferSize = sizeof (buffer); + DWORD type = REG_SZ; - if (RegQueryValueEx (k, valueName, 0, &type, (LPBYTE) buffer, &bufferSize) == ERROR_SUCCESS) - s = buffer; - else - s = defaultValue; + if (RegQueryValueEx (k, valueName, 0, &type, (LPBYTE) buffer, &bufferSize) == ERROR_SUCCESS) + { + if (type == REG_SZ) + result = buffer; + else if (type == REG_DWORD) + result = String ((int) *(DWORD*) buffer); + } - RegCloseKey (k); - } + RegCloseKey (k); + } - return s; + return result; } void PlatformUtilities::setRegistryValue (const String& regValuePath, - const String& value) + const String& value) { - String valueName; - HKEY k = findKeyForPath (regValuePath, true, valueName); + String valueName; + HKEY k = findKeyForPath (regValuePath, true, valueName); - if (k != 0) - { - RegSetValueEx (k, valueName, 0, REG_SZ, - (const BYTE*) (const WCHAR*) value, - sizeof (WCHAR) * (value.length() + 1)); + if (k != 0) + { + RegSetValueEx (k, valueName, 0, REG_SZ, + (const BYTE*) (const WCHAR*) value, + sizeof (WCHAR) * (value.length() + 1)); - RegCloseKey (k); - } + RegCloseKey (k); + } } bool PlatformUtilities::registryValueExists (const String& regValuePath) { - bool exists = false; - String valueName; - HKEY k = findKeyForPath (regValuePath, false, valueName); + bool exists = false; + String valueName; + HKEY k = findKeyForPath (regValuePath, false, valueName); - if (k != 0) - { - unsigned char buffer [2048]; - unsigned long bufferSize = sizeof (buffer); - DWORD type = 0; + if (k != 0) + { + unsigned char buffer [2048]; + unsigned long bufferSize = sizeof (buffer); + DWORD type = 0; - if (RegQueryValueEx (k, valueName, 0, &type, buffer, &bufferSize) == ERROR_SUCCESS) - exists = true; + if (RegQueryValueEx (k, valueName, 0, &type, buffer, &bufferSize) == ERROR_SUCCESS) + exists = true; - RegCloseKey (k); - } + RegCloseKey (k); + } - return exists; + return exists; } void PlatformUtilities::deleteRegistryValue (const String& regValuePath) { - String valueName; - HKEY k = findKeyForPath (regValuePath, true, valueName); + String valueName; + HKEY k = findKeyForPath (regValuePath, true, valueName); - if (k != 0) - { - RegDeleteValue (k, valueName); - RegCloseKey (k); - } + if (k != 0) + { + RegDeleteValue (k, valueName); + RegCloseKey (k); + } } void PlatformUtilities::deleteRegistryKey (const String& regKeyPath) { - String valueName; - HKEY k = findKeyForPath (regKeyPath, true, valueName); + String valueName; + HKEY k = findKeyForPath (regKeyPath, true, valueName); - if (k != 0) - { - RegDeleteKey (k, valueName); - RegCloseKey (k); - } + if (k != 0) + { + RegDeleteKey (k, valueName); + RegCloseKey (k); + } } void PlatformUtilities::registerFileAssociation (const String& fileExtension, - const String& symbolicDescription, - const String& fullDescription, - const File& targetExecutable, - int iconResourceNumber) + const String& symbolicDescription, + const String& fullDescription, + const File& targetExecutable, + int iconResourceNumber) { - setRegistryValue ("HKEY_CLASSES_ROOT\\" + fileExtension + "\\", symbolicDescription); + setRegistryValue ("HKEY_CLASSES_ROOT\\" + fileExtension + "\\", symbolicDescription); - const String key ("HKEY_CLASSES_ROOT\\" + symbolicDescription); + const String key ("HKEY_CLASSES_ROOT\\" + symbolicDescription); - if (iconResourceNumber != 0) - setRegistryValue (key + "\\DefaultIcon\\", - targetExecutable.getFullPathName() + "," + String (-iconResourceNumber)); + if (iconResourceNumber != 0) + setRegistryValue (key + "\\DefaultIcon\\", + targetExecutable.getFullPathName() + "," + String (-iconResourceNumber)); - setRegistryValue (key + "\\", fullDescription); + setRegistryValue (key + "\\", fullDescription); - setRegistryValue (key + "\\shell\\open\\command\\", - targetExecutable.getFullPathName() + " %1"); + setRegistryValue (key + "\\shell\\open\\command\\", + targetExecutable.getFullPathName() + " %1"); } bool juce_IsRunningInWine() { - HKEY key; - if (RegOpenKeyEx (HKEY_CURRENT_USER, _T("Software\\Wine"), 0, KEY_READ, &key) == ERROR_SUCCESS) - { - RegCloseKey (key); - return true; - } + HKEY key; + if (RegOpenKeyEx (HKEY_CURRENT_USER, _T("Software\\Wine"), 0, KEY_READ, &key) == ERROR_SUCCESS) + { + RegCloseKey (key); + return true; + } - return false; + return false; } const String JUCE_CALLTYPE PlatformUtilities::getCurrentCommandLineParams() throw() { - String s (::GetCommandLineW()); + String s (::GetCommandLineW()); - StringArray tokens; - tokens.addTokens (s, true); // tokenise so that we can remove the initial filename argument + StringArray tokens; + tokens.addTokens (s, true); // tokenise so that we can remove the initial filename argument - return tokens.joinIntoString (T(" "), 1); + return tokens.joinIntoString (T(" "), 1); } static void* currentModuleHandle = 0; void* PlatformUtilities::getCurrentModuleInstanceHandle() throw() { - if (currentModuleHandle == 0) - currentModuleHandle = GetModuleHandle (0); + if (currentModuleHandle == 0) + currentModuleHandle = GetModuleHandle (0); - return currentModuleHandle; + return currentModuleHandle; } void PlatformUtilities::setCurrentModuleInstanceHandle (void* const newHandle) throw() { - currentModuleHandle = newHandle; + currentModuleHandle = newHandle; } void PlatformUtilities::fpuReset() { #if JUCE_MSVC - _clearfp(); + _clearfp(); #endif } void PlatformUtilities::beep() { - MessageBeep (MB_OK); + MessageBeep (MB_OK); } #endif @@ -236477,9 +214239,9 @@ void PlatformUtilities::beep() // compiled on its own). #if JUCE_INCLUDED_FILE -static const unsigned int specialId = WM_APP + 0x4400; -static const unsigned int broadcastId = WM_APP + 0x4403; -static const unsigned int specialCallbackId = WM_APP + 0x4402; +static const unsigned int specialId = WM_APP + 0x4400; +static const unsigned int broadcastId = WM_APP + 0x4403; +static const unsigned int specialCallbackId = WM_APP + 0x4402; static const TCHAR* const messageWindowName = _T("JUCEWindow"); @@ -236487,248 +214249,252 @@ HWND juce_messageWindowHandle = 0; extern long improbableWindowNumber; // defined in windowing.cpp +#ifndef WM_APPCOMMAND + #define WM_APPCOMMAND 0x0319 +#endif + static LRESULT CALLBACK juce_MessageWndProc (HWND h, - const UINT message, - const WPARAM wParam, - const LPARAM lParam) throw() + const UINT message, + const WPARAM wParam, + const LPARAM lParam) throw() { - JUCE_TRY - { - if (h == juce_messageWindowHandle) - { - if (message == specialCallbackId) - { - MessageCallbackFunction* const func = (MessageCallbackFunction*) wParam; - return (LRESULT) (*func) ((void*) lParam); - } - else if (message == specialId) - { - // these are trapped early in the dispatch call, but must also be checked - // here in case there are windows modal dialog boxes doing their own - // dispatch loop and not calling our version + JUCE_TRY + { + if (h == juce_messageWindowHandle) + { + if (message == specialCallbackId) + { + MessageCallbackFunction* const func = (MessageCallbackFunction*) wParam; + return (LRESULT) (*func) ((void*) lParam); + } + else if (message == specialId) + { + // these are trapped early in the dispatch call, but must also be checked + // here in case there are windows modal dialog boxes doing their own + // dispatch loop and not calling our version - MessageManager::getInstance()->deliverMessage ((void*) lParam); - return 0; - } - else if (message == broadcastId) - { - const ScopedPointer messageString ((String*) lParam); - MessageManager::getInstance()->deliverBroadcastMessage (*messageString); - return 0; - } - else if (message == WM_COPYDATA && ((const COPYDATASTRUCT*) lParam)->dwData == broadcastId) - { - const String messageString ((const juce_wchar*) ((const COPYDATASTRUCT*) lParam)->lpData, - ((const COPYDATASTRUCT*) lParam)->cbData / sizeof (juce_wchar)); + MessageManager::getInstance()->deliverMessage ((void*) lParam); + return 0; + } + else if (message == broadcastId) + { + const ScopedPointer messageString ((String*) lParam); + MessageManager::getInstance()->deliverBroadcastMessage (*messageString); + return 0; + } + else if (message == WM_COPYDATA && ((const COPYDATASTRUCT*) lParam)->dwData == broadcastId) + { + const String messageString ((const juce_wchar*) ((const COPYDATASTRUCT*) lParam)->lpData, + ((const COPYDATASTRUCT*) lParam)->cbData / sizeof (juce_wchar)); - PostMessage (juce_messageWindowHandle, broadcastId, 0, (LPARAM) new String (messageString)); - return 0; - } - } - } - JUCE_CATCH_EXCEPTION + PostMessage (juce_messageWindowHandle, broadcastId, 0, (LPARAM) new String (messageString)); + return 0; + } + } + } + JUCE_CATCH_EXCEPTION - return DefWindowProc (h, message, wParam, lParam); + return DefWindowProc (h, message, wParam, lParam); } static bool isEventBlockedByModalComps (MSG& m) { - if (Component::getNumCurrentlyModalComponents() == 0 - || GetWindowLong (m.hwnd, GWLP_USERDATA) == improbableWindowNumber) - return false; + if (Component::getNumCurrentlyModalComponents() == 0 + || GetWindowLong (m.hwnd, GWLP_USERDATA) == improbableWindowNumber) + return false; - switch (m.message) - { - case WM_MOUSEMOVE: - case WM_NCMOUSEMOVE: - case 0x020A: /* WM_MOUSEWHEEL */ - case 0x020E: /* WM_MOUSEHWHEEL */ - case WM_KEYUP: - case WM_SYSKEYUP: - case WM_CHAR: - case WM_APPCOMMAND: - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - case WM_MOUSEACTIVATE: - case WM_NCMOUSEHOVER: - case WM_MOUSEHOVER: - return true; + switch (m.message) + { + case WM_MOUSEMOVE: + case WM_NCMOUSEMOVE: + case 0x020A: /* WM_MOUSEWHEEL */ + case 0x020E: /* WM_MOUSEHWHEEL */ + case WM_KEYUP: + case WM_SYSKEYUP: + case WM_CHAR: + case WM_APPCOMMAND: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_MOUSEACTIVATE: + case WM_NCMOUSEHOVER: + case WM_MOUSEHOVER: + return true; - case WM_NCLBUTTONDOWN: - case WM_NCLBUTTONDBLCLK: - case WM_NCRBUTTONDOWN: - case WM_NCRBUTTONDBLCLK: - case WM_NCMBUTTONDOWN: - case WM_NCMBUTTONDBLCLK: - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - { - Component* const modal = Component::getCurrentlyModalComponent (0); - if (modal != 0) - modal->inputAttemptWhenModal(); + case WM_NCLBUTTONDOWN: + case WM_NCLBUTTONDBLCLK: + case WM_NCRBUTTONDOWN: + case WM_NCRBUTTONDBLCLK: + case WM_NCMBUTTONDOWN: + case WM_NCMBUTTONDBLCLK: + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + { + Component* const modal = Component::getCurrentlyModalComponent (0); + if (modal != 0) + modal->inputAttemptWhenModal(); - return true; - } + return true; + } - default: - break; - } + default: + break; + } - return false; + return false; } bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages) { - MSG m; + MSG m; - if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, 0)) - return false; + if (returnIfNoPendingMessages && ! PeekMessage (&m, (HWND) 0, 0, 0, 0)) + return false; - if (GetMessage (&m, (HWND) 0, 0, 0) > 0) - { - if (m.message == specialId - && m.hwnd == juce_messageWindowHandle) - { - MessageManager::getInstance()->deliverMessage ((void*) m.lParam); - } - else if (! isEventBlockedByModalComps (m)) - { - if (GetWindowLong (m.hwnd, GWLP_USERDATA) != improbableWindowNumber - && (m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)) - { - // if it's someone else's window being clicked on, and the focus is - // currently on a juce window, pass the kb focus over.. - HWND currentFocus = GetFocus(); + if (GetMessage (&m, (HWND) 0, 0, 0) > 0) + { + if (m.message == specialId + && m.hwnd == juce_messageWindowHandle) + { + MessageManager::getInstance()->deliverMessage ((void*) m.lParam); + } + else if (! isEventBlockedByModalComps (m)) + { + if (GetWindowLong (m.hwnd, GWLP_USERDATA) != improbableWindowNumber + && (m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)) + { + // if it's someone else's window being clicked on, and the focus is + // currently on a juce window, pass the kb focus over.. + HWND currentFocus = GetFocus(); - if (currentFocus == 0 || GetWindowLong (currentFocus, GWLP_USERDATA) == improbableWindowNumber) - SetFocus (m.hwnd); - } + if (currentFocus == 0 || GetWindowLong (currentFocus, GWLP_USERDATA) == improbableWindowNumber) + SetFocus (m.hwnd); + } - TranslateMessage (&m); - DispatchMessage (&m); - } - } + TranslateMessage (&m); + DispatchMessage (&m); + } + } - return true; + return true; } bool juce_postMessageToSystemQueue (void* message) { - return PostMessage (juce_messageWindowHandle, specialId, 0, (LPARAM) message) != 0; + return PostMessage (juce_messageWindowHandle, specialId, 0, (LPARAM) message) != 0; } void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, - void* userData) + void* userData) { - if (MessageManager::getInstance()->isThisTheMessageThread()) - { - return (*callback) (userData); - } - else - { - // If a thread has a MessageManagerLock and then tries to call this method, it'll - // deadlock because the message manager is blocked from running, and can't - // call your function.. - jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager()); + if (MessageManager::getInstance()->isThisTheMessageThread()) + { + return (*callback) (userData); + } + else + { + // If a thread has a MessageManagerLock and then tries to call this method, it'll + // deadlock because the message manager is blocked from running, and can't + // call your function.. + jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - return (void*) SendMessage (juce_messageWindowHandle, - specialCallbackId, - (WPARAM) callback, - (LPARAM) userData); - } + return (void*) SendMessage (juce_messageWindowHandle, + specialCallbackId, + (WPARAM) callback, + (LPARAM) userData); + } } static BOOL CALLBACK BroadcastEnumWindowProc (HWND hwnd, LPARAM lParam) { - if (hwnd != juce_messageWindowHandle) - (reinterpret_cast (lParam))->add ((void*) hwnd); + if (hwnd != juce_messageWindowHandle) + (reinterpret_cast (lParam))->add ((void*) hwnd); - return TRUE; + return TRUE; } void MessageManager::broadcastMessage (const String& value) throw() { - VoidArray windows; - EnumWindows (&BroadcastEnumWindowProc, (LPARAM) &windows); + VoidArray windows; + EnumWindows (&BroadcastEnumWindowProc, (LPARAM) &windows); - const String localCopy (value); + const String localCopy (value); - COPYDATASTRUCT data; - data.dwData = broadcastId; - data.cbData = (localCopy.length() + 1) * sizeof (juce_wchar); - data.lpData = (void*) (const juce_wchar*) localCopy; + COPYDATASTRUCT data; + data.dwData = broadcastId; + data.cbData = (localCopy.length() + 1) * sizeof (juce_wchar); + data.lpData = (void*) (const juce_wchar*) localCopy; - for (int i = windows.size(); --i >= 0;) - { - HWND hwnd = (HWND) windows.getUnchecked(i); + for (int i = windows.size(); --i >= 0;) + { + HWND hwnd = (HWND) windows.getUnchecked(i); - TCHAR windowName [64]; // no need to read longer strings than this - GetWindowText (hwnd, windowName, 64); - windowName [63] = 0; + TCHAR windowName [64]; // no need to read longer strings than this + GetWindowText (hwnd, windowName, 64); + windowName [63] = 0; - if (String (windowName) == String (messageWindowName)) - { - DWORD_PTR result; - SendMessageTimeout (hwnd, WM_COPYDATA, - (WPARAM) juce_messageWindowHandle, - (LPARAM) &data, - SMTO_BLOCK | SMTO_ABORTIFHUNG, - 8000, - &result); - } - } + if (String (windowName) == String (messageWindowName)) + { + DWORD_PTR result; + SendMessageTimeout (hwnd, WM_COPYDATA, + (WPARAM) juce_messageWindowHandle, + (LPARAM) &data, + SMTO_BLOCK | SMTO_ABORTIFHUNG, + 8000, + &result); + } + } } static const String getMessageWindowClassName() { - // this name has to be different for each app/dll instance because otherwise - // poor old Win32 can get a bit confused (even despite it not being a process-global - // window class). + // this name has to be different for each app/dll instance because otherwise + // poor old Win32 can get a bit confused (even despite it not being a process-global + // window class). - static int number = 0; - if (number == 0) - number = 0x7fffffff & (int) Time::getHighResolutionTicks(); + static int number = 0; + if (number == 0) + number = 0x7fffffff & (int) Time::getHighResolutionTicks(); - return T("JUCEcs_") + String (number); + return T("JUCEcs_") + String (number); } void MessageManager::doPlatformSpecificInitialisation() { - OleInitialize (0); + OleInitialize (0); - const String className (getMessageWindowClassName()); + const String className (getMessageWindowClassName()); - HMODULE hmod = (HMODULE) PlatformUtilities::getCurrentModuleInstanceHandle(); + HMODULE hmod = (HMODULE) PlatformUtilities::getCurrentModuleInstanceHandle(); - WNDCLASSEX wc; - zerostruct (wc); + WNDCLASSEX wc; + zerostruct (wc); - wc.cbSize = sizeof (wc); - wc.lpfnWndProc = (WNDPROC) juce_MessageWndProc; - wc.cbWndExtra = 4; - wc.hInstance = hmod; - wc.lpszClassName = className; + wc.cbSize = sizeof (wc); + wc.lpfnWndProc = (WNDPROC) juce_MessageWndProc; + wc.cbWndExtra = 4; + wc.hInstance = hmod; + wc.lpszClassName = className; - RegisterClassEx (&wc); + RegisterClassEx (&wc); - juce_messageWindowHandle = CreateWindow (wc.lpszClassName, - messageWindowName, - 0, 0, 0, 0, 0, 0, 0, - hmod, 0); + juce_messageWindowHandle = CreateWindow (wc.lpszClassName, + messageWindowName, + 0, 0, 0, 0, 0, 0, 0, + hmod, 0); } void MessageManager::doPlatformSpecificShutdown() { - DestroyWindow (juce_messageWindowHandle); - UnregisterClass (getMessageWindowClassName(), 0); - OleUninitialize(); + DestroyWindow (juce_messageWindowHandle); + UnregisterClass (getMessageWindowClassName(), 0); + OleUninitialize(); } #endif @@ -236743,21 +214509,21 @@ void MessageManager::doPlatformSpecificShutdown() // these are in the windows SDK, but need to be repeated here for GCC.. #ifndef GET_APPCOMMAND_LPARAM - #define FAPPCOMMAND_MASK 0xF000 - #define GET_APPCOMMAND_LPARAM(lParam) ((short) (HIWORD (lParam) & ~FAPPCOMMAND_MASK)) - #define APPCOMMAND_MEDIA_NEXTTRACK 11 - #define APPCOMMAND_MEDIA_PREVIOUSTRACK 12 - #define APPCOMMAND_MEDIA_STOP 13 - #define APPCOMMAND_MEDIA_PLAY_PAUSE 14 - #define WM_APPCOMMAND 0x0319 + #define FAPPCOMMAND_MASK 0xF000 + #define GET_APPCOMMAND_LPARAM(lParam) ((short) (HIWORD (lParam) & ~FAPPCOMMAND_MASK)) + #define APPCOMMAND_MEDIA_NEXTTRACK 11 + #define APPCOMMAND_MEDIA_PREVIOUSTRACK 12 + #define APPCOMMAND_MEDIA_STOP 13 + #define APPCOMMAND_MEDIA_PLAY_PAUSE 14 + #define WM_APPCOMMAND 0x0319 #endif -extern void juce_repeatLastProcessPriority() throw(); // in juce_win32_Threads.cpp -extern void juce_CheckCurrentlyFocusedTopLevelWindow() throw(); // in juce_TopLevelWindow.cpp -extern bool juce_IsRunningInWine() throw(); +extern void juce_repeatLastProcessPriority(); // in juce_win32_Threads.cpp +extern void juce_CheckCurrentlyFocusedTopLevelWindow(); // in juce_TopLevelWindow.cpp +extern bool juce_IsRunningInWine(); #ifndef ULW_ALPHA - #define ULW_ALPHA 0x00000002 + #define ULW_ALPHA 0x00000002 #endif #ifndef AC_SRC_ALPHA @@ -236780,259 +214546,259 @@ static UpdateLayeredWinFunc updateLayeredWindow = 0; bool Desktop::canUseSemiTransparentWindows() throw() { - if (updateLayeredWindow == 0) - { - if (! juce_IsRunningInWine()) - { - HMODULE user32Mod = GetModuleHandle (_T("user32.dll")); - updateLayeredWindow = (UpdateLayeredWinFunc) GetProcAddress (user32Mod, "UpdateLayeredWindow"); - } - } + if (updateLayeredWindow == 0) + { + if (! juce_IsRunningInWine()) + { + HMODULE user32Mod = GetModuleHandle (_T("user32.dll")); + updateLayeredWindow = (UpdateLayeredWinFunc) GetProcAddress (user32Mod, "UpdateLayeredWindow"); + } + } - return updateLayeredWindow != 0; + return updateLayeredWindow != 0; } #undef DefWindowProc #define DefWindowProc DefWindowProcW -const int extendedKeyModifier = 0x10000; +const int extendedKeyModifier = 0x10000; -const int KeyPress::spaceKey = VK_SPACE; -const int KeyPress::returnKey = VK_RETURN; -const int KeyPress::escapeKey = VK_ESCAPE; -const int KeyPress::backspaceKey = VK_BACK; -const int KeyPress::deleteKey = VK_DELETE | extendedKeyModifier; -const int KeyPress::insertKey = VK_INSERT | extendedKeyModifier; -const int KeyPress::tabKey = VK_TAB; -const int KeyPress::leftKey = VK_LEFT | extendedKeyModifier; -const int KeyPress::rightKey = VK_RIGHT | extendedKeyModifier; -const int KeyPress::upKey = VK_UP | extendedKeyModifier; -const int KeyPress::downKey = VK_DOWN | extendedKeyModifier; -const int KeyPress::homeKey = VK_HOME | extendedKeyModifier; -const int KeyPress::endKey = VK_END | extendedKeyModifier; -const int KeyPress::pageUpKey = VK_PRIOR | extendedKeyModifier; -const int KeyPress::pageDownKey = VK_NEXT | extendedKeyModifier; -const int KeyPress::F1Key = VK_F1 | extendedKeyModifier; -const int KeyPress::F2Key = VK_F2 | extendedKeyModifier; -const int KeyPress::F3Key = VK_F3 | extendedKeyModifier; -const int KeyPress::F4Key = VK_F4 | extendedKeyModifier; -const int KeyPress::F5Key = VK_F5 | extendedKeyModifier; -const int KeyPress::F6Key = VK_F6 | extendedKeyModifier; -const int KeyPress::F7Key = VK_F7 | extendedKeyModifier; -const int KeyPress::F8Key = VK_F8 | extendedKeyModifier; -const int KeyPress::F9Key = VK_F9 | extendedKeyModifier; -const int KeyPress::F10Key = VK_F10 | extendedKeyModifier; -const int KeyPress::F11Key = VK_F11 | extendedKeyModifier; -const int KeyPress::F12Key = VK_F12 | extendedKeyModifier; -const int KeyPress::F13Key = VK_F13 | extendedKeyModifier; -const int KeyPress::F14Key = VK_F14 | extendedKeyModifier; -const int KeyPress::F15Key = VK_F15 | extendedKeyModifier; -const int KeyPress::F16Key = VK_F16 | extendedKeyModifier; -const int KeyPress::numberPad0 = VK_NUMPAD0 | extendedKeyModifier; -const int KeyPress::numberPad1 = VK_NUMPAD1 | extendedKeyModifier; -const int KeyPress::numberPad2 = VK_NUMPAD2 | extendedKeyModifier; -const int KeyPress::numberPad3 = VK_NUMPAD3 | extendedKeyModifier; -const int KeyPress::numberPad4 = VK_NUMPAD4 | extendedKeyModifier; -const int KeyPress::numberPad5 = VK_NUMPAD5 | extendedKeyModifier; -const int KeyPress::numberPad6 = VK_NUMPAD6 | extendedKeyModifier; -const int KeyPress::numberPad7 = VK_NUMPAD7 | extendedKeyModifier; -const int KeyPress::numberPad8 = VK_NUMPAD8 | extendedKeyModifier; -const int KeyPress::numberPad9 = VK_NUMPAD9 | extendedKeyModifier; -const int KeyPress::numberPadAdd = VK_ADD | extendedKeyModifier; -const int KeyPress::numberPadSubtract = VK_SUBTRACT | extendedKeyModifier; -const int KeyPress::numberPadMultiply = VK_MULTIPLY | extendedKeyModifier; -const int KeyPress::numberPadDivide = VK_DIVIDE | extendedKeyModifier; -const int KeyPress::numberPadSeparator = VK_SEPARATOR | extendedKeyModifier; -const int KeyPress::numberPadDecimalPoint = VK_DECIMAL | extendedKeyModifier; -const int KeyPress::numberPadEquals = 0x92 /*VK_OEM_NEC_EQUAL*/ | extendedKeyModifier; -const int KeyPress::numberPadDelete = VK_DELETE | extendedKeyModifier; -const int KeyPress::playKey = 0x30000; -const int KeyPress::stopKey = 0x30001; -const int KeyPress::fastForwardKey = 0x30002; -const int KeyPress::rewindKey = 0x30003; +const int KeyPress::spaceKey = VK_SPACE; +const int KeyPress::returnKey = VK_RETURN; +const int KeyPress::escapeKey = VK_ESCAPE; +const int KeyPress::backspaceKey = VK_BACK; +const int KeyPress::deleteKey = VK_DELETE | extendedKeyModifier; +const int KeyPress::insertKey = VK_INSERT | extendedKeyModifier; +const int KeyPress::tabKey = VK_TAB; +const int KeyPress::leftKey = VK_LEFT | extendedKeyModifier; +const int KeyPress::rightKey = VK_RIGHT | extendedKeyModifier; +const int KeyPress::upKey = VK_UP | extendedKeyModifier; +const int KeyPress::downKey = VK_DOWN | extendedKeyModifier; +const int KeyPress::homeKey = VK_HOME | extendedKeyModifier; +const int KeyPress::endKey = VK_END | extendedKeyModifier; +const int KeyPress::pageUpKey = VK_PRIOR | extendedKeyModifier; +const int KeyPress::pageDownKey = VK_NEXT | extendedKeyModifier; +const int KeyPress::F1Key = VK_F1 | extendedKeyModifier; +const int KeyPress::F2Key = VK_F2 | extendedKeyModifier; +const int KeyPress::F3Key = VK_F3 | extendedKeyModifier; +const int KeyPress::F4Key = VK_F4 | extendedKeyModifier; +const int KeyPress::F5Key = VK_F5 | extendedKeyModifier; +const int KeyPress::F6Key = VK_F6 | extendedKeyModifier; +const int KeyPress::F7Key = VK_F7 | extendedKeyModifier; +const int KeyPress::F8Key = VK_F8 | extendedKeyModifier; +const int KeyPress::F9Key = VK_F9 | extendedKeyModifier; +const int KeyPress::F10Key = VK_F10 | extendedKeyModifier; +const int KeyPress::F11Key = VK_F11 | extendedKeyModifier; +const int KeyPress::F12Key = VK_F12 | extendedKeyModifier; +const int KeyPress::F13Key = VK_F13 | extendedKeyModifier; +const int KeyPress::F14Key = VK_F14 | extendedKeyModifier; +const int KeyPress::F15Key = VK_F15 | extendedKeyModifier; +const int KeyPress::F16Key = VK_F16 | extendedKeyModifier; +const int KeyPress::numberPad0 = VK_NUMPAD0 | extendedKeyModifier; +const int KeyPress::numberPad1 = VK_NUMPAD1 | extendedKeyModifier; +const int KeyPress::numberPad2 = VK_NUMPAD2 | extendedKeyModifier; +const int KeyPress::numberPad3 = VK_NUMPAD3 | extendedKeyModifier; +const int KeyPress::numberPad4 = VK_NUMPAD4 | extendedKeyModifier; +const int KeyPress::numberPad5 = VK_NUMPAD5 | extendedKeyModifier; +const int KeyPress::numberPad6 = VK_NUMPAD6 | extendedKeyModifier; +const int KeyPress::numberPad7 = VK_NUMPAD7 | extendedKeyModifier; +const int KeyPress::numberPad8 = VK_NUMPAD8 | extendedKeyModifier; +const int KeyPress::numberPad9 = VK_NUMPAD9 | extendedKeyModifier; +const int KeyPress::numberPadAdd = VK_ADD | extendedKeyModifier; +const int KeyPress::numberPadSubtract = VK_SUBTRACT | extendedKeyModifier; +const int KeyPress::numberPadMultiply = VK_MULTIPLY | extendedKeyModifier; +const int KeyPress::numberPadDivide = VK_DIVIDE | extendedKeyModifier; +const int KeyPress::numberPadSeparator = VK_SEPARATOR | extendedKeyModifier; +const int KeyPress::numberPadDecimalPoint = VK_DECIMAL | extendedKeyModifier; +const int KeyPress::numberPadEquals = 0x92 /*VK_OEM_NEC_EQUAL*/ | extendedKeyModifier; +const int KeyPress::numberPadDelete = VK_DELETE | extendedKeyModifier; +const int KeyPress::playKey = 0x30000; +const int KeyPress::stopKey = 0x30001; +const int KeyPress::fastForwardKey = 0x30002; +const int KeyPress::rewindKey = 0x30003; class WindowsBitmapImage : public Image { public: - HBITMAP hBitmap; - BITMAPV4HEADER bitmapInfo; - HDC hdc; - unsigned char* bitmapData; + HBITMAP hBitmap; + BITMAPV4HEADER bitmapInfo; + HDC hdc; + unsigned char* bitmapData; - WindowsBitmapImage (const PixelFormat format_, - const int w, const int h, const bool clearImage) - : Image (format_, w, h) - { - jassert (format_ == RGB || format_ == ARGB); + WindowsBitmapImage (const PixelFormat format_, + const int w, const int h, const bool clearImage) + : Image (format_, w, h) + { + jassert (format_ == RGB || format_ == ARGB); - pixelStride = (format_ == RGB) ? 3 : 4; + pixelStride = (format_ == RGB) ? 3 : 4; - zerostruct (bitmapInfo); - bitmapInfo.bV4Size = sizeof (BITMAPV4HEADER); - bitmapInfo.bV4Width = w; - bitmapInfo.bV4Height = h; - bitmapInfo.bV4Planes = 1; - bitmapInfo.bV4CSType = 1; - bitmapInfo.bV4BitCount = (unsigned short) (pixelStride * 8); + zerostruct (bitmapInfo); + bitmapInfo.bV4Size = sizeof (BITMAPV4HEADER); + bitmapInfo.bV4Width = w; + bitmapInfo.bV4Height = h; + bitmapInfo.bV4Planes = 1; + bitmapInfo.bV4CSType = 1; + bitmapInfo.bV4BitCount = (unsigned short) (pixelStride * 8); - if (format_ == ARGB) - { - bitmapInfo.bV4AlphaMask = 0xff000000; - bitmapInfo.bV4RedMask = 0xff0000; - bitmapInfo.bV4GreenMask = 0xff00; - bitmapInfo.bV4BlueMask = 0xff; - bitmapInfo.bV4V4Compression = BI_BITFIELDS; - } - else - { - bitmapInfo.bV4V4Compression = BI_RGB; - } + if (format_ == ARGB) + { + bitmapInfo.bV4AlphaMask = 0xff000000; + bitmapInfo.bV4RedMask = 0xff0000; + bitmapInfo.bV4GreenMask = 0xff00; + bitmapInfo.bV4BlueMask = 0xff; + bitmapInfo.bV4V4Compression = BI_BITFIELDS; + } + else + { + bitmapInfo.bV4V4Compression = BI_RGB; + } - lineStride = -((w * pixelStride + 3) & ~3); + lineStride = -((w * pixelStride + 3) & ~3); - HDC dc = GetDC (0); - hdc = CreateCompatibleDC (dc); - ReleaseDC (0, dc); + HDC dc = GetDC (0); + hdc = CreateCompatibleDC (dc); + ReleaseDC (0, dc); - SetMapMode (hdc, MM_TEXT); + SetMapMode (hdc, MM_TEXT); - hBitmap = CreateDIBSection (hdc, - (BITMAPINFO*) &(bitmapInfo), - DIB_RGB_COLORS, - (void**) &bitmapData, - 0, 0); + hBitmap = CreateDIBSection (hdc, + (BITMAPINFO*) &(bitmapInfo), + DIB_RGB_COLORS, + (void**) &bitmapData, + 0, 0); - SelectObject (hdc, hBitmap); + SelectObject (hdc, hBitmap); - if (format_ == ARGB && clearImage) - zeromem (bitmapData, abs (h * lineStride)); + if (format_ == ARGB && clearImage) + zeromem (bitmapData, abs (h * lineStride)); - imageData = bitmapData - (lineStride * (h - 1)); - } + imageData = bitmapData - (lineStride * (h - 1)); + } - ~WindowsBitmapImage() - { - DeleteDC (hdc); - DeleteObject (hBitmap); - } + ~WindowsBitmapImage() + { + DeleteDC (hdc); + DeleteObject (hBitmap); + } - void blitToWindow (HWND hwnd, HDC dc, const bool transparent, - const int x, const int y, - const RectangleList& maskedRegion) throw() - { - static HDRAWDIB hdd = 0; - static bool needToCreateDrawDib = true; + void blitToWindow (HWND hwnd, HDC dc, const bool transparent, + const int x, const int y, + const RectangleList& maskedRegion) throw() + { + static HDRAWDIB hdd = 0; + static bool needToCreateDrawDib = true; - if (needToCreateDrawDib) - { - needToCreateDrawDib = false; + if (needToCreateDrawDib) + { + needToCreateDrawDib = false; - HDC dc = GetDC (0); - const int n = GetDeviceCaps (dc, BITSPIXEL); - ReleaseDC (0, dc); + HDC dc = GetDC (0); + const int n = GetDeviceCaps (dc, BITSPIXEL); + ReleaseDC (0, dc); - // only open if we're not palettised - if (n > 8) - hdd = DrawDibOpen(); - } + // only open if we're not palettised + if (n > 8) + hdd = DrawDibOpen(); + } - if (createPaletteIfNeeded) - { - HDC dc = GetDC (0); - const int n = GetDeviceCaps (dc, BITSPIXEL); - ReleaseDC (0, dc); + if (createPaletteIfNeeded) + { + HDC dc = GetDC (0); + const int n = GetDeviceCaps (dc, BITSPIXEL); + ReleaseDC (0, dc); - if (n <= 8) - palette = CreateHalftonePalette (dc); + if (n <= 8) + palette = CreateHalftonePalette (dc); - createPaletteIfNeeded = false; - } + createPaletteIfNeeded = false; + } - if (palette != 0) - { - SelectPalette (dc, palette, FALSE); - RealizePalette (dc); - SetStretchBltMode (dc, HALFTONE); - } + if (palette != 0) + { + SelectPalette (dc, palette, FALSE); + RealizePalette (dc); + SetStretchBltMode (dc, HALFTONE); + } - SetMapMode (dc, MM_TEXT); + SetMapMode (dc, MM_TEXT); - if (transparent) - { - POINT p, pos; - SIZE size; + if (transparent) + { + POINT p, pos; + SIZE size; - RECT windowBounds; - GetWindowRect (hwnd, &windowBounds); + RECT windowBounds; + GetWindowRect (hwnd, &windowBounds); - p.x = -x; - p.y = -y; - pos.x = windowBounds.left; - pos.y = windowBounds.top; - size.cx = windowBounds.right - windowBounds.left; - size.cy = windowBounds.bottom - windowBounds.top; + p.x = -x; + p.y = -y; + pos.x = windowBounds.left; + pos.y = windowBounds.top; + size.cx = windowBounds.right - windowBounds.left; + size.cy = windowBounds.bottom - windowBounds.top; - BLENDFUNCTION bf; - bf.AlphaFormat = AC_SRC_ALPHA; - bf.BlendFlags = 0; - bf.BlendOp = AC_SRC_OVER; - bf.SourceConstantAlpha = 0xff; + BLENDFUNCTION bf; + bf.AlphaFormat = AC_SRC_ALPHA; + bf.BlendFlags = 0; + bf.BlendOp = AC_SRC_OVER; + bf.SourceConstantAlpha = 0xff; - if (! maskedRegion.isEmpty()) - { - for (RectangleList::Iterator i (maskedRegion); i.next();) - { - const Rectangle& r = *i.getRectangle(); - ExcludeClipRect (hdc, r.getX(), r.getY(), r.getRight(), r.getBottom()); - } - } + if (! maskedRegion.isEmpty()) + { + for (RectangleList::Iterator i (maskedRegion); i.next();) + { + const Rectangle& r = *i.getRectangle(); + ExcludeClipRect (hdc, r.getX(), r.getY(), r.getRight(), r.getBottom()); + } + } - updateLayeredWindow (hwnd, 0, &pos, &size, hdc, &p, 0, &bf, ULW_ALPHA); - } - else - { - int savedDC = 0; + updateLayeredWindow (hwnd, 0, &pos, &size, hdc, &p, 0, &bf, ULW_ALPHA); + } + else + { + int savedDC = 0; - if (! maskedRegion.isEmpty()) - { - savedDC = SaveDC (dc); + if (! maskedRegion.isEmpty()) + { + savedDC = SaveDC (dc); - for (RectangleList::Iterator i (maskedRegion); i.next();) - { - const Rectangle& r = *i.getRectangle(); - ExcludeClipRect (dc, r.getX(), r.getY(), r.getRight(), r.getBottom()); - } - } + for (RectangleList::Iterator i (maskedRegion); i.next();) + { + const Rectangle& r = *i.getRectangle(); + ExcludeClipRect (dc, r.getX(), r.getY(), r.getRight(), r.getBottom()); + } + } - const int w = getWidth(); - const int h = getHeight(); + const int w = getWidth(); + const int h = getHeight(); - if (hdd == 0) - { - StretchDIBits (dc, - x, y, w, h, - 0, 0, w, h, - bitmapData, (const BITMAPINFO*) &bitmapInfo, - DIB_RGB_COLORS, SRCCOPY); - } - else - { - DrawDibDraw (hdd, dc, x, y, -1, -1, - (BITMAPINFOHEADER*) &bitmapInfo, bitmapData, - 0, 0, w, h, 0); - } + if (hdd == 0) + { + StretchDIBits (dc, + x, y, w, h, + 0, 0, w, h, + bitmapData, (const BITMAPINFO*) &bitmapInfo, + DIB_RGB_COLORS, SRCCOPY); + } + else + { + DrawDibDraw (hdd, dc, x, y, -1, -1, + (BITMAPINFOHEADER*) &bitmapInfo, bitmapData, + 0, 0, w, h, 0); + } - if (! maskedRegion.isEmpty()) - RestoreDC (dc, savedDC); - } - } + if (! maskedRegion.isEmpty()) + RestoreDC (dc, savedDC); + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - WindowsBitmapImage (const WindowsBitmapImage&); - const WindowsBitmapImage& operator= (const WindowsBitmapImage&); + WindowsBitmapImage (const WindowsBitmapImage&); + const WindowsBitmapImage& operator= (const WindowsBitmapImage&); }; long improbableWindowNumber = 0xf965aa01; // also referenced by messaging.cpp @@ -237042,2725 +214808,2707 @@ static int modifiersAtLastCallback = 0; static void updateKeyModifiers() throw() { - currentModifiers &= ~(ModifierKeys::shiftModifier - | ModifierKeys::ctrlModifier - | ModifierKeys::altModifier); + currentModifiers &= ~(ModifierKeys::shiftModifier + | ModifierKeys::ctrlModifier + | ModifierKeys::altModifier); - if ((GetKeyState (VK_SHIFT) & 0x8000) != 0) - currentModifiers |= ModifierKeys::shiftModifier; + if ((GetKeyState (VK_SHIFT) & 0x8000) != 0) + currentModifiers |= ModifierKeys::shiftModifier; - if ((GetKeyState (VK_CONTROL) & 0x8000) != 0) - currentModifiers |= ModifierKeys::ctrlModifier; + if ((GetKeyState (VK_CONTROL) & 0x8000) != 0) + currentModifiers |= ModifierKeys::ctrlModifier; - if ((GetKeyState (VK_MENU) & 0x8000) != 0) - currentModifiers |= ModifierKeys::altModifier; + if ((GetKeyState (VK_MENU) & 0x8000) != 0) + currentModifiers |= ModifierKeys::altModifier; - if ((GetKeyState (VK_RMENU) & 0x8000) != 0) - currentModifiers &= ~(ModifierKeys::ctrlModifier | ModifierKeys::altModifier); + if ((GetKeyState (VK_RMENU) & 0x8000) != 0) + currentModifiers &= ~(ModifierKeys::ctrlModifier | ModifierKeys::altModifier); } void ModifierKeys::updateCurrentModifiers() throw() { - currentModifierFlags = currentModifiers; + currentModifierFlags = currentModifiers; } bool KeyPress::isKeyCurrentlyDown (const int keyCode) throw() { - SHORT k = (SHORT) keyCode; + SHORT k = (SHORT) keyCode; - if ((keyCode & extendedKeyModifier) == 0 - && (k >= (SHORT) T('a') && k <= (SHORT) T('z'))) - k += (SHORT) T('A') - (SHORT) T('a'); + if ((keyCode & extendedKeyModifier) == 0 + && (k >= (SHORT) T('a') && k <= (SHORT) T('z'))) + k += (SHORT) T('A') - (SHORT) T('a'); - const SHORT translatedValues[] = { (SHORT) ',', VK_OEM_COMMA, - (SHORT) '+', VK_OEM_PLUS, - (SHORT) '-', VK_OEM_MINUS, - (SHORT) '.', VK_OEM_PERIOD, - (SHORT) ';', VK_OEM_1, - (SHORT) ':', VK_OEM_1, - (SHORT) '/', VK_OEM_2, - (SHORT) '?', VK_OEM_2, - (SHORT) '[', VK_OEM_4, - (SHORT) ']', VK_OEM_6 }; + const SHORT translatedValues[] = { (SHORT) ',', VK_OEM_COMMA, + (SHORT) '+', VK_OEM_PLUS, + (SHORT) '-', VK_OEM_MINUS, + (SHORT) '.', VK_OEM_PERIOD, + (SHORT) ';', VK_OEM_1, + (SHORT) ':', VK_OEM_1, + (SHORT) '/', VK_OEM_2, + (SHORT) '?', VK_OEM_2, + (SHORT) '[', VK_OEM_4, + (SHORT) ']', VK_OEM_6 }; - for (int i = 0; i < numElementsInArray (translatedValues); i += 2) - if (k == translatedValues [i]) - k = translatedValues [i + 1]; + for (int i = 0; i < numElementsInArray (translatedValues); i += 2) + if (k == translatedValues [i]) + k = translatedValues [i + 1]; - return (GetKeyState (k) & 0x8000) != 0; + return (GetKeyState (k) & 0x8000) != 0; } const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() throw() { - updateKeyModifiers(); + updateKeyModifiers(); - currentModifiers &= ~ModifierKeys::allMouseButtonModifiers; + currentModifiers &= ~ModifierKeys::allMouseButtonModifiers; - if ((GetKeyState (VK_LBUTTON) & 0x8000) != 0) - currentModifiers |= ModifierKeys::leftButtonModifier; + if ((GetKeyState (VK_LBUTTON) & 0x8000) != 0) + currentModifiers |= ModifierKeys::leftButtonModifier; - if ((GetKeyState (VK_RBUTTON) & 0x8000) != 0) - currentModifiers |= ModifierKeys::rightButtonModifier; + if ((GetKeyState (VK_RBUTTON) & 0x8000) != 0) + currentModifiers |= ModifierKeys::rightButtonModifier; - if ((GetKeyState (VK_MBUTTON) & 0x8000) != 0) - currentModifiers |= ModifierKeys::middleButtonModifier; + if ((GetKeyState (VK_MBUTTON) & 0x8000) != 0) + currentModifiers |= ModifierKeys::middleButtonModifier; - return ModifierKeys (currentModifiers); + return ModifierKeys (currentModifiers); } static int64 getMouseEventTime() throw() { - static int64 eventTimeOffset = 0; - static DWORD lastMessageTime = 0; - const DWORD thisMessageTime = GetMessageTime(); + static int64 eventTimeOffset = 0; + static DWORD lastMessageTime = 0; + const DWORD thisMessageTime = GetMessageTime(); - if (thisMessageTime < lastMessageTime || lastMessageTime == 0) - { - lastMessageTime = thisMessageTime; - eventTimeOffset = Time::currentTimeMillis() - thisMessageTime; - } + if (thisMessageTime < lastMessageTime || lastMessageTime == 0) + { + lastMessageTime = thisMessageTime; + eventTimeOffset = Time::currentTimeMillis() - thisMessageTime; + } - return eventTimeOffset + thisMessageTime; + return eventTimeOffset + thisMessageTime; } static void* callFunctionIfNotLocked (MessageCallbackFunction* callback, void* userData) { - if (MessageManager::getInstance()->currentThreadHasLockedMessageManager()) - return callback (userData); - else - return MessageManager::getInstance()->callFunctionOnMessageThread (callback, userData); + if (MessageManager::getInstance()->currentThreadHasLockedMessageManager()) + return callback (userData); + else + return MessageManager::getInstance()->callFunctionOnMessageThread (callback, userData); } class Win32ComponentPeer : public ComponentPeer { public: - Win32ComponentPeer (Component* const component, - const int windowStyleFlags) - : ComponentPeer (component, windowStyleFlags), - dontRepaint (false), - fullScreen (false), - isDragging (false), - isMouseOver (false), - hasCreatedCaret (false), - currentWindowIcon (0), - taskBarIcon (0), - dropTarget (0) - { - callFunctionIfNotLocked (&createWindowCallback, (void*) this); - - setTitle (component->getName()); - - if ((windowStyleFlags & windowHasDropShadow) != 0 - && Desktop::canUseSemiTransparentWindows()) - { - shadower = component->getLookAndFeel().createDropShadowerForComponent (component); - - if (shadower != 0) - shadower->setOwner (component); - } - else - { - shadower = 0; - } - } - - ~Win32ComponentPeer() - { - setTaskBarIcon (0); - deleteAndZero (shadower); - - // do this before the next bit to avoid messages arriving for this window - // before it's destroyed - SetWindowLongPtr (hwnd, GWLP_USERDATA, 0); - - callFunctionIfNotLocked (&destroyWindowCallback, (void*) hwnd); - - if (currentWindowIcon != 0) - DestroyIcon (currentWindowIcon); - - if (dropTarget != 0) - { - dropTarget->Release(); - dropTarget = 0; - } - } - - void* getNativeHandle() const - { - return (void*) hwnd; - } - - void setVisible (bool shouldBeVisible) - { - ShowWindow (hwnd, shouldBeVisible ? SW_SHOWNA : SW_HIDE); - - if (shouldBeVisible) - InvalidateRect (hwnd, 0, 0); - else - lastPaintTime = 0; - } - - void setTitle (const String& title) - { - SetWindowText (hwnd, title); - } - - void setPosition (int x, int y) - { - offsetWithinParent (x, y); - SetWindowPos (hwnd, 0, - x - windowBorder.getLeft(), - y - windowBorder.getTop(), - 0, 0, - SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); - } - - void repaintNowIfTransparent() - { - if (isTransparent() && lastPaintTime > 0 && Time::getMillisecondCounter() > lastPaintTime + 30) - handlePaintMessage(); - } - - void updateBorderSize() - { - WINDOWINFO info; - info.cbSize = sizeof (info); - - if (GetWindowInfo (hwnd, &info)) - { - windowBorder = BorderSize (info.rcClient.top - info.rcWindow.top, - info.rcClient.left - info.rcWindow.left, - info.rcWindow.bottom - info.rcClient.bottom, - info.rcWindow.right - info.rcClient.right); - } - } - - void setSize (int w, int h) - { - SetWindowPos (hwnd, 0, 0, 0, - w + windowBorder.getLeftAndRight(), - h + windowBorder.getTopAndBottom(), - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); - - updateBorderSize(); - - repaintNowIfTransparent(); - } - - void setBounds (int x, int y, int w, int h, const bool isNowFullScreen) - { - fullScreen = isNowFullScreen; - offsetWithinParent (x, y); - - SetWindowPos (hwnd, 0, - x - windowBorder.getLeft(), - y - windowBorder.getTop(), - w + windowBorder.getLeftAndRight(), - h + windowBorder.getTopAndBottom(), - SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); - - updateBorderSize(); - - repaintNowIfTransparent(); - } - - void getBounds (int& x, int& y, int& w, int& h) const - { - RECT r; - GetWindowRect (hwnd, &r); - - x = r.left; - y = r.top; - w = r.right - x; - h = r.bottom - y; - - HWND parentH = GetParent (hwnd); - if (parentH != 0) - { - GetWindowRect (parentH, &r); - x -= r.left; - y -= r.top; - } - - x += windowBorder.getLeft(); - y += windowBorder.getTop(); - w -= windowBorder.getLeftAndRight(); - h -= windowBorder.getTopAndBottom(); - } - - int getScreenX() const - { - RECT r; - GetWindowRect (hwnd, &r); - return r.left + windowBorder.getLeft(); - } - - int getScreenY() const - { - RECT r; - GetWindowRect (hwnd, &r); - return r.top + windowBorder.getTop(); - } - - void relativePositionToGlobal (int& x, int& y) - { - RECT r; - GetWindowRect (hwnd, &r); - - x += r.left + windowBorder.getLeft(); - y += r.top + windowBorder.getTop(); - } - - void globalPositionToRelative (int& x, int& y) - { - RECT r; - GetWindowRect (hwnd, &r); - - x -= r.left + windowBorder.getLeft(); - y -= r.top + windowBorder.getTop(); - } - - void setMinimised (bool shouldBeMinimised) - { - if (shouldBeMinimised != isMinimised()) - ShowWindow (hwnd, shouldBeMinimised ? SW_MINIMIZE : SW_SHOWNORMAL); - } - - bool isMinimised() const - { - WINDOWPLACEMENT wp; - wp.length = sizeof (WINDOWPLACEMENT); - GetWindowPlacement (hwnd, &wp); - - return wp.showCmd == SW_SHOWMINIMIZED; - } - - void setFullScreen (bool shouldBeFullScreen) - { - setMinimised (false); - - if (fullScreen != shouldBeFullScreen) - { - fullScreen = shouldBeFullScreen; - const ComponentDeletionWatcher deletionChecker (component); - - if (! fullScreen) - { - const Rectangle boundsCopy (lastNonFullscreenBounds); - - if (hasTitleBar()) - ShowWindow (hwnd, SW_SHOWNORMAL); - - if (! boundsCopy.isEmpty()) - { - setBounds (boundsCopy.getX(), - boundsCopy.getY(), - boundsCopy.getWidth(), - boundsCopy.getHeight(), - false); - } - } - else - { - if (hasTitleBar()) - ShowWindow (hwnd, SW_SHOWMAXIMIZED); - else - SendMessageW (hwnd, WM_SETTINGCHANGE, 0, 0); - } - - if (! deletionChecker.hasBeenDeleted()) - handleMovedOrResized(); - } - } - - bool isFullScreen() const - { - if (! hasTitleBar()) - return fullScreen; - - WINDOWPLACEMENT wp; - wp.length = sizeof (wp); - GetWindowPlacement (hwnd, &wp); - - return wp.showCmd == SW_SHOWMAXIMIZED; - } - - bool contains (int x, int y, bool trueIfInAChildWindow) const - { - RECT r; - GetWindowRect (hwnd, &r); - - POINT p; - p.x = x + r.left + windowBorder.getLeft(); - p.y = y + r.top + windowBorder.getTop(); - - HWND w = WindowFromPoint (p); - - return w == hwnd || (trueIfInAChildWindow && (IsChild (hwnd, w) != 0)); - } - - const BorderSize getFrameSize() const - { - return windowBorder; - } - - bool setAlwaysOnTop (bool alwaysOnTop) - { - const bool oldDeactivate = shouldDeactivateTitleBar; - shouldDeactivateTitleBar = ((styleFlags & windowIsTemporary) == 0); - - SetWindowPos (hwnd, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, - 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); - - shouldDeactivateTitleBar = oldDeactivate; - - if (shadower != 0) - shadower->componentBroughtToFront (*component); - - return true; - } - - void toFront (bool makeActive) - { - setMinimised (false); - - const bool oldDeactivate = shouldDeactivateTitleBar; - shouldDeactivateTitleBar = ((styleFlags & windowIsTemporary) == 0); - - callFunctionIfNotLocked (makeActive ? &toFrontCallback1 - : &toFrontCallback2, - (void*) hwnd); - - shouldDeactivateTitleBar = oldDeactivate; - - if (! makeActive) - { - // in this case a broughttofront call won't have occured, so do it now.. - handleBroughtToFront(); - } - } - - void toBehind (ComponentPeer* other) - { - Win32ComponentPeer* const otherPeer = dynamic_cast (other); - - jassert (otherPeer != 0); // wrong type of window? - - if (otherPeer != 0) - { - setMinimised (false); - - // must be careful not to try to put a topmost window behind a normal one, or win32 - // promotes the normal one to be topmost! - if (getComponent()->isAlwaysOnTop() == otherPeer->getComponent()->isAlwaysOnTop()) - SetWindowPos (hwnd, otherPeer->hwnd, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); - else if (otherPeer->getComponent()->isAlwaysOnTop()) - SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); - } - } - - bool isFocused() const - { - return callFunctionIfNotLocked (&getFocusCallback, 0) == (void*) hwnd; - } - - void grabFocus() - { - const bool oldDeactivate = shouldDeactivateTitleBar; - shouldDeactivateTitleBar = ((styleFlags & windowIsTemporary) == 0); - - callFunctionIfNotLocked (&setFocusCallback, (void*) hwnd); - - shouldDeactivateTitleBar = oldDeactivate; - } - - void textInputRequired (int /*x*/, int /*y*/) - { - if (! hasCreatedCaret) - { - hasCreatedCaret = true; - CreateCaret (hwnd, (HBITMAP) 1, 0, 0); - } - - ShowCaret (hwnd); - SetCaretPos (0, 0); - } - - void repaint (int x, int y, int w, int h) - { - const RECT r = { x, y, x + w, y + h }; - InvalidateRect (hwnd, &r, FALSE); - } - - void performAnyPendingRepaintsNow() - { - MSG m; - if (component->isVisible() && PeekMessage (&m, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE)) - DispatchMessage (&m); - } - - static Win32ComponentPeer* getOwnerOfWindow (HWND h) throw() - { - if (h != 0 && GetWindowLongPtr (h, GWLP_USERDATA) == improbableWindowNumber) - return (Win32ComponentPeer*) (pointer_sized_int) GetWindowLongPtr (h, 8); - - return 0; - } - - void setTaskBarIcon (const Image* const image) - { - if (image != 0) - { - HICON hicon = createHICONFromImage (*image, TRUE, 0, 0); - - if (taskBarIcon == 0) - { - taskBarIcon = new NOTIFYICONDATA(); - taskBarIcon->cbSize = sizeof (NOTIFYICONDATA); - taskBarIcon->hWnd = (HWND) hwnd; - taskBarIcon->uID = (int) (pointer_sized_int) hwnd; - taskBarIcon->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; - taskBarIcon->uCallbackMessage = WM_TRAYNOTIFY; - taskBarIcon->hIcon = hicon; - taskBarIcon->szTip[0] = 0; - - Shell_NotifyIcon (NIM_ADD, taskBarIcon); - } - else - { - HICON oldIcon = taskBarIcon->hIcon; - - taskBarIcon->hIcon = hicon; - taskBarIcon->uFlags = NIF_ICON; - Shell_NotifyIcon (NIM_MODIFY, taskBarIcon); - - DestroyIcon (oldIcon); - } - - DestroyIcon (hicon); - } - else if (taskBarIcon != 0) - { - taskBarIcon->uFlags = 0; - Shell_NotifyIcon (NIM_DELETE, taskBarIcon); - DestroyIcon (taskBarIcon->hIcon); - deleteAndZero (taskBarIcon); - } - } - - void setTaskBarIconToolTip (const String& toolTip) const - { - if (taskBarIcon != 0) - { - taskBarIcon->uFlags = NIF_TIP; - toolTip.copyToBuffer (taskBarIcon->szTip, sizeof (taskBarIcon->szTip) - 1); - Shell_NotifyIcon (NIM_MODIFY, taskBarIcon); - } - } - - bool isInside (HWND h) const - { - return GetAncestor (hwnd, GA_ROOT) == h; - } - - juce_UseDebuggingNewOperator - - bool dontRepaint; + Win32ComponentPeer (Component* const component, + const int windowStyleFlags) + : ComponentPeer (component, windowStyleFlags), + dontRepaint (false), + fullScreen (false), + isDragging (false), + isMouseOver (false), + hasCreatedCaret (false), + currentWindowIcon (0), + taskBarIcon (0), + dropTarget (0) + { + callFunctionIfNotLocked (&createWindowCallback, (void*) this); + + setTitle (component->getName()); + + if ((windowStyleFlags & windowHasDropShadow) != 0 + && Desktop::canUseSemiTransparentWindows()) + { + shadower = component->getLookAndFeel().createDropShadowerForComponent (component); + + if (shadower != 0) + shadower->setOwner (component); + } + else + { + shadower = 0; + } + } + + ~Win32ComponentPeer() + { + setTaskBarIcon (0); + deleteAndZero (shadower); + + // do this before the next bit to avoid messages arriving for this window + // before it's destroyed + SetWindowLongPtr (hwnd, GWLP_USERDATA, 0); + + callFunctionIfNotLocked (&destroyWindowCallback, (void*) hwnd); + + if (currentWindowIcon != 0) + DestroyIcon (currentWindowIcon); + + if (dropTarget != 0) + { + dropTarget->Release(); + dropTarget = 0; + } + } + + void* getNativeHandle() const + { + return (void*) hwnd; + } + + void setVisible (bool shouldBeVisible) + { + ShowWindow (hwnd, shouldBeVisible ? SW_SHOWNA : SW_HIDE); + + if (shouldBeVisible) + InvalidateRect (hwnd, 0, 0); + else + lastPaintTime = 0; + } + + void setTitle (const String& title) + { + SetWindowText (hwnd, title); + } + + void setPosition (int x, int y) + { + offsetWithinParent (x, y); + SetWindowPos (hwnd, 0, + x - windowBorder.getLeft(), + y - windowBorder.getTop(), + 0, 0, + SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); + } + + void repaintNowIfTransparent() + { + if (isTransparent() && lastPaintTime > 0 && Time::getMillisecondCounter() > lastPaintTime + 30) + handlePaintMessage(); + } + + void updateBorderSize() + { + WINDOWINFO info; + info.cbSize = sizeof (info); + + if (GetWindowInfo (hwnd, &info)) + { + windowBorder = BorderSize (info.rcClient.top - info.rcWindow.top, + info.rcClient.left - info.rcWindow.left, + info.rcWindow.bottom - info.rcClient.bottom, + info.rcWindow.right - info.rcClient.right); + } + } + + void setSize (int w, int h) + { + SetWindowPos (hwnd, 0, 0, 0, + w + windowBorder.getLeftAndRight(), + h + windowBorder.getTopAndBottom(), + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); + + updateBorderSize(); + + repaintNowIfTransparent(); + } + + void setBounds (int x, int y, int w, int h, const bool isNowFullScreen) + { + fullScreen = isNowFullScreen; + offsetWithinParent (x, y); + + SetWindowPos (hwnd, 0, + x - windowBorder.getLeft(), + y - windowBorder.getTop(), + w + windowBorder.getLeftAndRight(), + h + windowBorder.getTopAndBottom(), + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); + + updateBorderSize(); + + repaintNowIfTransparent(); + } + + void getBounds (int& x, int& y, int& w, int& h) const + { + RECT r; + GetWindowRect (hwnd, &r); + + x = r.left; + y = r.top; + w = r.right - x; + h = r.bottom - y; + + HWND parentH = GetParent (hwnd); + if (parentH != 0) + { + GetWindowRect (parentH, &r); + x -= r.left; + y -= r.top; + } + + x += windowBorder.getLeft(); + y += windowBorder.getTop(); + w -= windowBorder.getLeftAndRight(); + h -= windowBorder.getTopAndBottom(); + } + + int getScreenX() const + { + RECT r; + GetWindowRect (hwnd, &r); + return r.left + windowBorder.getLeft(); + } + + int getScreenY() const + { + RECT r; + GetWindowRect (hwnd, &r); + return r.top + windowBorder.getTop(); + } + + void relativePositionToGlobal (int& x, int& y) + { + RECT r; + GetWindowRect (hwnd, &r); + + x += r.left + windowBorder.getLeft(); + y += r.top + windowBorder.getTop(); + } + + void globalPositionToRelative (int& x, int& y) + { + RECT r; + GetWindowRect (hwnd, &r); + + x -= r.left + windowBorder.getLeft(); + y -= r.top + windowBorder.getTop(); + } + + void setMinimised (bool shouldBeMinimised) + { + if (shouldBeMinimised != isMinimised()) + ShowWindow (hwnd, shouldBeMinimised ? SW_MINIMIZE : SW_SHOWNORMAL); + } + + bool isMinimised() const + { + WINDOWPLACEMENT wp; + wp.length = sizeof (WINDOWPLACEMENT); + GetWindowPlacement (hwnd, &wp); + + return wp.showCmd == SW_SHOWMINIMIZED; + } + + void setFullScreen (bool shouldBeFullScreen) + { + setMinimised (false); + + if (fullScreen != shouldBeFullScreen) + { + fullScreen = shouldBeFullScreen; + const ComponentDeletionWatcher deletionChecker (component); + + if (! fullScreen) + { + const Rectangle boundsCopy (lastNonFullscreenBounds); + + if (hasTitleBar()) + ShowWindow (hwnd, SW_SHOWNORMAL); + + if (! boundsCopy.isEmpty()) + { + setBounds (boundsCopy.getX(), + boundsCopy.getY(), + boundsCopy.getWidth(), + boundsCopy.getHeight(), + false); + } + } + else + { + if (hasTitleBar()) + ShowWindow (hwnd, SW_SHOWMAXIMIZED); + else + SendMessageW (hwnd, WM_SETTINGCHANGE, 0, 0); + } + + if (! deletionChecker.hasBeenDeleted()) + handleMovedOrResized(); + } + } + + bool isFullScreen() const + { + if (! hasTitleBar()) + return fullScreen; + + WINDOWPLACEMENT wp; + wp.length = sizeof (wp); + GetWindowPlacement (hwnd, &wp); + + return wp.showCmd == SW_SHOWMAXIMIZED; + } + + bool contains (int x, int y, bool trueIfInAChildWindow) const + { + RECT r; + GetWindowRect (hwnd, &r); + + POINT p; + p.x = x + r.left + windowBorder.getLeft(); + p.y = y + r.top + windowBorder.getTop(); + + HWND w = WindowFromPoint (p); + + return w == hwnd || (trueIfInAChildWindow && (IsChild (hwnd, w) != 0)); + } + + const BorderSize getFrameSize() const + { + return windowBorder; + } + + bool setAlwaysOnTop (bool alwaysOnTop) + { + const bool oldDeactivate = shouldDeactivateTitleBar; + shouldDeactivateTitleBar = ((styleFlags & windowIsTemporary) == 0); + + SetWindowPos (hwnd, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, + 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + + shouldDeactivateTitleBar = oldDeactivate; + + if (shadower != 0) + shadower->componentBroughtToFront (*component); + + return true; + } + + void toFront (bool makeActive) + { + setMinimised (false); + + const bool oldDeactivate = shouldDeactivateTitleBar; + shouldDeactivateTitleBar = ((styleFlags & windowIsTemporary) == 0); + + callFunctionIfNotLocked (makeActive ? &toFrontCallback1 + : &toFrontCallback2, + (void*) hwnd); + + shouldDeactivateTitleBar = oldDeactivate; + + if (! makeActive) + { + // in this case a broughttofront call won't have occured, so do it now.. + handleBroughtToFront(); + } + } + + void toBehind (ComponentPeer* other) + { + Win32ComponentPeer* const otherPeer = dynamic_cast (other); + + jassert (otherPeer != 0); // wrong type of window? + + if (otherPeer != 0) + { + setMinimised (false); + + // must be careful not to try to put a topmost window behind a normal one, or win32 + // promotes the normal one to be topmost! + if (getComponent()->isAlwaysOnTop() == otherPeer->getComponent()->isAlwaysOnTop()) + SetWindowPos (hwnd, otherPeer->hwnd, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + else if (otherPeer->getComponent()->isAlwaysOnTop()) + SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + } + } + + bool isFocused() const + { + return callFunctionIfNotLocked (&getFocusCallback, 0) == (void*) hwnd; + } + + void grabFocus() + { + const bool oldDeactivate = shouldDeactivateTitleBar; + shouldDeactivateTitleBar = ((styleFlags & windowIsTemporary) == 0); + + callFunctionIfNotLocked (&setFocusCallback, (void*) hwnd); + + shouldDeactivateTitleBar = oldDeactivate; + } + + void textInputRequired (int /*x*/, int /*y*/) + { + if (! hasCreatedCaret) + { + hasCreatedCaret = true; + CreateCaret (hwnd, (HBITMAP) 1, 0, 0); + } + + ShowCaret (hwnd); + SetCaretPos (0, 0); + } + + void repaint (int x, int y, int w, int h) + { + const RECT r = { x, y, x + w, y + h }; + InvalidateRect (hwnd, &r, FALSE); + } + + void performAnyPendingRepaintsNow() + { + MSG m; + if (component->isVisible() && PeekMessage (&m, hwnd, WM_PAINT, WM_PAINT, PM_REMOVE)) + DispatchMessage (&m); + } + + static Win32ComponentPeer* getOwnerOfWindow (HWND h) throw() + { + if (h != 0 && GetWindowLongPtr (h, GWLP_USERDATA) == improbableWindowNumber) + return (Win32ComponentPeer*) (pointer_sized_int) GetWindowLongPtr (h, 8); + + return 0; + } + + void setTaskBarIcon (const Image* const image) + { + if (image != 0) + { + HICON hicon = createHICONFromImage (*image, TRUE, 0, 0); + + if (taskBarIcon == 0) + { + taskBarIcon = new NOTIFYICONDATA(); + taskBarIcon->cbSize = sizeof (NOTIFYICONDATA); + taskBarIcon->hWnd = (HWND) hwnd; + taskBarIcon->uID = (int) (pointer_sized_int) hwnd; + taskBarIcon->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; + taskBarIcon->uCallbackMessage = WM_TRAYNOTIFY; + taskBarIcon->hIcon = hicon; + taskBarIcon->szTip[0] = 0; + + Shell_NotifyIcon (NIM_ADD, taskBarIcon); + } + else + { + HICON oldIcon = taskBarIcon->hIcon; + + taskBarIcon->hIcon = hicon; + taskBarIcon->uFlags = NIF_ICON; + Shell_NotifyIcon (NIM_MODIFY, taskBarIcon); + + DestroyIcon (oldIcon); + } + + DestroyIcon (hicon); + } + else if (taskBarIcon != 0) + { + taskBarIcon->uFlags = 0; + Shell_NotifyIcon (NIM_DELETE, taskBarIcon); + DestroyIcon (taskBarIcon->hIcon); + deleteAndZero (taskBarIcon); + } + } + + void setTaskBarIconToolTip (const String& toolTip) const + { + if (taskBarIcon != 0) + { + taskBarIcon->uFlags = NIF_TIP; + toolTip.copyToBuffer (taskBarIcon->szTip, sizeof (taskBarIcon->szTip) - 1); + Shell_NotifyIcon (NIM_MODIFY, taskBarIcon); + } + } + + bool isInside (HWND h) const + { + return GetAncestor (hwnd, GA_ROOT) == h; + } + + juce_UseDebuggingNewOperator + + bool dontRepaint; private: - HWND hwnd; - DropShadower* shadower; - bool fullScreen, isDragging, isMouseOver, hasCreatedCaret; - BorderSize windowBorder; - HICON currentWindowIcon; - NOTIFYICONDATA* taskBarIcon; - IDropTarget* dropTarget; + HWND hwnd; + DropShadower* shadower; + bool fullScreen, isDragging, isMouseOver, hasCreatedCaret; + BorderSize windowBorder; + HICON currentWindowIcon; + NOTIFYICONDATA* taskBarIcon; + IDropTarget* dropTarget; - class TemporaryImage : public Timer - { - public: + class TemporaryImage : public Timer + { + public: - TemporaryImage() - : image (0) - { - } + TemporaryImage() + : image (0) + { + } - ~TemporaryImage() - { - delete image; - } + ~TemporaryImage() + { + delete image; + } - WindowsBitmapImage* getImage (const bool transparent, const int w, const int h) throw() - { - const Image::PixelFormat format = transparent ? Image::ARGB : Image::RGB; + WindowsBitmapImage* getImage (const bool transparent, const int w, const int h) throw() + { + const Image::PixelFormat format = transparent ? Image::ARGB : Image::RGB; - if (image == 0 || image->getWidth() < w || image->getHeight() < h || image->getFormat() != format) - { - delete image; - image = new WindowsBitmapImage (format, (w + 31) & ~31, (h + 31) & ~31, false); - } + if (image == 0 || image->getWidth() < w || image->getHeight() < h || image->getFormat() != format) + { + delete image; + image = new WindowsBitmapImage (format, (w + 31) & ~31, (h + 31) & ~31, false); + } - startTimer (3000); - return image; - } + startTimer (3000); + return image; + } - void timerCallback() - { - stopTimer(); - deleteAndZero (image); - } + void timerCallback() + { + stopTimer(); + deleteAndZero (image); + } - private: - WindowsBitmapImage* image; + private: + WindowsBitmapImage* image; - TemporaryImage (const TemporaryImage&); - const TemporaryImage& operator= (const TemporaryImage&); - }; + TemporaryImage (const TemporaryImage&); + const TemporaryImage& operator= (const TemporaryImage&); + }; - TemporaryImage offscreenImageGenerator; + TemporaryImage offscreenImageGenerator; - class WindowClassHolder : public DeletedAtShutdown - { - public: - WindowClassHolder() - : windowClassName ("JUCE_") - { - // this name has to be different for each app/dll instance because otherwise - // poor old Win32 can get a bit confused (even despite it not being a process-global - // window class). - windowClassName << (int) (Time::currentTimeMillis() & 0x7fffffff); + class WindowClassHolder : public DeletedAtShutdown + { + public: + WindowClassHolder() + : windowClassName ("JUCE_") + { + // this name has to be different for each app/dll instance because otherwise + // poor old Win32 can get a bit confused (even despite it not being a process-global + // window class). + windowClassName << (int) (Time::currentTimeMillis() & 0x7fffffff); - HINSTANCE moduleHandle = (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(); + HINSTANCE moduleHandle = (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(); - TCHAR moduleFile [1024]; - moduleFile[0] = 0; - GetModuleFileName (moduleHandle, moduleFile, 1024); - WORD iconNum = 0; + TCHAR moduleFile [1024]; + moduleFile[0] = 0; + GetModuleFileName (moduleHandle, moduleFile, 1024); + WORD iconNum = 0; - WNDCLASSEX wcex; - wcex.cbSize = sizeof (wcex); - wcex.style = CS_OWNDC; - wcex.lpfnWndProc = (WNDPROC) windowProc; - wcex.lpszClassName = windowClassName; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 32; - wcex.hInstance = moduleHandle; - wcex.hIcon = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum); - iconNum = 1; - wcex.hIconSm = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum); - wcex.hCursor = 0; - wcex.hbrBackground = 0; - wcex.lpszMenuName = 0; + WNDCLASSEX wcex; + wcex.cbSize = sizeof (wcex); + wcex.style = CS_OWNDC; + wcex.lpfnWndProc = (WNDPROC) windowProc; + wcex.lpszClassName = windowClassName; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 32; + wcex.hInstance = moduleHandle; + wcex.hIcon = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum); + iconNum = 1; + wcex.hIconSm = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum); + wcex.hCursor = 0; + wcex.hbrBackground = 0; + wcex.lpszMenuName = 0; - RegisterClassEx (&wcex); - } + RegisterClassEx (&wcex); + } - ~WindowClassHolder() - { - if (ComponentPeer::getNumPeers() == 0) - UnregisterClass (windowClassName, (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle()); + ~WindowClassHolder() + { + if (ComponentPeer::getNumPeers() == 0) + UnregisterClass (windowClassName, (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle()); - clearSingletonInstance(); - } + clearSingletonInstance(); + } - String windowClassName; + String windowClassName; - juce_DeclareSingleton_SingleThreaded_Minimal (WindowClassHolder); - }; + juce_DeclareSingleton_SingleThreaded_Minimal (WindowClassHolder); + }; - static void* createWindowCallback (void* userData) - { - ((Win32ComponentPeer*) userData)->createWindow(); - return 0; - } + static void* createWindowCallback (void* userData) + { + ((Win32ComponentPeer*) userData)->createWindow(); + return 0; + } - void createWindow() - { - DWORD exstyle = WS_EX_ACCEPTFILES; - DWORD type = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + void createWindow() + { + DWORD exstyle = WS_EX_ACCEPTFILES; + DWORD type = WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - if (hasTitleBar()) - { - type |= WS_OVERLAPPED; - exstyle |= WS_EX_APPWINDOW; + if (hasTitleBar()) + { + type |= WS_OVERLAPPED; + exstyle |= WS_EX_APPWINDOW; - if ((styleFlags & windowHasCloseButton) != 0) - { - type |= WS_SYSMENU; - } - else - { - // annoyingly, windows won't let you have a min/max button without a close button - jassert ((styleFlags & (windowHasMinimiseButton | windowHasMaximiseButton)) == 0); - } + if ((styleFlags & windowHasCloseButton) != 0) + { + type |= WS_SYSMENU; + } + else + { + // annoyingly, windows won't let you have a min/max button without a close button + jassert ((styleFlags & (windowHasMinimiseButton | windowHasMaximiseButton)) == 0); + } - if ((styleFlags & windowIsResizable) != 0) - type |= WS_THICKFRAME; - } - else - { - type |= WS_POPUP | WS_SYSMENU; + if ((styleFlags & windowIsResizable) != 0) + type |= WS_THICKFRAME; + } + else + { + type |= WS_POPUP | WS_SYSMENU; - if ((styleFlags & windowAppearsOnTaskbar) == 0) - exstyle |= WS_EX_TOOLWINDOW; - else - exstyle |= WS_EX_APPWINDOW; - } + if ((styleFlags & windowAppearsOnTaskbar) == 0) + exstyle |= WS_EX_TOOLWINDOW; + else + exstyle |= WS_EX_APPWINDOW; + } - if ((styleFlags & windowHasMinimiseButton) != 0) - type |= WS_MINIMIZEBOX; + if ((styleFlags & windowHasMinimiseButton) != 0) + type |= WS_MINIMIZEBOX; - if ((styleFlags & windowHasMaximiseButton) != 0) - type |= WS_MAXIMIZEBOX; + if ((styleFlags & windowHasMaximiseButton) != 0) + type |= WS_MAXIMIZEBOX; - if ((styleFlags & windowIgnoresMouseClicks) != 0) - exstyle |= WS_EX_TRANSPARENT; + if ((styleFlags & windowIgnoresMouseClicks) != 0) + exstyle |= WS_EX_TRANSPARENT; - if ((styleFlags & windowIsSemiTransparent) != 0 - && Desktop::canUseSemiTransparentWindows()) - exstyle |= WS_EX_LAYERED; + if ((styleFlags & windowIsSemiTransparent) != 0 + && Desktop::canUseSemiTransparentWindows()) + exstyle |= WS_EX_LAYERED; - hwnd = CreateWindowEx (exstyle, WindowClassHolder::getInstance()->windowClassName, L"", type, 0, 0, 0, 0, 0, 0, 0, 0); + hwnd = CreateWindowEx (exstyle, WindowClassHolder::getInstance()->windowClassName, L"", type, 0, 0, 0, 0, 0, 0, 0, 0); - if (hwnd != 0) - { - SetWindowLongPtr (hwnd, 0, 0); - SetWindowLongPtr (hwnd, 8, (LONG_PTR) this); - SetWindowLongPtr (hwnd, GWLP_USERDATA, improbableWindowNumber); + if (hwnd != 0) + { + SetWindowLongPtr (hwnd, 0, 0); + SetWindowLongPtr (hwnd, 8, (LONG_PTR) this); + SetWindowLongPtr (hwnd, GWLP_USERDATA, improbableWindowNumber); - if (dropTarget == 0) - dropTarget = new JuceDropTarget (this); + if (dropTarget == 0) + dropTarget = new JuceDropTarget (this); - RegisterDragDrop (hwnd, dropTarget); + RegisterDragDrop (hwnd, dropTarget); - updateBorderSize(); + updateBorderSize(); - // Calling this function here is (for some reason) necessary to make Windows - // correctly enable the menu items that we specify in the wm_initmenu message. - GetSystemMenu (hwnd, false); - } - else - { - jassertfalse - } - } + // Calling this function here is (for some reason) necessary to make Windows + // correctly enable the menu items that we specify in the wm_initmenu message. + GetSystemMenu (hwnd, false); + } + else + { + jassertfalse + } + } - static void* destroyWindowCallback (void* handle) - { - RevokeDragDrop ((HWND) handle); - DestroyWindow ((HWND) handle); - return 0; - } + static void* destroyWindowCallback (void* handle) + { + RevokeDragDrop ((HWND) handle); + DestroyWindow ((HWND) handle); + return 0; + } - static void* toFrontCallback1 (void* h) - { - SetForegroundWindow ((HWND) h); - return 0; - } + static void* toFrontCallback1 (void* h) + { + SetForegroundWindow ((HWND) h); + return 0; + } - static void* toFrontCallback2 (void* h) - { - SetWindowPos ((HWND) h, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); - return 0; - } + static void* toFrontCallback2 (void* h) + { + SetWindowPos ((HWND) h, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING); + return 0; + } - static void* setFocusCallback (void* h) - { - SetFocus ((HWND) h); - return 0; - } + static void* setFocusCallback (void* h) + { + SetFocus ((HWND) h); + return 0; + } - static void* getFocusCallback (void*) - { - return (void*) GetFocus(); - } + static void* getFocusCallback (void*) + { + return (void*) GetFocus(); + } - void offsetWithinParent (int& x, int& y) const - { - if (isTransparent()) - { - HWND parentHwnd = GetParent (hwnd); + void offsetWithinParent (int& x, int& y) const + { + if (isTransparent()) + { + HWND parentHwnd = GetParent (hwnd); - if (parentHwnd != 0) - { - RECT parentRect; - GetWindowRect (parentHwnd, &parentRect); - x += parentRect.left; - y += parentRect.top; - } - } - } + if (parentHwnd != 0) + { + RECT parentRect; + GetWindowRect (parentHwnd, &parentRect); + x += parentRect.left; + y += parentRect.top; + } + } + } - bool isTransparent() const - { - return (GetWindowLong (hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) != 0; - } + bool isTransparent() const + { + return (GetWindowLong (hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) != 0; + } - inline bool hasTitleBar() const throw() { return (styleFlags & windowHasTitleBar) != 0; } + inline bool hasTitleBar() const throw() { return (styleFlags & windowHasTitleBar) != 0; } - void setIcon (const Image& newIcon) - { - HICON hicon = createHICONFromImage (newIcon, TRUE, 0, 0); + void setIcon (const Image& newIcon) + { + HICON hicon = createHICONFromImage (newIcon, TRUE, 0, 0); - if (hicon != 0) - { - SendMessage (hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon); - SendMessage (hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon); + if (hicon != 0) + { + SendMessage (hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon); + SendMessage (hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon); - if (currentWindowIcon != 0) - DestroyIcon (currentWindowIcon); + if (currentWindowIcon != 0) + DestroyIcon (currentWindowIcon); - currentWindowIcon = hicon; - } - } + currentWindowIcon = hicon; + } + } - void handlePaintMessage() - { + void handlePaintMessage() + { #if DEBUG_REPAINT_TIMES - const double paintStart = Time::getMillisecondCounterHiRes(); + const double paintStart = Time::getMillisecondCounterHiRes(); #endif - HRGN rgn = CreateRectRgn (0, 0, 0, 0); - const int regionType = GetUpdateRgn (hwnd, rgn, false); + HRGN rgn = CreateRectRgn (0, 0, 0, 0); + const int regionType = GetUpdateRgn (hwnd, rgn, false); - PAINTSTRUCT paintStruct; - HDC dc = BeginPaint (hwnd, &paintStruct); // Note this can immediately generate a WM_NCPAINT - // message and become re-entrant, but that's OK + PAINTSTRUCT paintStruct; + HDC dc = BeginPaint (hwnd, &paintStruct); // Note this can immediately generate a WM_NCPAINT + // message and become re-entrant, but that's OK - // if something in a paint handler calls, e.g. a message box, this can become reentrant and - // corrupt the image it's using to paint into, so do a check here. - static bool reentrant = false; - if (reentrant) - { - DeleteObject (rgn); - EndPaint (hwnd, &paintStruct); - return; - } + // if something in a paint handler calls, e.g. a message box, this can become reentrant and + // corrupt the image it's using to paint into, so do a check here. + static bool reentrant = false; + if (reentrant) + { + DeleteObject (rgn); + EndPaint (hwnd, &paintStruct); + return; + } - reentrant = true; + reentrant = true; - // this is the rectangle to update.. - int x = paintStruct.rcPaint.left; - int y = paintStruct.rcPaint.top; - int w = paintStruct.rcPaint.right - x; - int h = paintStruct.rcPaint.bottom - y; + // this is the rectangle to update.. + int x = paintStruct.rcPaint.left; + int y = paintStruct.rcPaint.top; + int w = paintStruct.rcPaint.right - x; + int h = paintStruct.rcPaint.bottom - y; - const bool transparent = isTransparent(); + const bool transparent = isTransparent(); - if (transparent) - { - // it's not possible to have a transparent window with a title bar at the moment! - jassert (! hasTitleBar()); + if (transparent) + { + // it's not possible to have a transparent window with a title bar at the moment! + jassert (! hasTitleBar()); - RECT r; - GetWindowRect (hwnd, &r); - x = y = 0; - w = r.right - r.left; - h = r.bottom - r.top; - } + RECT r; + GetWindowRect (hwnd, &r); + x = y = 0; + w = r.right - r.left; + h = r.bottom - r.top; + } - if (w > 0 && h > 0) - { - clearMaskedRegion(); + if (w > 0 && h > 0) + { + clearMaskedRegion(); - WindowsBitmapImage* const offscreenImage = offscreenImageGenerator.getImage (transparent, w, h); + WindowsBitmapImage* const offscreenImage = offscreenImageGenerator.getImage (transparent, w, h); - RectangleList contextClip; + RectangleList contextClip; - bool needToPaintAll = true; + bool needToPaintAll = true; - if (regionType == COMPLEXREGION && ! transparent) - { - HRGN clipRgn = CreateRectRgnIndirect (&paintStruct.rcPaint); - CombineRgn (rgn, rgn, clipRgn, RGN_AND); - DeleteObject (clipRgn); + if (regionType == COMPLEXREGION && ! transparent) + { + HRGN clipRgn = CreateRectRgnIndirect (&paintStruct.rcPaint); + CombineRgn (rgn, rgn, clipRgn, RGN_AND); + DeleteObject (clipRgn); - char rgnData [8192]; - const DWORD res = GetRegionData (rgn, sizeof (rgnData), (RGNDATA*) rgnData); + char rgnData [8192]; + const DWORD res = GetRegionData (rgn, sizeof (rgnData), (RGNDATA*) rgnData); - if (res > 0 && res <= sizeof (rgnData)) - { - const RGNDATAHEADER* const hdr = &(((const RGNDATA*) rgnData)->rdh); + if (res > 0 && res <= sizeof (rgnData)) + { + const RGNDATAHEADER* const hdr = &(((const RGNDATA*) rgnData)->rdh); - if (hdr->iType == RDH_RECTANGLES - && hdr->rcBound.right - hdr->rcBound.left >= w - && hdr->rcBound.bottom - hdr->rcBound.top >= h) - { - needToPaintAll = false; + if (hdr->iType == RDH_RECTANGLES + && hdr->rcBound.right - hdr->rcBound.left >= w + && hdr->rcBound.bottom - hdr->rcBound.top >= h) + { + needToPaintAll = false; - const RECT* rects = (const RECT*) (rgnData + sizeof (RGNDATAHEADER)); - int num = ((RGNDATA*) rgnData)->rdh.nCount; + const RECT* rects = (const RECT*) (rgnData + sizeof (RGNDATAHEADER)); + int num = ((RGNDATA*) rgnData)->rdh.nCount; - while (--num >= 0) - { - // (need to move this one pixel to the left because of a win32 bug) - const int cx = jmax (x, rects->left - 1); - const int cy = rects->top; - const int cw = rects->right - cx; - const int ch = rects->bottom - rects->top; + while (--num >= 0) + { + // (need to move this one pixel to the left because of a win32 bug) + const int cx = jmax (x, (int) rects->left - 1); + const int cy = rects->top; + const int cw = rects->right - cx; + const int ch = rects->bottom - rects->top; - if (cx + cw - x <= w && cy + ch - y <= h) - { - contextClip.addWithoutMerging (Rectangle (cx - x, cy - y, cw, ch)); - } - else - { - needToPaintAll = true; - break; - } + if (cx + cw - x <= w && cy + ch - y <= h) + { + contextClip.addWithoutMerging (Rectangle (cx - x, cy - y, cw, ch)); + } + else + { + needToPaintAll = true; + break; + } - ++rects; - } - } - } - } + ++rects; + } + } + } + } - if (needToPaintAll) - { - contextClip.clear(); - contextClip.addWithoutMerging (Rectangle (0, 0, w, h)); - } + if (needToPaintAll) + { + contextClip.clear(); + contextClip.addWithoutMerging (Rectangle (0, 0, w, h)); + } - if (transparent) - { - RectangleList::Iterator i (contextClip); + if (transparent) + { + RectangleList::Iterator i (contextClip); - while (i.next()) - { - const Rectangle& r = *i.getRectangle(); - offscreenImage->clear (r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - } + while (i.next()) + { + const Rectangle& r = *i.getRectangle(); + offscreenImage->clear (r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + } - // if the component's not opaque, this won't draw properly unless the platform can support this - jassert (Desktop::canUseSemiTransparentWindows() || component->isOpaque()); + // if the component's not opaque, this won't draw properly unless the platform can support this + jassert (Desktop::canUseSemiTransparentWindows() || component->isOpaque()); - updateCurrentModifiers(); + updateCurrentModifiers(); - LowLevelGraphicsSoftwareRenderer context (*offscreenImage); - context.clipToRectangleList (contextClip); - context.setOrigin (-x, -y); + LowLevelGraphicsSoftwareRenderer context (*offscreenImage); + context.clipToRectangleList (contextClip); + context.setOrigin (-x, -y); - handlePaint (context); + handlePaint (context); - if (! dontRepaint) - offscreenImage->blitToWindow (hwnd, dc, transparent, x, y, maskedRegion); - } + if (! dontRepaint) + offscreenImage->blitToWindow (hwnd, dc, transparent, x, y, maskedRegion); + } - DeleteObject (rgn); - EndPaint (hwnd, &paintStruct); - reentrant = false; + DeleteObject (rgn); + EndPaint (hwnd, &paintStruct); + reentrant = false; #ifndef JUCE_GCC //xxx should add this fn for gcc.. - _fpreset(); // because some graphics cards can unmask FP exceptions + _fpreset(); // because some graphics cards can unmask FP exceptions #endif - lastPaintTime = Time::getMillisecondCounter(); + lastPaintTime = Time::getMillisecondCounter(); #if DEBUG_REPAINT_TIMES - const double elapsed = Time::getMillisecondCounterHiRes() - paintStart; - Logger::outputDebugString (T("repaint time: ") + String (elapsed, 2)); + const double elapsed = Time::getMillisecondCounterHiRes() - paintStart; + Logger::outputDebugString (T("repaint time: ") + String (elapsed, 2)); #endif - } - - void doMouseMove (const int x, const int y) - { - static uint32 lastMouseTime = 0; - // this can be set to throttle the mouse-messages to less than a - // certain number per second, as things can get unresponsive - // if each drag or move callback has to do a lot of work. - const int maxMouseMovesPerSecond = 60; - - const int64 mouseEventTime = getMouseEventTime(); - - if (! isMouseOver) - { - isMouseOver = true; - - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof (tme); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hwnd; - tme.dwHoverTime = 0; - - if (! TrackMouseEvent (&tme)) - { - jassertfalse; - } - - updateKeyModifiers(); - handleMouseEnter (x, y, mouseEventTime); - } - else if (! isDragging) - { - if (((unsigned int) x) < (unsigned int) component->getWidth() - && ((unsigned int) y) < (unsigned int) component->getHeight()) - { - RECT r; - GetWindowRect (hwnd, &r); - - POINT p; - p.x = x + r.left + windowBorder.getLeft(); - p.y = y + r.top + windowBorder.getTop(); - - if (WindowFromPoint (p) == hwnd) - { - const uint32 now = Time::getMillisecondCounter(); - - if (now > lastMouseTime + 1000 / maxMouseMovesPerSecond) - { - lastMouseTime = now; - handleMouseMove (x, y, mouseEventTime); - } - } - } - } - else - { - const uint32 now = Time::getMillisecondCounter(); - - if (now > lastMouseTime + 1000 / maxMouseMovesPerSecond) - { - lastMouseTime = now; - handleMouseDrag (x, y, mouseEventTime); - } - } - } - - void doMouseDown (const int x, const int y, const WPARAM wParam) - { - if (GetCapture() != hwnd) - SetCapture (hwnd); - - doMouseMove (x, y); - - currentModifiers &= ~ModifierKeys::allMouseButtonModifiers; - - if ((wParam & MK_LBUTTON) != 0) - currentModifiers |= ModifierKeys::leftButtonModifier; - - if ((wParam & MK_RBUTTON) != 0) - currentModifiers |= ModifierKeys::rightButtonModifier; - - if ((wParam & MK_MBUTTON) != 0) - currentModifiers |= ModifierKeys::middleButtonModifier; - - updateKeyModifiers(); - isDragging = true; - - handleMouseDown (x, y, getMouseEventTime()); - } - - void doMouseUp (const int x, const int y, const WPARAM wParam) - { - int numButtons = 0; - - if ((wParam & MK_LBUTTON) != 0) - ++numButtons; - - if ((wParam & MK_RBUTTON) != 0) - ++numButtons; - - if ((wParam & MK_MBUTTON) != 0) - ++numButtons; - - const int oldModifiers = currentModifiers; - - // update the currentmodifiers only after the callback, so the callback - // knows which button was released. - currentModifiers &= ~ModifierKeys::allMouseButtonModifiers; - - if ((wParam & MK_LBUTTON) != 0) - currentModifiers |= ModifierKeys::leftButtonModifier; - - if ((wParam & MK_RBUTTON) != 0) - currentModifiers |= ModifierKeys::rightButtonModifier; - - if ((wParam & MK_MBUTTON) != 0) - currentModifiers |= ModifierKeys::middleButtonModifier; - - updateKeyModifiers(); - isDragging = false; - - // release the mouse capture if the user's not still got a button down - if (numButtons == 0 && hwnd == GetCapture()) - ReleaseCapture(); - - handleMouseUp (oldModifiers, x, y, getMouseEventTime()); - } - - void doCaptureChanged() - { - if (isDragging) - { - RECT wr; - GetWindowRect (hwnd, &wr); - - const DWORD mp = GetMessagePos(); - - doMouseUp (GET_X_LPARAM (mp) - wr.left - windowBorder.getLeft(), - GET_Y_LPARAM (mp) - wr.top - windowBorder.getTop(), - (WPARAM) getMouseEventTime()); - } - } - - void doMouseExit() - { - if (isMouseOver) - { - isMouseOver = false; - RECT wr; - GetWindowRect (hwnd, &wr); - - const DWORD mp = GetMessagePos(); - - handleMouseExit (GET_X_LPARAM (mp) - wr.left - windowBorder.getLeft(), - GET_Y_LPARAM (mp) - wr.top - windowBorder.getTop(), - getMouseEventTime()); - } - } - - void doMouseWheel (const WPARAM wParam, const bool isVertical) - { - updateKeyModifiers(); - - const int amount = jlimit (-1000, 1000, (int) (0.75f * (short) HIWORD (wParam))); - - handleMouseWheel (isVertical ? 0 : amount, - isVertical ? amount : 0, - getMouseEventTime()); - } - - void sendModifierKeyChangeIfNeeded() - { - if (modifiersAtLastCallback != currentModifiers) - { - modifiersAtLastCallback = currentModifiers; - handleModifierKeysChange(); - } - } - - bool doKeyUp (const WPARAM key) - { - updateKeyModifiers(); - - switch (key) - { - case VK_SHIFT: - case VK_CONTROL: - case VK_MENU: - case VK_CAPITAL: - case VK_LWIN: - case VK_RWIN: - case VK_APPS: - case VK_NUMLOCK: - case VK_SCROLL: - case VK_LSHIFT: - case VK_RSHIFT: - case VK_LCONTROL: - case VK_LMENU: - case VK_RCONTROL: - case VK_RMENU: - sendModifierKeyChangeIfNeeded(); - } - - return handleKeyUpOrDown (false) - || Component::getCurrentlyModalComponent() != 0; - } - - bool doKeyDown (const WPARAM key) - { - updateKeyModifiers(); - bool used = false; - - switch (key) - { - case VK_SHIFT: - case VK_LSHIFT: - case VK_RSHIFT: - case VK_CONTROL: - case VK_LCONTROL: - case VK_RCONTROL: - case VK_MENU: - case VK_LMENU: - case VK_RMENU: - case VK_LWIN: - case VK_RWIN: - case VK_CAPITAL: - case VK_NUMLOCK: - case VK_SCROLL: - case VK_APPS: - sendModifierKeyChangeIfNeeded(); - break; - - case VK_LEFT: - case VK_RIGHT: - case VK_UP: - case VK_DOWN: - case VK_PRIOR: - case VK_NEXT: - case VK_HOME: - case VK_END: - case VK_DELETE: - case VK_INSERT: - case VK_F1: - case VK_F2: - case VK_F3: - case VK_F4: - case VK_F5: - case VK_F6: - case VK_F7: - case VK_F8: - case VK_F9: - case VK_F10: - case VK_F11: - case VK_F12: - case VK_F13: - case VK_F14: - case VK_F15: - case VK_F16: - used = handleKeyUpOrDown (true); - used = handleKeyPress (extendedKeyModifier | (int) key, 0) || used; - break; - - case VK_ADD: - case VK_SUBTRACT: - case VK_MULTIPLY: - case VK_DIVIDE: - case VK_SEPARATOR: - case VK_DECIMAL: - used = handleKeyUpOrDown (true); - break; - - default: - used = handleKeyUpOrDown (true); - - { - MSG msg; - - if (! PeekMessage (&msg, hwnd, WM_CHAR, WM_DEADCHAR, PM_NOREMOVE)) - { - // if there isn't a WM_CHAR or WM_DEADCHAR message pending, we need to - // manually generate the key-press event that matches this key-down. - - const UINT keyChar = MapVirtualKey (key, 2); - used = handleKeyPress ((int) LOWORD (keyChar), 0) || used; - } - } - - break; - } - - if (Component::getCurrentlyModalComponent() != 0) - used = true; - - return used; - } - - bool doKeyChar (int key, const LPARAM flags) - { - updateKeyModifiers(); - - juce_wchar textChar = (juce_wchar) key; - - const int virtualScanCode = (flags >> 16) & 0xff; - - if (key >= '0' && key <= '9') - { - switch (virtualScanCode) // check for a numeric keypad scan-code - { - case 0x52: - case 0x4f: - case 0x50: - case 0x51: - case 0x4b: - case 0x4c: - case 0x4d: - case 0x47: - case 0x48: - case 0x49: - key = (key - '0') + KeyPress::numberPad0; - break; - default: - break; - } - } - else - { - // convert the scan code to an unmodified character code.. - const UINT virtualKey = MapVirtualKey (virtualScanCode, 1); - UINT keyChar = MapVirtualKey (virtualKey, 2); - - keyChar = LOWORD (keyChar); - - if (keyChar != 0) - key = (int) keyChar; - - // avoid sending junk text characters for some control-key combinations - if (textChar < ' ' && (currentModifiers & (ModifierKeys::ctrlModifier | ModifierKeys::altModifier)) != 0) - textChar = 0; - } - - return handleKeyPress (key, textChar); - } - - bool doAppCommand (const LPARAM lParam) - { - int key = 0; - - switch (GET_APPCOMMAND_LPARAM (lParam)) - { - case APPCOMMAND_MEDIA_PLAY_PAUSE: - key = KeyPress::playKey; - break; - - case APPCOMMAND_MEDIA_STOP: - key = KeyPress::stopKey; - break; - - case APPCOMMAND_MEDIA_NEXTTRACK: - key = KeyPress::fastForwardKey; - break; - - case APPCOMMAND_MEDIA_PREVIOUSTRACK: - key = KeyPress::rewindKey; - break; - } - - if (key != 0) - { - updateKeyModifiers(); - - if (hwnd == GetActiveWindow()) - { - handleKeyPress (key, 0); - return true; - } - } - - return false; - } - - class JuceDropTarget : public IDropTarget - { - public: - JuceDropTarget (Win32ComponentPeer* const owner_) - : owner (owner_), - refCount (1) - { - } - - virtual ~JuceDropTarget() - { - jassert (refCount == 0); - } - - HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) - { - if (id == IID_IUnknown || id == IID_IDropTarget) - { - AddRef(); - *result = this; - return S_OK; - } - - *result = 0; - return E_NOINTERFACE; - } - - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } - - HRESULT __stdcall DragEnter (IDataObject* pDataObject, DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) - { - updateFileList (pDataObject); - int x = mousePos.x, y = mousePos.y; - owner->globalPositionToRelative (x, y); - owner->handleFileDragMove (files, x, y); - *pdwEffect = DROPEFFECT_COPY; - return S_OK; - } - - HRESULT __stdcall DragLeave() - { - owner->handleFileDragExit (files); - return S_OK; - } - - HRESULT __stdcall DragOver (DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) - { - int x = mousePos.x, y = mousePos.y; - owner->globalPositionToRelative (x, y); - owner->handleFileDragMove (files, x, y); - *pdwEffect = DROPEFFECT_COPY; - return S_OK; - } - - HRESULT __stdcall Drop (IDataObject* pDataObject, DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) - { - updateFileList (pDataObject); - int x = mousePos.x, y = mousePos.y; - owner->globalPositionToRelative (x, y); - owner->handleFileDragDrop (files, x, y); - *pdwEffect = DROPEFFECT_COPY; - return S_OK; - } - - private: - Win32ComponentPeer* const owner; - int refCount; - StringArray files; - - void updateFileList (IDataObject* const pDataObject) - { - files.clear(); - - FORMATETC format = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - STGMEDIUM medium = { TYMED_HGLOBAL, { 0 }, 0 }; - - if (pDataObject->GetData (&format, &medium) == S_OK) - { - const SIZE_T totalLen = GlobalSize (medium.hGlobal); - const LPDROPFILES pDropFiles = (const LPDROPFILES) GlobalLock (medium.hGlobal); - unsigned int i = 0; - - if (pDropFiles->fWide) - { - const WCHAR* const fname = (WCHAR*) (((const char*) pDropFiles) + sizeof (DROPFILES)); - - for (;;) - { - unsigned int len = 0; - while (i + len < totalLen && fname [i + len] != 0) - ++len; - - if (len == 0) - break; - - files.add (String (fname + i, len)); - i += len + 1; - } - } - else - { - const char* const fname = ((const char*) pDropFiles) + sizeof (DROPFILES); - - for (;;) - { - unsigned int len = 0; - while (i + len < totalLen && fname [i + len] != 0) - ++len; - - if (len == 0) - break; - - files.add (String (fname + i, len)); - i += len + 1; - } - } - - GlobalUnlock (medium.hGlobal); - } - } - - JuceDropTarget (const JuceDropTarget&); - const JuceDropTarget& operator= (const JuceDropTarget&); - }; - - void doSettingChange() - { - Desktop::getInstance().refreshMonitorSizes(); - - if (fullScreen && ! isMinimised()) - { - const Rectangle r (component->getParentMonitorArea()); - - SetWindowPos (hwnd, 0, - r.getX(), r.getY(), r.getWidth(), r.getHeight(), - SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOSENDCHANGING); - } - } + } + + void doMouseMove (const int x, const int y) + { + static uint32 lastMouseTime = 0; + // this can be set to throttle the mouse-messages to less than a + // certain number per second, as things can get unresponsive + // if each drag or move callback has to do a lot of work. + const int maxMouseMovesPerSecond = 60; + + const int64 mouseEventTime = getMouseEventTime(); + + if (! isMouseOver) + { + isMouseOver = true; + + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof (tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hwnd; + tme.dwHoverTime = 0; + + if (! TrackMouseEvent (&tme)) + { + jassertfalse; + } + + updateKeyModifiers(); + handleMouseEnter (x, y, mouseEventTime); + } + else if (! isDragging) + { + if (((unsigned int) x) < (unsigned int) component->getWidth() + && ((unsigned int) y) < (unsigned int) component->getHeight()) + { + RECT r; + GetWindowRect (hwnd, &r); + + POINT p; + p.x = x + r.left + windowBorder.getLeft(); + p.y = y + r.top + windowBorder.getTop(); + + if (WindowFromPoint (p) == hwnd) + { + const uint32 now = Time::getMillisecondCounter(); + + if (now > lastMouseTime + 1000 / maxMouseMovesPerSecond) + { + lastMouseTime = now; + handleMouseMove (x, y, mouseEventTime); + } + } + } + } + else + { + const uint32 now = Time::getMillisecondCounter(); + + if (now > lastMouseTime + 1000 / maxMouseMovesPerSecond) + { + lastMouseTime = now; + handleMouseDrag (x, y, mouseEventTime); + } + } + } + + void doMouseDown (const int x, const int y, const WPARAM wParam) + { + if (GetCapture() != hwnd) + SetCapture (hwnd); + + doMouseMove (x, y); + + currentModifiers &= ~ModifierKeys::allMouseButtonModifiers; + + if ((wParam & MK_LBUTTON) != 0) + currentModifiers |= ModifierKeys::leftButtonModifier; + + if ((wParam & MK_RBUTTON) != 0) + currentModifiers |= ModifierKeys::rightButtonModifier; + + if ((wParam & MK_MBUTTON) != 0) + currentModifiers |= ModifierKeys::middleButtonModifier; + + updateKeyModifiers(); + isDragging = true; + + handleMouseDown (x, y, getMouseEventTime()); + } + + void doMouseUp (const int x, const int y, const WPARAM wParam) + { + int numButtons = 0; + + if ((wParam & MK_LBUTTON) != 0) + ++numButtons; + + if ((wParam & MK_RBUTTON) != 0) + ++numButtons; + + if ((wParam & MK_MBUTTON) != 0) + ++numButtons; + + const int oldModifiers = currentModifiers; + + // update the currentmodifiers only after the callback, so the callback + // knows which button was released. + currentModifiers &= ~ModifierKeys::allMouseButtonModifiers; + + if ((wParam & MK_LBUTTON) != 0) + currentModifiers |= ModifierKeys::leftButtonModifier; + + if ((wParam & MK_RBUTTON) != 0) + currentModifiers |= ModifierKeys::rightButtonModifier; + + if ((wParam & MK_MBUTTON) != 0) + currentModifiers |= ModifierKeys::middleButtonModifier; + + updateKeyModifiers(); + isDragging = false; + + // release the mouse capture if the user's not still got a button down + if (numButtons == 0 && hwnd == GetCapture()) + ReleaseCapture(); + + handleMouseUp (oldModifiers, x, y, getMouseEventTime()); + } + + void doCaptureChanged() + { + if (isDragging) + { + RECT wr; + GetWindowRect (hwnd, &wr); + + const DWORD mp = GetMessagePos(); + + doMouseUp (GET_X_LPARAM (mp) - wr.left - windowBorder.getLeft(), + GET_Y_LPARAM (mp) - wr.top - windowBorder.getTop(), + (WPARAM) getMouseEventTime()); + } + } + + void doMouseExit() + { + if (isMouseOver) + { + isMouseOver = false; + RECT wr; + GetWindowRect (hwnd, &wr); + + const DWORD mp = GetMessagePos(); + + handleMouseExit (GET_X_LPARAM (mp) - wr.left - windowBorder.getLeft(), + GET_Y_LPARAM (mp) - wr.top - windowBorder.getTop(), + getMouseEventTime()); + } + } + + void doMouseWheel (const WPARAM wParam, const bool isVertical) + { + updateKeyModifiers(); + + const int amount = jlimit (-1000, 1000, (int) (0.75f * (short) HIWORD (wParam))); + + handleMouseWheel (isVertical ? 0 : amount, + isVertical ? amount : 0, + getMouseEventTime()); + } + + void sendModifierKeyChangeIfNeeded() + { + if (modifiersAtLastCallback != currentModifiers) + { + modifiersAtLastCallback = currentModifiers; + handleModifierKeysChange(); + } + } + + bool doKeyUp (const WPARAM key) + { + updateKeyModifiers(); + + switch (key) + { + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + case VK_CAPITAL: + case VK_LWIN: + case VK_RWIN: + case VK_APPS: + case VK_NUMLOCK: + case VK_SCROLL: + case VK_LSHIFT: + case VK_RSHIFT: + case VK_LCONTROL: + case VK_LMENU: + case VK_RCONTROL: + case VK_RMENU: + sendModifierKeyChangeIfNeeded(); + } + + return handleKeyUpOrDown (false) + || Component::getCurrentlyModalComponent() != 0; + } + + bool doKeyDown (const WPARAM key) + { + updateKeyModifiers(); + bool used = false; + + switch (key) + { + case VK_SHIFT: + case VK_LSHIFT: + case VK_RSHIFT: + case VK_CONTROL: + case VK_LCONTROL: + case VK_RCONTROL: + case VK_MENU: + case VK_LMENU: + case VK_RMENU: + case VK_LWIN: + case VK_RWIN: + case VK_CAPITAL: + case VK_NUMLOCK: + case VK_SCROLL: + case VK_APPS: + sendModifierKeyChangeIfNeeded(); + break; + + case VK_LEFT: + case VK_RIGHT: + case VK_UP: + case VK_DOWN: + case VK_PRIOR: + case VK_NEXT: + case VK_HOME: + case VK_END: + case VK_DELETE: + case VK_INSERT: + case VK_F1: + case VK_F2: + case VK_F3: + case VK_F4: + case VK_F5: + case VK_F6: + case VK_F7: + case VK_F8: + case VK_F9: + case VK_F10: + case VK_F11: + case VK_F12: + case VK_F13: + case VK_F14: + case VK_F15: + case VK_F16: + used = handleKeyUpOrDown (true); + used = handleKeyPress (extendedKeyModifier | (int) key, 0) || used; + break; + + case VK_ADD: + case VK_SUBTRACT: + case VK_MULTIPLY: + case VK_DIVIDE: + case VK_SEPARATOR: + case VK_DECIMAL: + used = handleKeyUpOrDown (true); + break; + + default: + used = handleKeyUpOrDown (true); + + { + MSG msg; + + if (! PeekMessage (&msg, hwnd, WM_CHAR, WM_DEADCHAR, PM_NOREMOVE)) + { + // if there isn't a WM_CHAR or WM_DEADCHAR message pending, we need to + // manually generate the key-press event that matches this key-down. + + const UINT keyChar = MapVirtualKey (key, 2); + used = handleKeyPress ((int) LOWORD (keyChar), 0) || used; + } + } + + break; + } + + if (Component::getCurrentlyModalComponent() != 0) + used = true; + + return used; + } + + bool doKeyChar (int key, const LPARAM flags) + { + updateKeyModifiers(); + + juce_wchar textChar = (juce_wchar) key; + + const int virtualScanCode = (flags >> 16) & 0xff; + + if (key >= '0' && key <= '9') + { + switch (virtualScanCode) // check for a numeric keypad scan-code + { + case 0x52: + case 0x4f: + case 0x50: + case 0x51: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x47: + case 0x48: + case 0x49: + key = (key - '0') + KeyPress::numberPad0; + break; + default: + break; + } + } + else + { + // convert the scan code to an unmodified character code.. + const UINT virtualKey = MapVirtualKey (virtualScanCode, 1); + UINT keyChar = MapVirtualKey (virtualKey, 2); + + keyChar = LOWORD (keyChar); + + if (keyChar != 0) + key = (int) keyChar; + + // avoid sending junk text characters for some control-key combinations + if (textChar < ' ' && (currentModifiers & (ModifierKeys::ctrlModifier | ModifierKeys::altModifier)) != 0) + textChar = 0; + } + + return handleKeyPress (key, textChar); + } + + bool doAppCommand (const LPARAM lParam) + { + int key = 0; + + switch (GET_APPCOMMAND_LPARAM (lParam)) + { + case APPCOMMAND_MEDIA_PLAY_PAUSE: + key = KeyPress::playKey; + break; + + case APPCOMMAND_MEDIA_STOP: + key = KeyPress::stopKey; + break; + + case APPCOMMAND_MEDIA_NEXTTRACK: + key = KeyPress::fastForwardKey; + break; + + case APPCOMMAND_MEDIA_PREVIOUSTRACK: + key = KeyPress::rewindKey; + break; + } + + if (key != 0) + { + updateKeyModifiers(); + + if (hwnd == GetActiveWindow()) + { + handleKeyPress (key, 0); + return true; + } + } + + return false; + } + + class JuceDropTarget : public IDropTarget + { + public: + JuceDropTarget (Win32ComponentPeer* const owner_) + : owner (owner_), + refCount (1) + { + } + + virtual ~JuceDropTarget() + { + jassert (refCount == 0); + } + + HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) + { + if (id == IID_IUnknown || id == IID_IDropTarget) + { + AddRef(); + *result = this; + return S_OK; + } + + *result = 0; + return E_NOINTERFACE; + } + + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } + + HRESULT __stdcall DragEnter (IDataObject* pDataObject, DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) + { + updateFileList (pDataObject); + int x = mousePos.x, y = mousePos.y; + owner->globalPositionToRelative (x, y); + owner->handleFileDragMove (files, x, y); + *pdwEffect = DROPEFFECT_COPY; + return S_OK; + } + + HRESULT __stdcall DragLeave() + { + owner->handleFileDragExit (files); + return S_OK; + } + + HRESULT __stdcall DragOver (DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) + { + int x = mousePos.x, y = mousePos.y; + owner->globalPositionToRelative (x, y); + owner->handleFileDragMove (files, x, y); + *pdwEffect = DROPEFFECT_COPY; + return S_OK; + } + + HRESULT __stdcall Drop (IDataObject* pDataObject, DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) + { + updateFileList (pDataObject); + int x = mousePos.x, y = mousePos.y; + owner->globalPositionToRelative (x, y); + owner->handleFileDragDrop (files, x, y); + *pdwEffect = DROPEFFECT_COPY; + return S_OK; + } + + private: + Win32ComponentPeer* const owner; + int refCount; + StringArray files; + + void updateFileList (IDataObject* const pDataObject) + { + files.clear(); + + FORMATETC format = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM medium = { TYMED_HGLOBAL, { 0 }, 0 }; + + if (pDataObject->GetData (&format, &medium) == S_OK) + { + const SIZE_T totalLen = GlobalSize (medium.hGlobal); + const LPDROPFILES pDropFiles = (const LPDROPFILES) GlobalLock (medium.hGlobal); + unsigned int i = 0; + + if (pDropFiles->fWide) + { + const WCHAR* const fname = (WCHAR*) (((const char*) pDropFiles) + sizeof (DROPFILES)); + + for (;;) + { + unsigned int len = 0; + while (i + len < totalLen && fname [i + len] != 0) + ++len; + + if (len == 0) + break; + + files.add (String (fname + i, len)); + i += len + 1; + } + } + else + { + const char* const fname = ((const char*) pDropFiles) + sizeof (DROPFILES); + + for (;;) + { + unsigned int len = 0; + while (i + len < totalLen && fname [i + len] != 0) + ++len; + + if (len == 0) + break; + + files.add (String (fname + i, len)); + i += len + 1; + } + } + + GlobalUnlock (medium.hGlobal); + } + } + + JuceDropTarget (const JuceDropTarget&); + const JuceDropTarget& operator= (const JuceDropTarget&); + }; + + void doSettingChange() + { + Desktop::getInstance().refreshMonitorSizes(); + + if (fullScreen && ! isMinimised()) + { + const Rectangle r (component->getParentMonitorArea()); + + SetWindowPos (hwnd, 0, + r.getX(), r.getY(), r.getWidth(), r.getHeight(), + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOSENDCHANGING); + } + } public: - static LRESULT CALLBACK windowProc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) - { - Win32ComponentPeer* const peer = getOwnerOfWindow (h); + static LRESULT CALLBACK windowProc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) + { + Win32ComponentPeer* const peer = getOwnerOfWindow (h); - if (peer != 0) - return peer->peerWindowProc (h, message, wParam, lParam); + if (peer != 0) + return peer->peerWindowProc (h, message, wParam, lParam); - return DefWindowProc (h, message, wParam, lParam); - } + return DefWindowProc (h, message, wParam, lParam); + } private: - LRESULT peerWindowProc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) - { - if (isValidPeer (this)) - { - switch (message) - { - - case WM_NCHITTEST: - if ((styleFlags & windowIgnoresMouseClicks) != 0) - return HTTRANSPARENT; - - if (hasTitleBar()) - break; - - return HTCLIENT; - - case WM_PAINT: - handlePaintMessage(); - return 0; - - case WM_NCPAINT: - if (wParam != 1) - handlePaintMessage(); - - if (hasTitleBar()) - break; + LRESULT peerWindowProc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) + { + if (isValidPeer (this)) + { + switch (message) + { + + case WM_NCHITTEST: + if ((styleFlags & windowIgnoresMouseClicks) != 0) + return HTTRANSPARENT; + + if (hasTitleBar()) + break; + + return HTCLIENT; + + case WM_PAINT: + handlePaintMessage(); + return 0; + + case WM_NCPAINT: + if (wParam != 1) + handlePaintMessage(); + + if (hasTitleBar()) + break; - return 0; + return 0; - case WM_ERASEBKGND: - case WM_NCCALCSIZE: - if (hasTitleBar()) - break; + case WM_ERASEBKGND: + case WM_NCCALCSIZE: + if (hasTitleBar()) + break; - return 1; + return 1; - case WM_MOUSEMOVE: - doMouseMove (GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam)); - return 0; + case WM_MOUSEMOVE: + doMouseMove (GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam)); + return 0; - case WM_MOUSELEAVE: - doMouseExit(); - return 0; - - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - doMouseDown (GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam), wParam); - return 0; + case WM_MOUSELEAVE: + doMouseExit(); + return 0; + + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + doMouseDown (GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam), wParam); + return 0; - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - doMouseUp (GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam), wParam); - return 0; - - case WM_CAPTURECHANGED: - doCaptureChanged(); - return 0; - - case WM_NCMOUSEMOVE: - if (hasTitleBar()) - break; - - return 0; - - case 0x020A: /* WM_MOUSEWHEEL */ - doMouseWheel (wParam, true); - return 0; - - case 0x020E: /* WM_MOUSEHWHEEL */ - doMouseWheel (wParam, false); - return 0; - - case WM_WINDOWPOSCHANGING: - if ((styleFlags & (windowHasTitleBar | windowIsResizable)) == (windowHasTitleBar | windowIsResizable)) - { - WINDOWPOS* const wp = (WINDOWPOS*) lParam; - - if ((wp->flags & (SWP_NOMOVE | SWP_NOSIZE)) != (SWP_NOMOVE | SWP_NOSIZE)) - { - if (constrainer != 0) - { - const Rectangle current (component->getX() - windowBorder.getLeft(), - component->getY() - windowBorder.getTop(), - component->getWidth() + windowBorder.getLeftAndRight(), - component->getHeight() + windowBorder.getTopAndBottom()); - - constrainer->checkBounds (wp->x, wp->y, wp->cx, wp->cy, - current, - Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), - wp->y != current.getY() && wp->y + wp->cy == current.getBottom(), - wp->x != current.getX() && wp->x + wp->cx == current.getRight(), - wp->y == current.getY() && wp->y + wp->cy != current.getBottom(), - wp->x == current.getX() && wp->x + wp->cx != current.getRight()); - } - } - } - - return 0; - - case WM_WINDOWPOSCHANGED: - handleMovedOrResized(); - - if (dontRepaint) - break; // needed for non-accelerated openGL windows to draw themselves correctly.. + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + doMouseUp (GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam), wParam); + return 0; + + case WM_CAPTURECHANGED: + doCaptureChanged(); + return 0; + + case WM_NCMOUSEMOVE: + if (hasTitleBar()) + break; + + return 0; + + case 0x020A: /* WM_MOUSEWHEEL */ + doMouseWheel (wParam, true); + return 0; + + case 0x020E: /* WM_MOUSEHWHEEL */ + doMouseWheel (wParam, false); + return 0; + + case WM_WINDOWPOSCHANGING: + if ((styleFlags & (windowHasTitleBar | windowIsResizable)) == (windowHasTitleBar | windowIsResizable)) + { + WINDOWPOS* const wp = (WINDOWPOS*) lParam; + + if ((wp->flags & (SWP_NOMOVE | SWP_NOSIZE)) != (SWP_NOMOVE | SWP_NOSIZE)) + { + if (constrainer != 0) + { + const Rectangle current (component->getX() - windowBorder.getLeft(), + component->getY() - windowBorder.getTop(), + component->getWidth() + windowBorder.getLeftAndRight(), + component->getHeight() + windowBorder.getTopAndBottom()); + + constrainer->checkBounds (wp->x, wp->y, wp->cx, wp->cy, + current, + Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), + wp->y != current.getY() && wp->y + wp->cy == current.getBottom(), + wp->x != current.getX() && wp->x + wp->cx == current.getRight(), + wp->y == current.getY() && wp->y + wp->cy != current.getBottom(), + wp->x == current.getX() && wp->x + wp->cx != current.getRight()); + } + } + } + + return 0; + + case WM_WINDOWPOSCHANGED: + handleMovedOrResized(); + + if (dontRepaint) + break; // needed for non-accelerated openGL windows to draw themselves correctly.. - return 0; + return 0; - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - if (doKeyDown (wParam)) - return 0; + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + if (doKeyDown (wParam)) + return 0; - break; + break; - case WM_KEYUP: - case WM_SYSKEYUP: - if (doKeyUp (wParam)) - return 0; + case WM_KEYUP: + case WM_SYSKEYUP: + if (doKeyUp (wParam)) + return 0; - break; + break; - case WM_CHAR: - if (doKeyChar ((int) wParam, lParam)) - return 0; + case WM_CHAR: + if (doKeyChar ((int) wParam, lParam)) + return 0; - break; + break; - case WM_APPCOMMAND: - if (doAppCommand (lParam)) - return TRUE; + case WM_APPCOMMAND: + if (doAppCommand (lParam)) + return TRUE; - break; - - case WM_SETFOCUS: - updateKeyModifiers(); - handleFocusGain(); - break; - - case WM_KILLFOCUS: - if (hasCreatedCaret) - { - hasCreatedCaret = false; - DestroyCaret(); - } - - handleFocusLoss(); - break; - - case WM_ACTIVATEAPP: - // Windows does weird things to process priority when you swap apps, - // so this forces an update when the app is brought to the front - if (wParam != FALSE) - juce_repeatLastProcessPriority(); - else - Desktop::getInstance().setKioskModeComponent (0); // turn kiosk mode off if we lose focus - - juce_CheckCurrentlyFocusedTopLevelWindow(); - modifiersAtLastCallback = -1; - return 0; - - case WM_ACTIVATE: - if (LOWORD (wParam) == WA_ACTIVE || LOWORD (wParam) == WA_CLICKACTIVE) - { - modifiersAtLastCallback = -1; - updateKeyModifiers(); - - if (isMinimised()) - { - component->repaint(); - handleMovedOrResized(); - - if (! isValidMessageListener()) - return 0; - } - - if (LOWORD (wParam) == WA_CLICKACTIVE - && component->isCurrentlyBlockedByAnotherModalComponent()) - { - int mx, my; - component->getMouseXYRelative (mx, my); - Component* const underMouse = component->getComponentAt (mx, my); - - if (underMouse != 0 && underMouse->isCurrentlyBlockedByAnotherModalComponent()) - Component::getCurrentlyModalComponent()->inputAttemptWhenModal(); - - return 0; - } - - handleBroughtToFront(); - - if (component->isCurrentlyBlockedByAnotherModalComponent()) - Component::getCurrentlyModalComponent()->toFront (true); - - return 0; - } - - break; - - case WM_NCACTIVATE: - // while a temporary window is being shown, prevent Windows from deactivating the - // title bars of our main windows. - if (wParam == 0 && ! shouldDeactivateTitleBar) - wParam = TRUE; // change this and let it get passed to the DefWindowProc. - - break; - - case WM_MOUSEACTIVATE: - if (! component->getMouseClickGrabsKeyboardFocus()) - return MA_NOACTIVATE; - - break; - - case WM_SHOWWINDOW: - if (wParam != 0) - handleBroughtToFront(); - - break; - - case WM_CLOSE: - if (! component->isCurrentlyBlockedByAnotherModalComponent()) - handleUserClosingWindow(); - - return 0; - - case WM_QUIT: - if (JUCEApplication::getInstance() != 0) - JUCEApplication::getInstance()->systemRequestedQuit(); - return 0; - - case WM_QUERYENDSESSION: - if (JUCEApplication::getInstance() != 0) - { - JUCEApplication::getInstance()->systemRequestedQuit(); - return MessageManager::getInstance()->hasStopMessageBeenSent(); - } - return TRUE; - - case WM_TRAYNOTIFY: - if (component->isCurrentlyBlockedByAnotherModalComponent()) - { - if (lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN - || lParam == WM_LBUTTONDBLCLK || lParam == WM_LBUTTONDBLCLK) - { - Component* const current = Component::getCurrentlyModalComponent(); - - if (current != 0) - current->inputAttemptWhenModal(); - } - } - else - { - const int oldModifiers = currentModifiers; - - MouseEvent e (0, 0, ModifierKeys::getCurrentModifiersRealtime(), component, - getMouseEventTime(), 0, 0, getMouseEventTime(), 1, false); - - if (lParam == WM_LBUTTONDOWN || lParam == WM_LBUTTONDBLCLK) - e.mods = ModifierKeys (e.mods.getRawFlags() | ModifierKeys::leftButtonModifier); - else if (lParam == WM_RBUTTONDOWN || lParam == WM_RBUTTONDBLCLK) - e.mods = ModifierKeys (e.mods.getRawFlags() | ModifierKeys::rightButtonModifier); - - if (lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN) - { - SetFocus (hwnd); - SetForegroundWindow (hwnd); - - component->mouseDown (e); - } - else if (lParam == WM_LBUTTONUP || lParam == WM_RBUTTONUP) - { - e.mods = ModifierKeys (oldModifiers); - component->mouseUp (e); - } - else if (lParam == WM_LBUTTONDBLCLK || lParam == WM_LBUTTONDBLCLK) - { - e.mods = ModifierKeys (oldModifiers); - component->mouseDoubleClick (e); - } - else if (lParam == WM_MOUSEMOVE) - { - component->mouseMove (e); - } - } - - break; - - case WM_SYNCPAINT: - return 0; - - case WM_PALETTECHANGED: - InvalidateRect (h, 0, 0); - break; - - case WM_DISPLAYCHANGE: - InvalidateRect (h, 0, 0); - createPaletteIfNeeded = true; - // intentional fall-through... - case WM_SETTINGCHANGE: // note the fall-through in the previous case! - doSettingChange(); - break; - - case WM_INITMENU: - if (! hasTitleBar()) - { - if (isFullScreen()) - { - EnableMenuItem ((HMENU) wParam, SC_RESTORE, MF_BYCOMMAND | MF_ENABLED); - EnableMenuItem ((HMENU) wParam, SC_MOVE, MF_BYCOMMAND | MF_GRAYED); - } - else if (! isMinimised()) - { - EnableMenuItem ((HMENU) wParam, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED); - } - } - break; - - case WM_SYSCOMMAND: - switch (wParam & 0xfff0) - { - case SC_CLOSE: - if (sendInputAttemptWhenModalMessage()) - return 0; - - if (hasTitleBar()) - { - PostMessage (h, WM_CLOSE, 0, 0); - return 0; - } - break; - - case SC_KEYMENU: - // (NB mustn't call sendInputAttemptWhenModalMessage() here because of very - // obscure situations that can arise if a modal loop is started from an alt-key - // keypress). - - if (hasTitleBar() && h == GetCapture()) - ReleaseCapture(); - - break; - - case SC_MAXIMIZE: - if (sendInputAttemptWhenModalMessage()) - return 0; - - setFullScreen (true); - return 0; - - case SC_MINIMIZE: - if (sendInputAttemptWhenModalMessage()) - return 0; - - if (! hasTitleBar()) - { - setMinimised (true); - return 0; - } - break; - - case SC_RESTORE: - if (sendInputAttemptWhenModalMessage()) - return 0; - - if (hasTitleBar()) - { - if (isFullScreen()) - { - setFullScreen (false); - return 0; - } - } - else - { - if (isMinimised()) - setMinimised (false); - else if (isFullScreen()) - setFullScreen (false); - - return 0; - } - - break; - } - - break; - - case WM_NCLBUTTONDOWN: - case WM_NCRBUTTONDOWN: - case WM_NCMBUTTONDOWN: - sendInputAttemptWhenModalMessage(); - break; - - //case WM_IME_STARTCOMPOSITION; - // return 0; - - case WM_GETDLGCODE: - return DLGC_WANTALLKEYS; - - default: - break; - } - } - - return DefWindowProc (h, message, wParam, lParam); - } - - bool sendInputAttemptWhenModalMessage() - { - if (component->isCurrentlyBlockedByAnotherModalComponent()) - { - Component* const current = Component::getCurrentlyModalComponent(); - - if (current != 0) - current->inputAttemptWhenModal(); - - return true; - } - - return false; - } - - Win32ComponentPeer (const Win32ComponentPeer&); - const Win32ComponentPeer& operator= (const Win32ComponentPeer&); + break; + + case WM_SETFOCUS: + updateKeyModifiers(); + handleFocusGain(); + break; + + case WM_KILLFOCUS: + if (hasCreatedCaret) + { + hasCreatedCaret = false; + DestroyCaret(); + } + + handleFocusLoss(); + break; + + case WM_ACTIVATEAPP: + // Windows does weird things to process priority when you swap apps, + // so this forces an update when the app is brought to the front + if (wParam != FALSE) + juce_repeatLastProcessPriority(); + else + Desktop::getInstance().setKioskModeComponent (0); // turn kiosk mode off if we lose focus + + juce_CheckCurrentlyFocusedTopLevelWindow(); + modifiersAtLastCallback = -1; + return 0; + + case WM_ACTIVATE: + if (LOWORD (wParam) == WA_ACTIVE || LOWORD (wParam) == WA_CLICKACTIVE) + { + modifiersAtLastCallback = -1; + updateKeyModifiers(); + + if (isMinimised()) + { + component->repaint(); + handleMovedOrResized(); + + if (! isValidMessageListener()) + return 0; + } + + if (LOWORD (wParam) == WA_CLICKACTIVE + && component->isCurrentlyBlockedByAnotherModalComponent()) + { + int mx, my; + component->getMouseXYRelative (mx, my); + Component* const underMouse = component->getComponentAt (mx, my); + + if (underMouse != 0 && underMouse->isCurrentlyBlockedByAnotherModalComponent()) + Component::getCurrentlyModalComponent()->inputAttemptWhenModal(); + + return 0; + } + + handleBroughtToFront(); + + if (component->isCurrentlyBlockedByAnotherModalComponent()) + Component::getCurrentlyModalComponent()->toFront (true); + + return 0; + } + + break; + + case WM_NCACTIVATE: + // while a temporary window is being shown, prevent Windows from deactivating the + // title bars of our main windows. + if (wParam == 0 && ! shouldDeactivateTitleBar) + wParam = TRUE; // change this and let it get passed to the DefWindowProc. + + break; + + case WM_MOUSEACTIVATE: + if (! component->getMouseClickGrabsKeyboardFocus()) + return MA_NOACTIVATE; + + break; + + case WM_SHOWWINDOW: + if (wParam != 0) + handleBroughtToFront(); + + break; + + case WM_CLOSE: + if (! component->isCurrentlyBlockedByAnotherModalComponent()) + handleUserClosingWindow(); + + return 0; + + case WM_QUIT: + if (JUCEApplication::getInstance() != 0) + JUCEApplication::getInstance()->systemRequestedQuit(); + return 0; + + case WM_QUERYENDSESSION: + if (JUCEApplication::getInstance() != 0) + { + JUCEApplication::getInstance()->systemRequestedQuit(); + return MessageManager::getInstance()->hasStopMessageBeenSent(); + } + return TRUE; + + case WM_TRAYNOTIFY: + if (component->isCurrentlyBlockedByAnotherModalComponent()) + { + if (lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN + || lParam == WM_LBUTTONDBLCLK || lParam == WM_LBUTTONDBLCLK) + { + Component* const current = Component::getCurrentlyModalComponent(); + + if (current != 0) + current->inputAttemptWhenModal(); + } + } + else + { + const int oldModifiers = currentModifiers; + + MouseEvent e (0, 0, ModifierKeys::getCurrentModifiersRealtime(), component, + getMouseEventTime(), 0, 0, getMouseEventTime(), 1, false); + + if (lParam == WM_LBUTTONDOWN || lParam == WM_LBUTTONDBLCLK) + e.mods = ModifierKeys (e.mods.getRawFlags() | ModifierKeys::leftButtonModifier); + else if (lParam == WM_RBUTTONDOWN || lParam == WM_RBUTTONDBLCLK) + e.mods = ModifierKeys (e.mods.getRawFlags() | ModifierKeys::rightButtonModifier); + + if (lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN) + { + SetFocus (hwnd); + SetForegroundWindow (hwnd); + + component->mouseDown (e); + } + else if (lParam == WM_LBUTTONUP || lParam == WM_RBUTTONUP) + { + e.mods = ModifierKeys (oldModifiers); + component->mouseUp (e); + } + else if (lParam == WM_LBUTTONDBLCLK || lParam == WM_LBUTTONDBLCLK) + { + e.mods = ModifierKeys (oldModifiers); + component->mouseDoubleClick (e); + } + else if (lParam == WM_MOUSEMOVE) + { + component->mouseMove (e); + } + } + + break; + + case WM_SYNCPAINT: + return 0; + + case WM_PALETTECHANGED: + InvalidateRect (h, 0, 0); + break; + + case WM_DISPLAYCHANGE: + InvalidateRect (h, 0, 0); + createPaletteIfNeeded = true; + // intentional fall-through... + case WM_SETTINGCHANGE: // note the fall-through in the previous case! + doSettingChange(); + break; + + case WM_INITMENU: + if (! hasTitleBar()) + { + if (isFullScreen()) + { + EnableMenuItem ((HMENU) wParam, SC_RESTORE, MF_BYCOMMAND | MF_ENABLED); + EnableMenuItem ((HMENU) wParam, SC_MOVE, MF_BYCOMMAND | MF_GRAYED); + } + else if (! isMinimised()) + { + EnableMenuItem ((HMENU) wParam, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED); + } + } + break; + + case WM_SYSCOMMAND: + switch (wParam & 0xfff0) + { + case SC_CLOSE: + if (sendInputAttemptWhenModalMessage()) + return 0; + + if (hasTitleBar()) + { + PostMessage (h, WM_CLOSE, 0, 0); + return 0; + } + break; + + case SC_KEYMENU: + // (NB mustn't call sendInputAttemptWhenModalMessage() here because of very + // obscure situations that can arise if a modal loop is started from an alt-key + // keypress). + + if (hasTitleBar() && h == GetCapture()) + ReleaseCapture(); + + break; + + case SC_MAXIMIZE: + if (sendInputAttemptWhenModalMessage()) + return 0; + + setFullScreen (true); + return 0; + + case SC_MINIMIZE: + if (sendInputAttemptWhenModalMessage()) + return 0; + + if (! hasTitleBar()) + { + setMinimised (true); + return 0; + } + break; + + case SC_RESTORE: + if (sendInputAttemptWhenModalMessage()) + return 0; + + if (hasTitleBar()) + { + if (isFullScreen()) + { + setFullScreen (false); + return 0; + } + } + else + { + if (isMinimised()) + setMinimised (false); + else if (isFullScreen()) + setFullScreen (false); + + return 0; + } + + break; + } + + break; + + case WM_NCLBUTTONDOWN: + case WM_NCRBUTTONDOWN: + case WM_NCMBUTTONDOWN: + sendInputAttemptWhenModalMessage(); + break; + + //case WM_IME_STARTCOMPOSITION; + // return 0; + + case WM_GETDLGCODE: + return DLGC_WANTALLKEYS; + + default: + break; + } + } + + return DefWindowProc (h, message, wParam, lParam); + } + + bool sendInputAttemptWhenModalMessage() + { + if (component->isCurrentlyBlockedByAnotherModalComponent()) + { + Component* const current = Component::getCurrentlyModalComponent(); + + if (current != 0) + current->inputAttemptWhenModal(); + + return true; + } + + return false; + } + + Win32ComponentPeer (const Win32ComponentPeer&); + const Win32ComponentPeer& operator= (const Win32ComponentPeer&); }; ComponentPeer* Component::createNewPeer (int styleFlags, void* /*nativeWindowToAttachTo*/) { - return new Win32ComponentPeer (this, styleFlags); + return new Win32ComponentPeer (this, styleFlags); } juce_ImplementSingleton_SingleThreaded (Win32ComponentPeer::WindowClassHolder); void SystemTrayIconComponent::setIconImage (const Image& newImage) { - Win32ComponentPeer* const wp = dynamic_cast (getPeer()); + Win32ComponentPeer* const wp = dynamic_cast (getPeer()); - if (wp != 0) - wp->setTaskBarIcon (&newImage); + if (wp != 0) + wp->setTaskBarIcon (&newImage); } void SystemTrayIconComponent::setIconTooltip (const String& tooltip) { - Win32ComponentPeer* const wp = dynamic_cast (getPeer()); + Win32ComponentPeer* const wp = dynamic_cast (getPeer()); - if (wp != 0) - wp->setTaskBarIconToolTip (tooltip); + if (wp != 0) + wp->setTaskBarIconToolTip (tooltip); } void juce_setWindowStyleBit (HWND h, const int styleType, const int feature, const bool bitIsSet) throw() { - DWORD val = GetWindowLong (h, styleType); + DWORD val = GetWindowLong (h, styleType); - if (bitIsSet) - val |= feature; - else - val &= ~feature; + if (bitIsSet) + val |= feature; + else + val &= ~feature; - SetWindowLongPtr (h, styleType, val); - SetWindowPos (h, 0, 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER - | SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING); + SetWindowLongPtr (h, styleType, val); + SetWindowPos (h, 0, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER + | SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_NOSENDCHANGING); } bool Process::isForegroundProcess() { - HWND fg = GetForegroundWindow(); + HWND fg = GetForegroundWindow(); - if (fg == 0) - return true; + if (fg == 0) + return true; - // when running as a plugin in IE8, the browser UI runs in a different process to the plugin, so - // process ID isn't a reliable way to check if the foreground window belongs to us - instead, we - // have to see if any of our windows are children of the foreground window - fg = GetAncestor (fg, GA_ROOT); + // when running as a plugin in IE8, the browser UI runs in a different process to the plugin, so + // process ID isn't a reliable way to check if the foreground window belongs to us - instead, we + // have to see if any of our windows are children of the foreground window + fg = GetAncestor (fg, GA_ROOT); - for (int i = ComponentPeer::getNumPeers(); --i >= 0;) - { - Win32ComponentPeer* const wp = dynamic_cast (ComponentPeer::getPeer (i)); + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) + { + Win32ComponentPeer* const wp = dynamic_cast (ComponentPeer::getPeer (i)); - if (wp != 0 && wp->isInside (fg)) - return true; - } + if (wp != 0 && wp->isInside (fg)) + return true; + } - return false; + return false; } bool AlertWindow::showNativeDialogBox (const String& title, - const String& bodyText, - bool isOkCancel) + const String& bodyText, + bool isOkCancel) { - return MessageBox (0, bodyText, title, - MB_SETFOREGROUND | (isOkCancel ? MB_OKCANCEL - : MB_OK)) == IDOK; + return MessageBox (0, bodyText, title, + MB_SETFOREGROUND | (isOkCancel ? MB_OKCANCEL + : MB_OK)) == IDOK; } void Desktop::getMousePosition (int& x, int& y) throw() { - POINT mousePos; - GetCursorPos (&mousePos); - x = mousePos.x; - y = mousePos.y; + POINT mousePos; + GetCursorPos (&mousePos); + x = mousePos.x; + y = mousePos.y; } void Desktop::setMousePosition (int x, int y) throw() { - SetCursorPos (x, y); + SetCursorPos (x, y); } Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage) { - return new Image (format, imageWidth, imageHeight, clearImage); + return new Image (format, imageWidth, imageHeight, clearImage); } class ScreenSaverDefeater : public Timer, - public DeletedAtShutdown + public DeletedAtShutdown { public: - ScreenSaverDefeater() throw() - { - startTimer (10000); - timerCallback(); - } + ScreenSaverDefeater() throw() + { + startTimer (10000); + timerCallback(); + } - ~ScreenSaverDefeater() {} + ~ScreenSaverDefeater() {} - void timerCallback() - { - if (Process::isForegroundProcess()) - { - // simulate a shift key getting pressed.. - INPUT input[2]; - input[0].type = INPUT_KEYBOARD; - input[0].ki.wVk = VK_SHIFT; - input[0].ki.dwFlags = 0; - input[0].ki.dwExtraInfo = 0; + void timerCallback() + { + if (Process::isForegroundProcess()) + { + // simulate a shift key getting pressed.. + INPUT input[2]; + input[0].type = INPUT_KEYBOARD; + input[0].ki.wVk = VK_SHIFT; + input[0].ki.dwFlags = 0; + input[0].ki.dwExtraInfo = 0; - input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = VK_SHIFT; - input[1].ki.dwFlags = KEYEVENTF_KEYUP; - input[1].ki.dwExtraInfo = 0; + input[1].type = INPUT_KEYBOARD; + input[1].ki.wVk = VK_SHIFT; + input[1].ki.dwFlags = KEYEVENTF_KEYUP; + input[1].ki.dwExtraInfo = 0; - SendInput (2, input, sizeof (INPUT)); - } - } + SendInput (2, input, sizeof (INPUT)); + } + } }; static ScreenSaverDefeater* screenSaverDefeater = 0; void Desktop::setScreenSaverEnabled (const bool isEnabled) throw() { - if (isEnabled) - { - deleteAndZero (screenSaverDefeater); - } - else if (screenSaverDefeater == 0) - { - screenSaverDefeater = new ScreenSaverDefeater(); - } + if (isEnabled) + { + deleteAndZero (screenSaverDefeater); + } + else if (screenSaverDefeater == 0) + { + screenSaverDefeater = new ScreenSaverDefeater(); + } } bool Desktop::isScreenSaverEnabled() throw() { - return screenSaverDefeater == 0; + return screenSaverDefeater == 0; } -/* (The code below is the "correct" way to disable the screen saver, but it - completely fails on winXP when the saver is password-protected...) - -static bool juce_screenSaverEnabled = true; - -void Desktop::setScreenSaverEnabled (const bool isEnabled) throw() -{ - juce_screenSaverEnabled = isEnabled; - SetThreadExecutionState (isEnabled ? ES_CONTINUOUS - : (ES_DISPLAY_REQUIRED | ES_CONTINUOUS)); -} - -bool Desktop::isScreenSaverEnabled() throw() -{ - return juce_screenSaverEnabled; -} -*/ - void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool /*allowMenusAndBars*/) { - if (enableOrDisable) - kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); + if (enableOrDisable) + kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); } static BOOL CALLBACK enumMonitorsProc (HMONITOR, HDC, LPRECT r, LPARAM userInfo) { - Array * const monitorCoords = (Array *) userInfo; + Array * const monitorCoords = (Array *) userInfo; - monitorCoords->add (Rectangle (r->left, r->top, r->right - r->left, r->bottom - r->top)); + monitorCoords->add (Rectangle (r->left, r->top, r->right - r->left, r->bottom - r->top)); - return TRUE; + return TRUE; } -void juce_updateMultiMonitorInfo (Array & monitorCoords, const bool clipToWorkArea) throw() +void juce_updateMultiMonitorInfo (Array & monitorCoords, const bool clipToWorkArea) { - EnumDisplayMonitors (0, 0, &enumMonitorsProc, (LPARAM) &monitorCoords); + EnumDisplayMonitors (0, 0, &enumMonitorsProc, (LPARAM) &monitorCoords); - // make sure the first in the list is the main monitor - for (int i = 1; i < monitorCoords.size(); ++i) - if (monitorCoords[i].getX() == 0 && monitorCoords[i].getY() == 0) - monitorCoords.swap (i, 0); + // make sure the first in the list is the main monitor + for (int i = 1; i < monitorCoords.size(); ++i) + if (monitorCoords[i].getX() == 0 && monitorCoords[i].getY() == 0) + monitorCoords.swap (i, 0); - if (monitorCoords.size() == 0) - { - RECT r; - GetWindowRect (GetDesktopWindow(), &r); + if (monitorCoords.size() == 0) + { + RECT r; + GetWindowRect (GetDesktopWindow(), &r); - monitorCoords.add (Rectangle (r.left, r.top, r.right - r.left, r.bottom - r.top)); - } + monitorCoords.add (Rectangle (r.left, r.top, r.right - r.left, r.bottom - r.top)); + } - if (clipToWorkArea) - { - // clip the main monitor to the active non-taskbar area - RECT r; - SystemParametersInfo (SPI_GETWORKAREA, 0, &r, 0); + if (clipToWorkArea) + { + // clip the main monitor to the active non-taskbar area + RECT r; + SystemParametersInfo (SPI_GETWORKAREA, 0, &r, 0); - Rectangle& screen = monitorCoords.getReference (0); + Rectangle& screen = monitorCoords.getReference (0); - screen.setPosition (jmax (screen.getX(), r.left), - jmax (screen.getY(), r.top)); + screen.setPosition (jmax (screen.getX(), (int) r.left), + jmax (screen.getY(), (int) r.top)); - screen.setSize (jmin (screen.getRight(), r.right) - screen.getX(), - jmin (screen.getBottom(), r.bottom) - screen.getY()); - } + screen.setSize (jmin (screen.getRight(), (int) r.right) - screen.getX(), + jmin (screen.getBottom(), (int) r.bottom) - screen.getY()); + } } static Image* createImageFromHBITMAP (HBITMAP bitmap) throw() { - Image* im = 0; + Image* im = 0; - if (bitmap != 0) - { - BITMAP bm; + if (bitmap != 0) + { + BITMAP bm; - if (GetObject (bitmap, sizeof (BITMAP), &bm) - && bm.bmWidth > 0 && bm.bmHeight > 0) - { - HDC tempDC = GetDC (0); - HDC dc = CreateCompatibleDC (tempDC); - ReleaseDC (0, tempDC); + if (GetObject (bitmap, sizeof (BITMAP), &bm) + && bm.bmWidth > 0 && bm.bmHeight > 0) + { + HDC tempDC = GetDC (0); + HDC dc = CreateCompatibleDC (tempDC); + ReleaseDC (0, tempDC); - SelectObject (dc, bitmap); + SelectObject (dc, bitmap); - im = new Image (Image::ARGB, bm.bmWidth, bm.bmHeight, true); + im = new Image (Image::ARGB, bm.bmWidth, bm.bmHeight, true); - for (int y = bm.bmHeight; --y >= 0;) - { - for (int x = bm.bmWidth; --x >= 0;) - { - COLORREF col = GetPixel (dc, x, y); + for (int y = bm.bmHeight; --y >= 0;) + { + for (int x = bm.bmWidth; --x >= 0;) + { + COLORREF col = GetPixel (dc, x, y); - im->setPixelAt (x, y, Colour ((uint8) GetRValue (col), - (uint8) GetGValue (col), - (uint8) GetBValue (col))); - } - } + im->setPixelAt (x, y, Colour ((uint8) GetRValue (col), + (uint8) GetGValue (col), + (uint8) GetBValue (col))); + } + } - DeleteDC (dc); - } - } + DeleteDC (dc); + } + } - return im; + return im; } static Image* createImageFromHICON (HICON icon) throw() { - ICONINFO info; + ICONINFO info; - if (GetIconInfo (icon, &info)) - { - Image* const mask = createImageFromHBITMAP (info.hbmMask); + if (GetIconInfo (icon, &info)) + { + Image* const mask = createImageFromHBITMAP (info.hbmMask); - if (mask == 0) - return 0; + if (mask == 0) + return 0; - Image* const image = createImageFromHBITMAP (info.hbmColor); + Image* const image = createImageFromHBITMAP (info.hbmColor); - if (image == 0) - return mask; + if (image == 0) + return mask; - for (int y = image->getHeight(); --y >= 0;) - { - for (int x = image->getWidth(); --x >= 0;) - { - const float brightness = mask->getPixelAt (x, y).getBrightness(); + for (int y = image->getHeight(); --y >= 0;) + { + for (int x = image->getWidth(); --x >= 0;) + { + const float brightness = mask->getPixelAt (x, y).getBrightness(); - if (brightness > 0.0f) - image->multiplyAlphaAt (x, y, 1.0f - brightness); - } - } + if (brightness > 0.0f) + image->multiplyAlphaAt (x, y, 1.0f - brightness); + } + } - delete mask; - return image; - } + delete mask; + return image; + } - return 0; + return 0; } static HICON createHICONFromImage (const Image& image, const BOOL isIcon, int hotspotX, int hotspotY) throw() { - HBITMAP mask = CreateBitmap (image.getWidth(), image.getHeight(), 1, 1, 0); + HBITMAP mask = CreateBitmap (image.getWidth(), image.getHeight(), 1, 1, 0); - ICONINFO info; - info.fIcon = isIcon; - info.xHotspot = hotspotX; - info.yHotspot = hotspotY; - info.hbmMask = mask; - HICON hi = 0; + ICONINFO info; + info.fIcon = isIcon; + info.xHotspot = hotspotX; + info.yHotspot = hotspotY; + info.hbmMask = mask; + HICON hi = 0; - if (SystemStats::getOperatingSystemType() >= SystemStats::WinXP) - { - WindowsBitmapImage bitmap (Image::ARGB, image.getWidth(), image.getHeight(), true); - Graphics g (bitmap); - g.drawImageAt (&image, 0, 0); + if (SystemStats::getOperatingSystemType() >= SystemStats::WinXP) + { + WindowsBitmapImage bitmap (Image::ARGB, image.getWidth(), image.getHeight(), true); + Graphics g (bitmap); + g.drawImageAt (&image, 0, 0); - info.hbmColor = bitmap.hBitmap; - hi = CreateIconIndirect (&info); - } - else - { - HBITMAP colour = CreateCompatibleBitmap (GetDC (0), image.getWidth(), image.getHeight()); + info.hbmColor = bitmap.hBitmap; + hi = CreateIconIndirect (&info); + } + else + { + HBITMAP colour = CreateCompatibleBitmap (GetDC (0), image.getWidth(), image.getHeight()); - HDC colDC = CreateCompatibleDC (GetDC (0)); - HDC alphaDC = CreateCompatibleDC (GetDC (0)); - SelectObject (colDC, colour); - SelectObject (alphaDC, mask); + HDC colDC = CreateCompatibleDC (GetDC (0)); + HDC alphaDC = CreateCompatibleDC (GetDC (0)); + SelectObject (colDC, colour); + SelectObject (alphaDC, mask); - for (int y = image.getHeight(); --y >= 0;) - { - for (int x = image.getWidth(); --x >= 0;) - { - const Colour c (image.getPixelAt (x, y)); + for (int y = image.getHeight(); --y >= 0;) + { + for (int x = image.getWidth(); --x >= 0;) + { + const Colour c (image.getPixelAt (x, y)); - SetPixel (colDC, x, y, COLORREF (c.getRed() | (c.getGreen() << 8) | (c.getBlue() << 16))); - SetPixel (alphaDC, x, y, COLORREF (0xffffff - (c.getAlpha() | (c.getAlpha() << 8) | (c.getAlpha() << 16)))); - } - } + SetPixel (colDC, x, y, COLORREF (c.getRed() | (c.getGreen() << 8) | (c.getBlue() << 16))); + SetPixel (alphaDC, x, y, COLORREF (0xffffff - (c.getAlpha() | (c.getAlpha() << 8) | (c.getAlpha() << 16)))); + } + } - DeleteDC (colDC); - DeleteDC (alphaDC); + DeleteDC (colDC); + DeleteDC (alphaDC); - info.hbmColor = colour; - hi = CreateIconIndirect (&info); - DeleteObject (colour); - } + info.hbmColor = colour; + hi = CreateIconIndirect (&info); + DeleteObject (colour); + } - DeleteObject (mask); - return hi; + DeleteObject (mask); + return hi; } Image* juce_createIconForFile (const File& file) { - Image* image = 0; + Image* image = 0; - TCHAR filename [1024]; - file.getFullPathName().copyToBuffer (filename, 1023); - WORD iconNum = 0; + TCHAR filename [1024]; + file.getFullPathName().copyToBuffer (filename, 1023); + WORD iconNum = 0; - HICON icon = ExtractAssociatedIcon ((HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(), - filename, &iconNum); + HICON icon = ExtractAssociatedIcon ((HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(), + filename, &iconNum); - if (icon != 0) - { - image = createImageFromHICON (icon); - DestroyIcon (icon); - } + if (icon != 0) + { + image = createImageFromHICON (icon); + DestroyIcon (icon); + } - return image; + return image; } void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) throw() { - const int maxW = GetSystemMetrics (SM_CXCURSOR); - const int maxH = GetSystemMetrics (SM_CYCURSOR); + const int maxW = GetSystemMetrics (SM_CXCURSOR); + const int maxH = GetSystemMetrics (SM_CYCURSOR); - const Image* im = ℑ - Image* newIm = 0; + const Image* im = ℑ + Image* newIm = 0; - if (image.getWidth() > maxW || image.getHeight() > maxH) - { - im = newIm = image.createCopy (maxW, maxH); + if (image.getWidth() > maxW || image.getHeight() > maxH) + { + im = newIm = image.createCopy (maxW, maxH); - hotspotX = (hotspotX * maxW) / image.getWidth(); - hotspotY = (hotspotY * maxH) / image.getHeight(); - } + hotspotX = (hotspotX * maxW) / image.getWidth(); + hotspotY = (hotspotY * maxH) / image.getHeight(); + } - void* cursorH = 0; + void* cursorH = 0; - const SystemStats::OperatingSystemType os = SystemStats::getOperatingSystemType(); + const SystemStats::OperatingSystemType os = SystemStats::getOperatingSystemType(); - if (os == SystemStats::WinXP) - { - cursorH = (void*) createHICONFromImage (*im, FALSE, hotspotX, hotspotY); - } - else - { - const int stride = (maxW + 7) >> 3; - HeapBlock andPlane, xorPlane; - andPlane.calloc (stride * maxH); - xorPlane.calloc (stride * maxH); - int index = 0; + if (os == SystemStats::WinXP) + { + cursorH = (void*) createHICONFromImage (*im, FALSE, hotspotX, hotspotY); + } + else + { + const int stride = (maxW + 7) >> 3; + HeapBlock andPlane, xorPlane; + andPlane.calloc (stride * maxH); + xorPlane.calloc (stride * maxH); + int index = 0; - for (int y = 0; y < maxH; ++y) - { - for (int x = 0; x < maxW; ++x) - { - const unsigned char bit = (unsigned char) (1 << (7 - (x & 7))); + for (int y = 0; y < maxH; ++y) + { + for (int x = 0; x < maxW; ++x) + { + const unsigned char bit = (unsigned char) (1 << (7 - (x & 7))); - const Colour pixelColour (im->getPixelAt (x, y)); + const Colour pixelColour (im->getPixelAt (x, y)); - if (pixelColour.getAlpha() < 127) - andPlane [index + (x >> 3)] |= bit; - else if (pixelColour.getBrightness() >= 0.5f) - xorPlane [index + (x >> 3)] |= bit; - } + if (pixelColour.getAlpha() < 127) + andPlane [index + (x >> 3)] |= bit; + else if (pixelColour.getBrightness() >= 0.5f) + xorPlane [index + (x >> 3)] |= bit; + } - index += stride; - } + index += stride; + } - cursorH = CreateCursor (0, hotspotX, hotspotY, maxW, maxH, andPlane, xorPlane); - } + cursorH = CreateCursor (0, hotspotX, hotspotY, maxW, maxH, andPlane, xorPlane); + } - delete newIm; - return cursorH; + delete newIm; + return cursorH; } void juce_deleteMouseCursor (void* const cursorHandle, const bool isStandard) throw() { - if (cursorHandle != 0 && ! isStandard) - DestroyCursor ((HCURSOR) cursorHandle); + if (cursorHandle != 0 && ! isStandard) + DestroyCursor ((HCURSOR) cursorHandle); } void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type) throw() { - LPCTSTR cursorName = IDC_ARROW; + LPCTSTR cursorName = IDC_ARROW; - switch (type) - { - case MouseCursor::NormalCursor: - cursorName = IDC_ARROW; - break; + switch (type) + { + case MouseCursor::NormalCursor: + cursorName = IDC_ARROW; + break; - case MouseCursor::NoCursor: - return 0; + case MouseCursor::NoCursor: + return 0; - case MouseCursor::DraggingHandCursor: - { - static void* dragHandCursor = 0; + case MouseCursor::DraggingHandCursor: + { + static void* dragHandCursor = 0; - if (dragHandCursor == 0) - { - static const unsigned char dragHandData[] = - { 71,73,70,56,57,97,16,0,16,0,145,2,0,0,0,0,255,255,255,0,0,0,0,0,0,33,249,4,1,0,0,2,0,44,0,0,0,0,16,0, - 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39, 132,117,151,116,132,146,248,60,209,138, - 98,22,203,114,34,236,37,52,77,217,247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 }; + if (dragHandCursor == 0) + { + static const unsigned char dragHandData[] = + { 71,73,70,56,57,97,16,0,16,0,145,2,0,0,0,0,255,255,255,0,0,0,0,0,0,33,249,4,1,0,0,2,0,44,0,0,0,0,16,0, + 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39, 132,117,151,116,132,146,248,60,209,138, + 98,22,203,114,34,236,37,52,77,217,247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 }; - const ScopedPointer image (ImageFileFormat::loadFrom ((const char*) dragHandData, sizeof (dragHandData))); - dragHandCursor = juce_createMouseCursorFromImage (*image, 8, 7); - } + const ScopedPointer image (ImageFileFormat::loadFrom ((const char*) dragHandData, sizeof (dragHandData))); + dragHandCursor = juce_createMouseCursorFromImage (*image, 8, 7); + } - return dragHandCursor; - } + return dragHandCursor; + } - case MouseCursor::WaitCursor: - cursorName = IDC_WAIT; - break; + case MouseCursor::WaitCursor: + cursorName = IDC_WAIT; + break; - case MouseCursor::IBeamCursor: - cursorName = IDC_IBEAM; - break; + case MouseCursor::IBeamCursor: + cursorName = IDC_IBEAM; + break; - case MouseCursor::PointingHandCursor: - cursorName = MAKEINTRESOURCE(32649); - break; + case MouseCursor::PointingHandCursor: + cursorName = MAKEINTRESOURCE(32649); + break; - case MouseCursor::LeftRightResizeCursor: - case MouseCursor::LeftEdgeResizeCursor: - case MouseCursor::RightEdgeResizeCursor: - cursorName = IDC_SIZEWE; - break; + case MouseCursor::LeftRightResizeCursor: + case MouseCursor::LeftEdgeResizeCursor: + case MouseCursor::RightEdgeResizeCursor: + cursorName = IDC_SIZEWE; + break; - case MouseCursor::UpDownResizeCursor: - case MouseCursor::TopEdgeResizeCursor: - case MouseCursor::BottomEdgeResizeCursor: - cursorName = IDC_SIZENS; - break; + case MouseCursor::UpDownResizeCursor: + case MouseCursor::TopEdgeResizeCursor: + case MouseCursor::BottomEdgeResizeCursor: + cursorName = IDC_SIZENS; + break; - case MouseCursor::TopLeftCornerResizeCursor: - case MouseCursor::BottomRightCornerResizeCursor: - cursorName = IDC_SIZENWSE; - break; + case MouseCursor::TopLeftCornerResizeCursor: + case MouseCursor::BottomRightCornerResizeCursor: + cursorName = IDC_SIZENWSE; + break; - case MouseCursor::TopRightCornerResizeCursor: - case MouseCursor::BottomLeftCornerResizeCursor: - cursorName = IDC_SIZENESW; - break; + case MouseCursor::TopRightCornerResizeCursor: + case MouseCursor::BottomLeftCornerResizeCursor: + cursorName = IDC_SIZENESW; + break; - case MouseCursor::UpDownLeftRightResizeCursor: - cursorName = IDC_SIZEALL; - break; + case MouseCursor::UpDownLeftRightResizeCursor: + cursorName = IDC_SIZEALL; + break; - case MouseCursor::CrosshairCursor: - cursorName = IDC_CROSS; - break; + case MouseCursor::CrosshairCursor: + cursorName = IDC_CROSS; + break; - case MouseCursor::CopyingCursor: - // can't seem to find one of these in the win32 list.. - break; - } + case MouseCursor::CopyingCursor: + // can't seem to find one of these in the win32 list.. + break; + } - HCURSOR cursorH = LoadCursor (0, cursorName); + HCURSOR cursorH = LoadCursor (0, cursorName); - if (cursorH == 0) - cursorH = LoadCursor (0, IDC_ARROW); + if (cursorH == 0) + cursorH = LoadCursor (0, IDC_ARROW); - return (void*) cursorH; + return (void*) cursorH; } void MouseCursor::showInWindow (ComponentPeer*) const throw() { - SetCursor ((HCURSOR) getHandle()); + SetCursor ((HCURSOR) getHandle()); } void MouseCursor::showInAllWindows() const throw() { - showInWindow (0); + showInWindow (0); } class JuceDropSource : public IDropSource { - int refCount; + int refCount; public: - JuceDropSource() - : refCount (1) - { - } + JuceDropSource() + : refCount (1) + { + } - virtual ~JuceDropSource() - { - jassert (refCount == 0); - } + virtual ~JuceDropSource() + { + jassert (refCount == 0); + } - HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) - { - if (id == IID_IUnknown || id == IID_IDropSource) - { - AddRef(); - *result = this; - return S_OK; - } + HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) + { + if (id == IID_IUnknown || id == IID_IDropSource) + { + AddRef(); + *result = this; + return S_OK; + } - *result = 0; - return E_NOINTERFACE; - } + *result = 0; + return E_NOINTERFACE; + } - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } - HRESULT __stdcall QueryContinueDrag (BOOL escapePressed, DWORD keys) - { - if (escapePressed) - return DRAGDROP_S_CANCEL; + HRESULT __stdcall QueryContinueDrag (BOOL escapePressed, DWORD keys) + { + if (escapePressed) + return DRAGDROP_S_CANCEL; - if ((keys & (MK_LBUTTON | MK_RBUTTON)) == 0) - return DRAGDROP_S_DROP; + if ((keys & (MK_LBUTTON | MK_RBUTTON)) == 0) + return DRAGDROP_S_DROP; - return S_OK; - } + return S_OK; + } - HRESULT __stdcall GiveFeedback (DWORD) - { - return DRAGDROP_S_USEDEFAULTCURSORS; - } + HRESULT __stdcall GiveFeedback (DWORD) + { + return DRAGDROP_S_USEDEFAULTCURSORS; + } }; class JuceEnumFormatEtc : public IEnumFORMATETC { public: - JuceEnumFormatEtc (const FORMATETC* const format_) - : refCount (1), - format (format_), - index (0) - { - } + JuceEnumFormatEtc (const FORMATETC* const format_) + : refCount (1), + format (format_), + index (0) + { + } - virtual ~JuceEnumFormatEtc() - { - jassert (refCount == 0); - } + virtual ~JuceEnumFormatEtc() + { + jassert (refCount == 0); + } - HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) - { - if (id == IID_IUnknown || id == IID_IEnumFORMATETC) - { - AddRef(); - *result = this; - return S_OK; - } + HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) + { + if (id == IID_IUnknown || id == IID_IEnumFORMATETC) + { + AddRef(); + *result = this; + return S_OK; + } - *result = 0; - return E_NOINTERFACE; - } + *result = 0; + return E_NOINTERFACE; + } - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } - HRESULT __stdcall Clone (IEnumFORMATETC** result) - { - if (result == 0) - return E_POINTER; + HRESULT __stdcall Clone (IEnumFORMATETC** result) + { + if (result == 0) + return E_POINTER; - JuceEnumFormatEtc* const newOne = new JuceEnumFormatEtc (format); - newOne->index = index; + JuceEnumFormatEtc* const newOne = new JuceEnumFormatEtc (format); + newOne->index = index; - *result = newOne; - return S_OK; - } + *result = newOne; + return S_OK; + } - HRESULT __stdcall Next (ULONG celt, LPFORMATETC lpFormatEtc, ULONG* pceltFetched) - { - if (pceltFetched != 0) - *pceltFetched = 0; - else if (celt != 1) - return S_FALSE; + HRESULT __stdcall Next (ULONG celt, LPFORMATETC lpFormatEtc, ULONG* pceltFetched) + { + if (pceltFetched != 0) + *pceltFetched = 0; + else if (celt != 1) + return S_FALSE; - if (index == 0 && celt > 0 && lpFormatEtc != 0) - { - copyFormatEtc (lpFormatEtc [0], *format); - ++index; + if (index == 0 && celt > 0 && lpFormatEtc != 0) + { + copyFormatEtc (lpFormatEtc [0], *format); + ++index; - if (pceltFetched != 0) - *pceltFetched = 1; + if (pceltFetched != 0) + *pceltFetched = 1; - return S_OK; - } + return S_OK; + } - return S_FALSE; - } + return S_FALSE; + } - HRESULT __stdcall Skip (ULONG celt) - { - if (index + (int) celt >= 1) - return S_FALSE; + HRESULT __stdcall Skip (ULONG celt) + { + if (index + (int) celt >= 1) + return S_FALSE; - index += celt; - return S_OK; - } + index += celt; + return S_OK; + } - HRESULT __stdcall Reset() - { - index = 0; - return S_OK; - } + HRESULT __stdcall Reset() + { + index = 0; + return S_OK; + } private: - int refCount; - const FORMATETC* const format; - int index; + int refCount; + const FORMATETC* const format; + int index; - static void copyFormatEtc (FORMATETC& dest, const FORMATETC& source) - { - dest = source; + static void copyFormatEtc (FORMATETC& dest, const FORMATETC& source) + { + dest = source; - if (source.ptd != 0) - { - dest.ptd = (DVTARGETDEVICE*) CoTaskMemAlloc (sizeof (DVTARGETDEVICE)); - *(dest.ptd) = *(source.ptd); - } - } + if (source.ptd != 0) + { + dest.ptd = (DVTARGETDEVICE*) CoTaskMemAlloc (sizeof (DVTARGETDEVICE)); + *(dest.ptd) = *(source.ptd); + } + } - JuceEnumFormatEtc (const JuceEnumFormatEtc&); - const JuceEnumFormatEtc& operator= (const JuceEnumFormatEtc&); + JuceEnumFormatEtc (const JuceEnumFormatEtc&); + const JuceEnumFormatEtc& operator= (const JuceEnumFormatEtc&); }; class JuceDataObject : public IDataObject { - JuceDropSource* const dropSource; - const FORMATETC* const format; - const STGMEDIUM* const medium; - int refCount; + JuceDropSource* const dropSource; + const FORMATETC* const format; + const STGMEDIUM* const medium; + int refCount; - JuceDataObject (const JuceDataObject&); - const JuceDataObject& operator= (const JuceDataObject&); + JuceDataObject (const JuceDataObject&); + const JuceDataObject& operator= (const JuceDataObject&); public: - JuceDataObject (JuceDropSource* const dropSource_, - const FORMATETC* const format_, - const STGMEDIUM* const medium_) - : dropSource (dropSource_), - format (format_), - medium (medium_), - refCount (1) - { - } + JuceDataObject (JuceDropSource* const dropSource_, + const FORMATETC* const format_, + const STGMEDIUM* const medium_) + : dropSource (dropSource_), + format (format_), + medium (medium_), + refCount (1) + { + } - virtual ~JuceDataObject() - { - jassert (refCount == 0); - } + virtual ~JuceDataObject() + { + jassert (refCount == 0); + } - HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) - { - if (id == IID_IUnknown || id == IID_IDataObject) - { - AddRef(); - *result = this; - return S_OK; - } + HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) + { + if (id == IID_IUnknown || id == IID_IDataObject) + { + AddRef(); + *result = this; + return S_OK; + } - *result = 0; - return E_NOINTERFACE; - } + *result = 0; + return E_NOINTERFACE; + } - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } - HRESULT __stdcall GetData (FORMATETC __RPC_FAR* pFormatEtc, STGMEDIUM __RPC_FAR* pMedium) - { - if (pFormatEtc->tymed == format->tymed - && pFormatEtc->cfFormat == format->cfFormat - && pFormatEtc->dwAspect == format->dwAspect) - { - pMedium->tymed = format->tymed; - pMedium->pUnkForRelease = 0; + HRESULT __stdcall GetData (FORMATETC __RPC_FAR* pFormatEtc, STGMEDIUM __RPC_FAR* pMedium) + { + if (pFormatEtc->tymed == format->tymed + && pFormatEtc->cfFormat == format->cfFormat + && pFormatEtc->dwAspect == format->dwAspect) + { + pMedium->tymed = format->tymed; + pMedium->pUnkForRelease = 0; - if (format->tymed == TYMED_HGLOBAL) - { - const SIZE_T len = GlobalSize (medium->hGlobal); - void* const src = GlobalLock (medium->hGlobal); - void* const dst = GlobalAlloc (GMEM_FIXED, len); + if (format->tymed == TYMED_HGLOBAL) + { + const SIZE_T len = GlobalSize (medium->hGlobal); + void* const src = GlobalLock (medium->hGlobal); + void* const dst = GlobalAlloc (GMEM_FIXED, len); - memcpy (dst, src, len); + memcpy (dst, src, len); - GlobalUnlock (medium->hGlobal); + GlobalUnlock (medium->hGlobal); - pMedium->hGlobal = dst; - return S_OK; - } - } + pMedium->hGlobal = dst; + return S_OK; + } + } - return DV_E_FORMATETC; - } + return DV_E_FORMATETC; + } - HRESULT __stdcall QueryGetData (FORMATETC __RPC_FAR* f) - { - if (f == 0) - return E_INVALIDARG; + HRESULT __stdcall QueryGetData (FORMATETC __RPC_FAR* f) + { + if (f == 0) + return E_INVALIDARG; - if (f->tymed == format->tymed - && f->cfFormat == format->cfFormat - && f->dwAspect == format->dwAspect) - return S_OK; + if (f->tymed == format->tymed + && f->cfFormat == format->cfFormat + && f->dwAspect == format->dwAspect) + return S_OK; - return DV_E_FORMATETC; - } + return DV_E_FORMATETC; + } - HRESULT __stdcall GetCanonicalFormatEtc (FORMATETC __RPC_FAR*, FORMATETC __RPC_FAR* pFormatEtcOut) - { - pFormatEtcOut->ptd = 0; - return E_NOTIMPL; - } + HRESULT __stdcall GetCanonicalFormatEtc (FORMATETC __RPC_FAR*, FORMATETC __RPC_FAR* pFormatEtcOut) + { + pFormatEtcOut->ptd = 0; + return E_NOTIMPL; + } - HRESULT __stdcall EnumFormatEtc (DWORD direction, IEnumFORMATETC __RPC_FAR *__RPC_FAR *result) - { - if (result == 0) - return E_POINTER; + HRESULT __stdcall EnumFormatEtc (DWORD direction, IEnumFORMATETC __RPC_FAR *__RPC_FAR *result) + { + if (result == 0) + return E_POINTER; - if (direction == DATADIR_GET) - { - *result = new JuceEnumFormatEtc (format); - return S_OK; - } + if (direction == DATADIR_GET) + { + *result = new JuceEnumFormatEtc (format); + return S_OK; + } - *result = 0; - return E_NOTIMPL; - } + *result = 0; + return E_NOTIMPL; + } - HRESULT __stdcall GetDataHere (FORMATETC __RPC_FAR*, STGMEDIUM __RPC_FAR*) { return DATA_E_FORMATETC; } - HRESULT __stdcall SetData (FORMATETC __RPC_FAR*, STGMEDIUM __RPC_FAR*, BOOL) { return E_NOTIMPL; } - HRESULT __stdcall DAdvise (FORMATETC __RPC_FAR*, DWORD, IAdviseSink __RPC_FAR*, DWORD __RPC_FAR*) { return OLE_E_ADVISENOTSUPPORTED; } - HRESULT __stdcall DUnadvise (DWORD) { return E_NOTIMPL; } - HRESULT __stdcall EnumDAdvise (IEnumSTATDATA __RPC_FAR *__RPC_FAR *) { return OLE_E_ADVISENOTSUPPORTED; } + HRESULT __stdcall GetDataHere (FORMATETC __RPC_FAR*, STGMEDIUM __RPC_FAR*) { return DATA_E_FORMATETC; } + HRESULT __stdcall SetData (FORMATETC __RPC_FAR*, STGMEDIUM __RPC_FAR*, BOOL) { return E_NOTIMPL; } + HRESULT __stdcall DAdvise (FORMATETC __RPC_FAR*, DWORD, IAdviseSink __RPC_FAR*, DWORD __RPC_FAR*) { return OLE_E_ADVISENOTSUPPORTED; } + HRESULT __stdcall DUnadvise (DWORD) { return E_NOTIMPL; } + HRESULT __stdcall EnumDAdvise (IEnumSTATDATA __RPC_FAR *__RPC_FAR *) { return OLE_E_ADVISENOTSUPPORTED; } }; static HDROP createHDrop (const StringArray& fileNames) throw() { - int totalChars = 0; - for (int i = fileNames.size(); --i >= 0;) - totalChars += fileNames[i].length() + 1; + int totalChars = 0; + for (int i = fileNames.size(); --i >= 0;) + totalChars += fileNames[i].length() + 1; - HDROP hDrop = (HDROP) GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, - sizeof (DROPFILES) - + sizeof (WCHAR) * (totalChars + 2)); + HDROP hDrop = (HDROP) GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, + sizeof (DROPFILES) + + sizeof (WCHAR) * (totalChars + 2)); - if (hDrop != 0) - { - LPDROPFILES pDropFiles = (LPDROPFILES) GlobalLock (hDrop); - pDropFiles->pFiles = sizeof (DROPFILES); + if (hDrop != 0) + { + LPDROPFILES pDropFiles = (LPDROPFILES) GlobalLock (hDrop); + pDropFiles->pFiles = sizeof (DROPFILES); - pDropFiles->fWide = true; + pDropFiles->fWide = true; - WCHAR* fname = (WCHAR*) (((char*) pDropFiles) + sizeof (DROPFILES)); + WCHAR* fname = (WCHAR*) (((char*) pDropFiles) + sizeof (DROPFILES)); - for (int i = 0; i < fileNames.size(); ++i) - { - fileNames[i].copyToBuffer (fname, 2048); - fname += fileNames[i].length() + 1; - } + for (int i = 0; i < fileNames.size(); ++i) + { + fileNames[i].copyToBuffer (fname, 2048); + fname += fileNames[i].length() + 1; + } - *fname = 0; + *fname = 0; - GlobalUnlock (hDrop); - } + GlobalUnlock (hDrop); + } - return hDrop; + return hDrop; } static bool performDragDrop (FORMATETC* const format, STGMEDIUM* const medium, const DWORD whatToDo) throw() { - JuceDropSource* const source = new JuceDropSource(); - JuceDataObject* const data = new JuceDataObject (source, format, medium); + JuceDropSource* const source = new JuceDropSource(); + JuceDataObject* const data = new JuceDataObject (source, format, medium); - DWORD effect; - const HRESULT res = DoDragDrop (data, source, whatToDo, &effect); + DWORD effect; + const HRESULT res = DoDragDrop (data, source, whatToDo, &effect); - data->Release(); - source->Release(); + data->Release(); + source->Release(); - return res == DRAGDROP_S_DROP; + return res == DRAGDROP_S_DROP; } bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, const bool canMove) { - FORMATETC format = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - STGMEDIUM medium = { TYMED_HGLOBAL, { 0 }, 0 }; + FORMATETC format = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM medium = { TYMED_HGLOBAL, { 0 }, 0 }; - medium.hGlobal = createHDrop (files); + medium.hGlobal = createHDrop (files); - return performDragDrop (&format, &medium, canMove ? (DROPEFFECT_COPY | DROPEFFECT_MOVE) - : DROPEFFECT_COPY); + return performDragDrop (&format, &medium, canMove ? (DROPEFFECT_COPY | DROPEFFECT_MOVE) + : DROPEFFECT_COPY); } bool DragAndDropContainer::performExternalDragDropOfText (const String& text) { - FORMATETC format = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - STGMEDIUM medium = { TYMED_HGLOBAL, { 0 }, 0 }; + FORMATETC format = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM medium = { TYMED_HGLOBAL, { 0 }, 0 }; - const int numChars = text.length(); + const int numChars = text.length(); - medium.hGlobal = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, (numChars + 2) * sizeof (WCHAR)); - char* d = (char*) GlobalLock (medium.hGlobal); + medium.hGlobal = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, (numChars + 2) * sizeof (WCHAR)); + char* d = (char*) GlobalLock (medium.hGlobal); - text.copyToBuffer ((WCHAR*) d, numChars + 1); - format.cfFormat = CF_UNICODETEXT; + text.copyToBuffer ((WCHAR*) d, numChars + 1); + format.cfFormat = CF_UNICODETEXT; - GlobalUnlock (medium.hGlobal); + GlobalUnlock (medium.hGlobal); - return performDragDrop (&format, &medium, DROPEFFECT_COPY | DROPEFFECT_MOVE); + return performDragDrop (&format, &medium, DROPEFFECT_COPY | DROPEFFECT_MOVE); } #endif @@ -239772,214 +217520,214 @@ bool DragAndDropContainer::performExternalDragDropOfText (const String& text) #if JUCE_INCLUDED_FILE static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe, - NEWTEXTMETRICEXW*, - int type, - LPARAM lParam) + NEWTEXTMETRICEXW*, + int type, + LPARAM lParam) { - if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) - { - const String fontName (lpelfe->elfLogFont.lfFaceName); + if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) + { + const String fontName (lpelfe->elfLogFont.lfFaceName); - ((StringArray*) lParam)->addIfNotAlreadyThere (fontName.removeCharacters (T("@"))); - } + ((StringArray*) lParam)->addIfNotAlreadyThere (fontName.removeCharacters (T("@"))); + } - return 1; + return 1; } static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, - NEWTEXTMETRICEXW*, - int type, - LPARAM lParam) + NEWTEXTMETRICEXW*, + int type, + LPARAM lParam) { - if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) - { - LOGFONTW lf; - zerostruct (lf); + if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) + { + LOGFONTW lf; + zerostruct (lf); - lf.lfWeight = FW_DONTCARE; - lf.lfOutPrecision = OUT_OUTLINE_PRECIS; - lf.lfQuality = DEFAULT_QUALITY; - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfPitchAndFamily = FF_DONTCARE; + lf.lfWeight = FW_DONTCARE; + lf.lfOutPrecision = OUT_OUTLINE_PRECIS; + lf.lfQuality = DEFAULT_QUALITY; + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfPitchAndFamily = FF_DONTCARE; - const String fontName (lpelfe->elfLogFont.lfFaceName); - fontName.copyToBuffer (lf.lfFaceName, LF_FACESIZE - 1); + const String fontName (lpelfe->elfLogFont.lfFaceName); + fontName.copyToBuffer (lf.lfFaceName, LF_FACESIZE - 1); - HDC dc = CreateCompatibleDC (0); - EnumFontFamiliesEx (dc, &lf, - (FONTENUMPROCW) &wfontEnum2, - lParam, 0); - DeleteDC (dc); - } + HDC dc = CreateCompatibleDC (0); + EnumFontFamiliesEx (dc, &lf, + (FONTENUMPROCW) &wfontEnum2, + lParam, 0); + DeleteDC (dc); + } - return 1; + return 1; } const StringArray Font::findAllTypefaceNames() throw() { - StringArray results; - HDC dc = CreateCompatibleDC (0); + StringArray results; + HDC dc = CreateCompatibleDC (0); - { - LOGFONTW lf; - zerostruct (lf); + { + LOGFONTW lf; + zerostruct (lf); - lf.lfWeight = FW_DONTCARE; - lf.lfOutPrecision = OUT_OUTLINE_PRECIS; - lf.lfQuality = DEFAULT_QUALITY; - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfPitchAndFamily = FF_DONTCARE; - lf.lfFaceName[0] = 0; + lf.lfWeight = FW_DONTCARE; + lf.lfOutPrecision = OUT_OUTLINE_PRECIS; + lf.lfQuality = DEFAULT_QUALITY; + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfPitchAndFamily = FF_DONTCARE; + lf.lfFaceName[0] = 0; - EnumFontFamiliesEx (dc, &lf, - (FONTENUMPROCW) &wfontEnum1, - (LPARAM) &results, 0); - } + EnumFontFamiliesEx (dc, &lf, + (FONTENUMPROCW) &wfontEnum1, + (LPARAM) &results, 0); + } - DeleteDC (dc); + DeleteDC (dc); - results.sort (true); - return results; + results.sort (true); + return results; } -extern bool juce_IsRunningInWine() throw(); +extern bool juce_IsRunningInWine(); void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed) throw() { - if (juce_IsRunningInWine()) - { - // If we're running in Wine, then use fonts that might be available on Linux.. - defaultSans = "Bitstream Vera Sans"; - defaultSerif = "Bitstream Vera Serif"; - defaultFixed = "Bitstream Vera Sans Mono"; - } - else - { - defaultSans = "Verdana"; - defaultSerif = "Times"; - defaultFixed = "Lucida Console"; - } + if (juce_IsRunningInWine()) + { + // If we're running in Wine, then use fonts that might be available on Linux.. + defaultSans = "Bitstream Vera Sans"; + defaultSerif = "Bitstream Vera Serif"; + defaultFixed = "Bitstream Vera Sans Mono"; + } + else + { + defaultSans = "Verdana"; + defaultSerif = "Times"; + defaultFixed = "Lucida Console"; + } } class FontDCHolder : private DeletedAtShutdown { public: - FontDCHolder() throw() - : dc (0), numKPs (0), size (0), - bold (false), italic (false) - { - } + FontDCHolder() throw() + : dc (0), numKPs (0), size (0), + bold (false), italic (false) + { + } - ~FontDCHolder() throw() - { - if (dc != 0) - { - DeleteDC (dc); - DeleteObject (fontH); - } + ~FontDCHolder() throw() + { + if (dc != 0) + { + DeleteDC (dc); + DeleteObject (fontH); + } - clearSingletonInstance(); - } + clearSingletonInstance(); + } - juce_DeclareSingleton_SingleThreaded_Minimal (FontDCHolder); + juce_DeclareSingleton_SingleThreaded_Minimal (FontDCHolder); - HDC loadFont (const String& fontName_, const bool bold_, const bool italic_, const int size_) throw() - { - if (fontName != fontName_ || bold != bold_ || italic != italic_ || size != size_) - { - fontName = fontName_; - bold = bold_; - italic = italic_; - size = size_; + HDC loadFont (const String& fontName_, const bool bold_, const bool italic_, const int size_) throw() + { + if (fontName != fontName_ || bold != bold_ || italic != italic_ || size != size_) + { + fontName = fontName_; + bold = bold_; + italic = italic_; + size = size_; - if (dc != 0) - { - DeleteDC (dc); - DeleteObject (fontH); - kps.free(); - } + if (dc != 0) + { + DeleteDC (dc); + DeleteObject (fontH); + kps.free(); + } - fontH = 0; + fontH = 0; - dc = CreateCompatibleDC (0); - SetMapperFlags (dc, 0); - SetMapMode (dc, MM_TEXT); + dc = CreateCompatibleDC (0); + SetMapperFlags (dc, 0); + SetMapMode (dc, MM_TEXT); - LOGFONTW lfw; - zerostruct (lfw); + LOGFONTW lfw; + zerostruct (lfw); - lfw.lfCharSet = DEFAULT_CHARSET; - lfw.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lfw.lfOutPrecision = OUT_OUTLINE_PRECIS; - lfw.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; - lfw.lfQuality = PROOF_QUALITY; - lfw.lfItalic = (BYTE) (italic ? TRUE : FALSE); - lfw.lfWeight = bold ? FW_BOLD : FW_NORMAL; - fontName.copyToBuffer (lfw.lfFaceName, LF_FACESIZE - 1); + lfw.lfCharSet = DEFAULT_CHARSET; + lfw.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lfw.lfOutPrecision = OUT_OUTLINE_PRECIS; + lfw.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + lfw.lfQuality = PROOF_QUALITY; + lfw.lfItalic = (BYTE) (italic ? TRUE : FALSE); + lfw.lfWeight = bold ? FW_BOLD : FW_NORMAL; + fontName.copyToBuffer (lfw.lfFaceName, LF_FACESIZE - 1); - lfw.lfHeight = size > 0 ? size : -256; - HFONT standardSizedFont = CreateFontIndirect (&lfw); + lfw.lfHeight = size > 0 ? size : -256; + HFONT standardSizedFont = CreateFontIndirect (&lfw); - if (standardSizedFont != 0) - { - if (SelectObject (dc, standardSizedFont) != 0) - { - fontH = standardSizedFont; + if (standardSizedFont != 0) + { + if (SelectObject (dc, standardSizedFont) != 0) + { + fontH = standardSizedFont; - if (size == 0) - { - OUTLINETEXTMETRIC otm; - if (GetOutlineTextMetrics (dc, sizeof (otm), &otm) != 0) - { - lfw.lfHeight = -(int) otm.otmEMSquare; - fontH = CreateFontIndirect (&lfw); + if (size == 0) + { + OUTLINETEXTMETRIC otm; + if (GetOutlineTextMetrics (dc, sizeof (otm), &otm) != 0) + { + lfw.lfHeight = -(int) otm.otmEMSquare; + fontH = CreateFontIndirect (&lfw); - SelectObject (dc, fontH); - DeleteObject (standardSizedFont); - } - } - } - else - { - jassertfalse - } - } - else - { - jassertfalse - } - } + SelectObject (dc, fontH); + DeleteObject (standardSizedFont); + } + } + } + else + { + jassertfalse + } + } + else + { + jassertfalse + } + } - return dc; - } + return dc; + } - KERNINGPAIR* getKerningPairs (int& numKPs_) throw() - { - if (kps == 0) - { - numKPs = GetKerningPairs (dc, 0, 0); - kps.calloc (numKPs); - GetKerningPairs (dc, numKPs, kps); - } + KERNINGPAIR* getKerningPairs (int& numKPs_) throw() + { + if (kps == 0) + { + numKPs = GetKerningPairs (dc, 0, 0); + kps.calloc (numKPs); + GetKerningPairs (dc, numKPs, kps); + } - numKPs_ = numKPs; - return kps; - } + numKPs_ = numKPs; + return kps; + } private: - HFONT fontH; - HDC dc; - String fontName; - HeapBlock kps; - int numKPs, size; - bool bold, italic; + HFONT fontH; + HDC dc; + String fontName; + HeapBlock kps; + int numKPs, size; + bool bold, italic; - FontDCHolder (const FontDCHolder&); - const FontDCHolder& operator= (const FontDCHolder&); + FontDCHolder (const FontDCHolder&); + const FontDCHolder& operator= (const FontDCHolder&); }; juce_ImplementSingleton_SingleThreaded (FontDCHolder); @@ -239987,145 +217735,145 @@ juce_ImplementSingleton_SingleThreaded (FontDCHolder); class WindowsTypeface : public CustomTypeface { public: - WindowsTypeface (const Font& font) - { - HDC dc = FontDCHolder::getInstance()->loadFont (font.getTypefaceName(), - font.isBold(), font.isItalic(), 0); + WindowsTypeface (const Font& font) + { + HDC dc = FontDCHolder::getInstance()->loadFont (font.getTypefaceName(), + font.isBold(), font.isItalic(), 0); - TEXTMETRIC tm; - tm.tmAscent = tm.tmHeight = 1; - tm.tmDefaultChar = 0; - GetTextMetrics (dc, &tm); + TEXTMETRIC tm; + tm.tmAscent = tm.tmHeight = 1; + tm.tmDefaultChar = 0; + GetTextMetrics (dc, &tm); - setCharacteristics (font.getTypefaceName(), - tm.tmAscent / (float) tm.tmHeight, - font.isBold(), font.isItalic(), - tm.tmDefaultChar); - } + setCharacteristics (font.getTypefaceName(), + tm.tmAscent / (float) tm.tmHeight, + font.isBold(), font.isItalic(), + tm.tmDefaultChar); + } - bool loadGlyphIfPossible (const juce_wchar character) - { - HDC dc = FontDCHolder::getInstance()->loadFont (name, isBold, isItalic, 0); + bool loadGlyphIfPossible (const juce_wchar character) + { + HDC dc = FontDCHolder::getInstance()->loadFont (name, isBold, isItalic, 0); - GLYPHMETRICS gm; + GLYPHMETRICS gm; - { - const WCHAR charToTest[] = { (WCHAR) character, 0 }; - WORD index = 0; + { + const WCHAR charToTest[] = { (WCHAR) character, 0 }; + WORD index = 0; - if (GetGlyphIndices (dc, charToTest, 1, &index, GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR - && index == 0xffff) - { - return false; - } - } + if (GetGlyphIndices (dc, charToTest, 1, &index, GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR + && index == 0xffff) + { + return false; + } + } - Path glyphPath; + Path glyphPath; - TEXTMETRIC tm; - if (! GetTextMetrics (dc, &tm)) - { - addGlyph (character, glyphPath, 0); - return true; - } + TEXTMETRIC tm; + if (! GetTextMetrics (dc, &tm)) + { + addGlyph (character, glyphPath, 0); + return true; + } - const float height = (float) tm.tmHeight; - static const MAT2 identityMatrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; + const float height = (float) tm.tmHeight; + static const MAT2 identityMatrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; - const int bufSize = GetGlyphOutline (dc, character, GGO_NATIVE, - &gm, 0, 0, &identityMatrix); + const int bufSize = GetGlyphOutline (dc, character, GGO_NATIVE, + &gm, 0, 0, &identityMatrix); - if (bufSize > 0) - { - HeapBlock data (bufSize); + if (bufSize > 0) + { + HeapBlock data (bufSize); - GetGlyphOutline (dc, character, GGO_NATIVE, &gm, - bufSize, data, &identityMatrix); + GetGlyphOutline (dc, character, GGO_NATIVE, &gm, + bufSize, data, &identityMatrix); - const TTPOLYGONHEADER* pheader = (TTPOLYGONHEADER*) data; + const TTPOLYGONHEADER* pheader = (TTPOLYGONHEADER*) data; - const float scaleX = 1.0f / height; - const float scaleY = -1.0f / height; + const float scaleX = 1.0f / height; + const float scaleY = -1.0f / height; - while ((char*) pheader < data + bufSize) - { - #define remapX(v) (scaleX * (v).x.value) - #define remapY(v) (scaleY * (v).y.value) + while ((char*) pheader < data + bufSize) + { + #define remapX(v) (scaleX * (v).x.value) + #define remapY(v) (scaleY * (v).y.value) - float x = remapX (pheader->pfxStart); - float y = remapY (pheader->pfxStart); + float x = remapX (pheader->pfxStart); + float y = remapY (pheader->pfxStart); - glyphPath.startNewSubPath (x, y); + glyphPath.startNewSubPath (x, y); - const TTPOLYCURVE* curve = (const TTPOLYCURVE*) ((const char*) pheader + sizeof (TTPOLYGONHEADER)); - const char* const curveEnd = ((const char*) pheader) + pheader->cb; + const TTPOLYCURVE* curve = (const TTPOLYCURVE*) ((const char*) pheader + sizeof (TTPOLYGONHEADER)); + const char* const curveEnd = ((const char*) pheader) + pheader->cb; - while ((const char*) curve < curveEnd) - { - if (curve->wType == TT_PRIM_LINE) - { - for (int i = 0; i < curve->cpfx; ++i) - { - x = remapX (curve->apfx [i]); - y = remapY (curve->apfx [i]); + while ((const char*) curve < curveEnd) + { + if (curve->wType == TT_PRIM_LINE) + { + for (int i = 0; i < curve->cpfx; ++i) + { + x = remapX (curve->apfx [i]); + y = remapY (curve->apfx [i]); - glyphPath.lineTo (x, y); - } - } - else if (curve->wType == TT_PRIM_QSPLINE) - { - for (int i = 0; i < curve->cpfx - 1; ++i) - { - const float x2 = remapX (curve->apfx [i]); - const float y2 = remapY (curve->apfx [i]); - float x3, y3; + glyphPath.lineTo (x, y); + } + } + else if (curve->wType == TT_PRIM_QSPLINE) + { + for (int i = 0; i < curve->cpfx - 1; ++i) + { + const float x2 = remapX (curve->apfx [i]); + const float y2 = remapY (curve->apfx [i]); + float x3, y3; - if (i < curve->cpfx - 2) - { - x3 = 0.5f * (x2 + remapX (curve->apfx [i + 1])); - y3 = 0.5f * (y2 + remapY (curve->apfx [i + 1])); - } - else - { - x3 = remapX (curve->apfx [i + 1]); - y3 = remapY (curve->apfx [i + 1]); - } + if (i < curve->cpfx - 2) + { + x3 = 0.5f * (x2 + remapX (curve->apfx [i + 1])); + y3 = 0.5f * (y2 + remapY (curve->apfx [i + 1])); + } + else + { + x3 = remapX (curve->apfx [i + 1]); + y3 = remapY (curve->apfx [i + 1]); + } - glyphPath.quadraticTo (x2, y2, x3, y3); + glyphPath.quadraticTo (x2, y2, x3, y3); - x = x3; - y = y3; - } - } + x = x3; + y = y3; + } + } - curve = (const TTPOLYCURVE*) &(curve->apfx [curve->cpfx]); - } + curve = (const TTPOLYCURVE*) &(curve->apfx [curve->cpfx]); + } - pheader = (const TTPOLYGONHEADER*) curve; + pheader = (const TTPOLYGONHEADER*) curve; - glyphPath.closeSubPath(); - } - } + glyphPath.closeSubPath(); + } + } - addGlyph (character, glyphPath, gm.gmCellIncX / height); + addGlyph (character, glyphPath, gm.gmCellIncX / height); - int numKPs; - const KERNINGPAIR* const kps = FontDCHolder::getInstance()->getKerningPairs (numKPs); + int numKPs; + const KERNINGPAIR* const kps = FontDCHolder::getInstance()->getKerningPairs (numKPs); - for (int i = 0; i < numKPs; ++i) - { - if (kps[i].wFirst == character) - addKerningPair (kps[i].wFirst, kps[i].wSecond, - kps[i].iKernAmount / height); - } + for (int i = 0; i < numKPs; ++i) + { + if (kps[i].wFirst == character) + addKerningPair (kps[i].wFirst, kps[i].wSecond, + kps[i].iKernAmount / height); + } - return true; - } + return true; + } }; const Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) { - return new WindowsTypeface (font); + return new WindowsTypeface (font); } #endif @@ -240142,303 +217890,303 @@ static Component* currentExtraFileWin = 0; static bool areThereAnyAlwaysOnTopWindows() { - for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) - { - Component* c = Desktop::getInstance().getComponent (i); + for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) + { + Component* c = Desktop::getInstance().getComponent (i); - if (c != 0 && c->isAlwaysOnTop() && c->isShowing()) - return true; - } + if (c != 0 && c->isAlwaysOnTop() && c->isShowing()) + return true; + } - return false; + return false; } static int CALLBACK browseCallbackProc (HWND hWnd, UINT msg, LPARAM lParam, LPARAM /*lpData*/) { - if (msg == BFFM_INITIALIZED) - { - SendMessage (hWnd, BFFM_SETSELECTIONW, TRUE, (LPARAM) defaultDirPath); - } - else if (msg == BFFM_VALIDATEFAILEDW) - { - returnedString = (LPCWSTR) lParam; - } - else if (msg == BFFM_VALIDATEFAILEDA) - { - returnedString = (const char*) lParam; - } + if (msg == BFFM_INITIALIZED) + { + SendMessage (hWnd, BFFM_SETSELECTIONW, TRUE, (LPARAM) defaultDirPath); + } + else if (msg == BFFM_VALIDATEFAILEDW) + { + returnedString = (LPCWSTR) lParam; + } + else if (msg == BFFM_VALIDATEFAILEDA) + { + returnedString = (const char*) lParam; + } - return 0; + return 0; } void juce_setWindowStyleBit (HWND h, const int styleType, const int feature, const bool bitIsSet) throw(); static UINT_PTR CALLBACK openCallback (HWND hdlg, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam) { - if (currentExtraFileWin != 0) - { - if (uiMsg == WM_INITDIALOG) - { - HWND dialogH = GetParent (hdlg); - jassert (dialogH != 0); - if (dialogH == 0) - dialogH = hdlg; + if (currentExtraFileWin != 0) + { + if (uiMsg == WM_INITDIALOG) + { + HWND dialogH = GetParent (hdlg); + jassert (dialogH != 0); + if (dialogH == 0) + dialogH = hdlg; - RECT r, cr; - GetWindowRect (dialogH, &r); - GetClientRect (dialogH, &cr); + RECT r, cr; + GetWindowRect (dialogH, &r); + GetClientRect (dialogH, &cr); - SetWindowPos (dialogH, 0, - r.left, r.top, - currentExtraFileWin->getWidth() + jmax (150, r.right - r.left), - jmax (150, r.bottom - r.top), - SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); + SetWindowPos (dialogH, 0, + r.left, r.top, + currentExtraFileWin->getWidth() + jmax (150, (int) (r.right - r.left)), + jmax (150, (int) (r.bottom - r.top)), + SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); - currentExtraFileWin->setBounds (cr.right, cr.top, currentExtraFileWin->getWidth(), cr.bottom - cr.top); - currentExtraFileWin->getChildComponent(0)->setBounds (0, 0, currentExtraFileWin->getWidth(), currentExtraFileWin->getHeight()); + currentExtraFileWin->setBounds (cr.right, cr.top, currentExtraFileWin->getWidth(), cr.bottom - cr.top); + currentExtraFileWin->getChildComponent(0)->setBounds (0, 0, currentExtraFileWin->getWidth(), currentExtraFileWin->getHeight()); - SetParent ((HWND) currentExtraFileWin->getWindowHandle(), (HWND) dialogH); - juce_setWindowStyleBit ((HWND)currentExtraFileWin->getWindowHandle(), GWL_STYLE, WS_CHILD, (dialogH != 0)); - juce_setWindowStyleBit ((HWND)currentExtraFileWin->getWindowHandle(), GWL_STYLE, WS_POPUP, (dialogH == 0)); - } - else if (uiMsg == WM_NOTIFY) - { - LPOFNOTIFY ofn = (LPOFNOTIFY) lParam; + SetParent ((HWND) currentExtraFileWin->getWindowHandle(), (HWND) dialogH); + juce_setWindowStyleBit ((HWND)currentExtraFileWin->getWindowHandle(), GWL_STYLE, WS_CHILD, (dialogH != 0)); + juce_setWindowStyleBit ((HWND)currentExtraFileWin->getWindowHandle(), GWL_STYLE, WS_POPUP, (dialogH == 0)); + } + else if (uiMsg == WM_NOTIFY) + { + LPOFNOTIFY ofn = (LPOFNOTIFY) lParam; - if (ofn->hdr.code == CDN_SELCHANGE) - { - FilePreviewComponent* comp = (FilePreviewComponent*) currentExtraFileWin->getChildComponent(0); + if (ofn->hdr.code == CDN_SELCHANGE) + { + FilePreviewComponent* comp = (FilePreviewComponent*) currentExtraFileWin->getChildComponent(0); - if (comp != 0) - { - TCHAR path [MAX_PATH * 2]; - path[0] = 0; - CommDlg_OpenSave_GetFilePath (GetParent (hdlg), (LPARAM) &path, MAX_PATH); + if (comp != 0) + { + TCHAR path [MAX_PATH * 2]; + path[0] = 0; + CommDlg_OpenSave_GetFilePath (GetParent (hdlg), (LPARAM) &path, MAX_PATH); - const String fn ((const WCHAR*) path); + const String fn ((const WCHAR*) path); - comp->selectedFileChanged (File (fn)); - } - } - } - } + comp->selectedFileChanged (File (fn)); + } + } + } + } - return 0; + return 0; } class FPComponentHolder : public Component { public: - FPComponentHolder() - { - setVisible (true); - setOpaque (true); - } + FPComponentHolder() + { + setVisible (true); + setOpaque (true); + } - ~FPComponentHolder() - { - } + ~FPComponentHolder() + { + } - void paint (Graphics& g) - { - g.fillAll (Colours::lightgrey); - } + void paint (Graphics& g) + { + g.fillAll (Colours::lightgrey); + } private: - FPComponentHolder (const FPComponentHolder&); - const FPComponentHolder& operator= (const FPComponentHolder&); + FPComponentHolder (const FPComponentHolder&); + const FPComponentHolder& operator= (const FPComponentHolder&); }; void FileChooser::showPlatformDialog (OwnedArray& results, - const String& title, - const File& currentFileOrDirectory, - const String& filter, - bool selectsDirectory, - bool selectsFiles, - bool isSaveDialogue, - bool warnAboutOverwritingExistingFiles, - bool selectMultipleFiles, - FilePreviewComponent* extraInfoComponent) + const String& title, + const File& currentFileOrDirectory, + const String& filter, + bool selectsDirectory, + bool selectsFiles, + bool isSaveDialogue, + bool warnAboutOverwritingExistingFiles, + bool selectMultipleFiles, + FilePreviewComponent* extraInfoComponent) { - const int numCharsAvailable = 32768; - MemoryBlock filenameSpace ((numCharsAvailable + 1) * sizeof (WCHAR), true); - WCHAR* const fname = (WCHAR*) filenameSpace.getData(); - int fnameIdx = 0; + const int numCharsAvailable = 32768; + MemoryBlock filenameSpace ((numCharsAvailable + 1) * sizeof (WCHAR), true); + WCHAR* const fname = (WCHAR*) filenameSpace.getData(); + int fnameIdx = 0; - JUCE_TRY - { - // use a modal window as the parent for this dialog box - // to block input from other app windows - const Rectangle mainMon (Desktop::getInstance().getMainMonitorArea()); + JUCE_TRY + { + // use a modal window as the parent for this dialog box + // to block input from other app windows + const Rectangle mainMon (Desktop::getInstance().getMainMonitorArea()); - Component w (String::empty); - w.setBounds (mainMon.getX() + mainMon.getWidth() / 4, - mainMon.getY() + mainMon.getHeight() / 4, - 0, 0); - w.setOpaque (true); - w.setAlwaysOnTop (areThereAnyAlwaysOnTopWindows()); - w.addToDesktop (0); + Component w (String::empty); + w.setBounds (mainMon.getX() + mainMon.getWidth() / 4, + mainMon.getY() + mainMon.getHeight() / 4, + 0, 0); + w.setOpaque (true); + w.setAlwaysOnTop (areThereAnyAlwaysOnTopWindows()); + w.addToDesktop (0); - if (extraInfoComponent == 0) - w.enterModalState(); + if (extraInfoComponent == 0) + w.enterModalState(); - String initialDir; + String initialDir; - if (currentFileOrDirectory.isDirectory()) - { - initialDir = currentFileOrDirectory.getFullPathName(); - } - else - { - currentFileOrDirectory.getFileName().copyToBuffer (fname, numCharsAvailable); + if (currentFileOrDirectory.isDirectory()) + { + initialDir = currentFileOrDirectory.getFullPathName(); + } + else + { + currentFileOrDirectory.getFileName().copyToBuffer (fname, numCharsAvailable); - initialDir = currentFileOrDirectory.getParentDirectory().getFullPathName(); - } + initialDir = currentFileOrDirectory.getParentDirectory().getFullPathName(); + } - if (currentExtraFileWin->isValidComponent()) - { - jassertfalse - return; - } + if (currentExtraFileWin->isValidComponent()) + { + jassertfalse + return; + } - if (selectsDirectory) - { - LPITEMIDLIST list = 0; - filenameSpace.fillWith (0); + if (selectsDirectory) + { + LPITEMIDLIST list = 0; + filenameSpace.fillWith (0); - { - BROWSEINFO bi; - zerostruct (bi); + { + BROWSEINFO bi; + zerostruct (bi); - bi.hwndOwner = (HWND) w.getWindowHandle(); - bi.pszDisplayName = fname; - bi.lpszTitle = title; - bi.lpfn = browseCallbackProc; + bi.hwndOwner = (HWND) w.getWindowHandle(); + bi.pszDisplayName = fname; + bi.lpszTitle = title; + bi.lpfn = browseCallbackProc; #ifdef BIF_USENEWUI - bi.ulFlags = BIF_USENEWUI | BIF_VALIDATE; + bi.ulFlags = BIF_USENEWUI | BIF_VALIDATE; #else - bi.ulFlags = 0x50; + bi.ulFlags = 0x50; #endif - defaultDirPath = (const WCHAR*) initialDir; + defaultDirPath = (const WCHAR*) initialDir; - list = SHBrowseForFolder (&bi); + list = SHBrowseForFolder (&bi); - if (! SHGetPathFromIDListW (list, fname)) - { - fname[0] = 0; - returnedString = String::empty; - } - } + if (! SHGetPathFromIDListW (list, fname)) + { + fname[0] = 0; + returnedString = String::empty; + } + } - LPMALLOC al; - if (list != 0 && SUCCEEDED (SHGetMalloc (&al))) - al->Free (list); + LPMALLOC al; + if (list != 0 && SUCCEEDED (SHGetMalloc (&al))) + al->Free (list); - defaultDirPath = 0; + defaultDirPath = 0; - if (returnedString.isNotEmpty()) - { - const String stringFName (fname); + if (returnedString.isNotEmpty()) + { + const String stringFName (fname); - results.add (new File (File (stringFName).getSiblingFile (returnedString))); - returnedString = String::empty; + results.add (new File (File (stringFName).getSiblingFile (returnedString))); + returnedString = String::empty; - return; - } - } - else - { - DWORD flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY; + return; + } + } + else + { + DWORD flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY; - if (warnAboutOverwritingExistingFiles) - flags |= OFN_OVERWRITEPROMPT; + if (warnAboutOverwritingExistingFiles) + flags |= OFN_OVERWRITEPROMPT; - if (selectMultipleFiles) - flags |= OFN_ALLOWMULTISELECT; + if (selectMultipleFiles) + flags |= OFN_ALLOWMULTISELECT; - if (extraInfoComponent != 0) - { - flags |= OFN_ENABLEHOOK; + if (extraInfoComponent != 0) + { + flags |= OFN_ENABLEHOOK; - currentExtraFileWin = new FPComponentHolder(); - currentExtraFileWin->addAndMakeVisible (extraInfoComponent); - currentExtraFileWin->setSize (jlimit (20, 800, extraInfoComponent->getWidth()), - extraInfoComponent->getHeight()); - currentExtraFileWin->addToDesktop (0); + currentExtraFileWin = new FPComponentHolder(); + currentExtraFileWin->addAndMakeVisible (extraInfoComponent); + currentExtraFileWin->setSize (jlimit (20, 800, extraInfoComponent->getWidth()), + extraInfoComponent->getHeight()); + currentExtraFileWin->addToDesktop (0); - currentExtraFileWin->enterModalState(); - } + currentExtraFileWin->enterModalState(); + } - { - WCHAR filters [1024]; - zeromem (filters, sizeof (filters)); - filter.copyToBuffer (filters, 1024); - filter.copyToBuffer (filters + filter.length() + 1, - 1022 - filter.length()); + { + WCHAR filters [1024]; + zeromem (filters, sizeof (filters)); + filter.copyToBuffer (filters, 1024); + filter.copyToBuffer (filters + filter.length() + 1, + 1022 - filter.length()); - OPENFILENAMEW of; - zerostruct (of); + OPENFILENAMEW of; + zerostruct (of); #ifdef OPENFILENAME_SIZE_VERSION_400W - of.lStructSize = OPENFILENAME_SIZE_VERSION_400W; + of.lStructSize = OPENFILENAME_SIZE_VERSION_400W; #else - of.lStructSize = sizeof (of); + of.lStructSize = sizeof (of); #endif - of.hwndOwner = (HWND) w.getWindowHandle(); - of.lpstrFilter = filters; - of.nFilterIndex = 1; - of.lpstrFile = fname; - of.nMaxFile = numCharsAvailable; - of.lpstrInitialDir = initialDir; - of.lpstrTitle = title; - of.Flags = flags; + of.hwndOwner = (HWND) w.getWindowHandle(); + of.lpstrFilter = filters; + of.nFilterIndex = 1; + of.lpstrFile = fname; + of.nMaxFile = numCharsAvailable; + of.lpstrInitialDir = initialDir; + of.lpstrTitle = title; + of.Flags = flags; - if (extraInfoComponent != 0) - of.lpfnHook = &openCallback; + if (extraInfoComponent != 0) + of.lpfnHook = &openCallback; - if (isSaveDialogue) - { - if (! GetSaveFileName (&of)) - fname[0] = 0; - else - fnameIdx = of.nFileOffset; - } - else - { - if (! GetOpenFileName (&of)) - fname[0] = 0; - else - fnameIdx = of.nFileOffset; - } - } - } - } + if (isSaveDialogue) + { + if (! GetSaveFileName (&of)) + fname[0] = 0; + else + fnameIdx = of.nFileOffset; + } + else + { + if (! GetOpenFileName (&of)) + fname[0] = 0; + else + fnameIdx = of.nFileOffset; + } + } + } + } #if JUCE_CATCH_UNHANDLED_EXCEPTIONS - catch (...) - { - fname[0] = 0; - } + catch (...) + { + fname[0] = 0; + } #endif - deleteAndZero (currentExtraFileWin); + deleteAndZero (currentExtraFileWin); - const WCHAR* const files = fname; + const WCHAR* const files = fname; - if (selectMultipleFiles && fnameIdx > 0 && files [fnameIdx - 1] == 0) - { - const WCHAR* filename = files + fnameIdx; + if (selectMultipleFiles && fnameIdx > 0 && files [fnameIdx - 1] == 0) + { + const WCHAR* filename = files + fnameIdx; - while (*filename != 0) - { - const String filepath (String (files) + T("\\") + String (filename)); - results.add (new File (filepath)); - filename += CharacterFunctions::length (filename) + 1; - } - } - else if (files[0] != 0) - { - results.add (new File (files)); - } + while (*filename != 0) + { + const String filepath (String (files) + T("\\") + String (filename)); + results.add (new File (filepath)); + filename += CharacterFunctions::length (filename) + 1; + } + } + else if (files[0] != 0) + { + results.add (new File (files)); + } } #endif @@ -240451,56 +218199,56 @@ void FileChooser::showPlatformDialog (OwnedArray& results, void SystemClipboard::copyTextToClipboard (const String& text) throw() { - if (OpenClipboard (0) != 0) - { - if (EmptyClipboard() != 0) - { - const int len = text.length(); + if (OpenClipboard (0) != 0) + { + if (EmptyClipboard() != 0) + { + const int len = text.length(); - if (len > 0) - { - HGLOBAL bufH = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, - (len + 1) * sizeof (wchar_t)); + if (len > 0) + { + HGLOBAL bufH = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, + (len + 1) * sizeof (wchar_t)); - if (bufH != 0) - { - wchar_t* const data = (wchar_t*) GlobalLock (bufH); - text.copyToBuffer (data, len); - GlobalUnlock (bufH); + if (bufH != 0) + { + wchar_t* const data = (wchar_t*) GlobalLock (bufH); + text.copyToBuffer (data, len); + GlobalUnlock (bufH); - SetClipboardData (CF_UNICODETEXT, bufH); - } - } - } + SetClipboardData (CF_UNICODETEXT, bufH); + } + } + } - CloseClipboard(); - } + CloseClipboard(); + } } const String SystemClipboard::getTextFromClipboard() throw() { - String result; + String result; - if (OpenClipboard (0) != 0) - { - HANDLE bufH = GetClipboardData (CF_UNICODETEXT); + if (OpenClipboard (0) != 0) + { + HANDLE bufH = GetClipboardData (CF_UNICODETEXT); - if (bufH != 0) - { - const wchar_t* const data = (const wchar_t*) GlobalLock (bufH); + if (bufH != 0) + { + const wchar_t* const data = (const wchar_t*) GlobalLock (bufH); - if (data != 0) - { - result = String (data, (int) (GlobalSize (bufH) / sizeof (tchar))); + if (data != 0) + { + result = String (data, (int) (GlobalSize (bufH) / sizeof (tchar))); - GlobalUnlock (bufH); - } - } + GlobalUnlock (bufH); + } + } - CloseClipboard(); - } + CloseClipboard(); + } - return result; + return result; } #endif @@ -240513,508 +218261,508 @@ const String SystemClipboard::getTextFromClipboard() throw() class JuceIStorage : public IStorage { - int refCount; + int refCount; public: - JuceIStorage() : refCount (1) {} + JuceIStorage() : refCount (1) {} - virtual ~JuceIStorage() - { - jassert (refCount == 0); - } + virtual ~JuceIStorage() + { + jassert (refCount == 0); + } - HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) - { - if (id == IID_IUnknown || id == IID_IStorage) - { - AddRef(); - *result = this; - return S_OK; - } + HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) + { + if (id == IID_IUnknown || id == IID_IStorage) + { + AddRef(); + *result = this; + return S_OK; + } - *result = 0; - return E_NOINTERFACE; - } + *result = 0; + return E_NOINTERFACE; + } - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; } + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; } - HRESULT __stdcall CreateStream (const WCHAR*, DWORD, DWORD, DWORD, IStream**) { return E_NOTIMPL; } - HRESULT __stdcall OpenStream (const WCHAR*, void*, DWORD, DWORD, IStream**) { return E_NOTIMPL; } - HRESULT __stdcall CreateStorage (const WCHAR*, DWORD, DWORD, DWORD, IStorage**) { return E_NOTIMPL; } - HRESULT __stdcall OpenStorage (const WCHAR*, IStorage*, DWORD, SNB, DWORD, IStorage**) { return E_NOTIMPL; } - HRESULT __stdcall CopyTo (DWORD, IID const*, SNB, IStorage*) { return E_NOTIMPL; } - HRESULT __stdcall MoveElementTo (const OLECHAR*,IStorage*, const OLECHAR*, DWORD) { return E_NOTIMPL; } - HRESULT __stdcall Commit (DWORD) { return E_NOTIMPL; } - HRESULT __stdcall Revert() { return E_NOTIMPL; } - HRESULT __stdcall EnumElements (DWORD, void*, DWORD, IEnumSTATSTG**) { return E_NOTIMPL; } - HRESULT __stdcall DestroyElement (const OLECHAR*) { return E_NOTIMPL; } - HRESULT __stdcall RenameElement (const WCHAR*, const WCHAR*) { return E_NOTIMPL; } - HRESULT __stdcall SetElementTimes (const WCHAR*, FILETIME const*, FILETIME const*, FILETIME const*) { return E_NOTIMPL; } - HRESULT __stdcall SetClass (REFCLSID) { return S_OK; } - HRESULT __stdcall SetStateBits (DWORD, DWORD) { return E_NOTIMPL; } - HRESULT __stdcall Stat (STATSTG*, DWORD) { return E_NOTIMPL; } + HRESULT __stdcall CreateStream (const WCHAR*, DWORD, DWORD, DWORD, IStream**) { return E_NOTIMPL; } + HRESULT __stdcall OpenStream (const WCHAR*, void*, DWORD, DWORD, IStream**) { return E_NOTIMPL; } + HRESULT __stdcall CreateStorage (const WCHAR*, DWORD, DWORD, DWORD, IStorage**) { return E_NOTIMPL; } + HRESULT __stdcall OpenStorage (const WCHAR*, IStorage*, DWORD, SNB, DWORD, IStorage**) { return E_NOTIMPL; } + HRESULT __stdcall CopyTo (DWORD, IID const*, SNB, IStorage*) { return E_NOTIMPL; } + HRESULT __stdcall MoveElementTo (const OLECHAR*,IStorage*, const OLECHAR*, DWORD) { return E_NOTIMPL; } + HRESULT __stdcall Commit (DWORD) { return E_NOTIMPL; } + HRESULT __stdcall Revert() { return E_NOTIMPL; } + HRESULT __stdcall EnumElements (DWORD, void*, DWORD, IEnumSTATSTG**) { return E_NOTIMPL; } + HRESULT __stdcall DestroyElement (const OLECHAR*) { return E_NOTIMPL; } + HRESULT __stdcall RenameElement (const WCHAR*, const WCHAR*) { return E_NOTIMPL; } + HRESULT __stdcall SetElementTimes (const WCHAR*, FILETIME const*, FILETIME const*, FILETIME const*) { return E_NOTIMPL; } + HRESULT __stdcall SetClass (REFCLSID) { return S_OK; } + HRESULT __stdcall SetStateBits (DWORD, DWORD) { return E_NOTIMPL; } + HRESULT __stdcall Stat (STATSTG*, DWORD) { return E_NOTIMPL; } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; class JuceOleInPlaceFrame : public IOleInPlaceFrame { - int refCount; - HWND window; + int refCount; + HWND window; public: - JuceOleInPlaceFrame (HWND window_) - : refCount (1), - window (window_) - { - } + JuceOleInPlaceFrame (HWND window_) + : refCount (1), + window (window_) + { + } - virtual ~JuceOleInPlaceFrame() - { - jassert (refCount == 0); - } + virtual ~JuceOleInPlaceFrame() + { + jassert (refCount == 0); + } - HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) - { - if (id == IID_IUnknown || id == IID_IOleInPlaceFrame) - { - AddRef(); - *result = this; - return S_OK; - } + HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) + { + if (id == IID_IUnknown || id == IID_IOleInPlaceFrame) + { + AddRef(); + *result = this; + return S_OK; + } - *result = 0; - return E_NOINTERFACE; - } + *result = 0; + return E_NOINTERFACE; + } - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; } + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; } - HRESULT __stdcall GetWindow (HWND* lphwnd) { *lphwnd = window; return S_OK; } - HRESULT __stdcall ContextSensitiveHelp (BOOL) { return E_NOTIMPL; } - HRESULT __stdcall GetBorder (LPRECT) { return E_NOTIMPL; } - HRESULT __stdcall RequestBorderSpace (LPCBORDERWIDTHS) { return E_NOTIMPL; } - HRESULT __stdcall SetBorderSpace (LPCBORDERWIDTHS) { return E_NOTIMPL; } - HRESULT __stdcall SetActiveObject (IOleInPlaceActiveObject*, LPCOLESTR) { return S_OK; } - HRESULT __stdcall InsertMenus (HMENU, LPOLEMENUGROUPWIDTHS) { return E_NOTIMPL; } - HRESULT __stdcall SetMenu (HMENU, HOLEMENU, HWND) { return S_OK; } - HRESULT __stdcall RemoveMenus (HMENU) { return E_NOTIMPL; } - HRESULT __stdcall SetStatusText (LPCOLESTR) { return S_OK; } - HRESULT __stdcall EnableModeless (BOOL) { return S_OK; } - HRESULT __stdcall TranslateAccelerator(LPMSG, WORD) { return E_NOTIMPL; } + HRESULT __stdcall GetWindow (HWND* lphwnd) { *lphwnd = window; return S_OK; } + HRESULT __stdcall ContextSensitiveHelp (BOOL) { return E_NOTIMPL; } + HRESULT __stdcall GetBorder (LPRECT) { return E_NOTIMPL; } + HRESULT __stdcall RequestBorderSpace (LPCBORDERWIDTHS) { return E_NOTIMPL; } + HRESULT __stdcall SetBorderSpace (LPCBORDERWIDTHS) { return E_NOTIMPL; } + HRESULT __stdcall SetActiveObject (IOleInPlaceActiveObject*, LPCOLESTR) { return S_OK; } + HRESULT __stdcall InsertMenus (HMENU, LPOLEMENUGROUPWIDTHS) { return E_NOTIMPL; } + HRESULT __stdcall SetMenu (HMENU, HOLEMENU, HWND) { return S_OK; } + HRESULT __stdcall RemoveMenus (HMENU) { return E_NOTIMPL; } + HRESULT __stdcall SetStatusText (LPCOLESTR) { return S_OK; } + HRESULT __stdcall EnableModeless (BOOL) { return S_OK; } + HRESULT __stdcall TranslateAccelerator(LPMSG, WORD) { return E_NOTIMPL; } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; class JuceIOleInPlaceSite : public IOleInPlaceSite { - int refCount; - HWND window; - JuceOleInPlaceFrame* frame; + int refCount; + HWND window; + JuceOleInPlaceFrame* frame; public: - JuceIOleInPlaceSite (HWND window_) - : refCount (1), - window (window_) - { - frame = new JuceOleInPlaceFrame (window); - } + JuceIOleInPlaceSite (HWND window_) + : refCount (1), + window (window_) + { + frame = new JuceOleInPlaceFrame (window); + } - virtual ~JuceIOleInPlaceSite() - { - jassert (refCount == 0); - frame->Release(); - } + virtual ~JuceIOleInPlaceSite() + { + jassert (refCount == 0); + frame->Release(); + } - HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) - { - if (id == IID_IUnknown || id == IID_IOleInPlaceSite) - { - AddRef(); - *result = this; - return S_OK; - } + HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) + { + if (id == IID_IUnknown || id == IID_IOleInPlaceSite) + { + AddRef(); + *result = this; + return S_OK; + } - *result = 0; - return E_NOINTERFACE; - } + *result = 0; + return E_NOINTERFACE; + } - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; } + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; } - HRESULT __stdcall GetWindow (HWND* lphwnd) { *lphwnd = window; return S_OK; } - HRESULT __stdcall ContextSensitiveHelp (BOOL) { return E_NOTIMPL; } - HRESULT __stdcall CanInPlaceActivate() { return S_OK; } - HRESULT __stdcall OnInPlaceActivate() { return S_OK; } - HRESULT __stdcall OnUIActivate() { return S_OK; } + HRESULT __stdcall GetWindow (HWND* lphwnd) { *lphwnd = window; return S_OK; } + HRESULT __stdcall ContextSensitiveHelp (BOOL) { return E_NOTIMPL; } + HRESULT __stdcall CanInPlaceActivate() { return S_OK; } + HRESULT __stdcall OnInPlaceActivate() { return S_OK; } + HRESULT __stdcall OnUIActivate() { return S_OK; } - HRESULT __stdcall GetWindowContext (LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc, LPRECT, LPRECT, LPOLEINPLACEFRAMEINFO lpFrameInfo) - { - frame->AddRef(); - *lplpFrame = frame; - *lplpDoc = 0; - lpFrameInfo->fMDIApp = FALSE; - lpFrameInfo->hwndFrame = window; - lpFrameInfo->haccel = 0; - lpFrameInfo->cAccelEntries = 0; - return S_OK; - } + HRESULT __stdcall GetWindowContext (LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc, LPRECT, LPRECT, LPOLEINPLACEFRAMEINFO lpFrameInfo) + { + // frame->AddRef(); // MS docs are unclear about whether this is needed, but it seems to lead to a memory leak.. + *lplpFrame = frame; + *lplpDoc = 0; + lpFrameInfo->fMDIApp = FALSE; + lpFrameInfo->hwndFrame = window; + lpFrameInfo->haccel = 0; + lpFrameInfo->cAccelEntries = 0; + return S_OK; + } - HRESULT __stdcall Scroll (SIZE) { return E_NOTIMPL; } - HRESULT __stdcall OnUIDeactivate (BOOL) { return S_OK; } - HRESULT __stdcall OnInPlaceDeactivate() { return S_OK; } - HRESULT __stdcall DiscardUndoState() { return E_NOTIMPL; } - HRESULT __stdcall DeactivateAndUndo() { return E_NOTIMPL; } - HRESULT __stdcall OnPosRectChange (LPCRECT) { return S_OK; } + HRESULT __stdcall Scroll (SIZE) { return E_NOTIMPL; } + HRESULT __stdcall OnUIDeactivate (BOOL) { return S_OK; } + HRESULT __stdcall OnInPlaceDeactivate() { return S_OK; } + HRESULT __stdcall DiscardUndoState() { return E_NOTIMPL; } + HRESULT __stdcall DeactivateAndUndo() { return E_NOTIMPL; } + HRESULT __stdcall OnPosRectChange (LPCRECT) { return S_OK; } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; class JuceIOleClientSite : public IOleClientSite { - int refCount; - JuceIOleInPlaceSite* inplaceSite; + int refCount; + JuceIOleInPlaceSite* inplaceSite; public: - JuceIOleClientSite (HWND window) - : refCount (1) - { - inplaceSite = new JuceIOleInPlaceSite (window); - } + JuceIOleClientSite (HWND window) + : refCount (1) + { + inplaceSite = new JuceIOleInPlaceSite (window); + } - virtual ~JuceIOleClientSite() - { - jassert (refCount == 0); - inplaceSite->Release(); - } + virtual ~JuceIOleClientSite() + { + jassert (refCount == 0); + inplaceSite->Release(); + } - HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) - { - if (id == IID_IUnknown || id == IID_IOleClientSite) - { - AddRef(); - *result = this; - return S_OK; - } - else if (id == IID_IOleInPlaceSite) - { - inplaceSite->AddRef(); - *result = inplaceSite; - return S_OK; - } + HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) + { + if (id == IID_IUnknown || id == IID_IOleClientSite) + { + AddRef(); + *result = this; + return S_OK; + } + else if (id == IID_IOleInPlaceSite) + { + inplaceSite->AddRef(); + *result = inplaceSite; + return S_OK; + } - *result = 0; - return E_NOINTERFACE; - } + *result = 0; + return E_NOINTERFACE; + } - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; } + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; } - HRESULT __stdcall SaveObject() { return E_NOTIMPL; } - HRESULT __stdcall GetMoniker (DWORD, DWORD, IMoniker**) { return E_NOTIMPL; } - HRESULT __stdcall GetContainer (LPOLECONTAINER* ppContainer) { *ppContainer = 0; return E_NOINTERFACE; } - HRESULT __stdcall ShowObject() { return S_OK; } - HRESULT __stdcall OnShowWindow (BOOL) { return E_NOTIMPL; } - HRESULT __stdcall RequestNewObjectLayout() { return E_NOTIMPL; } + HRESULT __stdcall SaveObject() { return E_NOTIMPL; } + HRESULT __stdcall GetMoniker (DWORD, DWORD, IMoniker**) { return E_NOTIMPL; } + HRESULT __stdcall GetContainer (LPOLECONTAINER* ppContainer) { *ppContainer = 0; return E_NOINTERFACE; } + HRESULT __stdcall ShowObject() { return S_OK; } + HRESULT __stdcall OnShowWindow (BOOL) { return E_NOTIMPL; } + HRESULT __stdcall RequestNewObjectLayout() { return E_NOTIMPL; } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; class ActiveXControlData : public ComponentMovementWatcher { - ActiveXControlComponent* const owner; - bool wasShowing; + ActiveXControlComponent* const owner; + bool wasShowing; public: - HWND controlHWND; - IStorage* storage; - IOleClientSite* clientSite; - IOleObject* control; + HWND controlHWND; + IStorage* storage; + IOleClientSite* clientSite; + IOleObject* control; - ActiveXControlData (HWND hwnd, - ActiveXControlComponent* const owner_) - : ComponentMovementWatcher (owner_), - owner (owner_), - wasShowing (owner_ != 0 && owner_->isShowing()), - controlHWND (0), - storage (new JuceIStorage()), - clientSite (new JuceIOleClientSite (hwnd)), - control (0) - { - } + ActiveXControlData (HWND hwnd, + ActiveXControlComponent* const owner_) + : ComponentMovementWatcher (owner_), + owner (owner_), + wasShowing (owner_ != 0 && owner_->isShowing()), + controlHWND (0), + storage (new JuceIStorage()), + clientSite (new JuceIOleClientSite (hwnd)), + control (0) + { + } - ~ActiveXControlData() - { - if (control != 0) - { - control->Close (OLECLOSE_NOSAVE); - control->Release(); - } + ~ActiveXControlData() + { + if (control != 0) + { + control->Close (OLECLOSE_NOSAVE); + control->Release(); + } - clientSite->Release(); - storage->Release(); - } + clientSite->Release(); + storage->Release(); + } - void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) - { - Component* const topComp = owner->getTopLevelComponent(); + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) + { + Component* const topComp = owner->getTopLevelComponent(); - if (topComp->getPeer() != 0) - { - int x = 0, y = 0; - owner->relativePositionToOtherComponent (topComp, x, y); + if (topComp->getPeer() != 0) + { + int x = 0, y = 0; + owner->relativePositionToOtherComponent (topComp, x, y); - owner->setControlBounds (Rectangle (x, y, owner->getWidth(), owner->getHeight())); - } - } + owner->setControlBounds (Rectangle (x, y, owner->getWidth(), owner->getHeight())); + } + } - void componentPeerChanged() - { - const bool isShowingNow = owner->isShowing(); + void componentPeerChanged() + { + const bool isShowingNow = owner->isShowing(); - if (wasShowing != isShowingNow) - { - wasShowing = isShowingNow; - owner->setControlVisible (isShowingNow); - } + if (wasShowing != isShowingNow) + { + wasShowing = isShowingNow; + owner->setControlVisible (isShowingNow); + } - componentMovedOrResized (true, true); - } + componentMovedOrResized (true, true); + } - void componentVisibilityChanged (Component&) - { - componentPeerChanged(); - } + void componentVisibilityChanged (Component&) + { + componentPeerChanged(); + } - static bool doesWindowMatch (const ActiveXControlComponent* const ax, HWND hwnd) - { - return ((ActiveXControlData*) ax->control) != 0 - && ((ActiveXControlData*) ax->control)->controlHWND == hwnd; - } + static bool doesWindowMatch (const ActiveXControlComponent* const ax, HWND hwnd) + { + return ((ActiveXControlData*) ax->control) != 0 + && ((ActiveXControlData*) ax->control)->controlHWND == hwnd; + } }; static VoidArray activeXComps; static HWND getHWND (const ActiveXControlComponent* const component) { - HWND hwnd = 0; + HWND hwnd = 0; - const IID iid = IID_IOleWindow; - IOleWindow* const window = (IOleWindow*) component->queryInterface (&iid); + const IID iid = IID_IOleWindow; + IOleWindow* const window = (IOleWindow*) component->queryInterface (&iid); - if (window != 0) - { - window->GetWindow (&hwnd); - window->Release(); - } + if (window != 0) + { + window->GetWindow (&hwnd); + window->Release(); + } - return hwnd; + return hwnd; } static void offerActiveXMouseEventToPeer (ComponentPeer* const peer, HWND hwnd, UINT message, LPARAM lParam) { - RECT activeXRect, peerRect; - GetWindowRect (hwnd, &activeXRect); - GetWindowRect ((HWND) peer->getNativeHandle(), &peerRect); + RECT activeXRect, peerRect; + GetWindowRect (hwnd, &activeXRect); + GetWindowRect ((HWND) peer->getNativeHandle(), &peerRect); - const int mx = GET_X_LPARAM (lParam) + activeXRect.left - peerRect.left; - const int my = GET_Y_LPARAM (lParam) + activeXRect.top - peerRect.top; - const int64 mouseEventTime = getMouseEventTime(); + const int mx = GET_X_LPARAM (lParam) + activeXRect.left - peerRect.left; + const int my = GET_Y_LPARAM (lParam) + activeXRect.top - peerRect.top; + const int64 mouseEventTime = getMouseEventTime(); - const int oldModifiers = currentModifiers; - ModifierKeys::getCurrentModifiersRealtime(); // to update the mouse button flags + const int oldModifiers = currentModifiers; + ModifierKeys::getCurrentModifiersRealtime(); // to update the mouse button flags - switch (message) - { - case WM_MOUSEMOVE: - if (ModifierKeys (currentModifiers).isAnyMouseButtonDown()) - peer->handleMouseDrag (mx, my, mouseEventTime); - else - peer->handleMouseMove (mx, my, mouseEventTime); - break; + switch (message) + { + case WM_MOUSEMOVE: + if (ModifierKeys (currentModifiers).isAnyMouseButtonDown()) + peer->handleMouseDrag (mx, my, mouseEventTime); + else + peer->handleMouseMove (mx, my, mouseEventTime); + break; - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - peer->handleMouseDown (mx, my, mouseEventTime); - break; + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + peer->handleMouseDown (mx, my, mouseEventTime); + break; - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - peer->handleMouseUp (oldModifiers, mx, my, mouseEventTime); - break; + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + peer->handleMouseUp (oldModifiers, mx, my, mouseEventTime); + break; - default: - break; - } + default: + break; + } } // intercepts events going to an activeX control, so we can sneakily use the mouse events static LRESULT CALLBACK activeXHookWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - for (int i = activeXComps.size(); --i >= 0;) - { - const ActiveXControlComponent* const ax = (const ActiveXControlComponent*) activeXComps.getUnchecked(i); + for (int i = activeXComps.size(); --i >= 0;) + { + const ActiveXControlComponent* const ax = (const ActiveXControlComponent*) activeXComps.getUnchecked(i); - if (ActiveXControlData::doesWindowMatch (ax, hwnd)) - { - switch (message) - { - case WM_MOUSEMOVE: - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - if (ax->isShowing()) - { - ComponentPeer* const peer = ax->getPeer(); + if (ActiveXControlData::doesWindowMatch (ax, hwnd)) + { + switch (message) + { + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + if (ax->isShowing()) + { + ComponentPeer* const peer = ax->getPeer(); - if (peer != 0) - { - offerActiveXMouseEventToPeer (peer, hwnd, message, lParam); + if (peer != 0) + { + offerActiveXMouseEventToPeer (peer, hwnd, message, lParam); - if (! ax->areMouseEventsAllowed()) - return 0; - } - } - break; + if (! ax->areMouseEventsAllowed()) + return 0; + } + } + break; - default: - break; - } + default: + break; + } - return CallWindowProc ((WNDPROC) (ax->originalWndProc), hwnd, message, wParam, lParam); - } - } + return CallWindowProc ((WNDPROC) (ax->originalWndProc), hwnd, message, wParam, lParam); + } + } - return DefWindowProc (hwnd, message, wParam, lParam); + return DefWindowProc (hwnd, message, wParam, lParam); } ActiveXControlComponent::ActiveXControlComponent() - : originalWndProc (0), - control (0), - mouseEventsAllowed (true) + : originalWndProc (0), + control (0), + mouseEventsAllowed (true) { - activeXComps.add (this); + activeXComps.add (this); } ActiveXControlComponent::~ActiveXControlComponent() { - deleteControl(); - activeXComps.removeValue (this); + deleteControl(); + activeXComps.removeValue (this); } void ActiveXControlComponent::paint (Graphics& g) { - if (control == 0) - g.fillAll (Colours::lightgrey); + if (control == 0) + g.fillAll (Colours::lightgrey); } bool ActiveXControlComponent::createControl (const void* controlIID) { - deleteControl(); - ComponentPeer* const peer = getPeer(); + deleteControl(); + ComponentPeer* const peer = getPeer(); - // the component must have already been added to a real window when you call this! - jassert (dynamic_cast (peer) != 0); + // the component must have already been added to a real window when you call this! + jassert (dynamic_cast (peer) != 0); - if (dynamic_cast (peer) != 0) - { - int x = 0, y = 0; - relativePositionToOtherComponent (getTopLevelComponent(), x, y); + if (dynamic_cast (peer) != 0) + { + int x = 0, y = 0; + relativePositionToOtherComponent (getTopLevelComponent(), x, y); - HWND hwnd = (HWND) peer->getNativeHandle(); + HWND hwnd = (HWND) peer->getNativeHandle(); - ScopedPointer info (new ActiveXControlData (hwnd, this)); + ScopedPointer info (new ActiveXControlData (hwnd, this)); - HRESULT hr; - if ((hr = OleCreate (*(const IID*) controlIID, IID_IOleObject, 1 /*OLERENDER_DRAW*/, 0, - info->clientSite, info->storage, - (void**) &(info->control))) == S_OK) - { - info->control->SetHostNames (L"Juce", 0); + HRESULT hr; + if ((hr = OleCreate (*(const IID*) controlIID, IID_IOleObject, 1 /*OLERENDER_DRAW*/, 0, + info->clientSite, info->storage, + (void**) &(info->control))) == S_OK) + { + info->control->SetHostNames (L"Juce", 0); - if (OleSetContainedObject (info->control, TRUE) == S_OK) - { - RECT rect; - rect.left = x; - rect.top = y; - rect.right = x + getWidth(); - rect.bottom = y + getHeight(); + if (OleSetContainedObject (info->control, TRUE) == S_OK) + { + RECT rect; + rect.left = x; + rect.top = y; + rect.right = x + getWidth(); + rect.bottom = y + getHeight(); - if (info->control->DoVerb (OLEIVERB_SHOW, 0, info->clientSite, 0, hwnd, &rect) == S_OK) - { - control = info.release(); - setControlBounds (Rectangle (x, y, getWidth(), getHeight())); + if (info->control->DoVerb (OLEIVERB_SHOW, 0, info->clientSite, 0, hwnd, &rect) == S_OK) + { + control = info.release(); + setControlBounds (Rectangle (x, y, getWidth(), getHeight())); - ((ActiveXControlData*) control)->controlHWND = getHWND (this); + ((ActiveXControlData*) control)->controlHWND = getHWND (this); - if (((ActiveXControlData*) control)->controlHWND != 0) - { - originalWndProc = (void*) (pointer_sized_int) GetWindowLongPtr ((HWND) ((ActiveXControlData*) control)->controlHWND, GWLP_WNDPROC); - SetWindowLongPtr ((HWND) ((ActiveXControlData*) control)->controlHWND, GWLP_WNDPROC, (LONG_PTR) activeXHookWndProc); - } + if (((ActiveXControlData*) control)->controlHWND != 0) + { + originalWndProc = (void*) (pointer_sized_int) GetWindowLongPtr ((HWND) ((ActiveXControlData*) control)->controlHWND, GWLP_WNDPROC); + SetWindowLongPtr ((HWND) ((ActiveXControlData*) control)->controlHWND, GWLP_WNDPROC, (LONG_PTR) activeXHookWndProc); + } - return true; - } - } - } - } + return true; + } + } + } + } - return false; + return false; } void ActiveXControlComponent::deleteControl() { - ActiveXControlData* const info = (ActiveXControlData*) control; + ActiveXControlData* const info = (ActiveXControlData*) control; - if (info != 0) - { - delete info; - control = 0; - originalWndProc = 0; - } + if (info != 0) + { + delete info; + control = 0; + originalWndProc = 0; + } } void* ActiveXControlComponent::queryInterface (const void* iid) const { - ActiveXControlData* const info = (ActiveXControlData*) control; + ActiveXControlData* const info = (ActiveXControlData*) control; - void* result = 0; + void* result = 0; - if (info != 0 && info->control != 0 - && info->control->QueryInterface (*(const IID*) iid, &result) == S_OK) - return result; + if (info != 0 && info->control != 0 + && info->control->QueryInterface (*(const IID*) iid, &result) == S_OK) + return result; - return 0; + return 0; } void ActiveXControlComponent::setControlBounds (const Rectangle& newBounds) const { - HWND hwnd = ((ActiveXControlData*) control)->controlHWND; + HWND hwnd = ((ActiveXControlData*) control)->controlHWND; - if (hwnd != 0) - MoveWindow (hwnd, newBounds.getX(), newBounds.getY(), newBounds.getWidth(), newBounds.getHeight(), TRUE); + if (hwnd != 0) + MoveWindow (hwnd, newBounds.getX(), newBounds.getY(), newBounds.getWidth(), newBounds.getHeight(), TRUE); } void ActiveXControlComponent::setControlVisible (const bool shouldBeVisible) const { - HWND hwnd = ((ActiveXControlData*) control)->controlHWND; + HWND hwnd = ((ActiveXControlData*) control)->controlHWND; - if (hwnd != 0) - ShowWindow (hwnd, shouldBeVisible ? SW_SHOWNA : SW_HIDE); + if (hwnd != 0) + ShowWindow (hwnd, shouldBeVisible ? SW_SHOWNA : SW_HIDE); } void ActiveXControlComponent::setMouseEventsAllowed (const bool eventsCanReachControl) { - mouseEventsAllowed = eventsCanReachControl; + mouseEventsAllowed = eventsCanReachControl; } #endif @@ -241034,468 +218782,455 @@ static bool isQTAvailable = false; struct QTMovieCompInternal { - QTMovieCompInternal() - : dataHandle (0) - { - } + QTMovieCompInternal() + : dataHandle (0) + { + } - ~QTMovieCompInternal() - { - clearHandle(); - } + ~QTMovieCompInternal() + { + clearHandle(); + } - IQTControlPtr qtControlInternal; - IQTMoviePtr qtMovieInternal; + IQTControlPtr qtControlInternal; + IQTMoviePtr qtMovieInternal; - Handle dataHandle; + Handle dataHandle; - void clearHandle() - { - if (dataHandle != 0) - { - DisposeHandle (dataHandle); - dataHandle = 0; - } - } + void clearHandle() + { + if (dataHandle != 0) + { + DisposeHandle (dataHandle); + dataHandle = 0; + } + } }; #define qtControl (((QTMovieCompInternal*) internal)->qtControlInternal) -#define qtMovie (((QTMovieCompInternal*) internal)->qtMovieInternal) +#define qtMovie (((QTMovieCompInternal*) internal)->qtMovieInternal) QuickTimeMovieComponent::QuickTimeMovieComponent() - : movieLoaded (false), - controllerVisible (true) + : movieLoaded (false), + controllerVisible (true) { - internal = new QTMovieCompInternal(); - setMouseEventsAllowed (false); + internal = new QTMovieCompInternal(); + setMouseEventsAllowed (false); } QuickTimeMovieComponent::~QuickTimeMovieComponent() { - closeMovie(); - qtControl = 0; + closeMovie(); + qtControl = 0; - deleteControl(); + deleteControl(); - delete internal; - internal = 0; + delete internal; + internal = 0; } bool QuickTimeMovieComponent::isQuickTimeAvailable() throw() { - if (! isQTAvailable) - { - isQTAvailable = (InitializeQTML (0) == noErr) - && (EnterMovies() == noErr); - } + if (! isQTAvailable) + { + isQTAvailable = (InitializeQTML (0) == noErr) + && (EnterMovies() == noErr); + } - return isQTAvailable; + return isQTAvailable; } void QuickTimeMovieComponent::createControlIfNeeded() { - if (isShowing() && ! isControlCreated()) - { - const IID qtIID = __uuidof (QTControl); + if (isShowing() && ! isControlCreated()) + { + const IID qtIID = __uuidof (QTControl); - if (createControl (&qtIID)) - { - const IID qtInterfaceIID = __uuidof (IQTControl); - qtControl = (IQTControl*) queryInterface (&qtInterfaceIID); + if (createControl (&qtIID)) + { + const IID qtInterfaceIID = __uuidof (IQTControl); + qtControl = (IQTControl*) queryInterface (&qtInterfaceIID); - if (qtControl != 0) - { - qtControl->Release(); // it has one ref too many at this point + if (qtControl != 0) + { + qtControl->Release(); // it has one ref too many at this point - qtControl->QuickTimeInitialize(); - qtControl->PutSizing (qtMovieFitsControl); + qtControl->QuickTimeInitialize(); + qtControl->PutSizing (qtMovieFitsControl); - if (movieFile != File::nonexistent) - loadMovie (movieFile, controllerVisible); - } - } - } + if (movieFile != File::nonexistent) + loadMovie (movieFile, controllerVisible); + } + } + } } bool QuickTimeMovieComponent::isControlCreated() const { - return isControlOpen(); + return isControlOpen(); } bool QuickTimeMovieComponent::loadMovie (InputStream* movieStream, - const bool isControllerVisible) + const bool isControllerVisible) { - movieFile = File::nonexistent; - movieLoaded = false; - qtMovie = 0; - controllerVisible = isControllerVisible; - createControlIfNeeded(); + movieFile = File::nonexistent; + movieLoaded = false; + qtMovie = 0; + controllerVisible = isControllerVisible; + createControlIfNeeded(); - if (isControlCreated()) - { - if (qtControl != 0) - { - qtControl->Put_MovieHandle (0); - ((QTMovieCompInternal*) internal)->clearHandle(); + if (isControlCreated()) + { + if (qtControl != 0) + { + qtControl->Put_MovieHandle (0); + ((QTMovieCompInternal*) internal)->clearHandle(); - Movie movie; - if (juce_OpenQuickTimeMovieFromStream (movieStream, movie, ((QTMovieCompInternal*) internal)->dataHandle)) - { - qtControl->Put_MovieHandle ((long) (pointer_sized_int) movie); + Movie movie; + if (juce_OpenQuickTimeMovieFromStream (movieStream, movie, ((QTMovieCompInternal*) internal)->dataHandle)) + { + qtControl->Put_MovieHandle ((long) (pointer_sized_int) movie); - qtMovie = qtControl->GetMovie(); + qtMovie = qtControl->GetMovie(); - if (qtMovie != 0) - qtMovie->PutMovieControllerType (isControllerVisible ? qtMovieControllerTypeStandard - : qtMovieControllerTypeNone); - } + if (qtMovie != 0) + qtMovie->PutMovieControllerType (isControllerVisible ? qtMovieControllerTypeStandard + : qtMovieControllerTypeNone); + } - if (movie == 0) - ((QTMovieCompInternal*) internal)->clearHandle(); - } + if (movie == 0) + ((QTMovieCompInternal*) internal)->clearHandle(); + } - movieLoaded = (qtMovie != 0); - } - else - { - // You're trying to open a movie when the control hasn't yet been created, probably because - // you've not yet added this component to a Window and made the whole component hierarchy visible. - jassertfalse - } + movieLoaded = (qtMovie != 0); + } + else + { + // You're trying to open a movie when the control hasn't yet been created, probably because + // you've not yet added this component to a Window and made the whole component hierarchy visible. + jassertfalse + } - delete movieStream; - return movieLoaded; + delete movieStream; + return movieLoaded; } void QuickTimeMovieComponent::closeMovie() { - stop(); - movieFile = File::nonexistent; - movieLoaded = false; - qtMovie = 0; + stop(); + movieFile = File::nonexistent; + movieLoaded = false; + qtMovie = 0; - if (qtControl != 0) - qtControl->Put_MovieHandle (0); + if (qtControl != 0) + qtControl->Put_MovieHandle (0); - ((QTMovieCompInternal*) internal)->clearHandle(); + ((QTMovieCompInternal*) internal)->clearHandle(); } const File QuickTimeMovieComponent::getCurrentMovieFile() const { - return movieFile; + return movieFile; } bool QuickTimeMovieComponent::isMovieOpen() const { - return movieLoaded; + return movieLoaded; } double QuickTimeMovieComponent::getMovieDuration() const { - if (qtMovie != 0) - return qtMovie->GetDuration() / (double) qtMovie->GetTimeScale(); + if (qtMovie != 0) + return qtMovie->GetDuration() / (double) qtMovie->GetTimeScale(); - return 0.0; + return 0.0; } void QuickTimeMovieComponent::getMovieNormalSize (int& width, int& height) const { - if (qtMovie != 0) - { - struct QTRECT r = qtMovie->GetNaturalRect(); + if (qtMovie != 0) + { + struct QTRECT r = qtMovie->GetNaturalRect(); - width = r.right - r.left; - height = r.bottom - r.top; - } - else - { - width = height = 0; - } + width = r.right - r.left; + height = r.bottom - r.top; + } + else + { + width = height = 0; + } } void QuickTimeMovieComponent::play() { - if (qtMovie != 0) - qtMovie->Play(); + if (qtMovie != 0) + qtMovie->Play(); } void QuickTimeMovieComponent::stop() { - if (qtMovie != 0) - qtMovie->Stop(); + if (qtMovie != 0) + qtMovie->Stop(); } bool QuickTimeMovieComponent::isPlaying() const { - return qtMovie != 0 && qtMovie->GetRate() != 0.0f; + return qtMovie != 0 && qtMovie->GetRate() != 0.0f; } void QuickTimeMovieComponent::setPosition (const double seconds) { - if (qtMovie != 0) - qtMovie->PutTime ((long) (seconds * qtMovie->GetTimeScale())); + if (qtMovie != 0) + qtMovie->PutTime ((long) (seconds * qtMovie->GetTimeScale())); } double QuickTimeMovieComponent::getPosition() const { - if (qtMovie != 0) - return qtMovie->GetTime() / (double) qtMovie->GetTimeScale(); + if (qtMovie != 0) + return qtMovie->GetTime() / (double) qtMovie->GetTimeScale(); - return 0.0; + return 0.0; } void QuickTimeMovieComponent::setSpeed (const float newSpeed) { - if (qtMovie != 0) - qtMovie->PutRate (newSpeed); + if (qtMovie != 0) + qtMovie->PutRate (newSpeed); } void QuickTimeMovieComponent::setMovieVolume (const float newVolume) { - if (qtMovie != 0) - { - qtMovie->PutAudioVolume (newVolume); - qtMovie->PutAudioMute (newVolume <= 0); - } + if (qtMovie != 0) + { + qtMovie->PutAudioVolume (newVolume); + qtMovie->PutAudioMute (newVolume <= 0); + } } float QuickTimeMovieComponent::getMovieVolume() const { - if (qtMovie != 0) - return qtMovie->GetAudioVolume(); + if (qtMovie != 0) + return qtMovie->GetAudioVolume(); - return 0.0f; + return 0.0f; } void QuickTimeMovieComponent::setLooping (const bool shouldLoop) { - if (qtMovie != 0) - qtMovie->PutLoop (shouldLoop); + if (qtMovie != 0) + qtMovie->PutLoop (shouldLoop); } bool QuickTimeMovieComponent::isLooping() const { - return qtMovie != 0 && qtMovie->GetLoop(); + return qtMovie != 0 && qtMovie->GetLoop(); } bool QuickTimeMovieComponent::isControllerVisible() const { - return controllerVisible; + return controllerVisible; } void QuickTimeMovieComponent::parentHierarchyChanged() { - createControlIfNeeded(); - QTCompBaseClass::parentHierarchyChanged(); + createControlIfNeeded(); + QTCompBaseClass::parentHierarchyChanged(); } void QuickTimeMovieComponent::visibilityChanged() { - createControlIfNeeded(); - QTCompBaseClass::visibilityChanged(); + createControlIfNeeded(); + QTCompBaseClass::visibilityChanged(); } void QuickTimeMovieComponent::paint (Graphics& g) { - if (! isControlCreated()) - g.fillAll (Colours::black); + if (! isControlCreated()) + g.fillAll (Colours::black); } static Handle createHandleDataRef (Handle dataHandle, const char* fileName) { - Handle dataRef = 0; - OSStatus err = PtrToHand (&dataHandle, &dataRef, sizeof (Handle)); - if (err == noErr) - { - Str255 suffix; + Handle dataRef = 0; + OSStatus err = PtrToHand (&dataHandle, &dataRef, sizeof (Handle)); + if (err == noErr) + { + Str255 suffix; - CharacterFunctions::copy ((char*) suffix, fileName, 128); + CharacterFunctions::copy ((char*) suffix, fileName, 128); - StringPtr name = suffix; - err = PtrAndHand (name, dataRef, name[0] + 1); + StringPtr name = suffix; + err = PtrAndHand (name, dataRef, name[0] + 1); - if (err == noErr) - { - long atoms[3]; - atoms[0] = EndianU32_NtoB (3 * sizeof (long)); - atoms[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType); - atoms[2] = EndianU32_NtoB (MovieFileType); + if (err == noErr) + { + long atoms[3]; + atoms[0] = EndianU32_NtoB (3 * sizeof (long)); + atoms[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType); + atoms[2] = EndianU32_NtoB (MovieFileType); - err = PtrAndHand (atoms, dataRef, 3 * sizeof (long)); + err = PtrAndHand (atoms, dataRef, 3 * sizeof (long)); - if (err == noErr) - return dataRef; - } + if (err == noErr) + return dataRef; + } - DisposeHandle (dataRef); - } + DisposeHandle (dataRef); + } - return 0; + return 0; } static CFStringRef juceStringToCFString (const String& s) { - const int len = s.length(); - const juce_wchar* const t = (const juce_wchar*) s; + const int len = s.length(); + const juce_wchar* const t = (const juce_wchar*) s; - HeapBlock temp (len + 2); - for (int i = 0; i <= len; ++i) - temp[i] = t[i]; + HeapBlock temp (len + 2); + for (int i = 0; i <= len; ++i) + temp[i] = t[i]; - return CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len); + return CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len); } static bool openMovie (QTNewMoviePropertyElement* props, int prop, Movie& movie) { - Boolean trueBool = true; - props[prop].propClass = kQTPropertyClass_MovieInstantiation; - props[prop].propID = kQTMovieInstantiationPropertyID_DontResolveDataRefs; - props[prop].propValueSize = sizeof (trueBool); - props[prop].propValueAddress = &trueBool; - ++prop; + Boolean trueBool = true; + props[prop].propClass = kQTPropertyClass_MovieInstantiation; + props[prop].propID = kQTMovieInstantiationPropertyID_DontResolveDataRefs; + props[prop].propValueSize = sizeof (trueBool); + props[prop].propValueAddress = &trueBool; + ++prop; - props[prop].propClass = kQTPropertyClass_MovieInstantiation; - props[prop].propID = kQTMovieInstantiationPropertyID_AsyncOK; - props[prop].propValueSize = sizeof (trueBool); - props[prop].propValueAddress = &trueBool; - ++prop; + props[prop].propClass = kQTPropertyClass_MovieInstantiation; + props[prop].propID = kQTMovieInstantiationPropertyID_AsyncOK; + props[prop].propValueSize = sizeof (trueBool); + props[prop].propValueAddress = &trueBool; + ++prop; - Boolean isActive = true; - props[prop].propClass = kQTPropertyClass_NewMovieProperty; - props[prop].propID = kQTNewMoviePropertyID_Active; - props[prop].propValueSize = sizeof (isActive); - props[prop].propValueAddress = &isActive; - ++prop; + Boolean isActive = true; + props[prop].propClass = kQTPropertyClass_NewMovieProperty; + props[prop].propID = kQTNewMoviePropertyID_Active; + props[prop].propValueSize = sizeof (isActive); + props[prop].propValueAddress = &isActive; + ++prop; - MacSetPort (0); + MacSetPort (0); - jassert (prop <= 5); - OSStatus err = NewMovieFromProperties (prop, props, 0, 0, &movie); + jassert (prop <= 5); + OSStatus err = NewMovieFromProperties (prop, props, 0, 0, &movie); - return err == noErr; + return err == noErr; } bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle) { - if (input == 0) - return false; + if (input == 0) + return false; - dataHandle = 0; - bool ok = false; + dataHandle = 0; + bool ok = false; - QTNewMoviePropertyElement props[5]; - zeromem (props, sizeof (props)); - int prop = 0; + QTNewMoviePropertyElement props[5]; + zeromem (props, sizeof (props)); + int prop = 0; - DataReferenceRecord dr; - props[prop].propClass = kQTPropertyClass_DataLocation; - props[prop].propID = kQTDataLocationPropertyID_DataReference; - props[prop].propValueSize = sizeof (dr); - props[prop].propValueAddress = (void*) &dr; - ++prop; + DataReferenceRecord dr; + props[prop].propClass = kQTPropertyClass_DataLocation; + props[prop].propID = kQTDataLocationPropertyID_DataReference; + props[prop].propValueSize = sizeof (dr); + props[prop].propValueAddress = (void*) &dr; + ++prop; - FileInputStream* const fin = dynamic_cast (input); + FileInputStream* const fin = dynamic_cast (input); - if (fin != 0) - { - CFStringRef filePath = juceStringToCFString (fin->getFile().getFullPathName()); + if (fin != 0) + { + CFStringRef filePath = juceStringToCFString (fin->getFile().getFullPathName()); - QTNewDataReferenceFromFullPathCFString (filePath, (QTPathStyle) kQTNativeDefaultPathStyle, 0, - &dr.dataRef, &dr.dataRefType); + QTNewDataReferenceFromFullPathCFString (filePath, (QTPathStyle) kQTNativeDefaultPathStyle, 0, + &dr.dataRef, &dr.dataRefType); - ok = openMovie (props, prop, movie); + ok = openMovie (props, prop, movie); - DisposeHandle (dr.dataRef); - CFRelease (filePath); - } - else - { - // sanity-check because this currently needs to load the whole stream into memory.. - jassert (input->getTotalLength() < 50 * 1024 * 1024); + DisposeHandle (dr.dataRef); + CFRelease (filePath); + } + else + { + // sanity-check because this currently needs to load the whole stream into memory.. + jassert (input->getTotalLength() < 50 * 1024 * 1024); - dataHandle = NewHandle ((Size) input->getTotalLength()); - HLock (dataHandle); - // read the entire stream into memory - this is a pain, but can't get it to work - // properly using a custom callback to supply the data. - input->read (*dataHandle, (int) input->getTotalLength()); - HUnlock (dataHandle); + dataHandle = NewHandle ((Size) input->getTotalLength()); + HLock (dataHandle); + // read the entire stream into memory - this is a pain, but can't get it to work + // properly using a custom callback to supply the data. + input->read (*dataHandle, (int) input->getTotalLength()); + HUnlock (dataHandle); - // different types to get QT to try. (We should really be a bit smarter here by - // working out in advance which one the stream contains, rather than just trying - // each one) - const char* const suffixesToTry[] = { "\04.mov", "\04.mp3", - "\04.avi", "\04.m4a" }; + // different types to get QT to try. (We should really be a bit smarter here by + // working out in advance which one the stream contains, rather than just trying + // each one) + const char* const suffixesToTry[] = { "\04.mov", "\04.mp3", + "\04.avi", "\04.m4a" }; - for (int i = 0; i < numElementsInArray (suffixesToTry) && ! ok; ++i) - { - /* // this fails for some bizarre reason - it can be bodged to work with - // movies, but can't seem to do it for other file types.. - QTNewMovieUserProcRecord procInfo; - procInfo.getMovieUserProc = NewGetMovieUPP (readMovieStreamProc); - procInfo.getMovieUserProcRefcon = this; - procInfo.defaultDataRef.dataRef = dataRef; - procInfo.defaultDataRef.dataRefType = HandleDataHandlerSubType; + for (int i = 0; i < numElementsInArray (suffixesToTry) && ! ok; ++i) + { - props[prop].propClass = kQTPropertyClass_DataLocation; - props[prop].propID = kQTDataLocationPropertyID_MovieUserProc; - props[prop].propValueSize = sizeof (procInfo); - props[prop].propValueAddress = (void*) &procInfo; - ++prop; */ + dr.dataRef = createHandleDataRef (dataHandle, suffixesToTry [i]); + dr.dataRefType = HandleDataHandlerSubType; + ok = openMovie (props, prop, movie); - dr.dataRef = createHandleDataRef (dataHandle, suffixesToTry [i]); - dr.dataRefType = HandleDataHandlerSubType; - ok = openMovie (props, prop, movie); + DisposeHandle (dr.dataRef); + } + } - DisposeHandle (dr.dataRef); - } - } - - return ok; + return ok; } bool QuickTimeMovieComponent::loadMovie (const File& movieFile_, - const bool isControllerVisible) + const bool isControllerVisible) { - const bool ok = loadMovie ((InputStream*) movieFile_.createInputStream(), isControllerVisible); - movieFile = movieFile_; - return ok; + const bool ok = loadMovie ((InputStream*) movieFile_.createInputStream(), isControllerVisible); + movieFile = movieFile_; + return ok; } bool QuickTimeMovieComponent::loadMovie (const URL& movieURL, - const bool isControllerVisible) + const bool isControllerVisible) { - return loadMovie ((InputStream*) movieURL.createInputStream (false), isControllerVisible); + return loadMovie ((InputStream*) movieURL.createInputStream (false), isControllerVisible); } void QuickTimeMovieComponent::goToStart() { - setPosition (0.0); + setPosition (0.0); } void QuickTimeMovieComponent::setBoundsWithCorrectAspectRatio (const Rectangle& spaceToFitWithin, - const RectanglePlacement& placement) + const RectanglePlacement& placement) { - int normalWidth, normalHeight; - getMovieNormalSize (normalWidth, normalHeight); + int normalWidth, normalHeight; + getMovieNormalSize (normalWidth, normalHeight); - if (normalWidth > 0 && normalHeight > 0 && ! spaceToFitWithin.isEmpty()) - { - double x = 0.0, y = 0.0, w = normalWidth, h = normalHeight; + if (normalWidth > 0 && normalHeight > 0 && ! spaceToFitWithin.isEmpty()) + { + double x = 0.0, y = 0.0, w = normalWidth, h = normalHeight; - placement.applyTo (x, y, w, h, - spaceToFitWithin.getX(), spaceToFitWithin.getY(), - spaceToFitWithin.getWidth(), spaceToFitWithin.getHeight()); + placement.applyTo (x, y, w, h, + spaceToFitWithin.getX(), spaceToFitWithin.getY(), + spaceToFitWithin.getWidth(), spaceToFitWithin.getHeight()); - if (w > 0 && h > 0) - { - setBounds (roundDoubleToInt (x), roundDoubleToInt (y), - roundDoubleToInt (w), roundDoubleToInt (h)); - } - } - else - { - setBounds (spaceToFitWithin); - } + if (w > 0 && h > 0) + { + setBounds (roundToInt (x), roundToInt (y), + roundToInt (w), roundToInt (h)); + } + } + else + { + setBounds (spaceToFitWithin); + } } #endif @@ -241510,309 +219245,309 @@ class WebBrowserComponentInternal : public ActiveXControlComponent { public: - WebBrowserComponentInternal() - : browser (0), - connectionPoint (0), - adviseCookie (0) - { - } + WebBrowserComponentInternal() + : browser (0), + connectionPoint (0), + adviseCookie (0) + { + } - ~WebBrowserComponentInternal() - { - if (connectionPoint != 0) - connectionPoint->Unadvise (adviseCookie); + ~WebBrowserComponentInternal() + { + if (connectionPoint != 0) + connectionPoint->Unadvise (adviseCookie); - if (browser != 0) - browser->Release(); - } + if (browser != 0) + browser->Release(); + } - void createBrowser() - { - createControl (&CLSID_WebBrowser); - browser = (IWebBrowser2*) queryInterface (&IID_IWebBrowser2); + void createBrowser() + { + createControl (&CLSID_WebBrowser); + browser = (IWebBrowser2*) queryInterface (&IID_IWebBrowser2); - IConnectionPointContainer* connectionPointContainer = (IConnectionPointContainer*) queryInterface (&IID_IConnectionPointContainer); + IConnectionPointContainer* connectionPointContainer = (IConnectionPointContainer*) queryInterface (&IID_IConnectionPointContainer); - if (connectionPointContainer != 0) - { - connectionPointContainer->FindConnectionPoint (DIID_DWebBrowserEvents2, - &connectionPoint); + if (connectionPointContainer != 0) + { + connectionPointContainer->FindConnectionPoint (DIID_DWebBrowserEvents2, + &connectionPoint); - if (connectionPoint != 0) - { - WebBrowserComponent* const owner = dynamic_cast (getParentComponent()); - jassert (owner != 0); + if (connectionPoint != 0) + { + WebBrowserComponent* const owner = dynamic_cast (getParentComponent()); + jassert (owner != 0); - EventHandler* handler = new EventHandler (owner); - connectionPoint->Advise (handler, &adviseCookie); - } - } - } + EventHandler* handler = new EventHandler (owner); + connectionPoint->Advise (handler, &adviseCookie); + } + } + } - void goToURL (const String& url, - const StringArray* headers, - const MemoryBlock* postData) - { - if (browser != 0) - { - LPSAFEARRAY sa = 0; - _variant_t flags, frame, postDataVar, headersVar; + void goToURL (const String& url, + const StringArray* headers, + const MemoryBlock* postData) + { + if (browser != 0) + { + LPSAFEARRAY sa = 0; + _variant_t flags, frame, postDataVar, headersVar; - if (headers != 0) - headersVar = (const tchar*) headers->joinIntoString ("\r\n"); + if (headers != 0) + headersVar = (const tchar*) headers->joinIntoString ("\r\n"); - if (postData != 0 && postData->getSize() > 0) - { - LPSAFEARRAY sa = SafeArrayCreateVector (VT_UI1, 0, postData->getSize()); + if (postData != 0 && postData->getSize() > 0) + { + LPSAFEARRAY sa = SafeArrayCreateVector (VT_UI1, 0, postData->getSize()); - if (sa != 0) - { - void* data = 0; - SafeArrayAccessData (sa, &data); - jassert (data != 0); + if (sa != 0) + { + void* data = 0; + SafeArrayAccessData (sa, &data); + jassert (data != 0); - if (data != 0) - { - postData->copyTo (data, 0, postData->getSize()); - SafeArrayUnaccessData (sa); + if (data != 0) + { + postData->copyTo (data, 0, postData->getSize()); + SafeArrayUnaccessData (sa); - VARIANT postDataVar2; - VariantInit (&postDataVar2); - V_VT (&postDataVar2) = VT_ARRAY | VT_UI1; - V_ARRAY (&postDataVar2) = sa; + VARIANT postDataVar2; + VariantInit (&postDataVar2); + V_VT (&postDataVar2) = VT_ARRAY | VT_UI1; + V_ARRAY (&postDataVar2) = sa; - postDataVar = postDataVar2; - } - } - } + postDataVar = postDataVar2; + } + } + } - browser->Navigate ((BSTR) (const OLECHAR*) url, - &flags, &frame, - &postDataVar, &headersVar); + browser->Navigate ((BSTR) (const OLECHAR*) url, + &flags, &frame, + &postDataVar, &headersVar); - if (sa != 0) - SafeArrayDestroy (sa); - } - } + if (sa != 0) + SafeArrayDestroy (sa); + } + } - IWebBrowser2* browser; + IWebBrowser2* browser; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - IConnectionPoint* connectionPoint; - DWORD adviseCookie; + IConnectionPoint* connectionPoint; + DWORD adviseCookie; - class EventHandler : public IDispatch, - public ComponentMovementWatcher - { - public: - EventHandler (WebBrowserComponent* owner_) - : ComponentMovementWatcher (owner_), - owner (owner_), - refCount (0) - { - } + class EventHandler : public IDispatch, + public ComponentMovementWatcher + { + public: + EventHandler (WebBrowserComponent* owner_) + : ComponentMovementWatcher (owner_), + owner (owner_), + refCount (0) + { + } - ~EventHandler() - { - } + ~EventHandler() + { + } - HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) - { - if (id == IID_IUnknown || id == IID_IDispatch || id == DIID_DWebBrowserEvents2) - { - AddRef(); - *result = this; - return S_OK; - } + HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) + { + if (id == IID_IUnknown || id == IID_IDispatch || id == DIID_DWebBrowserEvents2) + { + AddRef(); + *result = this; + return S_OK; + } - *result = 0; - return E_NOINTERFACE; - } + *result = 0; + return E_NOINTERFACE; + } - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } - HRESULT __stdcall GetTypeInfoCount (UINT __RPC_FAR*) { return E_NOTIMPL; } - HRESULT __stdcall GetTypeInfo (UINT, LCID, ITypeInfo __RPC_FAR *__RPC_FAR*) { return E_NOTIMPL; } - HRESULT __stdcall GetIDsOfNames (REFIID, LPOLESTR __RPC_FAR*, UINT, LCID, DISPID __RPC_FAR*) { return E_NOTIMPL; } + HRESULT __stdcall GetTypeInfoCount (UINT __RPC_FAR*) { return E_NOTIMPL; } + HRESULT __stdcall GetTypeInfo (UINT, LCID, ITypeInfo __RPC_FAR *__RPC_FAR*) { return E_NOTIMPL; } + HRESULT __stdcall GetIDsOfNames (REFIID, LPOLESTR __RPC_FAR*, UINT, LCID, DISPID __RPC_FAR*) { return E_NOTIMPL; } - HRESULT __stdcall Invoke (DISPID dispIdMember, REFIID /*riid*/, LCID /*lcid*/, - WORD /*wFlags*/, DISPPARAMS __RPC_FAR* pDispParams, - VARIANT __RPC_FAR* /*pVarResult*/, EXCEPINFO __RPC_FAR* /*pExcepInfo*/, - UINT __RPC_FAR* /*puArgErr*/) - { - switch (dispIdMember) - { - case DISPID_BEFORENAVIGATE2: - { - VARIANT* const vurl = pDispParams->rgvarg[5].pvarVal; + HRESULT __stdcall Invoke (DISPID dispIdMember, REFIID /*riid*/, LCID /*lcid*/, + WORD /*wFlags*/, DISPPARAMS __RPC_FAR* pDispParams, + VARIANT __RPC_FAR* /*pVarResult*/, EXCEPINFO __RPC_FAR* /*pExcepInfo*/, + UINT __RPC_FAR* /*puArgErr*/) + { + switch (dispIdMember) + { + case DISPID_BEFORENAVIGATE2: + { + VARIANT* const vurl = pDispParams->rgvarg[5].pvarVal; - String url; + String url; - if ((vurl->vt & VT_BYREF) != 0) - url = *vurl->pbstrVal; - else - url = vurl->bstrVal; + if ((vurl->vt & VT_BYREF) != 0) + url = *vurl->pbstrVal; + else + url = vurl->bstrVal; - *pDispParams->rgvarg->pboolVal - = owner->pageAboutToLoad (url) ? VARIANT_FALSE - : VARIANT_TRUE; + *pDispParams->rgvarg->pboolVal + = owner->pageAboutToLoad (url) ? VARIANT_FALSE + : VARIANT_TRUE; - return S_OK; - } + return S_OK; + } - default: - break; - } + default: + break; + } - return E_NOTIMPL; - } + return E_NOTIMPL; + } - void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) {} - void componentPeerChanged() {} + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) {} + void componentPeerChanged() {} - void componentVisibilityChanged (Component&) - { - owner->visibilityChanged(); - } + void componentVisibilityChanged (Component&) + { + owner->visibilityChanged(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - private: - WebBrowserComponent* const owner; - int refCount; + private: + WebBrowserComponent* const owner; + int refCount; - EventHandler (const EventHandler&); - const EventHandler& operator= (const EventHandler&); - }; + EventHandler (const EventHandler&); + const EventHandler& operator= (const EventHandler&); + }; }; WebBrowserComponent::WebBrowserComponent (const bool unloadPageWhenBrowserIsHidden_) - : browser (0), - blankPageShown (false), - unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_) + : browser (0), + blankPageShown (false), + unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_) { - setOpaque (true); - addAndMakeVisible (browser = new WebBrowserComponentInternal()); + setOpaque (true); + addAndMakeVisible (browser = new WebBrowserComponentInternal()); } WebBrowserComponent::~WebBrowserComponent() { - delete browser; + delete browser; } void WebBrowserComponent::goToURL (const String& url, - const StringArray* headers, - const MemoryBlock* postData) + const StringArray* headers, + const MemoryBlock* postData) { - lastURL = url; + lastURL = url; - lastHeaders.clear(); - if (headers != 0) - lastHeaders = *headers; + lastHeaders.clear(); + if (headers != 0) + lastHeaders = *headers; - lastPostData.setSize (0); - if (postData != 0) - lastPostData = *postData; + lastPostData.setSize (0); + if (postData != 0) + lastPostData = *postData; - blankPageShown = false; + blankPageShown = false; - browser->goToURL (url, headers, postData); + browser->goToURL (url, headers, postData); } void WebBrowserComponent::stop() { - if (browser->browser != 0) - browser->browser->Stop(); + if (browser->browser != 0) + browser->browser->Stop(); } void WebBrowserComponent::goBack() { - lastURL = String::empty; - blankPageShown = false; + lastURL = String::empty; + blankPageShown = false; - if (browser->browser != 0) - browser->browser->GoBack(); + if (browser->browser != 0) + browser->browser->GoBack(); } void WebBrowserComponent::goForward() { - lastURL = String::empty; + lastURL = String::empty; - if (browser->browser != 0) - browser->browser->GoForward(); + if (browser->browser != 0) + browser->browser->GoForward(); } void WebBrowserComponent::refresh() { - if (browser->browser != 0) - browser->browser->Refresh(); + if (browser->browser != 0) + browser->browser->Refresh(); } void WebBrowserComponent::paint (Graphics& g) { - if (browser->browser == 0) - g.fillAll (Colours::white); + if (browser->browser == 0) + g.fillAll (Colours::white); } void WebBrowserComponent::checkWindowAssociation() { - if (isShowing()) - { - if (browser->browser == 0 && getPeer() != 0) - { - browser->createBrowser(); - reloadLastURL(); - } - else - { - if (blankPageShown) - goBack(); - } - } - else - { - if (browser != 0 && unloadPageWhenBrowserIsHidden && ! blankPageShown) - { - // when the component becomes invisible, some stuff like flash - // carries on playing audio, so we need to force it onto a blank - // page to avoid this.. + if (isShowing()) + { + if (browser->browser == 0 && getPeer() != 0) + { + browser->createBrowser(); + reloadLastURL(); + } + else + { + if (blankPageShown) + goBack(); + } + } + else + { + if (browser != 0 && unloadPageWhenBrowserIsHidden && ! blankPageShown) + { + // when the component becomes invisible, some stuff like flash + // carries on playing audio, so we need to force it onto a blank + // page to avoid this.. - blankPageShown = true; - browser->goToURL ("about:blank", 0, 0); - } - } + blankPageShown = true; + browser->goToURL ("about:blank", 0, 0); + } + } } void WebBrowserComponent::reloadLastURL() { - if (lastURL.isNotEmpty()) - { - goToURL (lastURL, &lastHeaders, &lastPostData); - lastURL = String::empty; - } + if (lastURL.isNotEmpty()) + { + goToURL (lastURL, &lastHeaders, &lastPostData); + lastURL = String::empty; + } } void WebBrowserComponent::parentHierarchyChanged() { - checkWindowAssociation(); + checkWindowAssociation(); } void WebBrowserComponent::resized() { - browser->setSize (getWidth(), getHeight()); + browser->setSize (getWidth(), getHeight()); } void WebBrowserComponent::visibilityChanged() { - checkWindowAssociation(); + checkWindowAssociation(); } bool WebBrowserComponent::pageAboutToLoad (const String&) { - return true; + return true; } #endif @@ -241824,7 +219559,7 @@ bool WebBrowserComponent::pageAboutToLoad (const String&) #if JUCE_INCLUDED_FILE && JUCE_OPENGL #define WGL_EXT_FUNCTION_INIT(extType, extFunc) \ - ((extFunc = (extType) wglGetProcAddress (#extFunc)) != 0) + ((extFunc = (extType) wglGetProcAddress (#extFunc)) != 0) typedef const char* (WINAPI* PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); @@ -241832,496 +219567,496 @@ typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int* piAt typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_SWAP_METHOD_ARB 0x2007 -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_ALPHA_BITS_ARB 0x201B -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_ACCUM_RED_BITS_ARB 0x201E -#define WGL_ACCUM_GREEN_BITS_ARB 0x201F -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_STEREO_ARB 0x2012 -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 -#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_STEREO_ARB 0x2012 +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#define WGL_TYPE_RGBA_ARB 0x202B static void getWglExtensions (HDC dc, StringArray& result) throw() { - PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0; + PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0; - if (WGL_EXT_FUNCTION_INIT (PFNWGLGETEXTENSIONSSTRINGARBPROC, wglGetExtensionsStringARB)) - result.addTokens (String (wglGetExtensionsStringARB (dc)), false); - else - jassertfalse // If this fails, it may be because you didn't activate the openGL context + if (WGL_EXT_FUNCTION_INIT (PFNWGLGETEXTENSIONSSTRINGARBPROC, wglGetExtensionsStringARB)) + result.addTokens (String (wglGetExtensionsStringARB (dc)), false); + else + jassertfalse // If this fails, it may be because you didn't activate the openGL context } -class WindowedGLContext : public OpenGLContext +class WindowedGLContext : public OpenGLContext { public: - WindowedGLContext (Component* const component_, - HGLRC contextToShareWith, - const OpenGLPixelFormat& pixelFormat) - : renderContext (0), - nativeWindow (0), - dc (0), - component (component_) - { - jassert (component != 0); + WindowedGLContext (Component* const component_, + HGLRC contextToShareWith, + const OpenGLPixelFormat& pixelFormat) + : renderContext (0), + nativeWindow (0), + dc (0), + component (component_) + { + jassert (component != 0); - createNativeWindow(); + createNativeWindow(); - // Use a default pixel format that should be supported everywhere - PIXELFORMATDESCRIPTOR pfd; - zerostruct (pfd); - pfd.nSize = sizeof (pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 24; - pfd.cDepthBits = 16; + // Use a default pixel format that should be supported everywhere + PIXELFORMATDESCRIPTOR pfd; + zerostruct (pfd); + pfd.nSize = sizeof (pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.cDepthBits = 16; - const int format = ChoosePixelFormat (dc, &pfd); + const int format = ChoosePixelFormat (dc, &pfd); - if (format != 0) - SetPixelFormat (dc, format, &pfd); + if (format != 0) + SetPixelFormat (dc, format, &pfd); - renderContext = wglCreateContext (dc); - makeActive(); + renderContext = wglCreateContext (dc); + makeActive(); - setPixelFormat (pixelFormat); + setPixelFormat (pixelFormat); - if (contextToShareWith != 0 && renderContext != 0) - wglShareLists (contextToShareWith, renderContext); - } + if (contextToShareWith != 0 && renderContext != 0) + wglShareLists (contextToShareWith, renderContext); + } - ~WindowedGLContext() - { - makeInactive(); + ~WindowedGLContext() + { + makeInactive(); - wglDeleteContext (renderContext); + wglDeleteContext (renderContext); - ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc); - delete nativeWindow; - } + ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc); + delete nativeWindow; + } - bool makeActive() const throw() - { - jassert (renderContext != 0); - return wglMakeCurrent (dc, renderContext) != 0; - } + bool makeActive() const throw() + { + jassert (renderContext != 0); + return wglMakeCurrent (dc, renderContext) != 0; + } - bool makeInactive() const throw() - { - return (! isActive()) || (wglMakeCurrent (0, 0) != 0); - } + bool makeInactive() const throw() + { + return (! isActive()) || (wglMakeCurrent (0, 0) != 0); + } - bool isActive() const throw() - { - return wglGetCurrentContext() == renderContext; - } + bool isActive() const throw() + { + return wglGetCurrentContext() == renderContext; + } - const OpenGLPixelFormat getPixelFormat() const - { - OpenGLPixelFormat pf; + const OpenGLPixelFormat getPixelFormat() const + { + OpenGLPixelFormat pf; - makeActive(); - StringArray availableExtensions; - getWglExtensions (dc, availableExtensions); + makeActive(); + StringArray availableExtensions; + getWglExtensions (dc, availableExtensions); - fillInPixelFormatDetails (GetPixelFormat (dc), pf, availableExtensions); - return pf; - } + fillInPixelFormatDetails (GetPixelFormat (dc), pf, availableExtensions); + return pf; + } - void* getRawContext() const throw() - { - return renderContext; - } + void* getRawContext() const throw() + { + return renderContext; + } - bool setPixelFormat (const OpenGLPixelFormat& pixelFormat) - { - makeActive(); + bool setPixelFormat (const OpenGLPixelFormat& pixelFormat) + { + makeActive(); - PIXELFORMATDESCRIPTOR pfd; - zerostruct (pfd); - pfd.nSize = sizeof (pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.iLayerType = PFD_MAIN_PLANE; - pfd.cColorBits = (BYTE) (pixelFormat.redBits + pixelFormat.greenBits + pixelFormat.blueBits); - pfd.cRedBits = (BYTE) pixelFormat.redBits; - pfd.cGreenBits = (BYTE) pixelFormat.greenBits; - pfd.cBlueBits = (BYTE) pixelFormat.blueBits; - pfd.cAlphaBits = (BYTE) pixelFormat.alphaBits; - pfd.cDepthBits = (BYTE) pixelFormat.depthBufferBits; - pfd.cStencilBits = (BYTE) pixelFormat.stencilBufferBits; - pfd.cAccumBits = (BYTE) (pixelFormat.accumulationBufferRedBits + pixelFormat.accumulationBufferGreenBits - + pixelFormat.accumulationBufferBlueBits + pixelFormat.accumulationBufferAlphaBits); - pfd.cAccumRedBits = (BYTE) pixelFormat.accumulationBufferRedBits; - pfd.cAccumGreenBits = (BYTE) pixelFormat.accumulationBufferGreenBits; - pfd.cAccumBlueBits = (BYTE) pixelFormat.accumulationBufferBlueBits; - pfd.cAccumAlphaBits = (BYTE) pixelFormat.accumulationBufferAlphaBits; + PIXELFORMATDESCRIPTOR pfd; + zerostruct (pfd); + pfd.nSize = sizeof (pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.iLayerType = PFD_MAIN_PLANE; + pfd.cColorBits = (BYTE) (pixelFormat.redBits + pixelFormat.greenBits + pixelFormat.blueBits); + pfd.cRedBits = (BYTE) pixelFormat.redBits; + pfd.cGreenBits = (BYTE) pixelFormat.greenBits; + pfd.cBlueBits = (BYTE) pixelFormat.blueBits; + pfd.cAlphaBits = (BYTE) pixelFormat.alphaBits; + pfd.cDepthBits = (BYTE) pixelFormat.depthBufferBits; + pfd.cStencilBits = (BYTE) pixelFormat.stencilBufferBits; + pfd.cAccumBits = (BYTE) (pixelFormat.accumulationBufferRedBits + pixelFormat.accumulationBufferGreenBits + + pixelFormat.accumulationBufferBlueBits + pixelFormat.accumulationBufferAlphaBits); + pfd.cAccumRedBits = (BYTE) pixelFormat.accumulationBufferRedBits; + pfd.cAccumGreenBits = (BYTE) pixelFormat.accumulationBufferGreenBits; + pfd.cAccumBlueBits = (BYTE) pixelFormat.accumulationBufferBlueBits; + pfd.cAccumAlphaBits = (BYTE) pixelFormat.accumulationBufferAlphaBits; - int format = 0; + int format = 0; - PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = 0; + PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = 0; - StringArray availableExtensions; - getWglExtensions (dc, availableExtensions); + StringArray availableExtensions; + getWglExtensions (dc, availableExtensions); - if (availableExtensions.contains ("WGL_ARB_pixel_format") - && WGL_EXT_FUNCTION_INIT (PFNWGLCHOOSEPIXELFORMATARBPROC, wglChoosePixelFormatARB)) - { - int attributes[64]; - int n = 0; + if (availableExtensions.contains ("WGL_ARB_pixel_format") + && WGL_EXT_FUNCTION_INIT (PFNWGLCHOOSEPIXELFORMATARBPROC, wglChoosePixelFormatARB)) + { + int attributes[64]; + int n = 0; - attributes[n++] = WGL_DRAW_TO_WINDOW_ARB; - attributes[n++] = GL_TRUE; - attributes[n++] = WGL_SUPPORT_OPENGL_ARB; - attributes[n++] = GL_TRUE; - attributes[n++] = WGL_ACCELERATION_ARB; - attributes[n++] = WGL_FULL_ACCELERATION_ARB; - attributes[n++] = WGL_DOUBLE_BUFFER_ARB; - attributes[n++] = GL_TRUE; - attributes[n++] = WGL_PIXEL_TYPE_ARB; - attributes[n++] = WGL_TYPE_RGBA_ARB; + attributes[n++] = WGL_DRAW_TO_WINDOW_ARB; + attributes[n++] = GL_TRUE; + attributes[n++] = WGL_SUPPORT_OPENGL_ARB; + attributes[n++] = GL_TRUE; + attributes[n++] = WGL_ACCELERATION_ARB; + attributes[n++] = WGL_FULL_ACCELERATION_ARB; + attributes[n++] = WGL_DOUBLE_BUFFER_ARB; + attributes[n++] = GL_TRUE; + attributes[n++] = WGL_PIXEL_TYPE_ARB; + attributes[n++] = WGL_TYPE_RGBA_ARB; - attributes[n++] = WGL_COLOR_BITS_ARB; - attributes[n++] = pfd.cColorBits; - attributes[n++] = WGL_RED_BITS_ARB; - attributes[n++] = pixelFormat.redBits; - attributes[n++] = WGL_GREEN_BITS_ARB; - attributes[n++] = pixelFormat.greenBits; - attributes[n++] = WGL_BLUE_BITS_ARB; - attributes[n++] = pixelFormat.blueBits; - attributes[n++] = WGL_ALPHA_BITS_ARB; - attributes[n++] = pixelFormat.alphaBits; - attributes[n++] = WGL_DEPTH_BITS_ARB; - attributes[n++] = pixelFormat.depthBufferBits; + attributes[n++] = WGL_COLOR_BITS_ARB; + attributes[n++] = pfd.cColorBits; + attributes[n++] = WGL_RED_BITS_ARB; + attributes[n++] = pixelFormat.redBits; + attributes[n++] = WGL_GREEN_BITS_ARB; + attributes[n++] = pixelFormat.greenBits; + attributes[n++] = WGL_BLUE_BITS_ARB; + attributes[n++] = pixelFormat.blueBits; + attributes[n++] = WGL_ALPHA_BITS_ARB; + attributes[n++] = pixelFormat.alphaBits; + attributes[n++] = WGL_DEPTH_BITS_ARB; + attributes[n++] = pixelFormat.depthBufferBits; - if (pixelFormat.stencilBufferBits > 0) - { - attributes[n++] = WGL_STENCIL_BITS_ARB; - attributes[n++] = pixelFormat.stencilBufferBits; - } + if (pixelFormat.stencilBufferBits > 0) + { + attributes[n++] = WGL_STENCIL_BITS_ARB; + attributes[n++] = pixelFormat.stencilBufferBits; + } - attributes[n++] = WGL_ACCUM_RED_BITS_ARB; - attributes[n++] = pixelFormat.accumulationBufferRedBits; - attributes[n++] = WGL_ACCUM_GREEN_BITS_ARB; - attributes[n++] = pixelFormat.accumulationBufferGreenBits; - attributes[n++] = WGL_ACCUM_BLUE_BITS_ARB; - attributes[n++] = pixelFormat.accumulationBufferBlueBits; - attributes[n++] = WGL_ACCUM_ALPHA_BITS_ARB; - attributes[n++] = pixelFormat.accumulationBufferAlphaBits; + attributes[n++] = WGL_ACCUM_RED_BITS_ARB; + attributes[n++] = pixelFormat.accumulationBufferRedBits; + attributes[n++] = WGL_ACCUM_GREEN_BITS_ARB; + attributes[n++] = pixelFormat.accumulationBufferGreenBits; + attributes[n++] = WGL_ACCUM_BLUE_BITS_ARB; + attributes[n++] = pixelFormat.accumulationBufferBlueBits; + attributes[n++] = WGL_ACCUM_ALPHA_BITS_ARB; + attributes[n++] = pixelFormat.accumulationBufferAlphaBits; - if (availableExtensions.contains ("WGL_ARB_multisample") - && pixelFormat.fullSceneAntiAliasingNumSamples > 0) - { - attributes[n++] = WGL_SAMPLE_BUFFERS_ARB; - attributes[n++] = 1; - attributes[n++] = WGL_SAMPLES_ARB; - attributes[n++] = pixelFormat.fullSceneAntiAliasingNumSamples; - } + if (availableExtensions.contains ("WGL_ARB_multisample") + && pixelFormat.fullSceneAntiAliasingNumSamples > 0) + { + attributes[n++] = WGL_SAMPLE_BUFFERS_ARB; + attributes[n++] = 1; + attributes[n++] = WGL_SAMPLES_ARB; + attributes[n++] = pixelFormat.fullSceneAntiAliasingNumSamples; + } - attributes[n++] = 0; + attributes[n++] = 0; - UINT formatsCount; - const BOOL ok = wglChoosePixelFormatARB (dc, attributes, 0, 1, &format, &formatsCount); - (void) ok; - jassert (ok); - } - else - { - format = ChoosePixelFormat (dc, &pfd); - } + UINT formatsCount; + const BOOL ok = wglChoosePixelFormatARB (dc, attributes, 0, 1, &format, &formatsCount); + (void) ok; + jassert (ok); + } + else + { + format = ChoosePixelFormat (dc, &pfd); + } - if (format != 0) - { - makeInactive(); + if (format != 0) + { + makeInactive(); - // win32 can't change the pixel format of a window, so need to delete the - // old one and create a new one.. - jassert (nativeWindow != 0); - ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc); - delete nativeWindow; + // win32 can't change the pixel format of a window, so need to delete the + // old one and create a new one.. + jassert (nativeWindow != 0); + ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc); + delete nativeWindow; - createNativeWindow(); + createNativeWindow(); - if (SetPixelFormat (dc, format, &pfd)) - { - wglDeleteContext (renderContext); - renderContext = wglCreateContext (dc); + if (SetPixelFormat (dc, format, &pfd)) + { + wglDeleteContext (renderContext); + renderContext = wglCreateContext (dc); - jassert (renderContext != 0); - return renderContext != 0; - } - } + jassert (renderContext != 0); + return renderContext != 0; + } + } - return false; - } + return false; + } - void updateWindowPosition (int x, int y, int w, int h, int) - { - SetWindowPos ((HWND) nativeWindow->getNativeHandle(), 0, - x, y, w, h, - SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); - } + void updateWindowPosition (int x, int y, int w, int h, int) + { + SetWindowPos ((HWND) nativeWindow->getNativeHandle(), 0, + x, y, w, h, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); + } - void repaint() - { - int x, y, w, h; - nativeWindow->getBounds (x, y, w, h); - nativeWindow->repaint (0, 0, w, h); - } + void repaint() + { + int x, y, w, h; + nativeWindow->getBounds (x, y, w, h); + nativeWindow->repaint (0, 0, w, h); + } - void swapBuffers() - { - SwapBuffers (dc); - } + void swapBuffers() + { + SwapBuffers (dc); + } - bool setSwapInterval (const int numFramesPerSwap) - { - makeActive(); + bool setSwapInterval (const int numFramesPerSwap) + { + makeActive(); - StringArray availableExtensions; - getWglExtensions (dc, availableExtensions); + StringArray availableExtensions; + getWglExtensions (dc, availableExtensions); - PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = 0; + PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = 0; - return availableExtensions.contains ("WGL_EXT_swap_control") - && WGL_EXT_FUNCTION_INIT (PFNWGLSWAPINTERVALEXTPROC, wglSwapIntervalEXT) - && wglSwapIntervalEXT (numFramesPerSwap) != FALSE; - } + return availableExtensions.contains ("WGL_EXT_swap_control") + && WGL_EXT_FUNCTION_INIT (PFNWGLSWAPINTERVALEXTPROC, wglSwapIntervalEXT) + && wglSwapIntervalEXT (numFramesPerSwap) != FALSE; + } - int getSwapInterval() const - { - makeActive(); + int getSwapInterval() const + { + makeActive(); - StringArray availableExtensions; - getWglExtensions (dc, availableExtensions); + StringArray availableExtensions; + getWglExtensions (dc, availableExtensions); - PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = 0; + PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = 0; - if (availableExtensions.contains ("WGL_EXT_swap_control") - && WGL_EXT_FUNCTION_INIT (PFNWGLGETSWAPINTERVALEXTPROC, wglGetSwapIntervalEXT)) - return wglGetSwapIntervalEXT(); + if (availableExtensions.contains ("WGL_EXT_swap_control") + && WGL_EXT_FUNCTION_INIT (PFNWGLGETSWAPINTERVALEXTPROC, wglGetSwapIntervalEXT)) + return wglGetSwapIntervalEXT(); - return 0; - } + return 0; + } - void findAlternativeOpenGLPixelFormats (OwnedArray & results) - { - jassert (isActive()); + void findAlternativeOpenGLPixelFormats (OwnedArray & results) + { + jassert (isActive()); - StringArray availableExtensions; - getWglExtensions (dc, availableExtensions); + StringArray availableExtensions; + getWglExtensions (dc, availableExtensions); - PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = 0; - int numTypes = 0; + PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = 0; + int numTypes = 0; - if (availableExtensions.contains("WGL_ARB_pixel_format") - && WGL_EXT_FUNCTION_INIT (PFNWGLGETPIXELFORMATATTRIBIVARBPROC, wglGetPixelFormatAttribivARB)) - { - int attributes = WGL_NUMBER_PIXEL_FORMATS_ARB; + if (availableExtensions.contains("WGL_ARB_pixel_format") + && WGL_EXT_FUNCTION_INIT (PFNWGLGETPIXELFORMATATTRIBIVARBPROC, wglGetPixelFormatAttribivARB)) + { + int attributes = WGL_NUMBER_PIXEL_FORMATS_ARB; - if (! wglGetPixelFormatAttribivARB (dc, 1, 0, 1, &attributes, &numTypes)) - jassertfalse - } - else - { - numTypes = DescribePixelFormat (dc, 0, 0, 0); - } + if (! wglGetPixelFormatAttribivARB (dc, 1, 0, 1, &attributes, &numTypes)) + jassertfalse + } + else + { + numTypes = DescribePixelFormat (dc, 0, 0, 0); + } - OpenGLPixelFormat pf; + OpenGLPixelFormat pf; - for (int i = 0; i < numTypes; ++i) - { - if (fillInPixelFormatDetails (i + 1, pf, availableExtensions)) - { - bool alreadyListed = false; - for (int j = results.size(); --j >= 0;) - if (pf == *results.getUnchecked(j)) - alreadyListed = true; + for (int i = 0; i < numTypes; ++i) + { + if (fillInPixelFormatDetails (i + 1, pf, availableExtensions)) + { + bool alreadyListed = false; + for (int j = results.size(); --j >= 0;) + if (pf == *results.getUnchecked(j)) + alreadyListed = true; - if (! alreadyListed) - results.add (new OpenGLPixelFormat (pf)); - } - } - } + if (! alreadyListed) + results.add (new OpenGLPixelFormat (pf)); + } + } + } - void* getNativeWindowHandle() const - { - return nativeWindow != 0 ? nativeWindow->getNativeHandle() : 0; - } + void* getNativeWindowHandle() const + { + return nativeWindow != 0 ? nativeWindow->getNativeHandle() : 0; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - HGLRC renderContext; + HGLRC renderContext; private: - Win32ComponentPeer* nativeWindow; - Component* const component; - HDC dc; + Win32ComponentPeer* nativeWindow; + Component* const component; + HDC dc; - void createNativeWindow() - { - nativeWindow = new Win32ComponentPeer (component, 0); - nativeWindow->dontRepaint = true; - nativeWindow->setVisible (true); + void createNativeWindow() + { + nativeWindow = new Win32ComponentPeer (component, 0); + nativeWindow->dontRepaint = true; + nativeWindow->setVisible (true); - HWND hwnd = (HWND) nativeWindow->getNativeHandle(); + HWND hwnd = (HWND) nativeWindow->getNativeHandle(); - Win32ComponentPeer* const peer = dynamic_cast (component->getTopLevelComponent()->getPeer()); + Win32ComponentPeer* const peer = dynamic_cast (component->getTopLevelComponent()->getPeer()); - if (peer != 0) - { - SetParent (hwnd, (HWND) peer->getNativeHandle()); - juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_CHILD, true); - juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_POPUP, false); - } + if (peer != 0) + { + SetParent (hwnd, (HWND) peer->getNativeHandle()); + juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_CHILD, true); + juce_setWindowStyleBit (hwnd, GWL_STYLE, WS_POPUP, false); + } - dc = GetDC (hwnd); - } + dc = GetDC (hwnd); + } - bool fillInPixelFormatDetails (const int pixelFormatIndex, - OpenGLPixelFormat& result, - const StringArray& availableExtensions) const throw() - { - PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = 0; + bool fillInPixelFormatDetails (const int pixelFormatIndex, + OpenGLPixelFormat& result, + const StringArray& availableExtensions) const throw() + { + PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = 0; - if (availableExtensions.contains ("WGL_ARB_pixel_format") - && WGL_EXT_FUNCTION_INIT (PFNWGLGETPIXELFORMATATTRIBIVARBPROC, wglGetPixelFormatAttribivARB)) - { - int attributes[32]; - int numAttributes = 0; + if (availableExtensions.contains ("WGL_ARB_pixel_format") + && WGL_EXT_FUNCTION_INIT (PFNWGLGETPIXELFORMATATTRIBIVARBPROC, wglGetPixelFormatAttribivARB)) + { + int attributes[32]; + int numAttributes = 0; - attributes[numAttributes++] = WGL_DRAW_TO_WINDOW_ARB; - attributes[numAttributes++] = WGL_SUPPORT_OPENGL_ARB; - attributes[numAttributes++] = WGL_ACCELERATION_ARB; - attributes[numAttributes++] = WGL_DOUBLE_BUFFER_ARB; - attributes[numAttributes++] = WGL_PIXEL_TYPE_ARB; - attributes[numAttributes++] = WGL_RED_BITS_ARB; - attributes[numAttributes++] = WGL_GREEN_BITS_ARB; - attributes[numAttributes++] = WGL_BLUE_BITS_ARB; - attributes[numAttributes++] = WGL_ALPHA_BITS_ARB; - attributes[numAttributes++] = WGL_DEPTH_BITS_ARB; - attributes[numAttributes++] = WGL_STENCIL_BITS_ARB; - attributes[numAttributes++] = WGL_ACCUM_RED_BITS_ARB; - attributes[numAttributes++] = WGL_ACCUM_GREEN_BITS_ARB; - attributes[numAttributes++] = WGL_ACCUM_BLUE_BITS_ARB; - attributes[numAttributes++] = WGL_ACCUM_ALPHA_BITS_ARB; + attributes[numAttributes++] = WGL_DRAW_TO_WINDOW_ARB; + attributes[numAttributes++] = WGL_SUPPORT_OPENGL_ARB; + attributes[numAttributes++] = WGL_ACCELERATION_ARB; + attributes[numAttributes++] = WGL_DOUBLE_BUFFER_ARB; + attributes[numAttributes++] = WGL_PIXEL_TYPE_ARB; + attributes[numAttributes++] = WGL_RED_BITS_ARB; + attributes[numAttributes++] = WGL_GREEN_BITS_ARB; + attributes[numAttributes++] = WGL_BLUE_BITS_ARB; + attributes[numAttributes++] = WGL_ALPHA_BITS_ARB; + attributes[numAttributes++] = WGL_DEPTH_BITS_ARB; + attributes[numAttributes++] = WGL_STENCIL_BITS_ARB; + attributes[numAttributes++] = WGL_ACCUM_RED_BITS_ARB; + attributes[numAttributes++] = WGL_ACCUM_GREEN_BITS_ARB; + attributes[numAttributes++] = WGL_ACCUM_BLUE_BITS_ARB; + attributes[numAttributes++] = WGL_ACCUM_ALPHA_BITS_ARB; - if (availableExtensions.contains ("WGL_ARB_multisample")) - attributes[numAttributes++] = WGL_SAMPLES_ARB; + if (availableExtensions.contains ("WGL_ARB_multisample")) + attributes[numAttributes++] = WGL_SAMPLES_ARB; - int values[32]; - zeromem (values, sizeof (values)); + int values[32]; + zeromem (values, sizeof (values)); - if (wglGetPixelFormatAttribivARB (dc, pixelFormatIndex, 0, numAttributes, attributes, values)) - { - int n = 0; - bool isValidFormat = (values[n++] == GL_TRUE); // WGL_DRAW_TO_WINDOW_ARB - isValidFormat = (values[n++] == GL_TRUE) && isValidFormat; // WGL_SUPPORT_OPENGL_ARB - isValidFormat = (values[n++] == WGL_FULL_ACCELERATION_ARB) && isValidFormat; // WGL_ACCELERATION_ARB - isValidFormat = (values[n++] == GL_TRUE) && isValidFormat; // WGL_DOUBLE_BUFFER_ARB: - isValidFormat = (values[n++] == WGL_TYPE_RGBA_ARB) && isValidFormat; // WGL_PIXEL_TYPE_ARB - result.redBits = values[n++]; // WGL_RED_BITS_ARB - result.greenBits = values[n++]; // WGL_GREEN_BITS_ARB - result.blueBits = values[n++]; // WGL_BLUE_BITS_ARB - result.alphaBits = values[n++]; // WGL_ALPHA_BITS_ARB - result.depthBufferBits = values[n++]; // WGL_DEPTH_BITS_ARB - result.stencilBufferBits = values[n++]; // WGL_STENCIL_BITS_ARB - result.accumulationBufferRedBits = values[n++]; // WGL_ACCUM_RED_BITS_ARB - result.accumulationBufferGreenBits = values[n++]; // WGL_ACCUM_GREEN_BITS_ARB - result.accumulationBufferBlueBits = values[n++]; // WGL_ACCUM_BLUE_BITS_ARB - result.accumulationBufferAlphaBits = values[n++]; // WGL_ACCUM_ALPHA_BITS_ARB - result.fullSceneAntiAliasingNumSamples = (uint8) values[n++]; // WGL_SAMPLES_ARB + if (wglGetPixelFormatAttribivARB (dc, pixelFormatIndex, 0, numAttributes, attributes, values)) + { + int n = 0; + bool isValidFormat = (values[n++] == GL_TRUE); // WGL_DRAW_TO_WINDOW_ARB + isValidFormat = (values[n++] == GL_TRUE) && isValidFormat; // WGL_SUPPORT_OPENGL_ARB + isValidFormat = (values[n++] == WGL_FULL_ACCELERATION_ARB) && isValidFormat; // WGL_ACCELERATION_ARB + isValidFormat = (values[n++] == GL_TRUE) && isValidFormat; // WGL_DOUBLE_BUFFER_ARB: + isValidFormat = (values[n++] == WGL_TYPE_RGBA_ARB) && isValidFormat; // WGL_PIXEL_TYPE_ARB + result.redBits = values[n++]; // WGL_RED_BITS_ARB + result.greenBits = values[n++]; // WGL_GREEN_BITS_ARB + result.blueBits = values[n++]; // WGL_BLUE_BITS_ARB + result.alphaBits = values[n++]; // WGL_ALPHA_BITS_ARB + result.depthBufferBits = values[n++]; // WGL_DEPTH_BITS_ARB + result.stencilBufferBits = values[n++]; // WGL_STENCIL_BITS_ARB + result.accumulationBufferRedBits = values[n++]; // WGL_ACCUM_RED_BITS_ARB + result.accumulationBufferGreenBits = values[n++]; // WGL_ACCUM_GREEN_BITS_ARB + result.accumulationBufferBlueBits = values[n++]; // WGL_ACCUM_BLUE_BITS_ARB + result.accumulationBufferAlphaBits = values[n++]; // WGL_ACCUM_ALPHA_BITS_ARB + result.fullSceneAntiAliasingNumSamples = (uint8) values[n++]; // WGL_SAMPLES_ARB - return isValidFormat; - } - else - { - jassertfalse - } - } - else - { - PIXELFORMATDESCRIPTOR pfd; + return isValidFormat; + } + else + { + jassertfalse + } + } + else + { + PIXELFORMATDESCRIPTOR pfd; - if (DescribePixelFormat (dc, pixelFormatIndex, sizeof (pfd), &pfd)) - { - result.redBits = pfd.cRedBits; - result.greenBits = pfd.cGreenBits; - result.blueBits = pfd.cBlueBits; - result.alphaBits = pfd.cAlphaBits; - result.depthBufferBits = pfd.cDepthBits; - result.stencilBufferBits = pfd.cStencilBits; - result.accumulationBufferRedBits = pfd.cAccumRedBits; - result.accumulationBufferGreenBits = pfd.cAccumGreenBits; - result.accumulationBufferBlueBits = pfd.cAccumBlueBits; - result.accumulationBufferAlphaBits = pfd.cAccumAlphaBits; - result.fullSceneAntiAliasingNumSamples = 0; + if (DescribePixelFormat (dc, pixelFormatIndex, sizeof (pfd), &pfd)) + { + result.redBits = pfd.cRedBits; + result.greenBits = pfd.cGreenBits; + result.blueBits = pfd.cBlueBits; + result.alphaBits = pfd.cAlphaBits; + result.depthBufferBits = pfd.cDepthBits; + result.stencilBufferBits = pfd.cStencilBits; + result.accumulationBufferRedBits = pfd.cAccumRedBits; + result.accumulationBufferGreenBits = pfd.cAccumGreenBits; + result.accumulationBufferBlueBits = pfd.cAccumBlueBits; + result.accumulationBufferAlphaBits = pfd.cAccumAlphaBits; + result.fullSceneAntiAliasingNumSamples = 0; - return true; - } - else - { - jassertfalse - } - } + return true; + } + else + { + jassertfalse + } + } - return false; - } + return false; + } - WindowedGLContext (const WindowedGLContext&); - const WindowedGLContext& operator= (const WindowedGLContext&); + WindowedGLContext (const WindowedGLContext&); + const WindowedGLContext& operator= (const WindowedGLContext&); }; OpenGLContext* OpenGLContext::createContextForWindow (Component* const component, - const OpenGLPixelFormat& pixelFormat, - const OpenGLContext* const contextToShareWith) + const OpenGLPixelFormat& pixelFormat, + const OpenGLContext* const contextToShareWith) { - WindowedGLContext* c = new WindowedGLContext (component, - contextToShareWith != 0 ? (HGLRC) contextToShareWith->getRawContext() : 0, - pixelFormat); + WindowedGLContext* c = new WindowedGLContext (component, + contextToShareWith != 0 ? (HGLRC) contextToShareWith->getRawContext() : 0, + pixelFormat); - if (c->renderContext == 0) - deleteAndZero (c); + if (c->renderContext == 0) + deleteAndZero (c); - return c; + return c; } void* OpenGLComponent::getNativeWindowHandle() const { - return context != 0 ? ((WindowedGLContext*) context)->getNativeWindowHandle() : 0; + return context != 0 ? ((WindowedGLContext*) context)->getNativeWindowHandle() : 0; } void juce_glViewport (const int w, const int h) { - glViewport (0, 0, w, h); + glViewport (0, 0, w, h); } void OpenGLPixelFormat::getAvailablePixelFormats (Component* component, - OwnedArray & results) + OwnedArray & results) { - Component tempComp; + Component tempComp; - { - WindowedGLContext wc (component, 0, OpenGLPixelFormat (8, 8, 16, 0)); - wc.makeActive(); - wc.findAlternativeOpenGLPixelFormats (results); - } + { + WindowedGLContext wc (component, 0, OpenGLPixelFormat (8, 8, 16, 0)); + wc.makeActive(); + wc.findAlternativeOpenGLPixelFormats (results); + } } #endif @@ -242335,257 +220070,257 @@ void OpenGLPixelFormat::getAvailablePixelFormats (Component* component, #if JUCE_USE_CDREADER //*************************************************************************** -// %%% TARGET STATUS VALUES %%% +// %%% TARGET STATUS VALUES %%% //*************************************************************************** -#define STATUS_GOOD 0x00 // Status Good -#define STATUS_CHKCOND 0x02 // Check Condition -#define STATUS_CONDMET 0x04 // Condition Met -#define STATUS_BUSY 0x08 // Busy -#define STATUS_INTERM 0x10 // Intermediate -#define STATUS_INTCDMET 0x14 // Intermediate-condition met -#define STATUS_RESCONF 0x18 // Reservation conflict -#define STATUS_COMTERM 0x22 // Command Terminated -#define STATUS_QFULL 0x28 // Queue full +#define STATUS_GOOD 0x00 // Status Good +#define STATUS_CHKCOND 0x02 // Check Condition +#define STATUS_CONDMET 0x04 // Condition Met +#define STATUS_BUSY 0x08 // Busy +#define STATUS_INTERM 0x10 // Intermediate +#define STATUS_INTCDMET 0x14 // Intermediate-condition met +#define STATUS_RESCONF 0x18 // Reservation conflict +#define STATUS_COMTERM 0x22 // Command Terminated +#define STATUS_QFULL 0x28 // Queue full //*************************************************************************** -// %%% SCSI MISCELLANEOUS EQUATES %%% +// %%% SCSI MISCELLANEOUS EQUATES %%% //*************************************************************************** -#define MAXLUN 7 // Maximum Logical Unit Id -#define MAXTARG 7 // Maximum Target Id -#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs -#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's +#define MAXLUN 7 // Maximum Logical Unit Id +#define MAXTARG 7 // Maximum Target Id +#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs +#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's //*************************************************************************** -// %%% Commands for all Device Types %%% +// %%% Commands for all Device Types %%% //*************************************************************************** -#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) -#define SCSI_COMPARE 0x39 // Compare (O) -#define SCSI_COPY 0x18 // Copy (O) -#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) -#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) -#define SCSI_LOG_SELECT 0x4C // Log Select (O) -#define SCSI_LOG_SENSE 0x4D // Log Sense (O) -#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) -#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) -#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) -#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) -#define SCSI_READ_BUFF 0x3C // Read Buffer (O) -#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) -#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) -#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) -#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) +#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) +#define SCSI_COMPARE 0x39 // Compare (O) +#define SCSI_COPY 0x18 // Copy (O) +#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) +#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) +#define SCSI_LOG_SELECT 0x4C // Log Select (O) +#define SCSI_LOG_SENSE 0x4D // Log Sense (O) +#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) +#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) +#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) +#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) +#define SCSI_READ_BUFF 0x3C // Read Buffer (O) +#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) +#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) +#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) +#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) //*************************************************************************** -// %%% Commands Unique to Direct Access Devices %%% +// %%% Commands Unique to Direct Access Devices %%% //*************************************************************************** -#define SCSI_COMPARE 0x39 // Compare (O) -#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) -#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) -#define SCSI_PREFETCH 0x34 // Prefetch (O) -#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) -#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) -#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) -#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) -#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) -#define SCSI_READ_LONG 0x3E // Read Long (O) -#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) -#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) -#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) -#define SCSI_REZERO 0x01 // Rezero Unit (O) -#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) -#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) -#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) -#define SCSI_SEEK6 0x0B // Seek 6-Byte (O) -#define SCSI_SEEK10 0x2B // Seek 10-Byte (O) -#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) -#define SCSI_SET_LIMIT 0x33 // Set Limits (O) -#define SCSI_START_STP 0x1B // Start/Stop Unit (O) -#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) -#define SCSI_VERIFY 0x2F // Verify (O) -#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) -#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) -#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) -#define SCSI_WRITE_LONG 0x3F // Write Long (O) -#define SCSI_WRITE_SAME 0x41 // Write Same (O) +#define SCSI_COMPARE 0x39 // Compare (O) +#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) +#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) +#define SCSI_PREFETCH 0x34 // Prefetch (O) +#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) +#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) +#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) +#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) +#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) +#define SCSI_READ_LONG 0x3E // Read Long (O) +#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) +#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) +#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) +#define SCSI_REZERO 0x01 // Rezero Unit (O) +#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) +#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) +#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) +#define SCSI_SEEK6 0x0B // Seek 6-Byte (O) +#define SCSI_SEEK10 0x2B // Seek 10-Byte (O) +#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) +#define SCSI_SET_LIMIT 0x33 // Set Limits (O) +#define SCSI_START_STP 0x1B // Start/Stop Unit (O) +#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) +#define SCSI_VERIFY 0x2F // Verify (O) +#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) +#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) +#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) +#define SCSI_WRITE_LONG 0x3F // Write Long (O) +#define SCSI_WRITE_SAME 0x41 // Write Same (O) //*************************************************************************** // %%% Commands Unique to Sequential Access Devices %%% //*************************************************************************** -#define SCSI_ERASE 0x19 // Erase (MANDATORY) -#define SCSI_LOAD_UN 0x1b // Load/Unload (O) -#define SCSI_LOCATE 0x2B // Locate (O) -#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) -#define SCSI_READ_POS 0x34 // Read Position (O) -#define SCSI_READ_REV 0x0F // Read Reverse (O) -#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) -#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) -#define SCSI_REWIND 0x01 // Rewind (MANDATORY) -#define SCSI_SPACE 0x11 // Space (MANDATORY) -#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) -#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) +#define SCSI_ERASE 0x19 // Erase (MANDATORY) +#define SCSI_LOAD_UN 0x1b // Load/Unload (O) +#define SCSI_LOCATE 0x2B // Locate (O) +#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) +#define SCSI_READ_POS 0x34 // Read Position (O) +#define SCSI_READ_REV 0x0F // Read Reverse (O) +#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) +#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) +#define SCSI_REWIND 0x01 // Rewind (MANDATORY) +#define SCSI_SPACE 0x11 // Space (MANDATORY) +#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) +#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) //*************************************************************************** -// %%% Commands Unique to Printer Devices %%% +// %%% Commands Unique to Printer Devices %%% //*************************************************************************** -#define SCSI_PRINT 0x0A // Print (MANDATORY) -#define SCSI_SLEW_PNT 0x0B // Slew and Print (O) -#define SCSI_STOP_PNT 0x1B // Stop Print (O) -#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) +#define SCSI_PRINT 0x0A // Print (MANDATORY) +#define SCSI_SLEW_PNT 0x0B // Slew and Print (O) +#define SCSI_STOP_PNT 0x1B // Stop Print (O) +#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) //*************************************************************************** -// %%% Commands Unique to Processor Devices %%% +// %%% Commands Unique to Processor Devices %%% //*************************************************************************** -#define SCSI_RECEIVE 0x08 // Receive (O) -#define SCSI_SEND 0x0A // Send (O) +#define SCSI_RECEIVE 0x08 // Receive (O) +#define SCSI_SEND 0x0A // Send (O) //*************************************************************************** -// %%% Commands Unique to Write-Once Devices %%% +// %%% Commands Unique to Write-Once Devices %%% //*************************************************************************** -#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) -#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) -#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) -#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) -#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) -#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) -#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) -#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) -#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) -#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) -#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) -#define SCSI_WRITE12 0xAA // Write 12-Byte (O) -#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) -#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) +#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) +#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) +#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) +#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) +#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) +#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) +#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) +#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) +#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) +#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) +#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) +#define SCSI_WRITE12 0xAA // Write 12-Byte (O) +#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) +#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) //*************************************************************************** -// %%% Commands Unique to CD-ROM Devices %%% +// %%% Commands Unique to CD-ROM Devices %%% //*************************************************************************** -#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) -#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) -#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) -#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) -#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) -#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) -#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) -#define SCSI_READHEADER 0x44 // Read Header (O) -#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) -#define SCSI_READ_TOC 0x43 // Read TOC (O) +#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) +#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) +#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) +#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) +#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) +#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) +#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) +#define SCSI_READHEADER 0x44 // Read Header (O) +#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) +#define SCSI_READ_TOC 0x43 // Read TOC (O) //*************************************************************************** -// %%% Commands Unique to Scanner Devices %%% +// %%% Commands Unique to Scanner Devices %%% //*************************************************************************** -#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) -#define SCSI_GETWINDOW 0x25 // Get Window (O) -#define SCSI_OBJECTPOS 0x31 // Object Postion (O) -#define SCSI_SCAN 0x1B // Scan (O) -#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) +#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) +#define SCSI_GETWINDOW 0x25 // Get Window (O) +#define SCSI_OBJECTPOS 0x31 // Object Postion (O) +#define SCSI_SCAN 0x1B // Scan (O) +#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) //*************************************************************************** -// %%% Commands Unique to Optical Memory Devices %%% +// %%% Commands Unique to Optical Memory Devices %%% //*************************************************************************** -#define SCSI_UpdateBlk 0x3D // Update Block (O) +#define SCSI_UpdateBlk 0x3D // Update Block (O) //*************************************************************************** -// %%% Commands Unique to Medium Changer Devices %%% +// %%% Commands Unique to Medium Changer Devices %%% //*************************************************************************** -#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) -#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) -#define SCSI_POSTOELEM 0x2B // Position to Element (O) -#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) -#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) +#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) +#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) +#define SCSI_POSTOELEM 0x2B // Position to Element (O) +#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) +#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) //*************************************************************************** -// %%% Commands Unique to Communication Devices %%% +// %%% Commands Unique to Communication Devices %%% //*************************************************************************** -#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) -#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) -#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) -#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) -#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) -#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) +#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) +#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) +#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) +#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) +#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) +#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) //*************************************************************************** -// %%% Request Sense Data Format %%% +// %%% Request Sense Data Format %%% //*************************************************************************** typedef struct { - BYTE ErrorCode; // Error Code (70H or 71H) - BYTE SegmentNum; // Number of current segment descriptor - BYTE SenseKey; // Sense Key(See bit definitions too) - BYTE InfoByte0; // Information MSB - BYTE InfoByte1; // Information MID - BYTE InfoByte2; // Information MID - BYTE InfoByte3; // Information LSB - BYTE AddSenLen; // Additional Sense Length - BYTE ComSpecInf0; // Command Specific Information MSB - BYTE ComSpecInf1; // Command Specific Information MID - BYTE ComSpecInf2; // Command Specific Information MID - BYTE ComSpecInf3; // Command Specific Information LSB - BYTE AddSenseCode; // Additional Sense Code - BYTE AddSenQual; // Additional Sense Code Qualifier + BYTE ErrorCode; // Error Code (70H or 71H) + BYTE SegmentNum; // Number of current segment descriptor + BYTE SenseKey; // Sense Key(See bit definitions too) + BYTE InfoByte0; // Information MSB + BYTE InfoByte1; // Information MID + BYTE InfoByte2; // Information MID + BYTE InfoByte3; // Information LSB + BYTE AddSenLen; // Additional Sense Length + BYTE ComSpecInf0; // Command Specific Information MSB + BYTE ComSpecInf1; // Command Specific Information MID + BYTE ComSpecInf2; // Command Specific Information MID + BYTE ComSpecInf3; // Command Specific Information LSB + BYTE AddSenseCode; // Additional Sense Code + BYTE AddSenQual; // Additional Sense Code Qualifier BYTE FieldRepUCode; // Field Replaceable Unit Code - BYTE SenKeySpec15; // Sense Key Specific 15th byte - BYTE SenKeySpec16; // Sense Key Specific 16th byte - BYTE SenKeySpec17; // Sense Key Specific 17th byte + BYTE SenKeySpec15; // Sense Key Specific 15th byte + BYTE SenKeySpec16; // Sense Key Specific 16th byte + BYTE SenKeySpec17; // Sense Key Specific 17th byte BYTE AddSenseBytes; // Additional Sense Bytes } SENSE_DATA_FMT; //*************************************************************************** -// %%% REQUEST SENSE ERROR CODE %%% +// %%% REQUEST SENSE ERROR CODE %%% //*************************************************************************** -#define SERROR_CURRENT 0x70 // Current Errors -#define SERROR_DEFERED 0x71 // Deferred Errors +#define SERROR_CURRENT 0x70 // Current Errors +#define SERROR_DEFERED 0x71 // Deferred Errors //*************************************************************************** -// %%% REQUEST SENSE BIT DEFINITIONS %%% +// %%% REQUEST SENSE BIT DEFINITIONS %%% //*************************************************************************** -#define SENSE_VALID 0x80 // Byte 0 Bit 7 -#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 -#define SENSE_EOM 0x40 // Byte 2 Bit 6 -#define SENSE_ILI 0x20 // Byte 2 Bit 5 +#define SENSE_VALID 0x80 // Byte 0 Bit 7 +#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 +#define SENSE_EOM 0x40 // Byte 2 Bit 6 +#define SENSE_ILI 0x20 // Byte 2 Bit 5 //*************************************************************************** -// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% +// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% //*************************************************************************** -#define KEY_NOSENSE 0x00 // No Sense -#define KEY_RECERROR 0x01 // Recovered Error -#define KEY_NOTREADY 0x02 // Not Ready -#define KEY_MEDIUMERR 0x03 // Medium Error -#define KEY_HARDERROR 0x04 // Hardware Error -#define KEY_ILLGLREQ 0x05 // Illegal Request -#define KEY_UNITATT 0x06 // Unit Attention -#define KEY_DATAPROT 0x07 // Data Protect -#define KEY_BLANKCHK 0x08 // Blank Check -#define KEY_VENDSPEC 0x09 // Vendor Specific -#define KEY_COPYABORT 0x0A // Copy Abort -#define KEY_EQUAL 0x0C // Equal (Search) -#define KEY_VOLOVRFLW 0x0D // Volume Overflow -#define KEY_MISCOMP 0x0E // Miscompare (Search) -#define KEY_RESERVED 0x0F // Reserved +#define KEY_NOSENSE 0x00 // No Sense +#define KEY_RECERROR 0x01 // Recovered Error +#define KEY_NOTREADY 0x02 // Not Ready +#define KEY_MEDIUMERR 0x03 // Medium Error +#define KEY_HARDERROR 0x04 // Hardware Error +#define KEY_ILLGLREQ 0x05 // Illegal Request +#define KEY_UNITATT 0x06 // Unit Attention +#define KEY_DATAPROT 0x07 // Data Protect +#define KEY_BLANKCHK 0x08 // Blank Check +#define KEY_VENDSPEC 0x09 // Vendor Specific +#define KEY_COPYABORT 0x0A // Copy Abort +#define KEY_EQUAL 0x0C // Equal (Search) +#define KEY_VOLOVRFLW 0x0D // Volume Overflow +#define KEY_MISCOMP 0x0E // Miscompare (Search) +#define KEY_RESERVED 0x0F // Reserved //*************************************************************************** -// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% +// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% //*************************************************************************** -#define DTYPE_DASD 0x00 // Disk Device -#define DTYPE_SEQD 0x01 // Tape Device -#define DTYPE_PRNT 0x02 // Printer -#define DTYPE_PROC 0x03 // Processor -#define DTYPE_WORM 0x04 // Write-once read-multiple -#define DTYPE_CROM 0x05 // CD-ROM device -#define DTYPE_SCAN 0x06 // Scanner device -#define DTYPE_OPTI 0x07 // Optical memory device -#define DTYPE_JUKE 0x08 // Medium Changer device -#define DTYPE_COMM 0x09 // Communications device -#define DTYPE_RESL 0x0A // Reserved (low) -#define DTYPE_RESH 0x1E // Reserved (high) -#define DTYPE_UNKNOWN 0x1F // Unknown or no device type +#define DTYPE_DASD 0x00 // Disk Device +#define DTYPE_SEQD 0x01 // Tape Device +#define DTYPE_PRNT 0x02 // Printer +#define DTYPE_PROC 0x03 // Processor +#define DTYPE_WORM 0x04 // Write-once read-multiple +#define DTYPE_CROM 0x05 // CD-ROM device +#define DTYPE_SCAN 0x06 // Scanner device +#define DTYPE_OPTI 0x07 // Optical memory device +#define DTYPE_JUKE 0x08 // Medium Changer device +#define DTYPE_COMM 0x09 // Communications device +#define DTYPE_RESL 0x0A // Reserved (low) +#define DTYPE_RESH 0x1E // Reserved (high) +#define DTYPE_UNKNOWN 0x1F // Unknown or no device type //*************************************************************************** -// %%% ANSI APPROVED VERSION DEFINITIONS %%% +// %%% ANSI APPROVED VERSION DEFINITIONS %%% //*************************************************************************** -#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand -#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) -#define ANSI_SCSI2 0x2 // Device complies to SCSI-2 -#define ANSI_RESLO 0x3 // Reserved (low) -#define ANSI_RESHI 0x7 // Reserved (high) +#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand +#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) +#define ANSI_SCSI2 0x2 // Device complies to SCSI-2 +#define ANSI_RESLO 0x3 // Reserved (low) +#define ANSI_RESHI 0x7 // Reserved (high) typedef struct { @@ -242637,88 +220372,88 @@ typedef struct UCHAR Lun; } SCSI_ADDRESS, *PSCSI_ADDRESS; -#define METHOD_BUFFERED 0 -#define METHOD_IN_DIRECT 1 +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 #define METHOD_OUT_DIRECT 2 -#define METHOD_NEITHER 3 +#define METHOD_NEITHER 3 -#define FILE_ANY_ACCESS 0 +#define FILE_ANY_ACCESS 0 #ifndef FILE_READ_ACCESS -#define FILE_READ_ACCESS (0x0001) +#define FILE_READ_ACCESS (0x0001) #endif #ifndef FILE_WRITE_ACCESS -#define FILE_WRITE_ACCESS (0x0002) +#define FILE_WRITE_ACCESS (0x0002) #endif -#define IOCTL_SCSI_BASE 0x00000004 +#define IOCTL_SCSI_BASE 0x00000004 -#define SCSI_IOCTL_DATA_OUT 0 -#define SCSI_IOCTL_DATA_IN 1 +#define SCSI_IOCTL_DATA_OUT 0 +#define SCSI_IOCTL_DATA_IN 1 #define SCSI_IOCTL_DATA_UNSPECIFIED 2 -#define CTL_CODE2( DevType, Function, Method, Access ) ( \ - ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ +#define CTL_CODE2( DevType, Function, Method, Access ) ( \ + ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ ) -#define IOCTL_SCSI_PASS_THROUGH CTL_CODE2( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) -#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE2( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_PASS_THROUGH CTL_CODE2( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) +#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE2( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE2( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) -#define IOCTL_SCSI_GET_ADDRESS CTL_CODE2( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS ) +#define IOCTL_SCSI_GET_ADDRESS CTL_CODE2( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS ) -#define SENSE_LEN 14 -#define SRB_DIR_SCSI 0x00 -#define SRB_POSTING 0x01 +#define SENSE_LEN 14 +#define SRB_DIR_SCSI 0x00 +#define SRB_POSTING 0x01 #define SRB_ENABLE_RESIDUAL_COUNT 0x04 -#define SRB_DIR_IN 0x08 -#define SRB_DIR_OUT 0x10 -#define SRB_EVENT_NOTIFY 0x40 +#define SRB_DIR_IN 0x08 +#define SRB_DIR_OUT 0x10 +#define SRB_EVENT_NOTIFY 0x40 #define RESIDUAL_COUNT_SUPPORTED 0x02 -#define MAX_SRB_TIMEOUT 1080001u +#define MAX_SRB_TIMEOUT 1080001u #define DEFAULT_SRB_TIMEOUT 1080001u -#define SC_HA_INQUIRY 0x00 -#define SC_GET_DEV_TYPE 0x01 -#define SC_EXEC_SCSI_CMD 0x02 -#define SC_ABORT_SRB 0x03 -#define SC_RESET_DEV 0x04 -#define SC_SET_HA_PARMS 0x05 -#define SC_GET_DISK_INFO 0x06 -#define SC_RESCAN_SCSI_BUS 0x07 -#define SC_GETSET_TIMEOUTS 0x08 +#define SC_HA_INQUIRY 0x00 +#define SC_GET_DEV_TYPE 0x01 +#define SC_EXEC_SCSI_CMD 0x02 +#define SC_ABORT_SRB 0x03 +#define SC_RESET_DEV 0x04 +#define SC_SET_HA_PARMS 0x05 +#define SC_GET_DISK_INFO 0x06 +#define SC_RESCAN_SCSI_BUS 0x07 +#define SC_GETSET_TIMEOUTS 0x08 -#define SS_PENDING 0x00 -#define SS_COMP 0x01 -#define SS_ABORTED 0x02 -#define SS_ABORT_FAIL 0x03 -#define SS_ERR 0x04 -#define SS_INVALID_CMD 0x80 -#define SS_INVALID_HA 0x81 -#define SS_NO_DEVICE 0x82 -#define SS_INVALID_SRB 0xE0 -#define SS_OLD_MANAGER 0xE1 -#define SS_BUFFER_ALIGN 0xE1 -#define SS_ILLEGAL_MODE 0xE2 -#define SS_NO_ASPI 0xE3 -#define SS_FAILED_INIT 0xE4 -#define SS_ASPI_IS_BUSY 0xE5 -#define SS_BUFFER_TO_BIG 0xE6 -#define SS_BUFFER_TOO_BIG 0xE6 +#define SS_PENDING 0x00 +#define SS_COMP 0x01 +#define SS_ABORTED 0x02 +#define SS_ABORT_FAIL 0x03 +#define SS_ERR 0x04 +#define SS_INVALID_CMD 0x80 +#define SS_INVALID_HA 0x81 +#define SS_NO_DEVICE 0x82 +#define SS_INVALID_SRB 0xE0 +#define SS_OLD_MANAGER 0xE1 +#define SS_BUFFER_ALIGN 0xE1 +#define SS_ILLEGAL_MODE 0xE2 +#define SS_NO_ASPI 0xE3 +#define SS_FAILED_INIT 0xE4 +#define SS_ASPI_IS_BUSY 0xE5 +#define SS_BUFFER_TO_BIG 0xE6 +#define SS_BUFFER_TOO_BIG 0xE6 #define SS_MISMATCHED_COMPONENTS 0xE7 -#define SS_NO_ADAPTERS 0xE8 +#define SS_NO_ADAPTERS 0xE8 #define SS_INSUFFICIENT_RESOURCES 0xE9 -#define SS_ASPI_IS_SHUTDOWN 0xEA -#define SS_BAD_INSTALL 0xEB +#define SS_ASPI_IS_SHUTDOWN 0xEA +#define SS_BAD_INSTALL 0xEB -#define HASTAT_OK 0x00 -#define HASTAT_SEL_TO 0x11 -#define HASTAT_DO_DU 0x12 -#define HASTAT_BUS_FREE 0x13 -#define HASTAT_PHASE_ERR 0x14 -#define HASTAT_TIMEOUT 0x09 -#define HASTAT_COMMAND_TIMEOUT 0x0B -#define HASTAT_MESSAGE_REJECT 0x0D -#define HASTAT_BUS_RESET 0x0E -#define HASTAT_PARITY_ERROR 0x0F +#define HASTAT_OK 0x00 +#define HASTAT_SEL_TO 0x11 +#define HASTAT_DO_DU 0x12 +#define HASTAT_BUS_FREE 0x13 +#define HASTAT_PHASE_ERR 0x14 +#define HASTAT_TIMEOUT 0x09 +#define HASTAT_COMMAND_TIMEOUT 0x0B +#define HASTAT_MESSAGE_REJECT 0x0D +#define HASTAT_BUS_RESET 0x0E +#define HASTAT_PARITY_ERROR 0x0F #define HASTAT_REQUEST_SENSE_FAILED 0x10 #define PACKED @@ -242726,119 +220461,119 @@ typedef struct typedef struct { - BYTE SRB_Cmd; - BYTE SRB_Status; - BYTE SRB_HaID; - BYTE SRB_Flags; - DWORD SRB_Hdr_Rsvd; - BYTE HA_Count; - BYTE HA_SCSI_ID; - BYTE HA_ManagerId[16]; - BYTE HA_Identifier[16]; - BYTE HA_Unique[16]; - WORD HA_Rsvd1; - BYTE pad[20]; + BYTE SRB_Cmd; + BYTE SRB_Status; + BYTE SRB_HaID; + BYTE SRB_Flags; + DWORD SRB_Hdr_Rsvd; + BYTE HA_Count; + BYTE HA_SCSI_ID; + BYTE HA_ManagerId[16]; + BYTE HA_Identifier[16]; + BYTE HA_Unique[16]; + WORD HA_Rsvd1; + BYTE pad[20]; } PACKED SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry; typedef struct { - BYTE SRB_Cmd; - BYTE SRB_Status; - BYTE SRB_HaID; - BYTE SRB_Flags; - DWORD SRB_Hdr_Rsvd; - BYTE SRB_Target; - BYTE SRB_Lun; - BYTE SRB_DeviceType; - BYTE SRB_Rsvd1; - BYTE pad[68]; + BYTE SRB_Cmd; + BYTE SRB_Status; + BYTE SRB_HaID; + BYTE SRB_Flags; + DWORD SRB_Hdr_Rsvd; + BYTE SRB_Target; + BYTE SRB_Lun; + BYTE SRB_DeviceType; + BYTE SRB_Rsvd1; + BYTE pad[68]; } PACKED SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock; typedef struct { - BYTE SRB_Cmd; - BYTE SRB_Status; - BYTE SRB_HaID; - BYTE SRB_Flags; - DWORD SRB_Hdr_Rsvd; - BYTE SRB_Target; - BYTE SRB_Lun; - WORD SRB_Rsvd1; - DWORD SRB_BufLen; + BYTE SRB_Cmd; + BYTE SRB_Status; + BYTE SRB_HaID; + BYTE SRB_Flags; + DWORD SRB_Hdr_Rsvd; + BYTE SRB_Target; + BYTE SRB_Lun; + WORD SRB_Rsvd1; + DWORD SRB_BufLen; BYTE FAR *SRB_BufPointer; - BYTE SRB_SenseLen; - BYTE SRB_CDBLen; - BYTE SRB_HaStat; - BYTE SRB_TargStat; + BYTE SRB_SenseLen; + BYTE SRB_CDBLen; + BYTE SRB_HaStat; + BYTE SRB_TargStat; VOID FAR *SRB_PostProc; - BYTE SRB_Rsvd2[20]; - BYTE CDBByte[16]; + BYTE SRB_Rsvd2[20]; + BYTE CDBByte[16]; BYTE SenseArea[SENSE_LEN+2]; } PACKED SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd; typedef struct { - BYTE SRB_Cmd; - BYTE SRB_Status; - BYTE SRB_HaId; - BYTE SRB_Flags; - DWORD SRB_Hdr_Rsvd; + BYTE SRB_Cmd; + BYTE SRB_Status; + BYTE SRB_HaId; + BYTE SRB_Flags; + DWORD SRB_Hdr_Rsvd; } PACKED SRB, *PSRB, FAR *LPSRB; #pragma pack() struct CDDeviceInfo { - char vendor[9]; - char productId[17]; - char rev[5]; - char vendorSpec[21]; + char vendor[9]; + char productId[17]; + char rev[5]; + char vendorSpec[21]; - BYTE ha; - BYTE tgt; - BYTE lun; - char scsiDriveLetter; // will be 0 if not using scsi + BYTE ha; + BYTE tgt; + BYTE lun; + char scsiDriveLetter; // will be 0 if not using scsi }; class CDReadBuffer { public: - int startFrame; - int numFrames; - int dataStartOffset; - int dataLength; - BYTE* buffer; - int bufferSize; - int index; - bool wantsIndex; + int startFrame; + int numFrames; + int dataStartOffset; + int dataLength; + BYTE* buffer; + int bufferSize; + int index; + bool wantsIndex; - CDReadBuffer (const int numberOfFrames) - : startFrame (0), - numFrames (0), - dataStartOffset (0), - dataLength (0), - index (0), - wantsIndex (false) - { - bufferSize = 2352 * numberOfFrames; - buffer = (BYTE*) malloc (bufferSize); - } + CDReadBuffer (const int numberOfFrames) + : startFrame (0), + numFrames (0), + dataStartOffset (0), + dataLength (0), + index (0), + wantsIndex (false) + { + bufferSize = 2352 * numberOfFrames; + buffer = (BYTE*) malloc (bufferSize); + } - ~CDReadBuffer() - { - free (buffer); - } + ~CDReadBuffer() + { + free (buffer); + } - bool isZero() const - { - BYTE* p = buffer + dataStartOffset; + bool isZero() const + { + BYTE* p = buffer + dataStartOffset; - for (int i = dataLength; --i >= 0;) - if (*p++ != 0) - return false; + for (int i = dataLength; --i >= 0;) + if (*p++ != 0) + return false; - return true; - } + return true; + } }; class CDDeviceHandle; @@ -242846,97 +220581,97 @@ class CDDeviceHandle; class CDController { public: - CDController(); - virtual ~CDController(); + CDController(); + virtual ~CDController(); - virtual bool read (CDReadBuffer* t) = 0; - virtual void shutDown(); + virtual bool read (CDReadBuffer* t) = 0; + virtual void shutDown(); - bool readAudio (CDReadBuffer* t, CDReadBuffer* overlapBuffer = 0); - int getLastIndex(); + bool readAudio (CDReadBuffer* t, CDReadBuffer* overlapBuffer = 0); + int getLastIndex(); public: - bool initialised; + bool initialised; - CDDeviceHandle* deviceInfo; - int framesToCheck, framesOverlap; + CDDeviceHandle* deviceInfo; + int framesToCheck, framesOverlap; - void prepare (SRB_ExecSCSICmd& s); - void perform (SRB_ExecSCSICmd& s); - void setPaused (bool paused); + void prepare (SRB_ExecSCSICmd& s); + void perform (SRB_ExecSCSICmd& s); + void setPaused (bool paused); }; #pragma pack(1) struct TOCTRACK { - BYTE rsvd; - BYTE ADR; - BYTE trackNumber; - BYTE rsvd2; - BYTE addr[4]; + BYTE rsvd; + BYTE ADR; + BYTE trackNumber; + BYTE rsvd2; + BYTE addr[4]; }; struct TOC { - WORD tocLen; - BYTE firstTrack; - BYTE lastTrack; - TOCTRACK tracks[100]; + WORD tocLen; + BYTE firstTrack; + BYTE lastTrack; + TOCTRACK tracks[100]; }; #pragma pack() enum { - READTYPE_ANY = 0, - READTYPE_ATAPI1 = 1, - READTYPE_ATAPI2 = 2, - READTYPE_READ6 = 3, - READTYPE_READ10 = 4, - READTYPE_READ_D8 = 5, - READTYPE_READ_D4 = 6, - READTYPE_READ_D4_1 = 7, - READTYPE_READ10_2 = 8 + READTYPE_ANY = 0, + READTYPE_ATAPI1 = 1, + READTYPE_ATAPI2 = 2, + READTYPE_READ6 = 3, + READTYPE_READ10 = 4, + READTYPE_READ_D8 = 5, + READTYPE_READ_D4 = 6, + READTYPE_READ_D4_1 = 7, + READTYPE_READ10_2 = 8 }; class CDDeviceHandle { public: - CDDeviceHandle (const CDDeviceInfo* const device) - : scsiHandle (0), - readType (READTYPE_ANY), - controller (0) - { - memcpy (&info, device, sizeof (info)); - } + CDDeviceHandle (const CDDeviceInfo* const device) + : scsiHandle (0), + readType (READTYPE_ANY), + controller (0) + { + memcpy (&info, device, sizeof (info)); + } - ~CDDeviceHandle() - { - if (controller != 0) - { - controller->shutDown(); - delete controller; - } + ~CDDeviceHandle() + { + if (controller != 0) + { + controller->shutDown(); + delete controller; + } - if (scsiHandle != 0) - CloseHandle (scsiHandle); - } + if (scsiHandle != 0) + CloseHandle (scsiHandle); + } - bool readTOC (TOC* lpToc, bool useMSF); - bool readAudio (CDReadBuffer* buffer, CDReadBuffer* overlapBuffer = 0); - void openDrawer (bool shouldBeOpen); + bool readTOC (TOC* lpToc, bool useMSF); + bool readAudio (CDReadBuffer* buffer, CDReadBuffer* overlapBuffer = 0); + void openDrawer (bool shouldBeOpen); - CDDeviceInfo info; - HANDLE scsiHandle; - BYTE readType; + CDDeviceInfo info; + HANDLE scsiHandle; + BYTE readType; private: - CDController* controller; + CDController* controller; - bool testController (const int readType, - CDController* const newController, - CDReadBuffer* const bufferToUse); + bool testController (const int readType, + CDController* const newController, + CDReadBuffer* const bufferToUse); }; DWORD (*fGetASPI32SupportInfo)(void); @@ -242948,136 +220683,136 @@ static bool initialised = false; static bool InitialiseCDRipper() { - if (! initialised) - { - initialised = true; + if (! initialised) + { + initialised = true; - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof (info); - GetVersionEx (&info); + OSVERSIONINFO info; + info.dwOSVersionInfoSize = sizeof (info); + GetVersionEx (&info); - usingScsi = (info.dwPlatformId == VER_PLATFORM_WIN32_NT) && (info.dwMajorVersion > 4); + usingScsi = (info.dwPlatformId == VER_PLATFORM_WIN32_NT) && (info.dwMajorVersion > 4); - if (! usingScsi) - { - fGetASPI32SupportInfo = 0; - fSendASPI32Command = 0; - winAspiLib = LoadLibrary (_T("WNASPI32.DLL")); + if (! usingScsi) + { + fGetASPI32SupportInfo = 0; + fSendASPI32Command = 0; + winAspiLib = LoadLibrary (_T("WNASPI32.DLL")); - if (winAspiLib != 0) - { - fGetASPI32SupportInfo = (DWORD(*)(void)) GetProcAddress (winAspiLib, "GetASPI32SupportInfo"); - fSendASPI32Command = (DWORD(*)(LPSRB)) GetProcAddress (winAspiLib, "SendASPI32Command"); + if (winAspiLib != 0) + { + fGetASPI32SupportInfo = (DWORD(*)(void)) GetProcAddress (winAspiLib, "GetASPI32SupportInfo"); + fSendASPI32Command = (DWORD(*)(LPSRB)) GetProcAddress (winAspiLib, "SendASPI32Command"); - if (fGetASPI32SupportInfo == 0 || fSendASPI32Command == 0) - return false; - } - else - { - usingScsi = true; - } - } - } + if (fGetASPI32SupportInfo == 0 || fSendASPI32Command == 0) + return false; + } + else + { + usingScsi = true; + } + } + } - return true; + return true; } static void DeinitialiseCDRipper() { - if (winAspiLib != 0) - { - fGetASPI32SupportInfo = 0; - fSendASPI32Command = 0; - FreeLibrary (winAspiLib); - winAspiLib = 0; - } + if (winAspiLib != 0) + { + fGetASPI32SupportInfo = 0; + fSendASPI32Command = 0; + FreeLibrary (winAspiLib); + winAspiLib = 0; + } - initialised = false; + initialised = false; } static HANDLE CreateSCSIDeviceHandle (char driveLetter) { - TCHAR devicePath[8]; - devicePath[0] = '\\'; - devicePath[1] = '\\'; - devicePath[2] = '.'; - devicePath[3] = '\\'; - devicePath[4] = driveLetter; - devicePath[5] = ':'; - devicePath[6] = 0; + TCHAR devicePath[8]; + devicePath[0] = '\\'; + devicePath[1] = '\\'; + devicePath[2] = '.'; + devicePath[3] = '\\'; + devicePath[4] = driveLetter; + devicePath[5] = ':'; + devicePath[6] = 0; - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof (info); - GetVersionEx (&info); + OSVERSIONINFO info; + info.dwOSVersionInfoSize = sizeof (info); + GetVersionEx (&info); - DWORD flags = GENERIC_READ; + DWORD flags = GENERIC_READ; - if ((info.dwPlatformId == VER_PLATFORM_WIN32_NT) && (info.dwMajorVersion > 4)) - flags = GENERIC_READ | GENERIC_WRITE; + if ((info.dwPlatformId == VER_PLATFORM_WIN32_NT) && (info.dwMajorVersion > 4)) + flags = GENERIC_READ | GENERIC_WRITE; - HANDLE h = CreateFile (devicePath, flags, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + HANDLE h = CreateFile (devicePath, flags, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (h == INVALID_HANDLE_VALUE) - { - flags ^= GENERIC_WRITE; - h = CreateFile (devicePath, flags, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - } + if (h == INVALID_HANDLE_VALUE) + { + flags ^= GENERIC_WRITE; + h = CreateFile (devicePath, flags, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + } - return h; + return h; } static DWORD performScsiPassThroughCommand (const LPSRB_ExecSCSICmd srb, - const char driveLetter, - HANDLE& deviceHandle, - const bool retryOnFailure = true) + const char driveLetter, + HANDLE& deviceHandle, + const bool retryOnFailure = true) { - SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER s; - zerostruct (s); + SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER s; + zerostruct (s); - s.spt.Length = sizeof (SCSI_PASS_THROUGH); - s.spt.CdbLength = srb->SRB_CDBLen; + s.spt.Length = sizeof (SCSI_PASS_THROUGH); + s.spt.CdbLength = srb->SRB_CDBLen; - s.spt.DataIn = (BYTE) ((srb->SRB_Flags & SRB_DIR_IN) - ? SCSI_IOCTL_DATA_IN - : ((srb->SRB_Flags & SRB_DIR_OUT) - ? SCSI_IOCTL_DATA_OUT - : SCSI_IOCTL_DATA_UNSPECIFIED)); + s.spt.DataIn = (BYTE) ((srb->SRB_Flags & SRB_DIR_IN) + ? SCSI_IOCTL_DATA_IN + : ((srb->SRB_Flags & SRB_DIR_OUT) + ? SCSI_IOCTL_DATA_OUT + : SCSI_IOCTL_DATA_UNSPECIFIED)); - s.spt.DataTransferLength = srb->SRB_BufLen; - s.spt.TimeOutValue = 5; - s.spt.DataBuffer = srb->SRB_BufPointer; - s.spt.SenseInfoOffset = offsetof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); + s.spt.DataTransferLength = srb->SRB_BufLen; + s.spt.TimeOutValue = 5; + s.spt.DataBuffer = srb->SRB_BufPointer; + s.spt.SenseInfoOffset = offsetof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); - memcpy (s.spt.Cdb, srb->CDBByte, srb->SRB_CDBLen); + memcpy (s.spt.Cdb, srb->CDBByte, srb->SRB_CDBLen); - srb->SRB_Status = SS_ERR; - srb->SRB_TargStat = 0x0004; + srb->SRB_Status = SS_ERR; + srb->SRB_TargStat = 0x0004; - DWORD bytesReturned = 0; + DWORD bytesReturned = 0; - if (DeviceIoControl (deviceHandle, IOCTL_SCSI_PASS_THROUGH_DIRECT, - &s, sizeof (s), - &s, sizeof (s), - &bytesReturned, 0) != 0) - { - srb->SRB_Status = SS_COMP; - } - else if (retryOnFailure) - { - const DWORD error = GetLastError(); + if (DeviceIoControl (deviceHandle, IOCTL_SCSI_PASS_THROUGH_DIRECT, + &s, sizeof (s), + &s, sizeof (s), + &bytesReturned, 0) != 0) + { + srb->SRB_Status = SS_COMP; + } + else if (retryOnFailure) + { + const DWORD error = GetLastError(); - if ((error == ERROR_MEDIA_CHANGED) || (error == ERROR_INVALID_HANDLE)) - { - if (error != ERROR_INVALID_HANDLE) - CloseHandle (deviceHandle); + if ((error == ERROR_MEDIA_CHANGED) || (error == ERROR_INVALID_HANDLE)) + { + if (error != ERROR_INVALID_HANDLE) + CloseHandle (deviceHandle); - deviceHandle = CreateSCSIDeviceHandle (driveLetter); + deviceHandle = CreateSCSIDeviceHandle (driveLetter); - return performScsiPassThroughCommand (srb, driveLetter, deviceHandle, false); - } - } + return performScsiPassThroughCommand (srb, driveLetter, deviceHandle, false); + } + } - return srb->SRB_Status; + return srb->SRB_Status; } // Controller types.. @@ -243085,241 +220820,241 @@ static DWORD performScsiPassThroughCommand (const LPSRB_ExecSCSICmd srb, class ControllerType1 : public CDController { public: - ControllerType1() {} - ~ControllerType1() {} + ControllerType1() {} + ~ControllerType1() {} - bool read (CDReadBuffer* rb) - { - if (rb->numFrames * 2352 > rb->bufferSize) - return false; + bool read (CDReadBuffer* rb) + { + if (rb->numFrames * 2352 > rb->bufferSize) + return false; - SRB_ExecSCSICmd s; - prepare (s); - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = rb->bufferSize; - s.SRB_BufPointer = rb->buffer; - s.SRB_CDBLen = 12; - s.CDBByte[0] = 0xBE; - s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); - s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); - s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); - s.CDBByte[8] = (BYTE)(rb->numFrames & 0xFF); - s.CDBByte[9] = (BYTE)((deviceInfo->readType == READTYPE_ATAPI1) ? 0x10 : 0xF0); - perform (s); + SRB_ExecSCSICmd s; + prepare (s); + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = rb->bufferSize; + s.SRB_BufPointer = rb->buffer; + s.SRB_CDBLen = 12; + s.CDBByte[0] = 0xBE; + s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); + s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); + s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); + s.CDBByte[8] = (BYTE)(rb->numFrames & 0xFF); + s.CDBByte[9] = (BYTE)((deviceInfo->readType == READTYPE_ATAPI1) ? 0x10 : 0xF0); + perform (s); - if (s.SRB_Status != SS_COMP) - return false; + if (s.SRB_Status != SS_COMP) + return false; - rb->dataLength = rb->numFrames * 2352; - rb->dataStartOffset = 0; - return true; - } + rb->dataLength = rb->numFrames * 2352; + rb->dataStartOffset = 0; + return true; + } }; class ControllerType2 : public CDController { public: - ControllerType2() {} - ~ControllerType2() {} + ControllerType2() {} + ~ControllerType2() {} - void shutDown() - { - if (initialised) - { - BYTE bufPointer[] = { 0, 0, 0, 8, 83, 0, 0, 0, 0, 0, 8, 0 }; + void shutDown() + { + if (initialised) + { + BYTE bufPointer[] = { 0, 0, 0, 8, 83, 0, 0, 0, 0, 0, 8, 0 }; - SRB_ExecSCSICmd s; - prepare (s); - s.SRB_Flags = SRB_EVENT_NOTIFY | SRB_ENABLE_RESIDUAL_COUNT; - s.SRB_BufLen = 0x0C; - s.SRB_BufPointer = bufPointer; - s.SRB_CDBLen = 6; - s.CDBByte[0] = 0x15; - s.CDBByte[4] = 0x0C; - perform (s); - } - } + SRB_ExecSCSICmd s; + prepare (s); + s.SRB_Flags = SRB_EVENT_NOTIFY | SRB_ENABLE_RESIDUAL_COUNT; + s.SRB_BufLen = 0x0C; + s.SRB_BufPointer = bufPointer; + s.SRB_CDBLen = 6; + s.CDBByte[0] = 0x15; + s.CDBByte[4] = 0x0C; + perform (s); + } + } - bool init() - { - SRB_ExecSCSICmd s; - s.SRB_Status = SS_ERR; + bool init() + { + SRB_ExecSCSICmd s; + s.SRB_Status = SS_ERR; - if (deviceInfo->readType == READTYPE_READ10_2) - { - BYTE bufPointer1[] = { 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 9, 48, 35, 6, 0, 0, 0, 0, 0, 128 }; - BYTE bufPointer2[] = { 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 9, 48, 1, 6, 32, 7, 0, 0, 0, 0 }; + if (deviceInfo->readType == READTYPE_READ10_2) + { + BYTE bufPointer1[] = { 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 9, 48, 35, 6, 0, 0, 0, 0, 0, 128 }; + BYTE bufPointer2[] = { 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 9, 48, 1, 6, 32, 7, 0, 0, 0, 0 }; - for (int i = 0; i < 2; ++i) - { - prepare (s); - s.SRB_Flags = SRB_EVENT_NOTIFY; - s.SRB_BufLen = 0x14; - s.SRB_BufPointer = (i == 0) ? bufPointer1 : bufPointer2; - s.SRB_CDBLen = 6; - s.CDBByte[0] = 0x15; - s.CDBByte[1] = 0x10; - s.CDBByte[4] = 0x14; - perform (s); + for (int i = 0; i < 2; ++i) + { + prepare (s); + s.SRB_Flags = SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0x14; + s.SRB_BufPointer = (i == 0) ? bufPointer1 : bufPointer2; + s.SRB_CDBLen = 6; + s.CDBByte[0] = 0x15; + s.CDBByte[1] = 0x10; + s.CDBByte[4] = 0x14; + perform (s); - if (s.SRB_Status != SS_COMP) - return false; - } - } - else - { - BYTE bufPointer[] = { 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 9, 48 }; + if (s.SRB_Status != SS_COMP) + return false; + } + } + else + { + BYTE bufPointer[] = { 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 9, 48 }; - prepare (s); - s.SRB_Flags = SRB_EVENT_NOTIFY; - s.SRB_BufLen = 0x0C; - s.SRB_BufPointer = bufPointer; - s.SRB_CDBLen = 6; - s.CDBByte[0] = 0x15; - s.CDBByte[4] = 0x0C; - perform (s); - } + prepare (s); + s.SRB_Flags = SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0x0C; + s.SRB_BufPointer = bufPointer; + s.SRB_CDBLen = 6; + s.CDBByte[0] = 0x15; + s.CDBByte[4] = 0x0C; + perform (s); + } - return s.SRB_Status == SS_COMP; - } + return s.SRB_Status == SS_COMP; + } - bool read (CDReadBuffer* rb) - { - if (rb->numFrames * 2352 > rb->bufferSize) - return false; + bool read (CDReadBuffer* rb) + { + if (rb->numFrames * 2352 > rb->bufferSize) + return false; - if (!initialised) - { - initialised = init(); + if (!initialised) + { + initialised = init(); - if (!initialised) - return false; - } + if (!initialised) + return false; + } - SRB_ExecSCSICmd s; - prepare (s); - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = rb->bufferSize; - s.SRB_BufPointer = rb->buffer; - s.SRB_CDBLen = 10; - s.CDBByte[0] = 0x28; - s.CDBByte[1] = (BYTE)(deviceInfo->info.lun << 5); - s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); - s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); - s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); - s.CDBByte[8] = (BYTE)(rb->numFrames & 0xFF); - perform (s); + SRB_ExecSCSICmd s; + prepare (s); + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = rb->bufferSize; + s.SRB_BufPointer = rb->buffer; + s.SRB_CDBLen = 10; + s.CDBByte[0] = 0x28; + s.CDBByte[1] = (BYTE)(deviceInfo->info.lun << 5); + s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); + s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); + s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); + s.CDBByte[8] = (BYTE)(rb->numFrames & 0xFF); + perform (s); - if (s.SRB_Status != SS_COMP) - return false; + if (s.SRB_Status != SS_COMP) + return false; - rb->dataLength = rb->numFrames * 2352; - rb->dataStartOffset = 0; + rb->dataLength = rb->numFrames * 2352; + rb->dataStartOffset = 0; - return true; - } + return true; + } }; class ControllerType3 : public CDController { public: - ControllerType3() {} - ~ControllerType3() {} + ControllerType3() {} + ~ControllerType3() {} - bool read (CDReadBuffer* rb) - { - if (rb->numFrames * 2352 > rb->bufferSize) - return false; + bool read (CDReadBuffer* rb) + { + if (rb->numFrames * 2352 > rb->bufferSize) + return false; - if (!initialised) - { - setPaused (false); - initialised = true; - } + if (!initialised) + { + setPaused (false); + initialised = true; + } - SRB_ExecSCSICmd s; - prepare (s); - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = rb->numFrames * 2352; - s.SRB_BufPointer = rb->buffer; - s.SRB_CDBLen = 12; - s.CDBByte[0] = 0xD8; - s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); - s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); - s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); - s.CDBByte[9] = (BYTE)(rb->numFrames & 0xFF); - perform (s); + SRB_ExecSCSICmd s; + prepare (s); + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = rb->numFrames * 2352; + s.SRB_BufPointer = rb->buffer; + s.SRB_CDBLen = 12; + s.CDBByte[0] = 0xD8; + s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); + s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); + s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); + s.CDBByte[9] = (BYTE)(rb->numFrames & 0xFF); + perform (s); - if (s.SRB_Status != SS_COMP) - return false; + if (s.SRB_Status != SS_COMP) + return false; - rb->dataLength = rb->numFrames * 2352; - rb->dataStartOffset = 0; + rb->dataLength = rb->numFrames * 2352; + rb->dataStartOffset = 0; - return true; - } + return true; + } }; class ControllerType4 : public CDController { public: - ControllerType4() {} - ~ControllerType4() {} + ControllerType4() {} + ~ControllerType4() {} - bool selectD4Mode() - { - BYTE bufPointer[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 48 }; + bool selectD4Mode() + { + BYTE bufPointer[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 48 }; - SRB_ExecSCSICmd s; - prepare (s); - s.SRB_Flags = SRB_EVENT_NOTIFY; - s.SRB_CDBLen = 6; - s.SRB_BufLen = 12; - s.SRB_BufPointer = bufPointer; - s.CDBByte[0] = 0x15; - s.CDBByte[1] = 0x10; - s.CDBByte[4] = 0x08; - perform (s); + SRB_ExecSCSICmd s; + prepare (s); + s.SRB_Flags = SRB_EVENT_NOTIFY; + s.SRB_CDBLen = 6; + s.SRB_BufLen = 12; + s.SRB_BufPointer = bufPointer; + s.CDBByte[0] = 0x15; + s.CDBByte[1] = 0x10; + s.CDBByte[4] = 0x08; + perform (s); - return s.SRB_Status == SS_COMP; - } + return s.SRB_Status == SS_COMP; + } - bool read (CDReadBuffer* rb) - { - if (rb->numFrames * 2352 > rb->bufferSize) - return false; + bool read (CDReadBuffer* rb) + { + if (rb->numFrames * 2352 > rb->bufferSize) + return false; - if (!initialised) - { - setPaused (true); + if (!initialised) + { + setPaused (true); - if (deviceInfo->readType == READTYPE_READ_D4_1) - selectD4Mode(); + if (deviceInfo->readType == READTYPE_READ_D4_1) + selectD4Mode(); - initialised = true; - } + initialised = true; + } - SRB_ExecSCSICmd s; - prepare (s); - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = rb->bufferSize; - s.SRB_BufPointer = rb->buffer; - s.SRB_CDBLen = 10; - s.CDBByte[0] = 0xD4; - s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); - s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); - s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); - s.CDBByte[8] = (BYTE)(rb->numFrames & 0xFF); - perform (s); + SRB_ExecSCSICmd s; + prepare (s); + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = rb->bufferSize; + s.SRB_BufPointer = rb->buffer; + s.SRB_CDBLen = 10; + s.CDBByte[0] = 0xD4; + s.CDBByte[3] = (BYTE)((rb->startFrame >> 16) & 0xFF); + s.CDBByte[4] = (BYTE)((rb->startFrame >> 8) & 0xFF); + s.CDBByte[5] = (BYTE)(rb->startFrame & 0xFF); + s.CDBByte[8] = (BYTE)(rb->numFrames & 0xFF); + perform (s); - if (s.SRB_Status != SS_COMP) - return false; + if (s.SRB_Status != SS_COMP) + return false; - rb->dataLength = rb->numFrames * 2352; - rb->dataStartOffset = 0; + rb->dataLength = rb->numFrames * 2352; + rb->dataStartOffset = 0; - return true; - } + return true; + } }; CDController::CDController() : initialised (false) @@ -243332,42 +221067,42 @@ CDController::~CDController() void CDController::prepare (SRB_ExecSCSICmd& s) { - zerostruct (s); + zerostruct (s); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaID = deviceInfo->info.ha; - s.SRB_Target = deviceInfo->info.tgt; - s.SRB_Lun = deviceInfo->info.lun; - s.SRB_SenseLen = SENSE_LEN; + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaID = deviceInfo->info.ha; + s.SRB_Target = deviceInfo->info.tgt; + s.SRB_Lun = deviceInfo->info.lun; + s.SRB_SenseLen = SENSE_LEN; } void CDController::perform (SRB_ExecSCSICmd& s) { - HANDLE event = CreateEvent (0, TRUE, FALSE, 0); - s.SRB_PostProc = (void*)event; + HANDLE event = CreateEvent (0, TRUE, FALSE, 0); + s.SRB_PostProc = (void*)event; - ResetEvent (event); + ResetEvent (event); - DWORD status = (usingScsi) ? performScsiPassThroughCommand ((LPSRB_ExecSCSICmd)&s, - deviceInfo->info.scsiDriveLetter, - deviceInfo->scsiHandle) - : fSendASPI32Command ((LPSRB)&s); + DWORD status = (usingScsi) ? performScsiPassThroughCommand ((LPSRB_ExecSCSICmd)&s, + deviceInfo->info.scsiDriveLetter, + deviceInfo->scsiHandle) + : fSendASPI32Command ((LPSRB)&s); - if (status == SS_PENDING) - WaitForSingleObject (event, 4000); + if (status == SS_PENDING) + WaitForSingleObject (event, 4000); - CloseHandle (event); + CloseHandle (event); } void CDController::setPaused (bool paused) { - SRB_ExecSCSICmd s; - prepare (s); - s.SRB_Flags = SRB_EVENT_NOTIFY; - s.SRB_CDBLen = 10; - s.CDBByte[0] = 0x4B; - s.CDBByte[8] = (BYTE) (paused ? 0 : 1); - perform (s); + SRB_ExecSCSICmd s; + prepare (s); + s.SRB_Flags = SRB_EVENT_NOTIFY; + s.SRB_CDBLen = 10; + s.CDBByte[0] = 0x4B; + s.CDBByte[8] = (BYTE) (paused ? 0 : 1); + perform (s); } void CDController::shutDown() @@ -243376,507 +221111,507 @@ void CDController::shutDown() bool CDController::readAudio (CDReadBuffer* rb, CDReadBuffer* overlapBuffer) { - if (overlapBuffer != 0) - { - const bool canDoJitter = (overlapBuffer->bufferSize >= 2352 * framesToCheck); - const bool doJitter = canDoJitter && ! overlapBuffer->isZero(); + if (overlapBuffer != 0) + { + const bool canDoJitter = (overlapBuffer->bufferSize >= 2352 * framesToCheck); + const bool doJitter = canDoJitter && ! overlapBuffer->isZero(); - if (doJitter - && overlapBuffer->startFrame > 0 - && overlapBuffer->numFrames > 0 - && overlapBuffer->dataLength > 0) - { - const int numFrames = rb->numFrames; + if (doJitter + && overlapBuffer->startFrame > 0 + && overlapBuffer->numFrames > 0 + && overlapBuffer->dataLength > 0) + { + const int numFrames = rb->numFrames; - if (overlapBuffer->startFrame == (rb->startFrame - framesToCheck)) - { - rb->startFrame -= framesOverlap; + if (overlapBuffer->startFrame == (rb->startFrame - framesToCheck)) + { + rb->startFrame -= framesOverlap; - if (framesToCheck < framesOverlap - && numFrames + framesOverlap <= rb->bufferSize / 2352) - rb->numFrames += framesOverlap; - } - else - { - overlapBuffer->dataLength = 0; - overlapBuffer->startFrame = 0; - overlapBuffer->numFrames = 0; - } - } + if (framesToCheck < framesOverlap + && numFrames + framesOverlap <= rb->bufferSize / 2352) + rb->numFrames += framesOverlap; + } + else + { + overlapBuffer->dataLength = 0; + overlapBuffer->startFrame = 0; + overlapBuffer->numFrames = 0; + } + } - if (! read (rb)) - return false; + if (! read (rb)) + return false; - if (doJitter) - { - const int checkLen = framesToCheck * 2352; - const int maxToCheck = rb->dataLength - checkLen; + if (doJitter) + { + const int checkLen = framesToCheck * 2352; + const int maxToCheck = rb->dataLength - checkLen; - if (overlapBuffer->dataLength == 0 || overlapBuffer->isZero()) - return true; + if (overlapBuffer->dataLength == 0 || overlapBuffer->isZero()) + return true; - BYTE* const p = overlapBuffer->buffer + overlapBuffer->dataStartOffset; - bool found = false; + BYTE* const p = overlapBuffer->buffer + overlapBuffer->dataStartOffset; + bool found = false; - for (int i = 0; i < maxToCheck; ++i) - { - if (!memcmp (p, rb->buffer + i, checkLen)) - { - i += checkLen; - rb->dataStartOffset = i; - rb->dataLength -= i; - rb->startFrame = overlapBuffer->startFrame + framesToCheck; - found = true; - break; - } - } + for (int i = 0; i < maxToCheck; ++i) + { + if (!memcmp (p, rb->buffer + i, checkLen)) + { + i += checkLen; + rb->dataStartOffset = i; + rb->dataLength -= i; + rb->startFrame = overlapBuffer->startFrame + framesToCheck; + found = true; + break; + } + } - rb->numFrames = rb->dataLength / 2352; - rb->dataLength = 2352 * rb->numFrames; + rb->numFrames = rb->dataLength / 2352; + rb->dataLength = 2352 * rb->numFrames; - if (!found) - return false; - } + if (!found) + return false; + } - if (canDoJitter) - { - memcpy (overlapBuffer->buffer, - rb->buffer + rb->dataStartOffset + 2352 * (rb->numFrames - framesToCheck), - 2352 * framesToCheck); + if (canDoJitter) + { + memcpy (overlapBuffer->buffer, + rb->buffer + rb->dataStartOffset + 2352 * (rb->numFrames - framesToCheck), + 2352 * framesToCheck); - overlapBuffer->startFrame = rb->startFrame + rb->numFrames - framesToCheck; - overlapBuffer->numFrames = framesToCheck; - overlapBuffer->dataLength = 2352 * framesToCheck; - overlapBuffer->dataStartOffset = 0; - } - else - { - overlapBuffer->startFrame = 0; - overlapBuffer->numFrames = 0; - overlapBuffer->dataLength = 0; - } + overlapBuffer->startFrame = rb->startFrame + rb->numFrames - framesToCheck; + overlapBuffer->numFrames = framesToCheck; + overlapBuffer->dataLength = 2352 * framesToCheck; + overlapBuffer->dataStartOffset = 0; + } + else + { + overlapBuffer->startFrame = 0; + overlapBuffer->numFrames = 0; + overlapBuffer->dataLength = 0; + } - return true; - } - else - { - return read (rb); - } + return true; + } + else + { + return read (rb); + } } int CDController::getLastIndex() { - char qdata[100]; + char qdata[100]; - SRB_ExecSCSICmd s; - prepare (s); - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = sizeof (qdata); - s.SRB_BufPointer = (BYTE*)qdata; - s.SRB_CDBLen = 12; - s.CDBByte[0] = 0x42; - s.CDBByte[1] = (BYTE)(deviceInfo->info.lun << 5); - s.CDBByte[2] = 64; - s.CDBByte[3] = 1; // get current position - s.CDBByte[7] = 0; - s.CDBByte[8] = (BYTE)sizeof (qdata); - perform (s); + SRB_ExecSCSICmd s; + prepare (s); + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = sizeof (qdata); + s.SRB_BufPointer = (BYTE*)qdata; + s.SRB_CDBLen = 12; + s.CDBByte[0] = 0x42; + s.CDBByte[1] = (BYTE)(deviceInfo->info.lun << 5); + s.CDBByte[2] = 64; + s.CDBByte[3] = 1; // get current position + s.CDBByte[7] = 0; + s.CDBByte[8] = (BYTE)sizeof (qdata); + perform (s); - if (s.SRB_Status == SS_COMP) - return qdata[7]; + if (s.SRB_Status == SS_COMP) + return qdata[7]; - return 0; + return 0; } bool CDDeviceHandle::readTOC (TOC* lpToc, bool useMSF) { - HANDLE event = CreateEvent (0, TRUE, FALSE, 0); + HANDLE event = CreateEvent (0, TRUE, FALSE, 0); - SRB_ExecSCSICmd s; - zerostruct (s); + SRB_ExecSCSICmd s; + zerostruct (s); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaID = info.ha; - s.SRB_Target = info.tgt; - s.SRB_Lun = info.lun; - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = 0x324; - s.SRB_BufPointer = (BYTE*)lpToc; - s.SRB_SenseLen = 0x0E; - s.SRB_CDBLen = 0x0A; - s.SRB_PostProc = (void*)event; - s.CDBByte[0] = 0x43; - s.CDBByte[1] = (BYTE)(useMSF ? 0x02 : 0x00); - s.CDBByte[7] = 0x03; - s.CDBByte[8] = 0x24; + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaID = info.ha; + s.SRB_Target = info.tgt; + s.SRB_Lun = info.lun; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0x324; + s.SRB_BufPointer = (BYTE*)lpToc; + s.SRB_SenseLen = 0x0E; + s.SRB_CDBLen = 0x0A; + s.SRB_PostProc = (void*)event; + s.CDBByte[0] = 0x43; + s.CDBByte[1] = (BYTE)(useMSF ? 0x02 : 0x00); + s.CDBByte[7] = 0x03; + s.CDBByte[8] = 0x24; - ResetEvent (event); - DWORD status = (usingScsi) ? performScsiPassThroughCommand ((LPSRB_ExecSCSICmd)&s, info.scsiDriveLetter, scsiHandle) - : fSendASPI32Command ((LPSRB)&s); + ResetEvent (event); + DWORD status = (usingScsi) ? performScsiPassThroughCommand ((LPSRB_ExecSCSICmd)&s, info.scsiDriveLetter, scsiHandle) + : fSendASPI32Command ((LPSRB)&s); - if (status == SS_PENDING) - WaitForSingleObject (event, 4000); + if (status == SS_PENDING) + WaitForSingleObject (event, 4000); - CloseHandle (event); - return (s.SRB_Status == SS_COMP); + CloseHandle (event); + return (s.SRB_Status == SS_COMP); } bool CDDeviceHandle::readAudio (CDReadBuffer* const buffer, - CDReadBuffer* const overlapBuffer) + CDReadBuffer* const overlapBuffer) { - if (controller == 0) - { - testController (READTYPE_ATAPI2, new ControllerType1(), buffer) - || testController (READTYPE_ATAPI1, new ControllerType1(), buffer) - || testController (READTYPE_READ10_2, new ControllerType2(), buffer) - || testController (READTYPE_READ10, new ControllerType2(), buffer) - || testController (READTYPE_READ_D8, new ControllerType3(), buffer) - || testController (READTYPE_READ_D4, new ControllerType4(), buffer) - || testController (READTYPE_READ_D4_1, new ControllerType4(), buffer); - } + if (controller == 0) + { + testController (READTYPE_ATAPI2, new ControllerType1(), buffer) + || testController (READTYPE_ATAPI1, new ControllerType1(), buffer) + || testController (READTYPE_READ10_2, new ControllerType2(), buffer) + || testController (READTYPE_READ10, new ControllerType2(), buffer) + || testController (READTYPE_READ_D8, new ControllerType3(), buffer) + || testController (READTYPE_READ_D4, new ControllerType4(), buffer) + || testController (READTYPE_READ_D4_1, new ControllerType4(), buffer); + } - buffer->index = 0; + buffer->index = 0; - if ((controller != 0) - && controller->readAudio (buffer, overlapBuffer)) - { - if (buffer->wantsIndex) - buffer->index = controller->getLastIndex(); + if ((controller != 0) + && controller->readAudio (buffer, overlapBuffer)) + { + if (buffer->wantsIndex) + buffer->index = controller->getLastIndex(); - return true; - } + return true; + } - return false; + return false; } void CDDeviceHandle::openDrawer (bool shouldBeOpen) { - if (shouldBeOpen) - { - if (controller != 0) - { - controller->shutDown(); - delete controller; - controller = 0; - } + if (shouldBeOpen) + { + if (controller != 0) + { + controller->shutDown(); + delete controller; + controller = 0; + } - if (scsiHandle != 0) - { - CloseHandle (scsiHandle); - scsiHandle = 0; - } - } + if (scsiHandle != 0) + { + CloseHandle (scsiHandle); + scsiHandle = 0; + } + } - SRB_ExecSCSICmd s; - zerostruct (s); + SRB_ExecSCSICmd s; + zerostruct (s); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaID = info.ha; - s.SRB_Target = info.tgt; - s.SRB_Lun = info.lun; - s.SRB_SenseLen = SENSE_LEN; - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = 0; - s.SRB_BufPointer = 0; - s.SRB_CDBLen = 12; - s.CDBByte[0] = 0x1b; - s.CDBByte[1] = (BYTE)(info.lun << 5); - s.CDBByte[4] = (BYTE)((shouldBeOpen) ? 2 : 3); + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaID = info.ha; + s.SRB_Target = info.tgt; + s.SRB_Lun = info.lun; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0; + s.SRB_BufPointer = 0; + s.SRB_CDBLen = 12; + s.CDBByte[0] = 0x1b; + s.CDBByte[1] = (BYTE)(info.lun << 5); + s.CDBByte[4] = (BYTE)((shouldBeOpen) ? 2 : 3); - HANDLE event = CreateEvent (0, TRUE, FALSE, 0); - s.SRB_PostProc = (void*)event; + HANDLE event = CreateEvent (0, TRUE, FALSE, 0); + s.SRB_PostProc = (void*)event; - ResetEvent (event); + ResetEvent (event); - DWORD status = (usingScsi) ? performScsiPassThroughCommand ((LPSRB_ExecSCSICmd)&s, info.scsiDriveLetter, scsiHandle) - : fSendASPI32Command ((LPSRB)&s); + DWORD status = (usingScsi) ? performScsiPassThroughCommand ((LPSRB_ExecSCSICmd)&s, info.scsiDriveLetter, scsiHandle) + : fSendASPI32Command ((LPSRB)&s); - if (status == SS_PENDING) - WaitForSingleObject (event, 4000); + if (status == SS_PENDING) + WaitForSingleObject (event, 4000); - CloseHandle (event); + CloseHandle (event); } bool CDDeviceHandle::testController (const int type, - CDController* const newController, - CDReadBuffer* const rb) + CDController* const newController, + CDReadBuffer* const rb) { - controller = newController; - readType = (BYTE)type; + controller = newController; + readType = (BYTE)type; - controller->deviceInfo = this; - controller->framesToCheck = 1; - controller->framesOverlap = 3; + controller->deviceInfo = this; + controller->framesToCheck = 1; + controller->framesOverlap = 3; - bool passed = false; + bool passed = false; - memset (rb->buffer, 0xcd, rb->bufferSize); + memset (rb->buffer, 0xcd, rb->bufferSize); - if (controller->read (rb)) - { - passed = true; - int* p = (int*) (rb->buffer + rb->dataStartOffset); - int wrong = 0; + if (controller->read (rb)) + { + passed = true; + int* p = (int*) (rb->buffer + rb->dataStartOffset); + int wrong = 0; - for (int i = rb->dataLength / 4; --i >= 0;) - { - if (*p++ == (int) 0xcdcdcdcd) - { - if (++wrong == 4) - { - passed = false; - break; - } - } - else - { - wrong = 0; - } - } - } + for (int i = rb->dataLength / 4; --i >= 0;) + { + if (*p++ == (int) 0xcdcdcdcd) + { + if (++wrong == 4) + { + passed = false; + break; + } + } + else + { + wrong = 0; + } + } + } - if (! passed) - { - controller->shutDown(); - delete controller; - controller = 0; - } + if (! passed) + { + controller->shutDown(); + delete controller; + controller = 0; + } - return passed; + return passed; } static void GetAspiDeviceInfo (CDDeviceInfo* dev, BYTE ha, BYTE tgt, BYTE lun) { - HANDLE event = CreateEvent (0, TRUE, FALSE, 0); + HANDLE event = CreateEvent (0, TRUE, FALSE, 0); - const int bufSize = 128; - BYTE buffer[bufSize]; - zeromem (buffer, bufSize); + const int bufSize = 128; + BYTE buffer[bufSize]; + zeromem (buffer, bufSize); - SRB_ExecSCSICmd s; - zerostruct (s); + SRB_ExecSCSICmd s; + zerostruct (s); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaID = ha; - s.SRB_Target = tgt; - s.SRB_Lun = lun; - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = bufSize; - s.SRB_BufPointer = buffer; - s.SRB_SenseLen = SENSE_LEN; - s.SRB_CDBLen = 6; - s.SRB_PostProc = (void*)event; - s.CDBByte[0] = SCSI_INQUIRY; - s.CDBByte[4] = 100; + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaID = ha; + s.SRB_Target = tgt; + s.SRB_Lun = lun; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = bufSize; + s.SRB_BufPointer = buffer; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_CDBLen = 6; + s.SRB_PostProc = (void*)event; + s.CDBByte[0] = SCSI_INQUIRY; + s.CDBByte[4] = 100; - ResetEvent (event); + ResetEvent (event); - if (fSendASPI32Command ((LPSRB)&s) == SS_PENDING) - WaitForSingleObject (event, 4000); + if (fSendASPI32Command ((LPSRB)&s) == SS_PENDING) + WaitForSingleObject (event, 4000); - CloseHandle (event); + CloseHandle (event); - if (s.SRB_Status == SS_COMP) - { - memcpy (dev->vendor, &buffer[8], 8); - memcpy (dev->productId, &buffer[16], 16); - memcpy (dev->rev, &buffer[32], 4); - memcpy (dev->vendorSpec, &buffer[36], 20); - } + if (s.SRB_Status == SS_COMP) + { + memcpy (dev->vendor, &buffer[8], 8); + memcpy (dev->productId, &buffer[16], 16); + memcpy (dev->rev, &buffer[32], 4); + memcpy (dev->vendorSpec, &buffer[36], 20); + } } static int FindCDDevices (CDDeviceInfo* const list, - int maxItems) + int maxItems) { - int count = 0; + int count = 0; - if (usingScsi) - { - for (char driveLetter = 'b'; driveLetter <= 'z'; ++driveLetter) - { - TCHAR drivePath[8]; - drivePath[0] = driveLetter; - drivePath[1] = ':'; - drivePath[2] = '\\'; - drivePath[3] = 0; + if (usingScsi) + { + for (char driveLetter = 'b'; driveLetter <= 'z'; ++driveLetter) + { + TCHAR drivePath[8]; + drivePath[0] = driveLetter; + drivePath[1] = ':'; + drivePath[2] = '\\'; + drivePath[3] = 0; - if (GetDriveType (drivePath) == DRIVE_CDROM) - { - HANDLE h = CreateSCSIDeviceHandle (driveLetter); + if (GetDriveType (drivePath) == DRIVE_CDROM) + { + HANDLE h = CreateSCSIDeviceHandle (driveLetter); - if (h != INVALID_HANDLE_VALUE) - { - BYTE buffer[100], passThroughStruct[1024]; - zeromem (buffer, sizeof (buffer)); - zeromem (passThroughStruct, sizeof (passThroughStruct)); + if (h != INVALID_HANDLE_VALUE) + { + BYTE buffer[100], passThroughStruct[1024]; + zeromem (buffer, sizeof (buffer)); + zeromem (passThroughStruct, sizeof (passThroughStruct)); - PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER p = (PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)passThroughStruct; + PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER p = (PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)passThroughStruct; - p->spt.Length = sizeof (SCSI_PASS_THROUGH); - p->spt.CdbLength = 6; - p->spt.SenseInfoLength = 24; - p->spt.DataIn = SCSI_IOCTL_DATA_IN; - p->spt.DataTransferLength = 100; - p->spt.TimeOutValue = 2; - p->spt.DataBuffer = buffer; - p->spt.SenseInfoOffset = offsetof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); - p->spt.Cdb[0] = 0x12; - p->spt.Cdb[4] = 100; + p->spt.Length = sizeof (SCSI_PASS_THROUGH); + p->spt.CdbLength = 6; + p->spt.SenseInfoLength = 24; + p->spt.DataIn = SCSI_IOCTL_DATA_IN; + p->spt.DataTransferLength = 100; + p->spt.TimeOutValue = 2; + p->spt.DataBuffer = buffer; + p->spt.SenseInfoOffset = offsetof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); + p->spt.Cdb[0] = 0x12; + p->spt.Cdb[4] = 100; - DWORD bytesReturned = 0; + DWORD bytesReturned = 0; - if (DeviceIoControl (h, IOCTL_SCSI_PASS_THROUGH_DIRECT, - p, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), - p, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), - &bytesReturned, 0) != 0) - { - zeromem (&list[count], sizeof (CDDeviceInfo)); + if (DeviceIoControl (h, IOCTL_SCSI_PASS_THROUGH_DIRECT, + p, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), + p, sizeof (SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), + &bytesReturned, 0) != 0) + { + zeromem (&list[count], sizeof (CDDeviceInfo)); - list[count].scsiDriveLetter = driveLetter; + list[count].scsiDriveLetter = driveLetter; - memcpy (list[count].vendor, &buffer[8], 8); - memcpy (list[count].productId, &buffer[16], 16); - memcpy (list[count].rev, &buffer[32], 4); - memcpy (list[count].vendorSpec, &buffer[36], 20); + memcpy (list[count].vendor, &buffer[8], 8); + memcpy (list[count].productId, &buffer[16], 16); + memcpy (list[count].rev, &buffer[32], 4); + memcpy (list[count].vendorSpec, &buffer[36], 20); - zeromem (passThroughStruct, sizeof (passThroughStruct)); - PSCSI_ADDRESS scsiAddr = (PSCSI_ADDRESS)passThroughStruct; + zeromem (passThroughStruct, sizeof (passThroughStruct)); + PSCSI_ADDRESS scsiAddr = (PSCSI_ADDRESS)passThroughStruct; - scsiAddr->Length = sizeof (SCSI_ADDRESS); + scsiAddr->Length = sizeof (SCSI_ADDRESS); - if (DeviceIoControl (h, IOCTL_SCSI_GET_ADDRESS, - 0, 0, scsiAddr, sizeof (SCSI_ADDRESS), - &bytesReturned, 0) != 0) - { - list[count].ha = scsiAddr->PortNumber; - list[count].tgt = scsiAddr->TargetId; - list[count].lun = scsiAddr->Lun; - ++count; - } - } + if (DeviceIoControl (h, IOCTL_SCSI_GET_ADDRESS, + 0, 0, scsiAddr, sizeof (SCSI_ADDRESS), + &bytesReturned, 0) != 0) + { + list[count].ha = scsiAddr->PortNumber; + list[count].tgt = scsiAddr->TargetId; + list[count].lun = scsiAddr->Lun; + ++count; + } + } - CloseHandle (h); - } - } - } - } - else - { - const DWORD d = fGetASPI32SupportInfo(); - BYTE status = HIBYTE (LOWORD (d)); + CloseHandle (h); + } + } + } + } + else + { + const DWORD d = fGetASPI32SupportInfo(); + BYTE status = HIBYTE (LOWORD (d)); - if (status != SS_COMP || status == SS_NO_ADAPTERS) - return 0; + if (status != SS_COMP || status == SS_NO_ADAPTERS) + return 0; - const int numAdapters = LOBYTE (LOWORD (d)); + const int numAdapters = LOBYTE (LOWORD (d)); - for (BYTE ha = 0; ha < numAdapters; ++ha) - { - SRB_HAInquiry s; - zerostruct (s); + for (BYTE ha = 0; ha < numAdapters; ++ha) + { + SRB_HAInquiry s; + zerostruct (s); - s.SRB_Cmd = SC_HA_INQUIRY; - s.SRB_HaID = ha; - fSendASPI32Command ((LPSRB)&s); + s.SRB_Cmd = SC_HA_INQUIRY; + s.SRB_HaID = ha; + fSendASPI32Command ((LPSRB)&s); - if (s.SRB_Status == SS_COMP) - { - maxItems = (int)s.HA_Unique[3]; + if (s.SRB_Status == SS_COMP) + { + maxItems = (int)s.HA_Unique[3]; - if (maxItems == 0) - maxItems = 8; + if (maxItems == 0) + maxItems = 8; - for (BYTE tgt = 0; tgt < maxItems; ++tgt) - { - for (BYTE lun = 0; lun < 8; ++lun) - { - SRB_GDEVBlock sb; - zerostruct (sb); + for (BYTE tgt = 0; tgt < maxItems; ++tgt) + { + for (BYTE lun = 0; lun < 8; ++lun) + { + SRB_GDEVBlock sb; + zerostruct (sb); - sb.SRB_Cmd = SC_GET_DEV_TYPE; - sb.SRB_HaID = ha; - sb.SRB_Target = tgt; - sb.SRB_Lun = lun; - fSendASPI32Command ((LPSRB) &sb); + sb.SRB_Cmd = SC_GET_DEV_TYPE; + sb.SRB_HaID = ha; + sb.SRB_Target = tgt; + sb.SRB_Lun = lun; + fSendASPI32Command ((LPSRB) &sb); - if (sb.SRB_Status == SS_COMP - && sb.SRB_DeviceType == DTYPE_CROM) - { - zeromem (&list[count], sizeof (CDDeviceInfo)); + if (sb.SRB_Status == SS_COMP + && sb.SRB_DeviceType == DTYPE_CROM) + { + zeromem (&list[count], sizeof (CDDeviceInfo)); - list[count].ha = ha; - list[count].tgt = tgt; - list[count].lun = lun; + list[count].ha = ha; + list[count].tgt = tgt; + list[count].lun = lun; - GetAspiDeviceInfo (&(list[count]), ha, tgt, lun); + GetAspiDeviceInfo (&(list[count]), ha, tgt, lun); - ++count; - } - } - } - } - } - } + ++count; + } + } + } + } + } + } - return count; + return count; } static int ripperUsers = 0; static bool initialisedOk = false; class DeinitialiseTimer : private Timer, - private DeletedAtShutdown + private DeletedAtShutdown { - DeinitialiseTimer (const DeinitialiseTimer&); - const DeinitialiseTimer& operator= (const DeinitialiseTimer&); + DeinitialiseTimer (const DeinitialiseTimer&); + const DeinitialiseTimer& operator= (const DeinitialiseTimer&); public: - DeinitialiseTimer() - { - startTimer (4000); - } + DeinitialiseTimer() + { + startTimer (4000); + } - ~DeinitialiseTimer() - { - if (--ripperUsers == 0) - DeinitialiseCDRipper(); - } + ~DeinitialiseTimer() + { + if (--ripperUsers == 0) + DeinitialiseCDRipper(); + } - void timerCallback() - { - delete this; - } + void timerCallback() + { + delete this; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; static void incUserCount() { - if (ripperUsers++ == 0) - initialisedOk = InitialiseCDRipper(); + if (ripperUsers++ == 0) + initialisedOk = InitialiseCDRipper(); } static void decUserCount() { - new DeinitialiseTimer(); + new DeinitialiseTimer(); } struct CDDeviceWrapper { - CDDeviceHandle* cdH; - CDReadBuffer* overlapBuffer; - bool jitter; + CDDeviceHandle* cdH; + CDReadBuffer* overlapBuffer; + bool jitter; }; static int getAddressOf (const TOCTRACK* const t) { - return (((DWORD)t->addr[0]) << 24) + (((DWORD)t->addr[1]) << 16) + - (((DWORD)t->addr[2]) << 8) + ((DWORD)t->addr[3]); + return (((DWORD)t->addr[0]) << 24) + (((DWORD)t->addr[1]) << 16) + + (((DWORD)t->addr[2]) << 8) + ((DWORD)t->addr[3]); } static int getMSFAddressOf (const TOCTRACK* const t) { - return 60 * t->addr[1] + t->addr[2]; + return 60 * t->addr[1] + t->addr[2]; } static const int samplesPerFrame = 44100 / 75; @@ -243884,455 +221619,455 @@ static const int bytesPerFrame = samplesPerFrame * 4; const StringArray AudioCDReader::getAvailableCDNames() { - StringArray results; - incUserCount(); + StringArray results; + incUserCount(); - if (initialisedOk) - { - CDDeviceInfo list[8]; - const int num = FindCDDevices (list, 8); + if (initialisedOk) + { + CDDeviceInfo list[8]; + const int num = FindCDDevices (list, 8); - decUserCount(); + decUserCount(); - for (int i = 0; i < num; ++i) - { - String s; + for (int i = 0; i < num; ++i) + { + String s; - if (list[i].scsiDriveLetter > 0) - s << String::charToString (list[i].scsiDriveLetter).toUpperCase() << T(": "); + if (list[i].scsiDriveLetter > 0) + s << String::charToString (list[i].scsiDriveLetter).toUpperCase() << T(": "); - s << String (list[i].vendor).trim() - << T(" ") << String (list[i].productId).trim() - << T(" ") << String (list[i].rev).trim(); + s << String (list[i].vendor).trim() + << T(" ") << String (list[i].productId).trim() + << T(" ") << String (list[i].rev).trim(); - results.add (s); - } - } + results.add (s); + } + } - return results; + return results; } static CDDeviceHandle* openHandle (const CDDeviceInfo* const device) { - SRB_GDEVBlock s; - zerostruct (s); + SRB_GDEVBlock s; + zerostruct (s); - s.SRB_Cmd = SC_GET_DEV_TYPE; - s.SRB_HaID = device->ha; - s.SRB_Target = device->tgt; - s.SRB_Lun = device->lun; + s.SRB_Cmd = SC_GET_DEV_TYPE; + s.SRB_HaID = device->ha; + s.SRB_Target = device->tgt; + s.SRB_Lun = device->lun; - if (usingScsi) - { - HANDLE h = CreateSCSIDeviceHandle (device->scsiDriveLetter); + if (usingScsi) + { + HANDLE h = CreateSCSIDeviceHandle (device->scsiDriveLetter); - if (h != INVALID_HANDLE_VALUE) - { - CDDeviceHandle* cdh = new CDDeviceHandle (device); - cdh->scsiHandle = h; - return cdh; - } - } - else - { - if (fSendASPI32Command ((LPSRB)&s) == SS_COMP - && s.SRB_DeviceType == DTYPE_CROM) - { - return new CDDeviceHandle (device); - } - } + if (h != INVALID_HANDLE_VALUE) + { + CDDeviceHandle* cdh = new CDDeviceHandle (device); + cdh->scsiHandle = h; + return cdh; + } + } + else + { + if (fSendASPI32Command ((LPSRB)&s) == SS_COMP + && s.SRB_DeviceType == DTYPE_CROM) + { + return new CDDeviceHandle (device); + } + } - return 0; + return 0; } AudioCDReader* AudioCDReader::createReaderForCD (const int deviceIndex) { - incUserCount(); + incUserCount(); - if (initialisedOk) - { - CDDeviceInfo list[8]; - const int num = FindCDDevices (list, 8); + if (initialisedOk) + { + CDDeviceInfo list[8]; + const int num = FindCDDevices (list, 8); - if (((unsigned int) deviceIndex) < (unsigned int) num) - { - CDDeviceHandle* const handle = openHandle (&(list[deviceIndex])); + if (((unsigned int) deviceIndex) < (unsigned int) num) + { + CDDeviceHandle* const handle = openHandle (&(list[deviceIndex])); - if (handle != 0) - { - CDDeviceWrapper* const d = new CDDeviceWrapper(); - d->cdH = handle; - d->overlapBuffer = new CDReadBuffer(3); + if (handle != 0) + { + CDDeviceWrapper* const d = new CDDeviceWrapper(); + d->cdH = handle; + d->overlapBuffer = new CDReadBuffer(3); - return new AudioCDReader (d); - } - } - } + return new AudioCDReader (d); + } + } + } - decUserCount(); - return 0; + decUserCount(); + return 0; } AudioCDReader::AudioCDReader (void* handle_) - : AudioFormatReader (0, T("CD Audio")), - handle (handle_), - indexingEnabled (false), - lastIndex (0), - firstFrameInBuffer (0), - samplesInBuffer (0) + : AudioFormatReader (0, T("CD Audio")), + handle (handle_), + indexingEnabled (false), + lastIndex (0), + firstFrameInBuffer (0), + samplesInBuffer (0) { - jassert (handle_ != 0); + jassert (handle_ != 0); - refreshTrackLengths(); + refreshTrackLengths(); - sampleRate = 44100.0; - bitsPerSample = 16; - lengthInSamples = getPositionOfTrackStart (numTracks); - numChannels = 2; - usesFloatingPointData = false; + sampleRate = 44100.0; + bitsPerSample = 16; + lengthInSamples = getPositionOfTrackStart (numTracks); + numChannels = 2; + usesFloatingPointData = false; - buffer.setSize (4 * bytesPerFrame, true); + buffer.setSize (4 * bytesPerFrame, true); } AudioCDReader::~AudioCDReader() { - CDDeviceWrapper* const device = (CDDeviceWrapper*)handle; + CDDeviceWrapper* const device = (CDDeviceWrapper*)handle; - delete device->cdH; - delete device->overlapBuffer; - delete device; + delete device->cdH; + delete device->overlapBuffer; + delete device; - decUserCount(); + decUserCount(); } bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples) + int64 startSampleInFile, int numSamples) { - CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; + CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; - bool ok = true; + bool ok = true; - while (numSamples > 0) - { - const int bufferStartSample = firstFrameInBuffer * samplesPerFrame; - const int bufferEndSample = bufferStartSample + samplesInBuffer; + while (numSamples > 0) + { + const int bufferStartSample = firstFrameInBuffer * samplesPerFrame; + const int bufferEndSample = bufferStartSample + samplesInBuffer; - if (startSampleInFile >= bufferStartSample - && startSampleInFile < bufferEndSample) - { - const int toDo = (int) jmin ((int64) numSamples, bufferEndSample - startSampleInFile); + if (startSampleInFile >= bufferStartSample + && startSampleInFile < bufferEndSample) + { + const int toDo = (int) jmin ((int64) numSamples, bufferEndSample - startSampleInFile); - int* const l = destSamples[0] + startOffsetInDestBuffer; - int* const r = numDestChannels > 1 ? (destSamples[1] + startOffsetInDestBuffer) : 0; - const short* src = (const short*) buffer.getData(); - src += 2 * (startSampleInFile - bufferStartSample); + int* const l = destSamples[0] + startOffsetInDestBuffer; + int* const r = numDestChannels > 1 ? (destSamples[1] + startOffsetInDestBuffer) : 0; + const short* src = (const short*) buffer.getData(); + src += 2 * (startSampleInFile - bufferStartSample); - for (int i = 0; i < toDo; ++i) - { - l[i] = src [i << 1] << 16; + for (int i = 0; i < toDo; ++i) + { + l[i] = src [i << 1] << 16; - if (r != 0) - r[i] = src [(i << 1) + 1] << 16; - } + if (r != 0) + r[i] = src [(i << 1) + 1] << 16; + } - startOffsetInDestBuffer += toDo; - startSampleInFile += toDo; - numSamples -= toDo; - } - else - { - const int framesInBuffer = buffer.getSize() / bytesPerFrame; - const int frameNeeded = (int) (startSampleInFile / samplesPerFrame); + startOffsetInDestBuffer += toDo; + startSampleInFile += toDo; + numSamples -= toDo; + } + else + { + const int framesInBuffer = buffer.getSize() / bytesPerFrame; + const int frameNeeded = (int) (startSampleInFile / samplesPerFrame); - if (firstFrameInBuffer + framesInBuffer != frameNeeded) - { - device->overlapBuffer->dataLength = 0; - device->overlapBuffer->startFrame = 0; - device->overlapBuffer->numFrames = 0; - device->jitter = false; - } + if (firstFrameInBuffer + framesInBuffer != frameNeeded) + { + device->overlapBuffer->dataLength = 0; + device->overlapBuffer->startFrame = 0; + device->overlapBuffer->numFrames = 0; + device->jitter = false; + } - firstFrameInBuffer = frameNeeded; - lastIndex = 0; + firstFrameInBuffer = frameNeeded; + lastIndex = 0; - CDReadBuffer readBuffer (framesInBuffer + 4); - readBuffer.wantsIndex = indexingEnabled; + CDReadBuffer readBuffer (framesInBuffer + 4); + readBuffer.wantsIndex = indexingEnabled; - int i; - for (i = 5; --i >= 0;) - { - readBuffer.startFrame = frameNeeded; - readBuffer.numFrames = framesInBuffer; + int i; + for (i = 5; --i >= 0;) + { + readBuffer.startFrame = frameNeeded; + readBuffer.numFrames = framesInBuffer; - if (device->cdH->readAudio (&readBuffer, (device->jitter) ? device->overlapBuffer : 0)) - break; - else - device->overlapBuffer->dataLength = 0; - } + if (device->cdH->readAudio (&readBuffer, (device->jitter) ? device->overlapBuffer : 0)) + break; + else + device->overlapBuffer->dataLength = 0; + } - if (i >= 0) - { - memcpy ((char*) buffer.getData(), - readBuffer.buffer + readBuffer.dataStartOffset, - readBuffer.dataLength); + if (i >= 0) + { + memcpy ((char*) buffer.getData(), + readBuffer.buffer + readBuffer.dataStartOffset, + readBuffer.dataLength); - samplesInBuffer = readBuffer.dataLength >> 2; - lastIndex = readBuffer.index; - } - else - { - int* l = destSamples[0] + startOffsetInDestBuffer; - int* r = numDestChannels > 1 ? (destSamples[1] + startOffsetInDestBuffer) : 0; + samplesInBuffer = readBuffer.dataLength >> 2; + lastIndex = readBuffer.index; + } + else + { + int* l = destSamples[0] + startOffsetInDestBuffer; + int* r = numDestChannels > 1 ? (destSamples[1] + startOffsetInDestBuffer) : 0; - while (--numSamples >= 0) - { - *l++ = 0; + while (--numSamples >= 0) + { + *l++ = 0; - if (r != 0) - *r++ = 0; - } + if (r != 0) + *r++ = 0; + } - // sometimes the read fails for just the very last couple of blocks, so - // we'll ignore and errors in the last half-second of the disk.. - ok = startSampleInFile > (trackStarts [numTracks] - 20000); - break; - } - } - } + // sometimes the read fails for just the very last couple of blocks, so + // we'll ignore and errors in the last half-second of the disk.. + ok = startSampleInFile > (trackStarts [numTracks] - 20000); + break; + } + } + } - return ok; + return ok; } bool AudioCDReader::isCDStillPresent() const { - TOC toc; - zerostruct (toc); + TOC toc; + zerostruct (toc); - return ((CDDeviceWrapper*)handle)->cdH->readTOC (&toc, false); + return ((CDDeviceWrapper*)handle)->cdH->readTOC (&toc, false); } int AudioCDReader::getNumTracks() const { - return numTracks; + return numTracks; } int AudioCDReader::getPositionOfTrackStart (int trackNum) const { - return (trackNum >= 0 && trackNum <= numTracks) ? trackStarts [trackNum] * samplesPerFrame - : 0; + return (trackNum >= 0 && trackNum <= numTracks) ? trackStarts [trackNum] * samplesPerFrame + : 0; } void AudioCDReader::refreshTrackLengths() { - zeromem (trackStarts, sizeof (trackStarts)); - zeromem (audioTracks, sizeof (audioTracks)); + zeromem (trackStarts, sizeof (trackStarts)); + zeromem (audioTracks, sizeof (audioTracks)); - TOC toc; - zerostruct (toc); + TOC toc; + zerostruct (toc); - if (((CDDeviceWrapper*)handle)->cdH->readTOC (&toc, false)) - { - numTracks = 1 + toc.lastTrack - toc.firstTrack; + if (((CDDeviceWrapper*)handle)->cdH->readTOC (&toc, false)) + { + numTracks = 1 + toc.lastTrack - toc.firstTrack; - for (int i = 0; i <= numTracks; ++i) - { - trackStarts[i] = getAddressOf (&toc.tracks[i]); - audioTracks[i] = ((toc.tracks[i].ADR & 4) == 0); - } - } - else - { - numTracks = 0; - } + for (int i = 0; i <= numTracks; ++i) + { + trackStarts[i] = getAddressOf (&toc.tracks[i]); + audioTracks[i] = ((toc.tracks[i].ADR & 4) == 0); + } + } + else + { + numTracks = 0; + } } bool AudioCDReader::isTrackAudio (int trackNum) const { - return (trackNum >= 0 && trackNum <= numTracks) ? audioTracks [trackNum] - : false; + return (trackNum >= 0 && trackNum <= numTracks) ? audioTracks [trackNum] + : false; } void AudioCDReader::enableIndexScanning (bool b) { - indexingEnabled = b; + indexingEnabled = b; } int AudioCDReader::getLastIndex() const { - return lastIndex; + return lastIndex; } const int framesPerIndexRead = 4; int AudioCDReader::getIndexAt (int samplePos) { - CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; + CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; - const int frameNeeded = samplePos / samplesPerFrame; + const int frameNeeded = samplePos / samplesPerFrame; - device->overlapBuffer->dataLength = 0; - device->overlapBuffer->startFrame = 0; - device->overlapBuffer->numFrames = 0; - device->jitter = false; + device->overlapBuffer->dataLength = 0; + device->overlapBuffer->startFrame = 0; + device->overlapBuffer->numFrames = 0; + device->jitter = false; - firstFrameInBuffer = 0; - lastIndex = 0; + firstFrameInBuffer = 0; + lastIndex = 0; - CDReadBuffer readBuffer (4 + framesPerIndexRead); - readBuffer.wantsIndex = true; + CDReadBuffer readBuffer (4 + framesPerIndexRead); + readBuffer.wantsIndex = true; - int i; - for (i = 5; --i >= 0;) - { - readBuffer.startFrame = frameNeeded; - readBuffer.numFrames = framesPerIndexRead; + int i; + for (i = 5; --i >= 0;) + { + readBuffer.startFrame = frameNeeded; + readBuffer.numFrames = framesPerIndexRead; - if (device->cdH->readAudio (&readBuffer, (false) ? device->overlapBuffer : 0)) - break; - } + if (device->cdH->readAudio (&readBuffer, (false) ? device->overlapBuffer : 0)) + break; + } - if (i >= 0) - return readBuffer.index; + if (i >= 0) + return readBuffer.index; - return -1; + return -1; } const Array AudioCDReader::findIndexesInTrack (const int trackNumber) { - Array indexes; + Array indexes; - const int trackStart = getPositionOfTrackStart (trackNumber); - const int trackEnd = getPositionOfTrackStart (trackNumber + 1); + const int trackStart = getPositionOfTrackStart (trackNumber); + const int trackEnd = getPositionOfTrackStart (trackNumber + 1); - bool needToScan = true; + bool needToScan = true; - if (trackEnd - trackStart > 20 * 44100) - { - // check the end of the track for indexes before scanning the whole thing - needToScan = false; - int pos = jmax (trackStart, trackEnd - 44100 * 5); - bool seenAnIndex = false; + if (trackEnd - trackStart > 20 * 44100) + { + // check the end of the track for indexes before scanning the whole thing + needToScan = false; + int pos = jmax (trackStart, trackEnd - 44100 * 5); + bool seenAnIndex = false; - while (pos <= trackEnd - samplesPerFrame) - { - const int index = getIndexAt (pos); + while (pos <= trackEnd - samplesPerFrame) + { + const int index = getIndexAt (pos); - if (index == 0) - { - // lead-out, so skip back a bit if we've not found any indexes yet.. - if (seenAnIndex) - break; + if (index == 0) + { + // lead-out, so skip back a bit if we've not found any indexes yet.. + if (seenAnIndex) + break; - pos -= 44100 * 5; + pos -= 44100 * 5; - if (pos < trackStart) - break; - } - else - { - if (index > 0) - seenAnIndex = true; + if (pos < trackStart) + break; + } + else + { + if (index > 0) + seenAnIndex = true; - if (index > 1) - { - needToScan = true; - break; - } + if (index > 1) + { + needToScan = true; + break; + } - pos += samplesPerFrame * framesPerIndexRead; - } - } - } + pos += samplesPerFrame * framesPerIndexRead; + } + } + } - if (needToScan) - { - CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; + if (needToScan) + { + CDDeviceWrapper* const device = (CDDeviceWrapper*) handle; - int pos = trackStart; - int last = -1; + int pos = trackStart; + int last = -1; - while (pos < trackEnd - samplesPerFrame * 10) - { - const int frameNeeded = pos / samplesPerFrame; + while (pos < trackEnd - samplesPerFrame * 10) + { + const int frameNeeded = pos / samplesPerFrame; - device->overlapBuffer->dataLength = 0; - device->overlapBuffer->startFrame = 0; - device->overlapBuffer->numFrames = 0; - device->jitter = false; + device->overlapBuffer->dataLength = 0; + device->overlapBuffer->startFrame = 0; + device->overlapBuffer->numFrames = 0; + device->jitter = false; - firstFrameInBuffer = 0; + firstFrameInBuffer = 0; - CDReadBuffer readBuffer (4); - readBuffer.wantsIndex = true; + CDReadBuffer readBuffer (4); + readBuffer.wantsIndex = true; - int i; - for (i = 5; --i >= 0;) - { - readBuffer.startFrame = frameNeeded; - readBuffer.numFrames = framesPerIndexRead; + int i; + for (i = 5; --i >= 0;) + { + readBuffer.startFrame = frameNeeded; + readBuffer.numFrames = framesPerIndexRead; - if (device->cdH->readAudio (&readBuffer, (false) ? device->overlapBuffer : 0)) - break; - } + if (device->cdH->readAudio (&readBuffer, (false) ? device->overlapBuffer : 0)) + break; + } - if (i < 0) - break; + if (i < 0) + break; - if (readBuffer.index > last && readBuffer.index > 1) - { - last = readBuffer.index; - indexes.add (pos); - } + if (readBuffer.index > last && readBuffer.index > 1) + { + last = readBuffer.index; + indexes.add (pos); + } - pos += samplesPerFrame * framesPerIndexRead; - } + pos += samplesPerFrame * framesPerIndexRead; + } - indexes.removeValue (trackStart); - } + indexes.removeValue (trackStart); + } - return indexes; + return indexes; } int AudioCDReader::getCDDBId() { - refreshTrackLengths(); + refreshTrackLengths(); - if (numTracks > 0) - { - TOC toc; - zerostruct (toc); + if (numTracks > 0) + { + TOC toc; + zerostruct (toc); - if (((CDDeviceWrapper*) handle)->cdH->readTOC (&toc, true)) - { - int n = 0; + if (((CDDeviceWrapper*) handle)->cdH->readTOC (&toc, true)) + { + int n = 0; - for (int i = numTracks; --i >= 0;) - { - int j = getMSFAddressOf (&toc.tracks[i]); + for (int i = numTracks; --i >= 0;) + { + int j = getMSFAddressOf (&toc.tracks[i]); - while (j > 0) - { - n += (j % 10); - j /= 10; - } - } + while (j > 0) + { + n += (j % 10); + j /= 10; + } + } - if (n != 0) - { - const int t = getMSFAddressOf (&toc.tracks[numTracks]) - - getMSFAddressOf (&toc.tracks[0]); + if (n != 0) + { + const int t = getMSFAddressOf (&toc.tracks[numTracks]) + - getMSFAddressOf (&toc.tracks[0]); - return ((n % 0xff) << 24) | (t << 8) | numTracks; - } - } - } + return ((n % 0xff) << 24) | (t << 8) | numTracks; + } + } + } - return 0; + return 0; } void AudioCDReader::ejectDisk() { - ((CDDeviceWrapper*) handle)->cdH->openDrawer (true); + ((CDDeviceWrapper*) handle)->cdH->openDrawer (true); } #endif @@ -244341,300 +222076,300 @@ void AudioCDReader::ejectDisk() static IDiscRecorder* enumCDBurners (StringArray* list, int indexToOpen, IDiscMaster** master) { - CoInitialize (0); + CoInitialize (0); - IDiscMaster* dm; - IDiscRecorder* result = 0; + IDiscMaster* dm; + IDiscRecorder* result = 0; - if (SUCCEEDED (CoCreateInstance (CLSID_MSDiscMasterObj, 0, - CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, - IID_IDiscMaster, - (void**) &dm))) - { - if (SUCCEEDED (dm->Open())) - { - IEnumDiscRecorders* drEnum = 0; + if (SUCCEEDED (CoCreateInstance (CLSID_MSDiscMasterObj, 0, + CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, + IID_IDiscMaster, + (void**) &dm))) + { + if (SUCCEEDED (dm->Open())) + { + IEnumDiscRecorders* drEnum = 0; - if (SUCCEEDED (dm->EnumDiscRecorders (&drEnum))) - { - IDiscRecorder* dr = 0; - DWORD dummy; - int index = 0; + if (SUCCEEDED (dm->EnumDiscRecorders (&drEnum))) + { + IDiscRecorder* dr = 0; + DWORD dummy; + int index = 0; - while (drEnum->Next (1, &dr, &dummy) == S_OK) - { - if (indexToOpen == index) - { - result = dr; - break; - } - else if (list != 0) - { - BSTR path; + while (drEnum->Next (1, &dr, &dummy) == S_OK) + { + if (indexToOpen == index) + { + result = dr; + break; + } + else if (list != 0) + { + BSTR path; - if (SUCCEEDED (dr->GetPath (&path))) - list->add ((const WCHAR*) path); - } + if (SUCCEEDED (dr->GetPath (&path))) + list->add ((const WCHAR*) path); + } - ++index; - dr->Release(); - } + ++index; + dr->Release(); + } - drEnum->Release(); - } + drEnum->Release(); + } - if (master == 0) - dm->Close(); - } + if (master == 0) + dm->Close(); + } - if (master != 0) - *master = dm; - else - dm->Release(); - } + if (master != 0) + *master = dm; + else + dm->Release(); + } - return result; + return result; } const StringArray AudioCDBurner::findAvailableDevices() { - StringArray devs; - enumCDBurners (&devs, -1, 0); - return devs; + StringArray devs; + enumCDBurners (&devs, -1, 0); + return devs; } AudioCDBurner* AudioCDBurner::openDevice (const int deviceIndex) { - AudioCDBurner* b = new AudioCDBurner (deviceIndex); + AudioCDBurner* b = new AudioCDBurner (deviceIndex); - if (b->internal == 0) - deleteAndZero (b); + if (b->internal == 0) + deleteAndZero (b); - return b; + return b; } class CDBurnerInfo : public IDiscMasterProgressEvents { public: - CDBurnerInfo() - : refCount (1), - progress (0), - shouldCancel (false), - listener (0) - { - } + CDBurnerInfo() + : refCount (1), + progress (0), + shouldCancel (false), + listener (0) + { + } - ~CDBurnerInfo() - { - } + ~CDBurnerInfo() + { + } - HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) - { - if (result == 0) - return E_POINTER; + HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result) + { + if (result == 0) + return E_POINTER; - if (id == IID_IUnknown || id == IID_IDiscMasterProgressEvents) - { - AddRef(); - *result = this; - return S_OK; - } + if (id == IID_IUnknown || id == IID_IDiscMasterProgressEvents) + { + AddRef(); + *result = this; + return S_OK; + } - *result = 0; - return E_NOINTERFACE; - } + *result = 0; + return E_NOINTERFACE; + } - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { jassert (refCount > 0); const int r = --refCount; if (r == 0) delete this; return r; } - HRESULT __stdcall QueryCancel (boolean* pbCancel) - { - if (listener != 0 && ! shouldCancel) - shouldCancel = listener->audioCDBurnProgress (progress); + HRESULT __stdcall QueryCancel (boolean* pbCancel) + { + if (listener != 0 && ! shouldCancel) + shouldCancel = listener->audioCDBurnProgress (progress); - *pbCancel = shouldCancel; + *pbCancel = shouldCancel; - return S_OK; - } + return S_OK; + } - HRESULT __stdcall NotifyBlockProgress (long nCompleted, long nTotal) - { - progress = nCompleted / (float) nTotal; - shouldCancel = listener != 0 && listener->audioCDBurnProgress (progress); + HRESULT __stdcall NotifyBlockProgress (long nCompleted, long nTotal) + { + progress = nCompleted / (float) nTotal; + shouldCancel = listener != 0 && listener->audioCDBurnProgress (progress); - return E_NOTIMPL; - } + return E_NOTIMPL; + } - HRESULT __stdcall NotifyPnPActivity (void) { return E_NOTIMPL; } - HRESULT __stdcall NotifyAddProgress (long /*nCompletedSteps*/, long /*nTotalSteps*/) { return E_NOTIMPL; } - HRESULT __stdcall NotifyTrackProgress (long /*nCurrentTrack*/, long /*nTotalTracks*/) { return E_NOTIMPL; } - HRESULT __stdcall NotifyPreparingBurn (long /*nEstimatedSeconds*/) { return E_NOTIMPL; } - HRESULT __stdcall NotifyClosingDisc (long /*nEstimatedSeconds*/) { return E_NOTIMPL; } - HRESULT __stdcall NotifyBurnComplete (HRESULT /*status*/) { return E_NOTIMPL; } - HRESULT __stdcall NotifyEraseComplete (HRESULT /*status*/) { return E_NOTIMPL; } + HRESULT __stdcall NotifyPnPActivity (void) { return E_NOTIMPL; } + HRESULT __stdcall NotifyAddProgress (long /*nCompletedSteps*/, long /*nTotalSteps*/) { return E_NOTIMPL; } + HRESULT __stdcall NotifyTrackProgress (long /*nCurrentTrack*/, long /*nTotalTracks*/) { return E_NOTIMPL; } + HRESULT __stdcall NotifyPreparingBurn (long /*nEstimatedSeconds*/) { return E_NOTIMPL; } + HRESULT __stdcall NotifyClosingDisc (long /*nEstimatedSeconds*/) { return E_NOTIMPL; } + HRESULT __stdcall NotifyBurnComplete (HRESULT /*status*/) { return E_NOTIMPL; } + HRESULT __stdcall NotifyEraseComplete (HRESULT /*status*/) { return E_NOTIMPL; } - IDiscMaster* discMaster; - IDiscRecorder* discRecorder; - IRedbookDiscMaster* redbook; - AudioCDBurner::BurnProgressListener* listener; - float progress; - bool shouldCancel; + IDiscMaster* discMaster; + IDiscRecorder* discRecorder; + IRedbookDiscMaster* redbook; + AudioCDBurner::BurnProgressListener* listener; + float progress; + bool shouldCancel; private: - int refCount; + int refCount; }; AudioCDBurner::AudioCDBurner (const int deviceIndex) - : internal (0) + : internal (0) { - IDiscMaster* discMaster; - IDiscRecorder* dr = enumCDBurners (0, deviceIndex, &discMaster); + IDiscMaster* discMaster; + IDiscRecorder* dr = enumCDBurners (0, deviceIndex, &discMaster); - if (dr != 0) - { - IRedbookDiscMaster* redbook; - HRESULT hr = discMaster->SetActiveDiscMasterFormat (IID_IRedbookDiscMaster, (void**) &redbook); + if (dr != 0) + { + IRedbookDiscMaster* redbook; + HRESULT hr = discMaster->SetActiveDiscMasterFormat (IID_IRedbookDiscMaster, (void**) &redbook); - hr = discMaster->SetActiveDiscRecorder (dr); + hr = discMaster->SetActiveDiscRecorder (dr); - CDBurnerInfo* const info = new CDBurnerInfo(); - internal = info; + CDBurnerInfo* const info = new CDBurnerInfo(); + internal = info; - info->discMaster = discMaster; - info->discRecorder = dr; - info->redbook = redbook; - } + info->discMaster = discMaster; + info->discRecorder = dr; + info->redbook = redbook; + } } AudioCDBurner::~AudioCDBurner() { - CDBurnerInfo* const info = (CDBurnerInfo*) internal; + CDBurnerInfo* const info = (CDBurnerInfo*) internal; - if (info != 0) - { - info->discRecorder->Close(); - info->redbook->Release(); - info->discRecorder->Release(); - info->discMaster->Release(); + if (info != 0) + { + info->discRecorder->Close(); + info->redbook->Release(); + info->discRecorder->Release(); + info->discMaster->Release(); - info->Release(); - } + info->Release(); + } } bool AudioCDBurner::isDiskPresent() const { - CDBurnerInfo* const info = (CDBurnerInfo*) internal; + CDBurnerInfo* const info = (CDBurnerInfo*) internal; - HRESULT hr = info->discRecorder->OpenExclusive(); + HRESULT hr = info->discRecorder->OpenExclusive(); - long type, flags; - hr = info->discRecorder->QueryMediaType (&type, &flags); + long type, flags; + hr = info->discRecorder->QueryMediaType (&type, &flags); - info->discRecorder->Close(); - return hr == S_OK && type != 0 && (flags & MEDIA_WRITABLE) != 0; + info->discRecorder->Close(); + return hr == S_OK && type != 0 && (flags & MEDIA_WRITABLE) != 0; } int AudioCDBurner::getNumAvailableAudioBlocks() const { - CDBurnerInfo* const info = (CDBurnerInfo*) internal; - long blocksFree = 0; - info->redbook->GetAvailableAudioTrackBlocks (&blocksFree); - return blocksFree; + CDBurnerInfo* const info = (CDBurnerInfo*) internal; + long blocksFree = 0; + info->redbook->GetAvailableAudioTrackBlocks (&blocksFree); + return blocksFree; } const String AudioCDBurner::burn (AudioCDBurner::BurnProgressListener* listener, - const bool ejectDiscAfterwards, - const bool performFakeBurnForTesting) + const bool ejectDiscAfterwards, + const bool performFakeBurnForTesting) { - CDBurnerInfo* const info = (CDBurnerInfo*) internal; + CDBurnerInfo* const info = (CDBurnerInfo*) internal; - info->listener = listener; - info->progress = 0; - info->shouldCancel = false; + info->listener = listener; + info->progress = 0; + info->shouldCancel = false; - UINT_PTR cookie; - HRESULT hr = info->discMaster->ProgressAdvise (info, &cookie); + UINT_PTR cookie; + HRESULT hr = info->discMaster->ProgressAdvise (info, &cookie); - hr = info->discMaster->RecordDisc (performFakeBurnForTesting, - ejectDiscAfterwards); + hr = info->discMaster->RecordDisc (performFakeBurnForTesting, + ejectDiscAfterwards); - String error; - if (hr != S_OK) - { - const char* e = "Couldn't open or write to the CD device"; + String error; + if (hr != S_OK) + { + const char* e = "Couldn't open or write to the CD device"; - if (hr == IMAPI_E_USERABORT) - e = "User cancelled the write operation"; - else if (hr == IMAPI_E_MEDIUM_NOTPRESENT || hr == IMAPI_E_TRACKOPEN) - e = "No Disk present"; + if (hr == IMAPI_E_USERABORT) + e = "User cancelled the write operation"; + else if (hr == IMAPI_E_MEDIUM_NOTPRESENT || hr == IMAPI_E_TRACKOPEN) + e = "No Disk present"; - error = e; - } + error = e; + } - info->discMaster->ProgressUnadvise (cookie); - info->listener = 0; + info->discMaster->ProgressUnadvise (cookie); + info->listener = 0; - return error; + return error; } bool AudioCDBurner::addAudioTrack (AudioSource* source, int numSamples) { - if (source == 0) - return false; + if (source == 0) + return false; - CDBurnerInfo* const info = (CDBurnerInfo*) internal; + CDBurnerInfo* const info = (CDBurnerInfo*) internal; - long bytesPerBlock; - HRESULT hr = info->redbook->GetAudioBlockSize (&bytesPerBlock); + long bytesPerBlock; + HRESULT hr = info->redbook->GetAudioBlockSize (&bytesPerBlock); - const int samplesPerBlock = bytesPerBlock / 4; - bool ok = true; + const int samplesPerBlock = bytesPerBlock / 4; + bool ok = true; - hr = info->redbook->CreateAudioTrack ((long) numSamples / (bytesPerBlock * 4)); + hr = info->redbook->CreateAudioTrack ((long) numSamples / (bytesPerBlock * 4)); - HeapBlock buffer (bytesPerBlock); + HeapBlock buffer (bytesPerBlock); - AudioSampleBuffer sourceBuffer (2, samplesPerBlock); - int samplesDone = 0; + AudioSampleBuffer sourceBuffer (2, samplesPerBlock); + int samplesDone = 0; - source->prepareToPlay (samplesPerBlock, 44100.0); + source->prepareToPlay (samplesPerBlock, 44100.0); - while (ok) - { - { - AudioSourceChannelInfo info; - info.buffer = &sourceBuffer; - info.numSamples = samplesPerBlock; - info.startSample = 0; - sourceBuffer.clear(); + while (ok) + { + { + AudioSourceChannelInfo info; + info.buffer = &sourceBuffer; + info.numSamples = samplesPerBlock; + info.startSample = 0; + sourceBuffer.clear(); - source->getNextAudioBlock (info); - } + source->getNextAudioBlock (info); + } - zeromem (buffer, bytesPerBlock); + zeromem (buffer, bytesPerBlock); - AudioDataConverters::convertFloatToInt16LE (sourceBuffer.getSampleData (0, 0), - buffer, samplesPerBlock, 4); + AudioDataConverters::convertFloatToInt16LE (sourceBuffer.getSampleData (0, 0), + buffer, samplesPerBlock, 4); - AudioDataConverters::convertFloatToInt16LE (sourceBuffer.getSampleData (1, 0), - buffer + 2, samplesPerBlock, 4); + AudioDataConverters::convertFloatToInt16LE (sourceBuffer.getSampleData (1, 0), + buffer + 2, samplesPerBlock, 4); - hr = info->redbook->AddAudioTrackBlocks (buffer, bytesPerBlock); + hr = info->redbook->AddAudioTrackBlocks (buffer, bytesPerBlock); - if (hr != S_OK) - ok = false; + if (hr != S_OK) + ok = false; - samplesDone += samplesPerBlock; + samplesDone += samplesPerBlock; - if (samplesDone >= numSamples) - break; - } + if (samplesDone >= numSamples) + break; + } - hr = info->redbook->CloseAudioTrack(); + hr = info->redbook->CloseAudioTrack(); - delete source; + delete source; - return ok && hr == S_OK; + return ok && hr == S_OK; } #endif @@ -244657,583 +222392,583 @@ class MidiInThread : public Thread { public: - MidiInThread (MidiInput* const input_, - MidiInputCallback* const callback_) - : Thread ("Juce Midi"), - hIn (0), - input (input_), - callback (callback_), - isStarted (false), - startTime (0), - pendingLength(0) - { - for (int i = numInHeaders; --i >= 0;) - { - zeromem (&hdr[i], sizeof (MIDIHDR)); - hdr[i].lpData = inData[i]; - hdr[i].dwBufferLength = inBufferSize; - } - }; + MidiInThread (MidiInput* const input_, + MidiInputCallback* const callback_) + : Thread ("Juce Midi"), + hIn (0), + input (input_), + callback (callback_), + isStarted (false), + startTime (0), + pendingLength(0) + { + for (int i = numInHeaders; --i >= 0;) + { + zeromem (&hdr[i], sizeof (MIDIHDR)); + hdr[i].lpData = inData[i]; + hdr[i].dwBufferLength = inBufferSize; + } + }; - ~MidiInThread() - { - stop(); + ~MidiInThread() + { + stop(); - if (hIn != 0) - { - int count = 5; - while (--count >= 0) - { - if (midiInClose (hIn) == MMSYSERR_NOERROR) - break; + if (hIn != 0) + { + int count = 5; + while (--count >= 0) + { + if (midiInClose (hIn) == MMSYSERR_NOERROR) + break; - Sleep (20); - } - } - } + Sleep (20); + } + } + } - void handle (const uint32 message, const uint32 timeStamp) throw() - { - const int byte = message & 0xff; - if (byte < 0x80) - return; + void handle (const uint32 message, const uint32 timeStamp) throw() + { + const int byte = message & 0xff; + if (byte < 0x80) + return; - const int numBytes = MidiMessage::getMessageLengthFromFirstByte ((uint8) byte); + const int numBytes = MidiMessage::getMessageLengthFromFirstByte ((uint8) byte); - const double time = timeStampToTime (timeStamp); + const double time = timeStampToTime (timeStamp); - lock.enter(); - if (pendingLength < midiBufferSize - 12) - { - char* const p = pending + pendingLength; - *(double*) p = time; - *(uint32*) (p + 8) = numBytes; - *(uint32*) (p + 12) = message; - pendingLength += 12 + numBytes; - } - else - { - jassertfalse // midi buffer overflow! You might need to increase the size.. - } + lock.enter(); + if (pendingLength < midiBufferSize - 12) + { + char* const p = pending + pendingLength; + *(double*) p = time; + *(uint32*) (p + 8) = numBytes; + *(uint32*) (p + 12) = message; + pendingLength += 12 + numBytes; + } + else + { + jassertfalse // midi buffer overflow! You might need to increase the size.. + } - lock.exit(); - notify(); - } + lock.exit(); + notify(); + } - void handleSysEx (MIDIHDR* const hdr, const uint32 timeStamp) throw() - { - const int num = hdr->dwBytesRecorded; + void handleSysEx (MIDIHDR* const hdr, const uint32 timeStamp) throw() + { + const int num = hdr->dwBytesRecorded; - if (num > 0) - { - const double time = timeStampToTime (timeStamp); + if (num > 0) + { + const double time = timeStampToTime (timeStamp); - lock.enter(); + lock.enter(); - if (pendingLength < midiBufferSize - (8 + num)) - { - char* const p = pending + pendingLength; - *(double*) p = time; - *(uint32*) (p + 8) = num; - memcpy (p + 12, hdr->lpData, num); - pendingLength += 12 + num; - } - else - { - jassertfalse // midi buffer overflow! You might need to increase the size.. - } + if (pendingLength < midiBufferSize - (8 + num)) + { + char* const p = pending + pendingLength; + *(double*) p = time; + *(uint32*) (p + 8) = num; + memcpy (p + 12, hdr->lpData, num); + pendingLength += 12 + num; + } + else + { + jassertfalse // midi buffer overflow! You might need to increase the size.. + } - lock.exit(); - notify(); - } - } + lock.exit(); + notify(); + } + } - void writeBlock (const int i) throw() - { - hdr[i].dwBytesRecorded = 0; - MMRESULT res = midiInPrepareHeader (hIn, &hdr[i], sizeof (MIDIHDR)); - jassert (res == MMSYSERR_NOERROR); - res = midiInAddBuffer (hIn, &hdr[i], sizeof (MIDIHDR)); - jassert (res == MMSYSERR_NOERROR); - } + void writeBlock (const int i) throw() + { + hdr[i].dwBytesRecorded = 0; + MMRESULT res = midiInPrepareHeader (hIn, &hdr[i], sizeof (MIDIHDR)); + jassert (res == MMSYSERR_NOERROR); + res = midiInAddBuffer (hIn, &hdr[i], sizeof (MIDIHDR)); + jassert (res == MMSYSERR_NOERROR); + } - void run() - { - MemoryBlock pendingCopy (64); + void run() + { + MemoryBlock pendingCopy (64); - while (! threadShouldExit()) - { - for (int i = 0; i < numInHeaders; ++i) - { - if ((hdr[i].dwFlags & WHDR_DONE) != 0) - { - MMRESULT res = midiInUnprepareHeader (hIn, &hdr[i], sizeof (MIDIHDR)); - (void) res; - jassert (res == MMSYSERR_NOERROR); - writeBlock (i); - } - } + while (! threadShouldExit()) + { + for (int i = 0; i < numInHeaders; ++i) + { + if ((hdr[i].dwFlags & WHDR_DONE) != 0) + { + MMRESULT res = midiInUnprepareHeader (hIn, &hdr[i], sizeof (MIDIHDR)); + (void) res; + jassert (res == MMSYSERR_NOERROR); + writeBlock (i); + } + } - lock.enter(); + lock.enter(); - int len = pendingLength; + int len = pendingLength; - if (len > 0) - { - pendingCopy.ensureSize (len); - pendingCopy.copyFrom (pending, 0, len); - pendingLength = 0; - } + if (len > 0) + { + pendingCopy.ensureSize (len); + pendingCopy.copyFrom (pending, 0, len); + pendingLength = 0; + } - lock.exit(); + lock.exit(); //xxx needs to figure out if blocks are broken up or not - if (len == 0) - { - wait (500); - } - else - { - const char* p = (const char*) pendingCopy.getData(); + if (len == 0) + { + wait (500); + } + else + { + const char* p = (const char*) pendingCopy.getData(); - while (len > 0) - { - const double time = *(const double*) p; - const int messageLen = *(const int*) (p + 8); + while (len > 0) + { + const double time = *(const double*) p; + const int messageLen = *(const int*) (p + 8); - const MidiMessage message ((const uint8*) (p + 12), messageLen, time); + const MidiMessage message ((const uint8*) (p + 12), messageLen, time); - callback->handleIncomingMidiMessage (input, message); + callback->handleIncomingMidiMessage (input, message); - p += 12 + messageLen; - len -= 12 + messageLen; - } - } - } - } + p += 12 + messageLen; + len -= 12 + messageLen; + } + } + } + } - void start() throw() - { - jassert (hIn != 0); - if (hIn != 0 && ! isStarted) - { - stop(); + void start() throw() + { + jassert (hIn != 0); + if (hIn != 0 && ! isStarted) + { + stop(); - activeMidiThreads.addIfNotAlreadyThere (this); + activeMidiThreads.addIfNotAlreadyThere (this); - int i; - for (i = 0; i < numInHeaders; ++i) - writeBlock (i); + int i; + for (i = 0; i < numInHeaders; ++i) + writeBlock (i); - startTime = Time::getMillisecondCounter(); - MMRESULT res = midiInStart (hIn); + startTime = Time::getMillisecondCounter(); + MMRESULT res = midiInStart (hIn); - jassert (res == MMSYSERR_NOERROR); + jassert (res == MMSYSERR_NOERROR); - if (res == MMSYSERR_NOERROR) - { - isStarted = true; - pendingLength = 0; - startThread (6); - } - } - } + if (res == MMSYSERR_NOERROR) + { + isStarted = true; + pendingLength = 0; + startThread (6); + } + } + } - void stop() throw() - { - if (isStarted) - { - stopThread (5000); + void stop() throw() + { + if (isStarted) + { + stopThread (5000); - midiInReset (hIn); - midiInStop (hIn); + midiInReset (hIn); + midiInStop (hIn); - activeMidiThreads.removeValue (this); + activeMidiThreads.removeValue (this); - lock.enter(); - lock.exit(); + lock.enter(); + lock.exit(); - for (int i = numInHeaders; --i >= 0;) - { - if ((hdr[i].dwFlags & WHDR_DONE) != 0) - { - int c = 10; - while (--c >= 0 && midiInUnprepareHeader (hIn, &hdr[i], sizeof (MIDIHDR)) == MIDIERR_STILLPLAYING) - Sleep (20); + for (int i = numInHeaders; --i >= 0;) + { + if ((hdr[i].dwFlags & WHDR_DONE) != 0) + { + int c = 10; + while (--c >= 0 && midiInUnprepareHeader (hIn, &hdr[i], sizeof (MIDIHDR)) == MIDIERR_STILLPLAYING) + Sleep (20); - jassert (c >= 0); - } - } + jassert (c >= 0); + } + } - isStarted = false; - pendingLength = 0; - } - } + isStarted = false; + pendingLength = 0; + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - HMIDIIN hIn; + HMIDIIN hIn; private: - MidiInput* input; - MidiInputCallback* callback; - bool isStarted; - uint32 startTime; - CriticalSection lock; + MidiInput* input; + MidiInputCallback* callback; + bool isStarted; + uint32 startTime; + CriticalSection lock; - MIDIHDR hdr [numInHeaders]; - char inData [numInHeaders] [inBufferSize]; + MIDIHDR hdr [numInHeaders]; + char inData [numInHeaders] [inBufferSize]; - int pendingLength; - char pending [midiBufferSize]; + int pendingLength; + char pending [midiBufferSize]; - double timeStampToTime (uint32 timeStamp) throw() - { - timeStamp += startTime; + double timeStampToTime (uint32 timeStamp) throw() + { + timeStamp += startTime; - const uint32 now = Time::getMillisecondCounter(); - if (timeStamp > now) - { - if (timeStamp > now + 2) - --startTime; + const uint32 now = Time::getMillisecondCounter(); + if (timeStamp > now) + { + if (timeStamp > now + 2) + --startTime; - timeStamp = now; - } + timeStamp = now; + } - return 0.001 * timeStamp; - } + return 0.001 * timeStamp; + } - MidiInThread (const MidiInThread&); - const MidiInThread& operator= (const MidiInThread&); + MidiInThread (const MidiInThread&); + const MidiInThread& operator= (const MidiInThread&); }; static void CALLBACK midiInCallback (HMIDIIN, - UINT uMsg, - DWORD_PTR dwInstance, - DWORD_PTR midiMessage, - DWORD_PTR timeStamp) + UINT uMsg, + DWORD_PTR dwInstance, + DWORD_PTR midiMessage, + DWORD_PTR timeStamp) { - MidiInThread* const thread = (MidiInThread*) dwInstance; + MidiInThread* const thread = (MidiInThread*) dwInstance; - if (thread != 0 && activeMidiThreads.contains (thread)) - { - if (uMsg == MIM_DATA) - thread->handle ((uint32) midiMessage, (uint32) timeStamp); - else if (uMsg == MIM_LONGDATA) - thread->handleSysEx ((MIDIHDR*) midiMessage, (uint32) timeStamp); - } + if (thread != 0 && activeMidiThreads.contains (thread)) + { + if (uMsg == MIM_DATA) + thread->handle ((uint32) midiMessage, (uint32) timeStamp); + else if (uMsg == MIM_LONGDATA) + thread->handleSysEx ((MIDIHDR*) midiMessage, (uint32) timeStamp); + } } const StringArray MidiInput::getDevices() { - StringArray s; - const int num = midiInGetNumDevs(); + StringArray s; + const int num = midiInGetNumDevs(); - for (int i = 0; i < num; ++i) - { - MIDIINCAPS mc; - zerostruct (mc); + for (int i = 0; i < num; ++i) + { + MIDIINCAPS mc; + zerostruct (mc); - if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) - s.add (String (mc.szPname, sizeof (mc.szPname))); - } + if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) + s.add (String (mc.szPname, sizeof (mc.szPname))); + } - return s; + return s; } int MidiInput::getDefaultDeviceIndex() { - return 0; + return 0; } MidiInput* MidiInput::openDevice (const int index, MidiInputCallback* const callback) { - if (callback == 0) - return 0; + if (callback == 0) + return 0; - UINT deviceId = MIDI_MAPPER; - int n = 0; - String name; + UINT deviceId = MIDI_MAPPER; + int n = 0; + String name; - const int num = midiInGetNumDevs(); + const int num = midiInGetNumDevs(); - for (int i = 0; i < num; ++i) - { - MIDIINCAPS mc; - zerostruct (mc); + for (int i = 0; i < num; ++i) + { + MIDIINCAPS mc; + zerostruct (mc); - if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) - { - if (index == n) - { - deviceId = i; - name = String (mc.szPname, sizeof (mc.szPname)); - break; - } + if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) + { + if (index == n) + { + deviceId = i; + name = String (mc.szPname, sizeof (mc.szPname)); + break; + } - ++n; - } - } + ++n; + } + } - ScopedPointer in (new MidiInput (name)); - ScopedPointer thread (new MidiInThread (in, callback)); + ScopedPointer in (new MidiInput (name)); + ScopedPointer thread (new MidiInThread (in, callback)); - HMIDIIN h; - HRESULT err = midiInOpen (&h, deviceId, - (DWORD_PTR) &midiInCallback, - (DWORD_PTR) (MidiInThread*) thread, - CALLBACK_FUNCTION); + HMIDIIN h; + HRESULT err = midiInOpen (&h, deviceId, + (DWORD_PTR) &midiInCallback, + (DWORD_PTR) (MidiInThread*) thread, + CALLBACK_FUNCTION); - if (err == MMSYSERR_NOERROR) - { - thread->hIn = h; - in->internal = (void*) thread.release(); - return in.release(); - } + if (err == MMSYSERR_NOERROR) + { + thread->hIn = h; + in->internal = (void*) thread.release(); + return in.release(); + } - return 0; + return 0; } MidiInput::MidiInput (const String& name_) - : name (name_), - internal (0) + : name (name_), + internal (0) { } MidiInput::~MidiInput() { - if (internal != 0) - { - MidiInThread* const thread = (MidiInThread*) internal; - delete thread; - } + if (internal != 0) + { + MidiInThread* const thread = (MidiInThread*) internal; + delete thread; + } } void MidiInput::start() { - ((MidiInThread*) internal)->start(); + ((MidiInThread*) internal)->start(); } void MidiInput::stop() { - ((MidiInThread*) internal)->stop(); + ((MidiInThread*) internal)->stop(); } struct MidiOutHandle { - int refCount; - UINT deviceId; - HMIDIOUT handle; + int refCount; + UINT deviceId; + HMIDIOUT handle; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; -static VoidArray handles (4); +static Array midiOutputHandles; const StringArray MidiOutput::getDevices() { - StringArray s; - const int num = midiOutGetNumDevs(); + StringArray s; + const int num = midiOutGetNumDevs(); - for (int i = 0; i < num; ++i) - { - MIDIOUTCAPS mc; - zerostruct (mc); + for (int i = 0; i < num; ++i) + { + MIDIOUTCAPS mc; + zerostruct (mc); - if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) - s.add (String (mc.szPname, sizeof (mc.szPname))); - } + if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) + s.add (String (mc.szPname, sizeof (mc.szPname))); + } - return s; + return s; } int MidiOutput::getDefaultDeviceIndex() { - const int num = midiOutGetNumDevs(); - int n = 0; + const int num = midiOutGetNumDevs(); + int n = 0; - for (int i = 0; i < num; ++i) - { - MIDIOUTCAPS mc; - zerostruct (mc); + for (int i = 0; i < num; ++i) + { + MIDIOUTCAPS mc; + zerostruct (mc); - if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) - { - if ((mc.wTechnology & MOD_MAPPER) != 0) - return n; + if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) + { + if ((mc.wTechnology & MOD_MAPPER) != 0) + return n; - ++n; - } - } + ++n; + } + } - return 0; + return 0; } MidiOutput* MidiOutput::openDevice (int index) { - UINT deviceId = MIDI_MAPPER; - const int num = midiOutGetNumDevs(); - int i, n = 0; + UINT deviceId = MIDI_MAPPER; + const int num = midiOutGetNumDevs(); + int i, n = 0; - for (i = 0; i < num; ++i) - { - MIDIOUTCAPS mc; - zerostruct (mc); + for (i = 0; i < num; ++i) + { + MIDIOUTCAPS mc; + zerostruct (mc); - if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) - { - // use the microsoft sw synth as a default - best not to allow deviceId - // to be MIDI_MAPPER, or else device sharing breaks - if (String (mc.szPname, sizeof (mc.szPname)).containsIgnoreCase (T("microsoft"))) - deviceId = i; + if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR) + { + // use the microsoft sw synth as a default - best not to allow deviceId + // to be MIDI_MAPPER, or else device sharing breaks + if (String (mc.szPname, sizeof (mc.szPname)).containsIgnoreCase (T("microsoft"))) + deviceId = i; - if (index == n) - { - deviceId = i; - break; - } + if (index == n) + { + deviceId = i; + break; + } - ++n; - } - } + ++n; + } + } - for (i = handles.size(); --i >= 0;) - { - MidiOutHandle* const han = (MidiOutHandle*) handles.getUnchecked(i); + for (i = midiOutputHandles.size(); --i >= 0;) + { + MidiOutHandle* const han = midiOutputHandles.getUnchecked(i); - if (han != 0 && han->deviceId == deviceId) - { - han->refCount++; + if (han != 0 && han->deviceId == deviceId) + { + han->refCount++; - MidiOutput* const out = new MidiOutput(); - out->internal = (void*) han; - return out; - } - } + MidiOutput* const out = new MidiOutput(); + out->internal = (void*) han; + return out; + } + } - for (i = 4; --i >= 0;) - { - HMIDIOUT h = 0; - MMRESULT res = midiOutOpen (&h, deviceId, 0, 0, CALLBACK_NULL); + for (i = 4; --i >= 0;) + { + HMIDIOUT h = 0; + MMRESULT res = midiOutOpen (&h, deviceId, 0, 0, CALLBACK_NULL); - if (res == MMSYSERR_NOERROR) - { - MidiOutHandle* const han = new MidiOutHandle(); - han->deviceId = deviceId; - han->refCount = 1; - han->handle = h; - handles.add (han); + if (res == MMSYSERR_NOERROR) + { + MidiOutHandle* const han = new MidiOutHandle(); + han->deviceId = deviceId; + han->refCount = 1; + han->handle = h; + midiOutputHandles.add (han); - MidiOutput* const out = new MidiOutput(); - out->internal = (void*) han; - return out; - } - else if (res == MMSYSERR_ALLOCATED) - { - Sleep (100); - } - else - { - break; - } - } + MidiOutput* const out = new MidiOutput(); + out->internal = (void*) han; + return out; + } + else if (res == MMSYSERR_ALLOCATED) + { + Sleep (100); + } + else + { + break; + } + } - return 0; + return 0; } MidiOutput::~MidiOutput() { - MidiOutHandle* const h = (MidiOutHandle*) internal; + MidiOutHandle* const h = (MidiOutHandle*) internal; - if (handles.contains ((void*) h) && --(h->refCount) == 0) - { - midiOutClose (h->handle); - handles.removeValue ((void*) h); - delete h; - } + if (midiOutputHandles.contains (h) && --(h->refCount) == 0) + { + midiOutClose (h->handle); + midiOutputHandles.removeValue (h); + delete h; + } } void MidiOutput::reset() { - const MidiOutHandle* const h = (MidiOutHandle*) internal; - midiOutReset (h->handle); + const MidiOutHandle* const h = (MidiOutHandle*) internal; + midiOutReset (h->handle); } bool MidiOutput::getVolume (float& leftVol, - float& rightVol) + float& rightVol) { - const MidiOutHandle* const handle = (const MidiOutHandle*) internal; + const MidiOutHandle* const handle = (const MidiOutHandle*) internal; - DWORD n; - if (midiOutGetVolume (handle->handle, &n) == MMSYSERR_NOERROR) - { - const unsigned short* const nn = (const unsigned short*) &n; - rightVol = nn[0] / (float) 0xffff; - leftVol = nn[1] / (float) 0xffff; - return true; - } - else - { - rightVol = leftVol = 1.0f; - return false; - } + DWORD n; + if (midiOutGetVolume (handle->handle, &n) == MMSYSERR_NOERROR) + { + const unsigned short* const nn = (const unsigned short*) &n; + rightVol = nn[0] / (float) 0xffff; + leftVol = nn[1] / (float) 0xffff; + return true; + } + else + { + rightVol = leftVol = 1.0f; + return false; + } } void MidiOutput::setVolume (float leftVol, - float rightVol) + float rightVol) { - const MidiOutHandle* const handle = (MidiOutHandle*) internal; + const MidiOutHandle* const handle = (MidiOutHandle*) internal; - DWORD n; - unsigned short* const nn = (unsigned short*) &n; - nn[0] = (unsigned short) jlimit (0, 0xffff, (int)(rightVol * 0xffff)); - nn[1] = (unsigned short) jlimit (0, 0xffff, (int)(leftVol * 0xffff)); - midiOutSetVolume (handle->handle, n); + DWORD n; + unsigned short* const nn = (unsigned short*) &n; + nn[0] = (unsigned short) jlimit (0, 0xffff, (int)(rightVol * 0xffff)); + nn[1] = (unsigned short) jlimit (0, 0xffff, (int)(leftVol * 0xffff)); + midiOutSetVolume (handle->handle, n); } void MidiOutput::sendMessageNow (const MidiMessage& message) { - const MidiOutHandle* const handle = (const MidiOutHandle*) internal; + const MidiOutHandle* const handle = (const MidiOutHandle*) internal; - if (message.getRawDataSize() > 3 - || message.isSysEx()) - { - MIDIHDR h; - zerostruct (h); + if (message.getRawDataSize() > 3 + || message.isSysEx()) + { + MIDIHDR h; + zerostruct (h); - h.lpData = (char*) message.getRawData(); - h.dwBufferLength = message.getRawDataSize(); - h.dwBytesRecorded = message.getRawDataSize(); + h.lpData = (char*) message.getRawData(); + h.dwBufferLength = message.getRawDataSize(); + h.dwBytesRecorded = message.getRawDataSize(); - if (midiOutPrepareHeader (handle->handle, &h, sizeof (MIDIHDR)) == MMSYSERR_NOERROR) - { - MMRESULT res = midiOutLongMsg (handle->handle, &h, sizeof (MIDIHDR)); + if (midiOutPrepareHeader (handle->handle, &h, sizeof (MIDIHDR)) == MMSYSERR_NOERROR) + { + MMRESULT res = midiOutLongMsg (handle->handle, &h, sizeof (MIDIHDR)); - if (res == MMSYSERR_NOERROR) - { - while ((h.dwFlags & MHDR_DONE) == 0) - Sleep (1); + if (res == MMSYSERR_NOERROR) + { + while ((h.dwFlags & MHDR_DONE) == 0) + Sleep (1); - int count = 500; // 1 sec timeout + int count = 500; // 1 sec timeout - while (--count >= 0) - { - res = midiOutUnprepareHeader (handle->handle, &h, sizeof (MIDIHDR)); + while (--count >= 0) + { + res = midiOutUnprepareHeader (handle->handle, &h, sizeof (MIDIHDR)); - if (res == MIDIERR_STILLPLAYING) - Sleep (2); - else - break; - } - } - } - } - else - { - midiOutShortMsg (handle->handle, - *(unsigned int*) message.getRawData()); - } + if (res == MIDIERR_STILLPLAYING) + Sleep (2); + else + break; + } + } + } + } + else + { + midiOutShortMsg (handle->handle, + *(unsigned int*) message.getRawData()); + } } #endif @@ -245257,24 +222992,24 @@ void MidiOutput::sendMessageNow (const MidiMessage& message) #ifdef ASIO_DEBUGGING static void logError (const String& context, long error) { - String err ("unknown error"); + String err ("unknown error"); - if (error == ASE_NotPresent) - err = "Not Present"; - else if (error == ASE_HWMalfunction) - err = "Hardware Malfunction"; - else if (error == ASE_InvalidParameter) - err = "Invalid Parameter"; - else if (error == ASE_InvalidMode) - err = "Invalid Mode"; - else if (error == ASE_SPNotAdvancing) - err = "Sample position not advancing"; - else if (error == ASE_NoClock) - err = "No Clock"; - else if (error == ASE_NoMemory) - err = "Out of memory"; + if (error == ASE_NotPresent) + err = "Not Present"; + else if (error == ASE_HWMalfunction) + err = "Hardware Malfunction"; + else if (error == ASE_InvalidParameter) + err = "Invalid Parameter"; + else if (error == ASE_InvalidMode) + err = "Invalid Mode"; + else if (error == ASE_SPNotAdvancing) + err = "Sample position not advancing"; + else if (error == ASE_NoClock) + err = "No Clock"; + else if (error == ASE_NoMemory) + err = "Out of memory"; - log (T("!!error: ") + context + T(" - ") + err); + log (T("!!error: ") + context + T(" - ") + err); } #else #define logError(a, b) {} @@ -245286,1877 +223021,1876 @@ static ASIOAudioIODevice* volatile currentASIODev[3] = { 0, 0, 0 }; static const int maxASIOChannels = 160; class JUCE_API ASIOAudioIODevice : public AudioIODevice, - private Timer + private Timer { public: - Component ourWindow; - - ASIOAudioIODevice (const String& name_, const CLSID classId_, const int slotNumber, - const String& optionalDllForDirectLoading_) - : AudioIODevice (name_, T("ASIO")), - asioObject (0), - classId (classId_), - optionalDllForDirectLoading (optionalDllForDirectLoading_), - currentBitDepth (16), - currentSampleRate (0), - isOpen_ (false), - isStarted (false), - postOutput (true), - insideControlPanelModalLoop (false), - shouldUsePreferredSize (false) - { - name = name_; - - ourWindow.addToDesktop (0); - windowHandle = ourWindow.getWindowHandle(); - - jassert (currentASIODev [slotNumber] == 0); - currentASIODev [slotNumber] = this; - - openDevice(); - } - - ~ASIOAudioIODevice() - { - for (int i = 0; i < numElementsInArray (currentASIODev); ++i) - if (currentASIODev[i] == this) - currentASIODev[i] = 0; - - close(); - log ("ASIO - exiting"); - removeCurrentDriver(); - } - - void updateSampleRates() - { - // find a list of sample rates.. - const double possibleSampleRates[] = { 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 }; - sampleRates.clear(); - - if (asioObject != 0) - { - for (int index = 0; index < numElementsInArray (possibleSampleRates); ++index) - { - const long err = asioObject->canSampleRate (possibleSampleRates[index]); - - if (err == 0) - { - sampleRates.add ((int) possibleSampleRates[index]); - log (T("rate: ") + String ((int) possibleSampleRates[index])); - } - else if (err != ASE_NoClock) - { - logError (T("CanSampleRate"), err); - } - } - - if (sampleRates.size() == 0) - { - double cr = 0; - const long err = asioObject->getSampleRate (&cr); - log (T("No sample rates supported - current rate: ") + String ((int) cr)); - - if (err == 0) - sampleRates.add ((int) cr); - } - } - } - - const StringArray getOutputChannelNames() - { - return outputChannelNames; - } - - const StringArray getInputChannelNames() - { - return inputChannelNames; - } - - int getNumSampleRates() - { - return sampleRates.size(); - } - - double getSampleRate (int index) - { - return sampleRates [index]; - } - - int getNumBufferSizesAvailable() - { - return bufferSizes.size(); - } - - int getBufferSizeSamples (int index) - { - return bufferSizes [index]; - } - - int getDefaultBufferSize() - { - return preferredSize; - } - - const String open (const BitArray& inputChannels, - const BitArray& outputChannels, - double sr, - int bufferSizeSamples) - { - close(); - currentCallback = 0; - - if (bufferSizeSamples <= 0) - shouldUsePreferredSize = true; - - if (asioObject == 0 || ! isASIOOpen) - { - log ("Warning: device not open"); - const String err (openDevice()); - - if (asioObject == 0 || ! isASIOOpen) - return err; - } - - isStarted = false; - bufferIndex = -1; - long err = 0; - - long newPreferredSize = 0; - - // if the preferred size has just changed, assume it's a control panel thing and use it as the new value. - minSize = 0; - maxSize = 0; - newPreferredSize = 0; - granularity = 0; - - if (asioObject->getBufferSize (&minSize, &maxSize, &newPreferredSize, &granularity) == 0) - { - if (preferredSize != 0 && newPreferredSize != 0 && newPreferredSize != preferredSize) - shouldUsePreferredSize = true; - - preferredSize = newPreferredSize; - } - - // unfortunate workaround for certain manufacturers whose drivers crash horribly if you make - // dynamic changes to the buffer size... - shouldUsePreferredSize = shouldUsePreferredSize - || getName().containsIgnoreCase (T("Digidesign")); - - if (shouldUsePreferredSize) - { - log ("Using preferred size for buffer.."); - - if ((err = asioObject->getBufferSize (&minSize, &maxSize, &preferredSize, &granularity)) == 0) - { - bufferSizeSamples = preferredSize; - } - else - { - bufferSizeSamples = 1024; - logError ("GetBufferSize1", err); - } - - shouldUsePreferredSize = false; - } - - int sampleRate = roundDoubleToInt (sr); - currentSampleRate = sampleRate; - currentBlockSizeSamples = bufferSizeSamples; - currentChansOut.clear(); - currentChansIn.clear(); - zeromem (inBuffers, sizeof (inBuffers)); - zeromem (outBuffers, sizeof (outBuffers)); - - updateSampleRates(); - - if (sampleRate == 0 || (sampleRates.size() > 0 && ! sampleRates.contains (sampleRate))) - sampleRate = sampleRates[0]; - - jassert (sampleRate != 0); - if (sampleRate == 0) - sampleRate = 44100; - - long numSources = 32; - ASIOClockSource clocks[32]; - zeromem (clocks, sizeof (clocks)); - asioObject->getClockSources (clocks, &numSources); - bool isSourceSet = false; - - // careful not to remove this loop because it does more than just logging! - int i; - for (i = 0; i < numSources; ++i) - { - String s ("clock: "); - s += clocks[i].name; - - if (clocks[i].isCurrentSource) - { - isSourceSet = true; - s << " (cur)"; - } - - log (s); - } - - if (numSources > 1 && ! isSourceSet) - { - log ("setting clock source"); - asioObject->setClockSource (clocks[0].index); - Thread::sleep (20); - } - else - { - if (numSources == 0) - { - log ("ASIO - no clock sources!"); - } - } - - double cr = 0; - err = asioObject->getSampleRate (&cr); - if (err == 0) - { - currentSampleRate = cr; - } - else - { - logError ("GetSampleRate", err); - currentSampleRate = 0; - } - - error = String::empty; - needToReset = false; - isReSync = false; - err = 0; - bool buffersCreated = false; - - if (currentSampleRate != sampleRate) - { - log (T("ASIO samplerate: ") + String (currentSampleRate) + T(" to ") + String (sampleRate)); - err = asioObject->setSampleRate (sampleRate); - - if (err == ASE_NoClock && numSources > 0) - { - log ("trying to set a clock source.."); - Thread::sleep (10); - err = asioObject->setClockSource (clocks[0].index); - if (err != 0) - { - logError ("SetClock", err); - } - - Thread::sleep (10); - err = asioObject->setSampleRate (sampleRate); - } - } - - if (err == 0) - { - currentSampleRate = sampleRate; - - if (needToReset) - { - if (isReSync) - { - log ("Resync request"); - } - - log ("! Resetting ASIO after sample rate change"); - removeCurrentDriver(); - - loadDriver(); - const String error (initDriver()); - - if (error.isNotEmpty()) - { - log (T("ASIOInit: ") + error); - } - - needToReset = false; - isReSync = false; - } - - numActiveInputChans = 0; - numActiveOutputChans = 0; - - ASIOBufferInfo* info = bufferInfos; - int i; - for (i = 0; i < totalNumInputChans; ++i) - { - if (inputChannels[i]) - { - currentChansIn.setBit (i); - info->isInput = 1; - info->channelNum = i; - info->buffers[0] = info->buffers[1] = 0; - ++info; - ++numActiveInputChans; - } - } - - for (i = 0; i < totalNumOutputChans; ++i) - { - if (outputChannels[i]) - { - currentChansOut.setBit (i); - info->isInput = 0; - info->channelNum = i; - info->buffers[0] = info->buffers[1] = 0; - ++info; - ++numActiveOutputChans; - } - } - - const int totalBuffers = numActiveInputChans + numActiveOutputChans; - - callbacks.sampleRateDidChange = &sampleRateChangedCallback; - - if (currentASIODev[0] == this) - { - callbacks.bufferSwitch = &bufferSwitchCallback0; - callbacks.asioMessage = &asioMessagesCallback0; - callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0; - } - else if (currentASIODev[1] == this) - { - callbacks.bufferSwitch = &bufferSwitchCallback1; - callbacks.asioMessage = &asioMessagesCallback1; - callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1; - } - else if (currentASIODev[2] == this) - { - callbacks.bufferSwitch = &bufferSwitchCallback2; - callbacks.asioMessage = &asioMessagesCallback2; - callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2; - } - else - { - jassertfalse - } - - log ("disposing buffers"); - err = asioObject->disposeBuffers(); - - log (T("creating buffers: ") + String (totalBuffers) + T(", ") + String (currentBlockSizeSamples)); - err = asioObject->createBuffers (bufferInfos, - totalBuffers, - currentBlockSizeSamples, - &callbacks); - - if (err != 0) - { - currentBlockSizeSamples = preferredSize; - logError ("create buffers 2", err); - - asioObject->disposeBuffers(); - err = asioObject->createBuffers (bufferInfos, - totalBuffers, - currentBlockSizeSamples, - &callbacks); - } - - if (err == 0) - { - buffersCreated = true; - - tempBuffer.calloc (totalBuffers * currentBlockSizeSamples + 32); - - int n = 0; - Array types; - currentBitDepth = 16; - - for (i = 0; i < jmin (totalNumInputChans, maxASIOChannels); ++i) - { - if (inputChannels[i]) - { - inBuffers[n] = tempBuffer + (currentBlockSizeSamples * n); - - ASIOChannelInfo channelInfo; - zerostruct (channelInfo); - - channelInfo.channel = i; - channelInfo.isInput = 1; - asioObject->getChannelInfo (&channelInfo); - - types.addIfNotAlreadyThere (channelInfo.type); - typeToFormatParameters (channelInfo.type, - inputChannelBitDepths[n], - inputChannelBytesPerSample[n], - inputChannelIsFloat[n], - inputChannelLittleEndian[n]); - - currentBitDepth = jmax (currentBitDepth, inputChannelBitDepths[n]); - - ++n; - } - } - - jassert (numActiveInputChans == n); - n = 0; - - for (i = 0; i < jmin (totalNumOutputChans, maxASIOChannels); ++i) - { - if (outputChannels[i]) - { - outBuffers[n] = tempBuffer + (currentBlockSizeSamples * (numActiveInputChans + n)); - - ASIOChannelInfo channelInfo; - zerostruct (channelInfo); - - channelInfo.channel = i; - channelInfo.isInput = 0; - asioObject->getChannelInfo (&channelInfo); - - types.addIfNotAlreadyThere (channelInfo.type); - typeToFormatParameters (channelInfo.type, - outputChannelBitDepths[n], - outputChannelBytesPerSample[n], - outputChannelIsFloat[n], - outputChannelLittleEndian[n]); - - currentBitDepth = jmax (currentBitDepth, outputChannelBitDepths[n]); - - ++n; - } - } - - jassert (numActiveOutputChans == n); - - for (i = types.size(); --i >= 0;) - { - log (T("channel format: ") + String (types[i])); - } - - jassert (n <= totalBuffers); - - for (i = 0; i < numActiveOutputChans; ++i) - { - const int size = currentBlockSizeSamples * (outputChannelBitDepths[i] >> 3); - - if (bufferInfos [numActiveInputChans + i].buffers[0] == 0 - || bufferInfos [numActiveInputChans + i].buffers[1] == 0) - { - log ("!! Null buffers"); - } - else - { - zeromem (bufferInfos[numActiveInputChans + i].buffers[0], size); - zeromem (bufferInfos[numActiveInputChans + i].buffers[1], size); - } - } - - inputLatency = outputLatency = 0; - - if (asioObject->getLatencies (&inputLatency, &outputLatency) != 0) - { - log ("ASIO - no latencies"); - } - else - { - log (T("ASIO latencies: ") - + String ((int) outputLatency) - + T(", ") - + String ((int) inputLatency)); - } - - isOpen_ = true; - - log ("starting ASIO"); - calledback = false; - err = asioObject->start(); - - if (err != 0) - { - isOpen_ = false; - log ("ASIO - stop on failure"); - Thread::sleep (10); - asioObject->stop(); - error = "Can't start device"; - Thread::sleep (10); - } - else - { - int count = 300; - while (--count > 0 && ! calledback) - Thread::sleep (10); - - isStarted = true; - - if (! calledback) - { - error = "Device didn't start correctly"; - log ("ASIO didn't callback - stopping.."); - asioObject->stop(); - } - } - } - else - { - error = "Can't create i/o buffers"; - } - } - else - { - error = "Can't set sample rate: "; - error << sampleRate; - } - - if (error.isNotEmpty()) - { - logError (error, err); - - if (asioObject != 0 && buffersCreated) - asioObject->disposeBuffers(); - - Thread::sleep (20); - isStarted = false; - isOpen_ = false; - close(); - } - - needToReset = false; - isReSync = false; - - return error; - } - - void close() - { - error = String::empty; - stopTimer(); - stop(); - - if (isASIOOpen && isOpen_) - { - const ScopedLock sl (callbackLock); - - isOpen_ = false; - isStarted = false; - needToReset = false; - isReSync = false; - - log ("ASIO - stopping"); - - if (asioObject != 0) - { - Thread::sleep (20); - asioObject->stop(); - Thread::sleep (10); - asioObject->disposeBuffers(); - } - - Thread::sleep (10); - } - } - - bool isOpen() - { - return isOpen_ || insideControlPanelModalLoop; - } - - int getCurrentBufferSizeSamples() - { - return currentBlockSizeSamples; - } - - double getCurrentSampleRate() - { - return currentSampleRate; - } - - const BitArray getActiveOutputChannels() const - { - return currentChansOut; - } - - const BitArray getActiveInputChannels() const - { - return currentChansIn; - } - - int getCurrentBitDepth() - { - return currentBitDepth; - } - - int getOutputLatencyInSamples() - { - return outputLatency + currentBlockSizeSamples / 4; - } - - int getInputLatencyInSamples() - { - return inputLatency + currentBlockSizeSamples / 4; - } - - void start (AudioIODeviceCallback* callback) - { - if (callback != 0) - { - callback->audioDeviceAboutToStart (this); - - const ScopedLock sl (callbackLock); - currentCallback = callback; - } - } - - void stop() - { - AudioIODeviceCallback* const lastCallback = currentCallback; - - { - const ScopedLock sl (callbackLock); - currentCallback = 0; - } - - if (lastCallback != 0) - lastCallback->audioDeviceStopped(); - } - - bool isPlaying() - { - return isASIOOpen && (currentCallback != 0); - } - - const String getLastError() - { - return error; - } - - bool hasControlPanel() const - { - return true; - } - - bool showControlPanel() - { - log ("ASIO - showing control panel"); - - Component modalWindow (String::empty); - modalWindow.setOpaque (true); - modalWindow.addToDesktop (0); - modalWindow.enterModalState(); - bool done = false; - - JUCE_TRY - { - // are there are devices that need to be closed before showing their control panel? - // close(); - insideControlPanelModalLoop = true; - - const uint32 started = Time::getMillisecondCounter(); - - if (asioObject != 0) - { - asioObject->controlPanel(); - - const int spent = (int) Time::getMillisecondCounter() - (int) started; - - log (T("spent: ") + String (spent)); - - if (spent > 300) - { - shouldUsePreferredSize = true; - done = true; - } - } - } - JUCE_CATCH_ALL - - insideControlPanelModalLoop = false; - return done; - } - - void resetRequest() throw() - { - needToReset = true; - } - - void resyncRequest() throw() - { - needToReset = true; - isReSync = true; - } - - void timerCallback() - { - if (! insideControlPanelModalLoop) - { - stopTimer(); - - // used to cause a reset - log ("! ASIO restart request!"); - - if (isOpen_) - { - AudioIODeviceCallback* const oldCallback = currentCallback; - - close(); - open (BitArray (currentChansIn), BitArray (currentChansOut), - currentSampleRate, currentBlockSizeSamples); - - if (oldCallback != 0) - start (oldCallback); - } - } - else - { - startTimer (100); - } - } - - juce_UseDebuggingNewOperator + Component ourWindow; + + ASIOAudioIODevice (const String& name_, const CLSID classId_, const int slotNumber, + const String& optionalDllForDirectLoading_) + : AudioIODevice (name_, T("ASIO")), + asioObject (0), + classId (classId_), + optionalDllForDirectLoading (optionalDllForDirectLoading_), + currentBitDepth (16), + currentSampleRate (0), + isOpen_ (false), + isStarted (false), + postOutput (true), + insideControlPanelModalLoop (false), + shouldUsePreferredSize (false) + { + name = name_; + + ourWindow.addToDesktop (0); + windowHandle = ourWindow.getWindowHandle(); + + jassert (currentASIODev [slotNumber] == 0); + currentASIODev [slotNumber] = this; + + openDevice(); + } + + ~ASIOAudioIODevice() + { + for (int i = 0; i < numElementsInArray (currentASIODev); ++i) + if (currentASIODev[i] == this) + currentASIODev[i] = 0; + + close(); + log ("ASIO - exiting"); + removeCurrentDriver(); + } + + void updateSampleRates() + { + // find a list of sample rates.. + const double possibleSampleRates[] = { 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 }; + sampleRates.clear(); + + if (asioObject != 0) + { + for (int index = 0; index < numElementsInArray (possibleSampleRates); ++index) + { + const long err = asioObject->canSampleRate (possibleSampleRates[index]); + + if (err == 0) + { + sampleRates.add ((int) possibleSampleRates[index]); + log (T("rate: ") + String ((int) possibleSampleRates[index])); + } + else if (err != ASE_NoClock) + { + logError (T("CanSampleRate"), err); + } + } + + if (sampleRates.size() == 0) + { + double cr = 0; + const long err = asioObject->getSampleRate (&cr); + log (T("No sample rates supported - current rate: ") + String ((int) cr)); + + if (err == 0) + sampleRates.add ((int) cr); + } + } + } + + const StringArray getOutputChannelNames() + { + return outputChannelNames; + } + + const StringArray getInputChannelNames() + { + return inputChannelNames; + } + + int getNumSampleRates() + { + return sampleRates.size(); + } + + double getSampleRate (int index) + { + return sampleRates [index]; + } + + int getNumBufferSizesAvailable() + { + return bufferSizes.size(); + } + + int getBufferSizeSamples (int index) + { + return bufferSizes [index]; + } + + int getDefaultBufferSize() + { + return preferredSize; + } + + const String open (const BitArray& inputChannels, + const BitArray& outputChannels, + double sr, + int bufferSizeSamples) + { + close(); + currentCallback = 0; + + if (bufferSizeSamples <= 0) + shouldUsePreferredSize = true; + + if (asioObject == 0 || ! isASIOOpen) + { + log ("Warning: device not open"); + const String err (openDevice()); + + if (asioObject == 0 || ! isASIOOpen) + return err; + } + + isStarted = false; + bufferIndex = -1; + long err = 0; + + long newPreferredSize = 0; + + // if the preferred size has just changed, assume it's a control panel thing and use it as the new value. + minSize = 0; + maxSize = 0; + newPreferredSize = 0; + granularity = 0; + + if (asioObject->getBufferSize (&minSize, &maxSize, &newPreferredSize, &granularity) == 0) + { + if (preferredSize != 0 && newPreferredSize != 0 && newPreferredSize != preferredSize) + shouldUsePreferredSize = true; + + preferredSize = newPreferredSize; + } + + // unfortunate workaround for certain manufacturers whose drivers crash horribly if you make + // dynamic changes to the buffer size... + shouldUsePreferredSize = shouldUsePreferredSize + || getName().containsIgnoreCase (T("Digidesign")); + + if (shouldUsePreferredSize) + { + log ("Using preferred size for buffer.."); + + if ((err = asioObject->getBufferSize (&minSize, &maxSize, &preferredSize, &granularity)) == 0) + { + bufferSizeSamples = preferredSize; + } + else + { + bufferSizeSamples = 1024; + logError ("GetBufferSize1", err); + } + + shouldUsePreferredSize = false; + } + + int sampleRate = roundDoubleToInt (sr); + currentSampleRate = sampleRate; + currentBlockSizeSamples = bufferSizeSamples; + currentChansOut.clear(); + currentChansIn.clear(); + zeromem (inBuffers, sizeof (inBuffers)); + zeromem (outBuffers, sizeof (outBuffers)); + + updateSampleRates(); + + if (sampleRate == 0 || (sampleRates.size() > 0 && ! sampleRates.contains (sampleRate))) + sampleRate = sampleRates[0]; + + jassert (sampleRate != 0); + if (sampleRate == 0) + sampleRate = 44100; + + long numSources = 32; + ASIOClockSource clocks[32]; + zeromem (clocks, sizeof (clocks)); + asioObject->getClockSources (clocks, &numSources); + bool isSourceSet = false; + + // careful not to remove this loop because it does more than just logging! + int i; + for (i = 0; i < numSources; ++i) + { + String s ("clock: "); + s += clocks[i].name; + + if (clocks[i].isCurrentSource) + { + isSourceSet = true; + s << " (cur)"; + } + + log (s); + } + + if (numSources > 1 && ! isSourceSet) + { + log ("setting clock source"); + asioObject->setClockSource (clocks[0].index); + Thread::sleep (20); + } + else + { + if (numSources == 0) + { + log ("ASIO - no clock sources!"); + } + } + + double cr = 0; + err = asioObject->getSampleRate (&cr); + if (err == 0) + { + currentSampleRate = cr; + } + else + { + logError ("GetSampleRate", err); + currentSampleRate = 0; + } + + error = String::empty; + needToReset = false; + isReSync = false; + err = 0; + bool buffersCreated = false; + + if (currentSampleRate != sampleRate) + { + log (T("ASIO samplerate: ") + String (currentSampleRate) + T(" to ") + String (sampleRate)); + err = asioObject->setSampleRate (sampleRate); + + if (err == ASE_NoClock && numSources > 0) + { + log ("trying to set a clock source.."); + Thread::sleep (10); + err = asioObject->setClockSource (clocks[0].index); + if (err != 0) + { + logError ("SetClock", err); + } + + Thread::sleep (10); + err = asioObject->setSampleRate (sampleRate); + } + } + + if (err == 0) + { + currentSampleRate = sampleRate; + + if (needToReset) + { + if (isReSync) + { + log ("Resync request"); + } + + log ("! Resetting ASIO after sample rate change"); + removeCurrentDriver(); + + loadDriver(); + const String error (initDriver()); + + if (error.isNotEmpty()) + { + log (T("ASIOInit: ") + error); + } + + needToReset = false; + isReSync = false; + } + + numActiveInputChans = 0; + numActiveOutputChans = 0; + + ASIOBufferInfo* info = bufferInfos; + int i; + for (i = 0; i < totalNumInputChans; ++i) + { + if (inputChannels[i]) + { + currentChansIn.setBit (i); + info->isInput = 1; + info->channelNum = i; + info->buffers[0] = info->buffers[1] = 0; + ++info; + ++numActiveInputChans; + } + } + + for (i = 0; i < totalNumOutputChans; ++i) + { + if (outputChannels[i]) + { + currentChansOut.setBit (i); + info->isInput = 0; + info->channelNum = i; + info->buffers[0] = info->buffers[1] = 0; + ++info; + ++numActiveOutputChans; + } + } + + const int totalBuffers = numActiveInputChans + numActiveOutputChans; + + callbacks.sampleRateDidChange = &sampleRateChangedCallback; + + if (currentASIODev[0] == this) + { + callbacks.bufferSwitch = &bufferSwitchCallback0; + callbacks.asioMessage = &asioMessagesCallback0; + callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0; + } + else if (currentASIODev[1] == this) + { + callbacks.bufferSwitch = &bufferSwitchCallback1; + callbacks.asioMessage = &asioMessagesCallback1; + callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1; + } + else if (currentASIODev[2] == this) + { + callbacks.bufferSwitch = &bufferSwitchCallback2; + callbacks.asioMessage = &asioMessagesCallback2; + callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2; + } + else + { + jassertfalse + } + + log ("disposing buffers"); + err = asioObject->disposeBuffers(); + + log (T("creating buffers: ") + String (totalBuffers) + T(", ") + String (currentBlockSizeSamples)); + err = asioObject->createBuffers (bufferInfos, + totalBuffers, + currentBlockSizeSamples, + &callbacks); + + if (err != 0) + { + currentBlockSizeSamples = preferredSize; + logError ("create buffers 2", err); + + asioObject->disposeBuffers(); + err = asioObject->createBuffers (bufferInfos, + totalBuffers, + currentBlockSizeSamples, + &callbacks); + } + + if (err == 0) + { + buffersCreated = true; + + tempBuffer.calloc (totalBuffers * currentBlockSizeSamples + 32); + + int n = 0; + Array types; + currentBitDepth = 16; + + for (i = 0; i < jmin ((int) totalNumInputChans, maxASIOChannels); ++i) + { + if (inputChannels[i]) + { + inBuffers[n] = tempBuffer + (currentBlockSizeSamples * n); + + ASIOChannelInfo channelInfo; + zerostruct (channelInfo); + + channelInfo.channel = i; + channelInfo.isInput = 1; + asioObject->getChannelInfo (&channelInfo); + + types.addIfNotAlreadyThere (channelInfo.type); + typeToFormatParameters (channelInfo.type, + inputChannelBitDepths[n], + inputChannelBytesPerSample[n], + inputChannelIsFloat[n], + inputChannelLittleEndian[n]); + + currentBitDepth = jmax (currentBitDepth, inputChannelBitDepths[n]); + + ++n; + } + } + + jassert (numActiveInputChans == n); + n = 0; + + for (i = 0; i < jmin ((int) totalNumOutputChans, maxASIOChannels); ++i) + { + if (outputChannels[i]) + { + outBuffers[n] = tempBuffer + (currentBlockSizeSamples * (numActiveInputChans + n)); + + ASIOChannelInfo channelInfo; + zerostruct (channelInfo); + + channelInfo.channel = i; + channelInfo.isInput = 0; + asioObject->getChannelInfo (&channelInfo); + + types.addIfNotAlreadyThere (channelInfo.type); + typeToFormatParameters (channelInfo.type, + outputChannelBitDepths[n], + outputChannelBytesPerSample[n], + outputChannelIsFloat[n], + outputChannelLittleEndian[n]); + + currentBitDepth = jmax (currentBitDepth, outputChannelBitDepths[n]); + + ++n; + } + } + + jassert (numActiveOutputChans == n); + + for (i = types.size(); --i >= 0;) + { + log (T("channel format: ") + String (types[i])); + } + + jassert (n <= totalBuffers); + + for (i = 0; i < numActiveOutputChans; ++i) + { + const int size = currentBlockSizeSamples * (outputChannelBitDepths[i] >> 3); + + if (bufferInfos [numActiveInputChans + i].buffers[0] == 0 + || bufferInfos [numActiveInputChans + i].buffers[1] == 0) + { + log ("!! Null buffers"); + } + else + { + zeromem (bufferInfos[numActiveInputChans + i].buffers[0], size); + zeromem (bufferInfos[numActiveInputChans + i].buffers[1], size); + } + } + + inputLatency = outputLatency = 0; + + if (asioObject->getLatencies (&inputLatency, &outputLatency) != 0) + { + log ("ASIO - no latencies"); + } + else + { + log (T("ASIO latencies: ") + + String ((int) outputLatency) + + T(", ") + + String ((int) inputLatency)); + } + + isOpen_ = true; + + log ("starting ASIO"); + calledback = false; + err = asioObject->start(); + + if (err != 0) + { + isOpen_ = false; + log ("ASIO - stop on failure"); + Thread::sleep (10); + asioObject->stop(); + error = "Can't start device"; + Thread::sleep (10); + } + else + { + int count = 300; + while (--count > 0 && ! calledback) + Thread::sleep (10); + + isStarted = true; + + if (! calledback) + { + error = "Device didn't start correctly"; + log ("ASIO didn't callback - stopping.."); + asioObject->stop(); + } + } + } + else + { + error = "Can't create i/o buffers"; + } + } + else + { + error = "Can't set sample rate: "; + error << sampleRate; + } + + if (error.isNotEmpty()) + { + logError (error, err); + + if (asioObject != 0 && buffersCreated) + asioObject->disposeBuffers(); + + Thread::sleep (20); + isStarted = false; + isOpen_ = false; + close(); + } + + needToReset = false; + isReSync = false; + + return error; + } + + void close() + { + error = String::empty; + stopTimer(); + stop(); + + if (isASIOOpen && isOpen_) + { + const ScopedLock sl (callbackLock); + + isOpen_ = false; + isStarted = false; + needToReset = false; + isReSync = false; + + log ("ASIO - stopping"); + + if (asioObject != 0) + { + Thread::sleep (20); + asioObject->stop(); + Thread::sleep (10); + asioObject->disposeBuffers(); + } + + Thread::sleep (10); + } + } + + bool isOpen() + { + return isOpen_ || insideControlPanelModalLoop; + } + + int getCurrentBufferSizeSamples() + { + return currentBlockSizeSamples; + } + + double getCurrentSampleRate() + { + return currentSampleRate; + } + + const BitArray getActiveOutputChannels() const + { + return currentChansOut; + } + + const BitArray getActiveInputChannels() const + { + return currentChansIn; + } + + int getCurrentBitDepth() + { + return currentBitDepth; + } + + int getOutputLatencyInSamples() + { + return outputLatency + currentBlockSizeSamples / 4; + } + + int getInputLatencyInSamples() + { + return inputLatency + currentBlockSizeSamples / 4; + } + + void start (AudioIODeviceCallback* callback) + { + if (callback != 0) + { + callback->audioDeviceAboutToStart (this); + + const ScopedLock sl (callbackLock); + currentCallback = callback; + } + } + + void stop() + { + AudioIODeviceCallback* const lastCallback = currentCallback; + + { + const ScopedLock sl (callbackLock); + currentCallback = 0; + } + + if (lastCallback != 0) + lastCallback->audioDeviceStopped(); + } + + bool isPlaying() + { + return isASIOOpen && (currentCallback != 0); + } + + const String getLastError() + { + return error; + } + + bool hasControlPanel() const + { + return true; + } + + bool showControlPanel() + { + log ("ASIO - showing control panel"); + + Component modalWindow (String::empty); + modalWindow.setOpaque (true); + modalWindow.addToDesktop (0); + modalWindow.enterModalState(); + bool done = false; + + JUCE_TRY + { + // are there are devices that need to be closed before showing their control panel? + // close(); + insideControlPanelModalLoop = true; + + const uint32 started = Time::getMillisecondCounter(); + + if (asioObject != 0) + { + asioObject->controlPanel(); + + const int spent = (int) Time::getMillisecondCounter() - (int) started; + + log (T("spent: ") + String (spent)); + + if (spent > 300) + { + shouldUsePreferredSize = true; + done = true; + } + } + } + JUCE_CATCH_ALL + + insideControlPanelModalLoop = false; + return done; + } + + void resetRequest() throw() + { + needToReset = true; + } + + void resyncRequest() throw() + { + needToReset = true; + isReSync = true; + } + + void timerCallback() + { + if (! insideControlPanelModalLoop) + { + stopTimer(); + + // used to cause a reset + log ("! ASIO restart request!"); + + if (isOpen_) + { + AudioIODeviceCallback* const oldCallback = currentCallback; + + close(); + open (BitArray (currentChansIn), BitArray (currentChansOut), + currentSampleRate, currentBlockSizeSamples); + + if (oldCallback != 0) + start (oldCallback); + } + } + else + { + startTimer (100); + } + } + + juce_UseDebuggingNewOperator private: - IASIO* volatile asioObject; - ASIOCallbacks callbacks; - - void* windowHandle; - CLSID classId; - const String optionalDllForDirectLoading; - String error; - - long totalNumInputChans, totalNumOutputChans; - StringArray inputChannelNames, outputChannelNames; - - Array sampleRates, bufferSizes; - long inputLatency, outputLatency; - long minSize, maxSize, preferredSize, granularity; - - int volatile currentBlockSizeSamples; - int volatile currentBitDepth; - double volatile currentSampleRate; - BitArray currentChansOut, currentChansIn; - AudioIODeviceCallback* volatile currentCallback; - CriticalSection callbackLock; - - ASIOBufferInfo bufferInfos [maxASIOChannels]; - float* inBuffers [maxASIOChannels]; - float* outBuffers [maxASIOChannels]; - - int inputChannelBitDepths [maxASIOChannels]; - int outputChannelBitDepths [maxASIOChannels]; - int inputChannelBytesPerSample [maxASIOChannels]; - int outputChannelBytesPerSample [maxASIOChannels]; - bool inputChannelIsFloat [maxASIOChannels]; - bool outputChannelIsFloat [maxASIOChannels]; - bool inputChannelLittleEndian [maxASIOChannels]; - bool outputChannelLittleEndian [maxASIOChannels]; - - WaitableEvent event1; - HeapBlock tempBuffer; - int volatile bufferIndex, numActiveInputChans, numActiveOutputChans; - - bool isOpen_, isStarted; - bool volatile isASIOOpen; - bool volatile calledback; - bool volatile littleEndian, postOutput, needToReset, isReSync; - bool volatile insideControlPanelModalLoop; - bool volatile shouldUsePreferredSize; - - void removeCurrentDriver() - { - if (asioObject != 0) - { - asioObject->Release(); - asioObject = 0; - } - } - - bool loadDriver() - { - removeCurrentDriver(); - - JUCE_TRY - { - if (CoCreateInstance (classId, 0, CLSCTX_INPROC_SERVER, - classId, (void**) &asioObject) == S_OK) - { - return true; - } - - // If a class isn't registered but we have a path for it, we can fallback to - // doing a direct load of the COM object (only available via the juce_createASIOAudioIODeviceForGUID function). - if (optionalDllForDirectLoading.isNotEmpty()) - { - HMODULE h = LoadLibrary (optionalDllForDirectLoading); - - if (h != 0) - { - typedef HRESULT (CALLBACK* DllGetClassObjectFunc) (REFCLSID clsid, REFIID iid, LPVOID* ppv); - DllGetClassObjectFunc dllGetClassObject = (DllGetClassObjectFunc) GetProcAddress (h, "DllGetClassObject"); - - if (dllGetClassObject != 0) - { - IClassFactory* classFactory = 0; - HRESULT hr = dllGetClassObject (classId, IID_IClassFactory, (void**) &classFactory); - - if (classFactory != 0) - { - hr = classFactory->CreateInstance (0, classId, (void**) &asioObject); - classFactory->Release(); - } - - return asioObject != 0; - } - } - } - } - JUCE_CATCH_ALL - - asioObject = 0; - return false; - } - - const String initDriver() - { - if (asioObject != 0) - { - char buffer [256]; - zeromem (buffer, sizeof (buffer)); - - if (! asioObject->init (windowHandle)) - { - asioObject->getErrorMessage (buffer); - return String (buffer, sizeof (buffer) - 1); - } - - // just in case any daft drivers expect this to be called.. - asioObject->getDriverName (buffer); - - return String::empty; - } - - return "No Driver"; - } - - const String openDevice() - { - // use this in case the driver starts opening dialog boxes.. - Component modalWindow (String::empty); - modalWindow.setOpaque (true); - modalWindow.addToDesktop (0); - modalWindow.enterModalState(); - - // open the device and get its info.. - log (T("opening ASIO device: ") + getName()); - - needToReset = false; - isReSync = false; - outputChannelNames.clear(); - inputChannelNames.clear(); - bufferSizes.clear(); - sampleRates.clear(); - isASIOOpen = false; - isOpen_ = false; - totalNumInputChans = 0; - totalNumOutputChans = 0; - numActiveInputChans = 0; - numActiveOutputChans = 0; - currentCallback = 0; - - error = String::empty; - - if (getName().isEmpty()) - return error; - - long err = 0; - - if (loadDriver()) - { - if ((error = initDriver()).isEmpty()) - { - numActiveInputChans = 0; - numActiveOutputChans = 0; - totalNumInputChans = 0; - totalNumOutputChans = 0; - - if (asioObject != 0 - && (err = asioObject->getChannels (&totalNumInputChans, &totalNumOutputChans)) == 0) - { - log (String ((int) totalNumInputChans) + T(" in, ") + String ((int) totalNumOutputChans) + T(" out")); - - if ((err = asioObject->getBufferSize (&minSize, &maxSize, &preferredSize, &granularity)) == 0) - { - // find a list of buffer sizes.. - log (String ((int) minSize) + T(" ") + String ((int) maxSize) + T(" ") + String ((int)preferredSize) + T(" ") + String ((int)granularity)); - - if (granularity >= 0) - { - granularity = jmax (1, (int) granularity); - - for (int i = jmax (minSize, (int) granularity); i < jmin (6400, maxSize); i += granularity) - bufferSizes.addIfNotAlreadyThere (granularity * (i / granularity)); - } - else if (granularity < 0) - { - for (int i = 0; i < 18; ++i) - { - const int s = (1 << i); - - if (s >= minSize && s <= maxSize) - bufferSizes.add (s); - } - } - - if (! bufferSizes.contains (preferredSize)) - bufferSizes.insert (0, preferredSize); - - double currentRate = 0; - asioObject->getSampleRate (¤tRate); - - if (currentRate <= 0.0 || currentRate > 192001.0) - { - log ("setting sample rate"); - err = asioObject->setSampleRate (44100.0); - if (err != 0) - { - logError ("setting sample rate", err); - } - - asioObject->getSampleRate (¤tRate); - } - - currentSampleRate = currentRate; - - postOutput = (asioObject->outputReady() == 0); - if (postOutput) - { - log ("ASIO outputReady = ok"); - } - - updateSampleRates(); - - // ..because cubase does it at this point - inputLatency = outputLatency = 0; - if (asioObject->getLatencies (&inputLatency, &outputLatency) != 0) - { - log ("ASIO - no latencies"); - } - - log (String ("latencies: ") - + String ((int) inputLatency) - + T(", ") + String ((int) outputLatency)); - - // create some dummy buffers now.. because cubase does.. - numActiveInputChans = 0; - numActiveOutputChans = 0; - - ASIOBufferInfo* info = bufferInfos; - int i, numChans = 0; - for (i = 0; i < jmin (2, totalNumInputChans); ++i) - { - info->isInput = 1; - info->channelNum = i; - info->buffers[0] = info->buffers[1] = 0; - ++info; - ++numChans; - } - - const int outputBufferIndex = numChans; - - for (i = 0; i < jmin (2, totalNumOutputChans); ++i) - { - info->isInput = 0; - info->channelNum = i; - info->buffers[0] = info->buffers[1] = 0; - ++info; - ++numChans; - } - - callbacks.sampleRateDidChange = &sampleRateChangedCallback; - - if (currentASIODev[0] == this) - { - callbacks.bufferSwitch = &bufferSwitchCallback0; - callbacks.asioMessage = &asioMessagesCallback0; - callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0; - } - else if (currentASIODev[1] == this) - { - callbacks.bufferSwitch = &bufferSwitchCallback1; - callbacks.asioMessage = &asioMessagesCallback1; - callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1; - } - else if (currentASIODev[2] == this) - { - callbacks.bufferSwitch = &bufferSwitchCallback2; - callbacks.asioMessage = &asioMessagesCallback2; - callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2; - } - else - { - jassertfalse - } - - log (T("creating buffers (dummy): ") + String (numChans) - + T(", ") + String ((int) preferredSize)); - - if (preferredSize > 0) - { - err = asioObject->createBuffers (bufferInfos, numChans, preferredSize, &callbacks); - if (err != 0) - { - logError ("dummy buffers", err); - } - } - - long newInps = 0, newOuts = 0; - asioObject->getChannels (&newInps, &newOuts); - - if (totalNumInputChans != newInps || totalNumOutputChans != newOuts) - { - totalNumInputChans = newInps; - totalNumOutputChans = newOuts; - - log (String ((int) totalNumInputChans) + T(" in; ") - + String ((int) totalNumOutputChans) + T(" out")); - } - - updateSampleRates(); - - ASIOChannelInfo channelInfo; - channelInfo.type = 0; - - for (i = 0; i < totalNumInputChans; ++i) - { - zerostruct (channelInfo); - channelInfo.channel = i; - channelInfo.isInput = 1; - asioObject->getChannelInfo (&channelInfo); - - inputChannelNames.add (String (channelInfo.name)); - } - - for (i = 0; i < totalNumOutputChans; ++i) - { - zerostruct (channelInfo); - channelInfo.channel = i; - channelInfo.isInput = 0; - asioObject->getChannelInfo (&channelInfo); - - outputChannelNames.add (String (channelInfo.name)); - - typeToFormatParameters (channelInfo.type, - outputChannelBitDepths[i], - outputChannelBytesPerSample[i], - outputChannelIsFloat[i], - outputChannelLittleEndian[i]); - - if (i < 2) - { - // clear the channels that are used with the dummy stuff - const int bytesPerBuffer = preferredSize * (outputChannelBitDepths[i] >> 3); - zeromem (bufferInfos [outputBufferIndex + i].buffers[0], bytesPerBuffer); - zeromem (bufferInfos [outputBufferIndex + i].buffers[1], bytesPerBuffer); - } - } - - outputChannelNames.trim(); - inputChannelNames.trim(); - outputChannelNames.appendNumbersToDuplicates (false, true); - inputChannelNames.appendNumbersToDuplicates (false, true); - - // start and stop because cubase does it.. - asioObject->getLatencies (&inputLatency, &outputLatency); - - if ((err = asioObject->start()) != 0) - { - // ignore an error here, as it might start later after setting other stuff up - logError ("ASIO start", err); - } - - Thread::sleep (100); - asioObject->stop(); - } - else - { - error = "Can't detect buffer sizes"; - } - } - else - { - error = "Can't detect asio channels"; - } - } - } - else - { - error = "No such device"; - } - - if (error.isNotEmpty()) - { - logError (error, err); - - if (asioObject != 0) - asioObject->disposeBuffers(); - - removeCurrentDriver(); - isASIOOpen = false; - } - else - { - isASIOOpen = true; - log ("ASIO device open"); - } - - isOpen_ = false; - needToReset = false; - isReSync = false; - - return error; - } - - void callback (const long index) throw() - { - if (isStarted) - { - bufferIndex = index; - processBuffer(); - } - else - { - if (postOutput && (asioObject != 0)) - asioObject->outputReady(); - } - - calledback = true; - } - - void processBuffer() throw() - { - const ASIOBufferInfo* const infos = bufferInfos; - const int bi = bufferIndex; - - const ScopedLock sl (callbackLock); - - if (needToReset) - { - needToReset = false; - - if (isReSync) - { - log ("! ASIO resync"); - isReSync = false; - } - else - { - startTimer (20); - } - } - - if (bi >= 0) - { - const int samps = currentBlockSizeSamples; - - if (currentCallback != 0) - { - int i; - for (i = 0; i < numActiveInputChans; ++i) - { - float* const dst = inBuffers[i]; - - jassert (dst != 0); - - const char* const src = (const char*) (infos[i].buffers[bi]); - - if (inputChannelIsFloat[i]) - { - memcpy (dst, src, samps * sizeof (float)); - } - else - { - jassert (dst == tempBuffer + (samps * i)); - - switch (inputChannelBitDepths[i]) - { - case 16: - convertInt16ToFloat (src, dst, inputChannelBytesPerSample[i], - samps, inputChannelLittleEndian[i]); - break; - - case 24: - convertInt24ToFloat (src, dst, inputChannelBytesPerSample[i], - samps, inputChannelLittleEndian[i]); - break; - - case 32: - convertInt32ToFloat (src, dst, inputChannelBytesPerSample[i], - samps, inputChannelLittleEndian[i]); - break; - - case 64: - jassertfalse - break; - } - } - } - - currentCallback->audioDeviceIOCallback ((const float**) inBuffers, - numActiveInputChans, - outBuffers, - numActiveOutputChans, - samps); - - for (i = 0; i < numActiveOutputChans; ++i) - { - float* const src = outBuffers[i]; - - jassert (src != 0); - - char* const dst = (char*) (infos [numActiveInputChans + i].buffers[bi]); - - if (outputChannelIsFloat[i]) - { - memcpy (dst, src, samps * sizeof (float)); - } - else - { - jassert (src == tempBuffer + (samps * (numActiveInputChans + i))); - - switch (outputChannelBitDepths[i]) - { - case 16: - convertFloatToInt16 (src, dst, outputChannelBytesPerSample[i], - samps, outputChannelLittleEndian[i]); - break; - - case 24: - convertFloatToInt24 (src, dst, outputChannelBytesPerSample[i], - samps, outputChannelLittleEndian[i]); - break; - - case 32: - convertFloatToInt32 (src, dst, outputChannelBytesPerSample[i], - samps, outputChannelLittleEndian[i]); - break; - - case 64: - jassertfalse - break; - } - } - } - } - else - { - for (int i = 0; i < numActiveOutputChans; ++i) - { - const int bytesPerBuffer = samps * (outputChannelBitDepths[i] >> 3); - zeromem (infos[numActiveInputChans + i].buffers[bi], bytesPerBuffer); - } - } - } - - if (postOutput) - asioObject->outputReady(); - } - - static ASIOTime* bufferSwitchTimeInfoCallback0 (ASIOTime*, long index, long) throw() - { - if (currentASIODev[0] != 0) - currentASIODev[0]->callback (index); - - return 0; - } - - static ASIOTime* bufferSwitchTimeInfoCallback1 (ASIOTime*, long index, long) throw() - { - if (currentASIODev[1] != 0) - currentASIODev[1]->callback (index); - - return 0; - } - - static ASIOTime* bufferSwitchTimeInfoCallback2 (ASIOTime*, long index, long) throw() - { - if (currentASIODev[2] != 0) - currentASIODev[2]->callback (index); - - return 0; - } - - static void bufferSwitchCallback0 (long index, long) throw() - { - if (currentASIODev[0] != 0) - currentASIODev[0]->callback (index); - } - - static void bufferSwitchCallback1 (long index, long) throw() - { - if (currentASIODev[1] != 0) - currentASIODev[1]->callback (index); - } - - static void bufferSwitchCallback2 (long index, long) throw() - { - if (currentASIODev[2] != 0) - currentASIODev[2]->callback (index); - } - - static long asioMessagesCallback0 (long selector, long value, void*, double*) throw() - { - return asioMessagesCallback (selector, value, 0); - } - - static long asioMessagesCallback1 (long selector, long value, void*, double*) throw() - { - return asioMessagesCallback (selector, value, 1); - } - - static long asioMessagesCallback2 (long selector, long value, void*, double*) throw() - { - return asioMessagesCallback (selector, value, 2); - } - - static long asioMessagesCallback (long selector, long value, const int deviceIndex) throw() - { - switch (selector) - { - case kAsioSelectorSupported: - if (value == kAsioResetRequest - || value == kAsioEngineVersion - || value == kAsioResyncRequest - || value == kAsioLatenciesChanged - || value == kAsioSupportsInputMonitor) - return 1; - break; - - case kAsioBufferSizeChange: - break; - - case kAsioResetRequest: - if (currentASIODev[deviceIndex] != 0) - currentASIODev[deviceIndex]->resetRequest(); - - return 1; - - case kAsioResyncRequest: - if (currentASIODev[deviceIndex] != 0) - currentASIODev[deviceIndex]->resyncRequest(); - - return 1; - - case kAsioLatenciesChanged: - return 1; - - case kAsioEngineVersion: - return 2; - - case kAsioSupportsTimeInfo: - case kAsioSupportsTimeCode: - return 0; - } - - return 0; - } - - static void sampleRateChangedCallback (ASIOSampleRate) throw() - { - } - - static void convertInt16ToFloat (const char* src, - float* dest, - const int srcStrideBytes, - int numSamples, - const bool littleEndian) throw() - { - const double g = 1.0 / 32768.0; - - if (littleEndian) - { - while (--numSamples >= 0) - { - *dest++ = (float) (g * (short) ByteOrder::littleEndianShort (src)); - src += srcStrideBytes; - } - } - else - { - while (--numSamples >= 0) - { - *dest++ = (float) (g * (short) ByteOrder::bigEndianShort (src)); - src += srcStrideBytes; - } - } - } - - static void convertFloatToInt16 (const float* src, - char* dest, - const int dstStrideBytes, - int numSamples, - const bool littleEndian) throw() - { - const double maxVal = (double) 0x7fff; - - if (littleEndian) - { - while (--numSamples >= 0) - { - *(uint16*) dest = ByteOrder::swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); - dest += dstStrideBytes; - } - } - else - { - while (--numSamples >= 0) - { - *(uint16*) dest = ByteOrder::swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); - dest += dstStrideBytes; - } - } - } - - static void convertInt24ToFloat (const char* src, - float* dest, - const int srcStrideBytes, - int numSamples, - const bool littleEndian) throw() - { - const double g = 1.0 / 0x7fffff; - - if (littleEndian) - { - while (--numSamples >= 0) - { - *dest++ = (float) (g * ByteOrder::littleEndian24Bit (src)); - src += srcStrideBytes; - } - } - else - { - while (--numSamples >= 0) - { - *dest++ = (float) (g * ByteOrder::bigEndian24Bit (src)); - src += srcStrideBytes; - } - } - } - - static void convertFloatToInt24 (const float* src, - char* dest, - const int dstStrideBytes, - int numSamples, - const bool littleEndian) throw() - { - const double maxVal = (double) 0x7fffff; - - if (littleEndian) - { - while (--numSamples >= 0) - { - ByteOrder::littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); - dest += dstStrideBytes; - } - } - else - { - while (--numSamples >= 0) - { - ByteOrder::bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); - dest += dstStrideBytes; - } - } - } - - static void convertInt32ToFloat (const char* src, - float* dest, - const int srcStrideBytes, - int numSamples, - const bool littleEndian) throw() - { - const double g = 1.0 / 0x7fffffff; - - if (littleEndian) - { - while (--numSamples >= 0) - { - *dest++ = (float) (g * (int) ByteOrder::littleEndianInt (src)); - src += srcStrideBytes; - } - } - else - { - while (--numSamples >= 0) - { - *dest++ = (float) (g * (int) ByteOrder::bigEndianInt (src)); - src += srcStrideBytes; - } - } - } - - static void convertFloatToInt32 (const float* src, - char* dest, - const int dstStrideBytes, - int numSamples, - const bool littleEndian) throw() - { - const double maxVal = (double) 0x7fffffff; - - if (littleEndian) - { - while (--numSamples >= 0) - { - *(uint32*) dest = ByteOrder::swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); - dest += dstStrideBytes; - } - } - else - { - while (--numSamples >= 0) - { - *(uint32*) dest = ByteOrder::swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); - dest += dstStrideBytes; - } - } - } - - static void typeToFormatParameters (const long type, - int& bitDepth, - int& byteStride, - bool& formatIsFloat, - bool& littleEndian) throw() - { - bitDepth = 0; - littleEndian = false; - formatIsFloat = false; - - switch (type) - { - case ASIOSTInt16MSB: - case ASIOSTInt16LSB: - case ASIOSTInt32MSB16: - case ASIOSTInt32LSB16: - bitDepth = 16; break; - - case ASIOSTFloat32MSB: - case ASIOSTFloat32LSB: - formatIsFloat = true; - bitDepth = 32; break; - - case ASIOSTInt32MSB: - case ASIOSTInt32LSB: - bitDepth = 32; break; - - case ASIOSTInt24MSB: - case ASIOSTInt24LSB: - case ASIOSTInt32MSB24: - case ASIOSTInt32LSB24: - case ASIOSTInt32MSB18: - case ASIOSTInt32MSB20: - case ASIOSTInt32LSB18: - case ASIOSTInt32LSB20: - bitDepth = 24; break; - - case ASIOSTFloat64MSB: - case ASIOSTFloat64LSB: - default: - bitDepth = 64; - break; - } - - switch (type) - { - case ASIOSTInt16MSB: - case ASIOSTInt32MSB16: - case ASIOSTFloat32MSB: - case ASIOSTFloat64MSB: - case ASIOSTInt32MSB: - case ASIOSTInt32MSB18: - case ASIOSTInt32MSB20: - case ASIOSTInt32MSB24: - case ASIOSTInt24MSB: - littleEndian = false; break; - - case ASIOSTInt16LSB: - case ASIOSTInt32LSB16: - case ASIOSTFloat32LSB: - case ASIOSTFloat64LSB: - case ASIOSTInt32LSB: - case ASIOSTInt32LSB18: - case ASIOSTInt32LSB20: - case ASIOSTInt32LSB24: - case ASIOSTInt24LSB: - littleEndian = true; break; - - default: - break; - } - - switch (type) - { - case ASIOSTInt16LSB: - case ASIOSTInt16MSB: - byteStride = 2; break; - - case ASIOSTInt24LSB: - case ASIOSTInt24MSB: - byteStride = 3; break; - - case ASIOSTInt32MSB16: - case ASIOSTInt32LSB16: - case ASIOSTInt32MSB: - case ASIOSTInt32MSB18: - case ASIOSTInt32MSB20: - case ASIOSTInt32MSB24: - case ASIOSTInt32LSB: - case ASIOSTInt32LSB18: - case ASIOSTInt32LSB20: - case ASIOSTInt32LSB24: - case ASIOSTFloat32LSB: - case ASIOSTFloat32MSB: - byteStride = 4; break; - - case ASIOSTFloat64MSB: - case ASIOSTFloat64LSB: - byteStride = 8; break; - - default: - break; - } - } + IASIO* volatile asioObject; + ASIOCallbacks callbacks; + + void* windowHandle; + CLSID classId; + const String optionalDllForDirectLoading; + String error; + + long totalNumInputChans, totalNumOutputChans; + StringArray inputChannelNames, outputChannelNames; + + Array sampleRates, bufferSizes; + long inputLatency, outputLatency; + long minSize, maxSize, preferredSize, granularity; + + int volatile currentBlockSizeSamples; + int volatile currentBitDepth; + double volatile currentSampleRate; + BitArray currentChansOut, currentChansIn; + AudioIODeviceCallback* volatile currentCallback; + CriticalSection callbackLock; + + ASIOBufferInfo bufferInfos [maxASIOChannels]; + float* inBuffers [maxASIOChannels]; + float* outBuffers [maxASIOChannels]; + + int inputChannelBitDepths [maxASIOChannels]; + int outputChannelBitDepths [maxASIOChannels]; + int inputChannelBytesPerSample [maxASIOChannels]; + int outputChannelBytesPerSample [maxASIOChannels]; + bool inputChannelIsFloat [maxASIOChannels]; + bool outputChannelIsFloat [maxASIOChannels]; + bool inputChannelLittleEndian [maxASIOChannels]; + bool outputChannelLittleEndian [maxASIOChannels]; + + WaitableEvent event1; + HeapBlock tempBuffer; + int volatile bufferIndex, numActiveInputChans, numActiveOutputChans; + + bool isOpen_, isStarted; + bool volatile isASIOOpen; + bool volatile calledback; + bool volatile littleEndian, postOutput, needToReset, isReSync; + bool volatile insideControlPanelModalLoop; + bool volatile shouldUsePreferredSize; + + void removeCurrentDriver() + { + if (asioObject != 0) + { + asioObject->Release(); + asioObject = 0; + } + } + + bool loadDriver() + { + removeCurrentDriver(); + + JUCE_TRY + { + if (CoCreateInstance (classId, 0, CLSCTX_INPROC_SERVER, + classId, (void**) &asioObject) == S_OK) + { + return true; + } + + // If a class isn't registered but we have a path for it, we can fallback to + // doing a direct load of the COM object (only available via the juce_createASIOAudioIODeviceForGUID function). + if (optionalDllForDirectLoading.isNotEmpty()) + { + HMODULE h = LoadLibrary (optionalDllForDirectLoading); + + if (h != 0) + { + typedef HRESULT (CALLBACK* DllGetClassObjectFunc) (REFCLSID clsid, REFIID iid, LPVOID* ppv); + DllGetClassObjectFunc dllGetClassObject = (DllGetClassObjectFunc) GetProcAddress (h, "DllGetClassObject"); + + if (dllGetClassObject != 0) + { + IClassFactory* classFactory = 0; + HRESULT hr = dllGetClassObject (classId, IID_IClassFactory, (void**) &classFactory); + + if (classFactory != 0) + { + hr = classFactory->CreateInstance (0, classId, (void**) &asioObject); + classFactory->Release(); + } + + return asioObject != 0; + } + } + } + } + JUCE_CATCH_ALL + + asioObject = 0; + return false; + } + + const String initDriver() + { + if (asioObject != 0) + { + char buffer [256]; + zeromem (buffer, sizeof (buffer)); + + if (! asioObject->init (windowHandle)) + { + asioObject->getErrorMessage (buffer); + return String (buffer, sizeof (buffer) - 1); + } + + // just in case any daft drivers expect this to be called.. + asioObject->getDriverName (buffer); + + return String::empty; + } + + return "No Driver"; + } + + const String openDevice() + { + // use this in case the driver starts opening dialog boxes.. + Component modalWindow (String::empty); + modalWindow.setOpaque (true); + modalWindow.addToDesktop (0); + modalWindow.enterModalState(); + + // open the device and get its info.. + log (T("opening ASIO device: ") + getName()); + + needToReset = false; + isReSync = false; + outputChannelNames.clear(); + inputChannelNames.clear(); + bufferSizes.clear(); + sampleRates.clear(); + isASIOOpen = false; + isOpen_ = false; + totalNumInputChans = 0; + totalNumOutputChans = 0; + numActiveInputChans = 0; + numActiveOutputChans = 0; + currentCallback = 0; + + error = String::empty; + + if (getName().isEmpty()) + return error; + + long err = 0; + + if (loadDriver()) + { + if ((error = initDriver()).isEmpty()) + { + numActiveInputChans = 0; + numActiveOutputChans = 0; + totalNumInputChans = 0; + totalNumOutputChans = 0; + + if (asioObject != 0 + && (err = asioObject->getChannels (&totalNumInputChans, &totalNumOutputChans)) == 0) + { + log (String ((int) totalNumInputChans) + T(" in, ") + String ((int) totalNumOutputChans) + T(" out")); + + if ((err = asioObject->getBufferSize (&minSize, &maxSize, &preferredSize, &granularity)) == 0) + { + // find a list of buffer sizes.. + log (String ((int) minSize) + T(" ") + String ((int) maxSize) + T(" ") + String ((int)preferredSize) + T(" ") + String ((int)granularity)); + + if (granularity >= 0) + { + granularity = jmax (1, (int) granularity); + + for (int i = jmax ((int) minSize, (int) granularity); i < jmin (6400, (int) maxSize); i += granularity) + bufferSizes.addIfNotAlreadyThere (granularity * (i / granularity)); + } + else if (granularity < 0) + { + for (int i = 0; i < 18; ++i) + { + const int s = (1 << i); + + if (s >= minSize && s <= maxSize) + bufferSizes.add (s); + } + } + + if (! bufferSizes.contains (preferredSize)) + bufferSizes.insert (0, preferredSize); + + double currentRate = 0; + asioObject->getSampleRate (¤tRate); + + if (currentRate <= 0.0 || currentRate > 192001.0) + { + log ("setting sample rate"); + err = asioObject->setSampleRate (44100.0); + if (err != 0) + { + logError ("setting sample rate", err); + } + + asioObject->getSampleRate (¤tRate); + } + + currentSampleRate = currentRate; + + postOutput = (asioObject->outputReady() == 0); + if (postOutput) + { + log ("ASIO outputReady = ok"); + } + + updateSampleRates(); + + // ..because cubase does it at this point + inputLatency = outputLatency = 0; + if (asioObject->getLatencies (&inputLatency, &outputLatency) != 0) + { + log ("ASIO - no latencies"); + } + + log (String ("latencies: ") + + String ((int) inputLatency) + + T(", ") + String ((int) outputLatency)); + + // create some dummy buffers now.. because cubase does.. + numActiveInputChans = 0; + numActiveOutputChans = 0; + + ASIOBufferInfo* info = bufferInfos; + int i, numChans = 0; + for (i = 0; i < jmin (2, (int) totalNumInputChans); ++i) + { + info->isInput = 1; + info->channelNum = i; + info->buffers[0] = info->buffers[1] = 0; + ++info; + ++numChans; + } + + const int outputBufferIndex = numChans; + + for (i = 0; i < jmin (2, (int) totalNumOutputChans); ++i) + { + info->isInput = 0; + info->channelNum = i; + info->buffers[0] = info->buffers[1] = 0; + ++info; + ++numChans; + } + + callbacks.sampleRateDidChange = &sampleRateChangedCallback; + + if (currentASIODev[0] == this) + { + callbacks.bufferSwitch = &bufferSwitchCallback0; + callbacks.asioMessage = &asioMessagesCallback0; + callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0; + } + else if (currentASIODev[1] == this) + { + callbacks.bufferSwitch = &bufferSwitchCallback1; + callbacks.asioMessage = &asioMessagesCallback1; + callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1; + } + else if (currentASIODev[2] == this) + { + callbacks.bufferSwitch = &bufferSwitchCallback2; + callbacks.asioMessage = &asioMessagesCallback2; + callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2; + } + else + { + jassertfalse + } + + log (T("creating buffers (dummy): ") + String (numChans) + + T(", ") + String ((int) preferredSize)); + + if (preferredSize > 0) + { + err = asioObject->createBuffers (bufferInfos, numChans, preferredSize, &callbacks); + if (err != 0) + { + logError ("dummy buffers", err); + } + } + + long newInps = 0, newOuts = 0; + asioObject->getChannels (&newInps, &newOuts); + + if (totalNumInputChans != newInps || totalNumOutputChans != newOuts) + { + totalNumInputChans = newInps; + totalNumOutputChans = newOuts; + + log (String ((int) totalNumInputChans) + T(" in; ") + + String ((int) totalNumOutputChans) + T(" out")); + } + + updateSampleRates(); + + ASIOChannelInfo channelInfo; + channelInfo.type = 0; + + for (i = 0; i < totalNumInputChans; ++i) + { + zerostruct (channelInfo); + channelInfo.channel = i; + channelInfo.isInput = 1; + asioObject->getChannelInfo (&channelInfo); + + inputChannelNames.add (String (channelInfo.name)); + } + + for (i = 0; i < totalNumOutputChans; ++i) + { + zerostruct (channelInfo); + channelInfo.channel = i; + channelInfo.isInput = 0; + asioObject->getChannelInfo (&channelInfo); + + outputChannelNames.add (String (channelInfo.name)); + + typeToFormatParameters (channelInfo.type, + outputChannelBitDepths[i], + outputChannelBytesPerSample[i], + outputChannelIsFloat[i], + outputChannelLittleEndian[i]); + + if (i < 2) + { + // clear the channels that are used with the dummy stuff + const int bytesPerBuffer = preferredSize * (outputChannelBitDepths[i] >> 3); + zeromem (bufferInfos [outputBufferIndex + i].buffers[0], bytesPerBuffer); + zeromem (bufferInfos [outputBufferIndex + i].buffers[1], bytesPerBuffer); + } + } + + outputChannelNames.trim(); + inputChannelNames.trim(); + outputChannelNames.appendNumbersToDuplicates (false, true); + inputChannelNames.appendNumbersToDuplicates (false, true); + + // start and stop because cubase does it.. + asioObject->getLatencies (&inputLatency, &outputLatency); + + if ((err = asioObject->start()) != 0) + { + // ignore an error here, as it might start later after setting other stuff up + logError ("ASIO start", err); + } + + Thread::sleep (100); + asioObject->stop(); + } + else + { + error = "Can't detect buffer sizes"; + } + } + else + { + error = "Can't detect asio channels"; + } + } + } + else + { + error = "No such device"; + } + + if (error.isNotEmpty()) + { + logError (error, err); + + if (asioObject != 0) + asioObject->disposeBuffers(); + + removeCurrentDriver(); + isASIOOpen = false; + } + else + { + isASIOOpen = true; + log ("ASIO device open"); + } + + isOpen_ = false; + needToReset = false; + isReSync = false; + + return error; + } + + void callback (const long index) throw() + { + if (isStarted) + { + bufferIndex = index; + processBuffer(); + } + else + { + if (postOutput && (asioObject != 0)) + asioObject->outputReady(); + } + + calledback = true; + } + + void processBuffer() throw() + { + const ASIOBufferInfo* const infos = bufferInfos; + const int bi = bufferIndex; + + const ScopedLock sl (callbackLock); + + if (needToReset) + { + needToReset = false; + + if (isReSync) + { + log ("! ASIO resync"); + isReSync = false; + } + else + { + startTimer (20); + } + } + + if (bi >= 0) + { + const int samps = currentBlockSizeSamples; + + if (currentCallback != 0) + { + int i; + for (i = 0; i < numActiveInputChans; ++i) + { + float* const dst = inBuffers[i]; + + jassert (dst != 0); + + const char* const src = (const char*) (infos[i].buffers[bi]); + + if (inputChannelIsFloat[i]) + { + memcpy (dst, src, samps * sizeof (float)); + } + else + { + jassert (dst == tempBuffer + (samps * i)); + + switch (inputChannelBitDepths[i]) + { + case 16: + convertInt16ToFloat (src, dst, inputChannelBytesPerSample[i], + samps, inputChannelLittleEndian[i]); + break; + + case 24: + convertInt24ToFloat (src, dst, inputChannelBytesPerSample[i], + samps, inputChannelLittleEndian[i]); + break; + + case 32: + convertInt32ToFloat (src, dst, inputChannelBytesPerSample[i], + samps, inputChannelLittleEndian[i]); + break; + + case 64: + jassertfalse + break; + } + } + } + + currentCallback->audioDeviceIOCallback ((const float**) inBuffers, + numActiveInputChans, + outBuffers, + numActiveOutputChans, + samps); + + for (i = 0; i < numActiveOutputChans; ++i) + { + float* const src = outBuffers[i]; + + jassert (src != 0); + + char* const dst = (char*) (infos [numActiveInputChans + i].buffers[bi]); + + if (outputChannelIsFloat[i]) + { + memcpy (dst, src, samps * sizeof (float)); + } + else + { + jassert (src == tempBuffer + (samps * (numActiveInputChans + i))); + + switch (outputChannelBitDepths[i]) + { + case 16: + convertFloatToInt16 (src, dst, outputChannelBytesPerSample[i], + samps, outputChannelLittleEndian[i]); + break; + + case 24: + convertFloatToInt24 (src, dst, outputChannelBytesPerSample[i], + samps, outputChannelLittleEndian[i]); + break; + + case 32: + convertFloatToInt32 (src, dst, outputChannelBytesPerSample[i], + samps, outputChannelLittleEndian[i]); + break; + + case 64: + jassertfalse + break; + } + } + } + } + else + { + for (int i = 0; i < numActiveOutputChans; ++i) + { + const int bytesPerBuffer = samps * (outputChannelBitDepths[i] >> 3); + zeromem (infos[numActiveInputChans + i].buffers[bi], bytesPerBuffer); + } + } + } + + if (postOutput) + asioObject->outputReady(); + } + + static ASIOTime* bufferSwitchTimeInfoCallback0 (ASIOTime*, long index, long) throw() + { + if (currentASIODev[0] != 0) + currentASIODev[0]->callback (index); + + return 0; + } + + static ASIOTime* bufferSwitchTimeInfoCallback1 (ASIOTime*, long index, long) throw() + { + if (currentASIODev[1] != 0) + currentASIODev[1]->callback (index); + + return 0; + } + + static ASIOTime* bufferSwitchTimeInfoCallback2 (ASIOTime*, long index, long) throw() + { + if (currentASIODev[2] != 0) + currentASIODev[2]->callback (index); + + return 0; + } + + static void bufferSwitchCallback0 (long index, long) throw() + { + if (currentASIODev[0] != 0) + currentASIODev[0]->callback (index); + } + + static void bufferSwitchCallback1 (long index, long) throw() + { + if (currentASIODev[1] != 0) + currentASIODev[1]->callback (index); + } + + static void bufferSwitchCallback2 (long index, long) throw() + { + if (currentASIODev[2] != 0) + currentASIODev[2]->callback (index); + } + + static long asioMessagesCallback0 (long selector, long value, void*, double*) throw() + { + return asioMessagesCallback (selector, value, 0); + } + + static long asioMessagesCallback1 (long selector, long value, void*, double*) throw() + { + return asioMessagesCallback (selector, value, 1); + } + + static long asioMessagesCallback2 (long selector, long value, void*, double*) throw() + { + return asioMessagesCallback (selector, value, 2); + } + + static long asioMessagesCallback (long selector, long value, const int deviceIndex) throw() + { + switch (selector) + { + case kAsioSelectorSupported: + if (value == kAsioResetRequest + || value == kAsioEngineVersion + || value == kAsioResyncRequest + || value == kAsioLatenciesChanged + || value == kAsioSupportsInputMonitor) + return 1; + break; + + case kAsioBufferSizeChange: + break; + + case kAsioResetRequest: + if (currentASIODev[deviceIndex] != 0) + currentASIODev[deviceIndex]->resetRequest(); + + return 1; + + case kAsioResyncRequest: + if (currentASIODev[deviceIndex] != 0) + currentASIODev[deviceIndex]->resyncRequest(); + + return 1; + + case kAsioLatenciesChanged: + return 1; + + case kAsioEngineVersion: + return 2; + + case kAsioSupportsTimeInfo: + case kAsioSupportsTimeCode: + return 0; + } + + return 0; + } + + static void sampleRateChangedCallback (ASIOSampleRate) throw() + { + } + + static void convertInt16ToFloat (const char* src, + float* dest, + const int srcStrideBytes, + int numSamples, + const bool littleEndian) throw() + { + const double g = 1.0 / 32768.0; + + if (littleEndian) + { + while (--numSamples >= 0) + { + *dest++ = (float) (g * (short) ByteOrder::littleEndianShort (src)); + src += srcStrideBytes; + } + } + else + { + while (--numSamples >= 0) + { + *dest++ = (float) (g * (short) ByteOrder::bigEndianShort (src)); + src += srcStrideBytes; + } + } + } + + static void convertFloatToInt16 (const float* src, + char* dest, + const int dstStrideBytes, + int numSamples, + const bool littleEndian) throw() + { + const double maxVal = (double) 0x7fff; + + if (littleEndian) + { + while (--numSamples >= 0) + { + *(uint16*) dest = ByteOrder::swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + dest += dstStrideBytes; + } + } + else + { + while (--numSamples >= 0) + { + *(uint16*) dest = ByteOrder::swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + dest += dstStrideBytes; + } + } + } + + static void convertInt24ToFloat (const char* src, + float* dest, + const int srcStrideBytes, + int numSamples, + const bool littleEndian) throw() + { + const double g = 1.0 / 0x7fffff; + + if (littleEndian) + { + while (--numSamples >= 0) + { + *dest++ = (float) (g * ByteOrder::littleEndian24Bit (src)); + src += srcStrideBytes; + } + } + else + { + while (--numSamples >= 0) + { + *dest++ = (float) (g * ByteOrder::bigEndian24Bit (src)); + src += srcStrideBytes; + } + } + } + + static void convertFloatToInt24 (const float* src, + char* dest, + const int dstStrideBytes, + int numSamples, + const bool littleEndian) throw() + { + const double maxVal = (double) 0x7fffff; + + if (littleEndian) + { + while (--numSamples >= 0) + { + ByteOrder::littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); + dest += dstStrideBytes; + } + } + else + { + while (--numSamples >= 0) + { + ByteOrder::bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest); + dest += dstStrideBytes; + } + } + } + + static void convertInt32ToFloat (const char* src, + float* dest, + const int srcStrideBytes, + int numSamples, + const bool littleEndian) throw() + { + const double g = 1.0 / 0x7fffffff; + + if (littleEndian) + { + while (--numSamples >= 0) + { + *dest++ = (float) (g * (int) ByteOrder::littleEndianInt (src)); + src += srcStrideBytes; + } + } + else + { + while (--numSamples >= 0) + { + *dest++ = (float) (g * (int) ByteOrder::bigEndianInt (src)); + src += srcStrideBytes; + } + } + } + + static void convertFloatToInt32 (const float* src, + char* dest, + const int dstStrideBytes, + int numSamples, + const bool littleEndian) throw() + { + const double maxVal = (double) 0x7fffffff; + + if (littleEndian) + { + while (--numSamples >= 0) + { + *(uint32*) dest = ByteOrder::swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + dest += dstStrideBytes; + } + } + else + { + while (--numSamples >= 0) + { + *(uint32*) dest = ByteOrder::swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++))); + dest += dstStrideBytes; + } + } + } + + static void typeToFormatParameters (const long type, + int& bitDepth, + int& byteStride, + bool& formatIsFloat, + bool& littleEndian) throw() + { + bitDepth = 0; + littleEndian = false; + formatIsFloat = false; + + switch (type) + { + case ASIOSTInt16MSB: + case ASIOSTInt16LSB: + case ASIOSTInt32MSB16: + case ASIOSTInt32LSB16: + bitDepth = 16; break; + + case ASIOSTFloat32MSB: + case ASIOSTFloat32LSB: + formatIsFloat = true; + bitDepth = 32; break; + + case ASIOSTInt32MSB: + case ASIOSTInt32LSB: + bitDepth = 32; break; + + case ASIOSTInt24MSB: + case ASIOSTInt24LSB: + case ASIOSTInt32MSB24: + case ASIOSTInt32LSB24: + case ASIOSTInt32MSB18: + case ASIOSTInt32MSB20: + case ASIOSTInt32LSB18: + case ASIOSTInt32LSB20: + bitDepth = 24; break; + + case ASIOSTFloat64MSB: + case ASIOSTFloat64LSB: + default: + bitDepth = 64; + break; + } + + switch (type) + { + case ASIOSTInt16MSB: + case ASIOSTInt32MSB16: + case ASIOSTFloat32MSB: + case ASIOSTFloat64MSB: + case ASIOSTInt32MSB: + case ASIOSTInt32MSB18: + case ASIOSTInt32MSB20: + case ASIOSTInt32MSB24: + case ASIOSTInt24MSB: + littleEndian = false; break; + + case ASIOSTInt16LSB: + case ASIOSTInt32LSB16: + case ASIOSTFloat32LSB: + case ASIOSTFloat64LSB: + case ASIOSTInt32LSB: + case ASIOSTInt32LSB18: + case ASIOSTInt32LSB20: + case ASIOSTInt32LSB24: + case ASIOSTInt24LSB: + littleEndian = true; break; + + default: + break; + } + + switch (type) + { + case ASIOSTInt16LSB: + case ASIOSTInt16MSB: + byteStride = 2; break; + + case ASIOSTInt24LSB: + case ASIOSTInt24MSB: + byteStride = 3; break; + + case ASIOSTInt32MSB16: + case ASIOSTInt32LSB16: + case ASIOSTInt32MSB: + case ASIOSTInt32MSB18: + case ASIOSTInt32MSB20: + case ASIOSTInt32MSB24: + case ASIOSTInt32LSB: + case ASIOSTInt32LSB18: + case ASIOSTInt32LSB20: + case ASIOSTInt32LSB24: + case ASIOSTFloat32LSB: + case ASIOSTFloat32MSB: + byteStride = 4; break; + + case ASIOSTFloat64MSB: + case ASIOSTFloat64LSB: + byteStride = 8; break; + + default: + break; + } + } }; class ASIOAudioIODeviceType : public AudioIODeviceType { public: - ASIOAudioIODeviceType() - : AudioIODeviceType (T("ASIO")), - classIds (2), - hasScanned (false) - { - CoInitialize (0); - } + ASIOAudioIODeviceType() + : AudioIODeviceType (T("ASIO")), + hasScanned (false) + { + CoInitialize (0); + } - ~ASIOAudioIODeviceType() - { - } + ~ASIOAudioIODeviceType() + { + } - void scanForDevices() - { - hasScanned = true; + void scanForDevices() + { + hasScanned = true; - deviceNames.clear(); - classIds.clear(); + deviceNames.clear(); + classIds.clear(); - HKEY hk = 0; - int index = 0; + HKEY hk = 0; + int index = 0; - if (RegOpenKeyA (HKEY_LOCAL_MACHINE, "software\\asio", &hk) == ERROR_SUCCESS) - { - for (;;) - { - char name [256]; + if (RegOpenKeyA (HKEY_LOCAL_MACHINE, "software\\asio", &hk) == ERROR_SUCCESS) + { + for (;;) + { + char name [256]; - if (RegEnumKeyA (hk, index++, name, 256) == ERROR_SUCCESS) - { - addDriverInfo (name, hk); - } - else - { - break; - } - } + if (RegEnumKeyA (hk, index++, name, 256) == ERROR_SUCCESS) + { + addDriverInfo (name, hk); + } + else + { + break; + } + } - RegCloseKey (hk); - } - } + RegCloseKey (hk); + } + } - const StringArray getDeviceNames (const bool /*wantInputNames*/) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + const StringArray getDeviceNames (const bool /*wantInputNames*/) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - return deviceNames; - } + return deviceNames; + } - int getDefaultDeviceIndex (const bool) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + int getDefaultDeviceIndex (const bool) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - for (int i = deviceNames.size(); --i >= 0;) - if (deviceNames[i].containsIgnoreCase (T("asio4all"))) - return i; // asio4all is a safe choice for a default.. + for (int i = deviceNames.size(); --i >= 0;) + if (deviceNames[i].containsIgnoreCase (T("asio4all"))) + return i; // asio4all is a safe choice for a default.. #if JUCE_DEBUG - if (deviceNames.size() > 1 && deviceNames[0].containsIgnoreCase (T("digidesign"))) - return 1; // (the digi m-box driver crashes the app when you run - // it in the debugger, which can be a bit annoying) + if (deviceNames.size() > 1 && deviceNames[0].containsIgnoreCase (T("digidesign"))) + return 1; // (the digi m-box driver crashes the app when you run + // it in the debugger, which can be a bit annoying) #endif - return 0; - } + return 0; + } - static int findFreeSlot() - { - for (int i = 0; i < numElementsInArray (currentASIODev); ++i) - if (currentASIODev[i] == 0) - return i; + static int findFreeSlot() + { + for (int i = 0; i < numElementsInArray (currentASIODev); ++i) + if (currentASIODev[i] == 0) + return i; - jassertfalse; // unfortunately you can only have a finite number - // of ASIO devices open at the same time.. - return -1; - } + jassertfalse; // unfortunately you can only have a finite number + // of ASIO devices open at the same time.. + return -1; + } - int getIndexOfDevice (AudioIODevice* d, const bool /*asInput*/) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + int getIndexOfDevice (AudioIODevice* d, const bool /*asInput*/) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - return d == 0 ? -1 : deviceNames.indexOf (d->getName()); - } + return d == 0 ? -1 : deviceNames.indexOf (d->getName()); + } - bool hasSeparateInputsAndOutputs() const { return false; } + bool hasSeparateInputsAndOutputs() const { return false; } - AudioIODevice* createDevice (const String& outputDeviceName, - const String& inputDeviceName) - { - // ASIO can't open two different devices for input and output - they must be the same one. - jassert (inputDeviceName == outputDeviceName || outputDeviceName.isEmpty() || inputDeviceName.isEmpty()); - jassert (hasScanned); // need to call scanForDevices() before doing this + AudioIODevice* createDevice (const String& outputDeviceName, + const String& inputDeviceName) + { + // ASIO can't open two different devices for input and output - they must be the same one. + jassert (inputDeviceName == outputDeviceName || outputDeviceName.isEmpty() || inputDeviceName.isEmpty()); + jassert (hasScanned); // need to call scanForDevices() before doing this - const int index = deviceNames.indexOf (outputDeviceName.isNotEmpty() ? outputDeviceName - : inputDeviceName); + const int index = deviceNames.indexOf (outputDeviceName.isNotEmpty() ? outputDeviceName + : inputDeviceName); - if (index >= 0) - { - const int freeSlot = findFreeSlot(); + if (index >= 0) + { + const int freeSlot = findFreeSlot(); - if (freeSlot >= 0) - return new ASIOAudioIODevice (outputDeviceName, *(classIds [index]), freeSlot, String::empty); - } + if (freeSlot >= 0) + return new ASIOAudioIODevice (outputDeviceName, *(classIds [index]), freeSlot, String::empty); + } - return 0; - } + return 0; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - StringArray deviceNames; - OwnedArray classIds; + StringArray deviceNames; + OwnedArray classIds; - bool hasScanned; + bool hasScanned; - static bool checkClassIsOk (const String& classId) - { - HKEY hk = 0; - bool ok = false; + static bool checkClassIsOk (const String& classId) + { + HKEY hk = 0; + bool ok = false; - if (RegOpenKeyA (HKEY_CLASSES_ROOT, "clsid", &hk) == ERROR_SUCCESS) - { - int index = 0; + if (RegOpenKeyA (HKEY_CLASSES_ROOT, "clsid", &hk) == ERROR_SUCCESS) + { + int index = 0; - for (;;) - { - char buf [512]; + for (;;) + { + char buf [512]; - if (RegEnumKeyA (hk, index++, buf, 512) == ERROR_SUCCESS) - { - if (classId.equalsIgnoreCase (buf)) - { - HKEY subKey, pathKey; + if (RegEnumKeyA (hk, index++, buf, 512) == ERROR_SUCCESS) + { + if (classId.equalsIgnoreCase (buf)) + { + HKEY subKey, pathKey; - if (RegOpenKeyExA (hk, buf, 0, KEY_READ, &subKey) == ERROR_SUCCESS) - { - if (RegOpenKeyExA (subKey, "InprocServer32", 0, KEY_READ, &pathKey) == ERROR_SUCCESS) - { - char pathName [600]; - DWORD dtype = REG_SZ; - DWORD dsize = sizeof (pathName); + if (RegOpenKeyExA (hk, buf, 0, KEY_READ, &subKey) == ERROR_SUCCESS) + { + if (RegOpenKeyExA (subKey, "InprocServer32", 0, KEY_READ, &pathKey) == ERROR_SUCCESS) + { + char pathName [600]; + DWORD dtype = REG_SZ; + DWORD dsize = sizeof (pathName); - if (RegQueryValueExA (pathKey, 0, 0, &dtype, - (LPBYTE) pathName, &dsize) == ERROR_SUCCESS) - { - OFSTRUCT of; - zerostruct (of); + if (RegQueryValueExA (pathKey, 0, 0, &dtype, + (LPBYTE) pathName, &dsize) == ERROR_SUCCESS) + { + OFSTRUCT of; + zerostruct (of); - of.cBytes = sizeof (of); + of.cBytes = sizeof (of); - ok = (OpenFile (String (pathName), &of, OF_EXIST) != 0); - } + ok = (OpenFile (String (pathName), &of, OF_EXIST) != 0); + } - RegCloseKey (pathKey); - } + RegCloseKey (pathKey); + } - RegCloseKey (subKey); - } + RegCloseKey (subKey); + } - break; - } - } - else - { - break; - } - } + break; + } + } + else + { + break; + } + } - RegCloseKey (hk); - } + RegCloseKey (hk); + } - return ok; - } + return ok; + } - void addDriverInfo (const String& keyName, HKEY hk) - { - HKEY subKey; + void addDriverInfo (const String& keyName, HKEY hk) + { + HKEY subKey; - if (RegOpenKeyExA (hk, keyName, 0, KEY_READ, &subKey) == ERROR_SUCCESS) - { - char buf [256]; - DWORD dtype = REG_SZ; - DWORD dsize = sizeof (buf); - zeromem (buf, dsize); + if (RegOpenKeyExA (hk, keyName, 0, KEY_READ, &subKey) == ERROR_SUCCESS) + { + char buf [256]; + DWORD dtype = REG_SZ; + DWORD dsize = sizeof (buf); + zeromem (buf, dsize); - if (RegQueryValueExA (subKey, "clsid", 0, &dtype, (LPBYTE) buf, &dsize) == ERROR_SUCCESS) - { - if (dsize > 0 && checkClassIsOk (buf)) - { - wchar_t classIdStr [130]; - MultiByteToWideChar (CP_ACP, 0, buf, -1, classIdStr, 128); + if (RegQueryValueExA (subKey, "clsid", 0, &dtype, (LPBYTE) buf, &dsize) == ERROR_SUCCESS) + { + if (dsize > 0 && checkClassIsOk (buf)) + { + wchar_t classIdStr [130]; + MultiByteToWideChar (CP_ACP, 0, buf, -1, classIdStr, 128); - String deviceName; - CLSID classId; + String deviceName; + CLSID classId; - if (CLSIDFromString ((LPOLESTR) classIdStr, &classId) == S_OK) - { - dtype = REG_SZ; - dsize = sizeof (buf); + if (CLSIDFromString ((LPOLESTR) classIdStr, &classId) == S_OK) + { + dtype = REG_SZ; + dsize = sizeof (buf); - if (RegQueryValueExA (subKey, "description", 0, &dtype, (LPBYTE) buf, &dsize) == ERROR_SUCCESS) - deviceName = buf; - else - deviceName = keyName; + if (RegQueryValueExA (subKey, "description", 0, &dtype, (LPBYTE) buf, &dsize) == ERROR_SUCCESS) + deviceName = buf; + else + deviceName = keyName; - log (T("found ") + deviceName); - deviceNames.add (deviceName); - classIds.add (new CLSID (classId)); - } - } + log (T("found ") + deviceName); + deviceNames.add (deviceName); + classIds.add (new CLSID (classId)); + } + } - RegCloseKey (subKey); - } - } - } + RegCloseKey (subKey); + } + } + } - ASIOAudioIODeviceType (const ASIOAudioIODeviceType&); - const ASIOAudioIODeviceType& operator= (const ASIOAudioIODeviceType&); + ASIOAudioIODeviceType (const ASIOAudioIODeviceType&); + const ASIOAudioIODeviceType& operator= (const ASIOAudioIODeviceType&); }; AudioIODeviceType* juce_createAudioIODeviceType_ASIO() { - return new ASIOAudioIODeviceType(); + return new ASIOAudioIODeviceType(); } AudioIODevice* juce_createASIOAudioIODeviceForGUID (const String& name, - void* guid, - const String& optionalDllForDirectLoading) + void* guid, + const String& optionalDllForDirectLoading) { - const int freeSlot = ASIOAudioIODeviceType::findFreeSlot(); + const int freeSlot = ASIOAudioIODeviceType::findFreeSlot(); - if (freeSlot < 0) - return 0; + if (freeSlot < 0) + return 0; - return new ASIOAudioIODevice (name, *(CLSID*) guid, freeSlot, optionalDllForDirectLoading); + return new ASIOAudioIODevice (name, *(CLSID*) guid, freeSlot, optionalDllForDirectLoading); } #undef log @@ -247177,12 +224911,12 @@ extern "C" // Declare just the minimum number of interfaces for the DSound objects that we need.. typedef struct typeDSBUFFERDESC { - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; - GUID guid3DAlgorithm; + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; + GUID guid3DAlgorithm; } DSBUFFERDESC; struct IDirectSoundBuffer; @@ -247191,53 +224925,53 @@ struct IDirectSoundBuffer; #define INTERFACE IDirectSound DECLARE_INTERFACE_(IDirectSound, IUnknown) { - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - STDMETHOD(CreateSoundBuffer) (THIS_ DSBUFFERDESC*, IDirectSoundBuffer**, LPUNKNOWN) PURE; - STDMETHOD(GetCaps) (THIS_ void*) PURE; - STDMETHOD(DuplicateSoundBuffer) (THIS_ IDirectSoundBuffer*, IDirectSoundBuffer**) PURE; - STDMETHOD(SetCooperativeLevel) (THIS_ HWND, DWORD) PURE; - STDMETHOD(Compact) (THIS) PURE; - STDMETHOD(GetSpeakerConfig) (THIS_ LPDWORD) PURE; - STDMETHOD(SetSpeakerConfig) (THIS_ DWORD) PURE; - STDMETHOD(Initialize) (THIS_ const GUID*) PURE; + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + STDMETHOD(CreateSoundBuffer) (THIS_ DSBUFFERDESC*, IDirectSoundBuffer**, LPUNKNOWN) PURE; + STDMETHOD(GetCaps) (THIS_ void*) PURE; + STDMETHOD(DuplicateSoundBuffer) (THIS_ IDirectSoundBuffer*, IDirectSoundBuffer**) PURE; + STDMETHOD(SetCooperativeLevel) (THIS_ HWND, DWORD) PURE; + STDMETHOD(Compact) (THIS) PURE; + STDMETHOD(GetSpeakerConfig) (THIS_ LPDWORD) PURE; + STDMETHOD(SetSpeakerConfig) (THIS_ DWORD) PURE; + STDMETHOD(Initialize) (THIS_ const GUID*) PURE; }; #undef INTERFACE #define INTERFACE IDirectSoundBuffer DECLARE_INTERFACE_(IDirectSoundBuffer, IUnknown) { - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - STDMETHOD(GetCaps) (THIS_ void*) PURE; - STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD, LPDWORD) PURE; - STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX, DWORD, LPDWORD) PURE; - STDMETHOD(GetVolume) (THIS_ LPLONG) PURE; - STDMETHOD(GetPan) (THIS_ LPLONG) PURE; - STDMETHOD(GetFrequency) (THIS_ LPDWORD) PURE; - STDMETHOD(GetStatus) (THIS_ LPDWORD) PURE; - STDMETHOD(Initialize) (THIS_ IDirectSound*, DSBUFFERDESC*) PURE; - STDMETHOD(Lock) (THIS_ DWORD, DWORD, LPVOID*, LPDWORD, LPVOID*, LPDWORD, DWORD) PURE; - STDMETHOD(Play) (THIS_ DWORD, DWORD, DWORD) PURE; - STDMETHOD(SetCurrentPosition) (THIS_ DWORD) PURE; - STDMETHOD(SetFormat) (THIS_ const WAVEFORMATEX*) PURE; - STDMETHOD(SetVolume) (THIS_ LONG) PURE; - STDMETHOD(SetPan) (THIS_ LONG) PURE; - STDMETHOD(SetFrequency) (THIS_ DWORD) PURE; - STDMETHOD(Stop) (THIS) PURE; - STDMETHOD(Unlock) (THIS_ LPVOID, DWORD, LPVOID, DWORD) PURE; - STDMETHOD(Restore) (THIS) PURE; + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + STDMETHOD(GetCaps) (THIS_ void*) PURE; + STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD, LPDWORD) PURE; + STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX, DWORD, LPDWORD) PURE; + STDMETHOD(GetVolume) (THIS_ LPLONG) PURE; + STDMETHOD(GetPan) (THIS_ LPLONG) PURE; + STDMETHOD(GetFrequency) (THIS_ LPDWORD) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD) PURE; + STDMETHOD(Initialize) (THIS_ IDirectSound*, DSBUFFERDESC*) PURE; + STDMETHOD(Lock) (THIS_ DWORD, DWORD, LPVOID*, LPDWORD, LPVOID*, LPDWORD, DWORD) PURE; + STDMETHOD(Play) (THIS_ DWORD, DWORD, DWORD) PURE; + STDMETHOD(SetCurrentPosition) (THIS_ DWORD) PURE; + STDMETHOD(SetFormat) (THIS_ const WAVEFORMATEX*) PURE; + STDMETHOD(SetVolume) (THIS_ LONG) PURE; + STDMETHOD(SetPan) (THIS_ LONG) PURE; + STDMETHOD(SetFrequency) (THIS_ DWORD) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID, DWORD, LPVOID, DWORD) PURE; + STDMETHOD(Restore) (THIS) PURE; }; typedef struct typeDSCBUFFERDESC { - DWORD dwSize; - DWORD dwFlags; - DWORD dwBufferBytes; - DWORD dwReserved; - LPWAVEFORMATEX lpwfxFormat; + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; } DSCBUFFERDESC; struct IDirectSoundCaptureBuffer; @@ -247246,30 +224980,30 @@ struct IDirectSoundCaptureBuffer; #define INTERFACE IDirectSoundCapture DECLARE_INTERFACE_(IDirectSoundCapture, IUnknown) { - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - STDMETHOD(CreateCaptureBuffer) (THIS_ DSCBUFFERDESC*, IDirectSoundCaptureBuffer**, LPUNKNOWN) PURE; - STDMETHOD(GetCaps) (THIS_ void*) PURE; - STDMETHOD(Initialize) (THIS_ const GUID*) PURE; + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + STDMETHOD(CreateCaptureBuffer) (THIS_ DSCBUFFERDESC*, IDirectSoundCaptureBuffer**, LPUNKNOWN) PURE; + STDMETHOD(GetCaps) (THIS_ void*) PURE; + STDMETHOD(Initialize) (THIS_ const GUID*) PURE; }; #undef INTERFACE #define INTERFACE IDirectSoundCaptureBuffer DECLARE_INTERFACE_(IDirectSoundCaptureBuffer, IUnknown) { - STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; - STDMETHOD(GetCaps) (THIS_ void*) PURE; - STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD, LPDWORD) PURE; - STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX, DWORD, LPDWORD) PURE; - STDMETHOD(GetStatus) (THIS_ LPDWORD) PURE; - STDMETHOD(Initialize) (THIS_ IDirectSoundCapture*, DSCBUFFERDESC*) PURE; - STDMETHOD(Lock) (THIS_ DWORD, DWORD, LPVOID*, LPDWORD, LPVOID*, LPDWORD, DWORD) PURE; - STDMETHOD(Start) (THIS_ DWORD) PURE; - STDMETHOD(Stop) (THIS) PURE; - STDMETHOD(Unlock) (THIS_ LPVOID, DWORD, LPVOID, DWORD) PURE; + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + STDMETHOD(GetCaps) (THIS_ void*) PURE; + STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD, LPDWORD) PURE; + STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX, DWORD, LPDWORD) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD) PURE; + STDMETHOD(Initialize) (THIS_ IDirectSoundCapture*, DSCBUFFERDESC*) PURE; + STDMETHOD(Lock) (THIS_ DWORD, DWORD, LPVOID*, LPDWORD, LPVOID*, LPDWORD, DWORD) PURE; + STDMETHOD(Start) (THIS_ DWORD) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID, DWORD, LPVOID, DWORD) PURE; }; }; @@ -247278,100 +225012,100 @@ BEGIN_JUCE_NAMESPACE static const String getDSErrorMessage (HRESULT hr) { - const char* result = 0; + const char* result = 0; - switch (hr) - { - case MAKE_HRESULT(1, 0x878, 10): - result = "Device already allocated"; - break; - case MAKE_HRESULT(1, 0x878, 30): - result = "Control unavailable"; - break; - case E_INVALIDARG: - result = "Invalid parameter"; - break; - case MAKE_HRESULT(1, 0x878, 50): - result = "Invalid call"; - break; - case E_FAIL: - result = "Generic error"; - break; - case MAKE_HRESULT(1, 0x878, 70): - result = "Priority level error"; - break; - case E_OUTOFMEMORY: - result = "Out of memory"; - break; - case MAKE_HRESULT(1, 0x878, 100): - result = "Bad format"; - break; - case E_NOTIMPL: - result = "Unsupported function"; - break; - case MAKE_HRESULT(1, 0x878, 120): - result = "No driver"; - break; - case MAKE_HRESULT(1, 0x878, 130): - result = "Already initialised"; - break; - case CLASS_E_NOAGGREGATION: - result = "No aggregation"; - break; - case MAKE_HRESULT(1, 0x878, 150): - result = "Buffer lost"; - break; - case MAKE_HRESULT(1, 0x878, 160): - result = "Another app has priority"; - break; - case MAKE_HRESULT(1, 0x878, 170): - result = "Uninitialised"; - break; - case E_NOINTERFACE: - result = "No interface"; - break; - case S_OK: - result = "No error"; - break; + switch (hr) + { + case MAKE_HRESULT(1, 0x878, 10): + result = "Device already allocated"; + break; + case MAKE_HRESULT(1, 0x878, 30): + result = "Control unavailable"; + break; + case E_INVALIDARG: + result = "Invalid parameter"; + break; + case MAKE_HRESULT(1, 0x878, 50): + result = "Invalid call"; + break; + case E_FAIL: + result = "Generic error"; + break; + case MAKE_HRESULT(1, 0x878, 70): + result = "Priority level error"; + break; + case E_OUTOFMEMORY: + result = "Out of memory"; + break; + case MAKE_HRESULT(1, 0x878, 100): + result = "Bad format"; + break; + case E_NOTIMPL: + result = "Unsupported function"; + break; + case MAKE_HRESULT(1, 0x878, 120): + result = "No driver"; + break; + case MAKE_HRESULT(1, 0x878, 130): + result = "Already initialised"; + break; + case CLASS_E_NOAGGREGATION: + result = "No aggregation"; + break; + case MAKE_HRESULT(1, 0x878, 150): + result = "Buffer lost"; + break; + case MAKE_HRESULT(1, 0x878, 160): + result = "Another app has priority"; + break; + case MAKE_HRESULT(1, 0x878, 170): + result = "Uninitialised"; + break; + case E_NOINTERFACE: + result = "No interface"; + break; + case S_OK: + result = "No error"; + break; - default: - return "Unknown error: " + String ((int) hr); - } + default: + return "Unknown error: " + String ((int) hr); + } - return result; + return result; } #define DS_DEBUGGING 1 #ifdef DS_DEBUGGING - #define CATCH JUCE_CATCH_EXCEPTION - #undef log - #define log(a) Logger::writeToLog(a); - #undef logError - #define logError(a) logDSError(a, __LINE__); + #define CATCH JUCE_CATCH_EXCEPTION + #undef log + #define log(a) Logger::writeToLog(a); + #undef logError + #define logError(a) logDSError(a, __LINE__); - static void logDSError (HRESULT hr, int lineNum) - { - if (hr != S_OK) - { - String error ("DS error at line "); - error << lineNum << T(" - ") << getDSErrorMessage (hr); - log (error); - } - } + static void logDSError (HRESULT hr, int lineNum) + { + if (hr != S_OK) + { + String error ("DS error at line "); + error << lineNum << T(" - ") << getDSErrorMessage (hr); + log (error); + } + } #else - #define CATCH JUCE_CATCH_ALL - #define log(a) - #define logError(a) + #define CATCH JUCE_CATCH_ALL + #define log(a) + #define logError(a) #endif #define DSOUND_FUNCTION(functionName, params) \ - typedef HRESULT (WINAPI *type##functionName) params; \ - static type##functionName ds##functionName = 0; + typedef HRESULT (WINAPI *type##functionName) params; \ + static type##functionName ds##functionName = 0; #define DSOUND_FUNCTION_LOAD(functionName) \ - ds##functionName = (type##functionName) GetProcAddress (h, #functionName); \ - jassert (ds##functionName != 0); + ds##functionName = (type##functionName) GetProcAddress (h, #functionName); \ + jassert (ds##functionName != 0); typedef BOOL (CALLBACK *LPDSENUMCALLBACKW) (LPGUID, LPCWSTR, LPCWSTR, LPVOID); typedef BOOL (CALLBACK *LPDSENUMCALLBACKA) (LPGUID, LPCSTR, LPCSTR, LPVOID); @@ -247383,1382 +225117,1380 @@ DSOUND_FUNCTION (DirectSoundCaptureEnumerateW, (LPDSENUMCALLBACKW, LPVOID)) static void initialiseDSoundFunctions() { - if (dsDirectSoundCreate == 0) - { - HMODULE h = LoadLibraryA ("dsound.dll"); + if (dsDirectSoundCreate == 0) + { + HMODULE h = LoadLibraryA ("dsound.dll"); - DSOUND_FUNCTION_LOAD (DirectSoundCreate) - DSOUND_FUNCTION_LOAD (DirectSoundCaptureCreate) - DSOUND_FUNCTION_LOAD (DirectSoundEnumerateW) - DSOUND_FUNCTION_LOAD (DirectSoundCaptureEnumerateW) - } + DSOUND_FUNCTION_LOAD (DirectSoundCreate) + DSOUND_FUNCTION_LOAD (DirectSoundCaptureCreate) + DSOUND_FUNCTION_LOAD (DirectSoundEnumerateW) + DSOUND_FUNCTION_LOAD (DirectSoundCaptureEnumerateW) + } } class DSoundInternalOutChannel { - String name; - LPGUID guid; - int sampleRate, bufferSizeSamples; - float* leftBuffer; - float* rightBuffer; + String name; + LPGUID guid; + int sampleRate, bufferSizeSamples; + float* leftBuffer; + float* rightBuffer; - IDirectSound* pDirectSound; - IDirectSoundBuffer* pOutputBuffer; - DWORD writeOffset; - int totalBytesPerBuffer; - int bytesPerBuffer; - unsigned int lastPlayCursor; + IDirectSound* pDirectSound; + IDirectSoundBuffer* pOutputBuffer; + DWORD writeOffset; + int totalBytesPerBuffer; + int bytesPerBuffer; + unsigned int lastPlayCursor; public: - int bitDepth; - bool doneFlag; - - DSoundInternalOutChannel (const String& name_, - LPGUID guid_, - int rate, - int bufferSize, - float* left, - float* right) - : name (name_), - guid (guid_), - sampleRate (rate), - bufferSizeSamples (bufferSize), - leftBuffer (left), - rightBuffer (right), - pDirectSound (0), - pOutputBuffer (0), - bitDepth (16) - { - } - - ~DSoundInternalOutChannel() - { - close(); - } - - void close() - { - HRESULT hr; - - if (pOutputBuffer != 0) - { - JUCE_TRY - { - log (T("closing dsound out: ") + name); - hr = pOutputBuffer->Stop(); - logError (hr); - } - CATCH - - JUCE_TRY - { - hr = pOutputBuffer->Release(); - logError (hr); - } - CATCH - - pOutputBuffer = 0; - } - - if (pDirectSound != 0) - { - JUCE_TRY - { - hr = pDirectSound->Release(); - logError (hr); - } - CATCH - - pDirectSound = 0; - } - } - - const String open() - { - log (T("opening dsound out device: ") + name - + T(" rate=") + String (sampleRate) - + T(" bits=") + String (bitDepth) - + T(" buf=") + String (bufferSizeSamples)); - - pDirectSound = 0; - pOutputBuffer = 0; - writeOffset = 0; - - String error; - HRESULT hr = E_NOINTERFACE; - - if (dsDirectSoundCreate != 0) - hr = dsDirectSoundCreate (guid, &pDirectSound, 0); - - if (hr == S_OK) - { - bytesPerBuffer = (bufferSizeSamples * (bitDepth >> 2)) & ~15; - totalBytesPerBuffer = (3 * bytesPerBuffer) & ~15; - const int numChannels = 2; - - hr = pDirectSound->SetCooperativeLevel (GetDesktopWindow(), 2 /* DSSCL_PRIORITY */); - logError (hr); - - if (hr == S_OK) - { - IDirectSoundBuffer* pPrimaryBuffer; - - DSBUFFERDESC primaryDesc; - zerostruct (primaryDesc); - - primaryDesc.dwSize = sizeof (DSBUFFERDESC); - primaryDesc.dwFlags = 1 /* DSBCAPS_PRIMARYBUFFER */; - primaryDesc.dwBufferBytes = 0; - primaryDesc.lpwfxFormat = 0; - - log ("opening dsound out step 2"); - hr = pDirectSound->CreateSoundBuffer (&primaryDesc, &pPrimaryBuffer, 0); - logError (hr); - - if (hr == S_OK) - { - WAVEFORMATEX wfFormat; - wfFormat.wFormatTag = WAVE_FORMAT_PCM; - wfFormat.nChannels = (unsigned short) numChannels; - wfFormat.nSamplesPerSec = sampleRate; - wfFormat.wBitsPerSample = (unsigned short) bitDepth; - wfFormat.nBlockAlign = (unsigned short) (wfFormat.nChannels * wfFormat.wBitsPerSample / 8); - wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign; - wfFormat.cbSize = 0; - - hr = pPrimaryBuffer->SetFormat (&wfFormat); - logError (hr); - - if (hr == S_OK) - { - DSBUFFERDESC secondaryDesc; - zerostruct (secondaryDesc); - - secondaryDesc.dwSize = sizeof (DSBUFFERDESC); - secondaryDesc.dwFlags = 0x8000 /* DSBCAPS_GLOBALFOCUS */ - | 0x10000 /* DSBCAPS_GETCURRENTPOSITION2 */; - secondaryDesc.dwBufferBytes = totalBytesPerBuffer; - secondaryDesc.lpwfxFormat = &wfFormat; - - hr = pDirectSound->CreateSoundBuffer (&secondaryDesc, &pOutputBuffer, 0); - logError (hr); - - if (hr == S_OK) - { - log ("opening dsound out step 3"); - - DWORD dwDataLen; - unsigned char* pDSBuffData; - - hr = pOutputBuffer->Lock (0, totalBytesPerBuffer, - (LPVOID*) &pDSBuffData, &dwDataLen, 0, 0, 0); - logError (hr); - - if (hr == S_OK) - { - zeromem (pDSBuffData, dwDataLen); - - hr = pOutputBuffer->Unlock (pDSBuffData, dwDataLen, 0, 0); - - if (hr == S_OK) - { - hr = pOutputBuffer->SetCurrentPosition (0); - - if (hr == S_OK) - { - hr = pOutputBuffer->Play (0, 0, 1 /* DSBPLAY_LOOPING */); - - if (hr == S_OK) - return String::empty; - } - } - } - } - } - } - } - } - - error = getDSErrorMessage (hr); - close(); - return error; - } - - void synchronisePosition() - { - if (pOutputBuffer != 0) - { - DWORD playCursor; - pOutputBuffer->GetCurrentPosition (&playCursor, &writeOffset); - } - } - - bool service() - { - if (pOutputBuffer == 0) - return true; - - DWORD playCursor, writeCursor; - - for (;;) - { - HRESULT hr = pOutputBuffer->GetCurrentPosition (&playCursor, &writeCursor); - - if (hr == MAKE_HRESULT (1, 0x878, 150)) // DSERR_BUFFERLOST - { - pOutputBuffer->Restore(); - continue; - } - - if (hr == S_OK) - break; - - logError (hr); - jassertfalse - return true; - } - - int playWriteGap = writeCursor - playCursor; - if (playWriteGap < 0) - playWriteGap += totalBytesPerBuffer; - - int bytesEmpty = playCursor - writeOffset; - - if (bytesEmpty < 0) - bytesEmpty += totalBytesPerBuffer; - - if (bytesEmpty > (totalBytesPerBuffer - playWriteGap)) - { - writeOffset = writeCursor; - bytesEmpty = totalBytesPerBuffer - playWriteGap; - } - - if (bytesEmpty >= bytesPerBuffer) - { - LPBYTE lpbuf1 = 0; - LPBYTE lpbuf2 = 0; - DWORD dwSize1 = 0; - DWORD dwSize2 = 0; - - HRESULT hr = pOutputBuffer->Lock (writeOffset, - bytesPerBuffer, - (void**) &lpbuf1, &dwSize1, - (void**) &lpbuf2, &dwSize2, 0); - - if (hr == MAKE_HRESULT (1, 0x878, 150)) // DSERR_BUFFERLOST - { - pOutputBuffer->Restore(); - - hr = pOutputBuffer->Lock (writeOffset, - bytesPerBuffer, - (void**) &lpbuf1, &dwSize1, - (void**) &lpbuf2, &dwSize2, 0); - } - - if (hr == S_OK) - { - if (bitDepth == 16) - { - const float gainL = 32767.0f; - const float gainR = 32767.0f; - - int* dest = (int*)lpbuf1; - const float* left = leftBuffer; - const float* right = rightBuffer; - int samples1 = dwSize1 >> 2; - int samples2 = dwSize2 >> 2; - - if (left == 0) - { - while (--samples1 >= 0) - { - int r = roundFloatToInt (gainR * *right++); - - if (r < -32768) - r = -32768; - else if (r > 32767) - r = 32767; - - *dest++ = (r << 16); - } - - dest = (int*)lpbuf2; - - while (--samples2 >= 0) - { - int r = roundFloatToInt (gainR * *right++); - - if (r < -32768) - r = -32768; - else if (r > 32767) - r = 32767; - - *dest++ = (r << 16); - } - } - else if (right == 0) - { - while (--samples1 >= 0) - { - int l = roundFloatToInt (gainL * *left++); - - if (l < -32768) - l = -32768; - else if (l > 32767) - l = 32767; - - l &= 0xffff; - - *dest++ = l; - } - - dest = (int*)lpbuf2; - - while (--samples2 >= 0) - { - int l = roundFloatToInt (gainL * *left++); - - if (l < -32768) - l = -32768; - else if (l > 32767) - l = 32767; - - l &= 0xffff; - - *dest++ = l; - } - } - else - { - while (--samples1 >= 0) - { - int l = roundFloatToInt (gainL * *left++); - - if (l < -32768) - l = -32768; - else if (l > 32767) - l = 32767; - - l &= 0xffff; - - int r = roundFloatToInt (gainR * *right++); - - if (r < -32768) - r = -32768; - else if (r > 32767) - r = 32767; - - *dest++ = (r << 16) | l; - } - - dest = (int*)lpbuf2; - - while (--samples2 >= 0) - { - int l = roundFloatToInt (gainL * *left++); - - if (l < -32768) - l = -32768; - else if (l > 32767) - l = 32767; - - l &= 0xffff; - - int r = roundFloatToInt (gainR * *right++); - - if (r < -32768) - r = -32768; - else if (r > 32767) - r = 32767; - - *dest++ = (r << 16) | l; - } - } - } - else - { - jassertfalse - } - - writeOffset = (writeOffset + dwSize1 + dwSize2) % totalBytesPerBuffer; - - pOutputBuffer->Unlock (lpbuf1, dwSize1, lpbuf2, dwSize2); - } - else - { - jassertfalse - logError (hr); - } - - bytesEmpty -= bytesPerBuffer; - - return true; - } - else - { - return false; - } - } + int bitDepth; + bool doneFlag; + + DSoundInternalOutChannel (const String& name_, + LPGUID guid_, + int rate, + int bufferSize, + float* left, + float* right) + : name (name_), + guid (guid_), + sampleRate (rate), + bufferSizeSamples (bufferSize), + leftBuffer (left), + rightBuffer (right), + pDirectSound (0), + pOutputBuffer (0), + bitDepth (16) + { + } + + ~DSoundInternalOutChannel() + { + close(); + } + + void close() + { + HRESULT hr; + + if (pOutputBuffer != 0) + { + JUCE_TRY + { + log (T("closing dsound out: ") + name); + hr = pOutputBuffer->Stop(); + logError (hr); + } + CATCH + + JUCE_TRY + { + hr = pOutputBuffer->Release(); + logError (hr); + } + CATCH + + pOutputBuffer = 0; + } + + if (pDirectSound != 0) + { + JUCE_TRY + { + hr = pDirectSound->Release(); + logError (hr); + } + CATCH + + pDirectSound = 0; + } + } + + const String open() + { + log (T("opening dsound out device: ") + name + + T(" rate=") + String (sampleRate) + + T(" bits=") + String (bitDepth) + + T(" buf=") + String (bufferSizeSamples)); + + pDirectSound = 0; + pOutputBuffer = 0; + writeOffset = 0; + + String error; + HRESULT hr = E_NOINTERFACE; + + if (dsDirectSoundCreate != 0) + hr = dsDirectSoundCreate (guid, &pDirectSound, 0); + + if (hr == S_OK) + { + bytesPerBuffer = (bufferSizeSamples * (bitDepth >> 2)) & ~15; + totalBytesPerBuffer = (3 * bytesPerBuffer) & ~15; + const int numChannels = 2; + + hr = pDirectSound->SetCooperativeLevel (GetDesktopWindow(), 2 /* DSSCL_PRIORITY */); + logError (hr); + + if (hr == S_OK) + { + IDirectSoundBuffer* pPrimaryBuffer; + + DSBUFFERDESC primaryDesc; + zerostruct (primaryDesc); + + primaryDesc.dwSize = sizeof (DSBUFFERDESC); + primaryDesc.dwFlags = 1 /* DSBCAPS_PRIMARYBUFFER */; + primaryDesc.dwBufferBytes = 0; + primaryDesc.lpwfxFormat = 0; + + log ("opening dsound out step 2"); + hr = pDirectSound->CreateSoundBuffer (&primaryDesc, &pPrimaryBuffer, 0); + logError (hr); + + if (hr == S_OK) + { + WAVEFORMATEX wfFormat; + wfFormat.wFormatTag = WAVE_FORMAT_PCM; + wfFormat.nChannels = (unsigned short) numChannels; + wfFormat.nSamplesPerSec = sampleRate; + wfFormat.wBitsPerSample = (unsigned short) bitDepth; + wfFormat.nBlockAlign = (unsigned short) (wfFormat.nChannels * wfFormat.wBitsPerSample / 8); + wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign; + wfFormat.cbSize = 0; + + hr = pPrimaryBuffer->SetFormat (&wfFormat); + logError (hr); + + if (hr == S_OK) + { + DSBUFFERDESC secondaryDesc; + zerostruct (secondaryDesc); + + secondaryDesc.dwSize = sizeof (DSBUFFERDESC); + secondaryDesc.dwFlags = 0x8000 /* DSBCAPS_GLOBALFOCUS */ + | 0x10000 /* DSBCAPS_GETCURRENTPOSITION2 */; + secondaryDesc.dwBufferBytes = totalBytesPerBuffer; + secondaryDesc.lpwfxFormat = &wfFormat; + + hr = pDirectSound->CreateSoundBuffer (&secondaryDesc, &pOutputBuffer, 0); + logError (hr); + + if (hr == S_OK) + { + log ("opening dsound out step 3"); + + DWORD dwDataLen; + unsigned char* pDSBuffData; + + hr = pOutputBuffer->Lock (0, totalBytesPerBuffer, + (LPVOID*) &pDSBuffData, &dwDataLen, 0, 0, 0); + logError (hr); + + if (hr == S_OK) + { + zeromem (pDSBuffData, dwDataLen); + + hr = pOutputBuffer->Unlock (pDSBuffData, dwDataLen, 0, 0); + + if (hr == S_OK) + { + hr = pOutputBuffer->SetCurrentPosition (0); + + if (hr == S_OK) + { + hr = pOutputBuffer->Play (0, 0, 1 /* DSBPLAY_LOOPING */); + + if (hr == S_OK) + return String::empty; + } + } + } + } + } + } + } + } + + error = getDSErrorMessage (hr); + close(); + return error; + } + + void synchronisePosition() + { + if (pOutputBuffer != 0) + { + DWORD playCursor; + pOutputBuffer->GetCurrentPosition (&playCursor, &writeOffset); + } + } + + bool service() + { + if (pOutputBuffer == 0) + return true; + + DWORD playCursor, writeCursor; + + for (;;) + { + HRESULT hr = pOutputBuffer->GetCurrentPosition (&playCursor, &writeCursor); + + if (hr == MAKE_HRESULT (1, 0x878, 150)) // DSERR_BUFFERLOST + { + pOutputBuffer->Restore(); + continue; + } + + if (hr == S_OK) + break; + + logError (hr); + jassertfalse + return true; + } + + int playWriteGap = writeCursor - playCursor; + if (playWriteGap < 0) + playWriteGap += totalBytesPerBuffer; + + int bytesEmpty = playCursor - writeOffset; + + if (bytesEmpty < 0) + bytesEmpty += totalBytesPerBuffer; + + if (bytesEmpty > (totalBytesPerBuffer - playWriteGap)) + { + writeOffset = writeCursor; + bytesEmpty = totalBytesPerBuffer - playWriteGap; + } + + if (bytesEmpty >= bytesPerBuffer) + { + LPBYTE lpbuf1 = 0; + LPBYTE lpbuf2 = 0; + DWORD dwSize1 = 0; + DWORD dwSize2 = 0; + + HRESULT hr = pOutputBuffer->Lock (writeOffset, + bytesPerBuffer, + (void**) &lpbuf1, &dwSize1, + (void**) &lpbuf2, &dwSize2, 0); + + if (hr == MAKE_HRESULT (1, 0x878, 150)) // DSERR_BUFFERLOST + { + pOutputBuffer->Restore(); + + hr = pOutputBuffer->Lock (writeOffset, + bytesPerBuffer, + (void**) &lpbuf1, &dwSize1, + (void**) &lpbuf2, &dwSize2, 0); + } + + if (hr == S_OK) + { + if (bitDepth == 16) + { + const float gainL = 32767.0f; + const float gainR = 32767.0f; + + int* dest = (int*)lpbuf1; + const float* left = leftBuffer; + const float* right = rightBuffer; + int samples1 = dwSize1 >> 2; + int samples2 = dwSize2 >> 2; + + if (left == 0) + { + while (--samples1 >= 0) + { + int r = roundToInt (gainR * *right++); + + if (r < -32768) + r = -32768; + else if (r > 32767) + r = 32767; + + *dest++ = (r << 16); + } + + dest = (int*)lpbuf2; + + while (--samples2 >= 0) + { + int r = roundToInt (gainR * *right++); + + if (r < -32768) + r = -32768; + else if (r > 32767) + r = 32767; + + *dest++ = (r << 16); + } + } + else if (right == 0) + { + while (--samples1 >= 0) + { + int l = roundToInt (gainL * *left++); + + if (l < -32768) + l = -32768; + else if (l > 32767) + l = 32767; + + l &= 0xffff; + + *dest++ = l; + } + + dest = (int*)lpbuf2; + + while (--samples2 >= 0) + { + int l = roundToInt (gainL * *left++); + + if (l < -32768) + l = -32768; + else if (l > 32767) + l = 32767; + + l &= 0xffff; + + *dest++ = l; + } + } + else + { + while (--samples1 >= 0) + { + int l = roundToInt (gainL * *left++); + + if (l < -32768) + l = -32768; + else if (l > 32767) + l = 32767; + + l &= 0xffff; + + int r = roundToInt (gainR * *right++); + + if (r < -32768) + r = -32768; + else if (r > 32767) + r = 32767; + + *dest++ = (r << 16) | l; + } + + dest = (int*)lpbuf2; + + while (--samples2 >= 0) + { + int l = roundToInt (gainL * *left++); + + if (l < -32768) + l = -32768; + else if (l > 32767) + l = 32767; + + l &= 0xffff; + + int r = roundToInt (gainR * *right++); + + if (r < -32768) + r = -32768; + else if (r > 32767) + r = 32767; + + *dest++ = (r << 16) | l; + } + } + } + else + { + jassertfalse + } + + writeOffset = (writeOffset + dwSize1 + dwSize2) % totalBytesPerBuffer; + + pOutputBuffer->Unlock (lpbuf1, dwSize1, lpbuf2, dwSize2); + } + else + { + jassertfalse + logError (hr); + } + + bytesEmpty -= bytesPerBuffer; + + return true; + } + else + { + return false; + } + } }; struct DSoundInternalInChannel { - String name; - LPGUID guid; - int sampleRate, bufferSizeSamples; - float* leftBuffer; - float* rightBuffer; + String name; + LPGUID guid; + int sampleRate, bufferSizeSamples; + float* leftBuffer; + float* rightBuffer; - IDirectSound* pDirectSound; - IDirectSoundCapture* pDirectSoundCapture; - IDirectSoundCaptureBuffer* pInputBuffer; + IDirectSound* pDirectSound; + IDirectSoundCapture* pDirectSoundCapture; + IDirectSoundCaptureBuffer* pInputBuffer; public: - unsigned int readOffset; - int bytesPerBuffer, totalBytesPerBuffer; - int bitDepth; - bool doneFlag; + unsigned int readOffset; + int bytesPerBuffer, totalBytesPerBuffer; + int bitDepth; + bool doneFlag; - DSoundInternalInChannel (const String& name_, - LPGUID guid_, - int rate, - int bufferSize, - float* left, - float* right) - : name (name_), - guid (guid_), - sampleRate (rate), - bufferSizeSamples (bufferSize), - leftBuffer (left), - rightBuffer (right), - pDirectSound (0), - pDirectSoundCapture (0), - pInputBuffer (0), - bitDepth (16) - { - } + DSoundInternalInChannel (const String& name_, + LPGUID guid_, + int rate, + int bufferSize, + float* left, + float* right) + : name (name_), + guid (guid_), + sampleRate (rate), + bufferSizeSamples (bufferSize), + leftBuffer (left), + rightBuffer (right), + pDirectSound (0), + pDirectSoundCapture (0), + pInputBuffer (0), + bitDepth (16) + { + } - ~DSoundInternalInChannel() - { - close(); - } + ~DSoundInternalInChannel() + { + close(); + } - void close() - { - HRESULT hr; + void close() + { + HRESULT hr; - if (pInputBuffer != 0) - { - JUCE_TRY - { - log (T("closing dsound in: ") + name); - hr = pInputBuffer->Stop(); - logError (hr); - } - CATCH + if (pInputBuffer != 0) + { + JUCE_TRY + { + log (T("closing dsound in: ") + name); + hr = pInputBuffer->Stop(); + logError (hr); + } + CATCH - JUCE_TRY - { - hr = pInputBuffer->Release(); - logError (hr); - } - CATCH + JUCE_TRY + { + hr = pInputBuffer->Release(); + logError (hr); + } + CATCH - pInputBuffer = 0; - } + pInputBuffer = 0; + } - if (pDirectSoundCapture != 0) - { - JUCE_TRY - { - hr = pDirectSoundCapture->Release(); - logError (hr); - } - CATCH + if (pDirectSoundCapture != 0) + { + JUCE_TRY + { + hr = pDirectSoundCapture->Release(); + logError (hr); + } + CATCH - pDirectSoundCapture = 0; - } + pDirectSoundCapture = 0; + } - if (pDirectSound != 0) - { - JUCE_TRY - { - hr = pDirectSound->Release(); - logError (hr); - } - CATCH + if (pDirectSound != 0) + { + JUCE_TRY + { + hr = pDirectSound->Release(); + logError (hr); + } + CATCH - pDirectSound = 0; - } - } + pDirectSound = 0; + } + } - const String open() - { - log (T("opening dsound in device: ") + name - + T(" rate=") + String (sampleRate) + T(" bits=") + String (bitDepth) + T(" buf=") + String (bufferSizeSamples)); + const String open() + { + log (T("opening dsound in device: ") + name + + T(" rate=") + String (sampleRate) + T(" bits=") + String (bitDepth) + T(" buf=") + String (bufferSizeSamples)); - pDirectSound = 0; - pDirectSoundCapture = 0; - pInputBuffer = 0; - readOffset = 0; - totalBytesPerBuffer = 0; + pDirectSound = 0; + pDirectSoundCapture = 0; + pInputBuffer = 0; + readOffset = 0; + totalBytesPerBuffer = 0; - String error; - HRESULT hr = E_NOINTERFACE; + String error; + HRESULT hr = E_NOINTERFACE; - if (dsDirectSoundCaptureCreate != 0) - hr = dsDirectSoundCaptureCreate (guid, &pDirectSoundCapture, 0); + if (dsDirectSoundCaptureCreate != 0) + hr = dsDirectSoundCaptureCreate (guid, &pDirectSoundCapture, 0); - logError (hr); + logError (hr); - if (hr == S_OK) - { - const int numChannels = 2; - bytesPerBuffer = (bufferSizeSamples * (bitDepth >> 2)) & ~15; - totalBytesPerBuffer = (3 * bytesPerBuffer) & ~15; + if (hr == S_OK) + { + const int numChannels = 2; + bytesPerBuffer = (bufferSizeSamples * (bitDepth >> 2)) & ~15; + totalBytesPerBuffer = (3 * bytesPerBuffer) & ~15; - WAVEFORMATEX wfFormat; - wfFormat.wFormatTag = WAVE_FORMAT_PCM; - wfFormat.nChannels = (unsigned short)numChannels; - wfFormat.nSamplesPerSec = sampleRate; - wfFormat.wBitsPerSample = (unsigned short)bitDepth; - wfFormat.nBlockAlign = (unsigned short)(wfFormat.nChannels * (wfFormat.wBitsPerSample / 8)); - wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign; - wfFormat.cbSize = 0; + WAVEFORMATEX wfFormat; + wfFormat.wFormatTag = WAVE_FORMAT_PCM; + wfFormat.nChannels = (unsigned short)numChannels; + wfFormat.nSamplesPerSec = sampleRate; + wfFormat.wBitsPerSample = (unsigned short)bitDepth; + wfFormat.nBlockAlign = (unsigned short)(wfFormat.nChannels * (wfFormat.wBitsPerSample / 8)); + wfFormat.nAvgBytesPerSec = wfFormat.nSamplesPerSec * wfFormat.nBlockAlign; + wfFormat.cbSize = 0; - DSCBUFFERDESC captureDesc; - zerostruct (captureDesc); + DSCBUFFERDESC captureDesc; + zerostruct (captureDesc); - captureDesc.dwSize = sizeof (DSCBUFFERDESC); - captureDesc.dwFlags = 0; - captureDesc.dwBufferBytes = totalBytesPerBuffer; - captureDesc.lpwfxFormat = &wfFormat; + captureDesc.dwSize = sizeof (DSCBUFFERDESC); + captureDesc.dwFlags = 0; + captureDesc.dwBufferBytes = totalBytesPerBuffer; + captureDesc.lpwfxFormat = &wfFormat; - log (T("opening dsound in step 2")); - hr = pDirectSoundCapture->CreateCaptureBuffer (&captureDesc, &pInputBuffer, 0); + log (T("opening dsound in step 2")); + hr = pDirectSoundCapture->CreateCaptureBuffer (&captureDesc, &pInputBuffer, 0); - logError (hr); + logError (hr); - if (hr == S_OK) - { - hr = pInputBuffer->Start (1 /* DSCBSTART_LOOPING */); - logError (hr); + if (hr == S_OK) + { + hr = pInputBuffer->Start (1 /* DSCBSTART_LOOPING */); + logError (hr); - if (hr == S_OK) - return String::empty; - } - } + if (hr == S_OK) + return String::empty; + } + } - error = getDSErrorMessage (hr); - close(); + error = getDSErrorMessage (hr); + close(); - return error; - } + return error; + } - void synchronisePosition() - { - if (pInputBuffer != 0) - { - DWORD capturePos; - pInputBuffer->GetCurrentPosition (&capturePos, (DWORD*)&readOffset); - } - } + void synchronisePosition() + { + if (pInputBuffer != 0) + { + DWORD capturePos; + pInputBuffer->GetCurrentPosition (&capturePos, (DWORD*)&readOffset); + } + } - bool service() - { - if (pInputBuffer == 0) - return true; + bool service() + { + if (pInputBuffer == 0) + return true; - DWORD capturePos, readPos; - HRESULT hr = pInputBuffer->GetCurrentPosition (&capturePos, &readPos); - logError (hr); + DWORD capturePos, readPos; + HRESULT hr = pInputBuffer->GetCurrentPosition (&capturePos, &readPos); + logError (hr); - if (hr != S_OK) - return true; + if (hr != S_OK) + return true; - int bytesFilled = readPos - readOffset; - if (bytesFilled < 0) - bytesFilled += totalBytesPerBuffer; + int bytesFilled = readPos - readOffset; + if (bytesFilled < 0) + bytesFilled += totalBytesPerBuffer; - if (bytesFilled >= bytesPerBuffer) - { - LPBYTE lpbuf1 = 0; - LPBYTE lpbuf2 = 0; - DWORD dwsize1 = 0; - DWORD dwsize2 = 0; + if (bytesFilled >= bytesPerBuffer) + { + LPBYTE lpbuf1 = 0; + LPBYTE lpbuf2 = 0; + DWORD dwsize1 = 0; + DWORD dwsize2 = 0; - HRESULT hr = pInputBuffer->Lock (readOffset, - bytesPerBuffer, - (void**) &lpbuf1, &dwsize1, - (void**) &lpbuf2, &dwsize2, 0); + HRESULT hr = pInputBuffer->Lock (readOffset, + bytesPerBuffer, + (void**) &lpbuf1, &dwsize1, + (void**) &lpbuf2, &dwsize2, 0); - if (hr == S_OK) - { - if (bitDepth == 16) - { - const float g = 1.0f / 32768.0f; + if (hr == S_OK) + { + if (bitDepth == 16) + { + const float g = 1.0f / 32768.0f; - float* destL = leftBuffer; - float* destR = rightBuffer; - int samples1 = dwsize1 >> 2; - int samples2 = dwsize2 >> 2; + float* destL = leftBuffer; + float* destR = rightBuffer; + int samples1 = dwsize1 >> 2; + int samples2 = dwsize2 >> 2; - const short* src = (const short*)lpbuf1; + const short* src = (const short*)lpbuf1; - if (destL == 0) - { - while (--samples1 >= 0) - { - ++src; - *destR++ = *src++ * g; - } + if (destL == 0) + { + while (--samples1 >= 0) + { + ++src; + *destR++ = *src++ * g; + } - src = (const short*)lpbuf2; + src = (const short*)lpbuf2; - while (--samples2 >= 0) - { - ++src; - *destR++ = *src++ * g; - } - } - else if (destR == 0) - { - while (--samples1 >= 0) - { - *destL++ = *src++ * g; - ++src; - } + while (--samples2 >= 0) + { + ++src; + *destR++ = *src++ * g; + } + } + else if (destR == 0) + { + while (--samples1 >= 0) + { + *destL++ = *src++ * g; + ++src; + } - src = (const short*)lpbuf2; + src = (const short*)lpbuf2; - while (--samples2 >= 0) - { - *destL++ = *src++ * g; - ++src; - } - } - else - { - while (--samples1 >= 0) - { - *destL++ = *src++ * g; - *destR++ = *src++ * g; - } + while (--samples2 >= 0) + { + *destL++ = *src++ * g; + ++src; + } + } + else + { + while (--samples1 >= 0) + { + *destL++ = *src++ * g; + *destR++ = *src++ * g; + } - src = (const short*)lpbuf2; + src = (const short*)lpbuf2; - while (--samples2 >= 0) - { - *destL++ = *src++ * g; - *destR++ = *src++ * g; - } - } - } - else - { - jassertfalse - } + while (--samples2 >= 0) + { + *destL++ = *src++ * g; + *destR++ = *src++ * g; + } + } + } + else + { + jassertfalse + } - readOffset = (readOffset + dwsize1 + dwsize2) % totalBytesPerBuffer; + readOffset = (readOffset + dwsize1 + dwsize2) % totalBytesPerBuffer; - pInputBuffer->Unlock (lpbuf1, dwsize1, lpbuf2, dwsize2); - } - else - { - logError (hr); - jassertfalse - } + pInputBuffer->Unlock (lpbuf1, dwsize1, lpbuf2, dwsize2); + } + else + { + logError (hr); + jassertfalse + } - bytesFilled -= bytesPerBuffer; + bytesFilled -= bytesPerBuffer; - return true; - } - else - { - return false; - } - } + return true; + } + else + { + return false; + } + } }; class DSoundAudioIODevice : public AudioIODevice, - public Thread + public Thread { public: - DSoundAudioIODevice (const String& deviceName, - const int outputDeviceIndex_, - const int inputDeviceIndex_) - : AudioIODevice (deviceName, "DirectSound"), - Thread ("Juce DSound"), - isOpen_ (false), - isStarted (false), - outputDeviceIndex (outputDeviceIndex_), - inputDeviceIndex (inputDeviceIndex_), - inChans (4), - outChans (4), - numInputBuffers (0), - numOutputBuffers (0), - totalSamplesOut (0), - sampleRate (0.0), - inputBuffers (0), - outputBuffers (0), - callback (0), - bufferSizeSamples (0) - { - if (outputDeviceIndex_ >= 0) - { - outChannels.add (TRANS("Left")); - outChannels.add (TRANS("Right")); - } + DSoundAudioIODevice (const String& deviceName, + const int outputDeviceIndex_, + const int inputDeviceIndex_) + : AudioIODevice (deviceName, "DirectSound"), + Thread ("Juce DSound"), + isOpen_ (false), + isStarted (false), + outputDeviceIndex (outputDeviceIndex_), + inputDeviceIndex (inputDeviceIndex_), + numInputBuffers (0), + numOutputBuffers (0), + totalSamplesOut (0), + sampleRate (0.0), + inputBuffers (0), + outputBuffers (0), + callback (0), + bufferSizeSamples (0) + { + if (outputDeviceIndex_ >= 0) + { + outChannels.add (TRANS("Left")); + outChannels.add (TRANS("Right")); + } - if (inputDeviceIndex_ >= 0) - { - inChannels.add (TRANS("Left")); - inChannels.add (TRANS("Right")); - } - } + if (inputDeviceIndex_ >= 0) + { + inChannels.add (TRANS("Left")); + inChannels.add (TRANS("Right")); + } + } - ~DSoundAudioIODevice() - { - close(); - } + ~DSoundAudioIODevice() + { + close(); + } - const StringArray getOutputChannelNames() - { - return outChannels; - } + const StringArray getOutputChannelNames() + { + return outChannels; + } - const StringArray getInputChannelNames() - { - return inChannels; - } + const StringArray getInputChannelNames() + { + return inChannels; + } - int getNumSampleRates() - { - return 4; - } + int getNumSampleRates() + { + return 4; + } - double getSampleRate (int index) - { - const double samps[] = { 44100.0, 48000.0, 88200.0, 96000.0 }; + double getSampleRate (int index) + { + const double samps[] = { 44100.0, 48000.0, 88200.0, 96000.0 }; - return samps [jlimit (0, 3, index)]; - } + return samps [jlimit (0, 3, index)]; + } - int getNumBufferSizesAvailable() - { - return 50; - } + int getNumBufferSizesAvailable() + { + return 50; + } - int getBufferSizeSamples (int index) - { - int n = 64; - for (int i = 0; i < index; ++i) - n += (n < 512) ? 32 - : ((n < 1024) ? 64 - : ((n < 2048) ? 128 : 256)); + int getBufferSizeSamples (int index) + { + int n = 64; + for (int i = 0; i < index; ++i) + n += (n < 512) ? 32 + : ((n < 1024) ? 64 + : ((n < 2048) ? 128 : 256)); - return n; - } + return n; + } - int getDefaultBufferSize() - { - return 2560; - } + int getDefaultBufferSize() + { + return 2560; + } - const String open (const BitArray& inputChannels, - const BitArray& outputChannels, - double sampleRate, - int bufferSizeSamples) - { - lastError = openDevice (inputChannels, outputChannels, sampleRate, bufferSizeSamples); - isOpen_ = lastError.isEmpty(); + const String open (const BitArray& inputChannels, + const BitArray& outputChannels, + double sampleRate, + int bufferSizeSamples) + { + lastError = openDevice (inputChannels, outputChannels, sampleRate, bufferSizeSamples); + isOpen_ = lastError.isEmpty(); - return lastError; - } + return lastError; + } - void close() - { - stop(); + void close() + { + stop(); - if (isOpen_) - { - closeDevice(); - isOpen_ = false; - } - } + if (isOpen_) + { + closeDevice(); + isOpen_ = false; + } + } - bool isOpen() - { - return isOpen_ && isThreadRunning(); - } + bool isOpen() + { + return isOpen_ && isThreadRunning(); + } - int getCurrentBufferSizeSamples() - { - return bufferSizeSamples; - } + int getCurrentBufferSizeSamples() + { + return bufferSizeSamples; + } - double getCurrentSampleRate() - { - return sampleRate; - } + double getCurrentSampleRate() + { + return sampleRate; + } - int getCurrentBitDepth() - { - int i, bits = 256; + int getCurrentBitDepth() + { + int i, bits = 256; - for (i = inChans.size(); --i >= 0;) - bits = jmin (bits, inChans[i]->bitDepth); + for (i = inChans.size(); --i >= 0;) + bits = jmin (bits, inChans[i]->bitDepth); - for (i = outChans.size(); --i >= 0;) - bits = jmin (bits, outChans[i]->bitDepth); + for (i = outChans.size(); --i >= 0;) + bits = jmin (bits, outChans[i]->bitDepth); - if (bits > 32) - bits = 16; + if (bits > 32) + bits = 16; - return bits; - } + return bits; + } - const BitArray getActiveOutputChannels() const - { - return enabledOutputs; - } + const BitArray getActiveOutputChannels() const + { + return enabledOutputs; + } - const BitArray getActiveInputChannels() const - { - return enabledInputs; - } + const BitArray getActiveInputChannels() const + { + return enabledInputs; + } - int getOutputLatencyInSamples() - { - return (int) (getCurrentBufferSizeSamples() * 1.5); - } + int getOutputLatencyInSamples() + { + return (int) (getCurrentBufferSizeSamples() * 1.5); + } - int getInputLatencyInSamples() - { - return getOutputLatencyInSamples(); - } + int getInputLatencyInSamples() + { + return getOutputLatencyInSamples(); + } - void start (AudioIODeviceCallback* call) - { - if (isOpen_ && call != 0 && ! isStarted) - { - if (! isThreadRunning()) - { - // something gone wrong and the thread's stopped.. - isOpen_ = false; - return; - } + void start (AudioIODeviceCallback* call) + { + if (isOpen_ && call != 0 && ! isStarted) + { + if (! isThreadRunning()) + { + // something gone wrong and the thread's stopped.. + isOpen_ = false; + return; + } - call->audioDeviceAboutToStart (this); + call->audioDeviceAboutToStart (this); - const ScopedLock sl (startStopLock); - callback = call; - isStarted = true; - } - } + const ScopedLock sl (startStopLock); + callback = call; + isStarted = true; + } + } - void stop() - { - if (isStarted) - { - AudioIODeviceCallback* const callbackLocal = callback; + void stop() + { + if (isStarted) + { + AudioIODeviceCallback* const callbackLocal = callback; - { - const ScopedLock sl (startStopLock); - isStarted = false; - } + { + const ScopedLock sl (startStopLock); + isStarted = false; + } - if (callbackLocal != 0) - callbackLocal->audioDeviceStopped(); - } - } + if (callbackLocal != 0) + callbackLocal->audioDeviceStopped(); + } + } - bool isPlaying() - { - return isStarted && isOpen_ && isThreadRunning(); - } + bool isPlaying() + { + return isStarted && isOpen_ && isThreadRunning(); + } - const String getLastError() - { - return lastError; - } + const String getLastError() + { + return lastError; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - StringArray inChannels, outChannels; - int outputDeviceIndex, inputDeviceIndex; + StringArray inChannels, outChannels; + int outputDeviceIndex, inputDeviceIndex; private: - bool isOpen_; - bool isStarted; - String lastError; + bool isOpen_; + bool isStarted; + String lastError; - OwnedArray inChans; - OwnedArray outChans; - WaitableEvent startEvent; + OwnedArray inChans; + OwnedArray outChans; + WaitableEvent startEvent; - int numInputBuffers, numOutputBuffers, bufferSizeSamples; - int volatile totalSamplesOut; - int64 volatile lastBlockTime; - double sampleRate; - BitArray enabledInputs, enabledOutputs; - HeapBlock inputBuffers, outputBuffers; + int numInputBuffers, numOutputBuffers, bufferSizeSamples; + int volatile totalSamplesOut; + int64 volatile lastBlockTime; + double sampleRate; + BitArray enabledInputs, enabledOutputs; + HeapBlock inputBuffers, outputBuffers; - AudioIODeviceCallback* callback; - CriticalSection startStopLock; + AudioIODeviceCallback* callback; + CriticalSection startStopLock; - DSoundAudioIODevice (const DSoundAudioIODevice&); - const DSoundAudioIODevice& operator= (const DSoundAudioIODevice&); + DSoundAudioIODevice (const DSoundAudioIODevice&); + const DSoundAudioIODevice& operator= (const DSoundAudioIODevice&); - const String openDevice (const BitArray& inputChannels, - const BitArray& outputChannels, - double sampleRate_, - int bufferSizeSamples_); + const String openDevice (const BitArray& inputChannels, + const BitArray& outputChannels, + double sampleRate_, + int bufferSizeSamples_); - void closeDevice() - { - isStarted = false; - stopThread (5000); + void closeDevice() + { + isStarted = false; + stopThread (5000); - inChans.clear(); - outChans.clear(); + inChans.clear(); + outChans.clear(); - int i; - for (i = 0; i < numInputBuffers; ++i) - juce_free (inputBuffers[i]); + int i; + for (i = 0; i < numInputBuffers; ++i) + juce_free (inputBuffers[i]); - inputBuffers.free(); - numInputBuffers = 0; + inputBuffers.free(); + numInputBuffers = 0; - for (i = 0; i < numOutputBuffers; ++i) - juce_free (outputBuffers[i]); + for (i = 0; i < numOutputBuffers; ++i) + juce_free (outputBuffers[i]); - outputBuffers.free(); - numOutputBuffers = 0; - } + outputBuffers.free(); + numOutputBuffers = 0; + } - void resync() - { - if (! threadShouldExit()) - { - sleep (5); + void resync() + { + if (! threadShouldExit()) + { + sleep (5); - int i; - for (i = 0; i < outChans.size(); ++i) - outChans.getUnchecked(i)->synchronisePosition(); + int i; + for (i = 0; i < outChans.size(); ++i) + outChans.getUnchecked(i)->synchronisePosition(); - for (i = 0; i < inChans.size(); ++i) - inChans.getUnchecked(i)->synchronisePosition(); - } - } + for (i = 0; i < inChans.size(); ++i) + inChans.getUnchecked(i)->synchronisePosition(); + } + } public: - void run() - { - while (! threadShouldExit()) - { - if (wait (100)) - break; - } + void run() + { + while (! threadShouldExit()) + { + if (wait (100)) + break; + } - const int latencyMs = (int) (bufferSizeSamples * 1000.0 / sampleRate); - const int maxTimeMS = jmax (5, 3 * latencyMs); + const int latencyMs = (int) (bufferSizeSamples * 1000.0 / sampleRate); + const int maxTimeMS = jmax (5, 3 * latencyMs); - while (! threadShouldExit()) - { - int numToDo = 0; - uint32 startTime = Time::getMillisecondCounter(); + while (! threadShouldExit()) + { + int numToDo = 0; + uint32 startTime = Time::getMillisecondCounter(); - int i; - for (i = inChans.size(); --i >= 0;) - { - inChans.getUnchecked(i)->doneFlag = false; - ++numToDo; - } + int i; + for (i = inChans.size(); --i >= 0;) + { + inChans.getUnchecked(i)->doneFlag = false; + ++numToDo; + } - for (i = outChans.size(); --i >= 0;) - { - outChans.getUnchecked(i)->doneFlag = false; - ++numToDo; - } + for (i = outChans.size(); --i >= 0;) + { + outChans.getUnchecked(i)->doneFlag = false; + ++numToDo; + } - if (numToDo > 0) - { - const int maxCount = 3; - int count = maxCount; + if (numToDo > 0) + { + const int maxCount = 3; + int count = maxCount; - for (;;) - { - for (i = inChans.size(); --i >= 0;) - { - DSoundInternalInChannel* const in = inChans.getUnchecked(i); + for (;;) + { + for (i = inChans.size(); --i >= 0;) + { + DSoundInternalInChannel* const in = inChans.getUnchecked(i); - if ((! in->doneFlag) && in->service()) - { - in->doneFlag = true; - --numToDo; - } - } + if ((! in->doneFlag) && in->service()) + { + in->doneFlag = true; + --numToDo; + } + } - for (i = outChans.size(); --i >= 0;) - { - DSoundInternalOutChannel* const out = outChans.getUnchecked(i); + for (i = outChans.size(); --i >= 0;) + { + DSoundInternalOutChannel* const out = outChans.getUnchecked(i); - if ((! out->doneFlag) && out->service()) - { - out->doneFlag = true; - --numToDo; - } - } + if ((! out->doneFlag) && out->service()) + { + out->doneFlag = true; + --numToDo; + } + } - if (numToDo <= 0) - break; + if (numToDo <= 0) + break; - if (Time::getMillisecondCounter() > startTime + maxTimeMS) - { - resync(); - break; - } + if (Time::getMillisecondCounter() > startTime + maxTimeMS) + { + resync(); + break; + } - if (--count <= 0) - { - Sleep (1); - count = maxCount; - } + if (--count <= 0) + { + Sleep (1); + count = maxCount; + } - if (threadShouldExit()) - return; - } - } - else - { - sleep (1); - } + if (threadShouldExit()) + return; + } + } + else + { + sleep (1); + } - const ScopedLock sl (startStopLock); + const ScopedLock sl (startStopLock); - if (isStarted) - { - JUCE_TRY - { - callback->audioDeviceIOCallback ((const float**) inputBuffers, - numInputBuffers, - outputBuffers, - numOutputBuffers, - bufferSizeSamples); - } - JUCE_CATCH_EXCEPTION + if (isStarted) + { + JUCE_TRY + { + callback->audioDeviceIOCallback ((const float**) inputBuffers, + numInputBuffers, + outputBuffers, + numOutputBuffers, + bufferSizeSamples); + } + JUCE_CATCH_EXCEPTION - totalSamplesOut += bufferSizeSamples; - } - else - { - for (i = 0; i < numOutputBuffers; ++i) - if (outputBuffers[i] != 0) - zeromem (outputBuffers[i], bufferSizeSamples * sizeof (float)); + totalSamplesOut += bufferSizeSamples; + } + else + { + for (i = 0; i < numOutputBuffers; ++i) + if (outputBuffers[i] != 0) + zeromem (outputBuffers[i], bufferSizeSamples * sizeof (float)); - totalSamplesOut = 0; - sleep (1); - } - } - } + totalSamplesOut = 0; + sleep (1); + } + } + } }; class DSoundAudioIODeviceType : public AudioIODeviceType { public: - DSoundAudioIODeviceType() - : AudioIODeviceType (T("DirectSound")), - hasScanned (false) - { - initialiseDSoundFunctions(); - } + DSoundAudioIODeviceType() + : AudioIODeviceType (T("DirectSound")), + hasScanned (false) + { + initialiseDSoundFunctions(); + } - ~DSoundAudioIODeviceType() - { - } + ~DSoundAudioIODeviceType() + { + } - void scanForDevices() - { - hasScanned = true; + void scanForDevices() + { + hasScanned = true; - outputDeviceNames.clear(); - outputGuids.clear(); - inputDeviceNames.clear(); - inputGuids.clear(); + outputDeviceNames.clear(); + outputGuids.clear(); + inputDeviceNames.clear(); + inputGuids.clear(); - if (dsDirectSoundEnumerateW != 0) - { - dsDirectSoundEnumerateW (outputEnumProcW, this); - dsDirectSoundCaptureEnumerateW (inputEnumProcW, this); - } - } + if (dsDirectSoundEnumerateW != 0) + { + dsDirectSoundEnumerateW (outputEnumProcW, this); + dsDirectSoundCaptureEnumerateW (inputEnumProcW, this); + } + } - const StringArray getDeviceNames (const bool wantInputNames) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + const StringArray getDeviceNames (const bool wantInputNames) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - return wantInputNames ? inputDeviceNames - : outputDeviceNames; - } + return wantInputNames ? inputDeviceNames + : outputDeviceNames; + } - int getDefaultDeviceIndex (const bool /*forInput*/) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this - return 0; - } + int getDefaultDeviceIndex (const bool /*forInput*/) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this + return 0; + } - int getIndexOfDevice (AudioIODevice* device, const bool asInput) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + int getIndexOfDevice (AudioIODevice* device, const bool asInput) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - DSoundAudioIODevice* const d = dynamic_cast (device); - if (d == 0) - return -1; + DSoundAudioIODevice* const d = dynamic_cast (device); + if (d == 0) + return -1; - return asInput ? d->inputDeviceIndex - : d->outputDeviceIndex; - } + return asInput ? d->inputDeviceIndex + : d->outputDeviceIndex; + } - bool hasSeparateInputsAndOutputs() const { return true; } + bool hasSeparateInputsAndOutputs() const { return true; } - AudioIODevice* createDevice (const String& outputDeviceName, - const String& inputDeviceName) - { - jassert (hasScanned); // need to call scanForDevices() before doing this + AudioIODevice* createDevice (const String& outputDeviceName, + const String& inputDeviceName) + { + jassert (hasScanned); // need to call scanForDevices() before doing this - const int outputIndex = outputDeviceNames.indexOf (outputDeviceName); - const int inputIndex = inputDeviceNames.indexOf (inputDeviceName); + const int outputIndex = outputDeviceNames.indexOf (outputDeviceName); + const int inputIndex = inputDeviceNames.indexOf (inputDeviceName); - if (outputIndex >= 0 || inputIndex >= 0) - return new DSoundAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName - : inputDeviceName, - outputIndex, inputIndex); + if (outputIndex >= 0 || inputIndex >= 0) + return new DSoundAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName + : inputDeviceName, + outputIndex, inputIndex); - return 0; - } + return 0; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - StringArray outputDeviceNames; - OwnedArray outputGuids; + StringArray outputDeviceNames; + OwnedArray outputGuids; - StringArray inputDeviceNames; - OwnedArray inputGuids; + StringArray inputDeviceNames; + OwnedArray inputGuids; private: - bool hasScanned; + bool hasScanned; - BOOL outputEnumProc (LPGUID lpGUID, String desc) - { - desc = desc.trim(); + BOOL outputEnumProc (LPGUID lpGUID, String desc) + { + desc = desc.trim(); - if (desc.isNotEmpty()) - { - const String origDesc (desc); + if (desc.isNotEmpty()) + { + const String origDesc (desc); - int n = 2; - while (outputDeviceNames.contains (desc)) - desc = origDesc + T(" (") + String (n++) + T(")"); + int n = 2; + while (outputDeviceNames.contains (desc)) + desc = origDesc + T(" (") + String (n++) + T(")"); - outputDeviceNames.add (desc); + outputDeviceNames.add (desc); - if (lpGUID != 0) - outputGuids.add (new GUID (*lpGUID)); - else - outputGuids.add (0); - } + if (lpGUID != 0) + outputGuids.add (new GUID (*lpGUID)); + else + outputGuids.add (0); + } - return TRUE; - } + return TRUE; + } - static BOOL CALLBACK outputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object) - { - return ((DSoundAudioIODeviceType*) object) - ->outputEnumProc (lpGUID, String (description)); - } + static BOOL CALLBACK outputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object) + { + return ((DSoundAudioIODeviceType*) object) + ->outputEnumProc (lpGUID, String (description)); + } - static BOOL CALLBACK outputEnumProcA (LPGUID lpGUID, LPCTSTR description, LPCTSTR, LPVOID object) - { - return ((DSoundAudioIODeviceType*) object) - ->outputEnumProc (lpGUID, String (description)); - } + static BOOL CALLBACK outputEnumProcA (LPGUID lpGUID, LPCTSTR description, LPCTSTR, LPVOID object) + { + return ((DSoundAudioIODeviceType*) object) + ->outputEnumProc (lpGUID, String (description)); + } - BOOL CALLBACK inputEnumProc (LPGUID lpGUID, String desc) - { - desc = desc.trim(); + BOOL CALLBACK inputEnumProc (LPGUID lpGUID, String desc) + { + desc = desc.trim(); - if (desc.isNotEmpty()) - { - const String origDesc (desc); + if (desc.isNotEmpty()) + { + const String origDesc (desc); - int n = 2; - while (inputDeviceNames.contains (desc)) - desc = origDesc + T(" (") + String (n++) + T(")"); + int n = 2; + while (inputDeviceNames.contains (desc)) + desc = origDesc + T(" (") + String (n++) + T(")"); - inputDeviceNames.add (desc); + inputDeviceNames.add (desc); - if (lpGUID != 0) - inputGuids.add (new GUID (*lpGUID)); - else - inputGuids.add (0); - } + if (lpGUID != 0) + inputGuids.add (new GUID (*lpGUID)); + else + inputGuids.add (0); + } - return TRUE; - } + return TRUE; + } - static BOOL CALLBACK inputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object) - { - return ((DSoundAudioIODeviceType*) object) - ->inputEnumProc (lpGUID, String (description)); - } + static BOOL CALLBACK inputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object) + { + return ((DSoundAudioIODeviceType*) object) + ->inputEnumProc (lpGUID, String (description)); + } - static BOOL CALLBACK inputEnumProcA (LPGUID lpGUID, LPCTSTR description, LPCTSTR, LPVOID object) - { - return ((DSoundAudioIODeviceType*) object) - ->inputEnumProc (lpGUID, String (description)); - } + static BOOL CALLBACK inputEnumProcA (LPGUID lpGUID, LPCTSTR description, LPCTSTR, LPVOID object) + { + return ((DSoundAudioIODeviceType*) object) + ->inputEnumProc (lpGUID, String (description)); + } - DSoundAudioIODeviceType (const DSoundAudioIODeviceType&); - const DSoundAudioIODeviceType& operator= (const DSoundAudioIODeviceType&); + DSoundAudioIODeviceType (const DSoundAudioIODeviceType&); + const DSoundAudioIODeviceType& operator= (const DSoundAudioIODeviceType&); }; const String DSoundAudioIODevice::openDevice (const BitArray& inputChannels, - const BitArray& outputChannels, - double sampleRate_, - int bufferSizeSamples_) + const BitArray& outputChannels, + double sampleRate_, + int bufferSizeSamples_) { - closeDevice(); - totalSamplesOut = 0; + closeDevice(); + totalSamplesOut = 0; - sampleRate = sampleRate_; + sampleRate = sampleRate_; - if (bufferSizeSamples_ <= 0) - bufferSizeSamples_ = 960; // use as a default size if none is set. + if (bufferSizeSamples_ <= 0) + bufferSizeSamples_ = 960; // use as a default size if none is set. - bufferSizeSamples = bufferSizeSamples_ & ~7; + bufferSizeSamples = bufferSizeSamples_ & ~7; - DSoundAudioIODeviceType dlh; - dlh.scanForDevices(); + DSoundAudioIODeviceType dlh; + dlh.scanForDevices(); - enabledInputs = inputChannels; - enabledInputs.setRange (inChannels.size(), - enabledInputs.getHighestBit() + 1 - inChannels.size(), - false); + enabledInputs = inputChannels; + enabledInputs.setRange (inChannels.size(), + enabledInputs.getHighestBit() + 1 - inChannels.size(), + false); - numInputBuffers = enabledInputs.countNumberOfSetBits(); - inputBuffers.calloc (numInputBuffers + 2); - int i, numIns = 0; + numInputBuffers = enabledInputs.countNumberOfSetBits(); + inputBuffers.calloc (numInputBuffers + 2); + int i, numIns = 0; - for (i = 0; i <= enabledInputs.getHighestBit(); i += 2) - { - float* left = 0; - float* right = 0; + for (i = 0; i <= enabledInputs.getHighestBit(); i += 2) + { + float* left = 0; + float* right = 0; - if (enabledInputs[i]) - left = inputBuffers[numIns++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float)); + if (enabledInputs[i]) + left = inputBuffers[numIns++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float)); - if (enabledInputs[i + 1]) - right = inputBuffers[numIns++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float)); + if (enabledInputs[i + 1]) + right = inputBuffers[numIns++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float)); - if (left != 0 || right != 0) - inChans.add (new DSoundInternalInChannel (dlh.inputDeviceNames [inputDeviceIndex], - dlh.inputGuids [inputDeviceIndex], - (int) sampleRate, bufferSizeSamples, - left, right)); - } + if (left != 0 || right != 0) + inChans.add (new DSoundInternalInChannel (dlh.inputDeviceNames [inputDeviceIndex], + dlh.inputGuids [inputDeviceIndex], + (int) sampleRate, bufferSizeSamples, + left, right)); + } - enabledOutputs = outputChannels; - enabledOutputs.setRange (outChannels.size(), - enabledOutputs.getHighestBit() + 1 - outChannels.size(), - false); + enabledOutputs = outputChannels; + enabledOutputs.setRange (outChannels.size(), + enabledOutputs.getHighestBit() + 1 - outChannels.size(), + false); - numOutputBuffers = enabledOutputs.countNumberOfSetBits(); - outputBuffers.calloc (numOutputBuffers + 2); - int numOuts = 0; + numOutputBuffers = enabledOutputs.countNumberOfSetBits(); + outputBuffers.calloc (numOutputBuffers + 2); + int numOuts = 0; - for (i = 0; i <= enabledOutputs.getHighestBit(); i += 2) - { - float* left = 0; - float* right = 0; + for (i = 0; i <= enabledOutputs.getHighestBit(); i += 2) + { + float* left = 0; + float* right = 0; - if (enabledOutputs[i]) - left = outputBuffers[numOuts++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float)); + if (enabledOutputs[i]) + left = outputBuffers[numOuts++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float)); - if (enabledOutputs[i + 1]) - right = outputBuffers[numOuts++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float)); + if (enabledOutputs[i + 1]) + right = outputBuffers[numOuts++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float)); - if (left != 0 || right != 0) - outChans.add (new DSoundInternalOutChannel (dlh.outputDeviceNames[outputDeviceIndex], - dlh.outputGuids [outputDeviceIndex], - (int) sampleRate, bufferSizeSamples, - left, right)); - } + if (left != 0 || right != 0) + outChans.add (new DSoundInternalOutChannel (dlh.outputDeviceNames[outputDeviceIndex], + dlh.outputGuids [outputDeviceIndex], + (int) sampleRate, bufferSizeSamples, + left, right)); + } - String error; + String error; - // boost our priority while opening the devices to try to get better sync between them - const int oldThreadPri = GetThreadPriority (GetCurrentThread()); - const int oldProcPri = GetPriorityClass (GetCurrentProcess()); - SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - SetPriorityClass (GetCurrentProcess(), REALTIME_PRIORITY_CLASS); + // boost our priority while opening the devices to try to get better sync between them + const int oldThreadPri = GetThreadPriority (GetCurrentThread()); + const int oldProcPri = GetPriorityClass (GetCurrentProcess()); + SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + SetPriorityClass (GetCurrentProcess(), REALTIME_PRIORITY_CLASS); - for (i = 0; i < outChans.size(); ++i) - { - error = outChans[i]->open(); + for (i = 0; i < outChans.size(); ++i) + { + error = outChans[i]->open(); - if (error.isNotEmpty()) - { - error = T("Error opening ") + dlh.outputDeviceNames[i] - + T(": \"") + error + T("\""); - break; - } - } + if (error.isNotEmpty()) + { + error = T("Error opening ") + dlh.outputDeviceNames[i] + + T(": \"") + error + T("\""); + break; + } + } - if (error.isEmpty()) - { - for (i = 0; i < inChans.size(); ++i) - { - error = inChans[i]->open(); + if (error.isEmpty()) + { + for (i = 0; i < inChans.size(); ++i) + { + error = inChans[i]->open(); - if (error.isNotEmpty()) - { - error = T("Error opening ") + dlh.inputDeviceNames[i] - + T(": \"") + error + T("\""); - break; - } - } - } + if (error.isNotEmpty()) + { + error = T("Error opening ") + dlh.inputDeviceNames[i] + + T(": \"") + error + T("\""); + break; + } + } + } - if (error.isEmpty()) - { - totalSamplesOut = 0; + if (error.isEmpty()) + { + totalSamplesOut = 0; - for (i = 0; i < outChans.size(); ++i) - outChans.getUnchecked(i)->synchronisePosition(); + for (i = 0; i < outChans.size(); ++i) + outChans.getUnchecked(i)->synchronisePosition(); - for (i = 0; i < inChans.size(); ++i) - inChans.getUnchecked(i)->synchronisePosition(); + for (i = 0; i < inChans.size(); ++i) + inChans.getUnchecked(i)->synchronisePosition(); - startThread (9); - sleep (10); + startThread (9); + sleep (10); - notify(); - } - else - { - log (error); - } + notify(); + } + else + { + log (error); + } - SetThreadPriority (GetCurrentThread(), oldThreadPri); - SetPriorityClass (GetCurrentProcess(), oldProcPri); + SetThreadPriority (GetCurrentThread(), oldThreadPri); + SetPriorityClass (GetCurrentProcess(), oldProcPri); - return error; + return error; } AudioIODeviceType* juce_createAudioIODeviceType_DirectSound() { - return new DSoundAudioIODeviceType(); + return new DSoundAudioIODeviceType(); } #undef log @@ -248775,39 +226507,39 @@ AudioIODeviceType* juce_createAudioIODeviceType_DirectSound() const String getAudioErrorDesc (HRESULT hr) { - const char* e = 0; + const char* e = 0; - switch (hr) - { - case E_POINTER: e = "E_POINTER"; break; - case E_INVALIDARG: e = "E_INVALIDARG"; break; - case AUDCLNT_E_NOT_INITIALIZED: e = "AUDCLNT_E_NOT_INITIALIZED"; break; - case AUDCLNT_E_ALREADY_INITIALIZED: e = "AUDCLNT_E_ALREADY_INITIALIZED"; break; - case AUDCLNT_E_WRONG_ENDPOINT_TYPE: e = "AUDCLNT_E_WRONG_ENDPOINT_TYPE"; break; - case AUDCLNT_E_DEVICE_INVALIDATED: e = "AUDCLNT_E_DEVICE_INVALIDATED"; break; - case AUDCLNT_E_NOT_STOPPED: e = "AUDCLNT_E_NOT_STOPPED"; break; - case AUDCLNT_E_BUFFER_TOO_LARGE: e = "AUDCLNT_E_BUFFER_TOO_LARGE"; break; - case AUDCLNT_E_OUT_OF_ORDER: e = "AUDCLNT_E_OUT_OF_ORDER"; break; - case AUDCLNT_E_UNSUPPORTED_FORMAT: e = "AUDCLNT_E_UNSUPPORTED_FORMAT"; break; - case AUDCLNT_E_INVALID_SIZE: e = "AUDCLNT_E_INVALID_SIZE"; break; - case AUDCLNT_E_DEVICE_IN_USE: e = "AUDCLNT_E_DEVICE_IN_USE"; break; - case AUDCLNT_E_BUFFER_OPERATION_PENDING: e = "AUDCLNT_E_BUFFER_OPERATION_PENDING"; break; - case AUDCLNT_E_THREAD_NOT_REGISTERED: e = "AUDCLNT_E_THREAD_NOT_REGISTERED"; break; - case AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED: e = "AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED"; break; - case AUDCLNT_E_ENDPOINT_CREATE_FAILED: e = "AUDCLNT_E_ENDPOINT_CREATE_FAILED"; break; - case AUDCLNT_E_SERVICE_NOT_RUNNING: e = "AUDCLNT_E_SERVICE_NOT_RUNNING"; break; - case AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED: e = "AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED"; break; - case AUDCLNT_E_EXCLUSIVE_MODE_ONLY: e = "AUDCLNT_E_EXCLUSIVE_MODE_ONLY"; break; - case AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL: e = "AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL"; break; - case AUDCLNT_E_EVENTHANDLE_NOT_SET: e = "AUDCLNT_E_EVENTHANDLE_NOT_SET"; break; - case AUDCLNT_E_INCORRECT_BUFFER_SIZE: e = "AUDCLNT_E_INCORRECT_BUFFER_SIZE"; break; - case AUDCLNT_E_BUFFER_SIZE_ERROR: e = "AUDCLNT_E_BUFFER_SIZE_ERROR"; break; - case AUDCLNT_S_BUFFER_EMPTY: e = "AUDCLNT_S_BUFFER_EMPTY"; break; - case AUDCLNT_S_THREAD_ALREADY_REGISTERED: e = "AUDCLNT_S_THREAD_ALREADY_REGISTERED"; break; - default: return String::toHexString ((int) hr); - } + switch (hr) + { + case E_POINTER: e = "E_POINTER"; break; + case E_INVALIDARG: e = "E_INVALIDARG"; break; + case AUDCLNT_E_NOT_INITIALIZED: e = "AUDCLNT_E_NOT_INITIALIZED"; break; + case AUDCLNT_E_ALREADY_INITIALIZED: e = "AUDCLNT_E_ALREADY_INITIALIZED"; break; + case AUDCLNT_E_WRONG_ENDPOINT_TYPE: e = "AUDCLNT_E_WRONG_ENDPOINT_TYPE"; break; + case AUDCLNT_E_DEVICE_INVALIDATED: e = "AUDCLNT_E_DEVICE_INVALIDATED"; break; + case AUDCLNT_E_NOT_STOPPED: e = "AUDCLNT_E_NOT_STOPPED"; break; + case AUDCLNT_E_BUFFER_TOO_LARGE: e = "AUDCLNT_E_BUFFER_TOO_LARGE"; break; + case AUDCLNT_E_OUT_OF_ORDER: e = "AUDCLNT_E_OUT_OF_ORDER"; break; + case AUDCLNT_E_UNSUPPORTED_FORMAT: e = "AUDCLNT_E_UNSUPPORTED_FORMAT"; break; + case AUDCLNT_E_INVALID_SIZE: e = "AUDCLNT_E_INVALID_SIZE"; break; + case AUDCLNT_E_DEVICE_IN_USE: e = "AUDCLNT_E_DEVICE_IN_USE"; break; + case AUDCLNT_E_BUFFER_OPERATION_PENDING: e = "AUDCLNT_E_BUFFER_OPERATION_PENDING"; break; + case AUDCLNT_E_THREAD_NOT_REGISTERED: e = "AUDCLNT_E_THREAD_NOT_REGISTERED"; break; + case AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED: e = "AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED"; break; + case AUDCLNT_E_ENDPOINT_CREATE_FAILED: e = "AUDCLNT_E_ENDPOINT_CREATE_FAILED"; break; + case AUDCLNT_E_SERVICE_NOT_RUNNING: e = "AUDCLNT_E_SERVICE_NOT_RUNNING"; break; + case AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED: e = "AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED"; break; + case AUDCLNT_E_EXCLUSIVE_MODE_ONLY: e = "AUDCLNT_E_EXCLUSIVE_MODE_ONLY"; break; + case AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL: e = "AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL"; break; + case AUDCLNT_E_EVENTHANDLE_NOT_SET: e = "AUDCLNT_E_EVENTHANDLE_NOT_SET"; break; + case AUDCLNT_E_INCORRECT_BUFFER_SIZE: e = "AUDCLNT_E_INCORRECT_BUFFER_SIZE"; break; + case AUDCLNT_E_BUFFER_SIZE_ERROR: e = "AUDCLNT_E_BUFFER_SIZE_ERROR"; break; + case AUDCLNT_S_BUFFER_EMPTY: e = "AUDCLNT_S_BUFFER_EMPTY"; break; + case AUDCLNT_S_THREAD_ALREADY_REGISTERED: e = "AUDCLNT_S_THREAD_ALREADY_REGISTERED"; break; + default: return String::toHexString ((int) hr); + } - return e; + return e; } #define logFailure(hr) { if (FAILED (hr)) { DBG ("WASAPI FAIL! " + getAudioErrorDesc (hr)); jassertfalse } } @@ -248815,8 +226547,8 @@ const String getAudioErrorDesc (HRESULT hr) static bool wasapi_checkResult (HRESULT hr) { - logFailure (hr); - return SUCCEEDED (hr); + logFailure (hr); + return SUCCEEDED (hr); } #else @@ -248826,989 +226558,989 @@ static bool wasapi_checkResult (HRESULT hr) static const String wasapi_getDeviceID (IMMDevice* const device) { - String s; - WCHAR* deviceId = 0; + String s; + WCHAR* deviceId = 0; - if (OK (device->GetId (&deviceId))) - { - s = String (deviceId); - CoTaskMemFree (deviceId); - } + if (OK (device->GetId (&deviceId))) + { + s = String (deviceId); + CoTaskMemFree (deviceId); + } - return s; + return s; } static EDataFlow wasapi_getDataFlow (IMMDevice* const device) { - EDataFlow flow = eRender; - ComSmartPtr endPoint; - if (OK (device->QueryInterface (__uuidof (IMMEndpoint), (void**) &endPoint))) - (void) OK (endPoint->GetDataFlow (&flow)); + EDataFlow flow = eRender; + ComSmartPtr endPoint; + if (OK (device->QueryInterface (__uuidof (IMMEndpoint), (void**) &endPoint))) + (void) OK (endPoint->GetDataFlow (&flow)); - return flow; + return flow; } static int wasapi_refTimeToSamples (const REFERENCE_TIME& t, const double sampleRate) throw() { - return roundDoubleToInt (sampleRate * ((double) t) * 0.0000001); + return roundDoubleToInt (sampleRate * ((double) t) * 0.0000001); } static void wasapi_copyWavFormat (WAVEFORMATEXTENSIBLE& dest, const WAVEFORMATEX* const src) throw() { - memcpy (&dest, src, src->wFormatTag == WAVE_FORMAT_EXTENSIBLE ? sizeof (WAVEFORMATEXTENSIBLE) - : sizeof (WAVEFORMATEX)); + memcpy (&dest, src, src->wFormatTag == WAVE_FORMAT_EXTENSIBLE ? sizeof (WAVEFORMATEXTENSIBLE) + : sizeof (WAVEFORMATEX)); } class WASAPIDeviceBase { public: - WASAPIDeviceBase (const ComSmartPtr & device_) - : device (device_), - sampleRate (0), - numChannels (0), - actualNumChannels (0), - defaultSampleRate (0), - minBufferSize (0), - defaultBufferSize (0), - latencySamples (0) - { - clientEvent = CreateEvent (0, false, false, _T("JuceWASAPI")); + WASAPIDeviceBase (const ComSmartPtr & device_) + : device (device_), + sampleRate (0), + numChannels (0), + actualNumChannels (0), + defaultSampleRate (0), + minBufferSize (0), + defaultBufferSize (0), + latencySamples (0) + { + clientEvent = CreateEvent (0, false, false, _T("JuceWASAPI")); - ComSmartPtr tempClient (createClient()); - if (tempClient == 0) - return; + ComSmartPtr tempClient (createClient()); + if (tempClient == 0) + return; - REFERENCE_TIME defaultPeriod, minPeriod; - if (! OK (tempClient->GetDevicePeriod (&defaultPeriod, &minPeriod))) - return; + REFERENCE_TIME defaultPeriod, minPeriod; + if (! OK (tempClient->GetDevicePeriod (&defaultPeriod, &minPeriod))) + return; - WAVEFORMATEX* mixFormat = 0; - if (! OK (tempClient->GetMixFormat (&mixFormat))) - return; + WAVEFORMATEX* mixFormat = 0; + if (! OK (tempClient->GetMixFormat (&mixFormat))) + return; - WAVEFORMATEXTENSIBLE format; - wasapi_copyWavFormat (format, mixFormat); - CoTaskMemFree (mixFormat); + WAVEFORMATEXTENSIBLE format; + wasapi_copyWavFormat (format, mixFormat); + CoTaskMemFree (mixFormat); - actualNumChannels = numChannels = format.Format.nChannels; - defaultSampleRate = format.Format.nSamplesPerSec; - minBufferSize = wasapi_refTimeToSamples (minPeriod, defaultSampleRate); - defaultBufferSize = wasapi_refTimeToSamples (defaultPeriod, defaultSampleRate); + actualNumChannels = numChannels = format.Format.nChannels; + defaultSampleRate = format.Format.nSamplesPerSec; + minBufferSize = wasapi_refTimeToSamples (minPeriod, defaultSampleRate); + defaultBufferSize = wasapi_refTimeToSamples (defaultPeriod, defaultSampleRate); - FloatElementComparator comparator; - rates.addSorted (comparator, defaultSampleRate); + FloatElementComparator comparator; + rates.addSorted (comparator, defaultSampleRate); - static const double ratesToTest[] = { 44100.0, 48000.0, 88200.0, 96000.0 }; + static const double ratesToTest[] = { 44100.0, 48000.0, 88200.0, 96000.0 }; - for (int i = 0; i < numElementsInArray (ratesToTest); ++i) - { - if (ratesToTest[i] == defaultSampleRate) - continue; + for (int i = 0; i < numElementsInArray (ratesToTest); ++i) + { + if (ratesToTest[i] == defaultSampleRate) + continue; - format.Format.nSamplesPerSec = roundDoubleToInt (ratesToTest[i]); + format.Format.nSamplesPerSec = roundDoubleToInt (ratesToTest[i]); - if (SUCCEEDED (tempClient->IsFormatSupported (AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*) &format, 0))) - if (! rates.contains (ratesToTest[i])) - rates.addSorted (comparator, ratesToTest[i]); - } - } + if (SUCCEEDED (tempClient->IsFormatSupported (AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*) &format, 0))) + if (! rates.contains (ratesToTest[i])) + rates.addSorted (comparator, ratesToTest[i]); + } + } - ~WASAPIDeviceBase() - { - device = 0; - CloseHandle (clientEvent); - } + ~WASAPIDeviceBase() + { + device = 0; + CloseHandle (clientEvent); + } - bool isOk() const throw() { return defaultBufferSize > 0 && defaultSampleRate > 0; } + bool isOk() const throw() { return defaultBufferSize > 0 && defaultSampleRate > 0; } - bool openClient (const double newSampleRate, const BitArray& newChannels) - { - sampleRate = newSampleRate; - channels = newChannels; - channels.setRange (actualNumChannels, channels.getHighestBit() + 1 - actualNumChannels, false); - numChannels = channels.getHighestBit() + 1; + bool openClient (const double newSampleRate, const BitArray& newChannels) + { + sampleRate = newSampleRate; + channels = newChannels; + channels.setRange (actualNumChannels, channels.getHighestBit() + 1 - actualNumChannels, false); + numChannels = channels.getHighestBit() + 1; - if (numChannels == 0) - return true; + if (numChannels == 0) + return true; - client = createClient(); + client = createClient(); - if (client != 0 - && (tryInitialisingWithFormat (true, 4) || tryInitialisingWithFormat (false, 4) - || tryInitialisingWithFormat (false, 3) || tryInitialisingWithFormat (false, 2))) - { - channelMaps.clear(); - for (int i = 0; i <= channels.getHighestBit(); ++i) - if (channels[i]) - channelMaps.add (i); + if (client != 0 + && (tryInitialisingWithFormat (true, 4) || tryInitialisingWithFormat (false, 4) + || tryInitialisingWithFormat (false, 3) || tryInitialisingWithFormat (false, 2))) + { + channelMaps.clear(); + for (int i = 0; i <= channels.getHighestBit(); ++i) + if (channels[i]) + channelMaps.add (i); - REFERENCE_TIME latency; - if (OK (client->GetStreamLatency (&latency))) - latencySamples = wasapi_refTimeToSamples (latency, sampleRate); + REFERENCE_TIME latency; + if (OK (client->GetStreamLatency (&latency))) + latencySamples = wasapi_refTimeToSamples (latency, sampleRate); - (void) OK (client->GetBufferSize (&actualBufferSize)); + (void) OK (client->GetBufferSize (&actualBufferSize)); - return OK (client->SetEventHandle (clientEvent)); - } + return OK (client->SetEventHandle (clientEvent)); + } - return false; - } + return false; + } - void closeClient() - { - if (client != 0) - client->Stop(); + void closeClient() + { + if (client != 0) + client->Stop(); - client = 0; - ResetEvent (clientEvent); - } + client = 0; + ResetEvent (clientEvent); + } - ComSmartPtr device; - ComSmartPtr client; - double sampleRate, defaultSampleRate; - int numChannels, actualNumChannels; - int minBufferSize, defaultBufferSize, latencySamples; - Array rates; - HANDLE clientEvent; - BitArray channels; - AudioDataConverters::DataFormat dataFormat; - Array channelMaps; - UINT32 actualBufferSize; - int bytesPerSample; + ComSmartPtr device; + ComSmartPtr client; + double sampleRate, defaultSampleRate; + int numChannels, actualNumChannels; + int minBufferSize, defaultBufferSize, latencySamples; + Array rates; + HANDLE clientEvent; + BitArray channels; + AudioDataConverters::DataFormat dataFormat; + Array channelMaps; + UINT32 actualBufferSize; + int bytesPerSample; private: - const ComSmartPtr createClient() - { - ComSmartPtr client; + const ComSmartPtr createClient() + { + ComSmartPtr client; - if (device != 0) - { - HRESULT hr = device->Activate (__uuidof (IAudioClient), CLSCTX_INPROC_SERVER, 0, (void**) &client); - logFailure (hr); - } + if (device != 0) + { + HRESULT hr = device->Activate (__uuidof (IAudioClient), CLSCTX_INPROC_SERVER, 0, (void**) &client); + logFailure (hr); + } - return client; - } + return client; + } - bool tryInitialisingWithFormat (const bool useFloat, const int bytesPerSampleToTry) - { - WAVEFORMATEXTENSIBLE format; - zerostruct (format); + bool tryInitialisingWithFormat (const bool useFloat, const int bytesPerSampleToTry) + { + WAVEFORMATEXTENSIBLE format; + zerostruct (format); - if (numChannels <= 2 && bytesPerSampleToTry <= 2) - { - format.Format.wFormatTag = WAVE_FORMAT_PCM; - } - else - { - format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - format.Format.cbSize = sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX); - } + if (numChannels <= 2 && bytesPerSampleToTry <= 2) + { + format.Format.wFormatTag = WAVE_FORMAT_PCM; + } + else + { + format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + format.Format.cbSize = sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX); + } - format.Format.nSamplesPerSec = roundDoubleToInt (sampleRate); - format.Format.nChannels = (WORD) numChannels; - format.Format.wBitsPerSample = (WORD) (8 * bytesPerSampleToTry); - format.Format.nAvgBytesPerSec = (DWORD) (format.Format.nSamplesPerSec * numChannels * bytesPerSampleToTry); - format.Format.nBlockAlign = (WORD) (numChannels * bytesPerSampleToTry); - format.SubFormat = useFloat ? KSDATAFORMAT_SUBTYPE_IEEE_FLOAT : KSDATAFORMAT_SUBTYPE_PCM; - format.Samples.wValidBitsPerSample = format.Format.wBitsPerSample; + format.Format.nSamplesPerSec = roundDoubleToInt (sampleRate); + format.Format.nChannels = (WORD) numChannels; + format.Format.wBitsPerSample = (WORD) (8 * bytesPerSampleToTry); + format.Format.nAvgBytesPerSec = (DWORD) (format.Format.nSamplesPerSec * numChannels * bytesPerSampleToTry); + format.Format.nBlockAlign = (WORD) (numChannels * bytesPerSampleToTry); + format.SubFormat = useFloat ? KSDATAFORMAT_SUBTYPE_IEEE_FLOAT : KSDATAFORMAT_SUBTYPE_PCM; + format.Samples.wValidBitsPerSample = format.Format.wBitsPerSample; - switch (numChannels) - { - case 1: format.dwChannelMask = SPEAKER_FRONT_CENTER; break; - case 2: format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break; - case 4: format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break; - case 6: format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break; - case 8: format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER; break; - default: break; - } + switch (numChannels) + { + case 1: format.dwChannelMask = SPEAKER_FRONT_CENTER; break; + case 2: format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break; + case 4: format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break; + case 6: format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break; + case 8: format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER; break; + default: break; + } - WAVEFORMATEXTENSIBLE* nearestFormat = 0; + WAVEFORMATEXTENSIBLE* nearestFormat = 0; - HRESULT hr = client->IsFormatSupported (AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*) &format, (WAVEFORMATEX**) &nearestFormat); - logFailure (hr); + HRESULT hr = client->IsFormatSupported (AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*) &format, (WAVEFORMATEX**) &nearestFormat); + logFailure (hr); - if (hr == S_FALSE && format.Format.nSamplesPerSec == nearestFormat->Format.nSamplesPerSec) - { - wasapi_copyWavFormat (format, (WAVEFORMATEX*) nearestFormat); - hr = S_OK; - } + if (hr == S_FALSE && format.Format.nSamplesPerSec == nearestFormat->Format.nSamplesPerSec) + { + wasapi_copyWavFormat (format, (WAVEFORMATEX*) nearestFormat); + hr = S_OK; + } - CoTaskMemFree (nearestFormat); + CoTaskMemFree (nearestFormat); - GUID session; - if (hr == S_OK - && OK (client->Initialize (AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - 0, 0, (WAVEFORMATEX*) &format, &session))) - { - actualNumChannels = format.Format.nChannels; - const bool isFloat = format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - bytesPerSample = format.Format.wBitsPerSample / 8; - dataFormat = isFloat ? AudioDataConverters::float32LE - : (bytesPerSample == 4 ? AudioDataConverters::int32LE - : ((bytesPerSample == 3 ? AudioDataConverters::int24LE - : AudioDataConverters::int16LE))); - return true; - } + GUID session; + if (hr == S_OK + && OK (client->Initialize (AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + 0, 0, (WAVEFORMATEX*) &format, &session))) + { + actualNumChannels = format.Format.nChannels; + const bool isFloat = format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + bytesPerSample = format.Format.wBitsPerSample / 8; + dataFormat = isFloat ? AudioDataConverters::float32LE + : (bytesPerSample == 4 ? AudioDataConverters::int32LE + : ((bytesPerSample == 3 ? AudioDataConverters::int24LE + : AudioDataConverters::int16LE))); + return true; + } - return false; - } + return false; + } }; class WASAPIInputDevice : public WASAPIDeviceBase { public: - WASAPIInputDevice (const ComSmartPtr & device_) - : WASAPIDeviceBase (device_), - reservoir (1, 1) - { - } + WASAPIInputDevice (const ComSmartPtr & device_) + : WASAPIDeviceBase (device_), + reservoir (1, 1) + { + } - ~WASAPIInputDevice() - { - close(); - } + ~WASAPIInputDevice() + { + close(); + } - bool open (const double newSampleRate, const BitArray& newChannels) - { - reservoirSize = 0; - reservoirCapacity = 16384; - reservoir.setSize (actualNumChannels * reservoirCapacity * sizeof (float)); - return openClient (newSampleRate, newChannels) - && (numChannels == 0 || OK (client->GetService (__uuidof (IAudioCaptureClient), (void**) &captureClient))); - } + bool open (const double newSampleRate, const BitArray& newChannels) + { + reservoirSize = 0; + reservoirCapacity = 16384; + reservoir.setSize (actualNumChannels * reservoirCapacity * sizeof (float)); + return openClient (newSampleRate, newChannels) + && (numChannels == 0 || OK (client->GetService (__uuidof (IAudioCaptureClient), (void**) &captureClient))); + } - void close() - { - closeClient(); - captureClient = 0; - reservoir.setSize (0); - } + void close() + { + closeClient(); + captureClient = 0; + reservoir.setSize (0); + } - void copyBuffers (float** destBuffers, int numDestBuffers, int bufferSize, Thread& thread) - { - if (numChannels <= 0) - return; + void copyBuffers (float** destBuffers, int numDestBuffers, int bufferSize, Thread& thread) + { + if (numChannels <= 0) + return; - int offset = 0; + int offset = 0; - while (bufferSize > 0) - { - if (reservoirSize > 0) // There's stuff in the reservoir, so use that... - { - const int samplesToDo = jmin (bufferSize, (int) reservoirSize); + while (bufferSize > 0) + { + if (reservoirSize > 0) // There's stuff in the reservoir, so use that... + { + const int samplesToDo = jmin (bufferSize, (int) reservoirSize); - for (int i = 0; i < numDestBuffers; ++i) - { - float* const dest = destBuffers[i] + offset; - const int srcChan = channelMaps.getUnchecked(i); + for (int i = 0; i < numDestBuffers; ++i) + { + float* const dest = destBuffers[i] + offset; + const int srcChan = channelMaps.getUnchecked(i); - switch (dataFormat) - { - case AudioDataConverters::float32LE: - AudioDataConverters::convertFloat32LEToFloat (((uint8*) reservoir.getData()) + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels); - break; + switch (dataFormat) + { + case AudioDataConverters::float32LE: + AudioDataConverters::convertFloat32LEToFloat (((uint8*) reservoir.getData()) + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels); + break; - case AudioDataConverters::int32LE: - AudioDataConverters::convertInt32LEToFloat (((uint8*) reservoir.getData()) + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels); - break; + case AudioDataConverters::int32LE: + AudioDataConverters::convertInt32LEToFloat (((uint8*) reservoir.getData()) + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels); + break; - case AudioDataConverters::int24LE: - AudioDataConverters::convertInt24LEToFloat (((uint8*) reservoir.getData()) + 3 * srcChan, dest, samplesToDo, 3 * actualNumChannels); - break; + case AudioDataConverters::int24LE: + AudioDataConverters::convertInt24LEToFloat (((uint8*) reservoir.getData()) + 3 * srcChan, dest, samplesToDo, 3 * actualNumChannels); + break; - case AudioDataConverters::int16LE: - AudioDataConverters::convertInt16LEToFloat (((uint8*) reservoir.getData()) + 2 * srcChan, dest, samplesToDo, 2 * actualNumChannels); - break; + case AudioDataConverters::int16LE: + AudioDataConverters::convertInt16LEToFloat (((uint8*) reservoir.getData()) + 2 * srcChan, dest, samplesToDo, 2 * actualNumChannels); + break; - default: jassertfalse; break; - } - } + default: jassertfalse; break; + } + } - bufferSize -= samplesToDo; - offset += samplesToDo; - reservoirSize -= samplesToDo; - } - else - { - UINT32 packetLength = 0; - if (! OK (captureClient->GetNextPacketSize (&packetLength))) - break; + bufferSize -= samplesToDo; + offset += samplesToDo; + reservoirSize -= samplesToDo; + } + else + { + UINT32 packetLength = 0; + if (! OK (captureClient->GetNextPacketSize (&packetLength))) + break; - if (packetLength == 0) - { - if (thread.threadShouldExit()) - break; + if (packetLength == 0) + { + if (thread.threadShouldExit()) + break; - Thread::sleep (1); - continue; - } + Thread::sleep (1); + continue; + } - uint8* inputData = 0; - UINT32 numSamplesAvailable; - DWORD flags; + uint8* inputData = 0; + UINT32 numSamplesAvailable; + DWORD flags; - if (OK (captureClient->GetBuffer (&inputData, &numSamplesAvailable, &flags, 0, 0))) - { - const int samplesToDo = jmin (bufferSize, (int) numSamplesAvailable); + if (OK (captureClient->GetBuffer (&inputData, &numSamplesAvailable, &flags, 0, 0))) + { + const int samplesToDo = jmin (bufferSize, (int) numSamplesAvailable); - for (int i = 0; i < numDestBuffers; ++i) - { - float* const dest = destBuffers[i] + offset; - const int srcChan = channelMaps.getUnchecked(i); + for (int i = 0; i < numDestBuffers; ++i) + { + float* const dest = destBuffers[i] + offset; + const int srcChan = channelMaps.getUnchecked(i); - switch (dataFormat) - { - case AudioDataConverters::float32LE: - AudioDataConverters::convertFloat32LEToFloat (inputData + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels); - break; + switch (dataFormat) + { + case AudioDataConverters::float32LE: + AudioDataConverters::convertFloat32LEToFloat (inputData + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels); + break; - case AudioDataConverters::int32LE: - AudioDataConverters::convertInt32LEToFloat (inputData + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels); - break; + case AudioDataConverters::int32LE: + AudioDataConverters::convertInt32LEToFloat (inputData + 4 * srcChan, dest, samplesToDo, 4 * actualNumChannels); + break; - case AudioDataConverters::int24LE: - AudioDataConverters::convertInt24LEToFloat (inputData + 3 * srcChan, dest, samplesToDo, 3 * actualNumChannels); - break; + case AudioDataConverters::int24LE: + AudioDataConverters::convertInt24LEToFloat (inputData + 3 * srcChan, dest, samplesToDo, 3 * actualNumChannels); + break; - case AudioDataConverters::int16LE: - AudioDataConverters::convertInt16LEToFloat (inputData + 2 * srcChan, dest, samplesToDo, 2 * actualNumChannels); - break; + case AudioDataConverters::int16LE: + AudioDataConverters::convertInt16LEToFloat (inputData + 2 * srcChan, dest, samplesToDo, 2 * actualNumChannels); + break; - default: jassertfalse; break; - } - } + default: jassertfalse; break; + } + } - bufferSize -= samplesToDo; - offset += samplesToDo; + bufferSize -= samplesToDo; + offset += samplesToDo; - if (samplesToDo < numSamplesAvailable) - { - reservoirSize = jmin (numSamplesAvailable - samplesToDo, reservoirCapacity); - memcpy ((uint8*) reservoir.getData(), inputData + bytesPerSample * actualNumChannels * samplesToDo, - bytesPerSample * actualNumChannels * reservoirSize); - } + if (samplesToDo < numSamplesAvailable) + { + reservoirSize = jmin ((int) (numSamplesAvailable - samplesToDo), reservoirCapacity); + memcpy ((uint8*) reservoir.getData(), inputData + bytesPerSample * actualNumChannels * samplesToDo, + bytesPerSample * actualNumChannels * reservoirSize); + } - captureClient->ReleaseBuffer (numSamplesAvailable); - } - } - } - } + captureClient->ReleaseBuffer (numSamplesAvailable); + } + } + } + } - ComSmartPtr captureClient; - MemoryBlock reservoir; - int reservoirSize, reservoirCapacity; + ComSmartPtr captureClient; + MemoryBlock reservoir; + int reservoirSize, reservoirCapacity; }; class WASAPIOutputDevice : public WASAPIDeviceBase { public: - WASAPIOutputDevice (const ComSmartPtr & device_) - : WASAPIDeviceBase (device_) - { - } + WASAPIOutputDevice (const ComSmartPtr & device_) + : WASAPIDeviceBase (device_) + { + } - ~WASAPIOutputDevice() - { - close(); - } + ~WASAPIOutputDevice() + { + close(); + } - bool open (const double newSampleRate, const BitArray& newChannels) - { - return openClient (newSampleRate, newChannels) - && (numChannels == 0 || OK (client->GetService (__uuidof (IAudioRenderClient), (void**) &renderClient))); - } + bool open (const double newSampleRate, const BitArray& newChannels) + { + return openClient (newSampleRate, newChannels) + && (numChannels == 0 || OK (client->GetService (__uuidof (IAudioRenderClient), (void**) &renderClient))); + } - void close() - { - closeClient(); - renderClient = 0; - } + void close() + { + closeClient(); + renderClient = 0; + } - void copyBuffers (const float** const srcBuffers, const int numSrcBuffers, int bufferSize, Thread& thread) - { - if (numChannels <= 0) - return; + void copyBuffers (const float** const srcBuffers, const int numSrcBuffers, int bufferSize, Thread& thread) + { + if (numChannels <= 0) + return; - int offset = 0; + int offset = 0; - while (bufferSize > 0) - { - UINT32 padding = 0; - if (! OK (client->GetCurrentPadding (&padding))) - return; + while (bufferSize > 0) + { + UINT32 padding = 0; + if (! OK (client->GetCurrentPadding (&padding))) + return; - const int samplesToDo = jmin ((int) (actualBufferSize - padding), bufferSize); + const int samplesToDo = jmin ((int) (actualBufferSize - padding), bufferSize); - if (samplesToDo <= 0) - { - if (thread.threadShouldExit()) - break; + if (samplesToDo <= 0) + { + if (thread.threadShouldExit()) + break; - Thread::sleep (0); - continue; - } + Thread::sleep (0); + continue; + } - uint8* outputData = 0; - if (OK (renderClient->GetBuffer (samplesToDo, &outputData))) - { - for (int i = 0; i < numSrcBuffers; ++i) - { - const float* const source = srcBuffers[i] + offset; - const int destChan = channelMaps.getUnchecked(i); + uint8* outputData = 0; + if (OK (renderClient->GetBuffer (samplesToDo, &outputData))) + { + for (int i = 0; i < numSrcBuffers; ++i) + { + const float* const source = srcBuffers[i] + offset; + const int destChan = channelMaps.getUnchecked(i); - switch (dataFormat) - { - case AudioDataConverters::float32LE: - AudioDataConverters::convertFloatToFloat32LE (source, outputData + 4 * destChan, samplesToDo, 4 * actualNumChannels); - break; + switch (dataFormat) + { + case AudioDataConverters::float32LE: + AudioDataConverters::convertFloatToFloat32LE (source, outputData + 4 * destChan, samplesToDo, 4 * actualNumChannels); + break; - case AudioDataConverters::int32LE: - AudioDataConverters::convertFloatToInt32LE (source, outputData + 4 * destChan, samplesToDo, 4 * actualNumChannels); - break; + case AudioDataConverters::int32LE: + AudioDataConverters::convertFloatToInt32LE (source, outputData + 4 * destChan, samplesToDo, 4 * actualNumChannels); + break; - case AudioDataConverters::int24LE: - AudioDataConverters::convertFloatToInt24LE (source, outputData + 3 * destChan, samplesToDo, 3 * actualNumChannels); - break; + case AudioDataConverters::int24LE: + AudioDataConverters::convertFloatToInt24LE (source, outputData + 3 * destChan, samplesToDo, 3 * actualNumChannels); + break; - case AudioDataConverters::int16LE: - AudioDataConverters::convertFloatToInt16LE (source, outputData + 2 * destChan, samplesToDo, 2 * actualNumChannels); - break; + case AudioDataConverters::int16LE: + AudioDataConverters::convertFloatToInt16LE (source, outputData + 2 * destChan, samplesToDo, 2 * actualNumChannels); + break; - default: jassertfalse; break; - } - } + default: jassertfalse; break; + } + } - renderClient->ReleaseBuffer (samplesToDo, 0); + renderClient->ReleaseBuffer (samplesToDo, 0); - offset += samplesToDo; - bufferSize -= samplesToDo; - } - } - } + offset += samplesToDo; + bufferSize -= samplesToDo; + } + } + } - ComSmartPtr renderClient; + ComSmartPtr renderClient; }; class WASAPIAudioIODevice : public AudioIODevice, - public Thread + public Thread { public: - WASAPIAudioIODevice (const String& deviceName, - const String& outputDeviceId_, - const String& inputDeviceId_) - : AudioIODevice (deviceName, "Windows Audio"), - Thread ("Juce WASAPI"), - isOpen_ (false), - isStarted (false), - outputDevice (0), - outputDeviceId (outputDeviceId_), - inputDevice (0), - inputDeviceId (inputDeviceId_), - currentBufferSizeSamples (0), - currentSampleRate (0), - callback (0) - { - } + WASAPIAudioIODevice (const String& deviceName, + const String& outputDeviceId_, + const String& inputDeviceId_) + : AudioIODevice (deviceName, "Windows Audio"), + Thread ("Juce WASAPI"), + isOpen_ (false), + isStarted (false), + outputDevice (0), + outputDeviceId (outputDeviceId_), + inputDevice (0), + inputDeviceId (inputDeviceId_), + currentBufferSizeSamples (0), + currentSampleRate (0), + callback (0) + { + } - ~WASAPIAudioIODevice() - { - close(); + ~WASAPIAudioIODevice() + { + close(); - deleteAndZero (inputDevice); - deleteAndZero (outputDevice); - } + deleteAndZero (inputDevice); + deleteAndZero (outputDevice); + } - bool initialise() - { - double defaultSampleRateIn = 0, defaultSampleRateOut = 0; - int minBufferSizeIn = 0, defaultBufferSizeIn = 0, minBufferSizeOut = 0, defaultBufferSizeOut = 0; - latencyIn = latencyOut = 0; - Array ratesIn, ratesOut; + bool initialise() + { + double defaultSampleRateIn = 0, defaultSampleRateOut = 0; + int minBufferSizeIn = 0, defaultBufferSizeIn = 0, minBufferSizeOut = 0, defaultBufferSizeOut = 0; + latencyIn = latencyOut = 0; + Array ratesIn, ratesOut; - if (createDevices()) - { - jassert (inputDevice != 0 || outputDevice != 0); + if (createDevices()) + { + jassert (inputDevice != 0 || outputDevice != 0); - if (inputDevice != 0 && outputDevice != 0) - { - defaultSampleRate = jmin (inputDevice->defaultSampleRate, outputDevice->defaultSampleRate); - minBufferSize = jmin (inputDevice->minBufferSize, outputDevice->minBufferSize); - defaultBufferSize = jmax (inputDevice->defaultBufferSize, outputDevice->defaultBufferSize); - sampleRates = inputDevice->rates; - sampleRates.removeValuesNotIn (outputDevice->rates); - } - else - { - WASAPIDeviceBase* const d = inputDevice != 0 ? (WASAPIDeviceBase*) inputDevice : (WASAPIDeviceBase*) outputDevice; - defaultSampleRate = d->defaultSampleRate; - minBufferSize = d->minBufferSize; - defaultBufferSize = d->defaultBufferSize; - sampleRates = d->rates; - } + if (inputDevice != 0 && outputDevice != 0) + { + defaultSampleRate = jmin (inputDevice->defaultSampleRate, outputDevice->defaultSampleRate); + minBufferSize = jmin (inputDevice->minBufferSize, outputDevice->minBufferSize); + defaultBufferSize = jmax (inputDevice->defaultBufferSize, outputDevice->defaultBufferSize); + sampleRates = inputDevice->rates; + sampleRates.removeValuesNotIn (outputDevice->rates); + } + else + { + WASAPIDeviceBase* const d = inputDevice != 0 ? (WASAPIDeviceBase*) inputDevice : (WASAPIDeviceBase*) outputDevice; + defaultSampleRate = d->defaultSampleRate; + minBufferSize = d->minBufferSize; + defaultBufferSize = d->defaultBufferSize; + sampleRates = d->rates; + } - IntegerElementComparator comparator; - bufferSizes.addSorted (comparator, defaultBufferSize); - if (minBufferSize != defaultBufferSize) - bufferSizes.addSorted (comparator, minBufferSize); + IntegerElementComparator comparator; + bufferSizes.addSorted (comparator, defaultBufferSize); + if (minBufferSize != defaultBufferSize) + bufferSizes.addSorted (comparator, minBufferSize); - int n = 64; - for (int i = 0; i < 40; ++i) - { - if (n >= minBufferSize && n <= 2048 && ! bufferSizes.contains (n)) - bufferSizes.addSorted (comparator, n); + int n = 64; + for (int i = 0; i < 40; ++i) + { + if (n >= minBufferSize && n <= 2048 && ! bufferSizes.contains (n)) + bufferSizes.addSorted (comparator, n); - n += (n < 512) ? 32 : (n < 1024 ? 64 : 128); - } + n += (n < 512) ? 32 : (n < 1024 ? 64 : 128); + } - return true; - } + return true; + } - return false; - } + return false; + } - const StringArray getOutputChannelNames() - { - StringArray outChannels; + const StringArray getOutputChannelNames() + { + StringArray outChannels; - if (outputDevice != 0) - for (int i = 1; i <= outputDevice->actualNumChannels; ++i) - outChannels.add ("Output channel " + String (i)); + if (outputDevice != 0) + for (int i = 1; i <= outputDevice->actualNumChannels; ++i) + outChannels.add ("Output channel " + String (i)); - return outChannels; - } + return outChannels; + } - const StringArray getInputChannelNames() - { - StringArray inChannels; + const StringArray getInputChannelNames() + { + StringArray inChannels; - if (inputDevice != 0) - for (int i = 1; i <= inputDevice->actualNumChannels; ++i) - inChannels.add ("Input channel " + String (i)); + if (inputDevice != 0) + for (int i = 1; i <= inputDevice->actualNumChannels; ++i) + inChannels.add ("Input channel " + String (i)); - return inChannels; - } + return inChannels; + } - int getNumSampleRates() { return sampleRates.size(); } - double getSampleRate (int index) { return sampleRates [index]; } - int getNumBufferSizesAvailable() { return bufferSizes.size(); } - int getBufferSizeSamples (int index) { return bufferSizes [index]; } - int getDefaultBufferSize() { return defaultBufferSize; } + int getNumSampleRates() { return sampleRates.size(); } + double getSampleRate (int index) { return sampleRates [index]; } + int getNumBufferSizesAvailable() { return bufferSizes.size(); } + int getBufferSizeSamples (int index) { return bufferSizes [index]; } + int getDefaultBufferSize() { return defaultBufferSize; } - int getCurrentBufferSizeSamples() { return currentBufferSizeSamples; } - double getCurrentSampleRate() { return currentSampleRate; } - int getCurrentBitDepth() { return 32; } - int getOutputLatencyInSamples() { return latencyOut; } - int getInputLatencyInSamples() { return latencyIn; } - const BitArray getActiveOutputChannels() const { return outputDevice != 0 ? outputDevice->channels : BitArray(); } - const BitArray getActiveInputChannels() const { return inputDevice != 0 ? inputDevice->channels : BitArray(); } - const String getLastError() { return lastError; } + int getCurrentBufferSizeSamples() { return currentBufferSizeSamples; } + double getCurrentSampleRate() { return currentSampleRate; } + int getCurrentBitDepth() { return 32; } + int getOutputLatencyInSamples() { return latencyOut; } + int getInputLatencyInSamples() { return latencyIn; } + const BitArray getActiveOutputChannels() const { return outputDevice != 0 ? outputDevice->channels : BitArray(); } + const BitArray getActiveInputChannels() const { return inputDevice != 0 ? inputDevice->channels : BitArray(); } + const String getLastError() { return lastError; } - const String open (const BitArray& inputChannels, const BitArray& outputChannels, - double sampleRate, int bufferSizeSamples) - { - close(); - lastError = String::empty; + const String open (const BitArray& inputChannels, const BitArray& outputChannels, + double sampleRate, int bufferSizeSamples) + { + close(); + lastError = String::empty; - if (sampleRates.size() == 0 && inputDevice != 0 && outputDevice != 0) - { - lastError = "The input and output devices don't share a common sample rate!"; - return lastError; - } + if (sampleRates.size() == 0 && inputDevice != 0 && outputDevice != 0) + { + lastError = "The input and output devices don't share a common sample rate!"; + return lastError; + } - currentBufferSizeSamples = bufferSizeSamples <= 0 ? defaultBufferSize : jmax (bufferSizeSamples, minBufferSize); - currentSampleRate = sampleRate > 0 ? sampleRate : defaultSampleRate; + currentBufferSizeSamples = bufferSizeSamples <= 0 ? defaultBufferSize : jmax (bufferSizeSamples, minBufferSize); + currentSampleRate = sampleRate > 0 ? sampleRate : defaultSampleRate; - if (inputDevice != 0 && ! inputDevice->open (currentSampleRate, inputChannels)) - { - lastError = "Couldn't open the input device!"; - return lastError; - } + if (inputDevice != 0 && ! inputDevice->open (currentSampleRate, inputChannels)) + { + lastError = "Couldn't open the input device!"; + return lastError; + } - if (outputDevice != 0 && ! outputDevice->open (currentSampleRate, outputChannels)) - { - close(); - lastError = "Couldn't open the output device!"; - return lastError; - } + if (outputDevice != 0 && ! outputDevice->open (currentSampleRate, outputChannels)) + { + close(); + lastError = "Couldn't open the output device!"; + return lastError; + } - if (inputDevice != 0) - ResetEvent (inputDevice->clientEvent); - if (outputDevice != 0) - ResetEvent (outputDevice->clientEvent); + if (inputDevice != 0) + ResetEvent (inputDevice->clientEvent); + if (outputDevice != 0) + ResetEvent (outputDevice->clientEvent); - startThread (8); - Thread::sleep (5); + startThread (8); + Thread::sleep (5); - if (inputDevice != 0 && inputDevice->client != 0) - { - latencyIn = inputDevice->latencySamples + inputDevice->actualBufferSize + inputDevice->minBufferSize; - HRESULT hr = inputDevice->client->Start(); - logFailure (hr); //xxx handle this - } + if (inputDevice != 0 && inputDevice->client != 0) + { + latencyIn = inputDevice->latencySamples + inputDevice->actualBufferSize + inputDevice->minBufferSize; + HRESULT hr = inputDevice->client->Start(); + logFailure (hr); //xxx handle this + } - if (outputDevice != 0 && outputDevice->client != 0) - { - latencyOut = outputDevice->latencySamples + outputDevice->actualBufferSize + outputDevice->minBufferSize; - HRESULT hr = outputDevice->client->Start(); - logFailure (hr); //xxx handle this - } + if (outputDevice != 0 && outputDevice->client != 0) + { + latencyOut = outputDevice->latencySamples + outputDevice->actualBufferSize + outputDevice->minBufferSize; + HRESULT hr = outputDevice->client->Start(); + logFailure (hr); //xxx handle this + } - isOpen_ = true; - return lastError; - } + isOpen_ = true; + return lastError; + } - void close() - { - stop(); + void close() + { + stop(); - if (inputDevice != 0) - SetEvent (inputDevice->clientEvent); + if (inputDevice != 0) + SetEvent (inputDevice->clientEvent); - if (outputDevice != 0) - SetEvent (outputDevice->clientEvent); + if (outputDevice != 0) + SetEvent (outputDevice->clientEvent); - stopThread (5000); + stopThread (5000); - if (inputDevice != 0) - inputDevice->close(); + if (inputDevice != 0) + inputDevice->close(); - if (outputDevice != 0) - outputDevice->close(); + if (outputDevice != 0) + outputDevice->close(); - isOpen_ = false; - } + isOpen_ = false; + } - bool isOpen() { return isOpen_ && isThreadRunning(); } - bool isPlaying() { return isStarted && isOpen_ && isThreadRunning(); } + bool isOpen() { return isOpen_ && isThreadRunning(); } + bool isPlaying() { return isStarted && isOpen_ && isThreadRunning(); } - void start (AudioIODeviceCallback* call) - { - if (isOpen_ && call != 0 && ! isStarted) - { - if (! isThreadRunning()) - { - // something's gone wrong and the thread's stopped.. - isOpen_ = false; - return; - } + void start (AudioIODeviceCallback* call) + { + if (isOpen_ && call != 0 && ! isStarted) + { + if (! isThreadRunning()) + { + // something's gone wrong and the thread's stopped.. + isOpen_ = false; + return; + } - call->audioDeviceAboutToStart (this); + call->audioDeviceAboutToStart (this); - const ScopedLock sl (startStopLock); - callback = call; - isStarted = true; - } - } + const ScopedLock sl (startStopLock); + callback = call; + isStarted = true; + } + } - void stop() - { - if (isStarted) - { - AudioIODeviceCallback* const callbackLocal = callback; + void stop() + { + if (isStarted) + { + AudioIODeviceCallback* const callbackLocal = callback; - { - const ScopedLock sl (startStopLock); - isStarted = false; - } + { + const ScopedLock sl (startStopLock); + isStarted = false; + } - if (callbackLocal != 0) - callbackLocal->audioDeviceStopped(); - } - } + if (callbackLocal != 0) + callbackLocal->audioDeviceStopped(); + } + } - void run() - { - const int bufferSize = currentBufferSizeSamples; + void run() + { + const int bufferSize = currentBufferSizeSamples; - HANDLE events[2]; - int numEvents = 0; - if (inputDevice != 0) - events [numEvents++] = inputDevice->clientEvent; - if (outputDevice != 0) - events [numEvents++] = outputDevice->clientEvent; + HANDLE events[2]; + int numEvents = 0; + if (inputDevice != 0) + events [numEvents++] = inputDevice->clientEvent; + if (outputDevice != 0) + events [numEvents++] = outputDevice->clientEvent; - const int numInputBuffers = getActiveInputChannels().countNumberOfSetBits(); - const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); + const int numInputBuffers = getActiveInputChannels().countNumberOfSetBits(); + const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); - AudioSampleBuffer ins (jmax (1, numInputBuffers), bufferSize + 32); - AudioSampleBuffer outs (jmax (1, numOutputBuffers), bufferSize + 32); - float** const inputBuffers = ins.getArrayOfChannels(); - float** const outputBuffers = outs.getArrayOfChannels(); - ins.clear(); + AudioSampleBuffer ins (jmax (1, numInputBuffers), bufferSize + 32); + AudioSampleBuffer outs (jmax (1, numOutputBuffers), bufferSize + 32); + float** const inputBuffers = ins.getArrayOfChannels(); + float** const outputBuffers = outs.getArrayOfChannels(); + ins.clear(); - while (! threadShouldExit()) - { - const DWORD result = WaitForMultipleObjects (numEvents, events, true, 1000); + while (! threadShouldExit()) + { + const DWORD result = WaitForMultipleObjects (numEvents, events, true, 1000); - if (result == WAIT_TIMEOUT) - continue; + if (result == WAIT_TIMEOUT) + continue; - if (threadShouldExit()) - break; + if (threadShouldExit()) + break; - if (inputDevice != 0) - inputDevice->copyBuffers (inputBuffers, numInputBuffers, bufferSize, *this); + if (inputDevice != 0) + inputDevice->copyBuffers (inputBuffers, numInputBuffers, bufferSize, *this); - // Make the callback.. - { - const ScopedLock sl (startStopLock); + // Make the callback.. + { + const ScopedLock sl (startStopLock); - if (isStarted) - { - JUCE_TRY - { - callback->audioDeviceIOCallback ((const float**) inputBuffers, - numInputBuffers, - outputBuffers, - numOutputBuffers, - bufferSize); - } - JUCE_CATCH_EXCEPTION - } - else - { - outs.clear(); - } - } + if (isStarted) + { + JUCE_TRY + { + callback->audioDeviceIOCallback ((const float**) inputBuffers, + numInputBuffers, + outputBuffers, + numOutputBuffers, + bufferSize); + } + JUCE_CATCH_EXCEPTION + } + else + { + outs.clear(); + } + } - if (outputDevice != 0) - outputDevice->copyBuffers ((const float**) outputBuffers, numOutputBuffers, bufferSize, *this); - } - } + if (outputDevice != 0) + outputDevice->copyBuffers ((const float**) outputBuffers, numOutputBuffers, bufferSize, *this); + } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - String outputDeviceId, inputDeviceId; - String lastError; + String outputDeviceId, inputDeviceId; + String lastError; private: - // Device stats... - WASAPIInputDevice* inputDevice; - WASAPIOutputDevice* outputDevice; - double defaultSampleRate; - int minBufferSize, defaultBufferSize; - int latencyIn, latencyOut; - Array sampleRates; - Array bufferSizes; + // Device stats... + WASAPIInputDevice* inputDevice; + WASAPIOutputDevice* outputDevice; + double defaultSampleRate; + int minBufferSize, defaultBufferSize; + int latencyIn, latencyOut; + Array sampleRates; + Array bufferSizes; - // Active state... - bool isOpen_, isStarted; - int currentBufferSizeSamples; - double currentSampleRate; + // Active state... + bool isOpen_, isStarted; + int currentBufferSizeSamples; + double currentSampleRate; - AudioIODeviceCallback* callback; - CriticalSection startStopLock; + AudioIODeviceCallback* callback; + CriticalSection startStopLock; - bool createDevices() - { - ComSmartPtr enumerator; - if (! OK (enumerator.CoCreateInstance (__uuidof (MMDeviceEnumerator), CLSCTX_INPROC_SERVER))) - return false; + bool createDevices() + { + ComSmartPtr enumerator; + if (! OK (enumerator.CoCreateInstance (__uuidof (MMDeviceEnumerator), CLSCTX_INPROC_SERVER))) + return false; - ComSmartPtr deviceCollection; - if (! OK (enumerator->EnumAudioEndpoints (eAll, DEVICE_STATE_ACTIVE, &deviceCollection))) - return false; + ComSmartPtr deviceCollection; + if (! OK (enumerator->EnumAudioEndpoints (eAll, DEVICE_STATE_ACTIVE, &deviceCollection))) + return false; - UINT32 numDevices = 0; - if (! OK (deviceCollection->GetCount (&numDevices))) - return false; + UINT32 numDevices = 0; + if (! OK (deviceCollection->GetCount (&numDevices))) + return false; - for (UINT32 i = 0; i < numDevices; ++i) - { - ComSmartPtr device; - if (! OK (deviceCollection->Item (i, &device))) - continue; + for (UINT32 i = 0; i < numDevices; ++i) + { + ComSmartPtr device; + if (! OK (deviceCollection->Item (i, &device))) + continue; - const String deviceId (wasapi_getDeviceID (device)); - if (deviceId.isEmpty()) - continue; + const String deviceId (wasapi_getDeviceID (device)); + if (deviceId.isEmpty()) + continue; - const EDataFlow flow = wasapi_getDataFlow (device); + const EDataFlow flow = wasapi_getDataFlow (device); - if (deviceId == inputDeviceId && flow == eCapture) - inputDevice = new WASAPIInputDevice (device); - else if (deviceId == outputDeviceId && flow == eRender) - outputDevice = new WASAPIOutputDevice (device); - } + if (deviceId == inputDeviceId && flow == eCapture) + inputDevice = new WASAPIInputDevice (device); + else if (deviceId == outputDeviceId && flow == eRender) + outputDevice = new WASAPIOutputDevice (device); + } - return (outputDeviceId.isEmpty() || (outputDevice != 0 && outputDevice->isOk())) - && (inputDeviceId.isEmpty() || (inputDevice != 0 && inputDevice->isOk())); - } + return (outputDeviceId.isEmpty() || (outputDevice != 0 && outputDevice->isOk())) + && (inputDeviceId.isEmpty() || (inputDevice != 0 && inputDevice->isOk())); + } - WASAPIAudioIODevice (const WASAPIAudioIODevice&); - const WASAPIAudioIODevice& operator= (const WASAPIAudioIODevice&); + WASAPIAudioIODevice (const WASAPIAudioIODevice&); + const WASAPIAudioIODevice& operator= (const WASAPIAudioIODevice&); }; class WASAPIAudioIODeviceType : public AudioIODeviceType { public: - WASAPIAudioIODeviceType() - : AudioIODeviceType (T("Windows Audio")), - hasScanned (false) - { - } + WASAPIAudioIODeviceType() + : AudioIODeviceType (T("Windows Audio")), + hasScanned (false) + { + } - ~WASAPIAudioIODeviceType() - { - } + ~WASAPIAudioIODeviceType() + { + } - void scanForDevices() - { - hasScanned = true; + void scanForDevices() + { + hasScanned = true; - outputDeviceNames.clear(); - inputDeviceNames.clear(); - outputDeviceIds.clear(); - inputDeviceIds.clear(); + outputDeviceNames.clear(); + inputDeviceNames.clear(); + outputDeviceIds.clear(); + inputDeviceIds.clear(); - ComSmartPtr enumerator; - if (! OK (enumerator.CoCreateInstance (__uuidof (MMDeviceEnumerator), CLSCTX_INPROC_SERVER))) - return; + ComSmartPtr enumerator; + if (! OK (enumerator.CoCreateInstance (__uuidof (MMDeviceEnumerator), CLSCTX_INPROC_SERVER))) + return; - const String defaultRenderer = getDefaultEndpoint (enumerator, false); - const String defaultCapture = getDefaultEndpoint (enumerator, true); + const String defaultRenderer = getDefaultEndpoint (enumerator, false); + const String defaultCapture = getDefaultEndpoint (enumerator, true); - ComSmartPtr deviceCollection; - UINT32 numDevices = 0; + ComSmartPtr deviceCollection; + UINT32 numDevices = 0; - if (! (OK (enumerator->EnumAudioEndpoints (eAll, DEVICE_STATE_ACTIVE, &deviceCollection)) - && OK (deviceCollection->GetCount (&numDevices)))) - return; + if (! (OK (enumerator->EnumAudioEndpoints (eAll, DEVICE_STATE_ACTIVE, &deviceCollection)) + && OK (deviceCollection->GetCount (&numDevices)))) + return; - for (UINT32 i = 0; i < numDevices; ++i) - { - ComSmartPtr device; - if (! OK (deviceCollection->Item (i, &device))) - continue; + for (UINT32 i = 0; i < numDevices; ++i) + { + ComSmartPtr device; + if (! OK (deviceCollection->Item (i, &device))) + continue; - const String deviceId (wasapi_getDeviceID (device)); + const String deviceId (wasapi_getDeviceID (device)); - DWORD state = 0; - if (! OK (device->GetState (&state))) - continue; + DWORD state = 0; + if (! OK (device->GetState (&state))) + continue; - if (state != DEVICE_STATE_ACTIVE) - continue; + if (state != DEVICE_STATE_ACTIVE) + continue; - String name; + String name; - { - ComSmartPtr properties; - if (! OK (device->OpenPropertyStore (STGM_READ, &properties))) - continue; + { + ComSmartPtr properties; + if (! OK (device->OpenPropertyStore (STGM_READ, &properties))) + continue; - PROPVARIANT value; - PropVariantInit (&value); - if (OK (properties->GetValue (PKEY_Device_FriendlyName, &value))) - name = value.pwszVal; + PROPVARIANT value; + PropVariantInit (&value); + if (OK (properties->GetValue (PKEY_Device_FriendlyName, &value))) + name = value.pwszVal; - PropVariantClear (&value); - } + PropVariantClear (&value); + } - const EDataFlow flow = wasapi_getDataFlow (device); + const EDataFlow flow = wasapi_getDataFlow (device); - if (flow == eRender) - { - const int index = (deviceId == defaultRenderer) ? 0 : -1; - outputDeviceIds.insert (index, deviceId); - outputDeviceNames.insert (index, name); - } - else if (flow == eCapture) - { - const int index = (deviceId == defaultCapture) ? 0 : -1; - inputDeviceIds.insert (index, deviceId); - inputDeviceNames.insert (index, name); - } - } + if (flow == eRender) + { + const int index = (deviceId == defaultRenderer) ? 0 : -1; + outputDeviceIds.insert (index, deviceId); + outputDeviceNames.insert (index, name); + } + else if (flow == eCapture) + { + const int index = (deviceId == defaultCapture) ? 0 : -1; + inputDeviceIds.insert (index, deviceId); + inputDeviceNames.insert (index, name); + } + } - inputDeviceNames.appendNumbersToDuplicates (false, false); - outputDeviceNames.appendNumbersToDuplicates (false, false); - } + inputDeviceNames.appendNumbersToDuplicates (false, false); + outputDeviceNames.appendNumbersToDuplicates (false, false); + } - const StringArray getDeviceNames (const bool wantInputNames) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + const StringArray getDeviceNames (const bool wantInputNames) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - return wantInputNames ? inputDeviceNames - : outputDeviceNames; - } + return wantInputNames ? inputDeviceNames + : outputDeviceNames; + } - int getDefaultDeviceIndex (const bool /*forInput*/) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this - return 0; - } + int getDefaultDeviceIndex (const bool /*forInput*/) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this + return 0; + } - int getIndexOfDevice (AudioIODevice* device, const bool asInput) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this - WASAPIAudioIODevice* const d = dynamic_cast (device); - return d == 0 ? -1 : (asInput ? inputDeviceIds.indexOf (d->inputDeviceId) - : outputDeviceIds.indexOf (d->outputDeviceId)); - } + int getIndexOfDevice (AudioIODevice* device, const bool asInput) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this + WASAPIAudioIODevice* const d = dynamic_cast (device); + return d == 0 ? -1 : (asInput ? inputDeviceIds.indexOf (d->inputDeviceId) + : outputDeviceIds.indexOf (d->outputDeviceId)); + } - bool hasSeparateInputsAndOutputs() const { return true; } + bool hasSeparateInputsAndOutputs() const { return true; } - AudioIODevice* createDevice (const String& outputDeviceName, - const String& inputDeviceName) - { - jassert (hasScanned); // need to call scanForDevices() before doing this + AudioIODevice* createDevice (const String& outputDeviceName, + const String& inputDeviceName) + { + jassert (hasScanned); // need to call scanForDevices() before doing this - WASAPIAudioIODevice* d = 0; + WASAPIAudioIODevice* d = 0; - const int outputIndex = outputDeviceNames.indexOf (outputDeviceName); - const int inputIndex = inputDeviceNames.indexOf (inputDeviceName); + const int outputIndex = outputDeviceNames.indexOf (outputDeviceName); + const int inputIndex = inputDeviceNames.indexOf (inputDeviceName); - if (outputIndex >= 0 || inputIndex >= 0) - { - d = new WASAPIAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName - : inputDeviceName, - outputDeviceIds [outputIndex], - inputDeviceIds [inputIndex]); + if (outputIndex >= 0 || inputIndex >= 0) + { + d = new WASAPIAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName + : inputDeviceName, + outputDeviceIds [outputIndex], + inputDeviceIds [inputIndex]); - if (! d->initialise()) - deleteAndZero (d); - } + if (! d->initialise()) + deleteAndZero (d); + } - return d; - } + return d; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - StringArray outputDeviceNames, outputDeviceIds; - StringArray inputDeviceNames, inputDeviceIds; + StringArray outputDeviceNames, outputDeviceIds; + StringArray inputDeviceNames, inputDeviceIds; private: - bool hasScanned; + bool hasScanned; - static const String getDefaultEndpoint (IMMDeviceEnumerator* const enumerator, const bool forCapture) - { - String s; - IMMDevice* dev = 0; - if (OK (enumerator->GetDefaultAudioEndpoint (forCapture ? eCapture : eRender, - eMultimedia, &dev))) - { - WCHAR* deviceId = 0; - if (OK (dev->GetId (&deviceId))) - { - s = String (deviceId); - CoTaskMemFree (deviceId); - } + static const String getDefaultEndpoint (IMMDeviceEnumerator* const enumerator, const bool forCapture) + { + String s; + IMMDevice* dev = 0; + if (OK (enumerator->GetDefaultAudioEndpoint (forCapture ? eCapture : eRender, + eMultimedia, &dev))) + { + WCHAR* deviceId = 0; + if (OK (dev->GetId (&deviceId))) + { + s = String (deviceId); + CoTaskMemFree (deviceId); + } - dev->Release(); - } + dev->Release(); + } - return s; - } + return s; + } - WASAPIAudioIODeviceType (const WASAPIAudioIODeviceType&); - const WASAPIAudioIODeviceType& operator= (const WASAPIAudioIODeviceType&); + WASAPIAudioIODeviceType (const WASAPIAudioIODeviceType&); + const WASAPIAudioIODeviceType& operator= (const WASAPIAudioIODeviceType&); }; AudioIODeviceType* juce_createAudioIODeviceType_WASAPI() { - return new WASAPIAudioIODeviceType(); + return new WASAPIAudioIODeviceType(); } #undef logFailure @@ -249825,805 +227557,805 @@ AudioIODeviceType* juce_createAudioIODeviceType_WASAPI() class DShowCameraDeviceInteral : public ChangeBroadcaster { public: - DShowCameraDeviceInteral (CameraDevice* const owner_, - const ComSmartPtr & captureGraphBuilder_, - const ComSmartPtr & filter_, - int minWidth, int minHeight, - int maxWidth, int maxHeight) - : owner (owner_), - captureGraphBuilder (captureGraphBuilder_), - filter (filter_), - ok (false), - imageNeedsFlipping (false), - width (0), - height (0), - activeUsers (0), - recordNextFrameTime (false), - activeImage (0), - loadingImage (0) - { - HRESULT hr = graphBuilder.CoCreateInstance (CLSID_FilterGraph, CLSCTX_INPROC); - if (FAILED (hr)) - return; - - hr = captureGraphBuilder->SetFiltergraph (graphBuilder); - if (FAILED (hr)) - return; - - hr = graphBuilder->QueryInterface (IID_IMediaControl, (void**) &mediaControl); - if (FAILED (hr)) - return; - - { - ComSmartPtr streamConfig; - - hr = captureGraphBuilder->FindInterface (&PIN_CATEGORY_CAPTURE, - 0, - filter, - IID_IAMStreamConfig, - (void**) &streamConfig); - - if (streamConfig != 0) - { - getVideoSizes (streamConfig); - - if (! selectVideoSize (streamConfig, minWidth, minHeight, maxWidth, maxHeight)) - return; - } - } - - hr = graphBuilder->AddFilter (filter, _T("Video Capture")); - if (FAILED (hr)) - return; - - hr = smartTee.CoCreateInstance (CLSID_SmartTee, CLSCTX_INPROC_SERVER); - if (FAILED (hr)) - return; - - hr = graphBuilder->AddFilter (smartTee, _T("Smart Tee")); - if (FAILED (hr)) - return; - - if (! connectFilters (filter, smartTee)) - return; - - ComSmartPtr sampleGrabberBase; - hr = sampleGrabberBase.CoCreateInstance (CLSID_SampleGrabber, CLSCTX_INPROC_SERVER); - if (FAILED (hr)) - return; - - hr = sampleGrabberBase->QueryInterface (IID_ISampleGrabber, (void**) &sampleGrabber); - if (FAILED (hr)) - return; - - AM_MEDIA_TYPE mt; - zerostruct (mt); - mt.majortype = MEDIATYPE_Video; - mt.subtype = MEDIASUBTYPE_RGB24; - mt.formattype = FORMAT_VideoInfo; - sampleGrabber->SetMediaType (&mt); - - callback = new GrabberCallback (*this); - sampleGrabber->SetCallback (callback, 1); - - hr = graphBuilder->AddFilter (sampleGrabberBase, _T("Sample Grabber")); - if (FAILED (hr)) - return; - - ComSmartPtr grabberInputPin; - if (! (getPin (smartTee, PINDIR_OUTPUT, &smartTeeCaptureOutputPin, "capture") - && getPin (smartTee, PINDIR_OUTPUT, &smartTeePreviewOutputPin, "preview") - && getPin (sampleGrabberBase, PINDIR_INPUT, &grabberInputPin))) - return; - - hr = graphBuilder->Connect (smartTeePreviewOutputPin, grabberInputPin); - if (FAILED (hr)) - return; - - zerostruct (mt); - hr = sampleGrabber->GetConnectedMediaType (&mt); - VIDEOINFOHEADER* pVih = (VIDEOINFOHEADER*) (mt.pbFormat); - width = pVih->bmiHeader.biWidth; - height = pVih->bmiHeader.biHeight; - - ComSmartPtr nullFilter; - hr = nullFilter.CoCreateInstance (CLSID_NullRenderer, CLSCTX_INPROC_SERVER); - hr = graphBuilder->AddFilter (nullFilter, _T("Null Renderer")); - - if (connectFilters (sampleGrabberBase, nullFilter) - && addGraphToRot()) - { - activeImage = new Image (Image::RGB, width, height, true); - loadingImage = new Image (Image::RGB, width, height, true); - - ok = true; - } - } - - ~DShowCameraDeviceInteral() - { - if (mediaControl != 0) - mediaControl->Stop(); - - removeGraphFromRot(); - - for (int i = viewerComps.size(); --i >= 0;) - ((DShowCaptureViewerComp*) viewerComps.getUnchecked(i))->ownerDeleted(); - - callback = 0; - graphBuilder = 0; - sampleGrabber = 0; - mediaControl = 0; - filter = 0; - captureGraphBuilder = 0; - smartTee = 0; - smartTeePreviewOutputPin = 0; - smartTeeCaptureOutputPin = 0; - mux = 0; - fileWriter = 0; - - delete activeImage; - delete loadingImage; - } - - void addUser() - { - if (ok && activeUsers++ == 0) - mediaControl->Run(); - } - - void removeUser() - { - if (ok && --activeUsers == 0) - mediaControl->Stop(); - } - - void handleFrame (double /*time*/, BYTE* buffer, long /*bufferSize*/) - { - if (recordNextFrameTime) - { - const double defaultCameraLatency = 0.1; - - firstRecordedTime = Time::getCurrentTime() - RelativeTime (defaultCameraLatency); - recordNextFrameTime = false; - - ComSmartPtr pin; - if (getPin (filter, PINDIR_OUTPUT, &pin)) - { - ComSmartPtr pushSource; - HRESULT hr = pin->QueryInterface (IID_IAMPushSource, (void**) &pushSource); - - if (pushSource != 0) - { - REFERENCE_TIME latency = 0; - hr = pushSource->GetLatency (&latency); - - firstRecordedTime = firstRecordedTime - RelativeTime ((double) latency); - } - } - } - - imageSwapLock.enter(); - const int lineStride = width * 3; - const Image::BitmapData destData (*loadingImage, 0, 0, width, height, true); - - for (int i = 0; i < height; ++i) - memcpy (destData.getLinePointer ((height - 1) - i), - buffer + lineStride * i, - lineStride); - - imageNeedsFlipping = true; - imageSwapLock.exit(); - - callListeners (*loadingImage); - - sendChangeMessage (this); - } - - void drawCurrentImage (Graphics& g, int x, int y, int w, int h) - { - if (imageNeedsFlipping) - { - imageSwapLock.enter(); - swapVariables (loadingImage, activeImage); - imageNeedsFlipping = false; - imageSwapLock.exit(); - } - - RectanglePlacement rp (RectanglePlacement::centred); - double dx = 0, dy = 0, dw = width, dh = height; - rp.applyTo (dx, dy, dw, dh, x, y, w, h); - const int rx = roundDoubleToInt (dx), ry = roundDoubleToInt (dy); - const int rw = roundDoubleToInt (dw), rh = roundDoubleToInt (dh); - - g.saveState(); - g.excludeClipRegion (rx, ry, rw, rh); - g.fillAll (Colours::black); - g.restoreState(); - - g.drawImage (activeImage, rx, ry, rw, rh, 0, 0, width, height); - } - - bool createFileCaptureFilter (const File& file) - { - removeFileCaptureFilter(); - file.deleteFile(); - mediaControl->Stop(); - firstRecordedTime = Time(); - recordNextFrameTime = true; - - HRESULT hr = mux.CoCreateInstance (CLSID_AviDest, CLSCTX_INPROC_SERVER); - - if (SUCCEEDED (hr)) - { - hr = graphBuilder->AddFilter (mux, _T("AVI Mux")); - - if (SUCCEEDED (hr)) - { - fileWriter.CoCreateInstance (CLSID_FileWriter, CLSCTX_INPROC_SERVER); - - if (SUCCEEDED (hr)) - { - ComSmartPtr fileSink; - hr = fileWriter->QueryInterface (IID_IFileSinkFilter, (void**) &fileSink); - - if (SUCCEEDED (hr)) - { - AM_MEDIA_TYPE mt; - zerostruct (mt); - mt.majortype = MEDIATYPE_Stream; - mt.subtype = MEDIASUBTYPE_Avi; - mt.formattype = FORMAT_VideoInfo; - hr = fileSink->SetFileName (file.getFullPathName(), &mt); - - if (SUCCEEDED (hr)) - { - hr = graphBuilder->AddFilter (fileWriter, _T("File Writer")); - - if (SUCCEEDED (hr)) - { - ComSmartPtr muxInputPin, muxOutputPin, writerInput; - - if (getPin (mux, PINDIR_INPUT, &muxInputPin) - && getPin (mux, PINDIR_OUTPUT, &muxOutputPin) - && getPin (fileWriter, PINDIR_INPUT, &writerInput)) - { - hr = graphBuilder->Connect (smartTeeCaptureOutputPin, muxInputPin); - - if (SUCCEEDED (hr)) - { - hr = graphBuilder->Connect (muxOutputPin, writerInput); - - if (SUCCEEDED (hr)) - { - if (ok && activeUsers > 0) - mediaControl->Run(); - - return true; - } - } - } - } - } - } - } - } - } - - removeFileCaptureFilter(); - - if (ok && activeUsers > 0) - mediaControl->Run(); - - return false; - } - - void removeFileCaptureFilter() - { - mediaControl->Stop(); - - if (mux != 0) - { - graphBuilder->RemoveFilter (mux); - mux = 0; - } - - if (fileWriter != 0) - { - graphBuilder->RemoveFilter (fileWriter); - fileWriter = 0; - } - - if (ok && activeUsers > 0) - mediaControl->Run(); - } - - void addListener (CameraImageListener* listenerToAdd) - { - const ScopedLock sl (listenerLock); - - if (listeners.size() == 0) - addUser(); - - listeners.addIfNotAlreadyThere (listenerToAdd); - } - - void removeListener (CameraImageListener* listenerToRemove) - { - const ScopedLock sl (listenerLock); - listeners.removeValue (listenerToRemove); - - if (listeners.size() == 0) - removeUser(); - } - - void callListeners (Image& image) - { - const ScopedLock sl (listenerLock); - - for (int i = listeners.size(); --i >= 0;) - { - CameraImageListener* l = (CameraImageListener*) listeners[i]; - - if (l != 0) - l->imageReceived (image); - } - } - - class DShowCaptureViewerComp : public Component, - public ChangeListener - { - public: - DShowCaptureViewerComp (DShowCameraDeviceInteral* const owner_) - : owner (owner_) - { - setOpaque (true); - owner->addChangeListener (this); - owner->addUser(); - owner->viewerComps.add (this); - setSize (owner_->width, owner_->height); - } - - ~DShowCaptureViewerComp() - { - if (owner != 0) - { - owner->viewerComps.removeValue (this); - owner->removeUser(); - owner->removeChangeListener (this); - } - } - - void ownerDeleted() - { - owner = 0; - } - - void paint (Graphics& g) - { - g.setColour (Colours::black); - g.setImageResamplingQuality (Graphics::lowResamplingQuality); - - if (owner != 0) - owner->drawCurrentImage (g, 0, 0, getWidth(), getHeight()); - else - g.fillAll (Colours::black); - } - - void changeListenerCallback (void*) - { - repaint(); - } - - private: - DShowCameraDeviceInteral* owner; - }; - - bool ok; - int width, height; - Time firstRecordedTime; - - VoidArray viewerComps; + DShowCameraDeviceInteral (CameraDevice* const owner_, + const ComSmartPtr & captureGraphBuilder_, + const ComSmartPtr & filter_, + int minWidth, int minHeight, + int maxWidth, int maxHeight) + : owner (owner_), + captureGraphBuilder (captureGraphBuilder_), + filter (filter_), + ok (false), + imageNeedsFlipping (false), + width (0), + height (0), + activeUsers (0), + recordNextFrameTime (false), + activeImage (0), + loadingImage (0) + { + HRESULT hr = graphBuilder.CoCreateInstance (CLSID_FilterGraph, CLSCTX_INPROC); + if (FAILED (hr)) + return; + + hr = captureGraphBuilder->SetFiltergraph (graphBuilder); + if (FAILED (hr)) + return; + + hr = graphBuilder->QueryInterface (IID_IMediaControl, (void**) &mediaControl); + if (FAILED (hr)) + return; + + { + ComSmartPtr streamConfig; + + hr = captureGraphBuilder->FindInterface (&PIN_CATEGORY_CAPTURE, + 0, + filter, + IID_IAMStreamConfig, + (void**) &streamConfig); + + if (streamConfig != 0) + { + getVideoSizes (streamConfig); + + if (! selectVideoSize (streamConfig, minWidth, minHeight, maxWidth, maxHeight)) + return; + } + } + + hr = graphBuilder->AddFilter (filter, _T("Video Capture")); + if (FAILED (hr)) + return; + + hr = smartTee.CoCreateInstance (CLSID_SmartTee, CLSCTX_INPROC_SERVER); + if (FAILED (hr)) + return; + + hr = graphBuilder->AddFilter (smartTee, _T("Smart Tee")); + if (FAILED (hr)) + return; + + if (! connectFilters (filter, smartTee)) + return; + + ComSmartPtr sampleGrabberBase; + hr = sampleGrabberBase.CoCreateInstance (CLSID_SampleGrabber, CLSCTX_INPROC_SERVER); + if (FAILED (hr)) + return; + + hr = sampleGrabberBase->QueryInterface (IID_ISampleGrabber, (void**) &sampleGrabber); + if (FAILED (hr)) + return; + + AM_MEDIA_TYPE mt; + zerostruct (mt); + mt.majortype = MEDIATYPE_Video; + mt.subtype = MEDIASUBTYPE_RGB24; + mt.formattype = FORMAT_VideoInfo; + sampleGrabber->SetMediaType (&mt); + + callback = new GrabberCallback (*this); + sampleGrabber->SetCallback (callback, 1); + + hr = graphBuilder->AddFilter (sampleGrabberBase, _T("Sample Grabber")); + if (FAILED (hr)) + return; + + ComSmartPtr grabberInputPin; + if (! (getPin (smartTee, PINDIR_OUTPUT, &smartTeeCaptureOutputPin, "capture") + && getPin (smartTee, PINDIR_OUTPUT, &smartTeePreviewOutputPin, "preview") + && getPin (sampleGrabberBase, PINDIR_INPUT, &grabberInputPin))) + return; + + hr = graphBuilder->Connect (smartTeePreviewOutputPin, grabberInputPin); + if (FAILED (hr)) + return; + + zerostruct (mt); + hr = sampleGrabber->GetConnectedMediaType (&mt); + VIDEOINFOHEADER* pVih = (VIDEOINFOHEADER*) (mt.pbFormat); + width = pVih->bmiHeader.biWidth; + height = pVih->bmiHeader.biHeight; + + ComSmartPtr nullFilter; + hr = nullFilter.CoCreateInstance (CLSID_NullRenderer, CLSCTX_INPROC_SERVER); + hr = graphBuilder->AddFilter (nullFilter, _T("Null Renderer")); + + if (connectFilters (sampleGrabberBase, nullFilter) + && addGraphToRot()) + { + activeImage = new Image (Image::RGB, width, height, true); + loadingImage = new Image (Image::RGB, width, height, true); + + ok = true; + } + } + + ~DShowCameraDeviceInteral() + { + if (mediaControl != 0) + mediaControl->Stop(); + + removeGraphFromRot(); + + for (int i = viewerComps.size(); --i >= 0;) + ((DShowCaptureViewerComp*) viewerComps.getUnchecked(i))->ownerDeleted(); + + callback = 0; + graphBuilder = 0; + sampleGrabber = 0; + mediaControl = 0; + filter = 0; + captureGraphBuilder = 0; + smartTee = 0; + smartTeePreviewOutputPin = 0; + smartTeeCaptureOutputPin = 0; + mux = 0; + fileWriter = 0; + + delete activeImage; + delete loadingImage; + } + + void addUser() + { + if (ok && activeUsers++ == 0) + mediaControl->Run(); + } + + void removeUser() + { + if (ok && --activeUsers == 0) + mediaControl->Stop(); + } + + void handleFrame (double /*time*/, BYTE* buffer, long /*bufferSize*/) + { + if (recordNextFrameTime) + { + const double defaultCameraLatency = 0.1; + + firstRecordedTime = Time::getCurrentTime() - RelativeTime (defaultCameraLatency); + recordNextFrameTime = false; + + ComSmartPtr pin; + if (getPin (filter, PINDIR_OUTPUT, &pin)) + { + ComSmartPtr pushSource; + HRESULT hr = pin->QueryInterface (IID_IAMPushSource, (void**) &pushSource); + + if (pushSource != 0) + { + REFERENCE_TIME latency = 0; + hr = pushSource->GetLatency (&latency); + + firstRecordedTime = firstRecordedTime - RelativeTime ((double) latency); + } + } + } + + imageSwapLock.enter(); + const int lineStride = width * 3; + const Image::BitmapData destData (*loadingImage, 0, 0, width, height, true); + + for (int i = 0; i < height; ++i) + memcpy (destData.getLinePointer ((height - 1) - i), + buffer + lineStride * i, + lineStride); + + imageNeedsFlipping = true; + imageSwapLock.exit(); + + callListeners (*loadingImage); + + sendChangeMessage (this); + } + + void drawCurrentImage (Graphics& g, int x, int y, int w, int h) + { + if (imageNeedsFlipping) + { + imageSwapLock.enter(); + swapVariables (loadingImage, activeImage); + imageNeedsFlipping = false; + imageSwapLock.exit(); + } + + RectanglePlacement rp (RectanglePlacement::centred); + double dx = 0, dy = 0, dw = width, dh = height; + rp.applyTo (dx, dy, dw, dh, x, y, w, h); + const int rx = roundToInt (dx), ry = roundToInt (dy); + const int rw = roundToInt (dw), rh = roundToInt (dh); + + g.saveState(); + g.excludeClipRegion (rx, ry, rw, rh); + g.fillAll (Colours::black); + g.restoreState(); + + g.drawImage (activeImage, rx, ry, rw, rh, 0, 0, width, height); + } + + bool createFileCaptureFilter (const File& file) + { + removeFileCaptureFilter(); + file.deleteFile(); + mediaControl->Stop(); + firstRecordedTime = Time(); + recordNextFrameTime = true; + + HRESULT hr = mux.CoCreateInstance (CLSID_AviDest, CLSCTX_INPROC_SERVER); + + if (SUCCEEDED (hr)) + { + hr = graphBuilder->AddFilter (mux, _T("AVI Mux")); + + if (SUCCEEDED (hr)) + { + fileWriter.CoCreateInstance (CLSID_FileWriter, CLSCTX_INPROC_SERVER); + + if (SUCCEEDED (hr)) + { + ComSmartPtr fileSink; + hr = fileWriter->QueryInterface (IID_IFileSinkFilter, (void**) &fileSink); + + if (SUCCEEDED (hr)) + { + AM_MEDIA_TYPE mt; + zerostruct (mt); + mt.majortype = MEDIATYPE_Stream; + mt.subtype = MEDIASUBTYPE_Avi; + mt.formattype = FORMAT_VideoInfo; + hr = fileSink->SetFileName (file.getFullPathName(), &mt); + + if (SUCCEEDED (hr)) + { + hr = graphBuilder->AddFilter (fileWriter, _T("File Writer")); + + if (SUCCEEDED (hr)) + { + ComSmartPtr muxInputPin, muxOutputPin, writerInput; + + if (getPin (mux, PINDIR_INPUT, &muxInputPin) + && getPin (mux, PINDIR_OUTPUT, &muxOutputPin) + && getPin (fileWriter, PINDIR_INPUT, &writerInput)) + { + hr = graphBuilder->Connect (smartTeeCaptureOutputPin, muxInputPin); + + if (SUCCEEDED (hr)) + { + hr = graphBuilder->Connect (muxOutputPin, writerInput); + + if (SUCCEEDED (hr)) + { + if (ok && activeUsers > 0) + mediaControl->Run(); + + return true; + } + } + } + } + } + } + } + } + } + + removeFileCaptureFilter(); + + if (ok && activeUsers > 0) + mediaControl->Run(); + + return false; + } + + void removeFileCaptureFilter() + { + mediaControl->Stop(); + + if (mux != 0) + { + graphBuilder->RemoveFilter (mux); + mux = 0; + } + + if (fileWriter != 0) + { + graphBuilder->RemoveFilter (fileWriter); + fileWriter = 0; + } + + if (ok && activeUsers > 0) + mediaControl->Run(); + } + + void addListener (CameraImageListener* listenerToAdd) + { + const ScopedLock sl (listenerLock); + + if (listeners.size() == 0) + addUser(); + + listeners.addIfNotAlreadyThere (listenerToAdd); + } + + void removeListener (CameraImageListener* listenerToRemove) + { + const ScopedLock sl (listenerLock); + listeners.removeValue (listenerToRemove); + + if (listeners.size() == 0) + removeUser(); + } + + void callListeners (Image& image) + { + const ScopedLock sl (listenerLock); + + for (int i = listeners.size(); --i >= 0;) + { + CameraImageListener* l = (CameraImageListener*) listeners[i]; + + if (l != 0) + l->imageReceived (image); + } + } + + class DShowCaptureViewerComp : public Component, + public ChangeListener + { + public: + DShowCaptureViewerComp (DShowCameraDeviceInteral* const owner_) + : owner (owner_) + { + setOpaque (true); + owner->addChangeListener (this); + owner->addUser(); + owner->viewerComps.add (this); + setSize (owner_->width, owner_->height); + } + + ~DShowCaptureViewerComp() + { + if (owner != 0) + { + owner->viewerComps.removeValue (this); + owner->removeUser(); + owner->removeChangeListener (this); + } + } + + void ownerDeleted() + { + owner = 0; + } + + void paint (Graphics& g) + { + g.setColour (Colours::black); + g.setImageResamplingQuality (Graphics::lowResamplingQuality); + + if (owner != 0) + owner->drawCurrentImage (g, 0, 0, getWidth(), getHeight()); + else + g.fillAll (Colours::black); + } + + void changeListenerCallback (void*) + { + repaint(); + } + + private: + DShowCameraDeviceInteral* owner; + }; + + bool ok; + int width, height; + Time firstRecordedTime; + + VoidArray viewerComps; private: - CameraDevice* const owner; - ComSmartPtr captureGraphBuilder; - ComSmartPtr filter; - ComSmartPtr smartTee; - ComSmartPtr graphBuilder; - ComSmartPtr sampleGrabber; - ComSmartPtr mediaControl; - ComSmartPtr smartTeePreviewOutputPin; - ComSmartPtr smartTeeCaptureOutputPin; - ComSmartPtr mux, fileWriter; - int activeUsers; - Array widths, heights; - DWORD graphRegistrationID; + CameraDevice* const owner; + ComSmartPtr captureGraphBuilder; + ComSmartPtr filter; + ComSmartPtr smartTee; + ComSmartPtr graphBuilder; + ComSmartPtr sampleGrabber; + ComSmartPtr mediaControl; + ComSmartPtr smartTeePreviewOutputPin; + ComSmartPtr smartTeeCaptureOutputPin; + ComSmartPtr mux, fileWriter; + int activeUsers; + Array widths, heights; + DWORD graphRegistrationID; - CriticalSection imageSwapLock; - bool imageNeedsFlipping; - Image* loadingImage; - Image* activeImage; + CriticalSection imageSwapLock; + bool imageNeedsFlipping; + Image* loadingImage; + Image* activeImage; - bool recordNextFrameTime; + bool recordNextFrameTime; - void getVideoSizes (IAMStreamConfig* const streamConfig) - { - widths.clear(); - heights.clear(); + void getVideoSizes (IAMStreamConfig* const streamConfig) + { + widths.clear(); + heights.clear(); - int count = 0, size = 0; - streamConfig->GetNumberOfCapabilities (&count, &size); + int count = 0, size = 0; + streamConfig->GetNumberOfCapabilities (&count, &size); - if (size == sizeof (VIDEO_STREAM_CONFIG_CAPS)) - { - for (int i = 0; i < count; ++i) - { - VIDEO_STREAM_CONFIG_CAPS scc; - AM_MEDIA_TYPE* config; + if (size == sizeof (VIDEO_STREAM_CONFIG_CAPS)) + { + for (int i = 0; i < count; ++i) + { + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE* config; - HRESULT hr = streamConfig->GetStreamCaps (i, &config, (BYTE*) &scc); + HRESULT hr = streamConfig->GetStreamCaps (i, &config, (BYTE*) &scc); - if (SUCCEEDED (hr)) - { - const int w = scc.InputSize.cx; - const int h = scc.InputSize.cy; + if (SUCCEEDED (hr)) + { + const int w = scc.InputSize.cx; + const int h = scc.InputSize.cy; - bool duplicate = false; + bool duplicate = false; - for (int j = widths.size(); --j >= 0;) - { - if (w == widths.getUnchecked (j) && h == heights.getUnchecked (j)) - { - duplicate = true; - break; - } - } + for (int j = widths.size(); --j >= 0;) + { + if (w == widths.getUnchecked (j) && h == heights.getUnchecked (j)) + { + duplicate = true; + break; + } + } - if (! duplicate) - { - DBG ("Camera capture size: " + String (w) + ", " + String (h)); - widths.add (w); - heights.add (h); - } + if (! duplicate) + { + DBG ("Camera capture size: " + String (w) + ", " + String (h)); + widths.add (w); + heights.add (h); + } - deleteMediaType (config); - } - } - } - } + deleteMediaType (config); + } + } + } + } - bool selectVideoSize (IAMStreamConfig* const streamConfig, - const int minWidth, const int minHeight, - const int maxWidth, const int maxHeight) - { - int count = 0, size = 0; - streamConfig->GetNumberOfCapabilities (&count, &size); + bool selectVideoSize (IAMStreamConfig* const streamConfig, + const int minWidth, const int minHeight, + const int maxWidth, const int maxHeight) + { + int count = 0, size = 0; + streamConfig->GetNumberOfCapabilities (&count, &size); - if (size == sizeof (VIDEO_STREAM_CONFIG_CAPS)) - { - for (int i = 0; i < count; ++i) - { - VIDEO_STREAM_CONFIG_CAPS scc; - AM_MEDIA_TYPE* config; + if (size == sizeof (VIDEO_STREAM_CONFIG_CAPS)) + { + for (int i = 0; i < count; ++i) + { + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE* config; - HRESULT hr = streamConfig->GetStreamCaps (i, &config, (BYTE*) &scc); + HRESULT hr = streamConfig->GetStreamCaps (i, &config, (BYTE*) &scc); - if (SUCCEEDED (hr)) - { - if (scc.InputSize.cx >= minWidth - && scc.InputSize.cy >= minHeight - && scc.InputSize.cx <= maxWidth - && scc.InputSize.cy <= maxHeight) - { - hr = streamConfig->SetFormat (config); - deleteMediaType (config); - return SUCCEEDED (hr); - } + if (SUCCEEDED (hr)) + { + if (scc.InputSize.cx >= minWidth + && scc.InputSize.cy >= minHeight + && scc.InputSize.cx <= maxWidth + && scc.InputSize.cy <= maxHeight) + { + hr = streamConfig->SetFormat (config); + deleteMediaType (config); + return SUCCEEDED (hr); + } - deleteMediaType (config); - } - } - } + deleteMediaType (config); + } + } + } - return false; - } + return false; + } - static bool getPin (IBaseFilter* filter, const PIN_DIRECTION wantedDirection, IPin** result, const char* pinName = 0) - { - ComSmartPtr enumerator; - ComSmartPtr pin; + static bool getPin (IBaseFilter* filter, const PIN_DIRECTION wantedDirection, IPin** result, const char* pinName = 0) + { + ComSmartPtr enumerator; + ComSmartPtr pin; - filter->EnumPins (&enumerator); + filter->EnumPins (&enumerator); - while (enumerator->Next (1, &pin, 0) == S_OK) - { - PIN_DIRECTION dir; - pin->QueryDirection (&dir); + while (enumerator->Next (1, &pin, 0) == S_OK) + { + PIN_DIRECTION dir; + pin->QueryDirection (&dir); - if (wantedDirection == dir) - { - PIN_INFO info; - zerostruct (info); - pin->QueryPinInfo (&info); + if (wantedDirection == dir) + { + PIN_INFO info; + zerostruct (info); + pin->QueryPinInfo (&info); - if (pinName == 0 || String (pinName).equalsIgnoreCase (String (info.achName))) - { - pin.p->AddRef(); - *result = pin; - return true; - } - } - } + if (pinName == 0 || String (pinName).equalsIgnoreCase (String (info.achName))) + { + pin.p->AddRef(); + *result = pin; + return true; + } + } + } - return false; - } + return false; + } - bool connectFilters (IBaseFilter* const first, IBaseFilter* const second) const - { - ComSmartPtr in, out; + bool connectFilters (IBaseFilter* const first, IBaseFilter* const second) const + { + ComSmartPtr in, out; - return getPin (first, PINDIR_OUTPUT, &out) - && getPin (second, PINDIR_INPUT, &in) - && SUCCEEDED (graphBuilder->Connect (out, in)); - } + return getPin (first, PINDIR_OUTPUT, &out) + && getPin (second, PINDIR_INPUT, &in) + && SUCCEEDED (graphBuilder->Connect (out, in)); + } - bool addGraphToRot() - { - ComSmartPtr rot; - if (FAILED (GetRunningObjectTable (0, &rot))) - return false; + bool addGraphToRot() + { + ComSmartPtr rot; + if (FAILED (GetRunningObjectTable (0, &rot))) + return false; - ComSmartPtr moniker; - WCHAR buffer[128]; - HRESULT hr = CreateItemMoniker (_T("!"), buffer, &moniker); - if (FAILED (hr)) - return false; + ComSmartPtr moniker; + WCHAR buffer[128]; + HRESULT hr = CreateItemMoniker (_T("!"), buffer, &moniker); + if (FAILED (hr)) + return false; - graphRegistrationID = 0; - return SUCCEEDED (rot->Register (0, graphBuilder, moniker, &graphRegistrationID)); - } + graphRegistrationID = 0; + return SUCCEEDED (rot->Register (0, graphBuilder, moniker, &graphRegistrationID)); + } - void removeGraphFromRot() - { - ComSmartPtr rot; + void removeGraphFromRot() + { + ComSmartPtr rot; - if (SUCCEEDED (GetRunningObjectTable (0, &rot))) - rot->Revoke (graphRegistrationID); - } + if (SUCCEEDED (GetRunningObjectTable (0, &rot))) + rot->Revoke (graphRegistrationID); + } - static void deleteMediaType (AM_MEDIA_TYPE* const pmt) - { - if (pmt->cbFormat != 0) - CoTaskMemFree ((PVOID) pmt->pbFormat); + static void deleteMediaType (AM_MEDIA_TYPE* const pmt) + { + if (pmt->cbFormat != 0) + CoTaskMemFree ((PVOID) pmt->pbFormat); - if (pmt->pUnk != 0) - pmt->pUnk->Release(); + if (pmt->pUnk != 0) + pmt->pUnk->Release(); - CoTaskMemFree (pmt); - } + CoTaskMemFree (pmt); + } - class GrabberCallback : public ISampleGrabberCB - { - public: - GrabberCallback (DShowCameraDeviceInteral& owner_) - : owner (owner_) - { - } + class GrabberCallback : public ISampleGrabberCB + { + public: + GrabberCallback (DShowCameraDeviceInteral& owner_) + : owner (owner_) + { + } - HRESULT __stdcall QueryInterface (REFIID id, void** result) - { - if (id == IID_IUnknown) - *result = dynamic_cast (this); - else if (id == IID_ISampleGrabberCB) - *result = dynamic_cast (this); - else - { - *result = 0; - return E_NOINTERFACE; - } + HRESULT __stdcall QueryInterface (REFIID id, void** result) + { + if (id == IID_IUnknown) + *result = dynamic_cast (this); + else if (id == IID_ISampleGrabberCB) + *result = dynamic_cast (this); + else + { + *result = 0; + return E_NOINTERFACE; + } - AddRef(); - return S_OK; - } + AddRef(); + return S_OK; + } - ULONG __stdcall AddRef() { return ++refCount; } - ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; } + ULONG __stdcall AddRef() { return ++refCount; } + ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; } - STDMETHODIMP SampleCB (double /*SampleTime*/, IMediaSample* /*pSample*/) - { - return E_FAIL; - } + STDMETHODIMP SampleCB (double /*SampleTime*/, IMediaSample* /*pSample*/) + { + return E_FAIL; + } - STDMETHODIMP BufferCB (double time, BYTE* buffer, long bufferSize) - { - owner.handleFrame (time, buffer, bufferSize); - return S_OK; - } + STDMETHODIMP BufferCB (double time, BYTE* buffer, long bufferSize) + { + owner.handleFrame (time, buffer, bufferSize); + return S_OK; + } - private: - int refCount; - DShowCameraDeviceInteral& owner; + private: + int refCount; + DShowCameraDeviceInteral& owner; - GrabberCallback (const GrabberCallback&); - const GrabberCallback& operator= (const GrabberCallback&); - }; + GrabberCallback (const GrabberCallback&); + const GrabberCallback& operator= (const GrabberCallback&); + }; - ComSmartPtr callback; - VoidArray listeners; - CriticalSection listenerLock; + ComSmartPtr callback; + VoidArray listeners; + CriticalSection listenerLock; - DShowCameraDeviceInteral (const DShowCameraDeviceInteral&); - const DShowCameraDeviceInteral& operator= (const DShowCameraDeviceInteral&); + DShowCameraDeviceInteral (const DShowCameraDeviceInteral&); + const DShowCameraDeviceInteral& operator= (const DShowCameraDeviceInteral&); }; CameraDevice::CameraDevice (const String& name_, int /*index*/) - : name (name_) + : name (name_) { - isRecording = false; + isRecording = false; } CameraDevice::~CameraDevice() { - stopRecording(); - delete (DShowCameraDeviceInteral*) internal; - internal = 0; + stopRecording(); + delete (DShowCameraDeviceInteral*) internal; + internal = 0; } Component* CameraDevice::createViewerComponent() { - return new DShowCameraDeviceInteral::DShowCaptureViewerComp ((DShowCameraDeviceInteral*) internal); + return new DShowCameraDeviceInteral::DShowCaptureViewerComp ((DShowCameraDeviceInteral*) internal); } const String CameraDevice::getFileExtension() { - return ".avi"; + return ".avi"; } void CameraDevice::startRecordingToFile (const File& file) { - stopRecording(); + stopRecording(); - DShowCameraDeviceInteral* const d = (DShowCameraDeviceInteral*) internal; - d->addUser(); - isRecording = d->createFileCaptureFilter (file); + DShowCameraDeviceInteral* const d = (DShowCameraDeviceInteral*) internal; + d->addUser(); + isRecording = d->createFileCaptureFilter (file); } const Time CameraDevice::getTimeOfFirstRecordedFrame() const { - DShowCameraDeviceInteral* const d = (DShowCameraDeviceInteral*) internal; - return d->firstRecordedTime; + DShowCameraDeviceInteral* const d = (DShowCameraDeviceInteral*) internal; + return d->firstRecordedTime; } void CameraDevice::stopRecording() { - if (isRecording) - { - DShowCameraDeviceInteral* const d = (DShowCameraDeviceInteral*) internal; - d->removeFileCaptureFilter(); - d->removeUser(); - isRecording = false; - } + if (isRecording) + { + DShowCameraDeviceInteral* const d = (DShowCameraDeviceInteral*) internal; + d->removeFileCaptureFilter(); + d->removeUser(); + isRecording = false; + } } void CameraDevice::addListener (CameraImageListener* listenerToAdd) { - DShowCameraDeviceInteral* const d = (DShowCameraDeviceInteral*) internal; + DShowCameraDeviceInteral* const d = (DShowCameraDeviceInteral*) internal; - if (listenerToAdd != 0) - d->addListener (listenerToAdd); + if (listenerToAdd != 0) + d->addListener (listenerToAdd); } void CameraDevice::removeListener (CameraImageListener* listenerToRemove) { - DShowCameraDeviceInteral* const d = (DShowCameraDeviceInteral*) internal; + DShowCameraDeviceInteral* const d = (DShowCameraDeviceInteral*) internal; - if (listenerToRemove != 0) - d->removeListener (listenerToRemove); + if (listenerToRemove != 0) + d->removeListener (listenerToRemove); } static ComSmartPtr enumerateCameras (StringArray* const names, - const int deviceIndexToOpen, - String& name) + const int deviceIndexToOpen, + String& name) { - int index = 0; - ComSmartPtr result; + int index = 0; + ComSmartPtr result; - ComSmartPtr pDevEnum; - HRESULT hr = pDevEnum.CoCreateInstance (CLSID_SystemDeviceEnum, CLSCTX_INPROC); + ComSmartPtr pDevEnum; + HRESULT hr = pDevEnum.CoCreateInstance (CLSID_SystemDeviceEnum, CLSCTX_INPROC); - if (SUCCEEDED (hr)) - { - ComSmartPtr enumerator; - hr = pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &enumerator, 0); + if (SUCCEEDED (hr)) + { + ComSmartPtr enumerator; + hr = pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &enumerator, 0); - if (SUCCEEDED (hr) && enumerator != 0) - { - ComSmartPtr captureFilter; - ComSmartPtr moniker; - ULONG fetched; + if (SUCCEEDED (hr) && enumerator != 0) + { + ComSmartPtr captureFilter; + ComSmartPtr moniker; + ULONG fetched; - while (enumerator->Next (1, &moniker, &fetched) == S_OK) - { - hr = moniker->BindToObject (0, 0, IID_IBaseFilter, (void**) &captureFilter); + while (enumerator->Next (1, &moniker, &fetched) == S_OK) + { + hr = moniker->BindToObject (0, 0, IID_IBaseFilter, (void**) &captureFilter); - if (SUCCEEDED (hr)) - { - ComSmartPtr propertyBag; - hr = moniker->BindToStorage (0, 0, IID_IPropertyBag, (void**) &propertyBag); + if (SUCCEEDED (hr)) + { + ComSmartPtr propertyBag; + hr = moniker->BindToStorage (0, 0, IID_IPropertyBag, (void**) &propertyBag); - if (SUCCEEDED (hr)) - { - VARIANT var; - var.vt = VT_BSTR; + if (SUCCEEDED (hr)) + { + VARIANT var; + var.vt = VT_BSTR; - hr = propertyBag->Read (_T("FriendlyName"), &var, 0); - propertyBag = 0; + hr = propertyBag->Read (_T("FriendlyName"), &var, 0); + propertyBag = 0; - if (SUCCEEDED (hr)) - { - if (names != 0) - names->add (var.bstrVal); + if (SUCCEEDED (hr)) + { + if (names != 0) + names->add (var.bstrVal); - if (index == deviceIndexToOpen) - { - name = var.bstrVal; - result = captureFilter; - captureFilter = 0; - break; - } + if (index == deviceIndexToOpen) + { + name = var.bstrVal; + result = captureFilter; + captureFilter = 0; + break; + } - ++index; - } + ++index; + } - moniker = 0; - } + moniker = 0; + } - captureFilter = 0; - } - } - } - } + captureFilter = 0; + } + } + } + } - return result; + return result; } const StringArray CameraDevice::getAvailableDevices() { - StringArray devs; - String dummy; - enumerateCameras (&devs, -1, dummy); - return devs; + StringArray devs; + String dummy; + enumerateCameras (&devs, -1, dummy); + return devs; } CameraDevice* CameraDevice::openDevice (int index, - int minWidth, int minHeight, - int maxWidth, int maxHeight) + int minWidth, int minHeight, + int maxWidth, int maxHeight) { - ComSmartPtr captureGraphBuilder; - HRESULT hr = captureGraphBuilder.CoCreateInstance (CLSID_CaptureGraphBuilder2, CLSCTX_INPROC); + ComSmartPtr captureGraphBuilder; + HRESULT hr = captureGraphBuilder.CoCreateInstance (CLSID_CaptureGraphBuilder2, CLSCTX_INPROC); - if (SUCCEEDED (hr)) - { - String name; - const ComSmartPtr filter (enumerateCameras (0, index, name)); + if (SUCCEEDED (hr)) + { + String name; + const ComSmartPtr filter (enumerateCameras (0, index, name)); - if (filter != 0) - { - CameraDevice* const cam = new CameraDevice (name, index); - DShowCameraDeviceInteral* const intern - = new DShowCameraDeviceInteral (cam, captureGraphBuilder, filter, - minWidth, minHeight, maxWidth, maxHeight); - cam->internal = intern; + if (filter != 0) + { + CameraDevice* const cam = new CameraDevice (name, index); + DShowCameraDeviceInteral* const intern + = new DShowCameraDeviceInteral (cam, captureGraphBuilder, filter, + minWidth, minHeight, maxWidth, maxHeight); + cam->internal = intern; - if (intern->ok) - return cam; - else - delete cam; - } - } + if (intern->ok) + return cam; + else + delete cam; + } + } - return 0; + return 0; } #endif @@ -250674,19 +228406,9 @@ END_JUCE_NAMESPACE #if JUCE_LINUX /********* Start of inlined file: juce_linux_NativeCode.cpp *********/ -/* - This file wraps together all the mac-specific code, so that - we can include all the native headers just once, and compile all our - platform-specific stuff in one big lump, keeping it out of the way of - the rest of the codebase. -*/ BEGIN_JUCE_NAMESPACE -/* Remove this macro if you're having problems compiling the cpu affinity - calls (the API for these has changed about quite a bit in various Linux - versions, and a lot of distros seem to ship with obsolete versions) -*/ #if defined (CPU_ISSET) && ! defined (SUPPORT_AFFINITIES) #define SUPPORT_AFFINITIES 1 #endif @@ -250696,133 +228418,128 @@ BEGIN_JUCE_NAMESPACE // Now include the actual code files.. /********* Start of inlined file: juce_posix_SharedCode.h *********/ -/* - This file contains posix routines that are common to both the Linux and Mac builds. - - It gets included directly in the cpp files for these platforms. -*/ CriticalSection::CriticalSection() throw() { - pthread_mutexattr_t atts; - pthread_mutexattr_init (&atts); - pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init (&internal, &atts); + pthread_mutexattr_t atts; + pthread_mutexattr_init (&atts); + pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init (&internal, &atts); } CriticalSection::~CriticalSection() throw() { - pthread_mutex_destroy (&internal); + pthread_mutex_destroy (&internal); } void CriticalSection::enter() const throw() { - pthread_mutex_lock (&internal); + pthread_mutex_lock (&internal); } bool CriticalSection::tryEnter() const throw() { - return pthread_mutex_trylock (&internal) == 0; + return pthread_mutex_trylock (&internal) == 0; } void CriticalSection::exit() const throw() { - pthread_mutex_unlock (&internal); + pthread_mutex_unlock (&internal); } struct EventStruct { - pthread_cond_t condition; - pthread_mutex_t mutex; - bool triggered; + pthread_cond_t condition; + pthread_mutex_t mutex; + bool triggered; }; WaitableEvent::WaitableEvent() throw() { - EventStruct* const es = new EventStruct(); - es->triggered = false; + EventStruct* const es = new EventStruct(); + es->triggered = false; - pthread_cond_init (&es->condition, 0); - pthread_mutex_init (&es->mutex, 0); + pthread_cond_init (&es->condition, 0); + pthread_mutex_init (&es->mutex, 0); - internal = es; + internal = es; } WaitableEvent::~WaitableEvent() throw() { - EventStruct* const es = (EventStruct*) internal; + EventStruct* const es = (EventStruct*) internal; - pthread_cond_destroy (&es->condition); - pthread_mutex_destroy (&es->mutex); + pthread_cond_destroy (&es->condition); + pthread_mutex_destroy (&es->mutex); - delete es; + delete es; } bool WaitableEvent::wait (const int timeOutMillisecs) const throw() { - EventStruct* const es = (EventStruct*) internal; - pthread_mutex_lock (&es->mutex); + EventStruct* const es = (EventStruct*) internal; + pthread_mutex_lock (&es->mutex); - if (timeOutMillisecs < 0) - { - while (! es->triggered) - pthread_cond_wait (&es->condition, &es->mutex); - } - else - { - while (! es->triggered) - { - struct timeval t; - gettimeofday (&t, 0); + if (timeOutMillisecs < 0) + { + while (! es->triggered) + pthread_cond_wait (&es->condition, &es->mutex); + } + else + { + while (! es->triggered) + { + struct timeval t; + gettimeofday (&t, 0); - struct timespec time; - time.tv_sec = t.tv_sec + (timeOutMillisecs / 1000); - time.tv_nsec = (t.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000; + struct timespec time; + time.tv_sec = t.tv_sec + (timeOutMillisecs / 1000); + time.tv_nsec = (t.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000; - if (time.tv_nsec >= 1000000000) - { - time.tv_nsec -= 1000000000; - time.tv_sec++; - } + if (time.tv_nsec >= 1000000000) + { + time.tv_nsec -= 1000000000; + time.tv_sec++; + } - if (pthread_cond_timedwait (&es->condition, &es->mutex, &time) == ETIMEDOUT) - { - pthread_mutex_unlock (&es->mutex); - return false; - } - } - } + if (pthread_cond_timedwait (&es->condition, &es->mutex, &time) == ETIMEDOUT) + { + pthread_mutex_unlock (&es->mutex); + return false; + } + } + } - es->triggered = false; - pthread_mutex_unlock (&es->mutex); - return true; + es->triggered = false; + pthread_mutex_unlock (&es->mutex); + return true; } void WaitableEvent::signal() const throw() { - EventStruct* const es = (EventStruct*) internal; + EventStruct* const es = (EventStruct*) internal; - pthread_mutex_lock (&es->mutex); - es->triggered = true; - pthread_cond_broadcast (&es->condition); - pthread_mutex_unlock (&es->mutex); + pthread_mutex_lock (&es->mutex); + es->triggered = true; + pthread_cond_broadcast (&es->condition); + pthread_mutex_unlock (&es->mutex); } void WaitableEvent::reset() const throw() { - EventStruct* const es = (EventStruct*) internal; + EventStruct* const es = (EventStruct*) internal; - pthread_mutex_lock (&es->mutex); - es->triggered = false; - pthread_mutex_unlock (&es->mutex); + pthread_mutex_lock (&es->mutex); + es->triggered = false; + pthread_mutex_unlock (&es->mutex); } void JUCE_CALLTYPE Thread::sleep (int millisecs) { - struct timespec time; - time.tv_sec = millisecs / 1000; - time.tv_nsec = (millisecs % 1000) * 1000000; - nanosleep (&time, 0); + struct timespec time; + time.tv_sec = millisecs / 1000; + time.tv_nsec = (millisecs % 1000) * 1000000; + nanosleep (&time, 0); } const tchar File::separator = T('/'); @@ -250832,337 +228549,331 @@ bool juce_copyFile (const String& s, const String& d); static bool juce_stat (const String& fileName, struct stat& info) { - return fileName.isNotEmpty() - && (stat (fileName.toUTF8(), &info) == 0); + return fileName.isNotEmpty() + && (stat (fileName.toUTF8(), &info) == 0); } bool juce_isDirectory (const String& fileName) { - struct stat info; + struct stat info; - return fileName.isEmpty() - || (juce_stat (fileName, info) - && ((info.st_mode & S_IFDIR) != 0)); + return fileName.isEmpty() + || (juce_stat (fileName, info) + && ((info.st_mode & S_IFDIR) != 0)); } bool juce_fileExists (const String& fileName, const bool dontCountDirectories) { - if (fileName.isEmpty()) - return false; + if (fileName.isEmpty()) + return false; - const char* const fileNameUTF8 = fileName.toUTF8(); - bool exists = access (fileNameUTF8, F_OK) == 0; + const char* const fileNameUTF8 = fileName.toUTF8(); + bool exists = access (fileNameUTF8, F_OK) == 0; - if (exists && dontCountDirectories) - { - struct stat info; - const int res = stat (fileNameUTF8, &info); + if (exists && dontCountDirectories) + { + struct stat info; + const int res = stat (fileNameUTF8, &info); - if (res == 0 && (info.st_mode & S_IFDIR) != 0) - exists = false; - } + if (res == 0 && (info.st_mode & S_IFDIR) != 0) + exists = false; + } - return exists; + return exists; } int64 juce_getFileSize (const String& fileName) { - struct stat info; - return juce_stat (fileName, info) ? info.st_size : 0; + struct stat info; + return juce_stat (fileName, info) ? info.st_size : 0; } bool juce_canWriteToFile (const String& fileName) { - return access (fileName.toUTF8(), W_OK) == 0; + return access (fileName.toUTF8(), W_OK) == 0; } bool juce_deleteFile (const String& fileName) { - if (juce_isDirectory (fileName)) - return rmdir ((const char*) fileName.toUTF8()) == 0; - else - return remove ((const char*) fileName.toUTF8()) == 0; + if (juce_isDirectory (fileName)) + return rmdir ((const char*) fileName.toUTF8()) == 0; + else + return remove ((const char*) fileName.toUTF8()) == 0; } bool juce_moveFile (const String& source, const String& dest) { - if (rename (source.toUTF8(), dest.toUTF8()) == 0) - return true; + if (rename (source.toUTF8(), dest.toUTF8()) == 0) + return true; - if (juce_canWriteToFile (source) - && juce_copyFile (source, dest)) - { - if (juce_deleteFile (source)) - return true; + if (juce_canWriteToFile (source) + && juce_copyFile (source, dest)) + { + if (juce_deleteFile (source)) + return true; - juce_deleteFile (dest); - } + juce_deleteFile (dest); + } - return false; + return false; } void juce_createDirectory (const String& fileName) { - mkdir (fileName.toUTF8(), 0777); + mkdir (fileName.toUTF8(), 0777); } void* juce_fileOpen (const String& fileName, bool forWriting) { - int flags = O_RDONLY; + int flags = O_RDONLY; - if (forWriting) - { - if (juce_fileExists (fileName, false)) - { - const int f = open ((const char*) fileName.toUTF8(), O_RDWR, 00644); + if (forWriting) + { + if (juce_fileExists (fileName, false)) + { + const int f = open ((const char*) fileName.toUTF8(), O_RDWR, 00644); - if (f != -1) - lseek (f, 0, SEEK_END); + if (f != -1) + lseek (f, 0, SEEK_END); - return (void*) f; - } - else - { - flags = O_RDWR + O_CREAT; - } - } + return (void*) f; + } + else + { + flags = O_RDWR + O_CREAT; + } + } - return (void*) open ((const char*) fileName.toUTF8(), flags, 00644); + return (void*) open ((const char*) fileName.toUTF8(), flags, 00644); } void juce_fileClose (void* handle) { - if (handle != 0) - close ((int) (pointer_sized_int) handle); + if (handle != 0) + close ((int) (pointer_sized_int) handle); } int juce_fileRead (void* handle, void* buffer, int size) { - if (handle != 0) - return read ((int) (pointer_sized_int) handle, buffer, size); + if (handle != 0) + return (int) read ((int) (pointer_sized_int) handle, buffer, size); - return 0; + return 0; } int juce_fileWrite (void* handle, const void* buffer, int size) { - if (handle != 0) - return write ((int) (pointer_sized_int) handle, buffer, size); + if (handle != 0) + return (int) write ((int) (pointer_sized_int) handle, buffer, size); - return 0; + return 0; } int64 juce_fileSetPosition (void* handle, int64 pos) { - if (handle != 0 && lseek ((int) (pointer_sized_int) handle, pos, SEEK_SET) == pos) - return pos; + if (handle != 0 && lseek ((int) (pointer_sized_int) handle, pos, SEEK_SET) == pos) + return pos; - return -1; + return -1; } int64 juce_fileGetPosition (void* handle) { - if (handle != 0) - return lseek ((int) (pointer_sized_int) handle, 0, SEEK_CUR); - else - return -1; + if (handle != 0) + return lseek ((int) (pointer_sized_int) handle, 0, SEEK_CUR); + else + return -1; } void juce_fileFlush (void* handle) { - if (handle != 0) - fsync ((int) (pointer_sized_int) handle); + if (handle != 0) + fsync ((int) (pointer_sized_int) handle); } const File juce_getExecutableFile() { - Dl_info exeInfo; - dladdr ((const void*) juce_getExecutableFile, &exeInfo); - return File (exeInfo.dli_fname); + Dl_info exeInfo; + dladdr ((const void*) juce_getExecutableFile, &exeInfo); + return File (exeInfo.dli_fname); } // if this file doesn't exist, find a parent of it that does.. static bool doStatFS (const File* file, struct statfs& result) { - File f (*file); + File f (*file); - for (int i = 5; --i >= 0;) - { - if (f.exists()) - break; + for (int i = 5; --i >= 0;) + { + if (f.exists()) + break; - f = f.getParentDirectory(); - } + f = f.getParentDirectory(); + } - return statfs (f.getFullPathName().toUTF8(), &result) == 0; + return statfs (f.getFullPathName().toUTF8(), &result) == 0; } int64 File::getBytesFreeOnVolume() const { - struct statfs buf; - if (doStatFS (this, buf)) - return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user + struct statfs buf; + if (doStatFS (this, buf)) + return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user - return 0; + return 0; } int64 File::getVolumeTotalSize() const { - struct statfs buf; - if (doStatFS (this, buf)) - return (int64) buf.f_bsize * (int64) buf.f_blocks; + struct statfs buf; + if (doStatFS (this, buf)) + return (int64) buf.f_bsize * (int64) buf.f_blocks; - return 0; + return 0; } const String juce_getVolumeLabel (const String& filenameOnVolume, - int& volumeSerialNumber) + int& volumeSerialNumber) { - volumeSerialNumber = 0; + volumeSerialNumber = 0; #if JUCE_MAC - struct VolAttrBuf - { - u_int32_t length; - attrreference_t mountPointRef; - char mountPointSpace [MAXPATHLEN]; - } attrBuf; + struct VolAttrBuf + { + u_int32_t length; + attrreference_t mountPointRef; + char mountPointSpace [MAXPATHLEN]; + } attrBuf; - struct attrlist attrList; - zerostruct (attrList); - attrList.bitmapcount = ATTR_BIT_MAP_COUNT; - attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME; + struct attrlist attrList; + zerostruct (attrList); + attrList.bitmapcount = ATTR_BIT_MAP_COUNT; + attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME; - File f (filenameOnVolume); + File f (filenameOnVolume); - for (;;) - { - if (getattrlist ((const char*) f.getFullPathName().toUTF8(), - &attrList, &attrBuf, sizeof(attrBuf), 0) == 0) - { - return String::fromUTF8 (((const uint8*) &attrBuf.mountPointRef) + attrBuf.mountPointRef.attr_dataoffset, - (int) attrBuf.mountPointRef.attr_length); - } + for (;;) + { + if (getattrlist ((const char*) f.getFullPathName().toUTF8(), + &attrList, &attrBuf, sizeof(attrBuf), 0) == 0) + { + return String::fromUTF8 (((const uint8*) &attrBuf.mountPointRef) + attrBuf.mountPointRef.attr_dataoffset, + (int) attrBuf.mountPointRef.attr_length); + } - const File parent (f.getParentDirectory()); + const File parent (f.getParentDirectory()); - if (f == parent) - break; + if (f == parent) + break; - f = parent; - } + f = parent; + } #endif - return String::empty; + return String::empty; } void juce_runSystemCommand (const String& command) { - int result = system ((const char*) command.toUTF8()); - (void) result; + int result = system ((const char*) command.toUTF8()); + (void) result; } const String juce_getOutputFromCommand (const String& command) { - // slight bodge here, as we just pipe the output into a temp file and read it... - const File tempFile (File::getSpecialLocation (File::tempDirectory) - .getNonexistentChildFile (String::toHexString (Random::getSystemRandom().nextInt()), ".tmp", false)); + // slight bodge here, as we just pipe the output into a temp file and read it... + const File tempFile (File::getSpecialLocation (File::tempDirectory) + .getNonexistentChildFile (String::toHexString (Random::getSystemRandom().nextInt()), ".tmp", false)); - juce_runSystemCommand (command + " > " + tempFile.getFullPathName()); + juce_runSystemCommand (command + " > " + tempFile.getFullPathName()); - String result (tempFile.loadFileAsString()); - tempFile.deleteFile(); - return result; + String result (tempFile.loadFileAsString()); + tempFile.deleteFile(); + return result; } -#if JUCE_64BIT - #define filedesc ((long long) internal) -#else - #define filedesc ((int) internal) -#endif - InterProcessLock::InterProcessLock (const String& name_) - : internal (0), - name (name_), - reentrancyLevel (0) + : internal (0), + name (name_), + reentrancyLevel (0) { #if JUCE_MAC - // (don't use getSpecialLocation() to avoid the temp folder being different for each app) - const File temp (File (T("~/Library/Caches/Juce")).getChildFile (name)); + // (don't use getSpecialLocation() to avoid the temp folder being different for each app) + const File temp (File (T("~/Library/Caches/Juce")).getChildFile (name)); #else - const File temp (File::getSpecialLocation (File::tempDirectory).getChildFile (name)); + const File temp (File::getSpecialLocation (File::tempDirectory).getChildFile (name)); #endif - temp.create(); + temp.create(); - internal = (void*) open (temp.getFullPathName().toUTF8(), O_RDWR); + internal = open (temp.getFullPathName().toUTF8(), O_RDWR); } InterProcessLock::~InterProcessLock() { - while (reentrancyLevel > 0) - this->exit(); + while (reentrancyLevel > 0) + this->exit(); - close (filedesc); + close (internal); } bool InterProcessLock::enter (const int timeOutMillisecs) { - if (internal == 0) - return false; + if (internal == 0) + return false; - if (reentrancyLevel != 0) - return true; + if (reentrancyLevel != 0) + return true; - const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs; + const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs; - struct flock fl; - zerostruct (fl); - fl.l_whence = SEEK_SET; - fl.l_type = F_WRLCK; + struct flock fl; + zerostruct (fl); + fl.l_whence = SEEK_SET; + fl.l_type = F_WRLCK; - for (;;) - { - const int result = fcntl (filedesc, F_SETLK, &fl); + for (;;) + { + const int result = fcntl (internal, F_SETLK, &fl); - if (result >= 0) - { - ++reentrancyLevel; - return true; - } + if (result >= 0) + { + ++reentrancyLevel; + return true; + } - if (errno != EINTR) - { - if (timeOutMillisecs == 0 - || (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime)) - break; + if (errno != EINTR) + { + if (timeOutMillisecs == 0 + || (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime)) + break; - Thread::sleep (10); - } - } + Thread::sleep (10); + } + } - return false; + return false; } void InterProcessLock::exit() { - if (reentrancyLevel > 0 && internal != 0) - { - --reentrancyLevel; + if (reentrancyLevel > 0 && internal != 0) + { + --reentrancyLevel; - struct flock fl; - zerostruct (fl); - fl.l_whence = SEEK_SET; - fl.l_type = F_UNLCK; + struct flock fl; + zerostruct (fl); + fl.l_whence = SEEK_SET; + fl.l_type = F_UNLCK; - for (;;) - { - const int result = fcntl (filedesc, F_SETLKW, &fl); + for (;;) + { + const int result = fcntl (internal, F_SETLKW, &fl); - if (result >= 0 || errno != EINTR) - break; - } - } + if (result >= 0 || errno != EINTR) + break; + } + } } /********* End of inlined file: juce_posix_SharedCode.h *********/ @@ -251171,422 +228882,422 @@ void InterProcessLock::exit() // compiled on its own). #if JUCE_INCLUDED_FILE -#define U_ISOFS_SUPER_MAGIC (short) 0x9660 // linux/iso_fs.h -#define U_MSDOS_SUPER_MAGIC (short) 0x4d44 // linux/msdos_fs.h -#define U_NFS_SUPER_MAGIC (short) 0x6969 // linux/nfs_fs.h -#define U_SMB_SUPER_MAGIC (short) 0x517B // linux/smb_fs.h +#define U_ISOFS_SUPER_MAGIC (short) 0x9660 // linux/iso_fs.h +#define U_MSDOS_SUPER_MAGIC (short) 0x4d44 // linux/msdos_fs.h +#define U_NFS_SUPER_MAGIC (short) 0x6969 // linux/nfs_fs.h +#define U_SMB_SUPER_MAGIC (short) 0x517B // linux/smb_fs.h void juce_getFileTimes (const String& fileName, - int64& modificationTime, - int64& accessTime, - int64& creationTime) + int64& modificationTime, + int64& accessTime, + int64& creationTime) { - modificationTime = 0; - accessTime = 0; - creationTime = 0; + modificationTime = 0; + accessTime = 0; + creationTime = 0; - struct stat info; - const int res = stat (fileName.toUTF8(), &info); - if (res == 0) - { - modificationTime = (int64) info.st_mtime * 1000; - accessTime = (int64) info.st_atime * 1000; - creationTime = (int64) info.st_ctime * 1000; - } + struct stat info; + const int res = stat (fileName.toUTF8(), &info); + if (res == 0) + { + modificationTime = (int64) info.st_mtime * 1000; + accessTime = (int64) info.st_atime * 1000; + creationTime = (int64) info.st_ctime * 1000; + } } bool juce_setFileTimes (const String& fileName, - int64 modificationTime, - int64 accessTime, - int64 creationTime) + int64 modificationTime, + int64 accessTime, + int64 creationTime) { - struct utimbuf times; - times.actime = (time_t) (accessTime / 1000); - times.modtime = (time_t) (modificationTime / 1000); + struct utimbuf times; + times.actime = (time_t) (accessTime / 1000); + times.modtime = (time_t) (modificationTime / 1000); - return utime (fileName.toUTF8(), ×) == 0; + return utime (fileName.toUTF8(), ×) == 0; } bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) { - struct stat info; - const int res = stat (fileName.toUTF8(), &info); - if (res != 0) - return false; + struct stat info; + const int res = stat (fileName.toUTF8(), &info); + if (res != 0) + return false; - info.st_mode &= 0777; // Just permissions + info.st_mode &= 0777; // Just permissions - if( isReadOnly ) - info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); - else - // Give everybody write permission? - info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + if( isReadOnly ) + info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + else + // Give everybody write permission? + info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; - return chmod (fileName.toUTF8(), info.st_mode) == 0; + return chmod (fileName.toUTF8(), info.st_mode) == 0; } bool juce_copyFile (const String& s, const String& d) { - const File source (s), dest (d); + const File source (s), dest (d); - FileInputStream* in = source.createInputStream(); - bool ok = false; + FileInputStream* in = source.createInputStream(); + bool ok = false; - if (in != 0) - { - if (dest.deleteFile()) - { - FileOutputStream* const out = dest.createOutputStream(); + if (in != 0) + { + if (dest.deleteFile()) + { + FileOutputStream* const out = dest.createOutputStream(); - if (out != 0) - { - const int bytesCopied = out->writeFromInputStream (*in, -1); - delete out; + if (out != 0) + { + const int bytesCopied = out->writeFromInputStream (*in, -1); + delete out; - ok = (bytesCopied == source.getSize()); + ok = (bytesCopied == source.getSize()); - if (! ok) - dest.deleteFile(); - } - } + if (! ok) + dest.deleteFile(); + } + } - delete in; - } + delete in; + } - return ok; + return ok; } const StringArray juce_getFileSystemRoots() { - StringArray s; - s.add (T("/")); - return s; + StringArray s; + s.add (T("/")); + return s; } bool File::isOnCDRomDrive() const { - struct statfs buf; + struct statfs buf; - if (statfs (getFullPathName().toUTF8(), &buf) == 0) - return (buf.f_type == U_ISOFS_SUPER_MAGIC); + if (statfs (getFullPathName().toUTF8(), &buf) == 0) + return (buf.f_type == U_ISOFS_SUPER_MAGIC); - // Assume not if this fails for some reason - return false; + // Assume not if this fails for some reason + return false; } bool File::isOnHardDisk() const { - struct statfs buf; + struct statfs buf; - if (statfs (getFullPathName().toUTF8(), &buf) == 0) - { - switch (buf.f_type) - { - case U_ISOFS_SUPER_MAGIC: // CD-ROM - case U_MSDOS_SUPER_MAGIC: // Probably floppy (but could be mounted FAT filesystem) - case U_NFS_SUPER_MAGIC: // Network NFS - case U_SMB_SUPER_MAGIC: // Network Samba - return false; + if (statfs (getFullPathName().toUTF8(), &buf) == 0) + { + switch (buf.f_type) + { + case U_ISOFS_SUPER_MAGIC: // CD-ROM + case U_MSDOS_SUPER_MAGIC: // Probably floppy (but could be mounted FAT filesystem) + case U_NFS_SUPER_MAGIC: // Network NFS + case U_SMB_SUPER_MAGIC: // Network Samba + return false; - default: - // Assume anything else is a hard-disk (but note it could - // be a RAM disk. There isn't a good way of determining - // this for sure) - return true; - } - } + default: + // Assume anything else is a hard-disk (but note it could + // be a RAM disk. There isn't a good way of determining + // this for sure) + return true; + } + } - // Assume so if this fails for some reason - return true; + // Assume so if this fails for some reason + return true; } bool File::isOnRemovableDrive() const { - jassertfalse // xxx not implemented for linux! - return false; + jassertfalse // xxx not implemented for linux! + return false; } bool File::isHidden() const { - return getFileName().startsWithChar (T('.')); + return getFileName().startsWithChar (T('.')); } const char* juce_Argv0 = 0; // referenced from juce_Application.cpp const File File::getSpecialLocation (const SpecialLocationType type) { - switch (type) - { - case userHomeDirectory: - { - const char* homeDir = getenv ("HOME"); + switch (type) + { + case userHomeDirectory: + { + const char* homeDir = getenv ("HOME"); - if (homeDir == 0) - { - struct passwd* const pw = getpwuid (getuid()); - if (pw != 0) - homeDir = pw->pw_dir; - } + if (homeDir == 0) + { + struct passwd* const pw = getpwuid (getuid()); + if (pw != 0) + homeDir = pw->pw_dir; + } - return File (String::fromUTF8 ((const uint8*) homeDir)); - } + return File (String::fromUTF8 ((const uint8*) homeDir)); + } - case userDocumentsDirectory: - case userMusicDirectory: - case userMoviesDirectory: - case userApplicationDataDirectory: - return File ("~"); + case userDocumentsDirectory: + case userMusicDirectory: + case userMoviesDirectory: + case userApplicationDataDirectory: + return File ("~"); - case userDesktopDirectory: - return File ("~/Desktop"); + case userDesktopDirectory: + return File ("~/Desktop"); - case commonApplicationDataDirectory: - return File ("/var"); + case commonApplicationDataDirectory: + return File ("/var"); - case globalApplicationsDirectory: - return File ("/usr"); + case globalApplicationsDirectory: + return File ("/usr"); - case tempDirectory: - { - File tmp ("/var/tmp"); + case tempDirectory: + { + File tmp ("/var/tmp"); - if (! tmp.isDirectory()) - { - tmp = T("/tmp"); + if (! tmp.isDirectory()) + { + tmp = T("/tmp"); - if (! tmp.isDirectory()) - tmp = File::getCurrentWorkingDirectory(); - } + if (! tmp.isDirectory()) + tmp = File::getCurrentWorkingDirectory(); + } - return tmp; - } + return tmp; + } - case invokedExecutableFile: - if (juce_Argv0 != 0) - return File (String::fromUTF8 ((const uint8*) juce_Argv0)); - // deliberate fall-through... + case invokedExecutableFile: + if (juce_Argv0 != 0) + return File (String::fromUTF8 ((const uint8*) juce_Argv0)); + // deliberate fall-through... - case currentExecutableFile: - case currentApplicationFile: - return juce_getExecutableFile(); + case currentExecutableFile: + case currentApplicationFile: + return juce_getExecutableFile(); - default: - jassertfalse // unknown type? - break; - } + default: + jassertfalse // unknown type? + break; + } - return File::nonexistent; + return File::nonexistent; } const File File::getCurrentWorkingDirectory() { - char buf [2048]; - return File (String::fromUTF8 ((const uint8*) getcwd (buf, sizeof (buf)))); + char buf [2048]; + return File (String::fromUTF8 ((const uint8*) getcwd (buf, sizeof (buf)))); } bool File::setAsCurrentWorkingDirectory() const { - return chdir (getFullPathName().toUTF8()) == 0; + return chdir (getFullPathName().toUTF8()) == 0; } const String File::getVersion() const { - return String::empty; // xxx not yet implemented + return String::empty; // xxx not yet implemented } const File File::getLinkedTarget() const { - char buffer [4096]; - size_t numChars = readlink ((const char*) getFullPathName().toUTF8(), - buffer, sizeof (buffer)); + char buffer [4096]; + size_t numChars = readlink ((const char*) getFullPathName().toUTF8(), + buffer, sizeof (buffer)); - if (numChars > 0 && numChars <= sizeof (buffer)) - return File (String::fromUTF8 ((const uint8*) buffer, (int) numChars)); + if (numChars > 0 && numChars <= sizeof (buffer)) + return File (String::fromUTF8 ((const uint8*) buffer, (int) numChars)); - return *this; + return *this; } bool File::moveToTrash() const { - if (! exists()) - return true; + if (! exists()) + return true; - File trashCan (T("~/.Trash")); + File trashCan (T("~/.Trash")); - if (! trashCan.isDirectory()) - trashCan = T("~/.local/share/Trash/files"); + if (! trashCan.isDirectory()) + trashCan = T("~/.local/share/Trash/files"); - if (! trashCan.isDirectory()) - return false; + if (! trashCan.isDirectory()) + return false; - return moveFileTo (trashCan.getNonexistentChildFile (getFileNameWithoutExtension(), - getFileExtension())); + return moveFileTo (trashCan.getNonexistentChildFile (getFileNameWithoutExtension(), + getFileExtension())); } struct FindFileStruct { - String parentDir, wildCard; - DIR* dir; + String parentDir, wildCard; + DIR* dir; - bool getNextMatch (String& result, bool* const isDir, bool* const isHidden, int64* const fileSize, - Time* const modTime, Time* const creationTime, bool* const isReadOnly) - { - const char* const wildcardUTF8 = wildCard.toUTF8(); + bool getNextMatch (String& result, bool* const isDir, bool* const isHidden, int64* const fileSize, + Time* const modTime, Time* const creationTime, bool* const isReadOnly) + { + const char* const wildcardUTF8 = wildCard.toUTF8(); - for (;;) - { - struct dirent* const de = readdir (dir); + for (;;) + { + struct dirent* const de = readdir (dir); - if (de == 0) - break; + if (de == 0) + break; - if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0) - { - result = String::fromUTF8 ((const uint8*) de->d_name); + if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0) + { + result = String::fromUTF8 ((const uint8*) de->d_name); - const String path (parentDir + result); + const String path (parentDir + result); - if (isDir != 0 || fileSize != 0) - { - struct stat info; - const bool statOk = (stat (path.toUTF8(), &info) == 0); + if (isDir != 0 || fileSize != 0) + { + struct stat info; + const bool statOk = (stat (path.toUTF8(), &info) == 0); - if (isDir != 0) - *isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0)); + if (isDir != 0) + *isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0)); - if (isHidden != 0) - *isHidden = (de->d_name[0] == '.'); + if (isHidden != 0) + *isHidden = (de->d_name[0] == '.'); - if (fileSize != 0) - *fileSize = statOk ? info.st_size : 0; - } + if (fileSize != 0) + *fileSize = statOk ? info.st_size : 0; + } - if (modTime != 0 || creationTime != 0) - { - int64 m, a, c; - juce_getFileTimes (path, m, a, c); + if (modTime != 0 || creationTime != 0) + { + int64 m, a, c; + juce_getFileTimes (path, m, a, c); - if (modTime != 0) - *modTime = m; + if (modTime != 0) + *modTime = m; - if (creationTime != 0) - *creationTime = c; - } + if (creationTime != 0) + *creationTime = c; + } - if (isReadOnly != 0) - *isReadOnly = ! juce_canWriteToFile (path); + if (isReadOnly != 0) + *isReadOnly = ! juce_canWriteToFile (path); - return true; - } - } + return true; + } + } - return false; - } + return false; + } }; // returns 0 on failure void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile, - bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, - Time* creationTime, bool* isReadOnly) + bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, + Time* creationTime, bool* isReadOnly) { - DIR* d = opendir (directory.toUTF8()); + DIR* d = opendir (directory.toUTF8()); - if (d != 0) - { - FindFileStruct* ff = new FindFileStruct(); - ff->parentDir = directory; + if (d != 0) + { + FindFileStruct* ff = new FindFileStruct(); + ff->parentDir = directory; - if (!ff->parentDir.endsWithChar (File::separator)) - ff->parentDir += File::separator; + if (!ff->parentDir.endsWithChar (File::separator)) + ff->parentDir += File::separator; - ff->wildCard = wildCard; - if (wildCard == T("*.*")) - ff->wildCard = T("*"); + ff->wildCard = wildCard; + if (wildCard == T("*.*")) + ff->wildCard = T("*"); - ff->dir = d; + ff->dir = d; - if (ff->getNextMatch (firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly)) - { - return ff; - } - else - { - firstResultFile = String::empty; - isDir = false; - isHidden = false; - closedir (d); - delete ff; - } - } + if (ff->getNextMatch (firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly)) + { + return ff; + } + else + { + firstResultFile = String::empty; + isDir = false; + isHidden = false; + closedir (d); + delete ff; + } + } - return 0; + return 0; } bool juce_findFileNext (void* handle, String& resultFile, - bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) + bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) { - FindFileStruct* const ff = (FindFileStruct*) handle; + FindFileStruct* const ff = (FindFileStruct*) handle; - if (ff != 0) - return ff->getNextMatch (resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); + if (ff != 0) + return ff->getNextMatch (resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); - return false; + return false; } void juce_findFileClose (void* handle) { - FindFileStruct* const ff = (FindFileStruct*) handle; + FindFileStruct* const ff = (FindFileStruct*) handle; - if (ff != 0) - { - closedir (ff->dir); - delete ff; - } + if (ff != 0) + { + closedir (ff->dir); + delete ff; + } } bool juce_launchFile (const String& fileName, - const String& parameters) + const String& parameters) { - String cmdString (fileName.replace (T(" "), T("\\ "),false)); - cmdString << " " << parameters; + String cmdString (fileName.replace (T(" "), T("\\ "),false)); + cmdString << " " << parameters; - if (URL::isProbablyAWebsiteURL (fileName) - || cmdString.startsWithIgnoreCase (T("file:")) - || URL::isProbablyAnEmailAddress (fileName)) - { - // create a command that tries to launch a bunch of likely browsers - const char* const browserNames[] = { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" }; + if (URL::isProbablyAWebsiteURL (fileName) + || cmdString.startsWithIgnoreCase (T("file:")) + || URL::isProbablyAnEmailAddress (fileName)) + { + // create a command that tries to launch a bunch of likely browsers + const char* const browserNames[] = { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" }; - StringArray cmdLines; + StringArray cmdLines; - for (int i = 0; i < numElementsInArray (browserNames); ++i) - cmdLines.add (String (browserNames[i]) + T(" ") + cmdString.trim().quoted()); + for (int i = 0; i < numElementsInArray (browserNames); ++i) + cmdLines.add (String (browserNames[i]) + T(" ") + cmdString.trim().quoted()); - cmdString = cmdLines.joinIntoString (T(" || ")); - } + cmdString = cmdLines.joinIntoString (T(" || ")); + } - const char* const argv[4] = { "/bin/sh", "-c", (const char*) cmdString.toUTF8(), 0 }; + const char* const argv[4] = { "/bin/sh", "-c", (const char*) cmdString.toUTF8(), 0 }; - const int cpid = fork(); + const int cpid = fork(); - if (cpid == 0) - { - setsid(); + if (cpid == 0) + { + setsid(); - // Child process - execve (argv[0], (char**) argv, environ); - exit (0); - } + // Child process + execve (argv[0], (char**) argv, environ); + exit (0); + } - return cpid >= 0; + return cpid >= 0; } void File::revealToUser() const { - if (isDirectory()) - startAsProcess(); - else if (getParentDirectory().exists()) - getParentDirectory().startAsProcess(); + if (isDirectory()) + startAsProcess(); + else if (getParentDirectory().exists()) + getParentDirectory().startAsProcess(); } #endif @@ -251599,184 +229310,184 @@ void File::revealToUser() const struct NamedPipeInternal { - String pipeInName, pipeOutName; - int pipeIn, pipeOut; + String pipeInName, pipeOutName; + int pipeIn, pipeOut; - bool volatile createdPipe, blocked, stopReadOperation; + bool volatile createdPipe, blocked, stopReadOperation; - static void signalHandler (int) {} + static void signalHandler (int) {} }; void NamedPipe::cancelPendingReads() { - while (internal != 0 && ((NamedPipeInternal*) internal)->blocked) - { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + while (internal != 0 && ((NamedPipeInternal*) internal)->blocked) + { + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - intern->stopReadOperation = true; + intern->stopReadOperation = true; - char buffer [1] = { 0 }; - int bytesWritten = ::write (intern->pipeIn, buffer, 1); - (void) bytesWritten; + char buffer [1] = { 0 }; + int bytesWritten = (int) ::write (intern->pipeIn, buffer, 1); + (void) bytesWritten; - int timeout = 2000; - while (intern->blocked && --timeout >= 0) - Thread::sleep (2); + int timeout = 2000; + while (intern->blocked && --timeout >= 0) + Thread::sleep (2); - intern->stopReadOperation = false; - } + intern->stopReadOperation = false; + } } void NamedPipe::close() { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - if (intern != 0) - { - internal = 0; + if (intern != 0) + { + internal = 0; - if (intern->pipeIn != -1) - ::close (intern->pipeIn); + if (intern->pipeIn != -1) + ::close (intern->pipeIn); - if (intern->pipeOut != -1) - ::close (intern->pipeOut); + if (intern->pipeOut != -1) + ::close (intern->pipeOut); - if (intern->createdPipe) - { - unlink (intern->pipeInName); - unlink (intern->pipeOutName); - } + if (intern->createdPipe) + { + unlink (intern->pipeInName); + unlink (intern->pipeOutName); + } - delete intern; - } + delete intern; + } } bool NamedPipe::openInternal (const String& pipeName, const bool createPipe) { - close(); + close(); - NamedPipeInternal* const intern = new NamedPipeInternal(); - internal = intern; - intern->createdPipe = createPipe; - intern->blocked = false; - intern->stopReadOperation = false; + NamedPipeInternal* const intern = new NamedPipeInternal(); + internal = intern; + intern->createdPipe = createPipe; + intern->blocked = false; + intern->stopReadOperation = false; - signal (SIGPIPE, NamedPipeInternal::signalHandler); - siginterrupt (SIGPIPE, 1); + signal (SIGPIPE, NamedPipeInternal::signalHandler); + siginterrupt (SIGPIPE, 1); - const String pipePath (T("/tmp/") + File::createLegalFileName (pipeName)); + const String pipePath (T("/tmp/") + File::createLegalFileName (pipeName)); - intern->pipeInName = pipePath + T("_in"); - intern->pipeOutName = pipePath + T("_out"); - intern->pipeIn = -1; - intern->pipeOut = -1; + intern->pipeInName = pipePath + T("_in"); + intern->pipeOutName = pipePath + T("_out"); + intern->pipeIn = -1; + intern->pipeOut = -1; - if (createPipe) - { - if ((mkfifo (intern->pipeInName, 0666) && errno != EEXIST) - || (mkfifo (intern->pipeOutName, 0666) && errno != EEXIST)) - { - delete intern; - internal = 0; + if (createPipe) + { + if ((mkfifo (intern->pipeInName, 0666) && errno != EEXIST) + || (mkfifo (intern->pipeOutName, 0666) && errno != EEXIST)) + { + delete intern; + internal = 0; - return false; - } - } + return false; + } + } - return true; + return true; } int NamedPipe::read (void* destBuffer, int maxBytesToRead, int /*timeOutMilliseconds*/) { - int bytesRead = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + int bytesRead = -1; + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - if (intern != 0) - { - intern->blocked = true; + if (intern != 0) + { + intern->blocked = true; - if (intern->pipeIn == -1) - { - if (intern->createdPipe) - intern->pipeIn = ::open (intern->pipeInName, O_RDWR); - else - intern->pipeIn = ::open (intern->pipeOutName, O_RDWR); + if (intern->pipeIn == -1) + { + if (intern->createdPipe) + intern->pipeIn = ::open (intern->pipeInName, O_RDWR); + else + intern->pipeIn = ::open (intern->pipeOutName, O_RDWR); - if (intern->pipeIn == -1) - { - intern->blocked = false; - return -1; - } - } + if (intern->pipeIn == -1) + { + intern->blocked = false; + return -1; + } + } - bytesRead = 0; + bytesRead = 0; - char* p = (char*) destBuffer; + char* p = (char*) destBuffer; - while (bytesRead < maxBytesToRead) - { - const int bytesThisTime = maxBytesToRead - bytesRead; - const int numRead = ::read (intern->pipeIn, p, bytesThisTime); + while (bytesRead < maxBytesToRead) + { + const int bytesThisTime = maxBytesToRead - bytesRead; + const int numRead = (int) ::read (intern->pipeIn, p, bytesThisTime); - if (numRead <= 0 || intern->stopReadOperation) - { - bytesRead = -1; - break; - } + if (numRead <= 0 || intern->stopReadOperation) + { + bytesRead = -1; + break; + } - bytesRead += numRead; - p += bytesRead; - } + bytesRead += numRead; + p += bytesRead; + } - intern->blocked = false; - } + intern->blocked = false; + } - return bytesRead; + return bytesRead; } int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds) { - int bytesWritten = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + int bytesWritten = -1; + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - if (intern != 0) - { - if (intern->pipeOut == -1) - { - if (intern->createdPipe) - intern->pipeOut = ::open (intern->pipeOutName, O_WRONLY); - else - intern->pipeOut = ::open (intern->pipeInName, O_WRONLY); + if (intern != 0) + { + if (intern->pipeOut == -1) + { + if (intern->createdPipe) + intern->pipeOut = ::open (intern->pipeOutName, O_WRONLY); + else + intern->pipeOut = ::open (intern->pipeInName, O_WRONLY); - if (intern->pipeOut == -1) - { - return -1; - } - } + if (intern->pipeOut == -1) + { + return -1; + } + } - const char* p = (const char*) sourceBuffer; - bytesWritten = 0; + const char* p = (const char*) sourceBuffer; + bytesWritten = 0; - const uint32 timeOutTime = Time::getMillisecondCounter() + timeOutMilliseconds; + const uint32 timeOutTime = Time::getMillisecondCounter() + timeOutMilliseconds; - while (bytesWritten < numBytesToWrite - && (timeOutMilliseconds < 0 || Time::getMillisecondCounter() < timeOutTime)) - { - const int bytesThisTime = numBytesToWrite - bytesWritten; - const int numWritten = ::write (intern->pipeOut, p, bytesThisTime); + while (bytesWritten < numBytesToWrite + && (timeOutMilliseconds < 0 || Time::getMillisecondCounter() < timeOutTime)) + { + const int bytesThisTime = numBytesToWrite - bytesWritten; + const int numWritten = (int) ::write (intern->pipeOut, p, bytesThisTime); - if (numWritten <= 0) - { - bytesWritten = -1; - break; - } + if (numWritten <= 0) + { + bytesWritten = -1; + break; + } - bytesWritten += numWritten; - p += bytesWritten; - } - } + bytesWritten += numWritten; + p += bytesWritten; + } + } - return bytesWritten; + return bytesWritten; } #endif @@ -251789,441 +229500,439 @@ int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOut int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw() { - int numResults = 0; + int numResults = 0; - const int s = socket (AF_INET, SOCK_DGRAM, 0); - if (s != -1) - { - char buf [1024]; - struct ifconf ifc; - ifc.ifc_len = sizeof (buf); - ifc.ifc_buf = buf; - ioctl (s, SIOCGIFCONF, &ifc); + const int s = socket (AF_INET, SOCK_DGRAM, 0); + if (s != -1) + { + char buf [1024]; + struct ifconf ifc; + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + ioctl (s, SIOCGIFCONF, &ifc); - for (unsigned int i = 0; i < ifc.ifc_len / sizeof (struct ifreq); ++i) - { - struct ifreq ifr; - strcpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name); + for (unsigned int i = 0; i < ifc.ifc_len / sizeof (struct ifreq); ++i) + { + struct ifreq ifr; + strcpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name); - if (ioctl (s, SIOCGIFFLAGS, &ifr) == 0 - && (ifr.ifr_flags & IFF_LOOPBACK) == 0 - && ioctl (s, SIOCGIFHWADDR, &ifr) == 0 - && numResults < maxNum) - { - int64 a = 0; - for (int j = 6; --j >= 0;) - a = (a << 8) | (uint8) ifr.ifr_hwaddr.sa_data [littleEndian ? j : (5 - j)]; + if (ioctl (s, SIOCGIFFLAGS, &ifr) == 0 + && (ifr.ifr_flags & IFF_LOOPBACK) == 0 + && ioctl (s, SIOCGIFHWADDR, &ifr) == 0 + && numResults < maxNum) + { + int64 a = 0; + for (int j = 6; --j >= 0;) + a = (a << 8) | (uint8) ifr.ifr_hwaddr.sa_data [littleEndian ? j : (5 - j)]; - *addresses++ = a; - ++numResults; - } - } + *addresses++ = a; + ++numResults; + } + } - close (s); - } + close (s); + } - return numResults; + return numResults; } bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress, - const String& emailSubject, - const String& bodyText, - const StringArray& filesToAttach) + const String& emailSubject, + const String& bodyText, + const StringArray& filesToAttach) { - jassertfalse // xxx todo + jassertfalse // xxx todo - return false; + return false; } -/** A HTTP input stream that uses sockets. - */ class JUCE_HTTPSocketStream { public: - JUCE_HTTPSocketStream() - : readPosition (0), - socketHandle (-1), - levelsOfRedirection (0), - timeoutSeconds (15) - { - } + JUCE_HTTPSocketStream() + : readPosition (0), + socketHandle (-1), + levelsOfRedirection (0), + timeoutSeconds (15) + { + } - ~JUCE_HTTPSocketStream() - { - closeSocket(); - } + ~JUCE_HTTPSocketStream() + { + closeSocket(); + } - bool open (const String& url, - const String& headers, - const MemoryBlock& postData, - const bool isPost, - URL::OpenStreamProgressCallback* callback, - void* callbackContext, - int timeOutMs) - { - closeSocket(); + bool open (const String& url, + const String& headers, + const MemoryBlock& postData, + const bool isPost, + URL::OpenStreamProgressCallback* callback, + void* callbackContext, + int timeOutMs) + { + closeSocket(); - uint32 timeOutTime = Time::getMillisecondCounter(); + uint32 timeOutTime = Time::getMillisecondCounter(); - if (timeOutMs == 0) - timeOutTime += 60000; - else if (timeOutMs < 0) - timeOutTime = 0xffffffff; - else - timeOutTime += timeOutMs; + if (timeOutMs == 0) + timeOutTime += 60000; + else if (timeOutMs < 0) + timeOutTime = 0xffffffff; + else + timeOutTime += timeOutMs; - String hostName, hostPath; - int hostPort; + String hostName, hostPath; + int hostPort; - if (! decomposeURL (url, hostName, hostPath, hostPort)) - return false; + if (! decomposeURL (url, hostName, hostPath, hostPort)) + return false; - const struct hostent* host = 0; - int port = 0; + const struct hostent* host = 0; + int port = 0; - String proxyName, proxyPath; - int proxyPort = 0; + String proxyName, proxyPath; + int proxyPort = 0; - String proxyURL (getenv ("http_proxy")); - if (proxyURL.startsWithIgnoreCase (T("http://"))) - { - if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort)) - return false; + String proxyURL (getenv ("http_proxy")); + if (proxyURL.startsWithIgnoreCase (T("http://"))) + { + if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort)) + return false; - host = gethostbyname ((const char*) proxyName.toUTF8()); - port = proxyPort; - } - else - { - host = gethostbyname ((const char*) hostName.toUTF8()); - port = hostPort; - } + host = gethostbyname ((const char*) proxyName.toUTF8()); + port = proxyPort; + } + else + { + host = gethostbyname ((const char*) hostName.toUTF8()); + port = hostPort; + } - if (host == 0) - return false; + if (host == 0) + return false; - struct sockaddr_in address; - zerostruct (address); - memcpy ((void*) &address.sin_addr, (const void*) host->h_addr, host->h_length); - address.sin_family = host->h_addrtype; - address.sin_port = htons (port); + struct sockaddr_in address; + zerostruct (address); + memcpy ((void*) &address.sin_addr, (const void*) host->h_addr, host->h_length); + address.sin_family = host->h_addrtype; + address.sin_port = htons (port); - socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0); + socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0); - if (socketHandle == -1) - return false; + if (socketHandle == -1) + return false; - int receiveBufferSize = 16384; - setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize)); - setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0); + int receiveBufferSize = 16384; + setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize)); + setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0); #if JUCE_MAC - setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0); + setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0); #endif - if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1) - { - closeSocket(); - return false; - } + if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1) + { + closeSocket(); + return false; + } - const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, - proxyName, proxyPort, - hostPath, url, - headers, postData, - isPost)); - int totalHeaderSent = 0; + const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, + proxyName, proxyPort, + hostPath, url, + headers, postData, + isPost)); + size_t totalHeaderSent = 0; - while (totalHeaderSent < requestHeader.getSize()) - { - if (Time::getMillisecondCounter() > timeOutTime) - { - closeSocket(); - return false; - } + while (totalHeaderSent < requestHeader.getSize()) + { + if (Time::getMillisecondCounter() > timeOutTime) + { + closeSocket(); + return false; + } - const int numToSend = jmin (1024, requestHeader.getSize() - totalHeaderSent); + const int numToSend = jmin (1024, (int) (requestHeader.getSize() - totalHeaderSent)); - if (send (socketHandle, - ((const char*) requestHeader.getData()) + totalHeaderSent, - numToSend, 0) - != numToSend) - { - closeSocket(); - return false; - } + if (send (socketHandle, + ((const char*) requestHeader.getData()) + totalHeaderSent, + numToSend, 0) + != numToSend) + { + closeSocket(); + return false; + } - totalHeaderSent += numToSend; + totalHeaderSent += numToSend; - if (callback != 0 && ! callback (callbackContext, totalHeaderSent, requestHeader.getSize())) - { - closeSocket(); - return false; - } - } + if (callback != 0 && ! callback (callbackContext, totalHeaderSent, requestHeader.getSize())) + { + closeSocket(); + return false; + } + } - const String responseHeader (readResponse (timeOutTime)); + const String responseHeader (readResponse (timeOutTime)); - if (responseHeader.isNotEmpty()) - { - //DBG (responseHeader); + if (responseHeader.isNotEmpty()) + { + //DBG (responseHeader); - StringArray lines; - lines.addLines (responseHeader); + StringArray lines; + lines.addLines (responseHeader); - // NB - using charToString() here instead of just T(" "), because that was - // causing a mysterious gcc internal compiler error... - const int statusCode = responseHeader.fromFirstOccurrenceOf (String::charToString (T(' ')), false, false) - .substring (0, 3).getIntValue(); + // NB - using charToString() here instead of just T(" "), because that was + // causing a mysterious gcc internal compiler error... + const int statusCode = responseHeader.fromFirstOccurrenceOf (String::charToString (T(' ')), false, false) + .substring (0, 3).getIntValue(); - //int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue(); - //bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked"); + //int contentLength = findHeaderItem (lines, T("Content-Length:")).getIntValue(); + //bool isChunked = findHeaderItem (lines, T("Transfer-Encoding:")).equalsIgnoreCase ("chunked"); - String location (findHeaderItem (lines, T("Location:"))); + String location (findHeaderItem (lines, T("Location:"))); - if (statusCode >= 300 && statusCode < 400 - && location.isNotEmpty()) - { - if (! location.startsWithIgnoreCase (T("http://"))) - location = T("http://") + location; + if (statusCode >= 300 && statusCode < 400 + && location.isNotEmpty()) + { + if (! location.startsWithIgnoreCase (T("http://"))) + location = T("http://") + location; - if (levelsOfRedirection++ < 3) - return open (location, headers, postData, isPost, callback, callbackContext, timeOutMs); - } - else - { - levelsOfRedirection = 0; - return true; - } - } + if (levelsOfRedirection++ < 3) + return open (location, headers, postData, isPost, callback, callbackContext, timeOutMs); + } + else + { + levelsOfRedirection = 0; + return true; + } + } - closeSocket(); - return false; - } + closeSocket(); + return false; + } - int read (void* buffer, int bytesToRead) - { - fd_set readbits; - FD_ZERO (&readbits); - FD_SET (socketHandle, &readbits); + int read (void* buffer, int bytesToRead) + { + fd_set readbits; + FD_ZERO (&readbits); + FD_SET (socketHandle, &readbits); - struct timeval tv; - tv.tv_sec = timeoutSeconds; - tv.tv_usec = 0; + struct timeval tv; + tv.tv_sec = timeoutSeconds; + tv.tv_usec = 0; - if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) - return 0; // (timeout) + if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) + return 0; // (timeout) - const int bytesRead = jmax (0, recv (socketHandle, buffer, bytesToRead, MSG_WAITALL)); - readPosition += bytesRead; - return bytesRead; - } + const int bytesRead = jmax (0, recv (socketHandle, buffer, bytesToRead, MSG_WAITALL)); + readPosition += bytesRead; + return bytesRead; + } - int readPosition; + int readPosition; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - int socketHandle, levelsOfRedirection; - const int timeoutSeconds; + int socketHandle, levelsOfRedirection; + const int timeoutSeconds; - void closeSocket() - { - if (socketHandle >= 0) - close (socketHandle); + void closeSocket() + { + if (socketHandle >= 0) + close (socketHandle); - socketHandle = -1; - } + socketHandle = -1; + } - const MemoryBlock createRequestHeader (const String& hostName, - const int hostPort, - const String& proxyName, - const int proxyPort, - const String& hostPath, - const String& originalURL, - const String& headers, - const MemoryBlock& postData, - const bool isPost) - { - String header (isPost ? "POST " : "GET "); + const MemoryBlock createRequestHeader (const String& hostName, + const int hostPort, + const String& proxyName, + const int proxyPort, + const String& hostPath, + const String& originalURL, + const String& headers, + const MemoryBlock& postData, + const bool isPost) + { + String header (isPost ? "POST " : "GET "); - if (proxyName.isEmpty()) - { - header << hostPath << " HTTP/1.0\r\nHost: " - << hostName << ':' << hostPort; - } - else - { - header << originalURL << " HTTP/1.0\r\nHost: " - << proxyName << ':' << proxyPort; - } + if (proxyName.isEmpty()) + { + header << hostPath << " HTTP/1.0\r\nHost: " + << hostName << ':' << hostPort; + } + else + { + header << originalURL << " HTTP/1.0\r\nHost: " + << proxyName << ':' << proxyPort; + } - header << "\r\nUser-Agent: JUCE/" - << JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION - << "\r\nConnection: Close\r\nContent-Length: " - << postData.getSize() << "\r\n" - << headers << "\r\n"; + header << "\r\nUser-Agent: JUCE/" + << JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION + << "\r\nConnection: Close\r\nContent-Length: " + << postData.getSize() << "\r\n" + << headers << "\r\n"; - MemoryBlock mb; - mb.append (header.toUTF8(), (int) strlen (header.toUTF8())); - mb.append (postData.getData(), postData.getSize()); + MemoryBlock mb; + mb.append (header.toUTF8(), (int) strlen (header.toUTF8())); + mb.append (postData.getData(), postData.getSize()); - return mb; - } + return mb; + } - const String readResponse (const uint32 timeOutTime) - { - int bytesRead = 0, numConsecutiveLFs = 0; - MemoryBlock buffer (1024, true); + const String readResponse (const uint32 timeOutTime) + { + int bytesRead = 0, numConsecutiveLFs = 0; + MemoryBlock buffer (1024, true); - while (numConsecutiveLFs < 2 && bytesRead < 32768 - && Time::getMillisecondCounter() <= timeOutTime) - { - fd_set readbits; - FD_ZERO (&readbits); - FD_SET (socketHandle, &readbits); + while (numConsecutiveLFs < 2 && bytesRead < 32768 + && Time::getMillisecondCounter() <= timeOutTime) + { + fd_set readbits; + FD_ZERO (&readbits); + FD_SET (socketHandle, &readbits); - struct timeval tv; - tv.tv_sec = timeoutSeconds; - tv.tv_usec = 0; + struct timeval tv; + tv.tv_sec = timeoutSeconds; + tv.tv_usec = 0; - if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) - return String::empty; // (timeout) + if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) + return String::empty; // (timeout) - buffer.ensureSize (bytesRead + 8, true); - char* const dest = (char*) buffer.getData() + bytesRead; + buffer.ensureSize (bytesRead + 8, true); + char* const dest = (char*) buffer.getData() + bytesRead; - if (recv (socketHandle, dest, 1, 0) == -1) - return String::empty; + if (recv (socketHandle, dest, 1, 0) == -1) + return String::empty; - const char lastByte = *dest; - ++bytesRead; + const char lastByte = *dest; + ++bytesRead; - if (lastByte == '\n') - ++numConsecutiveLFs; - else if (lastByte != '\r') - numConsecutiveLFs = 0; - } + if (lastByte == '\n') + ++numConsecutiveLFs; + else if (lastByte != '\r') + numConsecutiveLFs = 0; + } - const String header (String::fromUTF8 ((const uint8*) buffer.getData())); + const String header (String::fromUTF8 ((const uint8*) buffer.getData())); - if (header.startsWithIgnoreCase (T("HTTP/"))) - return header.trimEnd(); + if (header.startsWithIgnoreCase (T("HTTP/"))) + return header.trimEnd(); - return String::empty; - } + return String::empty; + } - static bool decomposeURL (const String& url, - String& host, String& path, int& port) - { - if (! url.startsWithIgnoreCase (T("http://"))) - return false; + static bool decomposeURL (const String& url, + String& host, String& path, int& port) + { + if (! url.startsWithIgnoreCase (T("http://"))) + return false; - const int nextSlash = url.indexOfChar (7, '/'); - int nextColon = url.indexOfChar (7, ':'); - if (nextColon > nextSlash && nextSlash > 0) - nextColon = -1; + const int nextSlash = url.indexOfChar (7, '/'); + int nextColon = url.indexOfChar (7, ':'); + if (nextColon > nextSlash && nextSlash > 0) + nextColon = -1; - if (nextColon >= 0) - { - host = url.substring (7, nextColon); + if (nextColon >= 0) + { + host = url.substring (7, nextColon); - if (nextSlash >= 0) - port = url.substring (nextColon + 1, nextSlash).getIntValue(); - else - port = url.substring (nextColon + 1).getIntValue(); - } - else - { - port = 80; + if (nextSlash >= 0) + port = url.substring (nextColon + 1, nextSlash).getIntValue(); + else + port = url.substring (nextColon + 1).getIntValue(); + } + else + { + port = 80; - if (nextSlash >= 0) - host = url.substring (7, nextSlash); - else - host = url.substring (7); - } + if (nextSlash >= 0) + host = url.substring (7, nextSlash); + else + host = url.substring (7); + } - if (nextSlash >= 0) - path = url.substring (nextSlash); - else - path = T("/"); + if (nextSlash >= 0) + path = url.substring (nextSlash); + else + path = T("/"); - return true; - } + return true; + } - static const String findHeaderItem (const StringArray& lines, const String& itemName) - { - for (int i = 0; i < lines.size(); ++i) - if (lines[i].startsWithIgnoreCase (itemName)) - return lines[i].substring (itemName.length()).trim(); + static const String findHeaderItem (const StringArray& lines, const String& itemName) + { + for (int i = 0; i < lines.size(); ++i) + if (lines[i].startsWithIgnoreCase (itemName)) + return lines[i].substring (itemName.length()).trim(); - return String::empty; - } + return String::empty; + } }; bool juce_isOnLine() { - return true; + return true; } void* juce_openInternetFile (const String& url, - const String& headers, - const MemoryBlock& postData, - const bool isPost, - URL::OpenStreamProgressCallback* callback, - void* callbackContext, - int timeOutMs) + const String& headers, + const MemoryBlock& postData, + const bool isPost, + URL::OpenStreamProgressCallback* callback, + void* callbackContext, + int timeOutMs) { - JUCE_HTTPSocketStream* const s = new JUCE_HTTPSocketStream(); + JUCE_HTTPSocketStream* const s = new JUCE_HTTPSocketStream(); - if (s->open (url, headers, postData, isPost, - callback, callbackContext, timeOutMs)) - return s; + if (s->open (url, headers, postData, isPost, + callback, callbackContext, timeOutMs)) + return s; - delete s; - return 0; + delete s; + return 0; } void juce_closeInternetFile (void* handle) { - JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; + JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; - if (s != 0) - delete s; + if (s != 0) + delete s; } int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) { - JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; + JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; - if (s != 0) - return s->read (buffer, bytesToRead); + if (s != 0) + return s->read (buffer, bytesToRead); - return 0; + return 0; } int64 juce_getInternetFileContentLength (void* handle) { - JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; + JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; - if (s != 0) - { - //xxx todo - jassertfalse - } + if (s != 0) + { + //xxx todo + jassertfalse + } - return -1; + return -1; } int juce_seekInInternetFile (void* handle, int newPosition) { - JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; + JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle; - if (s != 0) - return s->readPosition; + if (s != 0) + return s->readPosition; - return 0; + return 0; } #endif @@ -252236,195 +229945,195 @@ int juce_seekInInternetFile (void* handle, int newPosition) void Logger::outputDebugString (const String& text) throw() { - fputs (text.toUTF8(), stdout); - fputs ("\n", stdout); + fputs (text.toUTF8(), stdout); + fputs ("\n", stdout); } void Logger::outputDebugPrintf (const tchar* format, ...) throw() { - String text; - va_list args; - va_start (args, format); - text.vprintf(format, args); - outputDebugString(text); + String text; + va_list args; + va_start (args, format); + text.vprintf(format, args); + outputDebugString(text); } SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() throw() { - return Linux; + return Linux; } const String SystemStats::getOperatingSystemName() throw() { - return T("Linux"); + return T("Linux"); } bool SystemStats::isOperatingSystem64Bit() throw() { #if JUCE_64BIT - return true; + return true; #else - //xxx not sure how to find this out?.. - return false; + //xxx not sure how to find this out?.. + return false; #endif } static const String getCpuInfo (const char* key, bool lastOne = false) throw() { - String info; - char buf [256]; + String info; + char buf [256]; - FILE* f = fopen ("/proc/cpuinfo", "r"); + FILE* f = fopen ("/proc/cpuinfo", "r"); - while (f != 0 && fgets (buf, sizeof(buf), f)) - { - if (strncmp (buf, key, strlen (key)) == 0) - { - char* p = buf; + while (f != 0 && fgets (buf, sizeof(buf), f)) + { + if (strncmp (buf, key, strlen (key)) == 0) + { + char* p = buf; - while (*p && *p != '\n') - ++p; + while (*p && *p != '\n') + ++p; - if (*p != 0) - *p = 0; + if (*p != 0) + *p = 0; - p = buf; + p = buf; - while (*p != 0 && *p != ':') - ++p; + while (*p != 0 && *p != ':') + ++p; - if (*p != 0 && *(p + 1) != 0) - info = p + 2; + if (*p != 0 && *(p + 1) != 0) + info = p + 2; - if (! lastOne) - break; - } - } + if (! lastOne) + break; + } + } - fclose (f); - return info; + fclose (f); + return info; } bool SystemStats::hasMMX() throw() { - return getCpuInfo ("flags").contains (T("mmx")); + return getCpuInfo ("flags").contains (T("mmx")); } bool SystemStats::hasSSE() throw() { - return getCpuInfo ("flags").contains (T("sse")); + return getCpuInfo ("flags").contains (T("sse")); } bool SystemStats::hasSSE2() throw() { - return getCpuInfo ("flags").contains (T("sse2")); + return getCpuInfo ("flags").contains (T("sse2")); } bool SystemStats::has3DNow() throw() { - return getCpuInfo ("flags").contains (T("3dnow")); + return getCpuInfo ("flags").contains (T("3dnow")); } const String SystemStats::getCpuVendor() throw() { - return getCpuInfo ("vendor_id"); + return getCpuInfo ("vendor_id"); } int SystemStats::getCpuSpeedInMegaherz() throw() { - const String speed (getCpuInfo ("cpu MHz")); + const String speed (getCpuInfo ("cpu MHz")); - return (int) (speed.getFloatValue() + 0.5f); + return (int) (speed.getFloatValue() + 0.5f); } int SystemStats::getMemorySizeInMegabytes() throw() { - struct sysinfo sysi; + struct sysinfo sysi; - if (sysinfo (&sysi) == 0) - return (sysi.totalram * sysi.mem_unit / (1024 * 1024)); + if (sysinfo (&sysi) == 0) + return (sysi.totalram * sysi.mem_unit / (1024 * 1024)); - return 0; + return 0; } uint32 juce_millisecondsSinceStartup() throw() { - static unsigned int calibrate = 0; - static bool calibrated = false; - timeval t; - unsigned int ret = 0; + static unsigned int calibrate = 0; + static bool calibrated = false; + timeval t; + unsigned int ret = 0; - if (! gettimeofday (&t, 0)) - { - if (! calibrated) - { - struct sysinfo sysi; + if (! gettimeofday (&t, 0)) + { + if (! calibrated) + { + struct sysinfo sysi; - if (sysinfo (&sysi) == 0) - // Safe to assume system was not brought up earlier than 1970! - calibrate = t.tv_sec - sysi.uptime; + if (sysinfo (&sysi) == 0) + // Safe to assume system was not brought up earlier than 1970! + calibrate = t.tv_sec - sysi.uptime; - calibrated = true; - } + calibrated = true; + } - ret = 1000 * (t.tv_sec - calibrate) + (t.tv_usec / 1000); - } + ret = 1000 * (t.tv_sec - calibrate) + (t.tv_usec / 1000); + } - return ret; + return ret; } double Time::getMillisecondCounterHiRes() throw() { - return getHighResolutionTicks() * 0.001; + return getHighResolutionTicks() * 0.001; } int64 Time::getHighResolutionTicks() throw() { - timeval t; - if (gettimeofday (&t, 0)) - return 0; + timeval t; + if (gettimeofday (&t, 0)) + return 0; - return ((int64) t.tv_sec * (int64) 1000000) + (int64) t.tv_usec; + return ((int64) t.tv_sec * (int64) 1000000) + (int64) t.tv_usec; } int64 Time::getHighResolutionTicksPerSecond() throw() { - // Microseconds - return 1000000; + // Microseconds + return 1000000; } bool Time::setSystemTimeToThisTime() const throw() { - timeval t; - t.tv_sec = millisSinceEpoch % 1000000; - t.tv_usec = millisSinceEpoch - t.tv_sec; + timeval t; + t.tv_sec = millisSinceEpoch % 1000000; + t.tv_usec = millisSinceEpoch - t.tv_sec; - return settimeofday (&t, NULL) ? false : true; + return settimeofday (&t, NULL) ? false : true; } int SystemStats::getPageSize() throw() { - static int systemPageSize = 0; + static int systemPageSize = 0; - if (systemPageSize == 0) - systemPageSize = sysconf (_SC_PAGESIZE); + if (systemPageSize == 0) + systemPageSize = sysconf (_SC_PAGESIZE); - return systemPageSize; + return systemPageSize; } int SystemStats::getNumCpus() throw() { - const int lastCpu = getCpuInfo ("processor", true).getIntValue(); + const int lastCpu = getCpuInfo ("processor", true).getIntValue(); - return lastCpu + 1; + return lastCpu + 1; } void SystemStats::initialiseStats() throw() { - // Process starts off as root when running suid - Process::lowerPrivilege(); + // Process starts off as root when running suid + Process::lowerPrivilege(); - String s (SystemStats::getJUCEVersion()); + String s (SystemStats::getJUCEVersion()); } void PlatformUtilities::fpuReset() @@ -252439,39 +230148,34 @@ void PlatformUtilities::fpuReset() // compiled on its own). #if JUCE_INCLUDED_FILE -/* - Note that a lot of methods that you'd expect to find in this file actually - live in juce_posix_SharedCode.h! -*/ - void JUCE_API juce_threadEntryPoint (void*); void* threadEntryProc (void* value) { - // New threads start off as root when running suid - Process::lowerPrivilege(); + // New threads start off as root when running suid + Process::lowerPrivilege(); - juce_threadEntryPoint (value); - return 0; + juce_threadEntryPoint (value); + return 0; } void* juce_createThread (void* userData) { - pthread_t handle = 0; + pthread_t handle = 0; - if (pthread_create (&handle, 0, threadEntryProc, userData) == 0) - { - pthread_detach (handle); - return (void*)handle; - } + if (pthread_create (&handle, 0, threadEntryProc, userData) == 0) + { + pthread_detach (handle); + return (void*)handle; + } - return 0; + return 0; } void juce_killThread (void* handle) { - if (handle != 0) - pthread_cancel ((pthread_t)handle); + if (handle != 0) + pthread_cancel ((pthread_t)handle); } void juce_setCurrentThreadName (const String& /*name*/) @@ -252480,183 +230184,161 @@ void juce_setCurrentThreadName (const String& /*name*/) Thread::ThreadID Thread::getCurrentThreadId() { - return (ThreadID) pthread_self(); + return (ThreadID) pthread_self(); } -/* - * This is all a bit non-ideal... the trouble is that on Linux you - * need to call setpriority to affect the dynamic priority for - * non-realtime processes, but this requires the pid, which is not - * accessible from the pthread_t. We could get it by calling getpid - * once each thread has started, but then we would need a list of - * running threads etc etc. - * Also there is no such thing as IDLE priority on Linux. - * For the moment, map idle, low and normal process priorities to - * SCHED_OTHER, with the thread priority ignored for these classes. - * Map high priority processes to the lower half of the SCHED_RR - * range, and realtime to the upper half - */ - // priority 1 to 10 where 5=normal, 1=low. If the handle is 0, sets the // priority of the current thread bool juce_setThreadPriority (void* handle, int priority) { - struct sched_param param; - int policy, maxp, minp, pri; + struct sched_param param; + int policy, maxp, minp, pri; - if (handle == 0) - handle = (void*) pthread_self(); + if (handle == 0) + handle = (void*) pthread_self(); - if (pthread_getschedparam ((pthread_t) handle, &policy, ¶m) == 0 - && policy != SCHED_OTHER) - { - minp = sched_get_priority_min(policy); - maxp = sched_get_priority_max(policy); + if (pthread_getschedparam ((pthread_t) handle, &policy, ¶m) == 0 + && policy != SCHED_OTHER) + { + minp = sched_get_priority_min(policy); + maxp = sched_get_priority_max(policy); - pri = ((maxp - minp) / 2) * (priority - 1) / 9; + pri = ((maxp - minp) / 2) * (priority - 1) / 9; - if (param.__sched_priority >= (minp + (maxp - minp) / 2)) - // Realtime process priority - param.__sched_priority = minp + ((maxp - minp) / 2) + pri; - else - // High process priority - param.__sched_priority = minp + pri; + if (param.__sched_priority >= (minp + (maxp - minp) / 2)) + // Realtime process priority + param.__sched_priority = minp + ((maxp - minp) / 2) + pri; + else + // High process priority + param.__sched_priority = minp + pri; - param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11); + param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11); - return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0; - } + return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0; + } - return false; + return false; } void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) { #if SUPPORT_AFFINITIES - cpu_set_t affinity; - CPU_ZERO (&affinity); + cpu_set_t affinity; + CPU_ZERO (&affinity); - for (int i = 0; i < 32; ++i) - if ((affinityMask & (1 << i)) != 0) - CPU_SET (i, &affinity); + for (int i = 0; i < 32; ++i) + if ((affinityMask & (1 << i)) != 0) + CPU_SET (i, &affinity); - /* - N.B. If this line causes a compile error, then you've probably not got the latest - version of glibc installed. - - If you don't want to update your copy of glibc and don't care about cpu affinities, - then you can just disable all this stuff by removing the SUPPORT_AFFINITIES macro - from the linuxincludes.h file. - */ - sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinity); - sched_yield(); + sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinity); + sched_yield(); #else - /* affinities aren't supported because either the appropriate header files weren't found, - or the SUPPORT_AFFINITIES macro was turned off in linuxheaders.h - */ - jassertfalse + /* affinities aren't supported because either the appropriate header files weren't found, + or the SUPPORT_AFFINITIES macro was turned off in linuxheaders.h + */ + jassertfalse #endif } void Thread::yield() { - sched_yield(); + sched_yield(); } // sets the process to 0=low priority, 1=normal, 2=high, 3=realtime void Process::setPriority (ProcessPriority prior) { - struct sched_param param; - int policy, maxp, minp; + struct sched_param param; + int policy, maxp, minp; - const int p = (int) prior; + const int p = (int) prior; - if (p <= 1) - policy = SCHED_OTHER; - else - policy = SCHED_RR; + if (p <= 1) + policy = SCHED_OTHER; + else + policy = SCHED_RR; - minp = sched_get_priority_min (policy); - maxp = sched_get_priority_max (policy); + minp = sched_get_priority_min (policy); + maxp = sched_get_priority_max (policy); - if (p < 2) - param.__sched_priority = 0; - else if (p == 2 ) - // Set to middle of lower realtime priority range - param.__sched_priority = minp + (maxp - minp) / 4; - else - // Set to middle of higher realtime priority range - param.__sched_priority = minp + (3 * (maxp - minp) / 4); + if (p < 2) + param.__sched_priority = 0; + else if (p == 2 ) + // Set to middle of lower realtime priority range + param.__sched_priority = minp + (maxp - minp) / 4; + else + // Set to middle of higher realtime priority range + param.__sched_priority = minp + (3 * (maxp - minp) / 4); - pthread_setschedparam (pthread_self(), policy, ¶m); + pthread_setschedparam (pthread_self(), policy, ¶m); } void Process::terminate() { - exit (0); + exit (0); } bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger() { - static char testResult = 0; + static char testResult = 0; - if (testResult == 0) - { - testResult = (char) ptrace (PT_TRACE_ME, 0, 0, 0); + if (testResult == 0) + { + testResult = (char) ptrace (PT_TRACE_ME, 0, 0, 0); - if (testResult >= 0) - { - ptrace (PT_DETACH, 0, (caddr_t) 1, 0); - testResult = 1; - } - } + if (testResult >= 0) + { + ptrace (PT_DETACH, 0, (caddr_t) 1, 0); + testResult = 1; + } + } - return testResult < 0; + return testResult < 0; } bool JUCE_CALLTYPE Process::isRunningUnderDebugger() { - return juce_isRunningUnderDebugger(); + return juce_isRunningUnderDebugger(); } void Process::raisePrivilege() { - // If running suid root, change effective user - // to root - if (geteuid() != 0 && getuid() == 0) - { - setreuid (geteuid(), getuid()); - setregid (getegid(), getgid()); - } + // If running suid root, change effective user + // to root + if (geteuid() != 0 && getuid() == 0) + { + setreuid (geteuid(), getuid()); + setregid (getegid(), getgid()); + } } void Process::lowerPrivilege() { - // If runing suid root, change effective user - // back to real user - if (geteuid() == 0 && getuid() != 0) - { - setreuid (geteuid(), getuid()); - setregid (getegid(), getgid()); - } + // If runing suid root, change effective user + // back to real user + if (geteuid() == 0 && getuid() != 0) + { + setreuid (geteuid(), getuid()); + setregid (getegid(), getgid()); + } } #if ! JUCE_ONLY_BUILD_CORE_LIBRARY void* PlatformUtilities::loadDynamicLibrary (const String& name) { - return dlopen ((const char*) name.toUTF8(), RTLD_LOCAL | RTLD_NOW); + return dlopen ((const char*) name.toUTF8(), RTLD_LOCAL | RTLD_NOW); } void PlatformUtilities::freeDynamicLibrary (void* handle) { - dlclose(handle); + dlclose(handle); } void* PlatformUtilities::getProcedureEntryPoint (void* libraryHandle, const String& procedureName) { - return dlsym (libraryHandle, (const char*) procedureName); + return dlsym (libraryHandle, (const char*) procedureName); } #endif @@ -252685,220 +230367,211 @@ static Atom atom_TARGETS; static void initSelectionAtoms() { - static bool isInitialised = false; - if (! isInitialised) - { - atom_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False); - atom_CLIPBOARD = XInternAtom (display, "CLIPBOARD", False); - atom_TARGETS = XInternAtom (display, "TARGETS", False); - } + static bool isInitialised = false; + if (! isInitialised) + { + atom_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False); + atom_CLIPBOARD = XInternAtom (display, "CLIPBOARD", False); + atom_TARGETS = XInternAtom (display, "TARGETS", False); + } } // Read the content of a window property as either a locale-dependent string or an utf8 string // works only for strings shorter than 1000000 bytes static String juce_readWindowProperty (Window window, Atom prop, - Atom fmt, // XA_STRING or UTF8_STRING - bool deleteAfterReading) + Atom fmt, // XA_STRING or UTF8_STRING + bool deleteAfterReading) { - String returnData; - uint8 *clipData; - Atom actualType; - int actualFormat; - unsigned long numItems, bytesLeft; + String returnData; + uint8 *clipData; + Atom actualType; + int actualFormat; + unsigned long numItems, bytesLeft; - if (XGetWindowProperty (display, window, prop, - 0L /* offset */, 1000000 /* length (max) */, False, - AnyPropertyType /* format */, - &actualType, &actualFormat, &numItems, &bytesLeft, - &clipData) == Success) - { - if (actualType == atom_UTF8_STRING && actualFormat == 8) - { - returnData = String::fromUTF8 (clipData, numItems); - } - else if (actualType == XA_STRING && actualFormat == 8) - { - returnData = String ((const char*) clipData, numItems); - } + if (XGetWindowProperty (display, window, prop, + 0L /* offset */, 1000000 /* length (max) */, False, + AnyPropertyType /* format */, + &actualType, &actualFormat, &numItems, &bytesLeft, + &clipData) == Success) + { + if (actualType == atom_UTF8_STRING && actualFormat == 8) + { + returnData = String::fromUTF8 (clipData, numItems); + } + else if (actualType == XA_STRING && actualFormat == 8) + { + returnData = String ((const char*) clipData, numItems); + } - if (clipData != 0) - XFree (clipData); + if (clipData != 0) + XFree (clipData); - jassert (bytesLeft == 0 || numItems == 1000000); - } + jassert (bytesLeft == 0 || numItems == 1000000); + } - if (deleteAfterReading) - XDeleteProperty (display, window, prop); + if (deleteAfterReading) + XDeleteProperty (display, window, prop); - return returnData; + return returnData; } // Send a SelectionRequest to the window owning the selection and waits for its answer (with a timeout) */ static bool juce_requestSelectionContent (String &selection_content, Atom selection, Atom requested_format) { - Atom property_name = XInternAtom (display, "JUCE_SEL", false); + Atom property_name = XInternAtom (display, "JUCE_SEL", false); - // The selection owner will be asked to set the JUCE_SEL property on the - // juce_messageWindowHandle with the selection content - XConvertSelection (display, selection, requested_format, property_name, - juce_messageWindowHandle, CurrentTime); + // The selection owner will be asked to set the JUCE_SEL property on the + // juce_messageWindowHandle with the selection content + XConvertSelection (display, selection, requested_format, property_name, + juce_messageWindowHandle, CurrentTime); - int timeoutMs = 200; // will wait at most for 200 ms + int timeoutMs = 200; // will wait at most for 200 ms - do - { - XEvent event; + do + { + XEvent event; - if (XCheckTypedWindowEvent (display, juce_messageWindowHandle, SelectionNotify, &event)) - { - if (event.xselection.property == property_name) - { - jassert (event.xselection.requestor == juce_messageWindowHandle); + if (XCheckTypedWindowEvent (display, juce_messageWindowHandle, SelectionNotify, &event)) + { + if (event.xselection.property == property_name) + { + jassert (event.xselection.requestor == juce_messageWindowHandle); - selection_content = juce_readWindowProperty (event.xselection.requestor, - event.xselection.property, - requested_format, true); - return true; - } - else - { - return false; // the format we asked for was denied.. (event.xselection.property == None) - } - } + selection_content = juce_readWindowProperty (event.xselection.requestor, + event.xselection.property, + requested_format, true); + return true; + } + else + { + return false; // the format we asked for was denied.. (event.xselection.property == None) + } + } - // not very elegant.. we could do a select() or something like that... - // however clipboard content requesting is inherently slow on x11, it - // often takes 50ms or more so... - Thread::sleep (4); - timeoutMs -= 4; - } - while (timeoutMs > 0); + // not very elegant.. we could do a select() or something like that... + // however clipboard content requesting is inherently slow on x11, it + // often takes 50ms or more so... + Thread::sleep (4); + timeoutMs -= 4; + } + while (timeoutMs > 0); - DBG("timeout for juce_requestSelectionContent"); - return false; + DBG("timeout for juce_requestSelectionContent"); + return false; } // Called from the event loop in juce_linux_Messaging in response to SelectionRequest events void juce_handleSelectionRequest (XSelectionRequestEvent &evt) { - initSelectionAtoms(); + initSelectionAtoms(); - // the selection content is sent to the target window as a window property - XSelectionEvent reply; - reply.type = SelectionNotify; - reply.display = evt.display; - reply.requestor = evt.requestor; - reply.selection = evt.selection; - reply.target = evt.target; - reply.property = None; // == "fail" - reply.time = evt.time; + // the selection content is sent to the target window as a window property + XSelectionEvent reply; + reply.type = SelectionNotify; + reply.display = evt.display; + reply.requestor = evt.requestor; + reply.selection = evt.selection; + reply.target = evt.target; + reply.property = None; // == "fail" + reply.time = evt.time; - HeapBlock data; - int propertyFormat = 0, numDataItems = 0; + HeapBlock data; + int propertyFormat = 0, numDataItems = 0; - if (evt.selection == XA_PRIMARY || evt.selection == atom_CLIPBOARD) - { - if (evt.target == XA_STRING) - { - // format data according to system locale - numDataItems = localClipboardContent.length(); - data.calloc (numDataItems + 2); - localClipboardContent.copyToBuffer ((char*) data, numDataItems + 1); - propertyFormat = 8; // bits/item - } - else if (evt.target == atom_UTF8_STRING) - { - // translate to utf8 - numDataItems = localClipboardContent.copyToUTF8 (0); - data.calloc (numDataItems + 2); - localClipboardContent.copyToUTF8 (data, numDataItems + 1); - propertyFormat = 8; // bits/item - } - else if (evt.target == atom_TARGETS) - { - // another application wants to know what we are able to send - numDataItems = 2; - propertyFormat = 32; // atoms are 32-bit - data.calloc (numDataItems * 4); - ((Atom*) data)[0] = atom_UTF8_STRING; - ((Atom*) data)[1] = XA_STRING; - } - } - else - { - DBG ("requested unsupported clipboard"); - } + if (evt.selection == XA_PRIMARY || evt.selection == atom_CLIPBOARD) + { + if (evt.target == XA_STRING) + { + // format data according to system locale + numDataItems = localClipboardContent.length(); + data.calloc (numDataItems + 2); + localClipboardContent.copyToBuffer ((char*) data, numDataItems + 1); + propertyFormat = 8; // bits/item + } + else if (evt.target == atom_UTF8_STRING) + { + // translate to utf8 + numDataItems = localClipboardContent.copyToUTF8 (0); + data.calloc (numDataItems + 2); + localClipboardContent.copyToUTF8 (data, numDataItems + 1); + propertyFormat = 8; // bits/item + } + else if (evt.target == atom_TARGETS) + { + // another application wants to know what we are able to send + numDataItems = 2; + propertyFormat = 32; // atoms are 32-bit + data.calloc (numDataItems * 4); + ((Atom*) data)[0] = atom_UTF8_STRING; + ((Atom*) data)[1] = XA_STRING; + } + } + else + { + DBG ("requested unsupported clipboard"); + } - if (data != 0) - { - const int maxReasonableSelectionSize = 1000000; + if (data != 0) + { + const int maxReasonableSelectionSize = 1000000; - // for very big chunks of data, we should use the "INCR" protocol , which is a pain in the *ss - if (evt.property != None && numDataItems < maxReasonableSelectionSize) - { - XChangeProperty (evt.display, evt.requestor, - evt.property, evt.target, - propertyFormat /* 8 or 32 */, PropModeReplace, - (const unsigned char*) data, numDataItems); - reply.property = evt.property; // " == success" - } - } + // for very big chunks of data, we should use the "INCR" protocol , which is a pain in the *ss + if (evt.property != None && numDataItems < maxReasonableSelectionSize) + { + XChangeProperty (evt.display, evt.requestor, + evt.property, evt.target, + propertyFormat /* 8 or 32 */, PropModeReplace, + (const unsigned char*) data, numDataItems); + reply.property = evt.property; // " == success" + } + } - XSendEvent (evt.display, evt.requestor, 0, NoEventMask, (XEvent*) &reply); + XSendEvent (evt.display, evt.requestor, 0, NoEventMask, (XEvent*) &reply); } void SystemClipboard::copyTextToClipboard (const String& clipText) throw() { - initSelectionAtoms(); - localClipboardContent = clipText; + initSelectionAtoms(); + localClipboardContent = clipText; - XSetSelectionOwner (display, XA_PRIMARY, juce_messageWindowHandle, CurrentTime); - XSetSelectionOwner (display, atom_CLIPBOARD, juce_messageWindowHandle, CurrentTime); + XSetSelectionOwner (display, XA_PRIMARY, juce_messageWindowHandle, CurrentTime); + XSetSelectionOwner (display, atom_CLIPBOARD, juce_messageWindowHandle, CurrentTime); } const String SystemClipboard::getTextFromClipboard() throw() { - initSelectionAtoms(); + initSelectionAtoms(); - /* 1) try to read from the "CLIPBOARD" selection first (the "high - level" clipboard that is supposed to be filled by ctrl-C - etc). When a clipboard manager is running, the content of this - selection is preserved even when the original selection owner - exits. + String content; + Atom selection = XA_PRIMARY; + Window selectionOwner = None; - 2) and then try to read from "PRIMARY" selection (the "legacy" selection - filled by good old x11 apps such as xterm) - */ - String content; - Atom selection = XA_PRIMARY; - Window selectionOwner = None; + if ((selectionOwner = XGetSelectionOwner (display, selection)) == None) + { + selection = atom_CLIPBOARD; + selectionOwner = XGetSelectionOwner (display, selection); + } - if ((selectionOwner = XGetSelectionOwner (display, selection)) == None) - { - selection = atom_CLIPBOARD; - selectionOwner = XGetSelectionOwner (display, selection); - } + if (selectionOwner != None) + { + if (selectionOwner == juce_messageWindowHandle) + { + content = localClipboardContent; + } + else + { + // first try: we want an utf8 string + bool ok = juce_requestSelectionContent (content, selection, atom_UTF8_STRING); - if (selectionOwner != None) - { - if (selectionOwner == juce_messageWindowHandle) - { - content = localClipboardContent; - } - else - { - // first try: we want an utf8 string - bool ok = juce_requestSelectionContent (content, selection, atom_UTF8_STRING); + if (! ok) + { + // second chance, ask for a good old locale-dependent string .. + ok = juce_requestSelectionContent (content, selection, XA_STRING); + } + } + } - if (! ok) - { - // second chance, ask for a good old locale-dependent string .. - ok = juce_requestSelectionContent (content, selection, XA_STRING); - } - } - } - - return content; + return content; } #endif @@ -252913,7 +230586,7 @@ const String SystemClipboard::getTextFromClipboard() throw() #define JUCE_DEBUG_XERRORS 1 #endif -Display* display = 0; // This is also referenced from WindowDriver.cpp +Display* display = 0; // This is also referenced from WindowDriver.cpp Window juce_messageWindowHandle = None; #define SpecialAtom "JUCESpecialAtom" @@ -252936,67 +230609,67 @@ extern void juce_handleSelectionRequest (XSelectionRequestEvent &evt); class InternalMessageQueue { public: - InternalMessageQueue() - { - int ret = ::socketpair (AF_LOCAL, SOCK_STREAM, 0, fd); - (void) ret; jassert (ret == 0); - } + InternalMessageQueue() + { + int ret = ::socketpair (AF_LOCAL, SOCK_STREAM, 0, fd); + (void) ret; jassert (ret == 0); + } - ~InternalMessageQueue() - { - close (fd[0]); - close (fd[1]); - } + ~InternalMessageQueue() + { + close (fd[0]); + close (fd[1]); + } - void postMessage (Message* msg) - { - ScopedLock sl (lock); - queue.add (msg); + void postMessage (Message* msg) + { + ScopedLock sl (lock); + queue.add (msg); - const unsigned char x = 0xff; - write (fd[0], &x, 1); - } + const unsigned char x = 0xff; + write (fd[0], &x, 1); + } - bool isEmpty() const - { - ScopedLock sl (lock); - return queue.size() == 0; - } + bool isEmpty() const + { + ScopedLock sl (lock); + return queue.size() == 0; + } - Message* popMessage() - { - Message* m = 0; - ScopedLock sl (lock); + Message* popMessage() + { + Message* m = 0; + ScopedLock sl (lock); - if (queue.size() != 0) - { - unsigned char x; - read (fd[1], &x, 1); + if (queue.size() != 0) + { + unsigned char x; + read (fd[1], &x, 1); - m = queue.getUnchecked(0); - queue.remove (0, false /* deleteObject */); - } + m = queue.getUnchecked(0); + queue.remove (0, false /* deleteObject */); + } - return m; - } + return m; + } - int getWaitHandle() const { return fd[1]; } + int getWaitHandle() const { return fd[1]; } private: - CriticalSection lock; - OwnedArray queue; - int fd[2]; + CriticalSection lock; + OwnedArray queue; + int fd[2]; }; struct MessageThreadFuncCall { - enum { uniqueID = 0x73774623 }; + enum { uniqueID = 0x73774623 }; - MessageCallbackFunction* func; - void* parameter; - void* result; - CriticalSection lock; - WaitableEvent event; + MessageCallbackFunction* func; + void* parameter; + void* result; + CriticalSection lock; + WaitableEvent event; }; static InternalMessageQueue* juce_internalMessageQueue = 0; @@ -253010,356 +230683,332 @@ static XIOErrorHandler oldIOErrorHandler = (XIOErrorHandler) 0; // Usually happens when client-server connection is broken static int ioErrorHandler (Display* display) { - DBG (T("ERROR: connection to X server broken.. terminating.")); + DBG (T("ERROR: connection to X server broken.. terminating.")); - errorOccurred = true; + errorOccurred = true; - if (JUCEApplication::getInstance() != 0) - Process::terminate(); + if (JUCEApplication::getInstance() != 0) + Process::terminate(); - return 0; + return 0; } // A protocol error has occurred static int errorHandler (Display* display, XErrorEvent* event) { #ifdef JUCE_DEBUG_XERRORS - char errorStr[64] = { 0 }; - char requestStr[64] = { 0 }; + char errorStr[64] = { 0 }; + char requestStr[64] = { 0 }; - XGetErrorText (display, event->error_code, errorStr, 64); + XGetErrorText (display, event->error_code, errorStr, 64); - XGetErrorDatabaseText (display, - "XRequest", - (const char*) String (event->request_code), - "Unknown", - requestStr, - 64); + XGetErrorDatabaseText (display, + "XRequest", + (const char*) String (event->request_code), + "Unknown", + requestStr, + 64); - DBG (T("ERROR: X returned ") + String (errorStr) + T(" for operation ") + String (requestStr)); + DBG (T("ERROR: X returned ") + String (errorStr) + T(" for operation ") + String (requestStr)); #endif - return 0; + return 0; } // Breakin from keyboard static void signalHandler (int sig) { - if (sig == SIGINT) - { - keyboardBreakOccurred = true; - return; - } + if (sig == SIGINT) + { + keyboardBreakOccurred = true; + return; + } - static bool reentrant = false; + static bool reentrant = false; - if (! reentrant) - { - reentrant = true; + if (! reentrant) + { + reentrant = true; - // Illegal instruction - fflush (stdout); - Logger::outputDebugString ("ERROR: Program executed illegal instruction.. terminating"); + // Illegal instruction + fflush (stdout); + Logger::outputDebugString ("ERROR: Program executed illegal instruction.. terminating"); - errorOccurred = true; + errorOccurred = true; - if (JUCEApplication::getInstance() != 0) - Process::terminate(); - } - else - { - if (JUCEApplication::getInstance() != 0) - exit(0); - } + if (JUCEApplication::getInstance() != 0) + Process::terminate(); + } + else + { + if (JUCEApplication::getInstance() != 0) + exit(0); + } } void MessageManager::doPlatformSpecificInitialisation() { - // Initialise xlib for multiple thread support - static bool initThreadCalled = false; + // Initialise xlib for multiple thread support + static bool initThreadCalled = false; - if (! initThreadCalled) - { - if (! XInitThreads()) - { - // This is fatal! Print error and closedown - Logger::outputDebugString ("Failed to initialise xlib thread support."); + if (! initThreadCalled) + { + if (! XInitThreads()) + { + // This is fatal! Print error and closedown + Logger::outputDebugString ("Failed to initialise xlib thread support."); - if (JUCEApplication::getInstance() != 0) - Process::terminate(); + if (JUCEApplication::getInstance() != 0) + Process::terminate(); - return; - } + return; + } - initThreadCalled = true; - } + initThreadCalled = true; + } - // This is called if the client/server connection is broken - oldIOErrorHandler = XSetIOErrorHandler (ioErrorHandler); + // This is called if the client/server connection is broken + oldIOErrorHandler = XSetIOErrorHandler (ioErrorHandler); - // This is called if a protocol error occurs - oldErrorHandler = XSetErrorHandler (errorHandler); + // This is called if a protocol error occurs + oldErrorHandler = XSetErrorHandler (errorHandler); - // Install signal handler for break-in - struct sigaction saction; - sigset_t maskSet; - sigemptyset (&maskSet); - saction.sa_handler = signalHandler; - saction.sa_mask = maskSet; - saction.sa_flags = 0; - sigaction (SIGINT, &saction, NULL); + // Install signal handler for break-in + struct sigaction saction; + sigset_t maskSet; + sigemptyset (&maskSet); + saction.sa_handler = signalHandler; + saction.sa_mask = maskSet; + saction.sa_flags = 0; + sigaction (SIGINT, &saction, NULL); #ifndef _DEBUG - // Setup signal handlers for various fatal errors - sigaction (SIGILL, &saction, NULL); - sigaction (SIGBUS, &saction, NULL); - sigaction (SIGFPE, &saction, NULL); - sigaction (SIGSEGV, &saction, NULL); - sigaction (SIGSYS, &saction, NULL); + // Setup signal handlers for various fatal errors + sigaction (SIGILL, &saction, NULL); + sigaction (SIGBUS, &saction, NULL); + sigaction (SIGFPE, &saction, NULL); + sigaction (SIGSEGV, &saction, NULL); + sigaction (SIGSYS, &saction, NULL); #endif - // Create the internal message queue - juce_internalMessageQueue = new InternalMessageQueue(); + // Create the internal message queue + juce_internalMessageQueue = new InternalMessageQueue(); - // Try to connect to a display - String displayName (getenv ("DISPLAY")); - if (displayName.isEmpty()) - displayName = T(":0.0"); + // Try to connect to a display + String displayName (getenv ("DISPLAY")); + if (displayName.isEmpty()) + displayName = T(":0.0"); - display = XOpenDisplay (displayName); + display = XOpenDisplay (displayName); - if (display == 0) - { - // This is not fatal! we can run headless. - return; - } + if (display == 0) + { + // This is not fatal! we can run headless. + return; + } - // Get defaults for various properties - int screen = DefaultScreen (display); - Window root = RootWindow (display, screen); - Visual* visual = DefaultVisual (display, screen); + // Get defaults for various properties + int screen = DefaultScreen (display); + Window root = RootWindow (display, screen); + Visual* visual = DefaultVisual (display, screen); - // Create atoms for our ClientMessages (these cannot be deleted) - specialId = XInternAtom (display, SpecialAtom, false); - broadcastId = XInternAtom (display, BroadcastAtom, false); - specialCallbackId = XInternAtom (display, SpecialCallbackAtom, false); + // Create atoms for our ClientMessages (these cannot be deleted) + specialId = XInternAtom (display, SpecialAtom, false); + broadcastId = XInternAtom (display, BroadcastAtom, false); + specialCallbackId = XInternAtom (display, SpecialCallbackAtom, false); - // Create a context to store user data associated with Windows we - // create in WindowDriver - improbableNumber = XUniqueContext(); + // Create a context to store user data associated with Windows we + // create in WindowDriver + improbableNumber = XUniqueContext(); - // We're only interested in client messages for this window - // which are always sent - XSetWindowAttributes swa; - swa.event_mask = NoEventMask; + // We're only interested in client messages for this window + // which are always sent + XSetWindowAttributes swa; + swa.event_mask = NoEventMask; - // Create our message window (this will never be mapped) - juce_messageWindowHandle = XCreateWindow (display, root, - 0, 0, 1, 1, 0, 0, InputOnly, - visual, CWEventMask, &swa); + // Create our message window (this will never be mapped) + juce_messageWindowHandle = XCreateWindow (display, root, + 0, 0, 1, 1, 0, 0, InputOnly, + visual, CWEventMask, &swa); } void MessageManager::doPlatformSpecificShutdown() { - deleteAndZero (juce_internalMessageQueue); + deleteAndZero (juce_internalMessageQueue); - if (display != 0 && ! errorOccurred) - { - XDestroyWindow (display, juce_messageWindowHandle); - XCloseDisplay (display); + if (display != 0 && ! errorOccurred) + { + XDestroyWindow (display, juce_messageWindowHandle); + XCloseDisplay (display); - // reset pointers - juce_messageWindowHandle = 0; - display = 0; + // reset pointers + juce_messageWindowHandle = 0; + display = 0; - // Restore original error handlers - XSetIOErrorHandler (oldIOErrorHandler); - oldIOErrorHandler = 0; - XSetErrorHandler (oldErrorHandler); - oldErrorHandler = 0; - } + // Restore original error handlers + XSetIOErrorHandler (oldIOErrorHandler); + oldIOErrorHandler = 0; + XSetErrorHandler (oldErrorHandler); + oldErrorHandler = 0; + } } bool juce_postMessageToSystemQueue (void* message) { - if (errorOccurred) - return false; + if (errorOccurred) + return false; - juce_internalMessageQueue->postMessage ((Message*) message); - return true; + juce_internalMessageQueue->postMessage ((Message*) message); + return true; } -/*bool juce_postMessageToX11Queue (void *message) -{ - XClientMessageEvent clientMsg; - clientMsg.display = display; - clientMsg.window = juce_messageWindowHandle; - clientMsg.type = ClientMessage; - clientMsg.format = 32; - clientMsg.message_type = specialId; -#if JUCE_64BIT - clientMsg.data.l[0] = (long) (0x00000000ffffffff & (((uint64) message) >> 32)); - clientMsg.data.l[1] = (long) (0x00000000ffffffff & (long) message); -#else - clientMsg.data.l[0] = (long) message; -#endif - - XSendEvent (display, juce_messageWindowHandle, false, - NoEventMask, (XEvent*) &clientMsg); - - XFlush (display); // This is necessary to ensure the event is delivered - - return true; -}*/ - void MessageManager::broadcastMessage (const String& value) throw() { - /* TODO */ } void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* func, - void* parameter) + void* parameter) { - if (errorOccurred) - return 0; + if (errorOccurred) + return 0; - if (! isThisTheMessageThread()) - { - MessageThreadFuncCall messageCallContext; - messageCallContext.func = func; - messageCallContext.parameter = parameter; + if (! isThisTheMessageThread()) + { + MessageThreadFuncCall messageCallContext; + messageCallContext.func = func; + messageCallContext.parameter = parameter; - juce_internalMessageQueue->postMessage (new Message (MessageThreadFuncCall::uniqueID, - 0, 0, &messageCallContext)); + juce_internalMessageQueue->postMessage (new Message (MessageThreadFuncCall::uniqueID, + 0, 0, &messageCallContext)); - // Wait for it to complete before continuing - messageCallContext.event.wait(); + // Wait for it to complete before continuing + messageCallContext.event.wait(); - return messageCallContext.result; - } - else - { - // Just call the function directly - return func (parameter); - } + return messageCallContext.result; + } + else + { + // Just call the function directly + return func (parameter); + } } // Wait for an event (either XEvent, or an internal Message) static bool juce_sleepUntilEvent (const int timeoutMs) { - if ((display != 0 && XPending (display)) || ! juce_internalMessageQueue->isEmpty()) - return true; + if ((display != 0 && XPending (display)) || ! juce_internalMessageQueue->isEmpty()) + return true; - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = timeoutMs * 1000; - int fd0 = juce_internalMessageQueue->getWaitHandle(); - int fdmax = fd0; + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = timeoutMs * 1000; + int fd0 = juce_internalMessageQueue->getWaitHandle(); + int fdmax = fd0; - fd_set readset; - FD_ZERO (&readset); - FD_SET (fd0, &readset); + fd_set readset; + FD_ZERO (&readset); + FD_SET (fd0, &readset); - if (display != 0) - { - int fd1 = XConnectionNumber (display); - FD_SET (fd1, &readset); - fdmax = jmax (fd0, fd1); - } + if (display != 0) + { + int fd1 = XConnectionNumber (display); + FD_SET (fd1, &readset); + fdmax = jmax (fd0, fd1); + } - int ret = select (fdmax + 1, &readset, 0, 0, &tv); - return (ret > 0); // ret <= 0 if error or timeout + int ret = select (fdmax + 1, &readset, 0, 0, &tv); + return (ret > 0); // ret <= 0 if error or timeout } // Handle next XEvent (if any) static bool juce_dispatchNextXEvent() { - if (display == 0 || ! XPending (display)) - return false; + if (display == 0 || ! XPending (display)) + return false; - XEvent evt; - XNextEvent (display, &evt); + XEvent evt; + XNextEvent (display, &evt); - if (evt.type == SelectionRequest && evt.xany.window == juce_messageWindowHandle) - { - juce_handleSelectionRequest (evt.xselectionrequest); - } - else if (evt.xany.window != juce_messageWindowHandle) - { - juce_windowMessageReceive (&evt); - } + if (evt.type == SelectionRequest && evt.xany.window == juce_messageWindowHandle) + { + juce_handleSelectionRequest (evt.xselectionrequest); + } + else if (evt.xany.window != juce_messageWindowHandle) + { + juce_windowMessageReceive (&evt); + } - return true; + return true; } // Handle next internal Message (if any) static bool juce_dispatchNextInternalMessage() { - if (juce_internalMessageQueue->isEmpty()) - return false; + if (juce_internalMessageQueue->isEmpty()) + return false; - ScopedPointer msg (juce_internalMessageQueue->popMessage()); + ScopedPointer msg (juce_internalMessageQueue->popMessage()); - if (msg->intParameter1 == MessageThreadFuncCall::uniqueID) - { - // Handle callback message - MessageThreadFuncCall* const call = (MessageThreadFuncCall*) msg->pointerParameter; + if (msg->intParameter1 == MessageThreadFuncCall::uniqueID) + { + // Handle callback message + MessageThreadFuncCall* const call = (MessageThreadFuncCall*) msg->pointerParameter; - call->result = (*(call->func)) (call->parameter); - call->event.signal(); - } - else - { - // Handle "normal" messages - MessageManager::getInstance()->deliverMessage (msg.release()); - } + call->result = (*(call->func)) (call->parameter); + call->event.signal(); + } + else + { + // Handle "normal" messages + MessageManager::getInstance()->deliverMessage (msg.release()); + } - return true; + return true; } // this function expects that it will NEVER be called simultaneously for two concurrent threads bool juce_dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages) { - for (;;) - { - if (errorOccurred) - break; + for (;;) + { + if (errorOccurred) + break; - if (keyboardBreakOccurred) - { - errorOccurred = true; + if (keyboardBreakOccurred) + { + errorOccurred = true; - if (JUCEApplication::getInstance() != 0) - Process::terminate(); + if (JUCEApplication::getInstance() != 0) + Process::terminate(); - break; - } + break; + } - static int totalEventCount = 0; - ++totalEventCount; + static int totalEventCount = 0; + ++totalEventCount; - // The purpose here is to give either priority to XEvents or - // to internal messages This is necessary to keep a "good" - // behaviour when the cpu is overloaded - if (totalEventCount & 1) - { - if (juce_dispatchNextXEvent() || juce_dispatchNextInternalMessage()) - return true; - } - else - { - if (juce_dispatchNextInternalMessage() || juce_dispatchNextXEvent()) - return true; - } + // The purpose here is to give either priority to XEvents or + // to internal messages This is necessary to keep a "good" + // behaviour when the cpu is overloaded + if (totalEventCount & 1) + { + if (juce_dispatchNextXEvent() || juce_dispatchNextInternalMessage()) + return true; + } + else + { + if (juce_dispatchNextInternalMessage() || juce_dispatchNextXEvent()) + return true; + } - if (returnIfNoPendingMessages) // early exit - break; + if (returnIfNoPendingMessages) // early exit + break; - // the timeout is to be on the safe side, but it does not seem to be useful - juce_sleepUntilEvent (2000); - } + // the timeout is to be on the safe side, but it does not seem to be useful + juce_sleepUntilEvent (2000); + } - return false; + return false; } #endif @@ -253374,439 +231023,439 @@ class FreeTypeFontFace { public: - enum FontStyle - { - Plain = 0, - Bold = 1, - Italic = 2 - }; + enum FontStyle + { + Plain = 0, + Bold = 1, + Italic = 2 + }; - struct FontNameIndex - { - String fileName; - int faceIndex; - }; + struct FontNameIndex + { + String fileName; + int faceIndex; + }; - FreeTypeFontFace (const String& familyName) throw() - : hasSerif (false), - monospaced (false) - { - family = familyName; - } + FreeTypeFontFace (const String& familyName) throw() + : hasSerif (false), + monospaced (false) + { + family = familyName; + } - void setFileName (const String& name, const int faceIndex, FontStyle style) throw() - { - if (names [(int) style].fileName.isEmpty()) - { - names [(int) style].fileName = name; - names [(int) style].faceIndex = faceIndex; - } - } + void setFileName (const String& name, const int faceIndex, FontStyle style) throw() + { + if (names [(int) style].fileName.isEmpty()) + { + names [(int) style].fileName = name; + names [(int) style].faceIndex = faceIndex; + } + } - const String& getFamilyName() const throw() { return family; } + const String& getFamilyName() const throw() { return family; } - const String& getFileName (const int style, int& faceIndex) const throw() - { - faceIndex = names[style].faceIndex; - return names[style].fileName; - } + const String& getFileName (const int style, int& faceIndex) const throw() + { + faceIndex = names[style].faceIndex; + return names[style].fileName; + } - void setMonospaced (bool mono) throw() { monospaced = mono; } - bool getMonospaced() const throw() { return monospaced; } + void setMonospaced (bool mono) throw() { monospaced = mono; } + bool getMonospaced() const throw() { return monospaced; } - void setSerif (const bool serif) throw() { hasSerif = serif; } - bool getSerif() const throw() { return hasSerif; } + void setSerif (const bool serif) throw() { hasSerif = serif; } + bool getSerif() const throw() { return hasSerif; } private: - String family; - FontNameIndex names[4]; - bool hasSerif, monospaced; + String family; + FontNameIndex names[4]; + bool hasSerif, monospaced; }; class FreeTypeInterface : public DeletedAtShutdown { public: - FreeTypeInterface() throw() - : lastFace (0), - lastBold (false), - lastItalic (false) - { - if (FT_Init_FreeType (&ftLib) != 0) - { - ftLib = 0; - DBG (T("Failed to initialize FreeType")); - } - - StringArray fontDirs; - fontDirs.addTokens (String (getenv ("JUCE_FONT_PATH")), T(";,"), 0); - fontDirs.removeEmptyStrings (true); - - if (fontDirs.size() == 0) - { - XmlDocument fontsConfig (File ("/etc/fonts/fonts.conf")); - XmlElement* const fontsInfo = fontsConfig.getDocumentElement(); - - if (fontsInfo != 0) - { - forEachXmlChildElementWithTagName (*fontsInfo, e, T("dir")) - { - fontDirs.add (e->getAllSubText().trim()); - } - - delete fontsInfo; - } - } - - if (fontDirs.size() == 0) - fontDirs.add ("/usr/X11R6/lib/X11/fonts"); - - for (int i = 0; i < fontDirs.size(); ++i) - enumerateFaces (fontDirs[i]); - } - - ~FreeTypeInterface() throw() - { - if (lastFace != 0) - FT_Done_Face (lastFace); - - if (ftLib != 0) - FT_Done_FreeType (ftLib); - - clearSingletonInstance(); - } - - FreeTypeFontFace* findOrCreate (const String& familyName, - const bool create = false) throw() - { - for (int i = 0; i < faces.size(); i++) - if (faces[i]->getFamilyName() == familyName) - return faces[i]; - - if (! create) - return NULL; - - FreeTypeFontFace* newFace = new FreeTypeFontFace (familyName); - faces.add (newFace); - - return newFace; - } - - // Enumerate all font faces available in a given directory - void enumerateFaces (const String& path) throw() - { - File dirPath (path); - if (path.isEmpty() || ! dirPath.isDirectory()) - return; - - DirectoryIterator di (dirPath, true); - - while (di.next()) - { - File possible (di.getFile()); - - if (possible.hasFileExtension (T("ttf")) - || possible.hasFileExtension (T("pfb")) - || possible.hasFileExtension (T("pcf"))) - { - FT_Face face; - int faceIndex = 0; - int numFaces = 0; - - do - { - if (FT_New_Face (ftLib, - possible.getFullPathName(), - faceIndex, - &face) == 0) - { - if (faceIndex == 0) - numFaces = face->num_faces; - - if ((face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) - { - FreeTypeFontFace* const newFace = findOrCreate (face->family_name, true); - int style = (int) FreeTypeFontFace::Plain; - - if ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0) - style |= (int) FreeTypeFontFace::Bold; - - if ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0) - style |= (int) FreeTypeFontFace::Italic; - - newFace->setFileName (possible.getFullPathName(), faceIndex, (FreeTypeFontFace::FontStyle) style); - newFace->setMonospaced ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0); - - // Surely there must be a better way to do this? - const String name (face->family_name); - newFace->setSerif (! (name.containsIgnoreCase (T("Sans")) - || name.containsIgnoreCase (T("Verdana")) - || name.containsIgnoreCase (T("Arial")))); - } - - FT_Done_Face (face); - } - - ++faceIndex; - } - while (faceIndex < numFaces); - } - } - } - - // Create a FreeType face object for a given font - FT_Face createFT_Face (const String& fontName, - const bool bold, - const bool italic) throw() - { - FT_Face face = 0; - - if (fontName == lastFontName && bold == lastBold && italic == lastItalic) - { - face = lastFace; - } - else - { - if (lastFace != 0) - { - FT_Done_Face (lastFace); - lastFace = 0; - } - - lastFontName = fontName; - lastBold = bold; - lastItalic = italic; - - FreeTypeFontFace* const ftFace = findOrCreate (fontName); - - if (ftFace != 0) - { - int style = (int) FreeTypeFontFace::Plain; - - if (bold) - style |= (int) FreeTypeFontFace::Bold; - - if (italic) - style |= (int) FreeTypeFontFace::Italic; - - int faceIndex; - String fileName (ftFace->getFileName (style, faceIndex)); - - if (fileName.isEmpty()) - { - style ^= (int) FreeTypeFontFace::Bold; - - fileName = ftFace->getFileName (style, faceIndex); - - if (fileName.isEmpty()) - { - style ^= (int) FreeTypeFontFace::Bold; - style ^= (int) FreeTypeFontFace::Italic; - - fileName = ftFace->getFileName (style, faceIndex); - - if (! fileName.length()) - { - style ^= (int) FreeTypeFontFace::Bold; - fileName = ftFace->getFileName (style, faceIndex); - } - } - } - - if (! FT_New_Face (ftLib, (const char*) fileName, faceIndex, &lastFace)) - { - face = lastFace; - - // If there isn't a unicode charmap then select the first one. - if (FT_Select_Charmap (face, ft_encoding_unicode)) - FT_Set_Charmap (face, face->charmaps[0]); - } - } - } - - return face; - } - - bool addGlyph (FT_Face face, CustomTypeface& dest, uint32 character) throw() - { - const unsigned int glyphIndex = FT_Get_Char_Index (face, character); - const float height = (float) (face->ascender - face->descender); - const float scaleX = 1.0f / height; - const float scaleY = -1.0f / height; - Path destShape; - - #define CONVERTX(val) (scaleX * (val).x) - #define CONVERTY(val) (scaleY * (val).y) - - if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM) != 0 - || face->glyph->format != ft_glyph_format_outline) - { - return false; - } - - const FT_Outline* const outline = &face->glyph->outline; - const short* const contours = outline->contours; - const char* const tags = outline->tags; - FT_Vector* const points = outline->points; - - for (int c = 0; c < outline->n_contours; c++) - { - const int startPoint = (c == 0) ? 0 : contours [c - 1] + 1; - const int endPoint = contours[c]; - - for (int p = startPoint; p <= endPoint; p++) - { - const float x = CONVERTX (points[p]); - const float y = CONVERTY (points[p]); - - if (p == startPoint) - { - if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic) - { - float x2 = CONVERTX (points [endPoint]); - float y2 = CONVERTY (points [endPoint]); - - if (FT_CURVE_TAG (tags[endPoint]) != FT_Curve_Tag_On) - { - x2 = (x + x2) * 0.5f; - y2 = (y + y2) * 0.5f; - } - - destShape.startNewSubPath (x2, y2); - } - else - { - destShape.startNewSubPath (x, y); - } - } - - if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_On) - { - if (p != startPoint) - destShape.lineTo (x, y); - } - else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic) - { - const int nextIndex = (p == endPoint) ? startPoint : p + 1; - float x2 = CONVERTX (points [nextIndex]); - float y2 = CONVERTY (points [nextIndex]); - - if (FT_CURVE_TAG (tags [nextIndex]) == FT_Curve_Tag_Conic) - { - x2 = (x + x2) * 0.5f; - y2 = (y + y2) * 0.5f; - } - else - { - ++p; - } - - destShape.quadraticTo (x, y, x2, y2); - } - else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Cubic) - { - if (p >= endPoint) - return false; - - const int next1 = p + 1; - const int next2 = (p == (endPoint - 1)) ? startPoint : p + 2; - - const float x2 = CONVERTX (points [next1]); - const float y2 = CONVERTY (points [next1]); - const float x3 = CONVERTX (points [next2]); - const float y3 = CONVERTY (points [next2]); - - if (FT_CURVE_TAG (tags[next1]) != FT_Curve_Tag_Cubic - || FT_CURVE_TAG (tags[next2]) != FT_Curve_Tag_On) - return false; - - destShape.cubicTo (x, y, x2, y2, x3, y3); - p += 2; - } - } - - destShape.closeSubPath(); - } - - dest.addGlyph (character, destShape, face->glyph->metrics.horiAdvance / height); - - if ((face->face_flags & FT_FACE_FLAG_KERNING) != 0) - addKerning (face, dest, character, glyphIndex); - - return true; - } - - void addKerning (FT_Face face, CustomTypeface& dest, const uint32 character, const uint32 glyphIndex) throw() - { - const float height = (float) (face->ascender - face->descender); - - uint32 rightGlyphIndex; - uint32 rightCharCode = FT_Get_First_Char (face, &rightGlyphIndex); - - while (rightGlyphIndex != 0) - { - FT_Vector kerning; - - if (FT_Get_Kerning (face, glyphIndex, rightGlyphIndex, ft_kerning_unscaled, &kerning) == 0) - { - if (kerning.x != 0) - dest.addKerningPair (character, rightCharCode, kerning.x / height); - } - - rightCharCode = FT_Get_Next_Char (face, rightCharCode, &rightGlyphIndex); - } - } - - // Add a glyph to a font - bool addGlyphToFont (const uint32 character, - const tchar* fontName, bool bold, bool italic, - CustomTypeface& dest) throw() - { - FT_Face face = createFT_Face (fontName, bold, italic); - - if (face != 0) - return addGlyph (face, dest, character); - - return false; - } - - void getFamilyNames (StringArray& familyNames) const throw() - { - for (int i = 0; i < faces.size(); i++) - familyNames.add (faces[i]->getFamilyName()); - } - - void getMonospacedNames (StringArray& monoSpaced) const throw() - { - for (int i = 0; i < faces.size(); i++) - if (faces[i]->getMonospaced()) - monoSpaced.add (faces[i]->getFamilyName()); - } - - void getSerifNames (StringArray& serif) const throw() - { - for (int i = 0; i < faces.size(); i++) - if (faces[i]->getSerif()) - serif.add (faces[i]->getFamilyName()); - } - - void getSansSerifNames (StringArray& sansSerif) const throw() - { - for (int i = 0; i < faces.size(); i++) - if (! faces[i]->getSerif()) - sansSerif.add (faces[i]->getFamilyName()); - } - - juce_DeclareSingleton_SingleThreaded_Minimal (FreeTypeInterface) + FreeTypeInterface() throw() + : lastFace (0), + lastBold (false), + lastItalic (false) + { + if (FT_Init_FreeType (&ftLib) != 0) + { + ftLib = 0; + DBG (T("Failed to initialize FreeType")); + } + + StringArray fontDirs; + fontDirs.addTokens (String (getenv ("JUCE_FONT_PATH")), T(";,"), 0); + fontDirs.removeEmptyStrings (true); + + if (fontDirs.size() == 0) + { + XmlDocument fontsConfig (File ("/etc/fonts/fonts.conf")); + XmlElement* const fontsInfo = fontsConfig.getDocumentElement(); + + if (fontsInfo != 0) + { + forEachXmlChildElementWithTagName (*fontsInfo, e, T("dir")) + { + fontDirs.add (e->getAllSubText().trim()); + } + + delete fontsInfo; + } + } + + if (fontDirs.size() == 0) + fontDirs.add ("/usr/X11R6/lib/X11/fonts"); + + for (int i = 0; i < fontDirs.size(); ++i) + enumerateFaces (fontDirs[i]); + } + + ~FreeTypeInterface() throw() + { + if (lastFace != 0) + FT_Done_Face (lastFace); + + if (ftLib != 0) + FT_Done_FreeType (ftLib); + + clearSingletonInstance(); + } + + FreeTypeFontFace* findOrCreate (const String& familyName, + const bool create = false) throw() + { + for (int i = 0; i < faces.size(); i++) + if (faces[i]->getFamilyName() == familyName) + return faces[i]; + + if (! create) + return NULL; + + FreeTypeFontFace* newFace = new FreeTypeFontFace (familyName); + faces.add (newFace); + + return newFace; + } + + // Enumerate all font faces available in a given directory + void enumerateFaces (const String& path) throw() + { + File dirPath (path); + if (path.isEmpty() || ! dirPath.isDirectory()) + return; + + DirectoryIterator di (dirPath, true); + + while (di.next()) + { + File possible (di.getFile()); + + if (possible.hasFileExtension (T("ttf")) + || possible.hasFileExtension (T("pfb")) + || possible.hasFileExtension (T("pcf"))) + { + FT_Face face; + int faceIndex = 0; + int numFaces = 0; + + do + { + if (FT_New_Face (ftLib, + possible.getFullPathName(), + faceIndex, + &face) == 0) + { + if (faceIndex == 0) + numFaces = face->num_faces; + + if ((face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) + { + FreeTypeFontFace* const newFace = findOrCreate (face->family_name, true); + int style = (int) FreeTypeFontFace::Plain; + + if ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0) + style |= (int) FreeTypeFontFace::Bold; + + if ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0) + style |= (int) FreeTypeFontFace::Italic; + + newFace->setFileName (possible.getFullPathName(), faceIndex, (FreeTypeFontFace::FontStyle) style); + newFace->setMonospaced ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0); + + // Surely there must be a better way to do this? + const String name (face->family_name); + newFace->setSerif (! (name.containsIgnoreCase (T("Sans")) + || name.containsIgnoreCase (T("Verdana")) + || name.containsIgnoreCase (T("Arial")))); + } + + FT_Done_Face (face); + } + + ++faceIndex; + } + while (faceIndex < numFaces); + } + } + } + + // Create a FreeType face object for a given font + FT_Face createFT_Face (const String& fontName, + const bool bold, + const bool italic) throw() + { + FT_Face face = 0; + + if (fontName == lastFontName && bold == lastBold && italic == lastItalic) + { + face = lastFace; + } + else + { + if (lastFace != 0) + { + FT_Done_Face (lastFace); + lastFace = 0; + } + + lastFontName = fontName; + lastBold = bold; + lastItalic = italic; + + FreeTypeFontFace* const ftFace = findOrCreate (fontName); + + if (ftFace != 0) + { + int style = (int) FreeTypeFontFace::Plain; + + if (bold) + style |= (int) FreeTypeFontFace::Bold; + + if (italic) + style |= (int) FreeTypeFontFace::Italic; + + int faceIndex; + String fileName (ftFace->getFileName (style, faceIndex)); + + if (fileName.isEmpty()) + { + style ^= (int) FreeTypeFontFace::Bold; + + fileName = ftFace->getFileName (style, faceIndex); + + if (fileName.isEmpty()) + { + style ^= (int) FreeTypeFontFace::Bold; + style ^= (int) FreeTypeFontFace::Italic; + + fileName = ftFace->getFileName (style, faceIndex); + + if (! fileName.length()) + { + style ^= (int) FreeTypeFontFace::Bold; + fileName = ftFace->getFileName (style, faceIndex); + } + } + } + + if (! FT_New_Face (ftLib, (const char*) fileName, faceIndex, &lastFace)) + { + face = lastFace; + + // If there isn't a unicode charmap then select the first one. + if (FT_Select_Charmap (face, ft_encoding_unicode)) + FT_Set_Charmap (face, face->charmaps[0]); + } + } + } + + return face; + } + + bool addGlyph (FT_Face face, CustomTypeface& dest, uint32 character) throw() + { + const unsigned int glyphIndex = FT_Get_Char_Index (face, character); + const float height = (float) (face->ascender - face->descender); + const float scaleX = 1.0f / height; + const float scaleY = -1.0f / height; + Path destShape; + + #define CONVERTX(val) (scaleX * (val).x) + #define CONVERTY(val) (scaleY * (val).y) + + if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM) != 0 + || face->glyph->format != ft_glyph_format_outline) + { + return false; + } + + const FT_Outline* const outline = &face->glyph->outline; + const short* const contours = outline->contours; + const char* const tags = outline->tags; + FT_Vector* const points = outline->points; + + for (int c = 0; c < outline->n_contours; c++) + { + const int startPoint = (c == 0) ? 0 : contours [c - 1] + 1; + const int endPoint = contours[c]; + + for (int p = startPoint; p <= endPoint; p++) + { + const float x = CONVERTX (points[p]); + const float y = CONVERTY (points[p]); + + if (p == startPoint) + { + if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic) + { + float x2 = CONVERTX (points [endPoint]); + float y2 = CONVERTY (points [endPoint]); + + if (FT_CURVE_TAG (tags[endPoint]) != FT_Curve_Tag_On) + { + x2 = (x + x2) * 0.5f; + y2 = (y + y2) * 0.5f; + } + + destShape.startNewSubPath (x2, y2); + } + else + { + destShape.startNewSubPath (x, y); + } + } + + if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_On) + { + if (p != startPoint) + destShape.lineTo (x, y); + } + else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Conic) + { + const int nextIndex = (p == endPoint) ? startPoint : p + 1; + float x2 = CONVERTX (points [nextIndex]); + float y2 = CONVERTY (points [nextIndex]); + + if (FT_CURVE_TAG (tags [nextIndex]) == FT_Curve_Tag_Conic) + { + x2 = (x + x2) * 0.5f; + y2 = (y + y2) * 0.5f; + } + else + { + ++p; + } + + destShape.quadraticTo (x, y, x2, y2); + } + else if (FT_CURVE_TAG (tags[p]) == FT_Curve_Tag_Cubic) + { + if (p >= endPoint) + return false; + + const int next1 = p + 1; + const int next2 = (p == (endPoint - 1)) ? startPoint : p + 2; + + const float x2 = CONVERTX (points [next1]); + const float y2 = CONVERTY (points [next1]); + const float x3 = CONVERTX (points [next2]); + const float y3 = CONVERTY (points [next2]); + + if (FT_CURVE_TAG (tags[next1]) != FT_Curve_Tag_Cubic + || FT_CURVE_TAG (tags[next2]) != FT_Curve_Tag_On) + return false; + + destShape.cubicTo (x, y, x2, y2, x3, y3); + p += 2; + } + } + + destShape.closeSubPath(); + } + + dest.addGlyph (character, destShape, face->glyph->metrics.horiAdvance / height); + + if ((face->face_flags & FT_FACE_FLAG_KERNING) != 0) + addKerning (face, dest, character, glyphIndex); + + return true; + } + + void addKerning (FT_Face face, CustomTypeface& dest, const uint32 character, const uint32 glyphIndex) throw() + { + const float height = (float) (face->ascender - face->descender); + + uint32 rightGlyphIndex; + uint32 rightCharCode = FT_Get_First_Char (face, &rightGlyphIndex); + + while (rightGlyphIndex != 0) + { + FT_Vector kerning; + + if (FT_Get_Kerning (face, glyphIndex, rightGlyphIndex, ft_kerning_unscaled, &kerning) == 0) + { + if (kerning.x != 0) + dest.addKerningPair (character, rightCharCode, kerning.x / height); + } + + rightCharCode = FT_Get_Next_Char (face, rightCharCode, &rightGlyphIndex); + } + } + + // Add a glyph to a font + bool addGlyphToFont (const uint32 character, + const tchar* fontName, bool bold, bool italic, + CustomTypeface& dest) throw() + { + FT_Face face = createFT_Face (fontName, bold, italic); + + if (face != 0) + return addGlyph (face, dest, character); + + return false; + } + + void getFamilyNames (StringArray& familyNames) const throw() + { + for (int i = 0; i < faces.size(); i++) + familyNames.add (faces[i]->getFamilyName()); + } + + void getMonospacedNames (StringArray& monoSpaced) const throw() + { + for (int i = 0; i < faces.size(); i++) + if (faces[i]->getMonospaced()) + monoSpaced.add (faces[i]->getFamilyName()); + } + + void getSerifNames (StringArray& serif) const throw() + { + for (int i = 0; i < faces.size(); i++) + if (faces[i]->getSerif()) + serif.add (faces[i]->getFamilyName()); + } + + void getSansSerifNames (StringArray& sansSerif) const throw() + { + for (int i = 0; i < faces.size(); i++) + if (! faces[i]->getSerif()) + sansSerif.add (faces[i]->getFamilyName()); + } + + juce_DeclareSingleton_SingleThreaded_Minimal (FreeTypeInterface) private: - FT_Library ftLib; - FT_Face lastFace; - String lastFontName; - bool lastBold, lastItalic; - OwnedArray faces; + FT_Library ftLib; + FT_Face lastFace; + String lastFontName; + bool lastBold, lastItalic; + OwnedArray faces; }; juce_ImplementSingleton_SingleThreaded (FreeTypeInterface) @@ -253814,103 +231463,103 @@ juce_ImplementSingleton_SingleThreaded (FreeTypeInterface) class FreetypeTypeface : public CustomTypeface { public: - FreetypeTypeface (const Font& font) - { - FT_Face face = FreeTypeInterface::getInstance() - ->createFT_Face (font.getTypefaceName(), font.isBold(), font.isItalic()); + FreetypeTypeface (const Font& font) + { + FT_Face face = FreeTypeInterface::getInstance() + ->createFT_Face (font.getTypefaceName(), font.isBold(), font.isItalic()); - if (face == 0) - { + if (face == 0) + { #ifdef JUCE_DEBUG - String msg (T("Failed to create typeface: ")); - msg << font.getTypefaceName() << " " << (font.isBold() ? 'B' : ' ') << (font.isItalic() ? 'I' : ' '); - DBG (msg); + String msg (T("Failed to create typeface: ")); + msg << font.getTypefaceName() << " " << (font.isBold() ? 'B' : ' ') << (font.isItalic() ? 'I' : ' '); + DBG (msg); #endif - } - else - { - setCharacteristics (font.getTypefaceName(), - face->ascender / (float) (face->ascender - face->descender), - font.isBold(), font.isItalic(), - L' '); - } - } + } + else + { + setCharacteristics (font.getTypefaceName(), + face->ascender / (float) (face->ascender - face->descender), + font.isBold(), font.isItalic(), + L' '); + } + } - bool loadGlyphIfPossible (const juce_wchar character) - { - return FreeTypeInterface::getInstance() - ->addGlyphToFont (character, name, isBold, isItalic, *this); - } + bool loadGlyphIfPossible (const juce_wchar character) + { + return FreeTypeInterface::getInstance() + ->addGlyphToFont (character, name, isBold, isItalic, *this); + } }; const Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) { - return new FreetypeTypeface (font); + return new FreetypeTypeface (font); } const StringArray Font::findAllTypefaceNames() throw() { - StringArray s; - FreeTypeInterface::getInstance()->getFamilyNames (s); - s.sort (true); - return s; + StringArray s; + FreeTypeInterface::getInstance()->getFamilyNames (s); + s.sort (true); + return s; } static const String pickBestFont (const StringArray& names, - const char* const choicesString) + const char* const choicesString) { - StringArray choices; - choices.addTokens (String (choicesString), T(","), 0); - choices.trim(); - choices.removeEmptyStrings(); + StringArray choices; + choices.addTokens (String (choicesString), T(","), 0); + choices.trim(); + choices.removeEmptyStrings(); - int i, j; - for (j = 0; j < choices.size(); ++j) - if (names.contains (choices[j], true)) - return choices[j]; + int i, j; + for (j = 0; j < choices.size(); ++j) + if (names.contains (choices[j], true)) + return choices[j]; - for (j = 0; j < choices.size(); ++j) - for (i = 0; i < names.size(); i++) - if (names[i].startsWithIgnoreCase (choices[j])) - return names[i]; + for (j = 0; j < choices.size(); ++j) + for (i = 0; i < names.size(); i++) + if (names[i].startsWithIgnoreCase (choices[j])) + return names[i]; - for (j = 0; j < choices.size(); ++j) - for (i = 0; i < names.size(); i++) - if (names[i].containsIgnoreCase (choices[j])) - return names[i]; + for (j = 0; j < choices.size(); ++j) + for (i = 0; i < names.size(); i++) + if (names[i].containsIgnoreCase (choices[j])) + return names[i]; - return names[0]; + return names[0]; } static const String linux_getDefaultSansSerifFontName() { - StringArray allFonts; - FreeTypeInterface::getInstance()->getSansSerifNames (allFonts); + StringArray allFonts; + FreeTypeInterface::getInstance()->getSansSerifNames (allFonts); - return pickBestFont (allFonts, "Verdana, Bitstream Vera Sans, Luxi Sans, Sans"); + return pickBestFont (allFonts, "Verdana, Bitstream Vera Sans, Luxi Sans, Sans"); } static const String linux_getDefaultSerifFontName() { - StringArray allFonts; - FreeTypeInterface::getInstance()->getSerifNames (allFonts); + StringArray allFonts; + FreeTypeInterface::getInstance()->getSerifNames (allFonts); - return pickBestFont (allFonts, "Bitstream Vera Serif, Times, Nimbus Roman, Serif"); + return pickBestFont (allFonts, "Bitstream Vera Serif, Times, Nimbus Roman, Serif"); } static const String linux_getDefaultMonospacedFontName() { - StringArray allFonts; - FreeTypeInterface::getInstance()->getMonospacedNames (allFonts); + StringArray allFonts; + FreeTypeInterface::getInstance()->getMonospacedNames (allFonts); - return pickBestFont (allFonts, "Bitstream Vera Sans Mono, Courier, Sans Mono, Mono"); + return pickBestFont (allFonts, "Bitstream Vera Sans Mono, Courier, Sans Mono, Mono"); } void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed) throw() { - defaultSans = linux_getDefaultSansSerifFontName(); - defaultSerif = linux_getDefaultSerifFontName(); - defaultFixed = linux_getDefaultMonospacedFontName(); + defaultSans = linux_getDefaultSansSerifFontName(); + defaultSerif = linux_getDefaultSerifFontName(); + defaultFixed = linux_getDefaultMonospacedFontName(); } #endif @@ -253924,7 +231573,7 @@ void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSeri #define TAKE_FOCUS 0 #define DELETE_WINDOW 1 -#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_REQUEST_DOCK 0 #define SYSTEM_TRAY_BEGIN_MESSAGE 1 #define SYSTEM_TRAY_CANCEL_MESSAGE 2 @@ -253966,27 +231615,27 @@ static int trappedErrorCode = 0; extern "C" int errorTrapHandler (Display* dpy, XErrorEvent* err) { - trappedErrorCode = err->error_code; - return 0; + trappedErrorCode = err->error_code; + return 0; } static void trapErrors() { - trappedErrorCode = 0; - oldHandler = XSetErrorHandler (errorTrapHandler); + trappedErrorCode = 0; + oldHandler = XSetErrorHandler (errorTrapHandler); } static bool untrapErrors() { - XSetErrorHandler (oldHandler); - return (trappedErrorCode == 0); + XSetErrorHandler (oldHandler); + return (trappedErrorCode == 0); } static bool isActiveApplication = false; bool Process::isForegroundProcess() { - return isActiveApplication; + return isActiveApplication; } // These are defined in juce_linux_Messaging.cpp @@ -253994,49 +231643,49 @@ extern Display* display; extern XContext improbableNumber; static const int eventMask = NoEventMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask - | EnterWindowMask | LeaveWindowMask | PointerMotionMask | KeymapStateMask - | ExposureMask | StructureNotifyMask | FocusChangeMask; + | EnterWindowMask | LeaveWindowMask | PointerMotionMask | KeymapStateMask + | ExposureMask | StructureNotifyMask | FocusChangeMask; static int pointerMap[5]; static int lastMousePosX = 0, lastMousePosY = 0; enum MouseButtons { - NoButton = 0, - LeftButton = 1, - MiddleButton = 2, - RightButton = 3, - WheelUp = 4, - WheelDown = 5 + NoButton = 0, + LeftButton = 1, + MiddleButton = 2, + RightButton = 3, + WheelUp = 4, + WheelDown = 5 }; static void getMousePos (int& x, int& y, int& mouseMods) throw() { - Window root, child; - int winx, winy; - unsigned int mask; + Window root, child; + int winx, winy; + unsigned int mask; - mouseMods = 0; + mouseMods = 0; - if (XQueryPointer (display, - RootWindow (display, DefaultScreen (display)), - &root, &child, - &x, &y, &winx, &winy, &mask) == False) - { - // Pointer not on the default screen - x = y = -1; - } - else - { - if ((mask & Button1Mask) != 0) - mouseMods |= ModifierKeys::leftButtonModifier; + if (XQueryPointer (display, + RootWindow (display, DefaultScreen (display)), + &root, &child, + &x, &y, &winx, &winy, &mask) == False) + { + // Pointer not on the default screen + x = y = -1; + } + else + { + if ((mask & Button1Mask) != 0) + mouseMods |= ModifierKeys::leftButtonModifier; - if ((mask & Button2Mask) != 0) - mouseMods |= ModifierKeys::middleButtonModifier; + if ((mask & Button2Mask) != 0) + mouseMods |= ModifierKeys::middleButtonModifier; - if ((mask & Button3Mask) != 0) - mouseMods |= ModifierKeys::rightButtonModifier; - } + if ((mask & Button3Mask) != 0) + mouseMods |= ModifierKeys::rightButtonModifier; + } } static int AltMask = 0; @@ -254047,3049 +231696,3040 @@ static char keyStates [32]; static void updateKeyStates (const int keycode, const bool press) throw() { - const int keybyte = keycode >> 3; - const int keybit = (1 << (keycode & 7)); + const int keybyte = keycode >> 3; + const int keybit = (1 << (keycode & 7)); - if (press) - keyStates [keybyte] |= keybit; - else - keyStates [keybyte] &= ~keybit; + if (press) + keyStates [keybyte] |= keybit; + else + keyStates [keybyte] &= ~keybit; } static bool keyDown (const int keycode) throw() { - const int keybyte = keycode >> 3; - const int keybit = (1 << (keycode & 7)); + const int keybyte = keycode >> 3; + const int keybit = (1 << (keycode & 7)); - return (keyStates [keybyte] & keybit) != 0; + return (keyStates [keybyte] & keybit) != 0; } static const int extendedKeyModifier = 0x10000000; bool KeyPress::isKeyCurrentlyDown (const int keyCode) throw() { - int keysym; + int keysym; - if (keyCode & extendedKeyModifier) - { - keysym = 0xff00 | (keyCode & 0xff); - } - else - { - keysym = keyCode; + if (keyCode & extendedKeyModifier) + { + keysym = 0xff00 | (keyCode & 0xff); + } + else + { + keysym = keyCode; - if (keysym == (XK_Tab & 0xff) - || keysym == (XK_Return & 0xff) - || keysym == (XK_Escape & 0xff) - || keysym == (XK_BackSpace & 0xff)) - { - keysym |= 0xff00; - } - } + if (keysym == (XK_Tab & 0xff) + || keysym == (XK_Return & 0xff) + || keysym == (XK_Escape & 0xff) + || keysym == (XK_BackSpace & 0xff)) + { + keysym |= 0xff00; + } + } - return keyDown (XKeysymToKeycode (display, keysym)); + return keyDown (XKeysymToKeycode (display, keysym)); } // Alt and Num lock are not defined by standard X // modifier constants: check what they're mapped to static void getModifierMapping() throw() { - const int altLeftCode = XKeysymToKeycode (display, XK_Alt_L); - const int numLockCode = XKeysymToKeycode (display, XK_Num_Lock); + const int altLeftCode = XKeysymToKeycode (display, XK_Alt_L); + const int numLockCode = XKeysymToKeycode (display, XK_Num_Lock); - AltMask = 0; - NumLockMask = 0; + AltMask = 0; + NumLockMask = 0; - XModifierKeymap* mapping = XGetModifierMapping (display); + XModifierKeymap* mapping = XGetModifierMapping (display); - if (mapping) - { - for (int i = 0; i < 8; i++) - { - if (mapping->modifiermap [i << 1] == altLeftCode) - AltMask = 1 << i; - else if (mapping->modifiermap [i << 1] == numLockCode) - NumLockMask = 1 << i; - } + if (mapping) + { + for (int i = 0; i < 8; i++) + { + if (mapping->modifiermap [i << 1] == altLeftCode) + AltMask = 1 << i; + else if (mapping->modifiermap [i << 1] == numLockCode) + NumLockMask = 1 << i; + } - XFreeModifiermap (mapping); - } + XFreeModifiermap (mapping); + } } static int currentModifiers = 0; void ModifierKeys::updateCurrentModifiers() throw() { - currentModifierFlags = currentModifiers; + currentModifierFlags = currentModifiers; } const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() throw() { - int x, y, mouseMods; - getMousePos (x, y, mouseMods); + int x, y, mouseMods; + getMousePos (x, y, mouseMods); - currentModifiers &= ~ModifierKeys::allMouseButtonModifiers; - currentModifiers |= mouseMods; + currentModifiers &= ~ModifierKeys::allMouseButtonModifiers; + currentModifiers |= mouseMods; - return ModifierKeys (currentModifiers); + return ModifierKeys (currentModifiers); } static void updateKeyModifiers (const int status) throw() { - currentModifiers &= ~(ModifierKeys::shiftModifier - | ModifierKeys::ctrlModifier - | ModifierKeys::altModifier); + currentModifiers &= ~(ModifierKeys::shiftModifier + | ModifierKeys::ctrlModifier + | ModifierKeys::altModifier); - if (status & ShiftMask) - currentModifiers |= ModifierKeys::shiftModifier; + if (status & ShiftMask) + currentModifiers |= ModifierKeys::shiftModifier; - if (status & ControlMask) - currentModifiers |= ModifierKeys::ctrlModifier; + if (status & ControlMask) + currentModifiers |= ModifierKeys::ctrlModifier; - if (status & AltMask) - currentModifiers |= ModifierKeys::altModifier; + if (status & AltMask) + currentModifiers |= ModifierKeys::altModifier; - numLock = ((status & NumLockMask) != 0); - capsLock = ((status & LockMask) != 0); + numLock = ((status & NumLockMask) != 0); + capsLock = ((status & LockMask) != 0); } static bool updateKeyModifiersFromSym (KeySym sym, const bool press) throw() { - int modifier = 0; - bool isModifier = true; + int modifier = 0; + bool isModifier = true; - switch (sym) - { - case XK_Shift_L: - case XK_Shift_R: - modifier = ModifierKeys::shiftModifier; - break; + switch (sym) + { + case XK_Shift_L: + case XK_Shift_R: + modifier = ModifierKeys::shiftModifier; + break; - case XK_Control_L: - case XK_Control_R: - modifier = ModifierKeys::ctrlModifier; - break; + case XK_Control_L: + case XK_Control_R: + modifier = ModifierKeys::ctrlModifier; + break; - case XK_Alt_L: - case XK_Alt_R: - modifier = ModifierKeys::altModifier; - break; + case XK_Alt_L: + case XK_Alt_R: + modifier = ModifierKeys::altModifier; + break; - case XK_Num_Lock: - if (press) - numLock = ! numLock; + case XK_Num_Lock: + if (press) + numLock = ! numLock; - break; + break; - case XK_Caps_Lock: - if (press) - capsLock = ! capsLock; + case XK_Caps_Lock: + if (press) + capsLock = ! capsLock; - break; + break; - case XK_Scroll_Lock: - break; + case XK_Scroll_Lock: + break; - default: - isModifier = false; - break; - } + default: + isModifier = false; + break; + } - if (modifier != 0) - { - if (press) - currentModifiers |= modifier; - else - currentModifiers &= ~modifier; - } + if (modifier != 0) + { + if (press) + currentModifiers |= modifier; + else + currentModifiers &= ~modifier; + } - return isModifier; + return isModifier; } #if JUCE_USE_XSHM static bool isShmAvailable() throw() { - static bool isChecked = false; - static bool isAvailable = false; + static bool isChecked = false; + static bool isAvailable = false; - if (! isChecked) - { - isChecked = true; + if (! isChecked) + { + isChecked = true; - int major, minor; - Bool pixmaps; + int major, minor; + Bool pixmaps; - if (XShmQueryVersion (display, &major, &minor, &pixmaps)) - { - trapErrors(); + if (XShmQueryVersion (display, &major, &minor, &pixmaps)) + { + trapErrors(); - XShmSegmentInfo segmentInfo; - zerostruct (segmentInfo); - XImage* xImage = XShmCreateImage (display, DefaultVisual (display, DefaultScreen (display)), - 24, ZPixmap, 0, &segmentInfo, 50, 50); + XShmSegmentInfo segmentInfo; + zerostruct (segmentInfo); + XImage* xImage = XShmCreateImage (display, DefaultVisual (display, DefaultScreen (display)), + 24, ZPixmap, 0, &segmentInfo, 50, 50); - if ((segmentInfo.shmid = shmget (IPC_PRIVATE, - xImage->bytes_per_line * xImage->height, - IPC_CREAT | 0777)) >= 0) - { - segmentInfo.shmaddr = (char*) shmat (segmentInfo.shmid, 0, 0); + if ((segmentInfo.shmid = shmget (IPC_PRIVATE, + xImage->bytes_per_line * xImage->height, + IPC_CREAT | 0777)) >= 0) + { + segmentInfo.shmaddr = (char*) shmat (segmentInfo.shmid, 0, 0); - if (segmentInfo.shmaddr != (void*) -1) - { - segmentInfo.readOnly = False; - xImage->data = segmentInfo.shmaddr; - XSync (display, False); + if (segmentInfo.shmaddr != (void*) -1) + { + segmentInfo.readOnly = False; + xImage->data = segmentInfo.shmaddr; + XSync (display, False); - if (XShmAttach (display, &segmentInfo) != 0) - { - XSync (display, False); - XShmDetach (display, &segmentInfo); + if (XShmAttach (display, &segmentInfo) != 0) + { + XSync (display, False); + XShmDetach (display, &segmentInfo); - isAvailable = true; - } - } + isAvailable = true; + } + } - XFlush (display); - XDestroyImage (xImage); + XFlush (display); + XDestroyImage (xImage); - shmdt (segmentInfo.shmaddr); - } + shmdt (segmentInfo.shmaddr); + } - shmctl (segmentInfo.shmid, IPC_RMID, 0); + shmctl (segmentInfo.shmid, IPC_RMID, 0); - isAvailable &= untrapErrors(); - } - } + isAvailable &= untrapErrors(); + } + } - return isAvailable; + return isAvailable; } #endif static Pixmap juce_createColourPixmapFromImage (Display* display, const Image& image) { - const int width = image.getWidth(); - const int height = image.getHeight(); - HeapBlock colour (width * height); - int index = 0; + const int width = image.getWidth(); + const int height = image.getHeight(); + HeapBlock colour (width * height); + int index = 0; - for (int y = 0; y < height; ++y) - for (int x = 0; x < width; ++x) - colour[index++] = image.getPixelAt (x, y).getARGB(); + for (int y = 0; y < height; ++y) + for (int x = 0; x < width; ++x) + colour[index++] = image.getPixelAt (x, y).getARGB(); - XImage* ximage = XCreateImage (display, CopyFromParent, 24, ZPixmap, - 0, (char*) colour, width, height, 32, 0); + XImage* ximage = XCreateImage (display, CopyFromParent, 24, ZPixmap, + 0, (char*) colour, width, height, 32, 0); - Pixmap pixmap = XCreatePixmap (display, DefaultRootWindow (display), - width, height, 24); + Pixmap pixmap = XCreatePixmap (display, DefaultRootWindow (display), + width, height, 24); - GC gc = XCreateGC (display, pixmap, 0, 0); - XPutImage (display, pixmap, gc, ximage, 0, 0, 0, 0, width, height); - XFreeGC (display, gc); + GC gc = XCreateGC (display, pixmap, 0, 0); + XPutImage (display, pixmap, gc, ximage, 0, 0, 0, 0, width, height); + XFreeGC (display, gc); - return pixmap; + return pixmap; } static Pixmap juce_createMaskPixmapFromImage (Display* display, const Image& image) { - const int width = image.getWidth(); - const int height = image.getHeight(); - const int stride = (width + 7) >> 3; - HeapBlock mask; - mask.calloc (stride * height); - const bool msbfirst = (BitmapBitOrder (display) == MSBFirst); + const int width = image.getWidth(); + const int height = image.getHeight(); + const int stride = (width + 7) >> 3; + HeapBlock mask; + mask.calloc (stride * height); + const bool msbfirst = (BitmapBitOrder (display) == MSBFirst); - for (int y = 0; y < height; ++y) - { - for (int x = 0; x < width; ++x) - { - const uint8 bit = (uint8) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7))); - const int offset = y * stride + (x >> 3); + for (int y = 0; y < height; ++y) + { + for (int x = 0; x < width; ++x) + { + const uint8 bit = (uint8) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7))); + const int offset = y * stride + (x >> 3); - if (image.getPixelAt (x, y).getAlpha() >= 128) - mask[offset] |= bit; - } - } + if (image.getPixelAt (x, y).getAlpha() >= 128) + mask[offset] |= bit; + } + } - return XCreatePixmapFromBitmapData (display, DefaultRootWindow (display), - (char*) mask, width, height, 1, 0, 1); + return XCreatePixmapFromBitmapData (display, DefaultRootWindow (display), + (char*) mask, width, height, 1, 0, 1); } class XBitmapImage : public Image { public: - XBitmapImage (const PixelFormat format_, const int w, const int h, - const bool clearImage, const bool is16Bit_) - : Image (format_, w, h), - is16Bit (is16Bit_) - { - jassert (format_ == RGB || format_ == ARGB); + XBitmapImage (const PixelFormat format_, const int w, const int h, + const bool clearImage, const bool is16Bit_) + : Image (format_, w, h), + is16Bit (is16Bit_) + { + jassert (format_ == RGB || format_ == ARGB); - pixelStride = (format_ == RGB) ? 3 : 4; - lineStride = ((w * pixelStride + 3) & ~3); + pixelStride = (format_ == RGB) ? 3 : 4; + lineStride = ((w * pixelStride + 3) & ~3); - Visual* const visual = DefaultVisual (display, DefaultScreen (display)); + Visual* const visual = DefaultVisual (display, DefaultScreen (display)); #if JUCE_USE_XSHM - usingXShm = false; + usingXShm = false; - if ((! is16Bit) && isShmAvailable()) - { - zerostruct (segmentInfo); + if ((! is16Bit) && isShmAvailable()) + { + zerostruct (segmentInfo); - xImage = XShmCreateImage (display, visual, 24, ZPixmap, 0, &segmentInfo, w, h); + xImage = XShmCreateImage (display, visual, 24, ZPixmap, 0, &segmentInfo, w, h); - if (xImage != 0) - { - if ((segmentInfo.shmid = shmget (IPC_PRIVATE, - xImage->bytes_per_line * xImage->height, - IPC_CREAT | 0777)) >= 0) - { - segmentInfo.shmaddr = (char*) shmat (segmentInfo.shmid, 0, 0); + if (xImage != 0) + { + if ((segmentInfo.shmid = shmget (IPC_PRIVATE, + xImage->bytes_per_line * xImage->height, + IPC_CREAT | 0777)) >= 0) + { + segmentInfo.shmaddr = (char*) shmat (segmentInfo.shmid, 0, 0); - if (segmentInfo.shmaddr != (void*) -1) - { - segmentInfo.readOnly = False; + if (segmentInfo.shmaddr != (void*) -1) + { + segmentInfo.readOnly = False; - xImage->data = segmentInfo.shmaddr; - imageData = (uint8*) segmentInfo.shmaddr; + xImage->data = segmentInfo.shmaddr; + imageData = (uint8*) segmentInfo.shmaddr; - XSync (display, False); + XSync (display, False); - if (XShmAttach (display, &segmentInfo) != 0) - { - XSync (display, False); - usingXShm = true; - } - else - { - jassertfalse - } - } - else - { - shmctl (segmentInfo.shmid, IPC_RMID, 0); - } - } - } - } + if (XShmAttach (display, &segmentInfo) != 0) + { + XSync (display, False); + usingXShm = true; + } + else + { + jassertfalse + } + } + else + { + shmctl (segmentInfo.shmid, IPC_RMID, 0); + } + } + } + } - if (! usingXShm) + if (! usingXShm) #endif - { - imageDataAllocated.malloc (lineStride * h); - imageData = imageDataAllocated; + { + imageDataAllocated.malloc (lineStride * h); + imageData = imageDataAllocated; - if (format_ == ARGB && clearImage) - zeromem (imageData, h * lineStride); + if (format_ == ARGB && clearImage) + zeromem (imageData, h * lineStride); - xImage = (XImage*) juce_calloc (sizeof (XImage)); + xImage = (XImage*) juce_calloc (sizeof (XImage)); - xImage->width = w; - xImage->height = h; - xImage->xoffset = 0; - xImage->format = ZPixmap; - xImage->data = (char*) imageData; - xImage->byte_order = ImageByteOrder (display); - xImage->bitmap_unit = BitmapUnit (display); - xImage->bitmap_bit_order = BitmapBitOrder (display); - xImage->bitmap_pad = 32; - xImage->depth = pixelStride * 8; - xImage->bytes_per_line = lineStride; - xImage->bits_per_pixel = pixelStride * 8; - xImage->red_mask = 0x00FF0000; - xImage->green_mask = 0x0000FF00; - xImage->blue_mask = 0x000000FF; + xImage->width = w; + xImage->height = h; + xImage->xoffset = 0; + xImage->format = ZPixmap; + xImage->data = (char*) imageData; + xImage->byte_order = ImageByteOrder (display); + xImage->bitmap_unit = BitmapUnit (display); + xImage->bitmap_bit_order = BitmapBitOrder (display); + xImage->bitmap_pad = 32; + xImage->depth = pixelStride * 8; + xImage->bytes_per_line = lineStride; + xImage->bits_per_pixel = pixelStride * 8; + xImage->red_mask = 0x00FF0000; + xImage->green_mask = 0x0000FF00; + xImage->blue_mask = 0x000000FF; - if (is16Bit) - { - const int pixelStride = 2; - const int lineStride = ((w * pixelStride + 3) & ~3); + if (is16Bit) + { + const int pixelStride = 2; + const int lineStride = ((w * pixelStride + 3) & ~3); - imageData16Bit.malloc (lineStride * h); - xImage->data = imageData16Bit; - xImage->bitmap_pad = 16; - xImage->depth = pixelStride * 8; - xImage->bytes_per_line = lineStride; - xImage->bits_per_pixel = pixelStride * 8; - xImage->red_mask = visual->red_mask; - xImage->green_mask = visual->green_mask; - xImage->blue_mask = visual->blue_mask; - } + imageData16Bit.malloc (lineStride * h); + xImage->data = imageData16Bit; + xImage->bitmap_pad = 16; + xImage->depth = pixelStride * 8; + xImage->bytes_per_line = lineStride; + xImage->bits_per_pixel = pixelStride * 8; + xImage->red_mask = visual->red_mask; + xImage->green_mask = visual->green_mask; + xImage->blue_mask = visual->blue_mask; + } - if (! XInitImage (xImage)) - { - jassertfalse - } - } - } + if (! XInitImage (xImage)) + { + jassertfalse + } + } + } - ~XBitmapImage() - { + ~XBitmapImage() + { #if JUCE_USE_XSHM - if (usingXShm) - { - XShmDetach (display, &segmentInfo); + if (usingXShm) + { + XShmDetach (display, &segmentInfo); - XFlush (display); - XDestroyImage (xImage); + XFlush (display); + XDestroyImage (xImage); - shmdt (segmentInfo.shmaddr); - shmctl (segmentInfo.shmid, IPC_RMID, 0); - } - else + shmdt (segmentInfo.shmaddr); + shmctl (segmentInfo.shmid, IPC_RMID, 0); + } + else #endif - { - xImage->data = 0; - XDestroyImage (xImage); - } - } + { + xImage->data = 0; + XDestroyImage (xImage); + } + } - void blitToWindow (Window window, int dx, int dy, int dw, int dh, int sx, int sy) - { - static GC gc = 0; + void blitToWindow (Window window, int dx, int dy, int dw, int dh, int sx, int sy) + { + static GC gc = 0; - if (gc == 0) - gc = DefaultGC (display, DefaultScreen (display)); + if (gc == 0) + gc = DefaultGC (display, DefaultScreen (display)); - if (is16Bit) - { - const uint32 rMask = xImage->red_mask; - const uint32 rShiftL = jmax (0, getShiftNeeded (rMask)); - const uint32 rShiftR = jmax (0, -getShiftNeeded (rMask)); - const uint32 gMask = xImage->green_mask; - const uint32 gShiftL = jmax (0, getShiftNeeded (gMask)); - const uint32 gShiftR = jmax (0, -getShiftNeeded (gMask)); - const uint32 bMask = xImage->blue_mask; - const uint32 bShiftL = jmax (0, getShiftNeeded (bMask)); - const uint32 bShiftR = jmax (0, -getShiftNeeded (bMask)); + if (is16Bit) + { + const uint32 rMask = xImage->red_mask; + const uint32 rShiftL = jmax (0, getShiftNeeded (rMask)); + const uint32 rShiftR = jmax (0, -getShiftNeeded (rMask)); + const uint32 gMask = xImage->green_mask; + const uint32 gShiftL = jmax (0, getShiftNeeded (gMask)); + const uint32 gShiftR = jmax (0, -getShiftNeeded (gMask)); + const uint32 bMask = xImage->blue_mask; + const uint32 bShiftL = jmax (0, getShiftNeeded (bMask)); + const uint32 bShiftR = jmax (0, -getShiftNeeded (bMask)); - const Image::BitmapData srcData (*this, 0, 0, getWidth(), getHeight()); + const Image::BitmapData srcData (*this, 0, 0, getWidth(), getHeight()); - for (int y = sy; y < sy + dh; ++y) - { - const uint8* p = srcData.getPixelPointer (sx, y); + for (int y = sy; y < sy + dh; ++y) + { + const uint8* p = srcData.getPixelPointer (sx, y); - for (int x = sx; x < sx + dw; ++x) - { - const PixelRGB* const pixel = (const PixelRGB*) p; - p += srcData.pixelStride; + for (int x = sx; x < sx + dw; ++x) + { + const PixelRGB* const pixel = (const PixelRGB*) p; + p += srcData.pixelStride; - XPutPixel (xImage, x, y, - (((((uint32) pixel->getRed()) << rShiftL) >> rShiftR) & rMask) - | (((((uint32) pixel->getGreen()) << gShiftL) >> gShiftR) & gMask) - | (((((uint32) pixel->getBlue()) << bShiftL) >> bShiftR) & bMask)); - } - } - } + XPutPixel (xImage, x, y, + (((((uint32) pixel->getRed()) << rShiftL) >> rShiftR) & rMask) + | (((((uint32) pixel->getGreen()) << gShiftL) >> gShiftR) & gMask) + | (((((uint32) pixel->getBlue()) << bShiftL) >> bShiftR) & bMask)); + } + } + } - // blit results to screen. + // blit results to screen. #if JUCE_USE_XSHM - if (usingXShm) - XShmPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh, True); - else + if (usingXShm) + XShmPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh, True); + else #endif - XPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh); - } + XPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - XImage* xImage; - const bool is16Bit; - HeapBlock imageData16Bit; + XImage* xImage; + const bool is16Bit; + HeapBlock imageData16Bit; #if JUCE_USE_XSHM - XShmSegmentInfo segmentInfo; - bool usingXShm; + XShmSegmentInfo segmentInfo; + bool usingXShm; #endif - static int getShiftNeeded (const uint32 mask) throw() - { - for (int i = 32; --i >= 0;) - if (((mask >> i) & 1) != 0) - return i - 7; + static int getShiftNeeded (const uint32 mask) throw() + { + for (int i = 32; --i >= 0;) + if (((mask >> i) & 1) != 0) + return i - 7; - jassertfalse - return 0; - } + jassertfalse + return 0; + } }; -#define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); +#define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); class LinuxComponentPeer : public ComponentPeer { public: - LinuxComponentPeer (Component* const component, const int windowStyleFlags) - : ComponentPeer (component, windowStyleFlags), - windowH (0), - parentWindow (0), - wx (0), - wy (0), - ww (0), - wh (0), - taskbarImage (0), - fullScreen (false), - entered (false), - mapped (false) - { - // it's dangerous to create a window on a thread other than the message thread.. - checkMessageManagerIsLocked - - repainter = new LinuxRepaintManager (this); - - createWindow(); - - setTitle (component->getName()); - } - - ~LinuxComponentPeer() - { - // it's dangerous to delete a window on a thread other than the message thread.. - checkMessageManagerIsLocked - - deleteTaskBarIcon(); - deleteIconPixmaps(); - - destroyWindow(); - - windowH = 0; - } - - void* getNativeHandle() const - { - return (void*) windowH; - } - - static LinuxComponentPeer* getPeerFor (Window windowHandle) throw() - { - XPointer peer = 0; - - if (! XFindContext (display, (XID) windowHandle, improbableNumber, &peer)) - { - if (peer != 0 && ! ((LinuxComponentPeer*) peer)->isValidMessageListener()) - peer = 0; - } - - return (LinuxComponentPeer*) peer; - } - - void setVisible (bool shouldBeVisible) - { - if (shouldBeVisible) - XMapWindow (display, windowH); - else - XUnmapWindow (display, windowH); - } - - void setTitle (const String& title) - { - setWindowTitle (windowH, title); - } - - void setPosition (int x, int y) - { - setBounds (x, y, ww, wh, false); - } - - void setSize (int w, int h) - { - setBounds (wx, wy, w, h, false); - } - - void setBounds (int x, int y, int w, int h, const bool isNowFullScreen) - { - fullScreen = isNowFullScreen; - - if (windowH != 0) - { - const ComponentDeletionWatcher deletionChecker (component); - - wx = x; - wy = y; - ww = jmax (1, w); - wh = jmax (1, h); - - // Make sure the Window manager does what we want - XSizeHints* hints = XAllocSizeHints(); - hints->flags = USSize | USPosition; - hints->width = ww; - hints->height = wh; - hints->x = wx; - hints->y = wy; - - if ((getStyleFlags() & (windowHasTitleBar | windowIsResizable)) == windowHasTitleBar) - { - hints->min_width = hints->max_width = hints->width; - hints->min_height = hints->max_height = hints->height; - hints->flags |= PMinSize | PMaxSize; - } - - XSetWMNormalHints (display, windowH, hints); - XFree (hints); - - XMoveResizeWindow (display, windowH, - wx - windowBorder.getLeft(), - wy - windowBorder.getTop(), ww, wh); - - if (! deletionChecker.hasBeenDeleted()) - { - updateBorderSize(); - handleMovedOrResized(); - } - } - } - - void getBounds (int& x, int& y, int& w, int& h) const - { - x = wx; - y = wy; - w = ww; - h = wh; - } - - int getScreenX() const - { - return wx; - } - - int getScreenY() const - { - return wy; - } - - void relativePositionToGlobal (int& x, int& y) - { - x += wx; - y += wy; - } - - void globalPositionToRelative (int& x, int& y) - { - x -= wx; - y -= wy; - } - - void setMinimised (bool shouldBeMinimised) - { - if (shouldBeMinimised) - { - Window root = RootWindow (display, DefaultScreen (display)); - - XClientMessageEvent clientMsg; - clientMsg.display = display; - clientMsg.window = windowH; - clientMsg.type = ClientMessage; - clientMsg.format = 32; - clientMsg.message_type = wm_ChangeState; - clientMsg.data.l[0] = IconicState; - - XSendEvent (display, root, false, - SubstructureRedirectMask | SubstructureNotifyMask, - (XEvent*) &clientMsg); - } - else - { - setVisible (true); - } - } - - bool isMinimised() const - { - bool minimised = false; - - unsigned char* stateProp; - unsigned long nitems, bytesLeft; - Atom actualType; - int actualFormat; - - if (XGetWindowProperty (display, windowH, wm_State, 0, 64, False, - wm_State, &actualType, &actualFormat, &nitems, &bytesLeft, - &stateProp) == Success - && actualType == wm_State - && actualFormat == 32 - && nitems > 0) - { - if (((unsigned long*) stateProp)[0] == IconicState) - minimised = true; - - XFree (stateProp); - } - - return minimised; - } - - void setFullScreen (const bool shouldBeFullScreen) - { - Rectangle r (lastNonFullscreenBounds); // (get a copy of this before de-minimising) - - setMinimised (false); - - if (fullScreen != shouldBeFullScreen) - { - if (shouldBeFullScreen) - r = Desktop::getInstance().getMainMonitorArea(); - - if (! r.isEmpty()) - setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen); - - getComponent()->repaint(); - } - } - - bool isFullScreen() const - { - return fullScreen; - } - - bool isChildWindowOf (Window possibleParent) const - { - Window* windowList = 0; - uint32 windowListSize = 0; - Window parent, root; - - if (XQueryTree (display, windowH, &root, &parent, &windowList, &windowListSize) != 0) - { - if (windowList != 0) - XFree (windowList); - - return parent == possibleParent; - } - - return false; - } - - bool isFrontWindow() const - { - Window* windowList = 0; - uint32 windowListSize = 0; - bool result = false; - - Window parent, root = RootWindow (display, DefaultScreen (display)); - - if (XQueryTree (display, root, &root, &parent, &windowList, &windowListSize) != 0) - { - for (int i = windowListSize; --i >= 0;) - { - LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (windowList[i]); - - if (peer != 0) - { - result = (peer == this); - break; - } - } - } - - if (windowList != 0) - XFree (windowList); - - return result; - } - - bool contains (int x, int y, bool trueIfInAChildWindow) const - { - jassert (x >= 0 && y >= 0 && x < ww && y < wh); // should only be called for points that are actually inside the bounds - - if (((unsigned int) x) >= (unsigned int) ww - || ((unsigned int) y) >= (unsigned int) wh) - return false; - - bool inFront = false; - - for (int i = 0; i < Desktop::getInstance().getNumComponents(); ++i) - { - Component* const c = Desktop::getInstance().getComponent (i); - - if (inFront) - { - if (c->contains (x + wx - c->getScreenX(), - y + wy - c->getScreenY())) - { - return false; - } - } - else if (c == getComponent()) - { - inFront = true; - } - } - - if (trueIfInAChildWindow) - return true; - - ::Window root, child; - unsigned int bw, depth; - int wx, wy, w, h; - - if (! XGetGeometry (display, (::Drawable) windowH, &root, - &wx, &wy, (unsigned int*) &w, (unsigned int*) &h, - &bw, &depth)) - { - return false; - } - - if (! XTranslateCoordinates (display, windowH, windowH, x, y, &wx, &wy, &child)) - return false; - - return child == None; - } - - const BorderSize getFrameSize() const - { - return BorderSize(); - } - - bool setAlwaysOnTop (bool alwaysOnTop) - { - if (windowH != 0) - { - const bool wasVisible = component->isVisible(); - - if (wasVisible) - setVisible (false); // doesn't always seem to work if the window is visible when this is done.. - - XSetWindowAttributes swa; - swa.override_redirect = alwaysOnTop ? True : False; - - XChangeWindowAttributes (display, windowH, CWOverrideRedirect, &swa); - - if (wasVisible) - setVisible (true); - } - - return true; - } - - void toFront (bool makeActive) - { - if (makeActive) - { - setVisible (true); - grabFocus(); - } - - XEvent ev; - ev.xclient.type = ClientMessage; - ev.xclient.serial = 0; - ev.xclient.send_event = True; - ev.xclient.message_type = wm_ActiveWin; - ev.xclient.window = windowH; - ev.xclient.format = 32; - ev.xclient.data.l[0] = 2; - ev.xclient.data.l[1] = CurrentTime; - ev.xclient.data.l[2] = 0; - ev.xclient.data.l[3] = 0; - ev.xclient.data.l[4] = 0; - - XSendEvent (display, RootWindow (display, DefaultScreen (display)), - False, - SubstructureRedirectMask | SubstructureNotifyMask, - &ev); - - XWindowAttributes attr; - XGetWindowAttributes (display, windowH, &attr); - - if (attr.override_redirect) - XRaiseWindow (display, windowH); - - XSync (display, False); - - handleBroughtToFront(); - } - - void toBehind (ComponentPeer* other) - { - LinuxComponentPeer* const otherPeer = dynamic_cast (other); - jassert (otherPeer != 0); // wrong type of window? - - if (otherPeer != 0) - { - setMinimised (false); - - Window newStack[] = { otherPeer->windowH, windowH }; - - XRestackWindows (display, newStack, 2); - } - } - - bool isFocused() const - { - int revert; - Window focusedWindow = 0; - XGetInputFocus (display, &focusedWindow, &revert); - - return focusedWindow == windowH; - } - - void grabFocus() - { - XWindowAttributes atts; - - if (windowH != 0 - && XGetWindowAttributes (display, windowH, &atts) - && atts.map_state == IsViewable - && ! isFocused()) - { - XSetInputFocus (display, windowH, RevertToParent, CurrentTime); - isActiveApplication = true; - } - } - - void textInputRequired (int /*x*/, int /*y*/) - { - } - - void repaint (int x, int y, int w, int h) - { - if (Rectangle::intersectRectangles (x, y, w, h, - 0, 0, - getComponent()->getWidth(), - getComponent()->getHeight())) - { - repainter->repaint (x, y, w, h); - } - } - - void performAnyPendingRepaintsNow() - { - repainter->performAnyPendingRepaintsNow(); - } - - void setIcon (const Image& newIcon) - { - const int dataSize = newIcon.getWidth() * newIcon.getHeight() + 2; - HeapBlock data (dataSize); - - int index = 0; - data[index++] = newIcon.getWidth(); - data[index++] = newIcon.getHeight(); - - for (int y = 0; y < newIcon.getHeight(); ++y) - for (int x = 0; x < newIcon.getWidth(); ++x) - data[index++] = newIcon.getPixelAt (x, y).getARGB(); - - XChangeProperty (display, windowH, - XInternAtom (display, "_NET_WM_ICON", False), - XA_CARDINAL, 32, PropModeReplace, - (unsigned char*) data, dataSize); - - deleteIconPixmaps(); - - XWMHints* wmHints = XGetWMHints (display, windowH); - - if (wmHints == 0) - wmHints = XAllocWMHints(); - - wmHints->flags |= IconPixmapHint | IconMaskHint; - wmHints->icon_pixmap = juce_createColourPixmapFromImage (display, newIcon); - wmHints->icon_mask = juce_createMaskPixmapFromImage (display, newIcon); - - XSetWMHints (display, windowH, wmHints); - XFree (wmHints); - - XSync (display, False); - } - - void deleteIconPixmaps() - { - XWMHints* wmHints = XGetWMHints (display, windowH); - - if (wmHints != 0) - { - if ((wmHints->flags & IconPixmapHint) != 0) - { - wmHints->flags &= ~IconPixmapHint; - XFreePixmap (display, wmHints->icon_pixmap); - } - - if ((wmHints->flags & IconMaskHint) != 0) - { - wmHints->flags &= ~IconMaskHint; - XFreePixmap (display, wmHints->icon_mask); - } - - XSetWMHints (display, windowH, wmHints); - XFree (wmHints); - } - } - - void handleWindowMessage (XEvent* event) - { - switch (event->xany.type) - { - case 2: // 'KeyPress' - { - XKeyEvent* const keyEvent = (XKeyEvent*) &event->xkey; - updateKeyStates (keyEvent->keycode, true); - - char utf8 [64]; - zeromem (utf8, sizeof (utf8)); - KeySym sym; - XLookupString (keyEvent, utf8, sizeof (utf8), &sym, 0); - - const juce_wchar unicodeChar = *(const juce_wchar*) String::fromUTF8 ((const uint8*) utf8, sizeof (utf8) - 1); - int keyCode = (int) unicodeChar; - - if (keyCode < 0x20) - keyCode = XKeycodeToKeysym (display, keyEvent->keycode, - (currentModifiers & ModifierKeys::shiftModifier) != 0 ? 1 : 0); - - const int oldMods = currentModifiers; - bool keyPressed = false; - - const bool keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, true); - - if ((sym & 0xff00) == 0xff00) - { - // Translate keypad - if (sym == XK_KP_Divide) - keyCode = XK_slash; - else if (sym == XK_KP_Multiply) - keyCode = XK_asterisk; - else if (sym == XK_KP_Subtract) - keyCode = XK_hyphen; - else if (sym == XK_KP_Add) - keyCode = XK_plus; - else if (sym == XK_KP_Enter) - keyCode = XK_Return; - else if (sym == XK_KP_Decimal) - keyCode = numLock ? XK_period : XK_Delete; - else if (sym == XK_KP_0) - keyCode = numLock ? XK_0 : XK_Insert; - else if (sym == XK_KP_1) - keyCode = numLock ? XK_1 : XK_End; - else if (sym == XK_KP_2) - keyCode = numLock ? XK_2 : XK_Down; - else if (sym == XK_KP_3) - keyCode = numLock ? XK_3 : XK_Page_Down; - else if (sym == XK_KP_4) - keyCode = numLock ? XK_4 : XK_Left; - else if (sym == XK_KP_5) - keyCode = XK_5; - else if (sym == XK_KP_6) - keyCode = numLock ? XK_6 : XK_Right; - else if (sym == XK_KP_7) - keyCode = numLock ? XK_7 : XK_Home; - else if (sym == XK_KP_8) - keyCode = numLock ? XK_8 : XK_Up; - else if (sym == XK_KP_9) - keyCode = numLock ? XK_9 : XK_Page_Up; - - switch (sym) - { - case XK_Left: - case XK_Right: - case XK_Up: - case XK_Down: - case XK_Page_Up: - case XK_Page_Down: - case XK_End: - case XK_Home: - case XK_Delete: - case XK_Insert: - keyPressed = true; - keyCode = (sym & 0xff) | extendedKeyModifier; - break; - case XK_Tab: - case XK_Return: - case XK_Escape: - case XK_BackSpace: - keyPressed = true; - keyCode &= 0xff; - break; - default: - { - if (sym >= XK_F1 && sym <= XK_F16) - { - keyPressed = true; - keyCode = (sym & 0xff) | extendedKeyModifier; - } - break; - } - } - } - - if (utf8[0] != 0 || ((sym & 0xff00) == 0 && sym >= 8)) - keyPressed = true; - - if (oldMods != currentModifiers) - handleModifierKeysChange(); - - if (keyDownChange) - handleKeyUpOrDown (true); - - if (keyPressed) - handleKeyPress (keyCode, unicodeChar); - - break; - } - - case KeyRelease: - { - const XKeyEvent* const keyEvent = (const XKeyEvent*) &event->xkey; - updateKeyStates (keyEvent->keycode, false); - - KeySym sym = XKeycodeToKeysym (display, keyEvent->keycode, 0); - - const int oldMods = currentModifiers; - const bool keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, false); - - if (oldMods != currentModifiers) - handleModifierKeysChange(); - - if (keyDownChange) - handleKeyUpOrDown (false); - - break; - } - - case ButtonPress: - { - const XButtonPressedEvent* const buttonPressEvent = (const XButtonPressedEvent*) &event->xbutton; - - bool buttonMsg = false; - bool wheelUpMsg = false; - bool wheelDownMsg = false; - - const int map = pointerMap [buttonPressEvent->button - Button1]; - - if (map == LeftButton) - { - currentModifiers |= ModifierKeys::leftButtonModifier; - buttonMsg = true; - } - else if (map == RightButton) - { - currentModifiers |= ModifierKeys::rightButtonModifier; - buttonMsg = true; - } - else if (map == MiddleButton) - { - currentModifiers |= ModifierKeys::middleButtonModifier; - buttonMsg = true; - } - else if (map == WheelUp) - { - wheelUpMsg = true; - } - else if (map == WheelDown) - { - wheelDownMsg = true; - } - - updateKeyModifiers (buttonPressEvent->state); - - if (buttonMsg) - { - toFront (true); - handleMouseDown (buttonPressEvent->x, buttonPressEvent->y, - getEventTime (buttonPressEvent->time)); - } - else if (wheelUpMsg || wheelDownMsg) - { - handleMouseWheel (0, wheelDownMsg ? -84 : 84, - getEventTime (buttonPressEvent->time)); - } - - lastMousePosX = lastMousePosY = 0x100000; - break; - } - - case ButtonRelease: - { - const XButtonReleasedEvent* const buttonRelEvent = (const XButtonReleasedEvent*) &event->xbutton; - - const int oldModifiers = currentModifiers; - const int map = pointerMap [buttonRelEvent->button - Button1]; - - if (map == LeftButton) - currentModifiers &= ~ModifierKeys::leftButtonModifier; - else if (map == RightButton) - currentModifiers &= ~ModifierKeys::rightButtonModifier; - else if (map == MiddleButton) - currentModifiers &= ~ModifierKeys::middleButtonModifier; - - updateKeyModifiers (buttonRelEvent->state); - - handleMouseUp (oldModifiers, - buttonRelEvent->x, buttonRelEvent->y, - getEventTime (buttonRelEvent->time)); - - lastMousePosX = lastMousePosY = 0x100000; - break; - } - - case MotionNotify: - { - const XPointerMovedEvent* const movedEvent = (const XPointerMovedEvent*) &event->xmotion; - - updateKeyModifiers (movedEvent->state); - - int x, y, mouseMods; - getMousePos (x, y, mouseMods); - - if (lastMousePosX != x || lastMousePosY != y) - { - lastMousePosX = x; - lastMousePosY = y; - - if (parentWindow != 0 && (styleFlags & windowHasTitleBar) == 0) - { - Window wRoot = 0, wParent = 0; - Window* wChild = 0; - unsigned int numChildren; - XQueryTree (display, windowH, &wRoot, &wParent, &wChild, &numChildren); - - if (wParent != 0 - && wParent != windowH - && wParent != wRoot) - { - parentWindow = wParent; - updateBounds(); - x -= getScreenX(); - y -= getScreenY(); - } - else - { - parentWindow = 0; - x -= getScreenX(); - y -= getScreenY(); - } - } - else - { - x -= getScreenX(); - y -= getScreenY(); - } - - if ((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0) - handleMouseMove (x, y, getEventTime (movedEvent->time)); - else - handleMouseDrag (x, y, getEventTime (movedEvent->time)); - } - - break; - } - - case EnterNotify: - { - lastMousePosX = lastMousePosY = 0x100000; - const XEnterWindowEvent* const enterEvent = (const XEnterWindowEvent*) &event->xcrossing; - - if ((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0 - && ! entered) - { - updateKeyModifiers (enterEvent->state); - - handleMouseEnter (enterEvent->x, enterEvent->y, getEventTime (enterEvent->time)); - - entered = true; - } - - break; - } - - case LeaveNotify: - { - const XLeaveWindowEvent* const leaveEvent = (const XLeaveWindowEvent*) &event->xcrossing; - - // Suppress the normal leave if we've got a pointer grab, or if - // it's a bogus one caused by clicking a mouse button when running - // in a Window manager - if (((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0 - && leaveEvent->mode == NotifyNormal) - || leaveEvent->mode == NotifyUngrab) - { - updateKeyModifiers (leaveEvent->state); - - handleMouseExit (leaveEvent->x, leaveEvent->y, getEventTime (leaveEvent->time)); - - entered = false; - } - - break; - } - - case FocusIn: - { - isActiveApplication = true; - if (isFocused()) - handleFocusGain(); - - break; - } - - case FocusOut: - { - isActiveApplication = false; - if (! isFocused()) - handleFocusLoss(); - - break; - } - - case Expose: - { - // Batch together all pending expose events - XExposeEvent* exposeEvent = (XExposeEvent*) &event->xexpose; - XEvent nextEvent; - - if (exposeEvent->window != windowH) - { - Window child; - XTranslateCoordinates (display, exposeEvent->window, windowH, - exposeEvent->x, exposeEvent->y, &exposeEvent->x, &exposeEvent->y, - &child); - } - - repaint (exposeEvent->x, exposeEvent->y, - exposeEvent->width, exposeEvent->height); - - while (XEventsQueued (display, QueuedAfterFlush) > 0) - { - XPeekEvent (display, (XEvent*) &nextEvent); - if (nextEvent.type != Expose || nextEvent.xany.window != event->xany.window) - break; - - XNextEvent (display, (XEvent*) &nextEvent); - XExposeEvent* nextExposeEvent = (XExposeEvent*) &nextEvent.xexpose; - repaint (nextExposeEvent->x, nextExposeEvent->y, - nextExposeEvent->width, nextExposeEvent->height); - } - - break; - } - - case CirculateNotify: - case CreateNotify: - case DestroyNotify: - // Think we can ignore these - break; - - case ConfigureNotify: - { - updateBounds(); - updateBorderSize(); - handleMovedOrResized(); - - // if the native title bar is dragged, need to tell any active menus, etc. - if ((styleFlags & windowHasTitleBar) != 0 - && component->isCurrentlyBlockedByAnotherModalComponent()) - { - Component* const currentModalComp = Component::getCurrentlyModalComponent(); - - if (currentModalComp != 0) - currentModalComp->inputAttemptWhenModal(); - } - - XConfigureEvent* const confEvent = (XConfigureEvent*) &event->xconfigure; - - if (confEvent->window == windowH - && confEvent->above != 0 - && isFrontWindow()) - { - handleBroughtToFront(); - } - - break; - } - - case ReparentNotify: - case GravityNotify: - { - parentWindow = 0; - Window wRoot = 0; - Window* wChild = 0; - unsigned int numChildren; - XQueryTree (display, windowH, &wRoot, &parentWindow, &wChild, &numChildren); - - if (parentWindow == windowH || parentWindow == wRoot) - parentWindow = 0; - - updateBounds(); - updateBorderSize(); - handleMovedOrResized(); - break; - } - - case MapNotify: - mapped = true; - handleBroughtToFront(); - break; - - case UnmapNotify: - mapped = false; - break; - - case MappingNotify: - { - XMappingEvent* mappingEvent = (XMappingEvent*) &event->xmapping; - - if (mappingEvent->request != MappingPointer) - { - // Deal with modifier/keyboard mapping - XRefreshKeyboardMapping (mappingEvent); - getModifierMapping(); - } - - break; - } - - case ClientMessage: - { - const XClientMessageEvent* const clientMsg = (const XClientMessageEvent*) &event->xclient; - - if (clientMsg->message_type == wm_Protocols && clientMsg->format == 32) - { - const Atom atom = (Atom) clientMsg->data.l[0]; - - if (atom == wm_ProtocolList [TAKE_FOCUS]) - { - XWindowAttributes atts; - - if (clientMsg->window != 0 - && XGetWindowAttributes (display, clientMsg->window, &atts)) - { - if (atts.map_state == IsViewable) - XSetInputFocus (display, clientMsg->window, RevertToParent, clientMsg->data.l[1]); - } - } - else if (atom == wm_ProtocolList [DELETE_WINDOW]) - { - handleUserClosingWindow(); - } - } - else if (clientMsg->message_type == XA_XdndEnter) - { - handleDragAndDropEnter (clientMsg); - } - else if (clientMsg->message_type == XA_XdndLeave) - { - resetDragAndDrop(); - } - else if (clientMsg->message_type == XA_XdndPosition) - { - handleDragAndDropPosition (clientMsg); - } - else if (clientMsg->message_type == XA_XdndDrop) - { - handleDragAndDropDrop (clientMsg); - } - else if (clientMsg->message_type == XA_XdndStatus) - { - handleDragAndDropStatus (clientMsg); - } - else if (clientMsg->message_type == XA_XdndFinished) - { - resetDragAndDrop(); - } - - break; - } - - case SelectionNotify: - handleDragAndDropSelection (event); - break; - - case SelectionClear: - case SelectionRequest: - break; - - default: + LinuxComponentPeer (Component* const component, const int windowStyleFlags) + : ComponentPeer (component, windowStyleFlags), + windowH (0), + parentWindow (0), + wx (0), + wy (0), + ww (0), + wh (0), + taskbarImage (0), + fullScreen (false), + entered (false), + mapped (false) + { + // it's dangerous to create a window on a thread other than the message thread.. + checkMessageManagerIsLocked + + repainter = new LinuxRepaintManager (this); + + createWindow(); + + setTitle (component->getName()); + } + + ~LinuxComponentPeer() + { + // it's dangerous to delete a window on a thread other than the message thread.. + checkMessageManagerIsLocked + + deleteTaskBarIcon(); + deleteIconPixmaps(); + + destroyWindow(); + + windowH = 0; + } + + void* getNativeHandle() const + { + return (void*) windowH; + } + + static LinuxComponentPeer* getPeerFor (Window windowHandle) throw() + { + XPointer peer = 0; + + if (! XFindContext (display, (XID) windowHandle, improbableNumber, &peer)) + { + if (peer != 0 && ! ((LinuxComponentPeer*) peer)->isValidMessageListener()) + peer = 0; + } + + return (LinuxComponentPeer*) peer; + } + + void setVisible (bool shouldBeVisible) + { + if (shouldBeVisible) + XMapWindow (display, windowH); + else + XUnmapWindow (display, windowH); + } + + void setTitle (const String& title) + { + setWindowTitle (windowH, title); + } + + void setPosition (int x, int y) + { + setBounds (x, y, ww, wh, false); + } + + void setSize (int w, int h) + { + setBounds (wx, wy, w, h, false); + } + + void setBounds (int x, int y, int w, int h, const bool isNowFullScreen) + { + fullScreen = isNowFullScreen; + + if (windowH != 0) + { + const ComponentDeletionWatcher deletionChecker (component); + + wx = x; + wy = y; + ww = jmax (1, w); + wh = jmax (1, h); + + // Make sure the Window manager does what we want + XSizeHints* hints = XAllocSizeHints(); + hints->flags = USSize | USPosition; + hints->width = ww; + hints->height = wh; + hints->x = wx; + hints->y = wy; + + if ((getStyleFlags() & (windowHasTitleBar | windowIsResizable)) == windowHasTitleBar) + { + hints->min_width = hints->max_width = hints->width; + hints->min_height = hints->max_height = hints->height; + hints->flags |= PMinSize | PMaxSize; + } + + XSetWMNormalHints (display, windowH, hints); + XFree (hints); + + XMoveResizeWindow (display, windowH, + wx - windowBorder.getLeft(), + wy - windowBorder.getTop(), ww, wh); + + if (! deletionChecker.hasBeenDeleted()) + { + updateBorderSize(); + handleMovedOrResized(); + } + } + } + + void getBounds (int& x, int& y, int& w, int& h) const + { + x = wx; + y = wy; + w = ww; + h = wh; + } + + int getScreenX() const + { + return wx; + } + + int getScreenY() const + { + return wy; + } + + void relativePositionToGlobal (int& x, int& y) + { + x += wx; + y += wy; + } + + void globalPositionToRelative (int& x, int& y) + { + x -= wx; + y -= wy; + } + + void setMinimised (bool shouldBeMinimised) + { + if (shouldBeMinimised) + { + Window root = RootWindow (display, DefaultScreen (display)); + + XClientMessageEvent clientMsg; + clientMsg.display = display; + clientMsg.window = windowH; + clientMsg.type = ClientMessage; + clientMsg.format = 32; + clientMsg.message_type = wm_ChangeState; + clientMsg.data.l[0] = IconicState; + + XSendEvent (display, root, false, + SubstructureRedirectMask | SubstructureNotifyMask, + (XEvent*) &clientMsg); + } + else + { + setVisible (true); + } + } + + bool isMinimised() const + { + bool minimised = false; + + unsigned char* stateProp; + unsigned long nitems, bytesLeft; + Atom actualType; + int actualFormat; + + if (XGetWindowProperty (display, windowH, wm_State, 0, 64, False, + wm_State, &actualType, &actualFormat, &nitems, &bytesLeft, + &stateProp) == Success + && actualType == wm_State + && actualFormat == 32 + && nitems > 0) + { + if (((unsigned long*) stateProp)[0] == IconicState) + minimised = true; + + XFree (stateProp); + } + + return minimised; + } + + void setFullScreen (const bool shouldBeFullScreen) + { + Rectangle r (lastNonFullscreenBounds); // (get a copy of this before de-minimising) + + setMinimised (false); + + if (fullScreen != shouldBeFullScreen) + { + if (shouldBeFullScreen) + r = Desktop::getInstance().getMainMonitorArea(); + + if (! r.isEmpty()) + setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen); + + getComponent()->repaint(); + } + } + + bool isFullScreen() const + { + return fullScreen; + } + + bool isChildWindowOf (Window possibleParent) const + { + Window* windowList = 0; + uint32 windowListSize = 0; + Window parent, root; + + if (XQueryTree (display, windowH, &root, &parent, &windowList, &windowListSize) != 0) + { + if (windowList != 0) + XFree (windowList); + + return parent == possibleParent; + } + + return false; + } + + bool isFrontWindow() const + { + Window* windowList = 0; + uint32 windowListSize = 0; + bool result = false; + + Window parent, root = RootWindow (display, DefaultScreen (display)); + + if (XQueryTree (display, root, &root, &parent, &windowList, &windowListSize) != 0) + { + for (int i = windowListSize; --i >= 0;) + { + LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (windowList[i]); + + if (peer != 0) + { + result = (peer == this); + break; + } + } + } + + if (windowList != 0) + XFree (windowList); + + return result; + } + + bool contains (int x, int y, bool trueIfInAChildWindow) const + { + jassert (x >= 0 && y >= 0 && x < ww && y < wh); // should only be called for points that are actually inside the bounds + + if (((unsigned int) x) >= (unsigned int) ww + || ((unsigned int) y) >= (unsigned int) wh) + return false; + + bool inFront = false; + + for (int i = 0; i < Desktop::getInstance().getNumComponents(); ++i) + { + Component* const c = Desktop::getInstance().getComponent (i); + + if (inFront) + { + if (c->contains (x + wx - c->getScreenX(), + y + wy - c->getScreenY())) + { + return false; + } + } + else if (c == getComponent()) + { + inFront = true; + } + } + + if (trueIfInAChildWindow) + return true; + + ::Window root, child; + unsigned int bw, depth; + int wx, wy, w, h; + + if (! XGetGeometry (display, (::Drawable) windowH, &root, + &wx, &wy, (unsigned int*) &w, (unsigned int*) &h, + &bw, &depth)) + { + return false; + } + + if (! XTranslateCoordinates (display, windowH, windowH, x, y, &wx, &wy, &child)) + return false; + + return child == None; + } + + const BorderSize getFrameSize() const + { + return BorderSize(); + } + + bool setAlwaysOnTop (bool alwaysOnTop) + { + if (windowH != 0) + { + const bool wasVisible = component->isVisible(); + + if (wasVisible) + setVisible (false); // doesn't always seem to work if the window is visible when this is done.. + + XSetWindowAttributes swa; + swa.override_redirect = alwaysOnTop ? True : False; + + XChangeWindowAttributes (display, windowH, CWOverrideRedirect, &swa); + + if (wasVisible) + setVisible (true); + } + + return true; + } + + void toFront (bool makeActive) + { + if (makeActive) + { + setVisible (true); + grabFocus(); + } + + XEvent ev; + ev.xclient.type = ClientMessage; + ev.xclient.serial = 0; + ev.xclient.send_event = True; + ev.xclient.message_type = wm_ActiveWin; + ev.xclient.window = windowH; + ev.xclient.format = 32; + ev.xclient.data.l[0] = 2; + ev.xclient.data.l[1] = CurrentTime; + ev.xclient.data.l[2] = 0; + ev.xclient.data.l[3] = 0; + ev.xclient.data.l[4] = 0; + + XSendEvent (display, RootWindow (display, DefaultScreen (display)), + False, + SubstructureRedirectMask | SubstructureNotifyMask, + &ev); + + XWindowAttributes attr; + XGetWindowAttributes (display, windowH, &attr); + + if (attr.override_redirect) + XRaiseWindow (display, windowH); + + XSync (display, False); + + handleBroughtToFront(); + } + + void toBehind (ComponentPeer* other) + { + LinuxComponentPeer* const otherPeer = dynamic_cast (other); + jassert (otherPeer != 0); // wrong type of window? + + if (otherPeer != 0) + { + setMinimised (false); + + Window newStack[] = { otherPeer->windowH, windowH }; + + XRestackWindows (display, newStack, 2); + } + } + + bool isFocused() const + { + int revert; + Window focusedWindow = 0; + XGetInputFocus (display, &focusedWindow, &revert); + + return focusedWindow == windowH; + } + + void grabFocus() + { + XWindowAttributes atts; + + if (windowH != 0 + && XGetWindowAttributes (display, windowH, &atts) + && atts.map_state == IsViewable + && ! isFocused()) + { + XSetInputFocus (display, windowH, RevertToParent, CurrentTime); + isActiveApplication = true; + } + } + + void textInputRequired (int /*x*/, int /*y*/) + { + } + + void repaint (int x, int y, int w, int h) + { + if (Rectangle::intersectRectangles (x, y, w, h, + 0, 0, + getComponent()->getWidth(), + getComponent()->getHeight())) + { + repainter->repaint (x, y, w, h); + } + } + + void performAnyPendingRepaintsNow() + { + repainter->performAnyPendingRepaintsNow(); + } + + void setIcon (const Image& newIcon) + { + const int dataSize = newIcon.getWidth() * newIcon.getHeight() + 2; + HeapBlock data (dataSize); + + int index = 0; + data[index++] = newIcon.getWidth(); + data[index++] = newIcon.getHeight(); + + for (int y = 0; y < newIcon.getHeight(); ++y) + for (int x = 0; x < newIcon.getWidth(); ++x) + data[index++] = newIcon.getPixelAt (x, y).getARGB(); + + XChangeProperty (display, windowH, + XInternAtom (display, "_NET_WM_ICON", False), + XA_CARDINAL, 32, PropModeReplace, + (unsigned char*) data, dataSize); + + deleteIconPixmaps(); + + XWMHints* wmHints = XGetWMHints (display, windowH); + + if (wmHints == 0) + wmHints = XAllocWMHints(); + + wmHints->flags |= IconPixmapHint | IconMaskHint; + wmHints->icon_pixmap = juce_createColourPixmapFromImage (display, newIcon); + wmHints->icon_mask = juce_createMaskPixmapFromImage (display, newIcon); + + XSetWMHints (display, windowH, wmHints); + XFree (wmHints); + + XSync (display, False); + } + + void deleteIconPixmaps() + { + XWMHints* wmHints = XGetWMHints (display, windowH); + + if (wmHints != 0) + { + if ((wmHints->flags & IconPixmapHint) != 0) + { + wmHints->flags &= ~IconPixmapHint; + XFreePixmap (display, wmHints->icon_pixmap); + } + + if ((wmHints->flags & IconMaskHint) != 0) + { + wmHints->flags &= ~IconMaskHint; + XFreePixmap (display, wmHints->icon_mask); + } + + XSetWMHints (display, windowH, wmHints); + XFree (wmHints); + } + } + + void handleWindowMessage (XEvent* event) + { + switch (event->xany.type) + { + case 2: // 'KeyPress' + { + XKeyEvent* const keyEvent = (XKeyEvent*) &event->xkey; + updateKeyStates (keyEvent->keycode, true); + + char utf8 [64]; + zeromem (utf8, sizeof (utf8)); + KeySym sym; + XLookupString (keyEvent, utf8, sizeof (utf8), &sym, 0); + + const juce_wchar unicodeChar = *(const juce_wchar*) String::fromUTF8 ((const uint8*) utf8, sizeof (utf8) - 1); + int keyCode = (int) unicodeChar; + + if (keyCode < 0x20) + keyCode = XKeycodeToKeysym (display, keyEvent->keycode, + (currentModifiers & ModifierKeys::shiftModifier) != 0 ? 1 : 0); + + const int oldMods = currentModifiers; + bool keyPressed = false; + + const bool keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, true); + + if ((sym & 0xff00) == 0xff00) + { + // Translate keypad + if (sym == XK_KP_Divide) + keyCode = XK_slash; + else if (sym == XK_KP_Multiply) + keyCode = XK_asterisk; + else if (sym == XK_KP_Subtract) + keyCode = XK_hyphen; + else if (sym == XK_KP_Add) + keyCode = XK_plus; + else if (sym == XK_KP_Enter) + keyCode = XK_Return; + else if (sym == XK_KP_Decimal) + keyCode = numLock ? XK_period : XK_Delete; + else if (sym == XK_KP_0) + keyCode = numLock ? XK_0 : XK_Insert; + else if (sym == XK_KP_1) + keyCode = numLock ? XK_1 : XK_End; + else if (sym == XK_KP_2) + keyCode = numLock ? XK_2 : XK_Down; + else if (sym == XK_KP_3) + keyCode = numLock ? XK_3 : XK_Page_Down; + else if (sym == XK_KP_4) + keyCode = numLock ? XK_4 : XK_Left; + else if (sym == XK_KP_5) + keyCode = XK_5; + else if (sym == XK_KP_6) + keyCode = numLock ? XK_6 : XK_Right; + else if (sym == XK_KP_7) + keyCode = numLock ? XK_7 : XK_Home; + else if (sym == XK_KP_8) + keyCode = numLock ? XK_8 : XK_Up; + else if (sym == XK_KP_9) + keyCode = numLock ? XK_9 : XK_Page_Up; + + switch (sym) + { + case XK_Left: + case XK_Right: + case XK_Up: + case XK_Down: + case XK_Page_Up: + case XK_Page_Down: + case XK_End: + case XK_Home: + case XK_Delete: + case XK_Insert: + keyPressed = true; + keyCode = (sym & 0xff) | extendedKeyModifier; + break; + case XK_Tab: + case XK_Return: + case XK_Escape: + case XK_BackSpace: + keyPressed = true; + keyCode &= 0xff; + break; + default: + { + if (sym >= XK_F1 && sym <= XK_F16) + { + keyPressed = true; + keyCode = (sym & 0xff) | extendedKeyModifier; + } + break; + } + } + } + + if (utf8[0] != 0 || ((sym & 0xff00) == 0 && sym >= 8)) + keyPressed = true; + + if (oldMods != currentModifiers) + handleModifierKeysChange(); + + if (keyDownChange) + handleKeyUpOrDown (true); + + if (keyPressed) + handleKeyPress (keyCode, unicodeChar); + + break; + } + + case KeyRelease: + { + const XKeyEvent* const keyEvent = (const XKeyEvent*) &event->xkey; + updateKeyStates (keyEvent->keycode, false); + + KeySym sym = XKeycodeToKeysym (display, keyEvent->keycode, 0); + + const int oldMods = currentModifiers; + const bool keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, false); + + if (oldMods != currentModifiers) + handleModifierKeysChange(); + + if (keyDownChange) + handleKeyUpOrDown (false); + + break; + } + + case ButtonPress: + { + const XButtonPressedEvent* const buttonPressEvent = (const XButtonPressedEvent*) &event->xbutton; + + bool buttonMsg = false; + bool wheelUpMsg = false; + bool wheelDownMsg = false; + + const int map = pointerMap [buttonPressEvent->button - Button1]; + + if (map == LeftButton) + { + currentModifiers |= ModifierKeys::leftButtonModifier; + buttonMsg = true; + } + else if (map == RightButton) + { + currentModifiers |= ModifierKeys::rightButtonModifier; + buttonMsg = true; + } + else if (map == MiddleButton) + { + currentModifiers |= ModifierKeys::middleButtonModifier; + buttonMsg = true; + } + else if (map == WheelUp) + { + wheelUpMsg = true; + } + else if (map == WheelDown) + { + wheelDownMsg = true; + } + + updateKeyModifiers (buttonPressEvent->state); + + if (buttonMsg) + { + toFront (true); + handleMouseDown (buttonPressEvent->x, buttonPressEvent->y, + getEventTime (buttonPressEvent->time)); + } + else if (wheelUpMsg || wheelDownMsg) + { + handleMouseWheel (0, wheelDownMsg ? -84 : 84, + getEventTime (buttonPressEvent->time)); + } + + lastMousePosX = lastMousePosY = 0x100000; + break; + } + + case ButtonRelease: + { + const XButtonReleasedEvent* const buttonRelEvent = (const XButtonReleasedEvent*) &event->xbutton; + + const int oldModifiers = currentModifiers; + const int map = pointerMap [buttonRelEvent->button - Button1]; + + if (map == LeftButton) + currentModifiers &= ~ModifierKeys::leftButtonModifier; + else if (map == RightButton) + currentModifiers &= ~ModifierKeys::rightButtonModifier; + else if (map == MiddleButton) + currentModifiers &= ~ModifierKeys::middleButtonModifier; + + updateKeyModifiers (buttonRelEvent->state); + + handleMouseUp (oldModifiers, + buttonRelEvent->x, buttonRelEvent->y, + getEventTime (buttonRelEvent->time)); + + lastMousePosX = lastMousePosY = 0x100000; + break; + } + + case MotionNotify: + { + const XPointerMovedEvent* const movedEvent = (const XPointerMovedEvent*) &event->xmotion; + + updateKeyModifiers (movedEvent->state); + + int x, y, mouseMods; + getMousePos (x, y, mouseMods); + + if (lastMousePosX != x || lastMousePosY != y) + { + lastMousePosX = x; + lastMousePosY = y; + + if (parentWindow != 0 && (styleFlags & windowHasTitleBar) == 0) + { + Window wRoot = 0, wParent = 0; + Window* wChild = 0; + unsigned int numChildren; + XQueryTree (display, windowH, &wRoot, &wParent, &wChild, &numChildren); + + if (wParent != 0 + && wParent != windowH + && wParent != wRoot) + { + parentWindow = wParent; + updateBounds(); + x -= getScreenX(); + y -= getScreenY(); + } + else + { + parentWindow = 0; + x -= getScreenX(); + y -= getScreenY(); + } + } + else + { + x -= getScreenX(); + y -= getScreenY(); + } + + if ((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0) + handleMouseMove (x, y, getEventTime (movedEvent->time)); + else + handleMouseDrag (x, y, getEventTime (movedEvent->time)); + } + + break; + } + + case EnterNotify: + { + lastMousePosX = lastMousePosY = 0x100000; + const XEnterWindowEvent* const enterEvent = (const XEnterWindowEvent*) &event->xcrossing; + + if ((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0 + && ! entered) + { + updateKeyModifiers (enterEvent->state); + + handleMouseEnter (enterEvent->x, enterEvent->y, getEventTime (enterEvent->time)); + + entered = true; + } + + break; + } + + case LeaveNotify: + { + const XLeaveWindowEvent* const leaveEvent = (const XLeaveWindowEvent*) &event->xcrossing; + + // Suppress the normal leave if we've got a pointer grab, or if + // it's a bogus one caused by clicking a mouse button when running + // in a Window manager + if (((currentModifiers & ModifierKeys::allMouseButtonModifiers) == 0 + && leaveEvent->mode == NotifyNormal) + || leaveEvent->mode == NotifyUngrab) + { + updateKeyModifiers (leaveEvent->state); + + handleMouseExit (leaveEvent->x, leaveEvent->y, getEventTime (leaveEvent->time)); + + entered = false; + } + + break; + } + + case FocusIn: + { + isActiveApplication = true; + if (isFocused()) + handleFocusGain(); + + break; + } + + case FocusOut: + { + isActiveApplication = false; + if (! isFocused()) + handleFocusLoss(); + + break; + } + + case Expose: + { + // Batch together all pending expose events + XExposeEvent* exposeEvent = (XExposeEvent*) &event->xexpose; + XEvent nextEvent; + + if (exposeEvent->window != windowH) + { + Window child; + XTranslateCoordinates (display, exposeEvent->window, windowH, + exposeEvent->x, exposeEvent->y, &exposeEvent->x, &exposeEvent->y, + &child); + } + + repaint (exposeEvent->x, exposeEvent->y, + exposeEvent->width, exposeEvent->height); + + while (XEventsQueued (display, QueuedAfterFlush) > 0) + { + XPeekEvent (display, (XEvent*) &nextEvent); + if (nextEvent.type != Expose || nextEvent.xany.window != event->xany.window) + break; + + XNextEvent (display, (XEvent*) &nextEvent); + XExposeEvent* nextExposeEvent = (XExposeEvent*) &nextEvent.xexpose; + repaint (nextExposeEvent->x, nextExposeEvent->y, + nextExposeEvent->width, nextExposeEvent->height); + } + + break; + } + + case CirculateNotify: + case CreateNotify: + case DestroyNotify: + // Think we can ignore these + break; + + case ConfigureNotify: + { + updateBounds(); + updateBorderSize(); + handleMovedOrResized(); + + // if the native title bar is dragged, need to tell any active menus, etc. + if ((styleFlags & windowHasTitleBar) != 0 + && component->isCurrentlyBlockedByAnotherModalComponent()) + { + Component* const currentModalComp = Component::getCurrentlyModalComponent(); + + if (currentModalComp != 0) + currentModalComp->inputAttemptWhenModal(); + } + + XConfigureEvent* const confEvent = (XConfigureEvent*) &event->xconfigure; + + if (confEvent->window == windowH + && confEvent->above != 0 + && isFrontWindow()) + { + handleBroughtToFront(); + } + + break; + } + + case ReparentNotify: + case GravityNotify: + { + parentWindow = 0; + Window wRoot = 0; + Window* wChild = 0; + unsigned int numChildren; + XQueryTree (display, windowH, &wRoot, &parentWindow, &wChild, &numChildren); + + if (parentWindow == windowH || parentWindow == wRoot) + parentWindow = 0; + + updateBounds(); + updateBorderSize(); + handleMovedOrResized(); + break; + } + + case MapNotify: + mapped = true; + handleBroughtToFront(); + break; + + case UnmapNotify: + mapped = false; + break; + + case MappingNotify: + { + XMappingEvent* mappingEvent = (XMappingEvent*) &event->xmapping; + + if (mappingEvent->request != MappingPointer) + { + // Deal with modifier/keyboard mapping + XRefreshKeyboardMapping (mappingEvent); + getModifierMapping(); + } + + break; + } + + case ClientMessage: + { + const XClientMessageEvent* const clientMsg = (const XClientMessageEvent*) &event->xclient; + + if (clientMsg->message_type == wm_Protocols && clientMsg->format == 32) + { + const Atom atom = (Atom) clientMsg->data.l[0]; + + if (atom == wm_ProtocolList [TAKE_FOCUS]) + { + XWindowAttributes atts; + + if (clientMsg->window != 0 + && XGetWindowAttributes (display, clientMsg->window, &atts)) + { + if (atts.map_state == IsViewable) + XSetInputFocus (display, clientMsg->window, RevertToParent, clientMsg->data.l[1]); + } + } + else if (atom == wm_ProtocolList [DELETE_WINDOW]) + { + handleUserClosingWindow(); + } + } + else if (clientMsg->message_type == XA_XdndEnter) + { + handleDragAndDropEnter (clientMsg); + } + else if (clientMsg->message_type == XA_XdndLeave) + { + resetDragAndDrop(); + } + else if (clientMsg->message_type == XA_XdndPosition) + { + handleDragAndDropPosition (clientMsg); + } + else if (clientMsg->message_type == XA_XdndDrop) + { + handleDragAndDropDrop (clientMsg); + } + else if (clientMsg->message_type == XA_XdndStatus) + { + handleDragAndDropStatus (clientMsg); + } + else if (clientMsg->message_type == XA_XdndFinished) + { + resetDragAndDrop(); + } + + break; + } + + case SelectionNotify: + handleDragAndDropSelection (event); + break; + + case SelectionClear: + case SelectionRequest: + break; + + default: #if JUCE_USE_XSHM - if (event->xany.type == XShmGetEventBase (display)) - repainter->notifyPaintCompleted(); + if (event->xany.type == XShmGetEventBase (display)) + repainter->notifyPaintCompleted(); #endif - break; - } - } + break; + } + } - void showMouseCursor (Cursor cursor) throw() - { - XDefineCursor (display, windowH, cursor); - } + void showMouseCursor (Cursor cursor) throw() + { + XDefineCursor (display, windowH, cursor); + } - void setTaskBarIcon (const Image& image) - { - deleteTaskBarIcon(); - taskbarImage = image.createCopy(); + void setTaskBarIcon (const Image& image) + { + deleteTaskBarIcon(); + taskbarImage = image.createCopy(); - Screen* const screen = XDefaultScreenOfDisplay (display); - const int screenNumber = XScreenNumberOfScreen (screen); + Screen* const screen = XDefaultScreenOfDisplay (display); + const int screenNumber = XScreenNumberOfScreen (screen); - char screenAtom[32]; - snprintf (screenAtom, sizeof (screenAtom), "_NET_SYSTEM_TRAY_S%d", screenNumber); - Atom selectionAtom = XInternAtom (display, screenAtom, false); + char screenAtom[32]; + snprintf (screenAtom, sizeof (screenAtom), "_NET_SYSTEM_TRAY_S%d", screenNumber); + Atom selectionAtom = XInternAtom (display, screenAtom, false); - XGrabServer (display); - Window managerWin = XGetSelectionOwner (display, selectionAtom); + XGrabServer (display); + Window managerWin = XGetSelectionOwner (display, selectionAtom); - if (managerWin != None) - XSelectInput (display, managerWin, StructureNotifyMask); + if (managerWin != None) + XSelectInput (display, managerWin, StructureNotifyMask); - XUngrabServer (display); - XFlush (display); + XUngrabServer (display); + XFlush (display); - if (managerWin != None) - { - XEvent ev; - zerostruct (ev); - ev.xclient.type = ClientMessage; - ev.xclient.window = managerWin; - ev.xclient.message_type = XInternAtom (display, "_NET_SYSTEM_TRAY_OPCODE", False); - ev.xclient.format = 32; - ev.xclient.data.l[0] = CurrentTime; - ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK; - ev.xclient.data.l[2] = windowH; - ev.xclient.data.l[3] = 0; - ev.xclient.data.l[4] = 0; + if (managerWin != None) + { + XEvent ev; + zerostruct (ev); + ev.xclient.type = ClientMessage; + ev.xclient.window = managerWin; + ev.xclient.message_type = XInternAtom (display, "_NET_SYSTEM_TRAY_OPCODE", False); + ev.xclient.format = 32; + ev.xclient.data.l[0] = CurrentTime; + ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK; + ev.xclient.data.l[2] = windowH; + ev.xclient.data.l[3] = 0; + ev.xclient.data.l[4] = 0; - XSendEvent (display, managerWin, False, NoEventMask, &ev); - XSync (display, False); - } + XSendEvent (display, managerWin, False, NoEventMask, &ev); + XSync (display, False); + } - // For older KDE's ... - long atomData = 1; - Atom trayAtom = XInternAtom (display, "KWM_DOCKWINDOW", false); - XChangeProperty (display, windowH, trayAtom, trayAtom, 32, PropModeReplace, (unsigned char*) &atomData, 1); + // For older KDE's ... + long atomData = 1; + Atom trayAtom = XInternAtom (display, "KWM_DOCKWINDOW", false); + XChangeProperty (display, windowH, trayAtom, trayAtom, 32, PropModeReplace, (unsigned char*) &atomData, 1); - // For more recent KDE's... - trayAtom = XInternAtom (display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", false); - XChangeProperty (display, windowH, trayAtom, XA_WINDOW, 32, PropModeReplace, (unsigned char*) &windowH, 1); + // For more recent KDE's... + trayAtom = XInternAtom (display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", false); + XChangeProperty (display, windowH, trayAtom, XA_WINDOW, 32, PropModeReplace, (unsigned char*) &windowH, 1); - // a minimum size must be specified for GNOME and Xfce, otherwise the icon is displayed with a width of 1 - XSizeHints* hints = XAllocSizeHints(); - hints->flags = PMinSize; - hints->min_width = 22; - hints->min_height = 22; - XSetWMNormalHints (display, windowH, hints); - XFree (hints); - } + // a minimum size must be specified for GNOME and Xfce, otherwise the icon is displayed with a width of 1 + XSizeHints* hints = XAllocSizeHints(); + hints->flags = PMinSize; + hints->min_width = 22; + hints->min_height = 22; + XSetWMNormalHints (display, windowH, hints); + XFree (hints); + } - void deleteTaskBarIcon() - { - deleteAndZero (taskbarImage); - } + void deleteTaskBarIcon() + { + deleteAndZero (taskbarImage); + } - const Image* getTaskbarIcon() const throw() { return taskbarImage; } + const Image* getTaskbarIcon() const throw() { return taskbarImage; } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - bool dontRepaint; + bool dontRepaint; private: - class LinuxRepaintManager : public Timer - { - public: - LinuxRepaintManager (LinuxComponentPeer* const peer_) - : peer (peer_), - lastTimeImageUsed (0) - { + class LinuxRepaintManager : public Timer + { + public: + LinuxRepaintManager (LinuxComponentPeer* const peer_) + : peer (peer_), + lastTimeImageUsed (0) + { #if JUCE_USE_XSHM - shmCompletedDrawing = true; + shmCompletedDrawing = true; - useARGBImagesForRendering = isShmAvailable(); + useARGBImagesForRendering = isShmAvailable(); - if (useARGBImagesForRendering) - { - XShmSegmentInfo segmentinfo; + if (useARGBImagesForRendering) + { + XShmSegmentInfo segmentinfo; - XImage* const testImage - = XShmCreateImage (display, DefaultVisual (display, DefaultScreen (display)), - 24, ZPixmap, 0, &segmentinfo, 64, 64); + XImage* const testImage + = XShmCreateImage (display, DefaultVisual (display, DefaultScreen (display)), + 24, ZPixmap, 0, &segmentinfo, 64, 64); - useARGBImagesForRendering = (testImage->bits_per_pixel == 32); - XDestroyImage (testImage); - } + useARGBImagesForRendering = (testImage->bits_per_pixel == 32); + XDestroyImage (testImage); + } #endif - } + } - ~LinuxRepaintManager() - { - } + ~LinuxRepaintManager() + { + } - void timerCallback() - { - if (! regionsNeedingRepaint.isEmpty() && shmCompletedDrawing) - { - stopTimer(); - performAnyPendingRepaintsNow(); - } - else if (Time::getApproximateMillisecondCounter() > lastTimeImageUsed + 3000) - { - stopTimer(); - image = 0; - } - } + void timerCallback() + { + if (! regionsNeedingRepaint.isEmpty() && shmCompletedDrawing) + { + stopTimer(); + performAnyPendingRepaintsNow(); + } + else if (Time::getApproximateMillisecondCounter() > lastTimeImageUsed + 3000) + { + stopTimer(); + image = 0; + } + } - void repaint (int x, int y, int w, int h) - { - if (! isTimerRunning()) - startTimer (repaintTimerPeriod); + void repaint (int x, int y, int w, int h) + { + if (! isTimerRunning()) + startTimer (repaintTimerPeriod); - regionsNeedingRepaint.add (x, y, w, h); - } + regionsNeedingRepaint.add (x, y, w, h); + } - void performAnyPendingRepaintsNow() - { - peer->clearMaskedRegion(); + void performAnyPendingRepaintsNow() + { + peer->clearMaskedRegion(); - const Rectangle totalArea (regionsNeedingRepaint.getBounds()); + const Rectangle totalArea (regionsNeedingRepaint.getBounds()); - if (! totalArea.isEmpty()) - { - shmCompletedDrawing = false; + if (! totalArea.isEmpty()) + { + shmCompletedDrawing = false; - if (image == 0 || image->getWidth() < totalArea.getWidth() - || image->getHeight() < totalArea.getHeight()) - { + if (image == 0 || image->getWidth() < totalArea.getWidth() + || image->getHeight() < totalArea.getHeight()) + { #if JUCE_USE_XSHM - image = new XBitmapImage (useARGBImagesForRendering ? Image::ARGB - : Image::RGB, + image = new XBitmapImage (useARGBImagesForRendering ? Image::ARGB + : Image::RGB, #else - image = new XBitmapImage (Image::RGB, + image = new XBitmapImage (Image::RGB, #endif - (totalArea.getWidth() + 31) & ~31, - (totalArea.getHeight() + 31) & ~31, - false, - peer->depthIs16Bit); - } + (totalArea.getWidth() + 31) & ~31, + (totalArea.getHeight() + 31) & ~31, + false, + peer->depthIs16Bit); + } - startTimer (repaintTimerPeriod); + startTimer (repaintTimerPeriod); - LowLevelGraphicsSoftwareRenderer context (*image); + LowLevelGraphicsSoftwareRenderer context (*image); - context.setOrigin (-totalArea.getX(), -totalArea.getY()); + context.setOrigin (-totalArea.getX(), -totalArea.getY()); - if (context.clipToRectangleList (regionsNeedingRepaint)) - peer->handlePaint (context); + if (context.clipToRectangleList (regionsNeedingRepaint)) + peer->handlePaint (context); - if (! peer->maskedRegion.isEmpty()) - regionsNeedingRepaint.subtract (peer->maskedRegion); + if (! peer->maskedRegion.isEmpty()) + regionsNeedingRepaint.subtract (peer->maskedRegion); - for (RectangleList::Iterator i (regionsNeedingRepaint); i.next();) - { - const Rectangle& r = *i.getRectangle(); + for (RectangleList::Iterator i (regionsNeedingRepaint); i.next();) + { + const Rectangle& r = *i.getRectangle(); - image->blitToWindow (peer->windowH, - r.getX(), r.getY(), r.getWidth(), r.getHeight(), - r.getX() - totalArea.getX(), r.getY() - totalArea.getY()); - } - } + image->blitToWindow (peer->windowH, + r.getX(), r.getY(), r.getWidth(), r.getHeight(), + r.getX() - totalArea.getX(), r.getY() - totalArea.getY()); + } + } - regionsNeedingRepaint.clear(); + regionsNeedingRepaint.clear(); - lastTimeImageUsed = Time::getApproximateMillisecondCounter(); - startTimer (repaintTimerPeriod); - } + lastTimeImageUsed = Time::getApproximateMillisecondCounter(); + startTimer (repaintTimerPeriod); + } #if JUCE_USE_XSHM - void notifyPaintCompleted() - { - shmCompletedDrawing = true; - } + void notifyPaintCompleted() + { + shmCompletedDrawing = true; + } #endif - private: - LinuxComponentPeer* const peer; - ScopedPointer image; - uint32 lastTimeImageUsed; - RectangleList regionsNeedingRepaint; + private: + LinuxComponentPeer* const peer; + ScopedPointer image; + uint32 lastTimeImageUsed; + RectangleList regionsNeedingRepaint; #if JUCE_USE_XSHM - bool useARGBImagesForRendering; - bool shmCompletedDrawing; + bool useARGBImagesForRendering; + bool shmCompletedDrawing; #endif - LinuxRepaintManager (const LinuxRepaintManager&); - const LinuxRepaintManager& operator= (const LinuxRepaintManager&); - }; - - ScopedPointer repainter; - - friend class LinuxRepaintManager; - Window windowH, parentWindow; - int wx, wy, ww, wh; - Image* taskbarImage; - bool fullScreen, entered, mapped, depthIs16Bit; - BorderSize windowBorder; - - void removeWindowDecorations (Window wndH) - { - Atom hints = XInternAtom (display, "_MOTIF_WM_HINTS", True); - - if (hints != None) - { - typedef struct - { - unsigned long flags; - unsigned long functions; - unsigned long decorations; - long input_mode; - unsigned long status; - } MotifWmHints; - - MotifWmHints motifHints; - zerostruct (motifHints); - motifHints.flags = 2; /* MWM_HINTS_DECORATIONS */ - motifHints.decorations = 0; - - XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace, - (unsigned char*) &motifHints, 4); - } - - hints = XInternAtom (display, "_WIN_HINTS", True); - - if (hints != None) - { - long gnomeHints = 0; - - XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace, - (unsigned char*) &gnomeHints, 1); - } - - hints = XInternAtom (display, "KWM_WIN_DECORATION", True); - - if (hints != None) - { - long kwmHints = 2; /*KDE_tinyDecoration*/ - - XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace, - (unsigned char*) &kwmHints, 1); - } - - hints = XInternAtom (display, "_NET_WM_WINDOW_TYPE", True); - - if (hints != None) - { - int netHints [2]; - int numHints = 0; - if ((styleFlags & windowIsTemporary) != 0) - netHints [numHints] = XInternAtom (display, "_NET_WM_WINDOW_TYPE_MENU", True); - else - netHints [numHints] = XInternAtom (display, "_NET_WM_WINDOW_TYPE_NORMAL", True); - - if (netHints [numHints] != 0) - ++numHints; - - netHints[numHints] = XInternAtom (display, "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", True); - - if (netHints [numHints] != 0) - ++numHints; - - XChangeProperty (display, wndH, hints, XA_ATOM, 32, PropModeReplace, - (unsigned char*) &netHints, numHints); - } - } - - void addWindowButtons (Window wndH) - { - Atom hints = XInternAtom (display, "_MOTIF_WM_HINTS", True); - - if (hints != None) - { - typedef struct - { - unsigned long flags; - unsigned long functions; - unsigned long decorations; - long input_mode; - unsigned long status; - } MotifWmHints; - - MotifWmHints motifHints; - zerostruct (motifHints); - - motifHints.flags = 1 | 2; /* MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS */ - motifHints.decorations = 2 /* MWM_DECOR_BORDER */ | 8 /* MWM_DECOR_TITLE */ | 16; /* MWM_DECOR_MENU */ - - motifHints.functions = 4 /* MWM_FUNC_MOVE */; - - if ((styleFlags & windowHasCloseButton) != 0) - motifHints.functions |= 32; /* MWM_FUNC_CLOSE */ - - if ((styleFlags & windowHasMinimiseButton) != 0) - { - motifHints.functions |= 8; /* MWM_FUNC_MINIMIZE */ - motifHints.decorations |= 0x20; /* MWM_DECOR_MINIMIZE */ - } - - if ((styleFlags & windowHasMaximiseButton) != 0) - { - motifHints.functions |= 0x10; /* MWM_FUNC_MAXIMIZE */ - motifHints.decorations |= 0x40; /* MWM_DECOR_MAXIMIZE */ - } - - if ((styleFlags & windowIsResizable) != 0) - { - motifHints.functions |= 2; /* MWM_FUNC_RESIZE */ - motifHints.decorations |= 0x4; /* MWM_DECOR_RESIZEH */ - } - - XChangeProperty (display, wndH, hints, hints, 32, 0, (unsigned char*) &motifHints, 5); - } - - hints = XInternAtom (display, "_NET_WM_ALLOWED_ACTIONS", True); - - if (hints != None) - { - int netHints [6]; - int num = 0; - - netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_RESIZE", (styleFlags & windowIsResizable) ? True : False); - netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_FULLSCREEN", (styleFlags & windowHasMaximiseButton) ? True : False); - netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_MINIMIZE", (styleFlags & windowHasMinimiseButton) ? True : False); - netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_CLOSE", (styleFlags & windowHasCloseButton) ? True : False); - - XChangeProperty (display, wndH, hints, XA_ATOM, 32, PropModeReplace, - (unsigned char*) &netHints, num); - } - } - - void createWindow() - { - static bool atomsInitialised = false; - - if (! atomsInitialised) - { - atomsInitialised = true; - - wm_Protocols = XInternAtom (display, "WM_PROTOCOLS", 1); - wm_ProtocolList [TAKE_FOCUS] = XInternAtom (display, "WM_TAKE_FOCUS", 1); - wm_ProtocolList [DELETE_WINDOW] = XInternAtom (display, "WM_DELETE_WINDOW", 1); - wm_ChangeState = XInternAtom (display, "WM_CHANGE_STATE", 1); - wm_State = XInternAtom (display, "WM_STATE", 1); - wm_ActiveWin = XInternAtom (display, "_NET_ACTIVE_WINDOW", False); - - XA_XdndAware = XInternAtom (display, "XdndAware", 0); - XA_XdndEnter = XInternAtom (display, "XdndEnter", 0); - XA_XdndLeave = XInternAtom (display, "XdndLeave", 0); - XA_XdndPosition = XInternAtom (display, "XdndPosition", 0); - XA_XdndStatus = XInternAtom (display, "XdndStatus", 0); - XA_XdndDrop = XInternAtom (display, "XdndDrop", 0); - XA_XdndFinished = XInternAtom (display, "XdndFinished", 0); - XA_XdndSelection = XInternAtom (display, "XdndSelection", 0); - XA_XdndProxy = XInternAtom (display, "XdndProxy", 0); - - XA_XdndTypeList = XInternAtom (display, "XdndTypeList", 0); - XA_XdndActionList = XInternAtom (display, "XdndActionList", 0); - XA_XdndActionCopy = XInternAtom (display, "XdndActionCopy", 0); - XA_XdndActionMove = XInternAtom (display, "XdndActionMove", 0); - XA_XdndActionLink = XInternAtom (display, "XdndActionLink", 0); - XA_XdndActionAsk = XInternAtom (display, "XdndActionAsk", 0); - XA_XdndActionPrivate = XInternAtom (display, "XdndActionPrivate", 0); - XA_XdndActionDescription = XInternAtom (display, "XdndActionDescription", 0); - - XA_JXSelectionWindowProperty = XInternAtom (display, "JXSelectionWindowProperty", 0); - - XA_MimeTextPlain = XInternAtom (display, "text/plain", 0); - XA_MimeTextUriList = XInternAtom (display, "text/uri-list", 0); - XA_MimeRootDrop = XInternAtom (display, "application/x-rootwindow-drop", 0); - } - - resetDragAndDrop(); - - XA_OtherMime = XA_MimeTextPlain; // xxx why?? - allowedMimeTypeAtoms [0] = XA_MimeTextPlain; - allowedMimeTypeAtoms [1] = XA_OtherMime; - allowedMimeTypeAtoms [2] = XA_MimeTextUriList; - - allowedActions [0] = XA_XdndActionMove; - allowedActions [1] = XA_XdndActionCopy; - allowedActions [2] = XA_XdndActionLink; - allowedActions [3] = XA_XdndActionAsk; - allowedActions [4] = XA_XdndActionPrivate; - - // Get defaults for various properties - const int screen = DefaultScreen (display); - Window root = RootWindow (display, screen); - - // Attempt to create a 24-bit window on the default screen. If this is not - // possible then exit - XVisualInfo desiredVisual; - desiredVisual.screen = screen; - desiredVisual.depth = 24; - depthIs16Bit = false; - - int numVisuals; - XVisualInfo* visuals = XGetVisualInfo (display, VisualScreenMask | VisualDepthMask, - &desiredVisual, &numVisuals); - - if (numVisuals < 1 || visuals == 0) - { - XFree (visuals); - desiredVisual.depth = 16; - - visuals = XGetVisualInfo (display, VisualScreenMask | VisualDepthMask, - &desiredVisual, &numVisuals); - - if (numVisuals < 1 || visuals == 0) - { - Logger::outputDebugString ("ERROR: System doesn't support 24 or 16 bit RGB display.\n"); - Process::terminate(); - } - - depthIs16Bit = true; - } - - XFree (visuals); - - // Set up the window attributes - XSetWindowAttributes swa; - swa.border_pixel = 0; - swa.background_pixmap = None; - swa.colormap = DefaultColormap (display, screen); - swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False; - swa.event_mask = eventMask; - - Window wndH = XCreateWindow (display, root, - 0, 0, 1, 1, - 0, 0, InputOutput, (Visual*) CopyFromParent, - CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect, - &swa); - - XGrabButton (display, AnyButton, AnyModifier, wndH, False, - ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, None, None); - - // Set the window context to identify the window handle object - if (XSaveContext (display, (XID) wndH, improbableNumber, (XPointer) this)) - { - // Failed - jassertfalse - Logger::outputDebugString ("Failed to create context information for window.\n"); - XDestroyWindow (display, wndH); - wndH = 0; - } - - // Set window manager hints - XWMHints* wmHints = XAllocWMHints(); - wmHints->flags = InputHint | StateHint; - wmHints->input = True; // Locally active input model - wmHints->initial_state = NormalState; - XSetWMHints (display, wndH, wmHints); - XFree (wmHints); - - if ((styleFlags & windowIsSemiTransparent) != 0) - { - //xxx - } - - if ((styleFlags & windowAppearsOnTaskbar) != 0) - { - //xxx - } - - //XSetTransientForHint (display, wndH, RootWindow (display, DefaultScreen (display))); - - if ((styleFlags & windowHasTitleBar) == 0) - removeWindowDecorations (wndH); - else - addWindowButtons (wndH); - - // Set window manager protocols - XChangeProperty (display, wndH, wm_Protocols, XA_ATOM, 32, PropModeReplace, - (unsigned char*) wm_ProtocolList, 2); - - // Set drag and drop flags - XChangeProperty (display, wndH, XA_XdndTypeList, XA_ATOM, 32, PropModeReplace, - (const unsigned char*) allowedMimeTypeAtoms, numElementsInArray (allowedMimeTypeAtoms)); - - XChangeProperty (display, wndH, XA_XdndActionList, XA_ATOM, 32, PropModeReplace, - (const unsigned char*) allowedActions, numElementsInArray (allowedActions)); - - XChangeProperty (display, wndH, XA_XdndActionDescription, XA_STRING, 8, PropModeReplace, - (const unsigned char*) "", 0); - - unsigned long dndVersion = ourDndVersion; - XChangeProperty (display, wndH, XA_XdndAware, XA_ATOM, 32, PropModeReplace, - (const unsigned char*) &dndVersion, 1); - - // Set window name - setWindowTitle (wndH, getComponent()->getName()); - - // Initialise the pointer and keyboard mapping - // This is not the same as the logical pointer mapping the X server uses: - // we don't mess with this. - static bool mappingInitialised = false; - - if (! mappingInitialised) - { - mappingInitialised = true; - - const int numButtons = XGetPointerMapping (display, 0, 0); - - if (numButtons == 2) - { - pointerMap[0] = LeftButton; - pointerMap[1] = RightButton; - pointerMap[2] = pointerMap[3] = pointerMap[4] = NoButton; - } - else if (numButtons >= 3) - { - pointerMap[0] = LeftButton; - pointerMap[1] = MiddleButton; - pointerMap[2] = RightButton; - - if (numButtons >= 5) - { - pointerMap[3] = WheelUp; - pointerMap[4] = WheelDown; - } - } - - getModifierMapping(); - } - - windowH = wndH; - } - - void destroyWindow() - { - XPointer handlePointer; - if (! XFindContext (display, (XID) windowH, improbableNumber, &handlePointer)) - XDeleteContext (display, (XID) windowH, improbableNumber); - - XDestroyWindow (display, windowH); - - // Wait for it to complete and then remove any events for this - // window from the event queue. - XSync (display, false); - - XEvent event; - while (XCheckWindowEvent (display, windowH, eventMask, &event) == True) - {} - } - - static int64 getEventTime (::Time t) throw() - { - static int64 eventTimeOffset = 0x12345678; - const int64 thisMessageTime = t; - - if (eventTimeOffset == 0x12345678) - eventTimeOffset = Time::currentTimeMillis() - thisMessageTime; - - return eventTimeOffset + thisMessageTime; - } - - static void setWindowTitle (Window xwin, const char* const title) throw() - { - XTextProperty nameProperty; - char* strings[] = { (char*) title }; - - if (XStringListToTextProperty (strings, 1, &nameProperty)) - { - XSetWMName (display, xwin, &nameProperty); - XSetWMIconName (display, xwin, &nameProperty); - - XFree (nameProperty.value); - } - } - - void updateBorderSize() - { - if ((styleFlags & windowHasTitleBar) == 0) - { - windowBorder = BorderSize (0); - } - else if (windowBorder.getTopAndBottom() == 0 && windowBorder.getLeftAndRight() == 0) - { - Atom hints = XInternAtom (display, "_NET_FRAME_EXTENTS", True); - - if (hints != None) - { - unsigned char* data = 0; - unsigned long nitems, bytesLeft; - Atom actualType; - int actualFormat; - - if (XGetWindowProperty (display, windowH, hints, 0, 4, False, - XA_CARDINAL, &actualType, &actualFormat, &nitems, &bytesLeft, - &data) == Success) - { - const unsigned long* const sizes = (const unsigned long*) data; - - if (actualFormat == 32) - windowBorder = BorderSize ((int) sizes[2], (int) sizes[0], - (int) sizes[3], (int) sizes[1]); - - XFree (data); - } - } - } - } - - void updateBounds() - { - jassert (windowH != 0); - if (windowH != 0) - { - Window root, child; - unsigned int bw, depth; - - if (! XGetGeometry (display, (::Drawable) windowH, &root, - &wx, &wy, (unsigned int*) &ww, (unsigned int*) &wh, - &bw, &depth)) - { - wx = wy = ww = wh = 0; - } - else if (! XTranslateCoordinates (display, windowH, root, 0, 0, &wx, &wy, &child)) - { - wx = wy = 0; - } - } - } - - void resetDragAndDrop() - { - dragAndDropFiles.clear(); - lastDropX = lastDropY = -1; - dragAndDropCurrentMimeType = 0; - dragAndDropSourceWindow = 0; - srcMimeTypeAtomList.clear(); - } - - void sendDragAndDropMessage (XClientMessageEvent& msg) - { - msg.type = ClientMessage; - msg.display = display; - msg.window = dragAndDropSourceWindow; - msg.format = 32; - msg.data.l[0] = windowH; - - XSendEvent (display, dragAndDropSourceWindow, False, 0, (XEvent*) &msg); - } - - void sendDragAndDropStatus (const bool acceptDrop, Atom dropAction) - { - XClientMessageEvent msg; - zerostruct (msg); - msg.message_type = XA_XdndStatus; - msg.data.l[1] = (acceptDrop ? 1 : 0) | 2; // 2 indicates that we want to receive position messages - msg.data.l[4] = dropAction; - - sendDragAndDropMessage (msg); - } - - void sendDragAndDropLeave() - { - XClientMessageEvent msg; - zerostruct (msg); - msg.message_type = XA_XdndLeave; - sendDragAndDropMessage (msg); - } - - void sendDragAndDropFinish() - { - XClientMessageEvent msg; - zerostruct (msg); - msg.message_type = XA_XdndFinished; - sendDragAndDropMessage (msg); - } - - void handleDragAndDropStatus (const XClientMessageEvent* const clientMsg) - { - if ((clientMsg->data.l[1] & 1) == 0) - { - sendDragAndDropLeave(); - - if (dragAndDropFiles.size() > 0) - handleFileDragExit (dragAndDropFiles); - - dragAndDropFiles.clear(); - } - } - - void handleDragAndDropPosition (const XClientMessageEvent* const clientMsg) - { - if (dragAndDropSourceWindow == 0) - return; - - dragAndDropSourceWindow = clientMsg->data.l[0]; - - const int dropX = ((int) clientMsg->data.l[2] >> 16) - getScreenX(); - const int dropY = ((int) clientMsg->data.l[2] & 0xffff) - getScreenY(); - - if (lastDropX != dropX || lastDropY != dropY) - { - lastDropX = dropX; - lastDropY = dropY; - - dragAndDropTimestamp = clientMsg->data.l[3]; - - Atom targetAction = XA_XdndActionCopy; - - for (int i = numElementsInArray (allowedActions); --i >= 0;) - { - if ((Atom) clientMsg->data.l[4] == allowedActions[i]) - { - targetAction = allowedActions[i]; - break; - } - } - - sendDragAndDropStatus (true, targetAction); - - if (dragAndDropFiles.size() == 0) - updateDraggedFileList (clientMsg); - - if (dragAndDropFiles.size() > 0) - handleFileDragMove (dragAndDropFiles, dropX, dropY); - } - } - - void handleDragAndDropDrop (const XClientMessageEvent* const clientMsg) - { - if (dragAndDropFiles.size() == 0) - updateDraggedFileList (clientMsg); - - const StringArray files (dragAndDropFiles); - const int lastX = lastDropX, lastY = lastDropY; - - sendDragAndDropFinish(); - resetDragAndDrop(); - - if (files.size() > 0) - handleFileDragDrop (files, lastX, lastY); - } - - void handleDragAndDropEnter (const XClientMessageEvent* const clientMsg) - { - dragAndDropFiles.clear(); - srcMimeTypeAtomList.clear(); - - dragAndDropCurrentMimeType = 0; - const int dndCurrentVersion = (int) (clientMsg->data.l[1] & 0xff000000) >> 24; - - if (dndCurrentVersion < 3 || dndCurrentVersion > ourDndVersion) - { - dragAndDropSourceWindow = 0; - return; - } - - dragAndDropSourceWindow = clientMsg->data.l[0]; - - if ((clientMsg->data.l[1] & 1) != 0) - { - Atom actual; - int format; - unsigned long count = 0, remaining = 0; - unsigned char* data = 0; - - XGetWindowProperty (display, dragAndDropSourceWindow, XA_XdndTypeList, - 0, 0x8000000L, False, XA_ATOM, &actual, &format, - &count, &remaining, &data); - - if (data != 0) - { - if (actual == XA_ATOM && format == 32 && count != 0) - { - const unsigned long* const types = (const unsigned long*) data; - - for (unsigned int i = 0; i < count; ++i) - if (types[i] != None) - srcMimeTypeAtomList.add (types[i]); - } - - XFree (data); - } - } - - if (srcMimeTypeAtomList.size() == 0) - { - for (int i = 2; i < 5; ++i) - if (clientMsg->data.l[i] != None) - srcMimeTypeAtomList.add (clientMsg->data.l[i]); - - if (srcMimeTypeAtomList.size() == 0) - { - dragAndDropSourceWindow = 0; - return; - } - } - - for (int i = 0; i < srcMimeTypeAtomList.size() && dragAndDropCurrentMimeType == 0; ++i) - for (int j = 0; j < numElementsInArray (allowedMimeTypeAtoms); ++j) - if (srcMimeTypeAtomList[i] == allowedMimeTypeAtoms[j]) - dragAndDropCurrentMimeType = allowedMimeTypeAtoms[j]; - - handleDragAndDropPosition (clientMsg); - } - - void handleDragAndDropSelection (const XEvent* const evt) - { - dragAndDropFiles.clear(); - - if (evt->xselection.property != 0) - { - StringArray lines; - - { - MemoryBlock dropData; - - for (;;) - { - Atom actual; - uint8* data = 0; - unsigned long count = 0, remaining = 0; - int format = 0; - - if (XGetWindowProperty (display, evt->xany.window, evt->xselection.property, - dropData.getSize() / 4, 65536, 1, AnyPropertyType, &actual, - &format, &count, &remaining, &data) == Success) - { - dropData.append (data, count * format / 8); - XFree (data); - - if (remaining == 0) - break; - } - else - { - XFree (data); - break; - } - } - - lines.addLines (dropData.toString()); - } - - for (int i = 0; i < lines.size(); ++i) - dragAndDropFiles.add (URL::removeEscapeChars (lines[i].fromFirstOccurrenceOf (T("file://"), false, true))); - - dragAndDropFiles.trim(); - dragAndDropFiles.removeEmptyStrings(); - } - } - - void updateDraggedFileList (const XClientMessageEvent* const clientMsg) - { - dragAndDropFiles.clear(); - - if (dragAndDropSourceWindow != None - && dragAndDropCurrentMimeType != 0) - { - dragAndDropTimestamp = clientMsg->data.l[2]; - - XConvertSelection (display, - XA_XdndSelection, - dragAndDropCurrentMimeType, - XA_JXSelectionWindowProperty, - windowH, - dragAndDropTimestamp); - } - } - - StringArray dragAndDropFiles; - int dragAndDropTimestamp, lastDropX, lastDropY; - - Atom XA_OtherMime, dragAndDropCurrentMimeType; - Window dragAndDropSourceWindow; - - unsigned int allowedActions [5]; - unsigned int allowedMimeTypeAtoms [3]; - Array srcMimeTypeAtomList; + LinuxRepaintManager (const LinuxRepaintManager&); + const LinuxRepaintManager& operator= (const LinuxRepaintManager&); + }; + + ScopedPointer repainter; + + friend class LinuxRepaintManager; + Window windowH, parentWindow; + int wx, wy, ww, wh; + Image* taskbarImage; + bool fullScreen, entered, mapped, depthIs16Bit; + BorderSize windowBorder; + + struct MotifWmHints + { + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long input_mode; + unsigned long status; + }; + + void removeWindowDecorations (Window wndH) + { + Atom hints = XInternAtom (display, "_MOTIF_WM_HINTS", True); + + if (hints != None) + { + MotifWmHints motifHints; + zerostruct (motifHints); + motifHints.flags = 2; /* MWM_HINTS_DECORATIONS */ + motifHints.decorations = 0; + + XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace, + (unsigned char*) &motifHints, 4); + } + + hints = XInternAtom (display, "_WIN_HINTS", True); + + if (hints != None) + { + long gnomeHints = 0; + + XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace, + (unsigned char*) &gnomeHints, 1); + } + + hints = XInternAtom (display, "KWM_WIN_DECORATION", True); + + if (hints != None) + { + long kwmHints = 2; /*KDE_tinyDecoration*/ + + XChangeProperty (display, wndH, hints, hints, 32, PropModeReplace, + (unsigned char*) &kwmHints, 1); + } + + hints = XInternAtom (display, "_NET_WM_WINDOW_TYPE", True); + + if (hints != None) + { + int netHints [2]; + int numHints = 0; + if ((styleFlags & windowIsTemporary) != 0) + netHints [numHints] = XInternAtom (display, "_NET_WM_WINDOW_TYPE_MENU", True); + else + netHints [numHints] = XInternAtom (display, "_NET_WM_WINDOW_TYPE_NORMAL", True); + + if (netHints [numHints] != 0) + ++numHints; + + netHints[numHints] = XInternAtom (display, "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", True); + + if (netHints [numHints] != 0) + ++numHints; + + XChangeProperty (display, wndH, hints, XA_ATOM, 32, PropModeReplace, + (unsigned char*) &netHints, numHints); + } + } + + void addWindowButtons (Window wndH) + { + Atom hints = XInternAtom (display, "_MOTIF_WM_HINTS", True); + + if (hints != None) + { + MotifWmHints motifHints; + zerostruct (motifHints); + + motifHints.flags = 1 | 2; /* MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS */ + motifHints.decorations = 2 /* MWM_DECOR_BORDER */ | 8 /* MWM_DECOR_TITLE */ | 16; /* MWM_DECOR_MENU */ + + motifHints.functions = 4 /* MWM_FUNC_MOVE */; + + if ((styleFlags & windowHasCloseButton) != 0) + motifHints.functions |= 32; /* MWM_FUNC_CLOSE */ + + if ((styleFlags & windowHasMinimiseButton) != 0) + { + motifHints.functions |= 8; /* MWM_FUNC_MINIMIZE */ + motifHints.decorations |= 0x20; /* MWM_DECOR_MINIMIZE */ + } + + if ((styleFlags & windowHasMaximiseButton) != 0) + { + motifHints.functions |= 0x10; /* MWM_FUNC_MAXIMIZE */ + motifHints.decorations |= 0x40; /* MWM_DECOR_MAXIMIZE */ + } + + if ((styleFlags & windowIsResizable) != 0) + { + motifHints.functions |= 2; /* MWM_FUNC_RESIZE */ + motifHints.decorations |= 0x4; /* MWM_DECOR_RESIZEH */ + } + + XChangeProperty (display, wndH, hints, hints, 32, 0, (unsigned char*) &motifHints, 5); + } + + hints = XInternAtom (display, "_NET_WM_ALLOWED_ACTIONS", True); + + if (hints != None) + { + int netHints [6]; + int num = 0; + + netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_RESIZE", (styleFlags & windowIsResizable) ? True : False); + netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_FULLSCREEN", (styleFlags & windowHasMaximiseButton) ? True : False); + netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_MINIMIZE", (styleFlags & windowHasMinimiseButton) ? True : False); + netHints [num++] = XInternAtom (display, "_NET_WM_ACTION_CLOSE", (styleFlags & windowHasCloseButton) ? True : False); + + XChangeProperty (display, wndH, hints, XA_ATOM, 32, PropModeReplace, + (unsigned char*) &netHints, num); + } + } + + void createWindow() + { + static bool atomsInitialised = false; + + if (! atomsInitialised) + { + atomsInitialised = true; + + wm_Protocols = XInternAtom (display, "WM_PROTOCOLS", 1); + wm_ProtocolList [TAKE_FOCUS] = XInternAtom (display, "WM_TAKE_FOCUS", 1); + wm_ProtocolList [DELETE_WINDOW] = XInternAtom (display, "WM_DELETE_WINDOW", 1); + wm_ChangeState = XInternAtom (display, "WM_CHANGE_STATE", 1); + wm_State = XInternAtom (display, "WM_STATE", 1); + wm_ActiveWin = XInternAtom (display, "_NET_ACTIVE_WINDOW", False); + + XA_XdndAware = XInternAtom (display, "XdndAware", 0); + XA_XdndEnter = XInternAtom (display, "XdndEnter", 0); + XA_XdndLeave = XInternAtom (display, "XdndLeave", 0); + XA_XdndPosition = XInternAtom (display, "XdndPosition", 0); + XA_XdndStatus = XInternAtom (display, "XdndStatus", 0); + XA_XdndDrop = XInternAtom (display, "XdndDrop", 0); + XA_XdndFinished = XInternAtom (display, "XdndFinished", 0); + XA_XdndSelection = XInternAtom (display, "XdndSelection", 0); + XA_XdndProxy = XInternAtom (display, "XdndProxy", 0); + + XA_XdndTypeList = XInternAtom (display, "XdndTypeList", 0); + XA_XdndActionList = XInternAtom (display, "XdndActionList", 0); + XA_XdndActionCopy = XInternAtom (display, "XdndActionCopy", 0); + XA_XdndActionMove = XInternAtom (display, "XdndActionMove", 0); + XA_XdndActionLink = XInternAtom (display, "XdndActionLink", 0); + XA_XdndActionAsk = XInternAtom (display, "XdndActionAsk", 0); + XA_XdndActionPrivate = XInternAtom (display, "XdndActionPrivate", 0); + XA_XdndActionDescription = XInternAtom (display, "XdndActionDescription", 0); + + XA_JXSelectionWindowProperty = XInternAtom (display, "JXSelectionWindowProperty", 0); + + XA_MimeTextPlain = XInternAtom (display, "text/plain", 0); + XA_MimeTextUriList = XInternAtom (display, "text/uri-list", 0); + XA_MimeRootDrop = XInternAtom (display, "application/x-rootwindow-drop", 0); + } + + resetDragAndDrop(); + + XA_OtherMime = XA_MimeTextPlain; // xxx why?? + allowedMimeTypeAtoms [0] = XA_MimeTextPlain; + allowedMimeTypeAtoms [1] = XA_OtherMime; + allowedMimeTypeAtoms [2] = XA_MimeTextUriList; + + allowedActions [0] = XA_XdndActionMove; + allowedActions [1] = XA_XdndActionCopy; + allowedActions [2] = XA_XdndActionLink; + allowedActions [3] = XA_XdndActionAsk; + allowedActions [4] = XA_XdndActionPrivate; + + // Get defaults for various properties + const int screen = DefaultScreen (display); + Window root = RootWindow (display, screen); + + // Attempt to create a 24-bit window on the default screen. If this is not + // possible then exit + XVisualInfo desiredVisual; + desiredVisual.screen = screen; + desiredVisual.depth = 24; + depthIs16Bit = false; + + int numVisuals; + XVisualInfo* visuals = XGetVisualInfo (display, VisualScreenMask | VisualDepthMask, + &desiredVisual, &numVisuals); + + if (numVisuals < 1 || visuals == 0) + { + XFree (visuals); + desiredVisual.depth = 16; + + visuals = XGetVisualInfo (display, VisualScreenMask | VisualDepthMask, + &desiredVisual, &numVisuals); + + if (numVisuals < 1 || visuals == 0) + { + Logger::outputDebugString ("ERROR: System doesn't support 24 or 16 bit RGB display.\n"); + Process::terminate(); + } + + depthIs16Bit = true; + } + + XFree (visuals); + + // Set up the window attributes + XSetWindowAttributes swa; + swa.border_pixel = 0; + swa.background_pixmap = None; + swa.colormap = DefaultColormap (display, screen); + swa.override_redirect = getComponent()->isAlwaysOnTop() ? True : False; + swa.event_mask = eventMask; + + Window wndH = XCreateWindow (display, root, + 0, 0, 1, 1, + 0, 0, InputOutput, (Visual*) CopyFromParent, + CWBorderPixel | CWColormap | CWBackPixmap | CWEventMask | CWOverrideRedirect, + &swa); + + XGrabButton (display, AnyButton, AnyModifier, wndH, False, + ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, None, None); + + // Set the window context to identify the window handle object + if (XSaveContext (display, (XID) wndH, improbableNumber, (XPointer) this)) + { + // Failed + jassertfalse + Logger::outputDebugString ("Failed to create context information for window.\n"); + XDestroyWindow (display, wndH); + wndH = 0; + } + + // Set window manager hints + XWMHints* wmHints = XAllocWMHints(); + wmHints->flags = InputHint | StateHint; + wmHints->input = True; // Locally active input model + wmHints->initial_state = NormalState; + XSetWMHints (display, wndH, wmHints); + XFree (wmHints); + + if ((styleFlags & windowIsSemiTransparent) != 0) + { + //xxx + } + + if ((styleFlags & windowAppearsOnTaskbar) != 0) + { + //xxx + } + + //XSetTransientForHint (display, wndH, RootWindow (display, DefaultScreen (display))); + + if ((styleFlags & windowHasTitleBar) == 0) + removeWindowDecorations (wndH); + else + addWindowButtons (wndH); + + // Set window manager protocols + XChangeProperty (display, wndH, wm_Protocols, XA_ATOM, 32, PropModeReplace, + (unsigned char*) wm_ProtocolList, 2); + + // Set drag and drop flags + XChangeProperty (display, wndH, XA_XdndTypeList, XA_ATOM, 32, PropModeReplace, + (const unsigned char*) allowedMimeTypeAtoms, numElementsInArray (allowedMimeTypeAtoms)); + + XChangeProperty (display, wndH, XA_XdndActionList, XA_ATOM, 32, PropModeReplace, + (const unsigned char*) allowedActions, numElementsInArray (allowedActions)); + + XChangeProperty (display, wndH, XA_XdndActionDescription, XA_STRING, 8, PropModeReplace, + (const unsigned char*) "", 0); + + unsigned long dndVersion = ourDndVersion; + XChangeProperty (display, wndH, XA_XdndAware, XA_ATOM, 32, PropModeReplace, + (const unsigned char*) &dndVersion, 1); + + // Set window name + setWindowTitle (wndH, getComponent()->getName()); + + // Initialise the pointer and keyboard mapping + // This is not the same as the logical pointer mapping the X server uses: + // we don't mess with this. + static bool mappingInitialised = false; + + if (! mappingInitialised) + { + mappingInitialised = true; + + const int numButtons = XGetPointerMapping (display, 0, 0); + + if (numButtons == 2) + { + pointerMap[0] = LeftButton; + pointerMap[1] = RightButton; + pointerMap[2] = pointerMap[3] = pointerMap[4] = NoButton; + } + else if (numButtons >= 3) + { + pointerMap[0] = LeftButton; + pointerMap[1] = MiddleButton; + pointerMap[2] = RightButton; + + if (numButtons >= 5) + { + pointerMap[3] = WheelUp; + pointerMap[4] = WheelDown; + } + } + + getModifierMapping(); + } + + windowH = wndH; + } + + void destroyWindow() + { + XPointer handlePointer; + if (! XFindContext (display, (XID) windowH, improbableNumber, &handlePointer)) + XDeleteContext (display, (XID) windowH, improbableNumber); + + XDestroyWindow (display, windowH); + + // Wait for it to complete and then remove any events for this + // window from the event queue. + XSync (display, false); + + XEvent event; + while (XCheckWindowEvent (display, windowH, eventMask, &event) == True) + {} + } + + static int64 getEventTime (::Time t) throw() + { + static int64 eventTimeOffset = 0x12345678; + const int64 thisMessageTime = t; + + if (eventTimeOffset == 0x12345678) + eventTimeOffset = Time::currentTimeMillis() - thisMessageTime; + + return eventTimeOffset + thisMessageTime; + } + + static void setWindowTitle (Window xwin, const char* const title) throw() + { + XTextProperty nameProperty; + char* strings[] = { (char*) title }; + + if (XStringListToTextProperty (strings, 1, &nameProperty)) + { + XSetWMName (display, xwin, &nameProperty); + XSetWMIconName (display, xwin, &nameProperty); + + XFree (nameProperty.value); + } + } + + void updateBorderSize() + { + if ((styleFlags & windowHasTitleBar) == 0) + { + windowBorder = BorderSize (0); + } + else if (windowBorder.getTopAndBottom() == 0 && windowBorder.getLeftAndRight() == 0) + { + Atom hints = XInternAtom (display, "_NET_FRAME_EXTENTS", True); + + if (hints != None) + { + unsigned char* data = 0; + unsigned long nitems, bytesLeft; + Atom actualType; + int actualFormat; + + if (XGetWindowProperty (display, windowH, hints, 0, 4, False, + XA_CARDINAL, &actualType, &actualFormat, &nitems, &bytesLeft, + &data) == Success) + { + const unsigned long* const sizes = (const unsigned long*) data; + + if (actualFormat == 32) + windowBorder = BorderSize ((int) sizes[2], (int) sizes[0], + (int) sizes[3], (int) sizes[1]); + + XFree (data); + } + } + } + } + + void updateBounds() + { + jassert (windowH != 0); + if (windowH != 0) + { + Window root, child; + unsigned int bw, depth; + + if (! XGetGeometry (display, (::Drawable) windowH, &root, + &wx, &wy, (unsigned int*) &ww, (unsigned int*) &wh, + &bw, &depth)) + { + wx = wy = ww = wh = 0; + } + else if (! XTranslateCoordinates (display, windowH, root, 0, 0, &wx, &wy, &child)) + { + wx = wy = 0; + } + } + } + + void resetDragAndDrop() + { + dragAndDropFiles.clear(); + lastDropX = lastDropY = -1; + dragAndDropCurrentMimeType = 0; + dragAndDropSourceWindow = 0; + srcMimeTypeAtomList.clear(); + } + + void sendDragAndDropMessage (XClientMessageEvent& msg) + { + msg.type = ClientMessage; + msg.display = display; + msg.window = dragAndDropSourceWindow; + msg.format = 32; + msg.data.l[0] = windowH; + + XSendEvent (display, dragAndDropSourceWindow, False, 0, (XEvent*) &msg); + } + + void sendDragAndDropStatus (const bool acceptDrop, Atom dropAction) + { + XClientMessageEvent msg; + zerostruct (msg); + msg.message_type = XA_XdndStatus; + msg.data.l[1] = (acceptDrop ? 1 : 0) | 2; // 2 indicates that we want to receive position messages + msg.data.l[4] = dropAction; + + sendDragAndDropMessage (msg); + } + + void sendDragAndDropLeave() + { + XClientMessageEvent msg; + zerostruct (msg); + msg.message_type = XA_XdndLeave; + sendDragAndDropMessage (msg); + } + + void sendDragAndDropFinish() + { + XClientMessageEvent msg; + zerostruct (msg); + msg.message_type = XA_XdndFinished; + sendDragAndDropMessage (msg); + } + + void handleDragAndDropStatus (const XClientMessageEvent* const clientMsg) + { + if ((clientMsg->data.l[1] & 1) == 0) + { + sendDragAndDropLeave(); + + if (dragAndDropFiles.size() > 0) + handleFileDragExit (dragAndDropFiles); + + dragAndDropFiles.clear(); + } + } + + void handleDragAndDropPosition (const XClientMessageEvent* const clientMsg) + { + if (dragAndDropSourceWindow == 0) + return; + + dragAndDropSourceWindow = clientMsg->data.l[0]; + + const int dropX = ((int) clientMsg->data.l[2] >> 16) - getScreenX(); + const int dropY = ((int) clientMsg->data.l[2] & 0xffff) - getScreenY(); + + if (lastDropX != dropX || lastDropY != dropY) + { + lastDropX = dropX; + lastDropY = dropY; + + dragAndDropTimestamp = clientMsg->data.l[3]; + + Atom targetAction = XA_XdndActionCopy; + + for (int i = numElementsInArray (allowedActions); --i >= 0;) + { + if ((Atom) clientMsg->data.l[4] == allowedActions[i]) + { + targetAction = allowedActions[i]; + break; + } + } + + sendDragAndDropStatus (true, targetAction); + + if (dragAndDropFiles.size() == 0) + updateDraggedFileList (clientMsg); + + if (dragAndDropFiles.size() > 0) + handleFileDragMove (dragAndDropFiles, dropX, dropY); + } + } + + void handleDragAndDropDrop (const XClientMessageEvent* const clientMsg) + { + if (dragAndDropFiles.size() == 0) + updateDraggedFileList (clientMsg); + + const StringArray files (dragAndDropFiles); + const int lastX = lastDropX, lastY = lastDropY; + + sendDragAndDropFinish(); + resetDragAndDrop(); + + if (files.size() > 0) + handleFileDragDrop (files, lastX, lastY); + } + + void handleDragAndDropEnter (const XClientMessageEvent* const clientMsg) + { + dragAndDropFiles.clear(); + srcMimeTypeAtomList.clear(); + + dragAndDropCurrentMimeType = 0; + const int dndCurrentVersion = (int) (clientMsg->data.l[1] & 0xff000000) >> 24; + + if (dndCurrentVersion < 3 || dndCurrentVersion > ourDndVersion) + { + dragAndDropSourceWindow = 0; + return; + } + + dragAndDropSourceWindow = clientMsg->data.l[0]; + + if ((clientMsg->data.l[1] & 1) != 0) + { + Atom actual; + int format; + unsigned long count = 0, remaining = 0; + unsigned char* data = 0; + + XGetWindowProperty (display, dragAndDropSourceWindow, XA_XdndTypeList, + 0, 0x8000000L, False, XA_ATOM, &actual, &format, + &count, &remaining, &data); + + if (data != 0) + { + if (actual == XA_ATOM && format == 32 && count != 0) + { + const unsigned long* const types = (const unsigned long*) data; + + for (unsigned int i = 0; i < count; ++i) + if (types[i] != None) + srcMimeTypeAtomList.add (types[i]); + } + + XFree (data); + } + } + + if (srcMimeTypeAtomList.size() == 0) + { + for (int i = 2; i < 5; ++i) + if (clientMsg->data.l[i] != None) + srcMimeTypeAtomList.add (clientMsg->data.l[i]); + + if (srcMimeTypeAtomList.size() == 0) + { + dragAndDropSourceWindow = 0; + return; + } + } + + for (int i = 0; i < srcMimeTypeAtomList.size() && dragAndDropCurrentMimeType == 0; ++i) + for (int j = 0; j < numElementsInArray (allowedMimeTypeAtoms); ++j) + if (srcMimeTypeAtomList[i] == allowedMimeTypeAtoms[j]) + dragAndDropCurrentMimeType = allowedMimeTypeAtoms[j]; + + handleDragAndDropPosition (clientMsg); + } + + void handleDragAndDropSelection (const XEvent* const evt) + { + dragAndDropFiles.clear(); + + if (evt->xselection.property != 0) + { + StringArray lines; + + { + MemoryBlock dropData; + + for (;;) + { + Atom actual; + uint8* data = 0; + unsigned long count = 0, remaining = 0; + int format = 0; + + if (XGetWindowProperty (display, evt->xany.window, evt->xselection.property, + dropData.getSize() / 4, 65536, 1, AnyPropertyType, &actual, + &format, &count, &remaining, &data) == Success) + { + dropData.append (data, count * format / 8); + XFree (data); + + if (remaining == 0) + break; + } + else + { + XFree (data); + break; + } + } + + lines.addLines (dropData.toString()); + } + + for (int i = 0; i < lines.size(); ++i) + dragAndDropFiles.add (URL::removeEscapeChars (lines[i].fromFirstOccurrenceOf (T("file://"), false, true))); + + dragAndDropFiles.trim(); + dragAndDropFiles.removeEmptyStrings(); + } + } + + void updateDraggedFileList (const XClientMessageEvent* const clientMsg) + { + dragAndDropFiles.clear(); + + if (dragAndDropSourceWindow != None + && dragAndDropCurrentMimeType != 0) + { + dragAndDropTimestamp = clientMsg->data.l[2]; + + XConvertSelection (display, + XA_XdndSelection, + dragAndDropCurrentMimeType, + XA_JXSelectionWindowProperty, + windowH, + dragAndDropTimestamp); + } + } + + StringArray dragAndDropFiles; + int dragAndDropTimestamp, lastDropX, lastDropY; + + Atom XA_OtherMime, dragAndDropCurrentMimeType; + Window dragAndDropSourceWindow; + + unsigned int allowedActions [5]; + unsigned int allowedMimeTypeAtoms [3]; + Array srcMimeTypeAtomList; }; void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool allowMenusAndBars) { - if (enableOrDisable) - kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); + if (enableOrDisable) + kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); } ComponentPeer* Component::createNewPeer (int styleFlags, void* /*nativeWindowToAttachTo*/) { - return new LinuxComponentPeer (this, styleFlags); + return new LinuxComponentPeer (this, styleFlags); } // (this callback is hooked up in the messaging code) void juce_windowMessageReceive (XEvent* event) { - if (event->xany.window != None) - { - LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (event->xany.window); + if (event->xany.window != None) + { + LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (event->xany.window); - if (ComponentPeer::isValidPeer (peer)) - peer->handleWindowMessage (event); - } - else - { - switch (event->xany.type) - { - case KeymapNotify: - { - const XKeymapEvent* const keymapEvent = (const XKeymapEvent*) &event->xkeymap; - memcpy (keyStates, keymapEvent->key_vector, 32); - break; - } + if (ComponentPeer::isValidPeer (peer)) + peer->handleWindowMessage (event); + } + else + { + switch (event->xany.type) + { + case KeymapNotify: + { + const XKeymapEvent* const keymapEvent = (const XKeymapEvent*) &event->xkeymap; + memcpy (keyStates, keymapEvent->key_vector, 32); + break; + } - default: - break; - } - } + default: + break; + } + } } -void juce_updateMultiMonitorInfo (Array & monitorCoords, const bool /*clipToWorkArea*/) throw() +void juce_updateMultiMonitorInfo (Array & monitorCoords, const bool /*clipToWorkArea*/) { - if (display == 0) - return; + if (display == 0) + return; #if JUCE_USE_XINERAMA - int major_opcode, first_event, first_error; + int major_opcode, first_event, first_error; - if (XQueryExtension (display, "XINERAMA", &major_opcode, &first_event, &first_error)) - { - typedef Bool (*tXineramaIsActive) (Display*); - typedef XineramaScreenInfo* (*tXineramaQueryScreens) (Display*, int*); + if (XQueryExtension (display, "XINERAMA", &major_opcode, &first_event, &first_error)) + { + typedef Bool (*tXineramaIsActive) (Display*); + typedef XineramaScreenInfo* (*tXineramaQueryScreens) (Display*, int*); - static tXineramaIsActive xXineramaIsActive = 0; - static tXineramaQueryScreens xXineramaQueryScreens = 0; + static tXineramaIsActive xXineramaIsActive = 0; + static tXineramaQueryScreens xXineramaQueryScreens = 0; - if (xXineramaIsActive == 0 || xXineramaQueryScreens == 0) - { - void* h = dlopen ("libXinerama.so", RTLD_GLOBAL | RTLD_NOW); + if (xXineramaIsActive == 0 || xXineramaQueryScreens == 0) + { + void* h = dlopen ("libXinerama.so", RTLD_GLOBAL | RTLD_NOW); - if (h != 0) - { - xXineramaIsActive = (tXineramaIsActive) dlsym (h, "XineramaIsActive"); - xXineramaQueryScreens = (tXineramaQueryScreens) dlsym (h, "XineramaQueryScreens"); - } - } + if (h != 0) + { + xXineramaIsActive = (tXineramaIsActive) dlsym (h, "XineramaIsActive"); + xXineramaQueryScreens = (tXineramaQueryScreens) dlsym (h, "XineramaQueryScreens"); + } + } - if (xXineramaIsActive != 0 - && xXineramaQueryScreens != 0 - && xXineramaIsActive (display)) - { - int numMonitors = 0; - XineramaScreenInfo* const screens = xXineramaQueryScreens (display, &numMonitors); + if (xXineramaIsActive != 0 + && xXineramaQueryScreens != 0 + && xXineramaIsActive (display)) + { + int numMonitors = 0; + XineramaScreenInfo* const screens = xXineramaQueryScreens (display, &numMonitors); - if (screens != 0) - { - for (int i = numMonitors; --i >= 0;) - { - int index = screens[i].screen_number; + if (screens != 0) + { + for (int i = numMonitors; --i >= 0;) + { + int index = screens[i].screen_number; - if (index >= 0) - { - while (monitorCoords.size() < index) - monitorCoords.add (Rectangle (0, 0, 0, 0)); + if (index >= 0) + { + while (monitorCoords.size() < index) + monitorCoords.add (Rectangle (0, 0, 0, 0)); - monitorCoords.set (index, Rectangle (screens[i].x_org, - screens[i].y_org, - screens[i].width, - screens[i].height)); - } - } + monitorCoords.set (index, Rectangle (screens[i].x_org, + screens[i].y_org, + screens[i].width, + screens[i].height)); + } + } - XFree (screens); - } - } - } + XFree (screens); + } + } + } - if (monitorCoords.size() == 0) + if (monitorCoords.size() == 0) #endif - { - Atom hints = XInternAtom (display, "_NET_WORKAREA", True); + { + Atom hints = XInternAtom (display, "_NET_WORKAREA", True); - if (hints != None) - { - const int numMonitors = ScreenCount (display); + if (hints != None) + { + const int numMonitors = ScreenCount (display); - for (int i = 0; i < numMonitors; ++i) - { - Window root = RootWindow (display, i); + for (int i = 0; i < numMonitors; ++i) + { + Window root = RootWindow (display, i); - unsigned long nitems, bytesLeft; - Atom actualType; - int actualFormat; - unsigned char* data = 0; + unsigned long nitems, bytesLeft; + Atom actualType; + int actualFormat; + unsigned char* data = 0; - if (XGetWindowProperty (display, root, hints, 0, 4, False, - XA_CARDINAL, &actualType, &actualFormat, &nitems, &bytesLeft, - &data) == Success) - { - const long* const position = (const long*) data; + if (XGetWindowProperty (display, root, hints, 0, 4, False, + XA_CARDINAL, &actualType, &actualFormat, &nitems, &bytesLeft, + &data) == Success) + { + const long* const position = (const long*) data; - if (actualType == XA_CARDINAL && actualFormat == 32 && nitems == 4) - monitorCoords.add (Rectangle (position[0], position[1], - position[2], position[3])); + if (actualType == XA_CARDINAL && actualFormat == 32 && nitems == 4) + monitorCoords.add (Rectangle (position[0], position[1], + position[2], position[3])); - XFree (data); - } - } - } + XFree (data); + } + } + } - if (monitorCoords.size() == 0) - { - monitorCoords.add (Rectangle (0, 0, - DisplayWidth (display, DefaultScreen (display)), - DisplayHeight (display, DefaultScreen (display)))); - } - } + if (monitorCoords.size() == 0) + { + monitorCoords.add (Rectangle (0, 0, + DisplayWidth (display, DefaultScreen (display)), + DisplayHeight (display, DefaultScreen (display)))); + } + } } bool Desktop::canUseSemiTransparentWindows() throw() { - return false; + return false; } void Desktop::getMousePosition (int& x, int& y) throw() { - int mouseMods; - getMousePos (x, y, mouseMods); + int mouseMods; + getMousePos (x, y, mouseMods); } void Desktop::setMousePosition (int x, int y) throw() { - Window root = RootWindow (display, DefaultScreen (display)); - XWarpPointer (display, None, root, 0, 0, 0, 0, x, y); + Window root = RootWindow (display, DefaultScreen (display)); + XWarpPointer (display, None, root, 0, 0, 0, 0, x, y); } static bool screenSaverAllowed = true; void Desktop::setScreenSaverEnabled (const bool isEnabled) throw() { - if (screenSaverAllowed != isEnabled) - { - screenSaverAllowed = isEnabled; + if (screenSaverAllowed != isEnabled) + { + screenSaverAllowed = isEnabled; - typedef void (*tXScreenSaverSuspend) (Display*, Bool); - static tXScreenSaverSuspend xScreenSaverSuspend = 0; + typedef void (*tXScreenSaverSuspend) (Display*, Bool); + static tXScreenSaverSuspend xScreenSaverSuspend = 0; - if (xScreenSaverSuspend == 0) - { - void* h = dlopen ("libXss.so", RTLD_GLOBAL | RTLD_NOW); + if (xScreenSaverSuspend == 0) + { + void* h = dlopen ("libXss.so", RTLD_GLOBAL | RTLD_NOW); - if (h != 0) - xScreenSaverSuspend = (tXScreenSaverSuspend) dlsym (h, "XScreenSaverSuspend"); - } + if (h != 0) + xScreenSaverSuspend = (tXScreenSaverSuspend) dlsym (h, "XScreenSaverSuspend"); + } - if (xScreenSaverSuspend != 0) - xScreenSaverSuspend (display, ! isEnabled); - } + if (xScreenSaverSuspend != 0) + xScreenSaverSuspend (display, ! isEnabled); + } } bool Desktop::isScreenSaverEnabled() throw() { - return screenSaverAllowed; + return screenSaverAllowed; } void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) throw() { - Window root = RootWindow (display, DefaultScreen (display)); - const unsigned int imageW = image.getWidth(); - const unsigned int imageH = image.getHeight(); - unsigned int cursorW, cursorH; + Window root = RootWindow (display, DefaultScreen (display)); + const unsigned int imageW = image.getWidth(); + const unsigned int imageH = image.getHeight(); + unsigned int cursorW, cursorH; - if (! XQueryBestCursor (display, root, imageW, imageH, &cursorW, &cursorH)) - return 0; + if (! XQueryBestCursor (display, root, imageW, imageH, &cursorW, &cursorH)) + return 0; - Image im (Image::ARGB, cursorW, cursorH, true); - Graphics g (im); + Image im (Image::ARGB, cursorW, cursorH, true); + Graphics g (im); - if (imageW > cursorW || imageH > cursorH) - { - hotspotX = (hotspotX * cursorW) / imageW; - hotspotY = (hotspotY * cursorH) / imageH; + if (imageW > cursorW || imageH > cursorH) + { + hotspotX = (hotspotX * cursorW) / imageW; + hotspotY = (hotspotY * cursorH) / imageH; - g.drawImageWithin (&image, 0, 0, imageW, imageH, - RectanglePlacement::xLeft | RectanglePlacement::yTop | RectanglePlacement::onlyReduceInSize, - false); - } - else - { - g.drawImageAt (&image, 0, 0); - } + g.drawImageWithin (&image, 0, 0, imageW, imageH, + RectanglePlacement::xLeft | RectanglePlacement::yTop | RectanglePlacement::onlyReduceInSize, + false); + } + else + { + g.drawImageAt (&image, 0, 0); + } - const int stride = (cursorW + 7) >> 3; - HeapBlock maskPlane, sourcePlane; - maskPlane.calloc (stride * cursorH); - sourcePlane.calloc (stride * cursorH); + const int stride = (cursorW + 7) >> 3; + HeapBlock maskPlane, sourcePlane; + maskPlane.calloc (stride * cursorH); + sourcePlane.calloc (stride * cursorH); - const bool msbfirst = (BitmapBitOrder (display) == MSBFirst); + const bool msbfirst = (BitmapBitOrder (display) == MSBFirst); - for (int y = cursorH; --y >= 0;) - { - for (int x = cursorW; --x >= 0;) - { - const uint8 mask = (uint8) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7))); - const int offset = y * stride + (x >> 3); + for (int y = cursorH; --y >= 0;) + { + for (int x = cursorW; --x >= 0;) + { + const uint8 mask = (uint8) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7))); + const int offset = y * stride + (x >> 3); - const Colour c (im.getPixelAt (x, y)); + const Colour c (im.getPixelAt (x, y)); - if (c.getAlpha() >= 128) - maskPlane[offset] |= mask; + if (c.getAlpha() >= 128) + maskPlane[offset] |= mask; - if (c.getBrightness() >= 0.5f) - sourcePlane[offset] |= mask; - } - } + if (c.getBrightness() >= 0.5f) + sourcePlane[offset] |= mask; + } + } - Pixmap sourcePixmap = XCreatePixmapFromBitmapData (display, root, (char*) sourcePlane, cursorW, cursorH, 0xffff, 0, 1); - Pixmap maskPixmap = XCreatePixmapFromBitmapData (display, root, (char*) maskPlane, cursorW, cursorH, 0xffff, 0, 1); + Pixmap sourcePixmap = XCreatePixmapFromBitmapData (display, root, (char*) sourcePlane, cursorW, cursorH, 0xffff, 0, 1); + Pixmap maskPixmap = XCreatePixmapFromBitmapData (display, root, (char*) maskPlane, cursorW, cursorH, 0xffff, 0, 1); - XColor white, black; - black.red = black.green = black.blue = 0; - white.red = white.green = white.blue = 0xffff; + XColor white, black; + black.red = black.green = black.blue = 0; + white.red = white.green = white.blue = 0xffff; - void* result = (void*) XCreatePixmapCursor (display, sourcePixmap, maskPixmap, &white, &black, hotspotX, hotspotY); + void* result = (void*) XCreatePixmapCursor (display, sourcePixmap, maskPixmap, &white, &black, hotspotX, hotspotY); - XFreePixmap (display, sourcePixmap); - XFreePixmap (display, maskPixmap); + XFreePixmap (display, sourcePixmap); + XFreePixmap (display, maskPixmap); - return result; + return result; } void juce_deleteMouseCursor (void* const cursorHandle, const bool) throw() { - if (cursorHandle != None) - XFreeCursor (display, (Cursor) cursorHandle); + if (cursorHandle != None) + XFreeCursor (display, (Cursor) cursorHandle); } void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type) throw() { - unsigned int shape; + unsigned int shape; - switch (type) - { - case MouseCursor::NoCursor: - { - const Image im (Image::ARGB, 16, 16, true); - return juce_createMouseCursorFromImage (im, 0, 0); - } + switch (type) + { + case MouseCursor::NoCursor: + { + const Image im (Image::ARGB, 16, 16, true); + return juce_createMouseCursorFromImage (im, 0, 0); + } - case MouseCursor::NormalCursor: - return (void*) None; // Use parent cursor + case MouseCursor::NormalCursor: + return (void*) None; // Use parent cursor - case MouseCursor::DraggingHandCursor: - { - static unsigned char dragHandData[] = {71,73,70,56,57,97,16,0,16,0,145,2,0,0,0,0,255,255,255,0, - 0,0,0,0,0,33,249,4,1,0,0,2,0,44,0,0,0,0,16,0, - 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39, - 132,117,151,116,132,146,248,60,209,138,98,22,203,114,34,236,37,52,77,217, - 247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 }; - const int dragHandDataSize = 99; + case MouseCursor::DraggingHandCursor: + { + static unsigned char dragHandData[] = {71,73,70,56,57,97,16,0,16,0,145,2,0,0,0,0,255,255,255,0, + 0,0,0,0,0,33,249,4,1,0,0,2,0,44,0,0,0,0,16,0, + 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39, + 132,117,151,116,132,146,248,60,209,138,98,22,203,114,34,236,37,52,77,217, + 247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 }; + const int dragHandDataSize = 99; - const ScopedPointer im (ImageFileFormat::loadFrom ((const char*) dragHandData, dragHandDataSize)); - return juce_createMouseCursorFromImage (*im, 8, 7); - } + const ScopedPointer im (ImageFileFormat::loadFrom ((const char*) dragHandData, dragHandDataSize)); + return juce_createMouseCursorFromImage (*im, 8, 7); + } - case MouseCursor::CopyingCursor: - { - static unsigned char copyCursorData[] = {71,73,70,56,57,97,21,0,21,0,145,0,0,0,0,0,255,255,255,0, - 128,128,255,255,255,33,249,4,1,0,0,3,0,44,0,0,0,0,21,0, - 21,0,0,2,72,4,134,169,171,16,199,98,11,79,90,71,161,93,56,111, - 78,133,218,215,137,31,82,154,100,200,86,91,202,142,12,108,212,87,235,174, - 15,54,214,126,237,226,37,96,59,141,16,37,18,201,142,157,230,204,51,112, - 252,114,147,74,83,5,50,68,147,208,217,16,71,149,252,124,5,0,59,0,0 }; - const int copyCursorSize = 119; + case MouseCursor::CopyingCursor: + { + static unsigned char copyCursorData[] = {71,73,70,56,57,97,21,0,21,0,145,0,0,0,0,0,255,255,255,0, + 128,128,255,255,255,33,249,4,1,0,0,3,0,44,0,0,0,0,21,0, + 21,0,0,2,72,4,134,169,171,16,199,98,11,79,90,71,161,93,56,111, + 78,133,218,215,137,31,82,154,100,200,86,91,202,142,12,108,212,87,235,174, + 15,54,214,126,237,226,37,96,59,141,16,37,18,201,142,157,230,204,51,112, + 252,114,147,74,83,5,50,68,147,208,217,16,71,149,252,124,5,0,59,0,0 }; + const int copyCursorSize = 119; - const ScopedPointer im (ImageFileFormat::loadFrom ((const char*) copyCursorData, copyCursorSize)); - return juce_createMouseCursorFromImage (*im, 1, 3); - } + const ScopedPointer im (ImageFileFormat::loadFrom ((const char*) copyCursorData, copyCursorSize)); + return juce_createMouseCursorFromImage (*im, 1, 3); + } - case MouseCursor::WaitCursor: - shape = XC_watch; - break; + case MouseCursor::WaitCursor: + shape = XC_watch; + break; - case MouseCursor::IBeamCursor: - shape = XC_xterm; - break; + case MouseCursor::IBeamCursor: + shape = XC_xterm; + break; - case MouseCursor::PointingHandCursor: - shape = XC_hand2; - break; + case MouseCursor::PointingHandCursor: + shape = XC_hand2; + break; - case MouseCursor::LeftRightResizeCursor: - shape = XC_sb_h_double_arrow; - break; + case MouseCursor::LeftRightResizeCursor: + shape = XC_sb_h_double_arrow; + break; - case MouseCursor::UpDownResizeCursor: - shape = XC_sb_v_double_arrow; - break; + case MouseCursor::UpDownResizeCursor: + shape = XC_sb_v_double_arrow; + break; - case MouseCursor::UpDownLeftRightResizeCursor: - shape = XC_fleur; - break; + case MouseCursor::UpDownLeftRightResizeCursor: + shape = XC_fleur; + break; - case MouseCursor::TopEdgeResizeCursor: - shape = XC_top_side; - break; + case MouseCursor::TopEdgeResizeCursor: + shape = XC_top_side; + break; - case MouseCursor::BottomEdgeResizeCursor: - shape = XC_bottom_side; - break; + case MouseCursor::BottomEdgeResizeCursor: + shape = XC_bottom_side; + break; - case MouseCursor::LeftEdgeResizeCursor: - shape = XC_left_side; - break; + case MouseCursor::LeftEdgeResizeCursor: + shape = XC_left_side; + break; - case MouseCursor::RightEdgeResizeCursor: - shape = XC_right_side; - break; + case MouseCursor::RightEdgeResizeCursor: + shape = XC_right_side; + break; - case MouseCursor::TopLeftCornerResizeCursor: - shape = XC_top_left_corner; - break; + case MouseCursor::TopLeftCornerResizeCursor: + shape = XC_top_left_corner; + break; - case MouseCursor::TopRightCornerResizeCursor: - shape = XC_top_right_corner; - break; + case MouseCursor::TopRightCornerResizeCursor: + shape = XC_top_right_corner; + break; - case MouseCursor::BottomLeftCornerResizeCursor: - shape = XC_bottom_left_corner; - break; + case MouseCursor::BottomLeftCornerResizeCursor: + shape = XC_bottom_left_corner; + break; - case MouseCursor::BottomRightCornerResizeCursor: - shape = XC_bottom_right_corner; - break; + case MouseCursor::BottomRightCornerResizeCursor: + shape = XC_bottom_right_corner; + break; - case MouseCursor::CrosshairCursor: - shape = XC_crosshair; - break; + case MouseCursor::CrosshairCursor: + shape = XC_crosshair; + break; - default: - return (void*) None; // Use parent cursor - } + default: + return (void*) None; // Use parent cursor + } - return (void*) XCreateFontCursor (display, shape); + return (void*) XCreateFontCursor (display, shape); } void MouseCursor::showInWindow (ComponentPeer* peer) const throw() { - LinuxComponentPeer* const lp = dynamic_cast (peer); + LinuxComponentPeer* const lp = dynamic_cast (peer); - if (lp != 0) - lp->showMouseCursor ((Cursor) getHandle()); + if (lp != 0) + lp->showMouseCursor ((Cursor) getHandle()); } void MouseCursor::showInAllWindows() const throw() { - for (int i = ComponentPeer::getNumPeers(); --i >= 0;) - showInWindow (ComponentPeer::getPeer (i)); + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) + showInWindow (ComponentPeer::getPeer (i)); } Image* juce_createIconForFile (const File& file) { - return 0; + return 0; } Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage) { - return new Image (format, imageWidth, imageHeight, clearImage); + return new Image (format, imageWidth, imageHeight, clearImage); } #if JUCE_OPENGL -class WindowedGLContext : public OpenGLContext +class WindowedGLContext : public OpenGLContext { public: - WindowedGLContext (Component* const component, - const OpenGLPixelFormat& pixelFormat_, - GLXContext sharedContext) - : renderContext (0), - embeddedWindow (0), - pixelFormat (pixelFormat_) - { - jassert (component != 0); - LinuxComponentPeer* const peer = dynamic_cast (component->getTopLevelComponent()->getPeer()); - if (peer == 0) - return; + WindowedGLContext (Component* const component, + const OpenGLPixelFormat& pixelFormat_, + GLXContext sharedContext) + : renderContext (0), + embeddedWindow (0), + pixelFormat (pixelFormat_) + { + jassert (component != 0); + LinuxComponentPeer* const peer = dynamic_cast (component->getTopLevelComponent()->getPeer()); + if (peer == 0) + return; - XSync (display, False); + XSync (display, False); - GLint attribs [64]; - int n = 0; - attribs[n++] = GLX_RGBA; - attribs[n++] = GLX_DOUBLEBUFFER; - attribs[n++] = GLX_RED_SIZE; - attribs[n++] = pixelFormat.redBits; - attribs[n++] = GLX_GREEN_SIZE; - attribs[n++] = pixelFormat.greenBits; - attribs[n++] = GLX_BLUE_SIZE; - attribs[n++] = pixelFormat.blueBits; - attribs[n++] = GLX_ALPHA_SIZE; - attribs[n++] = pixelFormat.alphaBits; - attribs[n++] = GLX_DEPTH_SIZE; - attribs[n++] = pixelFormat.depthBufferBits; - attribs[n++] = GLX_STENCIL_SIZE; - attribs[n++] = pixelFormat.stencilBufferBits; - attribs[n++] = GLX_ACCUM_RED_SIZE; - attribs[n++] = pixelFormat.accumulationBufferRedBits; - attribs[n++] = GLX_ACCUM_GREEN_SIZE; - attribs[n++] = pixelFormat.accumulationBufferGreenBits; - attribs[n++] = GLX_ACCUM_BLUE_SIZE; - attribs[n++] = pixelFormat.accumulationBufferBlueBits; - attribs[n++] = GLX_ACCUM_ALPHA_SIZE; - attribs[n++] = pixelFormat.accumulationBufferAlphaBits; + GLint attribs [64]; + int n = 0; + attribs[n++] = GLX_RGBA; + attribs[n++] = GLX_DOUBLEBUFFER; + attribs[n++] = GLX_RED_SIZE; + attribs[n++] = pixelFormat.redBits; + attribs[n++] = GLX_GREEN_SIZE; + attribs[n++] = pixelFormat.greenBits; + attribs[n++] = GLX_BLUE_SIZE; + attribs[n++] = pixelFormat.blueBits; + attribs[n++] = GLX_ALPHA_SIZE; + attribs[n++] = pixelFormat.alphaBits; + attribs[n++] = GLX_DEPTH_SIZE; + attribs[n++] = pixelFormat.depthBufferBits; + attribs[n++] = GLX_STENCIL_SIZE; + attribs[n++] = pixelFormat.stencilBufferBits; + attribs[n++] = GLX_ACCUM_RED_SIZE; + attribs[n++] = pixelFormat.accumulationBufferRedBits; + attribs[n++] = GLX_ACCUM_GREEN_SIZE; + attribs[n++] = pixelFormat.accumulationBufferGreenBits; + attribs[n++] = GLX_ACCUM_BLUE_SIZE; + attribs[n++] = pixelFormat.accumulationBufferBlueBits; + attribs[n++] = GLX_ACCUM_ALPHA_SIZE; + attribs[n++] = pixelFormat.accumulationBufferAlphaBits; - // xxx not sure how to do fullSceneAntiAliasingNumSamples on linux.. + // xxx not sure how to do fullSceneAntiAliasingNumSamples on linux.. - attribs[n++] = None; + attribs[n++] = None; - XVisualInfo* const bestVisual = glXChooseVisual (display, DefaultScreen (display), attribs); + XVisualInfo* const bestVisual = glXChooseVisual (display, DefaultScreen (display), attribs); - if (bestVisual == 0) - return; + if (bestVisual == 0) + return; - renderContext = glXCreateContext (display, bestVisual, sharedContext, GL_TRUE); + renderContext = glXCreateContext (display, bestVisual, sharedContext, GL_TRUE); - Window windowH = (Window) peer->getNativeHandle(); + Window windowH = (Window) peer->getNativeHandle(); - Colormap colourMap = XCreateColormap (display, windowH, bestVisual->visual, AllocNone); - XSetWindowAttributes swa; - swa.colormap = colourMap; - swa.border_pixel = 0; - swa.event_mask = ExposureMask | StructureNotifyMask; + Colormap colourMap = XCreateColormap (display, windowH, bestVisual->visual, AllocNone); + XSetWindowAttributes swa; + swa.colormap = colourMap; + swa.border_pixel = 0; + swa.event_mask = ExposureMask | StructureNotifyMask; - embeddedWindow = XCreateWindow (display, windowH, - 0, 0, 1, 1, 0, - bestVisual->depth, - InputOutput, - bestVisual->visual, - CWBorderPixel | CWColormap | CWEventMask, - &swa); + embeddedWindow = XCreateWindow (display, windowH, + 0, 0, 1, 1, 0, + bestVisual->depth, + InputOutput, + bestVisual->visual, + CWBorderPixel | CWColormap | CWEventMask, + &swa); - XSaveContext (display, (XID) embeddedWindow, improbableNumber, (XPointer) peer); + XSaveContext (display, (XID) embeddedWindow, improbableNumber, (XPointer) peer); - XMapWindow (display, embeddedWindow); - XFreeColormap (display, colourMap); + XMapWindow (display, embeddedWindow); + XFreeColormap (display, colourMap); - XFree (bestVisual); - XSync (display, False); - } + XFree (bestVisual); + XSync (display, False); + } - ~WindowedGLContext() - { - makeInactive(); + ~WindowedGLContext() + { + makeInactive(); - glXDestroyContext (display, renderContext); + glXDestroyContext (display, renderContext); - XUnmapWindow (display, embeddedWindow); - XDestroyWindow (display, embeddedWindow); - } + XUnmapWindow (display, embeddedWindow); + XDestroyWindow (display, embeddedWindow); + } - bool makeActive() const throw() - { - jassert (renderContext != 0); + bool makeActive() const throw() + { + jassert (renderContext != 0); - return glXMakeCurrent (display, embeddedWindow, renderContext) - && XSync (display, False); - } + return glXMakeCurrent (display, embeddedWindow, renderContext) + && XSync (display, False); + } - bool makeInactive() const throw() - { - return (! isActive()) || glXMakeCurrent (display, None, 0); - } + bool makeInactive() const throw() + { + return (! isActive()) || glXMakeCurrent (display, None, 0); + } - bool isActive() const throw() - { - return glXGetCurrentContext() == renderContext; - } + bool isActive() const throw() + { + return glXGetCurrentContext() == renderContext; + } - const OpenGLPixelFormat getPixelFormat() const - { - return pixelFormat; - } + const OpenGLPixelFormat getPixelFormat() const + { + return pixelFormat; + } - void* getRawContext() const throw() - { - return renderContext; - } + void* getRawContext() const throw() + { + return renderContext; + } - void updateWindowPosition (int x, int y, int w, int h, int) - { - XMoveResizeWindow (display, embeddedWindow, - x, y, jmax (1, w), jmax (1, h)); - } + void updateWindowPosition (int x, int y, int w, int h, int) + { + XMoveResizeWindow (display, embeddedWindow, + x, y, jmax (1, w), jmax (1, h)); + } - void swapBuffers() - { - glXSwapBuffers (display, embeddedWindow); - } + void swapBuffers() + { + glXSwapBuffers (display, embeddedWindow); + } - bool setSwapInterval (const int numFramesPerSwap) - { - // xxx needs doing.. - return false; - } + bool setSwapInterval (const int numFramesPerSwap) + { + // xxx needs doing.. + return false; + } - int getSwapInterval() const - { - // xxx needs doing.. - return 0; - } + int getSwapInterval() const + { + // xxx needs doing.. + return 0; + } - void repaint() - { - } + void repaint() + { + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - GLXContext renderContext; + GLXContext renderContext; private: - Window embeddedWindow; - OpenGLPixelFormat pixelFormat; + Window embeddedWindow; + OpenGLPixelFormat pixelFormat; - WindowedGLContext (const WindowedGLContext&); - const WindowedGLContext& operator= (const WindowedGLContext&); + WindowedGLContext (const WindowedGLContext&); + const WindowedGLContext& operator= (const WindowedGLContext&); }; OpenGLContext* OpenGLContext::createContextForWindow (Component* const component, - const OpenGLPixelFormat& pixelFormat, - const OpenGLContext* const contextToShareWith) + const OpenGLPixelFormat& pixelFormat, + const OpenGLContext* const contextToShareWith) { - WindowedGLContext* c = new WindowedGLContext (component, pixelFormat, - contextToShareWith != 0 ? (GLXContext) contextToShareWith->getRawContext() : 0); + WindowedGLContext* c = new WindowedGLContext (component, pixelFormat, + contextToShareWith != 0 ? (GLXContext) contextToShareWith->getRawContext() : 0); - if (c->renderContext == 0) - deleteAndZero (c); + if (c->renderContext == 0) + deleteAndZero (c); - return c; + return c; } void juce_glViewport (const int w, const int h) { - glViewport (0, 0, w, h); + glViewport (0, 0, w, h); } void OpenGLPixelFormat::getAvailablePixelFormats (Component* component, - OwnedArray & results) + OwnedArray & results) { - results.add (new OpenGLPixelFormat()); // xxx + results.add (new OpenGLPixelFormat()); // xxx } #endif bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, const bool canMoveFiles) { - jassertfalse // not implemented! - return false; + jassertfalse // not implemented! + return false; } bool DragAndDropContainer::performExternalDragDropOfText (const String& text) { - jassertfalse // not implemented! - return false; + jassertfalse // not implemented! + return false; } void SystemTrayIconComponent::setIconImage (const Image& newImage) { - if (! isOnDesktop ()) - addToDesktop (0); + if (! isOnDesktop ()) + addToDesktop (0); - LinuxComponentPeer* const wp = dynamic_cast (getPeer()); + LinuxComponentPeer* const wp = dynamic_cast (getPeer()); - if (wp != 0) - { - wp->setTaskBarIcon (newImage); + if (wp != 0) + { + wp->setTaskBarIcon (newImage); - setVisible (true); - toFront (false); - repaint(); - } + setVisible (true); + toFront (false); + repaint(); + } } void SystemTrayIconComponent::paint (Graphics& g) { - LinuxComponentPeer* const wp = dynamic_cast (getPeer()); + LinuxComponentPeer* const wp = dynamic_cast (getPeer()); - if (wp != 0) - { - const Image* const image = wp->getTaskbarIcon(); + if (wp != 0) + { + const Image* const image = wp->getTaskbarIcon(); - if (image != 0) - { - g.drawImageWithin (image, 0, 0, getWidth(), getHeight(), - RectanglePlacement::xLeft | RectanglePlacement::yTop | RectanglePlacement::onlyReduceInSize, - false); - } - } + if (image != 0) + { + g.drawImageWithin (image, 0, 0, getWidth(), getHeight(), + RectanglePlacement::xLeft | RectanglePlacement::yTop | RectanglePlacement::onlyReduceInSize, + false); + } + } } void SystemTrayIconComponent::setIconTooltip (const String& tooltip) { - // xxx not yet implemented! + // xxx not yet implemented! } void PlatformUtilities::beep() { - fprintf (stdout, "\a"); - fflush (stdout); + fprintf (stdout, "\a"); + fflush (stdout); } bool AlertWindow::showNativeDialogBox (const String& title, - const String& bodyText, - bool isOkCancel) + const String& bodyText, + bool isOkCancel) { - // xxx this is supposed to pop up an alert! - Logger::outputDebugString (title + ": " + bodyText); + // xxx this is supposed to pop up an alert! + Logger::outputDebugString (title + ": " + bodyText); - // use a non-native one for the time being.. - if (isOkCancel) - return AlertWindow::showOkCancelBox (AlertWindow::NoIcon, title, bodyText); - else - AlertWindow::showMessageBox (AlertWindow::NoIcon, title, bodyText); + // use a non-native one for the time being.. + if (isOkCancel) + return AlertWindow::showOkCancelBox (AlertWindow::NoIcon, title, bodyText); + else + AlertWindow::showMessageBox (AlertWindow::NoIcon, title, bodyText); - return true; + return true; } -const int KeyPress::spaceKey = XK_space & 0xff; -const int KeyPress::returnKey = XK_Return & 0xff; -const int KeyPress::escapeKey = XK_Escape & 0xff; -const int KeyPress::backspaceKey = XK_BackSpace & 0xff; -const int KeyPress::leftKey = (XK_Left & 0xff) | extendedKeyModifier; -const int KeyPress::rightKey = (XK_Right & 0xff) | extendedKeyModifier; -const int KeyPress::upKey = (XK_Up & 0xff) | extendedKeyModifier; -const int KeyPress::downKey = (XK_Down & 0xff) | extendedKeyModifier; -const int KeyPress::pageUpKey = (XK_Page_Up & 0xff) | extendedKeyModifier; -const int KeyPress::pageDownKey = (XK_Page_Down & 0xff) | extendedKeyModifier; -const int KeyPress::endKey = (XK_End & 0xff) | extendedKeyModifier; -const int KeyPress::homeKey = (XK_Home & 0xff) | extendedKeyModifier; -const int KeyPress::insertKey = (XK_Insert & 0xff) | extendedKeyModifier; -const int KeyPress::deleteKey = (XK_Delete & 0xff) | extendedKeyModifier; -const int KeyPress::tabKey = XK_Tab & 0xff; -const int KeyPress::F1Key = (XK_F1 & 0xff) | extendedKeyModifier; -const int KeyPress::F2Key = (XK_F2 & 0xff) | extendedKeyModifier; -const int KeyPress::F3Key = (XK_F3 & 0xff) | extendedKeyModifier; -const int KeyPress::F4Key = (XK_F4 & 0xff) | extendedKeyModifier; -const int KeyPress::F5Key = (XK_F5 & 0xff) | extendedKeyModifier; -const int KeyPress::F6Key = (XK_F6 & 0xff) | extendedKeyModifier; -const int KeyPress::F7Key = (XK_F7 & 0xff) | extendedKeyModifier; -const int KeyPress::F8Key = (XK_F8 & 0xff) | extendedKeyModifier; -const int KeyPress::F9Key = (XK_F9 & 0xff) | extendedKeyModifier; -const int KeyPress::F10Key = (XK_F10 & 0xff) | extendedKeyModifier; -const int KeyPress::F11Key = (XK_F11 & 0xff) | extendedKeyModifier; -const int KeyPress::F12Key = (XK_F12 & 0xff) | extendedKeyModifier; -const int KeyPress::F13Key = (XK_F13 & 0xff) | extendedKeyModifier; -const int KeyPress::F14Key = (XK_F14 & 0xff) | extendedKeyModifier; -const int KeyPress::F15Key = (XK_F15 & 0xff) | extendedKeyModifier; -const int KeyPress::F16Key = (XK_F16 & 0xff) | extendedKeyModifier; -const int KeyPress::numberPad0 = (XK_KP_0 & 0xff) | extendedKeyModifier; -const int KeyPress::numberPad1 = (XK_KP_1 & 0xff) | extendedKeyModifier; -const int KeyPress::numberPad2 = (XK_KP_2 & 0xff) | extendedKeyModifier; -const int KeyPress::numberPad3 = (XK_KP_3 & 0xff) | extendedKeyModifier; -const int KeyPress::numberPad4 = (XK_KP_4 & 0xff) | extendedKeyModifier; -const int KeyPress::numberPad5 = (XK_KP_5 & 0xff) | extendedKeyModifier; -const int KeyPress::numberPad6 = (XK_KP_6 & 0xff) | extendedKeyModifier; -const int KeyPress::numberPad7 = (XK_KP_7 & 0xff)| extendedKeyModifier; -const int KeyPress::numberPad8 = (XK_KP_8 & 0xff)| extendedKeyModifier; -const int KeyPress::numberPad9 = (XK_KP_9 & 0xff)| extendedKeyModifier; -const int KeyPress::numberPadAdd = (XK_KP_Add & 0xff)| extendedKeyModifier; -const int KeyPress::numberPadSubtract = (XK_KP_Subtract & 0xff)| extendedKeyModifier; -const int KeyPress::numberPadMultiply = (XK_KP_Multiply & 0xff)| extendedKeyModifier; -const int KeyPress::numberPadDivide = (XK_KP_Divide & 0xff)| extendedKeyModifier; -const int KeyPress::numberPadSeparator = (XK_KP_Separator & 0xff)| extendedKeyModifier; +const int KeyPress::spaceKey = XK_space & 0xff; +const int KeyPress::returnKey = XK_Return & 0xff; +const int KeyPress::escapeKey = XK_Escape & 0xff; +const int KeyPress::backspaceKey = XK_BackSpace & 0xff; +const int KeyPress::leftKey = (XK_Left & 0xff) | extendedKeyModifier; +const int KeyPress::rightKey = (XK_Right & 0xff) | extendedKeyModifier; +const int KeyPress::upKey = (XK_Up & 0xff) | extendedKeyModifier; +const int KeyPress::downKey = (XK_Down & 0xff) | extendedKeyModifier; +const int KeyPress::pageUpKey = (XK_Page_Up & 0xff) | extendedKeyModifier; +const int KeyPress::pageDownKey = (XK_Page_Down & 0xff) | extendedKeyModifier; +const int KeyPress::endKey = (XK_End & 0xff) | extendedKeyModifier; +const int KeyPress::homeKey = (XK_Home & 0xff) | extendedKeyModifier; +const int KeyPress::insertKey = (XK_Insert & 0xff) | extendedKeyModifier; +const int KeyPress::deleteKey = (XK_Delete & 0xff) | extendedKeyModifier; +const int KeyPress::tabKey = XK_Tab & 0xff; +const int KeyPress::F1Key = (XK_F1 & 0xff) | extendedKeyModifier; +const int KeyPress::F2Key = (XK_F2 & 0xff) | extendedKeyModifier; +const int KeyPress::F3Key = (XK_F3 & 0xff) | extendedKeyModifier; +const int KeyPress::F4Key = (XK_F4 & 0xff) | extendedKeyModifier; +const int KeyPress::F5Key = (XK_F5 & 0xff) | extendedKeyModifier; +const int KeyPress::F6Key = (XK_F6 & 0xff) | extendedKeyModifier; +const int KeyPress::F7Key = (XK_F7 & 0xff) | extendedKeyModifier; +const int KeyPress::F8Key = (XK_F8 & 0xff) | extendedKeyModifier; +const int KeyPress::F9Key = (XK_F9 & 0xff) | extendedKeyModifier; +const int KeyPress::F10Key = (XK_F10 & 0xff) | extendedKeyModifier; +const int KeyPress::F11Key = (XK_F11 & 0xff) | extendedKeyModifier; +const int KeyPress::F12Key = (XK_F12 & 0xff) | extendedKeyModifier; +const int KeyPress::F13Key = (XK_F13 & 0xff) | extendedKeyModifier; +const int KeyPress::F14Key = (XK_F14 & 0xff) | extendedKeyModifier; +const int KeyPress::F15Key = (XK_F15 & 0xff) | extendedKeyModifier; +const int KeyPress::F16Key = (XK_F16 & 0xff) | extendedKeyModifier; +const int KeyPress::numberPad0 = (XK_KP_0 & 0xff) | extendedKeyModifier; +const int KeyPress::numberPad1 = (XK_KP_1 & 0xff) | extendedKeyModifier; +const int KeyPress::numberPad2 = (XK_KP_2 & 0xff) | extendedKeyModifier; +const int KeyPress::numberPad3 = (XK_KP_3 & 0xff) | extendedKeyModifier; +const int KeyPress::numberPad4 = (XK_KP_4 & 0xff) | extendedKeyModifier; +const int KeyPress::numberPad5 = (XK_KP_5 & 0xff) | extendedKeyModifier; +const int KeyPress::numberPad6 = (XK_KP_6 & 0xff) | extendedKeyModifier; +const int KeyPress::numberPad7 = (XK_KP_7 & 0xff)| extendedKeyModifier; +const int KeyPress::numberPad8 = (XK_KP_8 & 0xff)| extendedKeyModifier; +const int KeyPress::numberPad9 = (XK_KP_9 & 0xff)| extendedKeyModifier; +const int KeyPress::numberPadAdd = (XK_KP_Add & 0xff)| extendedKeyModifier; +const int KeyPress::numberPadSubtract = (XK_KP_Subtract & 0xff)| extendedKeyModifier; +const int KeyPress::numberPadMultiply = (XK_KP_Multiply & 0xff)| extendedKeyModifier; +const int KeyPress::numberPadDivide = (XK_KP_Divide & 0xff)| extendedKeyModifier; +const int KeyPress::numberPadSeparator = (XK_KP_Separator & 0xff)| extendedKeyModifier; const int KeyPress::numberPadDecimalPoint = (XK_KP_Decimal & 0xff)| extendedKeyModifier; -const int KeyPress::numberPadEquals = (XK_KP_Equal & 0xff)| extendedKeyModifier; -const int KeyPress::numberPadDelete = (XK_KP_Delete & 0xff)| extendedKeyModifier; -const int KeyPress::playKey = (0xffeeff00) | extendedKeyModifier; -const int KeyPress::stopKey = (0xffeeff01) | extendedKeyModifier; -const int KeyPress::fastForwardKey = (0xffeeff02) | extendedKeyModifier; -const int KeyPress::rewindKey = (0xffeeff03) | extendedKeyModifier; +const int KeyPress::numberPadEquals = (XK_KP_Equal & 0xff)| extendedKeyModifier; +const int KeyPress::numberPadDelete = (XK_KP_Delete & 0xff)| extendedKeyModifier; +const int KeyPress::playKey = (0xffeeff00) | extendedKeyModifier; +const int KeyPress::stopKey = (0xffeeff01) | extendedKeyModifier; +const int KeyPress::fastForwardKey = (0xffeeff02) | extendedKeyModifier; +const int KeyPress::rewindKey = (0xffeeff03) | extendedKeyModifier; #endif /********* End of inlined file: juce_linux_Windowing.cpp *********/ @@ -257103,950 +234743,940 @@ static const int maxNumChans = 64; static void getDeviceSampleRates (snd_pcm_t* handle, Array & rates) { - const int ratesToTry[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 }; + const int ratesToTry[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 }; - snd_pcm_hw_params_t* hwParams; - snd_pcm_hw_params_alloca (&hwParams); + snd_pcm_hw_params_t* hwParams; + snd_pcm_hw_params_alloca (&hwParams); - for (int i = 0; ratesToTry[i] != 0; ++i) - { - if (snd_pcm_hw_params_any (handle, hwParams) >= 0 - && snd_pcm_hw_params_test_rate (handle, hwParams, ratesToTry[i], 0) == 0) - { - rates.addIfNotAlreadyThere (ratesToTry[i]); - } - } + for (int i = 0; ratesToTry[i] != 0; ++i) + { + if (snd_pcm_hw_params_any (handle, hwParams) >= 0 + && snd_pcm_hw_params_test_rate (handle, hwParams, ratesToTry[i], 0) == 0) + { + rates.addIfNotAlreadyThere (ratesToTry[i]); + } + } } static void getDeviceNumChannels (snd_pcm_t* handle, unsigned int* minChans, unsigned int* maxChans) { - snd_pcm_hw_params_t *params; - snd_pcm_hw_params_alloca (¶ms); + snd_pcm_hw_params_t *params; + snd_pcm_hw_params_alloca (¶ms); - if (snd_pcm_hw_params_any (handle, params) >= 0) - { - snd_pcm_hw_params_get_channels_min (params, minChans); - snd_pcm_hw_params_get_channels_max (params, maxChans); - } + if (snd_pcm_hw_params_any (handle, params) >= 0) + { + snd_pcm_hw_params_get_channels_min (params, minChans); + snd_pcm_hw_params_get_channels_max (params, maxChans); + } } static void getDeviceProperties (const String& id, - unsigned int& minChansOut, - unsigned int& maxChansOut, - unsigned int& minChansIn, - unsigned int& maxChansIn, - Array & rates) + unsigned int& minChansOut, + unsigned int& maxChansOut, + unsigned int& minChansIn, + unsigned int& maxChansIn, + Array & rates) { - if (id.isEmpty()) - return; + if (id.isEmpty()) + return; - snd_ctl_t* handle; + snd_ctl_t* handle; - if (snd_ctl_open (&handle, id.upToLastOccurrenceOf (T(","), false, false), SND_CTL_NONBLOCK) >= 0) - { - snd_pcm_info_t* info; - snd_pcm_info_alloca (&info); + if (snd_ctl_open (&handle, id.upToLastOccurrenceOf (T(","), false, false), SND_CTL_NONBLOCK) >= 0) + { + snd_pcm_info_t* info; + snd_pcm_info_alloca (&info); - snd_pcm_info_set_stream (info, SND_PCM_STREAM_PLAYBACK); - snd_pcm_info_set_device (info, id.fromLastOccurrenceOf (T(","), false, false).getIntValue()); - snd_pcm_info_set_subdevice (info, 0); + snd_pcm_info_set_stream (info, SND_PCM_STREAM_PLAYBACK); + snd_pcm_info_set_device (info, id.fromLastOccurrenceOf (T(","), false, false).getIntValue()); + snd_pcm_info_set_subdevice (info, 0); - if (snd_ctl_pcm_info (handle, info) >= 0) - { - snd_pcm_t* pcmHandle; - if (snd_pcm_open (&pcmHandle, id, SND_PCM_STREAM_PLAYBACK, SND_PCM_ASYNC | SND_PCM_NONBLOCK ) >= 0) - { - getDeviceNumChannels (pcmHandle, &minChansOut, &maxChansOut); - getDeviceSampleRates (pcmHandle, rates); + if (snd_ctl_pcm_info (handle, info) >= 0) + { + snd_pcm_t* pcmHandle; + if (snd_pcm_open (&pcmHandle, id, SND_PCM_STREAM_PLAYBACK, SND_PCM_ASYNC | SND_PCM_NONBLOCK ) >= 0) + { + getDeviceNumChannels (pcmHandle, &minChansOut, &maxChansOut); + getDeviceSampleRates (pcmHandle, rates); - snd_pcm_close (pcmHandle); - } - } + snd_pcm_close (pcmHandle); + } + } - snd_pcm_info_set_stream (info, SND_PCM_STREAM_CAPTURE); + snd_pcm_info_set_stream (info, SND_PCM_STREAM_CAPTURE); - if (snd_ctl_pcm_info (handle, info) >= 0) - { - snd_pcm_t* pcmHandle; - if (snd_pcm_open (&pcmHandle, id, SND_PCM_STREAM_CAPTURE, SND_PCM_ASYNC | SND_PCM_NONBLOCK ) >= 0) - { - getDeviceNumChannels (pcmHandle, &minChansIn, &maxChansIn); + if (snd_ctl_pcm_info (handle, info) >= 0) + { + snd_pcm_t* pcmHandle; + if (snd_pcm_open (&pcmHandle, id, SND_PCM_STREAM_CAPTURE, SND_PCM_ASYNC | SND_PCM_NONBLOCK ) >= 0) + { + getDeviceNumChannels (pcmHandle, &minChansIn, &maxChansIn); - if (rates.size() == 0) - getDeviceSampleRates (pcmHandle, rates); + if (rates.size() == 0) + getDeviceSampleRates (pcmHandle, rates); - snd_pcm_close (pcmHandle); - } - } + snd_pcm_close (pcmHandle); + } + } - snd_ctl_close (handle); - } + snd_ctl_close (handle); + } } class ALSADevice { public: - ALSADevice (const String& id, - const bool forInput) - : handle (0), - bitDepth (16), - numChannelsRunning (0), - isInput (forInput), - sampleFormat (AudioDataConverters::int16LE) - { - failed (snd_pcm_open (&handle, id, - forInput ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, - SND_PCM_ASYNC)); - } + ALSADevice (const String& id, + const bool forInput) + : handle (0), + bitDepth (16), + numChannelsRunning (0), + isInput (forInput), + sampleFormat (AudioDataConverters::int16LE) + { + failed (snd_pcm_open (&handle, id, + forInput ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, + SND_PCM_ASYNC)); + } - ~ALSADevice() - { - if (handle != 0) - snd_pcm_close (handle); - } + ~ALSADevice() + { + if (handle != 0) + snd_pcm_close (handle); + } - bool setParameters (unsigned int sampleRate, int numChannels, int bufferSize) - { - if (handle == 0) - return false; + bool setParameters (unsigned int sampleRate, int numChannels, int bufferSize) + { + if (handle == 0) + return false; - snd_pcm_hw_params_t* hwParams; - snd_pcm_hw_params_alloca (&hwParams); + snd_pcm_hw_params_t* hwParams; + snd_pcm_hw_params_alloca (&hwParams); - if (failed (snd_pcm_hw_params_any (handle, hwParams))) - return false; + if (failed (snd_pcm_hw_params_any (handle, hwParams))) + return false; - if (snd_pcm_hw_params_set_access (handle, hwParams, SND_PCM_ACCESS_RW_NONINTERLEAVED) >= 0) - isInterleaved = false; - else if (snd_pcm_hw_params_set_access (handle, hwParams, SND_PCM_ACCESS_RW_INTERLEAVED) >= 0) - isInterleaved = true; - else - { - jassertfalse - return false; - } + if (snd_pcm_hw_params_set_access (handle, hwParams, SND_PCM_ACCESS_RW_NONINTERLEAVED) >= 0) + isInterleaved = false; + else if (snd_pcm_hw_params_set_access (handle, hwParams, SND_PCM_ACCESS_RW_INTERLEAVED) >= 0) + isInterleaved = true; + else + { + jassertfalse + return false; + } - const int formatsToTry[] = { SND_PCM_FORMAT_FLOAT_LE, 32, AudioDataConverters::float32LE, - SND_PCM_FORMAT_FLOAT_BE, 32, AudioDataConverters::float32BE, - SND_PCM_FORMAT_S32_LE, 32, AudioDataConverters::int32LE, - SND_PCM_FORMAT_S32_BE, 32, AudioDataConverters::int32BE, - SND_PCM_FORMAT_S24_3LE, 24, AudioDataConverters::int24LE, - SND_PCM_FORMAT_S24_3BE, 24, AudioDataConverters::int24BE, - SND_PCM_FORMAT_S16_LE, 16, AudioDataConverters::int16LE, - SND_PCM_FORMAT_S16_BE, 16, AudioDataConverters::int16BE }; - bitDepth = 0; + const int formatsToTry[] = { SND_PCM_FORMAT_FLOAT_LE, 32, AudioDataConverters::float32LE, + SND_PCM_FORMAT_FLOAT_BE, 32, AudioDataConverters::float32BE, + SND_PCM_FORMAT_S32_LE, 32, AudioDataConverters::int32LE, + SND_PCM_FORMAT_S32_BE, 32, AudioDataConverters::int32BE, + SND_PCM_FORMAT_S24_3LE, 24, AudioDataConverters::int24LE, + SND_PCM_FORMAT_S24_3BE, 24, AudioDataConverters::int24BE, + SND_PCM_FORMAT_S16_LE, 16, AudioDataConverters::int16LE, + SND_PCM_FORMAT_S16_BE, 16, AudioDataConverters::int16BE }; + bitDepth = 0; - for (int i = 0; i < numElementsInArray (formatsToTry); i += 3) - { - if (snd_pcm_hw_params_set_format (handle, hwParams, (_snd_pcm_format) formatsToTry [i]) >= 0) - { - bitDepth = formatsToTry [i + 1]; - sampleFormat = (AudioDataConverters::DataFormat) formatsToTry [i + 2]; - break; - } - } + for (int i = 0; i < numElementsInArray (formatsToTry); i += 3) + { + if (snd_pcm_hw_params_set_format (handle, hwParams, (_snd_pcm_format) formatsToTry [i]) >= 0) + { + bitDepth = formatsToTry [i + 1]; + sampleFormat = (AudioDataConverters::DataFormat) formatsToTry [i + 2]; + break; + } + } - if (bitDepth == 0) - { - error = "device doesn't support a compatible PCM format"; - DBG (T("ALSA error: ") + error + T("\n")); - return false; - } + if (bitDepth == 0) + { + error = "device doesn't support a compatible PCM format"; + DBG (T("ALSA error: ") + error + T("\n")); + return false; + } - int dir = 0; - unsigned int periods = 4; - snd_pcm_uframes_t samplesPerPeriod = bufferSize; + int dir = 0; + unsigned int periods = 4; + snd_pcm_uframes_t samplesPerPeriod = bufferSize; - if (failed (snd_pcm_hw_params_set_rate_near (handle, hwParams, &sampleRate, 0)) - || failed (snd_pcm_hw_params_set_channels (handle, hwParams, numChannels)) - || failed (snd_pcm_hw_params_set_periods_near (handle, hwParams, &periods, &dir)) - || failed (snd_pcm_hw_params_set_period_size_near (handle, hwParams, &samplesPerPeriod, &dir)) - || failed (snd_pcm_hw_params (handle, hwParams))) - { - return false; - } + if (failed (snd_pcm_hw_params_set_rate_near (handle, hwParams, &sampleRate, 0)) + || failed (snd_pcm_hw_params_set_channels (handle, hwParams, numChannels)) + || failed (snd_pcm_hw_params_set_periods_near (handle, hwParams, &periods, &dir)) + || failed (snd_pcm_hw_params_set_period_size_near (handle, hwParams, &samplesPerPeriod, &dir)) + || failed (snd_pcm_hw_params (handle, hwParams))) + { + return false; + } - snd_pcm_sw_params_t* swParams; - snd_pcm_sw_params_alloca (&swParams); - snd_pcm_uframes_t boundary; + snd_pcm_sw_params_t* swParams; + snd_pcm_sw_params_alloca (&swParams); + snd_pcm_uframes_t boundary; - if (failed (snd_pcm_sw_params_current (handle, swParams)) - || failed (snd_pcm_sw_params_get_boundary (swParams, &boundary)) - || failed (snd_pcm_sw_params_set_silence_threshold (handle, swParams, 0)) - || failed (snd_pcm_sw_params_set_silence_size (handle, swParams, boundary)) - || failed (snd_pcm_sw_params_set_start_threshold (handle, swParams, samplesPerPeriod)) - || failed (snd_pcm_sw_params_set_stop_threshold (handle, swParams, boundary)) - || failed (snd_pcm_sw_params (handle, swParams))) - { - return false; - } + if (failed (snd_pcm_sw_params_current (handle, swParams)) + || failed (snd_pcm_sw_params_get_boundary (swParams, &boundary)) + || failed (snd_pcm_sw_params_set_silence_threshold (handle, swParams, 0)) + || failed (snd_pcm_sw_params_set_silence_size (handle, swParams, boundary)) + || failed (snd_pcm_sw_params_set_start_threshold (handle, swParams, samplesPerPeriod)) + || failed (snd_pcm_sw_params_set_stop_threshold (handle, swParams, boundary)) + || failed (snd_pcm_sw_params (handle, swParams))) + { + return false; + } - /* -#ifdef JUCE_DEBUG - // enable this to dump the config of the devices that get opened - snd_output_t* out; - snd_output_stdio_attach (&out, stderr, 0); - snd_pcm_hw_params_dump (hwParams, out); - snd_pcm_sw_params_dump (swParams, out); -#endif - */ + numChannelsRunning = numChannels; - numChannelsRunning = numChannels; + return true; + } - return true; - } + bool write (float** const data, const int numSamples) + { + if (isInterleaved) + { + scratch.ensureSize (sizeof (float) * numSamples * numChannelsRunning, false); + float* interleaved = (float*) scratch; - bool write (float** const data, const int numSamples) - { - if (isInterleaved) - { - scratch.ensureSize (sizeof (float) * numSamples * numChannelsRunning, false); - float* interleaved = (float*) scratch; + AudioDataConverters::interleaveSamples ((const float**) data, interleaved, numSamples, numChannelsRunning); + AudioDataConverters::convertFloatToFormat (sampleFormat, interleaved, interleaved, numSamples * numChannelsRunning); - AudioDataConverters::interleaveSamples ((const float**) data, interleaved, numSamples, numChannelsRunning); - AudioDataConverters::convertFloatToFormat (sampleFormat, interleaved, interleaved, numSamples * numChannelsRunning); + snd_pcm_sframes_t num = snd_pcm_writei (handle, (void*) interleaved, numSamples); - snd_pcm_sframes_t num = snd_pcm_writei (handle, (void*) interleaved, numSamples); + if (failed (num) && num != -EPIPE && num != -ESTRPIPE) + return false; + } + else + { + for (int i = 0; i < numChannelsRunning; ++i) + if (data[i] != 0) + AudioDataConverters::convertFloatToFormat (sampleFormat, data[i], data[i], numSamples); - if (failed (num) && num != -EPIPE && num != -ESTRPIPE) - return false; - } - else - { - for (int i = 0; i < numChannelsRunning; ++i) - if (data[i] != 0) - AudioDataConverters::convertFloatToFormat (sampleFormat, data[i], data[i], numSamples); + snd_pcm_sframes_t num = snd_pcm_writen (handle, (void**) data, numSamples); - snd_pcm_sframes_t num = snd_pcm_writen (handle, (void**) data, numSamples); + if (failed (num)) + { + if (num == -EPIPE) + { + if (failed (snd_pcm_prepare (handle))) + return false; + } + else if (num != -ESTRPIPE) + return false; + } + } - if (failed (num)) - { - if (num == -EPIPE) - { - if (failed (snd_pcm_prepare (handle))) - return false; - } - else if (num != -ESTRPIPE) - return false; - } - } + return true; + } - return true; - } + bool read (float** const data, const int numSamples) + { + if (isInterleaved) + { + scratch.ensureSize (sizeof (float) * numSamples * numChannelsRunning, false); + float* interleaved = (float*) scratch; - bool read (float** const data, const int numSamples) - { - if (isInterleaved) - { - scratch.ensureSize (sizeof (float) * numSamples * numChannelsRunning, false); - float* interleaved = (float*) scratch; + snd_pcm_sframes_t num = snd_pcm_readi (handle, (void*) interleaved, numSamples); - snd_pcm_sframes_t num = snd_pcm_readi (handle, (void*) interleaved, numSamples); + if (failed (num)) + { + if (num == -EPIPE) + { + if (failed (snd_pcm_prepare (handle))) + return false; + } + else if (num != -ESTRPIPE) + return false; + } - if (failed (num)) - { - if (num == -EPIPE) - { - if (failed (snd_pcm_prepare (handle))) - return false; - } - else if (num != -ESTRPIPE) - return false; - } + AudioDataConverters::convertFormatToFloat (sampleFormat, interleaved, interleaved, numSamples * numChannelsRunning); + AudioDataConverters::deinterleaveSamples (interleaved, data, numSamples, numChannelsRunning); + } + else + { + snd_pcm_sframes_t num = snd_pcm_readn (handle, (void**) data, numSamples); - AudioDataConverters::convertFormatToFloat (sampleFormat, interleaved, interleaved, numSamples * numChannelsRunning); - AudioDataConverters::deinterleaveSamples (interleaved, data, numSamples, numChannelsRunning); - } - else - { - snd_pcm_sframes_t num = snd_pcm_readn (handle, (void**) data, numSamples); + if (failed (num) && num != -EPIPE && num != -ESTRPIPE) + return false; - if (failed (num) && num != -EPIPE && num != -ESTRPIPE) - return false; + for (int i = 0; i < numChannelsRunning; ++i) + if (data[i] != 0) + AudioDataConverters::convertFormatToFloat (sampleFormat, data[i], data[i], numSamples); + } - for (int i = 0; i < numChannelsRunning; ++i) - if (data[i] != 0) - AudioDataConverters::convertFormatToFloat (sampleFormat, data[i], data[i], numSamples); - } + return true; + } - return true; - } + juce_UseDebuggingNewOperator - juce_UseDebuggingNewOperator - - snd_pcm_t* handle; - String error; - int bitDepth, numChannelsRunning; + snd_pcm_t* handle; + String error; + int bitDepth, numChannelsRunning; private: - const bool isInput; - bool isInterleaved; - MemoryBlock scratch; - AudioDataConverters::DataFormat sampleFormat; + const bool isInput; + bool isInterleaved; + MemoryBlock scratch; + AudioDataConverters::DataFormat sampleFormat; - bool failed (const int errorNum) - { - if (errorNum >= 0) - return false; + bool failed (const int errorNum) + { + if (errorNum >= 0) + return false; - error = snd_strerror (errorNum); - DBG (T("ALSA error: ") + error + T("\n")); - return true; - } + error = snd_strerror (errorNum); + DBG (T("ALSA error: ") + error + T("\n")); + return true; + } }; class ALSAThread : public Thread { public: - ALSAThread (const String& inputId_, - const String& outputId_) - : Thread ("Juce ALSA"), - sampleRate (0), - bufferSize (0), - callback (0), - inputId (inputId_), - outputId (outputId_), - outputDevice (0), - inputDevice (0), - numCallbacks (0), - totalNumInputChannels (0), - totalNumOutputChannels (0) - { - zeromem (outputChannelData, sizeof (outputChannelData)); - zeromem (outputChannelDataForCallback, sizeof (outputChannelDataForCallback)); - zeromem (inputChannelData, sizeof (inputChannelData)); - zeromem (inputChannelDataForCallback, sizeof (inputChannelDataForCallback)); + ALSAThread (const String& inputId_, + const String& outputId_) + : Thread ("Juce ALSA"), + sampleRate (0), + bufferSize (0), + callback (0), + inputId (inputId_), + outputId (outputId_), + outputDevice (0), + inputDevice (0), + numCallbacks (0), + totalNumInputChannels (0), + totalNumOutputChannels (0) + { + zeromem (outputChannelData, sizeof (outputChannelData)); + zeromem (outputChannelDataForCallback, sizeof (outputChannelDataForCallback)); + zeromem (inputChannelData, sizeof (inputChannelData)); + zeromem (inputChannelDataForCallback, sizeof (inputChannelDataForCallback)); - initialiseRatesAndChannels(); - } + initialiseRatesAndChannels(); + } - ~ALSAThread() - { - close(); - } + ~ALSAThread() + { + close(); + } - void open (BitArray inputChannels, - BitArray outputChannels, - const double sampleRate_, - const int bufferSize_) - { - close(); + void open (BitArray inputChannels, + BitArray outputChannels, + const double sampleRate_, + const int bufferSize_) + { + close(); - error = String::empty; - sampleRate = sampleRate_; - bufferSize = bufferSize_; - currentInputChans.clear(); - currentOutputChans.clear(); + error = String::empty; + sampleRate = sampleRate_; + bufferSize = bufferSize_; + currentInputChans.clear(); + currentOutputChans.clear(); - if (inputChannels.getHighestBit() >= 0) - { - for (int i = 0; i <= jmax (inputChannels.getHighestBit(), minChansIn); ++i) - { - inputChannelData [i] = (float*) juce_calloc (sizeof (float) * bufferSize); + if (inputChannels.getHighestBit() >= 0) + { + for (int i = 0; i <= jmax (inputChannels.getHighestBit(), (int) minChansIn); ++i) + { + inputChannelData [i] = (float*) juce_calloc (sizeof (float) * bufferSize); - if (inputChannels[i]) - { - inputChannelDataForCallback [totalNumInputChannels++] = inputChannelData [i]; - currentInputChans.setBit (i); - } - } - } + if (inputChannels[i]) + { + inputChannelDataForCallback [totalNumInputChannels++] = inputChannelData [i]; + currentInputChans.setBit (i); + } + } + } - if (outputChannels.getHighestBit() >= 0) - { - for (int i = 0; i <= jmax (outputChannels.getHighestBit(), minChansOut); ++i) - { - outputChannelData [i] = (float*) juce_calloc (sizeof (float) * bufferSize); + if (outputChannels.getHighestBit() >= 0) + { + for (int i = 0; i <= jmax (outputChannels.getHighestBit(), (int) minChansOut); ++i) + { + outputChannelData [i] = (float*) juce_calloc (sizeof (float) * bufferSize); - if (outputChannels[i]) - { - outputChannelDataForCallback [totalNumOutputChannels++] = outputChannelData [i]; - currentOutputChans.setBit (i); - } - } - } + if (outputChannels[i]) + { + outputChannelDataForCallback [totalNumOutputChannels++] = outputChannelData [i]; + currentOutputChans.setBit (i); + } + } + } - if (totalNumOutputChannels > 0 && outputId.isNotEmpty()) - { - outputDevice = new ALSADevice (outputId, false); + if (totalNumOutputChannels > 0 && outputId.isNotEmpty()) + { + outputDevice = new ALSADevice (outputId, false); - if (outputDevice->error.isNotEmpty()) - { - error = outputDevice->error; - deleteAndZero (outputDevice); - return; - } + if (outputDevice->error.isNotEmpty()) + { + error = outputDevice->error; + deleteAndZero (outputDevice); + return; + } - currentOutputChans.setRange (0, minChansOut, true); + currentOutputChans.setRange (0, minChansOut, true); - if (! outputDevice->setParameters ((unsigned int) sampleRate, - jlimit ((int) minChansOut, (int) maxChansOut, currentOutputChans.getHighestBit() + 1), - bufferSize)) - { - error = outputDevice->error; - deleteAndZero (outputDevice); - return; - } - } + if (! outputDevice->setParameters ((unsigned int) sampleRate, + jlimit ((int) minChansOut, (int) maxChansOut, currentOutputChans.getHighestBit() + 1), + bufferSize)) + { + error = outputDevice->error; + deleteAndZero (outputDevice); + return; + } + } - if (totalNumInputChannels > 0 && inputId.isNotEmpty()) - { - inputDevice = new ALSADevice (inputId, true); + if (totalNumInputChannels > 0 && inputId.isNotEmpty()) + { + inputDevice = new ALSADevice (inputId, true); - if (inputDevice->error.isNotEmpty()) - { - error = inputDevice->error; - deleteAndZero (inputDevice); - return; - } + if (inputDevice->error.isNotEmpty()) + { + error = inputDevice->error; + deleteAndZero (inputDevice); + return; + } - currentInputChans.setRange (0, minChansIn, true); + currentInputChans.setRange (0, minChansIn, true); - if (! inputDevice->setParameters ((unsigned int) sampleRate, - jlimit ((int) minChansIn, (int) maxChansIn, currentInputChans.getHighestBit() + 1), - bufferSize)) - { - error = inputDevice->error; - deleteAndZero (inputDevice); - return; - } - } + if (! inputDevice->setParameters ((unsigned int) sampleRate, + jlimit ((int) minChansIn, (int) maxChansIn, currentInputChans.getHighestBit() + 1), + bufferSize)) + { + error = inputDevice->error; + deleteAndZero (inputDevice); + return; + } + } - if (outputDevice == 0 && inputDevice == 0) - { - error = "no channels"; - return; - } + if (outputDevice == 0 && inputDevice == 0) + { + error = "no channels"; + return; + } - if (outputDevice != 0 && inputDevice != 0) - { - snd_pcm_link (outputDevice->handle, inputDevice->handle); - } + if (outputDevice != 0 && inputDevice != 0) + { + snd_pcm_link (outputDevice->handle, inputDevice->handle); + } - if (inputDevice != 0 && failed (snd_pcm_prepare (inputDevice->handle))) - return; + if (inputDevice != 0 && failed (snd_pcm_prepare (inputDevice->handle))) + return; - if (outputDevice != 0 && failed (snd_pcm_prepare (outputDevice->handle))) - return; + if (outputDevice != 0 && failed (snd_pcm_prepare (outputDevice->handle))) + return; - startThread (9); + startThread (9); - int count = 1000; + int count = 1000; - while (numCallbacks == 0) - { - sleep (5); + while (numCallbacks == 0) + { + sleep (5); - if (--count < 0 || ! isThreadRunning()) - { - error = "device didn't start"; - break; - } - } - } + if (--count < 0 || ! isThreadRunning()) + { + error = "device didn't start"; + break; + } + } + } - void close() - { - stopThread (6000); + void close() + { + stopThread (6000); - deleteAndZero (inputDevice); - deleteAndZero (outputDevice); + deleteAndZero (inputDevice); + deleteAndZero (outputDevice); - for (int i = 0; i < maxNumChans; ++i) - { - juce_free (inputChannelData [i]); - juce_free (outputChannelData [i]); - } + for (int i = 0; i < maxNumChans; ++i) + { + juce_free (inputChannelData [i]); + juce_free (outputChannelData [i]); + } - zeromem (outputChannelData, sizeof (outputChannelData)); - zeromem (outputChannelDataForCallback, sizeof (outputChannelDataForCallback)); - zeromem (inputChannelData, sizeof (inputChannelData)); - zeromem (inputChannelDataForCallback, sizeof (inputChannelDataForCallback)); - totalNumOutputChannels = 0; - totalNumInputChannels = 0; + zeromem (outputChannelData, sizeof (outputChannelData)); + zeromem (outputChannelDataForCallback, sizeof (outputChannelDataForCallback)); + zeromem (inputChannelData, sizeof (inputChannelData)); + zeromem (inputChannelDataForCallback, sizeof (inputChannelDataForCallback)); + totalNumOutputChannels = 0; + totalNumInputChannels = 0; - numCallbacks = 0; - } + numCallbacks = 0; + } - void setCallback (AudioIODeviceCallback* const newCallback) throw() - { - const ScopedLock sl (callbackLock); - callback = newCallback; - } + void setCallback (AudioIODeviceCallback* const newCallback) throw() + { + const ScopedLock sl (callbackLock); + callback = newCallback; + } - void run() - { - while (! threadShouldExit()) - { - if (inputDevice != 0) - { - if (! inputDevice->read (inputChannelData, bufferSize)) - { - DBG ("ALSA: read failure"); - break; - } - } + void run() + { + while (! threadShouldExit()) + { + if (inputDevice != 0) + { + if (! inputDevice->read (inputChannelData, bufferSize)) + { + DBG ("ALSA: read failure"); + break; + } + } - if (threadShouldExit()) - break; + if (threadShouldExit()) + break; - { - const ScopedLock sl (callbackLock); - ++numCallbacks; + { + const ScopedLock sl (callbackLock); + ++numCallbacks; - if (callback != 0) - { - callback->audioDeviceIOCallback ((const float**) inputChannelDataForCallback, - totalNumInputChannels, - outputChannelDataForCallback, - totalNumOutputChannels, - bufferSize); - } - else - { - for (int i = 0; i < totalNumOutputChannels; ++i) - zeromem (outputChannelDataForCallback[i], sizeof (float) * bufferSize); - } - } + if (callback != 0) + { + callback->audioDeviceIOCallback ((const float**) inputChannelDataForCallback, + totalNumInputChannels, + outputChannelDataForCallback, + totalNumOutputChannels, + bufferSize); + } + else + { + for (int i = 0; i < totalNumOutputChannels; ++i) + zeromem (outputChannelDataForCallback[i], sizeof (float) * bufferSize); + } + } - if (outputDevice != 0) - { - failed (snd_pcm_wait (outputDevice->handle, 2000)); + if (outputDevice != 0) + { + failed (snd_pcm_wait (outputDevice->handle, 2000)); - if (threadShouldExit()) - break; + if (threadShouldExit()) + break; - failed (snd_pcm_avail_update (outputDevice->handle)); + failed (snd_pcm_avail_update (outputDevice->handle)); - if (! outputDevice->write (outputChannelData, bufferSize)) - { - DBG ("ALSA: write failure"); - break; - } - } - } - } + if (! outputDevice->write (outputChannelData, bufferSize)) + { + DBG ("ALSA: write failure"); + break; + } + } + } + } - int getBitDepth() const throw() - { - if (outputDevice != 0) - return outputDevice->bitDepth; + int getBitDepth() const throw() + { + if (outputDevice != 0) + return outputDevice->bitDepth; - if (inputDevice != 0) - return inputDevice->bitDepth; + if (inputDevice != 0) + return inputDevice->bitDepth; - return 16; - } + return 16; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - String error; - double sampleRate; - int bufferSize; - BitArray currentInputChans, currentOutputChans; + String error; + double sampleRate; + int bufferSize; + BitArray currentInputChans, currentOutputChans; - Array sampleRates; - StringArray channelNamesOut, channelNamesIn; - AudioIODeviceCallback* callback; + Array sampleRates; + StringArray channelNamesOut, channelNamesIn; + AudioIODeviceCallback* callback; private: - const String inputId, outputId; - ALSADevice* outputDevice; - ALSADevice* inputDevice; - int numCallbacks; + const String inputId, outputId; + ALSADevice* outputDevice; + ALSADevice* inputDevice; + int numCallbacks; - CriticalSection callbackLock; + CriticalSection callbackLock; - float* outputChannelData [maxNumChans]; - float* outputChannelDataForCallback [maxNumChans]; - int totalNumInputChannels; - float* inputChannelData [maxNumChans]; - float* inputChannelDataForCallback [maxNumChans]; - int totalNumOutputChannels; + float* outputChannelData [maxNumChans]; + float* outputChannelDataForCallback [maxNumChans]; + int totalNumInputChannels; + float* inputChannelData [maxNumChans]; + float* inputChannelDataForCallback [maxNumChans]; + int totalNumOutputChannels; - unsigned int minChansOut, maxChansOut; - unsigned int minChansIn, maxChansIn; + unsigned int minChansOut, maxChansOut; + unsigned int minChansIn, maxChansIn; - bool failed (const int errorNum) throw() - { - if (errorNum >= 0) - return false; + bool failed (const int errorNum) throw() + { + if (errorNum >= 0) + return false; - error = snd_strerror (errorNum); - DBG (T("ALSA error: ") + error + T("\n")); - return true; - } + error = snd_strerror (errorNum); + DBG (T("ALSA error: ") + error + T("\n")); + return true; + } - void initialiseRatesAndChannels() throw() - { - sampleRates.clear(); - channelNamesOut.clear(); - channelNamesIn.clear(); - minChansOut = 0; - maxChansOut = 0; - minChansIn = 0; - maxChansIn = 0; - unsigned int dummy = 0; + void initialiseRatesAndChannels() throw() + { + sampleRates.clear(); + channelNamesOut.clear(); + channelNamesIn.clear(); + minChansOut = 0; + maxChansOut = 0; + minChansIn = 0; + maxChansIn = 0; + unsigned int dummy = 0; - getDeviceProperties (inputId, dummy, dummy, minChansIn, maxChansIn, sampleRates); - getDeviceProperties (outputId, minChansOut, maxChansOut, dummy, dummy, sampleRates); + getDeviceProperties (inputId, dummy, dummy, minChansIn, maxChansIn, sampleRates); + getDeviceProperties (outputId, minChansOut, maxChansOut, dummy, dummy, sampleRates); - unsigned int i; - for (i = 0; i < maxChansOut; ++i) - channelNamesOut.add (T("channel ") + String ((int) i + 1)); + unsigned int i; + for (i = 0; i < maxChansOut; ++i) + channelNamesOut.add (T("channel ") + String ((int) i + 1)); - for (i = 0; i < maxChansIn; ++i) - channelNamesIn.add (T("channel ") + String ((int) i + 1)); - } + for (i = 0; i < maxChansIn; ++i) + channelNamesIn.add (T("channel ") + String ((int) i + 1)); + } }; class ALSAAudioIODevice : public AudioIODevice { public: - ALSAAudioIODevice (const String& deviceName, - const String& inputId_, - const String& outputId_) - : AudioIODevice (deviceName, T("ALSA")), - inputId (inputId_), - outputId (outputId_), - isOpen_ (false), - isStarted (false), - internal (0) - { - internal = new ALSAThread (inputId, outputId); - } + ALSAAudioIODevice (const String& deviceName, + const String& inputId_, + const String& outputId_) + : AudioIODevice (deviceName, T("ALSA")), + inputId (inputId_), + outputId (outputId_), + isOpen_ (false), + isStarted (false), + internal (0) + { + internal = new ALSAThread (inputId, outputId); + } - ~ALSAAudioIODevice() - { - delete internal; - } + ~ALSAAudioIODevice() + { + delete internal; + } - const StringArray getOutputChannelNames() - { - return internal->channelNamesOut; - } + const StringArray getOutputChannelNames() + { + return internal->channelNamesOut; + } - const StringArray getInputChannelNames() - { - return internal->channelNamesIn; - } + const StringArray getInputChannelNames() + { + return internal->channelNamesIn; + } - int getNumSampleRates() - { - return internal->sampleRates.size(); - } + int getNumSampleRates() + { + return internal->sampleRates.size(); + } - double getSampleRate (int index) - { - return internal->sampleRates [index]; - } + double getSampleRate (int index) + { + return internal->sampleRates [index]; + } - int getNumBufferSizesAvailable() - { - return 50; - } + int getNumBufferSizesAvailable() + { + return 50; + } - int getBufferSizeSamples (int index) - { - int n = 16; - for (int i = 0; i < index; ++i) - n += n < 64 ? 16 - : (n < 512 ? 32 - : (n < 1024 ? 64 - : (n < 2048 ? 128 : 256))); + int getBufferSizeSamples (int index) + { + int n = 16; + for (int i = 0; i < index; ++i) + n += n < 64 ? 16 + : (n < 512 ? 32 + : (n < 1024 ? 64 + : (n < 2048 ? 128 : 256))); - return n; - } + return n; + } - int getDefaultBufferSize() - { - return 512; - } + int getDefaultBufferSize() + { + return 512; + } - const String open (const BitArray& inputChannels, - const BitArray& outputChannels, - double sampleRate, - int bufferSizeSamples) - { - close(); + const String open (const BitArray& inputChannels, + const BitArray& outputChannels, + double sampleRate, + int bufferSizeSamples) + { + close(); - if (bufferSizeSamples <= 0) - bufferSizeSamples = getDefaultBufferSize(); + if (bufferSizeSamples <= 0) + bufferSizeSamples = getDefaultBufferSize(); - if (sampleRate <= 0) - { - for (int i = 0; i < getNumSampleRates(); ++i) - { - if (getSampleRate (i) >= 44100) - { - sampleRate = getSampleRate (i); - break; - } - } - } + if (sampleRate <= 0) + { + for (int i = 0; i < getNumSampleRates(); ++i) + { + if (getSampleRate (i) >= 44100) + { + sampleRate = getSampleRate (i); + break; + } + } + } - internal->open (inputChannels, outputChannels, - sampleRate, bufferSizeSamples); + internal->open (inputChannels, outputChannels, + sampleRate, bufferSizeSamples); - isOpen_ = internal->error.isEmpty(); - return internal->error; - } + isOpen_ = internal->error.isEmpty(); + return internal->error; + } - void close() - { - stop(); - internal->close(); - isOpen_ = false; - } + void close() + { + stop(); + internal->close(); + isOpen_ = false; + } - bool isOpen() - { - return isOpen_; - } + bool isOpen() + { + return isOpen_; + } - int getCurrentBufferSizeSamples() - { - return internal->bufferSize; - } + int getCurrentBufferSizeSamples() + { + return internal->bufferSize; + } - double getCurrentSampleRate() - { - return internal->sampleRate; - } + double getCurrentSampleRate() + { + return internal->sampleRate; + } - int getCurrentBitDepth() - { - return internal->getBitDepth(); - } + int getCurrentBitDepth() + { + return internal->getBitDepth(); + } - const BitArray getActiveOutputChannels() const - { - return internal->currentOutputChans; - } + const BitArray getActiveOutputChannels() const + { + return internal->currentOutputChans; + } - const BitArray getActiveInputChannels() const - { - return internal->currentInputChans; - } + const BitArray getActiveInputChannels() const + { + return internal->currentInputChans; + } - int getOutputLatencyInSamples() - { - return 0; - } + int getOutputLatencyInSamples() + { + return 0; + } - int getInputLatencyInSamples() - { - return 0; - } + int getInputLatencyInSamples() + { + return 0; + } - void start (AudioIODeviceCallback* callback) - { - if (! isOpen_) - callback = 0; + void start (AudioIODeviceCallback* callback) + { + if (! isOpen_) + callback = 0; - internal->setCallback (callback); + internal->setCallback (callback); - if (callback != 0) - callback->audioDeviceAboutToStart (this); + if (callback != 0) + callback->audioDeviceAboutToStart (this); - isStarted = (callback != 0); - } + isStarted = (callback != 0); + } - void stop() - { - AudioIODeviceCallback* const oldCallback = internal->callback; + void stop() + { + AudioIODeviceCallback* const oldCallback = internal->callback; - start (0); + start (0); - if (oldCallback != 0) - oldCallback->audioDeviceStopped(); - } + if (oldCallback != 0) + oldCallback->audioDeviceStopped(); + } - bool isPlaying() - { - return isStarted && internal->error.isEmpty(); - } + bool isPlaying() + { + return isStarted && internal->error.isEmpty(); + } - const String getLastError() - { - return internal->error; - } + const String getLastError() + { + return internal->error; + } - String inputId, outputId; + String inputId, outputId; private: - bool isOpen_, isStarted; - ALSAThread* internal; + bool isOpen_, isStarted; + ALSAThread* internal; }; class ALSAAudioIODeviceType : public AudioIODeviceType { public: - ALSAAudioIODeviceType() - : AudioIODeviceType (T("ALSA")), - hasScanned (false) - { - } + ALSAAudioIODeviceType() + : AudioIODeviceType (T("ALSA")), + hasScanned (false) + { + } - ~ALSAAudioIODeviceType() - { - } + ~ALSAAudioIODeviceType() + { + } - void scanForDevices() - { - if (hasScanned) - return; + void scanForDevices() + { + if (hasScanned) + return; - hasScanned = true; - inputNames.clear(); - inputIds.clear(); - outputNames.clear(); - outputIds.clear(); + hasScanned = true; + inputNames.clear(); + inputIds.clear(); + outputNames.clear(); + outputIds.clear(); - snd_ctl_t* handle; - snd_ctl_card_info_t* info; - snd_ctl_card_info_alloca (&info); + snd_ctl_t* handle; + snd_ctl_card_info_t* info; + snd_ctl_card_info_alloca (&info); - int cardNum = -1; + int cardNum = -1; - while (outputIds.size() + inputIds.size() <= 32) - { - snd_card_next (&cardNum); + while (outputIds.size() + inputIds.size() <= 32) + { + snd_card_next (&cardNum); - if (cardNum < 0) - break; + if (cardNum < 0) + break; - if (snd_ctl_open (&handle, T("hw:") + String (cardNum), SND_CTL_NONBLOCK) >= 0) - { - if (snd_ctl_card_info (handle, info) >= 0) - { - String cardId (snd_ctl_card_info_get_id (info)); + if (snd_ctl_open (&handle, T("hw:") + String (cardNum), SND_CTL_NONBLOCK) >= 0) + { + if (snd_ctl_card_info (handle, info) >= 0) + { + String cardId (snd_ctl_card_info_get_id (info)); - if (cardId.removeCharacters (T("0123456789")).isEmpty()) - cardId = String (cardNum); + if (cardId.removeCharacters (T("0123456789")).isEmpty()) + cardId = String (cardNum); - int device = -1; + int device = -1; - for (;;) - { - if (snd_ctl_pcm_next_device (handle, &device) < 0 || device < 0) - break; + for (;;) + { + if (snd_ctl_pcm_next_device (handle, &device) < 0 || device < 0) + break; - String id, name; - id << "hw:" << cardId << ',' << device; + String id, name; + id << "hw:" << cardId << ',' << device; - bool isInput, isOutput; + bool isInput, isOutput; - if (testDevice (id, isInput, isOutput)) - { - name << snd_ctl_card_info_get_name (info); + if (testDevice (id, isInput, isOutput)) + { + name << snd_ctl_card_info_get_name (info); - if (name.isEmpty()) - name = id; + if (name.isEmpty()) + name = id; - if (isInput) - { - inputNames.add (name); - inputIds.add (id); - } + if (isInput) + { + inputNames.add (name); + inputIds.add (id); + } - if (isOutput) - { - outputNames.add (name); - outputIds.add (id); - } - } - } - } + if (isOutput) + { + outputNames.add (name); + outputIds.add (id); + } + } + } + } - snd_ctl_close (handle); - } - } + snd_ctl_close (handle); + } + } - inputNames.appendNumbersToDuplicates (false, true); - outputNames.appendNumbersToDuplicates (false, true); - } + inputNames.appendNumbersToDuplicates (false, true); + outputNames.appendNumbersToDuplicates (false, true); + } - const StringArray getDeviceNames (const bool wantInputNames) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + const StringArray getDeviceNames (const bool wantInputNames) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - return wantInputNames ? inputNames : outputNames; - } + return wantInputNames ? inputNames : outputNames; + } - int getDefaultDeviceIndex (const bool forInput) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this - return 0; - } + int getDefaultDeviceIndex (const bool forInput) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this + return 0; + } - bool hasSeparateInputsAndOutputs() const { return true; } + bool hasSeparateInputsAndOutputs() const { return true; } - int getIndexOfDevice (AudioIODevice* device, const bool asInput) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + int getIndexOfDevice (AudioIODevice* device, const bool asInput) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - ALSAAudioIODevice* const d = dynamic_cast (device); - if (d == 0) - return -1; + ALSAAudioIODevice* const d = dynamic_cast (device); + if (d == 0) + return -1; - return asInput ? inputIds.indexOf (d->inputId) - : outputIds.indexOf (d->outputId); - } + return asInput ? inputIds.indexOf (d->inputId) + : outputIds.indexOf (d->outputId); + } - AudioIODevice* createDevice (const String& outputDeviceName, - const String& inputDeviceName) - { - jassert (hasScanned); // need to call scanForDevices() before doing this + AudioIODevice* createDevice (const String& outputDeviceName, + const String& inputDeviceName) + { + jassert (hasScanned); // need to call scanForDevices() before doing this - const int inputIndex = inputNames.indexOf (inputDeviceName); - const int outputIndex = outputNames.indexOf (outputDeviceName); + const int inputIndex = inputNames.indexOf (inputDeviceName); + const int outputIndex = outputNames.indexOf (outputDeviceName); - String deviceName (outputIndex >= 0 ? outputDeviceName - : inputDeviceName); + String deviceName (outputIndex >= 0 ? outputDeviceName + : inputDeviceName); - if (inputIndex >= 0 || outputIndex >= 0) - return new ALSAAudioIODevice (deviceName, - inputIds [inputIndex], - outputIds [outputIndex]); + if (inputIndex >= 0 || outputIndex >= 0) + return new ALSAAudioIODevice (deviceName, + inputIds [inputIndex], + outputIds [outputIndex]); - return 0; - } + return 0; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - StringArray inputNames, outputNames, inputIds, outputIds; - bool hasScanned; + StringArray inputNames, outputNames, inputIds, outputIds; + bool hasScanned; - static bool testDevice (const String& id, bool& isInput, bool& isOutput) - { - unsigned int minChansOut = 0, maxChansOut = 0; - unsigned int minChansIn = 0, maxChansIn = 0; - Array rates; + static bool testDevice (const String& id, bool& isInput, bool& isOutput) + { + unsigned int minChansOut = 0, maxChansOut = 0; + unsigned int minChansIn = 0, maxChansIn = 0; + Array rates; - getDeviceProperties (id, minChansOut, maxChansOut, minChansIn, maxChansIn, rates); + getDeviceProperties (id, minChansOut, maxChansOut, minChansIn, maxChansIn, rates); - DBG (T("ALSA device: ") + id - + T(" outs=") + String ((int) minChansOut) + T("-") + String ((int) maxChansOut) - + T(" ins=") + String ((int) minChansIn) + T("-") + String ((int) maxChansIn) - + T(" rates=") + String (rates.size())); + DBG (T("ALSA device: ") + id + + T(" outs=") + String ((int) minChansOut) + T("-") + String ((int) maxChansOut) + + T(" ins=") + String ((int) minChansIn) + T("-") + String ((int) maxChansIn) + + T(" rates=") + String (rates.size())); - isInput = maxChansIn > 0; - isOutput = maxChansOut > 0; + isInput = maxChansIn > 0; + isOutput = maxChansOut > 0; - return (isInput || isOutput) && rates.size() > 0; - } + return (isInput || isOutput) && rates.size() > 0; + } - ALSAAudioIODeviceType (const ALSAAudioIODeviceType&); - const ALSAAudioIODeviceType& operator= (const ALSAAudioIODeviceType&); + ALSAAudioIODeviceType (const ALSAAudioIODeviceType&); + const ALSAAudioIODeviceType& operator= (const ALSAAudioIODeviceType&); }; AudioIODeviceType* juce_createAudioIODeviceType_ALSA() { - return new ALSAAudioIODeviceType(); + return new ALSAAudioIODeviceType(); } #endif @@ -258063,27 +235693,27 @@ static void* juce_libjack_handle = 0; void* juce_load_jack_function (const char* const name) { - if (juce_libjack_handle == 0) - return 0; + if (juce_libjack_handle == 0) + return 0; - return dlsym (juce_libjack_handle, name); + return dlsym (juce_libjack_handle, name); } #define JUCE_DECL_JACK_FUNCTION(return_type, fn_name, argument_types, arguments) \ - typedef return_type (*fn_name##_ptr_t)argument_types; \ - return_type fn_name argument_types { \ - static fn_name##_ptr_t fn = 0; \ - if (fn == 0) { fn = (fn_name##_ptr_t)juce_load_jack_function(#fn_name); } \ - if (fn) return (*fn)arguments; \ - else return 0; \ + typedef return_type (*fn_name##_ptr_t)argument_types; \ + return_type fn_name argument_types { \ + static fn_name##_ptr_t fn = 0; \ + if (fn == 0) { fn = (fn_name##_ptr_t)juce_load_jack_function(#fn_name); } \ + if (fn) return (*fn)arguments; \ + else return 0; \ } -#define JUCE_DECL_VOID_JACK_FUNCTION(fn_name, argument_types, arguments) \ - typedef void (*fn_name##_ptr_t)argument_types; \ - void fn_name argument_types { \ - static fn_name##_ptr_t fn = 0; \ - if (fn == 0) { fn = (fn_name##_ptr_t)juce_load_jack_function(#fn_name); } \ - if (fn) (*fn)arguments; \ +#define JUCE_DECL_VOID_JACK_FUNCTION(fn_name, argument_types, arguments) \ + typedef void (*fn_name##_ptr_t)argument_types; \ + void fn_name argument_types { \ + static fn_name##_ptr_t fn = 0; \ + if (fn == 0) { fn = (fn_name##_ptr_t)juce_load_jack_function(#fn_name); } \ + if (fn) (*fn)arguments; \ } JUCE_DECL_JACK_FUNCTION (jack_client_t*, jack_client_open, (const char* client_name, jack_options_t options, jack_status_t* status), (client_name, options, status)); @@ -258113,23 +235743,23 @@ JUCE_DECL_JACK_FUNCTION (int, jack_port_connected_to, (const jack_port_t* port, #if JACK_LOGGING_ENABLED static void jack_Log (const String& s) { - puts (s); + puts (s); } static void dumpJackErrorMessage (const jack_status_t status) throw() { - if (status & JackServerFailed || status & JackServerError) - jack_Log ("Unable to connect to JACK server"); - if (status & JackVersionError) - jack_Log ("Client's protocol version does not match"); - if (status & JackInvalidOption) - jack_Log ("The operation contained an invalid or unsupported option"); - if (status & JackNameNotUnique) - jack_Log ("The desired client name was not unique"); - if (status & JackNoSuchClient) - jack_Log ("Requested client does not exist"); - if (status & JackInitFailure) - jack_Log ("Unable to initialize client"); + if (status & JackServerFailed || status & JackServerError) + jack_Log ("Unable to connect to JACK server"); + if (status & JackVersionError) + jack_Log ("Client's protocol version does not match"); + if (status & JackInvalidOption) + jack_Log ("The operation contained an invalid or unsupported option"); + if (status & JackNameNotUnique) + jack_Log ("The desired client name was not unique"); + if (status & JackNoSuchClient) + jack_Log ("Requested client does not exist"); + if (status & JackInitFailure) + jack_Log ("Unable to initialize client"); } #else #define dumpJackErrorMessage(a) {} @@ -258143,488 +235773,488 @@ static void dumpJackErrorMessage (const jack_status_t status) throw() class JackAudioIODevice : public AudioIODevice { public: - JackAudioIODevice (const String& deviceName, - const String& inputId_, - const String& outputId_) - : AudioIODevice (deviceName, T("JACK")), - inputId (inputId_), - outputId (outputId_), - isOpen_ (false), - callback (0), - totalNumberOfInputChannels (0), - totalNumberOfOutputChannels (0) - { - jassert (deviceName.isNotEmpty()); + JackAudioIODevice (const String& deviceName, + const String& inputId_, + const String& outputId_) + : AudioIODevice (deviceName, T("JACK")), + inputId (inputId_), + outputId (outputId_), + isOpen_ (false), + callback (0), + totalNumberOfInputChannels (0), + totalNumberOfOutputChannels (0) + { + jassert (deviceName.isNotEmpty()); - jack_status_t status; - client = JUCE_NAMESPACE::jack_client_open (JUCE_JACK_CLIENT_NAME, JackNoStartServer, &status); + jack_status_t status; + client = JUCE_NAMESPACE::jack_client_open (JUCE_JACK_CLIENT_NAME, JackNoStartServer, &status); - if (client == 0) - { - dumpJackErrorMessage (status); - } - else - { - JUCE_NAMESPACE::jack_set_error_function (errorCallback); + if (client == 0) + { + dumpJackErrorMessage (status); + } + else + { + JUCE_NAMESPACE::jack_set_error_function (errorCallback); - // open input ports - const StringArray inputChannels (getInputChannelNames()); - for (int i = 0; i < inputChannels.size(); i++) - { - String inputName; - inputName << "in_" << (++totalNumberOfInputChannels); + // open input ports + const StringArray inputChannels (getInputChannelNames()); + for (int i = 0; i < inputChannels.size(); i++) + { + String inputName; + inputName << "in_" << (++totalNumberOfInputChannels); - inputPorts.add (JUCE_NAMESPACE::jack_port_register (client, (const char*) inputName, - JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)); - } + inputPorts.add (JUCE_NAMESPACE::jack_port_register (client, (const char*) inputName, + JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)); + } - // open output ports - const StringArray outputChannels (getOutputChannelNames()); - for (int i = 0; i < outputChannels.size (); i++) - { - String outputName; - outputName << "out_" << (++totalNumberOfOutputChannels); + // open output ports + const StringArray outputChannels (getOutputChannelNames()); + for (int i = 0; i < outputChannels.size (); i++) + { + String outputName; + outputName << "out_" << (++totalNumberOfOutputChannels); - outputPorts.add (JUCE_NAMESPACE::jack_port_register (client, (const char*) outputName, - JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)); - } + outputPorts.add (JUCE_NAMESPACE::jack_port_register (client, (const char*) outputName, + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)); + } - inChans.calloc (totalNumberOfInputChannels + 2); - outChans.calloc (totalNumberOfOutputChannels + 2); - } - } + inChans.calloc (totalNumberOfInputChannels + 2); + outChans.calloc (totalNumberOfOutputChannels + 2); + } + } - ~JackAudioIODevice() - { - close(); - if (client != 0) - { - JUCE_NAMESPACE::jack_client_close (client); - client = 0; - } - } + ~JackAudioIODevice() + { + close(); + if (client != 0) + { + JUCE_NAMESPACE::jack_client_close (client); + client = 0; + } + } - const StringArray getChannelNames (bool forInput) const - { - StringArray names; - const char** const ports = JUCE_NAMESPACE::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ - forInput ? JackPortIsInput : JackPortIsOutput); + const StringArray getChannelNames (bool forInput) const + { + StringArray names; + const char** const ports = JUCE_NAMESPACE::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ + forInput ? JackPortIsInput : JackPortIsOutput); - if (ports != 0) - { - int j = 0; - while (ports[j] != 0) - { - const String portName (ports [j++]); + if (ports != 0) + { + int j = 0; + while (ports[j] != 0) + { + const String portName (ports [j++]); - if (portName.upToFirstOccurrenceOf (T(":"), false, false) == getName()) - names.add (portName.fromFirstOccurrenceOf (T(":"), false, false)); - } + if (portName.upToFirstOccurrenceOf (T(":"), false, false) == getName()) + names.add (portName.fromFirstOccurrenceOf (T(":"), false, false)); + } - free (ports); - } + free (ports); + } - return names; - } + return names; + } - const StringArray getOutputChannelNames() { return getChannelNames (false); } - const StringArray getInputChannelNames() { return getChannelNames (true); } - int getNumSampleRates() { return client != 0 ? 1 : 0; } - double getSampleRate (int index) { return client != 0 ? JUCE_NAMESPACE::jack_get_sample_rate (client) : 0; } - int getNumBufferSizesAvailable() { return client != 0 ? 1 : 0; } - int getBufferSizeSamples (int index) { return getDefaultBufferSize(); } - int getDefaultBufferSize() { return client != 0 ? JUCE_NAMESPACE::jack_get_buffer_size (client) : 0; } + const StringArray getOutputChannelNames() { return getChannelNames (false); } + const StringArray getInputChannelNames() { return getChannelNames (true); } + int getNumSampleRates() { return client != 0 ? 1 : 0; } + double getSampleRate (int index) { return client != 0 ? JUCE_NAMESPACE::jack_get_sample_rate (client) : 0; } + int getNumBufferSizesAvailable() { return client != 0 ? 1 : 0; } + int getBufferSizeSamples (int index) { return getDefaultBufferSize(); } + int getDefaultBufferSize() { return client != 0 ? JUCE_NAMESPACE::jack_get_buffer_size (client) : 0; } - const String open (const BitArray& inputChannels, const BitArray& outputChannels, - double sampleRate, int bufferSizeSamples) - { - if (client == 0) - { - lastError = T("No JACK client running"); - return lastError; - } + const String open (const BitArray& inputChannels, const BitArray& outputChannels, + double sampleRate, int bufferSizeSamples) + { + if (client == 0) + { + lastError = T("No JACK client running"); + return lastError; + } - lastError = String::empty; - close(); + lastError = String::empty; + close(); - JUCE_NAMESPACE::jack_set_process_callback (client, processCallback, this); - JUCE_NAMESPACE::jack_on_shutdown (client, shutdownCallback, this); - JUCE_NAMESPACE::jack_activate (client); - isOpen_ = true; + JUCE_NAMESPACE::jack_set_process_callback (client, processCallback, this); + JUCE_NAMESPACE::jack_on_shutdown (client, shutdownCallback, this); + JUCE_NAMESPACE::jack_activate (client); + isOpen_ = true; - if (! inputChannels.isEmpty()) - { - const char** const ports = JUCE_NAMESPACE::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsOutput); + if (! inputChannels.isEmpty()) + { + const char** const ports = JUCE_NAMESPACE::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsOutput); - if (ports != 0) - { - const int numInputChannels = inputChannels.getHighestBit () + 1; + if (ports != 0) + { + const int numInputChannels = inputChannels.getHighestBit () + 1; - for (int i = 0; i < numInputChannels; ++i) - { - const String portName (ports[i]); + for (int i = 0; i < numInputChannels; ++i) + { + const String portName (ports[i]); - if (inputChannels[i] && portName.upToFirstOccurrenceOf (T(":"), false, false) == getName()) - { - int error = JUCE_NAMESPACE::jack_connect (client, ports[i], JUCE_NAMESPACE::jack_port_name ((jack_port_t*) inputPorts[i])); - if (error != 0) - jack_Log ("Cannot connect input port " + String (i) + " (" + String (ports[i]) + "), error " + String (error)); - } - } + if (inputChannels[i] && portName.upToFirstOccurrenceOf (T(":"), false, false) == getName()) + { + int error = JUCE_NAMESPACE::jack_connect (client, ports[i], JUCE_NAMESPACE::jack_port_name ((jack_port_t*) inputPorts[i])); + if (error != 0) + jack_Log ("Cannot connect input port " + String (i) + " (" + String (ports[i]) + "), error " + String (error)); + } + } - free (ports); - } - } + free (ports); + } + } - if (! outputChannels.isEmpty()) - { - const char** const ports = JUCE_NAMESPACE::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsInput); + if (! outputChannels.isEmpty()) + { + const char** const ports = JUCE_NAMESPACE::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsInput); - if (ports != 0) - { - const int numOutputChannels = outputChannels.getHighestBit () + 1; + if (ports != 0) + { + const int numOutputChannels = outputChannels.getHighestBit () + 1; - for (int i = 0; i < numOutputChannels; ++i) - { - const String portName (ports[i]); + for (int i = 0; i < numOutputChannels; ++i) + { + const String portName (ports[i]); - if (outputChannels[i] && portName.upToFirstOccurrenceOf (T(":"), false, false) == getName()) - { - int error = JUCE_NAMESPACE::jack_connect (client, JUCE_NAMESPACE::jack_port_name ((jack_port_t*) outputPorts[i]), ports[i]); - if (error != 0) - jack_Log ("Cannot connect output port " + String (i) + " (" + String (ports[i]) + "), error " + String (error)); - } - } + if (outputChannels[i] && portName.upToFirstOccurrenceOf (T(":"), false, false) == getName()) + { + int error = JUCE_NAMESPACE::jack_connect (client, JUCE_NAMESPACE::jack_port_name ((jack_port_t*) outputPorts[i]), ports[i]); + if (error != 0) + jack_Log ("Cannot connect output port " + String (i) + " (" + String (ports[i]) + "), error " + String (error)); + } + } - free (ports); - } - } + free (ports); + } + } - return lastError; - } + return lastError; + } - void close() - { - stop(); + void close() + { + stop(); - if (client != 0) - { - JUCE_NAMESPACE::jack_deactivate (client); - JUCE_NAMESPACE::jack_set_process_callback (client, processCallback, 0); - JUCE_NAMESPACE::jack_on_shutdown (client, shutdownCallback, 0); - } + if (client != 0) + { + JUCE_NAMESPACE::jack_deactivate (client); + JUCE_NAMESPACE::jack_set_process_callback (client, processCallback, 0); + JUCE_NAMESPACE::jack_on_shutdown (client, shutdownCallback, 0); + } - isOpen_ = false; - } + isOpen_ = false; + } - void start (AudioIODeviceCallback* newCallback) - { - if (isOpen_ && newCallback != callback) - { - if (newCallback != 0) - newCallback->audioDeviceAboutToStart (this); + void start (AudioIODeviceCallback* newCallback) + { + if (isOpen_ && newCallback != callback) + { + if (newCallback != 0) + newCallback->audioDeviceAboutToStart (this); - AudioIODeviceCallback* const oldCallback = callback; + AudioIODeviceCallback* const oldCallback = callback; - { - const ScopedLock sl (callbackLock); - callback = newCallback; - } + { + const ScopedLock sl (callbackLock); + callback = newCallback; + } - if (oldCallback != 0) - oldCallback->audioDeviceStopped(); - } - } + if (oldCallback != 0) + oldCallback->audioDeviceStopped(); + } + } - void stop() - { - start (0); - } + void stop() + { + start (0); + } - bool isOpen() { return isOpen_; } - bool isPlaying() { return callback != 0; } - int getCurrentBufferSizeSamples() { return getBufferSizeSamples (0); } - double getCurrentSampleRate() { return getSampleRate (0); } - int getCurrentBitDepth() { return 32; } - const String getLastError() { return lastError; } + bool isOpen() { return isOpen_; } + bool isPlaying() { return callback != 0; } + int getCurrentBufferSizeSamples() { return getBufferSizeSamples (0); } + double getCurrentSampleRate() { return getSampleRate (0); } + int getCurrentBitDepth() { return 32; } + const String getLastError() { return lastError; } - const BitArray getActiveOutputChannels() const - { - BitArray outputBits; + const BitArray getActiveOutputChannels() const + { + BitArray outputBits; - for (int i = 0; i < outputPorts.size(); i++) - if (JUCE_NAMESPACE::jack_port_connected ((jack_port_t*) outputPorts [i])) - outputBits.setBit (i); + for (int i = 0; i < outputPorts.size(); i++) + if (JUCE_NAMESPACE::jack_port_connected ((jack_port_t*) outputPorts [i])) + outputBits.setBit (i); - return outputBits; - } + return outputBits; + } - const BitArray getActiveInputChannels() const - { - BitArray inputBits; + const BitArray getActiveInputChannels() const + { + BitArray inputBits; - for (int i = 0; i < inputPorts.size(); i++) - if (JUCE_NAMESPACE::jack_port_connected ((jack_port_t*) inputPorts [i])) - inputBits.setBit (i); + for (int i = 0; i < inputPorts.size(); i++) + if (JUCE_NAMESPACE::jack_port_connected ((jack_port_t*) inputPorts [i])) + inputBits.setBit (i); - return inputBits; - } + return inputBits; + } - int getOutputLatencyInSamples() - { - int latency = 0; + int getOutputLatencyInSamples() + { + int latency = 0; - for (int i = 0; i < outputPorts.size(); i++) - latency = jmax (latency, (int) JUCE_NAMESPACE::jack_port_get_total_latency (client, (jack_port_t*) outputPorts [i])); + for (int i = 0; i < outputPorts.size(); i++) + latency = jmax (latency, (int) JUCE_NAMESPACE::jack_port_get_total_latency (client, (jack_port_t*) outputPorts [i])); - return latency; - } + return latency; + } - int getInputLatencyInSamples() - { - int latency = 0; + int getInputLatencyInSamples() + { + int latency = 0; - for (int i = 0; i < inputPorts.size(); i++) - latency = jmax (latency, (int) JUCE_NAMESPACE::jack_port_get_total_latency (client, (jack_port_t*) inputPorts [i])); + for (int i = 0; i < inputPorts.size(); i++) + latency = jmax (latency, (int) JUCE_NAMESPACE::jack_port_get_total_latency (client, (jack_port_t*) inputPorts [i])); - return latency; - } + return latency; + } - String inputId, outputId; + String inputId, outputId; private: - void process (const int numSamples) - { - int i, numActiveInChans = 0, numActiveOutChans = 0; + void process (const int numSamples) + { + int i, numActiveInChans = 0, numActiveOutChans = 0; - for (i = 0; i < totalNumberOfInputChannels; ++i) - { - jack_default_audio_sample_t* in - = (jack_default_audio_sample_t*) JUCE_NAMESPACE::jack_port_get_buffer ((jack_port_t*) inputPorts.getUnchecked(i), numSamples); + for (i = 0; i < totalNumberOfInputChannels; ++i) + { + jack_default_audio_sample_t* in + = (jack_default_audio_sample_t*) JUCE_NAMESPACE::jack_port_get_buffer ((jack_port_t*) inputPorts.getUnchecked(i), numSamples); - if (in != 0) - inChans [numActiveInChans++] = (float*) in; - } + if (in != 0) + inChans [numActiveInChans++] = (float*) in; + } - for (i = 0; i < totalNumberOfOutputChannels; ++i) - { - jack_default_audio_sample_t* out - = (jack_default_audio_sample_t*) JUCE_NAMESPACE::jack_port_get_buffer ((jack_port_t*) outputPorts.getUnchecked(i), numSamples); + for (i = 0; i < totalNumberOfOutputChannels; ++i) + { + jack_default_audio_sample_t* out + = (jack_default_audio_sample_t*) JUCE_NAMESPACE::jack_port_get_buffer ((jack_port_t*) outputPorts.getUnchecked(i), numSamples); - if (out != 0) - outChans [numActiveOutChans++] = (float*) out; - } + if (out != 0) + outChans [numActiveOutChans++] = (float*) out; + } - const ScopedLock sl (callbackLock); + const ScopedLock sl (callbackLock); - if (callback != 0) - { - callback->audioDeviceIOCallback ((const float**) inChans, numActiveInChans, - outChans, numActiveOutChans, numSamples); - } - else - { - for (i = 0; i < numActiveOutChans; ++i) - zeromem (outChans[i], sizeof (float) * numSamples); - } - } + if (callback != 0) + { + callback->audioDeviceIOCallback ((const float**) inChans, numActiveInChans, + outChans, numActiveOutChans, numSamples); + } + else + { + for (i = 0; i < numActiveOutChans; ++i) + zeromem (outChans[i], sizeof (float) * numSamples); + } + } - static int processCallback (jack_nframes_t nframes, void* callbackArgument) - { - if (callbackArgument != 0) - ((JackAudioIODevice*) callbackArgument)->process (nframes); + static int processCallback (jack_nframes_t nframes, void* callbackArgument) + { + if (callbackArgument != 0) + ((JackAudioIODevice*) callbackArgument)->process (nframes); - return 0; - } + return 0; + } - static void threadInitCallback (void* callbackArgument) - { - jack_Log ("JackAudioIODevice::initialise"); - } + static void threadInitCallback (void* callbackArgument) + { + jack_Log ("JackAudioIODevice::initialise"); + } - static void shutdownCallback (void* callbackArgument) - { - jack_Log ("JackAudioIODevice::shutdown"); + static void shutdownCallback (void* callbackArgument) + { + jack_Log ("JackAudioIODevice::shutdown"); - JackAudioIODevice* device = (JackAudioIODevice*) callbackArgument; + JackAudioIODevice* device = (JackAudioIODevice*) callbackArgument; - if (device != 0) - { - device->client = 0; - device->close(); - } - } + if (device != 0) + { + device->client = 0; + device->close(); + } + } - static void errorCallback (const char* msg) - { - jack_Log ("JackAudioIODevice::errorCallback " + String (msg)); - } + static void errorCallback (const char* msg) + { + jack_Log ("JackAudioIODevice::errorCallback " + String (msg)); + } - bool isOpen_; - jack_client_t* client; - String lastError; - AudioIODeviceCallback* callback; - CriticalSection callbackLock; + bool isOpen_; + jack_client_t* client; + String lastError; + AudioIODeviceCallback* callback; + CriticalSection callbackLock; - HeapBlock inChans, outChans; - int totalNumberOfInputChannels; - int totalNumberOfOutputChannels; - VoidArray inputPorts, outputPorts; + HeapBlock inChans, outChans; + int totalNumberOfInputChannels; + int totalNumberOfOutputChannels; + VoidArray inputPorts, outputPorts; }; class JackAudioIODeviceType : public AudioIODeviceType { public: - JackAudioIODeviceType() - : AudioIODeviceType (T("JACK")), - hasScanned (false) - { - } + JackAudioIODeviceType() + : AudioIODeviceType (T("JACK")), + hasScanned (false) + { + } - ~JackAudioIODeviceType() - { - } + ~JackAudioIODeviceType() + { + } - void scanForDevices() - { - hasScanned = true; - inputNames.clear(); - inputIds.clear(); - outputNames.clear(); - outputIds.clear(); + void scanForDevices() + { + hasScanned = true; + inputNames.clear(); + inputIds.clear(); + outputNames.clear(); + outputIds.clear(); - if (juce_libjack_handle == 0) - { - juce_libjack_handle = dlopen ("libjack.so", RTLD_LAZY); + if (juce_libjack_handle == 0) + { + juce_libjack_handle = dlopen ("libjack.so", RTLD_LAZY); - if (juce_libjack_handle == 0) - return; - } + if (juce_libjack_handle == 0) + return; + } - // open a dummy client - jack_status_t status; - jack_client_t* client = JUCE_NAMESPACE::jack_client_open ("JuceJackDummy", JackNoStartServer, &status); + // open a dummy client + jack_status_t status; + jack_client_t* client = JUCE_NAMESPACE::jack_client_open ("JuceJackDummy", JackNoStartServer, &status); - if (client == 0) - { - dumpJackErrorMessage (status); - } - else - { - // scan for output devices - const char** ports = JUCE_NAMESPACE::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsOutput); + if (client == 0) + { + dumpJackErrorMessage (status); + } + else + { + // scan for output devices + const char** ports = JUCE_NAMESPACE::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsOutput); - if (ports != 0) - { - int j = 0; - while (ports[j] != 0) - { - String clientName (ports[j]); - clientName = clientName.upToFirstOccurrenceOf (T(":"), false, false); + if (ports != 0) + { + int j = 0; + while (ports[j] != 0) + { + String clientName (ports[j]); + clientName = clientName.upToFirstOccurrenceOf (T(":"), false, false); - if (clientName != String (JUCE_JACK_CLIENT_NAME) - && ! inputNames.contains (clientName)) - { - inputNames.add (clientName); - inputIds.add (ports [j]); - } + if (clientName != String (JUCE_JACK_CLIENT_NAME) + && ! inputNames.contains (clientName)) + { + inputNames.add (clientName); + inputIds.add (ports [j]); + } - ++j; - } + ++j; + } - free (ports); - } + free (ports); + } - // scan for input devices - ports = JUCE_NAMESPACE::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsInput); + // scan for input devices + ports = JUCE_NAMESPACE::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsInput); - if (ports != 0) - { - int j = 0; - while (ports[j] != 0) - { - String clientName (ports[j]); - clientName = clientName.upToFirstOccurrenceOf (T(":"), false, false); + if (ports != 0) + { + int j = 0; + while (ports[j] != 0) + { + String clientName (ports[j]); + clientName = clientName.upToFirstOccurrenceOf (T(":"), false, false); - if (clientName != String (JUCE_JACK_CLIENT_NAME) - && ! outputNames.contains (clientName)) - { - outputNames.add (clientName); - outputIds.add (ports [j]); - } + if (clientName != String (JUCE_JACK_CLIENT_NAME) + && ! outputNames.contains (clientName)) + { + outputNames.add (clientName); + outputIds.add (ports [j]); + } - ++j; - } + ++j; + } - free (ports); - } + free (ports); + } - JUCE_NAMESPACE::jack_client_close (client); - } - } + JUCE_NAMESPACE::jack_client_close (client); + } + } - const StringArray getDeviceNames (const bool wantInputNames) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this - return wantInputNames ? inputNames : outputNames; - } + const StringArray getDeviceNames (const bool wantInputNames) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this + return wantInputNames ? inputNames : outputNames; + } - int getDefaultDeviceIndex (const bool forInput) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this - return 0; - } + int getDefaultDeviceIndex (const bool forInput) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this + return 0; + } - bool hasSeparateInputsAndOutputs() const { return true; } + bool hasSeparateInputsAndOutputs() const { return true; } - int getIndexOfDevice (AudioIODevice* device, const bool asInput) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + int getIndexOfDevice (AudioIODevice* device, const bool asInput) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - JackAudioIODevice* const d = dynamic_cast (device); - if (d == 0) - return -1; + JackAudioIODevice* const d = dynamic_cast (device); + if (d == 0) + return -1; - return asInput ? inputIds.indexOf (d->inputId) - : outputIds.indexOf (d->outputId); - } + return asInput ? inputIds.indexOf (d->inputId) + : outputIds.indexOf (d->outputId); + } - AudioIODevice* createDevice (const String& outputDeviceName, - const String& inputDeviceName) - { - jassert (hasScanned); // need to call scanForDevices() before doing this + AudioIODevice* createDevice (const String& outputDeviceName, + const String& inputDeviceName) + { + jassert (hasScanned); // need to call scanForDevices() before doing this - const int inputIndex = inputNames.indexOf (inputDeviceName); - const int outputIndex = outputNames.indexOf (outputDeviceName); + const int inputIndex = inputNames.indexOf (inputDeviceName); + const int outputIndex = outputNames.indexOf (outputDeviceName); - if (inputIndex >= 0 || outputIndex >= 0) - return new JackAudioIODevice (outputIndex >= 0 ? outputDeviceName - : inputDeviceName, - inputIds [inputIndex], - outputIds [outputIndex]); + if (inputIndex >= 0 || outputIndex >= 0) + return new JackAudioIODevice (outputIndex >= 0 ? outputDeviceName + : inputDeviceName, + inputIds [inputIndex], + outputIds [outputIndex]); - return 0; - } + return 0; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - StringArray inputNames, outputNames, inputIds, outputIds; - bool hasScanned; + StringArray inputNames, outputNames, inputIds, outputIds; + bool hasScanned; - JackAudioIODeviceType (const JackAudioIODeviceType&); - const JackAudioIODeviceType& operator= (const JackAudioIODeviceType&); + JackAudioIODeviceType (const JackAudioIODeviceType&); + const JackAudioIODeviceType& operator= (const JackAudioIODeviceType&); }; AudioIODeviceType* juce_createAudioIODeviceType_JACK() { - return new JackAudioIODeviceType(); + return new JackAudioIODeviceType(); } #else // if JACK is turned off.. -AudioIODeviceType* juce_createAudioIODeviceType_JACK() { return 0; } +AudioIODeviceType* juce_createAudioIODeviceType_JACK() { return 0; } #endif #endif @@ -258637,228 +236267,228 @@ AudioIODeviceType* juce_createAudioIODeviceType_JACK() { return 0; } #if JUCE_ALSA static snd_seq_t* iterateDevices (const bool forInput, - StringArray& deviceNamesFound, - const int deviceIndexToOpen) + StringArray& deviceNamesFound, + const int deviceIndexToOpen) { - snd_seq_t* returnedHandle = 0; - snd_seq_t* seqHandle; + snd_seq_t* returnedHandle = 0; + snd_seq_t* seqHandle; - if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT - : SND_SEQ_OPEN_OUTPUT, 0) == 0) - { - snd_seq_system_info_t* systemInfo; - snd_seq_client_info_t* clientInfo; + if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT + : SND_SEQ_OPEN_OUTPUT, 0) == 0) + { + snd_seq_system_info_t* systemInfo; + snd_seq_client_info_t* clientInfo; - if (snd_seq_system_info_malloc (&systemInfo) == 0) - { - if (snd_seq_system_info (seqHandle, systemInfo) == 0 - && snd_seq_client_info_malloc (&clientInfo) == 0) - { - int numClients = snd_seq_system_info_get_cur_clients (systemInfo); + if (snd_seq_system_info_malloc (&systemInfo) == 0) + { + if (snd_seq_system_info (seqHandle, systemInfo) == 0 + && snd_seq_client_info_malloc (&clientInfo) == 0) + { + int numClients = snd_seq_system_info_get_cur_clients (systemInfo); - while (--numClients >= 0 && returnedHandle == 0) - { - if (snd_seq_query_next_client (seqHandle, clientInfo) == 0) - { - snd_seq_port_info_t* portInfo; - if (snd_seq_port_info_malloc (&portInfo) == 0) - { - int numPorts = snd_seq_client_info_get_num_ports (clientInfo); - const int client = snd_seq_client_info_get_client (clientInfo); + while (--numClients >= 0 && returnedHandle == 0) + { + if (snd_seq_query_next_client (seqHandle, clientInfo) == 0) + { + snd_seq_port_info_t* portInfo; + if (snd_seq_port_info_malloc (&portInfo) == 0) + { + int numPorts = snd_seq_client_info_get_num_ports (clientInfo); + const int client = snd_seq_client_info_get_client (clientInfo); - snd_seq_port_info_set_client (portInfo, client); - snd_seq_port_info_set_port (portInfo, -1); + snd_seq_port_info_set_client (portInfo, client); + snd_seq_port_info_set_port (portInfo, -1); - while (--numPorts >= 0) - { - if (snd_seq_query_next_port (seqHandle, portInfo) == 0 - && (snd_seq_port_info_get_capability (portInfo) - & (forInput ? SND_SEQ_PORT_CAP_READ - : SND_SEQ_PORT_CAP_WRITE)) != 0) - { - deviceNamesFound.add (snd_seq_client_info_get_name (clientInfo)); + while (--numPorts >= 0) + { + if (snd_seq_query_next_port (seqHandle, portInfo) == 0 + && (snd_seq_port_info_get_capability (portInfo) + & (forInput ? SND_SEQ_PORT_CAP_READ + : SND_SEQ_PORT_CAP_WRITE)) != 0) + { + deviceNamesFound.add (snd_seq_client_info_get_name (clientInfo)); - if (deviceNamesFound.size() == deviceIndexToOpen + 1) - { - const int sourcePort = snd_seq_port_info_get_port (portInfo); - const int sourceClient = snd_seq_client_info_get_client (clientInfo); + if (deviceNamesFound.size() == deviceIndexToOpen + 1) + { + const int sourcePort = snd_seq_port_info_get_port (portInfo); + const int sourceClient = snd_seq_client_info_get_client (clientInfo); - if (sourcePort != -1) - { - snd_seq_set_client_name (seqHandle, - forInput ? "Juce Midi Input" - : "Juce Midi Output"); + if (sourcePort != -1) + { + snd_seq_set_client_name (seqHandle, + forInput ? "Juce Midi Input" + : "Juce Midi Output"); - const int portId - = snd_seq_create_simple_port (seqHandle, - forInput ? "Juce Midi In Port" - : "Juce Midi Out Port", - forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE) - : (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ), - SND_SEQ_PORT_TYPE_MIDI_GENERIC); + const int portId + = snd_seq_create_simple_port (seqHandle, + forInput ? "Juce Midi In Port" + : "Juce Midi Out Port", + forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE) + : (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ), + SND_SEQ_PORT_TYPE_MIDI_GENERIC); - snd_seq_connect_from (seqHandle, portId, sourceClient, sourcePort); + snd_seq_connect_from (seqHandle, portId, sourceClient, sourcePort); - returnedHandle = seqHandle; - } - } - } - } + returnedHandle = seqHandle; + } + } + } + } - snd_seq_port_info_free (portInfo); - } - } - } + snd_seq_port_info_free (portInfo); + } + } + } - snd_seq_client_info_free (clientInfo); - } + snd_seq_client_info_free (clientInfo); + } - snd_seq_system_info_free (systemInfo); - } + snd_seq_system_info_free (systemInfo); + } - if (returnedHandle == 0) - snd_seq_close (seqHandle); - } + if (returnedHandle == 0) + snd_seq_close (seqHandle); + } - deviceNamesFound.appendNumbersToDuplicates (true, true); + deviceNamesFound.appendNumbersToDuplicates (true, true); - return returnedHandle; + return returnedHandle; } static snd_seq_t* createDevice (const bool forInput, - const String& deviceNameToOpen) + const String& deviceNameToOpen) { - snd_seq_t* seqHandle = 0; + snd_seq_t* seqHandle = 0; - if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT - : SND_SEQ_OPEN_OUTPUT, 0) == 0) - { - snd_seq_set_client_name (seqHandle, - (const char*) (forInput ? (deviceNameToOpen + T(" Input")) - : (deviceNameToOpen + T(" Output")))); + if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT + : SND_SEQ_OPEN_OUTPUT, 0) == 0) + { + snd_seq_set_client_name (seqHandle, + (const char*) (forInput ? (deviceNameToOpen + T(" Input")) + : (deviceNameToOpen + T(" Output")))); - const int portId - = snd_seq_create_simple_port (seqHandle, - forInput ? "in" - : "out", - forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE) - : (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ), - forInput ? SND_SEQ_PORT_TYPE_APPLICATION - : SND_SEQ_PORT_TYPE_MIDI_GENERIC); + const int portId + = snd_seq_create_simple_port (seqHandle, + forInput ? "in" + : "out", + forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE) + : (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ), + forInput ? SND_SEQ_PORT_TYPE_APPLICATION + : SND_SEQ_PORT_TYPE_MIDI_GENERIC); - if (portId < 0) - { - snd_seq_close (seqHandle); - seqHandle = 0; - } - } + if (portId < 0) + { + snd_seq_close (seqHandle); + seqHandle = 0; + } + } - return seqHandle; + return seqHandle; } class MidiOutputDevice { public: - MidiOutputDevice (MidiOutput* const midiOutput_, - snd_seq_t* const seqHandle_) - : - midiOutput (midiOutput_), - seqHandle (seqHandle_), - maxEventSize (16 * 1024) - { - jassert (seqHandle != 0 && midiOutput != 0); - snd_midi_event_new (maxEventSize, &midiParser); - } + MidiOutputDevice (MidiOutput* const midiOutput_, + snd_seq_t* const seqHandle_) + : + midiOutput (midiOutput_), + seqHandle (seqHandle_), + maxEventSize (16 * 1024) + { + jassert (seqHandle != 0 && midiOutput != 0); + snd_midi_event_new (maxEventSize, &midiParser); + } - ~MidiOutputDevice() - { - snd_midi_event_free (midiParser); - snd_seq_close (seqHandle); - } + ~MidiOutputDevice() + { + snd_midi_event_free (midiParser); + snd_seq_close (seqHandle); + } - void sendMessageNow (const MidiMessage& message) - { - if (message.getRawDataSize() > maxEventSize) - { - maxEventSize = message.getRawDataSize(); - snd_midi_event_free (midiParser); - snd_midi_event_new (maxEventSize, &midiParser); - } + void sendMessageNow (const MidiMessage& message) + { + if (message.getRawDataSize() > maxEventSize) + { + maxEventSize = message.getRawDataSize(); + snd_midi_event_free (midiParser); + snd_midi_event_new (maxEventSize, &midiParser); + } - snd_seq_event_t event; - snd_seq_ev_clear (&event); + snd_seq_event_t event; + snd_seq_ev_clear (&event); - snd_midi_event_encode (midiParser, - message.getRawData(), - message.getRawDataSize(), - &event); + snd_midi_event_encode (midiParser, + message.getRawData(), + message.getRawDataSize(), + &event); - snd_midi_event_reset_encode (midiParser); + snd_midi_event_reset_encode (midiParser); - snd_seq_ev_set_source (&event, 0); - snd_seq_ev_set_subs (&event); - snd_seq_ev_set_direct (&event); + snd_seq_ev_set_source (&event, 0); + snd_seq_ev_set_subs (&event); + snd_seq_ev_set_direct (&event); - snd_seq_event_output (seqHandle, &event); - snd_seq_drain_output (seqHandle); - } + snd_seq_event_output (seqHandle, &event); + snd_seq_drain_output (seqHandle); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - MidiOutput* const midiOutput; - snd_seq_t* const seqHandle; - snd_midi_event_t* midiParser; - int maxEventSize; + MidiOutput* const midiOutput; + snd_seq_t* const seqHandle; + snd_midi_event_t* midiParser; + int maxEventSize; }; const StringArray MidiOutput::getDevices() { - StringArray devices; - iterateDevices (false, devices, -1); - return devices; + StringArray devices; + iterateDevices (false, devices, -1); + return devices; } int MidiOutput::getDefaultDeviceIndex() { - return 0; + return 0; } MidiOutput* MidiOutput::openDevice (int deviceIndex) { - MidiOutput* newDevice = 0; + MidiOutput* newDevice = 0; - StringArray devices; - snd_seq_t* const handle = iterateDevices (false, devices, deviceIndex); + StringArray devices; + snd_seq_t* const handle = iterateDevices (false, devices, deviceIndex); - if (handle != 0) - { - newDevice = new MidiOutput(); - newDevice->internal = new MidiOutputDevice (newDevice, handle); - } + if (handle != 0) + { + newDevice = new MidiOutput(); + newDevice->internal = new MidiOutputDevice (newDevice, handle); + } - return newDevice; + return newDevice; } MidiOutput* MidiOutput::createNewDevice (const String& deviceName) { - MidiOutput* newDevice = 0; + MidiOutput* newDevice = 0; - snd_seq_t* const handle = createDevice (false, deviceName); + snd_seq_t* const handle = createDevice (false, deviceName); - if (handle != 0) - { - newDevice = new MidiOutput(); - newDevice->internal = new MidiOutputDevice (newDevice, handle); - } + if (handle != 0) + { + newDevice = new MidiOutput(); + newDevice->internal = new MidiOutputDevice (newDevice, handle); + } - return newDevice; + return newDevice; } MidiOutput::~MidiOutput() { - MidiOutputDevice* const device = (MidiOutputDevice*) internal; - delete device; + MidiOutputDevice* const device = (MidiOutputDevice*) internal; + delete device; } void MidiOutput::reset() @@ -258867,7 +236497,7 @@ void MidiOutput::reset() bool MidiOutput::getVolume (float& leftVol, float& rightVol) { - return false; + return false; } void MidiOutput::setVolume (float leftVol, float rightVol) @@ -258876,176 +236506,176 @@ void MidiOutput::setVolume (float leftVol, float rightVol) void MidiOutput::sendMessageNow (const MidiMessage& message) { - ((MidiOutputDevice*) internal)->sendMessageNow (message); + ((MidiOutputDevice*) internal)->sendMessageNow (message); } class MidiInputThread : public Thread { public: - MidiInputThread (MidiInput* const midiInput_, - snd_seq_t* const seqHandle_, - MidiInputCallback* const callback_) - : Thread (T("Juce MIDI Input")), - midiInput (midiInput_), - seqHandle (seqHandle_), - callback (callback_) - { - jassert (seqHandle != 0 && callback != 0 && midiInput != 0); - } + MidiInputThread (MidiInput* const midiInput_, + snd_seq_t* const seqHandle_, + MidiInputCallback* const callback_) + : Thread (T("Juce MIDI Input")), + midiInput (midiInput_), + seqHandle (seqHandle_), + callback (callback_) + { + jassert (seqHandle != 0 && callback != 0 && midiInput != 0); + } - ~MidiInputThread() - { - snd_seq_close (seqHandle); - } + ~MidiInputThread() + { + snd_seq_close (seqHandle); + } - void run() - { - const int maxEventSize = 16 * 1024; - snd_midi_event_t* midiParser; + void run() + { + const int maxEventSize = 16 * 1024; + snd_midi_event_t* midiParser; - if (snd_midi_event_new (maxEventSize, &midiParser) >= 0) - { - HeapBlock buffer (maxEventSize); + if (snd_midi_event_new (maxEventSize, &midiParser) >= 0) + { + HeapBlock buffer (maxEventSize); - const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN); - struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd)); + const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN); + struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd)); - snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN); + snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN); - while (! threadShouldExit()) - { - if (poll (pfd, numPfds, 500) > 0) - { - snd_seq_event_t* inputEvent = 0; + while (! threadShouldExit()) + { + if (poll (pfd, numPfds, 500) > 0) + { + snd_seq_event_t* inputEvent = 0; - snd_seq_nonblock (seqHandle, 1); + snd_seq_nonblock (seqHandle, 1); - do - { - if (snd_seq_event_input (seqHandle, &inputEvent) >= 0) - { - // xxx what about SYSEXes that are too big for the buffer? - const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent); + do + { + if (snd_seq_event_input (seqHandle, &inputEvent) >= 0) + { + // xxx what about SYSEXes that are too big for the buffer? + const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent); - snd_midi_event_reset_decode (midiParser); + snd_midi_event_reset_decode (midiParser); - if (numBytes > 0) - { - const MidiMessage message ((const uint8*) buffer, - numBytes, - Time::getMillisecondCounter() * 0.001); + if (numBytes > 0) + { + const MidiMessage message ((const uint8*) buffer, + numBytes, + Time::getMillisecondCounter() * 0.001); - callback->handleIncomingMidiMessage (midiInput, message); - } + callback->handleIncomingMidiMessage (midiInput, message); + } - snd_seq_free_event (inputEvent); - } - } - while (snd_seq_event_input_pending (seqHandle, 0) > 0); + snd_seq_free_event (inputEvent); + } + } + while (snd_seq_event_input_pending (seqHandle, 0) > 0); - snd_seq_free_event (inputEvent); - } - } + snd_seq_free_event (inputEvent); + } + } - snd_midi_event_free (midiParser); - } - }; + snd_midi_event_free (midiParser); + } + }; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - MidiInput* const midiInput; - snd_seq_t* const seqHandle; - MidiInputCallback* const callback; + MidiInput* const midiInput; + snd_seq_t* const seqHandle; + MidiInputCallback* const callback; }; MidiInput::MidiInput (const String& name_) - : name (name_), - internal (0) + : name (name_), + internal (0) { } MidiInput::~MidiInput() { - stop(); - MidiInputThread* const thread = (MidiInputThread*) internal; - delete thread; + stop(); + MidiInputThread* const thread = (MidiInputThread*) internal; + delete thread; } void MidiInput::start() { - ((MidiInputThread*) internal)->startThread(); + ((MidiInputThread*) internal)->startThread(); } void MidiInput::stop() { - ((MidiInputThread*) internal)->stopThread (3000); + ((MidiInputThread*) internal)->stopThread (3000); } int MidiInput::getDefaultDeviceIndex() { - return 0; + return 0; } const StringArray MidiInput::getDevices() { - StringArray devices; - iterateDevices (true, devices, -1); - return devices; + StringArray devices; + iterateDevices (true, devices, -1); + return devices; } MidiInput* MidiInput::openDevice (int deviceIndex, MidiInputCallback* callback) { - MidiInput* newDevice = 0; + MidiInput* newDevice = 0; - StringArray devices; - snd_seq_t* const handle = iterateDevices (true, devices, deviceIndex); + StringArray devices; + snd_seq_t* const handle = iterateDevices (true, devices, deviceIndex); - if (handle != 0) - { - newDevice = new MidiInput (devices [deviceIndex]); - newDevice->internal = new MidiInputThread (newDevice, handle, callback); - } + if (handle != 0) + { + newDevice = new MidiInput (devices [deviceIndex]); + newDevice->internal = new MidiInputThread (newDevice, handle, callback); + } - return newDevice; + return newDevice; } MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallback* callback) { - MidiInput* newDevice = 0; + MidiInput* newDevice = 0; - snd_seq_t* const handle = createDevice (true, deviceName); + snd_seq_t* const handle = createDevice (true, deviceName); - if (handle != 0) - { - newDevice = new MidiInput (deviceName); - newDevice->internal = new MidiInputThread (newDevice, handle, callback); - } + if (handle != 0) + { + newDevice = new MidiInput (deviceName); + newDevice->internal = new MidiInputThread (newDevice, handle, callback); + } - return newDevice; + return newDevice; } #else // (These are just stub functions if ALSA is unavailable...) -const StringArray MidiOutput::getDevices() { return StringArray(); } -int MidiOutput::getDefaultDeviceIndex() { return 0; } -MidiOutput* MidiOutput::openDevice (int) { return 0; } -MidiOutput* MidiOutput::createNewDevice (const String&) { return 0; } +const StringArray MidiOutput::getDevices() { return StringArray(); } +int MidiOutput::getDefaultDeviceIndex() { return 0; } +MidiOutput* MidiOutput::openDevice (int) { return 0; } +MidiOutput* MidiOutput::createNewDevice (const String&) { return 0; } MidiOutput::~MidiOutput() {} -void MidiOutput::reset() {} -bool MidiOutput::getVolume (float&, float&) { return false; } -void MidiOutput::setVolume (float, float) {} -void MidiOutput::sendMessageNow (const MidiMessage&) {} +void MidiOutput::reset() {} +bool MidiOutput::getVolume (float&, float&) { return false; } +void MidiOutput::setVolume (float, float) {} +void MidiOutput::sendMessageNow (const MidiMessage&) {} MidiInput::MidiInput (const String& name_) : name (name_), internal (0) {} MidiInput::~MidiInput() {} void MidiInput::start() {} void MidiInput::stop() {} -int MidiInput::getDefaultDeviceIndex() { return 0; } +int MidiInput::getDefaultDeviceIndex() { return 0; } const StringArray MidiInput::getDevices() { return StringArray(); } -MidiInput* MidiInput::openDevice (int, MidiInputCallback*) { return 0; } +MidiInput* MidiInput::openDevice (int, MidiInputCallback*) { return 0; } MidiInput* MidiInput::createNewDevice (const String&, MidiInputCallback*) { return 0; } #endif @@ -259058,19 +236688,19 @@ MidiInput* MidiInput::createNewDevice (const String&, MidiInputCallback*) { re #if JUCE_INCLUDED_FILE && JUCE_USE_CDREADER AudioCDReader::AudioCDReader() - : AudioFormatReader (0, T("CD Audio")) + : AudioFormatReader (0, T("CD Audio")) { } const StringArray AudioCDReader::getAvailableCDNames() { - StringArray names; - return names; + StringArray names; + return names; } AudioCDReader* AudioCDReader::createReaderForCD (const int index) { - return 0; + return 0; } AudioCDReader::~AudioCDReader() @@ -259082,29 +236712,29 @@ void AudioCDReader::refreshTrackLengths() } bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples) + int64 startSampleInFile, int numSamples) { - return false; + return false; } bool AudioCDReader::isCDStillPresent() const { - return false; + return false; } int AudioCDReader::getNumTracks() const { - return 0; + return 0; } int AudioCDReader::getPositionOfTrackStart (int trackNum) const { - return 0; + return 0; } bool AudioCDReader::isTrackAudio (int trackNum) const { - return false; + return false; } void AudioCDReader::enableIndexScanning (bool b) @@ -259113,17 +236743,17 @@ void AudioCDReader::enableIndexScanning (bool b) int AudioCDReader::getLastIndex() const { - return 0; + return 0; } const Array AudioCDReader::findIndexesInTrack (const int trackNumber) { - return Array(); + return Array(); } int AudioCDReader::getCDDBId() { - return 0; + return 0; } #endif @@ -259135,74 +236765,74 @@ int AudioCDReader::getCDDBId() #if JUCE_INCLUDED_FILE void FileChooser::showPlatformDialog (OwnedArray& results, - const String& title, - const File& file, - const String& filters, - bool isDirectory, - bool selectsFiles, - bool isSave, - bool warnAboutOverwritingExistingFiles, - bool selectMultipleFiles, - FilePreviewComponent* previewComponent) + const String& title, + const File& file, + const String& filters, + bool isDirectory, + bool selectsFiles, + bool isSave, + bool warnAboutOverwritingExistingFiles, + bool selectMultipleFiles, + FilePreviewComponent* previewComponent) { - const tchar* const separator = T(":"); - String command ("zenity --file-selection"); + const tchar* const separator = T(":"); + String command ("zenity --file-selection"); - if (title.isNotEmpty()) - command << " --title=\"" << title << "\""; + if (title.isNotEmpty()) + command << " --title=\"" << title << "\""; - if (file != File::nonexistent) - command << " --filename=\"" << file.getFullPathName () << "\""; + if (file != File::nonexistent) + command << " --filename=\"" << file.getFullPathName () << "\""; - if (isDirectory) - command << " --directory"; + if (isDirectory) + command << " --directory"; - if (isSave) - command << " --save"; + if (isSave) + command << " --save"; - if (selectMultipleFiles) - command << " --multiple --separator=\"" << separator << "\""; + if (selectMultipleFiles) + command << " --multiple --separator=\"" << separator << "\""; - command << " 2>&1"; + command << " 2>&1"; - MemoryOutputStream result; - int status = -1; - FILE* stream = popen ((const char*) command.toUTF8(), "r"); + MemoryOutputStream result; + int status = -1; + FILE* stream = popen ((const char*) command.toUTF8(), "r"); - if (stream != 0) - { - for (;;) - { - char buffer [1024]; - const int bytesRead = fread (buffer, 1, sizeof (buffer), stream); + if (stream != 0) + { + for (;;) + { + char buffer [1024]; + const int bytesRead = fread (buffer, 1, sizeof (buffer), stream); - if (bytesRead <= 0) - break; + if (bytesRead <= 0) + break; - result.write (buffer, bytesRead); - } + result.write (buffer, bytesRead); + } - status = pclose (stream); - } + status = pclose (stream); + } - if (status == 0) - { - String resultString (String::fromUTF8 ((const uint8*) result.getData(), result.getDataSize())); - StringArray tokens; + if (status == 0) + { + String resultString (String::fromUTF8 ((const uint8*) result.getData(), result.getDataSize())); + StringArray tokens; - if (selectMultipleFiles) - tokens.addTokens (resultString, separator, 0); - else - tokens.add (resultString); + if (selectMultipleFiles) + tokens.addTokens (resultString, separator, 0); + else + tokens.add (resultString); - for (int i = 0; i < tokens.size(); i++) - results.add (new File (tokens[i])); + for (int i = 0; i < tokens.size(); i++) + results.add (new File (tokens[i])); - return; - } + return; + } - //xxx ain't got one! - jassertfalse + //xxx ain't got one! + jassertfalse } #endif @@ -259213,16 +236843,12 @@ void FileChooser::showPlatformDialog (OwnedArray& results, // compiled on its own). #if JUCE_INCLUDED_FILE && JUCE_WEB_BROWSER -/* - Sorry.. This class isn't implemented on Linux! -*/ - WebBrowserComponent::WebBrowserComponent (const bool unloadPageWhenBrowserIsHidden_) - : browser (0), - blankPageShown (false), - unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_) + : browser (0), + blankPageShown (false), + unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_) { - setOpaque (true); + setOpaque (true); } WebBrowserComponent::~WebBrowserComponent() @@ -259230,20 +236856,20 @@ WebBrowserComponent::~WebBrowserComponent() } void WebBrowserComponent::goToURL (const String& url, - const StringArray* headers, - const MemoryBlock* postData) + const StringArray* headers, + const MemoryBlock* postData) { - lastURL = url; + lastURL = url; - lastHeaders.clear(); - if (headers != 0) - lastHeaders = *headers; + lastHeaders.clear(); + if (headers != 0) + lastHeaders = *headers; - lastPostData.setSize (0); - if (postData != 0) - lastPostData = *postData; + lastPostData.setSize (0); + if (postData != 0) + lastPostData = *postData; - blankPageShown = false; + blankPageShown = false; } @@ -259253,14 +236879,14 @@ void WebBrowserComponent::stop() void WebBrowserComponent::goBack() { - lastURL = String::empty; - blankPageShown = false; + lastURL = String::empty; + blankPageShown = false; } void WebBrowserComponent::goForward() { - lastURL = String::empty; + lastURL = String::empty; } @@ -259270,7 +236896,7 @@ void WebBrowserComponent::refresh() void WebBrowserComponent::paint (Graphics& g) { - g.fillAll (Colours::white); + g.fillAll (Colours::white); } void WebBrowserComponent::checkWindowAssociation() @@ -259279,16 +236905,16 @@ void WebBrowserComponent::checkWindowAssociation() void WebBrowserComponent::reloadLastURL() { - if (lastURL.isNotEmpty()) - { - goToURL (lastURL, &lastHeaders, &lastPostData); - lastURL = String::empty; - } + if (lastURL.isNotEmpty()) + { + goToURL (lastURL, &lastHeaders, &lastPostData); + lastURL = String::empty; + } } void WebBrowserComponent::parentHierarchyChanged() { - checkWindowAssociation(); + checkWindowAssociation(); } void WebBrowserComponent::resized() @@ -259297,12 +236923,12 @@ void WebBrowserComponent::resized() void WebBrowserComponent::visibilityChanged() { - checkWindowAssociation(); + checkWindowAssociation(); } bool WebBrowserComponent::pageAboutToLoad (const String& url) { - return true; + return true; } #endif @@ -259318,12 +236944,6 @@ END_JUCE_NAMESPACE #if JUCE_MAC || JUCE_IPHONE /********* Start of inlined file: juce_mac_NativeCode.mm *********/ -/* - This file wraps together all the mac-specific code, so that - we can include all the native headers just once, and compile all our - platform-specific stuff in one big lump, keeping it out of the way of - the rest of the codebase. -*/ BEGIN_JUCE_NAMESPACE @@ -259334,19 +236954,6 @@ BEGIN_JUCE_NAMESPACE // Now include the actual code files.. /********* Start of inlined file: juce_mac_ObjCSuffix.h *********/ -/** This suffix is used for naming all Obj-C classes that are used inside juce. - - Because of the flat naming structure used by Obj-C, you can get horrible situations where - two DLLs are loaded into a host, each of which uses classes with the same names, and these get - cross-linked so that when you make a call to a class that you thought was private, it ends up - actually calling into a similarly named class in the other module's address space. - - By changing this macro to a unique value, you ensure that all the obj-C classes in your app - have unique names, and should avoid this problem. - - If you're using the amalgamated version, you can just set this macro to something unique before - you include juce_amalgamated.cpp. -*/ #ifndef JUCE_ObjCExtraSuffix #define JUCE_ObjCExtraSuffix 3 #endif @@ -259363,123 +236970,123 @@ BEGIN_JUCE_NAMESPACE static const String nsStringToJuce (NSString* s) { - return String::fromUTF8 ((uint8*) [s UTF8String]); + return String::fromUTF8 ((uint8*) [s UTF8String]); } static NSString* juceStringToNS (const String& s) { - return [NSString stringWithUTF8String: (const char*) s.toUTF8()]; + return [NSString stringWithUTF8String: (const char*) s.toUTF8()]; } static const String convertUTF16ToString (const UniChar* utf16) { - String s; + String s; - while (*utf16 != 0) - s += (juce_wchar) *utf16++; + while (*utf16 != 0) + s += (juce_wchar) *utf16++; - return s; + return s; } const String PlatformUtilities::cfStringToJuceString (CFStringRef cfString) { - String result; + String result; - if (cfString != 0) - { + if (cfString != 0) + { #if JUCE_STRINGS_ARE_UNICODE - CFRange range = { 0, CFStringGetLength (cfString) }; - HeapBlock u (range.length + 1); - CFStringGetCharacters (cfString, range, u); - u[range.length] = 0; - result = convertUTF16ToString (u); + CFRange range = { 0, CFStringGetLength (cfString) }; + HeapBlock u (range.length + 1); + CFStringGetCharacters (cfString, range, u); + u[range.length] = 0; + result = convertUTF16ToString (u); #else - const int len = CFStringGetLength (cfString); - HeapBlock buffer (len + 1); - CFStringGetCString (cfString, buffer, len + 1, CFStringGetSystemEncoding()); - result = buffer; + const int len = CFStringGetLength (cfString); + HeapBlock buffer (len + 1); + CFStringGetCString (cfString, buffer, len + 1, CFStringGetSystemEncoding()); + result = buffer; #endif - } + } - return result; + return result; } CFStringRef PlatformUtilities::juceStringToCFString (const String& s) { #if JUCE_STRINGS_ARE_UNICODE - const int len = s.length(); - const juce_wchar* t = (const juce_wchar*) s; - HeapBlock temp (len + 2); + const int len = s.length(); + const juce_wchar* t = (const juce_wchar*) s; + HeapBlock temp (len + 2); - for (int i = 0; i <= len; ++i) - temp[i] = t[i]; + for (int i = 0; i <= len; ++i) + temp[i] = t[i]; - return CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len); + return CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len); #else - return CFStringCreateWithCString (kCFAllocatorDefault, - (const char*) s, - CFStringGetSystemEncoding()); + return CFStringCreateWithCString (kCFAllocatorDefault, + (const char*) s, + CFStringGetSystemEncoding()); #endif } const String PlatformUtilities::convertToPrecomposedUnicode (const String& s) { #if JUCE_IPHONE - const ScopedAutoReleasePool pool; - return nsStringToJuce ([juceStringToNS (s) precomposedStringWithCanonicalMapping]); + const ScopedAutoReleasePool pool; + return nsStringToJuce ([juceStringToNS (s) precomposedStringWithCanonicalMapping]); #else - UnicodeMapping map; + UnicodeMapping map; - map.unicodeEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault, - kUnicodeNoSubset, - kTextEncodingDefaultFormat); + map.unicodeEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault, + kUnicodeNoSubset, + kTextEncodingDefaultFormat); - map.otherEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault, - kUnicodeCanonicalCompVariant, - kTextEncodingDefaultFormat); + map.otherEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault, + kUnicodeCanonicalCompVariant, + kTextEncodingDefaultFormat); - map.mappingVersion = kUnicodeUseLatestMapping; + map.mappingVersion = kUnicodeUseLatestMapping; - UnicodeToTextInfo conversionInfo = 0; - String result; + UnicodeToTextInfo conversionInfo = 0; + String result; - if (CreateUnicodeToTextInfo (&map, &conversionInfo) == noErr) - { - const int len = s.length(); + if (CreateUnicodeToTextInfo (&map, &conversionInfo) == noErr) + { + const int len = s.length(); - HeapBlock tempIn, tempOut; - tempIn.calloc (len + 2); - tempOut.calloc (len + 2); + HeapBlock tempIn, tempOut; + tempIn.calloc (len + 2); + tempOut.calloc (len + 2); - for (int i = 0; i <= len; ++i) - tempIn[i] = s[i]; + for (int i = 0; i <= len; ++i) + tempIn[i] = s[i]; - ByteCount bytesRead = 0; - ByteCount outputBufferSize = 0; + ByteCount bytesRead = 0; + ByteCount outputBufferSize = 0; - if (ConvertFromUnicodeToText (conversionInfo, - len * sizeof (UniChar), tempIn, - kUnicodeDefaultDirectionMask, - 0, 0, 0, 0, - len * sizeof (UniChar), &bytesRead, - &outputBufferSize, tempOut) == noErr) - { - result.preallocateStorage (bytesRead / sizeof (UniChar) + 2); + if (ConvertFromUnicodeToText (conversionInfo, + len * sizeof (UniChar), tempIn, + kUnicodeDefaultDirectionMask, + 0, 0, 0, 0, + len * sizeof (UniChar), &bytesRead, + &outputBufferSize, tempOut) == noErr) + { + result.preallocateStorage (bytesRead / sizeof (UniChar) + 2); - tchar* t = const_cast ((const tchar*) result); + tchar* t = const_cast ((const tchar*) result); - unsigned int i; - for (i = 0; i < bytesRead / sizeof (UniChar); ++i) - t[i] = (tchar) tempOut[i]; + unsigned int i; + for (i = 0; i < bytesRead / sizeof (UniChar); ++i) + t[i] = (tchar) tempOut[i]; - t[i] = 0; - } + t[i] = 0; + } - DisposeUnicodeToTextInfo (&conversionInfo); - } + DisposeUnicodeToTextInfo (&conversionInfo); + } - return result; + return result; #endif } @@ -259488,27 +237095,27 @@ const String PlatformUtilities::convertToPrecomposedUnicode (const String& s) void SystemClipboard::copyTextToClipboard (const String& text) throw() { #if JUCE_IPHONE - [[UIPasteboard generalPasteboard] setValue: juceStringToNS (text) - forPasteboardType: @"public.text"]; + [[UIPasteboard generalPasteboard] setValue: juceStringToNS (text) + forPasteboardType: @"public.text"]; #else - [[NSPasteboard generalPasteboard] declareTypes: [NSArray arrayWithObject: NSStringPboardType] - owner: nil]; + [[NSPasteboard generalPasteboard] declareTypes: [NSArray arrayWithObject: NSStringPboardType] + owner: nil]; - [[NSPasteboard generalPasteboard] setString: juceStringToNS (text) - forType: NSStringPboardType]; + [[NSPasteboard generalPasteboard] setString: juceStringToNS (text) + forType: NSStringPboardType]; #endif } const String SystemClipboard::getTextFromClipboard() throw() { #if JUCE_IPHONE - NSString* text = [[UIPasteboard generalPasteboard] valueForPasteboardType: @"public.text"]; + NSString* text = [[UIPasteboard generalPasteboard] valueForPasteboardType: @"public.text"]; #else - NSString* text = [[NSPasteboard generalPasteboard] stringForType: NSStringPboardType]; + NSString* text = [[NSPasteboard generalPasteboard] stringForType: NSStringPboardType]; #endif - return text == 0 ? String::empty - : nsStringToJuce (text); + return text == 0 ? String::empty + : nsStringToJuce (text); } #endif @@ -259528,41 +237135,41 @@ static double highResTimerToMillisecRatio = 0; static void juce_getCpuVendor (char* const v) throw() { - int vendor[4]; - zerostruct (vendor); - int dummy = 0; + int vendor[4]; + zerostruct (vendor); + int dummy = 0; - asm ("mov %%ebx, %%esi \n\t" - "cpuid \n\t" - "xchg %%esi, %%ebx" - : "=a" (dummy), "=S" (vendor[0]), "=c" (vendor[2]), "=d" (vendor[1]) : "a" (0)); + asm ("mov %%ebx, %%esi \n\t" + "cpuid \n\t" + "xchg %%esi, %%ebx" + : "=a" (dummy), "=S" (vendor[0]), "=c" (vendor[2]), "=d" (vendor[1]) : "a" (0)); - memcpy (v, vendor, 16); + memcpy (v, vendor, 16); } static unsigned int getCPUIDWord (unsigned int& familyModel, unsigned int& extFeatures) { - unsigned int cpu = 0; - unsigned int ext = 0; - unsigned int family = 0; - unsigned int dummy = 0; + unsigned int cpu = 0; + unsigned int ext = 0; + unsigned int family = 0; + unsigned int dummy = 0; - asm ("mov %%ebx, %%esi \n\t" - "cpuid \n\t" - "xchg %%esi, %%ebx" - : "=a" (family), "=S" (ext), "=c" (dummy), "=d" (cpu) : "a" (1)); + asm ("mov %%ebx, %%esi \n\t" + "cpuid \n\t" + "xchg %%esi, %%ebx" + : "=a" (family), "=S" (ext), "=c" (dummy), "=d" (cpu) : "a" (1)); - familyModel = family; - extFeatures = ext; - return cpu; + familyModel = family; + extFeatures = ext; + return cpu; } struct CPUFlags { - bool hasMMX : 1; - bool hasSSE : 1; - bool hasSSE2 : 1; - bool has3DNow : 1; + bool hasMMX : 1; + bool hasSSE : 1; + bool hasSSE2 : 1; + bool has3DNow : 1; }; static CPUFlags cpuFlags; @@ -259571,179 +237178,179 @@ static CPUFlags cpuFlags; void SystemStats::initialiseStats() throw() { - static bool initialised = false; + static bool initialised = false; - if (! initialised) - { - initialised = true; + if (! initialised) + { + initialised = true; #if JUCE_MAC - // extremely annoying: adding this line stops the apple menu items from working. Of - // course, not adding it means that carbon windows (e.g. in plugins) won't get - // any events. - //NSApplicationLoad(); - [NSApplication sharedApplication]; + // extremely annoying: adding this line stops the apple menu items from working. Of + // course, not adding it means that carbon windows (e.g. in plugins) won't get + // any events. + //NSApplicationLoad(); + [NSApplication sharedApplication]; #endif #if JUCE_INTEL - { - unsigned int familyModel, extFeatures; - const unsigned int features = getCPUIDWord (familyModel, extFeatures); + { + unsigned int familyModel, extFeatures; + const unsigned int features = getCPUIDWord (familyModel, extFeatures); - cpuFlags.hasMMX = ((features & (1 << 23)) != 0); - cpuFlags.hasSSE = ((features & (1 << 25)) != 0); - cpuFlags.hasSSE2 = ((features & (1 << 26)) != 0); - cpuFlags.has3DNow = ((extFeatures & (1 << 31)) != 0); - } + cpuFlags.hasMMX = ((features & (1 << 23)) != 0); + cpuFlags.hasSSE = ((features & (1 << 25)) != 0); + cpuFlags.hasSSE2 = ((features & (1 << 26)) != 0); + cpuFlags.has3DNow = ((extFeatures & (1 << 31)) != 0); + } #endif - mach_timebase_info_data_t timebase; - (void) mach_timebase_info (&timebase); - highResTimerFrequency = (int64) (1.0e9 * timebase.denom / timebase.numer); - highResTimerToMillisecRatio = timebase.numer / (1.0e6 * timebase.denom); + mach_timebase_info_data_t timebase; + (void) mach_timebase_info (&timebase); + highResTimerFrequency = (int64) (1.0e9 * timebase.denom / timebase.numer); + highResTimerToMillisecRatio = timebase.numer / (1.0e6 * timebase.denom); - String s (SystemStats::getJUCEVersion()); + String s (SystemStats::getJUCEVersion()); - rlimit lim; - getrlimit (RLIMIT_NOFILE, &lim); - lim.rlim_cur = lim.rlim_max = RLIM_INFINITY; - setrlimit (RLIMIT_NOFILE, &lim); - } + rlimit lim; + getrlimit (RLIMIT_NOFILE, &lim); + lim.rlim_cur = lim.rlim_max = RLIM_INFINITY; + setrlimit (RLIMIT_NOFILE, &lim); + } } SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() throw() { - return MacOSX; + return MacOSX; } const String SystemStats::getOperatingSystemName() throw() { - return T("Mac OS X"); + return T("Mac OS X"); } bool SystemStats::isOperatingSystem64Bit() throw() { #if JUCE_64BIT - return true; + return true; #else - //xxx not sure how to find this out?.. - return false; + //xxx not sure how to find this out?.. + return false; #endif } int SystemStats::getMemorySizeInMegabytes() throw() { - uint64 mem = 0; - size_t memSize = sizeof (mem); - int mib[] = { CTL_HW, HW_MEMSIZE }; - sysctl (mib, 2, &mem, &memSize, 0, 0); - return (int) (mem / (1024 * 1024)); + uint64 mem = 0; + size_t memSize = sizeof (mem); + int mib[] = { CTL_HW, HW_MEMSIZE }; + sysctl (mib, 2, &mem, &memSize, 0, 0); + return (int) (mem / (1024 * 1024)); } bool SystemStats::hasMMX() throw() { #if JUCE_INTEL - return cpuFlags.hasMMX; + return cpuFlags.hasMMX; #else - return false; + return false; #endif } bool SystemStats::hasSSE() throw() { #if JUCE_INTEL - return cpuFlags.hasSSE; + return cpuFlags.hasSSE; #else - return false; + return false; #endif } bool SystemStats::hasSSE2() throw() { #if JUCE_INTEL - return cpuFlags.hasSSE2; + return cpuFlags.hasSSE2; #else - return false; + return false; #endif } bool SystemStats::has3DNow() throw() { #if JUCE_INTEL - return cpuFlags.has3DNow; + return cpuFlags.has3DNow; #else - return false; + return false; #endif } const String SystemStats::getCpuVendor() throw() { #if JUCE_INTEL - char v [16]; - juce_getCpuVendor (v); - return String (v, 16); + char v [16]; + juce_getCpuVendor (v); + return String (v, 16); #else - return String::empty; + return String::empty; #endif } int SystemStats::getCpuSpeedInMegaherz() throw() { - uint64 speedHz = 0; - size_t speedSize = sizeof (speedHz); - int mib[] = { CTL_HW, HW_CPU_FREQ }; - sysctl (mib, 2, &speedHz, &speedSize, 0, 0); + uint64 speedHz = 0; + size_t speedSize = sizeof (speedHz); + int mib[] = { CTL_HW, HW_CPU_FREQ }; + sysctl (mib, 2, &speedHz, &speedSize, 0, 0); #if JUCE_BIG_ENDIAN - if (speedSize == 4) - speedHz >>= 32; + if (speedSize == 4) + speedHz >>= 32; #endif - return (int) (speedHz / 1000000); + return (int) (speedHz / 1000000); } int SystemStats::getNumCpus() throw() { #if JUCE_IPHONE || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) - return [[NSProcessInfo processInfo] activeProcessorCount]; + return (int) [[NSProcessInfo processInfo] activeProcessorCount]; #else - return MPProcessors(); + return MPProcessors(); #endif } uint32 juce_millisecondsSinceStartup() throw() { - return (uint32) (mach_absolute_time() * highResTimerToMillisecRatio); + return (uint32) (mach_absolute_time() * highResTimerToMillisecRatio); } double Time::getMillisecondCounterHiRes() throw() { - return mach_absolute_time() * highResTimerToMillisecRatio; + return mach_absolute_time() * highResTimerToMillisecRatio; } int64 Time::getHighResolutionTicks() throw() { - return (int64) mach_absolute_time(); + return (int64) mach_absolute_time(); } int64 Time::getHighResolutionTicksPerSecond() throw() { - return highResTimerFrequency; + return highResTimerFrequency; } int64 SystemStats::getClockCycleCounter() throw() { - return (int64) mach_absolute_time(); + return (int64) mach_absolute_time(); } bool Time::setSystemTimeToThisTime() const throw() { - jassertfalse - return false; + jassertfalse + return false; } int SystemStats::getPageSize() throw() { - return NSPageSize(); + return (int) NSPageSize(); } void PlatformUtilities::fpuReset() @@ -259760,90 +237367,90 @@ void PlatformUtilities::fpuReset() int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw() { - #ifndef IFT_ETHER - #define IFT_ETHER 6 - #endif + #ifndef IFT_ETHER + #define IFT_ETHER 6 + #endif - ifaddrs* addrs = 0; - int numResults = 0; + ifaddrs* addrs = 0; + int numResults = 0; - if (getifaddrs (&addrs) == 0) - { - const ifaddrs* cursor = addrs; + if (getifaddrs (&addrs) == 0) + { + const ifaddrs* cursor = addrs; - while (cursor != 0 && numResults < maxNum) - { - if (cursor->ifa_addr->sa_family == AF_LINK) - { - const sockaddr_dl* const sadd = (const sockaddr_dl*) cursor->ifa_addr; + while (cursor != 0 && numResults < maxNum) + { + if (cursor->ifa_addr->sa_family == AF_LINK) + { + const sockaddr_dl* const sadd = (const sockaddr_dl*) cursor->ifa_addr; - if (sadd->sdl_type == IFT_ETHER) - { - const uint8* const addr = ((const uint8*) sadd->sdl_data) + sadd->sdl_nlen; + if (sadd->sdl_type == IFT_ETHER) + { + const uint8* const addr = ((const uint8*) sadd->sdl_data) + sadd->sdl_nlen; - uint64 a = 0; - for (int i = 6; --i >= 0;) - a = (a << 8) | addr [littleEndian ? i : (5 - i)]; + uint64 a = 0; + for (int i = 6; --i >= 0;) + a = (a << 8) | addr [littleEndian ? i : (5 - i)]; - *addresses++ = (int64) a; - ++numResults; - } - } + *addresses++ = (int64) a; + ++numResults; + } + } - cursor = cursor->ifa_next; - } + cursor = cursor->ifa_next; + } - freeifaddrs (addrs); - } + freeifaddrs (addrs); + } - return numResults; + return numResults; } bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress, - const String& emailSubject, - const String& bodyText, - const StringArray& filesToAttach) + const String& emailSubject, + const String& bodyText, + const StringArray& filesToAttach) { #if JUCE_IPHONE - //xxx probably need to use MFMailComposeViewController - jassertfalse - return false; + //xxx probably need to use MFMailComposeViewController + jassertfalse + return false; #else - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - String script; - script << "tell application \"Mail\"\r\n" - "set newMessage to make new outgoing message with properties {subject:\"" - << emailSubject.replace (T("\""), T("\\\"")) - << "\", content:\"" - << bodyText.replace (T("\""), T("\\\"")) - << "\" & return & return}\r\n" - "tell newMessage\r\n" - "set visible to true\r\n" - "set sender to \"sdfsdfsdfewf\"\r\n" - "make new to recipient at end of to recipients with properties {address:\"" - << targetEmailAddress - << "\"}\r\n"; + String script; + script << "tell application \"Mail\"\r\n" + "set newMessage to make new outgoing message with properties {subject:\"" + << emailSubject.replace (T("\""), T("\\\"")) + << "\", content:\"" + << bodyText.replace (T("\""), T("\\\"")) + << "\" & return & return}\r\n" + "tell newMessage\r\n" + "set visible to true\r\n" + "set sender to \"sdfsdfsdfewf\"\r\n" + "make new to recipient at end of to recipients with properties {address:\"" + << targetEmailAddress + << "\"}\r\n"; - for (int i = 0; i < filesToAttach.size(); ++i) - { - script << "tell content\r\n" - "make new attachment with properties {file name:\"" - << filesToAttach[i].replace (T("\""), T("\\\"")) - << "\"} at after the last paragraph\r\n" - "end tell\r\n"; - } + for (int i = 0; i < filesToAttach.size(); ++i) + { + script << "tell content\r\n" + "make new attachment with properties {file name:\"" + << filesToAttach[i].replace (T("\""), T("\\\"")) + << "\"} at after the last paragraph\r\n" + "end tell\r\n"; + } - script << "end tell\r\n" - "end tell\r\n"; + script << "end tell\r\n" + "end tell\r\n"; - NSAppleScript* s = [[NSAppleScript alloc] - initWithSource: juceStringToNS (script)]; - NSDictionary* error = 0; - const bool ok = [s executeAndReturnError: &error] != nil; - [s release]; + NSAppleScript* s = [[NSAppleScript alloc] + initWithSource: juceStringToNS (script)]; + NSDictionary* error = 0; + const bool ok = [s executeAndReturnError: &error] != nil; + [s release]; - return ok; + return ok; #endif } @@ -259856,14 +237463,14 @@ using namespace JUCE_NAMESPACE; @interface JuceURLConnection : NSObject { @public - NSURLRequest* request; - NSURLConnection* connection; - NSMutableData* data; - Thread* runLoopThread; - bool initialised, hasFailed, hasFinished; - int position; - int64 contentLength; - NSLock* dataLock; + NSURLRequest* request; + NSURLConnection* connection; + NSMutableData* data; + Thread* runLoopThread; + bool initialised, hasFailed, hasFinished; + int position; + int64 contentLength; + NSLock* dataLock; } - (JuceURLConnection*) initWithRequest: (NSURLRequest*) req withCallback: (URL::OpenStreamProgressCallback*) callback withContext: (void*) context; @@ -259883,162 +237490,162 @@ using namespace JUCE_NAMESPACE; class JuceURLConnectionMessageThread : public Thread { - JuceURLConnection* owner; + JuceURLConnection* owner; public: - JuceURLConnectionMessageThread (JuceURLConnection* owner_) - : Thread (T("http connection")), - owner (owner_) - { - } + JuceURLConnectionMessageThread (JuceURLConnection* owner_) + : Thread (T("http connection")), + owner (owner_) + { + } - ~JuceURLConnectionMessageThread() - { - stopThread (10000); - } + ~JuceURLConnectionMessageThread() + { + stopThread (10000); + } - void run() - { - [owner createConnection]; + void run() + { + [owner createConnection]; - while (! threadShouldExit()) - { - const ScopedAutoReleasePool pool; - [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; - } - } + while (! threadShouldExit()) + { + const ScopedAutoReleasePool pool; + [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; + } + } }; @implementation JuceURLConnection - (JuceURLConnection*) initWithRequest: (NSURLRequest*) req - withCallback: (URL::OpenStreamProgressCallback*) callback - withContext: (void*) context; + withCallback: (URL::OpenStreamProgressCallback*) callback + withContext: (void*) context; { - [super init]; - request = req; - [request retain]; - data = [[NSMutableData data] retain]; - dataLock = [[NSLock alloc] init]; - connection = 0; - initialised = false; - hasFailed = false; - hasFinished = false; - contentLength = -1; + [super init]; + request = req; + [request retain]; + data = [[NSMutableData data] retain]; + dataLock = [[NSLock alloc] init]; + connection = 0; + initialised = false; + hasFailed = false; + hasFinished = false; + contentLength = -1; - runLoopThread = new JuceURLConnectionMessageThread (self); - runLoopThread->startThread(); + runLoopThread = new JuceURLConnectionMessageThread (self); + runLoopThread->startThread(); - while (runLoopThread->isThreadRunning() && ! initialised) - { - if (callback != 0) - callback (context, -1, [[request HTTPBody] length]); + while (runLoopThread->isThreadRunning() && ! initialised) + { + if (callback != 0) + callback (context, -1, (int) [[request HTTPBody] length]); - Thread::sleep (1); - } + Thread::sleep (1); + } - return self; + return self; } - (void) dealloc { - [self stop]; + [self stop]; - delete runLoopThread; - [connection release]; - [data release]; - [dataLock release]; - [request release]; - [super dealloc]; + delete runLoopThread; + [connection release]; + [data release]; + [dataLock release]; + [request release]; + [super dealloc]; } - (void) createConnection { - connection = [[NSURLConnection alloc] initWithRequest: request - delegate: [self retain]]; + connection = [[NSURLConnection alloc] initWithRequest: request + delegate: [self retain]]; - if (connection == nil) - runLoopThread->signalThreadShouldExit(); + if (connection == nil) + runLoopThread->signalThreadShouldExit(); } - (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response { - [dataLock lock]; - [data setLength: 0]; - [dataLock unlock]; - initialised = true; - contentLength = [response expectedContentLength]; + [dataLock lock]; + [data setLength: 0]; + [dataLock unlock]; + initialised = true; + contentLength = [response expectedContentLength]; } - (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error { - DBG (nsStringToJuce ([error description])); - hasFailed = true; - initialised = true; - runLoopThread->signalThreadShouldExit(); + DBG (nsStringToJuce ([error description])); + hasFailed = true; + initialised = true; + runLoopThread->signalThreadShouldExit(); } - (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) newData { - [dataLock lock]; - [data appendData: newData]; - [dataLock unlock]; - initialised = true; + [dataLock lock]; + [data appendData: newData]; + [dataLock unlock]; + initialised = true; } - (void) connectionDidFinishLoading: (NSURLConnection*) connection { - hasFinished = true; - initialised = true; - runLoopThread->signalThreadShouldExit(); + hasFinished = true; + initialised = true; + runLoopThread->signalThreadShouldExit(); } - (BOOL) isOpen { - return connection != 0 && ! hasFailed; + return connection != 0 && ! hasFailed; } - (int) readPosition { - return position; + return position; } - (int) read: (char*) dest numBytes: (int) numNeeded { - int numDone = 0; + int numDone = 0; - while (numNeeded > 0) - { - int available = jmin (numNeeded, [data length]); + while (numNeeded > 0) + { + int available = jmin (numNeeded, (int) [data length]); - if (available > 0) - { - [dataLock lock]; - [data getBytes: dest length: available]; - [data replaceBytesInRange: NSMakeRange (0, available) withBytes: nil length: 0]; - [dataLock unlock]; + if (available > 0) + { + [dataLock lock]; + [data getBytes: dest length: available]; + [data replaceBytesInRange: NSMakeRange (0, available) withBytes: nil length: 0]; + [dataLock unlock]; - numDone += available; - numNeeded -= available; - dest += available; - } - else - { - if (hasFailed || hasFinished) - break; + numDone += available; + numNeeded -= available; + dest += available; + } + else + { + if (hasFailed || hasFinished) + break; - Thread::sleep (1); - } - } + Thread::sleep (1); + } + } - position += numDone; - return numDone; + position += numDone; + return numDone; } - (void) stop { - [connection cancel]; - runLoopThread->stopThread (10000); + [connection cancel]; + runLoopThread->stopThread (10000); } @end @@ -260046,103 +237653,103 @@ BEGIN_JUCE_NAMESPACE bool juce_isOnLine() { - return true; + return true; } void* juce_openInternetFile (const String& url, - const String& headers, - const MemoryBlock& postData, - const bool isPost, - URL::OpenStreamProgressCallback* callback, - void* callbackContext, - int timeOutMs) + const String& headers, + const MemoryBlock& postData, + const bool isPost, + URL::OpenStreamProgressCallback* callback, + void* callbackContext, + int timeOutMs) { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - NSMutableURLRequest* req = [NSMutableURLRequest - requestWithURL: [NSURL URLWithString: juceStringToNS (url)] - cachePolicy: NSURLRequestUseProtocolCachePolicy - timeoutInterval: timeOutMs <= 0 ? 60.0 : (timeOutMs / 1000.0)]; + NSMutableURLRequest* req = [NSMutableURLRequest + requestWithURL: [NSURL URLWithString: juceStringToNS (url)] + cachePolicy: NSURLRequestUseProtocolCachePolicy + timeoutInterval: timeOutMs <= 0 ? 60.0 : (timeOutMs / 1000.0)]; - if (req == nil) - return 0; + if (req == nil) + return 0; - [req setHTTPMethod: isPost ? @"POST" : @"GET"]; - //[req setCachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData]; + [req setHTTPMethod: isPost ? @"POST" : @"GET"]; + //[req setCachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData]; - StringArray headerLines; - headerLines.addLines (headers); - headerLines.removeEmptyStrings (true); + StringArray headerLines; + headerLines.addLines (headers); + headerLines.removeEmptyStrings (true); - for (int i = 0; i < headerLines.size(); ++i) - { - const String key (headerLines[i].upToFirstOccurrenceOf (T(":"), false, false).trim()); - const String value (headerLines[i].fromFirstOccurrenceOf (T(":"), false, false).trim()); + for (int i = 0; i < headerLines.size(); ++i) + { + const String key (headerLines[i].upToFirstOccurrenceOf (T(":"), false, false).trim()); + const String value (headerLines[i].fromFirstOccurrenceOf (T(":"), false, false).trim()); - if (key.isNotEmpty() && value.isNotEmpty()) - [req addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)]; - } + if (key.isNotEmpty() && value.isNotEmpty()) + [req addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)]; + } - if (isPost && postData.getSize() > 0) - { - [req setHTTPBody: [NSData dataWithBytes: postData.getData() - length: postData.getSize()]]; - } + if (isPost && postData.getSize() > 0) + { + [req setHTTPBody: [NSData dataWithBytes: postData.getData() + length: postData.getSize()]]; + } - JuceURLConnection* const s = [[JuceURLConnection alloc] initWithRequest: req - withCallback: callback - withContext: callbackContext]; + JuceURLConnection* const s = [[JuceURLConnection alloc] initWithRequest: req + withCallback: callback + withContext: callbackContext]; - if ([s isOpen]) - return s; + if ([s isOpen]) + return s; - [s release]; - return 0; + [s release]; + return 0; } void juce_closeInternetFile (void* handle) { - JuceURLConnection* const s = (JuceURLConnection*) handle; + JuceURLConnection* const s = (JuceURLConnection*) handle; - if (s != 0) - { - const ScopedAutoReleasePool pool; - [s stop]; - [s release]; - } + if (s != 0) + { + const ScopedAutoReleasePool pool; + [s stop]; + [s release]; + } } int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead) { - JuceURLConnection* const s = (JuceURLConnection*) handle; + JuceURLConnection* const s = (JuceURLConnection*) handle; - if (s != 0) - { - const ScopedAutoReleasePool pool; - return [s read: (char*) buffer numBytes: bytesToRead]; - } + if (s != 0) + { + const ScopedAutoReleasePool pool; + return [s read: (char*) buffer numBytes: bytesToRead]; + } - return 0; + return 0; } int64 juce_getInternetFileContentLength (void* handle) { - JuceURLConnection* const s = (JuceURLConnection*) handle; + JuceURLConnection* const s = (JuceURLConnection*) handle; - if (s != 0) - return s->contentLength; + if (s != 0) + return s->contentLength; - return -1; + return -1; } int juce_seekInInternetFile (void* handle, int newPosition) { - JuceURLConnection* const s = (JuceURLConnection*) handle; + JuceURLConnection* const s = (JuceURLConnection*) handle; - if (s != 0) - return [s readPosition]; + if (s != 0) + return [s readPosition]; - return 0; + return 0; } #endif @@ -260155,184 +237762,184 @@ int juce_seekInInternetFile (void* handle, int newPosition) struct NamedPipeInternal { - String pipeInName, pipeOutName; - int pipeIn, pipeOut; + String pipeInName, pipeOutName; + int pipeIn, pipeOut; - bool volatile createdPipe, blocked, stopReadOperation; + bool volatile createdPipe, blocked, stopReadOperation; - static void signalHandler (int) {} + static void signalHandler (int) {} }; void NamedPipe::cancelPendingReads() { - while (internal != 0 && ((NamedPipeInternal*) internal)->blocked) - { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + while (internal != 0 && ((NamedPipeInternal*) internal)->blocked) + { + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - intern->stopReadOperation = true; + intern->stopReadOperation = true; - char buffer [1] = { 0 }; - int bytesWritten = ::write (intern->pipeIn, buffer, 1); - (void) bytesWritten; + char buffer [1] = { 0 }; + int bytesWritten = (int) ::write (intern->pipeIn, buffer, 1); + (void) bytesWritten; - int timeout = 2000; - while (intern->blocked && --timeout >= 0) - Thread::sleep (2); + int timeout = 2000; + while (intern->blocked && --timeout >= 0) + Thread::sleep (2); - intern->stopReadOperation = false; - } + intern->stopReadOperation = false; + } } void NamedPipe::close() { - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - if (intern != 0) - { - internal = 0; + if (intern != 0) + { + internal = 0; - if (intern->pipeIn != -1) - ::close (intern->pipeIn); + if (intern->pipeIn != -1) + ::close (intern->pipeIn); - if (intern->pipeOut != -1) - ::close (intern->pipeOut); + if (intern->pipeOut != -1) + ::close (intern->pipeOut); - if (intern->createdPipe) - { - unlink (intern->pipeInName); - unlink (intern->pipeOutName); - } + if (intern->createdPipe) + { + unlink (intern->pipeInName); + unlink (intern->pipeOutName); + } - delete intern; - } + delete intern; + } } bool NamedPipe::openInternal (const String& pipeName, const bool createPipe) { - close(); + close(); - NamedPipeInternal* const intern = new NamedPipeInternal(); - internal = intern; - intern->createdPipe = createPipe; - intern->blocked = false; - intern->stopReadOperation = false; + NamedPipeInternal* const intern = new NamedPipeInternal(); + internal = intern; + intern->createdPipe = createPipe; + intern->blocked = false; + intern->stopReadOperation = false; - signal (SIGPIPE, NamedPipeInternal::signalHandler); - siginterrupt (SIGPIPE, 1); + signal (SIGPIPE, NamedPipeInternal::signalHandler); + siginterrupt (SIGPIPE, 1); - const String pipePath (T("/tmp/") + File::createLegalFileName (pipeName)); + const String pipePath (T("/tmp/") + File::createLegalFileName (pipeName)); - intern->pipeInName = pipePath + T("_in"); - intern->pipeOutName = pipePath + T("_out"); - intern->pipeIn = -1; - intern->pipeOut = -1; + intern->pipeInName = pipePath + T("_in"); + intern->pipeOutName = pipePath + T("_out"); + intern->pipeIn = -1; + intern->pipeOut = -1; - if (createPipe) - { - if ((mkfifo (intern->pipeInName, 0666) && errno != EEXIST) - || (mkfifo (intern->pipeOutName, 0666) && errno != EEXIST)) - { - delete intern; - internal = 0; + if (createPipe) + { + if ((mkfifo (intern->pipeInName, 0666) && errno != EEXIST) + || (mkfifo (intern->pipeOutName, 0666) && errno != EEXIST)) + { + delete intern; + internal = 0; - return false; - } - } + return false; + } + } - return true; + return true; } int NamedPipe::read (void* destBuffer, int maxBytesToRead, int /*timeOutMilliseconds*/) { - int bytesRead = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + int bytesRead = -1; + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - if (intern != 0) - { - intern->blocked = true; + if (intern != 0) + { + intern->blocked = true; - if (intern->pipeIn == -1) - { - if (intern->createdPipe) - intern->pipeIn = ::open (intern->pipeInName, O_RDWR); - else - intern->pipeIn = ::open (intern->pipeOutName, O_RDWR); + if (intern->pipeIn == -1) + { + if (intern->createdPipe) + intern->pipeIn = ::open (intern->pipeInName, O_RDWR); + else + intern->pipeIn = ::open (intern->pipeOutName, O_RDWR); - if (intern->pipeIn == -1) - { - intern->blocked = false; - return -1; - } - } + if (intern->pipeIn == -1) + { + intern->blocked = false; + return -1; + } + } - bytesRead = 0; + bytesRead = 0; - char* p = (char*) destBuffer; + char* p = (char*) destBuffer; - while (bytesRead < maxBytesToRead) - { - const int bytesThisTime = maxBytesToRead - bytesRead; - const int numRead = ::read (intern->pipeIn, p, bytesThisTime); + while (bytesRead < maxBytesToRead) + { + const int bytesThisTime = maxBytesToRead - bytesRead; + const int numRead = (int) ::read (intern->pipeIn, p, bytesThisTime); - if (numRead <= 0 || intern->stopReadOperation) - { - bytesRead = -1; - break; - } + if (numRead <= 0 || intern->stopReadOperation) + { + bytesRead = -1; + break; + } - bytesRead += numRead; - p += bytesRead; - } + bytesRead += numRead; + p += bytesRead; + } - intern->blocked = false; - } + intern->blocked = false; + } - return bytesRead; + return bytesRead; } int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOutMilliseconds) { - int bytesWritten = -1; - NamedPipeInternal* const intern = (NamedPipeInternal*) internal; + int bytesWritten = -1; + NamedPipeInternal* const intern = (NamedPipeInternal*) internal; - if (intern != 0) - { - if (intern->pipeOut == -1) - { - if (intern->createdPipe) - intern->pipeOut = ::open (intern->pipeOutName, O_WRONLY); - else - intern->pipeOut = ::open (intern->pipeInName, O_WRONLY); + if (intern != 0) + { + if (intern->pipeOut == -1) + { + if (intern->createdPipe) + intern->pipeOut = ::open (intern->pipeOutName, O_WRONLY); + else + intern->pipeOut = ::open (intern->pipeInName, O_WRONLY); - if (intern->pipeOut == -1) - { - return -1; - } - } + if (intern->pipeOut == -1) + { + return -1; + } + } - const char* p = (const char*) sourceBuffer; - bytesWritten = 0; + const char* p = (const char*) sourceBuffer; + bytesWritten = 0; - const uint32 timeOutTime = Time::getMillisecondCounter() + timeOutMilliseconds; + const uint32 timeOutTime = Time::getMillisecondCounter() + timeOutMilliseconds; - while (bytesWritten < numBytesToWrite - && (timeOutMilliseconds < 0 || Time::getMillisecondCounter() < timeOutTime)) - { - const int bytesThisTime = numBytesToWrite - bytesWritten; - const int numWritten = ::write (intern->pipeOut, p, bytesThisTime); + while (bytesWritten < numBytesToWrite + && (timeOutMilliseconds < 0 || Time::getMillisecondCounter() < timeOutTime)) + { + const int bytesThisTime = numBytesToWrite - bytesWritten; + const int numWritten = (int) ::write (intern->pipeOut, p, bytesThisTime); - if (numWritten <= 0) - { - bytesWritten = -1; - break; - } + if (numWritten <= 0) + { + bytesWritten = -1; + break; + } - bytesWritten += numWritten; - p += bytesWritten; - } - } + bytesWritten += numWritten; + p += bytesWritten; + } + } - return bytesWritten; + return bytesWritten; } #endif @@ -260343,37 +237950,32 @@ int NamedPipe::write (const void* sourceBuffer, int numBytesToWrite, int timeOut // compiled on its own). #if JUCE_INCLUDED_FILE -/* - Note that a lot of methods that you'd expect to find in this file actually - live in juce_posix_SharedCode.h! -*/ - void JUCE_API juce_threadEntryPoint (void*); void* threadEntryProc (void* userData) { - const ScopedAutoReleasePool pool; - juce_threadEntryPoint (userData); - return 0; + const ScopedAutoReleasePool pool; + juce_threadEntryPoint (userData); + return 0; } void* juce_createThread (void* userData) { - pthread_t handle = 0; + pthread_t handle = 0; - if (pthread_create (&handle, 0, threadEntryProc, userData) == 0) - { - pthread_detach (handle); - return (void*) handle; - } + if (pthread_create (&handle, 0, threadEntryProc, userData) == 0) + { + pthread_detach (handle); + return (void*) handle; + } - return 0; + return 0; } void juce_killThread (void* handle) { - if (handle != 0) - pthread_cancel ((pthread_t) handle); + if (handle != 0) + pthread_cancel ((pthread_t) handle); } void juce_setCurrentThreadName (const String& /*name*/) @@ -260382,192 +237984,187 @@ void juce_setCurrentThreadName (const String& /*name*/) Thread::ThreadID Thread::getCurrentThreadId() { - return (ThreadID) pthread_self(); + return (ThreadID) pthread_self(); } bool juce_setThreadPriority (void* handle, int priority) { - if (handle == 0) - handle = (void*) pthread_self(); + if (handle == 0) + handle = (void*) pthread_self(); - struct sched_param param; - int policy; - pthread_getschedparam ((pthread_t) handle, &policy, ¶m); - param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11); - return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0; + struct sched_param param; + int policy; + pthread_getschedparam ((pthread_t) handle, &policy, ¶m); + param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11); + return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0; } void Thread::yield() { - sched_yield(); + sched_yield(); } void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) { - // xxx - jassertfalse + // xxx + jassertfalse } bool Process::isForegroundProcess() { #if JUCE_MAC - return [NSApp isActive]; + return [NSApp isActive]; #else - return true; // xxx change this if more than one app is ever possible on the iPhone! + return true; // xxx change this if more than one app is ever possible on the iPhone! #endif } void Process::raisePrivilege() { - jassertfalse + jassertfalse } void Process::lowerPrivilege() { - jassertfalse + jassertfalse } void Process::terminate() { - exit (0); + exit (0); } void Process::setPriority (ProcessPriority p) { - // xxx + // xxx } #endif /********* End of inlined file: juce_mac_Threads.mm *********/ /********* Start of inlined file: juce_posix_SharedCode.h *********/ -/* - This file contains posix routines that are common to both the Linux and Mac builds. - - It gets included directly in the cpp files for these platforms. -*/ CriticalSection::CriticalSection() throw() { - pthread_mutexattr_t atts; - pthread_mutexattr_init (&atts); - pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init (&internal, &atts); + pthread_mutexattr_t atts; + pthread_mutexattr_init (&atts); + pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init (&internal, &atts); } CriticalSection::~CriticalSection() throw() { - pthread_mutex_destroy (&internal); + pthread_mutex_destroy (&internal); } void CriticalSection::enter() const throw() { - pthread_mutex_lock (&internal); + pthread_mutex_lock (&internal); } bool CriticalSection::tryEnter() const throw() { - return pthread_mutex_trylock (&internal) == 0; + return pthread_mutex_trylock (&internal) == 0; } void CriticalSection::exit() const throw() { - pthread_mutex_unlock (&internal); + pthread_mutex_unlock (&internal); } struct EventStruct { - pthread_cond_t condition; - pthread_mutex_t mutex; - bool triggered; + pthread_cond_t condition; + pthread_mutex_t mutex; + bool triggered; }; WaitableEvent::WaitableEvent() throw() { - EventStruct* const es = new EventStruct(); - es->triggered = false; + EventStruct* const es = new EventStruct(); + es->triggered = false; - pthread_cond_init (&es->condition, 0); - pthread_mutex_init (&es->mutex, 0); + pthread_cond_init (&es->condition, 0); + pthread_mutex_init (&es->mutex, 0); - internal = es; + internal = es; } WaitableEvent::~WaitableEvent() throw() { - EventStruct* const es = (EventStruct*) internal; + EventStruct* const es = (EventStruct*) internal; - pthread_cond_destroy (&es->condition); - pthread_mutex_destroy (&es->mutex); + pthread_cond_destroy (&es->condition); + pthread_mutex_destroy (&es->mutex); - delete es; + delete es; } bool WaitableEvent::wait (const int timeOutMillisecs) const throw() { - EventStruct* const es = (EventStruct*) internal; - pthread_mutex_lock (&es->mutex); + EventStruct* const es = (EventStruct*) internal; + pthread_mutex_lock (&es->mutex); - if (timeOutMillisecs < 0) - { - while (! es->triggered) - pthread_cond_wait (&es->condition, &es->mutex); - } - else - { - while (! es->triggered) - { - struct timeval t; - gettimeofday (&t, 0); + if (timeOutMillisecs < 0) + { + while (! es->triggered) + pthread_cond_wait (&es->condition, &es->mutex); + } + else + { + while (! es->triggered) + { + struct timeval t; + gettimeofday (&t, 0); - struct timespec time; - time.tv_sec = t.tv_sec + (timeOutMillisecs / 1000); - time.tv_nsec = (t.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000; + struct timespec time; + time.tv_sec = t.tv_sec + (timeOutMillisecs / 1000); + time.tv_nsec = (t.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000; - if (time.tv_nsec >= 1000000000) - { - time.tv_nsec -= 1000000000; - time.tv_sec++; - } + if (time.tv_nsec >= 1000000000) + { + time.tv_nsec -= 1000000000; + time.tv_sec++; + } - if (pthread_cond_timedwait (&es->condition, &es->mutex, &time) == ETIMEDOUT) - { - pthread_mutex_unlock (&es->mutex); - return false; - } - } - } + if (pthread_cond_timedwait (&es->condition, &es->mutex, &time) == ETIMEDOUT) + { + pthread_mutex_unlock (&es->mutex); + return false; + } + } + } - es->triggered = false; - pthread_mutex_unlock (&es->mutex); - return true; + es->triggered = false; + pthread_mutex_unlock (&es->mutex); + return true; } void WaitableEvent::signal() const throw() { - EventStruct* const es = (EventStruct*) internal; + EventStruct* const es = (EventStruct*) internal; - pthread_mutex_lock (&es->mutex); - es->triggered = true; - pthread_cond_broadcast (&es->condition); - pthread_mutex_unlock (&es->mutex); + pthread_mutex_lock (&es->mutex); + es->triggered = true; + pthread_cond_broadcast (&es->condition); + pthread_mutex_unlock (&es->mutex); } void WaitableEvent::reset() const throw() { - EventStruct* const es = (EventStruct*) internal; + EventStruct* const es = (EventStruct*) internal; - pthread_mutex_lock (&es->mutex); - es->triggered = false; - pthread_mutex_unlock (&es->mutex); + pthread_mutex_lock (&es->mutex); + es->triggered = false; + pthread_mutex_unlock (&es->mutex); } void JUCE_CALLTYPE Thread::sleep (int millisecs) { - struct timespec time; - time.tv_sec = millisecs / 1000; - time.tv_nsec = (millisecs % 1000) * 1000000; - nanosleep (&time, 0); + struct timespec time; + time.tv_sec = millisecs / 1000; + time.tv_nsec = (millisecs % 1000) * 1000000; + nanosleep (&time, 0); } const tchar File::separator = T('/'); @@ -260577,337 +238174,331 @@ bool juce_copyFile (const String& s, const String& d); static bool juce_stat (const String& fileName, struct stat& info) { - return fileName.isNotEmpty() - && (stat (fileName.toUTF8(), &info) == 0); + return fileName.isNotEmpty() + && (stat (fileName.toUTF8(), &info) == 0); } bool juce_isDirectory (const String& fileName) { - struct stat info; + struct stat info; - return fileName.isEmpty() - || (juce_stat (fileName, info) - && ((info.st_mode & S_IFDIR) != 0)); + return fileName.isEmpty() + || (juce_stat (fileName, info) + && ((info.st_mode & S_IFDIR) != 0)); } bool juce_fileExists (const String& fileName, const bool dontCountDirectories) { - if (fileName.isEmpty()) - return false; + if (fileName.isEmpty()) + return false; - const char* const fileNameUTF8 = fileName.toUTF8(); - bool exists = access (fileNameUTF8, F_OK) == 0; + const char* const fileNameUTF8 = fileName.toUTF8(); + bool exists = access (fileNameUTF8, F_OK) == 0; - if (exists && dontCountDirectories) - { - struct stat info; - const int res = stat (fileNameUTF8, &info); + if (exists && dontCountDirectories) + { + struct stat info; + const int res = stat (fileNameUTF8, &info); - if (res == 0 && (info.st_mode & S_IFDIR) != 0) - exists = false; - } + if (res == 0 && (info.st_mode & S_IFDIR) != 0) + exists = false; + } - return exists; + return exists; } int64 juce_getFileSize (const String& fileName) { - struct stat info; - return juce_stat (fileName, info) ? info.st_size : 0; + struct stat info; + return juce_stat (fileName, info) ? info.st_size : 0; } bool juce_canWriteToFile (const String& fileName) { - return access (fileName.toUTF8(), W_OK) == 0; + return access (fileName.toUTF8(), W_OK) == 0; } bool juce_deleteFile (const String& fileName) { - if (juce_isDirectory (fileName)) - return rmdir ((const char*) fileName.toUTF8()) == 0; - else - return remove ((const char*) fileName.toUTF8()) == 0; + if (juce_isDirectory (fileName)) + return rmdir ((const char*) fileName.toUTF8()) == 0; + else + return remove ((const char*) fileName.toUTF8()) == 0; } bool juce_moveFile (const String& source, const String& dest) { - if (rename (source.toUTF8(), dest.toUTF8()) == 0) - return true; + if (rename (source.toUTF8(), dest.toUTF8()) == 0) + return true; - if (juce_canWriteToFile (source) - && juce_copyFile (source, dest)) - { - if (juce_deleteFile (source)) - return true; + if (juce_canWriteToFile (source) + && juce_copyFile (source, dest)) + { + if (juce_deleteFile (source)) + return true; - juce_deleteFile (dest); - } + juce_deleteFile (dest); + } - return false; + return false; } void juce_createDirectory (const String& fileName) { - mkdir (fileName.toUTF8(), 0777); + mkdir (fileName.toUTF8(), 0777); } void* juce_fileOpen (const String& fileName, bool forWriting) { - int flags = O_RDONLY; + int flags = O_RDONLY; - if (forWriting) - { - if (juce_fileExists (fileName, false)) - { - const int f = open ((const char*) fileName.toUTF8(), O_RDWR, 00644); + if (forWriting) + { + if (juce_fileExists (fileName, false)) + { + const int f = open ((const char*) fileName.toUTF8(), O_RDWR, 00644); - if (f != -1) - lseek (f, 0, SEEK_END); + if (f != -1) + lseek (f, 0, SEEK_END); - return (void*) f; - } - else - { - flags = O_RDWR + O_CREAT; - } - } + return (void*) f; + } + else + { + flags = O_RDWR + O_CREAT; + } + } - return (void*) open ((const char*) fileName.toUTF8(), flags, 00644); + return (void*) open ((const char*) fileName.toUTF8(), flags, 00644); } void juce_fileClose (void* handle) { - if (handle != 0) - close ((int) (pointer_sized_int) handle); + if (handle != 0) + close ((int) (pointer_sized_int) handle); } int juce_fileRead (void* handle, void* buffer, int size) { - if (handle != 0) - return read ((int) (pointer_sized_int) handle, buffer, size); + if (handle != 0) + return (int) read ((int) (pointer_sized_int) handle, buffer, size); - return 0; + return 0; } int juce_fileWrite (void* handle, const void* buffer, int size) { - if (handle != 0) - return write ((int) (pointer_sized_int) handle, buffer, size); + if (handle != 0) + return (int) write ((int) (pointer_sized_int) handle, buffer, size); - return 0; + return 0; } int64 juce_fileSetPosition (void* handle, int64 pos) { - if (handle != 0 && lseek ((int) (pointer_sized_int) handle, pos, SEEK_SET) == pos) - return pos; + if (handle != 0 && lseek ((int) (pointer_sized_int) handle, pos, SEEK_SET) == pos) + return pos; - return -1; + return -1; } int64 juce_fileGetPosition (void* handle) { - if (handle != 0) - return lseek ((int) (pointer_sized_int) handle, 0, SEEK_CUR); - else - return -1; + if (handle != 0) + return lseek ((int) (pointer_sized_int) handle, 0, SEEK_CUR); + else + return -1; } void juce_fileFlush (void* handle) { - if (handle != 0) - fsync ((int) (pointer_sized_int) handle); + if (handle != 0) + fsync ((int) (pointer_sized_int) handle); } const File juce_getExecutableFile() { - Dl_info exeInfo; - dladdr ((const void*) juce_getExecutableFile, &exeInfo); - return File (exeInfo.dli_fname); + Dl_info exeInfo; + dladdr ((const void*) juce_getExecutableFile, &exeInfo); + return File (exeInfo.dli_fname); } // if this file doesn't exist, find a parent of it that does.. static bool doStatFS (const File* file, struct statfs& result) { - File f (*file); + File f (*file); - for (int i = 5; --i >= 0;) - { - if (f.exists()) - break; + for (int i = 5; --i >= 0;) + { + if (f.exists()) + break; - f = f.getParentDirectory(); - } + f = f.getParentDirectory(); + } - return statfs (f.getFullPathName().toUTF8(), &result) == 0; + return statfs (f.getFullPathName().toUTF8(), &result) == 0; } int64 File::getBytesFreeOnVolume() const { - struct statfs buf; - if (doStatFS (this, buf)) - return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user + struct statfs buf; + if (doStatFS (this, buf)) + return (int64) buf.f_bsize * (int64) buf.f_bavail; // Note: this returns space available to non-super user - return 0; + return 0; } int64 File::getVolumeTotalSize() const { - struct statfs buf; - if (doStatFS (this, buf)) - return (int64) buf.f_bsize * (int64) buf.f_blocks; + struct statfs buf; + if (doStatFS (this, buf)) + return (int64) buf.f_bsize * (int64) buf.f_blocks; - return 0; + return 0; } const String juce_getVolumeLabel (const String& filenameOnVolume, - int& volumeSerialNumber) + int& volumeSerialNumber) { - volumeSerialNumber = 0; + volumeSerialNumber = 0; #if JUCE_MAC - struct VolAttrBuf - { - u_int32_t length; - attrreference_t mountPointRef; - char mountPointSpace [MAXPATHLEN]; - } attrBuf; + struct VolAttrBuf + { + u_int32_t length; + attrreference_t mountPointRef; + char mountPointSpace [MAXPATHLEN]; + } attrBuf; - struct attrlist attrList; - zerostruct (attrList); - attrList.bitmapcount = ATTR_BIT_MAP_COUNT; - attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME; + struct attrlist attrList; + zerostruct (attrList); + attrList.bitmapcount = ATTR_BIT_MAP_COUNT; + attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME; - File f (filenameOnVolume); + File f (filenameOnVolume); - for (;;) - { - if (getattrlist ((const char*) f.getFullPathName().toUTF8(), - &attrList, &attrBuf, sizeof(attrBuf), 0) == 0) - { - return String::fromUTF8 (((const uint8*) &attrBuf.mountPointRef) + attrBuf.mountPointRef.attr_dataoffset, - (int) attrBuf.mountPointRef.attr_length); - } + for (;;) + { + if (getattrlist ((const char*) f.getFullPathName().toUTF8(), + &attrList, &attrBuf, sizeof(attrBuf), 0) == 0) + { + return String::fromUTF8 (((const uint8*) &attrBuf.mountPointRef) + attrBuf.mountPointRef.attr_dataoffset, + (int) attrBuf.mountPointRef.attr_length); + } - const File parent (f.getParentDirectory()); + const File parent (f.getParentDirectory()); - if (f == parent) - break; + if (f == parent) + break; - f = parent; - } + f = parent; + } #endif - return String::empty; + return String::empty; } void juce_runSystemCommand (const String& command) { - int result = system ((const char*) command.toUTF8()); - (void) result; + int result = system ((const char*) command.toUTF8()); + (void) result; } const String juce_getOutputFromCommand (const String& command) { - // slight bodge here, as we just pipe the output into a temp file and read it... - const File tempFile (File::getSpecialLocation (File::tempDirectory) - .getNonexistentChildFile (String::toHexString (Random::getSystemRandom().nextInt()), ".tmp", false)); + // slight bodge here, as we just pipe the output into a temp file and read it... + const File tempFile (File::getSpecialLocation (File::tempDirectory) + .getNonexistentChildFile (String::toHexString (Random::getSystemRandom().nextInt()), ".tmp", false)); - juce_runSystemCommand (command + " > " + tempFile.getFullPathName()); + juce_runSystemCommand (command + " > " + tempFile.getFullPathName()); - String result (tempFile.loadFileAsString()); - tempFile.deleteFile(); - return result; + String result (tempFile.loadFileAsString()); + tempFile.deleteFile(); + return result; } -#if JUCE_64BIT - #define filedesc ((long long) internal) -#else - #define filedesc ((int) internal) -#endif - InterProcessLock::InterProcessLock (const String& name_) - : internal (0), - name (name_), - reentrancyLevel (0) + : internal (0), + name (name_), + reentrancyLevel (0) { #if JUCE_MAC - // (don't use getSpecialLocation() to avoid the temp folder being different for each app) - const File temp (File (T("~/Library/Caches/Juce")).getChildFile (name)); + // (don't use getSpecialLocation() to avoid the temp folder being different for each app) + const File temp (File (T("~/Library/Caches/Juce")).getChildFile (name)); #else - const File temp (File::getSpecialLocation (File::tempDirectory).getChildFile (name)); + const File temp (File::getSpecialLocation (File::tempDirectory).getChildFile (name)); #endif - temp.create(); + temp.create(); - internal = (void*) open (temp.getFullPathName().toUTF8(), O_RDWR); + internal = open (temp.getFullPathName().toUTF8(), O_RDWR); } InterProcessLock::~InterProcessLock() { - while (reentrancyLevel > 0) - this->exit(); + while (reentrancyLevel > 0) + this->exit(); - close (filedesc); + close (internal); } bool InterProcessLock::enter (const int timeOutMillisecs) { - if (internal == 0) - return false; + if (internal == 0) + return false; - if (reentrancyLevel != 0) - return true; + if (reentrancyLevel != 0) + return true; - const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs; + const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs; - struct flock fl; - zerostruct (fl); - fl.l_whence = SEEK_SET; - fl.l_type = F_WRLCK; + struct flock fl; + zerostruct (fl); + fl.l_whence = SEEK_SET; + fl.l_type = F_WRLCK; - for (;;) - { - const int result = fcntl (filedesc, F_SETLK, &fl); + for (;;) + { + const int result = fcntl (internal, F_SETLK, &fl); - if (result >= 0) - { - ++reentrancyLevel; - return true; - } + if (result >= 0) + { + ++reentrancyLevel; + return true; + } - if (errno != EINTR) - { - if (timeOutMillisecs == 0 - || (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime)) - break; + if (errno != EINTR) + { + if (timeOutMillisecs == 0 + || (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime)) + break; - Thread::sleep (10); - } - } + Thread::sleep (10); + } + } - return false; + return false; } void InterProcessLock::exit() { - if (reentrancyLevel > 0 && internal != 0) - { - --reentrancyLevel; + if (reentrancyLevel > 0 && internal != 0) + { + --reentrancyLevel; - struct flock fl; - zerostruct (fl); - fl.l_whence = SEEK_SET; - fl.l_type = F_UNLCK; + struct flock fl; + zerostruct (fl); + fl.l_whence = SEEK_SET; + fl.l_type = F_UNLCK; - for (;;) - { - const int result = fcntl (filedesc, F_SETLKW, &fl); + for (;;) + { + const int result = fcntl (internal, F_SETLKW, &fl); - if (result >= 0 || errno != EINTR) - break; - } - } + if (result >= 0 || errno != EINTR) + break; + } + } } /********* End of inlined file: juce_posix_SharedCode.h *********/ @@ -260916,516 +238507,509 @@ void InterProcessLock::exit() // compiled on its own). #if JUCE_INCLUDED_FILE -/* - Note that a lot of methods that you'd expect to find in this file actually - live in juce_posix_SharedCode.h! -*/ - void juce_getFileTimes (const String& fileName, - int64& modificationTime, - int64& accessTime, - int64& creationTime) + int64& modificationTime, + int64& accessTime, + int64& creationTime) { - modificationTime = 0; - accessTime = 0; - creationTime = 0; + modificationTime = 0; + accessTime = 0; + creationTime = 0; - struct stat info; - const int res = stat (fileName.toUTF8(), &info); - if (res == 0) - { - modificationTime = (int64) info.st_mtime * 1000; - accessTime = (int64) info.st_atime * 1000; - creationTime = (int64) info.st_ctime * 1000; - } + struct stat info; + const int res = stat (fileName.toUTF8(), &info); + if (res == 0) + { + modificationTime = (int64) info.st_mtime * 1000; + accessTime = (int64) info.st_atime * 1000; + creationTime = (int64) info.st_ctime * 1000; + } } bool juce_setFileTimes (const String& fileName, - int64 modificationTime, - int64 accessTime, - int64 creationTime) + int64 modificationTime, + int64 accessTime, + int64 creationTime) { - struct utimbuf times; - times.actime = (time_t) (accessTime / 1000); - times.modtime = (time_t) (modificationTime / 1000); + struct utimbuf times; + times.actime = (time_t) (accessTime / 1000); + times.modtime = (time_t) (modificationTime / 1000); - return utime (fileName.toUTF8(), ×) == 0; + return utime (fileName.toUTF8(), ×) == 0; } bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) { - struct stat info; - const int res = stat (fileName.toUTF8(), &info); - if (res != 0) - return false; + struct stat info; + const int res = stat (fileName.toUTF8(), &info); + if (res != 0) + return false; - info.st_mode &= 0777; // Just permissions + info.st_mode &= 0777; // Just permissions - if (isReadOnly) - info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); - else - // Give everybody write permission? - info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + if (isReadOnly) + info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + else + // Give everybody write permission? + info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; - return chmod (fileName.toUTF8(), info.st_mode) == 0; + return chmod (fileName.toUTF8(), info.st_mode) == 0; } bool juce_copyFile (const String& src, const String& dst) { - const ScopedAutoReleasePool pool; - NSFileManager* fm = [NSFileManager defaultManager]; + const ScopedAutoReleasePool pool; + NSFileManager* fm = [NSFileManager defaultManager]; - return [fm fileExistsAtPath: juceStringToNS (src)] + return [fm fileExistsAtPath: juceStringToNS (src)] #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - && [fm copyItemAtPath: juceStringToNS (src) - toPath: juceStringToNS (dst) - error: nil]; + && [fm copyItemAtPath: juceStringToNS (src) + toPath: juceStringToNS (dst) + error: nil]; #else - && [fm copyPath: juceStringToNS (src) - toPath: juceStringToNS (dst) - handler: nil]; + && [fm copyPath: juceStringToNS (src) + toPath: juceStringToNS (dst) + handler: nil]; #endif } const StringArray juce_getFileSystemRoots() { - StringArray s; - s.add (T("/")); - return s; + StringArray s; + s.add (T("/")); + return s; } static bool isFileOnDriveType (const File* const f, const char** types) { - struct statfs buf; + struct statfs buf; - if (doStatFS (f, buf)) - { - const String type (buf.f_fstypename); + if (doStatFS (f, buf)) + { + const String type (buf.f_fstypename); - while (*types != 0) - if (type.equalsIgnoreCase (*types++)) - return true; - } + while (*types != 0) + if (type.equalsIgnoreCase (*types++)) + return true; + } - return false; + return false; } bool File::isOnCDRomDrive() const { - static const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", 0 }; + static const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", 0 }; - return isFileOnDriveType (this, (const char**) cdTypes); + return isFileOnDriveType (this, (const char**) cdTypes); } bool File::isOnHardDisk() const { - static const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", 0 }; + static const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", 0 }; - return ! (isOnCDRomDrive() || isFileOnDriveType (this, (const char**) nonHDTypes)); + return ! (isOnCDRomDrive() || isFileOnDriveType (this, (const char**) nonHDTypes)); } bool File::isOnRemovableDrive() const { #if JUCE_IPHONE - return false; // xxx is this possible? + return false; // xxx is this possible? #else - const ScopedAutoReleasePool pool; - BOOL removable = false; + const ScopedAutoReleasePool pool; + BOOL removable = false; - [[NSWorkspace sharedWorkspace] - getFileSystemInfoForPath: juceStringToNS (getFullPathName()) - isRemovable: &removable - isWritable: nil - isUnmountable: nil - description: nil - type: nil]; + [[NSWorkspace sharedWorkspace] + getFileSystemInfoForPath: juceStringToNS (getFullPathName()) + isRemovable: &removable + isWritable: nil + isUnmountable: nil + description: nil + type: nil]; - return removable; + return removable; #endif } static bool juce_isHiddenFile (const String& path) { #if JUCE_IPHONE - return File (path).getFileName().startsWithChar (T('.')); + return File (path).getFileName().startsWithChar (T('.')); #else - FSRef ref; - if (! PlatformUtilities::makeFSRefFromPath (&ref, path)) - return false; + FSRef ref; + if (! PlatformUtilities::makeFSRefFromPath (&ref, path)) + return false; - FSCatalogInfo info; - FSGetCatalogInfo (&ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &info, 0, 0, 0); + FSCatalogInfo info; + FSGetCatalogInfo (&ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &info, 0, 0, 0); - if ((info.nodeFlags & kFSNodeIsDirectoryBit) != 0) - return (((FolderInfo*) &info.finderInfo)->finderFlags & kIsInvisible) != 0; + if ((info.nodeFlags & kFSNodeIsDirectoryBit) != 0) + return (((FolderInfo*) &info.finderInfo)->finderFlags & kIsInvisible) != 0; - return (((FileInfo*) &info.finderInfo)->finderFlags & kIsInvisible) != 0; + return (((FileInfo*) &info.finderInfo)->finderFlags & kIsInvisible) != 0; #endif } bool File::isHidden() const { - return juce_isHiddenFile (getFullPathName()); + return juce_isHiddenFile (getFullPathName()); } const char* juce_Argv0 = 0; // referenced from juce_Application.cpp const File File::getSpecialLocation (const SpecialLocationType type) { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - String resultPath; + String resultPath; - switch (type) - { - case userHomeDirectory: - resultPath = nsStringToJuce (NSHomeDirectory()); - break; + switch (type) + { + case userHomeDirectory: + resultPath = nsStringToJuce (NSHomeDirectory()); + break; - case userDocumentsDirectory: - resultPath = "~/Documents"; - break; + case userDocumentsDirectory: + resultPath = "~/Documents"; + break; - case userDesktopDirectory: - resultPath = "~/Desktop"; - break; + case userDesktopDirectory: + resultPath = "~/Desktop"; + break; - case userApplicationDataDirectory: - resultPath = "~/Library"; - break; + case userApplicationDataDirectory: + resultPath = "~/Library"; + break; - case commonApplicationDataDirectory: - resultPath = "/Library"; - break; + case commonApplicationDataDirectory: + resultPath = "/Library"; + break; - case globalApplicationsDirectory: - resultPath = "/Applications"; - break; + case globalApplicationsDirectory: + resultPath = "/Applications"; + break; - case userMusicDirectory: - resultPath = "~/Music"; - break; + case userMusicDirectory: + resultPath = "~/Music"; + break; - case userMoviesDirectory: - resultPath = "~/Movies"; - break; + case userMoviesDirectory: + resultPath = "~/Movies"; + break; - case tempDirectory: - { - File tmp (T("~/Library/Caches/") + juce_getExecutableFile().getFileNameWithoutExtension()); + case tempDirectory: + { + File tmp (T("~/Library/Caches/") + juce_getExecutableFile().getFileNameWithoutExtension()); - tmp.createDirectory(); - return tmp.getFullPathName(); - } + tmp.createDirectory(); + return tmp.getFullPathName(); + } - case invokedExecutableFile: - if (juce_Argv0 != 0) - return File (String::fromUTF8 ((const uint8*) juce_Argv0)); - // deliberate fall-through... + case invokedExecutableFile: + if (juce_Argv0 != 0) + return File (String::fromUTF8 ((const uint8*) juce_Argv0)); + // deliberate fall-through... - case currentExecutableFile: - return juce_getExecutableFile(); + case currentExecutableFile: + return juce_getExecutableFile(); - case currentApplicationFile: - { - const File exe (juce_getExecutableFile()); - const File parent (exe.getParentDirectory()); + case currentApplicationFile: + { + const File exe (juce_getExecutableFile()); + const File parent (exe.getParentDirectory()); - return parent.getFullPathName().endsWithIgnoreCase (T("Contents/MacOS")) - ? parent.getParentDirectory().getParentDirectory() - : exe; - } + return parent.getFullPathName().endsWithIgnoreCase (T("Contents/MacOS")) + ? parent.getParentDirectory().getParentDirectory() + : exe; + } - default: - jassertfalse // unknown type? - break; - } + default: + jassertfalse // unknown type? + break; + } - if (resultPath != 0) - return File (PlatformUtilities::convertToPrecomposedUnicode (resultPath)); + if (resultPath != 0) + return File (PlatformUtilities::convertToPrecomposedUnicode (resultPath)); - return File::nonexistent; + return File::nonexistent; } const File File::getCurrentWorkingDirectory() { - char buf [2048]; - getcwd (buf, sizeof(buf)); + char buf [2048]; + getcwd (buf, sizeof(buf)); - return File (PlatformUtilities::convertToPrecomposedUnicode (buf)); + return File (PlatformUtilities::convertToPrecomposedUnicode (buf)); } bool File::setAsCurrentWorkingDirectory() const { - return chdir (getFullPathName().toUTF8()) == 0; + return chdir (getFullPathName().toUTF8()) == 0; } const String File::getVersion() const { - const ScopedAutoReleasePool pool; - String result; + const ScopedAutoReleasePool pool; + String result; - NSBundle* bundle = [NSBundle bundleWithPath: juceStringToNS (getFullPathName())]; + NSBundle* bundle = [NSBundle bundleWithPath: juceStringToNS (getFullPathName())]; - if (bundle != 0) - { - NSDictionary* info = [bundle infoDictionary]; + if (bundle != 0) + { + NSDictionary* info = [bundle infoDictionary]; - if (info != 0) - { - NSString* name = [info valueForKey: @"CFBundleShortVersionString"]; + if (info != 0) + { + NSString* name = [info valueForKey: @"CFBundleShortVersionString"]; - if (name != nil) - result = nsStringToJuce (name); - } - } + if (name != nil) + result = nsStringToJuce (name); + } + } - return result; + return result; } const File File::getLinkedTarget() const { #if JUCE_IPHONE || (defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - NSString* dest = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath: juceStringToNS (getFullPathName()) error: nil]; + NSString* dest = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath: juceStringToNS (getFullPathName()) error: nil]; #else - NSString* dest = [[NSFileManager defaultManager] pathContentOfSymbolicLinkAtPath: juceStringToNS (getFullPathName())]; + NSString* dest = [[NSFileManager defaultManager] pathContentOfSymbolicLinkAtPath: juceStringToNS (getFullPathName())]; #endif - if (dest != nil) - return File (nsStringToJuce (dest)); + if (dest != nil) + return File (nsStringToJuce (dest)); - return *this; + return *this; } bool File::moveToTrash() const { - if (! exists()) - return true; + if (! exists()) + return true; #if JUCE_IPHONE - return deleteFile(); //xxx is there a trashcan on the iPhone? + return deleteFile(); //xxx is there a trashcan on the iPhone? #else - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - NSString* p = juceStringToNS (getFullPathName()); + NSString* p = juceStringToNS (getFullPathName()); - return [[NSWorkspace sharedWorkspace] - performFileOperation: NSWorkspaceRecycleOperation - source: [p stringByDeletingLastPathComponent] - destination: @"" - files: [NSArray arrayWithObject: [p lastPathComponent]] - tag: nil ]; + return [[NSWorkspace sharedWorkspace] + performFileOperation: NSWorkspaceRecycleOperation + source: [p stringByDeletingLastPathComponent] + destination: @"" + files: [NSArray arrayWithObject: [p lastPathComponent]] + tag: nil ]; #endif } struct FindFileStruct { - NSDirectoryEnumerator* enumerator; - String parentDir, wildCard; + NSDirectoryEnumerator* enumerator; + String parentDir, wildCard; }; bool juce_findFileNext (void* handle, String& resultFile, - bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) + bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) { - FindFileStruct* ff = (FindFileStruct*) handle; - NSString* file; - const char* const wildcardUTF8 = ff->wildCard.toUTF8(); + FindFileStruct* ff = (FindFileStruct*) handle; + NSString* file; + const char* const wildcardUTF8 = ff->wildCard.toUTF8(); - for (;;) - { - if (ff == 0 || (file = [ff->enumerator nextObject]) == 0) - return false; + for (;;) + { + if (ff == 0 || (file = [ff->enumerator nextObject]) == 0) + return false; - [ff->enumerator skipDescendents]; - resultFile = nsStringToJuce (file); + [ff->enumerator skipDescendents]; + resultFile = nsStringToJuce (file); - if (fnmatch (wildcardUTF8, resultFile.toUTF8(), FNM_CASEFOLD) != 0) - continue; + if (fnmatch (wildcardUTF8, resultFile.toUTF8(), FNM_CASEFOLD) != 0) + continue; - const String path (ff->parentDir + resultFile); + const String path (ff->parentDir + resultFile); - if (isDir != 0 || fileSize != 0) - { - struct stat info; - const bool statOk = juce_stat (path, info); + if (isDir != 0 || fileSize != 0) + { + struct stat info; + const bool statOk = juce_stat (path, info); - if (isDir != 0) - *isDir = statOk && ((info.st_mode & S_IFDIR) != 0); + if (isDir != 0) + *isDir = statOk && ((info.st_mode & S_IFDIR) != 0); - if (isHidden != 0) - *isHidden = juce_isHiddenFile (path); + if (isHidden != 0) + *isHidden = juce_isHiddenFile (path); - if (fileSize != 0) - *fileSize = statOk ? info.st_size : 0; - } + if (fileSize != 0) + *fileSize = statOk ? info.st_size : 0; + } - if (modTime != 0 || creationTime != 0) - { - int64 m, a, c; - juce_getFileTimes (path, m, a, c); + if (modTime != 0 || creationTime != 0) + { + int64 m, a, c; + juce_getFileTimes (path, m, a, c); - if (modTime != 0) - *modTime = m; + if (modTime != 0) + *modTime = m; - if (creationTime != 0) - *creationTime = c; - } + if (creationTime != 0) + *creationTime = c; + } - if (isReadOnly != 0) - *isReadOnly = ! juce_canWriteToFile (path); + if (isReadOnly != 0) + *isReadOnly = ! juce_canWriteToFile (path); - return true; - } + return true; + } } void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile, - bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, - Time* creationTime, bool* isReadOnly) + bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, + Time* creationTime, bool* isReadOnly) { - NSDirectoryEnumerator* e = [[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory)]; + NSDirectoryEnumerator* e = [[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory)]; - if (e != 0) - { - FindFileStruct* ff = new FindFileStruct(); - ff->enumerator = [e retain]; - ff->parentDir = directory; - ff->wildCard = wildCard; + if (e != 0) + { + ScopedPointer ff (new FindFileStruct()); + ff->enumerator = [e retain]; + ff->parentDir = directory; + ff->wildCard = wildCard; - if (! ff->parentDir.endsWithChar (File::separator)) - ff->parentDir += File::separator; + if (! ff->parentDir.endsWithChar (File::separator)) + ff->parentDir += File::separator; - if (juce_findFileNext (ff, firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly)) - return ff; + if (juce_findFileNext (ff, firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly)) + return ff.release(); - [e release]; - delete ff; - } + [e release]; + } - return 0; + return 0; } void juce_findFileClose (void* handle) { - FindFileStruct* ff = (FindFileStruct*) handle; - [ff->enumerator release]; - delete ff; + ScopedPointer ff ((FindFileStruct*) handle); + [ff->enumerator release]; } bool juce_launchExecutable (const String& pathAndArguments) { - const char* const argv[4] = { "/bin/sh", "-c", (const char*) pathAndArguments, 0 }; + const char* const argv[4] = { "/bin/sh", "-c", (const char*) pathAndArguments, 0 }; - const int cpid = fork(); + const int cpid = fork(); - if (cpid == 0) - { - // Child process - if (execve (argv[0], (char**) argv, 0) < 0) - exit (0); - } - else - { - if (cpid < 0) - return false; - } + if (cpid == 0) + { + // Child process + if (execve (argv[0], (char**) argv, 0) < 0) + exit (0); + } + else + { + if (cpid < 0) + return false; + } - return true; + return true; } bool juce_launchFile (const String& fileName, const String& parameters) { #if JUCE_IPHONE - return [[UIApplication sharedApplication] openURL: [NSURL fileURLWithPath: juceStringToNS (fileName)]]; + return [[UIApplication sharedApplication] openURL: [NSURL fileURLWithPath: juceStringToNS (fileName)]]; #else - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - if (parameters.isEmpty()) - { - return [[NSWorkspace sharedWorkspace] openFile: juceStringToNS (fileName)] - || [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: juceStringToNS (fileName)]]; - } + if (parameters.isEmpty()) + { + return [[NSWorkspace sharedWorkspace] openFile: juceStringToNS (fileName)] + || [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: juceStringToNS (fileName)]]; + } - bool ok = false; + bool ok = false; - FSRef ref; - if (PlatformUtilities::makeFSRefFromPath (&ref, fileName)) - { - if (PlatformUtilities::isBundle (fileName)) - { - NSMutableArray* urls = [NSMutableArray array]; + FSRef ref; + if (PlatformUtilities::makeFSRefFromPath (&ref, fileName)) + { + if (PlatformUtilities::isBundle (fileName)) + { + NSMutableArray* urls = [NSMutableArray array]; - StringArray docs; - docs.addTokens (parameters, true); - for (int i = 0; i < docs.size(); ++i) - [urls addObject: juceStringToNS (docs[i])]; + StringArray docs; + docs.addTokens (parameters, true); + for (int i = 0; i < docs.size(); ++i) + [urls addObject: juceStringToNS (docs[i])]; - ok = [[NSWorkspace sharedWorkspace] openURLs: urls - withAppBundleIdentifier: [[NSBundle bundleWithPath: juceStringToNS (fileName)] bundleIdentifier] - options: 0 - additionalEventParamDescriptor: nil - launchIdentifiers: nil]; - } - else - { - ok = juce_launchExecutable (T("\"") + fileName + T("\" ") + parameters); - } - } + ok = [[NSWorkspace sharedWorkspace] openURLs: urls + withAppBundleIdentifier: [[NSBundle bundleWithPath: juceStringToNS (fileName)] bundleIdentifier] + options: 0 + additionalEventParamDescriptor: nil + launchIdentifiers: nil]; + } + else + { + ok = juce_launchExecutable (T("\"") + fileName + T("\" ") + parameters); + } + } - return ok; + return ok; #endif } void File::revealToUser() const { #if ! JUCE_IPHONE - if (exists()) - [[NSWorkspace sharedWorkspace] selectFile: juceStringToNS (getFullPathName()) inFileViewerRootedAtPath: @""]; - else if (getParentDirectory().exists()) - getParentDirectory().revealToUser(); + if (exists()) + [[NSWorkspace sharedWorkspace] selectFile: juceStringToNS (getFullPathName()) inFileViewerRootedAtPath: @""]; + else if (getParentDirectory().exists()) + getParentDirectory().revealToUser(); #endif } #if ! JUCE_IPHONE bool PlatformUtilities::makeFSRefFromPath (FSRef* destFSRef, const String& path) { - return FSPathMakeRef ((const UInt8*) path.toUTF8(), destFSRef, 0) == noErr; + return FSPathMakeRef ((const UInt8*) path.toUTF8(), destFSRef, 0) == noErr; } const String PlatformUtilities::makePathFromFSRef (FSRef* file) { - uint8 path [2048]; - zeromem (path, sizeof (path)); + uint8 path [2048]; + zeromem (path, sizeof (path)); - String result; + String result; - if (FSRefMakePath (file, (UInt8*) path, sizeof (path) - 1) == noErr) - result = String::fromUTF8 (path); + if (FSRefMakePath (file, (UInt8*) path, sizeof (path) - 1) == noErr) + result = String::fromUTF8 (path); - return PlatformUtilities::convertToPrecomposedUnicode (result); + return PlatformUtilities::convertToPrecomposedUnicode (result); } #endif OSType PlatformUtilities::getTypeOfFile (const String& filename) { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; #if JUCE_IPHONE || (defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - NSDictionary* fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath: juceStringToNS (filename) error: nil]; + NSDictionary* fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath: juceStringToNS (filename) error: nil]; #else - NSDictionary* fileDict = [[NSFileManager defaultManager] fileAttributesAtPath: juceStringToNS (filename) traverseLink: NO]; + NSDictionary* fileDict = [[NSFileManager defaultManager] fileAttributesAtPath: juceStringToNS (filename) traverseLink: NO]; #endif - //return (OSType) [fileDict objectForKey: NSFileHFSTypeCode]; - return [fileDict fileHFSTypeCode]; + //return (OSType) [fileDict objectForKey: NSFileHFSTypeCode]; + return [fileDict fileHFSTypeCode]; } bool PlatformUtilities::isBundle (const String& filename) { #if JUCE_IPHONE - return false; // xxx can't find a sensible way to do this without trying to open the bundle.. + return false; // xxx can't find a sensible way to do this without trying to open the bundle.. #else - const ScopedAutoReleasePool pool; - return [[NSWorkspace sharedWorkspace] isFilePackageAtPath: juceStringToNS (filename)]; + const ScopedAutoReleasePool pool; + return [[NSWorkspace sharedWorkspace] isFilePackageAtPath: juceStringToNS (filename)]; #endif } @@ -261456,15 +239040,15 @@ END_JUCE_NAMESPACE - (void) applicationDidFinishLaunching: (UIApplication*) application { - String dummy; + String dummy; - if (! juce_intialisingApp->initialiseApp (dummy)) - exit (0); + if (! juce_intialisingApp->initialiseApp (dummy)) + exit (0); } - (void) applicationWillResignActive: (UIApplication*) application { - JUCEApplication::shutdownAppAndClearUp(); + JUCEApplication::shutdownAppAndClearUp(); } @end @@ -261473,24 +239057,24 @@ BEGIN_JUCE_NAMESPACE int juce_IPhoneMain (int argc, char* argv[], JUCEApplication* app) { - juce_intialisingApp = app; - return UIApplicationMain (argc, argv, nil, @"JuceAppStartupDelegate"); + juce_intialisingApp = app; + return UIApplicationMain (argc, argv, nil, @"JuceAppStartupDelegate"); } ScopedAutoReleasePool::ScopedAutoReleasePool() { - pool = [[NSAutoreleasePool alloc] init]; + pool = [[NSAutoreleasePool alloc] init]; } ScopedAutoReleasePool::~ScopedAutoReleasePool() { - [((NSAutoreleasePool*) pool) release]; + [((NSAutoreleasePool*) pool) release]; } void PlatformUtilities::beep() { - //xxx - //AudioServicesPlaySystemSound (); + //xxx + //AudioServicesPlaySystemSound (); } void PlatformUtilities::addItemToDock (const File& file) @@ -261504,7 +239088,7 @@ END_JUCE_NAMESPACE @interface JuceAlertBoxDelegate : NSObject { @public - bool clickedOk; + bool clickedOk; } - (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex; @@ -261515,8 +239099,8 @@ END_JUCE_NAMESPACE - (void) alertView: (UIAlertView*) alertView clickedButtonAtIndex: (NSInteger) buttonIndex { - clickedOk = (buttonIndex == 0); - alertView.hidden = true; + clickedOk = (buttonIndex == 0); + alertView.hidden = true; } @end @@ -261525,75 +239109,75 @@ BEGIN_JUCE_NAMESPACE // (This function is used directly by other bits of code) bool juce_iPhoneShowModalAlert (const String& title, - const String& bodyText, - NSString* okButtonText, - NSString* cancelButtonText) + const String& bodyText, + NSString* okButtonText, + NSString* cancelButtonText) { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - JuceAlertBoxDelegate* callback = [[JuceAlertBoxDelegate alloc] init]; + JuceAlertBoxDelegate* callback = [[JuceAlertBoxDelegate alloc] init]; - UIAlertView* alert = [[UIAlertView alloc] initWithTitle: juceStringToNS (title) - message: juceStringToNS (bodyText) - delegate: callback - cancelButtonTitle: okButtonText - otherButtonTitles: cancelButtonText, nil]; - [alert retain]; - [alert show]; + UIAlertView* alert = [[UIAlertView alloc] initWithTitle: juceStringToNS (title) + message: juceStringToNS (bodyText) + delegate: callback + cancelButtonTitle: okButtonText + otherButtonTitles: cancelButtonText, nil]; + [alert retain]; + [alert show]; - while (! alert.hidden && alert.superview != nil) - [[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; + while (! alert.hidden && alert.superview != nil) + [[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; - const bool result = callback->clickedOk; - [alert release]; - [callback release]; + const bool result = callback->clickedOk; + [alert release]; + [callback release]; - return result; + return result; } bool AlertWindow::showNativeDialogBox (const String& title, - const String& bodyText, - bool isOkCancel) + const String& bodyText, + bool isOkCancel) { - return juce_iPhoneShowModalAlert (title, bodyText, - @"OK", - isOkCancel ? @"Cancel" : nil); + return juce_iPhoneShowModalAlert (title, bodyText, + @"OK", + isOkCancel ? @"Cancel" : nil); } bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, const bool canMoveFiles) { - jassertfalse // no such thing on the iphone! - return false; + jassertfalse // no such thing on the iphone! + return false; } bool DragAndDropContainer::performExternalDragDropOfText (const String& text) { - jassertfalse // no such thing on the iphone! - return false; + jassertfalse // no such thing on the iphone! + return false; } void Desktop::setScreenSaverEnabled (const bool isEnabled) throw() { - [[UIApplication sharedApplication] setIdleTimerDisabled: ! isEnabled]; + [[UIApplication sharedApplication] setIdleTimerDisabled: ! isEnabled]; } bool Desktop::isScreenSaverEnabled() throw() { - return ! [[UIApplication sharedApplication] isIdleTimerDisabled]; + return ! [[UIApplication sharedApplication] isIdleTimerDisabled]; } -void juce_updateMultiMonitorInfo (Array & monitorCoords, const bool clipToWorkArea) throw() +void juce_updateMultiMonitorInfo (Array & monitorCoords, const bool clipToWorkArea) { - const ScopedAutoReleasePool pool; - monitorCoords.clear(); + const ScopedAutoReleasePool pool; + monitorCoords.clear(); - CGRect r = clipToWorkArea ? [[UIScreen mainScreen] applicationFrame] - : [[UIScreen mainScreen] bounds]; + CGRect r = clipToWorkArea ? [[UIScreen mainScreen] applicationFrame] + : [[UIScreen mainScreen] bounds]; - monitorCoords.add (Rectangle ((int) r.origin.x, - (int) r.origin.y, - (int) r.size.width, - (int) r.size.height)); + monitorCoords.add (Rectangle ((int) r.origin.x, + (int) r.origin.y, + (int) r.size.width, + (int) r.size.height)); } #endif @@ -261610,168 +239194,168 @@ void juce_updateMultiMonitorInfo (Array & monitorCoords, const bool c ScopedAutoReleasePool::ScopedAutoReleasePool() { - pool = [[NSAutoreleasePool alloc] init]; + pool = [[NSAutoreleasePool alloc] init]; } ScopedAutoReleasePool::~ScopedAutoReleasePool() { - [((NSAutoreleasePool*) pool) release]; + [((NSAutoreleasePool*) pool) release]; } void PlatformUtilities::beep() { - NSBeep(); + NSBeep(); } void PlatformUtilities::addItemToDock (const File& file) { - // check that it's not already there... - if (! juce_getOutputFromCommand ("defaults read com.apple.dock persistent-apps") - .containsIgnoreCase (file.getFullPathName())) - { - juce_runSystemCommand ("defaults write com.apple.dock persistent-apps -array-add \"tile-datafile-data_CFURLString" - + file.getFullPathName() + "_CFURLStringType0\""); + // check that it's not already there... + if (! juce_getOutputFromCommand ("defaults read com.apple.dock persistent-apps") + .containsIgnoreCase (file.getFullPathName())) + { + juce_runSystemCommand ("defaults write com.apple.dock persistent-apps -array-add \"tile-datafile-data_CFURLString" + + file.getFullPathName() + "_CFURLStringType0\""); - juce_runSystemCommand ("osascript -e \"tell application \\\"Dock\\\" to quit\""); - } + juce_runSystemCommand ("osascript -e \"tell application \\\"Dock\\\" to quit\""); + } } int PlatformUtilities::getOSXMinorVersionNumber() { - SInt32 versionMinor = 0; - OSErr err = Gestalt (gestaltSystemVersionMinor, &versionMinor); - (void) err; - jassert (err == noErr); - return (int) versionMinor; + SInt32 versionMinor = 0; + OSErr err = Gestalt (gestaltSystemVersionMinor, &versionMinor); + (void) err; + jassert (err == noErr); + return (int) versionMinor; } #if ! JUCE_ONLY_BUILD_CORE_LIBRARY bool AlertWindow::showNativeDialogBox (const String& title, - const String& bodyText, - bool isOkCancel) + const String& bodyText, + bool isOkCancel) { - const ScopedAutoReleasePool pool; - return NSRunAlertPanel (juceStringToNS (title), - juceStringToNS (bodyText), - @"Ok", - isOkCancel ? @"Cancel" : nil, - nil) == NSAlertDefaultReturn; + const ScopedAutoReleasePool pool; + return NSRunAlertPanel (juceStringToNS (title), + juceStringToNS (bodyText), + @"Ok", + isOkCancel ? @"Cancel" : nil, + nil) == NSAlertDefaultReturn; } bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, const bool canMoveFiles) { - if (files.size() == 0) - return false; + if (files.size() == 0) + return false; - Component* sourceComp = Component::getComponentUnderMouse(); + Component* sourceComp = Component::getComponentUnderMouse(); - if (sourceComp == 0) - { - jassertfalse // this method must be called in response to a - // component's mouseDrag event! - return false; - } + if (sourceComp == 0) + { + jassertfalse // this method must be called in response to a + // component's mouseDrag event! + return false; + } - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - NSView* view = (NSView*) sourceComp->getWindowHandle(); + NSView* view = (NSView*) sourceComp->getWindowHandle(); - if (view == 0) - return false; + if (view == 0) + return false; - NSPasteboard* pboard = [NSPasteboard pasteboardWithName: NSDragPboard]; - [pboard declareTypes: [NSArray arrayWithObject: NSFilenamesPboardType] - owner: nil]; + NSPasteboard* pboard = [NSPasteboard pasteboardWithName: NSDragPboard]; + [pboard declareTypes: [NSArray arrayWithObject: NSFilenamesPboardType] + owner: nil]; - NSMutableArray* filesArray = [NSMutableArray arrayWithCapacity: 4]; - for (int i = 0; i < files.size(); ++i) - [filesArray addObject: juceStringToNS (files[i])]; + NSMutableArray* filesArray = [NSMutableArray arrayWithCapacity: 4]; + for (int i = 0; i < files.size(); ++i) + [filesArray addObject: juceStringToNS (files[i])]; - [pboard setPropertyList: filesArray - forType: NSFilenamesPboardType]; + [pboard setPropertyList: filesArray + forType: NSFilenamesPboardType]; - NSPoint dragPosition = [view convertPoint: [[[view window] currentEvent] locationInWindow] - fromView: nil]; - dragPosition.x -= 16; - dragPosition.y -= 16; + NSPoint dragPosition = [view convertPoint: [[[view window] currentEvent] locationInWindow] + fromView: nil]; + dragPosition.x -= 16; + dragPosition.y -= 16; - [view dragImage: [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (files[0])] - at: dragPosition - offset: NSMakeSize (0, 0) - event: [[view window] currentEvent] - pasteboard: pboard - source: view - slideBack: YES]; + [view dragImage: [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (files[0])] + at: dragPosition + offset: NSMakeSize (0, 0) + event: [[view window] currentEvent] + pasteboard: pboard + source: view + slideBack: YES]; - return true; + return true; } bool DragAndDropContainer::performExternalDragDropOfText (const String& text) { - jassertfalse // not implemented! - return false; + jassertfalse // not implemented! + return false; } bool Desktop::canUseSemiTransparentWindows() throw() { - return true; + return true; } void Desktop::getMousePosition (int& x, int& y) throw() { - const ScopedAutoReleasePool pool; - const NSPoint p ([NSEvent mouseLocation]); - x = roundFloatToInt (p.x); - y = roundFloatToInt ([[[NSScreen screens] objectAtIndex: 0] frame].size.height - p.y); + const ScopedAutoReleasePool pool; + const NSPoint p ([NSEvent mouseLocation]); + x = roundToInt (p.x); + y = roundToInt ([[[NSScreen screens] objectAtIndex: 0] frame].size.height - p.y); } void Desktop::setMousePosition (int x, int y) throw() { - // this rubbish needs to be done around the warp call, to avoid causing a - // bizarre glitch.. - CGAssociateMouseAndMouseCursorPosition (false); - CGWarpMouseCursorPosition (CGPointMake (x, y)); - CGAssociateMouseAndMouseCursorPosition (true); + // this rubbish needs to be done around the warp call, to avoid causing a + // bizarre glitch.. + CGAssociateMouseAndMouseCursorPosition (false); + CGWarpMouseCursorPosition (CGPointMake (x, y)); + CGAssociateMouseAndMouseCursorPosition (true); } #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 class ScreenSaverDefeater : public Timer, - public DeletedAtShutdown + public DeletedAtShutdown { public: - ScreenSaverDefeater() throw() - { - startTimer (10000); - timerCallback(); - } + ScreenSaverDefeater() throw() + { + startTimer (10000); + timerCallback(); + } - ~ScreenSaverDefeater() {} + ~ScreenSaverDefeater() {} - void timerCallback() - { - if (Process::isForegroundProcess()) - UpdateSystemActivity (UsrActivity); - } + void timerCallback() + { + if (Process::isForegroundProcess()) + UpdateSystemActivity (UsrActivity); + } }; static ScreenSaverDefeater* screenSaverDefeater = 0; void Desktop::setScreenSaverEnabled (const bool isEnabled) throw() { - if (isEnabled) - { - deleteAndZero (screenSaverDefeater); - } - else if (screenSaverDefeater == 0) - { - screenSaverDefeater = new ScreenSaverDefeater(); - } + if (isEnabled) + { + deleteAndZero (screenSaverDefeater); + } + else if (screenSaverDefeater == 0) + { + screenSaverDefeater = new ScreenSaverDefeater(); + } } bool Desktop::isScreenSaverEnabled() throw() { - return screenSaverDefeater == 0; + return screenSaverDefeater == 0; } #else @@ -261780,57 +239364,57 @@ static IOPMAssertionID screenSaverDisablerID = 0; void Desktop::setScreenSaverEnabled (const bool isEnabled) throw() { - if (isEnabled) - { - if (screenSaverDisablerID != 0) - { - IOPMAssertionRelease (screenSaverDisablerID); - screenSaverDisablerID = 0; - } - } - else - { - if (screenSaverDisablerID == 0) - { + if (isEnabled) + { + if (screenSaverDisablerID != 0) + { + IOPMAssertionRelease (screenSaverDisablerID); + screenSaverDisablerID = 0; + } + } + else + { + if (screenSaverDisablerID == 0) + { #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - IOPMAssertionCreateWithName (kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, - CFSTR ("Juce"), &screenSaverDisablerID); + IOPMAssertionCreateWithName (kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, + CFSTR ("Juce"), &screenSaverDisablerID); #else - IOPMAssertionCreate (kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, - &screenSaverDisablerID); + IOPMAssertionCreate (kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, + &screenSaverDisablerID); #endif - } - } + } + } } bool Desktop::isScreenSaverEnabled() throw() { - return screenSaverDisablerID == 0; + return screenSaverDisablerID == 0; } #endif -void juce_updateMultiMonitorInfo (Array & monitorCoords, const bool clipToWorkArea) throw() +void juce_updateMultiMonitorInfo (Array & monitorCoords, const bool clipToWorkArea) { - const ScopedAutoReleasePool pool; - monitorCoords.clear(); - NSArray* screens = [NSScreen screens]; - const float mainScreenBottom = [[[NSScreen screens] objectAtIndex: 0] frame].size.height; + const ScopedAutoReleasePool pool; + monitorCoords.clear(); + NSArray* screens = [NSScreen screens]; + const CGFloat mainScreenBottom = [[[NSScreen screens] objectAtIndex: 0] frame].size.height; - for (unsigned int i = 0; i < [screens count]; ++i) - { - NSScreen* s = (NSScreen*) [screens objectAtIndex: i]; + for (unsigned int i = 0; i < [screens count]; ++i) + { + NSScreen* s = (NSScreen*) [screens objectAtIndex: i]; - NSRect r = clipToWorkArea ? [s visibleFrame] - : [s frame]; + NSRect r = clipToWorkArea ? [s visibleFrame] + : [s frame]; - monitorCoords.add (Rectangle ((int) r.origin.x, - (int) (mainScreenBottom - (r.origin.y + r.size.height)), - (int) r.size.width, - (int) r.size.height)); - } + monitorCoords.add (Rectangle ((int) r.origin.x, + (int) (mainScreenBottom - (r.origin.y + r.size.height)), + (int) r.size.width, + (int) r.size.height)); + } - jassert (monitorCoords.size() > 0); + jassert (monitorCoords.size() > 0); } #endif @@ -261847,38 +239431,38 @@ void juce_updateMultiMonitorInfo (Array & monitorCoords, const bool c void Logger::outputDebugString (const String& text) throw() { - fputs (text.toUTF8(), stderr); - fputs ("\n", stderr); + fputs (text.toUTF8(), stderr); + fputs ("\n", stderr); } void Logger::outputDebugPrintf (const tchar* format, ...) throw() { - String text; - va_list args; - va_start (args, format); - text.vprintf (format, args); - outputDebugString (text); + String text; + va_list args; + va_start (args, format); + text.vprintf (format, args); + outputDebugString (text); } bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger() { - static char testResult = 0; + static char testResult = 0; - if (testResult == 0) - { - struct kinfo_proc info; - int m[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() }; - size_t sz = sizeof (info); - sysctl (m, 4, &info, &sz, 0, 0); - testResult = ((info.kp_proc.p_flag & P_TRACED) != 0) ? 1 : -1; - } + if (testResult == 0) + { + struct kinfo_proc info; + int m[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() }; + size_t sz = sizeof (info); + sysctl (m, 4, &info, &sz, 0, 0); + testResult = ((info.kp_proc.p_flag & P_TRACED) != 0) ? 1 : -1; + } - return testResult > 0; + return testResult > 0; } bool JUCE_CALLTYPE Process::isRunningUnderDebugger() { - return juce_isRunningUnderDebugger(); + return juce_isRunningUnderDebugger(); } #endif @@ -261897,12 +239481,12 @@ bool JUCE_CALLTYPE Process::isRunningUnderDebugger() #define NEW_CGFONT_FUNCTIONS_UNAVAILABLE (CGFontCreateWithFontName == 0) #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 - #define SUPPORT_ONLY_10_4_FONTS 1 + #define SUPPORT_ONLY_10_4_FONTS 1 #endif END_JUCE_NAMESPACE @interface NSFont (PrivateHack) - - (NSGlyph) _defaultGlyphForChar: (unichar) theChar; + - (NSGlyph) _defaultGlyphForChar: (unichar) theChar; @end BEGIN_JUCE_NAMESPACE #endif @@ -261911,471 +239495,471 @@ class MacTypeface : public Typeface { public: - MacTypeface (const Font& font) - : Typeface (font.getTypefaceName()) - { - const ScopedAutoReleasePool pool; - renderingTransform = CGAffineTransformIdentity; + MacTypeface (const Font& font) + : Typeface (font.getTypefaceName()) + { + const ScopedAutoReleasePool pool; + renderingTransform = CGAffineTransformIdentity; - bool needsItalicTransform = false; + bool needsItalicTransform = false; #if JUCE_IPHONE - NSString* fontName = juceStringToNS (font.getTypefaceName()); + NSString* fontName = juceStringToNS (font.getTypefaceName()); - if (font.isItalic() || font.isBold()) - { - NSArray* familyFonts = [UIFont fontNamesForFamilyName: juceStringToNS (font.getTypefaceName())]; + if (font.isItalic() || font.isBold()) + { + NSArray* familyFonts = [UIFont fontNamesForFamilyName: juceStringToNS (font.getTypefaceName())]; - for (NSString* i in familyFonts) - { - const String fn (nsStringToJuce (i)); - const String afterDash (fn.fromFirstOccurrenceOf (T("-"), false, false)); + for (NSString* i in familyFonts) + { + const String fn (nsStringToJuce (i)); + const String afterDash (fn.fromFirstOccurrenceOf (T("-"), false, false)); - const bool probablyBold = afterDash.containsIgnoreCase (T("bold")) || fn.endsWithIgnoreCase (T("bold")); - const bool probablyItalic = afterDash.containsIgnoreCase (T("oblique")) - || afterDash.containsIgnoreCase (T("italic")) - || fn.endsWithIgnoreCase (T("oblique")) - || fn.endsWithIgnoreCase (T("italic")); + const bool probablyBold = afterDash.containsIgnoreCase (T("bold")) || fn.endsWithIgnoreCase (T("bold")); + const bool probablyItalic = afterDash.containsIgnoreCase (T("oblique")) + || afterDash.containsIgnoreCase (T("italic")) + || fn.endsWithIgnoreCase (T("oblique")) + || fn.endsWithIgnoreCase (T("italic")); - if (probablyBold == font.isBold() - && probablyItalic == font.isItalic()) - { - fontName = i; - needsItalicTransform = false; - break; - } - else if (probablyBold && (! probablyItalic) && probablyBold == font.isBold()) - { - fontName = i; - needsItalicTransform = true; // not ideal, so carry on in case we find a better one - } - } + if (probablyBold == font.isBold() + && probablyItalic == font.isItalic()) + { + fontName = i; + needsItalicTransform = false; + break; + } + else if (probablyBold && (! probablyItalic) && probablyBold == font.isBold()) + { + fontName = i; + needsItalicTransform = true; // not ideal, so carry on in case we find a better one + } + } - if (needsItalicTransform) - renderingTransform.c = 0.15f; - } + if (needsItalicTransform) + renderingTransform.c = 0.15f; + } - fontRef = CGFontCreateWithFontName ((CFStringRef) fontName); + fontRef = CGFontCreateWithFontName ((CFStringRef) fontName); - const int ascender = abs (CGFontGetAscent (fontRef)); - const float totalHeight = ascender + abs (CGFontGetDescent (fontRef)); - ascent = ascender / totalHeight; - unitsToHeightScaleFactor = 1.0f / totalHeight; - fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / totalHeight; + const int ascender = abs (CGFontGetAscent (fontRef)); + const float totalHeight = ascender + abs (CGFontGetDescent (fontRef)); + ascent = ascender / totalHeight; + unitsToHeightScaleFactor = 1.0f / totalHeight; + fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / totalHeight; #else - nsFont = [NSFont fontWithName: juceStringToNS (font.getTypefaceName()) size: 1024]; + nsFont = [NSFont fontWithName: juceStringToNS (font.getTypefaceName()) size: 1024]; - if (font.isItalic()) - { - NSFont* newFont = [[NSFontManager sharedFontManager] convertFont: nsFont - toHaveTrait: NSItalicFontMask]; + if (font.isItalic()) + { + NSFont* newFont = [[NSFontManager sharedFontManager] convertFont: nsFont + toHaveTrait: NSItalicFontMask]; - if (newFont == nsFont) - needsItalicTransform = true; // couldn't find a proper italic version, so fake it with a transform.. + if (newFont == nsFont) + needsItalicTransform = true; // couldn't find a proper italic version, so fake it with a transform.. - nsFont = newFont; - } + nsFont = newFont; + } - if (font.isBold()) - nsFont = [[NSFontManager sharedFontManager] convertFont: nsFont toHaveTrait: NSBoldFontMask]; + if (font.isBold()) + nsFont = [[NSFontManager sharedFontManager] convertFont: nsFont toHaveTrait: NSBoldFontMask]; - [nsFont retain]; + [nsFont retain]; - ascent = fabsf ([nsFont ascender]); - float totalSize = ascent + fabsf ([nsFont descender]); - ascent /= totalSize; + ascent = fabsf ((float) [nsFont ascender]); + float totalSize = ascent + fabsf ((float) [nsFont descender]); + ascent /= totalSize; - pathTransform = AffineTransform::identity.scale (1.0f / totalSize, 1.0f / totalSize); + pathTransform = AffineTransform::identity.scale (1.0f / totalSize, 1.0f / totalSize); - if (needsItalicTransform) - { - pathTransform = pathTransform.sheared (-0.15f, 0.0f); - renderingTransform.c = 0.15f; - } + if (needsItalicTransform) + { + pathTransform = pathTransform.sheared (-0.15f, 0.0f); + renderingTransform.c = 0.15f; + } #if SUPPORT_ONLY_10_4_FONTS - ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); + ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); - if (atsFont == 0) - atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); + if (atsFont == 0) + atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); - fontRef = CGFontCreateWithPlatformFont ((void*) &atsFont); + fontRef = CGFontCreateWithPlatformFont ((void*) &atsFont); - const float totalHeight = fabsf ([nsFont ascender]) + fabsf([nsFont descender]); - unitsToHeightScaleFactor = 1.0f / totalHeight; - fontHeightToCGSizeFactor = 1024.0f / totalHeight; + const float totalHeight = fabsf ([nsFont ascender]) + fabsf([nsFont descender]); + unitsToHeightScaleFactor = 1.0f / totalHeight; + fontHeightToCGSizeFactor = 1024.0f / totalHeight; #else #if SUPPORT_10_4_FONTS - if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) - { - ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); + if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) + { + ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); - if (atsFont == 0) - atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); + if (atsFont == 0) + atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); - fontRef = CGFontCreateWithPlatformFont ((void*) &atsFont); + fontRef = CGFontCreateWithPlatformFont ((void*) &atsFont); - const float totalHeight = fabsf ([nsFont ascender]) + fabsf([nsFont descender]); - unitsToHeightScaleFactor = 1.0f / totalHeight; - fontHeightToCGSizeFactor = 1024.0f / totalHeight; - } - else + const float totalHeight = fabsf ([nsFont ascender]) + fabsf([nsFont descender]); + unitsToHeightScaleFactor = 1.0f / totalHeight; + fontHeightToCGSizeFactor = 1024.0f / totalHeight; + } + else #endif - { - fontRef = CGFontCreateWithFontName ((CFStringRef) [nsFont fontName]); + { + fontRef = CGFontCreateWithFontName ((CFStringRef) [nsFont fontName]); - const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef)); - unitsToHeightScaleFactor = 1.0f / totalHeight; - fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / (float) totalHeight; - } + const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef)); + unitsToHeightScaleFactor = 1.0f / totalHeight; + fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / (float) totalHeight; + } #endif #endif - } + } - ~MacTypeface() - { + ~MacTypeface() + { #if ! JUCE_IPHONE - [nsFont release]; + [nsFont release]; #endif - if (fontRef != 0) - CGFontRelease (fontRef); - } + if (fontRef != 0) + CGFontRelease (fontRef); + } - float getAscent() const - { - return ascent; - } + float getAscent() const + { + return ascent; + } - float getDescent() const - { - return 1.0f - ascent; - } + float getDescent() const + { + return 1.0f - ascent; + } - float getStringWidth (const String& text) - { - if (fontRef == 0 || text.isEmpty()) - return 0; + float getStringWidth (const String& text) + { + if (fontRef == 0 || text.isEmpty()) + return 0; - const int length = text.length(); - HeapBlock glyphs; - createGlyphsForString (text, length, glyphs); + const int length = text.length(); + HeapBlock glyphs; + createGlyphsForString (text, length, glyphs); - float x = 0; + float x = 0; #if SUPPORT_ONLY_10_4_FONTS - HeapBlock advances (length); - [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; + HeapBlock advances (length); + [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; - for (int i = 0; i < length; ++i) - x += advances[i].width; + for (int i = 0; i < length; ++i) + x += advances[i].width; #else #if SUPPORT_10_4_FONTS - if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) - { - HeapBlock advances (length); - [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; + if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) + { + HeapBlock advances (length); + [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; - for (int i = 0; i < length; ++i) - x += advances[i].width; - } - else + for (int i = 0; i < length; ++i) + x += advances[i].width; + } + else #endif - { - HeapBlock advances (length); + { + HeapBlock advances (length); - if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances)) - for (int i = 0; i < length; ++i) - x += advances[i]; - } + if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances)) + for (int i = 0; i < length; ++i) + x += advances[i]; + } #endif - return x * unitsToHeightScaleFactor; - } + return x * unitsToHeightScaleFactor; + } - void getGlyphPositions (const String& text, Array & resultGlyphs, Array & xOffsets) - { - xOffsets.add (0); + void getGlyphPositions (const String& text, Array & resultGlyphs, Array & xOffsets) + { + xOffsets.add (0); - if (fontRef == 0 || text.isEmpty()) - return; + if (fontRef == 0 || text.isEmpty()) + return; - const int length = text.length(); - HeapBlock glyphs; - createGlyphsForString (text, length, glyphs); + const int length = text.length(); + HeapBlock glyphs; + createGlyphsForString (text, length, glyphs); #if SUPPORT_ONLY_10_4_FONTS - HeapBlock advances (length); - [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; + HeapBlock advances (length); + [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; - int x = 0; - for (int i = 0; i < length; ++i) - { - x += advances[i].width; - xOffsets.add (x * unitsToHeightScaleFactor); - resultGlyphs.add (((NSGlyph*) glyphs)[i]); - } + int x = 0; + for (int i = 0; i < length; ++i) + { + x += advances[i].width; + xOffsets.add (x * unitsToHeightScaleFactor); + resultGlyphs.add (((NSGlyph*) glyphs)[i]); + } #else #if SUPPORT_10_4_FONTS - if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) - { - HeapBlock advances (length); - [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; + if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) + { + HeapBlock advances (length); + [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; - float x = 0; - for (int i = 0; i < length; ++i) - { - x += advances[i].width; - xOffsets.add (x * unitsToHeightScaleFactor); - resultGlyphs.add (((NSGlyph*) glyphs)[i]); - } - } - else + float x = 0; + for (int i = 0; i < length; ++i) + { + x += advances[i].width; + xOffsets.add (x * unitsToHeightScaleFactor); + resultGlyphs.add (((NSGlyph*) glyphs)[i]); + } + } + else #endif - { - HeapBlock advances (length); + { + HeapBlock advances (length); - if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances)) - { - int x = 0; - for (int i = 0; i < length; ++i) - { - x += advances [i]; - xOffsets.add (x * unitsToHeightScaleFactor); - resultGlyphs.add (glyphs[i]); - } - } - } + if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances)) + { + int x = 0; + for (int i = 0; i < length; ++i) + { + x += advances [i]; + xOffsets.add (x * unitsToHeightScaleFactor); + resultGlyphs.add (glyphs[i]); + } + } + } #endif - } + } - bool getOutlineForGlyph (int glyphNumber, Path& path) - { + bool getOutlineForGlyph (int glyphNumber, Path& path) + { #if JUCE_IPHONE - return false; + return false; #else - if (nsFont == 0) - return false; + if (nsFont == 0) + return false; - // we might need to apply a transform to the path, so it mustn't have anything else in it - jassert (path.isEmpty()); + // we might need to apply a transform to the path, so it mustn't have anything else in it + jassert (path.isEmpty()); - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - NSBezierPath* bez = [NSBezierPath bezierPath]; - [bez moveToPoint: NSMakePoint (0, 0)]; - [bez appendBezierPathWithGlyph: (NSGlyph) glyphNumber - inFont: nsFont]; + NSBezierPath* bez = [NSBezierPath bezierPath]; + [bez moveToPoint: NSMakePoint (0, 0)]; + [bez appendBezierPathWithGlyph: (NSGlyph) glyphNumber + inFont: nsFont]; - for (int i = 0; i < [bez elementCount]; ++i) - { - NSPoint p[3]; - switch ([bez elementAtIndex: i associatedPoints: p]) - { - case NSMoveToBezierPathElement: - path.startNewSubPath (p[0].x, -p[0].y); - break; - case NSLineToBezierPathElement: - path.lineTo (p[0].x, -p[0].y); - break; - case NSCurveToBezierPathElement: - path.cubicTo (p[0].x, -p[0].y, p[1].x, -p[1].y, p[2].x, -p[2].y); - break; - case NSClosePathBezierPathElement: - path.closeSubPath(); - break; - default: - jassertfalse - break; - } - } + for (int i = 0; i < [bez elementCount]; ++i) + { + NSPoint p[3]; + switch ([bez elementAtIndex: i associatedPoints: p]) + { + case NSMoveToBezierPathElement: + path.startNewSubPath ((float) p[0].x, (float) -p[0].y); + break; + case NSLineToBezierPathElement: + path.lineTo ((float) p[0].x, (float) -p[0].y); + break; + case NSCurveToBezierPathElement: + path.cubicTo ((float) p[0].x, (float) -p[0].y, (float) p[1].x, (float) -p[1].y, (float) p[2].x, (float) -p[2].y); + break; + case NSClosePathBezierPathElement: + path.closeSubPath(); + break; + default: + jassertfalse + break; + } + } - path.applyTransform (pathTransform); - return true; + path.applyTransform (pathTransform); + return true; #endif - } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - CGFontRef fontRef; - float fontHeightToCGSizeFactor; - CGAffineTransform renderingTransform; + CGFontRef fontRef; + float fontHeightToCGSizeFactor; + CGAffineTransform renderingTransform; private: - float ascent, unitsToHeightScaleFactor; + float ascent, unitsToHeightScaleFactor; #if JUCE_IPHONE #else - NSFont* nsFont; - AffineTransform pathTransform; + NSFont* nsFont; + AffineTransform pathTransform; #endif - void createGlyphsForString (const juce_wchar* const text, const int length, HeapBlock & glyphs) - { + void createGlyphsForString (const juce_wchar* const text, const int length, HeapBlock & glyphs) + { #if SUPPORT_10_4_FONTS #if ! SUPPORT_ONLY_10_4_FONTS - if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) + if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) #endif - { - glyphs.malloc (sizeof (NSGlyph) * length, 1); - NSGlyph* const g = (NSGlyph*) glyphs; + { + glyphs.malloc (sizeof (NSGlyph) * length, 1); + NSGlyph* const g = (NSGlyph*) glyphs; - for (int i = 0; i < length; ++i) - g[i] = (NSGlyph) [nsFont _defaultGlyphForChar: text[i]]; + for (int i = 0; i < length; ++i) + g[i] = (NSGlyph) [nsFont _defaultGlyphForChar: text[i]]; - return; - } + return; + } #endif #if ! SUPPORT_ONLY_10_4_FONTS - if (charToGlyphMapper == 0) - charToGlyphMapper = new CharToGlyphMapper (fontRef); + if (charToGlyphMapper == 0) + charToGlyphMapper = new CharToGlyphMapper (fontRef); - glyphs.malloc (length); + glyphs.malloc (length); - for (int i = 0; i < length; ++i) - glyphs[i] = (CGGlyph) charToGlyphMapper->getGlyphForCharacter (text[i]); + for (int i = 0; i < length; ++i) + glyphs[i] = (CGGlyph) charToGlyphMapper->getGlyphForCharacter (text[i]); #endif - } + } #if ! SUPPORT_ONLY_10_4_FONTS - // Reads a CGFontRef's character map table to convert unicode into glyph numbers - class CharToGlyphMapper - { - public: - CharToGlyphMapper (CGFontRef fontRef) - : segCount (0), endCode (0), startCode (0), idDelta (0), - idRangeOffset (0), glyphIndexes (0) - { - CFDataRef cmapTable = CGFontCopyTableForTag (fontRef, 'cmap'); + // Reads a CGFontRef's character map table to convert unicode into glyph numbers + class CharToGlyphMapper + { + public: + CharToGlyphMapper (CGFontRef fontRef) + : segCount (0), endCode (0), startCode (0), idDelta (0), + idRangeOffset (0), glyphIndexes (0) + { + CFDataRef cmapTable = CGFontCopyTableForTag (fontRef, 'cmap'); - if (cmapTable != 0) - { - const int numSubtables = getValue16 (cmapTable, 2); + if (cmapTable != 0) + { + const int numSubtables = getValue16 (cmapTable, 2); - for (int i = 0; i < numSubtables; ++i) - { - if (getValue16 (cmapTable, i * 8 + 4) == 0) // check for platform ID of 0 - { - const int offset = getValue32 (cmapTable, i * 8 + 8); + for (int i = 0; i < numSubtables; ++i) + { + if (getValue16 (cmapTable, i * 8 + 4) == 0) // check for platform ID of 0 + { + const int offset = getValue32 (cmapTable, i * 8 + 8); - if (getValue16 (cmapTable, offset) == 4) // check that it's format 4.. - { - const int length = getValue16 (cmapTable, offset + 2); - const int segCountX2 = getValue16 (cmapTable, offset + 6); - segCount = segCountX2 / 2; - const int endCodeOffset = offset + 14; - const int startCodeOffset = endCodeOffset + 2 + segCountX2; - const int idDeltaOffset = startCodeOffset + segCountX2; - const int idRangeOffsetOffset = idDeltaOffset + segCountX2; - const int glyphIndexesOffset = idRangeOffsetOffset + segCountX2; + if (getValue16 (cmapTable, offset) == 4) // check that it's format 4.. + { + const int length = getValue16 (cmapTable, offset + 2); + const int segCountX2 = getValue16 (cmapTable, offset + 6); + segCount = segCountX2 / 2; + const int endCodeOffset = offset + 14; + const int startCodeOffset = endCodeOffset + 2 + segCountX2; + const int idDeltaOffset = startCodeOffset + segCountX2; + const int idRangeOffsetOffset = idDeltaOffset + segCountX2; + const int glyphIndexesOffset = idRangeOffsetOffset + segCountX2; - endCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + endCodeOffset, segCountX2); - startCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + startCodeOffset, segCountX2); - idDelta = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idDeltaOffset, segCountX2); - idRangeOffset = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idRangeOffsetOffset, segCountX2); - glyphIndexes = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + glyphIndexesOffset, offset + length - glyphIndexesOffset); - } + endCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + endCodeOffset, segCountX2); + startCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + startCodeOffset, segCountX2); + idDelta = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idDeltaOffset, segCountX2); + idRangeOffset = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idRangeOffsetOffset, segCountX2); + glyphIndexes = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + glyphIndexesOffset, offset + length - glyphIndexesOffset); + } - break; - } - } + break; + } + } - CFRelease (cmapTable); - } - } + CFRelease (cmapTable); + } + } - ~CharToGlyphMapper() - { - if (endCode != 0) - { - CFRelease (endCode); - CFRelease (startCode); - CFRelease (idDelta); - CFRelease (idRangeOffset); - CFRelease (glyphIndexes); - } - } + ~CharToGlyphMapper() + { + if (endCode != 0) + { + CFRelease (endCode); + CFRelease (startCode); + CFRelease (idDelta); + CFRelease (idRangeOffset); + CFRelease (glyphIndexes); + } + } - int getGlyphForCharacter (const juce_wchar c) const - { - for (int i = 0; i < segCount; ++i) - { - if (getValue16 (endCode, i * 2) >= c) - { - const int start = getValue16 (startCode, i * 2); - if (start > c) - break; + int getGlyphForCharacter (const juce_wchar c) const + { + for (int i = 0; i < segCount; ++i) + { + if (getValue16 (endCode, i * 2) >= c) + { + const int start = getValue16 (startCode, i * 2); + if (start > c) + break; - const int delta = getValue16 (idDelta, i * 2); - const int rangeOffset = getValue16 (idRangeOffset, i * 2); + const int delta = getValue16 (idDelta, i * 2); + const int rangeOffset = getValue16 (idRangeOffset, i * 2); - if (rangeOffset == 0) - return delta + c; - else - return getValue16 (glyphIndexes, 2 * ((rangeOffset / 2) + (c - start) - (segCount - i))); - } - } + if (rangeOffset == 0) + return delta + c; + else + return getValue16 (glyphIndexes, 2 * ((rangeOffset / 2) + (c - start) - (segCount - i))); + } + } - // If we failed to find it "properly", this dodgy fall-back seems to do the trick for most fonts! - return jmax (-1, c - 29); - } + // If we failed to find it "properly", this dodgy fall-back seems to do the trick for most fonts! + return jmax (-1, c - 29); + } - private: - int segCount; - CFDataRef endCode, startCode, idDelta, idRangeOffset, glyphIndexes; + private: + int segCount; + CFDataRef endCode, startCode, idDelta, idRangeOffset, glyphIndexes; - static uint16 getValue16 (CFDataRef data, const int index) - { - return CFSwapInt16BigToHost (*(UInt16*) (CFDataGetBytePtr (data) + index)); - } + static uint16 getValue16 (CFDataRef data, const int index) + { + return CFSwapInt16BigToHost (*(UInt16*) (CFDataGetBytePtr (data) + index)); + } - static uint32 getValue32 (CFDataRef data, const int index) - { - return CFSwapInt32BigToHost (*(UInt32*) (CFDataGetBytePtr (data) + index)); - } - }; + static uint32 getValue32 (CFDataRef data, const int index) + { + return CFSwapInt32BigToHost (*(UInt32*) (CFDataGetBytePtr (data) + index)); + } + }; - ScopedPointer charToGlyphMapper; + ScopedPointer charToGlyphMapper; #endif }; const Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) { - return new MacTypeface (font); + return new MacTypeface (font); } const StringArray Font::findAllTypefaceNames() throw() { - StringArray names; + StringArray names; - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; #if JUCE_IPHONE - NSArray* fonts = [UIFont familyNames]; + NSArray* fonts = [UIFont familyNames]; #else - NSArray* fonts = [[NSFontManager sharedFontManager] availableFontFamilies]; + NSArray* fonts = [[NSFontManager sharedFontManager] availableFontFamilies]; #endif - for (unsigned int i = 0; i < [fonts count]; ++i) - names.add (nsStringToJuce ((NSString*) [fonts objectAtIndex: i])); + for (unsigned int i = 0; i < [fonts count]; ++i) + names.add (nsStringToJuce ((NSString*) [fonts objectAtIndex: i])); - names.sort (true); - return names; + names.sort (true); + return names; } void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed) throw() { #if JUCE_IPHONE - defaultSans = "Helvetica"; - defaultSerif = "Times New Roman"; - defaultFixed = "Courier New"; + defaultSans = "Helvetica"; + defaultSerif = "Times New Roman"; + defaultFixed = "Courier New"; #else - defaultSans = "Lucida Grande"; - defaultSerif = "Times New Roman"; - defaultFixed = "Monaco"; + defaultSans = "Lucida Grande"; + defaultSerif = "Times New Roman"; + defaultFixed = "Monaco"; #endif } @@ -262391,688 +239975,688 @@ class CoreGraphicsImage : public Image { public: - CoreGraphicsImage (const PixelFormat format_, - const int imageWidth_, - const int imageHeight_, - const bool clearImage) - : Image (format_, imageWidth_, imageHeight_, clearImage) - { - CGColorSpaceRef colourSpace = format == Image::SingleChannel ? CGColorSpaceCreateDeviceGray() - : CGColorSpaceCreateDeviceRGB(); + CoreGraphicsImage (const PixelFormat format_, + const int imageWidth_, + const int imageHeight_, + const bool clearImage) + : Image (format_, imageWidth_, imageHeight_, clearImage) + { + CGColorSpaceRef colourSpace = format == Image::SingleChannel ? CGColorSpaceCreateDeviceGray() + : CGColorSpaceCreateDeviceRGB(); - context = CGBitmapContextCreate (imageData, imageWidth, imageHeight, 8, lineStride, - colourSpace, getCGImageFlags (*this)); + context = CGBitmapContextCreate (imageData, imageWidth, imageHeight, 8, lineStride, + colourSpace, getCGImageFlags (*this)); - CGColorSpaceRelease (colourSpace); - } + CGColorSpaceRelease (colourSpace); + } - ~CoreGraphicsImage() - { - CGContextRelease (context); - } + ~CoreGraphicsImage() + { + CGContextRelease (context); + } - LowLevelGraphicsContext* createLowLevelContext(); + LowLevelGraphicsContext* createLowLevelContext(); - static CGImageRef createImage (const Image& juceImage, const bool forAlpha, CGColorSpaceRef colourSpace) - { - const CoreGraphicsImage* nativeImage = dynamic_cast (&juceImage); + static CGImageRef createImage (const Image& juceImage, const bool forAlpha, CGColorSpaceRef colourSpace) + { + const CoreGraphicsImage* nativeImage = dynamic_cast (&juceImage); - if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha)) - { - return CGBitmapContextCreateImage (nativeImage->context); - } - else - { - const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight()); + if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha)) + { + return CGBitmapContextCreateImage (nativeImage->context); + } + else + { + const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight()); - CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.pixelStride, 0); + CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.pixelStride, 0); - CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height, - 8, srcData.pixelStride * 8, srcData.lineStride, - colourSpace, getCGImageFlags (juceImage), provider, - 0, true, kCGRenderingIntentDefault); + CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height, + 8, srcData.pixelStride * 8, srcData.lineStride, + colourSpace, getCGImageFlags (juceImage), provider, + 0, true, kCGRenderingIntentDefault); - CGDataProviderRelease (provider); - return imageRef; - } - } + CGDataProviderRelease (provider); + return imageRef; + } + } #if JUCE_MAC - static NSImage* createNSImage (const Image& image) - { - const ScopedAutoReleasePool pool; + static NSImage* createNSImage (const Image& image) + { + const ScopedAutoReleasePool pool; - NSImage* im = [[NSImage alloc] init]; - [im setSize: NSMakeSize (image.getWidth(), image.getHeight())]; - [im lockFocus]; + NSImage* im = [[NSImage alloc] init]; + [im setSize: NSMakeSize (image.getWidth(), image.getHeight())]; + [im lockFocus]; - CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); - CGImageRef imageRef = createImage (image, false, colourSpace); - CGColorSpaceRelease (colourSpace); + CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); + CGImageRef imageRef = createImage (image, false, colourSpace); + CGColorSpaceRelease (colourSpace); - CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; - CGContextDrawImage (cg, CGRectMake (0, 0, image.getWidth(), image.getHeight()), imageRef); + CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; + CGContextDrawImage (cg, CGRectMake (0, 0, image.getWidth(), image.getHeight()), imageRef); - CGImageRelease (imageRef); - [im unlockFocus]; + CGImageRelease (imageRef); + [im unlockFocus]; - return im; - } + return im; + } #endif - CGContextRef context; + CGContextRef context; private: - static CGBitmapInfo getCGImageFlags (const Image& image) - { + static CGBitmapInfo getCGImageFlags (const Image& image) + { #if JUCE_BIG_ENDIAN - return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault; + return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault; #else - return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault; + return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault; #endif - } + } }; Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage) { #if USE_COREGRAPHICS_RENDERING - return new CoreGraphicsImage (format == RGB ? ARGB : format, imageWidth, imageHeight, clearImage); + return new CoreGraphicsImage (format == RGB ? ARGB : format, imageWidth, imageHeight, clearImage); #else - return new Image (format, imageWidth, imageHeight, clearImage); + return new Image (format, imageWidth, imageHeight, clearImage); #endif } class CoreGraphicsContext : public LowLevelGraphicsContext { public: - CoreGraphicsContext (CGContextRef context_, const float flipHeight_) - : context (context_), - flipHeight (flipHeight_), - numGradientLookupEntries (0) - { - CGContextRetain (context); - CGContextSaveGState(context); - CGContextSetShouldSmoothFonts (context, true); - CGContextSetShouldAntialias (context, true); - CGContextSetBlendMode (context, kCGBlendModeNormal); - rgbColourSpace = CGColorSpaceCreateDeviceRGB(); - greyColourSpace = CGColorSpaceCreateDeviceGray(); - gradientCallbacks.version = 0; - gradientCallbacks.evaluate = gradientCallback; - gradientCallbacks.releaseInfo = 0; - state = new SavedState(); - } + CoreGraphicsContext (CGContextRef context_, const float flipHeight_) + : context (context_), + flipHeight (flipHeight_), + numGradientLookupEntries (0) + { + CGContextRetain (context); + CGContextSaveGState(context); + CGContextSetShouldSmoothFonts (context, true); + CGContextSetShouldAntialias (context, true); + CGContextSetBlendMode (context, kCGBlendModeNormal); + rgbColourSpace = CGColorSpaceCreateDeviceRGB(); + greyColourSpace = CGColorSpaceCreateDeviceGray(); + gradientCallbacks.version = 0; + gradientCallbacks.evaluate = gradientCallback; + gradientCallbacks.releaseInfo = 0; + state = new SavedState(); + } - ~CoreGraphicsContext() - { - CGContextRestoreGState (context); - CGContextRelease (context); - CGColorSpaceRelease (rgbColourSpace); - CGColorSpaceRelease (greyColourSpace); - } + ~CoreGraphicsContext() + { + CGContextRestoreGState (context); + CGContextRelease (context); + CGColorSpaceRelease (rgbColourSpace); + CGColorSpaceRelease (greyColourSpace); + } - bool isVectorDevice() const { return false; } + bool isVectorDevice() const { return false; } - void setOrigin (int x, int y) - { - CGContextTranslateCTM (context, x, -y); - } + void setOrigin (int x, int y) + { + CGContextTranslateCTM (context, x, -y); + } - bool clipToRectangle (const Rectangle& r) - { - CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight())); - return ! isClipEmpty(); - } + bool clipToRectangle (const Rectangle& r) + { + CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight())); + return ! isClipEmpty(); + } - bool clipToRectangleList (const RectangleList& clipRegion) - { - if (clipRegion.isEmpty()) - { - CGContextClipToRect (context, CGRectMake (0, 0, 0, 0)); - return false; - } - else - { - const int numRects = clipRegion.getNumRectangles(); + bool clipToRectangleList (const RectangleList& clipRegion) + { + if (clipRegion.isEmpty()) + { + CGContextClipToRect (context, CGRectMake (0, 0, 0, 0)); + return false; + } + else + { + const int numRects = clipRegion.getNumRectangles(); - HeapBlock rects (numRects); - for (int i = 0; i < numRects; ++i) - { - const Rectangle& r = clipRegion.getRectangle(i); - rects[i] = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); - } + HeapBlock rects (numRects); + for (int i = 0; i < numRects; ++i) + { + const Rectangle& r = clipRegion.getRectangle(i); + rects[i] = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); + } - CGContextClipToRects (context, rects, numRects); - return ! isClipEmpty(); - } - } + CGContextClipToRects (context, rects, numRects); + return ! isClipEmpty(); + } + } - void excludeClipRectangle (const Rectangle& r) - { - RectangleList remaining (getClipBounds()); - remaining.subtract (r); - clipToRectangleList (remaining); - } + void excludeClipRectangle (const Rectangle& r) + { + RectangleList remaining (getClipBounds()); + remaining.subtract (r); + clipToRectangleList (remaining); + } - void clipToPath (const Path& path, const AffineTransform& transform) - { - createPath (path, transform); - CGContextClip (context); - } + void clipToPath (const Path& path, const AffineTransform& transform) + { + createPath (path, transform); + CGContextClip (context); + } - void clipToImageAlpha (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform) - { - if (! transform.isSingularity()) - { - Image* singleChannelImage = createAlphaChannelImage (sourceImage); - CGImageRef image = CoreGraphicsImage::createImage (*singleChannelImage, true, greyColourSpace); + void clipToImageAlpha (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform) + { + if (! transform.isSingularity()) + { + Image* singleChannelImage = createAlphaChannelImage (sourceImage); + CGImageRef image = CoreGraphicsImage::createImage (*singleChannelImage, true, greyColourSpace); - flip(); - AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform)); - applyTransform (t); + flip(); + AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform)); + applyTransform (t); - CGRect r = CGRectMake (0, 0, sourceImage.getWidth(), sourceImage.getHeight()); - CGContextClipToMask (context, r, image); + CGRect r = CGRectMake (0, 0, sourceImage.getWidth(), sourceImage.getHeight()); + CGContextClipToMask (context, r, image); - applyTransform (t.inverted()); - flip(); + applyTransform (t.inverted()); + flip(); - CGImageRelease (image); - deleteAlphaChannelImage (sourceImage, singleChannelImage); - } - } + CGImageRelease (image); + deleteAlphaChannelImage (sourceImage, singleChannelImage); + } + } - bool clipRegionIntersects (const Rectangle& r) - { - return getClipBounds().intersects (r); - } + bool clipRegionIntersects (const Rectangle& r) + { + return getClipBounds().intersects (r); + } - const Rectangle getClipBounds() const - { - CGRect bounds = CGRectIntegral (CGContextGetClipBoundingBox (context)); + const Rectangle getClipBounds() const + { + CGRect bounds = CGRectIntegral (CGContextGetClipBoundingBox (context)); - return Rectangle (roundFloatToInt (bounds.origin.x), - roundFloatToInt (flipHeight - (bounds.origin.y + bounds.size.height)), - roundFloatToInt (bounds.size.width), - roundFloatToInt (bounds.size.height)); - } + return Rectangle (roundToInt (bounds.origin.x), + roundToInt (flipHeight - (bounds.origin.y + bounds.size.height)), + roundToInt (bounds.size.width), + roundToInt (bounds.size.height)); + } - bool isClipEmpty() const - { - return CGRectIsEmpty (CGContextGetClipBoundingBox (context)); - } + bool isClipEmpty() const + { + return CGRectIsEmpty (CGContextGetClipBoundingBox (context)); + } - void saveState() - { - CGContextSaveGState (context); - stateStack.add (new SavedState (*state)); - } + void saveState() + { + CGContextSaveGState (context); + stateStack.add (new SavedState (*state)); + } - void restoreState() - { - CGContextRestoreGState (context); + void restoreState() + { + CGContextRestoreGState (context); - SavedState* const top = stateStack.getLast(); + SavedState* const top = stateStack.getLast(); - if (top != 0) - { - state = top; - stateStack.removeLast (1, false); - } - else - { - jassertfalse // trying to pop with an empty stack! - } - } + if (top != 0) + { + state = top; + stateStack.removeLast (1, false); + } + else + { + jassertfalse // trying to pop with an empty stack! + } + } - void setFill (const FillType& fillType) - { - state->fillType = fillType; + void setFill (const FillType& fillType) + { + state->fillType = fillType; - if (fillType.isColour()) - { - CGContextSetRGBFillColor (context, fillType.colour.getFloatRed(), fillType.colour.getFloatGreen(), - fillType.colour.getFloatBlue(), fillType.colour.getFloatAlpha()); - CGContextSetAlpha (context, 1.0f); - } - } + if (fillType.isColour()) + { + CGContextSetRGBFillColor (context, fillType.colour.getFloatRed(), fillType.colour.getFloatGreen(), + fillType.colour.getFloatBlue(), fillType.colour.getFloatAlpha()); + CGContextSetAlpha (context, 1.0f); + } + } - void setOpacity (float newOpacity) - { - state->fillType.setOpacity (newOpacity); - setFill (state->fillType); - } + void setOpacity (float newOpacity) + { + state->fillType.setOpacity (newOpacity); + setFill (state->fillType); + } - void setInterpolationQuality (Graphics::ResamplingQuality quality) - { - CGContextSetInterpolationQuality (context, quality == Graphics::lowResamplingQuality - ? kCGInterpolationLow - : kCGInterpolationHigh); - } + void setInterpolationQuality (Graphics::ResamplingQuality quality) + { + CGContextSetInterpolationQuality (context, quality == Graphics::lowResamplingQuality + ? kCGInterpolationLow + : kCGInterpolationHigh); + } - void fillRect (const Rectangle& r, const bool replaceExistingContents) - { - CGRect cgRect = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); + void fillRect (const Rectangle& r, const bool replaceExistingContents) + { + CGRect cgRect = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); - if (replaceExistingContents) - { + if (replaceExistingContents) + { #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 - CGContextClearRect (context, cgRect); + CGContextClearRect (context, cgRect); #else #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 - if (CGContextDrawLinearGradient == 0) // (just a way of checking whether we're running in 10.5 or later) - CGContextClearRect (context, cgRect); - else + if (CGContextDrawLinearGradient == 0) // (just a way of checking whether we're running in 10.5 or later) + CGContextClearRect (context, cgRect); + else #endif - CGContextSetBlendMode (context, kCGBlendModeCopy); + CGContextSetBlendMode (context, kCGBlendModeCopy); #endif - fillRect (r, false); - CGContextSetBlendMode (context, kCGBlendModeNormal); - } - else - { - if (state->fillType.isColour()) - { - CGContextFillRect (context, cgRect); - } - else if (state->fillType.isGradient()) - { - CGContextSaveGState (context); - CGContextClipToRect (context, cgRect); - drawGradient(); - CGContextRestoreGState (context); - } - else - { - CGContextSaveGState (context); - CGContextClipToRect (context, cgRect); - drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); - CGContextRestoreGState (context); - } - } - } + fillRect (r, false); + CGContextSetBlendMode (context, kCGBlendModeNormal); + } + else + { + if (state->fillType.isColour()) + { + CGContextFillRect (context, cgRect); + } + else if (state->fillType.isGradient()) + { + CGContextSaveGState (context); + CGContextClipToRect (context, cgRect); + drawGradient(); + CGContextRestoreGState (context); + } + else + { + CGContextSaveGState (context); + CGContextClipToRect (context, cgRect); + drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); + CGContextRestoreGState (context); + } + } + } - void fillPath (const Path& path, const AffineTransform& transform) - { - CGContextSaveGState (context); + void fillPath (const Path& path, const AffineTransform& transform) + { + CGContextSaveGState (context); - if (state->fillType.isColour()) - { - flip(); - applyTransform (transform); - createPath (path); + if (state->fillType.isColour()) + { + flip(); + applyTransform (transform); + createPath (path); - if (path.isUsingNonZeroWinding()) - CGContextFillPath (context); - else - CGContextEOFillPath (context); - } - else - { - createPath (path, transform); + if (path.isUsingNonZeroWinding()) + CGContextFillPath (context); + else + CGContextEOFillPath (context); + } + else + { + createPath (path, transform); - if (path.isUsingNonZeroWinding()) - CGContextClip (context); - else - CGContextEOClip (context); + if (path.isUsingNonZeroWinding()) + CGContextClip (context); + else + CGContextEOClip (context); - if (state->fillType.isGradient()) - drawGradient(); - else - drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); - } + if (state->fillType.isGradient()) + drawGradient(); + else + drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); + } - CGContextRestoreGState (context); - } + CGContextRestoreGState (context); + } - void drawImage (const Image& sourceImage, const Rectangle& srcClip, - const AffineTransform& transform, const bool fillEntireClipAsTiles) - { - jassert (sourceImage.getBounds().contains (srcClip)); + void drawImage (const Image& sourceImage, const Rectangle& srcClip, + const AffineTransform& transform, const bool fillEntireClipAsTiles) + { + jassert (sourceImage.getBounds().contains (srcClip)); - CGImageRef fullImage = CoreGraphicsImage::createImage (sourceImage, false, rgbColourSpace); - CGImageRef image = fullImage; + CGImageRef fullImage = CoreGraphicsImage::createImage (sourceImage, false, rgbColourSpace); + CGImageRef image = fullImage; - if (srcClip != sourceImage.getBounds()) - { - image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClip.getX(), srcClip.getY(), - srcClip.getWidth(), srcClip.getHeight())); - CGImageRelease (fullImage); - } + if (srcClip != sourceImage.getBounds()) + { + image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClip.getX(), srcClip.getY(), + srcClip.getWidth(), srcClip.getHeight())); + CGImageRelease (fullImage); + } - CGContextSaveGState (context); - CGContextSetAlpha (context, state->fillType.getOpacity()); + CGContextSaveGState (context); + CGContextSetAlpha (context, state->fillType.getOpacity()); - flip(); - applyTransform (AffineTransform::scale (1.0f, -1.0f).translated (0, srcClip.getHeight()).followedBy (transform)); - CGRect imageRect = CGRectMake (0, 0, srcClip.getWidth(), srcClip.getHeight()); + flip(); + applyTransform (AffineTransform::scale (1.0f, -1.0f).translated (0, srcClip.getHeight()).followedBy (transform)); + CGRect imageRect = CGRectMake (0, 0, srcClip.getWidth(), srcClip.getHeight()); - if (fillEntireClipAsTiles) - { + if (fillEntireClipAsTiles) + { #if JUCE_IPHONE || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) - CGContextDrawTiledImage (context, imageRect, image); + CGContextDrawTiledImage (context, imageRect, image); #else #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - if (CGContextDrawTiledImage != 0) - CGContextDrawTiledImage (context, imageRect, image); - else + if (CGContextDrawTiledImage != 0) + CGContextDrawTiledImage (context, imageRect, image); + else #endif - { - // Fallback to manually doing a tiled fill on 10.4 - CGRect clip = CGRectIntegral (CGContextGetClipBoundingBox (context)); - const int iw = srcClip.getWidth(); - const int ih = srcClip.getHeight(); + { + // Fallback to manually doing a tiled fill on 10.4 + CGRect clip = CGRectIntegral (CGContextGetClipBoundingBox (context)); + const int iw = srcClip.getWidth(); + const int ih = srcClip.getHeight(); - int x = 0, y = 0; - while (x > clip.origin.x) x -= iw; - while (y > clip.origin.y) y -= ih; + int x = 0, y = 0; + while (x > clip.origin.x) x -= iw; + while (y > clip.origin.y) y -= ih; - const int right = (int) (clip.origin.x + clip.size.width); - const int bottom = (int) (clip.origin.y + clip.size.height); + const int right = (int) (clip.origin.x + clip.size.width); + const int bottom = (int) (clip.origin.y + clip.size.height); - while (y < bottom) - { - for (int x2 = x; x2 < right; x2 += iw) - CGContextDrawImage (context, CGRectMake (x2, y, iw, ih), image); + while (y < bottom) + { + for (int x2 = x; x2 < right; x2 += iw) + CGContextDrawImage (context, CGRectMake (x2, y, iw, ih), image); - y += ih; - } - } + y += ih; + } + } #endif - } - else - { - CGContextDrawImage (context, imageRect, image); - } + } + else + { + CGContextDrawImage (context, imageRect, image); + } - CGImageRelease (image); // (This causes a memory bug in iPhone sim 3.0 - try upgrading to a later version if you hit this) - CGContextRestoreGState (context); - } + CGImageRelease (image); // (This causes a memory bug in iPhone sim 3.0 - try upgrading to a later version if you hit this) + CGContextRestoreGState (context); + } - void drawLine (double x1, double y1, double x2, double y2) - { - CGContextSetLineCap (context, kCGLineCapSquare); - CGContextSetLineWidth (context, 1.0f); - CGContextSetRGBStrokeColor (context, - state->fillType.colour.getFloatRed(), state->fillType.colour.getFloatGreen(), - state->fillType.colour.getFloatBlue(), state->fillType.colour.getFloatAlpha()); + void drawLine (double x1, double y1, double x2, double y2) + { + CGContextSetLineCap (context, kCGLineCapSquare); + CGContextSetLineWidth (context, 1.0f); + CGContextSetRGBStrokeColor (context, + state->fillType.colour.getFloatRed(), state->fillType.colour.getFloatGreen(), + state->fillType.colour.getFloatBlue(), state->fillType.colour.getFloatAlpha()); - CGPoint line[] = { { (float) x1 + 0.5f, flipHeight - ((float) y1 + 0.5f) }, - { (float) x2 + 0.5f, flipHeight - ((float) y2 + 0.5f) } }; + CGPoint line[] = { { (float) x1 + 0.5f, flipHeight - ((float) y1 + 0.5f) }, + { (float) x2 + 0.5f, flipHeight - ((float) y2 + 0.5f) } }; - CGContextStrokeLineSegments (context, line, 1); - } + CGContextStrokeLineSegments (context, line, 1); + } - void drawVerticalLine (const int x, double top, double bottom) - { - CGContextFillRect (context, CGRectMake (x, flipHeight - (float) bottom, 1.0f, (float) (bottom - top))); - } + void drawVerticalLine (const int x, double top, double bottom) + { + CGContextFillRect (context, CGRectMake (x, flipHeight - (float) bottom, 1.0f, (float) (bottom - top))); + } - void drawHorizontalLine (const int y, double left, double right) - { - CGContextFillRect (context, CGRectMake ((float) left, flipHeight - (y + 1.0f), (float) (right - left), 1.0f)); - } + void drawHorizontalLine (const int y, double left, double right) + { + CGContextFillRect (context, CGRectMake ((float) left, flipHeight - (y + 1.0f), (float) (right - left), 1.0f)); + } - void setFont (const Font& newFont) - { - if (state->font != newFont) - { - state->fontRef = 0; - state->font = newFont; + void setFont (const Font& newFont) + { + if (state->font != newFont) + { + state->fontRef = 0; + state->font = newFont; - MacTypeface* mf = dynamic_cast ((Typeface*) state->font.getTypeface()); + MacTypeface* mf = dynamic_cast ((Typeface*) state->font.getTypeface()); - if (mf != 0) - { - state->fontRef = mf->fontRef; - CGContextSetFont (context, state->fontRef); - CGContextSetFontSize (context, state->font.getHeight() * mf->fontHeightToCGSizeFactor); + if (mf != 0) + { + state->fontRef = mf->fontRef; + CGContextSetFont (context, state->fontRef); + CGContextSetFontSize (context, state->font.getHeight() * mf->fontHeightToCGSizeFactor); - state->fontTransform = mf->renderingTransform; - state->fontTransform.a *= state->font.getHorizontalScale(); - CGContextSetTextMatrix (context, state->fontTransform); - } - } - } + state->fontTransform = mf->renderingTransform; + state->fontTransform.a *= state->font.getHorizontalScale(); + CGContextSetTextMatrix (context, state->fontTransform); + } + } + } - const Font getFont() - { - return state->font; - } + const Font getFont() + { + return state->font; + } - void drawGlyph (int glyphNumber, const AffineTransform& transform) - { - if (state->fontRef != 0 && state->fillType.isColour()) - { - if (transform.isOnlyTranslation()) - { - CGGlyph g = glyphNumber; - CGContextShowGlyphsAtPoint (context, transform.getTranslationX(), - flipHeight - roundFloatToInt (transform.getTranslationY()), &g, 1); - } - else - { - CGContextSaveGState (context); - flip(); - applyTransform (transform); + void drawGlyph (int glyphNumber, const AffineTransform& transform) + { + if (state->fontRef != 0 && state->fillType.isColour()) + { + if (transform.isOnlyTranslation()) + { + CGGlyph g = glyphNumber; + CGContextShowGlyphsAtPoint (context, transform.getTranslationX(), + flipHeight - roundToInt (transform.getTranslationY()), &g, 1); + } + else + { + CGContextSaveGState (context); + flip(); + applyTransform (transform); - CGAffineTransform t = state->fontTransform; - t.d = -t.d; - CGContextSetTextMatrix (context, t); + CGAffineTransform t = state->fontTransform; + t.d = -t.d; + CGContextSetTextMatrix (context, t); - CGGlyph g = glyphNumber; - CGContextShowGlyphsAtPoint (context, 0, 0, &g, 1); + CGGlyph g = glyphNumber; + CGContextShowGlyphsAtPoint (context, 0, 0, &g, 1); - CGContextSetTextMatrix (context, state->fontTransform); - CGContextRestoreGState (context); - } - } - else - { - Path p; - Font& f = state->font; - f.getTypeface()->getOutlineForGlyph (glyphNumber, p); + CGContextSetTextMatrix (context, state->fontTransform); + CGContextRestoreGState (context); + } + } + else + { + Path p; + Font& f = state->font; + f.getTypeface()->getOutlineForGlyph (glyphNumber, p); - fillPath (p, AffineTransform::scale (f.getHeight() * f.getHorizontalScale(), f.getHeight()) - .followedBy (transform)); - } - } + fillPath (p, AffineTransform::scale (f.getHeight() * f.getHorizontalScale(), f.getHeight()) + .followedBy (transform)); + } + } private: - CGContextRef context; - const float flipHeight; - CGColorSpaceRef rgbColourSpace, greyColourSpace; - CGFunctionCallbacks gradientCallbacks; + CGContextRef context; + const float flipHeight; + CGColorSpaceRef rgbColourSpace, greyColourSpace; + CGFunctionCallbacks gradientCallbacks; - struct SavedState - { - SavedState() - : font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity) - { - } + struct SavedState + { + SavedState() + : font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity) + { + } - SavedState (const SavedState& other) - : fillType (other.fillType), font (other.font), fontRef (other.fontRef), - fontTransform (other.fontTransform) - { - } + SavedState (const SavedState& other) + : fillType (other.fillType), font (other.font), fontRef (other.fontRef), + fontTransform (other.fontTransform) + { + } - ~SavedState() - { - } + ~SavedState() + { + } - FillType fillType; - Font font; - CGFontRef fontRef; - CGAffineTransform fontTransform; - }; + FillType fillType; + Font font; + CGFontRef fontRef; + CGAffineTransform fontTransform; + }; - ScopedPointer state; - OwnedArray stateStack; - HeapBlock gradientLookupTable; - int numGradientLookupEntries; + ScopedPointer state; + OwnedArray stateStack; + HeapBlock gradientLookupTable; + int numGradientLookupEntries; - static void gradientCallback (void* info, const CGFloat* inData, CGFloat* outData) - { - const CoreGraphicsContext* const g = (const CoreGraphicsContext*) info; + static void gradientCallback (void* info, const CGFloat* inData, CGFloat* outData) + { + const CoreGraphicsContext* const g = (const CoreGraphicsContext*) info; - const int index = roundFloatToInt (g->numGradientLookupEntries * inData[0]); - PixelARGB colour (g->gradientLookupTable [jlimit (0, g->numGradientLookupEntries, index)]); - colour.unpremultiply(); + const int index = roundToInt (g->numGradientLookupEntries * inData[0]); + PixelARGB colour (g->gradientLookupTable [jlimit (0, g->numGradientLookupEntries, index)]); + colour.unpremultiply(); - outData[0] = colour.getRed() / 255.0f; - outData[1] = colour.getGreen() / 255.0f; - outData[2] = colour.getBlue() / 255.0f; - outData[3] = colour.getAlpha() / 255.0f; - } + outData[0] = colour.getRed() / 255.0f; + outData[1] = colour.getGreen() / 255.0f; + outData[2] = colour.getBlue() / 255.0f; + outData[3] = colour.getAlpha() / 255.0f; + } - CGShadingRef createGradient (const AffineTransform& transform, ColourGradient gradient) - { - numGradientLookupEntries = gradient.createLookupTable (transform, gradientLookupTable); - --numGradientLookupEntries; + CGShadingRef createGradient (const AffineTransform& transform, ColourGradient gradient) + { + numGradientLookupEntries = gradient.createLookupTable (transform, gradientLookupTable); + --numGradientLookupEntries; - CGShadingRef result = 0; - CGFunctionRef function = CGFunctionCreate ((void*) this, 1, 0, 4, 0, &gradientCallbacks); - CGPoint p1 (CGPointMake (gradient.x1, gradient.y1)); + CGShadingRef result = 0; + CGFunctionRef function = CGFunctionCreate ((void*) this, 1, 0, 4, 0, &gradientCallbacks); + CGPoint p1 (CGPointMake (gradient.x1, gradient.y1)); - if (gradient.isRadial) - { - result = CGShadingCreateRadial (rgbColourSpace, p1, 0, - p1, hypotf (gradient.x1 - gradient.x2, gradient.y1 - gradient.y2), - function, true, true); - } - else - { - result = CGShadingCreateAxial (rgbColourSpace, p1, - CGPointMake (gradient.x2, gradient.y2), - function, true, true); - } + if (gradient.isRadial) + { + result = CGShadingCreateRadial (rgbColourSpace, p1, 0, + p1, hypotf (gradient.x1 - gradient.x2, gradient.y1 - gradient.y2), + function, true, true); + } + else + { + result = CGShadingCreateAxial (rgbColourSpace, p1, + CGPointMake (gradient.x2, gradient.y2), + function, true, true); + } - CGFunctionRelease (function); - return result; - } + CGFunctionRelease (function); + return result; + } - void drawGradient() - { - flip(); - applyTransform (state->fillType.transform); + void drawGradient() + { + flip(); + applyTransform (state->fillType.transform); - CGContextSetInterpolationQuality (context, kCGInterpolationDefault); // (This is required for 10.4, where there's a crash if - // you draw a gradient with high quality interp enabled). - CGShadingRef shading = createGradient (state->fillType.transform, *(state->fillType.gradient)); - CGContextSetAlpha (context, state->fillType.getOpacity()); - CGContextDrawShading (context, shading); - CGShadingRelease (shading); - } + CGContextSetInterpolationQuality (context, kCGInterpolationDefault); // (This is required for 10.4, where there's a crash if + // you draw a gradient with high quality interp enabled). + CGShadingRef shading = createGradient (state->fillType.transform, *(state->fillType.gradient)); + CGContextSetAlpha (context, state->fillType.getOpacity()); + CGContextDrawShading (context, shading); + CGShadingRelease (shading); + } - void createPath (const Path& path) const - { - CGContextBeginPath (context); - Path::Iterator i (path); + void createPath (const Path& path) const + { + CGContextBeginPath (context); + Path::Iterator i (path); - while (i.next()) - { - switch (i.elementType) - { - case Path::Iterator::startNewSubPath: - CGContextMoveToPoint (context, i.x1, i.y1); - break; - case Path::Iterator::lineTo: - CGContextAddLineToPoint (context, i.x1, i.y1); - break; - case Path::Iterator::quadraticTo: - CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); - break; - case Path::Iterator::cubicTo: - CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); - break; - case Path::Iterator::closePath: - CGContextClosePath (context); break; - default: - jassertfalse - break; - } - } - } + while (i.next()) + { + switch (i.elementType) + { + case Path::Iterator::startNewSubPath: + CGContextMoveToPoint (context, i.x1, i.y1); + break; + case Path::Iterator::lineTo: + CGContextAddLineToPoint (context, i.x1, i.y1); + break; + case Path::Iterator::quadraticTo: + CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); + break; + case Path::Iterator::cubicTo: + CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); + break; + case Path::Iterator::closePath: + CGContextClosePath (context); break; + default: + jassertfalse + break; + } + } + } - void createPath (const Path& path, const AffineTransform& transform) const - { - CGContextBeginPath (context); - Path::Iterator i (path); + void createPath (const Path& path, const AffineTransform& transform) const + { + CGContextBeginPath (context); + Path::Iterator i (path); - while (i.next()) - { - switch (i.elementType) - { - case Path::Iterator::startNewSubPath: - transform.transformPoint (i.x1, i.y1); - CGContextMoveToPoint (context, i.x1, flipHeight - i.y1); - break; - case Path::Iterator::lineTo: - transform.transformPoint (i.x1, i.y1); - CGContextAddLineToPoint (context, i.x1, flipHeight - i.y1); - break; - case Path::Iterator::quadraticTo: - transform.transformPoint (i.x1, i.y1); - transform.transformPoint (i.x2, i.y2); - CGContextAddQuadCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2); - break; - case Path::Iterator::cubicTo: - transform.transformPoint (i.x1, i.y1); - transform.transformPoint (i.x2, i.y2); - transform.transformPoint (i.x3, i.y3); - CGContextAddCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2, i.x3, flipHeight - i.y3); - break; - case Path::Iterator::closePath: - CGContextClosePath (context); break; - default: - jassertfalse - break; - } - } - } + while (i.next()) + { + switch (i.elementType) + { + case Path::Iterator::startNewSubPath: + transform.transformPoint (i.x1, i.y1); + CGContextMoveToPoint (context, i.x1, flipHeight - i.y1); + break; + case Path::Iterator::lineTo: + transform.transformPoint (i.x1, i.y1); + CGContextAddLineToPoint (context, i.x1, flipHeight - i.y1); + break; + case Path::Iterator::quadraticTo: + transform.transformPoint (i.x1, i.y1); + transform.transformPoint (i.x2, i.y2); + CGContextAddQuadCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2); + break; + case Path::Iterator::cubicTo: + transform.transformPoint (i.x1, i.y1); + transform.transformPoint (i.x2, i.y2); + transform.transformPoint (i.x3, i.y3); + CGContextAddCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2, i.x3, flipHeight - i.y3); + break; + case Path::Iterator::closePath: + CGContextClosePath (context); break; + default: + jassertfalse + break; + } + } + } - static Image* createAlphaChannelImage (const Image& im) - { - if (im.getFormat() == Image::SingleChannel) - return const_cast (&im); + static Image* createAlphaChannelImage (const Image& im) + { + if (im.getFormat() == Image::SingleChannel) + return const_cast (&im); - return im.createCopyOfAlphaChannel(); - } + return im.createCopyOfAlphaChannel(); + } - static void deleteAlphaChannelImage (const Image& im, Image* const alphaIm) - { - if (im.getFormat() != Image::SingleChannel) - delete alphaIm; - } + static void deleteAlphaChannelImage (const Image& im, Image* const alphaIm) + { + if (im.getFormat() != Image::SingleChannel) + delete alphaIm; + } - void flip() const - { - CGContextConcatCTM (context, CGAffineTransformMake (1, 0, 0, -1, 0, flipHeight)); - } + void flip() const + { + CGContextConcatCTM (context, CGAffineTransformMake (1, 0, 0, -1, 0, flipHeight)); + } - void applyTransform (const AffineTransform& transform) const - { - CGAffineTransform t; - t.a = transform.mat00; - t.b = transform.mat10; - t.c = transform.mat01; - t.d = transform.mat11; - t.tx = transform.mat02; - t.ty = transform.mat12; - CGContextConcatCTM (context, t); - } + void applyTransform (const AffineTransform& transform) const + { + CGAffineTransform t; + t.a = transform.mat00; + t.b = transform.mat10; + t.c = transform.mat01; + t.d = transform.mat11; + t.tx = transform.mat02; + t.ty = transform.mat12; + CGContextConcatCTM (context, t); + } - float flipY (float y) const - { - return flipHeight - y; - } + float flipY (float y) const + { + return flipHeight - y; + } }; LowLevelGraphicsContext* CoreGraphicsImage::createLowLevelContext() { - return new CoreGraphicsContext (context, imageHeight); + return new CoreGraphicsContext (context, imageHeight); } #endif @@ -263092,7 +240676,7 @@ END_JUCE_NAMESPACE @interface JuceUIView : UIView { @public - UIViewComponentPeer* owner; + UIViewComponentPeer* owner; } - (JuceUIView*) initWithOwner: (UIViewComponentPeer*) owner withFrame: (CGRect) frame; @@ -263118,8 +240702,8 @@ END_JUCE_NAMESPACE @interface JuceUIWindow : UIWindow { @private - UIViewComponentPeer* owner; - bool isZooming; + UIViewComponentPeer* owner; + bool isZooming; } - (void) setOwner: (UIViewComponentPeer*) owner; @@ -263131,57 +240715,57 @@ BEGIN_JUCE_NAMESPACE class UIViewComponentPeer : public ComponentPeer { public: - UIViewComponentPeer (Component* const component, - const int windowStyleFlags, - UIView* viewToAttachTo); + UIViewComponentPeer (Component* const component, + const int windowStyleFlags, + UIView* viewToAttachTo); - ~UIViewComponentPeer(); + ~UIViewComponentPeer(); - void* getNativeHandle() const; - void setVisible (bool shouldBeVisible); - void setTitle (const String& title); - void setPosition (int x, int y); - void setSize (int w, int h); - void setBounds (int x, int y, int w, int h, const bool isNowFullScreen); - void getBounds (int& x, int& y, int& w, int& h, const bool global) const; - void getBounds (int& x, int& y, int& w, int& h) const; - int getScreenX() const; - int getScreenY() const; - void relativePositionToGlobal (int& x, int& y); - void globalPositionToRelative (int& x, int& y); - void setMinimised (bool shouldBeMinimised); - bool isMinimised() const; - void setFullScreen (bool shouldBeFullScreen); - bool isFullScreen() const; - bool contains (int x, int y, bool trueIfInAChildWindow) const; - const BorderSize getFrameSize() const; - bool setAlwaysOnTop (bool alwaysOnTop); - void toFront (bool makeActiveWindow); - void toBehind (ComponentPeer* other); - void setIcon (const Image& newIcon); + void* getNativeHandle() const; + void setVisible (bool shouldBeVisible); + void setTitle (const String& title); + void setPosition (int x, int y); + void setSize (int w, int h); + void setBounds (int x, int y, int w, int h, const bool isNowFullScreen); + void getBounds (int& x, int& y, int& w, int& h, const bool global) const; + void getBounds (int& x, int& y, int& w, int& h) const; + int getScreenX() const; + int getScreenY() const; + void relativePositionToGlobal (int& x, int& y); + void globalPositionToRelative (int& x, int& y); + void setMinimised (bool shouldBeMinimised); + bool isMinimised() const; + void setFullScreen (bool shouldBeFullScreen); + bool isFullScreen() const; + bool contains (int x, int y, bool trueIfInAChildWindow) const; + const BorderSize getFrameSize() const; + bool setAlwaysOnTop (bool alwaysOnTop); + void toFront (bool makeActiveWindow); + void toBehind (ComponentPeer* other); + void setIcon (const Image& newIcon); - virtual void drawRect (CGRect r); + virtual void drawRect (CGRect r); - virtual bool canBecomeKeyWindow(); - virtual bool windowShouldClose(); + virtual bool canBecomeKeyWindow(); + virtual bool windowShouldClose(); - virtual void redirectMovedOrResized(); - virtual CGRect constrainRect (CGRect r); + virtual void redirectMovedOrResized(); + virtual CGRect constrainRect (CGRect r); - virtual void viewFocusGain(); - virtual void viewFocusLoss(); - bool isFocused() const; - void grabFocus(); - void textInputRequired (int x, int y); + virtual void viewFocusGain(); + virtual void viewFocusLoss(); + bool isFocused() const; + void grabFocus(); + void textInputRequired (int x, int y); - void repaint (int x, int y, int w, int h); - void performAnyPendingRepaintsNow(); + void repaint (int x, int y, int w, int h); + void performAnyPendingRepaintsNow(); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - UIWindow* window; - JuceUIView* view; - bool isSharedWindow, fullScreen, insideDrawRect; + UIWindow* window; + JuceUIView* view; + bool isSharedWindow, fullScreen, insideDrawRect; }; END_JUCE_NAMESPACE @@ -263189,174 +240773,174 @@ END_JUCE_NAMESPACE @implementation JuceUIView - (JuceUIView*) initWithOwner: (UIViewComponentPeer*) owner_ - withFrame: (CGRect) frame + withFrame: (CGRect) frame { - [super initWithFrame: frame]; - owner = owner_; + [super initWithFrame: frame]; + owner = owner_; - return self; + return self; } - (void) dealloc { - [super dealloc]; + [super dealloc]; } - (void) drawRect: (CGRect) r { - if (owner != 0) - owner->drawRect (r); + if (owner != 0) + owner->drawRect (r); } bool KeyPress::isKeyCurrentlyDown (const int keyCode) throw() { - return false; + return false; } static int currentModifiers = 0; const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() throw() { - return ModifierKeys (currentModifiers); + return ModifierKeys (currentModifiers); } void ModifierKeys::updateCurrentModifiers() throw() { - currentModifierFlags = currentModifiers; + currentModifierFlags = currentModifiers; } static int getModifierForButtonNumber (const int num) { - return num == 0 ? ModifierKeys::leftButtonModifier - : (num == 1 ? ModifierKeys::rightButtonModifier - : (num == 2 ? ModifierKeys::middleButtonModifier : 0)); + return num == 0 ? ModifierKeys::leftButtonModifier + : (num == 1 ? ModifierKeys::rightButtonModifier + : (num == 2 ? ModifierKeys::middleButtonModifier : 0)); } static int64 getMouseTime (UIEvent* e) { - return (Time::currentTimeMillis() - Time::getMillisecondCounter()) - + (int64) ([e timestamp] * 1000.0); + return (Time::currentTimeMillis() - Time::getMillisecondCounter()) + + (int64) ([e timestamp] * 1000.0); } int juce_lastMouseX = 0, juce_lastMouseY = 0; - (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event { - if (owner == 0) - return; + if (owner == 0) + return; - NSArray* const t = [[event touchesForView: self] allObjects]; + NSArray* const t = [[event touchesForView: self] allObjects]; - switch ([t count]) - { - case 1: // One finger.. - { - CGPoint p = [[t objectAtIndex: 0] locationInView: self]; - currentModifiers |= getModifierForButtonNumber (0); + switch ([t count]) + { + case 1: // One finger.. + { + CGPoint p = [[t objectAtIndex: 0] locationInView: self]; + currentModifiers |= getModifierForButtonNumber (0); - int x, y, w, h; - owner->getBounds (x, y, w, h, true); - juce_lastMouseX = x + (int) p.x; - juce_lastMouseY = y + (int) p.y; + int x, y, w, h; + owner->getBounds (x, y, w, h, true); + juce_lastMouseX = x + (int) p.x; + juce_lastMouseY = y + (int) p.y; - owner->handleMouseMove ((int) p.x, (int) p.y, getMouseTime (event)); + owner->handleMouseMove ((int) p.x, (int) p.y, getMouseTime (event)); - if (owner != 0) - owner->handleMouseDown ((int) p.x, (int) p.y, getMouseTime (event)); - } + if (owner != 0) + owner->handleMouseDown ((int) p.x, (int) p.y, getMouseTime (event)); + } - default: - //xxx multi-touch.. - break; - } + default: + //xxx multi-touch.. + break; + } } - (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event { - if (owner == 0) - return; + if (owner == 0) + return; - NSArray* const t = [[event touchesForView: self] allObjects]; + NSArray* const t = [[event touchesForView: self] allObjects]; - switch ([t count]) - { - case 1: // One finger.. - { - CGPoint p = [[t objectAtIndex: 0] locationInView: self]; + switch ([t count]) + { + case 1: // One finger.. + { + CGPoint p = [[t objectAtIndex: 0] locationInView: self]; - int x, y, w, h; - owner->getBounds (x, y, w, h, true); - juce_lastMouseX = x + (int) p.x; - juce_lastMouseY = y + (int) p.y; + int x, y, w, h; + owner->getBounds (x, y, w, h, true); + juce_lastMouseX = x + (int) p.x; + juce_lastMouseY = y + (int) p.y; - owner->handleMouseDrag ((int) p.x, (int) p.y, getMouseTime (event)); - } + owner->handleMouseDrag ((int) p.x, (int) p.y, getMouseTime (event)); + } - default: - //xxx multi-touch.. - break; - } + default: + //xxx multi-touch.. + break; + } } - (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event { - if (owner == 0) - return; + if (owner == 0) + return; - NSArray* const t = [[event touchesForView: self] allObjects]; + NSArray* const t = [[event touchesForView: self] allObjects]; - switch ([t count]) - { - case 1: // One finger.. - { - CGPoint p = [[t objectAtIndex: 0] locationInView: self]; + switch ([t count]) + { + case 1: // One finger.. + { + CGPoint p = [[t objectAtIndex: 0] locationInView: self]; - int x, y, w, h; - owner->getBounds (x, y, w, h, true); - juce_lastMouseX = x + (int) p.x; - juce_lastMouseY = y + (int) p.y; + int x, y, w, h; + owner->getBounds (x, y, w, h, true); + juce_lastMouseX = x + (int) p.x; + juce_lastMouseY = y + (int) p.y; - const int oldMods = currentModifiers; - currentModifiers &= ~getModifierForButtonNumber (0); - owner->handleMouseUp (oldMods, (int) p.x, (int) p.y, getMouseTime (event)); - } + const int oldMods = currentModifiers; + currentModifiers &= ~getModifierForButtonNumber (0); + owner->handleMouseUp (oldMods, (int) p.x, (int) p.y, getMouseTime (event)); + } - default: - //xxx multi-touch.. - break; - } + default: + //xxx multi-touch.. + break; + } } - (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event { - [self touchesEnded: touches withEvent: event]; + [self touchesEnded: touches withEvent: event]; } - (BOOL) becomeFirstResponder { - if (owner != 0) - owner->viewFocusGain(); + if (owner != 0) + owner->viewFocusGain(); - return true; + return true; } - (BOOL) resignFirstResponder { - if (owner != 0) - owner->viewFocusLoss(); + if (owner != 0) + owner->viewFocusLoss(); - return true; + return true; } - (BOOL) canBecomeFirstResponder { - return owner != 0 && owner->canBecomeKeyWindow(); + return owner != 0 && owner->canBecomeKeyWindow(); } - (void) asyncRepaint: (id) rect { - CGRect* r = (CGRect*) [((NSData*) rect) bytes]; - [self setNeedsDisplayInRect: *r]; + CGRect* r = (CGRect*) [((NSData*) rect) bytes]; + [self setNeedsDisplayInRect: *r]; } @end @@ -263365,16 +240949,16 @@ int juce_lastMouseX = 0, juce_lastMouseY = 0; - (void) setOwner: (UIViewComponentPeer*) owner_ { - owner = owner_; - isZooming = false; + owner = owner_; + isZooming = false; } - (void) becomeKeyWindow { - [super becomeKeyWindow]; + [super becomeKeyWindow]; - if (owner != 0) - owner->grabFocus(); + if (owner != 0) + owner->grabFocus(); } @end @@ -263382,380 +240966,380 @@ int juce_lastMouseX = 0, juce_lastMouseY = 0; BEGIN_JUCE_NAMESPACE UIViewComponentPeer::UIViewComponentPeer (Component* const component, - const int windowStyleFlags, - UIView* viewToAttachTo) - : ComponentPeer (component, windowStyleFlags), - window (0), - view (0), - isSharedWindow (viewToAttachTo != 0), - fullScreen (false), - insideDrawRect (false) + const int windowStyleFlags, + UIView* viewToAttachTo) + : ComponentPeer (component, windowStyleFlags), + window (0), + view (0), + isSharedWindow (viewToAttachTo != 0), + fullScreen (false), + insideDrawRect (false) { - CGRect r; - r.origin.x = 0; - r.origin.y = 0; - r.size.width = (float) component->getWidth(); - r.size.height = (float) component->getHeight(); + CGRect r; + r.origin.x = 0; + r.origin.y = 0; + r.size.width = (float) component->getWidth(); + r.size.height = (float) component->getHeight(); - view = [[JuceUIView alloc] initWithOwner: this withFrame: r]; + view = [[JuceUIView alloc] initWithOwner: this withFrame: r]; - if (isSharedWindow) - { - window = [viewToAttachTo window]; - [viewToAttachTo addSubview: view]; + if (isSharedWindow) + { + window = [viewToAttachTo window]; + [viewToAttachTo addSubview: view]; - setVisible (component->isVisible()); - } - else - { - r.origin.x = (float) component->getX(); - r.origin.y = (float) component->getY(); - r.origin.y = [[UIScreen mainScreen] bounds].size.height - (r.origin.y + r.size.height); + setVisible (component->isVisible()); + } + else + { + r.origin.x = (float) component->getX(); + r.origin.y = (float) component->getY(); + r.origin.y = [[UIScreen mainScreen] bounds].size.height - (r.origin.y + r.size.height); - window = [[JuceUIWindow alloc] init]; - window.frame = r; + window = [[JuceUIWindow alloc] init]; + window.frame = r; - window.opaque = component->isOpaque(); - view.opaque = component->isOpaque(); - window.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent: 0]; - view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent: 0]; + window.opaque = component->isOpaque(); + view.opaque = component->isOpaque(); + window.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent: 0]; + view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent: 0]; - [((JuceUIWindow*) window) setOwner: this]; + [((JuceUIWindow*) window) setOwner: this]; - if (component->isAlwaysOnTop()) - window.windowLevel = UIWindowLevelAlert; + if (component->isAlwaysOnTop()) + window.windowLevel = UIWindowLevelAlert; - [window addSubview: view]; - view.frame = CGRectMake (0, 0, r.size.width, r.size.height); + [window addSubview: view]; + view.frame = CGRectMake (0, 0, r.size.width, r.size.height); - view.hidden = ! component->isVisible(); - window.hidden = ! component->isVisible(); - } + view.hidden = ! component->isVisible(); + window.hidden = ! component->isVisible(); + } - setTitle (component->getName()); + setTitle (component->getName()); } UIViewComponentPeer::~UIViewComponentPeer() { - view->owner = 0; - [view removeFromSuperview]; - [view release]; + view->owner = 0; + [view removeFromSuperview]; + [view release]; - if (! isSharedWindow) - { - [((JuceUIWindow*) window) setOwner: 0]; - [window release]; - } + if (! isSharedWindow) + { + [((JuceUIWindow*) window) setOwner: 0]; + [window release]; + } } void* UIViewComponentPeer::getNativeHandle() const { - return view; + return view; } void UIViewComponentPeer::setVisible (bool shouldBeVisible) { - view.hidden = ! shouldBeVisible; + view.hidden = ! shouldBeVisible; - if (! isSharedWindow) - window.hidden = ! shouldBeVisible; + if (! isSharedWindow) + window.hidden = ! shouldBeVisible; } void UIViewComponentPeer::setTitle (const String& title) { - // xxx is this possible? + // xxx is this possible? } void UIViewComponentPeer::setPosition (int x, int y) { - setBounds (x, y, component->getWidth(), component->getHeight(), false); + setBounds (x, y, component->getWidth(), component->getHeight(), false); } void UIViewComponentPeer::setSize (int w, int h) { - setBounds (component->getX(), component->getY(), w, h, false); + setBounds (component->getX(), component->getY(), w, h, false); } void UIViewComponentPeer::setBounds (int x, int y, int w, int h, const bool isNowFullScreen) { - fullScreen = isNowFullScreen; - w = jmax (0, w); - h = jmax (0, h); + fullScreen = isNowFullScreen; + w = jmax (0, w); + h = jmax (0, h); - CGRect r; - r.origin.x = (float) x; - r.origin.y = (float) y; - r.size.width = (float) w; - r.size.height = (float) h; + CGRect r; + r.origin.x = (float) x; + r.origin.y = (float) y; + r.size.width = (float) w; + r.size.height = (float) h; - if (isSharedWindow) - { - //r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height); + if (isSharedWindow) + { + //r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height); - if ([view frame].size.width != r.size.width - || [view frame].size.height != r.size.height) - [view setNeedsDisplay]; + if ([view frame].size.width != r.size.width + || [view frame].size.height != r.size.height) + [view setNeedsDisplay]; - view.frame = r; - } - else - { - window.frame = r; - view.frame = CGRectMake (0, 0, r.size.width, r.size.height); - } + view.frame = r; + } + else + { + window.frame = r; + view.frame = CGRectMake (0, 0, r.size.width, r.size.height); + } } void UIViewComponentPeer::getBounds (int& x, int& y, int& w, int& h, const bool global) const { - CGRect r = [view frame]; + CGRect r = [view frame]; - if (global && [view window] != 0) - { - r = [view convertRect: r toView: nil]; - CGRect wr = [[view window] frame]; - r.origin.x += wr.origin.x; - r.origin.y += wr.origin.y; - } + if (global && [view window] != 0) + { + r = [view convertRect: r toView: nil]; + CGRect wr = [[view window] frame]; + r.origin.x += wr.origin.x; + r.origin.y += wr.origin.y; + } - x = (int) r.origin.x; - y = (int) r.origin.y; - w = (int) r.size.width; - h = (int) r.size.height; + x = (int) r.origin.x; + y = (int) r.origin.y; + w = (int) r.size.width; + h = (int) r.size.height; } void UIViewComponentPeer::getBounds (int& x, int& y, int& w, int& h) const { - getBounds (x, y, w, h, ! isSharedWindow); + getBounds (x, y, w, h, ! isSharedWindow); } int UIViewComponentPeer::getScreenX() const { - int x, y, w, h; - getBounds (x, y, w, h, true); - return x; + int x, y, w, h; + getBounds (x, y, w, h, true); + return x; } int UIViewComponentPeer::getScreenY() const { - int x, y, w, h; - getBounds (x, y, w, h, true); - return y; + int x, y, w, h; + getBounds (x, y, w, h, true); + return y; } void UIViewComponentPeer::relativePositionToGlobal (int& x, int& y) { - int wx, wy, ww, wh; - getBounds (wx, wy, ww, wh, true); - x += wx; - y += wy; + int wx, wy, ww, wh; + getBounds (wx, wy, ww, wh, true); + x += wx; + y += wy; } void UIViewComponentPeer::globalPositionToRelative (int& x, int& y) { - int wx, wy, ww, wh; - getBounds (wx, wy, ww, wh, true); - x -= wx; - y -= wy; + int wx, wy, ww, wh; + getBounds (wx, wy, ww, wh, true); + x -= wx; + y -= wy; } CGRect UIViewComponentPeer::constrainRect (CGRect r) { - if (constrainer != 0) - { - CGRect current = [window frame]; - current.origin.y = [[UIScreen mainScreen] bounds].size.height - current.origin.y - current.size.height; + if (constrainer != 0) + { + CGRect current = [window frame]; + current.origin.y = [[UIScreen mainScreen] bounds].size.height - current.origin.y - current.size.height; - r.origin.y = [[UIScreen mainScreen] bounds].size.height - r.origin.y - r.size.height; + r.origin.y = [[UIScreen mainScreen] bounds].size.height - r.origin.y - r.size.height; - int x = (int) r.origin.x; - int y = (int) r.origin.y; - int w = (int) r.size.width; - int h = (int) r.size.height; + int x = (int) r.origin.x; + int y = (int) r.origin.y; + int w = (int) r.size.width; + int h = (int) r.size.height; - Rectangle original ((int) current.origin.x, (int) current.origin.y, - (int) current.size.width, (int) current.size.height); + Rectangle original ((int) current.origin.x, (int) current.origin.y, + (int) current.size.width, (int) current.size.height); - constrainer->checkBounds (x, y, w, h, - original, - Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), - y != original.getY() && y + h == original.getBottom(), - x != original.getX() && x + w == original.getRight(), - y == original.getY() && y + h != original.getBottom(), - x == original.getX() && x + w != original.getRight()); + constrainer->checkBounds (x, y, w, h, + original, + Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), + y != original.getY() && y + h == original.getBottom(), + x != original.getX() && x + w == original.getRight(), + y == original.getY() && y + h != original.getBottom(), + x == original.getX() && x + w != original.getRight()); - r.origin.x = x; - r.origin.y = [[UIScreen mainScreen] bounds].size.height - r.size.height - y; - r.size.width = w; - r.size.height = h; - } + r.origin.x = x; + r.origin.y = [[UIScreen mainScreen] bounds].size.height - r.size.height - y; + r.size.width = w; + r.size.height = h; + } - return r; + return r; } void UIViewComponentPeer::setMinimised (bool shouldBeMinimised) { - // xxx + // xxx } bool UIViewComponentPeer::isMinimised() const { - return false; + return false; } void UIViewComponentPeer::setFullScreen (bool shouldBeFullScreen) { - if (! isSharedWindow) - { - Rectangle r (lastNonFullscreenBounds); + if (! isSharedWindow) + { + Rectangle r (lastNonFullscreenBounds); - setMinimised (false); + setMinimised (false); - if (fullScreen != shouldBeFullScreen) - { - if (shouldBeFullScreen) - r = Desktop::getInstance().getMainMonitorArea(); + if (fullScreen != shouldBeFullScreen) + { + if (shouldBeFullScreen) + r = Desktop::getInstance().getMainMonitorArea(); - // (can't call the component's setBounds method because that'll reset our fullscreen flag) - if (r != getComponent()->getBounds() && ! r.isEmpty()) - setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen); - } - } + // (can't call the component's setBounds method because that'll reset our fullscreen flag) + if (r != getComponent()->getBounds() && ! r.isEmpty()) + setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen); + } + } } bool UIViewComponentPeer::isFullScreen() const { - return fullScreen; + return fullScreen; } bool UIViewComponentPeer::contains (int x, int y, bool trueIfInAChildWindow) const { - if (((unsigned int) x) >= (unsigned int) component->getWidth() - || ((unsigned int) y) >= (unsigned int) component->getHeight()) - return false; + if (((unsigned int) x) >= (unsigned int) component->getWidth() + || ((unsigned int) y) >= (unsigned int) component->getHeight()) + return false; - CGPoint p; - p.x = (float) x; - p.y = (float) y; + CGPoint p; + p.x = (float) x; + p.y = (float) y; - UIView* v = [view hitTest: p withEvent: nil]; + UIView* v = [view hitTest: p withEvent: nil]; - if (trueIfInAChildWindow) - return v != nil; + if (trueIfInAChildWindow) + return v != nil; - return v == view; + return v == view; } const BorderSize UIViewComponentPeer::getFrameSize() const { - BorderSize b; + BorderSize b; - if (! isSharedWindow) - { - CGRect v = [view convertRect: [view frame] toView: nil]; - CGRect w = [window frame]; + if (! isSharedWindow) + { + CGRect v = [view convertRect: [view frame] toView: nil]; + CGRect w = [window frame]; - b.setTop ((int) (w.size.height - (v.origin.y + v.size.height))); - b.setBottom ((int) v.origin.y); - b.setLeft ((int) v.origin.x); - b.setRight ((int) (w.size.width - (v.origin.x + v.size.width))); - } + b.setTop ((int) (w.size.height - (v.origin.y + v.size.height))); + b.setBottom ((int) v.origin.y); + b.setLeft ((int) v.origin.x); + b.setRight ((int) (w.size.width - (v.origin.x + v.size.width))); + } - return b; + return b; } bool UIViewComponentPeer::setAlwaysOnTop (bool alwaysOnTop) { - if (! isSharedWindow) - window.windowLevel = alwaysOnTop ? UIWindowLevelAlert : UIWindowLevelNormal; + if (! isSharedWindow) + window.windowLevel = alwaysOnTop ? UIWindowLevelAlert : UIWindowLevelNormal; - return true; + return true; } void UIViewComponentPeer::toFront (bool makeActiveWindow) { - if (isSharedWindow) - [[view superview] bringSubviewToFront: view]; + if (isSharedWindow) + [[view superview] bringSubviewToFront: view]; - if (window != 0 && component->isVisible()) - [window makeKeyAndVisible]; + if (window != 0 && component->isVisible()) + [window makeKeyAndVisible]; } void UIViewComponentPeer::toBehind (ComponentPeer* other) { - UIViewComponentPeer* o = (UIViewComponentPeer*) other; + UIViewComponentPeer* o = (UIViewComponentPeer*) other; - if (isSharedWindow) - { - [[view superview] insertSubview: view belowSubview: o->view]; - } - else - { - jassertfalse // don't know how to do this - } + if (isSharedWindow) + { + [[view superview] insertSubview: view belowSubview: o->view]; + } + else + { + jassertfalse // don't know how to do this + } } void UIViewComponentPeer::setIcon (const Image& /*newIcon*/) { - // to do.. + // to do.. } static UIViewComponentPeer* currentlyFocusedPeer = 0; void UIViewComponentPeer::viewFocusGain() { - if (currentlyFocusedPeer != this) - { - if (ComponentPeer::isValidPeer (currentlyFocusedPeer)) - currentlyFocusedPeer->handleFocusLoss(); + if (currentlyFocusedPeer != this) + { + if (ComponentPeer::isValidPeer (currentlyFocusedPeer)) + currentlyFocusedPeer->handleFocusLoss(); - currentlyFocusedPeer = this; + currentlyFocusedPeer = this; - handleFocusGain(); - } + handleFocusGain(); + } } void UIViewComponentPeer::viewFocusLoss() { - if (currentlyFocusedPeer == this) - { - currentlyFocusedPeer = 0; - handleFocusLoss(); - } + if (currentlyFocusedPeer == this) + { + currentlyFocusedPeer = 0; + handleFocusLoss(); + } } void juce_HandleProcessFocusChange() { - if (UIViewComponentPeer::isValidPeer (currentlyFocusedPeer)) - { - if (Process::isForegroundProcess()) - { - currentlyFocusedPeer->handleFocusGain(); + if (UIViewComponentPeer::isValidPeer (currentlyFocusedPeer)) + { + if (Process::isForegroundProcess()) + { + currentlyFocusedPeer->handleFocusGain(); - ComponentPeer::bringModalComponentToFront(); - } - else - { - currentlyFocusedPeer->handleFocusLoss(); + ComponentPeer::bringModalComponentToFront(); + } + else + { + currentlyFocusedPeer->handleFocusLoss(); - // turn kiosk mode off if we lose focus.. - Desktop::getInstance().setKioskModeComponent (0); - } - } + // turn kiosk mode off if we lose focus.. + Desktop::getInstance().setKioskModeComponent (0); + } + } } bool UIViewComponentPeer::isFocused() const { - return isSharedWindow ? this == currentlyFocusedPeer - : (window != 0 && [window isKeyWindow]); + return isSharedWindow ? this == currentlyFocusedPeer + : (window != 0 && [window isKeyWindow]); } void UIViewComponentPeer::grabFocus() { - if (window != 0) - { - [window makeKeyWindow]; - viewFocusGain(); - } + if (window != 0) + { + [window makeKeyWindow]; + viewFocusGain(); + } } void UIViewComponentPeer::textInputRequired (int /*x*/, int /*y*/) @@ -263764,39 +241348,39 @@ void UIViewComponentPeer::textInputRequired (int /*x*/, int /*y*/) void UIViewComponentPeer::drawRect (CGRect r) { - if (r.size.width < 1.0f || r.size.height < 1.0f) - return; + if (r.size.width < 1.0f || r.size.height < 1.0f) + return; - CGContextRef cg = UIGraphicsGetCurrentContext(); + CGContextRef cg = UIGraphicsGetCurrentContext(); - if (! component->isOpaque()) - CGContextClearRect (cg, CGContextGetClipBoundingBox (cg)); + if (! component->isOpaque()) + CGContextClearRect (cg, CGContextGetClipBoundingBox (cg)); - CGContextConcatCTM (cg, CGAffineTransformMake (1, 0, 0, -1, 0, view.bounds.size.height)); - CoreGraphicsContext g (cg, view.bounds.size.height); + CGContextConcatCTM (cg, CGAffineTransformMake (1, 0, 0, -1, 0, view.bounds.size.height)); + CoreGraphicsContext g (cg, view.bounds.size.height); - insideDrawRect = true; - handlePaint (g); - insideDrawRect = false; + insideDrawRect = true; + handlePaint (g); + insideDrawRect = false; } bool UIViewComponentPeer::canBecomeKeyWindow() { - return (getStyleFlags() & JUCE_NAMESPACE::ComponentPeer::windowIgnoresKeyPresses) == 0; + return (getStyleFlags() & JUCE_NAMESPACE::ComponentPeer::windowIgnoresKeyPresses) == 0; } bool UIViewComponentPeer::windowShouldClose() { - if (! isValidPeer (this)) - return YES; + if (! isValidPeer (this)) + return YES; - handleUserClosingWindow(); - return NO; + handleUserClosingWindow(); + return NO; } void UIViewComponentPeer::redirectMovedOrResized() { - handleMovedOrResized(); + handleMovedOrResized(); } void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool allowMenusAndBars) @@ -263806,31 +241390,31 @@ void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable class AsyncRepaintMessage : public CallbackMessage { public: - UIViewComponentPeer* const peer; - const Rectangle rect; + UIViewComponentPeer* const peer; + const Rectangle rect; - AsyncRepaintMessage (UIViewComponentPeer* const peer_, const Rectangle& rect_) - : peer (peer_), rect (rect_) - { - } + AsyncRepaintMessage (UIViewComponentPeer* const peer_, const Rectangle& rect_) + : peer (peer_), rect (rect_) + { + } - void messageCallback() - { - if (ComponentPeer::isValidPeer (peer)) - peer->repaint (rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); - } + void messageCallback() + { + if (ComponentPeer::isValidPeer (peer)) + peer->repaint (rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); + } }; void UIViewComponentPeer::repaint (int x, int y, int w, int h) { - if (insideDrawRect || ! MessageManager::getInstance()->isThisTheMessageThread()) - { - (new AsyncRepaintMessage (this, Rectangle (x, y, w, h)))->post(); - } - else - { - [view setNeedsDisplayInRect: CGRectMake ((float) x, (float) y, (float) w, (float) h)]; - } + if (insideDrawRect || ! MessageManager::getInstance()->isThisTheMessageThread()) + { + (new AsyncRepaintMessage (this, Rectangle (x, y, w, h)))->post(); + } + else + { + [view setNeedsDisplayInRect: CGRectMake ((float) x, (float) y, (float) w, (float) h)]; + } } void UIViewComponentPeer::performAnyPendingRepaintsNow() @@ -263839,82 +241423,82 @@ void UIViewComponentPeer::performAnyPendingRepaintsNow() ComponentPeer* Component::createNewPeer (int styleFlags, void* windowToAttachTo) { - return new UIViewComponentPeer (this, styleFlags, (UIView*) windowToAttachTo); + return new UIViewComponentPeer (this, styleFlags, (UIView*) windowToAttachTo); } Image* juce_createIconForFile (const File& file) { - return 0; + return 0; } bool Desktop::canUseSemiTransparentWindows() throw() { - return true; + return true; } void Desktop::getMousePosition (int& x, int& y) throw() { - x = juce_lastMouseX; - y = juce_lastMouseY; + x = juce_lastMouseX; + y = juce_lastMouseY; } void Desktop::setMousePosition (int x, int y) throw() { } -const int KeyPress::spaceKey = ' '; -const int KeyPress::returnKey = 0x0d; -const int KeyPress::escapeKey = 0x1b; -const int KeyPress::backspaceKey = 0x7f; -const int KeyPress::leftKey = 0x1000; -const int KeyPress::rightKey = 0x1001; -const int KeyPress::upKey = 0x1002; -const int KeyPress::downKey = 0x1003; -const int KeyPress::pageUpKey = 0x1004; -const int KeyPress::pageDownKey = 0x1005; -const int KeyPress::endKey = 0x1006; -const int KeyPress::homeKey = 0x1007; -const int KeyPress::deleteKey = 0x1008; -const int KeyPress::insertKey = -1; -const int KeyPress::tabKey = 9; -const int KeyPress::F1Key = 0x2001; -const int KeyPress::F2Key = 0x2002; -const int KeyPress::F3Key = 0x2003; -const int KeyPress::F4Key = 0x2004; -const int KeyPress::F5Key = 0x2005; -const int KeyPress::F6Key = 0x2006; -const int KeyPress::F7Key = 0x2007; -const int KeyPress::F8Key = 0x2008; -const int KeyPress::F9Key = 0x2009; -const int KeyPress::F10Key = 0x200a; -const int KeyPress::F11Key = 0x200b; -const int KeyPress::F12Key = 0x200c; -const int KeyPress::F13Key = 0x200d; -const int KeyPress::F14Key = 0x200e; -const int KeyPress::F15Key = 0x200f; -const int KeyPress::F16Key = 0x2010; -const int KeyPress::numberPad0 = 0x30020; -const int KeyPress::numberPad1 = 0x30021; -const int KeyPress::numberPad2 = 0x30022; -const int KeyPress::numberPad3 = 0x30023; -const int KeyPress::numberPad4 = 0x30024; -const int KeyPress::numberPad5 = 0x30025; -const int KeyPress::numberPad6 = 0x30026; -const int KeyPress::numberPad7 = 0x30027; -const int KeyPress::numberPad8 = 0x30028; -const int KeyPress::numberPad9 = 0x30029; -const int KeyPress::numberPadAdd = 0x3002a; -const int KeyPress::numberPadSubtract = 0x3002b; -const int KeyPress::numberPadMultiply = 0x3002c; -const int KeyPress::numberPadDivide = 0x3002d; -const int KeyPress::numberPadSeparator = 0x3002e; +const int KeyPress::spaceKey = ' '; +const int KeyPress::returnKey = 0x0d; +const int KeyPress::escapeKey = 0x1b; +const int KeyPress::backspaceKey = 0x7f; +const int KeyPress::leftKey = 0x1000; +const int KeyPress::rightKey = 0x1001; +const int KeyPress::upKey = 0x1002; +const int KeyPress::downKey = 0x1003; +const int KeyPress::pageUpKey = 0x1004; +const int KeyPress::pageDownKey = 0x1005; +const int KeyPress::endKey = 0x1006; +const int KeyPress::homeKey = 0x1007; +const int KeyPress::deleteKey = 0x1008; +const int KeyPress::insertKey = -1; +const int KeyPress::tabKey = 9; +const int KeyPress::F1Key = 0x2001; +const int KeyPress::F2Key = 0x2002; +const int KeyPress::F3Key = 0x2003; +const int KeyPress::F4Key = 0x2004; +const int KeyPress::F5Key = 0x2005; +const int KeyPress::F6Key = 0x2006; +const int KeyPress::F7Key = 0x2007; +const int KeyPress::F8Key = 0x2008; +const int KeyPress::F9Key = 0x2009; +const int KeyPress::F10Key = 0x200a; +const int KeyPress::F11Key = 0x200b; +const int KeyPress::F12Key = 0x200c; +const int KeyPress::F13Key = 0x200d; +const int KeyPress::F14Key = 0x200e; +const int KeyPress::F15Key = 0x200f; +const int KeyPress::F16Key = 0x2010; +const int KeyPress::numberPad0 = 0x30020; +const int KeyPress::numberPad1 = 0x30021; +const int KeyPress::numberPad2 = 0x30022; +const int KeyPress::numberPad3 = 0x30023; +const int KeyPress::numberPad4 = 0x30024; +const int KeyPress::numberPad5 = 0x30025; +const int KeyPress::numberPad6 = 0x30026; +const int KeyPress::numberPad7 = 0x30027; +const int KeyPress::numberPad8 = 0x30028; +const int KeyPress::numberPad9 = 0x30029; +const int KeyPress::numberPadAdd = 0x3002a; +const int KeyPress::numberPadSubtract = 0x3002b; +const int KeyPress::numberPadMultiply = 0x3002c; +const int KeyPress::numberPadDivide = 0x3002d; +const int KeyPress::numberPadSeparator = 0x3002e; const int KeyPress::numberPadDecimalPoint = 0x3002f; -const int KeyPress::numberPadEquals = 0x30030; -const int KeyPress::numberPadDelete = 0x30031; -const int KeyPress::playKey = 0x30000; -const int KeyPress::stopKey = 0x30001; +const int KeyPress::numberPadEquals = 0x30030; +const int KeyPress::numberPadDelete = 0x30031; +const int KeyPress::playKey = 0x30000; +const int KeyPress::stopKey = 0x30001; const int KeyPress::fastForwardKey = 0x30002; -const int KeyPress::rewindKey = 0x30003; +const int KeyPress::rewindKey = 0x30003; #endif /********* End of inlined file: juce_iphone_UIViewComponentPeer.mm *********/ @@ -263926,10 +241510,10 @@ const int KeyPress::rewindKey = 0x30003; struct CallbackMessagePayload { - MessageCallbackFunction* function; - void* parameter; - void* volatile result; - bool volatile hasBeenExecuted; + MessageCallbackFunction* function; + void* parameter; + void* volatile result; + bool volatile hasBeenExecuted; }; END_JUCE_NAMESPACE @@ -263953,72 +241537,72 @@ using namespace JUCE_NAMESPACE; - (JuceAppDelegate*) init { - [super init]; + [super init]; - [[UIApplication sharedApplication] setDelegate: self]; + [[UIApplication sharedApplication] setDelegate: self]; - return self; + return self; } - (void) dealloc { - [[UIApplication sharedApplication] setDelegate: nil]; - [super dealloc]; + [[UIApplication sharedApplication] setDelegate: nil]; + [super dealloc]; } - (BOOL) application: (UIApplication*) application handleOpenURL: (NSURL*) url { - if (JUCEApplication::getInstance() != 0) - { - JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce ([url absoluteString])); - return YES; - } + if (JUCEApplication::getInstance() != 0) + { + JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce ([url absoluteString])); + return YES; + } - return NO; + return NO; } - (void) applicationDidBecomeActive: (NSNotification*) aNotification { - juce_HandleProcessFocusChange(); + juce_HandleProcessFocusChange(); } - (void) applicationDidResignActive: (NSNotification*) aNotification { - juce_HandleProcessFocusChange(); + juce_HandleProcessFocusChange(); } - (void) applicationWillUnhide: (NSNotification*) aNotification { - juce_HandleProcessFocusChange(); + juce_HandleProcessFocusChange(); } - (void) customEvent: (id) n { - NSData* data = (NSData*) n; - void* message = 0; - [data getBytes: &message length: sizeof (message)]; - [data release]; + NSData* data = (NSData*) n; + void* message = 0; + [data getBytes: &message length: sizeof (message)]; + [data release]; - if (message != 0) - MessageManager::getInstance()->deliverMessage (message); + if (message != 0) + MessageManager::getInstance()->deliverMessage (message); } - (void) performCallback: (id) info { - if ([info isKindOfClass: [NSData class]]) - { - CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes]; + if ([info isKindOfClass: [NSData class]]) + { + CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes]; - if (pl != 0) - { - pl->result = (*pl->function) (pl->parameter); - pl->hasBeenExecuted = true; - } - } - else - { - jassertfalse // should never get here! - } + if (pl != 0) + { + pl->result = (*pl->function) (pl->parameter); + pl->hasBeenExecuted = true; + } + } + else + { + jassertfalse // should never get here! + } } @end @@ -264029,37 +241613,37 @@ static JuceAppDelegate* juceAppDelegate = 0; void MessageManager::runDispatchLoop() { - jassert (isThisTheMessageThread()); // must only be called by the message thread - runDispatchLoopUntil (-1); + jassert (isThisTheMessageThread()); // must only be called by the message thread + runDispatchLoopUntil (-1); } static const int quitMessageId = 0xfffff321; void MessageManager::stopDispatchLoop() { - exit (0); // iPhone apps get no mercy.. + exit (0); // iPhone apps get no mercy.. } bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) { - const ScopedAutoReleasePool pool; - jassert (isThisTheMessageThread()); // must only be called by the message thread + const ScopedAutoReleasePool pool; + jassert (isThisTheMessageThread()); // must only be called by the message thread - uint32 endTime = Time::getMillisecondCounter() + millisecondsToRunFor; - NSDate* endDate = [NSDate dateWithTimeIntervalSinceNow: millisecondsToRunFor * 0.001]; + uint32 endTime = Time::getMillisecondCounter() + millisecondsToRunFor; + NSDate* endDate = [NSDate dateWithTimeIntervalSinceNow: millisecondsToRunFor * 0.001]; - while (! quitMessagePosted) - { - const ScopedAutoReleasePool pool; + while (! quitMessagePosted) + { + const ScopedAutoReleasePool pool; - [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode - beforeDate: endDate]; + [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode + beforeDate: endDate]; - if (millisecondsToRunFor >= 0 && Time::getMillisecondCounter() >= endTime) - break; - } + if (millisecondsToRunFor >= 0 && Time::getMillisecondCounter() >= endTime) + break; + } - return ! quitMessagePosted; + return ! quitMessagePosted; } static CFRunLoopRef runLoop = 0; @@ -264068,74 +241652,74 @@ static Array * pendingMessages = 0; static void runLoopSourceCallback (void*) { - if (pendingMessages != 0) - { - int numDispatched = 0; + if (pendingMessages != 0) + { + int numDispatched = 0; - do - { - void* const nextMessage = pendingMessages->remove (0); + do + { + void* const nextMessage = pendingMessages->remove (0); - if (nextMessage == 0) - return; + if (nextMessage == 0) + return; - const ScopedAutoReleasePool pool; - MessageManager::getInstance()->deliverMessage (nextMessage); + const ScopedAutoReleasePool pool; + MessageManager::getInstance()->deliverMessage (nextMessage); - } while (++numDispatched <= 4); + } while (++numDispatched <= 4); - CFRunLoopSourceSignal (runLoopSource); - CFRunLoopWakeUp (runLoop); - } + CFRunLoopSourceSignal (runLoopSource); + CFRunLoopWakeUp (runLoop); + } } void MessageManager::doPlatformSpecificInitialisation() { - pendingMessages = new Array (); + pendingMessages = new Array (); - runLoop = CFRunLoopGetCurrent(); - CFRunLoopSourceContext sourceContext; - zerostruct (sourceContext); - sourceContext.perform = runLoopSourceCallback; - runLoopSource = CFRunLoopSourceCreate (kCFAllocatorDefault, 1, &sourceContext); - CFRunLoopAddSource (runLoop, runLoopSource, kCFRunLoopCommonModes); + runLoop = CFRunLoopGetCurrent(); + CFRunLoopSourceContext sourceContext; + zerostruct (sourceContext); + sourceContext.perform = runLoopSourceCallback; + runLoopSource = CFRunLoopSourceCreate (kCFAllocatorDefault, 1, &sourceContext); + CFRunLoopAddSource (runLoop, runLoopSource, kCFRunLoopCommonModes); - if (juceAppDelegate == 0) - juceAppDelegate = [[JuceAppDelegate alloc] init]; + if (juceAppDelegate == 0) + juceAppDelegate = [[JuceAppDelegate alloc] init]; } void MessageManager::doPlatformSpecificShutdown() { - CFRunLoopSourceInvalidate (runLoopSource); - CFRelease (runLoopSource); - runLoopSource = 0; + CFRunLoopSourceInvalidate (runLoopSource); + CFRelease (runLoopSource); + runLoopSource = 0; - if (pendingMessages != 0) - { - while (pendingMessages->size() > 0) - delete ((Message*) pendingMessages->remove(0)); + if (pendingMessages != 0) + { + while (pendingMessages->size() > 0) + delete ((Message*) pendingMessages->remove(0)); - deleteAndZero (pendingMessages); - } + deleteAndZero (pendingMessages); + } - if (juceAppDelegate != 0) - { - [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate]; - [juceAppDelegate release]; - juceAppDelegate = 0; - } + if (juceAppDelegate != 0) + { + [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate]; + [juceAppDelegate release]; + juceAppDelegate = 0; + } } bool juce_postMessageToSystemQueue (void* message) { - if (pendingMessages != 0) - { - pendingMessages->add (message); - CFRunLoopSourceSignal (runLoopSource); - CFRunLoopWakeUp (runLoop); - } + if (pendingMessages != 0) + { + pendingMessages->add (message); + CFRunLoopSourceSignal (runLoopSource); + CFRunLoopWakeUp (runLoop); + } - return true; + return true; } void MessageManager::broadcastMessage (const String& value) throw() @@ -264143,35 +241727,35 @@ void MessageManager::broadcastMessage (const String& value) throw() } void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, - void* data) + void* data) { - if (isThisTheMessageThread()) - { - return (*callback) (data); - } - else - { - // If a thread has a MessageManagerLock and then tries to call this method, it'll - // deadlock because the message manager is blocked from running, so can never - // call your function.. - jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager()); + if (isThisTheMessageThread()) + { + return (*callback) (data); + } + else + { + // If a thread has a MessageManagerLock and then tries to call this method, it'll + // deadlock because the message manager is blocked from running, so can never + // call your function.. + jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - CallbackMessagePayload cmp; - cmp.function = callback; - cmp.parameter = data; - cmp.result = 0; - cmp.hasBeenExecuted = false; + CallbackMessagePayload cmp; + cmp.function = callback; + cmp.parameter = data; + cmp.result = 0; + cmp.hasBeenExecuted = false; - [juceAppDelegate performSelectorOnMainThread: @selector (performCallback:) - withObject: [NSData dataWithBytesNoCopy: &cmp - length: sizeof (cmp) - freeWhenDone: NO] - waitUntilDone: YES]; + [juceAppDelegate performSelectorOnMainThread: @selector (performCallback:) + withObject: [NSData dataWithBytesNoCopy: &cmp + length: sizeof (cmp) + freeWhenDone: NO] + waitUntilDone: YES]; - return cmp.result; - } + return cmp.result; + } } #endif @@ -264195,7 +241779,7 @@ using namespace JUCE_NAMESPACE; @interface JuceFileChooserDelegate : NSObject #endif { - StringArray* filters; + StringArray* filters; } - (JuceFileChooserDelegate*) initWithFilters: (StringArray*) filters_; @@ -264207,118 +241791,118 @@ using namespace JUCE_NAMESPACE; @implementation JuceFileChooserDelegate - (JuceFileChooserDelegate*) initWithFilters: (StringArray*) filters_ { - [super init]; - filters = filters_; - return self; + [super init]; + filters = filters_; + return self; } - (void) dealloc { - delete filters; - [super dealloc]; + delete filters; + [super dealloc]; } - (BOOL) panel: (id) sender shouldShowFilename: (NSString*) filename { - const String fname (nsStringToJuce (filename)); + const String fname (nsStringToJuce (filename)); - for (int i = filters->size(); --i >= 0;) - if (fname.matchesWildcard ((*filters)[i], true)) - return true; + for (int i = filters->size(); --i >= 0;) + if (fname.matchesWildcard ((*filters)[i], true)) + return true; - return File (fname).isDirectory(); + return File (fname).isDirectory(); } @end BEGIN_JUCE_NAMESPACE void FileChooser::showPlatformDialog (OwnedArray& results, - const String& title, - const File& currentFileOrDirectory, - const String& filter, - bool selectsDirectory, - bool selectsFiles, - bool isSaveDialogue, - bool warnAboutOverwritingExistingFiles, - bool selectMultipleFiles, - FilePreviewComponent* extraInfoComponent) + const String& title, + const File& currentFileOrDirectory, + const String& filter, + bool selectsDirectory, + bool selectsFiles, + bool isSaveDialogue, + bool warnAboutOverwritingExistingFiles, + bool selectMultipleFiles, + FilePreviewComponent* extraInfoComponent) { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - StringArray* filters = new StringArray(); - filters->addTokens (filter.replaceCharacters (T(",:"), T(";;")), T(";"), 0); - filters->trim(); - filters->removeEmptyStrings(); + StringArray* filters = new StringArray(); + filters->addTokens (filter.replaceCharacters (T(",:"), T(";;")), T(";"), 0); + filters->trim(); + filters->removeEmptyStrings(); - JuceFileChooserDelegate* delegate = [[JuceFileChooserDelegate alloc] initWithFilters: filters]; - [delegate autorelease]; + JuceFileChooserDelegate* delegate = [[JuceFileChooserDelegate alloc] initWithFilters: filters]; + [delegate autorelease]; - NSSavePanel* panel = isSaveDialogue ? [NSSavePanel savePanel] - : [NSOpenPanel openPanel]; + NSSavePanel* panel = isSaveDialogue ? [NSSavePanel savePanel] + : [NSOpenPanel openPanel]; - [panel setTitle: juceStringToNS (title)]; + [panel setTitle: juceStringToNS (title)]; - if (! isSaveDialogue) - { - NSOpenPanel* openPanel = (NSOpenPanel*) panel; - [openPanel setCanChooseDirectories: selectsDirectory]; - [openPanel setCanChooseFiles: selectsFiles]; - [openPanel setAllowsMultipleSelection: selectMultipleFiles]; - } + if (! isSaveDialogue) + { + NSOpenPanel* openPanel = (NSOpenPanel*) panel; + [openPanel setCanChooseDirectories: selectsDirectory]; + [openPanel setCanChooseFiles: selectsFiles]; + [openPanel setAllowsMultipleSelection: selectMultipleFiles]; + } - [panel setDelegate: delegate]; + [panel setDelegate: delegate]; - String directory, filename; + String directory, filename; - if (currentFileOrDirectory.isDirectory()) - { - directory = currentFileOrDirectory.getFullPathName(); - } - else - { - directory = currentFileOrDirectory.getParentDirectory().getFullPathName(); - filename = currentFileOrDirectory.getFileName(); - } + if (currentFileOrDirectory.isDirectory()) + { + directory = currentFileOrDirectory.getFullPathName(); + } + else + { + directory = currentFileOrDirectory.getParentDirectory().getFullPathName(); + filename = currentFileOrDirectory.getFileName(); + } - if ([panel runModalForDirectory: juceStringToNS (directory) - file: juceStringToNS (filename)] - == NSOKButton) - { - if (isSaveDialogue) - { - results.add (new File (nsStringToJuce ([panel filename]))); - } - else - { - NSOpenPanel* openPanel = (NSOpenPanel*) panel; - NSArray* urls = [openPanel filenames]; - for (unsigned int i = 0; i < [urls count]; ++i) - { - NSString* f = [urls objectAtIndex: i]; - results.add (new File (nsStringToJuce (f))); - } - } - } + if ([panel runModalForDirectory: juceStringToNS (directory) + file: juceStringToNS (filename)] + == NSOKButton) + { + if (isSaveDialogue) + { + results.add (new File (nsStringToJuce ([panel filename]))); + } + else + { + NSOpenPanel* openPanel = (NSOpenPanel*) panel; + NSArray* urls = [openPanel filenames]; + for (unsigned int i = 0; i < [urls count]; ++i) + { + NSString* f = [urls objectAtIndex: i]; + results.add (new File (nsStringToJuce (f))); + } + } + } - [panel setDelegate: nil]; + [panel setDelegate: nil]; } #else void FileChooser::showPlatformDialog (OwnedArray& results, - const String& title, - const File& currentFileOrDirectory, - const String& filter, - bool selectsDirectory, - bool selectsFiles, - bool isSaveDialogue, - bool warnAboutOverwritingExistingFiles, - bool selectMultipleFiles, - FilePreviewComponent* extraInfoComponent) + const String& title, + const File& currentFileOrDirectory, + const String& filter, + bool selectsDirectory, + bool selectsFiles, + bool isSaveDialogue, + bool warnAboutOverwritingExistingFiles, + bool selectMultipleFiles, + FilePreviewComponent* extraInfoComponent) { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - jassertfalse //xxx to do + jassertfalse //xxx to do } #endif @@ -264339,8 +241923,8 @@ END_JUCE_NAMESPACE @interface ThreadSafeNSOpenGLView : NSOpenGLView { - CriticalSection* contextLock; - bool needsUpdate; + CriticalSection* contextLock; + bool needsUpdate; } - (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format; @@ -264352,279 +241936,279 @@ END_JUCE_NAMESPACE @implementation ThreadSafeNSOpenGLView - (id) initWithFrame: (NSRect) frameRect - pixelFormat: (NSOpenGLPixelFormat*) format + pixelFormat: (NSOpenGLPixelFormat*) format { - contextLock = new CriticalSection(); - self = [super initWithFrame: frameRect pixelFormat: format]; + contextLock = new CriticalSection(); + self = [super initWithFrame: frameRect pixelFormat: format]; - if (self != nil) - [[NSNotificationCenter defaultCenter] addObserver: self - selector: @selector (_surfaceNeedsUpdate:) - name: NSViewGlobalFrameDidChangeNotification - object: self]; - return self; + if (self != nil) + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector (_surfaceNeedsUpdate:) + name: NSViewGlobalFrameDidChangeNotification + object: self]; + return self; } - (void) dealloc { - [[NSNotificationCenter defaultCenter] removeObserver: self]; - delete contextLock; - [super dealloc]; + [[NSNotificationCenter defaultCenter] removeObserver: self]; + delete contextLock; + [super dealloc]; } - (bool) makeActive { - const ScopedLock sl (*contextLock); + const ScopedLock sl (*contextLock); - if ([self openGLContext] == 0) - return false; + if ([self openGLContext] == 0) + return false; - [[self openGLContext] makeCurrentContext]; + [[self openGLContext] makeCurrentContext]; - if (needsUpdate) - { - [super update]; - needsUpdate = false; - } + if (needsUpdate) + { + [super update]; + needsUpdate = false; + } - return true; + return true; } - (void) makeInactive { - const ScopedLock sl (*contextLock); - [NSOpenGLContext clearCurrentContext]; + const ScopedLock sl (*contextLock); + [NSOpenGLContext clearCurrentContext]; } - (void) _surfaceNeedsUpdate: (NSNotification*) notification { - const ScopedLock sl (*contextLock); - needsUpdate = true; + const ScopedLock sl (*contextLock); + needsUpdate = true; } - (void) update { - const ScopedLock sl (*contextLock); - needsUpdate = true; + const ScopedLock sl (*contextLock); + needsUpdate = true; } - (void) reshape { - const ScopedLock sl (*contextLock); - needsUpdate = true; + const ScopedLock sl (*contextLock); + needsUpdate = true; } @end BEGIN_JUCE_NAMESPACE -class WindowedGLContext : public OpenGLContext +class WindowedGLContext : public OpenGLContext { public: - WindowedGLContext (Component* const component, - const OpenGLPixelFormat& pixelFormat_, - NSOpenGLContext* sharedContext) - : renderContext (0), - pixelFormat (pixelFormat_) - { - jassert (component != 0); + WindowedGLContext (Component* const component, + const OpenGLPixelFormat& pixelFormat_, + NSOpenGLContext* sharedContext) + : renderContext (0), + pixelFormat (pixelFormat_) + { + jassert (component != 0); - NSOpenGLPixelFormatAttribute attribs [64]; - int n = 0; - attribs[n++] = NSOpenGLPFADoubleBuffer; - attribs[n++] = NSOpenGLPFAAccelerated; - attribs[n++] = NSOpenGLPFAMPSafe; // NSOpenGLPFAAccelerated, NSOpenGLPFAMultiScreen, NSOpenGLPFASingleRenderer - attribs[n++] = NSOpenGLPFAColorSize; - attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits, - pixelFormat.greenBits, - pixelFormat.blueBits); - attribs[n++] = NSOpenGLPFAAlphaSize; - attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.alphaBits; - attribs[n++] = NSOpenGLPFADepthSize; - attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.depthBufferBits; - attribs[n++] = NSOpenGLPFAStencilSize; - attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.stencilBufferBits; - attribs[n++] = NSOpenGLPFAAccumSize; - attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.accumulationBufferRedBits, - pixelFormat.accumulationBufferGreenBits, - pixelFormat.accumulationBufferBlueBits, - pixelFormat.accumulationBufferAlphaBits); + NSOpenGLPixelFormatAttribute attribs [64]; + int n = 0; + attribs[n++] = NSOpenGLPFADoubleBuffer; + attribs[n++] = NSOpenGLPFAAccelerated; + attribs[n++] = NSOpenGLPFAMPSafe; // NSOpenGLPFAAccelerated, NSOpenGLPFAMultiScreen, NSOpenGLPFASingleRenderer + attribs[n++] = NSOpenGLPFAColorSize; + attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits, + pixelFormat.greenBits, + pixelFormat.blueBits); + attribs[n++] = NSOpenGLPFAAlphaSize; + attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.alphaBits; + attribs[n++] = NSOpenGLPFADepthSize; + attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.depthBufferBits; + attribs[n++] = NSOpenGLPFAStencilSize; + attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.stencilBufferBits; + attribs[n++] = NSOpenGLPFAAccumSize; + attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.accumulationBufferRedBits, + pixelFormat.accumulationBufferGreenBits, + pixelFormat.accumulationBufferBlueBits, + pixelFormat.accumulationBufferAlphaBits); - // xxx not sure how to do fullSceneAntiAliasingNumSamples.. - attribs[n++] = NSOpenGLPFASampleBuffers; - attribs[n++] = (NSOpenGLPixelFormatAttribute) 1; - attribs[n++] = NSOpenGLPFAClosestPolicy; - attribs[n++] = NSOpenGLPFANoRecovery; - attribs[n++] = (NSOpenGLPixelFormatAttribute) 0; + // xxx not sure how to do fullSceneAntiAliasingNumSamples.. + attribs[n++] = NSOpenGLPFASampleBuffers; + attribs[n++] = (NSOpenGLPixelFormatAttribute) 1; + attribs[n++] = NSOpenGLPFAClosestPolicy; + attribs[n++] = NSOpenGLPFANoRecovery; + attribs[n++] = (NSOpenGLPixelFormatAttribute) 0; - NSOpenGLPixelFormat* format - = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; + NSOpenGLPixelFormat* format + = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; - view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) - pixelFormat: format]; + view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) + pixelFormat: format]; - renderContext = [[[NSOpenGLContext alloc] initWithFormat: format - shareContext: sharedContext] autorelease]; + renderContext = [[[NSOpenGLContext alloc] initWithFormat: format + shareContext: sharedContext] autorelease]; - const GLint swapInterval = 1; - [renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; + const GLint swapInterval = 1; + [renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; - [view setOpenGLContext: renderContext]; - [renderContext setView: view]; + [view setOpenGLContext: renderContext]; + [renderContext setView: view]; - [format release]; + [format release]; - viewHolder = new NSViewComponentInternal (view, component); - } + viewHolder = new NSViewComponentInternal (view, component); + } - ~WindowedGLContext() - { - makeInactive(); - [renderContext clearDrawable]; - delete viewHolder; - } + ~WindowedGLContext() + { + makeInactive(); + [renderContext clearDrawable]; + viewHolder = 0; + } - bool makeActive() const throw() - { - jassert (renderContext != 0); - [view makeActive]; - return isActive(); - } + bool makeActive() const throw() + { + jassert (renderContext != 0); + [view makeActive]; + return isActive(); + } - bool makeInactive() const throw() - { - [view makeInactive]; - return true; - } + bool makeInactive() const throw() + { + [view makeInactive]; + return true; + } - bool isActive() const throw() - { - return [NSOpenGLContext currentContext] == renderContext; - } + bool isActive() const throw() + { + return [NSOpenGLContext currentContext] == renderContext; + } - const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; } - void* getRawContext() const throw() { return renderContext; } + const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; } + void* getRawContext() const throw() { return renderContext; } - void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight) - { - } + void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight) + { + } - void swapBuffers() - { - [renderContext flushBuffer]; - } + void swapBuffers() + { + [renderContext flushBuffer]; + } - bool setSwapInterval (const int numFramesPerSwap) - { - [renderContext setValues: (const GLint*) &numFramesPerSwap - forParameter: NSOpenGLCPSwapInterval]; - return true; - } + bool setSwapInterval (const int numFramesPerSwap) + { + [renderContext setValues: (const GLint*) &numFramesPerSwap + forParameter: NSOpenGLCPSwapInterval]; + return true; + } - int getSwapInterval() const - { - GLint numFrames = 0; - [renderContext getValues: &numFrames - forParameter: NSOpenGLCPSwapInterval]; - return numFrames; - } + int getSwapInterval() const + { + GLint numFrames = 0; + [renderContext getValues: &numFrames + forParameter: NSOpenGLCPSwapInterval]; + return numFrames; + } - void repaint() - { - // we need to invalidate the juce view that holds this gl view, to make it - // cause a repaint callback - NSView* v = (NSView*) viewHolder->view; - NSRect r = [v frame]; + void repaint() + { + // we need to invalidate the juce view that holds this gl view, to make it + // cause a repaint callback + NSView* v = (NSView*) viewHolder->view; + NSRect r = [v frame]; - // bit of a bodge here.. if we only invalidate the area of the gl component, - // it's completely covered by the NSOpenGLView, so the OS throws away the - // repaint message, thus never causing our paint() callback, and never repainting - // the comp. So invalidating just a little bit around the edge helps.. - [[v superview] setNeedsDisplayInRect: NSInsetRect (r, -2.0f, -2.0f)]; - } + // bit of a bodge here.. if we only invalidate the area of the gl component, + // it's completely covered by the NSOpenGLView, so the OS throws away the + // repaint message, thus never causing our paint() callback, and never repainting + // the comp. So invalidating just a little bit around the edge helps.. + [[v superview] setNeedsDisplayInRect: NSInsetRect (r, -2.0f, -2.0f)]; + } - void* getNativeWindowHandle() const { return viewHolder->view; } + void* getNativeWindowHandle() const { return viewHolder->view; } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - NSOpenGLContext* renderContext; - ThreadSafeNSOpenGLView* view; + NSOpenGLContext* renderContext; + ThreadSafeNSOpenGLView* view; private: - OpenGLPixelFormat pixelFormat; - NSViewComponentInternal* viewHolder; + OpenGLPixelFormat pixelFormat; + ScopedPointer viewHolder; - WindowedGLContext (const WindowedGLContext&); - const WindowedGLContext& operator= (const WindowedGLContext&); + WindowedGLContext (const WindowedGLContext&); + const WindowedGLContext& operator= (const WindowedGLContext&); }; OpenGLContext* OpenGLContext::createContextForWindow (Component* const component, - const OpenGLPixelFormat& pixelFormat, - const OpenGLContext* const contextToShareWith) + const OpenGLPixelFormat& pixelFormat, + const OpenGLContext* const contextToShareWith) { - ScopedPointer c (new WindowedGLContext (component, pixelFormat, - contextToShareWith != 0 ? (NSOpenGLContext*) contextToShareWith->getRawContext() : 0)); + ScopedPointer c (new WindowedGLContext (component, pixelFormat, + contextToShareWith != 0 ? (NSOpenGLContext*) contextToShareWith->getRawContext() : 0)); - return (c->renderContext != 0) ? c.release() : 0; + return (c->renderContext != 0) ? c.release() : 0; } void* OpenGLComponent::getNativeWindowHandle() const { - return context != 0 ? ((WindowedGLContext*) context)->getNativeWindowHandle() - : 0; + return context != 0 ? ((WindowedGLContext*) context)->getNativeWindowHandle() + : 0; } void juce_glViewport (const int w, const int h) { - glViewport (0, 0, w, h); + glViewport (0, 0, w, h); } void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/, - OwnedArray & results) + OwnedArray & results) { -/* GLint attribs [64]; - int n = 0; - attribs[n++] = AGL_RGBA; - attribs[n++] = AGL_DOUBLEBUFFER; - attribs[n++] = AGL_ACCELERATED; - attribs[n++] = AGL_NO_RECOVERY; - attribs[n++] = AGL_NONE; +/* GLint attribs [64]; + int n = 0; + attribs[n++] = AGL_RGBA; + attribs[n++] = AGL_DOUBLEBUFFER; + attribs[n++] = AGL_ACCELERATED; + attribs[n++] = AGL_NO_RECOVERY; + attribs[n++] = AGL_NONE; - AGLPixelFormat p = aglChoosePixelFormat (0, 0, attribs); + AGLPixelFormat p = aglChoosePixelFormat (0, 0, attribs); - while (p != 0) - { - OpenGLPixelFormat* const pf = new OpenGLPixelFormat(); - pf->redBits = getAGLAttribute (p, AGL_RED_SIZE); - pf->greenBits = getAGLAttribute (p, AGL_GREEN_SIZE); - pf->blueBits = getAGLAttribute (p, AGL_BLUE_SIZE); - pf->alphaBits = getAGLAttribute (p, AGL_ALPHA_SIZE); - pf->depthBufferBits = getAGLAttribute (p, AGL_DEPTH_SIZE); - pf->stencilBufferBits = getAGLAttribute (p, AGL_STENCIL_SIZE); - pf->accumulationBufferRedBits = getAGLAttribute (p, AGL_ACCUM_RED_SIZE); - pf->accumulationBufferGreenBits = getAGLAttribute (p, AGL_ACCUM_GREEN_SIZE); - pf->accumulationBufferBlueBits = getAGLAttribute (p, AGL_ACCUM_BLUE_SIZE); - pf->accumulationBufferAlphaBits = getAGLAttribute (p, AGL_ACCUM_ALPHA_SIZE); + while (p != 0) + { + OpenGLPixelFormat* const pf = new OpenGLPixelFormat(); + pf->redBits = getAGLAttribute (p, AGL_RED_SIZE); + pf->greenBits = getAGLAttribute (p, AGL_GREEN_SIZE); + pf->blueBits = getAGLAttribute (p, AGL_BLUE_SIZE); + pf->alphaBits = getAGLAttribute (p, AGL_ALPHA_SIZE); + pf->depthBufferBits = getAGLAttribute (p, AGL_DEPTH_SIZE); + pf->stencilBufferBits = getAGLAttribute (p, AGL_STENCIL_SIZE); + pf->accumulationBufferRedBits = getAGLAttribute (p, AGL_ACCUM_RED_SIZE); + pf->accumulationBufferGreenBits = getAGLAttribute (p, AGL_ACCUM_GREEN_SIZE); + pf->accumulationBufferBlueBits = getAGLAttribute (p, AGL_ACCUM_BLUE_SIZE); + pf->accumulationBufferAlphaBits = getAGLAttribute (p, AGL_ACCUM_ALPHA_SIZE); - results.add (pf); + results.add (pf); - p = aglNextPixelFormat (p); - }*/ + p = aglNextPixelFormat (p); + }*/ - //jassertfalse //xxx can't see how you do this in cocoa! + //jassertfalse //xxx can't see how you do this in cocoa! } #else OpenGLContext* OpenGLContext::createContextForWindow (Component* const component, - const OpenGLPixelFormat& pixelFormat, - const OpenGLContext* const contextToShareWith) + const OpenGLPixelFormat& pixelFormat, + const OpenGLContext* const contextToShareWith) { - return 0; + return 0; } void juce_glViewport (const int w, const int h) { - //glViewport (0, 0, w, h); + //glViewport (0, 0, w, h); } #endif @@ -264641,136 +242225,136 @@ void juce_glViewport (const int w, const int h) void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) throw() { - NSImage* im = CoreGraphicsImage::createNSImage (image); - NSCursor* c = [[NSCursor alloc] initWithImage: im - hotSpot: NSMakePoint (hotspotX, hotspotY)]; - [im release]; + NSImage* im = CoreGraphicsImage::createNSImage (image); + NSCursor* c = [[NSCursor alloc] initWithImage: im + hotSpot: NSMakePoint (hotspotX, hotspotY)]; + [im release]; - return (void*) c; + return (void*) c; } -static void* juce_cursorFromData (const unsigned char* data, const int size, float hx, float hy) throw() +static void* juce_cursorFromData (const unsigned char* data, const size_t size, float hx, float hy) throw() { - ScopedPointer im (ImageFileFormat::loadFrom ((const char*) data, size)); - jassert (im != 0); + ScopedPointer im (ImageFileFormat::loadFrom ((const char*) data, (int) size)); + jassert (im != 0); - if (im == 0) - return 0; + if (im == 0) + return 0; - return juce_createMouseCursorFromImage (*im, - (int) (hx * im->getWidth()), - (int) (hy * im->getHeight())); + return juce_createMouseCursorFromImage (*im, + (int) (hx * im->getWidth()), + (int) (hy * im->getHeight())); } static void* juce_cursorFromWebKitFile (const char* filename, float hx, float hy) { - File f ("/System/Library/Frameworks/WebKit.framework/Frameworks/WebCore.framework/Resources"); + File f ("/System/Library/Frameworks/WebKit.framework/Frameworks/WebCore.framework/Resources"); - MemoryBlock mb; - if (f.getChildFile (filename).loadFileAsData (mb)) - return juce_cursorFromData ((const unsigned char*) mb.getData(), mb.getSize(), hx, hy); + MemoryBlock mb; + if (f.getChildFile (filename).loadFileAsData (mb)) + return juce_cursorFromData ((const unsigned char*) mb.getData(), mb.getSize(), hx, hy); - return 0; + return 0; } void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type) throw() { - const ScopedAutoReleasePool pool; - NSCursor* c = 0; + const ScopedAutoReleasePool pool; + NSCursor* c = 0; - switch (type) - { - case MouseCursor::NormalCursor: - c = [NSCursor arrowCursor]; - break; + switch (type) + { + case MouseCursor::NormalCursor: + c = [NSCursor arrowCursor]; + break; - case MouseCursor::NoCursor: - { - Image blank (Image::ARGB, 8, 8, true); - return juce_createMouseCursorFromImage (blank, 0, 0); - } + case MouseCursor::NoCursor: + { + Image blank (Image::ARGB, 8, 8, true); + return juce_createMouseCursorFromImage (blank, 0, 0); + } - case MouseCursor::DraggingHandCursor: - c = [NSCursor openHandCursor]; - break; + case MouseCursor::DraggingHandCursor: + c = [NSCursor openHandCursor]; + break; - case MouseCursor::CopyingCursor: - return juce_cursorFromWebKitFile ("copyCursor.png", 0, 0); + case MouseCursor::CopyingCursor: + return juce_cursorFromWebKitFile ("copyCursor.png", 0, 0); - case MouseCursor::WaitCursor: - c = [NSCursor arrowCursor]; // avoid this on the mac, let the OS provide the beachball - break; - //return juce_cursorFromWebKitFile ("waitCursor.png", 0.5f, 0.5f); + case MouseCursor::WaitCursor: + c = [NSCursor arrowCursor]; // avoid this on the mac, let the OS provide the beachball + break; + //return juce_cursorFromWebKitFile ("waitCursor.png", 0.5f, 0.5f); - case MouseCursor::IBeamCursor: - c = [NSCursor IBeamCursor]; - break; + case MouseCursor::IBeamCursor: + c = [NSCursor IBeamCursor]; + break; - case MouseCursor::PointingHandCursor: - c = [NSCursor pointingHandCursor]; - break; + case MouseCursor::PointingHandCursor: + c = [NSCursor pointingHandCursor]; + break; - case MouseCursor::LeftRightResizeCursor: - c = [NSCursor resizeLeftRightCursor]; - break; + case MouseCursor::LeftRightResizeCursor: + c = [NSCursor resizeLeftRightCursor]; + break; - case MouseCursor::LeftEdgeResizeCursor: - c = [NSCursor resizeLeftCursor]; - break; + case MouseCursor::LeftEdgeResizeCursor: + c = [NSCursor resizeLeftCursor]; + break; - case MouseCursor::RightEdgeResizeCursor: - c = [NSCursor resizeRightCursor]; - break; + case MouseCursor::RightEdgeResizeCursor: + c = [NSCursor resizeRightCursor]; + break; - case MouseCursor::UpDownResizeCursor: - case MouseCursor::TopEdgeResizeCursor: - case MouseCursor::BottomEdgeResizeCursor: - return juce_cursorFromWebKitFile ("northSouthResizeCursor.png", 0.5f, 0.5f); + case MouseCursor::UpDownResizeCursor: + case MouseCursor::TopEdgeResizeCursor: + case MouseCursor::BottomEdgeResizeCursor: + return juce_cursorFromWebKitFile ("northSouthResizeCursor.png", 0.5f, 0.5f); - case MouseCursor::TopLeftCornerResizeCursor: - case MouseCursor::BottomRightCornerResizeCursor: - return juce_cursorFromWebKitFile ("northWestSouthEastResizeCursor.png", 0.5f, 0.5f); + case MouseCursor::TopLeftCornerResizeCursor: + case MouseCursor::BottomRightCornerResizeCursor: + return juce_cursorFromWebKitFile ("northWestSouthEastResizeCursor.png", 0.5f, 0.5f); - case MouseCursor::TopRightCornerResizeCursor: - case MouseCursor::BottomLeftCornerResizeCursor: - return juce_cursorFromWebKitFile ("northEastSouthWestResizeCursor.png", 0.5f, 0.5f); + case MouseCursor::TopRightCornerResizeCursor: + case MouseCursor::BottomLeftCornerResizeCursor: + return juce_cursorFromWebKitFile ("northEastSouthWestResizeCursor.png", 0.5f, 0.5f); - case MouseCursor::UpDownLeftRightResizeCursor: - return juce_cursorFromWebKitFile ("moveCursor.png", 0.5f, 0.5f); + case MouseCursor::UpDownLeftRightResizeCursor: + return juce_cursorFromWebKitFile ("moveCursor.png", 0.5f, 0.5f); - case MouseCursor::CrosshairCursor: - c = [NSCursor crosshairCursor]; - break; - } + case MouseCursor::CrosshairCursor: + c = [NSCursor crosshairCursor]; + break; + } - [c retain]; - return (void*) c; + [c retain]; + return (void*) c; } void juce_deleteMouseCursor (void* const cursorHandle, const bool isStandard) throw() { - NSCursor* c = (NSCursor*) cursorHandle; - [c release]; + NSCursor* c = (NSCursor*) cursorHandle; + [c release]; } void MouseCursor::showInAllWindows() const throw() { - showInWindow (0); + showInWindow (0); } void MouseCursor::showInWindow (ComponentPeer*) const throw() { - NSCursor* const c = (NSCursor*) getHandle(); - [c set]; + NSCursor* const c = (NSCursor*) getHandle(); + [c set]; } #else void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) throw() { return 0; } -void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type) throw() { return 0; } -void juce_deleteMouseCursor (void* const cursorHandle, const bool isStandard) throw() {} -void MouseCursor::showInAllWindows() const throw() {} -void MouseCursor::showInWindow (ComponentPeer*) const throw() {} +void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type) throw() { return 0; } +void juce_deleteMouseCursor (void* const cursorHandle, const bool isStandard) throw() {} +void MouseCursor::showInAllWindows() const throw() {} +void MouseCursor::showInWindow (ComponentPeer*) const throw() {} #endif @@ -264790,37 +242374,37 @@ END_JUCE_NAMESPACE @interface DownloadClickDetector : NSObject { - JUCE_NAMESPACE::WebBrowserComponent* ownerComponent; + JUCE_NAMESPACE::WebBrowserComponent* ownerComponent; } - (DownloadClickDetector*) initWithWebBrowserOwner: (JUCE_NAMESPACE::WebBrowserComponent*) ownerComponent; - (void) webView: (WebView*) webView decidePolicyForNavigationAction: (NSDictionary*) actionInformation - request: (NSURLRequest*) request - frame: (WebFrame*) frame - decisionListener: (id) listener; + request: (NSURLRequest*) request + frame: (WebFrame*) frame + decisionListener: (id) listener; @end @implementation DownloadClickDetector - (DownloadClickDetector*) initWithWebBrowserOwner: (JUCE_NAMESPACE::WebBrowserComponent*) ownerComponent_ { - [super init]; - ownerComponent = ownerComponent_; - return self; + [super init]; + ownerComponent = ownerComponent_; + return self; } - (void) webView: (WebView*) sender decidePolicyForNavigationAction: (NSDictionary*) actionInformation - request: (NSURLRequest*) request - frame: (WebFrame*) frame - decisionListener: (id ) listener + request: (NSURLRequest*) request + frame: (WebFrame*) frame + decisionListener: (id ) listener { - NSURL* url = [actionInformation valueForKey: @"WebActionOriginalURLKey"]; + NSURL* url = [actionInformation valueForKey: @"WebActionOriginalURLKey"]; - if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString]))) - [listener use]; - else - [listener ignore]; + if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString]))) + [listener use]; + else + [listener ignore]; } @end @@ -264830,136 +242414,136 @@ BEGIN_JUCE_NAMESPACE class WebBrowserComponentInternal : public NSViewComponent { public: - WebBrowserComponentInternal (WebBrowserComponent* owner) - { - webView = [[WebView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) - frameName: @"" - groupName: @""]; - setView (webView); + WebBrowserComponentInternal (WebBrowserComponent* owner) + { + webView = [[WebView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) + frameName: @"" + groupName: @""]; + setView (webView); - clickListener = [[DownloadClickDetector alloc] initWithWebBrowserOwner: owner]; - [webView setPolicyDelegate: clickListener]; - } + clickListener = [[DownloadClickDetector alloc] initWithWebBrowserOwner: owner]; + [webView setPolicyDelegate: clickListener]; + } - ~WebBrowserComponentInternal() - { - [webView setPolicyDelegate: nil]; - [clickListener release]; - setView (0); - } + ~WebBrowserComponentInternal() + { + [webView setPolicyDelegate: nil]; + [clickListener release]; + setView (0); + } - void goToURL (const String& url, - const StringArray* headers, - const MemoryBlock* postData) - { - NSMutableURLRequest* r - = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: juceStringToNS (url)] - cachePolicy: NSURLRequestUseProtocolCachePolicy - timeoutInterval: 30.0]; + void goToURL (const String& url, + const StringArray* headers, + const MemoryBlock* postData) + { + NSMutableURLRequest* r + = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: juceStringToNS (url)] + cachePolicy: NSURLRequestUseProtocolCachePolicy + timeoutInterval: 30.0]; - if (postData != 0 && postData->getSize() > 0) - { - [r setHTTPMethod: @"POST"]; - [r setHTTPBody: [NSData dataWithBytes: postData->getData() - length: postData->getSize()]]; - } + if (postData != 0 && postData->getSize() > 0) + { + [r setHTTPMethod: @"POST"]; + [r setHTTPBody: [NSData dataWithBytes: postData->getData() + length: postData->getSize()]]; + } - if (headers != 0) - { - for (int i = 0; i < headers->size(); ++i) - { - const String headerName ((*headers)[i].upToFirstOccurrenceOf (T(":"), false, false).trim()); - const String headerValue ((*headers)[i].fromFirstOccurrenceOf (T(":"), false, false).trim()); + if (headers != 0) + { + for (int i = 0; i < headers->size(); ++i) + { + const String headerName ((*headers)[i].upToFirstOccurrenceOf (T(":"), false, false).trim()); + const String headerValue ((*headers)[i].fromFirstOccurrenceOf (T(":"), false, false).trim()); - [r setValue: juceStringToNS (headerValue) - forHTTPHeaderField: juceStringToNS (headerName)]; - } - } + [r setValue: juceStringToNS (headerValue) + forHTTPHeaderField: juceStringToNS (headerName)]; + } + } - stop(); - [[webView mainFrame] loadRequest: r]; - } + stop(); + [[webView mainFrame] loadRequest: r]; + } - void goBack() - { - [webView goBack]; - } + void goBack() + { + [webView goBack]; + } - void goForward() - { - [webView goForward]; - } + void goForward() + { + [webView goForward]; + } - void stop() - { - [webView stopLoading: nil]; - } + void stop() + { + [webView stopLoading: nil]; + } - void refresh() - { - [webView reload: nil]; - } + void refresh() + { + [webView reload: nil]; + } private: - WebView* webView; - DownloadClickDetector* clickListener; + WebView* webView; + DownloadClickDetector* clickListener; }; WebBrowserComponent::WebBrowserComponent (const bool unloadPageWhenBrowserIsHidden_) - : browser (0), - blankPageShown (false), - unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_) + : browser (0), + blankPageShown (false), + unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_) { - setOpaque (true); + setOpaque (true); - addAndMakeVisible (browser = new WebBrowserComponentInternal (this)); + addAndMakeVisible (browser = new WebBrowserComponentInternal (this)); } WebBrowserComponent::~WebBrowserComponent() { - deleteAndZero (browser); + deleteAndZero (browser); } void WebBrowserComponent::goToURL (const String& url, - const StringArray* headers, - const MemoryBlock* postData) + const StringArray* headers, + const MemoryBlock* postData) { - lastURL = url; + lastURL = url; - lastHeaders.clear(); - if (headers != 0) - lastHeaders = *headers; + lastHeaders.clear(); + if (headers != 0) + lastHeaders = *headers; - lastPostData.setSize (0); - if (postData != 0) - lastPostData = *postData; + lastPostData.setSize (0); + if (postData != 0) + lastPostData = *postData; - blankPageShown = false; + blankPageShown = false; - browser->goToURL (url, headers, postData); + browser->goToURL (url, headers, postData); } void WebBrowserComponent::stop() { - browser->stop(); + browser->stop(); } void WebBrowserComponent::goBack() { - lastURL = String::empty; - blankPageShown = false; - browser->goBack(); + lastURL = String::empty; + blankPageShown = false; + browser->goBack(); } void WebBrowserComponent::goForward() { - lastURL = String::empty; - browser->goForward(); + lastURL = String::empty; + browser->goForward(); } void WebBrowserComponent::refresh() { - browser->refresh(); + browser->refresh(); } void WebBrowserComponent::paint (Graphics& g) @@ -264968,52 +242552,52 @@ void WebBrowserComponent::paint (Graphics& g) void WebBrowserComponent::checkWindowAssociation() { - if (isShowing()) - { - if (blankPageShown) - goBack(); - } - else - { - if (unloadPageWhenBrowserIsHidden && ! blankPageShown) - { - // when the component becomes invisible, some stuff like flash - // carries on playing audio, so we need to force it onto a blank - // page to avoid this, (and send it back when it's made visible again). + if (isShowing()) + { + if (blankPageShown) + goBack(); + } + else + { + if (unloadPageWhenBrowserIsHidden && ! blankPageShown) + { + // when the component becomes invisible, some stuff like flash + // carries on playing audio, so we need to force it onto a blank + // page to avoid this, (and send it back when it's made visible again). - blankPageShown = true; - browser->goToURL ("about:blank", 0, 0); - } - } + blankPageShown = true; + browser->goToURL ("about:blank", 0, 0); + } + } } void WebBrowserComponent::reloadLastURL() { - if (lastURL.isNotEmpty()) - { - goToURL (lastURL, &lastHeaders, &lastPostData); - lastURL = String::empty; - } + if (lastURL.isNotEmpty()) + { + goToURL (lastURL, &lastHeaders, &lastPostData); + lastURL = String::empty; + } } void WebBrowserComponent::parentHierarchyChanged() { - checkWindowAssociation(); + checkWindowAssociation(); } void WebBrowserComponent::resized() { - browser->setSize (getWidth(), getHeight()); + browser->setSize (getWidth(), getHeight()); } void WebBrowserComponent::visibilityChanged() { - checkWindowAssociation(); + checkWindowAssociation(); } bool WebBrowserComponent::pageAboutToLoad (const String& url) { - return true; + return true; } #else @@ -265027,8 +242611,8 @@ WebBrowserComponent::~WebBrowserComponent() } void WebBrowserComponent::goToURL (const String& url, - const StringArray* headers, - const MemoryBlock* postData) + const StringArray* headers, + const MemoryBlock* postData) { } @@ -265074,7 +242658,7 @@ void WebBrowserComponent::visibilityChanged() bool WebBrowserComponent::pageAboutToLoad (const String& url) { - return true; + return true; } #endif @@ -265091,548 +242675,534 @@ class IPhoneAudioIODevice : public AudioIODevice { public: - IPhoneAudioIODevice (const String& deviceName) - : AudioIODevice (deviceName, T("Audio")), - audioUnit (0), - isRunning (false), - callback (0), - actualBufferSize (0), - floatData (1, 2) - { - numInputChannels = 2; - numOutputChannels = 2; - preferredBufferSize = 0; + IPhoneAudioIODevice (const String& deviceName) + : AudioIODevice (deviceName, T("Audio")), + audioUnit (0), + isRunning (false), + callback (0), + actualBufferSize (0), + floatData (1, 2) + { + numInputChannels = 2; + numOutputChannels = 2; + preferredBufferSize = 0; - AudioSessionInitialize (0, 0, interruptionListenerStatic, this); - updateDeviceInfo(); - } + AudioSessionInitialize (0, 0, interruptionListenerStatic, this); + updateDeviceInfo(); + } - ~IPhoneAudioIODevice() - { - close(); - } + ~IPhoneAudioIODevice() + { + close(); + } - const StringArray getOutputChannelNames() - { - StringArray s; - s.add ("Left"); - s.add ("Right"); - return s; - } + const StringArray getOutputChannelNames() + { + StringArray s; + s.add ("Left"); + s.add ("Right"); + return s; + } - const StringArray getInputChannelNames() - { - StringArray s; - if (audioInputIsAvailable) - { - s.add ("Left"); - s.add ("Right"); - } - return s; - } + const StringArray getInputChannelNames() + { + StringArray s; + if (audioInputIsAvailable) + { + s.add ("Left"); + s.add ("Right"); + } + return s; + } - int getNumSampleRates() - { - return 1; - } + int getNumSampleRates() + { + return 1; + } - double getSampleRate (int index) - { - return sampleRate; - } + double getSampleRate (int index) + { + return sampleRate; + } - int getNumBufferSizesAvailable() - { - return 1; - } + int getNumBufferSizesAvailable() + { + return 1; + } - int getBufferSizeSamples (int index) - { - return getDefaultBufferSize(); - } + int getBufferSizeSamples (int index) + { + return getDefaultBufferSize(); + } - int getDefaultBufferSize() - { - return 1024; - } + int getDefaultBufferSize() + { + return 1024; + } - const String open (const BitArray& inputChannels, - const BitArray& outputChannels, - double sampleRate, - int bufferSize) - { - close(); + const String open (const BitArray& inputChannels, + const BitArray& outputChannels, + double sampleRate, + int bufferSize) + { + close(); - lastError = String::empty; - preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize; + lastError = String::empty; + preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize; - // xxx set up channel mapping + // xxx set up channel mapping - activeOutputChans = outputChannels; - activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false); - numOutputChannels = activeOutputChans.countNumberOfSetBits(); - monoOutputChannelNumber = activeOutputChans.findNextSetBit (0); + activeOutputChans = outputChannels; + activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false); + numOutputChannels = activeOutputChans.countNumberOfSetBits(); + monoOutputChannelNumber = activeOutputChans.findNextSetBit (0); - activeInputChans = inputChannels; - activeInputChans.setRange (2, activeInputChans.getHighestBit(), false); - numInputChannels = activeInputChans.countNumberOfSetBits(); - monoInputChannelNumber = activeInputChans.findNextSetBit (0); + activeInputChans = inputChannels; + activeInputChans.setRange (2, activeInputChans.getHighestBit(), false); + numInputChannels = activeInputChans.countNumberOfSetBits(); + monoInputChannelNumber = activeInputChans.findNextSetBit (0); - AudioSessionSetActive (true); + AudioSessionSetActive (true); - UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord; - AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (audioCategory), &audioCategory); - AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, propertyChangedStatic, this); + UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord; + AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (audioCategory), &audioCategory); + AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, propertyChangedStatic, this); - fixAudioRouteIfSetToReceiver(); - updateDeviceInfo(); + fixAudioRouteIfSetToReceiver(); + updateDeviceInfo(); - Float32 bufferDuration = preferredBufferSize / sampleRate; - AudioSessionSetProperty (kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof (bufferDuration), &bufferDuration); - actualBufferSize = preferredBufferSize; + Float32 bufferDuration = preferredBufferSize / sampleRate; + AudioSessionSetProperty (kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof (bufferDuration), &bufferDuration); + actualBufferSize = preferredBufferSize; - prepareFloatBuffers(); + prepareFloatBuffers(); - isRunning = true; - propertyChanged (0, 0, 0); // creates and starts the AU + isRunning = true; + propertyChanged (0, 0, 0); // creates and starts the AU - lastError = audioUnit != 0 ? String::empty - : T("Couldn't open the device"); - return lastError; - } + lastError = audioUnit != 0 ? String::empty + : T("Couldn't open the device"); + return lastError; + } - void close() - { - if (isRunning) - { - isRunning = false; - AudioSessionSetActive (false); + void close() + { + if (isRunning) + { + isRunning = false; + AudioSessionSetActive (false); - if (audioUnit != 0) - { - AudioComponentInstanceDispose (audioUnit); - audioUnit = 0; - } - } - } + if (audioUnit != 0) + { + AudioComponentInstanceDispose (audioUnit); + audioUnit = 0; + } + } + } - bool isOpen() - { - return isRunning; - } + bool isOpen() + { + return isRunning; + } - int getCurrentBufferSizeSamples() - { - return actualBufferSize; - } + int getCurrentBufferSizeSamples() + { + return actualBufferSize; + } - double getCurrentSampleRate() - { - return sampleRate; - } + double getCurrentSampleRate() + { + return sampleRate; + } - int getCurrentBitDepth() - { - return 16; - } + int getCurrentBitDepth() + { + return 16; + } - const BitArray getActiveOutputChannels() const - { - return activeOutputChans; - } + const BitArray getActiveOutputChannels() const + { + return activeOutputChans; + } - const BitArray getActiveInputChannels() const - { - return activeInputChans; - } + const BitArray getActiveInputChannels() const + { + return activeInputChans; + } - int getOutputLatencyInSamples() - { - return 0; //xxx - } + int getOutputLatencyInSamples() + { + return 0; //xxx + } - int getInputLatencyInSamples() - { - return 0; //xxx - } + int getInputLatencyInSamples() + { + return 0; //xxx + } - void start (AudioIODeviceCallback* callback_) - { - if (isRunning && callback != callback_) - { - if (callback_ != 0) - callback_->audioDeviceAboutToStart (this); + void start (AudioIODeviceCallback* callback_) + { + if (isRunning && callback != callback_) + { + if (callback_ != 0) + callback_->audioDeviceAboutToStart (this); - callbackLock.enter(); - callback = callback_; - callbackLock.exit(); - } - } + callbackLock.enter(); + callback = callback_; + callbackLock.exit(); + } + } - void stop() - { - if (isRunning) - { - callbackLock.enter(); - AudioIODeviceCallback* const lastCallback = callback; - callback = 0; - callbackLock.exit(); + void stop() + { + if (isRunning) + { + callbackLock.enter(); + AudioIODeviceCallback* const lastCallback = callback; + callback = 0; + callbackLock.exit(); - if (lastCallback != 0) - lastCallback->audioDeviceStopped(); - } - } + if (lastCallback != 0) + lastCallback->audioDeviceStopped(); + } + } - bool isPlaying() - { - return isRunning && callback != 0; - } + bool isPlaying() + { + return isRunning && callback != 0; + } - const String getLastError() - { - return lastError; - } + const String getLastError() + { + return lastError; + } private: - CriticalSection callbackLock; - Float64 sampleRate; - int numInputChannels, numOutputChannels; - int preferredBufferSize; - int actualBufferSize; - bool isRunning; - String lastError; + CriticalSection callbackLock; + Float64 sampleRate; + int numInputChannels, numOutputChannels; + int preferredBufferSize; + int actualBufferSize; + bool isRunning; + String lastError; - AudioStreamBasicDescription format; - AudioUnit audioUnit; - UInt32 audioInputIsAvailable; - AudioIODeviceCallback* callback; - BitArray activeOutputChans, activeInputChans; + AudioStreamBasicDescription format; + AudioUnit audioUnit; + UInt32 audioInputIsAvailable; + AudioIODeviceCallback* callback; + BitArray activeOutputChans, activeInputChans; - AudioSampleBuffer floatData; - float* inputChannels[3]; - float* outputChannels[3]; - bool monoInputChannelNumber, monoOutputChannelNumber; + AudioSampleBuffer floatData; + float* inputChannels[3]; + float* outputChannels[3]; + bool monoInputChannelNumber, monoOutputChannelNumber; - void prepareFloatBuffers() - { - floatData.setSize (numInputChannels + numOutputChannels, actualBufferSize); - zerostruct (inputChannels); - zerostruct (outputChannels); + void prepareFloatBuffers() + { + floatData.setSize (numInputChannels + numOutputChannels, actualBufferSize); + zerostruct (inputChannels); + zerostruct (outputChannels); - for (int i = 0; i < numInputChannels; ++i) - inputChannels[i] = floatData.getSampleData (i); + for (int i = 0; i < numInputChannels; ++i) + inputChannels[i] = floatData.getSampleData (i); - for (int i = 0; i < numOutputChannels; ++i) - outputChannels[i] = floatData.getSampleData (i + numInputChannels); - } + for (int i = 0; i < numOutputChannels; ++i) + outputChannels[i] = floatData.getSampleData (i + numInputChannels); + } - OSStatus process (AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, - UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData) - { - OSStatus err = noErr; + OSStatus process (AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData) + { + OSStatus err = noErr; - if (audioInputIsAvailable) - err = AudioUnitRender (audioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData); + if (audioInputIsAvailable) + err = AudioUnitRender (audioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData); - const ScopedLock sl (callbackLock); + const ScopedLock sl (callbackLock); - if (callback != 0) - { - if (audioInputIsAvailable && numInputChannels > 0) - { - short* shortData = (short*) ioData->mBuffers[0].mData; + if (callback != 0) + { + if (audioInputIsAvailable && numInputChannels > 0) + { + short* shortData = (short*) ioData->mBuffers[0].mData; - if (numInputChannels >= 2) - { - for (UInt32 i = 0; i < inNumberFrames; ++i) - { - inputChannels[0][i] = *shortData++ * (1.0f / 32768.0f); - inputChannels[1][i] = *shortData++ * (1.0f / 32768.0f); - } - } - else - { - if (monoInputChannelNumber > 0) - ++shortData; + if (numInputChannels >= 2) + { + for (UInt32 i = 0; i < inNumberFrames; ++i) + { + inputChannels[0][i] = *shortData++ * (1.0f / 32768.0f); + inputChannels[1][i] = *shortData++ * (1.0f / 32768.0f); + } + } + else + { + if (monoInputChannelNumber > 0) + ++shortData; - for (UInt32 i = 0; i < inNumberFrames; ++i) - { - inputChannels[0][i] = *shortData++ * (1.0f / 32768.0f); - ++shortData; - } - } - } - else - { - for (int i = numInputChannels; --i >= 0;) - zeromem (inputChannels[i], sizeof (float) * inNumberFrames); - } + for (UInt32 i = 0; i < inNumberFrames; ++i) + { + inputChannels[0][i] = *shortData++ * (1.0f / 32768.0f); + ++shortData; + } + } + } + else + { + for (int i = numInputChannels; --i >= 0;) + zeromem (inputChannels[i], sizeof (float) * inNumberFrames); + } - callback->audioDeviceIOCallback ((const float**) inputChannels, numInputChannels, - outputChannels, numOutputChannels, - (int) inNumberFrames); + callback->audioDeviceIOCallback ((const float**) inputChannels, numInputChannels, + outputChannels, numOutputChannels, + (int) inNumberFrames); - short* shortData = (short*) ioData->mBuffers[0].mData; - int n = 0; + short* shortData = (short*) ioData->mBuffers[0].mData; + int n = 0; - if (numOutputChannels >= 2) - { - for (UInt32 i = 0; i < inNumberFrames; ++i) - { - shortData [n++] = (short) (outputChannels[0][i] * 32767.0f); - shortData [n++] = (short) (outputChannels[1][i] * 32767.0f); - } - } - else if (numOutputChannels == 1) - { - for (UInt32 i = 0; i < inNumberFrames; ++i) - { - const short s = (short) (outputChannels[monoOutputChannelNumber][i] * 32767.0f); - shortData [n++] = s; - shortData [n++] = s; - } - } - else - { - zeromem (ioData->mBuffers[0].mData, 2 * sizeof (short) * inNumberFrames); - } - } - else - { - zeromem (ioData->mBuffers[0].mData, 2 * sizeof (short) * inNumberFrames); - } + if (numOutputChannels >= 2) + { + for (UInt32 i = 0; i < inNumberFrames; ++i) + { + shortData [n++] = (short) (outputChannels[0][i] * 32767.0f); + shortData [n++] = (short) (outputChannels[1][i] * 32767.0f); + } + } + else if (numOutputChannels == 1) + { + for (UInt32 i = 0; i < inNumberFrames; ++i) + { + const short s = (short) (outputChannels[monoOutputChannelNumber][i] * 32767.0f); + shortData [n++] = s; + shortData [n++] = s; + } + } + else + { + zeromem (ioData->mBuffers[0].mData, 2 * sizeof (short) * inNumberFrames); + } + } + else + { + zeromem (ioData->mBuffers[0].mData, 2 * sizeof (short) * inNumberFrames); + } - return err; - } + return err; + } - void updateDeviceInfo() - { - UInt32 size = sizeof (sampleRate); - AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareSampleRate, &size, &sampleRate); + void updateDeviceInfo() + { + UInt32 size = sizeof (sampleRate); + AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareSampleRate, &size, &sampleRate); - size = sizeof (audioInputIsAvailable); - AudioSessionGetProperty (kAudioSessionProperty_AudioInputAvailable, &size, &audioInputIsAvailable); - } + size = sizeof (audioInputIsAvailable); + AudioSessionGetProperty (kAudioSessionProperty_AudioInputAvailable, &size, &audioInputIsAvailable); + } - void propertyChanged (AudioSessionPropertyID inID, UInt32 inDataSize, const void* inPropertyValue) - { - if (! isRunning) - return; + void propertyChanged (AudioSessionPropertyID inID, UInt32 inDataSize, const void* inPropertyValue) + { + if (! isRunning) + return; - if (inPropertyValue != 0) - { - CFDictionaryRef routeChangeDictionary = (CFDictionaryRef) inPropertyValue; - CFNumberRef routeChangeReasonRef = (CFNumberRef) CFDictionaryGetValue (routeChangeDictionary, - CFSTR (kAudioSession_AudioRouteChangeKey_Reason)); + if (inPropertyValue != 0) + { + CFDictionaryRef routeChangeDictionary = (CFDictionaryRef) inPropertyValue; + CFNumberRef routeChangeReasonRef = (CFNumberRef) CFDictionaryGetValue (routeChangeDictionary, + CFSTR (kAudioSession_AudioRouteChangeKey_Reason)); - SInt32 routeChangeReason; - CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason); + SInt32 routeChangeReason; + CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason); - if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) - fixAudioRouteIfSetToReceiver(); - } + if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) + fixAudioRouteIfSetToReceiver(); + } - updateDeviceInfo(); - createAudioUnit(); + updateDeviceInfo(); + createAudioUnit(); - AudioSessionSetActive (true); + AudioSessionSetActive (true); - if (audioUnit != 0) - { - UInt32 formatSize = sizeof (format); - AudioUnitGetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, &formatSize); + if (audioUnit != 0) + { + UInt32 formatSize = sizeof (format); + AudioUnitGetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, &formatSize); - Float32 bufferDuration = preferredBufferSize / sampleRate; - UInt32 bufferDurationSize = sizeof (bufferDuration); - AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareIOBufferDuration, &bufferDurationSize, &bufferDurationSize); - actualBufferSize = (int) (sampleRate * bufferDuration + 0.5); + Float32 bufferDuration = preferredBufferSize / sampleRate; + UInt32 bufferDurationSize = sizeof (bufferDuration); + AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareIOBufferDuration, &bufferDurationSize, &bufferDurationSize); + actualBufferSize = (int) (sampleRate * bufferDuration + 0.5); - AudioOutputUnitStart (audioUnit); - } - } + AudioOutputUnitStart (audioUnit); + } + } - void interruptionListener (UInt32 inInterruption) - { - /*if (inInterruption == kAudioSessionBeginInterruption) - { - isRunning = false; - AudioOutputUnitStop (audioUnit); + void interruptionListener (UInt32 inInterruption) + { - if (juce_iPhoneShowModalAlert ("Audio Interrupted", - "This could have been interrupted by another application or by unplugging a headset", - @"Resume", - @"Cancel")) - { - isRunning = true; - propertyChanged (0, 0, 0); - } - }*/ + if (inInterruption == kAudioSessionEndInterruption) + { + isRunning = true; + AudioSessionSetActive (true); + AudioOutputUnitStart (audioUnit); + } + } - if (inInterruption == kAudioSessionEndInterruption) - { - isRunning = true; - AudioSessionSetActive (true); - AudioOutputUnitStart (audioUnit); - } - } + static OSStatus processStatic (void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData) + { + return ((IPhoneAudioIODevice*) inRefCon)->process (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); + } - static OSStatus processStatic (void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, - UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData) - { - return ((IPhoneAudioIODevice*) inRefCon)->process (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); - } + static void propertyChangedStatic (void* inClientData, AudioSessionPropertyID inID, UInt32 inDataSize, const void* inPropertyValue) + { + ((IPhoneAudioIODevice*) inClientData)->propertyChanged (inID, inDataSize, inPropertyValue); + } - static void propertyChangedStatic (void* inClientData, AudioSessionPropertyID inID, UInt32 inDataSize, const void* inPropertyValue) - { - ((IPhoneAudioIODevice*) inClientData)->propertyChanged (inID, inDataSize, inPropertyValue); - } + static void interruptionListenerStatic (void* inClientData, UInt32 inInterruption) + { + ((IPhoneAudioIODevice*) inClientData)->interruptionListener (inInterruption); + } - static void interruptionListenerStatic (void* inClientData, UInt32 inInterruption) - { - ((IPhoneAudioIODevice*) inClientData)->interruptionListener (inInterruption); - } + void resetFormat (const int numChannels) + { + memset (&format, 0, sizeof (format)); + format.mFormatID = kAudioFormatLinearPCM; + format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; + format.mBitsPerChannel = 8 * sizeof (short); + format.mChannelsPerFrame = 2; + format.mFramesPerPacket = 1; + format.mBytesPerFrame = format.mBytesPerPacket = 2 * sizeof (short); + } - void resetFormat (const int numChannels) - { - memset (&format, 0, sizeof (format)); - format.mFormatID = kAudioFormatLinearPCM; - format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; - format.mBitsPerChannel = 8 * sizeof (short); - format.mChannelsPerFrame = 2; - format.mFramesPerPacket = 1; - format.mBytesPerFrame = format.mBytesPerPacket = 2 * sizeof (short); - } + bool createAudioUnit() + { + if (audioUnit != 0) + { + AudioComponentInstanceDispose (audioUnit); + audioUnit = 0; + } - bool createAudioUnit() - { - if (audioUnit != 0) - { - AudioComponentInstanceDispose (audioUnit); - audioUnit = 0; - } + resetFormat (2); - resetFormat (2); + AudioComponentDescription desc; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_RemoteIO; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; - AudioComponentDescription desc; - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_RemoteIO; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; + AudioComponent comp = AudioComponentFindNext (0, &desc); + AudioComponentInstanceNew (comp, &audioUnit); - AudioComponent comp = AudioComponentFindNext (0, &desc); - AudioComponentInstanceNew (comp, &audioUnit); + if (audioUnit == 0) + return false; - if (audioUnit == 0) - return false; + const UInt32 one = 1; + AudioUnitSetProperty (audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof (one)); - const UInt32 one = 1; - AudioUnitSetProperty (audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof (one)); + AudioChannelLayout layout; + layout.mChannelBitmap = 0; + layout.mNumberChannelDescriptions = 0; + layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, &layout, sizeof (layout)); + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, 0, &layout, sizeof (layout)); - AudioChannelLayout layout; - layout.mChannelBitmap = 0; - layout.mNumberChannelDescriptions = 0; - layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; - AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, &layout, sizeof (layout)); - AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, 0, &layout, sizeof (layout)); + AURenderCallbackStruct inputProc; + inputProc.inputProc = processStatic; + inputProc.inputProcRefCon = this; + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &inputProc, sizeof (inputProc)); - AURenderCallbackStruct inputProc; - inputProc.inputProc = processStatic; - inputProc.inputProcRefCon = this; - AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &inputProc, sizeof (inputProc)); + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof (format)); + AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, sizeof (format)); - AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof (format)); - AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, sizeof (format)); + AudioUnitInitialize (audioUnit); + return true; + } - AudioUnitInitialize (audioUnit); - return true; - } + // If the routing is set to go through the receiver (i.e. the speaker, but quiet), this re-routes it + // to make it loud. Needed because by default when using an input + output, the output is kept quiet. + static void fixAudioRouteIfSetToReceiver() + { + CFStringRef audioRoute = 0; + UInt32 propertySize = sizeof (audioRoute); + if (AudioSessionGetProperty (kAudioSessionProperty_AudioRoute, &propertySize, &audioRoute) == noErr) + { + NSString* route = (NSString*) audioRoute; - // If the routing is set to go through the receiver (i.e. the speaker, but quiet), this re-routes it - // to make it loud. Needed because by default when using an input + output, the output is kept quiet. - static void fixAudioRouteIfSetToReceiver() - { - CFStringRef audioRoute = 0; - UInt32 propertySize = sizeof (audioRoute); - if (AudioSessionGetProperty (kAudioSessionProperty_AudioRoute, &propertySize, &audioRoute) == noErr) - { - NSString* route = (NSString*) audioRoute; + //DBG ("audio route: " + nsStringToJuce (route)); - //printf ("audio route: %s\n", [route cString]); + if ([route hasPrefix: @"Receiver"]) + { + UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; + AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRouteOverride), &audioRouteOverride); + } - if ([route hasPrefix: @"Receiver"]) - { - UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; - AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRouteOverride), &audioRouteOverride); - } + CFRelease (audioRoute); + } + } - CFRelease (audioRoute); - } - } - - IPhoneAudioIODevice (const IPhoneAudioIODevice&); - const IPhoneAudioIODevice& operator= (const IPhoneAudioIODevice&); + IPhoneAudioIODevice (const IPhoneAudioIODevice&); + const IPhoneAudioIODevice& operator= (const IPhoneAudioIODevice&); }; class IPhoneAudioIODeviceType : public AudioIODeviceType { public: - IPhoneAudioIODeviceType() - : AudioIODeviceType (T("iPhone Audio")) - { - } + IPhoneAudioIODeviceType() + : AudioIODeviceType (T("iPhone Audio")) + { + } - ~IPhoneAudioIODeviceType() - { - } + ~IPhoneAudioIODeviceType() + { + } - void scanForDevices() - { - } + void scanForDevices() + { + } - const StringArray getDeviceNames (const bool wantInputNames) const - { - StringArray s; - s.add ("iPhone Audio"); - return s; - } + const StringArray getDeviceNames (const bool wantInputNames) const + { + StringArray s; + s.add ("iPhone Audio"); + return s; + } - int getDefaultDeviceIndex (const bool forInput) const - { - return 0; - } + int getDefaultDeviceIndex (const bool forInput) const + { + return 0; + } - int getIndexOfDevice (AudioIODevice* device, const bool asInput) const - { - return device != 0 ? 0 : -1; - } + int getIndexOfDevice (AudioIODevice* device, const bool asInput) const + { + return device != 0 ? 0 : -1; + } - bool hasSeparateInputsAndOutputs() const { return false; } + bool hasSeparateInputsAndOutputs() const { return false; } - AudioIODevice* createDevice (const String& outputDeviceName, - const String& inputDeviceName) - { - if (outputDeviceName.isNotEmpty() || inputDeviceName.isNotEmpty()) - { - return new IPhoneAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName - : inputDeviceName); - } + AudioIODevice* createDevice (const String& outputDeviceName, + const String& inputDeviceName) + { + if (outputDeviceName.isNotEmpty() || inputDeviceName.isNotEmpty()) + { + return new IPhoneAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName + : inputDeviceName); + } - return 0; - } + return 0; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - IPhoneAudioIODeviceType (const IPhoneAudioIODeviceType&); - const IPhoneAudioIODeviceType& operator= (const IPhoneAudioIODeviceType&); + IPhoneAudioIODeviceType (const IPhoneAudioIODeviceType&); + const IPhoneAudioIODeviceType& operator= (const IPhoneAudioIODeviceType&); }; AudioIODeviceType* juce_createAudioIODeviceType_iPhoneAudio() { - return new IPhoneAudioIODeviceType(); + return new IPhoneAudioIODeviceType(); } #endif @@ -265650,12 +243220,12 @@ AudioIODeviceType* juce_createAudioIODeviceType_iPhoneAudio() static bool logAnyErrorsMidi (const OSStatus err, const int lineNum) { - if (err == noErr) - return true; + if (err == noErr) + return true; - log (T("CoreMidi error: ") + String (lineNum) + T(" - ") + String::toHexString ((int)err)); - jassertfalse - return false; + log (T("CoreMidi error: ") + String (lineNum) + T(" - ") + String::toHexString ((int)err)); + jassertfalse + return false; } #undef OK @@ -265663,165 +243233,165 @@ static bool logAnyErrorsMidi (const OSStatus err, const int lineNum) static const String getEndpointName (MIDIEndpointRef endpoint, bool isExternal) { - String result; - CFStringRef str = 0; + String result; + CFStringRef str = 0; - MIDIObjectGetStringProperty (endpoint, kMIDIPropertyName, &str); + MIDIObjectGetStringProperty (endpoint, kMIDIPropertyName, &str); - if (str != 0) - { - result = PlatformUtilities::cfStringToJuceString (str); - CFRelease (str); - str = 0; - } + if (str != 0) + { + result = PlatformUtilities::cfStringToJuceString (str); + CFRelease (str); + str = 0; + } - MIDIEntityRef entity = 0; - MIDIEndpointGetEntity (endpoint, &entity); + MIDIEntityRef entity = 0; + MIDIEndpointGetEntity (endpoint, &entity); - if (entity == 0) - return result; // probably virtual + if (entity == 0) + return result; // probably virtual - if (result.isEmpty()) - { - // endpoint name has zero length - try the entity - MIDIObjectGetStringProperty (entity, kMIDIPropertyName, &str); + if (result.isEmpty()) + { + // endpoint name has zero length - try the entity + MIDIObjectGetStringProperty (entity, kMIDIPropertyName, &str); - if (str != 0) - { - result += PlatformUtilities::cfStringToJuceString (str); - CFRelease (str); - str = 0; - } - } + if (str != 0) + { + result += PlatformUtilities::cfStringToJuceString (str); + CFRelease (str); + str = 0; + } + } - // now consider the device's name - MIDIDeviceRef device = 0; - MIDIEntityGetDevice (entity, &device); - if (device == 0) - return result; + // now consider the device's name + MIDIDeviceRef device = 0; + MIDIEntityGetDevice (entity, &device); + if (device == 0) + return result; - MIDIObjectGetStringProperty (device, kMIDIPropertyName, &str); + MIDIObjectGetStringProperty (device, kMIDIPropertyName, &str); - if (str != 0) - { - const String s (PlatformUtilities::cfStringToJuceString (str)); - CFRelease (str); + if (str != 0) + { + const String s (PlatformUtilities::cfStringToJuceString (str)); + CFRelease (str); - // if an external device has only one entity, throw away - // the endpoint name and just use the device name - if (isExternal && MIDIDeviceGetNumberOfEntities (device) < 2) - { - result = s; - } - else if (! result.startsWithIgnoreCase (s)) - { - // prepend the device name to the entity name - result = (s + T(" ") + result).trimEnd(); - } - } + // if an external device has only one entity, throw away + // the endpoint name and just use the device name + if (isExternal && MIDIDeviceGetNumberOfEntities (device) < 2) + { + result = s; + } + else if (! result.startsWithIgnoreCase (s)) + { + // prepend the device name to the entity name + result = (s + T(" ") + result).trimEnd(); + } + } - return result; + return result; } static const String getConnectedEndpointName (MIDIEndpointRef endpoint) { - String result; + String result; - // Does the endpoint have connections? - CFDataRef connections = 0; - int numConnections = 0; + // Does the endpoint have connections? + CFDataRef connections = 0; + int numConnections = 0; - MIDIObjectGetDataProperty (endpoint, kMIDIPropertyConnectionUniqueID, &connections); + MIDIObjectGetDataProperty (endpoint, kMIDIPropertyConnectionUniqueID, &connections); - if (connections != 0) - { - numConnections = CFDataGetLength (connections) / sizeof (MIDIUniqueID); + if (connections != 0) + { + numConnections = (int) (CFDataGetLength (connections) / sizeof (MIDIUniqueID)); - if (numConnections > 0) - { - const SInt32* pid = reinterpret_cast (CFDataGetBytePtr (connections)); + if (numConnections > 0) + { + const SInt32* pid = reinterpret_cast (CFDataGetBytePtr (connections)); - for (int i = 0; i < numConnections; ++i, ++pid) - { - MIDIUniqueID uid = EndianS32_BtoN (*pid); - MIDIObjectRef connObject; - MIDIObjectType connObjectType; - OSStatus err = MIDIObjectFindByUniqueID (uid, &connObject, &connObjectType); + for (int i = 0; i < numConnections; ++i, ++pid) + { + MIDIUniqueID uid = EndianS32_BtoN (*pid); + MIDIObjectRef connObject; + MIDIObjectType connObjectType; + OSStatus err = MIDIObjectFindByUniqueID (uid, &connObject, &connObjectType); - if (err == noErr) - { - String s; + if (err == noErr) + { + String s; - if (connObjectType == kMIDIObjectType_ExternalSource - || connObjectType == kMIDIObjectType_ExternalDestination) - { - // Connected to an external device's endpoint (10.3 and later). - s = getEndpointName (static_cast (connObject), true); - } - else - { - // Connected to an external device (10.2) (or something else, catch-all) - CFStringRef str = 0; - MIDIObjectGetStringProperty (connObject, kMIDIPropertyName, &str); + if (connObjectType == kMIDIObjectType_ExternalSource + || connObjectType == kMIDIObjectType_ExternalDestination) + { + // Connected to an external device's endpoint (10.3 and later). + s = getEndpointName (static_cast (connObject), true); + } + else + { + // Connected to an external device (10.2) (or something else, catch-all) + CFStringRef str = 0; + MIDIObjectGetStringProperty (connObject, kMIDIPropertyName, &str); - if (str != 0) - { - s = PlatformUtilities::cfStringToJuceString (str); - CFRelease (str); - } - } + if (str != 0) + { + s = PlatformUtilities::cfStringToJuceString (str); + CFRelease (str); + } + } - if (s.isNotEmpty()) - { - if (result.isNotEmpty()) - result += (", "); + if (s.isNotEmpty()) + { + if (result.isNotEmpty()) + result += (", "); - result += s; - } - } - } - } + result += s; + } + } + } + } - CFRelease (connections); - } + CFRelease (connections); + } - if (result.isNotEmpty()) - return result; + if (result.isNotEmpty()) + return result; - // Here, either the endpoint had no connections, or we failed to obtain names for any of them. - return getEndpointName (endpoint, false); + // Here, either the endpoint had no connections, or we failed to obtain names for any of them. + return getEndpointName (endpoint, false); } const StringArray MidiOutput::getDevices() { - StringArray s; + StringArray s; - const ItemCount num = MIDIGetNumberOfDestinations(); - for (ItemCount i = 0; i < num; ++i) - { - MIDIEndpointRef dest = MIDIGetDestination (i); + const ItemCount num = MIDIGetNumberOfDestinations(); + for (ItemCount i = 0; i < num; ++i) + { + MIDIEndpointRef dest = MIDIGetDestination (i); - if (dest != 0) - { - String name (getConnectedEndpointName (dest)); + if (dest != 0) + { + String name (getConnectedEndpointName (dest)); - if (name.isEmpty()) - name = ""; + if (name.isEmpty()) + name = ""; - s.add (name); - } - else - { - s.add (""); - } - } + s.add (name); + } + else + { + s.add (""); + } + } - return s; + return s; } int MidiOutput::getDefaultDeviceIndex() { - return 0; + return 0; } static MIDIClientRef globalMidiClient; @@ -265829,98 +243399,98 @@ static bool hasGlobalClientBeenCreated = false; static bool makeSureClientExists() { - if (! hasGlobalClientBeenCreated) - { - String name (T("JUCE")); + if (! hasGlobalClientBeenCreated) + { + String name (T("JUCE")); - if (JUCEApplication::getInstance() != 0) - name = JUCEApplication::getInstance()->getApplicationName(); + if (JUCEApplication::getInstance() != 0) + name = JUCEApplication::getInstance()->getApplicationName(); - CFStringRef appName = PlatformUtilities::juceStringToCFString (name); + CFStringRef appName = PlatformUtilities::juceStringToCFString (name); - hasGlobalClientBeenCreated = OK (MIDIClientCreate (appName, 0, 0, &globalMidiClient)); - CFRelease (appName); - } + hasGlobalClientBeenCreated = OK (MIDIClientCreate (appName, 0, 0, &globalMidiClient)); + CFRelease (appName); + } - return hasGlobalClientBeenCreated; + return hasGlobalClientBeenCreated; } class MidiPortAndEndpoint { public: - MidiPortAndEndpoint (MIDIPortRef port_, MIDIEndpointRef endPoint_) - : port (port_), endPoint (endPoint_) - { - } + MidiPortAndEndpoint (MIDIPortRef port_, MIDIEndpointRef endPoint_) + : port (port_), endPoint (endPoint_) + { + } - ~MidiPortAndEndpoint() - { - if (port != 0) - MIDIPortDispose (port); + ~MidiPortAndEndpoint() + { + if (port != 0) + MIDIPortDispose (port); - if (port == 0 && endPoint != 0) // if port == 0, it means we created the endpoint, so it's safe to delete it - MIDIEndpointDispose (endPoint); - } + if (port == 0 && endPoint != 0) // if port == 0, it means we created the endpoint, so it's safe to delete it + MIDIEndpointDispose (endPoint); + } - MIDIPortRef port; - MIDIEndpointRef endPoint; + MIDIPortRef port; + MIDIEndpointRef endPoint; }; MidiOutput* MidiOutput::openDevice (int index) { - MidiOutput* mo = 0; + MidiOutput* mo = 0; - if (((unsigned int) index) < (unsigned int) MIDIGetNumberOfDestinations()) - { - MIDIEndpointRef endPoint = MIDIGetDestination (index); + if (((unsigned int) index) < (unsigned int) MIDIGetNumberOfDestinations()) + { + MIDIEndpointRef endPoint = MIDIGetDestination (index); - CFStringRef pname; - if (OK (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname))) - { - log (T("CoreMidi - opening out: ") + PlatformUtilities::cfStringToJuceString (pname)); + CFStringRef pname; + if (OK (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname))) + { + log (T("CoreMidi - opening out: ") + PlatformUtilities::cfStringToJuceString (pname)); - if (makeSureClientExists()) - { - MIDIPortRef port; + if (makeSureClientExists()) + { + MIDIPortRef port; - if (OK (MIDIOutputPortCreate (globalMidiClient, pname, &port))) - { - mo = new MidiOutput(); - mo->internal = (void*) new MidiPortAndEndpoint (port, endPoint); - } - } + if (OK (MIDIOutputPortCreate (globalMidiClient, pname, &port))) + { + mo = new MidiOutput(); + mo->internal = (void*) new MidiPortAndEndpoint (port, endPoint); + } + } - CFRelease (pname); - } - } + CFRelease (pname); + } + } - return mo; + return mo; } MidiOutput* MidiOutput::createNewDevice (const String& deviceName) { - MidiOutput* mo = 0; + MidiOutput* mo = 0; - if (makeSureClientExists()) - { - MIDIEndpointRef endPoint; - CFStringRef name = PlatformUtilities::juceStringToCFString (deviceName); + if (makeSureClientExists()) + { + MIDIEndpointRef endPoint; + CFStringRef name = PlatformUtilities::juceStringToCFString (deviceName); - if (OK (MIDISourceCreate (globalMidiClient, name, &endPoint))) - { - mo = new MidiOutput(); - mo->internal = (void*) new MidiPortAndEndpoint (0, endPoint); - } + if (OK (MIDISourceCreate (globalMidiClient, name, &endPoint))) + { + mo = new MidiOutput(); + mo->internal = (void*) new MidiPortAndEndpoint (0, endPoint); + } - CFRelease (name); - } + CFRelease (name); + } - return mo; + return mo; } MidiOutput::~MidiOutput() { - delete (MidiPortAndEndpoint*) internal; + delete (MidiPortAndEndpoint*) internal; } void MidiOutput::reset() @@ -265929,7 +243499,7 @@ void MidiOutput::reset() bool MidiOutput::getVolume (float& leftVol, float& rightVol) { - return false; + return false; } void MidiOutput::setVolume (float leftVol, float rightVol) @@ -265938,90 +243508,90 @@ void MidiOutput::setVolume (float leftVol, float rightVol) void MidiOutput::sendMessageNow (const MidiMessage& message) { - MidiPortAndEndpoint* const mpe = (MidiPortAndEndpoint*) internal; + MidiPortAndEndpoint* const mpe = (MidiPortAndEndpoint*) internal; - if (message.isSysEx()) - { - const int maxPacketSize = 256; - int pos = 0, bytesLeft = message.getRawDataSize(); - const int numPackets = (bytesLeft + maxPacketSize - 1) / maxPacketSize; - HeapBlock packets; - packets.malloc (32 * numPackets + message.getRawDataSize(), 1); - packets->numPackets = numPackets; + if (message.isSysEx()) + { + const int maxPacketSize = 256; + int pos = 0, bytesLeft = message.getRawDataSize(); + const int numPackets = (bytesLeft + maxPacketSize - 1) / maxPacketSize; + HeapBlock packets; + packets.malloc (32 * numPackets + message.getRawDataSize(), 1); + packets->numPackets = numPackets; - MIDIPacket* p = packets->packet; + MIDIPacket* p = packets->packet; - for (int i = 0; i < numPackets; ++i) - { - p->timeStamp = 0; - p->length = jmin (maxPacketSize, bytesLeft); - memcpy (p->data, message.getRawData() + pos, p->length); - pos += p->length; - bytesLeft -= p->length; - p = MIDIPacketNext (p); - } + for (int i = 0; i < numPackets; ++i) + { + p->timeStamp = 0; + p->length = jmin (maxPacketSize, bytesLeft); + memcpy (p->data, message.getRawData() + pos, p->length); + pos += p->length; + bytesLeft -= p->length; + p = MIDIPacketNext (p); + } - if (mpe->port != 0) - MIDISend (mpe->port, mpe->endPoint, packets); - else - MIDIReceived (mpe->endPoint, packets); - } - else - { - MIDIPacketList packets; - packets.numPackets = 1; - packets.packet[0].timeStamp = 0; - packets.packet[0].length = message.getRawDataSize(); - *(int*) (packets.packet[0].data) = *(const int*) message.getRawData(); + if (mpe->port != 0) + MIDISend (mpe->port, mpe->endPoint, packets); + else + MIDIReceived (mpe->endPoint, packets); + } + else + { + MIDIPacketList packets; + packets.numPackets = 1; + packets.packet[0].timeStamp = 0; + packets.packet[0].length = message.getRawDataSize(); + *(int*) (packets.packet[0].data) = *(const int*) message.getRawData(); - if (mpe->port != 0) - MIDISend (mpe->port, mpe->endPoint, &packets); - else - MIDIReceived (mpe->endPoint, &packets); - } + if (mpe->port != 0) + MIDISend (mpe->port, mpe->endPoint, &packets); + else + MIDIReceived (mpe->endPoint, &packets); + } } const StringArray MidiInput::getDevices() { - StringArray s; + StringArray s; - const ItemCount num = MIDIGetNumberOfSources(); - for (ItemCount i = 0; i < num; ++i) - { - MIDIEndpointRef source = MIDIGetSource (i); + const ItemCount num = MIDIGetNumberOfSources(); + for (ItemCount i = 0; i < num; ++i) + { + MIDIEndpointRef source = MIDIGetSource (i); - if (source != 0) - { - String name (getConnectedEndpointName (source)); + if (source != 0) + { + String name (getConnectedEndpointName (source)); - if (name.isEmpty()) - name = ""; + if (name.isEmpty()) + name = ""; - s.add (name); - } - else - { - s.add (""); - } - } + s.add (name); + } + else + { + s.add (""); + } + } - return s; + return s; } int MidiInput::getDefaultDeviceIndex() { - return 0; + return 0; } struct MidiPortAndCallback { - MidiInput* input; - MidiPortAndEndpoint* portAndEndpoint; - MidiInputCallback* callback; - MemoryBlock pendingData; - int pendingBytes; - double pendingDataTime; - bool active; + MidiInput* input; + MidiPortAndEndpoint* portAndEndpoint; + MidiInputCallback* callback; + MemoryBlock pendingData; + int pendingBytes; + double pendingDataTime; + bool active; }; static CriticalSection callbackLock; @@ -266029,234 +243599,234 @@ static VoidArray activeCallbacks; static void processSysex (MidiPortAndCallback* const mpc, const uint8*& d, int& size, const double time) { - if (*d == 0xf0) - { - mpc->pendingBytes = 0; - mpc->pendingDataTime = time; - } + if (*d == 0xf0) + { + mpc->pendingBytes = 0; + mpc->pendingDataTime = time; + } - mpc->pendingData.ensureSize (mpc->pendingBytes + size, false); - uint8* totalMessage = (uint8*) mpc->pendingData.getData(); + mpc->pendingData.ensureSize (mpc->pendingBytes + size, false); + uint8* totalMessage = (uint8*) mpc->pendingData.getData(); - uint8* dest = totalMessage + mpc->pendingBytes; + uint8* dest = totalMessage + mpc->pendingBytes; - while (size > 0) - { - if (mpc->pendingBytes > 0 && *d >= 0x80) - { - if (*d >= 0xfa || *d == 0xf8) - { - mpc->callback->handleIncomingMidiMessage (mpc->input, MidiMessage (*d, time)); - ++d; - --size; - } - else - { - if (*d == 0xf7) - { - *dest++ = *d++; - mpc->pendingBytes++; - --size; - } + while (size > 0) + { + if (mpc->pendingBytes > 0 && *d >= 0x80) + { + if (*d >= 0xfa || *d == 0xf8) + { + mpc->callback->handleIncomingMidiMessage (mpc->input, MidiMessage (*d, time)); + ++d; + --size; + } + else + { + if (*d == 0xf7) + { + *dest++ = *d++; + mpc->pendingBytes++; + --size; + } - break; - } - } - else - { - *dest++ = *d++; - mpc->pendingBytes++; - --size; - } - } + break; + } + } + else + { + *dest++ = *d++; + mpc->pendingBytes++; + --size; + } + } - if (totalMessage [mpc->pendingBytes - 1] == 0xf7) - { - mpc->callback->handleIncomingMidiMessage (mpc->input, MidiMessage (totalMessage, - mpc->pendingBytes, - mpc->pendingDataTime)); - mpc->pendingBytes = 0; - } - else - { - mpc->callback->handlePartialSysexMessage (mpc->input, - totalMessage, - mpc->pendingBytes, - mpc->pendingDataTime); - } + if (totalMessage [mpc->pendingBytes - 1] == 0xf7) + { + mpc->callback->handleIncomingMidiMessage (mpc->input, MidiMessage (totalMessage, + mpc->pendingBytes, + mpc->pendingDataTime)); + mpc->pendingBytes = 0; + } + else + { + mpc->callback->handlePartialSysexMessage (mpc->input, + totalMessage, + mpc->pendingBytes, + mpc->pendingDataTime); + } } static void midiInputProc (const MIDIPacketList* pktlist, - void* readProcRefCon, - void* srcConnRefCon) + void* readProcRefCon, + void* srcConnRefCon) { - double time = Time::getMillisecondCounterHiRes() * 0.001; - const double originalTime = time; + double time = Time::getMillisecondCounterHiRes() * 0.001; + const double originalTime = time; - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) readProcRefCon; - const ScopedLock sl (callbackLock); + MidiPortAndCallback* const mpc = (MidiPortAndCallback*) readProcRefCon; + const ScopedLock sl (callbackLock); - if (activeCallbacks.contains (mpc) && mpc->active) - { - const MIDIPacket* packet = &pktlist->packet[0]; + if (activeCallbacks.contains (mpc) && mpc->active) + { + const MIDIPacket* packet = &pktlist->packet[0]; - for (unsigned int i = 0; i < pktlist->numPackets; ++i) - { - const uint8* d = (const uint8*) (packet->data); - int size = packet->length; + for (unsigned int i = 0; i < pktlist->numPackets; ++i) + { + const uint8* d = (const uint8*) (packet->data); + int size = packet->length; - while (size > 0) - { - time = originalTime; + while (size > 0) + { + time = originalTime; - if (mpc->pendingBytes > 0 || d[0] == 0xf0) - { - processSysex (mpc, d, size, time); - } - else - { - int used = 0; - const MidiMessage m (d, size, used, 0, time); + if (mpc->pendingBytes > 0 || d[0] == 0xf0) + { + processSysex (mpc, d, size, time); + } + else + { + int used = 0; + const MidiMessage m (d, size, used, 0, time); - if (used <= 0) - { - jassertfalse // malformed midi message - break; - } - else - { - mpc->callback->handleIncomingMidiMessage (mpc->input, m); - } + if (used <= 0) + { + jassertfalse // malformed midi message + break; + } + else + { + mpc->callback->handleIncomingMidiMessage (mpc->input, m); + } - size -= used; - d += used; - } - } + size -= used; + d += used; + } + } - packet = MIDIPacketNext (packet); - } - } + packet = MIDIPacketNext (packet); + } + } } MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) { - MidiInput* mi = 0; + MidiInput* mi = 0; - if (((unsigned int) index) < (unsigned int) MIDIGetNumberOfSources()) - { - MIDIEndpointRef endPoint = MIDIGetSource (index); + if (((unsigned int) index) < (unsigned int) MIDIGetNumberOfSources()) + { + MIDIEndpointRef endPoint = MIDIGetSource (index); - if (endPoint != 0) - { - CFStringRef pname; + if (endPoint != 0) + { + CFStringRef pname; - if (OK (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname))) - { - log (T("CoreMidi - opening inp: ") + PlatformUtilities::cfStringToJuceString (pname)); + if (OK (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname))) + { + log (T("CoreMidi - opening inp: ") + PlatformUtilities::cfStringToJuceString (pname)); - if (makeSureClientExists()) - { - MIDIPortRef port; + if (makeSureClientExists()) + { + MIDIPortRef port; - ScopedPointer mpc (new MidiPortAndCallback()); - mpc->active = false; + ScopedPointer mpc (new MidiPortAndCallback()); + mpc->active = false; - if (OK (MIDIInputPortCreate (globalMidiClient, pname, midiInputProc, mpc, &port))) - { - if (OK (MIDIPortConnectSource (port, endPoint, 0))) - { - mpc->portAndEndpoint = new MidiPortAndEndpoint (port, endPoint); - mpc->callback = callback; - mpc->pendingBytes = 0; - mpc->pendingData.ensureSize (128); + if (OK (MIDIInputPortCreate (globalMidiClient, pname, midiInputProc, mpc, &port))) + { + if (OK (MIDIPortConnectSource (port, endPoint, 0))) + { + mpc->portAndEndpoint = new MidiPortAndEndpoint (port, endPoint); + mpc->callback = callback; + mpc->pendingBytes = 0; + mpc->pendingData.ensureSize (128); - mi = new MidiInput (getDevices() [index]); - mpc->input = mi; - mi->internal = (void*) mpc; + mi = new MidiInput (getDevices() [index]); + mpc->input = mi; + mi->internal = (void*) mpc; - const ScopedLock sl (callbackLock); - activeCallbacks.add (mpc.release()); - } - else - { - OK (MIDIPortDispose (port)); - } - } - } - } + const ScopedLock sl (callbackLock); + activeCallbacks.add (mpc.release()); + } + else + { + OK (MIDIPortDispose (port)); + } + } + } + } - CFRelease (pname); - } - } + CFRelease (pname); + } + } - return mi; + return mi; } MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallback* callback) { - MidiInput* mi = 0; + MidiInput* mi = 0; - if (makeSureClientExists()) - { - ScopedPointer mpc (new MidiPortAndCallback()); - mpc->active = false; + if (makeSureClientExists()) + { + ScopedPointer mpc (new MidiPortAndCallback()); + mpc->active = false; - MIDIEndpointRef endPoint; - CFStringRef name = PlatformUtilities::juceStringToCFString(deviceName); - if (OK (MIDIDestinationCreate (globalMidiClient, name, midiInputProc, mpc, &endPoint))) - { - mpc->portAndEndpoint = new MidiPortAndEndpoint (0, endPoint); - mpc->callback = callback; - mpc->pendingBytes = 0; - mpc->pendingData.ensureSize (128); + MIDIEndpointRef endPoint; + CFStringRef name = PlatformUtilities::juceStringToCFString(deviceName); + if (OK (MIDIDestinationCreate (globalMidiClient, name, midiInputProc, mpc, &endPoint))) + { + mpc->portAndEndpoint = new MidiPortAndEndpoint (0, endPoint); + mpc->callback = callback; + mpc->pendingBytes = 0; + mpc->pendingData.ensureSize (128); - mi = new MidiInput (deviceName); - mpc->input = mi; - mi->internal = (void*) mpc; + mi = new MidiInput (deviceName); + mpc->input = mi; + mi->internal = (void*) mpc; - const ScopedLock sl (callbackLock); - activeCallbacks.add (mpc.release()); - } + const ScopedLock sl (callbackLock); + activeCallbacks.add (mpc.release()); + } - CFRelease (name); - } + CFRelease (name); + } - return mi; + return mi; } MidiInput::MidiInput (const String& name_) - : name (name_) + : name (name_) { } MidiInput::~MidiInput() { - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; - mpc->active = false; + MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; + mpc->active = false; - callbackLock.enter(); - activeCallbacks.removeValue (mpc); - callbackLock.exit(); + callbackLock.enter(); + activeCallbacks.removeValue (mpc); + callbackLock.exit(); - if (mpc->portAndEndpoint->port != 0) - OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint)); + if (mpc->portAndEndpoint->port != 0) + OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint)); - delete mpc->portAndEndpoint; - delete mpc; + delete mpc->portAndEndpoint; + delete mpc; } void MidiInput::start() { - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; - const ScopedLock sl (callbackLock); - mpc->active = true; + MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; + const ScopedLock sl (callbackLock); + mpc->active = true; } void MidiInput::stop() { - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; - const ScopedLock sl (callbackLock); - mpc->active = false; + MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; + const ScopedLock sl (callbackLock); + mpc->active = false; } #undef log @@ -266273,7 +243843,7 @@ void MidiOutput::reset() bool MidiOutput::getVolume (float& leftVol, float& rightVol) { - return false; + return false; } void MidiOutput::setVolume (float leftVol, float rightVol) @@ -266286,22 +243856,22 @@ void MidiOutput::sendMessageNow (const MidiMessage& message) const StringArray MidiOutput::getDevices() { - return StringArray(); + return StringArray(); } MidiOutput* MidiOutput::openDevice (int index) { - return 0; + return 0; } const StringArray MidiInput::getDevices() { - return StringArray(); + return StringArray(); } MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) { - return 0; + return 0; } #endif @@ -266321,12 +243891,12 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) #define NEW_CGFONT_FUNCTIONS_UNAVAILABLE (CGFontCreateWithFontName == 0) #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 - #define SUPPORT_ONLY_10_4_FONTS 1 + #define SUPPORT_ONLY_10_4_FONTS 1 #endif END_JUCE_NAMESPACE @interface NSFont (PrivateHack) - - (NSGlyph) _defaultGlyphForChar: (unichar) theChar; + - (NSGlyph) _defaultGlyphForChar: (unichar) theChar; @end BEGIN_JUCE_NAMESPACE #endif @@ -266335,471 +243905,471 @@ class MacTypeface : public Typeface { public: - MacTypeface (const Font& font) - : Typeface (font.getTypefaceName()) - { - const ScopedAutoReleasePool pool; - renderingTransform = CGAffineTransformIdentity; + MacTypeface (const Font& font) + : Typeface (font.getTypefaceName()) + { + const ScopedAutoReleasePool pool; + renderingTransform = CGAffineTransformIdentity; - bool needsItalicTransform = false; + bool needsItalicTransform = false; #if JUCE_IPHONE - NSString* fontName = juceStringToNS (font.getTypefaceName()); + NSString* fontName = juceStringToNS (font.getTypefaceName()); - if (font.isItalic() || font.isBold()) - { - NSArray* familyFonts = [UIFont fontNamesForFamilyName: juceStringToNS (font.getTypefaceName())]; + if (font.isItalic() || font.isBold()) + { + NSArray* familyFonts = [UIFont fontNamesForFamilyName: juceStringToNS (font.getTypefaceName())]; - for (NSString* i in familyFonts) - { - const String fn (nsStringToJuce (i)); - const String afterDash (fn.fromFirstOccurrenceOf (T("-"), false, false)); + for (NSString* i in familyFonts) + { + const String fn (nsStringToJuce (i)); + const String afterDash (fn.fromFirstOccurrenceOf (T("-"), false, false)); - const bool probablyBold = afterDash.containsIgnoreCase (T("bold")) || fn.endsWithIgnoreCase (T("bold")); - const bool probablyItalic = afterDash.containsIgnoreCase (T("oblique")) - || afterDash.containsIgnoreCase (T("italic")) - || fn.endsWithIgnoreCase (T("oblique")) - || fn.endsWithIgnoreCase (T("italic")); + const bool probablyBold = afterDash.containsIgnoreCase (T("bold")) || fn.endsWithIgnoreCase (T("bold")); + const bool probablyItalic = afterDash.containsIgnoreCase (T("oblique")) + || afterDash.containsIgnoreCase (T("italic")) + || fn.endsWithIgnoreCase (T("oblique")) + || fn.endsWithIgnoreCase (T("italic")); - if (probablyBold == font.isBold() - && probablyItalic == font.isItalic()) - { - fontName = i; - needsItalicTransform = false; - break; - } - else if (probablyBold && (! probablyItalic) && probablyBold == font.isBold()) - { - fontName = i; - needsItalicTransform = true; // not ideal, so carry on in case we find a better one - } - } + if (probablyBold == font.isBold() + && probablyItalic == font.isItalic()) + { + fontName = i; + needsItalicTransform = false; + break; + } + else if (probablyBold && (! probablyItalic) && probablyBold == font.isBold()) + { + fontName = i; + needsItalicTransform = true; // not ideal, so carry on in case we find a better one + } + } - if (needsItalicTransform) - renderingTransform.c = 0.15f; - } + if (needsItalicTransform) + renderingTransform.c = 0.15f; + } - fontRef = CGFontCreateWithFontName ((CFStringRef) fontName); + fontRef = CGFontCreateWithFontName ((CFStringRef) fontName); - const int ascender = abs (CGFontGetAscent (fontRef)); - const float totalHeight = ascender + abs (CGFontGetDescent (fontRef)); - ascent = ascender / totalHeight; - unitsToHeightScaleFactor = 1.0f / totalHeight; - fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / totalHeight; + const int ascender = abs (CGFontGetAscent (fontRef)); + const float totalHeight = ascender + abs (CGFontGetDescent (fontRef)); + ascent = ascender / totalHeight; + unitsToHeightScaleFactor = 1.0f / totalHeight; + fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / totalHeight; #else - nsFont = [NSFont fontWithName: juceStringToNS (font.getTypefaceName()) size: 1024]; + nsFont = [NSFont fontWithName: juceStringToNS (font.getTypefaceName()) size: 1024]; - if (font.isItalic()) - { - NSFont* newFont = [[NSFontManager sharedFontManager] convertFont: nsFont - toHaveTrait: NSItalicFontMask]; + if (font.isItalic()) + { + NSFont* newFont = [[NSFontManager sharedFontManager] convertFont: nsFont + toHaveTrait: NSItalicFontMask]; - if (newFont == nsFont) - needsItalicTransform = true; // couldn't find a proper italic version, so fake it with a transform.. + if (newFont == nsFont) + needsItalicTransform = true; // couldn't find a proper italic version, so fake it with a transform.. - nsFont = newFont; - } + nsFont = newFont; + } - if (font.isBold()) - nsFont = [[NSFontManager sharedFontManager] convertFont: nsFont toHaveTrait: NSBoldFontMask]; + if (font.isBold()) + nsFont = [[NSFontManager sharedFontManager] convertFont: nsFont toHaveTrait: NSBoldFontMask]; - [nsFont retain]; + [nsFont retain]; - ascent = fabsf ([nsFont ascender]); - float totalSize = ascent + fabsf ([nsFont descender]); - ascent /= totalSize; + ascent = fabsf ((float) [nsFont ascender]); + float totalSize = ascent + fabsf ((float) [nsFont descender]); + ascent /= totalSize; - pathTransform = AffineTransform::identity.scale (1.0f / totalSize, 1.0f / totalSize); + pathTransform = AffineTransform::identity.scale (1.0f / totalSize, 1.0f / totalSize); - if (needsItalicTransform) - { - pathTransform = pathTransform.sheared (-0.15f, 0.0f); - renderingTransform.c = 0.15f; - } + if (needsItalicTransform) + { + pathTransform = pathTransform.sheared (-0.15f, 0.0f); + renderingTransform.c = 0.15f; + } #if SUPPORT_ONLY_10_4_FONTS - ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); + ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); - if (atsFont == 0) - atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); + if (atsFont == 0) + atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); - fontRef = CGFontCreateWithPlatformFont ((void*) &atsFont); + fontRef = CGFontCreateWithPlatformFont ((void*) &atsFont); - const float totalHeight = fabsf ([nsFont ascender]) + fabsf([nsFont descender]); - unitsToHeightScaleFactor = 1.0f / totalHeight; - fontHeightToCGSizeFactor = 1024.0f / totalHeight; + const float totalHeight = fabsf ([nsFont ascender]) + fabsf([nsFont descender]); + unitsToHeightScaleFactor = 1.0f / totalHeight; + fontHeightToCGSizeFactor = 1024.0f / totalHeight; #else #if SUPPORT_10_4_FONTS - if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) - { - ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); + if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) + { + ATSFontRef atsFont = ATSFontFindFromName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); - if (atsFont == 0) - atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); + if (atsFont == 0) + atsFont = ATSFontFindFromPostScriptName ((CFStringRef) [nsFont fontName], kATSOptionFlagsDefault); - fontRef = CGFontCreateWithPlatformFont ((void*) &atsFont); + fontRef = CGFontCreateWithPlatformFont ((void*) &atsFont); - const float totalHeight = fabsf ([nsFont ascender]) + fabsf([nsFont descender]); - unitsToHeightScaleFactor = 1.0f / totalHeight; - fontHeightToCGSizeFactor = 1024.0f / totalHeight; - } - else + const float totalHeight = fabsf ([nsFont ascender]) + fabsf([nsFont descender]); + unitsToHeightScaleFactor = 1.0f / totalHeight; + fontHeightToCGSizeFactor = 1024.0f / totalHeight; + } + else #endif - { - fontRef = CGFontCreateWithFontName ((CFStringRef) [nsFont fontName]); + { + fontRef = CGFontCreateWithFontName ((CFStringRef) [nsFont fontName]); - const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef)); - unitsToHeightScaleFactor = 1.0f / totalHeight; - fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / (float) totalHeight; - } + const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef)); + unitsToHeightScaleFactor = 1.0f / totalHeight; + fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / (float) totalHeight; + } #endif #endif - } + } - ~MacTypeface() - { + ~MacTypeface() + { #if ! JUCE_IPHONE - [nsFont release]; + [nsFont release]; #endif - if (fontRef != 0) - CGFontRelease (fontRef); - } + if (fontRef != 0) + CGFontRelease (fontRef); + } - float getAscent() const - { - return ascent; - } + float getAscent() const + { + return ascent; + } - float getDescent() const - { - return 1.0f - ascent; - } + float getDescent() const + { + return 1.0f - ascent; + } - float getStringWidth (const String& text) - { - if (fontRef == 0 || text.isEmpty()) - return 0; + float getStringWidth (const String& text) + { + if (fontRef == 0 || text.isEmpty()) + return 0; - const int length = text.length(); - HeapBlock glyphs; - createGlyphsForString (text, length, glyphs); + const int length = text.length(); + HeapBlock glyphs; + createGlyphsForString (text, length, glyphs); - float x = 0; + float x = 0; #if SUPPORT_ONLY_10_4_FONTS - HeapBlock advances (length); - [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; + HeapBlock advances (length); + [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; - for (int i = 0; i < length; ++i) - x += advances[i].width; + for (int i = 0; i < length; ++i) + x += advances[i].width; #else #if SUPPORT_10_4_FONTS - if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) - { - HeapBlock advances (length); - [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; + if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) + { + HeapBlock advances (length); + [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; - for (int i = 0; i < length; ++i) - x += advances[i].width; - } - else + for (int i = 0; i < length; ++i) + x += advances[i].width; + } + else #endif - { - HeapBlock advances (length); + { + HeapBlock advances (length); - if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances)) - for (int i = 0; i < length; ++i) - x += advances[i]; - } + if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances)) + for (int i = 0; i < length; ++i) + x += advances[i]; + } #endif - return x * unitsToHeightScaleFactor; - } + return x * unitsToHeightScaleFactor; + } - void getGlyphPositions (const String& text, Array & resultGlyphs, Array & xOffsets) - { - xOffsets.add (0); + void getGlyphPositions (const String& text, Array & resultGlyphs, Array & xOffsets) + { + xOffsets.add (0); - if (fontRef == 0 || text.isEmpty()) - return; + if (fontRef == 0 || text.isEmpty()) + return; - const int length = text.length(); - HeapBlock glyphs; - createGlyphsForString (text, length, glyphs); + const int length = text.length(); + HeapBlock glyphs; + createGlyphsForString (text, length, glyphs); #if SUPPORT_ONLY_10_4_FONTS - HeapBlock advances (length); - [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; + HeapBlock advances (length); + [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; - int x = 0; - for (int i = 0; i < length; ++i) - { - x += advances[i].width; - xOffsets.add (x * unitsToHeightScaleFactor); - resultGlyphs.add (((NSGlyph*) glyphs)[i]); - } + int x = 0; + for (int i = 0; i < length; ++i) + { + x += advances[i].width; + xOffsets.add (x * unitsToHeightScaleFactor); + resultGlyphs.add (((NSGlyph*) glyphs)[i]); + } #else #if SUPPORT_10_4_FONTS - if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) - { - HeapBlock advances (length); - [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; + if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) + { + HeapBlock advances (length); + [nsFont getAdvancements: advances forGlyphs: (NSGlyph*) glyphs count: length]; - float x = 0; - for (int i = 0; i < length; ++i) - { - x += advances[i].width; - xOffsets.add (x * unitsToHeightScaleFactor); - resultGlyphs.add (((NSGlyph*) glyphs)[i]); - } - } - else + float x = 0; + for (int i = 0; i < length; ++i) + { + x += advances[i].width; + xOffsets.add (x * unitsToHeightScaleFactor); + resultGlyphs.add (((NSGlyph*) glyphs)[i]); + } + } + else #endif - { - HeapBlock advances (length); + { + HeapBlock advances (length); - if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances)) - { - int x = 0; - for (int i = 0; i < length; ++i) - { - x += advances [i]; - xOffsets.add (x * unitsToHeightScaleFactor); - resultGlyphs.add (glyphs[i]); - } - } - } + if (CGFontGetGlyphAdvances (fontRef, glyphs, length, advances)) + { + int x = 0; + for (int i = 0; i < length; ++i) + { + x += advances [i]; + xOffsets.add (x * unitsToHeightScaleFactor); + resultGlyphs.add (glyphs[i]); + } + } + } #endif - } + } - bool getOutlineForGlyph (int glyphNumber, Path& path) - { + bool getOutlineForGlyph (int glyphNumber, Path& path) + { #if JUCE_IPHONE - return false; + return false; #else - if (nsFont == 0) - return false; + if (nsFont == 0) + return false; - // we might need to apply a transform to the path, so it mustn't have anything else in it - jassert (path.isEmpty()); + // we might need to apply a transform to the path, so it mustn't have anything else in it + jassert (path.isEmpty()); - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - NSBezierPath* bez = [NSBezierPath bezierPath]; - [bez moveToPoint: NSMakePoint (0, 0)]; - [bez appendBezierPathWithGlyph: (NSGlyph) glyphNumber - inFont: nsFont]; + NSBezierPath* bez = [NSBezierPath bezierPath]; + [bez moveToPoint: NSMakePoint (0, 0)]; + [bez appendBezierPathWithGlyph: (NSGlyph) glyphNumber + inFont: nsFont]; - for (int i = 0; i < [bez elementCount]; ++i) - { - NSPoint p[3]; - switch ([bez elementAtIndex: i associatedPoints: p]) - { - case NSMoveToBezierPathElement: - path.startNewSubPath (p[0].x, -p[0].y); - break; - case NSLineToBezierPathElement: - path.lineTo (p[0].x, -p[0].y); - break; - case NSCurveToBezierPathElement: - path.cubicTo (p[0].x, -p[0].y, p[1].x, -p[1].y, p[2].x, -p[2].y); - break; - case NSClosePathBezierPathElement: - path.closeSubPath(); - break; - default: - jassertfalse - break; - } - } + for (int i = 0; i < [bez elementCount]; ++i) + { + NSPoint p[3]; + switch ([bez elementAtIndex: i associatedPoints: p]) + { + case NSMoveToBezierPathElement: + path.startNewSubPath ((float) p[0].x, (float) -p[0].y); + break; + case NSLineToBezierPathElement: + path.lineTo ((float) p[0].x, (float) -p[0].y); + break; + case NSCurveToBezierPathElement: + path.cubicTo ((float) p[0].x, (float) -p[0].y, (float) p[1].x, (float) -p[1].y, (float) p[2].x, (float) -p[2].y); + break; + case NSClosePathBezierPathElement: + path.closeSubPath(); + break; + default: + jassertfalse + break; + } + } - path.applyTransform (pathTransform); - return true; + path.applyTransform (pathTransform); + return true; #endif - } + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - CGFontRef fontRef; - float fontHeightToCGSizeFactor; - CGAffineTransform renderingTransform; + CGFontRef fontRef; + float fontHeightToCGSizeFactor; + CGAffineTransform renderingTransform; private: - float ascent, unitsToHeightScaleFactor; + float ascent, unitsToHeightScaleFactor; #if JUCE_IPHONE #else - NSFont* nsFont; - AffineTransform pathTransform; + NSFont* nsFont; + AffineTransform pathTransform; #endif - void createGlyphsForString (const juce_wchar* const text, const int length, HeapBlock & glyphs) - { + void createGlyphsForString (const juce_wchar* const text, const int length, HeapBlock & glyphs) + { #if SUPPORT_10_4_FONTS #if ! SUPPORT_ONLY_10_4_FONTS - if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) + if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) #endif - { - glyphs.malloc (sizeof (NSGlyph) * length, 1); - NSGlyph* const g = (NSGlyph*) glyphs; + { + glyphs.malloc (sizeof (NSGlyph) * length, 1); + NSGlyph* const g = (NSGlyph*) glyphs; - for (int i = 0; i < length; ++i) - g[i] = (NSGlyph) [nsFont _defaultGlyphForChar: text[i]]; + for (int i = 0; i < length; ++i) + g[i] = (NSGlyph) [nsFont _defaultGlyphForChar: text[i]]; - return; - } + return; + } #endif #if ! SUPPORT_ONLY_10_4_FONTS - if (charToGlyphMapper == 0) - charToGlyphMapper = new CharToGlyphMapper (fontRef); + if (charToGlyphMapper == 0) + charToGlyphMapper = new CharToGlyphMapper (fontRef); - glyphs.malloc (length); + glyphs.malloc (length); - for (int i = 0; i < length; ++i) - glyphs[i] = (CGGlyph) charToGlyphMapper->getGlyphForCharacter (text[i]); + for (int i = 0; i < length; ++i) + glyphs[i] = (CGGlyph) charToGlyphMapper->getGlyphForCharacter (text[i]); #endif - } + } #if ! SUPPORT_ONLY_10_4_FONTS - // Reads a CGFontRef's character map table to convert unicode into glyph numbers - class CharToGlyphMapper - { - public: - CharToGlyphMapper (CGFontRef fontRef) - : segCount (0), endCode (0), startCode (0), idDelta (0), - idRangeOffset (0), glyphIndexes (0) - { - CFDataRef cmapTable = CGFontCopyTableForTag (fontRef, 'cmap'); + // Reads a CGFontRef's character map table to convert unicode into glyph numbers + class CharToGlyphMapper + { + public: + CharToGlyphMapper (CGFontRef fontRef) + : segCount (0), endCode (0), startCode (0), idDelta (0), + idRangeOffset (0), glyphIndexes (0) + { + CFDataRef cmapTable = CGFontCopyTableForTag (fontRef, 'cmap'); - if (cmapTable != 0) - { - const int numSubtables = getValue16 (cmapTable, 2); + if (cmapTable != 0) + { + const int numSubtables = getValue16 (cmapTable, 2); - for (int i = 0; i < numSubtables; ++i) - { - if (getValue16 (cmapTable, i * 8 + 4) == 0) // check for platform ID of 0 - { - const int offset = getValue32 (cmapTable, i * 8 + 8); + for (int i = 0; i < numSubtables; ++i) + { + if (getValue16 (cmapTable, i * 8 + 4) == 0) // check for platform ID of 0 + { + const int offset = getValue32 (cmapTable, i * 8 + 8); - if (getValue16 (cmapTable, offset) == 4) // check that it's format 4.. - { - const int length = getValue16 (cmapTable, offset + 2); - const int segCountX2 = getValue16 (cmapTable, offset + 6); - segCount = segCountX2 / 2; - const int endCodeOffset = offset + 14; - const int startCodeOffset = endCodeOffset + 2 + segCountX2; - const int idDeltaOffset = startCodeOffset + segCountX2; - const int idRangeOffsetOffset = idDeltaOffset + segCountX2; - const int glyphIndexesOffset = idRangeOffsetOffset + segCountX2; + if (getValue16 (cmapTable, offset) == 4) // check that it's format 4.. + { + const int length = getValue16 (cmapTable, offset + 2); + const int segCountX2 = getValue16 (cmapTable, offset + 6); + segCount = segCountX2 / 2; + const int endCodeOffset = offset + 14; + const int startCodeOffset = endCodeOffset + 2 + segCountX2; + const int idDeltaOffset = startCodeOffset + segCountX2; + const int idRangeOffsetOffset = idDeltaOffset + segCountX2; + const int glyphIndexesOffset = idRangeOffsetOffset + segCountX2; - endCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + endCodeOffset, segCountX2); - startCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + startCodeOffset, segCountX2); - idDelta = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idDeltaOffset, segCountX2); - idRangeOffset = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idRangeOffsetOffset, segCountX2); - glyphIndexes = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + glyphIndexesOffset, offset + length - glyphIndexesOffset); - } + endCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + endCodeOffset, segCountX2); + startCode = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + startCodeOffset, segCountX2); + idDelta = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idDeltaOffset, segCountX2); + idRangeOffset = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + idRangeOffsetOffset, segCountX2); + glyphIndexes = CFDataCreate (kCFAllocatorDefault, CFDataGetBytePtr (cmapTable) + glyphIndexesOffset, offset + length - glyphIndexesOffset); + } - break; - } - } + break; + } + } - CFRelease (cmapTable); - } - } + CFRelease (cmapTable); + } + } - ~CharToGlyphMapper() - { - if (endCode != 0) - { - CFRelease (endCode); - CFRelease (startCode); - CFRelease (idDelta); - CFRelease (idRangeOffset); - CFRelease (glyphIndexes); - } - } + ~CharToGlyphMapper() + { + if (endCode != 0) + { + CFRelease (endCode); + CFRelease (startCode); + CFRelease (idDelta); + CFRelease (idRangeOffset); + CFRelease (glyphIndexes); + } + } - int getGlyphForCharacter (const juce_wchar c) const - { - for (int i = 0; i < segCount; ++i) - { - if (getValue16 (endCode, i * 2) >= c) - { - const int start = getValue16 (startCode, i * 2); - if (start > c) - break; + int getGlyphForCharacter (const juce_wchar c) const + { + for (int i = 0; i < segCount; ++i) + { + if (getValue16 (endCode, i * 2) >= c) + { + const int start = getValue16 (startCode, i * 2); + if (start > c) + break; - const int delta = getValue16 (idDelta, i * 2); - const int rangeOffset = getValue16 (idRangeOffset, i * 2); + const int delta = getValue16 (idDelta, i * 2); + const int rangeOffset = getValue16 (idRangeOffset, i * 2); - if (rangeOffset == 0) - return delta + c; - else - return getValue16 (glyphIndexes, 2 * ((rangeOffset / 2) + (c - start) - (segCount - i))); - } - } + if (rangeOffset == 0) + return delta + c; + else + return getValue16 (glyphIndexes, 2 * ((rangeOffset / 2) + (c - start) - (segCount - i))); + } + } - // If we failed to find it "properly", this dodgy fall-back seems to do the trick for most fonts! - return jmax (-1, c - 29); - } + // If we failed to find it "properly", this dodgy fall-back seems to do the trick for most fonts! + return jmax (-1, c - 29); + } - private: - int segCount; - CFDataRef endCode, startCode, idDelta, idRangeOffset, glyphIndexes; + private: + int segCount; + CFDataRef endCode, startCode, idDelta, idRangeOffset, glyphIndexes; - static uint16 getValue16 (CFDataRef data, const int index) - { - return CFSwapInt16BigToHost (*(UInt16*) (CFDataGetBytePtr (data) + index)); - } + static uint16 getValue16 (CFDataRef data, const int index) + { + return CFSwapInt16BigToHost (*(UInt16*) (CFDataGetBytePtr (data) + index)); + } - static uint32 getValue32 (CFDataRef data, const int index) - { - return CFSwapInt32BigToHost (*(UInt32*) (CFDataGetBytePtr (data) + index)); - } - }; + static uint32 getValue32 (CFDataRef data, const int index) + { + return CFSwapInt32BigToHost (*(UInt32*) (CFDataGetBytePtr (data) + index)); + } + }; - ScopedPointer charToGlyphMapper; + ScopedPointer charToGlyphMapper; #endif }; const Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) { - return new MacTypeface (font); + return new MacTypeface (font); } const StringArray Font::findAllTypefaceNames() throw() { - StringArray names; + StringArray names; - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; #if JUCE_IPHONE - NSArray* fonts = [UIFont familyNames]; + NSArray* fonts = [UIFont familyNames]; #else - NSArray* fonts = [[NSFontManager sharedFontManager] availableFontFamilies]; + NSArray* fonts = [[NSFontManager sharedFontManager] availableFontFamilies]; #endif - for (unsigned int i = 0; i < [fonts count]; ++i) - names.add (nsStringToJuce ((NSString*) [fonts objectAtIndex: i])); + for (unsigned int i = 0; i < [fonts count]; ++i) + names.add (nsStringToJuce ((NSString*) [fonts objectAtIndex: i])); - names.sort (true); - return names; + names.sort (true); + return names; } void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed) throw() { #if JUCE_IPHONE - defaultSans = "Helvetica"; - defaultSerif = "Times New Roman"; - defaultFixed = "Courier New"; + defaultSans = "Helvetica"; + defaultSerif = "Times New Roman"; + defaultFixed = "Courier New"; #else - defaultSans = "Lucida Grande"; - defaultSerif = "Times New Roman"; - defaultFixed = "Monaco"; + defaultSans = "Lucida Grande"; + defaultSerif = "Times New Roman"; + defaultFixed = "Monaco"; #endif } @@ -266817,688 +244387,688 @@ class CoreGraphicsImage : public Image { public: - CoreGraphicsImage (const PixelFormat format_, - const int imageWidth_, - const int imageHeight_, - const bool clearImage) - : Image (format_, imageWidth_, imageHeight_, clearImage) - { - CGColorSpaceRef colourSpace = format == Image::SingleChannel ? CGColorSpaceCreateDeviceGray() - : CGColorSpaceCreateDeviceRGB(); + CoreGraphicsImage (const PixelFormat format_, + const int imageWidth_, + const int imageHeight_, + const bool clearImage) + : Image (format_, imageWidth_, imageHeight_, clearImage) + { + CGColorSpaceRef colourSpace = format == Image::SingleChannel ? CGColorSpaceCreateDeviceGray() + : CGColorSpaceCreateDeviceRGB(); - context = CGBitmapContextCreate (imageData, imageWidth, imageHeight, 8, lineStride, - colourSpace, getCGImageFlags (*this)); + context = CGBitmapContextCreate (imageData, imageWidth, imageHeight, 8, lineStride, + colourSpace, getCGImageFlags (*this)); - CGColorSpaceRelease (colourSpace); - } + CGColorSpaceRelease (colourSpace); + } - ~CoreGraphicsImage() - { - CGContextRelease (context); - } + ~CoreGraphicsImage() + { + CGContextRelease (context); + } - LowLevelGraphicsContext* createLowLevelContext(); + LowLevelGraphicsContext* createLowLevelContext(); - static CGImageRef createImage (const Image& juceImage, const bool forAlpha, CGColorSpaceRef colourSpace) - { - const CoreGraphicsImage* nativeImage = dynamic_cast (&juceImage); + static CGImageRef createImage (const Image& juceImage, const bool forAlpha, CGColorSpaceRef colourSpace) + { + const CoreGraphicsImage* nativeImage = dynamic_cast (&juceImage); - if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha)) - { - return CGBitmapContextCreateImage (nativeImage->context); - } - else - { - const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight()); + if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha)) + { + return CGBitmapContextCreateImage (nativeImage->context); + } + else + { + const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight()); - CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.pixelStride, 0); + CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.pixelStride, 0); - CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height, - 8, srcData.pixelStride * 8, srcData.lineStride, - colourSpace, getCGImageFlags (juceImage), provider, - 0, true, kCGRenderingIntentDefault); + CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height, + 8, srcData.pixelStride * 8, srcData.lineStride, + colourSpace, getCGImageFlags (juceImage), provider, + 0, true, kCGRenderingIntentDefault); - CGDataProviderRelease (provider); - return imageRef; - } - } + CGDataProviderRelease (provider); + return imageRef; + } + } #if JUCE_MAC - static NSImage* createNSImage (const Image& image) - { - const ScopedAutoReleasePool pool; + static NSImage* createNSImage (const Image& image) + { + const ScopedAutoReleasePool pool; - NSImage* im = [[NSImage alloc] init]; - [im setSize: NSMakeSize (image.getWidth(), image.getHeight())]; - [im lockFocus]; + NSImage* im = [[NSImage alloc] init]; + [im setSize: NSMakeSize (image.getWidth(), image.getHeight())]; + [im lockFocus]; - CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); - CGImageRef imageRef = createImage (image, false, colourSpace); - CGColorSpaceRelease (colourSpace); + CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); + CGImageRef imageRef = createImage (image, false, colourSpace); + CGColorSpaceRelease (colourSpace); - CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; - CGContextDrawImage (cg, CGRectMake (0, 0, image.getWidth(), image.getHeight()), imageRef); + CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; + CGContextDrawImage (cg, CGRectMake (0, 0, image.getWidth(), image.getHeight()), imageRef); - CGImageRelease (imageRef); - [im unlockFocus]; + CGImageRelease (imageRef); + [im unlockFocus]; - return im; - } + return im; + } #endif - CGContextRef context; + CGContextRef context; private: - static CGBitmapInfo getCGImageFlags (const Image& image) - { + static CGBitmapInfo getCGImageFlags (const Image& image) + { #if JUCE_BIG_ENDIAN - return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault; + return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault; #else - return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault; + return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault; #endif - } + } }; Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage) { #if USE_COREGRAPHICS_RENDERING - return new CoreGraphicsImage (format == RGB ? ARGB : format, imageWidth, imageHeight, clearImage); + return new CoreGraphicsImage (format == RGB ? ARGB : format, imageWidth, imageHeight, clearImage); #else - return new Image (format, imageWidth, imageHeight, clearImage); + return new Image (format, imageWidth, imageHeight, clearImage); #endif } class CoreGraphicsContext : public LowLevelGraphicsContext { public: - CoreGraphicsContext (CGContextRef context_, const float flipHeight_) - : context (context_), - flipHeight (flipHeight_), - numGradientLookupEntries (0) - { - CGContextRetain (context); - CGContextSaveGState(context); - CGContextSetShouldSmoothFonts (context, true); - CGContextSetShouldAntialias (context, true); - CGContextSetBlendMode (context, kCGBlendModeNormal); - rgbColourSpace = CGColorSpaceCreateDeviceRGB(); - greyColourSpace = CGColorSpaceCreateDeviceGray(); - gradientCallbacks.version = 0; - gradientCallbacks.evaluate = gradientCallback; - gradientCallbacks.releaseInfo = 0; - state = new SavedState(); - } + CoreGraphicsContext (CGContextRef context_, const float flipHeight_) + : context (context_), + flipHeight (flipHeight_), + numGradientLookupEntries (0) + { + CGContextRetain (context); + CGContextSaveGState(context); + CGContextSetShouldSmoothFonts (context, true); + CGContextSetShouldAntialias (context, true); + CGContextSetBlendMode (context, kCGBlendModeNormal); + rgbColourSpace = CGColorSpaceCreateDeviceRGB(); + greyColourSpace = CGColorSpaceCreateDeviceGray(); + gradientCallbacks.version = 0; + gradientCallbacks.evaluate = gradientCallback; + gradientCallbacks.releaseInfo = 0; + state = new SavedState(); + } - ~CoreGraphicsContext() - { - CGContextRestoreGState (context); - CGContextRelease (context); - CGColorSpaceRelease (rgbColourSpace); - CGColorSpaceRelease (greyColourSpace); - } + ~CoreGraphicsContext() + { + CGContextRestoreGState (context); + CGContextRelease (context); + CGColorSpaceRelease (rgbColourSpace); + CGColorSpaceRelease (greyColourSpace); + } - bool isVectorDevice() const { return false; } + bool isVectorDevice() const { return false; } - void setOrigin (int x, int y) - { - CGContextTranslateCTM (context, x, -y); - } + void setOrigin (int x, int y) + { + CGContextTranslateCTM (context, x, -y); + } - bool clipToRectangle (const Rectangle& r) - { - CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight())); - return ! isClipEmpty(); - } + bool clipToRectangle (const Rectangle& r) + { + CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight())); + return ! isClipEmpty(); + } - bool clipToRectangleList (const RectangleList& clipRegion) - { - if (clipRegion.isEmpty()) - { - CGContextClipToRect (context, CGRectMake (0, 0, 0, 0)); - return false; - } - else - { - const int numRects = clipRegion.getNumRectangles(); + bool clipToRectangleList (const RectangleList& clipRegion) + { + if (clipRegion.isEmpty()) + { + CGContextClipToRect (context, CGRectMake (0, 0, 0, 0)); + return false; + } + else + { + const int numRects = clipRegion.getNumRectangles(); - HeapBlock rects (numRects); - for (int i = 0; i < numRects; ++i) - { - const Rectangle& r = clipRegion.getRectangle(i); - rects[i] = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); - } + HeapBlock rects (numRects); + for (int i = 0; i < numRects; ++i) + { + const Rectangle& r = clipRegion.getRectangle(i); + rects[i] = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); + } - CGContextClipToRects (context, rects, numRects); - return ! isClipEmpty(); - } - } + CGContextClipToRects (context, rects, numRects); + return ! isClipEmpty(); + } + } - void excludeClipRectangle (const Rectangle& r) - { - RectangleList remaining (getClipBounds()); - remaining.subtract (r); - clipToRectangleList (remaining); - } + void excludeClipRectangle (const Rectangle& r) + { + RectangleList remaining (getClipBounds()); + remaining.subtract (r); + clipToRectangleList (remaining); + } - void clipToPath (const Path& path, const AffineTransform& transform) - { - createPath (path, transform); - CGContextClip (context); - } + void clipToPath (const Path& path, const AffineTransform& transform) + { + createPath (path, transform); + CGContextClip (context); + } - void clipToImageAlpha (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform) - { - if (! transform.isSingularity()) - { - Image* singleChannelImage = createAlphaChannelImage (sourceImage); - CGImageRef image = CoreGraphicsImage::createImage (*singleChannelImage, true, greyColourSpace); + void clipToImageAlpha (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform) + { + if (! transform.isSingularity()) + { + Image* singleChannelImage = createAlphaChannelImage (sourceImage); + CGImageRef image = CoreGraphicsImage::createImage (*singleChannelImage, true, greyColourSpace); - flip(); - AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform)); - applyTransform (t); + flip(); + AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform)); + applyTransform (t); - CGRect r = CGRectMake (0, 0, sourceImage.getWidth(), sourceImage.getHeight()); - CGContextClipToMask (context, r, image); + CGRect r = CGRectMake (0, 0, sourceImage.getWidth(), sourceImage.getHeight()); + CGContextClipToMask (context, r, image); - applyTransform (t.inverted()); - flip(); + applyTransform (t.inverted()); + flip(); - CGImageRelease (image); - deleteAlphaChannelImage (sourceImage, singleChannelImage); - } - } + CGImageRelease (image); + deleteAlphaChannelImage (sourceImage, singleChannelImage); + } + } - bool clipRegionIntersects (const Rectangle& r) - { - return getClipBounds().intersects (r); - } + bool clipRegionIntersects (const Rectangle& r) + { + return getClipBounds().intersects (r); + } - const Rectangle getClipBounds() const - { - CGRect bounds = CGRectIntegral (CGContextGetClipBoundingBox (context)); + const Rectangle getClipBounds() const + { + CGRect bounds = CGRectIntegral (CGContextGetClipBoundingBox (context)); - return Rectangle (roundFloatToInt (bounds.origin.x), - roundFloatToInt (flipHeight - (bounds.origin.y + bounds.size.height)), - roundFloatToInt (bounds.size.width), - roundFloatToInt (bounds.size.height)); - } + return Rectangle (roundToInt (bounds.origin.x), + roundToInt (flipHeight - (bounds.origin.y + bounds.size.height)), + roundToInt (bounds.size.width), + roundToInt (bounds.size.height)); + } - bool isClipEmpty() const - { - return CGRectIsEmpty (CGContextGetClipBoundingBox (context)); - } + bool isClipEmpty() const + { + return CGRectIsEmpty (CGContextGetClipBoundingBox (context)); + } - void saveState() - { - CGContextSaveGState (context); - stateStack.add (new SavedState (*state)); - } + void saveState() + { + CGContextSaveGState (context); + stateStack.add (new SavedState (*state)); + } - void restoreState() - { - CGContextRestoreGState (context); + void restoreState() + { + CGContextRestoreGState (context); - SavedState* const top = stateStack.getLast(); + SavedState* const top = stateStack.getLast(); - if (top != 0) - { - state = top; - stateStack.removeLast (1, false); - } - else - { - jassertfalse // trying to pop with an empty stack! - } - } + if (top != 0) + { + state = top; + stateStack.removeLast (1, false); + } + else + { + jassertfalse // trying to pop with an empty stack! + } + } - void setFill (const FillType& fillType) - { - state->fillType = fillType; + void setFill (const FillType& fillType) + { + state->fillType = fillType; - if (fillType.isColour()) - { - CGContextSetRGBFillColor (context, fillType.colour.getFloatRed(), fillType.colour.getFloatGreen(), - fillType.colour.getFloatBlue(), fillType.colour.getFloatAlpha()); - CGContextSetAlpha (context, 1.0f); - } - } + if (fillType.isColour()) + { + CGContextSetRGBFillColor (context, fillType.colour.getFloatRed(), fillType.colour.getFloatGreen(), + fillType.colour.getFloatBlue(), fillType.colour.getFloatAlpha()); + CGContextSetAlpha (context, 1.0f); + } + } - void setOpacity (float newOpacity) - { - state->fillType.setOpacity (newOpacity); - setFill (state->fillType); - } + void setOpacity (float newOpacity) + { + state->fillType.setOpacity (newOpacity); + setFill (state->fillType); + } - void setInterpolationQuality (Graphics::ResamplingQuality quality) - { - CGContextSetInterpolationQuality (context, quality == Graphics::lowResamplingQuality - ? kCGInterpolationLow - : kCGInterpolationHigh); - } + void setInterpolationQuality (Graphics::ResamplingQuality quality) + { + CGContextSetInterpolationQuality (context, quality == Graphics::lowResamplingQuality + ? kCGInterpolationLow + : kCGInterpolationHigh); + } - void fillRect (const Rectangle& r, const bool replaceExistingContents) - { - CGRect cgRect = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); + void fillRect (const Rectangle& r, const bool replaceExistingContents) + { + CGRect cgRect = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); - if (replaceExistingContents) - { + if (replaceExistingContents) + { #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 - CGContextClearRect (context, cgRect); + CGContextClearRect (context, cgRect); #else #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 - if (CGContextDrawLinearGradient == 0) // (just a way of checking whether we're running in 10.5 or later) - CGContextClearRect (context, cgRect); - else + if (CGContextDrawLinearGradient == 0) // (just a way of checking whether we're running in 10.5 or later) + CGContextClearRect (context, cgRect); + else #endif - CGContextSetBlendMode (context, kCGBlendModeCopy); + CGContextSetBlendMode (context, kCGBlendModeCopy); #endif - fillRect (r, false); - CGContextSetBlendMode (context, kCGBlendModeNormal); - } - else - { - if (state->fillType.isColour()) - { - CGContextFillRect (context, cgRect); - } - else if (state->fillType.isGradient()) - { - CGContextSaveGState (context); - CGContextClipToRect (context, cgRect); - drawGradient(); - CGContextRestoreGState (context); - } - else - { - CGContextSaveGState (context); - CGContextClipToRect (context, cgRect); - drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); - CGContextRestoreGState (context); - } - } - } + fillRect (r, false); + CGContextSetBlendMode (context, kCGBlendModeNormal); + } + else + { + if (state->fillType.isColour()) + { + CGContextFillRect (context, cgRect); + } + else if (state->fillType.isGradient()) + { + CGContextSaveGState (context); + CGContextClipToRect (context, cgRect); + drawGradient(); + CGContextRestoreGState (context); + } + else + { + CGContextSaveGState (context); + CGContextClipToRect (context, cgRect); + drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); + CGContextRestoreGState (context); + } + } + } - void fillPath (const Path& path, const AffineTransform& transform) - { - CGContextSaveGState (context); + void fillPath (const Path& path, const AffineTransform& transform) + { + CGContextSaveGState (context); - if (state->fillType.isColour()) - { - flip(); - applyTransform (transform); - createPath (path); + if (state->fillType.isColour()) + { + flip(); + applyTransform (transform); + createPath (path); - if (path.isUsingNonZeroWinding()) - CGContextFillPath (context); - else - CGContextEOFillPath (context); - } - else - { - createPath (path, transform); + if (path.isUsingNonZeroWinding()) + CGContextFillPath (context); + else + CGContextEOFillPath (context); + } + else + { + createPath (path, transform); - if (path.isUsingNonZeroWinding()) - CGContextClip (context); - else - CGContextEOClip (context); + if (path.isUsingNonZeroWinding()) + CGContextClip (context); + else + CGContextEOClip (context); - if (state->fillType.isGradient()) - drawGradient(); - else - drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); - } + if (state->fillType.isGradient()) + drawGradient(); + else + drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); + } - CGContextRestoreGState (context); - } + CGContextRestoreGState (context); + } - void drawImage (const Image& sourceImage, const Rectangle& srcClip, - const AffineTransform& transform, const bool fillEntireClipAsTiles) - { - jassert (sourceImage.getBounds().contains (srcClip)); + void drawImage (const Image& sourceImage, const Rectangle& srcClip, + const AffineTransform& transform, const bool fillEntireClipAsTiles) + { + jassert (sourceImage.getBounds().contains (srcClip)); - CGImageRef fullImage = CoreGraphicsImage::createImage (sourceImage, false, rgbColourSpace); - CGImageRef image = fullImage; + CGImageRef fullImage = CoreGraphicsImage::createImage (sourceImage, false, rgbColourSpace); + CGImageRef image = fullImage; - if (srcClip != sourceImage.getBounds()) - { - image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClip.getX(), srcClip.getY(), - srcClip.getWidth(), srcClip.getHeight())); - CGImageRelease (fullImage); - } + if (srcClip != sourceImage.getBounds()) + { + image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClip.getX(), srcClip.getY(), + srcClip.getWidth(), srcClip.getHeight())); + CGImageRelease (fullImage); + } - CGContextSaveGState (context); - CGContextSetAlpha (context, state->fillType.getOpacity()); + CGContextSaveGState (context); + CGContextSetAlpha (context, state->fillType.getOpacity()); - flip(); - applyTransform (AffineTransform::scale (1.0f, -1.0f).translated (0, srcClip.getHeight()).followedBy (transform)); - CGRect imageRect = CGRectMake (0, 0, srcClip.getWidth(), srcClip.getHeight()); + flip(); + applyTransform (AffineTransform::scale (1.0f, -1.0f).translated (0, srcClip.getHeight()).followedBy (transform)); + CGRect imageRect = CGRectMake (0, 0, srcClip.getWidth(), srcClip.getHeight()); - if (fillEntireClipAsTiles) - { + if (fillEntireClipAsTiles) + { #if JUCE_IPHONE || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) - CGContextDrawTiledImage (context, imageRect, image); + CGContextDrawTiledImage (context, imageRect, image); #else #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - if (CGContextDrawTiledImage != 0) - CGContextDrawTiledImage (context, imageRect, image); - else + if (CGContextDrawTiledImage != 0) + CGContextDrawTiledImage (context, imageRect, image); + else #endif - { - // Fallback to manually doing a tiled fill on 10.4 - CGRect clip = CGRectIntegral (CGContextGetClipBoundingBox (context)); - const int iw = srcClip.getWidth(); - const int ih = srcClip.getHeight(); + { + // Fallback to manually doing a tiled fill on 10.4 + CGRect clip = CGRectIntegral (CGContextGetClipBoundingBox (context)); + const int iw = srcClip.getWidth(); + const int ih = srcClip.getHeight(); - int x = 0, y = 0; - while (x > clip.origin.x) x -= iw; - while (y > clip.origin.y) y -= ih; + int x = 0, y = 0; + while (x > clip.origin.x) x -= iw; + while (y > clip.origin.y) y -= ih; - const int right = (int) (clip.origin.x + clip.size.width); - const int bottom = (int) (clip.origin.y + clip.size.height); + const int right = (int) (clip.origin.x + clip.size.width); + const int bottom = (int) (clip.origin.y + clip.size.height); - while (y < bottom) - { - for (int x2 = x; x2 < right; x2 += iw) - CGContextDrawImage (context, CGRectMake (x2, y, iw, ih), image); + while (y < bottom) + { + for (int x2 = x; x2 < right; x2 += iw) + CGContextDrawImage (context, CGRectMake (x2, y, iw, ih), image); - y += ih; - } - } + y += ih; + } + } #endif - } - else - { - CGContextDrawImage (context, imageRect, image); - } + } + else + { + CGContextDrawImage (context, imageRect, image); + } - CGImageRelease (image); // (This causes a memory bug in iPhone sim 3.0 - try upgrading to a later version if you hit this) - CGContextRestoreGState (context); - } + CGImageRelease (image); // (This causes a memory bug in iPhone sim 3.0 - try upgrading to a later version if you hit this) + CGContextRestoreGState (context); + } - void drawLine (double x1, double y1, double x2, double y2) - { - CGContextSetLineCap (context, kCGLineCapSquare); - CGContextSetLineWidth (context, 1.0f); - CGContextSetRGBStrokeColor (context, - state->fillType.colour.getFloatRed(), state->fillType.colour.getFloatGreen(), - state->fillType.colour.getFloatBlue(), state->fillType.colour.getFloatAlpha()); + void drawLine (double x1, double y1, double x2, double y2) + { + CGContextSetLineCap (context, kCGLineCapSquare); + CGContextSetLineWidth (context, 1.0f); + CGContextSetRGBStrokeColor (context, + state->fillType.colour.getFloatRed(), state->fillType.colour.getFloatGreen(), + state->fillType.colour.getFloatBlue(), state->fillType.colour.getFloatAlpha()); - CGPoint line[] = { { (float) x1 + 0.5f, flipHeight - ((float) y1 + 0.5f) }, - { (float) x2 + 0.5f, flipHeight - ((float) y2 + 0.5f) } }; + CGPoint line[] = { { (float) x1 + 0.5f, flipHeight - ((float) y1 + 0.5f) }, + { (float) x2 + 0.5f, flipHeight - ((float) y2 + 0.5f) } }; - CGContextStrokeLineSegments (context, line, 1); - } + CGContextStrokeLineSegments (context, line, 1); + } - void drawVerticalLine (const int x, double top, double bottom) - { - CGContextFillRect (context, CGRectMake (x, flipHeight - (float) bottom, 1.0f, (float) (bottom - top))); - } + void drawVerticalLine (const int x, double top, double bottom) + { + CGContextFillRect (context, CGRectMake (x, flipHeight - (float) bottom, 1.0f, (float) (bottom - top))); + } - void drawHorizontalLine (const int y, double left, double right) - { - CGContextFillRect (context, CGRectMake ((float) left, flipHeight - (y + 1.0f), (float) (right - left), 1.0f)); - } + void drawHorizontalLine (const int y, double left, double right) + { + CGContextFillRect (context, CGRectMake ((float) left, flipHeight - (y + 1.0f), (float) (right - left), 1.0f)); + } - void setFont (const Font& newFont) - { - if (state->font != newFont) - { - state->fontRef = 0; - state->font = newFont; + void setFont (const Font& newFont) + { + if (state->font != newFont) + { + state->fontRef = 0; + state->font = newFont; - MacTypeface* mf = dynamic_cast ((Typeface*) state->font.getTypeface()); + MacTypeface* mf = dynamic_cast ((Typeface*) state->font.getTypeface()); - if (mf != 0) - { - state->fontRef = mf->fontRef; - CGContextSetFont (context, state->fontRef); - CGContextSetFontSize (context, state->font.getHeight() * mf->fontHeightToCGSizeFactor); + if (mf != 0) + { + state->fontRef = mf->fontRef; + CGContextSetFont (context, state->fontRef); + CGContextSetFontSize (context, state->font.getHeight() * mf->fontHeightToCGSizeFactor); - state->fontTransform = mf->renderingTransform; - state->fontTransform.a *= state->font.getHorizontalScale(); - CGContextSetTextMatrix (context, state->fontTransform); - } - } - } + state->fontTransform = mf->renderingTransform; + state->fontTransform.a *= state->font.getHorizontalScale(); + CGContextSetTextMatrix (context, state->fontTransform); + } + } + } - const Font getFont() - { - return state->font; - } + const Font getFont() + { + return state->font; + } - void drawGlyph (int glyphNumber, const AffineTransform& transform) - { - if (state->fontRef != 0 && state->fillType.isColour()) - { - if (transform.isOnlyTranslation()) - { - CGGlyph g = glyphNumber; - CGContextShowGlyphsAtPoint (context, transform.getTranslationX(), - flipHeight - roundFloatToInt (transform.getTranslationY()), &g, 1); - } - else - { - CGContextSaveGState (context); - flip(); - applyTransform (transform); + void drawGlyph (int glyphNumber, const AffineTransform& transform) + { + if (state->fontRef != 0 && state->fillType.isColour()) + { + if (transform.isOnlyTranslation()) + { + CGGlyph g = glyphNumber; + CGContextShowGlyphsAtPoint (context, transform.getTranslationX(), + flipHeight - roundToInt (transform.getTranslationY()), &g, 1); + } + else + { + CGContextSaveGState (context); + flip(); + applyTransform (transform); - CGAffineTransform t = state->fontTransform; - t.d = -t.d; - CGContextSetTextMatrix (context, t); + CGAffineTransform t = state->fontTransform; + t.d = -t.d; + CGContextSetTextMatrix (context, t); - CGGlyph g = glyphNumber; - CGContextShowGlyphsAtPoint (context, 0, 0, &g, 1); + CGGlyph g = glyphNumber; + CGContextShowGlyphsAtPoint (context, 0, 0, &g, 1); - CGContextSetTextMatrix (context, state->fontTransform); - CGContextRestoreGState (context); - } - } - else - { - Path p; - Font& f = state->font; - f.getTypeface()->getOutlineForGlyph (glyphNumber, p); + CGContextSetTextMatrix (context, state->fontTransform); + CGContextRestoreGState (context); + } + } + else + { + Path p; + Font& f = state->font; + f.getTypeface()->getOutlineForGlyph (glyphNumber, p); - fillPath (p, AffineTransform::scale (f.getHeight() * f.getHorizontalScale(), f.getHeight()) - .followedBy (transform)); - } - } + fillPath (p, AffineTransform::scale (f.getHeight() * f.getHorizontalScale(), f.getHeight()) + .followedBy (transform)); + } + } private: - CGContextRef context; - const float flipHeight; - CGColorSpaceRef rgbColourSpace, greyColourSpace; - CGFunctionCallbacks gradientCallbacks; + CGContextRef context; + const float flipHeight; + CGColorSpaceRef rgbColourSpace, greyColourSpace; + CGFunctionCallbacks gradientCallbacks; - struct SavedState - { - SavedState() - : font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity) - { - } + struct SavedState + { + SavedState() + : font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity) + { + } - SavedState (const SavedState& other) - : fillType (other.fillType), font (other.font), fontRef (other.fontRef), - fontTransform (other.fontTransform) - { - } + SavedState (const SavedState& other) + : fillType (other.fillType), font (other.font), fontRef (other.fontRef), + fontTransform (other.fontTransform) + { + } - ~SavedState() - { - } + ~SavedState() + { + } - FillType fillType; - Font font; - CGFontRef fontRef; - CGAffineTransform fontTransform; - }; + FillType fillType; + Font font; + CGFontRef fontRef; + CGAffineTransform fontTransform; + }; - ScopedPointer state; - OwnedArray stateStack; - HeapBlock gradientLookupTable; - int numGradientLookupEntries; + ScopedPointer state; + OwnedArray stateStack; + HeapBlock gradientLookupTable; + int numGradientLookupEntries; - static void gradientCallback (void* info, const CGFloat* inData, CGFloat* outData) - { - const CoreGraphicsContext* const g = (const CoreGraphicsContext*) info; + static void gradientCallback (void* info, const CGFloat* inData, CGFloat* outData) + { + const CoreGraphicsContext* const g = (const CoreGraphicsContext*) info; - const int index = roundFloatToInt (g->numGradientLookupEntries * inData[0]); - PixelARGB colour (g->gradientLookupTable [jlimit (0, g->numGradientLookupEntries, index)]); - colour.unpremultiply(); + const int index = roundToInt (g->numGradientLookupEntries * inData[0]); + PixelARGB colour (g->gradientLookupTable [jlimit (0, g->numGradientLookupEntries, index)]); + colour.unpremultiply(); - outData[0] = colour.getRed() / 255.0f; - outData[1] = colour.getGreen() / 255.0f; - outData[2] = colour.getBlue() / 255.0f; - outData[3] = colour.getAlpha() / 255.0f; - } + outData[0] = colour.getRed() / 255.0f; + outData[1] = colour.getGreen() / 255.0f; + outData[2] = colour.getBlue() / 255.0f; + outData[3] = colour.getAlpha() / 255.0f; + } - CGShadingRef createGradient (const AffineTransform& transform, ColourGradient gradient) - { - numGradientLookupEntries = gradient.createLookupTable (transform, gradientLookupTable); - --numGradientLookupEntries; + CGShadingRef createGradient (const AffineTransform& transform, ColourGradient gradient) + { + numGradientLookupEntries = gradient.createLookupTable (transform, gradientLookupTable); + --numGradientLookupEntries; - CGShadingRef result = 0; - CGFunctionRef function = CGFunctionCreate ((void*) this, 1, 0, 4, 0, &gradientCallbacks); - CGPoint p1 (CGPointMake (gradient.x1, gradient.y1)); + CGShadingRef result = 0; + CGFunctionRef function = CGFunctionCreate ((void*) this, 1, 0, 4, 0, &gradientCallbacks); + CGPoint p1 (CGPointMake (gradient.x1, gradient.y1)); - if (gradient.isRadial) - { - result = CGShadingCreateRadial (rgbColourSpace, p1, 0, - p1, hypotf (gradient.x1 - gradient.x2, gradient.y1 - gradient.y2), - function, true, true); - } - else - { - result = CGShadingCreateAxial (rgbColourSpace, p1, - CGPointMake (gradient.x2, gradient.y2), - function, true, true); - } + if (gradient.isRadial) + { + result = CGShadingCreateRadial (rgbColourSpace, p1, 0, + p1, hypotf (gradient.x1 - gradient.x2, gradient.y1 - gradient.y2), + function, true, true); + } + else + { + result = CGShadingCreateAxial (rgbColourSpace, p1, + CGPointMake (gradient.x2, gradient.y2), + function, true, true); + } - CGFunctionRelease (function); - return result; - } + CGFunctionRelease (function); + return result; + } - void drawGradient() - { - flip(); - applyTransform (state->fillType.transform); + void drawGradient() + { + flip(); + applyTransform (state->fillType.transform); - CGContextSetInterpolationQuality (context, kCGInterpolationDefault); // (This is required for 10.4, where there's a crash if - // you draw a gradient with high quality interp enabled). - CGShadingRef shading = createGradient (state->fillType.transform, *(state->fillType.gradient)); - CGContextSetAlpha (context, state->fillType.getOpacity()); - CGContextDrawShading (context, shading); - CGShadingRelease (shading); - } + CGContextSetInterpolationQuality (context, kCGInterpolationDefault); // (This is required for 10.4, where there's a crash if + // you draw a gradient with high quality interp enabled). + CGShadingRef shading = createGradient (state->fillType.transform, *(state->fillType.gradient)); + CGContextSetAlpha (context, state->fillType.getOpacity()); + CGContextDrawShading (context, shading); + CGShadingRelease (shading); + } - void createPath (const Path& path) const - { - CGContextBeginPath (context); - Path::Iterator i (path); + void createPath (const Path& path) const + { + CGContextBeginPath (context); + Path::Iterator i (path); - while (i.next()) - { - switch (i.elementType) - { - case Path::Iterator::startNewSubPath: - CGContextMoveToPoint (context, i.x1, i.y1); - break; - case Path::Iterator::lineTo: - CGContextAddLineToPoint (context, i.x1, i.y1); - break; - case Path::Iterator::quadraticTo: - CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); - break; - case Path::Iterator::cubicTo: - CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); - break; - case Path::Iterator::closePath: - CGContextClosePath (context); break; - default: - jassertfalse - break; - } - } - } + while (i.next()) + { + switch (i.elementType) + { + case Path::Iterator::startNewSubPath: + CGContextMoveToPoint (context, i.x1, i.y1); + break; + case Path::Iterator::lineTo: + CGContextAddLineToPoint (context, i.x1, i.y1); + break; + case Path::Iterator::quadraticTo: + CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); + break; + case Path::Iterator::cubicTo: + CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); + break; + case Path::Iterator::closePath: + CGContextClosePath (context); break; + default: + jassertfalse + break; + } + } + } - void createPath (const Path& path, const AffineTransform& transform) const - { - CGContextBeginPath (context); - Path::Iterator i (path); + void createPath (const Path& path, const AffineTransform& transform) const + { + CGContextBeginPath (context); + Path::Iterator i (path); - while (i.next()) - { - switch (i.elementType) - { - case Path::Iterator::startNewSubPath: - transform.transformPoint (i.x1, i.y1); - CGContextMoveToPoint (context, i.x1, flipHeight - i.y1); - break; - case Path::Iterator::lineTo: - transform.transformPoint (i.x1, i.y1); - CGContextAddLineToPoint (context, i.x1, flipHeight - i.y1); - break; - case Path::Iterator::quadraticTo: - transform.transformPoint (i.x1, i.y1); - transform.transformPoint (i.x2, i.y2); - CGContextAddQuadCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2); - break; - case Path::Iterator::cubicTo: - transform.transformPoint (i.x1, i.y1); - transform.transformPoint (i.x2, i.y2); - transform.transformPoint (i.x3, i.y3); - CGContextAddCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2, i.x3, flipHeight - i.y3); - break; - case Path::Iterator::closePath: - CGContextClosePath (context); break; - default: - jassertfalse - break; - } - } - } + while (i.next()) + { + switch (i.elementType) + { + case Path::Iterator::startNewSubPath: + transform.transformPoint (i.x1, i.y1); + CGContextMoveToPoint (context, i.x1, flipHeight - i.y1); + break; + case Path::Iterator::lineTo: + transform.transformPoint (i.x1, i.y1); + CGContextAddLineToPoint (context, i.x1, flipHeight - i.y1); + break; + case Path::Iterator::quadraticTo: + transform.transformPoint (i.x1, i.y1); + transform.transformPoint (i.x2, i.y2); + CGContextAddQuadCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2); + break; + case Path::Iterator::cubicTo: + transform.transformPoint (i.x1, i.y1); + transform.transformPoint (i.x2, i.y2); + transform.transformPoint (i.x3, i.y3); + CGContextAddCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2, i.x3, flipHeight - i.y3); + break; + case Path::Iterator::closePath: + CGContextClosePath (context); break; + default: + jassertfalse + break; + } + } + } - static Image* createAlphaChannelImage (const Image& im) - { - if (im.getFormat() == Image::SingleChannel) - return const_cast (&im); + static Image* createAlphaChannelImage (const Image& im) + { + if (im.getFormat() == Image::SingleChannel) + return const_cast (&im); - return im.createCopyOfAlphaChannel(); - } + return im.createCopyOfAlphaChannel(); + } - static void deleteAlphaChannelImage (const Image& im, Image* const alphaIm) - { - if (im.getFormat() != Image::SingleChannel) - delete alphaIm; - } + static void deleteAlphaChannelImage (const Image& im, Image* const alphaIm) + { + if (im.getFormat() != Image::SingleChannel) + delete alphaIm; + } - void flip() const - { - CGContextConcatCTM (context, CGAffineTransformMake (1, 0, 0, -1, 0, flipHeight)); - } + void flip() const + { + CGContextConcatCTM (context, CGAffineTransformMake (1, 0, 0, -1, 0, flipHeight)); + } - void applyTransform (const AffineTransform& transform) const - { - CGAffineTransform t; - t.a = transform.mat00; - t.b = transform.mat10; - t.c = transform.mat01; - t.d = transform.mat11; - t.tx = transform.mat02; - t.ty = transform.mat12; - CGContextConcatCTM (context, t); - } + void applyTransform (const AffineTransform& transform) const + { + CGAffineTransform t; + t.a = transform.mat00; + t.b = transform.mat10; + t.c = transform.mat01; + t.d = transform.mat11; + t.tx = transform.mat02; + t.ty = transform.mat12; + CGContextConcatCTM (context, t); + } - float flipY (float y) const - { - return flipHeight - y; - } + float flipY (float y) const + { + return flipHeight - y; + } }; LowLevelGraphicsContext* CoreGraphicsImage::createLowLevelContext() { - return new CoreGraphicsContext (context, imageHeight); + return new CoreGraphicsContext (context, imageHeight); } #endif @@ -267518,8 +245088,8 @@ END_JUCE_NAMESPACE @interface JuceNSView : NSView { @public - NSViewComponentPeer* owner; - NSNotificationCenter* notificationCenter; + NSViewComponentPeer* owner; + NSNotificationCenter* notificationCenter; } - (JuceNSView*) initWithOwner: (NSViewComponentPeer*) owner withFrame: (NSRect) frame; @@ -267581,8 +245151,8 @@ END_JUCE_NAMESPACE #endif { @private - NSViewComponentPeer* owner; - bool isZooming; + NSViewComponentPeer* owner; + bool isZooming; } - (void) setOwner: (NSViewComponentPeer*) owner; @@ -267599,93 +245169,83 @@ BEGIN_JUCE_NAMESPACE class NSViewComponentPeer : public ComponentPeer { public: - NSViewComponentPeer (Component* const component, - const int windowStyleFlags, - NSView* viewToAttachTo); + NSViewComponentPeer (Component* const component, + const int windowStyleFlags, + NSView* viewToAttachTo); - ~NSViewComponentPeer(); + ~NSViewComponentPeer(); - void* getNativeHandle() const; - void setVisible (bool shouldBeVisible); - void setTitle (const String& title); - void setPosition (int x, int y); - void setSize (int w, int h); - void setBounds (int x, int y, int w, int h, const bool isNowFullScreen); - void getBounds (int& x, int& y, int& w, int& h, const bool global) const; - void getBounds (int& x, int& y, int& w, int& h) const; - int getScreenX() const; - int getScreenY() const; - void relativePositionToGlobal (int& x, int& y); - void globalPositionToRelative (int& x, int& y); - void setMinimised (bool shouldBeMinimised); - bool isMinimised() const; - void setFullScreen (bool shouldBeFullScreen); - bool isFullScreen() const; - bool contains (int x, int y, bool trueIfInAChildWindow) const; - const BorderSize getFrameSize() const; - bool setAlwaysOnTop (bool alwaysOnTop); - void toFront (bool makeActiveWindow); - void toBehind (ComponentPeer* other); - void setIcon (const Image& newIcon); - const StringArray getAvailableRenderingEngines() throw(); - int getCurrentRenderingEngine() throw(); - void setCurrentRenderingEngine (int index) throw(); + void* getNativeHandle() const; + void setVisible (bool shouldBeVisible); + void setTitle (const String& title); + void setPosition (int x, int y); + void setSize (int w, int h); + void setBounds (int x, int y, int w, int h, const bool isNowFullScreen); + void getBounds (int& x, int& y, int& w, int& h, const bool global) const; + void getBounds (int& x, int& y, int& w, int& h) const; + int getScreenX() const; + int getScreenY() const; + void relativePositionToGlobal (int& x, int& y); + void globalPositionToRelative (int& x, int& y); + void setMinimised (bool shouldBeMinimised); + bool isMinimised() const; + void setFullScreen (bool shouldBeFullScreen); + bool isFullScreen() const; + bool contains (int x, int y, bool trueIfInAChildWindow) const; + const BorderSize getFrameSize() const; + bool setAlwaysOnTop (bool alwaysOnTop); + void toFront (bool makeActiveWindow); + void toBehind (ComponentPeer* other); + void setIcon (const Image& newIcon); + const StringArray getAvailableRenderingEngines() throw(); + int getCurrentRenderingEngine() throw(); + void setCurrentRenderingEngine (int index) throw(); - /* When you use multiple DLLs which share similarly-named obj-c classes - like - for example having more than one juce plugin loaded into a host, then when a - method is called, the actual code that runs might actually be in a different module - than the one you expect... So any calls to library functions or statics that are - made inside obj-c methods will probably end up getting executed in a different DLL's - memory space. Not a great thing to happen - this obviously leads to bizarre crashes. + virtual void redirectMouseDown (NSEvent* ev); + virtual void redirectMouseUp (NSEvent* ev); + virtual void redirectMouseDrag (NSEvent* ev); + virtual void redirectMouseMove (NSEvent* ev); + virtual void redirectMouseEnter (NSEvent* ev); + virtual void redirectMouseExit (NSEvent* ev); + virtual void redirectMouseWheel (NSEvent* ev); - To work around this insanity, I'm only allowing obj-c methods to make calls to - virtual methods of an object that's known to live inside the right module's space. - */ - virtual void redirectMouseDown (NSEvent* ev); - virtual void redirectMouseUp (NSEvent* ev); - virtual void redirectMouseDrag (NSEvent* ev); - virtual void redirectMouseMove (NSEvent* ev); - virtual void redirectMouseEnter (NSEvent* ev); - virtual void redirectMouseExit (NSEvent* ev); - virtual void redirectMouseWheel (NSEvent* ev); - - bool handleKeyEvent (NSEvent* ev, bool isKeyDown); - virtual bool redirectKeyDown (NSEvent* ev); - virtual bool redirectKeyUp (NSEvent* ev); - virtual void redirectModKeyChange (NSEvent* ev); + bool handleKeyEvent (NSEvent* ev, bool isKeyDown); + virtual bool redirectKeyDown (NSEvent* ev); + virtual bool redirectKeyUp (NSEvent* ev); + virtual void redirectModKeyChange (NSEvent* ev); #if MACOS_10_4_OR_EARLIER - virtual bool redirectPerformKeyEquivalent (NSEvent* ev); + virtual bool redirectPerformKeyEquivalent (NSEvent* ev); #endif - virtual BOOL sendDragCallback (int type, id sender); + virtual BOOL sendDragCallback (int type, id sender); - virtual bool isOpaque(); - virtual void drawRect (NSRect r); + virtual bool isOpaque(); + virtual void drawRect (NSRect r); - virtual bool canBecomeKeyWindow(); - virtual bool windowShouldClose(); + virtual bool canBecomeKeyWindow(); + virtual bool windowShouldClose(); - virtual void redirectMovedOrResized(); - virtual void viewMovedToWindow(); + virtual void redirectMovedOrResized(); + virtual void viewMovedToWindow(); - virtual NSRect constrainRect (NSRect r); + virtual NSRect constrainRect (NSRect r); - static void showArrowCursorIfNeeded(); + static void showArrowCursorIfNeeded(); - virtual void viewFocusGain(); - virtual void viewFocusLoss(); - bool isFocused() const; - void grabFocus(); - void textInputRequired (int x, int y); + virtual void viewFocusGain(); + virtual void viewFocusLoss(); + bool isFocused() const; + void grabFocus(); + void textInputRequired (int x, int y); - void repaint (int x, int y, int w, int h); - void performAnyPendingRepaintsNow(); + void repaint (int x, int y, int w, int h); + void performAnyPendingRepaintsNow(); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - NSWindow* window; - JuceNSView* view; - bool isSharedWindow, fullScreen, insideDrawRect, usingCoreGraphics; + NSWindow* window; + JuceNSView* view; + bool isSharedWindow, fullScreen, insideDrawRect, usingCoreGraphics; }; END_JUCE_NAMESPACE @@ -267693,262 +245253,262 @@ END_JUCE_NAMESPACE @implementation JuceNSView - (JuceNSView*) initWithOwner: (NSViewComponentPeer*) owner_ - withFrame: (NSRect) frame + withFrame: (NSRect) frame { - [super initWithFrame: frame]; - owner = owner_; + [super initWithFrame: frame]; + owner = owner_; - notificationCenter = [NSNotificationCenter defaultCenter]; + notificationCenter = [NSNotificationCenter defaultCenter]; - [notificationCenter addObserver: self - selector: @selector (frameChanged:) - name: NSViewFrameDidChangeNotification - object: self]; + [notificationCenter addObserver: self + selector: @selector (frameChanged:) + name: NSViewFrameDidChangeNotification + object: self]; - if (! owner_->isSharedWindow) - { - [notificationCenter addObserver: self - selector: @selector (frameChanged:) - name: NSWindowDidMoveNotification - object: owner_->window]; - } + if (! owner_->isSharedWindow) + { + [notificationCenter addObserver: self + selector: @selector (frameChanged:) + name: NSWindowDidMoveNotification + object: owner_->window]; + } - [self registerForDraggedTypes: [self getSupportedDragTypes]]; + [self registerForDraggedTypes: [self getSupportedDragTypes]]; - return self; + return self; } - (void) dealloc { - [notificationCenter removeObserver: self]; - [super dealloc]; + [notificationCenter removeObserver: self]; + [super dealloc]; } - (void) drawRect: (NSRect) r { - if (owner != 0) - owner->drawRect (r); + if (owner != 0) + owner->drawRect (r); } - (BOOL) isOpaque { - return owner == 0 || owner->isOpaque(); + return owner == 0 || owner->isOpaque(); } - (void) mouseDown: (NSEvent*) ev { - // In some host situations, the host will stop modal loops from working - // correctly if they're called from a mouse event, so we'll trigger - // the event asynchronously.. - if (JUCEApplication::getInstance() == 0) - [self performSelectorOnMainThread: @selector (asyncMouseDown:) - withObject: ev - waitUntilDone: NO]; - else - [self asyncMouseDown: ev]; + // In some host situations, the host will stop modal loops from working + // correctly if they're called from a mouse event, so we'll trigger + // the event asynchronously.. + if (JUCEApplication::getInstance() == 0) + [self performSelectorOnMainThread: @selector (asyncMouseDown:) + withObject: ev + waitUntilDone: NO]; + else + [self asyncMouseDown: ev]; } - (void) asyncMouseDown: (NSEvent*) ev { - if (owner != 0) - owner->redirectMouseDown (ev); + if (owner != 0) + owner->redirectMouseDown (ev); } - (void) mouseUp: (NSEvent*) ev { - // In some host situations, the host will stop modal loops from working - // correctly if they're called from a mouse event, so we'll trigger - // the event asynchronously.. - if (JUCEApplication::getInstance() == 0) - [self performSelectorOnMainThread: @selector (asyncMouseUp:) - withObject: ev - waitUntilDone: NO]; - else - [self asyncMouseUp: ev]; + // In some host situations, the host will stop modal loops from working + // correctly if they're called from a mouse event, so we'll trigger + // the event asynchronously.. + if (JUCEApplication::getInstance() == 0) + [self performSelectorOnMainThread: @selector (asyncMouseUp:) + withObject: ev + waitUntilDone: NO]; + else + [self asyncMouseUp: ev]; } - (void) asyncMouseUp: (NSEvent*) ev { - if (owner != 0) - owner->redirectMouseUp (ev); + if (owner != 0) + owner->redirectMouseUp (ev); } - (void) mouseDragged: (NSEvent*) ev { - if (owner != 0) - owner->redirectMouseDrag (ev); + if (owner != 0) + owner->redirectMouseDrag (ev); } - (void) mouseMoved: (NSEvent*) ev { - if (owner != 0) - owner->redirectMouseMove (ev); + if (owner != 0) + owner->redirectMouseMove (ev); } - (void) mouseEntered: (NSEvent*) ev { - if (owner != 0) - owner->redirectMouseEnter (ev); + if (owner != 0) + owner->redirectMouseEnter (ev); } - (void) mouseExited: (NSEvent*) ev { - if (owner != 0) - owner->redirectMouseExit (ev); + if (owner != 0) + owner->redirectMouseExit (ev); } - (void) rightMouseDown: (NSEvent*) ev { - [self mouseDown: ev]; + [self mouseDown: ev]; } - (void) rightMouseDragged: (NSEvent*) ev { - [self mouseDragged: ev]; + [self mouseDragged: ev]; } - (void) rightMouseUp: (NSEvent*) ev { - [self mouseUp: ev]; + [self mouseUp: ev]; } - (void) otherMouseDown: (NSEvent*) ev { - [self mouseDown: ev]; + [self mouseDown: ev]; } - (void) otherMouseDragged: (NSEvent*) ev { - [self mouseDragged: ev]; + [self mouseDragged: ev]; } - (void) otherMouseUp: (NSEvent*) ev { - [self mouseUp: ev]; + [self mouseUp: ev]; } - (void) scrollWheel: (NSEvent*) ev { - if (owner != 0) - owner->redirectMouseWheel (ev); + if (owner != 0) + owner->redirectMouseWheel (ev); } - (BOOL) acceptsFirstMouse: (NSEvent*) ev { - return YES; + return YES; } - (void) frameChanged: (NSNotification*) n { - if (owner != 0) - owner->redirectMovedOrResized(); + if (owner != 0) + owner->redirectMovedOrResized(); } - (void) viewDidMoveToWindow { if (owner != 0) - owner->viewMovedToWindow(); + owner->viewMovedToWindow(); } - (void) asyncRepaint: (id) rect { - NSRect* r = (NSRect*) [((NSData*) rect) bytes]; - [self setNeedsDisplayInRect: *r]; + NSRect* r = (NSRect*) [((NSData*) rect) bytes]; + [self setNeedsDisplayInRect: *r]; } - (void) keyDown: (NSEvent*) ev { - if (owner == 0 || ! owner->redirectKeyDown (ev)) - [super keyDown: ev]; + if (owner == 0 || ! owner->redirectKeyDown (ev)) + [super keyDown: ev]; } - (void) keyUp: (NSEvent*) ev { - if (owner == 0 || ! owner->redirectKeyUp (ev)) - [super keyUp: ev]; + if (owner == 0 || ! owner->redirectKeyUp (ev)) + [super keyUp: ev]; } - (void) flagsChanged: (NSEvent*) ev { - if (owner != 0) - owner->redirectModKeyChange (ev); + if (owner != 0) + owner->redirectModKeyChange (ev); } #if MACOS_10_4_OR_EARLIER - (BOOL) performKeyEquivalent: (NSEvent*) ev { - if (owner != 0 && owner->redirectPerformKeyEquivalent (ev)) - return true; + if (owner != 0 && owner->redirectPerformKeyEquivalent (ev)) + return true; - return [super performKeyEquivalent: ev]; + return [super performKeyEquivalent: ev]; } #endif - (BOOL) becomeFirstResponder { - if (owner != 0) - owner->viewFocusGain(); + if (owner != 0) + owner->viewFocusGain(); - return true; + return true; } - (BOOL) resignFirstResponder { - if (owner != 0) - owner->viewFocusLoss(); + if (owner != 0) + owner->viewFocusLoss(); - return true; + return true; } - (BOOL) acceptsFirstResponder { - return owner != 0 && owner->canBecomeKeyWindow(); + return owner != 0 && owner->canBecomeKeyWindow(); } - (NSArray*) getSupportedDragTypes { - return [NSArray arrayWithObjects: NSFilenamesPboardType, /*NSFilesPromisePboardType, NSStringPboardType,*/ nil]; + return [NSArray arrayWithObjects: NSFilenamesPboardType, /*NSFilesPromisePboardType, NSStringPboardType,*/ nil]; } - (BOOL) sendDragCallback: (int) type sender: (id ) sender { - return owner != 0 && owner->sendDragCallback (type, sender); + return owner != 0 && owner->sendDragCallback (type, sender); } - (NSDragOperation) draggingEntered: (id ) sender { - if ([self sendDragCallback: 0 sender: sender]) - return NSDragOperationCopy | NSDragOperationMove | NSDragOperationGeneric; - else - return NSDragOperationNone; + if ([self sendDragCallback: 0 sender: sender]) + return NSDragOperationCopy | NSDragOperationMove | NSDragOperationGeneric; + else + return NSDragOperationNone; } - (NSDragOperation) draggingUpdated: (id ) sender { - if ([self sendDragCallback: 0 sender: sender]) - return NSDragOperationCopy | NSDragOperationMove | NSDragOperationGeneric; - else - return NSDragOperationNone; + if ([self sendDragCallback: 0 sender: sender]) + return NSDragOperationCopy | NSDragOperationMove | NSDragOperationGeneric; + else + return NSDragOperationNone; } - (void) draggingEnded: (id ) sender { - [self sendDragCallback: 1 sender: sender]; + [self sendDragCallback: 1 sender: sender]; } - (void) draggingExited: (id ) sender { - [self sendDragCallback: 1 sender: sender]; + [self sendDragCallback: 1 sender: sender]; } - (BOOL) prepareForDragOperation: (id ) sender { - return YES; + return YES; } - (BOOL) performDragOperation: (id ) sender { - return [self sendDragCallback: 2 sender: sender]; + return [self sendDragCallback: 2 sender: sender]; } - (void) concludeDragOperation: (id ) sender @@ -267961,64 +245521,64 @@ END_JUCE_NAMESPACE - (void) setOwner: (NSViewComponentPeer*) owner_ { - owner = owner_; - isZooming = false; + owner = owner_; + isZooming = false; } - (BOOL) canBecomeKeyWindow { - return owner != 0 && owner->canBecomeKeyWindow(); + return owner != 0 && owner->canBecomeKeyWindow(); } - (void) becomeKeyWindow { - [super becomeKeyWindow]; + [super becomeKeyWindow]; - if (owner != 0) - owner->grabFocus(); + if (owner != 0) + owner->grabFocus(); } - (BOOL) windowShouldClose: (id) window { - return owner == 0 || owner->windowShouldClose(); + return owner == 0 || owner->windowShouldClose(); } - (NSRect) constrainFrameRect: (NSRect) frameRect toScreen: (NSScreen*) screen { - if (owner != 0) - frameRect = owner->constrainRect (frameRect); + if (owner != 0) + frameRect = owner->constrainRect (frameRect); - return frameRect; + return frameRect; } - (NSSize) windowWillResize: (NSWindow*) window toSize: (NSSize) proposedFrameSize { - if (isZooming) - return proposedFrameSize; + if (isZooming) + return proposedFrameSize; - NSRect frameRect = [self frame]; - frameRect.origin.y -= proposedFrameSize.height - frameRect.size.height; - frameRect.size = proposedFrameSize; + NSRect frameRect = [self frame]; + frameRect.origin.y -= proposedFrameSize.height - frameRect.size.height; + frameRect.size = proposedFrameSize; - if (owner != 0) - frameRect = owner->constrainRect (frameRect); + if (owner != 0) + frameRect = owner->constrainRect (frameRect); - return frameRect.size; + return frameRect.size; } - (void) zoom: (id) sender { - isZooming = true; - [super zoom: sender]; - isZooming = false; + isZooming = true; + [super zoom: sender]; + isZooming = false; } - (void) windowWillMove: (NSNotification*) notification { - if (JUCE_NAMESPACE::Component::getCurrentlyModalComponent() != 0 - && owner->getComponent()->isCurrentlyBlockedByAnotherModalComponent() - && (owner->getStyleFlags() & JUCE_NAMESPACE::ComponentPeer::windowHasTitleBar) != 0) - JUCE_NAMESPACE::Component::getCurrentlyModalComponent()->inputAttemptWhenModal(); + if (JUCE_NAMESPACE::Component::getCurrentlyModalComponent() != 0 + && owner->getComponent()->isCurrentlyBlockedByAnotherModalComponent() + && (owner->getStyleFlags() & JUCE_NAMESPACE::ComponentPeer::windowHasTitleBar) != 0) + JUCE_NAMESPACE::Component::getCurrentlyModalComponent()->inputAttemptWhenModal(); } @end @@ -268030,552 +245590,552 @@ static VoidArray keysCurrentlyDown; bool KeyPress::isKeyCurrentlyDown (const int keyCode) throw() { - if (keysCurrentlyDown.contains ((void*) keyCode)) - return true; + if (keysCurrentlyDown.contains ((void*) keyCode)) + return true; - if (keyCode >= 'A' && keyCode <= 'Z' - && keysCurrentlyDown.contains ((void*) (int) CharacterFunctions::toLowerCase ((tchar) keyCode))) - return true; + if (keyCode >= 'A' && keyCode <= 'Z' + && keysCurrentlyDown.contains ((void*) (int) CharacterFunctions::toLowerCase ((tchar) keyCode))) + return true; - if (keyCode >= 'a' && keyCode <= 'z' - && keysCurrentlyDown.contains ((void*) (int) CharacterFunctions::toUpperCase ((tchar) keyCode))) - return true; + if (keyCode >= 'a' && keyCode <= 'z' + && keysCurrentlyDown.contains ((void*) (int) CharacterFunctions::toUpperCase ((tchar) keyCode))) + return true; - return false; + return false; } static int getKeyCodeFromEvent (NSEvent* ev) { - const String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers])); - int keyCode = unmodified[0]; + const String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers])); + int keyCode = unmodified[0]; - if (keyCode == 0x19) // (backwards-tab) - keyCode = '\t'; - else if (keyCode == 0x03) // (enter) - keyCode = '\r'; + if (keyCode == 0x19) // (backwards-tab) + keyCode = '\t'; + else if (keyCode == 0x03) // (enter) + keyCode = '\r'; - return keyCode; + return keyCode; } static int currentModifiers = 0; static void updateModifiers (NSEvent* e) { - int m = currentModifiers & ~(ModifierKeys::shiftModifier | ModifierKeys::ctrlModifier - | ModifierKeys::altModifier | ModifierKeys::commandModifier); + int m = currentModifiers & ~(ModifierKeys::shiftModifier | ModifierKeys::ctrlModifier + | ModifierKeys::altModifier | ModifierKeys::commandModifier); - if (([e modifierFlags] & NSShiftKeyMask) != 0) - m |= ModifierKeys::shiftModifier; + if (([e modifierFlags] & NSShiftKeyMask) != 0) + m |= ModifierKeys::shiftModifier; - if (([e modifierFlags] & NSControlKeyMask) != 0) - m |= ModifierKeys::ctrlModifier; + if (([e modifierFlags] & NSControlKeyMask) != 0) + m |= ModifierKeys::ctrlModifier; - if (([e modifierFlags] & NSAlternateKeyMask) != 0) - m |= ModifierKeys::altModifier; + if (([e modifierFlags] & NSAlternateKeyMask) != 0) + m |= ModifierKeys::altModifier; - if (([e modifierFlags] & NSCommandKeyMask) != 0) - m |= ModifierKeys::commandModifier; + if (([e modifierFlags] & NSCommandKeyMask) != 0) + m |= ModifierKeys::commandModifier; - currentModifiers = m; + currentModifiers = m; } static void updateKeysDown (NSEvent* ev, bool isKeyDown) { - updateModifiers (ev); - int keyCode = getKeyCodeFromEvent (ev); + updateModifiers (ev); + int keyCode = getKeyCodeFromEvent (ev); - if (keyCode != 0) - { - if (isKeyDown) - keysCurrentlyDown.addIfNotAlreadyThere ((void*) keyCode); - else - keysCurrentlyDown.removeValue ((void*) keyCode); - } + if (keyCode != 0) + { + if (isKeyDown) + keysCurrentlyDown.addIfNotAlreadyThere ((void*) keyCode); + else + keysCurrentlyDown.removeValue ((void*) keyCode); + } } const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() throw() { - return ModifierKeys (currentModifiers); + return ModifierKeys (currentModifiers); } void ModifierKeys::updateCurrentModifiers() throw() { - currentModifierFlags = currentModifiers; + currentModifierFlags = currentModifiers; } static int64 getMouseTime (NSEvent* e) { - return (Time::currentTimeMillis() - Time::getMillisecondCounter()) - + (int64) ([e timestamp] * 1000.0); + return (Time::currentTimeMillis() - Time::getMillisecondCounter()) + + (int64) ([e timestamp] * 1000.0); } static void getMousePos (NSEvent* e, NSView* view, int& x, int& y) { - NSPoint p = [view convertPoint: [e locationInWindow] fromView: nil]; - x = roundFloatToInt (p.x); - y = roundFloatToInt ([view frame].size.height - p.y); + NSPoint p = [view convertPoint: [e locationInWindow] fromView: nil]; + x = roundToInt (p.x); + y = roundToInt ([view frame].size.height - p.y); } -static int getModifierForButtonNumber (const int num) +static int getModifierForButtonNumber (const NSInteger num) { - return num == 0 ? ModifierKeys::leftButtonModifier - : (num == 1 ? ModifierKeys::rightButtonModifier - : (num == 2 ? ModifierKeys::middleButtonModifier : 0)); + return num == 0 ? ModifierKeys::leftButtonModifier + : (num == 1 ? ModifierKeys::rightButtonModifier + : (num == 2 ? ModifierKeys::middleButtonModifier : 0)); } NSViewComponentPeer::NSViewComponentPeer (Component* const component_, - const int windowStyleFlags, - NSView* viewToAttachTo) - : ComponentPeer (component_, windowStyleFlags), - window (0), - view (0), - isSharedWindow (viewToAttachTo != 0), - fullScreen (false), - insideDrawRect (false), + const int windowStyleFlags, + NSView* viewToAttachTo) + : ComponentPeer (component_, windowStyleFlags), + window (0), + view (0), + isSharedWindow (viewToAttachTo != 0), + fullScreen (false), + insideDrawRect (false), #if USE_COREGRAPHICS_RENDERING - usingCoreGraphics (true) + usingCoreGraphics (true) #else - usingCoreGraphics (false) + usingCoreGraphics (false) #endif { - NSRect r; - r.origin.x = 0; - r.origin.y = 0; - r.size.width = (float) component->getWidth(); - r.size.height = (float) component->getHeight(); + NSRect r; + r.origin.x = 0; + r.origin.y = 0; + r.size.width = (float) component->getWidth(); + r.size.height = (float) component->getHeight(); - view = [[JuceNSView alloc] initWithOwner: this withFrame: r]; - [view setPostsFrameChangedNotifications: YES]; + view = [[JuceNSView alloc] initWithOwner: this withFrame: r]; + [view setPostsFrameChangedNotifications: YES]; - if (isSharedWindow) - { - window = [viewToAttachTo window]; - [viewToAttachTo addSubview: view]; + if (isSharedWindow) + { + window = [viewToAttachTo window]; + [viewToAttachTo addSubview: view]; - setVisible (component->isVisible()); - } - else - { - r.origin.x = (float) component->getX(); - r.origin.y = (float) component->getY(); - r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - (r.origin.y + r.size.height); + setVisible (component->isVisible()); + } + else + { + r.origin.x = (float) component->getX(); + r.origin.y = (float) component->getY(); + r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - (r.origin.y + r.size.height); - unsigned int style = 0; - if ((windowStyleFlags & windowHasTitleBar) == 0) - style = NSBorderlessWindowMask; - else - style = NSTitledWindowMask; + unsigned int style = 0; + if ((windowStyleFlags & windowHasTitleBar) == 0) + style = NSBorderlessWindowMask; + else + style = NSTitledWindowMask; - if ((windowStyleFlags & windowHasMinimiseButton) != 0) - style |= NSMiniaturizableWindowMask; + if ((windowStyleFlags & windowHasMinimiseButton) != 0) + style |= NSMiniaturizableWindowMask; - if ((windowStyleFlags & windowHasCloseButton) != 0) - style |= NSClosableWindowMask; + if ((windowStyleFlags & windowHasCloseButton) != 0) + style |= NSClosableWindowMask; - if ((windowStyleFlags & windowIsResizable) != 0) - style |= NSResizableWindowMask; + if ((windowStyleFlags & windowIsResizable) != 0) + style |= NSResizableWindowMask; - window = [[JuceNSWindow alloc] initWithContentRect: r - styleMask: style - backing: NSBackingStoreBuffered - defer: YES]; + window = [[JuceNSWindow alloc] initWithContentRect: r + styleMask: style + backing: NSBackingStoreBuffered + defer: YES]; - [((JuceNSWindow*) window) setOwner: this]; - [window orderOut: nil]; - [window setDelegate: (JuceNSWindow*) window]; - [window setOpaque: component->isOpaque()]; - [window setHasShadow: ((windowStyleFlags & windowHasDropShadow) != 0)]; + [((JuceNSWindow*) window) setOwner: this]; + [window orderOut: nil]; + [window setDelegate: (JuceNSWindow*) window]; + [window setOpaque: component->isOpaque()]; + [window setHasShadow: ((windowStyleFlags & windowHasDropShadow) != 0)]; - if (component->isAlwaysOnTop()) - [window setLevel: NSFloatingWindowLevel]; + if (component->isAlwaysOnTop()) + [window setLevel: NSFloatingWindowLevel]; - [window setContentView: view]; - [window setAutodisplay: YES]; - [window setAcceptsMouseMovedEvents: YES]; + [window setContentView: view]; + [window setAutodisplay: YES]; + [window setAcceptsMouseMovedEvents: YES]; - // We'll both retain and also release this on closing because plugin hosts can unexpectedly - // close the window for us, and also tend to get cause trouble if setReleasedWhenClosed is NO. - [window setReleasedWhenClosed: YES]; - [window retain]; + // We'll both retain and also release this on closing because plugin hosts can unexpectedly + // close the window for us, and also tend to get cause trouble if setReleasedWhenClosed is NO. + [window setReleasedWhenClosed: YES]; + [window retain]; - [window setExcludedFromWindowsMenu: (windowStyleFlags & windowIsTemporary) != 0]; - [window setIgnoresMouseEvents: (windowStyleFlags & windowIgnoresMouseClicks) != 0]; - } + [window setExcludedFromWindowsMenu: (windowStyleFlags & windowIsTemporary) != 0]; + [window setIgnoresMouseEvents: (windowStyleFlags & windowIgnoresMouseClicks) != 0]; + } - setTitle (component->getName()); + setTitle (component->getName()); } NSViewComponentPeer::~NSViewComponentPeer() { - view->owner = 0; - [view removeFromSuperview]; - [view release]; + view->owner = 0; + [view removeFromSuperview]; + [view release]; - if (! isSharedWindow) - { - [((JuceNSWindow*) window) setOwner: 0]; - [window close]; - [window release]; - } + if (! isSharedWindow) + { + [((JuceNSWindow*) window) setOwner: 0]; + [window close]; + [window release]; + } } void* NSViewComponentPeer::getNativeHandle() const { - return view; + return view; } void NSViewComponentPeer::setVisible (bool shouldBeVisible) { - if (isSharedWindow) - { - [view setHidden: ! shouldBeVisible]; - } - else - { - if (shouldBeVisible) - [window orderFront: nil]; - else - [window orderOut: nil]; - } + if (isSharedWindow) + { + [view setHidden: ! shouldBeVisible]; + } + else + { + if (shouldBeVisible) + [window orderFront: nil]; + else + [window orderOut: nil]; + } } void NSViewComponentPeer::setTitle (const String& title) { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - if (! isSharedWindow) - [window setTitle: juceStringToNS (title)]; + if (! isSharedWindow) + [window setTitle: juceStringToNS (title)]; } void NSViewComponentPeer::setPosition (int x, int y) { - setBounds (x, y, component->getWidth(), component->getHeight(), false); + setBounds (x, y, component->getWidth(), component->getHeight(), false); } void NSViewComponentPeer::setSize (int w, int h) { - setBounds (component->getX(), component->getY(), w, h, false); + setBounds (component->getX(), component->getY(), w, h, false); } void NSViewComponentPeer::setBounds (int x, int y, int w, int h, const bool isNowFullScreen) { - fullScreen = isNowFullScreen; - w = jmax (0, w); - h = jmax (0, h); + fullScreen = isNowFullScreen; + w = jmax (0, w); + h = jmax (0, h); - NSRect r; - r.origin.x = (float) x; - r.origin.y = (float) y; - r.size.width = (float) w; - r.size.height = (float) h; + NSRect r; + r.origin.x = (float) x; + r.origin.y = (float) y; + r.size.width = (float) w; + r.size.height = (float) h; - if (isSharedWindow) - { - r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height); + if (isSharedWindow) + { + r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height); - if ([view frame].size.width != r.size.width - || [view frame].size.height != r.size.height) - [view setNeedsDisplay: true]; + if ([view frame].size.width != r.size.width + || [view frame].size.height != r.size.height) + [view setNeedsDisplay: true]; - [view setFrame: r]; - } - else - { - r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - (r.origin.y + r.size.height); + [view setFrame: r]; + } + else + { + r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - (r.origin.y + r.size.height); - [window setFrame: [window frameRectForContentRect: r] - display: true]; - } + [window setFrame: [window frameRectForContentRect: r] + display: true]; + } } void NSViewComponentPeer::getBounds (int& x, int& y, int& w, int& h, const bool global) const { - NSRect r = [view frame]; + NSRect r = [view frame]; - if (global && [view window] != 0) - { - r = [view convertRect: r toView: nil]; - NSRect wr = [[view window] frame]; - r.origin.x += wr.origin.x; - r.origin.y += wr.origin.y; + if (global && [view window] != 0) + { + r = [view convertRect: r toView: nil]; + NSRect wr = [[view window] frame]; + r.origin.x += wr.origin.x; + r.origin.y += wr.origin.y; - y = (int) ([[[NSScreen screens] objectAtIndex:0] frame].size.height - r.origin.y - r.size.height); - } - else - { - y = (int) ([[view superview] frame].size.height - r.origin.y - r.size.height); - } + y = (int) ([[[NSScreen screens] objectAtIndex:0] frame].size.height - r.origin.y - r.size.height); + } + else + { + y = (int) ([[view superview] frame].size.height - r.origin.y - r.size.height); + } - x = (int) r.origin.x; - w = (int) r.size.width; - h = (int) r.size.height; + x = (int) r.origin.x; + w = (int) r.size.width; + h = (int) r.size.height; } void NSViewComponentPeer::getBounds (int& x, int& y, int& w, int& h) const { - getBounds (x, y, w, h, ! isSharedWindow); + getBounds (x, y, w, h, ! isSharedWindow); } int NSViewComponentPeer::getScreenX() const { - int x, y, w, h; - getBounds (x, y, w, h, true); - return x; + int x, y, w, h; + getBounds (x, y, w, h, true); + return x; } int NSViewComponentPeer::getScreenY() const { - int x, y, w, h; - getBounds (x, y, w, h, true); - return y; + int x, y, w, h; + getBounds (x, y, w, h, true); + return y; } void NSViewComponentPeer::relativePositionToGlobal (int& x, int& y) { - int wx, wy, ww, wh; - getBounds (wx, wy, ww, wh, true); - x += wx; - y += wy; + int wx, wy, ww, wh; + getBounds (wx, wy, ww, wh, true); + x += wx; + y += wy; } void NSViewComponentPeer::globalPositionToRelative (int& x, int& y) { - int wx, wy, ww, wh; - getBounds (wx, wy, ww, wh, true); - x -= wx; - y -= wy; + int wx, wy, ww, wh; + getBounds (wx, wy, ww, wh, true); + x -= wx; + y -= wy; } NSRect NSViewComponentPeer::constrainRect (NSRect r) { - if (constrainer != 0) - { - NSRect current = [window frame]; - current.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - current.origin.y - current.size.height; + if (constrainer != 0) + { + NSRect current = [window frame]; + current.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - current.origin.y - current.size.height; - r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - r.origin.y - r.size.height; + r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - r.origin.y - r.size.height; - int x = (int) r.origin.x; - int y = (int) r.origin.y; - int w = (int) r.size.width; - int h = (int) r.size.height; + int x = (int) r.origin.x; + int y = (int) r.origin.y; + int w = (int) r.size.width; + int h = (int) r.size.height; - Rectangle original ((int) current.origin.x, (int) current.origin.y, - (int) current.size.width, (int) current.size.height); + Rectangle original ((int) current.origin.x, (int) current.origin.y, + (int) current.size.width, (int) current.size.height); - constrainer->checkBounds (x, y, w, h, - original, - Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), - y != original.getY() && y + h == original.getBottom(), - x != original.getX() && x + w == original.getRight(), - y == original.getY() && y + h != original.getBottom(), - x == original.getX() && x + w != original.getRight()); + constrainer->checkBounds (x, y, w, h, + original, + Desktop::getInstance().getAllMonitorDisplayAreas().getBounds(), + y != original.getY() && y + h == original.getBottom(), + x != original.getX() && x + w == original.getRight(), + y == original.getY() && y + h != original.getBottom(), + x == original.getX() && x + w != original.getRight()); - r.origin.x = x; - r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - r.size.height - y; - r.size.width = w; - r.size.height = h; - } + r.origin.x = x; + r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - r.size.height - y; + r.size.width = w; + r.size.height = h; + } - return r; + return r; } void NSViewComponentPeer::setMinimised (bool shouldBeMinimised) { - if (! isSharedWindow) - { - if (shouldBeMinimised) - [window miniaturize: nil]; - else - [window deminiaturize: nil]; - } + if (! isSharedWindow) + { + if (shouldBeMinimised) + [window miniaturize: nil]; + else + [window deminiaturize: nil]; + } } bool NSViewComponentPeer::isMinimised() const { - return window != 0 && [window isMiniaturized]; + return window != 0 && [window isMiniaturized]; } void NSViewComponentPeer::setFullScreen (bool shouldBeFullScreen) { - if (! isSharedWindow) - { - Rectangle r (lastNonFullscreenBounds); + if (! isSharedWindow) + { + Rectangle r (lastNonFullscreenBounds); - setMinimised (false); + setMinimised (false); - if (fullScreen != shouldBeFullScreen) - { - if (shouldBeFullScreen && (getStyleFlags() & windowHasTitleBar) != 0) - { - fullScreen = true; - [window performZoom: nil]; - } - else - { - if (shouldBeFullScreen) - r = Desktop::getInstance().getMainMonitorArea(); + if (fullScreen != shouldBeFullScreen) + { + if (shouldBeFullScreen && (getStyleFlags() & windowHasTitleBar) != 0) + { + fullScreen = true; + [window performZoom: nil]; + } + else + { + if (shouldBeFullScreen) + r = Desktop::getInstance().getMainMonitorArea(); - // (can't call the component's setBounds method because that'll reset our fullscreen flag) - if (r != getComponent()->getBounds() && ! r.isEmpty()) - setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen); - } - } - } + // (can't call the component's setBounds method because that'll reset our fullscreen flag) + if (r != getComponent()->getBounds() && ! r.isEmpty()) + setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen); + } + } + } } bool NSViewComponentPeer::isFullScreen() const { - return fullScreen; + return fullScreen; } bool NSViewComponentPeer::contains (int x, int y, bool trueIfInAChildWindow) const { - if (((unsigned int) x) >= (unsigned int) component->getWidth() - || ((unsigned int) y) >= (unsigned int) component->getHeight()) - return false; + if (((unsigned int) x) >= (unsigned int) component->getWidth() + || ((unsigned int) y) >= (unsigned int) component->getHeight()) + return false; - NSPoint p; - p.x = (float) x; - p.y = (float) y; + NSPoint p; + p.x = (float) x; + p.y = (float) y; - NSView* v = [view hitTest: p]; + NSView* v = [view hitTest: p]; - if (trueIfInAChildWindow) - return v != nil; + if (trueIfInAChildWindow) + return v != nil; - return v == view; + return v == view; } const BorderSize NSViewComponentPeer::getFrameSize() const { - BorderSize b; + BorderSize b; - if (! isSharedWindow) - { - NSRect v = [view convertRect: [view frame] toView: nil]; - NSRect w = [window frame]; + if (! isSharedWindow) + { + NSRect v = [view convertRect: [view frame] toView: nil]; + NSRect w = [window frame]; - b.setTop ((int) (w.size.height - (v.origin.y + v.size.height))); - b.setBottom ((int) v.origin.y); - b.setLeft ((int) v.origin.x); - b.setRight ((int) (w.size.width - (v.origin.x + v.size.width))); - } + b.setTop ((int) (w.size.height - (v.origin.y + v.size.height))); + b.setBottom ((int) v.origin.y); + b.setLeft ((int) v.origin.x); + b.setRight ((int) (w.size.width - (v.origin.x + v.size.width))); + } - return b; + return b; } bool NSViewComponentPeer::setAlwaysOnTop (bool alwaysOnTop) { - if (! isSharedWindow) - { - [window setLevel: alwaysOnTop ? NSFloatingWindowLevel - : NSNormalWindowLevel]; - } + if (! isSharedWindow) + { + [window setLevel: alwaysOnTop ? NSFloatingWindowLevel + : NSNormalWindowLevel]; + } - return true; + return true; } void NSViewComponentPeer::toFront (bool makeActiveWindow) { - if (isSharedWindow) - { - [[view superview] addSubview: view - positioned: NSWindowAbove - relativeTo: nil]; - } + if (isSharedWindow) + { + [[view superview] addSubview: view + positioned: NSWindowAbove + relativeTo: nil]; + } - if (window != 0 && component->isVisible()) - { - if (makeActiveWindow) - [window makeKeyAndOrderFront: nil]; - else - [window orderFront: nil]; - } + if (window != 0 && component->isVisible()) + { + if (makeActiveWindow) + [window makeKeyAndOrderFront: nil]; + else + [window orderFront: nil]; + } } void NSViewComponentPeer::toBehind (ComponentPeer* other) { - NSViewComponentPeer* o = (NSViewComponentPeer*) other; + NSViewComponentPeer* o = (NSViewComponentPeer*) other; - if (isSharedWindow) - { - [[view superview] addSubview: view - positioned: NSWindowBelow - relativeTo: o->view]; - } - else - { - [window orderWindow: NSWindowBelow - relativeTo: o->window != 0 ? [o->window windowNumber] - : nil ]; - } + if (isSharedWindow) + { + [[view superview] addSubview: view + positioned: NSWindowBelow + relativeTo: o->view]; + } + else + { + [window orderWindow: NSWindowBelow + relativeTo: o->window != 0 ? [o->window windowNumber] + : nil ]; + } } void NSViewComponentPeer::setIcon (const Image& /*newIcon*/) { - // to do.. + // to do.. } void NSViewComponentPeer::viewFocusGain() { - if (currentlyFocusedPeer != this) - { - if (ComponentPeer::isValidPeer (currentlyFocusedPeer)) - currentlyFocusedPeer->handleFocusLoss(); + if (currentlyFocusedPeer != this) + { + if (ComponentPeer::isValidPeer (currentlyFocusedPeer)) + currentlyFocusedPeer->handleFocusLoss(); - currentlyFocusedPeer = this; + currentlyFocusedPeer = this; - handleFocusGain(); - } + handleFocusGain(); + } } void NSViewComponentPeer::viewFocusLoss() { - if (currentlyFocusedPeer == this) - { - currentlyFocusedPeer = 0; - handleFocusLoss(); - } + if (currentlyFocusedPeer == this) + { + currentlyFocusedPeer = 0; + handleFocusLoss(); + } } void juce_HandleProcessFocusChange() { - keysCurrentlyDown.clear(); + keysCurrentlyDown.clear(); - if (NSViewComponentPeer::isValidPeer (currentlyFocusedPeer)) - { - if (Process::isForegroundProcess()) - { - currentlyFocusedPeer->handleFocusGain(); + if (NSViewComponentPeer::isValidPeer (currentlyFocusedPeer)) + { + if (Process::isForegroundProcess()) + { + currentlyFocusedPeer->handleFocusGain(); - ComponentPeer::bringModalComponentToFront(); - } - else - { - currentlyFocusedPeer->handleFocusLoss(); + ComponentPeer::bringModalComponentToFront(); + } + else + { + currentlyFocusedPeer->handleFocusLoss(); - // turn kiosk mode off if we lose focus.. - Desktop::getInstance().setKioskModeComponent (0); - } - } + // turn kiosk mode off if we lose focus.. + Desktop::getInstance().setKioskModeComponent (0); + } + } } bool NSViewComponentPeer::isFocused() const { - return isSharedWindow ? this == currentlyFocusedPeer - : (window != 0 && [window isKeyWindow]); + return isSharedWindow ? this == currentlyFocusedPeer + : (window != 0 && [window isKeyWindow]); } void NSViewComponentPeer::grabFocus() { - if (window != 0) - { - [window makeKeyWindow]; - [window makeFirstResponder: view]; + if (window != 0) + { + [window makeKeyWindow]; + [window makeFirstResponder: view]; - viewFocusGain(); - } + viewFocusGain(); + } } void NSViewComponentPeer::textInputRequired (int /*x*/, int /*y*/) @@ -268584,459 +246144,459 @@ void NSViewComponentPeer::textInputRequired (int /*x*/, int /*y*/) bool NSViewComponentPeer::handleKeyEvent (NSEvent* ev, bool isKeyDown) { - String unicode (nsStringToJuce ([ev characters])); - String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers])); - int keyCode = getKeyCodeFromEvent (ev); + String unicode (nsStringToJuce ([ev characters])); + String unmodified (nsStringToJuce ([ev charactersIgnoringModifiers])); + int keyCode = getKeyCodeFromEvent (ev); - //DBG ("unicode: " + unicode + " " + String::toHexString ((int) unicode[0])); - //DBG ("unmodified: " + unmodified + " " + String::toHexString ((int) unmodified[0])); + //DBG ("unicode: " + unicode + " " + String::toHexString ((int) unicode[0])); + //DBG ("unmodified: " + unmodified + " " + String::toHexString ((int) unmodified[0])); - if (unicode.isNotEmpty() || keyCode != 0) - { - if (isKeyDown) - { - bool used = false; + if (unicode.isNotEmpty() || keyCode != 0) + { + if (isKeyDown) + { + bool used = false; - while (unicode.length() > 0) - { - juce_wchar textCharacter = unicode[0]; - unicode = unicode.substring (1); + while (unicode.length() > 0) + { + juce_wchar textCharacter = unicode[0]; + unicode = unicode.substring (1); - if (([ev modifierFlags] & NSCommandKeyMask) != 0) - textCharacter = 0; + if (([ev modifierFlags] & NSCommandKeyMask) != 0) + textCharacter = 0; - used = handleKeyUpOrDown (true) || used; - used = handleKeyPress (keyCode, textCharacter) || used; - } + used = handleKeyUpOrDown (true) || used; + used = handleKeyPress (keyCode, textCharacter) || used; + } - return used; - } - else - { - if (handleKeyUpOrDown (false)) - return true; - } - } + return used; + } + else + { + if (handleKeyUpOrDown (false)) + return true; + } + } - return false; + return false; } bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev) { - updateKeysDown (ev, true); - bool used = handleKeyEvent (ev, true); + updateKeysDown (ev, true); + bool used = handleKeyEvent (ev, true); - if (([ev modifierFlags] & NSCommandKeyMask) != 0) - { - // for command keys, the key-up event is thrown away, so simulate one.. - updateKeysDown (ev, false); - used = (isValidPeer (this) && handleKeyEvent (ev, false)) || used; - } + if (([ev modifierFlags] & NSCommandKeyMask) != 0) + { + // for command keys, the key-up event is thrown away, so simulate one.. + updateKeysDown (ev, false); + used = (isValidPeer (this) && handleKeyEvent (ev, false)) || used; + } - // (If we're running modally, don't allow unused keystrokes to be passed - // along to other blocked views..) - if (Component::getCurrentlyModalComponent() != 0) - used = true; + // (If we're running modally, don't allow unused keystrokes to be passed + // along to other blocked views..) + if (Component::getCurrentlyModalComponent() != 0) + used = true; - return used; + return used; } bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev) { - updateKeysDown (ev, false); - return handleKeyEvent (ev, false) - || Component::getCurrentlyModalComponent() != 0; + updateKeysDown (ev, false); + return handleKeyEvent (ev, false) + || Component::getCurrentlyModalComponent() != 0; } void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev) { - updateModifiers (ev); - handleModifierKeysChange(); + updateModifiers (ev); + handleModifierKeysChange(); } #if MACOS_10_4_OR_EARLIER bool NSViewComponentPeer::redirectPerformKeyEquivalent (NSEvent* ev) { - if ([ev type] == NSKeyDown) - return redirectKeyDown (ev); - else if ([ev type] == NSKeyUp) - return redirectKeyUp (ev); + if ([ev type] == NSKeyDown) + return redirectKeyDown (ev); + else if ([ev type] == NSKeyUp) + return redirectKeyUp (ev); - return false; + return false; } #endif void NSViewComponentPeer::redirectMouseDown (NSEvent* ev) { - updateModifiers (ev); - currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]); - int x, y; - getMousePos (ev, view, x, y); + updateModifiers (ev); + currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]); + int x, y; + getMousePos (ev, view, x, y); - handleMouseDown (x, y, getMouseTime (ev)); + handleMouseDown (x, y, getMouseTime (ev)); } void NSViewComponentPeer::redirectMouseUp (NSEvent* ev) { - const int oldMods = currentModifiers; - updateModifiers (ev); - currentModifiers &= ~getModifierForButtonNumber ([ev buttonNumber]); - int x, y; - getMousePos (ev, view, x, y); + const int oldMods = currentModifiers; + updateModifiers (ev); + currentModifiers &= ~getModifierForButtonNumber ([ev buttonNumber]); + int x, y; + getMousePos (ev, view, x, y); - handleMouseUp (oldMods, x, y, getMouseTime (ev)); - showArrowCursorIfNeeded(); + handleMouseUp (oldMods, x, y, getMouseTime (ev)); + showArrowCursorIfNeeded(); } void NSViewComponentPeer::redirectMouseDrag (NSEvent* ev) { - updateModifiers (ev); - currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]); - int x, y; - getMousePos (ev, view, x, y); + updateModifiers (ev); + currentModifiers |= getModifierForButtonNumber ([ev buttonNumber]); + int x, y; + getMousePos (ev, view, x, y); - handleMouseDrag (x, y, getMouseTime (ev)); + handleMouseDrag (x, y, getMouseTime (ev)); } void NSViewComponentPeer::redirectMouseMove (NSEvent* ev) { - updateModifiers (ev); - int x, y; - getMousePos (ev, view, x, y); + updateModifiers (ev); + int x, y; + getMousePos (ev, view, x, y); - handleMouseMove (x, y, getMouseTime (ev)); - showArrowCursorIfNeeded(); + handleMouseMove (x, y, getMouseTime (ev)); + showArrowCursorIfNeeded(); } void NSViewComponentPeer::redirectMouseEnter (NSEvent* ev) { - updateModifiers (ev); - int x, y; - getMousePos (ev, view, x, y); + updateModifiers (ev); + int x, y; + getMousePos (ev, view, x, y); - handleMouseEnter (x, y, getMouseTime (ev)); + handleMouseEnter (x, y, getMouseTime (ev)); } void NSViewComponentPeer::redirectMouseExit (NSEvent* ev) { - updateModifiers (ev); - int x, y; - getMousePos (ev, view, x, y); + updateModifiers (ev); + int x, y; + getMousePos (ev, view, x, y); - handleMouseExit (x, y, getMouseTime (ev)); + handleMouseExit (x, y, getMouseTime (ev)); } void NSViewComponentPeer::redirectMouseWheel (NSEvent* ev) { - updateModifiers (ev); + updateModifiers (ev); - handleMouseWheel (roundFloatToInt ([ev deltaX] * 10.0f), - roundFloatToInt ([ev deltaY] * 10.0f), - getMouseTime (ev)); + handleMouseWheel (roundToInt ([ev deltaX] * 10.0f), + roundToInt ([ev deltaY] * 10.0f), + getMouseTime (ev)); } void NSViewComponentPeer::showArrowCursorIfNeeded() { - if (Component::getComponentUnderMouse() == 0) - { - int mx, my; - Desktop::getInstance().getMousePosition (mx, my); + if (Component::getComponentUnderMouse() == 0) + { + int mx, my; + Desktop::getInstance().getMousePosition (mx, my); - if (Desktop::getInstance().findComponentAt (mx, my) == 0) - [[NSCursor arrowCursor] set]; - } + if (Desktop::getInstance().findComponentAt (mx, my) == 0) + [[NSCursor arrowCursor] set]; + } } BOOL NSViewComponentPeer::sendDragCallback (int type, id sender) { - NSString* bestType - = [[sender draggingPasteboard] availableTypeFromArray: [view getSupportedDragTypes]]; + NSString* bestType + = [[sender draggingPasteboard] availableTypeFromArray: [view getSupportedDragTypes]]; - if (bestType == nil) - return false; + if (bestType == nil) + return false; - NSPoint p = [view convertPoint: [sender draggingLocation] fromView: nil]; - int x = (int) p.x; - int y = (int) ([view frame].size.height - p.y); + NSPoint p = [view convertPoint: [sender draggingLocation] fromView: nil]; + int x = (int) p.x; + int y = (int) ([view frame].size.height - p.y); - StringArray files; + StringArray files; - id list = [[sender draggingPasteboard] propertyListForType: bestType]; - if (list == nil) - return false; + id list = [[sender draggingPasteboard] propertyListForType: bestType]; + if (list == nil) + return false; - if ([list isKindOfClass: [NSArray class]]) - { - NSArray* items = (NSArray*) list; + if ([list isKindOfClass: [NSArray class]]) + { + NSArray* items = (NSArray*) list; - for (unsigned int i = 0; i < [items count]; ++i) - files.add (nsStringToJuce ((NSString*) [items objectAtIndex: i])); - } + for (unsigned int i = 0; i < [items count]; ++i) + files.add (nsStringToJuce ((NSString*) [items objectAtIndex: i])); + } - if (files.size() == 0) - return false; + if (files.size() == 0) + return false; - if (type == 0) - handleFileDragMove (files, x, y); - else if (type == 1) - handleFileDragExit (files); - else if (type == 2) - handleFileDragDrop (files, x, y); + if (type == 0) + handleFileDragMove (files, x, y); + else if (type == 1) + handleFileDragExit (files); + else if (type == 2) + handleFileDragDrop (files, x, y); - return true; + return true; } bool NSViewComponentPeer::isOpaque() { - if (! getComponent()->isValidComponent()) - return true; + if (! getComponent()->isValidComponent()) + return true; - return getComponent()->isOpaque(); + return getComponent()->isOpaque(); } void NSViewComponentPeer::drawRect (NSRect r) { - if (r.size.width < 1.0f || r.size.height < 1.0f) - return; + if (r.size.width < 1.0f || r.size.height < 1.0f) + return; - CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; + CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; - if (! component->isOpaque()) - CGContextClearRect (cg, CGContextGetClipBoundingBox (cg)); + if (! component->isOpaque()) + CGContextClearRect (cg, CGContextGetClipBoundingBox (cg)); #if USE_COREGRAPHICS_RENDERING - if (usingCoreGraphics) - { - CoreGraphicsContext context (cg, [view frame].size.height); + if (usingCoreGraphics) + { + CoreGraphicsContext context (cg, (float) [view frame].size.height); - insideDrawRect = true; - handlePaint (context); - insideDrawRect = false; - } - else + insideDrawRect = true; + handlePaint (context); + insideDrawRect = false; + } + else #endif - { - Image temp (getComponent()->isOpaque() ? Image::RGB : Image::ARGB, - (int) (r.size.width + 0.5f), - (int) (r.size.height + 0.5f), - ! getComponent()->isOpaque()); + { + Image temp (getComponent()->isOpaque() ? Image::RGB : Image::ARGB, + (int) (r.size.width + 0.5f), + (int) (r.size.height + 0.5f), + ! getComponent()->isOpaque()); - LowLevelGraphicsSoftwareRenderer context (temp); - context.setOrigin (-roundFloatToInt (r.origin.x), - -roundFloatToInt ([view frame].size.height - (r.origin.y + r.size.height))); + LowLevelGraphicsSoftwareRenderer context (temp); + context.setOrigin (-roundToInt (r.origin.x), + -roundToInt ([view frame].size.height - (r.origin.y + r.size.height))); - const NSRect* rects = 0; - NSInteger numRects = 0; - [view getRectsBeingDrawn: &rects count: &numRects]; + const NSRect* rects = 0; + NSInteger numRects = 0; + [view getRectsBeingDrawn: &rects count: &numRects]; - RectangleList clip; - for (int i = 0; i < numRects; ++i) - { - clip.addWithoutMerging (Rectangle (roundFloatToInt (rects[i].origin.x), - roundFloatToInt ([view frame].size.height - (rects[i].origin.y + rects[i].size.height)), - roundFloatToInt (rects[i].size.width), - roundFloatToInt (rects[i].size.height))); - } + RectangleList clip; + for (int i = 0; i < numRects; ++i) + { + clip.addWithoutMerging (Rectangle (roundToInt (rects[i].origin.x), + roundToInt ([view frame].size.height - (rects[i].origin.y + rects[i].size.height)), + roundToInt (rects[i].size.width), + roundToInt (rects[i].size.height))); + } - if (context.clipToRectangleList (clip)) - { - insideDrawRect = true; - handlePaint (context); - insideDrawRect = false; + if (context.clipToRectangleList (clip)) + { + insideDrawRect = true; + handlePaint (context); + insideDrawRect = false; - CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); - CGImageRef image = CoreGraphicsImage::createImage (temp, false, colourSpace); - CGColorSpaceRelease (colourSpace); - CGContextDrawImage (cg, CGRectMake (r.origin.x, r.origin.y, temp.getWidth(), temp.getHeight()), image); - CGImageRelease (image); - } - } + CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); + CGImageRef image = CoreGraphicsImage::createImage (temp, false, colourSpace); + CGColorSpaceRelease (colourSpace); + CGContextDrawImage (cg, CGRectMake (r.origin.x, r.origin.y, temp.getWidth(), temp.getHeight()), image); + CGImageRelease (image); + } + } } const StringArray NSViewComponentPeer::getAvailableRenderingEngines() throw() { - StringArray s; - s.add ("Software Renderer"); + StringArray s; + s.add ("Software Renderer"); #if USE_COREGRAPHICS_RENDERING - s.add ("CoreGraphics Renderer"); + s.add ("CoreGraphics Renderer"); #endif - return s; + return s; } int NSViewComponentPeer::getCurrentRenderingEngine() throw() { - return usingCoreGraphics ? 1 : 0; + return usingCoreGraphics ? 1 : 0; } void NSViewComponentPeer::setCurrentRenderingEngine (int index) throw() { #if USE_COREGRAPHICS_RENDERING - if (usingCoreGraphics != (index > 0)) - { - usingCoreGraphics = index > 0; - [view setNeedsDisplay: true]; - } + if (usingCoreGraphics != (index > 0)) + { + usingCoreGraphics = index > 0; + [view setNeedsDisplay: true]; + } #endif } bool NSViewComponentPeer::canBecomeKeyWindow() { - return (getStyleFlags() & JUCE_NAMESPACE::ComponentPeer::windowIgnoresKeyPresses) == 0; + return (getStyleFlags() & JUCE_NAMESPACE::ComponentPeer::windowIgnoresKeyPresses) == 0; } bool NSViewComponentPeer::windowShouldClose() { - if (! isValidPeer (this)) - return YES; + if (! isValidPeer (this)) + return YES; - handleUserClosingWindow(); - return NO; + handleUserClosingWindow(); + return NO; } void NSViewComponentPeer::redirectMovedOrResized() { - handleMovedOrResized(); + handleMovedOrResized(); } void NSViewComponentPeer::viewMovedToWindow() { - if (isSharedWindow) - window = [view window]; + if (isSharedWindow) + window = [view window]; } void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool allowMenusAndBars) { - // Very annoyingly, this function has to use the old SetSystemUIMode function, - // which is in Carbon.framework. But, because there's no Cocoa equivalent, it - // is apparently still available in 64-bit apps.. - if (enableOrDisable) - { - SetSystemUIMode (kUIModeAllSuppressed, allowMenusAndBars ? kUIOptionAutoShowMenuBar : 0); - kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); - } - else - { - SetSystemUIMode (kUIModeNormal, 0); - } + // Very annoyingly, this function has to use the old SetSystemUIMode function, + // which is in Carbon.framework. But, because there's no Cocoa equivalent, it + // is apparently still available in 64-bit apps.. + if (enableOrDisable) + { + SetSystemUIMode (kUIModeAllSuppressed, allowMenusAndBars ? kUIOptionAutoShowMenuBar : 0); + kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); + } + else + { + SetSystemUIMode (kUIModeNormal, 0); + } } class AsyncRepaintMessage : public CallbackMessage { public: - NSViewComponentPeer* const peer; - const Rectangle rect; + NSViewComponentPeer* const peer; + const Rectangle rect; - AsyncRepaintMessage (NSViewComponentPeer* const peer_, const Rectangle& rect_) - : peer (peer_), rect (rect_) - { - } + AsyncRepaintMessage (NSViewComponentPeer* const peer_, const Rectangle& rect_) + : peer (peer_), rect (rect_) + { + } - void messageCallback() - { - if (ComponentPeer::isValidPeer (peer)) - peer->repaint (rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); - } + void messageCallback() + { + if (ComponentPeer::isValidPeer (peer)) + peer->repaint (rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight()); + } }; void NSViewComponentPeer::repaint (int x, int y, int w, int h) { - if (insideDrawRect) - { - (new AsyncRepaintMessage (this, Rectangle (x, y, w, h)))->post(); - } - else - { - [view setNeedsDisplayInRect: NSMakeRect ((float) x, (float) ([view frame].size.height - (y + h)), - (float) w, (float) h)]; - } + if (insideDrawRect) + { + (new AsyncRepaintMessage (this, Rectangle (x, y, w, h)))->post(); + } + else + { + [view setNeedsDisplayInRect: NSMakeRect ((float) x, (float) ([view frame].size.height - (y + h)), + (float) w, (float) h)]; + } } void NSViewComponentPeer::performAnyPendingRepaintsNow() { - [view displayIfNeeded]; + [view displayIfNeeded]; } ComponentPeer* Component::createNewPeer (int styleFlags, void* windowToAttachTo) { - return new NSViewComponentPeer (this, styleFlags, (NSView*) windowToAttachTo); + return new NSViewComponentPeer (this, styleFlags, (NSView*) windowToAttachTo); } Image* juce_createIconForFile (const File& file) { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (file.getFullPathName())]; + NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (file.getFullPathName())]; - CoreGraphicsImage* result = new CoreGraphicsImage (Image::ARGB, (int) [image size].width, (int) [image size].height, true); + CoreGraphicsImage* result = new CoreGraphicsImage (Image::ARGB, (int) [image size].width, (int) [image size].height, true); - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithGraphicsPort: result->context flipped: false]]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithGraphicsPort: result->context flipped: false]]; - [image drawAtPoint: NSMakePoint (0, 0) - fromRect: NSMakeRect (0, 0, [image size].width, [image size].height) - operation: NSCompositeSourceOver fraction: 1.0f]; + [image drawAtPoint: NSMakePoint (0, 0) + fromRect: NSMakeRect (0, 0, [image size].width, [image size].height) + operation: NSCompositeSourceOver fraction: 1.0f]; - [[NSGraphicsContext currentContext] flushGraphics]; - [NSGraphicsContext restoreGraphicsState]; + [[NSGraphicsContext currentContext] flushGraphics]; + [NSGraphicsContext restoreGraphicsState]; - return result; + return result; } -const int KeyPress::spaceKey = ' '; -const int KeyPress::returnKey = 0x0d; -const int KeyPress::escapeKey = 0x1b; -const int KeyPress::backspaceKey = 0x7f; -const int KeyPress::leftKey = NSLeftArrowFunctionKey; -const int KeyPress::rightKey = NSRightArrowFunctionKey; -const int KeyPress::upKey = NSUpArrowFunctionKey; -const int KeyPress::downKey = NSDownArrowFunctionKey; -const int KeyPress::pageUpKey = NSPageUpFunctionKey; -const int KeyPress::pageDownKey = NSPageDownFunctionKey; -const int KeyPress::endKey = NSEndFunctionKey; -const int KeyPress::homeKey = NSHomeFunctionKey; -const int KeyPress::deleteKey = NSDeleteFunctionKey; -const int KeyPress::insertKey = -1; -const int KeyPress::tabKey = 9; -const int KeyPress::F1Key = NSF1FunctionKey; -const int KeyPress::F2Key = NSF2FunctionKey; -const int KeyPress::F3Key = NSF3FunctionKey; -const int KeyPress::F4Key = NSF4FunctionKey; -const int KeyPress::F5Key = NSF5FunctionKey; -const int KeyPress::F6Key = NSF6FunctionKey; -const int KeyPress::F7Key = NSF7FunctionKey; -const int KeyPress::F8Key = NSF8FunctionKey; -const int KeyPress::F9Key = NSF9FunctionKey; -const int KeyPress::F10Key = NSF10FunctionKey; -const int KeyPress::F11Key = NSF1FunctionKey; -const int KeyPress::F12Key = NSF12FunctionKey; -const int KeyPress::F13Key = NSF13FunctionKey; -const int KeyPress::F14Key = NSF14FunctionKey; -const int KeyPress::F15Key = NSF15FunctionKey; -const int KeyPress::F16Key = NSF16FunctionKey; -const int KeyPress::numberPad0 = 0x30020; -const int KeyPress::numberPad1 = 0x30021; -const int KeyPress::numberPad2 = 0x30022; -const int KeyPress::numberPad3 = 0x30023; -const int KeyPress::numberPad4 = 0x30024; -const int KeyPress::numberPad5 = 0x30025; -const int KeyPress::numberPad6 = 0x30026; -const int KeyPress::numberPad7 = 0x30027; -const int KeyPress::numberPad8 = 0x30028; -const int KeyPress::numberPad9 = 0x30029; -const int KeyPress::numberPadAdd = 0x3002a; -const int KeyPress::numberPadSubtract = 0x3002b; -const int KeyPress::numberPadMultiply = 0x3002c; -const int KeyPress::numberPadDivide = 0x3002d; -const int KeyPress::numberPadSeparator = 0x3002e; +const int KeyPress::spaceKey = ' '; +const int KeyPress::returnKey = 0x0d; +const int KeyPress::escapeKey = 0x1b; +const int KeyPress::backspaceKey = 0x7f; +const int KeyPress::leftKey = NSLeftArrowFunctionKey; +const int KeyPress::rightKey = NSRightArrowFunctionKey; +const int KeyPress::upKey = NSUpArrowFunctionKey; +const int KeyPress::downKey = NSDownArrowFunctionKey; +const int KeyPress::pageUpKey = NSPageUpFunctionKey; +const int KeyPress::pageDownKey = NSPageDownFunctionKey; +const int KeyPress::endKey = NSEndFunctionKey; +const int KeyPress::homeKey = NSHomeFunctionKey; +const int KeyPress::deleteKey = NSDeleteFunctionKey; +const int KeyPress::insertKey = -1; +const int KeyPress::tabKey = 9; +const int KeyPress::F1Key = NSF1FunctionKey; +const int KeyPress::F2Key = NSF2FunctionKey; +const int KeyPress::F3Key = NSF3FunctionKey; +const int KeyPress::F4Key = NSF4FunctionKey; +const int KeyPress::F5Key = NSF5FunctionKey; +const int KeyPress::F6Key = NSF6FunctionKey; +const int KeyPress::F7Key = NSF7FunctionKey; +const int KeyPress::F8Key = NSF8FunctionKey; +const int KeyPress::F9Key = NSF9FunctionKey; +const int KeyPress::F10Key = NSF10FunctionKey; +const int KeyPress::F11Key = NSF1FunctionKey; +const int KeyPress::F12Key = NSF12FunctionKey; +const int KeyPress::F13Key = NSF13FunctionKey; +const int KeyPress::F14Key = NSF14FunctionKey; +const int KeyPress::F15Key = NSF15FunctionKey; +const int KeyPress::F16Key = NSF16FunctionKey; +const int KeyPress::numberPad0 = 0x30020; +const int KeyPress::numberPad1 = 0x30021; +const int KeyPress::numberPad2 = 0x30022; +const int KeyPress::numberPad3 = 0x30023; +const int KeyPress::numberPad4 = 0x30024; +const int KeyPress::numberPad5 = 0x30025; +const int KeyPress::numberPad6 = 0x30026; +const int KeyPress::numberPad7 = 0x30027; +const int KeyPress::numberPad8 = 0x30028; +const int KeyPress::numberPad9 = 0x30029; +const int KeyPress::numberPadAdd = 0x3002a; +const int KeyPress::numberPadSubtract = 0x3002b; +const int KeyPress::numberPadMultiply = 0x3002c; +const int KeyPress::numberPadDivide = 0x3002d; +const int KeyPress::numberPadSeparator = 0x3002e; const int KeyPress::numberPadDecimalPoint = 0x3002f; -const int KeyPress::numberPadEquals = 0x30030; -const int KeyPress::numberPadDelete = 0x30031; -const int KeyPress::playKey = 0x30000; -const int KeyPress::stopKey = 0x30001; +const int KeyPress::numberPadEquals = 0x30030; +const int KeyPress::numberPadDelete = 0x30031; +const int KeyPress::playKey = 0x30000; +const int KeyPress::stopKey = 0x30001; const int KeyPress::fastForwardKey = 0x30002; -const int KeyPress::rewindKey = 0x30003; +const int KeyPress::rewindKey = 0x30003; #endif /********* End of inlined file: juce_mac_NSViewComponentPeer.mm *********/ @@ -269050,136 +246610,136 @@ const int KeyPress::rewindKey = 0x30003; void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) throw() { - NSImage* im = CoreGraphicsImage::createNSImage (image); - NSCursor* c = [[NSCursor alloc] initWithImage: im - hotSpot: NSMakePoint (hotspotX, hotspotY)]; - [im release]; + NSImage* im = CoreGraphicsImage::createNSImage (image); + NSCursor* c = [[NSCursor alloc] initWithImage: im + hotSpot: NSMakePoint (hotspotX, hotspotY)]; + [im release]; - return (void*) c; + return (void*) c; } -static void* juce_cursorFromData (const unsigned char* data, const int size, float hx, float hy) throw() +static void* juce_cursorFromData (const unsigned char* data, const size_t size, float hx, float hy) throw() { - ScopedPointer im (ImageFileFormat::loadFrom ((const char*) data, size)); - jassert (im != 0); + ScopedPointer im (ImageFileFormat::loadFrom ((const char*) data, (int) size)); + jassert (im != 0); - if (im == 0) - return 0; + if (im == 0) + return 0; - return juce_createMouseCursorFromImage (*im, - (int) (hx * im->getWidth()), - (int) (hy * im->getHeight())); + return juce_createMouseCursorFromImage (*im, + (int) (hx * im->getWidth()), + (int) (hy * im->getHeight())); } static void* juce_cursorFromWebKitFile (const char* filename, float hx, float hy) { - File f ("/System/Library/Frameworks/WebKit.framework/Frameworks/WebCore.framework/Resources"); + File f ("/System/Library/Frameworks/WebKit.framework/Frameworks/WebCore.framework/Resources"); - MemoryBlock mb; - if (f.getChildFile (filename).loadFileAsData (mb)) - return juce_cursorFromData ((const unsigned char*) mb.getData(), mb.getSize(), hx, hy); + MemoryBlock mb; + if (f.getChildFile (filename).loadFileAsData (mb)) + return juce_cursorFromData ((const unsigned char*) mb.getData(), mb.getSize(), hx, hy); - return 0; + return 0; } void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type) throw() { - const ScopedAutoReleasePool pool; - NSCursor* c = 0; + const ScopedAutoReleasePool pool; + NSCursor* c = 0; - switch (type) - { - case MouseCursor::NormalCursor: - c = [NSCursor arrowCursor]; - break; + switch (type) + { + case MouseCursor::NormalCursor: + c = [NSCursor arrowCursor]; + break; - case MouseCursor::NoCursor: - { - Image blank (Image::ARGB, 8, 8, true); - return juce_createMouseCursorFromImage (blank, 0, 0); - } + case MouseCursor::NoCursor: + { + Image blank (Image::ARGB, 8, 8, true); + return juce_createMouseCursorFromImage (blank, 0, 0); + } - case MouseCursor::DraggingHandCursor: - c = [NSCursor openHandCursor]; - break; + case MouseCursor::DraggingHandCursor: + c = [NSCursor openHandCursor]; + break; - case MouseCursor::CopyingCursor: - return juce_cursorFromWebKitFile ("copyCursor.png", 0, 0); + case MouseCursor::CopyingCursor: + return juce_cursorFromWebKitFile ("copyCursor.png", 0, 0); - case MouseCursor::WaitCursor: - c = [NSCursor arrowCursor]; // avoid this on the mac, let the OS provide the beachball - break; - //return juce_cursorFromWebKitFile ("waitCursor.png", 0.5f, 0.5f); + case MouseCursor::WaitCursor: + c = [NSCursor arrowCursor]; // avoid this on the mac, let the OS provide the beachball + break; + //return juce_cursorFromWebKitFile ("waitCursor.png", 0.5f, 0.5f); - case MouseCursor::IBeamCursor: - c = [NSCursor IBeamCursor]; - break; + case MouseCursor::IBeamCursor: + c = [NSCursor IBeamCursor]; + break; - case MouseCursor::PointingHandCursor: - c = [NSCursor pointingHandCursor]; - break; + case MouseCursor::PointingHandCursor: + c = [NSCursor pointingHandCursor]; + break; - case MouseCursor::LeftRightResizeCursor: - c = [NSCursor resizeLeftRightCursor]; - break; + case MouseCursor::LeftRightResizeCursor: + c = [NSCursor resizeLeftRightCursor]; + break; - case MouseCursor::LeftEdgeResizeCursor: - c = [NSCursor resizeLeftCursor]; - break; + case MouseCursor::LeftEdgeResizeCursor: + c = [NSCursor resizeLeftCursor]; + break; - case MouseCursor::RightEdgeResizeCursor: - c = [NSCursor resizeRightCursor]; - break; + case MouseCursor::RightEdgeResizeCursor: + c = [NSCursor resizeRightCursor]; + break; - case MouseCursor::UpDownResizeCursor: - case MouseCursor::TopEdgeResizeCursor: - case MouseCursor::BottomEdgeResizeCursor: - return juce_cursorFromWebKitFile ("northSouthResizeCursor.png", 0.5f, 0.5f); + case MouseCursor::UpDownResizeCursor: + case MouseCursor::TopEdgeResizeCursor: + case MouseCursor::BottomEdgeResizeCursor: + return juce_cursorFromWebKitFile ("northSouthResizeCursor.png", 0.5f, 0.5f); - case MouseCursor::TopLeftCornerResizeCursor: - case MouseCursor::BottomRightCornerResizeCursor: - return juce_cursorFromWebKitFile ("northWestSouthEastResizeCursor.png", 0.5f, 0.5f); + case MouseCursor::TopLeftCornerResizeCursor: + case MouseCursor::BottomRightCornerResizeCursor: + return juce_cursorFromWebKitFile ("northWestSouthEastResizeCursor.png", 0.5f, 0.5f); - case MouseCursor::TopRightCornerResizeCursor: - case MouseCursor::BottomLeftCornerResizeCursor: - return juce_cursorFromWebKitFile ("northEastSouthWestResizeCursor.png", 0.5f, 0.5f); + case MouseCursor::TopRightCornerResizeCursor: + case MouseCursor::BottomLeftCornerResizeCursor: + return juce_cursorFromWebKitFile ("northEastSouthWestResizeCursor.png", 0.5f, 0.5f); - case MouseCursor::UpDownLeftRightResizeCursor: - return juce_cursorFromWebKitFile ("moveCursor.png", 0.5f, 0.5f); + case MouseCursor::UpDownLeftRightResizeCursor: + return juce_cursorFromWebKitFile ("moveCursor.png", 0.5f, 0.5f); - case MouseCursor::CrosshairCursor: - c = [NSCursor crosshairCursor]; - break; - } + case MouseCursor::CrosshairCursor: + c = [NSCursor crosshairCursor]; + break; + } - [c retain]; - return (void*) c; + [c retain]; + return (void*) c; } void juce_deleteMouseCursor (void* const cursorHandle, const bool isStandard) throw() { - NSCursor* c = (NSCursor*) cursorHandle; - [c release]; + NSCursor* c = (NSCursor*) cursorHandle; + [c release]; } void MouseCursor::showInAllWindows() const throw() { - showInWindow (0); + showInWindow (0); } void MouseCursor::showInWindow (ComponentPeer*) const throw() { - NSCursor* const c = (NSCursor*) getHandle(); - [c set]; + NSCursor* const c = (NSCursor*) getHandle(); + [c set]; } #else void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) throw() { return 0; } -void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type) throw() { return 0; } -void juce_deleteMouseCursor (void* const cursorHandle, const bool isStandard) throw() {} -void MouseCursor::showInAllWindows() const throw() {} -void MouseCursor::showInWindow (ComponentPeer*) const throw() {} +void* juce_createStandardMouseCursor (MouseCursor::StandardCursorType type) throw() { return 0; } +void juce_deleteMouseCursor (void* const cursorHandle, const bool isStandard) throw() {} +void MouseCursor::showInAllWindows() const throw() {} +void MouseCursor::showInWindow (ComponentPeer*) const throw() {} #endif @@ -269193,93 +246753,93 @@ void MouseCursor::showInWindow (ComponentPeer*) const throw() class NSViewComponentInternal : public ComponentMovementWatcher { - Component* const owner; - NSViewComponentPeer* currentPeer; - bool wasShowing; + Component* const owner; + NSViewComponentPeer* currentPeer; + bool wasShowing; public: - NSView* const view; + NSView* const view; - NSViewComponentInternal (NSView* const view_, Component* const owner_) - : ComponentMovementWatcher (owner_), - owner (owner_), - currentPeer (0), - wasShowing (false), - view (view_) - { - [view_ retain]; + NSViewComponentInternal (NSView* const view_, Component* const owner_) + : ComponentMovementWatcher (owner_), + owner (owner_), + currentPeer (0), + wasShowing (false), + view (view_) + { + [view_ retain]; - if (owner_->isShowing()) - componentPeerChanged(); - } + if (owner_->isShowing()) + componentPeerChanged(); + } - ~NSViewComponentInternal() - { - [view removeFromSuperview]; - [view release]; - } + ~NSViewComponentInternal() + { + [view removeFromSuperview]; + [view release]; + } - void componentMovedOrResized (Component& comp, bool wasMoved, bool wasResized) - { - ComponentMovementWatcher::componentMovedOrResized (comp, wasMoved, wasResized); + void componentMovedOrResized (Component& comp, bool wasMoved, bool wasResized) + { + ComponentMovementWatcher::componentMovedOrResized (comp, wasMoved, wasResized); - // The ComponentMovementWatcher version of this method avoids calling - // us when the top-level comp is resized, but for an NSView we need to know this - // because with inverted co-ords, we need to update the position even if the - // top-left pos hasn't changed - if (comp.isOnDesktop() && wasResized) - componentMovedOrResized (wasMoved, wasResized); - } + // The ComponentMovementWatcher version of this method avoids calling + // us when the top-level comp is resized, but for an NSView we need to know this + // because with inverted co-ords, we need to update the position even if the + // top-left pos hasn't changed + if (comp.isOnDesktop() && wasResized) + componentMovedOrResized (wasMoved, wasResized); + } - void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) - { - Component* const topComp = owner->getTopLevelComponent(); + void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) + { + Component* const topComp = owner->getTopLevelComponent(); - if (topComp->getPeer() != 0) - { - int x = 0, y = 0; - owner->relativePositionToOtherComponent (topComp, x, y); + if (topComp->getPeer() != 0) + { + int x = 0, y = 0; + owner->relativePositionToOtherComponent (topComp, x, y); - NSRect r; - r.origin.x = (float) x; - r.origin.y = (float) y; - r.size.width = (float) owner->getWidth(); - r.size.height = (float) owner->getHeight(); - r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height); + NSRect r; + r.origin.x = (float) x; + r.origin.y = (float) y; + r.size.width = (float) owner->getWidth(); + r.size.height = (float) owner->getHeight(); + r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height); - [view setFrame: r]; - } - } + [view setFrame: r]; + } + } - void componentPeerChanged() - { - NSViewComponentPeer* const peer = dynamic_cast (owner->getPeer()); + void componentPeerChanged() + { + NSViewComponentPeer* const peer = dynamic_cast (owner->getPeer()); - if (currentPeer != peer) - { - [view removeFromSuperview]; - currentPeer = peer; + if (currentPeer != peer) + { + [view removeFromSuperview]; + currentPeer = peer; - if (peer != 0) - { - [peer->view addSubview: view]; - componentMovedOrResized (false, false); - } - } + if (peer != 0) + { + [peer->view addSubview: view]; + componentMovedOrResized (false, false); + } + } - [view setHidden: ! owner->isShowing()]; - } + [view setHidden: ! owner->isShowing()]; + } - void componentVisibilityChanged (Component&) - { - componentPeerChanged(); - } + void componentVisibilityChanged (Component&) + { + componentPeerChanged(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - NSViewComponentInternal (const NSViewComponentInternal&); - const NSViewComponentInternal& operator= (const NSViewComponentInternal&); + NSViewComponentInternal (const NSViewComponentInternal&); + const NSViewComponentInternal& operator= (const NSViewComponentInternal&); }; NSViewComponent::NSViewComponent() @@ -269292,18 +246852,18 @@ NSViewComponent::~NSViewComponent() void NSViewComponent::setView (void* view) { - if (view != getView()) - { - if (view != 0) - info = new NSViewComponentInternal ((NSView*) view, this); - else - info = 0; - } + if (view != getView()) + { + if (view != 0) + info = new NSViewComponentInternal ((NSView*) view, this); + else + info = 0; + } } void* NSViewComponent::getView() const { - return info == 0 ? 0 : info->view; + return info == 0 ? 0 : info->view; } void NSViewComponent::paint (Graphics& g) @@ -269319,240 +246879,240 @@ void NSViewComponent::paint (Graphics& g) #if JUCE_INCLUDED_FILE AppleRemoteDevice::AppleRemoteDevice() - : device (0), - queue (0), - remoteId (0) + : device (0), + queue (0), + remoteId (0) { } AppleRemoteDevice::~AppleRemoteDevice() { - stop(); + stop(); } static io_object_t getAppleRemoteDevice() { - CFMutableDictionaryRef dict = IOServiceMatching ("AppleIRController"); + CFMutableDictionaryRef dict = IOServiceMatching ("AppleIRController"); - io_iterator_t iter = 0; - io_object_t iod = 0; + io_iterator_t iter = 0; + io_object_t iod = 0; - if (IOServiceGetMatchingServices (kIOMasterPortDefault, dict, &iter) == kIOReturnSuccess - && iter != 0) - { - iod = IOIteratorNext (iter); - } + if (IOServiceGetMatchingServices (kIOMasterPortDefault, dict, &iter) == kIOReturnSuccess + && iter != 0) + { + iod = IOIteratorNext (iter); + } - IOObjectRelease (iter); - return iod; + IOObjectRelease (iter); + return iod; } static bool createAppleRemoteInterface (io_object_t iod, void** device) { - jassert (*device == 0); - io_name_t classname; + jassert (*device == 0); + io_name_t classname; - if (IOObjectGetClass (iod, classname) == kIOReturnSuccess) - { - IOCFPlugInInterface** cfPlugInInterface = 0; - SInt32 score = 0; + if (IOObjectGetClass (iod, classname) == kIOReturnSuccess) + { + IOCFPlugInInterface** cfPlugInInterface = 0; + SInt32 score = 0; - if (IOCreatePlugInInterfaceForService (iod, - kIOHIDDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, - &cfPlugInInterface, - &score) == kIOReturnSuccess) - { - HRESULT hr = (*cfPlugInInterface)->QueryInterface (cfPlugInInterface, - CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), - device); + if (IOCreatePlugInInterfaceForService (iod, + kIOHIDDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, + &cfPlugInInterface, + &score) == kIOReturnSuccess) + { + HRESULT hr = (*cfPlugInInterface)->QueryInterface (cfPlugInInterface, + CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), + device); - (void) hr; + (void) hr; - (*cfPlugInInterface)->Release (cfPlugInInterface); - } - } + (*cfPlugInInterface)->Release (cfPlugInInterface); + } + } - return *device != 0; + return *device != 0; } bool AppleRemoteDevice::start (const bool inExclusiveMode) { - if (queue != 0) - return true; + if (queue != 0) + return true; - stop(); + stop(); - bool result = false; - io_object_t iod = getAppleRemoteDevice(); + bool result = false; + io_object_t iod = getAppleRemoteDevice(); - if (iod != 0) - { - if (createAppleRemoteInterface (iod, &device) && open (inExclusiveMode)) - result = true; - else - stop(); + if (iod != 0) + { + if (createAppleRemoteInterface (iod, &device) && open (inExclusiveMode)) + result = true; + else + stop(); - IOObjectRelease (iod); - } + IOObjectRelease (iod); + } - return result; + return result; } void AppleRemoteDevice::stop() { - if (queue != 0) - { - (*(IOHIDQueueInterface**) queue)->stop ((IOHIDQueueInterface**) queue); - (*(IOHIDQueueInterface**) queue)->dispose ((IOHIDQueueInterface**) queue); - (*(IOHIDQueueInterface**) queue)->Release ((IOHIDQueueInterface**) queue); - queue = 0; - } + if (queue != 0) + { + (*(IOHIDQueueInterface**) queue)->stop ((IOHIDQueueInterface**) queue); + (*(IOHIDQueueInterface**) queue)->dispose ((IOHIDQueueInterface**) queue); + (*(IOHIDQueueInterface**) queue)->Release ((IOHIDQueueInterface**) queue); + queue = 0; + } - if (device != 0) - { - (*(IOHIDDeviceInterface**) device)->close ((IOHIDDeviceInterface**) device); - (*(IOHIDDeviceInterface**) device)->Release ((IOHIDDeviceInterface**) device); - device = 0; - } + if (device != 0) + { + (*(IOHIDDeviceInterface**) device)->close ((IOHIDDeviceInterface**) device); + (*(IOHIDDeviceInterface**) device)->Release ((IOHIDDeviceInterface**) device); + device = 0; + } } bool AppleRemoteDevice::isActive() const { - return queue != 0; + return queue != 0; } static void appleRemoteQueueCallback (void* const target, const IOReturn result, void*, void*) { - if (result == kIOReturnSuccess) - ((AppleRemoteDevice*) target)->handleCallbackInternal(); + if (result == kIOReturnSuccess) + ((AppleRemoteDevice*) target)->handleCallbackInternal(); } bool AppleRemoteDevice::open (const bool openInExclusiveMode) { - Array cookies; + Array cookies; - CFArrayRef elements; - IOHIDDeviceInterface122** const device122 = (IOHIDDeviceInterface122**) device; + CFArrayRef elements; + IOHIDDeviceInterface122** const device122 = (IOHIDDeviceInterface122**) device; - if ((*device122)->copyMatchingElements (device122, 0, &elements) != kIOReturnSuccess) - return false; + if ((*device122)->copyMatchingElements (device122, 0, &elements) != kIOReturnSuccess) + return false; - for (int i = 0; i < CFArrayGetCount (elements); ++i) - { - CFDictionaryRef element = (CFDictionaryRef) CFArrayGetValueAtIndex (elements, i); + for (int i = 0; i < CFArrayGetCount (elements); ++i) + { + CFDictionaryRef element = (CFDictionaryRef) CFArrayGetValueAtIndex (elements, i); - // get the cookie - CFTypeRef object = CFDictionaryGetValue (element, CFSTR (kIOHIDElementCookieKey)); + // get the cookie + CFTypeRef object = CFDictionaryGetValue (element, CFSTR (kIOHIDElementCookieKey)); - if (object == 0 || CFGetTypeID (object) != CFNumberGetTypeID()) - continue; + if (object == 0 || CFGetTypeID (object) != CFNumberGetTypeID()) + continue; - long number; - if (! CFNumberGetValue ((CFNumberRef) object, kCFNumberLongType, &number)) - continue; + long number; + if (! CFNumberGetValue ((CFNumberRef) object, kCFNumberLongType, &number)) + continue; - cookies.add ((int) number); - } + cookies.add ((int) number); + } - CFRelease (elements); + CFRelease (elements); - if ((*(IOHIDDeviceInterface**) device) - ->open ((IOHIDDeviceInterface**) device, - openInExclusiveMode ? kIOHIDOptionsTypeSeizeDevice - : kIOHIDOptionsTypeNone) == KERN_SUCCESS) - { - queue = (*(IOHIDDeviceInterface**) device)->allocQueue ((IOHIDDeviceInterface**) device); + if ((*(IOHIDDeviceInterface**) device) + ->open ((IOHIDDeviceInterface**) device, + openInExclusiveMode ? kIOHIDOptionsTypeSeizeDevice + : kIOHIDOptionsTypeNone) == KERN_SUCCESS) + { + queue = (*(IOHIDDeviceInterface**) device)->allocQueue ((IOHIDDeviceInterface**) device); - if (queue != 0) - { - (*(IOHIDQueueInterface**) queue)->create ((IOHIDQueueInterface**) queue, 0, 12); + if (queue != 0) + { + (*(IOHIDQueueInterface**) queue)->create ((IOHIDQueueInterface**) queue, 0, 12); - for (int i = 0; i < cookies.size(); ++i) - { - IOHIDElementCookie cookie = (IOHIDElementCookie) cookies.getUnchecked(i); - (*(IOHIDQueueInterface**) queue)->addElement ((IOHIDQueueInterface**) queue, cookie, 0); - } + for (int i = 0; i < cookies.size(); ++i) + { + IOHIDElementCookie cookie = (IOHIDElementCookie) cookies.getUnchecked(i); + (*(IOHIDQueueInterface**) queue)->addElement ((IOHIDQueueInterface**) queue, cookie, 0); + } - CFRunLoopSourceRef eventSource; + CFRunLoopSourceRef eventSource; - if ((*(IOHIDQueueInterface**) queue) - ->createAsyncEventSource ((IOHIDQueueInterface**) queue, &eventSource) == KERN_SUCCESS) - { - if ((*(IOHIDQueueInterface**) queue)->setEventCallout ((IOHIDQueueInterface**) queue, - appleRemoteQueueCallback, this, 0) == KERN_SUCCESS) - { - CFRunLoopAddSource (CFRunLoopGetCurrent(), eventSource, kCFRunLoopDefaultMode); + if ((*(IOHIDQueueInterface**) queue) + ->createAsyncEventSource ((IOHIDQueueInterface**) queue, &eventSource) == KERN_SUCCESS) + { + if ((*(IOHIDQueueInterface**) queue)->setEventCallout ((IOHIDQueueInterface**) queue, + appleRemoteQueueCallback, this, 0) == KERN_SUCCESS) + { + CFRunLoopAddSource (CFRunLoopGetCurrent(), eventSource, kCFRunLoopDefaultMode); - (*(IOHIDQueueInterface**) queue)->start ((IOHIDQueueInterface**) queue); + (*(IOHIDQueueInterface**) queue)->start ((IOHIDQueueInterface**) queue); - return true; - } - } - } - } + return true; + } + } + } + } - return false; + return false; } void AppleRemoteDevice::handleCallbackInternal() { - int totalValues = 0; - AbsoluteTime nullTime = { 0, 0 }; - char cookies [12]; - int numCookies = 0; + int totalValues = 0; + AbsoluteTime nullTime = { 0, 0 }; + char cookies [12]; + int numCookies = 0; - while (numCookies < numElementsInArray (cookies)) - { - IOHIDEventStruct e; + while (numCookies < numElementsInArray (cookies)) + { + IOHIDEventStruct e; - if ((*(IOHIDQueueInterface**) queue)->getNextEvent ((IOHIDQueueInterface**) queue, &e, nullTime, 0) != kIOReturnSuccess) - break; + if ((*(IOHIDQueueInterface**) queue)->getNextEvent ((IOHIDQueueInterface**) queue, &e, nullTime, 0) != kIOReturnSuccess) + break; - if ((int) e.elementCookie == 19) - { - remoteId = e.value; - buttonPressed (switched, false); - } - else - { - totalValues += e.value; - cookies [numCookies++] = (char) (pointer_sized_int) e.elementCookie; - } - } + if ((int) e.elementCookie == 19) + { + remoteId = e.value; + buttonPressed (switched, false); + } + else + { + totalValues += e.value; + cookies [numCookies++] = (char) (pointer_sized_int) e.elementCookie; + } + } - cookies [numCookies++] = 0; - //DBG (String::toHexString ((uint8*) cookies, numCookies, 1) + " " + String (totalValues)); + cookies [numCookies++] = 0; + //DBG (String::toHexString ((uint8*) cookies, numCookies, 1) + " " + String (totalValues)); - static const char buttonPatterns[] = - { - 0x1f, 0x14, 0x12, 0x1f, 0x14, 0x12, 0, - 0x1f, 0x15, 0x12, 0x1f, 0x15, 0x12, 0, - 0x1f, 0x1d, 0x1c, 0x12, 0, - 0x1f, 0x1e, 0x1c, 0x12, 0, - 0x1f, 0x16, 0x12, 0x1f, 0x16, 0x12, 0, - 0x1f, 0x17, 0x12, 0x1f, 0x17, 0x12, 0, - 0x1f, 0x12, 0x04, 0x02, 0, - 0x1f, 0x12, 0x03, 0x02, 0, - 0x1f, 0x12, 0x1f, 0x12, 0, - 0x23, 0x1f, 0x12, 0x23, 0x1f, 0x12, 0, - 19, 0 - }; + static const char buttonPatterns[] = + { + 0x1f, 0x14, 0x12, 0x1f, 0x14, 0x12, 0, + 0x1f, 0x15, 0x12, 0x1f, 0x15, 0x12, 0, + 0x1f, 0x1d, 0x1c, 0x12, 0, + 0x1f, 0x1e, 0x1c, 0x12, 0, + 0x1f, 0x16, 0x12, 0x1f, 0x16, 0x12, 0, + 0x1f, 0x17, 0x12, 0x1f, 0x17, 0x12, 0, + 0x1f, 0x12, 0x04, 0x02, 0, + 0x1f, 0x12, 0x03, 0x02, 0, + 0x1f, 0x12, 0x1f, 0x12, 0, + 0x23, 0x1f, 0x12, 0x23, 0x1f, 0x12, 0, + 19, 0 + }; - int buttonNum = (int) menuButton; - int i = 0; + int buttonNum = (int) menuButton; + int i = 0; - while (i < numElementsInArray (buttonPatterns)) - { - if (strcmp (cookies, buttonPatterns + i) == 0) - { - buttonPressed ((ButtonType) buttonNum, totalValues > 0); - break; - } + while (i < numElementsInArray (buttonPatterns)) + { + if (strcmp (cookies, buttonPatterns + i) == 0) + { + buttonPressed ((ButtonType) buttonNum, totalValues > 0); + break; + } - i += strlen (buttonPatterns + i) + 1; - ++buttonNum; - } + i += (int) strlen (buttonPatterns + i) + 1; + ++buttonNum; + } } #endif @@ -269571,8 +247131,8 @@ END_JUCE_NAMESPACE @interface ThreadSafeNSOpenGLView : NSOpenGLView { - CriticalSection* contextLock; - bool needsUpdate; + CriticalSection* contextLock; + bool needsUpdate; } - (id) initWithFrame: (NSRect) frameRect pixelFormat: (NSOpenGLPixelFormat*) format; @@ -269584,279 +247144,279 @@ END_JUCE_NAMESPACE @implementation ThreadSafeNSOpenGLView - (id) initWithFrame: (NSRect) frameRect - pixelFormat: (NSOpenGLPixelFormat*) format + pixelFormat: (NSOpenGLPixelFormat*) format { - contextLock = new CriticalSection(); - self = [super initWithFrame: frameRect pixelFormat: format]; + contextLock = new CriticalSection(); + self = [super initWithFrame: frameRect pixelFormat: format]; - if (self != nil) - [[NSNotificationCenter defaultCenter] addObserver: self - selector: @selector (_surfaceNeedsUpdate:) - name: NSViewGlobalFrameDidChangeNotification - object: self]; - return self; + if (self != nil) + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector (_surfaceNeedsUpdate:) + name: NSViewGlobalFrameDidChangeNotification + object: self]; + return self; } - (void) dealloc { - [[NSNotificationCenter defaultCenter] removeObserver: self]; - delete contextLock; - [super dealloc]; + [[NSNotificationCenter defaultCenter] removeObserver: self]; + delete contextLock; + [super dealloc]; } - (bool) makeActive { - const ScopedLock sl (*contextLock); + const ScopedLock sl (*contextLock); - if ([self openGLContext] == 0) - return false; + if ([self openGLContext] == 0) + return false; - [[self openGLContext] makeCurrentContext]; + [[self openGLContext] makeCurrentContext]; - if (needsUpdate) - { - [super update]; - needsUpdate = false; - } + if (needsUpdate) + { + [super update]; + needsUpdate = false; + } - return true; + return true; } - (void) makeInactive { - const ScopedLock sl (*contextLock); - [NSOpenGLContext clearCurrentContext]; + const ScopedLock sl (*contextLock); + [NSOpenGLContext clearCurrentContext]; } - (void) _surfaceNeedsUpdate: (NSNotification*) notification { - const ScopedLock sl (*contextLock); - needsUpdate = true; + const ScopedLock sl (*contextLock); + needsUpdate = true; } - (void) update { - const ScopedLock sl (*contextLock); - needsUpdate = true; + const ScopedLock sl (*contextLock); + needsUpdate = true; } - (void) reshape { - const ScopedLock sl (*contextLock); - needsUpdate = true; + const ScopedLock sl (*contextLock); + needsUpdate = true; } @end BEGIN_JUCE_NAMESPACE -class WindowedGLContext : public OpenGLContext +class WindowedGLContext : public OpenGLContext { public: - WindowedGLContext (Component* const component, - const OpenGLPixelFormat& pixelFormat_, - NSOpenGLContext* sharedContext) - : renderContext (0), - pixelFormat (pixelFormat_) - { - jassert (component != 0); + WindowedGLContext (Component* const component, + const OpenGLPixelFormat& pixelFormat_, + NSOpenGLContext* sharedContext) + : renderContext (0), + pixelFormat (pixelFormat_) + { + jassert (component != 0); - NSOpenGLPixelFormatAttribute attribs [64]; - int n = 0; - attribs[n++] = NSOpenGLPFADoubleBuffer; - attribs[n++] = NSOpenGLPFAAccelerated; - attribs[n++] = NSOpenGLPFAMPSafe; // NSOpenGLPFAAccelerated, NSOpenGLPFAMultiScreen, NSOpenGLPFASingleRenderer - attribs[n++] = NSOpenGLPFAColorSize; - attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits, - pixelFormat.greenBits, - pixelFormat.blueBits); - attribs[n++] = NSOpenGLPFAAlphaSize; - attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.alphaBits; - attribs[n++] = NSOpenGLPFADepthSize; - attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.depthBufferBits; - attribs[n++] = NSOpenGLPFAStencilSize; - attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.stencilBufferBits; - attribs[n++] = NSOpenGLPFAAccumSize; - attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.accumulationBufferRedBits, - pixelFormat.accumulationBufferGreenBits, - pixelFormat.accumulationBufferBlueBits, - pixelFormat.accumulationBufferAlphaBits); + NSOpenGLPixelFormatAttribute attribs [64]; + int n = 0; + attribs[n++] = NSOpenGLPFADoubleBuffer; + attribs[n++] = NSOpenGLPFAAccelerated; + attribs[n++] = NSOpenGLPFAMPSafe; // NSOpenGLPFAAccelerated, NSOpenGLPFAMultiScreen, NSOpenGLPFASingleRenderer + attribs[n++] = NSOpenGLPFAColorSize; + attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.redBits, + pixelFormat.greenBits, + pixelFormat.blueBits); + attribs[n++] = NSOpenGLPFAAlphaSize; + attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.alphaBits; + attribs[n++] = NSOpenGLPFADepthSize; + attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.depthBufferBits; + attribs[n++] = NSOpenGLPFAStencilSize; + attribs[n++] = (NSOpenGLPixelFormatAttribute) pixelFormat.stencilBufferBits; + attribs[n++] = NSOpenGLPFAAccumSize; + attribs[n++] = (NSOpenGLPixelFormatAttribute) jmax (pixelFormat.accumulationBufferRedBits, + pixelFormat.accumulationBufferGreenBits, + pixelFormat.accumulationBufferBlueBits, + pixelFormat.accumulationBufferAlphaBits); - // xxx not sure how to do fullSceneAntiAliasingNumSamples.. - attribs[n++] = NSOpenGLPFASampleBuffers; - attribs[n++] = (NSOpenGLPixelFormatAttribute) 1; - attribs[n++] = NSOpenGLPFAClosestPolicy; - attribs[n++] = NSOpenGLPFANoRecovery; - attribs[n++] = (NSOpenGLPixelFormatAttribute) 0; + // xxx not sure how to do fullSceneAntiAliasingNumSamples.. + attribs[n++] = NSOpenGLPFASampleBuffers; + attribs[n++] = (NSOpenGLPixelFormatAttribute) 1; + attribs[n++] = NSOpenGLPFAClosestPolicy; + attribs[n++] = NSOpenGLPFANoRecovery; + attribs[n++] = (NSOpenGLPixelFormatAttribute) 0; - NSOpenGLPixelFormat* format - = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; + NSOpenGLPixelFormat* format + = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; - view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) - pixelFormat: format]; + view = [[ThreadSafeNSOpenGLView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) + pixelFormat: format]; - renderContext = [[[NSOpenGLContext alloc] initWithFormat: format - shareContext: sharedContext] autorelease]; + renderContext = [[[NSOpenGLContext alloc] initWithFormat: format + shareContext: sharedContext] autorelease]; - const GLint swapInterval = 1; - [renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; + const GLint swapInterval = 1; + [renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; - [view setOpenGLContext: renderContext]; - [renderContext setView: view]; + [view setOpenGLContext: renderContext]; + [renderContext setView: view]; - [format release]; + [format release]; - viewHolder = new NSViewComponentInternal (view, component); - } + viewHolder = new NSViewComponentInternal (view, component); + } - ~WindowedGLContext() - { - makeInactive(); - [renderContext clearDrawable]; - delete viewHolder; - } + ~WindowedGLContext() + { + makeInactive(); + [renderContext clearDrawable]; + viewHolder = 0; + } - bool makeActive() const throw() - { - jassert (renderContext != 0); - [view makeActive]; - return isActive(); - } + bool makeActive() const throw() + { + jassert (renderContext != 0); + [view makeActive]; + return isActive(); + } - bool makeInactive() const throw() - { - [view makeInactive]; - return true; - } + bool makeInactive() const throw() + { + [view makeInactive]; + return true; + } - bool isActive() const throw() - { - return [NSOpenGLContext currentContext] == renderContext; - } + bool isActive() const throw() + { + return [NSOpenGLContext currentContext] == renderContext; + } - const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; } - void* getRawContext() const throw() { return renderContext; } + const OpenGLPixelFormat getPixelFormat() const { return pixelFormat; } + void* getRawContext() const throw() { return renderContext; } - void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight) - { - } + void updateWindowPosition (int x, int y, int w, int h, int outerWindowHeight) + { + } - void swapBuffers() - { - [renderContext flushBuffer]; - } + void swapBuffers() + { + [renderContext flushBuffer]; + } - bool setSwapInterval (const int numFramesPerSwap) - { - [renderContext setValues: (const GLint*) &numFramesPerSwap - forParameter: NSOpenGLCPSwapInterval]; - return true; - } + bool setSwapInterval (const int numFramesPerSwap) + { + [renderContext setValues: (const GLint*) &numFramesPerSwap + forParameter: NSOpenGLCPSwapInterval]; + return true; + } - int getSwapInterval() const - { - GLint numFrames = 0; - [renderContext getValues: &numFrames - forParameter: NSOpenGLCPSwapInterval]; - return numFrames; - } + int getSwapInterval() const + { + GLint numFrames = 0; + [renderContext getValues: &numFrames + forParameter: NSOpenGLCPSwapInterval]; + return numFrames; + } - void repaint() - { - // we need to invalidate the juce view that holds this gl view, to make it - // cause a repaint callback - NSView* v = (NSView*) viewHolder->view; - NSRect r = [v frame]; + void repaint() + { + // we need to invalidate the juce view that holds this gl view, to make it + // cause a repaint callback + NSView* v = (NSView*) viewHolder->view; + NSRect r = [v frame]; - // bit of a bodge here.. if we only invalidate the area of the gl component, - // it's completely covered by the NSOpenGLView, so the OS throws away the - // repaint message, thus never causing our paint() callback, and never repainting - // the comp. So invalidating just a little bit around the edge helps.. - [[v superview] setNeedsDisplayInRect: NSInsetRect (r, -2.0f, -2.0f)]; - } + // bit of a bodge here.. if we only invalidate the area of the gl component, + // it's completely covered by the NSOpenGLView, so the OS throws away the + // repaint message, thus never causing our paint() callback, and never repainting + // the comp. So invalidating just a little bit around the edge helps.. + [[v superview] setNeedsDisplayInRect: NSInsetRect (r, -2.0f, -2.0f)]; + } - void* getNativeWindowHandle() const { return viewHolder->view; } + void* getNativeWindowHandle() const { return viewHolder->view; } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - NSOpenGLContext* renderContext; - ThreadSafeNSOpenGLView* view; + NSOpenGLContext* renderContext; + ThreadSafeNSOpenGLView* view; private: - OpenGLPixelFormat pixelFormat; - NSViewComponentInternal* viewHolder; + OpenGLPixelFormat pixelFormat; + ScopedPointer viewHolder; - WindowedGLContext (const WindowedGLContext&); - const WindowedGLContext& operator= (const WindowedGLContext&); + WindowedGLContext (const WindowedGLContext&); + const WindowedGLContext& operator= (const WindowedGLContext&); }; OpenGLContext* OpenGLContext::createContextForWindow (Component* const component, - const OpenGLPixelFormat& pixelFormat, - const OpenGLContext* const contextToShareWith) + const OpenGLPixelFormat& pixelFormat, + const OpenGLContext* const contextToShareWith) { - ScopedPointer c (new WindowedGLContext (component, pixelFormat, - contextToShareWith != 0 ? (NSOpenGLContext*) contextToShareWith->getRawContext() : 0)); + ScopedPointer c (new WindowedGLContext (component, pixelFormat, + contextToShareWith != 0 ? (NSOpenGLContext*) contextToShareWith->getRawContext() : 0)); - return (c->renderContext != 0) ? c.release() : 0; + return (c->renderContext != 0) ? c.release() : 0; } void* OpenGLComponent::getNativeWindowHandle() const { - return context != 0 ? ((WindowedGLContext*) context)->getNativeWindowHandle() - : 0; + return context != 0 ? ((WindowedGLContext*) context)->getNativeWindowHandle() + : 0; } void juce_glViewport (const int w, const int h) { - glViewport (0, 0, w, h); + glViewport (0, 0, w, h); } void OpenGLPixelFormat::getAvailablePixelFormats (Component* /*component*/, - OwnedArray & results) + OwnedArray & results) { -/* GLint attribs [64]; - int n = 0; - attribs[n++] = AGL_RGBA; - attribs[n++] = AGL_DOUBLEBUFFER; - attribs[n++] = AGL_ACCELERATED; - attribs[n++] = AGL_NO_RECOVERY; - attribs[n++] = AGL_NONE; +/* GLint attribs [64]; + int n = 0; + attribs[n++] = AGL_RGBA; + attribs[n++] = AGL_DOUBLEBUFFER; + attribs[n++] = AGL_ACCELERATED; + attribs[n++] = AGL_NO_RECOVERY; + attribs[n++] = AGL_NONE; - AGLPixelFormat p = aglChoosePixelFormat (0, 0, attribs); + AGLPixelFormat p = aglChoosePixelFormat (0, 0, attribs); - while (p != 0) - { - OpenGLPixelFormat* const pf = new OpenGLPixelFormat(); - pf->redBits = getAGLAttribute (p, AGL_RED_SIZE); - pf->greenBits = getAGLAttribute (p, AGL_GREEN_SIZE); - pf->blueBits = getAGLAttribute (p, AGL_BLUE_SIZE); - pf->alphaBits = getAGLAttribute (p, AGL_ALPHA_SIZE); - pf->depthBufferBits = getAGLAttribute (p, AGL_DEPTH_SIZE); - pf->stencilBufferBits = getAGLAttribute (p, AGL_STENCIL_SIZE); - pf->accumulationBufferRedBits = getAGLAttribute (p, AGL_ACCUM_RED_SIZE); - pf->accumulationBufferGreenBits = getAGLAttribute (p, AGL_ACCUM_GREEN_SIZE); - pf->accumulationBufferBlueBits = getAGLAttribute (p, AGL_ACCUM_BLUE_SIZE); - pf->accumulationBufferAlphaBits = getAGLAttribute (p, AGL_ACCUM_ALPHA_SIZE); + while (p != 0) + { + OpenGLPixelFormat* const pf = new OpenGLPixelFormat(); + pf->redBits = getAGLAttribute (p, AGL_RED_SIZE); + pf->greenBits = getAGLAttribute (p, AGL_GREEN_SIZE); + pf->blueBits = getAGLAttribute (p, AGL_BLUE_SIZE); + pf->alphaBits = getAGLAttribute (p, AGL_ALPHA_SIZE); + pf->depthBufferBits = getAGLAttribute (p, AGL_DEPTH_SIZE); + pf->stencilBufferBits = getAGLAttribute (p, AGL_STENCIL_SIZE); + pf->accumulationBufferRedBits = getAGLAttribute (p, AGL_ACCUM_RED_SIZE); + pf->accumulationBufferGreenBits = getAGLAttribute (p, AGL_ACCUM_GREEN_SIZE); + pf->accumulationBufferBlueBits = getAGLAttribute (p, AGL_ACCUM_BLUE_SIZE); + pf->accumulationBufferAlphaBits = getAGLAttribute (p, AGL_ACCUM_ALPHA_SIZE); - results.add (pf); + results.add (pf); - p = aglNextPixelFormat (p); - }*/ + p = aglNextPixelFormat (p); + }*/ - //jassertfalse //xxx can't see how you do this in cocoa! + //jassertfalse //xxx can't see how you do this in cocoa! } #else OpenGLContext* OpenGLContext::createContextForWindow (Component* const component, - const OpenGLPixelFormat& pixelFormat, - const OpenGLContext* const contextToShareWith) + const OpenGLPixelFormat& pixelFormat, + const OpenGLContext* const contextToShareWith) { - return 0; + return 0; } void juce_glViewport (const int w, const int h) { - //glViewport (0, 0, w, h); + //glViewport (0, 0, w, h); } #endif @@ -269882,7 +247442,7 @@ using namespace JUCE_NAMESPACE; @interface JuceMenuCallback : NSObject #endif { - JuceMainMenuHandler* owner; + JuceMainMenuHandler* owner; } - (JuceMenuCallback*) initWithOwner: (JuceMainMenuHandler*) owner_; @@ -269893,288 +247453,288 @@ using namespace JUCE_NAMESPACE; BEGIN_JUCE_NAMESPACE class JuceMainMenuHandler : private MenuBarModelListener, - private DeletedAtShutdown + private DeletedAtShutdown { public: - static JuceMainMenuHandler* instance; + static JuceMainMenuHandler* instance; - JuceMainMenuHandler() - : currentModel (0), - lastUpdateTime (0) - { - callback = [[JuceMenuCallback alloc] initWithOwner: this]; - } + JuceMainMenuHandler() + : currentModel (0), + lastUpdateTime (0) + { + callback = [[JuceMenuCallback alloc] initWithOwner: this]; + } - ~JuceMainMenuHandler() - { - setMenu (0); + ~JuceMainMenuHandler() + { + setMenu (0); - jassert (instance == this); - instance = 0; + jassert (instance == this); + instance = 0; - [callback release]; - } + [callback release]; + } - void setMenu (MenuBarModel* const newMenuBarModel) - { - if (currentModel != newMenuBarModel) - { - if (currentModel != 0) - currentModel->removeListener (this); + void setMenu (MenuBarModel* const newMenuBarModel) + { + if (currentModel != newMenuBarModel) + { + if (currentModel != 0) + currentModel->removeListener (this); - currentModel = newMenuBarModel; + currentModel = newMenuBarModel; - if (currentModel != 0) - currentModel->addListener (this); + if (currentModel != 0) + currentModel->addListener (this); - menuBarItemsChanged (0); - } - } + menuBarItemsChanged (0); + } + } - void addSubMenu (NSMenu* parent, const PopupMenu& child, - const String& name, const int menuId, const int tag) - { - NSMenuItem* item = [parent addItemWithTitle: juceStringToNS (name) - action: nil - keyEquivalent: @""]; - [item setTag: tag]; + void addSubMenu (NSMenu* parent, const PopupMenu& child, + const String& name, const int menuId, const int tag) + { + NSMenuItem* item = [parent addItemWithTitle: juceStringToNS (name) + action: nil + keyEquivalent: @""]; + [item setTag: tag]; - NSMenu* sub = createMenu (child, name, menuId, tag); + NSMenu* sub = createMenu (child, name, menuId, tag); - [parent setSubmenu: sub forItem: item]; - [sub setAutoenablesItems: false]; - [sub release]; - } + [parent setSubmenu: sub forItem: item]; + [sub setAutoenablesItems: false]; + [sub release]; + } - void updateSubMenu (NSMenuItem* parentItem, const PopupMenu& menuToCopy, - const String& name, const int menuId, const int tag) - { - [parentItem setTag: tag]; - NSMenu* menu = [parentItem submenu]; + void updateSubMenu (NSMenuItem* parentItem, const PopupMenu& menuToCopy, + const String& name, const int menuId, const int tag) + { + [parentItem setTag: tag]; + NSMenu* menu = [parentItem submenu]; - [menu setTitle: juceStringToNS (name)]; + [menu setTitle: juceStringToNS (name)]; - while ([menu numberOfItems] > 0) - [menu removeItemAtIndex: 0]; + while ([menu numberOfItems] > 0) + [menu removeItemAtIndex: 0]; - PopupMenu::MenuItemIterator iter (menuToCopy); + PopupMenu::MenuItemIterator iter (menuToCopy); - while (iter.next()) - addMenuItem (iter, menu, menuId, tag); + while (iter.next()) + addMenuItem (iter, menu, menuId, tag); - [menu setAutoenablesItems: false]; - [menu update]; - } + [menu setAutoenablesItems: false]; + [menu update]; + } - void menuBarItemsChanged (MenuBarModel*) - { - lastUpdateTime = Time::getMillisecondCounter(); + void menuBarItemsChanged (MenuBarModel*) + { + lastUpdateTime = Time::getMillisecondCounter(); - StringArray menuNames; - if (currentModel != 0) - menuNames = currentModel->getMenuBarNames(); + StringArray menuNames; + if (currentModel != 0) + menuNames = currentModel->getMenuBarNames(); - NSMenu* menuBar = [NSApp mainMenu]; - while ([menuBar numberOfItems] > 1 + menuNames.size()) - [menuBar removeItemAtIndex: [menuBar numberOfItems] - 1]; + NSMenu* menuBar = [NSApp mainMenu]; + while ([menuBar numberOfItems] > 1 + menuNames.size()) + [menuBar removeItemAtIndex: [menuBar numberOfItems] - 1]; - int menuId = 1; + int menuId = 1; - for (int i = 0; i < menuNames.size(); ++i) - { - const PopupMenu menu (currentModel->getMenuForIndex (i, menuNames [i])); + for (int i = 0; i < menuNames.size(); ++i) + { + const PopupMenu menu (currentModel->getMenuForIndex (i, menuNames [i])); - if (i >= [menuBar numberOfItems] - 1) - addSubMenu (menuBar, menu, menuNames[i], menuId, i); - else - updateSubMenu ([menuBar itemAtIndex: 1 + i], menu, menuNames[i], menuId, i); - } - } + if (i >= [menuBar numberOfItems] - 1) + addSubMenu (menuBar, menu, menuNames[i], menuId, i); + else + updateSubMenu ([menuBar itemAtIndex: 1 + i], menu, menuNames[i], menuId, i); + } + } - static void flashMenuBar (NSMenu* menu) - { - const unichar f35Key = NSF35FunctionKey; - NSString* f35String = [NSString stringWithCharacters: &f35Key length: 1]; + static void flashMenuBar (NSMenu* menu) + { + const unichar f35Key = NSF35FunctionKey; + NSString* f35String = [NSString stringWithCharacters: &f35Key length: 1]; - NSMenuItem* item = [[NSMenuItem alloc] initWithTitle: @"x" - action: nil - keyEquivalent: f35String]; - [item setTarget: nil]; - [menu insertItem: item atIndex: [menu numberOfItems]]; - [item release]; + NSMenuItem* item = [[NSMenuItem alloc] initWithTitle: @"x" + action: nil + keyEquivalent: f35String]; + [item setTarget: nil]; + [menu insertItem: item atIndex: [menu numberOfItems]]; + [item release]; - NSEvent* f35Event = [NSEvent keyEventWithType: NSKeyDown - location: NSZeroPoint - modifierFlags: NSCommandKeyMask - timestamp: 0 - windowNumber: 0 - context: [NSGraphicsContext currentContext] - characters: f35String - charactersIgnoringModifiers: f35String - isARepeat: NO - keyCode: 0]; + NSEvent* f35Event = [NSEvent keyEventWithType: NSKeyDown + location: NSZeroPoint + modifierFlags: NSCommandKeyMask + timestamp: 0 + windowNumber: 0 + context: [NSGraphicsContext currentContext] + characters: f35String + charactersIgnoringModifiers: f35String + isARepeat: NO + keyCode: 0]; - [menu performKeyEquivalent: f35Event]; - [menu removeItem: item]; - } + [menu performKeyEquivalent: f35Event]; + [menu removeItem: item]; + } - static NSMenuItem* findMenuItem (NSMenu* const menu, const ApplicationCommandTarget::InvocationInfo& info) - { - for (int i = [menu numberOfItems]; --i >= 0;) - { - NSMenuItem* m = [menu itemAtIndex: i]; - if ([m tag] == info.commandID) - return m; + static NSMenuItem* findMenuItem (NSMenu* const menu, const ApplicationCommandTarget::InvocationInfo& info) + { + for (NSInteger i = [menu numberOfItems]; --i >= 0;) + { + NSMenuItem* m = [menu itemAtIndex: i]; + if ([m tag] == info.commandID) + return m; - if ([m submenu] != 0) - { - NSMenuItem* found = findMenuItem ([m submenu], info); - if (found != 0) - return found; - } - } + if ([m submenu] != 0) + { + NSMenuItem* found = findMenuItem ([m submenu], info); + if (found != 0) + return found; + } + } - return 0; - } + return 0; + } - void menuCommandInvoked (MenuBarModel*, const ApplicationCommandTarget::InvocationInfo& info) - { - NSMenuItem* item = findMenuItem ([NSApp mainMenu], info); + void menuCommandInvoked (MenuBarModel*, const ApplicationCommandTarget::InvocationInfo& info) + { + NSMenuItem* item = findMenuItem ([NSApp mainMenu], info); - if (item != 0) - flashMenuBar ([item menu]); - } + if (item != 0) + flashMenuBar ([item menu]); + } - void updateMenus() - { - if (Time::getMillisecondCounter() > lastUpdateTime + 500) - menuBarItemsChanged (0); - } + void updateMenus() + { + if (Time::getMillisecondCounter() > lastUpdateTime + 500) + menuBarItemsChanged (0); + } - void invoke (const int commandId, ApplicationCommandManager* const commandManager, const int topLevelIndex) const - { - if (currentModel != 0) - { - if (commandManager != 0) - { - ApplicationCommandTarget::InvocationInfo info (commandId); - info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu; + void invoke (const int commandId, ApplicationCommandManager* const commandManager, const int topLevelIndex) const + { + if (currentModel != 0) + { + if (commandManager != 0) + { + ApplicationCommandTarget::InvocationInfo info (commandId); + info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu; - commandManager->invoke (info, true); - } + commandManager->invoke (info, true); + } - currentModel->menuItemSelected (commandId, topLevelIndex); - } - } + currentModel->menuItemSelected (commandId, topLevelIndex); + } + } - MenuBarModel* currentModel; - uint32 lastUpdateTime; + MenuBarModel* currentModel; + uint32 lastUpdateTime; - void addMenuItem (PopupMenu::MenuItemIterator& iter, NSMenu* menuToAddTo, - const int topLevelMenuId, const int topLevelIndex) - { - NSString* text = juceStringToNS (iter.itemName.upToFirstOccurrenceOf (T(""), false, true)); + void addMenuItem (PopupMenu::MenuItemIterator& iter, NSMenu* menuToAddTo, + const int topLevelMenuId, const int topLevelIndex) + { + NSString* text = juceStringToNS (iter.itemName.upToFirstOccurrenceOf (T(""), false, true)); - if (text == 0) - text = @""; + if (text == 0) + text = @""; - if (iter.isSeparator) - { - [menuToAddTo addItem: [NSMenuItem separatorItem]]; - } - else if (iter.isSectionHeader) - { - NSMenuItem* item = [menuToAddTo addItemWithTitle: text - action: nil - keyEquivalent: @""]; + if (iter.isSeparator) + { + [menuToAddTo addItem: [NSMenuItem separatorItem]]; + } + else if (iter.isSectionHeader) + { + NSMenuItem* item = [menuToAddTo addItemWithTitle: text + action: nil + keyEquivalent: @""]; - [item setEnabled: false]; - } - else if (iter.subMenu != 0) - { - NSMenuItem* item = [menuToAddTo addItemWithTitle: text - action: nil - keyEquivalent: @""]; + [item setEnabled: false]; + } + else if (iter.subMenu != 0) + { + NSMenuItem* item = [menuToAddTo addItemWithTitle: text + action: nil + keyEquivalent: @""]; - [item setTag: iter.itemId]; - [item setEnabled: iter.isEnabled]; + [item setTag: iter.itemId]; + [item setEnabled: iter.isEnabled]; - NSMenu* sub = createMenu (*iter.subMenu, iter.itemName, topLevelMenuId, topLevelIndex); - [sub setDelegate: nil]; - [menuToAddTo setSubmenu: sub forItem: item]; - [sub release]; - } - else - { - NSMenuItem* item = [menuToAddTo addItemWithTitle: text - action: @selector (menuItemInvoked:) - keyEquivalent: @""]; + NSMenu* sub = createMenu (*iter.subMenu, iter.itemName, topLevelMenuId, topLevelIndex); + [sub setDelegate: nil]; + [menuToAddTo setSubmenu: sub forItem: item]; + [sub release]; + } + else + { + NSMenuItem* item = [menuToAddTo addItemWithTitle: text + action: @selector (menuItemInvoked:) + keyEquivalent: @""]; - [item setTag: iter.itemId]; - [item setEnabled: iter.isEnabled]; - [item setState: iter.isTicked ? NSOnState : NSOffState]; - [item setTarget: (id) callback]; + [item setTag: iter.itemId]; + [item setEnabled: iter.isEnabled]; + [item setState: iter.isTicked ? NSOnState : NSOffState]; + [item setTarget: (id) callback]; - NSMutableArray* info = [NSMutableArray arrayWithObject: [NSNumber numberWithUnsignedLongLong: (pointer_sized_int) (void*) iter.commandManager]]; - [info addObject: [NSNumber numberWithInt: topLevelIndex]]; - [item setRepresentedObject: info]; + NSMutableArray* info = [NSMutableArray arrayWithObject: [NSNumber numberWithUnsignedLongLong: (pointer_sized_int) (void*) iter.commandManager]]; + [info addObject: [NSNumber numberWithInt: topLevelIndex]]; + [item setRepresentedObject: info]; - if (iter.commandManager != 0) - { - const Array keyPresses (iter.commandManager->getKeyMappings() - ->getKeyPressesAssignedToCommand (iter.itemId)); + if (iter.commandManager != 0) + { + const Array keyPresses (iter.commandManager->getKeyMappings() + ->getKeyPressesAssignedToCommand (iter.itemId)); - if (keyPresses.size() > 0) - { - const KeyPress& kp = keyPresses.getReference(0); + if (keyPresses.size() > 0) + { + const KeyPress& kp = keyPresses.getReference(0); - juce_wchar key = kp.getTextCharacter(); + juce_wchar key = kp.getTextCharacter(); - if (kp.getKeyCode() == KeyPress::backspaceKey) - key = NSBackspaceCharacter; - else if (kp.getKeyCode() == KeyPress::deleteKey) - key = NSDeleteCharacter; - else if (key == 0) - key = (juce_wchar) kp.getKeyCode(); + if (kp.getKeyCode() == KeyPress::backspaceKey) + key = NSBackspaceCharacter; + else if (kp.getKeyCode() == KeyPress::deleteKey) + key = NSDeleteCharacter; + else if (key == 0) + key = (juce_wchar) kp.getKeyCode(); - unsigned int mods = 0; - if (kp.getModifiers().isShiftDown()) - mods |= NSShiftKeyMask; - if (kp.getModifiers().isCtrlDown()) - mods |= NSControlKeyMask; - if (kp.getModifiers().isAltDown()) - mods |= NSAlternateKeyMask; - if (kp.getModifiers().isCommandDown()) - mods |= NSCommandKeyMask; + unsigned int mods = 0; + if (kp.getModifiers().isShiftDown()) + mods |= NSShiftKeyMask; + if (kp.getModifiers().isCtrlDown()) + mods |= NSControlKeyMask; + if (kp.getModifiers().isAltDown()) + mods |= NSAlternateKeyMask; + if (kp.getModifiers().isCommandDown()) + mods |= NSCommandKeyMask; - [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; - [item setKeyEquivalentModifierMask: mods]; - } - } - } - } + [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; + [item setKeyEquivalentModifierMask: mods]; + } + } + } + } - JuceMenuCallback* callback; + JuceMenuCallback* callback; private: - NSMenu* createMenu (const PopupMenu menu, - const String& menuName, - const int topLevelMenuId, - const int topLevelIndex) - { - NSMenu* m = [[NSMenu alloc] initWithTitle: juceStringToNS (menuName)]; + NSMenu* createMenu (const PopupMenu menu, + const String& menuName, + const int topLevelMenuId, + const int topLevelIndex) + { + NSMenu* m = [[NSMenu alloc] initWithTitle: juceStringToNS (menuName)]; - [m setAutoenablesItems: false]; - [m setDelegate: callback]; + [m setAutoenablesItems: false]; + [m setDelegate: callback]; - PopupMenu::MenuItemIterator iter (menu); + PopupMenu::MenuItemIterator iter (menu); - while (iter.next()) - addMenuItem (iter, m, topLevelMenuId, topLevelIndex); + while (iter.next()) + addMenuItem (iter, m, topLevelMenuId, topLevelIndex); - [m update]; - return m; - } + [m update]; + return m; + } }; JuceMainMenuHandler* JuceMainMenuHandler::instance = 0; @@ -270184,187 +247744,187 @@ END_JUCE_NAMESPACE - (JuceMenuCallback*) initWithOwner: (JuceMainMenuHandler*) owner_ { - [super init]; - owner = owner_; - return self; + [super init]; + owner = owner_; + return self; } - (void) dealloc { - [super dealloc]; + [super dealloc]; } - (void) menuItemInvoked: (id) menu { - NSMenuItem* item = (NSMenuItem*) menu; + NSMenuItem* item = (NSMenuItem*) menu; - if ([[item representedObject] isKindOfClass: [NSArray class]]) - { - // If the menu is being triggered by a keypress, the OS will have picked it up before we had a chance to offer it to - // our own components, which may have wanted to intercept it. So, rather than dispatching directly, we'll feed it back - // into the focused component and let it trigger the menu item indirectly. - NSEvent* e = [NSApp currentEvent]; - if ([e type] == NSKeyDown || [e type] == NSKeyUp) - { - if (JUCE_NAMESPACE::Component::getCurrentlyFocusedComponent()->isValidComponent()) - { - JUCE_NAMESPACE::NSViewComponentPeer* peer = dynamic_cast (JUCE_NAMESPACE::Component::getCurrentlyFocusedComponent()->getPeer()); + if ([[item representedObject] isKindOfClass: [NSArray class]]) + { + // If the menu is being triggered by a keypress, the OS will have picked it up before we had a chance to offer it to + // our own components, which may have wanted to intercept it. So, rather than dispatching directly, we'll feed it back + // into the focused component and let it trigger the menu item indirectly. + NSEvent* e = [NSApp currentEvent]; + if ([e type] == NSKeyDown || [e type] == NSKeyUp) + { + if (JUCE_NAMESPACE::Component::getCurrentlyFocusedComponent()->isValidComponent()) + { + JUCE_NAMESPACE::NSViewComponentPeer* peer = dynamic_cast (JUCE_NAMESPACE::Component::getCurrentlyFocusedComponent()->getPeer()); - if (peer != 0) - { - if ([e type] == NSKeyDown) - peer->redirectKeyDown (e); - else - peer->redirectKeyUp (e); + if (peer != 0) + { + if ([e type] == NSKeyDown) + peer->redirectKeyDown (e); + else + peer->redirectKeyUp (e); - return; - } - } - } + return; + } + } + } - NSArray* info = (NSArray*) [item representedObject]; + NSArray* info = (NSArray*) [item representedObject]; - owner->invoke ([item tag], - (ApplicationCommandManager*) (pointer_sized_int) - [((NSNumber*) [info objectAtIndex: 0]) unsignedLongLongValue], - (int) [((NSNumber*) [info objectAtIndex: 1]) intValue]); - } + owner->invoke ((int) [item tag], + (ApplicationCommandManager*) (pointer_sized_int) + [((NSNumber*) [info objectAtIndex: 0]) unsignedLongLongValue], + (int) [((NSNumber*) [info objectAtIndex: 1]) intValue]); + } } - (void) menuNeedsUpdate: (NSMenu*) menu; { - if (JuceMainMenuHandler::instance != 0) - JuceMainMenuHandler::instance->updateMenus(); + if (JuceMainMenuHandler::instance != 0) + JuceMainMenuHandler::instance->updateMenus(); } @end BEGIN_JUCE_NAMESPACE static NSMenu* createStandardAppMenu (NSMenu* menu, const String& appName, - const PopupMenu* extraItems) + const PopupMenu* extraItems) { - if (extraItems != 0 && JuceMainMenuHandler::instance != 0 && extraItems->getNumItems() > 0) - { - PopupMenu::MenuItemIterator iter (*extraItems); + if (extraItems != 0 && JuceMainMenuHandler::instance != 0 && extraItems->getNumItems() > 0) + { + PopupMenu::MenuItemIterator iter (*extraItems); - while (iter.next()) - JuceMainMenuHandler::instance->addMenuItem (iter, menu, 0, -1); + while (iter.next()) + JuceMainMenuHandler::instance->addMenuItem (iter, menu, 0, -1); - [menu addItem: [NSMenuItem separatorItem]]; - } + [menu addItem: [NSMenuItem separatorItem]]; + } - NSMenuItem* item; + NSMenuItem* item; - // Services... - item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Services", nil) - action: nil keyEquivalent: @""]; - [menu addItem: item]; - [item release]; - NSMenu* servicesMenu = [[NSMenu alloc] initWithTitle: @"Services"]; - [menu setSubmenu: servicesMenu forItem: item]; - [NSApp setServicesMenu: servicesMenu]; - [servicesMenu release]; - [menu addItem: [NSMenuItem separatorItem]]; + // Services... + item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Services", nil) + action: nil keyEquivalent: @""]; + [menu addItem: item]; + [item release]; + NSMenu* servicesMenu = [[NSMenu alloc] initWithTitle: @"Services"]; + [menu setSubmenu: servicesMenu forItem: item]; + [NSApp setServicesMenu: servicesMenu]; + [servicesMenu release]; + [menu addItem: [NSMenuItem separatorItem]]; - // Hide + Show stuff... - item = [[NSMenuItem alloc] initWithTitle: juceStringToNS ("Hide " + appName) - action: @selector (hide:) keyEquivalent: @"h"]; - [item setTarget: NSApp]; - [menu addItem: item]; - [item release]; + // Hide + Show stuff... + item = [[NSMenuItem alloc] initWithTitle: juceStringToNS ("Hide " + appName) + action: @selector (hide:) keyEquivalent: @"h"]; + [item setTarget: NSApp]; + [menu addItem: item]; + [item release]; - item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Hide Others", nil) - action: @selector (hideOtherApplications:) keyEquivalent: @"h"]; - [item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask]; - [item setTarget: NSApp]; - [menu addItem: item]; - [item release]; + item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Hide Others", nil) + action: @selector (hideOtherApplications:) keyEquivalent: @"h"]; + [item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask]; + [item setTarget: NSApp]; + [menu addItem: item]; + [item release]; - item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Show All", nil) - action: @selector (unhideAllApplications:) keyEquivalent: @""]; - [item setTarget: NSApp]; - [menu addItem: item]; - [item release]; + item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Show All", nil) + action: @selector (unhideAllApplications:) keyEquivalent: @""]; + [item setTarget: NSApp]; + [menu addItem: item]; + [item release]; - [menu addItem: [NSMenuItem separatorItem]]; + [menu addItem: [NSMenuItem separatorItem]]; - // Quit item.... - item = [[NSMenuItem alloc] initWithTitle: juceStringToNS ("Quit " + appName) - action: @selector (terminate:) keyEquivalent: @"q"]; + // Quit item.... + item = [[NSMenuItem alloc] initWithTitle: juceStringToNS ("Quit " + appName) + action: @selector (terminate:) keyEquivalent: @"q"]; - [item setTarget: NSApp]; - [menu addItem: item]; - [item release]; + [item setTarget: NSApp]; + [menu addItem: item]; + [item release]; - return menu; + return menu; } // Since our app has no NIB, this initialises a standard app menu... static void rebuildMainMenu (const PopupMenu* extraItems) { - // this can't be used in a plugin! - jassert (JUCEApplication::getInstance() != 0); + // this can't be used in a plugin! + jassert (JUCEApplication::getInstance() != 0); - if (JUCEApplication::getInstance() != 0) - { - const ScopedAutoReleasePool pool; + if (JUCEApplication::getInstance() != 0) + { + const ScopedAutoReleasePool pool; - NSMenu* mainMenu = [[NSMenu alloc] initWithTitle: @"MainMenu"]; - NSMenuItem* item = [mainMenu addItemWithTitle: @"Apple" action: nil keyEquivalent: @""]; + NSMenu* mainMenu = [[NSMenu alloc] initWithTitle: @"MainMenu"]; + NSMenuItem* item = [mainMenu addItemWithTitle: @"Apple" action: nil keyEquivalent: @""]; - NSMenu* appMenu = [[NSMenu alloc] initWithTitle: @"Apple"]; + NSMenu* appMenu = [[NSMenu alloc] initWithTitle: @"Apple"]; - [NSApp performSelector: @selector (setAppleMenu:) withObject: appMenu]; - [mainMenu setSubmenu: appMenu forItem: item]; + [NSApp performSelector: @selector (setAppleMenu:) withObject: appMenu]; + [mainMenu setSubmenu: appMenu forItem: item]; - [NSApp setMainMenu: mainMenu]; - createStandardAppMenu (appMenu, JUCEApplication::getInstance()->getApplicationName(), extraItems); + [NSApp setMainMenu: mainMenu]; + createStandardAppMenu (appMenu, JUCEApplication::getInstance()->getApplicationName(), extraItems); - [appMenu release]; - [mainMenu release]; - } + [appMenu release]; + [mainMenu release]; + } } void MenuBarModel::setMacMainMenu (MenuBarModel* newMenuBarModel, - const PopupMenu* extraAppleMenuItems) + const PopupMenu* extraAppleMenuItems) { - if (getMacMainMenu() != newMenuBarModel) - { - const ScopedAutoReleasePool pool; + if (getMacMainMenu() != newMenuBarModel) + { + const ScopedAutoReleasePool pool; - if (newMenuBarModel == 0) - { - delete JuceMainMenuHandler::instance; - jassert (JuceMainMenuHandler::instance == 0); // should be zeroed in the destructor - jassert (extraAppleMenuItems == 0); // you can't specify some extra items without also supplying a model + if (newMenuBarModel == 0) + { + delete JuceMainMenuHandler::instance; + jassert (JuceMainMenuHandler::instance == 0); // should be zeroed in the destructor + jassert (extraAppleMenuItems == 0); // you can't specify some extra items without also supplying a model - extraAppleMenuItems = 0; - } - else - { - if (JuceMainMenuHandler::instance == 0) - JuceMainMenuHandler::instance = new JuceMainMenuHandler(); + extraAppleMenuItems = 0; + } + else + { + if (JuceMainMenuHandler::instance == 0) + JuceMainMenuHandler::instance = new JuceMainMenuHandler(); - JuceMainMenuHandler::instance->setMenu (newMenuBarModel); - } - } + JuceMainMenuHandler::instance->setMenu (newMenuBarModel); + } + } - rebuildMainMenu (extraAppleMenuItems); + rebuildMainMenu (extraAppleMenuItems); - if (newMenuBarModel != 0) - newMenuBarModel->menuItemsChanged(); + if (newMenuBarModel != 0) + newMenuBarModel->menuItemsChanged(); } MenuBarModel* MenuBarModel::getMacMainMenu() { - return JuceMainMenuHandler::instance != 0 - ? JuceMainMenuHandler::instance->currentModel : 0; + return JuceMainMenuHandler::instance != 0 + ? JuceMainMenuHandler::instance->currentModel : 0; } void initialiseMainMenu() { - if (JUCEApplication::getInstance() != 0) // only needed in an app - rebuildMainMenu (0); + if (JUCEApplication::getInstance() != 0) // only needed in an app + rebuildMainMenu (0); } #endif @@ -270388,7 +247948,7 @@ using namespace JUCE_NAMESPACE; @interface JuceFileChooserDelegate : NSObject #endif { - StringArray* filters; + StringArray* filters; } - (JuceFileChooserDelegate*) initWithFilters: (StringArray*) filters_; @@ -270400,118 +247960,118 @@ using namespace JUCE_NAMESPACE; @implementation JuceFileChooserDelegate - (JuceFileChooserDelegate*) initWithFilters: (StringArray*) filters_ { - [super init]; - filters = filters_; - return self; + [super init]; + filters = filters_; + return self; } - (void) dealloc { - delete filters; - [super dealloc]; + delete filters; + [super dealloc]; } - (BOOL) panel: (id) sender shouldShowFilename: (NSString*) filename { - const String fname (nsStringToJuce (filename)); + const String fname (nsStringToJuce (filename)); - for (int i = filters->size(); --i >= 0;) - if (fname.matchesWildcard ((*filters)[i], true)) - return true; + for (int i = filters->size(); --i >= 0;) + if (fname.matchesWildcard ((*filters)[i], true)) + return true; - return File (fname).isDirectory(); + return File (fname).isDirectory(); } @end BEGIN_JUCE_NAMESPACE void FileChooser::showPlatformDialog (OwnedArray& results, - const String& title, - const File& currentFileOrDirectory, - const String& filter, - bool selectsDirectory, - bool selectsFiles, - bool isSaveDialogue, - bool warnAboutOverwritingExistingFiles, - bool selectMultipleFiles, - FilePreviewComponent* extraInfoComponent) + const String& title, + const File& currentFileOrDirectory, + const String& filter, + bool selectsDirectory, + bool selectsFiles, + bool isSaveDialogue, + bool warnAboutOverwritingExistingFiles, + bool selectMultipleFiles, + FilePreviewComponent* extraInfoComponent) { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - StringArray* filters = new StringArray(); - filters->addTokens (filter.replaceCharacters (T(",:"), T(";;")), T(";"), 0); - filters->trim(); - filters->removeEmptyStrings(); + StringArray* filters = new StringArray(); + filters->addTokens (filter.replaceCharacters (T(",:"), T(";;")), T(";"), 0); + filters->trim(); + filters->removeEmptyStrings(); - JuceFileChooserDelegate* delegate = [[JuceFileChooserDelegate alloc] initWithFilters: filters]; - [delegate autorelease]; + JuceFileChooserDelegate* delegate = [[JuceFileChooserDelegate alloc] initWithFilters: filters]; + [delegate autorelease]; - NSSavePanel* panel = isSaveDialogue ? [NSSavePanel savePanel] - : [NSOpenPanel openPanel]; + NSSavePanel* panel = isSaveDialogue ? [NSSavePanel savePanel] + : [NSOpenPanel openPanel]; - [panel setTitle: juceStringToNS (title)]; + [panel setTitle: juceStringToNS (title)]; - if (! isSaveDialogue) - { - NSOpenPanel* openPanel = (NSOpenPanel*) panel; - [openPanel setCanChooseDirectories: selectsDirectory]; - [openPanel setCanChooseFiles: selectsFiles]; - [openPanel setAllowsMultipleSelection: selectMultipleFiles]; - } + if (! isSaveDialogue) + { + NSOpenPanel* openPanel = (NSOpenPanel*) panel; + [openPanel setCanChooseDirectories: selectsDirectory]; + [openPanel setCanChooseFiles: selectsFiles]; + [openPanel setAllowsMultipleSelection: selectMultipleFiles]; + } - [panel setDelegate: delegate]; + [panel setDelegate: delegate]; - String directory, filename; + String directory, filename; - if (currentFileOrDirectory.isDirectory()) - { - directory = currentFileOrDirectory.getFullPathName(); - } - else - { - directory = currentFileOrDirectory.getParentDirectory().getFullPathName(); - filename = currentFileOrDirectory.getFileName(); - } + if (currentFileOrDirectory.isDirectory()) + { + directory = currentFileOrDirectory.getFullPathName(); + } + else + { + directory = currentFileOrDirectory.getParentDirectory().getFullPathName(); + filename = currentFileOrDirectory.getFileName(); + } - if ([panel runModalForDirectory: juceStringToNS (directory) - file: juceStringToNS (filename)] - == NSOKButton) - { - if (isSaveDialogue) - { - results.add (new File (nsStringToJuce ([panel filename]))); - } - else - { - NSOpenPanel* openPanel = (NSOpenPanel*) panel; - NSArray* urls = [openPanel filenames]; - for (unsigned int i = 0; i < [urls count]; ++i) - { - NSString* f = [urls objectAtIndex: i]; - results.add (new File (nsStringToJuce (f))); - } - } - } + if ([panel runModalForDirectory: juceStringToNS (directory) + file: juceStringToNS (filename)] + == NSOKButton) + { + if (isSaveDialogue) + { + results.add (new File (nsStringToJuce ([panel filename]))); + } + else + { + NSOpenPanel* openPanel = (NSOpenPanel*) panel; + NSArray* urls = [openPanel filenames]; + for (unsigned int i = 0; i < [urls count]; ++i) + { + NSString* f = [urls objectAtIndex: i]; + results.add (new File (nsStringToJuce (f))); + } + } + } - [panel setDelegate: nil]; + [panel setDelegate: nil]; } #else void FileChooser::showPlatformDialog (OwnedArray& results, - const String& title, - const File& currentFileOrDirectory, - const String& filter, - bool selectsDirectory, - bool selectsFiles, - bool isSaveDialogue, - bool warnAboutOverwritingExistingFiles, - bool selectMultipleFiles, - FilePreviewComponent* extraInfoComponent) + const String& title, + const File& currentFileOrDirectory, + const String& filter, + bool selectsDirectory, + bool selectsFiles, + bool isSaveDialogue, + bool warnAboutOverwritingExistingFiles, + bool selectMultipleFiles, + FilePreviewComponent* extraInfoComponent) { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - jassertfalse //xxx to do + jassertfalse //xxx to do } #endif @@ -270527,287 +248087,287 @@ void FileChooser::showPlatformDialog (OwnedArray& results, #define theMovie ((QTMovie*) movie) QuickTimeMovieComponent::QuickTimeMovieComponent() - : movie (0) + : movie (0) { - setOpaque (true); - setVisible (true); + setOpaque (true); + setVisible (true); - QTMovieView* view = [[QTMovieView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)]; - setView (view); + QTMovieView* view = [[QTMovieView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)]; + setView (view); } QuickTimeMovieComponent::~QuickTimeMovieComponent() { - closeMovie(); - setView (0); + closeMovie(); + setView (0); } bool QuickTimeMovieComponent::isQuickTimeAvailable() throw() { - return true; + return true; } static QTMovie* openMovieFromStream (InputStream* movieStream, File& movieFile) { - // unfortunately, QTMovie objects can only be created on the main thread.. - jassert (MessageManager::getInstance()->isThisTheMessageThread()); + // unfortunately, QTMovie objects can only be created on the main thread.. + jassert (MessageManager::getInstance()->isThisTheMessageThread()); - QTMovie* movie = 0; + QTMovie* movie = 0; - FileInputStream* const fin = dynamic_cast (movieStream); + FileInputStream* const fin = dynamic_cast (movieStream); - if (fin != 0) - { - movieFile = fin->getFile(); - movie = [QTMovie movieWithFile: juceStringToNS (movieFile.getFullPathName()) - error: nil]; - } - else - { - MemoryBlock temp; - movieStream->readIntoMemoryBlock (temp); + if (fin != 0) + { + movieFile = fin->getFile(); + movie = [QTMovie movieWithFile: juceStringToNS (movieFile.getFullPathName()) + error: nil]; + } + else + { + MemoryBlock temp; + movieStream->readIntoMemoryBlock (temp); - const char* const suffixesToTry[] = { ".mov", ".mp3", ".avi", ".m4a" }; + const char* const suffixesToTry[] = { ".mov", ".mp3", ".avi", ".m4a" }; - for (int i = 0; i < numElementsInArray (suffixesToTry); ++i) - { - movie = [QTMovie movieWithDataReference: [QTDataReference dataReferenceWithReferenceToData: [NSData dataWithBytes: temp.getData() - length: temp.getSize()] - name: [NSString stringWithUTF8String: suffixesToTry[i]] - MIMEType: @""] - error: nil]; + for (int i = 0; i < numElementsInArray (suffixesToTry); ++i) + { + movie = [QTMovie movieWithDataReference: [QTDataReference dataReferenceWithReferenceToData: [NSData dataWithBytes: temp.getData() + length: temp.getSize()] + name: [NSString stringWithUTF8String: suffixesToTry[i]] + MIMEType: @""] + error: nil]; - if (movie != 0) - break; - } - } + if (movie != 0) + break; + } + } - return movie; + return movie; } bool QuickTimeMovieComponent::loadMovie (const File& movieFile_, - const bool isControllerVisible_) + const bool isControllerVisible_) { - return loadMovie ((InputStream*) movieFile_.createInputStream(), isControllerVisible_); + return loadMovie ((InputStream*) movieFile_.createInputStream(), isControllerVisible_); } bool QuickTimeMovieComponent::loadMovie (InputStream* movieStream, - const bool controllerVisible_) + const bool controllerVisible_) { - closeMovie(); + closeMovie(); - if (getPeer() == 0) - { - // To open a movie, this component must be visible inside a functioning window, so that - // the QT control can be assigned to the window. - jassertfalse - return false; - } + if (getPeer() == 0) + { + // To open a movie, this component must be visible inside a functioning window, so that + // the QT control can be assigned to the window. + jassertfalse + return false; + } - movie = openMovieFromStream (movieStream, movieFile); + movie = openMovieFromStream (movieStream, movieFile); - [theMovie retain]; - QTMovieView* view = (QTMovieView*) getView(); - [view setMovie: theMovie]; - [view setControllerVisible: controllerVisible_]; - setLooping (looping); + [theMovie retain]; + QTMovieView* view = (QTMovieView*) getView(); + [view setMovie: theMovie]; + [view setControllerVisible: controllerVisible_]; + setLooping (looping); - return movie != nil; + return movie != nil; } bool QuickTimeMovieComponent::loadMovie (const URL& movieURL, - const bool isControllerVisible_) + const bool isControllerVisible_) { - // unfortunately, QTMovie objects can only be created on the main thread.. - jassert (MessageManager::getInstance()->isThisTheMessageThread()); + // unfortunately, QTMovie objects can only be created on the main thread.. + jassert (MessageManager::getInstance()->isThisTheMessageThread()); - closeMovie(); + closeMovie(); - if (getPeer() == 0) - { - // To open a movie, this component must be visible inside a functioning window, so that - // the QT control can be assigned to the window. - jassertfalse - return false; - } + if (getPeer() == 0) + { + // To open a movie, this component must be visible inside a functioning window, so that + // the QT control can be assigned to the window. + jassertfalse + return false; + } - NSURL* url = [NSURL URLWithString: juceStringToNS (movieURL.toString (true))]; - NSError* err; - if ([QTMovie canInitWithURL: url]) - movie = [QTMovie movieWithURL: url error: &err]; + NSURL* url = [NSURL URLWithString: juceStringToNS (movieURL.toString (true))]; + NSError* err; + if ([QTMovie canInitWithURL: url]) + movie = [QTMovie movieWithURL: url error: &err]; - [theMovie retain]; - QTMovieView* view = (QTMovieView*) getView(); - [view setMovie: theMovie]; - [view setControllerVisible: controllerVisible]; - setLooping (looping); + [theMovie retain]; + QTMovieView* view = (QTMovieView*) getView(); + [view setMovie: theMovie]; + [view setControllerVisible: controllerVisible]; + setLooping (looping); - return movie != nil; + return movie != nil; } void QuickTimeMovieComponent::closeMovie() { - stop(); - QTMovieView* view = (QTMovieView*) getView(); - [view setMovie: nil]; - [theMovie release]; - movie = 0; - movieFile = File::nonexistent; + stop(); + QTMovieView* view = (QTMovieView*) getView(); + [view setMovie: nil]; + [theMovie release]; + movie = 0; + movieFile = File::nonexistent; } bool QuickTimeMovieComponent::isMovieOpen() const { - return movie != nil; + return movie != nil; } const File QuickTimeMovieComponent::getCurrentMovieFile() const { - return movieFile; + return movieFile; } void QuickTimeMovieComponent::play() { - [theMovie play]; + [theMovie play]; } void QuickTimeMovieComponent::stop() { - [theMovie stop]; + [theMovie stop]; } bool QuickTimeMovieComponent::isPlaying() const { - return movie != 0 && [theMovie rate] != 0; + return movie != 0 && [theMovie rate] != 0; } void QuickTimeMovieComponent::setPosition (const double seconds) { - if (movie != 0) - { - QTTime t; - t.timeValue = (uint64) (100000.0 * seconds); - t.timeScale = 100000; - t.flags = 0; + if (movie != 0) + { + QTTime t; + t.timeValue = (uint64) (100000.0 * seconds); + t.timeScale = 100000; + t.flags = 0; - [theMovie setCurrentTime: t]; - } + [theMovie setCurrentTime: t]; + } } double QuickTimeMovieComponent::getPosition() const { - if (movie == 0) - return 0.0; + if (movie == 0) + return 0.0; - QTTime t = [theMovie currentTime]; - return t.timeValue / (double) t.timeScale; + QTTime t = [theMovie currentTime]; + return t.timeValue / (double) t.timeScale; } void QuickTimeMovieComponent::setSpeed (const float newSpeed) { - [theMovie setRate: newSpeed]; + [theMovie setRate: newSpeed]; } double QuickTimeMovieComponent::getMovieDuration() const { - if (movie == 0) - return 0.0; + if (movie == 0) + return 0.0; - QTTime t = [theMovie duration]; - return t.timeValue / (double) t.timeScale; + QTTime t = [theMovie duration]; + return t.timeValue / (double) t.timeScale; } void QuickTimeMovieComponent::setLooping (const bool shouldLoop) { - looping = shouldLoop; + looping = shouldLoop; - [theMovie setAttribute: [NSNumber numberWithBool: shouldLoop] - forKey: QTMovieLoopsAttribute]; + [theMovie setAttribute: [NSNumber numberWithBool: shouldLoop] + forKey: QTMovieLoopsAttribute]; } bool QuickTimeMovieComponent::isLooping() const { - return looping; + return looping; } void QuickTimeMovieComponent::setMovieVolume (const float newVolume) { - [theMovie setVolume: newVolume]; + [theMovie setVolume: newVolume]; } float QuickTimeMovieComponent::getMovieVolume() const { - return movie != 0 ? [theMovie volume] : 0.0f; + return movie != 0 ? [theMovie volume] : 0.0f; } void QuickTimeMovieComponent::getMovieNormalSize (int& width, int& height) const { - width = 0; - height = 0; + width = 0; + height = 0; - if (movie != 0) - { - NSSize s = [[theMovie attributeForKey: QTMovieNaturalSizeAttribute] sizeValue]; - width = (int) s.width; - height = (int) s.height; - } + if (movie != 0) + { + NSSize s = [[theMovie attributeForKey: QTMovieNaturalSizeAttribute] sizeValue]; + width = (int) s.width; + height = (int) s.height; + } } void QuickTimeMovieComponent::paint (Graphics& g) { - if (movie == 0) - g.fillAll (Colours::black); + if (movie == 0) + g.fillAll (Colours::black); } bool QuickTimeMovieComponent::isControllerVisible() const { - return controllerVisible; + return controllerVisible; } void QuickTimeMovieComponent::goToStart() { - setPosition (0.0); + setPosition (0.0); } void QuickTimeMovieComponent::setBoundsWithCorrectAspectRatio (const Rectangle& spaceToFitWithin, - const RectanglePlacement& placement) + const RectanglePlacement& placement) { - int normalWidth, normalHeight; - getMovieNormalSize (normalWidth, normalHeight); + int normalWidth, normalHeight; + getMovieNormalSize (normalWidth, normalHeight); - if (normalWidth > 0 && normalHeight > 0 && ! spaceToFitWithin.isEmpty()) - { - double x = 0.0, y = 0.0, w = normalWidth, h = normalHeight; + if (normalWidth > 0 && normalHeight > 0 && ! spaceToFitWithin.isEmpty()) + { + double x = 0.0, y = 0.0, w = normalWidth, h = normalHeight; - placement.applyTo (x, y, w, h, - spaceToFitWithin.getX(), spaceToFitWithin.getY(), - spaceToFitWithin.getWidth(), spaceToFitWithin.getHeight()); + placement.applyTo (x, y, w, h, + spaceToFitWithin.getX(), spaceToFitWithin.getY(), + spaceToFitWithin.getWidth(), spaceToFitWithin.getHeight()); - if (w > 0 && h > 0) - { - setBounds (roundDoubleToInt (x), roundDoubleToInt (y), - roundDoubleToInt (w), roundDoubleToInt (h)); - } - } - else - { - setBounds (spaceToFitWithin); - } + if (w > 0 && h > 0) + { + setBounds (roundToInt (x), roundToInt (y), + roundToInt (w), roundToInt (h)); + } + } + else + { + setBounds (spaceToFitWithin); + } } #if ! (JUCE_MAC && JUCE_64BIT) bool juce_OpenQuickTimeMovieFromStream (InputStream* movieStream, Movie& result, Handle& dataHandle) { - if (movieStream == 0) - return false; + if (movieStream == 0) + return false; - File file; - QTMovie* movie = openMovieFromStream (movieStream, file); + File file; + QTMovie* movie = openMovieFromStream (movieStream, file); - if (movie != nil) - result = [movie quickTimeMovie]; + if (movie != nil) + result = [movie quickTimeMovie]; - return movie != nil; + return movie != nil; } #endif @@ -270826,9 +248386,9 @@ END_JUCE_NAMESPACE @interface OpenDiskDevice : NSObject { - DRDevice* device; + DRDevice* device; - NSMutableArray* tracks; + NSMutableArray* tracks; } - (OpenDiskDevice*) initWithDevice: (DRDevice*) device; @@ -270837,15 +248397,15 @@ END_JUCE_NAMESPACE - (int) getNumAvailableAudioBlocks; - (void) addSourceTrack: (JUCE_NAMESPACE::AudioSource*) source numSamples: (int) numSamples_; - (void) burn: (JUCE_NAMESPACE::AudioCDBurner::BurnProgressListener*) listener errorString: (JUCE_NAMESPACE::String*) error - ejectAfterwards: (bool) shouldEject isFake: (bool) peformFakeBurnForTesting; + ejectAfterwards: (bool) shouldEject isFake: (bool) peformFakeBurnForTesting; @end #define AudioTrackProducer MakeObjCClassName(AudioTrackProducer) @interface AudioTrackProducer : NSObject { - JUCE_NAMESPACE::AudioSource* source; - int readPosition, lengthInFrames; + JUCE_NAMESPACE::AudioSource* source; + int readPosition, lengthInFrames; } - (AudioTrackProducer*) init: (int) lengthInFrames; @@ -270857,123 +248417,123 @@ END_JUCE_NAMESPACE - (BOOL) cleanupTrackAfterVerification:(DRTrack*)track; - (uint64_t) estimateLengthOfTrack:(DRTrack*)track; - (BOOL) prepareTrack:(DRTrack*)track forBurn:(DRBurn*)burn - toMedia:(NSDictionary*)mediaInfo; + toMedia:(NSDictionary*)mediaInfo; - (BOOL) prepareTrackForVerification:(DRTrack*)track; - (uint32_t) produceDataForTrack:(DRTrack*)track intoBuffer:(char*)buffer - length:(uint32_t)bufferLength atAddress:(uint64_t)address - blockSize:(uint32_t)blockSize ioFlags:(uint32_t*)flags; + length:(uint32_t)bufferLength atAddress:(uint64_t)address + blockSize:(uint32_t)blockSize ioFlags:(uint32_t*)flags; - (uint32_t) producePreGapForTrack:(DRTrack*)track - intoBuffer:(char*)buffer length:(uint32_t)bufferLength - atAddress:(uint64_t)address blockSize:(uint32_t)blockSize - ioFlags:(uint32_t*)flags; + intoBuffer:(char*)buffer length:(uint32_t)bufferLength + atAddress:(uint64_t)address blockSize:(uint32_t)blockSize + ioFlags:(uint32_t*)flags; - (BOOL) verifyDataForTrack:(DRTrack*)track inBuffer:(const char*)buffer - length:(uint32_t)bufferLength atAddress:(uint64_t)address - blockSize:(uint32_t)blockSize ioFlags:(uint32_t*)flags; + length:(uint32_t)bufferLength atAddress:(uint64_t)address + blockSize:(uint32_t)blockSize ioFlags:(uint32_t*)flags; - (uint32_t) producePreGapForTrack:(DRTrack*)track - intoBuffer:(char*)buffer length:(uint32_t)bufferLength - atAddress:(uint64_t)address blockSize:(uint32_t)blockSize - ioFlags:(uint32_t*)flags; + intoBuffer:(char*)buffer length:(uint32_t)bufferLength + atAddress:(uint64_t)address blockSize:(uint32_t)blockSize + ioFlags:(uint32_t*)flags; @end @implementation OpenDiskDevice - (OpenDiskDevice*) initWithDevice: (DRDevice*) device_ { - [super init]; + [super init]; - device = device_; - tracks = [[NSMutableArray alloc] init]; - return self; + device = device_; + tracks = [[NSMutableArray alloc] init]; + return self; } - (void) dealloc { - [tracks release]; - [super dealloc]; + [tracks release]; + [super dealloc]; } - (bool) isDiskPresent { - return [device isValid] - && [[[device status] objectForKey: DRDeviceMediaStateKey] - isEqualTo: DRDeviceMediaStateMediaPresent]; + return [device isValid] + && [[[device status] objectForKey: DRDeviceMediaStateKey] + isEqualTo: DRDeviceMediaStateMediaPresent]; } - (int) getNumAvailableAudioBlocks { - return [[[[device status] objectForKey: DRDeviceMediaInfoKey] - objectForKey: DRDeviceMediaBlocksFreeKey] intValue]; + return [[[[device status] objectForKey: DRDeviceMediaInfoKey] + objectForKey: DRDeviceMediaBlocksFreeKey] intValue]; } - (void) addSourceTrack: (JUCE_NAMESPACE::AudioSource*) source_ numSamples: (int) numSamples_ { - AudioTrackProducer* p = [[AudioTrackProducer alloc] initWithAudioSource: source_ numSamples: numSamples_]; - DRTrack* t = [[DRTrack alloc] initWithProducer: p]; - [p setupTrackProperties: t]; + AudioTrackProducer* p = [[AudioTrackProducer alloc] initWithAudioSource: source_ numSamples: numSamples_]; + DRTrack* t = [[DRTrack alloc] initWithProducer: p]; + [p setupTrackProperties: t]; - [tracks addObject: t]; + [tracks addObject: t]; - [t release]; - [p release]; + [t release]; + [p release]; } - (void) burn: (JUCE_NAMESPACE::AudioCDBurner::BurnProgressListener*) listener errorString: (JUCE_NAMESPACE::String*) error - ejectAfterwards: (bool) shouldEject isFake: (bool) peformFakeBurnForTesting + ejectAfterwards: (bool) shouldEject isFake: (bool) peformFakeBurnForTesting { - DRBurn* burn = [DRBurn burnForDevice: device]; + DRBurn* burn = [DRBurn burnForDevice: device]; - if (! [device acquireExclusiveAccess]) - { - *error = "Couldn't open or write to the CD device"; - return; - } + if (! [device acquireExclusiveAccess]) + { + *error = "Couldn't open or write to the CD device"; + return; + } - [device acquireMediaReservation]; + [device acquireMediaReservation]; - NSMutableDictionary* d = [[burn properties] mutableCopy]; - [d autorelease]; - [d setObject: [NSNumber numberWithBool: peformFakeBurnForTesting] forKey: DRBurnTestingKey]; - [d setObject: [NSNumber numberWithBool: false] forKey: DRBurnVerifyDiscKey]; - [d setObject: (shouldEject ? DRBurnCompletionActionEject : DRBurnCompletionActionMount) - forKey: DRBurnCompletionActionKey]; - [burn setProperties: d]; + NSMutableDictionary* d = [[burn properties] mutableCopy]; + [d autorelease]; + [d setObject: [NSNumber numberWithBool: peformFakeBurnForTesting] forKey: DRBurnTestingKey]; + [d setObject: [NSNumber numberWithBool: false] forKey: DRBurnVerifyDiscKey]; + [d setObject: (shouldEject ? DRBurnCompletionActionEject : DRBurnCompletionActionMount) + forKey: DRBurnCompletionActionKey]; + [burn setProperties: d]; - [burn writeLayout: tracks]; + [burn writeLayout: tracks]; - for (;;) - { - JUCE_NAMESPACE::Thread::sleep (300); - float progress = [[[burn status] objectForKey: DRStatusPercentCompleteKey] floatValue]; + for (;;) + { + JUCE_NAMESPACE::Thread::sleep (300); + float progress = [[[burn status] objectForKey: DRStatusPercentCompleteKey] floatValue]; - if (listener != 0 && listener->audioCDBurnProgress (progress)) - { - [burn abort]; - *error = "User cancelled the write operation"; - break; - } + if (listener != 0 && listener->audioCDBurnProgress (progress)) + { + [burn abort]; + *error = "User cancelled the write operation"; + break; + } - if ([[[burn status] objectForKey: DRStatusStateKey] isEqualTo: DRStatusStateFailed]) - { - *error = "Write operation failed"; - break; - } - else if ([[[burn status] objectForKey: DRStatusStateKey] isEqualTo: DRStatusStateDone]) - { - break; - } + if ([[[burn status] objectForKey: DRStatusStateKey] isEqualTo: DRStatusStateFailed]) + { + *error = "Write operation failed"; + break; + } + else if ([[[burn status] objectForKey: DRStatusStateKey] isEqualTo: DRStatusStateDone]) + { + break; + } - NSString* err = (NSString*) [[[burn status] objectForKey: DRErrorStatusKey] - objectForKey: DRErrorStatusErrorStringKey]; + NSString* err = (NSString*) [[[burn status] objectForKey: DRErrorStatusKey] + objectForKey: DRErrorStatusErrorStringKey]; - if ([err length] > 0) - { - *error = JUCE_NAMESPACE::String::fromUTF8 ((JUCE_NAMESPACE::uint8*) [err UTF8String]); - break; - } - } + if ([err length] > 0) + { + *error = JUCE_NAMESPACE::String::fromUTF8 ((JUCE_NAMESPACE::uint8*) [err UTF8String]); + break; + } + } - [device releaseMediaReservation]; - [device releaseExclusiveAccess]; + [device releaseMediaReservation]; + [device releaseExclusiveAccess]; } @end @@ -270981,44 +248541,44 @@ END_JUCE_NAMESPACE - (AudioTrackProducer*) init: (int) lengthInFrames_ { - lengthInFrames = lengthInFrames_; - readPosition = 0; - return self; + lengthInFrames = lengthInFrames_; + readPosition = 0; + return self; } - (void) setupTrackProperties: (DRTrack*) track { - NSMutableDictionary* p = [[track properties] mutableCopy]; - [p setObject:[DRMSF msfWithFrames: lengthInFrames] forKey: DRTrackLengthKey]; - [p setObject:[NSNumber numberWithUnsignedShort:2352] forKey: DRBlockSizeKey]; - [p setObject:[NSNumber numberWithInt:0] forKey: DRDataFormKey]; - [p setObject:[NSNumber numberWithInt:0] forKey: DRBlockTypeKey]; - [p setObject:[NSNumber numberWithInt:0] forKey: DRTrackModeKey]; - [p setObject:[NSNumber numberWithInt:0] forKey: DRSessionFormatKey]; + NSMutableDictionary* p = [[track properties] mutableCopy]; + [p setObject:[DRMSF msfWithFrames: lengthInFrames] forKey: DRTrackLengthKey]; + [p setObject:[NSNumber numberWithUnsignedShort:2352] forKey: DRBlockSizeKey]; + [p setObject:[NSNumber numberWithInt:0] forKey: DRDataFormKey]; + [p setObject:[NSNumber numberWithInt:0] forKey: DRBlockTypeKey]; + [p setObject:[NSNumber numberWithInt:0] forKey: DRTrackModeKey]; + [p setObject:[NSNumber numberWithInt:0] forKey: DRSessionFormatKey]; - [track setProperties: p]; - [p release]; + [track setProperties: p]; + [p release]; } - (AudioTrackProducer*) initWithAudioSource: (JUCE_NAMESPACE::AudioSource*) source_ numSamples: (int) lengthInSamples { - AudioTrackProducer* s = [self init: (lengthInSamples + 587) / 588]; + AudioTrackProducer* s = [self init: (lengthInSamples + 587) / 588]; - if (s != nil) - s->source = source_; + if (s != nil) + s->source = source_; - return s; + return s; } - (void) dealloc { - if (source != 0) - { - source->releaseResources(); - delete source; - } + if (source != 0) + { + source->releaseResources(); + delete source; + } - [super dealloc]; + [super dealloc]; } - (void) cleanupTrackAfterBurn: (DRTrack*) track @@ -271027,79 +248587,79 @@ END_JUCE_NAMESPACE - (BOOL) cleanupTrackAfterVerification: (DRTrack*) track { - return true; + return true; } - (uint64_t) estimateLengthOfTrack: (DRTrack*) track { - return lengthInFrames; + return lengthInFrames; } - (BOOL) prepareTrack: (DRTrack*) track forBurn: (DRBurn*) burn - toMedia: (NSDictionary*) mediaInfo + toMedia: (NSDictionary*) mediaInfo { - if (source != 0) - source->prepareToPlay (44100 / 75, 44100); + if (source != 0) + source->prepareToPlay (44100 / 75, 44100); - readPosition = 0; - return true; + readPosition = 0; + return true; } - (BOOL) prepareTrackForVerification: (DRTrack*) track { - if (source != 0) - source->prepareToPlay (44100 / 75, 44100); + if (source != 0) + source->prepareToPlay (44100 / 75, 44100); - return true; + return true; } - (uint32_t) produceDataForTrack: (DRTrack*) track intoBuffer: (char*) buffer - length: (uint32_t) bufferLength atAddress: (uint64_t) address - blockSize: (uint32_t) blockSize ioFlags: (uint32_t*) flags + length: (uint32_t) bufferLength atAddress: (uint64_t) address + blockSize: (uint32_t) blockSize ioFlags: (uint32_t*) flags { - if (source != 0) - { - const int numSamples = JUCE_NAMESPACE::jmin (bufferLength / 4, (lengthInFrames * (44100 / 75)) - readPosition); + if (source != 0) + { + const int numSamples = JUCE_NAMESPACE::jmin ((int) bufferLength / 4, (lengthInFrames * (44100 / 75)) - readPosition); - if (numSamples > 0) - { - JUCE_NAMESPACE::AudioSampleBuffer tempBuffer (2, numSamples); + if (numSamples > 0) + { + JUCE_NAMESPACE::AudioSampleBuffer tempBuffer (2, numSamples); - JUCE_NAMESPACE::AudioSourceChannelInfo info; - info.buffer = &tempBuffer; - info.startSample = 0; - info.numSamples = numSamples; + JUCE_NAMESPACE::AudioSourceChannelInfo info; + info.buffer = &tempBuffer; + info.startSample = 0; + info.numSamples = numSamples; - source->getNextAudioBlock (info); + source->getNextAudioBlock (info); - JUCE_NAMESPACE::AudioDataConverters::convertFloatToInt16LE (tempBuffer.getSampleData (0), - buffer, numSamples, 4); - JUCE_NAMESPACE::AudioDataConverters::convertFloatToInt16LE (tempBuffer.getSampleData (1), - buffer + 2, numSamples, 4); + JUCE_NAMESPACE::AudioDataConverters::convertFloatToInt16LE (tempBuffer.getSampleData (0), + buffer, numSamples, 4); + JUCE_NAMESPACE::AudioDataConverters::convertFloatToInt16LE (tempBuffer.getSampleData (1), + buffer + 2, numSamples, 4); - readPosition += numSamples; - } + readPosition += numSamples; + } - return numSamples * 4; - } + return numSamples * 4; + } - return 0; + return 0; } - (uint32_t) producePreGapForTrack: (DRTrack*) track - intoBuffer: (char*) buffer length: (uint32_t) bufferLength - atAddress: (uint64_t) address blockSize: (uint32_t) blockSize - ioFlags: (uint32_t*) flags + intoBuffer: (char*) buffer length: (uint32_t) bufferLength + atAddress: (uint64_t) address blockSize: (uint32_t) blockSize + ioFlags: (uint32_t*) flags { - zeromem (buffer, bufferLength); - return bufferLength; + zeromem (buffer, bufferLength); + return bufferLength; } - (BOOL) verifyDataForTrack: (DRTrack*) track inBuffer: (const char*) buffer - length: (uint32_t) bufferLength atAddress: (uint64_t) address - blockSize: (uint32_t) blockSize ioFlags: (uint32_t*) flags + length: (uint32_t) bufferLength atAddress: (uint64_t) address + blockSize: (uint32_t) blockSize ioFlags: (uint32_t*) flags { - return true; + return true; } @end @@ -271107,114 +248667,114 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE AudioCDBurner::AudioCDBurner (const int deviceIndex) - : internal (0) + : internal (0) { - OpenDiskDevice* dev = [[OpenDiskDevice alloc] initWithDevice: [[DRDevice devices] objectAtIndex: deviceIndex]]; + OpenDiskDevice* dev = [[OpenDiskDevice alloc] initWithDevice: [[DRDevice devices] objectAtIndex: deviceIndex]]; - internal = (void*) dev; + internal = (void*) dev; } AudioCDBurner::~AudioCDBurner() { - OpenDiskDevice* dev = (OpenDiskDevice*) internal; + OpenDiskDevice* dev = (OpenDiskDevice*) internal; - if (dev != 0) - [dev release]; + if (dev != 0) + [dev release]; } AudioCDBurner* AudioCDBurner::openDevice (const int deviceIndex) { - ScopedPointer b (new AudioCDBurner (deviceIndex)); + ScopedPointer b (new AudioCDBurner (deviceIndex)); - if (b->internal == 0) - b = 0; + if (b->internal == 0) + b = 0; - return b.release(); + return b.release(); } static NSArray* findDiskBurnerDevices() { - NSMutableArray* results = [NSMutableArray array]; - NSArray* devs = [DRDevice devices]; + NSMutableArray* results = [NSMutableArray array]; + NSArray* devs = [DRDevice devices]; - if (devs != 0) - { - int num = [devs count]; - int i; - for (i = 0; i < num; ++i) - { - NSDictionary* dic = [[devs objectAtIndex: i] info]; - NSString* name = [dic valueForKey: DRDeviceProductNameKey]; - if (name != nil) - [results addObject: name]; - } - } + if (devs != 0) + { + int num = [devs count]; + int i; + for (i = 0; i < num; ++i) + { + NSDictionary* dic = [[devs objectAtIndex: i] info]; + NSString* name = [dic valueForKey: DRDeviceProductNameKey]; + if (name != nil) + [results addObject: name]; + } + } - return results; + return results; } const StringArray AudioCDBurner::findAvailableDevices() { - NSArray* names = findDiskBurnerDevices(); - StringArray s; + NSArray* names = findDiskBurnerDevices(); + StringArray s; - for (unsigned int i = 0; i < [names count]; ++i) - s.add (String::fromUTF8 ((JUCE_NAMESPACE::uint8*) [[names objectAtIndex: i] UTF8String])); + for (unsigned int i = 0; i < [names count]; ++i) + s.add (String::fromUTF8 ((JUCE_NAMESPACE::uint8*) [[names objectAtIndex: i] UTF8String])); - return s; + return s; } bool AudioCDBurner::isDiskPresent() const { - OpenDiskDevice* dev = (OpenDiskDevice*) internal; + OpenDiskDevice* dev = (OpenDiskDevice*) internal; - return dev != 0 && [dev isDiskPresent]; + return dev != 0 && [dev isDiskPresent]; } int AudioCDBurner::getNumAvailableAudioBlocks() const { - OpenDiskDevice* dev = (OpenDiskDevice*) internal; + OpenDiskDevice* dev = (OpenDiskDevice*) internal; - return [dev getNumAvailableAudioBlocks]; + return [dev getNumAvailableAudioBlocks]; } bool AudioCDBurner::addAudioTrack (AudioSource* source, int numSamps) { - OpenDiskDevice* dev = (OpenDiskDevice*) internal; + OpenDiskDevice* dev = (OpenDiskDevice*) internal; - if (dev != 0) - { - [dev addSourceTrack: source numSamples: numSamps]; - return true; - } + if (dev != 0) + { + [dev addSourceTrack: source numSamples: numSamps]; + return true; + } - return false; + return false; } const String AudioCDBurner::burn (JUCE_NAMESPACE::AudioCDBurner::BurnProgressListener* listener, - const bool ejectDiscAfterwards, - const bool peformFakeBurnForTesting) + const bool ejectDiscAfterwards, + const bool peformFakeBurnForTesting) { - String error ("Couldn't open or write to the CD device"); + String error ("Couldn't open or write to the CD device"); - OpenDiskDevice* dev = (OpenDiskDevice*) internal; + OpenDiskDevice* dev = (OpenDiskDevice*) internal; - if (dev != 0) - { - error = String::empty; - [dev burn: listener - errorString: &error - ejectAfterwards: ejectDiscAfterwards - isFake: peformFakeBurnForTesting]; - } + if (dev != 0) + { + error = String::empty; + [dev burn: listener + errorString: &error + ejectAfterwards: ejectDiscAfterwards + isFake: peformFakeBurnForTesting]; + } - return error; + return error; } void AudioCDReader::ejectDisk() { - const ScopedAutoReleasePool p; - [[NSWorkspace sharedWorkspace] unmountAndEjectDeviceAtPath: juceStringToNS (volumeDir.getFullPathName())]; + const ScopedAutoReleasePool p; + [[NSWorkspace sharedWorkspace] unmountAndEjectDeviceAtPath: juceStringToNS (volumeDir.getFullPathName())]; } #endif @@ -271227,142 +248787,132 @@ void AudioCDReader::ejectDisk() struct CallbackMessagePayload { - MessageCallbackFunction* function; - void* parameter; - void* volatile result; - bool volatile hasBeenExecuted; + MessageCallbackFunction* function; + void* parameter; + void* volatile result; + bool volatile hasBeenExecuted; }; -/* When you use multiple DLLs which share similarly-named obj-c classes - like - for example having more than one juce plugin loaded into a host, then when a - method is called, the actual code that runs might actually be in a different module - than the one you expect... So any calls to library functions or statics that are - made inside obj-c methods will probably end up getting executed in a different DLL's - memory space. Not a great thing to happen - this obviously leads to bizarre crashes. - - To work around this insanity, I'm only allowing obj-c methods to make calls to - virtual methods of an object that's known to live inside the right module's space. -*/ class AppDelegateRedirector { public: - AppDelegateRedirector() - { + AppDelegateRedirector() + { #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 - runLoop = CFRunLoopGetMain(); + runLoop = CFRunLoopGetMain(); #else - runLoop = CFRunLoopGetCurrent(); + runLoop = CFRunLoopGetCurrent(); #endif - CFRunLoopSourceContext sourceContext; - zerostruct (sourceContext); - sourceContext.info = this; - sourceContext.perform = runLoopSourceCallback; - runLoopSource = CFRunLoopSourceCreate (kCFAllocatorDefault, 1, &sourceContext); - CFRunLoopAddSource (runLoop, runLoopSource, kCFRunLoopCommonModes); - } + CFRunLoopSourceContext sourceContext; + zerostruct (sourceContext); + sourceContext.info = this; + sourceContext.perform = runLoopSourceCallback; + runLoopSource = CFRunLoopSourceCreate (kCFAllocatorDefault, 1, &sourceContext); + CFRunLoopAddSource (runLoop, runLoopSource, kCFRunLoopCommonModes); + } - virtual ~AppDelegateRedirector() - { - CFRunLoopRemoveSource (runLoop, runLoopSource, kCFRunLoopCommonModes); - CFRunLoopSourceInvalidate (runLoopSource); - CFRelease (runLoopSource); + virtual ~AppDelegateRedirector() + { + CFRunLoopRemoveSource (runLoop, runLoopSource, kCFRunLoopCommonModes); + CFRunLoopSourceInvalidate (runLoopSource); + CFRelease (runLoopSource); - while (messages.size() > 0) - delete ((Message*) messages.remove(0)); - } + while (messages.size() > 0) + delete ((Message*) messages.remove(0)); + } - virtual NSApplicationTerminateReply shouldTerminate() - { - if (JUCEApplication::getInstance() != 0) - { - JUCEApplication::getInstance()->systemRequestedQuit(); - return NSTerminateCancel; - } + virtual NSApplicationTerminateReply shouldTerminate() + { + if (JUCEApplication::getInstance() != 0) + { + JUCEApplication::getInstance()->systemRequestedQuit(); + return NSTerminateCancel; + } - return NSTerminateNow; - } + return NSTerminateNow; + } - virtual BOOL openFile (const NSString* filename) - { - if (JUCEApplication::getInstance() != 0) - { - JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce (filename)); - return YES; - } + virtual BOOL openFile (const NSString* filename) + { + if (JUCEApplication::getInstance() != 0) + { + JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce (filename)); + return YES; + } - return NO; - } + return NO; + } - virtual void openFiles (NSArray* filenames) - { - StringArray files; - for (unsigned int i = 0; i < [filenames count]; ++i) - { - String filename (nsStringToJuce ((NSString*) [filenames objectAtIndex: i])); - if (filename.containsChar (T(' '))) - filename = filename.quoted('"'); + virtual void openFiles (NSArray* filenames) + { + StringArray files; + for (unsigned int i = 0; i < [filenames count]; ++i) + { + String filename (nsStringToJuce ((NSString*) [filenames objectAtIndex: i])); + if (filename.containsChar (T(' '))) + filename = filename.quoted('"'); - files.add (filename); - } + files.add (filename); + } - if (files.size() > 0 && JUCEApplication::getInstance() != 0) - { - JUCEApplication::getInstance()->anotherInstanceStarted (files.joinIntoString (T(" "))); - } - } + if (files.size() > 0 && JUCEApplication::getInstance() != 0) + { + JUCEApplication::getInstance()->anotherInstanceStarted (files.joinIntoString (T(" "))); + } + } - virtual void focusChanged() - { - juce_HandleProcessFocusChange(); - } + virtual void focusChanged() + { + juce_HandleProcessFocusChange(); + } - virtual void performCallback (CallbackMessagePayload* pl) - { - pl->result = (*pl->function) (pl->parameter); - pl->hasBeenExecuted = true; - } + virtual void performCallback (CallbackMessagePayload* pl) + { + pl->result = (*pl->function) (pl->parameter); + pl->hasBeenExecuted = true; + } - virtual void deleteSelf() - { - delete this; - } + virtual void deleteSelf() + { + delete this; + } - void postMessage (void* m) - { - messages.add (m); - CFRunLoopSourceSignal (runLoopSource); - CFRunLoopWakeUp (runLoop); - } + void postMessage (void* m) + { + messages.add (m); + CFRunLoopSourceSignal (runLoopSource); + CFRunLoopWakeUp (runLoop); + } private: - CFRunLoopRef runLoop; - CFRunLoopSourceRef runLoopSource; - Array messages; + CFRunLoopRef runLoop; + CFRunLoopSourceRef runLoopSource; + Array messages; - void runLoopCallback() - { - int numDispatched = 0; + void runLoopCallback() + { + int numDispatched = 0; - do - { - void* const nextMessage = messages.remove (0); + do + { + void* const nextMessage = messages.remove (0); - if (nextMessage == 0) - return; + if (nextMessage == 0) + return; - const ScopedAutoReleasePool pool; - MessageManager::getInstance()->deliverMessage (nextMessage); + const ScopedAutoReleasePool pool; + MessageManager::getInstance()->deliverMessage (nextMessage); - } while (++numDispatched <= 4); + } while (++numDispatched <= 4); - CFRunLoopSourceSignal (runLoopSource); - CFRunLoopWakeUp (runLoop); - } + CFRunLoopSourceSignal (runLoopSource); + CFRunLoopWakeUp (runLoop); + } - static void runLoopSourceCallback (void* info) - { - ((AppDelegateRedirector*) info)->runLoopCallback(); - } + static void runLoopSourceCallback (void* info) + { + ((AppDelegateRedirector*) info)->runLoopCallback(); + } }; END_JUCE_NAMESPACE @@ -271373,10 +248923,10 @@ using namespace JUCE_NAMESPACE; @interface JuceAppDelegate : NSObject { @private - id oldDelegate; + id oldDelegate; @public - AppDelegateRedirector* redirector; + AppDelegateRedirector* redirector; } - (JuceAppDelegate*) init; @@ -271395,85 +248945,85 @@ using namespace JUCE_NAMESPACE; - (JuceAppDelegate*) init { - [super init]; + [super init]; - redirector = new AppDelegateRedirector(); + redirector = new AppDelegateRedirector(); - NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; - if (JUCEApplication::getInstance() != 0) - { - oldDelegate = [NSApp delegate]; - [NSApp setDelegate: self]; - } - else - { - oldDelegate = 0; - [center addObserver: self selector: @selector (applicationDidResignActive:) - name: NSApplicationDidResignActiveNotification object: NSApp]; + if (JUCEApplication::getInstance() != 0) + { + oldDelegate = [NSApp delegate]; + [NSApp setDelegate: self]; + } + else + { + oldDelegate = 0; + [center addObserver: self selector: @selector (applicationDidResignActive:) + name: NSApplicationDidResignActiveNotification object: NSApp]; - [center addObserver: self selector: @selector (applicationDidBecomeActive:) - name: NSApplicationDidBecomeActiveNotification object: NSApp]; + [center addObserver: self selector: @selector (applicationDidBecomeActive:) + name: NSApplicationDidBecomeActiveNotification object: NSApp]; - [center addObserver: self selector: @selector (applicationWillUnhide:) - name: NSApplicationWillUnhideNotification object: NSApp]; - } + [center addObserver: self selector: @selector (applicationWillUnhide:) + name: NSApplicationWillUnhideNotification object: NSApp]; + } - return self; + return self; } - (void) dealloc { - if (oldDelegate != 0) - [NSApp setDelegate: oldDelegate]; + if (oldDelegate != 0) + [NSApp setDelegate: oldDelegate]; - redirector->deleteSelf(); - [super dealloc]; + redirector->deleteSelf(); + [super dealloc]; } - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication*) app { - return redirector->shouldTerminate(); + return redirector->shouldTerminate(); } - (BOOL) application: (NSApplication*) app openFile: (NSString*) filename { - return redirector->openFile (filename); + return redirector->openFile (filename); } - (void) application: (NSApplication*) sender openFiles: (NSArray*) filenames { - return redirector->openFiles (filenames); + return redirector->openFiles (filenames); } - (void) applicationDidBecomeActive: (NSNotification*) aNotification { - redirector->focusChanged(); + redirector->focusChanged(); } - (void) applicationDidResignActive: (NSNotification*) aNotification { - redirector->focusChanged(); + redirector->focusChanged(); } - (void) applicationWillUnhide: (NSNotification*) aNotification { - redirector->focusChanged(); + redirector->focusChanged(); } - (void) performCallback: (id) info { - if ([info isKindOfClass: [NSData class]]) - { - CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes]; + if ([info isKindOfClass: [NSData class]]) + { + CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes]; - if (pl != 0) - redirector->performCallback (pl); - } - else - { - jassertfalse // should never get here! - } + if (pl != 0) + redirector->performCallback (pl); + } + else + { + jassertfalse // should never get here! + } } - (void) dummyMethod {} // (used as a way of running a dummy thread) @@ -271486,180 +249036,180 @@ static JuceAppDelegate* juceAppDelegate = 0; void MessageManager::runDispatchLoop() { - if (! quitMessagePosted) // check that the quit message wasn't already posted.. - { - const ScopedAutoReleasePool pool; + if (! quitMessagePosted) // check that the quit message wasn't already posted.. + { + const ScopedAutoReleasePool pool; - // must only be called by the message thread! - jassert (isThisTheMessageThread()); + // must only be called by the message thread! + jassert (isThisTheMessageThread()); #if JUCE_CATCH_UNHANDLED_EXCEPTIONS - @try - { - [NSApp run]; - } - @catch (NSException* e) - { - // An AppKit exception will kill the app, but at least this provides a chance to log it., - std::runtime_error ex (std::string ("NSException: ") + [[e name] UTF8String] + ", Reason:" + [[e reason] UTF8String]); - JUCEApplication::sendUnhandledException (&ex, __FILE__, __LINE__); - } - @finally - { - } + @try + { + [NSApp run]; + } + @catch (NSException* e) + { + // An AppKit exception will kill the app, but at least this provides a chance to log it., + std::runtime_error ex (std::string ("NSException: ") + [[e name] UTF8String] + ", Reason:" + [[e reason] UTF8String]); + JUCEApplication::sendUnhandledException (&ex, __FILE__, __LINE__); + } + @finally + { + } #else - [NSApp run]; + [NSApp run]; #endif - } + } } void MessageManager::stopDispatchLoop() { - quitMessagePosted = true; - [NSApp stop: nil]; - [NSApp activateIgnoringOtherApps: YES]; // (if the app is inactive, it sits there and ignores the quit request until the next time it gets activated) - [NSEvent startPeriodicEventsAfterDelay: 0 withPeriod: 0.1]; + quitMessagePosted = true; + [NSApp stop: nil]; + [NSApp activateIgnoringOtherApps: YES]; // (if the app is inactive, it sits there and ignores the quit request until the next time it gets activated) + [NSEvent startPeriodicEventsAfterDelay: 0 withPeriod: 0.1]; } static bool isEventBlockedByModalComps (NSEvent* e) { - if (Component::getNumCurrentlyModalComponents() == 0) - return false; + if (Component::getNumCurrentlyModalComponents() == 0) + return false; - NSWindow* const w = [e window]; - if (w == 0 || [w worksWhenModal]) - return false; + NSWindow* const w = [e window]; + if (w == 0 || [w worksWhenModal]) + return false; - bool isKey = false, isInputAttempt = false; + bool isKey = false, isInputAttempt = false; - switch ([e type]) - { - case NSKeyDown: - case NSKeyUp: - isKey = isInputAttempt = true; - break; + switch ([e type]) + { + case NSKeyDown: + case NSKeyUp: + isKey = isInputAttempt = true; + break; - case NSLeftMouseDown: - case NSRightMouseDown: - case NSOtherMouseDown: - isInputAttempt = true; - break; + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + isInputAttempt = true; + break; - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: - case NSOtherMouseDragged: - if (Component::getComponentUnderMouse() != 0) - return false; - break; + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + case NSOtherMouseDragged: + if (Component::getComponentUnderMouse() != 0) + return false; + break; - case NSMouseMoved: - case NSMouseEntered: - case NSMouseExited: - case NSCursorUpdate: - case NSScrollWheel: - case NSTabletPoint: - case NSTabletProximity: - break; + case NSMouseMoved: + case NSMouseEntered: + case NSMouseExited: + case NSCursorUpdate: + case NSScrollWheel: + case NSTabletPoint: + case NSTabletProximity: + break; - default: - return false; - } + default: + return false; + } - for (int i = ComponentPeer::getNumPeers(); --i >= 0;) - { - ComponentPeer* const peer = ComponentPeer::getPeer (i); - NSView* const compView = (NSView*) peer->getNativeHandle(); + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) + { + ComponentPeer* const peer = ComponentPeer::getPeer (i); + NSView* const compView = (NSView*) peer->getNativeHandle(); - if ([compView window] == w) - { - if (isKey) - { - if (compView == [w firstResponder]) - return false; - } - else - { - if (NSPointInRect ([compView convertPoint: [e locationInWindow] fromView: nil], - [compView bounds])) - return false; - } - } - } + if ([compView window] == w) + { + if (isKey) + { + if (compView == [w firstResponder]) + return false; + } + else + { + if (NSPointInRect ([compView convertPoint: [e locationInWindow] fromView: nil], + [compView bounds])) + return false; + } + } + } - if (isInputAttempt) - { - if (! [NSApp isActive]) - [NSApp activateIgnoringOtherApps: YES]; + if (isInputAttempt) + { + if (! [NSApp isActive]) + [NSApp activateIgnoringOtherApps: YES]; - Component* const modal = Component::getCurrentlyModalComponent (0); - if (modal != 0) - modal->inputAttemptWhenModal(); - } + Component* const modal = Component::getCurrentlyModalComponent (0); + if (modal != 0) + modal->inputAttemptWhenModal(); + } - return true; + return true; } bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) { - const ScopedAutoReleasePool pool; - jassert (isThisTheMessageThread()); // must only be called by the message thread + const ScopedAutoReleasePool pool; + jassert (isThisTheMessageThread()); // must only be called by the message thread - uint32 endTime = Time::getMillisecondCounter() + millisecondsToRunFor; + uint32 endTime = Time::getMillisecondCounter() + millisecondsToRunFor; - while (! quitMessagePosted) - { - const ScopedAutoReleasePool pool2; + while (! quitMessagePosted) + { + const ScopedAutoReleasePool pool2; - CFRunLoopRunInMode (kCFRunLoopDefaultMode, 0.001, true); + CFRunLoopRunInMode (kCFRunLoopDefaultMode, 0.001, true); - NSEvent* e = [NSApp nextEventMatchingMask: NSAnyEventMask - untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.001] - inMode: NSDefaultRunLoopMode - dequeue: YES]; + NSEvent* e = [NSApp nextEventMatchingMask: NSAnyEventMask + untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.001] + inMode: NSDefaultRunLoopMode + dequeue: YES]; - if (e != 0 && ! isEventBlockedByModalComps (e)) - [NSApp sendEvent: e]; + if (e != 0 && ! isEventBlockedByModalComps (e)) + [NSApp sendEvent: e]; - if (Time::getMillisecondCounter() >= endTime) - break; - } + if (Time::getMillisecondCounter() >= endTime) + break; + } - return ! quitMessagePosted; + return ! quitMessagePosted; } void MessageManager::doPlatformSpecificInitialisation() { - if (juceAppDelegate == 0) - juceAppDelegate = [[JuceAppDelegate alloc] init]; + if (juceAppDelegate == 0) + juceAppDelegate = [[JuceAppDelegate alloc] init]; - // This launches a dummy thread, which forces Cocoa to initialise NSThreads - // correctly (needed prior to 10.5) - if (! [NSThread isMultiThreaded]) - [NSThread detachNewThreadSelector: @selector (dummyMethod) - toTarget: juceAppDelegate - withObject: nil]; + // This launches a dummy thread, which forces Cocoa to initialise NSThreads + // correctly (needed prior to 10.5) + if (! [NSThread isMultiThreaded]) + [NSThread detachNewThreadSelector: @selector (dummyMethod) + toTarget: juceAppDelegate + withObject: nil]; - initialiseMainMenu(); + initialiseMainMenu(); } void MessageManager::doPlatformSpecificShutdown() { - if (juceAppDelegate != 0) - { - [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate]; - [[NSNotificationCenter defaultCenter] removeObserver: juceAppDelegate]; - [juceAppDelegate release]; - juceAppDelegate = 0; - } + if (juceAppDelegate != 0) + { + [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate]; + [[NSNotificationCenter defaultCenter] removeObserver: juceAppDelegate]; + [juceAppDelegate release]; + juceAppDelegate = 0; + } } bool juce_postMessageToSystemQueue (void* message) { - juceAppDelegate->redirector->postMessage (message); - return true; + juceAppDelegate->redirector->postMessage (message); + return true; } void MessageManager::broadcastMessage (const String& value) throw() @@ -271667,35 +249217,35 @@ void MessageManager::broadcastMessage (const String& value) throw() } void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* callback, - void* data) + void* data) { - if (isThisTheMessageThread()) - { - return (*callback) (data); - } - else - { - // If a thread has a MessageManagerLock and then tries to call this method, it'll - // deadlock because the message manager is blocked from running, so can never - // call your function.. - jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager()); + if (isThisTheMessageThread()) + { + return (*callback) (data); + } + else + { + // If a thread has a MessageManagerLock and then tries to call this method, it'll + // deadlock because the message manager is blocked from running, so can never + // call your function.. + jassert (! MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - CallbackMessagePayload cmp; - cmp.function = callback; - cmp.parameter = data; - cmp.result = 0; - cmp.hasBeenExecuted = false; + CallbackMessagePayload cmp; + cmp.function = callback; + cmp.parameter = data; + cmp.result = 0; + cmp.hasBeenExecuted = false; - [juceAppDelegate performSelectorOnMainThread: @selector (performCallback:) - withObject: [NSData dataWithBytesNoCopy: &cmp - length: sizeof (cmp) - freeWhenDone: NO] - waitUntilDone: YES]; + [juceAppDelegate performSelectorOnMainThread: @selector (performCallback:) + withObject: [NSData dataWithBytesNoCopy: &cmp + length: sizeof (cmp) + freeWhenDone: NO] + waitUntilDone: YES]; - return cmp.result; - } + return cmp.result; + } } #endif @@ -271714,37 +249264,37 @@ END_JUCE_NAMESPACE @interface DownloadClickDetector : NSObject { - JUCE_NAMESPACE::WebBrowserComponent* ownerComponent; + JUCE_NAMESPACE::WebBrowserComponent* ownerComponent; } - (DownloadClickDetector*) initWithWebBrowserOwner: (JUCE_NAMESPACE::WebBrowserComponent*) ownerComponent; - (void) webView: (WebView*) webView decidePolicyForNavigationAction: (NSDictionary*) actionInformation - request: (NSURLRequest*) request - frame: (WebFrame*) frame - decisionListener: (id) listener; + request: (NSURLRequest*) request + frame: (WebFrame*) frame + decisionListener: (id) listener; @end @implementation DownloadClickDetector - (DownloadClickDetector*) initWithWebBrowserOwner: (JUCE_NAMESPACE::WebBrowserComponent*) ownerComponent_ { - [super init]; - ownerComponent = ownerComponent_; - return self; + [super init]; + ownerComponent = ownerComponent_; + return self; } - (void) webView: (WebView*) sender decidePolicyForNavigationAction: (NSDictionary*) actionInformation - request: (NSURLRequest*) request - frame: (WebFrame*) frame - decisionListener: (id ) listener + request: (NSURLRequest*) request + frame: (WebFrame*) frame + decisionListener: (id ) listener { - NSURL* url = [actionInformation valueForKey: @"WebActionOriginalURLKey"]; + NSURL* url = [actionInformation valueForKey: @"WebActionOriginalURLKey"]; - if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString]))) - [listener use]; - else - [listener ignore]; + if (ownerComponent->pageAboutToLoad (nsStringToJuce ([url absoluteString]))) + [listener use]; + else + [listener ignore]; } @end @@ -271754,136 +249304,136 @@ BEGIN_JUCE_NAMESPACE class WebBrowserComponentInternal : public NSViewComponent { public: - WebBrowserComponentInternal (WebBrowserComponent* owner) - { - webView = [[WebView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) - frameName: @"" - groupName: @""]; - setView (webView); + WebBrowserComponentInternal (WebBrowserComponent* owner) + { + webView = [[WebView alloc] initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f) + frameName: @"" + groupName: @""]; + setView (webView); - clickListener = [[DownloadClickDetector alloc] initWithWebBrowserOwner: owner]; - [webView setPolicyDelegate: clickListener]; - } + clickListener = [[DownloadClickDetector alloc] initWithWebBrowserOwner: owner]; + [webView setPolicyDelegate: clickListener]; + } - ~WebBrowserComponentInternal() - { - [webView setPolicyDelegate: nil]; - [clickListener release]; - setView (0); - } + ~WebBrowserComponentInternal() + { + [webView setPolicyDelegate: nil]; + [clickListener release]; + setView (0); + } - void goToURL (const String& url, - const StringArray* headers, - const MemoryBlock* postData) - { - NSMutableURLRequest* r - = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: juceStringToNS (url)] - cachePolicy: NSURLRequestUseProtocolCachePolicy - timeoutInterval: 30.0]; + void goToURL (const String& url, + const StringArray* headers, + const MemoryBlock* postData) + { + NSMutableURLRequest* r + = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: juceStringToNS (url)] + cachePolicy: NSURLRequestUseProtocolCachePolicy + timeoutInterval: 30.0]; - if (postData != 0 && postData->getSize() > 0) - { - [r setHTTPMethod: @"POST"]; - [r setHTTPBody: [NSData dataWithBytes: postData->getData() - length: postData->getSize()]]; - } + if (postData != 0 && postData->getSize() > 0) + { + [r setHTTPMethod: @"POST"]; + [r setHTTPBody: [NSData dataWithBytes: postData->getData() + length: postData->getSize()]]; + } - if (headers != 0) - { - for (int i = 0; i < headers->size(); ++i) - { - const String headerName ((*headers)[i].upToFirstOccurrenceOf (T(":"), false, false).trim()); - const String headerValue ((*headers)[i].fromFirstOccurrenceOf (T(":"), false, false).trim()); + if (headers != 0) + { + for (int i = 0; i < headers->size(); ++i) + { + const String headerName ((*headers)[i].upToFirstOccurrenceOf (T(":"), false, false).trim()); + const String headerValue ((*headers)[i].fromFirstOccurrenceOf (T(":"), false, false).trim()); - [r setValue: juceStringToNS (headerValue) - forHTTPHeaderField: juceStringToNS (headerName)]; - } - } + [r setValue: juceStringToNS (headerValue) + forHTTPHeaderField: juceStringToNS (headerName)]; + } + } - stop(); - [[webView mainFrame] loadRequest: r]; - } + stop(); + [[webView mainFrame] loadRequest: r]; + } - void goBack() - { - [webView goBack]; - } + void goBack() + { + [webView goBack]; + } - void goForward() - { - [webView goForward]; - } + void goForward() + { + [webView goForward]; + } - void stop() - { - [webView stopLoading: nil]; - } + void stop() + { + [webView stopLoading: nil]; + } - void refresh() - { - [webView reload: nil]; - } + void refresh() + { + [webView reload: nil]; + } private: - WebView* webView; - DownloadClickDetector* clickListener; + WebView* webView; + DownloadClickDetector* clickListener; }; WebBrowserComponent::WebBrowserComponent (const bool unloadPageWhenBrowserIsHidden_) - : browser (0), - blankPageShown (false), - unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_) + : browser (0), + blankPageShown (false), + unloadPageWhenBrowserIsHidden (unloadPageWhenBrowserIsHidden_) { - setOpaque (true); + setOpaque (true); - addAndMakeVisible (browser = new WebBrowserComponentInternal (this)); + addAndMakeVisible (browser = new WebBrowserComponentInternal (this)); } WebBrowserComponent::~WebBrowserComponent() { - deleteAndZero (browser); + deleteAndZero (browser); } void WebBrowserComponent::goToURL (const String& url, - const StringArray* headers, - const MemoryBlock* postData) + const StringArray* headers, + const MemoryBlock* postData) { - lastURL = url; + lastURL = url; - lastHeaders.clear(); - if (headers != 0) - lastHeaders = *headers; + lastHeaders.clear(); + if (headers != 0) + lastHeaders = *headers; - lastPostData.setSize (0); - if (postData != 0) - lastPostData = *postData; + lastPostData.setSize (0); + if (postData != 0) + lastPostData = *postData; - blankPageShown = false; + blankPageShown = false; - browser->goToURL (url, headers, postData); + browser->goToURL (url, headers, postData); } void WebBrowserComponent::stop() { - browser->stop(); + browser->stop(); } void WebBrowserComponent::goBack() { - lastURL = String::empty; - blankPageShown = false; - browser->goBack(); + lastURL = String::empty; + blankPageShown = false; + browser->goBack(); } void WebBrowserComponent::goForward() { - lastURL = String::empty; - browser->goForward(); + lastURL = String::empty; + browser->goForward(); } void WebBrowserComponent::refresh() { - browser->refresh(); + browser->refresh(); } void WebBrowserComponent::paint (Graphics& g) @@ -271892,52 +249442,52 @@ void WebBrowserComponent::paint (Graphics& g) void WebBrowserComponent::checkWindowAssociation() { - if (isShowing()) - { - if (blankPageShown) - goBack(); - } - else - { - if (unloadPageWhenBrowserIsHidden && ! blankPageShown) - { - // when the component becomes invisible, some stuff like flash - // carries on playing audio, so we need to force it onto a blank - // page to avoid this, (and send it back when it's made visible again). + if (isShowing()) + { + if (blankPageShown) + goBack(); + } + else + { + if (unloadPageWhenBrowserIsHidden && ! blankPageShown) + { + // when the component becomes invisible, some stuff like flash + // carries on playing audio, so we need to force it onto a blank + // page to avoid this, (and send it back when it's made visible again). - blankPageShown = true; - browser->goToURL ("about:blank", 0, 0); - } - } + blankPageShown = true; + browser->goToURL ("about:blank", 0, 0); + } + } } void WebBrowserComponent::reloadLastURL() { - if (lastURL.isNotEmpty()) - { - goToURL (lastURL, &lastHeaders, &lastPostData); - lastURL = String::empty; - } + if (lastURL.isNotEmpty()) + { + goToURL (lastURL, &lastHeaders, &lastPostData); + lastURL = String::empty; + } } void WebBrowserComponent::parentHierarchyChanged() { - checkWindowAssociation(); + checkWindowAssociation(); } void WebBrowserComponent::resized() { - browser->setSize (getWidth(), getHeight()); + browser->setSize (getWidth(), getHeight()); } void WebBrowserComponent::visibilityChanged() { - checkWindowAssociation(); + checkWindowAssociation(); } bool WebBrowserComponent::pageAboutToLoad (const String& url) { - return true; + return true; } #else @@ -271951,8 +249501,8 @@ WebBrowserComponent::~WebBrowserComponent() } void WebBrowserComponent::goToURL (const String& url, - const StringArray* headers, - const MemoryBlock* postData) + const StringArray* headers, + const MemoryBlock* postData) { } @@ -271998,7 +249548,7 @@ void WebBrowserComponent::visibilityChanged() bool WebBrowserComponent::pageAboutToLoad (const String& url) { - return true; + return true; } #endif @@ -272026,12 +249576,12 @@ bool WebBrowserComponent::pageAboutToLoad (const String& url) #if JUCE_COREAUDIO_ERROR_LOGGING_ENABLED static bool logAnyErrors_CoreAudio (const OSStatus err, const int lineNum) { - if (err == noErr) - return true; + if (err == noErr) + return true; - Logger::writeToLog (T("CoreAudio error: ") + String (lineNum) + T(" - ") + String::toHexString ((int)err)); - jassertfalse - return false; + Logger::writeToLog (T("CoreAudio error: ") + String (lineNum) + T(" - ") + String::toHexString ((int)err)); + jassertfalse + return false; } #define OK(a) logAnyErrors_CoreAudio (a, __LINE__) @@ -272043,1249 +249593,1249 @@ class CoreAudioInternal : public Timer { public: - CoreAudioInternal (AudioDeviceID id) - : inputLatency (0), - outputLatency (0), - callback (0), + CoreAudioInternal (AudioDeviceID id) + : inputLatency (0), + outputLatency (0), + callback (0), #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 - audioProcID (0), + audioProcID (0), #endif - inputDevice (0), - isSlaveDevice (false), - deviceID (id), - started (false), - sampleRate (0), - bufferSize (512), - numInputChans (0), - numOutputChans (0), - callbacksAllowed (true), - numInputChannelInfos (0), - numOutputChannelInfos (0) - { - jassert (deviceID != 0); - - updateDetailsFromDevice(); - - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioObjectPropertySelectorWildcard; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementWildcard; - - AudioObjectAddPropertyListener (deviceID, &pa, deviceListenerProc, this); - } - - ~CoreAudioInternal() - { - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioObjectPropertySelectorWildcard; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementWildcard; - - AudioObjectRemovePropertyListener (deviceID, &pa, deviceListenerProc, this); - - stop (false); - delete inputDevice; - } - - void allocateTempBuffers() - { - const int tempBufSize = bufferSize + 4; - audioBuffer.calloc ((numInputChans + numOutputChans) * tempBufSize); - - tempInputBuffers.calloc (numInputChans + 2); - tempOutputBuffers.calloc (numOutputChans + 2); - - int i, count = 0; - for (i = 0; i < numInputChans; ++i) - tempInputBuffers[i] = audioBuffer + count++ * tempBufSize; - - for (i = 0; i < numOutputChans; ++i) - tempOutputBuffers[i] = audioBuffer + count++ * tempBufSize; - } - - // returns the number of actual available channels - void fillInChannelInfo (const bool input) - { - int chanNum = 0; - UInt32 size; - - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyStreamConfiguration; - pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - pa.mElement = kAudioObjectPropertyElementMaster; - - if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) - { - HeapBlock bufList; - bufList.calloc (size, 1); - - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, bufList))) - { - const int numStreams = bufList->mNumberBuffers; - - for (int i = 0; i < numStreams; ++i) - { - const AudioBuffer& b = bufList->mBuffers[i]; - - for (unsigned int j = 0; j < b.mNumberChannels; ++j) - { - String name; - - { - uint8 channelName [256]; - zerostruct (channelName); - UInt32 nameSize = sizeof (channelName); - UInt32 channelNum = chanNum + 1; - pa.mSelector = kAudioDevicePropertyChannelName; - - if (AudioObjectGetPropertyData (deviceID, &pa, sizeof (channelNum), &channelNum, &nameSize, channelName) == noErr) - name = String::fromUTF8 (channelName, nameSize); - } - - if (input) - { - if (activeInputChans[chanNum]) - { - inputChannelInfo [numInputChannelInfos].streamNum = i; - inputChannelInfo [numInputChannelInfos].dataOffsetSamples = j; - inputChannelInfo [numInputChannelInfos].dataStrideSamples = b.mNumberChannels; - ++numInputChannelInfos; - } - - if (name.isEmpty()) - name << "Input " << (chanNum + 1); - - inChanNames.add (name); - } - else - { - if (activeOutputChans[chanNum]) - { - outputChannelInfo [numOutputChannelInfos].streamNum = i; - outputChannelInfo [numOutputChannelInfos].dataOffsetSamples = j; - outputChannelInfo [numOutputChannelInfos].dataStrideSamples = b.mNumberChannels; - ++numOutputChannelInfos; - } - - if (name.isEmpty()) - name << "Output " << (chanNum + 1); - - outChanNames.add (name); - } - - ++chanNum; - } - } - } - } - } - - void updateDetailsFromDevice() - { - stopTimer(); - - if (deviceID == 0) - return; - - const ScopedLock sl (callbackLock); - - Float64 sr; - UInt32 size = sizeof (Float64); - - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyNominalSampleRate; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementMaster; - - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &sr))) - sampleRate = sr; - - UInt32 framesPerBuf; - size = sizeof (framesPerBuf); - - pa.mSelector = kAudioDevicePropertyBufferFrameSize; - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &framesPerBuf))) - { - bufferSize = framesPerBuf; - allocateTempBuffers(); - } - - bufferSizes.clear(); - - pa.mSelector = kAudioDevicePropertyBufferFrameSizeRange; - - if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) - { - HeapBlock ranges; - ranges.calloc (size, 1); - - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, ranges))) - { - bufferSizes.add ((int) ranges[0].mMinimum); - - for (int i = 32; i < 8192; i += 32) - { - for (int j = size / sizeof (AudioValueRange); --j >= 0;) - { - if (i >= ranges[j].mMinimum && i <= ranges[j].mMaximum) - { - bufferSizes.addIfNotAlreadyThere (i); - break; - } - } - } - - if (bufferSize > 0) - bufferSizes.addIfNotAlreadyThere (bufferSize); - } - } - - if (bufferSizes.size() == 0 && bufferSize > 0) - bufferSizes.add (bufferSize); - - sampleRates.clear(); - const double possibleRates[] = { 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 }; - String rates; - - pa.mSelector = kAudioDevicePropertyAvailableNominalSampleRates; - - if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) - { - HeapBlock ranges; - ranges.calloc (size, 1); - - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, ranges))) - { - for (int i = 0; i < numElementsInArray (possibleRates); ++i) - { - bool ok = false; - - for (int j = size / sizeof (AudioValueRange); --j >= 0;) - if (possibleRates[i] >= ranges[j].mMinimum - 2 && possibleRates[i] <= ranges[j].mMaximum + 2) - ok = true; - - if (ok) - { - sampleRates.add (possibleRates[i]); - rates << possibleRates[i] << T(" "); - } - } - } - } - - if (sampleRates.size() == 0 && sampleRate > 0) - { - sampleRates.add (sampleRate); - rates << sampleRate; - } - - log (T("sr: ") + rates); - - inputLatency = 0; - outputLatency = 0; - UInt32 lat; - size = sizeof (lat); - pa.mSelector = kAudioDevicePropertyLatency; - pa.mScope = kAudioDevicePropertyScopeInput; - //if (AudioDeviceGetProperty (deviceID, 0, true, kAudioDevicePropertyLatency, &size, &lat) == noErr) - if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &lat) == noErr) - inputLatency = (int) lat; - - pa.mScope = kAudioDevicePropertyScopeOutput; - size = sizeof (lat); - - if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &lat) == noErr) - outputLatency = (int) lat; - - log (T("lat: ") + String (inputLatency) + T(" ") + String (outputLatency)); - - inChanNames.clear(); - outChanNames.clear(); - - inputChannelInfo.calloc (numInputChans + 2); - numInputChannelInfos = 0; - - outputChannelInfo.calloc (numOutputChans + 2); - numOutputChannelInfos = 0; - - fillInChannelInfo (true); - fillInChannelInfo (false); - } - - const StringArray getSources (bool input) - { - StringArray s; - HeapBlock types; - const int num = getAllDataSourcesForDevice (deviceID, input, types); - - for (int i = 0; i < num; ++i) - { - AudioValueTranslation avt; - char buffer[256]; - - avt.mInputData = (void*) &(types[i]); - avt.mInputDataSize = sizeof (UInt32); - avt.mOutputData = buffer; - avt.mOutputDataSize = 256; - - UInt32 transSize = sizeof (avt); - - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyDataSourceNameForID; - pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - pa.mElement = kAudioObjectPropertyElementMaster; - - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &transSize, &avt))) - { - DBG (buffer); - s.add (buffer); - } - } - - return s; - } - - int getCurrentSourceIndex (bool input) const - { - OSType currentSourceID = 0; - UInt32 size = sizeof (currentSourceID); - int result = -1; - - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyDataSource; - pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - pa.mElement = kAudioObjectPropertyElementMaster; - - if (deviceID != 0) - { - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, ¤tSourceID))) - { - HeapBlock types; - const int num = getAllDataSourcesForDevice (deviceID, input, types); - - for (int i = 0; i < num; ++i) - { - if (types[num] == currentSourceID) - { - result = i; - break; - } - } - } - } - - return result; - } - - void setCurrentSourceIndex (int index, bool input) - { - if (deviceID != 0) - { - HeapBlock types; - const int num = getAllDataSourcesForDevice (deviceID, input, types); - - if (((unsigned int) index) < (unsigned int) num) - { - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyDataSource; - pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - pa.mElement = kAudioObjectPropertyElementMaster; - - OSType typeId = types[index]; - - OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (typeId), &typeId)); - } - } - } - - const String reopen (const BitArray& inputChannels, - const BitArray& outputChannels, - double newSampleRate, - int bufferSizeSamples) - { - String error; - log ("CoreAudio reopen"); - callbacksAllowed = false; - stopTimer(); - - stop (false); - - activeInputChans = inputChannels; - activeInputChans.setRange (inChanNames.size(), - activeInputChans.getHighestBit() + 1 - inChanNames.size(), - false); - - activeOutputChans = outputChannels; - activeOutputChans.setRange (outChanNames.size(), - activeOutputChans.getHighestBit() + 1 - outChanNames.size(), - false); - - numInputChans = activeInputChans.countNumberOfSetBits(); - numOutputChans = activeOutputChans.countNumberOfSetBits(); - - // set sample rate - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyNominalSampleRate; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementMaster; - Float64 sr = newSampleRate; - - if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (sr), &sr))) - { - error = "Couldn't change sample rate"; - } - else - { - // change buffer size - UInt32 framesPerBuf = bufferSizeSamples; - pa.mSelector = kAudioDevicePropertyBufferFrameSize; - - if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (framesPerBuf), &framesPerBuf))) - { - error = "Couldn't change buffer size"; - } - else - { - // Annoyingly, after changing the rate and buffer size, some devices fail to - // correctly report their new settings until some random time in the future, so - // after calling updateDetailsFromDevice, we need to manually bodge these values - // to make sure we're using the correct numbers.. - updateDetailsFromDevice(); - sampleRate = newSampleRate; - bufferSize = bufferSizeSamples; - - if (sampleRates.size() == 0) - error = "Device has no available sample-rates"; - else if (bufferSizes.size() == 0) - error = "Device has no available buffer-sizes"; - else if (inputDevice != 0) - error = inputDevice->reopen (inputChannels, - outputChannels, - newSampleRate, - bufferSizeSamples); - } - } - - callbacksAllowed = true; - return error; - } - - bool start (AudioIODeviceCallback* cb) - { - if (! started) - { - callback = 0; - - if (deviceID != 0) - { + inputDevice (0), + isSlaveDevice (false), + deviceID (id), + started (false), + sampleRate (0), + bufferSize (512), + numInputChans (0), + numOutputChans (0), + callbacksAllowed (true), + numInputChannelInfos (0), + numOutputChannelInfos (0) + { + jassert (deviceID != 0); + + updateDetailsFromDevice(); + + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioObjectPropertySelectorWildcard; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementWildcard; + + AudioObjectAddPropertyListener (deviceID, &pa, deviceListenerProc, this); + } + + ~CoreAudioInternal() + { + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioObjectPropertySelectorWildcard; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementWildcard; + + AudioObjectRemovePropertyListener (deviceID, &pa, deviceListenerProc, this); + + stop (false); + delete inputDevice; + } + + void allocateTempBuffers() + { + const int tempBufSize = bufferSize + 4; + audioBuffer.calloc ((numInputChans + numOutputChans) * tempBufSize); + + tempInputBuffers.calloc (numInputChans + 2); + tempOutputBuffers.calloc (numOutputChans + 2); + + int i, count = 0; + for (i = 0; i < numInputChans; ++i) + tempInputBuffers[i] = audioBuffer + count++ * tempBufSize; + + for (i = 0; i < numOutputChans; ++i) + tempOutputBuffers[i] = audioBuffer + count++ * tempBufSize; + } + + // returns the number of actual available channels + void fillInChannelInfo (const bool input) + { + int chanNum = 0; + UInt32 size; + + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyStreamConfiguration; + pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + pa.mElement = kAudioObjectPropertyElementMaster; + + if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) + { + HeapBlock bufList; + bufList.calloc (size, 1); + + if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, bufList))) + { + const int numStreams = bufList->mNumberBuffers; + + for (int i = 0; i < numStreams; ++i) + { + const AudioBuffer& b = bufList->mBuffers[i]; + + for (unsigned int j = 0; j < b.mNumberChannels; ++j) + { + String name; + + { + uint8 channelName [256]; + zerostruct (channelName); + UInt32 nameSize = sizeof (channelName); + UInt32 channelNum = chanNum + 1; + pa.mSelector = kAudioDevicePropertyChannelName; + + if (AudioObjectGetPropertyData (deviceID, &pa, sizeof (channelNum), &channelNum, &nameSize, channelName) == noErr) + name = String::fromUTF8 (channelName, nameSize); + } + + if (input) + { + if (activeInputChans[chanNum]) + { + inputChannelInfo [numInputChannelInfos].streamNum = i; + inputChannelInfo [numInputChannelInfos].dataOffsetSamples = j; + inputChannelInfo [numInputChannelInfos].dataStrideSamples = b.mNumberChannels; + ++numInputChannelInfos; + } + + if (name.isEmpty()) + name << "Input " << (chanNum + 1); + + inChanNames.add (name); + } + else + { + if (activeOutputChans[chanNum]) + { + outputChannelInfo [numOutputChannelInfos].streamNum = i; + outputChannelInfo [numOutputChannelInfos].dataOffsetSamples = j; + outputChannelInfo [numOutputChannelInfos].dataStrideSamples = b.mNumberChannels; + ++numOutputChannelInfos; + } + + if (name.isEmpty()) + name << "Output " << (chanNum + 1); + + outChanNames.add (name); + } + + ++chanNum; + } + } + } + } + } + + void updateDetailsFromDevice() + { + stopTimer(); + + if (deviceID == 0) + return; + + const ScopedLock sl (callbackLock); + + Float64 sr; + UInt32 size = sizeof (Float64); + + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyNominalSampleRate; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementMaster; + + if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &sr))) + sampleRate = sr; + + UInt32 framesPerBuf; + size = sizeof (framesPerBuf); + + pa.mSelector = kAudioDevicePropertyBufferFrameSize; + if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &framesPerBuf))) + { + bufferSize = framesPerBuf; + allocateTempBuffers(); + } + + bufferSizes.clear(); + + pa.mSelector = kAudioDevicePropertyBufferFrameSizeRange; + + if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) + { + HeapBlock ranges; + ranges.calloc (size, 1); + + if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, ranges))) + { + bufferSizes.add ((int) ranges[0].mMinimum); + + for (int i = 32; i < 8192; i += 32) + { + for (int j = size / (int) sizeof (AudioValueRange); --j >= 0;) + { + if (i >= ranges[j].mMinimum && i <= ranges[j].mMaximum) + { + bufferSizes.addIfNotAlreadyThere (i); + break; + } + } + } + + if (bufferSize > 0) + bufferSizes.addIfNotAlreadyThere (bufferSize); + } + } + + if (bufferSizes.size() == 0 && bufferSize > 0) + bufferSizes.add (bufferSize); + + sampleRates.clear(); + const double possibleRates[] = { 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 }; + String rates; + + pa.mSelector = kAudioDevicePropertyAvailableNominalSampleRates; + + if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) + { + HeapBlock ranges; + ranges.calloc (size, 1); + + if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, ranges))) + { + for (int i = 0; i < numElementsInArray (possibleRates); ++i) + { + bool ok = false; + + for (int j = size / (int) sizeof (AudioValueRange); --j >= 0;) + if (possibleRates[i] >= ranges[j].mMinimum - 2 && possibleRates[i] <= ranges[j].mMaximum + 2) + ok = true; + + if (ok) + { + sampleRates.add (possibleRates[i]); + rates << possibleRates[i] << T(" "); + } + } + } + } + + if (sampleRates.size() == 0 && sampleRate > 0) + { + sampleRates.add (sampleRate); + rates << sampleRate; + } + + log (T("sr: ") + rates); + + inputLatency = 0; + outputLatency = 0; + UInt32 lat; + size = sizeof (lat); + pa.mSelector = kAudioDevicePropertyLatency; + pa.mScope = kAudioDevicePropertyScopeInput; + //if (AudioDeviceGetProperty (deviceID, 0, true, kAudioDevicePropertyLatency, &size, &lat) == noErr) + if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &lat) == noErr) + inputLatency = (int) lat; + + pa.mScope = kAudioDevicePropertyScopeOutput; + size = sizeof (lat); + + if (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &lat) == noErr) + outputLatency = (int) lat; + + log (T("lat: ") + String (inputLatency) + T(" ") + String (outputLatency)); + + inChanNames.clear(); + outChanNames.clear(); + + inputChannelInfo.calloc (numInputChans + 2); + numInputChannelInfos = 0; + + outputChannelInfo.calloc (numOutputChans + 2); + numOutputChannelInfos = 0; + + fillInChannelInfo (true); + fillInChannelInfo (false); + } + + const StringArray getSources (bool input) + { + StringArray s; + HeapBlock types; + const int num = getAllDataSourcesForDevice (deviceID, input, types); + + for (int i = 0; i < num; ++i) + { + AudioValueTranslation avt; + char buffer[256]; + + avt.mInputData = (void*) &(types[i]); + avt.mInputDataSize = sizeof (UInt32); + avt.mOutputData = buffer; + avt.mOutputDataSize = 256; + + UInt32 transSize = sizeof (avt); + + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyDataSourceNameForID; + pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + pa.mElement = kAudioObjectPropertyElementMaster; + + if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &transSize, &avt))) + { + DBG (buffer); + s.add (buffer); + } + } + + return s; + } + + int getCurrentSourceIndex (bool input) const + { + OSType currentSourceID = 0; + UInt32 size = sizeof (currentSourceID); + int result = -1; + + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyDataSource; + pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + pa.mElement = kAudioObjectPropertyElementMaster; + + if (deviceID != 0) + { + if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, ¤tSourceID))) + { + HeapBlock types; + const int num = getAllDataSourcesForDevice (deviceID, input, types); + + for (int i = 0; i < num; ++i) + { + if (types[num] == currentSourceID) + { + result = i; + break; + } + } + } + } + + return result; + } + + void setCurrentSourceIndex (int index, bool input) + { + if (deviceID != 0) + { + HeapBlock types; + const int num = getAllDataSourcesForDevice (deviceID, input, types); + + if (((unsigned int) index) < (unsigned int) num) + { + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyDataSource; + pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + pa.mElement = kAudioObjectPropertyElementMaster; + + OSType typeId = types[index]; + + OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (typeId), &typeId)); + } + } + } + + const String reopen (const BitArray& inputChannels, + const BitArray& outputChannels, + double newSampleRate, + int bufferSizeSamples) + { + String error; + log ("CoreAudio reopen"); + callbacksAllowed = false; + stopTimer(); + + stop (false); + + activeInputChans = inputChannels; + activeInputChans.setRange (inChanNames.size(), + activeInputChans.getHighestBit() + 1 - inChanNames.size(), + false); + + activeOutputChans = outputChannels; + activeOutputChans.setRange (outChanNames.size(), + activeOutputChans.getHighestBit() + 1 - outChanNames.size(), + false); + + numInputChans = activeInputChans.countNumberOfSetBits(); + numOutputChans = activeOutputChans.countNumberOfSetBits(); + + // set sample rate + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyNominalSampleRate; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementMaster; + Float64 sr = newSampleRate; + + if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (sr), &sr))) + { + error = "Couldn't change sample rate"; + } + else + { + // change buffer size + UInt32 framesPerBuf = bufferSizeSamples; + pa.mSelector = kAudioDevicePropertyBufferFrameSize; + + if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (framesPerBuf), &framesPerBuf))) + { + error = "Couldn't change buffer size"; + } + else + { + // Annoyingly, after changing the rate and buffer size, some devices fail to + // correctly report their new settings until some random time in the future, so + // after calling updateDetailsFromDevice, we need to manually bodge these values + // to make sure we're using the correct numbers.. + updateDetailsFromDevice(); + sampleRate = newSampleRate; + bufferSize = bufferSizeSamples; + + if (sampleRates.size() == 0) + error = "Device has no available sample-rates"; + else if (bufferSizes.size() == 0) + error = "Device has no available buffer-sizes"; + else if (inputDevice != 0) + error = inputDevice->reopen (inputChannels, + outputChannels, + newSampleRate, + bufferSizeSamples); + } + } + + callbacksAllowed = true; + return error; + } + + bool start (AudioIODeviceCallback* cb) + { + if (! started) + { + callback = 0; + + if (deviceID != 0) + { #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 - if (OK (AudioDeviceAddIOProc (deviceID, audioIOProc, (void*) this))) + if (OK (AudioDeviceAddIOProc (deviceID, audioIOProc, (void*) this))) #else - if (OK (AudioDeviceCreateIOProcID (deviceID, audioIOProc, (void*) this, &audioProcID))) + if (OK (AudioDeviceCreateIOProcID (deviceID, audioIOProc, (void*) this, &audioProcID))) #endif - { - if (OK (AudioDeviceStart (deviceID, audioIOProc))) - { - started = true; - } - else - { + { + if (OK (AudioDeviceStart (deviceID, audioIOProc))) + { + started = true; + } + else + { #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 - OK (AudioDeviceRemoveIOProc (deviceID, audioIOProc)); + OK (AudioDeviceRemoveIOProc (deviceID, audioIOProc)); #else - OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID)); - audioProcID = 0; + OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID)); + audioProcID = 0; #endif - } - } - } - } + } + } + } + } - if (started) - { - const ScopedLock sl (callbackLock); - callback = cb; - } + if (started) + { + const ScopedLock sl (callbackLock); + callback = cb; + } - if (inputDevice != 0) - return started && inputDevice->start (cb); - else - return started; - } + if (inputDevice != 0) + return started && inputDevice->start (cb); + else + return started; + } - void stop (bool leaveInterruptRunning) - { - callbackLock.enter(); - callback = 0; - callbackLock.exit(); + void stop (bool leaveInterruptRunning) + { + callbackLock.enter(); + callback = 0; + callbackLock.exit(); - if (started - && (deviceID != 0) - && ! leaveInterruptRunning) - { - OK (AudioDeviceStop (deviceID, audioIOProc)); + if (started + && (deviceID != 0) + && ! leaveInterruptRunning) + { + OK (AudioDeviceStop (deviceID, audioIOProc)); #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 - OK (AudioDeviceRemoveIOProc (deviceID, audioIOProc)); + OK (AudioDeviceRemoveIOProc (deviceID, audioIOProc)); #else - OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID)); - audioProcID = 0; + OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID)); + audioProcID = 0; #endif - started = false; + started = false; - callbackLock.enter(); - callbackLock.exit(); + callbackLock.enter(); + callbackLock.exit(); - // wait until it's definately stopped calling back.. - for (int i = 40; --i >= 0;) - { - Thread::sleep (50); + // wait until it's definately stopped calling back.. + for (int i = 40; --i >= 0;) + { + Thread::sleep (50); - UInt32 running = 0; - UInt32 size = sizeof (running); + UInt32 running = 0; + UInt32 size = sizeof (running); - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyDeviceIsRunning; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementMaster; + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyDeviceIsRunning; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementMaster; - OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &running)); + OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, &running)); - if (running == 0) - break; - } + if (running == 0) + break; + } - callbackLock.enter(); - callbackLock.exit(); - } + callbackLock.enter(); + callbackLock.exit(); + } - if (inputDevice != 0) - inputDevice->stop (leaveInterruptRunning); - } + if (inputDevice != 0) + inputDevice->stop (leaveInterruptRunning); + } - double getSampleRate() const - { - return sampleRate; - } + double getSampleRate() const + { + return sampleRate; + } - int getBufferSize() const - { - return bufferSize; - } + int getBufferSize() const + { + return bufferSize; + } - void audioCallback (const AudioBufferList* inInputData, - AudioBufferList* outOutputData) - { - int i; - const ScopedLock sl (callbackLock); + void audioCallback (const AudioBufferList* inInputData, + AudioBufferList* outOutputData) + { + int i; + const ScopedLock sl (callbackLock); - if (callback != 0) - { - if (inputDevice == 0) - { - for (i = numInputChans; --i >= 0;) - { - const CallbackDetailsForChannel& info = inputChannelInfo[i]; - float* dest = tempInputBuffers [i]; - const float* src = ((const float*) inInputData->mBuffers[info.streamNum].mData) - + info.dataOffsetSamples; - const int stride = info.dataStrideSamples; + if (callback != 0) + { + if (inputDevice == 0) + { + for (i = numInputChans; --i >= 0;) + { + const CallbackDetailsForChannel& info = inputChannelInfo[i]; + float* dest = tempInputBuffers [i]; + const float* src = ((const float*) inInputData->mBuffers[info.streamNum].mData) + + info.dataOffsetSamples; + const int stride = info.dataStrideSamples; - if (stride != 0) // if this is zero, info is invalid - { - for (int j = bufferSize; --j >= 0;) - { - *dest++ = *src; - src += stride; - } - } - } - } + if (stride != 0) // if this is zero, info is invalid + { + for (int j = bufferSize; --j >= 0;) + { + *dest++ = *src; + src += stride; + } + } + } + } - if (! isSlaveDevice) - { - if (inputDevice == 0) - { - callback->audioDeviceIOCallback ((const float**) tempInputBuffers, - numInputChans, - tempOutputBuffers, - numOutputChans, - bufferSize); - } - else - { - jassert (inputDevice->bufferSize == bufferSize); + if (! isSlaveDevice) + { + if (inputDevice == 0) + { + callback->audioDeviceIOCallback ((const float**) tempInputBuffers, + numInputChans, + tempOutputBuffers, + numOutputChans, + bufferSize); + } + else + { + jassert (inputDevice->bufferSize == bufferSize); - // Sometimes the two linked devices seem to get their callbacks in - // parallel, so we need to lock both devices to stop the input data being - // changed while inside our callback.. - const ScopedLock sl2 (inputDevice->callbackLock); + // Sometimes the two linked devices seem to get their callbacks in + // parallel, so we need to lock both devices to stop the input data being + // changed while inside our callback.. + const ScopedLock sl2 (inputDevice->callbackLock); - callback->audioDeviceIOCallback ((const float**) inputDevice->tempInputBuffers, - inputDevice->numInputChans, - tempOutputBuffers, - numOutputChans, - bufferSize); - } + callback->audioDeviceIOCallback ((const float**) inputDevice->tempInputBuffers, + inputDevice->numInputChans, + tempOutputBuffers, + numOutputChans, + bufferSize); + } - for (i = numOutputChans; --i >= 0;) - { - const CallbackDetailsForChannel& info = outputChannelInfo[i]; - const float* src = tempOutputBuffers [i]; - float* dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) - + info.dataOffsetSamples; - const int stride = info.dataStrideSamples; + for (i = numOutputChans; --i >= 0;) + { + const CallbackDetailsForChannel& info = outputChannelInfo[i]; + const float* src = tempOutputBuffers [i]; + float* dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) + + info.dataOffsetSamples; + const int stride = info.dataStrideSamples; - if (stride != 0) // if this is zero, info is invalid - { - for (int j = bufferSize; --j >= 0;) - { - *dest = *src++; - dest += stride; - } - } - } - } - } - else - { - for (i = jmin (numOutputChans, numOutputChannelInfos); --i >= 0;) - { - const CallbackDetailsForChannel& info = outputChannelInfo[i]; - float* dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) - + info.dataOffsetSamples; - const int stride = info.dataStrideSamples; + if (stride != 0) // if this is zero, info is invalid + { + for (int j = bufferSize; --j >= 0;) + { + *dest = *src++; + dest += stride; + } + } + } + } + } + else + { + for (i = jmin (numOutputChans, numOutputChannelInfos); --i >= 0;) + { + const CallbackDetailsForChannel& info = outputChannelInfo[i]; + float* dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) + + info.dataOffsetSamples; + const int stride = info.dataStrideSamples; - if (stride != 0) // if this is zero, info is invalid - { - for (int j = bufferSize; --j >= 0;) - { - *dest = 0.0f; - dest += stride; - } - } - } - } - } + if (stride != 0) // if this is zero, info is invalid + { + for (int j = bufferSize; --j >= 0;) + { + *dest = 0.0f; + dest += stride; + } + } + } + } + } - // called by callbacks - void deviceDetailsChanged() - { - if (callbacksAllowed) - startTimer (100); - } + // called by callbacks + void deviceDetailsChanged() + { + if (callbacksAllowed) + startTimer (100); + } - void timerCallback() - { - stopTimer(); - log ("CoreAudio device changed callback"); + void timerCallback() + { + stopTimer(); + log ("CoreAudio device changed callback"); - const double oldSampleRate = sampleRate; - const int oldBufferSize = bufferSize; - updateDetailsFromDevice(); + const double oldSampleRate = sampleRate; + const int oldBufferSize = bufferSize; + updateDetailsFromDevice(); - if (oldBufferSize != bufferSize || oldSampleRate != sampleRate) - { - callbacksAllowed = false; - stop (false); - updateDetailsFromDevice(); - callbacksAllowed = true; - } - } + if (oldBufferSize != bufferSize || oldSampleRate != sampleRate) + { + callbacksAllowed = false; + stop (false); + updateDetailsFromDevice(); + callbacksAllowed = true; + } + } - CoreAudioInternal* getRelatedDevice() const - { - UInt32 size = 0; - ScopedPointer result; + CoreAudioInternal* getRelatedDevice() const + { + UInt32 size = 0; + ScopedPointer result; - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyRelatedDevices; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementMaster; + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyRelatedDevices; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementMaster; - if (deviceID != 0 - && AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size) == noErr - && size > 0) - { - HeapBlock devs; - devs.calloc (size, 1); + if (deviceID != 0 + && AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size) == noErr + && size > 0) + { + HeapBlock devs; + devs.calloc (size, 1); - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, devs))) - { - for (unsigned int i = 0; i < size / sizeof (AudioDeviceID); ++i) - { - if (devs[i] != deviceID && devs[i] != 0) - { - result = new CoreAudioInternal (devs[i]); + if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, devs))) + { + for (unsigned int i = 0; i < size / sizeof (AudioDeviceID); ++i) + { + if (devs[i] != deviceID && devs[i] != 0) + { + result = new CoreAudioInternal (devs[i]); - const bool thisIsInput = inChanNames.size() > 0 && outChanNames.size() == 0; - const bool otherIsInput = result->inChanNames.size() > 0 && result->outChanNames.size() == 0; + const bool thisIsInput = inChanNames.size() > 0 && outChanNames.size() == 0; + const bool otherIsInput = result->inChanNames.size() > 0 && result->outChanNames.size() == 0; - if (thisIsInput != otherIsInput - || (inChanNames.size() + outChanNames.size() == 0) - || (result->inChanNames.size() + result->outChanNames.size()) == 0) - break; + if (thisIsInput != otherIsInput + || (inChanNames.size() + outChanNames.size() == 0) + || (result->inChanNames.size() + result->outChanNames.size()) == 0) + break; - result = 0; - } - } - } - } + result = 0; + } + } + } + } - return result.release(); - } + return result.release(); + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - int inputLatency, outputLatency; - BitArray activeInputChans, activeOutputChans; - StringArray inChanNames, outChanNames; - Array sampleRates; - Array bufferSizes; - AudioIODeviceCallback* callback; + int inputLatency, outputLatency; + BitArray activeInputChans, activeOutputChans; + StringArray inChanNames, outChanNames; + Array sampleRates; + Array bufferSizes; + AudioIODeviceCallback* callback; #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 - AudioDeviceIOProcID audioProcID; + AudioDeviceIOProcID audioProcID; #endif - CoreAudioInternal* inputDevice; - bool isSlaveDevice; + CoreAudioInternal* inputDevice; + bool isSlaveDevice; private: - CriticalSection callbackLock; - AudioDeviceID deviceID; - bool started; - double sampleRate; - int bufferSize; - HeapBlock audioBuffer; - int numInputChans, numOutputChans; - bool callbacksAllowed; + CriticalSection callbackLock; + AudioDeviceID deviceID; + bool started; + double sampleRate; + int bufferSize; + HeapBlock audioBuffer; + int numInputChans, numOutputChans; + bool callbacksAllowed; - struct CallbackDetailsForChannel - { - int streamNum; - int dataOffsetSamples; - int dataStrideSamples; - }; + struct CallbackDetailsForChannel + { + int streamNum; + int dataOffsetSamples; + int dataStrideSamples; + }; - int numInputChannelInfos, numOutputChannelInfos; - HeapBlock inputChannelInfo, outputChannelInfo; - HeapBlock tempInputBuffers, tempOutputBuffers; + int numInputChannelInfos, numOutputChannelInfos; + HeapBlock inputChannelInfo, outputChannelInfo; + HeapBlock tempInputBuffers, tempOutputBuffers; - CoreAudioInternal (const CoreAudioInternal&); - const CoreAudioInternal& operator= (const CoreAudioInternal&); + CoreAudioInternal (const CoreAudioInternal&); + const CoreAudioInternal& operator= (const CoreAudioInternal&); - static OSStatus audioIOProc (AudioDeviceID inDevice, - const AudioTimeStamp* inNow, - const AudioBufferList* inInputData, - const AudioTimeStamp* inInputTime, - AudioBufferList* outOutputData, - const AudioTimeStamp* inOutputTime, - void* device) - { - ((CoreAudioInternal*) device)->audioCallback (inInputData, outOutputData); - return noErr; - } + static OSStatus audioIOProc (AudioDeviceID inDevice, + const AudioTimeStamp* inNow, + const AudioBufferList* inInputData, + const AudioTimeStamp* inInputTime, + AudioBufferList* outOutputData, + const AudioTimeStamp* inOutputTime, + void* device) + { + ((CoreAudioInternal*) device)->audioCallback (inInputData, outOutputData); + return noErr; + } - static OSStatus deviceListenerProc (AudioDeviceID /*inDevice*/, UInt32 /*inLine*/, const AudioObjectPropertyAddress* pa, void* inClientData) - { - CoreAudioInternal* const intern = (CoreAudioInternal*) inClientData; + static OSStatus deviceListenerProc (AudioDeviceID /*inDevice*/, UInt32 /*inLine*/, const AudioObjectPropertyAddress* pa, void* inClientData) + { + CoreAudioInternal* const intern = (CoreAudioInternal*) inClientData; - switch (pa->mSelector) - { - case kAudioDevicePropertyBufferSize: - case kAudioDevicePropertyBufferFrameSize: - case kAudioDevicePropertyNominalSampleRate: - case kAudioDevicePropertyStreamFormat: - case kAudioDevicePropertyDeviceIsAlive: - intern->deviceDetailsChanged(); - break; + switch (pa->mSelector) + { + case kAudioDevicePropertyBufferSize: + case kAudioDevicePropertyBufferFrameSize: + case kAudioDevicePropertyNominalSampleRate: + case kAudioDevicePropertyStreamFormat: + case kAudioDevicePropertyDeviceIsAlive: + intern->deviceDetailsChanged(); + break; - case kAudioDevicePropertyBufferSizeRange: - case kAudioDevicePropertyVolumeScalar: - case kAudioDevicePropertyMute: - case kAudioDevicePropertyPlayThru: - case kAudioDevicePropertyDataSource: - case kAudioDevicePropertyDeviceIsRunning: - break; - } + case kAudioDevicePropertyBufferSizeRange: + case kAudioDevicePropertyVolumeScalar: + case kAudioDevicePropertyMute: + case kAudioDevicePropertyPlayThru: + case kAudioDevicePropertyDataSource: + case kAudioDevicePropertyDeviceIsRunning: + break; + } - return noErr; - } + return noErr; + } - static int getAllDataSourcesForDevice (AudioDeviceID deviceID, const bool input, HeapBlock & types) - { - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyDataSources; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementMaster; - UInt32 size = 0; + static int getAllDataSourcesForDevice (AudioDeviceID deviceID, const bool input, HeapBlock & types) + { + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyDataSources; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementMaster; + UInt32 size = 0; - if (deviceID != 0 - && OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) - { - types.calloc (size, 1); + if (deviceID != 0 + && OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) + { + types.calloc (size, 1); - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, types))) - return size / sizeof (OSType); - } + if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, types))) + return size / (int) sizeof (OSType); + } - return 0; - } + return 0; + } }; class CoreAudioIODevice : public AudioIODevice { public: - CoreAudioIODevice (const String& deviceName, - AudioDeviceID inputDeviceId, - const int inputIndex_, - AudioDeviceID outputDeviceId, - const int outputIndex_) - : AudioIODevice (deviceName, "CoreAudio"), - inputIndex (inputIndex_), - outputIndex (outputIndex_), - isOpen_ (false), - isStarted (false) - { - internal = 0; - CoreAudioInternal* device = 0; + CoreAudioIODevice (const String& deviceName, + AudioDeviceID inputDeviceId, + const int inputIndex_, + AudioDeviceID outputDeviceId, + const int outputIndex_) + : AudioIODevice (deviceName, "CoreAudio"), + inputIndex (inputIndex_), + outputIndex (outputIndex_), + isOpen_ (false), + isStarted (false) + { + internal = 0; + CoreAudioInternal* device = 0; - if (outputDeviceId == 0 || outputDeviceId == inputDeviceId) - { - jassert (inputDeviceId != 0); + if (outputDeviceId == 0 || outputDeviceId == inputDeviceId) + { + jassert (inputDeviceId != 0); - device = new CoreAudioInternal (inputDeviceId); - } - else - { - device = new CoreAudioInternal (outputDeviceId); + device = new CoreAudioInternal (inputDeviceId); + } + else + { + device = new CoreAudioInternal (outputDeviceId); - if (inputDeviceId != 0) - { - CoreAudioInternal* secondDevice = new CoreAudioInternal (inputDeviceId); + if (inputDeviceId != 0) + { + CoreAudioInternal* secondDevice = new CoreAudioInternal (inputDeviceId); - device->inputDevice = secondDevice; - secondDevice->isSlaveDevice = true; - } - } + device->inputDevice = secondDevice; + secondDevice->isSlaveDevice = true; + } + } - internal = device; + internal = device; - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioObjectPropertySelectorWildcard; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementWildcard; + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioObjectPropertySelectorWildcard; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementWildcard; - AudioObjectAddPropertyListener (kAudioObjectSystemObject, &pa, hardwareListenerProc, internal); - } + AudioObjectAddPropertyListener (kAudioObjectSystemObject, &pa, hardwareListenerProc, internal); + } - ~CoreAudioIODevice() - { - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioObjectPropertySelectorWildcard; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementWildcard; + ~CoreAudioIODevice() + { + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioObjectPropertySelectorWildcard; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementWildcard; - AudioObjectRemovePropertyListener (kAudioObjectSystemObject, &pa, hardwareListenerProc, internal); + AudioObjectRemovePropertyListener (kAudioObjectSystemObject, &pa, hardwareListenerProc, internal); - delete internal; - } + delete internal; + } - const StringArray getOutputChannelNames() - { - return internal->outChanNames; - } + const StringArray getOutputChannelNames() + { + return internal->outChanNames; + } - const StringArray getInputChannelNames() - { - if (internal->inputDevice != 0) - return internal->inputDevice->inChanNames; - else - return internal->inChanNames; - } + const StringArray getInputChannelNames() + { + if (internal->inputDevice != 0) + return internal->inputDevice->inChanNames; + else + return internal->inChanNames; + } - int getNumSampleRates() - { - return internal->sampleRates.size(); - } + int getNumSampleRates() + { + return internal->sampleRates.size(); + } - double getSampleRate (int index) - { - return internal->sampleRates [index]; - } + double getSampleRate (int index) + { + return internal->sampleRates [index]; + } - int getNumBufferSizesAvailable() - { - return internal->bufferSizes.size(); - } + int getNumBufferSizesAvailable() + { + return internal->bufferSizes.size(); + } - int getBufferSizeSamples (int index) - { - return internal->bufferSizes [index]; - } + int getBufferSizeSamples (int index) + { + return internal->bufferSizes [index]; + } - int getDefaultBufferSize() - { - for (int i = 0; i < getNumBufferSizesAvailable(); ++i) - if (getBufferSizeSamples(i) >= 512) - return getBufferSizeSamples(i); + int getDefaultBufferSize() + { + for (int i = 0; i < getNumBufferSizesAvailable(); ++i) + if (getBufferSizeSamples(i) >= 512) + return getBufferSizeSamples(i); - return 512; - } + return 512; + } - const String open (const BitArray& inputChannels, - const BitArray& outputChannels, - double sampleRate, - int bufferSizeSamples) - { - isOpen_ = true; + const String open (const BitArray& inputChannels, + const BitArray& outputChannels, + double sampleRate, + int bufferSizeSamples) + { + isOpen_ = true; - if (bufferSizeSamples <= 0) - bufferSizeSamples = getDefaultBufferSize(); + if (bufferSizeSamples <= 0) + bufferSizeSamples = getDefaultBufferSize(); - lastError = internal->reopen (inputChannels, outputChannels, sampleRate, bufferSizeSamples); - isOpen_ = lastError.isEmpty(); - return lastError; - } + lastError = internal->reopen (inputChannels, outputChannels, sampleRate, bufferSizeSamples); + isOpen_ = lastError.isEmpty(); + return lastError; + } - void close() - { - isOpen_ = false; - internal->stop (false); - } + void close() + { + isOpen_ = false; + internal->stop (false); + } - bool isOpen() - { - return isOpen_; - } + bool isOpen() + { + return isOpen_; + } - int getCurrentBufferSizeSamples() - { - return internal != 0 ? internal->getBufferSize() : 512; - } + int getCurrentBufferSizeSamples() + { + return internal != 0 ? internal->getBufferSize() : 512; + } - double getCurrentSampleRate() - { - return internal != 0 ? internal->getSampleRate() : 0; - } + double getCurrentSampleRate() + { + return internal != 0 ? internal->getSampleRate() : 0; + } - int getCurrentBitDepth() - { - return 32; // no way to find out, so just assume it's high.. - } + int getCurrentBitDepth() + { + return 32; // no way to find out, so just assume it's high.. + } - const BitArray getActiveOutputChannels() const - { - return internal != 0 ? internal->activeOutputChans : BitArray(); - } + const BitArray getActiveOutputChannels() const + { + return internal != 0 ? internal->activeOutputChans : BitArray(); + } - const BitArray getActiveInputChannels() const - { - BitArray chans; + const BitArray getActiveInputChannels() const + { + BitArray chans; - if (internal != 0) - { - chans = internal->activeInputChans; + if (internal != 0) + { + chans = internal->activeInputChans; - if (internal->inputDevice != 0) - chans.orWith (internal->inputDevice->activeInputChans); - } + if (internal->inputDevice != 0) + chans.orWith (internal->inputDevice->activeInputChans); + } - return chans; - } + return chans; + } - int getOutputLatencyInSamples() - { - if (internal == 0) - return 0; + int getOutputLatencyInSamples() + { + if (internal == 0) + return 0; - // this seems like a good guess at getting the latency right - comparing - // this with a round-trip measurement, it gets it to within a few millisecs - // for the built-in mac soundcard - return internal->outputLatency + internal->getBufferSize() * 2; - } + // this seems like a good guess at getting the latency right - comparing + // this with a round-trip measurement, it gets it to within a few millisecs + // for the built-in mac soundcard + return internal->outputLatency + internal->getBufferSize() * 2; + } - int getInputLatencyInSamples() - { - if (internal == 0) - return 0; + int getInputLatencyInSamples() + { + if (internal == 0) + return 0; - return internal->inputLatency + internal->getBufferSize() * 2; - } + return internal->inputLatency + internal->getBufferSize() * 2; + } - void start (AudioIODeviceCallback* callback) - { - if (internal != 0 && ! isStarted) - { - if (callback != 0) - callback->audioDeviceAboutToStart (this); + void start (AudioIODeviceCallback* callback) + { + if (internal != 0 && ! isStarted) + { + if (callback != 0) + callback->audioDeviceAboutToStart (this); - isStarted = true; - internal->start (callback); - } - } + isStarted = true; + internal->start (callback); + } + } - void stop() - { - if (isStarted && internal != 0) - { - AudioIODeviceCallback* const lastCallback = internal->callback; + void stop() + { + if (isStarted && internal != 0) + { + AudioIODeviceCallback* const lastCallback = internal->callback; - isStarted = false; - internal->stop (true); + isStarted = false; + internal->stop (true); - if (lastCallback != 0) - lastCallback->audioDeviceStopped(); - } - } + if (lastCallback != 0) + lastCallback->audioDeviceStopped(); + } + } - bool isPlaying() - { - if (internal->callback == 0) - isStarted = false; + bool isPlaying() + { + if (internal->callback == 0) + isStarted = false; - return isStarted; - } + return isStarted; + } - const String getLastError() - { - return lastError; - } + const String getLastError() + { + return lastError; + } - int inputIndex, outputIndex; + int inputIndex, outputIndex; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - CoreAudioInternal* internal; - bool isOpen_, isStarted; - String lastError; + CoreAudioInternal* internal; + bool isOpen_, isStarted; + String lastError; - static OSStatus hardwareListenerProc (AudioDeviceID /*inDevice*/, UInt32 /*inLine*/, const AudioObjectPropertyAddress* pa, void* inClientData) - { - CoreAudioInternal* const intern = (CoreAudioInternal*) inClientData; + static OSStatus hardwareListenerProc (AudioDeviceID /*inDevice*/, UInt32 /*inLine*/, const AudioObjectPropertyAddress* pa, void* inClientData) + { + CoreAudioInternal* const intern = (CoreAudioInternal*) inClientData; - switch (pa->mSelector) - { - case kAudioHardwarePropertyDevices: - intern->deviceDetailsChanged(); - break; + switch (pa->mSelector) + { + case kAudioHardwarePropertyDevices: + intern->deviceDetailsChanged(); + break; - case kAudioHardwarePropertyDefaultOutputDevice: - case kAudioHardwarePropertyDefaultInputDevice: - case kAudioHardwarePropertyDefaultSystemOutputDevice: - break; - } + case kAudioHardwarePropertyDefaultOutputDevice: + case kAudioHardwarePropertyDefaultInputDevice: + case kAudioHardwarePropertyDefaultSystemOutputDevice: + break; + } - return noErr; - } + return noErr; + } - CoreAudioIODevice (const CoreAudioIODevice&); - const CoreAudioIODevice& operator= (const CoreAudioIODevice&); + CoreAudioIODevice (const CoreAudioIODevice&); + const CoreAudioIODevice& operator= (const CoreAudioIODevice&); }; class CoreAudioIODeviceType : public AudioIODeviceType { public: - CoreAudioIODeviceType() - : AudioIODeviceType (T("CoreAudio")), - hasScanned (false) - { - } + CoreAudioIODeviceType() + : AudioIODeviceType (T("CoreAudio")), + hasScanned (false) + { + } - ~CoreAudioIODeviceType() - { - } + ~CoreAudioIODeviceType() + { + } - void scanForDevices() - { - hasScanned = true; + void scanForDevices() + { + hasScanned = true; - inputDeviceNames.clear(); - outputDeviceNames.clear(); - inputIds.clear(); - outputIds.clear(); + inputDeviceNames.clear(); + outputDeviceNames.clear(); + inputIds.clear(); + outputIds.clear(); - UInt32 size; + UInt32 size; - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioHardwarePropertyDevices; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementMaster; + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioHardwarePropertyDevices; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementMaster; - if (OK (AudioObjectGetPropertyDataSize (kAudioObjectSystemObject, &pa, 0, 0, &size))) - { - HeapBlock devs; - devs.calloc (size, 1); + if (OK (AudioObjectGetPropertyDataSize (kAudioObjectSystemObject, &pa, 0, 0, &size))) + { + HeapBlock devs; + devs.calloc (size, 1); - if (OK (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, 0, &size, devs))) - { - static bool alreadyLogged = false; - const int num = size / sizeof (AudioDeviceID); - for (int i = 0; i < num; ++i) - { - char name [1024]; - size = sizeof (name); - pa.mSelector = kAudioDevicePropertyDeviceName; + if (OK (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, 0, &size, devs))) + { + static bool alreadyLogged = false; + const int num = size / (int) sizeof (AudioDeviceID); + for (int i = 0; i < num; ++i) + { + char name [1024]; + size = sizeof (name); + pa.mSelector = kAudioDevicePropertyDeviceName; - if (OK (AudioObjectGetPropertyData (devs[i], &pa, 0, 0, &size, name))) - { - const String nameString (String::fromUTF8 ((const uint8*) name, strlen (name))); + if (OK (AudioObjectGetPropertyData (devs[i], &pa, 0, 0, &size, name))) + { + const String nameString (String::fromUTF8 ((const uint8*) name, (int) strlen (name))); - if (! alreadyLogged) - log (T("CoreAudio device: ") + nameString); + if (! alreadyLogged) + log (T("CoreAudio device: ") + nameString); - const int numIns = getNumChannels (devs[i], true); - const int numOuts = getNumChannels (devs[i], false); + const int numIns = getNumChannels (devs[i], true); + const int numOuts = getNumChannels (devs[i], false); - if (numIns > 0) - { - inputDeviceNames.add (nameString); - inputIds.add (devs[i]); - } + if (numIns > 0) + { + inputDeviceNames.add (nameString); + inputIds.add (devs[i]); + } - if (numOuts > 0) - { - outputDeviceNames.add (nameString); - outputIds.add (devs[i]); - } - } - } + if (numOuts > 0) + { + outputDeviceNames.add (nameString); + outputIds.add (devs[i]); + } + } + } - alreadyLogged = true; - } - } + alreadyLogged = true; + } + } - inputDeviceNames.appendNumbersToDuplicates (false, true); - outputDeviceNames.appendNumbersToDuplicates (false, true); - } + inputDeviceNames.appendNumbersToDuplicates (false, true); + outputDeviceNames.appendNumbersToDuplicates (false, true); + } - const StringArray getDeviceNames (const bool wantInputNames) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + const StringArray getDeviceNames (const bool wantInputNames) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - if (wantInputNames) - return inputDeviceNames; - else - return outputDeviceNames; - } + if (wantInputNames) + return inputDeviceNames; + else + return outputDeviceNames; + } - int getDefaultDeviceIndex (const bool forInput) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + int getDefaultDeviceIndex (const bool forInput) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - AudioDeviceID deviceID; - UInt32 size = sizeof (deviceID); + AudioDeviceID deviceID; + UInt32 size = sizeof (deviceID); - // if they're asking for any input channels at all, use the default input, so we - // get the built-in mic rather than the built-in output with no inputs.. + // if they're asking for any input channels at all, use the default input, so we + // get the built-in mic rather than the built-in output with no inputs.. - AudioObjectPropertyAddress pa; - pa.mSelector = forInput ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice; - pa.mScope = kAudioObjectPropertyScopeWildcard; - pa.mElement = kAudioObjectPropertyElementMaster; + AudioObjectPropertyAddress pa; + pa.mSelector = forInput ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice; + pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mElement = kAudioObjectPropertyElementMaster; - if (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, 0, &size, &deviceID) == noErr) - { - if (forInput) - { - for (int i = inputIds.size(); --i >= 0;) - if (inputIds[i] == deviceID) - return i; - } - else - { - for (int i = outputIds.size(); --i >= 0;) - if (outputIds[i] == deviceID) - return i; - } - } + if (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, 0, &size, &deviceID) == noErr) + { + if (forInput) + { + for (int i = inputIds.size(); --i >= 0;) + if (inputIds[i] == deviceID) + return i; + } + else + { + for (int i = outputIds.size(); --i >= 0;) + if (outputIds[i] == deviceID) + return i; + } + } - return 0; - } + return 0; + } - int getIndexOfDevice (AudioIODevice* device, const bool asInput) const - { - jassert (hasScanned); // need to call scanForDevices() before doing this + int getIndexOfDevice (AudioIODevice* device, const bool asInput) const + { + jassert (hasScanned); // need to call scanForDevices() before doing this - CoreAudioIODevice* const d = dynamic_cast (device); - if (d == 0) - return -1; + CoreAudioIODevice* const d = dynamic_cast (device); + if (d == 0) + return -1; - return asInput ? d->inputIndex - : d->outputIndex; - } + return asInput ? d->inputIndex + : d->outputIndex; + } - bool hasSeparateInputsAndOutputs() const { return true; } + bool hasSeparateInputsAndOutputs() const { return true; } - AudioIODevice* createDevice (const String& outputDeviceName, - const String& inputDeviceName) - { - jassert (hasScanned); // need to call scanForDevices() before doing this + AudioIODevice* createDevice (const String& outputDeviceName, + const String& inputDeviceName) + { + jassert (hasScanned); // need to call scanForDevices() before doing this - const int inputIndex = inputDeviceNames.indexOf (inputDeviceName); - const int outputIndex = outputDeviceNames.indexOf (outputDeviceName); + const int inputIndex = inputDeviceNames.indexOf (inputDeviceName); + const int outputIndex = outputDeviceNames.indexOf (outputDeviceName); - String deviceName (outputDeviceName); - if (deviceName.isEmpty()) - deviceName = inputDeviceName; + String deviceName (outputDeviceName); + if (deviceName.isEmpty()) + deviceName = inputDeviceName; - if (index >= 0) - return new CoreAudioIODevice (deviceName, - inputIds [inputIndex], - inputIndex, - outputIds [outputIndex], - outputIndex); + if (index >= 0) + return new CoreAudioIODevice (deviceName, + inputIds [inputIndex], + inputIndex, + outputIds [outputIndex], + outputIndex); - return 0; - } + return 0; + } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - StringArray inputDeviceNames, outputDeviceNames; - Array inputIds, outputIds; + StringArray inputDeviceNames, outputDeviceNames; + Array inputIds, outputIds; - bool hasScanned; + bool hasScanned; - static int getNumChannels (AudioDeviceID deviceID, bool input) - { - int total = 0; - UInt32 size; + static int getNumChannels (AudioDeviceID deviceID, bool input) + { + int total = 0; + UInt32 size; - AudioObjectPropertyAddress pa; - pa.mSelector = kAudioDevicePropertyStreamConfiguration; - pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; - pa.mElement = kAudioObjectPropertyElementMaster; + AudioObjectPropertyAddress pa; + pa.mSelector = kAudioDevicePropertyStreamConfiguration; + pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + pa.mElement = kAudioObjectPropertyElementMaster; - if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) - { - HeapBlock bufList; - bufList.calloc (size, 1); + if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, 0, &size))) + { + HeapBlock bufList; + bufList.calloc (size, 1); - if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, bufList))) - { - const int numStreams = bufList->mNumberBuffers; + if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, 0, &size, bufList))) + { + const int numStreams = bufList->mNumberBuffers; - for (int i = 0; i < numStreams; ++i) - { - const AudioBuffer& b = bufList->mBuffers[i]; - total += b.mNumberChannels; - } - } - } + for (int i = 0; i < numStreams; ++i) + { + const AudioBuffer& b = bufList->mBuffers[i]; + total += b.mNumberChannels; + } + } + } - return total; - } + return total; + } - CoreAudioIODeviceType (const CoreAudioIODeviceType&); - const CoreAudioIODeviceType& operator= (const CoreAudioIODeviceType&); + CoreAudioIODeviceType (const CoreAudioIODeviceType&); + const CoreAudioIODeviceType& operator= (const CoreAudioIODeviceType&); }; AudioIODeviceType* juce_createAudioIODeviceType_CoreAudio() { - return new CoreAudioIODeviceType(); + return new CoreAudioIODeviceType(); } #undef log @@ -273305,12 +250855,12 @@ AudioIODeviceType* juce_createAudioIODeviceType_CoreAudio() static bool logAnyErrorsMidi (const OSStatus err, const int lineNum) { - if (err == noErr) - return true; + if (err == noErr) + return true; - log (T("CoreMidi error: ") + String (lineNum) + T(" - ") + String::toHexString ((int)err)); - jassertfalse - return false; + log (T("CoreMidi error: ") + String (lineNum) + T(" - ") + String::toHexString ((int)err)); + jassertfalse + return false; } #undef OK @@ -273318,165 +250868,165 @@ static bool logAnyErrorsMidi (const OSStatus err, const int lineNum) static const String getEndpointName (MIDIEndpointRef endpoint, bool isExternal) { - String result; - CFStringRef str = 0; + String result; + CFStringRef str = 0; - MIDIObjectGetStringProperty (endpoint, kMIDIPropertyName, &str); + MIDIObjectGetStringProperty (endpoint, kMIDIPropertyName, &str); - if (str != 0) - { - result = PlatformUtilities::cfStringToJuceString (str); - CFRelease (str); - str = 0; - } + if (str != 0) + { + result = PlatformUtilities::cfStringToJuceString (str); + CFRelease (str); + str = 0; + } - MIDIEntityRef entity = 0; - MIDIEndpointGetEntity (endpoint, &entity); + MIDIEntityRef entity = 0; + MIDIEndpointGetEntity (endpoint, &entity); - if (entity == 0) - return result; // probably virtual + if (entity == 0) + return result; // probably virtual - if (result.isEmpty()) - { - // endpoint name has zero length - try the entity - MIDIObjectGetStringProperty (entity, kMIDIPropertyName, &str); + if (result.isEmpty()) + { + // endpoint name has zero length - try the entity + MIDIObjectGetStringProperty (entity, kMIDIPropertyName, &str); - if (str != 0) - { - result += PlatformUtilities::cfStringToJuceString (str); - CFRelease (str); - str = 0; - } - } + if (str != 0) + { + result += PlatformUtilities::cfStringToJuceString (str); + CFRelease (str); + str = 0; + } + } - // now consider the device's name - MIDIDeviceRef device = 0; - MIDIEntityGetDevice (entity, &device); - if (device == 0) - return result; + // now consider the device's name + MIDIDeviceRef device = 0; + MIDIEntityGetDevice (entity, &device); + if (device == 0) + return result; - MIDIObjectGetStringProperty (device, kMIDIPropertyName, &str); + MIDIObjectGetStringProperty (device, kMIDIPropertyName, &str); - if (str != 0) - { - const String s (PlatformUtilities::cfStringToJuceString (str)); - CFRelease (str); + if (str != 0) + { + const String s (PlatformUtilities::cfStringToJuceString (str)); + CFRelease (str); - // if an external device has only one entity, throw away - // the endpoint name and just use the device name - if (isExternal && MIDIDeviceGetNumberOfEntities (device) < 2) - { - result = s; - } - else if (! result.startsWithIgnoreCase (s)) - { - // prepend the device name to the entity name - result = (s + T(" ") + result).trimEnd(); - } - } + // if an external device has only one entity, throw away + // the endpoint name and just use the device name + if (isExternal && MIDIDeviceGetNumberOfEntities (device) < 2) + { + result = s; + } + else if (! result.startsWithIgnoreCase (s)) + { + // prepend the device name to the entity name + result = (s + T(" ") + result).trimEnd(); + } + } - return result; + return result; } static const String getConnectedEndpointName (MIDIEndpointRef endpoint) { - String result; + String result; - // Does the endpoint have connections? - CFDataRef connections = 0; - int numConnections = 0; + // Does the endpoint have connections? + CFDataRef connections = 0; + int numConnections = 0; - MIDIObjectGetDataProperty (endpoint, kMIDIPropertyConnectionUniqueID, &connections); + MIDIObjectGetDataProperty (endpoint, kMIDIPropertyConnectionUniqueID, &connections); - if (connections != 0) - { - numConnections = CFDataGetLength (connections) / sizeof (MIDIUniqueID); + if (connections != 0) + { + numConnections = (int) (CFDataGetLength (connections) / sizeof (MIDIUniqueID)); - if (numConnections > 0) - { - const SInt32* pid = reinterpret_cast (CFDataGetBytePtr (connections)); + if (numConnections > 0) + { + const SInt32* pid = reinterpret_cast (CFDataGetBytePtr (connections)); - for (int i = 0; i < numConnections; ++i, ++pid) - { - MIDIUniqueID uid = EndianS32_BtoN (*pid); - MIDIObjectRef connObject; - MIDIObjectType connObjectType; - OSStatus err = MIDIObjectFindByUniqueID (uid, &connObject, &connObjectType); + for (int i = 0; i < numConnections; ++i, ++pid) + { + MIDIUniqueID uid = EndianS32_BtoN (*pid); + MIDIObjectRef connObject; + MIDIObjectType connObjectType; + OSStatus err = MIDIObjectFindByUniqueID (uid, &connObject, &connObjectType); - if (err == noErr) - { - String s; + if (err == noErr) + { + String s; - if (connObjectType == kMIDIObjectType_ExternalSource - || connObjectType == kMIDIObjectType_ExternalDestination) - { - // Connected to an external device's endpoint (10.3 and later). - s = getEndpointName (static_cast (connObject), true); - } - else - { - // Connected to an external device (10.2) (or something else, catch-all) - CFStringRef str = 0; - MIDIObjectGetStringProperty (connObject, kMIDIPropertyName, &str); + if (connObjectType == kMIDIObjectType_ExternalSource + || connObjectType == kMIDIObjectType_ExternalDestination) + { + // Connected to an external device's endpoint (10.3 and later). + s = getEndpointName (static_cast (connObject), true); + } + else + { + // Connected to an external device (10.2) (or something else, catch-all) + CFStringRef str = 0; + MIDIObjectGetStringProperty (connObject, kMIDIPropertyName, &str); - if (str != 0) - { - s = PlatformUtilities::cfStringToJuceString (str); - CFRelease (str); - } - } + if (str != 0) + { + s = PlatformUtilities::cfStringToJuceString (str); + CFRelease (str); + } + } - if (s.isNotEmpty()) - { - if (result.isNotEmpty()) - result += (", "); + if (s.isNotEmpty()) + { + if (result.isNotEmpty()) + result += (", "); - result += s; - } - } - } - } + result += s; + } + } + } + } - CFRelease (connections); - } + CFRelease (connections); + } - if (result.isNotEmpty()) - return result; + if (result.isNotEmpty()) + return result; - // Here, either the endpoint had no connections, or we failed to obtain names for any of them. - return getEndpointName (endpoint, false); + // Here, either the endpoint had no connections, or we failed to obtain names for any of them. + return getEndpointName (endpoint, false); } const StringArray MidiOutput::getDevices() { - StringArray s; + StringArray s; - const ItemCount num = MIDIGetNumberOfDestinations(); - for (ItemCount i = 0; i < num; ++i) - { - MIDIEndpointRef dest = MIDIGetDestination (i); + const ItemCount num = MIDIGetNumberOfDestinations(); + for (ItemCount i = 0; i < num; ++i) + { + MIDIEndpointRef dest = MIDIGetDestination (i); - if (dest != 0) - { - String name (getConnectedEndpointName (dest)); + if (dest != 0) + { + String name (getConnectedEndpointName (dest)); - if (name.isEmpty()) - name = ""; + if (name.isEmpty()) + name = ""; - s.add (name); - } - else - { - s.add (""); - } - } + s.add (name); + } + else + { + s.add (""); + } + } - return s; + return s; } int MidiOutput::getDefaultDeviceIndex() { - return 0; + return 0; } static MIDIClientRef globalMidiClient; @@ -273484,98 +251034,98 @@ static bool hasGlobalClientBeenCreated = false; static bool makeSureClientExists() { - if (! hasGlobalClientBeenCreated) - { - String name (T("JUCE")); + if (! hasGlobalClientBeenCreated) + { + String name (T("JUCE")); - if (JUCEApplication::getInstance() != 0) - name = JUCEApplication::getInstance()->getApplicationName(); + if (JUCEApplication::getInstance() != 0) + name = JUCEApplication::getInstance()->getApplicationName(); - CFStringRef appName = PlatformUtilities::juceStringToCFString (name); + CFStringRef appName = PlatformUtilities::juceStringToCFString (name); - hasGlobalClientBeenCreated = OK (MIDIClientCreate (appName, 0, 0, &globalMidiClient)); - CFRelease (appName); - } + hasGlobalClientBeenCreated = OK (MIDIClientCreate (appName, 0, 0, &globalMidiClient)); + CFRelease (appName); + } - return hasGlobalClientBeenCreated; + return hasGlobalClientBeenCreated; } class MidiPortAndEndpoint { public: - MidiPortAndEndpoint (MIDIPortRef port_, MIDIEndpointRef endPoint_) - : port (port_), endPoint (endPoint_) - { - } + MidiPortAndEndpoint (MIDIPortRef port_, MIDIEndpointRef endPoint_) + : port (port_), endPoint (endPoint_) + { + } - ~MidiPortAndEndpoint() - { - if (port != 0) - MIDIPortDispose (port); + ~MidiPortAndEndpoint() + { + if (port != 0) + MIDIPortDispose (port); - if (port == 0 && endPoint != 0) // if port == 0, it means we created the endpoint, so it's safe to delete it - MIDIEndpointDispose (endPoint); - } + if (port == 0 && endPoint != 0) // if port == 0, it means we created the endpoint, so it's safe to delete it + MIDIEndpointDispose (endPoint); + } - MIDIPortRef port; - MIDIEndpointRef endPoint; + MIDIPortRef port; + MIDIEndpointRef endPoint; }; MidiOutput* MidiOutput::openDevice (int index) { - MidiOutput* mo = 0; + MidiOutput* mo = 0; - if (((unsigned int) index) < (unsigned int) MIDIGetNumberOfDestinations()) - { - MIDIEndpointRef endPoint = MIDIGetDestination (index); + if (((unsigned int) index) < (unsigned int) MIDIGetNumberOfDestinations()) + { + MIDIEndpointRef endPoint = MIDIGetDestination (index); - CFStringRef pname; - if (OK (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname))) - { - log (T("CoreMidi - opening out: ") + PlatformUtilities::cfStringToJuceString (pname)); + CFStringRef pname; + if (OK (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname))) + { + log (T("CoreMidi - opening out: ") + PlatformUtilities::cfStringToJuceString (pname)); - if (makeSureClientExists()) - { - MIDIPortRef port; + if (makeSureClientExists()) + { + MIDIPortRef port; - if (OK (MIDIOutputPortCreate (globalMidiClient, pname, &port))) - { - mo = new MidiOutput(); - mo->internal = (void*) new MidiPortAndEndpoint (port, endPoint); - } - } + if (OK (MIDIOutputPortCreate (globalMidiClient, pname, &port))) + { + mo = new MidiOutput(); + mo->internal = (void*) new MidiPortAndEndpoint (port, endPoint); + } + } - CFRelease (pname); - } - } + CFRelease (pname); + } + } - return mo; + return mo; } MidiOutput* MidiOutput::createNewDevice (const String& deviceName) { - MidiOutput* mo = 0; + MidiOutput* mo = 0; - if (makeSureClientExists()) - { - MIDIEndpointRef endPoint; - CFStringRef name = PlatformUtilities::juceStringToCFString (deviceName); + if (makeSureClientExists()) + { + MIDIEndpointRef endPoint; + CFStringRef name = PlatformUtilities::juceStringToCFString (deviceName); - if (OK (MIDISourceCreate (globalMidiClient, name, &endPoint))) - { - mo = new MidiOutput(); - mo->internal = (void*) new MidiPortAndEndpoint (0, endPoint); - } + if (OK (MIDISourceCreate (globalMidiClient, name, &endPoint))) + { + mo = new MidiOutput(); + mo->internal = (void*) new MidiPortAndEndpoint (0, endPoint); + } - CFRelease (name); - } + CFRelease (name); + } - return mo; + return mo; } MidiOutput::~MidiOutput() { - delete (MidiPortAndEndpoint*) internal; + delete (MidiPortAndEndpoint*) internal; } void MidiOutput::reset() @@ -273584,7 +251134,7 @@ void MidiOutput::reset() bool MidiOutput::getVolume (float& leftVol, float& rightVol) { - return false; + return false; } void MidiOutput::setVolume (float leftVol, float rightVol) @@ -273593,90 +251143,90 @@ void MidiOutput::setVolume (float leftVol, float rightVol) void MidiOutput::sendMessageNow (const MidiMessage& message) { - MidiPortAndEndpoint* const mpe = (MidiPortAndEndpoint*) internal; + MidiPortAndEndpoint* const mpe = (MidiPortAndEndpoint*) internal; - if (message.isSysEx()) - { - const int maxPacketSize = 256; - int pos = 0, bytesLeft = message.getRawDataSize(); - const int numPackets = (bytesLeft + maxPacketSize - 1) / maxPacketSize; - HeapBlock packets; - packets.malloc (32 * numPackets + message.getRawDataSize(), 1); - packets->numPackets = numPackets; + if (message.isSysEx()) + { + const int maxPacketSize = 256; + int pos = 0, bytesLeft = message.getRawDataSize(); + const int numPackets = (bytesLeft + maxPacketSize - 1) / maxPacketSize; + HeapBlock packets; + packets.malloc (32 * numPackets + message.getRawDataSize(), 1); + packets->numPackets = numPackets; - MIDIPacket* p = packets->packet; + MIDIPacket* p = packets->packet; - for (int i = 0; i < numPackets; ++i) - { - p->timeStamp = 0; - p->length = jmin (maxPacketSize, bytesLeft); - memcpy (p->data, message.getRawData() + pos, p->length); - pos += p->length; - bytesLeft -= p->length; - p = MIDIPacketNext (p); - } + for (int i = 0; i < numPackets; ++i) + { + p->timeStamp = 0; + p->length = jmin (maxPacketSize, bytesLeft); + memcpy (p->data, message.getRawData() + pos, p->length); + pos += p->length; + bytesLeft -= p->length; + p = MIDIPacketNext (p); + } - if (mpe->port != 0) - MIDISend (mpe->port, mpe->endPoint, packets); - else - MIDIReceived (mpe->endPoint, packets); - } - else - { - MIDIPacketList packets; - packets.numPackets = 1; - packets.packet[0].timeStamp = 0; - packets.packet[0].length = message.getRawDataSize(); - *(int*) (packets.packet[0].data) = *(const int*) message.getRawData(); + if (mpe->port != 0) + MIDISend (mpe->port, mpe->endPoint, packets); + else + MIDIReceived (mpe->endPoint, packets); + } + else + { + MIDIPacketList packets; + packets.numPackets = 1; + packets.packet[0].timeStamp = 0; + packets.packet[0].length = message.getRawDataSize(); + *(int*) (packets.packet[0].data) = *(const int*) message.getRawData(); - if (mpe->port != 0) - MIDISend (mpe->port, mpe->endPoint, &packets); - else - MIDIReceived (mpe->endPoint, &packets); - } + if (mpe->port != 0) + MIDISend (mpe->port, mpe->endPoint, &packets); + else + MIDIReceived (mpe->endPoint, &packets); + } } const StringArray MidiInput::getDevices() { - StringArray s; + StringArray s; - const ItemCount num = MIDIGetNumberOfSources(); - for (ItemCount i = 0; i < num; ++i) - { - MIDIEndpointRef source = MIDIGetSource (i); + const ItemCount num = MIDIGetNumberOfSources(); + for (ItemCount i = 0; i < num; ++i) + { + MIDIEndpointRef source = MIDIGetSource (i); - if (source != 0) - { - String name (getConnectedEndpointName (source)); + if (source != 0) + { + String name (getConnectedEndpointName (source)); - if (name.isEmpty()) - name = ""; + if (name.isEmpty()) + name = ""; - s.add (name); - } - else - { - s.add (""); - } - } + s.add (name); + } + else + { + s.add (""); + } + } - return s; + return s; } int MidiInput::getDefaultDeviceIndex() { - return 0; + return 0; } struct MidiPortAndCallback { - MidiInput* input; - MidiPortAndEndpoint* portAndEndpoint; - MidiInputCallback* callback; - MemoryBlock pendingData; - int pendingBytes; - double pendingDataTime; - bool active; + MidiInput* input; + MidiPortAndEndpoint* portAndEndpoint; + MidiInputCallback* callback; + MemoryBlock pendingData; + int pendingBytes; + double pendingDataTime; + bool active; }; static CriticalSection callbackLock; @@ -273684,234 +251234,234 @@ static VoidArray activeCallbacks; static void processSysex (MidiPortAndCallback* const mpc, const uint8*& d, int& size, const double time) { - if (*d == 0xf0) - { - mpc->pendingBytes = 0; - mpc->pendingDataTime = time; - } + if (*d == 0xf0) + { + mpc->pendingBytes = 0; + mpc->pendingDataTime = time; + } - mpc->pendingData.ensureSize (mpc->pendingBytes + size, false); - uint8* totalMessage = (uint8*) mpc->pendingData.getData(); + mpc->pendingData.ensureSize (mpc->pendingBytes + size, false); + uint8* totalMessage = (uint8*) mpc->pendingData.getData(); - uint8* dest = totalMessage + mpc->pendingBytes; + uint8* dest = totalMessage + mpc->pendingBytes; - while (size > 0) - { - if (mpc->pendingBytes > 0 && *d >= 0x80) - { - if (*d >= 0xfa || *d == 0xf8) - { - mpc->callback->handleIncomingMidiMessage (mpc->input, MidiMessage (*d, time)); - ++d; - --size; - } - else - { - if (*d == 0xf7) - { - *dest++ = *d++; - mpc->pendingBytes++; - --size; - } + while (size > 0) + { + if (mpc->pendingBytes > 0 && *d >= 0x80) + { + if (*d >= 0xfa || *d == 0xf8) + { + mpc->callback->handleIncomingMidiMessage (mpc->input, MidiMessage (*d, time)); + ++d; + --size; + } + else + { + if (*d == 0xf7) + { + *dest++ = *d++; + mpc->pendingBytes++; + --size; + } - break; - } - } - else - { - *dest++ = *d++; - mpc->pendingBytes++; - --size; - } - } + break; + } + } + else + { + *dest++ = *d++; + mpc->pendingBytes++; + --size; + } + } - if (totalMessage [mpc->pendingBytes - 1] == 0xf7) - { - mpc->callback->handleIncomingMidiMessage (mpc->input, MidiMessage (totalMessage, - mpc->pendingBytes, - mpc->pendingDataTime)); - mpc->pendingBytes = 0; - } - else - { - mpc->callback->handlePartialSysexMessage (mpc->input, - totalMessage, - mpc->pendingBytes, - mpc->pendingDataTime); - } + if (totalMessage [mpc->pendingBytes - 1] == 0xf7) + { + mpc->callback->handleIncomingMidiMessage (mpc->input, MidiMessage (totalMessage, + mpc->pendingBytes, + mpc->pendingDataTime)); + mpc->pendingBytes = 0; + } + else + { + mpc->callback->handlePartialSysexMessage (mpc->input, + totalMessage, + mpc->pendingBytes, + mpc->pendingDataTime); + } } static void midiInputProc (const MIDIPacketList* pktlist, - void* readProcRefCon, - void* srcConnRefCon) + void* readProcRefCon, + void* srcConnRefCon) { - double time = Time::getMillisecondCounterHiRes() * 0.001; - const double originalTime = time; + double time = Time::getMillisecondCounterHiRes() * 0.001; + const double originalTime = time; - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) readProcRefCon; - const ScopedLock sl (callbackLock); + MidiPortAndCallback* const mpc = (MidiPortAndCallback*) readProcRefCon; + const ScopedLock sl (callbackLock); - if (activeCallbacks.contains (mpc) && mpc->active) - { - const MIDIPacket* packet = &pktlist->packet[0]; + if (activeCallbacks.contains (mpc) && mpc->active) + { + const MIDIPacket* packet = &pktlist->packet[0]; - for (unsigned int i = 0; i < pktlist->numPackets; ++i) - { - const uint8* d = (const uint8*) (packet->data); - int size = packet->length; + for (unsigned int i = 0; i < pktlist->numPackets; ++i) + { + const uint8* d = (const uint8*) (packet->data); + int size = packet->length; - while (size > 0) - { - time = originalTime; + while (size > 0) + { + time = originalTime; - if (mpc->pendingBytes > 0 || d[0] == 0xf0) - { - processSysex (mpc, d, size, time); - } - else - { - int used = 0; - const MidiMessage m (d, size, used, 0, time); + if (mpc->pendingBytes > 0 || d[0] == 0xf0) + { + processSysex (mpc, d, size, time); + } + else + { + int used = 0; + const MidiMessage m (d, size, used, 0, time); - if (used <= 0) - { - jassertfalse // malformed midi message - break; - } - else - { - mpc->callback->handleIncomingMidiMessage (mpc->input, m); - } + if (used <= 0) + { + jassertfalse // malformed midi message + break; + } + else + { + mpc->callback->handleIncomingMidiMessage (mpc->input, m); + } - size -= used; - d += used; - } - } + size -= used; + d += used; + } + } - packet = MIDIPacketNext (packet); - } - } + packet = MIDIPacketNext (packet); + } + } } MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) { - MidiInput* mi = 0; + MidiInput* mi = 0; - if (((unsigned int) index) < (unsigned int) MIDIGetNumberOfSources()) - { - MIDIEndpointRef endPoint = MIDIGetSource (index); + if (((unsigned int) index) < (unsigned int) MIDIGetNumberOfSources()) + { + MIDIEndpointRef endPoint = MIDIGetSource (index); - if (endPoint != 0) - { - CFStringRef pname; + if (endPoint != 0) + { + CFStringRef pname; - if (OK (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname))) - { - log (T("CoreMidi - opening inp: ") + PlatformUtilities::cfStringToJuceString (pname)); + if (OK (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname))) + { + log (T("CoreMidi - opening inp: ") + PlatformUtilities::cfStringToJuceString (pname)); - if (makeSureClientExists()) - { - MIDIPortRef port; + if (makeSureClientExists()) + { + MIDIPortRef port; - ScopedPointer mpc (new MidiPortAndCallback()); - mpc->active = false; + ScopedPointer mpc (new MidiPortAndCallback()); + mpc->active = false; - if (OK (MIDIInputPortCreate (globalMidiClient, pname, midiInputProc, mpc, &port))) - { - if (OK (MIDIPortConnectSource (port, endPoint, 0))) - { - mpc->portAndEndpoint = new MidiPortAndEndpoint (port, endPoint); - mpc->callback = callback; - mpc->pendingBytes = 0; - mpc->pendingData.ensureSize (128); + if (OK (MIDIInputPortCreate (globalMidiClient, pname, midiInputProc, mpc, &port))) + { + if (OK (MIDIPortConnectSource (port, endPoint, 0))) + { + mpc->portAndEndpoint = new MidiPortAndEndpoint (port, endPoint); + mpc->callback = callback; + mpc->pendingBytes = 0; + mpc->pendingData.ensureSize (128); - mi = new MidiInput (getDevices() [index]); - mpc->input = mi; - mi->internal = (void*) mpc; + mi = new MidiInput (getDevices() [index]); + mpc->input = mi; + mi->internal = (void*) mpc; - const ScopedLock sl (callbackLock); - activeCallbacks.add (mpc.release()); - } - else - { - OK (MIDIPortDispose (port)); - } - } - } - } + const ScopedLock sl (callbackLock); + activeCallbacks.add (mpc.release()); + } + else + { + OK (MIDIPortDispose (port)); + } + } + } + } - CFRelease (pname); - } - } + CFRelease (pname); + } + } - return mi; + return mi; } MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallback* callback) { - MidiInput* mi = 0; + MidiInput* mi = 0; - if (makeSureClientExists()) - { - ScopedPointer mpc (new MidiPortAndCallback()); - mpc->active = false; + if (makeSureClientExists()) + { + ScopedPointer mpc (new MidiPortAndCallback()); + mpc->active = false; - MIDIEndpointRef endPoint; - CFStringRef name = PlatformUtilities::juceStringToCFString(deviceName); - if (OK (MIDIDestinationCreate (globalMidiClient, name, midiInputProc, mpc, &endPoint))) - { - mpc->portAndEndpoint = new MidiPortAndEndpoint (0, endPoint); - mpc->callback = callback; - mpc->pendingBytes = 0; - mpc->pendingData.ensureSize (128); + MIDIEndpointRef endPoint; + CFStringRef name = PlatformUtilities::juceStringToCFString(deviceName); + if (OK (MIDIDestinationCreate (globalMidiClient, name, midiInputProc, mpc, &endPoint))) + { + mpc->portAndEndpoint = new MidiPortAndEndpoint (0, endPoint); + mpc->callback = callback; + mpc->pendingBytes = 0; + mpc->pendingData.ensureSize (128); - mi = new MidiInput (deviceName); - mpc->input = mi; - mi->internal = (void*) mpc; + mi = new MidiInput (deviceName); + mpc->input = mi; + mi->internal = (void*) mpc; - const ScopedLock sl (callbackLock); - activeCallbacks.add (mpc.release()); - } + const ScopedLock sl (callbackLock); + activeCallbacks.add (mpc.release()); + } - CFRelease (name); - } + CFRelease (name); + } - return mi; + return mi; } MidiInput::MidiInput (const String& name_) - : name (name_) + : name (name_) { } MidiInput::~MidiInput() { - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; - mpc->active = false; + MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; + mpc->active = false; - callbackLock.enter(); - activeCallbacks.removeValue (mpc); - callbackLock.exit(); + callbackLock.enter(); + activeCallbacks.removeValue (mpc); + callbackLock.exit(); - if (mpc->portAndEndpoint->port != 0) - OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint)); + if (mpc->portAndEndpoint->port != 0) + OK (MIDIPortDisconnectSource (mpc->portAndEndpoint->port, mpc->portAndEndpoint->endPoint)); - delete mpc->portAndEndpoint; - delete mpc; + delete mpc->portAndEndpoint; + delete mpc; } void MidiInput::start() { - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; - const ScopedLock sl (callbackLock); - mpc->active = true; + MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; + const ScopedLock sl (callbackLock); + mpc->active = true; } void MidiInput::stop() { - MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; - const ScopedLock sl (callbackLock); - mpc->active = false; + MidiPortAndCallback* const mpc = (MidiPortAndCallback*) internal; + const ScopedLock sl (callbackLock); + mpc->active = false; } #undef log @@ -273928,7 +251478,7 @@ void MidiOutput::reset() bool MidiOutput::getVolume (float& leftVol, float& rightVol) { - return false; + return false; } void MidiOutput::setVolume (float leftVol, float rightVol) @@ -273941,22 +251491,22 @@ void MidiOutput::sendMessageNow (const MidiMessage& message) const StringArray MidiOutput::getDevices() { - return StringArray(); + return StringArray(); } MidiOutput* MidiOutput::openDevice (int index) { - return 0; + return 0; } const StringArray MidiInput::getDevices() { - return StringArray(); + return StringArray(); } MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) { - return 0; + return 0; } #endif @@ -273975,25 +251525,25 @@ class QTCameraDeviceInteral; END_JUCE_NAMESPACE -@interface QTCaptureCallbackDelegate : NSObject +@interface QTCaptureCallbackDelegate : NSObject { @public - CameraDevice* owner; - QTCameraDeviceInteral* internal; - Time* firstRecordedTime; + CameraDevice* owner; + QTCameraDeviceInteral* internal; + Time* firstRecordedTime; } - (QTCaptureCallbackDelegate*) initWithOwner: (CameraDevice*) owner internalDev: (QTCameraDeviceInteral*) d; - (void) dealloc; - (void) captureOutput: (QTCaptureOutput*) captureOutput - didOutputVideoFrame: (CVImageBufferRef) videoFrame - withSampleBuffer: (QTSampleBuffer*) sampleBuffer - fromConnection: (QTCaptureConnection*) connection; + didOutputVideoFrame: (CVImageBufferRef) videoFrame + withSampleBuffer: (QTSampleBuffer*) sampleBuffer + fromConnection: (QTCaptureConnection*) connection; - (void) captureOutput: (QTCaptureFileOutput*) captureOutput - didOutputSampleBuffer: (QTSampleBuffer*) sampleBuffer - fromConnection: (QTCaptureConnection*) connection; + didOutputSampleBuffer: (QTSampleBuffer*) sampleBuffer + fromConnection: (QTCaptureConnection*) connection; @end BEGIN_JUCE_NAMESPACE @@ -274001,194 +251551,194 @@ BEGIN_JUCE_NAMESPACE class QTCameraDeviceInteral { public: - QTCameraDeviceInteral (CameraDevice* owner, int index) - { - const ScopedAutoReleasePool pool; + QTCameraDeviceInteral (CameraDevice* owner, int index) + { + const ScopedAutoReleasePool pool; - session = [[QTCaptureSession alloc] init]; + session = [[QTCaptureSession alloc] init]; - NSArray* devs = [QTCaptureDevice inputDevicesWithMediaType: QTMediaTypeVideo]; - device = (QTCaptureDevice*) [devs objectAtIndex: index]; - input = 0; - audioInput = 0; - audioDevice = 0; - fileOutput = 0; - imageOutput = 0; - callbackDelegate = [[QTCaptureCallbackDelegate alloc] initWithOwner: owner - internalDev: this]; + NSArray* devs = [QTCaptureDevice inputDevicesWithMediaType: QTMediaTypeVideo]; + device = (QTCaptureDevice*) [devs objectAtIndex: index]; + input = 0; + audioInput = 0; + audioDevice = 0; + fileOutput = 0; + imageOutput = 0; + callbackDelegate = [[QTCaptureCallbackDelegate alloc] initWithOwner: owner + internalDev: this]; - NSError* err = 0; - [device retain]; - [device open: &err]; + NSError* err = 0; + [device retain]; + [device open: &err]; - if (err == 0) - { - input = [[QTCaptureDeviceInput alloc] initWithDevice: device]; - audioInput = [[QTCaptureDeviceInput alloc] initWithDevice: device]; + if (err == 0) + { + input = [[QTCaptureDeviceInput alloc] initWithDevice: device]; + audioInput = [[QTCaptureDeviceInput alloc] initWithDevice: device]; - [session addInput: input error: &err]; + [session addInput: input error: &err]; - if (err == 0) - { - resetFile(); + if (err == 0) + { + resetFile(); - imageOutput = [[QTCaptureDecompressedVideoOutput alloc] init]; - [imageOutput setDelegate: callbackDelegate]; + imageOutput = [[QTCaptureDecompressedVideoOutput alloc] init]; + [imageOutput setDelegate: callbackDelegate]; - if (err == 0) - { - [session startRunning]; - return; - } - } - } + if (err == 0) + { + [session startRunning]; + return; + } + } + } - openingError = nsStringToJuce ([err description]); - DBG (openingError); - } + openingError = nsStringToJuce ([err description]); + DBG (openingError); + } - ~QTCameraDeviceInteral() - { - [session stopRunning]; - [session removeOutput: imageOutput]; + ~QTCameraDeviceInteral() + { + [session stopRunning]; + [session removeOutput: imageOutput]; - [session release]; - [input release]; - [device release]; - [audioDevice release]; - [audioInput release]; - [fileOutput release]; - [imageOutput release]; - [callbackDelegate release]; - } + [session release]; + [input release]; + [device release]; + [audioDevice release]; + [audioInput release]; + [fileOutput release]; + [imageOutput release]; + [callbackDelegate release]; + } - void resetFile() - { - [fileOutput recordToOutputFileURL: nil]; - [session removeOutput: fileOutput]; - [fileOutput release]; - fileOutput = [[QTCaptureMovieFileOutput alloc] init]; + void resetFile() + { + [fileOutput recordToOutputFileURL: nil]; + [session removeOutput: fileOutput]; + [fileOutput release]; + fileOutput = [[QTCaptureMovieFileOutput alloc] init]; - [session removeInput: audioInput]; - [audioInput release]; - audioInput = 0; - [audioDevice release]; - audioDevice = 0; + [session removeInput: audioInput]; + [audioInput release]; + audioInput = 0; + [audioDevice release]; + audioDevice = 0; - [fileOutput setDelegate: callbackDelegate]; - } + [fileOutput setDelegate: callbackDelegate]; + } - void addDefaultAudioInput() - { - NSError* err = nil; - audioDevice = [QTCaptureDevice defaultInputDeviceWithMediaType: QTMediaTypeSound]; + void addDefaultAudioInput() + { + NSError* err = nil; + audioDevice = [QTCaptureDevice defaultInputDeviceWithMediaType: QTMediaTypeSound]; - if ([audioDevice open: &err]) - [audioDevice retain]; - else - audioDevice = nil; + if ([audioDevice open: &err]) + [audioDevice retain]; + else + audioDevice = nil; - if (audioDevice != 0) - { - audioInput = [[QTCaptureDeviceInput alloc] initWithDevice: audioDevice]; - [session addInput: audioInput error: &err]; - } - } + if (audioDevice != 0) + { + audioInput = [[QTCaptureDeviceInput alloc] initWithDevice: audioDevice]; + [session addInput: audioInput error: &err]; + } + } - void addListener (CameraImageListener* listenerToAdd) - { - const ScopedLock sl (listenerLock); + void addListener (CameraImageListener* listenerToAdd) + { + const ScopedLock sl (listenerLock); - if (listeners.size() == 0) - [session addOutput: imageOutput error: nil]; + if (listeners.size() == 0) + [session addOutput: imageOutput error: nil]; - listeners.addIfNotAlreadyThere (listenerToAdd); - } + listeners.addIfNotAlreadyThere (listenerToAdd); + } - void removeListener (CameraImageListener* listenerToRemove) - { - const ScopedLock sl (listenerLock); - listeners.removeValue (listenerToRemove); + void removeListener (CameraImageListener* listenerToRemove) + { + const ScopedLock sl (listenerLock); + listeners.removeValue (listenerToRemove); - if (listeners.size() == 0) - [session removeOutput: imageOutput]; - } + if (listeners.size() == 0) + [session removeOutput: imageOutput]; + } - void callListeners (CIImage* frame, int w, int h) - { - CoreGraphicsImage image (Image::ARGB, w, h, false); - CIContext* cic = [CIContext contextWithCGContext: image.context options: nil]; - [cic drawImage: frame inRect: CGRectMake (0, 0, w, h) fromRect: CGRectMake (0, 0, w, h)]; - CGContextFlush (image.context); + void callListeners (CIImage* frame, int w, int h) + { + CoreGraphicsImage image (Image::ARGB, w, h, false); + CIContext* cic = [CIContext contextWithCGContext: image.context options: nil]; + [cic drawImage: frame inRect: CGRectMake (0, 0, w, h) fromRect: CGRectMake (0, 0, w, h)]; + CGContextFlush (image.context); - const ScopedLock sl (listenerLock); + const ScopedLock sl (listenerLock); - for (int i = listeners.size(); --i >= 0;) - { - CameraImageListener* l = (CameraImageListener*) listeners[i]; + for (int i = listeners.size(); --i >= 0;) + { + CameraImageListener* l = (CameraImageListener*) listeners[i]; - if (l != 0) - l->imageReceived (image); - } - } + if (l != 0) + l->imageReceived (image); + } + } - QTCaptureDevice* device; - QTCaptureDeviceInput* input; - QTCaptureDevice* audioDevice; - QTCaptureDeviceInput* audioInput; - QTCaptureSession* session; - QTCaptureMovieFileOutput* fileOutput; - QTCaptureDecompressedVideoOutput* imageOutput; - QTCaptureCallbackDelegate* callbackDelegate; - String openingError; + QTCaptureDevice* device; + QTCaptureDeviceInput* input; + QTCaptureDevice* audioDevice; + QTCaptureDeviceInput* audioInput; + QTCaptureSession* session; + QTCaptureMovieFileOutput* fileOutput; + QTCaptureDecompressedVideoOutput* imageOutput; + QTCaptureCallbackDelegate* callbackDelegate; + String openingError; - VoidArray listeners; - CriticalSection listenerLock; + VoidArray listeners; + CriticalSection listenerLock; }; END_JUCE_NAMESPACE @implementation QTCaptureCallbackDelegate - (QTCaptureCallbackDelegate*) initWithOwner: (CameraDevice*) owner_ - internalDev: (QTCameraDeviceInteral*) d + internalDev: (QTCameraDeviceInteral*) d { - [super init]; - owner = owner_; - internal = d; - firstRecordedTime = 0; - return self; + [super init]; + owner = owner_; + internal = d; + firstRecordedTime = 0; + return self; } - (void) dealloc { - delete firstRecordedTime; - [super dealloc]; + delete firstRecordedTime; + [super dealloc]; } - (void) captureOutput: (QTCaptureOutput*) captureOutput - didOutputVideoFrame: (CVImageBufferRef) videoFrame - withSampleBuffer: (QTSampleBuffer*) sampleBuffer - fromConnection: (QTCaptureConnection*) connection + didOutputVideoFrame: (CVImageBufferRef) videoFrame + withSampleBuffer: (QTSampleBuffer*) sampleBuffer + fromConnection: (QTCaptureConnection*) connection { - if (internal->listeners.size() > 0) - { - const ScopedAutoReleasePool pool; + if (internal->listeners.size() > 0) + { + const ScopedAutoReleasePool pool; - internal->callListeners ([CIImage imageWithCVImageBuffer: videoFrame], - CVPixelBufferGetWidth (videoFrame), - CVPixelBufferGetHeight (videoFrame)); - } + internal->callListeners ([CIImage imageWithCVImageBuffer: videoFrame], + CVPixelBufferGetWidth (videoFrame), + CVPixelBufferGetHeight (videoFrame)); + } } - (void) captureOutput: (QTCaptureFileOutput*) captureOutput - didOutputSampleBuffer: (QTSampleBuffer*) sampleBuffer - fromConnection: (QTCaptureConnection*) connection + didOutputSampleBuffer: (QTSampleBuffer*) sampleBuffer + fromConnection: (QTCaptureConnection*) connection { - if (firstRecordedTime == 0) - { - const Time now (Time::getCurrentTime()); - firstRecordedTime = new Time (now - RelativeTime (0.1)); - } + if (firstRecordedTime == 0) + { + const Time now (Time::getCurrentTime()); + firstRecordedTime = new Time (now - RelativeTime (0.1)); + } } @end @@ -274197,149 +251747,149 @@ BEGIN_JUCE_NAMESPACE class QTCaptureViewerComp : public NSViewComponent { public: - QTCaptureViewerComp (CameraDevice* const cameraDevice, QTCameraDeviceInteral* const internal) - { - const ScopedAutoReleasePool pool; - captureView = [[QTCaptureView alloc] init]; - [captureView setCaptureSession: internal->session]; + QTCaptureViewerComp (CameraDevice* const cameraDevice, QTCameraDeviceInteral* const internal) + { + const ScopedAutoReleasePool pool; + captureView = [[QTCaptureView alloc] init]; + [captureView setCaptureSession: internal->session]; - setSize (640, 480); // xxx need to somehow get the movie size - how? - setView (captureView); - } + setSize (640, 480); // xxx need to somehow get the movie size - how? + setView (captureView); + } - ~QTCaptureViewerComp() - { - setView (0); - [captureView setCaptureSession: nil]; - [captureView release]; - } + ~QTCaptureViewerComp() + { + setView (0); + [captureView setCaptureSession: nil]; + [captureView release]; + } - QTCaptureView* captureView; + QTCaptureView* captureView; }; CameraDevice::CameraDevice (const String& name_, int index) - : name (name_) + : name (name_) { - isRecording = false; - QTCameraDeviceInteral* d = new QTCameraDeviceInteral (this, index); - internal = d; + isRecording = false; + QTCameraDeviceInteral* d = new QTCameraDeviceInteral (this, index); + internal = d; } CameraDevice::~CameraDevice() { - stopRecording(); - delete (QTCameraDeviceInteral*) internal; - internal = 0; + stopRecording(); + delete (QTCameraDeviceInteral*) internal; + internal = 0; } Component* CameraDevice::createViewerComponent() { - return new QTCaptureViewerComp (this, (QTCameraDeviceInteral*) internal); + return new QTCaptureViewerComp (this, (QTCameraDeviceInteral*) internal); } const String CameraDevice::getFileExtension() { - return ".mov"; + return ".mov"; } void CameraDevice::startRecordingToFile (const File& file) { - stopRecording(); + stopRecording(); - QTCameraDeviceInteral* const d = (QTCameraDeviceInteral*) internal; - deleteAndZero (d->callbackDelegate->firstRecordedTime); - file.deleteFile(); + QTCameraDeviceInteral* const d = (QTCameraDeviceInteral*) internal; + deleteAndZero (d->callbackDelegate->firstRecordedTime); + file.deleteFile(); - // In some versions of QT (e.g. on 10.5), if you record video without audio, the speed comes - // out wrong, so we'll put some audio in there too.., - d->addDefaultAudioInput(); + // In some versions of QT (e.g. on 10.5), if you record video without audio, the speed comes + // out wrong, so we'll put some audio in there too.., + d->addDefaultAudioInput(); - [d->session addOutput: d->fileOutput error: nil]; + [d->session addOutput: d->fileOutput error: nil]; - NSEnumerator* connectionEnumerator = [[d->fileOutput connections] objectEnumerator]; + NSEnumerator* connectionEnumerator = [[d->fileOutput connections] objectEnumerator]; - for (;;) - { - QTCaptureConnection* connection = [connectionEnumerator nextObject]; - if (connection == 0) - break; + for (;;) + { + QTCaptureConnection* connection = [connectionEnumerator nextObject]; + if (connection == 0) + break; - QTCompressionOptions* options = 0; - NSString* mediaType = [connection mediaType]; + QTCompressionOptions* options = 0; + NSString* mediaType = [connection mediaType]; - if ([mediaType isEqualToString: QTMediaTypeVideo]) - options = [QTCompressionOptions compressionOptionsWithIdentifier: @"QTCompressionOptionsSD480SizeH264Video"]; - else if ([mediaType isEqualToString: QTMediaTypeSound]) - options = [QTCompressionOptions compressionOptionsWithIdentifier: @"QTCompressionOptionsHighQualityAACAudio"]; + if ([mediaType isEqualToString: QTMediaTypeVideo]) + options = [QTCompressionOptions compressionOptionsWithIdentifier: @"QTCompressionOptionsSD480SizeH264Video"]; + else if ([mediaType isEqualToString: QTMediaTypeSound]) + options = [QTCompressionOptions compressionOptionsWithIdentifier: @"QTCompressionOptionsHighQualityAACAudio"]; - [d->fileOutput setCompressionOptions: options forConnection: connection]; - } + [d->fileOutput setCompressionOptions: options forConnection: connection]; + } - [d->fileOutput recordToOutputFileURL: [NSURL fileURLWithPath: juceStringToNS (file.getFullPathName())]]; - isRecording = true; + [d->fileOutput recordToOutputFileURL: [NSURL fileURLWithPath: juceStringToNS (file.getFullPathName())]]; + isRecording = true; } const Time CameraDevice::getTimeOfFirstRecordedFrame() const { - QTCameraDeviceInteral* const d = (QTCameraDeviceInteral*) internal; - if (d->callbackDelegate->firstRecordedTime != 0) - return *d->callbackDelegate->firstRecordedTime; + QTCameraDeviceInteral* const d = (QTCameraDeviceInteral*) internal; + if (d->callbackDelegate->firstRecordedTime != 0) + return *d->callbackDelegate->firstRecordedTime; - return Time(); + return Time(); } void CameraDevice::stopRecording() { - if (isRecording) - { - QTCameraDeviceInteral* const d = (QTCameraDeviceInteral*) internal; - d->resetFile(); - isRecording = false; - } + if (isRecording) + { + QTCameraDeviceInteral* const d = (QTCameraDeviceInteral*) internal; + d->resetFile(); + isRecording = false; + } } void CameraDevice::addListener (CameraImageListener* listenerToAdd) { - QTCameraDeviceInteral* const d = (QTCameraDeviceInteral*) internal; + QTCameraDeviceInteral* const d = (QTCameraDeviceInteral*) internal; - if (listenerToAdd != 0) - d->addListener (listenerToAdd); + if (listenerToAdd != 0) + d->addListener (listenerToAdd); } void CameraDevice::removeListener (CameraImageListener* listenerToRemove) { - QTCameraDeviceInteral* const d = (QTCameraDeviceInteral*) internal; + QTCameraDeviceInteral* const d = (QTCameraDeviceInteral*) internal; - if (listenerToRemove != 0) - d->removeListener (listenerToRemove); + if (listenerToRemove != 0) + d->removeListener (listenerToRemove); } const StringArray CameraDevice::getAvailableDevices() { - const ScopedAutoReleasePool pool; + const ScopedAutoReleasePool pool; - StringArray results; - NSArray* devs = [QTCaptureDevice inputDevicesWithMediaType: QTMediaTypeVideo]; + StringArray results; + NSArray* devs = [QTCaptureDevice inputDevicesWithMediaType: QTMediaTypeVideo]; - for (int i = 0; i < [devs count]; ++i) - { - QTCaptureDevice* dev = (QTCaptureDevice*) [devs objectAtIndex: i]; - results.add (nsStringToJuce ([dev localizedDisplayName])); - } + for (int i = 0; i < [devs count]; ++i) + { + QTCaptureDevice* dev = (QTCaptureDevice*) [devs objectAtIndex: i]; + results.add (nsStringToJuce ([dev localizedDisplayName])); + } - return results; + return results; } CameraDevice* CameraDevice::openDevice (int index, - int minWidth, int minHeight, - int maxWidth, int maxHeight) + int minWidth, int minHeight, + int maxWidth, int maxHeight) { - ScopedPointer d (new CameraDevice (getAvailableDevices() [index], index)); + ScopedPointer d (new CameraDevice (getAvailableDevices() [index], index)); - if (((QTCameraDeviceInteral*) (d->internal))->openingError.isEmpty()) - return d.release(); + if (((QTCameraDeviceInteral*) (d->internal))->openingError.isEmpty()) + return d.release(); - return 0; + return 0; } #endif diff --git a/juce_amalgamated.h b/juce_amalgamated.h index ebb011d633..e6d44e4f18 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -1,39 +1,3 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-9 by Raw Material Software Ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the GNU General - Public License (Version 2), as published by the Free Software Foundation. - A copy of the license is included in the JUCE distribution, or can be found - online at www.gnu.org/licenses. - - JUCE is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - To release a closed-source product which uses JUCE, commercial licenses are - available: visit www.rawmaterialsoftware.com/juce for more information. - - ============================================================================== -*/ - -/* - ============================================================================== - - This header contains the entire Juce source tree, and can be #included in - all your source files. - - As well as including this in your files, you should also add juce_inline.cpp - to your project (or juce_inline.mm on the Mac). - - ============================================================================== -*/ #ifndef __JUCE_AMALGAMATED_TEMPLATE_JUCEHEADER__ #define __JUCE_AMALGAMATED_TEMPLATE_JUCEHEADER__ @@ -44,62 +8,33 @@ #ifndef __JUCE_JUCEHEADER__ #define __JUCE_JUCEHEADER__ -/* - This is the main JUCE header file that applications need to include. - -*/ - // (this includes things that need defining outside of the JUCE namespace) /********* Start of inlined file: juce_StandardHeader.h *********/ #ifndef __JUCE_STANDARDHEADER_JUCEHEADER__ #define __JUCE_STANDARDHEADER_JUCEHEADER__ -/** Current Juce version number. +#define JUCE_MAJOR_VERSION 1 +#define JUCE_MINOR_VERSION 50 - See also SystemStats::getJUCEVersion() for a string version. -*/ -#define JUCE_MAJOR_VERSION 1 -#define JUCE_MINOR_VERSION 50 - -/** Current Juce version number. - - Bits 16 to 32 = major version. - Bits 8 to 16 = minor version. - Bits 0 to 8 = point release (not currently used). - - See also SystemStats::getJUCEVersion() for a string version. -*/ -#define JUCE_VERSION ((JUCE_MAJOR_VERSION << 16) + (JUCE_MINOR_VERSION << 8)) +#define JUCE_VERSION ((JUCE_MAJOR_VERSION << 16) + (JUCE_MINOR_VERSION << 8)) /********* Start of inlined file: juce_TargetPlatform.h *********/ #ifndef __JUCE_TARGETPLATFORM_JUCEHEADER__ #define __JUCE_TARGETPLATFORM_JUCEHEADER__ -/* This file figures out which platform is being built, and defines some macros - that the rest of the code can use for OS-specific compilation. - - Macros that will be set here are: - - - One of JUCE_WINDOWS, JUCE_MAC or JUCE_LINUX. - - Either JUCE_32BIT or JUCE_64BIT, depending on the architecture. - - Either JUCE_LITTLE_ENDIAN or JUCE_BIG_ENDIAN. - - Either JUCE_INTEL or JUCE_PPC - - Either JUCE_GCC or JUCE_MSVC -*/ - #if (defined (_WIN32) || defined (_WIN64)) - #define JUCE_WIN32 1 - #define JUCE_WINDOWS 1 + #define JUCE_WIN32 1 + #define JUCE_WINDOWS 1 #elif defined (LINUX) || defined (__linux__) - #define JUCE_LINUX 1 + #define JUCE_LINUX 1 #elif defined(__APPLE_CPP__) || defined(__APPLE_CC__) #include // (needed to find out what platform we're using) #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR - #define JUCE_IPHONE 1 + #define JUCE_IPHONE 1 #else - #define JUCE_MAC 1 + #define JUCE_MAC 1 #endif #else #error "Unknown platform!" @@ -107,18 +42,21 @@ #if JUCE_WINDOWS #ifdef _MSC_VER - #ifdef _WIN64 - #define JUCE_64BIT 1 - #else - #define JUCE_32BIT 1 - #endif + #ifdef _WIN64 + #define JUCE_64BIT 1 + #else + #define JUCE_32BIT 1 + #endif #endif #ifdef _DEBUG - #define JUCE_DEBUG 1 + #define JUCE_DEBUG 1 + #endif + + #ifdef __MINGW32__ + #define JUCE_MINGW 1 #endif - /** If defined, this indicates that the processor is little-endian. */ #define JUCE_LITTLE_ENDIAN 1 #define JUCE_INTEL 1 @@ -127,33 +65,33 @@ #if JUCE_MAC #ifndef NDEBUG - #define JUCE_DEBUG 1 + #define JUCE_DEBUG 1 #endif #ifdef __LITTLE_ENDIAN__ - #define JUCE_LITTLE_ENDIAN 1 + #define JUCE_LITTLE_ENDIAN 1 #else - #define JUCE_BIG_ENDIAN 1 + #define JUCE_BIG_ENDIAN 1 #endif #if defined (__ppc__) || defined (__ppc64__) - #define JUCE_PPC 1 + #define JUCE_PPC 1 #else - #define JUCE_INTEL 1 + #define JUCE_INTEL 1 #endif #ifdef __LP64__ - #define JUCE_64BIT 1 + #define JUCE_64BIT 1 #else - #define JUCE_32BIT 1 + #define JUCE_32BIT 1 #endif #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4 - #error "Building for OSX 10.3 is no longer supported!" + #error "Building for OSX 10.3 is no longer supported!" #endif #ifndef MAC_OS_X_VERSION_10_5 - #error "To build with 10.4 compatibility, use a 10.5 or 10.6 SDK and set the deployment target to 10.4" + #error "To build with 10.4 compatibility, use a 10.5 or 10.6 SDK and set the deployment target to 10.4" #endif #endif @@ -161,31 +99,31 @@ #if JUCE_IPHONE #ifndef NDEBUG - #define JUCE_DEBUG 1 + #define JUCE_DEBUG 1 #endif #ifdef __LITTLE_ENDIAN__ - #define JUCE_LITTLE_ENDIAN 1 + #define JUCE_LITTLE_ENDIAN 1 #else - #define JUCE_BIG_ENDIAN 1 + #define JUCE_BIG_ENDIAN 1 #endif #endif #if JUCE_LINUX #ifdef _DEBUG - #define JUCE_DEBUG 1 + #define JUCE_DEBUG 1 #endif // Allow override for big-endian Linux platforms #ifndef JUCE_BIG_ENDIAN - #define JUCE_LITTLE_ENDIAN 1 + #define JUCE_LITTLE_ENDIAN 1 #endif #if defined (__LP64__) || defined (_LP64) - #define JUCE_64BIT 1 + #define JUCE_64BIT 1 #else - #define JUCE_32BIT 1 + #define JUCE_32BIT 1 #endif #define JUCE_INTEL 1 @@ -199,7 +137,7 @@ #define JUCE_MSVC 1 #if _MSC_VER >= 1400 - #define JUCE_USE_INTRINSICS 1 + #define JUCE_USE_INTRINSICS 1 #endif #else #error unknown compiler @@ -214,98 +152,46 @@ #ifndef __JUCE_CONFIG_JUCEHEADER__ #define __JUCE_CONFIG_JUCEHEADER__ -/* - This file contains macros that enable/disable various JUCE features. -*/ - -/** The name of the namespace that all Juce classes and functions will be - put inside. If this is not defined, no namespace will be used. -*/ #ifndef JUCE_NAMESPACE #define JUCE_NAMESPACE juce #endif -/** Normally, JUCE_DEBUG is set to 1 or 0 based on compiler and project settings, - but if you define this value, you can override this can force it to be true or - false. -*/ #ifndef JUCE_FORCE_DEBUG //#define JUCE_FORCE_DEBUG 1 #endif -/** If this flag is enabled, the the jassert and jassertfalse macros will - always use Logger::writeToLog() to write a message when an assertion happens. - - Enabling it will also leave this turned on in release builds. When it's disabled, - however, the jassert and jassertfalse macros will not be compiled in a - release build. - - @see jassert, jassertfalse, Logger -*/ #ifndef JUCE_LOG_ASSERTIONS // #define JUCE_LOG_ASSERTIONS 1 #endif -/** Comment out this macro if you haven't got the Steinberg ASIO SDK, without - which the ASIOAudioIODevice class can't be built. See the comments in the - ASIOAudioIODevice class's header file for more info about this. - - (This only affects a Win32 build) -*/ #ifndef JUCE_ASIO #define JUCE_ASIO 1 #endif -/** Comment out this macro to disable the Windows WASAPI audio device type. -*/ #ifndef JUCE_WASAPI // #define JUCE_WASAPI 1 #endif -/** Comment out this macro to disable the Windows WASAPI audio device type. -*/ #ifndef JUCE_DIRECTSOUND #define JUCE_DIRECTSOUND 1 #endif -/** Comment out this macro to disable building of ALSA device support on Linux. -*/ #ifndef JUCE_ALSA #define JUCE_ALSA 1 #endif -/** Comment out this macro to disable building of JACK device support on Linux. -*/ #ifndef JUCE_JACK #define JUCE_JACK 1 #endif -/** Comment out this macro if you don't want to enable QuickTime or if you don't - have the SDK installed. - - If this flag is not enabled, the QuickTimeMovieComponent and QuickTimeAudioFormat - classes will be unavailable. - - On Windows, if you enable this, you'll need to have the QuickTime SDK - installed, and its header files will need to be on your include path. -*/ #if ! (defined (JUCE_QUICKTIME) || JUCE_LINUX || JUCE_IPHONE || (JUCE_WINDOWS && ! JUCE_MSVC)) #define JUCE_QUICKTIME 1 #endif -/** Comment out this macro if you don't want to enable OpenGL or if you don't - have the appropriate headers and libraries available. If it's not enabled, the - OpenGLComponent class will be unavailable. -*/ #ifndef JUCE_OPENGL #define JUCE_OPENGL 1 #endif -/** These flags enable the Ogg-Vorbis and Flac audio formats. - - If you're not going to need either of these formats, turn off the flags to - avoid bloating your codebase with them. -*/ #ifndef JUCE_USE_FLAC #define JUCE_USE_FLAC 1 #endif @@ -314,94 +200,56 @@ #define JUCE_USE_OGGVORBIS 1 #endif -/** This flag lets you enable the AudioCDBurner class. You might want to disable - it to build without the MS SDK under windows. -*/ #if (! defined (JUCE_USE_CDBURNER)) && ! (JUCE_WINDOWS && ! JUCE_MSVC) #define JUCE_USE_CDBURNER 1 #endif -/** This flag lets you enable support for the AudioCDReader class. You might want to disable - it to build without the MS SDK under windows. -*/ #ifndef JUCE_USE_CDREADER #define JUCE_USE_CDREADER 1 #endif -/** Enabling this provides support for cameras, using the CameraDevice class -*/ #if JUCE_QUICKTIME && ! defined (JUCE_USE_CAMERA) // #define JUCE_USE_CAMERA 1 #endif -/** Enabling this macro means that all regions that get repainted will have a coloured - line drawn around them. - - This is handy if you're trying to optimise drawing, because it lets you easily see - when anything is being repainted unnecessarily. -*/ #ifndef JUCE_ENABLE_REPAINT_DEBUGGING // #define JUCE_ENABLE_REPAINT_DEBUGGING 1 #endif -/** Enable this under Linux to use Xinerama for multi-monitor support. -*/ #ifndef JUCE_USE_XINERAMA #define JUCE_USE_XINERAMA 1 #endif -/** Enable this under Linux to use XShm for faster shared-memory rendering. -*/ #ifndef JUCE_USE_XSHM #define JUCE_USE_XSHM 1 #endif -/** Enabling this builds support for VST audio plugins. - @see VSTPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_AU -*/ #ifndef JUCE_PLUGINHOST_VST // #define JUCE_PLUGINHOST_VST 1 #endif -/** Enabling this builds support for AudioUnit audio plugins. - @see AudioUnitPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_VST -*/ #ifndef JUCE_PLUGINHOST_AU // #define JUCE_PLUGINHOST_AU 1 #endif -/** Enabling this will avoid including any UI code in the build. This is handy for - writing command-line utilities, e.g. on linux boxes which don't have some - of the UI libraries installed. -*/ #ifndef JUCE_ONLY_BUILD_CORE_LIBRARY //#define JUCE_ONLY_BUILD_CORE_LIBRARY 1 #endif -/** This lets you disable building of the WebBrowserComponent, if it's not required. -*/ #ifndef JUCE_WEB_BROWSER #define JUCE_WEB_BROWSER 1 #endif -/** Setting this allows the build to use old Carbon libraries that will be - deprecated in newer versions of OSX. This is handy for some backwards-compatibility - reasons. -*/ #ifndef JUCE_SUPPORT_CARBON #define JUCE_SUPPORT_CARBON 1 #endif -/* These flags let you avoid the direct inclusion of some 3rd-party libs in the - codebase - you might need to use this if you're linking to some of these libraries - yourself. -*/ #ifndef JUCE_INCLUDE_ZLIB_CODE - #define JUCE_INCLUDE_ZLIB_CODE 1 + #define JUCE_INCLUDE_ZLIB_CODE 1 #endif #ifndef JUCE_INCLUDE_FLAC_CODE - #define JUCE_INCLUDE_FLAC_CODE 1 + #define JUCE_INCLUDE_FLAC_CODE 1 #endif #ifndef JUCE_INCLUDE_OGGVORBIS_CODE @@ -409,33 +257,21 @@ #endif #ifndef JUCE_INCLUDE_PNGLIB_CODE - #define JUCE_INCLUDE_PNGLIB_CODE 1 + #define JUCE_INCLUDE_PNGLIB_CODE 1 #endif #ifndef JUCE_INCLUDE_JPEGLIB_CODE - #define JUCE_INCLUDE_JPEGLIB_CODE 1 + #define JUCE_INCLUDE_JPEGLIB_CODE 1 #endif -/** Enable this to add extra memory-leak info to the new and delete operators. - - (Currently, this only affects Windows builds in debug mode). -*/ #ifndef JUCE_CHECK_MEMORY_LEAKS #define JUCE_CHECK_MEMORY_LEAKS 1 #endif -/** Enable this to turn on juce's internal catching of exceptions. - - Turning it off will avoid any exception catching. With it on, all exceptions - are passed to the JUCEApplication::unhandledException() callback for logging. -*/ #ifndef JUCE_CATCH_UNHANDLED_EXCEPTIONS #define JUCE_CATCH_UNHANDLED_EXCEPTIONS 1 #endif -/** If this macro is set, the Juce String class will use unicode as its - internal representation. If it isn't set, it'll use ANSI. -*/ #ifndef JUCE_STRINGS_ARE_UNICODE #define JUCE_STRINGS_ARE_UNICODE 1 #endif @@ -462,8 +298,8 @@ /********* End of inlined file: juce_Config.h *********/ #ifdef JUCE_NAMESPACE - #define BEGIN_JUCE_NAMESPACE namespace JUCE_NAMESPACE { - #define END_JUCE_NAMESPACE } + #define BEGIN_JUCE_NAMESPACE namespace JUCE_NAMESPACE { + #define END_JUCE_NAMESPACE } #else #define BEGIN_JUCE_NAMESPACE #define END_JUCE_NAMESPACE @@ -473,20 +309,16 @@ #ifndef __JUCE_PLATFORMDEFS_JUCEHEADER__ #define __JUCE_PLATFORMDEFS_JUCEHEADER__ -/* This file defines miscellaneous macros for debugging, assertions, etc. -*/ - #ifdef JUCE_FORCE_DEBUG #undef JUCE_DEBUG #if JUCE_FORCE_DEBUG - #define JUCE_DEBUG 1 + #define JUCE_DEBUG 1 #endif #endif -/** This macro defines the C calling convention used as the standard for Juce calls. */ #if JUCE_MSVC - #define JUCE_CALLTYPE __stdcall + #define JUCE_CALLTYPE __stdcall #else #define JUCE_CALLTYPE #endif @@ -495,7 +327,7 @@ // (For info about JUCE_LOG_ASSERTIONS, have a look in juce_Config.h) #if JUCE_LOG_ASSERTIONS - #define juce_LogCurrentAssertion juce_LogAssertion (__FILE__, __LINE__); + #define juce_LogCurrentAssertion juce_LogAssertion (__FILE__, __LINE__); #elif defined (JUCE_DEBUG) #define juce_LogCurrentAssertion fprintf (stderr, "JUCE Assertion failure in %s, line %d\n", __FILE__, __LINE__); #else @@ -506,73 +338,52 @@ // If debugging is enabled.. - /** Writes a string to the standard error stream. + #define DBG(dbgtext) Logger::outputDebugString (dbgtext); - This is only compiled in a debug build. - - @see Logger::outputDebugString - */ - #define DBG(dbgtext) Logger::outputDebugString (dbgtext); - - /** Printf's a string to the standard error stream. - - This is only compiled in a debug build. - - @see Logger::outputDebugString - */ - #define DBG_PRINTF(dbgprintf) Logger::outputDebugPrintf dbgprintf; + #define DBG_PRINTF(dbgprintf) Logger::outputDebugPrintf dbgprintf; // Assertions.. #if JUCE_WINDOWS || DOXYGEN - #if JUCE_USE_INTRINSICS - #pragma intrinsic (__debugbreak) + #if JUCE_USE_INTRINSICS + #pragma intrinsic (__debugbreak) - /** This will try to break the debugger if one is currently hosting this app. - @see jassert() - */ - #define juce_breakDebugger __debugbreak(); + #define juce_breakDebugger __debugbreak(); - #elif JUCE_GCC - /** This will try to break the debugger if one is currently hosting this app. - @see jassert() - */ - #define juce_breakDebugger asm("int $3"); - #else - /** This will try to break the debugger if one is currently hosting this app. - @see jassert() - */ - #define juce_breakDebugger { __asm int 3 } - #endif + #elif JUCE_GCC + #define juce_breakDebugger asm("int $3"); + #else + #define juce_breakDebugger { __asm int 3 } + #endif #elif JUCE_MAC - #define juce_breakDebugger Debugger(); + #define juce_breakDebugger Debugger(); #elif JUCE_IPHONE - #define juce_breakDebugger kill (0, SIGTRAP); + #define juce_breakDebugger kill (0, SIGTRAP); #elif JUCE_LINUX - #define juce_breakDebugger kill (0, SIGTRAP); + #define juce_breakDebugger kill (0, SIGTRAP); #endif /** This will always cause an assertion failure. - It is only compiled in a debug build, (unless JUCE_LOG_ASSERTIONS is enabled - in juce_Config.h). + It is only compiled in a debug build, (unless JUCE_LOG_ASSERTIONS is enabled + in juce_Config.h). - @see jassert() + @see jassert() */ - #define jassertfalse { juce_LogCurrentAssertion; if (JUCE_NAMESPACE::juce_isRunningUnderDebugger()) juce_breakDebugger; } + #define jassertfalse { juce_LogCurrentAssertion; if (JUCE_NAMESPACE::juce_isRunningUnderDebugger()) juce_breakDebugger; } /** Platform-independent assertion macro. - This gets optimised out when not being built with debugging turned on. + This gets optimised out when not being built with debugging turned on. - Be careful not to call any functions within its arguments that are vital to - the behaviour of the program, because these won't get called in the release - build. + Be careful not to call any functions within its arguments that are vital to + the behaviour of the program, because these won't get called in the release + build. - @see jassertfalse + @see jassertfalse */ - #define jassert(expression) { if (! (expression)) jassertfalse } + #define jassert(expression) { if (! (expression)) jassertfalse } #else @@ -581,12 +392,12 @@ #define DBG(dbgtext) #define DBG_PRINTF(dbgprintf) - #define jassertfalse { juce_LogCurrentAssertion } + #define jassertfalse { juce_LogCurrentAssertion } #if JUCE_LOG_ASSERTIONS - #define jassert(expression) { if (! (expression)) jassertfalse } + #define jassert(expression) { if (! (expression)) jassertfalse } #else - #define jassert(a) { } + #define jassert(a) { } #endif #endif @@ -598,29 +409,26 @@ /** A compile-time assertion macro. - If the expression parameter is false, the macro will cause a compile error. + If the expression parameter is false, the macro will cause a compile error. */ -#define static_jassert(expression) JuceStaticAssert::dummy(); +#define static_jassert(expression) JuceStaticAssert::dummy(); #if JUCE_CATCH_UNHANDLED_EXCEPTIONS #define JUCE_TRY try - /** Used in try-catch blocks, this macro will send exceptions to the JUCEApplication - object so they can be logged by the application if it wants to. - */ #define JUCE_CATCH_EXCEPTION \ - catch (const std::exception& e) \ - { \ - JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \ - } \ - catch (...) \ - { \ - JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); \ - } + catch (const std::exception& e) \ + { \ + JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); \ + } \ + catch (...) \ + { \ + JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); \ + } - #define JUCE_CATCH_ALL catch (...) {} - #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse } + #define JUCE_CATCH_ALL catch (...) {} + #define JUCE_CATCH_ALL_ASSERT catch (...) { jassertfalse } #else @@ -634,47 +442,19 @@ // Macros for inlining. #if JUCE_MSVC - /** A platform-independent way of forcing an inline function. - - Use the syntax: @code - forcedinline void myfunction (int x) - @endcode - */ - #ifdef JUCE_DEBUG - #define forcedinline __forceinline + #ifndef JUCE_DEBUG + #define forcedinline __forceinline #else - #define forcedinline inline + #define forcedinline inline #endif - /** A platform-independent way of stopping the compiler inlining a function. - - Use the syntax: @code - juce_noinline void myfunction (int x) - @endcode - */ - #define juce_noinline - #else - /** A platform-independent way of forcing an inline function. - - Use the syntax: @code - forcedinline void myfunction (int x) - @endcode - */ #ifndef JUCE_DEBUG - #define forcedinline inline __attribute__((always_inline)) + #define forcedinline inline __attribute__((always_inline)) #else - #define forcedinline inline + #define forcedinline inline #endif - /** A platform-independent way of stopping the compiler inlining a function. - - Use the syntax: @code - juce_noinline void myfunction (int x) - @endcode - */ - #define juce_noinline __attribute__((noinline)) - #endif #endif // __JUCE_PLATFORMDEFS_JUCEHEADER__ @@ -720,25 +500,23 @@ // DLL building settings on Win32 #if JUCE_MSVC #ifdef JUCE_DLL_BUILD - #define JUCE_API __declspec (dllexport) - #pragma warning (disable: 4251) + #define JUCE_API __declspec (dllexport) + #pragma warning (disable: 4251) #elif defined (JUCE_DLL) - #define JUCE_API __declspec (dllimport) - #pragma warning (disable: 4251) + #define JUCE_API __declspec (dllimport) + #pragma warning (disable: 4251) #endif #elif defined (__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) #ifdef JUCE_DLL_BUILD - #define JUCE_API __attribute__ ((visibility("default"))) + #define JUCE_API __attribute__ ((visibility("default"))) #endif #endif #ifndef JUCE_API - /** This macro is added to all juce public class declarations. */ #define JUCE_API #endif -/** This macro is added to all juce public function declarations. */ -#define JUCE_PUBLIC_FUNCTION JUCE_API JUCE_CALLTYPE +#define JUCE_PUBLIC_FUNCTION JUCE_API JUCE_CALLTYPE // Now include some basics that are needed by most of the Juce classes... BEGIN_JUCE_NAMESPACE @@ -753,77 +531,44 @@ extern bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger(); #ifndef __JUCE_MEMORY_JUCEHEADER__ #define __JUCE_MEMORY_JUCEHEADER__ -/* - This file defines the various juce_malloc(), juce_free() macros that should be used in - preference to the standard calls. -*/ - #if defined (JUCE_DEBUG) && JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS #ifndef JUCE_DLL - // Win32 debug non-DLL versions.. + // Win32 debug non-DLL versions.. - /** This should be used instead of calling malloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_malloc(numBytes) _malloc_dbg (numBytes, _NORMAL_BLOCK, __FILE__, __LINE__) + #define juce_malloc(numBytes) _malloc_dbg (numBytes, _NORMAL_BLOCK, __FILE__, __LINE__) - /** This should be used instead of calling calloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_calloc(numBytes) _calloc_dbg (1, numBytes, _NORMAL_BLOCK, __FILE__, __LINE__) + #define juce_calloc(numBytes) _calloc_dbg (1, numBytes, _NORMAL_BLOCK, __FILE__, __LINE__) - /** This should be used instead of calling realloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_realloc(location, numBytes) _realloc_dbg (location, numBytes, _NORMAL_BLOCK, __FILE__, __LINE__) + #define juce_realloc(location, numBytes) _realloc_dbg (location, numBytes, _NORMAL_BLOCK, __FILE__, __LINE__) - /** This should be used instead of calling free directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_free(location) _free_dbg (location, _NORMAL_BLOCK) + #define juce_free(location) _free_dbg (location, _NORMAL_BLOCK) #else - // Win32 debug DLL versions.. + // Win32 debug DLL versions.. - // For the DLL, we'll define some functions in the DLL that will be used for allocation - that - // way all juce calls in the DLL and in the host API will all use the same allocator. - extern JUCE_API void* juce_DebugMalloc (const int size, const char* file, const int line); - extern JUCE_API void* juce_DebugCalloc (const int size, const char* file, const int line); - extern JUCE_API void* juce_DebugRealloc (void* const block, const int size, const char* file, const int line); - extern JUCE_API void juce_DebugFree (void* const block); + // For the DLL, we'll define some functions in the DLL that will be used for allocation - that + // way all juce calls in the DLL and in the host API will all use the same allocator. + extern JUCE_API void* juce_DebugMalloc (const int size, const char* file, const int line); + extern JUCE_API void* juce_DebugCalloc (const int size, const char* file, const int line); + extern JUCE_API void* juce_DebugRealloc (void* const block, const int size, const char* file, const int line); + extern JUCE_API void juce_DebugFree (void* const block); - /** This should be used instead of calling malloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_malloc(numBytes) JUCE_NAMESPACE::juce_DebugMalloc (numBytes, __FILE__, __LINE__) + #define juce_malloc(numBytes) JUCE_NAMESPACE::juce_DebugMalloc (numBytes, __FILE__, __LINE__) - /** This should be used instead of calling calloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_calloc(numBytes) JUCE_NAMESPACE::juce_DebugCalloc (numBytes, __FILE__, __LINE__) + #define juce_calloc(numBytes) JUCE_NAMESPACE::juce_DebugCalloc (numBytes, __FILE__, __LINE__) - /** This should be used instead of calling realloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_realloc(location, numBytes) JUCE_NAMESPACE::juce_DebugRealloc (location, numBytes, __FILE__, __LINE__) + #define juce_realloc(location, numBytes) JUCE_NAMESPACE::juce_DebugRealloc (location, numBytes, __FILE__, __LINE__) - /** This should be used instead of calling free directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_free(location) JUCE_NAMESPACE::juce_DebugFree (location) + #define juce_free(location) JUCE_NAMESPACE::juce_DebugFree (location) #endif #if ! defined (_AFXDLL) - /** This macro can be added to classes to add extra debugging information to the memory - allocated for them, so you can see the type of objects involved when there's a dump - of leaked objects at program shutdown. (Only works on win32 at the moment). - */ - #define juce_UseDebuggingNewOperator \ - static void* operator new (size_t sz) { void* const p = juce_malloc ((int) sz); return (p != 0) ? p : ::operator new (sz); } \ - static void* operator new (size_t sz, void* p) { return ::operator new (sz, p); } \ - static void operator delete (void* p) { juce_free (p); } + #define juce_UseDebuggingNewOperator \ + static void* operator new (size_t sz) { void* const p = juce_malloc ((int) sz); return (p != 0) ? p : ::operator new (sz); } \ + static void* operator new (size_t sz, void* p) { return ::operator new (sz, p); } \ + static void operator delete (void* p) { juce_free (p); } #endif #elif defined (JUCE_DLL) @@ -837,94 +582,54 @@ extern bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger(); extern JUCE_API void* juce_Realloc (void* const block, const int size); extern JUCE_API void juce_Free (void* const block); - /** This should be used instead of calling malloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_malloc(numBytes) JUCE_NAMESPACE::juce_Malloc (numBytes) + #define juce_malloc(numBytes) JUCE_NAMESPACE::juce_Malloc (numBytes) - /** This should be used instead of calling calloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_calloc(numBytes) JUCE_NAMESPACE::juce_Calloc (numBytes) + #define juce_calloc(numBytes) JUCE_NAMESPACE::juce_Calloc (numBytes) - /** This should be used instead of calling realloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_realloc(location, numBytes) JUCE_NAMESPACE::juce_Realloc (location, numBytes) + #define juce_realloc(location, numBytes) JUCE_NAMESPACE::juce_Realloc (location, numBytes) - /** This should be used instead of calling free directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_free(location) JUCE_NAMESPACE::juce_Free (location) + #define juce_free(location) JUCE_NAMESPACE::juce_Free (location) #define juce_UseDebuggingNewOperator \ - static void* operator new (size_t sz) { void* const p = juce_malloc ((int) sz); return (p != 0) ? p : ::operator new (sz); } \ - static void* operator new (size_t sz, void* p) { return ::operator new (sz, p); } \ - static void operator delete (void* p) { juce_free (p); } + static void* operator new (size_t sz) { void* const p = juce_malloc ((int) sz); return (p != 0) ? p : ::operator new (sz); } \ + static void* operator new (size_t sz, void* p) { return ::operator new (sz, p); } \ + static void operator delete (void* p) { juce_free (p); } #else // Mac, Linux and Win32 (release) versions.. - /** This should be used instead of calling malloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_malloc(numBytes) malloc (numBytes) + #define juce_malloc(numBytes) malloc (numBytes) - /** This should be used instead of calling calloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_calloc(numBytes) calloc (1, numBytes) + #define juce_calloc(numBytes) calloc (1, numBytes) - /** This should be used instead of calling realloc directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_realloc(location, numBytes) realloc (location, numBytes) + #define juce_realloc(location, numBytes) realloc (location, numBytes) - /** This should be used instead of calling free directly. - Only use direct memory allocation if there's really no way to use a HeapBlock object instead! - */ - #define juce_free(location) free (location) + #define juce_free(location) free (location) #endif -/** This macro can be added to classes to add extra debugging information to the memory - allocated for them, so you can see the type of objects involved when there's a dump - of leaked objects at program shutdown. (Only works on win32 at the moment). - - Note that if you create a class that inherits from a class that uses this macro, - your class must also use the macro, otherwise you'll probably get compile errors - because of ambiguous new operators. - - Most of the JUCE classes use it, so see these for examples of where it should go. -*/ #ifndef juce_UseDebuggingNewOperator #define juce_UseDebuggingNewOperator #endif #if JUCE_MSVC - /** This is a compiler-independent way of declaring a variable as being thread-local. - - E.g. - @code - juce_ThreadLocal int myVariable; - @endcode - */ - #define juce_ThreadLocal __declspec(thread) + #define juce_ThreadLocal __declspec(thread) #else - #define juce_ThreadLocal __thread + #define juce_ThreadLocal __thread #endif -/** Clears a block of memory. */ -#define zeromem(memory, numBytes) memset (memory, 0, numBytes) +#if JUCE_MINGW + #define alloca __builtin_alloca +#endif -/** Clears a reference to a local structure. */ -#define zerostruct(structure) memset (&structure, 0, sizeof (structure)) +inline void zeromem (void* memory, size_t numBytes) { memset (memory, 0, numBytes); } -/** A handy macro that calls delete on a pointer if it's non-zero, and - then sets the pointer to null. -*/ -#define deleteAndZero(pointer) { delete (pointer); (pointer) = 0; } +template +inline void zerostruct (Type& structure) { memset (&structure, 0, sizeof (structure)); } + +template +inline void deleteAndZero (Type& pointer) { delete pointer; pointer = 0; } #endif // __JUCE_MEMORY_JUCEHEADER__ /********* End of inlined file: juce_Memory.h *********/ @@ -933,284 +638,146 @@ extern bool JUCE_PUBLIC_FUNCTION juce_isRunningUnderDebugger(); #ifndef __JUCE_MATHSFUNCTIONS_JUCEHEADER__ #define __JUCE_MATHSFUNCTIONS_JUCEHEADER__ -/* - This file sets up some handy mathematical typdefs and functions. -*/ - // Definitions for the int8, int16, int32, int64 and pointer_sized_int types. -/** A platform-independent 8-bit signed integer type. */ -typedef signed char int8; -/** A platform-independent 8-bit unsigned integer type. */ -typedef unsigned char uint8; -/** A platform-independent 16-bit signed integer type. */ -typedef signed short int16; -/** A platform-independent 16-bit unsigned integer type. */ -typedef unsigned short uint16; -/** A platform-independent 32-bit signed integer type. */ -typedef signed int int32; -/** A platform-independent 32-bit unsigned integer type. */ -typedef unsigned int uint32; +typedef signed char int8; +typedef unsigned char uint8; +typedef signed short int16; +typedef unsigned short uint16; +typedef signed int int32; +typedef unsigned int uint32; #if JUCE_MSVC - /** A platform-independent 64-bit integer type. */ - typedef __int64 int64; - /** A platform-independent 64-bit unsigned integer type. */ - typedef unsigned __int64 uint64; - /** A platform-independent macro for writing 64-bit literals, needed because - different compilers have different syntaxes for this. - - E.g. writing literal64bit (0x1000000000) will translate to 0x1000000000LL for - GCC, or 0x1000000000 for MSVC. - */ - #define literal64bit(longLiteral) ((__int64) longLiteral) + typedef __int64 int64; + typedef unsigned __int64 uint64; + #define literal64bit(longLiteral) ((__int64) longLiteral) #else - /** A platform-independent 64-bit integer type. */ - typedef long long int64; - /** A platform-independent 64-bit unsigned integer type. */ - typedef unsigned long long uint64; - /** A platform-independent macro for writing 64-bit literals, needed because - different compilers have different syntaxes for this. - - E.g. writing literal64bit (0x1000000000) will translate to 0x1000000000LL for - GCC, or 0x1000000000 for MSVC. - */ - #define literal64bit(longLiteral) (longLiteral##LL) + typedef long long int64; + typedef unsigned long long uint64; + #define literal64bit(longLiteral) (longLiteral##LL) #endif #if JUCE_64BIT - /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef int64 pointer_sized_int; - /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef uint64 pointer_sized_uint; + typedef int64 pointer_sized_int; + typedef uint64 pointer_sized_uint; #elif _MSC_VER >= 1300 - /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef _W64 int pointer_sized_int; - /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef _W64 unsigned int pointer_sized_uint; + typedef _W64 int pointer_sized_int; + typedef _W64 unsigned int pointer_sized_uint; #else - /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef int pointer_sized_int; - /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef unsigned int pointer_sized_uint; + typedef int pointer_sized_int; + typedef unsigned int pointer_sized_uint; #endif -/** A platform-independent unicode character type. */ -typedef wchar_t juce_wchar; +typedef wchar_t juce_wchar; // Some indispensible min/max functions -/** Returns the larger of two values. */ -forcedinline int jmax (const int a, const int b) throw() { return (a < b) ? b : a; } -/** Returns the larger of two values. */ -forcedinline int64 jmax (const int64 a, const int64 b) throw() { return (a < b) ? b : a; } -/** Returns the larger of two values. */ -forcedinline float jmax (const float a, const float b) throw() { return (a < b) ? b : a; } -/** Returns the larger of two values. */ -forcedinline double jmax (const double a, const double b) throw() { return (a < b) ? b : a; } +template +inline Type jmax (const Type a, const Type b) { return (a < b) ? b : a; } -/** Returns the larger of three values. */ -inline int jmax (const int a, const int b, const int c) throw() { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); } -/** Returns the larger of three values. */ -inline int64 jmax (const int64 a, const int64 b, const int64 c) throw() { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); } -/** Returns the larger of three values. */ -inline float jmax (const float a, const float b, const float c) throw() { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); } -/** Returns the larger of three values. */ -inline double jmax (const double a, const double b, const double c) throw() { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); } +template +inline Type jmax (const Type a, const Type b, const Type c) { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); } -/** Returns the larger of four values. */ -inline int jmax (const int a, const int b, const int c, const int d) throw() { return jmax (a, jmax (b, c, d)); } -/** Returns the larger of four values. */ -inline int64 jmax (const int64 a, const int64 b, const int64 c, const int64 d) throw() { return jmax (a, jmax (b, c, d)); } -/** Returns the larger of four values. */ -inline float jmax (const float a, const float b, const float c, const float d) throw() { return jmax (a, jmax (b, c, d)); } -/** Returns the larger of four values. */ -inline double jmax (const double a, const double b, const double c, const double d) throw() { return jmax (a, jmax (b, c, d)); } +template +inline Type jmax (const Type a, const Type b, const Type c, const Type d) { return jmax (a, jmax (b, c, d)); } -/** Returns the smaller of two values. */ -inline int jmin (const int a, const int b) throw() { return (a > b) ? b : a; } -/** Returns the smaller of two values. */ -inline int64 jmin (const int64 a, const int64 b) throw() { return (a > b) ? b : a; } -/** Returns the smaller of two values. */ -inline float jmin (const float a, const float b) throw() { return (a > b) ? b : a; } -/** Returns the smaller of two values. */ -inline double jmin (const double a, const double b) throw() { return (a > b) ? b : a; } +template +inline Type jmin (const Type a, const Type b) { return (a > b) ? b : a; } -/** Returns the smaller of three values. */ -inline int jmin (const int a, const int b, const int c) throw() { return (a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a); } -/** Returns the smaller of three values. */ -inline int64 jmin (const int64 a, const int64 b, const int64 c) throw() { return (a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a); } -/** Returns the smaller of three values. */ -inline float jmin (const float a, const float b, const float c) throw() { return (a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a); } -/** Returns the smaller of three values. */ -inline double jmin (const double a, const double b, const double c) throw() { return (a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a); } +template +inline Type jmin (const Type a, const Type b, const Type c) { return (a > b) ? ((b > c) ? c : b) : ((a > c) ? c : a); } -/** Returns the smaller of four values. */ -inline int jmin (const int a, const int b, const int c, const int d) throw() { return jmin (a, jmin (b, c, d)); } -/** Returns the smaller of four values. */ -inline int64 jmin (const int64 a, const int64 b, const int64 c, const int64 d) throw() { return jmin (a, jmin (b, c, d)); } -/** Returns the smaller of four values. */ -inline float jmin (const float a, const float b, const float c, const float d) throw() { return jmin (a, jmin (b, c, d)); } -/** Returns the smaller of four values. */ -inline double jmin (const double a, const double b, const double c, const double d) throw() { return jmin (a, jmin (b, c, d)); } +template +inline Type jmin (const Type a, const Type b, const Type c, const Type d) { return jmin (a, jmin (b, c, d)); } -/** Constrains a value to keep it within a given range. - - This will check that the specified value lies between the lower and upper bounds - specified, and if not, will return the nearest value that would be in-range. Effectively, - it's like calling jmax (lowerLimit, jmin (upperLimit, value)). - - Note that it expects that lowerLimit <= upperLimit. If this isn't true, - the results will be unpredictable. - - @param lowerLimit the minimum value to return - @param upperLimit the maximum value to return - @param valueToConstrain the value to try to return - @returns the closest value to valueToConstrain which lies between lowerLimit - and upperLimit (inclusive) - @see jlimit0To, jmin, jmax -*/ template inline Type jlimit (const Type lowerLimit, - const Type upperLimit, - const Type valueToConstrain) throw() + const Type upperLimit, + const Type valueToConstrain) throw() { - jassert (lowerLimit <= upperLimit); // if these are in the wrong order, results are unpredictable.. + jassert (lowerLimit <= upperLimit); // if these are in the wrong order, results are unpredictable.. - return (valueToConstrain < lowerLimit) ? lowerLimit - : ((valueToConstrain > upperLimit) ? upperLimit - : valueToConstrain); + return (valueToConstrain < lowerLimit) ? lowerLimit + : ((valueToConstrain > upperLimit) ? upperLimit + : valueToConstrain); } -/** Handy function to swap two values over. -*/ template inline void swapVariables (Type& variable1, Type& variable2) { - const Type tempVal = variable1; - variable1 = variable2; - variable2 = tempVal; + const Type tempVal = variable1; + variable1 = variable2; + variable2 = tempVal; } -/** Handy macro for getting the number of elements in a simple const C array. - - E.g. - @code - static int myArray[] = { 1, 2, 3 }; - - int numElements = numElementsInArray (myArray) // returns 3 - @endcode -*/ -#define numElementsInArray(a) ((int) (sizeof (a) / sizeof ((a)[0]))) +template +inline int numElementsInArray (Type& array) { return (int) (sizeof (array) / sizeof (array[0])); } // Some useful maths functions that aren't always present with all compilers and build settings. -/** Using juce_hypot and juce_hypotf is easier than dealing with all the different - versions of these functions of various platforms and compilers. */ inline double juce_hypot (double a, double b) { #if JUCE_WINDOWS - return _hypot (a, b); + return _hypot (a, b); #else - return hypot (a, b); + return hypot (a, b); #endif } -/** Using juce_hypot and juce_hypotf is easier than dealing with all the different - versions of these functions of various platforms and compilers. */ inline float juce_hypotf (float a, float b) { #if JUCE_WINDOWS - return (float) _hypot (a, b); + return (float) _hypot (a, b); #else - return hypotf (a, b); + return hypotf (a, b); #endif } -/** 64-bit abs function. */ inline int64 abs64 (const int64 n) { - return (n >= 0) ? n : -n; + return (n >= 0) ? n : -n; } -/** A predefined value for Pi, at double-precision. - - @see float_Pi -*/ const double double_Pi = 3.1415926535897932384626433832795; -/** A predefined value for Pi, at sngle-precision. - - @see double_Pi -*/ const float float_Pi = 3.14159265358979323846f; -/** The isfinite() method seems to vary between platforms, so this is a - platform-independent function for it. -*/ template inline bool juce_isfinite (FloatingPointType value) { - #if JUCE_WINDOWS - return _finite (value); - #else - return std::isfinite (value); - #endif + #if JUCE_WINDOWS + return _finite (value); + #else + return std::isfinite (value); + #endif } -/** Fast floating-point-to-integer conversion. +template +inline int roundToInt (const FloatType value) throw() +{ + union { int asInt[2]; double asDouble; } n; + n.asDouble = ((double) value) + 6755399441055744.0; - This is faster than using the normal c++ cast to convert a double to an int, and - it will round the value to the nearest integer, rather than rounding it down - like the normal cast does. + #if JUCE_BIG_ENDIAN + return n.asInt [1]; + #else + return n.asInt [0]; + #endif +} + +inline int roundToIntAccurate (const double value) throw() +{ + return roundToInt (value + 1.5e-8); +} - Note that this routine gets its speed at the expense of some accuracy, and when - rounding values whose floating point component is exactly 0.5, odd numbers and - even numbers will be rounded up or down differently. For a more accurate conversion, - see roundDoubleToIntAccurate(). -*/ inline int roundDoubleToInt (const double value) throw() { - union { int asInt[2]; double asDouble; } n; - n.asDouble = value + 6755399441055744.0; - - #if JUCE_BIG_ENDIAN - return n.asInt [1]; - #else - return n.asInt [0]; - #endif + return roundToInt (value); } -/** Fast floating-point-to-integer conversion. - - This is a slightly slower and slightly more accurate version of roundDoubleToInt(). It works - fine for values above zero, but negative numbers are rounded the wrong way. -*/ -inline int roundDoubleToIntAccurate (const double value) throw() -{ - return roundDoubleToInt (value + 1.5e-8); -} - -/** Fast floating-point-to-integer conversion. - - This is faster than using the normal c++ cast to convert a float to an int, and - it will round the value to the nearest integer, rather than rounding it down - like the normal cast does. - - Note that this routine gets its speed at the expense of some accuracy, and when - rounding values whose floating point component is exactly 0.5, odd numbers and - even numbers will be rounded up or down differently. -*/ inline int roundFloatToInt (const float value) throw() { - union { int asInt[2]; double asDouble; } n; - n.asDouble = value + 6755399441055744.0; - - #if JUCE_BIG_ENDIAN - return n.asInt [1]; - #else - return n.asInt [0]; - #endif + return roundToInt (value); } #endif // __JUCE_MATHSFUNCTIONS_JUCEHEADER__ @@ -1220,66 +787,45 @@ inline int roundFloatToInt (const float value) throw() #ifndef __JUCE_BYTEORDER_JUCEHEADER__ #define __JUCE_BYTEORDER_JUCEHEADER__ -/** Contains static methods for converting the byte order between different - endiannesses. -*/ class JUCE_API ByteOrder { public: - /** Swaps the upper and lower bytes of a 16-bit integer. */ - static uint16 swap (uint16 value); + static uint16 swap (uint16 value); - /** Reverses the order of the 4 bytes in a 32-bit integer. */ - static uint32 swap (uint32 value); + static uint32 swap (uint32 value); - /** Reverses the order of the 8 bytes in a 64-bit integer. */ - static uint64 swap (uint64 value); + static uint64 swap (uint64 value); - /** Swaps the byte order of a 16-bit int if the CPU is big-endian */ - static uint16 swapIfBigEndian (const uint16 value); + static uint16 swapIfBigEndian (const uint16 value); - /** Swaps the byte order of a 32-bit int if the CPU is big-endian */ - static uint32 swapIfBigEndian (const uint32 value); + static uint32 swapIfBigEndian (const uint32 value); - /** Swaps the byte order of a 64-bit int if the CPU is big-endian */ - static uint64 swapIfBigEndian (const uint64 value); + static uint64 swapIfBigEndian (const uint64 value); - /** Swaps the byte order of a 16-bit int if the CPU is little-endian */ - static uint16 swapIfLittleEndian (const uint16 value); + static uint16 swapIfLittleEndian (const uint16 value); - /** Swaps the byte order of a 32-bit int if the CPU is little-endian */ - static uint32 swapIfLittleEndian (const uint32 value); + static uint32 swapIfLittleEndian (const uint32 value); - /** Swaps the byte order of a 64-bit int if the CPU is little-endian */ - static uint64 swapIfLittleEndian (const uint64 value); + static uint64 swapIfLittleEndian (const uint64 value); - /** Turns 4 bytes into a little-endian integer. */ - static uint32 littleEndianInt (const char* const bytes); + static uint32 littleEndianInt (const char* const bytes); - /** Turns 2 bytes into a little-endian integer. */ - static uint16 littleEndianShort (const char* const bytes); + static uint16 littleEndianShort (const char* const bytes); - /** Turns 4 bytes into a big-endian integer. */ - static uint32 bigEndianInt (const char* const bytes); + static uint32 bigEndianInt (const char* const bytes); - /** Turns 2 bytes into a big-endian integer. */ - static uint16 bigEndianShort (const char* const bytes); + static uint16 bigEndianShort (const char* const bytes); - /** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ - static int littleEndian24Bit (const char* const bytes); + static int littleEndian24Bit (const char* const bytes); - /** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ - static int bigEndian24Bit (const char* const bytes); + static int bigEndian24Bit (const char* const bytes); - /** Copies a 24-bit number to 3 little-endian bytes. */ - static void littleEndian24BitToChars (const int value, char* const destBytes); + static void littleEndian24BitToChars (const int value, char* const destBytes); - /** Copies a 24-bit number to 3 big-endian bytes. */ - static void bigEndian24BitToChars (const int value, char* const destBytes); + static void bigEndian24BitToChars (const int value, char* const destBytes); - /** Returns true if the current CPU is big-endian. */ - static bool isBigEndian(); + static bool isBigEndian(); }; #if JUCE_USE_INTRINSICS @@ -1289,72 +835,72 @@ public: inline uint16 ByteOrder::swap (uint16 n) { #if JUCE_USE_INTRINSICSxxx // agh - the MS compiler has an internal error when you try to use this intrinsic! - return (uint16) _byteswap_ushort (n); + return (uint16) _byteswap_ushort (n); #else - return (uint16) ((n << 8) | (n >> 8)); + return (uint16) ((n << 8) | (n >> 8)); #endif } inline uint32 ByteOrder::swap (uint32 n) { #if JUCE_MAC || JUCE_IPHONE - return OSSwapInt32 (n); + return OSSwapInt32 (n); #elif JUCE_GCC - asm("bswap %%eax" : "=a"(n) : "a"(n)); - return n; + asm("bswap %%eax" : "=a"(n) : "a"(n)); + return n; #elif JUCE_USE_INTRINSICS - return _byteswap_ulong (n); + return _byteswap_ulong (n); #else - __asm { - mov eax, n - bswap eax - mov n, eax - } - return n; + __asm { + mov eax, n + bswap eax + mov n, eax + } + return n; #endif } inline uint64 ByteOrder::swap (uint64 value) { #if JUCE_MAC || JUCE_IPHONE - return OSSwapInt64 (value); + return OSSwapInt64 (value); #elif JUCE_USE_INTRINSICS - return _byteswap_uint64 (value); + return _byteswap_uint64 (value); #else - return (((int64) swap ((uint32) value)) << 32) | swap ((uint32) (value >> 32)); + return (((int64) swap ((uint32) value)) << 32) | swap ((uint32) (value >> 32)); #endif } #if JUCE_LITTLE_ENDIAN - inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) { return v; } - inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) { return v; } - inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) { return v; } - inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) { return swap (v); } - inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) { return swap (v); } - inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) { return swap (v); } - inline uint32 ByteOrder::littleEndianInt (const char* const bytes) { return *(uint32*) bytes; } - inline uint16 ByteOrder::littleEndianShort (const char* const bytes) { return *(uint16*) bytes; } - inline uint32 ByteOrder::bigEndianInt (const char* const bytes) { return swap (*(uint32*) bytes); } - inline uint16 ByteOrder::bigEndianShort (const char* const bytes) { return swap (*(uint16*) bytes); } - inline bool ByteOrder::isBigEndian() { return false; } + inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) { return v; } + inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) { return v; } + inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) { return v; } + inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) { return swap (v); } + inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) { return swap (v); } + inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) { return swap (v); } + inline uint32 ByteOrder::littleEndianInt (const char* const bytes) { return *(uint32*) bytes; } + inline uint16 ByteOrder::littleEndianShort (const char* const bytes) { return *(uint16*) bytes; } + inline uint32 ByteOrder::bigEndianInt (const char* const bytes) { return swap (*(uint32*) bytes); } + inline uint16 ByteOrder::bigEndianShort (const char* const bytes) { return swap (*(uint16*) bytes); } + inline bool ByteOrder::isBigEndian() { return false; } #else - inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) { return swap (v); } - inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) { return swap (v); } - inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) { return swap (v); } - inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) { return v; } - inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) { return v; } - inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) { return v; } - inline uint32 ByteOrder::littleEndianInt (const char* const bytes) { return swap (*(uint32*) bytes); } - inline uint16 ByteOrder::littleEndianShort (const char* const bytes) { return swap (*(uint16*) bytes); } - inline uint32 ByteOrder::bigEndianInt (const char* const bytes) { return *(uint32*) bytes; } - inline uint16 ByteOrder::bigEndianShort (const char* const bytes) { return *(uint16*) bytes; } - inline bool ByteOrder::isBigEndian() { return true; } + inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) { return swap (v); } + inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) { return swap (v); } + inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) { return swap (v); } + inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) { return v; } + inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) { return v; } + inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) { return v; } + inline uint32 ByteOrder::littleEndianInt (const char* const bytes) { return swap (*(uint32*) bytes); } + inline uint16 ByteOrder::littleEndianShort (const char* const bytes) { return swap (*(uint16*) bytes); } + inline uint32 ByteOrder::bigEndianInt (const char* const bytes) { return *(uint32*) bytes; } + inline uint16 ByteOrder::bigEndianShort (const char* const bytes) { return *(uint16*) bytes; } + inline bool ByteOrder::isBigEndian() { return true; } #endif -inline int ByteOrder::littleEndian24Bit (const char* const bytes) { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); } -inline int ByteOrder::bigEndian24Bit (const char* const bytes) { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); } -inline void ByteOrder::littleEndian24BitToChars (const int value, char* const destBytes) { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); } -inline void ByteOrder::bigEndian24BitToChars (const int value, char* const destBytes) { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); } +inline int ByteOrder::littleEndian24Bit (const char* const bytes) { return (((int) bytes[2]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[0]); } +inline int ByteOrder::bigEndian24Bit (const char* const bytes) { return (((int) bytes[0]) << 16) | (((uint32) (uint8) bytes[1]) << 8) | ((uint32) (uint8) bytes[2]); } +inline void ByteOrder::littleEndian24BitToChars (const int value, char* const destBytes) { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); } +inline void ByteOrder::bigEndian24BitToChars (const int value, char* const destBytes) { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); } #endif // __JUCE_BYTEORDER_JUCEHEADER__ /********* End of inlined file: juce_ByteOrder.h *********/ @@ -1371,1304 +917,506 @@ inline void ByteOrder::bigEndian24BitToChars (const int value, char* const destB #ifndef __JUCE_CHARACTERFUNCTIONS_JUCEHEADER__ #define __JUCE_CHARACTERFUNCTIONS_JUCEHEADER__ -/* The String class can either use wchar_t unicode characters, or 8-bit characters - (in the default system encoding) as its internal representation. - - To use unicode, define the JUCE_STRINGS_ARE_UNICODE macro in juce_Config.h - - Be sure to use "tchar" for characters rather than "char", and always wrap string - literals in the T("abcd") macro, so that it all works nicely either way round. -*/ #if JUCE_STRINGS_ARE_UNICODE - #define JUCE_T(stringLiteral) (L##stringLiteral) - typedef juce_wchar tchar; + #define JUCE_T(stringLiteral) (L##stringLiteral) + typedef juce_wchar tchar; #define juce_tcharToWideChar(c) (c) #else - #define JUCE_T(stringLiteral) (stringLiteral) - typedef char tchar; + #define JUCE_T(stringLiteral) (stringLiteral) + typedef char tchar; #define juce_tcharToWideChar(c) ((juce_wchar) (unsigned char) (c)) #endif #if ! JUCE_DONT_DEFINE_MACROS -/** The 'T' macro allows a literal string to be compiled using either 8-bit characters - or unicode. - - If you write your string literals in the form T("xyz"), this will either be compiled - as "xyz" for non-unicode builds, or L"xyz" for unicode builds, depending on whether the - JUCE_STRINGS_ARE_UNICODE macro has been set in juce_Config.h - - Because the 'T' symbol is occasionally used inside 3rd-party library headers which you - may need to include after juce.h, you can use the juce_withoutMacros.h file (in - the juce/src directory) to avoid defining this macro. See the comments in - juce_withoutMacros.h for more info. -*/ -#define T(stringLiteral) JUCE_T(stringLiteral) +#define T(stringLiteral) JUCE_T(stringLiteral) #endif -/** - A set of methods for manipulating characters and character strings, with - duplicate methods to handle 8-bit and unicode characters. - - These are defined as wrappers around the basic C string handlers, to provide - a clean, cross-platform layer, (because various platforms differ in the - range of C library calls that they provide). - - @see String -*/ class JUCE_API CharacterFunctions { public: - static int length (const char* const s) throw(); - static int length (const juce_wchar* const s) throw(); + static int length (const char* const s) throw(); + static int length (const juce_wchar* const s) throw(); - static void copy (char* dest, const char* src, const int maxBytes) throw(); - static void copy (juce_wchar* dest, const juce_wchar* src, const int maxChars) throw(); + static void copy (char* dest, const char* src, const int maxBytes) throw(); + static void copy (juce_wchar* dest, const juce_wchar* src, const int maxChars) throw(); - static void copy (juce_wchar* dest, const char* src, const int maxChars) throw(); - static void copy (char* dest, const juce_wchar* src, const int maxBytes) throw(); - static int bytesRequiredForCopy (const juce_wchar* src) throw(); + static void copy (juce_wchar* dest, const char* src, const int maxChars) throw(); + static void copy (char* dest, const juce_wchar* src, const int maxBytes) throw(); + static int bytesRequiredForCopy (const juce_wchar* src) throw(); - static void append (char* dest, const char* src) throw(); - static void append (juce_wchar* dest, const juce_wchar* src) throw(); + static void append (char* dest, const char* src) throw(); + static void append (juce_wchar* dest, const juce_wchar* src) throw(); - static int compare (const char* const s1, const char* const s2) throw(); - static int compare (const juce_wchar* s1, const juce_wchar* s2) throw(); + static int compare (const char* const s1, const char* const s2) throw(); + static int compare (const juce_wchar* s1, const juce_wchar* s2) throw(); - static int compare (const char* const s1, const char* const s2, const int maxChars) throw(); - static int compare (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw(); + static int compare (const char* const s1, const char* const s2, const int maxChars) throw(); + static int compare (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw(); - static int compareIgnoreCase (const char* const s1, const char* const s2) throw(); - static int compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2) throw(); + static int compareIgnoreCase (const char* const s1, const char* const s2) throw(); + static int compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2) throw(); - static int compareIgnoreCase (const char* const s1, const char* const s2, const int maxChars) throw(); - static int compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw(); + static int compareIgnoreCase (const char* const s1, const char* const s2, const int maxChars) throw(); + static int compareIgnoreCase (const juce_wchar* s1, const juce_wchar* s2, int maxChars) throw(); - static const char* find (const char* const haystack, const char* const needle) throw(); - static const juce_wchar* find (const juce_wchar* haystack, const juce_wchar* const needle) throw(); + static const char* find (const char* const haystack, const char* const needle) throw(); + static const juce_wchar* find (const juce_wchar* haystack, const juce_wchar* const needle) throw(); - static int indexOfChar (const char* const haystack, const char needle, const bool ignoreCase) throw(); - static int indexOfChar (const juce_wchar* const haystack, const juce_wchar needle, const bool ignoreCase) throw(); + static int indexOfChar (const char* const haystack, const char needle, const bool ignoreCase) throw(); + static int indexOfChar (const juce_wchar* const haystack, const juce_wchar needle, const bool ignoreCase) throw(); - static int indexOfCharFast (const char* const haystack, const char needle) throw(); - static int indexOfCharFast (const juce_wchar* const haystack, const juce_wchar needle) throw(); + static int indexOfCharFast (const char* const haystack, const char needle) throw(); + static int indexOfCharFast (const juce_wchar* const haystack, const juce_wchar needle) throw(); - static int getIntialSectionContainingOnly (const char* const text, const char* const allowedChars) throw(); - static int getIntialSectionContainingOnly (const juce_wchar* const text, const juce_wchar* const allowedChars) throw(); + static int getIntialSectionContainingOnly (const char* const text, const char* const allowedChars) throw(); + static int getIntialSectionContainingOnly (const juce_wchar* const text, const juce_wchar* const allowedChars) throw(); - static int ftime (char* const dest, const int maxChars, const char* const format, const struct tm* const tm) throw(); - static int ftime (juce_wchar* const dest, const int maxChars, const juce_wchar* const format, const struct tm* const tm) throw(); + static int ftime (char* const dest, const int maxChars, const char* const format, const struct tm* const tm) throw(); + static int ftime (juce_wchar* const dest, const int maxChars, const juce_wchar* const format, const struct tm* const tm) throw(); - static int getIntValue (const char* const s) throw(); - static int getIntValue (const juce_wchar* s) throw(); + static int getIntValue (const char* const s) throw(); + static int getIntValue (const juce_wchar* s) throw(); - static int64 getInt64Value (const char* s) throw(); - static int64 getInt64Value (const juce_wchar* s) throw(); + static int64 getInt64Value (const char* s) throw(); + static int64 getInt64Value (const juce_wchar* s) throw(); - static double getDoubleValue (const char* const s) throw(); - static double getDoubleValue (const juce_wchar* const s) throw(); + static double getDoubleValue (const char* const s) throw(); + static double getDoubleValue (const juce_wchar* const s) throw(); - static char toUpperCase (const char character) throw(); - static juce_wchar toUpperCase (const juce_wchar character) throw(); - static void toUpperCase (char* s) throw(); + static char toUpperCase (const char character) throw(); + static juce_wchar toUpperCase (const juce_wchar character) throw(); + static void toUpperCase (char* s) throw(); - static void toUpperCase (juce_wchar* s) throw(); - static bool isUpperCase (const char character) throw(); - static bool isUpperCase (const juce_wchar character) throw(); + static void toUpperCase (juce_wchar* s) throw(); + static bool isUpperCase (const char character) throw(); + static bool isUpperCase (const juce_wchar character) throw(); - static char toLowerCase (const char character) throw(); - static juce_wchar toLowerCase (const juce_wchar character) throw(); - static void toLowerCase (char* s) throw(); - static void toLowerCase (juce_wchar* s) throw(); - static bool isLowerCase (const char character) throw(); - static bool isLowerCase (const juce_wchar character) throw(); + static char toLowerCase (const char character) throw(); + static juce_wchar toLowerCase (const juce_wchar character) throw(); + static void toLowerCase (char* s) throw(); + static void toLowerCase (juce_wchar* s) throw(); + static bool isLowerCase (const char character) throw(); + static bool isLowerCase (const juce_wchar character) throw(); - static bool isWhitespace (const char character) throw(); - static bool isWhitespace (const juce_wchar character) throw(); + static bool isWhitespace (const char character) throw(); + static bool isWhitespace (const juce_wchar character) throw(); - static bool isDigit (const char character) throw(); - static bool isDigit (const juce_wchar character) throw(); + static bool isDigit (const char character) throw(); + static bool isDigit (const juce_wchar character) throw(); - static bool isLetter (const char character) throw(); - static bool isLetter (const juce_wchar character) throw(); + static bool isLetter (const char character) throw(); + static bool isLetter (const juce_wchar character) throw(); - static bool isLetterOrDigit (const char character) throw(); - static bool isLetterOrDigit (const juce_wchar character) throw(); + static bool isLetterOrDigit (const char character) throw(); + static bool isLetterOrDigit (const juce_wchar character) throw(); - /** Returns 0 to 16 for '0' to 'F", or -1 for characters that aren't a legel - hex digit. - */ - static int getHexDigitValue (const tchar digit) throw(); + static int getHexDigitValue (const tchar digit) throw(); - static int printf (char* const dest, const int maxLength, const char* const format, ...) throw(); - static int printf (juce_wchar* const dest, const int maxLength, const juce_wchar* const format, ...) throw(); + static int printf (char* const dest, const int maxLength, const char* const format, ...) throw(); + static int printf (juce_wchar* const dest, const int maxLength, const juce_wchar* const format, ...) throw(); - static int vprintf (char* const dest, const int maxLength, const char* const format, va_list& args) throw(); - static int vprintf (juce_wchar* const dest, const int maxLength, const juce_wchar* const format, va_list& args) throw(); + static int vprintf (char* const dest, const int maxLength, const char* const format, va_list& args) throw(); + static int vprintf (juce_wchar* const dest, const int maxLength, const juce_wchar* const format, va_list& args) throw(); }; #endif // __JUCE_CHARACTERFUNCTIONS_JUCEHEADER__ /********* End of inlined file: juce_CharacterFunctions.h *********/ -/** - The JUCE String class! - - Using a reference-counted internal representation, these strings are fast - and efficient, and there are methods to do just about any operation you'll ever - dream of. - - @see StringArray, StringPairArray -*/ class JUCE_API String { public: - /** Creates an empty string. + String() throw(); - @see empty - */ - String() throw(); + String (const String& other) throw(); - /** Creates a copy of another string. */ - String (const String& other) throw(); + String (const char* const text) throw(); - /** Creates a string from a zero-terminated text string. + String (const char* const text, + const size_t maxChars) throw(); - The string is assumed to be stored in the default system encoding. - */ - String (const char* const text) throw(); - - /** Creates a string from an string of characters. - - This will use up the the first maxChars characters of the string (or - less if the string is actually shorter) - */ - String (const char* const text, - const int maxChars) throw(); - - /** Creates a string from a zero-terminated unicode text string. */ - String (const juce_wchar* const unicodeText) throw(); - - /** Creates a string from a unicode text string. - - This will use up the the first maxChars characters of the string (or - less if the string is actually shorter) - */ - String (const juce_wchar* const unicodeText, - const int maxChars) throw(); + String (const juce_wchar* const unicodeText) throw(); - /** Creates a string from a single character. */ - static const String charToString (const tchar character) throw(); + String (const juce_wchar* const unicodeText, + const size_t maxChars) throw(); - /** Destructor. */ - ~String() throw(); + static const String charToString (const tchar character) throw(); - /** This is an empty string that can be used whenever one is needed. + ~String() throw(); - It's better to use this than String() because it explains what's going on - and is more efficient. - */ - static const String empty; + static const String empty; - /** Generates a probably-unique 32-bit hashcode from this string. */ - int hashCode() const throw(); + int hashCode() const throw(); - /** Generates a probably-unique 64-bit hashcode from this string. */ - int64 hashCode64() const throw(); - - /** Returns the number of characters in the string. */ - int length() const throw(); - - // Assignment and concatenation operators.. - - /** Replaces this string's contents with another string. */ - const String& operator= (const tchar* const other) throw(); - - /** Replaces this string's contents with another string. */ - const String& operator= (const String& other) throw(); - - /** Appends another string at the end of this one. */ - const String& operator+= (const tchar* const textToAppend) throw(); - /** Appends another string at the end of this one. */ - const String& operator+= (const String& stringToAppend) throw(); - /** Appends a character at the end of this string. */ - const String& operator+= (const char characterToAppend) throw(); - /** Appends a character at the end of this string. */ - const String& operator+= (const juce_wchar characterToAppend) throw(); - - /** Appends a string at the end of this one. - - @param textToAppend the string to add - @param maxCharsToTake the maximum number of characters to take from the string passed in - */ - void append (const tchar* const textToAppend, - const int maxCharsToTake) throw(); - - /** Appends a string at the end of this one. - @returns the concatenated string - */ - const String operator+ (const String& stringToAppend) const throw(); - - /** Appends a string at the end of this one. - @returns the concatenated string - */ - const String operator+ (const tchar* const textToAppend) const throw(); - - /** Appends a character at the end of this one. - @returns the concatenated string - */ - const String operator+ (const tchar characterToAppend) const throw(); - - /** Appends a character at the end of this string. */ - String& operator<< (const char n) throw(); - /** Appends a character at the end of this string. */ - String& operator<< (const juce_wchar n) throw(); - /** Appends another string at the end of this one. */ - String& operator<< (const char* const text) throw(); - /** Appends another string at the end of this one. */ - String& operator<< (const juce_wchar* const text) throw(); - /** Appends another string at the end of this one. */ - String& operator<< (const String& text) throw(); - - /** Appends a decimal number at the end of this string. */ - String& operator<< (const short number) throw(); - /** Appends a decimal number at the end of this string. */ - String& operator<< (const int number) throw(); - /** Appends a decimal number at the end of this string. */ - String& operator<< (const unsigned int number) throw(); - /** Appends a decimal number at the end of this string. */ - String& operator<< (const long number) throw(); - /** Appends a decimal number at the end of this string. */ - String& operator<< (const unsigned long number) throw(); - /** Appends a decimal number at the end of this string. */ - String& operator<< (const float number) throw(); - /** Appends a decimal number at the end of this string. */ - String& operator<< (const double number) throw(); + int64 hashCode64() const throw(); - // Comparison methods.. - - /** Returns true if the string contains no characters. + int length() const throw(); - Note that there's also an isNotEmpty() method to help write readable code. + // Assignment and concatenation operators.. - @see containsNonWhitespaceChars() - */ - inline bool isEmpty() const throw() { return text->text[0] == 0; } + const String& operator= (const tchar* const other) throw(); - /** Returns true if the string contains at least one character. + const String& operator= (const String& other) throw(); - Note that there's also an isEmpty() method to help write readable code. + const String& operator+= (const tchar* const textToAppend) throw(); + const String& operator+= (const String& stringToAppend) throw(); + const String& operator+= (const char characterToAppend) throw(); + const String& operator+= (const juce_wchar characterToAppend) throw(); - @see containsNonWhitespaceChars() - */ - inline bool isNotEmpty() const throw() { return text->text[0] != 0; } + void append (const tchar* const textToAppend, + const int maxCharsToTake) throw(); - /** Case-sensitive comparison with another string. */ - bool operator== (const String& other) const throw(); - /** Case-sensitive comparison with another string. */ - bool operator== (const tchar* const other) const throw(); + const String operator+ (const String& stringToAppend) const throw(); - /** Case-sensitive comparison with another string. */ - bool operator!= (const String& other) const throw(); - /** Case-sensitive comparison with another string. */ - bool operator!= (const tchar* const other) const throw(); + const String operator+ (const tchar* const textToAppend) const throw(); - /** Case-insensitive comparison with another string. */ - bool equalsIgnoreCase (const String& other) const throw(); - /** Case-insensitive comparison with another string. */ - bool equalsIgnoreCase (const tchar* const other) const throw(); + const String operator+ (const tchar characterToAppend) const throw(); - /** Case-sensitive comparison with another string. */ - bool operator> (const String& other) const throw(); - /** Case-sensitive comparison with another string. */ - bool operator< (const tchar* const other) const throw(); - - /** Case-sensitive comparison with another string. */ - bool operator>= (const String& other) const throw(); - /** Case-sensitive comparison with another string. */ - bool operator<= (const tchar* const other) const throw(); - - /** Case-sensitive comparison with another string. - @returns 0 if the two strings are identical; negative if this string - comes before the other one alphabetically, or positive if it - comes after it. - */ - int compare (const tchar* const other) const throw(); + String& operator<< (const char n) throw(); + String& operator<< (const juce_wchar n) throw(); + String& operator<< (const char* const text) throw(); + String& operator<< (const juce_wchar* const text) throw(); + String& operator<< (const String& text) throw(); - /** Case-insensitive comparison with another string. - @returns 0 if the two strings are identical; negative if this string - comes before the other one alphabetically, or positive if it - comes after it. - */ - int compareIgnoreCase (const tchar* const other) const throw(); - - /** Lexicographic comparison with another string. + String& operator<< (const short number) throw(); + String& operator<< (const int number) throw(); + String& operator<< (const unsigned int number) throw(); + String& operator<< (const long number) throw(); + String& operator<< (const unsigned long number) throw(); + String& operator<< (const float number) throw(); + String& operator<< (const double number) throw(); - The comparison used here is case-insensitive and ignores leading non-alphanumeric - characters, making it good for sorting human-readable strings. + // Comparison methods.. - @returns 0 if the two strings are identical; negative if this string - comes before the other one alphabetically, or positive if it - comes after it. - */ - int compareLexicographically (const tchar* const other) const throw(); + inline bool isEmpty() const throw() { return text->text[0] == 0; } - /** Tests whether the string begins with another string. + inline bool isNotEmpty() const throw() { return text->text[0] != 0; } - Uses a case-sensitive comparison. - */ - bool startsWith (const tchar* const text) const throw(); + bool operator== (const String& other) const throw(); + bool operator== (const tchar* const other) const throw(); - /** Tests whether the string begins with a particular character. + bool operator!= (const String& other) const throw(); + bool operator!= (const tchar* const other) const throw(); - Uses a case-sensitive comparison. - */ - bool startsWithChar (const tchar character) const throw(); + bool equalsIgnoreCase (const String& other) const throw(); + bool equalsIgnoreCase (const tchar* const other) const throw(); - /** Tests whether the string begins with another string. + bool operator> (const String& other) const throw(); + bool operator< (const tchar* const other) const throw(); - Uses a case-insensitive comparison. - */ - bool startsWithIgnoreCase (const tchar* const text) const throw(); + bool operator>= (const String& other) const throw(); + bool operator<= (const tchar* const other) const throw(); - /** Tests whether the string ends with another string. + int compare (const tchar* const other) const throw(); - Uses a case-sensitive comparison. - */ - bool endsWith (const tchar* const text) const throw(); + int compareIgnoreCase (const tchar* const other) const throw(); - /** Tests whether the string ends with a particular character. + int compareLexicographically (const tchar* const other) const throw(); - Uses a case-sensitive comparison. - */ - bool endsWithChar (const tchar character) const throw(); + bool startsWith (const tchar* const text) const throw(); - /** Tests whether the string ends with another string. + bool startsWithChar (const tchar character) const throw(); - Uses a case-insensitive comparison. - */ - bool endsWithIgnoreCase (const tchar* const text) const throw(); + bool startsWithIgnoreCase (const tchar* const text) const throw(); - /** Tests whether the string contains another substring. + bool endsWith (const tchar* const text) const throw(); - Uses a case-sensitive comparison. - */ - bool contains (const tchar* const text) const throw(); + bool endsWithChar (const tchar character) const throw(); - /** Tests whether the string contains a particular character. + bool endsWithIgnoreCase (const tchar* const text) const throw(); - Uses a case-sensitive comparison. - */ - bool containsChar (const tchar character) const throw(); + bool contains (const tchar* const text) const throw(); - /** Tests whether the string contains another substring. + bool containsChar (const tchar character) const throw(); - Uses a case-insensitive comparison. - */ - bool containsIgnoreCase (const tchar* const text) const throw(); + bool containsIgnoreCase (const tchar* const text) const throw(); - /** Tests whether the string contains another substring as a distict word. + bool containsWholeWord (const tchar* const wordToLookFor) const throw(); - @returns true if the string contains this word, surrounded by - non-alphanumeric characters - @see indexOfWholeWord, containsWholeWordIgnoreCase - */ - bool containsWholeWord (const tchar* const wordToLookFor) const throw(); + bool containsWholeWordIgnoreCase (const tchar* const wordToLookFor) const throw(); - /** Tests whether the string contains another substring as a distict word. + int indexOfWholeWord (const tchar* const wordToLookFor) const throw(); - @returns true if the string contains this word, surrounded by - non-alphanumeric characters - @see indexOfWholeWordIgnoreCase, containsWholeWord - */ - bool containsWholeWordIgnoreCase (const tchar* const wordToLookFor) const throw(); + int indexOfWholeWordIgnoreCase (const tchar* const wordToLookFor) const throw(); - /** Finds an instance of another substring if it exists as a distict word. + bool containsAnyOf (const tchar* const charactersItMightContain) const throw(); - @returns if the string contains this word, surrounded by non-alphanumeric characters, - then this will return the index of the start of the substring. If it isn't - found, then it will return -1 - @see indexOfWholeWordIgnoreCase, containsWholeWord - */ - int indexOfWholeWord (const tchar* const wordToLookFor) const throw(); + bool containsOnly (const tchar* const charactersItMightContain) const throw(); - /** Finds an instance of another substring if it exists as a distict word. + bool containsNonWhitespaceChars() const throw(); - @returns if the string contains this word, surrounded by non-alphanumeric characters, - then this will return the index of the start of the substring. If it isn't - found, then it will return -1 - @see indexOfWholeWord, containsWholeWordIgnoreCase - */ - int indexOfWholeWordIgnoreCase (const tchar* const wordToLookFor) const throw(); + bool matchesWildcard (const tchar* wildcard, const bool ignoreCase) const throw(); - /** Looks for any of a set of characters in the string. + // Substring location methods.. - Uses a case-sensitive comparison. + int indexOfChar (const tchar characterToLookFor) const throw(); - @returns true if the string contains any of the characters from - the string that is passed in. - */ - bool containsAnyOf (const tchar* const charactersItMightContain) const throw(); + int indexOfChar (const int startIndex, const tchar characterToLookFor) const throw(); - /** Looks for a set of characters in the string. + int indexOfAnyOf (const tchar* const charactersToLookFor, + const int startIndex = 0, + const bool ignoreCase = false) const throw(); - Uses a case-sensitive comparison. + int indexOf (const tchar* const text) const throw(); - @returns true if the all the characters in the string are also found in the - string that is passed in. - */ - bool containsOnly (const tchar* const charactersItMightContain) const throw(); + int indexOf (const int startIndex, + const tchar* const textToLookFor) const throw(); - /** Returns true if this string contains any non-whitespace characters. + int indexOfIgnoreCase (const tchar* const textToLookFor) const throw(); - This will return false if the string contains only whitespace characters, or - if it's empty. + int indexOfIgnoreCase (const int startIndex, + const tchar* const textToLookFor) const throw(); - It is equivalent to calling "myString.trim().isNotEmpty()". - */ - bool containsNonWhitespaceChars() const throw(); + int lastIndexOfChar (const tchar character) const throw(); - /** Returns true if the string matches this simple wildcard expression. + int lastIndexOf (const tchar* const textToLookFor) const throw(); - So for example String ("abcdef").matchesWildcard ("*DEF", true) would return true. + int lastIndexOfIgnoreCase (const tchar* const textToLookFor) const throw(); - This isn't a full-blown regex though! The only wildcard characters supported - are "*" and "?". It's mainly intended for filename pattern matching. - */ - bool matchesWildcard (const tchar* wildcard, const bool ignoreCase) const throw(); + int lastIndexOfAnyOf (const tchar* const charactersToLookFor, + const bool ignoreCase = false) const throw(); - // Substring location methods.. + // Substring extraction and manipulation methods.. - /** Searches for a character inside this string. + /** Returns the character at this index in the string. - Uses a case-sensitive comparison. + No checks are made to see if the index is within a valid range, so be careful! + */ + inline const tchar& operator[] (const int index) const throw() { jassert (((unsigned int) index) <= (unsigned int) length()); return text->text [index]; } - @returns the index of the first occurrence of the character in this - string, or -1 if it's not found. - */ - int indexOfChar (const tchar characterToLookFor) const throw(); + tchar& operator[] (const int index) throw(); - /** Searches for a character inside this string. + tchar getLastCharacter() const throw(); - Uses a case-sensitive comparison. + const String substring (int startIndex, + int endIndex) const throw(); - @param startIndex the index from which the search should proceed - @param characterToLookFor the character to look for - @returns the index of the first occurrence of the character in this - string, or -1 if it's not found. - */ - int indexOfChar (const int startIndex, const tchar characterToLookFor) const throw(); + const String substring (const int startIndex) const throw(); - /** Returns the index of the first character that matches one of the characters - passed-in to this method. + const String dropLastCharacters (const int numberToDrop) const throw(); - This scans the string, beginning from the startIndex supplied, and if it finds - a character that appears in the string charactersToLookFor, it returns its index. + const String getLastCharacters (const int numCharacters) const throw(); - If none of these characters are found, it returns -1. + const String fromFirstOccurrenceOf (const tchar* const substringToStartFrom, + const bool includeSubStringInResult, + const bool ignoreCase) const throw(); - If ignoreCase is true, the comparison will be case-insensitive. + const String fromLastOccurrenceOf (const tchar* const substringToFind, + const bool includeSubStringInResult, + const bool ignoreCase) const throw(); - @see indexOfChar, lastIndexOfAnyOf - */ - int indexOfAnyOf (const tchar* const charactersToLookFor, - const int startIndex = 0, - const bool ignoreCase = false) const throw(); + const String upToFirstOccurrenceOf (const tchar* const substringToEndWith, + const bool includeSubStringInResult, + const bool ignoreCase) const throw(); - /** Searches for a substring within this string. + const String upToLastOccurrenceOf (const tchar* substringToFind, + const bool includeSubStringInResult, + const bool ignoreCase) const throw(); - Uses a case-sensitive comparison. + const String trim() const throw(); + const String trimStart() const throw(); + const String trimEnd() const throw(); - @returns the index of the first occurrence of this substring, or -1 if it's not found. - */ - int indexOf (const tchar* const text) const throw(); + const String trimCharactersAtStart (const tchar* charactersToTrim) const throw(); - /** Searches for a substring within this string. + const String trimCharactersAtEnd (const tchar* charactersToTrim) const throw(); - Uses a case-sensitive comparison. + const String toUpperCase() const throw(); - @param startIndex the index from which the search should proceed - @param textToLookFor the string to search for - @returns the index of the first occurrence of this substring, or -1 if it's not found. - */ - int indexOf (const int startIndex, - const tchar* const textToLookFor) const throw(); + const String toLowerCase() const throw(); - /** Searches for a substring within this string. + const String replaceSection (int startIndex, + int numCharactersToReplace, + const tchar* const stringToInsert) const throw(); - Uses a case-insensitive comparison. + const String replace (const tchar* const stringToReplace, + const tchar* const stringToInsertInstead, + const bool ignoreCase = false) const throw(); - @returns the index of the first occurrence of this substring, or -1 if it's not found. - */ - int indexOfIgnoreCase (const tchar* const textToLookFor) const throw(); + const String replaceCharacter (const tchar characterToReplace, + const tchar characterToInsertInstead) const throw(); - /** Searches for a substring within this string. + const String replaceCharacters (const String& charactersToReplace, + const tchar* const charactersToInsertInstead) const throw(); - Uses a case-insensitive comparison. + const String retainCharacters (const tchar* const charactersToRetain) const throw(); - @param startIndex the index from which the search should proceed - @param textToLookFor the string to search for - @returns the index of the first occurrence of this substring, or -1 if it's not found. - */ - int indexOfIgnoreCase (const int startIndex, - const tchar* const textToLookFor) const throw(); + const String removeCharacters (const tchar* const charactersToRemove) const throw(); - /** Searches for a character inside this string (working backwards from the end of the string). + const String initialSectionContainingOnly (const tchar* const permittedCharacters) const throw(); - Uses a case-sensitive comparison. + const String initialSectionNotContaining (const tchar* const charactersToStopAt) const throw(); - @returns the index of the last occurrence of the character in this - string, or -1 if it's not found. - */ - int lastIndexOfChar (const tchar character) const throw(); + bool isQuotedString() const throw(); - /** Searches for a substring inside this string (working backwards from the end of the string). + const String unquoted() const throw(); - Uses a case-sensitive comparison. + const String quoted (const tchar quoteCharacter = JUCE_T('"')) const throw(); - @returns the index of the start of the last occurrence of the - substring within this string, or -1 if it's not found. - */ - int lastIndexOf (const tchar* const textToLookFor) const throw(); + void printf (const tchar* const format, ...) throw(); - /** Searches for a substring inside this string (working backwards from the end of the string). + static const String formatted (const tchar* const format, ...) throw(); - Uses a case-insensitive comparison. + void vprintf (const tchar* const format, va_list& args) throw(); - @returns the index of the start of the last occurrence of the - substring within this string, or -1 if it's not found. - */ - int lastIndexOfIgnoreCase (const tchar* const textToLookFor) const throw(); + static const String repeatedString (const tchar* const stringToRepeat, + int numberOfTimesToRepeat) throw(); - /** Returns the index of the last character in this string that matches one of the - characters passed-in to this method. + static const String createStringFromData (const void* const data, + const int size) throw(); - This scans the string backwards, starting from its end, and if it finds - a character that appears in the string charactersToLookFor, it returns its index. + // Numeric conversions.. - If none of these characters are found, it returns -1. + explicit String (const int decimalInteger) throw(); - If ignoreCase is true, the comparison will be case-insensitive. + explicit String (const unsigned int decimalInteger) throw(); - @see lastIndexOf, indexOfAnyOf - */ - int lastIndexOfAnyOf (const tchar* const charactersToLookFor, - const bool ignoreCase = false) const throw(); + explicit String (const short decimalInteger) throw(); - // Substring extraction and manipulation methods.. + explicit String (const unsigned short decimalInteger) throw(); - /** Returns the character at this index in the string. + explicit String (const int64 largeIntegerValue) throw(); - No checks are made to see if the index is within a valid range, so be careful! - */ - inline const tchar& operator[] (const int index) const throw() { jassert (((unsigned int) index) <= (unsigned int) length()); return text->text [index]; } + explicit String (const uint64 largeIntegerValue) throw(); - /** Returns a character from the string such that it can also be altered. + explicit String (const float floatValue, + const int numberOfDecimalPlaces = 0) throw(); - This can be used as a way of easily changing characters in the string. + explicit String (const double doubleValue, + const int numberOfDecimalPlaces = 0) throw(); - Note that the index passed-in is not checked to see whether it's in-range, so - be careful when using this. - */ - tchar& operator[] (const int index) throw(); + int getIntValue() const throw(); - /** Returns the final character of the string. + int64 getLargeIntValue() const throw(); - If the string is empty this will return 0. - */ - tchar getLastCharacter() const throw(); + int getTrailingIntValue() const throw(); - /** Returns a subsection of the string. + float getFloatValue() const throw(); - If the range specified is beyond the limits of the string, as much as - possible is returned. + double getDoubleValue() const throw(); - @param startIndex the index of the start of the substring needed - @param endIndex all characters from startIndex up to (but not including) - this index are returned - @see fromFirstOccurrenceOf, dropLastCharacters, getLastCharacters, upToFirstOccurrenceOf - */ - const String substring (int startIndex, - int endIndex) const throw(); + int getHexValue32() const throw(); - /** Returns a section of the string, starting from a given position. + int64 getHexValue64() const throw(); - @param startIndex the first character to include. If this is beyond the end - of the string, an empty string is returned. If it is zero or - less, the whole string is returned. - @returns the substring from startIndex up to the end of the string - @see dropLastCharacters, getLastCharacters, fromFirstOccurrenceOf, upToFirstOccurrenceOf, fromLastOccurrenceOf - */ - const String substring (const int startIndex) const throw(); + static const String toHexString (const int number) throw(); - /** Returns a version of this string with a number of characters removed - from the end. + static const String toHexString (const int64 number) throw(); - @param numberToDrop the number of characters to drop from the end of the - string. If this is greater than the length of the string, - an empty string will be returned. If zero or less, the - original string will be returned. - @see substring, fromFirstOccurrenceOf, upToFirstOccurrenceOf, fromLastOccurrenceOf, getLastCharacter - */ - const String dropLastCharacters (const int numberToDrop) const throw(); + static const String toHexString (const short number) throw(); - /** Returns a number of characters from the end of the string. + static const String toHexString (const unsigned char* data, + const int size, + const int groupSize = 1) throw(); - This returns the last numCharacters characters from the end of the string. If the - string is shorter than numCharacters, the whole string is returned. - - @see substring, dropLastCharacters, getLastCharacter - */ - const String getLastCharacters (const int numCharacters) const throw(); - - /** Returns a section of the string starting from a given substring. - - This will search for the first occurrence of the given substring, and - return the section of the string starting from the point where this is - found (optionally not including the substring itself). - - e.g. for the string "123456", fromFirstOccurrenceOf ("34", true) would return "3456", and - fromFirstOccurrenceOf ("34", false) would return "56". - - If the substring isn't found, the method will return an empty string. - - If ignoreCase is true, the comparison will be case-insensitive. - - @see upToFirstOccurrenceOf, fromLastOccurrenceOf - */ - const String fromFirstOccurrenceOf (const tchar* const substringToStartFrom, - const bool includeSubStringInResult, - const bool ignoreCase) const throw(); - - /** Returns a section of the string starting from the last occurrence of a given substring. - - Similar to fromFirstOccurrenceOf(), but using the last occurrence of the substring, and - unlike fromFirstOccurrenceOf(), if the substring isn't found, this method will - return the whole of the original string. - - @see fromFirstOccurrenceOf, upToLastOccurrenceOf - */ - const String fromLastOccurrenceOf (const tchar* const substringToFind, - const bool includeSubStringInResult, - const bool ignoreCase) const throw(); - - /** Returns the start of this string, up to the first occurrence of a substring. - - This will search for the first occurrence of a given substring, and then - return a copy of the string, up to the position of this substring, - optionally including or excluding the substring itself in the result. - - e.g. for the string "123456", upTo ("34", false) would return "12", and - upTo ("34", true) would return "1234". - - If the substring isn't found, this will return the whole of the original string. - - @see upToLastOccurrenceOf, fromFirstOccurrenceOf - */ - const String upToFirstOccurrenceOf (const tchar* const substringToEndWith, - const bool includeSubStringInResult, - const bool ignoreCase) const throw(); - - /** Returns the start of this string, up to the last occurrence of a substring. - - Similar to upToFirstOccurrenceOf(), but this finds the last occurrence rather than the first. - If the substring isn't found, this will return an empty string. - - @see upToFirstOccurrenceOf, fromFirstOccurrenceOf - */ - const String upToLastOccurrenceOf (const tchar* substringToFind, - const bool includeSubStringInResult, - const bool ignoreCase) const throw(); - - /** Returns a copy of this string with any whitespace characters removed from the start and end. */ - const String trim() const throw(); - /** Returns a copy of this string with any whitespace characters removed from the start. */ - const String trimStart() const throw(); - /** Returns a copy of this string with any whitespace characters removed from the end. */ - const String trimEnd() const throw(); - - /** Returns a copy of this string, having removed a specified set of characters from its start. - Characters are removed from the start of the string until it finds one that is not in the - specified set, and then it stops. - @param charactersToTrim the set of characters to remove. This must not be null. - @see trim, trimStart, trimCharactersAtEnd - */ - const String trimCharactersAtStart (const tchar* charactersToTrim) const throw(); - - /** Returns a copy of this string, having removed a specified set of characters from its end. - Characters are removed from the end of the string until it finds one that is not in the - specified set, and then it stops. - @param charactersToTrim the set of characters to remove. This must not be null. - @see trim, trimEnd, trimCharactersAtStart - */ - const String trimCharactersAtEnd (const tchar* charactersToTrim) const throw(); - - /** Returns an upper-case version of this string. */ - const String toUpperCase() const throw(); - - /** Returns an lower-case version of this string. */ - const String toLowerCase() const throw(); - - /** Replaces a sub-section of the string with another string. - - This will return a copy of this string, with a set of characters - from startIndex to startIndex + numCharsToReplace removed, and with - a new string inserted in their place. - - Note that this is a const method, and won't alter the string itself. - - @param startIndex the first character to remove. If this is beyond the bounds of the string, - it will be constrained to a valid range. - @param numCharactersToReplace the number of characters to remove. If zero or less, no - characters will be taken out. - @param stringToInsert the new string to insert at startIndex after the characters have been - removed. - */ - const String replaceSection (int startIndex, - int numCharactersToReplace, - const tchar* const stringToInsert) const throw(); - - /** Replaces all occurrences of a substring with another string. - - Returns a copy of this string, with any occurrences of stringToReplace - swapped for stringToInsertInstead. - - Note that this is a const method, and won't alter the string itself. - */ - const String replace (const tchar* const stringToReplace, - const tchar* const stringToInsertInstead, - const bool ignoreCase = false) const throw(); - - /** Returns a string with all occurrences of a character replaced with a different one. */ - const String replaceCharacter (const tchar characterToReplace, - const tchar characterToInsertInstead) const throw(); - - /** Replaces a set of characters with another set. - - Returns a string in which each character from charactersToReplace has been replaced - by the character at the equivalent position in newCharacters (so the two strings - passed in must be the same length). - - e.g. translate ("abc", "def") replaces 'a' with 'd', 'b' with 'e', etc. - - Note that this is a const method, and won't affect the string itself. - */ - const String replaceCharacters (const String& charactersToReplace, - const tchar* const charactersToInsertInstead) const throw(); - - /** Returns a version of this string that only retains a fixed set of characters. - - This will return a copy of this string, omitting any characters which are not - found in the string passed-in. - - e.g. for "1122334455", retainCharacters ("432") would return "223344" - - Note that this is a const method, and won't alter the string itself. - */ - const String retainCharacters (const tchar* const charactersToRetain) const throw(); - - /** Returns a version of this string with a set of characters removed. - - This will return a copy of this string, omitting any characters which are - found in the string passed-in. - - e.g. for "1122334455", removeCharacters ("432") would return "1155" - - Note that this is a const method, and won't alter the string itself. - */ - const String removeCharacters (const tchar* const charactersToRemove) const throw(); - - /** Returns a section from the start of the string that only contains a certain set of characters. - - This returns the leftmost section of the string, up to (and not including) the - first character that doesn't appear in the string passed in. - */ - const String initialSectionContainingOnly (const tchar* const permittedCharacters) const throw(); - - /** Returns a section from the start of the string that only contains a certain set of characters. - - This returns the leftmost section of the string, up to (and not including) the - first character that occurs in the string passed in. - */ - const String initialSectionNotContaining (const tchar* const charactersToStopAt) const throw(); - - /** Checks whether the string might be in quotation marks. - - @returns true if the string begins with a quote character (either a double or single quote). - It is also true if there is whitespace before the quote, but it doesn't check the end of the string. - @see unquoted, quoted - */ - bool isQuotedString() const throw(); - - /** Removes quotation marks from around the string, (if there are any). - - Returns a copy of this string with any quotes removed from its ends. Quotes that aren't - at the ends of the string are not affected. If there aren't any quotes, the original string - is returned. - - Note that this is a const method, and won't alter the string itself. - - @see isQuotedString, quoted - */ - const String unquoted() const throw(); - - /** Adds quotation marks around a string. - - This will return a copy of the string with a quote at the start and end, (but won't - add the quote if there's already one there, so it's safe to call this on strings that - may already have quotes around them). - - Note that this is a const method, and won't alter the string itself. - - @param quoteCharacter the character to add at the start and end - @see isQuotedString, unquoted - */ - const String quoted (const tchar quoteCharacter = JUCE_T('"')) const throw(); - - /** Writes text into this string, using printf style-arguments. - - This will replace the contents of the string with the output of this - formatted printf. - - Note that using the %s token with a juce string is probably a bad idea, as - this may expect differect encodings on different platforms. - - @see formatted - */ - void printf (const tchar* const format, ...) throw(); - - /** Returns a string, created using arguments in the style of printf. - - This will return a string which is the result of a sprintf using the - arguments passed-in. - - Note that using the %s token with a juce string is probably a bad idea, as - this may expect differect encodings on different platforms. - - @see printf, vprintf - */ - static const String formatted (const tchar* const format, ...) throw(); - - /** Writes text into this string, using a printf style, but taking a va_list argument. - - This will replace the contents of the string with the output of this - formatted printf. Used by other methods, this is public in case it's - useful for other purposes where you want to pass a va_list through directly. - - Note that using the %s token with a juce string is probably a bad idea, as - this may expect differect encodings on different platforms. - - @see printf, formatted - */ - void vprintf (const tchar* const format, va_list& args) throw(); - - /** Creates a string which is a version of a string repeated and joined together. - - @param stringToRepeat the string to repeat - @param numberOfTimesToRepeat how many times to repeat it - */ - static const String repeatedString (const tchar* const stringToRepeat, - int numberOfTimesToRepeat) throw(); - - /** Creates a string from data in an unknown format. - - This looks at some binary data and tries to guess whether it's Unicode - or 8-bit characters, then returns a string that represents it correctly. - - Should be able to handle Unicode endianness correctly, by looking at - the first two bytes. - */ - static const String createStringFromData (const void* const data, - const int size) throw(); - - // Numeric conversions.. - - /** Creates a string containing this signed 32-bit integer as a decimal number. - - @see getIntValue, getFloatValue, getDoubleValue, toHexString - */ - explicit String (const int decimalInteger) throw(); - - /** Creates a string containing this unsigned 32-bit integer as a decimal number. - - @see getIntValue, getFloatValue, getDoubleValue, toHexString - */ - explicit String (const unsigned int decimalInteger) throw(); - - /** Creates a string containing this signed 16-bit integer as a decimal number. - - @see getIntValue, getFloatValue, getDoubleValue, toHexString - */ - explicit String (const short decimalInteger) throw(); - - /** Creates a string containing this unsigned 16-bit integer as a decimal number. - - @see getIntValue, getFloatValue, getDoubleValue, toHexString - */ - explicit String (const unsigned short decimalInteger) throw(); - - /** Creates a string containing this signed 64-bit integer as a decimal number. - - @see getLargeIntValue, getFloatValue, getDoubleValue, toHexString - */ - explicit String (const int64 largeIntegerValue) throw(); - - /** Creates a string containing this unsigned 64-bit integer as a decimal number. - - @see getLargeIntValue, getFloatValue, getDoubleValue, toHexString - */ - explicit String (const uint64 largeIntegerValue) throw(); - - /** Creates a string representing this floating-point number. - - @param floatValue the value to convert to a string - @param numberOfDecimalPlaces if this is > 0, it will format the number using that many - decimal places, and will not use exponent notation. If 0 or - less, it will use exponent notation if necessary. - @see getDoubleValue, getIntValue - */ - explicit String (const float floatValue, - const int numberOfDecimalPlaces = 0) throw(); - - /** Creates a string representing this floating-point number. - - @param doubleValue the value to convert to a string - @param numberOfDecimalPlaces if this is > 0, it will format the number using that many - decimal places, and will not use exponent notation. If 0 or - less, it will use exponent notation if necessary. - - @see getFloatValue, getIntValue - */ - explicit String (const double doubleValue, - const int numberOfDecimalPlaces = 0) throw(); - - /** Reads the value of the string as a decimal number (up to 32 bits in size). - - @returns the value of the string as a 32 bit signed base-10 integer. - @see getTrailingIntValue, getHexValue32, getHexValue64 - */ - int getIntValue() const throw(); - - /** Reads the value of the string as a decimal number (up to 64 bits in size). - - @returns the value of the string as a 64 bit signed base-10 integer. - */ - int64 getLargeIntValue() const throw(); - - /** Parses a decimal number from the end of the string. - - This will look for a value at the end of the string. - e.g. for "321 xyz654" it will return 654; for "2 3 4" it'll return 4. - - Negative numbers are not handled, so "xyz-5" returns 5. - - @see getIntValue - */ - int getTrailingIntValue() const throw(); - - /** Parses this string as a floating point number. - - @returns the value of the string as a 32-bit floating point value. - @see getDoubleValue - */ - float getFloatValue() const throw(); - - /** Parses this string as a floating point number. - - @returns the value of the string as a 64-bit floating point value. - @see getFloatValue - */ - double getDoubleValue() const throw(); - - /** Parses the string as a hexadecimal number. - - Non-hexadecimal characters in the string are ignored. - - If the string contains too many characters, then the lowest significant - digits are returned, e.g. "ffff12345678" would produce 0x12345678. - - @returns a 32-bit number which is the value of the string in hex. - */ - int getHexValue32() const throw(); - - /** Parses the string as a hexadecimal number. - - Non-hexadecimal characters in the string are ignored. - - If the string contains too many characters, then the lowest significant - digits are returned, e.g. "ffff1234567812345678" would produce 0x1234567812345678. - - @returns a 64-bit number which is the value of the string in hex. - */ - int64 getHexValue64() const throw(); - - /** Creates a string representing this 32-bit value in hexadecimal. */ - static const String toHexString (const int number) throw(); - - /** Creates a string representing this 64-bit value in hexadecimal. */ - static const String toHexString (const int64 number) throw(); - - /** Creates a string representing this 16-bit value in hexadecimal. */ - static const String toHexString (const short number) throw(); - - /** Creates a string containing a hex dump of a block of binary data. - - @param data the binary data to use as input - @param size how many bytes of data to use - @param groupSize how many bytes are grouped together before inserting a - space into the output. e.g. group size 0 has no spaces, - group size 1 looks like: "be a1 c2 ff", group size 2 looks - like "bea1 c2ff". - */ - static const String toHexString (const unsigned char* data, - const int size, - const int groupSize = 1) throw(); - - // Casting to character arrays.. + // Casting to character arrays.. #if JUCE_STRINGS_ARE_UNICODE - /** Returns a version of this string using the default 8-bit system encoding. + operator const char*() const throw(); - Because it returns a reference to the string's internal data, the pointer - that is returned must not be stored anywhere, as it can be deleted whenever the - string changes. - */ - operator const char*() const throw(); - - /** Returns a unicode version of this string. - - Because it returns a reference to the string's internal data, the pointer - that is returned must not be stored anywhere, as it can be deleted whenever the - string changes. - */ - inline operator const juce_wchar*() const throw() { return text->text; } + inline operator const juce_wchar*() const throw() { return text->text; } #else - /** Returns a version of this string using the default 8-bit system encoding. + inline operator const char*() const throw() { return text->text; } - Because it returns a reference to the string's internal data, the pointer - that is returned must not be stored anywhere, as it can be deleted whenever the - string changes. - */ - inline operator const char*() const throw() { return text->text; } - - /** Returns a unicode version of this string. - - Because it returns a reference to the string's internal data, the pointer - that is returned must not be stored anywhere, as it can be deleted whenever the - string changes. - */ - operator const juce_wchar*() const throw(); + operator const juce_wchar*() const throw(); #endif - /** Copies the string to a buffer. + void copyToBuffer (char* const destBuffer, + const int maxCharsToCopy) const throw(); - @param destBuffer the place to copy it to - @param maxCharsToCopy the maximum number of characters to copy to the buffer, - not including the tailing zero, so this shouldn't be - larger than the size of your destination buffer - 1 - */ - void copyToBuffer (char* const destBuffer, - const int maxCharsToCopy) const throw(); + void copyToBuffer (juce_wchar* const destBuffer, + const int maxCharsToCopy) const throw(); - /** Copies the string to a unicode buffer. + int copyToUTF8 (uint8* const destBuffer, const int maxBufferSizeBytes = 0x7fffffff) const throw(); - @param destBuffer the place to copy it to - @param maxCharsToCopy the maximum number of characters to copy to the buffer, - not including the tailing zero, so this shouldn't be - larger than the size of your destination buffer - 1 - */ - void copyToBuffer (juce_wchar* const destBuffer, - const int maxCharsToCopy) const throw(); + const char* toUTF8() const throw(); - /** Copies the string to a buffer as UTF-8 characters. + static const String fromUTF8 (const uint8* const utf8buffer, + int bufferSizeBytes = -1) throw(); - Returns the number of bytes copied to the buffer, including the terminating null - character. + void preallocateStorage (const size_t numCharsNeeded) throw(); - @param destBuffer the place to copy it to; if this is a null pointer, - the method just returns the number of bytes required - (including the terminating null character). - @param maxBufferSizeBytes the size of the destination buffer, in bytes. If the - string won't fit, it'll put in as many as it can while - still allowing for a terminating null char at the end, - and will return the number of bytes that were actually - used. If this value is < 0, no limit is used. - */ - int copyToUTF8 (uint8* const destBuffer, const int maxBufferSizeBytes = 0x7fffffff) const throw(); + class JUCE_API Concatenator + { + public: + Concatenator (String& stringToAppendTo); + ~Concatenator(); - /** Returns a pointer to a UTF-8 version of this string. + void append (const String& s); - Because it returns a reference to the string's internal data, the pointer - that is returned must not be stored anywhere, as it can be deleted whenever the - string changes. - */ - const char* toUTF8() const throw(); + private: + String& result; + int nextIndex; - /** Creates a String from a UTF-8 encoded buffer. + Concatenator (const Concatenator&); + const Concatenator& operator= (const Concatenator&); + }; - If the size is < 0, it'll keep reading until it hits a zero. - */ - static const String fromUTF8 (const uint8* const utf8buffer, - int bufferSizeBytes = -1) throw(); - - /** Increases the string's internally allocated storage. - - Although the string's contents won't be affected by this call, it will - increase the amount of memory allocated internally for the string to grow into. - - If you're about to make a large number of calls to methods such - as += or <<, it's more efficient to preallocate enough extra space - beforehand, so that these methods won't have to keep resizing the string - to append the extra characters. - - @param numCharsNeeded the number of characters to allocate storage for. If this - value is less than the currently allocated size, it will - have no effect. - */ - void preallocateStorage (const int numCharsNeeded) throw(); - - /** A helper class to improve performance when concatenating many large strings - together. - - Because appending one string to another involves measuring the length of - both strings, repeatedly doing this for many long strings will become - an exponentially slow operation. This class uses some internal state to - avoid that, so that each append operation only needs to measure the length - of the appended string. - */ - class JUCE_API Concatenator - { - public: - Concatenator (String& stringToAppendTo); - ~Concatenator(); - - void append (const String& s); - - private: - String& result; - int nextIndex; - - Concatenator (const Concatenator&); - const Concatenator& operator= (const Concatenator&); - }; - - juce_UseDebuggingNewOperator // (adds debugging info to find leaked objects) + juce_UseDebuggingNewOperator // (adds debugging info to find leaked objects) private: - struct InternalRefCountedStringHolder - { - int refCount; - int allocatedNumChars; + struct InternalRefCountedStringHolder + { + int refCount; + int allocatedNumChars; #if JUCE_STRINGS_ARE_UNICODE - wchar_t text[1]; + wchar_t text[1]; #else - char text[1]; + char text[1]; #endif - }; + }; - InternalRefCountedStringHolder* text; - static InternalRefCountedStringHolder emptyString; + InternalRefCountedStringHolder* text; + static InternalRefCountedStringHolder emptyString; - // internal constructor that preallocates a certain amount of memory - String (const int numChars, const int dummyVariable) throw(); + // internal constructor that preallocates a certain amount of memory + String (const int numChars, const int dummyVariable) throw(); - void deleteInternal() throw(); - void createInternal (const int numChars) throw(); - void createInternal (const tchar* const text, const tchar* const textEnd) throw(); - void appendInternal (const tchar* const text, const int numExtraChars) throw(); - void doubleToStringWithDecPlaces (double n, int numDecPlaces) throw(); - void dupeInternalIfMultiplyReferenced() throw(); + void deleteInternal() throw(); + void createInternal (const int numChars) throw(); + void createInternal (const tchar* const text, const tchar* const textEnd) throw(); + void appendInternal (const tchar* const text, const int numExtraChars) throw(); + void doubleToStringWithDecPlaces (double n, int numDecPlaces) throw(); + void dupeInternalIfMultiplyReferenced() throw(); }; -/** Global operator to allow a String to be appended to a string literal. - - This allows the use of expressions such as "abc" + String (x) - - @see String - */ const String JUCE_PUBLIC_FUNCTION operator+ (const char* const string1, - const String& string2) throw(); + const String& string2) throw(); -/** Global operator to allow a String to be appended to a string literal. - - This allows the use of expressions such as "abc" + String (x) - - @see String - */ const String JUCE_PUBLIC_FUNCTION operator+ (const juce_wchar* const string1, - const String& string2) throw(); + const String& string2) throw(); #endif // __JUCE_STRING_JUCEHEADER__ /********* End of inlined file: juce_String.h *********/ -/** - Acts as an application-wide logging class. - - A subclass of Logger can be created and passed into the Logger::setCurrentLogger - method and this will then be used by all calls to writeToLog. - - The logger class also contains methods for writing messages to the debugger's - output stream. - - @see FileLogger -*/ class JUCE_API Logger { public: - /** Destructor. */ - virtual ~Logger(); + virtual ~Logger(); - /** Sets the current logging class to use. + static void JUCE_CALLTYPE setCurrentLogger (Logger* const newLogger, + const bool deleteOldLogger = false); - Note that the object passed in won't be deleted when no longer needed. - A null pointer can be passed-in to disable any logging. + static void JUCE_CALLTYPE writeToLog (const String& message); - If deleteOldLogger is set to true, the existing logger will be - deleted (if there is one). - */ - static void JUCE_CALLTYPE setCurrentLogger (Logger* const newLogger, - const bool deleteOldLogger = false); + static void JUCE_CALLTYPE outputDebugString (const String& text) throw(); - /** Writes a string to the current logger. - - This will pass the string to the logger's logMessage() method if a logger - has been set. - - @see logMessage - */ - static void JUCE_CALLTYPE writeToLog (const String& message); - - /** Writes a message to the standard error stream. - - This can be called directly, or by using the DBG() macro in - juce_PlatformDefs.h (which will avoid calling the method in non-debug builds). - */ - static void JUCE_CALLTYPE outputDebugString (const String& text) throw(); - - /** Writes a message to the standard error stream. - - This can be called directly, or by using the DBG_PRINTF() macro in - juce_PlatformDefs.h (which will avoid calling the method in non-debug builds). - */ - static void JUCE_CALLTYPE outputDebugPrintf (const tchar* format, ...) throw(); + static void JUCE_CALLTYPE outputDebugPrintf (const tchar* format, ...) throw(); protected: - Logger(); + Logger(); - /** This is overloaded by subclasses to implement custom logging behaviour. - - @see setCurrentLogger - */ - virtual void logMessage (const String& message) = 0; + virtual void logMessage (const String& message) = 0; }; #endif // __JUCE_LOGGER_JUCEHEADER__ @@ -2710,111 +1458,67 @@ BEGIN_JUCE_NAMESPACE #ifndef __JUCE_ARRAYALLOCATIONBASE_JUCEHEADER__ #define __JUCE_ARRAYALLOCATIONBASE_JUCEHEADER__ -/** The default size of chunk in which arrays increase their storage. - - Used by ArrayAllocationBase and its subclasses. -*/ -const int juceDefaultArrayGranularity = 8; - -/** - Implements some basic array storage allocation functions. - - This class isn't really for public use - it's used by the other - array classes, but might come in handy for some purposes. - - @see Array, OwnedArray, ReferenceCountedArray -*/ template class ArrayAllocationBase { public: - /** Creates an empty array. + ArrayAllocationBase() throw() + : elements (0), + numAllocated (0) + { + } - @param granularity_ this is the size of increment by which the internal storage - will be increased. - */ - ArrayAllocationBase (const int granularity_) throw() - : elements (0), - numAllocated (0), - granularity (granularity_) - { - jassert (granularity > 0); - } + ~ArrayAllocationBase() + { + delete[] elements; + } - /** Destructor. */ - ~ArrayAllocationBase() - { - delete[] elements; - } + void setAllocatedSize (const int numElements) throw() + { + if (numAllocated != numElements) + { + if (numElements > 0) + { + ElementType* const newElements = new ElementType [numElements]; - /** Changes the amount of storage allocated. + const int itemsToRetain = jmin (numElements, numAllocated); - This will retain any data currently held in the array, and either add or - remove extra space at the end. + for (int i = 0; i < itemsToRetain; ++i) + newElements[i] = elements[i]; - @param numElements the number of elements that are needed - */ - void setAllocatedSize (const int numElements) throw() - { - if (numAllocated != numElements) - { - if (numElements > 0) - { - ElementType* const newElements = new ElementType [numElements]; + delete[] elements; + elements = newElements; - const int itemsToRetain = jmin (numElements, numAllocated); + } + else + { + delete[] elements; + elements = 0; + } - for (int i = 0; i < itemsToRetain; ++i) - newElements[i] = elements[i]; + numAllocated = numElements; + } + } - delete[] elements; - elements = newElements; + void ensureAllocatedSize (int minNumElements) throw() + { + if (minNumElements > numAllocated) + setAllocatedSize ((minNumElements + minNumElements / 2 + 8) & ~7); + } - } - else - { - delete[] elements; - elements = 0; - } + void shrinkToNoMoreThan (int maxNumElements) throw() + { + if (maxNumElements < numAllocated) + setAllocatedSize (maxNumElements); + } - numAllocated = numElements; - } - } - - /** Increases the amount of storage allocated if it is less than a given amount. - - This will retain any data currently held in the array, but will add - extra space at the end to make sure there it's at least as big as the size - passed in. If it's already bigger, no action is taken. - - @param minNumElements the minimum number of elements that are needed - */ - void ensureAllocatedSize (int minNumElements) throw() - { - if (minNumElements > numAllocated) - { - // for arrays with small granularity that get big, start - // increasing the size in bigger jumps - if (minNumElements > (granularity << 6)) - { - minNumElements += (minNumElements / granularity); - if (minNumElements > (granularity << 8)) - minNumElements += granularity << 6; - else - minNumElements += granularity << 5; - } - - setAllocatedSize (granularity * (minNumElements / granularity + 1)); - } - } - - ElementType* elements; - int numAllocated, granularity; + ElementType* elements; + int numAllocated; private: - ArrayAllocationBase (const ArrayAllocationBase&); - const ArrayAllocationBase& operator= (const ArrayAllocationBase&); + ArrayAllocationBase (const ArrayAllocationBase&); + const ArrayAllocationBase& operator= (const ArrayAllocationBase&); }; #endif // __JUCE_ARRAYALLOCATIONBASE_JUCEHEADER__ @@ -2824,281 +1528,201 @@ private: #ifndef __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__ #define __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__ -/** - Sorts a range of elements in an array. - - The comparator object that is passed-in must define a public method with the following - signature: - @code - int compareElements (ElementType first, ElementType second); - @endcode - - ..and this method must return: - - a value of < 0 if the first comes before the second - - a value of 0 if the two objects are equivalent - - a value of > 0 if the second comes before the first - - To improve performance, the compareElements() method can be declared as static or const. - - @param comparator an object which defines a compareElements() method - @param array the array to sort - @param firstElement the index of the first element of the range to be sorted - @param lastElement the index of the last element in the range that needs - sorting (this is inclusive) - @param retainOrderOfEquivalentItems if true, the order of items that the - comparator deems the same will be maintained - this will be - a slower algorithm than if they are allowed to be moved around. - - @see sortArrayRetainingOrder -*/ template static void sortArray (ElementComparator& comparator, - ElementType* const array, - int firstElement, - int lastElement, - const bool retainOrderOfEquivalentItems) + ElementType* const array, + int firstElement, + int lastElement, + const bool retainOrderOfEquivalentItems) { - (void) comparator; // if you pass in an object with a static compareElements() method, this - // avoids getting warning messages about the parameter being unused + (void) comparator; // if you pass in an object with a static compareElements() method, this + // avoids getting warning messages about the parameter being unused - if (lastElement > firstElement) - { - if (retainOrderOfEquivalentItems) - { - for (int i = firstElement; i < lastElement; ++i) - { - if (comparator.compareElements (array[i], array [i + 1]) > 0) - { - const ElementType temp = array [i]; - array [i] = array[i + 1]; - array [i + 1] = temp; + if (lastElement > firstElement) + { + if (retainOrderOfEquivalentItems) + { + for (int i = firstElement; i < lastElement; ++i) + { + if (comparator.compareElements (array[i], array [i + 1]) > 0) + { + const ElementType temp = array [i]; + array [i] = array[i + 1]; + array [i + 1] = temp; - if (i > firstElement) - i -= 2; - } - } - } - else - { - int fromStack[30], toStack[30]; - int stackIndex = 0; + if (i > firstElement) + i -= 2; + } + } + } + else + { + int fromStack[30], toStack[30]; + int stackIndex = 0; - for (;;) - { - const int size = (lastElement - firstElement) + 1; + for (;;) + { + const int size = (lastElement - firstElement) + 1; - if (size <= 8) - { - int j = lastElement; - int maxIndex; + if (size <= 8) + { + int j = lastElement; + int maxIndex; - while (j > firstElement) - { - maxIndex = firstElement; - for (int k = firstElement + 1; k <= j; ++k) - if (comparator.compareElements (array[k], array [maxIndex]) > 0) - maxIndex = k; + while (j > firstElement) + { + maxIndex = firstElement; + for (int k = firstElement + 1; k <= j; ++k) + if (comparator.compareElements (array[k], array [maxIndex]) > 0) + maxIndex = k; - const ElementType temp = array [maxIndex]; - array [maxIndex] = array[j]; - array [j] = temp; + const ElementType temp = array [maxIndex]; + array [maxIndex] = array[j]; + array [j] = temp; - --j; - } - } - else - { - const int mid = firstElement + (size >> 1); - ElementType temp = array [mid]; - array [mid] = array [firstElement]; - array [firstElement] = temp; + --j; + } + } + else + { + const int mid = firstElement + (size >> 1); + ElementType temp = array [mid]; + array [mid] = array [firstElement]; + array [firstElement] = temp; - int i = firstElement; - int j = lastElement + 1; + int i = firstElement; + int j = lastElement + 1; - for (;;) - { - while (++i <= lastElement - && comparator.compareElements (array[i], array [firstElement]) <= 0) - {} + for (;;) + { + while (++i <= lastElement + && comparator.compareElements (array[i], array [firstElement]) <= 0) + {} - while (--j > firstElement - && comparator.compareElements (array[j], array [firstElement]) >= 0) - {} + while (--j > firstElement + && comparator.compareElements (array[j], array [firstElement]) >= 0) + {} - if (j < i) - break; + if (j < i) + break; - temp = array[i]; - array[i] = array[j]; - array[j] = temp; - } + temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } - temp = array [firstElement]; - array [firstElement] = array[j]; - array [j] = temp; + temp = array [firstElement]; + array [firstElement] = array[j]; + array [j] = temp; - if (j - 1 - firstElement >= lastElement - i) - { - if (firstElement + 1 < j) - { - fromStack [stackIndex] = firstElement; - toStack [stackIndex] = j - 1; - ++stackIndex; - } + if (j - 1 - firstElement >= lastElement - i) + { + if (firstElement + 1 < j) + { + fromStack [stackIndex] = firstElement; + toStack [stackIndex] = j - 1; + ++stackIndex; + } - if (i < lastElement) - { - firstElement = i; - continue; - } - } - else - { - if (i < lastElement) - { - fromStack [stackIndex] = i; - toStack [stackIndex] = lastElement; - ++stackIndex; - } + if (i < lastElement) + { + firstElement = i; + continue; + } + } + else + { + if (i < lastElement) + { + fromStack [stackIndex] = i; + toStack [stackIndex] = lastElement; + ++stackIndex; + } - if (firstElement + 1 < j) - { - lastElement = j - 1; - continue; - } - } - } + if (firstElement + 1 < j) + { + lastElement = j - 1; + continue; + } + } + } - if (--stackIndex < 0) - break; + if (--stackIndex < 0) + break; - jassert (stackIndex < numElementsInArray (fromStack)); + jassert (stackIndex < numElementsInArray (fromStack)); - firstElement = fromStack [stackIndex]; - lastElement = toStack [stackIndex]; - } - } - } + firstElement = fromStack [stackIndex]; + lastElement = toStack [stackIndex]; + } + } + } } -/** - Searches a sorted array of elements, looking for the index at which a specified value - should be inserted for it to be in the correct order. - - The comparator object that is passed-in must define a public method with the following - signature: - @code - int compareElements (ElementType first, ElementType second); - @endcode - - ..and this method must return: - - a value of < 0 if the first comes before the second - - a value of 0 if the two objects are equivalent - - a value of > 0 if the second comes before the first - - To improve performance, the compareElements() method can be declared as static or const. - - @param comparator an object which defines a compareElements() method - @param array the array to search - @param newElement the value that is going to be inserted - @param firstElement the index of the first element to search - @param lastElement the index of the last element in the range (this is non-inclusive) -*/ template static int findInsertIndexInSortedArray (ElementComparator& comparator, - ElementType* const array, - const ElementType newElement, - int firstElement, - int lastElement) + ElementType* const array, + const ElementType newElement, + int firstElement, + int lastElement) { - jassert (firstElement <= lastElement); + jassert (firstElement <= lastElement); - (void) comparator; // if you pass in an object with a static compareElements() method, this - // avoids getting warning messages about the parameter being unused + (void) comparator; // if you pass in an object with a static compareElements() method, this + // avoids getting warning messages about the parameter being unused - while (firstElement < lastElement) - { - if (comparator.compareElements (newElement, array [firstElement]) == 0) - { - ++firstElement; - break; - } - else - { - const int halfway = (firstElement + lastElement) >> 1; + while (firstElement < lastElement) + { + if (comparator.compareElements (newElement, array [firstElement]) == 0) + { + ++firstElement; + break; + } + else + { + const int halfway = (firstElement + lastElement) >> 1; - if (halfway == firstElement) - { - if (comparator.compareElements (newElement, array [halfway]) >= 0) - ++firstElement; + if (halfway == firstElement) + { + if (comparator.compareElements (newElement, array [halfway]) >= 0) + ++firstElement; - break; - } - else if (comparator.compareElements (newElement, array [halfway]) >= 0) - { - firstElement = halfway; - } - else - { - lastElement = halfway; - } - } - } + break; + } + else if (comparator.compareElements (newElement, array [halfway]) >= 0) + { + firstElement = halfway; + } + else + { + lastElement = halfway; + } + } + } - return firstElement; + return firstElement; } -/** - A simple ElementComparator class that can be used to sort an array of - integer primitive objects. - - Example: @code - Array myArray; - - IntegerElementComparator sorter; - myArray.sort (sorter); - @endcode - - For floating point values, see the FloatElementComparator class instead. - - @see FloatElementComparator, ElementComparator -*/ template class IntegerElementComparator { public: - static int compareElements (const ElementType first, - const ElementType second) throw() - { - return (first < second) ? -1 : ((first == second) ? 0 : 1); - } + static int compareElements (const ElementType first, + const ElementType second) throw() + { + return (first < second) ? -1 : ((first == second) ? 0 : 1); + } }; -/** - A simple ElementComparator class that can be used to sort an array of numeric - double or floating point primitive objects. - - Example: @code - Array myArray; - - FloatElementComparator sorter; - myArray.sort (sorter); - @endcode - - For integer values, see the IntegerElementComparator class instead. - - @see IntegerElementComparator, ElementComparator -*/ template class FloatElementComparator { public: - static int compareElements (const ElementType first, - const ElementType second) throw() - { - return (first < second) ? -1 : ((first == second) ? 0 : 1); - } + static int compareElements (const ElementType first, + const ElementType second) throw() + { + return (first < second) ? -1 : ((first == second) ? 0 : 1); + } }; #endif // __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__ @@ -3108,1134 +1732,727 @@ public: #ifndef __JUCE_CRITICALSECTION_JUCEHEADER__ #define __JUCE_CRITICALSECTION_JUCEHEADER__ -/** - Prevents multiple threads from accessing shared objects at the same time. - - @see ScopedLock, Thread, InterProcessLock -*/ class JUCE_API CriticalSection { public: - /** - Creates a CriticalSection object - */ - CriticalSection() throw(); + CriticalSection() throw(); - /** Destroys a CriticalSection object. + ~CriticalSection() throw(); - If the critical section is deleted whilst locked, its subsequent behaviour - is unpredictable. - */ - ~CriticalSection() throw(); + void enter() const throw(); - /** Locks this critical section. + bool tryEnter() const throw(); - If the lock is currently held by another thread, this will wait until it - becomes free. + void exit() const throw(); - If the lock is already held by the caller thread, the method returns immediately. - - @see exit, ScopedLock - */ - void enter() const throw(); - - /** Attempts to lock this critical section without blocking. - - This method behaves identically to CriticalSection::enter, except that the caller thread - does not wait if the lock is currently held by another thread but returns false immediately. - - @returns false if the lock is currently held by another thread, true otherwise. - @see enter - */ - bool tryEnter() const throw(); - - /** Releases the lock. - - If the caller thread hasn't got the lock, this can have unpredictable results. - - If the enter() method has been called multiple times by the thread, each - call must be matched by a call to exit() before other threads will be allowed - to take over the lock. - - @see enter, ScopedLock - */ - void exit() const throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: #if JUCE_WIN32 #if JUCE_64BIT - // To avoid including windows.h in the public Juce includes, we'll just allocate a - // block of memory here that's big enough to be used internally as a windows critical - // section object. - uint8 internal [44]; + // To avoid including windows.h in the public Juce includes, we'll just allocate a + // block of memory here that's big enough to be used internally as a windows critical + // section object. + uint8 internal [44]; #else - uint8 internal [24]; + uint8 internal [24]; #endif #else - mutable pthread_mutex_t internal; + mutable pthread_mutex_t internal; #endif - CriticalSection (const CriticalSection&); - const CriticalSection& operator= (const CriticalSection&); + CriticalSection (const CriticalSection&); + const CriticalSection& operator= (const CriticalSection&); }; -/** - A class that can be used in place of a real CriticalSection object. - - This is currently used by some templated array classes, and should get - optimised out by the compiler. - - @see Array, OwnedArray, ReferenceCountedArray -*/ class JUCE_API DummyCriticalSection { public: - forcedinline DummyCriticalSection() throw() {} - forcedinline ~DummyCriticalSection() throw() {} + inline DummyCriticalSection() throw() {} + inline ~DummyCriticalSection() throw() {} - forcedinline void enter() const throw() {} - forcedinline void exit() const throw() {} + inline void enter() const throw() {} + inline void exit() const throw() {} }; #endif // __JUCE_CRITICALSECTION_JUCEHEADER__ /********* End of inlined file: juce_CriticalSection.h *********/ -/** - Holds a list of primitive objects, such as ints, doubles, or pointers. - - Examples of arrays are: Array or Array - - Note that when holding pointers to objects, the array doesn't take any ownership - of the objects - for doing this, see the OwnedArray class or the ReferenceCountedArray class. - - If you're using a class or struct as the element type, it must be - capable of being copied or moved with a straightforward memcpy, rather than - needing construction and destruction code. - - For holding lists of strings, use the specialised class StringArray. - - To make all the array's methods thread-safe, pass in "CriticalSection" as the templated - TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection. - - @see OwnedArray, ReferenceCountedArray, StringArray, CriticalSection -*/ template class Array { public: - /** Creates an empty array. - - @param granularity this is the size of increment by which the internal storage - used by the array will grow. Only change it from the default if you know the - array is going to be very big and needs to be able to grow efficiently. - */ - Array (const int granularity = juceDefaultArrayGranularity) throw() - : data (granularity), - numUsed (0) - { - } - - /** Creates a copy of another array. - @param other the array to copy - */ - Array (const Array& other) throw() - : data (other.data.granularity) - { - other.lockArray(); - numUsed = other.numUsed; - data.setAllocatedSize (other.numUsed); - memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); - other.unlockArray(); - } - - /** Initalises from a null-terminated C array of values. - - @param values the array to copy from - */ - Array (const ElementType* values) throw() - : data (juceDefaultArrayGranularity), - numUsed (0) - { - while (*values != 0) - add (*values++); - } - - /** Initalises from a C array of values. - - @param values the array to copy from - @param numValues the number of values in the array - */ - Array (const ElementType* values, int numValues) throw() - : data (juceDefaultArrayGranularity), - numUsed (numValues) - { - data.setAllocatedSize (numValues); - memcpy (data.elements, values, numValues * sizeof (ElementType)); - } - - /** Destructor. */ - ~Array() throw() - { - } - - /** Copies another array. - @param other the array to copy - */ - const Array & operator= (const Array & other) throw() - { - if (this != &other) - { - other.lockArray(); - lock.enter(); - - data.granularity = other.data.granularity; - data.ensureAllocatedSize (other.size()); - numUsed = other.numUsed; - memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); - minimiseStorageOverheads(); - - lock.exit(); - other.unlockArray(); - } - - return *this; - } - - /** Compares this array to another one. - Two arrays are considered equal if they both contain the same set of - elements, in the same order. - @param other the other array to compare with - */ - template - bool operator== (const OtherArrayType& other) const throw() - { - lock.enter(); - - if (numUsed != other.numUsed) - { - lock.exit(); - return false; - } - - for (int i = numUsed; --i >= 0;) - { - if (data.elements [i] != other.data.elements [i]) - { - lock.exit(); - return false; - } - } - - lock.exit(); - return true; - } - - /** Compares this array to another one. - Two arrays are considered equal if they both contain the same set of - elements, in the same order. - @param other the other array to compare with - */ - template - bool operator!= (const OtherArrayType& other) const throw() - { - return ! operator== (other); - } - - /** Removes all elements from the array. - This will remove all the elements, and free any storage that the array is - using. To clear the array without freeing the storage, use the clearQuick() - method instead. - - @see clearQuick - */ - void clear() throw() - { - lock.enter(); - data.setAllocatedSize (0); - numUsed = 0; - lock.exit(); - } - - /** Removes all elements from the array without freeing the array's allocated storage. - - @see clear - */ - void clearQuick() throw() - { - lock.enter(); - numUsed = 0; - lock.exit(); - } - - /** Returns the current number of elements in the array. - */ - inline int size() const throw() - { - return numUsed; - } - - /** Returns one of the elements in the array. - If the index passed in is beyond the range of valid elements, this - will return zero. - - If you're certain that the index will always be a valid element, you - can call getUnchecked() instead, which is faster. - - @param index the index of the element being requested (0 is the first element in the array) - @see getUnchecked, getFirst, getLast - */ - inline ElementType operator[] (const int index) const throw() - { - lock.enter(); - const ElementType result = (((unsigned int) index) < (unsigned int) numUsed) - ? data.elements [index] - : ElementType(); - lock.exit(); - - return result; - } - - /** Returns one of the elements in the array, without checking the index passed in. - - Unlike the operator[] method, this will try to return an element without - checking that the index is within the bounds of the array, so should only - be used when you're confident that it will always be a valid index. - - @param index the index of the element being requested (0 is the first element in the array) - @see operator[], getFirst, getLast - */ - inline ElementType getUnchecked (const int index) const throw() - { - lock.enter(); - jassert (((unsigned int) index) < (unsigned int) numUsed); - const ElementType result = data.elements [index]; - lock.exit(); - - return result; - } - - /** Returns a direct reference to one of the elements in the array, without checking the index passed in. - - This is like getUnchecked, but returns a direct reference to the element, so that - you can alter it directly. Obviously this can be dangerous, so only use it when - absolutely necessary. - - @param index the index of the element being requested (0 is the first element in the array) - @see operator[], getFirst, getLast - */ - inline ElementType& getReference (const int index) const throw() - { - lock.enter(); - jassert (((unsigned int) index) < (unsigned int) numUsed); - ElementType& result = data.elements [index]; - lock.exit(); - return result; - } - - /** Returns the first element in the array, or 0 if the array is empty. - - @see operator[], getUnchecked, getLast - */ - inline ElementType getFirst() const throw() - { - lock.enter(); - const ElementType result = (numUsed > 0) ? data.elements [0] - : ElementType(); - lock.exit(); - - return result; - } - - /** Returns the last element in the array, or 0 if the array is empty. - - @see operator[], getUnchecked, getFirst - */ - inline ElementType getLast() const throw() - { - lock.enter(); - const ElementType result = (numUsed > 0) ? data.elements [numUsed - 1] - : ElementType(); - lock.exit(); - - return result; - } - - /** Finds the index of the first element which matches the value passed in. - - This will search the array for the given object, and return the index - of its first occurrence. If the object isn't found, the method will return -1. - - @param elementToLookFor the value or object to look for - @returns the index of the object, or -1 if it's not found - */ - int indexOf (const ElementType elementToLookFor) const throw() - { - int result = -1; - - lock.enter(); - const ElementType* e = data.elements; - - for (int i = numUsed; --i >= 0;) - { - if (elementToLookFor == *e) - { - result = (int) (e - data.elements); - break; - } - - ++e; - } - - lock.exit(); - return result; - } - - /** Returns true if the array contains at least one occurrence of an object. - - @param elementToLookFor the value or object to look for - @returns true if the item is found - */ - bool contains (const ElementType elementToLookFor) const throw() - { - lock.enter(); - - const ElementType* e = data.elements; - int num = numUsed; - - while (num >= 4) - { - if (*e == elementToLookFor - || *++e == elementToLookFor - || *++e == elementToLookFor - || *++e == elementToLookFor) - { - lock.exit(); - return true; - } - - num -= 4; - ++e; - } - - while (num > 0) - { - if (elementToLookFor == *e) - { - lock.exit(); - return true; - } - - --num; - ++e; - } - - lock.exit(); - return false; - } - - /** Appends a new element at the end of the array. - - @param newElement the new object to add to the array - @see set, insert, addIfNotAlreadyThere, addSorted, addArray - */ - void add (const ElementType newElement) throw() - { - lock.enter(); - data.ensureAllocatedSize (numUsed + 1); - data.elements [numUsed++] = newElement; - lock.exit(); - } - - /** Inserts a new element into the array at a given position. - - If the index is less than 0 or greater than the size of the array, the - element will be added to the end of the array. - Otherwise, it will be inserted into the array, moving all the later elements - along to make room. - - @param indexToInsertAt the index at which the new element should be - inserted (pass in -1 to add it to the end) - @param newElement the new object to add to the array - @see add, addSorted, set - */ - void insert (int indexToInsertAt, const ElementType newElement) throw() - { - lock.enter(); - data.ensureAllocatedSize (numUsed + 1); - - if (((unsigned int) indexToInsertAt) < (unsigned int) numUsed) - { - ElementType* const insertPos = data.elements + indexToInsertAt; - const int numberToMove = numUsed - indexToInsertAt; - - if (numberToMove > 0) - memmove (insertPos + 1, insertPos, numberToMove * sizeof (ElementType)); - - *insertPos = newElement; - ++numUsed; - } - else - { - data.elements [numUsed++] = newElement; - } - - lock.exit(); - } - - /** Inserts multiple copies of an element into the array at a given position. - - If the index is less than 0 or greater than the size of the array, the - element will be added to the end of the array. - Otherwise, it will be inserted into the array, moving all the later elements - along to make room. - - @param indexToInsertAt the index at which the new element should be inserted - @param newElement the new object to add to the array - @param numberOfTimesToInsertIt how many copies of the value to insert - @see insert, add, addSorted, set - */ - void insertMultiple (int indexToInsertAt, const ElementType newElement, - int numberOfTimesToInsertIt) throw() - { - if (numberOfTimesToInsertIt > 0) - { - lock.enter(); - data.ensureAllocatedSize (numUsed + numberOfTimesToInsertIt); - - if (((unsigned int) indexToInsertAt) < (unsigned int) numUsed) - { - ElementType* insertPos = data.elements + indexToInsertAt; - const int numberToMove = numUsed - indexToInsertAt; - - memmove (insertPos + numberOfTimesToInsertIt, insertPos, numberToMove * sizeof (ElementType)); - numUsed += numberOfTimesToInsertIt; - - while (--numberOfTimesToInsertIt >= 0) - *insertPos++ = newElement; - } - else - { - while (--numberOfTimesToInsertIt >= 0) - data.elements [numUsed++] = newElement; - } - - lock.exit(); - } - } - - /** Inserts an array of values into this array at a given position. - - If the index is less than 0 or greater than the size of the array, the - new elements will be added to the end of the array. - Otherwise, they will be inserted into the array, moving all the later elements - along to make room. - - @param indexToInsertAt the index at which the first new element should be inserted - @param newElements the new values to add to the array - @param numberOfElements how many items are in the array - @see insert, add, addSorted, set - */ - void insertArray (int indexToInsertAt, - const ElementType* newElements, - int numberOfElements) throw() - { - if (numberOfElements > 0) - { - lock.enter(); - data.ensureAllocatedSize (numUsed + numberOfElements); - - if (((unsigned int) indexToInsertAt) < (unsigned int) numUsed) - { - ElementType* insertPos = data.elements + indexToInsertAt; - const int numberToMove = numUsed - indexToInsertAt; - - memmove (insertPos + numberOfElements, insertPos, numberToMove * sizeof (ElementType)); - numUsed += numberOfElements; - - while (--numberOfElements >= 0) - *insertPos++ = *newElements++; - } - else - { - while (--numberOfElements >= 0) - data.elements [numUsed++] = *newElements++; - } - - lock.exit(); - } - } - - /** Appends a new element at the end of the array as long as the array doesn't - already contain it. - - If the array already contains an element that matches the one passed in, nothing - will be done. - - @param newElement the new object to add to the array - */ - void addIfNotAlreadyThere (const ElementType newElement) throw() - { - lock.enter(); - - if (! contains (newElement)) - add (newElement); - - lock.exit(); - } - - /** Replaces an element with a new value. - - If the index is less than zero, this method does nothing. - If the index is beyond the end of the array, the item is added to the end of the array. - - @param indexToChange the index whose value you want to change - @param newValue the new value to set for this index. - @see add, insert - */ - void set (const int indexToChange, - const ElementType newValue) throw() - { - jassert (indexToChange >= 0); - - if (indexToChange >= 0) - { - lock.enter(); - - if (indexToChange < numUsed) - { - data.elements [indexToChange] = newValue; - } - else - { - data.ensureAllocatedSize (numUsed + 1); - data.elements [numUsed++] = newValue; - } - - lock.exit(); - } - } - - /** Replaces an element with a new value without doing any bounds-checking. - - This just sets a value directly in the array's internal storage, so you'd - better make sure it's in range! - - @param indexToChange the index whose value you want to change - @param newValue the new value to set for this index. - @see set, getUnchecked - */ - void setUnchecked (const int indexToChange, - const ElementType newValue) throw() - { - lock.enter(); - jassert (((unsigned int) indexToChange) < (unsigned int) numUsed); - data.elements [indexToChange] = newValue; - lock.exit(); - } - - /** Adds elements from an array to the end of this array. - - @param elementsToAdd the array of elements to add - @param numElementsToAdd how many elements are in this other array - @see add - */ - void addArray (const ElementType* elementsToAdd, - int numElementsToAdd) throw() - { - lock.enter(); - - if (numElementsToAdd > 0) - { - data.ensureAllocatedSize (numUsed + numElementsToAdd); - - while (--numElementsToAdd >= 0) - data.elements [numUsed++] = *elementsToAdd++; - } - - lock.exit(); - } - - /** This swaps the contents of this array with those of another array. - - If you need to exchange two arrays, this is vastly quicker than using copy-by-value - because it just swaps their internal pointers. - */ - template - void swapWithArray (OtherArrayType& otherArray) throw() - { - lock.enter(); - otherArray.lock.enter(); - swapVariables (numUsed, otherArray.numUsed); - swapVariables (data.elements, otherArray.data.elements); - swapVariables (data.numAllocated, otherArray.data.numAllocated); - otherArray.lock.exit(); - lock.exit(); - } - - /** Adds elements from another array to the end of this array. - - @param arrayToAddFrom the array from which to copy the elements - @param startIndex the first element of the other array to start copying from - @param numElementsToAdd how many elements to add from the other array. If this - value is negative or greater than the number of available elements, - all available elements will be copied. - @see add - */ - template - void addArray (const OtherArrayType& arrayToAddFrom, - int startIndex = 0, - int numElementsToAdd = -1) throw() - { - arrayToAddFrom.lockArray(); - lock.enter(); - - if (startIndex < 0) - { - jassertfalse - startIndex = 0; - } - - if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size()) - numElementsToAdd = arrayToAddFrom.size() - startIndex; - - while (--numElementsToAdd >= 0) - add (arrayToAddFrom.getUnchecked (startIndex++)); - - lock.exit(); - arrayToAddFrom.unlockArray(); - } - - /** Inserts a new element into the array, assuming that the array is sorted. - - This will use a comparator to find the position at which the new element - should go. If the array isn't sorted, the behaviour of this - method will be unpredictable. - - @param comparator the comparator to use to compare the elements - see the sort() - method for details about the form this object should take - @param newElement the new element to insert to the array - @see add, sort - */ - template - void addSorted (ElementComparator& comparator, - const ElementType newElement) throw() - { - lock.enter(); - insert (findInsertIndexInSortedArray (comparator, data.elements, newElement, 0, numUsed), newElement); - lock.exit(); - } - - /** Finds the index of an element in the array, assuming that the array is sorted. - - This will use a comparator to do a binary-chop to find the index of the given - element, if it exists. If the array isn't sorted, the behaviour of this - method will be unpredictable. - - @param comparator the comparator to use to compare the elements - see the sort() - method for details about the form this object should take - @param elementToLookFor the element to search for - @returns the index of the element, or -1 if it's not found - @see addSorted, sort - */ - template - int indexOfSorted (ElementComparator& comparator, - const ElementType elementToLookFor) const throw() - { - (void) comparator; // if you pass in an object with a static compareElements() method, this - // avoids getting warning messages about the parameter being unused - lock.enter(); - - int start = 0; - int end = numUsed; - - for (;;) - { - if (start >= end) - { - lock.exit(); - return -1; - } - else if (comparator.compareElements (elementToLookFor, data.elements [start]) == 0) - { - lock.exit(); - return start; - } - else - { - const int halfway = (start + end) >> 1; - - if (halfway == start) - { - lock.exit(); - return -1; - } - else if (comparator.compareElements (elementToLookFor, data.elements [halfway]) >= 0) - start = halfway; - else - end = halfway; - } - } - } - - /** Removes an element from the array. - - This will remove the element at a given index, and move back - all the subsequent elements to close the gap. - If the index passed in is out-of-range, nothing will happen. - - @param indexToRemove the index of the element to remove - @returns the element that has been removed - @see removeValue, removeRange - */ - ElementType remove (const int indexToRemove) throw() - { - lock.enter(); - - if (((unsigned int) indexToRemove) < (unsigned int) numUsed) - { - --numUsed; - - ElementType* const e = data.elements + indexToRemove; - ElementType const removed = *e; - const int numberToShift = numUsed - indexToRemove; - - if (numberToShift > 0) - memmove (e, e + 1, numberToShift * sizeof (ElementType)); - - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); - - lock.exit(); - return removed; - } - else - { - lock.exit(); - return ElementType(); - } - } - - /** Removes an item from the array. - - This will remove the first occurrence of the given element from the array. - If the item isn't found, no action is taken. - - @param valueToRemove the object to try to remove - @see remove, removeRange - */ - void removeValue (const ElementType valueToRemove) throw() - { - lock.enter(); - ElementType* e = data.elements; - - for (int i = numUsed; --i >= 0;) - { - if (valueToRemove == *e) - { - remove ((int) (e - data.elements)); - break; - } - - ++e; - } - - lock.exit(); - } - - /** Removes a range of elements from the array. - - This will remove a set of elements, starting from the given index, - and move subsequent elements down to close the gap. - - If the range extends beyond the bounds of the array, it will - be safely clipped to the size of the array. - - @param startIndex the index of the first element to remove - @param numberToRemove how many elements should be removed - @see remove, removeValue - */ - void removeRange (int startIndex, - const int numberToRemove) throw() - { - lock.enter(); - const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove); - startIndex = jlimit (0, numUsed, startIndex); - - if (endIndex > startIndex) - { - const int rangeSize = endIndex - startIndex; - ElementType* e = data.elements + startIndex; - int numToShift = numUsed - endIndex; - numUsed -= rangeSize; - - while (--numToShift >= 0) - { - *e = e [rangeSize]; - ++e; - } - - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); - } - - lock.exit(); - } - - /** Removes the last n elements from the array. - - @param howManyToRemove how many elements to remove from the end of the array - @see remove, removeValue, removeRange - */ - void removeLast (const int howManyToRemove = 1) throw() - { - lock.enter(); - numUsed = jmax (0, numUsed - howManyToRemove); - - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); - - lock.exit(); - } - - /** Removes any elements which are also in another array. - - @param otherArray the other array in which to look for elements to remove - @see removeValuesNotIn, remove, removeValue, removeRange - */ - template - void removeValuesIn (const OtherArrayType& otherArray) throw() - { - otherArray.lockArray(); - lock.enter(); - - if (this == &otherArray) - { - clear(); - } - else - { - if (otherArray.size() > 0) - { - for (int i = numUsed; --i >= 0;) - if (otherArray.contains (data.elements [i])) - remove (i); - } - } - - lock.exit(); - otherArray.unlockArray(); - } - - /** Removes any elements which are not found in another array. - - Only elements which occur in this other array will be retained. - - @param otherArray the array in which to look for elements NOT to remove - @see removeValuesIn, remove, removeValue, removeRange - */ - template - void removeValuesNotIn (const OtherArrayType& otherArray) throw() - { - otherArray.lockArray(); - lock.enter(); - - if (this != &otherArray) - { - if (otherArray.size() <= 0) - { - clear(); - } - else - { - for (int i = numUsed; --i >= 0;) - if (! otherArray.contains (data.elements [i])) - remove (i); - } - } - - lock.exit(); - otherArray.unlockArray(); - } - - /** Swaps over two elements in the array. - - This swaps over the elements found at the two indexes passed in. - If either index is out-of-range, this method will do nothing. - - @param index1 index of one of the elements to swap - @param index2 index of the other element to swap - */ - void swap (const int index1, - const int index2) throw() - { - lock.enter(); - - if (((unsigned int) index1) < (unsigned int) numUsed - && ((unsigned int) index2) < (unsigned int) numUsed) - { - swapVariables (data.elements [index1], - data.elements [index2]); - } - - lock.exit(); - } - - /** Moves one of the values to a different position. - - This will move the value to a specified index, shuffling along - any intervening elements as required. - - So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling - move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }. - - @param currentIndex the index of the value to be moved. If this isn't a - valid index, then nothing will be done - @param newIndex the index at which you'd like this value to end up. If this - is less than zero, the value will be moved to the end - of the array - */ - void move (const int currentIndex, - int newIndex) throw() - { - if (currentIndex != newIndex) - { - lock.enter(); - - if (((unsigned int) currentIndex) < (unsigned int) numUsed) - { - if (((unsigned int) newIndex) >= (unsigned int) numUsed) - newIndex = numUsed - 1; - - const ElementType value = data.elements [currentIndex]; - - if (newIndex > currentIndex) - { - memmove (data.elements + currentIndex, - data.elements + currentIndex + 1, - (newIndex - currentIndex) * sizeof (ElementType)); - } - else - { - memmove (data.elements + newIndex + 1, - data.elements + newIndex, - (currentIndex - newIndex) * sizeof (ElementType)); - } - - data.elements [newIndex] = value; - } - - lock.exit(); - } - } - - /** Reduces the amount of storage being used by the array. - - Arrays typically allocate slightly more storage than they need, and after - removing elements, they may have quite a lot of unused space allocated. - This method will reduce the amount of allocated storage to a minimum. - */ - void minimiseStorageOverheads() throw() - { - lock.enter(); - - if (numUsed == 0) - { - data.setAllocatedSize (0); - } - else - { - const int newAllocation = data.granularity * (numUsed / data.granularity + 1); - - if (newAllocation < data.numAllocated) - data.setAllocatedSize (newAllocation); - } - - lock.exit(); - } - - /** Increases the array's internal storage to hold a minimum number of elements. - - Calling this before adding a large known number of elements means that - the array won't have to keep dynamically resizing itself as the elements - are added, and it'll therefore be more efficient. - */ - void ensureStorageAllocated (const int minNumElements) throw() - { - data.ensureAllocatedSize (minNumElements); - } - - /** Sorts the elements in the array. - - This will use a comparator object to sort the elements into order. The object - passed must have a method of the form: - @code - int compareElements (ElementType first, ElementType second); - @endcode - - ..and this method must return: - - a value of < 0 if the first comes before the second - - a value of 0 if the two objects are equivalent - - a value of > 0 if the second comes before the first - - To improve performance, the compareElements() method can be declared as static or const. - - @param comparator the comparator to use for comparing elements. - @param retainOrderOfEquivalentItems if this is true, then items - which the comparator says are equivalent will be - kept in the order in which they currently appear - in the array. This is slower to perform, but may - be important in some cases. If it's false, a faster - algorithm is used, but equivalent elements may be - rearranged. - - @see addSorted, indexOfSorted, sortArray - */ - template - void sort (ElementComparator& comparator, - const bool retainOrderOfEquivalentItems = false) const throw() - { - (void) comparator; // if you pass in an object with a static compareElements() method, this - // avoids getting warning messages about the parameter being unused - lock.enter(); - sortArray (comparator, data.elements, 0, size() - 1, retainOrderOfEquivalentItems); - lock.exit(); - } - - /** Locks the array's CriticalSection. - - Of course if the type of section used is a DummyCriticalSection, this won't - have any effect. - - @see unlockArray - */ - void lockArray() const throw() - { - lock.enter(); - } - - /** Unlocks the array's CriticalSection. - - Of course if the type of section used is a DummyCriticalSection, this won't - have any effect. - - @see lockArray - */ - void unlockArray() const throw() - { - lock.exit(); - } - - juce_UseDebuggingNewOperator + Array() throw() + : numUsed (0) + { + } + + Array (const Array& other) throw() + { + other.lockArray(); + numUsed = other.numUsed; + data.setAllocatedSize (other.numUsed); + memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); + other.unlockArray(); + } + + Array (const ElementType* values) throw() + : numUsed (0) + { + while (*values != 0) + add (*values++); + } + + Array (const ElementType* values, int numValues) throw() + : numUsed (numValues) + { + data.setAllocatedSize (numValues); + memcpy (data.elements, values, numValues * sizeof (ElementType)); + } + + ~Array() throw() + { + } + + const Array & operator= (const Array & other) throw() + { + if (this != &other) + { + other.lockArray(); + lock.enter(); + + data.ensureAllocatedSize (other.size()); + numUsed = other.numUsed; + memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); + minimiseStorageOverheads(); + + lock.exit(); + other.unlockArray(); + } + + return *this; + } + + template + bool operator== (const OtherArrayType& other) const throw() + { + lock.enter(); + + if (numUsed != other.numUsed) + { + lock.exit(); + return false; + } + + for (int i = numUsed; --i >= 0;) + { + if (data.elements [i] != other.data.elements [i]) + { + lock.exit(); + return false; + } + } + + lock.exit(); + return true; + } + + template + bool operator!= (const OtherArrayType& other) const throw() + { + return ! operator== (other); + } + + void clear() throw() + { + lock.enter(); + data.setAllocatedSize (0); + numUsed = 0; + lock.exit(); + } + + void clearQuick() throw() + { + lock.enter(); + numUsed = 0; + lock.exit(); + } + + inline int size() const throw() + { + return numUsed; + } + + inline ElementType operator[] (const int index) const throw() + { + lock.enter(); + const ElementType result = (((unsigned int) index) < (unsigned int) numUsed) + ? data.elements [index] + : ElementType(); + lock.exit(); + + return result; + } + + inline ElementType getUnchecked (const int index) const throw() + { + lock.enter(); + jassert (((unsigned int) index) < (unsigned int) numUsed); + const ElementType result = data.elements [index]; + lock.exit(); + + return result; + } + + inline ElementType& getReference (const int index) const throw() + { + lock.enter(); + jassert (((unsigned int) index) < (unsigned int) numUsed); + ElementType& result = data.elements [index]; + lock.exit(); + return result; + } + + inline ElementType getFirst() const throw() + { + lock.enter(); + const ElementType result = (numUsed > 0) ? data.elements [0] + : ElementType(); + lock.exit(); + + return result; + } + + inline ElementType getLast() const throw() + { + lock.enter(); + const ElementType result = (numUsed > 0) ? data.elements [numUsed - 1] + : ElementType(); + lock.exit(); + + return result; + } + + int indexOf (const ElementType elementToLookFor) const throw() + { + int result = -1; + + lock.enter(); + const ElementType* e = data.elements; + + for (int i = numUsed; --i >= 0;) + { + if (elementToLookFor == *e) + { + result = (int) (e - data.elements); + break; + } + + ++e; + } + + lock.exit(); + return result; + } + + bool contains (const ElementType elementToLookFor) const throw() + { + lock.enter(); + + const ElementType* e = data.elements; + int num = numUsed; + + while (num >= 4) + { + if (*e == elementToLookFor + || *++e == elementToLookFor + || *++e == elementToLookFor + || *++e == elementToLookFor) + { + lock.exit(); + return true; + } + + num -= 4; + ++e; + } + + while (num > 0) + { + if (elementToLookFor == *e) + { + lock.exit(); + return true; + } + + --num; + ++e; + } + + lock.exit(); + return false; + } + + void add (const ElementType newElement) throw() + { + lock.enter(); + data.ensureAllocatedSize (numUsed + 1); + data.elements [numUsed++] = newElement; + lock.exit(); + } + + void insert (int indexToInsertAt, const ElementType newElement) throw() + { + lock.enter(); + data.ensureAllocatedSize (numUsed + 1); + + if (((unsigned int) indexToInsertAt) < (unsigned int) numUsed) + { + ElementType* const insertPos = data.elements + indexToInsertAt; + const int numberToMove = numUsed - indexToInsertAt; + + if (numberToMove > 0) + memmove (insertPos + 1, insertPos, numberToMove * sizeof (ElementType)); + + *insertPos = newElement; + ++numUsed; + } + else + { + data.elements [numUsed++] = newElement; + } + + lock.exit(); + } + + void insertMultiple (int indexToInsertAt, const ElementType newElement, + int numberOfTimesToInsertIt) throw() + { + if (numberOfTimesToInsertIt > 0) + { + lock.enter(); + data.ensureAllocatedSize (numUsed + numberOfTimesToInsertIt); + + if (((unsigned int) indexToInsertAt) < (unsigned int) numUsed) + { + ElementType* insertPos = data.elements + indexToInsertAt; + const int numberToMove = numUsed - indexToInsertAt; + + memmove (insertPos + numberOfTimesToInsertIt, insertPos, numberToMove * sizeof (ElementType)); + numUsed += numberOfTimesToInsertIt; + + while (--numberOfTimesToInsertIt >= 0) + *insertPos++ = newElement; + } + else + { + while (--numberOfTimesToInsertIt >= 0) + data.elements [numUsed++] = newElement; + } + + lock.exit(); + } + } + + void insertArray (int indexToInsertAt, + const ElementType* newElements, + int numberOfElements) throw() + { + if (numberOfElements > 0) + { + lock.enter(); + data.ensureAllocatedSize (numUsed + numberOfElements); + + if (((unsigned int) indexToInsertAt) < (unsigned int) numUsed) + { + ElementType* insertPos = data.elements + indexToInsertAt; + const int numberToMove = numUsed - indexToInsertAt; + + memmove (insertPos + numberOfElements, insertPos, numberToMove * sizeof (ElementType)); + numUsed += numberOfElements; + + while (--numberOfElements >= 0) + *insertPos++ = *newElements++; + } + else + { + while (--numberOfElements >= 0) + data.elements [numUsed++] = *newElements++; + } + + lock.exit(); + } + } + + void addIfNotAlreadyThere (const ElementType newElement) throw() + { + lock.enter(); + + if (! contains (newElement)) + add (newElement); + + lock.exit(); + } + + void set (const int indexToChange, + const ElementType newValue) throw() + { + jassert (indexToChange >= 0); + + if (indexToChange >= 0) + { + lock.enter(); + + if (indexToChange < numUsed) + { + data.elements [indexToChange] = newValue; + } + else + { + data.ensureAllocatedSize (numUsed + 1); + data.elements [numUsed++] = newValue; + } + + lock.exit(); + } + } + + void setUnchecked (const int indexToChange, + const ElementType newValue) throw() + { + lock.enter(); + jassert (((unsigned int) indexToChange) < (unsigned int) numUsed); + data.elements [indexToChange] = newValue; + lock.exit(); + } + + void addArray (const ElementType* elementsToAdd, + int numElementsToAdd) throw() + { + lock.enter(); + + if (numElementsToAdd > 0) + { + data.ensureAllocatedSize (numUsed + numElementsToAdd); + + while (--numElementsToAdd >= 0) + data.elements [numUsed++] = *elementsToAdd++; + } + + lock.exit(); + } + + template + void swapWithArray (OtherArrayType& otherArray) throw() + { + lock.enter(); + otherArray.lock.enter(); + swapVariables (numUsed, otherArray.numUsed); + swapVariables (data.elements, otherArray.data.elements); + swapVariables (data.numAllocated, otherArray.data.numAllocated); + otherArray.lock.exit(); + lock.exit(); + } + + template + void addArray (const OtherArrayType& arrayToAddFrom, + int startIndex = 0, + int numElementsToAdd = -1) throw() + { + arrayToAddFrom.lockArray(); + lock.enter(); + + if (startIndex < 0) + { + jassertfalse + startIndex = 0; + } + + if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size()) + numElementsToAdd = arrayToAddFrom.size() - startIndex; + + while (--numElementsToAdd >= 0) + add (arrayToAddFrom.getUnchecked (startIndex++)); + + lock.exit(); + arrayToAddFrom.unlockArray(); + } + + template + void addSorted (ElementComparator& comparator, + const ElementType newElement) throw() + { + lock.enter(); + insert (findInsertIndexInSortedArray (comparator, data.elements, newElement, 0, numUsed), newElement); + lock.exit(); + } + + template + int indexOfSorted (ElementComparator& comparator, + const ElementType elementToLookFor) const throw() + { + (void) comparator; // if you pass in an object with a static compareElements() method, this + // avoids getting warning messages about the parameter being unused + lock.enter(); + + int start = 0; + int end = numUsed; + + for (;;) + { + if (start >= end) + { + lock.exit(); + return -1; + } + else if (comparator.compareElements (elementToLookFor, data.elements [start]) == 0) + { + lock.exit(); + return start; + } + else + { + const int halfway = (start + end) >> 1; + + if (halfway == start) + { + lock.exit(); + return -1; + } + else if (comparator.compareElements (elementToLookFor, data.elements [halfway]) >= 0) + start = halfway; + else + end = halfway; + } + } + } + + ElementType remove (const int indexToRemove) throw() + { + lock.enter(); + + if (((unsigned int) indexToRemove) < (unsigned int) numUsed) + { + --numUsed; + + ElementType* const e = data.elements + indexToRemove; + ElementType const removed = *e; + const int numberToShift = numUsed - indexToRemove; + + if (numberToShift > 0) + memmove (e, e + 1, numberToShift * sizeof (ElementType)); + + if ((numUsed << 1) < data.numAllocated) + minimiseStorageOverheads(); + + lock.exit(); + return removed; + } + else + { + lock.exit(); + return ElementType(); + } + } + + void removeValue (const ElementType valueToRemove) throw() + { + lock.enter(); + ElementType* e = data.elements; + + for (int i = numUsed; --i >= 0;) + { + if (valueToRemove == *e) + { + remove ((int) (e - data.elements)); + break; + } + + ++e; + } + + lock.exit(); + } + + void removeRange (int startIndex, + const int numberToRemove) throw() + { + lock.enter(); + const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove); + startIndex = jlimit (0, numUsed, startIndex); + + if (endIndex > startIndex) + { + const int rangeSize = endIndex - startIndex; + ElementType* e = data.elements + startIndex; + int numToShift = numUsed - endIndex; + numUsed -= rangeSize; + + while (--numToShift >= 0) + { + *e = e [rangeSize]; + ++e; + } + + if ((numUsed << 1) < data.numAllocated) + minimiseStorageOverheads(); + } + + lock.exit(); + } + + void removeLast (const int howManyToRemove = 1) throw() + { + lock.enter(); + numUsed = jmax (0, numUsed - howManyToRemove); + + if ((numUsed << 1) < data.numAllocated) + minimiseStorageOverheads(); + + lock.exit(); + } + + template + void removeValuesIn (const OtherArrayType& otherArray) throw() + { + otherArray.lockArray(); + lock.enter(); + + if (this == &otherArray) + { + clear(); + } + else + { + if (otherArray.size() > 0) + { + for (int i = numUsed; --i >= 0;) + if (otherArray.contains (data.elements [i])) + remove (i); + } + } + + lock.exit(); + otherArray.unlockArray(); + } + + template + void removeValuesNotIn (const OtherArrayType& otherArray) throw() + { + otherArray.lockArray(); + lock.enter(); + + if (this != &otherArray) + { + if (otherArray.size() <= 0) + { + clear(); + } + else + { + for (int i = numUsed; --i >= 0;) + if (! otherArray.contains (data.elements [i])) + remove (i); + } + } + + lock.exit(); + otherArray.unlockArray(); + } + + void swap (const int index1, + const int index2) throw() + { + lock.enter(); + + if (((unsigned int) index1) < (unsigned int) numUsed + && ((unsigned int) index2) < (unsigned int) numUsed) + { + swapVariables (data.elements [index1], + data.elements [index2]); + } + + lock.exit(); + } + + void move (const int currentIndex, + int newIndex) throw() + { + if (currentIndex != newIndex) + { + lock.enter(); + + if (((unsigned int) currentIndex) < (unsigned int) numUsed) + { + if (((unsigned int) newIndex) >= (unsigned int) numUsed) + newIndex = numUsed - 1; + + const ElementType value = data.elements [currentIndex]; + + if (newIndex > currentIndex) + { + memmove (data.elements + currentIndex, + data.elements + currentIndex + 1, + (newIndex - currentIndex) * sizeof (ElementType)); + } + else + { + memmove (data.elements + newIndex + 1, + data.elements + newIndex, + (currentIndex - newIndex) * sizeof (ElementType)); + } + + data.elements [newIndex] = value; + } + + lock.exit(); + } + } + + void minimiseStorageOverheads() throw() + { + lock.enter(); + data.shrinkToNoMoreThan (numUsed); + lock.exit(); + } + + void ensureStorageAllocated (const int minNumElements) throw() + { + lock.enter(); + data.ensureAllocatedSize (minNumElements); + lock.exit(); + } + + template + void sort (ElementComparator& comparator, + const bool retainOrderOfEquivalentItems = false) const throw() + { + (void) comparator; // if you pass in an object with a static compareElements() method, this + // avoids getting warning messages about the parameter being unused + lock.enter(); + sortArray (comparator, data.elements, 0, size() - 1, retainOrderOfEquivalentItems); + lock.exit(); + } + + void lockArray() const throw() + { + lock.enter(); + } + + void unlockArray() const throw() + { + lock.exit(); + } + + juce_UseDebuggingNewOperator private: - ArrayAllocationBase data; - int numUsed; - TypeOfCriticalSectionToUse lock; + ArrayAllocationBase data; + int numUsed; + TypeOfCriticalSectionToUse lock; }; #endif // __JUCE_ARRAY_JUCEHEADER__ @@ -4255,210 +2472,93 @@ private: #ifndef __JUCE_HEAPBLOCK_JUCEHEADER__ #define __JUCE_HEAPBLOCK_JUCEHEADER__ -/** - Very simple container class to hold a pointer to some data on the heap. - - When you need to allocate some heap storage for something, always try to use - this class instead of allocating the memory directly using malloc/free. - - A HeapBlock object can be treated in pretty much exactly the same way - as an char*, but as long as you allocate it on the stack or as a class member, - it's almost impossible for it to leak memory. - - It also makes your code much more concise and readable than doing the same thing - using direct allocations, - - E.g. instead of this: - @code - int* temp = (int*) juce_malloc (1024 * sizeof (int)); - memcpy (temp, xyz, 1024 * sizeof (int)); - juce_free (temp); - temp = (int*) juce_calloc (2048 * sizeof (int)); - temp[0] = 1234; - memcpy (foobar, temp, 2048 * sizeof (int)); - juce_free (temp); - @endcode - - ..you could just write this: - @code - HeapBlock temp (1024); - memcpy (temp, xyz, 1024 * sizeof (int)); - temp.calloc (2048); - temp[0] = 1234; - memcpy (foobar, temp, 2048 * sizeof (int)); - @endcode - - The class is extremely lightweight, containing only a pointer to the - data, and exposes malloc/realloc/calloc/free methods that do the same jobs - as their less object-oriented counterparts. Despite adding safety, you probably - won't sacrifice any performance by using this in place of normal pointers. - - @see Array, OwnedArray, MemoryBlock -*/ template class HeapBlock { public: - /** Creates a HeapBlock which is initially just a null pointer. + HeapBlock() : data (0) + { + } - After creation, you can resize the array using the malloc(), calloc(), - or realloc() methods. - */ - HeapBlock() : data (0) - { - } + HeapBlock (const size_t numElements) + : data ((ElementType*) ::juce_malloc (numElements * sizeof (ElementType))) + { + } - /** Creates a HeapBlock containing a number of elements. + ~HeapBlock() + { + ::juce_free (data); + } - The contents of the block are undefined, as it will have been created by a - malloc call. + inline operator ElementType*() const { return data; } - If you want an array of zero values, you can use the calloc() method instead. - */ - HeapBlock (const int numElements) - : data ((ElementType*) ::juce_malloc (numElements * sizeof (ElementType))) - { - } + inline operator void*() const { return (void*) data; } - /** Destructor. + inline ElementType* operator->() const { return data; } - This will free the data, if any has been allocated. - */ - ~HeapBlock() - { - ::juce_free (data); - } + template + inline operator CastType*() const { return (CastType*) data; } - /** Returns a raw pointer to the allocated data. - This may be a null pointer if the data hasn't yet been allocated, or if it has been - freed by calling the free() method. - */ - inline operator ElementType*() const { return data; } + template + inline ElementType& operator[] (IndexType index) const { return data [index]; } - /** Returns a void pointer to the allocated data. - This may be a null pointer if the data hasn't yet been allocated, or if it has been - freed by calling the free() method. - */ - inline operator void*() const { return (void*) data; } + template + inline ElementType* operator+ (IndexType index) const { return data + index; } - /** Lets you use indirect calls to the first element in the array. - Obviously this will cause problems if the array hasn't been initialised, because it'll - be referencing a null pointer. - */ - inline ElementType* operator->() const { return data; } + inline ElementType** operator&() const { return (ElementType**) &data; } - /** Returns a pointer to the data by casting it to any type you need. - */ - template - inline operator CastType*() const { return (CastType*) data; } + inline bool operator== (const ElementType* const otherPointer) const { return otherPointer == data; } - /** Returns a reference to one of the data elements. - Obviously there's no bounds-checking here, as this object is just a dumb pointer and - has no idea of the size it currently has allocated. - */ - template - inline ElementType& operator[] (IndexType index) const { return data [index]; } + inline bool operator!= (const ElementType* const otherPointer) const { return otherPointer != data; } - /** Returns a pointer to a data element at an offset from the start of the array. - This is the same as doing pointer arithmetic on the raw pointer itself. - */ - template - inline ElementType* operator+ (IndexType index) const { return data + index; } + void malloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) + { + ::juce_free (data); + data = (ElementType*) ::juce_malloc (newNumElements * elementSize); + } - /** Returns a reference to the raw data pointer. - Beware that the pointer returned here will become invalid as soon as you call - any of the allocator methods on this object! - */ - inline ElementType** operator&() const { return (ElementType**) &data; } + void calloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) + { + ::juce_free (data); + data = (ElementType*) ::juce_calloc (newNumElements * elementSize); + } - /** Compares the pointer with another pointer. - This can be handy for checking whether this is a null pointer. - */ - inline bool operator== (const ElementType* const otherPointer) const { return otherPointer == data; } + void allocate (const size_t newNumElements, const bool initialiseToZero) + { + ::juce_free (data); - /** Compares the pointer with another pointer. - This can be handy for checking whether this is a null pointer. - */ - inline bool operator!= (const ElementType* const otherPointer) const { return otherPointer != data; } + if (initialiseToZero) + data = (ElementType*) ::juce_calloc (newNumElements * sizeof (ElementType)); + else + data = (ElementType*) ::juce_malloc (newNumElements * sizeof (ElementType)); + } - /** Allocates a specified amount of memory. + void realloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) + { + if (data == 0) + data = (ElementType*) ::juce_malloc (newNumElements * elementSize); + else + data = (ElementType*) ::juce_realloc (data, newNumElements * elementSize); + } - This uses the normal malloc to allocate an amount of memory for this object. - Any previously allocated memory will be freed by this method. + void free() + { + ::juce_free (data); + data = 0; + } - The number of bytes allocated will be (newNumElements * elementSize). Normally - you wouldn't need to specify the second parameter, but it can be handy if you need - to allocate a size in bytes rather than in terms of the number of elements. - - The data that is allocated will be freed when this object is deleted, or when you - call free() or any of the allocation methods. - */ - void malloc (const int newNumElements, const unsigned int elementSize = sizeof (ElementType)) - { - ::juce_free (data); - data = (ElementType*) ::juce_malloc (newNumElements * elementSize); - } - - /** Allocates a specified amount of memory and clears it. - This does the same job as the malloc() method, but clears the memory that it allocates. - */ - void calloc (const int newNumElements, const unsigned int elementSize = sizeof (ElementType)) - { - ::juce_free (data); - data = (ElementType*) ::juce_calloc (newNumElements * elementSize); - } - - /** Allocates a specified amount of memory and optionally clears it. - This does the same job as either malloc() or calloc(), depending on the - initialiseToZero parameter. - */ - void allocate (const int newNumElements, const bool initialiseToZero) - { - ::juce_free (data); - - if (initialiseToZero) - data = (ElementType*) ::juce_calloc (newNumElements * sizeof (ElementType)); - else - data = (ElementType*) ::juce_malloc (newNumElements * sizeof (ElementType)); - } - - /** Re-allocates a specified amount of memory. - - The semantics of this method are the same as malloc() and calloc(), but it - uses realloc() to keep as much of the existing data as possible. - */ - void realloc (const int newNumElements, const unsigned int elementSize = sizeof (ElementType)) - { - if (data == 0) - data = (ElementType*) ::juce_malloc (newNumElements * elementSize); - else - data = (ElementType*) ::juce_realloc (data, newNumElements * elementSize); - } - - /** Frees any currently-allocated data. - This will free the data and reset this object to be a null pointer. - */ - void free() - { - ::juce_free (data); - data = 0; - } - - /** Swaps this object's data with the data of another HeapBlock. - The two objects simply exchange their data pointers. - */ - void swapWith (HeapBlock & other) - { - swapVariables (data, other.data); - } + void swapWith (HeapBlock & other) + { + swapVariables (data, other.data); + } private: - ElementType* data; + ElementType* data; - HeapBlock (const HeapBlock&); - const HeapBlock& operator= (const HeapBlock&); + HeapBlock (const HeapBlock&); + const HeapBlock& operator= (const HeapBlock&); }; #endif // __JUCE_HEAPBLOCK_JUCEHEADER__ @@ -4466,302 +2566,113 @@ private: class MemoryBlock; -/** - An array of on/off bits, also usable to store large binary integers. - - A BitArray acts like an arbitrarily large integer whose bits can be set or - cleared, and some basic mathematical operations can be done on the number as - a whole. -*/ class JUCE_API BitArray { public: - /** Creates an empty BitArray */ - BitArray() throw(); + BitArray() throw(); - /** Creates a BitArray containing an integer value in its low bits. + BitArray (const unsigned int value) throw(); - The low 32 bits of the array are initialised with this value. - */ - BitArray (const unsigned int value) throw(); + BitArray (const int value) throw(); - /** Creates a BitArray containing an integer value in its low bits. + BitArray (int64 value) throw(); - The low 32 bits of the array are initialised with the absolute value - passed in, and its sign is set to reflect the sign of the number. - */ - BitArray (const int value) throw(); + BitArray (const BitArray& other) throw(); - /** Creates a BitArray containing an integer value in its low bits. + ~BitArray() throw(); - The low 64 bits of the array are initialised with the absolute value - passed in, and its sign is set to reflect the sign of the number. - */ - BitArray (int64 value) throw(); + const BitArray& operator= (const BitArray& other) throw(); - /** Creates a copy of another BitArray. */ - BitArray (const BitArray& other) throw(); + bool operator== (const BitArray& other) const throw(); + bool operator!= (const BitArray& other) const throw(); - /** Destructor. */ - ~BitArray() throw(); + void clear() throw(); - /** Copies another BitArray onto this one. */ - const BitArray& operator= (const BitArray& other) throw(); + void clearBit (const int bitNumber) throw(); - /** Two arrays are the same if the same bits are set. */ - bool operator== (const BitArray& other) const throw(); - /** Two arrays are the same if the same bits are set. */ - bool operator!= (const BitArray& other) const throw(); + void setBit (const int bitNumber) throw(); - /** Clears all bits in the BitArray to 0. */ - void clear() throw(); + void setBit (const int bitNumber, + const bool shouldBeSet) throw(); - /** Clears a particular bit in the array. */ - void clearBit (const int bitNumber) throw(); + void setRange (int startBit, + int numBits, + const bool shouldBeSet) throw(); - /** Sets a specified bit to 1. + void insertBit (const int bitNumber, + const bool shouldBeSet) throw(); - If the bit number is high, this will grow the array to accomodate it. - */ - void setBit (const int bitNumber) throw(); + bool operator[] (const int bit) const throw(); - /** Sets or clears a specified bit. */ - void setBit (const int bitNumber, - const bool shouldBeSet) throw(); + bool isEmpty() const throw(); - /** Sets a range of bits to be either on or off. + const BitArray getBitRange (int startBit, int numBits) const throw(); - @param startBit the first bit to change - @param numBits the number of bits to change - @param shouldBeSet whether to turn these bits on or off - */ - void setRange (int startBit, - int numBits, - const bool shouldBeSet) throw(); + int getBitRangeAsInt (int startBit, int numBits) const throw(); - /** Inserts a bit an a given position, shifting up any bits above it. */ - void insertBit (const int bitNumber, - const bool shouldBeSet) throw(); + void setBitRangeAsInt (int startBit, int numBits, + unsigned int valueToSet) throw(); - /** Returns the value of a specified bit in the array. + void orWith (const BitArray& other) throw(); - If the index is out-of-range, the result will be false. - */ - bool operator[] (const int bit) const throw(); + void andWith (const BitArray& other) throw(); - /** Returns true if no bits are set. */ - bool isEmpty() const throw(); + void xorWith (const BitArray& other) throw(); - /** Returns a range of bits in the array as a new BitArray. + void add (const BitArray& other) throw(); - e.g. getBitRangeAsInt (0, 64) would return the lowest 64 bits. - @see getBitRangeAsInt - */ - const BitArray getBitRange (int startBit, int numBits) const throw(); + void subtract (const BitArray& other) throw(); - /** Returns a range of bits in the array as an integer value. + void multiplyBy (const BitArray& other) throw(); - e.g. getBitRangeAsInt (0, 32) would return the lowest 32 bits. + void divideBy (const BitArray& divisor, BitArray& remainder) throw(); - Asking for more than 32 bits isn't allowed (obviously) - for that, use - getBitRange(). - */ - int getBitRangeAsInt (int startBit, int numBits) const throw(); + const BitArray findGreatestCommonDivisor (BitArray other) const throw(); - /** Sets a range of bits in the array based on an integer value. + void modulo (const BitArray& divisor) throw(); - Copies the given integer into the array, starting at startBit, - and only using up to numBits of the available bits. - */ - void setBitRangeAsInt (int startBit, int numBits, - unsigned int valueToSet) throw(); + void exponentModulo (const BitArray& exponent, const BitArray& modulus) throw(); - /** Performs a bitwise OR with another BitArray. + void inverseModulo (const BitArray& modulus) throw(); - The result ends up in this array. - */ - void orWith (const BitArray& other) throw(); + void shiftBits (int howManyBitsLeft, + int startBit = 0) throw(); - /** Performs a bitwise AND with another BitArray. + int compare (const BitArray& other) const throw(); - The result ends up in this array. - */ - void andWith (const BitArray& other) throw(); + int compareAbsolute (const BitArray& other) const throw(); - /** Performs a bitwise XOR with another BitArray. + bool isNegative() const throw(); - The result ends up in this array. - */ - void xorWith (const BitArray& other) throw(); + void setNegative (const bool shouldBeNegative) throw(); - /** Adds another BitArray's value to this one. + void negate() throw(); - Treating the two arrays as large positive integers, this - adds them up and puts the result in this array. - */ - void add (const BitArray& other) throw(); + int countNumberOfSetBits() const throw(); - /** Subtracts another BitArray's value from this one. + int findNextSetBit (int startIndex = 0) const throw(); - Treating the two arrays as large positive integers, this - subtracts them and puts the result in this array. + int findNextClearBit (int startIndex = 0) const throw(); - Note that if the result should be negative, this won't be - handled correctly. - */ - void subtract (const BitArray& other) throw(); + int getHighestBit() const throw(); - /** Multiplies another BitArray's value with this one. + const String toString (const int base, const int minimumNumCharacters = 1) const throw(); - Treating the two arrays as large positive integers, this - multiplies them and puts the result in this array. - */ - void multiplyBy (const BitArray& other) throw(); + void parseString (const String& text, + const int base) throw(); - /** Divides another BitArray's value into this one and also produces a remainder. + const MemoryBlock toMemoryBlock() const throw(); - Treating the two arrays as large positive integers, this - divides this value by the other, leaving the quotient in this - array, and the remainder is copied into the other BitArray passed in. - */ - void divideBy (const BitArray& divisor, BitArray& remainder) throw(); + void loadFromMemoryBlock (const MemoryBlock& data) throw(); - /** Returns the largest value that will divide both this value and the one - passed-in. - */ - const BitArray findGreatestCommonDivisor (BitArray other) const throw(); - - /** Performs a modulo operation on this value. - - The result is stored in this value. - */ - void modulo (const BitArray& divisor) throw(); - - /** Performs a combined exponent and modulo operation. - - This BitArray's value becomes (this ^ exponent) % modulus. - */ - void exponentModulo (const BitArray& exponent, const BitArray& modulus) throw(); - - /** Performs an inverse modulo on the value. - - i.e. the result is (this ^ -1) mod (modulus). - */ - void inverseModulo (const BitArray& modulus) throw(); - - /** Shifts a section of bits left or right. - - @param howManyBitsLeft how far to move the bits (+ve numbers shift it left, -ve numbers shift it right). - @param startBit the first bit to affect - if this is > 0, only bits above that index will be affected. - */ - void shiftBits (int howManyBitsLeft, - int startBit = 0) throw(); - - /** Does a signed comparison of two BitArrays. - - Return values are: - - 0 if the numbers are the same - - < 0 if this number is smaller than the other - - > 0 if this number is bigger than the other - */ - int compare (const BitArray& other) const throw(); - - /** Compares the magnitudes of two BitArrays, ignoring their signs. - - Return values are: - - 0 if the numbers are the same - - < 0 if this number is smaller than the other - - > 0 if this number is bigger than the other - */ - int compareAbsolute (const BitArray& other) const throw(); - - /** Returns true if the value is less than zero. - - @see setNegative, negate - */ - bool isNegative() const throw(); - - /** Changes the sign of the number to be positive or negative. - - @see isNegative, negate - */ - void setNegative (const bool shouldBeNegative) throw(); - - /** Inverts the sign of the number. - - @see isNegative, setNegative - */ - void negate() throw(); - - /** Counts the total number of set bits in the array. */ - int countNumberOfSetBits() const throw(); - - /** Looks for the index of the next set bit after a given starting point. - - searches from startIndex (inclusive) upwards for the first set bit, - and returns its index. - - If no set bits are found, it returns -1. - */ - int findNextSetBit (int startIndex = 0) const throw(); - - /** Looks for the index of the next clear bit after a given starting point. - - searches from startIndex (inclusive) upwards for the first clear bit, - and returns its index. - */ - int findNextClearBit (int startIndex = 0) const throw(); - - /** Returns the index of the highest set bit in the array. - - If the array is empty, this will return -1. - */ - int getHighestBit() const throw(); - - /** Converts the array to a number string. - - Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex). - - If minuimumNumCharacters is greater than 0, the returned string will be - padded with leading zeros to reach at least that length. - */ - const String toString (const int base, const int minimumNumCharacters = 1) const throw(); - - /** Converts a number string to an array. - - Any non-valid characters will be ignored. - - Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex). - */ - void parseString (const String& text, - const int base) throw(); - - /** Turns the array into a block of binary data. - - The data is arranged as little-endian, so the first byte of data is the low 8 bits - of the array, and so on. - - @see loadFromMemoryBlock - */ - const MemoryBlock toMemoryBlock() const throw(); - - /** Copies a block of raw data onto this array. - - The data is arranged as little-endian, so the first byte of data is the low 8 bits - of the array, and so on. - - @see toMemoryBlock - */ - void loadFromMemoryBlock (const MemoryBlock& data) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - void ensureSize (const int numVals) throw(); - HeapBlock values; - int numValues, highestBit; - bool negative; + void ensureSize (const int numVals) throw(); + HeapBlock values; + int numValues, highestBit; + bool negative; }; #endif // __JUCE_BITARRAY_JUCEHEADER__ @@ -4780,198 +2691,82 @@ private: #ifndef __JUCE_MEMORYBLOCK_JUCEHEADER__ #define __JUCE_MEMORYBLOCK_JUCEHEADER__ -/** - A class to hold a resizable block of raw data. - -*/ class JUCE_API MemoryBlock { public: - /** Create an uninitialised block with 0 size. */ - MemoryBlock() throw(); + MemoryBlock() throw(); - /** Creates a memory block with a given initial size. + MemoryBlock (const size_t initialSize, + const bool initialiseToZero = false) throw(); - @param initialSize the size of block to create - @param initialiseToZero whether to clear the memory or just leave it uninitialised - */ - MemoryBlock (const int initialSize, - const bool initialiseToZero = false) throw(); + MemoryBlock (const MemoryBlock& other) throw(); - /** Creates a copy of another memory block. */ - MemoryBlock (const MemoryBlock& other) throw(); + MemoryBlock (const void* const dataToInitialiseFrom, + const size_t sizeInBytes) throw(); - /** Creates a memory block using a copy of a block of data. + ~MemoryBlock() throw(); - @param dataToInitialiseFrom some data to copy into this block - @param sizeInBytes how much space to use - */ - MemoryBlock (const void* const dataToInitialiseFrom, - const int sizeInBytes) throw(); + const MemoryBlock& operator= (const MemoryBlock& other) throw(); - /** Destructor. */ - ~MemoryBlock() throw(); + bool operator== (const MemoryBlock& other) const throw(); - /** Copies another memory block onto this one. + bool operator!= (const MemoryBlock& other) const throw(); - This block will be resized and copied to exactly match the other one. - */ - const MemoryBlock& operator= (const MemoryBlock& other) throw(); + template + operator DataType*() const throw() { return (DataType*) data; } - /** Compares two memory blocks. + void* getData() const throw() { return data; } - @returns true only if the two blocks are the same size and have identical contents. - */ - bool operator== (const MemoryBlock& other) const throw(); + template + char& operator[] (const Type offset) const throw() { return data [offset]; } - /** Compares two memory blocks. + size_t getSize() const throw() { return size; } - @returns true if the two blocks are different sizes or have different contents. - */ - bool operator!= (const MemoryBlock& other) const throw(); + void setSize (const size_t newSize, + const bool initialiseNewSpaceToZero = false) throw(); - /** Returns a pointer to the data, casting it to any type of primitive data required. + void ensureSize (const size_t minimumSize, + const bool initialiseNewSpaceToZero = false) throw(); - Note that the pointer returned will probably become invalid when the - block is resized. - */ - template - operator DataType*() const throw() { return (DataType*) data; } + void fillWith (const uint8 valueToUse) throw(); - /** Returns a void pointer to the data. + void append (const void* const data, + const size_t numBytes) throw(); - Note that the pointer returned will probably become invalid when the - block is resized. - */ - void* getData() const throw() { return data; } + void swapWith (MemoryBlock& other) throw(); - /** Returns a byte from the memory block. + void copyFrom (const void* srcData, + int destinationOffset, + size_t numBytes) throw(); - This returns a reference, so you can also use it to set a byte. - */ - char& operator[] (const int offset) const throw() { return data [offset]; } + void copyTo (void* destData, + int sourceOffset, + size_t numBytes) const throw(); - /** Returns the block's current allocated size, in bytes. */ - int getSize() const throw() { return size; } + void removeSection (size_t startByte, size_t numBytesToRemove) throw(); - /** Resizes the memory block. + const String toString() const throw(); - This will try to keep as much of the block's current content as it can, - and can optionally be made to clear any new space that gets allocated at - the end of the block. + void loadFromHexString (const String& sourceHexString) throw(); - @param newSize the new desired size for the block - @param initialiseNewSpaceToZero if the block gets enlarged, this determines - whether to clear the new section or just leave it - uninitialised - @see ensureSize - */ - void setSize (const int newSize, - const bool initialiseNewSpaceToZero = false) throw(); + void setBitRange (size_t bitRangeStart, + size_t numBits, + int binaryNumberToApply) throw(); - /** Increases the block's size only if it's smaller than a given size. + int getBitRange (size_t bitRangeStart, + size_t numBitsToRead) const throw(); - @param minimumSize if the block is already bigger than this size, no action - will be taken; otherwise it will be increased to this size - @param initialiseNewSpaceToZero if the block gets enlarged, this determines - whether to clear the new section or just leave it - uninitialised - @see setSize - */ - void ensureSize (const int minimumSize, - const bool initialiseNewSpaceToZero = false) throw(); + const String toBase64Encoding() const throw(); - /** Fills the entire memory block with a repeated byte value. + bool fromBase64Encoding (const String& encodedString) throw(); - This is handy for clearing a block of memory to zero. - */ - void fillWith (const uint8 valueToUse) throw(); - - /** Adds another block of data to the end of this one. - - This block's size will be increased accordingly. - */ - void append (const void* const data, - const int numBytes) throw(); - - /** Copies data into this MemoryBlock from a memory address. - - @param srcData the memory location of the data to copy into this block - @param destinationOffset the offset in this block at which the data being copied should begin - @param numBytes how much to copy in (if this goes beyond the size of the memory block, - it will be clipped so not to do anything nasty) - */ - void copyFrom (const void* srcData, - int destinationOffset, - int numBytes) throw(); - - /** Copies data from this MemoryBlock to a memory address. - - @param destData the memory location to write to - @param sourceOffset the offset within this block from which the copied data will be read - @param numBytes how much to copy (if this extends beyond the limits of the memory block, - zeros will be used for that portion of the data) - */ - void copyTo (void* destData, - int sourceOffset, - int numBytes) const throw(); - - /** Chops out a section of the block. - - This will remove a section of the memory block and close the gap around it, - shifting any subsequent data downwards and reducing the size of the block. - - If the range specified goes beyond the size of the block, it will be clipped. - */ - void removeSection (int startByte, int numBytesToRemove) throw(); - - /** Attempts to parse the contents of the block as a zero-terminated string of 8-bit - characters in the system's default encoding. */ - const String toString() const throw(); - - /** Parses a string of hexadecimal numbers and writes this data into the memory block. - - The block will be resized to the number of valid bytes read from the string. - Non-hex characters in the string will be ignored. - - @see String::toHexString() - */ - void loadFromHexString (const String& sourceHexString) throw(); - - /** Sets a number of bits in the memory block, treating it as a long binary sequence. */ - void setBitRange (int bitRangeStart, - int numBits, - int binaryNumberToApply) throw(); - - /** Reads a number of bits from the memory block, treating it as one long binary sequence */ - int getBitRange (int bitRangeStart, - int numBitsToRead) const throw(); - - /** Returns a string of characters that represent the binary contents of this block. - - Uses a 64-bit encoding system to allow binary data to be turned into a string - of simple non-extended characters, e.g. for storage in XML. - - @see fromBase64Encoding - */ - const String toBase64Encoding() const throw(); - - /** Takes a string of encoded characters and turns it into binary data. - - The string passed in must have been created by to64BitEncoding(), and this - block will be resized to recreate the original data block. - - @see toBase64Encoding - */ - bool fromBase64Encoding (const String& encodedString) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - HeapBlock data; - int size; + HeapBlock data; + size_t size; }; #endif // __JUCE_MEMORYBLOCK_JUCEHEADER__ @@ -4988,890 +2783,568 @@ private: #ifndef __JUCE_SCOPEDPOINTER_JUCEHEADER__ #define __JUCE_SCOPEDPOINTER_JUCEHEADER__ -/** - This class holds a pointer which is automatically deleted when this object goes - out of scope. - - Once a pointer has been passed to a ScopedPointer, it will make sure that the pointer - gets deleted when the ScopedPointer is deleted. Using the ScopedPointer on the stack or - as member variables is a good way to use RAII to avoid accidentally leaking dynamically - created objects. - - A ScopedPointer can be used in pretty much the same way that you'd use a normal pointer - to an object. If you use the assignment operator to assign a different object to a - ScopedPointer, the old one will be automatically deleted. - - If you need to get a pointer out of a ScopedPointer without it being deleted, you - can use the release() method. -*/ template class JUCE_API ScopedPointer { public: - /** Creates a ScopedPointer containing a null pointer. */ - inline ScopedPointer() : object (0) - { - } + inline ScopedPointer() : object (0) + { + } - /** Creates a ScopedPointer that owns the specified object. */ - inline ScopedPointer (ObjectType* const objectToTakePossessionOf) - : object (objectToTakePossessionOf) - { - } + inline ScopedPointer (ObjectType* const objectToTakePossessionOf) + : object (objectToTakePossessionOf) + { + } - /** Creates a ScopedPointer that takes its pointer from another ScopedPointer. + ScopedPointer (ScopedPointer& objectToTransferFrom) + : object (objectToTransferFrom.object) + { + objectToTransferFrom.object = 0; + } - Because a pointer can only belong to one ScopedPointer, this transfers - the pointer from the other object to this one, and the other object is reset to - be a null pointer. - */ - ScopedPointer (ScopedPointer& objectToTransferFrom) - : object (objectToTransferFrom.object) - { - objectToTransferFrom.object = 0; - } + inline ~ScopedPointer() { delete object; } - /** Destructor. - This will delete the object that this ScopedPointer currently refers to. - */ - inline ~ScopedPointer() { delete object; } + const ScopedPointer& operator= (ScopedPointer& objectToTransferFrom) + { + if (this != objectToTransferFrom.getAddress()) + { + // Two ScopedPointers should never be able to refer to the same object - if + // this happens, you must have done something dodgy! + jassert (object != objectToTransferFrom.object); - /** Changes this ScopedPointer to point to a new object. + ObjectType* const oldObject = object; + object = objectToTransferFrom.object; + objectToTransferFrom.object = 0; + delete oldObject; + } - Because a pointer can only belong to one ScopedPointer, this transfers - the pointer from the other object to this one, and the other object is reset to - be a null pointer. + return *this; + } - If this ScopedPointer already points to an object, that object - will first be deleted. - */ - const ScopedPointer& operator= (ScopedPointer& objectToTransferFrom) - { - if (this != objectToTransferFrom.getAddress()) - { - // Two ScopedPointers should never be able to refer to the same object - if - // this happens, you must have done something dodgy! - jassert (object != objectToTransferFrom.object); + const ScopedPointer& operator= (ObjectType* const newObjectToTakePossessionOf) + { + if (object != newObjectToTakePossessionOf) + { + ObjectType* const oldObject = object; + object = newObjectToTakePossessionOf; + delete oldObject; + } - ObjectType* const oldObject = object; - object = objectToTransferFrom.object; - objectToTransferFrom.object = 0; - delete oldObject; - } + return *this; + } - return *this; - } + inline operator ObjectType*() const { return object; } - /** Changes this ScopedPointer to point to a new object. + inline ObjectType& operator*() const { return *object; } - If this ScopedPointer already points to an object, that object - will first be deleted. + inline ObjectType* operator->() const { return object; } - The pointer that you pass is may be null. - */ - const ScopedPointer& operator= (ObjectType* const newObjectToTakePossessionOf) - { - if (object != newObjectToTakePossessionOf) - { - ObjectType* const oldObject = object; - object = newObjectToTakePossessionOf; - delete oldObject; - } + template + inline operator CastType*() const { return static_cast (object); } - return *this; - } + inline ObjectType** operator&() const { return (ObjectType**) &object; } - /** Returns the object that this ScopedPointer refers to. - */ - inline operator ObjectType*() const { return object; } + ObjectType* release() { ObjectType* const o = object; object = 0; return o; } - /** Returns the object that this ScopedPointer refers to. - */ - inline ObjectType& operator*() const { return *object; } + inline bool operator== (const ObjectType* const otherPointer) const { return otherPointer == object; } - /** Lets you access methods and properties of the object that this ScopedPointer refers to. */ - inline ObjectType* operator->() const { return object; } + inline bool operator!= (const ObjectType* const otherPointer) const { return otherPointer != object; } - /** Returns a pointer to the object by casting it to whatever type you need. */ - template - inline operator CastType*() const { return static_cast (object); } + void swapWith (ScopedPointer & other) + { + // Two ScopedPointers should never be able to refer to the same object - if + // this happens, you must have done something dodgy! + jassert (object != other.object); - /** Returns a reference to the address of the object that this ScopedPointer refers to. */ - inline ObjectType** operator&() const { return (ObjectType**) &object; } - - /** Removes the current object from this ScopedPointer without deleting it. - - This will return the current object, and set the ScopedPointer to a null pointer. - */ - ObjectType* release() { ObjectType* const o = object; object = 0; return o; } - - /** Compares the pointer with another pointer. - This can be handy for checking whether this is a null pointer. - */ - inline bool operator== (const ObjectType* const otherPointer) const { return otherPointer == object; } - - /** Compares the pointer with another pointer. - This can be handy for checking whether this is a null pointer. - */ - inline bool operator!= (const ObjectType* const otherPointer) const { return otherPointer != object; } - - /** Swaps this object with that of another ScopedPointer. - The two objects simply exchange their pointers. - */ - void swapWith (ScopedPointer & other) - { - // Two ScopedPointers should never be able to refer to the same object - if - // this happens, you must have done something dodgy! - jassert (object != other.object); - - swapVariables (object, other.object); - } + swapVariables (object, other.object); + } private: - ObjectType* object; + ObjectType* object; - // (Required as an alternative to the overloaded & operator). - ScopedPointer* getAddress() { return this; } + // (Required as an alternative to the overloaded & operator). + ScopedPointer* getAddress() { return this; } }; #endif // __JUCE_SCOPEDPOINTER_JUCEHEADER__ /********* End of inlined file: juce_ScopedPointer.h *********/ -/** An array designed for holding objects. - - This holds a list of pointers to objects, and will automatically - delete the objects when they are removed from the array, or when the - array is itself deleted. - - Declare it in the form: OwnedArray - - ..and then add new objects, e.g. myOwnedArray.add (new MyObjectClass()); - - After adding objects, they are 'owned' by the array and will be deleted when - removed or replaced. - - To make all the array's methods thread-safe, pass in "CriticalSection" as the templated - TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection. - - @see Array, ReferenceCountedArray, StringArray, CriticalSection -*/ template + class TypeOfCriticalSectionToUse = DummyCriticalSection> class OwnedArray { public: - /** Creates an empty array. - - @param granularity this is the size of increment by which the internal storage - used by the array will grow. Only change it from the default if you know the - array is going to be very big and needs to be able to grow efficiently. - */ - OwnedArray (const int granularity = juceDefaultArrayGranularity) throw() - : data (granularity), - numUsed (0) - { - } - - /** Deletes the array and also deletes any objects inside it. - - To get rid of the array without deleting its objects, use its - clear (false) method before deleting it. - */ - ~OwnedArray() - { - clear (true); - } - - /** Clears the array, optionally deleting the objects inside it first. */ - void clear (const bool deleteObjects = true) - { - lock.enter(); - - if (deleteObjects) - { - while (numUsed > 0) - delete data.elements [--numUsed]; - } - - data.setAllocatedSize (0); - numUsed = 0; - lock.exit(); - } - - /** Returns the number of items currently in the array. - @see operator[] - */ - inline int size() const throw() - { - return numUsed; - } - - /** Returns a pointer to the object at this index in the array. - - If the index is out-of-range, this will return a null pointer, (and - it could be null anyway, because it's ok for the array to hold null - pointers as well as objects). - - @see getUnchecked - */ - inline ObjectClass* operator[] (const int index) const throw() - { - lock.enter(); - ObjectClass* const result = (((unsigned int) index) < (unsigned int) numUsed) - ? data.elements [index] - : (ObjectClass*) 0; - lock.exit(); - - return result; - } - - /** Returns a pointer to the object at this index in the array, without checking whether the index is in-range. - - This is a faster and less safe version of operator[] which doesn't check the index passed in, so - it can be used when you're sure the index if always going to be legal. - */ - inline ObjectClass* getUnchecked (const int index) const throw() - { - lock.enter(); - jassert (((unsigned int) index) < (unsigned int) numUsed); - ObjectClass* const result = data.elements [index]; - lock.exit(); - - return result; - } - - /** Returns a pointer to the first object in the array. - - This will return a null pointer if the array's empty. - @see getLast - */ - inline ObjectClass* getFirst() const throw() - { - lock.enter(); - ObjectClass* const result = (numUsed > 0) ? data.elements [0] - : (ObjectClass*) 0; - lock.exit(); - return result; - } - - /** Returns a pointer to the last object in the array. - - This will return a null pointer if the array's empty. - @see getFirst - */ - inline ObjectClass* getLast() const throw() - { - lock.enter(); - ObjectClass* const result = (numUsed > 0) ? data.elements [numUsed - 1] - : (ObjectClass*) 0; - lock.exit(); - - return result; - } - - /** Finds the index of an object which might be in the array. - - @param objectToLookFor the object to look for - @returns the index at which the object was found, or -1 if it's not found - */ - int indexOf (const ObjectClass* const objectToLookFor) const throw() - { - int result = -1; - - lock.enter(); - ObjectClass* const* e = data.elements; - - for (int i = numUsed; --i >= 0;) - { - if (objectToLookFor == *e) - { - result = (int) (e - data.elements); - break; - } - - ++e; - } - - lock.exit(); - return result; - } - - /** Returns true if the array contains a specified object. - - @param objectToLookFor the object to look for - @returns true if the object is in the array - */ - bool contains (const ObjectClass* const objectToLookFor) const throw() - { - lock.enter(); - - ObjectClass* const* e = data.elements; - int i = numUsed; - - while (i >= 4) - { - if (objectToLookFor == *e - || objectToLookFor == *++e - || objectToLookFor == *++e - || objectToLookFor == *++e) - { - lock.exit(); - return true; - } - - i -= 4; - ++e; - } - - while (i > 0) - { - if (objectToLookFor == *e) - { - lock.exit(); - return true; - } - - --i; - ++e; - } - - lock.exit(); - return false; - } - - /** Appends a new object to the end of the array. - - Note that the this object will be deleted by the OwnedArray when it - is removed, so be careful not to delete it somewhere else. - - Also be careful not to add the same object to the array more than once, - as this will obviously cause deletion of dangling pointers. - - @param newObject the new object to add to the array - @see set, insert, addIfNotAlreadyThere, addSorted - */ - void add (const ObjectClass* const newObject) throw() - { - lock.enter(); - data.ensureAllocatedSize (numUsed + 1); - data.elements [numUsed++] = const_cast (newObject); - lock.exit(); - } - - /** Inserts a new object into the array at the given index. - - Note that the this object will be deleted by the OwnedArray when it - is removed, so be careful not to delete it somewhere else. - - If the index is less than 0 or greater than the size of the array, the - element will be added to the end of the array. - Otherwise, it will be inserted into the array, moving all the later elements - along to make room. - - Be careful not to add the same object to the array more than once, - as this will obviously cause deletion of dangling pointers. - - @param indexToInsertAt the index at which the new element should be inserted - @param newObject the new object to add to the array - @see add, addSorted, addIfNotAlreadyThere, set - */ - void insert (int indexToInsertAt, - const ObjectClass* const newObject) throw() - { - if (indexToInsertAt >= 0) - { - lock.enter(); - - if (indexToInsertAt > numUsed) - indexToInsertAt = numUsed; - - data.ensureAllocatedSize (numUsed + 1); - - ObjectClass** const e = data.elements + indexToInsertAt; - const int numToMove = numUsed - indexToInsertAt; - - if (numToMove > 0) - memmove (e + 1, e, numToMove * sizeof (ObjectClass*)); - - *e = const_cast (newObject); - ++numUsed; - - lock.exit(); - } - else - { - add (newObject); - } - } - - /** Appends a new object at the end of the array as long as the array doesn't - already contain it. - - If the array already contains a matching object, nothing will be done. - - @param newObject the new object to add to the array - */ - void addIfNotAlreadyThere (const ObjectClass* const newObject) throw() - { - lock.enter(); - - if (! contains (newObject)) - add (newObject); - - lock.exit(); - } - - /** Replaces an object in the array with a different one. - - If the index is less than zero, this method does nothing. - If the index is beyond the end of the array, the new object is added to the end of the array. - - Be careful not to add the same object to the array more than once, - as this will obviously cause deletion of dangling pointers. - - @param indexToChange the index whose value you want to change - @param newObject the new value to set for this index. - @param deleteOldElement whether to delete the object that's being replaced with the new one - @see add, insert, remove - */ - void set (const int indexToChange, - const ObjectClass* const newObject, - const bool deleteOldElement = true) - { - if (indexToChange >= 0) - { - ScopedPointer toDelete; - lock.enter(); - - if (indexToChange < numUsed) - { - if (deleteOldElement) - { - toDelete = data.elements [indexToChange]; - - if (toDelete == newObject) - toDelete = 0; - } - - data.elements [indexToChange] = const_cast (newObject); - } - else - { - data.ensureAllocatedSize (numUsed + 1); - data.elements [numUsed++] = const_cast (newObject); - } - - lock.exit(); - } - } - - /** Inserts a new object into the array assuming that the array is sorted. - - This will use a comparator to find the position at which the new object - should go. If the array isn't sorted, the behaviour of this - method will be unpredictable. - - @param comparator the comparator to use to compare the elements - see the sort method - for details about this object's structure - @param newObject the new object to insert to the array - @see add, sort, indexOfSorted - */ - template - void addSorted (ElementComparator& comparator, - ObjectClass* const newObject) throw() - { - (void) comparator; // if you pass in an object with a static compareElements() method, this - // avoids getting warning messages about the parameter being unused - lock.enter(); - insert (findInsertIndexInSortedArray (comparator, data.elements, newObject, 0, numUsed), newObject); - lock.exit(); - } - - /** Finds the index of an object in the array, assuming that the array is sorted. - - This will use a comparator to do a binary-chop to find the index of the given - element, if it exists. If the array isn't sorted, the behaviour of this - method will be unpredictable. - - @param comparator the comparator to use to compare the elements - see the sort() - method for details about the form this object should take - @param objectToLookFor the object to search for - @returns the index of the element, or -1 if it's not found - @see addSorted, sort - */ - template - int indexOfSorted (ElementComparator& comparator, - const ObjectClass* const objectToLookFor) const throw() - { - (void) comparator; // if you pass in an object with a static compareElements() method, this - // avoids getting warning messages about the parameter being unused - lock.enter(); - - int start = 0; - int end = numUsed; - - for (;;) - { - if (start >= end) - { - lock.exit(); - return -1; - } - else if (comparator.compareElements (objectToLookFor, data.elements [start]) == 0) - { - lock.exit(); - return start; - } - else - { - const int halfway = (start + end) >> 1; - - if (halfway == start) - { - lock.exit(); - return -1; - } - else if (comparator.compareElements (objectToLookFor, data.elements [halfway]) >= 0) - start = halfway; - else - end = halfway; - } - } - } - - /** Removes an object from the array. - - This will remove the object at a given index (optionally also - deleting it) and move back all the subsequent objects to close the gap. - If the index passed in is out-of-range, nothing will happen. - - @param indexToRemove the index of the element to remove - @param deleteObject whether to delete the object that is removed - @see removeObject, removeRange - */ - void remove (const int indexToRemove, - const bool deleteObject = true) - { - ScopedPointer toDelete; - lock.enter(); - - if (((unsigned int) indexToRemove) < (unsigned int) numUsed) - { - ObjectClass** const e = data.elements + indexToRemove; - - if (deleteObject) - toDelete = *e; - - --numUsed; - const int numToShift = numUsed - indexToRemove; - - if (numToShift > 0) - memmove (e, e + 1, numToShift * sizeof (ObjectClass*)); - - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); - } - - lock.exit(); - } - - /** Removes a specified object from the array. - - If the item isn't found, no action is taken. - - @param objectToRemove the object to try to remove - @param deleteObject whether to delete the object (if it's found) - @see remove, removeRange - */ - void removeObject (const ObjectClass* const objectToRemove, - const bool deleteObject = true) - { - lock.enter(); - ObjectClass** e = data.elements; - - for (int i = numUsed; --i >= 0;) - { - if (objectToRemove == *e) - { - remove ((int) (e - data.elements), deleteObject); - break; - } - - ++e; - } - - lock.exit(); - } - - /** Removes a range of objects from the array. - - This will remove a set of objects, starting from the given index, - and move any subsequent elements down to close the gap. - - If the range extends beyond the bounds of the array, it will - be safely clipped to the size of the array. - - @param startIndex the index of the first object to remove - @param numberToRemove how many objects should be removed - @param deleteObjects whether to delete the objects that get removed - @see remove, removeObject - */ - void removeRange (int startIndex, - const int numberToRemove, - const bool deleteObjects = true) - { - lock.enter(); - const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove); - startIndex = jlimit (0, numUsed, startIndex); - - if (endIndex > startIndex) - { - if (deleteObjects) - { - for (int i = startIndex; i < endIndex; ++i) - { - delete data.elements [i]; - data.elements [i] = 0; // (in case one of the destructors accesses this array and hits a dangling pointer) - } - } - - const int rangeSize = endIndex - startIndex; - ObjectClass** e = data.elements + startIndex; - int numToShift = numUsed - endIndex; - numUsed -= rangeSize; - - while (--numToShift >= 0) - { - *e = e [rangeSize]; - ++e; - } - - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); - } - - lock.exit(); - } - - /** Removes the last n objects from the array. - - @param howManyToRemove how many objects to remove from the end of the array - @param deleteObjects whether to also delete the objects that are removed - @see remove, removeObject, removeRange - */ - void removeLast (int howManyToRemove = 1, - const bool deleteObjects = true) - { - lock.enter(); - - if (howManyToRemove >= numUsed) - { - clear (deleteObjects); - } - else - { - while (--howManyToRemove >= 0) - remove (numUsed - 1, deleteObjects); - } - - lock.exit(); - } - - /** Swaps a pair of objects in the array. - - If either of the indexes passed in is out-of-range, nothing will happen, - otherwise the two objects at these positions will be exchanged. - */ - void swap (const int index1, - const int index2) throw() - { - lock.enter(); - - if (((unsigned int) index1) < (unsigned int) numUsed - && ((unsigned int) index2) < (unsigned int) numUsed) - { - swapVariables (data.elements [index1], - data.elements [index2]); - } - - lock.exit(); - } - - /** Moves one of the objects to a different position. - - This will move the object to a specified index, shuffling along - any intervening elements as required. - - So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling - move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }. - - @param currentIndex the index of the object to be moved. If this isn't a - valid index, then nothing will be done - @param newIndex the index at which you'd like this object to end up. If this - is less than zero, it will be moved to the end of the array - */ - void move (const int currentIndex, - int newIndex) throw() - { - if (currentIndex != newIndex) - { - lock.enter(); - - if (((unsigned int) currentIndex) < (unsigned int) numUsed) - { - if (((unsigned int) newIndex) >= (unsigned int) numUsed) - newIndex = numUsed - 1; - - ObjectClass* const value = data.elements [currentIndex]; - - if (newIndex > currentIndex) - { - memmove (data.elements + currentIndex, - data.elements + currentIndex + 1, - (newIndex - currentIndex) * sizeof (ObjectClass*)); - } - else - { - memmove (data.elements + newIndex + 1, - data.elements + newIndex, - (currentIndex - newIndex) * sizeof (ObjectClass*)); - } - - data.elements [newIndex] = value; - } - - lock.exit(); - } - } - - /** This swaps the contents of this array with those of another array. - - If you need to exchange two arrays, this is vastly quicker than using copy-by-value - because it just swaps their internal pointers. - */ - template - void swapWithArray (OtherArrayType& otherArray) throw() - { - lock.enter(); - otherArray.lock.enter(); - swapVariables (numUsed, otherArray.numUsed); - swapVariables (data.elements, otherArray.data.elements); - swapVariables (data.numAllocated, otherArray.data.numAllocated); - otherArray.lock.exit(); - lock.exit(); - } - - /** Reduces the amount of storage being used by the array. - - Arrays typically allocate slightly more storage than they need, and after - removing elements, they may have quite a lot of unused space allocated. - This method will reduce the amount of allocated storage to a minimum. - */ - void minimiseStorageOverheads() throw() - { - lock.enter(); - - if (numUsed == 0) - { - data.setAllocatedSize (0); - } - else - { - const int newAllocation = data.granularity * (numUsed / data.granularity + 1); - - if (newAllocation < data.numAllocated) - data.setAllocatedSize (newAllocation); - } - - lock.exit(); - } - - /** Increases the array's internal storage to hold a minimum number of elements. - - Calling this before adding a large known number of elements means that - the array won't have to keep dynamically resizing itself as the elements - are added, and it'll therefore be more efficient. - */ - void ensureStorageAllocated (const int minNumElements) throw() - { - data.ensureAllocatedSize (minNumElements); - } - - /** Sorts the elements in the array. - - This will use a comparator object to sort the elements into order. The object - passed must have a method of the form: - @code - int compareElements (ElementType first, ElementType second); - @endcode - - ..and this method must return: - - a value of < 0 if the first comes before the second - - a value of 0 if the two objects are equivalent - - a value of > 0 if the second comes before the first - - To improve performance, the compareElements() method can be declared as static or const. - - @param comparator the comparator to use for comparing elements. - @param retainOrderOfEquivalentItems if this is true, then items - which the comparator says are equivalent will be - kept in the order in which they currently appear - in the array. This is slower to perform, but may - be important in some cases. If it's false, a faster - algorithm is used, but equivalent elements may be - rearranged. - @see sortArray, indexOfSorted - */ - template - void sort (ElementComparator& comparator, - const bool retainOrderOfEquivalentItems = false) const throw() - { - (void) comparator; // if you pass in an object with a static compareElements() method, this - // avoids getting warning messages about the parameter being unused - - lock.enter(); - sortArray (comparator, data.elements, 0, size() - 1, retainOrderOfEquivalentItems); - lock.exit(); - } - - /** Locks the array's CriticalSection. - - Of course if the type of section used is a DummyCriticalSection, this won't - have any effect. - - @see unlockArray - */ - void lockArray() const throw() - { - lock.enter(); - } - - /** Unlocks the array's CriticalSection. - - Of course if the type of section used is a DummyCriticalSection, this won't - have any effect. - - @see lockArray - */ - void unlockArray() const throw() - { - lock.exit(); - } - - juce_UseDebuggingNewOperator + OwnedArray() throw() + : numUsed (0) + { + } + + ~OwnedArray() + { + clear (true); + } + + void clear (const bool deleteObjects = true) + { + lock.enter(); + + if (deleteObjects) + { + while (numUsed > 0) + delete data.elements [--numUsed]; + } + + data.setAllocatedSize (0); + numUsed = 0; + lock.exit(); + } + + inline int size() const throw() + { + return numUsed; + } + + inline ObjectClass* operator[] (const int index) const throw() + { + lock.enter(); + ObjectClass* const result = (((unsigned int) index) < (unsigned int) numUsed) + ? data.elements [index] + : (ObjectClass*) 0; + lock.exit(); + + return result; + } + + inline ObjectClass* getUnchecked (const int index) const throw() + { + lock.enter(); + jassert (((unsigned int) index) < (unsigned int) numUsed); + ObjectClass* const result = data.elements [index]; + lock.exit(); + + return result; + } + + inline ObjectClass* getFirst() const throw() + { + lock.enter(); + ObjectClass* const result = (numUsed > 0) ? data.elements [0] + : (ObjectClass*) 0; + lock.exit(); + return result; + } + + inline ObjectClass* getLast() const throw() + { + lock.enter(); + ObjectClass* const result = (numUsed > 0) ? data.elements [numUsed - 1] + : (ObjectClass*) 0; + lock.exit(); + + return result; + } + + int indexOf (const ObjectClass* const objectToLookFor) const throw() + { + int result = -1; + + lock.enter(); + ObjectClass* const* e = data.elements; + + for (int i = numUsed; --i >= 0;) + { + if (objectToLookFor == *e) + { + result = (int) (e - data.elements); + break; + } + + ++e; + } + + lock.exit(); + return result; + } + + bool contains (const ObjectClass* const objectToLookFor) const throw() + { + lock.enter(); + + ObjectClass* const* e = data.elements; + int i = numUsed; + + while (i >= 4) + { + if (objectToLookFor == *e + || objectToLookFor == *++e + || objectToLookFor == *++e + || objectToLookFor == *++e) + { + lock.exit(); + return true; + } + + i -= 4; + ++e; + } + + while (i > 0) + { + if (objectToLookFor == *e) + { + lock.exit(); + return true; + } + + --i; + ++e; + } + + lock.exit(); + return false; + } + + void add (const ObjectClass* const newObject) throw() + { + lock.enter(); + data.ensureAllocatedSize (numUsed + 1); + data.elements [numUsed++] = const_cast (newObject); + lock.exit(); + } + + void insert (int indexToInsertAt, + const ObjectClass* const newObject) throw() + { + if (indexToInsertAt >= 0) + { + lock.enter(); + + if (indexToInsertAt > numUsed) + indexToInsertAt = numUsed; + + data.ensureAllocatedSize (numUsed + 1); + + ObjectClass** const e = data.elements + indexToInsertAt; + const int numToMove = numUsed - indexToInsertAt; + + if (numToMove > 0) + memmove (e + 1, e, numToMove * sizeof (ObjectClass*)); + + *e = const_cast (newObject); + ++numUsed; + + lock.exit(); + } + else + { + add (newObject); + } + } + + void addIfNotAlreadyThere (const ObjectClass* const newObject) throw() + { + lock.enter(); + + if (! contains (newObject)) + add (newObject); + + lock.exit(); + } + + void set (const int indexToChange, + const ObjectClass* const newObject, + const bool deleteOldElement = true) + { + if (indexToChange >= 0) + { + ScopedPointer toDelete; + lock.enter(); + + if (indexToChange < numUsed) + { + if (deleteOldElement) + { + toDelete = data.elements [indexToChange]; + + if (toDelete == newObject) + toDelete = 0; + } + + data.elements [indexToChange] = const_cast (newObject); + } + else + { + data.ensureAllocatedSize (numUsed + 1); + data.elements [numUsed++] = const_cast (newObject); + } + + lock.exit(); + } + } + + template + void addSorted (ElementComparator& comparator, + ObjectClass* const newObject) throw() + { + (void) comparator; // if you pass in an object with a static compareElements() method, this + // avoids getting warning messages about the parameter being unused + lock.enter(); + insert (findInsertIndexInSortedArray (comparator, data.elements, newObject, 0, numUsed), newObject); + lock.exit(); + } + + template + int indexOfSorted (ElementComparator& comparator, + const ObjectClass* const objectToLookFor) const throw() + { + (void) comparator; // if you pass in an object with a static compareElements() method, this + // avoids getting warning messages about the parameter being unused + lock.enter(); + + int start = 0; + int end = numUsed; + + for (;;) + { + if (start >= end) + { + lock.exit(); + return -1; + } + else if (comparator.compareElements (objectToLookFor, data.elements [start]) == 0) + { + lock.exit(); + return start; + } + else + { + const int halfway = (start + end) >> 1; + + if (halfway == start) + { + lock.exit(); + return -1; + } + else if (comparator.compareElements (objectToLookFor, data.elements [halfway]) >= 0) + start = halfway; + else + end = halfway; + } + } + } + + void remove (const int indexToRemove, + const bool deleteObject = true) + { + ScopedPointer toDelete; + lock.enter(); + + if (((unsigned int) indexToRemove) < (unsigned int) numUsed) + { + ObjectClass** const e = data.elements + indexToRemove; + + if (deleteObject) + toDelete = *e; + + --numUsed; + const int numToShift = numUsed - indexToRemove; + + if (numToShift > 0) + memmove (e, e + 1, numToShift * sizeof (ObjectClass*)); + + if ((numUsed << 1) < data.numAllocated) + minimiseStorageOverheads(); + } + + lock.exit(); + } + + void removeObject (const ObjectClass* const objectToRemove, + const bool deleteObject = true) + { + lock.enter(); + ObjectClass** e = data.elements; + + for (int i = numUsed; --i >= 0;) + { + if (objectToRemove == *e) + { + remove ((int) (e - data.elements), deleteObject); + break; + } + + ++e; + } + + lock.exit(); + } + + void removeRange (int startIndex, + const int numberToRemove, + const bool deleteObjects = true) + { + lock.enter(); + const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove); + startIndex = jlimit (0, numUsed, startIndex); + + if (endIndex > startIndex) + { + if (deleteObjects) + { + for (int i = startIndex; i < endIndex; ++i) + { + delete data.elements [i]; + data.elements [i] = 0; // (in case one of the destructors accesses this array and hits a dangling pointer) + } + } + + const int rangeSize = endIndex - startIndex; + ObjectClass** e = data.elements + startIndex; + int numToShift = numUsed - endIndex; + numUsed -= rangeSize; + + while (--numToShift >= 0) + { + *e = e [rangeSize]; + ++e; + } + + if ((numUsed << 1) < data.numAllocated) + minimiseStorageOverheads(); + } + + lock.exit(); + } + + void removeLast (int howManyToRemove = 1, + const bool deleteObjects = true) + { + lock.enter(); + + if (howManyToRemove >= numUsed) + { + clear (deleteObjects); + } + else + { + while (--howManyToRemove >= 0) + remove (numUsed - 1, deleteObjects); + } + + lock.exit(); + } + + void swap (const int index1, + const int index2) throw() + { + lock.enter(); + + if (((unsigned int) index1) < (unsigned int) numUsed + && ((unsigned int) index2) < (unsigned int) numUsed) + { + swapVariables (data.elements [index1], + data.elements [index2]); + } + + lock.exit(); + } + + void move (const int currentIndex, + int newIndex) throw() + { + if (currentIndex != newIndex) + { + lock.enter(); + + if (((unsigned int) currentIndex) < (unsigned int) numUsed) + { + if (((unsigned int) newIndex) >= (unsigned int) numUsed) + newIndex = numUsed - 1; + + ObjectClass* const value = data.elements [currentIndex]; + + if (newIndex > currentIndex) + { + memmove (data.elements + currentIndex, + data.elements + currentIndex + 1, + (newIndex - currentIndex) * sizeof (ObjectClass*)); + } + else + { + memmove (data.elements + newIndex + 1, + data.elements + newIndex, + (currentIndex - newIndex) * sizeof (ObjectClass*)); + } + + data.elements [newIndex] = value; + } + + lock.exit(); + } + } + + template + void swapWithArray (OtherArrayType& otherArray) throw() + { + lock.enter(); + otherArray.lock.enter(); + swapVariables (numUsed, otherArray.numUsed); + swapVariables (data.elements, otherArray.data.elements); + swapVariables (data.numAllocated, otherArray.data.numAllocated); + otherArray.lock.exit(); + lock.exit(); + } + + void minimiseStorageOverheads() throw() + { + lock.enter(); + data.shrinkToNoMoreThan (numUsed); + lock.exit(); + } + + void ensureStorageAllocated (const int minNumElements) throw() + { + lock.enter(); + data.ensureAllocatedSize (minNumElements); + lock.exit(); + } + + template + void sort (ElementComparator& comparator, + const bool retainOrderOfEquivalentItems = false) const throw() + { + (void) comparator; // if you pass in an object with a static compareElements() method, this + // avoids getting warning messages about the parameter being unused + + lock.enter(); + sortArray (comparator, data.elements, 0, size() - 1, retainOrderOfEquivalentItems); + lock.exit(); + } + + void lockArray() const throw() + { + lock.enter(); + } + + void unlockArray() const throw() + { + lock.exit(); + } + + juce_UseDebuggingNewOperator private: - ArrayAllocationBase data; - int numUsed; - TypeOfCriticalSectionToUse lock; + ArrayAllocationBase data; + int numUsed; + TypeOfCriticalSectionToUse lock; - // disallow copy constructor and assignment - OwnedArray (const OwnedArray&); - const OwnedArray& operator= (const OwnedArray&); + // disallow copy constructor and assignment + OwnedArray (const OwnedArray&); + const OwnedArray& operator= (const OwnedArray&); }; #endif // __JUCE_OWNEDARRAY_JUCEHEADER__ @@ -5898,410 +3371,152 @@ private: static const tchar* const defaultPostNumberString = JUCE_T(")"); #endif -/** - A special array for holding a list of strings. - - @see String, StringPairArray -*/ class JUCE_API StringArray { public: - /** Creates an empty string array */ - StringArray() throw(); + StringArray() throw(); - /** Creates a copy of another string array */ - StringArray (const StringArray& other) throw(); + StringArray (const StringArray& other) throw(); - /** Creates a copy of an array of string literals. + StringArray (const juce_wchar** const strings, + const int numberOfStrings) throw(); - @param strings an array of strings to add. Null pointers in the array will be - treated as empty strings - @param numberOfStrings how many items there are in the array - */ - StringArray (const juce_wchar** const strings, - const int numberOfStrings) throw(); + StringArray (const char** const strings, + const int numberOfStrings) throw(); - /** Creates a copy of an array of string literals. + StringArray (const juce_wchar** const strings) throw(); - @param strings an array of strings to add. Null pointers in the array will be - treated as empty strings - @param numberOfStrings how many items there are in the array - */ - StringArray (const char** const strings, - const int numberOfStrings) throw(); + StringArray (const char** const strings) throw(); - /** Creates a copy of a null-terminated array of string literals. + virtual ~StringArray() throw(); - Each item from the array passed-in is added, until it encounters a null pointer, - at which point it stops. - */ - StringArray (const juce_wchar** const strings) throw(); + const StringArray& operator= (const StringArray& other) throw(); - /** Creates a copy of a null-terminated array of string literals. + bool operator== (const StringArray& other) const throw(); - Each item from the array passed-in is added, until it encounters a null pointer, - at which point it stops. - */ - StringArray (const char** const strings) throw(); + bool operator!= (const StringArray& other) const throw(); - /** Destructor. */ - virtual ~StringArray() throw(); + inline int size() const throw() { return strings.size(); }; - /** Copies the contents of another string array into this one */ - const StringArray& operator= (const StringArray& other) throw(); + const String& operator[] (const int index) const throw(); - /** Compares two arrays. + bool contains (const String& stringToLookFor, + const bool ignoreCase = false) const throw(); - Comparisons are case-sensitive. + int indexOf (const String& stringToLookFor, + const bool ignoreCase = false, + int startIndex = 0) const throw(); - @returns true only if the other array contains exactly the same strings in the same order - */ - bool operator== (const StringArray& other) const throw(); + void add (const String& stringToAdd) throw(); - /** Compares two arrays. + void insert (const int index, + const String& stringToAdd) throw(); - Comparisons are case-sensitive. + void addIfNotAlreadyThere (const String& stringToAdd, + const bool ignoreCase = false) throw(); - @returns false if the other array contains exactly the same strings in the same order - */ - bool operator!= (const StringArray& other) const throw(); + void set (const int index, + const String& newString) throw(); - /** Returns the number of strings in the array */ - inline int size() const throw() { return strings.size(); }; + void addArray (const StringArray& other, + int startIndex = 0, + int numElementsToAdd = -1) throw(); - /** Returns one of the strings from the array. + int addTokens (const tchar* const stringToTokenise, + const bool preserveQuotedStrings) throw(); - If the index is out-of-range, an empty string is returned. + int addTokens (const tchar* const stringToTokenise, + const tchar* breakCharacters, + const tchar* quoteCharacters) throw(); - Obviously the reference returned shouldn't be stored for later use, as the - string it refers to may disappear when the array changes. - */ - const String& operator[] (const int index) const throw(); + int addLines (const tchar* stringToBreakUp) throw(); - /** Searches for a string in the array. + void clear() throw(); - The comparison will be case-insensitive if the ignoreCase parameter is true. + void remove (const int index) throw(); - @returns true if the string is found inside the array - */ - bool contains (const String& stringToLookFor, - const bool ignoreCase = false) const throw(); + void removeString (const String& stringToRemove, + const bool ignoreCase = false) throw(); - /** Searches for a string in the array. + void removeDuplicates (const bool ignoreCase) throw(); - The comparison will be case-insensitive if the ignoreCase parameter is true. + void removeEmptyStrings (const bool removeWhitespaceStrings = true) throw(); - @param stringToLookFor the string to try to find - @param ignoreCase whether the comparison should be case-insensitive - @param startIndex the first index to start searching from - @returns the index of the first occurrence of the string in this array, - or -1 if it isn't found. - */ - int indexOf (const String& stringToLookFor, - const bool ignoreCase = false, - int startIndex = 0) const throw(); + void move (const int currentIndex, int newIndex) throw(); - /** Appends a string at the end of the array. */ - void add (const String& stringToAdd) throw(); + void trim() throw(); - /** Inserts a string into the array. + void appendNumbersToDuplicates (const bool ignoreCaseWhenComparing, + const bool appendNumberToFirstInstance, + const tchar* const preNumberString = defaultPreNumberString, + const tchar* const postNumberString = defaultPostNumberString) throw(); - This will insert a string into the array at the given index, moving - up the other elements to make room for it. - If the index is less than zero or greater than the size of the array, - the new string will be added to the end of the array. - */ - void insert (const int index, - const String& stringToAdd) throw(); + const String joinIntoString (const String& separatorString, + int startIndex = 0, + int numberOfElements = -1) const throw(); - /** Adds a string to the array as long as it's not already in there. + void sort (const bool ignoreCase) throw(); - The search can optionally be case-insensitive. - */ - void addIfNotAlreadyThere (const String& stringToAdd, - const bool ignoreCase = false) throw(); + void minimiseStorageOverheads() throw(); - /** Replaces one of the strings in the array with another one. - - If the index is higher than the array's size, the new string will be - added to the end of the array; if it's less than zero nothing happens. - */ - void set (const int index, - const String& newString) throw(); - - /** Appends some strings from another array to the end of this one. - - @param other the array to add - @param startIndex the first element of the other array to add - @param numElementsToAdd the maximum number of elements to add (if this is - less than zero, they are all added) - */ - void addArray (const StringArray& other, - int startIndex = 0, - int numElementsToAdd = -1) throw(); - - /** Breaks up a string into tokens and adds them to this array. - - This will tokenise the given string using whitespace characters as the - token delimiters, and will add these tokens to the end of the array. - - @returns the number of tokens added - */ - int addTokens (const tchar* const stringToTokenise, - const bool preserveQuotedStrings) throw(); - - /** Breaks up a string into tokens and adds them to this array. - - This will tokenise the given string (using the string passed in to define the - token delimiters), and will add these tokens to the end of the array. - - @param stringToTokenise the string to tokenise - @param breakCharacters a string of characters, any of which will be considered - to be a token delimiter. - @param quoteCharacters if this string isn't empty, it defines a set of characters - which are treated as quotes. Any text occurring - between quotes is not broken up into tokens. - @returns the number of tokens added - */ - int addTokens (const tchar* const stringToTokenise, - const tchar* breakCharacters, - const tchar* quoteCharacters) throw(); - - /** Breaks up a string into lines and adds them to this array. - - This breaks a string down into lines separated by \\n or \\r\\n, and adds each line - to the array. Line-break characters are omitted from the strings that are added to - the array. - */ - int addLines (const tchar* stringToBreakUp) throw(); - - /** Removes all elements from the array. */ - void clear() throw(); - - /** Removes a string from the array. - - If the index is out-of-range, no action will be taken. - */ - void remove (const int index) throw(); - - /** Finds a string in the array and removes it. - - This will remove the first occurrence of the given string from the array. The - comparison may be case-insensitive depending on the ignoreCase parameter. - */ - void removeString (const String& stringToRemove, - const bool ignoreCase = false) throw(); - - /** Removes any duplicated elements from the array. - - If any string appears in the array more than once, only the first occurrence of - it will be retained. - - @param ignoreCase whether to use a case-insensitive comparison - */ - void removeDuplicates (const bool ignoreCase) throw(); - - /** Removes empty strings from the array. - - @param removeWhitespaceStrings if true, strings that only contain whitespace - characters will also be removed - */ - void removeEmptyStrings (const bool removeWhitespaceStrings = true) throw(); - - /** Moves one of the strings to a different position. - - This will move the string to a specified index, shuffling along - any intervening elements as required. - - So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling - move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }. - - @param currentIndex the index of the value to be moved. If this isn't a - valid index, then nothing will be done - @param newIndex the index at which you'd like this value to end up. If this - is less than zero, the value will be moved to the end - of the array - */ - void move (const int currentIndex, int newIndex) throw(); - - /** Deletes any whitespace characters from the starts and ends of all the strings. */ - void trim() throw(); - - /** Adds numbers to the strings in the array, to make each string unique. - - This will add numbers to the ends of groups of similar strings. - e.g. if there are two "moose" strings, they will become "moose (1)" and "moose (2)" - - @param ignoreCaseWhenComparing whether the comparison used is case-insensitive - @param appendNumberToFirstInstance whether the first of a group of similar strings - also has a number appended to it. - @param preNumberString when adding a number, this string is added before the number - @param postNumberString this string is appended after any numbers that are added - */ - void appendNumbersToDuplicates (const bool ignoreCaseWhenComparing, - const bool appendNumberToFirstInstance, - const tchar* const preNumberString = defaultPreNumberString, - const tchar* const postNumberString = defaultPostNumberString) throw(); - - /** Joins the strings in the array together into one string. - - This will join a range of elements from the array into a string, separating - them with a given string. - - e.g. joinIntoString (",") will turn an array of "a" "b" and "c" into "a,b,c". - - @param separatorString the string to insert between all the strings - @param startIndex the first element to join - @param numberOfElements how many elements to join together. If this is less - than zero, all available elements will be used. - */ - const String joinIntoString (const String& separatorString, - int startIndex = 0, - int numberOfElements = -1) const throw(); - - /** Sorts the array into alphabetical order. - - @param ignoreCase if true, the comparisons used will be case-sensitive. - */ - void sort (const bool ignoreCase) throw(); - - /** Reduces the amount of storage being used by the array. - - Arrays typically allocate slightly more storage than they need, and after - removing elements, they may have quite a lot of unused space allocated. - This method will reduce the amount of allocated storage to a minimum. - */ - void minimiseStorageOverheads() throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OwnedArray strings; + OwnedArray strings; }; #endif // __JUCE_STRINGARRAY_JUCEHEADER__ /********* End of inlined file: juce_StringArray.h *********/ -/** - A container for holding a set of strings which are keyed by another string. - - @see StringArray -*/ class JUCE_API StringPairArray { public: - /** Creates an empty array */ - StringPairArray (const bool ignoreCaseWhenComparingKeys = true) throw(); + StringPairArray (const bool ignoreCaseWhenComparingKeys = true) throw(); - /** Creates a copy of another array */ - StringPairArray (const StringPairArray& other) throw(); + StringPairArray (const StringPairArray& other) throw(); - /** Destructor. */ - ~StringPairArray() throw(); + ~StringPairArray() throw(); - /** Copies the contents of another string array into this one */ - const StringPairArray& operator= (const StringPairArray& other) throw(); + const StringPairArray& operator= (const StringPairArray& other) throw(); - /** Compares two arrays. + bool operator== (const StringPairArray& other) const throw(); - Comparisons are case-sensitive. + bool operator!= (const StringPairArray& other) const throw(); - @returns true only if the other array contains exactly the same strings with the same keys - */ - bool operator== (const StringPairArray& other) const throw(); + const String& operator[] (const String& key) const throw(); - /** Compares two arrays. + const String getValue (const String& key, const String& defaultReturnValue) const; - Comparisons are case-sensitive. + const StringArray& getAllKeys() const throw() { return keys; } - @returns false if the other array contains exactly the same strings with the same keys - */ - bool operator!= (const StringPairArray& other) const throw(); + const StringArray& getAllValues() const throw() { return values; } - /** Finds the value corresponding to a key string. + inline int size() const throw() { return keys.size(); }; - If no such key is found, this will just return an empty string. To check whether - a given key actually exists (because it might actually be paired with an empty string), use - the getAllKeys() method to obtain a list. + void set (const String& key, + const String& value) throw(); - Obviously the reference returned shouldn't be stored for later use, as the - string it refers to may disappear when the array changes. + void addArray (const StringPairArray& other); - @see getValue - */ - const String& operator[] (const String& key) const throw(); + void clear() throw(); - /** Finds the value corresponding to a key string. + void remove (const String& key) throw(); - If no such key is found, this will just return the value provided as a default. + void remove (const int index) throw(); - @see operator[] - */ - const String getValue (const String& key, const String& defaultReturnValue) const; + void setIgnoresCase (const bool shouldIgnoreCase) throw(); - /** Returns a list of all keys in the array. */ - const StringArray& getAllKeys() const throw() { return keys; } + const String getDescription() const; - /** Returns a list of all values in the array. */ - const StringArray& getAllValues() const throw() { return values; } + void minimiseStorageOverheads() throw(); - /** Returns the number of strings in the array */ - inline int size() const throw() { return keys.size(); }; - - /** Adds or amends a key/value pair. - - If a value already exists with this key, its value will be overwritten, - otherwise the key/value pair will be added to the array. - */ - void set (const String& key, - const String& value) throw(); - - /** Adds the items from another array to this one. - - This is equivalent to using set() to add each of the pairs from the other array. - */ - void addArray (const StringPairArray& other); - - /** Removes all elements from the array. */ - void clear() throw(); - - /** Removes a string from the array based on its key. - - If the key isn't found, nothing will happen. - */ - void remove (const String& key) throw(); - - /** Removes a string from the array based on its index. - - If the index is out-of-range, no action will be taken. - */ - void remove (const int index) throw(); - - /** Indicates whether to use a case-insensitive search when looking up a key string. - */ - void setIgnoresCase (const bool shouldIgnoreCase) throw(); - - /** Returns a descriptive string containing the items. - - This is handy for dumping the contents of an array. - */ - const String getDescription() const; - - /** Reduces the amount of storage being used by the array. - - Arrays typically allocate slightly more storage than they need, and after - removing elements, they may have quite a lot of unused space allocated. - This method will reduce the amount of allocated storage to a minimum. - */ - void minimiseStorageOverheads() throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - StringArray keys, values; - bool ignoreCase; + StringArray keys, values; + bool ignoreCase; }; #endif // __JUCE_STRINGPAIRARRAY_JUCEHEADER__ @@ -6319,469 +3534,137 @@ private: #ifndef __JUCE_INPUTSTREAM_JUCEHEADER__ #define __JUCE_INPUTSTREAM_JUCEHEADER__ -/** The base class for streams that read data. - - Input and output streams are used throughout the library - subclasses can override - some or all of the virtual functions to implement their behaviour. - - @see OutputStream, MemoryInputStream, BufferedInputStream, FileInputStream -*/ class JUCE_API InputStream { public: - /** Destructor. */ - virtual ~InputStream() {} + virtual ~InputStream() {} - /** Returns the total number of bytes available for reading in this stream. + virtual int64 getTotalLength() = 0; - Note that this is the number of bytes available from the start of the - stream, not from the current position. + virtual bool isExhausted() = 0; - If the size of the stream isn't actually known, this may return -1. - */ - virtual int64 getTotalLength() = 0; + virtual int read (void* destBuffer, + int maxBytesToRead) = 0; - /** Returns true if the stream has no more data to read. */ - virtual bool isExhausted() = 0; + virtual char readByte(); - /** Reads a set of bytes from the stream into a memory buffer. + virtual bool readBool(); - This is the only read method that subclasses actually need to implement, as the - InputStream base class implements the other read methods in terms of this one (although - it's often more efficient for subclasses to implement them directly). + virtual short readShort(); - @param destBuffer the destination buffer for the data - @param maxBytesToRead the maximum number of bytes to read - make sure the - memory block passed in is big enough to contain this - many bytes. + virtual short readShortBigEndian(); - @returns the actual number of bytes that were read, which may be less than - maxBytesToRead if the stream is exhausted before it gets that far - */ - virtual int read (void* destBuffer, - int maxBytesToRead) = 0; + virtual int readInt(); - /** Reads a byte from the stream. + virtual int readIntBigEndian(); - If the stream is exhausted, this will return zero. + virtual int64 readInt64(); - @see OutputStream::writeByte - */ - virtual char readByte(); + virtual int64 readInt64BigEndian(); - /** Reads a boolean from the stream. + virtual float readFloat(); - The bool is encoded as a single byte - 1 for true, 0 for false. + virtual float readFloatBigEndian(); - If the stream is exhausted, this will return false. + virtual double readDouble(); - @see OutputStream::writeBool - */ - virtual bool readBool(); + virtual double readDoubleBigEndian(); - /** Reads two bytes from the stream as a little-endian 16-bit value. + virtual int readCompressedInt(); - If the next two bytes read are byte1 and byte2, this returns - (byte1 | (byte2 << 8)). + virtual const String readNextLine(); - If the stream is exhausted partway through reading the bytes, this will return zero. + virtual const String readString(); - @see OutputStream::writeShort, readShortBigEndian - */ - virtual short readShort(); + virtual const String readEntireStreamAsString(); - /** Reads two bytes from the stream as a little-endian 16-bit value. + virtual int readIntoMemoryBlock (MemoryBlock& destBlock, + int maxNumBytesToRead = -1); - If the next two bytes read are byte1 and byte2, this returns - (byte2 | (byte1 << 8)). + virtual int64 getPosition() = 0; - If the stream is exhausted partway through reading the bytes, this will return zero. + virtual bool setPosition (int64 newPosition) = 0; - @see OutputStream::writeShortBigEndian, readShort - */ - virtual short readShortBigEndian(); + virtual void skipNextBytes (int64 numBytesToSkip); - /** Reads four bytes from the stream as a little-endian 32-bit value. - - If the next four bytes are byte1 to byte4, this returns - (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24)). - - If the stream is exhausted partway through reading the bytes, this will return zero. - - @see OutputStream::writeInt, readIntBigEndian - */ - virtual int readInt(); - - /** Reads four bytes from the stream as a big-endian 32-bit value. - - If the next four bytes are byte1 to byte4, this returns - (byte4 | (byte3 << 8) | (byte2 << 16) | (byte1 << 24)). - - If the stream is exhausted partway through reading the bytes, this will return zero. - - @see OutputStream::writeIntBigEndian, readInt - */ - virtual int readIntBigEndian(); - - /** Reads eight bytes from the stream as a little-endian 64-bit value. - - If the next eight bytes are byte1 to byte8, this returns - (byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24) | (byte5 << 32) | (byte6 << 40) | (byte7 << 48) | (byte8 << 56)). - - If the stream is exhausted partway through reading the bytes, this will return zero. - - @see OutputStream::writeInt64, readInt64BigEndian - */ - virtual int64 readInt64(); - - /** Reads eight bytes from the stream as a big-endian 64-bit value. - - If the next eight bytes are byte1 to byte8, this returns - (byte8 | (byte7 << 8) | (byte6 << 16) | (byte5 << 24) | (byte4 << 32) | (byte3 << 40) | (byte2 << 48) | (byte1 << 56)). - - If the stream is exhausted partway through reading the bytes, this will return zero. - - @see OutputStream::writeInt64BigEndian, readInt64 - */ - virtual int64 readInt64BigEndian(); - - /** Reads four bytes as a 32-bit floating point value. - - The raw 32-bit encoding of the float is read from the stream as a little-endian int. - - If the stream is exhausted partway through reading the bytes, this will return zero. - - @see OutputStream::writeFloat, readDouble - */ - virtual float readFloat(); - - /** Reads four bytes as a 32-bit floating point value. - - The raw 32-bit encoding of the float is read from the stream as a big-endian int. - - If the stream is exhausted partway through reading the bytes, this will return zero. - - @see OutputStream::writeFloatBigEndian, readDoubleBigEndian - */ - virtual float readFloatBigEndian(); - - /** Reads eight bytes as a 64-bit floating point value. - - The raw 64-bit encoding of the double is read from the stream as a little-endian int64. - - If the stream is exhausted partway through reading the bytes, this will return zero. - - @see OutputStream::writeDouble, readFloat - */ - virtual double readDouble(); - - /** Reads eight bytes as a 64-bit floating point value. - - The raw 64-bit encoding of the double is read from the stream as a big-endian int64. - - If the stream is exhausted partway through reading the bytes, this will return zero. - - @see OutputStream::writeDoubleBigEndian, readFloatBigEndian - */ - virtual double readDoubleBigEndian(); - - /** Reads an encoded 32-bit number from the stream using a space-saving compressed format. - - For small values, this is more space-efficient than using readInt() and OutputStream::writeInt() - - The format used is: number of significant bytes + up to 4 bytes in little-endian order. - - @see OutputStream::writeCompressedInt() - */ - virtual int readCompressedInt(); - - /** Reads a UTF8 string from the stream, up to the next linefeed or carriage return. - - This will read up to the next "\n" or "\r\n" or end-of-stream. - - After this call, the stream's position will be left pointing to the next character - following the line-feed, but the linefeeds aren't included in the string that - is returned. - */ - virtual const String readNextLine(); - - /** Reads a zero-terminated UTF8 string from the stream. - - This will read characters from the stream until it hits a zero character or - end-of-stream. - - @see OutputStream::writeString, readEntireStreamAsString - */ - virtual const String readString(); - - /** Tries to read the whole stream and turn it into a string. - - This will read from the stream's current position until the end-of-stream, and - will try to make an educated guess about whether it's unicode or an 8-bit encoding. - */ - virtual const String readEntireStreamAsString(); - - /** Reads from the stream and appends the data to a MemoryBlock. - - @param destBlock the block to append the data onto - @param maxNumBytesToRead if this is a positive value, it sets a limit to the number - of bytes that will be read - if it's negative, data - will be read until the stream is exhausted. - @returns the number of bytes that were added to the memory block - */ - virtual int readIntoMemoryBlock (MemoryBlock& destBlock, - int maxNumBytesToRead = -1); - - /** Returns the offset of the next byte that will be read from the stream. - - @see setPosition - */ - virtual int64 getPosition() = 0; - - /** Tries to move the current read position of the stream. - - The position is an absolute number of bytes from the stream's start. - - Some streams might not be able to do this, in which case they should do - nothing and return false. Others might be able to manage it by resetting - themselves and skipping to the correct position, although this is - obviously a bit slow. - - @returns true if the stream manages to reposition itself correctly - @see getPosition - */ - virtual bool setPosition (int64 newPosition) = 0; - - /** Reads and discards a number of bytes from the stream. - - Some input streams might implement this efficiently, but the base - class will just keep reading data until the requisite number of bytes - have been done. - */ - virtual void skipNextBytes (int64 numBytesToSkip); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - InputStream() throw() {} + InputStream() throw() {} }; #endif // __JUCE_INPUTSTREAM_JUCEHEADER__ /********* End of inlined file: juce_InputStream.h *********/ -/** - The base class for streams that write data to some kind of destination. - - Input and output streams are used throughout the library - subclasses can override - some or all of the virtual functions to implement their behaviour. - - @see InputStream, MemoryOutputStream, FileOutputStream -*/ class JUCE_API OutputStream { public: - /** Destructor. + virtual ~OutputStream(); - Some subclasses might want to do things like call flush() during their - destructors. - */ - virtual ~OutputStream(); + virtual void flush() = 0; - /** If the stream is using a buffer, this will ensure it gets written - out to the destination. */ - virtual void flush() = 0; + virtual bool setPosition (int64 newPosition) = 0; - /** Tries to move the stream's output position. + virtual int64 getPosition() = 0; - Not all streams will be able to seek to a new position - this will return - false if it fails to work. + virtual bool write (const void* dataToWrite, + int howManyBytes) = 0; - @see getPosition - */ - virtual bool setPosition (int64 newPosition) = 0; + virtual void writeByte (char byte); - /** Returns the stream's current position. + virtual void writeBool (bool boolValue); - @see setPosition - */ - virtual int64 getPosition() = 0; + virtual void writeShort (short value); - /** Writes a block of data to the stream. + virtual void writeShortBigEndian (short value); - When creating a subclass of OutputStream, this is the only write method - that needs to be overloaded - the base class has methods for writing other - types of data which use this to do the work. + virtual void writeInt (int value); - @returns false if the write operation fails for some reason - */ - virtual bool write (const void* dataToWrite, - int howManyBytes) = 0; + virtual void writeIntBigEndian (int value); - /** Writes a single byte to the stream. + virtual void writeInt64 (int64 value); - @see InputStream::readByte - */ - virtual void writeByte (char byte); + virtual void writeInt64BigEndian (int64 value); - /** Writes a boolean to the stream. + virtual void writeFloat (float value); - This is encoded as a byte - either 1 or 0. + virtual void writeFloatBigEndian (float value); - @see InputStream::readBool - */ - virtual void writeBool (bool boolValue); + virtual void writeDouble (double value); - /** Writes a 16-bit integer to the stream in a little-endian byte order. + virtual void writeDoubleBigEndian (double value); - This will write two bytes to the stream: (value & 0xff), then (value >> 8). + virtual void writeCompressedInt (int value); - @see InputStream::readShort - */ - virtual void writeShort (short value); + virtual void writeString (const String& text); - /** Writes a 16-bit integer to the stream in a big-endian byte order. + virtual void writeText (const String& text, + const bool asUnicode, + const bool writeUnicodeHeaderBytes); - This will write two bytes to the stream: (value >> 8), then (value & 0xff). + virtual void printf (const char* format, ...); - @see InputStream::readShortBigEndian - */ - virtual void writeShortBigEndian (short value); + virtual int writeFromInputStream (InputStream& source, + int maxNumBytesToWrite); - /** Writes a 32-bit integer to the stream in a little-endian byte order. + virtual OutputStream& operator<< (const int number); - @see InputStream::readInt - */ - virtual void writeInt (int value); + virtual OutputStream& operator<< (const double number); - /** Writes a 32-bit integer to the stream in a big-endian byte order. + virtual OutputStream& operator<< (const char character); - @see InputStream::readIntBigEndian - */ - virtual void writeIntBigEndian (int value); + virtual OutputStream& operator<< (const char* const text); - /** Writes a 64-bit integer to the stream in a little-endian byte order. + virtual OutputStream& operator<< (const juce_wchar* const text); - @see InputStream::readInt64 - */ - virtual void writeInt64 (int64 value); + virtual OutputStream& operator<< (const String& text); - /** Writes a 64-bit integer to the stream in a big-endian byte order. - - @see InputStream::readInt64BigEndian - */ - virtual void writeInt64BigEndian (int64 value); - - /** Writes a 32-bit floating point value to the stream. - - The binary 32-bit encoding of the float is written as a little-endian int. - - @see InputStream::readFloat - */ - virtual void writeFloat (float value); - - /** Writes a 32-bit floating point value to the stream. - - The binary 32-bit encoding of the float is written as a big-endian int. - - @see InputStream::readFloatBigEndian - */ - virtual void writeFloatBigEndian (float value); - - /** Writes a 64-bit floating point value to the stream. - - The eight raw bytes of the double value are written out as a little-endian 64-bit int. - - @see InputStream::readDouble - */ - virtual void writeDouble (double value); - - /** Writes a 64-bit floating point value to the stream. - - The eight raw bytes of the double value are written out as a big-endian 64-bit int. - - @see InputStream::readDoubleBigEndian - */ - virtual void writeDoubleBigEndian (double value); - - /** Writes a condensed encoding of a 32-bit integer. - - If you're storing a lot of integers which are unlikely to have very large values, - this can save a lot of space, because values under 0xff will only take up 2 bytes, - under 0xffff only 3 bytes, etc. - - The format used is: number of significant bytes + up to 4 bytes in little-endian order. - - @see InputStream::readCompressedInt - */ - virtual void writeCompressedInt (int value); - - /** Stores a string in the stream. - - This isn't the method to use if you're trying to append text to the end of a - text-file! It's intended for storing a string for later retrieval - by InputStream::readString. - - It writes the string to the stream as UTF8, with a null character terminating it. - - For appending text to a file, instead use writeText, printf, or operator<< - - @see InputStream::readString, writeText, printf, operator<< - */ - virtual void writeString (const String& text); - - /** Writes a string of text to the stream. - - It can either write it as 8-bit system-encoded characters, or as unicode, and - can also add unicode header bytes (0xff, 0xfe) to indicate the endianness (this - should only be done at the start of a file). - - The method also replaces '\\n' characters in the text with '\\r\\n'. - */ - virtual void writeText (const String& text, - const bool asUnicode, - const bool writeUnicodeHeaderBytes); - - /** Writes a string of text to the stream. - - @see writeText - */ - virtual void printf (const char* format, ...); - - /** Reads data from an input stream and writes it to this stream. - - @param source the stream to read from - @param maxNumBytesToWrite the number of bytes to read from the stream (if this is - less than zero, it will keep reading until the input - is exhausted) - */ - virtual int writeFromInputStream (InputStream& source, - int maxNumBytesToWrite); - - /** Writes a number to the stream as 8-bit characters in the default system encoding. */ - virtual OutputStream& operator<< (const int number); - - /** Writes a number to the stream as 8-bit characters in the default system encoding. */ - virtual OutputStream& operator<< (const double number); - - /** Writes a character to the stream. */ - virtual OutputStream& operator<< (const char character); - - /** Writes a null-terminated string to the stream. */ - virtual OutputStream& operator<< (const char* const text); - - /** Writes a null-terminated unicode text string to the stream, converting it - to 8-bit characters in the default system encoding. */ - virtual OutputStream& operator<< (const juce_wchar* const text); - - /** Writes a string to the stream as 8-bit characters in the default system encoding. */ - virtual OutputStream& operator<< (const String& text); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - OutputStream() throw(); + OutputStream() throw(); }; #endif // __JUCE_OUTPUTSTREAM_JUCEHEADER__ @@ -6799,515 +3682,187 @@ protected: #ifndef __JUCE_RELATIVETIME_JUCEHEADER__ #define __JUCE_RELATIVETIME_JUCEHEADER__ -/** A relative measure of time. - - The time is stored as a number of seconds, at double-precision floating - point accuracy, and may be positive or negative. - - If you need an absolute time, (i.e. a date + time), see the Time class. -*/ class JUCE_API RelativeTime { public: - /** Creates a RelativeTime. + explicit RelativeTime (const double seconds = 0.0) throw(); - @param seconds the number of seconds, which may be +ve or -ve. - @see milliseconds, minutes, hours, days, weeks - */ - explicit RelativeTime (const double seconds = 0.0) throw(); + RelativeTime (const RelativeTime& other) throw(); - /** Copies another relative time. */ - RelativeTime (const RelativeTime& other) throw(); + const RelativeTime& operator= (const RelativeTime& other) throw(); - /** Copies another relative time. */ - const RelativeTime& operator= (const RelativeTime& other) throw(); + ~RelativeTime() throw(); - /** Destructor. */ - ~RelativeTime() throw(); + static const RelativeTime milliseconds (const int milliseconds) throw(); - /** Creates a new RelativeTime object representing a number of milliseconds. + static const RelativeTime milliseconds (const int64 milliseconds) throw(); - @see minutes, hours, days, weeks - */ - static const RelativeTime milliseconds (const int milliseconds) throw(); + static const RelativeTime minutes (const double numberOfMinutes) throw(); - /** Creates a new RelativeTime object representing a number of milliseconds. + static const RelativeTime hours (const double numberOfHours) throw(); - @see minutes, hours, days, weeks - */ - static const RelativeTime milliseconds (const int64 milliseconds) throw(); + static const RelativeTime days (const double numberOfDays) throw(); - /** Creates a new RelativeTime object representing a number of minutes. + static const RelativeTime weeks (const double numberOfWeeks) throw(); - @see milliseconds, hours, days, weeks - */ - static const RelativeTime minutes (const double numberOfMinutes) throw(); + int64 inMilliseconds() const throw(); - /** Creates a new RelativeTime object representing a number of hours. + double inSeconds() const throw() { return seconds; } - @see milliseconds, minutes, days, weeks - */ - static const RelativeTime hours (const double numberOfHours) throw(); + double inMinutes() const throw(); - /** Creates a new RelativeTime object representing a number of days. + double inHours() const throw(); - @see milliseconds, minutes, hours, weeks - */ - static const RelativeTime days (const double numberOfDays) throw(); + double inDays() const throw(); - /** Creates a new RelativeTime object representing a number of weeks. + double inWeeks() const throw(); - @see milliseconds, minutes, hours, days - */ - static const RelativeTime weeks (const double numberOfWeeks) throw(); + const String getDescription (const String& returnValueForZeroTime = JUCE_T("0")) const throw(); - /** Returns the number of milliseconds this time represents. + bool operator== (const RelativeTime& other) const throw(); + bool operator!= (const RelativeTime& other) const throw(); - @see milliseconds, inSeconds, inMinutes, inHours, inDays, inWeeks - */ - int64 inMilliseconds() const throw(); + bool operator> (const RelativeTime& other) const throw(); + bool operator< (const RelativeTime& other) const throw(); + bool operator>= (const RelativeTime& other) const throw(); + bool operator<= (const RelativeTime& other) const throw(); - /** Returns the number of seconds this time represents. + const RelativeTime operator+ (const RelativeTime& timeToAdd) const throw(); + const RelativeTime operator- (const RelativeTime& timeToSubtract) const throw(); - @see inMilliseconds, inMinutes, inHours, inDays, inWeeks - */ - double inSeconds() const throw() { return seconds; } + const RelativeTime operator+ (const double secondsToAdd) const throw(); + const RelativeTime operator- (const double secondsToSubtract) const throw(); - /** Returns the number of minutes this time represents. + const RelativeTime& operator+= (const RelativeTime& timeToAdd) throw(); + const RelativeTime& operator-= (const RelativeTime& timeToSubtract) throw(); - @see inMilliseconds, inSeconds, inHours, inDays, inWeeks - */ - double inMinutes() const throw(); + const RelativeTime& operator+= (const double secondsToAdd) throw(); - /** Returns the number of hours this time represents. + const RelativeTime& operator-= (const double secondsToSubtract) throw(); - @see inMilliseconds, inSeconds, inMinutes, inDays, inWeeks - */ - double inHours() const throw(); - - /** Returns the number of days this time represents. - - @see inMilliseconds, inSeconds, inMinutes, inHours, inWeeks - */ - double inDays() const throw(); - - /** Returns the number of weeks this time represents. - - @see inMilliseconds, inSeconds, inMinutes, inHours, inDays - */ - double inWeeks() const throw(); - - /** Returns a readable textual description of the time. - - The exact format of the string returned will depend on - the magnitude of the time - e.g. - - "1 min 4 secs", "1 hr 45 mins", "2 weeks 5 days", "140 ms" - - so that only the two most significant units are printed. - - The returnValueForZeroTime value is the result that is returned if the - length is zero. Depending on your application you might want to use this - to return something more relevant like "empty" or "0 secs", etc. - - @see inMilliseconds, inSeconds, inMinutes, inHours, inDays, inWeeks - */ - const String getDescription (const String& returnValueForZeroTime = JUCE_T("0")) const throw(); - - /** Compares two RelativeTimes. */ - bool operator== (const RelativeTime& other) const throw(); - /** Compares two RelativeTimes. */ - bool operator!= (const RelativeTime& other) const throw(); - - /** Compares two RelativeTimes. */ - bool operator> (const RelativeTime& other) const throw(); - /** Compares two RelativeTimes. */ - bool operator< (const RelativeTime& other) const throw(); - /** Compares two RelativeTimes. */ - bool operator>= (const RelativeTime& other) const throw(); - /** Compares two RelativeTimes. */ - bool operator<= (const RelativeTime& other) const throw(); - - /** Adds another RelativeTime to this one and returns the result. */ - const RelativeTime operator+ (const RelativeTime& timeToAdd) const throw(); - /** Subtracts another RelativeTime from this one and returns the result. */ - const RelativeTime operator- (const RelativeTime& timeToSubtract) const throw(); - - /** Adds a number of seconds to this RelativeTime and returns the result. */ - const RelativeTime operator+ (const double secondsToAdd) const throw(); - /** Subtracts a number of seconds from this RelativeTime and returns the result. */ - const RelativeTime operator- (const double secondsToSubtract) const throw(); - - /** Adds another RelativeTime to this one. */ - const RelativeTime& operator+= (const RelativeTime& timeToAdd) throw(); - /** Subtracts another RelativeTime from this one. */ - const RelativeTime& operator-= (const RelativeTime& timeToSubtract) throw(); - - /** Adds a number of seconds to this time. */ - const RelativeTime& operator+= (const double secondsToAdd) throw(); - - /** Subtracts a number of seconds from this time. */ - const RelativeTime& operator-= (const double secondsToSubtract) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - double seconds; + double seconds; }; #endif // __JUCE_RELATIVETIME_JUCEHEADER__ /********* End of inlined file: juce_RelativeTime.h *********/ -/** - Holds an absolute date and time. - - Internally, the time is stored at millisecond precision. - - @see RelativeTime -*/ class JUCE_API Time { public: - /** Creates a Time object. + Time() throw(); - This default constructor creates a time of 1st January 1970, (which is - represented internally as 0ms). + Time (const Time& other) throw(); - To create a time object representing the current time, use getCurrentTime(). + Time (const int64 millisecondsSinceEpoch) throw(); - @see getCurrentTime - */ - Time() throw(); + Time (const int year, + const int month, + const int day, + const int hours, + const int minutes, + const int seconds = 0, + const int milliseconds = 0, + const bool useLocalTime = true) throw(); - /** Creates a copy of another Time object. */ - Time (const Time& other) throw(); + ~Time() throw(); - /** Creates a time based on a number of milliseconds. + const Time& operator= (const Time& other) throw(); - The internal millisecond count is set to 0 (1st January 1970). To create a - time object set to the current time, use getCurrentTime(). + static const Time JUCE_CALLTYPE getCurrentTime() throw(); - @param millisecondsSinceEpoch the number of milliseconds since the unix - 'epoch' (midnight Jan 1st 1970). - @see getCurrentTime, currentTimeMillis - */ - Time (const int64 millisecondsSinceEpoch) throw(); + int64 toMilliseconds() const throw() { return millisSinceEpoch; } - /** Creates a time from a set of date components. + int getYear() const throw(); - The timezone is assumed to be whatever the system is using as its locale. + int getMonth() const throw(); - @param year the year, in 4-digit format, e.g. 2004 - @param month the month, in the range 0 to 11 - @param day the day of the month, in the range 1 to 31 - @param hours hours in 24-hour clock format, 0 to 23 - @param minutes minutes 0 to 59 - @param seconds seconds 0 to 59 - @param milliseconds milliseconds 0 to 999 - @param useLocalTime if true, encode using the current machine's local time; if - false, it will always work in GMT. - */ - Time (const int year, - const int month, - const int day, - const int hours, - const int minutes, - const int seconds = 0, - const int milliseconds = 0, - const bool useLocalTime = true) throw(); + const String getMonthName (const bool threeLetterVersion) const throw(); - /** Destructor. */ - ~Time() throw(); + int getDayOfMonth() const throw(); - /** Copies this time from another one. */ - const Time& operator= (const Time& other) throw(); + int getDayOfWeek() const throw(); - /** Returns a Time object that is set to the current system time. + const String getWeekdayName (const bool threeLetterVersion) const throw(); - @see currentTimeMillis - */ - static const Time JUCE_CALLTYPE getCurrentTime() throw(); + int getHours() const throw(); - /** Returns the time as a number of milliseconds. + bool isAfternoon() const throw(); - @returns the number of milliseconds this Time object represents, since - midnight jan 1st 1970. - @see getMilliseconds - */ - int64 toMilliseconds() const throw() { return millisSinceEpoch; } + int getHoursInAmPmFormat() const throw(); - /** Returns the year. + int getMinutes() const throw(); - A 4-digit format is used, e.g. 2004. - */ - int getYear() const throw(); + int getSeconds() const throw(); - /** Returns the number of the month. + int getMilliseconds() const throw(); - The value returned is in the range 0 to 11. - @see getMonthName - */ - int getMonth() const throw(); + bool isDaylightSavingTime() const throw(); - /** Returns the name of the month. + const String getTimeZone() const throw(); - @param threeLetterVersion if true, it'll be a 3-letter abbreviation, e.g. "Jan"; if false - it'll return the long form, e.g. "January" - @see getMonth - */ - const String getMonthName (const bool threeLetterVersion) const throw(); + const String toString (const bool includeDate, + const bool includeTime, + const bool includeSeconds = true, + const bool use24HourClock = false) const throw(); - /** Returns the day of the month. + const String formatted (const tchar* const format) const throw(); - The value returned is in the range 1 to 31. - */ - int getDayOfMonth() const throw(); + const Time operator+ (const RelativeTime& delta) const throw() { return Time (millisSinceEpoch + delta.inMilliseconds()); } - /** Returns the number of the day of the week. + const Time operator- (const RelativeTime& delta) const throw() { return Time (millisSinceEpoch - delta.inMilliseconds()); } - The value returned is in the range 0 to 6 (0 = sunday, 1 = monday, etc). - */ - int getDayOfWeek() const throw(); + const RelativeTime operator- (const Time& other) const throw() { return RelativeTime::milliseconds (millisSinceEpoch - other.millisSinceEpoch); } - /** Returns the name of the weekday. + bool operator== (const Time& other) const throw() { return millisSinceEpoch == other.millisSinceEpoch; } - @param threeLetterVersion if true, it'll return a 3-letter abbreviation, e.g. "Tue"; if - false, it'll return the full version, e.g. "Tuesday". - */ - const String getWeekdayName (const bool threeLetterVersion) const throw(); + bool operator!= (const Time& other) const throw() { return millisSinceEpoch != other.millisSinceEpoch; } - /** Returns the number of hours since midnight. + bool operator< (const Time& other) const throw() { return millisSinceEpoch < other.millisSinceEpoch; } - This is in 24-hour clock format, in the range 0 to 23. + bool operator<= (const Time& other) const throw() { return millisSinceEpoch <= other.millisSinceEpoch; } - @see getHoursInAmPmFormat, isAfternoon - */ - int getHours() const throw(); + bool operator> (const Time& other) const throw() { return millisSinceEpoch > other.millisSinceEpoch; } - /** Returns true if the time is in the afternoon. + bool operator>= (const Time& other) const throw() { return millisSinceEpoch >= other.millisSinceEpoch; } - So it returns true for "PM", false for "AM". + bool setSystemTimeToThisTime() const throw(); - @see getHoursInAmPmFormat, getHours - */ - bool isAfternoon() const throw(); + static const String getWeekdayName (int dayNumber, + const bool threeLetterVersion) throw(); - /** Returns the hours in 12-hour clock format. + static const String getMonthName (int monthNumber, + const bool threeLetterVersion) throw(); - This will return a value 1 to 12 - use isAfternoon() to find out - whether this is in the afternoon or morning. + // Static methods for getting system timers directly.. - @see getHours, isAfternoon - */ - int getHoursInAmPmFormat() const throw(); + static int64 currentTimeMillis() throw(); - /** Returns the number of minutes, 0 to 59. */ - int getMinutes() const throw(); + static uint32 getMillisecondCounter() throw(); - /** Returns the number of seconds, 0 to 59. */ - int getSeconds() const throw(); + static double getMillisecondCounterHiRes() throw(); - /** Returns the number of milliseconds, 0 to 999. + static void waitForMillisecondCounter (const uint32 targetTime) throw(); - Unlike toMilliseconds(), this just returns the position within the - current second rather than the total number since the epoch. + static uint32 getApproximateMillisecondCounter() throw(); - @see toMilliseconds - */ - int getMilliseconds() const throw(); + // High-resolution timers.. - /** Returns true if the local timezone uses a daylight saving correction. */ - bool isDaylightSavingTime() const throw(); + static int64 getHighResolutionTicks() throw(); - /** Returns a 3-character string to indicate the local timezone. */ - const String getTimeZone() const throw(); + static int64 getHighResolutionTicksPerSecond() throw(); - /** Quick way of getting a string version of a date and time. + static double highResolutionTicksToSeconds (const int64 ticks) throw(); - For a more powerful way of formatting the date and time, see the formatted() method. - - @param includeDate whether to include the date in the string - @param includeTime whether to include the time in the string - @param includeSeconds if the time is being included, this provides an option not to include - the seconds in it - @param use24HourClock if the time is being included, sets whether to use am/pm or 24 - hour notation. - @see formatted - */ - const String toString (const bool includeDate, - const bool includeTime, - const bool includeSeconds = true, - const bool use24HourClock = false) const throw(); - - /** Converts this date/time to a string with a user-defined format. - - This uses the C strftime() function to format this time as a string. To save you - looking it up, these are the escape codes that strftime uses (other codes might - work on some platforms and not others, but these are the common ones): - - %a is replaced by the locale's abbreviated weekday name. - %A is replaced by the locale's full weekday name. - %b is replaced by the locale's abbreviated month name. - %B is replaced by the locale's full month name. - %c is replaced by the locale's appropriate date and time representation. - %d is replaced by the day of the month as a decimal number [01,31]. - %H is replaced by the hour (24-hour clock) as a decimal number [00,23]. - %I is replaced by the hour (12-hour clock) as a decimal number [01,12]. - %j is replaced by the day of the year as a decimal number [001,366]. - %m is replaced by the month as a decimal number [01,12]. - %M is replaced by the minute as a decimal number [00,59]. - %p is replaced by the locale's equivalent of either a.m. or p.m. - %S is replaced by the second as a decimal number [00,61]. - %U is replaced by the week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. - %w is replaced by the weekday as a decimal number [0,6], with 0 representing Sunday. - %W is replaced by the week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. - %x is replaced by the locale's appropriate date representation. - %X is replaced by the locale's appropriate time representation. - %y is replaced by the year without century as a decimal number [00,99]. - %Y is replaced by the year with century as a decimal number. - %Z is replaced by the timezone name or abbreviation, or by no bytes if no timezone information exists. - %% is replaced by %. - - @see toString - */ - const String formatted (const tchar* const format) const throw(); - - /** Adds a RelativeTime to this time and returns the result. */ - const Time operator+ (const RelativeTime& delta) const throw() { return Time (millisSinceEpoch + delta.inMilliseconds()); } - - /** Subtracts a RelativeTime from this time and returns the result. */ - const Time operator- (const RelativeTime& delta) const throw() { return Time (millisSinceEpoch - delta.inMilliseconds()); } - - /** Returns the relative time difference between this time and another one. */ - const RelativeTime operator- (const Time& other) const throw() { return RelativeTime::milliseconds (millisSinceEpoch - other.millisSinceEpoch); } - - /** Compares two Time objects. */ - bool operator== (const Time& other) const throw() { return millisSinceEpoch == other.millisSinceEpoch; } - - /** Compares two Time objects. */ - bool operator!= (const Time& other) const throw() { return millisSinceEpoch != other.millisSinceEpoch; } - - /** Compares two Time objects. */ - bool operator< (const Time& other) const throw() { return millisSinceEpoch < other.millisSinceEpoch; } - - /** Compares two Time objects. */ - bool operator<= (const Time& other) const throw() { return millisSinceEpoch <= other.millisSinceEpoch; } - - /** Compares two Time objects. */ - bool operator> (const Time& other) const throw() { return millisSinceEpoch > other.millisSinceEpoch; } - - /** Compares two Time objects. */ - bool operator>= (const Time& other) const throw() { return millisSinceEpoch >= other.millisSinceEpoch; } - - /** Tries to set the computer's clock. - - @returns true if this succeeds, although depending on the system, the - application might not have sufficient privileges to do this. - */ - bool setSystemTimeToThisTime() const throw(); - - /** Returns the name of a day of the week. - - @param dayNumber the day, 0 to 6 (0 = sunday, 1 = monday, etc) - @param threeLetterVersion if true, it'll return a 3-letter abbreviation, e.g. "Tue"; if - false, it'll return the full version, e.g. "Tuesday". - */ - static const String getWeekdayName (int dayNumber, - const bool threeLetterVersion) throw(); - - /** Returns the name of one of the months. - - @param monthNumber the month, 0 to 11 - @param threeLetterVersion if true, it'll be a 3-letter abbreviation, e.g. "Jan"; if false - it'll return the long form, e.g. "January" - */ - static const String getMonthName (int monthNumber, - const bool threeLetterVersion) throw(); - - // Static methods for getting system timers directly.. - - /** Returns the current system time. - - Returns the number of milliseconds since midnight jan 1st 1970. - - Should be accurate to within a few millisecs, depending on platform, - hardware, etc. - */ - static int64 currentTimeMillis() throw(); - - /** Returns the number of millisecs since system startup. - - Should be accurate to within a few millisecs, depending on platform, - hardware, etc. - - @see getApproximateMillisecondCounter - */ - static uint32 getMillisecondCounter() throw(); - - /** Returns the number of millisecs since system startup. - - Same as getMillisecondCounter(), but returns a more accurate value, using - the high-res timer. - - @see getMillisecondCounter - */ - static double getMillisecondCounterHiRes() throw(); - - /** Waits until the getMillisecondCounter() reaches a given value. - - This will make the thread sleep as efficiently as it can while it's waiting. - */ - static void waitForMillisecondCounter (const uint32 targetTime) throw(); - - /** Less-accurate but faster version of getMillisecondCounter(). - - This will return the last value that getMillisecondCounter() returned, so doesn't - need to make a system call, but is less accurate - it shouldn't be more than - 100ms away from the correct time, though, so is still accurate enough for a - lot of purposes. - - @see getMillisecondCounter - */ - static uint32 getApproximateMillisecondCounter() throw(); - - // High-resolution timers.. - - /** Returns the current high-resolution counter's tick-count. - - This is a similar idea to getMillisecondCounter(), but with a higher - resolution. - - @see getHighResolutionTicksPerSecond, highResolutionTicksToSeconds, - secondsToHighResolutionTicks - */ - static int64 getHighResolutionTicks() throw(); - - /** Returns the resolution of the high-resolution counter in ticks per second. - - @see getHighResolutionTicks, highResolutionTicksToSeconds, - secondsToHighResolutionTicks - */ - static int64 getHighResolutionTicksPerSecond() throw(); - - /** Converts a number of high-resolution ticks into seconds. - - @see getHighResolutionTicks, getHighResolutionTicksPerSecond, - secondsToHighResolutionTicks - */ - static double highResolutionTicksToSeconds (const int64 ticks) throw(); - - /** Converts a number seconds into high-resolution ticks. - - @see getHighResolutionTicks, getHighResolutionTicksPerSecond, - highResolutionTicksToSeconds - */ - static int64 secondsToHighResolutionTicks (const double seconds) throw(); + static int64 secondsToHighResolutionTicks (const double seconds) throw(); private: - int64 millisSinceEpoch; + int64 millisSinceEpoch; }; #endif // __JUCE_TIME_JUCEHEADER__ @@ -7316,1740 +3871,493 @@ private: class FileInputStream; class FileOutputStream; -/** - Represents a local file or directory. - - This class encapsulates the absolute pathname of a file or directory, and - has methods for finding out about the file and changing its properties. - - To read or write to the file, there are methods for returning an input or - output stream. - - @see FileInputStream, FileOutputStream -*/ class JUCE_API File { public: - /** Creates an (invalid) file object. + File() {} - The file is initially set to an empty path, so getFullPath() will return - an empty string, and comparing the file to File::nonexistent will return - true. + File (const String& path); - You can use its operator= method to point it at a proper file. - */ - File() {} + File (const File& other); - /** Creates a file from an absolute path. + ~File() {} - If the path supplied is a relative path, it is taken to be relative - to the current working directory (see File::getCurrentWorkingDirectory()), - but this isn't a recommended way of creating a file, because you - never know what the CWD is going to be. + const File& operator= (const String& newFilePath); - On the Mac/Linux, the path can include "~" notation for referring to - user home directories. - */ - File (const String& path); + const File& operator= (const File& otherFile); - /** Creates a copy of another file object. */ - File (const File& other); + static const File nonexistent; - /** Destructor. */ - ~File() {} + bool exists() const; - /** Sets the file based on an absolute pathname. + bool existsAsFile() const; - If the path supplied is a relative path, it is taken to be relative - to the current working directory (see File::getCurrentWorkingDirectory()), - but this isn't a recommended way of creating a file, because you - never know what the CWD is going to be. + bool isDirectory() const; - On the Mac/Linux, the path can include "~" notation for referring to - user home directories. - */ - const File& operator= (const String& newFilePath); + int64 getSize() const; - /** Copies from another file object. */ - const File& operator= (const File& otherFile); + static const String descriptionOfSizeInBytes (const int64 bytes); - /** This static constant is used for referring to an 'invalid' file. */ - static const File nonexistent; + const String& getFullPathName() const { return fullPath; } - /** Checks whether the file actually exists. + const String getFileName() const; - @returns true if the file exists, either as a file or a directory. - @see existsAsFile, isDirectory - */ - bool exists() const; + const String getRelativePathFrom (const File& directoryToBeRelativeTo) const; - /** Checks whether the file exists and is a file rather than a directory. + const String getFileExtension() const; - @returns true only if this is a real file, false if it's a directory - or doesn't exist - @see exists, isDirectory - */ - bool existsAsFile() const; + bool hasFileExtension (const String& extensionToTest) const; - /** Checks whether the file is a directory that exists. + const File withFileExtension (const String& newExtension) const; - @returns true only if the file is a directory which actually exists, so - false if it's a file or doesn't exist at all - @see exists, existsAsFile - */ - bool isDirectory() const; + const String getFileNameWithoutExtension() const; - /** Returns the size of the file in bytes. + int hashCode() const; - @returns the number of bytes in the file, or 0 if it doesn't exist. - */ - int64 getSize() const; + int64 hashCode64() const; - /** Utility function to convert a file size in bytes to a neat string description. + const File getChildFile (String relativePath) const; - So for example 100 would return "100 bytes", 2000 would return "2 KB", - 2000000 would produce "2 MB", etc. - */ - static const String descriptionOfSizeInBytes (const int64 bytes); + const File getSiblingFile (const String& siblingFileName) const; - /** Returns the complete, absolute path of this file. + const File getParentDirectory() const; - This includes the filename and all its parent folders. On Windows it'll - also include the drive letter prefix; on Mac or Linux it'll be a complete - path starting from the root folder. + bool isAChildOf (const File& potentialParentDirectory) const; - If you just want the file's name, you should use getFileName() or - getFileNameWithoutExtension(). + const File getNonexistentChildFile (const String& prefix, + const String& suffix, + bool putNumbersInBrackets = true) const; - @see getFileName, getRelativePathFrom - */ - const String& getFullPathName() const { return fullPath; } + const File getNonexistentSibling (const bool putNumbersInBrackets = true) const; - /** Returns the last section of the pathname. + bool operator== (const File& otherFile) const; + bool operator!= (const File& otherFile) const; - Returns just the final part of the path - e.g. if the whole path - is "/moose/fish/foo.txt" this will return "foo.txt". + bool hasWriteAccess() const; - For a directory, it returns the final part of the path - e.g. for the - directory "/moose/fish" it'll return "fish". + bool setReadOnly (const bool shouldBeReadOnly, + const bool applyRecursively = false) const; - If the filename begins with a dot, it'll return the whole filename, e.g. for - "/moose/.fish", it'll return ".fish" + bool isHidden() const; - @see getFullPathName, getFileNameWithoutExtension - */ - const String getFileName() const; + const File getLinkedTarget() const; - /** Creates a relative path that refers to a file relatively to a given directory. + const Time getLastModificationTime() const; - e.g. File ("/moose/foo.txt").getRelativePathFrom ("/moose/fish/haddock") - would return "../../foo.txt". + const Time getLastAccessTime() const; - If it's not possible to navigate from one file to the other, an absolute - path is returned. If the paths are invalid, an empty string may also be - returned. + const Time getCreationTime() const; - @param directoryToBeRelativeTo the directory which the resultant string will - be relative to. If this is actually a file rather than - a directory, its parent directory will be used instead. - If it doesn't exist, it's assumed to be a directory. - @see getChildFile, isAbsolutePath - */ - const String getRelativePathFrom (const File& directoryToBeRelativeTo) const; + bool setLastModificationTime (const Time& newTime) const; - /** Returns the file's extension. + bool setLastAccessTime (const Time& newTime) const; - Returns the file extension of this file, also including the dot. + bool setCreationTime (const Time& newTime) const; - e.g. "/moose/fish/foo.txt" would return ".txt" + const String getVersion() const; - @see hasFileExtension, withFileExtension, getFileNameWithoutExtension - */ - const String getFileExtension() const; + bool create() const; - /** Checks whether the file has a given extension. + bool createDirectory() const; - @param extensionToTest the extension to look for - it doesn't matter whether or - not this string has a dot at the start, so ".wav" and "wav" - will have the same effect. The comparison used is - case-insensitve. To compare with multiple extensions, this - parameter can contain multiple strings, separated by semi-colons - - so, for example: hasFileExtension (".jpeg;png;gif") would return - true if the file has any of those three extensions. + bool deleteFile() const; - @see getFileExtension, withFileExtension, getFileNameWithoutExtension - */ - bool hasFileExtension (const String& extensionToTest) const; + bool deleteRecursively() const; - /** Returns a version of this file with a different file extension. + bool moveToTrash() const; - e.g. File ("/moose/fish/foo.txt").withFileExtension ("html") returns "/moose/fish/foo.html" + bool moveFileTo (const File& targetLocation) const; - @param newExtension the new extension, either with or without a dot at the start (this - doesn't make any difference). To get remove a file's extension altogether, - pass an empty string into this function. + bool copyFileTo (const File& targetLocation) const; - @see getFileName, getFileExtension, hasFileExtension, getFileNameWithoutExtension - */ - const File withFileExtension (const String& newExtension) const; + bool copyDirectoryTo (const File& newDirectory) const; - /** Returns the last part of the filename, without its file extension. + enum TypesOfFileToFind + { + findDirectories = 1, /**< Use this flag to indicate that you want to find directories. */ + findFiles = 2, /**< Use this flag to indicate that you want to find files. */ + findFilesAndDirectories = 3, /**< Use this flag to indicate that you want to find both files and directories. */ + ignoreHiddenFiles = 4 /**< Add this flag to avoid returning any hidden files in the results. */ + }; - e.g. for "/moose/fish/foo.txt" this will return "foo". + int findChildFiles (OwnedArray& results, + const int whatToLookFor, + const bool searchRecursively, + const String& wildCardPattern = JUCE_T("*")) const; - @see getFileName, getFileExtension, hasFileExtension, withFileExtension - */ - const String getFileNameWithoutExtension() const; + int getNumberOfChildFiles (const int whatToLookFor, + const String& wildCardPattern = JUCE_T("*")) const; - /** Returns a 32-bit hash-code that identifies this file. + bool containsSubDirectories() const; - This is based on the filename. Obviously it's possible, although unlikely, that - two files will have the same hash-code. - */ - int hashCode() const; + FileInputStream* createInputStream() const; - /** Returns a 64-bit hash-code that identifies this file. + FileOutputStream* createOutputStream (const int bufferSize = 0x8000) const; - This is based on the filename. Obviously it's possible, although unlikely, that - two files will have the same hash-code. - */ - int64 hashCode64() const; + bool loadFileAsData (MemoryBlock& result) const; - /** Returns a file based on a relative path. + const String loadFileAsString() const; - This will find a child file or directory of the current object. + bool appendData (const void* const dataToAppend, + const int numberOfBytes) const; - e.g. - File ("/moose/fish").getChildFile ("foo.txt") will produce "/moose/fish/foo.txt". - File ("/moose/fish").getChildFile ("../foo.txt") will produce "/moose/foo.txt". + bool replaceWithData (const void* const dataToWrite, + const int numberOfBytes) const; - If the string is actually an absolute path, it will be treated as such, e.g. - File ("/moose/fish").getChildFile ("/foo.txt") will produce "/foo.txt" + bool appendText (const String& textToAppend, + const bool asUnicode = false, + const bool writeUnicodeHeaderBytes = false) const; - @see getSiblingFile, getParentDirectory, getRelativePathFrom, isAChildOf - */ - const File getChildFile (String relativePath) const; + bool replaceWithText (const String& textToWrite, + const bool asUnicode = false, + const bool writeUnicodeHeaderBytes = false) const; - /** Returns a file which is in the same directory as this one. + static void findFileSystemRoots (OwnedArray& results); - This is equivalent to getParentDirectory().getChildFile (name). + const String getVolumeLabel() const; - @see getChildFile, getParentDirectory - */ - const File getSiblingFile (const String& siblingFileName) const; + int getVolumeSerialNumber() const; - /** Returns the directory that contains this file or directory. + int64 getBytesFreeOnVolume() const; - e.g. for "/moose/fish/foo.txt" this will return "/moose/fish". - */ - const File getParentDirectory() const; + int64 getVolumeTotalSize() const; - /** Checks whether a file is somewhere inside a directory. + bool isOnCDRomDrive() const; - Returns true if this file is somewhere inside a subdirectory of the directory - that is passed in. Neither file actually has to exist, because the function - just checks the paths for similarities. + bool isOnHardDisk() const; - e.g. File ("/moose/fish/foo.txt").isAChildOf ("/moose") is true. - File ("/moose/fish/foo.txt").isAChildOf ("/moose/fish") is also true. - */ - bool isAChildOf (const File& potentialParentDirectory) const; + bool isOnRemovableDrive() const; - /** Chooses a filename relative to this one that doesn't already exist. + bool startAsProcess (const String& parameters = String::empty) const; - If this file is a directory, this will return a child file of this - directory that doesn't exist, by adding numbers to a prefix and suffix until - it finds one that isn't already there. + void revealToUser() const; - If the prefix + the suffix doesn't exist, it won't bother adding a number. + enum SpecialLocationType + { + userHomeDirectory, - e.g. File ("/moose/fish").getNonexistentChildFile ("foo", ".txt", true) might - return "/moose/fish/foo(2).txt" if there's already a file called "foo.txt". + userDocumentsDirectory, - @param prefix the string to use for the filename before the number - @param suffix the string to add to the filename after the number - @param putNumbersInBrackets if true, this will create filenames in the - format "prefix(number)suffix", if false, it will leave the - brackets out. - */ - const File getNonexistentChildFile (const String& prefix, - const String& suffix, - bool putNumbersInBrackets = true) const; + userDesktopDirectory, - /** Chooses a filename for a sibling file to this one that doesn't already exist. + userApplicationDataDirectory, - If this file doesn't exist, this will just return itself, otherwise it - will return an appropriate sibling that doesn't exist, e.g. if a file - "/moose/fish/foo.txt" exists, this might return "/moose/fish/foo(2).txt". + commonApplicationDataDirectory, - @param putNumbersInBrackets whether to add brackets around the numbers that - get appended to the new filename. - */ - const File getNonexistentSibling (const bool putNumbersInBrackets = true) const; + tempDirectory, - /** Compares the pathnames for two files. */ - bool operator== (const File& otherFile) const; - /** Compares the pathnames for two files. */ - bool operator!= (const File& otherFile) const; + currentExecutableFile, - /** Checks whether a file can be created or written to. + currentApplicationFile, - @returns true if it's possible to create and write to this file. If the file - doesn't already exist, this will check its parent directory to - see if writing is allowed. - @see setReadOnly - */ - bool hasWriteAccess() const; + invokedExecutableFile, - /** Changes the write-permission of a file or directory. + globalApplicationsDirectory, - @param shouldBeReadOnly whether to add or remove write-permission - @param applyRecursively if the file is a directory and this is true, it will - recurse through all the subfolders changing the permissions - of all files - @returns true if it manages to change the file's permissions. - @see hasWriteAccess - */ - bool setReadOnly (const bool shouldBeReadOnly, - const bool applyRecursively = false) const; + userMusicDirectory, - /** Returns true if this file is a hidden or system file. + userMoviesDirectory, + }; - The criteria for deciding whether a file is hidden are platform-dependent. - */ - bool isHidden() const; + static const File JUCE_CALLTYPE getSpecialLocation (const SpecialLocationType type); - /** If this file is a link, this returns the file that it points to. + static const File createTempFile (const String& fileNameEnding); - If this file isn't actually link, it'll just return itself. - */ - const File getLinkedTarget() const; + static const File getCurrentWorkingDirectory(); - /** Returns the last modification time of this file. + bool setAsCurrentWorkingDirectory() const; - @returns the time, or an invalid time if the file doesn't exist. - @see setLastModificationTime, getLastAccessTime, getCreationTime - */ - const Time getLastModificationTime() const; + static const tchar separator; - /** Returns the last time this file was accessed. + static const tchar* separatorString; - @returns the time, or an invalid time if the file doesn't exist. - @see setLastAccessTime, getLastModificationTime, getCreationTime - */ - const Time getLastAccessTime() const; + static const String createLegalFileName (const String& fileNameToFix); - /** Returns the time that this file was created. + static const String createLegalPathName (const String& pathNameToFix); - @returns the time, or an invalid time if the file doesn't exist. - @see getLastModificationTime, getLastAccessTime - */ - const Time getCreationTime() const; + static bool areFileNamesCaseSensitive(); - /** Changes the modification time for this file. + static bool isAbsolutePath (const String& path); - @param newTime the time to apply to the file - @returns true if it manages to change the file's time. - @see getLastModificationTime, setLastAccessTime, setCreationTime - */ - bool setLastModificationTime (const Time& newTime) const; - - /** Changes the last-access time for this file. - - @param newTime the time to apply to the file - @returns true if it manages to change the file's time. - @see getLastAccessTime, setLastModificationTime, setCreationTime - */ - bool setLastAccessTime (const Time& newTime) const; - - /** Changes the creation date for this file. - - @param newTime the time to apply to the file - @returns true if it manages to change the file's time. - @see getCreationTime, setLastModificationTime, setLastAccessTime - */ - bool setCreationTime (const Time& newTime) const; - - /** If possible, this will try to create a version string for the given file. - - The OS may be able to look at the file and give a version for it - e.g. with - executables, bundles, dlls, etc. If no version is available, this will - return an empty string. - */ - const String getVersion() const; - - /** Creates an empty file if it doesn't already exist. - - If the file that this object refers to doesn't exist, this will create a file - of zero size. - - If it already exists or is a directory, this method will do nothing. - - @returns true if the file has been created (or if it already existed). - @see createDirectory - */ - bool create() const; - - /** Creates a new directory for this filename. - - This will try to create the file as a directory, and fill also create - any parent directories it needs in order to complete the operation. - - @returns true if the directory has been created successfully, (or if it - already existed beforehand). - @see create - */ - bool createDirectory() const; - - /** Deletes a file. - - If this file is actually a directory, it may not be deleted correctly if it - contains files. See deleteRecursively() as a better way of deleting directories. - - @returns true if the file has been successfully deleted (or if it didn't exist to - begin with). - @see deleteRecursively - */ - bool deleteFile() const; - - /** Deletes a file or directory and all its subdirectories. - - If this file is a directory, this will try to delete it and all its subfolders. If - it's just a file, it will just try to delete the file. - - @returns true if the file and all its subfolders have been successfully deleted - (or if it didn't exist to begin with). - @see deleteFile - */ - bool deleteRecursively() const; - - /** Moves this file or folder to the trash. - - @returns true if the operation succeeded. It could fail if the trash is full, or - if the file is write-protected, so you should check the return value - and act appropriately. - */ - bool moveToTrash() const; - - /** Moves or renames a file. - - Tries to move a file to a different location. - If the target file already exists, this will attempt to delete it first, and - will fail if this can't be done. - - Note that the destination file isn't the directory to put it in, it's the actual - filename that you want the new file to have. - - @returns true if the operation succeeds - */ - bool moveFileTo (const File& targetLocation) const; - - /** Copies a file. - - Tries to copy a file to a different location. - If the target file already exists, this will attempt to delete it first, and - will fail if this can't be done. - - @returns true if the operation succeeds - */ - bool copyFileTo (const File& targetLocation) const; - - /** Copies a directory. - - Tries to copy an entire directory, recursively. - - If this file isn't a directory or if any target files can't be created, this - will return false. - - @param newDirectory the directory that this one should be copied to. Note that this - is the name of the actual directory to create, not the directory - into which the new one should be placed, so there must be enough - write privileges to create it if it doesn't exist. Any files inside - it will be overwritten by similarly named ones that are copied. - */ - bool copyDirectoryTo (const File& newDirectory) const; - - /** Used in file searching, to specify whether to return files, directories, or both. - */ - enum TypesOfFileToFind - { - findDirectories = 1, /**< Use this flag to indicate that you want to find directories. */ - findFiles = 2, /**< Use this flag to indicate that you want to find files. */ - findFilesAndDirectories = 3, /**< Use this flag to indicate that you want to find both files and directories. */ - ignoreHiddenFiles = 4 /**< Add this flag to avoid returning any hidden files in the results. */ - }; - - /** Searches inside a directory for files matching a wildcard pattern. - - Assuming that this file is a directory, this method will search it - for either files or subdirectories whose names match a filename pattern. - - @param results an array to which File objects will be added for the - files that the search comes up with - @param whatToLookFor a value from the TypesOfFileToFind enum, specifying whether to - return files, directories, or both. If the ignoreHiddenFiles flag - is also added to this value, hidden files won't be returned - @param searchRecursively if true, all subdirectories will be recursed into to do - an exhaustive search - @param wildCardPattern the filename pattern to search for, e.g. "*.txt" - @returns the number of results that have been found - - @see getNumberOfChildFiles, DirectoryIterator - */ - int findChildFiles (OwnedArray& results, - const int whatToLookFor, - const bool searchRecursively, - const String& wildCardPattern = JUCE_T("*")) const; - - /** Searches inside a directory and counts how many files match a wildcard pattern. - - Assuming that this file is a directory, this method will search it - for either files or subdirectories whose names match a filename pattern, - and will return the number of matches found. - - This isn't a recursive call, and will only search this directory, not - its children. - - @param whatToLookFor a value from the TypesOfFileToFind enum, specifying whether to - count files, directories, or both. If the ignoreHiddenFiles flag - is also added to this value, hidden files won't be counted - @param wildCardPattern the filename pattern to search for, e.g. "*.txt" - @returns the number of matches found - @see findChildFiles, DirectoryIterator - */ - int getNumberOfChildFiles (const int whatToLookFor, - const String& wildCardPattern = JUCE_T("*")) const; - - /** Returns true if this file is a directory that contains one or more subdirectories. - @see isDirectory, findChildFiles - */ - bool containsSubDirectories() const; - - /** Creates a stream to read from this file. - - @returns a stream that will read from this file (initially positioned at the - start of the file), or 0 if the file can't be opened for some reason - @see createOutputStream, loadFileAsData - */ - FileInputStream* createInputStream() const; - - /** Creates a stream to write to this file. - - If the file exists, the stream that is returned will be positioned ready for - writing at the end of the file, so you might want to use deleteFile() first - to write to an empty file. - - @returns a stream that will write to this file (initially positioned at the - end of the file), or 0 if the file can't be opened for some reason - @see createInputStream, printf, appendData, appendText - */ - FileOutputStream* createOutputStream (const int bufferSize = 0x8000) const; - - /** Loads a file's contents into memory as a block of binary data. - - Of course, trying to load a very large file into memory will blow up, so - it's better to check first. - - @param result the data block to which the file's contents should be appended - note - that if the memory block might already contain some data, you - might want to clear it first - @returns true if the file could all be read into memory - */ - bool loadFileAsData (MemoryBlock& result) const; - - /** Reads a file into memory as a string. - - Attempts to load the entire file as a zero-terminated string. - - This makes use of InputStream::readEntireStreamAsString, which should - automatically cope with unicode/acsii file formats. - */ - const String loadFileAsString() const; - - /** Writes text to the end of the file. - - This will try to do a printf to the file. - - @returns false if it can't write to the file for some reason - */ - bool printf (const tchar* format, ...) const; - - /** Appends a block of binary data to the end of the file. - - This will try to write the given buffer to the end of the file. - - @returns false if it can't write to the file for some reason - */ - bool appendData (const void* const dataToAppend, - const int numberOfBytes) const; - - /** Replaces this file's contents with a given block of data. - - This will delete the file and replace it with the given data. - - A nice feature of this method is that it's safe - instead of deleting - the file first and then re-writing it, it creates a new temporary file, - writes the data to that, and then moves the new file to replace the existing - file. This means that if the power gets pulled out or something crashes, - you're a lot less likely to end up with an empty file.. - - Returns true if the operation succeeds, or false if it fails. - - @see appendText - */ - bool replaceWithData (const void* const dataToWrite, - const int numberOfBytes) const; - - /** Appends a string to the end of the file. - - This will try to append a text string to the file, as either 16-bit unicode - or 8-bit characters in the default system encoding. - - It can also write the 'ff fe' unicode header bytes before the text to indicate - the endianness of the file. - - Any single \\n characters in the string are replaced with \\r\\n before it is written. - - @see replaceWithText - */ - bool appendText (const String& textToAppend, - const bool asUnicode = false, - const bool writeUnicodeHeaderBytes = false) const; - - /** Replaces this file's contents with a given text string. - - This will delete the file and replace it with the given text. - - A nice feature of this method is that it's safe - instead of deleting - the file first and then re-writing it, it creates a new temporary file, - writes the text to that, and then moves the new file to replace the existing - file. This means that if the power gets pulled out or something crashes, - you're a lot less likely to end up with an empty file.. - - For an explanation of the parameters here, see the appendText() method. - - Returns true if the operation succeeds, or false if it fails. - - @see appendText - */ - bool replaceWithText (const String& textToWrite, - const bool asUnicode = false, - const bool writeUnicodeHeaderBytes = false) const; - - /** Creates a set of files to represent each file root. - - e.g. on Windows this will create files for "c:\", "d:\" etc according - to which ones are available. On the Mac/Linux, this will probably - just add a single entry for "/". - */ - static void findFileSystemRoots (OwnedArray& results); - - /** Finds the name of the drive on which this file lives. - - @returns the volume label of the drive, or an empty string if this isn't possible - */ - const String getVolumeLabel() const; - - /** Returns the serial number of the volume on which this file lives. - - @returns the serial number, or zero if there's a problem doing this - */ - int getVolumeSerialNumber() const; - - /** Returns the number of bytes free on the drive that this file lives on. - - @returns the number of bytes free, or 0 if there's a problem finding this out - @see getVolumeTotalSize - */ - int64 getBytesFreeOnVolume() const; - - /** Returns the total size of the drive that contains this file. - - @returns the total number of bytes that the volume can hold - @see getBytesFreeOnVolume - */ - int64 getVolumeTotalSize() const; - - /** Returns true if this file is on a CD or DVD drive. */ - bool isOnCDRomDrive() const; - - /** Returns true if this file is on a hard disk. - - This will fail if it's a network drive, but will still be true for - removable hard-disks. - */ - bool isOnHardDisk() const; - - /** Returns true if this file is on a removable disk drive. - - This might be a usb-drive, a CD-rom, or maybe a network drive. - */ - bool isOnRemovableDrive() const; - - /** Launches the file as a process. - - - if the file is executable, this will run it. - - - if it's a document of some kind, it will launch the document with its - default viewer application. - - - if it's a folder, it will be opened in Explorer, Finder, or equivalent. - - @see revealToUser - */ - bool startAsProcess (const String& parameters = String::empty) const; - - /** Opens Finder, Explorer, or whatever the OS uses, to show the user this file's location. - @see startAsProcess - */ - void revealToUser() const; - - /** A set of types of location that can be passed to the getSpecialLocation() method. - */ - enum SpecialLocationType - { - /** The user's home folder. This is the same as using File ("~"). */ - userHomeDirectory, - - /** The user's default documents folder. On Windows, this might be the user's - "My Documents" folder. On the Mac it'll be their "Documents" folder. Linux - doesn't tend to have one of these, so it might just return their home folder. - */ - userDocumentsDirectory, - - /** The folder that contains the user's desktop objects. */ - userDesktopDirectory, - - /** The folder in which applications store their persistent user-specific settings. - On Windows, this might be "\Documents and Settings\username\Application Data". - On the Mac, it might be "~/Library". If you're going to store your settings in here, - always create your own sub-folder to put them in, to avoid making a mess. - */ - userApplicationDataDirectory, - - /** An equivalent of the userApplicationDataDirectory folder that is shared by all users - of the computer, rather than just the current user. - - On the Mac it'll be "/Library", on Windows, it could be something like - "\Documents and Settings\All Users\Application Data". - - Depending on the setup, this folder may be read-only. - */ - commonApplicationDataDirectory, - - /** The folder that should be used for temporary files. - - Always delete them when you're finished, to keep the user's computer tidy! - */ - tempDirectory, - - /** Returns this application's executable file. - - If running as a plug-in or DLL, this will (where possible) be the DLL rather than the - host app. - - On the mac this will return the unix binary, not the package folder - see - currentApplicationFile for that. - - See also invokedExecutableFile, which is similar, but if the exe was launched from a - file link, invokedExecutableFile will return the name of the link. - */ - currentExecutableFile, - - /** Returns this application's location. - - If running as a plug-in or DLL, this will (where possible) be the DLL rather than the - host app. - - On the mac this will return the package folder (if it's in one), not the unix binary - that's inside it - compare with currentExecutableFile. - */ - currentApplicationFile, - - /** Returns the file that was invoked to launch this executable. - This may differ from currentExecutableFile if the app was started from e.g. a link - this - will return the name of the link that was used, whereas currentExecutableFile will return - the actual location of the target executable. - */ - invokedExecutableFile, - - /** The directory in which applications normally get installed. - - So on windows, this would be something like "c:\program files", on the - Mac "/Applications", or "/usr" on linux. - */ - globalApplicationsDirectory, - - /** The most likely place where a user might store their music files. - */ - userMusicDirectory, - - /** The most likely place where a user might store their movie files. - */ - userMoviesDirectory, - }; - - /** Finds the location of a special type of file or directory, such as a home folder or - documents folder. - - @see SpecialLocationType - */ - static const File JUCE_CALLTYPE getSpecialLocation (const SpecialLocationType type); - - /** Returns a temporary file in the system's temp directory. - - This will try to return the name of a non-existent temp file. - - To get the temp folder, you can use getSpecialLocation (File::tempDirectory). - */ - static const File createTempFile (const String& fileNameEnding); - - /** Returns the current working directory. - - @see setAsCurrentWorkingDirectory - */ - static const File getCurrentWorkingDirectory(); - - /** Sets the current working directory to be this file. - - For this to work the file must point to a valid directory. - - @returns true if the current directory has been changed. - @see getCurrentWorkingDirectory - */ - bool setAsCurrentWorkingDirectory() const; - - /** The system-specific file separator character. - - On Windows, this will be '\', on Mac/Linux, it'll be '/' - */ - static const tchar separator; - - /** The system-specific file separator character, as a string. - - On Windows, this will be '\', on Mac/Linux, it'll be '/' - */ - static const tchar* separatorString; - - /** Removes illegal characters from a filename. - - This will return a copy of the given string after removing characters - that are not allowed in a legal filename, and possibly shortening the - string if it's too long. - - Because this will remove slashes, don't use it on an absolute pathname. - - @see createLegalPathName - */ - static const String createLegalFileName (const String& fileNameToFix); - - /** Removes illegal characters from a pathname. - - Similar to createLegalFileName(), but this won't remove slashes, so can - be used on a complete pathname. - - @see createLegalFileName - */ - static const String createLegalPathName (const String& pathNameToFix); - - /** Indicates whether filenames are case-sensitive on the current operating system. - */ - static bool areFileNamesCaseSensitive(); - - /** Returns true if the string seems to be a fully-specified absolute path. - */ - static bool isAbsolutePath (const String& path); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String fullPath; + String fullPath; - // internal way of contructing a file without checking the path - friend class DirectoryIterator; - File (const String&, int); - const String getPathUpToLastSlash() const; + // internal way of contructing a file without checking the path + friend class DirectoryIterator; + File (const String&, int); + const String getPathUpToLastSlash() const; }; #endif // __JUCE_FILE_JUCEHEADER__ /********* End of inlined file: juce_File.h *********/ -/** A handy macro to make it easy to iterate all the child elements in an XmlElement. - - The parentXmlElement should be a reference to the parent XML, and the childElementVariableName - will be the name of a pointer to each child element. - - E.g. @code - XmlElement* myParentXml = createSomeKindOfXmlDocument(); - - forEachXmlChildElement (*myParentXml, child) - { - if (child->hasTagName (T("FOO"))) - doSomethingWithXmlElement (child); - } - - @endcode - - @see forEachXmlChildElementWithTagName -*/ #define forEachXmlChildElement(parentXmlElement, childElementVariableName) \ \ - for (XmlElement* childElementVariableName = (parentXmlElement).getFirstChildElement(); \ - childElementVariableName != 0; \ - childElementVariableName = childElementVariableName->getNextElement()) + for (XmlElement* childElementVariableName = (parentXmlElement).getFirstChildElement(); \ + childElementVariableName != 0; \ + childElementVariableName = childElementVariableName->getNextElement()) -/** A macro that makes it easy to iterate all the child elements of an XmlElement - which have a specified tag. - - This does the same job as the forEachXmlChildElement macro, but only for those - elements that have a particular tag name. - - The parentXmlElement should be a reference to the parent XML, and the childElementVariableName - will be the name of a pointer to each child element. The requiredTagName is the - tag name to match. - - E.g. @code - XmlElement* myParentXml = createSomeKindOfXmlDocument(); - - forEachXmlChildElementWithTagName (*myParentXml, child, T("MYTAG")) - { - // the child object is now guaranteed to be a element.. - doSomethingWithMYTAGElement (child); - } - - @endcode - - @see forEachXmlChildElement -*/ #define forEachXmlChildElementWithTagName(parentXmlElement, childElementVariableName, requiredTagName) \ \ - for (XmlElement* childElementVariableName = (parentXmlElement).getChildByName (requiredTagName); \ - childElementVariableName != 0; \ - childElementVariableName = childElementVariableName->getNextElementWithTagName (requiredTagName)) + for (XmlElement* childElementVariableName = (parentXmlElement).getChildByName (requiredTagName); \ + childElementVariableName != 0; \ + childElementVariableName = childElementVariableName->getNextElementWithTagName (requiredTagName)) -/** Used to build a tree of elements representing an XML document. - - An XML document can be parsed into a tree of XmlElements, each of which - represents an XML tag structure, and which may itself contain other - nested elements. - - An XmlElement can also be converted back into a text document, and has - lots of useful methods for manipulating its attributes and sub-elements, - so XmlElements can actually be used as a handy general-purpose data - structure. - - Here's an example of parsing some elements: @code - // check we're looking at the right kind of document.. - if (myElement->hasTagName (T("ANIMALS"))) - { - // now we'll iterate its sub-elements looking for 'giraffe' elements.. - forEachXmlChildElement (*myElement, e) - { - if (e->hasTagName (T("GIRAFFE"))) - { - // found a giraffe, so use some of its attributes.. - - String giraffeName = e->getStringAttribute ("name"); - int giraffeAge = e->getIntAttribute ("age"); - bool isFriendly = e->getBoolAttribute ("friendly"); - } - } - } - @endcode - - And here's an example of how to create an XML document from scratch: @code - // create an outer node called "ANIMALS" - XmlElement animalsList ("ANIMALS"); - - for (int i = 0; i < numAnimals; ++i) - { - // create an inner element.. - XmlElement* giraffe = new XmlElement ("GIRAFFE"); - - giraffe->setAttribute ("name", "nigel"); - giraffe->setAttribute ("age", 10); - giraffe->setAttribute ("friendly", true); - - // ..and add our new element to the parent node - animalsList.addChildElement (giraffe); - } - - // now we can turn the whole thing into a text document.. - String myXmlDoc = animalsList.createDocument (String::empty); - @endcode - - @see XmlDocument -*/ class JUCE_API XmlElement { public: - /** Creates an XmlElement with this tag name. */ - XmlElement (const String& tagName) throw(); - - /** Creates a (deep) copy of another element. */ - XmlElement (const XmlElement& other) throw(); - - /** Creates a (deep) copy of another element. */ - const XmlElement& operator= (const XmlElement& other) throw(); - - /** Deleting an XmlElement will also delete all its child elements. */ - ~XmlElement() throw(); - - /** Compares two XmlElements to see if they contain the same text and attiributes. - - The elements are only considered equivalent if they contain the same attiributes - with the same values, and have the same sub-nodes. - - @param other the other element to compare to - @param ignoreOrderOfAttributes if true, this means that two elements with the - same attributes in a different order will be - considered the same; if false, the attributes must - be in the same order as well - */ - bool isEquivalentTo (const XmlElement* const other, - const bool ignoreOrderOfAttributes) const throw(); - - /** Returns an XML text document that represents this element. - - The string returned can be parsed to recreate the same XmlElement that - was used to create it. - - @param dtdToUse the DTD to add to the document - @param allOnOneLine if true, this means that the document will not contain any - linefeeds, so it'll be smaller but not very easy to read. - @param includeXmlHeader whether to add the ", this would return - "MOOSE". - - @see hasTagName - */ - inline const String& getTagName() const throw() { return tagName; } - - /** Tests whether this element has a particular tag name. - - @param possibleTagName the tag name you're comparing it with - - @see getTagName - */ - bool hasTagName (const tchar* const possibleTagName) const throw(); - - /** Returns the number of XML attributes this element contains. - - E.g. for an element such as \, this would - return 2. - */ - int getNumAttributes() const throw(); - - /** Returns the name of one of the elements attributes. - - E.g. for an element such as \, then - getAttributeName(1) would return "antlers". - - @see getAttributeValue, getStringAttribute - */ - const String& getAttributeName (const int attributeIndex) const throw(); - - /** Returns the value of one of the elements attributes. - - E.g. for an element such as \, then - getAttributeName(1) would return "2". - - @see getAttributeName, getStringAttribute - */ - const String& getAttributeValue (const int attributeIndex) const throw(); - - // Attribute-handling methods.. - - /** Checks whether the element contains an attribute with a certain name. */ - bool hasAttribute (const tchar* const attributeName) const throw(); - - /** Returns the value of a named attribute. - - @param attributeName the name of the attribute to look up - @param defaultReturnValue a value to return if the element doesn't have an attribute - with this name - */ - const String getStringAttribute (const tchar* const attributeName, - const tchar* const defaultReturnValue = 0) const throw(); - - /** Compares the value of a named attribute with a value passed-in. - - @param attributeName the name of the attribute to look up - @param stringToCompareAgainst the value to compare it with - @param ignoreCase whether the comparison should be case-insensitive - @returns true if the value of the attribute is the same as the string passed-in; - false if it's different (or if no such attribute exists) - */ - bool compareAttribute (const tchar* const attributeName, - const tchar* const stringToCompareAgainst, - const bool ignoreCase = false) const throw(); - - /** Returns the value of a named attribute as an integer. + XmlElement (const String& tagName) throw(); - This will try to find the attribute and convert it to an integer (using - the String::getIntValue() method). + XmlElement (const XmlElement& other) throw(); - @param attributeName the name of the attribute to look up - @param defaultReturnValue a value to return if the element doesn't have an attribute - with this name - @see setAttribute (const tchar* const, int) - */ - int getIntAttribute (const tchar* const attributeName, - const int defaultReturnValue = 0) const throw(); + const XmlElement& operator= (const XmlElement& other) throw(); - /** Returns the value of a named attribute as floating-point. + ~XmlElement() throw(); - This will try to find the attribute and convert it to an integer (using - the String::getDoubleValue() method). + bool isEquivalentTo (const XmlElement* const other, + const bool ignoreOrderOfAttributes) const throw(); - @param attributeName the name of the attribute to look up - @param defaultReturnValue a value to return if the element doesn't have an attribute - with this name - @see setAttribute (const tchar* const, double) - */ - double getDoubleAttribute (const tchar* const attributeName, - const double defaultReturnValue = 0.0) const throw(); + const String createDocument (const String& dtdToUse, + const bool allOnOneLine = false, + const bool includeXmlHeader = true, + const tchar* const encodingType = JUCE_T("UTF-8"), + const int lineWrapLength = 60) const throw(); - /** Returns the value of a named attribute as a boolean. + void writeToStream (OutputStream& output, + const String& dtdToUse, + const bool allOnOneLine = false, + const bool includeXmlHeader = true, + const tchar* const encodingType = JUCE_T("UTF-8"), + const int lineWrapLength = 60) const throw(); - This will try to find the attribute and interpret it as a boolean. To do this, - it'll return true if the value is "1", "true", "y", etc, or false for other - values. + bool writeToFile (const File& destinationFile, + const String& dtdToUse, + const tchar* const encodingType = JUCE_T("UTF-8"), + const int lineWrapLength = 60) const throw(); - @param attributeName the name of the attribute to look up - @param defaultReturnValue a value to return if the element doesn't have an attribute - with this name - */ - bool getBoolAttribute (const tchar* const attributeName, - const bool defaultReturnValue = false) const throw(); + inline const String& getTagName() const throw() { return tagName; } - /** Adds a named attribute to the element. + bool hasTagName (const tchar* const possibleTagName) const throw(); - If the element already contains an attribute with this name, it's value will - be updated to the new value. If there's no such attribute yet, a new one will - be added. + int getNumAttributes() const throw(); - Note that there are other setAttribute() methods that take integers, - doubles, etc. to make it easy to store numbers. + const String& getAttributeName (const int attributeIndex) const throw(); - @param attributeName the name of the attribute to set - @param newValue the value to set it to - @see removeAttribute - */ - void setAttribute (const tchar* const attributeName, - const String& newValue) throw(); + const String& getAttributeValue (const int attributeIndex) const throw(); - /** Adds a named attribute to the element. + // Attribute-handling methods.. - If the element already contains an attribute with this name, it's value will - be updated to the new value. If there's no such attribute yet, a new one will - be added. + bool hasAttribute (const tchar* const attributeName) const throw(); - Note that there are other setAttribute() methods that take integers, - doubles, etc. to make it easy to store numbers. + const String getStringAttribute (const tchar* const attributeName, + const tchar* const defaultReturnValue = 0) const throw(); - @param attributeName the name of the attribute to set - @param newValue the value to set it to - */ - void setAttribute (const tchar* const attributeName, - const tchar* const newValue) throw(); + bool compareAttribute (const tchar* const attributeName, + const tchar* const stringToCompareAgainst, + const bool ignoreCase = false) const throw(); - /** Adds a named attribute to the element, setting it to an integer value. + int getIntAttribute (const tchar* const attributeName, + const int defaultReturnValue = 0) const throw(); - If the element already contains an attribute with this name, it's value will - be updated to the new value. If there's no such attribute yet, a new one will - be added. + double getDoubleAttribute (const tchar* const attributeName, + const double defaultReturnValue = 0.0) const throw(); - Note that there are other setAttribute() methods that take integers, - doubles, etc. to make it easy to store numbers. + bool getBoolAttribute (const tchar* const attributeName, + const bool defaultReturnValue = false) const throw(); - @param attributeName the name of the attribute to set - @param newValue the value to set it to - */ - void setAttribute (const tchar* const attributeName, - const int newValue) throw(); + void setAttribute (const tchar* const attributeName, + const String& newValue) throw(); - /** Adds a named attribute to the element, setting it to a floating-point value. + void setAttribute (const tchar* const attributeName, + const tchar* const newValue) throw(); - If the element already contains an attribute with this name, it's value will - be updated to the new value. If there's no such attribute yet, a new one will - be added. + void setAttribute (const tchar* const attributeName, + const int newValue) throw(); - Note that there are other setAttribute() methods that take integers, - doubles, etc. to make it easy to store numbers. + void setAttribute (const tchar* const attributeName, + const double newValue) throw(); - @param attributeName the name of the attribute to set - @param newValue the value to set it to - */ - void setAttribute (const tchar* const attributeName, - const double newValue) throw(); + void removeAttribute (const tchar* const attributeName) throw(); - /** Removes a named attribute from the element. + void removeAllAttributes() throw(); - @param attributeName the name of the attribute to remove - @see removeAllAttributes - */ - void removeAttribute (const tchar* const attributeName) throw(); + // Child element methods.. - /** Removes all attributes from this element. - */ - void removeAllAttributes() throw(); + XmlElement* getFirstChildElement() const throw() { return firstChildElement; } - // Child element methods.. + inline XmlElement* getNextElement() const throw() { return nextElement; } - /** Returns the first of this element's sub-elements. + XmlElement* getNextElementWithTagName (const tchar* const requiredTagName) const; - see getNextElement() for an example of how to iterate the sub-elements. + int getNumChildElements() const throw(); - @see forEachXmlChildElement - */ - XmlElement* getFirstChildElement() const throw() { return firstChildElement; } + XmlElement* getChildElement (const int index) const throw(); - /** Returns the next of this element's siblings. + XmlElement* getChildByName (const tchar* const tagNameToLookFor) const throw(); - This can be used for iterating an element's sub-elements, e.g. - @code - XmlElement* child = myXmlDocument->getFirstChildElement(); + void addChildElement (XmlElement* const newChildElement) throw(); - while (child != 0) - { - ...do stuff with this child.. + void insertChildElement (XmlElement* const newChildNode, + int indexToInsertAt) throw(); - child = child->getNextElement(); - } - @endcode + bool replaceChildElement (XmlElement* const currentChildElement, + XmlElement* const newChildNode) throw(); - Note that when iterating the child elements, some of them might be - text elements as well as XML tags - use isTextElement() to work this - out. + void removeChildElement (XmlElement* const childToRemove, + const bool shouldDeleteTheChild) throw(); - Also, it's much easier and neater to use this method indirectly via the - forEachXmlChildElement macro. + void deleteAllChildElements() throw(); - @returns the sibling element that follows this one, or zero if this is the last - element in its parent + void deleteAllChildElementsWithTagName (const tchar* const tagName) throw(); - @see getNextElement, isTextElement, forEachXmlChildElement - */ - inline XmlElement* getNextElement() const throw() { return nextElement; } + bool containsChildElement (const XmlElement* const possibleChild) const throw(); - /** Returns the next of this element's siblings which has the specified tag - name. + XmlElement* findParentElementOf (const XmlElement* const elementToLookFor) throw(); - This is like getNextElement(), but will scan through the list until it - finds an element with the given tag name. + template + void sortChildElements (ElementComparator& comparator, + const bool retainOrderOfEquivalentItems = false) throw() + { + const int num = getNumChildElements(); - @see getNextElement, forEachXmlChildElementWithTagName - */ - XmlElement* getNextElementWithTagName (const tchar* const requiredTagName) const; + if (num > 1) + { + HeapBlock elems (num); + getChildElementsAsArray (elems); + sortArray (comparator, (XmlElement**) elems, 0, num - 1, retainOrderOfEquivalentItems); + reorderChildElements (elems, num); + } + } - /** Returns the number of sub-elements in this element. + bool isTextElement() const throw(); - @see getChildElement - */ - int getNumChildElements() const throw(); + const String getText() const throw(); - /** Returns the sub-element at a certain index. + void setText (const String& newText) throw(); - It's not very efficient to iterate the sub-elements by index - see - getNextElement() for an example of how best to iterate. + const String getAllSubText() const throw(); - @returns the n'th child of this element, or 0 if the index is out-of-range - @see getNextElement, isTextElement, getChildByName - */ - XmlElement* getChildElement (const int index) const throw(); + const String getChildElementAllSubText (const tchar* const childTagName, + const String& defaultReturnValue) const throw(); - /** Returns the first sub-element with a given tag-name. + void addTextElement (const String& text) throw(); - @param tagNameToLookFor the tag name of the element you want to find - @returns the first element with this tag name, or 0 if none is found - @see getNextElement, isTextElement, getChildElement - */ - XmlElement* getChildByName (const tchar* const tagNameToLookFor) const throw(); + void deleteAllTextElements() throw(); - /** Appends an element to this element's list of children. + static XmlElement* createTextElement (const String& text) throw(); - Child elements are deleted automatically when their parent is deleted, so - make sure the object that you pass in will not be deleted by anything else, - and make sure it's not already the child of another element. - - @see getFirstChildElement, getNextElement, getNumChildElements, - getChildElement, removeChildElement - */ - void addChildElement (XmlElement* const newChildElement) throw(); - - /** Inserts an element into this element's list of children. - - Child elements are deleted automatically when their parent is deleted, so - make sure the object that you pass in will not be deleted by anything else, - and make sure it's not already the child of another element. - - @param newChildNode the element to add - @param indexToInsertAt the index at which to insert the new element - if this is - below zero, it will be added to the end of the list - @see addChildElement, insertChildElement - */ - void insertChildElement (XmlElement* const newChildNode, - int indexToInsertAt) throw(); - - /** Replaces one of this element's children with another node. - - If the current element passed-in isn't actually a child of this element, - this will return false and the new one won't be added. Otherwise, the - existing element will be deleted, replaced with the new one, and it - will return true. - */ - bool replaceChildElement (XmlElement* const currentChildElement, - XmlElement* const newChildNode) throw(); - - /** Removes a child element. - - @param childToRemove the child to look for and remove - @param shouldDeleteTheChild if true, the child will be deleted, if false it'll - just remove it - */ - void removeChildElement (XmlElement* const childToRemove, - const bool shouldDeleteTheChild) throw(); - - /** Deletes all the child elements in the element. - - @see removeChildElement, deleteAllChildElementsWithTagName - */ - void deleteAllChildElements() throw(); - - /** Deletes all the child elements with a given tag name. - - @see removeChildElement - */ - void deleteAllChildElementsWithTagName (const tchar* const tagName) throw(); - - /** Returns true if the given element is a child of this one. */ - bool containsChildElement (const XmlElement* const possibleChild) const throw(); - - /** Recursively searches all sub-elements to find one that contains the specified - child element. - */ - XmlElement* findParentElementOf (const XmlElement* const elementToLookFor) throw(); - - /** Sorts the child elements using a comparator. - - This will use a comparator object to sort the elements into order. The object - passed must have a method of the form: - @code - int compareElements (const XmlElement* first, const XmlElement* second); - @endcode - - ..and this method must return: - - a value of < 0 if the first comes before the second - - a value of 0 if the two objects are equivalent - - a value of > 0 if the second comes before the first - - To improve performance, the compareElements() method can be declared as static or const. - - @param comparator the comparator to use for comparing elements. - @param retainOrderOfEquivalentItems if this is true, then items - which the comparator says are equivalent will be - kept in the order in which they currently appear - in the array. This is slower to perform, but may - be important in some cases. If it's false, a faster - algorithm is used, but equivalent elements may be - rearranged. - */ - template - void sortChildElements (ElementComparator& comparator, - const bool retainOrderOfEquivalentItems = false) throw() - { - const int num = getNumChildElements(); - - if (num > 1) - { - HeapBlock elems (num); - getChildElementsAsArray (elems); - sortArray (comparator, (XmlElement**) elems, 0, num - 1, retainOrderOfEquivalentItems); - reorderChildElements (elems, num); - } - } - - /** Returns true if this element is a section of text. - - Elements can either be an XML tag element or a secton of text, so this - is used to find out what kind of element this one is. - - @see getAllText, addTextElement, deleteAllTextElements - */ - bool isTextElement() const throw(); - - /** Returns the text for a text element. - - Note that if you have an element like this: - - @codehello@endcode - - then calling getText on the "xyz" element won't return "hello", because that is - actually stored in a special text sub-element inside the xyz element. To get the - "hello" string, you could either call getText on the (unnamed) sub-element, or - use getAllSubText() to do this automatically. - - @see isTextElement, getAllSubText, getChildElementAllSubText - */ - const String getText() const throw(); - - /** Sets the text in a text element. - - Note that this is only a valid call if this element is a text element. If it's - not, then no action will be performed. - */ - void setText (const String& newText) throw(); - - /** Returns all the text from this element's child nodes. - - This iterates all the child elements and when it finds text elements, - it concatenates their text into a big string which it returns. - - E.g. @code hello there @endcode - if you called getAllSubText on the "xyz" element, it'd return "hello there". - - @see isTextElement, getChildElementAllSubText, getText, addTextElement - */ - const String getAllSubText() const throw(); - - /** Returns all the sub-text of a named child element. - - If there is a child element with the given tag name, this will return - all of its sub-text (by calling getAllSubText() on it). If there is - no such child element, this will return the default string passed-in. - - @see getAllSubText - */ - const String getChildElementAllSubText (const tchar* const childTagName, - const String& defaultReturnValue) const throw(); - - /** Appends a section of text to this element. - - @see isTextElement, getText, getAllSubText - */ - void addTextElement (const String& text) throw(); - - /** Removes all the text elements from this element. - - @see isTextElement, getText, getAllSubText, addTextElement - */ - void deleteAllTextElements() throw(); - - /** Creates a text element that can be added to a parent element. - */ - static XmlElement* createTextElement (const String& text) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class XmlDocument; + friend class XmlDocument; - String tagName; - XmlElement* firstChildElement; - XmlElement* nextElement; + String tagName; + XmlElement* firstChildElement; + XmlElement* nextElement; - struct XmlAttributeNode - { - XmlAttributeNode (const XmlAttributeNode& other) throw(); - XmlAttributeNode (const String& name, const String& value) throw(); + struct XmlAttributeNode + { + XmlAttributeNode (const XmlAttributeNode& other) throw(); + XmlAttributeNode (const String& name, const String& value) throw(); - String name, value; - XmlAttributeNode* next; + String name, value; + XmlAttributeNode* next; - private: - const XmlAttributeNode& operator= (const XmlAttributeNode&); - }; + private: + const XmlAttributeNode& operator= (const XmlAttributeNode&); + }; - XmlAttributeNode* attributes; + XmlAttributeNode* attributes; - XmlElement (int) throw(); // for internal use - XmlElement (const tchar* const tagNameText, const int nameLen) throw(); + XmlElement (int) throw(); // for internal use + XmlElement (const tchar* const tagNameText, const int nameLen) throw(); - void copyChildrenAndAttributesFrom (const XmlElement& other) throw(); + void copyChildrenAndAttributesFrom (const XmlElement& other) throw(); - void writeElementAsText (OutputStream& out, - const int indentationLevel, - const int lineWrapLength) const throw(); + void writeElementAsText (OutputStream& out, + const int indentationLevel, + const int lineWrapLength) const throw(); - void getChildElementsAsArray (XmlElement**) const throw(); - void reorderChildElements (XmlElement** const, const int) throw(); + void getChildElementsAsArray (XmlElement**) const throw(); + void reorderChildElements (XmlElement** const, const int) throw(); }; #endif // __JUCE_XMLELEMENT_JUCEHEADER__ /********* End of inlined file: juce_XmlElement.h *********/ -/** - A set of named property values, which can be strings, integers, floating point, etc. - - Effectively, this just wraps a StringPairArray in an interface that makes it easier - to load and save types other than strings. - - See the PropertiesFile class for a subclass of this, which automatically broadcasts change - messages and saves/loads the list from a file. -*/ class JUCE_API PropertySet { public: - /** Creates an empty PropertySet. + PropertySet (const bool ignoreCaseOfKeyNames = false) throw(); - @param ignoreCaseOfKeyNames if true, the names of properties are compared in a - case-insensitive way - */ - PropertySet (const bool ignoreCaseOfKeyNames = false) throw(); + PropertySet (const PropertySet& other) throw(); - /** Creates a copy of another PropertySet. - */ - PropertySet (const PropertySet& other) throw(); + const PropertySet& operator= (const PropertySet& other) throw(); - /** Copies another PropertySet over this one. - */ - const PropertySet& operator= (const PropertySet& other) throw(); + virtual ~PropertySet(); - /** Destructor. */ - virtual ~PropertySet(); + const String getValue (const String& keyName, + const String& defaultReturnValue = String::empty) const throw(); - /** Returns one of the properties as a string. + int getIntValue (const String& keyName, + const int defaultReturnValue = 0) const throw(); - If the value isn't found in this set, then this will look for it in a fallback - property set (if you've specified one with the setFallbackPropertySet() method), - and if it can't find one there, it'll return the default value passed-in. + double getDoubleValue (const String& keyName, + const double defaultReturnValue = 0.0) const throw(); - @param keyName the name of the property to retrieve - @param defaultReturnValue a value to return if the named property doesn't actually exist - */ - const String getValue (const String& keyName, - const String& defaultReturnValue = String::empty) const throw(); + bool getBoolValue (const String& keyName, + const bool defaultReturnValue = false) const throw(); - /** Returns one of the properties as an integer. + XmlElement* getXmlValue (const String& keyName) const; - If the value isn't found in this set, then this will look for it in a fallback - property set (if you've specified one with the setFallbackPropertySet() method), - and if it can't find one there, it'll return the default value passed-in. + void setValue (const String& keyName, const String& value) throw(); - @param keyName the name of the property to retrieve - @param defaultReturnValue a value to return if the named property doesn't actually exist - */ - int getIntValue (const String& keyName, - const int defaultReturnValue = 0) const throw(); + void setValue (const String& keyName, const tchar* const value) throw(); - /** Returns one of the properties as an double. + void setValue (const String& keyName, const int value) throw(); - If the value isn't found in this set, then this will look for it in a fallback - property set (if you've specified one with the setFallbackPropertySet() method), - and if it can't find one there, it'll return the default value passed-in. + void setValue (const String& keyName, const double value) throw(); - @param keyName the name of the property to retrieve - @param defaultReturnValue a value to return if the named property doesn't actually exist - */ - double getDoubleValue (const String& keyName, - const double defaultReturnValue = 0.0) const throw(); + void setValue (const String& keyName, const bool value) throw(); - /** Returns one of the properties as an boolean. + void setValue (const String& keyName, const XmlElement* const xml); - The result will be true if the string found for this key name can be parsed as a non-zero - integer. + void removeValue (const String& keyName) throw(); - If the value isn't found in this set, then this will look for it in a fallback - property set (if you've specified one with the setFallbackPropertySet() method), - and if it can't find one there, it'll return the default value passed-in. + bool containsKey (const String& keyName) const throw(); - @param keyName the name of the property to retrieve - @param defaultReturnValue a value to return if the named property doesn't actually exist - */ - bool getBoolValue (const String& keyName, - const bool defaultReturnValue = false) const throw(); + void clear(); - /** Returns one of the properties as an XML element. + StringPairArray& getAllProperties() throw() { return properties; } - The result will a new XMLElement object that the caller must delete. If may return 0 if the - key isn't found, or if the entry contains an string that isn't valid XML. + const CriticalSection& getLock() const throw() { return lock; } - If the value isn't found in this set, then this will look for it in a fallback - property set (if you've specified one with the setFallbackPropertySet() method), - and if it can't find one there, it'll return the default value passed-in. + XmlElement* createXml (const String& nodeName) const throw(); - @param keyName the name of the property to retrieve - */ - XmlElement* getXmlValue (const String& keyName) const; + void restoreFromXml (const XmlElement& xml) throw(); - /** Sets a named property as a string. + void setFallbackPropertySet (PropertySet* fallbackProperties) throw(); - @param keyName the name of the property to set. (This mustn't be an empty string) - @param value the new value to set it to - */ - void setValue (const String& keyName, const String& value) throw(); + PropertySet* getFallbackPropertySet() const throw() { return fallbackProperties; } - /** Sets a named property as a string. - - @param keyName the name of the property to set. (This mustn't be an empty string) - @param value the new value to set it to - */ - void setValue (const String& keyName, const tchar* const value) throw(); - - /** Sets a named property to an integer. - - @param keyName the name of the property to set. (This mustn't be an empty string) - @param value the new value to set it to - */ - void setValue (const String& keyName, const int value) throw(); - - /** Sets a named property to a double. - - @param keyName the name of the property to set. (This mustn't be an empty string) - @param value the new value to set it to - */ - void setValue (const String& keyName, const double value) throw(); - - /** Sets a named property to a boolean. - - @param keyName the name of the property to set. (This mustn't be an empty string) - @param value the new value to set it to - */ - void setValue (const String& keyName, const bool value) throw(); - - /** Sets a named property to an XML element. - - @param keyName the name of the property to set. (This mustn't be an empty string) - @param xml the new element to set it to. If this is zero, the value will be set to - an empty string - @see getXmlValue - */ - void setValue (const String& keyName, const XmlElement* const xml); - - /** Deletes a property. - - @param keyName the name of the property to delete. (This mustn't be an empty string) - */ - void removeValue (const String& keyName) throw(); - - /** Returns true if the properies include the given key. */ - bool containsKey (const String& keyName) const throw(); - - /** Removes all values. */ - void clear(); - - /** Returns the keys/value pair array containing all the properties. */ - StringPairArray& getAllProperties() throw() { return properties; } - - /** Returns the lock used when reading or writing to this set */ - const CriticalSection& getLock() const throw() { return lock; } - - /** Returns an XML element which encapsulates all the items in this property set. - - The string parameter is the tag name that should be used for the node. - - @see restoreFromXml - */ - XmlElement* createXml (const String& nodeName) const throw(); - - /** Reloads a set of properties that were previously stored as XML. - - The node passed in must have been created by the createXml() method. - - @see createXml - */ - void restoreFromXml (const XmlElement& xml) throw(); - - /** Sets up a second PopertySet that will be used to look up any values that aren't - set in this one. - - If you set this up to be a pointer to a second property set, then whenever one - of the getValue() methods fails to find an entry in this set, it will look up that - value in the fallback set, and if it finds it, it will return that. - - Make sure that you don't delete the fallback set while it's still being used by - another set! To remove the fallback set, just call this method with a null pointer. - - @see getFallbackPropertySet - */ - void setFallbackPropertySet (PropertySet* fallbackProperties) throw(); - - /** Returns the fallback property set. - @see setFallbackPropertySet - */ - PropertySet* getFallbackPropertySet() const throw() { return fallbackProperties; } - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** Subclasses can override this to be told when one of the properies has been changed. - */ - virtual void propertyChanged(); + virtual void propertyChanged(); private: - StringPairArray properties; - PropertySet* fallbackProperties; - CriticalSection lock; - bool ignoreCaseOfKeys; + StringPairArray properties; + PropertySet* fallbackProperties; + CriticalSection lock; + bool ignoreCaseOfKeys; }; #endif // __JUCE_PROPERTYSET_JUCEHEADER__ @@ -9070,173 +4378,167 @@ private: #ifndef __JUCE_ATOMIC_JUCEHEADER__ #define __JUCE_ATOMIC_JUCEHEADER__ -/** Contains static functions for thread-safe atomic operations. -*/ class JUCE_API Atomic { public: - /** Increments an integer in a thread-safe way. */ - static void increment (int& variable); + static void increment (int& variable); - /** Increments an integer in a thread-safe way and returns its new value. */ - static int incrementAndReturn (int& variable); + static int incrementAndReturn (int& variable); - /** Decrements an integer in a thread-safe way. */ - static void decrement (int& variable); + static void decrement (int& variable); - /** Decrements an integer in a thread-safe way and returns its new value. */ - static int decrementAndReturn (int& variable); + static int decrementAndReturn (int& variable); }; -#if (JUCE_MAC || JUCE_IPHONE) // Mac and iPhone... +#if (JUCE_MAC || JUCE_IPHONE) // Mac and iPhone... #include -inline void Atomic::increment (int& variable) { OSAtomicIncrement32 ((int32_t*) &variable); } -inline int Atomic::incrementAndReturn (int& variable) { return OSAtomicIncrement32 ((int32_t*) &variable); } -inline void Atomic::decrement (int& variable) { OSAtomicDecrement32 ((int32_t*) &variable); } -inline int Atomic::decrementAndReturn (int& variable) { return OSAtomicDecrement32 ((int32_t*) &variable); } +inline void Atomic::increment (int& variable) { OSAtomicIncrement32 ((int32_t*) &variable); } +inline int Atomic::incrementAndReturn (int& variable) { return OSAtomicIncrement32 ((int32_t*) &variable); } +inline void Atomic::decrement (int& variable) { OSAtomicDecrement32 ((int32_t*) &variable); } +inline int Atomic::decrementAndReturn (int& variable) { return OSAtomicDecrement32 ((int32_t*) &variable); } #elif JUCE_GCC -#if JUCE_USE_GCC_ATOMIC_INTRINSICS // Linux with intrinsics... +#if JUCE_USE_GCC_ATOMIC_INTRINSICS // Linux with intrinsics... -inline void Atomic::increment (int& variable) { __sync_add_and_fetch (&variable, 1); } -inline int Atomic::incrementAndReturn (int& variable) { return __sync_add_and_fetch (&variable, 1); } -inline void Atomic::decrement (int& variable) { __sync_add_and_fetch (&variable, -1); } -inline int Atomic::decrementAndReturn (int& variable) { return __sync_add_and_fetch (&variable, -1); } +inline void Atomic::increment (int& variable) { __sync_add_and_fetch (&variable, 1); } +inline int Atomic::incrementAndReturn (int& variable) { return __sync_add_and_fetch (&variable, 1); } +inline void Atomic::decrement (int& variable) { __sync_add_and_fetch (&variable, -1); } +inline int Atomic::decrementAndReturn (int& variable) { return __sync_add_and_fetch (&variable, -1); } -#else // Linux without intrinsics... +#else // Linux without intrinsics... inline void Atomic::increment (int& variable) { - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock incl (%%rax)" - : - : "a" (&variable) - : "cc", "memory"); - #else - "lock incl %0" - : "=m" (variable) - : "m" (variable)); - #endif + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock incl (%%rax)" + : + : "a" (&variable) + : "cc", "memory"); + #else + "lock incl %0" + : "=m" (variable) + : "m" (variable)); + #endif } inline int Atomic::incrementAndReturn (int& variable) { - int result; + int result; - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock xaddl %%ebx, (%%rax) \n\ - incl %%ebx" - : "=b" (result) - : "a" (&variable), "b" (1) - : "cc", "memory"); - #else - "lock xaddl %%eax, (%%ecx) \n\ - incl %%eax" - : "=a" (result) - : "c" (&variable), "a" (1) - : "memory"); - #endif + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock xaddl %%ebx, (%%rax) \n\ + incl %%ebx" + : "=b" (result) + : "a" (&variable), "b" (1) + : "cc", "memory"); + #else + "lock xaddl %%eax, (%%ecx) \n\ + incl %%eax" + : "=a" (result) + : "c" (&variable), "a" (1) + : "memory"); + #endif - return result; + return result; } inline void Atomic::decrement (int& variable) { - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock decl (%%rax)" - : - : "a" (&variable) - : "cc", "memory"); - #else - "lock decl %0" - : "=m" (variable) - : "m" (variable)); - #endif + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock decl (%%rax)" + : + : "a" (&variable) + : "cc", "memory"); + #else + "lock decl %0" + : "=m" (variable) + : "m" (variable)); + #endif } inline int Atomic::decrementAndReturn (int& variable) { - int result; + int result; - __asm__ __volatile__ ( - #if JUCE_64BIT - "lock xaddl %%ebx, (%%rax) \n\ - decl %%ebx" - : "=b" (result) - : "a" (&variable), "b" (-1) - : "cc", "memory"); - #else - "lock xaddl %%eax, (%%ecx) \n\ - decl %%eax" - : "=a" (result) - : "c" (&variable), "a" (-1) - : "memory"); - #endif - return result; + __asm__ __volatile__ ( + #if JUCE_64BIT + "lock xaddl %%ebx, (%%rax) \n\ + decl %%ebx" + : "=b" (result) + : "a" (&variable), "b" (-1) + : "cc", "memory"); + #else + "lock xaddl %%eax, (%%ecx) \n\ + decl %%eax" + : "=a" (result) + : "c" (&variable), "a" (-1) + : "memory"); + #endif + return result; } #endif -#elif JUCE_USE_INTRINSICS // Windows with intrinsics... +#elif JUCE_USE_INTRINSICS // Windows with intrinsics... #pragma intrinsic (_InterlockedIncrement) #pragma intrinsic (_InterlockedDecrement) -inline void Atomic::increment (int& variable) { _InterlockedIncrement (reinterpret_cast (&variable)); } -inline int Atomic::incrementAndReturn (int& variable) { return _InterlockedIncrement (reinterpret_cast (&variable)); } -inline void Atomic::decrement (int& variable) { _InterlockedDecrement (reinterpret_cast (&variable)); } -inline int Atomic::decrementAndReturn (int& variable) { return _InterlockedDecrement (reinterpret_cast (&variable)); } +inline void Atomic::increment (int& variable) { _InterlockedIncrement (reinterpret_cast (&variable)); } +inline int Atomic::incrementAndReturn (int& variable) { return _InterlockedIncrement (reinterpret_cast (&variable)); } +inline void Atomic::decrement (int& variable) { _InterlockedDecrement (reinterpret_cast (&variable)); } +inline int Atomic::decrementAndReturn (int& variable) { return _InterlockedDecrement (reinterpret_cast (&variable)); } -#else // Windows without intrinsics... +#else // Windows without intrinsics... inline void Atomic::increment (int& variable) { - __asm { - mov ecx, dword ptr [variable] - lock inc dword ptr [ecx] - } + __asm { + mov ecx, dword ptr [variable] + lock inc dword ptr [ecx] + } } inline int Atomic::incrementAndReturn (int& variable) { - int result; + int result; - __asm { - mov ecx, dword ptr [variable] - mov eax, 1 - lock xadd dword ptr [ecx], eax - inc eax - mov result, eax - } + __asm { + mov ecx, dword ptr [variable] + mov eax, 1 + lock xadd dword ptr [ecx], eax + inc eax + mov result, eax + } - return result; + return result; } inline void Atomic::decrement (int& variable) { - __asm { - mov ecx, dword ptr [variable] - lock dec dword ptr [ecx] - } + __asm { + mov ecx, dword ptr [variable] + lock dec dword ptr [ecx] + } } inline int Atomic::decrementAndReturn (int& variable) { - int result; + int result; - __asm { - mov ecx, dword ptr [variable] - mov eax, -1 - lock xadd dword ptr [ecx], eax - dec eax - mov result, eax - } + __asm { + mov ecx, dword ptr [variable] + mov eax, -1 + lock xadd dword ptr [ecx], eax + dec eax + mov result, eax + } - return result; + return result; } #endif @@ -9244,967 +4546,626 @@ inline int Atomic::decrementAndReturn (int& variable) #endif // __JUCE_ATOMIC_JUCEHEADER__ /********* End of inlined file: juce_Atomic.h *********/ -/** - Adds reference-counting to an object. - - To add reference-counting to a class, derive it from this class, and - use the ReferenceCountedObjectPtr class to point to it. - - e.g. @code - class MyClass : public ReferenceCountedObject - { - void foo(); - - // This is a neat way of declaring a typedef for a pointer class, - // rather than typing out the full templated name each time.. - typedef ReferenceCountedObjectPtr Ptr; - }; - - MyClass::Ptr p = new MyClass(); - MyClass::Ptr p2 = p; - p = 0; - p2->foo(); - @endcode - - Once a new ReferenceCountedObject has been assigned to a pointer, be - careful not to delete the object manually. - - @see ReferenceCountedObjectPtr, ReferenceCountedArray -*/ class JUCE_API ReferenceCountedObject { public: - /** Increments the object's reference count. + inline void incReferenceCount() throw() + { + Atomic::increment (refCounts); - This is done automatically by the smart pointer, but is public just - in case it's needed for nefarious purposes. - */ - inline void incReferenceCount() throw() - { - Atomic::increment (refCounts); + jassert (refCounts > 0); + } - jassert (refCounts > 0); - } + inline void decReferenceCount() throw() + { + jassert (refCounts > 0); - /** Decreases the object's reference count. + if (Atomic::decrementAndReturn (refCounts) == 0) + delete this; + } - If the count gets to zero, the object will be deleted. - */ - inline void decReferenceCount() throw() - { - jassert (refCounts > 0); - - if (Atomic::decrementAndReturn (refCounts) == 0) - delete this; - } - - /** Returns the object's current reference count. */ - inline int getReferenceCount() const throw() - { - return refCounts; - } + inline int getReferenceCount() const throw() + { + return refCounts; + } protected: - /** Creates the reference-counted object (with an initial ref count of zero). */ - ReferenceCountedObject() - : refCounts (0) - { - } + ReferenceCountedObject() + : refCounts (0) + { + } - /** Destructor. */ - virtual ~ReferenceCountedObject() - { - // it's dangerous to delete an object that's still referenced by something else! - jassert (refCounts == 0); - } + virtual ~ReferenceCountedObject() + { + // it's dangerous to delete an object that's still referenced by something else! + jassert (refCounts == 0); + } private: - int refCounts; + int refCounts; }; -/** - Used to point to an object of type ReferenceCountedObject. - - It's wise to use a typedef instead of typing out the templated name - each time - e.g. - - typedef ReferenceCountedObjectPtr MyClassPtr; - - @see ReferenceCountedObject, ReferenceCountedObjectArray -*/ template class ReferenceCountedObjectPtr { public: - /** Creates a pointer to a null object. */ - inline ReferenceCountedObjectPtr() throw() - : referencedObject (0) - { - } + inline ReferenceCountedObjectPtr() throw() + : referencedObject (0) + { + } - /** Creates a pointer to an object. + inline ReferenceCountedObjectPtr (ReferenceCountedObjectClass* const refCountedObject) throw() + : referencedObject (refCountedObject) + { + if (refCountedObject != 0) + refCountedObject->incReferenceCount(); + } - This will increment the object's reference-count if it is non-null. - */ - inline ReferenceCountedObjectPtr (ReferenceCountedObjectClass* const refCountedObject) throw() - : referencedObject (refCountedObject) - { - if (refCountedObject != 0) - refCountedObject->incReferenceCount(); - } + inline ReferenceCountedObjectPtr (const ReferenceCountedObjectPtr& other) throw() + : referencedObject (other.referencedObject) + { + if (referencedObject != 0) + referencedObject->incReferenceCount(); + } - /** Copies another pointer. + const ReferenceCountedObjectPtr& operator= (const ReferenceCountedObjectPtr& other) + { + ReferenceCountedObjectClass* const newObject = other.referencedObject; - This will increment the object's reference-count (if it is non-null). - */ - inline ReferenceCountedObjectPtr (const ReferenceCountedObjectPtr& other) throw() - : referencedObject (other.referencedObject) - { - if (referencedObject != 0) - referencedObject->incReferenceCount(); - } + if (newObject != referencedObject) + { + if (newObject != 0) + newObject->incReferenceCount(); - /** Changes this pointer to point at a different object. + ReferenceCountedObjectClass* const oldObject = referencedObject; + referencedObject = newObject; - The reference count of the old object is decremented, and it might be - deleted if it hits zero. The new object's count is incremented. - */ - const ReferenceCountedObjectPtr& operator= (const ReferenceCountedObjectPtr& other) - { - ReferenceCountedObjectClass* const newObject = other.referencedObject; + if (oldObject != 0) + oldObject->decReferenceCount(); + } - if (newObject != referencedObject) - { - if (newObject != 0) - newObject->incReferenceCount(); + return *this; + } - ReferenceCountedObjectClass* const oldObject = referencedObject; - referencedObject = newObject; + const ReferenceCountedObjectPtr& operator= (ReferenceCountedObjectClass* const newObject) + { + if (referencedObject != newObject) + { + if (newObject != 0) + newObject->incReferenceCount(); - if (oldObject != 0) - oldObject->decReferenceCount(); - } + ReferenceCountedObjectClass* const oldObject = referencedObject; + referencedObject = newObject; - return *this; - } + if (oldObject != 0) + oldObject->decReferenceCount(); + } - /** Changes this pointer to point at a different object. + return *this; + } - The reference count of the old object is decremented, and it might be - deleted if it hits zero. The new object's count is incremented. - */ - const ReferenceCountedObjectPtr& operator= (ReferenceCountedObjectClass* const newObject) - { - if (referencedObject != newObject) - { - if (newObject != 0) - newObject->incReferenceCount(); + inline ~ReferenceCountedObjectPtr() + { + if (referencedObject != 0) + referencedObject->decReferenceCount(); + } - ReferenceCountedObjectClass* const oldObject = referencedObject; - referencedObject = newObject; + inline operator ReferenceCountedObjectClass*() const throw() + { + return referencedObject; + } - if (oldObject != 0) - oldObject->decReferenceCount(); - } + inline bool operator== (ReferenceCountedObjectClass* const object) const throw() + { + return referencedObject == object; + } - return *this; - } + inline bool operator!= (ReferenceCountedObjectClass* const object) const throw() + { + return referencedObject != object; + } - /** Destructor. - - This will decrement the object's reference-count, and may delete it if it - gets to zero. - */ - inline ~ReferenceCountedObjectPtr() - { - if (referencedObject != 0) - referencedObject->decReferenceCount(); - } - - /** Returns the object that this pointer references. - - The pointer returned may be zero, of course. - */ - inline operator ReferenceCountedObjectClass*() const throw() - { - return referencedObject; - } - - /** Returns true if this pointer refers to the given object. */ - inline bool operator== (ReferenceCountedObjectClass* const object) const throw() - { - return referencedObject == object; - } - - /** Returns true if this pointer doesn't refer to the given object. */ - inline bool operator!= (ReferenceCountedObjectClass* const object) const throw() - { - return referencedObject != object; - } - - // the -> operator is called on the referenced object - inline ReferenceCountedObjectClass* operator->() const throw() - { - return referencedObject; - } + // the -> operator is called on the referenced object + inline ReferenceCountedObjectClass* operator->() const throw() + { + return referencedObject; + } private: - ReferenceCountedObjectClass* referencedObject; + ReferenceCountedObjectClass* referencedObject; }; #endif // __JUCE_REFERENCECOUNTEDOBJECT_JUCEHEADER__ /********* End of inlined file: juce_ReferenceCountedObject.h *********/ -/** - Holds a list of objects derived from ReferenceCountedObject. - - A ReferenceCountedArray holds objects derived from ReferenceCountedObject, - and takes care of incrementing and decrementing their ref counts when they - are added and removed from the array. - - To make all the array's methods thread-safe, pass in "CriticalSection" as the templated - TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection. - - @see Array, OwnedArray, StringArray -*/ template class ReferenceCountedArray { public: - /** Creates an empty array. - - @param granularity this is the size of increment by which the internal storage - used by the array will grow. Only change it from the default if you know the - array is going to be very big and needs to be able to grow efficiently. - - @see ReferenceCountedObject, Array, OwnedArray - */ - ReferenceCountedArray (const int granularity = juceDefaultArrayGranularity) throw() - : data (granularity), - numUsed (0) - { - } - - /** Creates a copy of another array */ - ReferenceCountedArray (const ReferenceCountedArray& other) throw() - : data (other.data.granularity) - { - other.lockArray(); - numUsed = other.numUsed; - data.setAllocatedSize (numUsed); - memcpy (data.elements, other.data.elements, numUsed * sizeof (ObjectClass*)); - - for (int i = numUsed; --i >= 0;) - if (data.elements[i] != 0) - data.elements[i]->incReferenceCount(); - - other.unlockArray(); - } - - /** Copies another array into this one. - - Any existing objects in this array will first be released. - */ - const ReferenceCountedArray& operator= (const ReferenceCountedArray& other) throw() - { - if (this != &other) - { - other.lockArray(); - lock.enter(); - - clear(); - - data.granularity = other.granularity; - data.ensureAllocatedSize (other.numUsed); - numUsed = other.numUsed; - memcpy (data.elements, other.data.elements, numUsed * sizeof (ObjectClass*)); - minimiseStorageOverheads(); - - for (int i = numUsed; --i >= 0;) - if (data.elements[i] != 0) - data.elements[i]->incReferenceCount(); - - lock.exit(); - other.unlockArray(); - } - - return *this; - } - - /** Destructor. - - Any objects in the array will be released, and may be deleted if not referenced from elsewhere. - */ - ~ReferenceCountedArray() - { - clear(); - } - - /** Removes all objects from the array. - - Any objects in the array that are not referenced from elsewhere will be deleted. - */ - void clear() - { - lock.enter(); - - while (numUsed > 0) - if (data.elements [--numUsed] != 0) - data.elements [numUsed]->decReferenceCount(); - - jassert (numUsed == 0); - data.setAllocatedSize (0); - - lock.exit(); - } - - /** Returns the current number of objects in the array. */ - inline int size() const throw() - { - return numUsed; - } - - /** Returns a pointer to the object at this index in the array. - - If the index is out-of-range, this will return a null pointer, (and - it could be null anyway, because it's ok for the array to hold null - pointers as well as objects). - - @see getUnchecked - */ - inline const ReferenceCountedObjectPtr operator[] (const int index) const throw() - { - lock.enter(); - const ReferenceCountedObjectPtr result ((((unsigned int) index) < (unsigned int) numUsed) - ? data.elements [index] - : (ObjectClass*) 0); - lock.exit(); - return result; - } - - /** Returns a pointer to the object at this index in the array, without checking whether the index is in-range. - - This is a faster and less safe version of operator[] which doesn't check the index passed in, so - it can be used when you're sure the index if always going to be legal. - */ - inline const ReferenceCountedObjectPtr getUnchecked (const int index) const throw() - { - lock.enter(); - jassert (((unsigned int) index) < (unsigned int) numUsed); - const ReferenceCountedObjectPtr result (data.elements [index]); - lock.exit(); - return result; - } - - /** Returns a pointer to the first object in the array. - - This will return a null pointer if the array's empty. - @see getLast - */ - inline const ReferenceCountedObjectPtr getFirst() const throw() - { - lock.enter(); - const ReferenceCountedObjectPtr result ((numUsed > 0) ? data.elements [0] - : (ObjectClass*) 0); - lock.exit(); - - return result; - } - - /** Returns a pointer to the last object in the array. - - This will return a null pointer if the array's empty. - @see getFirst - */ - inline const ReferenceCountedObjectPtr getLast() const throw() - { - lock.enter(); - const ReferenceCountedObjectPtr result ((numUsed > 0) ? data.elements [numUsed - 1] - : (ObjectClass*) 0); - lock.exit(); - - return result; - } - - /** Finds the index of the first occurrence of an object in the array. - - @param objectToLookFor the object to look for - @returns the index at which the object was found, or -1 if it's not found - */ - int indexOf (const ObjectClass* const objectToLookFor) const throw() - { - int result = -1; - - lock.enter(); - ObjectClass** e = data.elements; - - for (int i = numUsed; --i >= 0;) - { - if (objectToLookFor == *e) - { - result = (int) (e - data.elements); - break; - } - - ++e; - } - - lock.exit(); - return result; - } - - /** Returns true if the array contains a specified object. - - @param objectToLookFor the object to look for - @returns true if the object is in the array - */ - bool contains (const ObjectClass* const objectToLookFor) const throw() - { - lock.enter(); - ObjectClass** e = data.elements; - - for (int i = numUsed; --i >= 0;) - { - if (objectToLookFor == *e) - { - lock.exit(); - return true; - } - - ++e; - } - - lock.exit(); - return false; - } - - /** Appends a new object to the end of the array. - - This will increase the new object's reference count. - - @param newObject the new object to add to the array - @see set, insert, addIfNotAlreadyThere, addSorted, addArray - */ - void add (ObjectClass* const newObject) throw() - { - lock.enter(); - data.ensureAllocatedSize (numUsed + 1); - data.elements [numUsed++] = newObject; - - if (newObject != 0) - newObject->incReferenceCount(); - - lock.exit(); - } - - /** Inserts a new object into the array at the given index. - - If the index is less than 0 or greater than the size of the array, the - element will be added to the end of the array. - Otherwise, it will be inserted into the array, moving all the later elements - along to make room. - - This will increase the new object's reference count. - - @param indexToInsertAt the index at which the new element should be inserted - @param newObject the new object to add to the array - @see add, addSorted, addIfNotAlreadyThere, set - */ - void insert (int indexToInsertAt, - ObjectClass* const newObject) throw() - { - if (indexToInsertAt >= 0) - { - lock.enter(); - - if (indexToInsertAt > numUsed) - indexToInsertAt = numUsed; - - data.ensureAllocatedSize (numUsed + 1); - - ObjectClass** const e = data.elements + indexToInsertAt; - const int numToMove = numUsed - indexToInsertAt; - - if (numToMove > 0) - memmove (e + 1, e, numToMove * sizeof (ObjectClass*)); - - *e = newObject; - - if (newObject != 0) - newObject->incReferenceCount(); - - ++numUsed; - lock.exit(); - } - else - { - add (newObject); - } - } - - /** Appends a new object at the end of the array as long as the array doesn't - already contain it. - - If the array already contains a matching object, nothing will be done. - - @param newObject the new object to add to the array - */ - void addIfNotAlreadyThere (ObjectClass* const newObject) throw() - { - lock.enter(); - - if (! contains (newObject)) - add (newObject); - - lock.exit(); - } - - /** Replaces an object in the array with a different one. - - If the index is less than zero, this method does nothing. - If the index is beyond the end of the array, the new object is added to the end of the array. - - The object being added has its reference count increased, and if it's replacing - another object, then that one has its reference count decreased, and may be deleted. - - @param indexToChange the index whose value you want to change - @param newObject the new value to set for this index. - @see add, insert, remove - */ - void set (const int indexToChange, - ObjectClass* const newObject) - { - if (indexToChange >= 0) - { - lock.enter(); - - if (newObject != 0) - newObject->incReferenceCount(); - - if (indexToChange < numUsed) - { - if (data.elements [indexToChange] != 0) - data.elements [indexToChange]->decReferenceCount(); - - data.elements [indexToChange] = newObject; - } - else - { - data.ensureAllocatedSize (numUsed + 1); - data.elements [numUsed++] = newObject; - } - - lock.exit(); - } - } - - /** Adds elements from another array to the end of this array. - - @param arrayToAddFrom the array from which to copy the elements - @param startIndex the first element of the other array to start copying from - @param numElementsToAdd how many elements to add from the other array. If this - value is negative or greater than the number of available elements, - all available elements will be copied. - @see add - */ - void addArray (const ReferenceCountedArray& arrayToAddFrom, - int startIndex = 0, - int numElementsToAdd = -1) throw() - { - arrayToAddFrom.lockArray(); - lock.enter(); - - if (startIndex < 0) - { - jassertfalse - startIndex = 0; - } - - if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size()) - numElementsToAdd = arrayToAddFrom.size() - startIndex; - - if (numElementsToAdd > 0) - { - data.ensureAllocatedSize (numUsed + numElementsToAdd); - - while (--numElementsToAdd >= 0) - add (arrayToAddFrom.getUnchecked (startIndex++)); - } - - lock.exit(); - arrayToAddFrom.unlockArray(); - } - - /** Inserts a new object into the array assuming that the array is sorted. - - This will use a comparator to find the position at which the new object - should go. If the array isn't sorted, the behaviour of this - method will be unpredictable. - - @param comparator the comparator object to use to compare the elements - see the - sort() method for details about this object's form - @param newObject the new object to insert to the array - @see add, sort - */ - template - void addSorted (ElementComparator& comparator, - ObjectClass* newObject) throw() - { - lock.enter(); - insert (findInsertIndexInSortedArray (comparator, data.elements, newObject, 0, numUsed), newObject); - lock.exit(); - } - - /** Inserts or replaces an object in the array, assuming it is sorted. - - This is similar to addSorted, but if a matching element already exists, then it will be - replaced by the new one, rather than the new one being added as well. - */ - template - void addOrReplaceSorted (ElementComparator& comparator, - ObjectClass* newObject) throw() - { - lock.enter(); - const int index = findInsertIndexInSortedArray (comparator, data.elements, newObject, 0, numUsed); - - if (index > 0 && comparator.compareElements (newObject, data.elements [index - 1]) == 0) - set (index - 1, newObject); // replace an existing object that matches - else - insert (index, newObject); // no match, so insert the new one - - lock.exit(); - } - - /** Removes an object from the array. - - This will remove the object at a given index and move back all the - subsequent objects to close the gap. - - If the index passed in is out-of-range, nothing will happen. - - The object that is removed will have its reference count decreased, - and may be deleted if not referenced from elsewhere. - - @param indexToRemove the index of the element to remove - @see removeObject, removeRange - */ - void remove (const int indexToRemove) - { - lock.enter(); - - if (((unsigned int) indexToRemove) < (unsigned int) numUsed) - { - ObjectClass** const e = data.elements + indexToRemove; - - if (*e != 0) - (*e)->decReferenceCount(); - - --numUsed; - const int numberToShift = numUsed - indexToRemove; - - if (numberToShift > 0) - memmove (e, e + 1, numberToShift * sizeof (ObjectClass*)); - - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); - } - - lock.exit(); - } - - /** Removes the first occurrence of a specified object from the array. - - If the item isn't found, no action is taken. If it is found, it is - removed and has its reference count decreased. - - @param objectToRemove the object to try to remove - @see remove, removeRange - */ - void removeObject (ObjectClass* const objectToRemove) - { - lock.enter(); - remove (indexOf (objectToRemove)); - lock.exit(); - } - - /** Removes a range of objects from the array. - - This will remove a set of objects, starting from the given index, - and move any subsequent elements down to close the gap. - - If the range extends beyond the bounds of the array, it will - be safely clipped to the size of the array. - - The objects that are removed will have their reference counts decreased, - and may be deleted if not referenced from elsewhere. - - @param startIndex the index of the first object to remove - @param numberToRemove how many objects should be removed - @see remove, removeObject - */ - void removeRange (const int startIndex, - const int numberToRemove) - { - lock.enter(); - - const int start = jlimit (0, numUsed, startIndex); - const int end = jlimit (0, numUsed, startIndex + numberToRemove); - - if (end > start) - { - int i; - for (i = start; i < end; ++i) - { - if (data.elements[i] != 0) - { - data.elements[i]->decReferenceCount(); - data.elements[i] = 0; // (in case one of the destructors accesses this array and hits a dangling pointer) - } - } - - const int rangeSize = end - start; - ObjectClass** e = data.elements + start; - i = numUsed - end; - numUsed -= rangeSize; - - while (--i >= 0) - { - *e = e [rangeSize]; - ++e; - } - - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); - } - - lock.exit(); - } - - /** Removes the last n objects from the array. - - The objects that are removed will have their reference counts decreased, - and may be deleted if not referenced from elsewhere. - - @param howManyToRemove how many objects to remove from the end of the array - @see remove, removeObject, removeRange - */ - void removeLast (int howManyToRemove = 1) - { - lock.enter(); - - if (howManyToRemove > numUsed) - howManyToRemove = numUsed; - - while (--howManyToRemove >= 0) - remove (numUsed - 1); - - lock.exit(); - } - - /** Swaps a pair of objects in the array. - - If either of the indexes passed in is out-of-range, nothing will happen, - otherwise the two objects at these positions will be exchanged. - */ - void swap (const int index1, - const int index2) throw() - { - lock.enter(); - - if (((unsigned int) index1) < (unsigned int) numUsed - && ((unsigned int) index2) < (unsigned int) numUsed) - { - swapVariables (data.elements [index1], - data.elements [index2]); - } - - lock.exit(); - } - - /** Moves one of the objects to a different position. - - This will move the object to a specified index, shuffling along - any intervening elements as required. - - So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling - move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }. - - @param currentIndex the index of the object to be moved. If this isn't a - valid index, then nothing will be done - @param newIndex the index at which you'd like this object to end up. If this - is less than zero, it will be moved to the end of the array - */ - void move (const int currentIndex, - int newIndex) throw() - { - if (currentIndex != newIndex) - { - lock.enter(); - - if (((unsigned int) currentIndex) < (unsigned int) numUsed) - { - if (((unsigned int) newIndex) >= (unsigned int) numUsed) - newIndex = numUsed - 1; - - ObjectClass* const value = data.elements [currentIndex]; - - if (newIndex > currentIndex) - { - memmove (data.elements + currentIndex, - data.elements + currentIndex + 1, - (newIndex - currentIndex) * sizeof (ObjectClass*)); - } - else - { - memmove (data.elements + newIndex + 1, - data.elements + newIndex, - (currentIndex - newIndex) * sizeof (ObjectClass*)); - } - - data.elements [newIndex] = value; - } - - lock.exit(); - } - } - - /** Compares this array to another one. - - @returns true only if the other array contains the same objects in the same order - */ - bool operator== (const ReferenceCountedArray& other) const throw() - { - other.lockArray(); - lock.enter(); - - bool result = numUsed == other.numUsed; - - if (result) - { - for (int i = numUsed; --i >= 0;) - { - if (data.elements [i] != other.data.elements [i]) - { - result = false; - break; - } - } - } - - lock.exit(); - other.unlockArray(); - - return result; - } - - /** Compares this array to another one. - - @see operator== - */ - bool operator!= (const ReferenceCountedArray& other) const throw() - { - return ! operator== (other); - } - - /** Sorts the elements in the array. - - This will use a comparator object to sort the elements into order. The object - passed must have a method of the form: - @code - int compareElements (ElementType first, ElementType second); - @endcode - - ..and this method must return: - - a value of < 0 if the first comes before the second - - a value of 0 if the two objects are equivalent - - a value of > 0 if the second comes before the first - - To improve performance, the compareElements() method can be declared as static or const. - - @param comparator the comparator to use for comparing elements. - @param retainOrderOfEquivalentItems if this is true, then items - which the comparator says are equivalent will be - kept in the order in which they currently appear - in the array. This is slower to perform, but may - be important in some cases. If it's false, a faster - algorithm is used, but equivalent elements may be - rearranged. - - @see sortArray - */ - template - void sort (ElementComparator& comparator, - const bool retainOrderOfEquivalentItems = false) const throw() - { - (void) comparator; // if you pass in an object with a static compareElements() method, this - // avoids getting warning messages about the parameter being unused - - lock.enter(); - sortArray (comparator, data.elements, 0, size() - 1, retainOrderOfEquivalentItems); - lock.exit(); - } - - /** Reduces the amount of storage being used by the array. - - Arrays typically allocate slightly more storage than they need, and after - removing elements, they may have quite a lot of unused space allocated. - This method will reduce the amount of allocated storage to a minimum. - */ - void minimiseStorageOverheads() throw() - { - lock.enter(); - - if (numUsed == 0) - { - data.setAllocatedSize (0); - } - else - { - const int newAllocation = data.granularity * (numUsed / data.granularity + 1); - - if (newAllocation < data.numAllocated) - data.setAllocatedSize (newAllocation); - } - - lock.exit(); - } - - /** Locks the array's CriticalSection. - - Of course if the type of section used is a DummyCriticalSection, this won't - have any effect. - - @see unlockArray - */ - void lockArray() const throw() - { - lock.enter(); - } - - /** Unlocks the array's CriticalSection. - - Of course if the type of section used is a DummyCriticalSection, this won't - have any effect. - - @see lockArray - */ - void unlockArray() const throw() - { - lock.exit(); - } - - juce_UseDebuggingNewOperator + ReferenceCountedArray() throw() + : numUsed (0) + { + } + + ReferenceCountedArray (const ReferenceCountedArray& other) throw() + { + other.lockArray(); + numUsed = other.numUsed; + data.setAllocatedSize (numUsed); + memcpy (data.elements, other.data.elements, numUsed * sizeof (ObjectClass*)); + + for (int i = numUsed; --i >= 0;) + if (data.elements[i] != 0) + data.elements[i]->incReferenceCount(); + + other.unlockArray(); + } + + const ReferenceCountedArray& operator= (const ReferenceCountedArray& other) throw() + { + if (this != &other) + { + other.lockArray(); + lock.enter(); + + clear(); + + data.ensureAllocatedSize (other.numUsed); + numUsed = other.numUsed; + memcpy (data.elements, other.data.elements, numUsed * sizeof (ObjectClass*)); + minimiseStorageOverheads(); + + for (int i = numUsed; --i >= 0;) + if (data.elements[i] != 0) + data.elements[i]->incReferenceCount(); + + lock.exit(); + other.unlockArray(); + } + + return *this; + } + + ~ReferenceCountedArray() + { + clear(); + } + + void clear() + { + lock.enter(); + + while (numUsed > 0) + if (data.elements [--numUsed] != 0) + data.elements [numUsed]->decReferenceCount(); + + jassert (numUsed == 0); + data.setAllocatedSize (0); + + lock.exit(); + } + + inline int size() const throw() + { + return numUsed; + } + + inline const ReferenceCountedObjectPtr operator[] (const int index) const throw() + { + lock.enter(); + const ReferenceCountedObjectPtr result ((((unsigned int) index) < (unsigned int) numUsed) + ? data.elements [index] + : (ObjectClass*) 0); + lock.exit(); + return result; + } + + inline const ReferenceCountedObjectPtr getUnchecked (const int index) const throw() + { + lock.enter(); + jassert (((unsigned int) index) < (unsigned int) numUsed); + const ReferenceCountedObjectPtr result (data.elements [index]); + lock.exit(); + return result; + } + + inline const ReferenceCountedObjectPtr getFirst() const throw() + { + lock.enter(); + const ReferenceCountedObjectPtr result ((numUsed > 0) ? data.elements [0] + : (ObjectClass*) 0); + lock.exit(); + + return result; + } + + inline const ReferenceCountedObjectPtr getLast() const throw() + { + lock.enter(); + const ReferenceCountedObjectPtr result ((numUsed > 0) ? data.elements [numUsed - 1] + : (ObjectClass*) 0); + lock.exit(); + + return result; + } + + int indexOf (const ObjectClass* const objectToLookFor) const throw() + { + int result = -1; + + lock.enter(); + ObjectClass** e = data.elements; + + for (int i = numUsed; --i >= 0;) + { + if (objectToLookFor == *e) + { + result = (int) (e - data.elements); + break; + } + + ++e; + } + + lock.exit(); + return result; + } + + bool contains (const ObjectClass* const objectToLookFor) const throw() + { + lock.enter(); + ObjectClass** e = data.elements; + + for (int i = numUsed; --i >= 0;) + { + if (objectToLookFor == *e) + { + lock.exit(); + return true; + } + + ++e; + } + + lock.exit(); + return false; + } + + void add (ObjectClass* const newObject) throw() + { + lock.enter(); + data.ensureAllocatedSize (numUsed + 1); + data.elements [numUsed++] = newObject; + + if (newObject != 0) + newObject->incReferenceCount(); + + lock.exit(); + } + + void insert (int indexToInsertAt, + ObjectClass* const newObject) throw() + { + if (indexToInsertAt >= 0) + { + lock.enter(); + + if (indexToInsertAt > numUsed) + indexToInsertAt = numUsed; + + data.ensureAllocatedSize (numUsed + 1); + + ObjectClass** const e = data.elements + indexToInsertAt; + const int numToMove = numUsed - indexToInsertAt; + + if (numToMove > 0) + memmove (e + 1, e, numToMove * sizeof (ObjectClass*)); + + *e = newObject; + + if (newObject != 0) + newObject->incReferenceCount(); + + ++numUsed; + lock.exit(); + } + else + { + add (newObject); + } + } + + void addIfNotAlreadyThere (ObjectClass* const newObject) throw() + { + lock.enter(); + + if (! contains (newObject)) + add (newObject); + + lock.exit(); + } + + void set (const int indexToChange, + ObjectClass* const newObject) + { + if (indexToChange >= 0) + { + lock.enter(); + + if (newObject != 0) + newObject->incReferenceCount(); + + if (indexToChange < numUsed) + { + if (data.elements [indexToChange] != 0) + data.elements [indexToChange]->decReferenceCount(); + + data.elements [indexToChange] = newObject; + } + else + { + data.ensureAllocatedSize (numUsed + 1); + data.elements [numUsed++] = newObject; + } + + lock.exit(); + } + } + + void addArray (const ReferenceCountedArray& arrayToAddFrom, + int startIndex = 0, + int numElementsToAdd = -1) throw() + { + arrayToAddFrom.lockArray(); + lock.enter(); + + if (startIndex < 0) + { + jassertfalse + startIndex = 0; + } + + if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size()) + numElementsToAdd = arrayToAddFrom.size() - startIndex; + + if (numElementsToAdd > 0) + { + data.ensureAllocatedSize (numUsed + numElementsToAdd); + + while (--numElementsToAdd >= 0) + add (arrayToAddFrom.getUnchecked (startIndex++)); + } + + lock.exit(); + arrayToAddFrom.unlockArray(); + } + + template + void addSorted (ElementComparator& comparator, + ObjectClass* newObject) throw() + { + lock.enter(); + insert (findInsertIndexInSortedArray (comparator, data.elements, newObject, 0, numUsed), newObject); + lock.exit(); + } + + template + void addOrReplaceSorted (ElementComparator& comparator, + ObjectClass* newObject) throw() + { + lock.enter(); + const int index = findInsertIndexInSortedArray (comparator, data.elements, newObject, 0, numUsed); + + if (index > 0 && comparator.compareElements (newObject, data.elements [index - 1]) == 0) + set (index - 1, newObject); // replace an existing object that matches + else + insert (index, newObject); // no match, so insert the new one + + lock.exit(); + } + + void remove (const int indexToRemove) + { + lock.enter(); + + if (((unsigned int) indexToRemove) < (unsigned int) numUsed) + { + ObjectClass** const e = data.elements + indexToRemove; + + if (*e != 0) + (*e)->decReferenceCount(); + + --numUsed; + const int numberToShift = numUsed - indexToRemove; + + if (numberToShift > 0) + memmove (e, e + 1, numberToShift * sizeof (ObjectClass*)); + + if ((numUsed << 1) < data.numAllocated) + minimiseStorageOverheads(); + } + + lock.exit(); + } + + void removeObject (ObjectClass* const objectToRemove) + { + lock.enter(); + remove (indexOf (objectToRemove)); + lock.exit(); + } + + void removeRange (const int startIndex, + const int numberToRemove) + { + lock.enter(); + + const int start = jlimit (0, numUsed, startIndex); + const int end = jlimit (0, numUsed, startIndex + numberToRemove); + + if (end > start) + { + int i; + for (i = start; i < end; ++i) + { + if (data.elements[i] != 0) + { + data.elements[i]->decReferenceCount(); + data.elements[i] = 0; // (in case one of the destructors accesses this array and hits a dangling pointer) + } + } + + const int rangeSize = end - start; + ObjectClass** e = data.elements + start; + i = numUsed - end; + numUsed -= rangeSize; + + while (--i >= 0) + { + *e = e [rangeSize]; + ++e; + } + + if ((numUsed << 1) < data.numAllocated) + minimiseStorageOverheads(); + } + + lock.exit(); + } + + void removeLast (int howManyToRemove = 1) + { + lock.enter(); + + if (howManyToRemove > numUsed) + howManyToRemove = numUsed; + + while (--howManyToRemove >= 0) + remove (numUsed - 1); + + lock.exit(); + } + + void swap (const int index1, + const int index2) throw() + { + lock.enter(); + + if (((unsigned int) index1) < (unsigned int) numUsed + && ((unsigned int) index2) < (unsigned int) numUsed) + { + swapVariables (data.elements [index1], + data.elements [index2]); + } + + lock.exit(); + } + + void move (const int currentIndex, + int newIndex) throw() + { + if (currentIndex != newIndex) + { + lock.enter(); + + if (((unsigned int) currentIndex) < (unsigned int) numUsed) + { + if (((unsigned int) newIndex) >= (unsigned int) numUsed) + newIndex = numUsed - 1; + + ObjectClass* const value = data.elements [currentIndex]; + + if (newIndex > currentIndex) + { + memmove (data.elements + currentIndex, + data.elements + currentIndex + 1, + (newIndex - currentIndex) * sizeof (ObjectClass*)); + } + else + { + memmove (data.elements + newIndex + 1, + data.elements + newIndex, + (currentIndex - newIndex) * sizeof (ObjectClass*)); + } + + data.elements [newIndex] = value; + } + + lock.exit(); + } + } + + bool operator== (const ReferenceCountedArray& other) const throw() + { + other.lockArray(); + lock.enter(); + + bool result = numUsed == other.numUsed; + + if (result) + { + for (int i = numUsed; --i >= 0;) + { + if (data.elements [i] != other.data.elements [i]) + { + result = false; + break; + } + } + } + + lock.exit(); + other.unlockArray(); + + return result; + } + + bool operator!= (const ReferenceCountedArray& other) const throw() + { + return ! operator== (other); + } + + template + void sort (ElementComparator& comparator, + const bool retainOrderOfEquivalentItems = false) const throw() + { + (void) comparator; // if you pass in an object with a static compareElements() method, this + // avoids getting warning messages about the parameter being unused + + lock.enter(); + sortArray (comparator, data.elements, 0, size() - 1, retainOrderOfEquivalentItems); + lock.exit(); + } + + void minimiseStorageOverheads() throw() + { + lock.enter(); + data.shrinkToNoMoreThan (numUsed); + lock.exit(); + } + + void lockArray() const throw() + { + lock.enter(); + } + + void unlockArray() const throw() + { + lock.exit(); + } + + juce_UseDebuggingNewOperator private: - ArrayAllocationBase data; - int numUsed; - TypeOfCriticalSectionToUse lock; + ArrayAllocationBase data; + int numUsed; + TypeOfCriticalSectionToUse lock; }; #endif // __JUCE_REFERENCECOUNTEDARRAY_JUCEHEADER__ @@ -10228,594 +5189,409 @@ private: #pragma warning (disable: 4512) #endif -/** - Holds a set of unique primitive objects, such as ints or doubles. - - A set can only hold one item with a given value, so if for example it's a - set of integers, attempting to add the same integer twice will do nothing - the second time. - - Internally, the list of items is kept sorted (which means that whatever - kind of primitive type is used must support the ==, <, >, <= and >= operators - to determine the order), and searching the set for known values is very fast - because it uses a binary-chop method. - - Note that if you're using a class or struct as the element type, it must be - capable of being copied or moved with a straightforward memcpy, rather than - needing construction and destruction code. - - To make all the set's methods thread-safe, pass in "CriticalSection" as the templated - TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection. - - @see Array, OwnedArray, ReferenceCountedArray, StringArray, CriticalSection -*/ template class SortedSet { public: - /** Creates an empty set. - - @param granularity this is the size of increment by which the internal storage - used by the array will grow. Only change it from the default if you know the - array is going to be very big and needs to be able to grow efficiently. - */ - SortedSet (const int granularity = juceDefaultArrayGranularity) throw() - : data (granularity), - numUsed (0) - { - } - - /** Creates a copy of another set. - @param other the set to copy - */ - SortedSet (const SortedSet& other) throw() - : data (other.data.granularity) - { - other.lockSet(); - numUsed = other.numUsed; - data.setAllocatedSize (other.numUsed); - memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); - other.unlockSet(); - } - - /** Destructor. */ - ~SortedSet() throw() - { - } - - /** Copies another set over this one. - @param other the set to copy - */ - const SortedSet & operator= (const SortedSet & other) throw() - { - if (this != &other) - { - other.lockSet(); - lock.enter(); - - data.granularity = other.data.granularity; - data.ensureAllocatedSize (other.size()); - numUsed = other.numUsed; - memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); - minimiseStorageOverheads(); - - lock.exit(); - other.unlockSet(); - } - - return *this; - } - - /** Compares this set to another one. - - Two sets are considered equal if they both contain the same set of - elements. - - @param other the other set to compare with - */ - bool operator== (const SortedSet& other) const throw() - { - lock.enter(); - - if (numUsed != other.numUsed) - { - lock.exit(); - return false; - } - - for (int i = numUsed; --i >= 0;) - { - if (data.elements [i] != other.data.elements [i]) - { - lock.exit(); - return false; - } - } - - lock.exit(); - return true; - } - - /** Compares this set to another one. - - Two sets are considered equal if they both contain the same set of - elements. - - @param other the other set to compare with - */ - bool operator!= (const SortedSet& other) const throw() - { - return ! operator== (other); - } - - /** Removes all elements from the set. - - This will remove all the elements, and free any storage that the set is - using. To clear it without freeing the storage, use the clearQuick() - method instead. - - @see clearQuick - */ - void clear() throw() - { - lock.enter(); - data.setAllocatedSize (0); - numUsed = 0; - lock.exit(); - } - - /** Removes all elements from the set without freeing the array's allocated storage. - - @see clear - */ - void clearQuick() throw() - { - lock.enter(); - numUsed = 0; - lock.exit(); - } - - /** Returns the current number of elements in the set. - */ - inline int size() const throw() - { - return numUsed; - } - - /** Returns one of the elements in the set. - - If the index passed in is beyond the range of valid elements, this - will return zero. - - If you're certain that the index will always be a valid element, you - can call getUnchecked() instead, which is faster. - - @param index the index of the element being requested (0 is the first element in the set) - @see getUnchecked, getFirst, getLast - */ - inline ElementType operator[] (const int index) const throw() - { - lock.enter(); - const ElementType result = (((unsigned int) index) < (unsigned int) numUsed) - ? data.elements [index] - : (ElementType) 0; - lock.exit(); - - return result; - } - - /** Returns one of the elements in the set, without checking the index passed in. - Unlike the operator[] method, this will try to return an element without - checking that the index is within the bounds of the set, so should only - be used when you're confident that it will always be a valid index. - - @param index the index of the element being requested (0 is the first element in the set) - @see operator[], getFirst, getLast - */ - inline ElementType getUnchecked (const int index) const throw() - { - lock.enter(); - jassert (((unsigned int) index) < (unsigned int) numUsed); - const ElementType result = data.elements [index]; - lock.exit(); - - return result; - } - - /** Returns the first element in the set, or 0 if the set is empty. - - @see operator[], getUnchecked, getLast - */ - inline ElementType getFirst() const throw() - { - lock.enter(); - const ElementType result = (numUsed > 0) ? data.elements [0] - : (ElementType) 0; - lock.exit(); - - return result; - } - - /** Returns the last element in the set, or 0 if the set is empty. - - @see operator[], getUnchecked, getFirst - */ - inline ElementType getLast() const throw() - { - lock.enter(); - const ElementType result = (numUsed > 0) ? data.elements [numUsed - 1] - : (ElementType) 0; - lock.exit(); - - return result; - } - - /** Finds the index of the first element which matches the value passed in. - - This will search the set for the given object, and return the index - of its first occurrence. If the object isn't found, the method will return -1. - - @param elementToLookFor the value or object to look for - @returns the index of the object, or -1 if it's not found - */ - int indexOf (const ElementType elementToLookFor) const throw() - { - lock.enter(); - - int start = 0; - int end = numUsed; - - for (;;) - { - if (start >= end) - { - lock.exit(); - return -1; - } - else if (elementToLookFor == data.elements [start]) - { - lock.exit(); - return start; - } - else - { - const int halfway = (start + end) >> 1; - - if (halfway == start) - { - lock.exit(); - return -1; - } - else if (elementToLookFor >= data.elements [halfway]) - start = halfway; - else - end = halfway; - } - } - } - - /** Returns true if the set contains at least one occurrence of an object. - - @param elementToLookFor the value or object to look for - @returns true if the item is found - */ - bool contains (const ElementType elementToLookFor) const throw() - { - lock.enter(); - - int start = 0; - int end = numUsed; - - for (;;) - { - if (start >= end) - { - lock.exit(); - return false; - } - else if (elementToLookFor == data.elements [start]) - { - lock.exit(); - return true; - } - else - { - const int halfway = (start + end) >> 1; - - if (halfway == start) - { - lock.exit(); - return false; - } - else if (elementToLookFor >= data.elements [halfway]) - start = halfway; - else - end = halfway; - } - } - } - - /** Adds a new element to the set, (as long as it's not already in there). - - @param newElement the new object to add to the set - @see set, insert, addIfNotAlreadyThere, addSorted, addSet, addArray - */ - void add (const ElementType newElement) throw() - { - lock.enter(); - - int start = 0; - int end = numUsed; - - for (;;) - { - if (start >= end) - { - jassert (start <= end); - insertInternal (start, newElement); - break; - } - else if (newElement == data.elements [start]) - { - break; - } - else - { - const int halfway = (start + end) >> 1; - - if (halfway == start) - { - if (newElement >= data.elements [halfway]) - insertInternal (start + 1, newElement); - else - insertInternal (start, newElement); - - break; - } - else if (newElement >= data.elements [halfway]) - start = halfway; - else - end = halfway; - } - } - - lock.exit(); - } - - /** Adds elements from an array to this set. - - @param elementsToAdd the array of elements to add - @param numElementsToAdd how many elements are in this other array - @see add - */ - void addArray (const ElementType* elementsToAdd, - int numElementsToAdd) throw() - { - lock.enter(); - - while (--numElementsToAdd >= 0) - add (*elementsToAdd++); - - lock.exit(); - } - - /** Adds elements from another set to this one. - - @param setToAddFrom the set from which to copy the elements - @param startIndex the first element of the other set to start copying from - @param numElementsToAdd how many elements to add from the other set. If this - value is negative or greater than the number of available elements, - all available elements will be copied. - @see add - */ - template - void addSet (const OtherSetType& setToAddFrom, - int startIndex = 0, - int numElementsToAdd = -1) throw() - { - setToAddFrom.lockSet(); - lock.enter(); - jassert (this != &setToAddFrom); - - if (this != &setToAddFrom) - { - if (startIndex < 0) - { - jassertfalse - startIndex = 0; - } - - if (numElementsToAdd < 0 || startIndex + numElementsToAdd > setToAddFrom.size()) - numElementsToAdd = setToAddFrom.size() - startIndex; - - addArray (setToAddFrom.elements + startIndex, numElementsToAdd); - } - - lock.exit(); - setToAddFrom.unlockSet(); - } - - /** Removes an element from the set. - - This will remove the element at a given index. - If the index passed in is out-of-range, nothing will happen. - - @param indexToRemove the index of the element to remove - @returns the element that has been removed - @see removeValue, removeRange - */ - ElementType remove (const int indexToRemove) throw() - { - lock.enter(); - - if (((unsigned int) indexToRemove) < (unsigned int) numUsed) - { - --numUsed; - - ElementType* const e = data.elements + indexToRemove; - ElementType const removed = *e; - const int numberToShift = numUsed - indexToRemove; - - if (numberToShift > 0) - memmove (e, e + 1, numberToShift * sizeof (ElementType)); - - if ((numUsed << 1) < data.numAllocated) - minimiseStorageOverheads(); - - lock.exit(); - return removed; - } - else - { - lock.exit(); - return 0; - } - } - - /** Removes an item from the set. - - This will remove the given element from the set, if it's there. - - @param valueToRemove the object to try to remove - @see remove, removeRange - */ - void removeValue (const ElementType valueToRemove) throw() - { - lock.enter(); - remove (indexOf (valueToRemove)); - lock.exit(); - } - - /** Removes any elements which are also in another set. - - @param otherSet the other set in which to look for elements to remove - @see removeValuesNotIn, remove, removeValue, removeRange - */ - template - void removeValuesIn (const OtherSetType& otherSet) throw() - { - otherSet.lockSet(); - lock.enter(); - - if (this == &otherSet) - { - clear(); - } - else - { - if (otherSet.size() > 0) - { - for (int i = numUsed; --i >= 0;) - if (otherSet.contains (data.elements [i])) - remove (i); - } - } - - lock.exit(); - otherSet.unlockSet(); - } - - /** Removes any elements which are not found in another set. - - Only elements which occur in this other set will be retained. - - @param otherSet the set in which to look for elements NOT to remove - @see removeValuesIn, remove, removeValue, removeRange - */ - template - void removeValuesNotIn (const OtherSetType& otherSet) throw() - { - otherSet.lockSet(); - lock.enter(); - - if (this != &otherSet) - { - if (otherSet.size() <= 0) - { - clear(); - } - else - { - for (int i = numUsed; --i >= 0;) - if (! otherSet.contains (data.elements [i])) - remove (i); - } - } - - lock.exit(); - otherSet.lockSet(); - } - - /** Reduces the amount of storage being used by the set. - - Sets typically allocate slightly more storage than they need, and after - removing elements, they may have quite a lot of unused space allocated. - This method will reduce the amount of allocated storage to a minimum. - */ - void minimiseStorageOverheads() throw() - { - lock.enter(); - - if (numUsed == 0) - { - data.setAllocatedSize (0); - } - else - { - const int newAllocation = data.granularity * (numUsed / data.granularity + 1); - - if (newAllocation < data.numAllocated) - data.setAllocatedSize (newAllocation); - } - - lock.exit(); - } - - /** Locks the set's CriticalSection. - - Of course if the type of section used is a DummyCriticalSection, this won't - have any effect. - - @see unlockSet - */ - void lockSet() const throw() - { - lock.enter(); - } - - /** Unlocks the set's CriticalSection. - - Of course if the type of section used is a DummyCriticalSection, this won't - have any effect. - - @see lockSet - */ - void unlockSet() const throw() - { - lock.exit(); - } - - juce_UseDebuggingNewOperator + SortedSet() throw() + : numUsed (0) + { + } + + SortedSet (const SortedSet& other) throw() + { + other.lockSet(); + numUsed = other.numUsed; + data.setAllocatedSize (other.numUsed); + memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); + other.unlockSet(); + } + + ~SortedSet() throw() + { + } + + const SortedSet & operator= (const SortedSet & other) throw() + { + if (this != &other) + { + other.lockSet(); + lock.enter(); + + data.ensureAllocatedSize (other.size()); + numUsed = other.numUsed; + memcpy (data.elements, other.data.elements, numUsed * sizeof (ElementType)); + minimiseStorageOverheads(); + + lock.exit(); + other.unlockSet(); + } + + return *this; + } + + bool operator== (const SortedSet& other) const throw() + { + lock.enter(); + + if (numUsed != other.numUsed) + { + lock.exit(); + return false; + } + + for (int i = numUsed; --i >= 0;) + { + if (data.elements [i] != other.data.elements [i]) + { + lock.exit(); + return false; + } + } + + lock.exit(); + return true; + } + + bool operator!= (const SortedSet& other) const throw() + { + return ! operator== (other); + } + + void clear() throw() + { + lock.enter(); + data.setAllocatedSize (0); + numUsed = 0; + lock.exit(); + } + + void clearQuick() throw() + { + lock.enter(); + numUsed = 0; + lock.exit(); + } + + inline int size() const throw() + { + return numUsed; + } + + inline ElementType operator[] (const int index) const throw() + { + lock.enter(); + const ElementType result = (((unsigned int) index) < (unsigned int) numUsed) + ? data.elements [index] + : (ElementType) 0; + lock.exit(); + + return result; + } + + inline ElementType getUnchecked (const int index) const throw() + { + lock.enter(); + jassert (((unsigned int) index) < (unsigned int) numUsed); + const ElementType result = data.elements [index]; + lock.exit(); + + return result; + } + + inline ElementType getFirst() const throw() + { + lock.enter(); + const ElementType result = (numUsed > 0) ? data.elements [0] + : (ElementType) 0; + lock.exit(); + + return result; + } + + inline ElementType getLast() const throw() + { + lock.enter(); + const ElementType result = (numUsed > 0) ? data.elements [numUsed - 1] + : (ElementType) 0; + lock.exit(); + + return result; + } + + int indexOf (const ElementType elementToLookFor) const throw() + { + lock.enter(); + + int start = 0; + int end = numUsed; + + for (;;) + { + if (start >= end) + { + lock.exit(); + return -1; + } + else if (elementToLookFor == data.elements [start]) + { + lock.exit(); + return start; + } + else + { + const int halfway = (start + end) >> 1; + + if (halfway == start) + { + lock.exit(); + return -1; + } + else if (elementToLookFor >= data.elements [halfway]) + start = halfway; + else + end = halfway; + } + } + } + + bool contains (const ElementType elementToLookFor) const throw() + { + lock.enter(); + + int start = 0; + int end = numUsed; + + for (;;) + { + if (start >= end) + { + lock.exit(); + return false; + } + else if (elementToLookFor == data.elements [start]) + { + lock.exit(); + return true; + } + else + { + const int halfway = (start + end) >> 1; + + if (halfway == start) + { + lock.exit(); + return false; + } + else if (elementToLookFor >= data.elements [halfway]) + start = halfway; + else + end = halfway; + } + } + } + + void add (const ElementType newElement) throw() + { + lock.enter(); + + int start = 0; + int end = numUsed; + + for (;;) + { + if (start >= end) + { + jassert (start <= end); + insertInternal (start, newElement); + break; + } + else if (newElement == data.elements [start]) + { + break; + } + else + { + const int halfway = (start + end) >> 1; + + if (halfway == start) + { + if (newElement >= data.elements [halfway]) + insertInternal (start + 1, newElement); + else + insertInternal (start, newElement); + + break; + } + else if (newElement >= data.elements [halfway]) + start = halfway; + else + end = halfway; + } + } + + lock.exit(); + } + + void addArray (const ElementType* elementsToAdd, + int numElementsToAdd) throw() + { + lock.enter(); + + while (--numElementsToAdd >= 0) + add (*elementsToAdd++); + + lock.exit(); + } + + template + void addSet (const OtherSetType& setToAddFrom, + int startIndex = 0, + int numElementsToAdd = -1) throw() + { + setToAddFrom.lockSet(); + lock.enter(); + jassert (this != &setToAddFrom); + + if (this != &setToAddFrom) + { + if (startIndex < 0) + { + jassertfalse + startIndex = 0; + } + + if (numElementsToAdd < 0 || startIndex + numElementsToAdd > setToAddFrom.size()) + numElementsToAdd = setToAddFrom.size() - startIndex; + + addArray (setToAddFrom.elements + startIndex, numElementsToAdd); + } + + lock.exit(); + setToAddFrom.unlockSet(); + } + + ElementType remove (const int indexToRemove) throw() + { + lock.enter(); + + if (((unsigned int) indexToRemove) < (unsigned int) numUsed) + { + --numUsed; + + ElementType* const e = data.elements + indexToRemove; + ElementType const removed = *e; + const int numberToShift = numUsed - indexToRemove; + + if (numberToShift > 0) + memmove (e, e + 1, numberToShift * sizeof (ElementType)); + + if ((numUsed << 1) < data.numAllocated) + minimiseStorageOverheads(); + + lock.exit(); + return removed; + } + else + { + lock.exit(); + return 0; + } + } + + void removeValue (const ElementType valueToRemove) throw() + { + lock.enter(); + remove (indexOf (valueToRemove)); + lock.exit(); + } + + template + void removeValuesIn (const OtherSetType& otherSet) throw() + { + otherSet.lockSet(); + lock.enter(); + + if (this == &otherSet) + { + clear(); + } + else + { + if (otherSet.size() > 0) + { + for (int i = numUsed; --i >= 0;) + if (otherSet.contains (data.elements [i])) + remove (i); + } + } + + lock.exit(); + otherSet.unlockSet(); + } + + template + void removeValuesNotIn (const OtherSetType& otherSet) throw() + { + otherSet.lockSet(); + lock.enter(); + + if (this != &otherSet) + { + if (otherSet.size() <= 0) + { + clear(); + } + else + { + for (int i = numUsed; --i >= 0;) + if (! otherSet.contains (data.elements [i])) + remove (i); + } + } + + lock.exit(); + otherSet.lockSet(); + } + + void minimiseStorageOverheads() throw() + { + lock.enter(); + data.shrinkToNoMoreThan (numUsed); + lock.exit(); + } + + void lockSet() const throw() + { + lock.enter(); + } + + void unlockSet() const throw() + { + lock.exit(); + } + + juce_UseDebuggingNewOperator private: - ArrayAllocationBase data; - int numUsed; - TypeOfCriticalSectionToUse lock; + ArrayAllocationBase data; + int numUsed; + TypeOfCriticalSectionToUse lock; - void insertInternal (const int indexToInsertAt, const ElementType newElement) throw() - { - data.ensureAllocatedSize (numUsed + 1); + void insertInternal (const int indexToInsertAt, const ElementType newElement) throw() + { + data.ensureAllocatedSize (numUsed + 1); - ElementType* const insertPos = data.elements + indexToInsertAt; - const int numberToMove = numUsed - indexToInsertAt; + ElementType* const insertPos = data.elements + indexToInsertAt; + const int numberToMove = numUsed - indexToInsertAt; - if (numberToMove > 0) - memmove (insertPos + 1, insertPos, numberToMove * sizeof (ElementType)); + if (numberToMove > 0) + memmove (insertPos + 1, insertPos, numberToMove * sizeof (ElementType)); - *insertPos = newElement; - ++numUsed; - } + *insertPos = newElement; + ++numUsed; + } }; #if JUCE_MSVC @@ -10832,320 +5608,256 @@ private: #ifndef __JUCE_SPARSESET_JUCEHEADER__ #define __JUCE_SPARSESET_JUCEHEADER__ -/** - Holds a set of primitive values, storing them as a set of ranges. - - This container acts like a simple BitArray, but can efficiently hold large - continguous ranges of values. It's quite a specialised class, mostly useful - for things like keeping the set of selected rows in a listbox. - - The type used as a template paramter must be an integer type, such as int, short, - int64, etc. -*/ template class SparseSet { public: - /** Creates a new empty set. */ - SparseSet() throw() - { - } + SparseSet() throw() + { + } - /** Creates a copy of another SparseSet. */ - SparseSet (const SparseSet& other) throw() - : values (other.values) - { - } + SparseSet (const SparseSet& other) throw() + : values (other.values) + { + } - /** Destructor. */ - ~SparseSet() throw() - { - } + ~SparseSet() throw() + { + } - /** Clears the set. */ - void clear() throw() - { - values.clear(); - } + void clear() throw() + { + values.clear(); + } - /** Checks whether the set is empty. + bool isEmpty() const throw() + { + return values.size() == 0; + } - This is much quicker than using (size() == 0). - */ - bool isEmpty() const throw() - { - return values.size() == 0; - } + Type size() const throw() + { + Type num = 0; - /** Returns the number of values in the set. + for (int i = 0; i < values.size(); i += 2) + num += values[i + 1] - values[i]; - Because of the way the data is stored, this method can take longer if there - are a lot of items in the set. Use isEmpty() for a quick test of whether there - are any items. - */ - Type size() const throw() - { - Type num = 0; + return num; + } - for (int i = 0; i < values.size(); i += 2) - num += values[i + 1] - values[i]; + Type operator[] (int index) const throw() + { + for (int i = 0; i < values.size(); i += 2) + { + const Type s = values.getUnchecked(i); + const Type e = values.getUnchecked(i + 1); - return num; - } + if (index < e - s) + return s + index; - /** Returns one of the values in the set. + index -= e - s; + } - @param index the index of the value to retrieve, in the range 0 to (size() - 1). - @returns the value at this index, or 0 if it's out-of-range - */ - Type operator[] (int index) const throw() - { - for (int i = 0; i < values.size(); i += 2) - { - const Type s = values.getUnchecked(i); - const Type e = values.getUnchecked(i + 1); + return (Type) 0; + } - if (index < e - s) - return s + index; + bool contains (const Type valueToLookFor) const throw() + { + bool on = false; - index -= e - s; - } + for (int i = 0; i < values.size(); ++i) + { + if (values.getUnchecked(i) > valueToLookFor) + return on; - return (Type) 0; - } + on = ! on; + } - /** Checks whether a particular value is in the set. */ - bool contains (const Type valueToLookFor) const throw() - { - bool on = false; + return false; + } - for (int i = 0; i < values.size(); ++i) - { - if (values.getUnchecked(i) > valueToLookFor) - return on; + int getNumRanges() const throw() + { + return values.size() >> 1; + } - on = ! on; - } + bool getRange (const int rangeIndex, + Type& startValue, + Type& numValues) const throw() + { + if (((unsigned int) rangeIndex) < (unsigned int) getNumRanges()) + { + startValue = values [rangeIndex << 1]; + numValues = values [(rangeIndex << 1) + 1] - startValue; - return false; - } + return true; + } - /** Returns the number of contiguous blocks of values. + return false; + } - @see getRange - */ - int getNumRanges() const throw() - { - return values.size() >> 1; - } + bool getTotalRange (Type& lowestValue, + Type& highestValue) const throw() + { + if (values.size() > 0) + { + lowestValue = values.getUnchecked (0); + highestValue = values.getUnchecked (values.size() - 1); + return true; + } - /** Returns one of the contiguous ranges of values stored. + return false; + } - @param rangeIndex the index of the range to look up, between 0 - and (getNumRanges() - 1) - @param startValue on return, the value at the start of the range - @param numValues on return, the number of values in the range + void addRange (const Type firstValue, + const Type numValuesToAdd) throw() + { + jassert (numValuesToAdd >= 0); - @see getTotalRange - */ - bool getRange (const int rangeIndex, - Type& startValue, - Type& numValues) const throw() - { - if (((unsigned int) rangeIndex) < (unsigned int) getNumRanges()) - { - startValue = values [rangeIndex << 1]; - numValues = values [(rangeIndex << 1) + 1] - startValue; + if (numValuesToAdd > 0) + { + removeRange (firstValue, numValuesToAdd); - return true; - } + IntegerElementComparator sorter; + values.addSorted (sorter, firstValue); + values.addSorted (sorter, firstValue + numValuesToAdd); - return false; - } + simplify(); + } + } - /** Returns the lowest and highest values in the set. + void removeRange (const Type firstValue, + const Type numValuesToRemove) throw() + { + jassert (numValuesToRemove >= 0); - @see getRange - */ - bool getTotalRange (Type& lowestValue, - Type& highestValue) const throw() - { - if (values.size() > 0) - { - lowestValue = values.getUnchecked (0); - highestValue = values.getUnchecked (values.size() - 1); - return true; - } + if (numValuesToRemove >= 0 + && firstValue < values.getLast()) + { + const bool onAtStart = contains (firstValue - 1); + const Type lastValue = firstValue + jmin (numValuesToRemove, values.getLast() - firstValue); + const bool onAtEnd = contains (lastValue); - return false; - } + for (int i = values.size(); --i >= 0;) + { + if (values.getUnchecked(i) <= lastValue) + { + while (values.getUnchecked(i) >= firstValue) + { + values.remove (i); - /** Adds a range of contiguous values to the set. + if (--i < 0) + break; + } - e.g. addRange (10, 4) will add (10, 11, 12, 13) to the set. + break; + } + } - @param firstValue the start of the range of values to add - @param numValuesToAdd how many values to add - */ - void addRange (const Type firstValue, - const Type numValuesToAdd) throw() - { - jassert (numValuesToAdd >= 0); + IntegerElementComparator sorter; - if (numValuesToAdd > 0) - { - removeRange (firstValue, numValuesToAdd); + if (onAtStart) + values.addSorted (sorter, firstValue); - IntegerElementComparator sorter; - values.addSorted (sorter, firstValue); - values.addSorted (sorter, firstValue + numValuesToAdd); + if (onAtEnd) + values.addSorted (sorter, lastValue); - simplify(); - } - } + simplify(); + } + } - /** Removes a range of values from the set. + void invertRange (const Type firstValue, + const Type numValues) + { + SparseSet newItems; + newItems.addRange (firstValue, numValues); - e.g. removeRange (10, 4) will remove (10, 11, 12, 13) from the set. + int i; + for (i = getNumRanges(); --i >= 0;) + { + const int start = values [i << 1]; + const int end = values [(i << 1) + 1]; - @param firstValue the start of the range of values to remove - @param numValuesToRemove how many values to remove - */ - void removeRange (const Type firstValue, - const Type numValuesToRemove) throw() - { - jassert (numValuesToRemove >= 0); + newItems.removeRange (start, end); + } - if (numValuesToRemove >= 0 - && firstValue < values.getLast()) - { - const bool onAtStart = contains (firstValue - 1); - const Type lastValue = firstValue + jmin (numValuesToRemove, values.getLast() - firstValue); - const bool onAtEnd = contains (lastValue); + removeRange (firstValue, numValues); - for (int i = values.size(); --i >= 0;) - { - if (values.getUnchecked(i) <= lastValue) - { - while (values.getUnchecked(i) >= firstValue) - { - values.remove (i); + for (i = newItems.getNumRanges(); --i >= 0;) + { + const int start = newItems.values [i << 1]; + const int end = newItems.values [(i << 1) + 1]; - if (--i < 0) - break; - } + addRange (start, end); + } + } - break; - } - } + bool overlapsRange (const Type firstValue, + const Type numValues) throw() + { + jassert (numValues >= 0); - IntegerElementComparator sorter; + if (numValues > 0) + { + for (int i = getNumRanges(); --i >= 0;) + { + if (firstValue >= values.getUnchecked ((i << 1) + 1)) + return false; - if (onAtStart) - values.addSorted (sorter, firstValue); + if (firstValue + numValues > values.getUnchecked (i << 1)) + return true; + } + } - if (onAtEnd) - values.addSorted (sorter, lastValue); + return false; + } - simplify(); - } - } + bool containsRange (const Type firstValue, + const Type numValues) throw() + { + jassert (numValues >= 0); - /** Does an XOR of the values in a given range. */ - void invertRange (const Type firstValue, - const Type numValues) - { - SparseSet newItems; - newItems.addRange (firstValue, numValues); + if (numValues > 0) + { + for (int i = getNumRanges(); --i >= 0;) + { + if (firstValue >= values.getUnchecked ((i << 1) + 1)) + return false; - int i; - for (i = getNumRanges(); --i >= 0;) - { - const int start = values [i << 1]; - const int end = values [(i << 1) + 1]; + if (firstValue >= values.getUnchecked (i << 1) + && firstValue + numValues <= values.getUnchecked ((i << 1) + 1)) + return true; + } + } - newItems.removeRange (start, end); - } + return false; + } - removeRange (firstValue, numValues); + bool operator== (const SparseSet& other) throw() + { + return values == other.values; + } - for (i = newItems.getNumRanges(); --i >= 0;) - { - const int start = newItems.values [i << 1]; - const int end = newItems.values [(i << 1) + 1]; + bool operator!= (const SparseSet& other) throw() + { + return values != other.values; + } - addRange (start, end); - } - } - - /** Checks whether any part of a given range overlaps any part of this one. */ - bool overlapsRange (const Type firstValue, - const Type numValues) throw() - { - jassert (numValues >= 0); - - if (numValues > 0) - { - for (int i = getNumRanges(); --i >= 0;) - { - if (firstValue >= values.getUnchecked ((i << 1) + 1)) - return false; - - if (firstValue + numValues > values.getUnchecked (i << 1)) - return true; - } - } - - return false; - } - - /** Checks whether the whole of a given range is contained within this one. */ - bool containsRange (const Type firstValue, - const Type numValues) throw() - { - jassert (numValues >= 0); - - if (numValues > 0) - { - for (int i = getNumRanges(); --i >= 0;) - { - if (firstValue >= values.getUnchecked ((i << 1) + 1)) - return false; - - if (firstValue >= values.getUnchecked (i << 1) - && firstValue + numValues <= values.getUnchecked ((i << 1) + 1)) - return true; - } - } - - return false; - } - - bool operator== (const SparseSet& other) throw() - { - return values == other.values; - } - - bool operator!= (const SparseSet& other) throw() - { - return values != other.values; - } - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - // alternating start/end values of ranges of values that are present. - Array values; + // alternating start/end values of ranges of values that are present. + Array values; - void simplify() throw() - { - jassert ((values.size() & 1) == 0); + void simplify() throw() + { + jassert ((values.size() & 1) == 0); - for (int i = values.size(); --i > 0;) - if (values.getUnchecked(i) == values.getUnchecked (i - 1)) - values.removeRange (i - 1, 2); - } + for (int i = values.size(); --i > 0;) + if (values.getUnchecked(i) == values.getUnchecked (i - 1)) + values.removeRange (i - 1, 2); + } }; #endif // __JUCE_SPARSESET_JUCEHEADER__ @@ -11164,222 +5876,150 @@ private: class JUCE_API DynamicObject; -/** - A variant class, that can be used to hold a range of primitive values. - - A var object can hold a range of simple primitive values, strings, or - a reference-counted pointer to a DynamicObject. The var class is intended - to act like the values used in dynamic scripting languages. - - @see DynamicObject -*/ class JUCE_API var { public: - typedef const var (DynamicObject::*MethodFunction) (const var* arguments, int numArguments); + typedef const var (DynamicObject::*MethodFunction) (const var* arguments, int numArguments); - /** Creates a void variant. */ - var() throw(); + var() throw(); - /** Destructor. */ - ~var(); + ~var(); - var (const var& valueToCopy) throw(); - var (const int value) throw(); - var (const bool value) throw(); - var (const double value) throw(); - var (const char* const value) throw(); - var (const juce_wchar* const value) throw(); - var (const String& value) throw(); - var (DynamicObject* const object) throw(); - var (MethodFunction method) throw(); + var (const var& valueToCopy) throw(); + var (const int value) throw(); + var (const bool value) throw(); + var (const double value) throw(); + var (const char* const value) throw(); + var (const juce_wchar* const value) throw(); + var (const String& value) throw(); + var (DynamicObject* const object) throw(); + var (MethodFunction method) throw(); - const var& operator= (const var& valueToCopy) throw(); - const var& operator= (const int value) throw(); - const var& operator= (const bool value) throw(); - const var& operator= (const double value) throw(); - const var& operator= (const char* const value) throw(); - const var& operator= (const juce_wchar* const value) throw(); - const var& operator= (const String& value) throw(); - const var& operator= (DynamicObject* const object) throw(); - const var& operator= (MethodFunction method) throw(); + const var& operator= (const var& valueToCopy) throw(); + const var& operator= (const int value) throw(); + const var& operator= (const bool value) throw(); + const var& operator= (const double value) throw(); + const var& operator= (const char* const value) throw(); + const var& operator= (const juce_wchar* const value) throw(); + const var& operator= (const String& value) throw(); + const var& operator= (DynamicObject* const object) throw(); + const var& operator= (MethodFunction method) throw(); - operator int() const throw(); - operator bool() const throw(); - operator float() const throw(); - operator double() const throw(); - operator const String() const throw(); - const String toString() const throw(); - DynamicObject* getObject() const throw(); + operator int() const throw(); + operator bool() const throw(); + operator float() const throw(); + operator double() const throw(); + operator const String() const throw(); + const String toString() const throw(); + DynamicObject* getObject() const throw(); - bool isVoid() const throw() { return type == voidType; } - bool isInt() const throw() { return type == intType; } - bool isBool() const throw() { return type == boolType; } - bool isDouble() const throw() { return type == doubleType; } - bool isString() const throw() { return type == stringType; } - bool isObject() const throw() { return type == objectType; } - bool isMethod() const throw() { return type == methodType; } + bool isVoid() const throw() { return type == voidType; } + bool isInt() const throw() { return type == intType; } + bool isBool() const throw() { return type == boolType; } + bool isDouble() const throw() { return type == doubleType; } + bool isString() const throw() { return type == stringType; } + bool isObject() const throw() { return type == objectType; } + bool isMethod() const throw() { return type == methodType; } - bool operator== (const var& other) const throw(); - bool operator!= (const var& other) const throw(); + bool operator== (const var& other) const throw(); + bool operator!= (const var& other) const throw(); - /** Writes a binary representation of this value to a stream. - The data can be read back later using readFromStream(). - */ - void writeToStream (OutputStream& output) const throw(); + void writeToStream (OutputStream& output) const throw(); - /** Reads back a stored binary representation of a value. - The data in the stream must have been written using writeToStream(), or this - will have unpredictable results. - */ - static const var readFromStream (InputStream& input) throw(); + static const var readFromStream (InputStream& input) throw(); - class JUCE_API identifier - { - public: - identifier (const char* const name) throw(); - identifier (const String& name) throw(); - ~identifier() throw(); + class JUCE_API identifier + { + public: + identifier (const char* const name) throw(); + identifier (const String& name) throw(); + ~identifier() throw(); - bool operator== (const identifier& other) const throw() - { - jassert (hashCode != other.hashCode || name == other.name); // check for name hash collisions - return hashCode == other.hashCode; - } + bool operator== (const identifier& other) const throw() + { + jassert (hashCode != other.hashCode || name == other.name); // check for name hash collisions + return hashCode == other.hashCode; + } - String name; - int hashCode; - }; + String name; + int hashCode; + }; - /** If this variant is an object, this returns one of its properties. */ - const var operator[] (const identifier& propertyName) const throw(); + const var operator[] (const identifier& propertyName) const throw(); - /** If this variant is an object, this invokes one of its methods with no arguments. */ - const var call (const identifier& method) const; - /** If this variant is an object, this invokes one of its methods with one argument. */ - const var call (const identifier& method, const var& arg1) const; - /** If this variant is an object, this invokes one of its methods with 2 arguments. */ - const var call (const identifier& method, const var& arg1, const var& arg2) const; - /** If this variant is an object, this invokes one of its methods with 3 arguments. */ - const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3); - /** If this variant is an object, this invokes one of its methods with 4 arguments. */ - const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const; - /** If this variant is an object, this invokes one of its methods with 5 arguments. */ - const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const; + const var call (const identifier& method) const; + const var call (const identifier& method, const var& arg1) const; + const var call (const identifier& method, const var& arg1, const var& arg2) const; + const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3); + const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const; + const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const; - /** If this variant is an object, this invokes one of its methods with a list of arguments. */ - const var invoke (const identifier& method, const var* arguments, int numArguments) const; + const var invoke (const identifier& method, const var* arguments, int numArguments) const; - /** If this variant is a method pointer, this invokes it on a target object. */ - const var invoke (const var& targetObject, const var* arguments, int numArguments) const; + const var invoke (const var& targetObject, const var* arguments, int numArguments) const; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - enum Type - { - voidType = 0, - intType, - boolType, - doubleType, - stringType, - objectType, - methodType - }; + enum Type + { + voidType = 0, + intType, + boolType, + doubleType, + stringType, + objectType, + methodType + }; - Type type; + Type type; - union - { - int intValue; - bool boolValue; - double doubleValue; - String* stringValue; - DynamicObject* objectValue; - MethodFunction methodValue; - } value; + union + { + int intValue; + bool boolValue; + double doubleValue; + String* stringValue; + DynamicObject* objectValue; + MethodFunction methodValue; + } value; - void releaseValue() throw(); + void releaseValue() throw(); }; -/** - Represents a dynamically implemented object. - - An instance of this class can be used to store named properties, and - by subclassing hasMethod() and invokeMethod(), you can give your object - methods. - - This is intended for use as a wrapper for scripting language objects. -*/ class JUCE_API DynamicObject : public ReferenceCountedObject { public: - DynamicObject(); + DynamicObject(); - /** Destructor. */ - virtual ~DynamicObject(); + virtual ~DynamicObject(); - /** Returns true if the object has a property with this name. - Note that if the property is actually a method, this will return false. - */ - virtual bool hasProperty (const var::identifier& propertyName) const; + virtual bool hasProperty (const var::identifier& propertyName) const; - /** Returns a named property. + virtual const var getProperty (const var::identifier& propertyName) const; - This returns a void if no such property exists. - */ - virtual const var getProperty (const var::identifier& propertyName) const; + virtual void setProperty (const var::identifier& propertyName, const var& newValue); - /** Sets a named property. */ - virtual void setProperty (const var::identifier& propertyName, const var& newValue); + virtual void removeProperty (const var::identifier& propertyName); - /** Removes a named property. */ - virtual void removeProperty (const var::identifier& propertyName); + virtual bool hasMethod (const var::identifier& methodName) const; - /** Checks whether this object has the specified method. + virtual const var invokeMethod (const var::identifier& methodName, + const var* parameters, + int numParameters); - The default implementation of this just checks whether there's a property - with this name that's actually a method, but this can be overridden for - building objects with dynamic invocation. - */ - virtual bool hasMethod (const var::identifier& methodName) const; + void setMethod (const var::identifier& methodName, + var::MethodFunction methodFunction); - /** Invokes a named method on this object. + void clear(); - The default implementation looks up the named property, and if it's a method - call, then it invokes it. - - This method is virtual to allow more dynamic invocation to used for objects - where the methods may not already be set as properies. - */ - virtual const var invokeMethod (const var::identifier& methodName, - const var* parameters, - int numParameters); - - /** Sets up a method. - - This is basically the same as calling setProperty (methodName, (var::MethodFunction) myFunction), but - helps to avoid accidentally invoking the wrong type of var constructor. It also makes - the code easier to read, - - The compiler will probably force you to use an explicit cast your method to a (var::MethodFunction), e.g. - @code - setMethod ("doSomething", (var::MethodFunction) &MyClass::doSomething); - @endcode - */ - void setMethod (const var::identifier& methodName, - var::MethodFunction methodFunction); - - /** Removes all properties and methods from the object. */ - void clear(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - Array propertyIds; - OwnedArray propertyValues; + Array propertyIds; + OwnedArray propertyValues; }; #endif // __JUCE_VARIANT_JUCEHEADER__ @@ -11400,378 +6040,183 @@ private: class MessageListener; class MessageManager; -/** The base class for objects that can be delivered to a MessageListener. - - The simplest Message object contains a few integer and pointer parameters - that the user can set, and this is enough for a lot of purposes. For passing more - complex data, subclasses of Message can also be used. - - @see MessageListener, MessageManager, ActionListener, ChangeListener -*/ class JUCE_API Message { public: - /** Creates an uninitialised message. + Message() throw(); - The class's variables will also be left uninitialised. - */ - Message() throw(); + Message (const int intParameter1, + const int intParameter2, + const int intParameter3, + void* const pointerParameter) throw(); - /** Creates a message object, filling in the member variables. + virtual ~Message() throw(); - The corresponding public member variables will be set from the parameters - passed in. - */ - Message (const int intParameter1, - const int intParameter2, - const int intParameter3, - void* const pointerParameter) throw(); + // These values can be used for carrying simple data that the application needs to + // pass around. For more complex messages, just create a subclass. - /** Destructor. */ - virtual ~Message() throw(); + int intParameter1; /**< user-defined integer value. */ + int intParameter2; /**< user-defined integer value. */ + int intParameter3; /**< user-defined integer value. */ + void* pointerParameter; /**< user-defined pointer value. */ - // These values can be used for carrying simple data that the application needs to - // pass around. For more complex messages, just create a subclass. - - int intParameter1; /**< user-defined integer value. */ - int intParameter2; /**< user-defined integer value. */ - int intParameter3; /**< user-defined integer value. */ - void* pointerParameter; /**< user-defined pointer value. */ - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class MessageListener; - friend class MessageManager; - MessageListener* messageRecipient; + friend class MessageListener; + friend class MessageManager; + MessageListener* messageRecipient; - Message (const Message&); - const Message& operator= (const Message&); + Message (const Message&); + const Message& operator= (const Message&); }; #endif // __JUCE_MESSAGE_JUCEHEADER__ /********* End of inlined file: juce_Message.h *********/ -/** - MessageListener subclasses can post and receive Message objects. - - @see Message, MessageManager, ActionListener, ChangeListener -*/ class JUCE_API MessageListener { protected: - /** Creates a MessageListener. */ - MessageListener() throw(); + MessageListener() throw(); public: - /** Destructor. + virtual ~MessageListener(); - When a MessageListener is deleted, it removes itself from a global list - of registered listeners, so that the isValidMessageListener() method - will no longer return true. - */ - virtual ~MessageListener(); + virtual void handleMessage (const Message& message) = 0; - /** This is the callback method that receives incoming messages. + void postMessage (Message* const message) const throw(); - This is called by the MessageManager from its dispatch loop. - - @see postMessage - */ - virtual void handleMessage (const Message& message) = 0; - - /** Sends a message to the message queue, for asynchronous delivery to this listener - later on. - - This method can be called safely by any thread. - - @param message the message object to send - this will be deleted - automatically by the message queue, so don't keep any - references to it after calling this method. - @see handleMessage - */ - void postMessage (Message* const message) const throw(); - - /** Checks whether this MessageListener has been deleted. - - Although not foolproof, this method is safe to call on dangling or null - pointers. A list of active MessageListeners is kept internally, so this - checks whether the object is on this list or not. - - Note that it's possible to get a false-positive here, if an object is - deleted and another is subsequently created that happens to be at the - exact same memory location, but I can't think of a good way of avoiding - this. - */ - bool isValidMessageListener() const throw(); + bool isValidMessageListener() const throw(); }; #endif // __JUCE_MESSAGELISTENER_JUCEHEADER__ /********* End of inlined file: juce_MessageListener.h *********/ -/** - Has a callback method that is triggered asynchronously. - - This object allows an asynchronous callback function to be triggered, for - tasks such as coalescing multiple updates into a single callback later on. - - Basically, one or more calls to the triggerAsyncUpdate() will result in the - message thread calling handleAsyncUpdate() as soon as it can. -*/ class JUCE_API AsyncUpdater { public: - /** Creates an AsyncUpdater object. */ - AsyncUpdater() throw(); + AsyncUpdater() throw(); - /** Destructor. + virtual ~AsyncUpdater(); - If there are any pending callbacks when the object is deleted, these are lost. - */ - virtual ~AsyncUpdater(); + void triggerAsyncUpdate() throw(); - /** Causes the callback to be triggered at a later time. + void cancelPendingUpdate() throw(); - This method returns immediately, having made sure that a callback - to the handleAsyncUpdate() method will occur as soon as possible. + void handleUpdateNowIfNeeded(); - If an update callback is already pending but hasn't happened yet, calls - to this method will be ignored. - - It's thread-safe to call this method from any number of threads without - needing to worry about locking. - */ - void triggerAsyncUpdate() throw(); - - /** This will stop any pending updates from happening. - - If called after triggerAsyncUpdate() and before the handleAsyncUpdate() - callback happens, this will cancel the handleAsyncUpdate() callback. - */ - void cancelPendingUpdate() throw(); - - /** If an update has been triggered and is pending, this will invoke it - synchronously. - - Use this as a kind of "flush" operation - if an update is pending, the - handleAsyncUpdate() method will be called immediately; if no update is - pending, then nothing will be done. - */ - void handleUpdateNowIfNeeded(); - - /** Called back to do whatever your class needs to do. - - This method is called by the message thread at the next convenient time - after the triggerAsyncUpdate() method has been called. - */ - virtual void handleAsyncUpdate() = 0; + virtual void handleAsyncUpdate() = 0; private: - class AsyncUpdaterInternal : public MessageListener - { - public: - AsyncUpdaterInternal() throw() {} - ~AsyncUpdaterInternal() {} + class AsyncUpdaterInternal : public MessageListener + { + public: + AsyncUpdaterInternal() throw() {} + ~AsyncUpdaterInternal() {} - void handleMessage (const Message&); + void handleMessage (const Message&); - AsyncUpdater* owner; + AsyncUpdater* owner; - private: - AsyncUpdaterInternal (const AsyncUpdaterInternal&); - const AsyncUpdaterInternal& operator= (const AsyncUpdaterInternal&); - }; + private: + AsyncUpdaterInternal (const AsyncUpdaterInternal&); + const AsyncUpdaterInternal& operator= (const AsyncUpdaterInternal&); + }; - AsyncUpdaterInternal internalAsyncHandler; - bool asyncMessagePending; + AsyncUpdaterInternal internalAsyncHandler; + bool asyncMessagePending; }; #endif // __JUCE_ASYNCUPDATER_JUCEHEADER__ /********* End of inlined file: juce_AsyncUpdater.h *********/ -/** - Represents a shared variant value. - - A Value object contains a reference to a var object, and can get and set its value. - Listeners can be attached to be told when the value is changed. - - The Value class is a wrapper around a shared, reference-counted underlying data - object - this means that multiple Value objects can all refer to the same piece of - data, allowing all of them to be notified when any of them changes it. - - The base class of Value contains a simple var object, but subclasses can be - created that map a Value onto any kind of underlying data, e.g. - ValueTree::getPropertyAsValue() returns a Value object that is a wrapper - for one of its properties. -*/ class JUCE_API Value { public: - /** Creates an empty Value, containing a void var. */ - Value(); + Value(); - /** Creates a Value that refers to the same value as another one. + Value (const Value& other); - Note that this doesn't make a copy of the other value - both this and the other - Value will share the same underlying value, so that when either one alters it, both - will see it change. - */ - Value (const Value& other); + Value (const var& initialValue); - /** Creates a Value that is set to the specified value. */ - Value (const var& initialValue); + ~Value(); - /** Destructor. */ - ~Value(); + const var getValue() const; - /** Returns the current value. */ - const var getValue() const; + operator const var() const; - /** Returns the current value. */ - operator const var() const; + const String toString() const; - /** Sets the current value. + void setValue (const var& newValue); - You can also use operator= to set the value. + const Value& operator= (const var& newValue); - If there are any listeners registered, they will be notified of the - change asynchronously. - */ - void setValue (const var& newValue); + void referTo (const Value& valueToReferTo); - /** Sets the current value. + bool refersToSameSourceAs (const Value& other) const; - This is the same as calling setValue(). + bool operator== (const Value& other) const; - If there are any listeners registered, they will be notified of the - change asynchronously. - */ - const Value& operator= (const var& newValue); + bool operator!= (const Value& other) const; - /** Makes this object refer to the same underlying ValueSource as another one. + class JUCE_API Listener + { + public: + Listener() {} + virtual ~Listener() {} - Once this object has been connected to another one, changing either one - will update the other. + virtual void valueChanged (Value& value) = 0; + }; - Existing listeners will still be registered after you call this method, and - they'll continue to receive messages when the new value changes. - */ - void referTo (const Value& valueToReferTo); + void addListener (Listener* const listener); - /** Returns true if this value and the other one are references to the same value. - */ - bool refersToSameSourceAs (const Value& other) const; + void removeListener (Listener* const listener); - /** Compares two values. - This is a compare-by-value comparison, so is effectively the same as - saying (this->getValue() == other.getValue()). - */ - bool operator== (const Value& other) const; + class JUCE_API ValueSource : public ReferenceCountedObject, + public AsyncUpdater + { + public: + ValueSource(); + virtual ~ValueSource(); - /** Compares two values. - This is a compare-by-value comparison, so is effectively the same as - saying (this->getValue() != other.getValue()). - */ - bool operator!= (const Value& other) const; + virtual const var getValue() const = 0; + virtual void setValue (const var& newValue) = 0; - /** Receives callbacks when a Value object changes. - @see Value::addListener - */ - class JUCE_API Listener - { - public: - Listener() {} - virtual ~Listener() {} + void sendChangeMessage (const bool dispatchSynchronously); - /** Called when a Value object is changed. + juce_UseDebuggingNewOperator - Note that the Value object passed as a parameter may not be exactly the same - object that you registered the listener with - it might be a copy that refers - to the same underlying ValueSource. To find out, you can call Value::refersToSameSourceAs(). - */ - virtual void valueChanged (Value& value) = 0; - }; + protected: + friend class Value; + SortedSet valuesWithListeners; - /** Adds a listener to receive callbacks when the value changes. + void handleAsyncUpdate(); - The listener is added to this specific Value object, and not to the shared - object that it refers to. When this object is deleted, all the listeners will - be lost, even if other references to the same Value still exist. So when you're - adding a listener, make sure that you add it to a ValueTree instance that will last - for as long as you need the listener. In general, you'd never want to add a listener - to a local stack-based ValueTree, but more likely to one that's a member variable. + ValueSource (const ValueSource&); + const ValueSource& operator= (const ValueSource&); + }; - @see removeListener - */ - void addListener (Listener* const listener); + explicit Value (ValueSource* const valueSource); + ValueSource& getValueSource() { return *value; } - /** Removes a listener that was previously added with addListener(). */ - void removeListener (Listener* const listener); - - /** - Used internally by the Value class as the base class for its shared value objects. - - The Value class is essentially a reference-counted pointer to a shared instance - of a ValueSource object. If you're feeling adventurous, you can create your own custom - ValueSource classes to allow Value objects to represent your own custom data items. - */ - class JUCE_API ValueSource : public ReferenceCountedObject, - public AsyncUpdater - { - public: - ValueSource(); - virtual ~ValueSource(); - - /** Returns the current value of this object. */ - virtual const var getValue() const = 0; - /** Changes the current value. - This must also trigger a change message if the value actually changes. - */ - virtual void setValue (const var& newValue) = 0; - - /** Delivers a change message to all the listeners that are registered with - this value. - - If dispatchSynchronously is true, the method will call all the listeners - before returning; otherwise it'll dispatch a message and make the call later. - */ - void sendChangeMessage (const bool dispatchSynchronously); - - juce_UseDebuggingNewOperator - - protected: - friend class Value; - SortedSet valuesWithListeners; - - void handleAsyncUpdate(); - - ValueSource (const ValueSource&); - const ValueSource& operator= (const ValueSource&); - }; - - /** @internal */ - explicit Value (ValueSource* const valueSource); - /** @internal */ - ValueSource& getValueSource() { return *value; } - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class ValueSource; - ReferenceCountedObjectPtr value; - SortedSet listeners; + friend class ValueSource; + ReferenceCountedObjectPtr value; + SortedSet listeners; - void callListeners(); + void callListeners(); - // This is disallowed to avoid confusion about whether it should - // do a by-value or by-reference copy. - const Value& operator= (const Value& other); + // This is disallowed to avoid confusion about whether it should + // do a by-value or by-reference copy. + const Value& operator= (const Value& other); }; #endif // __JUCE_VALUE_JUCEHEADER__ @@ -11800,31 +6245,12 @@ private: #ifndef __JUCE_CHANGELISTENER_JUCEHEADER__ #define __JUCE_CHANGELISTENER_JUCEHEADER__ -/** - Receives callbacks about changes to some kind of object. - - Many objects use a ChangeListenerList to keep a set of listeners which they - will inform when something changes. A subclass of ChangeListener - is used to receive these callbacks. - - Note that the major difference between an ActionListener and a ChangeListener - is that for a ChangeListener, multiple changes will be coalesced into fewer - callbacks, but ActionListeners perform one callback for every event posted. - - @see ChangeListenerList, ChangeBroadcaster, ActionListener -*/ class JUCE_API ChangeListener { public: - /** Destructor. */ - virtual ~ChangeListener() {} + virtual ~ChangeListener() {} - /** Overridden by your subclass to receive the callback. - - @param objectThatHasChanged the value that was passed to the - ChangeListenerList::sendChangeMessage() method - */ - virtual void changeListenerCallback (void* objectThatHasChanged) = 0; + virtual void changeListenerCallback (void* objectThatHasChanged) = 0; }; #endif // __JUCE_CHANGELISTENER_JUCEHEADER__ @@ -11834,275 +6260,104 @@ public: #ifndef __JUCE_SCOPEDLOCK_JUCEHEADER__ #define __JUCE_SCOPEDLOCK_JUCEHEADER__ -/** - Automatically locks and unlocks a CriticalSection object. - - Use one of these as a local variable to control access to a CriticalSection. - - e.g. @code - - CriticalSection myCriticalSection; - - for (;;) - { - const ScopedLock myScopedLock (myCriticalSection); - // myCriticalSection is now locked - - ...do some stuff... - - // myCriticalSection gets unlocked here. - } - @endcode - - @see CriticalSection, ScopedUnlock -*/ class JUCE_API ScopedLock { public: - /** Creates a ScopedLock. + inline ScopedLock (const CriticalSection& lock) throw() : lock_ (lock) { lock.enter(); } - As soon as it is created, this will lock the CriticalSection, and - when the ScopedLock object is deleted, the CriticalSection will - be unlocked. - - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! Best just to use it - as a local stack object, rather than creating one with the new() operator. - */ - inline ScopedLock (const CriticalSection& lock) throw() : lock_ (lock) { lock.enter(); } - - /** Destructor. - - The CriticalSection will be unlocked when the destructor is called. - - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! - */ - inline ~ScopedLock() throw() { lock_.exit(); } + inline ~ScopedLock() throw() { lock_.exit(); } private: - const CriticalSection& lock_; + const CriticalSection& lock_; - ScopedLock (const ScopedLock&); - const ScopedLock& operator= (const ScopedLock&); + ScopedLock (const ScopedLock&); + const ScopedLock& operator= (const ScopedLock&); }; -/** - Automatically unlocks and re-locks a CriticalSection object. - - This is the reverse of a ScopedLock object - instead of locking the critical - section for the lifetime of this object, it unlocks it. - - Make sure you don't try to unlock critical sections that aren't actually locked! - - e.g. @code - - CriticalSection myCriticalSection; - - for (;;) - { - const ScopedLock myScopedLock (myCriticalSection); - // myCriticalSection is now locked - - ... do some stuff with it locked .. - - while (xyz) - { - ... do some stuff with it locked .. - - const ScopedUnlock unlocker (myCriticalSection); - - // myCriticalSection is now unlocked for the remainder of this block, - // and re-locked at the end. - - ...do some stuff with it unlocked ... - } - - // myCriticalSection gets unlocked here. - } - @endcode - - @see CriticalSection, ScopedLock -*/ class ScopedUnlock { public: - /** Creates a ScopedUnlock. + inline ScopedUnlock (const CriticalSection& lock) throw() : lock_ (lock) { lock.exit(); } - As soon as it is created, this will unlock the CriticalSection, and - when the ScopedLock object is deleted, the CriticalSection will - be re-locked. - - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! Best just to use it - as a local stack object, rather than creating one with the new() operator. - */ - inline ScopedUnlock (const CriticalSection& lock) throw() : lock_ (lock) { lock.exit(); } - - /** Destructor. - - The CriticalSection will be unlocked when the destructor is called. - - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! - */ - inline ~ScopedUnlock() throw() { lock_.enter(); } + inline ~ScopedUnlock() throw() { lock_.enter(); } private: - const CriticalSection& lock_; + const CriticalSection& lock_; - ScopedUnlock (const ScopedLock&); - const ScopedUnlock& operator= (const ScopedUnlock&); + ScopedUnlock (const ScopedLock&); + const ScopedUnlock& operator= (const ScopedUnlock&); }; #endif // __JUCE_SCOPEDLOCK_JUCEHEADER__ /********* End of inlined file: juce_ScopedLock.h *********/ -/** - A set of ChangeListeners. - - Listeners can be added and removed from the list, and change messages can be - broadcast to all the listeners. - - @see ChangeListener, ChangeBroadcaster -*/ class JUCE_API ChangeListenerList : public MessageListener { public: - /** Creates an empty list. */ - ChangeListenerList() throw(); + ChangeListenerList() throw(); - /** Destructor. */ - ~ChangeListenerList() throw(); + ~ChangeListenerList() throw(); - /** Adds a listener to the list. + void addChangeListener (ChangeListener* const listener) throw(); - (Trying to add a listener that's already on the list will have no effect). - */ - void addChangeListener (ChangeListener* const listener) throw(); + void removeChangeListener (ChangeListener* const listener) throw(); - /** Removes a listener from the list. + void removeAllChangeListeners() throw(); - If the listener isn't on the list, this won't have any effect. - */ - void removeChangeListener (ChangeListener* const listener) throw(); + void sendChangeMessage (void* objectThatHasChanged) throw(); - /** Removes all listeners from the list. */ - void removeAllChangeListeners() throw(); + void sendSynchronousChangeMessage (void* objectThatHasChanged); - /** Posts an asynchronous change message to all the listeners. + void dispatchPendingMessages(); - If a message has already been sent and hasn't yet been delivered, this - method won't send another - in this way it coalesces multiple frequent - changes into fewer actual callbacks to the ChangeListeners. Contrast this - with the ActionListener, which posts a new event for every call to its - sendActionMessage() method. + void handleMessage (const Message&); - Only listeners which are on the list when the change event is delivered - will receive the event - and this may include listeners that weren't on - the list when the change message was sent. - - @param objectThatHasChanged this pointer is passed to the - ChangeListener::changeListenerCallback() method, - and can be any value the application needs - @see sendSynchronousChangeMessage - */ - void sendChangeMessage (void* objectThatHasChanged) throw(); - - /** This will synchronously callback all the ChangeListeners. - - Use this if you need to synchronously force a call to all the - listeners' ChangeListener::changeListenerCallback() methods. - */ - void sendSynchronousChangeMessage (void* objectThatHasChanged); - - /** If a change message has been sent but not yet dispatched, this will - use sendSynchronousChangeMessage() to make the callback immediately. - */ - void dispatchPendingMessages(); - - /** @internal */ - void handleMessage (const Message&); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - SortedSet listeners; - CriticalSection lock; - void* lastChangedObject; - bool messagePending; + SortedSet listeners; + CriticalSection lock; + void* lastChangedObject; + bool messagePending; - ChangeListenerList (const ChangeListenerList&); - const ChangeListenerList& operator= (const ChangeListenerList&); + ChangeListenerList (const ChangeListenerList&); + const ChangeListenerList& operator= (const ChangeListenerList&); }; #endif // __JUCE_CHANGELISTENERLIST_JUCEHEADER__ /********* End of inlined file: juce_ChangeListenerList.h *********/ -/** Manages a list of ChangeListeners, and can send them messages. - - To quickly add methods to your class that can add/remove change - listeners and broadcast to them, you can derive from this. - - @see ChangeListenerList, ChangeListener -*/ class JUCE_API ChangeBroadcaster { public: - /** Creates an ChangeBroadcaster. */ - ChangeBroadcaster() throw(); + ChangeBroadcaster() throw(); - /** Destructor. */ - virtual ~ChangeBroadcaster(); + virtual ~ChangeBroadcaster(); - /** Adds a listener to the list. + void addChangeListener (ChangeListener* const listener) throw(); - (Trying to add a listener that's already on the list will have no effect). - */ - void addChangeListener (ChangeListener* const listener) throw(); + void removeChangeListener (ChangeListener* const listener) throw(); - /** Removes a listener from the list. + void removeAllChangeListeners() throw(); - If the listener isn't on the list, this won't have any effect. - */ - void removeChangeListener (ChangeListener* const listener) throw(); + void sendChangeMessage (void* objectThatHasChanged) throw(); - /** Removes all listeners from the list. */ - void removeAllChangeListeners() throw(); + void sendSynchronousChangeMessage (void* objectThatHasChanged); - /** Broadcasts a change message to all the registered listeners. - - The message will be delivered asynchronously by the event thread, so this - method will not directly call any of the listeners. For a synchronous - message, use sendSynchronousChangeMessage(). - - @see ChangeListenerList::sendActionMessage - */ - void sendChangeMessage (void* objectThatHasChanged) throw(); - - /** Sends a synchronous change message to all the registered listeners. - - @see ChangeListenerList::sendSynchronousChangeMessage - */ - void sendSynchronousChangeMessage (void* objectThatHasChanged); - - /** If a change message has been sent but not yet dispatched, this will - use sendSynchronousChangeMessage() to make the callback immediately. - */ - void dispatchPendingMessages(); + void dispatchPendingMessages(); private: - ChangeListenerList changeListenerList; + ChangeListenerList changeListenerList; - ChangeBroadcaster (const ChangeBroadcaster&); - const ChangeBroadcaster& operator= (const ChangeBroadcaster&); + ChangeBroadcaster (const ChangeBroadcaster&); + const ChangeBroadcaster& operator= (const ChangeBroadcaster&); }; #endif // __JUCE_CHANGEBROADCASTER_JUCEHEADER__ @@ -12112,590 +6367,228 @@ private: #ifndef __JUCE_UNDOABLEACTION_JUCEHEADER__ #define __JUCE_UNDOABLEACTION_JUCEHEADER__ -/** - Used by the UndoManager class to store an action which can be done - and undone. - - @see UndoManager -*/ class JUCE_API UndoableAction { protected: - /** Creates an action. */ - UndoableAction() throw() {} + UndoableAction() throw() {} public: - /** Destructor. */ - virtual ~UndoableAction() {} + virtual ~UndoableAction() {} - /** Overridden by a subclass to perform the action. + virtual bool perform() = 0; - This method is called by the UndoManager, and shouldn't be used directly by - applications. + virtual bool undo() = 0; - Be careful not to make any calls in a perform() method that could call - recursively back into the UndoManager::perform() method - - @returns true if the action could be performed. - @see UndoManager::perform - */ - virtual bool perform() = 0; - - /** Overridden by a subclass to undo the action. - - This method is called by the UndoManager, and shouldn't be used directly by - applications. - - Be careful not to make any calls in an undo() method that could call - recursively back into the UndoManager::perform() method - - @returns true if the action could be undone without any errors. - @see UndoManager::perform - */ - virtual bool undo() = 0; - - /** Returns a value to indicate how much memory this object takes up. - - Because the UndoManager keeps a list of UndoableActions, this is used - to work out how much space each one will take up, so that the UndoManager - can work out how many to keep. - - The default value returned here is 10 - units are arbitrary and - don't have to be accurate. - - @see UndoManager::getNumberOfUnitsTakenUpByStoredCommands, - UndoManager::setMaxNumberOfStoredUnits - */ - virtual int getSizeInUnits() { return 10; } + virtual int getSizeInUnits() { return 10; } }; #endif // __JUCE_UNDOABLEACTION_JUCEHEADER__ /********* End of inlined file: juce_UndoableAction.h *********/ -/** - Manages a list of undo/redo commands. - - An UndoManager object keeps a list of past actions and can use these actions - to move backwards and forwards through an undo history. - - To use it, create subclasses of UndoableAction which perform all the - actions you need, then when you need to actually perform an action, create one - and pass it to the UndoManager's perform() method. - - The manager also uses the concept of 'transactions' to group the actions - together - all actions performed between calls to beginNewTransaction() are - grouped together and are all undone/redone as a group. - - The UndoManager is a ChangeBroadcaster, so listeners can register to be told - when actions are performed or undone. - - @see UndoableAction -*/ class JUCE_API UndoManager : public ChangeBroadcaster { public: - /** Creates an UndoManager. + UndoManager (const int maxNumberOfUnitsToKeep = 30000, + const int minimumTransactionsToKeep = 30); - @param maxNumberOfUnitsToKeep each UndoableAction object returns a value - to indicate how much storage it takes up - (UndoableAction::getSizeInUnits()), so this - lets you specify the maximum total number of - units that the undomanager is allowed to - keep in memory before letting the older actions - drop off the end of the list. - @param minimumTransactionsToKeep this specifies the minimum number of transactions - that will be kept, even if this involves exceeding - the amount of space specified in maxNumberOfUnitsToKeep - */ - UndoManager (const int maxNumberOfUnitsToKeep = 30000, - const int minimumTransactionsToKeep = 30); + ~UndoManager(); - /** Destructor. */ - ~UndoManager(); + void clearUndoHistory(); - /** Deletes all stored actions in the list. */ - void clearUndoHistory(); + int getNumberOfUnitsTakenUpByStoredCommands() const; - /** Returns the current amount of space to use for storing UndoableAction objects. + void setMaxNumberOfStoredUnits (const int maxNumberOfUnitsToKeep, + const int minimumTransactionsToKeep); - @see setMaxNumberOfStoredUnits - */ - int getNumberOfUnitsTakenUpByStoredCommands() const; + bool perform (UndoableAction* const action, + const String& actionName = String::empty); - /** Sets the amount of space that can be used for storing UndoableAction objects. + void beginNewTransaction (const String& actionName = String::empty); - @param maxNumberOfUnitsToKeep each UndoableAction object returns a value - to indicate how much storage it takes up - (UndoableAction::getSizeInUnits()), so this - lets you specify the maximum total number of - units that the undomanager is allowed to - keep in memory before letting the older actions - drop off the end of the list. - @param minimumTransactionsToKeep this specifies the minimum number of transactions - that will be kept, even if this involves exceeding - the amount of space specified in maxNumberOfUnitsToKeep - @see getNumberOfUnitsTakenUpByStoredCommands - */ - void setMaxNumberOfStoredUnits (const int maxNumberOfUnitsToKeep, - const int minimumTransactionsToKeep); + void setCurrentTransactionName (const String& newName); - /** Performs an action and adds it to the undo history list. + bool canUndo() const; - @param action the action to perform - this will be deleted by the UndoManager - when no longer needed - @param actionName if this string is non-empty, the current transaction will be - given this name; if it's empty, the current transaction name will - be left unchanged. See setCurrentTransactionName() - @returns true if the command succeeds - see UndoableAction::perform - @see beginNewTransaction - */ - bool perform (UndoableAction* const action, - const String& actionName = String::empty); + const String getUndoDescription() const; - /** Starts a new group of actions that together will be treated as a single transaction. + bool undo(); - All actions that are passed to the perform() method between calls to this - method are grouped together and undone/redone together by a single call to - undo() or redo(). + bool undoCurrentTransactionOnly(); - @param actionName a description of the transaction that is about to be - performed - */ - void beginNewTransaction (const String& actionName = String::empty); + void getActionsInCurrentTransaction (Array & actionsFound) const; - /** Changes the name stored for the current transaction. + bool canRedo() const; - Each transaction is given a name when the beginNewTransaction() method is - called, but this can be used to change that name without starting a new - transaction. - */ - void setCurrentTransactionName (const String& newName); + const String getRedoDescription() const; - /** Returns true if there's at least one action in the list to undo. + bool redo(); - @see getUndoDescription, undo, canRedo - */ - bool canUndo() const; - - /** Returns the description of the transaction that would be next to get undone. - - The description returned is the one that was passed into beginNewTransaction - before the set of actions was performed. - - @see undo - */ - const String getUndoDescription() const; - - /** Tries to roll-back the last transaction. - - @returns true if the transaction can be undone, and false if it fails, or - if there aren't any transactions to undo - */ - bool undo(); - - /** Tries to roll-back any actions that were added to the current transaction. - - This will perform an undo() only if there are some actions in the undo list - that were added after the last call to beginNewTransaction(). - - This is useful because it lets you call beginNewTransaction(), then - perform an operation which may or may not actually perform some actions, and - then call this method to get rid of any actions that might have been done - without it rolling back the previous transaction if nothing was actually - done. - - @returns true if any actions were undone. - */ - bool undoCurrentTransactionOnly(); - - /** Returns a list of the UndoableAction objects that have been performed during the - transaction that is currently open. - - Effectively, this is the list of actions that would be undone if undoCurrentTransactionOnly() - were to be called now. - - The first item in the list is the earliest action performed. - */ - void getActionsInCurrentTransaction (Array & actionsFound) const; - - /** Returns true if there's at least one action in the list to redo. - - @see getRedoDescription, redo, canUndo - */ - bool canRedo() const; - - /** Returns the description of the transaction that would be next to get redone. - - The description returned is the one that was passed into beginNewTransaction - before the set of actions was performed. - - @see redo - */ - const String getRedoDescription() const; - - /** Tries to redo the last transaction that was undone. - - @returns true if the transaction can be redone, and false if it fails, or - if there aren't any transactions to redo - */ - bool redo(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OwnedArray > transactions; - StringArray transactionNames; - String currentTransactionName; - int totalUnitsStored, maxNumUnitsToKeep, minimumTransactionsToKeep, nextIndex; - bool newTransaction, reentrancyCheck; + OwnedArray > transactions; + StringArray transactionNames; + String currentTransactionName; + int totalUnitsStored, maxNumUnitsToKeep, minimumTransactionsToKeep, nextIndex; + bool newTransaction, reentrancyCheck; - // disallow copy constructor - UndoManager (const UndoManager&); - const UndoManager& operator= (const UndoManager&); + // disallow copy constructor + UndoManager (const UndoManager&); + const UndoManager& operator= (const UndoManager&); }; #endif // __JUCE_UNDOMANAGER_JUCEHEADER__ /********* End of inlined file: juce_UndoManager.h *********/ -/** - A powerful tree structure that can be used to hold free-form data, and which can - handle its own undo and redo behaviour. - - A ValueTree contains a list of named properties as var objects, and also holds - any number of sub-trees. - - Create ValueTree objects on the stack, and don't be afraid to copy them around, as - they're simply a lightweight reference to a shared data container. Creating a copy - of another ValueTree simply creates a new reference to the same underlying object - to - make a separate, deep copy of a tree you should explicitly call createCopy(). - - Each ValueTree has a type name, in much the same way as an XmlElement has a tag name, - and much of the structure of a ValueTree is similar to an XmlElement tree. - You can convert a ValueTree to and from an XmlElement, and as long as the XML doesn't - contain text elements, the conversion works well and makes a good serialisation - format. They can also be serialised to a binary format, which is very fast and compact. - - All the methods that change data take an optional UndoManager, which will be used - to track any changes to the object. For this to work, you have to be careful to - consistently always use the same UndoManager for all operations to any node inside - the tree. - - A ValueTree can only be a child of one parent at a time, so if you're moving one from - one tree to another, be careful to always remove it first, before adding it. This - could also mess up your undo/redo chain, so be wary! In a debug build you should hit - assertions if you try to do anything dangerous, but there are still plenty of ways it - could go wrong. - - Listeners can be added to a ValueTree to be told when properies change and when - nodes are added or removed. - - @see var, XmlElement -*/ class JUCE_API ValueTree { public: - /** Creates an empty ValueTree with the given type name. - Like an XmlElement, each ValueTree node has a type, which you can access with - getType() and hasType(). - */ - ValueTree (const String& type); + ValueTree (const String& type); - /** Creates a reference to another ValueTree. */ - ValueTree (const ValueTree& other); + ValueTree (const ValueTree& other); - /** Makes this object reference another node. */ - const ValueTree& operator= (const ValueTree& other); + const ValueTree& operator= (const ValueTree& other); - /** Destructor. */ - ~ValueTree(); + ~ValueTree(); - /** Returns true if both this and the other tree node refer to the same underlying structure. - Note that this isn't a value comparison - two independently-created trees which - contain identical data are not considered equal. - */ - bool operator== (const ValueTree& other) const; + bool operator== (const ValueTree& other) const; - /** Returns true if this and the other node refer to different underlying structures. - Note that this isn't a value comparison - two independently-created trees which - contain identical data are not considered equal. - */ - bool operator!= (const ValueTree& other) const; + bool operator!= (const ValueTree& other) const; - /** Returns true if this node refers to some valid data. - It's hard to create an invalid node, but you might get one returned, e.g. by an out-of-range - call to getChild(). - */ - bool isValid() const { return object != 0; } + bool isValid() const { return object != 0; } - /** Returns a deep copy of this tree and all its sub-nodes. */ - ValueTree createCopy() const; + ValueTree createCopy() const; - /** Returns the type of this node. - The type is specified when the ValueTree is created. - @see hasType - */ - const String getType() const; + const String getType() const; - /** Returns true if the node has this type. - The comparison is case-sensitive. - */ - bool hasType (const String& typeName) const; + bool hasType (const String& typeName) const; - /** Returns the value of a named property. - If no such property has been set, this will return a void variant. - You can also use operator[] to get a property. - @see var, setProperty, hasProperty - */ - const var getProperty (const var::identifier& name) const; + const var getProperty (const var::identifier& name) const; - /** Returns the value of a named property. - If no such property has been set, this will return a void variant. This is the same as - calling getProperty(). - @see getProperty - */ - const var operator[] (const var::identifier& name) const; + const var operator[] (const var::identifier& name) const; - /** Changes a named property of the node. - If the undoManager parameter is non-null, its UndoManager::perform() method will be used, - so that this change can be undone. - @see var, getProperty, removeProperty - */ - void setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager); + void setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager); - /** Returns true if the node contains a named property. */ - bool hasProperty (const var::identifier& name) const; + bool hasProperty (const var::identifier& name) const; - /** Removes a property from the node. - If the undoManager parameter is non-null, its UndoManager::perform() method will be used, - so that this change can be undone. - */ - void removeProperty (const var::identifier& name, UndoManager* const undoManager); + void removeProperty (const var::identifier& name, UndoManager* const undoManager); - /** Removes all properties from the node. - If the undoManager parameter is non-null, its UndoManager::perform() method will be used, - so that this change can be undone. - */ - void removeAllProperties (UndoManager* const undoManager); + void removeAllProperties (UndoManager* const undoManager); - /** Returns the total number of properties that the node contains. - @see getProperty. - */ - int getNumProperties() const; + int getNumProperties() const; - /** Returns the identifier of the property with a given index. - @see getNumProperties - */ - const var::identifier getPropertyName (int index) const; + const var::identifier getPropertyName (int index) const; - /** Returns a Value object that can be used to control and respond to one of the tree's properties. + Value getPropertyAsValue (const var::identifier& name, UndoManager* const undoManager) const; - The Value object will maintain a reference to this tree, and will use the undo manager when - it needs to change the value. Attaching a Value::Listener to the value object will provide - callbacks whenever the property changes. - */ - Value getPropertyAsValue (const var::identifier& name, UndoManager* const undoManager) const; + int getNumChildren() const; - /** Returns the number of child nodes belonging to this one. - @see getChild - */ - int getNumChildren() const; + ValueTree getChild (int index) const; - /** Returns one of this node's child nodes. - If the index is out of range, it'll return an invalid node. (See isValid() to find out - whether a node is valid). - */ - ValueTree getChild (int index) const; + ValueTree getChildWithName (const String& type) const; - /** Looks for a child node with the speficied type name. - If no such node is found, it'll return an invalid node. (See isValid() to find out - whether a node is valid). - */ - ValueTree getChildWithName (const String& type) const; + ValueTree getChildWithProperty (const var::identifier& propertyName, const var& propertyValue) const; - /** Looks for the first child node that has the speficied property value. + void addChild (ValueTree child, int index, UndoManager* const undoManager); - This will scan the child nodes in order, until it finds one that has property that matches - the specified value. + void removeChild (ValueTree& child, UndoManager* const undoManager); - If no such node is found, it'll return an invalid node. (See isValid() to find out - whether a node is valid). - */ - ValueTree getChildWithProperty (const var::identifier& propertyName, const var& propertyValue) const; + void removeChild (const int childIndex, UndoManager* const undoManager); - /** Adds a child to this node. + void removeAllChildren (UndoManager* const undoManager); - Make sure that the child is removed from any former parent node before calling this, or - you'll hit an assertion. + bool isAChildOf (const ValueTree& possibleParent) const; - If the index is < 0 or greater than the current number of child nodes, the new node will - be added at the end of the list. + ValueTree getParent() const; - If the undoManager parameter is non-null, its UndoManager::perform() method will be used, - so that this change can be undone. - */ - void addChild (ValueTree child, int index, UndoManager* const undoManager); + XmlElement* createXml() const; - /** Removes the specified child from this node's child-list. - If the undoManager parameter is non-null, its UndoManager::perform() method will be used, - so that this change can be undone. - */ - void removeChild (ValueTree& child, UndoManager* const undoManager); + static ValueTree fromXml (const XmlElement& xml); - /** Removes a child from this node's child-list. - If the undoManager parameter is non-null, its UndoManager::perform() method will be used, - so that this change can be undone. - */ - void removeChild (const int childIndex, UndoManager* const undoManager); + void writeToStream (OutputStream& output); - /** Removes all child-nodes from this node. - If the undoManager parameter is non-null, its UndoManager::perform() method will be used, - so that this change can be undone. - */ - void removeAllChildren (UndoManager* const undoManager); + static ValueTree readFromStream (InputStream& input); - /** Returns true if this node is anywhere below the specified parent node. - This returns true if the node is a child-of-a-child, as well as a direct child. - */ - bool isAChildOf (const ValueTree& possibleParent) const; + class JUCE_API Listener + { + public: + virtual ~Listener() {} - /** Returns the parent node that contains this one. - If the node has no parent, this will return an invalid node. (See isValid() to find out - whether a node is valid). - */ - ValueTree getParent() const; + virtual void valueTreePropertyChanged (ValueTree& tree, const var::identifier& property) = 0; - /** Creates an XmlElement that holds a complete image of this node and all its children. + virtual void valueTreeChildrenChanged (ValueTree& tree) = 0; - If this node is invalid, this may return 0. Otherwise, the XML that is produced can - be used to recreate a similar node by calling fromXml() - @see fromXml - */ - XmlElement* createXml() const; + virtual void valueTreeParentChanged (ValueTree& tree) = 0; + }; - /** Tries to recreate a node from its XML representation. + void addListener (Listener* listener); - This isn't designed to cope with random XML data - for a sensible result, it should only - be fed XML that was created by the createXml() method. - */ - static ValueTree fromXml (const XmlElement& xml); + void removeListener (Listener* listener); - /** Stores this tree (and all its children) in a binary format. - - Once written, the data can be read back with readFromStream(). - - It's much faster to load/save your tree in binary form than as XML, but - obviously isn't human-readable. - */ - void writeToStream (OutputStream& output); - - /** Reloads a tree from a stream that was written with writeToStream(). - */ - static ValueTree readFromStream (InputStream& input); - - /** Listener class for events that happen to a ValueTree. - - To get events from a ValueTree, make your class implement this interface, and use - ValueTree::addListener() and ValueTree::removeListener() to register it. - */ - class JUCE_API Listener - { - public: - /** Destructor. */ - virtual ~Listener() {} - - /** This method is called when one of the properties of this node has been changed. */ - virtual void valueTreePropertyChanged (ValueTree& tree, const var::identifier& property) = 0; - - /** This method is called when one or more of the children of this node have been added or removed. */ - virtual void valueTreeChildrenChanged (ValueTree& tree) = 0; - - /** This method is called when this node has been added or removed from a parent node. */ - virtual void valueTreeParentChanged (ValueTree& tree) = 0; - }; - - /** Adds a listener to receive callbacks when this node is changed. - - The listener is added to this specific ValueTree object, and not to the shared - object that it refers to. When this object is deleted, all the listeners will - be lost, even if other references to the same ValueTree still exist. And if you - use the operator= to make this refer to a different ValueTree, any listeners will - begin listening to changes to the new tree instead of the old one. - - When you're adding a listener, make sure that you add it to a ValueTree instance that - will last for as long as you need the listener. In general, you'd never want to add a - listener to a local stack-based ValueTree, and would usually add one to a member variable. - - @see removeListener - */ - void addListener (Listener* listener); - - /** Removes a listener that was previously added with addListener(). */ - void removeListener (Listener* listener); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class ValueTreeSetPropertyAction; - friend class ValueTreeChildChangeAction; + friend class ValueTreeSetPropertyAction; + friend class ValueTreeChildChangeAction; - class JUCE_API SharedObject : public ReferenceCountedObject - { - public: - SharedObject (const String& type); - SharedObject (const SharedObject& other); - ~SharedObject(); + class JUCE_API SharedObject : public ReferenceCountedObject + { + public: + SharedObject (const String& type); + SharedObject (const SharedObject& other); + ~SharedObject(); - struct Property - { - Property (const var::identifier& name, const var& value); + struct Property + { + Property (const var::identifier& name, const var& value); - var::identifier name; - var value; - }; + var::identifier name; + var value; + }; - const String type; - OwnedArray properties; - ReferenceCountedArray children; - SortedSet valueTreesWithListeners; - SharedObject* parent; + const String type; + OwnedArray properties; + ReferenceCountedArray children; + SortedSet valueTreesWithListeners; + SharedObject* parent; - void sendPropertyChangeMessage (const var::identifier& property); - void sendChildChangeMessage(); - void sendParentChangeMessage(); - const var getProperty (const var::identifier& name) const; - void setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager); - bool hasProperty (const var::identifier& name) const; - void removeProperty (const var::identifier& name, UndoManager* const undoManager); - void removeAllProperties (UndoManager* const undoManager); - bool isAChildOf (const SharedObject* const possibleParent) const; - ValueTree getChildWithName (const String& type) const; - ValueTree getChildWithProperty (const var::identifier& propertyName, const var& propertyValue) const; - void addChild (SharedObject* child, int index, UndoManager* const undoManager); - void removeChild (const int childIndex, UndoManager* const undoManager); - void removeAllChildren (UndoManager* const undoManager); - XmlElement* createXml() const; + void sendPropertyChangeMessage (const var::identifier& property); + void sendChildChangeMessage(); + void sendParentChangeMessage(); + const var getProperty (const var::identifier& name) const; + void setProperty (const var::identifier& name, const var& newValue, UndoManager* const undoManager); + bool hasProperty (const var::identifier& name) const; + void removeProperty (const var::identifier& name, UndoManager* const undoManager); + void removeAllProperties (UndoManager* const undoManager); + bool isAChildOf (const SharedObject* const possibleParent) const; + ValueTree getChildWithName (const String& type) const; + ValueTree getChildWithProperty (const var::identifier& propertyName, const var& propertyValue) const; + void addChild (SharedObject* child, int index, UndoManager* const undoManager); + void removeChild (const int childIndex, UndoManager* const undoManager); + void removeAllChildren (UndoManager* const undoManager); + XmlElement* createXml() const; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - private: - const SharedObject& operator= (const SharedObject&); - }; + private: + const SharedObject& operator= (const SharedObject&); + }; - friend class SharedObject; + friend class SharedObject; - typedef ReferenceCountedObjectPtr SharedObjectPtr; + typedef ReferenceCountedObjectPtr SharedObjectPtr; - ReferenceCountedObjectPtr object; - SortedSet listeners; + ReferenceCountedObjectPtr object; + SortedSet listeners; - void deliverPropertyChangeMessage (const var::identifier& property); - void deliverChildChangeMessage(); - void deliverParentChangeMessage(); + void deliverPropertyChangeMessage (const var::identifier& property); + void deliverChildChangeMessage(); + void deliverParentChangeMessage(); - ValueTree (SharedObject* const object_); + ValueTree (SharedObject* const object_); }; #endif // __JUCE_VALUETREE_JUCEHEADER__ @@ -12711,12 +6604,6 @@ private: #ifndef __JUCE_VOIDARRAY_JUCEHEADER__ #define __JUCE_VOIDARRAY_JUCEHEADER__ -/** - A typedef for an Array of void*'s. - - VoidArrays are used in various places throughout the library instead of - more strongly-typed arrays, to keep code-size low. -*/ typedef Array VoidArray; #endif // __JUCE_VOIDARRAY_JUCEHEADER__ @@ -12735,75 +6622,34 @@ typedef Array VoidArray; #ifndef __JUCE_FILELOGGER_JUCEHEADER__ #define __JUCE_FILELOGGER_JUCEHEADER__ -/** - A simple implemenation of a Logger that writes to a file. - - @see Logger -*/ class JUCE_API FileLogger : public Logger { public: - /** Creates a FileLogger for a given file. + FileLogger (const File& fileToWriteTo, + const String& welcomeMessage, + const int maxInitialFileSizeBytes = 128 * 1024); - @param fileToWriteTo the file that to use - new messages will be appended - to the file. If the file doesn't exist, it will be created, - along with any parent directories that are needed. - @param welcomeMessage when opened, the logger will write a header to the log, along - with the current date and time, and this welcome message - @param maxInitialFileSizeBytes if this is zero or greater, then if the file already exists - but is larger than this number of bytes, then the start of the - file will be truncated to keep the size down. This prevents a log - file getting ridiculously large over time. The file will be truncated - at a new-line boundary. If this value is less than zero, no size limit - will be imposed; if it's zero, the file will always be deleted. Note that - the size is only checked once when this object is created - any logging - that is done later will be appended without any checking - */ - FileLogger (const File& fileToWriteTo, - const String& welcomeMessage, - const int maxInitialFileSizeBytes = 128 * 1024); + ~FileLogger(); - /** Destructor. */ - ~FileLogger(); + void logMessage (const String& message); - void logMessage (const String& message); + static FileLogger* createDefaultAppLogger (const String& logFileSubDirectoryName, + const String& logFileName, + const String& welcomeMessage, + const int maxInitialFileSizeBytes = 128 * 1024); - /** Helper function to create a log file in the correct place for this platform. - - On Windows this will return a logger with a path such as: - c:\\Documents and Settings\\username\\Application Data\\[logFileSubDirectoryName]\\[logFileName] - - On the Mac it'll create something like: - ~/Library/Logs/[logFileName] - - The method might return 0 if the file can't be created for some reason. - - @param logFileSubDirectoryName if a subdirectory is needed, this is what it will be called - - it's best to use the something like the name of your application here. - @param logFileName the name of the file to create, e.g. "MyAppLog.txt". Don't just - call it "log.txt" because if it goes in a directory with logs - from other applications (as it will do on the Mac) then no-one - will know which one is yours! - @param welcomeMessage a message that will be written to the log when it's opened. - @param maxInitialFileSizeBytes (see the FileLogger constructor for more info on this) - */ - static FileLogger* createDefaultAppLogger (const String& logFileSubDirectoryName, - const String& logFileName, - const String& welcomeMessage, - const int maxInitialFileSizeBytes = 128 * 1024); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - File logFile; - CriticalSection logLock; - ScopedPointer logStream; + File logFile; + CriticalSection logLock; + ScopedPointer logStream; - void trimFileSize (int maxFileSizeBytes) const; + void trimFileSize (int maxFileSizeBytes) const; - FileLogger (const FileLogger&); - const FileLogger& operator= (const FileLogger&); + FileLogger (const FileLogger&); + const FileLogger& operator= (const FileLogger&); }; #endif // __JUCE_FILELOGGER_JUCEHEADER__ @@ -12816,49 +6662,12 @@ private: #ifndef __JUCE_INITIALISATION_JUCEHEADER__ #define __JUCE_INITIALISATION_JUCEHEADER__ -/** Initialises Juce's GUI classes. - - If you're embedding Juce into an application that uses its own event-loop rather - than using the START_JUCE_APPLICATION macro, call this function before making any - Juce calls, to make sure things are initialised correctly. - - Note that if you're creating a Juce DLL for Windows, you may also need to call the - PlatformUtilities::setCurrentModuleInstanceHandle() method. - - @see shutdownJuce_GUI(), initialiseJuce_NonGUI() -*/ void JUCE_PUBLIC_FUNCTION initialiseJuce_GUI(); -/** Clears up any static data being used by Juce's GUI classes. - - If you're embedding Juce into an application that uses its own event-loop rather - than using the START_JUCE_APPLICATION macro, call this function in your shutdown - code to clean up any juce objects that might be lying around. - - @see initialiseJuce_GUI(), initialiseJuce_NonGUI() -*/ void JUCE_PUBLIC_FUNCTION shutdownJuce_GUI(); -/** Initialises the core parts of Juce. - - If you're embedding Juce into either a command-line program, call this function - at the start of your main() function to make sure that Juce is initialised correctly. - - Note that if you're creating a Juce DLL for Windows, you may also need to call the - PlatformUtilities::setCurrentModuleInstanceHandle() method. - - @see shutdownJuce_NonGUI, initialiseJuce_GUI -*/ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI(); -/** Clears up any static data being used by Juce's non-gui core classes. - - If you're embedding Juce into either a command-line program, call this function - at the end of your main() function if you want to make sure any Juce objects are - cleaned up correctly. - - @see initialiseJuce_NonGUI, initialiseJuce_GUI -*/ void JUCE_PUBLIC_FUNCTION shutdownJuce_NonGUI(); #endif // __JUCE_INITIALISATION_JUCEHEADER__ @@ -12880,77 +6689,31 @@ void JUCE_PUBLIC_FUNCTION shutdownJuce_NonGUI(); #ifndef __JUCE_PERFORMANCECOUNTER_JUCEHEADER__ #define __JUCE_PERFORMANCECOUNTER_JUCEHEADER__ -/** A timer for measuring performance of code and dumping the results to a file. - - e.g. @code - - PerformanceCounter pc ("fish", 50, "/temp/myfishlog.txt"); - - for (;;) - { - pc.start(); - - doSomethingFishy(); - - pc.stop(); - } - @endcode - - In this example, the time of each period between calling start/stop will be - measured and averaged over 50 runs, and the results printed to a file - every 50 times round the loop. -*/ class JUCE_API PerformanceCounter { public: - /** Creates a PerformanceCounter object. + PerformanceCounter (const String& counterName, + int runsPerPrintout = 100, + const File& loggingFile = File::nonexistent); - @param counterName the name used when printing out the statistics - @param runsPerPrintout the number of start/stop iterations before calling - printStatistics() - @param loggingFile a file to dump the results to - if this is File::nonexistent, - the results are just written to the debugger output - */ - PerformanceCounter (const String& counterName, - int runsPerPrintout = 100, - const File& loggingFile = File::nonexistent); + ~PerformanceCounter(); - /** Destructor. */ - ~PerformanceCounter(); + void start(); - /** Starts timing. + void stop(); - @see stop - */ - void start(); + void printStatistics(); - /** Stops timing and prints out the results. - - The number of iterations before doing a printout of the - results is set in the constructor. - - @see start - */ - void stop(); - - /** Dumps the current metrics to the debugger output and to a file. - - As well as using Logger::outputDebugString to print the results, - this will write then to the file specified in the constructor (if - this was valid). - */ - void printStatistics(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String name; - int numRuns, runsPerPrint; - double totalTime; - int64 started; - File outputFile; + String name; + int numRuns, runsPerPrint; + double totalTime; + int64 started; + File outputFile; }; #endif // __JUCE_PERFORMANCECOUNTER_JUCEHEADER__ @@ -12966,161 +6729,77 @@ private: #ifndef __JUCE_PLATFORMUTILITIES_JUCEHEADER__ #define __JUCE_PLATFORMUTILITIES_JUCEHEADER__ -/** - A collection of miscellaneous platform-specific utilities. - -*/ class JUCE_API PlatformUtilities { public: - /** Plays the operating system's default alert 'beep' sound. */ - static void beep(); + static void beep(); - static bool launchEmailWithAttachments (const String& targetEmailAddress, - const String& emailSubject, - const String& bodyText, - const StringArray& filesToAttach); + static bool launchEmailWithAttachments (const String& targetEmailAddress, + const String& emailSubject, + const String& bodyText, + const StringArray& filesToAttach); #if JUCE_MAC || JUCE_IPHONE || DOXYGEN - /** MAC ONLY - Turns a Core CF String into a juce one. */ - static const String cfStringToJuceString (CFStringRef cfString); + static const String cfStringToJuceString (CFStringRef cfString); - /** MAC ONLY - Turns a juce string into a Core CF one. */ - static CFStringRef juceStringToCFString (const String& s); + static CFStringRef juceStringToCFString (const String& s); - /** MAC ONLY - Turns a file path into an FSRef, returning true if it succeeds. */ - static bool makeFSRefFromPath (FSRef* destFSRef, const String& path); + static bool makeFSRefFromPath (FSRef* destFSRef, const String& path); - /** MAC ONLY - Turns an FSRef into a juce string path. */ - static const String makePathFromFSRef (FSRef* file); + static const String makePathFromFSRef (FSRef* file); - /** MAC ONLY - Converts any decomposed unicode characters in a string into - their precomposed equivalents. - */ - static const String convertToPrecomposedUnicode (const String& s); + static const String convertToPrecomposedUnicode (const String& s); - /** MAC ONLY - Gets the type of a file from the file's resources. */ - static OSType getTypeOfFile (const String& filename); + static OSType getTypeOfFile (const String& filename); - /** MAC ONLY - Returns true if this file is actually a bundle. */ - static bool isBundle (const String& filename); + static bool isBundle (const String& filename); - /** MAC ONLY - Adds an item to the dock */ - static void addItemToDock (const File& file); + static void addItemToDock (const File& file); - /** MAC ONLY - Returns the current OS version number. - E.g. if it's running on 10.4, this will be 4, 10.5 will return 5, etc. - */ - static int getOSXMinorVersionNumber(); + static int getOSXMinorVersionNumber(); #endif #if JUCE_WINDOWS || DOXYGEN - // Some registry helper functions: + // Some registry helper functions: - /** WIN32 ONLY - Returns a string from the registry. + static const String getRegistryValue (const String& regValuePath, + const String& defaultValue = String::empty); - The path is a string for the entire path of a value in the registry, - e.g. "HKEY_CURRENT_USER\Software\foo\bar" - */ - static const String getRegistryValue (const String& regValuePath, - const String& defaultValue = String::empty); + static void setRegistryValue (const String& regValuePath, + const String& value); - /** WIN32 ONLY - Sets a registry value as a string. + static bool registryValueExists (const String& regValuePath); - This will take care of creating any groups needed to get to the given - registry value. - */ - static void setRegistryValue (const String& regValuePath, - const String& value); + static void deleteRegistryValue (const String& regValuePath); - /** WIN32 ONLY - Returns true if the given value exists in the registry. */ - static bool registryValueExists (const String& regValuePath); + static void deleteRegistryKey (const String& regKeyPath); - /** WIN32 ONLY - Deletes a registry value. */ - static void deleteRegistryValue (const String& regValuePath); + static void registerFileAssociation (const String& fileExtension, + const String& symbolicDescription, + const String& fullDescription, + const File& targetExecutable, + int iconResourceNumber); - /** WIN32 ONLY - Deletes a registry key (which is registry-talk for 'folder'). */ - static void deleteRegistryKey (const String& regKeyPath); + static void* JUCE_CALLTYPE getCurrentModuleInstanceHandle() throw(); - /** WIN32 ONLY - Creates a file association in the registry. + static void JUCE_CALLTYPE setCurrentModuleInstanceHandle (void* newHandle) throw(); - This lets you set the exe that should be launched by a given file extension. - @param fileExtension the file extension to associate, including the - initial dot, e.g. ".txt" - @param symbolicDescription a space-free short token to identify the file type - @param fullDescription a human-readable description of the file type - @param targetExecutable the executable that should be launched - @param iconResourceNumber the icon that gets displayed for the file type will be - found by looking up this resource number in the - executable. Pass 0 here to not use an icon - */ - static void registerFileAssociation (const String& fileExtension, - const String& symbolicDescription, - const String& fullDescription, - const File& targetExecutable, - int iconResourceNumber); - - /** WIN32 ONLY - This returns the HINSTANCE of the current module. - - In a normal Juce application this will be set to the module handle - of the application executable. - - If you're writing a DLL using Juce and plan to use any Juce messaging or - windows, you'll need to make sure you use the setCurrentModuleInstanceHandle() - to set the correct module handle in your DllMain() function, because - the win32 system relies on the correct instance handle when opening windows. - */ - static void* JUCE_CALLTYPE getCurrentModuleInstanceHandle() throw(); - - /** WIN32 ONLY - Sets a new module handle to be used by the library. - - @see getCurrentModuleInstanceHandle() - */ - static void JUCE_CALLTYPE setCurrentModuleInstanceHandle (void* newHandle) throw(); - - /** WIN32 ONLY - Gets the command-line params as a string. - - This is needed to avoid unicode problems with the argc type params. - */ - static const String JUCE_CALLTYPE getCurrentCommandLineParams() throw(); + static const String JUCE_CALLTYPE getCurrentCommandLineParams() throw(); #endif - /** Clears the floating point unit's flags. - - Only has an effect under win32, currently. - */ - static void fpuReset(); + static void fpuReset(); #if JUCE_LINUX || JUCE_WINDOWS - /** Loads a dynamically-linked library into the process's address space. + static void* loadDynamicLibrary (const String& pathOrFilename); - @param pathOrFilename the platform-dependent name and search path - @returns a handle which can be used by getProcedureEntryPoint(), or - zero if it fails. - @see freeDynamicLibrary, getProcedureEntryPoint - */ - static void* loadDynamicLibrary (const String& pathOrFilename); + static void freeDynamicLibrary (void* libraryHandle); - /** Frees a dynamically-linked library. - - @param libraryHandle a handle created by loadDynamicLibrary - @see loadDynamicLibrary, getProcedureEntryPoint - */ - static void freeDynamicLibrary (void* libraryHandle); - - /** Finds a procedure call in a dynamically-linked library. - - @param libraryHandle a library handle returned by loadDynamicLibrary - @param procedureName the name of the procedure call to try to load - @returns a pointer to the function if found, or 0 if it fails - @see loadDynamicLibrary - */ - static void* getProcedureEntryPoint (void* libraryHandle, - const String& procedureName); + static void* getProcedureEntryPoint (void* libraryHandle, + const String& procedureName); #endif #if JUCE_LINUX || DOXYGEN @@ -13130,105 +6809,68 @@ public: #if JUCE_MAC || JUCE_IPHONE -/** A handy C++ wrapper that creates and deletes an NSAutoreleasePool object - using RAII. -*/ class ScopedAutoReleasePool { public: - ScopedAutoReleasePool(); - ~ScopedAutoReleasePool(); + ScopedAutoReleasePool(); + ~ScopedAutoReleasePool(); private: - void* pool; + void* pool; - ScopedAutoReleasePool (const ScopedAutoReleasePool&); - const ScopedAutoReleasePool& operator= (const ScopedAutoReleasePool&); + ScopedAutoReleasePool (const ScopedAutoReleasePool&); + const ScopedAutoReleasePool& operator= (const ScopedAutoReleasePool&); }; #endif #if JUCE_MAC -/** - A wrapper class for picking up events from an Apple IR remote control device. - - To use it, just create a subclass of this class, implementing the buttonPressed() - callback, then call start() and stop() to start or stop receiving events. -*/ class JUCE_API AppleRemoteDevice { public: - AppleRemoteDevice(); - virtual ~AppleRemoteDevice(); + AppleRemoteDevice(); + virtual ~AppleRemoteDevice(); - /** The set of buttons that may be pressed. - @see buttonPressed - */ - enum ButtonType - { - menuButton = 0, /**< The menu button (if it's held for a short time). */ - playButton, /**< The play button. */ - plusButton, /**< The plus or volume-up button. */ - minusButton, /**< The minus or volume-down button. */ - rightButton, /**< The right button (if it's held for a short time). */ - leftButton, /**< The left button (if it's held for a short time). */ - rightButton_Long, /**< The right button (if it's held for a long time). */ - leftButton_Long, /**< The menu button (if it's held for a long time). */ - menuButton_Long, /**< The menu button (if it's held for a long time). */ - playButtonSleepMode, - switched - }; + enum ButtonType + { + menuButton = 0, /**< The menu button (if it's held for a short time). */ + playButton, /**< The play button. */ + plusButton, /**< The plus or volume-up button. */ + minusButton, /**< The minus or volume-down button. */ + rightButton, /**< The right button (if it's held for a short time). */ + leftButton, /**< The left button (if it's held for a short time). */ + rightButton_Long, /**< The right button (if it's held for a long time). */ + leftButton_Long, /**< The menu button (if it's held for a long time). */ + menuButton_Long, /**< The menu button (if it's held for a long time). */ + playButtonSleepMode, + switched + }; - /** Override this method to receive the callback about a button press. + virtual void buttonPressed (const ButtonType buttonId, const bool isDown) = 0; - The callback will happen on the application's message thread. + bool start (const bool inExclusiveMode); - Some buttons trigger matching up and down events, in which the isDown parameter - will be true and then false. Others only send a single event when the - button is pressed. - */ - virtual void buttonPressed (const ButtonType buttonId, const bool isDown) = 0; + void stop(); - /** Starts the device running and responding to events. + bool isActive() const; - Returns true if it managed to open the device. + int getRemoteId() const { return remoteId; } - @param inExclusiveMode if true, the remote will be grabbed exclusively for this app, - and will not be available to any other part of the system. If - false, it will be shared with other apps. - @see stop - */ - bool start (const bool inExclusiveMode); + juce_UseDebuggingNewOperator - /** Stops the device running. - @see start - */ - void stop(); - - /** Returns true if the device has been started successfully. - */ - bool isActive() const; - - /** Returns the ID number of the remote, if it has sent one. - */ - int getRemoteId() const { return remoteId; } - - juce_UseDebuggingNewOperator - - /** @internal */ - void handleCallbackInternal(); + void handleCallbackInternal(); private: - void* device; - void* queue; - int remoteId; + void* device; + void* queue; + int remoteId; - bool open (const bool openInExclusiveMode); + bool open (const bool openInExclusiveMode); - AppleRemoteDevice (const AppleRemoteDevice&); - const AppleRemoteDevice& operator= (const AppleRemoteDevice&); + AppleRemoteDevice (const AppleRemoteDevice&); + const AppleRemoteDevice& operator= (const AppleRemoteDevice&); }; #endif @@ -13243,92 +6885,40 @@ private: #ifndef __JUCE_RANDOM_JUCEHEADER__ #define __JUCE_RANDOM_JUCEHEADER__ -/** - A simple pseudo-random number generator. -*/ class JUCE_API Random { public: - /** Creates a Random object based on a seed value. + Random (const int64 seedValue) throw(); - For a given seed value, the subsequent numbers generated by this object - will be predictable, so a good idea is to set this value based - on the time, e.g. + ~Random() throw(); - new Random (Time::currentTimeMillis()) - */ - Random (const int64 seedValue) throw(); + int nextInt() throw(); - /** Destructor. */ - ~Random() throw(); + int nextInt (const int maxValue) throw(); - /** Returns the next random 32 bit integer. + int64 nextInt64() throw(); - @returns a random integer from the full range 0x80000000 to 0x7fffffff - */ - int nextInt() throw(); + float nextFloat() throw(); - /** Returns the next random number, limited to a given range. + double nextDouble() throw(); - @returns a random integer between 0 (inclusive) and maxValue (exclusive). - */ - int nextInt (const int maxValue) throw(); + bool nextBool() throw(); - /** Returns the next 64-bit random number. + const BitArray nextLargeNumber (const BitArray& maximumValue) throw(); - @returns a random integer from the full range 0x8000000000000000 to 0x7fffffffffffffff - */ - int64 nextInt64() throw(); + void fillBitsRandomly (BitArray& arrayToChange, int startBit, int numBits) throw(); - /** Returns the next random floating-point number. + static Random& getSystemRandom() throw(); - @returns a random value in the range 0 to 1.0 - */ - float nextFloat() throw(); + void setSeed (const int64 newSeed) throw(); - /** Returns the next random floating-point number. + void setSeedRandomly(); - @returns a random value in the range 0 to 1.0 - */ - double nextDouble() throw(); - - /** Returns the next random boolean value. - */ - bool nextBool() throw(); - - /** Returns a BitArray containing a random number. - - @returns a random value in the range 0 to (maximumValue - 1). - */ - const BitArray nextLargeNumber (const BitArray& maximumValue) throw(); - - /** Sets a range of bits in a BitArray to random values. */ - void fillBitsRandomly (BitArray& arrayToChange, int startBit, int numBits) throw(); - - /** To avoid the overhead of having to create a new Random object whenever - you need a number, this is a shared application-wide object that - can be used. - - It's not thread-safe though, so threads should use their own Random object. - */ - static Random& getSystemRandom() throw(); - - /** Resets this Random object to a given seed value. */ - void setSeed (const int64 newSeed) throw(); - - /** Reseeds this generator using a value generated from various semi-random system - properties like the current time, etc. - - Because this function convolves the time with the last seed value, calling - it repeatedly will increase the randomness of the final result. - */ - void setSeedRandomly(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - int64 seed; + int64 seed; }; #endif // __JUCE_RANDOM_JUCEHEADER__ @@ -13344,253 +6934,150 @@ private: #ifndef __JUCE_SINGLETON_JUCEHEADER__ #define __JUCE_SINGLETON_JUCEHEADER__ -/** - Macro to declare member variables and methods for a singleton class. - - To use this, add the line juce_DeclareSingleton (MyClass, doNotRecreateAfterDeletion) - to the class's definition. - - Then put a macro juce_ImplementSingleton (MyClass) along with the class's - implementation code. - - It's also a very good idea to also add the call clearSingletonInstance() in your class's - destructor, in case it is deleted by other means than deleteInstance() - - Clients can then call the static method MyClass::getInstance() to get a pointer - to the singleton, or MyClass::getInstanceWithoutCreating() which will return 0 if - no instance currently exists. - - e.g. @code - - class MySingleton - { - public: - MySingleton() - { - } - - ~MySingleton() - { - // this ensures that no dangling pointers are left when the - // singleton is deleted. - clearSingletonInstance(); - } - - juce_DeclareSingleton (MySingleton, false) - }; - - juce_ImplementSingleton (MySingleton) - - // example of usage: - MySingleton* m = MySingleton::getInstance(); // creates the singleton if there isn't already one. - - ... - - MySingleton::deleteInstance(); // safely deletes the singleton (if it's been created). - - @endcode - - If doNotRecreateAfterDeletion = true, it won't allow the object to be created more - than once during the process's lifetime - i.e. after you've created and deleted the - object, getInstance() will refuse to create another one. This can be useful to stop - objects being accidentally re-created during your app's shutdown code. - - If you know that your object will only be created and deleted by a single thread, you - can use the slightly more efficient juce_DeclareSingleton_SingleThreaded() macro instead - of this one. - - @see juce_ImplementSingleton, juce_DeclareSingleton_SingleThreaded -*/ #define juce_DeclareSingleton(classname, doNotRecreateAfterDeletion) \ \ - static classname* _singletonInstance; \ - static JUCE_NAMESPACE::CriticalSection _singletonLock; \ + static classname* _singletonInstance; \ + static JUCE_NAMESPACE::CriticalSection _singletonLock; \ \ - static classname* getInstance() \ - { \ - if (_singletonInstance == 0) \ - {\ - const JUCE_NAMESPACE::ScopedLock sl (_singletonLock); \ + static classname* getInstance() \ + { \ + if (_singletonInstance == 0) \ + {\ + const JUCE_NAMESPACE::ScopedLock sl (_singletonLock); \ \ - if (_singletonInstance == 0) \ - { \ - static bool alreadyInside = false; \ - static bool createdOnceAlready = false; \ + if (_singletonInstance == 0) \ + { \ + static bool alreadyInside = false; \ + static bool createdOnceAlready = false; \ \ - const bool problem = alreadyInside || ((doNotRecreateAfterDeletion) && createdOnceAlready); \ - jassert (! problem); \ - if (! problem) \ - { \ - createdOnceAlready = true; \ - alreadyInside = true; \ - classname* newObject = new classname(); /* (use a stack variable to avoid setting the newObject value before the class has finished its constructor) */ \ - alreadyInside = false; \ + const bool problem = alreadyInside || ((doNotRecreateAfterDeletion) && createdOnceAlready); \ + jassert (! problem); \ + if (! problem) \ + { \ + createdOnceAlready = true; \ + alreadyInside = true; \ + classname* newObject = new classname(); /* (use a stack variable to avoid setting the newObject value before the class has finished its constructor) */ \ + alreadyInside = false; \ \ - _singletonInstance = newObject; \ - } \ - } \ - } \ + _singletonInstance = newObject; \ + } \ + } \ + } \ \ - return _singletonInstance; \ - } \ + return _singletonInstance; \ + } \ \ - static inline classname* getInstanceWithoutCreating() throw() \ - { \ - return _singletonInstance; \ - } \ + static inline classname* getInstanceWithoutCreating() throw() \ + { \ + return _singletonInstance; \ + } \ \ - static void deleteInstance() \ - { \ - const JUCE_NAMESPACE::ScopedLock sl (_singletonLock); \ - if (_singletonInstance != 0) \ - { \ - classname* const old = _singletonInstance; \ - _singletonInstance = 0; \ - delete old; \ - } \ - } \ + static void deleteInstance() \ + { \ + const JUCE_NAMESPACE::ScopedLock sl (_singletonLock); \ + if (_singletonInstance != 0) \ + { \ + classname* const old = _singletonInstance; \ + _singletonInstance = 0; \ + delete old; \ + } \ + } \ \ - void clearSingletonInstance() throw() \ - { \ - if (_singletonInstance == this) \ - _singletonInstance = 0; \ - } + void clearSingletonInstance() throw() \ + { \ + if (_singletonInstance == this) \ + _singletonInstance = 0; \ + } -/** This is a counterpart to the juce_DeclareSingleton macro. - - After adding the juce_DeclareSingleton to the class definition, this macro has - to be used in the cpp file. -*/ #define juce_ImplementSingleton(classname) \ \ - classname* classname::_singletonInstance = 0; \ - JUCE_NAMESPACE::CriticalSection classname::_singletonLock; + classname* classname::_singletonInstance = 0; \ + JUCE_NAMESPACE::CriticalSection classname::_singletonLock; -/** - Macro to declare member variables and methods for a singleton class. - - This is exactly the same as juce_DeclareSingleton, but doesn't use a critical - section to make access to it thread-safe. If you know that your object will - only ever be created or deleted by a single thread, then this is a - more efficient version to use. - - If doNotRecreateAfterDeletion = true, it won't allow the object to be created more - than once during the process's lifetime - i.e. after you've created and deleted the - object, getInstance() will refuse to create another one. This can be useful to stop - objects being accidentally re-created during your app's shutdown code. - - See the documentation for juce_DeclareSingleton for more information about - how to use it, the only difference being that you have to use - juce_ImplementSingleton_SingleThreaded instead of juce_ImplementSingleton. - - @see juce_ImplementSingleton_SingleThreaded, juce_DeclareSingleton, juce_DeclareSingleton_SingleThreaded_Minimal -*/ #define juce_DeclareSingleton_SingleThreaded(classname, doNotRecreateAfterDeletion) \ \ - static classname* _singletonInstance; \ + static classname* _singletonInstance; \ \ - static classname* getInstance() \ - { \ - if (_singletonInstance == 0) \ - { \ - static bool alreadyInside = false; \ - static bool createdOnceAlready = false; \ + static classname* getInstance() \ + { \ + if (_singletonInstance == 0) \ + { \ + static bool alreadyInside = false; \ + static bool createdOnceAlready = false; \ \ - const bool problem = alreadyInside || ((doNotRecreateAfterDeletion) && createdOnceAlready); \ - jassert (! problem); \ - if (! problem) \ - { \ - createdOnceAlready = true; \ - alreadyInside = true; \ - classname* newObject = new classname(); /* (use a stack variable to avoid setting the newObject value before the class has finished its constructor) */ \ - alreadyInside = false; \ + const bool problem = alreadyInside || ((doNotRecreateAfterDeletion) && createdOnceAlready); \ + jassert (! problem); \ + if (! problem) \ + { \ + createdOnceAlready = true; \ + alreadyInside = true; \ + classname* newObject = new classname(); /* (use a stack variable to avoid setting the newObject value before the class has finished its constructor) */ \ + alreadyInside = false; \ \ - _singletonInstance = newObject; \ - } \ - } \ + _singletonInstance = newObject; \ + } \ + } \ \ - return _singletonInstance; \ - } \ + return _singletonInstance; \ + } \ \ - static inline classname* getInstanceWithoutCreating() throw() \ - { \ - return _singletonInstance; \ - } \ + static inline classname* getInstanceWithoutCreating() throw() \ + { \ + return _singletonInstance; \ + } \ \ - static void deleteInstance() \ - { \ - if (_singletonInstance != 0) \ - { \ - classname* const old = _singletonInstance; \ - _singletonInstance = 0; \ - delete old; \ - } \ - } \ + static void deleteInstance() \ + { \ + if (_singletonInstance != 0) \ + { \ + classname* const old = _singletonInstance; \ + _singletonInstance = 0; \ + delete old; \ + } \ + } \ \ - void clearSingletonInstance() throw() \ - { \ - if (_singletonInstance == this) \ - _singletonInstance = 0; \ - } + void clearSingletonInstance() throw() \ + { \ + if (_singletonInstance == this) \ + _singletonInstance = 0; \ + } -/** - Macro to declare member variables and methods for a singleton class. - - This is like juce_DeclareSingleton_SingleThreaded, but doesn't do any checking - for recursion or repeated instantiation. It's intended for use as a lightweight - version of a singleton, where you're using it in very straightforward - circumstances and don't need the extra checking. - - Juce use the normal juce_ImplementSingleton_SingleThreaded as the counterpart - to this declaration, as you would with juce_DeclareSingleton_SingleThreaded. - - See the documentation for juce_DeclareSingleton for more information about - how to use it, the only difference being that you have to use - juce_ImplementSingleton_SingleThreaded instead of juce_ImplementSingleton. - - @see juce_ImplementSingleton_SingleThreaded, juce_DeclareSingleton -*/ #define juce_DeclareSingleton_SingleThreaded_Minimal(classname) \ \ - static classname* _singletonInstance; \ + static classname* _singletonInstance; \ \ - static classname* getInstance() \ - { \ - if (_singletonInstance == 0) \ - _singletonInstance = new classname(); \ + static classname* getInstance() \ + { \ + if (_singletonInstance == 0) \ + _singletonInstance = new classname(); \ \ - return _singletonInstance; \ - } \ + return _singletonInstance; \ + } \ \ - static inline classname* getInstanceWithoutCreating() throw() \ - { \ - return _singletonInstance; \ - } \ + static inline classname* getInstanceWithoutCreating() throw() \ + { \ + return _singletonInstance; \ + } \ \ - static void deleteInstance() \ - { \ - if (_singletonInstance != 0) \ - { \ - classname* const old = _singletonInstance; \ - _singletonInstance = 0; \ - delete old; \ - } \ - } \ + static void deleteInstance() \ + { \ + if (_singletonInstance != 0) \ + { \ + classname* const old = _singletonInstance; \ + _singletonInstance = 0; \ + delete old; \ + } \ + } \ \ - void clearSingletonInstance() throw() \ - { \ - if (_singletonInstance == this) \ - _singletonInstance = 0; \ - } + void clearSingletonInstance() throw() \ + { \ + if (_singletonInstance == this) \ + _singletonInstance = 0; \ + } -/** This is a counterpart to the juce_DeclareSingleton_SingleThreaded macro. - - After adding juce_DeclareSingleton_SingleThreaded or juce_DeclareSingleton_SingleThreaded_Minimal - to the class definition, this macro has to be used somewhere in the cpp file. -*/ #define juce_ImplementSingleton_SingleThreaded(classname) \ \ - classname* classname::_singletonInstance = 0; + classname* classname::_singletonInstance = 0; #endif // __JUCE_SINGLETON_JUCEHEADER__ /********* End of inlined file: juce_Singleton.h *********/ @@ -13605,141 +7092,71 @@ private: #ifndef __JUCE_SYSTEMSTATS_JUCEHEADER__ #define __JUCE_SYSTEMSTATS_JUCEHEADER__ -/** - Contains methods for finding out about the current hardware and OS configuration. -*/ class JUCE_API SystemStats { public: - /** Returns the current version of JUCE, + static const String getJUCEVersion() throw(); - (just in case you didn't already know at compile-time.) + enum OperatingSystemType + { + UnknownOS = 0, - See also the JUCE_VERSION, JUCE_MAJOR_VERSION and JUCE_MINOR_VERSION macros. - */ - static const String getJUCEVersion() throw(); + MacOSX = 0x1000, + Linux = 0x2000, - /** The set of possible results of the getOperatingSystemType() method. - */ - enum OperatingSystemType - { - UnknownOS = 0, + Win95 = 0x4001, + Win98 = 0x4002, + WinNT351 = 0x4103, + WinNT40 = 0x4104, + Win2000 = 0x4105, + WinXP = 0x4106, + WinVista = 0x4107, + Windows7 = 0x4108, - MacOSX = 0x1000, - Linux = 0x2000, + Windows = 0x4000, /**< To test whether any version of Windows is running, + you can use the expression ((getOperatingSystemType() & Windows) != 0). */ + WindowsNT = 0x0100, /**< To test whether the platform is Windows NT or later (i.e. not Win95 or 98), + you can use the expression ((getOperatingSystemType() & WindowsNT) != 0). */ + }; - Win95 = 0x4001, - Win98 = 0x4002, - WinNT351 = 0x4103, - WinNT40 = 0x4104, - Win2000 = 0x4105, - WinXP = 0x4106, - WinVista = 0x4107, - Windows7 = 0x4108, + static OperatingSystemType getOperatingSystemType() throw(); - Windows = 0x4000, /**< To test whether any version of Windows is running, - you can use the expression ((getOperatingSystemType() & Windows) != 0). */ - WindowsNT = 0x0100, /**< To test whether the platform is Windows NT or later (i.e. not Win95 or 98), - you can use the expression ((getOperatingSystemType() & WindowsNT) != 0). */ - }; + static const String getOperatingSystemName() throw(); - /** Returns the type of operating system we're running on. + static bool isOperatingSystem64Bit() throw(); - @returns one of the values from the OperatingSystemType enum. - @see getOperatingSystemName - */ - static OperatingSystemType getOperatingSystemType() throw(); + // CPU and memory information.. - /** Returns the name of the type of operating system we're running on. + static int getCpuSpeedInMegaherz() throw(); - @returns a string describing the OS type. - @see getOperatingSystemType - */ - static const String getOperatingSystemName() throw(); + static const String getCpuVendor() throw(); - /** Returns true if the OS is 64-bit, or false for a 32-bit OS. - */ - static bool isOperatingSystem64Bit() throw(); + static bool hasMMX() throw(); - // CPU and memory information.. + static bool hasSSE() throw(); - /** Returns the approximate CPU speed. + static bool hasSSE2() throw(); - @returns the speed in megahertz, e.g. 1500, 2500, 32000 (depending on - what year you're reading this...) - */ - static int getCpuSpeedInMegaherz() throw(); + static bool has3DNow() throw(); - /** Returns a string to indicate the CPU vendor. + static int getNumCpus() throw(); - Might not be known on some systems. - */ - static const String getCpuVendor() throw(); + static int64 getClockCycleCounter() throw(); - /** Checks whether Intel MMX instructions are available. */ - static bool hasMMX() throw(); + static int getMemorySizeInMegabytes() throw(); - /** Checks whether Intel SSE instructions are available. */ - static bool hasSSE() throw(); + static int getPageSize() throw(); - /** Checks whether Intel SSE2 instructions are available. */ - static bool hasSSE2() throw(); - - /** Checks whether AMD 3DNOW instructions are available. */ - static bool has3DNow() throw(); - - /** Returns the number of CPUs. - */ - static int getNumCpus() throw(); - - /** Returns a clock-cycle tick counter, if available. - - If the machine can do it, this will return a tick-count - where each tick is one cpu clock cycle - used for profiling - code. - - @returns the tick count, or zero if not available. - */ - static int64 getClockCycleCounter() throw(); - - /** Finds out how much RAM is in the machine. - - @returns the approximate number of megabytes of memory, or zero if - something goes wrong when finding out. - */ - static int getMemorySizeInMegabytes() throw(); - - /** Returns the system page-size. - - This is only used by programmers with beards. - */ - static int getPageSize() throw(); - - /** Returns a list of MAC addresses found on this machine. - - @param addresses an array into which the MAC addresses should be copied - @param maxNum the number of elements in this array - @param littleEndian the endianness of the numbers to return. If this is true, - the least-significant byte of each number is the first byte - of the mac address. If false, the least significant byte is - the last number. Note that the default values of this parameter - are different on Mac/PC to avoid breaking old software that was - written before this parameter was added (when the two systems - defaulted to using different endiannesses). In newer - software you probably want to specify an explicit value - for this. - @returns the number of MAC addresses that were found - */ - static int getMACAddresses (int64* addresses, int maxNum, + static int getMACAddresses (int64* addresses, int maxNum, #if JUCE_MAC - const bool littleEndian = true) throw(); + const bool littleEndian = true) throw(); #else - const bool littleEndian = false) throw(); + const bool littleEndian = false) throw(); #endif - // not-for-public-use platform-specific method gets called at startup to initialise things. - static void initialiseStats() throw(); + // not-for-public-use platform-specific method gets called at startup to initialise things. + static void initialiseStats() throw(); }; #endif // __JUCE_SYSTEMSTATS_JUCEHEADER__ @@ -13758,87 +7175,46 @@ public: #ifndef __JUCE_UUID_JUCEHEADER__ #define __JUCE_UUID_JUCEHEADER__ -/** - A universally unique 128-bit identifier. - - This class generates very random unique numbers based on the system time - and MAC addresses if any are available. It's extremely unlikely that two identical - UUIDs would ever be created by chance. - - The class includes methods for saving the ID as a string or as raw binary data. -*/ class JUCE_API Uuid { public: - /** Creates a new unique ID. */ - Uuid(); + Uuid(); - /** Destructor. */ - ~Uuid() throw(); + ~Uuid() throw(); - /** Creates a copy of another UUID. */ - Uuid (const Uuid& other); + Uuid (const Uuid& other); - /** Copies another UUID. */ - Uuid& operator= (const Uuid& other); + Uuid& operator= (const Uuid& other); - /** Returns true if the ID is zero. */ - bool isNull() const throw(); + bool isNull() const throw(); - /** Compares two UUIDs. */ - bool operator== (const Uuid& other) const; + bool operator== (const Uuid& other) const; - /** Compares two UUIDs. */ - bool operator!= (const Uuid& other) const; + bool operator!= (const Uuid& other) const; - /** Returns a stringified version of this UUID. + const String toString() const; - A Uuid object can later be reconstructed from this string using operator= or - the constructor that takes a string parameter. + Uuid (const String& uuidString); - @returns a 32 character hex string. - */ - const String toString() const; + Uuid& operator= (const String& uuidString); - /** Creates an ID from an encoded string version. + const uint8* getRawData() const throw() { return value.asBytes; } - @see toString - */ - Uuid (const String& uuidString); + Uuid (const uint8* const rawData); - /** Copies from a stringified UUID. + Uuid& operator= (const uint8* const rawData); - The string passed in should be one that was created with the toString() method. - */ - Uuid& operator= (const String& uuidString); - - /** Returns a pointer to the internal binary representation of the ID. - - This is an array of 16 bytes. To reconstruct a Uuid from its data, use - the constructor or operator= method that takes an array of uint8s. - */ - const uint8* getRawData() const throw() { return value.asBytes; } - - /** Creates a UUID from a 16-byte array. - - @see getRawData - */ - Uuid (const uint8* const rawData); - - /** Sets this UUID from 16-bytes of raw data. */ - Uuid& operator= (const uint8* const rawData); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - union - { - uint8 asBytes [16]; - int asInt[4]; - int64 asInt64[2]; + union + { + uint8 asBytes [16]; + int asInt[4]; + int64 asInt64[2]; - } value; + } value; }; #endif // __JUCE_UUID_JUCEHEADER__ @@ -13851,42 +7227,29 @@ private: #ifndef __JUCE_BLOWFISH_JUCEHEADER__ #define __JUCE_BLOWFISH_JUCEHEADER__ -/** - BlowFish encryption class. - -*/ class JUCE_API BlowFish { public: - /** Creates an object that can encode/decode based on the specified key. + BlowFish (const uint8* keyData, int keyBytes); - The key data can be up to 72 bytes long. - */ - BlowFish (const uint8* keyData, int keyBytes); + BlowFish (const BlowFish& other); - /** Creates a copy of another blowfish object. */ - BlowFish (const BlowFish& other); + const BlowFish& operator= (const BlowFish& other); - /** Copies another blowfish object. */ - const BlowFish& operator= (const BlowFish& other); + ~BlowFish(); - /** Destructor. */ - ~BlowFish(); + void encrypt (uint32& data1, uint32& data2) const; - /** Encrypts a pair of 32-bit integers. */ - void encrypt (uint32& data1, uint32& data2) const; + void decrypt (uint32& data1, uint32& data2) const; - /** Decrypts a pair of 32-bit integers. */ - void decrypt (uint32& data1, uint32& data2) const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - uint32 p[18]; - HeapBlock s[4]; + uint32 p[18]; + HeapBlock s[4]; - uint32 F (uint32 x) const; + uint32 F (uint32 x) const; }; #endif // __JUCE_BLOWFISH_JUCEHEADER__ @@ -13899,88 +7262,55 @@ private: #ifndef __JUCE_MD5_JUCEHEADER__ #define __JUCE_MD5_JUCEHEADER__ -/** - MD5 checksum class. - - Create one of these with a block of source data or a string, and it calculates the - MD5 checksum of that data. - - You can then retrieve this checksum as a 16-byte block, or as a hex string. -*/ class JUCE_API MD5 { public: - /** Creates a null MD5 object. */ - MD5(); + MD5(); - /** Creates a copy of another MD5. */ - MD5 (const MD5& other); + MD5 (const MD5& other); - /** Copies another MD5. */ - const MD5& operator= (const MD5& other); + const MD5& operator= (const MD5& other); - /** Creates a checksum for a block of binary data. */ - MD5 (const MemoryBlock& data); + MD5 (const MemoryBlock& data); - /** Creates a checksum for a block of binary data. */ - MD5 (const char* data, const int numBytes); + MD5 (const char* data, const size_t numBytes); - /** Creates a checksum for a string. + MD5 (const String& text); - Note that this operates on the string as a block of unicode characters, so the - result you get will differ from the value you'd get if the string was treated - as a block of utf8 or ascii. Bear this in mind if you're comparing the result - of this method with a checksum created by a different framework, which may have - used a different encoding. - */ - MD5 (const String& text); + MD5 (InputStream& input, int64 numBytesToRead = -1); - /** Creates a checksum for the input from a stream. + MD5 (const File& file); - This will read up to the given number of bytes from the stream, and produce the - checksum of that. If the number of bytes to read is negative, it'll read - until the stream is exhausted. - */ - MD5 (InputStream& input, int numBytesToRead = -1); + ~MD5(); - /** Creates a checksum for a file. */ - MD5 (const File& file); + const MemoryBlock getRawChecksumData() const; - /** Destructor. */ - ~MD5(); + const String toHexString() const; - /** Returns the checksum as a 16-byte block of data. */ - const MemoryBlock getRawChecksumData() const; + bool operator== (const MD5& other) const; - /** Returns the checksum as a 32-digit hex string. */ - const String toHexString() const; + bool operator!= (const MD5& other) const; - /** Compares this to another MD5. */ - bool operator== (const MD5& other) const; - - /** Compares this to another MD5. */ - bool operator!= (const MD5& other) const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - uint8 result [16]; + uint8 result [16]; - struct ProcessContext - { - uint8 buffer [64]; - uint32 state [4]; - uint32 count [2]; + struct ProcessContext + { + uint8 buffer [64]; + uint32 state [4]; + uint32 count [2]; - ProcessContext(); + ProcessContext(); - void processBlock (const uint8* const data, int dataSize); - void transform (const uint8* const buffer); - void finish (uint8* const result); - }; + void processBlock (const uint8* const data, size_t dataSize); + void transform (const uint8* const buffer); + void finish (uint8* const result); + }; - void processStream (InputStream& input, int numBytesToRead); + void processStream (InputStream& input, int64 numBytesToRead); }; #endif // __JUCE_MD5_JUCEHEADER__ @@ -13993,41 +7323,17 @@ private: #ifndef __JUCE_PRIMES_JUCEHEADER__ #define __JUCE_PRIMES_JUCEHEADER__ -/** - Prime number creation class. - - This class contains static methods for generating and testing prime numbers. - - @see BitArray -*/ class JUCE_API Primes { public: - /** Creates a random prime number with a given bit-length. + static const BitArray createProbablePrime (int bitLength, + int certainty, + const int* randomSeeds = 0, + int numRandomSeeds = 0) throw(); - The certainty parameter specifies how many iterations to use when testing - for primality. A safe value might be anything over about 20-30. - - The randomSeeds parameter lets you optionally pass it a set of values with - which to seed the random number generation, improving the security of the - keys generated. - */ - static const BitArray createProbablePrime (int bitLength, - int certainty, - const int* randomSeeds = 0, - int numRandomSeeds = 0) throw(); - - /** Tests a number to see if it's prime. - - This isn't a bulletproof test, it uses a Miller-Rabin test to determine - whether the number is prime. - - The certainty parameter specifies how many iterations to use when testing - a - safe value might be anything over about 20-30. - */ - static bool isProbablyPrime (const BitArray& number, - int certainty) throw(); + static bool isProbablyPrime (const BitArray& number, + int certainty) throw(); }; #endif // __JUCE_PRIMES_JUCEHEADER__ @@ -14040,74 +7346,30 @@ public: #ifndef __JUCE_RSAKEY_JUCEHEADER__ #define __JUCE_RSAKEY_JUCEHEADER__ -/** - RSA public/private key-pair encryption class. - - An object of this type makes up one half of a public/private RSA key pair. Use the - createKeyPair() method to create a matching pair for encoding/decoding. -*/ class JUCE_API RSAKey { public: - /** Creates a null key object. + RSAKey() throw(); - Initialise a pair of objects for use with the createKeyPair() method. - */ - RSAKey() throw(); + RSAKey (const String& stringRepresentation) throw(); - /** Loads a key from an encoded string representation. + ~RSAKey() throw(); - This reloads a key from a string created by the toString() method. - */ - RSAKey (const String& stringRepresentation) throw(); + const String toString() const throw(); - /** Destructor. */ - ~RSAKey() throw(); + bool applyToValue (BitArray& value) const throw(); - /** Turns the key into a string representation. + static void createKeyPair (RSAKey& publicKey, + RSAKey& privateKey, + const int numBits, + const int* randomSeeds = 0, + const int numRandomSeeds = 0) throw(); - This can be reloaded using the constructor that takes a string. - */ - const String toString() const throw(); - - /** Encodes or decodes a value. - - Call this on the public key object to encode some data, then use the matching - private key object to decode it. - - Returns false if the operation couldn't be completed, e.g. if this key hasn't been - initialised correctly. - - NOTE: This method dumbly applies this key to this data. If you encode some data - and then try to decode it with a key that doesn't match, this method will still - happily do its job and return true, but the result won't be what you were expecting. - It's your responsibility to check that the result is what you wanted. - */ - bool applyToValue (BitArray& value) const throw(); - - /** Creates a public/private key-pair. - - Each key will perform one-way encryption that can only be reversed by - using the other key. - - The numBits parameter specifies the size of key, e.g. 128, 256, 512 bit. Bigger - sizes are more secure, but this method will take longer to execute. - - The randomSeeds parameter lets you optionally pass it a set of values with - which to seed the random number generation, improving the security of the - keys generated. - */ - static void createKeyPair (RSAKey& publicKey, - RSAKey& privateKey, - const int numBits, - const int* randomSeeds = 0, - const int numRandomSeeds = 0) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - BitArray part1, part2; + BitArray part1, part2; }; #endif // __JUCE_RSAKEY_JUCEHEADER__ @@ -14120,83 +7382,35 @@ protected: #ifndef __JUCE_DIRECTORYITERATOR_JUCEHEADER__ #define __JUCE_DIRECTORYITERATOR_JUCEHEADER__ -/** - Searches through a the files in a directory, returning each file that is found. - - A DirectoryIterator will search through a directory and its subdirectories using - a wildcard filepattern match. - - If you may be finding a large number of files, this is better than - using File::findChildFiles() because it doesn't block while it finds them - all, and this is more memory-efficient. - - It can also guess how far it's got using a wildly inaccurate algorithm. -*/ class JUCE_API DirectoryIterator { public: - /** Creates a DirectoryIterator for a given directory. + DirectoryIterator (const File& directory, + bool isRecursive, + const String& wildCard = JUCE_T("*"), + const int whatToLookFor = File::findFiles); - After creating one of these, call its next() method to get the - first file - e.g. @code + ~DirectoryIterator(); - DirectoryIterator iter (File ("/animals/mooses"), true, "*.moose"); + bool next(); - while (iter.next()) - { - File theFileItFound (iter.getFile()); + const File getFile() const; - ... etc - } - @endcode + float getEstimatedProgress() const; - @param directory the directory to search in - @param isRecursive whether all the subdirectories should also be searched - @param wildCard the file pattern to match - @param whatToLookFor a value from the File::TypesOfFileToFind enum, specifying - whether to look for files, directories, or both. - */ - DirectoryIterator (const File& directory, - bool isRecursive, - const String& wildCard = JUCE_T("*"), - const int whatToLookFor = File::findFiles); - - /** Destructor. */ - ~DirectoryIterator(); - - /** Call this to move the iterator along to the next file. - - @returns true if a file was found (you can then use getFile() to see what it was) - or - false if there are no more matching files. - */ - bool next(); - - /** Returns the file that the iterator is currently pointing at. - - The result of this call is only valid after a call to next() has returned true. - */ - const File getFile() const; - - /** Returns a guess of how far through the search the iterator has got. - - @returns a value 0.0 to 1.0 to show the progress, although this won't be - very accurate. - */ - float getEstimatedProgress() const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OwnedArray filesFound; - OwnedArray dirsFound; - String wildCard; - int index; - const int whatToLookFor; - ScopedPointer subIterator; + OwnedArray filesFound; + OwnedArray dirsFound; + String wildCard; + int index; + const int whatToLookFor; + ScopedPointer subIterator; - DirectoryIterator (const DirectoryIterator&); - const DirectoryIterator& operator= (const DirectoryIterator&); + DirectoryIterator (const DirectoryIterator&); + const DirectoryIterator& operator= (const DirectoryIterator&); }; #endif // __JUCE_DIRECTORYITERATOR_JUCEHEADER__ @@ -14212,43 +7426,32 @@ private: #ifndef __JUCE_FILEINPUTSTREAM_JUCEHEADER__ #define __JUCE_FILEINPUTSTREAM_JUCEHEADER__ -/** - An input stream that reads from a local file. - - @see InputStream, FileOutputStream, File::createInputStream -*/ class JUCE_API FileInputStream : public InputStream { public: - /** Creates a FileInputStream. + FileInputStream (const File& fileToRead); - @param fileToRead the file to read from - if the file can't be accessed for some - reason, then the stream will just contain no data - */ - FileInputStream (const File& fileToRead); + ~FileInputStream(); - /** Destructor. */ - ~FileInputStream(); + const File& getFile() const throw() { return file; } - const File& getFile() const throw() { return file; } + int64 getTotalLength(); + int read (void* destBuffer, int maxBytesToRead); + bool isExhausted(); + int64 getPosition(); + bool setPosition (int64 pos); - int64 getTotalLength(); - int read (void* destBuffer, int maxBytesToRead); - bool isExhausted(); - int64 getPosition(); - bool setPosition (int64 pos); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - File file; - void* fileHandle; - int64 currentPosition, totalSize; - bool needToSeek; + File file; + void* fileHandle; + int64 currentPosition, totalSize; + bool needToSeek; - FileInputStream (const FileInputStream&); - const FileInputStream& operator= (const FileInputStream&); + FileInputStream (const FileInputStream&); + const FileInputStream& operator= (const FileInputStream&); }; #endif // __JUCE_FILEINPUTSTREAM_JUCEHEADER__ @@ -14261,56 +7464,32 @@ private: #ifndef __JUCE_FILEOUTPUTSTREAM_JUCEHEADER__ #define __JUCE_FILEOUTPUTSTREAM_JUCEHEADER__ -/** - An output stream that writes into a local file. - - @see OutputStream, FileInputStream, File::createOutputStream -*/ class JUCE_API FileOutputStream : public OutputStream { public: - /** Creates a FileOutputStream. + FileOutputStream (const File& fileToWriteTo, + const int bufferSizeToUse = 16384); - If the file doesn't exist, it will first be created. If the file can't be - created or opened, the failedToOpen() method will return - true. + ~FileOutputStream(); - If the file already exists when opened, the stream's write-postion will - be set to the end of the file. To overwrite an existing file, - use File::deleteFile() before opening the stream, or use setPosition(0) - after it's opened (although this won't truncate the file). + const File& getFile() const { return file; } - It's better to use File::createOutputStream() to create one of these, rather - than using the class directly. - */ - FileOutputStream (const File& fileToWriteTo, - const int bufferSizeToUse = 16384); + bool failedToOpen() const { return fileHandle == 0; } - /** Destructor. */ - ~FileOutputStream(); + void flush(); + int64 getPosition(); + bool setPosition (int64 pos); + bool write (const void* data, int numBytes); - /** Returns the file that this stream is writing to. - */ - const File& getFile() const { return file; } - - /** Returns true if the stream couldn't be opened for some reason. - */ - bool failedToOpen() const { return fileHandle == 0; } - - void flush(); - int64 getPosition(); - bool setPosition (int64 pos); - bool write (const void* data, int numBytes); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - File file; - void* fileHandle; - int64 currentPosition; - int bufferSize, bytesInBuffer; - HeapBlock buffer; + File file; + void* fileHandle; + int64 currentPosition; + int bufferSize, bytesInBuffer; + HeapBlock buffer; }; #endif // __JUCE_FILEOUTPUTSTREAM_JUCEHEADER__ @@ -14323,131 +7502,53 @@ private: #ifndef __JUCE_FILESEARCHPATH_JUCEHEADER__ #define __JUCE_FILESEARCHPATH_JUCEHEADER__ -/** - Encapsulates a set of folders that make up a search path. - - @see File -*/ class JUCE_API FileSearchPath { public: - /** Creates an empty search path. */ - FileSearchPath(); + FileSearchPath(); - /** Creates a search path from a string of pathnames. + FileSearchPath (const String& path); - The path can be semicolon- or comma-separated, e.g. - "/foo/bar;/foo/moose;/fish/moose" + FileSearchPath (const FileSearchPath& other); - The separate folders are tokenised and added to the search path. - */ - FileSearchPath (const String& path); + ~FileSearchPath(); - /** Creates a copy of another search path. */ - FileSearchPath (const FileSearchPath& other); + const FileSearchPath& operator= (const String& path); - /** Destructor. */ - ~FileSearchPath(); + int getNumPaths() const; - /** Uses a string containing a list of pathnames to re-initialise this list. + const File operator[] (const int index) const; - This search path is cleared and the semicolon- or comma-separated folders - in this string are added instead. e.g. "/foo/bar;/foo/moose;/fish/moose" - */ - const FileSearchPath& operator= (const String& path); + const String toString() const; - /** Returns the number of folders in this search path. + void add (const File& directoryToAdd, + const int insertIndex = -1); - @see operator[] - */ - int getNumPaths() const; + void addIfNotAlreadyThere (const File& directoryToAdd); - /** Returns one of the folders in this search path. + void remove (const int indexToRemove); - The file returned isn't guaranteed to actually be a valid directory. + void addPath (const FileSearchPath& other); - @see getNumPaths - */ - const File operator[] (const int index) const; + void removeRedundantPaths(); - /** Returns the search path as a semicolon-separated list of directories. */ - const String toString() const; + void removeNonExistentPaths(); - /** Adds a new directory to the search path. + int findChildFiles (OwnedArray& results, + const int whatToLookFor, + const bool searchRecursively, + const String& wildCardPattern = JUCE_T("*")) const; - The new directory is added to the end of the list if the insertIndex parameter is - less than zero, otherwise it is inserted at the given index. - */ - void add (const File& directoryToAdd, - const int insertIndex = -1); + bool isFileInPath (const File& fileToCheck, + const bool checkRecursively) const; - /** Adds a new directory to the search path if it's not already in there. */ - void addIfNotAlreadyThere (const File& directoryToAdd); - - /** Removes a directory from the search path. */ - void remove (const int indexToRemove); - - /** Merges another search path into this one. - - This will remove any duplicate directories. - */ - void addPath (const FileSearchPath& other); - - /** Removes any directories that are actually subdirectories of one of the other directories in the search path. - - If the search is intended to be recursive, there's no point having nested folders in the search - path, because they'll just get searched twice and you'll get duplicate results. - - e.g. if the path is "c:\abc\de;c:\abc", this method will simplify it to "c:\abc" - */ - void removeRedundantPaths(); - - /** Removes any directories that don't actually exist. */ - void removeNonExistentPaths(); - - /** Searches the path for a wildcard. - - This will search all the directories in the search path in order, adding any - matching files to the results array. - - @param results an array to append the results to - @param whatToLookFor a value from the File::TypesOfFileToFind enum, specifying whether to - return files, directories, or both. - @param searchRecursively whether to recursively search the subdirectories too - @param wildCardPattern a pattern to match against the filenames - @returns the number of files added to the array - @see File::findChildFiles - */ - int findChildFiles (OwnedArray& results, - const int whatToLookFor, - const bool searchRecursively, - const String& wildCardPattern = JUCE_T("*")) const; - - /** Finds out whether a file is inside one of the path's directories. - - This will return true if the specified file is a child of one of the - directories specified by this path. Note that this doesn't actually do any - searching or check that the files exist - it just looks at the pathnames - to work out whether the file would be inside a directory. - - @param fileToCheck the file to look for - @param checkRecursively if true, then this will return true if the file is inside a - subfolder of one of the path's directories (at any depth). If false - it will only return true if the file is actually a direct child - of one of the directories. - @see File::isAChildOf - - */ - bool isFileInPath (const File& fileToCheck, - const bool checkRecursively) const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - StringArray directories; + StringArray directories; - void init (const String& path); + void init (const String& path); }; #endif // __JUCE_FILESEARCHPATH_JUCEHEADER__ @@ -14460,80 +7561,41 @@ private: #ifndef __JUCE_NAMEDPIPE_JUCEHEADER__ #define __JUCE_NAMEDPIPE_JUCEHEADER__ -/** - A cross-process pipe that can have data written to and read from it. - - Two or more processes can use these for inter-process communication. - - @see InterprocessConnection -*/ class JUCE_API NamedPipe { public: - /** Creates a NamedPipe. */ - NamedPipe(); + NamedPipe(); - /** Destructor. */ - ~NamedPipe(); + ~NamedPipe(); - /** Tries to open a pipe that already exists. + bool openExisting (const String& pipeName); - Returns true if it succeeds. - */ - bool openExisting (const String& pipeName); + bool createNewPipe (const String& pipeName); - /** Tries to create a new pipe. + void close(); - Returns true if it succeeds. - */ - bool createNewPipe (const String& pipeName); + bool isOpen() const; - /** Closes the pipe, if it's open. */ - void close(); + const String getName() const; - /** True if the pipe is currently open. */ - bool isOpen() const; + int read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds = 5000); - /** Returns the last name that was used to try to open this pipe. */ - const String getName() const; + int write (const void* sourceBuffer, int numBytesToWrite, + int timeOutMilliseconds = 2000); - /** Reads data from the pipe. + void cancelPendingReads(); - This will block until another thread has written enough data into the pipe to fill - the number of bytes specified, or until another thread calls the cancelPendingReads() - method. - - If the operation fails, it returns -1, otherwise, it will return the number of - bytes read. - - If timeOutMilliseconds is less than zero, it will wait indefinitely, otherwise - this is a maximum timeout for reading from the pipe. - */ - int read (void* destBuffer, int maxBytesToRead, int timeOutMilliseconds = 5000); - - /** Writes some data to the pipe. - - If the operation fails, it returns -1, otherwise, it will return the number of - bytes written. - */ - int write (const void* sourceBuffer, int numBytesToWrite, - int timeOutMilliseconds = 2000); - - /** If any threads are currently blocked on a read operation, this tells them to abort. - */ - void cancelPendingReads(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - void* internal; - String currentPipeName; + void* internal; + String currentPipeName; - NamedPipe (const NamedPipe&); - const NamedPipe& operator= (const NamedPipe&); + NamedPipe (const NamedPipe&); + const NamedPipe& operator= (const NamedPipe&); - bool openInternal (const String& pipeName, const bool createPipe); + bool openInternal (const String& pipeName, const bool createPipe); }; #endif // __JUCE_NAMEDPIPE_JUCEHEADER__ @@ -14550,174 +7612,86 @@ private: #ifndef __JUCE_INPUTSOURCE_JUCEHEADER__ #define __JUCE_INPUTSOURCE_JUCEHEADER__ -/** - A lightweight object that can create a stream to read some kind of resource. - - This may be used to refer to a file, or some other kind of source, allowing a - caller to create an input stream that can read from it when required. - - @see FileInputSource -*/ class JUCE_API InputSource { public: - InputSource() throw() {} + InputSource() throw() {} - /** Destructor. */ - virtual ~InputSource() {} + virtual ~InputSource() {} - /** Returns a new InputStream to read this item. + virtual InputStream* createInputStream() = 0; - @returns an inputstream that the caller will delete, or 0 if - the filename isn't found. - */ - virtual InputStream* createInputStream() = 0; + virtual InputStream* createInputStreamFor (const String& relatedItemPath) = 0; - /** Returns a new InputStream to read an item, relative. + virtual int64 hashCode() const = 0; - @param relatedItemPath the relative pathname of the resource that is required - @returns an inputstream that the caller will delete, or 0 if - the item isn't found. - */ - virtual InputStream* createInputStreamFor (const String& relatedItemPath) = 0; - - /** Returns a hash code that uniquely represents this item. - */ - virtual int64 hashCode() const = 0; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; #endif // __JUCE_INPUTSOURCE_JUCEHEADER__ /********* End of inlined file: juce_InputSource.h *********/ -/** - Decodes a ZIP file from a stream. - - This can enumerate the items in a ZIP file and can create suitable stream objects - to read each one. -*/ class JUCE_API ZipFile { public: - /** Creates a ZipFile for a given stream. + ZipFile (InputStream* const inputStream, + const bool deleteStreamWhenDestroyed) throw(); - @param inputStream the stream to read from - @param deleteStreamWhenDestroyed if set to true, the object passed-in - will be deleted when this ZipFile object is deleted - */ - ZipFile (InputStream* const inputStream, - const bool deleteStreamWhenDestroyed) throw(); + ZipFile (const File& file); - /** Creates a ZipFile based for a file. */ - ZipFile (const File& file); + ZipFile (InputSource* const inputSource); - /** Creates a ZipFile for an input source. + ~ZipFile() throw(); - The inputSource object will be owned by the zip file, which will delete - it later when not needed. - */ - ZipFile (InputSource* const inputSource); + struct ZipEntry + { + String filename; - /** Destructor. */ - ~ZipFile() throw(); + unsigned int uncompressedSize; - /** - Contains information about one of the entries in a ZipFile. + Time fileTime; + }; - @see ZipFile::getEntry - */ - struct ZipEntry - { - /** The name of the file, which may also include a partial pathname. */ - String filename; + int getNumEntries() const throw(); - /** The file's original size. */ - unsigned int uncompressedSize; + const ZipEntry* getEntry (const int index) const throw(); - /** The last time the file was modified. */ - Time fileTime; - }; + int getIndexOfFileName (const String& fileName) const throw(); - /** Returns the number of items in the zip file. */ - int getNumEntries() const throw(); + const ZipEntry* getEntry (const String& fileName) const throw(); - /** Returns a structure that describes one of the entries in the zip file. + void sortEntriesByFilename(); - This may return zero if the index is out of range. + InputStream* createStreamForEntry (const int index); - @see ZipFile::ZipEntry - */ - const ZipEntry* getEntry (const int index) const throw(); + void uncompressTo (const File& targetDirectory, + const bool shouldOverwriteFiles = true); - /** Returns the index of the first entry with a given filename. - - This uses a case-sensitive comparison to look for a filename in the - list of entries. It might return -1 if no match is found. - - @see ZipFile::ZipEntry - */ - int getIndexOfFileName (const String& fileName) const throw(); - - /** Returns a structure that describes one of the entries in the zip file. - - This uses a case-sensitive comparison to look for a filename in the - list of entries. It might return 0 if no match is found. - - @see ZipFile::ZipEntry - */ - const ZipEntry* getEntry (const String& fileName) const throw(); - - /** Sorts the list of entries, based on the filename. - */ - void sortEntriesByFilename(); - - /** Creates a stream that can read from one of the zip file's entries. - - The stream that is returned must be deleted by the caller (and - zero might be returned if a stream can't be opened for some reason). - - The stream must not be used after the ZipFile object that created - has been deleted. - */ - InputStream* createStreamForEntry (const int index); - - /** Uncompresses all of the files in the zip file. - - This will expand all the entires into a target directory. The relative - paths of the entries are used. - - @param targetDirectory the root folder to uncompress to - @param shouldOverwriteFiles whether to overwrite existing files with similarly-named ones - */ - void uncompressTo (const File& targetDirectory, - const bool shouldOverwriteFiles = true); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - class ZipInputStream; - class ZipFilenameComparator; - class ZipEntryInfo; + class ZipInputStream; + class ZipFilenameComparator; + class ZipEntryInfo; - OwnedArray entries; - CriticalSection lock; - InputStream* inputStream; - ScopedPointer streamToDelete; - ScopedPointer inputSource; + OwnedArray entries; + CriticalSection lock; + InputStream* inputStream; + ScopedPointer streamToDelete; + ScopedPointer inputSource; #ifdef JUCE_DEBUG - int numOpenStreams; + int numOpenStreams; #endif - void init(); - int findEndOfZipEntryTable (InputStream* in, int& numEntries); - static int compareElements (const ZipEntryInfo* first, const ZipEntryInfo* second); + void init(); + int findEndOfZipEntryTable (InputStream* in, int& numEntries); + static int compareElements (const ZipEntryInfo* first, const ZipEntryInfo* second); - ZipFile (const ZipFile&); - const ZipFile& operator= (const ZipFile&); + ZipFile (const ZipFile&); + const ZipFile& operator= (const ZipFile&); }; #endif // __JUCE_ZIPFILE_JUCEHEADER__ @@ -14730,262 +7704,100 @@ private: #ifndef __JUCE_SOCKET_JUCEHEADER__ #define __JUCE_SOCKET_JUCEHEADER__ -/** - A wrapper for a streaming (TCP) socket. - - This allows low-level use of sockets; for an easier-to-use messaging layer on top of - sockets, you could also try the InterprocessConnection class. - - @see DatagramSocket, InterprocessConnection, InterprocessConnectionServer -*/ class JUCE_API StreamingSocket { public: - /** Creates an uninitialised socket. + StreamingSocket(); - To connect it, use the connect() method, after which you can read() or write() - to it. + ~StreamingSocket(); - To wait for other sockets to connect to this one, the createListener() method - enters "listener" mode, and can be used to spawn new sockets for each connection - that comes along. - */ - StreamingSocket(); + bool bindToPort (const int localPortNumber); - /** Destructor. */ - ~StreamingSocket(); + bool connect (const String& remoteHostname, + const int remotePortNumber, + const int timeOutMillisecs = 3000); - /** Binds the socket to the specified local port. + bool isConnected() const throw() { return connected; } - @returns true on success; false may indicate that another socket is already bound - on the same port - */ - bool bindToPort (const int localPortNumber); + void close(); - /** Tries to connect the socket to hostname:port. + const String& getHostName() const throw() { return hostName; } - If timeOutMillisecs is 0, then this method will block until the operating system - rejects the connection (which could take a long time). + int getPort() const throw() { return portNumber; } - @returns true if it succeeds. - @see isConnected - */ - bool connect (const String& remoteHostname, - const int remotePortNumber, - const int timeOutMillisecs = 3000); + bool isLocal() const throw(); - /** True if the socket is currently connected. */ - bool isConnected() const throw() { return connected; } + int waitUntilReady (const bool readyForReading, + const int timeoutMsecs) const; - /** Closes the connection. */ - void close(); + int read (void* destBuffer, const int maxBytesToRead, + const bool blockUntilSpecifiedAmountHasArrived); - /** Returns the name of the currently connected host. */ - const String& getHostName() const throw() { return hostName; } + int write (const void* sourceBuffer, const int numBytesToWrite); - /** Returns the port number that's currently open. */ - int getPort() const throw() { return portNumber; } + bool createListener (const int portNumber, const String& localHostName = String::empty); - /** True if the socket is connected to this machine rather than over the network. */ - bool isLocal() const throw(); + StreamingSocket* waitForNextConnection() const; - /** Waits until the socket is ready for reading or writing. - - If readyForReading is true, it will wait until the socket is ready for - reading; if false, it will wait until it's ready for writing. - - If the timeout is < 0, it will wait forever, or else will give up after - the specified time. - - If the socket is ready on return, this returns 1. If it times-out before - the socket becomes ready, it returns 0. If an error occurs, it returns -1. - */ - int waitUntilReady (const bool readyForReading, - const int timeoutMsecs) const; - - /** Reads bytes from the socket. - - If blockUntilSpecifiedAmountHasArrived is true, the method will block until - maxBytesToRead bytes have been read, (or until an error occurs). If this - flag is false, the method will return as much data as is currently available - without blocking. - - @returns the number of bytes read, or -1 if there was an error. - @see waitUntilReady - */ - int read (void* destBuffer, const int maxBytesToRead, - const bool blockUntilSpecifiedAmountHasArrived); - - /** Writes bytes to the socket from a buffer. - - Note that this method will block unless you have checked the socket is ready - for writing before calling it (see the waitUntilReady() method). - - @returns the number of bytes written, or -1 if there was an error. - */ - int write (const void* sourceBuffer, const int numBytesToWrite); - - /** Puts this socket into "listener" mode. - - When in this mode, your thread can call waitForNextConnection() repeatedly, - which will spawn new sockets for each new connection, so that these can - be handled in parallel by other threads. - - @param portNumber the port number to listen on - @param localHostName the interface address to listen on - pass an empty - string to listen on all addresses - @returns true if it manages to open the socket successfully. - - @see waitForNextConnection - */ - bool createListener (const int portNumber, const String& localHostName = String::empty); - - /** When in "listener" mode, this waits for a connection and spawns it as a new - socket. - - The object that gets returned will be owned by the caller. - - This method can only be called after using createListener(). - - @see createListener - */ - StreamingSocket* waitForNextConnection() const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String hostName; - int volatile portNumber, handle; - bool connected, isListener; + String hostName; + int volatile portNumber, handle; + bool connected, isListener; - StreamingSocket (const String& hostname, const int portNumber, const int handle); - StreamingSocket (const StreamingSocket&); - const StreamingSocket& operator= (const StreamingSocket&); + StreamingSocket (const String& hostname, const int portNumber, const int handle); + StreamingSocket (const StreamingSocket&); + const StreamingSocket& operator= (const StreamingSocket&); }; -/** - A wrapper for a datagram (UDP) socket. - - This allows low-level use of sockets; for an easier-to-use messaging layer on top of - sockets, you could also try the InterprocessConnection class. - - @see StreamingSocket, InterprocessConnection, InterprocessConnectionServer -*/ class JUCE_API DatagramSocket { public: - /** - Creates an (uninitialised) datagram socket. + DatagramSocket (const int localPortNumber, + const bool enableBroadcasting = false); - The localPortNumber is the port on which to bind this socket. If this value is 0, - the port number is assigned by the operating system. + ~DatagramSocket(); - To use the socket for sending, call the connect() method. This will not immediately - make a connection, but will save the destination you've provided. After this, you can - call read() or write(). + bool bindToPort (const int localPortNumber); - If enableBroadcasting is true, the socket will be allowed to send broadcast messages - (may require extra privileges on linux) + bool connect (const String& remoteHostname, + const int remotePortNumber, + const int timeOutMillisecs = 3000); - To wait for other sockets to connect to this one, call waitForNextConnection(). - */ - DatagramSocket (const int localPortNumber, - const bool enableBroadcasting = false); + bool isConnected() const throw() { return connected; } - /** Destructor. */ - ~DatagramSocket(); + void close(); - /** Binds the socket to the specified local port. + const String& getHostName() const throw() { return hostName; } - @returns true on success; false may indicate that another socket is already bound - on the same port - */ - bool bindToPort (const int localPortNumber); + int getPort() const throw() { return portNumber; } - /** Tries to connect the socket to hostname:port. + bool isLocal() const throw(); - If timeOutMillisecs is 0, then this method will block until the operating system - rejects the connection (which could take a long time). + int waitUntilReady (const bool readyForReading, + const int timeoutMsecs) const; - @returns true if it succeeds. - @see isConnected - */ - bool connect (const String& remoteHostname, - const int remotePortNumber, - const int timeOutMillisecs = 3000); + int read (void* destBuffer, const int maxBytesToRead, + const bool blockUntilSpecifiedAmountHasArrived); - /** True if the socket is currently connected. */ - bool isConnected() const throw() { return connected; } + int write (const void* sourceBuffer, const int numBytesToWrite); - /** Closes the connection. */ - void close(); + DatagramSocket* waitForNextConnection() const; - /** Returns the name of the currently connected host. */ - const String& getHostName() const throw() { return hostName; } - - /** Returns the port number that's currently open. */ - int getPort() const throw() { return portNumber; } - - /** True if the socket is connected to this machine rather than over the network. */ - bool isLocal() const throw(); - - /** Waits until the socket is ready for reading or writing. - - If readyForReading is true, it will wait until the socket is ready for - reading; if false, it will wait until it's ready for writing. - - If the timeout is < 0, it will wait forever, or else will give up after - the specified time. - - If the socket is ready on return, this returns 1. If it times-out before - the socket becomes ready, it returns 0. If an error occurs, it returns -1. - */ - int waitUntilReady (const bool readyForReading, - const int timeoutMsecs) const; - - /** Reads bytes from the socket. - - If blockUntilSpecifiedAmountHasArrived is true, the method will block until - maxBytesToRead bytes have been read, (or until an error occurs). If this - flag is false, the method will return as much data as is currently available - without blocking. - - @returns the number of bytes read, or -1 if there was an error. - @see waitUntilReady - */ - int read (void* destBuffer, const int maxBytesToRead, - const bool blockUntilSpecifiedAmountHasArrived); - - /** Writes bytes to the socket from a buffer. - - Note that this method will block unless you have checked the socket is ready - for writing before calling it (see the waitUntilReady() method). - - @returns the number of bytes written, or -1 if there was an error. - */ - int write (const void* sourceBuffer, const int numBytesToWrite); - - /** This waits for incoming data to be sent, and returns a socket that can be used - to read it. - - The object that gets returned is owned by the caller, and can't be used for - sending, but can be used to read the data. - */ - DatagramSocket* waitForNextConnection() const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String hostName; - int volatile portNumber, handle; - bool connected, allowBroadcast; - void* serverAddress; + String hostName; + int volatile portNumber, handle; + bool connected, allowBroadcast; + void* serverAddress; - DatagramSocket (const String& hostname, const int portNumber, const int handle, const int localPortNumber); - DatagramSocket (const DatagramSocket&); - const DatagramSocket& operator= (const DatagramSocket&); + DatagramSocket (const String& hostname, const int portNumber, const int handle, const int localPortNumber); + DatagramSocket (const DatagramSocket&); + const DatagramSocket& operator= (const DatagramSocket&); }; #endif // __JUCE_SOCKET_JUCEHEADER__ @@ -14998,252 +7810,80 @@ private: #ifndef __JUCE_URL_JUCEHEADER__ #define __JUCE_URL_JUCEHEADER__ -/** - Represents a URL and has a bunch of useful functions to manipulate it. - - This class can be used to launch URLs in browsers, and also to create - InputStreams that can read from remote http or ftp sources. -*/ class JUCE_API URL { public: - /** Creates an empty URL. */ - URL(); + URL(); - /** Creates a URL from a string. */ - URL (const String& url); + URL (const String& url); - /** Creates a copy of another URL. */ - URL (const URL& other); + URL (const URL& other); - /** Destructor. */ - ~URL(); + ~URL(); - /** Copies this URL from another one. */ - const URL& operator= (const URL& other); + const URL& operator= (const URL& other); - /** Returns a string version of the URL. + const String toString (const bool includeGetParameters) const; - If includeGetParameters is true and any parameters have been set with the - withParameter() method, then the string will have these appended on the - end and url-encoded. - */ - const String toString (const bool includeGetParameters) const; + bool isWellFormed() const; - /** True if it seems to be valid. */ - bool isWellFormed() const; + const String getDomain() const; - /** Returns just the domain part of the URL. + const String getSubPath() const; - E.g. for "http://www.xyz.com/foobar", this will return "www.xyz.com". - */ - const String getDomain() const; + const String getScheme() const; - /** Returns the path part of the URL. + const URL withNewSubPath (const String& newPath) const; - E.g. for "http://www.xyz.com/foo/bar?x=1", this will return "foo/bar". - */ - const String getSubPath() const; + const URL withParameter (const String& parameterName, + const String& parameterValue) const; - /** Returns the scheme of the URL. + const URL withFileToUpload (const String& parameterName, + const File& fileToUpload, + const String& mimeType) const; - E.g. for "http://www.xyz.com/foobar", this will return "http". (It won't - include the colon). - */ - const String getScheme() const; + const StringPairArray& getParameters() const; - /** Returns a new version of this URL that uses a different sub-path. + const StringPairArray& getFilesToUpload() const; - E.g. if the URL is "http://www.xyz.com/foo?x=1" and you call this with - "bar", it'll return "http://www.xyz.com/bar?x=1". - */ - const URL withNewSubPath (const String& newPath) const; + const StringPairArray& getMimeTypesOfUploadFiles() const; - /** Returns a copy of this URL, with a GET parameter added to the end. + const URL withPOSTData (const String& postData) const; - Any control characters in the value will be encoded. + const String getPostData() const { return postData; } - e.g. calling "withParameter ("amount", "some fish") for the url "www.fish.com" - would produce a new url whose toString(true) method would return - "www.fish.com?amount=some+fish". - */ - const URL withParameter (const String& parameterName, - const String& parameterValue) const; + bool launchInDefaultBrowser() const; - /** Returns a copy of this URl, with a file-upload type parameter added to it. + static bool isProbablyAWebsiteURL (const String& possibleURL); - When performing a POST where one of your parameters is a binary file, this - lets you specify the file. + static bool isProbablyAnEmailAddress (const String& possibleEmailAddress); - Note that the filename is stored, but the file itself won't actually be read - until this URL is later used to create a network input stream. - */ - const URL withFileToUpload (const String& parameterName, - const File& fileToUpload, - const String& mimeType) const; + typedef bool (OpenStreamProgressCallback) (void* context, int bytesSent, int totalBytes); - /** Returns a set of all the parameters encoded into the url. + InputStream* createInputStream (const bool usePostCommand, + OpenStreamProgressCallback* const progressCallback = 0, + void* const progressCallbackContext = 0, + const String& extraHeaders = String::empty, + const int connectionTimeOutMs = 0) const; - E.g. for the url "www.fish.com?type=haddock&amount=some+fish", this array would - contain two pairs: "type" => "haddock" and "amount" => "some fish". + bool readEntireBinaryStream (MemoryBlock& destData, + const bool usePostCommand = false) const; - The values returned will have been cleaned up to remove any escape characters. + const String readEntireTextStream (const bool usePostCommand = false) const; - @see getNamedParameter, withParameter - */ - const StringPairArray& getParameters() const; + XmlElement* readEntireXmlStream (const bool usePostCommand = false) const; - /** Returns the set of files that should be uploaded as part of a POST operation. + static const String addEscapeChars (const String& stringToAddEscapeCharsTo, + const bool isParameter); - This is the set of files that were added to the URL with the withFileToUpload() - method. - */ - const StringPairArray& getFilesToUpload() const; + static const String removeEscapeChars (const String& stringToRemoveEscapeCharsFrom); - /** Returns the set of mime types associated with each of the upload files. - */ - const StringPairArray& getMimeTypesOfUploadFiles() const; - - /** Returns a copy of this URL, with a block of data to send as the POST data. - - If you're setting the POST data, be careful not to have any parameters set - as well, otherwise it'll all get thrown in together, and might not have the - desired effect. - - If the URL already contains some POST data, this will replace it, rather - than being appended to it. - - This data will only be used if you specify a post operation when you call - createInputStream(). - */ - const URL withPOSTData (const String& postData) const; - - /** Returns the data that was set using withPOSTData(). - */ - const String getPostData() const { return postData; } - - /** Tries to launch the system's default browser to open the URL. - - Returns true if this seems to have worked. - */ - bool launchInDefaultBrowser() const; - - /** Takes a guess as to whether a string might be a valid website address. - - This isn't foolproof! - */ - static bool isProbablyAWebsiteURL (const String& possibleURL); - - /** Takes a guess as to whether a string might be a valid email address. - - This isn't foolproof! - */ - static bool isProbablyAnEmailAddress (const String& possibleEmailAddress); - - /** This callback function can be used by the createInputStream() method. - - It allows your app to receive progress updates during a lengthy POST operation. If you - want to continue the operation, this should return true, or false to abort. - */ - typedef bool (OpenStreamProgressCallback) (void* context, int bytesSent, int totalBytes); - - /** Attempts to open a stream that can read from this URL. - - @param usePostCommand if true, it will try to do use a http 'POST' to pass - the paramters, otherwise it'll encode them into the - URL and do a 'GET'. - @param progressCallback if this is non-zero, it lets you supply a callback function - to keep track of the operation's progress. This can be useful - for lengthy POST operations, so that you can provide user feedback. - @param progressCallbackContext if a callback is specified, this value will be passed to - the function - @param extraHeaders if not empty, this string is appended onto the headers that - are used for the request. It must therefore be a valid set of HTML - header directives, separated by newlines. - @param connectionTimeOutMs if 0, this will use whatever default setting the OS chooses. If - a negative number, it will be infinite. Otherwise it specifies a - time in milliseconds. - */ - InputStream* createInputStream (const bool usePostCommand, - OpenStreamProgressCallback* const progressCallback = 0, - void* const progressCallbackContext = 0, - const String& extraHeaders = String::empty, - const int connectionTimeOutMs = 0) const; - - /** Tries to download the entire contents of this URL into a binary data block. - - If it succeeds, this will return true and append the data it read onto the end - of the memory block. - - @param destData the memory block to append the new data to - @param usePostCommand whether to use a POST command to get the data (uses - a GET command if this is false) - @see readEntireTextStream, readEntireXmlStream - */ - bool readEntireBinaryStream (MemoryBlock& destData, - const bool usePostCommand = false) const; - - /** Tries to download the entire contents of this URL as a string. - - If it fails, this will return an empty string, otherwise it will return the - contents of the downloaded file. If you need to distinguish between a read - operation that fails and one that returns an empty string, you'll need to use - a different method, such as readEntireBinaryStream(). - - @param usePostCommand whether to use a POST command to get the data (uses - a GET command if this is false) - @see readEntireBinaryStream, readEntireXmlStream - */ - const String readEntireTextStream (const bool usePostCommand = false) const; - - /** Tries to download the entire contents of this URL and parse it as XML. - - If it fails, or if the text that it reads can't be parsed as XML, this will - return 0. - - When it returns a valid XmlElement object, the caller is responsibile for deleting - this object when no longer needed. - - @param usePostCommand whether to use a POST command to get the data (uses - a GET command if this is false) - - @see readEntireBinaryStream, readEntireTextStream - */ - XmlElement* readEntireXmlStream (const bool usePostCommand = false) const; - - /** Adds escape sequences to a string to encode any characters that aren't - legal in a URL. - - E.g. any spaces will be replaced with "%20". - - This is the opposite of removeEscapeChars(). - - If isParameter is true, it means that the string is going to be used - as a parameter, so it also encodes '$' and ',' (which would otherwise - be legal in a URL. - - @see removeEscapeChars - */ - static const String addEscapeChars (const String& stringToAddEscapeCharsTo, - const bool isParameter); - - /** Replaces any escape character sequences in a string with their original - character codes. - - E.g. any instances of "%20" will be replaced by a space. - - This is the opposite of addEscapeChars(). - - @see addEscapeChars - */ - static const String removeEscapeChars (const String& stringToRemoveEscapeCharsFrom); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String url, postData; - StringPairArray parameters, filesToUpload, mimeTypes; + String url, postData; + StringPairArray parameters, filesToUpload, mimeTypes; }; #endif // __JUCE_URL_JUCEHEADER__ @@ -15256,54 +7896,35 @@ private: #ifndef __JUCE_BUFFEREDINPUTSTREAM_JUCEHEADER__ #define __JUCE_BUFFEREDINPUTSTREAM_JUCEHEADER__ -/** Wraps another input stream, and reads from it using an intermediate buffer - - If you're using an input stream such as a file input stream, and making lots of - small read accesses to it, it's probably sensible to wrap it in one of these, - so that the source stream gets accessed in larger chunk sizes, meaning less - work for the underlying stream. -*/ class JUCE_API BufferedInputStream : public InputStream { public: - /** Creates a BufferedInputStream from an input source. + BufferedInputStream (InputStream* const sourceStream, + const int bufferSize, + const bool deleteSourceWhenDestroyed); - @param sourceStream the source stream to read from - @param bufferSize the size of reservoir to use to buffer the source - @param deleteSourceWhenDestroyed whether the sourceStream that is passed in should be - deleted by this object when it is itself deleted. - */ - BufferedInputStream (InputStream* const sourceStream, - const int bufferSize, - const bool deleteSourceWhenDestroyed); + ~BufferedInputStream(); - /** Destructor. + int64 getTotalLength(); + int64 getPosition(); + bool setPosition (int64 newPosition); + int read (void* destBuffer, int maxBytesToRead); + const String readString(); + bool isExhausted(); - This may also delete the source stream, if that option was chosen when the - buffered stream was created. - */ - ~BufferedInputStream(); - - int64 getTotalLength(); - int64 getPosition(); - bool setPosition (int64 newPosition); - int read (void* destBuffer, int maxBytesToRead); - const String readString(); - bool isExhausted(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - InputStream* const source; - ScopedPointer sourceToDelete; - int bufferSize; - int64 position, lastReadPos, bufferStart, bufferOverlap; - HeapBlock buffer; - void ensureBuffered(); + InputStream* const source; + ScopedPointer sourceToDelete; + int bufferSize; + int64 position, lastReadPos, bufferStart, bufferOverlap; + HeapBlock buffer; + void ensureBuffered(); - BufferedInputStream (const BufferedInputStream&); - const BufferedInputStream& operator= (const BufferedInputStream&); + BufferedInputStream (const BufferedInputStream&); + const BufferedInputStream& operator= (const BufferedInputStream&); }; #endif // __JUCE_BUFFEREDINPUTSTREAM_JUCEHEADER__ @@ -15316,29 +7937,24 @@ private: #ifndef __JUCE_FILEINPUTSOURCE_JUCEHEADER__ #define __JUCE_FILEINPUTSOURCE_JUCEHEADER__ -/** - A type of InputSource that represents a normal file. - - @see InputSource -*/ -class JUCE_API FileInputSource : public InputSource +class JUCE_API FileInputSource : public InputSource { public: - FileInputSource (const File& file); - ~FileInputSource(); + FileInputSource (const File& file); + ~FileInputSource(); - InputStream* createInputStream(); - InputStream* createInputStreamFor (const String& relatedItemPath); - int64 hashCode() const; + InputStream* createInputStream(); + InputStream* createInputStreamFor (const String& relatedItemPath); + int64 hashCode() const; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - const File file; + const File file; - FileInputSource (const FileInputSource&); - const FileInputSource& operator= (const FileInputSource&); + FileInputSource (const FileInputSource&); + const FileInputSource& operator= (const FileInputSource&); }; #endif // __JUCE_FILEINPUTSOURCE_JUCEHEADER__ @@ -15353,52 +7969,33 @@ private: class GZIPCompressorHelper; -/** - A stream which uses zlib to compress the data written into it. - - @see GZIPDecompressorInputStream -*/ class JUCE_API GZIPCompressorOutputStream : public OutputStream { public: - /** Creates a compression stream. + GZIPCompressorOutputStream (OutputStream* const destStream, + int compressionLevel = 0, + const bool deleteDestStreamWhenDestroyed = false, + const bool noWrap = false); - @param destStream the stream into which the compressed data should - be written - @param compressionLevel how much to compress the data, between 1 and 9, where - 1 is the fastest/lowest compression, and 9 is the - slowest/highest compression. Any value outside this range - indicates that a default compression level should be used. - @param deleteDestStreamWhenDestroyed whether or not to delete the destStream object when - this stream is destroyed - @param noWrap this is used internally by the ZipFile class - and should be ignored by user applications - */ - GZIPCompressorOutputStream (OutputStream* const destStream, - int compressionLevel = 0, - const bool deleteDestStreamWhenDestroyed = false, - const bool noWrap = false); + ~GZIPCompressorOutputStream(); - /** Destructor. */ - ~GZIPCompressorOutputStream(); + void flush(); + int64 getPosition(); + bool setPosition (int64 newPosition); + bool write (const void* destBuffer, int howMany); - void flush(); - int64 getPosition(); - bool setPosition (int64 newPosition); - bool write (const void* destBuffer, int howMany); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OutputStream* const destStream; - ScopedPointer streamToDelete; - HeapBlock buffer; - ScopedPointer helper; - bool doNextBlock(); + OutputStream* const destStream; + ScopedPointer streamToDelete; + HeapBlock buffer; + ScopedPointer helper; + bool doNextBlock(); - GZIPCompressorOutputStream (const GZIPCompressorOutputStream&); - const GZIPCompressorOutputStream& operator= (const GZIPCompressorOutputStream&); + GZIPCompressorOutputStream (const GZIPCompressorOutputStream&); + const GZIPCompressorOutputStream& operator= (const GZIPCompressorOutputStream&); }; #endif // __JUCE_GZIPCOMPRESSOROUTPUTSTREAM_JUCEHEADER__ @@ -15413,59 +8010,38 @@ private: class GZIPDecompressHelper; -/** - This stream will decompress a source-stream using zlib. - - Tip: if you're reading lots of small items from one of these streams, you - can increase the performance enormously by passing it through a - BufferedInputStream, so that it has to read larger blocks less often. - - @see GZIPCompressorOutputStream -*/ class JUCE_API GZIPDecompressorInputStream : public InputStream { public: - /** Creates a decompressor stream. + GZIPDecompressorInputStream (InputStream* const sourceStream, + const bool deleteSourceWhenDestroyed, + const bool noWrap = false, + const int64 uncompressedStreamLength = -1); - @param sourceStream the stream to read from - @param deleteSourceWhenDestroyed whether or not to delete the source stream - when this object is destroyed - @param noWrap this is used internally by the ZipFile class - and should be ignored by user applications - @param uncompressedStreamLength if the creator knows the length that the - uncompressed stream will be, then it can supply this - value, which will be returned by getTotalLength() - */ - GZIPDecompressorInputStream (InputStream* const sourceStream, - const bool deleteSourceWhenDestroyed, - const bool noWrap = false, - const int64 uncompressedStreamLength = -1); + ~GZIPDecompressorInputStream(); - /** Destructor. */ - ~GZIPDecompressorInputStream(); + int64 getPosition(); + bool setPosition (int64 pos); + int64 getTotalLength(); + bool isExhausted(); + int read (void* destBuffer, int maxBytesToRead); - int64 getPosition(); - bool setPosition (int64 pos); - int64 getTotalLength(); - bool isExhausted(); - int read (void* destBuffer, int maxBytesToRead); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - InputStream* const sourceStream; - ScopedPointer streamToDelete; - const int64 uncompressedStreamLength; - const bool noWrap; - bool isEof; - int activeBufferSize; - int64 originalSourcePos, currentPos; - HeapBlock buffer; - ScopedPointer helper; + InputStream* const sourceStream; + ScopedPointer streamToDelete; + const int64 uncompressedStreamLength; + const bool noWrap; + bool isEof; + int activeBufferSize; + int64 originalSourcePos, currentPos; + HeapBlock buffer; + ScopedPointer helper; - GZIPDecompressorInputStream (const GZIPDecompressorInputStream&); - const GZIPDecompressorInputStream& operator= (const GZIPDecompressorInputStream&); + GZIPDecompressorInputStream (const GZIPDecompressorInputStream&); + const GZIPDecompressorInputStream& operator= (const GZIPDecompressorInputStream&); }; #endif // __JUCE_GZIPDECOMPRESSORINPUTSTREAM_JUCEHEADER__ @@ -15484,45 +8060,28 @@ private: #ifndef __JUCE_MEMORYINPUTSTREAM_JUCEHEADER__ #define __JUCE_MEMORYINPUTSTREAM_JUCEHEADER__ -/** - Allows a block of data and to be accessed as a stream. - - This can either be used to refer to a shared block of memory, or can make its - own internal copy of the data when the MemoryInputStream is created. -*/ class JUCE_API MemoryInputStream : public InputStream { public: - /** Creates a MemoryInputStream. + MemoryInputStream (const void* const sourceData, + const size_t sourceDataSize, + const bool keepInternalCopyOfData); - @param sourceData the block of data to use as the stream's source - @param sourceDataSize the number of bytes in the source data block - @param keepInternalCopyOfData if false, the stream will just keep a pointer to - the source data, so this data shouldn't be changed - for the lifetime of the stream; if this parameter is - true, the stream will make its own copy of the - data and use that. - */ - MemoryInputStream (const void* const sourceData, - const int sourceDataSize, - const bool keepInternalCopyOfData); + ~MemoryInputStream(); - /** Destructor. */ - ~MemoryInputStream(); + int64 getPosition(); + bool setPosition (int64 pos); + int64 getTotalLength(); + bool isExhausted(); + int read (void* destBuffer, int maxBytesToRead); - int64 getPosition(); - bool setPosition (int64 pos); - int64 getTotalLength(); - bool isExhausted(); - int read (void* destBuffer, int maxBytesToRead); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - const char* data; - int dataSize, position; - MemoryBlock internalCopy; + const char* data; + size_t dataSize, position; + MemoryBlock internalCopy; }; #endif // __JUCE_MEMORYINPUTSTREAM_JUCEHEADER__ @@ -15535,60 +8094,33 @@ private: #ifndef __JUCE_MEMORYOUTPUTSTREAM_JUCEHEADER__ #define __JUCE_MEMORYOUTPUTSTREAM_JUCEHEADER__ -/** Writes data to an internal memory buffer, which grows as required. - - The data that was written into the stream can then be accessed later as - a contiguous block of memory. -*/ class JUCE_API MemoryOutputStream : public OutputStream { public: - /** Creates a memory stream ready for writing into. + MemoryOutputStream (const size_t initialSize = 256, + const size_t granularity = 256, + MemoryBlock* const memoryBlockToWriteTo = 0) throw(); - @param initialSize the intial amount of space to allocate for writing into - @param granularity the increments by which the internal storage will be increased - @param memoryBlockToWriteTo if this is non-zero, then this block will be used as the - place that the data gets stored. If it's zero, the stream - will allocate its own storage internally, which you can - access using getData() and getDataSize() - */ - MemoryOutputStream (const int initialSize = 256, - const int granularity = 256, - MemoryBlock* const memoryBlockToWriteTo = 0) throw(); + ~MemoryOutputStream() throw(); - /** Destructor. + const char* getData() throw(); - This will free any data that was written to it. - */ - ~MemoryOutputStream() throw(); + size_t getDataSize() const throw(); - /** Returns a pointer to the data that has been written to the stream. + void reset() throw(); - @see getDataSize - */ - const char* getData() throw(); + void flush(); + bool write (const void* buffer, int howMany); + int64 getPosition(); + bool setPosition (int64 newPosition); - /** Returns the number of bytes of data that have been written to the stream. - - @see getData - */ - int getDataSize() const throw(); - - /** Resets the stream, clearing any data that has been written to it so far. */ - void reset() throw(); - - void flush(); - bool write (const void* buffer, int howMany); - int64 getPosition(); - bool setPosition (int64 newPosition); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - MemoryBlock* data; - ScopedPointer dataToDelete; - int position, size, blockSize; + MemoryBlock* data; + ScopedPointer dataToDelete; + size_t position, size, blockSize; }; #endif // __JUCE_MEMORYOUTPUTSTREAM_JUCEHEADER__ @@ -15604,59 +8136,32 @@ private: #ifndef __JUCE_SUBREGIONSTREAM_JUCEHEADER__ #define __JUCE_SUBREGIONSTREAM_JUCEHEADER__ -/** Wraps another input stream, and reads from a specific part of it. - - This lets you take a subsection of a stream and present it as an entire - stream in its own right. -*/ class JUCE_API SubregionStream : public InputStream { public: - /** Creates a SubregionStream from an input source. + SubregionStream (InputStream* const sourceStream, + const int64 startPositionInSourceStream, + const int64 lengthOfSourceStream, + const bool deleteSourceWhenDestroyed) throw(); - @param sourceStream the source stream to read from - @param startPositionInSourceStream this is the position in the source stream that - corresponds to position 0 in this stream - @param lengthOfSourceStream this specifies the maximum number of bytes - from the source stream that will be passed through - by this stream. When the position of this stream - exceeds lengthOfSourceStream, it will cause an end-of-stream. - If the length passed in here is greater than the length - of the source stream (as returned by getTotalLength()), - then the smaller value will be used. - Passing a negative value for this parameter means it - will keep reading until the source's end-of-stream. - @param deleteSourceWhenDestroyed whether the sourceStream that is passed in should be - deleted by this object when it is itself deleted. - */ - SubregionStream (InputStream* const sourceStream, - const int64 startPositionInSourceStream, - const int64 lengthOfSourceStream, - const bool deleteSourceWhenDestroyed) throw(); + ~SubregionStream() throw(); - /** Destructor. + int64 getTotalLength(); + int64 getPosition(); + bool setPosition (int64 newPosition); + int read (void* destBuffer, int maxBytesToRead); + bool isExhausted(); - This may also delete the source stream, if that option was chosen when the - buffered stream was created. - */ - ~SubregionStream() throw(); - - int64 getTotalLength(); - int64 getPosition(); - bool setPosition (int64 newPosition); - int read (void* destBuffer, int maxBytesToRead); - bool isExhausted(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - InputStream* const source; - ScopedPointer sourceToDelete; - const int64 startPositionInSourceStream, lengthOfSourceStream; + InputStream* const source; + ScopedPointer sourceToDelete; + const int64 startPositionInSourceStream, lengthOfSourceStream; - SubregionStream (const SubregionStream&); - const SubregionStream& operator= (const SubregionStream&); + SubregionStream (const SubregionStream&); + const SubregionStream& operator= (const SubregionStream&); }; #endif // __JUCE_SUBREGIONSTREAM_JUCEHEADER__ @@ -15672,157 +8177,43 @@ private: #ifndef __JUCE_LOCALISEDSTRINGS_JUCEHEADER__ #define __JUCE_LOCALISEDSTRINGS_JUCEHEADER__ -/** Used in the same way as the T(text) macro, this will attempt to translate a - string into a localised version using the LocalisedStrings class. +#define TRANS(stringLiteral) \ + LocalisedStrings::translateWithCurrentMappings (stringLiteral) - @see LocalisedStrings -*/ -#define TRANS(stringLiteral) \ - LocalisedStrings::translateWithCurrentMappings (stringLiteral) - -/** - Used to convert strings to localised foreign-language versions. - - This is basically a look-up table of strings and their translated equivalents. - It can be loaded from a text file, so that you can supply a set of localised - versions of strings that you use in your app. - - To use it in your code, simply call the translate() method on each string that - might have foreign versions, and if none is found, the method will just return - the original string. - - The translation file should start with some lines specifying a description of - the language it contains, and also a list of ISO country codes where it might - be appropriate to use the file. After that, each line of the file should contain - a pair of quoted strings with an '=' sign. - - E.g. for a french translation, the file might be: - - @code - language: French - countries: fr be mc ch lu - - "hello" = "bonjour" - "goodbye" = "au revoir" - @endcode - - If the strings need to contain a quote character, they can use '\"' instead, and - if the first non-whitespace character on a line isn't a quote, then it's ignored, - (you can use this to add comments). - - Note that this is a singleton class, so don't create or destroy the object directly. - There's also a TRANS(text) macro defined to make it easy to use the this. - - E.g. @code - printSomething (TRANS("hello")); - @endcode - - This macro is used in the Juce classes themselves, so your application has a chance to - intercept and translate any internal Juce text strings that might be shown. (You can easily - get a list of all the messages by searching for the TRANS() macro in the Juce source - code). -*/ class JUCE_API LocalisedStrings { public: - /** Creates a set of translations from the text of a translation file. + LocalisedStrings (const String& fileContents); - When you create one of these, you can call setCurrentMappings() to make it - the set of mappings that the system's using. - */ - LocalisedStrings (const String& fileContents); + LocalisedStrings (const File& fileToLoad); - /** Creates a set of translations from a file. + ~LocalisedStrings(); - When you create one of these, you can call setCurrentMappings() to make it - the set of mappings that the system's using. - */ - LocalisedStrings (const File& fileToLoad); + static void setCurrentMappings (LocalisedStrings* newTranslations); - /** Destructor. */ - ~LocalisedStrings(); + static LocalisedStrings* getCurrentMappings(); - /** Selects the current set of mappings to be used by the system. + static const String translateWithCurrentMappings (const String& text); - The object you pass in will be automatically deleted when no longer needed, so - don't keep a pointer to it. You can also pass in zero to remove the current - mappings. + static const String translateWithCurrentMappings (const char* text); - See also the TRANS() macro, which uses the current set to do its translation. + const String translate (const String& text) const; - @see translateWithCurrentMappings - */ - static void setCurrentMappings (LocalisedStrings* newTranslations); + const String getLanguageName() const { return languageName; } - /** Returns the currently selected set of mappings. + const StringArray getCountryCodes() const { return countryCodes; } - This is the object that was last passed to setCurrentMappings(). It may - be 0 if none has been created. - */ - static LocalisedStrings* getCurrentMappings(); + void setIgnoresCase (const bool shouldIgnoreCase); - /** Tries to translate a string using the currently selected set of mappings. - - If no mapping has been set, or if the mapping doesn't contain a translation - for the string, this will just return the original string. - - See also the TRANS() macro, which uses this method to do its translation. - - @see setCurrentMappings, getCurrentMappings - */ - static const String translateWithCurrentMappings (const String& text); - - /** Tries to translate a string using the currently selected set of mappings. - - If no mapping has been set, or if the mapping doesn't contain a translation - for the string, this will just return the original string. - - See also the TRANS() macro, which uses this method to do its translation. - - @see setCurrentMappings, getCurrentMappings - */ - static const String translateWithCurrentMappings (const char* text); - - /** Attempts to look up a string and return its localised version. - - If the string isn't found in the list, the original string will be returned. - */ - const String translate (const String& text) const; - - /** Returns the name of the language specified in the translation file. - - This is specified in the file using a line starting with "language:", e.g. - @code - language: german - @endcode - */ - const String getLanguageName() const { return languageName; } - - /** Returns the list of suitable country codes listed in the translation file. - - These is specified in the file using a line starting with "countries:", e.g. - @code - countries: fr be mc ch lu - @endcode - - The country codes are supposed to be 2-character ISO complient codes. - */ - const StringArray getCountryCodes() const { return countryCodes; } - - /** Indicates whether to use a case-insensitive search when looking up a string. - This defaults to true. - */ - void setIgnoresCase (const bool shouldIgnoreCase); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String languageName; - StringArray countryCodes; - StringPairArray translations; + String languageName; + StringArray countryCodes; + StringPairArray translations; - void loadFromText (const String& fileContents); + void loadFromText (const String& fileContents); }; #endif // __JUCE_LOCALISEDSTRINGS_JUCEHEADER__ @@ -15844,127 +8235,53 @@ private: #ifndef __JUCE_XMLDOCUMENT_JUCEHEADER__ #define __JUCE_XMLDOCUMENT_JUCEHEADER__ -/** - Parses a text-based XML document and creates an XmlElement object from it. - - The parser will parse DTDs to load external entities but won't - check the document for validity against the DTD. - - e.g. - @code - - XmlDocument myDocument (File ("myfile.xml")); - XmlElement* mainElement = myDocument.getDocumentElement(); - - if (mainElement == 0) - { - String error = myDocument.getLastParseError(); - } - else - { - ..use the element - } - - @endcode - - @see XmlElement -*/ class JUCE_API XmlDocument { public: - /** Creates an XmlDocument from the xml text. + XmlDocument (const String& documentText) throw(); - The text doesn't actually get parsed until the getDocumentElement() method is - called. - */ - XmlDocument (const String& documentText) throw(); + XmlDocument (const File& file); - /** Creates an XmlDocument from a file. + ~XmlDocument() throw(); - The text doesn't actually get parsed until the getDocumentElement() method is - called. - */ - XmlDocument (const File& file); + XmlElement* getDocumentElement (const bool onlyReadOuterDocumentElement = false); - /** Destructor. */ - ~XmlDocument() throw(); + const String& getLastParseError() const throw(); - /** Creates an XmlElement object to represent the main document node. + void setInputSource (InputSource* const newSource) throw(); - This method will do the actual parsing of the text, and if there's a - parse error, it may returns 0 (and you can find out the error using - the getLastParseError() method). + void setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw(); - @param onlyReadOuterDocumentElement if true, the parser will only read the - first section of the file, and will only - return the outer document element - this - allows quick checking of large files to - see if they contain the correct type of - tag, without having to parse the entire file - @returns a new XmlElement which the caller will need to delete, or null if - there was an error. - @see getLastParseError - */ - XmlElement* getDocumentElement (const bool onlyReadOuterDocumentElement = false); - - /** Returns the parsing error that occurred the last time getDocumentElement was called. - - @returns the error, or an empty string if there was no error. - */ - const String& getLastParseError() const throw(); - - /** Sets an input source object to use for parsing documents that reference external entities. - - If the document has been created from a file, this probably won't be needed, but - if you're parsing some text and there might be a DTD that references external - files, you may need to create a custom input source that can retrieve the - other files it needs. - - The object that is passed-in will be deleted automatically when no longer needed. - - @see InputSource - */ - void setInputSource (InputSource* const newSource) throw(); - - /** Sets a flag to change the treatment of empty text elements. - - If this is true (the default state), then any text elements that contain only - whitespace characters will be ingored during parsing. If you need to catch - whitespace-only text, then you should set this to false before calling the - getDocumentElement() method. - */ - void setEmptyTextElementsIgnored (const bool shouldBeIgnored) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String originalText; - const tchar* input; - bool outOfData, errorOccurred; + String originalText; + const tchar* input; + bool outOfData, errorOccurred; - bool identifierLookupTable [128]; - String lastError, dtdText; - StringArray tokenisedDTD; - bool needToLoadDTD, ignoreEmptyTextElements; - ScopedPointer inputSource; + bool identifierLookupTable [128]; + String lastError, dtdText; + StringArray tokenisedDTD; + bool needToLoadDTD, ignoreEmptyTextElements; + ScopedPointer inputSource; - void setLastError (const String& desc, const bool carryOn) throw(); - void skipHeader() throw(); - void skipNextWhiteSpace() throw(); - tchar readNextChar() throw(); - XmlElement* readNextElement (const bool alsoParseSubElements) throw(); - void readChildElements (XmlElement* parent) throw(); - int findNextTokenLength() throw(); - void readQuotedString (String& result) throw(); - void readEntity (String& result) throw(); - static bool isXmlIdentifierCharSlow (const tchar c) throw(); - bool isXmlIdentifierChar (const tchar c) const throw(); + void setLastError (const String& desc, const bool carryOn) throw(); + void skipHeader() throw(); + void skipNextWhiteSpace() throw(); + tchar readNextChar() throw(); + XmlElement* readNextElement (const bool alsoParseSubElements) throw(); + void readChildElements (XmlElement* parent) throw(); + int findNextTokenLength() throw(); + void readQuotedString (String& result) throw(); + void readEntity (String& result) throw(); + static bool isXmlIdentifierCharSlow (const tchar c) throw(); + bool isXmlIdentifierChar (const tchar c) const throw(); - const String getFileContents (const String& filename) const; - const String expandEntity (const String& entity); - const String expandExternalEntity (const String& entity); - const String getParameterEntity (const String& entity); + const String getFileContents (const String& filename) const; + const String expandEntity (const String& entity); + const String expandExternalEntity (const String& entity); + const String getParameterEntity (const String& entity); }; #endif // __JUCE_XMLDOCUMENT_JUCEHEADER__ @@ -15983,52 +8300,35 @@ private: #ifndef __JUCE_INTERPROCESSLOCK_JUCEHEADER__ #define __JUCE_INTERPROCESSLOCK_JUCEHEADER__ -/** - Acts as a critical section which processes can use to block each other. - - @see CriticalSection -*/ class JUCE_API InterProcessLock { public: - /** Creates a lock object. + InterProcessLock (const String& name); - @param name a name that processes will use to identify this lock object - */ - InterProcessLock (const String& name); + ~InterProcessLock(); - /** Destructor. + bool enter (int timeOutMillisecs = -1); - This will also release the lock if it's currently held by this process. - */ - ~InterProcessLock(); + void exit(); - /** Attempts to lock the critical section. - - @param timeOutMillisecs how many milliseconds to wait if the lock - is already held by another process - a value of - 0 will return immediately, negative values will wait - forever - @returns true if the lock could be gained within the timeout period, or - false if the timeout expired. - */ - bool enter (int timeOutMillisecs = -1); - - /** Releases the lock if it's currently held by this process. - */ - void exit(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - void* internal; - String name; - int reentrancyLevel; + #if JUCE_WINDOWS + void* internal; +// #elif JUCE_64BIT + // long long internal; + #else + int internal; + #endif - InterProcessLock (const InterProcessLock&); - const InterProcessLock& operator= (const InterProcessLock&); + String name; + int reentrancyLevel; + + InterProcessLock (const InterProcessLock&); + const InterProcessLock& operator= (const InterProcessLock&); }; #endif // __JUCE_INTERPROCESSLOCK_JUCEHEADER__ @@ -16041,64 +8341,29 @@ private: #ifndef __JUCE_PROCESS_JUCEHEADER__ #define __JUCE_PROCESS_JUCEHEADER__ -/** Represents the current executable's process. - - This contains methods for controlling the current application at the - process-level. - - @see Thread, JUCEApplication -*/ class JUCE_API Process { public: - enum ProcessPriority - { - LowPriority = 0, - NormalPriority = 1, - HighPriority = 2, - RealtimePriority = 3 - }; + enum ProcessPriority + { + LowPriority = 0, + NormalPriority = 1, + HighPriority = 2, + RealtimePriority = 3 + }; - /** Changes the current process's priority. + static void setPriority (const ProcessPriority priority); - @param priority the process priority, where - 0=low, 1=normal, 2=high, 3=realtime - */ - static void setPriority (const ProcessPriority priority); + static void terminate(); - /** Kills the current process immediately. + static bool isForegroundProcess(); - This is an emergency process terminator that kills the application - immediately - it's intended only for use only when something goes - horribly wrong. + static void raisePrivilege(); - @see JUCEApplication::quit - */ - static void terminate(); + static void lowerPrivilege(); - /** Returns true if this application process is the one that the user is - currently using. - */ - static bool isForegroundProcess(); - - /** Raises the current process's privilege level. - - Does nothing if this isn't supported by the current OS, or if process - privilege level is fixed. - */ - static void raisePrivilege(); - - /** Lowers the current process's privilege level. - - Does nothing if this isn't supported by the current OS, or if process - privilege level is fixed. - */ - static void lowerPrivilege(); - - /** Returns true if this process is being hosted by a debugger. - */ - static bool JUCE_CALLTYPE isRunningUnderDebugger(); + static bool JUCE_CALLTYPE isRunningUnderDebugger(); }; #endif // __JUCE_PROCESS_JUCEHEADER__ @@ -16115,65 +8380,27 @@ public: #ifndef __JUCE_WAITABLEEVENT_JUCEHEADER__ #define __JUCE_WAITABLEEVENT_JUCEHEADER__ -/** - Allows threads to wait for events triggered by other threads. - - A thread can call wait() on a WaitableObject, and this will suspend the - calling thread until another thread wakes it up by calling the signal() - method. -*/ class JUCE_API WaitableEvent { public: - /** Creates a WaitableEvent object. */ - WaitableEvent() throw(); + WaitableEvent() throw(); - /** Destructor. + ~WaitableEvent() throw(); - If other threads are waiting on this object when it gets deleted, this - can cause nasty errors, so be careful! - */ - ~WaitableEvent() throw(); + bool wait (const int timeOutMilliseconds = -1) const throw(); - /** Suspends the calling thread until the event has been signalled. + void signal() const throw(); - This will wait until the object's signal() method is called by another thread, - or until the timeout expires. + void reset() const throw(); - After the event has been signalled, this method will return true and reset - the event. - - @param timeOutMilliseconds the maximum time to wait, in milliseconds. A negative - value will cause it to wait forever. - - @returns true if the object has been signalled, false if the timeout expires first. - @see signal, reset - */ - bool wait (const int timeOutMilliseconds = -1) const throw(); - - /** Wakes up any threads that are currently waiting on this object. - - If signal() is called when nothing is waiting, the next thread to call wait() - will return immediately and reset the signal. - - @see wait, reset - */ - void signal() const throw(); - - /** Resets the event to an unsignalled state. - - If it's not already signalled, this does nothing. - */ - void reset() const throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - void* internal; + void* internal; - WaitableEvent (const WaitableEvent&); - const WaitableEvent& operator= (const WaitableEvent&); + WaitableEvent (const WaitableEvent&); + const WaitableEvent& operator= (const WaitableEvent&); }; #endif // __JUCE_WAITABLEEVENT_JUCEHEADER__ @@ -16183,351 +8410,116 @@ private: #ifndef __JUCE_THREAD_JUCEHEADER__ #define __JUCE_THREAD_JUCEHEADER__ -/** - Encapsulates a thread. - - Subclasses derive from Thread and implement the run() method, in which they - do their business. The thread can then be started with the startThread() method - and controlled with various other methods. - - This class also contains some thread-related static methods, such - as sleep(), yield(), getCurrentThreadId() etc. - - @see CriticalSection, WaitableEvent, Process, ThreadWithProgressWindow, - MessageManagerLock -*/ class JUCE_API Thread { public: - /** - Creates a thread. + Thread (const String& threadName); - When first created, the thread is not running. Use the startThread() - method to start it. - */ - Thread (const String& threadName); + virtual ~Thread(); - /** Destructor. + virtual void run() = 0; - Deleting a Thread object that is running will only give the thread a - brief opportunity to stop itself cleanly, so it's recommended that you - should always call stopThread() with a decent timeout before deleting, - to avoid the thread being forcibly killed (which is a Bad Thing). - */ - virtual ~Thread(); + // Thread control functions.. - /** Must be implemented to perform the thread's actual code. + void startThread(); - Remember that the thread must regularly check the threadShouldExit() - method whilst running, and if this returns true it should return from - the run() method as soon as possible to avoid being forcibly killed. + void startThread (const int priority); - @see threadShouldExit, startThread - */ - virtual void run() = 0; + void stopThread (const int timeOutMilliseconds); - // Thread control functions.. + bool isThreadRunning() const; - /** Starts the thread running. + void signalThreadShouldExit(); - This will start the thread's run() method. - (if it's already started, startThread() won't do anything). + inline bool threadShouldExit() const { return threadShouldExit_; } - @see stopThread - */ - void startThread(); + bool waitForThreadToExit (const int timeOutMilliseconds) const; - /** Starts the thread with a given priority. + bool setPriority (const int priority); - Launches the thread with a given priority, where 0 = lowest, 10 = highest. - If the thread is already running, its priority will be changed. + static bool setCurrentThreadPriority (const int priority); - @see startThread, setPriority - */ - void startThread (const int priority); + void setAffinityMask (const uint32 affinityMask); - /** Attempts to stop the thread running. + static void setCurrentThreadAffinityMask (const uint32 affinityMask); - This method will cause the threadShouldExit() method to return true - and call notify() in case the thread is currently waiting. + // this can be called from any thread that needs to pause.. + static void JUCE_CALLTYPE sleep (int milliseconds); - Hopefully the thread will then respond to this by exiting cleanly, and - the stopThread method will wait for a given time-period for this to - happen. + static void JUCE_CALLTYPE yield(); - If the thread is stuck and fails to respond after the time-out, it gets - forcibly killed, which is a very bad thing to happen, as it could still - be holding locks, etc. which are needed by other parts of your program. + bool wait (const int timeOutMilliseconds) const; - @param timeOutMilliseconds The number of milliseconds to wait for the - thread to finish before killing it by force. A negative - value in here will wait forever. - @see signalThreadShouldExit, threadShouldExit, waitForThreadToExit, isThreadRunning - */ - void stopThread (const int timeOutMilliseconds); + void notify() const; - /** Returns true if the thread is currently active */ - bool isThreadRunning() const; + typedef void* ThreadID; - /** Sets a flag to tell the thread it should stop. + static ThreadID getCurrentThreadId(); - Calling this means that the threadShouldExit() method will then return true. - The thread should be regularly checking this to see whether it should exit. + static Thread* getCurrentThread(); - @see threadShouldExit - @see waitForThreadToExit - */ - void signalThreadShouldExit(); + ThreadID getThreadId() const { return threadId_; } - /** Checks whether the thread has been told to stop running. + const String getThreadName() const { return threadName_; } - Threads need to check this regularly, and if it returns true, they should - return from their run() method at the first possible opportunity. + static int getNumRunningThreads(); - @see signalThreadShouldExit - */ - inline bool threadShouldExit() const { return threadShouldExit_; } + static void stopAllThreads (const int timeoutInMillisecs); - /** Waits for the thread to stop. - - This will waits until isThreadRunning() is false or until a timeout expires. - - @param timeOutMilliseconds the time to wait, in milliseconds. If this value - is less than zero, it will wait forever. - @returns true if the thread exits, or false if the timeout expires first. - */ - bool waitForThreadToExit (const int timeOutMilliseconds) const; - - /** Changes the thread's priority. - May return false if for some reason the priority can't be changed. - - @param priority the new priority, in the range 0 (lowest) to 10 (highest). A priority - of 5 is normal. - */ - bool setPriority (const int priority); - - /** Changes the priority of the caller thread. - - Similar to setPriority(), but this static method acts on the caller thread. - May return false if for some reason the priority can't be changed. - - @see setPriority - */ - static bool setCurrentThreadPriority (const int priority); - - /** Sets the affinity mask for the thread. - - This will only have an effect next time the thread is started - i.e. if the - thread is already running when called, it'll have no effect. - - @see setCurrentThreadAffinityMask - */ - void setAffinityMask (const uint32 affinityMask); - - /** Changes the affinity mask for the caller thread. - - This will change the affinity mask for the thread that calls this static method. - - @see setAffinityMask - */ - static void setCurrentThreadAffinityMask (const uint32 affinityMask); - - // this can be called from any thread that needs to pause.. - static void JUCE_CALLTYPE sleep (int milliseconds); - - /** Yields the calling thread's current time-slot. */ - static void JUCE_CALLTYPE yield(); - - /** Makes the thread wait for a notification. - - This puts the thread to sleep until either the timeout period expires, or - another thread calls the notify() method to wake it up. - - @returns true if the event has been signalled, false if the timeout expires. - */ - bool wait (const int timeOutMilliseconds) const; - - /** Wakes up the thread. - - If the thread has called the wait() method, this will wake it up. - - @see wait - */ - void notify() const; - - /** A value type used for thread IDs. - @see getCurrentThreadId(), getThreadId() - */ - typedef void* ThreadID; - - /** Returns an id that identifies the caller thread. - - To find the ID of a particular thread object, use getThreadId(). - - @returns a unique identifier that identifies the calling thread. - @see getThreadId - */ - static ThreadID getCurrentThreadId(); - - /** Finds the thread object that is currently running. - - Note that the main UI thread (or other non-Juce threads) don't have a Thread - object associated with them, so this will return 0. - */ - static Thread* getCurrentThread(); - - /** Returns the ID of this thread. - - That means the ID of this thread object - not of the thread that's calling the method. - - This can change when the thread is started and stopped, and will be invalid if the - thread's not actually running. - - @see getCurrentThreadId - */ - ThreadID getThreadId() const { return threadId_; } - - /** Returns the name of the thread. - - This is the name that gets set in the constructor. - */ - const String getThreadName() const { return threadName_; } - - /** Returns the number of currently-running threads. - - @returns the number of Thread objects known to be currently running. - @see stopAllThreads - */ - static int getNumRunningThreads(); - - /** Tries to stop all currently-running threads. - - This will attempt to stop all the threads known to be running at the moment. - */ - static void stopAllThreads (const int timeoutInMillisecs); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - const String threadName_; - void* volatile threadHandle_; - CriticalSection startStopLock; - WaitableEvent startSuspensionEvent_, defaultEvent_; + const String threadName_; + void* volatile threadHandle_; + CriticalSection startStopLock; + WaitableEvent startSuspensionEvent_, defaultEvent_; - int threadPriority_; - ThreadID threadId_; - uint32 affinityMask_; - bool volatile threadShouldExit_; + int threadPriority_; + ThreadID threadId_; + uint32 affinityMask_; + bool volatile threadShouldExit_; - friend void JUCE_API juce_threadEntryPoint (void*); - static void threadEntryPoint (Thread* thread); + friend void JUCE_API juce_threadEntryPoint (void*); + static void threadEntryPoint (Thread* thread); - Thread (const Thread&); - const Thread& operator= (const Thread&); + Thread (const Thread&); + const Thread& operator= (const Thread&); }; #endif // __JUCE_THREAD_JUCEHEADER__ /********* End of inlined file: juce_Thread.h *********/ -/** - A critical section that allows multiple simultaneous readers. - - Features of this type of lock are: - - - Multiple readers can hold the lock at the same time, but only one writer - can hold it at once. - - Writers trying to gain the lock will be blocked until all readers and writers - have released it - - Readers trying to gain the lock while a writer is waiting to acquire it will be - blocked until the writer has obtained and released it - - If a thread already has a read lock and tries to obtain a write lock, it will succeed if - there are no other readers - - If a thread already has the write lock and tries to obtain a read lock, this will succeed. - - Recursive locking is supported. - - @see ScopedReadLock, ScopedWriteLock, CriticalSection -*/ class JUCE_API ReadWriteLock { public: - /** - Creates a ReadWriteLock object. - */ - ReadWriteLock() throw(); + ReadWriteLock() throw(); - /** Destructor. + ~ReadWriteLock() throw(); - If the object is deleted whilst locked, any subsequent behaviour - is unpredictable. - */ - ~ReadWriteLock() throw(); + void enterRead() const throw(); - /** Locks this object for reading. + void exitRead() const throw(); - Multiple threads can simulaneously lock the object for reading, but if another - thread has it locked for writing, then this will block until it releases the - lock. + void enterWrite() const throw(); - @see exitRead, ScopedReadLock - */ - void enterRead() const throw(); + bool tryEnterWrite() const throw(); - /** Releases the read-lock. + void exitWrite() const throw(); - If the caller thread hasn't got the lock, this can have unpredictable results. - - If the enterRead() method has been called multiple times by the thread, each - call must be matched by a call to exitRead() before other threads will be allowed - to take over the lock. - - @see enterRead, ScopedReadLock - */ - void exitRead() const throw(); - - /** Locks this object for writing. - - This will block until any other threads that have it locked for reading or - writing have released their lock. - - @see exitWrite, ScopedWriteLock - */ - void enterWrite() const throw(); - - /** Tries to lock this object for writing. - - This is like enterWrite(), but doesn't block - it returns true if it manages - to obtain the lock. - - @see enterWrite - */ - bool tryEnterWrite() const throw(); - - /** Releases the write-lock. - - If the caller thread hasn't got the lock, this can have unpredictable results. - - If the enterWrite() method has been called multiple times by the thread, each - call must be matched by a call to exit() before other threads will be allowed - to take over the lock. - - @see enterWrite, ScopedWriteLock - */ - void exitWrite() const throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - CriticalSection accessLock; - WaitableEvent waitEvent; - mutable int numWaitingWriters, numWriters; - mutable Thread::ThreadID writerThreadId; - mutable Array readerThreads; + CriticalSection accessLock; + WaitableEvent waitEvent; + mutable int numWaitingWriters, numWriters; + mutable Thread::ThreadID writerThreadId; + mutable Array readerThreads; - ReadWriteLock (const ReadWriteLock&); - const ReadWriteLock& operator= (const ReadWriteLock&); + ReadWriteLock (const ReadWriteLock&); + const ReadWriteLock& operator= (const ReadWriteLock&); }; #endif // __JUCE_READWRITELOCK_JUCEHEADER__ @@ -16543,59 +8535,20 @@ private: #ifndef __JUCE_SCOPEDREADLOCK_JUCEHEADER__ #define __JUCE_SCOPEDREADLOCK_JUCEHEADER__ -/** - Automatically locks and unlocks a ReadWriteLock object. - - Use one of these as a local variable to control access to a ReadWriteLock. - - e.g. @code - - ReadWriteLock myLock; - - for (;;) - { - const ScopedReadLock myScopedLock (myLock); - // myLock is now locked - - ...do some stuff... - - // myLock gets unlocked here. - } - @endcode - - @see ReadWriteLock, ScopedWriteLock -*/ class JUCE_API ScopedReadLock { public: - /** Creates a ScopedReadLock. + inline ScopedReadLock (const ReadWriteLock& lock) throw() : lock_ (lock) { lock.enterRead(); } - As soon as it is created, this will call ReadWriteLock::enterRead(), and - when the ScopedReadLock object is deleted, the ReadWriteLock will - be unlocked. - - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! Best just to use it - as a local stack object, rather than creating one with the new() operator. - */ - inline ScopedReadLock (const ReadWriteLock& lock) throw() : lock_ (lock) { lock.enterRead(); } - - /** Destructor. - - The ReadWriteLock's exitRead() method will be called when the destructor is called. - - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! - */ - inline ~ScopedReadLock() throw() { lock_.exitRead(); } + inline ~ScopedReadLock() throw() { lock_.exitRead(); } private: - const ReadWriteLock& lock_; + const ReadWriteLock& lock_; - ScopedReadLock (const ScopedReadLock&); - const ScopedReadLock& operator= (const ScopedReadLock&); + ScopedReadLock (const ScopedReadLock&); + const ScopedReadLock& operator= (const ScopedReadLock&); }; #endif // __JUCE_SCOPEDREADLOCK_JUCEHEADER__ @@ -16608,75 +8561,23 @@ private: #ifndef __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ #define __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ -/** - Automatically tries to lock and unlock a CriticalSection object. - - Use one of these as a local variable to control access to a CriticalSection. - - e.g. @code - - CriticalSection myCriticalSection; - - for (;;) - { - const ScopedTryLock myScopedTryLock (myCriticalSection); - - // Unlike using a ScopedLock, this may fail to actually get the lock, so you - // should test this with the isLocked() method before doing your thread-unsafe - // action.. - if (myScopedTryLock.isLocked()) - { - ...do some stuff... - } - else - { - ..our attempt at locking failed because another thread had already locked it.. - } - - // myCriticalSection gets unlocked here (if it was locked) - } - @endcode - - @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock -*/ class JUCE_API ScopedTryLock { public: - /** Creates a ScopedTryLock. + inline ScopedTryLock (const CriticalSection& lock) throw() : lock_ (lock), lockWasSuccessful (lock.tryEnter()) {} - As soon as it is created, this will try to lock the CriticalSection, and - when the ScopedTryLock object is deleted, the CriticalSection will - be unlocked if the lock was successful. + inline ~ScopedTryLock() throw() { if (lockWasSuccessful) lock_.exit(); } - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! Best just to use it - as a local stack object, rather than creating one with the new() operator. - */ - inline ScopedTryLock (const CriticalSection& lock) throw() : lock_ (lock), lockWasSuccessful (lock.tryEnter()) {} - - /** Destructor. - - The CriticalSection will be unlocked (if locked) when the destructor is called. - - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! - */ - inline ~ScopedTryLock() throw() { if (lockWasSuccessful) lock_.exit(); } - - /** Lock state - - @return True if the CriticalSection is locked. - */ - bool isLocked() const throw() { return lockWasSuccessful; } + bool isLocked() const throw() { return lockWasSuccessful; } private: - const CriticalSection& lock_; - const bool lockWasSuccessful; + const CriticalSection& lock_; + const bool lockWasSuccessful; - ScopedTryLock (const ScopedTryLock&); - const ScopedTryLock& operator= (const ScopedTryLock&); + ScopedTryLock (const ScopedTryLock&); + const ScopedTryLock& operator= (const ScopedTryLock&); }; #endif // __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ @@ -16689,59 +8590,20 @@ private: #ifndef __JUCE_SCOPEDWRITELOCK_JUCEHEADER__ #define __JUCE_SCOPEDWRITELOCK_JUCEHEADER__ -/** - Automatically locks and unlocks a ReadWriteLock object. - - Use one of these as a local variable to control access to a ReadWriteLock. - - e.g. @code - - ReadWriteLock myLock; - - for (;;) - { - const ScopedWriteLock myScopedLock (myLock); - // myLock is now locked - - ...do some stuff... - - // myLock gets unlocked here. - } - @endcode - - @see ReadWriteLock, ScopedReadLock -*/ class JUCE_API ScopedWriteLock { public: - /** Creates a ScopedWriteLock. + inline ScopedWriteLock (const ReadWriteLock& lock) throw() : lock_ (lock) { lock.enterWrite(); } - As soon as it is created, this will call ReadWriteLock::enterWrite(), and - when the ScopedWriteLock object is deleted, the ReadWriteLock will - be unlocked. - - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! Best just to use it - as a local stack object, rather than creating one with the new() operator. - */ - inline ScopedWriteLock (const ReadWriteLock& lock) throw() : lock_ (lock) { lock.enterWrite(); } - - /** Destructor. - - The ReadWriteLock's exitWrite() method will be called when the destructor is called. - - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! - */ - inline ~ScopedWriteLock() throw() { lock_.exitWrite(); } + inline ~ScopedWriteLock() throw() { lock_.exitWrite(); } private: - const ReadWriteLock& lock_; + const ReadWriteLock& lock_; - ScopedWriteLock (const ScopedWriteLock&); - const ScopedWriteLock& operator= (const ScopedWriteLock&); + ScopedWriteLock (const ScopedWriteLock&); + const ScopedWriteLock& operator= (const ScopedWriteLock&); }; #endif // __JUCE_SCOPEDWRITELOCK_JUCEHEADER__ @@ -16760,271 +8622,112 @@ private: class ThreadPool; class ThreadPoolThread; -/** - A task that is executed by a ThreadPool object. - - A ThreadPool keeps a list of ThreadPoolJob objects which are executed by - its threads. - - The runJob() method needs to be implemented to do the task, and if the code that - does the work takes a significant time to run, it must keep checking the shouldExit() - method to see if something is trying to interrupt the job. If shouldExit() returns - true, the runJob() method must return immediately. - - @see ThreadPool, Thread -*/ class JUCE_API ThreadPoolJob { public: - /** Creates a thread pool job object. + ThreadPoolJob (const String& name); - After creating your job, add it to a thread pool with ThreadPool::addJob(). - */ - ThreadPoolJob (const String& name); + virtual ~ThreadPoolJob(); - /** Destructor. */ - virtual ~ThreadPoolJob(); + const String getJobName() const; - /** Returns the name of this job. - @see setJobName - */ - const String getJobName() const; + void setJobName (const String& newName); - /** Changes the job's name. - @see getJobName - */ - void setJobName (const String& newName); + enum JobStatus + { + jobHasFinished = 0, /**< indicates that the job has finished and can be + removed from the pool. */ - /** These are the values that can be returned by the runJob() method. - */ - enum JobStatus - { - jobHasFinished = 0, /**< indicates that the job has finished and can be - removed from the pool. */ + jobHasFinishedAndShouldBeDeleted, /**< indicates that the job has finished and that it + should be automatically deleted by the pool. */ - jobHasFinishedAndShouldBeDeleted, /**< indicates that the job has finished and that it - should be automatically deleted by the pool. */ + jobNeedsRunningAgain /**< indicates that the job would like to be called + again when a thread is free. */ + }; - jobNeedsRunningAgain /**< indicates that the job would like to be called - again when a thread is free. */ - }; + virtual JobStatus runJob() = 0; - /** Peforms the actual work that this job needs to do. + bool isRunning() const { return isActive; } - Your subclass must implement this method, in which is does its work. + bool shouldExit() const { return shouldStop; } - If the code in this method takes a significant time to run, it must repeatedly check - the shouldExit() method to see if something is trying to interrupt the job. - If shouldExit() ever returns true, the runJob() method must return immediately. + void signalJobShouldExit(); - If this method returns jobHasFinished, then the job will be removed from the pool - immediately. If it returns jobNeedsRunningAgain, then the job will be left in the - pool and will get a chance to run again as soon as a thread is free. - - @see shouldExit() - */ - virtual JobStatus runJob() = 0; - - /** Returns true if this job is currently running its runJob() method. */ - bool isRunning() const { return isActive; } - - /** Returns true if something is trying to interrupt this job and make it stop. - - Your runJob() method must call this whenever it gets a chance, and if it ever - returns true, the runJob() method must return immediately. - - @see signalJobShouldExit() - */ - bool shouldExit() const { return shouldStop; } - - /** Calling this will cause the shouldExit() method to return true, and the job - should (if it's been implemented correctly) stop as soon as possible. - - @see shouldExit() - */ - void signalJobShouldExit(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class ThreadPool; - friend class ThreadPoolThread; - String jobName; - ThreadPool* pool; - bool shouldStop, isActive, shouldBeDeleted; + friend class ThreadPool; + friend class ThreadPoolThread; + String jobName; + ThreadPool* pool; + bool shouldStop, isActive, shouldBeDeleted; - ThreadPoolJob (const ThreadPoolJob&); - const ThreadPoolJob& operator= (const ThreadPoolJob&); + ThreadPoolJob (const ThreadPoolJob&); + const ThreadPoolJob& operator= (const ThreadPoolJob&); }; -/** - A set of threads that will run a list of jobs. - - When a ThreadPoolJob object is added to the ThreadPool's list, its run() method - will be called by the next pooled thread that becomes free. - - @see ThreadPoolJob, Thread -*/ class JUCE_API ThreadPool { public: - /** Creates a thread pool. + ThreadPool (const int numberOfThreads, + const bool startThreadsOnlyWhenNeeded = true, + const int stopThreadsWhenNotUsedTimeoutMs = 5000); - Once you've created a pool, you can give it some things to do with the addJob() - method. + ~ThreadPool(); - @param numberOfThreads the maximum number of actual threads to run. - @param startThreadsOnlyWhenNeeded if this is true, then no threads will be started - until there are some jobs to run. If false, then - all the threads will be fired-up immediately so that - they're ready for action - @param stopThreadsWhenNotUsedTimeoutMs if this timeout is > 0, then if any threads have been - inactive for this length of time, they will automatically - be stopped until more jobs come along and they're needed - */ - ThreadPool (const int numberOfThreads, - const bool startThreadsOnlyWhenNeeded = true, - const int stopThreadsWhenNotUsedTimeoutMs = 5000); + class JUCE_API JobSelector + { + public: + virtual ~JobSelector() {} - /** Destructor. + virtual bool isJobSuitable (ThreadPoolJob* job) = 0; + }; - This will attempt to remove all the jobs before deleting, but if you want to - specify a timeout, you should call removeAllJobs() explicitly before deleting - the pool. - */ - ~ThreadPool(); + void addJob (ThreadPoolJob* const job); - /** A callback class used when you need to select which ThreadPoolJob objects are suitable - for some kind of operation. - @see ThreadPool::removeAllJobs - */ - class JUCE_API JobSelector - { - public: - virtual ~JobSelector() {} + bool removeJob (ThreadPoolJob* const job, + const bool interruptIfRunning, + const int timeOutMilliseconds); - /** Should return true if the specified thread matches your criteria for whatever - operation that this object is being used for. + bool removeAllJobs (const bool interruptRunningJobs, + const int timeOutMilliseconds, + const bool deleteInactiveJobs = false, + JobSelector* selectedJobsToRemove = 0); - Any implementation of this method must be extremely fast and thread-safe! - */ - virtual bool isJobSuitable (ThreadPoolJob* job) = 0; - }; + int getNumJobs() const; - /** Adds a job to the queue. + ThreadPoolJob* getJob (const int index) const; - Once a job has been added, then the next time a thread is free, it will run - the job's ThreadPoolJob::runJob() method. Depending on the return value of the - runJob() method, the pool will either remove the job from the pool or add it to - the back of the queue to be run again. - */ - void addJob (ThreadPoolJob* const job); + bool contains (const ThreadPoolJob* const job) const; - /** Tries to remove a job from the pool. + bool isJobRunning (const ThreadPoolJob* const job) const; - If the job isn't yet running, this will simply remove it. If it is running, it - will wait for it to finish. + bool waitForJobToFinish (const ThreadPoolJob* const job, + const int timeOutMilliseconds) const; - If the timeout period expires before the job finishes running, then the job will be - left in the pool and this will return false. It returns true if the job is sucessfully - stopped and removed. + const StringArray getNamesOfAllJobs (const bool onlyReturnActiveJobs) const; - @param job the job to remove - @param interruptIfRunning if true, then if the job is currently busy, its - ThreadPoolJob::signalJobShouldExit() method will be called to try - to interrupt it. If false, then if the job will be allowed to run - until it stops normally (or the timeout expires) - @param timeOutMilliseconds the length of time this method should wait for the job to finish - before giving up and returning false - */ - bool removeJob (ThreadPoolJob* const job, - const bool interruptIfRunning, - const int timeOutMilliseconds); + bool setThreadPriorities (const int newPriority); - /** Tries to remove all jobs from the pool. - - @param interruptRunningJobs if true, then all running jobs will have their ThreadPoolJob::signalJobShouldExit() - methods called to try to interrupt them - @param timeOutMilliseconds the length of time this method should wait for all the jobs to finish - before giving up and returning false - @param deleteInactiveJobs if true, any jobs that aren't currently running will be deleted. If false, - they will simply be removed from the pool. Jobs that are already running when - this method is called can choose whether they should be deleted by - returning jobHasFinishedAndShouldBeDeleted from their runJob() method. - @param selectedJobsToRemove if this is non-zero, the JobSelector object is asked to decide which - jobs should be removed. If it is zero, all jobs are removed - @returns true if all jobs are successfully stopped and removed; false if the timeout period - expires while waiting for one or more jobs to stop - */ - bool removeAllJobs (const bool interruptRunningJobs, - const int timeOutMilliseconds, - const bool deleteInactiveJobs = false, - JobSelector* selectedJobsToRemove = 0); - - /** Returns the number of jobs currently running or queued. - */ - int getNumJobs() const; - - /** Returns one of the jobs in the queue. - - Note that this can be a very volatile list as jobs might be continuously getting shifted - around in the list, and this method may return 0 if the index is currently out-of-range. - */ - ThreadPoolJob* getJob (const int index) const; - - /** Returns true if the given job is currently queued or running. - - @see isJobRunning() - */ - bool contains (const ThreadPoolJob* const job) const; - - /** Returns true if the given job is currently being run by a thread. - */ - bool isJobRunning (const ThreadPoolJob* const job) const; - - /** Waits until a job has finished running and has been removed from the pool. - - This will wait until the job is no longer in the pool - i.e. until its - runJob() method returns ThreadPoolJob::jobHasFinished. - - If the timeout period expires before the job finishes, this will return false; - it returns true if the job has finished successfully. - */ - bool waitForJobToFinish (const ThreadPoolJob* const job, - const int timeOutMilliseconds) const; - - /** Returns a list of the names of all the jobs currently running or queued. - - If onlyReturnActiveJobs is true, only the ones currently running are returned. - */ - const StringArray getNamesOfAllJobs (const bool onlyReturnActiveJobs) const; - - /** Changes the priority of all the threads. - - This will call Thread::setPriority() for each thread in the pool. - May return false if for some reason the priority can't be changed. - */ - bool setThreadPriorities (const int newPriority); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - const int numThreads, threadStopTimeout; - int priority; - HeapBlock threads; - VoidArray jobs; + const int numThreads, threadStopTimeout; + int priority; + HeapBlock threads; + VoidArray jobs; - CriticalSection lock; - uint32 lastJobEndTime; - WaitableEvent jobFinishedSignal; + CriticalSection lock; + uint32 lastJobEndTime; + WaitableEvent jobFinishedSignal; - friend class ThreadPoolThread; - bool runNextJob(); + friend class ThreadPoolThread; + bool runNextJob(); - ThreadPool (const ThreadPool&); - const ThreadPool& operator= (const ThreadPool&); + ThreadPool (const ThreadPool&); + const ThreadPool& operator= (const ThreadPool&); }; #endif // __JUCE_THREADPOOL_JUCEHEADER__ @@ -17037,101 +8740,43 @@ private: #ifndef __JUCE_TIMESLICETHREAD_JUCEHEADER__ #define __JUCE_TIMESLICETHREAD_JUCEHEADER__ -/** - Used by the TimeSliceThread class. - - To register your class with a TimeSliceThread, derive from this class and - use the TimeSliceThread::addTimeSliceClient() method to add it to the list. - - Make sure you always call TimeSliceThread::removeTimeSliceClient() before - deleting your client! - - @see TimeSliceThread -*/ class JUCE_API TimeSliceClient { public: - /** Destructor. */ - virtual ~TimeSliceClient() {} + virtual ~TimeSliceClient() {} - /** Called back by a TimeSliceThread. - - When you register this class with it, a TimeSliceThread will repeatedly call - this method. - - The implementation of this method should use its time-slice to do something that's - quick - never block for longer than absolutely necessary. - - @returns Your method should return true if it needs more time, or false if it's - not too busy and doesn't need calling back urgently. If all the thread's - clients indicate that they're not busy, then it'll save CPU by sleeping for - up to half a second in between callbacks. You can force the TimeSliceThread - to wake up and poll again immediately by calling its notify() method. - */ - virtual bool useTimeSlice() = 0; + virtual bool useTimeSlice() = 0; }; -/** - A thread that keeps a list of clients, and calls each one in turn, giving them - all a chance to run some sort of short task. - - @see TimeSliceClient, Thread -*/ class JUCE_API TimeSliceThread : public Thread { public: - /** - Creates a TimeSliceThread. + TimeSliceThread (const String& threadName); - When first created, the thread is not running. Use the startThread() - method to start it. - */ - TimeSliceThread (const String& threadName); + ~TimeSliceThread(); - /** Destructor. + void addTimeSliceClient (TimeSliceClient* const client); - Deleting a Thread object that is running will only give the thread a - brief opportunity to stop itself cleanly, so it's recommended that you - should always call stopThread() with a decent timeout before deleting, - to avoid the thread being forcibly killed (which is a Bad Thing). - */ - ~TimeSliceThread(); + void removeTimeSliceClient (TimeSliceClient* const client); - /** Adds a client to the list. + int getNumClients() const; - The client's callbacks will start immediately (possibly before the method - has returned). - */ - void addTimeSliceClient (TimeSliceClient* const client); + TimeSliceClient* getClient (const int index) const; - /** Removes a client from the list. + void run(); - This method will make sure that all callbacks to the client have completely - finished before the method returns. - */ - void removeTimeSliceClient (TimeSliceClient* const client); - - /** Returns the number of registered clients. */ - int getNumClients() const; - - /** Returns one of the registered clients. */ - TimeSliceClient* getClient (const int index) const; - - /** @internal */ - void run(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - CriticalSection callbackLock, listLock; - Array clients; - int index; - TimeSliceClient* clientBeingCalled; - bool clientsChanged; + CriticalSection callbackLock, listLock; + Array clients; + int index; + TimeSliceClient* clientBeingCalled; + bool clientsChanged; - TimeSliceThread (const TimeSliceThread&); - const TimeSliceThread& operator= (const TimeSliceThread&); + TimeSliceThread (const TimeSliceThread&); + const TimeSliceThread& operator= (const TimeSliceThread&); }; #endif // __JUCE_TIMESLICETHREAD_JUCEHEADER__ @@ -17176,120 +8821,69 @@ class SharedMouseCursorInternal; class ComponentPeer; class Component; -/** - Represents a mouse cursor image. - - This object can either be used to represent one of the standard mouse - cursor shapes, or a custom one generated from an image. -*/ class JUCE_API MouseCursor { public: - /** The set of available standard mouse cursors. */ - enum StandardCursorType - { - NoCursor = 0, /**< An invisible cursor. */ - NormalCursor, /**< The stardard arrow cursor. */ + enum StandardCursorType + { + NoCursor = 0, /**< An invisible cursor. */ + NormalCursor, /**< The stardard arrow cursor. */ - WaitCursor, /**< The normal hourglass or spinning-beachball 'busy' cursor. */ - IBeamCursor, /**< A vertical I-beam for positioning within text. */ - CrosshairCursor, /**< A pair of crosshairs. */ - CopyingCursor, /**< The normal arrow cursor, but with a "+" on it to indicate - that you're dragging a copy of something. */ + WaitCursor, /**< The normal hourglass or spinning-beachball 'busy' cursor. */ + IBeamCursor, /**< A vertical I-beam for positioning within text. */ + CrosshairCursor, /**< A pair of crosshairs. */ + CopyingCursor, /**< The normal arrow cursor, but with a "+" on it to indicate + that you're dragging a copy of something. */ - PointingHandCursor, /**< A hand with a pointing finger, for clicking on web-links. */ - DraggingHandCursor, /**< An open flat hand for dragging heavy objects around. */ + PointingHandCursor, /**< A hand with a pointing finger, for clicking on web-links. */ + DraggingHandCursor, /**< An open flat hand for dragging heavy objects around. */ - LeftRightResizeCursor, /**< An arrow pointing left and right. */ - UpDownResizeCursor, /**< an arrow pointing up and down. */ - UpDownLeftRightResizeCursor, /**< An arrow pointing up, down, left and right. */ + LeftRightResizeCursor, /**< An arrow pointing left and right. */ + UpDownResizeCursor, /**< an arrow pointing up and down. */ + UpDownLeftRightResizeCursor, /**< An arrow pointing up, down, left and right. */ - TopEdgeResizeCursor, /**< A platform-specific cursor for resizing the top-edge of a window. */ - BottomEdgeResizeCursor, /**< A platform-specific cursor for resizing the bottom-edge of a window. */ - LeftEdgeResizeCursor, /**< A platform-specific cursor for resizing the left-edge of a window. */ - RightEdgeResizeCursor, /**< A platform-specific cursor for resizing the right-edge of a window. */ - TopLeftCornerResizeCursor, /**< A platform-specific cursor for resizing the top-left-corner of a window. */ - TopRightCornerResizeCursor, /**< A platform-specific cursor for resizing the top-right-corner of a window. */ - BottomLeftCornerResizeCursor, /**< A platform-specific cursor for resizing the bottom-left-corner of a window. */ - BottomRightCornerResizeCursor /**< A platform-specific cursor for resizing the bottom-right-corner of a window. */ - }; + TopEdgeResizeCursor, /**< A platform-specific cursor for resizing the top-edge of a window. */ + BottomEdgeResizeCursor, /**< A platform-specific cursor for resizing the bottom-edge of a window. */ + LeftEdgeResizeCursor, /**< A platform-specific cursor for resizing the left-edge of a window. */ + RightEdgeResizeCursor, /**< A platform-specific cursor for resizing the right-edge of a window. */ + TopLeftCornerResizeCursor, /**< A platform-specific cursor for resizing the top-left-corner of a window. */ + TopRightCornerResizeCursor, /**< A platform-specific cursor for resizing the top-right-corner of a window. */ + BottomLeftCornerResizeCursor, /**< A platform-specific cursor for resizing the bottom-left-corner of a window. */ + BottomRightCornerResizeCursor /**< A platform-specific cursor for resizing the bottom-right-corner of a window. */ + }; - /** Creates the standard arrow cursor. */ - MouseCursor() throw(); + MouseCursor() throw(); - /** Creates one of the standard mouse cursor */ - MouseCursor (const StandardCursorType type) throw(); + MouseCursor (const StandardCursorType type) throw(); - /** Creates a custom cursor from an image. + MouseCursor (const Image& image, + const int hotSpotX, + const int hotSpotY) throw(); - @param image the image to use for the cursor - if this is bigger than the - system can manage, it might get scaled down first, and might - also have to be turned to black-and-white if it can't do colour - cursors. - @param hotSpotX the x position of the cursor's hotspot within the image - @param hotSpotY the y position of the cursor's hotspot within the image - */ - MouseCursor (const Image& image, - const int hotSpotX, - const int hotSpotY) throw(); + MouseCursor (const MouseCursor& other) throw(); - /** Creates a copy of another cursor object. */ - MouseCursor (const MouseCursor& other) throw(); + const MouseCursor& operator= (const MouseCursor& other) throw(); - /** Copies this cursor from another object. */ - const MouseCursor& operator= (const MouseCursor& other) throw(); + ~MouseCursor() throw(); - /** Destructor. */ - ~MouseCursor() throw(); + bool operator== (const MouseCursor& other) const throw(); - /** Checks whether two mouse cursors are the same. + bool operator!= (const MouseCursor& other) const throw(); - For custom cursors, two cursors created from the same image won't be - recognised as the same, only MouseCursor objects that have been - copied from the same object. - */ - bool operator== (const MouseCursor& other) const throw(); + static void showWaitCursor() throw(); - /** Checks whether two mouse cursors are the same. + static void hideWaitCursor() throw(); - For custom cursors, two cursors created from the same image won't be - recognised as the same, only MouseCursor objects that have been - copied from the same object. - */ - bool operator!= (const MouseCursor& other) const throw(); - - /** Makes the system show its default 'busy' cursor. - - This will turn the system cursor to an hourglass or spinning beachball - until the next time the mouse is moved, or hideWaitCursor() is called. - - This is handy if the message loop is about to block for a couple of - seconds while busy and you want to give the user feedback about this. - - @see MessageManager::setTimeBeforeShowingWaitCursor - */ - static void showWaitCursor() throw(); - - /** If showWaitCursor has been called, this will return the mouse to its - normal state. - - This will look at what component is under the mouse, and update the - cursor to be the correct one for that component. - - @see showWaitCursor - */ - static void hideWaitCursor() throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ReferenceCountedObjectPtr cursorHandle; + ReferenceCountedObjectPtr cursorHandle; - friend class Component; - void showInWindow (ComponentPeer* window) const throw(); - void showInAllWindows() const throw(); - void* getHandle() const throw(); + friend class Component; + void showInWindow (ComponentPeer* window) const throw(); + void showInAllWindows() const throw(); + void* getHandle() const throw(); }; #endif // __JUCE_MOUSECURSOR_JUCEHEADER__ @@ -17309,533 +8903,178 @@ class Component; #ifndef __JUCE_MODIFIERKEYS_JUCEHEADER__ #define __JUCE_MODIFIERKEYS_JUCEHEADER__ -/** - Represents the state of the mouse buttons and modifier keys. - - This is used both by mouse events and by KeyPress objects to describe - the state of keys such as shift, control, alt, etc. - - @see KeyPress, MouseEvent::mods -*/ class JUCE_API ModifierKeys { public: - /** Creates a ModifierKeys object from a raw set of flags. + ModifierKeys (const int flags = 0) throw(); - @param flags to represent the keys that are down - @see shiftModifier, ctrlModifier, altModifier, leftButtonModifier, - rightButtonModifier, commandModifier, popupMenuClickModifier - */ - ModifierKeys (const int flags = 0) throw(); + ModifierKeys (const ModifierKeys& other) throw(); - /** Creates a copy of another object. */ - ModifierKeys (const ModifierKeys& other) throw(); + const ModifierKeys& operator= (const ModifierKeys& other) throw(); - /** Copies this object from another one. */ - const ModifierKeys& operator= (const ModifierKeys& other) throw(); + inline bool isCommandDown() const throw() { return (flags & commandModifier) != 0; } - /** Checks whether the 'command' key flag is set (or 'ctrl' on Windows/Linux). + inline bool isPopupMenu() const throw() { return (flags & popupMenuClickModifier) != 0; } - This is a platform-agnostic way of checking for the operating system's - preferred command-key modifier - so on the Mac it tests for the Apple key, on - Windows/Linux, it's actually checking for the CTRL key. - */ - inline bool isCommandDown() const throw() { return (flags & commandModifier) != 0; } + inline bool isLeftButtonDown() const throw() { return (flags & leftButtonModifier) != 0; } - /** Checks whether the user is trying to launch a pop-up menu. + inline bool isRightButtonDown() const throw() { return (flags & rightButtonModifier) != 0; } - This checks for platform-specific modifiers that might indicate that the user - is following the operating system's normal method of showing a pop-up menu. + inline bool isMiddleButtonDown() const throw() { return (flags & middleButtonModifier) != 0; } - So on Windows/Linux, this method is really testing for a right-click. - On the Mac, it tests for either the CTRL key being down, or a right-click. - */ - inline bool isPopupMenu() const throw() { return (flags & popupMenuClickModifier) != 0; } + inline bool isAnyMouseButtonDown() const throw() { return (flags & allMouseButtonModifiers) != 0; } - /** Checks whether the flag is set for the left mouse-button. */ - inline bool isLeftButtonDown() const throw() { return (flags & leftButtonModifier) != 0; } + inline bool isAnyModifierKeyDown() const throw() { return (flags & (shiftModifier | ctrlModifier | altModifier | commandModifier)) != 0; } - /** Checks whether the flag is set for the right mouse-button. + inline bool isShiftDown() const throw() { return (flags & shiftModifier) != 0; } - Note that for detecting popup-menu clicks, you should be using isPopupMenu() instead, as - this is platform-independent (and makes your code more explanatory too). - */ - inline bool isRightButtonDown() const throw() { return (flags & rightButtonModifier) != 0; } + inline bool isCtrlDown() const throw() { return (flags & ctrlModifier) != 0; } - inline bool isMiddleButtonDown() const throw() { return (flags & middleButtonModifier) != 0; } + inline bool isAltDown() const throw() { return (flags & altModifier) != 0; } - /** Tests for any of the mouse-button flags. */ - inline bool isAnyMouseButtonDown() const throw() { return (flags & allMouseButtonModifiers) != 0; } + enum Flags + { + shiftModifier = 1, - /** Tests for any of the modifier key flags. */ - inline bool isAnyModifierKeyDown() const throw() { return (flags & (shiftModifier | ctrlModifier | altModifier | commandModifier)) != 0; } + ctrlModifier = 2, - /** Checks whether the shift key's flag is set. */ - inline bool isShiftDown() const throw() { return (flags & shiftModifier) != 0; } + altModifier = 4, - /** Checks whether the CTRL key's flag is set. + leftButtonModifier = 16, - Remember that it's better to use the platform-agnostic routines to test for command-key and - popup-menu modifiers. + rightButtonModifier = 32, - @see isCommandDown, isPopupMenu - */ - inline bool isCtrlDown() const throw() { return (flags & ctrlModifier) != 0; } - - /** Checks whether the shift key's flag is set. */ - inline bool isAltDown() const throw() { return (flags & altModifier) != 0; } - - /** Flags that represent the different keys. */ - enum Flags - { - /** Shift key flag. */ - shiftModifier = 1, - - /** CTRL key flag. */ - ctrlModifier = 2, - - /** ALT key flag. */ - altModifier = 4, - - /** Left mouse button flag. */ - leftButtonModifier = 16, - - /** Right mouse button flag. */ - rightButtonModifier = 32, - - /** Middle mouse button flag. */ - middleButtonModifier = 64, + middleButtonModifier = 64, #if JUCE_MAC - /** Command key flag - on windows this is the same as the CTRL key flag. */ - commandModifier = 8, + commandModifier = 8, - /** Popup menu flag - on windows this is the same as rightButtonModifier, on the - Mac it's the same as (rightButtonModifier | ctrlModifier). */ - popupMenuClickModifier = rightButtonModifier | ctrlModifier, + popupMenuClickModifier = rightButtonModifier | ctrlModifier, #else - /** Command key flag - on windows this is the same as the CTRL key flag. */ - commandModifier = ctrlModifier, + commandModifier = ctrlModifier, - /** Popup menu flag - on windows this is the same as rightButtonModifier, on the - Mac it's the same as (rightButtonModifier | ctrlModifier). */ - popupMenuClickModifier = rightButtonModifier, + popupMenuClickModifier = rightButtonModifier, #endif - /** Represents a combination of all the shift, alt, ctrl and command key modifiers. */ - allKeyboardModifiers = shiftModifier | ctrlModifier | altModifier | commandModifier, + allKeyboardModifiers = shiftModifier | ctrlModifier | altModifier | commandModifier, - /** Represents a combination of all the mouse buttons at once. */ - allMouseButtonModifiers = leftButtonModifier | rightButtonModifier | middleButtonModifier, - }; + allMouseButtonModifiers = leftButtonModifier | rightButtonModifier | middleButtonModifier, + }; - /** Returns the raw flags for direct testing. */ - inline int getRawFlags() const throw() { return flags; } + inline int getRawFlags() const throw() { return flags; } - /** Tests a combination of flags and returns true if any of them are set. */ - inline bool testFlags (const int flagsToTest) const throw() { return (flags & flagsToTest) != 0; } + inline bool testFlags (const int flagsToTest) const throw() { return (flags & flagsToTest) != 0; } - /** Creates a ModifierKeys object to represent the last-known state of the - keyboard and mouse buttons. + static const ModifierKeys getCurrentModifiers() throw(); - @see getCurrentModifiersRealtime - */ - static const ModifierKeys getCurrentModifiers() throw(); - - /** Creates a ModifierKeys object to represent the current state of the - keyboard and mouse buttons. - - This isn't often needed and isn't recommended, but will actively check all the - mouse and key states rather than just returning their last-known state like - getCurrentModifiers() does. - - This is only needed in special circumstances for up-to-date modifier information - at times when the app's event loop isn't running normally. - */ - static const ModifierKeys getCurrentModifiersRealtime() throw(); + static const ModifierKeys getCurrentModifiersRealtime() throw(); private: - int flags; + int flags; - static int currentModifierFlags; + static int currentModifierFlags; - friend class ComponentPeer; - static void updateCurrentModifiers() throw(); + friend class ComponentPeer; + static void updateCurrentModifiers() throw(); }; #endif // __JUCE_MODIFIERKEYS_JUCEHEADER__ /********* End of inlined file: juce_ModifierKeys.h *********/ -/** - Contains position and status information about a mouse event. - - @see MouseListener, Component::mouseMove, Component::mouseEnter, Component::mouseExit, - Component::mouseDown, Component::mouseUp, Component::mouseDrag -*/ class JUCE_API MouseEvent { public: - /** Creates a MouseEvent. + MouseEvent (const int x, const int y, + const ModifierKeys& modifiers, + Component* const originator, + const Time& eventTime, + const int mouseDownX, + const int mouseDownY, + const Time& mouseDownTime, + const int numberOfClicks, + const bool mouseWasDragged) throw(); - Normally an application will never need to use this. + ~MouseEvent() throw(); - @param x the x position of the mouse, relative to the component that is passed-in - @param y the y position of the mouse, relative to the component that is passed-in - @param modifiers the key modifiers at the time of the event - @param originator the component that the mouse event applies to - @param eventTime the time the event happened - @param mouseDownX the x position of the corresponding mouse-down event (relative to the component that is passed-in). - If there isn't a corresponding mouse-down (e.g. for a mouse-move), this will just be - the same as the current mouse-x position. - @param mouseDownY the y position of the corresponding mouse-down event (relative to the component that is passed-in) - If there isn't a corresponding mouse-down (e.g. for a mouse-move), this will just be - the same as the current mouse-y position. - @param mouseDownTime the time at which the corresponding mouse-down event happened - If there isn't a corresponding mouse-down (e.g. for a mouse-move), this will just be - the same as the current mouse-event time. - @param numberOfClicks how many clicks, e.g. a double-click event will be 2, a triple-click will be 3, etc - @param mouseWasDragged whether the mouse has been dragged significantly since the previous mouse-down - */ - MouseEvent (const int x, const int y, - const ModifierKeys& modifiers, - Component* const originator, - const Time& eventTime, - const int mouseDownX, - const int mouseDownY, - const Time& mouseDownTime, - const int numberOfClicks, - const bool mouseWasDragged) throw(); + int x; - /** Destructor. */ - ~MouseEvent() throw(); + int y; - /** The x-position of the mouse when the event occurred. + ModifierKeys mods; - This value is relative to the top-left of the component to which the - event applies (as indicated by the MouseEvent::eventComponent field). - */ - int x; + Component* eventComponent; - /** The y-position of the mouse when the event occurred. + Component* originalComponent; - This value is relative to the top-left of the component to which the - event applies (as indicated by the MouseEvent::eventComponent field). - */ - int y; + Time eventTime; - /** The key modifiers associated with the event. + int getMouseDownX() const throw(); - This will let you find out which mouse buttons were down, as well as which - modifier keys were held down. + int getMouseDownY() const throw(); - When used for mouse-up events, this will indicate the state of the mouse buttons - just before they were released, so that you can tell which button they let go of. - */ - ModifierKeys mods; + int getDistanceFromDragStart() const throw(); - /** The component that this event applies to. + int getDistanceFromDragStartX() const throw(); - This is usually the component that the mouse was over at the time, but for mouse-drag - events the mouse could actually be over a different component and the events are - still sent to the component that the button was originally pressed on. + int getDistanceFromDragStartY() const throw(); - The x and y member variables are relative to this component's position. + bool mouseWasClicked() const throw(); - If you use getEventRelativeTo() to retarget this object to be relative to a different - component, this pointer will be updated, but originalComponent remains unchanged. + int getNumberOfClicks() const throw() { return numberOfClicks; } - @see originalComponent - */ - Component* eventComponent; + int getLengthOfMousePress() const throw(); - /** The component that the event first occurred on. + int getScreenX() const throw(); - If you use getEventRelativeTo() to retarget this object to be relative to a different - component, this value remains unchanged to indicate the first component that received it. + int getScreenY() const throw(); - @see eventComponent - */ - Component* originalComponent; + int getMouseDownScreenX() const throw(); - /** The time that this mouse-event occurred. - */ - Time eventTime; + int getMouseDownScreenY() const throw(); - /** Returns the x co-ordinate of the last place that a mouse was pressed. + const MouseEvent getEventRelativeTo (Component* const otherComponent) const throw(); - The co-ordinate is relative to the component specified in MouseEvent::component. + static void setDoubleClickTimeout (const int timeOutMilliseconds) throw(); - @see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasClicked - */ - int getMouseDownX() const throw(); + static int getDoubleClickTimeout() throw(); - /** Returns the y co-ordinate of the last place that a mouse was pressed. - - The co-ordinate is relative to the component specified in MouseEvent::component. - - @see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasClicked - */ - int getMouseDownY() const throw(); - - /** Returns the straight-line distance between where the mouse is now and where it - was the last time the button was pressed. - - This is quite handy for things like deciding whether the user has moved far enough - for it to be considered a drag operation. - - @see getDistanceFromDragStartX - */ - int getDistanceFromDragStart() const throw(); - - /** Returns the difference between the mouse's current x postion and where it was - when the button was last pressed. - - @see getDistanceFromDragStart - */ - int getDistanceFromDragStartX() const throw(); - - /** Returns the difference between the mouse's current y postion and where it was - when the button was last pressed. - - @see getDistanceFromDragStart - */ - int getDistanceFromDragStartY() const throw(); - - /** Returns true if the mouse has just been clicked. - - Used in either your mouseUp() or mouseDrag() methods, this will tell you whether - the user has dragged the mouse more than a few pixels from the place where the - mouse-down occurred. - - Once they have dragged it far enough for this method to return false, it will continue - to return false until the mouse-up, even if they move the mouse back to the same - position where they originally pressed it. This means that it's very handy for - objects that can either be clicked on or dragged, as you can use it in the mouseDrag() - callback to ignore any small movements they might make while clicking. - - @returns true if the mouse wasn't dragged by more than a few pixels between - the last time the button was pressed and released. - */ - bool mouseWasClicked() const throw(); - - /** For a click event, the number of times the mouse was clicked in succession. - - So for example a double-click event will return 2, a triple-click 3, etc. - */ - int getNumberOfClicks() const throw() { return numberOfClicks; } - - /** Returns the time that the mouse button has been held down for. - - If called from a mouseDrag or mouseUp callback, this will return the - number of milliseconds since the corresponding mouseDown event occurred. - If called in other contexts, e.g. a mouseMove, then the returned value - may be 0 or an undefined value. - */ - int getLengthOfMousePress() const throw(); - - /** Returns the mouse x position of this event, in global screen co-ordinates. - - The co-ordinates are relative to the top-left of the main monitor. - - @see getMouseDownScreenX, Desktop::getMousePosition - */ - int getScreenX() const throw(); - - /** Returns the mouse y position of this event, in global screen co-ordinates. - - The co-ordinates are relative to the top-left of the main monitor. - - @see getMouseDownScreenY, Desktop::getMousePosition - */ - int getScreenY() const throw(); - - /** Returns the x co-ordinate at which the mouse button was last pressed. - - The co-ordinates are relative to the top-left of the main monitor. - - @see getScreenX, Desktop::getMousePosition - */ - int getMouseDownScreenX() const throw(); - - /** Returns the y co-ordinate at which the mouse button was last pressed. - - The co-ordinates are relative to the top-left of the main monitor. - - @see getScreenY, Desktop::getMousePosition - */ - int getMouseDownScreenY() const throw(); - - /** Creates a version of this event that is relative to a different component. - - The x and y positions of the event that is returned will have been - adjusted to be relative to the new component. - */ - const MouseEvent getEventRelativeTo (Component* const otherComponent) const throw(); - - /** Changes the application-wide setting for the double-click time limit. - - This is the maximum length of time between mouse-clicks for it to be - considered a double-click. It's used by the Component class. - - @see getDoubleClickTimeout, MouseListener::mouseDoubleClick - */ - static void setDoubleClickTimeout (const int timeOutMilliseconds) throw(); - - /** Returns the application-wide setting for the double-click time limit. - - This is the maximum length of time between mouse-clicks for it to be - considered a double-click. It's used by the Component class. - - @see setDoubleClickTimeout, MouseListener::mouseDoubleClick - */ - static int getDoubleClickTimeout() throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - int mouseDownX, mouseDownY; - Time mouseDownTime; - int numberOfClicks; - bool wasMovedSinceMouseDown; + int mouseDownX, mouseDownY; + Time mouseDownTime; + int numberOfClicks; + bool wasMovedSinceMouseDown; }; #endif // __JUCE_MOUSEEVENT_JUCEHEADER__ /********* End of inlined file: juce_MouseEvent.h *********/ -/** - A MouseListener can be registered with a component to receive callbacks - about mouse events that happen to that component. - - @see Component::addMouseListener, Component::removeMouseListener -*/ class JUCE_API MouseListener { public: - /** Destructor. */ - virtual ~MouseListener() {} + virtual ~MouseListener() {} - /** Called when the mouse moves inside a component. + virtual void mouseMove (const MouseEvent& e); - If the mouse button isn't pressed and the mouse moves over a component, - this will be called to let the component react to this. + virtual void mouseEnter (const MouseEvent& e); - A component will always get a mouseEnter callback before a mouseMove. + virtual void mouseExit (const MouseEvent& e); - @param e details about the position and status of the mouse event, including - the source component in which it occurred - @see mouseEnter, mouseExit, mouseDrag, contains - */ - virtual void mouseMove (const MouseEvent& e); + virtual void mouseDown (const MouseEvent& e); - /** Called when the mouse first enters a component. + virtual void mouseDrag (const MouseEvent& e); - If the mouse button isn't pressed and the mouse moves into a component, - this will be called to let the component react to this. + virtual void mouseUp (const MouseEvent& e); - When the mouse button is pressed and held down while being moved in - or out of a component, no mouseEnter or mouseExit callbacks are made - only - mouseDrag messages are sent to the component that the mouse was originally - clicked on, until the button is released. + virtual void mouseDoubleClick (const MouseEvent& e); - @param e details about the position and status of the mouse event, including - the source component in which it occurred - @see mouseExit, mouseDrag, mouseMove, contains - */ - virtual void mouseEnter (const MouseEvent& e); - - /** Called when the mouse moves out of a component. - - This will be called when the mouse moves off the edge of this - component. - - If the mouse button was pressed, and it was then dragged off the - edge of the component and released, then this callback will happen - when the button is released, after the mouseUp callback. - - @param e details about the position and status of the mouse event, including - the source component in which it occurred - @see mouseEnter, mouseDrag, mouseMove, contains - */ - virtual void mouseExit (const MouseEvent& e); - - /** Called when a mouse button is pressed. - - The MouseEvent object passed in contains lots of methods for finding out - which button was pressed, as well as which modifier keys (e.g. shift, ctrl) - were held down at the time. - - Once a button is held down, the mouseDrag method will be called when the - mouse moves, until the button is released. - - @param e details about the position and status of the mouse event, including - the source component in which it occurred - @see mouseUp, mouseDrag, mouseDoubleClick, contains - */ - virtual void mouseDown (const MouseEvent& e); - - /** Called when the mouse is moved while a button is held down. - - When a mouse button is pressed inside a component, that component - receives mouseDrag callbacks each time the mouse moves, even if the - mouse strays outside the component's bounds. - - @param e details about the position and status of the mouse event, including - the source component in which it occurred - @see mouseDown, mouseUp, mouseMove, contains, setDragRepeatInterval - */ - virtual void mouseDrag (const MouseEvent& e); - - /** Called when a mouse button is released. - - A mouseUp callback is sent to the component in which a button was pressed - even if the mouse is actually over a different component when the - button is released. - - The MouseEvent object passed in contains lots of methods for finding out - which buttons were down just before they were released. - - @param e details about the position and status of the mouse event, including - the source component in which it occurred - @see mouseDown, mouseDrag, mouseDoubleClick, contains - */ - virtual void mouseUp (const MouseEvent& e); - - /** Called when a mouse button has been double-clicked on a component. - - The MouseEvent object passed in contains lots of methods for finding out - which button was pressed, as well as which modifier keys (e.g. shift, ctrl) - were held down at the time. - - @param e details about the position and status of the mouse event, including - the source component in which it occurred - @see mouseDown, mouseUp - */ - virtual void mouseDoubleClick (const MouseEvent& e); - - /** Called when the mouse-wheel is moved. - - This callback is sent to the component that the mouse is over when the - wheel is moved. - - If not overridden, the component will forward this message to its parent, so - that parent components can collect mouse-wheel messages that happen to - child components which aren't interested in them. - - @param e details about the position and status of the mouse event, including - the source component in which it occurred - @param wheelIncrementX the speed and direction of the horizontal scroll-wheel - a positive - value means the wheel has been pushed to the right, negative means it - was pushed to the left - @param wheelIncrementY the speed and direction of the vertical scroll-wheel - a positive - value means the wheel has been pushed upwards, negative means it - was pushed downwards - */ - virtual void mouseWheelMove (const MouseEvent& e, - float wheelIncrementX, - float wheelIncrementY); + virtual void mouseWheelMove (const MouseEvent& e, + float wheelIncrementX, + float wheelIncrementY); }; #endif // __JUCE_MOUSELISTENER_JUCEHEADER__ @@ -17847,71 +9086,24 @@ public: class Component; -/** - Gets informed about changes to a component's hierarchy or position. - - To monitor a component for changes, register a subclass of ComponentListener - with the component using Component::addComponentListener(). - - Be sure to deregister listeners before you delete them! - - @see Component::addComponentListener, Component::removeComponentListener -*/ class JUCE_API ComponentListener { public: - /** Destructor. */ - virtual ~ComponentListener() {} + virtual ~ComponentListener() {} - /** Called when the component's position or size changes. + virtual void componentMovedOrResized (Component& component, + bool wasMoved, + bool wasResized); - @param component the component that was moved or resized - @param wasMoved true if the component's top-left corner has just moved - @param wasResized true if the component's width or height has just changed - @see Component::setBounds, Component::resized, Component::moved - */ - virtual void componentMovedOrResized (Component& component, - bool wasMoved, - bool wasResized); + virtual void componentBroughtToFront (Component& component); - /** Called when the component is brought to the top of the z-order. + virtual void componentVisibilityChanged (Component& component); - @param component the component that was moved - @see Component::toFront, Component::broughtToFront - */ - virtual void componentBroughtToFront (Component& component); + virtual void componentChildrenChanged (Component& component); - /** Called when the component is made visible or invisible. + virtual void componentParentHierarchyChanged (Component& component); - @param component the component that changed - @see Component::setVisible - */ - virtual void componentVisibilityChanged (Component& component); - - /** Called when the component has children added or removed. - - @param component the component whose children were changed - @see Component::childrenChanged, Component::addChildComponent, - Component::removeChildComponent - */ - virtual void componentChildrenChanged (Component& component); - - /** Called to indicate that the component's parents have changed. - - When a component is added or removed from its parent, all of its children - will produce this notification (recursively - so all children of its - children will also be called as well). - - @param component the component that this listener is registered with - @see Component::parentHierarchyChanged - */ - virtual void componentParentHierarchyChanged (Component& component); - - /** Called when the component's name is changed. - - @see Component::setName, Component::getName - */ - virtual void componentNameChanged (Component& component); + virtual void componentNameChanged (Component& component); }; #endif // __JUCE_COMPONENTLISTENER_JUCEHEADER__ @@ -17925,211 +9117,118 @@ public: #ifndef __JUCE_KEYPRESS_JUCEHEADER__ #define __JUCE_KEYPRESS_JUCEHEADER__ -/** - Represents a key press, including any modifier keys that are needed. - - E.g. a KeyPress might represent CTRL+C, SHIFT+ALT+H, Spacebar, Escape, etc. - - @see Component, KeyListener, Button::addShortcut, KeyPressMappingManager -*/ class JUCE_API KeyPress { public: - /** Creates an (invalid) KeyPress. + KeyPress() throw(); - @see isValid - */ - KeyPress() throw(); + KeyPress (const int keyCode, + const ModifierKeys& modifiers, + const juce_wchar textCharacter) throw(); - /** Creates a KeyPress for a key and some modifiers. + KeyPress (const int keyCode) throw(); - e.g. - CTRL+C would be: KeyPress ('c', ModifierKeys::ctrlModifier) - SHIFT+Escape would be: KeyPress (KeyPress::escapeKey, ModifierKeys::shiftModifier) + KeyPress (const KeyPress& other) throw(); - @param keyCode a code that represents the key - this value must be - one of special constants listed in this class, or an - 8-bit character code such as a letter (case is ignored), - digit or a simple key like "," or ".". Note that this - isn't the same as the textCharacter parameter, so for example - a keyCode of 'a' and a shift-key modifier should have a - textCharacter value of 'A'. - @param modifiers the modifiers to associate with the keystroke - @param textCharacter the character that would be printed if someone typed - this keypress into a text editor. This value may be - null if the keypress is a non-printing character - @see getKeyCode, isKeyCode, getModifiers - */ - KeyPress (const int keyCode, - const ModifierKeys& modifiers, - const juce_wchar textCharacter) throw(); + const KeyPress& operator= (const KeyPress& other) throw(); - /** Creates a keypress with a keyCode but no modifiers or text character. - */ - KeyPress (const int keyCode) throw(); + bool operator== (const KeyPress& other) const throw(); - /** Creates a copy of another KeyPress. */ - KeyPress (const KeyPress& other) throw(); + bool operator!= (const KeyPress& other) const throw(); - /** Copies this KeyPress from another one. */ - const KeyPress& operator= (const KeyPress& other) throw(); + bool isValid() const throw() { return keyCode != 0; } - /** Compares two KeyPress objects. */ - bool operator== (const KeyPress& other) const throw(); + int getKeyCode() const throw() { return keyCode; } - /** Compares two KeyPress objects. */ - bool operator!= (const KeyPress& other) const throw(); + const ModifierKeys getModifiers() const throw() { return mods; } - /** Returns true if this is a valid KeyPress. + juce_wchar getTextCharacter() const throw() { return textCharacter; } - A null keypress can be created by the default constructor, in case it's - needed. - */ - bool isValid() const throw() { return keyCode != 0; } + bool isKeyCode (const int keyCodeToCompare) const throw() { return keyCode == keyCodeToCompare; } - /** Returns the key code itself. + static const KeyPress createFromDescription (const String& textVersion) throw(); - This will either be one of the special constants defined in this class, - or an 8-bit character code. - */ - int getKeyCode() const throw() { return keyCode; } + const String getTextDescription() const throw(); - /** Returns the key modifiers. + bool isCurrentlyDown() const throw(); - @see ModifierKeys - */ - const ModifierKeys getModifiers() const throw() { return mods; } + static bool isKeyCurrentlyDown (int keyCode) throw(); - /** Returns the character that is associated with this keypress. + // Key codes + // + // Note that the actual values of these are platform-specific and may change + // without warning, so don't store them anywhere as constants. For persisting/retrieving + // KeyPress objects, use getTextDescription() and createFromDescription() instead. + // - This is the character that you'd expect to see printed if you press this - keypress in a text editor or similar component. - */ - juce_wchar getTextCharacter() const throw() { return textCharacter; } + static const int spaceKey; /**< key-code for the space bar */ + static const int escapeKey; /**< key-code for the escape key */ + static const int returnKey; /**< key-code for the return key*/ + static const int tabKey; /**< key-code for the tab key*/ - /** Checks whether the KeyPress's key is the same as the one provided, without checking - the modifiers. + static const int deleteKey; /**< key-code for the delete key (not backspace) */ + static const int backspaceKey; /**< key-code for the backspace key */ + static const int insertKey; /**< key-code for the insert key */ - The values for key codes can either be one of the special constants defined in - this class, or an 8-bit character code. + static const int upKey; /**< key-code for the cursor-up key */ + static const int downKey; /**< key-code for the cursor-down key */ + static const int leftKey; /**< key-code for the cursor-left key */ + static const int rightKey; /**< key-code for the cursor-right key */ + static const int pageUpKey; /**< key-code for the page-up key */ + static const int pageDownKey; /**< key-code for the page-down key */ + static const int homeKey; /**< key-code for the home key */ + static const int endKey; /**< key-code for the end key */ - @see getKeyCode - */ - bool isKeyCode (const int keyCodeToCompare) const throw() { return keyCode == keyCodeToCompare; } + static const int F1Key; /**< key-code for the F1 key */ + static const int F2Key; /**< key-code for the F2 key */ + static const int F3Key; /**< key-code for the F3 key */ + static const int F4Key; /**< key-code for the F4 key */ + static const int F5Key; /**< key-code for the F5 key */ + static const int F6Key; /**< key-code for the F6 key */ + static const int F7Key; /**< key-code for the F7 key */ + static const int F8Key; /**< key-code for the F8 key */ + static const int F9Key; /**< key-code for the F9 key */ + static const int F10Key; /**< key-code for the F10 key */ + static const int F11Key; /**< key-code for the F11 key */ + static const int F12Key; /**< key-code for the F12 key */ + static const int F13Key; /**< key-code for the F13 key */ + static const int F14Key; /**< key-code for the F14 key */ + static const int F15Key; /**< key-code for the F15 key */ + static const int F16Key; /**< key-code for the F16 key */ - /** Converts a textual key description to a KeyPress. + static const int numberPad0; /**< key-code for the 0 on the numeric keypad. */ + static const int numberPad1; /**< key-code for the 1 on the numeric keypad. */ + static const int numberPad2; /**< key-code for the 2 on the numeric keypad. */ + static const int numberPad3; /**< key-code for the 3 on the numeric keypad. */ + static const int numberPad4; /**< key-code for the 4 on the numeric keypad. */ + static const int numberPad5; /**< key-code for the 5 on the numeric keypad. */ + static const int numberPad6; /**< key-code for the 6 on the numeric keypad. */ + static const int numberPad7; /**< key-code for the 7 on the numeric keypad. */ + static const int numberPad8; /**< key-code for the 8 on the numeric keypad. */ + static const int numberPad9; /**< key-code for the 9 on the numeric keypad. */ - This attempts to decode a textual version of a keypress, e.g. "CTRL + C" or "SPACE". + static const int numberPadAdd; /**< key-code for the add sign on the numeric keypad. */ + static const int numberPadSubtract; /**< key-code for the subtract sign on the numeric keypad. */ + static const int numberPadMultiply; /**< key-code for the multiply sign on the numeric keypad. */ + static const int numberPadDivide; /**< key-code for the divide sign on the numeric keypad. */ + static const int numberPadSeparator; /**< key-code for the comma on the numeric keypad. */ + static const int numberPadDecimalPoint; /**< key-code for the decimal point sign on the numeric keypad. */ + static const int numberPadEquals; /**< key-code for the equals key on the numeric keypad. */ + static const int numberPadDelete; /**< key-code for the delete key on the numeric keypad. */ - This isn't designed to cope with any kind of input, but should be given the - strings that are created by the getTextDescription() method. + static const int playKey; /**< key-code for a multimedia 'play' key, (not all keyboards will have one) */ + static const int stopKey; /**< key-code for a multimedia 'stop' key, (not all keyboards will have one) */ + static const int fastForwardKey; /**< key-code for a multimedia 'fast-forward' key, (not all keyboards will have one) */ + static const int rewindKey; /**< key-code for a multimedia 'rewind' key, (not all keyboards will have one) */ - If the string can't be parsed, the object returned will be invalid. - - @see getTextDescription - */ - static const KeyPress createFromDescription (const String& textVersion) throw(); - - /** Creates a textual description of the key combination. - - e.g. "CTRL + C" or "DELETE". - - To store a keypress in a file, use this method, along with createFromDescription() - to retrieve it later. - */ - const String getTextDescription() const throw(); - - /** Checks whether the user is currently holding down the keys that make up this - KeyPress. - - Note that this will return false if any extra modifier keys are - down - e.g. if the keypress is CTRL+X and the user is actually holding CTRL+ALT+x - then it will be false. - */ - bool isCurrentlyDown() const throw(); - - /** Checks whether a particular key is held down, irrespective of modifiers. - - The values for key codes can either be one of the special constants defined in - this class, or an 8-bit character code. - */ - static bool isKeyCurrentlyDown (int keyCode) throw(); - - // Key codes - // - // Note that the actual values of these are platform-specific and may change - // without warning, so don't store them anywhere as constants. For persisting/retrieving - // KeyPress objects, use getTextDescription() and createFromDescription() instead. - // - - static const int spaceKey; /**< key-code for the space bar */ - static const int escapeKey; /**< key-code for the escape key */ - static const int returnKey; /**< key-code for the return key*/ - static const int tabKey; /**< key-code for the tab key*/ - - static const int deleteKey; /**< key-code for the delete key (not backspace) */ - static const int backspaceKey; /**< key-code for the backspace key */ - static const int insertKey; /**< key-code for the insert key */ - - static const int upKey; /**< key-code for the cursor-up key */ - static const int downKey; /**< key-code for the cursor-down key */ - static const int leftKey; /**< key-code for the cursor-left key */ - static const int rightKey; /**< key-code for the cursor-right key */ - static const int pageUpKey; /**< key-code for the page-up key */ - static const int pageDownKey; /**< key-code for the page-down key */ - static const int homeKey; /**< key-code for the home key */ - static const int endKey; /**< key-code for the end key */ - - static const int F1Key; /**< key-code for the F1 key */ - static const int F2Key; /**< key-code for the F2 key */ - static const int F3Key; /**< key-code for the F3 key */ - static const int F4Key; /**< key-code for the F4 key */ - static const int F5Key; /**< key-code for the F5 key */ - static const int F6Key; /**< key-code for the F6 key */ - static const int F7Key; /**< key-code for the F7 key */ - static const int F8Key; /**< key-code for the F8 key */ - static const int F9Key; /**< key-code for the F9 key */ - static const int F10Key; /**< key-code for the F10 key */ - static const int F11Key; /**< key-code for the F11 key */ - static const int F12Key; /**< key-code for the F12 key */ - static const int F13Key; /**< key-code for the F13 key */ - static const int F14Key; /**< key-code for the F14 key */ - static const int F15Key; /**< key-code for the F15 key */ - static const int F16Key; /**< key-code for the F16 key */ - - static const int numberPad0; /**< key-code for the 0 on the numeric keypad. */ - static const int numberPad1; /**< key-code for the 1 on the numeric keypad. */ - static const int numberPad2; /**< key-code for the 2 on the numeric keypad. */ - static const int numberPad3; /**< key-code for the 3 on the numeric keypad. */ - static const int numberPad4; /**< key-code for the 4 on the numeric keypad. */ - static const int numberPad5; /**< key-code for the 5 on the numeric keypad. */ - static const int numberPad6; /**< key-code for the 6 on the numeric keypad. */ - static const int numberPad7; /**< key-code for the 7 on the numeric keypad. */ - static const int numberPad8; /**< key-code for the 8 on the numeric keypad. */ - static const int numberPad9; /**< key-code for the 9 on the numeric keypad. */ - - static const int numberPadAdd; /**< key-code for the add sign on the numeric keypad. */ - static const int numberPadSubtract; /**< key-code for the subtract sign on the numeric keypad. */ - static const int numberPadMultiply; /**< key-code for the multiply sign on the numeric keypad. */ - static const int numberPadDivide; /**< key-code for the divide sign on the numeric keypad. */ - static const int numberPadSeparator; /**< key-code for the comma on the numeric keypad. */ - static const int numberPadDecimalPoint; /**< key-code for the decimal point sign on the numeric keypad. */ - static const int numberPadEquals; /**< key-code for the equals key on the numeric keypad. */ - static const int numberPadDelete; /**< key-code for the delete key on the numeric keypad. */ - - static const int playKey; /**< key-code for a multimedia 'play' key, (not all keyboards will have one) */ - static const int stopKey; /**< key-code for a multimedia 'stop' key, (not all keyboards will have one) */ - static const int fastForwardKey; /**< key-code for a multimedia 'fast-forward' key, (not all keyboards will have one) */ - static const int rewindKey; /**< key-code for a multimedia 'rewind' key, (not all keyboards will have one) */ - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - int keyCode; - ModifierKeys mods; - juce_wchar textCharacter; + int keyCode; + ModifierKeys mods; + juce_wchar textCharacter; }; #endif // __JUCE_KEYPRESS_JUCEHEADER__ @@ -18137,48 +9236,15 @@ private: class Component; -/** - Receives callbacks when keys are pressed. - - You can add a key listener to a component to be informed when that component - gets key events. See the Component::addListener method for more details. - - @see KeyPress, Component::addKeyListener, KeyPressMappingManager -*/ class JUCE_API KeyListener { public: - /** Destructor. */ - virtual ~KeyListener() {} + virtual ~KeyListener() {} - /** Called to indicate that a key has been pressed. + virtual bool keyPressed (const KeyPress& key, + Component* originatingComponent) = 0; - If your implementation returns true, then the key event is considered to have - been consumed, and will not be passed on to any other components. If it returns - false, then the key will be passed to other components that might want to use it. - - @param key the keystroke, including modifier keys - @param originatingComponent the component that received the key event - @see keyStateChanged, Component::keyPressed - */ - virtual bool keyPressed (const KeyPress& key, - Component* originatingComponent) = 0; - - /** Called when any key is pressed or released. - - When this is called, classes that might be interested in - the state of one or more keys can use KeyPress::isKeyCurrentlyDown() to - check whether their key has changed. - - If your implementation returns true, then the key event is considered to have - been consumed, and will not be passed on to any other components. If it returns - false, then the key will be passed to other components that might want to use it. - - @param originatingComponent the component that received the key event - @param isKeyDown true if a key is being pressed, false if one is being released - @see KeyPress, Component::keyStateChanged - */ - virtual bool keyStateChanged (const bool isKeyDown, Component* originatingComponent); + virtual bool keyStateChanged (const bool isKeyDown, Component* originatingComponent); }; #endif // __JUCE_KEYLISTENER_JUCEHEADER__ @@ -18190,62 +9256,18 @@ public: class Component; -/** - Controls the order in which focus moves between components. - - The default algorithm used by this class to work out the order of traversal - is as follows: - - if two components both have an explicit focus order specified, then the - one with the lowest number comes first (see the Component::setExplicitFocusOrder() - method). - - any component with an explicit focus order greater than 0 comes before ones - that don't have an order specified. - - any unspecified components are traversed in a left-to-right, then top-to-bottom - order. - - If you need traversal in a more customised way, you can create a subclass - of KeyboardFocusTraverser that uses your own algorithm, and use - Component::createFocusTraverser() to create it. - - @see Component::setExplicitFocusOrder, Component::createFocusTraverser -*/ class JUCE_API KeyboardFocusTraverser { public: - KeyboardFocusTraverser(); + KeyboardFocusTraverser(); - /** Destructor. */ - virtual ~KeyboardFocusTraverser(); + virtual ~KeyboardFocusTraverser(); - /** Returns the component that should be given focus after the specified one - when moving "forwards". + virtual Component* getNextComponent (Component* current); - The default implementation will return the next component which is to the - right of or below this one. + virtual Component* getPreviousComponent (Component* current); - This may return 0 if there's no suitable candidate. - */ - virtual Component* getNextComponent (Component* current); - - /** Returns the component that should be given focus after the specified one - when moving "backwards". - - The default implementation will return the next component which is to the - left of or above this one. - - This may return 0 if there's no suitable candidate. - */ - virtual Component* getPreviousComponent (Component* current); - - /** Returns the component that should receive focus be default within the given - parent component. - - The default implementation will just return the foremost child component that - wants focus. - - This may return 0 if there's no suitable candidate. - */ - virtual Component* getDefaultComponent (Component* parentComponent); + virtual Component* getDefaultComponent (Component* parentComponent); }; #endif // __JUCE_KEYBOARDFOCUSTRAVERSER_JUCEHEADER__ @@ -18275,160 +9297,81 @@ public: #ifndef __JUCE_AFFINETRANSFORM_JUCEHEADER__ #define __JUCE_AFFINETRANSFORM_JUCEHEADER__ -/** - Represents a 2D affine-transformation matrix. - - An affine transformation is a transformation such as a rotation, scale, shear, - resize or translation. - - These are used for various 2D transformation tasks, e.g. with Path objects. - - @see Path, Point, Line -*/ class JUCE_API AffineTransform { public: - /** Creates an identity transform. */ - AffineTransform() throw(); + AffineTransform() throw(); - /** Creates a copy of another transform. */ - AffineTransform (const AffineTransform& other) throw(); + AffineTransform (const AffineTransform& other) throw(); - /** Creates a transform from a set of raw matrix values. + AffineTransform (const float mat00, const float mat01, const float mat02, + const float mat10, const float mat11, const float mat12) throw(); - The resulting matrix is: + const AffineTransform& operator= (const AffineTransform& other) throw(); - (mat00 mat01 mat02) - (mat10 mat11 mat12) - ( 0 0 1 ) - */ - AffineTransform (const float mat00, const float mat01, const float mat02, - const float mat10, const float mat11, const float mat12) throw(); + bool operator== (const AffineTransform& other) const throw(); - /** Copies from another AffineTransform object */ - const AffineTransform& operator= (const AffineTransform& other) throw(); + bool operator!= (const AffineTransform& other) const throw(); - /** Compares two transforms. */ - bool operator== (const AffineTransform& other) const throw(); + static const AffineTransform identity; - /** Compares two transforms. */ - bool operator!= (const AffineTransform& other) const throw(); + void transformPoint (float& x, + float& y) const throw(); - /** A ready-to-use identity transform, which you can use to append other - transformations to. + void transformPoint (double& x, + double& y) const throw(); - e.g. @code - AffineTransform myTransform = AffineTransform::identity.rotated (.5f) - .scaled (2.0f); + const AffineTransform translated (const float deltaX, + const float deltaY) const throw(); - @endcode - */ - static const AffineTransform identity; + static const AffineTransform translation (const float deltaX, + const float deltaY) throw(); - /** Transforms a 2D co-ordinate using this matrix. */ - void transformPoint (float& x, - float& y) const throw(); + const AffineTransform rotated (const float angleInRadians) const throw(); - /** Transforms a 2D co-ordinate using this matrix. */ - void transformPoint (double& x, - double& y) const throw(); + const AffineTransform rotated (const float angleInRadians, + const float pivotX, + const float pivotY) const throw(); - /** Returns a new transform which is the same as this one followed by a translation. */ - const AffineTransform translated (const float deltaX, - const float deltaY) const throw(); + static const AffineTransform rotation (const float angleInRadians) throw(); - /** Returns a new transform which is a translation. */ - static const AffineTransform translation (const float deltaX, - const float deltaY) throw(); + static const AffineTransform rotation (const float angleInRadians, + const float pivotX, + const float pivotY) throw(); - /** Returns a transform which is the same as this one followed by a rotation. + const AffineTransform scaled (const float factorX, + const float factorY) const throw(); - The rotation is specified by a number of radians to rotate clockwise, centred around - the origin (0, 0). - */ - const AffineTransform rotated (const float angleInRadians) const throw(); + static const AffineTransform scale (const float factorX, + const float factorY) throw(); - /** Returns a transform which is the same as this one followed by a rotation about a given point. + const AffineTransform sheared (const float shearX, + const float shearY) const throw(); - The rotation is specified by a number of radians to rotate clockwise, centred around - the co-ordinates passed in. - */ - const AffineTransform rotated (const float angleInRadians, - const float pivotX, - const float pivotY) const throw(); + const AffineTransform inverted() const throw(); - /** Returns a new transform which is a rotation about (0, 0). */ - static const AffineTransform rotation (const float angleInRadians) throw(); + const AffineTransform followedBy (const AffineTransform& other) const throw(); - /** Returns a new transform which is a rotation about a given point. */ - static const AffineTransform rotation (const float angleInRadians, - const float pivotX, - const float pivotY) throw(); + bool isIdentity() const throw(); - /** Returns a transform which is the same as this one followed by a re-scaling. + bool isSingularity() const throw(); - The scaling is centred around the origin (0, 0). - */ - const AffineTransform scaled (const float factorX, - const float factorY) const throw(); + bool isOnlyTranslation() const throw(); - /** Returns a new transform which is a re-scale about the origin. */ - static const AffineTransform scale (const float factorX, - const float factorY) throw(); + float getTranslationX() const throw() { return mat02; } - /** Returns a transform which is the same as this one followed by a shear. + float getTranslationY() const throw() { return mat12; } - The shear is centred around the origin (0, 0). - */ - const AffineTransform sheared (const float shearX, - const float shearY) const throw(); + juce_UseDebuggingNewOperator - /** Returns a matrix which is the inverse operation of this one. - - Some matrices don't have an inverse - in this case, the method will just return - an identity transform. - */ - const AffineTransform inverted() const throw(); - - /** Returns the result of concatenating another transformation after this one. */ - const AffineTransform followedBy (const AffineTransform& other) const throw(); - - /** Returns true if this transform has no effect on points. */ - bool isIdentity() const throw(); - - /** Returns true if this transform maps to a singularity - i.e. if it has no inverse. */ - bool isSingularity() const throw(); - - /** Returns true if the transform only translates, and doesn't scale or rotate the - points. */ - bool isOnlyTranslation() const throw(); - - /** If this transform is only a translation, this returns the X offset. - @see isOnlyTranslation - */ - float getTranslationX() const throw() { return mat02; } - - /** If this transform is only a translation, this returns the X offset. - @see isOnlyTranslation - */ - float getTranslationY() const throw() { return mat12; } - - juce_UseDebuggingNewOperator - - /* The transform matrix is: - - (mat00 mat01 mat02) - (mat10 mat11 mat12) - ( 0 0 1 ) - */ - float mat00, mat01, mat02; - float mat10, mat11, mat12; + float mat00, mat01, mat02; + float mat10, mat11, mat12; private: - const AffineTransform followedBy (const float mat00, const float mat01, const float mat02, - const float mat10, const float mat11, const float mat12) const throw(); + const AffineTransform followedBy (const float mat00, const float mat01, const float mat02, + const float mat10, const float mat11, const float mat12) const throw(); }; #endif // __JUCE_AFFINETRANSFORM_JUCEHEADER__ @@ -18438,54 +9381,33 @@ private: #ifndef __JUCE_POINT_JUCEHEADER__ #define __JUCE_POINT_JUCEHEADER__ -/** - A pair of (x, y) co-ordinates. - - Uses 32-bit floating point accuracy. - - @see Line, Path, AffineTransform -*/ class JUCE_API Point { public: - /** Creates a point with co-ordinates (0, 0). */ - Point() throw(); + Point() throw(); - /** Creates a copy of another point. */ - Point (const Point& other) throw(); + Point (const Point& other) throw(); - /** Creates a point from an (x, y) position. */ - Point (const float x, const float y) throw(); + Point (const float x, const float y) throw(); - /** Copies this point from another one. - @see setXY - */ - const Point& operator= (const Point& other) throw(); + const Point& operator= (const Point& other) throw(); - /** Destructor. */ - ~Point() throw(); + ~Point() throw(); - /** Returns the point's x co-ordinate. */ - inline float getX() const throw() { return x; } + inline float getX() const throw() { return x; } - /** Returns the point's y co-ordinate. */ - inline float getY() const throw() { return y; } + inline float getY() const throw() { return y; } - /** Changes the point's x and y co-ordinates. */ - void setXY (const float x, - const float y) throw(); + void setXY (const float x, + const float y) throw(); - /** Uses a transform to change the point's co-ordinates. + void applyTransform (const AffineTransform& transform) throw(); - @see AffineTransform::transformPoint - */ - void applyTransform (const AffineTransform& transform) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - float x, y; + float x, y; }; #endif // __JUCE_POINT_JUCEHEADER__ @@ -18495,226 +9417,108 @@ private: #ifndef __JUCE_RECTANGLE_JUCEHEADER__ #define __JUCE_RECTANGLE_JUCEHEADER__ -/** - A rectangle, specified using integer co-ordinates. - - @see RectangleList, Path, Line, Point -*/ class JUCE_API Rectangle { public: - /** Creates a rectangle of zero size. + Rectangle() throw(); - The default co-ordinates will be (0, 0, 0, 0). - */ - Rectangle() throw(); + Rectangle (const Rectangle& other) throw(); - /** Creates a copy of another rectangle. */ - Rectangle (const Rectangle& other) throw(); + Rectangle (const int x, const int y, + const int width, const int height) throw(); - /** Creates a rectangle with a given position and size. */ - Rectangle (const int x, const int y, - const int width, const int height) throw(); + Rectangle (const int width, const int height) throw(); - /** Creates a rectangle with a given size, and a position of (0, 0). */ - Rectangle (const int width, const int height) throw(); + ~Rectangle() throw(); - /** Destructor. */ - ~Rectangle() throw(); + inline int getX() const throw() { return x; } - /** Returns the x co-ordinate of the rectangle's left-hand-side. */ - inline int getX() const throw() { return x; } + inline int getY() const throw() { return y; } - /** Returns the y co-ordinate of the rectangle's top edge. */ - inline int getY() const throw() { return y; } + inline int getWidth() const throw() { return w; } - /** Returns the width of the rectangle. */ - inline int getWidth() const throw() { return w; } + inline int getHeight() const throw() { return h; } - /** Returns the height of the rectangle. */ - inline int getHeight() const throw() { return h; } + inline int getRight() const throw() { return x + w; } - /** Returns the x co-ordinate of the rectangle's right-hand-side. */ - inline int getRight() const throw() { return x + w; } + inline int getBottom() const throw() { return y + h; } - /** Returns the y co-ordinate of the rectangle's bottom edge. */ - inline int getBottom() const throw() { return y + h; } + inline int getCentreX() const throw() { return x + (w >> 1); } - /** Returns the x co-ordinate of the rectangle's centre. */ - inline int getCentreX() const throw() { return x + (w >> 1); } + inline int getCentreY() const throw() { return y + (h >> 1); } - /** Returns the y co-ordinate of the rectangle's centre. */ - inline int getCentreY() const throw() { return y + (h >> 1); } + bool isEmpty() const throw(); - /** Returns true if the rectangle's width and height are both zero or less */ - bool isEmpty() const throw(); + void setPosition (const int x, const int y) throw(); - /** Changes the position of the rectangle's top-left corner (leaving its size unchanged). */ - void setPosition (const int x, const int y) throw(); + void setSize (const int w, const int h) throw(); - /** Changes the rectangle's size, leaving the position of its top-left corner unchanged. */ - void setSize (const int w, const int h) throw(); + void setBounds (const int newX, const int newY, + const int newWidth, const int newHeight) throw(); - /** Changes all the rectangle's co-ordinates. */ - void setBounds (const int newX, const int newY, - const int newWidth, const int newHeight) throw(); + void setWidth (const int newWidth) throw(); - /** Changes the rectangle's width */ - void setWidth (const int newWidth) throw(); + void setHeight (const int newHeight) throw(); - /** Changes the rectangle's height */ - void setHeight (const int newHeight) throw(); + void setLeft (const int newLeft) throw(); - /** Moves the x position, adjusting the width so that the right-hand edge remains in the same place. - If the x is moved to be on the right of the current right-hand edge, the width will be set to zero. - */ - void setLeft (const int newLeft) throw(); + void setTop (const int newTop) throw(); - /** Moves the y position, adjusting the height so that the bottom edge remains in the same place. - If the y is moved to be below the current bottom edge, the height will be set to zero. - */ - void setTop (const int newTop) throw(); + void setRight (const int newRight) throw(); - /** Adjusts the width so that the right-hand edge of the rectangle has this new value. - If the new right is below the current X value, the X will be pushed down to match it. - @see getRight - */ - void setRight (const int newRight) throw(); + void setBottom (const int newBottom) throw(); - /** Adjusts the height so that the bottom edge of the rectangle has this new value. - If the new bottom is lower than the current Y value, the Y will be pushed down to match it. - @see getBottom - */ - void setBottom (const int newBottom) throw(); + void translate (const int deltaX, + const int deltaY) throw(); - /** Moves the rectangle's position by adding amount to its x and y co-ordinates. */ - void translate (const int deltaX, - const int deltaY) throw(); + const Rectangle translated (const int deltaX, + const int deltaY) const throw(); - /** Returns a rectangle which is the same as this one moved by a given amount. */ - const Rectangle translated (const int deltaX, - const int deltaY) const throw(); + void expand (const int deltaX, + const int deltaY) throw(); - /** Expands the rectangle by a given amount. + const Rectangle expanded (const int deltaX, + const int deltaY) const throw(); - Effectively, its new size is (x - deltaX, y - deltaY, w + deltaX * 2, h + deltaY * 2). - @see expanded, reduce, reduced - */ - void expand (const int deltaX, - const int deltaY) throw(); + void reduce (const int deltaX, + const int deltaY) throw(); - /** Returns a rectangle that is larger than this one by a given amount. + const Rectangle reduced (const int deltaX, + const int deltaY) const throw(); - Effectively, the rectangle returned is (x - deltaX, y - deltaY, w + deltaX * 2, h + deltaY * 2). - @see expand, reduce, reduced - */ - const Rectangle expanded (const int deltaX, - const int deltaY) const throw(); + bool operator== (const Rectangle& other) const throw(); - /** Shrinks the rectangle by a given amount. + bool operator!= (const Rectangle& other) const throw(); - Effectively, its new size is (x + deltaX, y + deltaY, w - deltaX * 2, h - deltaY * 2). - @see reduced, expand, expanded - */ - void reduce (const int deltaX, - const int deltaY) throw(); + bool contains (const int x, const int y) const throw(); - /** Returns a rectangle that is smaller than this one by a given amount. + bool contains (const Rectangle& other) const throw(); - Effectively, the rectangle returned is (x + deltaX, y + deltaY, w - deltaX * 2, h - deltaY * 2). - @see reduce, expand, expanded - */ - const Rectangle reduced (const int deltaX, - const int deltaY) const throw(); + bool intersects (const Rectangle& other) const throw(); - /** Returns true if the two rectangles are identical. */ - bool operator== (const Rectangle& other) const throw(); + const Rectangle getIntersection (const Rectangle& other) const throw(); - /** Returns true if the two rectangles are not identical. */ - bool operator!= (const Rectangle& other) const throw(); + bool intersectRectangle (int& x, int& y, int& w, int& h) const throw(); - /** Returns true if this co-ordinate is inside the rectangle. */ - bool contains (const int x, const int y) const throw(); + const Rectangle getUnion (const Rectangle& other) const throw(); - /** Returns true if this other rectangle is completely inside this one. */ - bool contains (const Rectangle& other) const throw(); + bool enlargeIfAdjacent (const Rectangle& other) throw(); - /** Returns true if any part of another rectangle overlaps this one. */ - bool intersects (const Rectangle& other) const throw(); + bool reduceIfPartlyContainedIn (const Rectangle& other) throw(); - /** Returns the region that is the overlap between this and another rectangle. + static bool intersectRectangles (int& x1, int& y1, int& w1, int& h1, + int x2, int y2, int w2, int h2) throw(); - If the two rectangles don't overlap, the rectangle returned will be empty. - */ - const Rectangle getIntersection (const Rectangle& other) const throw(); + const String toString() const throw(); - /** Clips a rectangle so that it lies only within this one. + static const Rectangle fromString (const String& stringVersion); - This is a non-static version of intersectRectangles(). - - Returns false if the two regions didn't overlap. - */ - bool intersectRectangle (int& x, int& y, int& w, int& h) const throw(); - - /** Returns the smallest rectangle that contains both this one and the one - passed-in. - */ - const Rectangle getUnion (const Rectangle& other) const throw(); - - /** If this rectangle merged with another one results in a simple rectangle, this - will set this rectangle to the result, and return true. - - Returns false and does nothing to this rectangle if the two rectangles don't overlap, - or if they form a complex region. - */ - bool enlargeIfAdjacent (const Rectangle& other) throw(); - - /** If after removing another rectangle from this one the result is a simple rectangle, - this will set this object's bounds to be the result, and return true. - - Returns false and does nothing to this rectangle if the two rectangles don't overlap, - or if removing the other one would form a complex region. - */ - bool reduceIfPartlyContainedIn (const Rectangle& other) throw(); - - /** Static utility to intersect two sets of rectangular co-ordinates. - - Returns false if the two regions didn't overlap. - - @see intersectRectangle - */ - static bool intersectRectangles (int& x1, int& y1, int& w1, int& h1, - int x2, int y2, int w2, int h2) throw(); - - /** Creates a string describing this rectangle. - - The string will be of the form "x y width height", e.g. "100 100 400 200". - - Coupled with the fromString() method, this is very handy for things like - storing rectangles (particularly component positions) in XML attributes. - - @see fromString - */ - const String toString() const throw(); - - /** Parses a string containing a rectangle's details. - - The string should contain 4 integer tokens, in the form "x y width height". They - can be comma or whitespace separated. - - This method is intended to go with the toString() method, to form an easy way - of saving/loading rectangles as strings. - - @see toString - */ - static const Rectangle fromString (const String& stringVersion); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class RectangleList; - int x, y, w, h; + friend class RectangleList; + int x, y, w, h; }; #endif // __JUCE_RECTANGLE_JUCEHEADER__ @@ -18724,139 +9528,68 @@ private: #ifndef __JUCE_JUSTIFICATION_JUCEHEADER__ #define __JUCE_JUSTIFICATION_JUCEHEADER__ -/** - Represents a type of justification to be used when positioning graphical items. - - e.g. it indicates whether something should be placed top-left, top-right, - centred, etc. - - It is used in various places wherever this kind of information is needed. -*/ class JUCE_API Justification { public: - /** Creates a Justification object using a combination of flags. */ - inline Justification (const int flags_) throw() : flags (flags_) {} + inline Justification (const int flags_) throw() : flags (flags_) {} - /** Creates a copy of another Justification object. */ - Justification (const Justification& other) throw(); + Justification (const Justification& other) throw(); - /** Copies another Justification object. */ - const Justification& operator= (const Justification& other) throw(); + const Justification& operator= (const Justification& other) throw(); - /** Returns the raw flags that are set for this Justification object. */ - inline int getFlags() const throw() { return flags; } + inline int getFlags() const throw() { return flags; } - /** Tests a set of flags for this object. + inline bool testFlags (const int flagsToTest) const throw() { return (flags & flagsToTest) != 0; } - @returns true if any of the flags passed in are set on this object. - */ - inline bool testFlags (const int flagsToTest) const throw() { return (flags & flagsToTest) != 0; } + int getOnlyVerticalFlags() const throw(); - /** Returns just the flags from this object that deal with vertical layout. */ - int getOnlyVerticalFlags() const throw(); + int getOnlyHorizontalFlags() const throw(); - /** Returns just the flags from this object that deal with horizontal layout. */ - int getOnlyHorizontalFlags() const throw(); + void applyToRectangle (int& x, int& y, + const int w, const int h, + const int spaceX, const int spaceY, + const int spaceW, const int spaceH) const throw(); - /** Adjusts the position of a rectangle to fit it into a space. + enum + { - The (x, y) position of the rectangle will be updated to position it inside the - given space according to the justification flags. - */ - void applyToRectangle (int& x, int& y, - const int w, const int h, - const int spaceX, const int spaceY, - const int spaceW, const int spaceH) const throw(); + left = 1, - /** Flag values that can be combined and used in the constructor. */ - enum - { + right = 2, - /** Indicates that the item should be aligned against the left edge of the available space. */ - left = 1, + horizontallyCentred = 4, - /** Indicates that the item should be aligned against the right edge of the available space. */ - right = 2, + top = 8, - /** Indicates that the item should be placed in the centre between the left and right - sides of the available space. */ - horizontallyCentred = 4, + bottom = 16, - /** Indicates that the item should be aligned against the top edge of the available space. */ - top = 8, + verticallyCentred = 32, - /** Indicates that the item should be aligned against the bottom edge of the available space. */ - bottom = 16, + horizontallyJustified = 64, - /** Indicates that the item should be placed in the centre between the top and bottom - sides of the available space. */ - verticallyCentred = 32, + centred = 36, - /** Indicates that lines of text should be spread out to fill the maximum width - available, so that both margins are aligned vertically. - */ - horizontallyJustified = 64, + centredLeft = 33, - /** Indicates that the item should be centred vertically and horizontally. + centredRight = 34, - This is equivalent to (horizontallyCentred | verticallyCentred) - */ - centred = 36, + centredTop = 12, - /** Indicates that the item should be centred vertically but placed on the left hand side. + centredBottom = 20, - This is equivalent to (left | verticallyCentred) - */ - centredLeft = 33, + topLeft = 9, - /** Indicates that the item should be centred vertically but placed on the right hand side. + topRight = 10, - This is equivalent to (right | verticallyCentred) - */ - centredRight = 34, + bottomLeft = 17, - /** Indicates that the item should be centred horizontally and placed at the top. - - This is equivalent to (horizontallyCentred | top) - */ - centredTop = 12, - - /** Indicates that the item should be centred horizontally and placed at the bottom. - - This is equivalent to (horizontallyCentred | bottom) - */ - centredBottom = 20, - - /** Indicates that the item should be placed in the top-left corner. - - This is equivalent to (left | top) - */ - topLeft = 9, - - /** Indicates that the item should be placed in the top-right corner. - - This is equivalent to (right | top) - */ - topRight = 10, - - /** Indicates that the item should be placed in the bottom-left corner. - - This is equivalent to (left | bottom) - */ - bottomLeft = 17, - - /** Indicates that the item should be placed in the bottom-left corner. - - This is equivalent to (right | bottom) - */ - bottomRight = 18 - }; + bottomRight = 18 + }; private: - int flags; + int flags; }; #endif // __JUCE_JUSTIFICATION_JUCEHEADER__ @@ -18870,171 +9603,130 @@ class Path; class RectangleList; class Image; -/** - A table of horizontal scan-line segments - used for rasterising Paths. - - @see Path, Graphics -*/ class JUCE_API EdgeTable { public: - /** Creates an edge table containing a path. + EdgeTable (const Rectangle& clipLimits, + const Path& pathToAdd, + const AffineTransform& transform) throw(); - A table is created with a fixed vertical range, and only sections of the path - which lie within this range will be added to the table. + EdgeTable (const Rectangle& rectangleToAdd) throw(); - @param clipLimits only the region of the path that lies within this area will be added - @param pathToAdd the path to add to the table - @param transform a transform to apply to the path being added - */ - EdgeTable (const Rectangle& clipLimits, - const Path& pathToAdd, - const AffineTransform& transform) throw(); + EdgeTable (const RectangleList& rectanglesToAdd) throw(); - /** Creates an edge table containing a rectangle. - */ - EdgeTable (const Rectangle& rectangleToAdd) throw(); + EdgeTable (const float x, const float y, + const float w, const float h) throw(); - /** Creates an edge table containing a rectangle list. - */ - EdgeTable (const RectangleList& rectanglesToAdd) throw(); + EdgeTable (const EdgeTable& other) throw(); - /** Creates an edge table containing a rectangle. - */ - EdgeTable (const float x, const float y, - const float w, const float h) throw(); + const EdgeTable& operator= (const EdgeTable& other) throw(); - /** Creates a copy of another edge table. */ - EdgeTable (const EdgeTable& other) throw(); + ~EdgeTable() throw(); - /** Copies from another edge table. */ - const EdgeTable& operator= (const EdgeTable& other) throw(); + void clipToRectangle (const Rectangle& r) throw(); + void excludeRectangle (const Rectangle& r) throw(); + void clipToEdgeTable (const EdgeTable& other); + void clipLineToMask (int x, int y, uint8* mask, int maskStride, int numPixels) throw(); + bool isEmpty() throw(); + const Rectangle& getMaximumBounds() const throw() { return bounds; } + void translate (float dx, int dy) throw(); - /** Destructor. */ - ~EdgeTable() throw(); + void optimiseTable() throw(); - void clipToRectangle (const Rectangle& r) throw(); - void excludeRectangle (const Rectangle& r) throw(); - void clipToEdgeTable (const EdgeTable& other); - void clipLineToMask (int x, int y, uint8* mask, int maskStride, int numPixels) throw(); - bool isEmpty() throw(); - const Rectangle& getMaximumBounds() const throw() { return bounds; } - void translate (float dx, int dy) throw(); + template + void iterate (EdgeTableIterationCallback& iterationCallback) const throw() + { + const int* lineStart = table; - /** Reduces the amount of space the table has allocated. + for (int y = 0; y < bounds.getHeight(); ++y) + { + const int* line = lineStart; + lineStart += lineStrideElements; + int numPoints = line[0]; - This will shrink the table down to use as little memory as possible - useful for - read-only tables that get stored and re-used for rendering. - */ - void optimiseTable() throw(); + if (--numPoints > 0) + { + int x = *++line; + jassert ((x >> 8) >= bounds.getX() && (x >> 8) < bounds.getRight()); + int levelAccumulator = 0; - /** Iterates the lines in the table, for rendering. + iterationCallback.setEdgeTableYPos (bounds.getY() + y); - This function will iterate each line in the table, and call a user-defined class - to render each pixel or continuous line of pixels that the table contains. + while (--numPoints >= 0) + { + const int level = *++line; + jassert (((unsigned int) level) < (unsigned int) 256); + const int endX = *++line; + jassert (endX >= x); + const int endOfRun = (endX >> 8); - @param iterationCallback this templated class must contain the following methods: - @code - inline void setEdgeTableYPos (int y); - inline void handleEdgeTablePixel (int x, int alphaLevel) const; - inline void handleEdgeTableLine (int x, int width, int alphaLevel) const; - @endcode - (these don't necessarily have to be 'const', but it might help it go faster) - */ - template - void iterate (EdgeTableIterationCallback& iterationCallback) const throw() - { - const int* lineStart = table; + if (endOfRun == (x >> 8)) + { + // small segment within the same pixel, so just save it for the next + // time round.. + levelAccumulator += (endX - x) * level; + } + else + { + // plot the fist pixel of this segment, including any accumulated + // levels from smaller segments that haven't been drawn yet + levelAccumulator += (0xff - (x & 0xff)) * level; + levelAccumulator >>= 8; + x >>= 8; - for (int y = 0; y < bounds.getHeight(); ++y) - { - const int* line = lineStart; - lineStart += lineStrideElements; - int numPoints = line[0]; + if (levelAccumulator > 0) + { + if (levelAccumulator >> 8) + levelAccumulator = 0xff; - if (--numPoints > 0) - { - int x = *++line; - jassert ((x >> 8) >= bounds.getX() && (x >> 8) < bounds.getRight()); - int levelAccumulator = 0; + iterationCallback.handleEdgeTablePixel (x, levelAccumulator); + } - iterationCallback.setEdgeTableYPos (bounds.getY() + y); + // if there's a run of similar pixels, do it all in one go.. + if (level > 0) + { + jassert (endOfRun <= bounds.getRight()); + const int numPix = endOfRun - ++x; - while (--numPoints >= 0) - { - const int level = *++line; - jassert (((unsigned int) level) < (unsigned int) 256); - const int endX = *++line; - jassert (endX >= x); - const int endOfRun = (endX >> 8); + if (numPix > 0) + iterationCallback.handleEdgeTableLine (x, numPix, level); + } - if (endOfRun == (x >> 8)) - { - // small segment within the same pixel, so just save it for the next - // time round.. - levelAccumulator += (endX - x) * level; - } - else - { - // plot the fist pixel of this segment, including any accumulated - // levels from smaller segments that haven't been drawn yet - levelAccumulator += (0xff - (x & 0xff)) * level; - levelAccumulator >>= 8; - x >>= 8; + // save the bit at the end to be drawn next time round the loop. + levelAccumulator = (endX & 0xff) * level; + } - if (levelAccumulator > 0) - { - if (levelAccumulator >> 8) - levelAccumulator = 0xff; + x = endX; + } - iterationCallback.handleEdgeTablePixel (x, levelAccumulator); - } + if (levelAccumulator > 0) + { + levelAccumulator >>= 8; + if (levelAccumulator >> 8) + levelAccumulator = 0xff; - // if there's a run of similar pixels, do it all in one go.. - if (level > 0) - { - jassert (endOfRun <= bounds.getRight()); - const int numPix = endOfRun - ++x; + x >>= 8; + jassert (x >= bounds.getX() && x < bounds.getRight()); + iterationCallback.handleEdgeTablePixel (x, levelAccumulator); + } + } + } + } - if (numPix > 0) - iterationCallback.handleEdgeTableLine (x, numPix, level); - } - - // save the bit at the end to be drawn next time round the loop. - levelAccumulator = (endX & 0xff) * level; - } - - x = endX; - } - - if (levelAccumulator > 0) - { - levelAccumulator >>= 8; - if (levelAccumulator >> 8) - levelAccumulator = 0xff; - - x >>= 8; - jassert (x >= bounds.getX() && x < bounds.getRight()); - iterationCallback.handleEdgeTablePixel (x, levelAccumulator); - } - } - } - } - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - // table line format: number of points; point0 x, point0 levelDelta, point1 x, point1 levelDelta, etc - HeapBlock table; - Rectangle bounds; - int maxEdgesPerLine, lineStrideElements; - bool needToCheckEmptinesss; + // table line format: number of points; point0 x, point0 levelDelta, point1 x, point1 levelDelta, etc + HeapBlock table; + Rectangle bounds; + int maxEdgesPerLine, lineStrideElements; + bool needToCheckEmptinesss; - void addEdgePoint (const int x, const int y, const int winding) throw(); - void remapTableForNumEdges (const int newNumEdgesPerLine) throw(); - void intersectWithEdgeTableLine (const int y, const int* otherLine) throw(); - void sanitiseLevels (const bool useNonZeroWinding) throw(); + void addEdgePoint (const int x, const int y, const int winding) throw(); + void remapTableForNumEdges (const int newNumEdgesPerLine) throw(); + void intersectWithEdgeTableLine (const int y, const int* otherLine) throw(); + void sanitiseLevels (const bool useNonZeroWinding) throw(); }; #endif // __JUCE_EDGETABLE_JUCEHEADER__ @@ -19042,597 +9734,210 @@ private: class Image; -/** - A path is a sequence of lines and curves that may either form a closed shape - or be open-ended. - - To use a path, you can create an empty one, then add lines and curves to it - to create shapes, then it can be rendered by a Graphics context or used - for geometric operations. - - e.g. @code - Path myPath; - - myPath.startNewSubPath (10.0f, 10.0f); // move the current position to (10, 10) - myPath.lineTo (100.0f, 200.0f); // draw a line from here to (100, 200) - myPath.quadraticTo (0.0f, 150.0f, 5.0f, 50.0f); // draw a curve that ends at (5, 50) - myPath.closeSubPath(); // close the subpath with a line back to (10, 10) - - // add an ellipse as well, which will form a second sub-path within the path.. - myPath.addEllipse (50.0f, 50.0f, 40.0f, 30.0f); - - // double the width of the whole thing.. - myPath.applyTransform (AffineTransform::scale (2.0f, 1.0f)); - - // and draw it to a graphics context with a 5-pixel thick outline. - g.strokePath (myPath, PathStrokeType (5.0f)); - - @endcode - - A path object can actually contain multiple sub-paths, which may themselves - be open or closed. - - @see PathFlatteningIterator, PathStrokeType, Graphics -*/ class JUCE_API Path { public: - /** Creates an empty path. */ - Path() throw(); + Path() throw(); - /** Creates a copy of another path. */ - Path (const Path& other) throw(); + Path (const Path& other) throw(); - /** Destructor. */ - ~Path() throw(); + ~Path() throw(); - /** Copies this path from another one. */ - const Path& operator= (const Path& other) throw(); + const Path& operator= (const Path& other) throw(); - /** Returns true if the path doesn't contain any lines or curves. */ - bool isEmpty() const throw(); + bool isEmpty() const throw(); - /** Returns the smallest rectangle that contains all points within the path. - */ - void getBounds (float& x, float& y, - float& w, float& h) const throw(); + void getBounds (float& x, float& y, + float& w, float& h) const throw(); - /** Returns the smallest rectangle that contains all points within the path - after it's been transformed with the given tranasform matrix. - */ - void getBoundsTransformed (const AffineTransform& transform, - float& x, float& y, - float& w, float& h) const throw(); + void getBoundsTransformed (const AffineTransform& transform, + float& x, float& y, + float& w, float& h) const throw(); - /** Checks whether a point lies within the path. + bool contains (const float x, + const float y, + const float tolerence = 10.0f) const throw(); - This is only relevent for closed paths (see closeSubPath()), and - may produce false results if used on a path which has open sub-paths. + bool intersectsLine (const float x1, const float y1, + const float x2, const float y2, + const float tolerence = 10.0f) throw(); - The path's winding rule is taken into account by this method. + void clear() throw(); - The tolerence parameter is passed to the PathFlatteningIterator that - is used to trace the path - for more info about it, see the notes for - the PathFlatteningIterator constructor. + void startNewSubPath (const float startX, + const float startY) throw(); - @see closeSubPath, setUsingNonZeroWinding - */ - bool contains (const float x, - const float y, - const float tolerence = 10.0f) const throw(); + void closeSubPath() throw(); - /** Checks whether a line crosses the path. + void lineTo (const float endX, + const float endY) throw(); - This will return positive if the line crosses any of the paths constituent - lines or curves. It doesn't take into account whether the line is inside - or outside the path, or whether the path is open or closed. + void quadraticTo (const float controlPointX, + const float controlPointY, + const float endPointX, + const float endPointY) throw(); - The tolerence parameter is passed to the PathFlatteningIterator that - is used to trace the path - for more info about it, see the notes for - the PathFlatteningIterator constructor. - */ - bool intersectsLine (const float x1, const float y1, - const float x2, const float y2, - const float tolerence = 10.0f) throw(); + void cubicTo (const float controlPoint1X, + const float controlPoint1Y, + const float controlPoint2X, + const float controlPoint2Y, + const float endPointX, + const float endPointY) throw(); - /** Removes all lines and curves, resetting the path completely. */ - void clear() throw(); + const Point getCurrentPosition() const; - /** Begins a new subpath with a given starting position. + void addRectangle (const float x, const float y, + const float w, const float h) throw(); - This will move the path's current position to the co-ordinates passed in and - make it ready to draw lines or curves starting from this position. + void addRectangle (const Rectangle& rectangle) throw(); - After adding whatever lines and curves are needed, you can either - close the current sub-path using closeSubPath() or call startNewSubPath() - to move to a new sub-path, leaving the old one open-ended. + void addRoundedRectangle (const float x, const float y, + const float w, const float h, + float cornerSize) throw(); - @see lineTo, quadraticTo, cubicTo, closeSubPath - */ - void startNewSubPath (const float startX, - const float startY) throw(); + void addRoundedRectangle (const float x, const float y, + const float w, const float h, + float cornerSizeX, + float cornerSizeY) throw(); - /** Closes a the current sub-path with a line back to its start-point. + void addTriangle (const float x1, const float y1, + const float x2, const float y2, + const float x3, const float y3) throw(); - When creating a closed shape such as a triangle, don't use 3 lineTo() - calls - instead use two lineTo() calls, followed by a closeSubPath() - to join the final point back to the start. + void addQuadrilateral (const float x1, const float y1, + const float x2, const float y2, + const float x3, const float y3, + const float x4, const float y4) throw(); - This ensures that closes shapes are recognised as such, and this is - important for tasks like drawing strokes, which needs to know whether to - draw end-caps or not. + void addEllipse (const float x, const float y, + const float width, const float height) throw(); - @see startNewSubPath, lineTo, quadraticTo, cubicTo, closeSubPath - */ - void closeSubPath() throw(); + void addArc (const float x, const float y, + const float width, const float height, + const float fromRadians, + const float toRadians, + const bool startAsNewSubPath = false) throw(); - /** Adds a line from the shape's last position to a new end-point. + void addCentredArc (const float centreX, const float centreY, + const float radiusX, const float radiusY, + const float rotationOfEllipse, + const float fromRadians, + const float toRadians, + const bool startAsNewSubPath = false) throw(); - This will connect the end-point of the last line or curve that was added - to a new point, using a straight line. + void addPieSegment (const float x, const float y, + const float width, const float height, + const float fromRadians, + const float toRadians, + const float innerCircleProportionalSize); - See the class description for an example of how to add lines and curves to a path. + void addLineSegment (const float startX, const float startY, + const float endX, const float endY, + float lineThickness) throw(); - @see startNewSubPath, quadraticTo, cubicTo, closeSubPath - */ - void lineTo (const float endX, - const float endY) throw(); + void addArrow (const float startX, const float startY, + const float endX, const float endY, + float lineThickness, + float arrowheadWidth, + float arrowheadLength) throw(); - /** Adds a quadratic bezier curve from the shape's last position to a new position. + void addStar (const float centreX, + const float centreY, + const int numberOfPoints, + const float innerRadius, + const float outerRadius, + const float startAngle = 0.0f); - This will connect the end-point of the last line or curve that was added - to a new point, using a quadratic spline with one control-point. + void addBubble (float bodyX, float bodyY, + float bodyW, float bodyH, + float cornerSize, + float arrowTipX, + float arrowTipY, + int whichSide, + float arrowPositionAlongEdgeProportional, + float arrowWidth); - See the class description for an example of how to add lines and curves to a path. + void addPath (const Path& pathToAppend) throw(); - @see startNewSubPath, lineTo, cubicTo, closeSubPath - */ - void quadraticTo (const float controlPointX, - const float controlPointY, - const float endPointX, - const float endPointY) throw(); + void addPath (const Path& pathToAppend, + const AffineTransform& transformToApply) throw(); - /** Adds a cubic bezier curve from the shape's last position to a new position. + void swapWithPath (Path& other); - This will connect the end-point of the last line or curve that was added - to a new point, using a cubic spline with two control-points. + void applyTransform (const AffineTransform& transform) throw(); - See the class description for an example of how to add lines and curves to a path. + void scaleToFit (const float x, const float y, + const float width, const float height, + const bool preserveProportions) throw(); - @see startNewSubPath, lineTo, quadraticTo, closeSubPath - */ - void cubicTo (const float controlPoint1X, - const float controlPoint1Y, - const float controlPoint2X, - const float controlPoint2Y, - const float endPointX, - const float endPointY) throw(); + const AffineTransform getTransformToScaleToFit (const float x, const float y, + const float width, const float height, + const bool preserveProportions, + const Justification& justificationType = Justification::centred) const throw(); - /** Returns the last point that was added to the path by one of the drawing methods. - */ - const Point getCurrentPosition() const; + const Path createPathWithRoundedCorners (const float cornerRadius) const throw(); - /** Adds a rectangle to the path. + void setUsingNonZeroWinding (const bool isNonZeroWinding) throw(); - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). + bool isUsingNonZeroWinding() const { return useNonZeroWinding; } - @see addRoundedRectangle, addTriangle - */ - void addRectangle (const float x, const float y, - const float w, const float h) throw(); + class JUCE_API Iterator + { + public: - /** Adds a rectangle to the path. + Iterator (const Path& path); + ~Iterator(); - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). + bool next(); - @see addRoundedRectangle, addTriangle - */ - void addRectangle (const Rectangle& rectangle) throw(); + enum PathElementType + { + startNewSubPath, /**< For this type, x1 and y1 will be set to indicate the first point in the subpath. */ + lineTo, /**< For this type, x1 and y1 indicate the end point of the line. */ + quadraticTo, /**< For this type, x1, y1, x2, y2 indicate the control point and endpoint of a quadratic curve. */ + cubicTo, /**< For this type, x1, y1, x2, y2, x3, y3 indicate the two control points and the endpoint of a cubic curve. */ + closePath /**< Indicates that the sub-path is being closed. None of the x or y values are valid in this case. */ + }; - /** Adds a rectangle with rounded corners to the path. + PathElementType elementType; - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). - - @see addRectangle, addTriangle - */ - void addRoundedRectangle (const float x, const float y, - const float w, const float h, - float cornerSize) throw(); - - /** Adds a rectangle with rounded corners to the path. - - The rectangle is added as a new sub-path. (Any currently open paths will be - left open). - - @see addRectangle, addTriangle - */ - void addRoundedRectangle (const float x, const float y, - const float w, const float h, - float cornerSizeX, - float cornerSizeY) throw(); - - /** Adds a triangle to the path. - - The triangle is added as a new closed sub-path. (Any currently open paths will be - left open). - - Note that whether the vertices are specified in clockwise or anticlockwise - order will affect how the triangle is filled when it overlaps other - shapes (the winding order setting will affect this of course). - */ - void addTriangle (const float x1, const float y1, - const float x2, const float y2, - const float x3, const float y3) throw(); - - /** Adds a quadrilateral to the path. - - The quad is added as a new closed sub-path. (Any currently open paths will be - left open). - - Note that whether the vertices are specified in clockwise or anticlockwise - order will affect how the quad is filled when it overlaps other - shapes (the winding order setting will affect this of course). - */ - void addQuadrilateral (const float x1, const float y1, - const float x2, const float y2, - const float x3, const float y3, - const float x4, const float y4) throw(); - - /** Adds an ellipse to the path. - - The shape is added as a new sub-path. (Any currently open paths will be - left open). - - @see addArc - */ - void addEllipse (const float x, const float y, - const float width, const float height) throw(); - - /** Adds an elliptical arc to the current path. - - Note that when specifying the start and end angles, the curve will be drawn either clockwise - or anti-clockwise according to whether the end angle is greater than the start. This means - that sometimes you may need to use values greater than 2*Pi for the end angle. - - @param x the left-hand edge of the rectangle in which the elliptical outline fits - @param y the top edge of the rectangle in which the elliptical outline fits - @param width the width of the rectangle in which the elliptical outline fits - @param height the height of the rectangle in which the elliptical outline fits - @param fromRadians the angle (clockwise) in radians at which to start the arc segment (where 0 is the - top-centre of the ellipse) - @param toRadians the angle (clockwise) in radians at which to end the arc segment (where 0 is the - top-centre of the ellipse). This angle can be greater than 2*Pi, so for example to - draw a curve clockwise from the 9 o'clock position to the 3 o'clock position via - 12 o'clock, you'd use 1.5*Pi and 2.5*Pi as the start and finish points. - @param startAsNewSubPath if true, the arc will begin a new subpath from its starting point; if false, - it will be added to the current sub-path, continuing from the current postition - - @see addCentredArc, arcTo, addPieSegment, addEllipse - */ - void addArc (const float x, const float y, - const float width, const float height, - const float fromRadians, - const float toRadians, - const bool startAsNewSubPath = false) throw(); - - /** Adds an arc which is centred at a given point, and can have a rotation specified. - - Note that when specifying the start and end angles, the curve will be drawn either clockwise - or anti-clockwise according to whether the end angle is greater than the start. This means - that sometimes you may need to use values greater than 2*Pi for the end angle. - - @param centreX the centre x of the ellipse - @param centreY the centre y of the ellipse - @param radiusX the horizontal radius of the ellipse - @param radiusY the vertical radius of the ellipse - @param rotationOfEllipse an angle by which the whole ellipse should be rotated about its centre, in radians (clockwise) - @param fromRadians the angle (clockwise) in radians at which to start the arc segment (where 0 is the - top-centre of the ellipse) - @param toRadians the angle (clockwise) in radians at which to end the arc segment (where 0 is the - top-centre of the ellipse). This angle can be greater than 2*Pi, so for example to - draw a curve clockwise from the 9 o'clock position to the 3 o'clock position via - 12 o'clock, you'd use 1.5*Pi and 2.5*Pi as the start and finish points. - @param startAsNewSubPath if true, the arc will begin a new subpath from its starting point; if false, - it will be added to the current sub-path, continuing from the current postition - - @see addArc, arcTo - */ - void addCentredArc (const float centreX, const float centreY, - const float radiusX, const float radiusY, - const float rotationOfEllipse, - const float fromRadians, - const float toRadians, - const bool startAsNewSubPath = false) throw(); - - /** Adds a "pie-chart" shape to the path. - - The shape is added as a new sub-path. (Any currently open paths will be - left open). - - Note that when specifying the start and end angles, the curve will be drawn either clockwise - or anti-clockwise according to whether the end angle is greater than the start. This means - that sometimes you may need to use values greater than 2*Pi for the end angle. - - @param x the left-hand edge of the rectangle in which the elliptical outline fits - @param y the top edge of the rectangle in which the elliptical outline fits - @param width the width of the rectangle in which the elliptical outline fits - @param height the height of the rectangle in which the elliptical outline fits - @param fromRadians the angle (clockwise) in radians at which to start the arc segment (where 0 is the - top-centre of the ellipse) - @param toRadians the angle (clockwise) in radians at which to end the arc segment (where 0 is the - top-centre of the ellipse) - @param innerCircleProportionalSize if this is > 0, then the pie will be drawn as a curved band around a hollow - ellipse at its centre, where this value indicates the inner ellipse's size with - respect to the outer one. - - @see addArc - */ - void addPieSegment (const float x, const float y, - const float width, const float height, - const float fromRadians, - const float toRadians, - const float innerCircleProportionalSize); - - /** Adds a line with a specified thickness. - - The line is added as a new closed sub-path. (Any currently open paths will be - left open). - - @see addArrow - */ - void addLineSegment (const float startX, const float startY, - const float endX, const float endY, - float lineThickness) throw(); - - /** Adds a line with an arrowhead on the end. - - The arrow is added as a new closed sub-path. (Any currently open paths will be - left open). - */ - void addArrow (const float startX, const float startY, - const float endX, const float endY, - float lineThickness, - float arrowheadWidth, - float arrowheadLength) throw(); - - /** Adds a star shape to the path. - - */ - void addStar (const float centreX, - const float centreY, - const int numberOfPoints, - const float innerRadius, - const float outerRadius, - const float startAngle = 0.0f); - - /** Adds a speech-bubble shape to the path. - - @param bodyX the left of the main body area of the bubble - @param bodyY the top of the main body area of the bubble - @param bodyW the width of the main body area of the bubble - @param bodyH the height of the main body area of the bubble - @param cornerSize the amount by which to round off the corners of the main body rectangle - @param arrowTipX the x position that the tip of the arrow should connect to - @param arrowTipY the y position that the tip of the arrow should connect to - @param whichSide the side to connect the arrow to: 0 = top, 1 = left, 2 = bottom, 3 = right - @param arrowPositionAlongEdgeProportional how far along the edge of the main rectangle the - arrow's base should be - this is a proportional distance between 0 and 1.0 - @param arrowWidth how wide the base of the arrow should be where it joins the main rectangle - */ - void addBubble (float bodyX, float bodyY, - float bodyW, float bodyH, - float cornerSize, - float arrowTipX, - float arrowTipY, - int whichSide, - float arrowPositionAlongEdgeProportional, - float arrowWidth); - - /** Adds another path to this one. - - The new path is added as a new sub-path. (Any currently open paths in this - path will be left open). - - @param pathToAppend the path to add - */ - void addPath (const Path& pathToAppend) throw(); - - /** Adds another path to this one, transforming it on the way in. - - The new path is added as a new sub-path, its points being transformed by the given - matrix before being added. - - @param pathToAppend the path to add - @param transformToApply an optional transform to apply to the incoming vertices - */ - void addPath (const Path& pathToAppend, - const AffineTransform& transformToApply) throw(); - - /** Swaps the contents of this path with another one. - - The internal data of the two paths is swapped over, so this is much faster than - copying it to a temp variable and back. - */ - void swapWithPath (Path& other); - - /** Applies a 2D transform to all the vertices in the path. - - @see AffineTransform, scaleToFit, getTransformToScaleToFit - */ - void applyTransform (const AffineTransform& transform) throw(); - - /** Rescales this path to make it fit neatly into a given space. - - This is effectively a quick way of calling - applyTransform (getTransformToScaleToFit (x, y, w, h, preserveProportions)) - - @param x the x position of the rectangle to fit the path inside - @param y the y position of the rectangle to fit the path inside - @param width the width of the rectangle to fit the path inside - @param height the height of the rectangle to fit the path inside - @param preserveProportions if true, it will fit the path into the space without altering its - horizontal/vertical scale ratio; if false, it will distort the - path to fill the specified ratio both horizontally and vertically - - @see applyTransform, getTransformToScaleToFit - */ - void scaleToFit (const float x, const float y, - const float width, const float height, - const bool preserveProportions) throw(); - - /** Returns a transform that can be used to rescale the path to fit into a given space. - - @param x the x position of the rectangle to fit the path inside - @param y the y position of the rectangle to fit the path inside - @param width the width of the rectangle to fit the path inside - @param height the height of the rectangle to fit the path inside - @param preserveProportions if true, it will fit the path into the space without altering its - horizontal/vertical scale ratio; if false, it will distort the - path to fill the specified ratio both horizontally and vertically - @param justificationType if the proportions are preseved, the resultant path may be smaller - than the available rectangle, so this describes how it should be - positioned within the space. - @returns an appropriate transformation - - @see applyTransform, scaleToFit - - */ - const AffineTransform getTransformToScaleToFit (const float x, const float y, - const float width, const float height, - const bool preserveProportions, - const Justification& justificationType = Justification::centred) const throw(); + float x1, y1, x2, y2, x3, y3; - /** Creates a version of this path where all sharp corners have been replaced by curves. + private: + const Path& path; + int index; - Wherever two lines meet at an angle, this will replace the corner with a curve - of the given radius. - */ - const Path createPathWithRoundedCorners (const float cornerRadius) const throw(); + Iterator (const Iterator&); + const Iterator& operator= (const Iterator&); + }; - /** Changes the winding-rule to be used when filling the path. + void loadPathFromStream (InputStream& source); - If set to true (which is the default), then the path uses a non-zero-winding rule - to determine which points are inside the path. If set to false, it uses an - alternate-winding rule. + void loadPathFromData (const unsigned char* const data, + const int numberOfBytes) throw(); - The winding-rule comes into play when areas of the shape overlap other - areas, and determines whether the overlapping regions are considered to be - inside or outside. + void writePathToStream (OutputStream& destination) const; - Changing this value just sets a flag - it doesn't affect the contents of the - path. + const String toString() const; - @see isUsingNonZeroWinding - */ - void setUsingNonZeroWinding (const bool isNonZeroWinding) throw(); + void restoreFromString (const String& stringVersion); - /** Returns the flag that indicates whether the path should use a non-zero winding rule. - - The default for a new path is true. - - @see setUsingNonZeroWinding - */ - bool isUsingNonZeroWinding() const { return useNonZeroWinding; } - - /** Iterates the lines and curves that a path contains. - - @see Path, PathFlatteningIterator - */ - class JUCE_API Iterator - { - public: - - Iterator (const Path& path); - ~Iterator(); - - /** Moves onto the next element in the path. - - If this returns false, there are no more elements. If it returns true, - the elementType variable will be set to the type of the current element, - and some of the x and y variables will be filled in with values. - */ - bool next(); - - enum PathElementType - { - startNewSubPath, /**< For this type, x1 and y1 will be set to indicate the first point in the subpath. */ - lineTo, /**< For this type, x1 and y1 indicate the end point of the line. */ - quadraticTo, /**< For this type, x1, y1, x2, y2 indicate the control point and endpoint of a quadratic curve. */ - cubicTo, /**< For this type, x1, y1, x2, y2, x3, y3 indicate the two control points and the endpoint of a cubic curve. */ - closePath /**< Indicates that the sub-path is being closed. None of the x or y values are valid in this case. */ - }; - - PathElementType elementType; - - float x1, y1, x2, y2, x3, y3; - - private: - const Path& path; - int index; - - Iterator (const Iterator&); - const Iterator& operator= (const Iterator&); - }; - - /** Loads a stored path from a data stream. - - The data in the stream must have been written using writePathToStream(). - - Note that this will append the stored path to whatever is currently in - this path, so you might need to call clear() beforehand. - - @see loadPathFromData, writePathToStream - */ - void loadPathFromStream (InputStream& source); - - /** Loads a stored path from a block of data. - - This is similar to loadPathFromStream(), but just reads from a block - of data. Useful if you're including stored shapes in your code as a - block of static data. - - @see loadPathFromStream, writePathToStream - */ - void loadPathFromData (const unsigned char* const data, - const int numberOfBytes) throw(); - - /** Stores the path by writing it out to a stream. - - After writing out a path, you can reload it using loadPathFromStream(). - - @see loadPathFromStream, loadPathFromData - */ - void writePathToStream (OutputStream& destination) const; - - /** Creates a string containing a textual representation of this path. - @see restoreFromString - */ - const String toString() const; - - /** Restores this path from a string that was created with the toString() method. - @see toString() - */ - void restoreFromString (const String& stringVersion); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class PathFlatteningIterator; - friend class Path::Iterator; - ArrayAllocationBase data; - int numElements; - float pathXMin, pathXMax, pathYMin, pathYMax; - bool useNonZeroWinding; + friend class PathFlatteningIterator; + friend class Path::Iterator; + ArrayAllocationBase data; + int numElements; + float pathXMin, pathXMax, pathYMin, pathYMax; + bool useNonZeroWinding; - static const float lineMarker; - static const float moveMarker; - static const float quadMarker; - static const float cubicMarker; - static const float closeSubPathMarker; + static const float lineMarker; + static const float moveMarker; + static const float quadMarker; + static const float cubicMarker; + static const float closeSubPathMarker; }; #endif // __JUCE_PATH_JUCEHEADER__ @@ -19641,188 +9946,91 @@ private: class Font; class CustomTypefaceGlyphInfo; -/** A typeface represents a size-independent font. - - This base class is abstract, but calling createSystemTypefaceFor() will return - a platform-specific subclass that can be used. - - The CustomTypeface subclass allow you to build your own typeface, and to - load and save it in the Juce typeface format. - - Normally you should never need to deal directly with Typeface objects - the Font - class does everything you typically need for rendering text. - - @see CustomTypeface, Font -*/ class JUCE_API Typeface : public ReferenceCountedObject { public: - /** A handy typedef for a pointer to a typeface. */ - typedef ReferenceCountedObjectPtr Ptr; + typedef ReferenceCountedObjectPtr Ptr; - /** Returns the name of the typeface. - @see Font::getTypefaceName - */ - const String getName() const throw() { return name; } + const String getName() const throw() { return name; } - /** Creates a new system typeface. */ - static const Ptr createSystemTypefaceFor (const Font& font); + static const Ptr createSystemTypefaceFor (const Font& font); - /** Destructor. */ - virtual ~Typeface(); + virtual ~Typeface(); - /** Returns the ascent of the font, as a proportion of its height. - The height is considered to always be normalised as 1.0, so this will be a - value less that 1.0, indicating the proportion of the font that lies above - its baseline. - */ - virtual float getAscent() const = 0; + virtual float getAscent() const = 0; - /** Returns the descent of the font, as a proportion of its height. - The height is considered to always be normalised as 1.0, so this will be a - value less that 1.0, indicating the proportion of the font that lies below - its baseline. - */ - virtual float getDescent() const = 0; + virtual float getDescent() const = 0; - /** Measures the width of a line of text. + virtual float getStringWidth (const String& text) = 0; - The distance returned is based on the font having an normalised height of 1.0. + virtual void getGlyphPositions (const String& text, Array & glyphs, Array& xOffsets) = 0; - You should never need to call this directly! Use Font::getStringWidth() instead! - */ - virtual float getStringWidth (const String& text) = 0; + virtual bool getOutlineForGlyph (int glyphNumber, Path& path) = 0; - /** Converts a line of text into its glyph numbers and their positions. - - The distances returned are based on the font having an normalised height of 1.0. - - You should never need to call this directly! Use Font::getGlyphPositions() instead! - */ - virtual void getGlyphPositions (const String& text, Array & glyphs, Array& xOffsets) = 0; - - /** Returns the outline for a glyph. - - The path returned will be normalised to a font height of 1.0. - */ - virtual bool getOutlineForGlyph (int glyphNumber, Path& path) = 0; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - String name; + String name; - Typeface (const String& name) throw(); + Typeface (const String& name) throw(); private: - Typeface (const Typeface&); - const Typeface& operator= (const Typeface&); + Typeface (const Typeface&); + const Typeface& operator= (const Typeface&); }; -/** A typeface that can be populated with custom glyphs. - - You can create a CustomTypeface if you need one that contains your own glyphs, - or if you need to load a typeface from a Juce-formatted binary stream. - - If you want to create a copy of a native face, you can use addGlyphsFromOtherTypeface() - to copy glyphs into this face. - - @see Typeface, Font -*/ class JUCE_API CustomTypeface : public Typeface { public: - /** Creates a new, empty typeface. */ - CustomTypeface(); + CustomTypeface(); - /** Loads a typeface from a previously saved stream. - The stream must have been created by writeToStream(). - @see writeToStream - */ - CustomTypeface (InputStream& serialisedTypefaceStream); + CustomTypeface (InputStream& serialisedTypefaceStream); - /** Destructor. */ - ~CustomTypeface(); + ~CustomTypeface(); - /** Resets this typeface, deleting all its glyphs and settings. */ - void clear(); + void clear(); - /** Sets the vital statistics for the typeface. - @param name the typeface's name - @param ascent the ascent - this is normalised to a height of 1.0 and this is - the value that will be returned by Typeface::getAscent(). The - descent is assumed to be (1.0 - ascent) - @param isBold should be true if the typeface is bold - @param isItalic should be true if the typeface is italic - @param defaultCharacter the character to be used as a replacement if there's - no glyph available for the character that's being drawn - */ - void setCharacteristics (const String& name, const float ascent, - const bool isBold, const bool isItalic, - const juce_wchar defaultCharacter) throw(); + void setCharacteristics (const String& name, const float ascent, + const bool isBold, const bool isItalic, + const juce_wchar defaultCharacter) throw(); - /** Adds a glyph to the typeface. + void addGlyph (const juce_wchar character, const Path& path, const float width) throw(); - The path that is passed in is normalised so that the font height is 1.0, and its - origin is the anchor point of the character on its baseline. + void addKerningPair (const juce_wchar char1, const juce_wchar char2, const float extraAmount) throw(); - The width is the nominal width of the character, and any extra kerning values that - are specified will be added to this width. - */ - void addGlyph (const juce_wchar character, const Path& path, const float width) throw(); + void addGlyphsFromOtherTypeface (Typeface& typefaceToCopy, juce_wchar characterStartIndex, int numCharacters) throw(); - /** Specifies an extra kerning amount to be used between a pair of characters. - The amount will be added to the nominal width of the first character when laying out a string. - */ - void addKerningPair (const juce_wchar char1, const juce_wchar char2, const float extraAmount) throw(); + bool writeToStream (OutputStream& outputStream); - /** Adds a range of glyphs from another typeface. - This will attempt to pull in the paths and kerning information from another typeface and - add it to this one. - */ - void addGlyphsFromOtherTypeface (Typeface& typefaceToCopy, juce_wchar characterStartIndex, int numCharacters) throw(); + // The following methods implement the basic Typeface behaviour. + float getAscent() const; + float getDescent() const; + float getStringWidth (const String& text); + void getGlyphPositions (const String& text, Array & glyphs, Array& xOffsets); + bool getOutlineForGlyph (int glyphNumber, Path& path); + int getGlyphForCharacter (juce_wchar character); - /** Saves this typeface as a Juce-formatted font file. - A CustomTypeface can be created to reload the data that is written - see the CustomTypeface - constructor. - */ - bool writeToStream (OutputStream& outputStream); - - // The following methods implement the basic Typeface behaviour. - float getAscent() const; - float getDescent() const; - float getStringWidth (const String& text); - void getGlyphPositions (const String& text, Array & glyphs, Array& xOffsets); - bool getOutlineForGlyph (int glyphNumber, Path& path); - int getGlyphForCharacter (juce_wchar character); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - juce_wchar defaultCharacter; - float ascent; - bool isBold, isItalic; + juce_wchar defaultCharacter; + float ascent; + bool isBold, isItalic; - /** If a subclass overrides this, it can load glyphs into the font on-demand. - When methods such as getGlyphPositions() or getOutlineForGlyph() are asked for a - particular character and there's no corresponding glyph, they'll call this - method so that a subclass can try to add that glyph, returning true if it - manages to do so. - */ - virtual bool loadGlyphIfPossible (const juce_wchar characterNeeded); + virtual bool loadGlyphIfPossible (const juce_wchar characterNeeded); private: - OwnedArray glyphs; - short lookupTable [128]; + OwnedArray glyphs; + short lookupTable [128]; - CustomTypeface (const CustomTypeface&); - const CustomTypeface& operator= (const CustomTypeface&); + CustomTypeface (const CustomTypeface&); + const CustomTypeface& operator= (const CustomTypeface&); - CustomTypefaceGlyphInfo* findGlyph (const juce_wchar character, const bool loadIfNeeded) throw(); - CustomTypefaceGlyphInfo* findGlyphSubstituting (const juce_wchar character) throw(); + CustomTypefaceGlyphInfo* findGlyph (const juce_wchar character, const bool loadIfNeeded) throw(); + CustomTypefaceGlyphInfo* findGlyphSubstituting (const juce_wchar character) throw(); }; #endif // __JUCE_TYPEFACE_JUCEHEADER__ @@ -19830,327 +10038,125 @@ private: class LowLevelGraphicsContext; -/** - Represents a particular font, including its size, style, etc. - - Apart from the typeface to be used, a Font object also dictates whether - the font is bold, italic, underlined, how big it is, and its kerning and - horizontal scale factor. - - @see Typeface -*/ class JUCE_API Font { public: - /** A combination of these values is used by the constructor to specify the - style of font to use. - */ - enum FontStyleFlags - { - plain = 0, /**< indicates a plain, non-bold, non-italic version of the font. @see setStyleFlags */ - bold = 1, /**< boldens the font. @see setStyleFlags */ - italic = 2, /**< finds an italic version of the font. @see setStyleFlags */ - underlined = 4 /**< underlines the font. @see setStyleFlags */ - }; + enum FontStyleFlags + { + plain = 0, /**< indicates a plain, non-bold, non-italic version of the font. @see setStyleFlags */ + bold = 1, /**< boldens the font. @see setStyleFlags */ + italic = 2, /**< finds an italic version of the font. @see setStyleFlags */ + underlined = 4 /**< underlines the font. @see setStyleFlags */ + }; - /** Creates a sans-serif font in a given size. + Font (const float fontHeight, + const int styleFlags = plain) throw(); - @param fontHeight the height in pixels (can be fractional) - @param styleFlags the style to use - this can be a combination of the - Font::bold, Font::italic and Font::underlined, or - just Font::plain for the normal style. - @see FontStyleFlags, getDefaultSansSerifFontName - */ - Font (const float fontHeight, - const int styleFlags = plain) throw(); + Font (const String& typefaceName, + const float fontHeight, + const int styleFlags) throw(); - /** Creates a font with a given typeface and parameters. + Font (const Font& other) throw(); - @param typefaceName the name of the typeface to use - @param fontHeight the height in pixels (can be fractional) - @param styleFlags the style to use - this can be a combination of the - Font::bold, Font::italic and Font::underlined, or - just Font::plain for the normal style. - @see FontStyleFlags, getDefaultSansSerifFontName - */ - Font (const String& typefaceName, - const float fontHeight, - const int styleFlags) throw(); + Font (const Typeface::Ptr& typeface) throw(); - /** Creates a copy of another Font object. */ - Font (const Font& other) throw(); + Font() throw(); - /** Creates a font for a typeface. */ - Font (const Typeface::Ptr& typeface) throw(); + const Font& operator= (const Font& other) throw(); - /** Creates a basic sans-serif font at a default height. + bool operator== (const Font& other) const throw(); + bool operator!= (const Font& other) const throw(); - You should use one of the other constructors for creating a font that you're planning - on drawing with - this constructor is here to help initialise objects before changing - the font's settings later. - */ - Font() throw(); + ~Font() throw(); - /** Copies this font from another one. */ - const Font& operator= (const Font& other) throw(); + void setTypefaceName (const String& faceName) throw(); - bool operator== (const Font& other) const throw(); - bool operator!= (const Font& other) const throw(); + const String& getTypefaceName() const throw() { return font->typefaceName; } - /** Destructor. */ - ~Font() throw(); + static const String getDefaultSansSerifFontName() throw(); - /** Changes the name of the typeface family. + static const String getDefaultSerifFontName() throw(); - e.g. "Arial", "Courier", etc. + static const String getDefaultMonospacedFontName() throw(); - This may also be set to Font::getDefaultSansSerifFontName(), Font::getDefaultSerifFontName(), - or Font::getDefaultMonospacedFontName(), which are not actual platform-specific font names, - but are generic names that are used to represent the various default fonts. - If you need to know the exact typeface name being used, you can call - Font::getTypeface()->getTypefaceName(), which will give you the platform-specific name. + static void getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed) throw(); - If a suitable font isn't found on the machine, it'll just use a default instead. - */ - void setTypefaceName (const String& faceName) throw(); + float getHeight() const throw() { return font->height; } - /** Returns the name of the typeface family that this font uses. + void setHeight (float newHeight) throw(); - e.g. "Arial", "Courier", etc. + void setHeightWithoutChangingWidth (float newHeight) throw(); - This may also be set to Font::getDefaultSansSerifFontName(), Font::getDefaultSerifFontName(), - or Font::getDefaultMonospacedFontName(), which are not actual platform-specific font names, - but are generic names that are used to represent the various default fonts. + float getAscent() const throw(); - If you need to know the exact typeface name being used, you can call - Font::getTypeface()->getTypefaceName(), which will give you the platform-specific name. - */ - const String& getTypefaceName() const throw() { return font->typefaceName; } + float getDescent() const throw(); - /** Returns a typeface name that represents the default sans-serif font. + int getStyleFlags() const throw() { return font->styleFlags; } - This is also the typeface that will be used when a font is created without - specifying any typeface details. + void setStyleFlags (const int newFlags) throw(); - Note that this method just returns a generic placeholder string that means "the default - sans-serif font" - it's not the actual name of this font. To get the actual name, use - getPlatformDefaultFontNames() or LookAndFeel::getTypefaceForFont(). + void setBold (const bool shouldBeBold) throw(); + bool isBold() const throw(); - @see setTypefaceName, getDefaultSerifFontName, getDefaultMonospacedFontName - */ - static const String getDefaultSansSerifFontName() throw(); + void setItalic (const bool shouldBeItalic) throw(); + bool isItalic() const throw(); - /** Returns a typeface name that represents the default sans-serif font. + void setUnderline (const bool shouldBeUnderlined) throw(); + bool isUnderlined() const throw(); - Note that this method just returns a generic placeholder string that means "the default - serif font" - it's not the actual name of this font. To get the actual name, use - getPlatformDefaultFontNames() or LookAndFeel::getTypefaceForFont(). + void setHorizontalScale (const float scaleFactor) throw(); - @see setTypefaceName, getDefaultSansSerifFontName, getDefaultMonospacedFontName - */ - static const String getDefaultSerifFontName() throw(); + float getHorizontalScale() const throw() { return font->horizontalScale; } - /** Returns a typeface name that represents the default sans-serif font. + void setExtraKerningFactor (const float extraKerning) throw(); - Note that this method just returns a generic placeholder string that means "the default - monospaced font" - it's not the actual name of this font. To get the actual name, use - getPlatformDefaultFontNames() or LookAndFeel::getTypefaceForFont(). + float getExtraKerningFactor() const throw() { return font->kerning; } - @see setTypefaceName, getDefaultSansSerifFontName, getDefaultSerifFontName - */ - static const String getDefaultMonospacedFontName() throw(); + void setSizeAndStyle (float newHeight, + const int newStyleFlags, + const float newHorizontalScale, + const float newKerningAmount) throw(); - /** Returns the typeface names of the default fonts on the current platform. */ - static void getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed) throw(); + int getStringWidth (const String& text) const throw(); - /** Returns the total height of this font. + float getStringWidthFloat (const String& text) const throw(); - This is the maximum height, from the top of the ascent to the bottom of the - descenders. + void getGlyphPositions (const String& text, Array & glyphs, Array & xOffsets) const throw(); - @see setHeight, setHeightWithoutChangingWidth, getAscent - */ - float getHeight() const throw() { return font->height; } + Typeface* getTypeface() const throw(); - /** Changes the font's height. + static void findFonts (OwnedArray& results) throw(); - @see getHeight, setHeightWithoutChangingWidth - */ - void setHeight (float newHeight) throw(); + static const StringArray findAllTypefaceNames() throw(); - /** Changes the font's height without changing its width. + static const String getFallbackFontName() throw(); - This alters the horizontal scale to compensate for the change in height. - */ - void setHeightWithoutChangingWidth (float newHeight) throw(); + static void setFallbackFontName (const String& name) throw(); - /** Returns the height of the font above its baseline. - - This is the maximum height from the baseline to the top. - - @see getHeight, getDescent - */ - float getAscent() const throw(); - - /** Returns the amount that the font descends below its baseline. - - This is calculated as (getHeight() - getAscent()). - - @see getAscent, getHeight - */ - float getDescent() const throw(); - - /** Returns the font's style flags. - - This will return a bitwise-or'ed combination of values from the FontStyleFlags - enum, to describe whether the font is bold, italic, etc. - - @see FontStyleFlags - */ - int getStyleFlags() const throw() { return font->styleFlags; } - - /** Changes the font's style. - - @param newFlags a bitwise-or'ed combination of values from the FontStyleFlags - enum, to set the font's properties - @see FontStyleFlags - */ - void setStyleFlags (const int newFlags) throw(); - - /** Makes the font bold or non-bold. */ - void setBold (const bool shouldBeBold) throw(); - /** Returns true if the font is bold. */ - bool isBold() const throw(); - - /** Makes the font italic or non-italic. */ - void setItalic (const bool shouldBeItalic) throw(); - /** Returns true if the font is italic. */ - bool isItalic() const throw(); - - /** Makes the font underlined or non-underlined. */ - void setUnderline (const bool shouldBeUnderlined) throw(); - /** Returns true if the font is underlined. */ - bool isUnderlined() const throw(); - - /** Changes the font's horizontal scale factor. - - @param scaleFactor a value of 1.0 is the normal scale, less than this will be - narrower, greater than 1.0 will be stretched out. - */ - void setHorizontalScale (const float scaleFactor) throw(); - - /** Returns the font's horizontal scale. - - A value of 1.0 is the normal scale, less than this will be narrower, greater - than 1.0 will be stretched out. - - @see setHorizontalScale - */ - float getHorizontalScale() const throw() { return font->horizontalScale; } - - /** Changes the font's kerning. - - @param extraKerning a multiple of the font's height that will be added - to space between the characters. So a value of zero is - normal spacing, positive values spread the letters out, - negative values make them closer together. - */ - void setExtraKerningFactor (const float extraKerning) throw(); - - /** Returns the font's kerning. - - This is the extra space added between adjacent characters, as a proportion - of the font's height. - - A value of zero is normal spacing, positive values will spread the letters - out more, and negative values make them closer together. - */ - float getExtraKerningFactor() const throw() { return font->kerning; } - - /** Changes all the font's characteristics with one call. */ - void setSizeAndStyle (float newHeight, - const int newStyleFlags, - const float newHorizontalScale, - const float newKerningAmount) throw(); - - /** Returns the total width of a string as it would be drawn using this font. - - For a more accurate floating-point result, use getStringWidthFloat(). - */ - int getStringWidth (const String& text) const throw(); - - /** Returns the total width of a string as it would be drawn using this font. - - @see getStringWidth - */ - float getStringWidthFloat (const String& text) const throw(); - - /** Returns the series of glyph numbers and their x offsets needed to represent a string. - - An extra x offset is added at the end of the run, to indicate where the right hand - edge of the last character is. - */ - void getGlyphPositions (const String& text, Array & glyphs, Array & xOffsets) const throw(); - - /** Returns the typeface used by this font. - - Note that the object returned may go out of scope if this font is deleted - or has its style changed. - */ - Typeface* getTypeface() const throw(); - - /** Creates an array of Font objects to represent all the fonts on the system. - - If you just need the names of the typefaces, you can also use - findAllTypefaceNames() instead. - - @param results the array to which new Font objects will be added. - */ - static void findFonts (OwnedArray& results) throw(); - - /** Returns a list of all the available typeface names. - - The names returned can be passed into setTypefaceName(). - - You can use this instead of findFonts() if you only need their names, and not - font objects. - */ - static const StringArray findAllTypefaceNames() throw(); - - /** Returns the name of the typeface to be used for rendering glyphs that aren't found - in the requested typeface. - */ - static const String getFallbackFontName() throw(); - - /** Sets the (platform-specific) name of the typeface to use to find glyphs that aren't - available in whatever font you're trying to use. - */ - static void setFallbackFontName (const String& name) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class FontGlyphAlphaMap; - friend class TypefaceCache; + friend class FontGlyphAlphaMap; + friend class TypefaceCache; - class SharedFontInternal : public ReferenceCountedObject - { - public: - SharedFontInternal (const String& typefaceName, const float height, const float horizontalScale, - const float kerning, const float ascent, const int styleFlags, - Typeface* const typeface) throw(); - SharedFontInternal (const SharedFontInternal& other) throw(); + class SharedFontInternal : public ReferenceCountedObject + { + public: + SharedFontInternal (const String& typefaceName, const float height, const float horizontalScale, + const float kerning, const float ascent, const int styleFlags, + Typeface* const typeface) throw(); + SharedFontInternal (const SharedFontInternal& other) throw(); - String typefaceName; - float height, horizontalScale, kerning, ascent; - int styleFlags; - Typeface::Ptr typeface; - }; + String typefaceName; + float height, horizontalScale, kerning, ascent; + int styleFlags; + Typeface::Ptr typeface; + }; - ReferenceCountedObjectPtr font; - void dupeInternalIfShared() throw(); + ReferenceCountedObjectPtr font; + void dupeInternalIfShared() throw(); }; #endif // __JUCE_FONT_JUCEHEADER__ @@ -20160,131 +10166,69 @@ private: #ifndef __JUCE_PATHSTROKETYPE_JUCEHEADER__ #define __JUCE_PATHSTROKETYPE_JUCEHEADER__ -/** - Describes a type of stroke used to render a solid outline along a path. - - A PathStrokeType object can be used directly to create the shape of an outline - around a path, and is used by Graphics::strokePath to specify the type of - stroke to draw. - - @see Path, Graphics::strokePath -*/ class JUCE_API PathStrokeType { public: - /** The type of shape to use for the corners between two adjacent line segments. */ - enum JointStyle - { - mitered, /**< Indicates that corners should be drawn with sharp joints. - Note that for angles that curve back on themselves, drawing a - mitre could require extending the point too far away from the - path, so a mitre limit is imposed and any corners that exceed it - are drawn as bevelled instead. */ - curved, /**< Indicates that corners should be drawn as rounded-off. */ - beveled /**< Indicates that corners should be drawn with a line flattening their - outside edge. */ - }; + enum JointStyle + { + mitered, /**< Indicates that corners should be drawn with sharp joints. + Note that for angles that curve back on themselves, drawing a + mitre could require extending the point too far away from the + path, so a mitre limit is imposed and any corners that exceed it + are drawn as bevelled instead. */ + curved, /**< Indicates that corners should be drawn as rounded-off. */ + beveled /**< Indicates that corners should be drawn with a line flattening their + outside edge. */ + }; - /** The type shape to use for the ends of lines. */ - enum EndCapStyle - { - butt, /**< Ends of lines are flat and don't extend beyond the end point. */ - square, /**< Ends of lines are flat, but stick out beyond the end point for half - the thickness of the stroke. */ - rounded /**< Ends of lines are rounded-off with a circular shape. */ - }; + enum EndCapStyle + { + butt, /**< Ends of lines are flat and don't extend beyond the end point. */ + square, /**< Ends of lines are flat, but stick out beyond the end point for half + the thickness of the stroke. */ + rounded /**< Ends of lines are rounded-off with a circular shape. */ + }; - /** Creates a stroke type. + PathStrokeType (const float strokeThickness, + const JointStyle jointStyle = mitered, + const EndCapStyle endStyle = butt) throw(); - @param strokeThickness the width of the line to use - @param jointStyle the type of joints to use for corners - @param endStyle the type of end-caps to use for the ends of open paths. - */ - PathStrokeType (const float strokeThickness, - const JointStyle jointStyle = mitered, - const EndCapStyle endStyle = butt) throw(); + PathStrokeType (const PathStrokeType& other) throw(); - /** Createes a copy of another stroke type. */ - PathStrokeType (const PathStrokeType& other) throw(); + const PathStrokeType& operator= (const PathStrokeType& other) throw(); - /** Copies another stroke onto this one. */ - const PathStrokeType& operator= (const PathStrokeType& other) throw(); + ~PathStrokeType() throw(); - /** Destructor. */ - ~PathStrokeType() throw(); + void createStrokedPath (Path& destPath, + const Path& sourcePath, + const AffineTransform& transform = AffineTransform::identity, + const float extraAccuracy = 1.0f) const throw(); - /** Applies this stroke type to a path and returns the resultant stroke as another Path. + void createDashedStroke (Path& destPath, + const Path& sourcePath, + const float* dashLengths, + int numDashLengths, + const AffineTransform& transform = AffineTransform::identity, + const float extraAccuracy = 1.0f) const throw(); - @param destPath the resultant stroked outline shape will be copied into this path. - Note that it's ok for the source and destination Paths to be - the same object, so you can easily turn a path into a stroked version - of itself. - @param sourcePath the path to use as the source - @param transform an optional transform to apply to the points from the source path - as they are being used - @param extraAccuracy if this is greater than 1.0, it will subdivide the path to - a higher resolution, which improved the quality if you'll later want - to enlarge the stroked path + float getStrokeThickness() const throw() { return thickness; } - @see createDashedStroke - */ - void createStrokedPath (Path& destPath, - const Path& sourcePath, - const AffineTransform& transform = AffineTransform::identity, - const float extraAccuracy = 1.0f) const throw(); + JointStyle getJointStyle() const throw() { return jointStyle; } - /** Applies this stroke type to a path, creating a dashed line. + EndCapStyle getEndStyle() const throw() { return endStyle; } - This is similar to createStrokedPath, but uses the array passed in to - break the stroke up into a series of dashes. + juce_UseDebuggingNewOperator - @param destPath the resultant stroked outline shape will be copied into this path. - Note that it's ok for the source and destination Paths to be - the same object, so you can easily turn a path into a stroked version - of itself. - @param sourcePath the path to use as the source - @param dashLengths An array of alternating on/off lengths. E.g. { 2, 3, 4, 5 } will create - a line of length 2, then skip a length of 3, then add a line of length 4, - skip 5, and keep repeating this pattern. - @param numDashLengths The number of lengths in the dashLengths array. This should really be - an even number, otherwise the pattern will get out of step as it - repeats. - @param transform an optional transform to apply to the points from the source path - as they are being used - @param extraAccuracy if this is greater than 1.0, it will subdivide the path to - a higher resolution, which improved the quality if you'll later want - to enlarge the stroked path - */ - void createDashedStroke (Path& destPath, - const Path& sourcePath, - const float* dashLengths, - int numDashLengths, - const AffineTransform& transform = AffineTransform::identity, - const float extraAccuracy = 1.0f) const throw(); + bool operator== (const PathStrokeType& other) const throw(); - /** Returns the stroke thickness. */ - float getStrokeThickness() const throw() { return thickness; } - - /** Returns the joint style. */ - JointStyle getJointStyle() const throw() { return jointStyle; } - - /** Returns the end-cap style. */ - EndCapStyle getEndStyle() const throw() { return endStyle; } - - juce_UseDebuggingNewOperator - - /** Compares the stroke thickness, joint and end styles of two stroke types. */ - bool operator== (const PathStrokeType& other) const throw(); - - /** Compares the stroke thickness, joint and end styles of two stroke types. */ - bool operator!= (const PathStrokeType& other) const throw(); + bool operator!= (const PathStrokeType& other) const throw(); private: - float thickness; - JointStyle jointStyle; - EndCapStyle endStyle; + float thickness; + JointStyle jointStyle; + EndCapStyle endStyle; }; #endif // __JUCE_PATHSTROKETYPE_JUCEHEADER__ @@ -20294,220 +10238,92 @@ private: #ifndef __JUCE_LINE_JUCEHEADER__ #define __JUCE_LINE_JUCEHEADER__ -/** - Represents a line, using 32-bit float co-ordinates. - - This class contains a bunch of useful methods for various geometric - tasks. - - @see Point, Rectangle, Path, Graphics::drawLine -*/ class JUCE_API Line { public: - /** Creates a line, using (0, 0) as its start and end points. */ - Line() throw(); + Line() throw(); - /** Creates a copy of another line. */ - Line (const Line& other) throw(); + Line (const Line& other) throw(); - /** Creates a line based on the co-ordinates of its start and end points. */ - Line (const float startX, - const float startY, - const float endX, - const float endY) throw(); + Line (const float startX, + const float startY, + const float endX, + const float endY) throw(); - /** Creates a line from its start and end points. */ - Line (const Point& start, - const Point& end) throw(); + Line (const Point& start, + const Point& end) throw(); - /** Copies a line from another one. */ - const Line& operator= (const Line& other) throw(); + const Line& operator= (const Line& other) throw(); - /** Destructor. */ - ~Line() throw(); + ~Line() throw(); - /** Returns the x co-ordinate of the line's start point. */ - inline float getStartX() const throw() { return startX; } + inline float getStartX() const throw() { return startX; } - /** Returns the y co-ordinate of the line's start point. */ - inline float getStartY() const throw() { return startY; } + inline float getStartY() const throw() { return startY; } - /** Returns the x co-ordinate of the line's end point. */ - inline float getEndX() const throw() { return endX; } + inline float getEndX() const throw() { return endX; } - /** Returns the y co-ordinate of the line's end point. */ - inline float getEndY() const throw() { return endY; } + inline float getEndY() const throw() { return endY; } - /** Returns the line's start point. */ - const Point getStart() const throw(); + const Point getStart() const throw(); - /** Returns the line's end point. */ - const Point getEnd() const throw(); + const Point getEnd() const throw(); - /** Changes this line's start point */ - void setStart (const float newStartX, - const float newStartY) throw(); + void setStart (const float newStartX, + const float newStartY) throw(); - /** Changes this line's end point */ - void setEnd (const float newEndX, - const float newEndY) throw(); + void setEnd (const float newEndX, + const float newEndY) throw(); - /** Changes this line's start point */ - void setStart (const Point& newStart) throw(); + void setStart (const Point& newStart) throw(); - /** Changes this line's end point */ - void setEnd (const Point& newEnd) throw(); + void setEnd (const Point& newEnd) throw(); - /** Applies an affine transform to the line's start and end points. */ - void applyTransform (const AffineTransform& transform) throw(); + void applyTransform (const AffineTransform& transform) throw(); - /** Returns the length of the line. */ - float getLength() const throw(); + float getLength() const throw(); - /** Returns true if the line's start and end x co-ordinates are the same. */ - bool isVertical() const throw(); + bool isVertical() const throw(); - /** Returns true if the line's start and end y co-ordinates are the same. */ - bool isHorizontal() const throw(); + bool isHorizontal() const throw(); - /** Returns the line's angle. + float getAngle() const throw(); - This value is the number of radians clockwise from the 3 o'clock direction, - where the line's start point is considered to be at the centre. - */ - float getAngle() const throw(); + bool operator== (const Line& other) const throw(); - /** Compares two lines. */ - bool operator== (const Line& other) const throw(); + bool operator!= (const Line& other) const throw(); - /** Compares two lines. */ - bool operator!= (const Line& other) const throw(); + bool intersects (const Line& line, + float& intersectionX, + float& intersectionY) const throw(); - /** Finds the intersection between two lines. + const Point getPointAlongLine (const float distanceFromStart) const throw(); - @param line the other line - @param intersectionX the x co-ordinate of the point where the lines meet (or - where they would meet if they were infinitely long) - the intersection (if the lines intersect). If the lines - are parallel, this will just be set to the position - of one of the line's endpoints. - @param intersectionY the y co-ordinate of the point where the lines meet - @returns true if the line segments intersect; false if they dont. Even if they - don't intersect, the intersection co-ordinates returned will still - be valid - */ - bool intersects (const Line& line, - float& intersectionX, - float& intersectionY) const throw(); + const Point getPointAlongLine (const float distanceFromStart, + const float perpendicularDistance) const throw(); - /** Returns the location of the point which is a given distance along this line. + const Point getPointAlongLineProportionally (const float proportionOfLength) const throw(); - @param distanceFromStart the distance to move along the line from its - start point. This value can be negative or longer - than the line itself - @see getPointAlongLineProportionally - */ - const Point getPointAlongLine (const float distanceFromStart) const throw(); + float getDistanceFromLine (const float x, + const float y) const throw(); - /** Returns a point which is a certain distance along and to the side of this line. + float findNearestPointTo (const float x, + const float y) const throw(); - This effectively moves a given distance along the line, then another distance - perpendicularly to this, and returns the resulting position. + bool isPointAbove (const float x, const float y) const throw(); - @param distanceFromStart the distance to move along the line from its - start point. This value can be negative or longer - than the line itself - @param perpendicularDistance how far to move sideways from the line. If you're - looking along the line from its start towards its - end, then a positive value here will move to the - right, negative value move to the left. - */ - const Point getPointAlongLine (const float distanceFromStart, - const float perpendicularDistance) const throw(); + const Line withShortenedStart (const float distanceToShortenBy) const throw(); - /** Returns the location of the point which is a given distance along this line - proportional to the line's length. + const Line withShortenedEnd (const float distanceToShortenBy) const throw(); - @param proportionOfLength the distance to move along the line from its - start point, in multiples of the line's length. - So a value of 0.0 will return the line's start point - and a value of 1.0 will return its end point. (This value - can be negative or greater than 1.0). - @see getPointAlongLine - */ - const Point getPointAlongLineProportionally (const float proportionOfLength) const throw(); + bool clipToPath (const Path& path, + const bool keepSectionOutsidePath) throw(); - /** Returns the smallest distance between this line segment and a given point. - - So if the point is close to the line, this will return the perpendicular - distance from the line; if the point is a long way beyond one of the line's - end-point's, it'll return the straight-line distance to the nearest end-point. - - @param x x position of the point to test - @param y y position of the point to test - @returns the point's distance from the line - @see getPositionAlongLineOfNearestPoint - */ - float getDistanceFromLine (const float x, - const float y) const throw(); - - /** Finds the point on this line which is nearest to a given point, and - returns its position as a proportional position along the line. - - @param x x position of the point to test - @param y y position of the point to test - @returns a value 0 to 1.0 which is the distance along this line from the - line's start to the point which is nearest to the point passed-in. To - turn this number into a position, use getPointAlongLineProportionally(). - @see getDistanceFromLine, getPointAlongLineProportionally - */ - float findNearestPointTo (const float x, - const float y) const throw(); - - /** Returns true if the given point lies above this line. - - The return value is true if the point's y coordinate is less than the y - coordinate of this line at the given x (assuming the line extends infinitely - in both directions). - */ - bool isPointAbove (const float x, const float y) const throw(); - - /** Returns a shortened copy of this line. - - This will chop off part of the start of this line by a certain amount, (leaving the - end-point the same), and return the new line. - */ - const Line withShortenedStart (const float distanceToShortenBy) const throw(); - - /** Returns a shortened copy of this line. - - This will chop off part of the end of this line by a certain amount, (leaving the - start-point the same), and return the new line. - */ - const Line withShortenedEnd (const float distanceToShortenBy) const throw(); - - /** Cuts off parts of this line to keep the parts that are either inside or - outside a path. - - Note that this isn't smart enough to cope with situations where the - line would need to be cut into multiple pieces to correctly clip against - a re-entrant shape. - - @param path the path to clip against - @param keepSectionOutsidePath if true, it's the section outside the path - that will be kept; if false its the section inside - the path - @returns true if the line was changed. - */ - bool clipToPath (const Path& path, - const bool keepSectionOutsidePath) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - float startX, startY, endX, endY; + float startX, startY, endX, endY; }; #endif // __JUCE_LINE_JUCEHEADER__ @@ -20537,524 +10353,409 @@ private: class PixelRGB; class PixelAlpha; -/** - Represents a 32-bit ARGB pixel with premultiplied alpha, and can perform compositing - operations with it. - - This is used internally by the imaging classes. - - @see PixelRGB -*/ class JUCE_API PixelARGB { public: - /** Creates a pixel without defining its colour. */ - PixelARGB() throw() {} - ~PixelARGB() throw() {} + PixelARGB() throw() {} + ~PixelARGB() throw() {} - /** Creates a pixel from a 32-bit argb value. - */ - PixelARGB (const uint32 argb_) throw() - : argb (argb_) - { - } + PixelARGB (const uint32 argb_) throw() + : argb (argb_) + { + } - forcedinline uint32 getARGB() const throw() { return argb; } - forcedinline uint32 getRB() const throw() { return 0x00ff00ff & argb; } - forcedinline uint32 getAG() const throw() { return 0x00ff00ff & (argb >> 8); } + forcedinline uint32 getARGB() const throw() { return argb; } + forcedinline uint32 getRB() const throw() { return 0x00ff00ff & argb; } + forcedinline uint32 getAG() const throw() { return 0x00ff00ff & (argb >> 8); } - forcedinline uint8 getAlpha() const throw() { return components.a; } - forcedinline uint8 getRed() const throw() { return components.r; } - forcedinline uint8 getGreen() const throw() { return components.g; } - forcedinline uint8 getBlue() const throw() { return components.b; } + forcedinline uint8 getAlpha() const throw() { return components.a; } + forcedinline uint8 getRed() const throw() { return components.r; } + forcedinline uint8 getGreen() const throw() { return components.g; } + forcedinline uint8 getBlue() const throw() { return components.b; } - /** Blends another pixel onto this one. + forcedinline void blend (const PixelARGB& src) throw() + { + uint32 sargb = src.getARGB(); + const uint32 alpha = 0x100 - (sargb >> 24); - This takes into account the opacity of the pixel being overlaid, and blends - it accordingly. - */ - forcedinline void blend (const PixelARGB& src) throw() - { - uint32 sargb = src.getARGB(); - const uint32 alpha = 0x100 - (sargb >> 24); + sargb += 0x00ff00ff & ((getRB() * alpha) >> 8); + sargb += 0xff00ff00 & (getAG() * alpha); - sargb += 0x00ff00ff & ((getRB() * alpha) >> 8); - sargb += 0xff00ff00 & (getAG() * alpha); + argb = sargb; + } - argb = sargb; - } + forcedinline void blend (const PixelAlpha& src) throw(); - /** Blends another pixel onto this one. + forcedinline void blend (const PixelRGB& src) throw(); - This takes into account the opacity of the pixel being overlaid, and blends - it accordingly. - */ - forcedinline void blend (const PixelAlpha& src) throw(); + template + forcedinline void blend (const Pixel& src, uint32 extraAlpha) throw() + { + ++extraAlpha; - /** Blends another pixel onto this one. + uint32 sargb = ((extraAlpha * src.getAG()) & 0xff00ff00) + | (((extraAlpha * src.getRB()) >> 8) & 0x00ff00ff); - This takes into account the opacity of the pixel being overlaid, and blends - it accordingly. - */ - forcedinline void blend (const PixelRGB& src) throw(); + const uint32 alpha = 0x100 - (sargb >> 24); - /** Blends another pixel onto this one, applying an extra multiplier to its opacity. + sargb += 0x00ff00ff & ((getRB() * alpha) >> 8); + sargb += 0xff00ff00 & (getAG() * alpha); - The opacity of the pixel being overlaid is scaled by the extraAlpha factor before - being used, so this can blend semi-transparently from a PixelRGB argument. - */ - template - forcedinline void blend (const Pixel& src, uint32 extraAlpha) throw() - { - ++extraAlpha; + argb = sargb; + } - uint32 sargb = ((extraAlpha * src.getAG()) & 0xff00ff00) - | (((extraAlpha * src.getRB()) >> 8) & 0x00ff00ff); + template + forcedinline void tween (const Pixel& src, const uint32 amount) throw() + { + uint32 drb = getRB(); + drb += (((src.getRB() - drb) * amount) >> 8); + drb &= 0x00ff00ff; - const uint32 alpha = 0x100 - (sargb >> 24); + uint32 dag = getAG(); + dag += (((src.getAG() - dag) * amount) >> 8); + dag &= 0x00ff00ff; + dag <<= 8; - sargb += 0x00ff00ff & ((getRB() * alpha) >> 8); - sargb += 0xff00ff00 & (getAG() * alpha); + dag |= drb; + argb = dag; + } - argb = sargb; - } + template + forcedinline void set (const Pixel& src) throw() + { + argb = src.getARGB(); + } - /** Blends another pixel with this one, creating a colour that is somewhere - between the two, as specified by the amount. - */ - template - forcedinline void tween (const Pixel& src, const uint32 amount) throw() - { - uint32 drb = getRB(); - drb += (((src.getRB() - drb) * amount) >> 8); - drb &= 0x00ff00ff; + forcedinline void setAlpha (const uint8 newAlpha) throw() + { + components.a = newAlpha; + } - uint32 dag = getAG(); - dag += (((src.getAG() - dag) * amount) >> 8); - dag &= 0x00ff00ff; - dag <<= 8; + forcedinline void multiplyAlpha (int multiplier) throw() + { + ++multiplier; - dag |= drb; - argb = dag; - } + argb = ((multiplier * getAG()) & 0xff00ff00) + | (((multiplier * getRB()) >> 8) & 0x00ff00ff); + } - /** Copies another pixel colour over this one. + forcedinline void multiplyAlpha (const float multiplier) throw() + { + multiplyAlpha ((int) (multiplier * 256.0f)); + } - This doesn't blend it - this colour is simply replaced by the other one. - */ - template - forcedinline void set (const Pixel& src) throw() - { - argb = src.getARGB(); - } + void setARGB (const uint8 a, const uint8 r, const uint8 g, const uint8 b) throw() + { + components.b = b; + components.g = g; + components.r = r; + components.a = a; + } - /** Replaces the colour's alpha value with another one. */ - forcedinline void setAlpha (const uint8 newAlpha) throw() - { - components.a = newAlpha; - } + forcedinline void premultiply() throw() + { + const uint32 alpha = components.a; - /** Multiplies the colour's alpha value with another one. */ - forcedinline void multiplyAlpha (int multiplier) throw() - { - ++multiplier; + if (alpha < 0xff) + { + if (alpha == 0) + { + components.b = 0; + components.g = 0; + components.r = 0; + } + else + { + components.b = (uint8) ((components.b * alpha + 0x7f) >> 8); + components.g = (uint8) ((components.g * alpha + 0x7f) >> 8); + components.r = (uint8) ((components.r * alpha + 0x7f) >> 8); + } + } + } - argb = ((multiplier * getAG()) & 0xff00ff00) - | (((multiplier * getRB()) >> 8) & 0x00ff00ff); - } + forcedinline void unpremultiply() throw() + { + const uint32 alpha = components.a; - forcedinline void multiplyAlpha (const float multiplier) throw() - { - multiplyAlpha ((int) (multiplier * 256.0f)); - } + if (alpha < 0xff) + { + if (alpha == 0) + { + components.b = 0; + components.g = 0; + components.r = 0; + } + else + { + components.b = (uint8) jmin ((uint32) 0xff, (components.b * 0xff) / alpha); + components.g = (uint8) jmin ((uint32) 0xff, (components.g * 0xff) / alpha); + components.r = (uint8) jmin ((uint32) 0xff, (components.r * 0xff) / alpha); + } + } + } - /** Sets the pixel's colour from individual components. */ - void setARGB (const uint8 a, const uint8 r, const uint8 g, const uint8 b) throw() - { - components.b = b; - components.g = g; - components.r = r; - components.a = a; - } + forcedinline void desaturate() throw() + { + if (components.a < 0xff && components.a > 0) + { + const int newUnpremultipliedLevel = (0xff * ((int) components.r + (int) components.g + (int) components.b) / (3 * components.a)); - /** Premultiplies the pixel's RGB values by its alpha. */ - forcedinline void premultiply() throw() - { - const uint32 alpha = components.a; + components.r = components.g = components.b + = (uint8) ((newUnpremultipliedLevel * components.a + 0x7f) >> 8); + } + else + { + components.r = components.g = components.b + = (uint8) (((int) components.r + (int) components.g + (int) components.b) / 3); + } + } - if (alpha < 0xff) - { - if (alpha == 0) - { - components.b = 0; - components.g = 0; - components.r = 0; - } - else - { - components.b = (uint8) ((components.b * alpha + 0x7f) >> 8); - components.g = (uint8) ((components.g * alpha + 0x7f) >> 8); - components.r = (uint8) ((components.r * alpha + 0x7f) >> 8); - } - } - } - - /** Unpremultiplies the pixel's RGB values. */ - forcedinline void unpremultiply() throw() - { - const uint32 alpha = components.a; - - if (alpha < 0xff) - { - if (alpha == 0) - { - components.b = 0; - components.g = 0; - components.r = 0; - } - else - { - components.b = (uint8) jmin (0xff, (components.b * 0xff) / alpha); - components.g = (uint8) jmin (0xff, (components.g * 0xff) / alpha); - components.r = (uint8) jmin (0xff, (components.r * 0xff) / alpha); - } - } - } - - forcedinline void desaturate() throw() - { - if (components.a < 0xff && components.a > 0) - { - const int newUnpremultipliedLevel = (0xff * ((int) components.r + (int) components.g + (int) components.b) / (3 * components.a)); - - components.r = components.g = components.b - = (uint8) ((newUnpremultipliedLevel * components.a + 0x7f) >> 8); - } - else - { - components.r = components.g = components.b - = (uint8) (((int) components.r + (int) components.g + (int) components.b) / 3); - } - } - - /** The indexes of the different components in the byte layout of this type of colour. */ - #if JUCE_BIG_ENDIAN - enum { indexA = 0, indexR = 1, indexG = 2, indexB = 3 }; - #else - enum { indexA = 3, indexR = 2, indexG = 1, indexB = 0 }; - #endif + #if JUCE_BIG_ENDIAN + enum { indexA = 0, indexR = 1, indexG = 2, indexB = 3 }; + #else + enum { indexA = 3, indexR = 2, indexG = 1, indexB = 0 }; + #endif private: - union - { - uint32 argb; + union + { + uint32 argb; - struct - { + struct + { #if JUCE_BIG_ENDIAN - uint8 a : 8, r : 8, g : 8, b : 8; + uint8 a : 8, r : 8, g : 8, b : 8; #else - uint8 b, g, r, a; + uint8 b, g, r, a; #endif - } PACKED components; - }; + } PACKED components; + }; } PACKED; -/** - Represents a 24-bit RGB pixel, and can perform compositing operations on it. - - This is used internally by the imaging classes. - - @see PixelARGB -*/ class JUCE_API PixelRGB { public: - /** Creates a pixel without defining its colour. */ - PixelRGB() throw() {} - ~PixelRGB() throw() {} + PixelRGB() throw() {} + ~PixelRGB() throw() {} - /** Creates a pixel from a 32-bit argb value. + PixelRGB (const uint32 argb) throw() + { + r = (uint8) (argb >> 16); + g = (uint8) (argb >> 8); + b = (uint8) (argb); + } - (The argb format is that used by PixelARGB) - */ - PixelRGB (const uint32 argb) throw() - { - r = (uint8) (argb >> 16); - g = (uint8) (argb >> 8); - b = (uint8) (argb); - } + forcedinline uint32 getARGB() const throw() { return 0xff000000 | b | (g << 8) | (r << 16); } + forcedinline uint32 getRB() const throw() { return b | (uint32) (r << 16); } + forcedinline uint32 getAG() const throw() { return 0xff0000 | g; } - forcedinline uint32 getARGB() const throw() { return 0xff000000 | b | (g << 8) | (r << 16); } - forcedinline uint32 getRB() const throw() { return b | (uint32) (r << 16); } - forcedinline uint32 getAG() const throw() { return 0xff0000 | g; } + forcedinline uint8 getAlpha() const throw() { return 0xff; } + forcedinline uint8 getRed() const throw() { return r; } + forcedinline uint8 getGreen() const throw() { return g; } + forcedinline uint8 getBlue() const throw() { return b; } - forcedinline uint8 getAlpha() const throw() { return 0xff; } - forcedinline uint8 getRed() const throw() { return r; } - forcedinline uint8 getGreen() const throw() { return g; } - forcedinline uint8 getBlue() const throw() { return b; } + forcedinline void blend (const PixelARGB& src) throw() + { + uint32 sargb = src.getARGB(); + const uint32 alpha = 0x100 - (sargb >> 24); - /** Blends another pixel onto this one. + sargb += 0x00ff00ff & ((getRB() * alpha) >> 8); + sargb += 0x0000ff00 & (g * alpha); - This takes into account the opacity of the pixel being overlaid, and blends - it accordingly. - */ - forcedinline void blend (const PixelARGB& src) throw() - { - uint32 sargb = src.getARGB(); - const uint32 alpha = 0x100 - (sargb >> 24); + r = (uint8) (sargb >> 16); + g = (uint8) (sargb >> 8); + b = (uint8) sargb; + } - sargb += 0x00ff00ff & ((getRB() * alpha) >> 8); - sargb += 0x0000ff00 & (g * alpha); + forcedinline void blend (const PixelRGB& src) throw() + { + set (src); + } - r = (uint8) (sargb >> 16); - g = (uint8) (sargb >> 8); - b = (uint8) sargb; - } + forcedinline void blend (const PixelAlpha& src) throw(); - forcedinline void blend (const PixelRGB& src) throw() - { - set (src); - } + template + forcedinline void blend (const Pixel& src, uint32 extraAlpha) throw() + { + ++extraAlpha; + const uint32 srb = (extraAlpha * src.getRB()) >> 8; + const uint32 sag = extraAlpha * src.getAG(); + uint32 sargb = (sag & 0xff00ff00) | (srb & 0x00ff00ff); - forcedinline void blend (const PixelAlpha& src) throw(); + const uint32 alpha = 0x100 - (sargb >> 24); - /** Blends another pixel onto this one, applying an extra multiplier to its opacity. + sargb += 0x00ff00ff & ((getRB() * alpha) >> 8); + sargb += 0x0000ff00 & (g * alpha); - The opacity of the pixel being overlaid is scaled by the extraAlpha factor before - being used, so this can blend semi-transparently from a PixelRGB argument. - */ - template - forcedinline void blend (const Pixel& src, uint32 extraAlpha) throw() - { - ++extraAlpha; - const uint32 srb = (extraAlpha * src.getRB()) >> 8; - const uint32 sag = extraAlpha * src.getAG(); - uint32 sargb = (sag & 0xff00ff00) | (srb & 0x00ff00ff); + b = (uint8) sargb; + g = (uint8) (sargb >> 8); + r = (uint8) (sargb >> 16); + } - const uint32 alpha = 0x100 - (sargb >> 24); + template + forcedinline void tween (const Pixel& src, const uint32 amount) throw() + { + uint32 drb = getRB(); + drb += (((src.getRB() - drb) * amount) >> 8); - sargb += 0x00ff00ff & ((getRB() * alpha) >> 8); - sargb += 0x0000ff00 & (g * alpha); + uint32 dag = getAG(); + dag += (((src.getAG() - dag) * amount) >> 8); - b = (uint8) sargb; - g = (uint8) (sargb >> 8); - r = (uint8) (sargb >> 16); - } + b = (uint8) drb; + g = (uint8) dag; + r = (uint8) (drb >> 16); + } - /** Blends another pixel with this one, creating a colour that is somewhere - between the two, as specified by the amount. - */ - template - forcedinline void tween (const Pixel& src, const uint32 amount) throw() - { - uint32 drb = getRB(); - drb += (((src.getRB() - drb) * amount) >> 8); + template + forcedinline void set (const Pixel& src) throw() + { + b = src.getBlue(); + g = src.getGreen(); + r = src.getRed(); + } - uint32 dag = getAG(); - dag += (((src.getAG() - dag) * amount) >> 8); + forcedinline void setAlpha (const uint8) throw() {} - b = (uint8) drb; - g = (uint8) dag; - r = (uint8) (drb >> 16); - } + forcedinline void multiplyAlpha (int) throw() {} - /** Copies another pixel colour over this one. + void setARGB (const uint8, const uint8 r_, const uint8 g_, const uint8 b_) throw() + { + r = r_; + g = g_; + b = b_; + } - This doesn't blend it - this colour is simply replaced by the other one. - Because PixelRGB has no alpha channel, any alpha value in the source pixel - is thrown away. - */ - template - forcedinline void set (const Pixel& src) throw() - { - b = src.getBlue(); - g = src.getGreen(); - r = src.getRed(); - } + forcedinline void premultiply() throw() {} - /** This method is included for compatibility with the PixelARGB class. */ - forcedinline void setAlpha (const uint8) throw() {} + forcedinline void unpremultiply() throw() {} - /** Multiplies the colour's alpha value with another one. */ - forcedinline void multiplyAlpha (int) throw() {} + forcedinline void desaturate() throw() + { + r = g = b = (uint8) (((int) r + (int) g + (int) b) / 3); + } - /** Sets the pixel's colour from individual components. */ - void setARGB (const uint8, const uint8 r_, const uint8 g_, const uint8 b_) throw() - { - r = r_; - g = g_; - b = b_; - } - - /** Premultiplies the pixel's RGB values by its alpha. */ - forcedinline void premultiply() throw() {} - - /** Unpremultiplies the pixel's RGB values. */ - forcedinline void unpremultiply() throw() {} - - forcedinline void desaturate() throw() - { - r = g = b = (uint8) (((int) r + (int) g + (int) b) / 3); - } - - /** The indexes of the different components in the byte layout of this type of colour. */ - #if JUCE_MAC - enum { indexR = 0, indexG = 1, indexB = 2 }; - #else - enum { indexR = 2, indexG = 1, indexB = 0 }; - #endif + #if JUCE_MAC + enum { indexR = 0, indexG = 1, indexB = 2 }; + #else + enum { indexR = 2, indexG = 1, indexB = 0 }; + #endif private: #if JUCE_MAC - uint8 r, g, b; + uint8 r, g, b; #else - uint8 b, g, r; + uint8 b, g, r; #endif } PACKED; forcedinline void PixelARGB::blend (const PixelRGB& src) throw() { - set (src); + set (src); } -/** - Represents an 8-bit single-channel pixel, and can perform compositing operations on it. - - This is used internally by the imaging classes. - - @see PixelARGB, PixelRGB -*/ class JUCE_API PixelAlpha { public: - /** Creates a pixel without defining its colour. */ - PixelAlpha() throw() {} - ~PixelAlpha() throw() {} + PixelAlpha() throw() {} + ~PixelAlpha() throw() {} - /** Creates a pixel from a 32-bit argb value. + PixelAlpha (const uint32 argb) throw() + { + a = (uint8) (argb >> 24); + } - (The argb format is that used by PixelARGB) - */ - PixelAlpha (const uint32 argb) throw() - { - a = (uint8) (argb >> 24); - } + forcedinline uint32 getARGB() const throw() { return (((uint32) a) << 24) | (((uint32) a) << 16) | (((uint32) a) << 8) | a; } + forcedinline uint32 getRB() const throw() { return (((uint32) a) << 16) | a; } + forcedinline uint32 getAG() const throw() { return (((uint32) a) << 16) | a; } - forcedinline uint32 getARGB() const throw() { return (((uint32) a) << 24) | (((uint32) a) << 16) | (((uint32) a) << 8) | a; } - forcedinline uint32 getRB() const throw() { return (((uint32) a) << 16) | a; } - forcedinline uint32 getAG() const throw() { return (((uint32) a) << 16) | a; } + forcedinline uint8 getAlpha() const throw() { return a; } + forcedinline uint8 getRed() const throw() { return 0; } + forcedinline uint8 getGreen() const throw() { return 0; } + forcedinline uint8 getBlue() const throw() { return 0; } - forcedinline uint8 getAlpha() const throw() { return a; } - forcedinline uint8 getRed() const throw() { return 0; } - forcedinline uint8 getGreen() const throw() { return 0; } - forcedinline uint8 getBlue() const throw() { return 0; } + template + forcedinline void blend (const Pixel& src) throw() + { + const int srcA = src.getAlpha(); + a = (uint8) ((a * (0x100 - srcA) >> 8) + srcA); + } - /** Blends another pixel onto this one. + template + forcedinline void blend (const Pixel& src, uint32 extraAlpha) throw() + { + ++extraAlpha; + const int srcAlpha = (extraAlpha * src.getAlpha()) >> 8; + a = (uint8) ((a * (0x100 - srcAlpha) >> 8) + srcAlpha); + } - This takes into account the opacity of the pixel being overlaid, and blends - it accordingly. - */ - template - forcedinline void blend (const Pixel& src) throw() - { - const int srcA = src.getAlpha(); - a = (uint8) ((a * (0x100 - srcA) >> 8) + srcA); - } + template + forcedinline void tween (const Pixel& src, const uint32 amount) throw() + { + a += ((src,getAlpha() - a) * amount) >> 8; + } - /** Blends another pixel onto this one, applying an extra multiplier to its opacity. + template + forcedinline void set (const Pixel& src) throw() + { + a = src.getAlpha(); + } - The opacity of the pixel being overlaid is scaled by the extraAlpha factor before - being used, so this can blend semi-transparently from a PixelRGB argument. - */ - template - forcedinline void blend (const Pixel& src, uint32 extraAlpha) throw() - { - ++extraAlpha; - const int srcAlpha = (extraAlpha * src.getAlpha()) >> 8; - a = (uint8) ((a * (0x100 - srcAlpha) >> 8) + srcAlpha); - } + forcedinline void setAlpha (const uint8 newAlpha) throw() + { + a = newAlpha; + } - /** Blends another pixel with this one, creating a colour that is somewhere - between the two, as specified by the amount. - */ - template - forcedinline void tween (const Pixel& src, const uint32 amount) throw() - { - a += ((src,getAlpha() - a) * amount) >> 8; - } + forcedinline void multiplyAlpha (int multiplier) throw() + { + ++multiplier; + a = (uint8) ((a * multiplier) >> 8); + } - /** Copies another pixel colour over this one. + forcedinline void multiplyAlpha (const float multiplier) throw() + { + a = (uint8) (a * multiplier); + } - This doesn't blend it - this colour is simply replaced by the other one. - */ - template - forcedinline void set (const Pixel& src) throw() - { - a = src.getAlpha(); - } + forcedinline void setARGB (const uint8 a_, const uint8 r, const uint8 g, const uint8 b) throw() + { + a = a_; + } - /** Replaces the colour's alpha value with another one. */ - forcedinline void setAlpha (const uint8 newAlpha) throw() - { - a = newAlpha; - } + forcedinline void premultiply() throw() + { + } - /** Multiplies the colour's alpha value with another one. */ - forcedinline void multiplyAlpha (int multiplier) throw() - { - ++multiplier; - a = (uint8) ((a * multiplier) >> 8); - } + forcedinline void unpremultiply() throw() + { + } - forcedinline void multiplyAlpha (const float multiplier) throw() - { - a = (uint8) (a * multiplier); - } - - /** Sets the pixel's colour from individual components. */ - forcedinline void setARGB (const uint8 a_, const uint8 r, const uint8 g, const uint8 b) throw() - { - a = a_; - } - - /** Premultiplies the pixel's RGB values by its alpha. */ - forcedinline void premultiply() throw() - { - } - - /** Unpremultiplies the pixel's RGB values. */ - forcedinline void unpremultiply() throw() - { - } - - forcedinline void desaturate() throw() - { - } + forcedinline void desaturate() throw() + { + } private: - uint8 a : 8; + uint8 a : 8; } PACKED; forcedinline void PixelRGB::blend (const PixelAlpha& src) throw() { - blend (PixelARGB (src.getARGB())); + blend (PixelARGB (src.getARGB())); } forcedinline void PixelARGB::blend (const PixelAlpha& src) throw() { - uint32 sargb = src.getARGB(); - const uint32 alpha = 0x100 - (sargb >> 24); + uint32 sargb = src.getARGB(); + const uint32 alpha = 0x100 - (sargb >> 24); - sargb += 0x00ff00ff & ((getRB() * alpha) >> 8); - sargb += 0xff00ff00 & (getAG() * alpha); + sargb += 0x00ff00ff & ((getRB() * alpha) >> 8); + sargb += 0xff00ff00 & (getAG() * alpha); - argb = sargb; + argb = sargb; } #if JUCE_MSVC @@ -21066,395 +10767,204 @@ forcedinline void PixelARGB::blend (const PixelAlpha& src) throw() #endif // __JUCE_PIXELFORMATS_JUCEHEADER__ /********* End of inlined file: juce_PixelFormats.h *********/ -/** - Represents a colour, also including a transparency value. - - The colour is stored internally as unsigned 8-bit red, green, blue and alpha values. -*/ class JUCE_API Colour { public: - /** Creates a transparent black colour. */ - Colour() throw(); - - /** Creates a copy of another Colour object. */ - Colour (const Colour& other) throw(); - - /** Creates a colour from a 32-bit ARGB value. - - The format of this number is: - ((alpha << 24) | (red << 16) | (green << 8) | blue). - - All components in the range 0x00 to 0xff. - An alpha of 0x00 is completely transparent, alpha of 0xff is opaque. - - @see getPixelARGB - */ - explicit Colour (const uint32 argb) throw(); - - /** Creates an opaque colour using 8-bit red, green and blue values */ - Colour (const uint8 red, - const uint8 green, - const uint8 blue) throw(); + Colour() throw(); - /** Creates an opaque colour using 8-bit red, green and blue values */ - static const Colour fromRGB (const uint8 red, - const uint8 green, - const uint8 blue) throw(); - - /** Creates a colour using 8-bit red, green, blue and alpha values. */ - Colour (const uint8 red, - const uint8 green, - const uint8 blue, - const uint8 alpha) throw(); + Colour (const Colour& other) throw(); - /** Creates a colour using 8-bit red, green, blue and alpha values. */ - static const Colour fromRGBA (const uint8 red, - const uint8 green, - const uint8 blue, - const uint8 alpha) throw(); + explicit Colour (const uint32 argb) throw(); - /** Creates a colour from 8-bit red, green, and blue values, and a floating-point alpha. + Colour (const uint8 red, + const uint8 green, + const uint8 blue) throw(); - Alpha of 0.0 is transparent, alpha of 1.0f is opaque. - Values outside the valid range will be clipped. - */ - Colour (const uint8 red, - const uint8 green, - const uint8 blue, - const float alpha) throw(); + static const Colour fromRGB (const uint8 red, + const uint8 green, + const uint8 blue) throw(); - /** Creates a colour using 8-bit red, green, blue and float alpha values. */ - static const Colour fromRGBAFloat (const uint8 red, - const uint8 green, - const uint8 blue, - const float alpha) throw(); + Colour (const uint8 red, + const uint8 green, + const uint8 blue, + const uint8 alpha) throw(); - /** Creates a colour using floating point hue, saturation and brightness values, and an 8-bit alpha. + static const Colour fromRGBA (const uint8 red, + const uint8 green, + const uint8 blue, + const uint8 alpha) throw(); - The floating point values must be between 0.0 and 1.0. - An alpha of 0x00 is completely transparent, alpha of 0xff is opaque. - Values outside the valid range will be clipped. - */ - Colour (const float hue, - const float saturation, - const float brightness, - const uint8 alpha) throw(); + Colour (const uint8 red, + const uint8 green, + const uint8 blue, + const float alpha) throw(); - /** Creates a colour using floating point hue, saturation, brightness and alpha values. + static const Colour fromRGBAFloat (const uint8 red, + const uint8 green, + const uint8 blue, + const float alpha) throw(); - All values must be between 0.0 and 1.0. - Numbers outside the valid range will be clipped. - */ - Colour (const float hue, - const float saturation, - const float brightness, - const float alpha) throw(); + Colour (const float hue, + const float saturation, + const float brightness, + const uint8 alpha) throw(); - /** Creates a colour using floating point hue, saturation and brightness values, and an 8-bit alpha. + Colour (const float hue, + const float saturation, + const float brightness, + const float alpha) throw(); - The floating point values must be between 0.0 and 1.0. - An alpha of 0x00 is completely transparent, alpha of 0xff is opaque. - Values outside the valid range will be clipped. - */ - static const Colour fromHSV (const float hue, - const float saturation, - const float brightness, - const float alpha) throw(); + static const Colour fromHSV (const float hue, + const float saturation, + const float brightness, + const float alpha) throw(); - /** Destructor. */ - ~Colour() throw(); + ~Colour() throw(); - /** Copies another Colour object. */ - const Colour& operator= (const Colour& other) throw(); + const Colour& operator= (const Colour& other) throw(); - /** Compares two colours. */ - bool operator== (const Colour& other) const throw(); - /** Compares two colours. */ - bool operator!= (const Colour& other) const throw(); + bool operator== (const Colour& other) const throw(); + bool operator!= (const Colour& other) const throw(); - /** Returns the red component of this colour. + uint8 getRed() const throw() { return argb.getRed(); } - @returns a value between 0x00 and 0xff. - */ - uint8 getRed() const throw() { return argb.getRed(); } + uint8 getGreen() const throw() { return argb.getGreen(); } - /** Returns the green component of this colour. + uint8 getBlue() const throw() { return argb.getBlue(); } - @returns a value between 0x00 and 0xff. - */ - uint8 getGreen() const throw() { return argb.getGreen(); } + float getFloatRed() const throw(); - /** Returns the blue component of this colour. + float getFloatGreen() const throw(); - @returns a value between 0x00 and 0xff. - */ - uint8 getBlue() const throw() { return argb.getBlue(); } + float getFloatBlue() const throw(); - /** Returns the red component of this colour as a floating point value. + const PixelARGB getPixelARGB() const throw(); - @returns a value between 0.0 and 1.0 - */ - float getFloatRed() const throw(); + uint32 getARGB() const throw(); - /** Returns the green component of this colour as a floating point value. + uint8 getAlpha() const throw() { return argb.getAlpha(); } - @returns a value between 0.0 and 1.0 - */ - float getFloatGreen() const throw(); + float getFloatAlpha() const throw(); - /** Returns the blue component of this colour as a floating point value. + bool isOpaque() const throw(); - @returns a value between 0.0 and 1.0 - */ - float getFloatBlue() const throw(); + bool isTransparent() const throw(); - /** Returns a premultiplied ARGB pixel object that represents this colour. - */ - const PixelARGB getPixelARGB() const throw(); + const Colour withAlpha (const uint8 newAlpha) const throw(); - /** Returns a 32-bit integer that represents this colour. + const Colour withAlpha (const float newAlpha) const throw(); - The format of this number is: - ((alpha << 24) | (red << 16) | (green << 16) | blue). - */ - uint32 getARGB() const throw(); + const Colour withMultipliedAlpha (const float alphaMultiplier) const throw(); - /** Returns the colour's alpha (opacity). + const Colour overlaidWith (const Colour& foregroundColour) const throw(); - Alpha of 0x00 is completely transparent, 0xff is completely opaque. - */ - uint8 getAlpha() const throw() { return argb.getAlpha(); } + const Colour interpolatedWith (const Colour& other, float proportionOfOther) const throw(); - /** Returns the colour's alpha (opacity) as a floating point value. + float getHue() const throw(); - Alpha of 0.0 is completely transparent, 1.0 is completely opaque. - */ - float getFloatAlpha() const throw(); + float getSaturation() const throw(); - /** Returns true if this colour is completely opaque. + float getBrightness() const throw(); - Equivalent to (getAlpha() == 0xff). - */ - bool isOpaque() const throw(); + void getHSB (float& hue, + float& saturation, + float& brightness) const throw(); - /** Returns true if this colour is completely transparent. + const Colour withHue (const float newHue) const throw(); - Equivalent to (getAlpha() == 0x00). - */ - bool isTransparent() const throw(); + const Colour withSaturation (const float newSaturation) const throw(); - /** Returns a colour that's the same colour as this one, but with a new alpha value. */ - const Colour withAlpha (const uint8 newAlpha) const throw(); + const Colour withBrightness (const float newBrightness) const throw(); - /** Returns a colour that's the same colour as this one, but with a new alpha value. */ - const Colour withAlpha (const float newAlpha) const throw(); + const Colour withRotatedHue (const float amountToRotate) const throw(); - /** Returns a colour that's the same colour as this one, but with a modified alpha value. + const Colour withMultipliedSaturation (const float multiplier) const throw(); - The new colour's alpha will be this object's alpha multiplied by the value passed-in. - */ - const Colour withMultipliedAlpha (const float alphaMultiplier) const throw(); + const Colour withMultipliedBrightness (const float amount) const throw(); - /** Returns a colour that is the result of alpha-compositing a new colour over this one. + const Colour brighter (float amountBrighter = 0.4f) const throw(); - If the foreground colour is semi-transparent, it is blended onto this colour - accordingly. - */ - const Colour overlaidWith (const Colour& foregroundColour) const throw(); + const Colour darker (float amountDarker = 0.4f) const throw(); - /** Returns a colour that lies somewhere between this one and another. + const Colour contrasting (const float amount = 1.0f) const throw(); - If amountOfOther is zero, the result is 100% this colour, if amountOfOther - is 1.0, the result is 100% of the other colour. - */ - const Colour interpolatedWith (const Colour& other, float proportionOfOther) const throw(); + static const Colour contrasting (const Colour& colour1, + const Colour& colour2) throw(); - /** Returns the colour's hue component. - The value returned is in the range 0.0 to 1.0 - */ - float getHue() const throw(); + static const Colour greyLevel (const float brightness) throw(); - /** Returns the colour's saturation component. - The value returned is in the range 0.0 to 1.0 - */ - float getSaturation() const throw(); + const String toString() const throw(); - /** Returns the colour's brightness component. - The value returned is in the range 0.0 to 1.0 - */ - float getBrightness() const throw(); + static const Colour fromString (const String& encodedColourString); - /** Returns the colour's hue, saturation and brightness components all at once. - The values returned are in the range 0.0 to 1.0 - */ - void getHSB (float& hue, - float& saturation, - float& brightness) const throw(); - - /** Returns a copy of this colour with a different hue. */ - const Colour withHue (const float newHue) const throw(); - - /** Returns a copy of this colour with a different saturation. */ - const Colour withSaturation (const float newSaturation) const throw(); - - /** Returns a copy of this colour with a different brightness. - @see brighter, darker, withMultipliedBrightness - */ - const Colour withBrightness (const float newBrightness) const throw(); - - /** Returns a copy of this colour with it hue rotated. - - The new colour's hue is ((this->getHue() + amountToRotate) % 1.0) - - @see brighter, darker, withMultipliedBrightness - */ - const Colour withRotatedHue (const float amountToRotate) const throw(); - - /** Returns a copy of this colour with its saturation multiplied by the given value. - - The new colour's saturation is (this->getSaturation() * multiplier) - (the result is clipped to legal limits). - */ - const Colour withMultipliedSaturation (const float multiplier) const throw(); - - /** Returns a copy of this colour with its brightness multiplied by the given value. - - The new colour's saturation is (this->getBrightness() * multiplier) - (the result is clipped to legal limits). - */ - const Colour withMultipliedBrightness (const float amount) const throw(); - - /** Returns a brighter version of this colour. - - @param amountBrighter how much brighter to make it - a value from 0 to 1.0 where 0 is - unchanged, and higher values make it brighter - @see withMultipliedBrightness - */ - const Colour brighter (float amountBrighter = 0.4f) const throw(); - - /** Returns a darker version of this colour. - - @param amountDarker how much darker to make it - a value from 0 to 1.0 where 0 is - unchanged, and higher values make it darker - @see withMultipliedBrightness - */ - const Colour darker (float amountDarker = 0.4f) const throw(); - - /** Returns a colour that will be clearly visible against this colour. - - The amount parameter indicates how contrasting the new colour should - be, so e.g. Colours::black.contrasting (0.1f) will return a colour - that's just a little bit lighter; Colours::black.contrasting (1.0f) will - return white; Colours::white.contrasting (1.0f) will return black, etc. - */ - const Colour contrasting (const float amount = 1.0f) const throw(); - - /** Returns a colour that contrasts against two colours. - - Looks for a colour that contrasts with both of the colours passed-in. - - Handy for things like choosing a highlight colour in text editors, etc. - */ - static const Colour contrasting (const Colour& colour1, - const Colour& colour2) throw(); - - /** Returns an opaque shade of grey. - - @param brightness the level of grey to return - 0 is black, 1.0 is white - */ - static const Colour greyLevel (const float brightness) throw(); - - /** Returns a stringified version of this colour. - - The string can be turned back into a colour using the fromString() method. - */ - const String toString() const throw(); - - /** Reads the colour from a string that was created with toString(). - */ - static const Colour fromString (const String& encodedColourString); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - PixelARGB argb; + PixelARGB argb; }; #endif // __JUCE_COLOUR_JUCEHEADER__ /********* End of inlined file: juce_Colour.h *********/ -/** - Contains a set of predefined named colours (mostly standard HTML colours) - - @see Colour, Colours::greyLevel -*/ class Colours { public: - static JUCE_API const Colour + static JUCE_API const Colour - transparentBlack, /**< ARGB = 0x00000000 */ - transparentWhite, /**< ARGB = 0x00ffffff */ + transparentBlack, /**< ARGB = 0x00000000 */ + transparentWhite, /**< ARGB = 0x00ffffff */ - black, /**< ARGB = 0xff000000 */ - white, /**< ARGB = 0xffffffff */ - blue, /**< ARGB = 0xff0000ff */ - grey, /**< ARGB = 0xff808080 */ - green, /**< ARGB = 0xff008000 */ - red, /**< ARGB = 0xffff0000 */ - yellow, /**< ARGB = 0xffffff00 */ + black, /**< ARGB = 0xff000000 */ + white, /**< ARGB = 0xffffffff */ + blue, /**< ARGB = 0xff0000ff */ + grey, /**< ARGB = 0xff808080 */ + green, /**< ARGB = 0xff008000 */ + red, /**< ARGB = 0xffff0000 */ + yellow, /**< ARGB = 0xffffff00 */ - aliceblue, antiquewhite, aqua, aquamarine, - azure, beige, bisque, blanchedalmond, - blueviolet, brown, burlywood, cadetblue, - chartreuse, chocolate, coral, cornflowerblue, - cornsilk, crimson, cyan, darkblue, - darkcyan, darkgoldenrod, darkgrey, darkgreen, - darkkhaki, darkmagenta, darkolivegreen, darkorange, - darkorchid, darkred, darksalmon, darkseagreen, - darkslateblue, darkslategrey, darkturquoise, darkviolet, - deeppink, deepskyblue, dimgrey, dodgerblue, - firebrick, floralwhite, forestgreen, fuchsia, - gainsboro, gold, goldenrod, greenyellow, - honeydew, hotpink, indianred, indigo, - ivory, khaki, lavender, lavenderblush, - lemonchiffon, lightblue, lightcoral, lightcyan, - lightgoldenrodyellow, lightgreen, lightgrey, lightpink, - lightsalmon, lightseagreen, lightskyblue, lightslategrey, - lightsteelblue, lightyellow, lime, limegreen, - linen, magenta, maroon, mediumaquamarine, - mediumblue, mediumorchid, mediumpurple, mediumseagreen, - mediumslateblue, mediumspringgreen, mediumturquoise, mediumvioletred, - midnightblue, mintcream, mistyrose, navajowhite, - navy, oldlace, olive, olivedrab, - orange, orangered, orchid, palegoldenrod, - palegreen, paleturquoise, palevioletred, papayawhip, - peachpuff, peru, pink, plum, - powderblue, purple, rosybrown, royalblue, - saddlebrown, salmon, sandybrown, seagreen, - seashell, sienna, silver, skyblue, - slateblue, slategrey, snow, springgreen, - steelblue, tan, teal, thistle, - tomato, turquoise, violet, wheat, - whitesmoke, yellowgreen; + aliceblue, antiquewhite, aqua, aquamarine, + azure, beige, bisque, blanchedalmond, + blueviolet, brown, burlywood, cadetblue, + chartreuse, chocolate, coral, cornflowerblue, + cornsilk, crimson, cyan, darkblue, + darkcyan, darkgoldenrod, darkgrey, darkgreen, + darkkhaki, darkmagenta, darkolivegreen, darkorange, + darkorchid, darkred, darksalmon, darkseagreen, + darkslateblue, darkslategrey, darkturquoise, darkviolet, + deeppink, deepskyblue, dimgrey, dodgerblue, + firebrick, floralwhite, forestgreen, fuchsia, + gainsboro, gold, goldenrod, greenyellow, + honeydew, hotpink, indianred, indigo, + ivory, khaki, lavender, lavenderblush, + lemonchiffon, lightblue, lightcoral, lightcyan, + lightgoldenrodyellow, lightgreen, lightgrey, lightpink, + lightsalmon, lightseagreen, lightskyblue, lightslategrey, + lightsteelblue, lightyellow, lime, limegreen, + linen, magenta, maroon, mediumaquamarine, + mediumblue, mediumorchid, mediumpurple, mediumseagreen, + mediumslateblue, mediumspringgreen, mediumturquoise, mediumvioletred, + midnightblue, mintcream, mistyrose, navajowhite, + navy, oldlace, olive, olivedrab, + orange, orangered, orchid, palegoldenrod, + palegreen, paleturquoise, palevioletred, papayawhip, + peachpuff, peru, pink, plum, + powderblue, purple, rosybrown, royalblue, + saddlebrown, salmon, sandybrown, seagreen, + seashell, sienna, silver, skyblue, + slateblue, slategrey, snow, springgreen, + steelblue, tan, teal, thistle, + tomato, turquoise, violet, wheat, + whitesmoke, yellowgreen; - /** Attempts to look up a string in the list of known colour names, and return - the appropriate colour. - - A non-case-sensitive search is made of the list of predefined colours, and - if a match is found, that colour is returned. If no match is found, the - colour passed in as the defaultColour parameter is returned. - */ - static JUCE_API const Colour findColourForName (const String& colourName, - const Colour& defaultColour); + static JUCE_API const Colour findColourForName (const String& colourName, + const Colour& defaultColour); private: - // this isn't a class you should ever instantiate - it's just here for the - // static values in it. - Colours(); + // this isn't a class you should ever instantiate - it's just here for the + // static values in it. + Colours(); }; #endif // __JUCE_COLOURS_JUCEHEADER__ @@ -21468,122 +10978,55 @@ private: #ifndef __JUCE_COLOURGRADIENT_JUCEHEADER__ #define __JUCE_COLOURGRADIENT_JUCEHEADER__ -/** - Describes the layout and colours that should be used to paint a colour gradient. - - @see Graphics::setGradientFill -*/ class JUCE_API ColourGradient { public: - /** Creates a gradient object. + ColourGradient (const Colour& colour1, + const float x1, + const float y1, + const Colour& colour2, + const float x2, + const float y2, + const bool isRadial) throw(); - (x1, y1) is the location to draw with colour1. Likewise (x2, y2) is where - colour2 should be. In between them there's a gradient. + ColourGradient() throw(); - If isRadial is true, the colours form a circular gradient with (x1, y1) at - its centre. + ~ColourGradient() throw(); - The alpha transparencies of the colours are used, so note that - if you blend from transparent to a solid colour, the RGB of the transparent - colour will become visible in parts of the gradient. e.g. blending - from Colour::transparentBlack to Colours::white will produce a - muddy grey colour midway, but Colour::transparentWhite to Colours::white - will be white all the way across. + void clearColours() throw(); - @see ColourGradient - */ - ColourGradient (const Colour& colour1, - const float x1, - const float y1, - const Colour& colour2, - const float x2, - const float y2, - const bool isRadial) throw(); + void addColour (const double proportionAlongGradient, + const Colour& colour) throw(); - /** Creates an uninitialised gradient. + void multiplyOpacity (const float multiplier) throw(); - If you use this constructor instead of the other one, be sure to set all the - object's public member variables before using it! - */ - ColourGradient() throw(); + int getNumColours() const throw(); - /** Destructor */ - ~ColourGradient() throw(); + double getColourPosition (const int index) const throw(); - /** Removes any colours that have been added. + const Colour getColour (const int index) const throw(); - This will also remove any start and end colours, so the gradient won't work. You'll - need to add more colours with addColour(). - */ - void clearColours() throw(); + const Colour getColourAtPosition (const float position) const throw(); - /** Adds a colour at a point along the length of the gradient. + int createLookupTable (const AffineTransform& transform, HeapBlock & resultLookupTable) const throw(); - This allows the gradient to go through a spectrum of colours, instead of just a - start and end colour. + bool isOpaque() const throw(); - @param proportionAlongGradient a value between 0 and 1.0, which is the proportion - of the distance along the line between the two points - at which the colour should occur. - @param colour the colour that should be used at this point - */ - void addColour (const double proportionAlongGradient, - const Colour& colour) throw(); + bool isInvisible() const throw(); - /** Multiplies the alpha value of all the colours by the given scale factor */ - void multiplyOpacity (const float multiplier) throw(); + float x1; + float y1; - /** Returns the number of colour-stops that have been added. */ - int getNumColours() const throw(); + float x2; + float y2; - /** Returns the position along the length of the gradient of the colour with this index. + bool isRadial; - The index is from 0 to getNumColours() - 1. The return value will be between 0.0 and 1.0 - */ - double getColourPosition (const int index) const throw(); - - /** Returns the colour that was added with a given index. - - The index is from 0 to getNumColours() - 1. The return value will be between 0.0 and 1.0 - */ - const Colour getColour (const int index) const throw(); - - /** Returns the an interpolated colour at any position along the gradient. - @param position the position along the gradient, between 0 and 1 - */ - const Colour getColourAtPosition (const float position) const throw(); - - /** Creates a set of interpolated premultiplied ARGB values. - This will resize the HeapBlock, fill it with the colours, and will return the number of - colours that it added. - */ - int createLookupTable (const AffineTransform& transform, HeapBlock & resultLookupTable) const throw(); - - /** Returns true if all colours are opaque. */ - bool isOpaque() const throw(); - - /** Returns true if all colours are completely transparent. */ - bool isInvisible() const throw(); - - float x1; - float y1; - - float x2; - float y2; - - /** If true, the gradient should be filled circularly, centred around - (x1, y1), with (x2, y2) defining a point on the circumference. - - If false, the gradient is linear between the two points. - */ - bool isRadial; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - Array colours; + Array colours; }; #endif // __JUCE_COLOURGRADIENT_JUCEHEADER__ @@ -21591,104 +11034,48 @@ private: class Image; -/** - Represents a colour or fill pattern to use for rendering paths. - - This is used by the Graphics and DrawablePath classes as a way to encapsulate - a brush type. It can either be a solid colour, a gradient, or a tiled image. - - @see Graphics::setFillType, DrawablePath::setFill -*/ class JUCE_API FillType { public: - /** Creates a default fill type, of solid black. */ - FillType() throw(); + FillType() throw(); - /** Creates a fill type of a solid colour. - @see setColour - */ - FillType (const Colour& colour) throw(); + FillType (const Colour& colour) throw(); - /** Creates a gradient fill type. - @see setGradient - */ - FillType (const ColourGradient& gradient) throw(); + FillType (const ColourGradient& gradient) throw(); - /** Creates a tiled image fill type. The transform allows you to set the scaling, offset - and rotation of the pattern. - @see setTiledImage - */ - FillType (const Image& image, const AffineTransform& transform) throw(); + FillType (const Image& image, const AffineTransform& transform) throw(); - /** Creates a copy of another FillType. */ - FillType (const FillType& other) throw(); + FillType (const FillType& other) throw(); - /** Makes a copy of another FillType. */ - const FillType& operator= (const FillType& other) throw(); + const FillType& operator= (const FillType& other) throw(); - /** Destructor. */ - ~FillType() throw(); + ~FillType() throw(); - /** Returns true if this is a solid colour fill, and not a gradient or image. */ - bool isColour() const throw() { return gradient == 0 && image == 0; } + bool isColour() const throw() { return gradient == 0 && image == 0; } - /** Returns true if this is a gradient fill. */ - bool isGradient() const throw() { return gradient != 0; } + bool isGradient() const throw() { return gradient != 0; } - /** Returns true if this is a tiled image pattern fill. */ - bool isTiledImage() const throw() { return image != 0; } + bool isTiledImage() const throw() { return image != 0; } - /** Turns this object into a solid colour fill. - If the object was an image or gradient, those fields will no longer be valid. */ - void setColour (const Colour& newColour) throw(); + void setColour (const Colour& newColour) throw(); - /** Turns this object into a gradient fill. */ - void setGradient (const ColourGradient& newGradient) throw(); + void setGradient (const ColourGradient& newGradient) throw(); - /** Turns this object into a tiled image fill type. The transform allows you to set - the scaling, offset and rotation of the pattern. - */ - void setTiledImage (const Image& image, const AffineTransform& transform) throw(); + void setTiledImage (const Image& image, const AffineTransform& transform) throw(); - /** Changes the opacity that should be used. - If the fill is a solid colour, this just changes the opacity of that colour. For - gradients and image tiles, it changes the opacity that will be used for them. - */ - void setOpacity (const float newOpacity) throw(); + void setOpacity (const float newOpacity) throw(); - /** Returns the current opacity to be applied to the colour, gradient, or image. - @see setOpacity - */ - float getOpacity() const throw() { return colour.getFloatAlpha(); } + float getOpacity() const throw() { return colour.getFloatAlpha(); } - /** The solid colour being used. + Colour colour; - If the fill type is not a solid colour, the alpha channel of this colour indicates - the opacity that should be used for the fill, and the RGB channels are ignored. - */ - Colour colour; + ScopedPointer gradient; - /** Returns the gradient that should be used for filling. - This will be zero if the object is some other type of fill. - If a gradient is active, the overall opacity with which it should be applied - is indicated by the alpha channel of the colour variable. - */ - ScopedPointer gradient; + const Image* image; - /** Returns the image that should be used for tiling. - The FillType object just keeps a pointer to this image, it doesn't own it, so you have to - be careful to make sure the image doesn't get deleted while it's being used. - If an image fill is active, the overall opacity with which it should be applied - is indicated by the alpha channel of the colour variable. - */ - const Image* image; + AffineTransform transform; - /** The transform that should be applied to the image or gradient that's being drawn. - */ - AffineTransform transform; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; #endif // __JUCE_FILLTYPE_JUCEHEADER__ @@ -21698,123 +11085,69 @@ public: #ifndef __JUCE_RECTANGLEPLACEMENT_JUCEHEADER__ #define __JUCE_RECTANGLEPLACEMENT_JUCEHEADER__ -/** - Defines the method used to postion some kind of rectangular object within - a rectangular viewport. - - Although similar to Justification, this is more specific, and has some extra - options. -*/ class JUCE_API RectanglePlacement { public: - /** Creates a RectanglePlacement object using a combination of flags. */ - inline RectanglePlacement (const int flags_) throw() : flags (flags_) {} + inline RectanglePlacement (const int flags_) throw() : flags (flags_) {} - /** Creates a copy of another Justification object. */ - RectanglePlacement (const RectanglePlacement& other) throw(); + RectanglePlacement (const RectanglePlacement& other) throw(); - /** Copies another Justification object. */ - const RectanglePlacement& operator= (const RectanglePlacement& other) throw(); + const RectanglePlacement& operator= (const RectanglePlacement& other) throw(); - /** Flag values that can be combined and used in the constructor. */ - enum - { + enum + { - /** Indicates that the source rectangle's left edge should be aligned with the left edge of the target rectangle. */ - xLeft = 1, + xLeft = 1, - /** Indicates that the source rectangle's right edge should be aligned with the right edge of the target rectangle. */ - xRight = 2, + xRight = 2, - /** Indicates that the source should be placed in the centre between the left and right - sides of the available space. */ - xMid = 4, + xMid = 4, - /** Indicates that the source's top edge should be aligned with the top edge of the - destination rectangle. */ - yTop = 8, + yTop = 8, - /** Indicates that the source's bottom edge should be aligned with the bottom edge of the - destination rectangle. */ - yBottom = 16, + yBottom = 16, - /** Indicates that the source should be placed in the centre between the top and bottom - sides of the available space. */ - yMid = 32, + yMid = 32, - /** If this flag is set, then the source rectangle will be resized to completely fill - the destination rectangle, and all other flags are ignored. - */ - stretchToFit = 64, + stretchToFit = 64, - /** If this flag is set, then the source rectangle will be resized so that it is the - minimum size to completely fill the destination rectangle, without changing its - aspect ratio. This means that some of the source rectangle may fall outside - the destination. + fillDestination = 128, - If this flag is not set, the source will be given the maximum size at which none - of it falls outside the destination rectangle. - */ - fillDestination = 128, + onlyReduceInSize = 256, - /** Indicates that the source rectangle can be reduced in size if required, but should - never be made larger than its original size. - */ - onlyReduceInSize = 256, + onlyIncreaseInSize = 512, - /** Indicates that the source rectangle can be enlarged if required, but should - never be made smaller than its original size. - */ - onlyIncreaseInSize = 512, + doNotResize = (onlyIncreaseInSize | onlyReduceInSize), - /** Indicates that the source rectangle's size should be left unchanged. - */ - doNotResize = (onlyIncreaseInSize | onlyReduceInSize), + centred = 4 + 32 + }; - /** A shorthand value that is equivalent to (xMid | yMid). */ - centred = 4 + 32 - }; + inline int getFlags() const throw() { return flags; } - /** Returns the raw flags that are set for this object. */ - inline int getFlags() const throw() { return flags; } + inline bool testFlags (const int flagsToTest) const throw() { return (flags & flagsToTest) != 0; } - /** Tests a set of flags for this object. + void applyTo (double& sourceX, + double& sourceY, + double& sourceW, + double& sourceH, + const double destinationX, + const double destinationY, + const double destinationW, + const double destinationH) const throw(); - @returns true if any of the flags passed in are set on this object. - */ - inline bool testFlags (const int flagsToTest) const throw() { return (flags & flagsToTest) != 0; } - - /** Adjusts the position and size of a rectangle to fit it into a space. - - The source rectangle co-ordinates will be adjusted so that they fit into - the destination rectangle based on this object's flags. - */ - void applyTo (double& sourceX, - double& sourceY, - double& sourceW, - double& sourceH, - const double destinationX, - const double destinationY, - const double destinationW, - const double destinationH) const throw(); - - /** Returns the transform that should be applied to these source co-ordinates to fit them - into the destination rectangle using the current flags. - */ - const AffineTransform getTransformToFit (float sourceX, - float sourceY, - float sourceW, - float sourceH, - const float destinationX, - const float destinationY, - const float destinationW, - const float destinationH) const throw(); + const AffineTransform getTransformToFit (float sourceX, + float sourceY, + float sourceW, + float sourceH, + const float destinationX, + const float destinationY, + const float destinationW, + const float destinationH) const throw(); private: - int flags; + int flags; }; #endif // __JUCE_RECTANGLEPLACEMENT_JUCEHEADER__ @@ -21824,713 +11157,282 @@ class LowLevelGraphicsContext; class Image; class RectangleList; -/** - A graphics context, used for drawing a component or image. - - When a Component needs painting, a Graphics context is passed to its - Component::paint() method, and this you then call methods within this - object to actually draw the component's content. - - A Graphics can also be created from an image, to allow drawing directly onto - that image. - - @see Component::paint -*/ class JUCE_API Graphics { public: - /** Creates a Graphics object to draw directly onto the given image. + Graphics (Image& imageToDrawOnto) throw(); - The graphics object that is created will be set up to draw onto the image, - with the context's clipping area being the entire size of the image, and its - origin being the image's origin. To draw into a subsection of an image, use the - reduceClipRegion() and setOrigin() methods. + ~Graphics() throw(); + + void setColour (const Colour& newColour) throw(); - Obviously you shouldn't delete the image before this context is deleted. - */ - Graphics (Image& imageToDrawOnto) throw(); + void setOpacity (const float newOpacity) throw(); + + void setGradientFill (const ColourGradient& gradient) throw(); - /** Destructor. */ - ~Graphics() throw(); + void setTiledImageFill (const Image& imageToUse, + const int anchorX, + const int anchorY, + const float opacity) throw(); + + void setFillType (const FillType& newFill) throw(); + + void setFont (const Font& newFont) throw(); + + void setFont (const float newFontHeight, + const int fontStyleFlags = Font::plain) throw(); + + void drawSingleLineText (const String& text, + const int startX, + const int baselineY) const throw(); + + void drawMultiLineText (const String& text, + const int startX, + const int baselineY, + const int maximumLineWidth) const throw(); + + void drawTextAsPath (const String& text, + const AffineTransform& transform) const throw(); + + void drawText (const String& text, + const int x, + const int y, + const int width, + const int height, + const Justification& justificationType, + const bool useEllipsesIfTooBig) const throw(); + + void drawFittedText (const String& text, + const int x, + const int y, + const int width, + const int height, + const Justification& justificationFlags, + const int maximumNumberOfLines, + const float minimumHorizontalScale = 0.7f) const throw(); + + void fillAll() const throw(); + + void fillAll (const Colour& colourToUse) const throw(); + + void fillRect (int x, + int y, + int width, + int height) const throw(); + + void fillRect (const Rectangle& rectangle) const throw(); + + void fillRect (const float x, + const float y, + const float width, + const float height) const throw(); + + void fillRoundedRectangle (const float x, + const float y, + const float width, + const float height, + const float cornerSize) const throw(); + + void fillRoundedRectangle (const Rectangle& rectangle, + const float cornerSize) const throw(); + + void fillCheckerBoard (int x, int y, + int width, int height, + const int checkWidth, + const int checkHeight, + const Colour& colour1, + const Colour& colour2) const throw(); + + void drawRect (const int x, + const int y, + const int width, + const int height, + const int lineThickness = 1) const throw(); + + void drawRect (const float x, + const float y, + const float width, + const float height, + const float lineThickness = 1.0f) const throw(); + + void drawRect (const Rectangle& rectangle, + const int lineThickness = 1) const throw(); + + void drawRoundedRectangle (const float x, + const float y, + const float width, + const float height, + const float cornerSize, + const float lineThickness) const throw(); + + void drawRoundedRectangle (const Rectangle& rectangle, + const float cornerSize, + const float lineThickness) const throw(); + + void drawBevel (const int x, + const int y, + const int width, + const int height, + const int bevelThickness, + const Colour& topLeftColour = Colours::white, + const Colour& bottomRightColour = Colours::black, + const bool useGradient = true, + const bool sharpEdgeOnOutside = true) const throw(); + + void setPixel (int x, int y) const throw(); + + void fillEllipse (const float x, + const float y, + const float width, + const float height) const throw(); + + void drawEllipse (const float x, + const float y, + const float width, + const float height, + const float lineThickness) const throw(); + + void drawLine (float startX, + float startY, + float endX, + float endY) const throw(); + + void drawLine (const float startX, + const float startY, + const float endX, + const float endY, + const float lineThickness) const throw(); + + void drawLine (const Line& line) const throw(); + + void drawLine (const Line& line, + const float lineThickness) const throw(); + + void drawDashedLine (const float startX, + const float startY, + const float endX, + const float endY, + const float* const dashLengths, + const int numDashLengths, + const float lineThickness = 1.0f) const throw(); + + void drawVerticalLine (const int x, float top, float bottom) const throw(); + + void drawHorizontalLine (const int y, float left, float right) const throw(); + + void fillPath (const Path& path, + const AffineTransform& transform = AffineTransform::identity) const throw(); + + void strokePath (const Path& path, + const PathStrokeType& strokeType, + const AffineTransform& transform = AffineTransform::identity) const throw(); + + void drawArrow (const float startX, + const float startY, + const float endX, + const float endY, + const float lineThickness, + const float arrowheadWidth, + const float arrowheadLength) const throw(); + + enum ResamplingQuality + { + lowResamplingQuality = 0, /**< Just uses a nearest-neighbour algorithm for resampling. */ + mediumResamplingQuality = 1, /**< Uses bilinear interpolation for upsampling and area-averaging for downsampling. */ + highResamplingQuality = 2 /**< Uses bicubic interpolation for upsampling and area-averaging for downsampling. */ + }; - /** Changes the current drawing colour. + void setImageResamplingQuality (const ResamplingQuality newQuality) throw(); + + void drawImageAt (const Image* const imageToDraw, + const int topLeftX, + const int topLeftY, + const bool fillAlphaChannelWithCurrentBrush = false) const throw(); - This sets the colour that will now be used for drawing operations - it also - sets the opacity to that of the colour passed-in. + void drawImage (const Image* const imageToDraw, + int destX, + int destY, + int destWidth, + int destHeight, + int sourceX, + int sourceY, + int sourceWidth, + int sourceHeight, + const bool fillAlphaChannelWithCurrentBrush = false) const throw(); - If a brush is being used when this method is called, the brush will be deselected, - and any subsequent drawing will be done with a solid colour brush instead. + void drawImageTransformed (const Image* const imageToDraw, + const Rectangle& imageSubRegion, + const AffineTransform& transform, + const bool fillAlphaChannelWithCurrentBrush = false) const throw(); - @see setOpacity - */ - void setColour (const Colour& newColour) throw(); + void drawImageWithin (const Image* const imageToDraw, + const int destX, + const int destY, + const int destWidth, + const int destHeight, + const RectanglePlacement& placementWithinTarget, + const bool fillAlphaChannelWithCurrentBrush = false) const throw(); - /** Changes the opacity to use with the current colour. + const Rectangle getClipBounds() const throw(); - If a solid colour is being used for drawing, this changes its opacity - to this new value (i.e. it doesn't multiply the colour's opacity by this amount). + bool clipRegionIntersects (const int x, const int y, const int width, const int height) const throw(); - If a gradient is being used, this will have no effect on it. + bool reduceClipRegion (const int x, const int y, + const int width, const int height) throw(); - A value of 0.0 is completely transparent, 1.0 is completely opaque. - */ - void setOpacity (const float newOpacity) throw(); + bool reduceClipRegion (const RectangleList& clipRegion) throw(); - /** Sets the context to use a gradient for its fill pattern. - */ - void setGradientFill (const ColourGradient& gradient) throw(); + bool reduceClipRegion (const Path& path, const AffineTransform& transform = AffineTransform::identity) throw(); - /** Sets the context to use a tiled image pattern for filling. - Make sure that you don't delete this image while it's still being used by - this context! - */ - void setTiledImageFill (const Image& imageToUse, - const int anchorX, - const int anchorY, - const float opacity) throw(); + bool reduceClipRegion (const Image& image, const Rectangle& sourceClipRegion, + const AffineTransform& transform) throw(); - /** Changes the current fill settings. - @see setColour, setGradientFill, setTiledImageFill - */ - void setFillType (const FillType& newFill) throw(); + void excludeClipRegion (const int x, const int y, + const int width, const int height) throw(); - /** Changes the font to use for subsequent text-drawing functions. + bool isClipEmpty() const throw(); - Note there's also a setFont (float, int) method to quickly change the size and - style of the current font. + void saveState() throw(); - @see drawSingleLineText, drawMultiLineText, drawTextAsPath, drawText, drawFittedText - */ - void setFont (const Font& newFont) throw(); + void restoreState() throw(); - /** Changes the size and style of the currently-selected font. + void setOrigin (const int newOriginX, + const int newOriginY) throw(); - This is a convenient shortcut that changes the context's current font to a - different size or style. The typeface won't be changed. + void resetToDefaultState() throw(); - @see Font - */ - void setFont (const float newFontHeight, - const int fontStyleFlags = Font::plain) throw(); + bool isVectorDevice() const throw(); - /** Draws a one-line text string. + juce_UseDebuggingNewOperator - This will use the current colour (or brush) to fill the text. The font is the last - one specified by setFont(). + Graphics (LowLevelGraphicsContext* const internalContext) throw(); - @param text the string to draw - @param startX the position to draw the left-hand edge of the text - @param baselineY the position of the text's baseline - @see drawMultiLineText, drawText, drawFittedText, GlyphArrangement::addLineOfText - */ - void drawSingleLineText (const String& text, - const int startX, - const int baselineY) const throw(); - - /** Draws text across multiple lines. - - This will break the text onto a new line where there's a new-line or - carriage-return character, or at a word-boundary when the text becomes wider - than the size specified by the maximumLineWidth parameter. - - @see setFont, drawSingleLineText, drawFittedText, GlyphArrangement::addJustifiedText - */ - void drawMultiLineText (const String& text, - const int startX, - const int baselineY, - const int maximumLineWidth) const throw(); - - /** Renders a string of text as a vector path. - - This allows a string to be transformed with an arbitrary AffineTransform and - rendered using the current colour/brush. It's much slower than the normal text methods - but more accurate. - - @see setFont - */ - void drawTextAsPath (const String& text, - const AffineTransform& transform) const throw(); - - /** Draws a line of text within a specified rectangle. - - The text will be positioned within the rectangle based on the justification - flags passed-in. If the string is too long to fit inside the rectangle, it will - either be truncated or will have ellipsis added to its end (if the useEllipsesIfTooBig - flag is true). - - @see drawSingleLineText, drawFittedText, drawMultiLineText, GlyphArrangement::addJustifiedText - */ - void drawText (const String& text, - const int x, - const int y, - const int width, - const int height, - const Justification& justificationType, - const bool useEllipsesIfTooBig) const throw(); - - /** Tries to draw a text string inside a given space. - - This does its best to make the given text readable within the specified rectangle, - so it useful for labelling things. - - If the text is too big, it'll be squashed horizontally or broken over multiple lines - if the maximumLinesToUse value allows this. If the text just won't fit into the space, - it'll cram as much as possible in there, and put some ellipsis at the end to show that - it's been truncated. - - A Justification parameter lets you specify how the text is laid out within the rectangle, - both horizontally and vertically. - - The minimumHorizontalScale parameter specifies how much the text can be squashed horizontally - to try to squeeze it into the space. If you don't want any horizontal scaling to occur, you - can set this value to 1.0f. - - @see GlyphArrangement::addFittedText - */ - void drawFittedText (const String& text, - const int x, - const int y, - const int width, - const int height, - const Justification& justificationFlags, - const int maximumNumberOfLines, - const float minimumHorizontalScale = 0.7f) const throw(); - - /** Fills the context's entire clip region with the current colour or brush. - - (See also the fillAll (const Colour&) method which is a quick way of filling - it with a given colour). - */ - void fillAll() const throw(); - - /** Fills the context's entire clip region with a given colour. - - This leaves the context's current colour and brush unchanged, it just - uses the specified colour temporarily. - */ - void fillAll (const Colour& colourToUse) const throw(); - - /** Fills a rectangle with the current colour or brush. - - @see drawRect, fillRoundedRectangle - */ - void fillRect (int x, - int y, - int width, - int height) const throw(); - - /** Fills a rectangle with the current colour or brush. */ - void fillRect (const Rectangle& rectangle) const throw(); - - /** Fills a rectangle with the current colour or brush. - - This uses sub-pixel positioning so is slower than the fillRect method which - takes integer co-ordinates. - */ - void fillRect (const float x, - const float y, - const float width, - const float height) const throw(); - - /** Uses the current colour or brush to fill a rectangle with rounded corners. - - @see drawRoundedRectangle, Path::addRoundedRectangle - */ - void fillRoundedRectangle (const float x, - const float y, - const float width, - const float height, - const float cornerSize) const throw(); - - /** Uses the current colour or brush to fill a rectangle with rounded corners. - - @see drawRoundedRectangle, Path::addRoundedRectangle - */ - void fillRoundedRectangle (const Rectangle& rectangle, - const float cornerSize) const throw(); - - /** Fills a rectangle with a checkerboard pattern, alternating between two colours. - */ - void fillCheckerBoard (int x, int y, - int width, int height, - const int checkWidth, - const int checkHeight, - const Colour& colour1, - const Colour& colour2) const throw(); - - /** Draws four lines to form a rectangular outline, using the current colour or brush. - - The lines are drawn inside the given rectangle, and greater line thicknesses - extend inwards. - - @see fillRect - */ - void drawRect (const int x, - const int y, - const int width, - const int height, - const int lineThickness = 1) const throw(); - - /** Draws four lines to form a rectangular outline, using the current colour or brush. - - The lines are drawn inside the given rectangle, and greater line thicknesses - extend inwards. - - @see fillRect - */ - void drawRect (const float x, - const float y, - const float width, - const float height, - const float lineThickness = 1.0f) const throw(); - - /** Draws four lines to form a rectangular outline, using the current colour or brush. - - The lines are drawn inside the given rectangle, and greater line thicknesses - extend inwards. - - @see fillRect - */ - void drawRect (const Rectangle& rectangle, - const int lineThickness = 1) const throw(); - - /** Uses the current colour or brush to draw the outline of a rectangle with rounded corners. - - @see fillRoundedRectangle, Path::addRoundedRectangle - */ - void drawRoundedRectangle (const float x, - const float y, - const float width, - const float height, - const float cornerSize, - const float lineThickness) const throw(); - - /** Uses the current colour or brush to draw the outline of a rectangle with rounded corners. - - @see fillRoundedRectangle, Path::addRoundedRectangle - */ - void drawRoundedRectangle (const Rectangle& rectangle, - const float cornerSize, - const float lineThickness) const throw(); - - /** Draws a 3D raised (or indented) bevel using two colours. - - The bevel is drawn inside the given rectangle, and greater bevel thicknesses - extend inwards. - - The top-left colour is used for the top- and left-hand edges of the - bevel; the bottom-right colour is used for the bottom- and right-hand - edges. - - If useGradient is true, then the bevel fades out to make it look more curved - and less angular. If sharpEdgeOnOutside is true, the outside of the bevel is - sharp, and it fades towards the centre; if sharpEdgeOnOutside is false, then - the centre edges are sharp and it fades towards the outside. - */ - void drawBevel (const int x, - const int y, - const int width, - const int height, - const int bevelThickness, - const Colour& topLeftColour = Colours::white, - const Colour& bottomRightColour = Colours::black, - const bool useGradient = true, - const bool sharpEdgeOnOutside = true) const throw(); - - /** Draws a pixel using the current colour or brush. - */ - void setPixel (int x, int y) const throw(); - - /** Fills an ellipse with the current colour or brush. - - The ellipse is drawn to fit inside the given rectangle. - - @see drawEllipse, Path::addEllipse - */ - void fillEllipse (const float x, - const float y, - const float width, - const float height) const throw(); - - /** Draws an elliptical stroke using the current colour or brush. - - @see fillEllipse, Path::addEllipse - */ - void drawEllipse (const float x, - const float y, - const float width, - const float height, - const float lineThickness) const throw(); - - /** Draws a line between two points. - - The line is 1 pixel wide and drawn with the current colour or brush. - */ - void drawLine (float startX, - float startY, - float endX, - float endY) const throw(); - - /** Draws a line between two points with a given thickness. - - @see Path::addLineSegment - */ - void drawLine (const float startX, - const float startY, - const float endX, - const float endY, - const float lineThickness) const throw(); - - /** Draws a line between two points. - - The line is 1 pixel wide and drawn with the current colour or brush. - */ - void drawLine (const Line& line) const throw(); - - /** Draws a line between two points with a given thickness. - - @see Path::addLineSegment - */ - void drawLine (const Line& line, - const float lineThickness) const throw(); - - /** Draws a dashed line using a custom set of dash-lengths. - - @param startX the line's start x co-ordinate - @param startY the line's start y co-ordinate - @param endX the line's end x co-ordinate - @param endY the line's end y co-ordinate - @param dashLengths a series of lengths to specify the on/off lengths - e.g. - { 4, 5, 6, 7 } will draw a line of 4 pixels, skip 5 pixels, - draw 6 pixels, skip 7 pixels, and then repeat. - @param numDashLengths the number of elements in the array (this must be an even number). - @param lineThickness the thickness of the line to draw - @see PathStrokeType::createDashedStroke - */ - void drawDashedLine (const float startX, - const float startY, - const float endX, - const float endY, - const float* const dashLengths, - const int numDashLengths, - const float lineThickness = 1.0f) const throw(); - - /** Draws a vertical line of pixels at a given x position. - - The x position is an integer, but the top and bottom of the line can be sub-pixel - positions, and these will be anti-aliased if necessary. - */ - void drawVerticalLine (const int x, float top, float bottom) const throw(); - - /** Draws a horizontal line of pixels at a given y position. - - The y position is an integer, but the left and right ends of the line can be sub-pixel - positions, and these will be anti-aliased if necessary. - */ - void drawHorizontalLine (const int y, float left, float right) const throw(); - - /** Fills a path using the currently selected colour or brush. - */ - void fillPath (const Path& path, - const AffineTransform& transform = AffineTransform::identity) const throw(); - - /** Draws a path's outline using the currently selected colour or brush. - */ - void strokePath (const Path& path, - const PathStrokeType& strokeType, - const AffineTransform& transform = AffineTransform::identity) const throw(); - - /** Draws a line with an arrowhead. - - @param startX the line's start x co-ordinate - @param startY the line's start y co-ordinate - @param endX the line's end x co-ordinate (the tip of the arrowhead) - @param endY the line's end y co-ordinate (the tip of the arrowhead) - @param lineThickness the thickness of the line - @param arrowheadWidth the width of the arrow head (perpendicular to the line) - @param arrowheadLength the length of the arrow head (along the length of the line) - */ - void drawArrow (const float startX, - const float startY, - const float endX, - const float endY, - const float lineThickness, - const float arrowheadWidth, - const float arrowheadLength) const throw(); - - /** Types of rendering quality that can be specified when drawing images. - - @see blendImage, Graphics::setImageResamplingQuality - */ - enum ResamplingQuality - { - lowResamplingQuality = 0, /**< Just uses a nearest-neighbour algorithm for resampling. */ - mediumResamplingQuality = 1, /**< Uses bilinear interpolation for upsampling and area-averaging for downsampling. */ - highResamplingQuality = 2 /**< Uses bicubic interpolation for upsampling and area-averaging for downsampling. */ - }; - - /** Changes the quality that will be used when resampling images. - - By default a Graphics object will be set to mediumRenderingQuality. - - @see Graphics::drawImage, Graphics::drawImageTransformed, Graphics::drawImageWithin - */ - void setImageResamplingQuality (const ResamplingQuality newQuality) throw(); - - /** Draws an image. - - This will draw the whole of an image, positioning its top-left corner at the - given co-ordinates, and keeping its size the same. This is the simplest image - drawing method - the others give more control over the scaling and clipping - of the images. - - Images are composited using the context's current opacity, so if you - don't want it to be drawn semi-transparently, be sure to call setOpacity (1.0f) - (or setColour() with an opaque colour) before drawing images. - */ - void drawImageAt (const Image* const imageToDraw, - const int topLeftX, - const int topLeftY, - const bool fillAlphaChannelWithCurrentBrush = false) const throw(); - - /** Draws part of an image, rescaling it to fit in a given target region. - - The specified area of the source image is rescaled and drawn to fill the - specifed destination rectangle. - - Images are composited using the context's current opacity, so if you - don't want it to be drawn semi-transparently, be sure to call setOpacity (1.0f) - (or setColour() with an opaque colour) before drawing images. - - @param imageToDraw the image to overlay - @param destX the left of the destination rectangle - @param destY the top of the destination rectangle - @param destWidth the width of the destination rectangle - @param destHeight the height of the destination rectangle - @param sourceX the left of the rectangle to copy from the source image - @param sourceY the top of the rectangle to copy from the source image - @param sourceWidth the width of the rectangle to copy from the source image - @param sourceHeight the height of the rectangle to copy from the source image - @param fillAlphaChannelWithCurrentBrush if true, then instead of drawing the source image's pixels, - the source image's alpha channel is used as a mask with - which to fill the destination using the current colour - or brush. (If the source is has no alpha channel, then - it will just fill the target with a solid rectangle) - @see setImageResamplingQuality, drawImageAt, drawImageWithin, fillAlphaMap - */ - void drawImage (const Image* const imageToDraw, - int destX, - int destY, - int destWidth, - int destHeight, - int sourceX, - int sourceY, - int sourceWidth, - int sourceHeight, - const bool fillAlphaChannelWithCurrentBrush = false) const throw(); - - /** Draws part of an image, having applied an affine transform to it. - - This lets you throw the image around in some wacky ways, rotate it, shear, - scale it, etc. - - A subregion is specified within the source image, and all transformations - will be treated as relative to the origin of this sub-region. So, for example if - your subregion is (50, 50, 100, 100), and your transform is a translation of (20, 20), - the resulting pixel drawn at (20, 20) in the destination context is from (50, 50) in - your image. If you want to use the whole image, then Image::getBounds() returns a - suitable rectangle to use as the imageSubRegion parameter. - - Images are composited using the context's current opacity, so if you - don't want it to be drawn semi-transparently, be sure to call setOpacity (1.0f) - (or setColour() with an opaque colour) before drawing images. - - If fillAlphaChannelWithCurrentBrush is set to true, then the image's RGB channels - are ignored and it is filled with the current brush, masked by its alpha channel. - - @see setImageResamplingQuality, drawImage - */ - void drawImageTransformed (const Image* const imageToDraw, - const Rectangle& imageSubRegion, - const AffineTransform& transform, - const bool fillAlphaChannelWithCurrentBrush = false) const throw(); - - /** Draws an image to fit within a designated rectangle. - - If the image is too big or too small for the space, it will be rescaled - to fit as nicely as it can do without affecting its aspect ratio. It will - then be placed within the target rectangle according to the justification flags - specified. - - @param imageToDraw the source image to draw - @param destX top-left of the target rectangle to fit it into - @param destY top-left of the target rectangle to fit it into - @param destWidth size of the target rectangle to fit the image into - @param destHeight size of the target rectangle to fit the image into - @param placementWithinTarget this specifies how the image should be positioned - within the target rectangle - see the RectanglePlacement - class for more details about this. - @param fillAlphaChannelWithCurrentBrush if true, then instead of drawing the image, just its - alpha channel will be used as a mask with which to - draw with the current brush or colour. This is - similar to fillAlphaMap(), and see also drawImage() - @see setImageResamplingQuality, drawImage, drawImageTransformed, drawImageAt, RectanglePlacement - */ - void drawImageWithin (const Image* const imageToDraw, - const int destX, - const int destY, - const int destWidth, - const int destHeight, - const RectanglePlacement& placementWithinTarget, - const bool fillAlphaChannelWithCurrentBrush = false) const throw(); - - /** Returns the position of the bounding box for the current clipping region. - - @see getClipRegion, clipRegionIntersects - */ - const Rectangle getClipBounds() const throw(); - - /** Checks whether a rectangle overlaps the context's clipping region. - - If this returns false, no part of the given area can be drawn onto, so this - method can be used to optimise a component's paint() method, by letting it - avoid drawing complex objects that aren't within the region being repainted. - */ - bool clipRegionIntersects (const int x, const int y, const int width, const int height) const throw(); - - /** Intersects the current clipping region with another region. - - @returns true if the resulting clipping region is non-zero in size - @see setOrigin, clipRegionIntersects - */ - bool reduceClipRegion (const int x, const int y, - const int width, const int height) throw(); - - /** Intersects the current clipping region with a rectangle list region. - - @returns true if the resulting clipping region is non-zero in size - @see setOrigin, clipRegionIntersects - */ - bool reduceClipRegion (const RectangleList& clipRegion) throw(); - - /** Intersects the current clipping region with a path. - - @returns true if the resulting clipping region is non-zero in size - @see reduceClipRegion - */ - bool reduceClipRegion (const Path& path, const AffineTransform& transform = AffineTransform::identity) throw(); - - /** Intersects the current clipping region with an image's alpha-channel. - - The current clipping path is intersected with the area covered by this image's - alpha-channel, after the image has been transformed by the specified matrix. - - @param image the image whose alpha-channel should be used. If the image doesn't - have an alpha-channel, it is treated as entirely opaque. - @param sourceClipRegion a subsection of the image that should be used. To use the - entire image, just pass a rectangle of bounds - (0, 0, image.getWidth(), image.getHeight()). - @param transform a matrix to apply to the image - @returns true if the resulting clipping region is non-zero in size - @see reduceClipRegion - */ - bool reduceClipRegion (const Image& image, const Rectangle& sourceClipRegion, - const AffineTransform& transform) throw(); - - /** Excludes a rectangle to stop it being drawn into. */ - void excludeClipRegion (const int x, const int y, - const int width, const int height) throw(); - - /** Returns true if no drawing can be done because the clip region is zero. */ - bool isClipEmpty() const throw(); - - /** Saves the current graphics state on an internal stack. - - To restore the state, use restoreState(). - */ - void saveState() throw(); - - /** Restores a graphics state that was previously saved with saveState(). - */ - void restoreState() throw(); - - /** Moves the position of the context's origin. - - This changes the position that the context considers to be (0, 0) to - the specified position. - - So if you call setOrigin (100, 100), then the position that was previously - referred to as (100, 100) will subsequently be considered to be (0, 0). - - @see reduceClipRegion - */ - void setOrigin (const int newOriginX, - const int newOriginY) throw(); - - /** Resets the current colour, brush, and font to default settings. */ - void resetToDefaultState() throw(); - - /** Returns true if this context is drawing to a vector-based device, such as a printer. */ - bool isVectorDevice() const throw(); - - juce_UseDebuggingNewOperator - - /** Create a graphics that uses a given low-level renderer. - - For internal use only. - - NB. The context will NOT be deleted by this object when it is deleted. - */ - Graphics (LowLevelGraphicsContext* const internalContext) throw(); - - /** @internal */ - LowLevelGraphicsContext* getInternalContext() const throw() { return context; } + LowLevelGraphicsContext* getInternalContext() const throw() { return context; } private: - LowLevelGraphicsContext* const context; - const bool ownsContext; + LowLevelGraphicsContext* const context; + ScopedPointer contextToDelete; - bool saveStatePending; - void saveStateIfPending() throw(); + bool saveStatePending; + void saveStateIfPending() throw(); - const Graphics& operator= (const Graphics& other); - Graphics (const Graphics&); + const Graphics& operator= (const Graphics& other); + Graphics (const Graphics&); }; #endif // __JUCE_GRAPHICS_JUCEHEADER__ /********* End of inlined file: juce_Graphics.h *********/ -/** - A graphical effect filter that can be applied to components. - - An ImageEffectFilter can be applied to the image that a component - paints before it hits the screen. - - This is used for adding effects like shadows, blurs, etc. - - @see Component::setComponentEffect -*/ class JUCE_API ImageEffectFilter { public: - /** Overridden to render the effect. + virtual void applyEffect (Image& sourceImage, + Graphics& destContext) = 0; - The implementation of this method must use the image that is passed in - as its source, and should render its output to the graphics context passed in. - - @param sourceImage the image that the source component has just rendered with - its paint() method. The image may or may not have an alpha - channel, depending on whether the component is opaque. - @param destContext the graphics context to use to draw the resultant image. - */ - virtual void applyEffect (Image& sourceImage, - Graphics& destContext) = 0; - - /** Destructor. */ - virtual ~ImageEffectFilter() {} + virtual ~ImageEffectFilter() {} }; @@ -22541,212 +11443,92 @@ public: #ifndef __JUCE_RECTANGLELIST_JUCEHEADER__ #define __JUCE_RECTANGLELIST_JUCEHEADER__ -/** - Maintains a set of rectangles as a complex region. - - This class allows a set of rectangles to be treated as a solid shape, and can - add and remove rectangular sections of it, and simplify overlapping or - adjacent rectangles. - - @see Rectangle -*/ class JUCE_API RectangleList { public: - /** Creates an empty RectangleList */ - RectangleList() throw(); + RectangleList() throw(); - /** Creates a copy of another list */ - RectangleList (const RectangleList& other) throw(); + RectangleList (const RectangleList& other) throw(); - /** Creates a list containing just one rectangle. */ - RectangleList (const Rectangle& rect) throw(); + RectangleList (const Rectangle& rect) throw(); - /** Copies this list from another one. */ - const RectangleList& operator= (const RectangleList& other) throw(); + const RectangleList& operator= (const RectangleList& other) throw(); - /** Destructor. */ - ~RectangleList() throw(); + ~RectangleList() throw(); - /** Returns true if the region is empty. */ - bool isEmpty() const throw(); + bool isEmpty() const throw(); - /** Returns the number of rectangles in the list. */ - int getNumRectangles() const throw() { return rects.size(); } + int getNumRectangles() const throw() { return rects.size(); } - /** Returns one of the rectangles at a particular index. + const Rectangle getRectangle (const int index) const throw(); - @returns the rectangle at the index, or an empty rectangle if the - index is out-of-range. - */ - const Rectangle getRectangle (const int index) const throw(); + void clear() throw(); - /** Removes all rectangles to leave an empty region. */ - void clear() throw(); + void add (const int x, const int y, + const int w, const int h) throw(); - /** Merges a new rectangle into the list. + void add (const Rectangle& rect) throw(); - The rectangle being added will first be clipped to remove any parts of it - that overlap existing rectangles in the list. - */ - void add (const int x, const int y, - const int w, const int h) throw(); + void addWithoutMerging (const Rectangle& rect) throw(); - /** Merges a new rectangle into the list. + void add (const RectangleList& other) throw(); - The rectangle being added will first be clipped to remove any parts of it - that overlap existing rectangles in the list, and adjacent rectangles will be - merged into it. - */ - void add (const Rectangle& rect) throw(); + void subtract (const Rectangle& rect) throw(); - /** Dumbly adds a rectangle to the list without checking for overlaps. + void subtract (const RectangleList& otherList) throw(); - This simply adds the rectangle to the end, it doesn't merge it or remove - any overlapping bits. - */ - void addWithoutMerging (const Rectangle& rect) throw(); + bool clipTo (const Rectangle& rect) throw(); - /** Merges another rectangle list into this one. + bool clipTo (const RectangleList& other) throw(); - Any overlaps between the two lists will be clipped, so that the result is - the union of both lists. - */ - void add (const RectangleList& other) throw(); + bool getIntersectionWith (const Rectangle& rect, RectangleList& destRegion) const throw(); - /** Removes a rectangular region from the list. + void swapWith (RectangleList& otherList) throw(); - Any rectangles in the list which overlap this will be clipped and subdivided - if necessary. - */ - void subtract (const Rectangle& rect) throw(); + bool containsPoint (const int x, const int y) const throw(); - /** Removes all areas in another RectangleList from this one. + bool containsRectangle (const Rectangle& rectangleToCheck) const throw(); - Any rectangles in the list which overlap this will be clipped and subdivided - if necessary. - */ - void subtract (const RectangleList& otherList) throw(); + bool intersectsRectangle (const Rectangle& rectangleToCheck) const throw(); - /** Removes any areas of the region that lie outside a given rectangle. + bool intersects (const RectangleList& other) const throw(); - Any rectangles in the list which overlap this will be clipped and subdivided - if necessary. + const Rectangle getBounds() const throw(); - Returns true if the resulting region is not empty, false if it is empty. + void consolidate() throw(); - @see getIntersectionWith - */ - bool clipTo (const Rectangle& rect) throw(); + void offsetAll (const int dx, const int dy) throw(); - /** Removes any areas of the region that lie outside a given rectangle list. + const Path toPath() const throw(); - Any rectangles in this object which overlap the specified list will be clipped - and subdivided if necessary. + class Iterator + { + public: - Returns true if the resulting region is not empty, false if it is empty. + Iterator (const RectangleList& list) throw(); + ~Iterator() throw(); - @see getIntersectionWith - */ - bool clipTo (const RectangleList& other) throw(); + bool next() throw(); - /** Creates a region which is the result of clipping this one to a given rectangle. + const Rectangle* getRectangle() const throw() { return current; } - Unlike the other clipTo method, this one doesn't affect this object - it puts the - resulting region into the list whose reference is passed-in. + juce_UseDebuggingNewOperator - Returns true if the resulting region is not empty, false if it is empty. + private: + const Rectangle* current; + const RectangleList& owner; + int index; - @see clipTo - */ - bool getIntersectionWith (const Rectangle& rect, RectangleList& destRegion) const throw(); + Iterator (const Iterator&); + const Iterator& operator= (const Iterator&); + }; - /** Swaps the contents of this and another list. - - This swaps their internal pointers, so is hugely faster than using copy-by-value - to swap them. - */ - void swapWith (RectangleList& otherList) throw(); - - /** Checks whether the region contains a given point. - - @returns true if the point lies within one of the rectangles in the list - */ - bool containsPoint (const int x, const int y) const throw(); - - /** Checks whether the region contains the whole of a given rectangle. - - @returns true all parts of the rectangle passed in lie within the region - defined by this object - @see intersectsRectangle, containsPoint - */ - bool containsRectangle (const Rectangle& rectangleToCheck) const throw(); - - /** Checks whether the region contains any part of a given rectangle. - - @returns true if any part of the rectangle passed in lies within the region - defined by this object - @see containsRectangle - */ - bool intersectsRectangle (const Rectangle& rectangleToCheck) const throw(); - - /** Checks whether this region intersects any part of another one. - - @see intersectsRectangle - */ - bool intersects (const RectangleList& other) const throw(); - - /** Returns the smallest rectangle that can enclose the whole of this region. */ - const Rectangle getBounds() const throw(); - - /** Optimises the list into a minimum number of constituent rectangles. - - This will try to combine any adjacent rectangles into larger ones where - possible, to simplify lists that might have been fragmented by repeated - add/subtract calls. - */ - void consolidate() throw(); - - /** Adds an x and y value to all the co-ordinates. */ - void offsetAll (const int dx, const int dy) throw(); - - /** Creates a Path object to represent this region. */ - const Path toPath() const throw(); - - /** An iterator for accessing all the rectangles in a RectangleList. */ - class Iterator - { - public: - - Iterator (const RectangleList& list) throw(); - ~Iterator() throw(); - - /** Advances to the next rectangle, and returns true if it's not finished. - - Call this before using getRectangle() to find the rectangle that was returned. - */ - bool next() throw(); - - /** Returns the current rectangle. */ - const Rectangle* getRectangle() const throw() { return current; } - - juce_UseDebuggingNewOperator - - private: - const Rectangle* current; - const RectangleList& owner; - int index; - - Iterator (const Iterator&); - const Iterator& operator= (const Iterator&); - }; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class Iterator; - Array rects; + friend class Iterator; + Array rects; }; #endif // __JUCE_RECTANGLELIST_JUCEHEADER__ @@ -22756,88 +11538,58 @@ private: #ifndef __JUCE_BORDERSIZE_JUCEHEADER__ #define __JUCE_BORDERSIZE_JUCEHEADER__ -/** - Specifies a set of gaps to be left around the sides of a rectangle. - - This is basically the size of the spaces at the top, bottom, left and right of - a rectangle. It's used by various component classes to specify borders. - - @see Rectangle -*/ class JUCE_API BorderSize { public: - /** Creates a null border. + BorderSize() throw(); - All sizes are left as 0. - */ - BorderSize() throw(); + BorderSize (const BorderSize& other) throw(); - /** Creates a copy of another border. */ - BorderSize (const BorderSize& other) throw(); + BorderSize (const int topGap, + const int leftGap, + const int bottomGap, + const int rightGap) throw(); - /** Creates a border with the given gaps. */ - BorderSize (const int topGap, - const int leftGap, - const int bottomGap, - const int rightGap) throw(); + BorderSize (const int allGaps) throw(); - /** Creates a border with the given gap on all sides. */ - BorderSize (const int allGaps) throw(); + ~BorderSize() throw(); - /** Destructor. */ - ~BorderSize() throw(); + int getTop() const throw() { return top; } - /** Returns the gap that should be left at the top of the region. */ - int getTop() const throw() { return top; } + int getLeft() const throw() { return left; } - /** Returns the gap that should be left at the top of the region. */ - int getLeft() const throw() { return left; } + int getBottom() const throw() { return bottom; } - /** Returns the gap that should be left at the top of the region. */ - int getBottom() const throw() { return bottom; } + int getRight() const throw() { return right; } - /** Returns the gap that should be left at the top of the region. */ - int getRight() const throw() { return right; } + int getTopAndBottom() const throw() { return top + bottom; } - /** Returns the sum of the top and bottom gaps. */ - int getTopAndBottom() const throw() { return top + bottom; } + int getLeftAndRight() const throw() { return left + right; } - /** Returns the sum of the left and right gaps. */ - int getLeftAndRight() const throw() { return left + right; } + void setTop (const int newTopGap) throw(); - /** Changes the top gap. */ - void setTop (const int newTopGap) throw(); + void setLeft (const int newLeftGap) throw(); - /** Changes the left gap. */ - void setLeft (const int newLeftGap) throw(); + void setBottom (const int newBottomGap) throw(); - /** Changes the bottom gap. */ - void setBottom (const int newBottomGap) throw(); + void setRight (const int newRightGap) throw(); - /** Changes the right gap. */ - void setRight (const int newRightGap) throw(); + const Rectangle subtractedFrom (const Rectangle& original) const throw(); - /** Returns a rectangle with these borders removed from it. */ - const Rectangle subtractedFrom (const Rectangle& original) const throw(); + void subtractFrom (Rectangle& rectangle) const throw(); - /** Removes this border from a given rectangle. */ - void subtractFrom (Rectangle& rectangle) const throw(); + const Rectangle addedTo (const Rectangle& original) const throw(); - /** Returns a rectangle with these borders added around it. */ - const Rectangle addedTo (const Rectangle& original) const throw(); + void addTo (Rectangle& original) const throw(); - /** Adds this border around a given rectangle. */ - void addTo (Rectangle& original) const throw(); + bool operator== (const BorderSize& other) const throw(); + bool operator!= (const BorderSize& other) const throw(); - bool operator== (const BorderSize& other) const throw(); - bool operator!= (const BorderSize& other) const throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - int top, left, bottom, right; + int top, left, bottom, right; }; #endif // __JUCE_BORDERSIZE_JUCEHEADER__ @@ -22853,343 +11605,189 @@ class Graphics; class ComponentBoundsConstrainer; class ComponentDeletionWatcher; -/** - The base class for window objects that wrap a component as a real operating - system object. - - This is an abstract base class - the platform specific code contains default - implementations of it that create and manage windows. - - @see Component::createNewPeer -*/ -class JUCE_API ComponentPeer : public MessageListener +class JUCE_API ComponentPeer : public MessageListener { public: - /** A combination of these flags is passed to the ComponentPeer constructor. */ - enum StyleFlags - { - windowAppearsOnTaskbar = (1 << 0), /**< Indicates that the window should have a corresponding - entry on the taskbar (ignored on MacOSX) */ - windowIsTemporary = (1 << 1), /**< Indicates that the window is a temporary popup, like a menu, - tooltip, etc. */ - windowIgnoresMouseClicks = (1 << 2), /**< Indicates that the window should let mouse clicks pass - through it (may not be possible on some platforms). */ - windowHasTitleBar = (1 << 3), /**< Indicates that the window should have a normal OS-specific - title bar and frame\. if not specified, the window will be - borderless. */ - windowIsResizable = (1 << 4), /**< Indicates that the window should have a resizable border. */ - windowHasMinimiseButton = (1 << 5), /**< Indicates that if the window has a title bar, it should have a - minimise button on it. */ - windowHasMaximiseButton = (1 << 6), /**< Indicates that if the window has a title bar, it should have a - maximise button on it. */ - windowHasCloseButton = (1 << 7), /**< Indicates that if the window has a title bar, it should have a - close button on it. */ - windowHasDropShadow = (1 << 8), /**< Indicates that the window should have a drop-shadow (this may - not be possible on all platforms). */ - windowRepaintedExplictly = (1 << 9), /**< Not intended for public use - this tells a window not to - do its own repainting, but only to repaint when the - performAnyPendingRepaintsNow() method is called. */ - windowIgnoresKeyPresses = (1 << 10), /**< Tells the window not to catch any keypresses. This can - be used for things like plugin windows, to stop them interfering - with the host's shortcut keys */ - windowIsSemiTransparent = (1 << 31) /**< Not intended for public use - makes a window transparent. */ + enum StyleFlags + { + windowAppearsOnTaskbar = (1 << 0), /**< Indicates that the window should have a corresponding + entry on the taskbar (ignored on MacOSX) */ + windowIsTemporary = (1 << 1), /**< Indicates that the window is a temporary popup, like a menu, + tooltip, etc. */ + windowIgnoresMouseClicks = (1 << 2), /**< Indicates that the window should let mouse clicks pass + through it (may not be possible on some platforms). */ + windowHasTitleBar = (1 << 3), /**< Indicates that the window should have a normal OS-specific + title bar and frame\. if not specified, the window will be + borderless. */ + windowIsResizable = (1 << 4), /**< Indicates that the window should have a resizable border. */ + windowHasMinimiseButton = (1 << 5), /**< Indicates that if the window has a title bar, it should have a + minimise button on it. */ + windowHasMaximiseButton = (1 << 6), /**< Indicates that if the window has a title bar, it should have a + maximise button on it. */ + windowHasCloseButton = (1 << 7), /**< Indicates that if the window has a title bar, it should have a + close button on it. */ + windowHasDropShadow = (1 << 8), /**< Indicates that the window should have a drop-shadow (this may + not be possible on all platforms). */ + windowRepaintedExplictly = (1 << 9), /**< Not intended for public use - this tells a window not to + do its own repainting, but only to repaint when the + performAnyPendingRepaintsNow() method is called. */ + windowIgnoresKeyPresses = (1 << 10), /**< Tells the window not to catch any keypresses. This can + be used for things like plugin windows, to stop them interfering + with the host's shortcut keys */ + windowIsSemiTransparent = (1 << 31) /**< Not intended for public use - makes a window transparent. */ - }; + }; - /** Creates a peer. + ComponentPeer (Component* const component, + const int styleFlags) throw(); - The component is the one that we intend to represent, and the style flags are - a combination of the values in the StyleFlags enum - */ - ComponentPeer (Component* const component, - const int styleFlags) throw(); + virtual ~ComponentPeer(); - /** Destructor. */ - virtual ~ComponentPeer(); + Component* getComponent() const throw() { return component; } - /** Returns the component being represented by this peer. */ - Component* getComponent() const throw() { return component; } + int getStyleFlags() const throw() { return styleFlags; } - /** Returns the set of style flags that were set when the window was created. + virtual void* getNativeHandle() const = 0; - @see Component::addToDesktop - */ - int getStyleFlags() const throw() { return styleFlags; } + virtual void setVisible (bool shouldBeVisible) = 0; - /** Returns the raw handle to whatever kind of window is being used. + virtual void setTitle (const String& title) = 0; - On windows, this is probably a HWND, on the mac, it's likely to be a WindowRef, - but rememeber there's no guarantees what you'll get back. - */ - virtual void* getNativeHandle() const = 0; + virtual void setPosition (int x, int y) = 0; - /** Shows or hides the window. */ - virtual void setVisible (bool shouldBeVisible) = 0; + virtual void setSize (int w, int h) = 0; - /** Changes the title of the window. */ - virtual void setTitle (const String& title) = 0; + virtual void setBounds (int x, int y, int w, int h, const bool isNowFullScreen) = 0; - /** Moves the window without changing its size. + virtual void getBounds (int& x, int& y, int& w, int& h) const = 0; - If the native window is contained in another window, then the co-ordinates are - relative to the parent window's origin, not the screen origin. + virtual int getScreenX() const = 0; - This should result in a callback to handleMovedOrResized(). - */ - virtual void setPosition (int x, int y) = 0; + virtual int getScreenY() const = 0; - /** Resizes the window without changing its position. + virtual void relativePositionToGlobal (int& x, int& y) = 0; - This should result in a callback to handleMovedOrResized(). - */ - virtual void setSize (int w, int h) = 0; + virtual void globalPositionToRelative (int& x, int& y) = 0; - /** Moves and resizes the window. + virtual void setMinimised (bool shouldBeMinimised) = 0; - If the native window is contained in another window, then the co-ordinates are - relative to the parent window's origin, not the screen origin. + virtual bool isMinimised() const = 0; - This should result in a callback to handleMovedOrResized(). - */ - virtual void setBounds (int x, int y, int w, int h, const bool isNowFullScreen) = 0; + virtual void setFullScreen (bool shouldBeFullScreen) = 0; - /** Returns the current position and size of the window. + virtual bool isFullScreen() const = 0; - If the native window is contained in another window, then the co-ordinates are - relative to the parent window's origin, not the screen origin. - */ - virtual void getBounds (int& x, int& y, int& w, int& h) const = 0; + void setNonFullScreenBounds (const Rectangle& newBounds) throw(); - /** Returns the x-position of this window, relative to the screen's origin. */ - virtual int getScreenX() const = 0; + const Rectangle& getNonFullScreenBounds() const throw(); - /** Returns the y-position of this window, relative to the screen's origin. */ - virtual int getScreenY() const = 0; + virtual void setIcon (const Image& newIcon) = 0; - /** Converts a position relative to the top-left of this component to screen co-ordinates. */ - virtual void relativePositionToGlobal (int& x, int& y) = 0; + void setConstrainer (ComponentBoundsConstrainer* const newConstrainer) throw(); - /** Converts a screen co-ordinate to a position relative to the top-left of this component. */ - virtual void globalPositionToRelative (int& x, int& y) = 0; + ComponentBoundsConstrainer* getConstrainer() const throw() { return constrainer; } - /** Minimises the window. */ - virtual void setMinimised (bool shouldBeMinimised) = 0; + virtual bool contains (int x, int y, bool trueIfInAChildWindow) const = 0; - /** True if the window is currently minimised. */ - virtual bool isMinimised() const = 0; + virtual const BorderSize getFrameSize() const = 0; - /** Enable/disable fullscreen mode for the window. */ - virtual void setFullScreen (bool shouldBeFullScreen) = 0; + void handleMovedOrResized(); - /** True if the window is currently full-screen. */ - virtual bool isFullScreen() const = 0; + void handleScreenSizeChange(); - /** Sets the size to restore to if fullscreen mode is turned off. */ - void setNonFullScreenBounds (const Rectangle& newBounds) throw(); + void handlePaint (LowLevelGraphicsContext& contextToPaintTo); - /** Returns the size to restore to if fullscreen mode is turned off. */ - const Rectangle& getNonFullScreenBounds() const throw(); + virtual bool setAlwaysOnTop (bool alwaysOnTop) = 0; - /** Attempts to change the icon associated with this window. - */ - virtual void setIcon (const Image& newIcon) = 0; + virtual void toFront (bool makeActive) = 0; - /** Sets a constrainer to use if the peer can resize itself. + virtual void toBehind (ComponentPeer* other) = 0; - The constrainer won't be deleted by this object, so the caller must manage its lifetime. - */ - void setConstrainer (ComponentBoundsConstrainer* const newConstrainer) throw(); + void handleBroughtToFront(); - /** Returns the current constrainer, if one has been set. */ - ComponentBoundsConstrainer* getConstrainer() const throw() { return constrainer; } + virtual bool isFocused() const = 0; - /** Checks if a point is in the window. + virtual void grabFocus() = 0; - Coordinates are relative to the top-left of this window. If trueIfInAChildWindow - is false, then this returns false if the point is actually inside a child of this - window. - */ - virtual bool contains (int x, int y, bool trueIfInAChildWindow) const = 0; + virtual void textInputRequired (int x, int y) = 0; - /** Returns the size of the window frame that's around this window. + void handleFocusGain(); + void handleFocusLoss(); - Whether or not the window has a normal window frame depends on the flags - that were set when the window was created by Component::addToDesktop() - */ - virtual const BorderSize getFrameSize() const = 0; + Component* getLastFocusedSubcomponent() const throw(); - /** This is called when the window's bounds change. + bool handleKeyPress (const int keyCode, + const juce_wchar textCharacter); - A peer implementation must call this when the window is moved and resized, so that - this method can pass the message on to the component. - */ - void handleMovedOrResized(); + bool handleKeyUpOrDown (const bool isKeyDown); - /** This is called if the screen resolution changes. + void handleModifierKeysChange(); - A peer implementation must call this if the monitor arrangement changes or the available - screen size changes. - */ - void handleScreenSizeChange(); + virtual void repaint (int x, int y, int w, int h) = 0; - /** This is called to repaint the component into the given context. */ - void handlePaint (LowLevelGraphicsContext& contextToPaintTo); + virtual void performAnyPendingRepaintsNow() = 0; - /** Sets this window to either be always-on-top or normal. + void handleMouseEnter (int x, int y, const int64 time); + void handleMouseMove (int x, int y, const int64 time); + void handleMouseDown (int x, int y, const int64 time); + void handleMouseDrag (int x, int y, const int64 time); + void handleMouseUp (const int oldModifiers, int x, int y, const int64 time); + void handleMouseExit (int x, int y, const int64 time); + void handleMouseWheel (const int amountX, const int amountY, const int64 time); - Some kinds of window might not be able to do this, so should return false. - */ - virtual bool setAlwaysOnTop (bool alwaysOnTop) = 0; + void sendFakeMouseMove() throw(); - /** Brings the window to the top, optionally also giving it focus. */ - virtual void toFront (bool makeActive) = 0; + void handleUserClosingWindow(); - /** Moves the window to be just behind another one. */ - virtual void toBehind (ComponentPeer* other) = 0; + void handleFileDragMove (const StringArray& files, int x, int y); + void handleFileDragExit (const StringArray& files); + void handleFileDragDrop (const StringArray& files, int x, int y); - /** Called when the window is brought to the front, either by the OS or by a call - to toFront(). - */ - void handleBroughtToFront(); + void clearMaskedRegion() throw(); - /** True if the window has the keyboard focus. */ - virtual bool isFocused() const = 0; + void addMaskedRegion (int x, int y, int w, int h) throw(); - /** Tries to give the window keyboard focus. */ - virtual void grabFocus() = 0; + static int getNumPeers() throw(); - /** Tells the window that text input may be required at the given position. + static ComponentPeer* getPeer (const int index) throw(); - This may cause things like a virtual on-screen keyboard to appear, depending - on the OS. - */ - virtual void textInputRequired (int x, int y) = 0; + static bool isValidPeer (const ComponentPeer* const peer) throw(); - /** Called when the window gains keyboard focus. */ - void handleFocusGain(); - /** Called when the window loses keyboard focus. */ - void handleFocusLoss(); + static void bringModalComponentToFront(); - Component* getLastFocusedSubcomponent() const throw(); + virtual const StringArray getAvailableRenderingEngines() throw(); + virtual int getCurrentRenderingEngine() throw(); + virtual void setCurrentRenderingEngine (int index) throw(); - /** Called when a key is pressed. - - For keycode info, see the KeyPress class. - Returns true if the keystroke was used. - */ - bool handleKeyPress (const int keyCode, - const juce_wchar textCharacter); - - /** Called whenever a key is pressed or released. - Returns true if the keystroke was used. - */ - bool handleKeyUpOrDown (const bool isKeyDown); - - /** Called whenever a modifier key is pressed or released. */ - void handleModifierKeysChange(); - - /** Invalidates a region of the window to be repainted asynchronously. */ - virtual void repaint (int x, int y, int w, int h) = 0; - - /** This can be called (from the message thread) to cause the immediate redrawing - of any areas of this window that need repainting. - - You shouldn't ever really need to use this, it's mainly for special purposes - like supporting audio plugins where the host's event loop is out of our control. - */ - virtual void performAnyPendingRepaintsNow() = 0; - - void handleMouseEnter (int x, int y, const int64 time); - void handleMouseMove (int x, int y, const int64 time); - void handleMouseDown (int x, int y, const int64 time); - void handleMouseDrag (int x, int y, const int64 time); - void handleMouseUp (const int oldModifiers, int x, int y, const int64 time); - void handleMouseExit (int x, int y, const int64 time); - void handleMouseWheel (const int amountX, const int amountY, const int64 time); - - /** Causes a mouse-move callback to be made asynchronously. */ - void sendFakeMouseMove() throw(); - - void handleUserClosingWindow(); - - void handleFileDragMove (const StringArray& files, int x, int y); - void handleFileDragExit (const StringArray& files); - void handleFileDragDrop (const StringArray& files, int x, int y); - - /** Resets the masking region. - - The subclass should call this every time it's about to call the handlePaint - method. - - @see addMaskedRegion - */ - void clearMaskedRegion() throw(); - - /** Adds a rectangle to the set of areas not to paint over. - - A component can call this on its peer during its paint() method, to signal - that the painting code should ignore a given region. The reason - for this is to stop embedded windows (such as OpenGL) getting painted over. - - The masked region is cleared each time before a paint happens, so a component - will have to make sure it calls this every time it's painted. - */ - void addMaskedRegion (int x, int y, int w, int h) throw(); - - /** Returns the number of currently-active peers. - - @see getPeer - */ - static int getNumPeers() throw(); - - /** Returns one of the currently-active peers. - - @see getNumPeers - */ - static ComponentPeer* getPeer (const int index) throw(); - - /** Checks if this peer object is valid. - - @see getNumPeers - */ - static bool isValidPeer (const ComponentPeer* const peer) throw(); - - static void bringModalComponentToFront(); - - virtual const StringArray getAvailableRenderingEngines() throw(); - virtual int getCurrentRenderingEngine() throw(); - virtual void setCurrentRenderingEngine (int index) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - Component* const component; - const int styleFlags; - RectangleList maskedRegion; - Rectangle lastNonFullscreenBounds; - uint32 lastPaintTime; - ComponentBoundsConstrainer* constrainer; + Component* const component; + const int styleFlags; + RectangleList maskedRegion; + Rectangle lastNonFullscreenBounds; + uint32 lastPaintTime; + ComponentBoundsConstrainer* constrainer; - static void updateCurrentModifiers() throw(); + static void updateCurrentModifiers() throw(); - /** @internal */ - void handleMessage (const Message& message); + void handleMessage (const Message& message); private: - Component* lastFocusedComponent; - ScopedPointer dragAndDropTargetComponent; - Component* lastDragAndDropCompUnderMouse; - bool fakeMouseMessageSent : 1, isWindowMinimised : 1; + Component* lastFocusedComponent; + ScopedPointer dragAndDropTargetComponent; + Component* lastDragAndDropCompUnderMouse; + bool fakeMouseMessageSent : 1, isWindowMinimised : 1; - friend class Component; - static ComponentPeer* getPeerFor (const Component* const component) throw(); + friend class Component; + static ComponentPeer* getPeerFor (const Component* const component) throw(); - void setLastDragDropTarget (Component* comp); + void setLastDragDropTarget (Component* comp); - ComponentPeer (const ComponentPeer&); - const ComponentPeer& operator= (const ComponentPeer&); + ComponentPeer (const ComponentPeer&); + const ComponentPeer& operator= (const ComponentPeer&); }; #endif // __JUCE_COMPONENTPEER_JUCEHEADER__ @@ -23197,2043 +11795,526 @@ private: class LookAndFeel; -/** - The base class for all JUCE user-interface objects. - -*/ class JUCE_API Component : public MouseListener, - protected MessageListener + protected MessageListener { public: - /** Creates a component. + Component() throw(); - To get it to actually appear, you'll also need to: - - Either add it to a parent component or use the addToDesktop() method to - make it a desktop window - - Set its size and position to something sensible - - Use setVisible() to make it visible + virtual ~Component(); - And for it to serve any useful purpose, you'll need to write a - subclass of Component or use one of the other types of component from - the library. - */ - Component() throw(); + Component (const String& componentName) throw(); - /** Destructor. + const String& getName() const throw() { return componentName_; } - Note that when a component is deleted, any child components it might - contain are NOT deleted unless you explicitly call deleteAllChildren() first. - */ - virtual ~Component(); + virtual void setName (const String& newName); - /** Creates a component, setting its name at the same time. + bool isValidComponent() const throw(); - @see getName, setName - */ - Component (const String& componentName) throw(); + virtual void setVisible (bool shouldBeVisible); - /** Returns the name of this component. + bool isVisible() const throw() { return flags.visibleFlag; } - @see setName - */ - const String& getName() const throw() { return componentName_; } + virtual void visibilityChanged(); - /** Sets the name of this component. + bool isShowing() const throw(); - When the name changes, all registered ComponentListeners will receive a - ComponentListener::componentNameChanged() callback. + void fadeOutComponent (const int lengthOfFadeOutInMilliseconds, + const int deltaXToMove = 0, + const int deltaYToMove = 0, + const float scaleFactorAtEnd = 1.0f); - @see getName - */ - virtual void setName (const String& newName); - - /** Checks whether this Component object has been deleted. - - This will check whether this object is still a valid component, or whether - it's been deleted. + virtual void addToDesktop (int windowStyleFlags, + void* nativeWindowToAttachTo = 0); - It's safe to call this on null or dangling pointers, but note that there is a - small risk if another new (but different) component has been created at the - same memory address which this one occupied, this methods can return a - false positive. - */ - bool isValidComponent() const throw(); + void removeFromDesktop(); - /** Makes the component visible or invisible. + bool isOnDesktop() const throw(); - This method will show or hide the component. - Note that components default to being non-visible when first created. - Also note that visible components won't be seen unless all their parent components - are also visible. + ComponentPeer* getPeer() const throw(); - This method will call visibilityChanged() and also componentVisibilityChanged() - for any component listeners that are interested in this component. + virtual void userTriedToCloseWindow(); - @param shouldBeVisible whether to show or hide the component - @see isVisible, isShowing, visibilityChanged, ComponentListener::componentVisibilityChanged - */ - virtual void setVisible (bool shouldBeVisible); + virtual void minimisationStateChanged (bool isNowMinimised); - /** Tests whether the component is visible or not. + void toFront (const bool shouldAlsoGainFocus); - this doesn't necessarily tell you whether this comp is actually on the screen - because this depends on whether all the parent components are also visible - use - isShowing() to find this out. + void toBack(); - @see isShowing, setVisible - */ - bool isVisible() const throw() { return flags.visibleFlag; } + void toBehind (Component* const other); - /** Called when this component's visiblility changes. + void setAlwaysOnTop (const bool shouldStayOnTop); - @see setVisible, isVisible - */ - virtual void visibilityChanged(); + bool isAlwaysOnTop() const throw(); - /** Tests whether this component and all its parents are visible. + inline int getX() const throw() { return bounds_.getX(); } - @returns true only if this component and all its parents are visible. - @see isVisible - */ - bool isShowing() const throw(); + inline int getY() const throw() { return bounds_.getY(); } - /** Makes a component invisible using a groovy fade-out and animated zoom effect. + inline int getWidth() const throw() { return bounds_.getWidth(); } - To do this, this function will cunningly: - - take a snapshot of the component as it currently looks - - call setVisible(false) on the component - - replace it with a special component that will continue drawing the - snapshot, animating it and gradually making it more transparent - - when it's gone, the special component will also be deleted + inline int getHeight() const throw() { return bounds_.getHeight(); } - As soon as this method returns, the component can be safely removed and deleted - leaving the proxy to do the fade-out, so it's even ok to call this in a - component's destructor. + int getRight() const throw() { return bounds_.getRight(); } - Passing non-zero x and y values will cause the ghostly component image to - also whizz off by this distance while fading out. If the scale factor is - not 1.0, it will also zoom from the component's current size to this new size. + int getBottom() const throw() { return bounds_.getBottom(); } - One thing to be careful about is that the parent component must be able to cope - with this unknown component type being added to it. - */ - void fadeOutComponent (const int lengthOfFadeOutInMilliseconds, - const int deltaXToMove = 0, - const int deltaYToMove = 0, - const float scaleFactorAtEnd = 1.0f); + const Rectangle& getBounds() const throw() { return bounds_; } - /** Makes this component appear as a window on the desktop. + void getVisibleArea (RectangleList& result, + const bool includeSiblings) const; - Note that before calling this, you should make sure that the component's opacity is - set correctly using setOpaque(). If the component is non-opaque, the windowing - system will try to create a special transparent window for it, which will generally take - a lot more CPU to operate (and might not even be possible on some platforms). + int getScreenX() const throw(); - If the component is inside a parent component at the time this method is called, it - will be first be removed from that parent. Likewise if a component on the desktop - is subsequently added to another component, it'll be removed from the desktop. + int getScreenY() const throw(); - @param windowStyleFlags a combination of the flags specified in the - ComponentPeer::StyleFlags enum, which define the - window's characteristics. - @param nativeWindowToAttachTo this allows an OS object to be passed-in as the window - in which the juce component should place itself. On Windows, - this would be a HWND, a HIViewRef on the Mac. Not necessarily - supported on all platforms, and best left as 0 unless you know - what you're doing - @see removeFromDesktop, isOnDesktop, userTriedToCloseWindow, - getPeer, ComponentPeer::setMinimised, ComponentPeer::StyleFlags, - ComponentPeer::getStyleFlags, ComponentPeer::setFullScreen - */ - virtual void addToDesktop (int windowStyleFlags, - void* nativeWindowToAttachTo = 0); + void relativePositionToGlobal (int& x, int& y) const throw(); - /** If the component is currently showing on the desktop, this will hide it. + void globalPositionToRelative (int& x, int& y) const throw(); - You can also use setVisible() to hide a desktop window temporarily, but - removeFromDesktop() will free any system resources that are being used up. + void relativePositionToOtherComponent (const Component* const targetComponent, + int& x, int& y) const throw(); - @see addToDesktop, isOnDesktop - */ - void removeFromDesktop(); + void setTopLeftPosition (const int x, const int y); - /** Returns true if this component is currently showing on the desktop. + void setTopRightPosition (const int x, const int y); - @see addToDesktop, removeFromDesktop - */ - bool isOnDesktop() const throw(); + void setSize (const int newWidth, const int newHeight); - /** Returns the heavyweight window that contains this component. + void setBounds (int x, int y, int width, int height); - If this component is itself on the desktop, this will return the window - object that it is using. Otherwise, it will return the window of - its top-level parent component. + void setBounds (const Rectangle& newBounds); - This may return 0 if there isn't a desktop component. + void setBoundsRelative (const float proportionalX, const float proportionalY, + const float proportionalWidth, const float proportionalHeight); - @see addToDesktop, isOnDesktop - */ - ComponentPeer* getPeer() const throw(); + void setBoundsInset (const BorderSize& borders); - /** For components on the desktop, this is called if the system wants to close the window. + void setBoundsToFit (int x, int y, int width, int height, + const Justification& justification, + const bool onlyReduceInSize); - This is a signal that either the user or the system wants the window to close. The - default implementation of this method will trigger an assertion to warn you that your - component should do something about it, but you can override this to ignore the event - if you want. - */ - virtual void userTriedToCloseWindow(); + void setCentrePosition (const int x, const int y); - /** Called for a desktop component which has just been minimised or un-minimised. + void setCentreRelative (const float x, const float y); - This will only be called for components on the desktop. + void centreWithSize (const int width, const int height); - @see getPeer, ComponentPeer::setMinimised, ComponentPeer::isMinimised - */ - virtual void minimisationStateChanged (bool isNowMinimised); + int proportionOfWidth (const float proportion) const throw(); - /** Brings the component to the front of its siblings. + int proportionOfHeight (const float proportion) const throw(); - If some of the component's siblings have had their 'always-on-top' flag set, - then they will still be kept in front of this one (unless of course this - one is also 'always-on-top'). + int getParentWidth() const throw(); - @param shouldAlsoGainFocus if true, this will also try to assign keyboard focus - to the component (see grabKeyboardFocus() for more details) - @see toBack, toBehind, setAlwaysOnTop - */ - void toFront (const bool shouldAlsoGainFocus); + int getParentHeight() const throw(); - /** Changes this component's z-order to be at the back of all its siblings. + const Rectangle getParentMonitorArea() const throw(); - If the component is set to be 'always-on-top', it will only be moved to the - back of the other other 'always-on-top' components. + int getNumChildComponents() const throw(); - @see toFront, toBehind, setAlwaysOnTop - */ - void toBack(); + Component* getChildComponent (const int index) const throw(); - /** Changes this component's z-order so that it's just behind another component. + int getIndexOfChildComponent (const Component* const child) const throw(); - @see toFront, toBack - */ - void toBehind (Component* const other); + void addChildComponent (Component* const child, + int zOrder = -1); - /** Sets whether the component should always be kept at the front of its siblings. + void addAndMakeVisible (Component* const child, + int zOrder = -1); - @see isAlwaysOnTop - */ - void setAlwaysOnTop (const bool shouldStayOnTop); + void removeChildComponent (Component* const childToRemove); - /** Returns true if this component is set to always stay in front of its siblings. + Component* removeChildComponent (const int childIndexToRemove); - @see setAlwaysOnTop - */ - bool isAlwaysOnTop() const throw(); + void removeAllChildren(); - /** Returns the x co-ordinate of the component's left edge. + void deleteAllChildren(); - This is a distance in pixels from the left edge of the component's parent. + Component* getParentComponent() const throw() { return parentComponent_; } - @see getScreenX - */ - inline int getX() const throw() { return bounds_.getX(); } + template + TargetClass* findParentComponentOfClass (TargetClass* const dummyParameter = 0) const + { + (void) dummyParameter; + Component* p = parentComponent_; + while (p != 0) + { + TargetClass* target = dynamic_cast (p); + if (target != 0) + return target; - /** Returns the y co-ordinate of the top of this component. + p = p->parentComponent_; + } - This is a distance in pixels from the top edge of the component's parent. + return 0; + } - @see getScreenY - */ - inline int getY() const throw() { return bounds_.getY(); } + Component* getTopLevelComponent() const throw(); - /** Returns the component's width in pixels. */ - inline int getWidth() const throw() { return bounds_.getWidth(); } + bool isParentOf (const Component* possibleChild) const throw(); - /** Returns the component's height in pixels. */ - inline int getHeight() const throw() { return bounds_.getHeight(); } + virtual void parentHierarchyChanged(); - /** Returns the x co-ordinate of the component's right-hand edge. + virtual void childrenChanged(); - This is a distance in pixels from the left edge of the component's parent. - */ - int getRight() const throw() { return bounds_.getRight(); } + virtual bool hitTest (int x, int y); - /** Returns the y co-ordinate of the bottom edge of this component. + void setInterceptsMouseClicks (const bool allowClicksOnThisComponent, + const bool allowClicksOnChildComponents) throw(); - This is a distance in pixels from the top edge of the component's parent. - */ - int getBottom() const throw() { return bounds_.getBottom(); } + void getInterceptsMouseClicks (bool& allowsClicksOnThisComponent, + bool& allowsClicksOnChildComponents) const throw(); - /** Returns this component's bounding box. + virtual bool contains (int x, int y); - The rectangle returned is relative to the top-left of the component's parent. - */ - const Rectangle& getBounds() const throw() { return bounds_; } + bool reallyContains (int x, int y, + const bool returnTrueIfWithinAChild); - /** Returns the region of this component that's not obscured by other, opaque components. + Component* getComponentAt (const int x, const int y); - The RectangleList that is returned represents the area of this component - which isn't covered by opaque child components. + void repaint() throw(); - If includeSiblings is true, it will also take into account any siblings - that may be overlapping the component. - */ - void getVisibleArea (RectangleList& result, - const bool includeSiblings) const; + void repaint (const int x, const int y, + const int width, const int height) throw(); - /** Returns this component's x co-ordinate relative the the screen's top-left origin. + void setBufferedToImage (const bool shouldBeBuffered) throw(); - @see getX, relativePositionToGlobal - */ - int getScreenX() const throw(); + Image* createComponentSnapshot (const Rectangle& areaToGrab, + const bool clipImageToComponentBounds = true); - /** Returns this component's y co-ordinate relative the the screen's top-left origin. + void paintEntireComponent (Graphics& context); - @see getY, relativePositionToGlobal - */ - int getScreenY() const throw(); + void setComponentEffect (ImageEffectFilter* const newEffect); - /** Converts a position relative to this component's top-left into a screen co-ordinate. + ImageEffectFilter* getComponentEffect() const throw() { return effect_; } - @see globalPositionToRelative, relativePositionToOtherComponent - */ - void relativePositionToGlobal (int& x, int& y) const throw(); + LookAndFeel& getLookAndFeel() const throw(); - /** Converts a screen co-ordinate into a position relative to this component's top-left. + void setLookAndFeel (LookAndFeel* const newLookAndFeel); - @see relativePositionToGlobal, relativePositionToOtherComponent - */ - void globalPositionToRelative (int& x, int& y) const throw(); + virtual void lookAndFeelChanged(); - /** Converts a position relative to this component's top-left into a position - relative to another component's top-left. + void sendLookAndFeelChange(); - @see relativePositionToGlobal, globalPositionToRelative - */ - void relativePositionToOtherComponent (const Component* const targetComponent, - int& x, int& y) const throw(); + void setOpaque (const bool shouldBeOpaque) throw(); - /** Moves the component to a new position. + bool isOpaque() const throw(); - Changes the component's top-left position (without changing its size). - The position is relative to the top-left of the component's parent. + void setBroughtToFrontOnMouseClick (const bool shouldBeBroughtToFront) throw(); - If the component actually moves, this method will make a synchronous call to moved(). + bool isBroughtToFrontOnMouseClick() const throw(); - @see setBounds, ComponentListener::componentMovedOrResized - */ - void setTopLeftPosition (const int x, const int y); + // Keyboard focus methods - /** Moves the component to a new position. + void setWantsKeyboardFocus (const bool wantsFocus) throw(); - Changes the position of the component's top-right corner (keeping it the same size). - The position is relative to the top-left of the component's parent. + bool getWantsKeyboardFocus() const throw(); - If the component actually moves, this method will make a synchronous call to moved(). - */ - void setTopRightPosition (const int x, const int y); + void setMouseClickGrabsKeyboardFocus (const bool shouldGrabFocus); - /** Changes the size of the component. + bool getMouseClickGrabsKeyboardFocus() const throw(); - A synchronous call to resized() will be occur if the size actually changes. - */ - void setSize (const int newWidth, const int newHeight); + void grabKeyboardFocus(); - /** Changes the component's position and size. + bool hasKeyboardFocus (const bool trueIfChildIsFocused) const throw(); - The co-ordinates are relative to the top-left of the component's parent, or relative - to the origin of the screen is the component is on the desktop. + static Component* JUCE_CALLTYPE getCurrentlyFocusedComponent() throw(); - If this method changes the component's top-left position, it will make a synchronous - call to moved(). If it changes the size, it will also make a call to resized(). + void moveKeyboardFocusToSibling (const bool moveToNext); - @see setTopLeftPosition, setSize, ComponentListener::componentMovedOrResized - */ - void setBounds (int x, int y, int width, int height); + virtual KeyboardFocusTraverser* createFocusTraverser(); - /** Changes the component's position and size. + int getExplicitFocusOrder() const throw(); - @see setBounds - */ - void setBounds (const Rectangle& newBounds); + void setExplicitFocusOrder (const int newFocusOrderIndex) throw(); - /** Changes the component's position and size in terms of fractions of its parent's size. + void setFocusContainer (const bool shouldBeFocusContainer) throw(); - The values are factors of the parent's size, so for example - setBoundsRelative (0.2f, 0.2f, 0.5f, 0.5f) would give it half the - width and height of the parent, with its top-left position 20% of - the way across and down the parent. - */ - void setBoundsRelative (const float proportionalX, const float proportionalY, - const float proportionalWidth, const float proportionalHeight); + bool isFocusContainer() const throw(); - /** Changes the component's position and size based on the amount of space to leave around it. + bool isEnabled() const throw(); - This will position the component within its parent, leaving the specified number of - pixels around each edge. - */ - void setBoundsInset (const BorderSize& borders); + void setEnabled (const bool shouldBeEnabled); - /** Positions the component within a given rectangle, keeping its proportions - unchanged. + virtual void enablementChanged(); - If onlyReduceInSize is false, the component will be resized to fill as much of the - rectangle as possible without changing its aspect ratio (the component's - current size is used to determine its aspect ratio, so a zero-size component - won't work here). If onlyReduceInSize is true, it will only be resized if it's - too big to fit inside the rectangle. + void setMouseCursor (const MouseCursor& cursorType) throw(); - It will then be positioned within the rectangle according to the justification flags - specified. - */ - void setBoundsToFit (int x, int y, int width, int height, - const Justification& justification, - const bool onlyReduceInSize); + virtual const MouseCursor getMouseCursor(); - /** Changes the position of the component's centre. + void updateMouseCursor() const throw(); - Leaves the component's size unchanged, but sets the position of its centre - relative to its parent's top-left. - */ - void setCentrePosition (const int x, const int y); + virtual void paint (Graphics& g); - /** Changes the position of the component's centre. + virtual void paintOverChildren (Graphics& g); - Leaves the position unchanged, but positions its centre relative to its - parent's size. E.g. setCentreRelative (0.5f, 0.5f) would place it centrally in - its parent. - */ - void setCentreRelative (const float x, const float y); + virtual void mouseMove (const MouseEvent& e); - /** Changes the component's size and centres it within its parent. + virtual void mouseEnter (const MouseEvent& e); - After changing the size, the component will be moved so that it's - centred within its parent. - */ - void centreWithSize (const int width, const int height); + virtual void mouseExit (const MouseEvent& e); - /** Returns a proportion of the component's width. + virtual void mouseDown (const MouseEvent& e); - This is a handy equivalent of (getWidth() * proportion). - */ - int proportionOfWidth (const float proportion) const throw(); + virtual void mouseDrag (const MouseEvent& e); - /** Returns a proportion of the component's height. + virtual void mouseUp (const MouseEvent& e); - This is a handy equivalent of (getHeight() * proportion). - */ - int proportionOfHeight (const float proportion) const throw(); + virtual void mouseDoubleClick (const MouseEvent& e); - /** Returns the width of the component's parent. + virtual void mouseWheelMove (const MouseEvent& e, + float wheelIncrementX, + float wheelIncrementY); - If the component has no parent (i.e. if it's on the desktop), this will return - the width of the screen. - */ - int getParentWidth() const throw(); + static void beginDragAutoRepeat (const int millisecondIntervalBetweenCallbacks); - /** Returns the height of the component's parent. + void setRepaintsOnMouseActivity (const bool shouldRepaint) throw(); - If the component has no parent (i.e. if it's on the desktop), this will return - the height of the screen. - */ - int getParentHeight() const throw(); + void addMouseListener (MouseListener* const newListener, + const bool wantsEventsForAllNestedChildComponents) throw(); - /** Returns the screen co-ordinates of the monitor that contains this component. + void removeMouseListener (MouseListener* const listenerToRemove) throw(); - If there's only one monitor, this will return its size - if there are multiple - monitors, it will return the area of the monitor that contains the component's - centre. - */ - const Rectangle getParentMonitorArea() const throw(); + void addKeyListener (KeyListener* const newListener) throw(); - /** Returns the number of child components that this component contains. + void removeKeyListener (KeyListener* const listenerToRemove) throw(); - @see getChildComponent, getIndexOfChildComponent - */ - int getNumChildComponents() const throw(); + virtual bool keyPressed (const KeyPress& key); - /** Returns one of this component's child components, by it index. + virtual bool keyStateChanged (const bool isKeyDown); - The component with index 0 is at the back of the z-order, the one at the - front will have index (getNumChildComponents() - 1). + virtual void modifierKeysChanged (const ModifierKeys& modifiers); - If the index is out-of-range, this will return a null pointer. + enum FocusChangeType + { + focusChangedByMouseClick, /**< Means that the user clicked the mouse to change focus. */ + focusChangedByTabKey, /**< Means that the user pressed the tab key to move the focus. */ + focusChangedDirectly /**< Means that the focus was changed by a call to grabKeyboardFocus(). */ + }; - @see getNumChildComponents, getIndexOfChildComponent - */ - Component* getChildComponent (const int index) const throw(); + virtual void focusGained (FocusChangeType cause); - /** Returns the index of this component in the list of child components. + virtual void focusLost (FocusChangeType cause); - A value of 0 means it is first in the list (i.e. behind all other components). Higher - values are further towards the front. + virtual void focusOfChildComponentChanged (FocusChangeType cause); - Returns -1 if the component passed-in is not a child of this component. + bool isMouseOver() const throw(); - @see getNumChildComponents, getChildComponent, addChildComponent, toFront, toBack, toBehind - */ - int getIndexOfChildComponent (const Component* const child) const throw(); + bool isMouseButtonDown() const throw(); - /** Adds a child component to this one. + bool isMouseOverOrDragging() const throw(); - @param child the new component to add. If the component passed-in is already - the child of another component, it'll first be removed from that. + static bool JUCE_CALLTYPE isMouseButtonDownAnywhere() throw(); - @param zOrder The index in the child-list at which this component should be inserted. - A value of -1 will insert it in front of the others, 0 is the back. - @see removeChildComponent, addAndMakeVisible, getChild, - ComponentListener::componentChildrenChanged - */ - void addChildComponent (Component* const child, - int zOrder = -1); + void getMouseXYRelative (int& x, int& y) const throw(); - /** Adds a child component to this one, and also makes the child visible if it isn't. + static Component* JUCE_CALLTYPE getComponentUnderMouse() throw(); - Quite a useful function, this is just the same as calling addChildComponent() - followed by setVisible (true) on the child. - */ - void addAndMakeVisible (Component* const child, - int zOrder = -1); + void enableUnboundedMouseMovement (bool shouldUnboundedMovementBeEnabled, + bool keepCursorVisibleUntilOffscreen = false) throw(); - /** Removes one of this component's child-components. + virtual void resized(); - If the child passed-in isn't actually a child of this component (either because - it's invalid or is the child of a different parent), then nothing is done. + virtual void moved(); - Note that removing a child will not delete it! + virtual void childBoundsChanged (Component* child); - @see addChildComponent, ComponentListener::componentChildrenChanged - */ - void removeChildComponent (Component* const childToRemove); + virtual void parentSizeChanged(); - /** Removes one of this component's child-components by index. + virtual void broughtToFront(); - This will return a pointer to the component that was removed, or null if - the index was out-of-range. + void addComponentListener (ComponentListener* const newListener) throw(); - Note that removing a child will not delete it! + void removeComponentListener (ComponentListener* const listenerToRemove) throw(); - @see addChildComponent, ComponentListener::componentChildrenChanged - */ - Component* removeChildComponent (const int childIndexToRemove); + void postCommandMessage (const int commandId) throw(); - /** Removes all this component's children. + virtual void handleCommandMessage (int commandId); - Note that this won't delete them! To do that, use deleteAllChildren() instead. - */ - void removeAllChildren(); + int runModalLoop(); - /** Removes all this component's children, and deletes them. + void enterModalState (const bool takeKeyboardFocus = true); - @see removeAllChildren - */ - void deleteAllChildren(); + void exitModalState (const int returnValue); - /** Returns the component which this component is inside. + bool isCurrentlyModal() const throw(); - If this is the highest-level component or hasn't yet been added to - a parent, this will return null. - */ - Component* getParentComponent() const throw() { return parentComponent_; } + static int JUCE_CALLTYPE getNumCurrentlyModalComponents() throw(); - /** Searches the parent components for a component of a specified class. + static Component* JUCE_CALLTYPE getCurrentlyModalComponent (int index = 0) throw(); - For example findParentComponentOfClass \() would return the first parent - component that can be dynamically cast to a MyComp, or will return 0 if none - of the parents are suitable. + bool isCurrentlyBlockedByAnotherModalComponent() const throw(); - N.B. The dummy parameter is needed to work around a VC6 compiler bug. - */ - template - TargetClass* findParentComponentOfClass (TargetClass* const dummyParameter = 0) const - { - (void) dummyParameter; - Component* p = parentComponent_; - while (p != 0) - { - TargetClass* target = dynamic_cast (p); - if (target != 0) - return target; + virtual bool canModalEventBeSentToComponent (const Component* targetComponent); - p = p->parentComponent_; - } + virtual void inputAttemptWhenModal(); - return 0; - } + const String getComponentProperty (const String& keyName, + const bool useParentComponentIfNotFound, + const String& defaultReturnValue = String::empty) const throw(); - /** Returns the highest-level component which contains this one or its parents. + int getComponentPropertyInt (const String& keyName, + const bool useParentComponentIfNotFound, + const int defaultReturnValue = 0) const throw(); - This will search upwards in the parent-hierarchy from this component, until it - finds the highest one that doesn't have a parent (i.e. is on the desktop or - not yet added to a parent), and will return that. - */ - Component* getTopLevelComponent() const throw(); + double getComponentPropertyDouble (const String& keyName, + const bool useParentComponentIfNotFound, + const double defaultReturnValue = 0.0) const throw(); - /** Checks whether a component is anywhere inside this component or its children. + bool getComponentPropertyBool (const String& keyName, + const bool useParentComponentIfNotFound, + const bool defaultReturnValue = false) const throw(); - This will recursively check through this components children to see if the - given component is anywhere inside. - */ - bool isParentOf (const Component* possibleChild) const throw(); + const Colour getComponentPropertyColour (const String& keyName, + const bool useParentComponentIfNotFound, + const Colour& defaultReturnValue = Colours::black) const throw(); - /** Called to indicate that the component's parents have changed. + void setComponentProperty (const String& keyName, const String& value) throw(); - When a component is added or removed from its parent, this method will - be called on all of its children (recursively - so all children of its - children will also be called as well). + void setComponentProperty (const String& keyName, const int value) throw(); - Subclasses can override this if they need to react to this in some way. + void setComponentProperty (const String& keyName, const double value) throw(); - @see getParentComponent, isShowing, ComponentListener::componentParentHierarchyChanged - */ - virtual void parentHierarchyChanged(); + void setComponentProperty (const String& keyName, const bool value) throw(); - /** Subclasses can use this callback to be told when children are added or removed. + void setComponentProperty (const String& keyName, const Colour& newColour) throw(); - @see parentHierarchyChanged - */ - virtual void childrenChanged(); + void removeComponentProperty (const String& keyName) throw(); - /** Tests whether a given point inside the component. + PropertySet* getComponentProperties() const throw() { return propertySet_; } - Overriding this method allows you to create components which only intercept - mouse-clicks within a user-defined area. + const Colour findColour (const int colourId, const bool inheritFromParent = false) const throw(); - This is called to find out whether a particular x, y co-ordinate is - considered to be inside the component or not, and is used by methods such - as contains() and getComponentAt() to work out which component - the mouse is clicked on. + void setColour (const int colourId, const Colour& colour); - Components with custom shapes will probably want to override it to perform - some more complex hit-testing. + void removeColour (const int colourId); - The default implementation of this method returns either true or false, - depending on the value that was set by calling setInterceptsMouseClicks() (true - is the default return value). + bool isColourSpecified (const int colourId) const throw(); - Note that the hit-test region is not related to the opacity with which - areas of a component are painted. - - Applications should never call hitTest() directly - instead use the - contains() method, because this will also test for occlusion by the - component's parent. - - Note that for components on the desktop, this method will be ignored, because it's - not always possible to implement this behaviour on all platforms. - - @param x the x co-ordinate to test, relative to the left hand edge of this - component. This value is guaranteed to be greater than or equal to - zero, and less than the component's width - @param y the y co-ordinate to test, relative to the top edge of this - component. This value is guaranteed to be greater than or equal to - zero, and less than the component's height - @returns true if the click is considered to be inside the component - @see setInterceptsMouseClicks, contains - */ - virtual bool hitTest (int x, int y); - - /** Changes the default return value for the hitTest() method. - - Setting this to false is an easy way to make a component pass its mouse-clicks - through to the components behind it. - - When a component is created, the default setting for this is true. - - @param allowClicksOnThisComponent if true, hitTest() will always return true; if false, it will - return false (or true for child components if allowClicksOnChildComponents - is true) - @param allowClicksOnChildComponents if this is true and allowClicksOnThisComponent is false, then child - components can be clicked on as normal but clicks on this component pass - straight through; if this is false and allowClicksOnThisComponent - is false, then neither this component nor any child components can - be clicked on - @see hitTest, getInterceptsMouseClicks - */ - void setInterceptsMouseClicks (const bool allowClicksOnThisComponent, - const bool allowClicksOnChildComponents) throw(); + void copyAllExplicitColoursTo (Component& target) const throw(); - /** Retrieves the current state of the mouse-click interception flags. + virtual void colourChanged(); - On return, the two parameters are set to the state used in the last call to - setInterceptsMouseClicks(). + void* getWindowHandle() const throw(); - @see setInterceptsMouseClicks - */ - void getInterceptsMouseClicks (bool& allowsClicksOnThisComponent, - bool& allowsClicksOnChildComponents) const throw(); + uint32 getComponentUID() const throw() { return componentUID; } - /** Returns true if a given point lies within this component or one of its children. - - Never override this method! Use hitTest to create custom hit regions. - - @param x the x co-ordinate to test, relative to this component's left hand edge. - @param y the y co-ordinate to test, relative to this component's top edge. - @returns true if the point is within the component's hit-test area, but only if - that part of the component isn't clipped by its parent component. Note - that this won't take into account any overlapping sibling components - which might be in the way - for that, see reallyContains() - @see hitTest, reallyContains, getComponentAt - */ - virtual bool contains (int x, int y); - - /** Returns true if a given point lies in this component, taking any overlapping - siblings into account. - - @param x the x co-ordinate to test, relative to this component's left hand edge. - @param y the y co-ordinate to test, relative to this component's top edge. - @param returnTrueIfWithinAChild if the point actually lies within a child of this - component, this determines the value that will - be returned. - - @see contains, getComponentAt - */ - bool reallyContains (int x, int y, - const bool returnTrueIfWithinAChild); - - /** Returns the component at a certain point within this one. - - @param x the x co-ordinate to test, relative to this component's left hand edge. - @param y the y co-ordinate to test, relative to this component's top edge. - @returns the component that is at this position - which may be 0, this component, - or one of its children. Note that overlapping siblings that might actually - be in the way are not taken into account by this method - to account for these, - instead call getComponentAt on the top-level parent of this component. - @see hitTest, contains, reallyContains - */ - Component* getComponentAt (const int x, const int y); - - /** Marks the whole component as needing to be redrawn. - - Calling this will not do any repainting immediately, but will mark the component - as 'dirty'. At some point in the near future the operating system will send a paint - message, which will redraw all the dirty regions of all components. - There's no guarantee about how soon after calling repaint() the redraw will actually - happen, and other queued events may be delivered before a redraw is done. - - If the setBufferedToImage() method has been used to cause this component - to use a buffer, the repaint() call will invalidate the component's buffer. - - To redraw just a subsection of the component rather than the whole thing, - use the repaint (int, int, int, int) method. - - @see paint - */ - void repaint() throw(); - - /** Marks a subsection of this component as needing to be redrawn. - - Calling this will not do any repainting immediately, but will mark the given region - of the component as 'dirty'. At some point in the near future the operating system - will send a paint message, which will redraw all the dirty regions of all components. - There's no guarantee about how soon after calling repaint() the redraw will actually - happen, and other queued events may be delivered before a redraw is done. - - The region that is passed in will be clipped to keep it within the bounds of this - component. - - @see repaint() - */ - void repaint (const int x, const int y, - const int width, const int height) throw(); - - /** Makes the component use an internal buffer to optimise its redrawing. - - Setting this flag to true will cause the component to allocate an - internal buffer into which it paints itself, so that when asked to - redraw itself, it can use this buffer rather than actually calling the - paint() method. - - The buffer is kept until the repaint() method is called directly on - this component (or until it is resized), when the image is invalidated - and then redrawn the next time the component is painted. - - Note that only the drawing that happens within the component's paint() - method is drawn into the buffer, it's child components are not buffered, and - nor is the paintOverChildren() method. - - @see repaint, paint, createComponentSnapshot - */ - void setBufferedToImage (const bool shouldBeBuffered) throw(); - - /** Generates a snapshot of part of this component. - - This will return a new Image, the size of the rectangle specified, - containing a snapshot of the specified area of the component and all - its children. - - The image may or may not have an alpha-channel, depending on whether the - image is opaque or not. - - If the clipImageToComponentBounds parameter is true and the area is greater than - the size of the component, it'll be clipped. If clipImageToComponentBounds is false - then parts of the component beyond its bounds can be drawn. - - The caller is responsible for deleting the image that is returned. - - @see paintEntireComponent - */ - Image* createComponentSnapshot (const Rectangle& areaToGrab, - const bool clipImageToComponentBounds = true); - - /** Draws this component and all its subcomponents onto the specified graphics - context. - - You should very rarely have to use this method, it's simply there in case you need - to draw a component with a custom graphics context for some reason, e.g. for - creating a snapshot of the component. - - It calls paint(), paintOverChildren() and recursively calls paintEntireComponent() - on its children in order to render the entire tree. - - The graphics context may be left in an undefined state after this method returns, - so you may need to reset it if you're going to use it again. - */ - void paintEntireComponent (Graphics& context); - - /** Adds an effect filter to alter the component's appearance. - - When a component has an effect filter set, then this is applied to the - results of its paint() method. There are a few preset effects, such as - a drop-shadow or glow, but they can be user-defined as well. - - The effect that is passed in will not be deleted by the component - the - caller must take care of deleting it. - - To remove an effect from a component, pass a null pointer in as the parameter. - - @see ImageEffectFilter, DropShadowEffect, GlowEffect - */ - void setComponentEffect (ImageEffectFilter* const newEffect); - - /** Returns the current component effect. - - @see setComponentEffect - */ - ImageEffectFilter* getComponentEffect() const throw() { return effect_; } - - /** Finds the appropriate look-and-feel to use for this component. - - If the component hasn't had a look-and-feel explicitly set, this will - return the parent's look-and-feel, or just the default one if there's no - parent. - - @see setLookAndFeel, lookAndFeelChanged - */ - LookAndFeel& getLookAndFeel() const throw(); - - /** Sets the look and feel to use for this component. - - This will also change the look and feel for any child components that haven't - had their look set explicitly. - - The object passed in will not be deleted by the component, so it's the caller's - responsibility to manage it. It may be used at any time until this component - has been deleted. - - Calling this method will also invoke the sendLookAndFeelChange() method. - - @see getLookAndFeel, lookAndFeelChanged - */ - void setLookAndFeel (LookAndFeel* const newLookAndFeel); - - /** Called to let the component react to a change in the look-and-feel setting. - - When the look-and-feel is changed for a component, this will be called in - all its child components, recursively. - - It can also be triggered manually by the sendLookAndFeelChange() method, in case - an application uses a LookAndFeel class that might have changed internally. - - @see sendLookAndFeelChange, getLookAndFeel - */ - virtual void lookAndFeelChanged(); - - /** Calls the lookAndFeelChanged() method in this component and all its children. - - This will recurse through the children and their children, calling lookAndFeelChanged() - on them all. - - @see lookAndFeelChanged - */ - void sendLookAndFeelChange(); - - /** Indicates whether any parts of the component might be transparent. - - Components that always paint all of their contents with solid colour and - thus completely cover any components behind them should use this method - to tell the repaint system that they are opaque. - - This information is used to optimise drawing, because it means that - objects underneath opaque windows don't need to be painted. - - By default, components are considered transparent, unless this is used to - make it otherwise. - - @see isOpaque, getVisibleArea - */ - void setOpaque (const bool shouldBeOpaque) throw(); - - /** Returns true if no parts of this component are transparent. - - @returns the value that was set by setOpaque, (the default being false) - @see setOpaque - */ - bool isOpaque() const throw(); - - /** Indicates whether the component should be brought to the front when clicked. - - Setting this flag to true will cause the component to be brought to the front - when the mouse is clicked somewhere inside it or its child components. - - Note that a top-level desktop window might still be brought to the front by the - operating system when it's clicked, depending on how the OS works. - - By default this is set to false. - - @see setMouseClickGrabsKeyboardFocus - */ - void setBroughtToFrontOnMouseClick (const bool shouldBeBroughtToFront) throw(); - - /** Indicates whether the component should be brought to the front when clicked-on. - - @see setBroughtToFrontOnMouseClick - */ - bool isBroughtToFrontOnMouseClick() const throw(); - - // Keyboard focus methods - - /** Sets a flag to indicate whether this component needs keyboard focus or not. - - By default components aren't actually interested in gaining the - focus, but this method can be used to turn this on. - - See the grabKeyboardFocus() method for details about the way a component - is chosen to receive the focus. - - @see grabKeyboardFocus, getWantsKeyboardFocus - */ - void setWantsKeyboardFocus (const bool wantsFocus) throw(); - - /** Returns true if the component is interested in getting keyboard focus. - - This returns the flag set by setWantsKeyboardFocus(). The default - setting is false. - - @see setWantsKeyboardFocus - */ - bool getWantsKeyboardFocus() const throw(); - - /** Chooses whether a click on this component automatically grabs the focus. - - By default this is set to true, but you might want a component which can - be focused, but where you don't want the user to be able to affect it directly - by clicking. - */ - void setMouseClickGrabsKeyboardFocus (const bool shouldGrabFocus); - - /** Returns the last value set with setMouseClickGrabsKeyboardFocus(). - - See setMouseClickGrabsKeyboardFocus() for more info. - */ - bool getMouseClickGrabsKeyboardFocus() const throw(); - - /** Tries to give keyboard focus to this component. - - When the user clicks on a component or its grabKeyboardFocus() - method is called, the following procedure is used to work out which - component should get it: - - - if the component that was clicked on actually wants focus (as indicated - by calling getWantsKeyboardFocus), it gets it. - - if the component itself doesn't want focus, it will try to pass it - on to whichever of its children is the default component, as determined by - KeyboardFocusTraverser::getDefaultComponent() - - if none of its children want focus at all, it will pass it up to its - parent instead, unless it's a top-level component without a parent, - in which case it just takes the focus itself. - - @see setWantsKeyboardFocus, getWantsKeyboardFocus, hasKeyboardFocus, - getCurrentlyFocusedComponent, focusGained, focusLost, - keyPressed, keyStateChanged - */ - void grabKeyboardFocus(); - - /** Returns true if this component currently has the keyboard focus. - - @param trueIfChildIsFocused if this is true, then the method returns true if - either this component or any of its children (recursively) - have the focus. If false, the method only returns true if - this component has the focus. - - @see grabKeyboardFocus, setWantsKeyboardFocus, getCurrentlyFocusedComponent, - focusGained, focusLost - */ - bool hasKeyboardFocus (const bool trueIfChildIsFocused) const throw(); - - /** Returns the component that currently has the keyboard focus. - - @returns the focused component, or null if nothing is focused. - */ - static Component* JUCE_CALLTYPE getCurrentlyFocusedComponent() throw(); - - /** Tries to move the keyboard focus to one of this component's siblings. - - This will try to move focus to either the next or previous component. (This - is the method that is used when shifting focus by pressing the tab key). - - Components for which getWantsKeyboardFocus() returns false are not looked at. - - @param moveToNext if true, the focus will move forwards; if false, it will - move backwards - @see grabKeyboardFocus, setFocusContainer, setWantsKeyboardFocus - */ - void moveKeyboardFocusToSibling (const bool moveToNext); - - /** Creates a KeyboardFocusTraverser object to use to determine the logic by - which focus should be passed from this component. - - The default implementation of this method will return a default - KeyboardFocusTraverser if this component is a focus container (as determined - by the setFocusContainer() method). If the component isn't a focus - container, then it will recursively ask its parents for a KeyboardFocusTraverser. - - If you overrride this to return a custom KeyboardFocusTraverser, then - this component and all its sub-components will use the new object to - make their focusing decisions. - - The method should return a new object, which the caller is required to - delete when no longer needed. - */ - virtual KeyboardFocusTraverser* createFocusTraverser(); - - /** Returns the focus order of this component, if one has been specified. - - By default components don't have a focus order - in that case, this - will return 0. Lower numbers indicate that the component will be - earlier in the focus traversal order. - - To change the order, call setExplicitFocusOrder(). - - The focus order may be used by the KeyboardFocusTraverser class as part of - its algorithm for deciding the order in which components should be traversed. - See the KeyboardFocusTraverser class for more details on this. - - @see moveKeyboardFocusToSibling, createFocusTraverser, KeyboardFocusTraverser - */ - int getExplicitFocusOrder() const throw(); - - /** Sets the index used in determining the order in which focusable components - should be traversed. - - A value of 0 or less is taken to mean that no explicit order is wanted, and - that traversal should use other factors, like the component's position. - - @see getExplicitFocusOrder, moveKeyboardFocusToSibling - */ - void setExplicitFocusOrder (const int newFocusOrderIndex) throw(); - - /** Indicates whether this component is a parent for components that can have - their focus traversed. - - This flag is used by the default implementation of the createFocusTraverser() - method, which uses the flag to find the first parent component (of the currently - focused one) which wants to be a focus container. - - So using this method to set the flag to 'true' causes this component to - act as the top level within which focus is passed around. - - @see isFocusContainer, createFocusTraverser, moveKeyboardFocusToSibling - */ - void setFocusContainer (const bool shouldBeFocusContainer) throw(); - - /** Returns true if this component has been marked as a focus container. - - See setFocusContainer() for more details. - - @see setFocusContainer, moveKeyboardFocusToSibling, createFocusTraverser - */ - bool isFocusContainer() const throw(); - - /** Returns true if the component (and all its parents) are enabled. - - Components are enabled by default, and can be disabled with setEnabled(). Exactly - what difference this makes to the component depends on the type. E.g. buttons - and sliders will choose to draw themselves differently, etc. - - Note that if one of this component's parents is disabled, this will always - return false, even if this component itself is enabled. - - @see setEnabled, enablementChanged - */ - bool isEnabled() const throw(); - - /** Enables or disables this component. - - Disabling a component will also cause all of its child components to become - disabled. - - Similarly, enabling a component which is inside a disabled parent - component won't make any difference until the parent is re-enabled. - - @see isEnabled, enablementChanged - */ - void setEnabled (const bool shouldBeEnabled); - - /** Callback to indicate that this component has been enabled or disabled. - - This can be triggered by one of the component's parent components - being enabled or disabled, as well as changes to the component itself. - - The default implementation of this method does nothing; your class may - wish to repaint itself or something when this happens. - - @see setEnabled, isEnabled - */ - virtual void enablementChanged(); - - /** Changes the mouse cursor shape to use when the mouse is over this component. - - Note that the cursor set by this method can be overridden by the getMouseCursor - method. - - @see MouseCursor - */ - void setMouseCursor (const MouseCursor& cursorType) throw(); - - /** Returns the mouse cursor shape to use when the mouse is over this component. - - The default implementation will return the cursor that was set by setCursor() - but can be overridden for more specialised purposes, e.g. returning different - cursors depending on the mouse position. - - @see MouseCursor - */ - virtual const MouseCursor getMouseCursor(); - - /** Forces the current mouse cursor to be updated. - - If you're overriding the getMouseCursor() method to control which cursor is - displayed, then this will only be checked each time the user moves the mouse. So - if you want to force the system to check that the cursor being displayed is - up-to-date (even if the mouse is just sitting there), call this method. - - This isn't needed if you're only using setMouseCursor(). - */ - void updateMouseCursor() const throw(); - - /** Components can override this method to draw their content. - - The paint() method gets called when a region of a component needs redrawing, - either because the component's repaint() method has been called, or because - something has happened on the screen that means a section of a window needs - to be redrawn. - - Any child components will draw themselves over whatever this method draws. If - you need to paint over the top of your child components, you can also implement - the paintOverChildren() method to do this. - - If you want to cause a component to redraw itself, this is done asynchronously - - calling the repaint() method marks a region of the component as "dirty", and the - paint() method will automatically be called sometime later, by the message thread, - to paint any bits that need refreshing. In Juce (and almost all modern UI frameworks), - you never redraw something synchronously. - - You should never need to call this method directly - to take a snapshot of the - component you could use createComponentSnapshot() or paintEntireComponent(). - - @param g the graphics context that must be used to do the drawing operations. - @see repaint, paintOverChildren, Graphics - */ - virtual void paint (Graphics& g); - - /** Components can override this method to draw over the top of their children. - - For most drawing operations, it's better to use the normal paint() method, - but if you need to overlay something on top of the children, this can be - used. - - @see paint, Graphics - */ - virtual void paintOverChildren (Graphics& g); - - /** Called when the mouse moves inside this component. - - If the mouse button isn't pressed and the mouse moves over a component, - this will be called to let the component react to this. - - A component will always get a mouseEnter callback before a mouseMove. - - @param e details about the position and status of the mouse event - @see mouseEnter, mouseExit, mouseDrag, contains - */ - virtual void mouseMove (const MouseEvent& e); - - /** Called when the mouse first enters this component. - - If the mouse button isn't pressed and the mouse moves into a component, - this will be called to let the component react to this. - - When the mouse button is pressed and held down while being moved in - or out of a component, no mouseEnter or mouseExit callbacks are made - only - mouseDrag messages are sent to the component that the mouse was originally - clicked on, until the button is released. - - If you're writing a component that needs to repaint itself when the mouse - enters and exits, it might be quicker to use the setRepaintsOnMouseActivity() - method. - - @param e details about the position and status of the mouse event - @see mouseExit, mouseDrag, mouseMove, contains - */ - virtual void mouseEnter (const MouseEvent& e); - - /** Called when the mouse moves out of this component. - - This will be called when the mouse moves off the edge of this - component. - - If the mouse button was pressed, and it was then dragged off the - edge of the component and released, then this callback will happen - when the button is released, after the mouseUp callback. - - If you're writing a component that needs to repaint itself when the mouse - enters and exits, it might be quicker to use the setRepaintsOnMouseActivity() - method. - - @param e details about the position and status of the mouse event - @see mouseEnter, mouseDrag, mouseMove, contains - */ - virtual void mouseExit (const MouseEvent& e); - - /** Called when a mouse button is pressed while it's over this component. - - The MouseEvent object passed in contains lots of methods for finding out - which button was pressed, as well as which modifier keys (e.g. shift, ctrl) - were held down at the time. - - Once a button is held down, the mouseDrag method will be called when the - mouse moves, until the button is released. - - @param e details about the position and status of the mouse event - @see mouseUp, mouseDrag, mouseDoubleClick, contains - */ - virtual void mouseDown (const MouseEvent& e); - - /** Called when the mouse is moved while a button is held down. - - When a mouse button is pressed inside a component, that component - receives mouseDrag callbacks each time the mouse moves, even if the - mouse strays outside the component's bounds. - - If you want to be able to drag things off the edge of a component - and have the component scroll when you get to the edges, the - beginDragAutoRepeat() method might be useful. - - @param e details about the position and status of the mouse event - @see mouseDown, mouseUp, mouseMove, contains, beginDragAutoRepeat - */ - virtual void mouseDrag (const MouseEvent& e); - - /** Called when a mouse button is released. - - A mouseUp callback is sent to the component in which a button was pressed - even if the mouse is actually over a different component when the - button is released. - - The MouseEvent object passed in contains lots of methods for finding out - which buttons were down just before they were released. - - @param e details about the position and status of the mouse event - @see mouseDown, mouseDrag, mouseDoubleClick, contains - */ - virtual void mouseUp (const MouseEvent& e); - - /** Called when a mouse button has been double-clicked in this component. - - The MouseEvent object passed in contains lots of methods for finding out - which button was pressed, as well as which modifier keys (e.g. shift, ctrl) - were held down at the time. - - For altering the time limit used to detect double-clicks, - see MouseEvent::setDoubleClickTimeout. - - @param e details about the position and status of the mouse event - @see mouseDown, mouseUp, MouseEvent::setDoubleClickTimeout, - MouseEvent::getDoubleClickTimeout - */ - virtual void mouseDoubleClick (const MouseEvent& e); - - /** Called when the mouse-wheel is moved. - - This callback is sent to the component that the mouse is over when the - wheel is moved. - - If not overridden, the component will forward this message to its parent, so - that parent components can collect mouse-wheel messages that happen to - child components which aren't interested in them. - - @param e details about the position and status of the mouse event - @param wheelIncrementX the speed and direction of the horizontal scroll-wheel - a positive - value means the wheel has been pushed to the right, negative means it - was pushed to the left - @param wheelIncrementY the speed and direction of the vertical scroll-wheel - a positive - value means the wheel has been pushed upwards, negative means it - was pushed downwards - */ - virtual void mouseWheelMove (const MouseEvent& e, - float wheelIncrementX, - float wheelIncrementY); - - /** Ensures that a non-stop stream of mouse-drag events will be sent during the - next mouse-drag operation. - - This allows you to make sure that mouseDrag() events sent continuously, even - when the mouse isn't moving. This can be useful for things like auto-scrolling - components when the mouse is near an edge. - - Call this method during a mouseDown() or mouseDrag() callback, specifying the - minimum interval between consecutive mouse drag callbacks. The callbacks - will continue until the mouse is released, and then the interval will be reset, - so you need to make sure it's called every time you begin a drag event. If it - is called when the mouse isn't actually being pressed, it will apply to the next - mouse-drag operation that happens. - - Passing an interval of 0 or less will cancel the auto-repeat. - - @see mouseDrag - */ - static void beginDragAutoRepeat (const int millisecondIntervalBetweenCallbacks); - - /** Causes automatic repaints when the mouse enters or exits this component. - - If turned on, then when the mouse enters/exits, or when the button is pressed/released - on the component, it will trigger a repaint. - - This is handy for things like buttons that need to draw themselves differently when - the mouse moves over them, and it avoids having to override all the different mouse - callbacks and call repaint(). - - @see mouseEnter, mouseExit, mouseDown, mouseUp - */ - void setRepaintsOnMouseActivity (const bool shouldRepaint) throw(); - - /** Registers a listener to be told when mouse events occur in this component. - - If you need to get informed about mouse events in a component but can't or - don't want to override its methods, you can attach any number of listeners - to the component, and these will get told about the events in addition to - the component's own callbacks being called. - - Note that a MouseListener can also be attached to more than one component. - - @param newListener the listener to register - @param wantsEventsForAllNestedChildComponents if true, the listener will receive callbacks - for events that happen to any child component - within this component, including deeply-nested - child components. If false, it will only be - told about events that this component handles. - @see MouseListener, removeMouseListener - */ - void addMouseListener (MouseListener* const newListener, - const bool wantsEventsForAllNestedChildComponents) throw(); - - /** Deregisters a mouse listener. - - @see addMouseListener, MouseListener - */ - void removeMouseListener (MouseListener* const listenerToRemove) throw(); - - /** Adds a listener that wants to hear about keypresses that this component receives. - - The listeners that are registered with a component are called by its keyPressed() or - keyStateChanged() methods (assuming these haven't been overridden to do something else). - - If you add an object as a key listener, be careful to remove it when the object - is deleted, or the component will be left with a dangling pointer. - - @see keyPressed, keyStateChanged, removeKeyListener - */ - void addKeyListener (KeyListener* const newListener) throw(); - - /** Removes a previously-registered key listener. - - @see addKeyListener - */ - void removeKeyListener (KeyListener* const listenerToRemove) throw(); - - /** Called when a key is pressed. - - When a key is pressed, the component that has the keyboard focus will have this - method called. Remember that a component will only be given the focus if its - setWantsKeyboardFocus() method has been used to enable this. - - If your implementation returns true, the event will be consumed and not passed - on to any other listeners. If it returns false, the key will be passed to any - KeyListeners that have been registered with this component. As soon as one of these - returns true, the process will stop, but if they all return false, the event will - be passed upwards to this component's parent, and so on. - - The default implementation of this method does nothing and returns false. - - @see keyStateChanged, getCurrentlyFocusedComponent, addKeyListener - */ - virtual bool keyPressed (const KeyPress& key); - - /** Called when a key is pressed or released. - - Whenever a key on the keyboard is pressed or released (including modifier keys - like shift and ctrl), this method will be called on the component that currently - has the keyboard focus. Remember that a component will only be given the focus if - its setWantsKeyboardFocus() method has been used to enable this. - - If your implementation returns true, the event will be consumed and not passed - on to any other listeners. If it returns false, then any KeyListeners that have - been registered with this component will have their keyStateChanged methods called. - As soon as one of these returns true, the process will stop, but if they all return - false, the event will be passed upwards to this component's parent, and so on. - - The default implementation of this method does nothing and returns false. - - To find out which keys are up or down at any time, see the KeyPress::isKeyCurrentlyDown() - method. - - @param isKeyDown true if a key has been pressed; false if it has been released - - @see keyPressed, KeyPress, getCurrentlyFocusedComponent, addKeyListener - */ - virtual bool keyStateChanged (const bool isKeyDown); - - /** Called when a modifier key is pressed or released. - - Whenever the shift, control, alt or command keys are pressed or released, - this method will be called on the component that currently has the keyboard focus. - Remember that a component will only be given the focus if its setWantsKeyboardFocus() - method has been used to enable this. - - The default implementation of this method actually calls its parent's modifierKeysChanged - method, so that focused components which aren't interested in this will give their - parents a chance to act on the event instead. - - @see keyStateChanged, ModifierKeys - */ - virtual void modifierKeysChanged (const ModifierKeys& modifiers); - - /** Enumeration used by the focusChanged() and focusLost() methods. */ - enum FocusChangeType - { - focusChangedByMouseClick, /**< Means that the user clicked the mouse to change focus. */ - focusChangedByTabKey, /**< Means that the user pressed the tab key to move the focus. */ - focusChangedDirectly /**< Means that the focus was changed by a call to grabKeyboardFocus(). */ - }; - - /** Called to indicate that this component has just acquired the keyboard focus. - - @see focusLost, setWantsKeyboardFocus, getCurrentlyFocusedComponent, hasKeyboardFocus - */ - virtual void focusGained (FocusChangeType cause); - - /** Called to indicate that this component has just lost the keyboard focus. - - @see focusGained, setWantsKeyboardFocus, getCurrentlyFocusedComponent, hasKeyboardFocus - */ - virtual void focusLost (FocusChangeType cause); - - /** Called to indicate that one of this component's children has been focused or unfocused. - - Essentially this means that the return value of a call to hasKeyboardFocus (true) has - changed. It happens when focus moves from one of this component's children (at any depth) - to a component that isn't contained in this one, (or vice-versa). - - @see focusGained, setWantsKeyboardFocus, getCurrentlyFocusedComponent, hasKeyboardFocus - */ - virtual void focusOfChildComponentChanged (FocusChangeType cause); - - /** Returns true if the mouse is currently over this component. - - If the mouse isn't over the component, this will return false, even if the - mouse is currently being dragged - so you can use this in your mouseDrag - method to find out whether it's really over the component or not. - - Note that when the mouse button is being held down, then the only component - for which this method will return true is the one that was originally - clicked on. - - @see isMouseButtonDown. isMouseOverOrDragging, mouseDrag - */ - bool isMouseOver() const throw(); - - /** Returns true if the mouse button is currently held down in this component. - - Note that this is a test to see whether the mouse is being pressed in this - component, so it'll return false if called on component A when the mouse - is actually being dragged in component B. - - @see isMouseButtonDownAnywhere, isMouseOver, isMouseOverOrDragging - */ - bool isMouseButtonDown() const throw(); - - /** True if the mouse is over this component, or if it's being dragged in this component. - - This is a handy equivalent to (isMouseOver() || isMouseButtonDown()). - - @see isMouseOver, isMouseButtonDown, isMouseButtonDownAnywhere - */ - bool isMouseOverOrDragging() const throw(); - - /** Returns true if a mouse button is currently down. - - Unlike isMouseButtonDown, this will test the current state of the - buttons without regard to which component (if any) it has been - pressed in. - - @see isMouseButtonDown, ModifierKeys - */ - static bool JUCE_CALLTYPE isMouseButtonDownAnywhere() throw(); - - /** Returns the mouse's current position, relative to this component. - - The co-ordinates are relative to the component's top-left corner. - */ - void getMouseXYRelative (int& x, int& y) const throw(); - - /** Returns the component that's currently underneath the mouse. - - @returns the component or 0 if there isn't one. - @see contains, getComponentAt - */ - static Component* JUCE_CALLTYPE getComponentUnderMouse() throw(); - - /** Allows the mouse to move beyond the edges of the screen. - - Calling this method when the mouse button is currently pressed inside this component - will remove the cursor from the screen and allow the mouse to (seem to) move beyond - the edges of the screen. - - This means that the co-ordinates returned to mouseDrag() will be unbounded, and this - can be used for things like custom slider controls or dragging objects around, where - movement would be otherwise be limited by the mouse hitting the edges of the screen. - - The unbounded mode is automatically turned off when the mouse button is released, or - it can be turned off explicitly by calling this method again. - - @param shouldUnboundedMovementBeEnabled whether to turn this mode on or off - @param keepCursorVisibleUntilOffscreen if set to false, the cursor will immediately be - hidden; if true, it will only be hidden when it - is moved beyond the edge of the screen - */ - void enableUnboundedMouseMovement (bool shouldUnboundedMovementBeEnabled, - bool keepCursorVisibleUntilOffscreen = false) throw(); - - /** Called when this component's size has been changed. - - A component can implement this method to do things such as laying out its - child components when its width or height changes. - - The method is called synchronously as a result of the setBounds or setSize - methods, so repeatedly changing a components size will repeatedly call its - resized method (unlike things like repainting, where multiple calls to repaint - are coalesced together). - - If the component is a top-level window on the desktop, its size could also - be changed by operating-system factors beyond the application's control. - - @see moved, setSize - */ - virtual void resized(); - - /** Called when this component's position has been changed. - - This is called when the position relative to its parent changes, not when - its absolute position on the screen changes (so it won't be called for - all child components when a parent component is moved). - - The method is called synchronously as a result of the setBounds, setTopLeftPosition - or any of the other repositioning methods, and like resized(), it will be - called each time those methods are called. - - If the component is a top-level window on the desktop, its position could also - be changed by operating-system factors beyond the application's control. - - @see resized, setBounds - */ - virtual void moved(); - - /** Called when one of this component's children is moved or resized. - - If the parent wants to know about changes to its immediate children (not - to children of its children), this is the method to override. - - @see moved, resized, parentSizeChanged - */ - virtual void childBoundsChanged (Component* child); - - /** Called when this component's immediate parent has been resized. - - If the component is a top-level window, this indicates that the screen size - has changed. - - @see childBoundsChanged, moved, resized - */ - virtual void parentSizeChanged(); - - /** Called when this component has been moved to the front of its siblings. - - The component may have been brought to the front by the toFront() method, or - by the operating system if it's a top-level window. - - @see toFront - */ - virtual void broughtToFront(); - - /** Adds a listener to be told about changes to the component hierarchy or position. - - Component listeners get called when this component's size, position or children - change - see the ComponentListener class for more details. - - @param newListener the listener to register - if this is already registered, it - will be ignored. - @see ComponentListener, removeComponentListener - */ - void addComponentListener (ComponentListener* const newListener) throw(); - - /** Removes a component listener. - - @see addComponentListener - */ - void removeComponentListener (ComponentListener* const listenerToRemove) throw(); - - /** Dispatches a numbered message to this component. - - This is a quick and cheap way of allowing simple asynchronous messages to - be sent to components. It's also safe, because if the component that you - send the message to is a null or dangling pointer, this won't cause an error. - - The command ID is later delivered to the component's handleCommandMessage() method by - the application's message queue. - - @see handleCommandMessage - */ - void postCommandMessage (const int commandId) throw(); - - /** Called to handle a command that was sent by postCommandMessage(). - - This is called by the message thread when a command message arrives, and - the component can override this method to process it in any way it needs to. - - @see postCommandMessage - */ - virtual void handleCommandMessage (int commandId); - - /** Runs a component modally, waiting until the loop terminates. - - This method first makes the component visible, brings it to the front and - gives it the keyboard focus. - - It then runs a loop, dispatching messages from the system message queue, but - blocking all mouse or keyboard messages from reaching any components other - than this one and its children. - - This loop continues until the component's exitModalState() method is called (or - the component is deleted), and then this method returns, returning the value - passed into exitModalState(). - - @see enterModalState, exitModalState, isCurrentlyModal, getCurrentlyModalComponent, - isCurrentlyBlockedByAnotherModalComponent, MessageManager::dispatchNextMessage - */ - int runModalLoop(); - - /** Puts the component into a modal state. - - This makes the component modal, so that messages are blocked from reaching - any components other than this one and its children, but unlike runModalLoop(), - this method returns immediately. - - If takeKeyboardFocus is true, the component will use grabKeyboardFocus() to - get the focus, which is usually what you'll want it to do. If not, it will leave - the focus unchanged. - - @see exitModalState, runModalLoop - */ - void enterModalState (const bool takeKeyboardFocus = true); - - /** Ends a component's modal state. - - If this component is currently modal, this will turn of its modalness, and return - a value to the runModalLoop() method that might have be running its modal loop. - - @see runModalLoop, enterModalState, isCurrentlyModal - */ - void exitModalState (const int returnValue); - - /** Returns true if this component is the modal one. - - It's possible to have nested modal components, e.g. a pop-up dialog box - that launches another pop-up, but this will only return true for - the one at the top of the stack. - - @see getCurrentlyModalComponent - */ - bool isCurrentlyModal() const throw(); - - /** Returns the number of components that are currently in a modal state. - @see getCurrentlyModalComponent - */ - static int JUCE_CALLTYPE getNumCurrentlyModalComponents() throw(); - - /** Returns one of the components that are currently modal. - - The index specifies which of the possible modal components to return. The order - of the components in this list is the reverse of the order in which they became - modal - so the component at index 0 is always the active component, and the others - are progressively earlier ones that are themselves now blocked by later ones. - - @returns the modal component, or null if no components are modal (or if the - index is out of range) - @see getNumCurrentlyModalComponents, runModalLoop, isCurrentlyModal - */ - static Component* JUCE_CALLTYPE getCurrentlyModalComponent (int index = 0) throw(); - - /** Checks whether there's a modal component somewhere that's stopping this one - from receiving messages. - - If there is a modal component, its canModalEventBeSentToComponent() method - will be called to see if it will still allow this component to receive events. - - @see runModalLoop, getCurrentlyModalComponent - */ - bool isCurrentlyBlockedByAnotherModalComponent() const throw(); - - /** When a component is modal, this callback allows it to choose which other - components can still receive events. - - When a modal component is active and the user clicks on a non-modal component, - this method is called on the modal component, and if it returns true, the - event is allowed to reach its target. If it returns false, the event is blocked - and the inputAttemptWhenModal() callback is made. - - It called by the isCurrentlyBlockedByAnotherModalComponent() method. The default - implementation just returns false in all cases. - */ - virtual bool canModalEventBeSentToComponent (const Component* targetComponent); - - /** Called when the user tries to click on a component that is blocked by another - modal component. - - When a component is modal and the user clicks on one of the other components, - the modal component will receive this callback. - - The default implementation of this method will play a beep, and bring the currently - modal component to the front, but it can be overridden to do other tasks. - - @see isCurrentlyBlockedByAnotherModalComponent, canModalEventBeSentToComponent - */ - virtual void inputAttemptWhenModal(); - - /** Returns one of the component's properties as a string. - - @param keyName the name of the property to retrieve - @param useParentComponentIfNotFound if this is true and the key isn't present in this component's - properties, then it will check whether the parent component has - the key. - @param defaultReturnValue a value to return if the named property doesn't actually exist - */ - const String getComponentProperty (const String& keyName, - const bool useParentComponentIfNotFound, - const String& defaultReturnValue = String::empty) const throw(); - - /** Returns one of the properties as an integer. - - @param keyName the name of the property to retrieve - @param useParentComponentIfNotFound if this is true and the key isn't present in this component's - properties, then it will check whether the parent component has - the key. - @param defaultReturnValue a value to return if the named property doesn't actually exist - */ - int getComponentPropertyInt (const String& keyName, - const bool useParentComponentIfNotFound, - const int defaultReturnValue = 0) const throw(); - - /** Returns one of the properties as an double. - - @param keyName the name of the property to retrieve - @param useParentComponentIfNotFound if this is true and the key isn't present in this component's - properties, then it will check whether the parent component has - the key. - @param defaultReturnValue a value to return if the named property doesn't actually exist - */ - double getComponentPropertyDouble (const String& keyName, - const bool useParentComponentIfNotFound, - const double defaultReturnValue = 0.0) const throw(); - - /** Returns one of the properties as an boolean. - - The result will be true if the string found for this key name can be parsed as a non-zero - integer. - - @param keyName the name of the property to retrieve - @param useParentComponentIfNotFound if this is true and the key isn't present in this component's - properties, then it will check whether the parent component has - the key. - @param defaultReturnValue a value to return if the named property doesn't actually exist - */ - bool getComponentPropertyBool (const String& keyName, - const bool useParentComponentIfNotFound, - const bool defaultReturnValue = false) const throw(); - - /** Returns one of the properties as an colour. - - @param keyName the name of the property to retrieve - @param useParentComponentIfNotFound if this is true and the key isn't present in this component's - properties, then it will check whether the parent component has - the key. - @param defaultReturnValue a colour to return if the named property doesn't actually exist - */ - const Colour getComponentPropertyColour (const String& keyName, - const bool useParentComponentIfNotFound, - const Colour& defaultReturnValue = Colours::black) const throw(); - - /** Sets a named property as a string. - - @param keyName the name of the property to set. (This mustn't be an empty string) - @param value the new value to set it to - @see removeComponentProperty - */ - void setComponentProperty (const String& keyName, const String& value) throw(); - - /** Sets a named property to an integer. - - @param keyName the name of the property to set. (This mustn't be an empty string) - @param value the new value to set it to - @see removeComponentProperty - */ - void setComponentProperty (const String& keyName, const int value) throw(); - - /** Sets a named property to a double. - - @param keyName the name of the property to set. (This mustn't be an empty string) - @param value the new value to set it to - @see removeComponentProperty - */ - void setComponentProperty (const String& keyName, const double value) throw(); - - /** Sets a named property to a boolean. - - @param keyName the name of the property to set. (This mustn't be an empty string) - @param value the new value to set it to - @see removeComponentProperty - */ - void setComponentProperty (const String& keyName, const bool value) throw(); - - /** Sets a named property to a colour. - - @param keyName the name of the property to set. (This mustn't be an empty string) - @param newColour the new colour to set it to - @see removeComponentProperty - */ - void setComponentProperty (const String& keyName, const Colour& newColour) throw(); - - /** Deletes a named component property. - - @param keyName the name of the property to delete. (This mustn't be an empty string) - @see setComponentProperty, getComponentProperty - */ - void removeComponentProperty (const String& keyName) throw(); - - /** Returns the complete set of properties that have been set for this component. - - If no properties have been set, this will return a null pointer. - - @see getComponentProperty, setComponentProperty - */ - PropertySet* getComponentProperties() const throw() { return propertySet_; } - - /** Looks for a colour that has been registered with the given colour ID number. - - If a colour has been set for this ID number using setColour(), then it is - returned. If none has been set, the method will try calling the component's - LookAndFeel class's findColour() method. If none has been registered with the - look-and-feel either, it will just return black. - - The colour IDs for various purposes are stored as enums in the components that - they are relevent to - for an example, see Slider::ColourIds, - Label::ColourIds, TextEditor::ColourIds, TreeView::ColourIds, etc. - - @see setColour, isColourSpecified, colourChanged, LookAndFeel::findColour, LookAndFeel::setColour - */ - const Colour findColour (const int colourId, const bool inheritFromParent = false) const throw(); - - /** Registers a colour to be used for a particular purpose. - - Changing a colour will cause a synchronous callback to the colourChanged() - method, which your component can override if it needs to do something when - colours are altered. - - For more details about colour IDs, see the comments for findColour(). - - @see findColour, isColourSpecified, colourChanged, LookAndFeel::findColour, LookAndFeel::setColour - */ - void setColour (const int colourId, const Colour& colour); - - /** If a colour has been set with setColour(), this will remove it. - - This allows you to make a colour revert to its default state. - */ - void removeColour (const int colourId); - - /** Returns true if the specified colour ID has been explicitly set for this - component using the setColour() method. - */ - bool isColourSpecified (const int colourId) const throw(); - - /** This looks for any colours that have been specified for this component, - and copies them to the specified target component. - */ - void copyAllExplicitColoursTo (Component& target) const throw(); - - /** This method is called when a colour is changed by the setColour() method. - - @see setColour, findColour - */ - virtual void colourChanged(); - - /** Returns the underlying native window handle for this component. - - This is platform-dependent and strictly for power-users only! - */ - void* getWindowHandle() const throw(); - - /** When created, each component is given a number to uniquely identify it. - - The number is incremented each time a new component is created, so it's a more - unique way of identifying a component than using its memory location (which - may be reused after the component is deleted, of course). - */ - uint32 getComponentUID() const throw() { return componentUID; } - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class ComponentPeer; - friend class InternalDragRepeater; + friend class ComponentPeer; + friend class InternalDragRepeater; - static Component* currentlyFocusedComponent; - static Component* componentUnderMouse; + static Component* currentlyFocusedComponent; + static Component* componentUnderMouse; - String componentName_; - Component* parentComponent_; - uint32 componentUID; - Rectangle bounds_; - unsigned short numDeepMouseListeners; - Array childComponentList_; - LookAndFeel* lookAndFeel_; - MouseCursor cursor_; - ImageEffectFilter* effect_; - Image* bufferedImage_; - VoidArray* mouseListeners_; - VoidArray* keyListeners_; - VoidArray* componentListeners_; - PropertySet* propertySet_; + String componentName_; + Component* parentComponent_; + uint32 componentUID; + Rectangle bounds_; + int numDeepMouseListeners; + Array childComponentList_; + LookAndFeel* lookAndFeel_; + MouseCursor cursor_; + ImageEffectFilter* effect_; + Image* bufferedImage_; + VoidArray* mouseListeners_; + VoidArray* keyListeners_; + VoidArray* componentListeners_; + PropertySet* propertySet_; - struct ComponentFlags - { - bool hasHeavyweightPeerFlag : 1; - bool visibleFlag : 1; - bool opaqueFlag : 1; - bool ignoresMouseClicksFlag : 1; - bool allowChildMouseClicksFlag : 1; - bool wantsFocusFlag : 1; - bool isFocusContainerFlag : 1; - bool dontFocusOnMouseClickFlag : 1; - bool alwaysOnTopFlag : 1; - bool bufferToImageFlag : 1; - bool bringToFrontOnClickFlag : 1; - bool repaintOnMouseActivityFlag : 1; - bool draggingFlag : 1; - bool mouseOverFlag : 1; - bool mouseInsideFlag : 1; - bool currentlyModalFlag : 1; - bool isDisabledFlag : 1; - bool childCompFocusedFlag : 1; + struct ComponentFlags + { + bool hasHeavyweightPeerFlag : 1; + bool visibleFlag : 1; + bool opaqueFlag : 1; + bool ignoresMouseClicksFlag : 1; + bool allowChildMouseClicksFlag : 1; + bool wantsFocusFlag : 1; + bool isFocusContainerFlag : 1; + bool dontFocusOnMouseClickFlag : 1; + bool alwaysOnTopFlag : 1; + bool bufferToImageFlag : 1; + bool bringToFrontOnClickFlag : 1; + bool repaintOnMouseActivityFlag : 1; + bool draggingFlag : 1; + bool mouseOverFlag : 1; + bool mouseInsideFlag : 1; + bool currentlyModalFlag : 1; + bool isDisabledFlag : 1; + bool childCompFocusedFlag : 1; #ifdef JUCE_DEBUG - bool isInsidePaintCall : 1; + bool isInsidePaintCall : 1; #endif - }; + }; - union - { - uint32 componentFlags_; - ComponentFlags flags; - }; + union + { + uint32 componentFlags_; + ComponentFlags flags; + }; - void internalMouseEnter (int x, int y, const int64 time); - void internalMouseExit (int x, int y, const int64 time); - void internalMouseDown (int x, int y); - void internalMouseUp (const int oldModifiers, int x, int y, const int64 time); - void internalMouseDrag (int x, int y, const int64 time); - void internalMouseMove (int x, int y, const int64 time); - void internalMouseWheel (const int intAmountX, const int intAmountY, const int64 time); - void internalBroughtToFront(); - void internalFocusGain (const FocusChangeType cause); - void internalFocusLoss (const FocusChangeType cause); - void internalChildFocusChange (FocusChangeType cause); - void internalModalInputAttempt(); - void internalModifierKeysChanged(); - void internalChildrenChanged(); - void internalHierarchyChanged(); - void internalUpdateMouseCursor (const bool forcedUpdate) throw(); - void sendMovedResizedMessages (const bool wasMoved, const bool wasResized); - void repaintParent() throw(); - void sendFakeMouseMove() const; - void takeKeyboardFocus (const FocusChangeType cause); - void grabFocusInternal (const FocusChangeType cause, const bool canTryParent = true); - static void giveAwayFocus(); - void sendEnablementChangeMessage(); - static void* runModalLoopCallback (void*); - static void bringModalComponentToFront(); - void subtractObscuredRegions (RectangleList& result, - const int deltaX, const int deltaY, - const Rectangle& clipRect, - const Component* const compToAvoid) const throw(); - void clipObscuredRegions (Graphics& g, const Rectangle& clipRect, - const int deltaX, const int deltaY) const throw(); + void internalMouseEnter (int x, int y, const int64 time); + void internalMouseExit (int x, int y, const int64 time); + void internalMouseDown (int x, int y); + void internalMouseUp (const int oldModifiers, int x, int y, const int64 time); + void internalMouseDrag (int x, int y, const int64 time); + void internalMouseMove (int x, int y, const int64 time); + void internalMouseWheel (const int intAmountX, const int intAmountY, const int64 time); + void internalBroughtToFront(); + void internalFocusGain (const FocusChangeType cause); + void internalFocusLoss (const FocusChangeType cause); + void internalChildFocusChange (FocusChangeType cause); + void internalModalInputAttempt(); + void internalModifierKeysChanged(); + void internalChildrenChanged(); + void internalHierarchyChanged(); + void internalUpdateMouseCursor (const bool forcedUpdate) throw(); + void sendMovedResizedMessages (const bool wasMoved, const bool wasResized); + void repaintParent() throw(); + void sendFakeMouseMove() const; + void takeKeyboardFocus (const FocusChangeType cause); + void grabFocusInternal (const FocusChangeType cause, const bool canTryParent = true); + static void giveAwayFocus(); + void sendEnablementChangeMessage(); + static void* runModalLoopCallback (void*); + static void bringModalComponentToFront(); + void subtractObscuredRegions (RectangleList& result, + const int deltaX, const int deltaY, + const Rectangle& clipRect, + const Component* const compToAvoid) const throw(); + void clipObscuredRegions (Graphics& g, const Rectangle& clipRect, + const int deltaX, const int deltaY) const throw(); - // how much of the component is not off the edges of its parents - const Rectangle getUnclippedArea() const; - void sendVisibilityChangeMessage(); + // how much of the component is not off the edges of its parents + const Rectangle getUnclippedArea() const; + void sendVisibilityChangeMessage(); - // This is included here just to cause a compile error if your code is still handling - // drag-and-drop with this method. If so, just update it to use the new FileDragAndDropTarget - // class, which is easy (just make your class inherit from FileDragAndDropTarget, and - // implement its methods instead of this Component method). - virtual void filesDropped (const StringArray&, int, int) {} + // This is included here just to cause a compile error if your code is still handling + // drag-and-drop with this method. If so, just update it to use the new FileDragAndDropTarget + // class, which is easy (just make your class inherit from FileDragAndDropTarget, and + // implement its methods instead of this Component method). + virtual void filesDropped (const StringArray&, int, int) {} - // components aren't allowed to have copy constructors, as this would mess up parent - // hierarchies. You might need to give your subclasses a private dummy constructor like - // this one to avoid compiler warnings. - Component (const Component&); + // components aren't allowed to have copy constructors, as this would mess up parent + // hierarchies. You might need to give your subclasses a private dummy constructor like + // this one to avoid compiler warnings. + Component (const Component&); - const Component& operator= (const Component&); + const Component& operator= (const Component&); - // (dummy method to cause a deliberate compile error - if you hit this, you need to update your - // subclass to use the new parameters to keyStateChanged) - virtual void keyStateChanged() {}; + // (dummy method to cause a deliberate compile error - if you hit this, you need to update your + // subclass to use the new parameters to keyStateChanged) + virtual void keyStateChanged() {}; protected: - /** @internal */ - virtual void internalRepaint (int x, int y, int w, int h); + virtual void internalRepaint (int x, int y, int w, int h); - virtual ComponentPeer* createNewPeer (int styleFlags, void* nativeWindowToAttachTo); + virtual ComponentPeer* createNewPeer (int styleFlags, void* nativeWindowToAttachTo); - /** Overridden from the MessageListener parent class. - - You can override this if you really need to, but be sure to pass your unwanted messages up - to this base class implementation, as the Component class needs to send itself messages - to work properly. - */ - void handleMessage (const Message&); + void handleMessage (const Message&); }; #endif // __JUCE_COMPONENT_JUCEHEADER__ @@ -25247,437 +12328,159 @@ protected: #ifndef __JUCE_APPLICATIONCOMMANDID_JUCEHEADER__ #define __JUCE_APPLICATIONCOMMANDID_JUCEHEADER__ -/** A type used to hold the unique ID for an application command. - - This is a numeric type, so it can be stored as an integer. - - @see ApplicationCommandInfo, ApplicationCommandManager, - ApplicationCommandTarget, KeyPressMappingSet -*/ typedef int CommandID; -/** A set of general-purpose application command IDs. - - Because these commands are likely to be used in most apps, they're defined - here to help different apps to use the same numeric values for them. - - Of course you don't have to use these, but some of them are used internally by - Juce - e.g. the quit ID is recognised as a command by the JUCEApplication class. - - @see ApplicationCommandInfo, ApplicationCommandManager, - ApplicationCommandTarget, KeyPressMappingSet -*/ namespace StandardApplicationCommandIDs { - /** This command ID should be used to send a "Quit the App" command. + static const CommandID quit = 0x1001; - This command is recognised by the JUCEApplication class, so if it is invoked - and no other ApplicationCommandTarget handles the event first, the JUCEApplication - object will catch it and call JUCEApplication::systemRequestedQuit(). - */ - static const CommandID quit = 0x1001; + static const CommandID del = 0x1002; - /** The command ID that should be used to send a "Delete" command. */ - static const CommandID del = 0x1002; + static const CommandID cut = 0x1003; - /** The command ID that should be used to send a "Cut" command. */ - static const CommandID cut = 0x1003; + static const CommandID copy = 0x1004; - /** The command ID that should be used to send a "Copy to clipboard" command. */ - static const CommandID copy = 0x1004; + static const CommandID paste = 0x1005; - /** The command ID that should be used to send a "Paste from clipboard" command. */ - static const CommandID paste = 0x1005; + static const CommandID selectAll = 0x1006; - /** The command ID that should be used to send a "Select all" command. */ - static const CommandID selectAll = 0x1006; - - /** The command ID that should be used to send a "Deselect all" command. */ - static const CommandID deselectAll = 0x1007; + static const CommandID deselectAll = 0x1007; } #endif // __JUCE_APPLICATIONCOMMANDID_JUCEHEADER__ /********* End of inlined file: juce_ApplicationCommandID.h *********/ -/** - Holds information describing an application command. - - This object is used to pass information about a particular command, such as its - name, description and other usage flags. - - When an ApplicationCommandTarget is asked to provide information about the commands - it can perform, this is the structure gets filled-in to describe each one. - - @see ApplicationCommandTarget, ApplicationCommandTarget::getCommandInfo(), - ApplicationCommandManager -*/ struct JUCE_API ApplicationCommandInfo { - ApplicationCommandInfo (const CommandID commandID) throw(); + ApplicationCommandInfo (const CommandID commandID) throw(); - /** Sets a number of the structures values at once. + void setInfo (const String& shortName, + const String& description, + const String& categoryName, + const int flags) throw(); - The meanings of each of the parameters is described below, in the appropriate - member variable's description. - */ - void setInfo (const String& shortName, - const String& description, - const String& categoryName, - const int flags) throw(); + void setActive (const bool isActive) throw(); - /** An easy way to set or remove the isDisabled bit in the structure's flags field. + void setTicked (const bool isTicked) throw(); - If isActive is true, the flags member has the isDisabled bit cleared; if isActive - is false, the bit is set. - */ - void setActive (const bool isActive) throw(); + void addDefaultKeypress (const int keyCode, + const ModifierKeys& modifiers) throw(); - /** An easy way to set or remove the isTicked bit in the structure's flags field. - */ - void setTicked (const bool isTicked) throw(); + CommandID commandID; - /** Handy method for adding a keypress to the defaultKeypresses array. + String shortName; - This is just so you can write things like: - @code - myinfo.addDefaultKeypress (T('s'), ModifierKeys::commandModifier); - @endcode - instead of - @code - myinfo.defaultKeypresses.add (KeyPress (T('s'), ModifierKeys::commandModifier)); - @endcode - */ - void addDefaultKeypress (const int keyCode, - const ModifierKeys& modifiers) throw(); + String description; - /** The command's unique ID number. - */ - CommandID commandID; + String categoryName; - /** A short name to describe the command. + Array defaultKeypresses; - This should be suitable for use in menus, on buttons that trigger the command, etc. + enum CommandFlags + { + isDisabled = 1 << 0, - You can use the setInfo() method to quickly set this and some of the command's - other properties. - */ - String shortName; + isTicked = 1 << 1, - /** A longer description of the command. + wantsKeyUpDownCallbacks = 1 << 2, - This should be suitable for use in contexts such as a KeyMappingEditorComponent or - pop-up tooltip describing what the command does. + hiddenFromKeyEditor = 1 << 3, - You can use the setInfo() method to quickly set this and some of the command's - other properties. - */ - String description; + readOnlyInKeyEditor = 1 << 4, - /** A named category that the command fits into. + dontTriggerVisualFeedback = 1 << 5 + }; - You can give your commands any category you like, and these will be displayed in - contexts such as the KeyMappingEditorComponent, where the category is used to group - commands together. - - You can use the setInfo() method to quickly set this and some of the command's - other properties. - */ - String categoryName; - - /** A list of zero or more keypresses that should be used as the default keys for - this command. - - Methods such as KeyPressMappingSet::resetToDefaultMappings() will use the keypresses in - this list to initialise the default set of key-to-command mappings. - - @see addDefaultKeypress - */ - Array defaultKeypresses; - - /** Flags describing the ways in which this command should be used. - - A bitwise-OR of these values is stored in the ApplicationCommandInfo::flags - variable. - */ - enum CommandFlags - { - /** Indicates that the command can't currently be performed. - - The ApplicationCommandTarget::getCommandInfo() method must set this flag if it's - not currently permissable to perform the command. If the flag is set, then - components that trigger the command, e.g. PopupMenu, may choose to grey-out the - command or show themselves as not being enabled. - - @see ApplicationCommandInfo::setActive - */ - isDisabled = 1 << 0, - - /** Indicates that the command should have a tick next to it on a menu. - - If your command is shown on a menu and this is set, it'll show a tick next to - it. Other components such as buttons may also use this flag to indicate that it - is a value that can be toggled, and is currently in the 'on' state. - - @see ApplicationCommandInfo::setTicked - */ - isTicked = 1 << 1, - - /** If this flag is present, then when a KeyPressMappingSet invokes the command, - it will call the command twice, once on key-down and again on key-up. - - @see ApplicationCommandTarget::InvocationInfo - */ - wantsKeyUpDownCallbacks = 1 << 2, - - /** If this flag is present, then a KeyMappingEditorComponent will not display the - command in its list. - */ - hiddenFromKeyEditor = 1 << 3, - - /** If this flag is present, then a KeyMappingEditorComponent will display the - command in its list, but won't allow the assigned keypress to be changed. - */ - readOnlyInKeyEditor = 1 << 4, - - /** If this flag is present and the command is invoked from a keypress, then any - buttons or menus that are also connected to the command will not flash to - indicate that they've been triggered. - */ - dontTriggerVisualFeedback = 1 << 5 - }; - - /** A bitwise-OR of the values specified in the CommandFlags enum. - - You can use the setInfo() method to quickly set this and some of the command's - other properties. - */ - int flags; + int flags; }; #endif // __JUCE_APPLICATIONCOMMANDINFO_JUCEHEADER__ /********* End of inlined file: juce_ApplicationCommandInfo.h *********/ -/** - A command target publishes a list of command IDs that it can perform. - - An ApplicationCommandManager despatches commands to targets, which must be - able to provide information about what commands they can handle. - - To create a target, you'll need to inherit from this class, implementing all of - its pure virtual methods. - - For info about how a target is chosen to receive a command, see - ApplicationCommandManager::getFirstCommandTarget(). - - @see ApplicationCommandManager, ApplicationCommandInfo -*/ class JUCE_API ApplicationCommandTarget { public: - /** Creates a command target. */ - ApplicationCommandTarget(); + ApplicationCommandTarget(); - /** Destructor. */ - virtual ~ApplicationCommandTarget(); + virtual ~ApplicationCommandTarget(); - /** - */ - struct JUCE_API InvocationInfo - { + struct JUCE_API InvocationInfo + { - InvocationInfo (const CommandID commandID) throw(); + InvocationInfo (const CommandID commandID) throw(); - /** The UID of the command that should be performed. */ - CommandID commandID; + CommandID commandID; - /** The command's flags. + int commandFlags; - See ApplicationCommandInfo for a description of these flag values. - */ - int commandFlags; + enum InvocationMethod + { + direct = 0, /**< The command is being invoked directly by a piece of code. */ + fromKeyPress, /**< The command is being invoked by a key-press. */ + fromMenu, /**< The command is being invoked by a menu selection. */ + fromButton /**< The command is being invoked by a button click. */ + }; - /** The types of context in which the command might be called. */ - enum InvocationMethod - { - direct = 0, /**< The command is being invoked directly by a piece of code. */ - fromKeyPress, /**< The command is being invoked by a key-press. */ - fromMenu, /**< The command is being invoked by a menu selection. */ - fromButton /**< The command is being invoked by a button click. */ - }; + InvocationMethod invocationMethod; - /** The type of event that triggered this command. */ - InvocationMethod invocationMethod; + Component* originatingComponent; - /** If triggered by a keypress or menu, this will be the component that had the - keyboard focus at the time. + KeyPress keyPress; - If triggered by a button, it may be set to that component, or it may be null. - */ - Component* originatingComponent; + bool isKeyDown; - /** The keypress that was used to invoke it. + int millisecsSinceKeyPressed; + }; - Note that this will be an invalid keypress if the command was invoked - by some other means than a keyboard shortcut. - */ - KeyPress keyPress; + virtual ApplicationCommandTarget* getNextCommandTarget() = 0; - /** True if the callback is being invoked when the key is pressed, - false if the key is being released. + virtual void getAllCommands (Array & commands) = 0; - @see KeyPressMappingSet::addCommand() - */ - bool isKeyDown; + virtual void getCommandInfo (const CommandID commandID, + ApplicationCommandInfo& result) = 0; - /** If the key is being released, this indicates how long it had been held - down for. + virtual bool perform (const InvocationInfo& info) = 0; - (Only relevant if isKeyDown is false.) - */ - int millisecsSinceKeyPressed; - }; + bool invoke (const InvocationInfo& invocationInfo, + const bool asynchronously); - /** This must return the next target to try after this one. + bool invokeDirectly (const CommandID commandID, + const bool asynchronously); - When a command is being sent, and the first target can't handle - that command, this method is used to determine the next target that should - be tried. + ApplicationCommandTarget* getTargetForCommand (const CommandID commandID); - It may return 0 if it doesn't know of another target. + bool isCommandActive (const CommandID commandID); - If your target is a Component, you would usually use the findFirstTargetParentComponent() - method to return a parent component that might want to handle it. + ApplicationCommandTarget* findFirstTargetParentComponent(); - @see invoke - */ - virtual ApplicationCommandTarget* getNextCommandTarget() = 0; - - /** This must return a complete list of commands that this target can handle. - - Your target should add all the command IDs that it handles to the array that is - passed-in. - */ - virtual void getAllCommands (Array & commands) = 0; - - /** This must provide details about one of the commands that this target can perform. - - This will be called with one of the command IDs that the target provided in its - getAllCommands() methods. - - It should fill-in all appropriate fields of the ApplicationCommandInfo structure with - suitable information about the command. (The commandID field will already have been filled-in - by the caller). - - The easiest way to set the info is using the ApplicationCommandInfo::setInfo() method to - set all the fields at once. - - If the command is currently inactive for some reason, this method must use - ApplicationCommandInfo::setActive() to make that clear, (or it should set the isDisabled - bit of the ApplicationCommandInfo::flags field). - - Any default key-presses for the command should be appended to the - ApplicationCommandInfo::defaultKeypresses field. - - Note that if you change something that affects the status of the commands - that would be returned by this method (e.g. something that makes some commands - active or inactive), you should call ApplicationCommandManager::commandStatusChanged() - to cause the manager to refresh its status. - */ - virtual void getCommandInfo (const CommandID commandID, - ApplicationCommandInfo& result) = 0; - - /** This must actually perform the specified command. - - If this target is able to perform the command specified by the commandID field of the - InvocationInfo structure, then it should do so, and must return true. - - If it can't handle this command, it should return false, which tells the caller to pass - the command on to the next target in line. - - @see invoke, ApplicationCommandManager::invoke - */ - virtual bool perform (const InvocationInfo& info) = 0; - - /** Makes this target invoke a command. - - Your code can call this method to invoke a command on this target, but normally - you'd call it indirectly via ApplicationCommandManager::invoke() or - ApplicationCommandManager::invokeDirectly(). - - If this target can perform the given command, it will call its perform() method to - do so. If not, then getNextCommandTarget() will be used to determine the next target - to try, and the command will be passed along to it. - - @param invocationInfo this must be correctly filled-in, describing the context for - the invocation. - @param asynchronously if false, the command will be performed before this method returns. - If true, a message will be posted so that the command will be performed - later on the message thread, and this method will return immediately. - @see perform, ApplicationCommandManager::invoke - */ - bool invoke (const InvocationInfo& invocationInfo, - const bool asynchronously); - - /** Invokes a given command directly on this target. - - This is just an easy way to call invoke() without having to fill out the InvocationInfo - structure. - */ - bool invokeDirectly (const CommandID commandID, - const bool asynchronously); - - /** Searches this target and all subsequent ones for the first one that can handle - the specified command. - - This will use getNextCommandTarget() to determine the chain of targets to try - after this one. - */ - ApplicationCommandTarget* getTargetForCommand (const CommandID commandID); - - /** Checks whether this command can currently be performed by this target. - - This will return true only if a call to getCommandInfo() doesn't set the - isDisabled flag to indicate that the command is inactive. - */ - bool isCommandActive (const CommandID commandID); - - /** If this object is a Component, this method will seach upwards in its current - UI hierarchy for the next parent component that implements the - ApplicationCommandTarget class. - - If your target is a Component, this is a very handy method to use in your - getNextCommandTarget() implementation. - */ - ApplicationCommandTarget* findFirstTargetParentComponent(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - // (for async invocation of commands) - class CommandTargetMessageInvoker : public MessageListener - { - public: - CommandTargetMessageInvoker (ApplicationCommandTarget* const owner); - ~CommandTargetMessageInvoker(); + // (for async invocation of commands) + class CommandTargetMessageInvoker : public MessageListener + { + public: + CommandTargetMessageInvoker (ApplicationCommandTarget* const owner); + ~CommandTargetMessageInvoker(); - void handleMessage (const Message& message); + void handleMessage (const Message& message); - private: - ApplicationCommandTarget* const owner; + private: + ApplicationCommandTarget* const owner; - CommandTargetMessageInvoker (const CommandTargetMessageInvoker&); - const CommandTargetMessageInvoker& operator= (const CommandTargetMessageInvoker&); - }; + CommandTargetMessageInvoker (const CommandTargetMessageInvoker&); + const CommandTargetMessageInvoker& operator= (const CommandTargetMessageInvoker&); + }; - ScopedPointer messageInvoker; + ScopedPointer messageInvoker; - friend class CommandTargetMessageInvoker; - bool tryToInvoke (const InvocationInfo& info, const bool async); + friend class CommandTargetMessageInvoker; + bool tryToInvoke (const InvocationInfo& info, const bool async); - ApplicationCommandTarget (const ApplicationCommandTarget&); - const ApplicationCommandTarget& operator= (const ApplicationCommandTarget&); + ApplicationCommandTarget (const ApplicationCommandTarget&); + const ApplicationCommandTarget& operator= (const ApplicationCommandTarget&); }; #endif // __JUCE_APPLICATIONCOMMANDTARGET_JUCEHEADER__ @@ -25687,292 +12490,85 @@ private: #ifndef __JUCE_ACTIONLISTENER_JUCEHEADER__ #define __JUCE_ACTIONLISTENER_JUCEHEADER__ -/** - Receives callbacks to indicate that some kind of event has occurred. - - Used by various classes, e.g. buttons when they are pressed, to tell listeners - about something that's happened. - - @see ActionListenerList, ActionBroadcaster, ChangeListener -*/ class JUCE_API ActionListener { public: - /** Destructor. */ - virtual ~ActionListener() {} + virtual ~ActionListener() {} - /** Overridden by your subclass to receive the callback. - - @param message the string that was specified when the event was triggered - by a call to ActionListenerList::sendActionMessage() - */ - virtual void actionListenerCallback (const String& message) = 0; + virtual void actionListenerCallback (const String& message) = 0; }; #endif // __JUCE_ACTIONLISTENER_JUCEHEADER__ /********* End of inlined file: juce_ActionListener.h *********/ -/** - An instance of this class is used to specify initialisation and shutdown - code for the application. - - An application that wants to run in the JUCE framework needs to declare a - subclass of JUCEApplication and implement its various pure virtual methods. - - It then needs to use the START_JUCE_APPLICATION macro somewhere in a cpp file - to declare an instance of this class and generate a suitable platform-specific - main() function. - - e.g. @code - class MyJUCEApp : public JUCEApplication - { - // NEVER put objects inside a JUCEApplication class - only use pointers to - // objects, which you must create in the initialise() method. - MyApplicationWindow* myMainWindow; - - public: - MyJUCEApp() - : myMainWindow (0) - { - // never create any Juce objects in the constructor - do all your initialisation - // in the initialise() method. - } - - ~MyJUCEApp() - { - // all your shutdown code must have already been done in the shutdown() method - - // nothing should happen in this destructor. - } - - void initialise (const String& commandLine) - { - myMainWindow = new MyApplicationWindow(); - myMainWindow->setBounds (100, 100, 400, 500); - myMainWindow->setVisible (true); - } - - void shutdown() - { - delete myMainWindow; - } - - const String getApplicationName() - { - return T("Super JUCE-o-matic"); - } - - const String getApplicationVersion() - { - return T("1.0"); - } - }; - - // this creates wrapper code to actually launch the app properly. - START_JUCE_APPLICATION (MyJUCEApp) - @endcode - - Because this object will be created before Juce has properly initialised, you must - NEVER add any member variable objects that will be automatically constructed. Likewise - don't put ANY code in the constructor that could call Juce functions. Any objects that - you want to add to the class must be pointers, which you should instantiate during the - initialise() method, and delete in the shutdown() method. - - @see MessageManager, DeletedAtShutdown -*/ class JUCE_API JUCEApplication : public ApplicationCommandTarget, - private ActionListener + private ActionListener { protected: - /** Constructs a JUCE app object. - - If subclasses implement a constructor or destructor, they shouldn't call any - JUCE code in there - put your startup/shutdown code in initialise() and - shutdown() instead. - */ - JUCEApplication(); + JUCEApplication(); public: - /** Destructor. + virtual ~JUCEApplication(); - If subclasses implement a constructor or destructor, they shouldn't call any - JUCE code in there - put your startup/shutdown code in initialise() and - shutdown() instead. - */ - virtual ~JUCEApplication(); + static JUCEApplication* getInstance() throw(); - /** Returns the global instance of the application object being run. */ - static JUCEApplication* getInstance() throw(); + virtual void initialise (const String& commandLineParameters) = 0; - /** Called when the application starts. + bool isInitialising() const throw(); - This will be called once to let the application do whatever initialisation - it needs, create its windows, etc. + virtual void shutdown() = 0; - After the method returns, the normal event-dispatch loop will be run, - until the quit() method is called, at which point the shutdown() - method will be called to let the application clear up anything it needs - to delete. + virtual const String getApplicationName() = 0; - If during the initialise() method, the application decides not to start-up - after all, it can just call the quit() method and the event loop won't be run. + virtual const String getApplicationVersion(); - @param commandLineParameters the line passed in does not include the - name of the executable, just the parameter list. - @see shutdown, quit - */ - virtual void initialise (const String& commandLineParameters) = 0; + virtual bool moreThanOneInstanceAllowed(); - /** Returns true if the application hasn't yet completed its initialise() method - and entered the main event loop. + virtual void anotherInstanceStarted (const String& commandLine); - This is handy for things like splash screens to know when the app's up-and-running - properly. - */ - bool isInitialising() const throw(); + virtual void systemRequestedQuit(); - /* Called to allow the application to clear up before exiting. + virtual void unhandledException (const std::exception* e, + const String& sourceFilename, + const int lineNumber); - After JUCEApplication::quit() has been called, the event-dispatch loop will - terminate, and this method will get called to allow the app to sort itself - out. + static void quit(); - Be careful that nothing happens in this method that might rely on messages - being sent, or any kind of window activity, because the message loop is no - longer running at this point. + void setApplicationReturnValue (const int newReturnValue) throw(); - @see DeletedAtShutdown - */ - virtual void shutdown() = 0; + int getApplicationReturnValue() const throw() { return appReturnValue; } - /** Returns the application's name. + const String getCommandLineParameters() const throw() { return commandLineParameters; } - An application must implement this to name itself. - */ - virtual const String getApplicationName() = 0; + // These are used by the START_JUCE_APPLICATION() macro and aren't for public use. - /** Returns the application's version number. + static int main (String& commandLine, JUCEApplication* const newApp); + static int main (int argc, char* argv[], JUCEApplication* const newApp); - An application can implement this to give itself a version. - (The default implementation of this just returns an empty string). - */ - virtual const String getApplicationVersion(); + static void sendUnhandledException (const std::exception* const e, + const char* const sourceFile, + const int lineNumber); - /** Checks whether multiple instances of the app are allowed. - - If you application class returns true for this, more than one instance is - permitted to run (except on the Mac where this isn't possible). - - If it's false, the second instance won't start, but it you will still get a - callback to anotherInstanceStarted() to tell you about this - which - gives you a chance to react to what the user was trying to do. - */ - virtual bool moreThanOneInstanceAllowed(); - - /** Indicates that the user has tried to start up another instance of the app. - - This will get called even if moreThanOneInstanceAllowed() is false. - */ - virtual void anotherInstanceStarted (const String& commandLine); - - /** Called when the operating system is trying to close the application. - - The default implementation of this method is to call quit(), but it may - be overloaded to ignore the request or do some other special behaviour - instead. For example, you might want to offer the user the chance to save - their changes before quitting, and give them the chance to cancel. - - If you want to send a quit signal to your app, this is the correct method - to call, because it means that requests that come from the system get handled - in the same way as those from your own application code. So e.g. you'd - call this method from a "quit" item on a menu bar. - */ - virtual void systemRequestedQuit(); - - /** If any unhandled exceptions make it through to the message dispatch loop, this - callback will be triggered, in case you want to log them or do some other - type of error-handling. - - If the type of exception is derived from the std::exception class, the pointer - passed-in will be valid. If the exception is of unknown type, this pointer - will be null. - */ - virtual void unhandledException (const std::exception* e, - const String& sourceFilename, - const int lineNumber); - - /** Signals that the main message loop should stop and the application should terminate. - - This isn't synchronous, it just posts a quit message to the main queue, and - when this message arrives, the message loop will stop, the shutdown() method - will be called, and the app will exit. - - Note that this will cause an unconditional quit to happen, so if you need an - extra level before this, e.g. to give the user the chance to save their work - and maybe cancel the quit, you'll need to handle this in the systemRequestedQuit() - method - see that method's help for more info. - - @see MessageManager, DeletedAtShutdown - */ - static void quit(); - - /** Sets the value that should be returned as the application's exit code when the - app quits. - - This is the value that's returned by the main() function. Normally you'd leave this - as 0 unless you want to indicate an error code. - - @see getApplicationReturnValue - */ - void setApplicationReturnValue (const int newReturnValue) throw(); - - /** Returns the value that has been set as the application's exit code. - @see setApplicationReturnValue - */ - int getApplicationReturnValue() const throw() { return appReturnValue; } - - /** Returns the application's command line params. - */ - const String getCommandLineParameters() const throw() { return commandLineParameters; } - - // These are used by the START_JUCE_APPLICATION() macro and aren't for public use. - - /** @internal */ - static int main (String& commandLine, JUCEApplication* const newApp); - /** @internal */ - static int main (int argc, char* argv[], JUCEApplication* const newApp); - - /** @internal */ - static void sendUnhandledException (const std::exception* const e, - const char* const sourceFile, - const int lineNumber); - - /** @internal */ - ApplicationCommandTarget* getNextCommandTarget(); - /** @internal */ - void getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result); - /** @internal */ - void getAllCommands (Array & commands); - /** @internal */ - bool perform (const InvocationInfo& info); - /** @internal */ - void actionListenerCallback (const String& message); + ApplicationCommandTarget* getNextCommandTarget(); + void getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result); + void getAllCommands (Array & commands); + bool perform (const InvocationInfo& info); + void actionListenerCallback (const String& message); private: - String commandLineParameters; - int appReturnValue; - bool stillInitialising; - InterProcessLock* appLock; + String commandLineParameters; + int appReturnValue; + bool stillInitialising; + InterProcessLock* appLock; - JUCEApplication (const JUCEApplication&); - const JUCEApplication& operator= (const JUCEApplication&); + JUCEApplication (const JUCEApplication&); + const JUCEApplication& operator= (const JUCEApplication&); public: - /** @internal */ - bool initialiseApp (String& commandLine); - /** @internal */ - static int shutdownAppAndClearUp(); + bool initialiseApp (String& commandLine); + static int shutdownAppAndClearUp(); }; #endif // __JUCE_APPLICATION_JUCEHEADER__ @@ -25999,40 +12595,19 @@ public: #ifndef __JUCE_DELETEDATSHUTDOWN_JUCEHEADER__ #define __JUCE_DELETEDATSHUTDOWN_JUCEHEADER__ -/** - Classes derived from this will be automatically deleted when the application exits. - - After JUCEApplication::shutdown() has been called, any objects derived from - DeletedAtShutdown which are still in existence will be deleted in the reverse - order to that in which they were created. - - So if you've got a singleton and don't want to have to explicitly delete it, just - inherit from this and it'll be taken care of. -*/ class JUCE_API DeletedAtShutdown { protected: - /** Creates a DeletedAtShutdown object. */ - DeletedAtShutdown(); + DeletedAtShutdown(); - /** Destructor. - - It's ok to delete these objects explicitly - it's only the ones left - dangling at the end that will be deleted automatically. - */ - virtual ~DeletedAtShutdown(); + virtual ~DeletedAtShutdown(); public: - /** Deletes all extant objects. - - This shouldn't be used by applications, as it's called automatically - in the shutdown code of the JUCEApplication class. - */ - static void deleteAll(); + static void deleteAll(); private: - DeletedAtShutdown (const DeletedAtShutdown&); - const DeletedAtShutdown& operator= (const DeletedAtShutdown&); + DeletedAtShutdown (const DeletedAtShutdown&); + const DeletedAtShutdown& operator= (const DeletedAtShutdown&); }; #endif // __JUCE_DELETEDATSHUTDOWN_JUCEHEADER__ @@ -26044,323 +12619,134 @@ private: class InternalTimerThread; -/** - Repeatedly calls a user-defined method at a specified time interval. - - A Timer's timerCallback() method will be repeatedly called at a given - interval. Initially when a Timer object is created, they will do nothing - until the startTimer() method is called, then the message thread will - start calling it back until stopTimer() is called. - - The time interval isn't guaranteed to be precise to any more than maybe - 10-20ms, and the intervals may end up being much longer than requested if the - system is busy. Because it's the message thread that is doing the callbacks, - any messages that take a significant amount of time to process will block - all the timers for that period. - - If you need to have a single callback that is shared by multiple timers with - different frequencies, then the MultiTimer class allows you to do that - its - structure is very similar to the Timer class, but contains multiple timers - internally, each one identified by an ID number. - - @see MultiTimer -*/ class JUCE_API Timer { protected: - /** Creates a Timer. + Timer() throw(); - When created, the timer is stopped, so use startTimer() to get it going. - */ - Timer() throw(); - - /** Creates a copy of another timer. - - Note that this timer won't be started, even if the one you're copying - is running. - */ - Timer (const Timer& other) throw(); + Timer (const Timer& other) throw(); public: - /** Destructor. */ - virtual ~Timer(); + virtual ~Timer(); - /** The user-defined callback routine that actually gets called periodically. + virtual void timerCallback() = 0; - It's perfectly ok to call startTimer() or stopTimer() from within this - callback to change the subsequent intervals. - */ - virtual void timerCallback() = 0; + void startTimer (const int intervalInMilliseconds) throw(); - /** Starts the timer and sets the length of interval required. + void stopTimer() throw(); - If the timer is already started, this will reset it, so the - time between calling this method and the next timer callback - will not be less than the interval length passed in. + bool isTimerRunning() const throw() { return periodMs > 0; } - @param intervalInMilliseconds the interval to use (any values less than 1 will be - rounded up to 1) - */ - void startTimer (const int intervalInMilliseconds) throw(); - - /** Stops the timer. - - No more callbacks will be made after this method returns. - - If this is called from a different thread, any callbacks that may - be currently executing may be allowed to finish before the method - returns. - */ - void stopTimer() throw(); - - /** Checks if the timer has been started. - - @returns true if the timer is running. - */ - bool isTimerRunning() const throw() { return periodMs > 0; } - - /** Returns the timer's interval. - - @returns the timer's interval in milliseconds if it's running, or 0 if it's not. - */ - int getTimerInterval() const throw() { return periodMs; } + int getTimerInterval() const throw() { return periodMs; } private: - friend class InternalTimerThread; - int countdownMs, periodMs; - Timer* previous; - Timer* next; + friend class InternalTimerThread; + int countdownMs, periodMs; + Timer* previous; + Timer* next; - const Timer& operator= (const Timer&); + const Timer& operator= (const Timer&); }; #endif // __JUCE_TIMER_JUCEHEADER__ /********* End of inlined file: juce_Timer.h *********/ -/** - Classes can implement this interface and register themselves with the Desktop class - to receive callbacks when the currently focused component changes. - - @see Desktop::addFocusChangeListener, Desktop::removeFocusChangeListener -*/ class JUCE_API FocusChangeListener { public: - /** Destructor. */ - virtual ~FocusChangeListener() {} + virtual ~FocusChangeListener() {} - /** Callback to indicate that the currently focused component has changed. */ - virtual void globalFocusChanged (Component* focusedComponent) = 0; + virtual void globalFocusChanged (Component* focusedComponent) = 0; }; -/** - Describes and controls aspects of the computer's desktop. - -*/ class JUCE_API Desktop : private DeletedAtShutdown, - private Timer, - private AsyncUpdater + private Timer, + private AsyncUpdater { public: - /** There's only one dektop object, and this method will return it. - */ - static Desktop& JUCE_CALLTYPE getInstance() throw(); + static Desktop& JUCE_CALLTYPE getInstance() throw(); - /** Returns a list of the positions of all the monitors available. + const RectangleList getAllMonitorDisplayAreas (const bool clippedToWorkArea = true) const throw(); - The first rectangle in the list will be the main monitor area. + const Rectangle getMainMonitorArea (const bool clippedToWorkArea = true) const throw(); - If clippedToWorkArea is true, it will exclude any areas like the taskbar on Windows, - or the menu bar on Mac. If clippedToWorkArea is false, the entire monitor area is returned. - */ - const RectangleList getAllMonitorDisplayAreas (const bool clippedToWorkArea = true) const throw(); + const Rectangle getMonitorAreaContaining (int x, int y, const bool clippedToWorkArea = true) const throw(); - /** Returns the position and size of the main monitor. + static void getMousePosition (int& x, int& y) throw(); - If clippedToWorkArea is true, it will exclude any areas like the taskbar on Windows, - or the menu bar on Mac. If clippedToWorkArea is false, the entire monitor area is returned. - */ - const Rectangle getMainMonitorArea (const bool clippedToWorkArea = true) const throw(); + static void setMousePosition (int x, int y) throw(); - /** Returns the position and size of the monitor which contains this co-ordinate. + static void getLastMouseDownPosition (int& x, int& y) throw(); - If none of the monitors contains the point, this will just return the - main monitor. + static int getMouseButtonClickCounter() throw(); - If clippedToWorkArea is true, it will exclude any areas like the taskbar on Windows, - or the menu bar on Mac. If clippedToWorkArea is false, the entire monitor area is returned. - */ - const Rectangle getMonitorAreaContaining (int x, int y, const bool clippedToWorkArea = true) const throw(); + static void setScreenSaverEnabled (const bool isEnabled) throw(); - /** Returns the mouse position. + static bool isScreenSaverEnabled() throw(); - The co-ordinates are relative to the top-left of the main monitor. - */ - static void getMousePosition (int& x, int& y) throw(); + void addGlobalMouseListener (MouseListener* const listener) throw(); - /** Makes the mouse pointer jump to a given location. + void removeGlobalMouseListener (MouseListener* const listener) throw(); - The co-ordinates are relative to the top-left of the main monitor. - */ - static void setMousePosition (int x, int y) throw(); + void addFocusChangeListener (FocusChangeListener* const listener) throw(); - /** Returns the last position at which a mouse button was pressed. - */ - static void getLastMouseDownPosition (int& x, int& y) throw(); + void removeFocusChangeListener (FocusChangeListener* const listener) throw(); - /** Returns the number of times the mouse button has been clicked since the - app started. + void setKioskModeComponent (Component* componentToUse, + const bool allowMenusAndBars = true); - Each mouse-down event increments this number by 1. - */ - static int getMouseButtonClickCounter() throw(); + Component* getKioskModeComponent() const { return kioskModeComponent; } - /** This lets you prevent the screensaver from becoming active. + int getNumComponents() const throw(); - Handy if you're running some sort of presentation app where having a screensaver - appear would be annoying. + Component* getComponent (const int index) const throw(); - Pass false to disable the screensaver, and true to re-enable it. (Note that this - won't enable a screensaver unless the user has actually set one up). + Component* findComponentAt (const int screenX, + const int screenY) const; - The disablement will only happen while the Juce application is the foreground - process - if another task is running in front of it, then the screensaver will - be unaffected. + juce_UseDebuggingNewOperator - @see isScreenSaverEnabled - */ - static void setScreenSaverEnabled (const bool isEnabled) throw(); + void refreshMonitorSizes() throw(); - /** Returns true if the screensaver has not been turned off. - - This will return the last value passed into setScreenSaverEnabled(). Note that - it won't tell you whether the user is actually using a screen saver, just - whether this app is deliberately preventing one from running. - - @see setScreenSaverEnabled - */ - static bool isScreenSaverEnabled() throw(); - - /** Registers a MouseListener that will receive all mouse events that occur on - any component. - - @see removeGlobalMouseListener - */ - void addGlobalMouseListener (MouseListener* const listener) throw(); - - /** Unregisters a MouseListener that was added with the addGlobalMouseListener() - method. - - @see addGlobalMouseListener - */ - void removeGlobalMouseListener (MouseListener* const listener) throw(); - - /** Registers a MouseListener that will receive a callback whenever the focused - component changes. - */ - void addFocusChangeListener (FocusChangeListener* const listener) throw(); - - /** Unregisters a listener that was added with addFocusChangeListener(). */ - void removeFocusChangeListener (FocusChangeListener* const listener) throw(); - - /** Takes a component and makes it full-screen, removing the taskbar, dock, etc. - - The component must already be on the desktop for this method to work. It will - be resized to completely fill the screen and any extraneous taskbars, menu bars, - etc will be hidden. - - To exit kiosk mode, just call setKioskModeComponent (0). When this is called, - the component that's currently being used will be resized back to the size - and position it was in before being put into this mode. - - If allowMenusAndBars is true, things like the menu and dock (on mac) are still - allowed to pop up when the mouse moves onto them. If this is false, it'll try - to hide as much on-screen paraphenalia as possible. - */ - void setKioskModeComponent (Component* componentToUse, - const bool allowMenusAndBars = true); - - /** Returns the component that is currently being used in kiosk-mode. - - This is the component that was last set by setKioskModeComponent(). If none - has been set, this returns 0. - */ - Component* getKioskModeComponent() const { return kioskModeComponent; } - - /** Returns the number of components that are currently active as top-level - desktop windows. - - @see getComponent, Component::addToDesktop - */ - int getNumComponents() const throw(); - - /** Returns one of the top-level desktop window components. - - The index is from 0 to getNumComponents() - 1. This could return 0 if the - index is out-of-range. - - @see getNumComponents, Component::addToDesktop - */ - Component* getComponent (const int index) const throw(); - - /** Finds the component at a given screen location. - - This will drill down into top-level windows to find the child component at - the given position. - - Returns 0 if the co-ordinates are inside a non-Juce window. - */ - Component* findComponentAt (const int screenX, - const int screenY) const; - - juce_UseDebuggingNewOperator - - /** Tells this object to refresh its idea of what the screen resolution is. - - (Called internally by the native code). - */ - void refreshMonitorSizes() throw(); - - /** True if the OS supports semitransparent windows */ - static bool canUseSemiTransparentWindows() throw(); + static bool canUseSemiTransparentWindows() throw(); private: - friend class Component; - friend class ComponentPeer; - SortedSet mouseListeners, focusListeners; - VoidArray desktopComponents; + friend class Component; + friend class ComponentPeer; + SortedSet mouseListeners, focusListeners; + VoidArray desktopComponents; - friend class DeletedAtShutdown; - friend class TopLevelWindowManager; - Desktop() throw(); - ~Desktop() throw(); + friend class DeletedAtShutdown; + friend class TopLevelWindowManager; + Desktop() throw(); + ~Desktop() throw(); - Array monitorCoordsClipped, monitorCoordsUnclipped; - int lastMouseX, lastMouseY; + Array monitorCoordsClipped, monitorCoordsUnclipped; + int lastMouseX, lastMouseY; - Component* kioskModeComponent; - Rectangle kioskComponentOriginalBounds; + Component* kioskModeComponent; + Rectangle kioskComponentOriginalBounds; - void timerCallback(); - void sendMouseMove(); - void resetTimer() throw(); + void timerCallback(); + void sendMouseMove(); + void resetTimer() throw(); - int getNumDisplayMonitors() const throw(); - const Rectangle getDisplayMonitorCoordinates (const int index, const bool clippedToWorkArea) const throw(); + int getNumDisplayMonitors() const throw(); + const Rectangle getDisplayMonitorCoordinates (const int index, const bool clippedToWorkArea) const throw(); - void addDesktopComponent (Component* const c) throw(); - void removeDesktopComponent (Component* const c) throw(); - void componentBroughtToFront (Component* const c) throw(); + void addDesktopComponent (Component* const c) throw(); + void removeDesktopComponent (Component* const c) throw(); + void componentBroughtToFront (Component* const c) throw(); - void triggerFocusCallback() throw(); - void handleAsyncUpdate(); + void triggerFocusCallback() throw(); + void handleAsyncUpdate(); - Desktop (const Desktop&); - const Desktop& operator= (const Desktop&); + Desktop (const Desktop&); + const Desktop& operator= (const Desktop&); }; #endif // __JUCE_DESKTOP_JUCEHEADER__ @@ -26369,318 +12755,89 @@ private: class KeyPressMappingSet; class ApplicationCommandManagerListener; -/** - One of these objects holds a list of all the commands your app can perform, - and despatches these commands when needed. - - Application commands are a good way to trigger actions in your app, e.g. "Quit", - "Copy", "Paste", etc. Menus, buttons and keypresses can all be given commands - to invoke automatically, which means you don't have to handle the result of a menu - or button click manually. Commands are despatched to ApplicationCommandTarget objects - which can choose which events they want to handle. - - This architecture also allows for nested ApplicationCommandTargets, so that for example - you could have two different objects, one inside the other, both of which can respond to - a "delete" command. Depending on which one has focus, the command will be sent to the - appropriate place, regardless of whether it was triggered by a menu, keypress or some other - method. - - To set up your app to use commands, you'll need to do the following: - - - Create a global ApplicationCommandManager to hold the list of all possible - commands. (This will also manage a set of key-mappings for them). - - - Make some of your UI components (or other objects) inherit from ApplicationCommandTarget. - This allows the object to provide a list of commands that it can perform, and - to handle them. - - - Register each type of command using ApplicationCommandManager::registerAllCommandsForTarget(), - or ApplicationCommandManager::registerCommand(). - - - If you want key-presses to trigger your commands, use the ApplicationCommandManager::getKeyMappings() - method to access the key-mapper object, which you will need to register as a key-listener - in whatever top-level component you're using. See the KeyPressMappingSet class for more help - about setting this up. - - - Use methods such as PopupMenu::addCommandItem() or Button::setCommandToTrigger() to - cause these commands to be invoked automatically. - - - Commands can be invoked directly by your code using ApplicationCommandManager::invokeDirectly(). - - When a command is invoked, the ApplicationCommandManager will try to choose the best - ApplicationCommandTarget to receive the specified command. To do this it will use the - current keyboard focus to see which component might be interested, and will search the - component hierarchy for those that also implement the ApplicationCommandTarget interface. - If an ApplicationCommandTarget isn't interested in the command that is being invoked, then - the next one in line will be tried (see the ApplicationCommandTarget::getNextCommandTarget() - method), and so on until ApplicationCommandTarget::getNextCommandTarget() returns 0. At this - point if the command still hasn't been performed, it will be passed to the current - JUCEApplication object (which is itself an ApplicationCommandTarget). - - To exert some custom control over which ApplicationCommandTarget is chosen to invoke a command, - you can override the ApplicationCommandManager::getFirstCommandTarget() method and choose - the object yourself. - - @see ApplicationCommandTarget, ApplicationCommandInfo -*/ class JUCE_API ApplicationCommandManager : private AsyncUpdater, - private FocusChangeListener + private FocusChangeListener { public: - /** Creates an ApplicationCommandManager. + ApplicationCommandManager(); - Once created, you'll need to register all your app's commands with it, using - ApplicationCommandManager::registerAllCommandsForTarget() or - ApplicationCommandManager::registerCommand(). - */ - ApplicationCommandManager(); + virtual ~ApplicationCommandManager(); - /** Destructor. + void clearCommands(); - Make sure that you don't delete this if pointers to it are still being used by - objects such as PopupMenus or Buttons. - */ - virtual ~ApplicationCommandManager(); + void registerCommand (const ApplicationCommandInfo& newCommand); - /** Clears the current list of all commands. + void registerAllCommandsForTarget (ApplicationCommandTarget* target); - Note that this will also clear the contents of the KeyPressMappingSet. - */ - void clearCommands(); + void removeCommand (const CommandID commandID); - /** Adds a command to the list of registered commands. + void commandStatusChanged(); - @see registerAllCommandsForTarget - */ - void registerCommand (const ApplicationCommandInfo& newCommand); + int getNumCommands() const throw() { return commands.size(); } - /** Adds all the commands that this target publishes to the manager's list. + const ApplicationCommandInfo* getCommandForIndex (const int index) const throw() { return commands [index]; } - This will use ApplicationCommandTarget::getAllCommands() and ApplicationCommandTarget::getCommandInfo() - to get details about all the commands that this target can do, and will call - registerCommand() to add each one to the manger's list. + const ApplicationCommandInfo* getCommandForID (const CommandID commandID) const throw(); - @see registerCommand - */ - void registerAllCommandsForTarget (ApplicationCommandTarget* target); + const String getNameOfCommand (const CommandID commandID) const throw(); - /** Removes the command with a specified ID. + const String getDescriptionOfCommand (const CommandID commandID) const throw(); - Note that this will also remove any key mappings that are mapped to the command. - */ - void removeCommand (const CommandID commandID); + const StringArray getCommandCategories() const throw(); - /** This should be called to tell the manager that one of its registered commands may have changed - its active status. + const Array getCommandsInCategory (const String& categoryName) const throw(); - Because the command manager only finds out whether a command is active or inactive by querying - the current ApplicationCommandTarget, this is used to tell it that things may have changed. It - allows things like buttons to update their enablement, etc. + KeyPressMappingSet* getKeyMappings() const throw() { return keyMappings; } - This method will cause an asynchronous call to ApplicationCommandManagerListener::applicationCommandListChanged() - for any registered listeners. - */ - void commandStatusChanged(); + bool invokeDirectly (const CommandID commandID, + const bool asynchronously); - /** Returns the number of commands that have been registered. + bool invoke (const ApplicationCommandTarget::InvocationInfo& invocationInfo, + const bool asynchronously); - @see registerCommand - */ - int getNumCommands() const throw() { return commands.size(); } + virtual ApplicationCommandTarget* getFirstCommandTarget (const CommandID commandID); - /** Returns the details about one of the registered commands. + void setFirstCommandTarget (ApplicationCommandTarget* const newTarget) throw(); - The index is between 0 and (getNumCommands() - 1). - */ - const ApplicationCommandInfo* getCommandForIndex (const int index) const throw() { return commands [index]; } + ApplicationCommandTarget* getTargetForCommand (const CommandID commandID, + ApplicationCommandInfo& upToDateInfo); - /** Returns the details about a given command ID. + void addListener (ApplicationCommandManagerListener* const listener) throw(); - This will search the list of registered commands for one with the given command - ID number, and return its associated info. If no matching command is found, this - will return 0. - */ - const ApplicationCommandInfo* getCommandForID (const CommandID commandID) const throw(); + void removeListener (ApplicationCommandManagerListener* const listener) throw(); - /** Returns the name field for a command. + static ApplicationCommandTarget* findDefaultComponentTarget(); - An empty string is returned if no command with this ID has been registered. - @see getDescriptionOfCommand - */ - const String getNameOfCommand (const CommandID commandID) const throw(); + static ApplicationCommandTarget* findTargetForComponent (Component* component); - /** Returns the description field for a command. - - An empty string is returned if no command with this ID has been registered. If the - command has no description, this will return its short name field instead. - - @see getNameOfCommand - */ - const String getDescriptionOfCommand (const CommandID commandID) const throw(); - - /** Returns the list of categories. - - This will go through all registered commands, and return a list of all the distict - categoryName values from their ApplicationCommandInfo structure. - - @see getCommandsInCategory() - */ - const StringArray getCommandCategories() const throw(); - - /** Returns a list of all the command UIDs in a particular category. - - @see getCommandCategories() - */ - const Array getCommandsInCategory (const String& categoryName) const throw(); - - /** Returns the manager's internal set of key mappings. - - This object can be used to edit the keypresses. To actually link this object up - to invoke commands when a key is pressed, see the comments for the KeyPressMappingSet - class. - - @see KeyPressMappingSet - */ - KeyPressMappingSet* getKeyMappings() const throw() { return keyMappings; } - - /** Invokes the given command directly, sending it to the default target. - - This is just an easy way to call invoke() without having to fill out the InvocationInfo - structure. - */ - bool invokeDirectly (const CommandID commandID, - const bool asynchronously); - - /** Sends a command to the default target. - - This will choose a target using getFirstCommandTarget(), and send the specified command - to it using the ApplicationCommandTarget::invoke() method. This means that if the - first target can't handle the command, it will be passed on to targets further down the - chain (see ApplicationCommandTarget::invoke() for more info). - - @param invocationInfo this must be correctly filled-in, describing the context for - the invocation. - @param asynchronously if false, the command will be performed before this method returns. - If true, a message will be posted so that the command will be performed - later on the message thread, and this method will return immediately. - - @see ApplicationCommandTarget::invoke - */ - bool invoke (const ApplicationCommandTarget::InvocationInfo& invocationInfo, - const bool asynchronously); - - /** Chooses the ApplicationCommandTarget to which a command should be sent. - - Whenever the manager needs to know which target a command should be sent to, it calls - this method to determine the first one to try. - - By default, this method will return the target that was set by calling setFirstCommandTarget(). - If no target is set, it will return the result of findDefaultComponentTarget(). - - If you need to make sure all commands go via your own custom target, then you can - either use setFirstCommandTarget() to specify a single target, or override this method - if you need more complex logic to choose one. - - It may return 0 if no targets are available. - - @see getTargetForCommand, invoke, invokeDirectly - */ - virtual ApplicationCommandTarget* getFirstCommandTarget (const CommandID commandID); - - /** Sets a target to be returned by getFirstCommandTarget(). - - If this is set to 0, then getFirstCommandTarget() will by default return the - result of findDefaultComponentTarget(). - - If you use this to set a target, make sure you call setFirstCommandTarget (0) before - deleting the target object. - */ - void setFirstCommandTarget (ApplicationCommandTarget* const newTarget) throw(); - - /** Tries to find the best target to use to perform a given command. - - This will call getFirstCommandTarget() to find the preferred target, and will - check whether that target can handle the given command. If it can't, then it'll use - ApplicationCommandTarget::getNextCommandTarget() to find the next one to try, and - so on until no more are available. - - If no targets are found that can perform the command, this method will return 0. - - If a target is found, then it will get the target to fill-in the upToDateInfo - structure with the latest info about that command, so that the caller can see - whether the command is disabled, ticked, etc. - */ - ApplicationCommandTarget* getTargetForCommand (const CommandID commandID, - ApplicationCommandInfo& upToDateInfo); - - /** Registers a listener that will be called when various events occur. */ - void addListener (ApplicationCommandManagerListener* const listener) throw(); - - /** Deregisters a previously-added listener. */ - void removeListener (ApplicationCommandManagerListener* const listener) throw(); - - /** Looks for a suitable command target based on which Components have the keyboard focus. - - This is used by the default implementation of ApplicationCommandTarget::getFirstCommandTarget(), - but is exposed here in case it's useful. - - It tries to pick the best ApplicationCommandTarget by looking at focused components, top level - windows, etc., and using the findTargetForComponent() method. - */ - static ApplicationCommandTarget* findDefaultComponentTarget(); - - /** Examines this component and all its parents in turn, looking for the first one - which is a ApplicationCommandTarget. - - Returns the first ApplicationCommandTarget that it finds, or 0 if none of them implement - that class. - */ - static ApplicationCommandTarget* findTargetForComponent (Component* component); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OwnedArray commands; - SortedSet listeners; - ScopedPointer keyMappings; - ApplicationCommandTarget* firstTarget; + OwnedArray commands; + SortedSet listeners; + ScopedPointer keyMappings; + ApplicationCommandTarget* firstTarget; - void sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo& info) const; - void handleAsyncUpdate(); - void globalFocusChanged (Component*); + void sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo& info) const; + void handleAsyncUpdate(); + void globalFocusChanged (Component*); - // xxx this is just here to cause a compile error in old code that hasn't been changed to use the new - // version of this method. - virtual short getFirstCommandTarget() { return 0; } + // xxx this is just here to cause a compile error in old code that hasn't been changed to use the new + // version of this method. + virtual short getFirstCommandTarget() { return 0; } }; -/** - A listener that receives callbacks from an ApplicationCommandManager when - commands are invoked or the command list is changed. - - @see ApplicationCommandManager::addListener, ApplicationCommandManager::removeListener - -*/ class JUCE_API ApplicationCommandManagerListener { public: - /** Destructor. */ - virtual ~ApplicationCommandManagerListener() {} + virtual ~ApplicationCommandManagerListener() {} - /** Called when an app command is about to be invoked. */ - virtual void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info) = 0; + virtual void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info) = 0; - /** Called when commands are registered or deregistered from the - command manager, or when commands are made active or inactive. - - Note that if you're using this to watch for changes to whether a command is disabled, - you'll need to make sure that ApplicationCommandManager::commandStatusChanged() is called - whenever the status of your command might have changed. - */ - virtual void applicationCommandListChanged() = 0; + virtual void applicationCommandListChanged() = 0; }; #endif // __JUCE_APPLICATIONCOMMANDMANAGER_JUCEHEADER__ @@ -26700,270 +12857,109 @@ public: #ifndef __JUCE_PROPERTIESFILE_JUCEHEADER__ #define __JUCE_PROPERTIESFILE_JUCEHEADER__ -/** Wrapper on a file that stores a list of key/value data pairs. - - Useful for storing application settings, etc. See the PropertySet class for - the interfaces that read and write values. - - Not designed for very large amounts of data, as it keeps all the values in - memory and writes them out to disk lazily when they are changed. - - Because this class derives from ChangeBroadcaster, ChangeListeners can be registered - with it, and these will be signalled when a value changes. - - @see PropertySet -*/ class JUCE_API PropertiesFile : public PropertySet, - public ChangeBroadcaster, - private Timer + public ChangeBroadcaster, + private Timer { public: - enum FileFormatOptions - { - ignoreCaseOfKeyNames = 1, - storeAsBinary = 2, - storeAsCompressedBinary = 4, - storeAsXML = 8 - }; + enum FileFormatOptions + { + ignoreCaseOfKeyNames = 1, + storeAsBinary = 2, + storeAsCompressedBinary = 4, + storeAsXML = 8 + }; - /** - Creates a PropertiesFile object. + PropertiesFile (const File& file, + const int millisecondsBeforeSaving, + const int options); - @param file the file to use - @param millisecondsBeforeSaving if this is zero or greater, then after a value - is changed, the object will wait for this amount - of time and then save the file. If zero, the file - will be written to disk immediately on being changed - (which might be slow, as it'll re-write synchronously - each time a value-change method is called). If it is - less than zero, the file won't be saved until - save() or saveIfNeeded() are explicitly called. - @param options a combination of the flags in the FileFormatOptions - enum, which specify the type of file to save, and other - options. - */ - PropertiesFile (const File& file, - const int millisecondsBeforeSaving, - const int options); + ~PropertiesFile(); - /** Destructor. + bool saveIfNeeded(); - When deleted, the file will first call saveIfNeeded() to flush any changes to disk. - */ - ~PropertiesFile(); + bool save(); - /** This will flush all the values to disk if they've changed since the last - time they were saved. + bool needsToBeSaved() const; - Returns false if it fails to write to the file for some reason (maybe because - it's read-only or the directory doesn't exist or something). + const File getFile() const { return file; } - @see save - */ - bool saveIfNeeded(); + static PropertiesFile* createDefaultAppPropertiesFile (const String& applicationName, + const String& fileNameSuffix, + const String& folderName, + const bool commonToAllUsers, + const int millisecondsBeforeSaving, + const int propertiesFileOptions); - /** This will force a write-to-disk of the current values, regardless of whether - anything has changed since the last save. + static const File getDefaultAppSettingsFile (const String& applicationName, + const String& fileNameSuffix, + const String& folderName, + const bool commonToAllUsers); - Returns false if it fails to write to the file for some reason (maybe because - it's read-only or the directory doesn't exist or something). - - @see saveIfNeeded - */ - bool save(); - - /** Returns true if the properties have been altered since the last time they were - saved. - */ - bool needsToBeSaved() const; - - /** Returns the file that's being used. */ - const File getFile() const { return file; } - - /** Handy utility to create a properties file in whatever the standard OS-specific - location is for these things. - - This uses getDefaultAppSettingsFile() to decide what file to create, then - creates a PropertiesFile object with the specified properties. See - getDefaultAppSettingsFile() and the class's constructor for descriptions of - what the parameters do. - - @see getDefaultAppSettingsFile - */ - static PropertiesFile* createDefaultAppPropertiesFile (const String& applicationName, - const String& fileNameSuffix, - const String& folderName, - const bool commonToAllUsers, - const int millisecondsBeforeSaving, - const int propertiesFileOptions); - - /** Handy utility to choose a file in the standard OS-dependent location for application - settings files. - - So on a Mac, this will return a file called: - ~/Library/Preferences/[folderName]/[applicationName].[fileNameSuffix] - - On Windows it'll return something like: - C:\\Documents and Settings\\username\\Application Data\\[folderName]\\[applicationName].[fileNameSuffix] - - On Linux it'll return - ~/.[folderName]/[applicationName].[fileNameSuffix] - - If you pass an empty string as the folder name, it'll use the app name for this (or - omit the folder name on the Mac). - - If commonToAllUsers is true, then this will return the same file for all users of the - computer, regardless of the current user. If it is false, the file will be specific to - only the current user. Use this to choose whether you're saving settings that are common - or user-specific. - */ - static const File getDefaultAppSettingsFile (const String& applicationName, - const String& fileNameSuffix, - const String& folderName, - const bool commonToAllUsers); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - virtual void propertyChanged(); + virtual void propertyChanged(); private: - File file; - int timerInterval; - const int options; - bool needsWriting; + File file; + int timerInterval; + const int options; + bool needsWriting; - void timerCallback(); + void timerCallback(); - PropertiesFile (const PropertiesFile&); - const PropertiesFile& operator= (const PropertiesFile&); + PropertiesFile (const PropertiesFile&); + const PropertiesFile& operator= (const PropertiesFile&); }; #endif // __JUCE_PROPERTIESFILE_JUCEHEADER__ /********* End of inlined file: juce_PropertiesFile.h *********/ -/** - Manages a collection of properties. - - This is a slightly higher-level wrapper for PropertiesFile, which can be used - as a singleton. - - It holds two different PropertiesFile objects internally, one for user-specific - settings (stored in your user directory), and one for settings that are common to - all users (stored in a folder accessible to all users). - - The class manages the creation of these files on-demand, allowing access via the - getUserSettings() and getCommonSettings() methods. It also has a few handy - methods like testWriteAccess() to check that the files can be saved. - - If you're using one of these as a singleton, then your app's start-up code should - first of all call setStorageParameters() to tell it the parameters to use to create - the properties files. - - @see PropertiesFile -*/ class JUCE_API ApplicationProperties : public DeletedAtShutdown { public: - /** - Creates an ApplicationProperties object. + ApplicationProperties() throw(); - Before using it, you must call setStorageParameters() to give it the info - it needs to create the property files. - */ - ApplicationProperties() throw(); + ~ApplicationProperties(); - /** Destructor. - */ - ~ApplicationProperties(); + juce_DeclareSingleton (ApplicationProperties, false) - juce_DeclareSingleton (ApplicationProperties, false) + void setStorageParameters (const String& applicationName, + const String& fileNameSuffix, + const String& folderName, + const int millisecondsBeforeSaving, + const int propertiesFileOptions) throw(); - /** Gives the object the information it needs to create the appropriate properties files. + bool testWriteAccess (const bool testUserSettings, + const bool testCommonSettings, + const bool showWarningDialogOnFailure); - See the comments for PropertiesFile::createDefaultAppPropertiesFile() for more - info about how these parameters are used. - */ - void setStorageParameters (const String& applicationName, - const String& fileNameSuffix, - const String& folderName, - const int millisecondsBeforeSaving, - const int propertiesFileOptions) throw(); + PropertiesFile* getUserSettings() throw(); - /** Tests whether the files can be successfully written to, and can show - an error message if not. + PropertiesFile* getCommonSettings (const bool returnUserPropsIfReadOnly) throw(); - Returns true if none of the tests fail. + bool saveIfNeeded(); - @param testUserSettings if true, the user settings file will be tested - @param testCommonSettings if true, the common settings file will be tested - @param showWarningDialogOnFailure if true, the method will show a helpful error - message box if either of the tests fail - */ - bool testWriteAccess (const bool testUserSettings, - const bool testCommonSettings, - const bool showWarningDialogOnFailure); + void closeFiles(); - /** Returns the user settings file. - - The first time this is called, it will create and load the properties file. - - Note that when you search the user PropertiesFile for a value that it doesn't contain, - the common settings are used as a second-chance place to look. This is done via the - PropertySet::setFallbackPropertySet() method - by default the common settings are set - to the fallback for the user settings. - - @see getCommonSettings - */ - PropertiesFile* getUserSettings() throw(); - - /** Returns the common settings file. - - The first time this is called, it will create and load the properties file. - - @param returnUserPropsIfReadOnly if this is true, and the common properties file is - read-only (e.g. because the user doesn't have permission to write - to shared files), then this will return the user settings instead, - (like getUserSettings() would do). This is handy if you'd like to - write a value to the common settings, but if that's no possible, - then you'd rather write to the user settings than none at all. - If returnUserPropsIfReadOnly is false, this method will always return - the common settings, even if any changes to them can't be saved. - @see getUserSettings - */ - PropertiesFile* getCommonSettings (const bool returnUserPropsIfReadOnly) throw(); - - /** Saves both files if they need to be saved. - - @see PropertiesFile::saveIfNeeded - */ - bool saveIfNeeded(); - - /** Flushes and closes both files if they are open. - - This flushes any pending changes to disk with PropertiesFile::saveIfNeeded() - and closes both files. They will then be re-opened the next time getUserSettings() - or getCommonSettings() is called. - */ - void closeFiles(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ScopedPointer userProps, commonProps; + ScopedPointer userProps, commonProps; - String appName, fileSuffix, folderName; - int msBeforeSaving, options; - int commonSettingsAreReadOnly; + String appName, fileSuffix, folderName; + int msBeforeSaving, options; + int commonSettingsAreReadOnly; - ApplicationProperties (const ApplicationProperties&); - const ApplicationProperties& operator= (const ApplicationProperties&); + ApplicationProperties (const ApplicationProperties&); + const ApplicationProperties& operator= (const ApplicationProperties&); - void openFiles() throw(); + void openFiles() throw(); }; #endif // __JUCE_APPLICATIONPROPERTIES_JUCEHEADER__ @@ -26986,190 +12982,64 @@ private: class AudioFormat; -/** - Reads samples from an audio file stream. - - A subclass that reads a specific type of audio format will be created by - an AudioFormat object. - - @see AudioFormat, AudioFormatWriter -*/ class JUCE_API AudioFormatReader { protected: - /** Creates an AudioFormatReader object. - - @param sourceStream the stream to read from - this will be deleted - by this object when it is no longer needed. (Some - specialised readers might not use this parameter and - can leave it as 0). - @param formatName the description that will be returned by the getFormatName() - method - */ - AudioFormatReader (InputStream* const sourceStream, - const String& formatName); + AudioFormatReader (InputStream* const sourceStream, + const String& formatName); public: - /** Destructor. */ - virtual ~AudioFormatReader(); + virtual ~AudioFormatReader(); - /** Returns a description of what type of format this is. + const String getFormatName() const throw() { return formatName; } - E.g. "AIFF" - */ - const String getFormatName() const throw() { return formatName; } + bool read (int** destSamples, + int numDestChannels, + int64 startSampleInSource, + int numSamplesToRead, + const bool fillLeftoverChannelsWithCopies); - /** Reads samples from the stream. + virtual void readMaxLevels (int64 startSample, + int64 numSamples, + float& lowestLeft, + float& highestLeft, + float& lowestRight, + float& highestRight); - @param destSamples an array of buffers into which the sample data for each - channel will be written. - If the format is fixed-point, each channel will be written - as an array of 32-bit signed integers using the full - range -0x80000000 to 0x7fffffff, regardless of the source's - bit-depth. If it is a floating-point format, you should cast - the resulting array to a (float**) to get the values (in the - range -1.0 to 1.0 or beyond) - If the format is stereo, then destSamples[0] is the left channel - data, and destSamples[1] is the right channel. - The numDestChannels parameter indicates how many pointers this array - contains, but some of these pointers can be null if you don't want to - read data for some of the channels - @param numDestChannels the number of array elements in the destChannels array - @param startSampleInSource the position in the audio file or stream at which the samples - should be read, as a number of samples from the start of the - stream. It's ok for this to be beyond the start or end of the - available data - any samples that are out-of-range will be returned - as zeros. - @param numSamplesToRead the number of samples to read. If this is greater than the number - of samples that the file or stream contains. the result will be padded - with zeros - @param fillLeftoverChannelsWithCopies if true, this indicates that if there's no source data available - for some of the channels that you pass in, then they should be filled with - copies of valid source channels. - E.g. if you're reading a mono file and you pass 2 channels to this method, then - if fillLeftoverChannelsWithCopies is true, both destination channels will be filled - with the same data from the file's single channel. If fillLeftoverChannelsWithCopies - was false, then only the first channel would be filled with the file's contents, and - the second would be cleared. If there are many channels, e.g. you try to read 4 channels - from a stereo file, then the last 3 would all end up with copies of the same data. - @returns true if the operation succeeded, false if there was an error. Note - that reading sections of data beyond the extent of the stream isn't an - error - the reader should just return zeros for these regions - @see readMaxLevels - */ - bool read (int** destSamples, - int numDestChannels, - int64 startSampleInSource, - int numSamplesToRead, - const bool fillLeftoverChannelsWithCopies); + int64 searchForLevel (int64 startSample, + int64 numSamplesToSearch, + const double magnitudeRangeMinimum, + const double magnitudeRangeMaximum, + const int minimumConsecutiveSamples); - /** Finds the highest and lowest sample levels from a section of the audio stream. + double sampleRate; - This will read a block of samples from the stream, and measure the - highest and lowest sample levels from the channels in that section, returning - these as normalised floating-point levels. + unsigned int bitsPerSample; - @param startSample the offset into the audio stream to start reading from. It's - ok for this to be beyond the start or end of the stream. - @param numSamples how many samples to read - @param lowestLeft on return, this is the lowest absolute sample from the left channel - @param highestLeft on return, this is the highest absolute sample from the left channel - @param lowestRight on return, this is the lowest absolute sample from the right - channel (if there is one) - @param highestRight on return, this is the highest absolute sample from the right - channel (if there is one) - @see read - */ - virtual void readMaxLevels (int64 startSample, - int64 numSamples, - float& lowestLeft, - float& highestLeft, - float& lowestRight, - float& highestRight); + int64 lengthInSamples; - /** Scans the source looking for a sample whose magnitude is in a specified range. + unsigned int numChannels; - This will read from the source, either forwards or backwards between two sample - positions, until it finds a sample whose magnitude lies between two specified levels. + bool usesFloatingPointData; - If it finds a suitable sample, it returns its position; if not, it will return -1. + StringPairArray metadataValues; - There's also a minimumConsecutiveSamples setting to help avoid spikes or zero-crossing - points when you're searching for a continuous range of samples + InputStream* input; - @param startSample the first sample to look at - @param numSamplesToSearch the number of samples to scan. If this value is negative, - the search will go backwards - @param magnitudeRangeMinimum the lowest magnitude (inclusive) that is considered a hit, from 0 to 1.0 - @param magnitudeRangeMaximum the highest magnitude (inclusive) that is considered a hit, from 0 to 1.0 - @param minimumConsecutiveSamples if this is > 0, the method will only look for a sequence - of this many consecutive samples, all of which lie - within the target range. When it finds such a sequence, - it returns the position of the first in-range sample - it found (i.e. the earliest one if scanning forwards, the - latest one if scanning backwards) - */ - int64 searchForLevel (int64 startSample, - int64 numSamplesToSearch, - const double magnitudeRangeMinimum, - const double magnitudeRangeMaximum, - const int minimumConsecutiveSamples); + virtual bool readSamples (int** destSamples, + int numDestChannels, + int startOffsetInDestBuffer, + int64 startSampleInFile, + int numSamples) = 0; - /** The sample-rate of the stream. */ - double sampleRate; - - /** The number of bits per sample, e.g. 16, 24, 32. */ - unsigned int bitsPerSample; - - /** The total number of samples in the audio stream. */ - int64 lengthInSamples; - - /** The total number of channels in the audio stream. */ - unsigned int numChannels; - - /** Indicates whether the data is floating-point or fixed. */ - bool usesFloatingPointData; - - /** A set of metadata values that the reader has pulled out of the stream. - - Exactly what these values are depends on the format, so you can - check out the format implementation code to see what kind of stuff - they understand. - */ - StringPairArray metadataValues; - - /** The input stream, for use by subclasses. */ - InputStream* input; - - /** Subclasses must implement this method to perform the low-level read operation. - - Callers should use read() instead of calling this directly. - - @param destSamples the array of destination buffers to fill. Some of these - pointers may be null - @param numDestChannels the number of items in the destSamples array. This - value is guaranteed not to be greater than the number of - channels that this reader object contains - @param startOffsetInDestBuffer the number of samples from the start of the - dest data at which to begin writing - @param startSampleInFile the number of samples into the source data at which - to begin reading. This value is guaranteed to be >= 0. - @param numSamples the number of samples to read - */ - virtual bool readSamples (int** destSamples, - int numDestChannels, - int startOffsetInDestBuffer, - int64 startSampleInFile, - int numSamples) = 0; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String formatName; + String formatName; - AudioFormatReader (const AudioFormatReader&); - const AudioFormatReader& operator= (const AudioFormatReader&); + AudioFormatReader (const AudioFormatReader&); + const AudioFormatReader& operator= (const AudioFormatReader&); }; #endif // __JUCE_AUDIOFORMATREADER_JUCEHEADER__ @@ -27190,812 +13060,330 @@ private: class AudioFormatReader; class AudioFormatWriter; -/** - A multi-channel buffer of 32-bit floating point audio samples. - -*/ class JUCE_API AudioSampleBuffer { public: - /** Creates a buffer with a specified number of channels and samples. - - The contents of the buffer will initially be undefined, so use clear() to - set all the samples to zero. - - The buffer will allocate its memory internally, and this will be released - when the buffer is deleted. - */ - AudioSampleBuffer (const int numChannels, - const int numSamples) throw(); - - /** Creates a buffer using a pre-allocated block of memory. - - Note that if the buffer is resized or its number of channels is changed, it - will re-allocate memory internally and copy the existing data to this new area, - so it will then stop directly addressing this memory. - - @param dataToReferTo a pre-allocated array containing pointers to the data - for each channel that should be used by this buffer. The - buffer will only refer to this memory, it won't try to delete - it when the buffer is deleted or resized. - @param numChannels the number of channels to use - this must correspond to the - number of elements in the array passed in - @param numSamples the number of samples to use - this must correspond to the - size of the arrays passed in - */ - AudioSampleBuffer (float** dataToReferTo, - const int numChannels, - const int numSamples) throw(); - - /** Copies another buffer. - - This buffer will make its own copy of the other's data, unless the buffer was created - using an external data buffer, in which case boths buffers will just point to the same - shared block of data. - */ - AudioSampleBuffer (const AudioSampleBuffer& other) throw(); - - /** Copies another buffer onto this one. - - This buffer's size will be changed to that of the other buffer. - */ - const AudioSampleBuffer& operator= (const AudioSampleBuffer& other) throw(); - - /** Destructor. - - This will free any memory allocated by the buffer. - */ - virtual ~AudioSampleBuffer() throw(); - - /** Returns the number of channels of audio data that this buffer contains. - - @see getSampleData - */ - int getNumChannels() const throw() { return numChannels; } - - /** Returns the number of samples allocated in each of the buffer's channels. - - @see getSampleData - */ - int getNumSamples() const throw() { return size; } - - /** Returns a pointer one of the buffer's channels. - - For speed, this doesn't check whether the channel number is out of range, - so be careful when using it! - */ - float* getSampleData (const int channelNumber) const throw() - { - jassert (((unsigned int) channelNumber) < (unsigned int) numChannels); - return channels [channelNumber]; - } - - /** Returns a pointer to a sample in one of the buffer's channels. - - For speed, this doesn't check whether the channel and sample number - are out-of-range, so be careful when using it! - */ - float* getSampleData (const int channelNumber, - const int sampleOffset) const throw() - { - jassert (((unsigned int) channelNumber) < (unsigned int) numChannels); - jassert (((unsigned int) sampleOffset) < (unsigned int) size); - return channels [channelNumber] + sampleOffset; - } - - /** Returns an array of pointers to the channels in the buffer. - - Don't modify any of the pointers that are returned, and bear in mind that - these will become invalid if the buffer is resized. - */ - float** getArrayOfChannels() const throw() { return channels; } - - /** Chages the buffer's size or number of channels. - - This can expand or contract the buffer's length, and add or remove channels. - - If keepExistingContent is true, it will try to preserve as much of the - old data as it can in the new buffer. - - If clearExtraSpace is true, then any extra channels or space that is - allocated will be also be cleared. If false, then this space is left - uninitialised. - - If avoidReallocating is true, then changing the buffer's size won't reduce the - amount of memory that is currently allocated (but it will still increase it if - the new size is bigger than the amount it currently has). If this is false, then - a new allocation will be done so that the buffer uses takes up the minimum amount - of memory that it needs. - */ - void setSize (const int newNumChannels, - const int newNumSamples, - const bool keepExistingContent = false, - const bool clearExtraSpace = false, - const bool avoidReallocating = false) throw(); - - /** Makes this buffer point to a pre-allocated set of channel data arrays. - - There's also a constructor that lets you specify arrays like this, but this - lets you change the channels dynamically. - - Note that if the buffer is resized or its number of channels is changed, it - will re-allocate memory internally and copy the existing data to this new area, - so it will then stop directly addressing this memory. - - @param dataToReferTo a pre-allocated array containing pointers to the data - for each channel that should be used by this buffer. The - buffer will only refer to this memory, it won't try to delete - it when the buffer is deleted or resized. - @param numChannels the number of channels to use - this must correspond to the - number of elements in the array passed in - @param numSamples the number of samples to use - this must correspond to the - size of the arrays passed in - */ - void setDataToReferTo (float** dataToReferTo, - const int numChannels, - const int numSamples) throw(); - - /** Clears all the samples in all channels. */ - void clear() throw(); - - /** Clears a specified region of all the channels. - - For speed, this doesn't check whether the channel and sample number - are in-range, so be careful! - */ - void clear (const int startSample, - const int numSamples) throw(); - - /** Clears a specified region of just one channel. - - For speed, this doesn't check whether the channel and sample number - are in-range, so be careful! - */ - void clear (const int channel, - const int startSample, - const int numSamples) throw(); - - /** Applies a gain multiple to a region of one channel. - - For speed, this doesn't check whether the channel and sample number - are in-range, so be careful! - */ - void applyGain (const int channel, - const int startSample, - int numSamples, - const float gain) throw(); - - /** Applies a gain multiple to a region of all the channels. - - For speed, this doesn't check whether the sample numbers - are in-range, so be careful! - */ - void applyGain (const int startSample, - const int numSamples, - const float gain) throw(); - - /** Applies a range of gains to a region of a channel. - - The gain that is applied to each sample will vary from - startGain on the first sample to endGain on the last Sample, - so it can be used to do basic fades. - - For speed, this doesn't check whether the sample numbers - are in-range, so be careful! - */ - void applyGainRamp (const int channel, - const int startSample, - int numSamples, - float startGain, - float endGain) throw(); - - /** Adds samples from another buffer to this one. - - @param destChannel the channel within this buffer to add the samples to - @param destStartSample the start sample within this buffer's channel - @param source the source buffer to add from - @param sourceChannel the channel within the source buffer to read from - @param sourceStartSample the offset within the source buffer's channel to start reading samples from - @param numSamples the number of samples to process - @param gainToApplyToSource an optional gain to apply to the source samples before they are - added to this buffer's samples - - @see copyFrom - */ - void addFrom (const int destChannel, - const int destStartSample, - const AudioSampleBuffer& source, - const int sourceChannel, - const int sourceStartSample, - int numSamples, - const float gainToApplyToSource = 1.0f) throw(); - - /** Adds samples from an array of floats to one of the channels. - - @param destChannel the channel within this buffer to add the samples to - @param destStartSample the start sample within this buffer's channel - @param source the source data to use - @param numSamples the number of samples to process - @param gainToApplyToSource an optional gain to apply to the source samples before they are - added to this buffer's samples - - @see copyFrom - */ - void addFrom (const int destChannel, - const int destStartSample, - const float* source, - int numSamples, - const float gainToApplyToSource = 1.0f) throw(); - - /** Adds samples from an array of floats, applying a gain ramp to them. - - @param destChannel the channel within this buffer to add the samples to - @param destStartSample the start sample within this buffer's channel - @param source the source data to use - @param numSamples the number of samples to process - @param startGain the gain to apply to the first sample (this is multiplied with - the source samples before they are added to this buffer) - @param endGain the gain to apply to the final sample. The gain is linearly - interpolated between the first and last samples. - */ - void addFromWithRamp (const int destChannel, - const int destStartSample, - const float* source, - int numSamples, - float startGain, - float endGain) throw(); - - /** Copies samples from another buffer to this one. - - @param destChannel the channel within this buffer to copy the samples to - @param destStartSample the start sample within this buffer's channel - @param source the source buffer to read from - @param sourceChannel the channel within the source buffer to read from - @param sourceStartSample the offset within the source buffer's channel to start reading samples from - @param numSamples the number of samples to process - - @see addFrom - */ - void copyFrom (const int destChannel, - const int destStartSample, - const AudioSampleBuffer& source, - const int sourceChannel, - const int sourceStartSample, - int numSamples) throw(); - - /** Copies samples from an array of floats into one of the channels. - - @param destChannel the channel within this buffer to copy the samples to - @param destStartSample the start sample within this buffer's channel - @param source the source buffer to read from - @param numSamples the number of samples to process - - @see addFrom - */ - void copyFrom (const int destChannel, - const int destStartSample, - const float* source, - int numSamples) throw(); - - /** Copies samples from an array of floats into one of the channels, applying a gain to it. - - @param destChannel the channel within this buffer to copy the samples to - @param destStartSample the start sample within this buffer's channel - @param source the source buffer to read from - @param numSamples the number of samples to process - @param gain the gain to apply - - @see addFrom - */ - void copyFrom (const int destChannel, - const int destStartSample, - const float* source, - int numSamples, - const float gain) throw(); - - /** Copies samples from an array of floats into one of the channels, applying a gain ramp. - - @param destChannel the channel within this buffer to copy the samples to - @param destStartSample the start sample within this buffer's channel - @param source the source buffer to read from - @param numSamples the number of samples to process - @param startGain the gain to apply to the first sample (this is multiplied with - the source samples before they are copied to this buffer) - @param endGain the gain to apply to the final sample. The gain is linearly - interpolated between the first and last samples. - - @see addFrom - */ - void copyFromWithRamp (const int destChannel, - const int destStartSample, - const float* source, - int numSamples, - float startGain, - float endGain) throw(); - - /** Finds the highest and lowest sample values in a given range. - - @param channel the channel to read from - @param startSample the start sample within the channel - @param numSamples the number of samples to check - @param minVal on return, the lowest value that was found - @param maxVal on return, the highest value that was found - */ - void findMinMax (const int channel, - const int startSample, - int numSamples, - float& minVal, - float& maxVal) const throw(); - - /** Finds the highest absolute sample value within a region of a channel. - */ - float getMagnitude (const int channel, - const int startSample, - const int numSamples) const throw(); - - /** Finds the highest absolute sample value within a region on all channels. - */ - float getMagnitude (const int startSample, - const int numSamples) const throw(); - - /** Returns the root mean squared level for a region of a channel. - */ - float getRMSLevel (const int channel, - const int startSample, - const int numSamples) const throw(); - - /** Fills a section of the buffer using an AudioReader as its source. - - This will convert the reader's fixed- or floating-point data to - the buffer's floating-point format, and will try to intelligently - cope with mismatches between the number of channels in the reader - and the buffer. - - @see writeToAudioWriter - */ - void readFromAudioReader (AudioFormatReader* reader, - const int startSample, - const int numSamples, - const int readerStartSample, - const bool useReaderLeftChan, - const bool useReaderRightChan) throw(); - - /** Writes a section of this buffer to an audio writer. - - This saves you having to mess about with channels or floating/fixed - point conversion. - - @see readFromAudioReader - */ - void writeToAudioWriter (AudioFormatWriter* writer, - const int startSample, - const int numSamples) const throw(); - - juce_UseDebuggingNewOperator + AudioSampleBuffer (const int numChannels, + const int numSamples) throw(); + + AudioSampleBuffer (float** dataToReferTo, + const int numChannels, + const int numSamples) throw(); + + AudioSampleBuffer (const AudioSampleBuffer& other) throw(); + + const AudioSampleBuffer& operator= (const AudioSampleBuffer& other) throw(); + + virtual ~AudioSampleBuffer() throw(); + + int getNumChannels() const throw() { return numChannels; } + + int getNumSamples() const throw() { return size; } + + float* getSampleData (const int channelNumber) const throw() + { + jassert (((unsigned int) channelNumber) < (unsigned int) numChannels); + return channels [channelNumber]; + } + + float* getSampleData (const int channelNumber, + const int sampleOffset) const throw() + { + jassert (((unsigned int) channelNumber) < (unsigned int) numChannels); + jassert (((unsigned int) sampleOffset) < (unsigned int) size); + return channels [channelNumber] + sampleOffset; + } + + float** getArrayOfChannels() const throw() { return channels; } + + void setSize (const int newNumChannels, + const int newNumSamples, + const bool keepExistingContent = false, + const bool clearExtraSpace = false, + const bool avoidReallocating = false) throw(); + + void setDataToReferTo (float** dataToReferTo, + const int numChannels, + const int numSamples) throw(); + + void clear() throw(); + + void clear (const int startSample, + const int numSamples) throw(); + + void clear (const int channel, + const int startSample, + const int numSamples) throw(); + + void applyGain (const int channel, + const int startSample, + int numSamples, + const float gain) throw(); + + void applyGain (const int startSample, + const int numSamples, + const float gain) throw(); + + void applyGainRamp (const int channel, + const int startSample, + int numSamples, + float startGain, + float endGain) throw(); + + void addFrom (const int destChannel, + const int destStartSample, + const AudioSampleBuffer& source, + const int sourceChannel, + const int sourceStartSample, + int numSamples, + const float gainToApplyToSource = 1.0f) throw(); + + void addFrom (const int destChannel, + const int destStartSample, + const float* source, + int numSamples, + const float gainToApplyToSource = 1.0f) throw(); + + void addFromWithRamp (const int destChannel, + const int destStartSample, + const float* source, + int numSamples, + float startGain, + float endGain) throw(); + + void copyFrom (const int destChannel, + const int destStartSample, + const AudioSampleBuffer& source, + const int sourceChannel, + const int sourceStartSample, + int numSamples) throw(); + + void copyFrom (const int destChannel, + const int destStartSample, + const float* source, + int numSamples) throw(); + + void copyFrom (const int destChannel, + const int destStartSample, + const float* source, + int numSamples, + const float gain) throw(); + + void copyFromWithRamp (const int destChannel, + const int destStartSample, + const float* source, + int numSamples, + float startGain, + float endGain) throw(); + + void findMinMax (const int channel, + const int startSample, + int numSamples, + float& minVal, + float& maxVal) const throw(); + + float getMagnitude (const int channel, + const int startSample, + const int numSamples) const throw(); + + float getMagnitude (const int startSample, + const int numSamples) const throw(); + + float getRMSLevel (const int channel, + const int startSample, + const int numSamples) const throw(); + + void readFromAudioReader (AudioFormatReader* reader, + const int startSample, + const int numSamples, + const int readerStartSample, + const bool useReaderLeftChan, + const bool useReaderRightChan) throw(); + + void writeToAudioWriter (AudioFormatWriter* writer, + const int startSample, + const int numSamples) const throw(); + + juce_UseDebuggingNewOperator private: - int numChannels, size, allocatedBytes; - float** channels; - HeapBlock allocatedData; - float* preallocatedChannelSpace [32]; + int numChannels, size; + size_t allocatedBytes; + float** channels; + HeapBlock allocatedData; + float* preallocatedChannelSpace [32]; - void allocateData(); - void allocateChannels (float** const dataToReferTo); + void allocateData(); + void allocateChannels (float** const dataToReferTo); }; #endif // __JUCE_AUDIOSAMPLEBUFFER_JUCEHEADER__ /********* End of inlined file: juce_AudioSampleBuffer.h *********/ -/** - Used by AudioSource::getNextAudioBlock(). -*/ struct JUCE_API AudioSourceChannelInfo { - /** The destination buffer to fill with audio data. + AudioSampleBuffer* buffer; - When the AudioSource::getNextAudioBlock() method is called, the active section - of this buffer should be filled with whatever output the source produces. + int startSample; - Only the samples specified by the startSample and numSamples members of this structure - should be affected by the call. + int numSamples; - The contents of the buffer when it is passed to the the AudioSource::getNextAudioBlock() - method can be treated as the input if the source is performing some kind of filter operation, - but should be cleared if this is not the case - the clearActiveBufferRegion() is - a handy way of doing this. - - The number of channels in the buffer could be anything, so the AudioSource - must cope with this in whatever way is appropriate for its function. - */ - AudioSampleBuffer* buffer; - - /** The first sample in the buffer from which the callback is expected - to write data. */ - int startSample; - - /** The number of samples in the buffer which the callback is expected to - fill with data. */ - int numSamples; - - /** Convenient method to clear the buffer if the source is not producing any data. */ - void clearActiveBufferRegion() const - { - if (buffer != 0) - buffer->clear (startSample, numSamples); - } + void clearActiveBufferRegion() const + { + if (buffer != 0) + buffer->clear (startSample, numSamples); + } }; -/** - Base class for objects that can produce a continuous stream of audio. - - @see AudioFormatReaderSource, ResamplingAudioSource -*/ class JUCE_API AudioSource { protected: - /** Creates an AudioSource. */ - AudioSource() throw() {} + AudioSource() throw() {} public: - /** Destructor. */ - virtual ~AudioSource() {} + virtual ~AudioSource() {} - /** Tells the source to prepare for playing. + virtual void prepareToPlay (int samplesPerBlockExpected, + double sampleRate) = 0; - The source can use this opportunity to initialise anything it needs to. + virtual void releaseResources() = 0; - Note that this method could be called more than once in succession without - a matching call to releaseResources(), so make sure your code is robust and - can handle that kind of situation. - - @param samplesPerBlockExpected the number of samples that the source - will be expected to supply each time its - getNextAudioBlock() method is called. This - number may vary slightly, because it will be dependent - on audio hardware callbacks, and these aren't - guaranteed to always use a constant block size, so - the source should be able to cope with small variations. - @param sampleRate the sample rate that the output will be used at - this - is needed by sources such as tone generators. - @see releaseResources, getNextAudioBlock - */ - virtual void prepareToPlay (int samplesPerBlockExpected, - double sampleRate) = 0; - - /** Allows the source to release anything it no longer needs after playback has stopped. - - This will be called when the source is no longer going to have its getNextAudioBlock() - method called, so it should release any spare memory, etc. that it might have - allocated during the prepareToPlay() call. - - Note that there's no guarantee that prepareToPlay() will actually have been called before - releaseResources(), and it may be called more than once in succession, so make sure your - code is robust and doesn't make any assumptions about when it will be called. - - @see prepareToPlay, getNextAudioBlock - */ - virtual void releaseResources() = 0; - - /** Called repeatedly to fetch subsequent blocks of audio data. - - After calling the prepareToPlay() method, this callback will be made each - time the audio playback hardware (or whatever other destination the audio - data is going to) needs another block of data. - - It will generally be called on a high-priority system thread, or possibly even - an interrupt, so be careful not to do too much work here, as that will cause - audio glitches! - - @see AudioSourceChannelInfo, prepareToPlay, releaseResources - */ - virtual void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) = 0; + virtual void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) = 0; }; #endif // __JUCE_AUDIOSOURCE_JUCEHEADER__ /********* End of inlined file: juce_AudioSource.h *********/ -/** - Writes samples to an audio file stream. - - A subclass that writes a specific type of audio format will be created by - an AudioFormat object. - - After creating one of these with the AudioFormat::createWriterFor() method - you can call its write() method to store the samples, and then delete it. - - @see AudioFormat, AudioFormatReader -*/ class JUCE_API AudioFormatWriter { protected: - /** Creates an AudioFormatWriter object. - - @param destStream the stream to write to - this will be deleted - by this object when it is no longer needed - @param formatName the description that will be returned by the getFormatName() - method - @param sampleRate the sample rate to use - the base class just stores - this value, it doesn't do anything with it - @param numberOfChannels the number of channels to write - the base class just stores - this value, it doesn't do anything with it - @param bitsPerSample the bit depth of the stream - the base class just stores - this value, it doesn't do anything with it - */ - AudioFormatWriter (OutputStream* const destStream, - const String& formatName, - const double sampleRate, - const unsigned int numberOfChannels, - const unsigned int bitsPerSample); + AudioFormatWriter (OutputStream* const destStream, + const String& formatName, + const double sampleRate, + const unsigned int numberOfChannels, + const unsigned int bitsPerSample); public: - /** Destructor. */ - virtual ~AudioFormatWriter(); + virtual ~AudioFormatWriter(); - /** Returns a description of what type of format this is. + const String getFormatName() const throw() { return formatName; } - E.g. "AIFF file" - */ - const String getFormatName() const throw() { return formatName; } + virtual bool write (const int** samplesToWrite, + int numSamples) = 0; - /** Writes a set of samples to the audio stream. + bool writeFromAudioReader (AudioFormatReader& reader, + int64 startSample, + int64 numSamplesToRead); - Note that if you're trying to write the contents of an AudioSampleBuffer, you - can use AudioSampleBuffer::writeToAudioWriter(). + bool writeFromAudioSource (AudioSource& source, + int numSamplesToRead, + const int samplesPerBlock = 2048); - @param samplesToWrite an array of arrays containing the sample data for - each channel to write. This is a zero-terminated - array of arrays, and can contain a different number - of channels than the actual stream uses, and the - writer should do its best to cope with this. - If the format is fixed-point, each channel will be formatted - as an array of signed integers using the full 32-bit - range -0x80000000 to 0x7fffffff, regardless of the source's - bit-depth. If it is a floating-point format, you should treat - the arrays as arrays of floats, and just cast it to an (int**) - to pass it into the method. - @param numSamples the number of samples to write - */ - virtual bool write (const int** samplesToWrite, - int numSamples) = 0; + double getSampleRate() const throw() { return sampleRate; } - /** Reads a section of samples from an AudioFormatReader, and writes these to - the output. + int getNumChannels() const throw() { return numChannels; } - This will take care of any floating-point conversion that's required to convert - between the two formats. It won't deal with sample-rate conversion, though. + int getBitsPerSample() const throw() { return bitsPerSample; } - If numSamplesToRead < 0, it will write the entire length of the reader. + bool isFloatingPoint() const throw() { return usesFloatingPointData; } - @returns false if it can't read or write properly during the operation - */ - bool writeFromAudioReader (AudioFormatReader& reader, - int64 startSample, - int64 numSamplesToRead); - - /** Reads some samples from an AudioSource, and writes these to the output. - - The source must already have been initialised with the AudioSource::prepareToPlay() method - - @param source the source to read from - @param numSamplesToRead total number of samples to read and write - @param samplesPerBlock the maximum number of samples to fetch from the source - @returns false if it can't read or write properly during the operation - */ - bool writeFromAudioSource (AudioSource& source, - int numSamplesToRead, - const int samplesPerBlock = 2048); - - /** Returns the sample rate being used. */ - double getSampleRate() const throw() { return sampleRate; } - - /** Returns the number of channels being written. */ - int getNumChannels() const throw() { return numChannels; } - - /** Returns the bit-depth of the data being written. */ - int getBitsPerSample() const throw() { return bitsPerSample; } - - /** Returns true if it's a floating-point format, false if it's fixed-point. */ - bool isFloatingPoint() const throw() { return usesFloatingPointData; } - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** The sample rate of the stream. */ - double sampleRate; + double sampleRate; - /** The number of channels being written to the stream. */ - unsigned int numChannels; + unsigned int numChannels; - /** The bit depth of the file. */ - unsigned int bitsPerSample; + unsigned int bitsPerSample; - /** True if it's a floating-point format, false if it's fixed-point. */ - bool usesFloatingPointData; + bool usesFloatingPointData; - /** The output stream for Use by subclasses. */ - OutputStream* output; + OutputStream* output; private: - String formatName; + String formatName; }; #endif // __JUCE_AUDIOFORMATWRITER_JUCEHEADER__ /********* End of inlined file: juce_AudioFormatWriter.h *********/ -/** - Subclasses of AudioFormat are used to read and write different audio - file formats. - - @see AudioFormatReader, AudioFormatWriter, WavAudioFormat, AiffAudioFormat -*/ class JUCE_API AudioFormat { public: - /** Destructor. */ - virtual ~AudioFormat(); + virtual ~AudioFormat(); - /** Returns the name of this format. + const String& getFormatName() const; - e.g. "WAV file" or "AIFF file" - */ - const String& getFormatName() const; + const StringArray& getFileExtensions() const; - /** Returns all the file extensions that might apply to a file of this format. + virtual bool canHandleFile (const File& fileToTest); - The first item will be the one that's preferred when creating a new file. + virtual const Array getPossibleSampleRates() = 0; - So for a wav file this might just return ".wav"; for an AIFF file it might - return two items, ".aif" and ".aiff" - */ - const StringArray& getFileExtensions() const; + virtual const Array getPossibleBitDepths() = 0; - /** Returns true if this the given file can be read by this format. + virtual bool canDoStereo() = 0; - Subclasses shouldn't do too much work here, just check the extension or - file type. The base class implementation just checks the file's extension - against one of the ones that was registered in the constructor. - */ - virtual bool canHandleFile (const File& fileToTest); + virtual bool canDoMono() = 0; - /** Returns a set of sample rates that the format can read and write. */ - virtual const Array getPossibleSampleRates() = 0; + virtual bool isCompressed(); - /** Returns a set of bit depths that the format can read and write. */ - virtual const Array getPossibleBitDepths() = 0; + virtual const StringArray getQualityOptions(); - /** Returns true if the format can do 2-channel audio. */ - virtual bool canDoStereo() = 0; + virtual AudioFormatReader* createReaderFor (InputStream* sourceStream, + const bool deleteStreamIfOpeningFails) = 0; - /** Returns true if the format can do 1-channel audio. */ - virtual bool canDoMono() = 0; - - /** Returns true if the format uses compressed data. */ - virtual bool isCompressed(); - - /** Returns a list of different qualities that can be used when writing. - - Non-compressed formats will just return an empty array, but for something - like Ogg-Vorbis or MP3, it might return a list of bit-rates, etc. - - When calling createWriterFor(), an index from this array is passed in to - tell the format which option is required. - */ - virtual const StringArray getQualityOptions(); - - /** Tries to create an object that can read from a stream containing audio - data in this format. - - The reader object that is returned can be used to read from the stream, and - should then be deleted by the caller. - - @param sourceStream the stream to read from - the AudioFormatReader object - that is returned will delete this stream when it no longer - needs it. - @param deleteStreamIfOpeningFails if no reader can be created, this determines whether this method - should delete the stream object that was passed-in. (If a valid - reader is returned, it will always be in charge of deleting the - stream, so this parameter is ignored) - @see AudioFormatReader - */ - virtual AudioFormatReader* createReaderFor (InputStream* sourceStream, - const bool deleteStreamIfOpeningFails) = 0; - - /** Tries to create an object that can write to a stream with this audio format. - - The writer object that is returned can be used to write to the stream, and - should then be deleted by the caller. - - If the stream can't be created for some reason (e.g. the parameters passed in - here aren't suitable), this will return 0. - - @param streamToWriteTo the stream that the data will go to - this will be - deleted by the AudioFormatWriter object when it's no longer - needed. If no AudioFormatWriter can be created by this method, - the stream will NOT be deleted, so that the caller can re-use it - to try to open a different format, etc - @param sampleRateToUse the sample rate for the file, which must be one of the ones - returned by getPossibleSampleRates() - @param numberOfChannels the number of channels - this must be either 1 or 2, and - the choice will depend on the results of canDoMono() and - canDoStereo() - @param bitsPerSample the bits per sample to use - this must be one of the values - returned by getPossibleBitDepths() - @param metadataValues a set of metadata values that the writer should try to write - to the stream. Exactly what these are depends on the format, - and the subclass doesn't actually have to do anything with - them if it doesn't want to. Have a look at the specific format - implementation classes to see possible values that can be - used - @param qualityOptionIndex the index of one of compression qualities returned by the - getQualityOptions() method. If there aren't any quality options - for this format, just pass 0 in this parameter, as it'll be - ignored - @see AudioFormatWriter - */ - virtual AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, - double sampleRateToUse, - unsigned int numberOfChannels, - int bitsPerSample, - const StringPairArray& metadataValues, - int qualityOptionIndex) = 0; + virtual AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, + double sampleRateToUse, + unsigned int numberOfChannels, + int bitsPerSample, + const StringPairArray& metadataValues, + int qualityOptionIndex) = 0; protected: - /** Creates an AudioFormat object. - - @param formatName this sets the value that will be returned by getFormatName() - @param fileExtensions a zero-terminated list of file extensions - this is what will - be returned by getFileExtension() - */ - AudioFormat (const String& formatName, - const tchar** const fileExtensions); + AudioFormat (const String& formatName, + const tchar** const fileExtensions); private: - String formatName; - StringArray fileExtensions; + String formatName; + StringArray fileExtensions; }; #endif // __JUCE_AUDIOFORMAT_JUCEHEADER__ /********* End of inlined file: juce_AudioFormat.h *********/ -/** - Reads and Writes AIFF format audio files. - - @see AudioFormat -*/ class JUCE_API AiffAudioFormat : public AudioFormat { public: - /** Creates an format object. */ - AiffAudioFormat(); + AiffAudioFormat(); - /** Destructor. */ - ~AiffAudioFormat(); + ~AiffAudioFormat(); - const Array getPossibleSampleRates(); - const Array getPossibleBitDepths(); - bool canDoStereo(); - bool canDoMono(); + const Array getPossibleSampleRates(); + const Array getPossibleBitDepths(); + bool canDoStereo(); + bool canDoMono(); #if JUCE_MAC - bool canHandleFile (const File& fileToTest); + bool canHandleFile (const File& fileToTest); #endif - AudioFormatReader* createReaderFor (InputStream* sourceStream, - const bool deleteStreamIfOpeningFails); + AudioFormatReader* createReaderFor (InputStream* sourceStream, + const bool deleteStreamIfOpeningFails); - AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, - double sampleRateToUse, - unsigned int numberOfChannels, - int bitsPerSample, - const StringPairArray& metadataValues, - int qualityOptionIndex); + AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, + double sampleRateToUse, + unsigned int numberOfChannels, + int bitsPerSample, + const StringPairArray& metadataValues, + int qualityOptionIndex); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; #endif // __JUCE_AIFFAUDIOFORMAT_JUCEHEADER__ @@ -28010,74 +13398,41 @@ public: #if JUCE_USE_CDBURNER -/** -*/ class AudioCDBurner { public: - /** Returns a list of available optical drives. + static const StringArray findAvailableDevices(); - Use openDevice() to open one of the items from this list. - */ - static const StringArray findAvailableDevices(); + static AudioCDBurner* openDevice (const int deviceIndex); - /** Tries to open one of the optical drives. + ~AudioCDBurner(); - The deviceIndex is an index into the array returned by findAvailableDevices(). - */ - static AudioCDBurner* openDevice (const int deviceIndex); + bool isDiskPresent() const; - /** Destructor. */ - ~AudioCDBurner(); + int getNumAvailableAudioBlocks() const; - /** Returns true if there's a writable disk in the drive. - */ - bool isDiskPresent() const; + bool addAudioTrack (AudioSource* source, int numSamples); - /** Returns the number of free blocks on the disk. + class BurnProgressListener + { + public: + BurnProgressListener() throw() {} + virtual ~BurnProgressListener() {} - There are 75 blocks per second, at 44100Hz. - */ - int getNumAvailableAudioBlocks() const; + virtual bool audioCDBurnProgress (float proportionComplete) = 0; + }; - /** Adds a track to be written. + const String burn (BurnProgressListener* listener, + const bool ejectDiscAfterwards, + const bool peformFakeBurnForTesting); - The source passed-in here will be kept by this object, and it will - be used and deleted at some point in the future, either during the - burn() method or when this AudioCDBurner object is deleted. Your caller - method shouldn't keep a reference to it or use it again after passing - it in here. - */ - bool addAudioTrack (AudioSource* source, int numSamples); - - /** - - Return true to cancel the current burn operation - */ - class BurnProgressListener - { - public: - BurnProgressListener() throw() {} - virtual ~BurnProgressListener() {} - - /** Called at intervals to report on the progress of the AudioCDBurner. - - To cancel the burn, return true from this. - */ - virtual bool audioCDBurnProgress (float proportionComplete) = 0; - }; - - const String burn (BurnProgressListener* listener, - const bool ejectDiscAfterwards, - const bool peformFakeBurnForTesting); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioCDBurner (const int deviceIndex); + AudioCDBurner (const int deviceIndex); - void* internal; + void* internal; }; #endif @@ -28097,146 +13452,71 @@ private: #endif -/** - A type of AudioFormatReader that reads from an audio CD. - - One of these can be used to read a CD as if it's one big audio stream. Use the - getPositionOfTrackStart() method to find where the individual tracks are - within the stream. - - @see AudioFormatReader -*/ class JUCE_API AudioCDReader : public AudioFormatReader { public: - /** Returns a list of names of Audio CDs currently available for reading. + static const StringArray getAvailableCDNames(); - If there's a CD drive but no CD in it, this might return an empty list, or - possibly a device that can be opened but which has no tracks, depending - on the platform. + static AudioCDReader* createReaderForCD (const int index); - @see createReaderForCD - */ - static const StringArray getAvailableCDNames(); + ~AudioCDReader(); - /** Tries to create an AudioFormatReader that can read from an Audio CD. + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples); - @param index the index of one of the available CDs - use getAvailableCDNames() - to find out how many there are. - @returns a new AudioCDReader object, or 0 if it couldn't be created. The - caller will be responsible for deleting the object returned. - */ - static AudioCDReader* createReaderForCD (const int index); + bool isCDStillPresent() const; - /** Destructor. */ - ~AudioCDReader(); + int getNumTracks() const; - /** Implementation of the AudioFormatReader method. */ - bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples); + int getPositionOfTrackStart (int trackNum) const; - /** Checks whether the CD has been removed from the drive. - */ - bool isCDStillPresent() const; + bool isTrackAudio (int trackNum) const; - /** Returns the total number of tracks (audio + data). - */ - int getNumTracks() const; + void refreshTrackLengths(); - /** Finds the sample offset of the start of a track. + void enableIndexScanning (bool enabled); - @param trackNum the track number, where 0 is the first track. - */ - int getPositionOfTrackStart (int trackNum) const; + int getLastIndex() const; - /** Returns true if a given track is an audio track. + const Array findIndexesInTrack (const int trackNumber); - @param trackNum the track number, where 0 is the first track. - */ - bool isTrackAudio (int trackNum) const; + int getCDDBId(); - /** Refreshes the object's table of contents. + void ejectDisk(); - If the disc has been ejected and a different one put in since this - object was created, this will cause it to update its idea of how many tracks - there are, etc. - */ - void refreshTrackLengths(); - - /** Enables scanning for indexes within tracks. - - @see getLastIndex - */ - void enableIndexScanning (bool enabled); - - /** Returns the index number found during the last read() call. - - Index scanning is turned off by default - turn it on with enableIndexScanning(). - - Then when the read() method is called, if it comes across an index within that - block, the index number is stored and returned by this method. - - Some devices might not support indexes, of course. - - (If you don't know what CD indexes are, it's unlikely you'll ever need them). - - @see enableIndexScanning - */ - int getLastIndex() const; - - /** Scans a track to find the position of any indexes within it. - - @param trackNumber the track to look in, where 0 is the first track on the disc - @returns an array of sample positions of any index points found (not including - the index that marks the start of the track) - */ - const Array findIndexesInTrack (const int trackNumber); - - /** Returns the CDDB id number for the CD. - - It's not a great way of identifying a disc, but it's traditional. - */ - int getCDDBId(); - - /** Tries to eject the disk. - - Of course this might not be possible, if some other process is using it. - */ - void ejectDisk(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: #if JUCE_MAC - File volumeDir; - OwnedArray tracks; - Array trackStartSamples; - int currentReaderTrack; - ScopedPointer reader; - AudioCDReader (const File& volume); + File volumeDir; + OwnedArray tracks; + Array trackStartSamples; + int currentReaderTrack; + ScopedPointer reader; + AudioCDReader (const File& volume); public: - static int compareElements (const File* const, const File* const) throw(); + static int compareElements (const File* const, const File* const) throw(); private: #elif JUCE_WINDOWS - int numTracks; - int trackStarts[100]; - bool audioTracks [100]; - void* handle; - bool indexingEnabled; - int lastIndex, firstFrameInBuffer, samplesInBuffer; - MemoryBlock buffer; - AudioCDReader (void* handle); - int getIndexAt (int samplePos); + int numTracks; + int trackStarts[100]; + bool audioTracks [100]; + void* handle; + bool indexingEnabled; + int lastIndex, firstFrameInBuffer, samplesInBuffer; + MemoryBlock buffer; + AudioCDReader (void* handle); + int getIndexAt (int samplePos); #elif JUCE_LINUX - AudioCDReader(); + AudioCDReader(); #endif - AudioCDReader (const AudioCDReader&); - const AudioCDReader& operator= (const AudioCDReader&); + AudioCDReader (const AudioCDReader&); + const AudioCDReader& operator= (const AudioCDReader&); }; #endif @@ -28253,110 +13533,42 @@ private: #ifndef __JUCE_AUDIOFORMATMANAGER_JUCEHEADER__ #define __JUCE_AUDIOFORMATMANAGER_JUCEHEADER__ -/** - A class for keeping a list of available audio formats, and for deciding which - one to use to open a given file. - - You can either use this class as a singleton object, or create instances of it - yourself. Once created, use its registerFormat() method to tell it which - formats it should use. - - @see AudioFormat -*/ class JUCE_API AudioFormatManager { public: - /** Creates an empty format manager. + AudioFormatManager(); - Before it'll be any use, you'll need to call registerFormat() with all the - formats you want it to be able to recognise. - */ - AudioFormatManager(); + ~AudioFormatManager(); - /** Destructor. */ - ~AudioFormatManager(); + juce_DeclareSingleton (AudioFormatManager, false); - juce_DeclareSingleton (AudioFormatManager, false); + void registerFormat (AudioFormat* newFormat, + const bool makeThisTheDefaultFormat); - /** Adds a format to the manager's list of available file types. + void registerBasicFormats(); - The object passed-in will be deleted by this object, so don't keep a pointer - to it! + void clearFormats(); - If makeThisTheDefaultFormat is true, then the getDefaultFormat() method will - return this one when called. - */ - void registerFormat (AudioFormat* newFormat, - const bool makeThisTheDefaultFormat); + int getNumKnownFormats() const; - /** Handy method to make it easy to register the formats that come with Juce. + AudioFormat* getKnownFormat (const int index) const; - Currently, this will add WAV and AIFF to the list. - */ - void registerBasicFormats(); + AudioFormat* findFormatForFileExtension (const String& fileExtension) const; - /** Clears the list of known formats. */ - void clearFormats(); + AudioFormat* getDefaultFormat() const; - /** Returns the number of currently registered file formats. */ - int getNumKnownFormats() const; + const String getWildcardForAllFormats() const; - /** Returns one of the registered file formats. */ - AudioFormat* getKnownFormat (const int index) const; + AudioFormatReader* createReaderFor (const File& audioFile); - /** Looks for which of the known formats is listed as being for a given file - extension. + AudioFormatReader* createReaderFor (InputStream* audioFileStream); - The extension may have a dot before it, so e.g. ".wav" or "wav" are both ok. - */ - AudioFormat* findFormatForFileExtension (const String& fileExtension) const; - - /** Returns the format which has been set as the default one. - - You can set a format as being the default when it is registered. It's useful - when you want to write to a file, because the best format may change between - platforms, e.g. AIFF is preferred on the Mac, WAV on Windows. - - If none has been set as the default, this method will just return the first - one in the list. - */ - AudioFormat* getDefaultFormat() const; - - /** Returns a set of wildcards for file-matching that contains the extensions for - all known formats. - - E.g. if might return "*.wav;*.aiff" if it just knows about wavs and aiffs. - */ - const String getWildcardForAllFormats() const; - - /** Searches through the known formats to try to create a suitable reader for - this file. - - If none of the registered formats can open the file, it'll return 0. If it - returns a reader, it's the caller's responsibility to delete the reader. - */ - AudioFormatReader* createReaderFor (const File& audioFile); - - /** Searches through the known formats to try to create a suitable reader for - this stream. - - The stream object that is passed-in will be deleted by this method or by the - reader that is returned, so the caller should not keep any references to it. - - The stream that is passed-in must be capable of being repositioned so - that all the formats can have a go at opening it. - - If none of the registered formats can open the stream, it'll return 0. If it - returns a reader, it's the caller's responsibility to delete the reader. - */ - AudioFormatReader* createReaderFor (InputStream* audioFileStream); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - VoidArray knownFormats; - int defaultFormatIndex; + VoidArray knownFormats; + int defaultFormatIndex; }; #endif // __JUCE_AUDIOFORMATMANAGER_JUCEHEADER__ @@ -28375,60 +13587,36 @@ private: #ifndef __JUCE_AUDIOSUBSECTIONREADER_JUCEHEADER__ #define __JUCE_AUDIOSUBSECTIONREADER_JUCEHEADER__ -/** - This class is used to wrap an AudioFormatReader and only read from a - subsection of the file. - - So if you have a reader which can read a 1000 sample file, you could wrap it - in one of these to only access, e.g. samples 100 to 200, and any samples - outside that will come back as 0. Accessing sample 0 from this reader will - actually read the first sample from the other's subsection, which might - be at a non-zero position. - - @see AudioFormatReader -*/ class JUCE_API AudioSubsectionReader : public AudioFormatReader { public: - /** Creates a AudioSubsectionReader for a given data source. + AudioSubsectionReader (AudioFormatReader* const sourceReader, + const int64 subsectionStartSample, + const int64 subsectionLength, + const bool deleteSourceWhenDeleted); - @param sourceReader the source reader from which we'll be taking data - @param subsectionStartSample the sample within the source reader which will be - mapped onto sample 0 for this reader. - @param subsectionLength the number of samples from the source that will - make up the subsection. If this reader is asked for - any samples beyond this region, it will return zero. - @param deleteSourceWhenDeleted if true, the sourceReader object will be deleted when - this object is deleted. - */ - AudioSubsectionReader (AudioFormatReader* const sourceReader, - const int64 subsectionStartSample, - const int64 subsectionLength, - const bool deleteSourceWhenDeleted); + ~AudioSubsectionReader(); - /** Destructor. */ - ~AudioSubsectionReader(); + bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, + int64 startSampleInFile, int numSamples); - bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples); + void readMaxLevels (int64 startSample, + int64 numSamples, + float& lowestLeft, + float& highestLeft, + float& lowestRight, + float& highestRight); - void readMaxLevels (int64 startSample, - int64 numSamples, - float& lowestLeft, - float& highestLeft, - float& lowestRight, - float& highestRight); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioFormatReader* const source; - int64 startSample, length; - const bool deleteSourceWhenDeleted; + AudioFormatReader* const source; + int64 startSample, length; + const bool deleteSourceWhenDeleted; - AudioSubsectionReader (const AudioSubsectionReader&); - const AudioSubsectionReader& operator= (const AudioSubsectionReader&); + AudioSubsectionReader (const AudioSubsectionReader&); + const AudioSubsectionReader& operator= (const AudioSubsectionReader&); }; #endif // __JUCE_AUDIOSUBSECTIONREADER_JUCEHEADER__ @@ -28443,148 +13631,78 @@ private: class AudioThumbnailCache; -/** - Makes it easy to quickly draw scaled views of the waveform shape of an - audio file. - - To use this class, just create an AudioThumbNail class for the file you want - to draw, call setSource to tell it which file or resource to use, then call - drawChannel() to draw it. - - The class will asynchronously scan the wavefile to create its scaled-down view, - so you should make your UI repaint itself as this data comes in. To do this, the - AudioThumbnail is a ChangeBroadcaster, and will broadcast a message when its - listeners should repaint themselves. - - The thumbnail stores an internal low-res version of the wave data, and this can - be loaded and saved to avoid having to scan the file again. - - @see AudioThumbnailCache -*/ -class JUCE_API AudioThumbnail : public ChangeBroadcaster, - public TimeSliceClient, - private Timer +class JUCE_API AudioThumbnail : public ChangeBroadcaster, + public TimeSliceClient, + private Timer { public: - /** Creates an audio thumbnail. + AudioThumbnail (const int sourceSamplesPerThumbnailSample, + AudioFormatManager& formatManagerToUse, + AudioThumbnailCache& cacheToUse); - @param sourceSamplesPerThumbnailSample when creating a stored, low-res version - of the audio data, this is the scale at which it should be done. (This - number is the number of original samples that will be averaged for each - low-res sample) - @param formatManagerToUse the audio format manager that is used to open the file - @param cacheToUse an instance of an AudioThumbnailCache - this provides a background - thread and storage that is used to by the thumbnail, and the cache - object can be shared between multiple thumbnails - */ - AudioThumbnail (const int sourceSamplesPerThumbnailSample, - AudioFormatManager& formatManagerToUse, - AudioThumbnailCache& cacheToUse); + ~AudioThumbnail(); - /** Destructor. */ - ~AudioThumbnail(); + void setSource (InputSource* const newSource); - /** Specifies the file or stream that contains the audio file. + void loadFrom (InputStream& input); - For a file, just call - @code - setSource (new FileInputSource (file)) - @endcode + void saveTo (OutputStream& output) const; - You can pass a zero in here to clear the thumbnail. + int getNumChannels() const throw(); - The source that is passed in will be deleted by this object when it is no - longer needed - */ - void setSource (InputSource* const newSource); + double getTotalLength() const throw(); - /** Reloads the low res thumbnail data from an input stream. + void drawChannel (Graphics& g, + int x, int y, int w, int h, + double startTimeSeconds, + double endTimeSeconds, + int channelNum, + const float verticalZoomFactor); - The thumb will automatically attempt to reload itself from its - AudioThumbnailCache. - */ - void loadFrom (InputStream& input); + bool isFullyLoaded() const throw(); - /** Saves the low res thumbnail data to an output stream. + bool useTimeSlice(); + void timerCallback(); - The thumb will automatically attempt to save itself to its - AudioThumbnailCache after it finishes scanning the wave file. - */ - void saveTo (OutputStream& output) const; - - /** Returns the number of channels in the file. - */ - int getNumChannels() const throw(); - - /** Returns the length of the audio file, in seconds. - */ - double getTotalLength() const throw(); - - /** Renders the waveform shape for a channel. - - The waveform will be drawn within the specified rectangle, where startTime - and endTime specify the times within the audio file that should be positioned - at the left and right edges of the rectangle. - - The waveform will be scaled vertically so that a full-volume sample will fill - the rectangle vertically, but you can also specify an extra vertical scale factor - with the verticalZoomFactor parameter. - */ - void drawChannel (Graphics& g, - int x, int y, int w, int h, - double startTimeSeconds, - double endTimeSeconds, - int channelNum, - const float verticalZoomFactor); - - /** Returns true if the low res preview is fully generated. - */ - bool isFullyLoaded() const throw(); - - /** @internal */ - bool useTimeSlice(); - /** @internal */ - void timerCallback(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioFormatManager& formatManagerToUse; - AudioThumbnailCache& cache; - ScopedPointer source; + AudioFormatManager& formatManagerToUse; + AudioThumbnailCache& cache; + ScopedPointer source; - CriticalSection readerLock; - ScopedPointer reader; + CriticalSection readerLock; + ScopedPointer reader; - MemoryBlock data, cachedLevels; - int orginalSamplesPerThumbnailSample; + MemoryBlock data, cachedLevels; + int orginalSamplesPerThumbnailSample; - int numChannelsCached, numSamplesCached; - double cachedStart, cachedTimePerPixel; - bool cacheNeedsRefilling; + int numChannelsCached, numSamplesCached; + double cachedStart, cachedTimePerPixel; + bool cacheNeedsRefilling; - void clear(); + void clear(); - AudioFormatReader* createReader() const; + AudioFormatReader* createReader() const; - void generateSection (AudioFormatReader& reader, - int64 startSample, - int numSamples); + void generateSection (AudioFormatReader& reader, + int64 startSample, + int numSamples); - char* getChannelData (int channel) const; + char* getChannelData (int channel) const; - void refillCache (const int numSamples, - double startTime, - const double timePerPixel); + void refillCache (const int numSamples, + double startTime, + const double timePerPixel); - friend class AudioThumbnailCache; + friend class AudioThumbnailCache; - // true if it needs more callbacks from the readNextBlockFromAudioFile() method - bool initialiseFromAudioFile (AudioFormatReader& reader); + // true if it needs more callbacks from the readNextBlockFromAudioFile() method + bool initialiseFromAudioFile (AudioFormatReader& reader); - // returns true if more needs to be read - bool readNextBlockFromAudioFile (AudioFormatReader& reader); + // returns true if more needs to be read + bool readNextBlockFromAudioFile (AudioFormatReader& reader); }; #endif // __JUCE_AUDIOTHUMBNAIL_JUCEHEADER__ @@ -28599,58 +13717,30 @@ private: struct ThumbnailCacheEntry; -/** - An instance of this class is used to manage multiple AudioThumbnail objects. - - The cache runs a single background thread that is shared by all the thumbnails - that need it, and it maintains a set of low-res previews in memory, to avoid - having to re-scan audio files too often. - - @see AudioThumbnail -*/ class JUCE_API AudioThumbnailCache : public TimeSliceThread { public: - /** Creates a cache object. + AudioThumbnailCache (const int maxNumThumbsToStore); - The maxNumThumbsToStore parameter lets you specify how many previews should - be kept in memory at once. - */ - AudioThumbnailCache (const int maxNumThumbsToStore); + ~AudioThumbnailCache(); - /** Destructor. */ - ~AudioThumbnailCache(); + void clear(); - /** Clears out any stored thumbnails. - */ - void clear(); + bool loadThumb (AudioThumbnail& thumb, const int64 hashCode); - /** Reloads the specified thumb if this cache contains the appropriate stored - data. + void storeThumb (const AudioThumbnail& thumb, const int64 hashCode); - This is called automatically by the AudioThumbnail class, so you shouldn't - normally need to call it directly. - */ - bool loadThumb (AudioThumbnail& thumb, const int64 hashCode); - - /** Stores the cachable data from the specified thumb in this cache. - - This is called automatically by the AudioThumbnail class, so you shouldn't - normally need to call it directly. - */ - void storeThumb (const AudioThumbnail& thumb, const int64 hashCode); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OwnedArray thumbs; - int maxNumThumbsToStore; + OwnedArray thumbs; + int maxNumThumbsToStore; - friend class AudioThumbnail; - void addThumbnail (AudioThumbnail* const thumb); - void removeThumbnail (AudioThumbnail* const thumb); + friend class AudioThumbnail; + void addThumbnail (AudioThumbnail* const thumb); + void removeThumbnail (AudioThumbnail* const thumb); }; #endif // __JUCE_AUDIOTHUMBNAILCACHE_JUCEHEADER__ @@ -28665,39 +13755,30 @@ private: #if JUCE_USE_FLAC || defined (DOXYGEN) -/** - Reads and writes the lossless-compression FLAC audio format. - - To compile this, you'll need to set the JUCE_USE_FLAC flag in juce_Config.h, - and make sure your include search path and library search path are set up to find - the FLAC header files and static libraries. - - @see AudioFormat -*/ -class JUCE_API FlacAudioFormat : public AudioFormat +class JUCE_API FlacAudioFormat : public AudioFormat { public: - FlacAudioFormat(); - ~FlacAudioFormat(); + FlacAudioFormat(); + ~FlacAudioFormat(); - const Array getPossibleSampleRates(); - const Array getPossibleBitDepths(); - bool canDoStereo(); - bool canDoMono(); - bool isCompressed(); + const Array getPossibleSampleRates(); + const Array getPossibleBitDepths(); + bool canDoStereo(); + bool canDoMono(); + bool isCompressed(); - AudioFormatReader* createReaderFor (InputStream* sourceStream, - const bool deleteStreamIfOpeningFails); + AudioFormatReader* createReaderFor (InputStream* sourceStream, + const bool deleteStreamIfOpeningFails); - AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, - double sampleRateToUse, - unsigned int numberOfChannels, - int bitsPerSample, - const StringPairArray& metadataValues, - int qualityOptionIndex); + AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, + double sampleRateToUse, + unsigned int numberOfChannels, + int bitsPerSample, + const StringPairArray& metadataValues, + int qualityOptionIndex); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; #endif @@ -28713,50 +13794,33 @@ public: #if JUCE_USE_OGGVORBIS || defined (DOXYGEN) -/** - Reads and writes the Ogg-Vorbis audio format. - - To compile this, you'll need to set the JUCE_USE_OGGVORBIS flag in juce_Config.h, - and make sure your include search path and library search path are set up to find - the Vorbis and Ogg header files and static libraries. - - @see AudioFormat, -*/ class JUCE_API OggVorbisAudioFormat : public AudioFormat { public: - OggVorbisAudioFormat(); - ~OggVorbisAudioFormat(); + OggVorbisAudioFormat(); + ~OggVorbisAudioFormat(); - const Array getPossibleSampleRates(); - const Array getPossibleBitDepths(); - bool canDoStereo(); - bool canDoMono(); - bool isCompressed(); - const StringArray getQualityOptions(); + const Array getPossibleSampleRates(); + const Array getPossibleBitDepths(); + bool canDoStereo(); + bool canDoMono(); + bool isCompressed(); + const StringArray getQualityOptions(); - /** Tries to estimate the quality level of an ogg file based on its size. + int estimateOggFileQuality (const File& source); - If it can't read the file for some reason, this will just return 1 (medium quality), - otherwise it will return the approximate quality setting that would have been used - to create the file. + AudioFormatReader* createReaderFor (InputStream* sourceStream, + const bool deleteStreamIfOpeningFails); - @see getQualityOptions - */ - int estimateOggFileQuality (const File& source); + AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, + double sampleRateToUse, + unsigned int numberOfChannels, + int bitsPerSample, + const StringPairArray& metadataValues, + int qualityOptionIndex); - AudioFormatReader* createReaderFor (InputStream* sourceStream, - const bool deleteStreamIfOpeningFails); - - AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, - double sampleRateToUse, - unsigned int numberOfChannels, - int bitsPerSample, - const StringPairArray& metadataValues, - int qualityOptionIndex); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; #endif @@ -28772,40 +13836,30 @@ public: #if JUCE_QUICKTIME -/** - Uses QuickTime to read the audio track a movie or media file. - - As well as QuickTime movies, this should also manage to open other audio - files that quicktime can understand, like mp3, m4a, etc. - - @see AudioFormat -*/ class JUCE_API QuickTimeAudioFormat : public AudioFormat { public: - /** Creates a format object. */ - QuickTimeAudioFormat(); + QuickTimeAudioFormat(); - /** Destructor. */ - ~QuickTimeAudioFormat(); + ~QuickTimeAudioFormat(); - const Array getPossibleSampleRates(); - const Array getPossibleBitDepths(); - bool canDoStereo(); - bool canDoMono(); + const Array getPossibleSampleRates(); + const Array getPossibleBitDepths(); + bool canDoStereo(); + bool canDoMono(); - AudioFormatReader* createReaderFor (InputStream* sourceStream, - const bool deleteStreamIfOpeningFails); + AudioFormatReader* createReaderFor (InputStream* sourceStream, + const bool deleteStreamIfOpeningFails); - AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, - double sampleRateToUse, - unsigned int numberOfChannels, - int bitsPerSample, - const StringPairArray& metadataValues, - int qualityOptionIndex); + AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, + double sampleRateToUse, + unsigned int numberOfChannels, + int bitsPerSample, + const StringPairArray& metadataValues, + int qualityOptionIndex); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; #endif @@ -28819,116 +13873,53 @@ public: #ifndef __JUCE_WAVAUDIOFORMAT_JUCEHEADER__ #define __JUCE_WAVAUDIOFORMAT_JUCEHEADER__ -/** - Reads and Writes WAV format audio files. - - @see AudioFormat -*/ class JUCE_API WavAudioFormat : public AudioFormat { public: - /** Creates a format object. */ - WavAudioFormat(); + WavAudioFormat(); - /** Destructor. */ - ~WavAudioFormat(); + ~WavAudioFormat(); - /** Metadata property name used by wav readers and writers for adding - a BWAV chunk to the file. + static const tchar* const bwavDescription; - @see AudioFormatReader::metadataValues, createWriterFor - */ - static const tchar* const bwavDescription; + static const tchar* const bwavOriginator; - /** Metadata property name used by wav readers and writers for adding - a BWAV chunk to the file. + static const tchar* const bwavOriginatorRef; - @see AudioFormatReader::metadataValues, createWriterFor - */ - static const tchar* const bwavOriginator; + static const tchar* const bwavOriginationDate; - /** Metadata property name used by wav readers and writers for adding - a BWAV chunk to the file. + static const tchar* const bwavOriginationTime; - @see AudioFormatReader::metadataValues, createWriterFor - */ - static const tchar* const bwavOriginatorRef; + static const tchar* const bwavTimeReference; - /** Metadata property name used by wav readers and writers for adding - a BWAV chunk to the file. + static const tchar* const bwavCodingHistory; - Date format is: yyyy-mm-dd + static const StringPairArray createBWAVMetadata (const String& description, + const String& originator, + const String& originatorRef, + const Time& dateAndTime, + const int64 timeReferenceSamples, + const String& codingHistory); - @see AudioFormatReader::metadataValues, createWriterFor - */ - static const tchar* const bwavOriginationDate; + const Array getPossibleSampleRates(); + const Array getPossibleBitDepths(); + bool canDoStereo(); + bool canDoMono(); - /** Metadata property name used by wav readers and writers for adding - a BWAV chunk to the file. + AudioFormatReader* createReaderFor (InputStream* sourceStream, + const bool deleteStreamIfOpeningFails); - Time format is: hh-mm-ss + AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, + double sampleRateToUse, + unsigned int numberOfChannels, + int bitsPerSample, + const StringPairArray& metadataValues, + int qualityOptionIndex); - @see AudioFormatReader::metadataValues, createWriterFor - */ - static const tchar* const bwavOriginationTime; + bool replaceMetadataInFile (const File& wavFile, const StringPairArray& newMetadata); - /** Metadata property name used by wav readers and writers for adding - a BWAV chunk to the file. - - This is the number of samples from the start of an edit that the - file is supposed to begin at. Seems like an obvious mistake to - only allow a file to occur in an edit once, but that's the way - it is.. - - @see AudioFormatReader::metadataValues, createWriterFor - */ - static const tchar* const bwavTimeReference; - - /** Metadata property name used by wav readers and writers for adding - a BWAV chunk to the file. - - This is a - - @see AudioFormatReader::metadataValues, createWriterFor - */ - static const tchar* const bwavCodingHistory; - - /** Utility function to fill out the appropriate metadata for a BWAV file. - - This just makes it easier than using the property names directly, and it - fills out the time and date in the right format. - */ - static const StringPairArray createBWAVMetadata (const String& description, - const String& originator, - const String& originatorRef, - const Time& dateAndTime, - const int64 timeReferenceSamples, - const String& codingHistory); - - const Array getPossibleSampleRates(); - const Array getPossibleBitDepths(); - bool canDoStereo(); - bool canDoMono(); - - AudioFormatReader* createReaderFor (InputStream* sourceStream, - const bool deleteStreamIfOpeningFails); - - AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo, - double sampleRateToUse, - unsigned int numberOfChannels, - int bitsPerSample, - const StringPairArray& metadataValues, - int qualityOptionIndex); - - /** Utility function to replace the metadata in a wav file with a new set of values. - - If possible, this cheats by overwriting just the metadata region of the file, rather - than by copying the whole file again. - */ - bool replaceMetadataInFile (const File& wavFile, const StringPairArray& newMetadata); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; #endif // __JUCE_WAVAUDIOFORMAT_JUCEHEADER__ @@ -28945,120 +13936,67 @@ public: #ifndef __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__ #define __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__ -/** - A type of AudioSource which can be repositioned. - - The basic AudioSource just streams continuously with no idea of a current - time or length, so the PositionableAudioSource is used for a finite stream - that has a current read position. - - @see AudioSource, AudioTransportSource -*/ class JUCE_API PositionableAudioSource : public AudioSource { protected: - /** Creates the PositionableAudioSource. */ - PositionableAudioSource() throw() {} + PositionableAudioSource() throw() {} public: - /** Destructor */ - ~PositionableAudioSource() {} + ~PositionableAudioSource() {} - /** Tells the stream to move to a new position. + virtual void setNextReadPosition (int newPosition) = 0; - Calling this indicates that the next call to AudioSource::getNextAudioBlock() - should return samples from this position. + virtual int getNextReadPosition() const = 0; - Note that this may be called on a different thread to getNextAudioBlock(), - so the subclass should make sure it's synchronised. - */ - virtual void setNextReadPosition (int newPosition) = 0; + virtual int getTotalLength() const = 0; - /** Returns the position from which the next block will be returned. - - @see setNextReadPosition - */ - virtual int getNextReadPosition() const = 0; - - /** Returns the total length of the stream (in samples). */ - virtual int getTotalLength() const = 0; - - /** Returns true if this source is actually playing in a loop. */ - virtual bool isLooping() const = 0; + virtual bool isLooping() const = 0; }; #endif // __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__ /********* End of inlined file: juce_PositionableAudioSource.h *********/ -/** - A type of AudioSource that will read from an AudioFormatReader. - - @see PositionableAudioSource, AudioTransportSource, BufferingAudioSource -*/ class JUCE_API AudioFormatReaderSource : public PositionableAudioSource { public: - /** Creates an AudioFormatReaderSource for a given reader. + AudioFormatReaderSource (AudioFormatReader* const sourceReader, + const bool deleteReaderWhenThisIsDeleted); - @param sourceReader the reader to use as the data source - @param deleteReaderWhenThisIsDeleted if true, the reader passed-in will be deleted - when this object is deleted; if false it will be - left up to the caller to manage its lifetime - */ - AudioFormatReaderSource (AudioFormatReader* const sourceReader, - const bool deleteReaderWhenThisIsDeleted); + ~AudioFormatReaderSource(); - /** Destructor. */ - ~AudioFormatReaderSource(); + void setLooping (const bool shouldLoop) throw(); - /** Toggles loop-mode. + bool isLooping() const { return looping; } - If set to true, it will continuously loop the input source. If false, - it will just emit silence after the source has finished. + AudioFormatReader* getAudioFormatReader() const throw() { return reader; } - @see isLooping - */ - void setLooping (const bool shouldLoop) throw(); + void prepareToPlay (int samplesPerBlockExpected, double sampleRate); - /** Returns whether loop-mode is turned on or not. */ - bool isLooping() const { return looping; } + void releaseResources(); - /** Returns the reader that's being used. */ - AudioFormatReader* getAudioFormatReader() const throw() { return reader; } + void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - /** Implementation of the AudioSource method. */ - void prepareToPlay (int samplesPerBlockExpected, double sampleRate); + void setNextReadPosition (int newPosition); - /** Implementation of the AudioSource method. */ - void releaseResources(); + int getNextReadPosition() const; - /** Implementation of the AudioSource method. */ - void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); + int getTotalLength() const; - /** Implements the PositionableAudioSource method. */ - void setNextReadPosition (int newPosition); - - /** Implements the PositionableAudioSource method. */ - int getNextReadPosition() const; - - /** Implements the PositionableAudioSource method. */ - int getTotalLength() const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioFormatReader* reader; - bool deleteReader; + AudioFormatReader* reader; + bool deleteReader; - int volatile nextPlayPos; - bool volatile looping; + int volatile nextPlayPos; + bool volatile looping; - void readBufferSection (int start, int length, AudioSampleBuffer& buffer, int startSample); + void readBufferSection (int start, int length, AudioSampleBuffer& buffer, int startSample); - AudioFormatReaderSource (const AudioFormatReaderSource&); - const AudioFormatReaderSource& operator= (const AudioFormatReaderSource&); + AudioFormatReaderSource (const AudioFormatReaderSource&); + const AudioFormatReaderSource& operator= (const AudioFormatReaderSource&); }; #endif // __JUCE_AUDIOFORMATREADERSOURCE_JUCEHEADER__ @@ -29080,366 +14018,130 @@ private: class AudioIODevice; -/** - One of these is passed to an AudioIODevice object to stream the audio data - in and out. - - The AudioIODevice will repeatedly call this class's audioDeviceIOCallback() - method on its own high-priority audio thread, when it needs to send or receive - the next block of data. - - @see AudioIODevice, AudioDeviceManager -*/ class JUCE_API AudioIODeviceCallback { public: - /** Destructor. */ - virtual ~AudioIODeviceCallback() {} + virtual ~AudioIODeviceCallback() {} - /** Processes a block of incoming and outgoing audio data. + virtual void audioDeviceIOCallback (const float** inputChannelData, + int numInputChannels, + float** outputChannelData, + int numOutputChannels, + int numSamples) = 0; - The subclass's implementation should use the incoming audio for whatever - purposes it needs to, and must fill all the output channels with the next - block of output data before returning. + virtual void audioDeviceAboutToStart (AudioIODevice* device) = 0; - The channel data is arranged with the same array indices as the channel name - array returned by AudioIODevice::getOutputChannelNames(), but those channels - that aren't specified in AudioIODevice::open() will have a null pointer for their - associated channel, so remember to check for this. - - @param inputChannelData a set of arrays containing the audio data for each - incoming channel - this data is valid until the function - returns. There will be one channel of data for each input - channel that was enabled when the audio device was opened - (see AudioIODevice::open()) - @param numInputChannels the number of pointers to channel data in the - inputChannelData array. - @param outputChannelData a set of arrays which need to be filled with the data - that should be sent to each outgoing channel of the device. - There will be one channel of data for each output channel - that was enabled when the audio device was opened (see - AudioIODevice::open()) - The initial contents of the array is undefined, so the - callback function must fill all the channels with zeros if - its output is silence. Failing to do this could cause quite - an unpleasant noise! - @param numOutputChannels the number of pointers to channel data in the - outputChannelData array. - @param numSamples the number of samples in each channel of the input and - output arrays. The number of samples will depend on the - audio device's buffer size and will usually remain constant, - although this isn't guaranteed, so make sure your code can - cope with reasonable changes in the buffer size from one - callback to the next. - */ - virtual void audioDeviceIOCallback (const float** inputChannelData, - int numInputChannels, - float** outputChannelData, - int numOutputChannels, - int numSamples) = 0; - - /** Called to indicate that the device is about to start calling back. - - This will be called just before the audio callbacks begin, either when this - callback has just been added to an audio device, or after the device has been - restarted because of a sample-rate or block-size change. - - You can use this opportunity to find out the sample rate and block size - that the device is going to use by calling the AudioIODevice::getCurrentSampleRate() - and AudioIODevice::getCurrentBufferSizeSamples() on the supplied pointer. - - @param device the audio IO device that will be used to drive the callback. - Note that if you're going to store this this pointer, it is - only valid until the next time that audioDeviceStopped is called. - */ - virtual void audioDeviceAboutToStart (AudioIODevice* device) = 0; - - /** Called to indicate that the device has stopped. - */ - virtual void audioDeviceStopped() = 0; + virtual void audioDeviceStopped() = 0; }; -/** - Base class for an audio device with synchronised input and output channels. - - Subclasses of this are used to implement different protocols such as DirectSound, - ASIO, CoreAudio, etc. - - To create one of these, you'll need to use the AudioIODeviceType class - see the - documentation for that class for more info. - - For an easier way of managing audio devices and their settings, have a look at the - AudioDeviceManager class. - - @see AudioIODeviceType, AudioDeviceManager -*/ class JUCE_API AudioIODevice { public: - /** Destructor. */ - virtual ~AudioIODevice(); + virtual ~AudioIODevice(); - /** Returns the device's name, (as set in the constructor). */ - const String& getName() const throw() { return name; } + const String& getName() const throw() { return name; } - /** Returns the type of the device. + const String& getTypeName() const throw() { return typeName; } - E.g. "CoreAudio", "ASIO", etc. - this comes from the AudioIODeviceType that created it. - */ - const String& getTypeName() const throw() { return typeName; } + virtual const StringArray getOutputChannelNames() = 0; - /** Returns the names of all the available output channels on this device. - To find out which of these are currently in use, call getActiveOutputChannels(). - */ - virtual const StringArray getOutputChannelNames() = 0; + virtual const StringArray getInputChannelNames() = 0; - /** Returns the names of all the available input channels on this device. - To find out which of these are currently in use, call getActiveInputChannels(). - */ - virtual const StringArray getInputChannelNames() = 0; + virtual int getNumSampleRates() = 0; - /** Returns the number of sample-rates this device supports. + virtual double getSampleRate (int index) = 0; - To find out which rates are available on this device, use this method to - find out how many there are, and getSampleRate() to get the rates. + virtual int getNumBufferSizesAvailable() = 0; - @see getSampleRate - */ - virtual int getNumSampleRates() = 0; + virtual int getBufferSizeSamples (int index) = 0; - /** Returns one of the sample-rates this device supports. + virtual int getDefaultBufferSize() = 0; - To find out which rates are available on this device, use getNumSampleRates() to - find out how many there are, and getSampleRate() to get the individual rates. + virtual const String open (const BitArray& inputChannels, + const BitArray& outputChannels, + double sampleRate, + int bufferSizeSamples) = 0; - The sample rate is set by the open() method. + virtual void close() = 0; - (Note that for DirectSound some rates might not work, depending on combinations - of i/o channels that are being opened). + virtual bool isOpen() = 0; - @see getNumSampleRates - */ - virtual double getSampleRate (int index) = 0; + virtual void start (AudioIODeviceCallback* callback) = 0; - /** Returns the number of sizes of buffer that are available. + virtual void stop() = 0; - @see getBufferSizeSamples, getDefaultBufferSize - */ - virtual int getNumBufferSizesAvailable() = 0; + virtual bool isPlaying() = 0; - /** Returns one of the possible buffer-sizes. + virtual const String getLastError() = 0; - @param index the index of the buffer-size to use, from 0 to getNumBufferSizesAvailable() - 1 - @returns a number of samples - @see getNumBufferSizesAvailable, getDefaultBufferSize - */ - virtual int getBufferSizeSamples (int index) = 0; + virtual int getCurrentBufferSizeSamples() = 0; - /** Returns the default buffer-size to use. + virtual double getCurrentSampleRate() = 0; - @returns a number of samples - @see getNumBufferSizesAvailable, getBufferSizeSamples - */ - virtual int getDefaultBufferSize() = 0; + virtual int getCurrentBitDepth() = 0; - /** Tries to open the device ready to play. + virtual const BitArray getActiveOutputChannels() const = 0; - @param inputChannels a BitArray in which a set bit indicates that the corresponding - input channel should be enabled - @param outputChannels a BitArray in which a set bit indicates that the corresponding - output channel should be enabled - @param sampleRate the sample rate to try to use - to find out which rates are - available, see getNumSampleRates() and getSampleRate() - @param bufferSizeSamples the size of i/o buffer to use - to find out the available buffer - sizes, see getNumBufferSizesAvailable() and getBufferSizeSamples() - @returns an error description if there's a problem, or an empty string if it succeeds in - opening the device - @see close - */ - virtual const String open (const BitArray& inputChannels, - const BitArray& outputChannels, - double sampleRate, - int bufferSizeSamples) = 0; + virtual const BitArray getActiveInputChannels() const = 0; - /** Closes and releases the device if it's open. */ - virtual void close() = 0; + virtual int getOutputLatencyInSamples() = 0; - /** Returns true if the device is still open. + virtual int getInputLatencyInSamples() = 0; - A device might spontaneously close itself if something goes wrong, so this checks if - it's still open. - */ - virtual bool isOpen() = 0; + virtual bool hasControlPanel() const; - /** Starts the device actually playing. - - This must be called after the device has been opened. - - @param callback the callback to use for streaming the data. - @see AudioIODeviceCallback, open - */ - virtual void start (AudioIODeviceCallback* callback) = 0; - - /** Stops the device playing. - - Once a device has been started, this will stop it. Any pending calls to the - callback class will be flushed before this method returns. - */ - virtual void stop() = 0; - - /** Returns true if the device is still calling back. - - The device might mysteriously stop, so this checks whether it's - still playing. - */ - virtual bool isPlaying() = 0; - - /** Returns the last error that happened if anything went wrong. */ - virtual const String getLastError() = 0; - - /** Returns the buffer size that the device is currently using. - - If the device isn't actually open, this value doesn't really mean much. - */ - virtual int getCurrentBufferSizeSamples() = 0; - - /** Returns the sample rate that the device is currently using. - - If the device isn't actually open, this value doesn't really mean much. - */ - virtual double getCurrentSampleRate() = 0; - - /** Returns the device's current physical bit-depth. - - If the device isn't actually open, this value doesn't really mean much. - */ - virtual int getCurrentBitDepth() = 0; - - /** Returns a mask showing which of the available output channels are currently - enabled. - @see getOutputChannelNames - */ - virtual const BitArray getActiveOutputChannels() const = 0; - - /** Returns a mask showing which of the available input channels are currently - enabled. - @see getInputChannelNames - */ - virtual const BitArray getActiveInputChannels() const = 0; - - /** Returns the device's output latency. - - This is the delay in samples between a callback getting a block of data, and - that data actually getting played. - */ - virtual int getOutputLatencyInSamples() = 0; - - /** Returns the device's input latency. - - This is the delay in samples between some audio actually arriving at the soundcard, - and the callback getting passed this block of data. - */ - virtual int getInputLatencyInSamples() = 0; - - /** True if this device can show a pop-up control panel for editing its settings. - - This is generally just true of ASIO devices. If true, you can call showControlPanel() - to display it. - */ - virtual bool hasControlPanel() const; - - /** Shows a device-specific control panel if there is one. - - This should only be called for devices which return true from hasControlPanel(). - */ - virtual bool showControlPanel(); + virtual bool showControlPanel(); protected: - /** Creates a device, setting its name and type member variables. */ - AudioIODevice (const String& deviceName, - const String& typeName); + AudioIODevice (const String& deviceName, + const String& typeName); - /** @internal */ - String name, typeName; + String name, typeName; }; #endif // __JUCE_AUDIOIODEVICE_JUCEHEADER__ /********* End of inlined file: juce_AudioIODevice.h *********/ -/** - Wrapper class to continuously stream audio from an audio source to an - AudioIODevice. - - This object acts as an AudioIODeviceCallback, so can be attached to an - output device, and will stream audio from an AudioSource. -*/ class JUCE_API AudioSourcePlayer : public AudioIODeviceCallback { public: - /** Creates an empty AudioSourcePlayer. */ - AudioSourcePlayer(); + AudioSourcePlayer(); - /** Destructor. + virtual ~AudioSourcePlayer(); - Make sure this object isn't still being used by an AudioIODevice before - deleting it! - */ - virtual ~AudioSourcePlayer(); + void setSource (AudioSource* newSource); - /** Changes the current audio source to play from. + AudioSource* getCurrentSource() const throw() { return source; } - If the source passed in is already being used, this method will do nothing. - If the source is not null, its prepareToPlay() method will be called - before it starts being used for playback. + void setGain (const float newGain) throw(); - If there's another source currently playing, its releaseResources() method - will be called after it has been swapped for the new one. + void audioDeviceIOCallback (const float** inputChannelData, + int totalNumInputChannels, + float** outputChannelData, + int totalNumOutputChannels, + int numSamples); - @param newSource the new source to use - this will NOT be deleted - by this object when no longer needed, so it's the - caller's responsibility to manage it. - */ - void setSource (AudioSource* newSource); + void audioDeviceAboutToStart (AudioIODevice* device); - /** Returns the source that's playing. + void audioDeviceStopped(); - May return 0 if there's no source. - */ - AudioSource* getCurrentSource() const throw() { return source; } - - /** Sets a gain to apply to the audio data. */ - void setGain (const float newGain) throw(); - - /** Implementation of the AudioIODeviceCallback method. */ - void audioDeviceIOCallback (const float** inputChannelData, - int totalNumInputChannels, - float** outputChannelData, - int totalNumOutputChannels, - int numSamples); - - /** Implementation of the AudioIODeviceCallback method. */ - void audioDeviceAboutToStart (AudioIODevice* device); - - /** Implementation of the AudioIODeviceCallback method. */ - void audioDeviceStopped(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - CriticalSection readLock; - AudioSource* source; - double sampleRate; - int bufferSize; - float* channels [128]; - float* outputChans [128]; - const float* inputChans [128]; - AudioSampleBuffer tempBuffer; - float lastGain, gain; + CriticalSection readLock; + AudioSource* source; + double sampleRate; + int bufferSize; + float* channels [128]; + float* outputChans [128]; + const float* inputChans [128]; + AudioSampleBuffer tempBuffer; + float lastGain, gain; - AudioSourcePlayer (const AudioSourcePlayer&); - const AudioSourcePlayer& operator= (const AudioSourcePlayer&); + AudioSourcePlayer (const AudioSourcePlayer&); + const AudioSourcePlayer& operator= (const AudioSourcePlayer&); }; #endif // __JUCE_AUDIOSOURCEPLAYER_JUCEHEADER__ @@ -29456,77 +14158,49 @@ private: #ifndef __JUCE_BUFFERINGAUDIOSOURCE_JUCEHEADER__ #define __JUCE_BUFFERINGAUDIOSOURCE_JUCEHEADER__ -/** - An AudioSource which takes another source as input, and buffers it using a thread. - - Create this as a wrapper around another thread, and it will read-ahead with - a background thread to smooth out playback. You can either create one of these - directly, or use it indirectly using an AudioTransportSource. - - @see PositionableAudioSource, AudioTransportSource -*/ class JUCE_API BufferingAudioSource : public PositionableAudioSource { public: - /** Creates a BufferingAudioSource. + BufferingAudioSource (PositionableAudioSource* source, + const bool deleteSourceWhenDeleted, + int numberOfSamplesToBuffer); - @param source the input source to read from - @param deleteSourceWhenDeleted if true, then the input source object will - be deleted when this object is deleted - @param numberOfSamplesToBuffer the size of buffer to use for reading ahead - */ - BufferingAudioSource (PositionableAudioSource* source, - const bool deleteSourceWhenDeleted, - int numberOfSamplesToBuffer); + ~BufferingAudioSource(); - /** Destructor. + void prepareToPlay (int samplesPerBlockExpected, double sampleRate); - The input source may be deleted depending on whether the deleteSourceWhenDeleted - flag was set in the constructor. - */ - ~BufferingAudioSource(); + void releaseResources(); - /** Implementation of the AudioSource method. */ - void prepareToPlay (int samplesPerBlockExpected, double sampleRate); + void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - /** Implementation of the AudioSource method. */ - void releaseResources(); + void setNextReadPosition (int newPosition); - /** Implementation of the AudioSource method. */ - void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); + int getNextReadPosition() const; - /** Implements the PositionableAudioSource method. */ - void setNextReadPosition (int newPosition); + int getTotalLength() const { return source->getTotalLength(); } - /** Implements the PositionableAudioSource method. */ - int getNextReadPosition() const; + bool isLooping() const { return source->isLooping(); } - /** Implements the PositionableAudioSource method. */ - int getTotalLength() const { return source->getTotalLength(); } - - /** Implements the PositionableAudioSource method. */ - bool isLooping() const { return source->isLooping(); } - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - PositionableAudioSource* source; - bool deleteSourceWhenDeleted; - int numberOfSamplesToBuffer; - AudioSampleBuffer buffer; - CriticalSection bufferStartPosLock; - int volatile bufferValidStart, bufferValidEnd, nextPlayPos; - bool wasSourceLooping; - double volatile sampleRate; + PositionableAudioSource* source; + bool deleteSourceWhenDeleted; + int numberOfSamplesToBuffer; + AudioSampleBuffer buffer; + CriticalSection bufferStartPosLock; + int volatile bufferValidStart, bufferValidEnd, nextPlayPos; + bool wasSourceLooping; + double volatile sampleRate; - friend class SharedBufferingAudioSourceThread; - bool readNextBufferChunk(); - void readBufferSection (int start, int length, int bufferOffset); + friend class SharedBufferingAudioSourceThread; + bool readNextBufferChunk(); + void readBufferSection (int start, int length, int bufferOffset); - BufferingAudioSource (const BufferingAudioSource&); - const BufferingAudioSource& operator= (const BufferingAudioSource&); + BufferingAudioSource (const BufferingAudioSource&); + const BufferingAudioSource& operator= (const BufferingAudioSource&); }; #endif // __JUCE_BUFFERINGAUDIOSOURCE_JUCEHEADER__ @@ -29536,214 +14210,116 @@ private: #ifndef __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__ #define __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__ -/** - A type of AudioSource that takes an input source and changes its sample rate. - - @see AudioSource -*/ class JUCE_API ResamplingAudioSource : public AudioSource { public: - /** Creates a ResamplingAudioSource for a given input source. + ResamplingAudioSource (AudioSource* const inputSource, + const bool deleteInputWhenDeleted); - @param inputSource the input source to read from - @param deleteInputWhenDeleted if true, the input source will be deleted when - this object is deleted - */ - ResamplingAudioSource (AudioSource* const inputSource, - const bool deleteInputWhenDeleted); + ~ResamplingAudioSource(); - /** Destructor. */ - ~ResamplingAudioSource(); + void setResamplingRatio (const double samplesInPerOutputSample); - /** Changes the resampling ratio. + double getResamplingRatio() const throw() { return ratio; } - (This value can be changed at any time, even while the source is running). + void prepareToPlay (int samplesPerBlockExpected, double sampleRate); + void releaseResources(); + void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - @param samplesInPerOutputSample if set to 1.0, the input is passed through; higher - values will speed it up; lower values will slow it - down. The ratio must be greater than 0 - */ - void setResamplingRatio (const double samplesInPerOutputSample); - - /** Returns the current resampling ratio. - - This is the value that was set by setResamplingRatio(). - */ - double getResamplingRatio() const throw() { return ratio; } - - void prepareToPlay (int samplesPerBlockExpected, double sampleRate); - void releaseResources(); - void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioSource* const input; - const bool deleteInputWhenDeleted; - double ratio, lastRatio; - AudioSampleBuffer buffer; - int bufferPos, sampsInBuffer; - double subSampleOffset; - double coefficients[6]; - CriticalSection ratioLock; + AudioSource* const input; + const bool deleteInputWhenDeleted; + double ratio, lastRatio; + AudioSampleBuffer buffer; + int bufferPos, sampsInBuffer; + double subSampleOffset; + double coefficients[6]; + CriticalSection ratioLock; - void setFilterCoefficients (double c1, double c2, double c3, double c4, double c5, double c6); - void createLowPass (const double proportionalRate); + void setFilterCoefficients (double c1, double c2, double c3, double c4, double c5, double c6); + void createLowPass (const double proportionalRate); - struct FilterState - { - double x1, x2, y1, y2; - }; + struct FilterState + { + double x1, x2, y1, y2; + }; - FilterState filterStates[2]; - void resetFilters(); + FilterState filterStates[2]; + void resetFilters(); - void applyFilter (float* samples, int num, FilterState& fs); + void applyFilter (float* samples, int num, FilterState& fs); - ResamplingAudioSource (const ResamplingAudioSource&); - const ResamplingAudioSource& operator= (const ResamplingAudioSource&); + ResamplingAudioSource (const ResamplingAudioSource&); + const ResamplingAudioSource& operator= (const ResamplingAudioSource&); }; #endif // __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__ /********* End of inlined file: juce_ResamplingAudioSource.h *********/ -/** - An AudioSource that takes a PositionableAudioSource and allows it to be - played, stopped, started, etc. - - This can also be told use a buffer and background thread to read ahead, and - if can correct for different sample-rates. - - You may want to use one of these along with an AudioSourcePlayer and AudioIODevice - to control playback of an audio file. - - @see AudioSource, AudioSourcePlayer -*/ class JUCE_API AudioTransportSource : public PositionableAudioSource, - public ChangeBroadcaster + public ChangeBroadcaster { public: - /** Creates an AudioTransportSource. + AudioTransportSource(); - After creating one of these, use the setSource() method to select an input source. - */ - AudioTransportSource(); + ~AudioTransportSource(); - /** Destructor. */ - ~AudioTransportSource(); + void setSource (PositionableAudioSource* const newSource, + int readAheadBufferSize = 0, + double sourceSampleRateToCorrectFor = 0.0); - /** Sets the reader that is being used as the input source. + void setPosition (double newPosition); - This will stop playback, reset the position to 0 and change to the new reader. + double getCurrentPosition() const; - The source passed in will not be deleted by this object, so must be managed by - the caller. + bool hasStreamFinished() const throw() { return inputStreamEOF; } - @param newSource the new input source to use. This may be zero - @param readAheadBufferSize a size of buffer to use for reading ahead. If this - is zero, no reading ahead will be done; if it's - greater than zero, a BufferingAudioSource will be used - to do the reading-ahead - @param sourceSampleRateToCorrectFor if this is non-zero, it specifies the sample - rate of the source, and playback will be sample-rate - adjusted to maintain playback at the correct pitch. If - this is 0, no sample-rate adjustment will be performed - */ - void setSource (PositionableAudioSource* const newSource, - int readAheadBufferSize = 0, - double sourceSampleRateToCorrectFor = 0.0); + void start(); - /** Changes the current playback position in the source stream. + void stop(); - The next time the getNextAudioBlock() method is called, this - is the time from which it'll read data. + bool isPlaying() const throw() { return playing; } - @see getPosition - */ - void setPosition (double newPosition); + void setGain (const float newGain) throw(); - /** Returns the position that the next data block will be read from + float getGain() const throw() { return gain; } - This is a time in seconds. - */ - double getCurrentPosition() const; + void prepareToPlay (int samplesPerBlockExpected, double sampleRate); - /** Returns true if the player has stopped because its input stream ran out of data. - */ - bool hasStreamFinished() const throw() { return inputStreamEOF; } + void releaseResources(); - /** Starts playing (if a source has been selected). + void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - If it starts playing, this will send a message to any ChangeListeners - that are registered with this object. - */ - void start(); + void setNextReadPosition (int newPosition); - /** Stops playing. + int getNextReadPosition() const; - If it's actually playing, this will send a message to any ChangeListeners - that are registered with this object. - */ - void stop(); + int getTotalLength() const; - /** Returns true if it's currently playing. */ - bool isPlaying() const throw() { return playing; } + bool isLooping() const; - /** Changes the gain to apply to the output. - - @param newGain a factor by which to multiply the outgoing samples, - so 1.0 = 0dB, 0.5 = -6dB, 2.0 = 6dB, etc. - */ - void setGain (const float newGain) throw(); - - /** Returns the current gain setting. - - @see setGain - */ - float getGain() const throw() { return gain; } - - /** Implementation of the AudioSource method. */ - void prepareToPlay (int samplesPerBlockExpected, double sampleRate); - - /** Implementation of the AudioSource method. */ - void releaseResources(); - - /** Implementation of the AudioSource method. */ - void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - - /** Implements the PositionableAudioSource method. */ - void setNextReadPosition (int newPosition); - - /** Implements the PositionableAudioSource method. */ - int getNextReadPosition() const; - - /** Implements the PositionableAudioSource method. */ - int getTotalLength() const; - - /** Implements the PositionableAudioSource method. */ - bool isLooping() const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - PositionableAudioSource* source; - ResamplingAudioSource* resamplerSource; - BufferingAudioSource* bufferingSource; - PositionableAudioSource* positionableSource; - AudioSource* masterSource; + PositionableAudioSource* source; + ResamplingAudioSource* resamplerSource; + BufferingAudioSource* bufferingSource; + PositionableAudioSource* positionableSource; + AudioSource* masterSource; - CriticalSection callbackLock; - float volatile gain, lastGain; - bool volatile playing, stopped; - double sampleRate, sourceSampleRate; - int blockSize, readAheadBufferSize; - bool isPrepared, inputStreamEOF; + CriticalSection callbackLock; + float volatile gain, lastGain; + bool volatile playing, stopped; + double sampleRate, sourceSampleRate; + int blockSize, readAheadBufferSize; + bool isPrepared, inputStreamEOF; - AudioTransportSource (const AudioTransportSource&); - const AudioTransportSource& operator= (const AudioTransportSource&); + AudioTransportSource (const AudioTransportSource&); + const AudioTransportSource& operator= (const AudioTransportSource&); }; #endif // __JUCE_AUDIOTRANSPORTSOURCE_JUCEHEADER__ @@ -29759,118 +14335,53 @@ private: #ifndef __JUCE_CHANNELREMAPPINGAUDIOSOURCE_JUCEHEADER__ #define __JUCE_CHANNELREMAPPINGAUDIOSOURCE_JUCEHEADER__ -/** - An AudioSource that takes the audio from another source, and re-maps its - input and output channels to a different arrangement. - - You can use this to increase or decrease the number of channels that an - audio source uses, or to re-order those channels. - - Call the reset() method before using it to set up a default mapping, and then - the setInputChannelMapping() and setOutputChannelMapping() methods to - create an appropriate mapping, otherwise no channels will be connected and - it'll produce silence. - - @see AudioSource -*/ class ChannelRemappingAudioSource : public AudioSource { public: - /** Creates a remapping source that will pass on audio from the given input. + ChannelRemappingAudioSource (AudioSource* const source, + const bool deleteSourceWhenDeleted); - @param source the input source to use. Make sure that this doesn't - get deleted before the ChannelRemappingAudioSource object - @param deleteSourceWhenDeleted if true, the input source will be deleted - when this object is deleted, if false, the caller is - responsible for its deletion - */ - ChannelRemappingAudioSource (AudioSource* const source, - const bool deleteSourceWhenDeleted); + ~ChannelRemappingAudioSource(); - /** Destructor. */ - ~ChannelRemappingAudioSource(); + void setNumberOfChannelsToProduce (const int requiredNumberOfChannels) throw(); - /** Specifies a number of channels that this audio source must produce from its - getNextAudioBlock() callback. - */ - void setNumberOfChannelsToProduce (const int requiredNumberOfChannels) throw(); + void clearAllMappings() throw(); - /** Clears any mapped channels. + void setInputChannelMapping (const int destChannelIndex, + const int sourceChannelIndex) throw(); - After this, no channels are mapped, so this object will produce silence. Create - some mappings with setInputChannelMapping() and setOutputChannelMapping(). - */ - void clearAllMappings() throw(); + void setOutputChannelMapping (const int sourceChannelIndex, + const int destChannelIndex) throw(); - /** Creates an input channel mapping. + int getRemappedInputChannel (const int inputChannelIndex) const throw(); - When the getNextAudioBlock() method is called, the data in channel sourceChannelIndex of the incoming - data will be sent to destChannelIndex of our input source. + int getRemappedOutputChannel (const int outputChannelIndex) const throw(); - @param destChannelIndex the index of an input channel in our input audio source (i.e. the - source specified when this object was created). - @param sourceChannelIndex the index of the input channel in the incoming audio data buffer - during our getNextAudioBlock() callback - */ - void setInputChannelMapping (const int destChannelIndex, - const int sourceChannelIndex) throw(); + XmlElement* createXml() const throw(); - /** Creates an output channel mapping. + void restoreFromXml (const XmlElement& e) throw(); - When the getNextAudioBlock() method is called, the data returned in channel sourceChannelIndex by - our input audio source will be copied to channel destChannelIndex of the final buffer. + void prepareToPlay (int samplesPerBlockExpected, double sampleRate); + void releaseResources(); + void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - @param sourceChannelIndex the index of an output channel coming from our input audio source - (i.e. the source specified when this object was created). - @param destChannelIndex the index of the output channel in the incoming audio data buffer - during our getNextAudioBlock() callback - */ - void setOutputChannelMapping (const int sourceChannelIndex, - const int destChannelIndex) throw(); - - /** Returns the channel from our input that will be sent to channel inputChannelIndex of - our input audio source. - */ - int getRemappedInputChannel (const int inputChannelIndex) const throw(); - - /** Returns the output channel to which channel outputChannelIndex of our input audio - source will be sent to. - */ - int getRemappedOutputChannel (const int outputChannelIndex) const throw(); - - /** Returns an XML object to encapsulate the state of the mappings. - - @see restoreFromXml - */ - XmlElement* createXml() const throw(); - - /** Restores the mappings from an XML object created by createXML(). - - @see createXml - */ - void restoreFromXml (const XmlElement& e) throw(); - - void prepareToPlay (int samplesPerBlockExpected, double sampleRate); - void releaseResources(); - void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - int requiredNumberOfChannels; - Array remappedInputs, remappedOutputs; + int requiredNumberOfChannels; + Array remappedInputs, remappedOutputs; - AudioSource* const source; - const bool deleteSourceWhenDeleted; + AudioSource* const source; + const bool deleteSourceWhenDeleted; - AudioSampleBuffer buffer; - AudioSourceChannelInfo remappedInfo; + AudioSampleBuffer buffer; + AudioSourceChannelInfo remappedInfo; - CriticalSection lock; + CriticalSection lock; - ChannelRemappingAudioSource (const ChannelRemappingAudioSource&); - const ChannelRemappingAudioSource& operator= (const ChannelRemappingAudioSource&); + ChannelRemappingAudioSource (const ChannelRemappingAudioSource&); + const ChannelRemappingAudioSource& operator= (const ChannelRemappingAudioSource&); }; #endif // __JUCE_CHANNELREMAPPINGAUDIOSOURCE_JUCEHEADER__ @@ -29887,158 +14398,92 @@ private: #ifndef __JUCE_IIRFILTER_JUCEHEADER__ #define __JUCE_IIRFILTER_JUCEHEADER__ -/** - An IIR filter that can perform low, high, or band-pass filtering on an - audio signal. - - @see IIRFilterAudioSource -*/ class JUCE_API IIRFilter { public: - /** Creates a filter. + IIRFilter() throw(); - Initially the filter is inactive, so will have no effect on samples that - you process with it. Use the appropriate method to turn it into the type - of filter needed. - */ - IIRFilter() throw(); + IIRFilter (const IIRFilter& other) throw(); - /** Creates a copy of another filter. */ - IIRFilter (const IIRFilter& other) throw(); + ~IIRFilter() throw(); - /** Destructor. */ - ~IIRFilter() throw(); + void reset() throw(); - /** Resets the filter's processing pipeline, ready to start a new stream of data. + void processSamples (float* const samples, + const int numSamples) throw(); - Note that this clears the processing state, but the type of filter and - its coefficients aren't changed. To put a filter into an inactive state, use - the makeInactive() method. - */ - void reset() throw(); + float processSingleSampleRaw (const float sample) throw(); - /** Performs the filter operation on the given set of samples. - */ - void processSamples (float* const samples, - const int numSamples) throw(); + void makeLowPass (const double sampleRate, + const double frequency) throw(); - /** Processes a single sample, without any locking or checking. + void makeHighPass (const double sampleRate, + const double frequency) throw(); - Use this if you need fast processing of a single value, but be aware that - this isn't thread-safe in the way that processSamples() is. - */ - float processSingleSampleRaw (const float sample) throw(); + void makeLowShelf (const double sampleRate, + const double cutOffFrequency, + const double Q, + const float gainFactor) throw(); - /** Sets the filter up to act as a low-pass filter. - */ - void makeLowPass (const double sampleRate, - const double frequency) throw(); + void makeHighShelf (const double sampleRate, + const double cutOffFrequency, + const double Q, + const float gainFactor) throw(); - /** Sets the filter up to act as a high-pass filter. - */ - void makeHighPass (const double sampleRate, - const double frequency) throw(); + void makeBandPass (const double sampleRate, + const double centreFrequency, + const double Q, + const float gainFactor) throw(); - /** Sets the filter up to act as a low-pass shelf filter with variable Q and gain. + void makeInactive() throw(); - The gain is a scale factor that the low frequencies are multiplied by, so values - greater than 1.0 will boost the low frequencies, values less than 1.0 will - attenuate them. - */ - void makeLowShelf (const double sampleRate, - const double cutOffFrequency, - const double Q, - const float gainFactor) throw(); + void copyCoefficientsFrom (const IIRFilter& other) throw(); - /** Sets the filter up to act as a high-pass shelf filter with variable Q and gain. - - The gain is a scale factor that the high frequencies are multiplied by, so values - greater than 1.0 will boost the high frequencies, values less than 1.0 will - attenuate them. - */ - void makeHighShelf (const double sampleRate, - const double cutOffFrequency, - const double Q, - const float gainFactor) throw(); - - /** Sets the filter up to act as a band pass filter centred around a - frequency, with a variable Q and gain. - - The gain is a scale factor that the centre frequencies are multiplied by, so - values greater than 1.0 will boost the centre frequencies, values less than - 1.0 will attenuate them. - */ - void makeBandPass (const double sampleRate, - const double centreFrequency, - const double Q, - const float gainFactor) throw(); - - /** Clears the filter's coefficients so that it becomes inactive. - */ - void makeInactive() throw(); - - /** Makes this filter duplicate the set-up of another one. - */ - void copyCoefficientsFrom (const IIRFilter& other) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - CriticalSection processLock; + CriticalSection processLock; - void setCoefficients (double c1, double c2, double c3, - double c4, double c5, double c6) throw(); + void setCoefficients (double c1, double c2, double c3, + double c4, double c5, double c6) throw(); - bool active; - float coefficients[6]; - float x1, x2, y1, y2; + bool active; + float coefficients[6]; + float x1, x2, y1, y2; - // (use the copyCoefficientsFrom() method instead of this operator) - const IIRFilter& operator= (const IIRFilter&); + // (use the copyCoefficientsFrom() method instead of this operator) + const IIRFilter& operator= (const IIRFilter&); }; #endif // __JUCE_IIRFILTER_JUCEHEADER__ /********* End of inlined file: juce_IIRFilter.h *********/ -/** - An AudioSource that performs an IIR filter on another source. -*/ class JUCE_API IIRFilterAudioSource : public AudioSource { public: - /** Creates a IIRFilterAudioSource for a given input source. + IIRFilterAudioSource (AudioSource* const inputSource, + const bool deleteInputWhenDeleted); - @param inputSource the input source to read from - @param deleteInputWhenDeleted if true, the input source will be deleted when - this object is deleted - */ - IIRFilterAudioSource (AudioSource* const inputSource, - const bool deleteInputWhenDeleted); + ~IIRFilterAudioSource(); - /** Destructor. */ - ~IIRFilterAudioSource(); + void setFilterParameters (const IIRFilter& newSettings); - /** Changes the filter to use the same parameters as the one being passed in. - */ - void setFilterParameters (const IIRFilter& newSettings); + void prepareToPlay (int samplesPerBlockExpected, double sampleRate); + void releaseResources(); + void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - void prepareToPlay (int samplesPerBlockExpected, double sampleRate); - void releaseResources(); - void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioSource* const input; - const bool deleteInputWhenDeleted; - OwnedArray iirFilters; + AudioSource* const input; + const bool deleteInputWhenDeleted; + OwnedArray iirFilters; - IIRFilterAudioSource (const IIRFilterAudioSource&); - const IIRFilterAudioSource& operator= (const IIRFilterAudioSource&); + IIRFilterAudioSource (const IIRFilterAudioSource&); + const IIRFilterAudioSource& operator= (const IIRFilterAudioSource&); }; #endif // __JUCE_IIRFILTERAUDIOSOURCE_JUCEHEADER__ @@ -30051,89 +14496,41 @@ private: #ifndef __JUCE_MIXERAUDIOSOURCE_JUCEHEADER__ #define __JUCE_MIXERAUDIOSOURCE_JUCEHEADER__ -/** - An AudioSource that mixes together the output of a set of other AudioSources. - - Input sources can be added and removed while the mixer is running as long as their - prepareToPlay() and releaseResources() methods are called before and after adding - them to the mixer. -*/ class JUCE_API MixerAudioSource : public AudioSource { public: - /** Creates a MixerAudioSource. - */ - MixerAudioSource(); + MixerAudioSource(); - /** Destructor. */ - ~MixerAudioSource(); + ~MixerAudioSource(); - /** Adds an input source to the mixer. + void addInputSource (AudioSource* newInput, + const bool deleteWhenRemoved); - If the mixer is running you'll need to make sure that the input source - is ready to play by calling its prepareToPlay() method before adding it. - If the mixer is stopped, then its input sources will be automatically - prepared when the mixer's prepareToPlay() method is called. + void removeInputSource (AudioSource* input, + const bool deleteSource); - @param newInput the source to add to the mixer - @param deleteWhenRemoved if true, then this source will be deleted when - the mixer is deleted or when removeAllInputs() is - called (unless the source is previously removed - with the removeInputSource method) - */ - void addInputSource (AudioSource* newInput, - const bool deleteWhenRemoved); + void removeAllInputs(); - /** Removes an input source. + void prepareToPlay (int samplesPerBlockExpected, double sampleRate); - If the mixer is running, this will remove the source but not call its - releaseResources() method, so the caller might want to do this manually. + void releaseResources(); - @param input the source to remove - @param deleteSource whether to delete this source after it's been removed - */ - void removeInputSource (AudioSource* input, - const bool deleteSource); + void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - /** Removes all the input sources. - - If the mixer is running, this will remove the sources but not call their - releaseResources() method, so the caller might want to do this manually. - - Any sources which were added with the deleteWhenRemoved flag set will be - deleted by this method. - */ - void removeAllInputs(); - - /** Implementation of the AudioSource method. - - This will call prepareToPlay() on all its input sources. - */ - void prepareToPlay (int samplesPerBlockExpected, double sampleRate); - - /** Implementation of the AudioSource method. - - This will call releaseResources() on all its input sources. - */ - void releaseResources(); - - /** Implementation of the AudioSource method. */ - void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - VoidArray inputs; - BitArray inputsToDelete; - CriticalSection lock; - AudioSampleBuffer tempBuffer; - double currentSampleRate; - int bufferSizeExpected; + VoidArray inputs; + BitArray inputsToDelete; + CriticalSection lock; + AudioSampleBuffer tempBuffer; + double currentSampleRate; + int bufferSizeExpected; - MixerAudioSource (const MixerAudioSource&); - const MixerAudioSource& operator= (const MixerAudioSource&); + MixerAudioSource (const MixerAudioSource&); + const MixerAudioSource& operator= (const MixerAudioSource&); }; #endif // __JUCE_MIXERAUDIOSOURCE_JUCEHEADER__ @@ -30152,45 +14549,34 @@ private: #ifndef __JUCE_TONEGENERATORAUDIOSOURCE_JUCEHEADER__ #define __JUCE_TONEGENERATORAUDIOSOURCE_JUCEHEADER__ -/** - A simple AudioSource that generates a sine wave. - -*/ class JUCE_API ToneGeneratorAudioSource : public AudioSource { public: - /** Creates a ToneGeneratorAudioSource. */ - ToneGeneratorAudioSource(); + ToneGeneratorAudioSource(); - /** Destructor. */ - ~ToneGeneratorAudioSource(); + ~ToneGeneratorAudioSource(); - /** Sets the signal's amplitude. */ - void setAmplitude (const float newAmplitude); + void setAmplitude (const float newAmplitude); - /** Sets the signal's frequency. */ - void setFrequency (const double newFrequencyHz); + void setFrequency (const double newFrequencyHz); - /** Implementation of the AudioSource method. */ - void prepareToPlay (int samplesPerBlockExpected, double sampleRate); + void prepareToPlay (int samplesPerBlockExpected, double sampleRate); - /** Implementation of the AudioSource method. */ - void releaseResources(); + void releaseResources(); - /** Implementation of the AudioSource method. */ - void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); + void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - double frequency, sampleRate; - double currentPhase, phasePerSample; - float amplitude; + double frequency, sampleRate; + double currentPhase, phasePerSample; + float amplitude; - ToneGeneratorAudioSource (const ToneGeneratorAudioSource&); - const ToneGeneratorAudioSource& operator= (const ToneGeneratorAudioSource&); + ToneGeneratorAudioSource (const ToneGeneratorAudioSource&); + const ToneGeneratorAudioSource& operator= (const ToneGeneratorAudioSource&); }; #endif // __JUCE_TONEGENERATORAUDIOSOURCE_JUCEHEADER__ @@ -30210,111 +14596,43 @@ private: class AudioDeviceManager; class Component; -/** - Represents a type of audio driver, such as DirectSound, ASIO, CoreAudio, etc. - - To get a list of available audio driver types, use the createDeviceTypes() - method. Each of the objects returned can then be used to list the available - devices of that type. E.g. - @code - OwnedArray types; - AudioIODeviceType::createDeviceTypes (types); - - for (int i = 0; i < types.size(); ++i) - { - String typeName (types[i]->getTypeName()); // This will be things like "DirectSound", "CoreAudio", etc. - - types[i]->scanForDevices(); // This must be called before getting the list of devices - - StringArray deviceNames (types[i]->getDeviceNames()); // This will now return a list of available devices of this type - - for (int j = 0; j < deviceNames.size(); ++j) - { - AudioIODevice* device = types[i]->createDevice (deviceNames [j]); - - ... - } - } - @endcode - - For an easier way of managing audio devices and their settings, have a look at the - AudioDeviceManager class. - - @see AudioIODevice, AudioDeviceManager -*/ class JUCE_API AudioIODeviceType { public: - /** Returns the name of this type of driver that this object manages. + const String& getTypeName() const throw() { return typeName; } - This will be something like "DirectSound", "ASIO", "CoreAudio", "ALSA", etc. - */ - const String& getTypeName() const throw() { return typeName; } + virtual void scanForDevices() = 0; - /** Refreshes the object's cached list of known devices. + virtual const StringArray getDeviceNames (const bool wantInputNames = false) const = 0; - This must be called at least once before calling getDeviceNames() or any of - the other device creation methods. - */ - virtual void scanForDevices() = 0; + virtual int getDefaultDeviceIndex (const bool forInput) const = 0; - /** Returns the list of available devices of this type. + virtual int getIndexOfDevice (AudioIODevice* device, const bool asInput) const = 0; - The scanForDevices() method must have been called to create this list. + virtual bool hasSeparateInputsAndOutputs() const = 0; - @param wantInputNames only really used by DirectSound where devices are split up - into inputs and outputs, this indicates whether to use - the input or output name to refer to a pair of devices. - */ - virtual const StringArray getDeviceNames (const bool wantInputNames = false) const = 0; + virtual AudioIODevice* createDevice (const String& outputDeviceName, + const String& inputDeviceName) = 0; - /** Returns the name of the default device. + struct DeviceSetupDetails + { + AudioDeviceManager* manager; + int minNumInputChannels, maxNumInputChannels; + int minNumOutputChannels, maxNumOutputChannels; + bool useStereoPairs; + }; - This will be one of the names from the getDeviceNames() list. - - @param forInput if true, this means that a default input device should be - returned; if false, it should return the default output - */ - virtual int getDefaultDeviceIndex (const bool forInput) const = 0; - - /** Returns the index of a given device in the list of device names. - If asInput is true, it shows the index in the inputs list, otherwise it - looks for it in the outputs list. - */ - virtual int getIndexOfDevice (AudioIODevice* device, const bool asInput) const = 0; - - /** Returns true if two different devices can be used for the input and output. - */ - virtual bool hasSeparateInputsAndOutputs() const = 0; - - /** Creates one of the devices of this type. - - The deviceName must be one of the strings returned by getDeviceNames(), and - scanForDevices() must have been called before this method is used. - */ - virtual AudioIODevice* createDevice (const String& outputDeviceName, - const String& inputDeviceName) = 0; - - struct DeviceSetupDetails - { - AudioDeviceManager* manager; - int minNumInputChannels, maxNumInputChannels; - int minNumOutputChannels, maxNumOutputChannels; - bool useStereoPairs; - }; - - /** Destructor. */ - virtual ~AudioIODeviceType(); + virtual ~AudioIODeviceType(); protected: - AudioIODeviceType (const tchar* const typeName); + AudioIODeviceType (const tchar* const typeName); private: - String typeName; + String typeName; - AudioIODeviceType (const AudioIODeviceType&); - const AudioIODeviceType& operator= (const AudioIODeviceType&); + AudioIODeviceType (const AudioIODeviceType&); + const AudioIODeviceType& operator= (const AudioIODeviceType&); }; #endif // __JUCE_AUDIOIODEVICETYPE_JUCEHEADER__ @@ -30328,868 +14646,301 @@ private: #ifndef __JUCE_MIDIMESSAGE_JUCEHEADER__ #define __JUCE_MIDIMESSAGE_JUCEHEADER__ -/** - Encapsulates a MIDI message. - - @see MidiMessageSequence, MidiOutput, MidiInput -*/ class JUCE_API MidiMessage { public: - /** Creates a 3-byte short midi message. - - @param byte1 message byte 1 - @param byte2 message byte 2 - @param byte3 message byte 3 - @param timeStamp the time to give the midi message - this value doesn't - use any particular units, so will be application-specific - */ - MidiMessage (const int byte1, - const int byte2, - const int byte3, - const double timeStamp = 0) throw(); - - /** Creates a 2-byte short midi message. + MidiMessage (const int byte1, + const int byte2, + const int byte3, + const double timeStamp = 0) throw(); - @param byte1 message byte 1 - @param byte2 message byte 2 - @param timeStamp the time to give the midi message - this value doesn't - use any particular units, so will be application-specific - */ - MidiMessage (const int byte1, - const int byte2, - const double timeStamp = 0) throw(); - - /** Creates a 1-byte short midi message. + MidiMessage (const int byte1, + const int byte2, + const double timeStamp = 0) throw(); - @param byte1 message byte 1 - @param timeStamp the time to give the midi message - this value doesn't - use any particular units, so will be application-specific - */ - MidiMessage (const int byte1, - const double timeStamp = 0) throw(); + MidiMessage (const int byte1, + const double timeStamp = 0) throw(); - /** Creates a midi message from a block of data. */ - MidiMessage (const uint8* const data, - const int dataSize, - const double timeStamp = 0) throw(); + MidiMessage (const uint8* const data, + const int dataSize, + const double timeStamp = 0) throw(); - /** Reads the next midi message from some data. + MidiMessage (const uint8* data, + int size, + int& numBytesUsed, + uint8 lastStatusByte, + double timeStamp = 0) throw(); - This will read as many bytes from a data stream as it needs to make a - complete message, and will return the number of bytes it used. This lets - you read a sequence of midi messages from a file or stream. + MidiMessage (const MidiMessage& other) throw(); - @param data the data to read from - @param size the maximum number of bytes it's allowed to read - @param numBytesUsed returns the number of bytes that were actually needed - @param lastStatusByte in a sequence of midi messages, the initial byte - can be dropped from a message if it's the same as the - first byte of the previous message, so this lets you - supply the byte to use if the first byte of the message - has in fact been dropped. - @param timeStamp the time to give the midi message - this value doesn't - use any particular units, so will be application-specific - */ - MidiMessage (const uint8* data, - int size, - int& numBytesUsed, - uint8 lastStatusByte, - double timeStamp = 0) throw(); + MidiMessage (const MidiMessage& other, + const double newTimeStamp) throw(); - /** Creates a copy of another midi message. */ - MidiMessage (const MidiMessage& other) throw(); + ~MidiMessage() throw(); - /** Creates a copy of another midi message, with a different timestamp. */ - MidiMessage (const MidiMessage& other, - const double newTimeStamp) throw(); + const MidiMessage& operator= (const MidiMessage& other) throw(); - /** Destructor. */ - ~MidiMessage() throw(); + uint8* getRawData() const throw() { return data; } - /** Copies this message from another one. */ - const MidiMessage& operator= (const MidiMessage& other) throw(); + int getRawDataSize() const throw() { return size; } - /** Returns a pointer to the raw midi data. + double getTimeStamp() const throw() { return timeStamp; } - @see getRawDataSize - */ - uint8* getRawData() const throw() { return data; } + void setTimeStamp (const double newTimestamp) throw() { timeStamp = newTimestamp; } - /** Returns the number of bytes of data in the message. + void addToTimeStamp (const double delta) throw() { timeStamp += delta; } - @see getRawData - */ - int getRawDataSize() const throw() { return size; } + int getChannel() const throw(); - /** Returns the timestamp associated with this message. + bool isForChannel (const int channelNumber) const throw(); - The exact meaning of this time and its units will vary, as messages are used in - a variety of different contexts. + void setChannel (const int newChannelNumber) throw(); - If you're getting the message from a midi file, this could be a time in seconds, or - a number of ticks - see MidiFile::convertTimestampTicksToSeconds(). + bool isSysEx() const throw(); - If the message is being used in a MidiBuffer, it might indicate the number of - audio samples from the start of the buffer. + const uint8* getSysExData() const throw(); - If the message was created by a MidiInput, see MidiInputCallback::handleIncomingMidiMessage() - for details of the way that it initialises this value. + int getSysExDataSize() const throw(); - @see setTimeStamp, addToTimeStamp - */ - double getTimeStamp() const throw() { return timeStamp; } + bool isNoteOn (const bool returnTrueForVelocity0 = false) const throw(); - /** Changes the message's associated timestamp. + static const MidiMessage noteOn (const int channel, + const int noteNumber, + const float velocity) throw(); - The units for the timestamp will be application-specific - see the notes for getTimeStamp(). + static const MidiMessage noteOn (const int channel, + const int noteNumber, + const uint8 velocity) throw(); - @see addToTimeStamp, getTimeStamp - */ - void setTimeStamp (const double newTimestamp) throw() { timeStamp = newTimestamp; } + bool isNoteOff (const bool returnTrueForNoteOnVelocity0 = true) const throw(); - /** Adds a value to the message's timestamp. + static const MidiMessage noteOff (const int channel, + const int noteNumber) throw(); - The units for the timestamp will be application-specific. - */ - void addToTimeStamp (const double delta) throw() { timeStamp += delta; } + bool isNoteOnOrOff() const throw(); - /** Returns the midi channel associated with the message. + int getNoteNumber() const throw(); - @returns a value 1 to 16 if the message has a channel, or 0 if it hasn't (e.g. - if it's a sysex) - @see isForChannel, setChannel - */ - int getChannel() const throw(); + void setNoteNumber (const int newNoteNumber) throw(); - /** Returns true if the message applies to the given midi channel. + uint8 getVelocity() const throw(); - @param channelNumber the channel number to look for, in the range 1 to 16 - @see getChannel, setChannel - */ - bool isForChannel (const int channelNumber) const throw(); + float getFloatVelocity() const throw(); - /** Changes the message's midi channel. + void setVelocity (const float newVelocity) throw(); - This won't do anything for non-channel messages like sysexes. + void multiplyVelocity (const float scaleFactor) throw(); - @param newChannelNumber the channel number to change it to, in the range 1 to 16 - */ - void setChannel (const int newChannelNumber) throw(); + bool isProgramChange() const throw(); - /** Returns true if this is a system-exclusive message. - */ - bool isSysEx() const throw(); + int getProgramChangeNumber() const throw(); - /** Returns a pointer to the sysex data inside the message. + static const MidiMessage programChange (const int channel, + const int programNumber) throw(); - If this event isn't a sysex event, it'll return 0. + bool isPitchWheel() const throw(); - @see getSysExDataSize - */ - const uint8* getSysExData() const throw(); + int getPitchWheelValue() const throw(); - /** Returns the size of the sysex data. + static const MidiMessage pitchWheel (const int channel, + const int position) throw(); - This value excludes the 0xf0 header byte and the 0xf7 at the end. + bool isAftertouch() const throw(); - @see getSysExData - */ - int getSysExDataSize() const throw(); + int getAfterTouchValue() const throw(); - /** Returns true if this message is a 'key-down' event. + static const MidiMessage aftertouchChange (const int channel, + const int noteNumber, + const int aftertouchAmount) throw(); - @param returnTrueForVelocity0 if true, then if this event is a note-on with - velocity 0, it will still be considered to be a note-on and the - method will return true. If returnTrueForVelocity0 is false, then - if this is a note-on event with velocity 0, it'll be regarded as - a note-off, and the method will return false + bool isChannelPressure() const throw(); - @see isNoteOff, getNoteNumber, getVelocity, noteOn - */ - bool isNoteOn (const bool returnTrueForVelocity0 = false) const throw(); + int getChannelPressureValue() const throw(); - /** Creates a key-down message (using a floating-point velocity). + static const MidiMessage channelPressureChange (const int channel, + const int pressure) throw(); - @param channel the midi channel, in the range 1 to 16 - @param noteNumber the key number, 0 to 127 - @param velocity in the range 0 to 1.0 - @see isNoteOn - */ - static const MidiMessage noteOn (const int channel, - const int noteNumber, - const float velocity) throw(); + bool isController() const throw(); - /** Creates a key-down message (using an integer velocity). + int getControllerNumber() const throw(); - @param channel the midi channel, in the range 1 to 16 - @param noteNumber the key number, 0 to 127 - @param velocity in the range 0 to 127 - @see isNoteOn - */ - static const MidiMessage noteOn (const int channel, - const int noteNumber, - const uint8 velocity) throw(); + int getControllerValue() const throw(); - /** Returns true if this message is a 'key-up' event. + static const MidiMessage controllerEvent (const int channel, + const int controllerType, + const int value) throw(); - If returnTrueForNoteOnVelocity0 is true, then his will also return true - for a note-on event with a velocity of 0. + bool isAllNotesOff() const throw(); - @see isNoteOn, getNoteNumber, getVelocity, noteOff - */ - bool isNoteOff (const bool returnTrueForNoteOnVelocity0 = true) const throw(); + bool isAllSoundOff() const throw(); - /** Creates a key-up message. + static const MidiMessage allNotesOff (const int channel) throw(); - @param channel the midi channel, in the range 1 to 16 - @param noteNumber the key number, 0 to 127 - @see isNoteOff - */ - static const MidiMessage noteOff (const int channel, - const int noteNumber) throw(); + static const MidiMessage allSoundOff (const int channel) throw(); - /** Returns true if this message is a 'key-down' or 'key-up' event. + static const MidiMessage allControllersOff (const int channel) throw(); - @see isNoteOn, isNoteOff - */ - bool isNoteOnOrOff() const throw(); + bool isMetaEvent() const throw(); - /** Returns the midi note number for note-on and note-off messages. + int getMetaEventType() const throw(); - If the message isn't a note-on or off, the value returned will be - meaningless. + const uint8* getMetaEventData() const throw(); - @see isNoteOff, getMidiNoteName, getMidiNoteInHertz, setNoteNumber - */ - int getNoteNumber() const throw(); + int getMetaEventLength() const throw(); - /** Changes the midi note number of a note-on or note-off message. + bool isTrackMetaEvent() const throw(); - If the message isn't a note on or off, this will do nothing. - */ - void setNoteNumber (const int newNoteNumber) throw(); + bool isEndOfTrackMetaEvent() const throw(); - /** Returns the velocity of a note-on or note-off message. + static const MidiMessage endOfTrack() throw(); - The value returned will be in the range 0 to 127. + bool isTrackNameEvent() const throw(); - If the message isn't a note-on or off event, it will return 0. + bool isTextMetaEvent() const throw(); - @see getFloatVelocity - */ - uint8 getVelocity() const throw(); + const String getTextFromTextMetaEvent() const throw(); - /** Returns the velocity of a note-on or note-off message. + bool isTempoMetaEvent() const throw(); - The value returned will be in the range 0 to 1.0 + double getTempoMetaEventTickLength (const short timeFormat) const throw(); - If the message isn't a note-on or off event, it will return 0. + double getTempoSecondsPerQuarterNote() const throw(); - @see getVelocity, setVelocity - */ - float getFloatVelocity() const throw(); + static const MidiMessage tempoMetaEvent (const int microsecondsPerQuarterNote) throw(); - /** Changes the velocity of a note-on or note-off message. + bool isTimeSignatureMetaEvent() const throw(); - If the message isn't a note on or off, this will do nothing. + void getTimeSignatureInfo (int& numerator, + int& denominator) const throw(); - @param newVelocity the new velocity, in the range 0 to 1.0 - @see getFloatVelocity, multiplyVelocity - */ - void setVelocity (const float newVelocity) throw(); + static const MidiMessage timeSignatureMetaEvent (const int numerator, + const int denominator) throw(); - /** Multiplies the velocity of a note-on or note-off message by a given amount. + bool isKeySignatureMetaEvent() const throw(); - If the message isn't a note on or off, this will do nothing. + int getKeySignatureNumberOfSharpsOrFlats() const throw(); - @param scaleFactor the value by which to multiply the velocity - @see setVelocity - */ - void multiplyVelocity (const float scaleFactor) throw(); + bool isMidiChannelMetaEvent() const throw(); - /** Returns true if the message is a program (patch) change message. + int getMidiChannelMetaEventChannel() const throw(); - @see getProgramChangeNumber, getGMInstrumentName - */ - bool isProgramChange() const throw(); + static const MidiMessage midiChannelMetaEvent (const int channel) throw(); - /** Returns the new program number of a program change message. + bool isActiveSense() const throw(); - If the message isn't a program change, the value returned will be - nonsense. + bool isMidiStart() const throw(); - @see isProgramChange, getGMInstrumentName - */ - int getProgramChangeNumber() const throw(); + static const MidiMessage midiStart() throw(); - /** Creates a program-change message. + bool isMidiContinue() const throw(); - @param channel the midi channel, in the range 1 to 16 - @param programNumber the midi program number, 0 to 127 - @see isProgramChange, getGMInstrumentName - */ - static const MidiMessage programChange (const int channel, - const int programNumber) throw(); + static const MidiMessage midiContinue() throw(); - /** Returns true if the message is a pitch-wheel move. + bool isMidiStop() const throw(); - @see getPitchWheelValue, pitchWheel - */ - bool isPitchWheel() const throw(); + static const MidiMessage midiStop() throw(); - /** Returns the pitch wheel position from a pitch-wheel move message. + bool isMidiClock() const throw(); - The value returned is a 14-bit number from 0 to 0x3fff, indicating the wheel position. - If called for messages which aren't pitch wheel events, the number returned will be - nonsense. + static const MidiMessage midiClock() throw(); - @see isPitchWheel - */ - int getPitchWheelValue() const throw(); + bool isSongPositionPointer() const throw(); - /** Creates a pitch-wheel move message. + int getSongPositionPointerMidiBeat() const throw(); - @param channel the midi channel, in the range 1 to 16 - @param position the wheel position, in the range 0 to 16383 - @see isPitchWheel - */ - static const MidiMessage pitchWheel (const int channel, - const int position) throw(); + static const MidiMessage songPositionPointer (const int positionInMidiBeats) throw(); - /** Returns true if the message is an aftertouch event. + bool isQuarterFrame() const throw(); - For aftertouch events, use the getNoteNumber() method to find out the key - that it applies to, and getAftertouchValue() to find out the amount. Use - getChannel() to find out the channel. + int getQuarterFrameSequenceNumber() const throw(); - @see getAftertouchValue, getNoteNumber - */ - bool isAftertouch() const throw(); + int getQuarterFrameValue() const throw(); - /** Returns the amount of aftertouch from an aftertouch messages. + static const MidiMessage quarterFrame (const int sequenceNumber, + const int value) throw(); - The value returned is in the range 0 to 127, and will be nonsense for messages - other than aftertouch messages. + enum SmpteTimecodeType + { + fps24 = 0, + fps25 = 1, + fps30drop = 2, + fps30 = 3 + }; - @see isAftertouch - */ - int getAfterTouchValue() const throw(); + bool isFullFrame() const throw(); - /** Creates an aftertouch message. + void getFullFrameParameters (int& hours, + int& minutes, + int& seconds, + int& frames, + SmpteTimecodeType& timecodeType) const throw(); - @param channel the midi channel, in the range 1 to 16 - @param noteNumber the key number, 0 to 127 - @param aftertouchAmount the amount of aftertouch, 0 to 127 - @see isAftertouch - */ - static const MidiMessage aftertouchChange (const int channel, - const int noteNumber, - const int aftertouchAmount) throw(); + static const MidiMessage fullFrame (const int hours, + const int minutes, + const int seconds, + const int frames, + SmpteTimecodeType timecodeType); - /** Returns true if the message is a channel-pressure change event. + enum MidiMachineControlCommand + { + mmc_stop = 1, + mmc_play = 2, + mmc_deferredplay = 3, + mmc_fastforward = 4, + mmc_rewind = 5, + mmc_recordStart = 6, + mmc_recordStop = 7, + mmc_pause = 9 + }; - This is like aftertouch, but common to the whole channel rather than a specific - note. Use getChannelPressureValue() to find out the pressure, and getChannel() - to find out the channel. + bool isMidiMachineControlMessage() const throw(); - @see channelPressureChange - */ - bool isChannelPressure() const throw(); + MidiMachineControlCommand getMidiMachineControlCommand() const throw(); - /** Returns the pressure from a channel pressure change message. + static const MidiMessage midiMachineControlCommand (MidiMachineControlCommand command); - @returns the pressure, in the range 0 to 127 - @see isChannelPressure, channelPressureChange - */ - int getChannelPressureValue() const throw(); + bool isMidiMachineControlGoto (int& hours, + int& minutes, + int& seconds, + int& frames) const throw(); - /** Creates a channel-pressure change event. + static const MidiMessage midiMachineControlGoto (int hours, + int minutes, + int seconds, + int frames); - @param channel the midi channel: 1 to 16 - @param pressure the pressure, 0 to 127 - @see isChannelPressure - */ - static const MidiMessage channelPressureChange (const int channel, - const int pressure) throw(); + static const MidiMessage masterVolume (const float volume) throw(); - /** Returns true if this is a midi controller message. + static const MidiMessage createSysExMessage (const uint8* sysexData, + const int dataSize) throw(); - @see getControllerNumber, getControllerValue, controllerEvent - */ - bool isController() const throw(); + static int readVariableLengthVal (const uint8* data, + int& numBytesUsed) throw(); - /** Returns the controller number of a controller message. + static int getMessageLengthFromFirstByte (const uint8 firstByte) throw(); - The name of the controller can be looked up using the getControllerName() method. + static const String getMidiNoteName (int noteNumber, + bool useSharps, + bool includeOctaveNumber, + int octaveNumForMiddleC) throw(); - Note that the value returned is invalid for messages that aren't controller changes. + static const double getMidiNoteInHertz (int noteNumber) throw(); - @see isController, getControllerName, getControllerValue - */ - int getControllerNumber() const throw(); + static const String getGMInstrumentName (int midiInstrumentNumber) throw(); - /** Returns the controller value from a controller message. + static const String getGMInstrumentBankName (int midiBankNumber) throw(); - A value 0 to 127 is returned to indicate the new controller position. + static const String getRhythmInstrumentName (int midiNoteNumber) throw(); - Note that the value returned is invalid for messages that aren't controller changes. + static const String getControllerName (int controllerNumber) throw(); - @see isController, getControllerNumber - */ - int getControllerValue() const throw(); - - /** Creates a controller message. - - @param channel the midi channel, in the range 1 to 16 - @param controllerType the type of controller - @param value the controller value - @see isController - */ - static const MidiMessage controllerEvent (const int channel, - const int controllerType, - const int value) throw(); - - /** Checks whether this message is an all-notes-off message. - - @see allNotesOff - */ - bool isAllNotesOff() const throw(); - - /** Checks whether this message is an all-sound-off message. - - @see allSoundOff - */ - bool isAllSoundOff() const throw(); - - /** Creates an all-notes-off message. - - @param channel the midi channel, in the range 1 to 16 - @see isAllNotesOff - */ - static const MidiMessage allNotesOff (const int channel) throw(); - - /** Creates an all-sound-off message. - - @param channel the midi channel, in the range 1 to 16 - @see isAllSoundOff - */ - static const MidiMessage allSoundOff (const int channel) throw(); - - /** Creates an all-controllers-off message. - - @param channel the midi channel, in the range 1 to 16 - */ - static const MidiMessage allControllersOff (const int channel) throw(); - - /** Returns true if this event is a meta-event. - - Meta-events are things like tempo changes, track names, etc. - - @see getMetaEventType, isTrackMetaEvent, isEndOfTrackMetaEvent, - isTextMetaEvent, isTrackNameEvent, isTempoMetaEvent, isTimeSignatureMetaEvent, - isKeySignatureMetaEvent, isMidiChannelMetaEvent - */ - bool isMetaEvent() const throw(); - - /** Returns a meta-event's type number. - - If the message isn't a meta-event, this will return -1. - - @see isMetaEvent, isTrackMetaEvent, isEndOfTrackMetaEvent, - isTextMetaEvent, isTrackNameEvent, isTempoMetaEvent, isTimeSignatureMetaEvent, - isKeySignatureMetaEvent, isMidiChannelMetaEvent - */ - int getMetaEventType() const throw(); - - /** Returns a pointer to the data in a meta-event. - - @see isMetaEvent, getMetaEventLength - */ - const uint8* getMetaEventData() const throw(); - - /** Returns the length of the data for a meta-event. - - @see isMetaEvent, getMetaEventData - */ - int getMetaEventLength() const throw(); - - /** Returns true if this is a 'track' meta-event. */ - bool isTrackMetaEvent() const throw(); - - /** Returns true if this is an 'end-of-track' meta-event. */ - bool isEndOfTrackMetaEvent() const throw(); - - /** Creates an end-of-track meta-event. - - @see isEndOfTrackMetaEvent - */ - static const MidiMessage endOfTrack() throw(); - - /** Returns true if this is an 'track name' meta-event. - - You can use the getTextFromTextMetaEvent() method to get the track's name. - */ - bool isTrackNameEvent() const throw(); - - /** Returns true if this is a 'text' meta-event. - - @see getTextFromTextMetaEvent - */ - bool isTextMetaEvent() const throw(); - - /** Returns the text from a text meta-event. - - @see isTextMetaEvent - */ - const String getTextFromTextMetaEvent() const throw(); - - /** Returns true if this is a 'tempo' meta-event. - - @see getTempoMetaEventTickLength, getTempoSecondsPerQuarterNote - */ - bool isTempoMetaEvent() const throw(); - - /** Returns the tick length from a tempo meta-event. - - @param timeFormat the 16-bit time format value from the midi file's header. - @returns the tick length (in seconds). - @see isTempoMetaEvent - */ - double getTempoMetaEventTickLength (const short timeFormat) const throw(); - - /** Calculates the seconds-per-quarter-note from a tempo meta-event. - - @see isTempoMetaEvent, getTempoMetaEventTickLength - */ - double getTempoSecondsPerQuarterNote() const throw(); - - /** Creates a tempo meta-event. - - @see isTempoMetaEvent - */ - static const MidiMessage tempoMetaEvent (const int microsecondsPerQuarterNote) throw(); - - /** Returns true if this is a 'time-signature' meta-event. - - @see getTimeSignatureInfo - */ - bool isTimeSignatureMetaEvent() const throw(); - - /** Returns the time-signature values from a time-signature meta-event. - - @see isTimeSignatureMetaEvent - */ - void getTimeSignatureInfo (int& numerator, - int& denominator) const throw(); - - /** Creates a time-signature meta-event. - - @see isTimeSignatureMetaEvent - */ - static const MidiMessage timeSignatureMetaEvent (const int numerator, - const int denominator) throw(); - - /** Returns true if this is a 'key-signature' meta-event. - - @see getKeySignatureNumberOfSharpsOrFlats - */ - bool isKeySignatureMetaEvent() const throw(); - - /** Returns the key from a key-signature meta-event. - - @see isKeySignatureMetaEvent - */ - int getKeySignatureNumberOfSharpsOrFlats() const throw(); - - /** Returns true if this is a 'channel' meta-event. - - A channel meta-event specifies the midi channel that should be used - for subsequent meta-events. - - @see getMidiChannelMetaEventChannel - */ - bool isMidiChannelMetaEvent() const throw(); - - /** Returns the channel number from a channel meta-event. - - @returns the channel, in the range 1 to 16. - @see isMidiChannelMetaEvent - */ - int getMidiChannelMetaEventChannel() const throw(); - - /** Creates a midi channel meta-event. - - @param channel the midi channel, in the range 1 to 16 - @see isMidiChannelMetaEvent - */ - static const MidiMessage midiChannelMetaEvent (const int channel) throw(); - - /** Returns true if this is an active-sense message. */ - bool isActiveSense() const throw(); - - /** Returns true if this is a midi start event. - - @see midiStart - */ - bool isMidiStart() const throw(); - - /** Creates a midi start event. */ - static const MidiMessage midiStart() throw(); - - /** Returns true if this is a midi continue event. - - @see midiContinue - */ - bool isMidiContinue() const throw(); - - /** Creates a midi continue event. */ - static const MidiMessage midiContinue() throw(); - - /** Returns true if this is a midi stop event. - - @see midiStop - */ - bool isMidiStop() const throw(); - - /** Creates a midi stop event. */ - static const MidiMessage midiStop() throw(); - - /** Returns true if this is a midi clock event. - - @see midiClock, songPositionPointer - */ - bool isMidiClock() const throw(); - - /** Creates a midi clock event. */ - static const MidiMessage midiClock() throw(); - - /** Returns true if this is a song-position-pointer message. - - @see getSongPositionPointerMidiBeat, songPositionPointer - */ - bool isSongPositionPointer() const throw(); - - /** Returns the midi beat-number of a song-position-pointer message. - - @see isSongPositionPointer, songPositionPointer - */ - int getSongPositionPointerMidiBeat() const throw(); - - /** Creates a song-position-pointer message. - - The position is a number of midi beats from the start of the song, where 1 midi - beat is 6 midi clocks, and there are 24 midi clocks in a quarter-note. So there - are 4 midi beats in a quarter-note. - - @see isSongPositionPointer, getSongPositionPointerMidiBeat - */ - static const MidiMessage songPositionPointer (const int positionInMidiBeats) throw(); - - /** Returns true if this is a quarter-frame midi timecode message. - - @see quarterFrame, getQuarterFrameSequenceNumber, getQuarterFrameValue - */ - bool isQuarterFrame() const throw(); - - /** Returns the sequence number of a quarter-frame midi timecode message. - - This will be a value between 0 and 7. - - @see isQuarterFrame, getQuarterFrameValue, quarterFrame - */ - int getQuarterFrameSequenceNumber() const throw(); - - /** Returns the value from a quarter-frame message. - - This will be the lower nybble of the message's data-byte, a value - between 0 and 15 - */ - int getQuarterFrameValue() const throw(); - - /** Creates a quarter-frame MTC message. - - @param sequenceNumber a value 0 to 7 for the upper nybble of the message's data byte - @param value a value 0 to 15 for the lower nybble of the message's data byte - */ - static const MidiMessage quarterFrame (const int sequenceNumber, - const int value) throw(); - - /** SMPTE timecode types. - - Used by the getFullFrameParameters() and fullFrame() methods. - */ - enum SmpteTimecodeType - { - fps24 = 0, - fps25 = 1, - fps30drop = 2, - fps30 = 3 - }; - - /** Returns true if this is a full-frame midi timecode message. - */ - bool isFullFrame() const throw(); - - /** Extracts the timecode information from a full-frame midi timecode message. - - You should only call this on messages where you've used isFullFrame() to - check that they're the right kind. - */ - void getFullFrameParameters (int& hours, - int& minutes, - int& seconds, - int& frames, - SmpteTimecodeType& timecodeType) const throw(); - - /** Creates a full-frame MTC message. - */ - static const MidiMessage fullFrame (const int hours, - const int minutes, - const int seconds, - const int frames, - SmpteTimecodeType timecodeType); - - /** Types of MMC command. - - @see isMidiMachineControlMessage, getMidiMachineControlCommand, midiMachineControlCommand - */ - enum MidiMachineControlCommand - { - mmc_stop = 1, - mmc_play = 2, - mmc_deferredplay = 3, - mmc_fastforward = 4, - mmc_rewind = 5, - mmc_recordStart = 6, - mmc_recordStop = 7, - mmc_pause = 9 - }; - - /** Checks whether this is an MMC message. - - If it is, you can use the getMidiMachineControlCommand() to find out its type. - */ - bool isMidiMachineControlMessage() const throw(); - - /** For an MMC message, this returns its type. - - Make sure it's actually an MMC message with isMidiMachineControlMessage() before - calling this method. - */ - MidiMachineControlCommand getMidiMachineControlCommand() const throw(); - - /** Creates an MMC message. - */ - static const MidiMessage midiMachineControlCommand (MidiMachineControlCommand command); - - /** Checks whether this is an MMC "goto" message. - - If it is, the parameters passed-in are set to the time that the message contains. - - @see midiMachineControlGoto - */ - bool isMidiMachineControlGoto (int& hours, - int& minutes, - int& seconds, - int& frames) const throw(); - - /** Creates an MMC "goto" message. - - This messages tells the device to go to a specific frame. - - @see isMidiMachineControlGoto - */ - static const MidiMessage midiMachineControlGoto (int hours, - int minutes, - int seconds, - int frames); - - /** Creates a master-volume change message. - - @param volume the volume, 0 to 1.0 - */ - static const MidiMessage masterVolume (const float volume) throw(); - - /** Creates a system-exclusive message. - - The data passed in is wrapped with header and tail bytes of 0xf0 and 0xf7. - */ - static const MidiMessage createSysExMessage (const uint8* sysexData, - const int dataSize) throw(); - - /** Reads a midi variable-length integer. - - @param data the data to read the number from - @param numBytesUsed on return, this will be set to the number of bytes that were read - */ - static int readVariableLengthVal (const uint8* data, - int& numBytesUsed) throw(); - - /** Based on the first byte of a short midi message, this uses a lookup table - to return the message length (either 1, 2, or 3 bytes). - - The value passed in must be 0x80 or higher. - */ - static int getMessageLengthFromFirstByte (const uint8 firstByte) throw(); - - /** Returns the name of a midi note number. - - E.g "C", "D#", etc. - - @param noteNumber the midi note number, 0 to 127 - @param useSharps if true, sharpened notes are used, e.g. "C#", otherwise - they'll be flattened, e.g. "Db" - @param includeOctaveNumber if true, the octave number will be appended to the string, - e.g. "C#4" - @param octaveNumForMiddleC if an octave number is being appended, this indicates the - number that will be used for middle C's octave - - @see getMidiNoteInHertz - */ - static const String getMidiNoteName (int noteNumber, - bool useSharps, - bool includeOctaveNumber, - int octaveNumForMiddleC) throw(); - - /** Returns the frequency of a midi note number. - - @see getMidiNoteName - */ - static const double getMidiNoteInHertz (int noteNumber) throw(); - - /** Returns the standard name of a GM instrument. - - @param midiInstrumentNumber the program number 0 to 127 - @see getProgramChangeNumber - */ - static const String getGMInstrumentName (int midiInstrumentNumber) throw(); - - /** Returns the name of a bank of GM instruments. - - @param midiBankNumber the bank, 0 to 15 - */ - static const String getGMInstrumentBankName (int midiBankNumber) throw(); - - /** Returns the standard name of a channel 10 percussion sound. - - @param midiNoteNumber the key number, 35 to 81 - */ - static const String getRhythmInstrumentName (int midiNoteNumber) throw(); - - /** Returns the name of a controller type number. - - @see getControllerNumber - */ - static const String getControllerName (int controllerNumber) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - double timeStamp; - uint8* data; - int message, size; + double timeStamp; + uint8* data; + int message, size; }; #endif // __JUCE_MIDIMESSAGE_JUCEHEADER__ @@ -31197,148 +14948,58 @@ private: class MidiInput; -/** - Receives midi messages from a midi input device. - - This class is overridden to handle incoming midi messages. See the MidiInput - class for more details. - - @see MidiInput -*/ class JUCE_API MidiInputCallback { public: - /** Destructor. */ - virtual ~MidiInputCallback() {} + virtual ~MidiInputCallback() {} - /** Receives an incoming message. + virtual void handleIncomingMidiMessage (MidiInput* source, + const MidiMessage& message) = 0; - A MidiInput object will call this method when a midi event arrives. It'll be - called on a high-priority system thread, so avoid doing anything time-consuming - in here, and avoid making any UI calls. You might find the MidiBuffer class helpful - for queueing incoming messages for use later. - - @param source the MidiInput object that generated the message - @param message the incoming message. The message's timestamp is set to a value - equivalent to (Time::getMillisecondCounter() / 1000.0) to specify the - time when the message arrived. - */ - virtual void handleIncomingMidiMessage (MidiInput* source, - const MidiMessage& message) = 0; - - /** Notification sent each time a packet of a multi-packet sysex message arrives. - - If a long sysex message is broken up into multiple packets, this callback is made - for each packet that arrives until the message is finished, at which point - the normal handleIncomingMidiMessage() callback will be made with the entire - message. - - The message passed in will contain the start of a sysex, but won't be finished - with the terminating 0xf7 byte. - */ - virtual void handlePartialSysexMessage (MidiInput* source, - const uint8* messageData, - const int numBytesSoFar, - const double timestamp) - { - // (this bit is just to avoid compiler warnings about unused variables) - (void) source; (void) messageData; (void) numBytesSoFar; (void) timestamp; - } + virtual void handlePartialSysexMessage (MidiInput* source, + const uint8* messageData, + const int numBytesSoFar, + const double timestamp) + { + // (this bit is just to avoid compiler warnings about unused variables) + (void) source; (void) messageData; (void) numBytesSoFar; (void) timestamp; + } }; -/** - Represents a midi input device. - - To create one of these, use the static getDevices() method to find out what inputs are - available, and then use the openDevice() method to try to open one. - - @see MidiOutput -*/ class JUCE_API MidiInput { public: - /** Returns a list of the available midi input devices. + static const StringArray getDevices(); - You can open one of the devices by passing its index into the - openDevice() method. + static int getDefaultDeviceIndex(); - @see getDefaultDeviceIndex, openDevice - */ - static const StringArray getDevices(); - - /** Returns the index of the default midi input device to use. - - This refers to the index in the list returned by getDevices(). - */ - static int getDefaultDeviceIndex(); - - /** Tries to open one of the midi input devices. - - This will return a MidiInput object if it manages to open it. You can then - call start() and stop() on this device, and delete it when no longer needed. - - If the device can't be opened, this will return a null pointer. - - @param deviceIndex the index of a device from the list returned by getDevices() - @param callback the object that will receive the midi messages from this device. - - @see MidiInputCallback, getDevices - */ - static MidiInput* openDevice (int deviceIndex, - MidiInputCallback* callback); + static MidiInput* openDevice (int deviceIndex, + MidiInputCallback* callback); #if JUCE_LINUX || JUCE_MAC || DOXYGEN - /** This will try to create a new midi input device (Not available on Windows). - - This will attempt to create a new midi input device with the specified name, - for other apps to connect to. - - Returns 0 if a device can't be created. - - @param deviceName the name to use for the new device - @param callback the object that will receive the midi messages from this device. - */ - static MidiInput* createNewDevice (const String& deviceName, - MidiInputCallback* callback); + static MidiInput* createNewDevice (const String& deviceName, + MidiInputCallback* callback); #endif - /** Destructor. */ - virtual ~MidiInput(); + virtual ~MidiInput(); - /** Returns the name of this device. - */ - virtual const String getName() const throw() { return name; } + virtual const String getName() const throw() { return name; } - /** Allows you to set a custom name for the device, in case you don't like the name - it was given when created. - */ - virtual void setName (const String& newName) throw() { name = newName; } + virtual void setName (const String& newName) throw() { name = newName; } - /** Starts the device running. + virtual void start(); - After calling this, the device will start sending midi messages to the - MidiInputCallback object that was specified when the openDevice() method - was called. + virtual void stop(); - @see stop - */ - virtual void start(); - - /** Stops the device running. - - @see start - */ - virtual void stop(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - String name; - void* internal; + String name; + void* internal; - MidiInput (const String& name); - MidiInput (const MidiInput&); + MidiInput (const String& name); + MidiInput (const MidiInput&); }; #endif // __JUCE_MIDIINPUT_JUCEHEADER__ @@ -31352,334 +15013,145 @@ protected: #ifndef __JUCE_MIDIBUFFER_JUCEHEADER__ #define __JUCE_MIDIBUFFER_JUCEHEADER__ -/** - Holds a sequence of time-stamped midi events. - - Analogous to the AudioSampleBuffer, this holds a set of midi events with - integer time-stamps. The buffer is kept sorted in order of the time-stamps. - - @see MidiMessage -*/ class JUCE_API MidiBuffer { public: - /** Creates an empty MidiBuffer. */ - MidiBuffer() throw(); + MidiBuffer() throw(); - /** Creates a MidiBuffer containing a single midi message. */ - MidiBuffer (const MidiMessage& message) throw(); + MidiBuffer (const MidiMessage& message) throw(); - /** Creates a copy of another MidiBuffer. */ - MidiBuffer (const MidiBuffer& other) throw(); + MidiBuffer (const MidiBuffer& other) throw(); - /** Makes a copy of another MidiBuffer. */ - const MidiBuffer& operator= (const MidiBuffer& other) throw(); + const MidiBuffer& operator= (const MidiBuffer& other) throw(); - /** Destructor */ - ~MidiBuffer() throw(); + ~MidiBuffer() throw(); - /** Removes all events from the buffer. */ - void clear() throw(); + void clear() throw(); - /** Removes all events between two times from the buffer. + void clear (const int start, + const int numSamples) throw(); - All events for which (start <= event position < start + numSamples) will - be removed. - */ - void clear (const int start, - const int numSamples) throw(); + bool isEmpty() const throw(); - /** Returns true if the buffer is empty. + int getNumEvents() const throw(); - To actually retrieve the events, use a MidiBuffer::Iterator object - */ - bool isEmpty() const throw(); + void addEvent (const MidiMessage& midiMessage, + const int sampleNumber) throw(); - /** Counts the number of events in the buffer. + void addEvent (const uint8* const rawMidiData, + const int maxBytesOfMidiData, + const int sampleNumber) throw(); - This is actually quite a slow operation, as it has to iterate through all - the events, so you might prefer to call isEmpty() if that's all you need - to know. - */ - int getNumEvents() const throw(); + void addEvents (const MidiBuffer& otherBuffer, + const int startSample, + const int numSamples, + const int sampleDeltaToAdd) throw(); - /** Adds an event to the buffer. + int getFirstEventTime() const throw(); - The sample number will be used to determine the position of the event in - the buffer, which is always kept sorted. The MidiMessage's timestamp is - ignored. + int getLastEventTime() const throw(); - If an event is added whose sample position is the same as one or more events - already in the buffer, the new event will be placed after the existing ones. + void swap (MidiBuffer& other); - To retrieve events, use a MidiBuffer::Iterator object - */ - void addEvent (const MidiMessage& midiMessage, - const int sampleNumber) throw(); + class Iterator + { + public: - /** Adds an event to the buffer from raw midi data. + Iterator (const MidiBuffer& buffer) throw(); - The sample number will be used to determine the position of the event in - the buffer, which is always kept sorted. + ~Iterator() throw(); - If an event is added whose sample position is the same as one or more events - already in the buffer, the new event will be placed after the existing ones. + void setNextSamplePosition (const int samplePosition) throw(); - The event data will be inspected to calculate the number of bytes in length that - the midi event really takes up, so maxBytesOfMidiData may be longer than the data - that actually gets stored. E.g. if you pass in a note-on and a length of 4 bytes, - it'll actually only store 3 bytes. If the midi data is invalid, it might not - add an event at all. + bool getNextEvent (MidiMessage& result, + int& samplePosition) throw(); - To retrieve events, use a MidiBuffer::Iterator object - */ - void addEvent (const uint8* const rawMidiData, - const int maxBytesOfMidiData, - const int sampleNumber) throw(); + bool getNextEvent (const uint8* &midiData, + int& numBytesOfMidiData, + int& samplePosition) throw(); - /** Adds some events from another buffer to this one. + juce_UseDebuggingNewOperator - @param otherBuffer the buffer containing the events you want to add - @param startSample the lowest sample number in the source buffer for which - events should be added. Any source events whose timestamp is - less than this will be ignored - @param numSamples the valid range of samples from the source buffer for which - events should be added - i.e. events in the source buffer whose - timestamp is greater than or equal to (startSample + numSamples) - will be ignored. If this value is less than 0, all events after - startSample will be taken. - @param sampleDeltaToAdd a value which will be added to the source timestamps of the events - that are added to this buffer - */ - void addEvents (const MidiBuffer& otherBuffer, - const int startSample, - const int numSamples, - const int sampleDeltaToAdd) throw(); + private: + const MidiBuffer& buffer; + const uint8* data; - /** Returns the sample number of the first event in the buffer. + Iterator (const Iterator&); + const Iterator& operator= (const Iterator&); + }; - If the buffer's empty, this will just return 0. - */ - int getFirstEventTime() const throw(); - - /** Returns the sample number of the last event in the buffer. - - If the buffer's empty, this will just return 0. - */ - int getLastEventTime() const throw(); - - /** Exchanges the contents of this buffer with another one. - - This is a quick operation, because no memory allocating or copying is done, it - just swaps the internal state of the two buffers. - */ - void swap (MidiBuffer& other); - - /** - Used to iterate through the events in a MidiBuffer. - - Note that altering the buffer while an iterator is using it isn't a - safe operation. - - @see MidiBuffer - */ - class Iterator - { - public: - - /** Creates an Iterator for this MidiBuffer. */ - Iterator (const MidiBuffer& buffer) throw(); - - /** Destructor. */ - ~Iterator() throw(); - - /** Repositions the iterator so that the next event retrieved will be the first - one whose sample position is at greater than or equal to the given position. - */ - void setNextSamplePosition (const int samplePosition) throw(); - - /** Retrieves a copy of the next event from the buffer. - - @param result on return, this will be the message (the MidiMessage's timestamp - is not set) - @param samplePosition on return, this will be the position of the event - @returns true if an event was found, or false if the iterator has reached - the end of the buffer - */ - bool getNextEvent (MidiMessage& result, - int& samplePosition) throw(); - - /** Retrieves the next event from the buffer. - - @param midiData on return, this pointer will be set to a block of data containing - the midi message. Note that to make it fast, this is a pointer - directly into the MidiBuffer's internal data, so is only valid - temporarily until the MidiBuffer is altered. - @param numBytesOfMidiData on return, this is the number of bytes of data used by the - midi message - @param samplePosition on return, this will be the position of the event - @returns true if an event was found, or false if the iterator has reached - the end of the buffer - */ - bool getNextEvent (const uint8* &midiData, - int& numBytesOfMidiData, - int& samplePosition) throw(); - - juce_UseDebuggingNewOperator - - private: - const MidiBuffer& buffer; - const uint8* data; - - Iterator (const Iterator&); - const Iterator& operator= (const Iterator&); - }; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class MidiBuffer::Iterator; - ArrayAllocationBase data; - int bytesUsed; + friend class MidiBuffer::Iterator; + MemoryBlock data; + int bytesUsed; - uint8* findEventAfter (uint8* d, const int samplePosition) const throw(); + uint8* findEventAfter (uint8* d, const int samplePosition) const throw(); }; #endif // __JUCE_MIDIBUFFER_JUCEHEADER__ /********* End of inlined file: juce_MidiBuffer.h *********/ -/** - Represents a midi output device. - - To create one of these, use the static getDevices() method to find out what - outputs are available, then use the openDevice() method to try to open one. - - @see MidiInput -*/ class JUCE_API MidiOutput : private Thread { public: - /** Returns a list of the available midi output devices. + static const StringArray getDevices(); - You can open one of the devices by passing its index into the - openDevice() method. + static int getDefaultDeviceIndex(); - @see getDefaultDeviceIndex, openDevice - */ - static const StringArray getDevices(); - - /** Returns the index of the default midi output device to use. - - This refers to the index in the list returned by getDevices(). - */ - static int getDefaultDeviceIndex(); - - /** Tries to open one of the midi output devices. - - This will return a MidiOutput object if it manages to open it. You can then - send messages to this device, and delete it when no longer needed. - - If the device can't be opened, this will return a null pointer. - - @param deviceIndex the index of a device from the list returned by getDevices() - @see getDevices - */ - static MidiOutput* openDevice (int deviceIndex); + static MidiOutput* openDevice (int deviceIndex); #if JUCE_LINUX || JUCE_MAC || DOXYGEN - /** This will try to create a new midi output device (Not available on Windows). - - This will attempt to create a new midi output device that other apps can connect - to and use as their midi input. - - Returns 0 if a device can't be created. - - @param deviceName the name to use for the new device - */ - static MidiOutput* createNewDevice (const String& deviceName); + static MidiOutput* createNewDevice (const String& deviceName); #endif - /** Destructor. */ - virtual ~MidiOutput(); + virtual ~MidiOutput(); - /** Makes this device output a midi message. + virtual void sendMessageNow (const MidiMessage& message); - @see MidiMessage - */ - virtual void sendMessageNow (const MidiMessage& message); + virtual void reset(); - /** Sends a midi reset to the device. */ - virtual void reset(); + virtual bool getVolume (float& leftVol, + float& rightVol); - /** Returns the current volume setting for this device. */ - virtual bool getVolume (float& leftVol, - float& rightVol); + virtual void setVolume (float leftVol, + float rightVol); - /** Changes the overall volume for this device. */ - virtual void setVolume (float leftVol, - float rightVol); + virtual void sendBlockOfMessages (const MidiBuffer& buffer, + const double millisecondCounterToStartAt, + double samplesPerSecondForBuffer) throw(); - /** This lets you supply a block of messages that will be sent out at some point - in the future. + virtual void clearAllPendingMessages() throw(); - The MidiOutput class has an internal thread that can send out timestamped - messages - this appends a set of messages to its internal buffer, ready for - sending. + virtual void startBackgroundThread() throw(); - This will only work if you've already started the thread with startBackgroundThread(). + virtual void stopBackgroundThread() throw(); - A time is supplied, at which the block of messages should be sent. This time uses - the same time base as Time::getMillisecondCounter(), and must be in the future. - - The samplesPerSecondForBuffer parameter indicates the number of samples per second - used by the MidiBuffer. Each event in a MidiBuffer has a sample position, and the - samplesPerSecondForBuffer value is needed to convert this sample position to a - real time. - */ - virtual void sendBlockOfMessages (const MidiBuffer& buffer, - const double millisecondCounterToStartAt, - double samplesPerSecondForBuffer) throw(); - - /** Gets rid of any midi messages that had been added by sendBlockOfMessages(). - */ - virtual void clearAllPendingMessages() throw(); - - /** Starts up a background thread so that the device can send blocks of data. - - Call this to get the device ready, before using sendBlockOfMessages(). - */ - virtual void startBackgroundThread() throw(); - - /** Stops the background thread, and clears any pending midi events. - - @see startBackgroundThread - */ - virtual void stopBackgroundThread() throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - void* internal; + void* internal; - struct PendingMessage - { - PendingMessage (const uint8* const data, const int len, const double sampleNumber) throw(); + struct PendingMessage + { + PendingMessage (const uint8* const data, const int len, const double sampleNumber) throw(); - MidiMessage message; - PendingMessage* next; + MidiMessage message; + PendingMessage* next; - juce_UseDebuggingNewOperator - }; + juce_UseDebuggingNewOperator + }; - CriticalSection lock; - PendingMessage* firstMessage; + CriticalSection lock; + PendingMessage* firstMessage; - MidiOutput() throw(); - MidiOutput (const MidiOutput&); + MidiOutput() throw(); + MidiOutput (const MidiOutput&); - void run(); + void run(); }; #endif // __JUCE_MIDIOUTPUT_JUCEHEADER__ @@ -31697,43 +15169,26 @@ protected: #ifndef __JUCE_COMPONENTDELETIONWATCHER_JUCEHEADER__ #define __JUCE_COMPONENTDELETIONWATCHER_JUCEHEADER__ -/** - Object for monitoring a component, and later testing whether it's still valid. - - Slightly obscure, this one, but it's used internally for making sure that - after some callbacks, a component hasn't been deleted. It's more reliable than - just using isValidComponent(), which can provide false-positives if a new - component is created at the same memory location as an old one. -*/ class JUCE_API ComponentDeletionWatcher { public: - /** Creates a watcher for a given component. + ComponentDeletionWatcher (const Component* const componentToWatch) throw(); - The component must be valid at the time it's passed in. - */ - ComponentDeletionWatcher (const Component* const componentToWatch) throw(); + ~ComponentDeletionWatcher() throw(); - /** Destructor. */ - ~ComponentDeletionWatcher() throw(); + bool hasBeenDeleted() const throw(); - /** Returns true if the component has been deleted since the time that this - object was created. - */ - bool hasBeenDeleted() const throw(); + const Component* getComponent() const throw(); - /** Returns the component that's being watched, or null if it has been deleted. */ - const Component* getComponent() const throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - const Component* const componentToWatch; - const uint32 componentUID; + const Component* const componentToWatch; + const uint32 componentUID; - ComponentDeletionWatcher (const ComponentDeletionWatcher&); - const ComponentDeletionWatcher& operator= (const ComponentDeletionWatcher&); + ComponentDeletionWatcher (const ComponentDeletionWatcher&); + const ComponentDeletionWatcher& operator= (const ComponentDeletionWatcher&); }; #endif // __JUCE_COMPONENTDELETIONWATCHER_JUCEHEADER__ @@ -31763,138 +15218,73 @@ private: #ifndef __JUCE_TOOLTIPCLIENT_JUCEHEADER__ #define __JUCE_TOOLTIPCLIENT_JUCEHEADER__ -/** - Components that want to use pop-up tooltips should implement this interface. - - A TooltipWindow will wait for the mouse to hover over a component that - implements the TooltipClient interface, and when it finds one, it will display - the tooltip returned by its getTooltip() method. - - @see TooltipWindow, SettableTooltipClient -*/ class JUCE_API TooltipClient { public: - /** Destructor. */ - virtual ~TooltipClient() {} + virtual ~TooltipClient() {} - /** Returns the string that this object wants to show as its tooltip. */ - virtual const String getTooltip() = 0; + virtual const String getTooltip() = 0; }; -/** - An implementation of TooltipClient that stores the tooltip string and a method - for changing it. - - This makes it easy to add a tooltip to a custom component, by simply adding this - as a base class and calling setTooltip(). - - Many of the Juce widgets already use this as a base class to implement their - tooltips. - - @see TooltipClient, TooltipWindow -*/ class JUCE_API SettableTooltipClient : public TooltipClient { public: - /** Destructor. */ - virtual ~SettableTooltipClient() {} + virtual ~SettableTooltipClient() {} - virtual void setTooltip (const String& newTooltip) { tooltipString = newTooltip; } + virtual void setTooltip (const String& newTooltip) { tooltipString = newTooltip; } - virtual const String getTooltip() { return tooltipString; } + virtual const String getTooltip() { return tooltipString; } - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - String tooltipString; + String tooltipString; }; #endif // __JUCE_TOOLTIPCLIENT_JUCEHEADER__ /********* End of inlined file: juce_TooltipClient.h *********/ -/** - A window that displays a pop-up tooltip when the mouse hovers over another component. - - To enable tooltips in your app, just create a single instance of a TooltipWindow - object. - - The TooltipWindow object will then stay invisible, waiting until the mouse - hovers for the specified length of time - it will then see if it's currently - over a component which implements the TooltipClient interface, and if so, - it will make itself visible to show the tooltip in the appropriate place. - - @see TooltipClient, SettableTooltipClient -*/ class JUCE_API TooltipWindow : public Component, - private Timer + private Timer { public: - /** Creates a tooltip window. + TooltipWindow (Component* parentComponent = 0, + const int millisecondsBeforeTipAppears = 700); - Make sure your app only creates one instance of this class, otherwise you'll - get multiple overlaid tooltips appearing. The window will initially be invisible - and will make itself visible when it needs to display a tip. + ~TooltipWindow(); - To change the style of tooltips, see the LookAndFeel class for its tooltip - methods. + void setMillisecondsBeforeTipAppears (const int newTimeMs = 700) throw(); - @param parentComponent if set to 0, the TooltipWindow will appear on the desktop, - otherwise the tooltip will be added to the given parent - component. - @param millisecondsBeforeTipAppears the time for which the mouse has to stay still - before a tooltip will be shown + enum ColourIds + { + backgroundColourId = 0x1001b00, /**< The colour to fill the background with. */ + textColourId = 0x1001c00, /**< The colour to use for the text. */ + outlineColourId = 0x1001c10 /**< The colour to use to draw an outline around the tooltip. */ + }; - @see TooltipClient, LookAndFeel::drawTooltip, LookAndFeel::getTooltipSize - */ - TooltipWindow (Component* parentComponent = 0, - const int millisecondsBeforeTipAppears = 700); - - /** Destructor. */ - ~TooltipWindow(); - - /** Changes the time before the tip appears. - This lets you change the value that was set in the constructor. - */ - void setMillisecondsBeforeTipAppears (const int newTimeMs = 700) throw(); - - /** A set of colour IDs to use to change the colour of various aspects of the tooltip. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1001b00, /**< The colour to fill the background with. */ - textColourId = 0x1001c00, /**< The colour to use for the text. */ - outlineColourId = 0x1001c10 /**< The colour to use to draw an outline around the tooltip. */ - }; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - int millisecondsBeforeTipAppears; - int mouseX, mouseY, mouseClicks; - unsigned int lastCompChangeTime, lastHideTime; - Component* lastComponentUnderMouse; - bool changedCompsSinceShown; - String tipShowing, lastTipUnderMouse; + int millisecondsBeforeTipAppears; + int mouseX, mouseY, mouseClicks; + unsigned int lastCompChangeTime, lastHideTime; + Component* lastComponentUnderMouse; + bool changedCompsSinceShown; + String tipShowing, lastTipUnderMouse; - void paint (Graphics& g); - void mouseEnter (const MouseEvent& e); - void timerCallback(); + void paint (Graphics& g); + void mouseEnter (const MouseEvent& e); + void timerCallback(); - static const String getTipFor (Component* const c); - void showFor (Component* const c, const String& tip); - void hide(); + static const String getTipFor (Component* const c); + void showFor (Component* const c, const String& tip); + void hide(); - TooltipWindow (const TooltipWindow&); - const TooltipWindow& operator= (const TooltipWindow&); + TooltipWindow (const TooltipWindow&); + const TooltipWindow& operator= (const TooltipWindow&); }; #endif // __JUCE_TOOLTIPWINDOW_JUCEHEADER__ @@ -31902,453 +15292,184 @@ private: class Button; -/** - Used to receive callbacks when a button is clicked. - - @see Button::addButtonListener, Button::removeButtonListener -*/ class JUCE_API ButtonListener { public: - /** Destructor. */ - virtual ~ButtonListener() {} + virtual ~ButtonListener() {} - /** Called when the button is clicked. */ - virtual void buttonClicked (Button* button) = 0; + virtual void buttonClicked (Button* button) = 0; - /** Called when the button's state changes. */ - virtual void buttonStateChanged (Button*) {} + virtual void buttonStateChanged (Button*) {} }; -/** - A base class for buttons. - - This contains all the logic for button behaviours such as enabling/disabling, - responding to shortcut keystrokes, auto-repeating when held down, toggle-buttons - and radio groups, etc. - - @see TextButton, DrawableButton, ToggleButton -*/ class JUCE_API Button : public Component, - public SettableTooltipClient, - public ApplicationCommandManagerListener, - public Value::Listener, - private KeyListener + public SettableTooltipClient, + public ApplicationCommandManagerListener, + public Value::Listener, + private KeyListener { protected: - /** Creates a button. - - @param buttonName the text to put in the button (the component's name is also - initially set to this string, but these can be changed later - using the setName() and setButtonText() methods) - */ - Button (const String& buttonName); + Button (const String& buttonName); public: - /** Destructor. */ - virtual ~Button(); + virtual ~Button(); - /** Changes the button's text. + void setButtonText (const String& newText) throw(); - @see getButtonText - */ - void setButtonText (const String& newText) throw(); + const String getButtonText() const throw() { return text; } - /** Returns the text displayed in the button. + bool isDown() const throw(); - @see setButtonText - */ - const String getButtonText() const throw() { return text; } + bool isOver() const throw(); - /** Returns true if the button is currently being held down by the mouse. + void setToggleState (const bool shouldBeOn, + const bool sendChangeNotification); - @see isOver - */ - bool isDown() const throw(); + bool getToggleState() const throw() { return isOn.getValue(); } - /** Returns true if the mouse is currently over the button. + Value& getToggleStateValue() { return isOn; } - This will be also be true if the mouse is being held down. + void setClickingTogglesState (const bool shouldToggle) throw(); - @see isDown - */ - bool isOver() const throw(); + bool getClickingTogglesState() const throw(); - /** A button has an on/off state associated with it, and this changes that. + void setRadioGroupId (const int newGroupId); - By default buttons are 'off' and for simple buttons that you click to perform - an action you won't change this. Toggle buttons, however will want to - change their state when turned on or off. + int getRadioGroupId() const throw() { return radioGroupId; } - @param shouldBeOn whether to set the button's toggle state to be on or - off. If it's a member of a button group, this will - always try to turn it on, and to turn off any other - buttons in the group - @param sendChangeNotification if true, a callback will be made to clicked(); if false - the button will be repainted but no notification will - be sent - @see getToggleState, setRadioGroupId - */ - void setToggleState (const bool shouldBeOn, - const bool sendChangeNotification); + void addButtonListener (ButtonListener* const newListener) throw(); - /** Returns true if the button in 'on'. + void removeButtonListener (ButtonListener* const listener) throw(); - By default buttons are 'off' and for simple buttons that you click to perform - an action you won't change this. Toggle buttons, however will want to - change their state when turned on or off. + virtual void triggerClick(); - @see setToggleState - */ - bool getToggleState() const throw() { return isOn.getValue(); } + void setCommandToTrigger (ApplicationCommandManager* commandManagerToUse, + const int commandID, + const bool generateTooltip); - /** Returns the Value object that represents the botton's toggle state. - You can use this Value object to connect the button's state to external values or setters, - either by taking a copy of the Value, or by using Value::referTo() to make it point to - your own Value object. - @see getToggleState, Value - */ - Value& getToggleStateValue() { return isOn; } + int getCommandID() const throw() { return commandID; } - /** This tells the button to automatically flip the toggle state when - the button is clicked. + void addShortcut (const KeyPress& key); - If set to true, then before the clicked() callback occurs, the toggle-state - of the button is flipped. - */ - void setClickingTogglesState (const bool shouldToggle) throw(); + void clearShortcuts(); - /** Returns true if this button is set to be an automatic toggle-button. + bool isRegisteredForShortcut (const KeyPress& key) const throw(); - This returns the last value that was passed to setClickingTogglesState(). - */ - bool getClickingTogglesState() const throw(); + void setRepeatSpeed (const int initialDelayInMillisecs, + const int repeatDelayInMillisecs, + const int minimumDelayInMillisecs = -1) throw(); - /** Enables the button to act as a member of a mutually-exclusive group - of 'radio buttons'. + void setTriggeredOnMouseDown (const bool isTriggeredOnMouseDown) throw(); - If the group ID is set to a non-zero number, then this button will - act as part of a group of buttons with the same ID, only one of - which can be 'on' at the same time. Note that when it's part of - a group, clicking a toggle-button that's 'on' won't turn it off. + uint32 getMillisecondsSinceButtonDown() const throw(); - To find other buttons with the same ID, this button will search through - its sibling components for ToggleButtons, so all the buttons for a - particular group must be placed inside the same parent component. + void setVisible (bool shouldBeVisible); - Set the group ID back to zero if you want it to act as a normal toggle - button again. + void setTooltip (const String& newTooltip); - @see getRadioGroupId - */ - void setRadioGroupId (const int newGroupId); + // (implementation of the TooltipClient method) + const String getTooltip(); - /** Returns the ID of the group to which this button belongs. + enum ConnectedEdgeFlags + { + ConnectedOnLeft = 1, + ConnectedOnRight = 2, + ConnectedOnTop = 4, + ConnectedOnBottom = 8 + }; - (See setRadioGroupId() for an explanation of this). - */ - int getRadioGroupId() const throw() { return radioGroupId; } + void setConnectedEdges (const int connectedEdgeFlags) throw(); - /** Registers a listener to receive events when this button's state changes. + int getConnectedEdgeFlags() const throw() { return connectedEdgeFlags; } - If the listener is already registered, this will not register it again. + bool isConnectedOnLeft() const throw() { return (connectedEdgeFlags & ConnectedOnLeft) != 0; } - @see removeButtonListener - */ - void addButtonListener (ButtonListener* const newListener) throw(); + bool isConnectedOnRight() const throw() { return (connectedEdgeFlags & ConnectedOnRight) != 0; } - /** Removes a previously-registered button listener + bool isConnectedOnTop() const throw() { return (connectedEdgeFlags & ConnectedOnTop) != 0; } - @see addButtonListener - */ - void removeButtonListener (ButtonListener* const listener) throw(); + bool isConnectedOnBottom() const throw() { return (connectedEdgeFlags & ConnectedOnBottom) != 0; } - /** Causes the button to act as if it's been clicked. + enum ButtonState + { + buttonNormal, + buttonOver, + buttonDown + }; - This will asynchronously make the button draw itself going down and up, and - will then call back the clicked() method as if mouse was clicked on it. + void setState (const ButtonState newState); - @see clicked - */ - virtual void triggerClick(); - - /** Sets a command ID for this button to automatically invoke when it's clicked. - - When the button is pressed, it will use the given manager to trigger the - command ID. - - Obviously be careful that the ApplicationCommandManager doesn't get deleted - before this button is. To disable the command triggering, call this method and - pass 0 for the parameters. - - If generateTooltip is true, then the button's tooltip will be automatically - generated based on the name of this command and its current shortcut key. - - @see addShortcut, getCommandID - */ - void setCommandToTrigger (ApplicationCommandManager* commandManagerToUse, - const int commandID, - const bool generateTooltip); - - /** Returns the command ID that was set by setCommandToTrigger(). - */ - int getCommandID() const throw() { return commandID; } - - /** Assigns a shortcut key to trigger the button. - - The button registers itself with its top-level parent component for keypresses. - - Note that a different way of linking buttons to keypresses is by using the - setCommandToTrigger() method to invoke a command. - - @see clearShortcuts - */ - void addShortcut (const KeyPress& key); - - /** Removes all key shortcuts that had been set for this button. - - @see addShortcut - */ - void clearShortcuts(); - - /** Returns true if the given keypress is a shortcut for this button. - - @see addShortcut - */ - bool isRegisteredForShortcut (const KeyPress& key) const throw(); - - /** Sets an auto-repeat speed for the button when it is held down. - - (Auto-repeat is disabled by default). - - @param initialDelayInMillisecs how long to wait after the mouse is pressed before - triggering the next click. If this is zero, auto-repeat - is disabled - @param repeatDelayInMillisecs the frequently subsequent repeated clicks should be - triggered - @param minimumDelayInMillisecs if this is greater than 0, the auto-repeat speed will - get faster, the longer the button is held down, up to the - minimum interval specified here - */ - void setRepeatSpeed (const int initialDelayInMillisecs, - const int repeatDelayInMillisecs, - const int minimumDelayInMillisecs = -1) throw(); - - /** Sets whether the button click should happen when the mouse is pressed or released. - - By default the button is only considered to have been clicked when the mouse is - released, but setting this to true will make it call the clicked() method as soon - as the button is pressed. - - This is useful if the button is being used to show a pop-up menu, as it allows - the click to be used as a drag onto the menu. - */ - void setTriggeredOnMouseDown (const bool isTriggeredOnMouseDown) throw(); - - /** Returns the number of milliseconds since the last time the button - went into the 'down' state. - */ - uint32 getMillisecondsSinceButtonDown() const throw(); - - /** (overridden from Component to do special stuff). */ - void setVisible (bool shouldBeVisible); - - /** Sets the tooltip for this button. - - @see TooltipClient, TooltipWindow - */ - void setTooltip (const String& newTooltip); - - // (implementation of the TooltipClient method) - const String getTooltip(); - - /** A combination of these flags are used by setConnectedEdges(). - */ - enum ConnectedEdgeFlags - { - ConnectedOnLeft = 1, - ConnectedOnRight = 2, - ConnectedOnTop = 4, - ConnectedOnBottom = 8 - }; - - /** Hints about which edges of the button might be connected to adjoining buttons. - - The value passed in is a bitwise combination of any of the values in the - ConnectedEdgeFlags enum. - - E.g. if you are placing two buttons adjacent to each other, you could use this to - indicate which edges are touching, and the LookAndFeel might choose to drawn them - without rounded corners on the edges that connect. It's only a hint, so the - LookAndFeel can choose to ignore it if it's not relevent for this type of - button. - */ - void setConnectedEdges (const int connectedEdgeFlags) throw(); - - /** Returns the set of flags passed into setConnectedEdges(). */ - int getConnectedEdgeFlags() const throw() { return connectedEdgeFlags; } - - /** Indicates whether the button adjoins another one on its left edge. - @see setConnectedEdges - */ - bool isConnectedOnLeft() const throw() { return (connectedEdgeFlags & ConnectedOnLeft) != 0; } - - /** Indicates whether the button adjoins another one on its right edge. - @see setConnectedEdges - */ - bool isConnectedOnRight() const throw() { return (connectedEdgeFlags & ConnectedOnRight) != 0; } - - /** Indicates whether the button adjoins another one on its top edge. - @see setConnectedEdges - */ - bool isConnectedOnTop() const throw() { return (connectedEdgeFlags & ConnectedOnTop) != 0; } - - /** Indicates whether the button adjoins another one on its bottom edge. - @see setConnectedEdges - */ - bool isConnectedOnBottom() const throw() { return (connectedEdgeFlags & ConnectedOnBottom) != 0; } - - /** Used by setState(). */ - enum ButtonState - { - buttonNormal, - buttonOver, - buttonDown - }; - - /** Can be used to force the button into a particular state. - - This only changes the button's appearance, it won't trigger a click, or stop any mouse-clicks - from happening. - - The state that you set here will only last until it is automatically changed when the mouse - enters or exits the button, or the mouse-button is pressed or released. - */ - void setState (const ButtonState newState); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** This method is called when the button has been clicked. + virtual void clicked(); - Subclasses can override this to perform whatever they actions they need - to do. + virtual void clicked (const ModifierKeys& modifiers); - Alternatively, a ButtonListener can be added to the button, and these listeners - will be called when the click occurs. + virtual void paintButton (Graphics& g, + bool isMouseOverButton, + bool isButtonDown) = 0; - @see triggerClick - */ - virtual void clicked(); + virtual void buttonStateChanged(); - /** This method is called when the button has been clicked. - - By default it just calls clicked(), but you might want to override it to handle - things like clicking when a modifier key is pressed, etc. - - @see ModifierKeys - */ - virtual void clicked (const ModifierKeys& modifiers); - - /** Subclasses should override this to actually paint the button's contents. - - It's better to use this than the paint method, because it gives you information - about the over/down state of the button. - - @param g the graphics context to use - @param isMouseOverButton true if the button is either in the 'over' or - 'down' state - @param isButtonDown true if the button should be drawn in the 'down' position - */ - virtual void paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown) = 0; - - /** Called when the button's up/down/over state changes. - - Subclasses can override this if they need to do something special when the button - goes up or down. - - @see isDown, isOver - */ - virtual void buttonStateChanged(); - - /** @internal */ - virtual void internalClickCallback (const ModifierKeys& modifiers); - /** @internal */ - void handleCommandMessage (int commandId); - /** @internal */ - void mouseEnter (const MouseEvent& e); - /** @internal */ - void mouseExit (const MouseEvent& e); - /** @internal */ - void mouseDown (const MouseEvent& e); - /** @internal */ - void mouseDrag (const MouseEvent& e); - /** @internal */ - void mouseUp (const MouseEvent& e); - /** @internal */ - bool keyPressed (const KeyPress& key); - /** @internal */ - bool keyPressed (const KeyPress& key, Component* originatingComponent); - /** @internal */ - bool keyStateChanged (const bool isKeyDown, Component* originatingComponent); - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void parentHierarchyChanged(); - /** @internal */ - void focusGained (FocusChangeType cause); - /** @internal */ - void focusLost (FocusChangeType cause); - /** @internal */ - void enablementChanged(); - /** @internal */ - void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo&); - /** @internal */ - void applicationCommandListChanged(); - /** @internal */ - void valueChanged (Value& value); + virtual void internalClickCallback (const ModifierKeys& modifiers); + void handleCommandMessage (int commandId); + void mouseEnter (const MouseEvent& e); + void mouseExit (const MouseEvent& e); + void mouseDown (const MouseEvent& e); + void mouseDrag (const MouseEvent& e); + void mouseUp (const MouseEvent& e); + bool keyPressed (const KeyPress& key); + bool keyPressed (const KeyPress& key, Component* originatingComponent); + bool keyStateChanged (const bool isKeyDown, Component* originatingComponent); + void paint (Graphics& g); + void parentHierarchyChanged(); + void focusGained (FocusChangeType cause); + void focusLost (FocusChangeType cause); + void enablementChanged(); + void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo&); + void applicationCommandListChanged(); + void valueChanged (Value& value); private: - Array shortcuts; - Component* keySource; - String text; - SortedSet buttonListeners; + Array shortcuts; + Component* keySource; + String text; + SortedSet buttonListeners; - friend class InternalButtonRepeatTimer; - ScopedPointer repeatTimer; - uint32 buttonPressTime, lastTimeCallbackTime; - ApplicationCommandManager* commandManagerToUse; - int autoRepeatDelay, autoRepeatSpeed, autoRepeatMinimumDelay; - int radioGroupId, commandID, connectedEdgeFlags; - ButtonState buttonState; + friend class InternalButtonRepeatTimer; + ScopedPointer repeatTimer; + uint32 buttonPressTime, lastTimeCallbackTime; + ApplicationCommandManager* commandManagerToUse; + int autoRepeatDelay, autoRepeatSpeed, autoRepeatMinimumDelay; + int radioGroupId, commandID, connectedEdgeFlags; + ButtonState buttonState; - Value isOn; - bool lastToggleState : 1; - bool clickTogglesState : 1; - bool needsToRelease : 1; - bool needsRepainting : 1; - bool isKeyDown : 1; - bool triggerOnMouseDown : 1; - bool generateTooltip : 1; + Value isOn; + bool lastToggleState : 1; + bool clickTogglesState : 1; + bool needsToRelease : 1; + bool needsRepainting : 1; + bool isKeyDown : 1; + bool triggerOnMouseDown : 1; + bool generateTooltip : 1; - void repeatTimerCallback() throw(); - Timer& getRepeatTimer() throw(); + void repeatTimerCallback() throw(); + Timer& getRepeatTimer() throw(); - ButtonState updateState (const MouseEvent* const e) throw(); - bool isShortcutPressed() const throw(); - void turnOffOtherButtonsInGroup (const bool sendChangeNotification); + ButtonState updateState (const MouseEvent* const e) throw(); + bool isShortcutPressed() const throw(); + void turnOffOtherButtonsInGroup (const bool sendChangeNotification); - void flashButtonState() throw(); - void sendClickMessage (const ModifierKeys& modifiers); - void sendStateMessage(); + void flashButtonState() throw(); + void sendClickMessage (const ModifierKeys& modifiers); + void sendStateMessage(); - Button (const Button&); - const Button& operator= (const Button&); + Button (const Button&); + const Button& operator= (const Button&); }; #endif // __JUCE_BUTTON_JUCEHEADER__ @@ -32356,487 +15477,188 @@ private: class ScrollBar; -/** - A class for receiving events from a ScrollBar. - - You can register a ScrollBarListener with a ScrollBar using the ScrollBar::addListener() - method, and it will be called when the bar's position changes. - - @see ScrollBar::addListener, ScrollBar::removeListener -*/ class JUCE_API ScrollBarListener { public: - /** Destructor. */ - virtual ~ScrollBarListener() {} + virtual ~ScrollBarListener() {} - /** Called when a ScrollBar is moved. - - @param scrollBarThatHasMoved the bar that has moved - @param newRangeStart the new range start of this bar - */ - virtual void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, - const double newRangeStart) = 0; + virtual void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, + const double newRangeStart) = 0; }; -/** - A scrollbar component. - - To use a scrollbar, set up its total range using the setRangeLimits() method - this - sets the range of values it can represent. Then you can use setCurrentRange() to - change the position and size of the scrollbar's 'thumb'. - - Registering a ScrollBarListener with the scrollbar will allow you to find out when - the user moves it, and you can use the getCurrentRangeStart() to find out where - they moved it to. - - The scrollbar will adjust its own visibility according to whether its thumb size - allows it to actually be scrolled. - - For most purposes, it's probably easier to use a ViewportContainer or ListBox - instead of handling a scrollbar directly. - - @see ScrollBarListener -*/ class JUCE_API ScrollBar : public Component, - public AsyncUpdater, - private Timer + public AsyncUpdater, + private Timer { public: - /** Creates a Scrollbar. + ScrollBar (const bool isVertical, + const bool buttonsAreVisible = true); - @param isVertical whether it should be a vertical or horizontal bar - @param buttonsAreVisible whether to show the up/down or left/right buttons - */ - ScrollBar (const bool isVertical, - const bool buttonsAreVisible = true); + ~ScrollBar(); - /** Destructor. */ - ~ScrollBar(); + bool isVertical() const throw() { return vertical; } - /** Returns true if the scrollbar is vertical, false if it's horizontal. */ - bool isVertical() const throw() { return vertical; } + void setOrientation (const bool shouldBeVertical) throw(); - /** Changes the scrollbar's direction. + void setButtonVisibility (const bool buttonsAreVisible); - You'll also need to resize the bar appropriately - this just changes its internal - layout. + void setAutoHide (const bool shouldHideWhenFullRange); - @param shouldBeVertical true makes it vertical; false makes it horizontal. - */ - void setOrientation (const bool shouldBeVertical) throw(); + void setRangeLimits (const double minimum, + const double maximum) throw(); - /** Shows or hides the scrollbar's buttons. */ - void setButtonVisibility (const bool buttonsAreVisible); + double getMinimumRangeLimit() const throw() { return minimum; } - /** Tells the scrollbar whether to make itself invisible when not needed. + double getMaximumRangeLimit() const throw() { return maximum; } - The default behaviour is for a scrollbar to become invisible when the thumb - fills the whole of its range (i.e. when it can't be moved). Setting this - value to false forces the bar to always be visible. - */ - void setAutoHide (const bool shouldHideWhenFullRange); + void setCurrentRange (double newStart, + double newSize) throw(); - /** Sets the minimum and maximum values that the bar will move between. + void setCurrentRangeStart (double newStart) throw(); - The bar's thumb will always be constrained so that the top of the thumb - will be >= minimum, and the bottom of the thumb <= maximum. + double getCurrentRangeStart() const throw() { return rangeStart; } - @see setCurrentRange - */ - void setRangeLimits (const double minimum, - const double maximum) throw(); + double getCurrentRangeSize() const throw() { return rangeSize; } - /** Returns the lower value that the thumb can be set to. + void setSingleStepSize (const double newSingleStepSize) throw(); - This is the value set by setRangeLimits(). - */ - double getMinimumRangeLimit() const throw() { return minimum; } + void moveScrollbarInSteps (const int howManySteps) throw(); - /** Returns the upper value that the thumb can be set to. + void moveScrollbarInPages (const int howManyPages) throw(); - This is the value set by setRangeLimits(). - */ - double getMaximumRangeLimit() const throw() { return maximum; } + void scrollToTop() throw(); - /** Changes the position of the scrollbar's 'thumb'. + void scrollToBottom() throw(); - This sets both the position and size of the thumb - to just set the position without - changing the size, you can use setCurrentRangeStart(). + void setButtonRepeatSpeed (const int initialDelayInMillisecs, + const int repeatDelayInMillisecs, + const int minimumDelayInMillisecs = -1) throw(); - If this method call actually changes the scrollbar's position, it will trigger an - asynchronous call to ScrollBarListener::scrollBarMoved() for all the listeners that - are registered. + enum ColourIds + { + backgroundColourId = 0x1000300, /**< The background colour of the scrollbar. */ + thumbColourId = 0x1000400, /**< A base colour to use for the thumb. The look and feel will probably use variations on this colour. */ + trackColourId = 0x1000401 /**< A base colour to use for the slot area of the bar. The look and feel will probably use variations on this colour. */ + }; - @param newStart the top (or left) of the thumb, in the range - getMinimumRangeLimit() <= newStart <= getMaximumRangeLimit(). If the - value is beyond these limits, it will be clipped. - @param newSize the size of the thumb, such that - getMinimumRangeLimit() <= newStart + newSize <= getMaximumRangeLimit(). If the - size is beyond these limits, it will be clipped. - @see setCurrentRangeStart, getCurrentRangeStart, getCurrentRangeSize - */ - void setCurrentRange (double newStart, - double newSize) throw(); + void addListener (ScrollBarListener* const listener) throw(); - /** Moves the bar's thumb position. + void removeListener (ScrollBarListener* const listener) throw(); - This will move the thumb position without changing the thumb size. Note - that the maximum thumb start position is (getMaximumRangeLimit() - getCurrentRangeSize()). + bool keyPressed (const KeyPress& key); + void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); + void lookAndFeelChanged(); + void handleAsyncUpdate(); + void mouseDown (const MouseEvent& e); + void mouseDrag (const MouseEvent& e); + void mouseUp (const MouseEvent& e); + void paint (Graphics& g); + void resized(); - If this method call actually changes the scrollbar's position, it will trigger an - asynchronous call to ScrollBarListener::scrollBarMoved() for all the listeners that - are registered. - - @see setCurrentRange - */ - void setCurrentRangeStart (double newStart) throw(); - - /** Returns the position of the top of the thumb. - - @see setCurrentRangeStart - */ - double getCurrentRangeStart() const throw() { return rangeStart; } - - /** Returns the current size of the thumb. - - @see setCurrentRange - */ - double getCurrentRangeSize() const throw() { return rangeSize; } - - /** Sets the amount by which the up and down buttons will move the bar. - - The value here is in terms of the total range, and is added or subtracted - from the thumb position when the user clicks an up/down (or left/right) button. - */ - void setSingleStepSize (const double newSingleStepSize) throw(); - - /** Moves the scrollbar by a number of single-steps. - - This will move the bar by a multiple of its single-step interval (as - specified using the setSingleStepSize() method). - - A positive value here will move the bar down or to the right, a negative - value moves it up or to the left. - */ - void moveScrollbarInSteps (const int howManySteps) throw(); - - /** Moves the scroll bar up or down in pages. - - This will move the bar by a multiple of its current thumb size, effectively - doing a page-up or down. - - A positive value here will move the bar down or to the right, a negative - value moves it up or to the left. - */ - void moveScrollbarInPages (const int howManyPages) throw(); - - /** Scrolls to the top (or left). - - This is the same as calling setCurrentRangeStart (getMinimumRangeLimit()); - */ - void scrollToTop() throw(); - - /** Scrolls to the bottom (or right). - - This is the same as calling setCurrentRangeStart (getMaximumRangeLimit() - getCurrentRangeSize()); - */ - void scrollToBottom() throw(); - - /** Changes the delay before the up and down buttons autorepeat when they are held - down. - - For an explanation of what the parameters are for, see Button::setRepeatSpeed(). - - @see Button::setRepeatSpeed - */ - void setButtonRepeatSpeed (const int initialDelayInMillisecs, - const int repeatDelayInMillisecs, - const int minimumDelayInMillisecs = -1) throw(); - - /** A set of colour IDs to use to change the colour of various aspects of the component. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1000300, /**< The background colour of the scrollbar. */ - thumbColourId = 0x1000400, /**< A base colour to use for the thumb. The look and feel will probably use variations on this colour. */ - trackColourId = 0x1000401 /**< A base colour to use for the slot area of the bar. The look and feel will probably use variations on this colour. */ - }; - - /** Registers a listener that will be called when the scrollbar is moved. */ - void addListener (ScrollBarListener* const listener) throw(); - - /** Deregisters a previously-registered listener. */ - void removeListener (ScrollBarListener* const listener) throw(); - - /** @internal */ - bool keyPressed (const KeyPress& key); - /** @internal */ - void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); - /** @internal */ - void lookAndFeelChanged(); - /** @internal */ - void handleAsyncUpdate(); - /** @internal */ - void mouseDown (const MouseEvent& e); - /** @internal */ - void mouseDrag (const MouseEvent& e); - /** @internal */ - void mouseUp (const MouseEvent& e); - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void resized(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - double minimum, maximum; - double rangeStart, rangeSize; - double singleStepSize, dragStartRange; - int thumbAreaStart, thumbAreaSize, thumbStart, thumbSize; - int dragStartMousePos, lastMousePos; - int initialDelayInMillisecs, repeatDelayInMillisecs, minimumDelayInMillisecs; - bool vertical, isDraggingThumb, alwaysVisible; - Button* upButton; - Button* downButton; - SortedSet listeners; + double minimum, maximum; + double rangeStart, rangeSize; + double singleStepSize, dragStartRange; + int thumbAreaStart, thumbAreaSize, thumbStart, thumbSize; + int dragStartMousePos, lastMousePos; + int initialDelayInMillisecs, repeatDelayInMillisecs, minimumDelayInMillisecs; + bool vertical, isDraggingThumb, alwaysVisible; + Button* upButton; + Button* downButton; + SortedSet listeners; - void updateThumbPosition() throw(); - void timerCallback(); + void updateThumbPosition() throw(); + void timerCallback(); - ScrollBar (const ScrollBar&); - const ScrollBar& operator= (const ScrollBar&); + ScrollBar (const ScrollBar&); + const ScrollBar& operator= (const ScrollBar&); }; #endif // __JUCE_SCROLLBAR_JUCEHEADER__ /********* End of inlined file: juce_ScrollBar.h *********/ -/** - A Viewport is used to contain a larger child component, and allows the child - to be automatically scrolled around. - - To use a Viewport, just create one and set the component that goes inside it - using the setViewedComponent() method. When the child component changes size, - the Viewport will adjust its scrollbars accordingly. - - A subclass of the viewport can be created which will receive calls to its - visibleAreaChanged() method when the subcomponent changes position or size. - -*/ class JUCE_API Viewport : public Component, - private ComponentListener, - private ScrollBarListener + private ComponentListener, + private ScrollBarListener { public: - /** Creates a Viewport. + Viewport (const String& componentName = String::empty); - The viewport is initially empty - use the setViewedComponent() method to - add a child component for it to manage. - */ - Viewport (const String& componentName = String::empty); + ~Viewport(); - /** Destructor. */ - ~Viewport(); + void setViewedComponent (Component* const newViewedComponent); - /** Sets the component that this viewport will contain and scroll around. + Component* getViewedComponent() const throw() { return contentComp; } - This will add the given component to this Viewport and position it at - (0, 0). + void setViewPosition (const int xPixelsOffset, + const int yPixelsOffset); - (Don't add or remove any child components directly using the normal - Component::addChildComponent() methods). + void setViewPositionProportionately (const double proportionX, + const double proportionY); - @param newViewedComponent the component to add to this viewport (this pointer - may be null). The component passed in will be deleted - by the Viewport when it's no longer needed - @see getViewedComponent - */ - void setViewedComponent (Component* const newViewedComponent); + bool autoScroll (int mouseX, int mouseY, int distanceFromEdge, int maximumSpeed); - /** Returns the component that's currently being used inside the Viewport. + int getViewPositionX() const throw() { return lastVX; } - @see setViewedComponent - */ - Component* getViewedComponent() const throw() { return contentComp; } + int getViewPositionY() const throw() { return lastVY; } - /** Changes the position of the viewed component. + int getViewWidth() const throw() { return lastVW; } - The inner component will be moved so that the pixel at the top left of - the viewport will be the pixel at position (xPixelsOffset, yPixelsOffset) - within the inner component. + int getViewHeight() const throw() { return lastVH; } - This will update the scrollbars and might cause a call to visibleAreaChanged(). + int getMaximumVisibleWidth() const throw(); - @see getViewPositionX, getViewPositionY, setViewPositionProportionately - */ - void setViewPosition (const int xPixelsOffset, - const int yPixelsOffset); + int getMaximumVisibleHeight() const throw(); - /** Changes the view position as a proportion of the distance it can move. + virtual void visibleAreaChanged (int visibleX, int visibleY, + int visibleW, int visibleH); - The values here are from 0.0 to 1.0 - where (0, 0) would put the - visible area in the top-left, and (1, 1) would put it as far down and - to the right as it's possible to go whilst keeping the child component - on-screen. - */ - void setViewPositionProportionately (const double proportionX, - const double proportionY); + void setScrollBarsShown (const bool showVerticalScrollbarIfNeeded, + const bool showHorizontalScrollbarIfNeeded); - /** If the specified position is at the edges of the viewport, this method scrolls - the viewport to bring that position nearer to the centre. + bool isVerticalScrollBarShown() const throw() { return showVScrollbar; } - Call this if you're dragging an object inside a viewport and want to make it scroll - when the user approaches an edge. You might also find Component::beginDragAutoRepeat() - useful when auto-scrolling. + bool isHorizontalScrollBarShown() const throw() { return showHScrollbar; } - @param mouseX the x position, relative to the Viewport's top-left - @param mouseY the y position, relative to the Viewport's top-left - @param distanceFromEdge specifies how close to an edge the position needs to be - before the viewport should scroll in that direction - @param maximumSpeed the maximum number of pixels that the viewport is allowed - to scroll by. - @returns true if the viewport was scrolled - */ - bool autoScroll (int mouseX, int mouseY, int distanceFromEdge, int maximumSpeed); + void setScrollBarThickness (const int thickness); - /** Returns the position within the child component of the top-left of its visible area. - @see getViewWidth, setViewPosition - */ - int getViewPositionX() const throw() { return lastVX; } + int getScrollBarThickness() const throw(); - /** Returns the position within the child component of the top-left of its visible area. - @see getViewHeight, setViewPosition - */ - int getViewPositionY() const throw() { return lastVY; } + void setSingleStepSizes (const int stepX, const int stepY); - /** Returns the width of the visible area of the child component. + void setScrollBarButtonVisibility (const bool buttonsVisible); - This may be less than the width of this Viewport if there's a vertical scrollbar - or if the child component is itself smaller. - */ - int getViewWidth() const throw() { return lastVW; } + ScrollBar* getVerticalScrollBar() const throw() { return verticalScrollBar; } - /** Returns the height of the visible area of the child component. + ScrollBar* getHorizontalScrollBar() const throw() { return horizontalScrollBar; } - This may be less than the height of this Viewport if there's a horizontal scrollbar - or if the child component is itself smaller. - */ - int getViewHeight() const throw() { return lastVH; } + juce_UseDebuggingNewOperator - /** Returns the width available within this component for the contents. - - This will be the width of the viewport component minus the width of a - vertical scrollbar (if visible). - */ - int getMaximumVisibleWidth() const throw(); - - /** Returns the height available within this component for the contents. - - This will be the height of the viewport component minus the space taken up - by a horizontal scrollbar (if visible). - */ - int getMaximumVisibleHeight() const throw(); - - /** Callback method that is called when the visible area changes. - - This will be called when the visible area is moved either be scrolling or - by calls to setViewPosition(), etc. - */ - virtual void visibleAreaChanged (int visibleX, int visibleY, - int visibleW, int visibleH); - - /** Turns scrollbars on or off. - - If set to false, the scrollbars won't ever appear. When true (the default) - they will appear only when needed. - */ - void setScrollBarsShown (const bool showVerticalScrollbarIfNeeded, - const bool showHorizontalScrollbarIfNeeded); - - /** True if the vertical scrollbar is enabled. - @see setScrollBarsShown - */ - bool isVerticalScrollBarShown() const throw() { return showVScrollbar; } - - /** True if the horizontal scrollbar is enabled. - @see setScrollBarsShown - */ - bool isHorizontalScrollBarShown() const throw() { return showHScrollbar; } - - /** Changes the width of the scrollbars. - - If this isn't specified, the default width from the LookAndFeel class will be used. - - @see LookAndFeel::getDefaultScrollbarWidth - */ - void setScrollBarThickness (const int thickness); - - /** Returns the thickness of the scrollbars. - - @see setScrollBarThickness - */ - int getScrollBarThickness() const throw(); - - /** Changes the distance that a single-step click on a scrollbar button - will move the viewport. - */ - void setSingleStepSizes (const int stepX, const int stepY); - - /** Shows or hides the buttons on any scrollbars that are used. - - @see ScrollBar::setButtonVisibility - */ - void setScrollBarButtonVisibility (const bool buttonsVisible); - - /** Returns a pointer to the scrollbar component being used. - - Handy if you need to customise the bar somehow. - */ - ScrollBar* getVerticalScrollBar() const throw() { return verticalScrollBar; } - - /** Returns a pointer to the scrollbar component being used. - - Handy if you need to customise the bar somehow. - */ - ScrollBar* getHorizontalScrollBar() const throw() { return horizontalScrollBar; } - - juce_UseDebuggingNewOperator - - /** @internal */ - void resized(); - /** @internal */ - void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, const double newRangeStart); - /** @internal */ - void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); - /** @internal */ - bool keyPressed (const KeyPress& key); - /** @internal */ - void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); - /** @internal */ - bool useMouseWheelMoveIfNeeded (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); + void resized(); + void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, const double newRangeStart); + void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); + bool keyPressed (const KeyPress& key); + void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); + bool useMouseWheelMoveIfNeeded (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); private: - Component* contentComp; - int lastVX, lastVY, lastVW, lastVH; - int scrollBarThickness; - int singleStepX, singleStepY; - bool showHScrollbar, showVScrollbar; - Component* contentHolder; - ScrollBar* verticalScrollBar; - ScrollBar* horizontalScrollBar; + Component* contentComp; + int lastVX, lastVY, lastVW, lastVH; + int scrollBarThickness; + int singleStepX, singleStepY; + bool showHScrollbar, showVScrollbar; + Component* contentHolder; + ScrollBar* verticalScrollBar; + ScrollBar* horizontalScrollBar; - void updateVisibleRegion(); - Viewport (const Viewport&); - const Viewport& operator= (const Viewport&); + void updateVisibleRegion(); + Viewport (const Viewport&); + const Viewport& operator= (const Viewport&); }; #endif // __JUCE_VIEWPORT_JUCEHEADER__ @@ -32850,422 +15672,186 @@ private: #ifndef __JUCE_POPUPMENUCUSTOMCOMPONENT_JUCEHEADER__ #define __JUCE_POPUPMENUCUSTOMCOMPONENT_JUCEHEADER__ -/** A user-defined copmonent that can appear inside one of the rows of a popup menu. - - @see PopupMenu::addCustomItem -*/ class JUCE_API PopupMenuCustomComponent : public Component { public: - /** Destructor. */ - ~PopupMenuCustomComponent(); + ~PopupMenuCustomComponent(); - /** Chooses the size that this component would like to have. + virtual void getIdealSize (int& idealWidth, + int& idealHeight) = 0; - Note that the size which this method returns isn't necessarily the one that - the menu will give it, as it will be stretched to fit the other items in - the menu. - */ - virtual void getIdealSize (int& idealWidth, - int& idealHeight) = 0; + void triggerMenuItem(); - /** Dismisses the menu indicating that this item has been chosen. - - This will cause the menu to exit from its modal state, returning - this item's id as the result. - */ - void triggerMenuItem(); - - /** Returns true if this item should be highlighted because the mouse is - over it. - - You can call this method in your paint() method to find out whether - to draw a highlight. - */ - bool isItemHighlighted() const throw() { return isHighlighted; } + bool isItemHighlighted() const throw() { return isHighlighted; } protected: - /** Constructor. - - If isTriggeredAutomatically is true, then the menu will automatically detect - a click on this component and use that to trigger it. If it's false, then it's - up to your class to manually trigger the item if it wants to. - */ - PopupMenuCustomComponent (const bool isTriggeredAutomatically = true); + PopupMenuCustomComponent (const bool isTriggeredAutomatically = true); private: - friend class MenuItemInfo; - friend class MenuItemComponent; - friend class PopupMenuWindow; - int refCount_; - bool isHighlighted, isTriggeredAutomatically; + friend class MenuItemInfo; + friend class MenuItemComponent; + friend class PopupMenuWindow; + int refCount_; + bool isHighlighted, isTriggeredAutomatically; - PopupMenuCustomComponent (const PopupMenuCustomComponent&); - const PopupMenuCustomComponent& operator= (const PopupMenuCustomComponent&); + PopupMenuCustomComponent (const PopupMenuCustomComponent&); + const PopupMenuCustomComponent& operator= (const PopupMenuCustomComponent&); }; #endif // __JUCE_POPUPMENUCUSTOMCOMPONENT_JUCEHEADER__ /********* End of inlined file: juce_PopupMenuCustomComponent.h *********/ -/** Creates and displays a popup-menu. - - To show a popup-menu, you create one of these, add some items to it, then - call its show() method, which returns the id of the item the user selects. - - E.g. @code - void MyWidget::mouseDown (const MouseEvent& e) - { - PopupMenu m; - m.addItem (1, "item 1"); - m.addItem (2, "item 2"); - - const int result = m.show(); - - if (result == 0) - { - // user dismissed the menu without picking anything - } - else if (result == 1) - { - // user picked item 1 - } - else if (result == 2) - { - // user picked item 2 - } - } - @endcode - - Submenus are easy too: @code - - void MyWidget::mouseDown (const MouseEvent& e) - { - PopupMenu subMenu; - subMenu.addItem (1, "item 1"); - subMenu.addItem (2, "item 2"); - - PopupMenu mainMenu; - mainMenu.addItem (3, "item 3"); - mainMenu.addSubMenu ("other choices", subMenu); - - const int result = m.show(); - - ...etc - } - @endcode -*/ class JUCE_API PopupMenu { public: - /** Creates an empty popup menu. */ - PopupMenu(); + PopupMenu(); - /** Creates a copy of another menu. */ - PopupMenu (const PopupMenu& other); + PopupMenu (const PopupMenu& other); - /** Destructor. */ - ~PopupMenu(); + ~PopupMenu(); - /** Copies this menu from another one. */ - const PopupMenu& operator= (const PopupMenu& other); + const PopupMenu& operator= (const PopupMenu& other); - /** Resets the menu, removing all its items. */ - void clear(); + void clear(); - /** Appends a new text item for this menu to show. + void addItem (const int itemResultId, + const String& itemText, + const bool isActive = true, + const bool isTicked = false, + const Image* const iconToUse = 0); - @param itemResultId the number that will be returned from the show() method - if the user picks this item. The value should never be - zero, because that's used to indicate that the user didn't - select anything. - @param itemText the text to show. - @param isActive if false, the item will be shown 'greyed-out' and can't be - picked - @param isTicked if true, the item will be shown with a tick next to it - @param iconToUse if this is non-zero, it should be an image that will be - displayed to the left of the item. This method will take its - own copy of the image passed-in, so there's no need to keep - it hanging around. + void addCommandItem (ApplicationCommandManager* commandManager, + const int commandID, + const String& displayName = String::empty); - @see addSeparator, addColouredItem, addCustomItem, addSubMenu - */ - void addItem (const int itemResultId, - const String& itemText, - const bool isActive = true, - const bool isTicked = false, - const Image* const iconToUse = 0); + void addColouredItem (const int itemResultId, + const String& itemText, + const Colour& itemTextColour, + const bool isActive = true, + const bool isTicked = false, + const Image* const iconToUse = 0); - /** Adds an item that represents one of the commands in a command manager object. + void addCustomItem (const int itemResultId, + PopupMenuCustomComponent* const customComponent); - @param commandManager the manager to use to trigger the command and get information - about it - @param commandID the ID of the command - @param displayName if this is non-empty, then this string will be used instead of - the command's registered name - */ - void addCommandItem (ApplicationCommandManager* commandManager, - const int commandID, - const String& displayName = String::empty); + void addCustomItem (const int itemResultId, + Component* customComponent, + int idealWidth, int idealHeight, + const bool triggerMenuItemAutomaticallyWhenClicked); - /** Appends a text item with a special colour. + void addSubMenu (const String& subMenuName, + const PopupMenu& subMenu, + const bool isActive = true, + Image* const iconToUse = 0, + const bool isTicked = false); - This is the same as addItem(), but specifies a colour to use for the - text, which will override the default colours that are used by the - current look-and-feel. See addItem() for a description of the parameters. - */ - void addColouredItem (const int itemResultId, - const String& itemText, - const Colour& itemTextColour, - const bool isActive = true, - const bool isTicked = false, - const Image* const iconToUse = 0); + void addSeparator(); - /** Appends a custom menu item. + void addSectionHeader (const String& title); - This will add a user-defined component to use as a menu item. The component - passed in will be deleted by this menu when it's no longer needed. + int getNumItems() const; - @see PopupMenuCustomComponent - */ - void addCustomItem (const int itemResultId, - PopupMenuCustomComponent* const customComponent); + bool containsCommandItem (const int commandID) const; - /** Appends a custom menu item that can't be used to trigger a result. + bool containsAnyActiveItems() const; - This will add a user-defined component to use as a menu item. Unlike the - addCustomItem() method that takes a PopupMenuCustomComponent, this version - can't trigger a result from it, so doesn't take a menu ID. It also doesn't - delete the component when it's finished, so it's the caller's responsibility - to manage the component that is passed-in. + int show (const int itemIdThatMustBeVisible = 0, + const int minimumWidth = 0, + const int maximumNumColumns = 0, + const int standardItemHeight = 0); - if triggerMenuItemAutomaticallyWhenClicked is true, the menu itself will handle - detection of a mouse-click on your component, and use that to trigger the - menu ID specified in itemResultId. If this is false, the menu item can't - be triggered, so itemResultId is not used. + int showAt (const int screenX, + const int screenY, + const int itemIdThatMustBeVisible = 0, + const int minimumWidth = 0, + const int maximumNumColumns = 0, + const int standardItemHeight = 0); - @see PopupMenuCustomComponent - */ - void addCustomItem (const int itemResultId, - Component* customComponent, - int idealWidth, int idealHeight, - const bool triggerMenuItemAutomaticallyWhenClicked); + int showAt (Component* componentToAttachTo, + const int itemIdThatMustBeVisible = 0, + const int minimumWidth = 0, + const int maximumNumColumns = 0, + const int standardItemHeight = 0); - /** Appends a sub-menu. + static void JUCE_CALLTYPE dismissAllActiveMenus(); - If the menu that's passed in is empty, it will appear as an inactive item. - */ - void addSubMenu (const String& subMenuName, - const PopupMenu& subMenu, - const bool isActive = true, - Image* const iconToUse = 0, - const bool isTicked = false); + void setLookAndFeel (LookAndFeel* const newLookAndFeel); - /** Appends a separator to the menu, to help break it up into sections. + enum ColourIds + { + backgroundColourId = 0x1000700, /**< The colour to fill the menu's background with. */ + textColourId = 0x1000600, /**< The colour for normal menu item text, (unless the + colour is specified when the item is added). */ + headerTextColourId = 0x1000601, /**< The colour for section header item text (see the + addSectionHeader() method). */ + highlightedBackgroundColourId = 0x1000900, /**< The colour to fill the background of the currently + highlighted menu item. */ + highlightedTextColourId = 0x1000800, /**< The colour to use for the text of the currently + highlighted item. */ + }; - The menu class is smart enough not to display separators at the top or bottom - of the menu, and it will replace mutliple adjacent separators with a single - one, so your code can be quite free and easy about adding these, and it'll - always look ok. - */ - void addSeparator(); + class JUCE_API MenuItemIterator + { + public: - /** Adds a non-clickable text item to the menu. + MenuItemIterator (const PopupMenu& menu); - This is a bold-font items which can be used as a header to separate the items - into named groups. - */ - void addSectionHeader (const String& title); + ~MenuItemIterator(); - /** Returns the number of items that the menu currently contains. + bool next(); - (This doesn't count separators). - */ - int getNumItems() const; + String itemName; + const PopupMenu* subMenu; + int itemId; + bool isSeparator; + bool isTicked; + bool isEnabled; + bool isCustomComponent; + bool isSectionHeader; + const Colour* customColour; + const Image* customImage; + ApplicationCommandManager* commandManager; - /** Returns true if the menu contains a command item that triggers the given command. */ - bool containsCommandItem (const int commandID) const; + juce_UseDebuggingNewOperator - /** Returns true if the menu contains any items that can be used. */ - bool containsAnyActiveItems() const; + private: + const PopupMenu& menu; + int index; - /** Displays the menu and waits for the user to pick something. + MenuItemIterator (const MenuItemIterator&); + const MenuItemIterator& operator= (const MenuItemIterator&); + }; - This will display the menu modally, and return the ID of the item that the - user picks. If they click somewhere off the menu to get rid of it without - choosing anything, this will return 0. - - The current location of the mouse will be used as the position to show the - menu - to explicitly set the menu's position, use showAt() instead. Depending - on where this point is on the screen, the menu will appear above, below or - to the side of the point. - - @param itemIdThatMustBeVisible if you set this to the ID of one of the menu items, - then when the menu first appears, it will make sure - that this item is visible. So if the menu has too many - items to fit on the screen, it will be scrolled to a - position where this item is visible. - @param minimumWidth a minimum width for the menu, in pixels. It may be wider - than this if some items are too long to fit. - @param maximumNumColumns if there are too many items to fit on-screen in a single - vertical column, the menu may be laid out as a series of - columns - this is the maximum number allowed. To use the - default value for this (probably about 7), you can pass - in zero. - @param standardItemHeight if this is non-zero, it will be used as the standard - height for menu items (apart from custom items) - @see showAt - */ - int show (const int itemIdThatMustBeVisible = 0, - const int minimumWidth = 0, - const int maximumNumColumns = 0, - const int standardItemHeight = 0); - - /** Displays the menu at a specific location. - - This is the same as show(), but uses a specific location (in global screen - co-ordinates) rather than the current mouse position. - - Note that the co-ordinates don't specify the top-left of the menu - they - indicate a point of interest, and the menu will position itself nearby to - this point, trying to keep it fully on-screen. - - @see show() - */ - int showAt (const int screenX, - const int screenY, - const int itemIdThatMustBeVisible = 0, - const int minimumWidth = 0, - const int maximumNumColumns = 0, - const int standardItemHeight = 0); - - /** Displays the menu as if it's attached to a component such as a button. - - This is similar to showAt(), but will position it next to the given component, e.g. - so that the menu's edge is aligned with that of the component. This is intended for - things like buttons that trigger a pop-up menu. - */ - int showAt (Component* componentToAttachTo, - const int itemIdThatMustBeVisible = 0, - const int minimumWidth = 0, - const int maximumNumColumns = 0, - const int standardItemHeight = 0); - - /** Closes any menus that are currently open. - - This might be useful if you have a situation where your window is being closed - by some means other than a user action, and you'd like to make sure that menus - aren't left hanging around. - */ - static void JUCE_CALLTYPE dismissAllActiveMenus(); - - /** Specifies a look-and-feel for the menu and any sub-menus that it has. - - This can be called before show() if you need a customised menu. Be careful - not to delete the LookAndFeel object before the menu has been deleted. - */ - void setLookAndFeel (LookAndFeel* const newLookAndFeel); - - /** A set of colour IDs to use to change the colour of various aspects of the menu. - - These constants can be used either via the LookAndFeel::setColour() - method for the look and feel that is set for this menu with setLookAndFeel() - - @see setLookAndFeel, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1000700, /**< The colour to fill the menu's background with. */ - textColourId = 0x1000600, /**< The colour for normal menu item text, (unless the - colour is specified when the item is added). */ - headerTextColourId = 0x1000601, /**< The colour for section header item text (see the - addSectionHeader() method). */ - highlightedBackgroundColourId = 0x1000900, /**< The colour to fill the background of the currently - highlighted menu item. */ - highlightedTextColourId = 0x1000800, /**< The colour to use for the text of the currently - highlighted item. */ - }; - - /** - Allows you to iterate through the items in a pop-up menu, and examine - their properties. - - To use this, just create one and repeatedly call its next() method. When this - returns true, all the member variables of the iterator are filled-out with - information describing the menu item. When it returns false, the end of the - list has been reached. - */ - class JUCE_API MenuItemIterator - { - public: - - /** Creates an iterator that will scan through the items in the specified - menu. - - Be careful not to add any items to a menu while it is being iterated, - or things could get out of step. - */ - MenuItemIterator (const PopupMenu& menu); - - /** Destructor. */ - ~MenuItemIterator(); - - /** Returns true if there is another item, and sets up all this object's - member variables to reflect that item's properties. - */ - bool next(); - - String itemName; - const PopupMenu* subMenu; - int itemId; - bool isSeparator; - bool isTicked; - bool isEnabled; - bool isCustomComponent; - bool isSectionHeader; - const Colour* customColour; - const Image* customImage; - ApplicationCommandManager* commandManager; - - juce_UseDebuggingNewOperator - - private: - const PopupMenu& menu; - int index; - - MenuItemIterator (const MenuItemIterator&); - const MenuItemIterator& operator= (const MenuItemIterator&); - }; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class PopupMenuWindow; - friend class MenuItemIterator; - VoidArray items; - LookAndFeel* lookAndFeel; - bool separatorPending; + friend class PopupMenuWindow; + friend class MenuItemIterator; + VoidArray items; + LookAndFeel* lookAndFeel; + bool separatorPending; - void addSeparatorIfPending(); + void addSeparatorIfPending(); - int showMenu (const int x, const int y, const int w, const int h, - const int itemIdThatMustBeVisible, - const int minimumWidth, - const int maximumNumColumns, - const int standardItemHeight, - const bool alignToRectangle, - Component* const componentAttachedTo); + int showMenu (const int x, const int y, const int w, const int h, + const int itemIdThatMustBeVisible, + const int minimumWidth, + const int maximumNumColumns, + const int standardItemHeight, + const bool alignToRectangle, + Component* const componentAttachedTo); - friend class MenuBarComponent; - Component* createMenuComponent (const int x, const int y, const int w, const int h, - const int itemIdThatMustBeVisible, - const int minimumWidth, - const int maximumNumColumns, - const int standardItemHeight, - const bool alignToRectangle, - Component* menuBarComponent, - ApplicationCommandManager** managerOfChosenCommand, - Component* const componentAttachedTo); + friend class MenuBarComponent; + Component* createMenuComponent (const int x, const int y, const int w, const int h, + const int itemIdThatMustBeVisible, + const int minimumWidth, + const int maximumNumColumns, + const int standardItemHeight, + const bool alignToRectangle, + Component* menuBarComponent, + ApplicationCommandManager** managerOfChosenCommand, + Component* const componentAttachedTo); }; #endif // __JUCE_POPUPMENU_JUCEHEADER__ @@ -33274,659 +15860,305 @@ private: class TextEditor; class TextHolderComponent; -/** - Receives callbacks from a TextEditor component when it changes. - - @see TextEditor::addListener -*/ class JUCE_API TextEditorListener { public: - /** Destructor. */ - virtual ~TextEditorListener() {} + virtual ~TextEditorListener() {} - /** Called when the user changes the text in some way. */ - virtual void textEditorTextChanged (TextEditor& editor) = 0; + virtual void textEditorTextChanged (TextEditor& editor) = 0; - /** Called when the user presses the return key. */ - virtual void textEditorReturnKeyPressed (TextEditor& editor) = 0; + virtual void textEditorReturnKeyPressed (TextEditor& editor) = 0; - /** Called when the user presses the escape key. */ - virtual void textEditorEscapeKeyPressed (TextEditor& editor) = 0; + virtual void textEditorEscapeKeyPressed (TextEditor& editor) = 0; - /** Called when the text editor loses focus. */ - virtual void textEditorFocusLost (TextEditor& editor) = 0; + virtual void textEditorFocusLost (TextEditor& editor) = 0; }; -/** - A component containing text that can be edited. - - A TextEditor can either be in single- or multi-line mode, and supports mixed - fonts and colours. - - @see TextEditorListener, Label -*/ class JUCE_API TextEditor : public Component, - public SettableTooltipClient + public SettableTooltipClient { public: - /** Creates a new, empty text editor. + TextEditor (const String& componentName = String::empty, + const tchar passwordCharacter = 0); - @param componentName the name to pass to the component for it to use as its name - @param passwordCharacter if this is not zero, this character will be used as a replacement - for all characters that are drawn on screen - e.g. to create - a password-style textbox containing circular blobs instead of text, - you could set this value to 0x25cf, which is the unicode character - for a black splodge (not all fonts include this, though), or 0x2022, - which is a bullet (probably the best choice for linux). - */ - TextEditor (const String& componentName = String::empty, - const tchar passwordCharacter = 0); + virtual ~TextEditor(); - /** Destructor. */ - virtual ~TextEditor(); + void setMultiLine (const bool shouldBeMultiLine, + const bool shouldWordWrap = true); - /** Puts the editor into either multi- or single-line mode. + bool isMultiLine() const; - By default, the editor will be in single-line mode, so use this if you need a multi-line - editor. + void setReturnKeyStartsNewLine (const bool shouldStartNewLine); - See also the setReturnKeyStartsNewLine() method, which will also need to be turned - on if you want a multi-line editor with line-breaks. + bool getReturnKeyStartsNewLine() const { return returnKeyStartsNewLine; } - @see isMultiLine, setReturnKeyStartsNewLine - */ - void setMultiLine (const bool shouldBeMultiLine, - const bool shouldWordWrap = true); + void setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed); - /** Returns true if the editor is in multi-line mode. - */ - bool isMultiLine() const; + bool isTabKeyUsedAsCharacter() const { return tabKeyUsed; } - /** Changes the behaviour of the return key. + void setReadOnly (const bool shouldBeReadOnly); - If set to true, the return key will insert a new-line into the text; if false - it will trigger a call to the TextEditorListener::textEditorReturnKeyPressed() - method. By default this is set to false, and when true it will only insert - new-lines when in multi-line mode (see setMultiLine()). - */ - void setReturnKeyStartsNewLine (const bool shouldStartNewLine); + bool isReadOnly() const; - /** Returns the value set by setReturnKeyStartsNewLine(). + void setCaretVisible (const bool shouldBeVisible); - See setReturnKeyStartsNewLine() for more info. - */ - bool getReturnKeyStartsNewLine() const { return returnKeyStartsNewLine; } + bool isCaretVisible() const { return caretVisible; } - /** Indicates whether the tab key should be accepted and used to input a tab character, - or whether it gets ignored. + void setScrollbarsShown (bool shouldBeEnabled); - By default the tab key is ignored, so that it can be used to switch keyboard focus - between components. - */ - void setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed); + bool areScrollbarsShown() const { return scrollbarVisible; } - /** Returns true if the tab key is being used for input. - @see setTabKeyUsedAsCharacter - */ - bool isTabKeyUsedAsCharacter() const { return tabKeyUsed; } + void setPasswordCharacter (const tchar passwordCharacter); - /** Changes the editor to read-only mode. + tchar getPasswordCharacter() const { return passwordCharacter; } - By default, the text editor is not read-only. If you're making it read-only, you - might also want to call setCaretVisible (false) to get rid of the caret. + void setPopupMenuEnabled (const bool menuEnabled); - The text can still be highlighted and copied when in read-only mode. + bool isPopupMenuEnabled() const { return popupMenuEnabled; } - @see isReadOnly, setCaretVisible - */ - void setReadOnly (const bool shouldBeReadOnly); + bool isPopupMenuCurrentlyActive() const { return menuActive; } - /** Returns true if the editor is in read-only mode. - */ - bool isReadOnly() const; + enum ColourIds + { + backgroundColourId = 0x1000200, /**< The colour to use for the text component's background - this can be + transparent if necessary. */ - /** Makes the caret visible or invisible. + textColourId = 0x1000201, /**< The colour that will be used when text is added to the editor. Note + that because the editor can contain multiple colours, calling this + method won't change the colour of existing text - to do that, call + applyFontToAllText() after calling this method.*/ - By default the caret is visible. + highlightColourId = 0x1000202, /**< The colour with which to fill the background of highlighted sections of + the text - this can be transparent if you don't want to show any + highlighting.*/ - @see setCaretColour, setCaretPosition - */ - void setCaretVisible (const bool shouldBeVisible); + highlightedTextColourId = 0x1000203, /**< The colour with which to draw the text in highlighted sections. */ - /** Returns true if the caret is enabled. - @see setCaretVisible - */ - bool isCaretVisible() const { return caretVisible; } + caretColourId = 0x1000204, /**< The colour with which to draw the caret. */ - /** Enables/disables a vertical scrollbar. + outlineColourId = 0x1000205, /**< If this is non-transparent, it will be used to draw a box around + the edge of the component. */ - (This only applies when in multi-line mode). When the text gets too long to fit - in the component, a scrollbar can appear to allow it to be scrolled. Even when - this is enabled, the scrollbar will be hidden unless it's needed. + focusedOutlineColourId = 0x1000206, /**< If this is non-transparent, it will be used to draw a box around + the edge of the component when it has focus. */ - By default the scrollbar is enabled. - */ - void setScrollbarsShown (bool shouldBeEnabled); + shadowColourId = 0x1000207, /**< If this is non-transparent, it'll be used to draw an inner shadow + around the edge of the editor. */ + }; - /** Returns true if scrollbars are enabled. - @see setScrollbarsShown - */ - bool areScrollbarsShown() const { return scrollbarVisible; } + void setFont (const Font& newFont); - /** Changes the password character used to disguise the text. + void applyFontToAllText (const Font& newFont); - @param passwordCharacter if this is not zero, this character will be used as a replacement - for all characters that are drawn on screen - e.g. to create - a password-style textbox containing circular blobs instead of text, - you could set this value to 0x25cf, which is the unicode character - for a black splodge (not all fonts include this, though), or 0x2022, - which is a bullet (probably the best choice for linux). - */ - void setPasswordCharacter (const tchar passwordCharacter); + const Font getFont() const; - /** Returns the current password character. - @see setPasswordCharacter -l */ - tchar getPasswordCharacter() const { return passwordCharacter; } + void setSelectAllWhenFocused (const bool b); - /** Allows a right-click menu to appear for the editor. + void setInputRestrictions (const int maxTextLength, + const String& allowedCharacters = String::empty); - (This defaults to being enabled). + void setTextToShowWhenEmpty (const String& text, const Colour& colourToUse); - If enabled, right-clicking (or command-clicking on the Mac) will pop up a menu - of options such as cut/copy/paste, undo/redo, etc. - */ - void setPopupMenuEnabled (const bool menuEnabled); + void setScrollBarThickness (const int newThicknessPixels); - /** Returns true if the right-click menu is enabled. - @see setPopupMenuEnabled - */ - bool isPopupMenuEnabled() const { return popupMenuEnabled; } + void setScrollBarButtonVisibility (const bool buttonsVisible); - /** Returns true if a popup-menu is currently being displayed. - */ - bool isPopupMenuCurrentlyActive() const { return menuActive; } + void addListener (TextEditorListener* const newListener); - /** A set of colour IDs to use to change the colour of various aspects of the editor. + void removeListener (TextEditorListener* const listenerToRemove); - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. + const String getText() const; - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1000200, /**< The colour to use for the text component's background - this can be - transparent if necessary. */ + const String getTextSubstring (const int startCharacter, const int endCharacter) const; - textColourId = 0x1000201, /**< The colour that will be used when text is added to the editor. Note - that because the editor can contain multiple colours, calling this - method won't change the colour of existing text - to do that, call - applyFontToAllText() after calling this method.*/ + bool isEmpty() const; - highlightColourId = 0x1000202, /**< The colour with which to fill the background of highlighted sections of - the text - this can be transparent if you don't want to show any - highlighting.*/ + void setText (const String& newText, + const bool sendTextChangeMessage = true); - highlightedTextColourId = 0x1000203, /**< The colour with which to draw the text in highlighted sections. */ + Value& getTextValue(); - caretColourId = 0x1000204, /**< The colour with which to draw the caret. */ + void insertTextAtCursor (String textToInsert); - outlineColourId = 0x1000205, /**< If this is non-transparent, it will be used to draw a box around - the edge of the component. */ + void clear(); - focusedOutlineColourId = 0x1000206, /**< If this is non-transparent, it will be used to draw a box around - the edge of the component when it has focus. */ + void cut(); - shadowColourId = 0x1000207, /**< If this is non-transparent, it'll be used to draw an inner shadow - around the edge of the editor. */ - }; + void copy(); - /** Sets the font to use for newly added text. + void paste(); - This will change the font that will be used next time any text is added or entered - into the editor. It won't change the font of any existing text - to do that, use - applyFontToAllText() instead. + void setCaretPosition (const int newIndex); - @see applyFontToAllText - */ - void setFont (const Font& newFont); + int getCaretPosition() const; - /** Applies a font to all the text in the editor. + void scrollEditorToPositionCaret (const int desiredCaretX, + const int desiredCaretY); - This will also set the current font to use for any new text that's added. + const Rectangle getCaretRectangle(); - @see setFont - */ - void applyFontToAllText (const Font& newFont); + void setHighlightedRegion (int startIndex, + int numberOfCharactersToHighlight); - /** Returns the font that's currently being used for new text. + int getHighlightedRegionStart() const { return selectionStart; } - @see setFont - */ - const Font getFont() const; + int getHighlightedRegionLength() const { return jmax (0, selectionEnd - selectionStart); } - /** If set to true, focusing on the editor will highlight all its text. + const String getHighlightedText() const; - (Set to false by default). + int getTextIndexAt (const int x, const int y); - This is useful for boxes where you expect the user to re-enter all the - text when they focus on the component, rather than editing what's already there. - */ - void setSelectAllWhenFocused (const bool b); + int getTotalNumChars() const; - /** Sets limits on the characters that can be entered. + int getTextWidth() const; - @param maxTextLength if this is > 0, it sets a maximum length limit; if 0, no - limit is set - @param allowedCharacters if this is non-empty, then only characters that occur in - this string are allowed to be entered into the editor. - */ - void setInputRestrictions (const int maxTextLength, - const String& allowedCharacters = String::empty); + int getTextHeight() const; - /** When the text editor is empty, it can be set to display a message. + void setIndents (const int newLeftIndent, const int newTopIndent); - This is handy for things like telling the user what to type in the box - the - string is only displayed, it's not taken to actually be the contents of - the editor. - */ - void setTextToShowWhenEmpty (const String& text, const Colour& colourToUse); + void setBorder (const BorderSize& border); - /** Changes the size of the scrollbars that are used. + const BorderSize getBorder() const; - Handy if you need smaller scrollbars for a small text box. - */ - void setScrollBarThickness (const int newThicknessPixels); + void setScrollToShowCursor (const bool shouldScrollToShowCursor); - /** Shows or hides the buttons on any scrollbars that are used. + void paint (Graphics& g); + void paintOverChildren (Graphics& g); + void mouseDown (const MouseEvent& e); + void mouseUp (const MouseEvent& e); + void mouseDrag (const MouseEvent& e); + void mouseDoubleClick (const MouseEvent& e); + void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); + bool keyPressed (const KeyPress& key); + bool keyStateChanged (const bool isKeyDown); + void focusGained (FocusChangeType cause); + void focusLost (FocusChangeType cause); + void resized(); + void enablementChanged(); + void colourChanged(); - @see ScrollBar::setButtonVisibility - */ - void setScrollBarButtonVisibility (const bool buttonsVisible); - - /** Registers a listener to be told when things happen to the text. - - @see removeListener - */ - void addListener (TextEditorListener* const newListener); - - /** Deregisters a listener. - - @see addListener - */ - void removeListener (TextEditorListener* const listenerToRemove); - - /** Returns the entire contents of the editor. */ - const String getText() const; - - /** Returns a section of the contents of the editor. */ - const String getTextSubstring (const int startCharacter, const int endCharacter) const; - - /** Returns true if there are no characters in the editor. - - This is more efficient than calling getText().isEmpty(). - */ - bool isEmpty() const; - - /** Sets the entire content of the editor. - - This will clear the editor and insert the given text (using the current text colour - and font). You can set the current text colour using - @code setColour (TextEditor::textColourId, ...); - @endcode - - @param newText the text to add - @param sendTextChangeMessage if true, this will cause a change message to - be sent to all the listeners. - @see insertText - */ - void setText (const String& newText, - const bool sendTextChangeMessage = true); - - /** Returns a Value object that can be used to get or set the text. - - Bear in mind that this operate quite slowly if your text box contains large - amounts of text, as it needs to dynamically build the string that's involved. It's - best used for small text boxes. - */ - Value& getTextValue(); - - /** Inserts some text at the current cursor position. - - If a section of the text is highlighted, it will be replaced by - this string, otherwise it will be inserted. - - To delete a section of text, you can use setHighlightedRegion() to - highlight it, and call insertTextAtCursor (String::empty). - - @see setCaretPosition, getCaretPosition, setHighlightedRegion - */ - void insertTextAtCursor (String textToInsert); - - /** Deletes all the text from the editor. */ - void clear(); - - /** Deletes the currently selected region, and puts it on the clipboard. - - @see copy, paste, SystemClipboard - */ - void cut(); - - /** Copies any currently selected region to the clipboard. - - @see cut, paste, SystemClipboard - */ - void copy(); - - /** Pastes the contents of the clipboard into the editor at the cursor position. - - @see cut, copy, SystemClipboard - */ - void paste(); - - /** Moves the caret to be in front of a given character. - - @see getCaretPosition - */ - void setCaretPosition (const int newIndex); - - /** Returns the current index of the caret. - - @see setCaretPosition - */ - int getCaretPosition() const; - - /** Attempts to scroll the text editor so that the caret ends up at - a specified position. - - This won't affect the caret's position within the text, it tries to scroll - the entire editor vertically and horizontally so that the caret is sitting - at the given position (relative to the top-left of this component). - - Depending on the amount of text available, it might not be possible to - scroll far enough for the caret to reach this exact position, but it - will go as far as it can in that direction. - */ - void scrollEditorToPositionCaret (const int desiredCaretX, - const int desiredCaretY); - - /** Get the graphical position of the caret. - - The rectangle returned is relative to the component's top-left corner. - @see scrollEditorToPositionCaret - */ - const Rectangle getCaretRectangle(); - - /** Selects a section of the text. - */ - void setHighlightedRegion (int startIndex, - int numberOfCharactersToHighlight); - - /** Returns the first character that is selected. - - If nothing is selected, this will still return a character index, but getHighlightedRegionLength() - will return 0. - - @see setHighlightedRegion, getHighlightedRegionLength - */ - int getHighlightedRegionStart() const { return selectionStart; } - - /** Returns the number of characters that are selected. - - @see setHighlightedRegion, getHighlightedRegionStart - */ - int getHighlightedRegionLength() const { return jmax (0, selectionEnd - selectionStart); } - - /** Returns the section of text that is currently selected. */ - const String getHighlightedText() const; - - /** Finds the index of the character at a given position. - - The co-ordinates are relative to the component's top-left. - */ - int getTextIndexAt (const int x, const int y); - - /** Counts the number of characters in the text. - - This is quicker than getting the text as a string if you just need to know - the length. - */ - int getTotalNumChars() const; - - /** Returns the total width of the text, as it is currently laid-out. - - This may be larger than the size of the TextEditor, and can change when - the TextEditor is resized or the text changes. - */ - int getTextWidth() const; - - /** Returns the maximum height of the text, as it is currently laid-out. - - This may be larger than the size of the TextEditor, and can change when - the TextEditor is resized or the text changes. - */ - int getTextHeight() const; - - /** Changes the size of the gap at the top and left-edge of the editor. - - By default there's a gap of 4 pixels. - */ - void setIndents (const int newLeftIndent, const int newTopIndent); - - /** Changes the size of border left around the edge of the component. - - @see getBorder - */ - void setBorder (const BorderSize& border); - - /** Returns the size of border around the edge of the component. - - @see setBorder - */ - const BorderSize getBorder() const; - - /** Used to disable the auto-scrolling which keeps the cursor visible. - - If true (the default), the editor will scroll when the cursor moves offscreen. If - set to false, it won't. - */ - void setScrollToShowCursor (const bool shouldScrollToShowCursor); - - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void paintOverChildren (Graphics& g); - /** @internal */ - void mouseDown (const MouseEvent& e); - /** @internal */ - void mouseUp (const MouseEvent& e); - /** @internal */ - void mouseDrag (const MouseEvent& e); - /** @internal */ - void mouseDoubleClick (const MouseEvent& e); - /** @internal */ - void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); - /** @internal */ - bool keyPressed (const KeyPress& key); - /** @internal */ - bool keyStateChanged (const bool isKeyDown); - /** @internal */ - void focusGained (FocusChangeType cause); - /** @internal */ - void focusLost (FocusChangeType cause); - /** @internal */ - void resized(); - /** @internal */ - void enablementChanged(); - /** @internal */ - void colourChanged(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** This adds the items to the popup menu. + virtual void addPopupMenuItems (PopupMenu& menuToAddTo, + const MouseEvent* mouseClickEvent); - By default it adds the cut/copy/paste items, but you can override this if - you need to replace these with your own items. + virtual void performPopupMenuAction (const int menuItemID); - If you want to add your own items to the existing ones, you can override this, - call the base class's addPopupMenuItems() method, then append your own items. + void scrollToMakeSureCursorIsVisible(); - When the menu has been shown, performPopupMenuAction() will be called to - perform the item that the user has chosen. + void moveCaret (int newCaretPos); - The default menu items will be added using item IDs in the range - 0x7fff0000 - 0x7fff1000, so you should avoid those values for your own - menu IDs. + void moveCursorTo (const int newPosition, const bool isSelecting); - If this was triggered by a mouse-click, the mouseClickEvent parameter will be - a pointer to the info about it, or may be null if the menu is being triggered - by some other means. + void textChanged(); - @see performPopupMenuAction, setPopupMenuEnabled, isPopupMenuEnabled - */ - virtual void addPopupMenuItems (PopupMenu& menuToAddTo, - const MouseEvent* mouseClickEvent); + void newTransaction(); - /** This is called to perform one of the items that was shown on the popup menu. + void doUndoRedo (const bool isRedo); - If you've overridden addPopupMenuItems(), you should also override this - to perform the actions that you've added. + virtual void returnPressed(); - If you've overridden addPopupMenuItems() but have still left the default items - on the menu, remember to call the superclass's performPopupMenuAction() - so that it can perform the default actions if that's what the user clicked on. + virtual void escapePressed(); - @see addPopupMenuItems, setPopupMenuEnabled, isPopupMenuEnabled - */ - virtual void performPopupMenuAction (const int menuItemID); - - /** Scrolls the minimum distance needed to get the caret into view. */ - void scrollToMakeSureCursorIsVisible(); - - /** @internal */ - void moveCaret (int newCaretPos); - - /** @internal */ - void moveCursorTo (const int newPosition, const bool isSelecting); - - /** Used internally to dispatch a text-change message. */ - void textChanged(); - - /** Begins a new transaction in the UndoManager. - */ - void newTransaction(); - - /** Used internally to trigger an undo or redo. */ - void doUndoRedo (const bool isRedo); - - /** Can be overridden to intercept return key presses directly */ - virtual void returnPressed(); - - /** Can be overridden to intercept escape key presses directly */ - virtual void escapePressed(); - - /** @internal */ - void handleCommandMessage (int commandId); + void handleCommandMessage (int commandId); private: - ScopedPointer viewport; - TextHolderComponent* textHolder; - BorderSize borderSize; + ScopedPointer viewport; + TextHolderComponent* textHolder; + BorderSize borderSize; - bool readOnly : 1; - bool multiline : 1; - bool wordWrap : 1; - bool returnKeyStartsNewLine : 1; - bool caretVisible : 1; - bool popupMenuEnabled : 1; - bool selectAllTextWhenFocused : 1; - bool scrollbarVisible : 1; - bool wasFocused : 1; - bool caretFlashState : 1; - bool keepCursorOnScreen : 1; - bool tabKeyUsed : 1; - bool menuActive : 1; - bool valueTextNeedsUpdating : 1; + bool readOnly : 1; + bool multiline : 1; + bool wordWrap : 1; + bool returnKeyStartsNewLine : 1; + bool caretVisible : 1; + bool popupMenuEnabled : 1; + bool selectAllTextWhenFocused : 1; + bool scrollbarVisible : 1; + bool wasFocused : 1; + bool caretFlashState : 1; + bool keepCursorOnScreen : 1; + bool tabKeyUsed : 1; + bool menuActive : 1; + bool valueTextNeedsUpdating : 1; - UndoManager undoManager; - float cursorX, cursorY, cursorHeight; - int maxTextLength; - int selectionStart, selectionEnd; - int leftIndent, topIndent; - unsigned int lastTransactionTime; - Font currentFont; - mutable int totalNumChars; - int caretPosition; - VoidArray sections; - String textToShowWhenEmpty; - Colour colourForTextWhenEmpty; - tchar passwordCharacter; - Value textValue; + UndoManager undoManager; + float cursorX, cursorY, cursorHeight; + int maxTextLength; + int selectionStart, selectionEnd; + int leftIndent, topIndent; + unsigned int lastTransactionTime; + Font currentFont; + mutable int totalNumChars; + int caretPosition; + VoidArray sections; + String textToShowWhenEmpty; + Colour colourForTextWhenEmpty; + tchar passwordCharacter; + Value textValue; - enum - { - notDragging, - draggingSelectionStart, - draggingSelectionEnd - } dragType; + enum + { + notDragging, + draggingSelectionStart, + draggingSelectionEnd + } dragType; - String allowedCharacters; - SortedSet listeners; + String allowedCharacters; + SortedSet listeners; - friend class TextEditorInsertAction; - friend class TextEditorRemoveAction; + friend class TextEditorInsertAction; + friend class TextEditorRemoveAction; - void coalesceSimilarSections(); - void splitSection (const int sectionIndex, const int charToSplitAt); + void coalesceSimilarSections(); + void splitSection (const int sectionIndex, const int charToSplitAt); - void clearInternal (UndoManager* const um); + void clearInternal (UndoManager* const um); - void insert (const String& text, - const int insertIndex, - const Font& font, - const Colour& colour, - UndoManager* const um, - const int caretPositionToMoveTo); + void insert (const String& text, + const int insertIndex, + const Font& font, + const Colour& colour, + UndoManager* const um, + const int caretPositionToMoveTo); - void reinsert (const int insertIndex, - const VoidArray& sections); + void reinsert (const int insertIndex, + const VoidArray& sections); - void remove (const int startIndex, - int endIndex, - UndoManager* const um, - const int caretPositionToMoveTo); + void remove (const int startIndex, + int endIndex, + UndoManager* const um, + const int caretPositionToMoveTo); - void getCharPosition (const int index, - float& x, float& y, - float& lineHeight) const; + void getCharPosition (const int index, + float& x, float& y, + float& lineHeight) const; - void updateCaretPosition(); + void updateCaretPosition(); - void textWasChangedByValue(); + void textWasChangedByValue(); - int indexAtPosition (const float x, - const float y); + int indexAtPosition (const float x, + const float y); - int findWordBreakAfter (const int position) const; - int findWordBreakBefore (const int position) const; + int findWordBreakAfter (const int position) const; + int findWordBreakBefore (const int position) const; - friend class TextHolderComponent; - friend class TextEditorViewport; - void drawContent (Graphics& g); - void updateTextHolderSize(); - float getWordWrapWidth() const; - void timerCallbackInt(); - void repaintCaret(); - void repaintText (int textStartIndex, int textEndIndex); + friend class TextHolderComponent; + friend class TextEditorViewport; + void drawContent (Graphics& g); + void updateTextHolderSize(); + float getWordWrapWidth() const; + void timerCallbackInt(); + void repaintCaret(); + void repaintText (int textStartIndex, int textEndIndex); - TextEditor (const TextEditor&); - const TextEditor& operator= (const TextEditor&); + TextEditor (const TextEditor&); + const TextEditor& operator= (const TextEditor&); }; #endif // __JUCE_TEXTEDITOR_JUCEHEADER__ @@ -33934,297 +16166,141 @@ private: class Label; -/** - A class for receiving events from a Label. - - You can register a LabelListener with a Label using the Label::addListener() - method, and it will be called when the text of the label changes, either because - of a call to Label::setText() or by the user editing the text (if the label is - editable). - - @see Label::addListener, Label::removeListener -*/ class JUCE_API LabelListener { public: - /** Destructor. */ - virtual ~LabelListener() {} + virtual ~LabelListener() {} - /** Called when a Label's text has changed. - */ - virtual void labelTextChanged (Label* labelThatHasChanged) = 0; + virtual void labelTextChanged (Label* labelThatHasChanged) = 0; }; -/** - A component that displays a text string, and can optionally become a text - editor when clicked. -*/ class JUCE_API Label : public Component, - public SettableTooltipClient, - protected TextEditorListener, - private ComponentListener + public SettableTooltipClient, + protected TextEditorListener, + private ComponentListener, + private Value::Listener { public: - /** Creates a Label. + Label (const String& componentName, + const String& labelText); - @param componentName the name to give the component - @param labelText the text to show in the label - */ - Label (const String& componentName, - const String& labelText); + ~Label(); - /** Destructor. */ - ~Label(); + void setText (const String& newText, + const bool broadcastChangeMessage); - /** Changes the label text. + const String getText (const bool returnActiveEditorContents = false) const throw(); - If broadcastChangeMessage is true and the new text is different to the current - text, then the class will broadcast a change message to any LabelListeners that - are registered. - */ - void setText (const String& newText, - const bool broadcastChangeMessage); + Value& getTextValue() { return textValue; } - /** Returns the label's current text. + void setFont (const Font& newFont) throw(); - @param returnActiveEditorContents if this is true and the label is currently - being edited, then this method will return the - text as it's being shown in the editor. If false, - then the value returned here won't be updated until - the user has finished typing and pressed the return - key. - */ - const String getText (const bool returnActiveEditorContents = false) const throw(); + const Font& getFont() const throw(); - /** Changes the font to use to draw the text. + enum ColourIds + { + backgroundColourId = 0x1000280, /**< The background colour to fill the label with. */ + textColourId = 0x1000281, /**< The colour for the text. */ + outlineColourId = 0x1000282 /**< An optional colour to use to draw a border around the label. + Leave this transparent to not have an outline. */ + }; - @see getFont - */ - void setFont (const Font& newFont) throw(); + void setJustificationType (const Justification& justification) throw(); - /** Returns the font currently being used. + const Justification getJustificationType() const throw() { return justification; } - @see setFont - */ - const Font& getFont() const throw(); + void setBorderSize (int horizontalBorder, int verticalBorder); - /** A set of colour IDs to use to change the colour of various aspects of the label. + int getHorizontalBorderSize() const throw() { return horizontalBorderSize; } - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. + int getVerticalBorderSize() const throw() { return verticalBorderSize; } - Note that you can also use the constants from TextEditor::ColourIds to change the - colour of the text editor that is opened when a label is editable. + void attachToComponent (Component* owner, + const bool onLeft); - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1000280, /**< The background colour to fill the label with. */ - textColourId = 0x1000281, /**< The colour for the text. */ - outlineColourId = 0x1000282 /**< An optional colour to use to draw a border around the label. - Leave this transparent to not have an outline. */ - }; + Component* getAttachedComponent() const throw() { return ownerComponent; } - /** Sets the style of justification to be used for positioning the text. + bool isAttachedOnLeft() const throw() { return leftOfOwnerComp; } - (The default is Justification::centredLeft) - */ - void setJustificationType (const Justification& justification) throw(); + void setMinimumHorizontalScale (const float newScale); - /** Returns the type of justification, as set in setJustificationType(). */ - const Justification getJustificationType() const throw() { return justification; } + float getMinimumHorizontalScale() const throw() { return minimumHorizontalScale; } - /** Changes the gap that is left between the edge of the component and the text. - By default there's a small gap left at the sides of the component to allow for - the drawing of the border, but you can change this if necessary. - */ - void setBorderSize (int horizontalBorder, int verticalBorder); + void addListener (LabelListener* const listener) throw(); - /** Returns the size of the horizontal gap being left around the text. - */ - int getHorizontalBorderSize() const throw() { return horizontalBorderSize; } + void removeListener (LabelListener* const listener) throw(); - /** Returns the size of the vertical gap being left around the text. - */ - int getVerticalBorderSize() const throw() { return verticalBorderSize; } + void setEditable (const bool editOnSingleClick, + const bool editOnDoubleClick = false, + const bool lossOfFocusDiscardsChanges = false) throw(); - /** Makes this label "stick to" another component. + bool isEditableOnSingleClick() const throw() { return editSingleClick; } - This will cause the label to follow another component around, staying - either to its left or above it. + bool isEditableOnDoubleClick() const throw() { return editDoubleClick; } - @param owner the component to follow - @param onLeft if true, the label will stay on the left of its component; if - false, it will stay above it. - */ - void attachToComponent (Component* owner, - const bool onLeft); + bool doesLossOfFocusDiscardChanges() const throw() { return lossOfFocusDiscardsChanges; } - /** If this label has been attached to another component using attachToComponent, this - returns the other component. + bool isEditable() const throw() { return editSingleClick || editDoubleClick; } - Returns 0 if the label is not attached. - */ - Component* getAttachedComponent() const throw() { return ownerComponent; } + void showEditor(); - /** If the label is attached to the left of another component, this returns true. + void hideEditor (const bool discardCurrentEditorContents); - Returns false if the label is above the other component. This is only relevent if - attachToComponent() has been called. - */ - bool isAttachedOnLeft() const throw() { return leftOfOwnerComp; } + bool isBeingEdited() const throw(); - /** Specifies the minimum amount that the font can be squashed horizantally before it starts - using ellipsis. - - @see Graphics::drawFittedText - */ - void setMinimumHorizontalScale (const float newScale); - - float getMinimumHorizontalScale() const throw() { return minimumHorizontalScale; } - - /** Registers a listener that will be called when the label's text changes. */ - void addListener (LabelListener* const listener) throw(); - - /** Deregisters a previously-registered listener. */ - void removeListener (LabelListener* const listener) throw(); - - /** Makes the label turn into a TextEditor when clicked. - - By default this is turned off. - - If turned on, then single- or double-clicking will turn the label into - an editor. If the user then changes the text, then the ChangeBroadcaster - base class will be used to send change messages to any listeners that - have registered. - - If the user changes the text, the textWasEdited() method will be called - afterwards, and subclasses can override this if they need to do anything - special. - - @param editOnSingleClick if true, just clicking once on the label will start editing the text - @param editOnDoubleClick if true, a double-click is needed to start editing - @param lossOfFocusDiscardsChanges if true, clicking somewhere else while the text is being - edited will discard any changes; if false, then this will - commit the changes. - @see showEditor, setEditorColours, TextEditor - */ - void setEditable (const bool editOnSingleClick, - const bool editOnDoubleClick = false, - const bool lossOfFocusDiscardsChanges = false) throw(); - - /** Returns true if this option was set using setEditable(). */ - bool isEditableOnSingleClick() const throw() { return editSingleClick; } - - /** Returns true if this option was set using setEditable(). */ - bool isEditableOnDoubleClick() const throw() { return editDoubleClick; } - - /** Returns true if this option has been set in a call to setEditable(). */ - bool doesLossOfFocusDiscardChanges() const throw() { return lossOfFocusDiscardsChanges; } - - /** Returns true if the user can edit this label's text. */ - bool isEditable() const throw() { return editSingleClick || editDoubleClick; } - - /** Makes the editor appear as if the label had been clicked by the user. - - @see textWasEdited, setEditable - */ - void showEditor(); - - /** Hides the editor if it was being shown. - - @param discardCurrentEditorContents if true, the label's text will be - reset to whatever it was before the editor - was shown; if false, the current contents of the - editor will be used to set the label's text - before it is hidden. - */ - void hideEditor (const bool discardCurrentEditorContents); - - /** Returns true if the editor is currently focused and active. */ - bool isBeingEdited() const throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void resized(); - /** @internal */ - void mouseUp (const MouseEvent& e); - /** @internal */ - void mouseDoubleClick (const MouseEvent& e); - /** @internal */ - void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); - /** @internal */ - void componentParentHierarchyChanged (Component& component); - /** @internal */ - void componentVisibilityChanged (Component& component); - /** @internal */ - void inputAttemptWhenModal(); - /** @internal */ - void focusGained (FocusChangeType); - /** @internal */ - void enablementChanged(); - /** @internal */ - KeyboardFocusTraverser* createFocusTraverser(); - /** @internal */ - void textEditorTextChanged (TextEditor& editor); - /** @internal */ - void textEditorReturnKeyPressed (TextEditor& editor); - /** @internal */ - void textEditorEscapeKeyPressed (TextEditor& editor); - /** @internal */ - void textEditorFocusLost (TextEditor& editor); - /** @internal */ - void colourChanged(); + virtual TextEditor* createEditorComponent(); - /** Creates the TextEditor component that will be used when the user has clicked on the label. + virtual void textWasEdited(); - Subclasses can override this if they need to customise this component in some way. - */ - virtual TextEditor* createEditorComponent(); + virtual void textWasChanged(); - /** Called after the user changes the text. - */ - virtual void textWasEdited(); + virtual void editorShown (TextEditor* editorComponent); - /** Called when the text has been altered. - */ - virtual void textWasChanged(); + virtual void editorAboutToBeHidden (TextEditor* editorComponent); - /** Called when the text editor has just appeared, due to a user click or other - focus change. - */ - virtual void editorShown (TextEditor* editorComponent); - - /** Called when the text editor is going to be deleted, after editing has finished. - */ - virtual void editorAboutToBeHidden (TextEditor* editorComponent); + void paint (Graphics& g); + void resized(); + void mouseUp (const MouseEvent& e); + void mouseDoubleClick (const MouseEvent& e); + void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); + void componentParentHierarchyChanged (Component& component); + void componentVisibilityChanged (Component& component); + void inputAttemptWhenModal(); + void focusGained (FocusChangeType); + void enablementChanged(); + KeyboardFocusTraverser* createFocusTraverser(); + void textEditorTextChanged (TextEditor& editor); + void textEditorReturnKeyPressed (TextEditor& editor); + void textEditorEscapeKeyPressed (TextEditor& editor); + void textEditorFocusLost (TextEditor& editor); + void colourChanged(); + void valueChanged (Value&); private: - String text; - Font font; - Justification justification; - ScopedPointer editor; - SortedSet listeners; - Component* ownerComponent; - ScopedPointer deletionWatcher; - int horizontalBorderSize, verticalBorderSize; - float minimumHorizontalScale; - bool editSingleClick : 1; - bool editDoubleClick : 1; - bool lossOfFocusDiscardsChanges : 1; - bool leftOfOwnerComp : 1; + Value textValue; + String lastTextValue; + Font font; + Justification justification; + ScopedPointer editor; + SortedSet listeners; + Component* ownerComponent; + ScopedPointer deletionWatcher; + int horizontalBorderSize, verticalBorderSize; + float minimumHorizontalScale; + bool editSingleClick : 1; + bool editDoubleClick : 1; + bool lossOfFocusDiscardsChanges : 1; + bool leftOfOwnerComp : 1; - bool updateFromTextEditorContents(); - void callChangeListeners(); + bool updateFromTextEditorContents(); + void callChangeListeners(); - Label (const Label&); - const Label& operator= (const Label&); + Label (const Label&); + const Label& operator= (const Label&); }; #endif // __JUCE_LABEL_JUCEHEADER__ @@ -34232,798 +16308,319 @@ private: class ComboBox; -/** - A class for receiving events from a ComboBox. - - You can register a ComboBoxListener with a ComboBox using the ComboBox::addListener() - method, and it will be called when the selected item in the box changes. - - @see ComboBox::addListener, ComboBox::removeListener -*/ class JUCE_API ComboBoxListener { public: - /** Destructor. */ - virtual ~ComboBoxListener() {} + virtual ~ComboBoxListener() {} - /** Called when a ComboBox has its selected item changed. - */ - virtual void comboBoxChanged (ComboBox* comboBoxThatHasChanged) = 0; + virtual void comboBoxChanged (ComboBox* comboBoxThatHasChanged) = 0; }; -/** - A component that lets the user choose from a drop-down list of choices. - - The combo-box has a list of text strings, each with an associated id number, - that will be shown in the drop-down list when the user clicks on the component. - - The currently selected choice is displayed in the combo-box, and this can - either be read-only text, or editable. - - To find out when the user selects a different item or edits the text, you - can register a ComboBoxListener to receive callbacks. - - @see ComboBoxListener -*/ class JUCE_API ComboBox : public Component, - public SettableTooltipClient, - private LabelListener, - private AsyncUpdater + public SettableTooltipClient, + private LabelListener, + private AsyncUpdater, + private Value::Listener { public: - /** Creates a combo-box. + ComboBox (const String& componentName); - On construction, the text field will be empty, so you should call the - setSelectedId() or setText() method to choose the initial value before - displaying it. + ~ComboBox(); - @param componentName the name to set for the component (see Component::setName()) - */ - ComboBox (const String& componentName); + void setEditableText (const bool isEditable); - /** Destructor. */ - ~ComboBox(); + bool isTextEditable() const throw(); - /** Sets whether the test in the combo-box is editable. + void setJustificationType (const Justification& justification) throw(); - The default state for a new ComboBox is non-editable, and can only be changed - by choosing from the drop-down list. - */ - void setEditableText (const bool isEditable); + const Justification getJustificationType() const throw(); - /** Returns true if the text is directly editable. - @see setEditableText - */ - bool isTextEditable() const throw(); + void addItem (const String& newItemText, + const int newItemId) throw(); - /** Sets the style of justification to be used for positioning the text. + void addSeparator() throw(); - The default is Justification::centredLeft. The text is displayed using a - Label component inside the ComboBox. - */ - void setJustificationType (const Justification& justification) throw(); + void addSectionHeading (const String& headingName) throw(); - /** Returns the current justification for the text box. - @see setJustificationType - */ - const Justification getJustificationType() const throw(); + void setItemEnabled (const int itemId, + const bool shouldBeEnabled) throw(); - /** Adds an item to be shown in the drop-down list. + void changeItemText (const int itemId, + const String& newText) throw(); - @param newItemText the text of the item to show in the list - @param newItemId an associated ID number that can be set or retrieved - see - getSelectedId() and setSelectedId() - @see setItemEnabled, addSeparator, addSectionHeading, removeItem, getNumItems, getItemText, getItemId - */ - void addItem (const String& newItemText, - const int newItemId) throw(); + void clear (const bool dontSendChangeMessage = false); - /** Adds a separator line to the drop-down list. + int getNumItems() const throw(); - This is like adding a separator to a popup menu. See PopupMenu::addSeparator(). - */ - void addSeparator() throw(); + const String getItemText (const int index) const throw(); - /** Adds a heading to the drop-down list, so that you can group the items into - different sections. + int getItemId (const int index) const throw(); - The headings are indented slightly differently to set them apart from the - items on the list, and obviously can't be selected. You might want to add - separators between your sections too. + int indexOfItemId (const int itemId) const throw(); - @see addItem, addSeparator - */ - void addSectionHeading (const String& headingName) throw(); + int getSelectedId() const throw(); - /** This allows items in the drop-down list to be selectively disabled. + Value& getSelectedIdAsValue() throw() { return currentId; } - When you add an item, it's enabled by default, but you can call this - method to change its status. + void setSelectedId (const int newItemId, + const bool dontSendChangeMessage = false) throw(); - If you disable an item which is already selected, this won't change the - current selection - it just stops the user choosing that item from the list. - */ - void setItemEnabled (const int itemId, - const bool shouldBeEnabled) throw(); + int getSelectedItemIndex() const throw(); - /** Changes the text for an existing item. - */ - void changeItemText (const int itemId, - const String& newText) throw(); + void setSelectedItemIndex (const int newItemIndex, + const bool dontSendChangeMessage = false) throw(); - /** Removes all the items from the drop-down list. + const String getText() const throw(); - If this call causes the content to be cleared, then a change-message - will be broadcast unless dontSendChangeMessage is true. + void setText (const String& newText, + const bool dontSendChangeMessage = false) throw(); - @see addItem, removeItem, getNumItems - */ - void clear (const bool dontSendChangeMessage = false); + void showEditor(); - /** Returns the number of items that have been added to the list. + void addListener (ComboBoxListener* const listener) throw(); - Note that this doesn't include headers or separators. - */ - int getNumItems() const throw(); + void removeListener (ComboBoxListener* const listener) throw(); - /** Returns the text for one of the items in the list. + void setTextWhenNothingSelected (const String& newMessage) throw(); - Note that this doesn't include headers or separators. + const String getTextWhenNothingSelected() const throw(); - @param index the item's index from 0 to (getNumItems() - 1) - */ - const String getItemText (const int index) const throw(); + void setTextWhenNoChoicesAvailable (const String& newMessage) throw(); - /** Returns the ID for one of the items in the list. + const String getTextWhenNoChoicesAvailable() const throw(); - Note that this doesn't include headers or separators. + void setTooltip (const String& newTooltip); - @param index the item's index from 0 to (getNumItems() - 1) - */ - int getItemId (const int index) const throw(); + enum ColourIds + { + backgroundColourId = 0x1000b00, /**< The background colour to fill the box with. */ + textColourId = 0x1000a00, /**< The colour for the text in the box. */ + outlineColourId = 0x1000c00, /**< The colour for an outline around the box. */ + buttonColourId = 0x1000d00, /**< The base colour for the button (a LookAndFeel class will probably use variations on this). */ + arrowColourId = 0x1000e00, /**< The colour for the arrow shape that pops up the menu */ + }; - /** Returns the ID of the item that's currently shown in the box. + void labelTextChanged (Label*); + void enablementChanged(); + void colourChanged(); + void focusGained (Component::FocusChangeType cause); + void focusLost (Component::FocusChangeType cause); + void handleAsyncUpdate(); + const String getTooltip() { return label->getTooltip(); } + void mouseDown (const MouseEvent&); + void mouseDrag (const MouseEvent&); + void mouseUp (const MouseEvent&); + void lookAndFeelChanged(); + void paint (Graphics&); + void resized(); + bool keyStateChanged (const bool isKeyDown); + bool keyPressed (const KeyPress&); + void valueChanged (Value&); - If no item is selected, or if the text is editable and the user - has entered something which isn't one of the items in the list, then - this will return 0. - - @see setSelectedId, getSelectedItemIndex, getText - */ - int getSelectedId() const throw(); - - /** Sets one of the items to be the current selection. - - This will set the ComboBox's text to that of the item that matches - this ID. - - @param newItemId the new item to select - @param dontSendChangeMessage if set to true, this method won't trigger a - change notification - @see getSelectedId, setSelectedItemIndex, setText - */ - void setSelectedId (const int newItemId, - const bool dontSendChangeMessage = false) throw(); - - /** Returns the index of the item that's currently shown in the box. - - If no item is selected, or if the text is editable and the user - has entered something which isn't one of the items in the list, then - this will return -1. - - @see setSelectedItemIndex, getSelectedId, getText - */ - int getSelectedItemIndex() const throw(); - - /** Sets one of the items to be the current selection. - - This will set the ComboBox's text to that of the item at the given - index in the list. - - @param newItemIndex the new item to select - @param dontSendChangeMessage if set to true, this method won't trigger a - change notification - @see getSelectedItemIndex, setSelectedId, setText - */ - void setSelectedItemIndex (const int newItemIndex, - const bool dontSendChangeMessage = false) throw(); - - /** Returns the text that is currently shown in the combo-box's text field. - - If the ComboBox has editable text, then this text may have been edited - by the user; otherwise it will be one of the items from the list, or - possibly an empty string if nothing was selected. - - @see setText, getSelectedId, getSelectedItemIndex - */ - const String getText() const throw(); - - /** Sets the contents of the combo-box's text field. - - The text passed-in will be set as the current text regardless of whether - it is one of the items in the list. If the current text isn't one of the - items, then getSelectedId() will return -1, otherwise it wil return - the approriate ID. - - @param newText the text to select - @param dontSendChangeMessage if set to true, this method won't trigger a - change notification - @see getText - */ - void setText (const String& newText, - const bool dontSendChangeMessage = false) throw(); - - /** Programmatically opens the text editor to allow the user to edit the current item. - - This is the same effect as when the box is clicked-on. - @see Label::showEditor(); - */ - void showEditor(); - - /** Registers a listener that will be called when the box's content changes. */ - void addListener (ComboBoxListener* const listener) throw(); - - /** Deregisters a previously-registered listener. */ - void removeListener (ComboBoxListener* const listener) throw(); - - /** Sets a message to display when there is no item currently selected. - - @see getTextWhenNothingSelected - */ - void setTextWhenNothingSelected (const String& newMessage) throw(); - - /** Returns the text that is shown when no item is selected. - - @see setTextWhenNothingSelected - */ - const String getTextWhenNothingSelected() const throw(); - - /** Sets the message to show when there are no items in the list, and the user clicks - on the drop-down box. - - By default it just says "no choices", but this lets you change it to something more - meaningful. - */ - void setTextWhenNoChoicesAvailable (const String& newMessage) throw(); - - /** Returns the text shown when no items have been added to the list. - @see setTextWhenNoChoicesAvailable - */ - const String getTextWhenNoChoicesAvailable() const throw(); - - /** Gives the ComboBox a tooltip. */ - void setTooltip (const String& newTooltip); - - /** A set of colour IDs to use to change the colour of various aspects of the combo box. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - To change the colours of the menu that pops up - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1000b00, /**< The background colour to fill the box with. */ - textColourId = 0x1000a00, /**< The colour for the text in the box. */ - outlineColourId = 0x1000c00, /**< The colour for an outline around the box. */ - buttonColourId = 0x1000d00, /**< The base colour for the button (a LookAndFeel class will probably use variations on this). */ - arrowColourId = 0x1000e00, /**< The colour for the arrow shape that pops up the menu */ - }; - - /** @internal */ - void labelTextChanged (Label*); - /** @internal */ - void enablementChanged(); - /** @internal */ - void colourChanged(); - /** @internal */ - void focusGained (Component::FocusChangeType cause); - /** @internal */ - void focusLost (Component::FocusChangeType cause); - /** @internal */ - void handleAsyncUpdate(); - /** @internal */ - const String getTooltip() { return label->getTooltip(); } - /** @internal */ - void mouseDown (const MouseEvent&); - /** @internal */ - void mouseDrag (const MouseEvent&); - /** @internal */ - void mouseUp (const MouseEvent&); - /** @internal */ - void lookAndFeelChanged(); - /** @internal */ - void paint (Graphics&); - /** @internal */ - void resized(); - /** @internal */ - bool keyStateChanged (const bool isKeyDown); - /** @internal */ - bool keyPressed (const KeyPress&); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - struct ItemInfo - { - String name; - int itemId; - bool isEnabled : 1, isHeading : 1; + struct ItemInfo + { + String name; + int itemId; + bool isEnabled : 1, isHeading : 1; - bool isSeparator() const throw(); - bool isRealItem() const throw(); - }; + bool isSeparator() const throw(); + bool isRealItem() const throw(); + }; - OwnedArray items; - int currentIndex; - bool isButtonDown; - bool separatorPending; - bool menuActive; - SortedSet listeners; - Label* label; - String textWhenNothingSelected, noChoicesMessage; + OwnedArray items; + Value currentId; + int lastCurrentId; + bool isButtonDown, separatorPending, menuActive, textIsCustom; + SortedSet listeners; + Label* label; + String textWhenNothingSelected, noChoicesMessage; - void showPopup(); + void showPopup(); - ItemInfo* getItemForId (const int itemId) const throw(); - ItemInfo* getItemForIndex (const int index) const throw(); + ItemInfo* getItemForId (const int itemId) const throw(); + ItemInfo* getItemForIndex (const int index) const throw(); - ComboBox (const ComboBox&); - const ComboBox& operator= (const ComboBox&); + ComboBox (const ComboBox&); + const ComboBox& operator= (const ComboBox&); }; #endif // __JUCE_COMBOBOX_JUCEHEADER__ /********* End of inlined file: juce_ComboBox.h *********/ -/** - Manages the state of some audio and midi i/o devices. - - This class keeps tracks of a currently-selected audio device, through - with which it continuously streams data from an audio callback, as well as - one or more midi inputs. - - The idea is that your application will create one global instance of this object, - and let it take care of creating and deleting specific types of audio devices - internally. So when the device is changed, your callbacks will just keep running - without having to worry about this. - - The manager can save and reload all of its device settings as XML, which - makes it very easy for you to save and reload the audio setup of your - application. - - And to make it easy to let the user change its settings, there's a component - to do just that - the AudioDeviceSelectorComponent class, which contains a set of - device selection/sample-rate/latency controls. - - To use an AudioDeviceManager, create one, and use initialise() to set it up. Then - call addAudioCallback() to register your audio callback with it, and use that to process - your audio data. - - The manager also acts as a handy hub for incoming midi messages, allowing a - listener to register for messages from either a specific midi device, or from whatever - the current default midi input device is. The listener then doesn't have to worry about - re-registering with different midi devices if they are changed or deleted. - - And yet another neat trick is that amount of CPU time being used is measured and - available with the getCpuUsage() method. - - The AudioDeviceManager is a ChangeBroadcaster, and will send a change message to - listeners whenever one of its settings is changed. - - @see AudioDeviceSelectorComponent, AudioIODevice, AudioIODeviceType -*/ class JUCE_API AudioDeviceManager : public ChangeBroadcaster { public: - /** Creates a default AudioDeviceManager. - - Initially no audio device will be selected. You should call the initialise() method - and register an audio callback with setAudioCallback() before it'll be able to - actually make any noise. - */ - AudioDeviceManager(); - - /** Destructor. */ - ~AudioDeviceManager(); - - /** - This structure holds a set of properties describing the current audio setup. - - @see AudioDeviceManager::setAudioDeviceSetup() - */ - struct JUCE_API AudioDeviceSetup - { - AudioDeviceSetup(); - bool operator== (const AudioDeviceSetup& other) const; - - /** The name of the audio device used for output. - The name has to be one of the ones listed by the AudioDeviceManager's currently - selected device type. - This may be the same as the input device. - */ - String outputDeviceName; - - /** The name of the audio device used for input. - This may be the same as the output device. - */ - String inputDeviceName; - - /** The current sample rate. - This rate is used for both the input and output devices. - */ - double sampleRate; - - /** The buffer size, in samples. - This buffer size is used for both the input and output devices. - */ - int bufferSize; - - /** The set of active input channels. - The bits that are set in this array indicate the channels of the - input device that are active. - */ - BitArray inputChannels; - - /** If this is true, it indicates that the inputChannels array - should be ignored, and instead, the device's default channels - should be used. - */ - bool useDefaultInputChannels; - - /** The set of active output channels. - The bits that are set in this array indicate the channels of the - input device that are active. - */ - BitArray outputChannels; - - /** If this is true, it indicates that the outputChannels array - should be ignored, and instead, the device's default channels - should be used. - */ - bool useDefaultOutputChannels; - }; - - /** Opens a set of audio devices ready for use. - - This will attempt to open either a default audio device, or one that was - previously saved as XML. - - @param numInputChannelsNeeded a minimum number of input channels needed - by your app. - @param numOutputChannelsNeeded a minimum number of output channels to open - @param savedState either a previously-saved state that was produced - by createStateXml(), or 0 if you want the manager - to choose the best device to open. - @param selectDefaultDeviceOnFailure if true, then if the device specified in the XML - fails to open, then a default device will be used - instead. If false, then on failure, no device is - opened. - @param preferredDefaultDeviceName if this is not empty, and there's a device with this - name, then that will be used as the default device - (assuming that there wasn't one specified in the XML). - The string can actually be a simple wildcard, containing "*" - and "?" characters - @param preferredSetupOptions if this is non-null, the structure will be used as the - set of preferred settings when opening the device. If you - use this parameter, the preferredDefaultDeviceName - field will be ignored - - @returns an error message if anything went wrong, or an empty string if it worked ok. - */ - const String initialise (const int numInputChannelsNeeded, - const int numOutputChannelsNeeded, - const XmlElement* const savedState, - const bool selectDefaultDeviceOnFailure, - const String& preferredDefaultDeviceName = String::empty, - const AudioDeviceSetup* preferredSetupOptions = 0); - - /** Returns some XML representing the current state of the manager. - - This stores the current device, its samplerate, block size, etc, and - can be restored later with initialise(). - */ - XmlElement* createStateXml() const; - - /** Returns the current device properties that are in use. - - @see setAudioDeviceSetup - */ - void getAudioDeviceSetup (AudioDeviceSetup& setup); - - /** Changes the current device or its settings. - - If you want to change a device property, like the current sample rate or - block size, you can call getAudioDeviceSetup() to retrieve the current - settings, then tweak the appropriate fields in the AudioDeviceSetup structure, - and pass it back into this method to apply the new settings. - - @param newSetup the settings that you'd like to use - @param treatAsChosenDevice if this is true and if the device opens correctly, these new - settings will be taken as having been explicitly chosen by the - user, and the next time createStateXml() is called, these settings - will be returned. If it's false, then the device is treated as a - temporary or default device, and a call to createStateXml() will - return either the last settings that were made with treatAsChosenDevice - as true, or the last XML settings that were passed into initialise(). - @returns an error message if anything went wrong, or an empty string if it worked ok. - - @see getAudioDeviceSetup - */ - const String setAudioDeviceSetup (const AudioDeviceSetup& newSetup, - const bool treatAsChosenDevice); - - /** Returns the currently-active audio device. */ - AudioIODevice* getCurrentAudioDevice() const throw() { return currentAudioDevice; } - - /** Returns the type of audio device currently in use. - @see setCurrentAudioDeviceType - */ - const String getCurrentAudioDeviceType() const throw() { return currentDeviceType; } - - /** Returns the currently active audio device type object. - Don't keep a copy of this pointer - it's owned by the device manager and could - change at any time. - */ - AudioIODeviceType* getCurrentDeviceTypeObject() const; - - /** Changes the class of audio device being used. - - This switches between, e.g. ASIO and DirectSound. On the Mac you probably won't ever call - this because there's only one type: CoreAudio. - - For a list of types, see getAvailableDeviceTypes(). - */ - void setCurrentAudioDeviceType (const String& type, - const bool treatAsChosenDevice); - - /** Closes the currently-open device. - - You can call restartLastAudioDevice() later to reopen it in the same state - that it was just in. - */ - void closeAudioDevice(); + AudioDeviceManager(); - /** Tries to reload the last audio device that was running. + ~AudioDeviceManager(); - Note that this only reloads the last device that was running before - closeAudioDevice() was called - it doesn't reload any kind of saved-state, - and can only be called after a device has been opened with SetAudioDevice(). + struct JUCE_API AudioDeviceSetup + { + AudioDeviceSetup(); + bool operator== (const AudioDeviceSetup& other) const; - If a device is already open, this call will do nothing. - */ - void restartLastAudioDevice(); + String outputDeviceName; - /** Registers an audio callback to be used. + String inputDeviceName; - The manager will redirect callbacks from whatever audio device is currently - in use to all registered callback objects. If more than one callback is - active, they will all be given the same input data, and their outputs will - be summed. + double sampleRate; - If necessary, this method will invoke audioDeviceAboutToStart() on the callback - object before returning. + int bufferSize; - To remove a callback, use removeAudioCallback(). - */ - void addAudioCallback (AudioIODeviceCallback* newCallback); + BitArray inputChannels; - /** Deregisters a previously added callback. + bool useDefaultInputChannels; - If necessary, this method will invoke audioDeviceStopped() on the callback - object before returning. + BitArray outputChannels; - @see addAudioCallback - */ - void removeAudioCallback (AudioIODeviceCallback* callback); + bool useDefaultOutputChannels; + }; - /** Returns the average proportion of available CPU being spent inside the audio callbacks. + const String initialise (const int numInputChannelsNeeded, + const int numOutputChannelsNeeded, + const XmlElement* const savedState, + const bool selectDefaultDeviceOnFailure, + const String& preferredDefaultDeviceName = String::empty, + const AudioDeviceSetup* preferredSetupOptions = 0); - Returns a value between 0 and 1.0 - */ - double getCpuUsage() const; + XmlElement* createStateXml() const; - /** Enables or disables a midi input device. + void getAudioDeviceSetup (AudioDeviceSetup& setup); - The list of devices can be obtained with the MidiInput::getDevices() method. + const String setAudioDeviceSetup (const AudioDeviceSetup& newSetup, + const bool treatAsChosenDevice); - Any incoming messages from enabled input devices will be forwarded on to all the - listeners that have been registered with the addMidiInputCallback() method. They - can either register for messages from a particular device, or from just the - "default" midi input. + AudioIODevice* getCurrentAudioDevice() const throw() { return currentAudioDevice; } - Routing the midi input via an AudioDeviceManager means that when a listener - registers for the default midi input, this default device can be changed by the - manager without the listeners having to know about it or re-register. + const String getCurrentAudioDeviceType() const throw() { return currentDeviceType; } - It also means that a listener can stay registered for a midi input that is disabled - or not present, so that when the input is re-enabled, the listener will start - receiving messages again. + AudioIODeviceType* getCurrentDeviceTypeObject() const; - @see addMidiInputCallback, isMidiInputEnabled - */ - void setMidiInputEnabled (const String& midiInputDeviceName, - const bool enabled); + void setCurrentAudioDeviceType (const String& type, + const bool treatAsChosenDevice); - /** Returns true if a given midi input device is being used. + void closeAudioDevice(); - @see setMidiInputEnabled - */ - bool isMidiInputEnabled (const String& midiInputDeviceName) const; + void restartLastAudioDevice(); - /** Registers a listener for callbacks when midi events arrive from a midi input. + void addAudioCallback (AudioIODeviceCallback* newCallback); - The device name can be empty to indicate that it wants events from whatever the - current "default" device is. Or it can be the name of one of the midi input devices - (see MidiInput::getDevices() for the names). + void removeAudioCallback (AudioIODeviceCallback* callback); - Only devices which are enabled (see the setMidiInputEnabled() method) will have their - events forwarded on to listeners. - */ - void addMidiInputCallback (const String& midiInputDeviceName, - MidiInputCallback* callback); + double getCpuUsage() const; - /** Removes a listener that was previously registered with addMidiInputCallback(). - */ - void removeMidiInputCallback (const String& midiInputDeviceName, - MidiInputCallback* callback); + void setMidiInputEnabled (const String& midiInputDeviceName, + const bool enabled); - /** Sets a midi output device to use as the default. + bool isMidiInputEnabled (const String& midiInputDeviceName) const; - The list of devices can be obtained with the MidiOutput::getDevices() method. + void addMidiInputCallback (const String& midiInputDeviceName, + MidiInputCallback* callback); - The specified device will be opened automatically and can be retrieved with the - getDefaultMidiOutput() method. + void removeMidiInputCallback (const String& midiInputDeviceName, + MidiInputCallback* callback); - Pass in an empty string to deselect all devices. For the default device, you - can use MidiOutput::getDevices() [MidiOutput::getDefaultDeviceIndex()]. + void setDefaultMidiOutput (const String& deviceName); - @see getDefaultMidiOutput, getDefaultMidiOutputName - */ - void setDefaultMidiOutput (const String& deviceName); + const String getDefaultMidiOutputName() const throw() { return defaultMidiOutputName; } - /** Returns the name of the default midi output. + MidiOutput* getDefaultMidiOutput() const throw() { return defaultMidiOutput; } - @see setDefaultMidiOutput, getDefaultMidiOutput - */ - const String getDefaultMidiOutputName() const throw() { return defaultMidiOutputName; } + const OwnedArray & getAvailableDeviceTypes(); - /** Returns the current default midi output device. + virtual void createAudioDeviceTypes (OwnedArray & types); - If no device has been selected, or the device can't be opened, this will - return 0. + void playTestSound(); - @see getDefaultMidiOutputName - */ - MidiOutput* getDefaultMidiOutput() const throw() { return defaultMidiOutput; } + void enableInputLevelMeasurement (const bool enableMeasurement); - /** Returns a list of the types of device supported. - */ - const OwnedArray & getAvailableDeviceTypes(); + double getCurrentInputLevel() const; - /** Creates a list of available types. - - This will add a set of new AudioIODeviceType objects to the specified list, to - represent each available types of device. - - You can override this if your app needs to do something specific, like avoid - using DirectSound devices, etc. - */ - virtual void createAudioDeviceTypes (OwnedArray & types); - - /** Plays a beep through the current audio device. - - This is here to allow the audio setup UI panels to easily include a "test" - button so that the user can check where the audio is coming from. - */ - void playTestSound(); - - /** Turns on level-measuring. - - When enabled, the device manager will measure the peak input level - across all channels, and you can get this level by calling getCurrentInputLevel(). - - This is mainly intended for audio setup UI panels to use to create a mic - level display, so that the user can check that they've selected the right - device. - - A simple filter is used to make the level decay smoothly, but this is - only intended for giving rough feedback, and not for any kind of accurate - measurement. - */ - void enableInputLevelMeasurement (const bool enableMeasurement); - - /** Returns the current input level. - - To use this, you must first enable it by calling enableInputLevelMeasurement(). - - See enableInputLevelMeasurement() for more info. - */ - double getCurrentInputLevel() const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OwnedArray availableDeviceTypes; - OwnedArray lastDeviceTypeConfigs; + OwnedArray availableDeviceTypes; + OwnedArray lastDeviceTypeConfigs; - AudioDeviceSetup currentSetup; - ScopedPointer currentAudioDevice; - SortedSet callbacks; - int numInputChansNeeded, numOutputChansNeeded; - String currentDeviceType; - BitArray inputChannels, outputChannels; - ScopedPointer lastExplicitSettings; - mutable bool listNeedsScanning; - bool useInputNames; - int inputLevelMeasurementEnabledCount; - double inputLevel; - ScopedPointer testSound; - int testSoundPosition; - AudioSampleBuffer tempBuffer; + AudioDeviceSetup currentSetup; + ScopedPointer currentAudioDevice; + SortedSet callbacks; + int numInputChansNeeded, numOutputChansNeeded; + String currentDeviceType; + BitArray inputChannels, outputChannels; + ScopedPointer lastExplicitSettings; + mutable bool listNeedsScanning; + bool useInputNames; + int inputLevelMeasurementEnabledCount; + double inputLevel; + ScopedPointer testSound; + int testSoundPosition; + AudioSampleBuffer tempBuffer; - StringArray midiInsFromXml; - OwnedArray enabledMidiInputs; - Array midiCallbacks; - Array midiCallbackDevices; - String defaultMidiOutputName; - ScopedPointer defaultMidiOutput; - CriticalSection audioCallbackLock, midiCallbackLock; + StringArray midiInsFromXml; + OwnedArray enabledMidiInputs; + Array midiCallbacks; + Array midiCallbackDevices; + String defaultMidiOutputName; + ScopedPointer defaultMidiOutput; + CriticalSection audioCallbackLock, midiCallbackLock; - double cpuUsageMs, timeToCpuScale; + double cpuUsageMs, timeToCpuScale; - class CallbackHandler : public AudioIODeviceCallback, - public MidiInputCallback - { - public: - AudioDeviceManager* owner; + class CallbackHandler : public AudioIODeviceCallback, + public MidiInputCallback + { + public: + AudioDeviceManager* owner; - void audioDeviceIOCallback (const float** inputChannelData, - int totalNumInputChannels, - float** outputChannelData, - int totalNumOutputChannels, - int numSamples); + void audioDeviceIOCallback (const float** inputChannelData, + int totalNumInputChannels, + float** outputChannelData, + int totalNumOutputChannels, + int numSamples); - void audioDeviceAboutToStart (AudioIODevice*); + void audioDeviceAboutToStart (AudioIODevice*); - void audioDeviceStopped(); + void audioDeviceStopped(); - void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message); - }; + void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message); + }; - CallbackHandler callbackHandler; - friend class CallbackHandler; + CallbackHandler callbackHandler; + friend class CallbackHandler; - void audioDeviceIOCallbackInt (const float** inputChannelData, - int totalNumInputChannels, - float** outputChannelData, - int totalNumOutputChannels, - int numSamples); - void audioDeviceAboutToStartInt (AudioIODevice* const device); - void audioDeviceStoppedInt(); + void audioDeviceIOCallbackInt (const float** inputChannelData, + int totalNumInputChannels, + float** outputChannelData, + int totalNumOutputChannels, + int numSamples); + void audioDeviceAboutToStartInt (AudioIODevice* const device); + void audioDeviceStoppedInt(); - void handleIncomingMidiMessageInt (MidiInput* source, const MidiMessage& message); + void handleIncomingMidiMessageInt (MidiInput* source, const MidiMessage& message); - const String restartDevice (int blockSizeToUse, double sampleRateToUse, - const BitArray& ins, const BitArray& outs); - void stopDevice(); + const String restartDevice (int blockSizeToUse, double sampleRateToUse, + const BitArray& ins, const BitArray& outs); + void stopDevice(); - void updateXml(); + void updateXml(); - void createDeviceTypesIfNeeded(); - void scanDevicesIfNeeded(); - void deleteCurrentDevice(); - double chooseBestSampleRate (double preferred) const; - void insertDefaultDeviceNames (AudioDeviceSetup& setup) const; + void createDeviceTypesIfNeeded(); + void scanDevicesIfNeeded(); + void deleteCurrentDevice(); + double chooseBestSampleRate (double preferred) const; + void insertDefaultDeviceNames (AudioDeviceSetup& setup) const; - AudioIODeviceType* findType (const String& inputName, const String& outputName); + AudioIODeviceType* findType (const String& inputName, const String& outputName); - AudioDeviceManager (const AudioDeviceManager&); - const AudioDeviceManager& operator= (const AudioDeviceManager&); + AudioDeviceManager (const AudioDeviceManager&); + const AudioDeviceManager& operator= (const AudioDeviceManager&); }; #endif // __JUCE_AUDIODEVICEMANAGER_JUCEHEADER__ @@ -35048,62 +16645,57 @@ private: #ifndef __JUCE_AUDIODATACONVERTERS_JUCEHEADER__ #define __JUCE_AUDIODATACONVERTERS_JUCEHEADER__ -/** - A set of routines to convert buffers of 32-bit floating point data to and from - various integer formats. - -*/ class JUCE_API AudioDataConverters { public: - static void convertFloatToInt16LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 2); - static void convertFloatToInt16BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 2); + static void convertFloatToInt16LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 2); + static void convertFloatToInt16BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 2); - static void convertFloatToInt24LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 3); - static void convertFloatToInt24BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 3); + static void convertFloatToInt24LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 3); + static void convertFloatToInt24BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 3); - static void convertFloatToInt32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); - static void convertFloatToInt32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); + static void convertFloatToInt32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); + static void convertFloatToInt32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); - static void convertFloatToFloat32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); - static void convertFloatToFloat32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); + static void convertFloatToFloat32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); + static void convertFloatToFloat32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample = 4); - static void convertInt16LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 2); - static void convertInt16BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 2); + static void convertInt16LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 2); + static void convertInt16BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 2); - static void convertInt24LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 3); - static void convertInt24BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 3); + static void convertInt24LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 3); + static void convertInt24BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 3); - static void convertInt32LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); - static void convertInt32BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); + static void convertInt32LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); + static void convertInt32BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); - static void convertFloat32LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); - static void convertFloat32BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); + static void convertFloat32LEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); + static void convertFloat32BEToFloat (const void* source, float* dest, int numSamples, const int srcBytesPerSample = 4); - enum DataFormat - { - int16LE, - int16BE, - int24LE, - int24BE, - int32LE, - int32BE, - float32LE, - float32BE, - }; + enum DataFormat + { + int16LE, + int16BE, + int24LE, + int24BE, + int32LE, + int32BE, + float32LE, + float32BE, + }; - static void convertFloatToFormat (const DataFormat destFormat, - const float* source, void* dest, int numSamples); + static void convertFloatToFormat (const DataFormat destFormat, + const float* source, void* dest, int numSamples); - static void convertFormatToFloat (const DataFormat sourceFormat, - const void* source, float* dest, int numSamples); + static void convertFormatToFloat (const DataFormat sourceFormat, + const void* source, float* dest, int numSamples); - static void interleaveSamples (const float** source, float* dest, - const int numSamples, const int numChannels); + static void interleaveSamples (const float** source, float* dest, + const int numSamples, const int numChannels); - static void deinterleaveSamples (const float* source, float** dest, - const int numSamples, const int numChannels); + static void deinterleaveSamples (const float* source, float** dest, + const int numSamples, const int numChannels); }; #endif // __JUCE_AUDIODATACONVERTERS_JUCEHEADER__ @@ -35129,401 +16721,150 @@ public: #ifndef __JUCE_MIDIMESSAGESEQUENCE_JUCEHEADER__ #define __JUCE_MIDIMESSAGESEQUENCE_JUCEHEADER__ -/** - A sequence of timestamped midi messages. - - This allows the sequence to be manipulated, and also to be read from and - written to a standard midi file. - - @see MidiMessage, MidiFile -*/ class JUCE_API MidiMessageSequence { public: - /** Creates an empty midi sequence object. */ - MidiMessageSequence(); + MidiMessageSequence(); - /** Creates a copy of another sequence. */ - MidiMessageSequence (const MidiMessageSequence& other); + MidiMessageSequence (const MidiMessageSequence& other); - /** Replaces this sequence with another one. */ - const MidiMessageSequence& operator= (const MidiMessageSequence& other); + const MidiMessageSequence& operator= (const MidiMessageSequence& other); - /** Destructor. */ - ~MidiMessageSequence(); + ~MidiMessageSequence(); - /** Structure used to hold midi events in the sequence. + class MidiEventHolder + { + public: - These structures act as 'handles' on the events as they are moved about in - the list, and make it quick to find the matching note-offs for note-on events. + ~MidiEventHolder(); - @see MidiMessageSequence::getEventPointer - */ - class MidiEventHolder - { - public: + MidiMessage message; - /** Destructor. */ - ~MidiEventHolder(); + MidiEventHolder* noteOffObject; - /** The message itself, whose timestamp is used to specify the event's time. - */ - MidiMessage message; + juce_UseDebuggingNewOperator - /** The matching note-off event (if this is a note-on event). + private: + friend class MidiMessageSequence; + MidiEventHolder (const MidiMessage& message); + }; - If this isn't a note-on, this pointer will be null. + void clear(); - Use the MidiMessageSequence::updateMatchedPairs() method to keep these - note-offs up-to-date after events have been moved around in the sequence - or deleted. - */ - MidiEventHolder* noteOffObject; + int getNumEvents() const; - juce_UseDebuggingNewOperator + MidiEventHolder* getEventPointer (const int index) const; - private: - friend class MidiMessageSequence; - MidiEventHolder (const MidiMessage& message); - }; + double getTimeOfMatchingKeyUp (const int index) const; - /** Clears the sequence. */ - void clear(); + int getIndexOfMatchingKeyUp (const int index) const; - /** Returns the number of events in the sequence. */ - int getNumEvents() const; + int getIndexOf (MidiEventHolder* const event) const; - /** Returns a pointer to one of the events. */ - MidiEventHolder* getEventPointer (const int index) const; + int getNextIndexAtTime (const double timeStamp) const; - /** Returns the time of the note-up that matches the note-on at this index. + double getStartTime() const; - If the event at this index isn't a note-on, it'll just return 0. + double getEndTime() const; - @see MidiMessageSequence::MidiEventHolder::noteOffObject - */ - double getTimeOfMatchingKeyUp (const int index) const; + double getEventTime (const int index) const; - /** Returns the index of the note-up that matches the note-on at this index. + void addEvent (const MidiMessage& newMessage, + double timeAdjustment = 0); - If the event at this index isn't a note-on, it'll just return -1. + void deleteEvent (const int index, + const bool deleteMatchingNoteUp); - @see MidiMessageSequence::MidiEventHolder::noteOffObject - */ - int getIndexOfMatchingKeyUp (const int index) const; + void addSequence (const MidiMessageSequence& other, + double timeAdjustmentDelta, + double firstAllowableDestTime, + double endOfAllowableDestTimes); - /** Returns the index of an event. */ - int getIndexOf (MidiEventHolder* const event) const; + void updateMatchedPairs(); - /** Returns the index of the first event on or after the given timestamp. + void extractMidiChannelMessages (const int channelNumberToExtract, + MidiMessageSequence& destSequence, + const bool alsoIncludeMetaEvents) const; - If the time is beyond the end of the sequence, this will return the - number of events. - */ - int getNextIndexAtTime (const double timeStamp) const; + void extractSysExMessages (MidiMessageSequence& destSequence) const; - /** Returns the timestamp of the first event in the sequence. + void deleteMidiChannelMessages (const int channelNumberToRemove); - @see getEndTime - */ - double getStartTime() const; + void deleteSysExMessages(); - /** Returns the timestamp of the last event in the sequence. + void addTimeToMessages (const double deltaTime); - @see getStartTime - */ - double getEndTime() const; + void createControllerUpdatesForTime (const int channelNumber, + const double time, + OwnedArray& resultMessages); - /** Returns the timestamp of the event at a given index. + juce_UseDebuggingNewOperator - If the index is out-of-range, this will return 0.0 - */ - double getEventTime (const int index) const; - - /** Inserts a midi message into the sequence. - - The index at which the new message gets inserted will depend on its timestamp, - because the sequence is kept sorted. - - Remember to call updateMatchedPairs() after adding note-on events. - - @param newMessage the new message to add (an internal copy will be made) - @param timeAdjustment an optional value to add to the timestamp of the message - that will be inserted - @see updateMatchedPairs - */ - void addEvent (const MidiMessage& newMessage, - double timeAdjustment = 0); - - /** Deletes one of the events in the sequence. - - Remember to call updateMatchedPairs() after removing events. - - @param index the index of the event to delete - @param deleteMatchingNoteUp whether to also remove the matching note-off - if the event you're removing is a note-on - */ - void deleteEvent (const int index, - const bool deleteMatchingNoteUp); - - /** Merges another sequence into this one. - - Remember to call updateMatchedPairs() after using this method. - - @param other the sequence to add from - @param timeAdjustmentDelta an amount to add to the timestamps of the midi events - as they are read from the other sequence - @param firstAllowableDestTime events will not be added if their time is earlier - than this time. (This is after their time has been adjusted - by the timeAdjustmentDelta) - @param endOfAllowableDestTimes events will not be added if their time is equal to - or greater than this time. (This is after their time has - been adjusted by the timeAdjustmentDelta) - */ - void addSequence (const MidiMessageSequence& other, - double timeAdjustmentDelta, - double firstAllowableDestTime, - double endOfAllowableDestTimes); - - /** Makes sure all the note-on and note-off pairs are up-to-date. - - Call this after moving messages about or deleting/adding messages, and it - will scan the list and make sure all the note-offs in the MidiEventHolder - structures are pointing at the correct ones. - */ - void updateMatchedPairs(); - - /** Copies all the messages for a particular midi channel to another sequence. - - @param channelNumberToExtract the midi channel to look for, in the range 1 to 16 - @param destSequence the sequence that the chosen events should be copied to - @param alsoIncludeMetaEvents if true, any meta-events (which don't apply to a specific - channel) will also be copied across. - @see extractSysExMessages - */ - void extractMidiChannelMessages (const int channelNumberToExtract, - MidiMessageSequence& destSequence, - const bool alsoIncludeMetaEvents) const; - - /** Copies all midi sys-ex messages to another sequence. - - @param destSequence this is the sequence to which any sys-exes in this sequence - will be added - @see extractMidiChannelMessages - */ - void extractSysExMessages (MidiMessageSequence& destSequence) const; - - /** Removes any messages in this sequence that have a specific midi channel. - - @param channelNumberToRemove the midi channel to look for, in the range 1 to 16 - */ - void deleteMidiChannelMessages (const int channelNumberToRemove); - - /** Removes any sys-ex messages from this sequence. - */ - void deleteSysExMessages(); - - /** Adds an offset to the timestamps of all events in the sequence. - - @param deltaTime the amount to add to each timestamp. - */ - void addTimeToMessages (const double deltaTime); - - /** Scans through the sequence to determine the state of any midi controllers at - a given time. - - This will create a sequence of midi controller changes that can be - used to set all midi controllers to the state they would be in at the - specified time within this sequence. - - As well as controllers, it will also recreate the midi program number - and pitch bend position. - - @param channelNumber the midi channel to look for, in the range 1 to 16. Controllers - for other channels will be ignored. - @param time the time at which you want to find out the state - there are - no explicit units for this time measurement, it's the same units - as used for the timestamps of the messages - @param resultMessages an array to which midi controller-change messages will be added. This - will be the minimum number of controller changes to recreate the - state at the required time. - */ - void createControllerUpdatesForTime (const int channelNumber, - const double time, - OwnedArray& resultMessages); - - juce_UseDebuggingNewOperator - - /** @internal */ - static int compareElements (const MidiMessageSequence::MidiEventHolder* const first, - const MidiMessageSequence::MidiEventHolder* const second) throw(); + static int compareElements (const MidiMessageSequence::MidiEventHolder* const first, + const MidiMessageSequence::MidiEventHolder* const second) throw(); private: - friend class MidiComparator; - friend class MidiFile; - OwnedArray list; + friend class MidiComparator; + friend class MidiFile; + OwnedArray list; - void sort(); + void sort(); }; #endif // __JUCE_MIDIMESSAGESEQUENCE_JUCEHEADER__ /********* End of inlined file: juce_MidiMessageSequence.h *********/ -/** - Reads/writes standard midi format files. - - To read a midi file, create a MidiFile object and call its readFrom() method. You - can then get the individual midi tracks from it using the getTrack() method. - - To write a file, create a MidiFile object, add some MidiMessageSequence objects - to it using the addTrack() method, and then call its writeTo() method to stream - it out. - - @see MidiMessageSequence -*/ class JUCE_API MidiFile { public: - /** Creates an empty MidiFile object. - */ - MidiFile() throw(); + MidiFile() throw(); - /** Destructor. */ - ~MidiFile() throw(); + ~MidiFile() throw(); - /** Returns the number of tracks in the file. + int getNumTracks() const throw(); - @see getTrack, addTrack - */ - int getNumTracks() const throw(); + const MidiMessageSequence* getTrack (const int index) const throw(); - /** Returns a pointer to one of the tracks in the file. + void addTrack (const MidiMessageSequence& trackSequence) throw(); - @returns a pointer to the track, or 0 if the index is out-of-range - @see getNumTracks, addTrack - */ - const MidiMessageSequence* getTrack (const int index) const throw(); + void clear() throw(); - /** Adds a midi track to the file. + short getTimeFormat() const throw(); - This will make its own internal copy of the sequence that is passed-in. + void setTicksPerQuarterNote (const int ticksPerQuarterNote) throw(); - @see getNumTracks, getTrack - */ - void addTrack (const MidiMessageSequence& trackSequence) throw(); + void setSmpteTimeFormat (const int framesPerSecond, + const int subframeResolution) throw(); - /** Removes all midi tracks from the file. + void findAllTempoEvents (MidiMessageSequence& tempoChangeEvents) const; - @see getNumTracks - */ - void clear() throw(); + void findAllTimeSigEvents (MidiMessageSequence& timeSigEvents) const; - /** Returns the raw time format code that will be written to a stream. + double getLastTimestamp() const; - After reading a midi file, this method will return the time-format that - was read from the file's header. It can be changed using the setTicksPerQuarterNote() - or setSmpteTimeFormat() methods. + bool readFrom (InputStream& sourceStream); - If the value returned is positive, it indicates the number of midi ticks - per quarter-note - see setTicksPerQuarterNote(). + bool writeTo (OutputStream& destStream); - It it's negative, the upper byte indicates the frames-per-second (but negative), and - the lower byte is the number of ticks per frame - see setSmpteTimeFormat(). - */ - short getTimeFormat() const throw(); + void convertTimestampTicksToSeconds(); - /** Sets the time format to use when this file is written to a stream. + juce_UseDebuggingNewOperator - If this is called, the file will be written as bars/beats using the - specified resolution, rather than SMPTE absolute times, as would be - used if setSmpteTimeFormat() had been called instead. - - @param ticksPerQuarterNote e.g. 96, 960 - @see setSmpteTimeFormat - */ - void setTicksPerQuarterNote (const int ticksPerQuarterNote) throw(); - - /** Sets the time format to use when this file is written to a stream. - - If this is called, the file will be written using absolute times, rather - than bars/beats as would be the case if setTicksPerBeat() had been called - instead. - - @param framesPerSecond must be 24, 25, 29 or 30 - @param subframeResolution the sub-second resolution, e.g. 4 (midi time code), - 8, 10, 80 (SMPTE bit resolution), or 100. For millisecond - timing, setSmpteTimeFormat (25, 40) - @see setTicksPerBeat - */ - void setSmpteTimeFormat (const int framesPerSecond, - const int subframeResolution) throw(); - - /** Makes a list of all the tempo-change meta-events from all tracks in the midi file. - - Useful for finding the positions of all the tempo changes in a file. - - @param tempoChangeEvents a list to which all the events will be added - */ - void findAllTempoEvents (MidiMessageSequence& tempoChangeEvents) const; - - /** Makes a list of all the time-signature meta-events from all tracks in the midi file. - - Useful for finding the positions of all the tempo changes in a file. - - @param timeSigEvents a list to which all the events will be added - */ - void findAllTimeSigEvents (MidiMessageSequence& timeSigEvents) const; - - /** Returns the latest timestamp in any of the tracks. - - (Useful for finding the length of the file). - */ - double getLastTimestamp() const; - - /** Reads a midi file format stream. - - After calling this, you can get the tracks that were read from the file by using the - getNumTracks() and getTrack() methods. - - The timestamps of the midi events in the tracks will represent their positions in - terms of midi ticks. To convert them to seconds, use the convertTimestampTicksToSeconds() - method. - - @returns true if the stream was read successfully - */ - bool readFrom (InputStream& sourceStream); - - /** Writes the midi tracks as a standard midi file. - - @returns true if the operation succeeded. - */ - bool writeTo (OutputStream& destStream); - - /** Converts the timestamp of all the midi events from midi ticks to seconds. - - This will use the midi time format and tempo/time signature info in the - tracks to convert all the timestamps to absolute values in seconds. - */ - void convertTimestampTicksToSeconds(); - - juce_UseDebuggingNewOperator - - /** @internal */ - static int compareElements (const MidiMessageSequence::MidiEventHolder* const first, - const MidiMessageSequence::MidiEventHolder* const second) throw(); + static int compareElements (const MidiMessageSequence::MidiEventHolder* const first, + const MidiMessageSequence::MidiEventHolder* const second) throw(); private: - OwnedArray tracks; - short timeFormat; + OwnedArray tracks; + short timeFormat; - MidiFile (const MidiFile&); - const MidiFile& operator= (const MidiFile&); + MidiFile (const MidiFile&); + const MidiFile& operator= (const MidiFile&); - void readNextTrack (const char* data, int size); - void writeTrack (OutputStream& mainOut, const int trackNum); + void readNextTrack (const char* data, int size); + void writeTrack (OutputStream& mainOut, const int trackNum); }; #endif // __JUCE_MIDIFILE_JUCEHEADER__ @@ -35538,174 +16879,63 @@ private: class MidiKeyboardState; -/** - Receives events from a MidiKeyboardState object. - - @see MidiKeyboardState -*/ class JUCE_API MidiKeyboardStateListener { public: - MidiKeyboardStateListener() throw() {} - virtual ~MidiKeyboardStateListener() {} + MidiKeyboardStateListener() throw() {} + virtual ~MidiKeyboardStateListener() {} - /** Called when one of the MidiKeyboardState's keys is pressed. + virtual void handleNoteOn (MidiKeyboardState* source, + int midiChannel, int midiNoteNumber, float velocity) = 0; - This will be called synchronously when the state is either processing a - buffer in its MidiKeyboardState::processNextMidiBuffer() method, or - when a note is being played with its MidiKeyboardState::noteOn() method. - - Note that this callback could happen from an audio callback thread, so be - careful not to block, and avoid any UI activity in the callback. - */ - virtual void handleNoteOn (MidiKeyboardState* source, - int midiChannel, int midiNoteNumber, float velocity) = 0; - - /** Called when one of the MidiKeyboardState's keys is released. - - This will be called synchronously when the state is either processing a - buffer in its MidiKeyboardState::processNextMidiBuffer() method, or - when a note is being played with its MidiKeyboardState::noteOff() method. - - Note that this callback could happen from an audio callback thread, so be - careful not to block, and avoid any UI activity in the callback. - */ - virtual void handleNoteOff (MidiKeyboardState* source, - int midiChannel, int midiNoteNumber) = 0; + virtual void handleNoteOff (MidiKeyboardState* source, + int midiChannel, int midiNoteNumber) = 0; }; -/** - Represents a piano keyboard, keeping track of which keys are currently pressed. - - This object can parse a stream of midi events, using them to update its idea - of which keys are pressed for each individiual midi channel. - - When keys go up or down, it can broadcast these events to listener objects. - - It also allows key up/down events to be triggered with its noteOn() and noteOff() - methods, and midi messages for these events will be merged into the - midi stream that gets processed by processNextMidiBuffer(). -*/ class JUCE_API MidiKeyboardState { public: - MidiKeyboardState(); - ~MidiKeyboardState(); + MidiKeyboardState(); + ~MidiKeyboardState(); - /** Resets the state of the object. + void reset(); - All internal data for all the channels is reset, but no events are sent as a - result. + bool isNoteOn (const int midiChannel, const int midiNoteNumber) const throw(); - If you want to release any keys that are currently down, and to send out note-up - midi messages for this, use the allNotesOff() method instead. - */ - void reset(); + bool isNoteOnForChannels (const int midiChannelMask, const int midiNoteNumber) const throw(); - /** Returns true if the given midi key is currently held down for the given midi channel. + void noteOn (const int midiChannel, const int midiNoteNumber, const float velocity); - The channel number must be between 1 and 16. If you want to see if any notes are - on for a range of channels, use the isNoteOnForChannels() method. - */ - bool isNoteOn (const int midiChannel, const int midiNoteNumber) const throw(); + void noteOff (const int midiChannel, const int midiNoteNumber); - /** Returns true if the given midi key is currently held down on any of a set of midi channels. + void allNotesOff (const int midiChannel); - The channel mask has a bit set for each midi channel you want to test for - bit - 0 = midi channel 1, bit 1 = midi channel 2, etc. + void processNextMidiEvent (const MidiMessage& message); - If a note is on for at least one of the specified channels, this returns true. - */ - bool isNoteOnForChannels (const int midiChannelMask, const int midiNoteNumber) const throw(); + void processNextMidiBuffer (MidiBuffer& buffer, + const int startSample, + const int numSamples, + const bool injectIndirectEvents); - /** Turns a specified note on. + void addListener (MidiKeyboardStateListener* const listener) throw(); - This will cause a suitable midi note-on event to be injected into the midi buffer during the - next call to processNextMidiBuffer(). + void removeListener (MidiKeyboardStateListener* const listener) throw(); - It will also trigger a synchronous callback to the listeners to tell them that the key has - gone down. - */ - void noteOn (const int midiChannel, const int midiNoteNumber, const float velocity); - - /** Turns a specified note off. - - This will cause a suitable midi note-off event to be injected into the midi buffer during the - next call to processNextMidiBuffer(). - - It will also trigger a synchronous callback to the listeners to tell them that the key has - gone up. - - But if the note isn't acutally down for the given channel, this method will in fact do nothing. - */ - void noteOff (const int midiChannel, const int midiNoteNumber); - - /** This will turn off any currently-down notes for the given midi channel. - - If you pass 0 for the midi channel, it will in fact turn off all notes on all channels. - - Calling this method will make calls to noteOff(), so can trigger synchronous callbacks - and events being added to the midi stream. - */ - void allNotesOff (const int midiChannel); - - /** Looks at a key-up/down event and uses it to update the state of this object. - - To process a buffer full of midi messages, use the processNextMidiBuffer() method - instead. - */ - void processNextMidiEvent (const MidiMessage& message); - - /** Scans a midi stream for up/down events and adds its own events to it. - - This will look for any up/down events and use them to update the internal state, - synchronously making suitable callbacks to the listeners. - - If injectIndirectEvents is true, then midi events to produce the recent noteOn() - and noteOff() calls will be added into the buffer. - - Only the section of the buffer whose timestamps are between startSample and - (startSample + numSamples) will be affected, and any events added will be placed - between these times. - - If you're going to use this method, you'll need to keep calling it regularly for - it to work satisfactorily. - - To process a single midi event at a time, use the processNextMidiEvent() method - instead. - */ - void processNextMidiBuffer (MidiBuffer& buffer, - const int startSample, - const int numSamples, - const bool injectIndirectEvents); - - /** Registers a listener for callbacks when keys go up or down. - - @see removeListener - */ - void addListener (MidiKeyboardStateListener* const listener) throw(); - - /** Deregisters a listener. - - @see addListener - */ - void removeListener (MidiKeyboardStateListener* const listener) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - CriticalSection lock; - uint16 noteStates [128]; - MidiBuffer eventsToAdd; - VoidArray listeners; + CriticalSection lock; + uint16 noteStates [128]; + MidiBuffer eventsToAdd; + VoidArray listeners; - void noteOnInternal (const int midiChannel, const int midiNoteNumber, const float velocity); - void noteOffInternal (const int midiChannel, const int midiNoteNumber); + void noteOnInternal (const int midiChannel, const int midiNoteNumber, const float velocity); + void noteOffInternal (const int midiChannel, const int midiNoteNumber); - MidiKeyboardState (const MidiKeyboardState&); - const MidiKeyboardState& operator= (const MidiKeyboardState&); + MidiKeyboardState (const MidiKeyboardState&); + const MidiKeyboardState& operator= (const MidiKeyboardState&); }; #endif // __JUCE_MIDIKEYBOARDSTATE_JUCEHEADER__ @@ -35721,75 +16951,36 @@ private: #ifndef __JUCE_MIDIMESSAGECOLLECTOR_JUCEHEADER__ #define __JUCE_MIDIMESSAGECOLLECTOR_JUCEHEADER__ -/** - Collects incoming realtime MIDI messages and turns them into blocks suitable for - processing by a block-based audio callback. - - The class can also be used as either a MidiKeyboardStateListener or a MidiInputCallback - so it can easily use a midi input or keyboard component as its source. - - @see MidiMessage, MidiInput -*/ -class JUCE_API MidiMessageCollector : public MidiKeyboardStateListener, - public MidiInputCallback +class JUCE_API MidiMessageCollector : public MidiKeyboardStateListener, + public MidiInputCallback { public: - /** Creates a MidiMessageCollector. */ - MidiMessageCollector(); + MidiMessageCollector(); - /** Destructor. */ - ~MidiMessageCollector(); + ~MidiMessageCollector(); - /** Clears any messages from the queue. + void reset (const double sampleRate); - You need to call this method before starting to use the collector, so that - it knows the correct sample rate to use. - */ - void reset (const double sampleRate); + void addMessageToQueue (const MidiMessage& message); - /** Takes an incoming real-time message and adds it to the queue. + void removeNextBlockOfMessages (MidiBuffer& destBuffer, + const int numSamples); - The message's timestamp is taken, and it will be ready for retrieval as part - of the block returned by the next call to removeNextBlockOfMessages(). + void handleNoteOn (MidiKeyboardState* source, int midiChannel, int midiNoteNumber, float velocity); + void handleNoteOff (MidiKeyboardState* source, int midiChannel, int midiNoteNumber); + void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message); - This method is fully thread-safe when overlapping calls are made with - removeNextBlockOfMessages(). - */ - void addMessageToQueue (const MidiMessage& message); - - /** Removes all the pending messages from the queue as a buffer. - - This will also correct the messages' timestamps to make sure they're in - the range 0 to numSamples - 1. - - This call should be made regularly by something like an audio processing - callback, because the time that it happens is used in calculating the - midi event positions. - - This method is fully thread-safe when overlapping calls are made with - addMessageToQueue(). - */ - void removeNextBlockOfMessages (MidiBuffer& destBuffer, - const int numSamples); - - /** @internal */ - void handleNoteOn (MidiKeyboardState* source, int midiChannel, int midiNoteNumber, float velocity); - /** @internal */ - void handleNoteOff (MidiKeyboardState* source, int midiChannel, int midiNoteNumber); - /** @internal */ - void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - double lastCallbackTime; - CriticalSection midiCallbackLock; - MidiBuffer incomingMessages; - double sampleRate; + double lastCallbackTime; + CriticalSection midiCallbackLock; + MidiBuffer incomingMessages; + double sampleRate; - MidiMessageCollector (const MidiMessageCollector&); - const MidiMessageCollector& operator= (const MidiMessageCollector&); + MidiMessageCollector (const MidiMessageCollector&); + const MidiMessageCollector& operator= (const MidiMessageCollector&); }; #endif // __JUCE_MIDIMESSAGECOLLECTOR_JUCEHEADER__ @@ -35823,32 +17014,20 @@ private: class AudioProcessor; -/** - Base class for the component that acts as the GUI for an AudioProcessor. - - Derive your editor component from this class, and create an instance of it - by overriding the AudioProcessor::createEditor() method. - - @see AudioProcessor, GenericAudioProcessorEditor -*/ class JUCE_API AudioProcessorEditor : public Component { protected: - /** Creates an editor for the specified processor. - */ - AudioProcessorEditor (AudioProcessor* const owner); + AudioProcessorEditor (AudioProcessor* const owner); public: - /** Destructor. */ - ~AudioProcessorEditor(); + ~AudioProcessorEditor(); - /** Returns a pointer to the processor that this editor represents. */ - AudioProcessor* getAudioProcessor() const throw() { return owner; } + AudioProcessor* getAudioProcessor() const throw() { return owner; } private: - AudioProcessor* const owner; + AudioProcessor* const owner; }; #endif // __JUCE_AUDIOPROCESSOREDITOR_JUCEHEADER__ @@ -35860,79 +17039,23 @@ private: class AudioProcessor; -/** - Base class for listeners that want to know about changes to an AudioProcessor. - - Use AudioProcessor::addListener() to register your listener with an AudioProcessor. - - @see AudioProcessor -*/ class JUCE_API AudioProcessorListener { public: - /** Destructor. */ - virtual ~AudioProcessorListener() {} + virtual ~AudioProcessorListener() {} - /** Receives a callback when a parameter is changed. + virtual void audioProcessorParameterChanged (AudioProcessor* processor, + int parameterIndex, + float newValue) = 0; - IMPORTANT NOTE: this will be called synchronously when a parameter changes, and - many audio processors will change their parameter during their audio callback. - This means that not only has your handler code got to be completely thread-safe, - but it's also got to be VERY fast, and avoid blocking. If you need to handle - this event on your message thread, use this callback to trigger an AsyncUpdater - or ChangeBroadcaster which you can respond to on the message thread. - */ - virtual void audioProcessorParameterChanged (AudioProcessor* processor, - int parameterIndex, - float newValue) = 0; + virtual void audioProcessorChanged (AudioProcessor* processor) = 0; - /** Called to indicate that something else in the plugin has changed, like its - program, number of parameters, etc. + virtual void audioProcessorParameterChangeGestureBegin (AudioProcessor* processor, + int parameterIndex); - IMPORTANT NOTE: this will be called synchronously, and many audio processors will - call it during their audio callback. This means that not only has your handler code - got to be completely thread-safe, but it's also got to be VERY fast, and avoid - blocking. If you need to handle this event on your message thread, use this callback - to trigger an AsyncUpdater or ChangeBroadcaster which you can respond to later on the - message thread. - */ - virtual void audioProcessorChanged (AudioProcessor* processor) = 0; - - /** Indicates that a parameter change gesture has started. - - E.g. if the user is dragging a slider, this would be called when they first - press the mouse button, and audioProcessorParameterChangeGestureEnd would be - called when they release it. - - IMPORTANT NOTE: this will be called synchronously, and many audio processors will - call it during their audio callback. This means that not only has your handler code - got to be completely thread-safe, but it's also got to be VERY fast, and avoid - blocking. If you need to handle this event on your message thread, use this callback - to trigger an AsyncUpdater or ChangeBroadcaster which you can respond to later on the - message thread. - - @see audioProcessorParameterChangeGestureEnd - */ - virtual void audioProcessorParameterChangeGestureBegin (AudioProcessor* processor, - int parameterIndex); - - /** Indicates that a parameter change gesture has finished. - - E.g. if the user is dragging a slider, this would be called when they release - the mouse button. - - IMPORTANT NOTE: this will be called synchronously, and many audio processors will - call it during their audio callback. This means that not only has your handler code - got to be completely thread-safe, but it's also got to be VERY fast, and avoid - blocking. If you need to handle this event on your message thread, use this callback - to trigger an AsyncUpdater or ChangeBroadcaster which you can respond to later on the - message thread. - - @see audioPluginParameterChangeGestureStart - */ - virtual void audioProcessorParameterChangeGestureEnd (AudioProcessor* processor, - int parameterIndex); + virtual void audioProcessorParameterChangeGestureEnd (AudioProcessor* processor, + int parameterIndex); }; #endif // __JUCE_AUDIOPROCESSORLISTENER_JUCEHEADER__ @@ -35942,623 +17065,199 @@ public: #ifndef __JUCE_AUDIOPLAYHEAD_JUCEHEADER__ #define __JUCE_AUDIOPLAYHEAD_JUCEHEADER__ -/** - A subclass of AudioPlayHead can supply information about the position and - status of a moving play head during audio playback. - - One of these can be supplied to an AudioProcessor object so that it can find - out about the position of the audio that it is rendering. - - @see AudioProcessor::setPlayHead, AudioProcessor::getPlayHead -*/ class JUCE_API AudioPlayHead { protected: - AudioPlayHead() {} + AudioPlayHead() {} public: - virtual ~AudioPlayHead() {} + virtual ~AudioPlayHead() {} - /** Frame rate types. */ - enum FrameRateType - { - fps24 = 0, - fps25 = 1, - fps2997 = 2, - fps30 = 3, - fps2997drop = 4, - fps30drop = 5, - fpsUnknown = 99 - }; + enum FrameRateType + { + fps24 = 0, + fps25 = 1, + fps2997 = 2, + fps30 = 3, + fps2997drop = 4, + fps30drop = 5, + fpsUnknown = 99 + }; - /** This structure is filled-in by the AudioPlayHead::getCurrentPosition() method. - */ - struct CurrentPositionInfo - { - /** The tempo in BPM */ - double bpm; + struct CurrentPositionInfo + { + double bpm; - /** Time signature numerator, e.g. the 3 of a 3/4 time sig */ - int timeSigNumerator; - /** Time signature denominator, e.g. the 4 of a 3/4 time sig */ - int timeSigDenominator; + int timeSigNumerator; + int timeSigDenominator; - /** The current play position, in seconds from the start of the edit. */ - double timeInSeconds; + double timeInSeconds; - /** For timecode, the position of the start of the edit, in seconds from 00:00:00:00. */ - double editOriginTime; + double editOriginTime; - /** The current play position in pulses-per-quarter-note. + double ppqPosition; - This is the number of quarter notes since the edit start. - */ - double ppqPosition; + double ppqPositionOfLastBarStart; - /** The position of the start of the last bar, in pulses-per-quarter-note. + FrameRateType frameRate; - This is the number of quarter notes from the start of the edit to the - start of the current bar. + bool isPlaying; - Note - this value may be unavailable on some hosts, e.g. Pro-Tools. If - it's not available, the value will be 0. - */ - double ppqPositionOfLastBarStart; + bool isRecording; + }; - /** The video frame rate, if applicable. */ - FrameRateType frameRate; - - /** True if the transport is currently playing. */ - bool isPlaying; - - /** True if the transport is currently recording. - - (When isRecording is true, then isPlaying will also be true). - */ - bool isRecording; - }; - - /** Fills-in the given structure with details about the transport's - position at the start of the current processing block. - */ - virtual bool getCurrentPosition (CurrentPositionInfo& result) = 0; + virtual bool getCurrentPosition (CurrentPositionInfo& result) = 0; }; #endif // __JUCE_AUDIOPLAYHEAD_JUCEHEADER__ /********* End of inlined file: juce_AudioPlayHead.h *********/ -/** - Base class for audio processing filters or plugins. - - This is intended to act as a base class of audio filter that is general enough to - be wrapped as a VST, AU, RTAS, etc, or used internally. - - It is also used by the plugin hosting code as the wrapper around an instance - of a loaded plugin. - - Derive your filter class from this base class, and if you're building a plugin, - you should implement a global function called createPluginFilter() which creates - and returns a new instance of your subclass. -*/ class JUCE_API AudioProcessor { protected: - /** Constructor. - - You can also do your initialisation tasks in the initialiseFilterInfo() - call, which will be made after this object has been created. - */ - AudioProcessor(); + AudioProcessor(); public: - /** Destructor. */ - virtual ~AudioProcessor(); - - /** Returns the name of this processor. - */ - virtual const String getName() const = 0; - - /** Called before playback starts, to let the filter prepare itself. - - The sample rate is the target sample rate, and will remain constant until - playback stops. - - The estimatedSamplesPerBlock value is a HINT about the typical number of - samples that will be processed for each callback, but isn't any kind - of guarantee. The actual block sizes that the host uses may be different - each time the callback happens, and may be more or less than this value. - */ - virtual void prepareToPlay (double sampleRate, - int estimatedSamplesPerBlock) = 0; - - /** Called after playback has stopped, to let the filter free up any resources it - no longer needs. - */ - virtual void releaseResources() = 0; - - /** Renders the next block. - - When this method is called, the buffer contains a number of channels which is - at least as great as the maximum number of input and output channels that - this filter is using. It will be filled with the filter's input data and - should be replaced with the filter's output. - - So for example if your filter has 2 input channels and 4 output channels, then - the buffer will contain 4 channels, the first two being filled with the - input data. Your filter should read these, do its processing, and replace - the contents of all 4 channels with its output. - - Or if your filter has 5 inputs and 2 outputs, the buffer will have 5 channels, - all filled with data, and your filter should overwrite the first 2 of these - with its output. But be VERY careful not to write anything to the last 3 - channels, as these might be mapped to memory that the host assumes is read-only! - - Note that if you have more outputs than inputs, then only those channels that - correspond to an input channel are guaranteed to contain sensible data - e.g. - in the case of 2 inputs and 4 outputs, the first two channels contain the input, - but the last two channels may contain garbage, so you should be careful not to - let this pass through without being overwritten or cleared. - - Also note that the buffer may have more channels than are strictly necessary, - but your should only read/write from the ones that your filter is supposed to - be using. - - The number of samples in these buffers is NOT guaranteed to be the same for every - callback, and may be more or less than the estimated value given to prepareToPlay(). - Your code must be able to cope with variable-sized blocks, or you're going to get - clicks and crashes! + virtual ~AudioProcessor(); - If the filter is receiving a midi input, then the midiMessages array will be filled - with the midi messages for this block. Each message's timestamp will indicate the - message's time, as a number of samples from the start of the block. - - Any messages left in the midi buffer when this method has finished are assumed to - be the filter's midi output. This means that your filter should be careful to - clear any incoming messages from the array if it doesn't want them to be passed-on. + virtual const String getName() const = 0; - Be very careful about what you do in this callback - it's going to be called by - the audio thread, so any kind of interaction with the UI is absolutely - out of the question. If you change a parameter in here and need to tell your UI to - update itself, the best way is probably to inherit from a ChangeBroadcaster, let - the UI components register as listeners, and then call sendChangeMessage() inside the - processBlock() method to send out an asynchronous message. You could also use - the AsyncUpdater class in a similar way. - */ - virtual void processBlock (AudioSampleBuffer& buffer, - MidiBuffer& midiMessages) = 0; - - /** Returns the current AudioPlayHead object that should be used to find - out the state and position of the playhead. + virtual void prepareToPlay (double sampleRate, + int estimatedSamplesPerBlock) = 0; - You can call this from your processBlock() method, and use the AudioPlayHead - object to get the details about the time of the start of the block currently - being processed. + virtual void releaseResources() = 0; - If the host hasn't supplied a playhead object, this will return 0. - */ - AudioPlayHead* getPlayHead() const throw() { return playHead; } + virtual void processBlock (AudioSampleBuffer& buffer, + MidiBuffer& midiMessages) = 0; - /** Returns the current sample rate. + AudioPlayHead* getPlayHead() const throw() { return playHead; } - This can be called from your processBlock() method - it's not guaranteed - to be valid at any other time, and may return 0 if it's unknown. - */ - double getSampleRate() const throw() { return sampleRate; } + double getSampleRate() const throw() { return sampleRate; } - /** Returns the current typical block size that is being used. + int getBlockSize() const throw() { return blockSize; } - This can be called from your processBlock() method - it's not guaranteed - to be valid at any other time. + int getNumInputChannels() const throw() { return numInputChannels; } - Remember it's not the ONLY block size that may be used when calling - processBlock, it's just the normal one. The actual block sizes used may be - larger or smaller than this, and will vary between successive calls. - */ - int getBlockSize() const throw() { return blockSize; } + int getNumOutputChannels() const throw() { return numOutputChannels; } - /** Returns the number of input channels that the host will be sending the filter. + virtual const String getInputChannelName (const int channelIndex) const = 0; - If writing a plugin, your JucePluginCharacteristics.h file should specify the - number of channels that your filter would prefer to have, and this method lets - you know how many the host is actually using. + virtual const String getOutputChannelName (const int channelIndex) const = 0; - Note that this method is only valid during or after the prepareToPlay() - method call. Until that point, the number of channels will be unknown. - */ - int getNumInputChannels() const throw() { return numInputChannels; } + virtual bool isInputChannelStereoPair (int index) const = 0; - /** Returns the number of output channels that the host will be sending the filter. + virtual bool isOutputChannelStereoPair (int index) const = 0; - If writing a plugin, your JucePluginCharacteristics.h file should specify the - number of channels that your filter would prefer to have, and this method lets - you know how many the host is actually using. + int getLatencySamples() const throw() { return latencySamples; } - Note that this method is only valid during or after the prepareToPlay() - method call. Until that point, the number of channels will be unknown. - */ - int getNumOutputChannels() const throw() { return numOutputChannels; } + void setLatencySamples (const int newLatency); - /** Returns the name of one of the input channels, as returned by the host. + virtual bool acceptsMidi() const = 0; - The host might not supply very useful names for channels, and this might be - something like "1", "2", "left", "right", etc. - */ - virtual const String getInputChannelName (const int channelIndex) const = 0; + virtual bool producesMidi() const = 0; - /** Returns the name of one of the output channels, as returned by the host. + const CriticalSection& getCallbackLock() const throw() { return callbackLock; } - The host might not supply very useful names for channels, and this might be - something like "1", "2", "left", "right", etc. - */ - virtual const String getOutputChannelName (const int channelIndex) const = 0; + void suspendProcessing (const bool shouldBeSuspended); - /** Returns true if the specified channel is part of a stereo pair with its neighbour. */ - virtual bool isInputChannelStereoPair (int index) const = 0; + bool isSuspended() const throw() { return suspended; } - /** Returns true if the specified channel is part of a stereo pair with its neighbour. */ - virtual bool isOutputChannelStereoPair (int index) const = 0; + virtual void reset(); - /** This returns the number of samples delay that the filter imposes on the audio - passing through it. + bool isNonRealtime() const throw() { return nonRealtime; } - The host will call this to find the latency - the filter itself should set this value - by calling setLatencySamples() as soon as it can during its initialisation. - */ - int getLatencySamples() const throw() { return latencySamples; } + void setNonRealtime (const bool isNonRealtime) throw(); - /** The filter should call this to set the number of samples delay that it introduces. + virtual AudioProcessorEditor* createEditor() = 0; - The filter should call this as soon as it can during initialisation, and can call it - later if the value changes. - */ - void setLatencySamples (const int newLatency); + AudioProcessorEditor* getActiveEditor() const throw() { return activeEditor; } - /** Returns true if the processor wants midi messages. */ - virtual bool acceptsMidi() const = 0; + AudioProcessorEditor* createEditorIfNeeded(); - /** Returns true if the processor produces midi messages. */ - virtual bool producesMidi() const = 0; + virtual int getNumParameters() = 0; - /** This returns a critical section that will automatically be locked while the host - is calling the processBlock() method. + virtual const String getParameterName (int parameterIndex) = 0; - Use it from your UI or other threads to lock access to variables that are used - by the process callback, but obviously be careful not to keep it locked for - too long, because that could cause stuttering playback. If you need to do something - that'll take a long time and need the processing to stop while it happens, use the - suspendProcessing() method instead. + virtual float getParameter (int parameterIndex) = 0; - @see suspendProcessing - */ - const CriticalSection& getCallbackLock() const throw() { return callbackLock; } + virtual const String getParameterText (int parameterIndex) = 0; - /** Enables and disables the processing callback. + virtual void setParameter (int parameterIndex, + float newValue) = 0; - If you need to do something time-consuming on a thread and would like to make sure - the audio processing callback doesn't happen until you've finished, use this - to disable the callback and re-enable it again afterwards. + void setParameterNotifyingHost (int parameterIndex, + float newValue); - E.g. - @code - void loadNewPatch() - { - suspendProcessing (true); + virtual bool isParameterAutomatable (int parameterIndex) const; - ..do something that takes ages.. + virtual bool isMetaParameter (int parameterIndex) const; - suspendProcessing (false); - } - @endcode + void beginParameterChangeGesture (int parameterIndex); - If the host tries to make an audio callback while processing is suspended, the - filter will return an empty buffer, but won't block the audio thread like it would - do if you use the getCallbackLock() critical section to synchronise access. + void endParameterChangeGesture (int parameterIndex); - If you're going to use this, your processBlock() method must call isSuspended() and - check whether it's suspended or not. If it is, then it should skip doing any real - processing, either emitting silence or passing the input through unchanged. + void updateHostDisplay(); - @see getCallbackLock - */ - void suspendProcessing (const bool shouldBeSuspended); + virtual int getNumPrograms() = 0; - /** Returns true if processing is currently suspended. - @see suspendProcessing - */ - bool isSuspended() const throw() { return suspended; } + virtual int getCurrentProgram() = 0; - /** A plugin can override this to be told when it should reset any playing voices. + virtual void setCurrentProgram (int index) = 0; - The default implementation does nothing, but a host may call this to tell the - plugin that it should stop any tails or sounds that have been left running. - */ - virtual void reset(); + virtual const String getProgramName (int index) = 0; - /** Returns true if the processor is being run in an offline mode for rendering. + virtual void changeProgramName (int index, const String& newName) = 0; - If the processor is being run live on realtime signals, this returns false. - If the mode is unknown, this will assume it's realtime and return false. + virtual void getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData) = 0; - This value may be unreliable until the prepareToPlay() method has been called, - and could change each time prepareToPlay() is called. + virtual void getCurrentProgramStateInformation (JUCE_NAMESPACE::MemoryBlock& destData); - @see setNonRealtime() - */ - bool isNonRealtime() const throw() { return nonRealtime; } + virtual void setStateInformation (const void* data, int sizeInBytes) = 0; - /** Called by the host to tell this processor whether it's being used in a non-realime - capacity for offline rendering or bouncing. + virtual void setCurrentProgramStateInformation (const void* data, int sizeInBytes); - Whatever value is passed-in will be - */ - void setNonRealtime (const bool isNonRealtime) throw(); + void addListener (AudioProcessorListener* const newListener) throw(); - /** Creates the filter's UI. + void removeListener (AudioProcessorListener* const listenerToRemove) throw(); - This can return 0 if you want a UI-less filter, in which case the host may create - a generic UI that lets the user twiddle the parameters directly. + void editorBeingDeleted (AudioProcessorEditor* const editor) throw(); - If you do want to pass back a component, the component should be created and set to - the correct size before returning it. + void setPlayHead (AudioPlayHead* const newPlayHead) throw(); - Remember not to do anything silly like allowing your filter to keep a pointer to - the component that gets created - it could be deleted later without any warning, which - would make your pointer into a dangler. Use the getActiveEditor() method instead. + void setPlayConfigDetails (const int numIns, const int numOuts, + const double sampleRate, + const int blockSize) throw(); - The correct way to handle the connection between an editor component and its - filter is to use something like a ChangeBroadcaster so that the editor can - register itself as a listener, and be told when a change occurs. This lets them - safely unregister themselves when they are deleted. - - Here are a few things to bear in mind when writing an editor: - - - Initially there won't be an editor, until the user opens one, or they might - not open one at all. Your filter mustn't rely on it being there. - - An editor object may be deleted and a replacement one created again at any time. - - It's safe to assume that an editor will be deleted before its filter. - */ - virtual AudioProcessorEditor* createEditor() = 0; - - /** Returns the active editor, if there is one. - - Bear in mind this can return 0, even if an editor has previously been - opened. - */ - AudioProcessorEditor* getActiveEditor() const throw() { return activeEditor; } - - /** Returns the active editor, or if there isn't one, it will create one. - - This may call createEditor() internally to create the component. - */ - AudioProcessorEditor* createEditorIfNeeded(); - - /** This must return the correct value immediately after the object has been - created, and mustn't change the number of parameters later. - */ - virtual int getNumParameters() = 0; - - /** Returns the name of a particular parameter. */ - virtual const String getParameterName (int parameterIndex) = 0; - - /** Called by the host to find out the value of one of the filter's parameters. - - The host will expect the value returned to be between 0 and 1.0. - - This could be called quite frequently, so try to make your code efficient. - It's also likely to be called by non-UI threads, so the code in here should - be thread-aware. - */ - virtual float getParameter (int parameterIndex) = 0; - - /** Returns the value of a parameter as a text string. */ - virtual const String getParameterText (int parameterIndex) = 0; - - /** The host will call this method to change the value of one of the filter's parameters. - - The host may call this at any time, including during the audio processing - callback, so the filter has to process this very fast and avoid blocking. - - If you want to set the value of a parameter internally, e.g. from your - editor component, then don't call this directly - instead, use the - setParameterNotifyingHost() method, which will also send a message to - the host telling it about the change. If the message isn't sent, the host - won't be able to automate your parameters properly. - - The value passed will be between 0 and 1.0. - */ - virtual void setParameter (int parameterIndex, - float newValue) = 0; - - /** Your filter can call this when it needs to change one of its parameters. - - This could happen when the editor or some other internal operation changes - a parameter. This method will call the setParameter() method to change the - value, and will then send a message to the host telling it about the change. - - Note that to make sure the host correctly handles automation, you should call - the beginParameterChangeGesture() and endParameterChangeGesture() methods to - tell the host when the user has started and stopped changing the parameter. - */ - void setParameterNotifyingHost (int parameterIndex, - float newValue); - - /** Returns true if the host can automate this parameter. - - By default, this returns true for all parameters. - */ - virtual bool isParameterAutomatable (int parameterIndex) const; - - /** Should return true if this parameter is a "meta" parameter. - - A meta-parameter is a parameter that changes other params. It is used - by some hosts (e.g. AudioUnit hosts). - - By default this returns false. - */ - virtual bool isMetaParameter (int parameterIndex) const; - - /** Sends a signal to the host to tell it that the user is about to start changing this - parameter. - - This allows the host to know when a parameter is actively being held by the user, and - it may use this information to help it record automation. - - If you call this, it must be matched by a later call to endParameterChangeGesture(). - */ - void beginParameterChangeGesture (int parameterIndex); - - /** Tells the host that the user has finished changing this parameter. - - This allows the host to know when a parameter is actively being held by the user, and - it may use this information to help it record automation. - - A call to this method must follow a call to beginParameterChangeGesture(). - */ - void endParameterChangeGesture (int parameterIndex); - - /** The filter can call this when something (apart from a parameter value) has changed. - - It sends a hint to the host that something like the program, number of parameters, - etc, has changed, and that it should update itself. - */ - void updateHostDisplay(); - - /** Returns the number of preset programs the filter supports. - - The value returned must be valid as soon as this object is created, and - must not change over its lifetime. - - This value shouldn't be less than 1. - */ - virtual int getNumPrograms() = 0; - - /** Returns the number of the currently active program. - */ - virtual int getCurrentProgram() = 0; - - /** Called by the host to change the current program. - */ - virtual void setCurrentProgram (int index) = 0; - - /** Must return the name of a given program. */ - virtual const String getProgramName (int index) = 0; - - /** Called by the host to rename a program. - */ - virtual void changeProgramName (int index, const String& newName) = 0; - - /** The host will call this method when it wants to save the filter's internal state. - - This must copy any info about the filter's state into the block of memory provided, - so that the host can store this and later restore it using setStateInformation(). - - Note that there's also a getCurrentProgramStateInformation() method, which only - stores the current program, not the state of the entire filter. - - See also the helper function copyXmlToBinary() for storing settings as XML. - - @see getCurrentProgramStateInformation - */ - virtual void getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData) = 0; - - /** The host will call this method if it wants to save the state of just the filter's - current program. - - Unlike getStateInformation, this should only return the current program's state. - - Not all hosts support this, and if you don't implement it, the base class - method just calls getStateInformation() instead. If you do implement it, be - sure to also implement getCurrentProgramStateInformation. - - @see getStateInformation, setCurrentProgramStateInformation - */ - virtual void getCurrentProgramStateInformation (JUCE_NAMESPACE::MemoryBlock& destData); - - /** This must restore the filter's state from a block of data previously created - using getStateInformation(). - - Note that there's also a setCurrentProgramStateInformation() method, which tries - to restore just the current program, not the state of the entire filter. - - See also the helper function getXmlFromBinary() for loading settings as XML. - - @see setCurrentProgramStateInformation - */ - virtual void setStateInformation (const void* data, int sizeInBytes) = 0; - - /** The host will call this method if it wants to restore the state of just the filter's - current program. - - Not all hosts support this, and if you don't implement it, the base class - method just calls setStateInformation() instead. If you do implement it, be - sure to also implement getCurrentProgramStateInformation. - - @see setStateInformation, getCurrentProgramStateInformation - */ - virtual void setCurrentProgramStateInformation (const void* data, int sizeInBytes); - - /** Adds a listener that will be called when an aspect of this processor changes. */ - void addListener (AudioProcessorListener* const newListener) throw(); - - /** Removes a previously added listener. */ - void removeListener (AudioProcessorListener* const listenerToRemove) throw(); - - /** Not for public use - this is called before deleting an editor component. */ - void editorBeingDeleted (AudioProcessorEditor* const editor) throw(); - - /** Not for public use - this is called to initialise the processor. */ - void setPlayHead (AudioPlayHead* const newPlayHead) throw(); - - /** Not for public use - this is called to initialise the processor before playing. */ - void setPlayConfigDetails (const int numIns, const int numOuts, - const double sampleRate, - const int blockSize) throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** Helper function that just converts an xml element into a binary blob. + static void copyXmlToBinary (const XmlElement& xml, + JUCE_NAMESPACE::MemoryBlock& destData); - Use this in your filter's getStateInformation() method if you want to - store its state as xml. + static XmlElement* getXmlFromBinary (const void* data, + const int sizeInBytes); - Then use getXmlFromBinary() to reverse this operation and retrieve the XML - from a binary blob. - */ - static void copyXmlToBinary (const XmlElement& xml, - JUCE_NAMESPACE::MemoryBlock& destData); + AudioPlayHead* playHead; - /** Retrieves an XML element that was stored as binary with the copyXmlToBinary() method. - - This might return 0 if the data's unsuitable or corrupted. Otherwise it will return - an XmlElement object that the caller must delete when no longer needed. - */ - static XmlElement* getXmlFromBinary (const void* data, - const int sizeInBytes); - - /** @internal */ - AudioPlayHead* playHead; - - /** @internal */ - void sendParamChangeMessageToListeners (const int parameterIndex, const float newValue); + void sendParamChangeMessageToListeners (const int parameterIndex, const float newValue); private: - VoidArray listeners; - AudioProcessorEditor* activeEditor; - double sampleRate; - int blockSize, numInputChannels, numOutputChannels, latencySamples; - bool suspended, nonRealtime; - CriticalSection callbackLock, listenerLock; + VoidArray listeners; + AudioProcessorEditor* activeEditor; + double sampleRate; + int blockSize, numInputChannels, numOutputChannels, latencySamples; + bool suspended, nonRealtime; + CriticalSection callbackLock, listenerLock; #ifdef JUCE_DEBUG - BitArray changingParams; + BitArray changingParams; #endif - AudioProcessor (const AudioProcessor&); - const AudioProcessor& operator= (const AudioProcessor&); + AudioProcessor (const AudioProcessor&); + const AudioProcessor& operator= (const AudioProcessor&); }; #endif // __JUCE_AUDIOPROCESSOR_JUCEHEADER__ @@ -36568,138 +17267,66 @@ private: #ifndef __JUCE_PLUGINDESCRIPTION_JUCEHEADER__ #define __JUCE_PLUGINDESCRIPTION_JUCEHEADER__ -/** - A small class to represent some facts about a particular type of plugin. - - This class is for storing and managing the details about a plugin without - actually having to load an instance of it. - - A KnownPluginList contains a list of PluginDescription objects. - - @see KnownPluginList -*/ class JUCE_API PluginDescription { public: - PluginDescription() throw(); - PluginDescription (const PluginDescription& other) throw(); - const PluginDescription& operator= (const PluginDescription& other) throw(); - ~PluginDescription() throw(); + PluginDescription() throw(); + PluginDescription (const PluginDescription& other) throw(); + const PluginDescription& operator= (const PluginDescription& other) throw(); + ~PluginDescription() throw(); - /** The name of the plugin. */ - String name; + String name; - /** The plugin format, e.g. "VST", "AudioUnit", etc. - */ - String pluginFormatName; + String pluginFormatName; - /** A category, such as "Dynamics", "Reverbs", etc. - */ - String category; + String category; - /** The manufacturer. */ - String manufacturerName; + String manufacturerName; - /** The version. This string doesn't have any particular format. */ - String version; + String version; - /** Either the file containing the plugin module, or some other unique way - of identifying it. + String fileOrIdentifier; - E.g. for an AU, this would be an ID string that the component manager - could use to retrieve the plugin. For a VST, it's the file path. - */ - String fileOrIdentifier; + Time lastFileModTime; - /** The last time the plugin file was changed. - This is handy when scanning for new or changed plugins. - */ - Time lastFileModTime; + int uid; - /** A unique ID for the plugin. + bool isInstrument; - Note that this might not be unique between formats, e.g. a VST and some - other format might actually have the same id. + int numInputChannels; - @see createIdentifierString - */ - int uid; + int numOutputChannels; - /** True if the plugin identifies itself as a synthesiser. */ - bool isInstrument; + bool isDuplicateOf (const PluginDescription& other) const; - /** The number of inputs. */ - int numInputChannels; + const String createIdentifierString() const throw(); - /** The number of outputs. */ - int numOutputChannels; + XmlElement* createXml() const; - /** Returns true if the two descriptions refer the the same plugin. + bool loadFromXml (const XmlElement& xml); - This isn't quite as simple as them just having the same file (because of - shell plugins). - */ - bool isDuplicateOf (const PluginDescription& other) const; - - /** Returns a string that can be saved and used to uniquely identify the - plugin again. - - This contains less info than the XML encoding, and is independent of the - plugin's file location, so can be used to store a plugin ID for use - across different machines. - */ - const String createIdentifierString() const throw(); - - /** Creates an XML object containing these details. - - @see loadFromXml - */ - XmlElement* createXml() const; - - /** Reloads the info in this structure from an XML record that was previously - saved with createXML(). - - Returns true if the XML was a valid plugin description. - */ - bool loadFromXml (const XmlElement& xml); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; #endif // __JUCE_PLUGINDESCRIPTION_JUCEHEADER__ /********* End of inlined file: juce_PluginDescription.h *********/ -/** - Base class for an active instance of a plugin. - - This derives from the AudioProcessor class, and adds some extra functionality - that helps when wrapping dynamically loaded plugins. - - @see AudioProcessor, AudioPluginFormat -*/ class JUCE_API AudioPluginInstance : public AudioProcessor { public: - /** Destructor. + virtual ~AudioPluginInstance(); - Make sure that you delete any UI components that belong to this plugin before - deleting the plugin. - */ - virtual ~AudioPluginInstance(); + virtual void fillInPluginDescription (PluginDescription& description) const = 0; - /** Fills-in the appropriate parts of this plugin description object. - */ - virtual void fillInPluginDescription (PluginDescription& description) const = 0; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - AudioPluginInstance(); + AudioPluginInstance(); - AudioPluginInstance (const AudioPluginInstance&); - const AudioPluginInstance& operator= (const AudioPluginInstance&); + AudioPluginInstance (const AudioPluginInstance&); + const AudioPluginInstance& operator= (const AudioPluginInstance&); }; #endif // __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__ @@ -36707,84 +17334,37 @@ protected: class PluginDescription; -/** - The base class for a type of plugin format, such as VST, AudioUnit, LADSPA, etc. - - Use the static getNumFormats() and getFormat() calls to find the types - of format that are available. -*/ class JUCE_API AudioPluginFormat { public: - /** Destructor. */ - virtual ~AudioPluginFormat(); + virtual ~AudioPluginFormat(); - /** Returns the format name. + virtual const String getName() const = 0; - E.g. "VST", "AudioUnit", etc. - */ - virtual const String getName() const = 0; + virtual void findAllTypesForFile (OwnedArray & results, + const String& fileOrIdentifier) = 0; - /** This tries to create descriptions for all the plugin types available in - a binary module file. + virtual AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc) = 0; - The file will be some kind of DLL or bundle. + virtual bool fileMightContainThisPluginType (const String& fileOrIdentifier) = 0; - Normally there will only be one type returned, but some plugins - (e.g. VST shells) can use a single DLL to create a set of different plugin - subtypes, so in that case, each subtype is returned as a separate object. - */ - virtual void findAllTypesForFile (OwnedArray & results, - const String& fileOrIdentifier) = 0; + virtual const String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) = 0; - /** Tries to recreate a type from a previously generated PluginDescription. + virtual bool doesPluginStillExist (const PluginDescription& desc) = 0; - @see PluginDescription::createInstance - */ - virtual AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc) = 0; + virtual const StringArray searchPathsForPlugins (const FileSearchPath& directoriesToSearch, + const bool recursive) = 0; - /** Should do a quick check to see if this file or directory might be a plugin of - this format. + virtual const FileSearchPath getDefaultLocationsToSearch() = 0; - This is for searching for potential files, so it shouldn't actually try to - load the plugin or do anything time-consuming. - */ - virtual bool fileMightContainThisPluginType (const String& fileOrIdentifier) = 0; - - /** Returns a readable version of the name of the plugin that this identifier refers to. - */ - virtual const String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) = 0; - - /** Checks whether this plugin could possibly be loaded. - - It doesn't actually need to load it, just to check whether the file or component - still exists. - */ - virtual bool doesPluginStillExist (const PluginDescription& desc) = 0; - - /** Searches a suggested set of directories for any plugins in this format. - - The path might be ignored, e.g. by AUs, which are found by the OS rather - than manually. - */ - virtual const StringArray searchPathsForPlugins (const FileSearchPath& directoriesToSearch, - const bool recursive) = 0; - - /** Returns the typical places to look for this kind of plugin. - - Note that if this returns no paths, it means that the format can't be scanned-for - (i.e. it's an internal format that doesn't live in files) - */ - virtual const FileSearchPath getDefaultLocationsToSearch() = 0; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - AudioPluginFormat() throw(); + AudioPluginFormat() throw(); - AudioPluginFormat (const AudioPluginFormat&); - const AudioPluginFormat& operator= (const AudioPluginFormat&); + AudioPluginFormat (const AudioPluginFormat&); + const AudioPluginFormat& operator= (const AudioPluginFormat&); }; #endif // __JUCE_AUDIOPLUGINFORMAT_JUCEHEADER__ @@ -36792,30 +17372,27 @@ protected: #if JUCE_PLUGINHOST_AU && JUCE_MAC -/** - Implements a plugin format manager for AudioUnits. -*/ class JUCE_API AudioUnitPluginFormat : public AudioPluginFormat { public: - AudioUnitPluginFormat(); - ~AudioUnitPluginFormat(); + AudioUnitPluginFormat(); + ~AudioUnitPluginFormat(); - const String getName() const { return "AudioUnit"; } - void findAllTypesForFile (OwnedArray & results, const String& fileOrIdentifier); - AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); - bool fileMightContainThisPluginType (const String& fileOrIdentifier); - const String getNameOfPluginFromIdentifier (const String& fileOrIdentifier); - const StringArray searchPathsForPlugins (const FileSearchPath& directoriesToSearch, const bool recursive); - bool doesPluginStillExist (const PluginDescription& desc); - const FileSearchPath getDefaultLocationsToSearch(); + const String getName() const { return "AudioUnit"; } + void findAllTypesForFile (OwnedArray & results, const String& fileOrIdentifier); + AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); + bool fileMightContainThisPluginType (const String& fileOrIdentifier); + const String getNameOfPluginFromIdentifier (const String& fileOrIdentifier); + const StringArray searchPathsForPlugins (const FileSearchPath& directoriesToSearch, const bool recursive); + bool doesPluginStillExist (const PluginDescription& desc); + const FileSearchPath getDefaultLocationsToSearch(); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioUnitPluginFormat (const AudioUnitPluginFormat&); - const AudioUnitPluginFormat& operator= (const AudioUnitPluginFormat&); + AudioUnitPluginFormat (const AudioUnitPluginFormat&); + const AudioUnitPluginFormat& operator= (const AudioUnitPluginFormat&); }; #endif @@ -36834,28 +17411,25 @@ private: // Sorry, this file is just a placeholder at the moment!... -/** - Implements a plugin format manager for DirectX plugins. -*/ class JUCE_API DirectXPluginFormat : public AudioPluginFormat { public: - DirectXPluginFormat(); - ~DirectXPluginFormat(); + DirectXPluginFormat(); + ~DirectXPluginFormat(); - const String getName() const { return "DirectX"; } - void findAllTypesForFile (OwnedArray & results, const String& fileOrIdentifier); - AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); - bool fileMightContainThisPluginType (const String& fileOrIdentifier); - const String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) { return fileOrIdentifier; } - const FileSearchPath getDefaultLocationsToSearch(); + const String getName() const { return "DirectX"; } + void findAllTypesForFile (OwnedArray & results, const String& fileOrIdentifier); + AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); + bool fileMightContainThisPluginType (const String& fileOrIdentifier); + const String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) { return fileOrIdentifier; } + const FileSearchPath getDefaultLocationsToSearch(); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - DirectXPluginFormat (const DirectXPluginFormat&); - const DirectXPluginFormat& operator= (const DirectXPluginFormat&); + DirectXPluginFormat (const DirectXPluginFormat&); + const DirectXPluginFormat& operator= (const DirectXPluginFormat&); }; #endif @@ -36874,28 +17448,25 @@ private: // Sorry, this file is just a placeholder at the moment!... -/** - Implements a plugin format manager for DirectX plugins. -*/ class JUCE_API LADSPAPluginFormat : public AudioPluginFormat { public: - LADSPAPluginFormat(); - ~LADSPAPluginFormat(); + LADSPAPluginFormat(); + ~LADSPAPluginFormat(); - const String getName() const { return "LADSPA"; } - void findAllTypesForFile (OwnedArray & results, const String& fileOrIdentifier); - AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); - bool fileMightContainThisPluginType (const String& fileOrIdentifier); - const String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) { return fileOrIdentifier; } - const FileSearchPath getDefaultLocationsToSearch(); + const String getName() const { return "LADSPA"; } + void findAllTypesForFile (OwnedArray & results, const String& fileOrIdentifier); + AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); + bool fileMightContainThisPluginType (const String& fileOrIdentifier); + const String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) { return fileOrIdentifier; } + const FileSearchPath getDefaultLocationsToSearch(); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - LADSPAPluginFormat (const LADSPAPluginFormat&); - const LADSPAPluginFormat& operator= (const LADSPAPluginFormat&); + LADSPAPluginFormat (const LADSPAPluginFormat&); + const LADSPAPluginFormat& operator= (const LADSPAPluginFormat&); }; #endif @@ -36912,153 +17483,148 @@ private: #ifndef __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ #define __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ -/** Holds a set of VSTMidiEvent objects and makes it easy to add - events to the list. - - This is used by both the VST hosting code and the plugin wrapper. -*/ class VSTMidiEventList { public: - VSTMidiEventList() - : numEventsUsed (0), numEventsAllocated (0) - { - } + VSTMidiEventList() + : numEventsUsed (0), numEventsAllocated (0) + { + } - ~VSTMidiEventList() - { - freeEvents(); - } + ~VSTMidiEventList() + { + freeEvents(); + } - void clear() - { - numEventsUsed = 0; + void clear() + { + numEventsUsed = 0; - if (events != 0) - events->numEvents = 0; - } + if (events != 0) + events->numEvents = 0; + } - void addEvent (const void* const midiData, const int numBytes, const int frameOffset) - { - ensureSize (numEventsUsed + 1); + void addEvent (const void* const midiData, const int numBytes, const int frameOffset) + { + ensureSize (numEventsUsed + 1); - VstMidiEvent* const e = (VstMidiEvent*) (events->events [numEventsUsed]); - events->numEvents = ++numEventsUsed; + VstMidiEvent* const e = (VstMidiEvent*) (events->events [numEventsUsed]); + events->numEvents = ++numEventsUsed; - if (numBytes <= 4) - { - if (e->type == kVstSysExType) - { - juce_free (((VstMidiSysexEvent*) e)->sysexDump); - e->type = kVstMidiType; - e->byteSize = sizeof (VstMidiEvent); - e->noteLength = 0; - e->noteOffset = 0; - e->detune = 0; - e->noteOffVelocity = 0; - } + if (numBytes <= 4) + { + if (e->type == kVstSysExType) + { + juce_free (((VstMidiSysexEvent*) e)->sysexDump); + e->type = kVstMidiType; + e->byteSize = sizeof (VstMidiEvent); + e->noteLength = 0; + e->noteOffset = 0; + e->detune = 0; + e->noteOffVelocity = 0; + } - e->deltaFrames = frameOffset; - memcpy (e->midiData, midiData, numBytes); - } - else - { - VstMidiSysexEvent* const se = (VstMidiSysexEvent*) e; + e->deltaFrames = frameOffset; + memcpy (e->midiData, midiData, numBytes); + } + else + { + VstMidiSysexEvent* const se = (VstMidiSysexEvent*) e; - if (se->type == kVstSysExType) - se->sysexDump = (char*) juce_realloc (se->sysexDump, numBytes); - else - se->sysexDump = (char*) juce_malloc (numBytes); + if (se->type == kVstSysExType) + se->sysexDump = (char*) juce_realloc (se->sysexDump, numBytes); + else + se->sysexDump = (char*) juce_malloc (numBytes); - memcpy (se->sysexDump, midiData, numBytes); + memcpy (se->sysexDump, midiData, numBytes); - se->type = kVstSysExType; - se->byteSize = sizeof (VstMidiSysexEvent); - se->deltaFrames = frameOffset; - se->flags = 0; - se->dumpBytes = numBytes; - se->resvd1 = 0; - se->resvd2 = 0; - } - } + se->type = kVstSysExType; + se->byteSize = sizeof (VstMidiSysexEvent); + se->deltaFrames = frameOffset; + se->flags = 0; + se->dumpBytes = numBytes; + se->resvd1 = 0; + se->resvd2 = 0; + } + } - // Handy method to pull the events out of an event buffer supplied by the host - // or plugin. - static void addEventsToMidiBuffer (const VstEvents* events, MidiBuffer& dest) - { - for (int i = 0; i < events->numEvents; ++i) - { - const VstEvent* const e = events->events[i]; + // Handy method to pull the events out of an event buffer supplied by the host + // or plugin. + static void addEventsToMidiBuffer (const VstEvents* events, MidiBuffer& dest) + { + for (int i = 0; i < events->numEvents; ++i) + { + const VstEvent* const e = events->events[i]; - if (e != 0) - { - if (e->type == kVstMidiType) - { - dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiEvent*) e)->midiData, - 4, e->deltaFrames); - } - else if (e->type == kVstSysExType) - { - dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiSysexEvent*) e)->sysexDump, - (int) ((const VstMidiSysexEvent*) e)->dumpBytes, - e->deltaFrames); - } - } - } - } + if (e != 0) + { + if (e->type == kVstMidiType) + { + dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiEvent*) e)->midiData, + 4, e->deltaFrames); + } + else if (e->type == kVstSysExType) + { + dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiSysexEvent*) e)->sysexDump, + (int) ((const VstMidiSysexEvent*) e)->dumpBytes, + e->deltaFrames); + } + } + } + } - void ensureSize (int numEventsNeeded) - { - if (numEventsNeeded > numEventsAllocated) - { - numEventsNeeded = (numEventsNeeded + 32) & ~31; + void ensureSize (int numEventsNeeded) + { + if (numEventsNeeded > numEventsAllocated) + { + numEventsNeeded = (numEventsNeeded + 32) & ~31; - const int size = 20 + sizeof (VstEvent*) * numEventsNeeded; + const int size = 20 + sizeof (VstEvent*) * numEventsNeeded; - if (events == 0) - events.calloc (size, 1); - else - events.realloc (size, 1); + if (events == 0) + events.calloc (size, 1); + else + events.realloc (size, 1); - for (int i = numEventsAllocated; i < numEventsNeeded; ++i) - { - VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (jmax ((int) sizeof (VstMidiEvent), - (int) sizeof (VstMidiSysexEvent))); - e->type = kVstMidiType; - e->byteSize = sizeof (VstMidiEvent); + for (int i = numEventsAllocated; i < numEventsNeeded; ++i) + { + VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (jmax ((int) sizeof (VstMidiEvent), + (int) sizeof (VstMidiSysexEvent))); + e->type = kVstMidiType; + e->byteSize = sizeof (VstMidiEvent); - events->events[i] = (VstEvent*) e; - } + events->events[i] = (VstEvent*) e; + } - numEventsAllocated = numEventsNeeded; - } - } + numEventsAllocated = numEventsNeeded; + } + } - void freeEvents() - { - if (events != 0) - { - for (int i = numEventsAllocated; --i >= 0;) - { - VstMidiEvent* const e = (VstMidiEvent*) (events->events[i]); + void freeEvents() + { + if (events != 0) + { + for (int i = numEventsAllocated; --i >= 0;) + { + VstMidiEvent* const e = (VstMidiEvent*) (events->events[i]); - if (e->type == kVstSysExType) - juce_free (((VstMidiSysexEvent*) e)->sysexDump); + if (e->type == kVstSysExType) + juce_free (((VstMidiSysexEvent*) e)->sysexDump); - juce_free (e); - } + juce_free (e); + } - events.free(); - numEventsUsed = 0; - numEventsAllocated = 0; - } - } + events.free(); + numEventsUsed = 0; + numEventsAllocated = 0; + } + } - HeapBlock events; + HeapBlock events; private: - int numEventsUsed, numEventsAllocated; + int numEventsUsed, numEventsAllocated; }; #endif // __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ @@ -37074,32 +17640,29 @@ private: #if JUCE_PLUGINHOST_VST -/** - Implements a plugin format manager for VSTs. -*/ class JUCE_API VSTPluginFormat : public AudioPluginFormat { public: - VSTPluginFormat(); - ~VSTPluginFormat(); + VSTPluginFormat(); + ~VSTPluginFormat(); - const String getName() const { return "VST"; } - void findAllTypesForFile (OwnedArray & results, const String& fileOrIdentifier); - AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); - bool fileMightContainThisPluginType (const String& fileOrIdentifier); - const String getNameOfPluginFromIdentifier (const String& fileOrIdentifier); - const StringArray searchPathsForPlugins (const FileSearchPath& directoriesToSearch, const bool recursive); - bool doesPluginStillExist (const PluginDescription& desc); - const FileSearchPath getDefaultLocationsToSearch(); + const String getName() const { return "VST"; } + void findAllTypesForFile (OwnedArray & results, const String& fileOrIdentifier); + AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc); + bool fileMightContainThisPluginType (const String& fileOrIdentifier); + const String getNameOfPluginFromIdentifier (const String& fileOrIdentifier); + const StringArray searchPathsForPlugins (const FileSearchPath& directoriesToSearch, const bool recursive); + bool doesPluginStillExist (const PluginDescription& desc); + const FileSearchPath getDefaultLocationsToSearch(); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - VSTPluginFormat (const VSTPluginFormat&); - const VSTPluginFormat& operator= (const VSTPluginFormat&); + VSTPluginFormat (const VSTPluginFormat&); + const VSTPluginFormat& operator= (const VSTPluginFormat&); - void recursiveFileSearch (StringArray& results, const File& dir, const bool recursive); + void recursiveFileSearch (StringArray& results, const File& dir, const bool recursive); }; #endif @@ -37116,68 +17679,36 @@ private: #ifndef __JUCE_AUDIOPLUGINFORMATMANAGER_JUCEHEADER__ #define __JUCE_AUDIOPLUGINFORMATMANAGER_JUCEHEADER__ -/** - This maintains a list of known AudioPluginFormats. - - @see AudioPluginFormat -*/ class JUCE_API AudioPluginFormatManager : public DeletedAtShutdown { public: - AudioPluginFormatManager() throw(); + AudioPluginFormatManager() throw(); - /** Destructor. */ - ~AudioPluginFormatManager() throw(); + ~AudioPluginFormatManager() throw(); - juce_DeclareSingleton_SingleThreaded (AudioPluginFormatManager, false); + juce_DeclareSingleton_SingleThreaded (AudioPluginFormatManager, false); - /** Adds any formats that it knows about, e.g. VST. - */ - void addDefaultFormats(); + void addDefaultFormats(); - /** Returns the number of types of format that are available. + int getNumFormats() throw(); - Use getFormat() to get one of them. - */ - int getNumFormats() throw(); + AudioPluginFormat* getFormat (const int index) throw(); - /** Returns one of the available formats. + void addFormat (AudioPluginFormat* const format) throw(); - @see getNumFormats - */ - AudioPluginFormat* getFormat (const int index) throw(); + AudioPluginInstance* createPluginInstance (const PluginDescription& description, + String& errorMessage) const; - /** Adds a format to the list. + bool doesPluginStillExist (const PluginDescription& description) const; - The object passed in will be owned and deleted by the manager. - */ - void addFormat (AudioPluginFormat* const format) throw(); - - /** Tries to load the type for this description, by trying all the formats - that this manager knows about. - - The caller is responsible for deleting the object that is returned. - - If it can't load the plugin, it returns 0 and leaves a message in the - errorMessage string. - */ - AudioPluginInstance* createPluginInstance (const PluginDescription& description, - String& errorMessage) const; - - /** Checks that the file or component for this plugin actually still exists. - - (This won't try to load the plugin) - */ - bool doesPluginStillExist (const PluginDescription& description) const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OwnedArray formats; + OwnedArray formats; - AudioPluginFormatManager (const AudioPluginFormatManager&); - const AudioPluginFormatManager& operator= (const AudioPluginFormatManager&); + AudioPluginFormatManager (const AudioPluginFormatManager&); + const AudioPluginFormatManager& operator= (const AudioPluginFormatManager&); }; #endif // __JUCE_AUDIOPLUGINFORMATMANAGER_JUCEHEADER__ @@ -37193,131 +17724,65 @@ private: #ifndef __JUCE_KNOWNPLUGINLIST_JUCEHEADER__ #define __JUCE_KNOWNPLUGINLIST_JUCEHEADER__ -/** - Manages a list of plugin types. - - This can be easily edited, saved and loaded, and used to create instances of - the plugin types in it. - - @see PluginListComponent -*/ class JUCE_API KnownPluginList : public ChangeBroadcaster { public: - /** Creates an empty list. - */ - KnownPluginList(); + KnownPluginList(); - /** Destructor. */ - ~KnownPluginList(); + ~KnownPluginList(); - /** Clears the list. */ - void clear(); + void clear(); - /** Returns the number of types currently in the list. - @see getType - */ - int getNumTypes() const throw() { return types.size(); } + int getNumTypes() const throw() { return types.size(); } - /** Returns one of the types. - @see getNumTypes - */ - PluginDescription* getType (const int index) const throw() { return types [index]; } + PluginDescription* getType (const int index) const throw() { return types [index]; } - /** Looks for a type in the list which comes from this file. - */ - PluginDescription* getTypeForFile (const String& fileOrIdentifier) const throw(); + PluginDescription* getTypeForFile (const String& fileOrIdentifier) const throw(); - /** Looks for a type in the list which matches a plugin type ID. + PluginDescription* getTypeForIdentifierString (const String& identifierString) const throw(); - The identifierString parameter must have been created by - PluginDescription::createIdentifierString(). - */ - PluginDescription* getTypeForIdentifierString (const String& identifierString) const throw(); + bool addType (const PluginDescription& type); - /** Adds a type manually from its description. */ - bool addType (const PluginDescription& type); + void removeType (const int index) throw(); - /** Removes a type. */ - void removeType (const int index) throw(); + bool scanAndAddFile (const String& possiblePluginFileOrIdentifier, + const bool dontRescanIfAlreadyInList, + OwnedArray & typesFound, + AudioPluginFormat& formatToUse); - /** Looks for all types that can be loaded from a given file, and adds them - to the list. + bool isListingUpToDate (const String& possiblePluginFileOrIdentifier) const throw(); - If dontRescanIfAlreadyInList is true, then the file will only be loaded and - re-tested if it's not already in the list, or if the file's modification - time has changed since the list was created. If dontRescanIfAlreadyInList is - false, the file will always be reloaded and tested. + void scanAndAddDragAndDroppedFiles (const StringArray& filenames, + OwnedArray & typesFound); - Returns true if any new types were added, and all the types found in this - file (even if it was already known and hasn't been re-scanned) get returned - in the array. - */ - bool scanAndAddFile (const String& possiblePluginFileOrIdentifier, - const bool dontRescanIfAlreadyInList, - OwnedArray & typesFound, - AudioPluginFormat& formatToUse); + enum SortMethod + { + defaultOrder = 0, + sortAlphabetically, + sortByCategory, + sortByManufacturer, + sortByFileSystemLocation + }; - /** Returns true if the specified file is already known about and if it - hasn't been modified since our entry was created. - */ - bool isListingUpToDate (const String& possiblePluginFileOrIdentifier) const throw(); + void addToMenu (PopupMenu& menu, + const SortMethod sortMethod) const; - /** Scans and adds a bunch of files that might have been dragged-and-dropped. + int getIndexChosenByMenu (const int menuResultCode) const; - If any types are found in the files, their descriptions are returned in the array. - */ - void scanAndAddDragAndDroppedFiles (const StringArray& filenames, - OwnedArray & typesFound); + void sort (const SortMethod method); - /** Sort methods used to change the order of the plugins in the list. - */ - enum SortMethod - { - defaultOrder = 0, - sortAlphabetically, - sortByCategory, - sortByManufacturer, - sortByFileSystemLocation - }; + XmlElement* createXml() const; - /** Adds all the plugin types to a popup menu so that the user can select one. + void recreateFromXml (const XmlElement& xml); - Depending on the sort method, it may add sub-menus for categories, - manufacturers, etc. - - Use getIndexChosenByMenu() to find out the type that was chosen. - */ - void addToMenu (PopupMenu& menu, - const SortMethod sortMethod) const; - - /** Converts a menu item index that has been chosen into its index in this list. - - Returns -1 if it's not an ID that was used. - - @see addToMenu - */ - int getIndexChosenByMenu (const int menuResultCode) const; - - /** Sorts the list. */ - void sort (const SortMethod method); - - /** Creates some XML that can be used to store the state of this list. - */ - XmlElement* createXml() const; - - /** Recreates the state of this list from its stored XML format. - */ - void recreateFromXml (const XmlElement& xml); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OwnedArray types; + OwnedArray types; - KnownPluginList (const KnownPluginList&); - const KnownPluginList& operator= (const KnownPluginList&); + KnownPluginList (const KnownPluginList&); + const KnownPluginList& operator= (const KnownPluginList&); }; #endif // __JUCE_KNOWNPLUGINLIST_JUCEHEADER__ @@ -37333,90 +17798,42 @@ private: #ifndef __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__ #define __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__ -/** - Scans a directory for plugins, and adds them to a KnownPluginList. - - To use one of these, create it and call scanNextFile() repeatedly, until - it returns false. -*/ class JUCE_API PluginDirectoryScanner { public: - /** - Creates a scanner. + PluginDirectoryScanner (KnownPluginList& listToAddResultsTo, + AudioPluginFormat& formatToLookFor, + FileSearchPath directoriesToSearch, + const bool searchRecursively, + const File& deadMansPedalFile); - @param listToAddResultsTo this will get the new types added to it. - @param formatToLookFor this is the type of format that you want to look for - @param directoriesToSearch the path to search - @param searchRecursively true to search recursively - @param deadMansPedalFile if this isn't File::nonexistent, then it will - be used as a file to store the names of any plugins - that crash during initialisation. If there are - any plugins listed in it, then these will always - be scanned after all other possible files have - been tried - in this way, even if there's a few - dodgy plugins in your path, then a couple of rescans - will still manage to find all the proper plugins. - It's probably best to choose a file in the user's - application data directory (alongside your app's - settings file) for this. The file format it uses - is just a list of filenames of the modules that - failed. - */ - PluginDirectoryScanner (KnownPluginList& listToAddResultsTo, - AudioPluginFormat& formatToLookFor, - FileSearchPath directoriesToSearch, - const bool searchRecursively, - const File& deadMansPedalFile); + ~PluginDirectoryScanner(); - /** Destructor. */ - ~PluginDirectoryScanner(); + bool scanNextFile (const bool dontRescanIfAlreadyInList); - /** Tries the next likely-looking file. + const String getNextPluginFileThatWillBeScanned() const throw(); - If dontRescanIfAlreadyInList is true, then the file will only be loaded and - re-tested if it's not already in the list, or if the file's modification - time has changed since the list was created. If dontRescanIfAlreadyInList is - false, the file will always be reloaded and tested. + float getProgress() const { return progress; } - Returns false when there are no more files to try. - */ - bool scanNextFile (const bool dontRescanIfAlreadyInList); + const StringArray& getFailedFiles() const throw() { return failedFiles; } - /** Returns the description of the plugin that will be scanned during the next - call to scanNextFile(). - - This is handy if you want to show the user which file is currently getting - scanned. - */ - const String getNextPluginFileThatWillBeScanned() const throw(); - - /** Returns the estimated progress, between 0 and 1. - */ - float getProgress() const { return progress; } - - /** This returns a list of all the filenames of things that looked like being - a plugin file, but which failed to open for some reason. - */ - const StringArray& getFailedFiles() const throw() { return failedFiles; } - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - KnownPluginList& list; - AudioPluginFormat& format; - StringArray filesOrIdentifiersToScan; - File deadMansPedalFile; - StringArray failedFiles; - int nextIndex; - float progress; + KnownPluginList& list; + AudioPluginFormat& format; + StringArray filesOrIdentifiersToScan; + File deadMansPedalFile; + StringArray failedFiles; + int nextIndex; + float progress; - const StringArray getDeadMansPedalFile() throw(); - void setDeadMansPedalFile (const StringArray& newContents) throw(); + const StringArray getDeadMansPedalFile() throw(); + void setDeadMansPedalFile (const StringArray& newContents) throw(); - PluginDirectoryScanner (const PluginDirectoryScanner&); - const PluginDirectoryScanner& operator= (const PluginDirectoryScanner&); + PluginDirectoryScanner (const PluginDirectoryScanner&); + const PluginDirectoryScanner& operator= (const PluginDirectoryScanner&); }; #endif // __JUCE_PLUGINDIRECTORYSCANNER_JUCEHEADER__ @@ -37435,543 +17852,179 @@ private: class ListViewport; -/** - A subclass of this is used to drive a ListBox. - - @see ListBox -*/ class JUCE_API ListBoxModel { public: - /** Destructor. */ - virtual ~ListBoxModel() {} + virtual ~ListBoxModel() {} - /** This has to return the number of items in the list. + virtual int getNumRows() = 0; - @see ListBox::getNumRows() - */ - virtual int getNumRows() = 0; + virtual void paintListBoxItem (int rowNumber, + Graphics& g, + int width, int height, + bool rowIsSelected) = 0; - /** This method must be implemented to draw a row of the list. - */ - virtual void paintListBoxItem (int rowNumber, - Graphics& g, - int width, int height, - bool rowIsSelected) = 0; + virtual Component* refreshComponentForRow (int rowNumber, bool isRowSelected, + Component* existingComponentToUpdate); - /** This is used to create or update a custom component to go in a row of the list. + virtual void listBoxItemClicked (int row, const MouseEvent& e); - Any row may contain a custom component, or can just be drawn with the paintListBoxItem() method - and handle mouse clicks with listBoxItemClicked(). + virtual void listBoxItemDoubleClicked (int row, const MouseEvent& e); - This method will be called whenever a custom component might need to be updated - e.g. - when the table is changed, or TableListBox::updateContent() is called. + virtual void backgroundClicked(); - If you don't need a custom component for the specified row, then return 0. + virtual void selectedRowsChanged (int lastRowSelected); - If you do want a custom component, and the existingComponentToUpdate is null, then - this method must create a suitable new component and return it. + virtual void deleteKeyPressed (int lastRowSelected); - If the existingComponentToUpdate is non-null, it will be a pointer to a component previously created - by this method. In this case, the method must either update it to make sure it's correctly representing - the given row (which may be different from the one that the component was created for), or it can - delete this component and return a new one. + virtual void returnKeyPressed (int lastRowSelected); - The component that your method returns will be deleted by the ListBox when it is no longer needed. - */ - virtual Component* refreshComponentForRow (int rowNumber, bool isRowSelected, - Component* existingComponentToUpdate); + virtual void listWasScrolled(); - /** This can be overridden to react to the user clicking on a row. + virtual const String getDragSourceDescription (const SparseSet& currentlySelectedRows); - @see listBoxItemDoubleClicked - */ - virtual void listBoxItemClicked (int row, const MouseEvent& e); - - /** This can be overridden to react to the user double-clicking on a row. - - @see listBoxItemClicked - */ - virtual void listBoxItemDoubleClicked (int row, const MouseEvent& e); - - /** This can be overridden to react to the user double-clicking on a part of the list where - there are no rows. - - @see listBoxItemClicked - */ - virtual void backgroundClicked(); - - /** Override this to be informed when rows are selected or deselected. - - This will be called whenever a row is selected or deselected. If a range of - rows is selected all at once, this will just be called once for that event. - - @param lastRowSelected the last row that the user selected. If no - rows are currently selected, this may be -1. - */ - virtual void selectedRowsChanged (int lastRowSelected); - - /** Override this to be informed when the delete key is pressed. - - If no rows are selected when they press the key, this won't be called. - - @param lastRowSelected the last row that had been selected when they pressed the - key - if there are multiple selections, this might not be - very useful - */ - virtual void deleteKeyPressed (int lastRowSelected); - - /** Override this to be informed when the return key is pressed. - - If no rows are selected when they press the key, this won't be called. - - @param lastRowSelected the last row that had been selected when they pressed the - key - if there are multiple selections, this might not be - very useful - */ - virtual void returnKeyPressed (int lastRowSelected); - - /** Override this to be informed when the list is scrolled. - - This might be caused by the user moving the scrollbar, or by programmatic changes - to the list position. - */ - virtual void listWasScrolled(); - - /** To allow rows from your list to be dragged-and-dropped, implement this method. - - If this returns a non-empty name then when the user drags a row, the listbox will - try to find a DragAndDropContainer in its parent hierarchy, and will use it to trigger - a drag-and-drop operation, using this string as the source description, with the listbox - itself as the source component. - - @see DragAndDropContainer::startDragging - */ - virtual const String getDragSourceDescription (const SparseSet& currentlySelectedRows); - - /** You can override this to provide tool tips for specific rows. - @see TooltipClient - */ - virtual const String getTooltipForRow (int row); + virtual const String getTooltipForRow (int row); }; -/** - A list of items that can be scrolled vertically. - - To create a list, you'll need to create a subclass of ListBoxModel. This can - either paint each row of the list and respond to events via callbacks, or for - more specialised tasks, it can supply a custom component to fill each row. - - @see ComboBox, TableListBox -*/ class JUCE_API ListBox : public Component, - public SettableTooltipClient + public SettableTooltipClient { public: - /** Creates a ListBox. + ListBox (const String& componentName, + ListBoxModel* const model); - The model pointer passed-in can be null, in which case you can set it later - with setModel(). - */ - ListBox (const String& componentName, - ListBoxModel* const model); + ~ListBox(); - /** Destructor. */ - ~ListBox(); + void setModel (ListBoxModel* const newModel); - /** Changes the current data model to display. */ - void setModel (ListBoxModel* const newModel); + ListBoxModel* getModel() const throw() { return model; } - /** Returns the current list model. */ - ListBoxModel* getModel() const throw() { return model; } + void updateContent(); - /** Causes the list to refresh its content. + void setMultipleSelectionEnabled (bool shouldBeEnabled); - Call this when the number of rows in the list changes, or if you want it - to call refreshComponentForRow() on all the row components. + void setMouseMoveSelectsRows (bool shouldSelect); - Be careful not to call it from a different thread, though, as it's not - thread-safe. - */ - void updateContent(); + void selectRow (const int rowNumber, + bool dontScrollToShowThisRow = false, + bool deselectOthersFirst = true); - /** Turns on multiple-selection of rows. + void selectRangeOfRows (int firstRow, + int lastRow); - By default this is disabled. + void deselectRow (const int rowNumber); - When your row component gets clicked you'll need to call the - selectRowsBasedOnModifierKeys() method to tell the list that it's been - clicked and to get it to do the appropriate selection based on whether - the ctrl/shift keys are held down. - */ - void setMultipleSelectionEnabled (bool shouldBeEnabled); + void deselectAllRows(); - /** Makes the list react to mouse moves by selecting the row that the mouse if over. + void flipRowSelection (const int rowNumber); - This function is here primarily for the ComboBox class to use, but might be - useful for some other purpose too. - */ - void setMouseMoveSelectsRows (bool shouldSelect); + const SparseSet getSelectedRows() const; - /** Selects a row. + void setSelectedRows (const SparseSet& setOfRowsToBeSelected, + const bool sendNotificationEventToModel = true); - If the row is already selected, this won't do anything. + bool isRowSelected (const int rowNumber) const; - @param rowNumber the row to select - @param dontScrollToShowThisRow if true, the list's position won't change; if false and - the selected row is off-screen, it'll scroll to make - sure that row is on-screen - @param deselectOthersFirst if true and there are multiple selections, these will - first be deselected before this item is selected - @see isRowSelected, selectRowsBasedOnModifierKeys, flipRowSelection, deselectRow, - deselectAllRows, selectRangeOfRows - */ - void selectRow (const int rowNumber, - bool dontScrollToShowThisRow = false, - bool deselectOthersFirst = true); + int getNumSelectedRows() const; - /** Selects a set of rows. + int getSelectedRow (const int index = 0) const; - This will add these rows to the current selection, so you might need to - clear the current selection first with deselectAllRows() + int getLastRowSelected() const; - @param firstRow the first row to select (inclusive) - @param lastRow the last row to select (inclusive) - */ - void selectRangeOfRows (int firstRow, - int lastRow); + void selectRowsBasedOnModifierKeys (const int rowThatWasClickedOn, + const ModifierKeys& modifiers); - /** Deselects a row. + void setVerticalPosition (const double newProportion); - If it's not currently selected, this will do nothing. + double getVerticalPosition() const; - @see selectRow, deselectAllRows - */ - void deselectRow (const int rowNumber); + void scrollToEnsureRowIsOnscreen (const int row); - /** Deselects any currently selected rows. + ScrollBar* getVerticalScrollBar() const throw(); - @see deselectRow - */ - void deselectAllRows(); + ScrollBar* getHorizontalScrollBar() const throw(); - /** Selects or deselects a row. + int getRowContainingPosition (const int x, const int y) const throw(); - If the row's currently selected, this deselects it, and vice-versa. - */ - void flipRowSelection (const int rowNumber); + int getInsertionIndexForPosition (const int x, const int y) const throw(); - /** Returns a sparse set indicating the rows that are currently selected. + const Rectangle getRowPosition (const int rowNumber, + const bool relativeToComponentTopLeft) const throw(); - @see setSelectedRows - */ - const SparseSet getSelectedRows() const; + Component* getComponentForRowNumber (const int rowNumber) const throw(); - /** Sets the rows that should be selected, based on an explicit set of ranges. + int getRowNumberOfComponent (Component* const rowComponent) const throw(); - If sendNotificationEventToModel is true, the ListBoxModel::selectedRowsChanged() - method will be called. If it's false, no notification will be sent to the model. + int getVisibleRowWidth() const throw(); - @see getSelectedRows - */ - void setSelectedRows (const SparseSet& setOfRowsToBeSelected, - const bool sendNotificationEventToModel = true); + void setRowHeight (const int newHeight); - /** Checks whether a row is selected. - */ - bool isRowSelected (const int rowNumber) const; + int getRowHeight() const throw() { return rowHeight; } - /** Returns the number of rows that are currently selected. + int getNumRowsOnScreen() const throw(); - @see getSelectedRow, isRowSelected, getLastRowSelected - */ - int getNumSelectedRows() const; + enum ColourIds + { + backgroundColourId = 0x1002800, /**< The background colour to fill the list with. + Make this transparent if you don't want the background to be filled. */ + outlineColourId = 0x1002810, /**< An optional colour to use to draw a border around the list. + Make this transparent to not have an outline. */ + textColourId = 0x1002820 /**< The preferred colour to use for drawing text in the listbox. */ + }; - /** Returns the row number of a selected row. + void setOutlineThickness (const int outlineThickness); - This will return the row number of the Nth selected row. The row numbers returned will - be sorted in order from low to high. + int getOutlineThickness() const throw() { return outlineThickness; } - @param index the index of the selected row to return, (from 0 to getNumSelectedRows() - 1) - @returns the row number, or -1 if the index was out of range or if there aren't any rows - selected - @see getNumSelectedRows, isRowSelected, getLastRowSelected - */ - int getSelectedRow (const int index = 0) const; + void setHeaderComponent (Component* const newHeaderComponent); - /** Returns the last row that the user selected. + void setMinimumContentWidth (const int newMinimumWidth); - This isn't the same as the highest row number that is currently selected - if the user - had multiply-selected rows 10, 5 and then 6 in that order, this would return 6. + int getVisibleContentWidth() const throw(); - If nothing is selected, it will return -1. - */ - int getLastRowSelected() const; + void repaintRow (const int rowNumber) throw(); - /** Multiply-selects rows based on the modifier keys. + Image* createSnapshotOfSelectedRows (int& x, int& y); - If no modifier keys are down, this will select the given row and - deselect any others. + Viewport* getViewport() const throw(); - If the ctrl (or command on the Mac) key is down, it'll flip the - state of the selected row. + bool keyPressed (const KeyPress& key); + bool keyStateChanged (const bool isKeyDown); + void paint (Graphics& g); + void paintOverChildren (Graphics& g); + void resized(); + void visibilityChanged(); + void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); + void mouseMove (const MouseEvent&); + void mouseExit (const MouseEvent&); + void mouseUp (const MouseEvent&); + void colourChanged(); + void startDragAndDrop (const MouseEvent& e, const String& dragDescription); - If the shift key is down, it'll select up to the given row from the - last row selected. - - @see selectRow - */ - void selectRowsBasedOnModifierKeys (const int rowThatWasClickedOn, - const ModifierKeys& modifiers); - - /** Scrolls the list to a particular position. - - The proportion is between 0 and 1.0, so 0 scrolls to the top of the list, - 1.0 scrolls to the bottom. - - If the total number of rows all fit onto the screen at once, then this - method won't do anything. - - @see getVerticalPosition - */ - void setVerticalPosition (const double newProportion); - - /** Returns the current vertical position as a proportion of the total. - - This can be used in conjunction with setVerticalPosition() to save and restore - the list's position. It returns a value in the range 0 to 1. - - @see setVerticalPosition - */ - double getVerticalPosition() const; - - /** Scrolls if necessary to make sure that a particular row is visible. - */ - void scrollToEnsureRowIsOnscreen (const int row); - - /** Returns a pointer to the scrollbar. - - (Unlikely to be useful for most people). - */ - ScrollBar* getVerticalScrollBar() const throw(); - - /** Returns a pointer to the scrollbar. - - (Unlikely to be useful for most people). - */ - ScrollBar* getHorizontalScrollBar() const throw(); - - /** Finds the row index that contains a given x,y position. - - The position is relative to the ListBox's top-left. - - If no row exists at this position, the method will return -1. - - @see getComponentForRowNumber - */ - int getRowContainingPosition (const int x, const int y) const throw(); - - /** Finds a row index that would be the most suitable place to insert a new - item for a given position. - - This is useful when the user is e.g. dragging and dropping onto the listbox, - because it lets you easily choose the best position to insert the item that - they drop, based on where they drop it. - - If the position is out of range, this will return -1. If the position is - beyond the end of the list, it will return getNumRows() to indicate the end - of the list. - - @see getComponentForRowNumber - */ - int getInsertionIndexForPosition (const int x, const int y) const throw(); - - /** Returns the position of one of the rows, relative to the top-left of - the listbox. - - This may be off-screen, and the range of the row number that is passed-in is - not checked to see if it's a valid row. - */ - const Rectangle getRowPosition (const int rowNumber, - const bool relativeToComponentTopLeft) const throw(); - - /** Finds the row component for a given row in the list. - - The component returned will have been created using createRowComponent(). - - If the component for this row is off-screen or if the row is out-of-range, - this will return 0. - - @see getRowContainingPosition - */ - Component* getComponentForRowNumber (const int rowNumber) const throw(); - - /** Returns the row number that the given component represents. - - If the component isn't one of the list's rows, this will return -1. - */ - int getRowNumberOfComponent (Component* const rowComponent) const throw(); - - /** Returns the width of a row (which may be less than the width of this component - if there's a scrollbar). - */ - int getVisibleRowWidth() const throw(); - - /** Sets the height of each row in the list. - - The default height is 22 pixels. - - @see getRowHeight - */ - void setRowHeight (const int newHeight); - - /** Returns the height of a row in the list. - - @see setRowHeight - */ - int getRowHeight() const throw() { return rowHeight; } - - /** Returns the number of rows actually visible. - - This is the number of whole rows which will fit on-screen, so the value might - be more than the actual number of rows in the list. - */ - int getNumRowsOnScreen() const throw(); - - /** A set of colour IDs to use to change the colour of various aspects of the label. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1002800, /**< The background colour to fill the list with. - Make this transparent if you don't want the background to be filled. */ - outlineColourId = 0x1002810, /**< An optional colour to use to draw a border around the list. - Make this transparent to not have an outline. */ - textColourId = 0x1002820 /**< The preferred colour to use for drawing text in the listbox. */ - }; - - /** Sets the thickness of a border that will be drawn around the box. - - To set the colour of the outline, use @code setColour (ListBox::outlineColourId, colourXYZ); @endcode - @see outlineColourId - */ - void setOutlineThickness (const int outlineThickness); - - /** Returns the thickness of outline that will be drawn around the listbox. - - @see setOutlineColour - */ - int getOutlineThickness() const throw() { return outlineThickness; } - - /** Sets a component that the list should use as a header. - - This will position the given component at the top of the list, maintaining the - height of the component passed-in, but rescaling it horizontally to match the - width of the items in the listbox. - - The component will be deleted when setHeaderComponent() is called with a - different component, or when the listbox is deleted. - */ - void setHeaderComponent (Component* const newHeaderComponent); - - /** Changes the width of the rows in the list. - - This can be used to make the list's row components wider than the list itself - the - width of the rows will be either the width of the list or this value, whichever is - greater, and if the rows become wider than the list, a horizontal scrollbar will - appear. - - The default value for this is 0, which means that the rows will always - be the same width as the list. - */ - void setMinimumContentWidth (const int newMinimumWidth); - - /** Returns the space currently available for the row items, taking into account - borders, scrollbars, etc. - */ - int getVisibleContentWidth() const throw(); - - /** Repaints one of the rows. - - This is a lightweight alternative to calling updateContent, and just causes a - repaint of the row's area. - */ - void repaintRow (const int rowNumber) throw(); - - /** This fairly obscure method creates an image that just shows the currently - selected row components. - - It's a handy method for doing drag-and-drop, as it can be passed to the - DragAndDropContainer for use as the drag image. - - Note that it will make the row components temporarily invisible, so if you're - using custom components this could affect them if they're sensitive to that - sort of thing. - - @see Component::createComponentSnapshot - */ - Image* createSnapshotOfSelectedRows (int& x, int& y); - - /** Returns the viewport that this ListBox uses. - - You may need to use this to change parameters such as whether scrollbars - are shown, etc. - */ - Viewport* getViewport() const throw(); - - /** @internal */ - bool keyPressed (const KeyPress& key); - /** @internal */ - bool keyStateChanged (const bool isKeyDown); - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void paintOverChildren (Graphics& g); - /** @internal */ - void resized(); - /** @internal */ - void visibilityChanged(); - /** @internal */ - void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); - /** @internal */ - void mouseMove (const MouseEvent&); - /** @internal */ - void mouseExit (const MouseEvent&); - /** @internal */ - void mouseUp (const MouseEvent&); - /** @internal */ - void colourChanged(); - /** @internal */ - void startDragAndDrop (const MouseEvent& e, const String& dragDescription); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class ListViewport; - friend class TableListBox; - ListBoxModel* model; - ListViewport* viewport; - Component* headerComponent; - int totalItems, rowHeight, minimumRowWidth; - int outlineThickness; - int lastMouseX, lastMouseY, lastRowSelected; - bool mouseMoveSelects, multipleSelection, hasDoneInitialUpdate; - SparseSet selected; + friend class ListViewport; + friend class TableListBox; + ListBoxModel* model; + ListViewport* viewport; + Component* headerComponent; + int totalItems, rowHeight, minimumRowWidth; + int outlineThickness; + int lastMouseX, lastMouseY, lastRowSelected; + bool mouseMoveSelects, multipleSelection, hasDoneInitialUpdate; + SparseSet selected; - void selectRowInternal (const int rowNumber, - bool dontScrollToShowThisRow, - bool deselectOthersFirst, - bool isMouseClick); + void selectRowInternal (const int rowNumber, + bool dontScrollToShowThisRow, + bool deselectOthersFirst, + bool isMouseClick); - ListBox (const ListBox&); - const ListBox& operator= (const ListBox&); + ListBox (const ListBox&); + const ListBox& operator= (const ListBox&); }; #endif // __JUCE_LISTBOX_JUCEHEADER__ @@ -37981,138 +18034,83 @@ private: #ifndef __JUCE_TEXTBUTTON_JUCEHEADER__ #define __JUCE_TEXTBUTTON_JUCEHEADER__ -/** - A button that uses the standard lozenge-shaped background with a line of - text on it. - - @see Button, DrawableButton -*/ class JUCE_API TextButton : public Button { public: - /** Creates a TextButton. + TextButton (const String& buttonName, + const String& toolTip = String::empty); - @param buttonName the text to put in the button (the component's name is also - initially set to this string, but these can be changed later - using the setName() and setButtonText() methods) - @param toolTip an optional string to use as a toolip + ~TextButton(); - @see Button - */ - TextButton (const String& buttonName, - const String& toolTip = String::empty); + enum ColourIds + { + buttonColourId = 0x1000100, /**< The colour used to fill the button shape (when the button is toggled + 'off'). The look-and-feel class might re-interpret this to add + effects, etc. */ + buttonOnColourId = 0x1000101, /**< The colour used to fill the button shape (when the button is toggled + 'on'). The look-and-feel class might re-interpret this to add + effects, etc. */ + textColourOffId = 0x1000102, /**< The colour to use for the button's text when the button's toggle state is "off". */ + textColourOnId = 0x1000103 /**< The colour to use for the button's text.when the button's toggle state is "on". */ + }; - /** Destructor. */ - ~TextButton(); + void changeWidthToFitText (const int newHeight = -1); - /** A set of colour IDs to use to change the colour of various aspects of the button. + virtual const Font getFont(); - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - buttonColourId = 0x1000100, /**< The colour used to fill the button shape (when the button is toggled - 'off'). The look-and-feel class might re-interpret this to add - effects, etc. */ - buttonOnColourId = 0x1000101, /**< The colour used to fill the button shape (when the button is toggled - 'on'). The look-and-feel class might re-interpret this to add - effects, etc. */ - textColourOffId = 0x1000102, /**< The colour to use for the button's text when the button's toggle state is "off". */ - textColourOnId = 0x1000103 /**< The colour to use for the button's text.when the button's toggle state is "on". */ - }; - - /** Resizes the button to fit neatly around its current text. - - If newHeight is >= 0, the button's height will be changed to this - value. If it's less than zero, its height will be unaffected. - */ - void changeWidthToFitText (const int newHeight = -1); - - /** This can be overridden to use different fonts than the default one. - - Note that you'll need to set the font's size appropriately, too. - */ - virtual const Font getFont(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown); - /** @internal */ - void colourChanged(); + void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown); + void colourChanged(); private: - TextButton (const TextButton&); - const TextButton& operator= (const TextButton&); + TextButton (const TextButton&); + const TextButton& operator= (const TextButton&); }; #endif // __JUCE_TEXTBUTTON_JUCEHEADER__ /********* End of inlined file: juce_TextButton.h *********/ -/** - A component displaying a list of plugins, with options to scan for them, - add, remove and sort them. -*/ class JUCE_API PluginListComponent : public Component, - public ListBoxModel, - public ChangeListener, - public ButtonListener, - public Timer + public ListBoxModel, + public ChangeListener, + public ButtonListener, + public Timer { public: - /** - Creates the list component. + PluginListComponent (KnownPluginList& listToRepresent, + const File& deadMansPedalFile, + PropertiesFile* const propertiesToUse); - For info about the deadMansPedalFile, see the PluginDirectoryScanner constructor. + ~PluginListComponent(); - The properties file, if supplied, is used to store the user's last search paths. - */ - PluginListComponent (KnownPluginList& listToRepresent, - const File& deadMansPedalFile, - PropertiesFile* const propertiesToUse); + void resized(); + bool isInterestedInFileDrag (const StringArray& files); + void filesDropped (const StringArray& files, int, int); + int getNumRows(); + void paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected); + void deleteKeyPressed (int lastRowSelected); + void buttonClicked (Button* b); + void changeListenerCallback (void*); + void timerCallback(); - /** Destructor. */ - ~PluginListComponent(); - - /** @internal */ - void resized(); - /** @internal */ - bool isInterestedInFileDrag (const StringArray& files); - /** @internal */ - void filesDropped (const StringArray& files, int, int); - /** @internal */ - int getNumRows(); - /** @internal */ - void paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected); - /** @internal */ - void deleteKeyPressed (int lastRowSelected); - /** @internal */ - void buttonClicked (Button* b); - /** @internal */ - void changeListenerCallback (void*); - /** @internal */ - void timerCallback(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - KnownPluginList& list; - File deadMansPedalFile; - ListBox* listBox; - TextButton* optionsButton; - PropertiesFile* propertiesToUse; - int typeToScan; + KnownPluginList& list; + File deadMansPedalFile; + ListBox* listBox; + TextButton* optionsButton; + PropertiesFile* propertiesToUse; + int typeToScan; - void scanFor (AudioPluginFormat* format); + void scanFor (AudioPluginFormat* format); - PluginListComponent (const PluginListComponent&); - const PluginListComponent& operator= (const PluginListComponent&); + PluginListComponent (const PluginListComponent&); + const PluginListComponent& operator= (const PluginListComponent&); }; #endif // __JUCE_PLUGINLISTCOMPONENT_JUCEHEADER__ @@ -38134,388 +18132,237 @@ private: #ifndef __JUCE_AUDIOPROCESSORGRAPH_JUCEHEADER__ #define __JUCE_AUDIOPROCESSORGRAPH_JUCEHEADER__ -/** - A type of AudioProcessor which plays back a graph of other AudioProcessors. - - Use one of these objects if you want to wire-up a set of AudioProcessors - and play back the result. - - Processors can be added to the graph as "nodes" using addNode(), and once - added, you can connect any of their input or output channels to other - nodes using addConnection(). - - To play back a graph through an audio device, you might want to use an - AudioProcessorPlayer object. -*/ class JUCE_API AudioProcessorGraph : public AudioProcessor, - public AsyncUpdater + public AsyncUpdater { public: - /** Creates an empty graph. - */ - AudioProcessorGraph(); + AudioProcessorGraph(); - /** Destructor. + ~AudioProcessorGraph(); - Any processor objects that have been added to the graph will also be deleted. - */ - ~AudioProcessorGraph(); + class JUCE_API Node : public ReferenceCountedObject + { + public: + ~Node(); - /** Represents one of the nodes, or processors, in an AudioProcessorGraph. + const uint32 id; - To create a node, call AudioProcessorGraph::addNode(). - */ - class JUCE_API Node : public ReferenceCountedObject - { - public: - /** Destructor. - */ - ~Node(); + AudioProcessor* const processor; - /** The ID number assigned to this node. + PropertySet properties; - This is assigned by the graph that owns it, and can't be changed. - */ - const uint32 id; + typedef ReferenceCountedObjectPtr Ptr; - /** The actual processor object that this node represents. - */ - AudioProcessor* const processor; + juce_UseDebuggingNewOperator - /** A set of user-definable properties that are associated with this node. + private: + friend class AudioProcessorGraph; - This can be used to attach values to the node for whatever purpose seems - useful. For example, you might store an x and y position if your application - is displaying the nodes on-screen. - */ - PropertySet properties; + bool isPrepared; - /** A convenient typedef for referring to a pointer to a node object. - */ - typedef ReferenceCountedObjectPtr Ptr; + Node (const uint32 id, AudioProcessor* const processor); - juce_UseDebuggingNewOperator + void prepare (const double sampleRate, const int blockSize, AudioProcessorGraph* const graph); + void unprepare(); - private: - friend class AudioProcessorGraph; + Node (const Node&); + const Node& operator= (const Node&); + }; - bool isPrepared; + struct JUCE_API Connection + { + public: - Node (const uint32 id, AudioProcessor* const processor); + uint32 sourceNodeId; - void prepare (const double sampleRate, const int blockSize, AudioProcessorGraph* const graph); - void unprepare(); + int sourceChannelIndex; - Node (const Node&); - const Node& operator= (const Node&); - }; + uint32 destNodeId; - /** Represents a connection between two channels of two nodes in an AudioProcessorGraph. + int destChannelIndex; - To create a connection, use AudioProcessorGraph::addConnection(). - */ - struct JUCE_API Connection - { - public: + juce_UseDebuggingNewOperator - /** The ID number of the node which is the input source for this connection. - @see AudioProcessorGraph::getNodeForId - */ - uint32 sourceNodeId; + private: + }; - /** The index of the output channel of the source node from which this - connection takes its data. + void clear(); - If this value is the special number AudioProcessorGraph::midiChannelIndex, then - it is referring to the source node's midi output. Otherwise, it is the zero-based - index of an audio output channel in the source node. - */ - int sourceChannelIndex; + int getNumNodes() const { return nodes.size(); } - /** The ID number of the node which is the destination for this connection. - @see AudioProcessorGraph::getNodeForId - */ - uint32 destNodeId; + Node* getNode (const int index) const { return nodes [index]; } - /** The index of the input channel of the destination node to which this - connection delivers its data. + Node* getNodeForId (const uint32 nodeId) const; - If this value is the special number AudioProcessorGraph::midiChannelIndex, then - it is referring to the destination node's midi input. Otherwise, it is the zero-based - index of an audio input channel in the destination node. - */ - int destChannelIndex; + Node* addNode (AudioProcessor* const newProcessor, + uint32 nodeId = 0); - juce_UseDebuggingNewOperator + bool removeNode (const uint32 nodeId); - private: - }; + int getNumConnections() const { return connections.size(); } - /** Deletes all nodes and connections from this graph. + const Connection* getConnection (const int index) const { return connections [index]; } - Any processor objects in the graph will be deleted. - */ - void clear(); + const Connection* getConnectionBetween (const uint32 sourceNodeId, + const int sourceChannelIndex, + const uint32 destNodeId, + const int destChannelIndex) const; - /** Returns the number of nodes in the graph. */ - int getNumNodes() const { return nodes.size(); } + bool isConnected (const uint32 possibleSourceNodeId, + const uint32 possibleDestNodeId) const; - /** Returns a pointer to one of the nodes in the graph. + bool canConnect (const uint32 sourceNodeId, const int sourceChannelIndex, + const uint32 destNodeId, const int destChannelIndex) const; - This will return 0 if the index is out of range. - @see getNodeForId - */ - Node* getNode (const int index) const { return nodes [index]; } + bool addConnection (const uint32 sourceNodeId, const int sourceChannelIndex, + const uint32 destNodeId, const int destChannelIndex); - /** Searches the graph for a node with the given ID number and returns it. + void removeConnection (const int index); - If no such node was found, this returns 0. - @see getNode - */ - Node* getNodeForId (const uint32 nodeId) const; + bool removeConnection (const uint32 sourceNodeId, const int sourceChannelIndex, + const uint32 destNodeId, const int destChannelIndex); - /** Adds a node to the graph. + bool disconnectNode (const uint32 nodeId); - This creates a new node in the graph, for the specified processor. Once you have - added a processor to the graph, the graph owns it and will delete it later when - it is no longer needed. + bool removeIllegalConnections(); - The optional nodeId parameter lets you specify an ID to use for the node, but - if the value is already in use, this new node will overwrite the old one. + static const int midiChannelIndex; - If this succeeds, it returns a pointer to the newly-created node. - */ - Node* addNode (AudioProcessor* const newProcessor, - uint32 nodeId = 0); + class JUCE_API AudioGraphIOProcessor : public AudioPluginInstance + { + public: + enum IODeviceType + { + audioInputNode, /**< In this mode, the processor has output channels + representing all the audio input channels that are + coming into its parent audio graph. */ + audioOutputNode, /**< In this mode, the processor has input channels + representing all the audio output channels that are + going out of its parent audio graph. */ + midiInputNode, /**< In this mode, the processor has a midi output which + delivers the same midi data that is arriving at its + parent graph. */ + midiOutputNode /**< In this mode, the processor has a midi input and + any data sent to it will be passed out of the parent + graph. */ + }; - /** Deletes a node within the graph which has the specified ID. + IODeviceType getType() const { return type; } - This will also delete any connections that are attached to this node. - */ - bool removeNode (const uint32 nodeId); + AudioProcessorGraph* getParentGraph() const { return graph; } - /** Returns the number of connections in the graph. */ - int getNumConnections() const { return connections.size(); } + bool isInput() const; + bool isOutput() const; - /** Returns a pointer to one of the connections in the graph. */ - const Connection* getConnection (const int index) const { return connections [index]; } + AudioGraphIOProcessor (const IODeviceType type); + ~AudioGraphIOProcessor(); - /** Searches for a connection between some specified channels. - - If no such connection is found, this returns 0. - */ - const Connection* getConnectionBetween (const uint32 sourceNodeId, - const int sourceChannelIndex, - const uint32 destNodeId, - const int destChannelIndex) const; - - /** Returns true if there is a connection between any of the channels of - two specified nodes. - */ - bool isConnected (const uint32 possibleSourceNodeId, - const uint32 possibleDestNodeId) const; - - /** Returns true if it would be legal to connect the specified points. - */ - bool canConnect (const uint32 sourceNodeId, const int sourceChannelIndex, - const uint32 destNodeId, const int destChannelIndex) const; - - /** Attempts to connect two specified channels of two nodes. - - If this isn't allowed (e.g. because you're trying to connect a midi channel - to an audio one or other such nonsense), then it'll return false. - */ - bool addConnection (const uint32 sourceNodeId, const int sourceChannelIndex, - const uint32 destNodeId, const int destChannelIndex); - - /** Deletes the connection with the specified index. - - Returns true if a connection was actually deleted. - */ - void removeConnection (const int index); - - /** Deletes any connection between two specified points. - - Returns true if a connection was actually deleted. - */ - bool removeConnection (const uint32 sourceNodeId, const int sourceChannelIndex, - const uint32 destNodeId, const int destChannelIndex); - - /** Removes all connections from the specified node. - */ - bool disconnectNode (const uint32 nodeId); + const String getName() const; + void fillInPluginDescription (PluginDescription& d) const; - /** Performs a sanity checks of all the connections. - - This might be useful if some of the processors are doing things like changing - their channel counts, which could render some connections obsolete. - */ - bool removeIllegalConnections(); - - /** A special number that represents the midi channel of a node. - - This is used as a channel index value if you want to refer to the midi input - or output instead of an audio channel. - */ - static const int midiChannelIndex; - - /** A special type of AudioProcessor that can live inside an AudioProcessorGraph - in order to use the audio that comes into and out of the graph itself. - - If you create an AudioGraphIOProcessor in "input" mode, it will act as a - node in the graph which delivers the audio that is coming into the parent - graph. This allows you to stream the data to other nodes and process the - incoming audio. - - Likewise, one of these in "output" mode can be sent data which it will add to - the sum of data being sent to the graph's output. - - @see AudioProcessorGraph - */ - class JUCE_API AudioGraphIOProcessor : public AudioPluginInstance - { - public: - /** Specifies the mode in which this processor will operate. - */ - enum IODeviceType - { - audioInputNode, /**< In this mode, the processor has output channels - representing all the audio input channels that are - coming into its parent audio graph. */ - audioOutputNode, /**< In this mode, the processor has input channels - representing all the audio output channels that are - going out of its parent audio graph. */ - midiInputNode, /**< In this mode, the processor has a midi output which - delivers the same midi data that is arriving at its - parent graph. */ - midiOutputNode /**< In this mode, the processor has a midi input and - any data sent to it will be passed out of the parent - graph. */ - }; - - /** Returns the mode of this processor. */ - IODeviceType getType() const { return type; } - - /** Returns the parent graph to which this processor belongs, or 0 if it - hasn't yet been added to one. */ - AudioProcessorGraph* getParentGraph() const { return graph; } - - /** True if this is an audio or midi input. */ - bool isInput() const; - /** True if this is an audio or midi output. */ - bool isOutput() const; - - AudioGraphIOProcessor (const IODeviceType type); - ~AudioGraphIOProcessor(); - - const String getName() const; - void fillInPluginDescription (PluginDescription& d) const; - - void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); - void releaseResources(); - void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - - const String getInputChannelName (const int channelIndex) const; - const String getOutputChannelName (const int channelIndex) const; - bool isInputChannelStereoPair (int index) const; - bool isOutputChannelStereoPair (int index) const; - bool acceptsMidi() const; - bool producesMidi() const; - - AudioProcessorEditor* createEditor(); - - int getNumParameters(); - const String getParameterName (int); - float getParameter (int); - const String getParameterText (int); - void setParameter (int, float); - - int getNumPrograms(); - int getCurrentProgram(); - void setCurrentProgram (int); - const String getProgramName (int); - void changeProgramName (int, const String&); - - void getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData); - void setStateInformation (const void* data, int sizeInBytes); - - /** @internal */ - void setParentGraph (AudioProcessorGraph* const graph); - - juce_UseDebuggingNewOperator - - private: - const IODeviceType type; - AudioProcessorGraph* graph; - - AudioGraphIOProcessor (const AudioGraphIOProcessor&); - const AudioGraphIOProcessor& operator= (const AudioGraphIOProcessor&); - }; - - // AudioProcessor methods: - - const String getName() const; - - void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); - void releaseResources(); - void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - - const String getInputChannelName (const int channelIndex) const; - const String getOutputChannelName (const int channelIndex) const; - bool isInputChannelStereoPair (int index) const; - bool isOutputChannelStereoPair (int index) const; - - bool acceptsMidi() const; - bool producesMidi() const; - - AudioProcessorEditor* createEditor() { return 0; } - - int getNumParameters() { return 0; } - const String getParameterName (int) { return String::empty; } - float getParameter (int) { return 0; } - const String getParameterText (int) { return String::empty; } - void setParameter (int, float) { } - - int getNumPrograms() { return 0; } - int getCurrentProgram() { return 0; } - void setCurrentProgram (int) { } - const String getProgramName (int) { return String::empty; } - void changeProgramName (int, const String&) { } - - void getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData); - void setStateInformation (const void* data, int sizeInBytes); + void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); + void releaseResources(); + void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); - /** @internal */ - void handleAsyncUpdate(); + const String getInputChannelName (const int channelIndex) const; + const String getOutputChannelName (const int channelIndex) const; + bool isInputChannelStereoPair (int index) const; + bool isOutputChannelStereoPair (int index) const; + bool acceptsMidi() const; + bool producesMidi() const; - juce_UseDebuggingNewOperator + AudioProcessorEditor* createEditor(); + + int getNumParameters(); + const String getParameterName (int); + float getParameter (int); + const String getParameterText (int); + void setParameter (int, float); + + int getNumPrograms(); + int getCurrentProgram(); + void setCurrentProgram (int); + const String getProgramName (int); + void changeProgramName (int, const String&); + + void getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData); + void setStateInformation (const void* data, int sizeInBytes); + + void setParentGraph (AudioProcessorGraph* const graph); + + juce_UseDebuggingNewOperator + + private: + const IODeviceType type; + AudioProcessorGraph* graph; + + AudioGraphIOProcessor (const AudioGraphIOProcessor&); + const AudioGraphIOProcessor& operator= (const AudioGraphIOProcessor&); + }; + + // AudioProcessor methods: + + const String getName() const; + + void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); + void releaseResources(); + void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); + + const String getInputChannelName (const int channelIndex) const; + const String getOutputChannelName (const int channelIndex) const; + bool isInputChannelStereoPair (int index) const; + bool isOutputChannelStereoPair (int index) const; + + bool acceptsMidi() const; + bool producesMidi() const; + + AudioProcessorEditor* createEditor() { return 0; } + + int getNumParameters() { return 0; } + const String getParameterName (int) { return String::empty; } + float getParameter (int) { return 0; } + const String getParameterText (int) { return String::empty; } + void setParameter (int, float) { } + + int getNumPrograms() { return 0; } + int getCurrentProgram() { return 0; } + void setCurrentProgram (int) { } + const String getProgramName (int) { return String::empty; } + void changeProgramName (int, const String&) { } + + void getStateInformation (JUCE_NAMESPACE::MemoryBlock& destData); + void setStateInformation (const void* data, int sizeInBytes); + + void handleAsyncUpdate(); + + juce_UseDebuggingNewOperator private: - ReferenceCountedArray nodes; - OwnedArray connections; - int lastNodeId; - AudioSampleBuffer renderingBuffers; - OwnedArray midiBuffers; + ReferenceCountedArray nodes; + OwnedArray connections; + int lastNodeId; + AudioSampleBuffer renderingBuffers; + OwnedArray midiBuffers; - CriticalSection renderLock; - VoidArray renderingOps; + CriticalSection renderLock; + VoidArray renderingOps; - friend class AudioGraphIOProcessor; - AudioSampleBuffer* currentAudioInputBuffer; - AudioSampleBuffer currentAudioOutputBuffer; - MidiBuffer* currentMidiInputBuffer; - MidiBuffer currentMidiOutputBuffer; + friend class AudioGraphIOProcessor; + AudioSampleBuffer* currentAudioInputBuffer; + AudioSampleBuffer currentAudioOutputBuffer; + MidiBuffer* currentMidiInputBuffer; + MidiBuffer currentMidiOutputBuffer; - void clearRenderingSequence(); - void buildRenderingSequence(); + void clearRenderingSequence(); + void buildRenderingSequence(); - bool isAnInputTo (const uint32 possibleInputId, - const uint32 possibleDestinationId, - const int recursionCheck) const; + bool isAnInputTo (const uint32 possibleInputId, + const uint32 possibleDestinationId, + const int recursionCheck) const; - AudioProcessorGraph (const AudioProcessorGraph&); - const AudioProcessorGraph& operator= (const AudioProcessorGraph&); + AudioProcessorGraph (const AudioProcessorGraph&); + const AudioProcessorGraph& operator= (const AudioProcessorGraph&); }; #endif // __JUCE_AUDIOPROCESSORGRAPH_JUCEHEADER__ @@ -38531,77 +18378,48 @@ private: #ifndef __JUCE_AUDIOPROCESSORPLAYER_JUCEHEADER__ #define __JUCE_AUDIOPROCESSORPLAYER_JUCEHEADER__ -/** - An AudioIODeviceCallback object which streams audio through an AudioProcessor. - - To use one of these, just make it the callback used by your AudioIODevice, and - give it a processor to use by calling setProcessor(). - - It's also a MidiInputCallback, so you can connect it to both an audio and midi - input to send both streams through the processor. - - @see AudioProcessor, AudioProcessorGraph -*/ -class JUCE_API AudioProcessorPlayer : public AudioIODeviceCallback, - public MidiInputCallback +class JUCE_API AudioProcessorPlayer : public AudioIODeviceCallback, + public MidiInputCallback { public: - /** - */ - AudioProcessorPlayer(); + AudioProcessorPlayer(); - /** Destructor. */ - virtual ~AudioProcessorPlayer(); + virtual ~AudioProcessorPlayer(); - /** Sets the processor that should be played. + void setProcessor (AudioProcessor* const processorToPlay); - The processor that is passed in will not be deleted or owned by this object. - To stop anything playing, pass in 0 to this method. - */ - void setProcessor (AudioProcessor* const processorToPlay); + AudioProcessor* getCurrentProcessor() const { return processor; } - /** Returns the current audio processor that is being played. - */ - AudioProcessor* getCurrentProcessor() const { return processor; } + MidiMessageCollector& getMidiMessageCollector() { return messageCollector; } - /** Returns a midi message collector that you can pass midi messages to if you - want them to be injected into the midi stream that is being sent to the - processor. - */ - MidiMessageCollector& getMidiMessageCollector() { return messageCollector; } + void audioDeviceIOCallback (const float** inputChannelData, + int totalNumInputChannels, + float** outputChannelData, + int totalNumOutputChannels, + int numSamples); + void audioDeviceAboutToStart (AudioIODevice* device); + void audioDeviceStopped(); + void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message); - /** @internal */ - void audioDeviceIOCallback (const float** inputChannelData, - int totalNumInputChannels, - float** outputChannelData, - int totalNumOutputChannels, - int numSamples); - /** @internal */ - void audioDeviceAboutToStart (AudioIODevice* device); - /** @internal */ - void audioDeviceStopped(); - /** @internal */ - void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - AudioProcessor* processor; - CriticalSection lock; - double sampleRate; - int blockSize; - bool isPrepared; + AudioProcessor* processor; + CriticalSection lock; + double sampleRate; + int blockSize; + bool isPrepared; - int numInputChans, numOutputChans; - float* channels [128]; - AudioSampleBuffer tempBuffer; + int numInputChans, numOutputChans; + float* channels [128]; + AudioSampleBuffer tempBuffer; - MidiBuffer incomingMidi; - MidiMessageCollector messageCollector; + MidiBuffer incomingMidi; + MidiMessageCollector messageCollector; - AudioProcessorPlayer (const AudioProcessorPlayer&); - const AudioProcessorPlayer& operator= (const AudioProcessorPlayer&); + AudioProcessorPlayer (const AudioProcessorPlayer&); + const AudioProcessorPlayer& operator= (const AudioProcessorPlayer&); }; #endif // __JUCE_AUDIOPROCESSORPLAYER_JUCEHEADER__ @@ -38624,239 +18442,100 @@ private: class EditableProperty; -/** - A base class for a component that goes in a PropertyPanel and displays one of - an item's properties. - - Subclasses of this are used to display a property in various forms, e.g. a - ChoicePropertyComponent shows its value as a combo box; a SliderPropertyComponent - shows its value as a slider; a TextPropertyComponent as a text box, etc. - - A subclass must implement the refresh() method which will be called to tell the - component to update itself, and is also responsible for calling this it when the - item that it refers to is changed. - - @see PropertyPanel, TextPropertyComponent, SliderPropertyComponent, - ChoicePropertyComponent, ButtonPropertyComponent, BooleanPropertyComponent -*/ class JUCE_API PropertyComponent : public Component, - public SettableTooltipClient + public SettableTooltipClient { public: - /** Creates a PropertyComponent. + PropertyComponent (const String& propertyName, + const int preferredHeight = 25); - @param propertyName the name is stored as this component's name, and is - used as the name displayed next to this component in - a property panel - @param preferredHeight the height that the component should be given - some - items may need to be larger than a normal row height. - This value can also be set if a subclass changes the - preferredHeight member variable. - */ - PropertyComponent (const String& propertyName, - const int preferredHeight = 25); + ~PropertyComponent(); - /** Destructor. */ - ~PropertyComponent(); + int getPreferredHeight() const throw() { return preferredHeight; } - /** Returns this item's preferred height. + virtual void refresh() = 0; - This value is specified either in the constructor or by a subclass changing the - preferredHeight member variable. - */ - int getPreferredHeight() const throw() { return preferredHeight; } + void paint (Graphics& g); - /** Updates the property component if the item it refers to has changed. + void resized(); - A subclass must implement this method, and other objects may call it to - force it to refresh itself. + void enablementChanged(); - The subclass should be economical in the amount of work is done, so for - example it should check whether it really needs to do a repaint rather than - just doing one every time this method is called, as it may be called when - the value being displayed hasn't actually changed. - */ - virtual void refresh() = 0; - - /** The default paint method fills the background and draws a label for the - item's name. - - @see LookAndFeel::drawPropertyComponentBackground(), LookAndFeel::drawPropertyComponentLabel() - */ - void paint (Graphics& g); - - /** The default resize method positions any child component to the right of this - one, based on the look and feel's default label size. - */ - void resized(); - - /** By default, this just repaints the component. */ - void enablementChanged(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** Used by the PropertyPanel to determine how high this component needs to be. - - A subclass can update this value in its constructor but shouldn't alter it later - as changes won't necessarily be picked up. - */ - int preferredHeight; + int preferredHeight; }; #endif // __JUCE_PROPERTYCOMPONENT_JUCEHEADER__ /********* End of inlined file: juce_PropertyComponent.h *********/ -/** - A panel that holds a list of PropertyComponent objects. - - This panel displays a list of PropertyComponents, and allows them to be organised - into collapsible sections. - - To use, simply create one of these and add your properties to it with addProperties() - or addSection(). - - @see PropertyComponent -*/ class JUCE_API PropertyPanel : public Component { public: - /** Creates an empty property panel. */ - PropertyPanel(); + PropertyPanel(); - /** Destructor. */ - ~PropertyPanel(); + ~PropertyPanel(); - /** Deletes all property components from the panel. - */ - void clear(); + void clear(); - /** Adds a set of properties to the panel. + void addProperties (const Array & newPropertyComponents); - The components in the list will be owned by this object and will be automatically - deleted later on when no longer needed. + void addSection (const String& sectionTitle, + const Array & newPropertyComponents, + const bool shouldSectionInitiallyBeOpen = true); - These properties are added without them being inside a named section. If you - want them to be kept together in a collapsible section, use addSection() instead. - */ - void addProperties (const Array & newPropertyComponents); + void refreshAll() const; - /** Adds a set of properties to the panel. + const StringArray getSectionNames() const; - These properties are added at the bottom of the list, under a section heading with - a plus/minus button that allows it to be opened and closed. + bool isSectionOpen (const int sectionIndex) const; - The components in the list will be owned by this object and will be automatically - deleted later on when no longer needed. + void setSectionOpen (const int sectionIndex, const bool shouldBeOpen); - To add properies without them being in a section, use addProperties(). - */ - void addSection (const String& sectionTitle, - const Array & newPropertyComponents, - const bool shouldSectionInitiallyBeOpen = true); + void setSectionEnabled (const int sectionIndex, const bool shouldBeEnabled); - /** Calls the refresh() method of all PropertyComponents in the panel */ - void refreshAll() const; + XmlElement* getOpennessState() const; - /** Returns a list of all the names of sections in the panel. + void restoreOpennessState (const XmlElement& newState); - These are the sections that have been added with addSection(). - */ - const StringArray getSectionNames() const; + void setMessageWhenEmpty (const String& newMessage); - /** Returns true if the section at this index is currently open. + const String& getMessageWhenEmpty() const; - The index is from 0 up to the number of items returned by getSectionNames(). - */ - bool isSectionOpen (const int sectionIndex) const; + void paint (Graphics& g); + void resized(); - /** Opens or closes one of the sections. - - The index is from 0 up to the number of items returned by getSectionNames(). - */ - void setSectionOpen (const int sectionIndex, const bool shouldBeOpen); - - /** Enables or disables one of the sections. - - The index is from 0 up to the number of items returned by getSectionNames(). - */ - void setSectionEnabled (const int sectionIndex, const bool shouldBeEnabled); - - /** Saves the current state of open/closed sections so it can be restored later. - - The caller is responsible for deleting the object that is returned. - - To restore this state, use restoreOpennessState(). - - @see restoreOpennessState - */ - XmlElement* getOpennessState() const; - - /** Restores a previously saved arrangement of open/closed sections. - - This will try to restore a snapshot of the panel's state that was created by - the getOpennessState() method. If any of the sections named in the original - XML aren't present, they will be ignored. - - @see getOpennessState - */ - void restoreOpennessState (const XmlElement& newState); - - /** Sets a message to be displayed when there are no properties in the panel. - - The default message is "nothing selected". - */ - void setMessageWhenEmpty (const String& newMessage); - - /** Returns the message that is displayed when there are no properties. - @see setMessageWhenEmpty - */ - const String& getMessageWhenEmpty() const; - - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void resized(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - Viewport* viewport; - Component* propertyHolderComponent; - String messageWhenEmpty; + Viewport* viewport; + Component* propertyHolderComponent; + String messageWhenEmpty; - void updatePropHolderLayout() const; - void updatePropHolderLayout (const int width) const; + void updatePropHolderLayout() const; + void updatePropHolderLayout (const int width) const; }; #endif // __JUCE_PROPERTYPANEL_JUCEHEADER__ /********* End of inlined file: juce_PropertyPanel.h *********/ -/** - A type of UI component that displays the parameters of an AudioProcessor as - a simple list of sliders. - - This can be used for showing an editor for a processor that doesn't supply - its own custom editor. - - @see AudioProcessor -*/ -class JUCE_API GenericAudioProcessorEditor : public AudioProcessorEditor +class JUCE_API GenericAudioProcessorEditor : public AudioProcessorEditor { public: - GenericAudioProcessorEditor (AudioProcessor* const owner); - ~GenericAudioProcessorEditor(); + GenericAudioProcessorEditor (AudioProcessor* const owner); + ~GenericAudioProcessorEditor(); - void paint (Graphics& g); - void resized(); + void paint (Graphics& g); + void resized(); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - PropertyPanel* panel; + PropertyPanel* panel; }; #endif // __JUCE_GENERICAUDIOPROCESSOREDITOR_JUCEHEADER__ @@ -38873,545 +18552,231 @@ private: #ifndef __JUCE_SYNTHESISER_JUCEHEADER__ #define __JUCE_SYNTHESISER_JUCEHEADER__ -/** - Describes one of the sounds that a Synthesiser can play. - - A synthesiser can contain one or more sounds, and a sound can choose which - midi notes and channels can trigger it. - - The SynthesiserSound is a passive class that just describes what the sound is - - the actual audio rendering for a sound is done by a SynthesiserVoice. This allows - more than one SynthesiserVoice to play the same sound at the same time. - - @see Synthesiser, SynthesiserVoice -*/ -class JUCE_API SynthesiserSound : public ReferenceCountedObject +class JUCE_API SynthesiserSound : public ReferenceCountedObject { protected: - SynthesiserSound(); + SynthesiserSound(); public: - /** Destructor. */ - virtual ~SynthesiserSound(); + virtual ~SynthesiserSound(); - /** Returns true if this sound should be played when a given midi note is pressed. + virtual bool appliesToNote (const int midiNoteNumber) = 0; - The Synthesiser will use this information when deciding which sounds to trigger - for a given note. - */ - virtual bool appliesToNote (const int midiNoteNumber) = 0; + virtual bool appliesToChannel (const int midiChannel) = 0; - /** Returns true if the sound should be triggered by midi events on a given channel. + typedef ReferenceCountedObjectPtr Ptr; - The Synthesiser will use this information when deciding which sounds to trigger - for a given note. - */ - virtual bool appliesToChannel (const int midiChannel) = 0; - - /** - */ - typedef ReferenceCountedObjectPtr Ptr; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; -/** - Represents a voice that a Synthesiser can use to play a SynthesiserSound. - - A voice plays a single sound at a time, and a synthesiser holds an array of - voices so that it can play polyphonically. - - @see Synthesiser, SynthesiserSound -*/ class JUCE_API SynthesiserVoice { public: - /** Creates a voice. */ - SynthesiserVoice(); + SynthesiserVoice(); - /** Destructor. */ - virtual ~SynthesiserVoice(); + virtual ~SynthesiserVoice(); - /** Returns the midi note that this voice is currently playing. + int getCurrentlyPlayingNote() const { return currentlyPlayingNote; } - Returns a value less than 0 if no note is playing. - */ - int getCurrentlyPlayingNote() const { return currentlyPlayingNote; } + const SynthesiserSound::Ptr getCurrentlyPlayingSound() const { return currentlyPlayingSound; } - /** Returns the sound that this voice is currently playing. + virtual bool canPlaySound (SynthesiserSound* sound) = 0; - Returns 0 if it's not playing. - */ - const SynthesiserSound::Ptr getCurrentlyPlayingSound() const { return currentlyPlayingSound; } + virtual void startNote (const int midiNoteNumber, + const float velocity, + SynthesiserSound* sound, + const int currentPitchWheelPosition) = 0; - /** Must return true if this voice object is capable of playing the given sound. + virtual void stopNote (const bool allowTailOff) = 0; - If there are different classes of sound, and different classes of voice, a voice can - choose which ones it wants to take on. + virtual void pitchWheelMoved (const int newValue) = 0; - A typical implementation of this method may just return true if there's only one type - of voice and sound, or it might check the type of the sound object passed-in and - see if it's one that it understands. - */ - virtual bool canPlaySound (SynthesiserSound* sound) = 0; + virtual void controllerMoved (const int controllerNumber, + const int newValue) = 0; - /** Called to start a new note. + virtual void renderNextBlock (AudioSampleBuffer& outputBuffer, + int startSample, + int numSamples) = 0; - This will be called during the rendering callback, so must be fast and thread-safe. - */ - virtual void startNote (const int midiNoteNumber, - const float velocity, - SynthesiserSound* sound, - const int currentPitchWheelPosition) = 0; + bool isPlayingChannel (const int midiChannel) const; - /** Called to stop a note. + void setCurrentPlaybackSampleRate (const double newRate); - This will be called during the rendering callback, so must be fast and thread-safe. - - If allowTailOff is false or the voice doesn't want to tail-off, then it must stop all - sound immediately, and must call clearCurrentNote() to reset the state of this voice - and allow the synth to reassign it another sound. - - If allowTailOff is true and the voice decides to do a tail-off, then it's allowed to - begin fading out its sound, and it can stop playing until it's finished. As soon as it - finishes playing (during the rendering callback), it must make sure that it calls - clearCurrentNote(). - */ - virtual void stopNote (const bool allowTailOff) = 0; - - /** Called to let the voice know that the pitch wheel has been moved. - - This will be called during the rendering callback, so must be fast and thread-safe. - */ - virtual void pitchWheelMoved (const int newValue) = 0; - - /** Called to let the voice know that a midi controller has been moved. - - This will be called during the rendering callback, so must be fast and thread-safe. - */ - virtual void controllerMoved (const int controllerNumber, - const int newValue) = 0; - - /** Renders the next block of data for this voice. - - The output audio data must be added to the current contents of the buffer provided. - Only the region of the buffer between startSample and (startSample + numSamples) - should be altered by this method. - - If the voice is currently silent, it should just return without doing anything. - - If the sound that the voice is playing finishes during the course of this rendered - block, it must call clearCurrentNote(), to tell the synthesiser that it has finished. - - The size of the blocks that are rendered can change each time it is called, and may - involve rendering as little as 1 sample at a time. In between rendering callbacks, - the voice's methods will be called to tell it about note and controller events. - */ - virtual void renderNextBlock (AudioSampleBuffer& outputBuffer, - int startSample, - int numSamples) = 0; - - /** Returns true if the voice is currently playing a sound which is mapped to the given - midi channel. - - If it's not currently playing, this will return false. - */ - bool isPlayingChannel (const int midiChannel) const; - - /** Changes the voice's reference sample rate. - - The rate is set so that subclasses know the output rate and can set their pitch - accordingly. - - This method is called by the synth, and subclasses can access the current rate with - the currentSampleRate member. - */ - void setCurrentPlaybackSampleRate (const double newRate); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** Returns the current target sample rate at which rendering is being done. + double getSampleRate() const { return currentSampleRate; } - This is available for subclasses so they can pitch things correctly. - */ - double getSampleRate() const { return currentSampleRate; } - - /** Resets the state of this voice after a sound has finished playing. - - The subclass must call this when it finishes playing a note and becomes available - to play new ones. - - It must either call it in the stopNote() method, or if the voice is tailing off, - then it should call it later during the renderNextBlock method, as soon as it - finishes its tail-off. - - It can also be called at any time during the render callback if the sound happens - to have finished, e.g. if it's playing a sample and the sample finishes. - */ - void clearCurrentNote(); + void clearCurrentNote(); private: - friend class Synthesiser; + friend class Synthesiser; - double currentSampleRate; - int currentlyPlayingNote; - uint32 noteOnTime; - SynthesiserSound::Ptr currentlyPlayingSound; + double currentSampleRate; + int currentlyPlayingNote; + uint32 noteOnTime; + SynthesiserSound::Ptr currentlyPlayingSound; }; -/** - Base class for a musical device that can play sounds. - - To create a synthesiser, you'll need to create a subclass of SynthesiserSound - to describe each sound available to your synth, and a subclass of SynthesiserVoice - which can play back one of these sounds. - - Then you can use the addVoice() and addSound() methods to give the synthesiser a - set of sounds, and a set of voices it can use to play them. If you only give it - one voice it will be monophonic - the more voices it has, the more polyphony it'll - have available. - - Then repeatedly call the renderNextBlock() method to produce the audio. Any midi - events that go in will be scanned for note on/off messages, and these are used to - start and stop the voices playing the appropriate sounds. - - While it's playing, you can also cause notes to be triggered by calling the noteOn(), - noteOff() and other controller methods. - - Before rendering, be sure to call the setCurrentPlaybackSampleRate() to tell it - what the target playback rate is. This value is passed on to the voices so that - they can pitch their output correctly. -*/ class JUCE_API Synthesiser { public: - /** Creates a new synthesiser. + Synthesiser(); - You'll need to add some sounds and voices before it'll make any sound.. - */ - Synthesiser(); + virtual ~Synthesiser(); - /** Destructor. */ - virtual ~Synthesiser(); + void clearVoices(); - /** Deletes all voices. */ - void clearVoices(); + int getNumVoices() const { return voices.size(); } - /** Returns the number of voices that have been added. */ - int getNumVoices() const { return voices.size(); } + SynthesiserVoice* getVoice (const int index) const; - /** Returns one of the voices that have been added. */ - SynthesiserVoice* getVoice (const int index) const; + void addVoice (SynthesiserVoice* const newVoice); - /** Adds a new voice to the synth. + void removeVoice (const int index); - All the voices should be the same class of object and are treated equally. + void clearSounds(); - The object passed in will be managed by the synthesiser, which will delete - it later on when no longer needed. The caller should not retain a pointer to the - voice. - */ - void addVoice (SynthesiserVoice* const newVoice); + int getNumSounds() const { return sounds.size(); } - /** Deletes one of the voices. */ - void removeVoice (const int index); + SynthesiserSound* getSound (const int index) const { return sounds [index]; } - /** Deletes all sounds. */ - void clearSounds(); + void addSound (const SynthesiserSound::Ptr& newSound); - /** Returns the number of sounds that have been added to the synth. */ - int getNumSounds() const { return sounds.size(); } + void removeSound (const int index); - /** Returns one of the sounds. */ - SynthesiserSound* getSound (const int index) const { return sounds [index]; } + void setNoteStealingEnabled (const bool shouldStealNotes); - /** Adds a new sound to the synthesiser. + bool isNoteStealingEnabled() const { return shouldStealNotes; } - The object passed in is reference counted, so will be deleted when it is removed - from the synthesiser, and when no voices are still using it. - */ - void addSound (const SynthesiserSound::Ptr& newSound); + virtual void noteOn (const int midiChannel, + const int midiNoteNumber, + const float velocity); - /** Removes and deletes one of the sounds. */ - void removeSound (const int index); + virtual void noteOff (const int midiChannel, + const int midiNoteNumber, + const bool allowTailOff); - /** If set to true, then the synth will try to take over an existing voice if - it runs out and needs to play another note. + virtual void allNotesOff (const int midiChannel, + const bool allowTailOff); - The value of this boolean is passed into findFreeVoice(), so the result will - depend on the implementation of this method. - */ - void setNoteStealingEnabled (const bool shouldStealNotes); + virtual void handlePitchWheel (const int midiChannel, + const int wheelValue); - /** Returns true if note-stealing is enabled. - @see setNoteStealingEnabled - */ - bool isNoteStealingEnabled() const { return shouldStealNotes; } + virtual void handleController (const int midiChannel, + const int controllerNumber, + const int controllerValue); - /** Triggers a note-on event. + void setCurrentPlaybackSampleRate (const double sampleRate); - The default method here will find all the sounds that want to be triggered by - this note/channel. For each sound, it'll try to find a free voice, and use the - voice to start playing the sound. + void renderNextBlock (AudioSampleBuffer& outputAudio, + const MidiBuffer& inputMidi, + int startSample, + int numSamples); - Subclasses might want to override this if they need a more complex algorithm. - - This method will be called automatically according to the midi data passed into - renderNextBlock(), but may be called explicitly too. - */ - virtual void noteOn (const int midiChannel, - const int midiNoteNumber, - const float velocity); - - /** Triggers a note-off event. - - This will turn off any voices that are playing a sound for the given note/channel. - - If allowTailOff is true, the voices will be allowed to fade out the notes gracefully - (if they can do). If this is false, the notes will all be cut off immediately. - - This method will be called automatically according to the midi data passed into - renderNextBlock(), but may be called explicitly too. - */ - virtual void noteOff (const int midiChannel, - const int midiNoteNumber, - const bool allowTailOff); - - /** Turns off all notes. - - This will turn off any voices that are playing a sound on the given midi channel. - - If midiChannel is 0 or less, then all voices will be turned off, regardless of - which channel they're playing. - - If allowTailOff is true, the voices will be allowed to fade out the notes gracefully - (if they can do). If this is false, the notes will all be cut off immediately. - - This method will be called automatically according to the midi data passed into - renderNextBlock(), but may be called explicitly too. - */ - virtual void allNotesOff (const int midiChannel, - const bool allowTailOff); - - /** Sends a pitch-wheel message. - - This will send a pitch-wheel message to any voices that are playing sounds on - the given midi channel. - - This method will be called automatically according to the midi data passed into - renderNextBlock(), but may be called explicitly too. - - @param midiChannel the midi channel for the event - @param wheelValue the wheel position, from 0 to 0x3fff, as returned by MidiMessage::getPitchWheelValue() - */ - virtual void handlePitchWheel (const int midiChannel, - const int wheelValue); - - /** Sends a midi controller message. - - This will send a midi controller message to any voices that are playing sounds on - the given midi channel. - - This method will be called automatically according to the midi data passed into - renderNextBlock(), but may be called explicitly too. - - @param midiChannel the midi channel for the event - @param controllerNumber the midi controller type, as returned by MidiMessage::getControllerNumber() - @param controllerValue the midi controller value, between 0 and 127, as returned by MidiMessage::getControllerValue() - */ - virtual void handleController (const int midiChannel, - const int controllerNumber, - const int controllerValue); - - /** Tells the synthesiser what the sample rate is for the audio it's being used to - render. - - This value is propagated to the voices so that they can use it to render the correct - pitches. - */ - void setCurrentPlaybackSampleRate (const double sampleRate); - - /** Creates the next block of audio output. - - This will process the next numSamples of data from all the voices, and add that output - to the audio block supplied, starting from the offset specified. Note that the - data will be added to the current contents of the buffer, so you should clear it - before calling this method if necessary. - - The midi events in the inputMidi buffer are parsed for note and controller events, - and these are used to trigger the voices. Note that the startSample offset applies - both to the audio output buffer and the midi input buffer, so any midi events - with timestamps outside the specified region will be ignored. - */ - void renderNextBlock (AudioSampleBuffer& outputAudio, - const MidiBuffer& inputMidi, - int startSample, - int numSamples); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** This is used to control access to the rendering callback and the note trigger methods. */ - CriticalSection lock; + CriticalSection lock; - OwnedArray voices; - ReferenceCountedArray sounds; + OwnedArray voices; + ReferenceCountedArray sounds; - /** The last pitch-wheel values for each midi channel. */ - int lastPitchWheelValues [16]; + int lastPitchWheelValues [16]; - /** Searches through the voices to find one that's not currently playing, and which - can play the given sound. + virtual SynthesiserVoice* findFreeVoice (SynthesiserSound* soundToPlay, + const bool stealIfNoneAvailable) const; - Returns 0 if all voices are busy and stealing isn't enabled. + void startVoice (SynthesiserVoice* const voice, + SynthesiserSound* const sound, + const int midiChannel, + const int midiNoteNumber, + const float velocity); - This can be overridden to implement custom voice-stealing algorithms. - */ - virtual SynthesiserVoice* findFreeVoice (SynthesiserSound* soundToPlay, - const bool stealIfNoneAvailable) const; - - /** Starts a specified voice playing a particular sound. - - You'll probably never need to call this, it's used internally by noteOn(), but - may be needed by subclasses for custom behaviours. - */ - void startVoice (SynthesiserVoice* const voice, - SynthesiserSound* const sound, - const int midiChannel, - const int midiNoteNumber, - const float velocity); - - /** xxx Temporary method here to cause a compiler error - note the new parameters for this method. */ - int findFreeVoice (const bool) const { return 0; } + int findFreeVoice (const bool) const { return 0; } private: - double sampleRate; - uint32 lastNoteOnCounter; - bool shouldStealNotes; + double sampleRate; + uint32 lastNoteOnCounter; + bool shouldStealNotes; - Synthesiser (const Synthesiser&); - const Synthesiser& operator= (const Synthesiser&); + Synthesiser (const Synthesiser&); + const Synthesiser& operator= (const Synthesiser&); }; #endif // __JUCE_SYNTHESISER_JUCEHEADER__ /********* End of inlined file: juce_Synthesiser.h *********/ -/** - A subclass of SynthesiserSound that represents a sampled audio clip. - - This is a pretty basic sampler, and just attempts to load the whole audio stream - into memory. - - To use it, create a Synthesiser, add some SamplerVoice objects to it, then - give it some SampledSound objects to play. - - @see SamplerVoice, Synthesiser, SynthesiserSound -*/ -class JUCE_API SamplerSound : public SynthesiserSound +class JUCE_API SamplerSound : public SynthesiserSound { public: - /** Creates a sampled sound from an audio reader. + SamplerSound (const String& name, + AudioFormatReader& source, + const BitArray& midiNotes, + const int midiNoteForNormalPitch, + const double attackTimeSecs, + const double releaseTimeSecs, + const double maxSampleLengthSeconds); - This will attempt to load the audio from the source into memory and store - it in this object. + ~SamplerSound(); - @param name a name for the sample - @param source the audio to load. This object can be safely deleted by the - caller after this constructor returns - @param midiNotes the set of midi keys that this sound should be played on. This - is used by the SynthesiserSound::appliesToNote() method - @param midiNoteForNormalPitch the midi note at which the sample should be played - with its natural rate. All other notes will be pitched - up or down relative to this one - @param attackTimeSecs the attack (fade-in) time, in seconds - @param releaseTimeSecs the decay (fade-out) time, in seconds - @param maxSampleLengthSeconds a maximum length of audio to read from the audio - source, in seconds - */ - SamplerSound (const String& name, - AudioFormatReader& source, - const BitArray& midiNotes, - const int midiNoteForNormalPitch, - const double attackTimeSecs, - const double releaseTimeSecs, - const double maxSampleLengthSeconds); + const String& getName() const { return name; } - /** Destructor. */ - ~SamplerSound(); + AudioSampleBuffer* getAudioData() const { return data; } - /** Returns the sample's name */ - const String& getName() const { return name; } + bool appliesToNote (const int midiNoteNumber); + bool appliesToChannel (const int midiChannel); - /** Returns the audio sample data. - This could be 0 if there was a problem loading it. - */ - AudioSampleBuffer* getAudioData() const { return data; } - - bool appliesToNote (const int midiNoteNumber); - bool appliesToChannel (const int midiChannel); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class SamplerVoice; + friend class SamplerVoice; - String name; - ScopedPointer data; - double sourceSampleRate; - BitArray midiNotes; - int length, attackSamples, releaseSamples; - int midiRootNote; + String name; + ScopedPointer data; + double sourceSampleRate; + BitArray midiNotes; + int length, attackSamples, releaseSamples; + int midiRootNote; }; -/** - A subclass of SynthesiserVoice that can play a SamplerSound. - - To use it, create a Synthesiser, add some SamplerVoice objects to it, then - give it some SampledSound objects to play. - - @see SamplerSound, Synthesiser, SynthesiserVoice -*/ -class JUCE_API SamplerVoice : public SynthesiserVoice +class JUCE_API SamplerVoice : public SynthesiserVoice { public: - /** Creates a SamplerVoice. - */ - SamplerVoice(); + SamplerVoice(); - /** Destructor. */ - ~SamplerVoice(); + ~SamplerVoice(); - bool canPlaySound (SynthesiserSound* sound); + bool canPlaySound (SynthesiserSound* sound); - void startNote (const int midiNoteNumber, - const float velocity, - SynthesiserSound* sound, - const int currentPitchWheelPosition); + void startNote (const int midiNoteNumber, + const float velocity, + SynthesiserSound* sound, + const int currentPitchWheelPosition); - void stopNote (const bool allowTailOff); + void stopNote (const bool allowTailOff); - void pitchWheelMoved (const int newValue); - void controllerMoved (const int controllerNumber, - const int newValue); + void pitchWheelMoved (const int newValue); + void controllerMoved (const int controllerNumber, + const int newValue); - void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples); + void renderNextBlock (AudioSampleBuffer& outputBuffer, int startSample, int numSamples); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - double pitchRatio; - double sourceSamplePosition; - float lgain, rgain, attackReleaseLevel, attackDelta, releaseDelta; - bool isInAttack, isInRelease; + double pitchRatio; + double sourceSamplePosition; + float lgain, rgain, attackReleaseLevel, attackDelta, releaseDelta; + bool isInAttack, isInRelease; }; #endif // __JUCE_SAMPLER_JUCEHEADER__ @@ -39431,110 +18796,59 @@ private: #ifndef __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ #define __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ -/** - A set of ActionListeners. - - Listeners can be added and removed from the list, and messages can be - broadcast to all the listeners. - - @see ActionListener, ActionBroadcaster -*/ class JUCE_API ActionListenerList : public MessageListener { public: - /** Creates an empty list. */ - ActionListenerList() throw(); + ActionListenerList() throw(); - /** Destructor. */ - ~ActionListenerList() throw(); + ~ActionListenerList() throw(); - /** Adds a listener to the list. + void addActionListener (ActionListener* const listener) throw(); - (Trying to add a listener that's already on the list will have no effect). - */ - void addActionListener (ActionListener* const listener) throw(); + void removeActionListener (ActionListener* const listener) throw(); - /** Removes a listener from the list. + void removeAllActionListeners() throw(); - If the listener isn't on the list, this won't have any effect. - */ - void removeActionListener (ActionListener* const listener) throw(); + void sendActionMessage (const String& message) const; - /** Removes all listeners from the list. */ - void removeAllActionListeners() throw(); + void handleMessage (const Message&); - /** Broadcasts a message to all the registered listeners. - - This sends the message asynchronously. - - If a listener is on the list when this method is called but is removed from - the list before the message arrives, it won't receive the message. Similarly - listeners that are added to the list after the message is sent but before it - arrives won't get the message either. - */ - void sendActionMessage (const String& message) const; - - /** @internal */ - void handleMessage (const Message&); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - SortedSet actionListeners_; - CriticalSection actionListenerLock_; + SortedSet actionListeners_; + CriticalSection actionListenerLock_; - ActionListenerList (const ActionListenerList&); - const ActionListenerList& operator= (const ActionListenerList&); + ActionListenerList (const ActionListenerList&); + const ActionListenerList& operator= (const ActionListenerList&); }; #endif // __JUCE_ACTIONLISTENERLIST_JUCEHEADER__ /********* End of inlined file: juce_ActionListenerList.h *********/ -/** Manages a list of ActionListeners, and can send them messages. - - To quickly add methods to your class that can add/remove action - listeners and broadcast to them, you can derive from this. - - @see ActionListenerList, ActionListener -*/ class JUCE_API ActionBroadcaster { public: - /** Creates an ActionBroadcaster. */ - ActionBroadcaster() throw(); + ActionBroadcaster() throw(); - /** Destructor. */ - virtual ~ActionBroadcaster(); + virtual ~ActionBroadcaster(); - /** Adds a listener to the list. + void addActionListener (ActionListener* const listener); - (Trying to add a listener that's already on the list will have no effect). - */ - void addActionListener (ActionListener* const listener); + void removeActionListener (ActionListener* const listener); - /** Removes a listener from the list. + void removeAllActionListeners(); - If the listener isn't on the list, this won't have any effect. - */ - void removeActionListener (ActionListener* const listener); - - /** Removes all listeners from the list. */ - void removeAllActionListeners(); - - /** Broadcasts a message to all the registered listeners. - - @see ActionListenerList::sendActionMessage - */ - void sendActionMessage (const String& message) const; + void sendActionMessage (const String& message) const; private: - ActionListenerList actionListenerList; + ActionListenerList actionListenerList; - ActionBroadcaster (const ActionBroadcaster&); - const ActionBroadcaster& operator= (const ActionBroadcaster&); + ActionBroadcaster (const ActionBroadcaster&); + const ActionBroadcaster& operator= (const ActionBroadcaster&); }; #endif // __JUCE_ACTIONBROADCASTER_JUCEHEADER__ @@ -39556,51 +18870,23 @@ private: #ifndef __JUCE_CALLBACKMESSAGE_JUCEHEADER__ #define __JUCE_CALLBACKMESSAGE_JUCEHEADER__ -/** - A message that calls a custom function when it gets delivered. - - You can use this class to fire off actions that you want to be performed later - on the message thread. - - Unlike other Message objects, these don't get sent to a MessageListener, you - just call the post() method to send them, and when they arrive, your - messageCallback() method will automatically be invoked. - - @see MessageListener, MessageManager, ActionListener, ChangeListener -*/ class JUCE_API CallbackMessage : public Message { public: - CallbackMessage() throw(); + CallbackMessage() throw(); - /** Destructor. */ - ~CallbackMessage() throw(); + ~CallbackMessage() throw(); - /** Called when the message is delivered. + virtual void messageCallback() = 0; - You should implement this method and make it do whatever action you want - to perform. + void post(); - Note that like all other messages, this object will be deleted immediately - after this method has been invoked. - */ - virtual void messageCallback() = 0; - - /** Instead of sending this message to a MessageListener, just call this method - to post it to the event queue. - - After you've called this, this object will belong to the MessageManager, - which will delete it later. So make sure you don't delete the object yourself, - call post() more than once, or call post() on a stack-based obect! - */ - void post(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - CallbackMessage (const CallbackMessage&); - const CallbackMessage& operator= (const CallbackMessage&); + CallbackMessage (const CallbackMessage&); + const CallbackMessage& operator= (const CallbackMessage&); }; #endif // __JUCE_CALLBACKMESSAGE_JUCEHEADER__ @@ -39624,176 +18910,71 @@ private: class InterprocessConnectionServer; -/** - Manages a simple two-way messaging connection to another process, using either - a socket or a named pipe as the transport medium. - - To connect to a waiting socket or an open pipe, use the connectToSocket() or - connectToPipe() methods. If this succeeds, messages can be sent to the other end, - and incoming messages will result in a callback via the messageReceived() - method. - - To open a pipe and wait for another client to connect to it, use the createPipe() - method. - - To act as a socket server and create connections for one or more client, see the - InterprocessConnectionServer class. - - @see InterprocessConnectionServer, Socket, NamedPipe -*/ -class JUCE_API InterprocessConnection : public Thread, - private MessageListener +class JUCE_API InterprocessConnection : public Thread, + private MessageListener { public: - /** Creates a connection. + InterprocessConnection (const bool callbacksOnMessageThread = true, + const uint32 magicMessageHeaderNumber = 0xf2b49e2c); - Connections are created manually, connecting them with the connectToSocket() - or connectToPipe() methods, or they are created automatically by a InterprocessConnectionServer - when a client wants to connect. + ~InterprocessConnection(); - @param callbacksOnMessageThread if true, callbacks to the connectionMade(), - connectionLost() and messageReceived() methods will - always be made using the message thread; if false, - these will be called immediately on the connection's - own thread. - @param magicMessageHeaderNumber a magic number to use in the header to check the - validity of the data blocks being sent and received. This - can be any number, but the sender and receiver must obviously - use matching values or they won't recognise each other. - */ - InterprocessConnection (const bool callbacksOnMessageThread = true, - const uint32 magicMessageHeaderNumber = 0xf2b49e2c); + bool connectToSocket (const String& hostName, + const int portNumber, + const int timeOutMillisecs); - /** Destructor. */ - ~InterprocessConnection(); + bool connectToPipe (const String& pipeName, + const int pipeReceiveMessageTimeoutMs = -1); - /** Tries to connect this object to a socket. + bool createPipe (const String& pipeName, + const int pipeReceiveMessageTimeoutMs = -1); - For this to work, the machine on the other end needs to have a InterprocessConnectionServer - object waiting to receive client connections on this port number. + void disconnect(); - @param hostName the host computer, either a network address or name - @param portNumber the socket port number to try to connect to - @param timeOutMillisecs how long to keep trying before giving up - @returns true if the connection is established successfully - @see Socket - */ - bool connectToSocket (const String& hostName, - const int portNumber, - const int timeOutMillisecs); + bool isConnected() const; - /** Tries to connect the object to an existing named pipe. + StreamingSocket* getSocket() const throw() { return socket; } - For this to work, another process on the same computer must already have opened - an InterprocessConnection object and used createPipe() to create a pipe for this - to connect to. + NamedPipe* getPipe() const throw() { return pipe; } - You can optionally specify a timeout length to be passed to the NamedPipe::read() method. + const String getConnectedHostName() const; - @returns true if it connects successfully. - @see createPipe, NamedPipe - */ - bool connectToPipe (const String& pipeName, - const int pipeReceiveMessageTimeoutMs = -1); + bool sendMessage (const MemoryBlock& message); - /** Tries to create a new pipe for other processes to connect to. + virtual void connectionMade() = 0; - This creates a pipe with the given name, so that other processes can use - connectToPipe() to connect to the other end. + virtual void connectionLost() = 0; - You can optionally specify a timeout length to be passed to the NamedPipe::read() method. + virtual void messageReceived (const MemoryBlock& message) = 0; - If another process is already using this pipe, this will fail and return false. - */ - bool createPipe (const String& pipeName, - const int pipeReceiveMessageTimeoutMs = -1); - - /** Disconnects and closes any currently-open sockets or pipes. */ - void disconnect(); - - /** True if a socket or pipe is currently active. */ - bool isConnected() const; - - /** Returns the socket that this connection is using (or null if it uses a pipe). */ - StreamingSocket* getSocket() const throw() { return socket; } - - /** Returns the pipe that this connection is using (or null if it uses a socket). */ - NamedPipe* getPipe() const throw() { return pipe; } - - /** Returns the name of the machine at the other end of this connection. - - This will return an empty string if the other machine isn't known for - some reason. - */ - const String getConnectedHostName() const; - - /** Tries to send a message to the other end of this connection. - - This will fail if it's not connected, or if there's some kind of write error. If - it succeeds, the connection object at the other end will receive the message by - a callback to its messageReceived() method. - - @see messageReceived - */ - bool sendMessage (const MemoryBlock& message); - - /** Called when the connection is first connected. - - If the connection was created with the callbacksOnMessageThread flag set, then - this will be called on the message thread; otherwise it will be called on a server - thread. - */ - virtual void connectionMade() = 0; - - /** Called when the connection is broken. - - If the connection was created with the callbacksOnMessageThread flag set, then - this will be called on the message thread; otherwise it will be called on a server - thread. - */ - virtual void connectionLost() = 0; - - /** Called when a message arrives. - - When the object at the other end of this connection sends us a message with sendMessage(), - this callback is used to deliver it to us. - - If the connection was created with the callbacksOnMessageThread flag set, then - this will be called on the message thread; otherwise it will be called on a server - thread. - - @see sendMessage - */ - virtual void messageReceived (const MemoryBlock& message) = 0; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - CriticalSection pipeAndSocketLock; - ScopedPointer socket; - ScopedPointer pipe; - bool callbackConnectionState; - const bool useMessageThread; - const uint32 magicMessageHeader; - int pipeReceiveMessageTimeout; + CriticalSection pipeAndSocketLock; + ScopedPointer socket; + ScopedPointer pipe; + bool callbackConnectionState; + const bool useMessageThread; + const uint32 magicMessageHeader; + int pipeReceiveMessageTimeout; - friend class InterprocessConnectionServer; + friend class InterprocessConnectionServer; - void initialiseWithSocket (StreamingSocket* const socket_); - void initialiseWithPipe (NamedPipe* const pipe_); + void initialiseWithSocket (StreamingSocket* const socket_); + void initialiseWithPipe (NamedPipe* const pipe_); - void handleMessage (const Message& message); + void handleMessage (const Message& message); - void connectionMadeInt(); - void connectionLostInt(); - void deliverDataInt (const MemoryBlock& data); + void connectionMadeInt(); + void connectionLostInt(); + void deliverDataInt (const MemoryBlock& data); - bool readNextMessageInt(); - void run(); + bool readNextMessageInt(); + void run(); - InterprocessConnection (const InterprocessConnection&); - const InterprocessConnection& operator= (const InterprocessConnection&); + InterprocessConnection (const InterprocessConnection&); + const InterprocessConnection& operator= (const InterprocessConnection&); }; #endif // __JUCE_INTERPROCESSCONNECTION_JUCEHEADER__ @@ -39806,68 +18987,32 @@ private: #ifndef __JUCE_INTERPROCESSCONNECTIONSERVER_JUCEHEADER__ #define __JUCE_INTERPROCESSCONNECTIONSERVER_JUCEHEADER__ -/** - An object that waits for client sockets to connect to a port on this host, and - creates InterprocessConnection objects for each one. - - To use this, create a class derived from it which implements the createConnectionObject() - method, so that it creates suitable connection objects for each client that tries - to connect. - - @see InterprocessConnection -*/ -class JUCE_API InterprocessConnectionServer : private Thread +class JUCE_API InterprocessConnectionServer : private Thread { public: - /** Creates an uninitialised server object. - */ - InterprocessConnectionServer(); + InterprocessConnectionServer(); - /** Destructor. */ - ~InterprocessConnectionServer(); + ~InterprocessConnectionServer(); - /** Starts an internal thread which listens on the given port number. + bool beginWaitingForSocket (const int portNumber); - While this is running, in another process tries to connect with the - InterprocessConnection::connectToSocket() method, this object will call - createConnectionObject() to create a connection to that client. - - Use stop() to stop the thread running. - - @see createConnectionObject, stop - */ - bool beginWaitingForSocket (const int portNumber); - - /** Terminates the listener thread, if it's active. - - @see beginWaitingForSocket - */ - void stop(); + void stop(); protected: - /** Creates a suitable connection object for a client process that wants to - connect to this one. - - This will be called by the listener thread when a client process tries - to connect, and must return a new InterprocessConnection object that will - then run as this end of the connection. - - @see InterprocessConnection - */ - virtual InterprocessConnection* createConnectionObject() = 0; + virtual InterprocessConnection* createConnectionObject() = 0; public: - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ScopedPointer socket; + ScopedPointer socket; - void run(); + void run(); - InterprocessConnectionServer (const InterprocessConnectionServer&); - const InterprocessConnectionServer& operator= (const InterprocessConnectionServer&); + InterprocessConnectionServer (const InterprocessConnectionServer&); + const InterprocessConnectionServer& operator= (const InterprocessConnectionServer&); }; #endif // __JUCE_INTERPROCESSCONNECTIONSERVER_JUCEHEADER__ @@ -39889,265 +19034,98 @@ private: class Component; class MessageManagerLock; -/** See MessageManager::callFunctionOnMessageThread() for use of this function type -*/ typedef void* (MessageCallbackFunction) (void* userData); -/** Delivers Message objects to MessageListeners, and handles the event-dispatch loop. - - @see Message, MessageListener, MessageManagerLock, JUCEApplication -*/ class JUCE_API MessageManager { public: - /** Returns the global instance of the MessageManager. */ - static MessageManager* getInstance() throw(); + static MessageManager* getInstance() throw(); - /** Runs the event dispatch loop until a stop message is posted. + void runDispatchLoop(); - This method is only intended to be run by the application's startup routine, - as it blocks, and will only return after the stopDispatchLoop() method has been used. + void stopDispatchLoop(); - @see stopDispatchLoop - */ - void runDispatchLoop(); + bool hasStopMessageBeenSent() const throw() { return quitMessagePosted; } - /** Sends a signal that the dispatch loop should terminate. + bool runDispatchLoopUntil (int millisecondsToRunFor); - After this is called, the runDispatchLoop() or runDispatchLoopUntil() methods - will be interrupted and will return. + void* callFunctionOnMessageThread (MessageCallbackFunction* callback, + void* userData); - @see runDispatchLoop - */ - void stopDispatchLoop(); + bool isThisTheMessageThread() const throw(); - /** Returns true if the stopDispatchLoop() method has been called. - */ - bool hasStopMessageBeenSent() const throw() { return quitMessagePosted; } + void setCurrentMessageThread (const Thread::ThreadID threadId) throw(); - /** Synchronously dispatches messages until a given time has elapsed. + Thread::ThreadID getCurrentMessageThread() const throw() { return messageThreadId; } - Returns false if a quit message has been posted by a call to stopDispatchLoop(), - otherwise returns true. - */ - bool runDispatchLoopUntil (int millisecondsToRunFor); + bool currentThreadHasLockedMessageManager() const throw(); - /** Calls a function using the message-thread. + static void broadcastMessage (const String& messageText) throw(); - This can be used by any thread to cause this function to be called-back - by the message thread. If it's the message-thread that's calling this method, - then the function will just be called; if another thread is calling, a message - will be posted to the queue, and this method will block until that message - is delivered, the function is called, and the result is returned. + void registerBroadcastListener (ActionListener* listener) throw(); - Be careful not to cause any deadlocks with this! It's easy to do - e.g. if the caller - thread has a critical section locked, which an unrelated message callback then tries to lock - before the message thread gets round to processing this callback. + void deregisterBroadcastListener (ActionListener* listener) throw(); - @param callback the function to call - its signature must be @code - void* myCallbackFunction (void*) @endcode - @param userData a user-defined pointer that will be passed to the function that gets called - @returns the value that the callback function returns. - @see MessageManagerLock - */ - void* callFunctionOnMessageThread (MessageCallbackFunction* callback, - void* userData); + void deliverMessage (void*); + void deliverBroadcastMessage (const String&); + ~MessageManager() throw(); - /** Returns true if the caller-thread is the message thread. */ - bool isThisTheMessageThread() const throw(); - - /** Called to tell the manager which thread is the one that's running the dispatch loop. - - (Best to ignore this method unless you really know what you're doing..) - @see getCurrentMessageThread - */ - void setCurrentMessageThread (const Thread::ThreadID threadId) throw(); - - /** Returns the ID of the current message thread, as set by setCurrentMessageThread(). - - (Best to ignore this method unless you really know what you're doing..) - @see setCurrentMessageThread - */ - Thread::ThreadID getCurrentMessageThread() const throw() { return messageThreadId; } - - /** Returns true if the caller thread has currenltly got the message manager locked. - - see the MessageManagerLock class for more info about this. - - This will be true if the caller is the message thread, because that automatically - gains a lock while a message is being dispatched. - */ - bool currentThreadHasLockedMessageManager() const throw(); - - /** Sends a message to all other JUCE applications that are running. - - @param messageText the string that will be passed to the actionListenerCallback() - method of the broadcast listeners in the other app. - @see registerBroadcastListener, ActionListener - */ - static void broadcastMessage (const String& messageText) throw(); - - /** Registers a listener to get told about broadcast messages. - - The actionListenerCallback() callback's string parameter - is the message passed into broadcastMessage(). - - @see broadcastMessage - */ - void registerBroadcastListener (ActionListener* listener) throw(); - - /** Deregisters a broadcast listener. */ - void deregisterBroadcastListener (ActionListener* listener) throw(); - - /** @internal */ - void deliverMessage (void*); - /** @internal */ - void deliverBroadcastMessage (const String&); - /** @internal */ - ~MessageManager() throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - MessageManager() throw(); + MessageManager() throw(); - friend class MessageListener; - friend class ChangeBroadcaster; - friend class ActionBroadcaster; - friend class CallbackMessage; - static MessageManager* instance; + friend class MessageListener; + friend class ChangeBroadcaster; + friend class ActionBroadcaster; + friend class CallbackMessage; + static MessageManager* instance; - SortedSet messageListeners; - ScopedPointer broadcastListeners; + SortedSet messageListeners; + ScopedPointer broadcastListeners; - friend class JUCEApplication; - bool quitMessagePosted, quitMessageReceived; - Thread::ThreadID messageThreadId; + friend class JUCEApplication; + bool quitMessagePosted, quitMessageReceived; + Thread::ThreadID messageThreadId; - VoidArray modalComponents; - static void* exitModalLoopCallback (void*); + VoidArray modalComponents; + static void* exitModalLoopCallback (void*); - void postMessageToQueue (Message* const message); - void postCallbackMessage (Message* const message); + void postMessageToQueue (Message* const message); + void postCallbackMessage (Message* const message); - static void doPlatformSpecificInitialisation(); - static void doPlatformSpecificShutdown(); + static void doPlatformSpecificInitialisation(); + static void doPlatformSpecificShutdown(); - friend class MessageManagerLock; - Thread::ThreadID volatile threadWithLock; - CriticalSection lockingLock; + friend class MessageManagerLock; + Thread::ThreadID volatile threadWithLock; + CriticalSection lockingLock; - MessageManager (const MessageManager&); - const MessageManager& operator= (const MessageManager&); + MessageManager (const MessageManager&); + const MessageManager& operator= (const MessageManager&); }; -/** Used to make sure that the calling thread has exclusive access to the message loop. - - Because it's not thread-safe to call any of the Component or other UI classes - from threads other than the message thread, one of these objects can be used to - lock the message loop and allow this to be done. The message thread will be - suspended for the lifetime of the MessageManagerLock object, so create one on - the stack like this: @code - void MyThread::run() - { - someData = 1234; - - const MessageManagerLock mmLock; - // the event loop will now be locked so it's safe to make a few calls.. - - myComponent->setBounds (newBounds); - myComponent->repaint(); - - // ..the event loop will now be unlocked as the MessageManagerLock goes out of scope - } - @endcode - - Obviously be careful not to create one of these and leave it lying around, or - your app will grind to a halt! - - Another caveat is that using this in conjunction with other CriticalSections - can create lots of interesting ways of producing a deadlock! In particular, if - your message thread calls stopThread() for a thread that uses these locks, - you'll get an (occasional) deadlock.. - - @see MessageManager, MessageManager::currentThreadHasLockedMessageManager -*/ class JUCE_API MessageManagerLock { public: - /** Tries to acquire a lock on the message manager. + MessageManagerLock (Thread* const threadToCheckForExitSignal = 0) throw(); - The constructor attempts to gain a lock on the message loop, and the lock will be - kept for the lifetime of this object. + MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal) throw(); - Optionally, you can pass a thread object here, and while waiting to obtain the lock, - this method will keep checking whether the thread has been given the - Thread::signalThreadShouldExit() signal. If this happens, then it will return - without gaining the lock. If you pass a thread, you must check whether the lock was - successful by calling lockWasGained(). If this is false, your thread is being told to - die, so you should take evasive action. + ~MessageManagerLock() throw(); - If you pass zero for the thread object, it will wait indefinitely for the lock - be - careful when doing this, because it's very easy to deadlock if your message thread - attempts to call stopThread() on a thread just as that thread attempts to get the - message lock. - - If the calling thread already has the lock, nothing will be done, so it's safe and - quick to use these locks recursively. - - E.g. - @code - void run() - { - ... - - while (! threadShouldExit()) - { - MessageManagerLock mml (Thread::getCurrentThread()); - - if (! mml.lockWasGained()) - return; // another thread is trying to kill us! - - ..do some locked stuff here.. - } - - ..and now the MM is now unlocked.. - } - @endcode - - */ - MessageManagerLock (Thread* const threadToCheckForExitSignal = 0) throw(); - - /** This has the same behaviour as the other constructor, but takes a ThreadPoolJob - instead of a thread. - - See the MessageManagerLock (Thread*) constructor for details on how this works. - */ - MessageManagerLock (ThreadPoolJob* const jobToCheckForExitSignal) throw(); - - /** Releases the current thread's lock on the message manager. - - Make sure this object is created and deleted by the same thread, - otherwise there are no guarantees what will happen! - */ - ~MessageManagerLock() throw(); - - /** Returns true if the lock was successfully acquired. - - (See the constructor that takes a Thread for more info). - */ - bool lockWasGained() const throw() { return locked; } + bool lockWasGained() const throw() { return locked; } private: - bool locked, needsUnlocking; - void* sharedEvents; + bool locked, needsUnlocking; + void* sharedEvents; - void init (Thread* const thread, ThreadPoolJob* const job) throw(); + void init (Thread* const thread, ThreadPoolJob* const job) throw(); - MessageManagerLock (const MessageManagerLock&); - const MessageManagerLock& operator= (const MessageManagerLock&); + MessageManagerLock (const MessageManagerLock&); + const MessageManagerLock& operator= (const MessageManagerLock&); }; #endif // __JUCE_MESSAGEMANAGER_JUCEHEADER__ @@ -40160,97 +19138,34 @@ private: #ifndef __JUCE_MULTITIMER_JUCEHEADER__ #define __JUCE_MULTITIMER_JUCEHEADER__ -/** - A type of timer class that can run multiple timers with different frequencies, - all of which share a single callback. - - This class is very similar to the Timer class, but allows you run multiple - separate timers, where each one has a unique ID number. The methods in this - class are exactly equivalent to those in Timer, but with the addition of - this ID number. - - To use it, you need to create a subclass of MultiTimer, implementing the - timerCallback() method. Then you can start timers with startTimer(), and - each time the callback is triggered, it passes in the ID of the timer that - caused it. - - @see Timer -*/ class JUCE_API MultiTimer { protected: - /** Creates a MultiTimer. + MultiTimer() throw(); - When created, no timers are running, so use startTimer() to start things off. - */ - MultiTimer() throw(); - - /** Creates a copy of another timer. - - Note that this timer will not contain any running timers, even if the one you're - copying from was running. - */ - MultiTimer (const MultiTimer& other) throw(); + MultiTimer (const MultiTimer& other) throw(); public: - /** Destructor. */ - virtual ~MultiTimer(); + virtual ~MultiTimer(); - /** The user-defined callback routine that actually gets called by each of the - timers that are running. + virtual void timerCallback (const int timerId) = 0; - It's perfectly ok to call startTimer() or stopTimer() from within this - callback to change the subsequent intervals. - */ - virtual void timerCallback (const int timerId) = 0; + void startTimer (const int timerId, const int intervalInMilliseconds) throw(); - /** Starts a timer and sets the length of interval required. + void stopTimer (const int timerId) throw(); - If the timer is already started, this will reset it, so the - time between calling this method and the next timer callback - will not be less than the interval length passed in. + bool isTimerRunning (const int timerId) const throw(); - @param timerId a unique Id number that identifies the timer to - start. This is the id that will be passed back - to the timerCallback() method when this timer is - triggered - @param intervalInMilliseconds the interval to use (any values less than 1 will be - rounded up to 1) - */ - void startTimer (const int timerId, const int intervalInMilliseconds) throw(); - - /** Stops a timer. - - If a timer has been started with the given ID number, it will be cancelled. - No more callbacks will be made for the specified timer after this method returns. - - If this is called from a different thread, any callbacks that may - be currently executing may be allowed to finish before the method - returns. - */ - void stopTimer (const int timerId) throw(); - - /** Checks whether a timer has been started for a specified ID. - - @returns true if a timer with the given ID is running. - */ - bool isTimerRunning (const int timerId) const throw(); - - /** Returns the interval for a specified timer ID. - - @returns the timer's interval in milliseconds if it's running, or 0 if it's no timer - is running for the ID number specified. - */ - int getTimerInterval (const int timerId) const throw(); + int getTimerInterval (const int timerId) const throw(); private: - class MultiTimerCallback; - CriticalSection timerListLock; - OwnedArray timers; + class MultiTimerCallback; + CriticalSection timerListLock; + OwnedArray timers; - const MultiTimer& operator= (const MultiTimer&); + const MultiTimer& operator= (const MultiTimer&); }; #endif // __JUCE_MULTITIMER_JUCEHEADER__ @@ -40270,105 +19185,59 @@ private: #ifndef __JUCE_DROPSHADOWEFFECT_JUCEHEADER__ #define __JUCE_DROPSHADOWEFFECT_JUCEHEADER__ -/** - An effect filter that adds a drop-shadow behind the image's content. - - (This will only work on images/components that aren't opaque, of course). - - When added to a component, this effect will draw a soft-edged - shadow based on what gets drawn inside it. The shadow will also - be applied to the component's children. - - For speed, this doesn't use a proper gaussian blur, but cheats by - using a simple bilinear filter. If you need a really high-quality - shadow, check out ImageConvolutionKernel::createGaussianBlur() - - @see Component::setComponentEffect -*/ class JUCE_API DropShadowEffect : public ImageEffectFilter { public: - /** Creates a default drop-shadow effect. + DropShadowEffect(); - To customise the shadow's appearance, use the setShadowProperties() - method. - */ - DropShadowEffect(); + ~DropShadowEffect(); - /** Destructor. */ - ~DropShadowEffect(); + void setShadowProperties (const float newRadius, + const float newOpacity, + const int newShadowOffsetX, + const int newShadowOffsetY); - /** Sets up parameters affecting the shadow's appearance. + void applyEffect (Image& sourceImage, Graphics& destContext); - @param newRadius the (approximate) radius of the blur used - @param newOpacity the opacity with which the shadow is rendered - @param newShadowOffsetX allows the shadow to be shifted in relation to the - component's contents - @param newShadowOffsetY allows the shadow to be shifted in relation to the - component's contents - */ - void setShadowProperties (const float newRadius, - const float newOpacity, - const int newShadowOffsetX, - const int newShadowOffsetY); - - /** @internal */ - void applyEffect (Image& sourceImage, Graphics& destContext); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - int offsetX, offsetY; - float radius, opacity; + int offsetX, offsetY; + float radius, opacity; }; #endif // __JUCE_DROPSHADOWEFFECT_JUCEHEADER__ /********* End of inlined file: juce_DropShadowEffect.h *********/ -/** - A button with an arrow in it. - - @see Button -*/ class JUCE_API ArrowButton : public Button { public: - /** Creates an ArrowButton. + ArrowButton (const String& buttonName, + float arrowDirection, + const Colour& arrowColour); - @param buttonName the name to give the button - @param arrowDirection the direction the arrow should point in, where 0.0 is - pointing right, 0.25 is down, 0.5 is left, 0.75 is up - @param arrowColour the colour to use for the arrow - */ - ArrowButton (const String& buttonName, - float arrowDirection, - const Colour& arrowColour); + ~ArrowButton(); - /** Destructor. */ - ~ArrowButton(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown); + void paintButton (Graphics& g, + bool isMouseOverButton, + bool isButtonDown); - /** @internal */ - void buttonStateChanged(); + void buttonStateChanged(); private: - Colour colour; - DropShadowEffect shadow; - Path path; - int offset; + Colour colour; + DropShadowEffect shadow; + Path path; + int offset; - ArrowButton (const ArrowButton&); - const ArrowButton& operator= (const ArrowButton&); + ArrowButton (const ArrowButton&); + const ArrowButton& operator= (const ArrowButton&); }; #endif // __JUCE_ARROWBUTTON_JUCEHEADER__ @@ -40388,305 +19257,139 @@ private: #ifndef __JUCE_DRAWABLE_JUCEHEADER__ #define __JUCE_DRAWABLE_JUCEHEADER__ -/** - The base class for objects which can draw themselves, e.g. polygons, images, etc. - - @see DrawableComposite, DrawableImage, DrawablePath, DrawableText -*/ class JUCE_API Drawable { protected: - /** The base class can't be instantiated directly. - - @see DrawableComposite, DrawableImage, DrawablePath, DrawableText - */ - Drawable(); + Drawable(); public: - /** Destructor. */ - virtual ~Drawable(); + virtual ~Drawable(); - /** Creates a deep copy of this Drawable object. + virtual Drawable* createCopy() const = 0; - Use this to create a new copy of this and any sub-objects in the tree. - */ - virtual Drawable* createCopy() const = 0; + void draw (Graphics& g, const float opacity, + const AffineTransform& transform = AffineTransform::identity) const; - /** Renders this Drawable object. - @see drawWithin - */ - void draw (Graphics& g, const float opacity, - const AffineTransform& transform = AffineTransform::identity) const; + void drawAt (Graphics& g, + const float x, + const float y, + const float opacity) const; - /** Renders the Drawable at a given offset within the Graphics context. + void drawWithin (Graphics& g, + const int destX, + const int destY, + const int destWidth, + const int destHeight, + const RectanglePlacement& placement, + const float opacity) const; - The co-ordinates passed-in are used to translate the object relative to its own - origin before drawing it - this is basically a quick way of saying: + class RenderingContext + { + public: + RenderingContext (Graphics& g, const AffineTransform& transform, const float opacity) throw(); - @code - draw (g, AffineTransform::translation (x, y)). - @endcode - */ - void drawAt (Graphics& g, - const float x, - const float y, - const float opacity) const; + Graphics& g; + AffineTransform transform; + float opacity; - /** Renders the Drawable within a rectangle, scaling it to fit neatly inside without - changing its aspect-ratio. + private: + const RenderingContext& operator= (const RenderingContext&); + }; - The object can placed arbitrarily within the rectangle based on a Justification type, - and can either be made as big as possible, or just reduced to fit. + virtual void render (const RenderingContext& context) const = 0; - @param g the graphics context to render onto - @param destX top-left of the target rectangle to fit it into - @param destY top-left of the target rectangle to fit it into - @param destWidth size of the target rectangle to fit the image into - @param destHeight size of the target rectangle to fit the image into - @param placement defines the alignment and rescaling to use to fit - this object within the target rectangle. - @param opacity the opacity to use, in the range 0 to 1.0 - */ - void drawWithin (Graphics& g, - const int destX, - const int destY, - const int destWidth, - const int destHeight, - const RectanglePlacement& placement, - const float opacity) const; + virtual void getBounds (float& x, float& y, float& width, float& height) const = 0; - /** Holds the information needed when telling a drawable to render itself. - @see Drawable::draw - */ - class RenderingContext - { - public: - RenderingContext (Graphics& g, const AffineTransform& transform, const float opacity) throw(); + virtual bool hitTest (float x, float y) const = 0; - Graphics& g; - AffineTransform transform; - float opacity; + const String& getName() const throw() { return name; } - private: - const RenderingContext& operator= (const RenderingContext&); - }; + void setName (const String& newName) throw() { name = newName; } - /** Renders this Drawable object. - @see draw - */ - virtual void render (const RenderingContext& context) const = 0; + static Drawable* createFromImageData (const void* data, const size_t numBytes); - /** Returns the smallest rectangle that can contain this Drawable object. + static Drawable* createFromImageDataStream (InputStream& dataSource); - Co-ordinates are relative to the object's own origin. - */ - virtual void getBounds (float& x, float& y, float& width, float& height) const = 0; + static Drawable* createFromImageFile (const File& file); - /** Returns true if the given point is somewhere inside this Drawable. + static Drawable* createFromSVG (const XmlElement& svgDocument); - Co-ordinates are relative to the object's own origin. - */ - virtual bool hitTest (float x, float y) const = 0; + static Drawable* createFromValueTree (const ValueTree& tree) throw(); - /** Returns the name given to this drawable. - @see setName - */ - const String& getName() const throw() { return name; } + virtual ValueTree createValueTree() const throw() = 0; - /** Assigns a name to this drawable. */ - void setName (const String& newName) throw() { name = newName; } - - /** Tries to turn some kind of image file into a drawable. - - The data could be an image that the ImageFileFormat class understands, or it - could be SVG. - */ - static Drawable* createFromImageData (const void* data, const int numBytes); - - /** Tries to turn a stream containing some kind of image data into a drawable. - - The data could be an image that the ImageFileFormat class understands, or it - could be SVG. - */ - static Drawable* createFromImageDataStream (InputStream& dataSource); - - /** Tries to turn a file containing some kind of image data into a drawable. - - The data could be an image that the ImageFileFormat class understands, or it - could be SVG. - */ - static Drawable* createFromImageFile (const File& file); - - /** Attempts to parse an SVG (Scalable Vector Graphics) document, and to turn this - into a Drawable tree. - - The object returned must be deleted by the caller. If something goes wrong - while parsing, it may return 0. - - SVG is a pretty large and complex spec, and this doesn't aim to be a full - implementation, but it can return the basic vector objects. - */ - static Drawable* createFromSVG (const XmlElement& svgDocument); - - /** Tries to create a Drawable from a previously-saved ValueTree. - The ValueTree must have been created by the createValueTree() method. - */ - static Drawable* createFromValueTree (const ValueTree& tree) throw(); - - /** Creates a ValueTree to represent this Drawable. - The VarTree that is returned can be turned back into a Drawable with - createFromValueTree(). - */ - virtual ValueTree createValueTree() const throw() = 0; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - Drawable (const Drawable&); - const Drawable& operator= (const Drawable&); + Drawable (const Drawable&); + const Drawable& operator= (const Drawable&); - String name; + String name; }; #endif // __JUCE_DRAWABLE_JUCEHEADER__ /********* End of inlined file: juce_Drawable.h *********/ -/** - A button that displays a Drawable. - - Up to three Drawable objects can be given to this button, to represent the - 'normal', 'over' and 'down' states. - - @see Button -*/ class JUCE_API DrawableButton : public Button { public: - enum ButtonStyle - { - ImageFitted, /**< The button will just display the images, but will resize and centre them to fit inside it. */ - ImageRaw, /**< The button will just display the images in their normal size and position. - This leaves it up to the caller to make sure the images are the correct size and position for the button. */ - ImageAboveTextLabel, /**< Draws the button as a text label across the bottom with the image resized and scaled to fit above it. */ - ImageOnButtonBackground /**< Draws the button as a standard rounded-rectangle button with the image on top. */ - }; + enum ButtonStyle + { + ImageFitted, /**< The button will just display the images, but will resize and centre them to fit inside it. */ + ImageRaw, /**< The button will just display the images in their normal size and position. + This leaves it up to the caller to make sure the images are the correct size and position for the button. */ + ImageAboveTextLabel, /**< Draws the button as a text label across the bottom with the image resized and scaled to fit above it. */ + ImageOnButtonBackground /**< Draws the button as a standard rounded-rectangle button with the image on top. */ + }; - /** Creates a DrawableButton. + DrawableButton (const String& buttonName, + const ButtonStyle buttonStyle); - After creating one of these, use setImages() to specify the drawables to use. + ~DrawableButton(); - @param buttonName the name to give the component - @param buttonStyle the layout to use + void setImages (const Drawable* normalImage, + const Drawable* overImage = 0, + const Drawable* downImage = 0, + const Drawable* disabledImage = 0, + const Drawable* normalImageOn = 0, + const Drawable* overImageOn = 0, + const Drawable* downImageOn = 0, + const Drawable* disabledImageOn = 0); - @see ButtonStyle, setButtonStyle, setImages - */ - DrawableButton (const String& buttonName, - const ButtonStyle buttonStyle); + void setButtonStyle (const ButtonStyle newStyle); - /** Destructor. */ - ~DrawableButton(); + void setBackgroundColours (const Colour& toggledOffColour, + const Colour& toggledOnColour); - /** Sets up the images to draw for the various button states. + const Colour& getBackgroundColour() const throw(); - The button will keep its own internal copies of these drawables. + void setEdgeIndent (const int numPixelsIndent); - @param normalImage the thing to draw for the button's 'normal' state. An internal copy - will be made of the object passed-in if it is non-zero. - @param overImage the thing to draw for the button's 'over' state - if this is - zero, the button's normal image will be used when the mouse is - over it. An internal copy will be made of the object passed-in - if it is non-zero. - @param downImage the thing to draw for the button's 'down' state - if this is - zero, the 'over' image will be used instead (or the normal image - as a last resort). An internal copy will be made of the object - passed-in if it is non-zero. - @param disabledImage an image to draw when the button is disabled. If this is zero, - the normal image will be drawn with a reduced opacity instead. - An internal copy will be made of the object passed-in if it is - non-zero. - @param normalImageOn same as the normalImage, but this is used when the button's toggle - state is 'on'. If this is 0, the normal image is used instead - @param overImageOn same as the overImage, but this is used when the button's toggle - state is 'on'. If this is 0, the normalImageOn is drawn instead - @param downImageOn same as the downImage, but this is used when the button's toggle - state is 'on'. If this is 0, the overImageOn is drawn instead - @param disabledImageOn same as the disabledImage, but this is used when the button's toggle - state is 'on'. If this is 0, the normal image will be drawn instead - with a reduced opacity - */ - void setImages (const Drawable* normalImage, - const Drawable* overImage = 0, - const Drawable* downImage = 0, - const Drawable* disabledImage = 0, - const Drawable* normalImageOn = 0, - const Drawable* overImageOn = 0, - const Drawable* downImageOn = 0, - const Drawable* disabledImageOn = 0); + const Drawable* getCurrentImage() const throw(); + const Drawable* getNormalImage() const throw(); + const Drawable* getOverImage() const throw(); + const Drawable* getDownImage() const throw(); - /** Changes the button's style. - - @see ButtonStyle - */ - void setButtonStyle (const ButtonStyle newStyle); - - /** Changes the button's background colours. - - The toggledOffColour is the colour to use when the button's toggle state - is off, and toggledOnColour when it's on. - - For an ImageOnly or ImageAboveTextLabel style, the background colour is - used to fill the background of the component. - - For an ImageOnButtonBackground style, the colour is used to draw the - button's lozenge shape and exactly how the colour's used will depend - on the LookAndFeel. - */ - void setBackgroundColours (const Colour& toggledOffColour, - const Colour& toggledOnColour); - - /** Returns the current background colour being used. - - @see setBackgroundColour - */ - const Colour& getBackgroundColour() const throw(); - - /** Gives the button an optional amount of space around the edge of the drawable. - - This will only apply to ImageFitted or ImageRaw styles, it won't affect the - ones on a button background. If the button is too small for the given gap, a - smaller gap will be used. - - By default there's a gap of about 3 pixels. - */ - void setEdgeIndent (const int numPixelsIndent); - - /** Returns the image that the button is currently displaying. */ - const Drawable* getCurrentImage() const throw(); - const Drawable* getNormalImage() const throw(); - const Drawable* getOverImage() const throw(); - const Drawable* getDownImage() const throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown); + void paintButton (Graphics& g, + bool isMouseOverButton, + bool isButtonDown); private: - ButtonStyle style; - ScopedPointer normalImage, overImage, downImage, disabledImage; - ScopedPointer normalImageOn, overImageOn, downImageOn, disabledImageOn; - Colour backgroundOff, backgroundOn; - int edgeIndent; + ButtonStyle style; + ScopedPointer normalImage, overImage, downImage, disabledImage; + ScopedPointer normalImageOn, overImageOn, downImageOn, disabledImageOn; + Colour backgroundOff, backgroundOn; + int edgeIndent; - void deleteImages(); - DrawableButton (const DrawableButton&); - const DrawableButton& operator= (const DrawableButton&); + void deleteImages(); + DrawableButton (const DrawableButton&); + const DrawableButton& operator= (const DrawableButton&); }; #endif // __JUCE_DRAWABLEBUTTON_JUCEHEADER__ @@ -40699,84 +19402,49 @@ private: #ifndef __JUCE_HYPERLINKBUTTON_JUCEHEADER__ #define __JUCE_HYPERLINKBUTTON_JUCEHEADER__ -/** - A button showing an underlined weblink, that will launch the link - when it's clicked. - - @see Button -*/ class JUCE_API HyperlinkButton : public Button { public: - /** Creates a HyperlinkButton. + HyperlinkButton (const String& linkText, + const URL& linkURL); - @param linkText the text that will be displayed in the button - this is - also set as the Component's name, but the text can be - changed later with the Button::getButtonText() method - @param linkURL the URL to launch when the user clicks the button - */ - HyperlinkButton (const String& linkText, - const URL& linkURL); + ~HyperlinkButton(); - /** Destructor. */ - ~HyperlinkButton(); + void setFont (const Font& newFont, + const bool resizeToMatchComponentHeight, + const Justification& justificationType = Justification::horizontallyCentred); - /** Changes the font to use for the text. + enum ColourIds + { + textColourId = 0x1001f00, /**< The colour to use for the URL text. */ + }; - If resizeToMatchComponentHeight is true, the font's height will be adjusted - to match the size of the component. - */ - void setFont (const Font& newFont, - const bool resizeToMatchComponentHeight, - const Justification& justificationType = Justification::horizontallyCentred); + void setURL (const URL& newURL) throw(); - /** A set of colour IDs to use to change the colour of various aspects of the link. + const URL& getURL() const throw() { return url; } - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. + void changeWidthToFitText(); - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - textColourId = 0x1001f00, /**< The colour to use for the URL text. */ - }; - - /** Changes the URL that the button will trigger. */ - void setURL (const URL& newURL) throw(); - - /** Returns the URL that the button will trigger. */ - const URL& getURL() const throw() { return url; } - - /** Resizes the button horizontally to fit snugly around the text. - - This won't affect the button's height. - */ - void changeWidthToFitText(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void clicked(); - /** @internal */ - void colourChanged(); - /** @internal */ - void paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown); + void clicked(); + void colourChanged(); + void paintButton (Graphics& g, + bool isMouseOverButton, + bool isButtonDown); private: - URL url; - Font font; - bool resizeFont; - Justification justification; + URL url; + Font font; + bool resizeFont; + Justification justification; - const Font getFontToUse() const; + const Font getFontToUse() const; - HyperlinkButton (const HyperlinkButton&); - const HyperlinkButton& operator= (const HyperlinkButton&); + HyperlinkButton (const HyperlinkButton&); + const HyperlinkButton& operator= (const HyperlinkButton&); }; #endif // __JUCE_HYPERLINKBUTTON_JUCEHEADER__ @@ -40789,138 +19457,58 @@ private: #ifndef __JUCE_IMAGEBUTTON_JUCEHEADER__ #define __JUCE_IMAGEBUTTON_JUCEHEADER__ -/** - As the title suggests, this is a button containing an image. - - The colour and transparency of the image can be set to vary when the - button state changes. - - @see Button, ShapeButton, TextButton -*/ class JUCE_API ImageButton : public Button { public: - /** Creates an ImageButton. + ImageButton (const String& name); - Use setImage() to specify the image to use. The colours and opacities that - are specified here can be changed later using setDrawingOptions(). + ~ImageButton(); - @param name the name to give the component - */ - ImageButton (const String& name); + void setImages (const bool resizeButtonNowToFitThisImage, + const bool rescaleImagesWhenButtonSizeChanges, + const bool preserveImageProportions, + Image* const normalImage, + const float imageOpacityWhenNormal, + const Colour& overlayColourWhenNormal, + Image* const overImage, + const float imageOpacityWhenOver, + const Colour& overlayColourWhenOver, + Image* const downImage, + const float imageOpacityWhenDown, + const Colour& overlayColourWhenDown, + const float hitTestAlphaThreshold = 0.0f); - /** Destructor. */ - ~ImageButton(); + Image* getNormalImage() const throw(); - /** Sets up the images to draw in various states. + Image* getOverImage() const throw(); - Important! Bear in mind that if you pass the same image in for more than one of - these parameters, this button will delete it (or release from the ImageCache) - multiple times! + Image* getDownImage() const throw(); - @param resizeButtonNowToFitThisImage if true, the button will be immediately - resized to the same dimensions as the normal image - @param rescaleImagesWhenButtonSizeChanges if true, the image will be rescaled to fit the - button when the button's size changes - @param preserveImageProportions if true then any rescaling of the image to fit - the button will keep the image's x and y proportions - correct - i.e. it won't distort its shape, although - this might create gaps around the edges - @param normalImage the image to use when the button is in its normal state. The - image passed in will be deleted (or released if it - was created by the ImageCache class) when the - button no longer needs it. - @param imageOpacityWhenNormal the opacity to use when drawing the normal image. - @param overlayColourWhenNormal an overlay colour to use to fill the alpha channel of the - normal image - if this colour is transparent, no overlay - will be drawn. The overlay will be drawn over the top of the - image, so you can basically add a solid or semi-transparent - colour to the image to brighten or darken it - @param overImage the image to use when the mouse is over the button. If - you want to use the same image as was set in the normalImage - parameter, this value can be 0. As for normalImage, it - will be deleted or released by the button when no longer - needed - @param imageOpacityWhenOver the opacity to use when drawing the image when the mouse - is over the button - @param overlayColourWhenOver an overlay colour to use to fill the alpha channel of the - image when the mouse is over - if this colour is transparent, - no overlay will be drawn - @param downImage an image to use when the button is pressed down. If set - to zero, the 'over' image will be drawn instead (or the - normal image if there isn't an 'over' image either). This - image will be deleted or released by the button when no - longer needed - @param imageOpacityWhenDown the opacity to use when drawing the image when the button - is pressed - @param overlayColourWhenDown an overlay colour to use to fill the alpha channel of the - image when the button is pressed down - if this colour is - transparent, no overlay will be drawn - @param hitTestAlphaThreshold if set to zero, the mouse is considered to be over the button - whenever it's inside the button's bounding rectangle. If - set to values higher than 0, the mouse will only be - considered to be over the image when the value of the - image's alpha channel at that position is greater than - this level. - */ - void setImages (const bool resizeButtonNowToFitThisImage, - const bool rescaleImagesWhenButtonSizeChanges, - const bool preserveImageProportions, - Image* const normalImage, - const float imageOpacityWhenNormal, - const Colour& overlayColourWhenNormal, - Image* const overImage, - const float imageOpacityWhenOver, - const Colour& overlayColourWhenOver, - Image* const downImage, - const float imageOpacityWhenDown, - const Colour& overlayColourWhenDown, - const float hitTestAlphaThreshold = 0.0f); - - /** Returns the currently set 'normal' image. */ - Image* getNormalImage() const throw(); - - /** Returns the image that's drawn when the mouse is over the button. - - If an 'over' image has been set, this will return it; otherwise it'll - just return the normal image. - */ - Image* getOverImage() const throw(); - - /** Returns the image that's drawn when the button is held down. - - If a 'down' image has been set, this will return it; otherwise it'll - return the 'over' image or normal image, depending on what's available. - */ - Image* getDownImage() const throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - bool hitTest (int x, int y); - /** @internal */ - void paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown); + bool hitTest (int x, int y); + void paintButton (Graphics& g, + bool isMouseOverButton, + bool isButtonDown); private: - bool scaleImageToFit, preserveProportions; - unsigned char alphaThreshold; - int imageX, imageY, imageW, imageH; - Image* normalImage; - Image* overImage; - Image* downImage; - float normalOpacity, overOpacity, downOpacity; - Colour normalOverlay, overOverlay, downOverlay; + bool scaleImageToFit, preserveProportions; + unsigned char alphaThreshold; + int imageX, imageY, imageW, imageH; + Image* normalImage; + Image* overImage; + Image* downImage; + float normalOpacity, overOpacity, downOpacity; + Colour normalOverlay, overOverlay, downOverlay; - Image* getCurrentImage() const; - void deleteImages(); + Image* getCurrentImage() const; + void deleteImages(); - ImageButton (const ImageButton&); - const ImageButton& operator= (const ImageButton&); + ImageButton (const ImageButton&); + const ImageButton& operator= (const ImageButton&); }; #endif // __JUCE_IMAGEBUTTON_JUCEHEADER__ @@ -40933,78 +19521,45 @@ private: #ifndef __JUCE_SHAPEBUTTON_JUCEHEADER__ #define __JUCE_SHAPEBUTTON_JUCEHEADER__ -/** - A button that contains a filled shape. - - @see Button, ImageButton, TextButton, ArrowButton -*/ class JUCE_API ShapeButton : public Button { public: - /** Creates a ShapeButton. + ShapeButton (const String& name, + const Colour& normalColour, + const Colour& overColour, + const Colour& downColour); - @param name a name to give the component - see Component::setName() - @param normalColour the colour to fill the shape with when the mouse isn't over - @param overColour the colour to use when the mouse is over the shape - @param downColour the colour to use when the button is in the pressed-down state - */ - ShapeButton (const String& name, - const Colour& normalColour, - const Colour& overColour, - const Colour& downColour); + ~ShapeButton(); - /** Destructor. */ - ~ShapeButton(); + void setShape (const Path& newShape, + const bool resizeNowToFitThisShape, + const bool maintainShapeProportions, + const bool hasDropShadow); - /** Sets the shape to use. + void setColours (const Colour& normalColour, + const Colour& overColour, + const Colour& downColour); - @param newShape the shape to use - @param resizeNowToFitThisShape if true, the button will be resized to fit the shape's bounds - @param maintainShapeProportions if true, the shape's proportions will be kept fixed when - the button is resized - @param hasDropShadow if true, the button will be given a drop-shadow effect - */ - void setShape (const Path& newShape, - const bool resizeNowToFitThisShape, - const bool maintainShapeProportions, - const bool hasDropShadow); + void setOutline (const Colour& outlineColour, + const float outlineStrokeWidth); - /** Set the colours to use for drawing the shape. - - @param normalColour the colour to fill the shape with when the mouse isn't over - @param overColour the colour to use when the mouse is over the shape - @param downColour the colour to use when the button is in the pressed-down state - */ - void setColours (const Colour& normalColour, - const Colour& overColour, - const Colour& downColour); - - /** Sets up an outline to draw around the shape. - - @param outlineColour the colour to use - @param outlineStrokeWidth the thickness of line to draw - */ - void setOutline (const Colour& outlineColour, - const float outlineStrokeWidth); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown); + void paintButton (Graphics& g, + bool isMouseOverButton, + bool isButtonDown); private: - Colour normalColour, overColour, downColour, outlineColour; - DropShadowEffect shadow; - Path shape; - bool maintainShapeProportions; - float outlineWidth; + Colour normalColour, overColour, downColour, outlineColour; + DropShadowEffect shadow; + Path shape; + bool maintainShapeProportions; + float outlineWidth; - ShapeButton (const ShapeButton&); - const ShapeButton& operator= (const ShapeButton&); + ShapeButton (const ShapeButton&); + const ShapeButton& operator= (const ShapeButton&); }; #endif // __JUCE_SHAPEBUTTON_JUCEHEADER__ @@ -41020,62 +19575,34 @@ private: #ifndef __JUCE_TOGGLEBUTTON_JUCEHEADER__ #define __JUCE_TOGGLEBUTTON_JUCEHEADER__ -/** - A button that can be toggled on/off. - - All buttons can be toggle buttons, but this lets you create one of the - standard ones which has a tick-box and a text label next to it. - - @see Button, DrawableButton, TextButton -*/ class JUCE_API ToggleButton : public Button { public: - /** Creates a ToggleButton. + ToggleButton (const String& buttonText); - @param buttonText the text to put in the button (the component's name is also - initially set to this string, but these can be changed later - using the setName() and setButtonText() methods) - */ - ToggleButton (const String& buttonText); + ~ToggleButton(); - /** Destructor. */ - ~ToggleButton(); + void changeWidthToFitText(); - /** Resizes the button to fit neatly around its current text. + enum ColourIds + { + textColourId = 0x1006501 /**< The colour to use for the button's text. */ + }; - The button's height won't be affected, only its width. - */ - void changeWidthToFitText(); - - /** A set of colour IDs to use to change the colour of various aspects of the button. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - textColourId = 0x1006501 /**< The colour to use for the button's text. */ - }; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void paintButton (Graphics& g, - bool isMouseOverButton, - bool isButtonDown); + void paintButton (Graphics& g, + bool isMouseOverButton, + bool isButtonDown); - /** @internal */ - void colourChanged(); + void colourChanged(); private: - ToggleButton (const ToggleButton&); - const ToggleButton& operator= (const ToggleButton&); + ToggleButton (const ToggleButton&); + const ToggleButton& operator= (const ToggleButton&); }; #endif // __JUCE_TOGGLEBUTTON_JUCEHEADER__ @@ -41104,264 +19631,74 @@ private: #ifndef __JUCE_DRAGANDDROPTARGET_JUCEHEADER__ #define __JUCE_DRAGANDDROPTARGET_JUCEHEADER__ -/** - Components derived from this class can have things dropped onto them by a DragAndDropContainer. - - To create a component that can receive things drag-and-dropped by a DragAndDropContainer, - derive your component from this class, and make sure that it is somewhere inside a - DragAndDropContainer component. - - Note: If all that you need to do is to respond to files being drag-and-dropped from - the operating system onto your component, you don't need any of these classes: instead - see the FileDragAndDropTarget class. - - @see DragAndDropContainer, FileDragAndDropTarget -*/ class JUCE_API DragAndDropTarget { public: - /** Destructor. */ - virtual ~DragAndDropTarget() {} + virtual ~DragAndDropTarget() {} - /** Callback to check whether this target is interested in the type of object being - dragged. + virtual bool isInterestedInDragSource (const String& sourceDescription, + Component* sourceComponent) = 0; - @param sourceDescription the description string passed into DragAndDropContainer::startDragging() - @param sourceComponent the component that was passed into DragAndDropContainer::startDragging() - @returns true if this component wants to receive the other callbacks regarging this - type of object; if it returns false, no other callbacks will be made. - */ - virtual bool isInterestedInDragSource (const String& sourceDescription, - Component* sourceComponent) = 0; + virtual void itemDragEnter (const String& sourceDescription, + Component* sourceComponent, + int x, + int y); - /** Callback to indicate that something is being dragged over this component. + virtual void itemDragMove (const String& sourceDescription, + Component* sourceComponent, + int x, + int y); - This gets called when the user moves the mouse into this component while dragging - something. + virtual void itemDragExit (const String& sourceDescription, + Component* sourceComponent); - Use this callback as a trigger to make your component repaint itself to give the - user feedback about whether the item can be dropped here or not. + virtual void itemDropped (const String& sourceDescription, + Component* sourceComponent, + int x, + int y) = 0; - @param sourceDescription the description string passed into DragAndDropContainer::startDragging() - @param sourceComponent the component that was passed into DragAndDropContainer::startDragging() - @param x the mouse x position, relative to this component - @param y the mouse y position, relative to this component - @see itemDragExit - */ - virtual void itemDragEnter (const String& sourceDescription, - Component* sourceComponent, - int x, - int y); - - /** Callback to indicate that the user is dragging something over this component. - - This gets called when the user moves the mouse over this component while dragging - something. Normally overriding itemDragEnter() and itemDragExit() are enough, but - this lets you know what happens in-between. - - @param sourceDescription the description string passed into DragAndDropContainer::startDragging() - @param sourceComponent the component that was passed into DragAndDropContainer::startDragging() - @param x the mouse x position, relative to this component - @param y the mouse y position, relative to this component - */ - virtual void itemDragMove (const String& sourceDescription, - Component* sourceComponent, - int x, - int y); - - /** Callback to indicate that something has been dragged off the edge of this component. - - This gets called when the user moves the mouse out of this component while dragging - something. - - If you've used itemDragEnter() to repaint your component and give feedback, use this - as a signal to repaint it in its normal state. - - @param sourceDescription the description string passed into DragAndDropContainer::startDragging() - @param sourceComponent the component that was passed into DragAndDropContainer::startDragging() - @see itemDragEnter - */ - virtual void itemDragExit (const String& sourceDescription, - Component* sourceComponent); - - /** Callback to indicate that the user has dropped something onto this component. - - When the user drops an item this get called, and you can use the description to - work out whether your object wants to deal with it or not. - - Note that after this is called, the itemDragExit method may not be called, so you should - clean up in here if there's anything you need to do when the drag finishes. - - @param sourceDescription the description string passed into DragAndDropContainer::startDragging() - @param sourceComponent the component that was passed into DragAndDropContainer::startDragging() - @param x the mouse x position, relative to this component - @param y the mouse y position, relative to this component - */ - virtual void itemDropped (const String& sourceDescription, - Component* sourceComponent, - int x, - int y) = 0; - - /** Overriding this allows the target to tell the drag container whether to - draw the drag image while the cursor is over it. - - By default it returns true, but if you return false, then the normal drag - image will not be shown when the cursor is over this target. - */ - virtual bool shouldDrawDragImageWhenOver(); + virtual bool shouldDrawDragImageWhenOver(); }; #endif // __JUCE_DRAGANDDROPTARGET_JUCEHEADER__ /********* End of inlined file: juce_DragAndDropTarget.h *********/ -/** - Enables drag-and-drop behaviour for a component and all its sub-components. - - For a component to be able to make or receive drag-and-drop events, one of its parent - components must derive from this class. It's probably best for the top-level - component to implement it. - - Then to start a drag operation, any sub-component can just call the startDragging() - method, and this object will take over, tracking the mouse and sending appropriate - callbacks to any child components derived from DragAndDropTarget which the mouse - moves over. - - Note: If all that you need to do is to respond to files being drag-and-dropped from - the operating system onto your component, you don't need any of these classes: you can do this - simply by overriding Component::filesDropped(). - - @see DragAndDropTarget -*/ class JUCE_API DragAndDropContainer { public: - /** Creates a DragAndDropContainer. + DragAndDropContainer(); - The object that derives from this class must also be a Component. - */ - DragAndDropContainer(); + virtual ~DragAndDropContainer(); - /** Destructor. */ - virtual ~DragAndDropContainer(); + void startDragging (const String& sourceDescription, + Component* sourceComponent, + Image* dragImage = 0, + const bool allowDraggingToOtherJuceWindows = false, + const Point* imageOffsetFromMouse = 0); - /** Begins a drag-and-drop operation. + bool isDragAndDropActive() const; - This starts a drag-and-drop operation - call it when the user drags the - mouse in your drag-source component, and this object will track mouse - movements until the user lets go of the mouse button, and will send - appropriate messages to DragAndDropTarget objects that the mouse moves - over. + const String getCurrentDragDescription() const; - findParentDragContainerFor() is a handy method to call to find the - drag container to use for a component. + static DragAndDropContainer* findParentDragContainerFor (Component* childComponent); - @param sourceDescription a string to use as the description of the thing being - dragged - this will be passed to the objects that might be - dropped-onto so they can decide if they want to handle it or - not - @param sourceComponent the component that is being dragged - @param dragImage the image to drag around underneath the mouse. If this is - zero, a snapshot of the sourceComponent will be used instead. An - image passed-in will be deleted by this object when no longer - needed. - @param allowDraggingToOtherJuceWindows if true, the dragged component will appear as a desktop - window, and can be dragged to DragAndDropTargets that are the - children of components other than this one. - @param imageOffsetFromMouse if an image has been passed-in, this specifies the offset - at which the image should be drawn from the mouse. If it isn't - specified, then the image will be centred around the mouse. If - an image hasn't been passed-in, this will be ignored. - */ - void startDragging (const String& sourceDescription, - Component* sourceComponent, - Image* dragImage = 0, - const bool allowDraggingToOtherJuceWindows = false, - const Point* imageOffsetFromMouse = 0); + static bool performExternalDragDropOfFiles (const StringArray& files, const bool canMoveFiles); - /** Returns true if something is currently being dragged. */ - bool isDragAndDropActive() const; + static bool performExternalDragDropOfText (const String& text); - /** Returns the description of the thing that's currently being dragged. - - If nothing's being dragged, this will return an empty string, otherwise it's the - string that was passed into startDragging(). - - @see startDragging - */ - const String getCurrentDragDescription() const; - - /** Utility to find the DragAndDropContainer for a given Component. - - This will search up this component's parent hierarchy looking for the first - parent component which is a DragAndDropContainer. - - It's useful when a component wants to call startDragging but doesn't know - the DragAndDropContainer it should to use. - - Obviously this may return 0 if it doesn't find a suitable component. - */ - static DragAndDropContainer* findParentDragContainerFor (Component* childComponent); - - /** This performs a synchronous drag-and-drop of a set of files to some external - application. - - You can call this function in response to a mouseDrag callback, and it will - block, running its own internal message loop and tracking the mouse, while it - uses a native operating system drag-and-drop operation to move or copy some - files to another application. - - @param files a list of filenames to drag - @param canMoveFiles if true, the app that receives the files is allowed to move the files to a new location - (if this is appropriate). If false, the receiver is expected to make a copy of them. - @returns true if the files were successfully dropped somewhere, or false if it - was interrupted - @see performExternalDragDropOfText - */ - static bool performExternalDragDropOfFiles (const StringArray& files, const bool canMoveFiles); - - /** This performs a synchronous drag-and-drop of a block of text to some external - application. - - You can call this function in response to a mouseDrag callback, and it will - block, running its own internal message loop and tracking the mouse, while it - uses a native operating system drag-and-drop operation to move or copy some - text to another application. - - @param text the text to copy - @returns true if the text was successfully dropped somewhere, or false if it - was interrupted - @see performExternalDragDropOfFiles - */ - static bool performExternalDragDropOfText (const String& text); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** Override this if you want to be able to perform an external drag a set of files - when the user drags outside of this container component. - - This method will be called when a drag operation moves outside the Juce-based window, - and if you want it to then perform a file drag-and-drop, add the filenames you want - to the array passed in, and return true. - - @param dragSourceDescription the description passed into the startDrag() call when the drag began - @param dragSourceComponent the component passed into the startDrag() call when the drag began - @param files on return, the filenames you want to drag - @param canMoveFiles on return, true if it's ok for the receiver to move the files; false if - it must make a copy of them (see the performExternalDragDropOfFiles() - method) - @see performExternalDragDropOfFiles - */ - virtual bool shouldDropFilesWhenDraggedExternally (const String& dragSourceDescription, - Component* dragSourceComponent, - StringArray& files, - bool& canMoveFiles); + virtual bool shouldDropFilesWhenDraggedExternally (const String& dragSourceDescription, + Component* dragSourceComponent, + StringArray& files, + bool& canMoveFiles); private: - friend class DragImageComponent; - ScopedPointer dragImageComponent; - String currentDragDesc; + friend class DragImageComponent; + ScopedPointer dragImageComponent; + String currentDragDesc; }; #endif // __JUCE_DRAGANDDROPCONTAINER_JUCEHEADER__ @@ -41371,104 +19708,38 @@ private: #ifndef __JUCE_COMPONENTANIMATOR_JUCEHEADER__ #define __JUCE_COMPONENTANIMATOR_JUCEHEADER__ -/** - Animates a set of components, moving it to a new position. - - To use this, create a ComponentAnimator, and use its animateComponent() method - to tell it to move components to destination positions. Any number of - components can be animated by one ComponentAnimator object (if you've got a - lot of components to move, it's much more efficient to share a single animator - than to have many animators running at once). - - You'll need to make sure the animator object isn't deleted before it finishes - moving the components. - - The class is a ChangeBroadcaster and sends a notification when any components - start or finish being animated. -*/ class JUCE_API ComponentAnimator : public ChangeBroadcaster, - private Timer + private Timer { public: - /** Creates a ComponentAnimator. */ - ComponentAnimator(); + ComponentAnimator(); - /** Destructor. */ - ~ComponentAnimator(); + ~ComponentAnimator(); - /** Starts a component moving from its current position to a specified position. + void animateComponent (Component* const component, + const Rectangle& finalPosition, + const int millisecondsToSpendMoving, + const double startSpeed = 1.0, + const double endSpeed = 1.0); - If the component is already in the middle of an animation, that will be abandoned, - and a new animation will begin, moving the component from its current location. + void cancelAnimation (Component* const component, + const bool moveComponentToItsFinalPosition); - The start and end speed parameters let you apply some acceleration to the component's - movement. + void cancelAllAnimations (const bool moveComponentsToTheirFinalPositions); - @param component the component to move - @param finalPosition the destination position and size to move it to - @param millisecondsToSpendMoving how long, in milliseconds, it should take - to arrive at its destination - @param startSpeed a value to indicate the relative start speed of the - animation. If this is 0, the component will start - by accelerating from rest; higher values mean that it - will have an initial speed greater than zero. If the - value if greater than 1, it will decelerate towards the - middle of its journey. To move the component at a constant - rate for its entire animation, set both the start and - end speeds to 1.0 - @param endSpeed a relative speed at which the component should be moving - when the animation finishes. If this is 0, the component - will decelerate to a standstill at its final position; higher - values mean the component will still be moving when it stops. - To move the component at a constant rate for its entire - animation, set both the start and end speeds to 1.0 - */ - void animateComponent (Component* const component, - const Rectangle& finalPosition, - const int millisecondsToSpendMoving, - const double startSpeed = 1.0, - const double endSpeed = 1.0); + const Rectangle getComponentDestination (Component* const component); - /** Stops a component if it's currently being animated. + bool isAnimating (Component* component) const; - If moveComponentToItsFinalPosition is true, then the component will - be immediately moved to its destination position and size. If false, it will be - left in whatever location it currently occupies. - */ - void cancelAnimation (Component* const component, - const bool moveComponentToItsFinalPosition); - - /** Clears all of the active animations. - - If moveComponentsToTheirFinalPositions is true, all the components will - be immediately set to their final positions. If false, they will be - left in whatever locations they currently occupy. - */ - void cancelAllAnimations (const bool moveComponentsToTheirFinalPositions); - - /** Returns the destination position for a component. - - If the component is being animated, this will return the target position that - was specified when animateComponent() was called. - - If the specified component isn't currently being animated, this method will just - return its current position. - */ - const Rectangle getComponentDestination (Component* const component); - - /** Returns true if the specified component is currently being animated. - */ - bool isAnimating (Component* component) const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - VoidArray tasks; - uint32 lastTime; + VoidArray tasks; + uint32 lastTime; - void* findTaskFor (Component* const component) const; - void timerCallback(); + void* findTaskFor (Component* const component) const; + void timerCallback(); }; #endif // __JUCE_COMPONENTANIMATOR_JUCEHEADER__ @@ -41478,275 +19749,124 @@ class ToolbarItemComponent; class ToolbarItemFactory; class MissingItemsComponent; -/** - A toolbar component. - - A toolbar contains a horizontal or vertical strip of ToolbarItemComponents, - and looks after their order and layout. - - Items (icon buttons or other custom components) are added to a toolbar using a - ToolbarItemFactory - each type of item is given a unique ID number, and a - toolbar might contain more than one instance of a particular item type. - - Toolbars can be interactively customised, allowing the user to drag the items - around, and to drag items onto or off the toolbar, using the ToolbarItemPalette - component as a source of new items. - - @see ToolbarItemFactory, ToolbarItemComponent, ToolbarItemPalette -*/ class JUCE_API Toolbar : public Component, - public DragAndDropContainer, - public DragAndDropTarget, - private ButtonListener + public DragAndDropContainer, + public DragAndDropTarget, + private ButtonListener { public: - /** Creates an empty toolbar component. + Toolbar(); - To add some icons or other components to your toolbar, you'll need to - create a ToolbarItemFactory class that can create a suitable set of - ToolbarItemComponents. + ~Toolbar(); - @see ToolbarItemFactory, ToolbarItemComponents - */ - Toolbar(); + void setVertical (const bool shouldBeVertical); - /** Destructor. + bool isVertical() const throw() { return vertical; } - Any items on the bar will be deleted when the toolbar is deleted. - */ - ~Toolbar(); + int getThickness() const throw(); - /** Changes the bar's orientation. - @see isVertical - */ - void setVertical (const bool shouldBeVertical); + int getLength() const throw(); - /** Returns true if the bar is set to be vertical, or false if it's horizontal. + void clear(); - You can change the bar's orientation with setVertical(). - */ - bool isVertical() const throw() { return vertical; } + void addItem (ToolbarItemFactory& factory, + const int itemId, + const int insertIndex = -1); - /** Returns the depth of the bar. + void removeToolbarItem (const int itemIndex); - If the bar is horizontal, this will return its height; if it's vertical, it - will return its width. + int getNumItems() const throw(); - @see getLength - */ - int getThickness() const throw(); + int getItemId (const int itemIndex) const throw(); - /** Returns the length of the bar. + ToolbarItemComponent* getItemComponent (const int itemIndex) const throw(); - If the bar is horizontal, this will return its width; if it's vertical, it - will return its height. + void addDefaultItems (ToolbarItemFactory& factoryToUse); - @see getThickness - */ - int getLength() const throw(); + enum ToolbarItemStyle + { + iconsOnly, /**< Means that the toolbar should just contain icons. */ + iconsWithText, /**< Means that the toolbar should have text labels under each icon. */ + textOnly /**< Means that the toolbar only display text labels for each item. */ + }; - /** Deletes all items from the bar. - */ - void clear(); + ToolbarItemStyle getStyle() const throw() { return toolbarStyle; } - /** Adds an item to the toolbar. + void setStyle (const ToolbarItemStyle& newStyle); - The factory's ToolbarItemFactory::createItem() will be called by this method - to create the component that will actually be added to the bar. + enum CustomisationFlags + { + allowIconsOnlyChoice = 1, /**< If this flag is specified, the customisation dialog can + show the "icons only" option on its choice of toolbar styles. */ + allowIconsWithTextChoice = 2, /**< If this flag is specified, the customisation dialog can + show the "icons with text" option on its choice of toolbar styles. */ + allowTextOnlyChoice = 4, /**< If this flag is specified, the customisation dialog can + show the "text only" option on its choice of toolbar styles. */ + showResetToDefaultsButton = 8, /**< If this flag is specified, the customisation dialog can + show a button to reset the toolbar to its default set of items. */ - The new item will be inserted at the specified index (if the index is -1, it - will be added to the right-hand or bottom end of the bar). + allCustomisationOptionsEnabled = (allowIconsOnlyChoice | allowIconsWithTextChoice | allowTextOnlyChoice | showResetToDefaultsButton) + }; - Once added, the component will be automatically deleted by this object when it - is no longer needed. + void showCustomisationDialog (ToolbarItemFactory& factory, + const int optionFlags = allCustomisationOptionsEnabled); - @see ToolbarItemFactory - */ - void addItem (ToolbarItemFactory& factory, - const int itemId, - const int insertIndex = -1); + void setEditingActive (const bool editingEnabled); - /** Deletes one of the items from the bar. - */ - void removeToolbarItem (const int itemIndex); + enum ColourIds + { + backgroundColourId = 0x1003200, /**< A colour to use to fill the toolbar's background. For + more control over this, override LookAndFeel::paintToolbarBackground(). */ + separatorColourId = 0x1003210, /**< A colour to use to draw the separator lines. */ - /** Returns the number of items currently on the toolbar. + buttonMouseOverBackgroundColourId = 0x1003220, /**< A colour used to paint the background of buttons when the mouse is + over them. */ + buttonMouseDownBackgroundColourId = 0x1003230, /**< A colour used to paint the background of buttons when the mouse is + held down on them. */ - @see getItemId, getItemComponent - */ - int getNumItems() const throw(); + labelTextColourId = 0x1003240, /**< A colour to use for drawing the text under buttons + when the style is set to iconsWithText or textOnly. */ - /** Returns the ID of the item with the given index. + editingModeOutlineColourId = 0x1003250 /**< A colour to use for an outline around buttons when + the customisation dialog is active and the mouse moves over them. */ + }; - If the index is less than zero or greater than the number of items, - this will return 0. + const String toString() const; - @see getNumItems - */ - int getItemId (const int itemIndex) const throw(); + bool restoreFromString (ToolbarItemFactory& factoryToUse, + const String& savedVersion); - /** Returns the component being used for the item with the given index. + void paint (Graphics& g); + void resized(); + void buttonClicked (Button*); + void mouseDown (const MouseEvent&); + bool isInterestedInDragSource (const String&, Component*); + void itemDragMove (const String&, Component*, int, int); + void itemDragExit (const String&, Component*); + void itemDropped (const String&, Component*, int, int); + void updateAllItemPositions (const bool animate); + static ToolbarItemComponent* createItem (ToolbarItemFactory&, const int itemId); - If the index is less than zero or greater than the number of items, - this will return 0. - - @see getNumItems - */ - ToolbarItemComponent* getItemComponent (const int itemIndex) const throw(); - - /** Clears this toolbar and adds to it the default set of items that the specified - factory creates. - - @see ToolbarItemFactory::getDefaultItemSet - */ - void addDefaultItems (ToolbarItemFactory& factoryToUse); - - /** Options for the way items should be displayed. - @see setStyle, getStyle - */ - enum ToolbarItemStyle - { - iconsOnly, /**< Means that the toolbar should just contain icons. */ - iconsWithText, /**< Means that the toolbar should have text labels under each icon. */ - textOnly /**< Means that the toolbar only display text labels for each item. */ - }; - - /** Returns the toolbar's current style. - @see ToolbarItemStyle, setStyle - */ - ToolbarItemStyle getStyle() const throw() { return toolbarStyle; } - - /** Changes the toolbar's current style. - @see ToolbarItemStyle, getStyle, ToolbarItemComponent::setStyle - */ - void setStyle (const ToolbarItemStyle& newStyle); - - /** Flags used by the showCustomisationDialog() method. */ - enum CustomisationFlags - { - allowIconsOnlyChoice = 1, /**< If this flag is specified, the customisation dialog can - show the "icons only" option on its choice of toolbar styles. */ - allowIconsWithTextChoice = 2, /**< If this flag is specified, the customisation dialog can - show the "icons with text" option on its choice of toolbar styles. */ - allowTextOnlyChoice = 4, /**< If this flag is specified, the customisation dialog can - show the "text only" option on its choice of toolbar styles. */ - showResetToDefaultsButton = 8, /**< If this flag is specified, the customisation dialog can - show a button to reset the toolbar to its default set of items. */ - - allCustomisationOptionsEnabled = (allowIconsOnlyChoice | allowIconsWithTextChoice | allowTextOnlyChoice | showResetToDefaultsButton) - }; - - /** Pops up a modal dialog box that allows this toolbar to be customised by the user. - - The dialog contains a ToolbarItemPalette and various controls for editing other - aspects of the toolbar. This method will block and run the dialog box modally, - returning when the user closes it. - - The factory is used to determine the set of items that will be shown on the - palette. - - The optionFlags parameter is a bitwise-or of values from the CustomisationFlags - enum. - - @see ToolbarItemPalette - */ - void showCustomisationDialog (ToolbarItemFactory& factory, - const int optionFlags = allCustomisationOptionsEnabled); - - /** Turns on or off the toolbar's editing mode, in which its items can be - rearranged by the user. - - (In most cases it's easier just to use showCustomisationDialog() instead of - trying to enable editing directly). - - @see ToolbarItemPalette - */ - void setEditingActive (const bool editingEnabled); - - /** A set of colour IDs to use to change the colour of various aspects of the toolbar. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1003200, /**< A colour to use to fill the toolbar's background. For - more control over this, override LookAndFeel::paintToolbarBackground(). */ - separatorColourId = 0x1003210, /**< A colour to use to draw the separator lines. */ - - buttonMouseOverBackgroundColourId = 0x1003220, /**< A colour used to paint the background of buttons when the mouse is - over them. */ - buttonMouseDownBackgroundColourId = 0x1003230, /**< A colour used to paint the background of buttons when the mouse is - held down on them. */ - - labelTextColourId = 0x1003240, /**< A colour to use for drawing the text under buttons - when the style is set to iconsWithText or textOnly. */ - - editingModeOutlineColourId = 0x1003250 /**< A colour to use for an outline around buttons when - the customisation dialog is active and the mouse moves over them. */ - }; - - /** Returns a string that represents the toolbar's current set of items. - - This lets you later restore the same item layout using restoreFromString(). - - @see restoreFromString - */ - const String toString() const; - - /** Restores a set of items that was previously stored in a string by the toString() - method. - - The factory object is used to create any item components that are needed. - - @see toString - */ - bool restoreFromString (ToolbarItemFactory& factoryToUse, - const String& savedVersion); - - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void resized(); - /** @internal */ - void buttonClicked (Button*); - /** @internal */ - void mouseDown (const MouseEvent&); - /** @internal */ - bool isInterestedInDragSource (const String&, Component*); - /** @internal */ - void itemDragMove (const String&, Component*, int, int); - /** @internal */ - void itemDragExit (const String&, Component*); - /** @internal */ - void itemDropped (const String&, Component*, int, int); - /** @internal */ - void updateAllItemPositions (const bool animate); - /** @internal */ - static ToolbarItemComponent* createItem (ToolbarItemFactory&, const int itemId); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - Button* missingItemsButton; - bool vertical, isEditingActive; - ToolbarItemStyle toolbarStyle; - ComponentAnimator animator; - friend class MissingItemsComponent; - Array items; + Button* missingItemsButton; + bool vertical, isEditingActive; + ToolbarItemStyle toolbarStyle; + ComponentAnimator animator; + friend class MissingItemsComponent; + Array items; - friend class ItemDragAndDropOverlayComponent; - static const tchar* const toolbarDragDescriptor; + friend class ItemDragAndDropOverlayComponent; + static const tchar* const toolbarDragDescriptor; - void addItemInternal (ToolbarItemFactory& factory, const int itemId, const int insertIndex); + void addItemInternal (ToolbarItemFactory& factory, const int itemId, const int insertIndex); - ToolbarItemComponent* getNextActiveComponent (int index, const int delta) const; + ToolbarItemComponent* getNextActiveComponent (int index, const int delta) const; - Toolbar (const Toolbar&); - const Toolbar& operator= (const Toolbar&); + Toolbar (const Toolbar&); + const Toolbar& operator= (const Toolbar&); }; #endif // __JUCE_TOOLBAR_JUCEHEADER__ @@ -41754,232 +19874,99 @@ private: class ItemDragAndDropOverlayComponent; -/** - A component that can be used as one of the items in a Toolbar. - - Each of the items on a toolbar must be a component derived from ToolbarItemComponent, - and these objects are always created by a ToolbarItemFactory - see the ToolbarItemFactory - class for further info about creating them. - - The ToolbarItemComponent class is actually a button, but can be used to hold non-button - components too. To do this, set the value of isBeingUsedAsAButton to false when - calling the constructor, and override contentAreaChanged(), in which you can position - any sub-components you need to add. - - To add basic buttons without writing a special subclass, have a look at the - ToolbarButton class. - - @see ToolbarButton, Toolbar, ToolbarItemFactory -*/ class JUCE_API ToolbarItemComponent : public Button { public: - /** Constructor. + ToolbarItemComponent (const int itemId, + const String& labelText, + const bool isBeingUsedAsAButton); - @param itemId the ID of the type of toolbar item which this represents - @param labelText the text to display if the toolbar's style is set to - Toolbar::iconsWithText or Toolbar::textOnly - @param isBeingUsedAsAButton set this to false if you don't want the button - to draw itself with button over/down states when the mouse - moves over it or clicks - */ - ToolbarItemComponent (const int itemId, - const String& labelText, - const bool isBeingUsedAsAButton); + ~ToolbarItemComponent(); - /** Destructor. */ - ~ToolbarItemComponent(); + int getItemId() const throw() { return itemId; } - /** Returns the item type ID that this component represents. - This value is in the constructor. - */ - int getItemId() const throw() { return itemId; } + Toolbar* getToolbar() const; - /** Returns the toolbar that contains this component, or 0 if it's not currently - inside one. - */ - Toolbar* getToolbar() const; + bool isToolbarVertical() const; - /** Returns true if this component is currently inside a toolbar which is vertical. - @see Toolbar::isVertical - */ - bool isToolbarVertical() const; + Toolbar::ToolbarItemStyle getStyle() const throw() { return toolbarStyle; } - /** Returns the current style setting of this item. + virtual void setStyle (const Toolbar::ToolbarItemStyle& newStyle); - Styles are listed in the Toolbar::ToolbarItemStyle enum. - @see setStyle, Toolbar::getStyle - */ - Toolbar::ToolbarItemStyle getStyle() const throw() { return toolbarStyle; } + const Rectangle getContentArea() const throw() { return contentArea; } - /** Changes the current style setting of this item. + virtual bool getToolbarItemSizes (int toolbarThickness, + bool isToolbarVertical, + int& preferredSize, + int& minSize, + int& maxSize) = 0; - Styles are listed in the Toolbar::ToolbarItemStyle enum, and are automatically updated - by the toolbar that holds this item. + virtual void paintButtonArea (Graphics& g, + int width, int height, + bool isMouseOver, bool isMouseDown) = 0; - @see setStyle, Toolbar::setStyle - */ - virtual void setStyle (const Toolbar::ToolbarItemStyle& newStyle); + virtual void contentAreaChanged (const Rectangle& newBounds) = 0; - /** Returns the area of the component that should be used to display the button image or - other contents of the item. + enum ToolbarEditingMode + { + normalMode = 0, /**< Means that the component is active, inside a toolbar. */ + editableOnToolbar, /**< Means that the component is on a toolbar, but the toolbar is in + customisation mode, and the items can be dragged around. */ + editableOnPalette /**< Means that the component is on an new-item palette, so it can be + dragged onto a toolbar to add it to that bar.*/ + }; - This content area may change when the item's style changes, and may leave a space around the - edge of the component where the text label can be shown. + void setEditingMode (const ToolbarEditingMode newMode); - @see contentAreaChanged - */ - const Rectangle getContentArea() const throw() { return contentArea; } + ToolbarEditingMode getEditingMode() const throw() { return mode; } - /** This method must return the size criteria for this item, based on a given toolbar - size and orientation. + void paintButton (Graphics& g, bool isMouseOver, bool isMouseDown); + void resized(); - The preferredSize, minSize and maxSize values must all be set by your implementation - method. If the toolbar is horizontal, these will be the width of the item; for a vertical - toolbar, they refer to the item's height. - - The preferredSize is the size that the component would like to be, and this must be - between the min and max sizes. For a fixed-size item, simply set all three variables to - the same value. - - The toolbarThickness parameter tells you the depth of the toolbar - the same as calling - Toolbar::getThickness(). - - The isToolbarVertical parameter tells you whether the bar is oriented horizontally or - vertically. - */ - virtual bool getToolbarItemSizes (int toolbarThickness, - bool isToolbarVertical, - int& preferredSize, - int& minSize, - int& maxSize) = 0; - - /** Your subclass should use this method to draw its content area. - - The graphics object that is passed-in will have been clipped and had its origin - moved to fit the content area as specified get getContentArea(). The width and height - parameters are the width and height of the content area. - - If the component you're writing isn't a button, you can just do nothing in this method. - */ - virtual void paintButtonArea (Graphics& g, - int width, int height, - bool isMouseOver, bool isMouseDown) = 0; - - /** Callback to indicate that the content area of this item has changed. - - This might be because the component was resized, or because the style changed and - the space needed for the text label is different. - - See getContentArea() for a description of what the area is. - */ - virtual void contentAreaChanged (const Rectangle& newBounds) = 0; - - /** Editing modes. - These are used by setEditingMode(), but will be rarely needed in user code. - */ - enum ToolbarEditingMode - { - normalMode = 0, /**< Means that the component is active, inside a toolbar. */ - editableOnToolbar, /**< Means that the component is on a toolbar, but the toolbar is in - customisation mode, and the items can be dragged around. */ - editableOnPalette /**< Means that the component is on an new-item palette, so it can be - dragged onto a toolbar to add it to that bar.*/ - }; - - /** Changes the editing mode of this component. - - This is used by the ToolbarItemPalette and related classes for making the items draggable, - and is unlikely to be of much use in end-user-code. - */ - void setEditingMode (const ToolbarEditingMode newMode); - - /** Returns the current editing mode of this component. - - This is used by the ToolbarItemPalette and related classes for making the items draggable, - and is unlikely to be of much use in end-user-code. - */ - ToolbarEditingMode getEditingMode() const throw() { return mode; } - - /** @internal */ - void paintButton (Graphics& g, bool isMouseOver, bool isMouseDown); - /** @internal */ - void resized(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class Toolbar; - friend class ItemDragAndDropOverlayComponent; - const int itemId; - ToolbarEditingMode mode; - Toolbar::ToolbarItemStyle toolbarStyle; - ScopedPointer overlayComp; - int dragOffsetX, dragOffsetY; - bool isActive, isBeingDragged, isBeingUsedAsAButton; - Rectangle contentArea; + friend class Toolbar; + friend class ItemDragAndDropOverlayComponent; + const int itemId; + ToolbarEditingMode mode; + Toolbar::ToolbarItemStyle toolbarStyle; + ScopedPointer overlayComp; + int dragOffsetX, dragOffsetY; + bool isActive, isBeingDragged, isBeingUsedAsAButton; + Rectangle contentArea; - ToolbarItemComponent (const ToolbarItemComponent&); - const ToolbarItemComponent& operator= (const ToolbarItemComponent&); + ToolbarItemComponent (const ToolbarItemComponent&); + const ToolbarItemComponent& operator= (const ToolbarItemComponent&); }; #endif // __JUCE_TOOLBARITEMCOMPONENT_JUCEHEADER__ /********* End of inlined file: juce_ToolbarItemComponent.h *********/ -/** - A type of button designed to go on a toolbar. - - This simple button can have two Drawable objects specified - one for normal - use and another one (optionally) for the button's "on" state if it's a - toggle button. - - @see Toolbar, ToolbarItemFactory, ToolbarItemComponent, Drawable, Button -*/ class JUCE_API ToolbarButton : public ToolbarItemComponent { public: - /** Creates a ToolbarButton. + ToolbarButton (const int itemId, + const String& labelText, + Drawable* const normalImage, + Drawable* const toggledOnImage); - @param itemId the ID for this toolbar item type. This is passed through to the - ToolbarItemComponent constructor - @param labelText the text to display on the button (if the toolbar is using a style - that shows text labels). This is passed through to the - ToolbarItemComponent constructor - @param normalImage a drawable object that the button should use as its icon. The object - that is passed-in here will be kept by this object and will be - deleted when no longer needed or when this button is deleted. - @param toggledOnImage a drawable object that the button can use as its icon if the button - is in a toggled-on state (see the Button::getToggleState() method). If - 0 is passed-in here, then the normal image will be used instead, regardless - of the toggle state. The object that is passed-in here will be kept by - this object and will be deleted when no longer needed or when this button - is deleted. - */ - ToolbarButton (const int itemId, - const String& labelText, - Drawable* const normalImage, - Drawable* const toggledOnImage); + ~ToolbarButton(); - /** Destructor. */ - ~ToolbarButton(); + bool getToolbarItemSizes (int toolbarDepth, bool isToolbarVertical, int& preferredSize, + int& minSize, int& maxSize); + void paintButtonArea (Graphics& g, int width, int height, bool isMouseOver, bool isMouseDown); + void contentAreaChanged (const Rectangle& newBounds); - /** @internal */ - bool getToolbarItemSizes (int toolbarDepth, bool isToolbarVertical, int& preferredSize, - int& minSize, int& maxSize); - /** @internal */ - void paintButtonArea (Graphics& g, int width, int height, bool isMouseOver, bool isMouseDown); - /** @internal */ - void contentAreaChanged (const Rectangle& newBounds); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ScopedPointer normalImage, toggledOnImage; + ScopedPointer normalImage, toggledOnImage; - ToolbarButton (const ToolbarButton&); - const ToolbarButton& operator= (const ToolbarButton&); + ToolbarButton (const ToolbarButton&); + const ToolbarButton& operator= (const ToolbarButton&); }; #endif // __JUCE_TOOLBARBUTTON_JUCEHEADER__ @@ -41994,353 +19981,166 @@ private: class CodeDocumentLine; -/** - A class for storing and manipulating a source code file. - - When using a CodeEditorComponent, it takes one of these as its source object. - - The CodeDocument stores its content as an array of lines, which makes it - quick to insert and delete. - - @see CodeEditorComponent -*/ class JUCE_API CodeDocument { public: - /** Creates a new, empty document. - */ - CodeDocument(); - - /** Destructor. */ - ~CodeDocument(); - - /** A position in a code document. - - Using this class you can find a position in a code document and quickly get its - character position, line, and index. By calling setPositionMaintained (true), the - position is automatically updated when text is inserted or deleted in the document, - so that it maintains its original place in the text. - */ - class JUCE_API Position - { - public: - /** Creates an uninitialised postion. - Don't attempt to call any methods on this until you've given it an owner document - to refer to! - */ - Position() throw(); - - /** Creates a position based on a line and index in a document. - - Note that this index is NOT the column number, it's the number of characters from the - start of the line. The "column" number isn't quite the same, because if the line - contains any tab characters, the relationship of the index to its visual column depends on - the number of spaces per tab being used! - - Lines are numbered from zero, and if the line or index are beyond the bounds of the document, - they will be adjusted to keep them within its limits. - */ - Position (const CodeDocument* const ownerDocument, - const int line, const int indexInLine) throw(); - - /** Creates a position based on a character index in a document. - This position is placed at the specified number of characters from the start of the - document. The line and column are auto-calculated. - - If the position is beyond the range of the document, it'll be adjusted to keep it - inside. - */ - Position (const CodeDocument* const ownerDocument, - const int charactersFromStartOfDocument) throw(); - - /** Creates a copy of another position. - - This will copy the position, but the new object will not be set to maintain its position, - even if the source object was set to do so. - */ - Position (const Position& other) throw(); - - /** Destructor. */ - ~Position() throw(); - - const Position& operator= (const Position& other) throw(); - bool operator== (const Position& other) const throw(); - bool operator!= (const Position& other) const throw(); - - /** Points this object at a new position within the document. - - If the position is beyond the range of the document, it'll be adjusted to keep it - inside. - @see getPosition, setLineAndIndex - */ - void setPosition (const int charactersFromStartOfDocument) throw(); - - /** Returns the position as the number of characters from the start of the document. - @see setPosition, getLineNumber, getIndexInLine - */ - int getPosition() const throw() { return characterPos; } - - /** Moves the position to a new line and index within the line. - - Note that the index is NOT the column at which the position appears in an editor. - If the line contains any tab characters, the relationship of the index to its - visual position depends on the number of spaces per tab being used! - - Lines are numbered from zero, and if the line or index are beyond the bounds of the document, - they will be adjusted to keep them within its limits. - */ - void setLineAndIndex (const int newLine, const int newIndexInLine) throw(); - - /** Returns the line number of this position. - The first line in the document is numbered zero, not one! - */ - int getLineNumber() const throw() { return line; } - - /** Returns the number of characters from the start of the line. - - Note that this value is NOT the column at which the position appears in an editor. - If the line contains any tab characters, the relationship of the index to its - visual position depends on the number of spaces per tab being used! - */ - int getIndexInLine() const throw() { return indexInLine; } - - /** Allows the position to be automatically updated when the document changes. - - If this is set to true, the positon will register with its document so that - when the document has text inserted or deleted, this position will be automatically - moved to keep it at the same position in the text. - */ - void setPositionMaintained (const bool isMaintained) throw(); - - /** Moves the position forwards or backwards by the specified number of characters. - @see movedBy - */ - void moveBy (int characterDelta) throw(); - - /** Returns a position which is the same as this one, moved by the specified number of - characters. - @see moveBy - */ - const Position movedBy (const int characterDelta) const throw(); - - /** Returns a position which is the same as this one, moved up or down by the specified - number of lines. - @see movedBy - */ - const Position movedByLines (const int deltaLines) const throw(); - - /** Returns the character in the document at this position. - @see getLineText - */ - const tchar getCharacter() const throw(); - - /** Returns the line from the document that this position is within. - @see getCharacter, getLineNumber - */ - const String getLineText() const throw(); - - private: - CodeDocument* owner; - int characterPos, line, indexInLine; - bool positionMaintained; - }; + CodeDocument(); - /** Returns the full text of the document. */ - const String getAllContent() const throw(); - - /** Returns a section of the document's text. */ - const String getTextBetween (const Position& start, const Position& end) const throw(); - - /** Returns a line from the document. */ - const String getLine (const int lineIndex) const throw(); - - /** Returns the number of characters in the document. */ - int getNumCharacters() const throw(); - - /** Returns the number of lines in the document. */ - int getNumLines() const throw() { return lines.size(); } - - /** Returns the number of characters in the longest line of the document. */ - int getMaximumLineLength() throw(); - - /** Deletes a section of the text. - - This operation is undoable. - */ - void deleteSection (const Position& startPosition, const Position& endPosition); - - /** Inserts some text into the document at a given position. - - This operation is undoable. - */ - void insertText (const Position& position, const String& text); - - /** Clears the document and replaces it with some new text. - - This operation is undoable - if you're trying to completely reset the document, you - might want to also call clearUndoHistory() and setSavePoint() after using this method. - */ - void replaceAllContent (const String& newContent); - - /** Returns the preferred new-line characters for the document. - This will be either "\n", "\r\n", or (rarely) "\r". - @see setNewLineCharacters - */ - const String getNewLineCharacters() const throw() { return newLineChars; } - - /** Sets the new-line characters that the document should use. - The string must be either "\n", "\r\n", or (rarely) "\r". - @see getNewLineCharacters - */ - void setNewLineCharacters (const String& newLine) throw(); - - /** Begins a new undo transaction. - - The document itself will not call this internally, so relies on whatever is using the - document to periodically call this to break up the undo sequence into sensible chunks. - @see UndoManager::beginNewTransaction - */ - void newTransaction(); - - /** Undo the last operation. - @see UndoManager::undo - */ - void undo(); - - /** Redo the last operation. - @see UndoManager::redo - */ - void redo(); - - /** Clears the undo history. - @see UndoManager::clearUndoHistory - */ - void clearUndoHistory(); - - /** Returns the document's UndoManager */ - UndoManager& getUndoManager() throw() { return undoManager; } - - /** Makes a note that the document's current state matches the one that is saved. - - After this has been called, hasChangedSinceSavePoint() will return false until - the document has been altered, and then it'll start returning true. If the document is - altered, but then undone until it gets back to this state, hasChangedSinceSavePoint() - will again return false. - - @see hasChangedSinceSavePoint - */ - void setSavePoint() throw(); - - /** Returns true if the state of the document differs from the state it was in when - setSavePoint() was last called. + ~CodeDocument(); - @see setSavePoint - */ - bool hasChangedSinceSavePoint() const throw(); + class JUCE_API Position + { + public: + Position() throw(); - /** Searches for a word-break. */ - const Position findWordBreakAfter (const Position& position) const throw(); + Position (const CodeDocument* const ownerDocument, + const int line, const int indexInLine) throw(); - /** Searches for a word-break. */ - const Position findWordBreakBefore (const Position& position) const throw(); + Position (const CodeDocument* const ownerDocument, + const int charactersFromStartOfDocument) throw(); - /** An object that receives callbacks from the CodeDocument when its text changes. - @see CodeDocument::addListener, CodeDocument::removeListener - */ - class JUCE_API Listener - { - public: - Listener() {} - virtual ~Listener() {} + Position (const Position& other) throw(); - /** Called by a CodeDocument when it is altered. - */ - virtual void codeDocumentChanged (const Position& affectedTextStart, - const Position& affectedTextEnd) = 0; - }; - - /** Registers a listener object to receive callbacks when the document changes. - If the listener is already registered, this method has no effect. - @see removeListener - */ - void addListener (Listener* const listener) throw(); - - /** Deregisters a listener. - @see addListener - */ - void removeListener (Listener* const listener) throw(); - - /** Iterates the text in a CodeDocument. - - This class lets you read characters from a CodeDocument. It's designed to be used - by a SyntaxAnalyser object. - - @see CodeDocument, SyntaxAnalyser - */ - class Iterator - { - public: - Iterator (CodeDocument* const document) throw(); - Iterator (const Iterator& other); - const Iterator& operator= (const Iterator& other) throw(); - ~Iterator() throw(); - - /** Reads the next character and returns it. - @see peekNextChar - */ - juce_wchar nextChar() throw(); - - /** Reads the next character without advancing the current position. */ - juce_wchar peekNextChar() const throw(); - - /** Advances the position by one character. */ - void skip() throw(); - - /** Returns the position of the next character as its position within the - whole document. - */ - int getPosition() const throw() { return position; } - - /** Skips over any whitespace characters until the next character is non-whitespace. */ - void skipWhitespace(); - - /** Skips forward until the next character will be the first character on the next line */ - void skipToEndOfLine(); - - /** Returns the line number of the next character. */ - int getLine() const throw() { return line; } - - /** Returns true if the iterator has reached the end of the document. */ - bool isEOF() const throw(); - - private: - CodeDocument* document; - int line, position; - }; - - juce_UseDebuggingNewOperator + ~Position() throw(); + + const Position& operator= (const Position& other) throw(); + bool operator== (const Position& other) const throw(); + bool operator!= (const Position& other) const throw(); + + void setPosition (const int charactersFromStartOfDocument) throw(); + + int getPosition() const throw() { return characterPos; } + + void setLineAndIndex (const int newLine, const int newIndexInLine) throw(); + + int getLineNumber() const throw() { return line; } + + int getIndexInLine() const throw() { return indexInLine; } + + void setPositionMaintained (const bool isMaintained) throw(); + + void moveBy (int characterDelta) throw(); + + const Position movedBy (const int characterDelta) const throw(); + + const Position movedByLines (const int deltaLines) const throw(); + + const tchar getCharacter() const throw(); + + const String getLineText() const throw(); + + private: + CodeDocument* owner; + int characterPos, line, indexInLine; + bool positionMaintained; + }; + + const String getAllContent() const throw(); + + const String getTextBetween (const Position& start, const Position& end) const throw(); + + const String getLine (const int lineIndex) const throw(); + + int getNumCharacters() const throw(); + + int getNumLines() const throw() { return lines.size(); } + + int getMaximumLineLength() throw(); + + void deleteSection (const Position& startPosition, const Position& endPosition); + + void insertText (const Position& position, const String& text); + + void replaceAllContent (const String& newContent); + + const String getNewLineCharacters() const throw() { return newLineChars; } + + void setNewLineCharacters (const String& newLine) throw(); + + void newTransaction(); + + void undo(); + + void redo(); + + void clearUndoHistory(); + + UndoManager& getUndoManager() throw() { return undoManager; } + + void setSavePoint() throw(); + + bool hasChangedSinceSavePoint() const throw(); + + const Position findWordBreakAfter (const Position& position) const throw(); + + const Position findWordBreakBefore (const Position& position) const throw(); + + class JUCE_API Listener + { + public: + Listener() {} + virtual ~Listener() {} + + virtual void codeDocumentChanged (const Position& affectedTextStart, + const Position& affectedTextEnd) = 0; + }; + + void addListener (Listener* const listener) throw(); + + void removeListener (Listener* const listener) throw(); + + class Iterator + { + public: + Iterator (CodeDocument* const document) throw(); + Iterator (const Iterator& other); + const Iterator& operator= (const Iterator& other) throw(); + ~Iterator() throw(); + + juce_wchar nextChar() throw(); + + juce_wchar peekNextChar() const throw(); + + void skip() throw(); + + int getPosition() const throw() { return position; } + + void skipWhitespace(); + + void skipToEndOfLine(); + + int getLine() const throw() { return line; } + + bool isEOF() const throw(); + + private: + CodeDocument* document; + int line, position; + }; + + juce_UseDebuggingNewOperator private: - friend class CodeDocumentInsertAction; - friend class CodeDocumentDeleteAction; - friend class Iterator; - friend class Position; + friend class CodeDocumentInsertAction; + friend class CodeDocumentDeleteAction; + friend class Iterator; + friend class Position; - OwnedArray lines; - Array positionsToMaintain; - UndoManager undoManager; - int currentActionIndex, indexOfSavedState; - int maximumLineLength; - VoidArray listeners; - String newLineChars; + OwnedArray lines; + Array positionsToMaintain; + UndoManager undoManager; + int currentActionIndex, indexOfSavedState; + int maximumLineLength; + VoidArray listeners; + String newLineChars; - void sendListenerChangeMessage (const int startLine, const int endLine); + void sendListenerChangeMessage (const int startLine, const int endLine); - void insert (const String& text, const int insertPos, const bool undoable); - void remove (const int startPos, const int endPos, const bool undoable); + void insert (const String& text, const int insertPos, const bool undoable); + void remove (const int startPos, const int endPos, const bool undoable); - CodeDocument (const CodeDocument&); - const CodeDocument& operator= (const CodeDocument&); + CodeDocument (const CodeDocument&); + const CodeDocument& operator= (const CodeDocument&); }; #endif // __JUCE_CODEDOCUMENT_JUCEHEADER__ @@ -42357,38 +20157,19 @@ private: #ifndef __JUCE_CODETOKENISER_JUCEHEADER__ #define __JUCE_CODETOKENISER_JUCEHEADER__ -/** - A base class for tokenising code so that the syntax can be displayed in a - code editor. - - @see CodeDocument, CodeEditorComponent -*/ class JUCE_API CodeTokeniser { public: - CodeTokeniser() {} - virtual ~CodeTokeniser() {} + CodeTokeniser() {} + virtual ~CodeTokeniser() {} - /** Reads the next token from the source and returns its token type. + virtual int readNextToken (CodeDocument::Iterator& source) = 0; - This must leave the source pointing to the first character in the - next token. - */ - virtual int readNextToken (CodeDocument::Iterator& source) = 0; + virtual const StringArray getTokenTypes() = 0; - /** Returns a list of the names of the token types this analyser uses. + virtual const Colour getDefaultColour (const int tokenType) = 0; - The index in this list must match the token type numbers that are - returned by readNextToken(). - */ - virtual const StringArray getTokenTypes() = 0; - - /** Returns a suggested syntax highlighting colour for a specified - token type. - */ - virtual const Colour getDefaultColour (const int tokenType) = 0; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; #endif // __JUCE_CODETOKENISER_JUCEHEADER__ @@ -42396,252 +20177,164 @@ public: class CodeEditorLine; -/** - A text editor component designed specifically for source code. - - This is designed to handle syntax highlighting and fast editing of very large - files. -*/ class JUCE_API CodeEditorComponent : public Component, - public Timer, - public ScrollBarListener, - public CodeDocument::Listener, - public AsyncUpdater + public Timer, + public ScrollBarListener, + public CodeDocument::Listener, + public AsyncUpdater { public: - /** Creates an editor for a document. + CodeEditorComponent (CodeDocument& document, + CodeTokeniser* const codeTokeniser); - The tokeniser object is optional - pass 0 to disable syntax highlighting. - The object that you pass in is not owned or deleted by the editor - you must - make sure that it doesn't get deleted while this component is still using it. + ~CodeEditorComponent(); - @see CodeDocument - */ - CodeEditorComponent (CodeDocument& document, - CodeTokeniser* const codeTokeniser); + CodeDocument& getDocument() const throw() { return document; } - /** Destructor. */ - ~CodeEditorComponent(); + void loadContent (const String& newContent); - /** Returns the code document that this component is editing. */ - CodeDocument& getDocument() const throw() { return document; } + float getCharWidth() const throw() { return charWidth; } - /** Loads the given content into the document. - This will completely reset the CodeDocument object, clear its undo history, - and fill it with this text. - */ - void loadContent (const String& newContent); + int getLineHeight() const throw() { return lineHeight; } - /** Returns the standard character width. */ - float getCharWidth() const throw() { return charWidth; } + int getNumLinesOnScreen() const throw() { return linesOnScreen; } - /** Returns the height of a line of text, in pixels. */ - int getLineHeight() const throw() { return lineHeight; } + int getNumColumnsOnScreen() const throw() { return columnsOnScreen; } - /** Returns the number of whole lines visible on the screen, - This doesn't include a cut-off line that might be visible at the bottom if the - component's height isn't an exact multiple of the line-height. - */ - int getNumLinesOnScreen() const throw() { return linesOnScreen; } + const CodeDocument::Position getCaretPos() const { return caretPos; } - /** Returns the number of whole columns visible on the screen. - This doesn't include any cut-off columns at the right-hand edge. - */ - int getNumColumnsOnScreen() const throw() { return columnsOnScreen; } + void moveCaretTo (const CodeDocument::Position& newPos, const bool selecting); - /** Returns the current caret position. */ - const CodeDocument::Position getCaretPos() const { return caretPos; } + const Rectangle getCharacterBounds (const CodeDocument::Position& pos) const throw(); - /** Moves the caret. - If selecting is true, the section of the document between the current - caret position and the new one will become selected. If false, any currently - selected region will be deselected. - */ - void moveCaretTo (const CodeDocument::Position& newPos, const bool selecting); + const CodeDocument::Position getPositionAt (int x, int y); - /** Returns the on-screen position of a character in the document. - The rectangle returned is relative to this component's top-left origin. - */ - const Rectangle getCharacterBounds (const CodeDocument::Position& pos) const throw(); + void cursorLeft (const bool moveInWholeWordSteps, const bool selecting); + void cursorRight (const bool moveInWholeWordSteps, const bool selecting); + void cursorDown (const bool selecting); + void cursorUp (const bool selecting); - /** Finds the character at a given on-screen position. - The co-ordinates are relative to this component's top-left origin. - */ - const CodeDocument::Position getPositionAt (int x, int y); + void pageDown (const bool selecting); + void pageUp (const bool selecting); - void cursorLeft (const bool moveInWholeWordSteps, const bool selecting); - void cursorRight (const bool moveInWholeWordSteps, const bool selecting); - void cursorDown (const bool selecting); - void cursorUp (const bool selecting); + void scrollDown(); + void scrollUp(); + void scrollToLine (int newFirstLineOnScreen); + void scrollBy (int deltaLines); + void scrollToColumn (int newFirstColumnOnScreen); + void scrollToKeepCaretOnScreen(); - void pageDown (const bool selecting); - void pageUp (const bool selecting); + void goToStartOfDocument (const bool selecting); + void goToStartOfLine (const bool selecting); + void goToEndOfDocument (const bool selecting); + void goToEndOfLine (const bool selecting); - void scrollDown(); - void scrollUp(); - void scrollToLine (int newFirstLineOnScreen); - void scrollBy (int deltaLines); - void scrollToColumn (int newFirstColumnOnScreen); - void scrollToKeepCaretOnScreen(); + void deselectAll(); + void selectAll(); - void goToStartOfDocument (const bool selecting); - void goToStartOfLine (const bool selecting); - void goToEndOfDocument (const bool selecting); - void goToEndOfLine (const bool selecting); + void insertTextAtCaret (const String& textToInsert); + void insertTabAtCaret(); + void cut(); + void copy(); + void copyThenCut(); + void paste(); + void backspace (const bool moveInWholeWordSteps); + void deleteForward (const bool moveInWholeWordSteps); - void deselectAll(); - void selectAll(); + void undo(); + void redo(); - void insertTextAtCaret (const String& textToInsert); - void insertTabAtCaret(); - void cut(); - void copy(); - void copyThenCut(); - void paste(); - void backspace (const bool moveInWholeWordSteps); - void deleteForward (const bool moveInWholeWordSteps); + void setTabSize (const int numSpacesPerTab, + const bool insertSpacesInsteadOfTabCharacters) throw(); - void undo(); - void redo(); + int getTabSize() const throw() { return spacesPerTab; } - /** Changes the current tab settings. - This lets you change the tab size and whether pressing the tab key inserts a - tab character, or its equivalent number of spaces. - */ - void setTabSize (const int numSpacesPerTab, - const bool insertSpacesInsteadOfTabCharacters) throw(); + bool areSpacesInsertedForTabs() const { return useSpacesForTabs; } - /** Returns the current number of spaces per tab. - @see setTabSize - */ - int getTabSize() const throw() { return spacesPerTab; } + void setFont (const Font& newFont); - /** Returns true if the tab key will insert spaces instead of actual tab characters. - @see setTabSize - */ - bool areSpacesInsertedForTabs() const { return useSpacesForTabs; } + void resetToDefaultColours(); - /** Changes the font. - Make sure you only use a fixed-width font, or this component will look pretty nasty! - */ - void setFont (const Font& newFont); + void setColourForTokenType (const int tokenType, const Colour& colour); - /** Resets the syntax highlighting colours to the default ones provided by the - code tokeniser. - @see CodeTokeniser::getDefaultColour - */ - void resetToDefaultColours(); + const Colour getColourForTokenType (const int tokenType) const throw(); - /** Changes one of the syntax highlighting colours. - The token type values are dependent on the tokeniser being used - use - CodeTokeniser::getTokenTypes() to get a list of the token types. - @see getColourForTokenType - */ - void setColourForTokenType (const int tokenType, const Colour& colour); + enum ColourIds + { + backgroundColourId = 0x1004500, /**< A colour to use to fill the editor's background. */ + caretColourId = 0x1004501, /**< The colour to draw the caret. */ + highlightColourId = 0x1004502, /**< The colour to use for the highlighted background under + selected text. */ + defaultTextColourId = 0x1004503 /**< The colour to use for text when no syntax colouring is + enabled. */ + }; - /** Returns one of the syntax highlighting colours. - The token type values are dependent on the tokeniser being used - use - CodeTokeniser::getTokenTypes() to get a list of the token types. - @see setColourForTokenType - */ - const Colour getColourForTokenType (const int tokenType) const throw(); + void setScrollbarThickness (const int thickness) throw(); - /** A set of colour IDs to use to change the colour of various aspects of the editor. + void resized(); + void paint (Graphics& g); + bool keyPressed (const KeyPress& key); + void mouseDown (const MouseEvent& e); + void mouseDrag (const MouseEvent& e); + void mouseUp (const MouseEvent& e); + void mouseDoubleClick (const MouseEvent& e); + void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); + void timerCallback(); + void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, const double newRangeStart); + void handleAsyncUpdate(); + void codeDocumentChanged (const CodeDocument::Position& affectedTextStart, + const CodeDocument::Position& affectedTextEnd); - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1004500, /**< A colour to use to fill the editor's background. */ - caretColourId = 0x1004501, /**< The colour to draw the caret. */ - highlightColourId = 0x1004502, /**< The colour to use for the highlighted background under - selected text. */ - defaultTextColourId = 0x1004503 /**< The colour to use for text when no syntax colouring is - enabled. */ - }; - - /** Changes the size of the scrollbars. */ - void setScrollbarThickness (const int thickness) throw(); - - /** @internal */ - void resized(); - /** @internal */ - void paint (Graphics& g); - /** @internal */ - bool keyPressed (const KeyPress& key); - /** @internal */ - void mouseDown (const MouseEvent& e); - /** @internal */ - void mouseDrag (const MouseEvent& e); - /** @internal */ - void mouseUp (const MouseEvent& e); - /** @internal */ - void mouseDoubleClick (const MouseEvent& e); - /** @internal */ - void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); - /** @internal */ - void timerCallback(); - /** @internal */ - void scrollBarMoved (ScrollBar* scrollBarThatHasMoved, const double newRangeStart); - /** @internal */ - void handleAsyncUpdate(); - /** @internal */ - void codeDocumentChanged (const CodeDocument::Position& affectedTextStart, - const CodeDocument::Position& affectedTextEnd); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - CodeDocument& document; + CodeDocument& document; - Font font; - int firstLineOnScreen, gutter, spacesPerTab; - float charWidth; - int lineHeight, linesOnScreen, columnsOnScreen; - int scrollbarThickness; - bool useSpacesForTabs; - double xOffset; + Font font; + int firstLineOnScreen, gutter, spacesPerTab; + float charWidth; + int lineHeight, linesOnScreen, columnsOnScreen; + int scrollbarThickness; + bool useSpacesForTabs; + double xOffset; - CodeDocument::Position caretPos; - CodeDocument::Position selectionStart, selectionEnd; - Component* caret; - ScrollBar* verticalScrollBar; - ScrollBar* horizontalScrollBar; + CodeDocument::Position caretPos; + CodeDocument::Position selectionStart, selectionEnd; + Component* caret; + ScrollBar* verticalScrollBar; + ScrollBar* horizontalScrollBar; - enum DragType - { - notDragging, - draggingSelectionStart, - draggingSelectionEnd - }; + enum DragType + { + notDragging, + draggingSelectionStart, + draggingSelectionEnd + }; - DragType dragType; + DragType dragType; - CodeTokeniser* codeTokeniser; - Array coloursForTokenCategories; + CodeTokeniser* codeTokeniser; + Array coloursForTokenCategories; - OwnedArray lines; - void rebuildLineTokens(); + OwnedArray lines; + void rebuildLineTokens(); - OwnedArray cachedIterators; - void clearCachedIterators (const int firstLineToBeInvalid) throw(); - void updateCachedIterators (int maxLineNum); - void getIteratorForPosition (int position, CodeDocument::Iterator& result); + OwnedArray cachedIterators; + void clearCachedIterators (const int firstLineToBeInvalid) throw(); + void updateCachedIterators (int maxLineNum); + void getIteratorForPosition (int position, CodeDocument::Iterator& result); - void updateScrollBars(); - void scrollToLineInternal (int line); - void scrollToColumnInternal (double column); - void newTransaction(); + void updateScrollBars(); + void scrollToLineInternal (int line); + void scrollToColumnInternal (double column); + void newTransaction(); - int indexToColumn (int line, int index) const throw(); - int columnToIndex (int line, int column) const throw(); + int indexToColumn (int line, int index) const throw(); + int columnToIndex (int line, int column) const throw(); - CodeEditorComponent (const CodeEditorComponent&); - const CodeEditorComponent& operator= (const CodeEditorComponent&); + CodeEditorComponent (const CodeEditorComponent&); + const CodeEditorComponent& operator= (const CodeEditorComponent&); }; #endif // __JUCE_CODEEDITORCOMPONENT_JUCEHEADER__ @@ -42657,38 +20350,33 @@ private: #ifndef __JUCE_CPLUSPLUSCODETOKENISER_JUCEHEADER__ #define __JUCE_CPLUSPLUSCODETOKENISER_JUCEHEADER__ -/** - A simple lexical analyser for syntax colouring of C++ code. - - @see SyntaxAnalyser, CodeEditorComponent, CodeDocument -*/ -class JUCE_API CPlusPlusCodeTokeniser : public CodeTokeniser +class JUCE_API CPlusPlusCodeTokeniser : public CodeTokeniser { public: - CPlusPlusCodeTokeniser(); - ~CPlusPlusCodeTokeniser(); + CPlusPlusCodeTokeniser(); + ~CPlusPlusCodeTokeniser(); - enum TokenType - { - tokenType_error = 0, - tokenType_comment, - tokenType_builtInKeyword, - tokenType_identifier, - tokenType_integerLiteral, - tokenType_floatLiteral, - tokenType_stringLiteral, - tokenType_operator, - tokenType_bracket, - tokenType_punctuation, - tokenType_preprocessor - }; + enum TokenType + { + tokenType_error = 0, + tokenType_comment, + tokenType_builtInKeyword, + tokenType_identifier, + tokenType_integerLiteral, + tokenType_floatLiteral, + tokenType_stringLiteral, + tokenType_operator, + tokenType_bracket, + tokenType_punctuation, + tokenType_preprocessor + }; - int readNextToken (CodeDocument::Iterator& source); - const StringArray getTokenTypes(); - const Colour getDefaultColour (const int tokenType); + int readNextToken (CodeDocument::Iterator& source); + const StringArray getTokenTypes(); + const Colour getDefaultColour (const int tokenType); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator }; #endif // __JUCE_CPLUSPLUSCODETOKENISER_JUCEHEADER__ @@ -42710,89 +20398,46 @@ public: #ifndef __JUCE_PROGRESSBAR_JUCEHEADER__ #define __JUCE_PROGRESSBAR_JUCEHEADER__ -/** - A progress bar component. - - To use this, just create one and make it visible. It'll run its own timer - to keep an eye on a variable that you give it, and will automatically - redraw itself when the variable changes. - - For an easy way of running a background task with a dialog box showing its - progress, see the ThreadWithProgressWindow class. - - @see ThreadWithProgressWindow -*/ class JUCE_API ProgressBar : public Component, - public SettableTooltipClient, - private Timer + public SettableTooltipClient, + private Timer { public: - /** Creates a ProgressBar. + ProgressBar (double& progress); - @param progress pass in a reference to a double that you're going to - update with your task's progress. The ProgressBar will - monitor the value of this variable and will redraw itself - when the value changes. The range is from 0 to 1.0. Obviously - you'd better be careful not to delete this variable while the - ProgressBar still exists! - */ - ProgressBar (double& progress); + ~ProgressBar(); - /** Destructor. */ - ~ProgressBar(); + void setPercentageDisplay (const bool shouldDisplayPercentage); - /** Turns the percentage display on or off. + void setTextToDisplay (const String& text); - By default this is on, and the progress bar will display a text string showing - its current percentage. - */ - void setPercentageDisplay (const bool shouldDisplayPercentage); + enum ColourIds + { + backgroundColourId = 0x1001900, /**< The background colour, behind the bar. */ + foregroundColourId = 0x1001a00, /**< The colour to use to draw the bar itself. LookAndFeel + classes will probably use variations on this colour. */ + }; - /** Gives the progress bar a string to display inside it. - - If you call this, it will turn off the percentage display. - @see setPercentageDisplay - */ - void setTextToDisplay (const String& text); - - /** A set of colour IDs to use to change the colour of various aspects of the bar. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1001900, /**< The background colour, behind the bar. */ - foregroundColourId = 0x1001a00, /**< The colour to use to draw the bar itself. LookAndFeel - classes will probably use variations on this colour. */ - }; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void lookAndFeelChanged(); - /** @internal */ - void visibilityChanged(); - /** @internal */ - void colourChanged(); + void paint (Graphics& g); + void lookAndFeelChanged(); + void visibilityChanged(); + void colourChanged(); private: - double& progress; - double currentValue; - bool displayPercentage; - String displayedMessage, currentMessage; - uint32 lastCallbackTime; + double& progress; + double currentValue; + bool displayPercentage; + String displayedMessage, currentMessage; + uint32 lastCallbackTime; - void timerCallback(); + void timerCallback(); - ProgressBar (const ProgressBar&); - const ProgressBar& operator= (const ProgressBar&); + ProgressBar (const ProgressBar&); + const ProgressBar& operator= (const ProgressBar&); }; #endif // __JUCE_PROGRESSBAR_JUCEHEADER__ @@ -42811,788 +20456,302 @@ private: class Slider; -/** - A class for receiving callbacks from a Slider. - - To be told when a slider's value changes, you can register a SliderListener - object using Slider::addListener(). - - @see Slider::addListener, Slider::removeListener -*/ class JUCE_API SliderListener { public: - /** Destructor. */ - virtual ~SliderListener() {} + virtual ~SliderListener() {} - /** Called when the slider's value is changed. + virtual void sliderValueChanged (Slider* slider) = 0; - This may be caused by dragging it, or by typing in its text entry box, - or by a call to Slider::setValue(). + virtual void sliderDragStarted (Slider* slider); - You can find out the new value using Slider::getValue(). - - @see Slider::valueChanged - */ - virtual void sliderValueChanged (Slider* slider) = 0; - - /** Called when the slider is about to be dragged. - - This is called when a drag begins, then it's followed by multiple calls - to sliderValueChanged(), and then sliderDragEnded() is called after the - user lets go. - - @see sliderDragEnded, Slider::startedDragging - */ - virtual void sliderDragStarted (Slider* slider); - - /** Called after a drag operation has finished. - - @see sliderDragStarted, Slider::stoppedDragging - */ - virtual void sliderDragEnded (Slider* slider); + virtual void sliderDragEnded (Slider* slider); }; #endif // __JUCE_SLIDERLISTENER_JUCEHEADER__ /********* End of inlined file: juce_SliderListener.h *********/ -/** - A slider control for changing a value. - - The slider can be horizontal, vertical, or rotary, and can optionally have - a text-box inside it to show an editable display of the current value. - - To use it, create a Slider object and use the setSliderStyle() method - to set up the type you want. To set up the text-entry box, use setTextBoxStyle(). - - To define the values that it can be set to, see the setRange() and setValue() methods. - - There are also lots of custom tweaks you can do by subclassing and overriding - some of the virtual methods, such as changing the scaling, changing the format of - the text display, custom ways of limiting the values, etc. - - You can register SliderListeners with a slider, which will be informed when the value - changes, or a subclass can override valueChanged() to be informed synchronously. - - @see SliderListener -*/ class JUCE_API Slider : public Component, - public SettableTooltipClient, - private AsyncUpdater, - private ButtonListener, - private LabelListener, - private Value::Listener + public SettableTooltipClient, + private AsyncUpdater, + private ButtonListener, + private LabelListener, + private Value::Listener { public: - /** Creates a slider. - - When created, you'll need to set up the slider's style and range with setSliderStyle(), - setRange(), etc. - */ - Slider (const String& componentName); - - /** Destructor. */ - ~Slider(); - - /** The types of slider available. - - @see setSliderStyle, setRotaryParameters - */ - enum SliderStyle - { - LinearHorizontal, /**< A traditional horizontal slider. */ - LinearVertical, /**< A traditional vertical slider. */ - LinearBar, /**< A horizontal bar slider with the text label drawn on top of it. */ - Rotary, /**< A rotary control that you move by dragging the mouse in a circular motion, like a knob. - @see setRotaryParameters */ - RotaryHorizontalDrag, /**< A rotary control that you move by dragging the mouse left-to-right. - @see setRotaryParameters */ - RotaryVerticalDrag, /**< A rotary control that you move by dragging the mouse up-and-down. - @see setRotaryParameters */ - IncDecButtons, /**< A pair of buttons that increment or decrement the slider's value by the increment set in setRange(). */ - - TwoValueHorizontal, /**< A horizontal slider that has two thumbs instead of one, so it can show a minimum and maximum value. - @see setMinValue, setMaxValue */ - TwoValueVertical, /**< A vertical slider that has two thumbs instead of one, so it can show a minimum and maximum value. - @see setMinValue, setMaxValue */ - - ThreeValueHorizontal, /**< A horizontal slider that has three thumbs instead of one, so it can show a minimum and maximum - value, with the current value being somewhere between them. - @see setMinValue, setMaxValue */ - ThreeValueVertical, /**< A vertical slider that has three thumbs instead of one, so it can show a minimum and maximum - value, with the current value being somewhere between them. - @see setMinValue, setMaxValue */ - }; - - /** Changes the type of slider interface being used. - - @param newStyle the type of interface - @see setRotaryParameters, setVelocityBasedMode, - */ - void setSliderStyle (const SliderStyle newStyle); - - /** Returns the slider's current style. - - @see setSliderStyle - */ - SliderStyle getSliderStyle() const { return style; } - - /** Changes the properties of a rotary slider. - - @param startAngleRadians the angle (in radians, clockwise from the top) at which - the slider's minimum value is represented - @param endAngleRadians the angle (in radians, clockwise from the top) at which - the slider's maximum value is represented. This must be - greater than startAngleRadians - @param stopAtEnd if true, then when the slider is dragged around past the - minimum or maximum, it'll stop there; if false, it'll wrap - back to the opposite value - */ - void setRotaryParameters (const float startAngleRadians, - const float endAngleRadians, - const bool stopAtEnd); - - /** Sets the distance the mouse has to move to drag the slider across - the full extent of its range. - - This only applies when in modes like RotaryHorizontalDrag, where it's using - relative mouse movements to adjust the slider. - */ - void setMouseDragSensitivity (const int distanceForFullScaleDrag); - - /** Changes the way the the mouse is used when dragging the slider. - - If true, this will turn on velocity-sensitive dragging, so that - the faster the mouse moves, the bigger the movement to the slider. This - helps when making accurate adjustments if the slider's range is quite large. - - If false, the slider will just try to snap to wherever the mouse is. - */ - void setVelocityBasedMode (const bool isVelocityBased); - - /** Returns true if velocity-based mode is active. - @see setVelocityBasedMode - */ - bool getVelocityBasedMode() const { return isVelocityBased; } - - /** Changes aspects of the scaling used when in velocity-sensitive mode. - - These apply when you've used setVelocityBasedMode() to turn on velocity mode, - or if you're holding down ctrl. - - @param sensitivity higher values than 1.0 increase the range of acceleration used - @param threshold the minimum number of pixels that the mouse needs to move for it - to be treated as a movement - @param offset values greater than 0.0 increase the minimum speed that will be used when - the threshold is reached - @param userCanPressKeyToSwapMode if true, then the user can hold down the ctrl or command - key to toggle velocity-sensitive mode - */ - void setVelocityModeParameters (const double sensitivity = 1.0, - const int threshold = 1, - const double offset = 0.0, - const bool userCanPressKeyToSwapMode = true); - - /** Returns the velocity sensitivity setting. - @see setVelocityModeParameters - */ - double getVelocitySensitivity() const { return velocityModeSensitivity; } - - /** Returns the velocity threshold setting. - @see setVelocityModeParameters - */ - int getVelocityThreshold() const { return velocityModeThreshold; } - - /** Returns the velocity offset setting. - @see setVelocityModeParameters - */ - double getVelocityOffset() const { return velocityModeOffset; } - - /** Returns the velocity user key setting. - @see setVelocityModeParameters - */ - bool getVelocityModeIsSwappable() const { return userKeyOverridesVelocity; } - - /** Sets up a skew factor to alter the way values are distributed. - - You may want to use a range of values on the slider where more accuracy - is required towards one end of the range, so this will logarithmically - spread the values across the length of the slider. - - If the factor is < 1.0, the lower end of the range will fill more of the - slider's length; if the factor is > 1.0, the upper end of the range - will be expanded instead. A factor of 1.0 doesn't skew it at all. - - To set the skew position by using a mid-point, use the setSkewFactorFromMidPoint() - method instead. - - @see getSkewFactor, setSkewFactorFromMidPoint - */ - void setSkewFactor (const double factor); - - /** Sets up a skew factor to alter the way values are distributed. - - This allows you to specify the slider value that should appear in the - centre of the slider's visible range. - - @see setSkewFactor, getSkewFactor - */ - void setSkewFactorFromMidPoint (const double sliderValueToShowAtMidPoint); - - /** Returns the current skew factor. - - See setSkewFactor for more info. - - @see setSkewFactor, setSkewFactorFromMidPoint - */ - double getSkewFactor() const { return skewFactor; } - - /** Used by setIncDecButtonsMode(). - */ - enum IncDecButtonMode - { - incDecButtonsNotDraggable, - incDecButtonsDraggable_AutoDirection, - incDecButtonsDraggable_Horizontal, - incDecButtonsDraggable_Vertical - }; - - /** When the style is IncDecButtons, this lets you turn on a mode where the mouse - can be dragged on the buttons to drag the values. - - By default this is turned off. When enabled, clicking on the buttons still works - them as normal, but by holding down the mouse on a button and dragging it a little - distance, it flips into a mode where the value can be dragged. The drag direction can - either be set explicitly to be vertical or horizontal, or can be set to - incDecButtonsDraggable_AutoDirection so that it depends on whether the buttons - are side-by-side or above each other. - */ - void setIncDecButtonsMode (const IncDecButtonMode mode); - - /** The position of the slider's text-entry box. - - @see setTextBoxStyle - */ - enum TextEntryBoxPosition - { - NoTextBox, /**< Doesn't display a text box. */ - TextBoxLeft, /**< Puts the text box to the left of the slider, vertically centred. */ - TextBoxRight, /**< Puts the text box to the right of the slider, vertically centred. */ - TextBoxAbove, /**< Puts the text box above the slider, horizontally centred. */ - TextBoxBelow /**< Puts the text box below the slider, horizontally centred. */ - }; - - /** Changes the location and properties of the text-entry box. - - @param newPosition where it should go (or NoTextBox to not have one at all) - @param isReadOnly if true, it's a read-only display - @param textEntryBoxWidth the width of the text-box in pixels. Make sure this leaves enough - room for the slider as well! - @param textEntryBoxHeight the height of the text-box in pixels. Make sure this leaves enough - room for the slider as well! - - @see setTextBoxIsEditable, getValueFromText, getTextFromValue - */ - void setTextBoxStyle (const TextEntryBoxPosition newPosition, - const bool isReadOnly, - const int textEntryBoxWidth, - const int textEntryBoxHeight); - - /** Returns the status of the text-box. - @see setTextBoxStyle - */ - const TextEntryBoxPosition getTextBoxPosition() const { return textBoxPos; } - - /** Returns the width used for the text-box. - @see setTextBoxStyle - */ - int getTextBoxWidth() const { return textBoxWidth; } - - /** Returns the height used for the text-box. - @see setTextBoxStyle - */ - int getTextBoxHeight() const { return textBoxHeight; } - - /** Makes the text-box editable. - - By default this is true, and the user can enter values into the textbox, - but it can be turned off if that's not suitable. - - @see setTextBoxStyle, getValueFromText, getTextFromValue - */ - void setTextBoxIsEditable (const bool shouldBeEditable); - - /** Returns true if the text-box is read-only. - @see setTextBoxStyle - */ - bool isTextBoxEditable() const { return editableText; } - - /** If the text-box is editable, this will give it the focus so that the user can - type directly into it. - - This is basically the effect as the user clicking on it. - */ - void showTextBox(); - - /** If the text-box currently has focus and is being edited, this resets it and takes keyboard - focus away from it. - - @param discardCurrentEditorContents if true, the slider's value will be left - unchanged; if false, the current contents of the - text editor will be used to set the slider position - before it is hidden. - */ - void hideTextBox (const bool discardCurrentEditorContents); - - /** Changes the slider's current value. - - This will trigger a callback to SliderListener::sliderValueChanged() for any listeners - that are registered, and will synchronously call the valueChanged() method in case subclasses - want to handle it. - - @param newValue the new value to set - this will be restricted by the - minimum and maximum range, and will be snapped to the - nearest interval if one has been set - @param sendUpdateMessage if false, a change to the value will not trigger a call to - any SliderListeners or the valueChanged() method - @param sendMessageSynchronously if true, then a call to the SliderListeners will be made - synchronously; if false, it will be asynchronous - */ - void setValue (double newValue, - const bool sendUpdateMessage = true, - const bool sendMessageSynchronously = false); - - /** Returns the slider's current value. */ - double getValue() const; - - /** Returns the Value object that represents the slider's current position. - You can use this Value object to connect the slider's position to external values or setters, - either by taking a copy of the Value, or by using Value::referTo() to make it point to - your own Value object. - @see Value, getMaxValue, getMinValueObject - */ - Value& getValueObject() { return currentValue; } - - /** Sets the limits that the slider's value can take. - - @param newMinimum the lowest value allowed - @param newMaximum the highest value allowed - @param newInterval the steps in which the value is allowed to increase - if this - is not zero, the value will always be (newMinimum + (newInterval * an integer)). - */ - void setRange (const double newMinimum, - const double newMaximum, - const double newInterval = 0); - - /** Returns the current maximum value. - @see setRange - */ - double getMaximum() const { return maximum; } - - /** Returns the current minimum value. - @see setRange - */ - double getMinimum() const { return minimum; } - - /** Returns the current step-size for values. - @see setRange - */ - double getInterval() const { return interval; } - - /** For a slider with two or three thumbs, this returns the lower of its values. - - For a two-value slider, the values are controlled with getMinValue() and getMaxValue(). - A slider with three values also uses the normal getValue() and setValue() methods to - control the middle value. - - @see setMinValue, getMaxValue, TwoValueHorizontal, TwoValueVertical, ThreeValueHorizontal, ThreeValueVertical - */ - double getMinValue() const; - - /** For a slider with two or three thumbs, this returns the lower of its values. - You can use this Value object to connect the slider's position to external values or setters, - either by taking a copy of the Value, or by using Value::referTo() to make it point to - your own Value object. - @see Value, getMinValue, getMaxValueObject - */ - Value& getMinValueObject() { return valueMin; } - - /** For a slider with two or three thumbs, this sets the lower of its values. - - This will trigger a callback to SliderListener::sliderValueChanged() for any listeners - that are registered, and will synchronously call the valueChanged() method in case subclasses - want to handle it. - - @param newValue the new value to set - this will be restricted by the - minimum and maximum range, and will be snapped to the nearest - interval if one has been set. - @param sendUpdateMessage if false, a change to the value will not trigger a call to - any SliderListeners or the valueChanged() method - @param sendMessageSynchronously if true, then a call to the SliderListeners will be made - synchronously; if false, it will be asynchronous - @param allowNudgingOfOtherValues if false, this value will be restricted to being below the - max value (in a two-value slider) or the mid value (in a three-value - slider). If false, then if this value goes beyond those values, - it will push them along with it. - @see getMinValue, setMaxValue, setValue - */ - void setMinValue (double newValue, - const bool sendUpdateMessage = true, - const bool sendMessageSynchronously = false, - const bool allowNudgingOfOtherValues = false); - - /** For a slider with two or three thumbs, this returns the higher of its values. - - For a two-value slider, the values are controlled with getMinValue() and getMaxValue(). - A slider with three values also uses the normal getValue() and setValue() methods to - control the middle value. - - @see getMinValue, TwoValueHorizontal, TwoValueVertical, ThreeValueHorizontal, ThreeValueVertical - */ - double getMaxValue() const; - - /** For a slider with two or three thumbs, this returns the higher of its values. - You can use this Value object to connect the slider's position to external values or setters, - either by taking a copy of the Value, or by using Value::referTo() to make it point to - your own Value object. - @see Value, getMaxValue, getMinValueObject - */ - Value& getMaxValueObject() { return valueMax; } - - /** For a slider with two or three thumbs, this sets the lower of its values. - - This will trigger a callback to SliderListener::sliderValueChanged() for any listeners - that are registered, and will synchronously call the valueChanged() method in case subclasses - want to handle it. - - @param newValue the new value to set - this will be restricted by the - minimum and maximum range, and will be snapped to the nearest - interval if one has been set. - @param sendUpdateMessage if false, a change to the value will not trigger a call to - any SliderListeners or the valueChanged() method - @param sendMessageSynchronously if true, then a call to the SliderListeners will be made - synchronously; if false, it will be asynchronous - @param allowNudgingOfOtherValues if false, this value will be restricted to being above the - min value (in a two-value slider) or the mid value (in a three-value - slider). If false, then if this value goes beyond those values, - it will push them along with it. - @see getMaxValue, setMinValue, setValue - */ - void setMaxValue (double newValue, - const bool sendUpdateMessage = true, - const bool sendMessageSynchronously = false, - const bool allowNudgingOfOtherValues = false); - - /** Adds a listener to be called when this slider's value changes. */ - void addListener (SliderListener* const listener); - - /** Removes a previously-registered listener. */ - void removeListener (SliderListener* const listener); - - /** This lets you choose whether double-clicking moves the slider to a given position. - - By default this is turned off, but it's handy if you want a double-click to act - as a quick way of resetting a slider. Just pass in the value you want it to - go to when double-clicked. - - @see getDoubleClickReturnValue - */ - void setDoubleClickReturnValue (const bool isDoubleClickEnabled, - const double valueToSetOnDoubleClick); - - /** Returns the values last set by setDoubleClickReturnValue() method. - - Sets isEnabled to true if double-click is enabled, and returns the value - that was set. - - @see setDoubleClickReturnValue - */ - double getDoubleClickReturnValue (bool& isEnabled) const; - - /** Tells the slider whether to keep sending change messages while the user - is dragging the slider. - - If set to true, a change message will only be sent when the user has - dragged the slider and let go. If set to false (the default), then messages - will be continuously sent as they drag it while the mouse button is still - held down. - */ - void setChangeNotificationOnlyOnRelease (const bool onlyNotifyOnRelease); - - /** This lets you change whether the slider thumb jumps to the mouse position - when you click. - - By default, this is true. If it's false, then the slider moves with relative - motion when you drag it. - - This only applies to linear bars, and won't affect two- or three- value - sliders. - */ - void setSliderSnapsToMousePosition (const bool shouldSnapToMouse); - - /** If enabled, this gives the slider a pop-up bubble which appears while the - slider is being dragged. - - This can be handy if your slider doesn't have a text-box, so that users can - see the value just when they're changing it. - - If you pass a component as the parentComponentToUse parameter, the pop-up - bubble will be added as a child of that component when it's needed. If you - pass 0, the pop-up will be placed on the desktop instead (note that it's a - transparent window, so if you're using an OS that can't do transparent windows - you'll have to add it to a parent component instead). - */ - void setPopupDisplayEnabled (const bool isEnabled, - Component* const parentComponentToUse); - - /** If this is set to true, then right-clicking on the slider will pop-up - a menu to let the user change the way it works. - - By default this is turned off, but when turned on, the menu will include - things like velocity sensitivity, and for rotary sliders, whether they - use a linear or rotary mouse-drag to move them. - */ - void setPopupMenuEnabled (const bool menuEnabled); - - /** This can be used to stop the mouse scroll-wheel from moving the slider. + Slider (const String& componentName); - By default it's enabled. - */ - void setScrollWheelEnabled (const bool enabled); + ~Slider(); - /** Returns a number to indicate which thumb is currently being dragged by the - mouse. - - This will return 0 for the main thumb, 1 for the minimum-value thumb, 2 for - the maximum-value thumb, or -1 if none is currently down. - */ - int getThumbBeingDragged() const { return sliderBeingDragged; } + enum SliderStyle + { + LinearHorizontal, /**< A traditional horizontal slider. */ + LinearVertical, /**< A traditional vertical slider. */ + LinearBar, /**< A horizontal bar slider with the text label drawn on top of it. */ + Rotary, /**< A rotary control that you move by dragging the mouse in a circular motion, like a knob. + @see setRotaryParameters */ + RotaryHorizontalDrag, /**< A rotary control that you move by dragging the mouse left-to-right. + @see setRotaryParameters */ + RotaryVerticalDrag, /**< A rotary control that you move by dragging the mouse up-and-down. + @see setRotaryParameters */ + IncDecButtons, /**< A pair of buttons that increment or decrement the slider's value by the increment set in setRange(). */ - /** Callback to indicate that the user is about to start dragging the slider. + TwoValueHorizontal, /**< A horizontal slider that has two thumbs instead of one, so it can show a minimum and maximum value. + @see setMinValue, setMaxValue */ + TwoValueVertical, /**< A vertical slider that has two thumbs instead of one, so it can show a minimum and maximum value. + @see setMinValue, setMaxValue */ - @see SliderListener::sliderDragStarted - */ - virtual void startedDragging(); + ThreeValueHorizontal, /**< A horizontal slider that has three thumbs instead of one, so it can show a minimum and maximum + value, with the current value being somewhere between them. + @see setMinValue, setMaxValue */ + ThreeValueVertical, /**< A vertical slider that has three thumbs instead of one, so it can show a minimum and maximum + value, with the current value being somewhere between them. + @see setMinValue, setMaxValue */ + }; - /** Callback to indicate that the user has just stopped dragging the slider. + void setSliderStyle (const SliderStyle newStyle); - @see SliderListener::sliderDragEnded - */ - virtual void stoppedDragging(); + SliderStyle getSliderStyle() const { return style; } - /** Callback to indicate that the user has just moved the slider. + void setRotaryParameters (const float startAngleRadians, + const float endAngleRadians, + const bool stopAtEnd); - @see SliderListener::sliderValueChanged - */ - virtual void valueChanged(); + void setMouseDragSensitivity (const int distanceForFullScaleDrag); - /** Callback to indicate that the user has just moved the slider. - Note - the valueChanged() method has changed its format and now no longer has - any parameters. Update your code to use the new version. - This version has been left here with an int as its return value to cause - a syntax error if you've got existing code that uses the old version. - */ - virtual int valueChanged (double) { jassertfalse; return 0; } + void setVelocityBasedMode (const bool isVelocityBased); - /** Subclasses can override this to convert a text string to a value. + bool getVelocityBasedMode() const { return isVelocityBased; } - When the user enters something into the text-entry box, this method is - called to convert it to a value. + void setVelocityModeParameters (const double sensitivity = 1.0, + const int threshold = 1, + const double offset = 0.0, + const bool userCanPressKeyToSwapMode = true); - The default routine just tries to convert it to a double. + double getVelocitySensitivity() const { return velocityModeSensitivity; } - @see getTextFromValue - */ - virtual double getValueFromText (const String& text); + int getVelocityThreshold() const { return velocityModeThreshold; } - /** Turns the slider's current value into a text string. + double getVelocityOffset() const { return velocityModeOffset; } - Subclasses can override this to customise the formatting of the text-entry box. + bool getVelocityModeIsSwappable() const { return userKeyOverridesVelocity; } - The default implementation just turns the value into a string, using - a number of decimal places based on the range interval. If a suffix string - has been set using setTextValueSuffix(), this will be appended to the text. - - @see getValueFromText - */ - virtual const String getTextFromValue (double value); + void setSkewFactor (const double factor); - /** Sets a suffix to append to the end of the numeric value when it's displayed as - a string. + void setSkewFactorFromMidPoint (const double sliderValueToShowAtMidPoint); - This is used by the default implementation of getTextFromValue(), and is just - appended to the numeric value. For more advanced formatting, you can override - getTextFromValue() and do something else. - */ - void setTextValueSuffix (const String& suffix); + double getSkewFactor() const { return skewFactor; } - /** Allows a user-defined mapping of distance along the slider to its value. + enum IncDecButtonMode + { + incDecButtonsNotDraggable, + incDecButtonsDraggable_AutoDirection, + incDecButtonsDraggable_Horizontal, + incDecButtonsDraggable_Vertical + }; - The default implementation for this performs the skewing operation that - can be set up in the setSkewFactor() method. Override it if you need - some kind of custom mapping instead, but make sure you also implement the - inverse function in valueToProportionOfLength(). + void setIncDecButtonsMode (const IncDecButtonMode mode); - @param proportion a value 0 to 1.0, indicating a distance along the slider - @returns the slider value that is represented by this position - @see valueToProportionOfLength - */ - virtual double proportionOfLengthToValue (double proportion); + enum TextEntryBoxPosition + { + NoTextBox, /**< Doesn't display a text box. */ + TextBoxLeft, /**< Puts the text box to the left of the slider, vertically centred. */ + TextBoxRight, /**< Puts the text box to the right of the slider, vertically centred. */ + TextBoxAbove, /**< Puts the text box above the slider, horizontally centred. */ + TextBoxBelow /**< Puts the text box below the slider, horizontally centred. */ + }; - /** Allows a user-defined mapping of value to the position of the slider along its length. + void setTextBoxStyle (const TextEntryBoxPosition newPosition, + const bool isReadOnly, + const int textEntryBoxWidth, + const int textEntryBoxHeight); - The default implementation for this performs the skewing operation that - can be set up in the setSkewFactor() method. Override it if you need - some kind of custom mapping instead, but make sure you also implement the - inverse function in proportionOfLengthToValue(). + const TextEntryBoxPosition getTextBoxPosition() const { return textBoxPos; } - @param value a valid slider value, between the range of values specified in - setRange() - @returns a value 0 to 1.0 indicating the distance along the slider that - represents this value - @see proportionOfLengthToValue - */ - virtual double valueToProportionOfLength (double value); + int getTextBoxWidth() const { return textBoxWidth; } - /** Returns the X or Y coordinate of a value along the slider's length. + int getTextBoxHeight() const { return textBoxHeight; } - If the slider is horizontal, this will be the X coordinate of the given - value, relative to the left of the slider. If it's vertical, then this will - be the Y coordinate, relative to the top of the slider. + void setTextBoxIsEditable (const bool shouldBeEditable); - If the slider is rotary, this will throw an assertion and return 0. If the - value is out-of-range, it will be constrained to the length of the slider. - */ - float getPositionOfValue (const double value); + bool isTextBoxEditable() const { return editableText; } - /** This can be overridden to allow the slider to snap to user-definable values. + void showTextBox(); - If overridden, it will be called when the user tries to move the slider to - a given position, and allows a subclass to sanity-check this value, possibly - returning a different value to use instead. + void hideTextBox (const bool discardCurrentEditorContents); - @param attemptedValue the value the user is trying to enter - @param userIsDragging true if the user is dragging with the mouse; false if - they are entering the value using the text box - @returns the value to use instead - */ - virtual double snapValue (double attemptedValue, const bool userIsDragging); + void setValue (double newValue, + const bool sendUpdateMessage = true, + const bool sendMessageSynchronously = false); - /** This can be called to force the text box to update its contents. + double getValue() const; - (Not normally needed, as this is done automatically). - */ - void updateText(); - - /** True if the slider moves horizontally. */ - bool isHorizontal() const; - /** True if the slider moves vertically. */ - bool isVertical() const; - - /** A set of colour IDs to use to change the colour of various aspects of the slider. + Value& getValueObject() { return currentValue; } - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. + void setRange (const double newMinimum, + const double newMaximum, + const double newInterval = 0); - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1001200, /**< A colour to use to fill the slider's background. */ - thumbColourId = 0x1001300, /**< The colour to draw the thumb with. It's up to the look - and feel class how this is used. */ - trackColourId = 0x1001310, /**< The colour to draw the groove that the thumb moves along. */ - rotarySliderFillColourId = 0x1001311, /**< For rotary sliders, this colour fills the outer curve. */ - rotarySliderOutlineColourId = 0x1001312, /**< For rotary sliders, this colour is used to draw the outer curve's outline. */ - - textBoxTextColourId = 0x1001400, /**< The colour for the text in the text-editor box used for editing the value. */ - textBoxBackgroundColourId = 0x1001500, /**< The background colour for the text-editor box. */ - textBoxHighlightColourId = 0x1001600, /**< The text highlight colour for the text-editor box. */ - textBoxOutlineColourId = 0x1001700 /**< The colour to use for a border around the text-editor box. */ - }; - - juce_UseDebuggingNewOperator + double getMaximum() const { return maximum; } + + double getMinimum() const { return minimum; } + + double getInterval() const { return interval; } + + double getMinValue() const; + + Value& getMinValueObject() { return valueMin; } + + void setMinValue (double newValue, + const bool sendUpdateMessage = true, + const bool sendMessageSynchronously = false, + const bool allowNudgingOfOtherValues = false); + + double getMaxValue() const; + + Value& getMaxValueObject() { return valueMax; } + + void setMaxValue (double newValue, + const bool sendUpdateMessage = true, + const bool sendMessageSynchronously = false, + const bool allowNudgingOfOtherValues = false); + + void addListener (SliderListener* const listener); + + void removeListener (SliderListener* const listener); + + void setDoubleClickReturnValue (const bool isDoubleClickEnabled, + const double valueToSetOnDoubleClick); + + double getDoubleClickReturnValue (bool& isEnabled) const; + + void setChangeNotificationOnlyOnRelease (const bool onlyNotifyOnRelease); + + void setSliderSnapsToMousePosition (const bool shouldSnapToMouse); + + void setPopupDisplayEnabled (const bool isEnabled, + Component* const parentComponentToUse); + + void setPopupMenuEnabled (const bool menuEnabled); + + void setScrollWheelEnabled (const bool enabled); + + int getThumbBeingDragged() const { return sliderBeingDragged; } + + virtual void startedDragging(); + + virtual void stoppedDragging(); + + virtual void valueChanged(); + + /** Callback to indicate that the user has just moved the slider. + Note - the valueChanged() method has changed its format and now no longer has + any parameters. Update your code to use the new version. + This version has been left here with an int as its return value to cause + a syntax error if you've got existing code that uses the old version. + */ + virtual int valueChanged (double) { jassertfalse; return 0; } + + virtual double getValueFromText (const String& text); + + virtual const String getTextFromValue (double value); + + void setTextValueSuffix (const String& suffix); + + virtual double proportionOfLengthToValue (double proportion); + + virtual double valueToProportionOfLength (double value); + + float getPositionOfValue (const double value); + + virtual double snapValue (double attemptedValue, const bool userIsDragging); + + void updateText(); + + bool isHorizontal() const; + bool isVertical() const; + + enum ColourIds + { + backgroundColourId = 0x1001200, /**< A colour to use to fill the slider's background. */ + thumbColourId = 0x1001300, /**< The colour to draw the thumb with. It's up to the look + and feel class how this is used. */ + trackColourId = 0x1001310, /**< The colour to draw the groove that the thumb moves along. */ + rotarySliderFillColourId = 0x1001311, /**< For rotary sliders, this colour fills the outer curve. */ + rotarySliderOutlineColourId = 0x1001312, /**< For rotary sliders, this colour is used to draw the outer curve's outline. */ + + textBoxTextColourId = 0x1001400, /**< The colour for the text in the text-editor box used for editing the value. */ + textBoxBackgroundColourId = 0x1001500, /**< The background colour for the text-editor box. */ + textBoxHighlightColourId = 0x1001600, /**< The text highlight colour for the text-editor box. */ + textBoxOutlineColourId = 0x1001700 /**< The colour to use for a border around the text-editor box. */ + }; + + juce_UseDebuggingNewOperator protected: - /** @internal */ - void labelTextChanged (Label*); - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void resized(); - /** @internal */ - void mouseDown (const MouseEvent& e); - /** @internal */ - void mouseUp (const MouseEvent& e); - /** @internal */ - void mouseDrag (const MouseEvent& e); - /** @internal */ - void mouseDoubleClick (const MouseEvent& e); - /** @internal */ - void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); - /** @internal */ - void modifierKeysChanged (const ModifierKeys& modifiers); - /** @internal */ - void buttonClicked (Button* button); - /** @internal */ - void lookAndFeelChanged(); - /** @internal */ - void enablementChanged(); - /** @internal */ - void focusOfChildComponentChanged (FocusChangeType cause); - /** @internal */ - void handleAsyncUpdate(); - /** @internal */ - void colourChanged(); - /** @internal */ - void valueChanged (Value& value); + void labelTextChanged (Label*); + void paint (Graphics& g); + void resized(); + void mouseDown (const MouseEvent& e); + void mouseUp (const MouseEvent& e); + void mouseDrag (const MouseEvent& e); + void mouseDoubleClick (const MouseEvent& e); + void mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY); + void modifierKeysChanged (const ModifierKeys& modifiers); + void buttonClicked (Button* button); + void lookAndFeelChanged(); + void enablementChanged(); + void focusOfChildComponentChanged (FocusChangeType cause); + void handleAsyncUpdate(); + void colourChanged(); + void valueChanged (Value& value); private: - SortedSet listeners; - Value currentValue, valueMin, valueMax; - double lastCurrentValue, lastValueMin, lastValueMax; - double minimum, maximum, interval, doubleClickReturnValue; - double valueWhenLastDragged, valueOnMouseDown, skewFactor, lastAngle; - double velocityModeSensitivity, velocityModeOffset, minMaxDiff; - int velocityModeThreshold; - float rotaryStart, rotaryEnd; - int numDecimalPlaces, mouseXWhenLastDragged, mouseYWhenLastDragged; - int mouseDragStartX, mouseDragStartY; - int sliderRegionStart, sliderRegionSize; - int sliderBeingDragged; - int pixelsForFullDragExtent; - Rectangle sliderRect; - String textSuffix; + SortedSet listeners; + Value currentValue, valueMin, valueMax; + double lastCurrentValue, lastValueMin, lastValueMax; + double minimum, maximum, interval, doubleClickReturnValue; + double valueWhenLastDragged, valueOnMouseDown, skewFactor, lastAngle; + double velocityModeSensitivity, velocityModeOffset, minMaxDiff; + int velocityModeThreshold; + float rotaryStart, rotaryEnd; + int numDecimalPlaces, mouseXWhenLastDragged, mouseYWhenLastDragged; + int mouseDragStartX, mouseDragStartY; + int sliderRegionStart, sliderRegionSize; + int sliderBeingDragged; + int pixelsForFullDragExtent; + Rectangle sliderRect; + String textSuffix; - SliderStyle style; - TextEntryBoxPosition textBoxPos; - int textBoxWidth, textBoxHeight; - IncDecButtonMode incDecButtonMode; + SliderStyle style; + TextEntryBoxPosition textBoxPos; + int textBoxWidth, textBoxHeight; + IncDecButtonMode incDecButtonMode; - bool editableText : 1, doubleClickToValue : 1; - bool isVelocityBased : 1, userKeyOverridesVelocity : 1, rotaryStop : 1; - bool incDecButtonsSideBySide : 1, sendChangeOnlyOnRelease : 1, popupDisplayEnabled : 1; - bool menuEnabled : 1, menuShown : 1, mouseWasHidden : 1, incDecDragged : 1; - bool scrollWheelEnabled : 1, snapsToMousePos : 1; - Font font; - Label* valueBox; - Button* incButton; - Button* decButton; - ScopedPointer popupDisplay; - Component* parentForPopupDisplay; + bool editableText : 1, doubleClickToValue : 1; + bool isVelocityBased : 1, userKeyOverridesVelocity : 1, rotaryStop : 1; + bool incDecButtonsSideBySide : 1, sendChangeOnlyOnRelease : 1, popupDisplayEnabled : 1; + bool menuEnabled : 1, menuShown : 1, mouseWasHidden : 1, incDecDragged : 1; + bool scrollWheelEnabled : 1, snapsToMousePos : 1; + Font font; + Label* valueBox; + Button* incButton; + Button* decButton; + ScopedPointer popupDisplay; + Component* parentForPopupDisplay; - float getLinearSliderPos (const double value); - void restoreMouseIfHidden(); - void sendDragStart(); - void sendDragEnd(); - double constrainedValue (double value) const; - void triggerChangeMessage (const bool synchronous); - bool incDecDragDirectionIsHorizontal() const; + float getLinearSliderPos (const double value); + void restoreMouseIfHidden(); + void sendDragStart(); + void sendDragEnd(); + double constrainedValue (double value) const; + void triggerChangeMessage (const bool synchronous); + bool incDecDragDirectionIsHorizontal() const; - Slider (const Slider&); - const Slider& operator= (const Slider&); + Slider (const Slider&); + const Slider& operator= (const Slider&); }; #endif // __JUCE_SLIDER_JUCEHEADER__ @@ -43610,394 +20769,166 @@ private: class TableHeaderComponent; -/** - Receives events from a TableHeaderComponent when columns are resized, moved, etc. - - You can register one of these objects for table events using TableHeaderComponent::addListener() - and TableHeaderComponent::removeListener(). - - @see TableHeaderComponent -*/ class JUCE_API TableHeaderListener { public: - TableHeaderListener() {} + TableHeaderListener() {} - /** Destructor. */ - virtual ~TableHeaderListener() {} + virtual ~TableHeaderListener() {} - /** This is called when some of the table's columns are added, removed, hidden, - or rearranged. - */ - virtual void tableColumnsChanged (TableHeaderComponent* tableHeader) = 0; + virtual void tableColumnsChanged (TableHeaderComponent* tableHeader) = 0; - /** This is called when one or more of the table's columns are resized. - */ - virtual void tableColumnsResized (TableHeaderComponent* tableHeader) = 0; + virtual void tableColumnsResized (TableHeaderComponent* tableHeader) = 0; - /** This is called when the column by which the table should be sorted is changed. - */ - virtual void tableSortOrderChanged (TableHeaderComponent* tableHeader) = 0; + virtual void tableSortOrderChanged (TableHeaderComponent* tableHeader) = 0; - /** This is called when the user begins or ends dragging one of the columns around. - - When the user starts dragging a column, this is called with the ID of that - column. When they finish dragging, it is called again with 0 as the ID. - */ - virtual void tableColumnDraggingChanged (TableHeaderComponent* tableHeader, - int columnIdNowBeingDragged); + virtual void tableColumnDraggingChanged (TableHeaderComponent* tableHeader, + int columnIdNowBeingDragged); }; -/** - A component that displays a strip of column headings for a table, and allows these - to be resized, dragged around, etc. - - This is just the component that goes at the top of a table. You can use it - directly for custom components, or to create a simple table, use the - TableListBox class. - - To use one of these, create it and use addColumn() to add all the columns that you need. - Each column must be given a unique ID number that's used to refer to it. - - @see TableListBox, TableHeaderListener -*/ class JUCE_API TableHeaderComponent : public Component, - private AsyncUpdater + private AsyncUpdater { public: - /** Creates an empty table header. - */ - TableHeaderComponent(); - - /** Destructor. */ - ~TableHeaderComponent(); - - /** A combination of these flags are passed into the addColumn() method to specify - the properties of a column. - */ - enum ColumnPropertyFlags - { - visible = 1, /**< If this is set, the column will be shown; if not, it will be hidden until the user enables it with the pop-up menu. */ - resizable = 2, /**< If this is set, the column can be resized by dragging it. */ - draggable = 4, /**< If this is set, the column can be dragged around to change its order in the table. */ - appearsOnColumnMenu = 8, /**< If this is set, the column will be shown on the pop-up menu allowing it to be hidden/shown. */ - sortable = 16, /**< If this is set, then clicking on the column header will set it to be the sort column, and clicking again will reverse the order. */ - sortedForwards = 32, /**< If this is set, the column is currently the one by which the table is sorted (forwards). */ - sortedBackwards = 64, /**< If this is set, the column is currently the one by which the table is sorted (backwards). */ - - /** This set of default flags is used as the default parameter value in addColumn(). */ - defaultFlags = (visible | resizable | draggable | appearsOnColumnMenu | sortable), - - /** A quick way of combining flags for a column that's not resizable. */ - notResizable = (visible | draggable | appearsOnColumnMenu | sortable), - - /** A quick way of combining flags for a column that's not resizable or sortable. */ - notResizableOrSortable = (visible | draggable | appearsOnColumnMenu), - - /** A quick way of combining flags for a column that's not sortable. */ - notSortable = (visible | resizable | draggable | appearsOnColumnMenu) - }; - - /** Adds a column to the table. - - This will add a column, and asynchronously call the tableColumnsChanged() method of any - registered listeners. - - @param columnName the name of the new column. It's ok to have two or more columns with the same name - @param columnId an ID for this column. The ID can be any number apart from 0, but every column must have - a unique ID. This is used to identify the column later on, after the user may have - changed the order that they appear in - @param width the initial width of the column, in pixels - @param maximumWidth a maximum width that the column can take when the user is resizing it. This only applies - if the 'resizable' flag is specified for this column - @param minimumWidth a minimum width that the column can take when the user is resizing it. This only applies - if the 'resizable' flag is specified for this column - @param propertyFlags a combination of some of the values from the ColumnPropertyFlags enum, to define the - properties of this column - @param insertIndex the index at which the column should be added. A value of 0 puts it at the start (left-hand side) - and -1 puts it at the end (right-hand size) of the table. Note that the index the index within - all columns, not just the index amongst those that are currently visible - */ - void addColumn (const String& columnName, - const int columnId, - const int width, - const int minimumWidth = 30, - const int maximumWidth = -1, - const int propertyFlags = defaultFlags, - const int insertIndex = -1); + TableHeaderComponent(); - /** Removes a column with the given ID. + ~TableHeaderComponent(); - If there is such a column, this will asynchronously call the tableColumnsChanged() method of any - registered listeners. - */ - void removeColumn (const int columnIdToRemove); + enum ColumnPropertyFlags + { + visible = 1, /**< If this is set, the column will be shown; if not, it will be hidden until the user enables it with the pop-up menu. */ + resizable = 2, /**< If this is set, the column can be resized by dragging it. */ + draggable = 4, /**< If this is set, the column can be dragged around to change its order in the table. */ + appearsOnColumnMenu = 8, /**< If this is set, the column will be shown on the pop-up menu allowing it to be hidden/shown. */ + sortable = 16, /**< If this is set, then clicking on the column header will set it to be the sort column, and clicking again will reverse the order. */ + sortedForwards = 32, /**< If this is set, the column is currently the one by which the table is sorted (forwards). */ + sortedBackwards = 64, /**< If this is set, the column is currently the one by which the table is sorted (backwards). */ - /** Deletes all columns from the table. + defaultFlags = (visible | resizable | draggable | appearsOnColumnMenu | sortable), - If there are any columns to remove, this will asynchronously call the tableColumnsChanged() method of any - registered listeners. - */ - void removeAllColumns(); + notResizable = (visible | draggable | appearsOnColumnMenu | sortable), - /** Returns the number of columns in the table. + notResizableOrSortable = (visible | draggable | appearsOnColumnMenu), - If onlyCountVisibleColumns is true, this will return the number of visible columns; otherwise it'll - return the total number of columns, including hidden ones. + notSortable = (visible | resizable | draggable | appearsOnColumnMenu) + }; - @see isColumnVisible - */ - int getNumColumns (const bool onlyCountVisibleColumns) const; + void addColumn (const String& columnName, + const int columnId, + const int width, + const int minimumWidth = 30, + const int maximumWidth = -1, + const int propertyFlags = defaultFlags, + const int insertIndex = -1); - /** Returns the name for a column. - @see setColumnName - */ - const String getColumnName (const int columnId) const; + void removeColumn (const int columnIdToRemove); - /** Changes the name of a column. */ - void setColumnName (const int columnId, const String& newName); + void removeAllColumns(); - /** Moves a column to a different index in the table. + int getNumColumns (const bool onlyCountVisibleColumns) const; - @param columnId the column to move - @param newVisibleIndex the target index for it, from 0 to the number of columns currently visible. - */ - void moveColumn (const int columnId, int newVisibleIndex); + const String getColumnName (const int columnId) const; - /** Returns the width of one of the columns. - */ - int getColumnWidth (const int columnId) const; + void setColumnName (const int columnId, const String& newName); - /** Changes the width of a column. + void moveColumn (const int columnId, int newVisibleIndex); - This will cause an asynchronous callback to the tableColumnsResized() method of any registered listeners. - */ - void setColumnWidth (const int columnId, const int newWidth); + int getColumnWidth (const int columnId) const; - /** Shows or hides a column. + void setColumnWidth (const int columnId, const int newWidth); - This can cause an asynchronous callback to the tableColumnsChanged() method of any registered listeners. - @see isColumnVisible - */ - void setColumnVisible (const int columnId, const bool shouldBeVisible); + void setColumnVisible (const int columnId, const bool shouldBeVisible); - /** Returns true if this column is currently visible. - @see setColumnVisible - */ - bool isColumnVisible (const int columnId) const; + bool isColumnVisible (const int columnId) const; - /** Changes the column which is the sort column. + void setSortColumnId (const int columnId, const bool sortForwards); - This can cause an asynchronous callback to the tableSortOrderChanged() method of any registered listeners. + int getSortColumnId() const; - If this method doesn't actually change the column ID, then no re-sort will take place (you can - call reSortTable() to force a re-sort to happen if you've modified the table's contents). + bool isSortedForwards() const; - @see getSortColumnId, isSortedForwards, reSortTable - */ - void setSortColumnId (const int columnId, const bool sortForwards); + void reSortTable(); - /** Returns the column ID by which the table is currently sorted, or 0 if it is unsorted. + int getTotalWidth() const; - @see setSortColumnId, isSortedForwards - */ - int getSortColumnId() const; + int getIndexOfColumnId (const int columnId, const bool onlyCountVisibleColumns) const; - /** Returns true if the table is currently sorted forwards, or false if it's backwards. - @see setSortColumnId - */ - bool isSortedForwards() const; + int getColumnIdOfIndex (int index, const bool onlyCountVisibleColumns) const; - /** Triggers a re-sort of the table according to the current sort-column. + const Rectangle getColumnPosition (const int index) const; - If you modifiy the table's contents, you can call this to signal that the table needs - to be re-sorted. + int getColumnIdAtX (const int xToFind) const; - (This doesn't do any sorting synchronously - it just asynchronously sends a call to the - tableSortOrderChanged() method of any listeners). - */ - void reSortTable(); + void setStretchToFitActive (const bool shouldStretchToFit); - /** Returns the total width of all the visible columns in the table. - */ - int getTotalWidth() const; + bool isStretchToFitActive() const; - /** Returns the index of a given column. + void resizeAllColumnsToFit (int targetTotalWidth); - If there's no such column ID, this will return -1. + void setPopupMenuActive (const bool hasMenu); - If onlyCountVisibleColumns is true, this will return the index amoungst the visible columns; - otherwise it'll return the index amongst all the columns, including any hidden ones. - */ - int getIndexOfColumnId (const int columnId, const bool onlyCountVisibleColumns) const; + bool isPopupMenuActive() const; - /** Returns the ID of the column at a given index. + const String toString() const; - If onlyCountVisibleColumns is true, this will count the index amoungst the visible columns; - otherwise it'll count it amongst all the columns, including any hidden ones. + void restoreFromString (const String& storedVersion); - If the index is out-of-range, it'll return 0. - */ - int getColumnIdOfIndex (int index, const bool onlyCountVisibleColumns) const; + void addListener (TableHeaderListener* const newListener); - /** Returns the rectangle containing of one of the columns. + void removeListener (TableHeaderListener* const listenerToRemove); - The index is an index from 0 to the number of columns that are currently visible (hidden - ones are not counted). It returns a rectangle showing the position of the column relative - to this component's top-left. If the index is out-of-range, an empty rectangle is retrurned. - */ - const Rectangle getColumnPosition (const int index) const; + virtual void columnClicked (int columnId, const ModifierKeys& mods); - /** Finds the column ID at a given x-position in the component. + virtual void addMenuItems (PopupMenu& menu, const int columnIdClicked); - If there is a column at this point this returns its ID, or if not, it will return 0. - */ - int getColumnIdAtX (const int xToFind) const; + virtual void reactToMenuItem (const int menuReturnId, const int columnIdClicked); - /** If set to true, this indicates that the columns should be expanded or shrunk to fill the - entire width of the component. + void paint (Graphics& g); + void resized(); + void mouseMove (const MouseEvent&); + void mouseEnter (const MouseEvent&); + void mouseExit (const MouseEvent&); + void mouseDown (const MouseEvent&); + void mouseDrag (const MouseEvent&); + void mouseUp (const MouseEvent&); + const MouseCursor getMouseCursor(); - By default this is disabled. Turning it on also means that when resizing a column, those - on the right will be squashed to fit. - */ - void setStretchToFitActive (const bool shouldStretchToFit); + virtual void showColumnChooserMenu (const int columnIdClicked); - /** Returns true if stretch-to-fit has been enabled. - @see setStretchToFitActive - */ - bool isStretchToFitActive() const; - - /** If stretch-to-fit is enabled, this will resize all the columns to make them fit into the - specified width, keeping their relative proportions the same. - - If the minimum widths of the columns are too wide to fit into this space, it may - actually end up wider. - */ - void resizeAllColumnsToFit (int targetTotalWidth); - - /** Enables or disables the pop-up menu. - - The default menu allows the user to show or hide columns. You can add custom - items to this menu by overloading the addMenuItems() and reactToMenuItem() methods. - - By default the menu is enabled. - - @see isPopupMenuActive, addMenuItems, reactToMenuItem - */ - void setPopupMenuActive (const bool hasMenu); - - /** Returns true if the pop-up menu is enabled. - @see setPopupMenuActive - */ - bool isPopupMenuActive() const; - - /** Returns a string that encapsulates the table's current layout. - - This can be restored later using restoreFromString(). It saves the order of - the columns, the currently-sorted column, and the widths. - - @see restoreFromString - */ - const String toString() const; - - /** Restores the state of the table, based on a string previously created with - toString(). - - @see toString - */ - void restoreFromString (const String& storedVersion); - - /** Adds a listener to be informed about things that happen to the header. */ - void addListener (TableHeaderListener* const newListener); - - /** Removes a previously-registered listener. */ - void removeListener (TableHeaderListener* const listenerToRemove); - - /** This can be overridden to handle a mouse-click on one of the column headers. - - The default implementation will use this click to call getSortColumnId() and - change the sort order. - */ - virtual void columnClicked (int columnId, const ModifierKeys& mods); - - /** This can be overridden to add custom items to the pop-up menu. - - If you override this, you should call the superclass's method to add its - column show/hide items, if you want them on the menu as well. - - Then to handle the result, override reactToMenuItem(). - - @see reactToMenuItem - */ - virtual void addMenuItems (PopupMenu& menu, const int columnIdClicked); - - /** Override this to handle any custom items that you have added to the - pop-up menu with an addMenuItems() override. - - If the menuReturnId isn't one of your own custom menu items, you'll need to - call TableHeaderComponent::reactToMenuItem() to allow the base class to - handle the items that it had added. - - @see addMenuItems - */ - virtual void reactToMenuItem (const int menuReturnId, const int columnIdClicked); - - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void resized(); - /** @internal */ - void mouseMove (const MouseEvent&); - /** @internal */ - void mouseEnter (const MouseEvent&); - /** @internal */ - void mouseExit (const MouseEvent&); - /** @internal */ - void mouseDown (const MouseEvent&); - /** @internal */ - void mouseDrag (const MouseEvent&); - /** @internal */ - void mouseUp (const MouseEvent&); - /** @internal */ - const MouseCursor getMouseCursor(); - - /** Can be overridden for more control over the pop-up menu behaviour. */ - virtual void showColumnChooserMenu (const int columnIdClicked); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - struct ColumnInfo - { - String name; - int id, propertyFlags, width, minimumWidth, maximumWidth; - double lastDeliberateWidth; + struct ColumnInfo + { + String name; + int id, propertyFlags, width, minimumWidth, maximumWidth; + double lastDeliberateWidth; - bool isVisible() const; - }; + bool isVisible() const; + }; - OwnedArray columns; - Array listeners; - ScopedPointer dragOverlayComp; + OwnedArray columns; + Array listeners; + ScopedPointer dragOverlayComp; - bool columnsChanged, columnsResized, sortChanged, menuActive, stretchToFit; - int columnIdBeingResized, columnIdBeingDragged, initialColumnWidth; - int columnIdUnderMouse, draggingColumnOffset, draggingColumnOriginalIndex, lastDeliberateWidth; + bool columnsChanged, columnsResized, sortChanged, menuActive, stretchToFit; + int columnIdBeingResized, columnIdBeingDragged, initialColumnWidth; + int columnIdUnderMouse, draggingColumnOffset, draggingColumnOriginalIndex, lastDeliberateWidth; - ColumnInfo* getInfoForId (const int columnId) const; - int visibleIndexToTotalIndex (const int visibleIndex) const; - void sendColumnsChanged(); - void handleAsyncUpdate(); - void beginDrag (const MouseEvent&); - void endDrag (const int finalIndex); - int getResizeDraggerAt (const int mouseX) const; - void updateColumnUnderMouse (int x, int y); - void resizeColumnsToFit (int firstColumnIndex, int targetTotalWidth); + ColumnInfo* getInfoForId (const int columnId) const; + int visibleIndexToTotalIndex (const int visibleIndex) const; + void sendColumnsChanged(); + void handleAsyncUpdate(); + void beginDrag (const MouseEvent&); + void endDrag (const int finalIndex); + int getResizeDraggerAt (const int mouseX) const; + void updateColumnUnderMouse (int x, int y); + void resizeColumnsToFit (int firstColumnIndex, int targetTotalWidth); - TableHeaderComponent (const TableHeaderComponent&); - const TableHeaderComponent operator= (const TableHeaderComponent&); + TableHeaderComponent (const TableHeaderComponent&); + const TableHeaderComponent operator= (const TableHeaderComponent&); }; #endif // __JUCE_TABLEHEADERCOMPONENT_JUCEHEADER__ @@ -44010,281 +20941,114 @@ private: #ifndef __JUCE_TABLELISTBOX_JUCEHEADER__ #define __JUCE_TABLELISTBOX_JUCEHEADER__ -/** - One of these is used by a TableListBox as the data model for the table's contents. - - The virtual methods that you override in this class take care of drawing the - table cells, and reacting to events. - - @see TableListBox -*/ class JUCE_API TableListBoxModel { public: - TableListBoxModel() {} + TableListBoxModel() {} - /** Destructor. */ - virtual ~TableListBoxModel() {} + virtual ~TableListBoxModel() {} - /** This must return the number of rows currently in the table. + virtual int getNumRows() = 0; - If the number of rows changes, you must call TableListBox::updateContent() to - cause it to refresh the list. - */ - virtual int getNumRows() = 0; + virtual void paintRowBackground (Graphics& g, + int rowNumber, + int width, int height, + bool rowIsSelected) = 0; - /** This must draw the background behind one of the rows in the table. + virtual void paintCell (Graphics& g, + int rowNumber, + int columnId, + int width, int height, + bool rowIsSelected) = 0; - The graphics context has its origin at the row's top-left, and your method - should fill the area specified by the width and height parameters. - */ - virtual void paintRowBackground (Graphics& g, - int rowNumber, - int width, int height, - bool rowIsSelected) = 0; + virtual Component* refreshComponentForCell (int rowNumber, int columnId, bool isRowSelected, + Component* existingComponentToUpdate); - /** This must draw one of the cells. + virtual void cellClicked (int rowNumber, int columnId, const MouseEvent& e); - The graphics context's origin will already be set to the top-left of the cell, - whose size is specified by (width, height). - */ - virtual void paintCell (Graphics& g, - int rowNumber, - int columnId, - int width, int height, - bool rowIsSelected) = 0; + virtual void cellDoubleClicked (int rowNumber, int columnId, const MouseEvent& e); - /** This is used to create or update a custom component to go in a cell. + virtual void backgroundClicked(); - Any cell may contain a custom component, or can just be drawn with the paintCell() method - and handle mouse clicks with cellClicked(). + virtual void sortOrderChanged (int newSortColumnId, const bool isForwards); - This method will be called whenever a custom component might need to be updated - e.g. - when the table is changed, or TableListBox::updateContent() is called. + virtual int getColumnAutoSizeWidth (int columnId); - If you don't need a custom component for the specified cell, then return 0. + virtual const String getCellTooltip (int rowNumber, int columnId); - If you do want a custom component, and the existingComponentToUpdate is null, then - this method must create a new component suitable for the cell, and return it. + virtual void selectedRowsChanged (int lastRowSelected); - If the existingComponentToUpdate is non-null, it will be a pointer to a component previously created - by this method. In this case, the method must either update it to make sure it's correctly representing - the given cell (which may be different from the one that the component was created for), or it can - delete this component and return a new one. - */ - virtual Component* refreshComponentForCell (int rowNumber, int columnId, bool isRowSelected, - Component* existingComponentToUpdate); + virtual void deleteKeyPressed (int lastRowSelected); - /** This callback is made when the user clicks on one of the cells in the table. + virtual void returnKeyPressed (int lastRowSelected); - The mouse event's coordinates will be relative to the entire table row. - @see cellDoubleClicked, backgroundClicked - */ - virtual void cellClicked (int rowNumber, int columnId, const MouseEvent& e); + virtual void listWasScrolled(); - /** This callback is made when the user clicks on one of the cells in the table. - - The mouse event's coordinates will be relative to the entire table row. - @see cellClicked, backgroundClicked - */ - virtual void cellDoubleClicked (int rowNumber, int columnId, const MouseEvent& e); - - /** This can be overridden to react to the user double-clicking on a part of the list where - there are no rows. - - @see cellClicked - */ - virtual void backgroundClicked(); - - /** This callback is made when the table's sort order is changed. - - This could be because the user has clicked a column header, or because the - TableHeaderComponent::setSortColumnId() method was called. - - If you implement this, your method should re-sort the table using the given - column as the key. - */ - virtual void sortOrderChanged (int newSortColumnId, const bool isForwards); - - /** Returns the best width for one of the columns. - - If you implement this method, you should measure the width of all the items - in this column, and return the best size. - - Returning 0 means that the column shouldn't be changed. - - This is used by TableListBox::autoSizeColumn() and TableListBox::autoSizeAllColumns(). - */ - virtual int getColumnAutoSizeWidth (int columnId); - - /** Returns a tooltip for a particular cell in the table. - */ - virtual const String getCellTooltip (int rowNumber, int columnId); - - /** Override this to be informed when rows are selected or deselected. - - @see ListBox::selectedRowsChanged() - */ - virtual void selectedRowsChanged (int lastRowSelected); - - /** Override this to be informed when the delete key is pressed. - - @see ListBox::deleteKeyPressed() - */ - virtual void deleteKeyPressed (int lastRowSelected); - - /** Override this to be informed when the return key is pressed. - - @see ListBox::returnKeyPressed() - */ - virtual void returnKeyPressed (int lastRowSelected); - - /** Override this to be informed when the list is scrolled. - - This might be caused by the user moving the scrollbar, or by programmatic changes - to the list position. - */ - virtual void listWasScrolled(); - - /** To allow rows from your table to be dragged-and-dropped, implement this method. - - If this returns a non-empty name then when the user drags a row, the table will try to - find a DragAndDropContainer in its parent hierarchy, and will use it to trigger a - drag-and-drop operation, using this string as the source description, and the listbox - itself as the source component. - - @see DragAndDropContainer::startDragging - */ - virtual const String getDragSourceDescription (const SparseSet& currentlySelectedRows); + virtual const String getDragSourceDescription (const SparseSet& currentlySelectedRows); }; -/** - A table of cells, using a TableHeaderComponent as its header. - - This component makes it easy to create a table by providing a TableListBoxModel as - the data source. - - @see TableListBoxModel, TableHeaderComponent -*/ class JUCE_API TableListBox : public ListBox, - private ListBoxModel, - private TableHeaderListener + private ListBoxModel, + private TableHeaderListener { public: - /** Creates a TableListBox. + TableListBox (const String& componentName, + TableListBoxModel* const model); - The model pointer passed-in can be null, in which case you can set it later - with setModel(). - */ - TableListBox (const String& componentName, - TableListBoxModel* const model); + ~TableListBox(); - /** Destructor. */ - ~TableListBox(); + void setModel (TableListBoxModel* const newModel); - /** Changes the TableListBoxModel that is being used for this table. - */ - void setModel (TableListBoxModel* const newModel); + TableListBoxModel* getModel() const { return model; } - /** Returns the model currently in use. */ - TableListBoxModel* getModel() const { return model; } + TableHeaderComponent* getHeader() const { return header; } - /** Returns the header component being used in this table. */ - TableHeaderComponent* getHeader() const { return header; } + void setHeaderHeight (const int newHeight); - /** Changes the height of the table header component. - @see getHeaderHeight - */ - void setHeaderHeight (const int newHeight); + int getHeaderHeight() const; - /** Returns the height of the table header. - @see setHeaderHeight - */ - int getHeaderHeight() const; + void autoSizeColumn (const int columnId); - /** Resizes a column to fit its contents. + void autoSizeAllColumns(); - This uses TableListBoxModel::getColumnAutoSizeWidth() to find the best width, - and applies that to the column. + void setAutoSizeMenuOptionShown (const bool shouldBeShown); - @see autoSizeAllColumns, TableHeaderComponent::setColumnWidth - */ - void autoSizeColumn (const int columnId); + bool isAutoSizeMenuOptionShown() const; - /** Calls autoSizeColumn() for all columns in the table. */ - void autoSizeAllColumns(); + const Rectangle getCellPosition (const int columnId, + const int rowNumber, + const bool relativeToComponentTopLeft) const; - /** Enables or disables the auto size options on the popup menu. + void scrollToEnsureColumnIsOnscreen (const int columnId); - By default, these are enabled. - */ - void setAutoSizeMenuOptionShown (const bool shouldBeShown); + int getNumRows(); + void paintListBoxItem (int, Graphics&, int, int, bool); + Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate); + void selectedRowsChanged (int lastRowSelected); + void deleteKeyPressed (int currentSelectedRow); + void returnKeyPressed (int currentSelectedRow); + void backgroundClicked(); + void listWasScrolled(); + void tableColumnsChanged (TableHeaderComponent*); + void tableColumnsResized (TableHeaderComponent*); + void tableSortOrderChanged (TableHeaderComponent*); + void tableColumnDraggingChanged (TableHeaderComponent*, int); + void resized(); - /** True if the auto-size options should be shown on the menu. - @see setAutoSizeMenuOptionsShown - */ - bool isAutoSizeMenuOptionShown() const; - - /** Returns the position of one of the cells in the table. - - If relativeToComponentTopLeft is true, the co-ordinates are relative to - the table component's top-left. The row number isn't checked to see if it's - in-range, but the column ID must exist or this will return an empty rectangle. - - If relativeToComponentTopLeft is false, the co-ords are relative to the - top-left of the table's top-left cell. - */ - const Rectangle getCellPosition (const int columnId, - const int rowNumber, - const bool relativeToComponentTopLeft) const; - - /** Scrolls horizontally if necessary to make sure that a particular column is visible. - - @see ListBox::scrollToEnsureRowIsOnscreen - */ - void scrollToEnsureColumnIsOnscreen (const int columnId); - - /** @internal */ - int getNumRows(); - /** @internal */ - void paintListBoxItem (int, Graphics&, int, int, bool); - /** @internal */ - Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate); - /** @internal */ - void selectedRowsChanged (int lastRowSelected); - /** @internal */ - void deleteKeyPressed (int currentSelectedRow); - /** @internal */ - void returnKeyPressed (int currentSelectedRow); - /** @internal */ - void backgroundClicked(); - /** @internal */ - void listWasScrolled(); - /** @internal */ - void tableColumnsChanged (TableHeaderComponent*); - /** @internal */ - void tableColumnsResized (TableHeaderComponent*); - /** @internal */ - void tableSortOrderChanged (TableHeaderComponent*); - /** @internal */ - void tableColumnDraggingChanged (TableHeaderComponent*, int); - /** @internal */ - void resized(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - TableHeaderComponent* header; - TableListBoxModel* model; - int columnIdNowBeingDragged; - bool autoSizeOptionsShown; + TableHeaderComponent* header; + TableListBoxModel* model; + int columnIdNowBeingDragged; + bool autoSizeOptionsShown; - void updateColumnComponents() const; + void updateColumnComponents() const; - TableListBox (const TableListBox&); - const TableListBox& operator= (const TableListBox&); + TableListBox (const TableListBox&); + const TableListBox& operator= (const TableListBox&); }; #endif // __JUCE_TABLELISTBOX_JUCEHEADER__ @@ -44306,79 +21070,29 @@ private: #ifndef __JUCE_TOOLBARITEMFACTORY_JUCEHEADER__ #define __JUCE_TOOLBARITEMFACTORY_JUCEHEADER__ -/** - A factory object which can create ToolbarItemComponent objects. - - A subclass of ToolbarItemFactory publishes a set of types of toolbar item - that it can create. - - Each type of item is identified by a unique ID, and multiple instances of an - item type can exist at once (even on the same toolbar, e.g. spacers or separator - bars). - - @see Toolbar, ToolbarItemComponent, ToolbarButton -*/ class JUCE_API ToolbarItemFactory { public: - ToolbarItemFactory(); + ToolbarItemFactory(); - /** Destructor. */ - virtual ~ToolbarItemFactory(); + virtual ~ToolbarItemFactory(); - /** A set of reserved item ID values, used for the built-in item types. - */ - enum SpecialItemIds - { - separatorBarId = -1, /**< The item ID for a vertical (or horizontal) separator bar that - can be placed between sets of items to break them into groups. */ - spacerId = -2, /**< The item ID for a fixed-width space that can be placed between - items.*/ - flexibleSpacerId = -3 /**< The item ID for a gap that pushes outwards against the things on - either side of it, filling any available space. */ - }; + enum SpecialItemIds + { + separatorBarId = -1, /**< The item ID for a vertical (or horizontal) separator bar that + can be placed between sets of items to break them into groups. */ + spacerId = -2, /**< The item ID for a fixed-width space that can be placed between + items.*/ + flexibleSpacerId = -3 /**< The item ID for a gap that pushes outwards against the things on + either side of it, filling any available space. */ + }; - /** Must return a list of the IDs for all the item types that this factory can create. + virtual void getAllToolbarItemIds (Array & ids) = 0; - The ids should be added to the array that is passed-in. + virtual void getDefaultItemSet (Array & ids) = 0; - An item ID can be any integer you choose, except for 0, which is considered a null ID, - and the predefined IDs in the SpecialItemIds enum. - - You should also add the built-in types (separatorBarId, spacerId and flexibleSpacerId) - to this list if you want your toolbar to be able to contain those items. - - The list returned here is used by the ToolbarItemPalette class to obtain its list - of available items, and their order on the palette will reflect the order in which - they appear on this list. - - @see ToolbarItemPalette - */ - virtual void getAllToolbarItemIds (Array & ids) = 0; - - /** Must return the set of items that should be added to a toolbar as its default set. - - This method is used by Toolbar::addDefaultItems() to determine which items to - create. - - The items that your method adds to the array that is passed-in will be added to the - toolbar in the same order. Items can appear in the list more than once. - */ - virtual void getDefaultItemSet (Array & ids) = 0; - - /** Must create an instance of one of the items that the factory lists in its - getAllToolbarItemIds() method. - - The itemId parameter can be any of the values listed by your getAllToolbarItemIds() - method, except for the built-in item types from the SpecialItemIds enum, which - are created internally by the toolbar code. - - Try not to keep a pointer to the object that is returned, as it will be deleted - automatically by the toolbar, and remember that multiple instances of the same - item type are likely to exist at the same time. - */ - virtual ToolbarItemComponent* createItem (const int itemId) = 0; + virtual ToolbarItemComponent* createItem (const int itemId) = 0; }; #endif // __JUCE_TOOLBARITEMFACTORY_JUCEHEADER__ @@ -44391,49 +21105,30 @@ public: #ifndef __JUCE_TOOLBARITEMPALETTE_JUCEHEADER__ #define __JUCE_TOOLBARITEMPALETTE_JUCEHEADER__ -/** - A component containing a list of toolbar items, which the user can drag onto - a toolbar to add them. - - You can use this class directly, but it's a lot easier to call Toolbar::showCustomisationDialog(), - which automatically shows one of these in a dialog box with lots of extra controls. - - @see Toolbar -*/ -class JUCE_API ToolbarItemPalette : public Component, - public DragAndDropContainer +class JUCE_API ToolbarItemPalette : public Component, + public DragAndDropContainer { public: - /** Creates a palette of items for a given factory, with the aim of adding them - to the specified toolbar. + ToolbarItemPalette (ToolbarItemFactory& factory, + Toolbar* const toolbar); - The ToolbarItemFactory::getAllToolbarItemIds() method is used to create the - set of items that are shown in this palette. + ~ToolbarItemPalette(); - The toolbar and factory must not be deleted while this object exists. - */ - ToolbarItemPalette (ToolbarItemFactory& factory, - Toolbar* const toolbar); + void resized(); - /** Destructor. */ - ~ToolbarItemPalette(); - - /** @internal */ - void resized(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ToolbarItemFactory& factory; - Toolbar* toolbar; - Viewport* viewport; + ToolbarItemFactory& factory; + Toolbar* toolbar; + Viewport* viewport; - friend class Toolbar; - void replaceComponent (ToolbarItemComponent* const comp); + friend class Toolbar; + void replaceComponent (ToolbarItemComponent* const comp); - ToolbarItemPalette (const ToolbarItemPalette&); - const ToolbarItemPalette& operator= (const ToolbarItemPalette&); + ToolbarItemPalette (const ToolbarItemPalette&); + const ToolbarItemPalette& operator= (const ToolbarItemPalette&); }; #endif // __JUCE_TOOLBARITEMPALETTE_JUCEHEADER__ @@ -44450,79 +21145,20 @@ private: #ifndef __JUCE_FILEDRAGANDDROPTARGET_JUCEHEADER__ #define __JUCE_FILEDRAGANDDROPTARGET_JUCEHEADER__ -/** - Components derived from this class can have files dropped onto them by an external application. - - @see DragAndDropContainer -*/ class JUCE_API FileDragAndDropTarget { public: - /** Destructor. */ - virtual ~FileDragAndDropTarget() {} + virtual ~FileDragAndDropTarget() {} - /** Callback to check whether this target is interested in the set of files being offered. + virtual bool isInterestedInFileDrag (const StringArray& files) = 0; - Note that this will be called repeatedly when the user is dragging the mouse around over your - component, so don't do anything time-consuming in here, like opening the files to have a look - inside them! + virtual void fileDragEnter (const StringArray& files, int x, int y); - @param files the set of (absolute) pathnames of the files that the user is dragging - @returns true if this component wants to receive the other callbacks regarging this - type of object; if it returns false, no other callbacks will be made. - */ - virtual bool isInterestedInFileDrag (const StringArray& files) = 0; + virtual void fileDragMove (const StringArray& files, int x, int y); - /** Callback to indicate that some files are being dragged over this component. + virtual void fileDragExit (const StringArray& files); - This gets called when the user moves the mouse into this component while dragging. - - Use this callback as a trigger to make your component repaint itself to give the - user feedback about whether the files can be dropped here or not. - - @param files the set of (absolute) pathnames of the files that the user is dragging - @param x the mouse x position, relative to this component - @param y the mouse y position, relative to this component - */ - virtual void fileDragEnter (const StringArray& files, int x, int y); - - /** Callback to indicate that the user is dragging some files over this component. - - This gets called when the user moves the mouse over this component while dragging. - Normally overriding itemDragEnter() and itemDragExit() are enough, but - this lets you know what happens in-between. - - @param files the set of (absolute) pathnames of the files that the user is dragging - @param x the mouse x position, relative to this component - @param y the mouse y position, relative to this component - */ - virtual void fileDragMove (const StringArray& files, int x, int y); - - /** Callback to indicate that the mouse has moved away from this component. - - This gets called when the user moves the mouse out of this component while dragging - the files. - - If you've used fileDragEnter() to repaint your component and give feedback, use this - as a signal to repaint it in its normal state. - - @param files the set of (absolute) pathnames of the files that the user is dragging - */ - virtual void fileDragExit (const StringArray& files); - - /** Callback to indicate that the user has dropped the files onto this component. - - When the user drops the files, this get called, and you can use the files in whatever - way is appropriate. - - Note that after this is called, the fileDragExit method may not be called, so you should - clean up in here if there's anything you need to do when the drag finishes. - - @param files the set of (absolute) pathnames of the files that the user is dragging - @param x the mouse x position, relative to this component - @param y the mouse y position, relative to this component - */ - virtual void filesDropped (const StringArray& files, int x, int y) = 0; + virtual void filesDropped (const StringArray& files, int x, int y) = 0; }; #endif // __JUCE_FILEDRAGANDDROPTARGET_JUCEHEADER__ @@ -44530,732 +21166,249 @@ public: class TreeView; -/** - An item in a treeview. - - A TreeViewItem can either be a leaf-node in the tree, or it can contain its - own sub-items. - - To implement an item that contains sub-items, override the itemOpennessChanged() - method so that when it is opened, it adds the new sub-items to itself using the - addSubItem method. Depending on the nature of the item it might choose to only - do this the first time it's opened, or it might want to refresh itself each time. - It also has the option of deleting its sub-items when it is closed, or leaving them - in place. -*/ class JUCE_API TreeViewItem { public: - /** Constructor. */ - TreeViewItem(); + TreeViewItem(); - /** Destructor. */ - virtual ~TreeViewItem(); + virtual ~TreeViewItem(); - /** Returns the number of sub-items that have been added to this item. + int getNumSubItems() const throw(); - Note that this doesn't mean much if the node isn't open. + TreeViewItem* getSubItem (const int index) const throw(); - @see getSubItem, mightContainSubItems, addSubItem - */ - int getNumSubItems() const throw(); + void clearSubItems(); - /** Returns one of the item's sub-items. + void addSubItem (TreeViewItem* const newItem, + const int insertPosition = -1); - Remember that the object returned might get deleted at any time when its parent - item is closed or refreshed, depending on the nature of the items you're using. + void removeSubItem (const int index, + const bool deleteItem = true); - @see getNumSubItems - */ - TreeViewItem* getSubItem (const int index) const throw(); + TreeView* getOwnerView() const throw() { return ownerView; } - /** Removes any sub-items. */ - void clearSubItems(); + TreeViewItem* getParentItem() const throw() { return parentItem; } - /** Adds a sub-item. + bool isOpen() const throw(); - @param newItem the object to add to the item's sub-item list. Once added, these can be - found using getSubItem(). When the items are later removed with - removeSubItem() (or when this item is deleted), they will be deleted. - @param insertPosition the index which the new item should have when it's added. If this - value is less than 0, the item will be added to the end of the list. - */ - void addSubItem (TreeViewItem* const newItem, - const int insertPosition = -1); + void setOpen (const bool shouldBeOpen); - /** Removes one of the sub-items. + bool isSelected() const throw(); - @param index the item to remove - @param deleteItem if true, the item that is removed will also be deleted. - */ - void removeSubItem (const int index, - const bool deleteItem = true); + void setSelected (const bool shouldBeSelected, + const bool deselectOtherItemsFirst); - /** Returns the TreeView to which this item belongs. */ - TreeView* getOwnerView() const throw() { return ownerView; } + const Rectangle getItemPosition (const bool relativeToTreeViewTopLeft) const throw(); - /** Returns the item within which this item is contained. */ - TreeViewItem* getParentItem() const throw() { return parentItem; } + void treeHasChanged() const throw(); - /** True if this item is currently open in the treeview. */ - bool isOpen() const throw(); + void repaintItem() const; - /** Opens or closes the item. + int getRowNumberInTree() const throw(); - When opened or closed, the item's itemOpennessChanged() method will be called, - and a subclass should use this callback to create and add any sub-items that - it needs to. + bool areAllParentsOpen() const throw(); - @see itemOpennessChanged, mightContainSubItems - */ - void setOpen (const bool shouldBeOpen); + void setLinesDrawnForSubItems (const bool shouldDrawLines) throw(); - /** True if this item is currently selected. + virtual bool mightContainSubItems() = 0; - Use this when painting the node, to decide whether to draw it as selected or not. - */ - bool isSelected() const throw(); + virtual const String getUniqueName() const; - /** Selects or deselects the item. + virtual void itemOpennessChanged (bool isNowOpen); - This will cause a callback to itemSelectionChanged() - */ - void setSelected (const bool shouldBeSelected, - const bool deselectOtherItemsFirst); + virtual int getItemWidth() const { return -1; } - /** Returns the rectangle that this item occupies. + virtual int getItemHeight() const { return 20; } - If relativeToTreeViewTopLeft is true, the co-ordinates are relative to the - top-left of the TreeView comp, so this will depend on the scroll-position of - the tree. If false, it is relative to the top-left of the topmost item in the - tree (so this would be unaffected by scrolling the view). - */ - const Rectangle getItemPosition (const bool relativeToTreeViewTopLeft) const throw(); + virtual bool canBeSelected() const { return true; } - /** Sends a signal to the treeview to make it refresh itself. + virtual Component* createItemComponent() { return 0; } - Call this if your items have changed and you want the tree to update to reflect - this. - */ - void treeHasChanged() const throw(); + virtual void paintItem (Graphics& g, int width, int height); - /** Sends a repaint message to redraw just this item. + virtual void paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver); - Note that you should only call this if you want to repaint a superficial change. If - you're altering the tree's nodes, you should instead call treeHasChanged(). - */ - void repaintItem() const; + virtual void itemClicked (const MouseEvent& e); - /** Returns the row number of this item in the tree. + virtual void itemDoubleClicked (const MouseEvent& e); - The row number of an item will change according to which items are open. + virtual void itemSelectionChanged (bool isNowSelected); - @see TreeView::getNumRowsInTree(), TreeView::getItemOnRow() - */ - int getRowNumberInTree() const throw(); + virtual const String getTooltip(); - /** Returns true if all the item's parent nodes are open. + virtual const String getDragSourceDescription(); - This is useful to check whether the item might actually be visible or not. - */ - bool areAllParentsOpen() const throw(); + virtual bool isInterestedInFileDrag (const StringArray& files); - /** Changes whether lines are drawn to connect any sub-items to this item. + virtual void filesDropped (const StringArray& files, int insertIndex); - By default, line-drawing is turned on. - */ - void setLinesDrawnForSubItems (const bool shouldDrawLines) throw(); + virtual bool isInterestedInDragSource (const String& sourceDescription, Component* sourceComponent); - /** Tells the tree whether this item can potentially be opened. + virtual void itemDropped (const String& sourceDescription, Component* sourceComponent, int insertIndex); - If your item could contain sub-items, this should return true; if it returns - false then the tree will not try to open the item. This determines whether or - not the item will be drawn with a 'plus' button next to it. - */ - virtual bool mightContainSubItems() = 0; + void setDrawsInLeftMargin (bool canDrawInLeftMargin) throw(); - /** Returns a string to uniquely identify this item. + XmlElement* getOpennessState() const throw(); - If you're planning on using the TreeView::getOpennessState() method, then - these strings will be used to identify which nodes are open. The string - should be unique amongst the item's sibling items, but it's ok for there - to be duplicates at other levels of the tree. + void restoreOpennessState (const XmlElement& xml) throw(); - If you're not going to store the state, then it's ok not to bother implementing - this method. - */ - virtual const String getUniqueName() const; + int getIndexInParent() const throw(); - /** Called when an item is opened or closed. + bool isLastOfSiblings() const throw(); - When setOpen() is called and the item has specified that it might - have sub-items with the mightContainSubItems() method, this method - is called to let the item create or manage its sub-items. + const String getItemIdentifierString() const; - So when this is called with isNowOpen set to true (i.e. when the item is being - opened), a subclass might choose to use clearSubItems() and addSubItem() to - refresh its sub-item list. - - When this is called with isNowOpen set to false, the subclass might want - to use clearSubItems() to save on space, or it might choose to leave them, - depending on the nature of the tree. - - You could also use this callback as a trigger to start a background process - which asynchronously creates sub-items and adds them, if that's more - appropriate for the task in hand. - - @see mightContainSubItems - */ - virtual void itemOpennessChanged (bool isNowOpen); - - /** Must return the width required by this item. - - If your item needs to have a particular width in pixels, return that value; if - you'd rather have it just fill whatever space is available in the treeview, - return -1. - - If all your items return -1, no horizontal scrollbar will be shown, but if any - items have fixed widths and extend beyond the width of the treeview, a - scrollbar will appear. - - Each item can be a different width, but if they change width, you should call - treeHasChanged() to update the tree. - */ - virtual int getItemWidth() const { return -1; } - - /** Must return the height required by this item. - - This is the height in pixels that the item will take up. Items in the tree - can be different heights, but if they change height, you should call - treeHasChanged() to update the tree. - */ - virtual int getItemHeight() const { return 20; } - - /** You can override this method to return false if you don't want to allow the - user to select this item. - */ - virtual bool canBeSelected() const { return true; } - - /** Creates a component that will be used to represent this item. - - You don't have to implement this method - if it returns 0 then no component - will be used for the item, and you can just draw it using the paintItem() - callback. But if you do return a component, it will be positioned in the - treeview so that it can be used to represent this item. - - The component returned will be managed by the treeview, so always return - a new component, and don't keep a reference to it, as the treeview will - delete it later when it goes off the screen or is no longer needed. Also - bear in mind that if the component keeps a reference to the item that - created it, that item could be deleted before the component. Its position - and size will be completely managed by the tree, so don't attempt to move it - around. - - Something you may want to do with your component is to give it a pointer to - the TreeView that created it. This is perfectly safe, and there's no danger - of it becoming a dangling pointer because the TreeView will always delete - the component before it is itself deleted. - - As long as you stick to these rules you can return whatever kind of - component you like. It's most useful if you're doing things like drag-and-drop - of items, or want to use a Label component to edit item names, etc. - */ - virtual Component* createItemComponent() { return 0; } - - /** Draws the item's contents. - - You can choose to either implement this method and draw each item, or you - can use createItemComponent() to create a component that will represent the - item. - - If all you need in your tree is to be able to draw the items and detect when - the user selects or double-clicks one of them, it's probably enough to - use paintItem(), itemClicked() and itemDoubleClicked(). If you need more - complicated interactions, you may need to use createItemComponent() instead. - - @param g the graphics context to draw into - @param width the width of the area available for drawing - @param height the height of the area available for drawing - */ - virtual void paintItem (Graphics& g, int width, int height); - - /** Draws the item's open/close button. - - If you don't implement this method, the default behaviour is to - call LookAndFeel::drawTreeviewPlusMinusBox(), but you can override - it for custom effects. - */ - virtual void paintOpenCloseButton (Graphics& g, int width, int height, bool isMouseOver); - - /** Called when the user clicks on this item. - - If you're using createItemComponent() to create a custom component for the - item, the mouse-clicks might not make it through to the treeview, but this - is how you find out about clicks when just drawing each item individually. - - The associated mouse-event details are passed in, so you can find out about - which button, where it was, etc. - - @see itemDoubleClicked - */ - virtual void itemClicked (const MouseEvent& e); - - /** Called when the user double-clicks on this item. - - If you're using createItemComponent() to create a custom component for the - item, the mouse-clicks might not make it through to the treeview, but this - is how you find out about clicks when just drawing each item individually. - - The associated mouse-event details are passed in, so you can find out about - which button, where it was, etc. - - If not overridden, the base class method here will open or close the item as - if the 'plus' button had been clicked. - - @see itemClicked - */ - virtual void itemDoubleClicked (const MouseEvent& e); - - /** Called when the item is selected or deselected. - - Use this if you want to do something special when the item's selectedness - changes. By default it'll get repainted when this happens. - */ - virtual void itemSelectionChanged (bool isNowSelected); - - /** The item can return a tool tip string here if it wants to. - @see TooltipClient - */ - virtual const String getTooltip(); - - /** To allow items from your treeview to be dragged-and-dropped, implement this method. - - If this returns a non-empty name then when the user drags an item, the treeview will - try to find a DragAndDropContainer in its parent hierarchy, and will use it to trigger - a drag-and-drop operation, using this string as the source description, with the treeview - itself as the source component. - - If you need more complex drag-and-drop behaviour, you can use custom components for - the items, and use those to trigger the drag. - - To accept drag-and-drop in your tree, see isInterestedInDragSource(), - isInterestedInFileDrag(), etc. - - @see DragAndDropContainer::startDragging - */ - virtual const String getDragSourceDescription(); - - /** If you want your item to be able to have files drag-and-dropped onto it, implement this - method and return true. - - If you return true and allow some files to be dropped, you'll also need to implement the - filesDropped() method to do something with them. - - Note that this will be called often, so make your implementation very quick! There's - certainly no time to try opening the files and having a think about what's inside them! - - For responding to internal drag-and-drop of other types of object, see isInterestedInDragSource(). - @see FileDragAndDropTarget::isInterestedInFileDrag, isInterestedInDragSource - */ - virtual bool isInterestedInFileDrag (const StringArray& files); - - /** When files are dropped into this item, this callback is invoked. - - For this to work, you'll need to have also implemented isInterestedInFileDrag(). - The insertIndex value indicates where in the list of sub-items the files were dropped. - @see FileDragAndDropTarget::filesDropped, isInterestedInFileDrag - */ - virtual void filesDropped (const StringArray& files, int insertIndex); - - /** If you want your item to act as a DragAndDropTarget, implement this method and return true. - - If you implement this method, you'll also need to implement itemDropped() in order to handle - the items when they are dropped. - To respond to drag-and-drop of files from external applications, see isInterestedInFileDrag(). - @see DragAndDropTarget::isInterestedInDragSource, itemDropped - */ - virtual bool isInterestedInDragSource (const String& sourceDescription, Component* sourceComponent); - - /** When a things are dropped into this item, this callback is invoked. - - For this to work, you need to have also implemented isInterestedInDragSource(). - The insertIndex value indicates where in the list of sub-items the new items should be placed. - @see isInterestedInDragSource, DragAndDropTarget::itemDropped - */ - virtual void itemDropped (const String& sourceDescription, Component* sourceComponent, int insertIndex); - - /** Sets a flag to indicate that the item wants to be allowed - to draw all the way across to the left edge of the treeview. - - By default this is false, which means that when the paintItem() - method is called, its graphics context is clipped to only allow - drawing within the item's rectangle. If this flag is set to true, - then the graphics context isn't clipped on its left side, so it - can draw all the way across to the left margin. Note that the - context will still have its origin in the same place though, so - the coordinates of anything to its left will be negative. It's - mostly useful if you want to draw a wider bar behind the - highlighted item. - */ - void setDrawsInLeftMargin (bool canDrawInLeftMargin) throw(); - - /** Saves the current state of open/closed nodes so it can be restored later. - - This takes a snapshot of which sub-nodes have been explicitly opened or closed, - and records it as XML. To identify node objects it uses the - TreeViewItem::getUniqueName() method to create named paths. This - means that the same state of open/closed nodes can be restored to a - completely different instance of the tree, as long as it contains nodes - whose unique names are the same. - - You'd normally want to use TreeView::getOpennessState() rather than call it - for a specific item, but this can be handy if you need to briefly save the state - for a section of the tree. - - The caller is responsible for deleting the object that is returned. - @see TreeView::getOpennessState, restoreOpennessState - */ - XmlElement* getOpennessState() const throw(); - - /** Restores the openness of this item and all its sub-items from a saved state. - - See TreeView::restoreOpennessState for more details. - - You'd normally want to use TreeView::restoreOpennessState() rather than call it - for a specific item, but this can be handy if you need to briefly save the state - for a section of the tree. - - @see TreeView::restoreOpennessState, getOpennessState - */ - void restoreOpennessState (const XmlElement& xml) throw(); - - /** Returns the index of this item in its parent's sub-items. */ - int getIndexInParent() const throw(); - - /** Returns true if this item is the last of its parent's sub-itens. */ - bool isLastOfSiblings() const throw(); - - /** Creates a string that can be used to uniquely retrieve this item in the tree. - - The string that is returned can be passed to TreeView::findItemFromIdentifierString(). - The string takes the form of a path, constructed from the getUniqueName() of this - item and all its parents, so these must all be correctly implemented for it to work. - @see TreeView::findItemFromIdentifierString, getUniqueName - */ - const String getItemIdentifierString() const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - TreeView* ownerView; - TreeViewItem* parentItem; - OwnedArray subItems; - int y, itemHeight, totalHeight, itemWidth, totalWidth; - int uid; - bool selected : 1; - bool redrawNeeded : 1; - bool drawLinesInside : 1; - bool drawsInLeftMargin : 1; - unsigned int openness : 2; + TreeView* ownerView; + TreeViewItem* parentItem; + OwnedArray subItems; + int y, itemHeight, totalHeight, itemWidth, totalWidth; + int uid; + bool selected : 1; + bool redrawNeeded : 1; + bool drawLinesInside : 1; + bool drawsInLeftMargin : 1; + unsigned int openness : 2; - friend class TreeView; - friend class TreeViewContentComponent; + friend class TreeView; + friend class TreeViewContentComponent; - void updatePositions (int newY); - int getIndentX() const throw(); - void setOwnerView (TreeView* const newOwner) throw(); - void paintRecursively (Graphics& g, int width); - TreeViewItem* getTopLevelItem() throw(); - TreeViewItem* findItemRecursively (int y) throw(); - TreeViewItem* getDeepestOpenParentItem() throw(); - int getNumRows() const throw(); - TreeViewItem* getItemOnRow (int index) throw(); - void deselectAllRecursively(); - int countSelectedItemsRecursively() const throw(); - TreeViewItem* getSelectedItemWithIndex (int index) throw(); - TreeViewItem* getNextVisibleItem (const bool recurse) const throw(); - TreeViewItem* findItemFromIdentifierString (const String& identifierString); + void updatePositions (int newY); + int getIndentX() const throw(); + void setOwnerView (TreeView* const newOwner) throw(); + void paintRecursively (Graphics& g, int width); + TreeViewItem* getTopLevelItem() throw(); + TreeViewItem* findItemRecursively (int y) throw(); + TreeViewItem* getDeepestOpenParentItem() throw(); + int getNumRows() const throw(); + TreeViewItem* getItemOnRow (int index) throw(); + void deselectAllRecursively(); + int countSelectedItemsRecursively() const throw(); + TreeViewItem* getSelectedItemWithIndex (int index) throw(); + TreeViewItem* getNextVisibleItem (const bool recurse) const throw(); + TreeViewItem* findItemFromIdentifierString (const String& identifierString); - TreeViewItem (const TreeViewItem&); - const TreeViewItem& operator= (const TreeViewItem&); + TreeViewItem (const TreeViewItem&); + const TreeViewItem& operator= (const TreeViewItem&); }; -/** - A tree-view component. - - Use one of these to hold and display a structure of TreeViewItem objects. - -*/ class JUCE_API TreeView : public Component, - public SettableTooltipClient, - public FileDragAndDropTarget, - public DragAndDropTarget, - private AsyncUpdater + public SettableTooltipClient, + public FileDragAndDropTarget, + public DragAndDropTarget, + private AsyncUpdater { public: - /** Creates an empty treeview. + TreeView (const String& componentName = String::empty); - Once you've got a treeview component, you'll need to give it something to - display, using the setRootItem() method. - */ - TreeView (const String& componentName = String::empty); + ~TreeView(); - /** Destructor. */ - ~TreeView(); + void setRootItem (TreeViewItem* const newRootItem); - /** Sets the item that is displayed in the treeview. + TreeViewItem* getRootItem() const throw() { return rootItem; } - A tree has a single root item which contains as many sub-items as it needs. If - you want the tree to contain a number of root items, you should still use a single - root item above these, but hide it using setRootItemVisible(). + void deleteRootItem(); - You can pass in 0 to this method to clear the tree and remove its current root item. + void setRootItemVisible (const bool shouldBeVisible); - The object passed in will not be deleted by the treeview, it's up to the caller - to delete it when no longer needed. BUT make absolutely sure that you don't delete - this item until you've removed it from the tree, either by calling setRootItem (0), - or by deleting the tree first. You can also use deleteRootItem() as a quick way - to delete it. - */ - void setRootItem (TreeViewItem* const newRootItem); + bool isRootItemVisible() const throw() { return rootItemVisible; } - /** Returns the tree's root item. + void setDefaultOpenness (const bool isOpenByDefault); - This will be the last object passed to setRootItem(), or 0 if none has been set. - */ - TreeViewItem* getRootItem() const throw() { return rootItem; } + bool areItemsOpenByDefault() const throw() { return defaultOpenness; } - /** This will remove and delete the current root item. + void setMultiSelectEnabled (const bool canMultiSelect); - It's a convenient way of deleting the item and calling setRootItem (0). - */ - void deleteRootItem(); + bool isMultiSelectEnabled() const throw() { return multiSelectEnabled; } - /** Changes whether the tree's root item is shown or not. + void setOpenCloseButtonsVisible (const bool shouldBeVisible); - If the root item is hidden, only its sub-items will be shown in the treeview - this - lets you make the tree look as if it's got many root items. If it's hidden, this call - will also make sure the root item is open (otherwise the treeview would look empty). - */ - void setRootItemVisible (const bool shouldBeVisible); + bool areOpenCloseButtonsVisible() const throw() { return openCloseButtonsVisible; } - /** Returns true if the root item is visible. + void clearSelectedItems(); - @see setRootItemVisible - */ - bool isRootItemVisible() const throw() { return rootItemVisible; } + int getNumSelectedItems() const throw(); - /** Sets whether items are open or closed by default. + TreeViewItem* getSelectedItem (const int index) const throw(); - Normally, items are closed until the user opens them, but you can use this - to make them default to being open until explicitly closed. + int getNumRowsInTree() const; - @see areItemsOpenByDefault - */ - void setDefaultOpenness (const bool isOpenByDefault); + TreeViewItem* getItemOnRow (int index) const; - /** Returns true if the tree's items default to being open. + TreeViewItem* getItemAt (int yPosition) const throw(); - @see setDefaultOpenness - */ - bool areItemsOpenByDefault() const throw() { return defaultOpenness; } + void scrollToKeepItemVisible (TreeViewItem* item); - /** This sets a flag to indicate that the tree can be used for multi-selection. + Viewport* getViewport() const throw() { return viewport; } - You can always select multiple items internally by calling the - TreeViewItem::setSelected() method, but this flag indicates whether the user - is allowed to multi-select by clicking on the tree. + int getIndentSize() const throw() { return indentSize; } - By default it is disabled. + void setIndentSize (const int newIndentSize); - @see isMultiSelectEnabled - */ - void setMultiSelectEnabled (const bool canMultiSelect); + TreeViewItem* findItemFromIdentifierString (const String& identifierString) const; - /** Returns whether multi-select has been enabled for the tree. + XmlElement* getOpennessState (const bool alsoIncludeScrollPosition) const; - @see setMultiSelectEnabled - */ - bool isMultiSelectEnabled() const throw() { return multiSelectEnabled; } + void restoreOpennessState (const XmlElement& newState); - /** Sets a flag to indicate whether to hide the open/close buttons. + enum ColourIds + { + backgroundColourId = 0x1000500, /**< A background colour to fill the component with. */ + linesColourId = 0x1000501, /**< The colour to draw the lines with.*/ + dragAndDropIndicatorColourId = 0x1000502 /**< The colour to use for the drag-and-drop target position indicator. */ + }; - @see areOpenCloseButtonsVisible - */ - void setOpenCloseButtonsVisible (const bool shouldBeVisible); + void paint (Graphics& g); + void resized(); + bool keyPressed (const KeyPress& key); + void colourChanged(); + void enablementChanged(); + bool isInterestedInFileDrag (const StringArray& files); + void fileDragEnter (const StringArray& files, int x, int y); + void fileDragMove (const StringArray& files, int x, int y); + void fileDragExit (const StringArray& files); + void filesDropped (const StringArray& files, int x, int y); + bool isInterestedInDragSource (const String& sourceDescription, Component* sourceComponent); + void itemDragEnter (const String& sourceDescription, Component* sourceComponent, int x, int y); + void itemDragMove (const String& sourceDescription, Component* sourceComponent, int x, int y); + void itemDragExit (const String& sourceDescription, Component* sourceComponent); + void itemDropped (const String& sourceDescription, Component* sourceComponent, int x, int y); - /** Returns whether open/close buttons are shown. - - @see setOpenCloseButtonsVisible - */ - bool areOpenCloseButtonsVisible() const throw() { return openCloseButtonsVisible; } - - /** Deselects any items that are currently selected. */ - void clearSelectedItems(); - - /** Returns the number of items that are currently selected. - - @see getSelectedItem, clearSelectedItems - */ - int getNumSelectedItems() const throw(); - - /** Returns one of the selected items in the tree. - - @param index the index, 0 to (getNumSelectedItems() - 1) - */ - TreeViewItem* getSelectedItem (const int index) const throw(); - - /** Returns the number of rows the tree is using. - - This will depend on which items are open. - - @see TreeViewItem::getRowNumberInTree() - */ - int getNumRowsInTree() const; - - /** Returns the item on a particular row of the tree. - - If the index is out of range, this will return 0. - - @see getNumRowsInTree, TreeViewItem::getRowNumberInTree() - */ - TreeViewItem* getItemOnRow (int index) const; - - /** Returns the item that contains a given y position. - The y is relative to the top of the TreeView component. - */ - TreeViewItem* getItemAt (int yPosition) const throw(); - - /** Tries to scroll the tree so that this item is on-screen somewhere. */ - void scrollToKeepItemVisible (TreeViewItem* item); - - /** Returns the treeview's Viewport object. */ - Viewport* getViewport() const throw() { return viewport; } - - /** Returns the number of pixels by which each nested level of the tree is indented. - @see setIndentSize - */ - int getIndentSize() const throw() { return indentSize; } - - /** Changes the distance by which each nested level of the tree is indented. - @see getIndentSize - */ - void setIndentSize (const int newIndentSize); - - /** Searches the tree for an item with the specified identifier. - The identifer string must have been created by calling TreeViewItem::getItemIdentifierString(). - If no such item exists, this will return false. If the item is found, all of its items - will be automatically opened. - */ - TreeViewItem* findItemFromIdentifierString (const String& identifierString) const; - - /** Saves the current state of open/closed nodes so it can be restored later. - - This takes a snapshot of which nodes have been explicitly opened or closed, - and records it as XML. To identify node objects it uses the - TreeViewItem::getUniqueName() method to create named paths. This - means that the same state of open/closed nodes can be restored to a - completely different instance of the tree, as long as it contains nodes - whose unique names are the same. - - The caller is responsible for deleting the object that is returned. - - @param alsoIncludeScrollPosition if this is true, the state will also - include information about where the - tree has been scrolled to vertically, - so this can also be restored - @see restoreOpennessState - */ - XmlElement* getOpennessState (const bool alsoIncludeScrollPosition) const; - - /** Restores a previously saved arrangement of open/closed nodes. - - This will try to restore a snapshot of the tree's state that was created by - the getOpennessState() method. If any of the nodes named in the original - XML aren't present in this tree, they will be ignored. - - @see getOpennessState - */ - void restoreOpennessState (const XmlElement& newState); - - /** A set of colour IDs to use to change the colour of various aspects of the treeview. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1000500, /**< A background colour to fill the component with. */ - linesColourId = 0x1000501, /**< The colour to draw the lines with.*/ - dragAndDropIndicatorColourId = 0x1000502 /**< The colour to use for the drag-and-drop target position indicator. */ - }; - - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void resized(); - /** @internal */ - bool keyPressed (const KeyPress& key); - /** @internal */ - void colourChanged(); - /** @internal */ - void enablementChanged(); - /** @internal */ - bool isInterestedInFileDrag (const StringArray& files); - /** @internal */ - void fileDragEnter (const StringArray& files, int x, int y); - /** @internal */ - void fileDragMove (const StringArray& files, int x, int y); - /** @internal */ - void fileDragExit (const StringArray& files); - /** @internal */ - void filesDropped (const StringArray& files, int x, int y); - /** @internal */ - bool isInterestedInDragSource (const String& sourceDescription, Component* sourceComponent); - /** @internal */ - void itemDragEnter (const String& sourceDescription, Component* sourceComponent, int x, int y); - /** @internal */ - void itemDragMove (const String& sourceDescription, Component* sourceComponent, int x, int y); - /** @internal */ - void itemDragExit (const String& sourceDescription, Component* sourceComponent); - /** @internal */ - void itemDropped (const String& sourceDescription, Component* sourceComponent, int x, int y); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class TreeViewItem; - friend class TreeViewContentComponent; - Viewport* viewport; - CriticalSection nodeAlterationLock; - TreeViewItem* rootItem; - Component* dragInsertPointHighlight; - Component* dragTargetGroupHighlight; - int indentSize; - bool defaultOpenness : 1; - bool needsRecalculating : 1; - bool rootItemVisible : 1; - bool multiSelectEnabled : 1; - bool openCloseButtonsVisible : 1; + friend class TreeViewItem; + friend class TreeViewContentComponent; + Viewport* viewport; + CriticalSection nodeAlterationLock; + TreeViewItem* rootItem; + Component* dragInsertPointHighlight; + Component* dragTargetGroupHighlight; + int indentSize; + bool defaultOpenness : 1; + bool needsRecalculating : 1; + bool rootItemVisible : 1; + bool multiSelectEnabled : 1; + bool openCloseButtonsVisible : 1; - void itemsChanged() throw(); - void handleAsyncUpdate(); - void moveSelectedRow (int delta); - void updateButtonUnderMouse (const MouseEvent& e); - void showDragHighlight (TreeViewItem* item, int insertIndex, int x, int y) throw(); - void hideDragHighlight() throw(); - void handleDrag (const StringArray& files, const String& sourceDescription, Component* sourceComponent, int x, int y); - void handleDrop (const StringArray& files, const String& sourceDescription, Component* sourceComponent, int x, int y); - TreeViewItem* getInsertPosition (int& x, int& y, int& insertIndex, - const StringArray& files, const String& sourceDescription, - Component* sourceComponent) const throw(); + void itemsChanged() throw(); + void handleAsyncUpdate(); + void moveSelectedRow (int delta); + void updateButtonUnderMouse (const MouseEvent& e); + void showDragHighlight (TreeViewItem* item, int insertIndex, int x, int y) throw(); + void hideDragHighlight() throw(); + void handleDrag (const StringArray& files, const String& sourceDescription, Component* sourceComponent, int x, int y); + void handleDrop (const StringArray& files, const String& sourceDescription, Component* sourceComponent, int x, int y); + TreeViewItem* getInsertPosition (int& x, int& y, int& insertIndex, + const StringArray& files, const String& sourceDescription, + Component* sourceComponent) const throw(); - TreeView (const TreeView&); - const TreeView& operator= (const TreeView&); + TreeView (const TreeView&); + const TreeView& operator= (const TreeView&); }; #endif // __JUCE_TREEVIEW_JUCEHEADER__ @@ -45276,43 +21429,23 @@ private: #ifndef __JUCE_FILEFILTER_JUCEHEADER__ #define __JUCE_FILEFILTER_JUCEHEADER__ -/** - Interface for deciding which files are suitable for something. - - For example, this is used by DirectoryContentsList to select which files - go into the list. - - @see WildcardFileFilter, DirectoryContentsList, FileListComponent, FileBrowserComponent -*/ class JUCE_API FileFilter { public: - /** Creates a filter with the given description. + FileFilter (const String& filterDescription); - The description can be returned later with the getDescription() method. - */ - FileFilter (const String& filterDescription); + virtual ~FileFilter(); - /** Destructor. */ - virtual ~FileFilter(); + const String& getDescription() const throw(); - /** Returns the description that the filter was created with. */ - const String& getDescription() const throw(); + virtual bool isFileSuitable (const File& file) const = 0; - /** Should return true if this file is suitable for inclusion in whatever context - the object is being used. - */ - virtual bool isFileSuitable (const File& file) const = 0; - - /** Should return true if this directory is suitable for inclusion in whatever context - the object is being used. - */ - virtual bool isDirectorySuitable (const File& file) const = 0; + virtual bool isDirectorySuitable (const File& file) const = 0; protected: - String description; + String description; }; #endif // __JUCE_FILEFILTER_JUCEHEADER__ @@ -45322,446 +21455,196 @@ protected: #ifndef __JUCE_IMAGE_JUCEHEADER__ #define __JUCE_IMAGE_JUCEHEADER__ -/** - Holds a fixed-size bitmap. - - The image is stored in either 24-bit RGB or 32-bit premultiplied-ARGB format. - - To draw into an image, create a Graphics object for it. - e.g. @code - - // create a transparent 500x500 image.. - Image myImage (Image::RGB, 500, 500, true); - - Graphics g (myImage); - g.setColour (Colours::red); - g.fillEllipse (20, 20, 300, 200); // draws a red ellipse in our image. - @endcode - - Other useful ways to create an image are with the ImageCache class, or the - ImageFileFormat, which provides a way to load common image files. - - @see Graphics, ImageFileFormat, ImageCache, ImageConvolutionKernel -*/ class JUCE_API Image { public: - enum PixelFormat - { - RGB, /**<< each pixel is a 3-byte packed RGB colour value. For byte order, see the PixelRGB class. */ - ARGB, /**<< each pixel is a 4-byte ARGB premultiplied colour value. For byte order, see the PixelARGB class. */ - SingleChannel /**<< each pixel is a 1-byte alpha channel value. */ - }; + enum PixelFormat + { + RGB, /**<< each pixel is a 3-byte packed RGB colour value. For byte order, see the PixelRGB class. */ + ARGB, /**<< each pixel is a 4-byte ARGB premultiplied colour value. For byte order, see the PixelARGB class. */ + SingleChannel /**<< each pixel is a 1-byte alpha channel value. */ + }; - /** Creates an in-memory image with a specified size and format. + Image (const PixelFormat format, + const int imageWidth, + const int imageHeight, + const bool clearImage); - To create an image that can use native OS rendering methods, see createNativeImage(). + Image (const Image& other); - @param format the number of colour channels in the image - @param imageWidth the desired width of the image, in pixels - this value must be - greater than zero (otherwise a width of 1 will be used) - @param imageHeight the desired width of the image, in pixels - this value must be - greater than zero (otherwise a height of 1 will be used) - @param clearImage if true, the image will initially be cleared to black or transparent - black. If false, the image may contain random data, and the - user will have to deal with this - */ - Image (const PixelFormat format, - const int imageWidth, - const int imageHeight, - const bool clearImage); + virtual ~Image(); - /** Creates a copy of another image. + static Image* createNativeImage (const PixelFormat format, + const int imageWidth, + const int imageHeight, + const bool clearImage); - @see createCopy - */ - Image (const Image& other); + int getWidth() const throw() { return imageWidth; } - /** Destructor. */ - virtual ~Image(); + int getHeight() const throw() { return imageHeight; } - /** Tries to create an image that is uses native drawing methods when you render - onto it. + const Rectangle getBounds() const throw() { return Rectangle (0, 0, imageWidth, imageHeight); } - On some platforms this will just return a normal software-based image. - */ - static Image* createNativeImage (const PixelFormat format, - const int imageWidth, - const int imageHeight, - const bool clearImage); + PixelFormat getFormat() const throw() { return format; } - /** Returns the image's width (in pixels). */ - int getWidth() const throw() { return imageWidth; } + bool isARGB() const throw() { return format == ARGB; } - /** Returns the image's height (in pixels). */ - int getHeight() const throw() { return imageHeight; } + bool isRGB() const throw() { return format == RGB; } - /** Returns a rectangle with the same size as this image. - The rectangle is always at position (0, 0). - */ - const Rectangle getBounds() const throw() { return Rectangle (0, 0, imageWidth, imageHeight); } + bool hasAlphaChannel() const throw() { return format != RGB; } - /** Returns the image's pixel format. */ - PixelFormat getFormat() const throw() { return format; } + virtual void clear (int x, int y, int w, int h, + const Colour& colourToClearTo = Colour (0x00000000)); - /** True if the image's format is ARGB. */ - bool isARGB() const throw() { return format == ARGB; } + virtual Image* createCopy (int newWidth = -1, + int newHeight = -1, + const Graphics::ResamplingQuality quality = Graphics::mediumResamplingQuality) const; - /** True if the image's format is RGB. */ - bool isRGB() const throw() { return format == RGB; } + virtual Image* createCopyOfAlphaChannel() const; - /** True if the image contains an alpha-channel. */ - bool hasAlphaChannel() const throw() { return format != RGB; } + virtual const Colour getPixelAt (const int x, const int y) const; - /** Clears a section of the image with a given colour. + virtual void setPixelAt (const int x, const int y, const Colour& colour); - This won't do any alpha-blending - it just sets all pixels in the image to - the given colour (which may be non-opaque if the image has an alpha channel). - */ - virtual void clear (int x, int y, int w, int h, - const Colour& colourToClearTo = Colour (0x00000000)); + virtual void multiplyAlphaAt (const int x, const int y, const float multiplier); - /** Returns a new image that's a copy of this one. + virtual void multiplyAllAlphas (const float amountToMultiplyBy); - A new size for the copied image can be specified, or values less than - zero can be passed-in to use the image's existing dimensions. + virtual void desaturate(); - It's up to the caller to delete the image when no longer needed. - */ - virtual Image* createCopy (int newWidth = -1, - int newHeight = -1, - const Graphics::ResamplingQuality quality = Graphics::mediumResamplingQuality) const; + class BitmapData + { + public: + BitmapData (Image& image, int x, int y, int w, int h, const bool needsToBeWritable); + BitmapData (const Image& image, int x, int y, int w, int h); + ~BitmapData(); - /** Returns a new single-channel image which is a copy of the alpha-channel of this image. - */ - virtual Image* createCopyOfAlphaChannel() const; + inline uint8* getLinePointer (const int y) const { return data + y * lineStride; } - /** Returns the colour of one of the pixels in the image. + inline uint8* getPixelPointer (const int x, const int y) const { return data + y * lineStride + x * pixelStride; } - If the co-ordinates given are beyond the image's boundaries, this will - return Colours::transparentBlack. + uint8* data; + int lineStride, pixelStride, width, height; - (0, 0) is the image's top-left corner. + private: + BitmapData (const BitmapData&); + const BitmapData& operator= (const BitmapData&); + }; - @see getAlphaAt, setPixelAt, blendPixelAt - */ - virtual const Colour getPixelAt (const int x, const int y) const; + virtual void setPixelData (int destX, int destY, int destW, int destH, + const uint8* sourcePixelData, int sourceLineStride); - /** Sets the colour of one of the image's pixels. + virtual void moveImageSection (int destX, int destY, + int sourceX, int sourceY, + int width, int height); - If the co-ordinates are beyond the image's boundaries, then nothing will - happen. + void createSolidAreaMask (RectangleList& result, + const float alphaThreshold = 0.5f) const; - Note that unlike blendPixelAt(), this won't do any alpha-blending, it'll - just replace the existing pixel with the given one. The colour's opacity - will be ignored if this image doesn't have an alpha-channel. + juce_UseDebuggingNewOperator - (0, 0) is the image's top-left corner. - - @see blendPixelAt - */ - virtual void setPixelAt (const int x, const int y, const Colour& colour); - - /** Changes the opacity of a pixel. - - This only has an effect if the image has an alpha channel and if the - given co-ordinates are inside the image's boundary. - - The multiplier must be in the range 0 to 1.0, and the current alpha - at the given co-ordinates will be multiplied by this value. - - @see getAlphaAt, setPixelAt - */ - virtual void multiplyAlphaAt (const int x, const int y, const float multiplier); - - /** Changes the overall opacity of the image. - - This will multiply the alpha value of each pixel in the image by the given - amount (limiting the resulting alpha values between 0 and 255). This allows - you to make an image more or less transparent. - - If the image doesn't have an alpha channel, this won't have any effect. - */ - virtual void multiplyAllAlphas (const float amountToMultiplyBy); - - /** Changes all the colours to be shades of grey, based on their current luminosity. - */ - virtual void desaturate(); - - /** Retrieves a section of an image as raw pixel data, so it can be read or written to. - - You should only use this class as a last resort - messing about with the internals of - an image is only recommended for people who really know what they're doing! - - A BitmapData object should be used as a temporary, stack-based object. Don't keep one - hanging around while the image is being used elsewhere. - - Depending on the way the image class is implemented, this may create a temporary buffer - which is copied back to the image when the object is deleted, or it may just get a pointer - directly into the image's raw data. - - You can use the stride and data values in this class directly, but don't alter them! - The actual format of the pixel data depends on the image's format - see Image::getFormat(), - and the PixelRGB, PixelARGB and PixelAlpha classes for more info. - */ - class BitmapData - { - public: - BitmapData (Image& image, int x, int y, int w, int h, const bool needsToBeWritable); - BitmapData (const Image& image, int x, int y, int w, int h); - ~BitmapData(); - - /** Returns a pointer to the start of a line in the image. - The co-ordinate you provide here isn't checked, so it's the caller's responsibility to make - sure it's not out-of-range. - */ - inline uint8* getLinePointer (const int y) const { return data + y * lineStride; } - - /** Returns a pointer to a pixel in the image. - The co-ordinates you give here are not checked, so it's the caller's responsibility to make sure they're - not out-of-range. - */ - inline uint8* getPixelPointer (const int x, const int y) const { return data + y * lineStride + x * pixelStride; } - - uint8* data; - int lineStride, pixelStride, width, height; - - private: - BitmapData (const BitmapData&); - const BitmapData& operator= (const BitmapData&); - }; - - /** Copies some pixel values to a rectangle of the image. - - The format of the pixel data must match that of the image itself, and the - rectangle supplied must be within the image's bounds. - */ - virtual void setPixelData (int destX, int destY, int destW, int destH, - const uint8* sourcePixelData, int sourceLineStride); - - /** Copies a section of the image to somewhere else within itself. - */ - virtual void moveImageSection (int destX, int destY, - int sourceX, int sourceY, - int width, int height); - - /** Creates a RectangleList containing rectangles for all non-transparent pixels - of the image. - - @param result the list that will have the area added to it - @param alphaThreshold for a semi-transparent image, any pixels whose alpha is - above this level will be considered opaque - */ - void createSolidAreaMask (RectangleList& result, - const float alphaThreshold = 0.5f) const; - - juce_UseDebuggingNewOperator - - /** Creates a context suitable for drawing onto this image. - - Don't call this method directly! It's used internally by the Graphics class. - */ - virtual LowLevelGraphicsContext* createLowLevelContext(); + virtual LowLevelGraphicsContext* createLowLevelContext(); protected: - friend class BitmapData; - const PixelFormat format; - const int imageWidth, imageHeight; + friend class BitmapData; + const PixelFormat format; + const int imageWidth, imageHeight; - /** Used internally so that subclasses can call a constructor that doesn't allocate memory */ - Image (const PixelFormat format, - const int imageWidth, - const int imageHeight); + Image (const PixelFormat format, + const int imageWidth, + const int imageHeight); - int pixelStride, lineStride; - HeapBlock imageDataAllocated; - uint8* imageData; + int pixelStride, lineStride; + HeapBlock imageDataAllocated; + uint8* imageData; private: - const Image& operator= (const Image&); + const Image& operator= (const Image&); }; #endif // __JUCE_IMAGE_JUCEHEADER__ /********* End of inlined file: juce_Image.h *********/ -/** - A class to asynchronously scan for details about the files in a directory. - - This keeps a list of files and some information about them, using a background - thread to scan for more files. As files are found, it broadcasts change messages - to tell any listeners. - - @see FileListComponent, FileBrowserComponent -*/ class JUCE_API DirectoryContentsList : public ChangeBroadcaster, - public TimeSliceClient + public TimeSliceClient { public: - /** Creates a directory list. + DirectoryContentsList (const FileFilter* const fileFilter, + TimeSliceThread& threadToUse); - To set the directory it should point to, use setDirectory(), which will - also start it scanning for files on the background thread. + ~DirectoryContentsList(); - When the background thread finds and adds new files to this list, the - ChangeBroadcaster class will send a change message, so you can register - listeners and update them when the list changes. + void setDirectory (const File& directory, + const bool includeDirectories, + const bool includeFiles); - @param fileFilter an optional filter to select which files are - included in the list. If this is 0, then all files - and directories are included. Make sure that the - filter doesn't get deleted during the lifetime of this - object - @param threadToUse a thread object that this list can use - to scan for files as a background task. Make sure - that the thread you give it has been started, or you - won't get any files! - */ - DirectoryContentsList (const FileFilter* const fileFilter, - TimeSliceThread& threadToUse); + const File& getDirectory() const; - /** Destructor. */ - ~DirectoryContentsList(); + void clear(); - /** Sets the directory to look in for files. + void refresh(); - If the directory that's passed in is different to the current one, this will - also start the background thread scanning it for files. - */ - void setDirectory (const File& directory, - const bool includeDirectories, - const bool includeFiles); + bool isStillLoading() const; - /** Returns the directory that's currently being used. */ - const File& getDirectory() const; + void setIgnoresHiddenFiles (const bool shouldIgnoreHiddenFiles); - /** Clears the list, and stops the thread scanning for files. */ - void clear(); + bool ignoresHiddenFiles() const { return ignoreHiddenFiles; } - /** Clears the list and restarts scanning the directory for files. */ - void refresh(); + struct FileInfo + { - /** True if the background thread hasn't yet finished scanning for files. */ - bool isStillLoading() const; + String filename; - /** Tells the list whether or not to ignore hidden files. + int64 fileSize; - By default these are ignored. - */ - void setIgnoresHiddenFiles (const bool shouldIgnoreHiddenFiles); + Time modificationTime; - /** Returns true if hidden files are ignored. - @see setIgnoresHiddenFiles - */ - bool ignoresHiddenFiles() const { return ignoreHiddenFiles; } + Time creationTime; - /** Contains cached information about one of the files in a DirectoryContentsList. - */ - struct FileInfo - { + bool isDirectory; - /** The filename. + bool isReadOnly; + }; - This isn't a full pathname, it's just the last part of the path, same as you'd - get from File::getFileName(). + int getNumFiles() const; - To get the full pathname, use DirectoryContentsList::getDirectory().getChildFile (filename). - */ - String filename; + bool getFileInfo (const int index, + FileInfo& resultInfo) const; - /** File size in bytes. */ - int64 fileSize; + const File getFile (const int index) const; - /** File modification time. + const FileFilter* getFilter() const { return fileFilter; } - As supplied by File::getLastModificationTime(). - */ - Time modificationTime; + bool useTimeSlice(); + TimeSliceThread& getTimeSliceThread() { return thread; } + static int compareElements (const DirectoryContentsList::FileInfo* const first, + const DirectoryContentsList::FileInfo* const second); - /** File creation time. - - As supplied by File::getCreationTime(). - */ - Time creationTime; - - /** True if the file is a directory. */ - bool isDirectory; - - /** True if the file is read-only. */ - bool isReadOnly; - }; - - /** Returns the number of files currently available in the list. - - The info about one of these files can be retrieved with getFileInfo() or - getFile(). - - Obviously as the background thread runs and scans the directory for files, this - number will change. - - @see getFileInfo, getFile - */ - int getNumFiles() const; - - /** Returns the cached information about one of the files in the list. - - If the index is in-range, this will return true and will copy the file's details - to the structure that is passed-in. - - If it returns false, then the index wasn't in range, and the structure won't - be affected. - - @see getNumFiles, getFile - */ - bool getFileInfo (const int index, - FileInfo& resultInfo) const; - - /** Returns one of the files in the list. - - @param index should be less than getNumFiles(). If this is out-of-range, the - return value will be File::nonexistent - @see getNumFiles, getFileInfo - */ - const File getFile (const int index) const; - - /** Returns the file filter being used. - - The filter is specified in the constructor. - */ - const FileFilter* getFilter() const { return fileFilter; } - - /** @internal */ - bool useTimeSlice(); - /** @internal */ - TimeSliceThread& getTimeSliceThread() { return thread; } - /** @internal */ - static int compareElements (const DirectoryContentsList::FileInfo* const first, - const DirectoryContentsList::FileInfo* const second); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - File root; - const FileFilter* fileFilter; - TimeSliceThread& thread; - bool includeDirectories, includeFiles, ignoreHiddenFiles; + File root; + const FileFilter* fileFilter; + TimeSliceThread& thread; + bool includeDirectories, includeFiles, ignoreHiddenFiles; - CriticalSection fileListLock; - OwnedArray files; + CriticalSection fileListLock; + OwnedArray files; - void* volatile fileFindHandle; - bool volatile shouldStop; + void* volatile fileFindHandle; + bool volatile shouldStop; - void changed(); - bool checkNextFile (bool& hasChanged); - bool addFile (const String& filename, const bool isDir, const bool isHidden, - const int64 fileSize, const Time& modTime, - const Time& creationTime, const bool isReadOnly); + void changed(); + bool checkNextFile (bool& hasChanged); + bool addFile (const String& filename, const bool isDir, const bool isHidden, + const int64 fileSize, const Time& modTime, + const Time& creationTime, const bool isReadOnly); - DirectoryContentsList (const DirectoryContentsList&); - const DirectoryContentsList& operator= (const DirectoryContentsList&); + DirectoryContentsList (const DirectoryContentsList&); + const DirectoryContentsList& operator= (const DirectoryContentsList&); }; #endif // __JUCE_DIRECTORYCONTENTSLIST_JUCEHEADER__ @@ -45771,104 +21654,58 @@ private: #ifndef __JUCE_FILEBROWSERLISTENER_JUCEHEADER__ #define __JUCE_FILEBROWSERLISTENER_JUCEHEADER__ -/** - A listener for user selection events in a file browser. - - This is used by a FileBrowserComponent or FileListComponent. -*/ class JUCE_API FileBrowserListener { public: - /** Destructor. */ - virtual ~FileBrowserListener(); + virtual ~FileBrowserListener(); - /** Callback when the user selects a different file in the browser. */ - virtual void selectionChanged() = 0; + virtual void selectionChanged() = 0; - /** Callback when the user clicks on a file in the browser. */ - virtual void fileClicked (const File& file, const MouseEvent& e) = 0; + virtual void fileClicked (const File& file, const MouseEvent& e) = 0; - /** Callback when the user double-clicks on a file in the browser. */ - virtual void fileDoubleClicked (const File& file) = 0; + virtual void fileDoubleClicked (const File& file) = 0; }; #endif // __JUCE_FILEBROWSERLISTENER_JUCEHEADER__ /********* End of inlined file: juce_FileBrowserListener.h *********/ -/** - A base class for components that display a list of the files in a directory. - - @see DirectoryContentsList -*/ class JUCE_API DirectoryContentsDisplayComponent { public: - /** - */ - DirectoryContentsDisplayComponent (DirectoryContentsList& listToShow); + DirectoryContentsDisplayComponent (DirectoryContentsList& listToShow); - /** Destructor. */ - virtual ~DirectoryContentsDisplayComponent(); + virtual ~DirectoryContentsDisplayComponent(); - /** Returns the number of files the user has got selected. - @see getSelectedFile - */ - virtual int getNumSelectedFiles() const = 0; + virtual int getNumSelectedFiles() const = 0; - /** Returns one of the files that the user has currently selected. - The index should be in the range 0 to (getNumSelectedFiles() - 1). - @see getNumSelectedFiles - */ - virtual const File getSelectedFile (int index) const = 0; + virtual const File getSelectedFile (int index) const = 0; - /** Scrolls this view to the top. */ - virtual void scrollToTop() = 0; + virtual void scrollToTop() = 0; - /** Adds a listener to be told when files are selected or clicked. + void addListener (FileBrowserListener* const listener) throw(); - @see removeListener - */ - void addListener (FileBrowserListener* const listener) throw(); + void removeListener (FileBrowserListener* const listener) throw(); - /** Removes a listener. + enum ColourIds + { + highlightColourId = 0x1000540, /**< The colour to use to fill a highlighted row of the list. */ + textColourId = 0x1000541, /**< The colour for the text. */ + }; - @see addListener - */ - void removeListener (FileBrowserListener* const listener) throw(); + void sendSelectionChangeMessage(); + void sendDoubleClickMessage (const File& file); + void sendMouseClickMessage (const File& file, const MouseEvent& e); - /** A set of colour IDs to use to change the colour of various aspects of the label. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - Note that you can also use the constants from TextEditor::ColourIds to change the - colour of the text editor that is opened when a label is editable. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - highlightColourId = 0x1000540, /**< The colour to use to fill a highlighted row of the list. */ - textColourId = 0x1000541, /**< The colour for the text. */ - }; - - /** @internal */ - void sendSelectionChangeMessage(); - /** @internal */ - void sendDoubleClickMessage (const File& file); - /** @internal */ - void sendMouseClickMessage (const File& file, const MouseEvent& e); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - DirectoryContentsList& fileList; - SortedSet listeners; + DirectoryContentsList& fileList; + SortedSet listeners; - DirectoryContentsDisplayComponent (const DirectoryContentsDisplayComponent&); - const DirectoryContentsDisplayComponent& operator= (const DirectoryContentsDisplayComponent&); + DirectoryContentsDisplayComponent (const DirectoryContentsDisplayComponent&); + const DirectoryContentsDisplayComponent& operator= (const DirectoryContentsDisplayComponent&); }; #endif // __JUCE_DIRECTORYCONTENTSDISPLAYCOMPONENT_JUCEHEADER__ @@ -45888,230 +21725,126 @@ protected: #ifndef __JUCE_FILEPREVIEWCOMPONENT_JUCEHEADER__ #define __JUCE_FILEPREVIEWCOMPONENT_JUCEHEADER__ -/** - Base class for components that live inside a file chooser dialog box and - show previews of the files that get selected. - - One of these allows special extra information to be displayed for files - in a dialog box as the user selects them. Each time the current file or - directory is changed, the selectedFileChanged() method will be called - to allow it to update itself appropriately. - - @see FileChooser, ImagePreviewComponent -*/ class JUCE_API FilePreviewComponent : public Component { public: - /** Creates a FilePreviewComponent. */ - FilePreviewComponent(); + FilePreviewComponent(); - /** Destructor. */ - ~FilePreviewComponent(); + ~FilePreviewComponent(); - /** Called to indicate that the user's currently selected file has changed. + virtual void selectedFileChanged (const File& newSelectedFile) = 0; - @param newSelectedFile the newly selected file or directory, which may be - File::nonexistent if none is selected. - */ - virtual void selectedFileChanged (const File& newSelectedFile) = 0; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - FilePreviewComponent (const FilePreviewComponent&); - const FilePreviewComponent& operator= (const FilePreviewComponent&); + FilePreviewComponent (const FilePreviewComponent&); + const FilePreviewComponent& operator= (const FilePreviewComponent&); }; #endif // __JUCE_FILEPREVIEWCOMPONENT_JUCEHEADER__ /********* End of inlined file: juce_FilePreviewComponent.h *********/ -/** - A component for browsing and selecting a file or directory to open or save. - - This contains a FileListComponent and adds various boxes and controls for - navigating and selecting a file. It can work in different modes so that it can - be used for loading or saving a file, or for choosing a directory. - - @see FileChooserDialogBox, FileChooser, FileListComponent -*/ class JUCE_API FileBrowserComponent : public Component, - public ChangeBroadcaster, - private FileBrowserListener, - private TextEditorListener, - private ButtonListener, - private ComboBoxListener, - private FileFilter + public ChangeBroadcaster, + private FileBrowserListener, + private TextEditorListener, + private ButtonListener, + private ComboBoxListener, + private FileFilter { public: - /** Various options for the browser. + enum FileChooserFlags + { + openMode = 1, /**< specifies that the component should allow the user to + choose an existing file with the intention of opening it. */ + saveMode = 2, /**< specifies that the component should allow the user to specify + the name of a file that will be used to save something. */ + canSelectFiles = 4, /**< specifies that the user can select files (can be used in + conjunction with canSelectDirectories). */ + canSelectDirectories = 8, /**< specifies that the user can select directories (can be used in + conjuction with canSelectFiles). */ + canSelectMultipleItems = 16, /**< specifies that the user can select multiple items. */ + useTreeView = 32, /**< specifies that a tree-view should be shown instead of a file list. */ + filenameBoxIsReadOnly = 64 /**< specifies that the user can't type directly into the filename box. */ + }; - A combination of these is passed into the FileBrowserComponent constructor. - */ - enum FileChooserFlags - { - openMode = 1, /**< specifies that the component should allow the user to - choose an existing file with the intention of opening it. */ - saveMode = 2, /**< specifies that the component should allow the user to specify - the name of a file that will be used to save something. */ - canSelectFiles = 4, /**< specifies that the user can select files (can be used in - conjunction with canSelectDirectories). */ - canSelectDirectories = 8, /**< specifies that the user can select directories (can be used in - conjuction with canSelectFiles). */ - canSelectMultipleItems = 16, /**< specifies that the user can select multiple items. */ - useTreeView = 32, /**< specifies that a tree-view should be shown instead of a file list. */ - filenameBoxIsReadOnly = 64 /**< specifies that the user can't type directly into the filename box. */ - }; + FileBrowserComponent (int flags, + const File& initialFileOrDirectory, + const FileFilter* fileFilter, + FilePreviewComponent* previewComp); - /** Creates a FileBrowserComponent. + ~FileBrowserComponent(); - @param flags A combination of flags from the FileChooserFlags enumeration, - used to specify the component's behaviour. The flags must contain - either openMode or saveMode, and canSelectFiles and/or - canSelectDirectories. - @param initialFileOrDirectory The file or directory that should be selected when - the component begins. If this is File::nonexistent, - a default directory will be chosen. - @param fileFilter an optional filter to use to determine which files - are shown. If this is 0 then all files are displayed. Note - that a pointer is kept internally to this object, so - make sure that it is not deleted before the browser object - is deleted. - @param previewComp an optional preview component that will be used to - show previews of files that the user selects - */ - FileBrowserComponent (int flags, - const File& initialFileOrDirectory, - const FileFilter* fileFilter, - FilePreviewComponent* previewComp); + int getNumSelectedFiles() const throw(); - /** Destructor. */ - ~FileBrowserComponent(); + const File getSelectedFile (int index) const throw(); - /** Returns the number of files that the user has got selected. - If multiple select isn't active, this will only be 0 or 1. To get the complete - list of files they've chosen, pass an index to getCurrentFile(). - */ - int getNumSelectedFiles() const throw(); + bool currentFileIsValid() const; - /** Returns one of the files that the user has chosen. - If the box has multi-select enabled, the index lets you specify which of the files - to get - see getNumSelectedFiles() to find out how many files were chosen. - @see getHighlightedFile - */ - const File getSelectedFile (int index) const throw(); + const File getHighlightedFile() const throw(); - /** Returns true if the currently selected file(s) are usable. + const File getRoot() const; - This can be used to decide whether the user can press "ok" for the - current file. What it does depends on the mode, so for example in an "open" - mode, this only returns true if a file has been selected and if it exists. - In a "save" mode, a non-existent file would also be valid. - */ - bool currentFileIsValid() const; + void setRoot (const File& newRootDirectory); - /** This returns the last item in the view that the user has highlighted. - This may be different from getCurrentFile(), which returns the value - that is shown in the filename box, and if there are multiple selections, - this will only return one of them. - @see getCurrentFile - */ - const File getHighlightedFile() const throw(); + void goUp(); - /** Returns the directory whose contents are currently being shown in the listbox. */ - const File getRoot() const; + void refresh(); - /** Changes the directory that's being shown in the listbox. */ - void setRoot (const File& newRootDirectory); + virtual const String getActionVerb() const; - /** Equivalent to pressing the "up" button to browse the parent directory. */ - void goUp(); + bool isSaveMode() const throw(); - /** Refreshes the directory that's currently being listed. */ - void refresh(); + void addListener (FileBrowserListener* const listener) throw(); - /** Returns a verb to describe what should happen when the file is accepted. + void removeListener (FileBrowserListener* const listener) throw(); - E.g. if browsing in "load file" mode, this will be "Open", if in "save file" - mode, it'll be "Save", etc. - */ - virtual const String getActionVerb() const; + void resized(); + void buttonClicked (Button* b); + void comboBoxChanged (ComboBox*); + void textEditorTextChanged (TextEditor& editor); + void textEditorReturnKeyPressed (TextEditor& editor); + void textEditorEscapeKeyPressed (TextEditor& editor); + void textEditorFocusLost (TextEditor& editor); + bool keyPressed (const KeyPress& key); + void selectionChanged(); + void fileClicked (const File& f, const MouseEvent& e); + void fileDoubleClicked (const File& f); + bool isFileSuitable (const File& file) const; + bool isDirectorySuitable (const File&) const; - /** Returns true if the saveMode flag was set when this component was created. - */ - bool isSaveMode() const throw(); + FilePreviewComponent* getPreviewComponent() const throw(); - /** Adds a listener to be told when the user selects and clicks on files. - - @see removeListener - */ - void addListener (FileBrowserListener* const listener) throw(); - - /** Removes a listener. - - @see addListener - */ - void removeListener (FileBrowserListener* const listener) throw(); - - /** @internal */ - void resized(); - /** @internal */ - void buttonClicked (Button* b); - /** @internal */ - void comboBoxChanged (ComboBox*); - /** @internal */ - void textEditorTextChanged (TextEditor& editor); - /** @internal */ - void textEditorReturnKeyPressed (TextEditor& editor); - /** @internal */ - void textEditorEscapeKeyPressed (TextEditor& editor); - /** @internal */ - void textEditorFocusLost (TextEditor& editor); - /** @internal */ - bool keyPressed (const KeyPress& key); - /** @internal */ - void selectionChanged(); - /** @internal */ - void fileClicked (const File& f, const MouseEvent& e); - /** @internal */ - void fileDoubleClicked (const File& f); - /** @internal */ - bool isFileSuitable (const File& file) const; - /** @internal */ - bool isDirectorySuitable (const File&) const; - - /** @internal */ - FilePreviewComponent* getPreviewComponent() const throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - virtual const BitArray getRoots (StringArray& rootNames, StringArray& rootPaths); + virtual const BitArray getRoots (StringArray& rootNames, StringArray& rootPaths); private: - ScopedPointer fileList; - const FileFilter* fileFilter; + ScopedPointer fileList; + const FileFilter* fileFilter; - int flags; - File currentRoot; - OwnedArray chosenFiles; - SortedSet listeners; + int flags; + File currentRoot; + OwnedArray chosenFiles; + SortedSet listeners; - DirectoryContentsDisplayComponent* fileListComponent; - FilePreviewComponent* previewComp; - ComboBox* currentPathBox; - TextEditor* filenameBox; - Button* goUpButton; + DirectoryContentsDisplayComponent* fileListComponent; + FilePreviewComponent* previewComp; + ComboBox* currentPathBox; + TextEditor* filenameBox; + Button* goUpButton; - TimeSliceThread thread; + TimeSliceThread thread; - void sendListenerChangeMessage(); - bool isFileOrDirSuitable (const File& f) const; + void sendListenerChangeMessage(); + bool isFileOrDirSuitable (const File& f) const; - FileBrowserComponent (const FileBrowserComponent&); - const FileBrowserComponent& operator= (const FileBrowserComponent&); + FileBrowserComponent (const FileBrowserComponent&); + const FileBrowserComponent& operator= (const FileBrowserComponent&); }; #endif // __JUCE_FILEBROWSERCOMPONENT_JUCEHEADER__ @@ -46127,168 +21860,56 @@ private: #ifndef __JUCE_FILECHOOSER_JUCEHEADER__ #define __JUCE_FILECHOOSER_JUCEHEADER__ -/** - Creates a dialog box to choose a file or directory to load or save. - - To use a FileChooser: - - create one (as a local stack variable is the neatest way) - - call one of its browseFor.. methods - - if this returns true, the user has selected a file, so you can retrieve it - with the getResult() method. - - e.g. @code - void loadMooseFile() - { - FileChooser myChooser ("Please select the moose you want to load...", - File::getSpecialLocation (File::userHomeDirectory), - "*.moose"); - - if (myChooser.browseForFileToOpen()) - { - File mooseFile (myChooser.getResult()); - - loadMoose (mooseFile); - } - } - @endcode -*/ class JUCE_API FileChooser { public: - /** Creates a FileChooser. + FileChooser (const String& dialogBoxTitle, + const File& initialFileOrDirectory = File::nonexistent, + const String& filePatternsAllowed = String::empty, + const bool useOSNativeDialogBox = true); - After creating one of these, use one of the browseFor... methods to display it. + ~FileChooser(); - @param dialogBoxTitle a text string to display in the dialog box to - tell the user what's going on - @param initialFileOrDirectory the file or directory that should be selected when - the dialog box opens. If this parameter is set to - File::nonexistent, a sensible default directory - will be used instead. - @param filePatternsAllowed a set of file patterns to specify which files can be - selected - each pattern should be separated by a - comma or semi-colon, e.g. "*" or "*.jpg;*.gif". An - empty string means that all files are allowed - @param useOSNativeDialogBox if true, then a native dialog box will be used if - possible; if false, then a Juce-based browser dialog - box will always be used - @see browseForFileToOpen, browseForFileToSave, browseForDirectory - */ - FileChooser (const String& dialogBoxTitle, - const File& initialFileOrDirectory = File::nonexistent, - const String& filePatternsAllowed = String::empty, - const bool useOSNativeDialogBox = true); + bool browseForFileToOpen (FilePreviewComponent* previewComponent = 0); - /** Destructor. */ - ~FileChooser(); + bool browseForMultipleFilesToOpen (FilePreviewComponent* previewComponent = 0); - /** Shows a dialog box to choose a file to open. + bool browseForFileToSave (const bool warnAboutOverwritingExistingFiles); - This will display the dialog box modally, using an "open file" mode, so that - it won't allow non-existent files or directories to be chosen. + bool browseForDirectory(); - @param previewComponent an optional component to display inside the dialog - box to show special info about the files that the user - is browsing. The component will not be deleted by this - object, so the caller must take care of it. - @returns true if the user selected a file, in which case, use the getResult() - method to find out what it was. Returns false if they cancelled instead. - @see browseForFileToSave, browseForDirectory - */ - bool browseForFileToOpen (FilePreviewComponent* previewComponent = 0); + bool browseForMultipleFilesOrDirectories (FilePreviewComponent* previewComponent = 0); - /** Same as browseForFileToOpen, but allows the user to select multiple files. + const File getResult() const; - The files that are returned can be obtained by calling getResults(). See - browseForFileToOpen() for more info about the behaviour of this method. - */ - bool browseForMultipleFilesToOpen (FilePreviewComponent* previewComponent = 0); + const OwnedArray & getResults() const; - /** Shows a dialog box to choose a file to save. - - This will display the dialog box modally, using an "save file" mode, so it - will allow non-existent files to be chosen, but not directories. - - @param warnAboutOverwritingExistingFiles if true, the dialog box will ask - the user if they're sure they want to overwrite a file that already - exists - @returns true if the user chose a file and pressed 'ok', in which case, use - the getResult() method to find out what the file was. Returns false - if they cancelled instead. - @see browseForFileToOpen, browseForDirectory - */ - bool browseForFileToSave (const bool warnAboutOverwritingExistingFiles); - - /** Shows a dialog box to choose a directory. - - This will display the dialog box modally, using an "open directory" mode, so it - will only allow directories to be returned, not files. - - @returns true if the user chose a directory and pressed 'ok', in which case, use - the getResult() method to find out what they chose. Returns false - if they cancelled instead. - @see browseForFileToOpen, browseForFileToSave - */ - bool browseForDirectory(); - - /** Same as browseForFileToOpen, but allows the user to select multiple files and directories. - - The files that are returned can be obtained by calling getResults(). See - browseForFileToOpen() for more info about the behaviour of this method. - */ - bool browseForMultipleFilesOrDirectories (FilePreviewComponent* previewComponent = 0); - - /** Returns the last file that was chosen by one of the browseFor methods. - - After calling the appropriate browseFor... method, this method lets you - find out what file or directory they chose. - - Note that the file returned is only valid if the browse method returned true (i.e. - if the user pressed 'ok' rather than cancelling). - - If you're using a multiple-file select, then use the getResults() method instead, - to obtain the list of all files chosen. - - @see getResults - */ - const File getResult() const; - - /** Returns a list of all the files that were chosen during the last call to a - browse method. - - This array may be empty if no files were chosen, or can contain multiple entries - if multiple files were chosen. - - @see getResult - */ - const OwnedArray & getResults() const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String title, filters; - File startingFile; - OwnedArray results; - bool useNativeDialogBox; + String title, filters; + File startingFile; + OwnedArray results; + bool useNativeDialogBox; - bool showDialog (const bool selectsDirectories, - const bool selectsFiles, - const bool isSave, - const bool warnAboutOverwritingExistingFiles, - const bool selectMultipleFiles, - FilePreviewComponent* const previewComponent); + bool showDialog (const bool selectsDirectories, + const bool selectsFiles, + const bool isSave, + const bool warnAboutOverwritingExistingFiles, + const bool selectMultipleFiles, + FilePreviewComponent* const previewComponent); - static void showPlatformDialog (OwnedArray& results, - const String& title, - const File& file, - const String& filters, - bool selectsDirectories, - bool selectsFiles, - bool isSave, - bool warnAboutOverwritingExistingFiles, - bool selectMultipleFiles, - FilePreviewComponent* previewComponent); + static void showPlatformDialog (OwnedArray& results, + const String& title, + const File& file, + const String& filters, + bool selectsDirectories, + bool selectsFiles, + bool isSave, + bool warnAboutOverwritingExistingFiles, + bool selectMultipleFiles, + FilePreviewComponent* previewComponent); }; #endif // __JUCE_FILECHOOSER_JUCEHEADER__ @@ -46313,207 +21934,102 @@ private: #ifndef __JUCE_DROPSHADOWER_JUCEHEADER__ #define __JUCE_DROPSHADOWER_JUCEHEADER__ -/** - Adds a drop-shadow to a component. - - This object creates and manages a set of components which sit around a - component, creating a gaussian shadow around it. The components will track - the position of the component and if it's brought to the front they'll also - follow this. - - For desktop windows you don't need to use this class directly - just - set the Component::windowHasDropShadow flag when calling - Component::addToDesktop(), and the system will create one of these if it's - needed (which it obviously isn't on the Mac, for example). -*/ class JUCE_API DropShadower : public ComponentListener { public: - /** Creates a DropShadower. + DropShadower (const float alpha = 0.5f, + const int xOffset = 1, + const int yOffset = 5, + const float blurRadius = 10.0f); - @param alpha the opacity of the shadows, from 0 to 1.0 - @param xOffset the horizontal displacement of the shadow, in pixels - @param yOffset the vertical displacement of the shadow, in pixels - @param blurRadius the radius of the blur to use for creating the shadow - */ - DropShadower (const float alpha = 0.5f, - const int xOffset = 1, - const int yOffset = 5, - const float blurRadius = 10.0f); + virtual ~DropShadower(); - /** Destructor. */ - virtual ~DropShadower(); + void setOwner (Component* componentToFollow); - /** Attaches the DropShadower to the component you want to shadow. */ - void setOwner (Component* componentToFollow); + void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); + void componentBroughtToFront (Component& component); + void componentChildrenChanged (Component& component); + void componentParentHierarchyChanged (Component& component); + void componentVisibilityChanged (Component& component); - /** @internal */ - void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); - /** @internal */ - void componentBroughtToFront (Component& component); - /** @internal */ - void componentChildrenChanged (Component& component); - /** @internal */ - void componentParentHierarchyChanged (Component& component); - /** @internal */ - void componentVisibilityChanged (Component& component); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - Component* owner; - int numShadows; - Component* shadowWindows[4]; - Image* shadowImageSections[12]; - const int shadowEdge, xOffset, yOffset; - const float alpha, blurRadius; - bool inDestructor, reentrant; + Component* owner; + int numShadows; + Component* shadowWindows[4]; + Image* shadowImageSections[12]; + const int shadowEdge, xOffset, yOffset; + const float alpha, blurRadius; + bool inDestructor, reentrant; - void updateShadows(); - void setShadowImage (Image* const src, - const int num, - const int w, const int h, - const int sx, const int sy); + void updateShadows(); + void setShadowImage (Image* const src, + const int num, + const int w, const int h, + const int sx, const int sy); - void bringShadowWindowsToFront(); - void deleteShadowWindows(); + void bringShadowWindowsToFront(); + void deleteShadowWindows(); - DropShadower (const DropShadower&); - const DropShadower& operator= (const DropShadower&); + DropShadower (const DropShadower&); + const DropShadower& operator= (const DropShadower&); }; #endif // __JUCE_DROPSHADOWER_JUCEHEADER__ /********* End of inlined file: juce_DropShadower.h *********/ -/** - A base class for top-level windows. - - This class is used for components that are considered a major part of your - application - e.g. ResizableWindow, DocumentWindow, DialogWindow, AlertWindow, - etc. Things like menus that pop up briefly aren't derived from it. - - A TopLevelWindow is probably on the desktop, but this isn't mandatory - it - could itself be the child of another component. - - The class manages a list of all instances of top-level windows that are in use, - and each one is also given the concept of being "active". The active window is - one that is actively being used by the user. This isn't quite the same as the - component with the keyboard focus, because there may be a popup menu or other - temporary window which gets keyboard focus while the active top level window is - unchanged. - - A top-level window also has an optional drop-shadow. - - @see ResizableWindow, DocumentWindow, DialogWindow -*/ class JUCE_API TopLevelWindow : public Component { public: - /** Creates a TopLevelWindow. + TopLevelWindow (const String& name, + const bool addToDesktop); - @param name the name to give the component - @param addToDesktop if true, the window will be automatically added to the - desktop; if false, you can use it as a child component - */ - TopLevelWindow (const String& name, - const bool addToDesktop); + ~TopLevelWindow(); - /** Destructor. */ - ~TopLevelWindow(); + bool isActiveWindow() const throw() { return windowIsActive_; } - /** True if this is currently the TopLevelWindow that is actively being used. + void centreAroundComponent (Component* componentToCentreAround, + const int width, const int height); - This isn't quite the same as having keyboard focus, because the focus may be - on a child component or a temporary pop-up menu, etc, while this window is - still considered to be active. + void setDropShadowEnabled (const bool useShadow); - @see activeWindowStatusChanged - */ - bool isActiveWindow() const throw() { return windowIsActive_; } + void setUsingNativeTitleBar (const bool useNativeTitleBar); - /** This will set the bounds of the window so that it's centred in front of another - window. + bool isUsingNativeTitleBar() const throw() { return useNativeTitleBar && isOnDesktop(); } - If your app has a few windows open and want to pop up a dialog box for one of - them, you can use this to show it in front of the relevent parent window, which - is a bit neater than just having it appear in the middle of the screen. + static int getNumTopLevelWindows() throw(); - If componentToCentreAround is 0, then the currently active TopLevelWindow will - be used instead. If no window is focused, it'll just default to the middle of the - screen. - */ - void centreAroundComponent (Component* componentToCentreAround, - const int width, const int height); + static TopLevelWindow* getTopLevelWindow (const int index) throw(); - /** Turns the drop-shadow on and off. */ - void setDropShadowEnabled (const bool useShadow); + static TopLevelWindow* getActiveTopLevelWindow() throw(); - /** Sets whether an OS-native title bar will be used, or a Juce one. + juce_UseDebuggingNewOperator - @see isUsingNativeTitleBar - */ - void setUsingNativeTitleBar (const bool useNativeTitleBar); - - /** Returns true if the window is currently using an OS-native title bar. - - @see setUsingNativeTitleBar - */ - bool isUsingNativeTitleBar() const throw() { return useNativeTitleBar && isOnDesktop(); } - - /** Returns the number of TopLevelWindow objects currently in use. - - @see getTopLevelWindow - */ - static int getNumTopLevelWindows() throw(); - - /** Returns one of the TopLevelWindow objects currently in use. - - The index is 0 to (getNumTopLevelWindows() - 1). - */ - static TopLevelWindow* getTopLevelWindow (const int index) throw(); - - /** Returns the currently-active top level window. - - There might not be one, of course, so this can return 0. - */ - static TopLevelWindow* getActiveTopLevelWindow() throw(); - - juce_UseDebuggingNewOperator - - /** @internal */ - virtual void addToDesktop (int windowStyleFlags, void* nativeWindowToAttachTo = 0); + virtual void addToDesktop (int windowStyleFlags, void* nativeWindowToAttachTo = 0); protected: - /** This callback happens when this window becomes active or inactive. + virtual void activeWindowStatusChanged(); - @see isActiveWindow - */ - virtual void activeWindowStatusChanged(); - - /** @internal */ - void focusOfChildComponentChanged (FocusChangeType cause); - /** @internal */ - void parentHierarchyChanged(); - /** @internal */ - void visibilityChanged(); - /** @internal */ - virtual int getDesktopWindowStyleFlags() const; - /** @internal */ - void recreateDesktopWindow(); + void focusOfChildComponentChanged (FocusChangeType cause); + void parentHierarchyChanged(); + void visibilityChanged(); + virtual int getDesktopWindowStyleFlags() const; + void recreateDesktopWindow(); private: - friend class TopLevelWindowManager; - bool useDropShadow, useNativeTitleBar, windowIsActive_; - ScopedPointer shadower; + friend class TopLevelWindowManager; + bool useDropShadow, useNativeTitleBar, windowIsActive_; + ScopedPointer shadower; - void setWindowActive (const bool isNowActive) throw(); + void setWindowActive (const bool isNowActive) throw(); - TopLevelWindow (const TopLevelWindow&); - const TopLevelWindow& operator= (const TopLevelWindow&); + TopLevelWindow (const TopLevelWindow&); + const TopLevelWindow& operator= (const TopLevelWindow&); }; #endif // __JUCE_TOPLEVELWINDOW_JUCEHEADER__ @@ -46527,230 +22043,107 @@ private: #ifndef __JUCE_COMPONENTBOUNDSCONSTRAINER_JUCEHEADER__ #define __JUCE_COMPONENTBOUNDSCONSTRAINER_JUCEHEADER__ -/** - A class that imposes restrictions on a Component's size or position. - - This is used by classes such as ResizableCornerComponent, - ResizableBorderComponent and ResizableWindow. - - The base class can impose some basic size and position limits, but you can - also subclass this for custom uses. - - @see ResizableCornerComponent, ResizableBorderComponent, ResizableWindow -*/ class JUCE_API ComponentBoundsConstrainer { public: - /** When first created, the object will not impose any restrictions on the components. */ - ComponentBoundsConstrainer() throw(); + ComponentBoundsConstrainer() throw(); - /** Destructor. */ - virtual ~ComponentBoundsConstrainer(); + virtual ~ComponentBoundsConstrainer(); - /** Imposes a minimum width limit. */ - void setMinimumWidth (const int minimumWidth) throw(); + void setMinimumWidth (const int minimumWidth) throw(); - /** Returns the current minimum width. */ - int getMinimumWidth() const throw() { return minW; } + int getMinimumWidth() const throw() { return minW; } - /** Imposes a maximum width limit. */ - void setMaximumWidth (const int maximumWidth) throw(); + void setMaximumWidth (const int maximumWidth) throw(); - /** Returns the current maximum width. */ - int getMaximumWidth() const throw() { return maxW; } + int getMaximumWidth() const throw() { return maxW; } - /** Imposes a minimum height limit. */ - void setMinimumHeight (const int minimumHeight) throw(); + void setMinimumHeight (const int minimumHeight) throw(); - /** Returns the current minimum height. */ - int getMinimumHeight() const throw() { return minH; } + int getMinimumHeight() const throw() { return minH; } - /** Imposes a maximum height limit. */ - void setMaximumHeight (const int maximumHeight) throw(); + void setMaximumHeight (const int maximumHeight) throw(); - /** Returns the current maximum height. */ - int getMaximumHeight() const throw() { return maxH; } + int getMaximumHeight() const throw() { return maxH; } - /** Imposes a minimum width and height limit. */ - void setMinimumSize (const int minimumWidth, - const int minimumHeight) throw(); + void setMinimumSize (const int minimumWidth, + const int minimumHeight) throw(); - /** Imposes a maximum width and height limit. */ - void setMaximumSize (const int maximumWidth, - const int maximumHeight) throw(); + void setMaximumSize (const int maximumWidth, + const int maximumHeight) throw(); - /** Set all the maximum and minimum dimensions. */ - void setSizeLimits (const int minimumWidth, - const int minimumHeight, - const int maximumWidth, - const int maximumHeight) throw(); + void setSizeLimits (const int minimumWidth, + const int minimumHeight, + const int maximumWidth, + const int maximumHeight) throw(); - /** Sets the amount by which the component is allowed to go off-screen. + void setMinimumOnscreenAmounts (const int minimumWhenOffTheTop, + const int minimumWhenOffTheLeft, + const int minimumWhenOffTheBottom, + const int minimumWhenOffTheRight) throw(); - The values indicate how many pixels must remain on-screen when dragged off - one of its parent's edges, so e.g. if minimumWhenOffTheTop is set to 10, then - when the component goes off the top of the screen, its y-position will be - clipped so that there are always at least 10 pixels on-screen. In other words, - the lowest y-position it can take would be (10 - the component's height). + void setFixedAspectRatio (const double widthOverHeight) throw(); - If you pass 0 or less for one of these amounts, the component is allowed - to move beyond that edge completely, with no restrictions at all. + double getFixedAspectRatio() const throw(); - If you pass a very large number (i.e. larger that the dimensions of the - component itself), then the component won't be allowed to overlap that - edge at all. So e.g. setting minimumWhenOffTheLeft to 0xffffff will mean that - the component will bump into the left side of the screen and go no further. - */ - void setMinimumOnscreenAmounts (const int minimumWhenOffTheTop, - const int minimumWhenOffTheLeft, - const int minimumWhenOffTheBottom, - const int minimumWhenOffTheRight) throw(); + virtual void checkBounds (int& x, int& y, int& w, int& h, + const Rectangle& previousBounds, + const Rectangle& limits, + const bool isStretchingTop, + const bool isStretchingLeft, + const bool isStretchingBottom, + const bool isStretchingRight); - /** Specifies a width-to-height ratio that the resizer should always maintain. + virtual void resizeStart(); - If the value is 0, no aspect ratio is enforced. If it's non-zero, the width - will always be maintained as this multiple of the height. + virtual void resizeEnd(); - @see setResizeLimits - */ - void setFixedAspectRatio (const double widthOverHeight) throw(); + void setBoundsForComponent (Component* const component, + int x, int y, int w, int h, + const bool isStretchingTop, + const bool isStretchingLeft, + const bool isStretchingBottom, + const bool isStretchingRight); - /** Returns the aspect ratio that was set with setFixedAspectRatio(). + void checkComponentBounds (Component* component); - If no aspect ratio is being enforced, this will return 0. - */ - double getFixedAspectRatio() const throw(); + virtual void applyBoundsToComponent (Component* component, + int x, int y, int w, int h); - /** This callback changes the given co-ordinates to impose whatever the current - constraints are set to be. - - @param x the x position that should be examined and adjusted - @param y the y position that should be examined and adjusted - @param w the width that should be examined and adjusted - @param h the height that should be examined and adjusted - @param previousBounds the component's current size - @param limits the region in which the component can be positioned - @param isStretchingTop whether the top edge of the component is being resized - @param isStretchingLeft whether the left edge of the component is being resized - @param isStretchingBottom whether the bottom edge of the component is being resized - @param isStretchingRight whether the right edge of the component is being resized - */ - virtual void checkBounds (int& x, int& y, int& w, int& h, - const Rectangle& previousBounds, - const Rectangle& limits, - const bool isStretchingTop, - const bool isStretchingLeft, - const bool isStretchingBottom, - const bool isStretchingRight); - - /** This callback happens when the resizer is about to start dragging. */ - virtual void resizeStart(); - - /** This callback happens when the resizer has finished dragging. */ - virtual void resizeEnd(); - - /** Checks the given bounds, and then sets the component to the corrected size. */ - void setBoundsForComponent (Component* const component, - int x, int y, int w, int h, - const bool isStretchingTop, - const bool isStretchingLeft, - const bool isStretchingBottom, - const bool isStretchingRight); - - /** Performs a check on the current size of a component, and moves or resizes - it if it fails the constraints. - */ - void checkComponentBounds (Component* component); - - /** Called by setBoundsForComponent() to apply a new constrained size to a - component. - - By default this just calls setBounds(), but it virtual in case it's needed for - extremely cunning purposes. - */ - virtual void applyBoundsToComponent (Component* component, - int x, int y, int w, int h); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - int minW, maxW, minH, maxH; - int minOffTop, minOffLeft, minOffBottom, minOffRight; - double aspectRatio; + int minW, maxW, minH, maxH; + int minOffTop, minOffLeft, minOffBottom, minOffRight; + double aspectRatio; - ComponentBoundsConstrainer (const ComponentBoundsConstrainer&); - const ComponentBoundsConstrainer& operator= (const ComponentBoundsConstrainer&); + ComponentBoundsConstrainer (const ComponentBoundsConstrainer&); + const ComponentBoundsConstrainer& operator= (const ComponentBoundsConstrainer&); }; #endif // __JUCE_COMPONENTBOUNDSCONSTRAINER_JUCEHEADER__ /********* End of inlined file: juce_ComponentBoundsConstrainer.h *********/ -/** - An object to take care of the logic for dragging components around with the mouse. - - Very easy to use - in your mouseDown() callback, call startDraggingComponent(), - then in your mouseDrag() callback, call dragComponent(). - - When starting a drag, you can give it a ComponentBoundsConstrainer to use - to limit the component's position and keep it on-screen. - - e.g. @code - class MyDraggableComp - { - ComponentDragger myDragger; - - void mouseDown (const MouseEvent& e) - { - myDragger.startDraggingComponent (this, 0); - } - - void mouseDrag (const MouseEvent& e) - { - myDragger.dragComponent (this, e); - } - }; - @endcode -*/ class JUCE_API ComponentDragger { public: - /** Creates a ComponentDragger. */ - ComponentDragger(); + ComponentDragger(); - /** Destructor. */ - virtual ~ComponentDragger(); + virtual ~ComponentDragger(); - /** Call this from your component's mouseDown() method, to prepare for dragging. + void startDraggingComponent (Component* const componentToDrag, + ComponentBoundsConstrainer* constrainer); - @param componentToDrag the component that you want to drag - @param constrainer a constrainer object to use to keep the component - from going offscreen - @see dragComponent - */ - void startDraggingComponent (Component* const componentToDrag, - ComponentBoundsConstrainer* constrainer); + void dragComponent (Component* const componentToDrag, + const MouseEvent& e); - /** Call this from your mouseDrag() callback to move the component. - - This will move the component, but will first check the validity of the - component's new position using the checkPosition() method, which you - can override if you need to enforce special positioning limits on the - component. - - @param componentToDrag the component that you want to drag - @param e the current mouse-drag event - @see dragComponent - */ - void dragComponent (Component* const componentToDrag, - const MouseEvent& e); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ComponentBoundsConstrainer* constrainer; - int originalX, originalY; + ComponentBoundsConstrainer* constrainer; + int originalX, originalY; }; #endif // __JUCE_COMPONENTDRAGGER_JUCEHEADER__ @@ -46760,89 +22153,41 @@ private: #ifndef __JUCE_RESIZABLEBORDERCOMPONENT_JUCEHEADER__ #define __JUCE_RESIZABLEBORDERCOMPONENT_JUCEHEADER__ -/** - A component that resizes its parent window when dragged. - - This component forms a frame around the edge of a component, allowing it to - be dragged by the edges or corners to resize it - like the way windows are - resized in MSWindows or Linux. - - To use it, just add it to your component, making it fill the entire parent component - (there's a mouse hit-test that only traps mouse-events which land around the - edge of the component, so it's even ok to put it on top of any other components - you're using). Make sure you rescale the resizer component to fill the parent - each time the parent's size changes. - - @see ResizableCornerComponent -*/ class JUCE_API ResizableBorderComponent : public Component { public: - /** Creates a resizer. + ResizableBorderComponent (Component* const componentToResize, + ComponentBoundsConstrainer* const constrainer); - Pass in the target component which you want to be resized when this one is - dragged. + ~ResizableBorderComponent(); - The target component will usually be a parent of the resizer component, but this - isn't mandatory. + void setBorderThickness (const BorderSize& newBorderSize) throw(); - Remember that when the target component is resized, it'll need to move and - resize this component to keep it in place, as this won't happen automatically. + const BorderSize getBorderThickness() const throw(); - If the constrainer parameter is non-zero, then this object will be used to enforce - limits on the size and position that the component can be stretched to. Make sure - that the constrainer isn't deleted while still in use by this object. - - @see ComponentBoundsConstrainer - */ - ResizableBorderComponent (Component* const componentToResize, - ComponentBoundsConstrainer* const constrainer); - - /** Destructor. */ - ~ResizableBorderComponent(); - - /** Specifies how many pixels wide the draggable edges of this component are. - - @see getBorderThickness - */ - void setBorderThickness (const BorderSize& newBorderSize) throw(); - - /** Returns the number of pixels wide that the draggable edges of this component are. - - @see setBorderThickness - */ - const BorderSize getBorderThickness() const throw(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void mouseEnter (const MouseEvent& e); - /** @internal */ - void mouseMove (const MouseEvent& e); - /** @internal */ - void mouseDown (const MouseEvent& e); - /** @internal */ - void mouseDrag (const MouseEvent& e); - /** @internal */ - void mouseUp (const MouseEvent& e); - /** @internal */ - bool hitTest (int x, int y); + void paint (Graphics& g); + void mouseEnter (const MouseEvent& e); + void mouseMove (const MouseEvent& e); + void mouseDown (const MouseEvent& e); + void mouseDrag (const MouseEvent& e); + void mouseUp (const MouseEvent& e); + bool hitTest (int x, int y); private: - Component* const component; - ComponentBoundsConstrainer* constrainer; - BorderSize borderSize; - int originalX, originalY, originalW, originalH; - int mouseZone; + Component* const component; + ComponentBoundsConstrainer* constrainer; + BorderSize borderSize; + int originalX, originalY, originalW, originalH; + int mouseZone; - void updateMouseZone (const MouseEvent& e) throw(); + void updateMouseZone (const MouseEvent& e) throw(); - ResizableBorderComponent (const ResizableBorderComponent&); - const ResizableBorderComponent& operator= (const ResizableBorderComponent&); + ResizableBorderComponent (const ResizableBorderComponent&); + const ResizableBorderComponent& operator= (const ResizableBorderComponent&); }; #endif // __JUCE_RESIZABLEBORDERCOMPONENT_JUCEHEADER__ @@ -46852,390 +22197,144 @@ private: #ifndef __JUCE_RESIZABLECORNERCOMPONENT_JUCEHEADER__ #define __JUCE_RESIZABLECORNERCOMPONENT_JUCEHEADER__ -/** A component that resizes a parent window when dragged. - - This is the small triangular stripey resizer component you get in the bottom-right - of windows (more commonly on the Mac than Windows). Put one in the corner of - a larger component and it will automatically resize its parent when it gets dragged - around. - - @see ResizableFrameComponent -*/ class JUCE_API ResizableCornerComponent : public Component { public: - /** Creates a resizer. + ResizableCornerComponent (Component* const componentToResize, + ComponentBoundsConstrainer* const constrainer); - Pass in the target component which you want to be resized when this one is - dragged. + ~ResizableCornerComponent(); - The target component will usually be a parent of the resizer component, but this - isn't mandatory. - - Remember that when the target component is resized, it'll need to move and - resize this component to keep it in place, as this won't happen automatically. - - If the constrainer parameter is non-zero, then this object will be used to enforce - limits on the size and position that the component can be stretched to. Make sure - that the constrainer isn't deleted while still in use by this object. If you - pass a zero in here, no limits will be put on the sizes it can be stretched to. - - @see ComponentBoundsConstrainer - */ - ResizableCornerComponent (Component* const componentToResize, - ComponentBoundsConstrainer* const constrainer); - - /** Destructor. */ - ~ResizableCornerComponent(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void mouseDown (const MouseEvent& e); - /** @internal */ - void mouseDrag (const MouseEvent& e); - /** @internal */ - void mouseUp (const MouseEvent& e); - /** @internal */ - bool hitTest (int x, int y); + void paint (Graphics& g); + void mouseDown (const MouseEvent& e); + void mouseDrag (const MouseEvent& e); + void mouseUp (const MouseEvent& e); + bool hitTest (int x, int y); private: - Component* const component; - ComponentBoundsConstrainer* constrainer; - int originalX, originalY, originalW, originalH; + Component* const component; + ComponentBoundsConstrainer* constrainer; + int originalX, originalY, originalW, originalH; - ResizableCornerComponent (const ResizableCornerComponent&); - const ResizableCornerComponent& operator= (const ResizableCornerComponent&); + ResizableCornerComponent (const ResizableCornerComponent&); + const ResizableCornerComponent& operator= (const ResizableCornerComponent&); }; #endif // __JUCE_RESIZABLECORNERCOMPONENT_JUCEHEADER__ /********* End of inlined file: juce_ResizableCornerComponent.h *********/ -/** - A base class for top-level windows that can be dragged around and resized. - - To add content to the window, use its setContentComponent() method to - give it a component that will remain positioned inside it (leaving a gap around - the edges for a border). - - It's not advisable to add child components directly to a ResizableWindow: put them - inside your content component instead. And overriding methods like resized(), moved(), etc - is also not recommended - instead override these methods for your content component. - (If for some obscure reason you do need to override these methods, always remember to - call the super-class's resized() method too, otherwise it'll fail to lay out the window - decorations correctly). - - By default resizing isn't enabled - use the setResizable() method to enable it and - to choose the style of resizing to use. - - @see TopLevelWindow -*/ class JUCE_API ResizableWindow : public TopLevelWindow { public: - /** Creates a ResizableWindow. + ResizableWindow (const String& name, + const bool addToDesktop); - This constructor doesn't specify a background colour, so the LookAndFeel's default - background colour will be used. + ResizableWindow (const String& name, + const Colour& backgroundColour, + const bool addToDesktop); - @param name the name to give the component - @param addToDesktop if true, the window will be automatically added to the - desktop; if false, you can use it as a child component - */ - ResizableWindow (const String& name, - const bool addToDesktop); + ~ResizableWindow(); - /** Creates a ResizableWindow. + const Colour getBackgroundColour() const throw(); - @param name the name to give the component - @param backgroundColour the colour to use for filling the window's background. - @param addToDesktop if true, the window will be automatically added to the - desktop; if false, you can use it as a child component - */ - ResizableWindow (const String& name, - const Colour& backgroundColour, - const bool addToDesktop); + void setBackgroundColour (const Colour& newColour); - /** Destructor. + void setResizable (const bool shouldBeResizable, + const bool useBottomRightCornerResizer); - If a content component has been set with setContentComponent(), it - will be deleted. - */ - ~ResizableWindow(); + bool isResizable() const throw(); - /** Returns the colour currently being used for the window's background. + void setResizeLimits (const int newMinimumWidth, + const int newMinimumHeight, + const int newMaximumWidth, + const int newMaximumHeight) throw(); - As a convenience the window will fill itself with this colour, but you - can override the paint() method if you need more customised behaviour. + ComponentBoundsConstrainer* getConstrainer() throw() { return constrainer; } - This method is the same as retrieving the colour for ResizableWindow::backgroundColourId. + void setConstrainer (ComponentBoundsConstrainer* newConstrainer); - @see setBackgroundColour - */ - const Colour getBackgroundColour() const throw(); + void setBoundsConstrained (int x, int y, int width, int height); - /** Changes the colour currently being used for the window's background. + bool isFullScreen() const; - As a convenience the window will fill itself with this colour, but you - can override the paint() method if you need more customised behaviour. + void setFullScreen (const bool shouldBeFullScreen); - Note that the opaque state of this window is altered by this call to reflect - the opacity of the colour passed-in. On window systems which can't support - semi-transparent windows this might cause problems, (though it's unlikely you'll - be using this class as a base for a semi-transparent component anyway). + bool isMinimised() const; - You can also use the ResizableWindow::backgroundColourId colour id to set - this colour. + void setMinimised (const bool shouldMinimise); - @see getBackgroundColour - */ - void setBackgroundColour (const Colour& newColour); + const String getWindowStateAsString(); - /** Make the window resizable or fixed. + bool restoreWindowStateFromString (const String& previousState); - @param shouldBeResizable whether it's resizable at all - @param useBottomRightCornerResizer if true, it'll add a ResizableCornerComponent at the - bottom-right; if false, it'll use a ResizableBorderComponent - around the edge - @see setResizeLimits, isResizable - */ - void setResizable (const bool shouldBeResizable, - const bool useBottomRightCornerResizer); + Component* getContentComponent() const throw() { return contentComponent; } - /** True if resizing is enabled. + void setContentComponent (Component* const newContentComponent, + const bool deleteOldOne = true, + const bool resizeToFit = false); - @see setResizable - */ - bool isResizable() const throw(); + void setContentComponentSize (int width, int height); - /** This sets the maximum and minimum sizes for the window. + enum ColourIds + { + backgroundColourId = 0x1005700, /**< A colour to use to fill the window's background. */ + }; - If the window's current size is outside these limits, it will be resized to - make sure it's within them. - - Calling setBounds() on the component will bypass any size checking - it's only when - the window is being resized by the user that these values are enforced. - - @see setResizable, setFixedAspectRatio - */ - void setResizeLimits (const int newMinimumWidth, - const int newMinimumHeight, - const int newMaximumWidth, - const int newMaximumHeight) throw(); - - /** Returns the bounds constrainer object that this window is using. - - You can access this to change its properties. - */ - ComponentBoundsConstrainer* getConstrainer() throw() { return constrainer; } - - /** Sets the bounds-constrainer object to use for resizing and dragging this window. - - A pointer to the object you pass in will be kept, but it won't be deleted - by this object, so it's the caller's responsiblity to manage it. - - If you pass 0, then no contraints will be placed on the positioning of the window. - */ - void setConstrainer (ComponentBoundsConstrainer* newConstrainer); - - /** Calls the window's setBounds method, after first checking these bounds - with the current constrainer. - - @see setConstrainer - */ - void setBoundsConstrained (int x, int y, int width, int height); - - /** Returns true if the window is currently in full-screen mode. - - @see setFullScreen - */ - bool isFullScreen() const; - - /** Puts the window into full-screen mode, or restores it to its normal size. - - If true, the window will become full-screen; if false, it will return to the - last size it was before being made full-screen. - - @see isFullScreen - */ - void setFullScreen (const bool shouldBeFullScreen); - - /** Returns true if the window is currently minimised. - - @see setMinimised - */ - bool isMinimised() const; - - /** Minimises the window, or restores it to its previous position and size. - - When being un-minimised, it'll return to the last position and size it - was in before being minimised. - - @see isMinimised - */ - void setMinimised (const bool shouldMinimise); - - /** Returns a string which encodes the window's current size and position. - - This string will encapsulate the window's size, position, and whether it's - in full-screen mode. It's intended for letting your application save and - restore a window's position. - - Use the restoreWindowStateFromString() to restore from a saved state. - - @see restoreWindowStateFromString - */ - const String getWindowStateAsString(); - - /** Restores the window to a previously-saved size and position. - - This restores the window's size, positon and full-screen status from an - string that was previously created with the getWindowStateAsString() - method. - - @returns false if the string wasn't a valid window state - @see getWindowStateAsString - */ - bool restoreWindowStateFromString (const String& previousState); - - /** Returns the current content component. - - This will be the component set by setContentComponent(), or 0 if none - has yet been specified. - - @see setContentComponent - */ - Component* getContentComponent() const throw() { return contentComponent; } - - /** Changes the current content component. - - This sets a component that will be placed in the centre of the ResizableWindow, - (leaving a space around the edge for the border). - - You should never add components directly to a ResizableWindow (or any of its subclasses) - with addChildComponent(). Instead, add them to the content component. - - @param newContentComponent the new component to use (or null to not use one) - this - component will be deleted either when replaced by another call - to this method, or when the ResizableWindow is deleted. - To remove a content component without deleting it, use - setContentComponent (0, false). - @param deleteOldOne if true, the previous content component will be deleted; if - false, the previous component will just be removed without - deleting it. - @param resizeToFit if true, the ResizableWindow will maintain its size such that - it always fits around the size of the content component. If false, the - new content will be resized to fit the current space available. - */ - void setContentComponent (Component* const newContentComponent, - const bool deleteOldOne = true, - const bool resizeToFit = false); - - /** Changes the window so that the content component ends up with the specified size. - - This is basically a setSize call on the window, but which adds on the borders, - so you can specify the content component's target size. - */ - void setContentComponentSize (int width, int height); - - /** A set of colour IDs to use to change the colour of various aspects of the window. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1005700, /**< A colour to use to fill the window's background. */ - }; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** @internal */ - void paint (Graphics& g); - /** (if overriding this, make sure you call ResizableWindow::resized() in your subclass) */ - void moved(); - /** (if overriding this, make sure you call ResizableWindow::resized() in your subclass) */ - void resized(); - /** @internal */ - void mouseDown (const MouseEvent& e); - /** @internal */ - void mouseDrag (const MouseEvent& e); - /** @internal */ - void lookAndFeelChanged(); - /** @internal */ - void childBoundsChanged (Component* child); - /** @internal */ - void parentSizeChanged(); - /** @internal */ - void visibilityChanged(); - /** @internal */ - void activeWindowStatusChanged(); - /** @internal */ - int getDesktopWindowStyleFlags() const; + void paint (Graphics& g); + void moved(); + void resized(); + void mouseDown (const MouseEvent& e); + void mouseDrag (const MouseEvent& e); + void lookAndFeelChanged(); + void childBoundsChanged (Component* child); + void parentSizeChanged(); + void visibilityChanged(); + void activeWindowStatusChanged(); + int getDesktopWindowStyleFlags() const; - /** Returns the width of the border to use around the window. + virtual const BorderSize getBorderThickness(); - @see getContentComponentBorder - */ - virtual const BorderSize getBorderThickness(); - - /** Returns the insets to use when positioning the content component. - - @see getBorderThickness - */ - virtual const BorderSize getContentComponentBorder(); + virtual const BorderSize getContentComponentBorder(); #ifdef JUCE_DEBUG - /** Overridden to warn people about adding components directly to this component - instead of using setContentComponent(). - - If you know what you're doing and are sure you really want to add a component, specify - a base-class method call to Component::addAndMakeVisible(), to side-step this warning. - */ - void addChildComponent (Component* const child, int zOrder = -1); - /** Overridden to warn people about adding components directly to this component - instead of using setContentComponent(). - - If you know what you're doing and are sure you really want to add a component, specify - a base-class method call to Component::addAndMakeVisible(), to side-step this warning. - */ - void addAndMakeVisible (Component* const child, int zOrder = -1); + void addChildComponent (Component* const child, int zOrder = -1); + void addAndMakeVisible (Component* const child, int zOrder = -1); #endif - ScopedPointer resizableCorner; - ScopedPointer resizableBorder; + ScopedPointer resizableCorner; + ScopedPointer resizableBorder; private: - ScopedPointer contentComponent; - bool resizeToFitContent, fullscreen; - ComponentDragger dragger; - Rectangle lastNonFullScreenPos; - ComponentBoundsConstrainer defaultConstrainer; - ComponentBoundsConstrainer* constrainer; - #ifdef JUCE_DEBUG - bool hasBeenResized; - #endif + ScopedPointer contentComponent; + bool resizeToFitContent, fullscreen; + ComponentDragger dragger; + Rectangle lastNonFullScreenPos; + ComponentBoundsConstrainer defaultConstrainer; + ComponentBoundsConstrainer* constrainer; + #ifdef JUCE_DEBUG + bool hasBeenResized; + #endif - void updateLastPos(); + void updateLastPos(); - ResizableWindow (const ResizableWindow&); - const ResizableWindow& operator= (const ResizableWindow&); + ResizableWindow (const ResizableWindow&); + const ResizableWindow& operator= (const ResizableWindow&); - // (xxx remove these eventually) - // temporarily here to stop old code compiling, as the parameters for these methods have changed.. - void getBorderThickness (int& left, int& top, int& right, int& bottom); - // temporarily here to stop old code compiling, as the parameters for these methods have changed.. - void getContentComponentBorder (int& left, int& top, int& right, int& bottom); + // (xxx remove these eventually) + // temporarily here to stop old code compiling, as the parameters for these methods have changed.. + void getBorderThickness (int& left, int& top, int& right, int& bottom); + // temporarily here to stop old code compiling, as the parameters for these methods have changed.. + void getContentComponentBorder (int& left, int& top, int& right, int& bottom); }; #endif // __JUCE_RESIZABLEWINDOW_JUCEHEADER__ @@ -47245,391 +22344,183 @@ private: #ifndef __JUCE_GLYPHARRANGEMENT_JUCEHEADER__ #define __JUCE_GLYPHARRANGEMENT_JUCEHEADER__ -/** - A glyph from a particular font, with a particular size, style, - typeface and position. - - @see GlyphArrangement, Font -*/ class JUCE_API PositionedGlyph { public: - /** Returns the character the glyph represents. */ - juce_wchar getCharacter() const { return character; } - /** Checks whether the glyph is actually empty. */ - bool isWhitespace() const { return CharacterFunctions::isWhitespace (character); } + juce_wchar getCharacter() const { return character; } + bool isWhitespace() const { return CharacterFunctions::isWhitespace (character); } - /** Returns the position of the glyph's left-hand edge. */ - float getLeft() const { return x; } - /** Returns the position of the glyph's right-hand edge. */ - float getRight() const { return x + w; } - /** Returns the y position of the glyph's baseline. */ - float getBaselineY() const { return y; } - /** Returns the y position of the top of the glyph. */ - float getTop() const { return y - font.getAscent(); } - /** Returns the y position of the bottom of the glyph. */ - float getBottom() const { return y + font.getDescent(); } + float getLeft() const { return x; } + float getRight() const { return x + w; } + float getBaselineY() const { return y; } + float getTop() const { return y - font.getAscent(); } + float getBottom() const { return y + font.getDescent(); } - /** Shifts the glyph's position by a relative amount. */ - void moveBy (const float deltaX, - const float deltaY); + void moveBy (const float deltaX, + const float deltaY); - /** Draws the glyph into a graphics context. */ - void draw (const Graphics& g) const; + void draw (const Graphics& g) const; - /** Draws the glyph into a graphics context, with an extra transform applied to it. */ - void draw (const Graphics& g, const AffineTransform& transform) const; + void draw (const Graphics& g, const AffineTransform& transform) const; - /** Returns the path for this glyph. + void createPath (Path& path) const; - @param path the glyph's outline will be appended to this path - */ - void createPath (Path& path) const; + bool hitTest (float x, float y) const; - /** Checks to see if a point lies within this glyph. */ - bool hitTest (float x, float y) const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - friend class GlyphArrangement; - float x, y, w; - Font font; - juce_wchar character; - int glyph; + friend class GlyphArrangement; + float x, y, w; + Font font; + juce_wchar character; + int glyph; - PositionedGlyph(); + PositionedGlyph(); }; -/** - A set of glyphs, each with a position. - - You can create a GlyphArrangement, text to it and then draw it onto a - graphics context. It's used internally by the text methods in the - Graphics class, but can be used directly if more control is needed. - - @see Font, PositionedGlyph -*/ class JUCE_API GlyphArrangement { public: - /** Creates an empty arrangement. */ - GlyphArrangement(); + GlyphArrangement(); - /** Takes a copy of another arrangement. */ - GlyphArrangement (const GlyphArrangement& other); + GlyphArrangement (const GlyphArrangement& other); - /** Copies another arrangement onto this one. + const GlyphArrangement& operator= (const GlyphArrangement& other); - To add another arrangement without clearing this one, use addGlyphArrangement(). - */ - const GlyphArrangement& operator= (const GlyphArrangement& other); + ~GlyphArrangement(); - /** Destructor. */ - ~GlyphArrangement(); + int getNumGlyphs() const { return glyphs.size(); } - /** Returns the total number of glyphs in the arrangement. */ - int getNumGlyphs() const { return glyphs.size(); } + PositionedGlyph& getGlyph (const int index) const; - /** Returns one of the glyphs from the arrangement. + void clear(); - @param index the glyph's index, from 0 to (getNumGlyphs() - 1). Be - careful not to pass an out-of-range index here, as it - doesn't do any bounds-checking. - */ - PositionedGlyph& getGlyph (const int index) const; + void addLineOfText (const Font& font, + const String& text, + const float x, + const float y); - /** Clears all text from the arrangement and resets it. - */ - void clear(); + void addCurtailedLineOfText (const Font& font, + const String& text, + float x, + const float y, + const float maxWidthPixels, + const bool useEllipsis); - /** Appends a line of text to the arrangement. + void addJustifiedText (const Font& font, + const String& text, + float x, float y, + const float maxLineWidth, + const Justification& horizontalLayout); - This will add the text as a single line, where x is the left-hand edge of the - first character, and y is the position for the text's baseline. + void addFittedText (const Font& font, + const String& text, + const float x, const float y, + const float width, const float height, + const Justification& layout, + int maximumLinesToUse, + const float minimumHorizontalScale = 0.7f); - If the text contains new-lines or carriage-returns, this will ignore them - use - addJustifiedText() to add multi-line arrangements. - */ - void addLineOfText (const Font& font, - const String& text, - const float x, - const float y); + void addGlyphArrangement (const GlyphArrangement& other); - /** Adds a line of text, truncating it if it's wider than a specified size. + void draw (const Graphics& g) const; - This is the same as addLineOfText(), but if the line's width exceeds the value - specified in maxWidthPixels, it will be truncated using either ellipsis (i.e. dots: "..."), - if useEllipsis is true, or if this is false, it will just drop any subsequent characters. - */ - void addCurtailedLineOfText (const Font& font, - const String& text, - float x, - const float y, - const float maxWidthPixels, - const bool useEllipsis); + void draw (const Graphics& g, const AffineTransform& transform) const; - /** Adds some multi-line text, breaking lines at word-boundaries if they are too wide. + void createPath (Path& path) const; - This will add text to the arrangement, breaking it into new lines either where there - is a new-line or carriage-return character in the text, or where a line's width - exceeds the value set in maxLineWidth. + int findGlyphIndexAt (float x, float y) const; - Each line that is added will be laid out using the flags set in horizontalLayout, so - the lines can be left- or right-justified, or centred horizontally in the space - between x and (x + maxLineWidth). + void getBoundingBox (int startIndex, + int numGlyphs, + float& left, + float& top, + float& right, + float& bottom, + const bool includeWhitespace) const; - The y co-ordinate is the position of the baseline of the first line of text - subsequent - lines will be placed below it, separated by a distance of font.getHeight(). - */ - void addJustifiedText (const Font& font, - const String& text, - float x, float y, - const float maxLineWidth, - const Justification& horizontalLayout); + void moveRangeOfGlyphs (int startIndex, int numGlyphs, + const float deltaX, + const float deltaY); - /** Tries to fit some text withing a given space. + void removeRangeOfGlyphs (int startIndex, int numGlyphs); - This does its best to make the given text readable within the specified rectangle, - so it useful for labelling things. + void stretchRangeOfGlyphs (int startIndex, int numGlyphs, + const float horizontalScaleFactor); - If the text is too big, it'll be squashed horizontally or broken over multiple lines - if the maximumLinesToUse value allows this. If the text just won't fit into the space, - it'll cram as much as possible in there, and put some ellipsis at the end to show that - it's been truncated. + void justifyGlyphs (const int startIndex, const int numGlyphs, + const float x, + const float y, + const float width, + const float height, + const Justification& justification); - A Justification parameter lets you specify how the text is laid out within the rectangle, - both horizontally and vertically. - - @see Graphics::drawFittedText - */ - void addFittedText (const Font& font, - const String& text, - const float x, const float y, - const float width, const float height, - const Justification& layout, - int maximumLinesToUse, - const float minimumHorizontalScale = 0.7f); - - /** Appends another glyph arrangement to this one. */ - void addGlyphArrangement (const GlyphArrangement& other); - - /** Draws this glyph arrangement to a graphics context. - - This uses cached bitmaps so is much faster than the draw (Graphics&, const AffineTransform&) - method, which renders the glyphs as filled vectors. - */ - void draw (const Graphics& g) const; - - /** Draws this glyph arrangement to a graphics context. - - This renders the paths as filled vectors, so is far slower than the draw (Graphics&) - method for non-transformed arrangements. - */ - void draw (const Graphics& g, const AffineTransform& transform) const; - - /** Converts the set of glyphs into a path. - - @param path the glyphs' outlines will be appended to this path - */ - void createPath (Path& path) const; - - /** Looks for a glyph that contains the given co-ordinate. - - @returns the index of the glyph, or -1 if none were found. - */ - int findGlyphIndexAt (float x, float y) const; - - /** Finds the smallest rectangle that will enclose a subset of the glyphs. - - @param startIndex the first glyph to test - @param numGlyphs the number of glyphs to include; if this is < 0, all glyphs after - startIndex will be included - @param left on return, the leftmost co-ordinate of the rectangle - @param top on return, the top co-ordinate of the rectangle - @param right on return, the rightmost co-ordinate of the rectangle - @param bottom on return, the bottom co-ordinate of the rectangle - @param includeWhitespace if true, the extent of any whitespace characters will also - be taken into account - */ - void getBoundingBox (int startIndex, - int numGlyphs, - float& left, - float& top, - float& right, - float& bottom, - const bool includeWhitespace) const; - - /** Shifts a set of glyphs by a given amount. - - @param startIndex the first glyph to transform - @param numGlyphs the number of glyphs to move; if this is < 0, all glyphs after - startIndex will be used - @param deltaX the amount to add to their x-positions - @param deltaY the amount to add to their y-positions - */ - void moveRangeOfGlyphs (int startIndex, int numGlyphs, - const float deltaX, - const float deltaY); - - /** Removes a set of glyphs from the arrangement. - - @param startIndex the first glyph to remove - @param numGlyphs the number of glyphs to remove; if this is < 0, all glyphs after - startIndex will be deleted - */ - void removeRangeOfGlyphs (int startIndex, int numGlyphs); - - /** Expands or compresses a set of glyphs horizontally. - - @param startIndex the first glyph to transform - @param numGlyphs the number of glyphs to stretch; if this is < 0, all glyphs after - startIndex will be used - @param horizontalScaleFactor how much to scale their horizontal width by - */ - void stretchRangeOfGlyphs (int startIndex, int numGlyphs, - const float horizontalScaleFactor); - - /** Justifies a set of glyphs within a given space. - - This moves the glyphs as a block so that the whole thing is located within the - given rectangle with the specified layout. - - If the Justification::horizontallyJustified flag is specified, each line will - be stretched out to fill the specified width. - */ - void justifyGlyphs (const int startIndex, const int numGlyphs, - const float x, - const float y, - const float width, - const float height, - const Justification& justification); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - OwnedArray glyphs; + OwnedArray glyphs; - int insertEllipsis (const Font& font, const float maxXPos, const int startIndex, int endIndex); - int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, - const Justification& justification, float minimumHorizontalScale); - void spreadOutLine (const int start, const int numGlyphs, const float targetWidth); + int insertEllipsis (const Font& font, const float maxXPos, const int startIndex, int endIndex); + int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, + const Justification& justification, float minimumHorizontalScale); + void spreadOutLine (const int start, const int numGlyphs, const float targetWidth); }; #endif // __JUCE_GLYPHARRANGEMENT_JUCEHEADER__ /********* End of inlined file: juce_GlyphArrangement.h *********/ -/** - A file open/save dialog box. - - This is a Juce-based file dialog box; to use a native file chooser, see the - FileChooser class. - - To use one of these, create it and call its show() method. e.g. - - @code - { - WildcardFileFilter wildcardFilter (T("*.foo"), T("Foo files")); - - FileBrowserComponent browser (FileBrowserComponent::loadFileMode, - File::nonexistent, - &wildcardFilter, - 0); - - FileChooserDialogBox dialogBox (T("Open some kind of file"), - T("Please choose some kind of file that you want to open..."), - browser, - getLookAndFeel().alertWindowBackground); - - if (dialogBox.show()) - { - File selectedFile = browser.getCurrentFile(); - ... - } - } - @endcode - - @see FileChooser -*/ class JUCE_API FileChooserDialogBox : public ResizableWindow, - public ButtonListener, - public FileBrowserListener + public ButtonListener, + public FileBrowserListener { public: - /** Creates a file chooser box. + FileChooserDialogBox (const String& title, + const String& instructions, + FileBrowserComponent& browserComponent, + const bool warnAboutOverwritingExistingFiles, + const Colour& backgroundColour); - @param title the main title to show at the top of the box - @param instructions an optional longer piece of text to show below the title in - a smaller font, describing in more detail what's required. - @param browserComponent a FileBrowserComponent that will be shown inside this dialog - box. Make sure you delete this after (but not before!) the - dialog box has been deleted. - @param warnAboutOverwritingExistingFiles if true, then the user will be asked to confirm - if they try to select a file that already exists. (This - flag is only used when saving files) - @param backgroundColour the background colour for the top level window + ~FileChooserDialogBox(); - @see FileBrowserComponent, FilePreviewComponent - */ - FileChooserDialogBox (const String& title, - const String& instructions, - FileBrowserComponent& browserComponent, - const bool warnAboutOverwritingExistingFiles, - const Colour& backgroundColour); + bool show (int width = 0,int height = 0); - /** Destructor. */ - ~FileChooserDialogBox(); + void buttonClicked (Button* button); + void closeButtonPressed(); + void selectionChanged(); + void fileClicked (const File& file, const MouseEvent& e); + void fileDoubleClicked (const File& file); - /** Displays and runs the dialog box modally. - - This will show the box with the specified size, returning true if the user - pressed 'ok', or false if they cancelled. - - Leave the width or height as 0 to use the default size - */ - bool show (int width = 0,int height = 0); - - /** @internal */ - void buttonClicked (Button* button); - /** @internal */ - void closeButtonPressed(); - /** @internal */ - void selectionChanged(); - /** @internal */ - void fileClicked (const File& file, const MouseEvent& e); - /** @internal */ - void fileDoubleClicked (const File& file); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - class ContentComponent : public Component - { - public: - ContentComponent(); - ~ContentComponent(); + class ContentComponent : public Component + { + public: + ContentComponent(); + ~ContentComponent(); - void paint (Graphics& g); - void resized(); + void paint (Graphics& g); + void resized(); - String instructions; - GlyphArrangement text; + String instructions; + GlyphArrangement text; - FileBrowserComponent* chooserComponent; - FilePreviewComponent* previewComponent; - TextButton* okButton; - TextButton* cancelButton; - }; + FileBrowserComponent* chooserComponent; + FilePreviewComponent* previewComponent; + TextButton* okButton; + TextButton* cancelButton; + }; - ContentComponent* content; - const bool warnAboutOverwritingExistingFiles; + ContentComponent* content; + const bool warnAboutOverwritingExistingFiles; - FileChooserDialogBox (const FileChooserDialogBox&); - const FileChooserDialogBox& operator= (const FileChooserDialogBox&); + FileChooserDialogBox (const FileChooserDialogBox&); + const FileChooserDialogBox& operator= (const FileChooserDialogBox&); }; #endif // __JUCE_FILECHOOSERDIALOGBOX_JUCEHEADER__ @@ -47645,67 +22536,38 @@ private: #ifndef __JUCE_FILELISTCOMPONENT_JUCEHEADER__ #define __JUCE_FILELISTCOMPONENT_JUCEHEADER__ -/** - A component that displays the files in a directory as a listbox. - - This implements the DirectoryContentsDisplayComponent base class so that - it can be used in a FileBrowserComponent. - - To attach a listener to it, use its DirectoryContentsDisplayComponent base - class and the FileBrowserListener class. - - @see DirectoryContentsList, FileTreeComponent -*/ class JUCE_API FileListComponent : public ListBox, - public DirectoryContentsDisplayComponent, - private ListBoxModel, - private ChangeListener + public DirectoryContentsDisplayComponent, + private ListBoxModel, + private ChangeListener { public: - /** Creates a listbox to show the contents of a specified directory. - */ - FileListComponent (DirectoryContentsList& listToShow); + FileListComponent (DirectoryContentsList& listToShow); - /** Destructor. */ - ~FileListComponent(); + ~FileListComponent(); - /** Returns the number of files the user has got selected. - @see getSelectedFile - */ - int getNumSelectedFiles() const; + int getNumSelectedFiles() const; - /** Returns one of the files that the user has currently selected. - The index should be in the range 0 to (getNumSelectedFiles() - 1). - @see getNumSelectedFiles - */ - const File getSelectedFile (int index = 0) const; + const File getSelectedFile (int index = 0) const; - /** Scrolls to the top of the list. */ - void scrollToTop(); + void scrollToTop(); - /** @internal */ - void changeListenerCallback (void*); - /** @internal */ - int getNumRows(); - /** @internal */ - void paintListBoxItem (int, Graphics&, int, int, bool); - /** @internal */ - Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate); - /** @internal */ - void selectedRowsChanged (int lastRowSelected); - /** @internal */ - void deleteKeyPressed (int currentSelectedRow); - /** @internal */ - void returnKeyPressed (int currentSelectedRow); + void changeListenerCallback (void*); + int getNumRows(); + void paintListBoxItem (int, Graphics&, int, int, bool); + Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate); + void selectedRowsChanged (int lastRowSelected); + void deleteKeyPressed (int currentSelectedRow); + void returnKeyPressed (int currentSelectedRow); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - FileListComponent (const FileListComponent&); - const FileListComponent& operator= (const FileListComponent&); + FileListComponent (const FileListComponent&); + const FileListComponent& operator= (const FileListComponent&); - File lastDirectory; + File lastDirectory; }; #endif // __JUCE_FILELISTCOMPONENT_JUCEHEADER__ @@ -47720,183 +22582,87 @@ private: class FilenameComponent; -/** - Listens for events happening to a FilenameComponent. - - Use FilenameComponent::addListener() and FilenameComponent::removeListener() to - register one of these objects for event callbacks when the filename is changed. - - @see FilenameComponent -*/ class JUCE_API FilenameComponentListener { public: - /** Destructor. */ - virtual ~FilenameComponentListener() {} + virtual ~FilenameComponentListener() {} - /** This method is called after the FilenameComponent's file has been changed. */ - virtual void filenameComponentChanged (FilenameComponent* fileComponentThatHasChanged) = 0; + virtual void filenameComponentChanged (FilenameComponent* fileComponentThatHasChanged) = 0; }; -/** - Shows a filename as an editable text box, with a 'browse' button and a - drop-down list for recently selected files. - - A handy component for dialogue boxes where you want the user to be able to - select a file or directory. - - Attach an FilenameComponentListener using the addListener() method, and it will - get called each time the user changes the filename, either by browsing for a file - and clicking 'ok', or by typing a new filename into the box and pressing return. - - @see FileChooser, ComboBox -*/ class JUCE_API FilenameComponent : public Component, - public SettableTooltipClient, - public FileDragAndDropTarget, - private AsyncUpdater, - private ButtonListener, - private ComboBoxListener + public SettableTooltipClient, + public FileDragAndDropTarget, + private AsyncUpdater, + private ButtonListener, + private ComboBoxListener { public: - /** Creates a FilenameComponent. + FilenameComponent (const String& name, + const File& currentFile, + const bool canEditFilename, + const bool isDirectory, + const bool isForSaving, + const String& fileBrowserWildcard, + const String& enforcedSuffix, + const String& textWhenNothingSelected); - @param name the name for this component. - @param currentFile the file to initially show in the box - @param canEditFilename if true, the user can manually edit the filename; if false, - they can only change it by browsing for a new file - @param isDirectory if true, the file will be treated as a directory, and - an appropriate directory browser used - @param isForSaving if true, the file browser will allow non-existent files to - be picked, as the file is assumed to be used for saving rather - than loading - @param fileBrowserWildcard a wildcard pattern to use in the file browser - e.g. "*.txt;*.foo". - If an empty string is passed in, then the pattern is assumed to be "*" - @param enforcedSuffix if this is non-empty, it is treated as a suffix that will be added - to any filenames that are entered or chosen - @param textWhenNothingSelected the message to display in the box before any filename is entered. (This - will only appear if the initial file isn't valid) - */ - FilenameComponent (const String& name, - const File& currentFile, - const bool canEditFilename, - const bool isDirectory, - const bool isForSaving, - const String& fileBrowserWildcard, - const String& enforcedSuffix, - const String& textWhenNothingSelected); + ~FilenameComponent(); - /** Destructor. */ - ~FilenameComponent(); + const File getCurrentFile() const; - /** Returns the currently displayed filename. */ - const File getCurrentFile() const; + void setCurrentFile (File newFile, + const bool addToRecentlyUsedList, + const bool sendChangeNotification = true); - /** Changes the current filename. + void setFilenameIsEditable (const bool shouldBeEditable); - If addToRecentlyUsedList is true, the filename will also be added to the - drop-down list of recent files. + void setDefaultBrowseTarget (const File& newDefaultDirectory) throw(); - If sendChangeNotification is false, then the listeners won't be told of the - change. - */ - void setCurrentFile (File newFile, - const bool addToRecentlyUsedList, - const bool sendChangeNotification = true); + const StringArray getRecentlyUsedFilenames() const; - /** Changes whether the use can type into the filename box. - */ - void setFilenameIsEditable (const bool shouldBeEditable); + void setRecentlyUsedFilenames (const StringArray& filenames); - /** Sets a file or directory to be the default starting point for the browser to show. + void addRecentlyUsedFile (const File& file); - This is only used if the current file hasn't been set. - */ - void setDefaultBrowseTarget (const File& newDefaultDirectory) throw(); + void setMaxNumberOfRecentFiles (const int newMaximum); - /** Returns all the entries on the recent files list. + void setBrowseButtonText (const String& browseButtonText); - This can be used in conjunction with setRecentlyUsedFilenames() for saving the - state of this list. + void addListener (FilenameComponentListener* const listener) throw(); - @see setRecentlyUsedFilenames - */ - const StringArray getRecentlyUsedFilenames() const; + void removeListener (FilenameComponentListener* const listener) throw(); - /** Sets all the entries on the recent files list. + void setTooltip (const String& newTooltip); - This can be used in conjunction with getRecentlyUsedFilenames() for saving the - state of this list. + void paintOverChildren (Graphics& g); + void resized(); + void lookAndFeelChanged(); + bool isInterestedInFileDrag (const StringArray& files); + void filesDropped (const StringArray& files, int, int); + void fileDragEnter (const StringArray& files, int, int); + void fileDragExit (const StringArray& files); - @see getRecentlyUsedFilenames, addRecentlyUsedFile - */ - void setRecentlyUsedFilenames (const StringArray& filenames); - - /** Adds an entry to the recently-used files dropdown list. - - If the file is already in the list, it will be moved to the top. A limit - is also placed on the number of items that are kept in the list. - - @see getRecentlyUsedFilenames, setRecentlyUsedFilenames, setMaxNumberOfRecentFiles - */ - void addRecentlyUsedFile (const File& file); - - /** Changes the limit for the number of files that will be stored in the recent-file list. - */ - void setMaxNumberOfRecentFiles (const int newMaximum); - - /** Changes the text shown on the 'browse' button. - - By default this button just says "..." but you can change it. The button itself - can be changed using the look-and-feel classes, so it might not actually have any - text on it. - */ - void setBrowseButtonText (const String& browseButtonText); - - /** Adds a listener that will be called when the selected file is changed. */ - void addListener (FilenameComponentListener* const listener) throw(); - - /** Removes a previously-registered listener. */ - void removeListener (FilenameComponentListener* const listener) throw(); - - /** Gives the component a tooltip. */ - void setTooltip (const String& newTooltip); - - /** @internal */ - void paintOverChildren (Graphics& g); - /** @internal */ - void resized(); - /** @internal */ - void lookAndFeelChanged(); - /** @internal */ - bool isInterestedInFileDrag (const StringArray& files); - /** @internal */ - void filesDropped (const StringArray& files, int, int); - /** @internal */ - void fileDragEnter (const StringArray& files, int, int); - /** @internal */ - void fileDragExit (const StringArray& files); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ComboBox* filenameBox; - String lastFilename; - Button* browseButton; - int maxRecentFiles; - bool isDir, isSaving, isFileDragOver; - String wildcard, enforcedSuffix, browseButtonText; - SortedSet listeners; - File defaultBrowseFile; + ComboBox* filenameBox; + String lastFilename; + Button* browseButton; + int maxRecentFiles; + bool isDir, isSaving, isFileDragOver; + String wildcard, enforcedSuffix, browseButtonText; + SortedSet listeners; + File defaultBrowseFile; - void comboBoxChanged (ComboBox*); - void buttonClicked (Button* button); - void handleAsyncUpdate(); + void comboBoxChanged (ComboBox*); + void buttonClicked (Button* button); + void handleAsyncUpdate(); - FilenameComponent (const FilenameComponent&); - const FilenameComponent& operator= (const FilenameComponent&); + FilenameComponent (const FilenameComponent&); + const FilenameComponent& operator= (const FilenameComponent&); }; #endif // __JUCE_FILENAMECOMPONENT_JUCEHEADER__ @@ -47912,95 +22678,61 @@ private: #ifndef __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__ #define __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__ -/** - Shows a set of file paths in a list, allowing them to be added, removed or - re-ordered. - - @see FileSearchPath -*/ class JUCE_API FileSearchPathListComponent : public Component, - public SettableTooltipClient, - public FileDragAndDropTarget, - private ButtonListener, - private ListBoxModel + public SettableTooltipClient, + public FileDragAndDropTarget, + private ButtonListener, + private ListBoxModel { public: - /** Creates an empty FileSearchPathListComponent. + FileSearchPathListComponent(); - */ - FileSearchPathListComponent(); + ~FileSearchPathListComponent(); - /** Destructor. */ - ~FileSearchPathListComponent(); + const FileSearchPath& getPath() const throw() { return path; } - /** Returns the path as it is currently shown. */ - const FileSearchPath& getPath() const throw() { return path; } + void setPath (const FileSearchPath& newPath); - /** Changes the current path. */ - void setPath (const FileSearchPath& newPath); + void setDefaultBrowseTarget (const File& newDefaultDirectory) throw(); - /** Sets a file or directory to be the default starting point for the browser to show. + enum ColourIds + { + backgroundColourId = 0x1004100, /**< The background colour to fill the component with. + Make this transparent if you don't want the background to be filled. */ + }; - This is only used if the current file hasn't been set. - */ - void setDefaultBrowseTarget (const File& newDefaultDirectory) throw(); + int getNumRows(); + void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected); + void deleteKeyPressed (int lastRowSelected); + void returnKeyPressed (int lastRowSelected); + void listBoxItemDoubleClicked (int row, const MouseEvent&); + void selectedRowsChanged (int lastRowSelected); + void resized(); + void paint (Graphics& g); + bool isInterestedInFileDrag (const StringArray& files); + void filesDropped (const StringArray& files, int, int); + void buttonClicked (Button* button); - /** A set of colour IDs to use to change the colour of various aspects of the label. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1004100, /**< The background colour to fill the component with. - Make this transparent if you don't want the background to be filled. */ - }; - - /** @internal */ - int getNumRows(); - /** @internal */ - void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected); - /** @internal */ - void deleteKeyPressed (int lastRowSelected); - /** @internal */ - void returnKeyPressed (int lastRowSelected); - /** @internal */ - void listBoxItemDoubleClicked (int row, const MouseEvent&); - /** @internal */ - void selectedRowsChanged (int lastRowSelected); - /** @internal */ - void resized(); - /** @internal */ - void paint (Graphics& g); - /** @internal */ - bool isInterestedInFileDrag (const StringArray& files); - /** @internal */ - void filesDropped (const StringArray& files, int, int); - /** @internal */ - void buttonClicked (Button* button); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - FileSearchPath path; - File defaultBrowseTarget; + FileSearchPath path; + File defaultBrowseTarget; - ListBox* listBox; - Button* addButton; - Button* removeButton; - Button* changeButton; - Button* upButton; - Button* downButton; + ListBox* listBox; + Button* addButton; + Button* removeButton; + Button* changeButton; + Button* upButton; + Button* downButton; - void changed() throw(); - void updateButtons() throw(); + void changed() throw(); + void updateButtons() throw(); - FileSearchPathListComponent (const FileSearchPathListComponent&); - const FileSearchPathListComponent& operator= (const FileSearchPathListComponent&); + FileSearchPathListComponent (const FileSearchPathListComponent&); + const FileSearchPathListComponent& operator= (const FileSearchPathListComponent&); }; #endif // __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__ @@ -48013,61 +22745,32 @@ private: #ifndef __JUCE_FILETREECOMPONENT_JUCEHEADER__ #define __JUCE_FILETREECOMPONENT_JUCEHEADER__ -/** - A component that displays the files in a directory as a treeview. - - This implements the DirectoryContentsDisplayComponent base class so that - it can be used in a FileBrowserComponent. - - To attach a listener to it, use its DirectoryContentsDisplayComponent base - class and the FileBrowserListener class. - - @see DirectoryContentsList, FileListComponent -*/ class JUCE_API FileTreeComponent : public TreeView, - public DirectoryContentsDisplayComponent + public DirectoryContentsDisplayComponent { public: - /** Creates a listbox to show the contents of a specified directory. - */ - FileTreeComponent (DirectoryContentsList& listToShow); + FileTreeComponent (DirectoryContentsList& listToShow); - /** Destructor. */ - ~FileTreeComponent(); + ~FileTreeComponent(); - /** Returns the number of files the user has got selected. - @see getSelectedFile - */ - int getNumSelectedFiles() const { return TreeView::getNumSelectedItems(); } + int getNumSelectedFiles() const { return TreeView::getNumSelectedItems(); } - /** Returns one of the files that the user has currently selected. - The index should be in the range 0 to (getNumSelectedFiles() - 1). - @see getNumSelectedFiles - */ - const File getSelectedFile (int index = 0) const; + const File getSelectedFile (int index = 0) const; - /** Scrolls the list to the top. */ - void scrollToTop(); + void scrollToTop(); - /** Setting a name for this allows tree items to be dragged. + void setDragAndDropDescription (const String& description) throw(); - The string that you pass in here will be returned by the getDragSourceDescription() - of the items in the tree. For more info, see TreeViewItem::getDragSourceDescription(). - */ - void setDragAndDropDescription (const String& description) throw(); + const String& getDragAndDropDescription() const throw() { return dragAndDropDescription; } - /** Returns the last value that was set by setDragAndDropDescription(). - */ - const String& getDragAndDropDescription() const throw() { return dragAndDropDescription; } - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - String dragAndDropDescription; + String dragAndDropDescription; - FileTreeComponent (const FileTreeComponent&); - const FileTreeComponent& operator= (const FileTreeComponent&); + FileTreeComponent (const FileTreeComponent&); + const FileTreeComponent& operator= (const FileTreeComponent&); }; #endif // __JUCE_FILETREECOMPONENT_JUCEHEADER__ @@ -48080,40 +22783,30 @@ private: #ifndef __JUCE_IMAGEPREVIEWCOMPONENT_JUCEHEADER__ #define __JUCE_IMAGEPREVIEWCOMPONENT_JUCEHEADER__ -/** - A simple preview component that shows thumbnails of image files. - - @see FileChooserDialogBox, FilePreviewComponent -*/ class JUCE_API ImagePreviewComponent : public FilePreviewComponent, - private Timer + private Timer { public: - /** Creates an ImagePreviewComponent. */ - ImagePreviewComponent(); + ImagePreviewComponent(); - /** Destructor. */ - ~ImagePreviewComponent(); + ~ImagePreviewComponent(); - /** @internal */ - void selectedFileChanged (const File& newSelectedFile); - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void timerCallback(); + void selectedFileChanged (const File& newSelectedFile); + void paint (Graphics& g); + void timerCallback(); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - File fileToLoad; - ScopedPointer currentThumbnail; - String currentDetails; + File fileToLoad; + ScopedPointer currentThumbnail; + String currentDetails; - void getThumbSize (int& w, int& h) const; + void getThumbSize (int& w, int& h) const; - ImagePreviewComponent (const ImagePreviewComponent&); - const ImagePreviewComponent& operator= (const ImagePreviewComponent&); + ImagePreviewComponent (const ImagePreviewComponent&); + const ImagePreviewComponent& operator= (const ImagePreviewComponent&); }; #endif // __JUCE_IMAGEPREVIEWCOMPONENT_JUCEHEADER__ @@ -48126,48 +22819,27 @@ private: #ifndef __JUCE_WILDCARDFILEFILTER_JUCEHEADER__ #define __JUCE_WILDCARDFILEFILTER_JUCEHEADER__ -/** - A type of FileFilter that works by wildcard pattern matching. - - This filter only allows files that match one of the specified patterns, but - allows all directories through. - - @see FileFilter, DirectoryContentsList, FileListComponent, FileBrowserComponent -*/ class JUCE_API WildcardFileFilter : public FileFilter { public: - /** - Creates a wildcard filter for one or more patterns. + WildcardFileFilter (const String& fileWildcardPatterns, + const String& directoryWildcardPatterns, + const String& description); - The wildcardPatterns parameter is a comma or semicolon-delimited set of - patterns, e.g. "*.wav;*.aiff" would look for files ending in either .wav - or .aiff. + ~WildcardFileFilter(); - The description is a name to show the user in a list of possible patterns, so - for the wav/aiff example, your description might be "audio files". - */ - WildcardFileFilter (const String& fileWildcardPatterns, - const String& directoryWildcardPatterns, - const String& description); + bool isFileSuitable (const File& file) const; - /** Destructor. */ - ~WildcardFileFilter(); + bool isDirectorySuitable (const File& file) const; - /** Returns true if the filename matches one of the patterns specified. */ - bool isFileSuitable (const File& file) const; - - /** This always returns true. */ - bool isDirectorySuitable (const File& file) const; - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - StringArray fileWildcards, directoryWildcards; + StringArray fileWildcards, directoryWildcards; - static void parse (const String& pattern, StringArray& result) throw(); - static bool match (const File& file, const StringArray& wildcards) throw(); + static void parse (const String& pattern, StringArray& result) throw(); + static bool match (const File& file, const StringArray& wildcards) throw(); }; #endif // __JUCE_WILDCARDFILEFILTER_JUCEHEADER__ @@ -48202,339 +22874,141 @@ private: #ifndef __JUCE_KEYPRESSMAPPINGSET_JUCEHEADER__ #define __JUCE_KEYPRESSMAPPINGSET_JUCEHEADER__ -/** - Manages and edits a list of keypresses, which it uses to invoke the appropriate - command in a ApplicationCommandManager. - - Normally, you won't actually create a KeyPressMappingSet directly, because - each ApplicationCommandManager contains its own KeyPressMappingSet, so typically - you'd create yourself an ApplicationCommandManager, and call its - ApplicationCommandManager::getKeyMappings() method to get a pointer to its - KeyPressMappingSet. - - For one of these to actually use keypresses, you'll need to add it as a KeyListener - to the top-level component for which you want to handle keystrokes. So for example: - - @code - class MyMainWindow : public Component - { - ApplicationCommandManager* myCommandManager; - - public: - MyMainWindow() - { - myCommandManager = new ApplicationCommandManager(); - - // first, make sure the command manager has registered all the commands that its - // targets can perform.. - myCommandManager->registerAllCommandsForTarget (myCommandTarget1); - myCommandManager->registerAllCommandsForTarget (myCommandTarget2); - - // this will use the command manager to initialise the KeyPressMappingSet with - // the default keypresses that were specified when the targets added their commands - // to the manager. - myCommandManager->getKeyMappings()->resetToDefaultMappings(); - - // having set up the default key-mappings, you might now want to load the last set - // of mappings that the user configured. - myCommandManager->getKeyMappings()->restoreFromXml (lastSavedKeyMappingsXML); - - // Now tell our top-level window to send any keypresses that arrive to the - // KeyPressMappingSet, which will use them to invoke the appropriate commands. - addKeyListener (myCommandManager->getKeyMappings()); - } - - ... - } - @endcode - - KeyPressMappingSet derives from ChangeBroadcaster so that interested parties can - register to be told when a command or mapping is added, removed, etc. - - There's also a UI component called KeyMappingEditorComponent that can be used - to easily edit the key mappings. - - @see Component::addKeyListener(), KeyMappingEditorComponent, ApplicationCommandManager -*/ class JUCE_API KeyPressMappingSet : public KeyListener, - public ChangeBroadcaster, - public FocusChangeListener + public ChangeBroadcaster, + public FocusChangeListener { public: - /** Creates a KeyPressMappingSet for a given command manager. + KeyPressMappingSet (ApplicationCommandManager* const commandManager) throw(); - Normally, you won't actually create a KeyPressMappingSet directly, because - each ApplicationCommandManager contains its own KeyPressMappingSet, so the - best thing to do is to create your ApplicationCommandManager, and use the - ApplicationCommandManager::getKeyMappings() method to access its mappings. + KeyPressMappingSet (const KeyPressMappingSet& other) throw(); - When a suitable keypress happens, the manager's invoke() method will be - used to invoke the appropriate command. + ~KeyPressMappingSet(); - @see ApplicationCommandManager - */ - KeyPressMappingSet (ApplicationCommandManager* const commandManager) throw(); + ApplicationCommandManager* getCommandManager() const throw() { return commandManager; } - /** Creates an copy of a KeyPressMappingSet. */ - KeyPressMappingSet (const KeyPressMappingSet& other) throw(); + const Array getKeyPressesAssignedToCommand (const CommandID commandID) const throw(); - /** Destructor. */ - ~KeyPressMappingSet(); + void addKeyPress (const CommandID commandID, + const KeyPress& newKeyPress, + int insertIndex = -1) throw(); - ApplicationCommandManager* getCommandManager() const throw() { return commandManager; } + void resetToDefaultMappings() throw(); - /** Returns a list of keypresses that are assigned to a particular command. + void resetToDefaultMapping (const CommandID commandID) throw(); - @param commandID the command's ID - */ - const Array getKeyPressesAssignedToCommand (const CommandID commandID) const throw(); + void clearAllKeyPresses() throw(); - /** Assigns a keypress to a command. + void clearAllKeyPresses (const CommandID commandID) throw(); - If the keypress is already assigned to a different command, it will first be - removed from that command, to avoid it triggering multiple functions. + void removeKeyPress (const CommandID commandID, + const int keyPressIndex) throw(); - @param commandID the ID of the command that you want to add a keypress to. If - this is 0, the keypress will be removed from anything that it - was previously assigned to, but not re-assigned - @param newKeyPress the new key-press - @param insertIndex if this is less than zero, the key will be appended to the - end of the list of keypresses; otherwise the new keypress will - be inserted into the existing list at this index - */ - void addKeyPress (const CommandID commandID, - const KeyPress& newKeyPress, - int insertIndex = -1) throw(); + void removeKeyPress (const KeyPress& keypress) throw(); - /** Reset all mappings to the defaults, as dictated by the ApplicationCommandManager. + bool containsMapping (const CommandID commandID, + const KeyPress& keyPress) const throw(); - @see resetToDefaultMapping - */ - void resetToDefaultMappings() throw(); + CommandID findCommandForKeyPress (const KeyPress& keyPress) const throw(); - /** Resets all key-mappings to the defaults for a particular command. + bool restoreFromXml (const XmlElement& xmlVersion); - @see resetToDefaultMappings - */ - void resetToDefaultMapping (const CommandID commandID) throw(); + XmlElement* createXml (const bool saveDifferencesFromDefaultSet) const; - /** Removes all keypresses that are assigned to any commands. */ - void clearAllKeyPresses() throw(); + bool keyPressed (const KeyPress& key, Component* originatingComponent); + bool keyStateChanged (const bool isKeyDown, Component* originatingComponent); + void globalFocusChanged (Component* focusedComponent); - /** Removes all keypresses that are assigned to a particular command. */ - void clearAllKeyPresses (const CommandID commandID) throw(); - - /** Removes one of the keypresses that are assigned to a command. - - See the getKeyPressesAssignedToCommand() for the list of keypresses to - which the keyPressIndex refers. - */ - void removeKeyPress (const CommandID commandID, - const int keyPressIndex) throw(); - - /** Removes a keypress from any command that it may be assigned to. - */ - void removeKeyPress (const KeyPress& keypress) throw(); - - /** Returns true if the given command is linked to this key. */ - bool containsMapping (const CommandID commandID, - const KeyPress& keyPress) const throw(); - - /** Looks for a command that corresponds to a keypress. - - @returns the UID of the command or 0 if none was found - */ - CommandID findCommandForKeyPress (const KeyPress& keyPress) const throw(); - - /** Tries to recreate the mappings from a previously stored state. - - The XML passed in must have been created by the createXml() method. - - If the stored state makes any reference to commands that aren't - currently available, these will be ignored. - - If the set of mappings being loaded was a set of differences (using createXml (true)), - then this will call resetToDefaultMappings() and then merge the saved mappings - on top. If the saved set was created with createXml (false), then this method - will first clear all existing mappings and load the saved ones as a complete set. - - @returns true if it manages to load the XML correctly - @see createXml - */ - bool restoreFromXml (const XmlElement& xmlVersion); - - /** Creates an XML representation of the current mappings. - - This will produce a lump of XML that can be later reloaded using - restoreFromXml() to recreate the current mapping state. - - The object that is returned must be deleted by the caller. - - @param saveDifferencesFromDefaultSet if this is false, then all keypresses - will be saved into the XML. If it's true, then the XML will - only store the differences between the current mappings and - the default mappings you'd get from calling resetToDefaultMappings(). - The advantage of saving a set of differences from the default is that - if you change the default mappings (in a new version of your app, for - example), then these will be merged into a user's saved preferences. - - @see restoreFromXml - */ - XmlElement* createXml (const bool saveDifferencesFromDefaultSet) const; - - /** @internal */ - bool keyPressed (const KeyPress& key, Component* originatingComponent); - /** @internal */ - bool keyStateChanged (const bool isKeyDown, Component* originatingComponent); - /** @internal */ - void globalFocusChanged (Component* focusedComponent); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ApplicationCommandManager* commandManager; + ApplicationCommandManager* commandManager; - struct CommandMapping - { - CommandID commandID; - Array keypresses; - bool wantsKeyUpDownCallbacks; - }; + struct CommandMapping + { + CommandID commandID; + Array keypresses; + bool wantsKeyUpDownCallbacks; + }; - OwnedArray mappings; + OwnedArray mappings; - struct KeyPressTime - { - KeyPress key; - uint32 timeWhenPressed; - }; + struct KeyPressTime + { + KeyPress key; + uint32 timeWhenPressed; + }; - OwnedArray keysDown; + OwnedArray keysDown; - void handleMessage (const Message& message); + void handleMessage (const Message& message); - void invokeCommand (const CommandID commandID, - const KeyPress& keyPress, - const bool isKeyDown, - const int millisecsSinceKeyPressed, - Component* const originatingComponent) const; + void invokeCommand (const CommandID commandID, + const KeyPress& keyPress, + const bool isKeyDown, + const int millisecsSinceKeyPressed, + Component* const originatingComponent) const; - const KeyPressMappingSet& operator= (const KeyPressMappingSet&); + const KeyPressMappingSet& operator= (const KeyPressMappingSet&); }; #endif // __JUCE_KEYPRESSMAPPINGSET_JUCEHEADER__ /********* End of inlined file: juce_KeyPressMappingSet.h *********/ -/** - A component to allow editing of the keymaps stored by a KeyPressMappingSet - object. - - @see KeyPressMappingSet -*/ class JUCE_API KeyMappingEditorComponent : public Component, - public TreeViewItem, - public ChangeListener, - private ButtonListener + public TreeViewItem, + public ChangeListener, + private ButtonListener { public: - /** Creates a KeyMappingEditorComponent. + KeyMappingEditorComponent (KeyPressMappingSet* const mappingSet, + const bool showResetToDefaultButton); - @param mappingSet this is the set of mappings to display and - edit. Make sure the mappings object is not - deleted before this component! - @param showResetToDefaultButton if true, then at the bottom of the - list, the component will include a 'reset to - defaults' button. - */ - KeyMappingEditorComponent (KeyPressMappingSet* const mappingSet, - const bool showResetToDefaultButton); + virtual ~KeyMappingEditorComponent(); - /** Destructor. */ - virtual ~KeyMappingEditorComponent(); + void setColours (const Colour& mainBackground, + const Colour& textColour); - /** Sets up the colours to use for parts of the component. + KeyPressMappingSet* getMappings() const throw() { return mappings; } - @param mainBackground colour to use for most of the background - @param textColour colour to use for the text - */ - void setColours (const Colour& mainBackground, - const Colour& textColour); + virtual bool shouldCommandBeIncluded (const CommandID commandID); - /** Returns the KeyPressMappingSet that this component is acting upon. - */ - KeyPressMappingSet* getMappings() const throw() { return mappings; } + virtual bool isCommandReadOnly (const CommandID commandID); - /** Can be overridden if some commands need to be excluded from the list. + virtual const String getDescriptionForKeyPress (const KeyPress& key); - By default this will use the KeyPressMappingSet's shouldCommandBeVisibleInEditor() - method to decide what to return, but you can override it to handle special cases. - */ - virtual bool shouldCommandBeIncluded (const CommandID commandID); + enum ColourIds + { + backgroundColourId = 0x100ad00, /**< The background colour to fill the editor background. */ + textColourId = 0x100ad01, /**< The colour for the text. */ + }; - /** Can be overridden to indicate that some commands are shown as read-only. + void parentHierarchyChanged(); + void resized(); + void changeListenerCallback (void*); + bool mightContainSubItems(); + const String getUniqueName() const; + void buttonClicked (Button* button); - By default this will use the KeyPressMappingSet's shouldCommandBeReadOnlyInEditor() - method to decide what to return, but you can override it to handle special cases. - */ - virtual bool isCommandReadOnly (const CommandID commandID); - - /** This can be overridden to let you change the format of the string used - to describe a keypress. - - This is handy if you're using non-standard KeyPress objects, e.g. for custom - keys that are triggered by something else externally. If you override the - method, be sure to let the base class's method handle keys you're not - interested in. - */ - virtual const String getDescriptionForKeyPress (const KeyPress& key); - - /** A set of colour IDs to use to change the colour of various aspects of the editor. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - To change the colours of the menu that pops up - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x100ad00, /**< The background colour to fill the editor background. */ - textColourId = 0x100ad01, /**< The colour for the text. */ - }; - - /** @internal */ - void parentHierarchyChanged(); - /** @internal */ - void resized(); - /** @internal */ - void changeListenerCallback (void*); - /** @internal */ - bool mightContainSubItems(); - /** @internal */ - const String getUniqueName() const; - /** @internal */ - void buttonClicked (Button* button); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - KeyPressMappingSet* mappings; - TreeView* tree; - friend class KeyMappingTreeViewItem; - friend class KeyCategoryTreeViewItem; - friend class KeyMappingItemComponent; - friend class KeyMappingChangeButton; - TextButton* resetButton; + KeyPressMappingSet* mappings; + TreeView* tree; + friend class KeyMappingTreeViewItem; + friend class KeyCategoryTreeViewItem; + friend class KeyMappingItemComponent; + friend class KeyMappingChangeButton; + TextButton* resetButton; - void assignNewKey (const CommandID commandID, int index); + void assignNewKey (const CommandID commandID, int index); - KeyMappingEditorComponent (const KeyMappingEditorComponent&); - const KeyMappingEditorComponent& operator= (const KeyMappingEditorComponent&); + KeyMappingEditorComponent (const KeyMappingEditorComponent&); + const KeyMappingEditorComponent& operator= (const KeyMappingEditorComponent&); }; #endif // __JUCE_KEYMAPPINGEDITORCOMPONENT_JUCEHEADER__ @@ -48562,62 +23036,39 @@ private: #ifndef __JUCE_COMPONENTMOVEMENTWATCHER_JUCEHEADER__ #define __JUCE_COMPONENTMOVEMENTWATCHER_JUCEHEADER__ -/** An object that watches for any movement of a component or any of its parent components. - - This makes it easy to check when a component is moved relative to its top-level - peer window. The normal Component::moved() method is only called when a component - moves relative to its immediate parent, and sometimes you want to know if any of - components higher up the tree have moved (which of course will affect the overall - position of all their sub-components). - - It also includes a callback that lets you know when the top-level peer is changed. - - This class is used by specialised components like OpenGLComponent or QuickTimeComponent - because they need to keep their custom windows in the right place and respond to - changes in the peer. -*/ -class JUCE_API ComponentMovementWatcher : public ComponentListener +class JUCE_API ComponentMovementWatcher : public ComponentListener { public: - /** Creates a ComponentMovementWatcher to watch a given target component. */ - ComponentMovementWatcher (Component* const component); + ComponentMovementWatcher (Component* const component); - /** Destructor. */ - ~ComponentMovementWatcher(); + ~ComponentMovementWatcher(); - /** This callback happens when the component that is being watched is moved - relative to its top-level peer window, or when it is resized. - */ - virtual void componentMovedOrResized (bool wasMoved, bool wasResized) = 0; + virtual void componentMovedOrResized (bool wasMoved, bool wasResized) = 0; - /** This callback happens when the component's top-level peer is changed. - */ - virtual void componentPeerChanged() = 0; + virtual void componentPeerChanged() = 0; - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator - /** @internal */ - void componentParentHierarchyChanged (Component& component); - /** @internal */ - void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); + void componentParentHierarchyChanged (Component& component); + void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized); private: - Component* const component; - ComponentPeer* lastPeer; - VoidArray registeredParentComps; - bool reentrant; - int lastX, lastY, lastWidth, lastHeight; + Component* const component; + ComponentPeer* lastPeer; + VoidArray registeredParentComps; + bool reentrant; + int lastX, lastY, lastWidth, lastHeight; #ifdef JUCE_DEBUG - ScopedPointer deletionWatcher; + ScopedPointer deletionWatcher; #endif - void unregister() throw(); - void registerWithParentComps() throw(); + void unregister() throw(); + void registerWithParentComps() throw(); - ComponentMovementWatcher (const ComponentMovementWatcher&); - const ComponentMovementWatcher& operator= (const ComponentMovementWatcher&); + ComponentMovementWatcher (const ComponentMovementWatcher&); + const ComponentMovementWatcher& operator= (const ComponentMovementWatcher&); }; #endif // __JUCE_COMPONENTMOVEMENTWATCHER_JUCEHEADER__ @@ -48630,72 +23081,39 @@ private: #ifndef __JUCE_GROUPCOMPONENT_JUCEHEADER__ #define __JUCE_GROUPCOMPONENT_JUCEHEADER__ -/** - A component that draws an outline around itself and has an optional title at - the top, for drawing an outline around a group of controls. - -*/ -class JUCE_API GroupComponent : public Component +class JUCE_API GroupComponent : public Component { public: - /** Creates a GroupComponent. + GroupComponent (const String& componentName, + const String& labelText); - @param componentName the name to give the component - @param labelText the text to show at the top of the outline - */ - GroupComponent (const String& componentName, - const String& labelText); + ~GroupComponent(); - /** Destructor. */ - ~GroupComponent(); + void setText (const String& newText) throw(); - /** Changes the text that's shown at the top of the component. */ - void setText (const String& newText) throw(); + const String getText() const throw(); - /** Returns the currently displayed text label. */ - const String getText() const throw(); + void setTextLabelPosition (const Justification& justification); - /** Sets the positioning of the text label. + const Justification getTextLabelPosition() const throw() { return justification; } - (The default is Justification::left) + enum ColourIds + { + outlineColourId = 0x1005400, /**< The colour to use for drawing the line around the edge. */ + textColourId = 0x1005410 /**< The colour to use to draw the text label. */ + }; - @see getTextLabelPosition - */ - void setTextLabelPosition (const Justification& justification); - - /** Returns the current text label position. - - @see setTextLabelPosition - */ - const Justification getTextLabelPosition() const throw() { return justification; } - - /** A set of colour IDs to use to change the colour of various aspects of the component. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - outlineColourId = 0x1005400, /**< The colour to use for drawing the line around the edge. */ - textColourId = 0x1005410 /**< The colour to use to draw the text label. */ - }; - - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void enablementChanged(); - /** @internal */ - void colourChanged(); + void paint (Graphics& g); + void enablementChanged(); + void colourChanged(); private: - String text; - Justification justification; + String text; + Justification justification; - GroupComponent (const GroupComponent&); - const GroupComponent& operator= (const GroupComponent&); + GroupComponent (const GroupComponent&); + const GroupComponent& operator= (const GroupComponent&); }; #endif // __JUCE_GROUPCOMPONENT_JUCEHEADER__ @@ -48718,460 +23136,224 @@ private: class TabbedButtonBar; -/** In a TabbedButtonBar, this component is used for each of the buttons. - - If you want to create a TabbedButtonBar with custom tab components, derive - your component from this class, and override the TabbedButtonBar::createTabButton() - method to create it instead of the default one. - - @see TabbedButtonBar -*/ class JUCE_API TabBarButton : public Button { public: - /** Creates the tab button. */ - TabBarButton (const String& name, - TabbedButtonBar* const ownerBar, - const int tabIndex); + TabBarButton (const String& name, + TabbedButtonBar* const ownerBar, + const int tabIndex); - /** Destructor. */ - ~TabBarButton(); + ~TabBarButton(); - /** Chooses the best length for the tab, given the specified depth. + virtual int getBestTabLength (const int depth); - If the tab is horizontal, this should return its width, and the depth - specifies its height. If it's vertical, it should return the height, and - the depth is actually its width. - */ - virtual int getBestTabLength (const int depth); + void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown); + void clicked (const ModifierKeys& mods); + bool hitTest (int x, int y); - void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown); - void clicked (const ModifierKeys& mods); - bool hitTest (int x, int y); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - friend class TabbedButtonBar; - TabbedButtonBar* const owner; - int tabIndex, overlapPixels; - DropShadowEffect shadow; + friend class TabbedButtonBar; + TabbedButtonBar* const owner; + int tabIndex, overlapPixels; + DropShadowEffect shadow; - /** Returns an area of the component that's safe to draw in. - - This deals with the orientation of the tabs, which affects which side is - touching the tabbed box's content component. - */ - void getActiveArea (int& x, int& y, int& w, int& h); + void getActiveArea (int& x, int& y, int& w, int& h); private: - TabBarButton (const TabBarButton&); - const TabBarButton& operator= (const TabBarButton&); + TabBarButton (const TabBarButton&); + const TabBarButton& operator= (const TabBarButton&); }; -/** - A vertical or horizontal bar containing tabs that you can select. - - You can use one of these to generate things like a dialog box that has - tabbed pages you can flip between. Attach a ChangeListener to the - button bar to be told when the user changes the page. - - An easier method than doing this is to use a TabbedComponent, which - contains its own TabbedButtonBar and which takes care of the layout - and other housekeeping. - - @see TabbedComponent -*/ class JUCE_API TabbedButtonBar : public Component, - public ChangeBroadcaster, - public ButtonListener + public ChangeBroadcaster, + public ButtonListener { public: - /** The placement of the tab-bar + enum Orientation + { + TabsAtTop, + TabsAtBottom, + TabsAtLeft, + TabsAtRight + }; - @see setOrientation, getOrientation - */ - enum Orientation - { - TabsAtTop, - TabsAtBottom, - TabsAtLeft, - TabsAtRight - }; + TabbedButtonBar (const Orientation orientation); - /** Creates a TabbedButtonBar with a given placement. + ~TabbedButtonBar(); - You can change the orientation later if you need to. - */ - TabbedButtonBar (const Orientation orientation); + void setOrientation (const Orientation orientation); - /** Destructor. */ - ~TabbedButtonBar(); + Orientation getOrientation() const throw() { return orientation; } - /** Changes the bar's orientation. + void clearTabs(); - This won't change the bar's actual size - you'll need to do that yourself, - but this determines which direction the tabs go in, and which side they're - stuck to. - */ - void setOrientation (const Orientation orientation); + void addTab (const String& tabName, + const Colour& tabBackgroundColour, + int insertIndex = -1); - /** Returns the current orientation. + void setTabName (const int tabIndex, + const String& newName); - @see setOrientation - */ - Orientation getOrientation() const throw() { return orientation; } + void removeTab (const int tabIndex); - /** Deletes all the tabs from the bar. + void moveTab (const int currentIndex, + const int newIndex); - @see addTab - */ - void clearTabs(); + int getNumTabs() const; - /** Adds a tab to the bar. + const StringArray getTabNames() const; - Tabs are added in left-to-right reading order. + void setCurrentTabIndex (int newTabIndex, const bool sendChangeMessage = true); - If this is the first tab added, it'll also be automatically selected. - */ - void addTab (const String& tabName, - const Colour& tabBackgroundColour, - int insertIndex = -1); + const String& getCurrentTabName() const throw() { return tabs [currentTabIndex]; } - /** Changes the name of one of the tabs. */ - void setTabName (const int tabIndex, - const String& newName); + int getCurrentTabIndex() const throw() { return currentTabIndex; } - /** Gets rid of one of the tabs. */ - void removeTab (const int tabIndex); + TabBarButton* getTabButton (const int index) const; - /** Moves a tab to a new index in the list. + virtual void currentTabChanged (const int newCurrentTabIndex, + const String& newCurrentTabName); - Pass -1 as the index to move it to the end of the list. - */ - void moveTab (const int currentIndex, - const int newIndex); + virtual void popupMenuClickOnTab (const int tabIndex, + const String& tabName); - /** Returns the number of tabs in the bar. */ - int getNumTabs() const; + const Colour getTabBackgroundColour (const int tabIndex); - /** Returns a list of all the tab names in the bar. */ - const StringArray getTabNames() const; + void setTabBackgroundColour (const int tabIndex, const Colour& newColour); - /** Changes the currently selected tab. + enum ColourIds + { + tabOutlineColourId = 0x1005812, /**< The colour to use to draw an outline around the tabs. */ + tabTextColourId = 0x1005813, /**< The colour to use to draw the tab names. If this isn't specified, + the look and feel will choose an appropriate colour. */ + frontOutlineColourId = 0x1005814, /**< The colour to use to draw an outline around the currently-selected tab. */ + frontTextColourId = 0x1005815, /**< The colour to use to draw the currently-selected tab name. If + this isn't specified, the look and feel will choose an appropriate + colour. */ + }; - This will send a change message and cause a synchronous callback to - the currentTabChanged() method. (But if the given tab is already selected, - nothing will be done). + void resized(); + void buttonClicked (Button* button); + void lookAndFeelChanged(); - To deselect all the tabs, use an index of -1. - */ - void setCurrentTabIndex (int newTabIndex, const bool sendChangeMessage = true); - - /** Returns the name of the currently selected tab. - - This could be an empty string if none are selected. - */ - const String& getCurrentTabName() const throw() { return tabs [currentTabIndex]; } - - /** Returns the index of the currently selected tab. - - This could return -1 if none are selected. - */ - int getCurrentTabIndex() const throw() { return currentTabIndex; } - - /** Returns the button for a specific tab. - - The button that is returned may be deleted later by this component, so don't hang - on to the pointer that is returned. A null pointer may be returned if the index is - out of range. - */ - TabBarButton* getTabButton (const int index) const; - - /** Callback method to indicate the selected tab has been changed. - - @see setCurrentTabIndex - */ - virtual void currentTabChanged (const int newCurrentTabIndex, - const String& newCurrentTabName); - - /** Callback method to indicate that the user has right-clicked on a tab. - - (Or ctrl-clicked on the Mac) - */ - virtual void popupMenuClickOnTab (const int tabIndex, - const String& tabName); - - /** Returns the colour of a tab. - - This is the colour that was specified in addTab(). - */ - const Colour getTabBackgroundColour (const int tabIndex); - - /** Changes the background colour of a tab. - - @see addTab, getTabBackgroundColour - */ - void setTabBackgroundColour (const int tabIndex, const Colour& newColour); - - /** A set of colour IDs to use to change the colour of various aspects of the component. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - tabOutlineColourId = 0x1005812, /**< The colour to use to draw an outline around the tabs. */ - tabTextColourId = 0x1005813, /**< The colour to use to draw the tab names. If this isn't specified, - the look and feel will choose an appropriate colour. */ - frontOutlineColourId = 0x1005814, /**< The colour to use to draw an outline around the currently-selected tab. */ - frontTextColourId = 0x1005815, /**< The colour to use to draw the currently-selected tab name. If - this isn't specified, the look and feel will choose an appropriate - colour. */ - }; - - /** @internal */ - void resized(); - /** @internal */ - void buttonClicked (Button* button); - /** @internal */ - void lookAndFeelChanged(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - /** This creates one of the tabs. - - If you need to use custom tab components, you can override this method and - return your own class instead of the default. - */ - virtual TabBarButton* createTabButton (const String& tabName, - const int tabIndex); + virtual TabBarButton* createTabButton (const String& tabName, + const int tabIndex); private: - Orientation orientation; + Orientation orientation; - StringArray tabs; - Array tabColours; - int currentTabIndex; - Component* behindFrontTab; - Button* extraTabsButton; + StringArray tabs; + Array tabColours; + int currentTabIndex; + Component* behindFrontTab; + Button* extraTabsButton; - TabbedButtonBar (const TabbedButtonBar&); - const TabbedButtonBar& operator= (const TabbedButtonBar&); + TabbedButtonBar (const TabbedButtonBar&); + const TabbedButtonBar& operator= (const TabbedButtonBar&); }; #endif // __JUCE_TABBEDBUTTONBAR_JUCEHEADER__ /********* End of inlined file: juce_TabbedButtonBar.h *********/ -/** - A component with a TabbedButtonBar along one of its sides. - - This makes it easy to create a set of tabbed pages, just add a bunch of tabs - with addTab(), and this will take care of showing the pages for you when the - user clicks on a different tab. - - @see TabbedButtonBar -*/ class JUCE_API TabbedComponent : public Component { public: - /** Creates a TabbedComponent, specifying where the tabs should be placed. + TabbedComponent (const TabbedButtonBar::Orientation orientation); - Once created, add some tabs with the addTab() method. - */ - TabbedComponent (const TabbedButtonBar::Orientation orientation); + ~TabbedComponent(); - /** Destructor. */ - ~TabbedComponent(); + void setOrientation (const TabbedButtonBar::Orientation orientation); - /** Changes the placement of the tabs. + TabbedButtonBar::Orientation getOrientation() const throw(); - This will rearrange the layout to place the tabs along the appropriate - side of this component, and will shift the content component accordingly. + void setTabBarDepth (const int newDepth); - @see TabbedButtonBar::setOrientation - */ - void setOrientation (const TabbedButtonBar::Orientation orientation); + int getTabBarDepth() const throw() { return tabDepth; } - /** Returns the current tab placement. + void setOutline (const int newThickness); - @see setOrientation, TabbedButtonBar::getOrientation - */ - TabbedButtonBar::Orientation getOrientation() const throw(); + void setIndent (const int indentThickness); - /** Specifies how many pixels wide or high the tab-bar should be. + void clearTabs(); - If the tabs are placed along the top or bottom, this specified the height - of the bar; if they're along the left or right edges, it'll be the width - of the bar. - */ - void setTabBarDepth (const int newDepth); + void addTab (const String& tabName, + const Colour& tabBackgroundColour, + Component* const contentComponent, + const bool deleteComponentWhenNotNeeded, + const int insertIndex = -1); - /** Returns the current thickness of the tab bar. + void setTabName (const int tabIndex, + const String& newName); - @see setTabBarDepth - */ - int getTabBarDepth() const throw() { return tabDepth; } + void removeTab (const int tabIndex); - /** Specifies the thickness of an outline that should be drawn around the content component. + int getNumTabs() const; - If this thickness is > 0, a line will be drawn around the three sides of the content - component which don't touch the tab-bar, and the content component will be inset by this amount. + const StringArray getTabNames() const; - To set the colour of the line, use setColour (outlineColourId, ...). - */ - void setOutline (const int newThickness); + Component* getTabContentComponent (const int tabIndex) const throw(); - /** Specifies a gap to leave around the edge of the content component. + const Colour getTabBackgroundColour (const int tabIndex) const throw(); - Each edge of the content component will be indented by the given number of pixels. - */ - void setIndent (const int indentThickness); + void setTabBackgroundColour (const int tabIndex, const Colour& newColour); - /** Removes all the tabs from the bar. + void setCurrentTabIndex (const int newTabIndex, const bool sendChangeMessage = true); - @see TabbedButtonBar::clearTabs - */ - void clearTabs(); + int getCurrentTabIndex() const; - /** Adds a tab to the tab-bar. + const String& getCurrentTabName() const; - The component passed in will be shown for the tab, and if deleteComponentWhenNotNeeded - is true, it will be deleted when the tab is removed or when this object is - deleted. + Component* getCurrentContentComponent() const throw() { return panelComponent; } - @see TabbedButtonBar::addTab - */ - void addTab (const String& tabName, - const Colour& tabBackgroundColour, - Component* const contentComponent, - const bool deleteComponentWhenNotNeeded, - const int insertIndex = -1); + virtual void currentTabChanged (const int newCurrentTabIndex, + const String& newCurrentTabName); - /** Changes the name of one of the tabs. */ - void setTabName (const int tabIndex, - const String& newName); + virtual void popupMenuClickOnTab (const int tabIndex, + const String& tabName); - /** Gets rid of one of the tabs. */ - void removeTab (const int tabIndex); + TabbedButtonBar& getTabbedButtonBar() const throw() { return *tabs; } - /** Returns the number of tabs in the bar. */ - int getNumTabs() const; + enum ColourIds + { + backgroundColourId = 0x1005800, /**< The colour to fill the background behind the tabs. */ + outlineColourId = 0x1005801, /**< The colour to use to draw an outline around the content. + (See setOutline) */ + }; - /** Returns a list of all the tab names in the bar. */ - const StringArray getTabNames() const; + void paint (Graphics& g); + void resized(); + void lookAndFeelChanged(); - /** Returns the content component that was added for the given index. - - Be sure not to use or delete the components that are returned, as this may interfere - with the TabbedComponent's use of them. - */ - Component* getTabContentComponent (const int tabIndex) const throw(); - - /** Returns the colour of one of the tabs. */ - const Colour getTabBackgroundColour (const int tabIndex) const throw(); - - /** Changes the background colour of one of the tabs. */ - void setTabBackgroundColour (const int tabIndex, const Colour& newColour); - - /** Changes the currently-selected tab. - - To deselect all the tabs, pass -1 as the index. - - @see TabbedButtonBar::setCurrentTabIndex - */ - void setCurrentTabIndex (const int newTabIndex, const bool sendChangeMessage = true); - - /** Returns the index of the currently selected tab. - - @see addTab, TabbedButtonBar::getCurrentTabIndex() - */ - int getCurrentTabIndex() const; - - /** Returns the name of the currently selected tab. - - @see addTab, TabbedButtonBar::getCurrentTabName() - */ - const String& getCurrentTabName() const; - - /** Returns the current component that's filling the panel. - - This will return 0 if there isn't one. - */ - Component* getCurrentContentComponent() const throw() { return panelComponent; } - - /** Callback method to indicate the selected tab has been changed. - - @see setCurrentTabIndex - */ - virtual void currentTabChanged (const int newCurrentTabIndex, - const String& newCurrentTabName); - - /** Callback method to indicate that the user has right-clicked on a tab. - - (Or ctrl-clicked on the Mac) - */ - virtual void popupMenuClickOnTab (const int tabIndex, - const String& tabName); - - /** Returns the tab button bar component that is being used. - */ - TabbedButtonBar& getTabbedButtonBar() const throw() { return *tabs; } - - /** A set of colour IDs to use to change the colour of various aspects of the component. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - backgroundColourId = 0x1005800, /**< The colour to fill the background behind the tabs. */ - outlineColourId = 0x1005801, /**< The colour to use to draw an outline around the content. - (See setOutline) */ - }; - - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void resized(); - /** @internal */ - void lookAndFeelChanged(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator protected: - TabbedButtonBar* tabs; + TabbedButtonBar* tabs; - /** This creates one of the tab buttons. - - If you need to use custom tab components, you can override this method and - return your own class instead of the default. - */ - virtual TabBarButton* createTabButton (const String& tabName, - const int tabIndex); + virtual TabBarButton* createTabButton (const String& tabName, + const int tabIndex); private: - Array contentComponents; - Component* panelComponent; - int tabDepth; - int outlineThickness, edgeIndent; + Array contentComponents; + Component* panelComponent; + int tabDepth; + int outlineThickness, edgeIndent; - friend class TabCompButtonBar; - void changeCallback (const int newCurrentTabIndex, const String& newTabName); + friend class TabCompButtonBar; + void changeCallback (const int newCurrentTabIndex, const String& newTabName); - TabbedComponent (const TabbedComponent&); - const TabbedComponent& operator= (const TabbedComponent&); + TabbedComponent (const TabbedComponent&); + const TabbedComponent& operator= (const TabbedComponent&); }; #endif // __JUCE_TABBEDCOMPONENT_JUCEHEADER__ @@ -49191,466 +23373,211 @@ private: class MenuBarModel; -/** - A class to receive callbacks when a MenuBarModel changes. - - @see MenuBarModel::addListener, MenuBarModel::removeListener, MenuBarModel::menuItemsChanged -*/ class JUCE_API MenuBarModelListener { public: - /** Destructor. */ - virtual ~MenuBarModelListener() {} + virtual ~MenuBarModelListener() {} - /** This callback is made when items are changed in the menu bar model. - */ - virtual void menuBarItemsChanged (MenuBarModel* menuBarModel) = 0; + virtual void menuBarItemsChanged (MenuBarModel* menuBarModel) = 0; - /** This callback is made when an application command is invoked that - is represented by one of the items in the menu bar model. - */ - virtual void menuCommandInvoked (MenuBarModel* menuBarModel, - const ApplicationCommandTarget::InvocationInfo& info) = 0; + virtual void menuCommandInvoked (MenuBarModel* menuBarModel, + const ApplicationCommandTarget::InvocationInfo& info) = 0; }; -/** - A class for controlling MenuBar components. - - This class is used to tell a MenuBar what menus to show, and to respond - to a menu being selected. - - @see MenuBarModelListener, MenuBarComponent, PopupMenu -*/ -class JUCE_API MenuBarModel : private AsyncUpdater, - private ApplicationCommandManagerListener +class JUCE_API MenuBarModel : private AsyncUpdater, + private ApplicationCommandManagerListener { public: - MenuBarModel() throw(); + MenuBarModel() throw(); - /** Destructor. */ - virtual ~MenuBarModel(); + virtual ~MenuBarModel(); - /** Call this when some of your menu items have changed. + void menuItemsChanged(); - This method will cause a callback to any MenuBarListener objects that - are registered with this model. + void setApplicationCommandManagerToWatch (ApplicationCommandManager* const manager) throw(); - If this model is displaying items from an ApplicationCommandManager, you - can use the setApplicationCommandManagerToWatch() method to cause - change messages to be sent automatically when the ApplicationCommandManager - is changed. + void addListener (MenuBarModelListener* const listenerToAdd) throw(); - @see addListener, removeListener, MenuBarListener - */ - void menuItemsChanged(); + void removeListener (MenuBarModelListener* const listenerToRemove) throw(); - /** Tells the menu bar to listen to the specified command manager, and to update - itself when the commands change. + virtual const StringArray getMenuBarNames() = 0; - This will also allow it to flash a menu name when a command from that menu - is invoked using a keystroke. - */ - void setApplicationCommandManagerToWatch (ApplicationCommandManager* const manager) throw(); + virtual const PopupMenu getMenuForIndex (int topLevelMenuIndex, + const String& menuName) = 0; - /** Registers a listener for callbacks when the menu items in this model change. - - The listener object will get callbacks when this object's menuItemsChanged() - method is called. - - @see removeListener - */ - void addListener (MenuBarModelListener* const listenerToAdd) throw(); - - /** Removes a listener. - - @see addListener - */ - void removeListener (MenuBarModelListener* const listenerToRemove) throw(); - - /** This method must return a list of the names of the menus. */ - virtual const StringArray getMenuBarNames() = 0; - - /** This should return the popup menu to display for a given top-level menu. - - @param topLevelMenuIndex the index of the top-level menu to show - @param menuName the name of the top-level menu item to show - */ - virtual const PopupMenu getMenuForIndex (int topLevelMenuIndex, - const String& menuName) = 0; - - /** This is called when a menu item has been clicked on. - - @param menuItemID the item ID of the PopupMenu item that was selected - @param topLevelMenuIndex the index of the top-level menu from which the item was - chosen (just in case you've used duplicate ID numbers - on more than one of the popup menus) - */ - virtual void menuItemSelected (int menuItemID, - int topLevelMenuIndex) = 0; + virtual void menuItemSelected (int menuItemID, + int topLevelMenuIndex) = 0; #if JUCE_MAC || DOXYGEN - /** MAC ONLY - Sets the model that is currently being shown as the main - menu bar at the top of the screen on the Mac. + static void setMacMainMenu (MenuBarModel* newMenuBarModel, + const PopupMenu* extraAppleMenuItems = 0); - You can pass 0 to stop the current model being displayed. Be careful - not to delete a model while it is being used. - - An optional extra menu can be specified, containing items to add to the top of - the apple menu. (Confusingly, the 'apple' menu isn't the one with a picture of - an apple, it's the one next to it, with your application's name at the top - and the services menu etc on it). When one of these items is selected, the - menu bar model will be used to invoke it, and in the menuItemSelected() callback - the topLevelMenuIndex parameter will be -1. If you pass in an extraAppleMenuItems - object then newMenuBarModel must be non-null. - */ - static void setMacMainMenu (MenuBarModel* newMenuBarModel, - const PopupMenu* extraAppleMenuItems = 0); - - /** MAC ONLY - Returns the menu model that is currently being shown as - the main menu bar. - */ - static MenuBarModel* getMacMainMenu(); + static MenuBarModel* getMacMainMenu(); #endif - /** @internal */ - void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info); - /** @internal */ - void applicationCommandListChanged(); - /** @internal */ - void handleAsyncUpdate(); + void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info); + void applicationCommandListChanged(); + void handleAsyncUpdate(); - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - ApplicationCommandManager* manager; - SortedSet listeners; + ApplicationCommandManager* manager; + SortedSet listeners; - MenuBarModel (const MenuBarModel&); - const MenuBarModel& operator= (const MenuBarModel&); + MenuBarModel (const MenuBarModel&); + const MenuBarModel& operator= (const MenuBarModel&); }; #endif // __JUCE_MENUBARMODEL_JUCEHEADER__ /********* End of inlined file: juce_MenuBarModel.h *********/ -/** - A menu bar component. - - @see MenuBarModel -*/ class JUCE_API MenuBarComponent : public Component, - private MenuBarModelListener, - private Timer + private MenuBarModelListener, + private Timer { public: - /** Creates a menu bar. + MenuBarComponent (MenuBarModel* const model); - @param model the model object to use to control this bar. You can - pass 0 into this if you like, and set the model later - using the setModel() method - */ - MenuBarComponent (MenuBarModel* const model); + ~MenuBarComponent(); - /** Destructor. */ - ~MenuBarComponent(); + void setModel (MenuBarModel* const newModel); - /** Changes the model object to use to control the bar. + void showMenu (const int menuIndex); - This can be 0, in which case the bar will be empty. Don't delete the object - that is passed-in while it's still being used by this MenuBar. - */ - void setModel (MenuBarModel* const newModel); + void paint (Graphics& g); + void resized(); + void mouseEnter (const MouseEvent& e); + void mouseExit (const MouseEvent& e); + void mouseDown (const MouseEvent& e); + void mouseDrag (const MouseEvent& e); + void mouseUp (const MouseEvent& e); + void mouseMove (const MouseEvent& e); + void inputAttemptWhenModal(); + void handleCommandMessage (int commandId); + bool keyPressed (const KeyPress& key); + void menuBarItemsChanged (MenuBarModel* menuBarModel); + void menuCommandInvoked (MenuBarModel* menuBarModel, + const ApplicationCommandTarget::InvocationInfo& info); - /** Pops up one of the menu items. - - This lets you manually open one of the menus - it could be triggered by a - key shortcut, for example. - */ - void showMenu (const int menuIndex); - - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void resized(); - /** @internal */ - void mouseEnter (const MouseEvent& e); - /** @internal */ - void mouseExit (const MouseEvent& e); - /** @internal */ - void mouseDown (const MouseEvent& e); - /** @internal */ - void mouseDrag (const MouseEvent& e); - /** @internal */ - void mouseUp (const MouseEvent& e); - /** @internal */ - void mouseMove (const MouseEvent& e); - /** @internal */ - void inputAttemptWhenModal(); - /** @internal */ - void handleCommandMessage (int commandId); - /** @internal */ - bool keyPressed (const KeyPress& key); - /** @internal */ - void menuBarItemsChanged (MenuBarModel* menuBarModel); - /** @internal */ - void menuCommandInvoked (MenuBarModel* menuBarModel, - const ApplicationCommandTarget::InvocationInfo& info); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - MenuBarModel* model; + MenuBarModel* model; - StringArray menuNames; - Array xPositions; - int itemUnderMouse, currentPopupIndex, topLevelIndexClicked, indexToShowAgain; - int lastMouseX, lastMouseY; - bool inModalState; - ScopedPointer currentPopup; + StringArray menuNames; + Array xPositions; + int itemUnderMouse, currentPopupIndex, topLevelIndexClicked, indexToShowAgain; + int lastMouseX, lastMouseY; + bool inModalState; + ScopedPointer currentPopup; - int getItemAt (int x, int y); - void updateItemUnderMouse (const int x, const int y); - void hideCurrentMenu(); - void timerCallback(); - void repaintMenuItem (int index); + int getItemAt (int x, int y); + void updateItemUnderMouse (const int x, const int y); + void hideCurrentMenu(); + void timerCallback(); + void repaintMenuItem (int index); - MenuBarComponent (const MenuBarComponent&); - const MenuBarComponent& operator= (const MenuBarComponent&); + MenuBarComponent (const MenuBarComponent&); + const MenuBarComponent& operator= (const MenuBarComponent&); }; #endif // __JUCE_MENUBARCOMPONENT_JUCEHEADER__ /********* End of inlined file: juce_MenuBarComponent.h *********/ -/** - A resizable window with a title bar and maximise, minimise and close buttons. - - This subclass of ResizableWindow creates a fairly standard type of window with - a title bar and various buttons. The name of the component is shown in the - title bar, and an icon can optionally be specified with setIcon(). - - All the methods available to a ResizableWindow are also available to this, - so it can easily be made resizable, minimised, maximised, etc. - - It's not advisable to add child components directly to a DocumentWindow: put them - inside your content component instead. And overriding methods like resized(), moved(), etc - is also not recommended - instead override these methods for your content component. - (If for some obscure reason you do need to override these methods, always remember to - call the super-class's resized() method too, otherwise it'll fail to lay out the window - decorations correctly). - - You can also automatically add a menu bar to the window, using the setMenuBar() - method. - - @see ResizableWindow, DialogWindow -*/ class JUCE_API DocumentWindow : public ResizableWindow { public: - /** The set of available button-types that can be put on the title bar. + enum TitleBarButtons + { + minimiseButton = 1, + maximiseButton = 2, + closeButton = 4, - @see setTitleBarButtonsRequired - */ - enum TitleBarButtons - { - minimiseButton = 1, - maximiseButton = 2, - closeButton = 4, + allButtons = 7 + }; - /** A combination of all the buttons above. */ - allButtons = 7 - }; + DocumentWindow (const String& name, + const Colour& backgroundColour, + const int requiredButtons, + const bool addToDesktop = true); - /** Creates a DocumentWindow. + ~DocumentWindow(); - @param name the name to give the component - this is also - the title shown at the top of the window. To change - this later, use setName() - @param backgroundColour the colour to use for filling the window's background. - @param requiredButtons specifies which of the buttons (close, minimise, maximise) - should be shown on the title bar. This value is a bitwise - combination of values from the TitleBarButtons enum. Note - that it can be "allButtons" to get them all. You - can change this later with the setTitleBarButtonsRequired() - method, which can also specify where they are positioned. - @param addToDesktop if true, the window will be automatically added to the - desktop; if false, you can use it as a child component - @see TitleBarButtons - */ - DocumentWindow (const String& name, - const Colour& backgroundColour, - const int requiredButtons, - const bool addToDesktop = true); + void setName (const String& newName); - /** Destructor. + void setIcon (const Image* imageToUse); - If a content component has been set with setContentComponent(), it - will be deleted. - */ - ~DocumentWindow(); + void setTitleBarHeight (const int newHeight); - /** Changes the component's name. + int getTitleBarHeight() const; - (This is overridden from Component::setName() to cause a repaint, as - the name is what gets drawn across the window's title bar). - */ - void setName (const String& newName); + void setTitleBarButtonsRequired (const int requiredButtons, + const bool positionTitleBarButtonsOnLeft); - /** Sets an icon to show in the title bar, next to the title. + void setTitleBarTextCentred (const bool textShouldBeCentred); - A copy is made internally of the image, so the caller can delete the - image after calling this. If 0 is passed-in, any existing icon will be - removed. - */ - void setIcon (const Image* imageToUse); + void setMenuBar (MenuBarModel* menuBarModel, + const int menuBarHeight = 0); - /** Changes the height of the title-bar. */ - void setTitleBarHeight (const int newHeight); + virtual void closeButtonPressed(); - /** Returns the current title bar height. */ - int getTitleBarHeight() const; + virtual void minimiseButtonPressed(); - /** Changes the set of title-bar buttons being shown. + virtual void maximiseButtonPressed(); - @param requiredButtons specifies which of the buttons (close, minimise, maximise) - should be shown on the title bar. This value is a bitwise - combination of values from the TitleBarButtons enum. Note - that it can be "allButtons" to get them all. - @param positionTitleBarButtonsOnLeft if true, the buttons should go at the - left side of the bar; if false, they'll be placed at the right - */ - void setTitleBarButtonsRequired (const int requiredButtons, - const bool positionTitleBarButtonsOnLeft); + Button* getCloseButton() const throw(); - /** Sets whether the title should be centred within the window. + Button* getMinimiseButton() const throw(); - If true, the title text is shown in the middle of the title-bar; if false, - it'll be shown at the left of the bar. - */ - void setTitleBarTextCentred (const bool textShouldBeCentred); + Button* getMaximiseButton() const throw(); - /** Creates a menu inside this window. + enum ColourIds + { + textColourId = 0x1005701, /**< The colour to draw any text with. It's up to the look + and feel class how this is used. */ + }; - @param menuBarModel this specifies a MenuBarModel that should be used to - generate the contents of a menu bar that will be placed - just below the title bar, and just above any content - component. If this value is zero, any existing menu bar - will be removed from the component; if non-zero, one will - be added if it's required. - @param menuBarHeight the height of the menu bar component, if one is needed. Pass a value of zero - or less to use the look-and-feel's default size. - */ - void setMenuBar (MenuBarModel* menuBarModel, - const int menuBarHeight = 0); + void paint (Graphics& g); + void resized(); + void lookAndFeelChanged(); + const BorderSize getBorderThickness(); + const BorderSize getContentComponentBorder(); + void mouseDoubleClick (const MouseEvent& e); + void userTriedToCloseWindow(); + void activeWindowStatusChanged(); + int getDesktopWindowStyleFlags() const; + void parentHierarchyChanged(); + const Rectangle getTitleBarArea(); - /** This method is called when the user tries to close the window. - - This is triggered by the user clicking the close button, or using some other - OS-specific key shortcut or OS menu for getting rid of a window. - - If the window is just a pop-up, you should override this closeButtonPressed() - method and make it delete the window in whatever way is appropriate for your - app. E.g. you might just want to call "delete this". - - If your app is centred around this window such that the whole app should quit when - the window is closed, then you will probably want to use this method as an opportunity - to call JUCEApplication::quit(), and leave the window to be deleted later by your - JUCEApplication::shutdown() method. (Doing it this way means that your window will - still get cleaned-up if the app is quit by some other means (e.g. a cmd-Q on the mac - or closing it via the taskbar icon on Windows). - - (Note that the DocumentWindow class overrides Component::userTriedToCloseWindow() and - redirects it to call this method, so any methods of closing the window that are - caught by userTriedToCloseWindow() will also end up here). - */ - virtual void closeButtonPressed(); - - /** Callback that is triggered when the minimise button is pressed. - - The default implementation of this calls ResizableWindow::setMinimised(), but - you can override it to do more customised behaviour. - */ - virtual void minimiseButtonPressed(); - - /** Callback that is triggered when the maximise button is pressed, or when the - title-bar is double-clicked. - - The default implementation of this calls ResizableWindow::setFullScreen(), but - you can override it to do more customised behaviour. - */ - virtual void maximiseButtonPressed(); - - /** Returns the close button, (or 0 if there isn't one). */ - Button* getCloseButton() const throw(); - - /** Returns the minimise button, (or 0 if there isn't one). */ - Button* getMinimiseButton() const throw(); - - /** Returns the maximise button, (or 0 if there isn't one). */ - Button* getMaximiseButton() const throw(); - - /** A set of colour IDs to use to change the colour of various aspects of the window. - - These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() - methods. - - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour - */ - enum ColourIds - { - textColourId = 0x1005701, /**< The colour to draw any text with. It's up to the look - and feel class how this is used. */ - }; - - /** @internal */ - void paint (Graphics& g); - /** @internal */ - void resized(); - /** @internal */ - void lookAndFeelChanged(); - /** @internal */ - const BorderSize getBorderThickness(); - /** @internal */ - const BorderSize getContentComponentBorder(); - /** @internal */ - void mouseDoubleClick (const MouseEvent& e); - /** @internal */ - void userTriedToCloseWindow(); - /** @internal */ - void activeWindowStatusChanged(); - /** @internal */ - int getDesktopWindowStyleFlags() const; - /** @internal */ - void parentHierarchyChanged(); - /** @internal */ - const Rectangle getTitleBarArea(); - - juce_UseDebuggingNewOperator + juce_UseDebuggingNewOperator private: - int titleBarHeight, menuBarHeight, requiredButtons; - bool positionTitleBarButtonsOnLeft, drawTitleTextCentred; - ScopedPointer